summaryrefslogtreecommitdiff
path: root/sound/soc/codecs/tas5086.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/tas5086.c')
-rw-r--r--sound/soc/codecs/tas5086.c153
1 files changed, 67 insertions, 86 deletions
diff --git a/sound/soc/codecs/tas5086.c b/sound/soc/codecs/tas5086.c
index b7de857abb16..12bf6a89dbd8 100644
--- a/sound/soc/codecs/tas5086.c
+++ b/sound/soc/codecs/tas5086.c
@@ -1,18 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* TAS5086 ASoC codec driver
*
* Copyright (c) 2013 Daniel Mack <zonque@gmail.com>
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
* TODO:
* - implement DAPM and input muxing
* - implement modulation limit
@@ -33,14 +24,13 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/delay.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/spi/spi.h>
#include <linux/of.h>
#include <linux/of_device.h>
-#include <linux/of_gpio.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
@@ -255,15 +245,15 @@ struct tas5086_private {
/* Current sample rate for de-emphasis control */
int rate;
/* GPIO driving Reset pin, if any */
- int gpio_nreset;
+ struct gpio_desc *reset;
struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)];
};
static int tas5086_deemph[] = { 0, 32000, 44100, 48000 };
-static int tas5086_set_deemph(struct snd_soc_codec *codec)
+static int tas5086_set_deemph(struct snd_soc_component *component)
{
- struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
+ struct tas5086_private *priv = snd_soc_component_get_drvdata(component);
int i, val = 0;
if (priv->deemph) {
@@ -282,8 +272,8 @@ static int tas5086_set_deemph(struct snd_soc_codec *codec)
static int tas5086_get_deemph(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
- struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
+ struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+ struct tas5086_private *priv = snd_soc_component_get_drvdata(component);
ucontrol->value.integer.value[0] = priv->deemph;
@@ -293,20 +283,20 @@ static int tas5086_get_deemph(struct snd_kcontrol *kcontrol,
static int tas5086_put_deemph(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
- struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
+ struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+ struct tas5086_private *priv = snd_soc_component_get_drvdata(component);
priv->deemph = ucontrol->value.integer.value[0];
- return tas5086_set_deemph(codec);
+ return tas5086_set_deemph(component);
}
static int tas5086_set_dai_sysclk(struct snd_soc_dai *codec_dai,
int clk_id, unsigned int freq, int dir)
{
- struct snd_soc_codec *codec = codec_dai->codec;
- struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
+ struct snd_soc_component *component = codec_dai->component;
+ struct tas5086_private *priv = snd_soc_component_get_drvdata(component);
switch (clk_id) {
case TAS5086_CLK_IDX_MCLK:
@@ -323,12 +313,12 @@ static int tas5086_set_dai_sysclk(struct snd_soc_dai *codec_dai,
static int tas5086_set_dai_fmt(struct snd_soc_dai *codec_dai,
unsigned int format)
{
- struct snd_soc_codec *codec = codec_dai->codec;
- struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
+ struct snd_soc_component *component = codec_dai->component;
+ struct tas5086_private *priv = snd_soc_component_get_drvdata(component);
/* The TAS5086 can only be slave to all clocks */
- if ((format & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) {
- dev_err(codec->dev, "Invalid clocking mode\n");
+ if ((format & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) != SND_SOC_DAIFMT_CBC_CFC) {
+ dev_err(component->dev, "Invalid clocking mode\n");
return -EINVAL;
}
@@ -361,8 +351,8 @@ static int tas5086_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct snd_soc_codec *codec = dai->codec;
- struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
+ struct snd_soc_component *component = dai->component;
+ struct tas5086_private *priv = snd_soc_component_get_drvdata(component);
int val;
int ret;
@@ -373,7 +363,7 @@ static int tas5086_hw_params(struct snd_pcm_substream *substream,
ARRAY_SIZE(tas5086_sample_rates), priv->rate);
if (val < 0) {
- dev_err(codec->dev, "Invalid sample rate\n");
+ dev_err(component->dev, "Invalid sample rate\n");
return -EINVAL;
}
@@ -387,7 +377,7 @@ static int tas5086_hw_params(struct snd_pcm_substream *substream,
val = index_in_array(tas5086_ratios, ARRAY_SIZE(tas5086_ratios),
priv->mclk / priv->rate);
if (val < 0) {
- dev_err(codec->dev, "Invalid MCLK / Fs ratio\n");
+ dev_err(component->dev, "Invalid MCLK / Fs ratio\n");
return -EINVAL;
}
@@ -424,7 +414,7 @@ static int tas5086_hw_params(struct snd_pcm_substream *substream,
val = 0x06;
break;
default:
- dev_err(codec->dev, "Invalid DAI format\n");
+ dev_err(component->dev, "Invalid DAI format\n");
return -EINVAL;
}
@@ -440,7 +430,7 @@ static int tas5086_hw_params(struct snd_pcm_substream *substream,
val += 2;
break;
default:
- dev_err(codec->dev, "Invalid bit width\n");
+ dev_err(component->dev, "Invalid bit width\n");
return -EINVAL;
}
@@ -454,13 +444,13 @@ static int tas5086_hw_params(struct snd_pcm_substream *substream,
if (ret < 0)
return ret;
- return tas5086_set_deemph(codec);
+ return tas5086_set_deemph(component);
}
static int tas5086_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
{
- struct snd_soc_codec *codec = dai->codec;
- struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
+ struct snd_soc_component *component = dai->component;
+ struct tas5086_private *priv = snd_soc_component_get_drvdata(component);
unsigned int val = 0;
if (mute)
@@ -471,11 +461,11 @@ static int tas5086_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
static void tas5086_reset(struct tas5086_private *priv)
{
- if (gpio_is_valid(priv->gpio_nreset)) {
+ if (priv->reset) {
/* Reset codec - minimum assertion time is 400ns */
- gpio_direction_output(priv->gpio_nreset, 0);
+ gpiod_set_value_cansleep(priv->reset, 1);
udelay(1);
- gpio_set_value(priv->gpio_nreset, 1);
+ gpiod_set_value_cansleep(priv->reset, 0);
/* Codec needs ~15ms to wake up */
msleep(15);
@@ -496,7 +486,7 @@ static int tas5086_init(struct device *dev, struct tas5086_private *priv)
/*
* If any of the channels is configured to start in Mid-Z mode,
* configure 'part 1' of the PWM starts to use Mid-Z, and tell
- * all configured mid-z channels to start start under 'part 1'.
+ * all configured mid-z channels to start under 'part 1'.
*/
if (priv->pwm_start_mid_z)
regmap_write(priv->regmap, TAS5086_PWM_START,
@@ -773,9 +763,9 @@ static struct snd_soc_dai_driver tas5086_dai = {
};
#ifdef CONFIG_PM
-static int tas5086_soc_suspend(struct snd_soc_codec *codec)
+static int tas5086_soc_suspend(struct snd_soc_component *component)
{
- struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
+ struct tas5086_private *priv = snd_soc_component_get_drvdata(component);
int ret;
/* Shut down all channels */
@@ -788,9 +778,9 @@ static int tas5086_soc_suspend(struct snd_soc_codec *codec)
return 0;
}
-static int tas5086_soc_resume(struct snd_soc_codec *codec)
+static int tas5086_soc_resume(struct snd_soc_component *component)
{
- struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
+ struct tas5086_private *priv = snd_soc_component_get_drvdata(component);
int ret;
ret = regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies);
@@ -800,7 +790,7 @@ static int tas5086_soc_resume(struct snd_soc_codec *codec)
tas5086_reset(priv);
regcache_mark_dirty(priv->regmap);
- ret = tas5086_init(codec->dev, priv);
+ ret = tas5086_init(component->dev, priv);
if (ret < 0)
return ret;
@@ -823,22 +813,22 @@ static const struct of_device_id tas5086_dt_ids[] = {
MODULE_DEVICE_TABLE(of, tas5086_dt_ids);
#endif
-static int tas5086_probe(struct snd_soc_codec *codec)
+static int tas5086_probe(struct snd_soc_component *component)
{
- struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
+ struct tas5086_private *priv = snd_soc_component_get_drvdata(component);
int i, ret;
ret = regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies);
if (ret < 0) {
- dev_err(codec->dev, "Failed to enable regulators: %d\n", ret);
+ dev_err(component->dev, "Failed to enable regulators: %d\n", ret);
return ret;
}
priv->pwm_start_mid_z = 0;
priv->charge_period = 1300000; /* hardware default is 1300 ms */
- if (of_match_device(of_match_ptr(tas5086_dt_ids), codec->dev)) {
- struct device_node *of_node = codec->dev->of_node;
+ if (of_match_device(of_match_ptr(tas5086_dt_ids), component->dev)) {
+ struct device_node *of_node = component->dev->of_node;
of_property_read_u32(of_node, "ti,charge-period",
&priv->charge_period);
@@ -849,13 +839,13 @@ static int tas5086_probe(struct snd_soc_codec *codec)
snprintf(name, sizeof(name),
"ti,mid-z-channel-%d", i + 1);
- if (of_get_property(of_node, name, NULL) != NULL)
+ if (of_property_read_bool(of_node, name))
priv->pwm_start_mid_z |= 1 << i;
}
}
tas5086_reset(priv);
- ret = tas5086_init(codec->dev, priv);
+ ret = tas5086_init(component->dev, priv);
if (ret < 0)
goto exit_disable_regulators;
@@ -872,36 +862,36 @@ exit_disable_regulators:
return ret;
}
-static int tas5086_remove(struct snd_soc_codec *codec)
+static void tas5086_remove(struct snd_soc_component *component)
{
- struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
+ struct tas5086_private *priv = snd_soc_component_get_drvdata(component);
- if (gpio_is_valid(priv->gpio_nreset))
+ if (priv->reset) {
/* Set codec to the reset state */
- gpio_set_value(priv->gpio_nreset, 0);
+ gpiod_set_value_cansleep(priv->reset, 1);
+ }
regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies);
-
- return 0;
};
-static struct snd_soc_codec_driver soc_codec_dev_tas5086 = {
+static const struct snd_soc_component_driver soc_component_dev_tas5086 = {
.probe = tas5086_probe,
.remove = tas5086_remove,
.suspend = tas5086_soc_suspend,
.resume = tas5086_soc_resume,
- .component_driver = {
- .controls = tas5086_controls,
- .num_controls = ARRAY_SIZE(tas5086_controls),
- .dapm_widgets = tas5086_dapm_widgets,
- .num_dapm_widgets = ARRAY_SIZE(tas5086_dapm_widgets),
- .dapm_routes = tas5086_dapm_routes,
- .num_dapm_routes = ARRAY_SIZE(tas5086_dapm_routes),
- },
+ .controls = tas5086_controls,
+ .num_controls = ARRAY_SIZE(tas5086_controls),
+ .dapm_widgets = tas5086_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(tas5086_dapm_widgets),
+ .dapm_routes = tas5086_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(tas5086_dapm_routes),
+ .idle_bias_on = 1,
+ .use_pmdown_time = 1,
+ .endianness = 1,
};
static const struct i2c_device_id tas5086_i2c_id[] = {
- { "tas5086", 0 },
+ { "tas5086" },
{ }
};
MODULE_DEVICE_TABLE(i2c, tas5086_i2c_id);
@@ -920,12 +910,10 @@ static const struct regmap_config tas5086_regmap = {
.reg_write = tas5086_reg_write,
};
-static int tas5086_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int tas5086_i2c_probe(struct i2c_client *i2c)
{
struct tas5086_private *priv;
struct device *dev = &i2c->dev;
- int gpio_nreset = -EINVAL;
int i, ret;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
@@ -951,16 +939,11 @@ static int tas5086_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata(i2c, priv);
- if (of_match_device(of_match_ptr(tas5086_dt_ids), dev)) {
- struct device_node *of_node = dev->of_node;
- gpio_nreset = of_get_named_gpio(of_node, "reset-gpio", 0);
- }
-
- if (gpio_is_valid(gpio_nreset))
- if (devm_gpio_request(dev, gpio_nreset, "TAS5086 Reset"))
- gpio_nreset = -EINVAL;
-
- priv->gpio_nreset = gpio_nreset;
+ /* Request line asserted */
+ priv->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(priv->reset))
+ return PTR_ERR(priv->reset);
+ gpiod_set_consumer_name(priv->reset, "TAS5086 Reset");
ret = regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies);
if (ret < 0) {
@@ -985,17 +968,15 @@ static int tas5086_i2c_probe(struct i2c_client *i2c,
regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies);
if (ret == 0)
- ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_tas5086,
+ ret = devm_snd_soc_register_component(&i2c->dev,
+ &soc_component_dev_tas5086,
&tas5086_dai, 1);
return ret;
}
-static int tas5086_i2c_remove(struct i2c_client *i2c)
-{
- snd_soc_unregister_codec(&i2c->dev);
- return 0;
-}
+static void tas5086_i2c_remove(struct i2c_client *i2c)
+{}
static struct i2c_driver tas5086_i2c_driver = {
.driver = {