[alsa-devel] [PATCH 0/4] ASoC: tpa6130a2: Add support for multiple instances
The current tpa6130a2 driver supports only a single instance. This patch series add support for multiple instances by removing the global variable that holds the instance. This is performed by using the component API, regmap, the snd_soc_{info,put,get}_volsw API and DAPM.
This patch series also touches code from the Nokia RX51 which I didn't tested (as I am testing the tpa6130a2 in another board that is not upstream). I would appreciate is if someone who possesses the Nokia RX51 (n900) could please test the code.
This patch series is based on git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next Available at https://git.collabora.com/cgit/user/koike/linux.git/log/?h=sound/review/tpa6...
Helen Koike (4): ASoC: tpa6130a2: Register component ASoC: tap6130a2: Use regmap ASoC: tpa6130a2: Use snd soc volsw functions ASoC: tpa6130a2: Add DAPM support
sound/soc/codecs/tpa6130a2.c | 382 ++++++++++++------------------------------- sound/soc/codecs/tpa6130a2.h | 14 +- sound/soc/omap/rx51.c | 45 ++--- 3 files changed, 130 insertions(+), 311 deletions(-)
Add tpa6130a2 controls by the component API and update rx51 accordingly
Signed-off-by: Lars-Peter Clausen lars@metafoo.de [koike: port for upstream] Signed-off-by: Helen Koike helen.koike@collabora.co.uk --- sound/soc/codecs/tpa6130a2.c | 26 +++++++++++++------------- sound/soc/codecs/tpa6130a2.h | 1 - sound/soc/omap/rx51.c | 23 ++++++++++++----------- 3 files changed, 25 insertions(+), 25 deletions(-)
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index 11d85c5..f700d92 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c @@ -348,23 +348,22 @@ int tpa6130a2_stereo_enable(struct snd_soc_codec *codec, int enable) } EXPORT_SYMBOL_GPL(tpa6130a2_stereo_enable);
-int tpa6130a2_add_controls(struct snd_soc_codec *codec) +static int tpa6130a2_component_probe(struct snd_soc_component *component) { - struct tpa6130a2_data *data; - - if (tpa6130a2_client == NULL) - return -ENODEV; - - data = i2c_get_clientdata(tpa6130a2_client); + struct tpa6130a2_data *data = snd_soc_component_get_drvdata(component);
if (data->id == TPA6140A2) - return snd_soc_add_codec_controls(codec, tpa6140a2_controls, - ARRAY_SIZE(tpa6140a2_controls)); + return snd_soc_add_component_controls(component, + tpa6140a2_controls, ARRAY_SIZE(tpa6140a2_controls)); else - return snd_soc_add_codec_controls(codec, tpa6130a2_controls, - ARRAY_SIZE(tpa6130a2_controls)); + return snd_soc_add_component_controls(component, + tpa6130a2_controls, ARRAY_SIZE(tpa6130a2_controls)); } -EXPORT_SYMBOL_GPL(tpa6130a2_add_controls); + +struct snd_soc_component_driver tpa6130a2_component_driver = { + .name = "tpa6130a2", + .probe = tpa6130a2_component_probe, +};
static int tpa6130a2_probe(struct i2c_client *client, const struct i2c_device_id *id) @@ -451,7 +450,8 @@ static int tpa6130a2_probe(struct i2c_client *client, if (ret != 0) goto err_gpio;
- return 0; + return devm_snd_soc_register_component(&client->dev, + &tpa6130a2_component_driver, NULL, 0);
err_gpio: tpa6130a2_client = NULL; diff --git a/sound/soc/codecs/tpa6130a2.h b/sound/soc/codecs/tpa6130a2.h index 4174440..78ee723 100644 --- a/sound/soc/codecs/tpa6130a2.h +++ b/sound/soc/codecs/tpa6130a2.h @@ -56,7 +56,6 @@ /* TPA6130A2_REG_VERSION (0x04) */ #define TPA6130A2_VERSION_MASK (0x0f)
-extern int tpa6130a2_add_controls(struct snd_soc_codec *codec); extern int tpa6130a2_stereo_enable(struct snd_soc_codec *codec, int enable);
#endif /* __TPA6130A2_H__ */ diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c index 5494924..b59cf89 100644 --- a/sound/soc/omap/rx51.c +++ b/sound/soc/omap/rx51.c @@ -286,16 +286,10 @@ static const struct snd_kcontrol_new aic34_rx51_controls[] = {
static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd) { - struct snd_soc_codec *codec = rtd->codec; struct snd_soc_card *card = rtd->card; struct rx51_audio_pdata *pdata = snd_soc_card_get_drvdata(card); int err;
- err = tpa6130a2_add_controls(codec); - if (err < 0) { - dev_err(card->dev, "Failed to add TPA6130A2 controls\n"); - return err; - } snd_soc_limit_volume(card, "TPA6130A2 Headphone Playback Volume", 42);
err = omap_mcbsp_st_add_controls(rtd, 2); @@ -357,6 +351,10 @@ static struct snd_soc_aux_dev rx51_aux_dev[] = { .name = "TLV320AIC34b", .codec_name = "tlv320aic3x-codec.2-0019", }, + { + .name = "TPA61320A2", + .codec_name = "tpa6130a2.2-0060", + }, };
static struct snd_soc_codec_conf rx51_codec_conf[] = { @@ -364,6 +362,10 @@ static struct snd_soc_codec_conf rx51_codec_conf[] = { .dev_name = "tlv320aic3x-codec.2-0019", .name_prefix = "b", }, + { + .dev_name = "tpa6130a2.2-0060", + .name_prefix = "TPA6130A2", + }, };
/* Audio card */ @@ -435,11 +437,10 @@ static int rx51_soc_probe(struct platform_device *pdev) dev_err(&pdev->dev, "Headphone amplifier node is not provided\n"); return -EINVAL; } - - /* TODO: tpa6130a2a driver supports only a single instance, so - * this driver ignores the headphone-amplifier node for now. - * It's already mandatory in the DT binding to be future proof. - */ + rx51_aux_dev[1].codec_name = NULL; + rx51_aux_dev[1].codec_of_node = dai_node; + rx51_codec_conf[1].dev_name = NULL; + rx51_codec_conf[1].of_node = dai_node; }
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
Hi Helen,
On Sat, Jun 18, 2016 at 12:26:28AM -0300, Helen Koike wrote:
Add tpa6130a2 controls by the component API and update rx51 accordingly
Signed-off-by: Lars-Peter Clausen lars@metafoo.de [koike: port for upstream] Signed-off-by: Helen Koike helen.koike@collabora.co.uk
sound/soc/codecs/tpa6130a2.c | 26 +++++++++++++------------- sound/soc/codecs/tpa6130a2.h | 1 - sound/soc/omap/rx51.c | 23 ++++++++++++----------- 3 files changed, 25 insertions(+), 25 deletions(-)
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index 11d85c5..f700d92 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c @@ -348,23 +348,22 @@ int tpa6130a2_stereo_enable(struct snd_soc_codec *codec, int enable) } EXPORT_SYMBOL_GPL(tpa6130a2_stereo_enable);
-int tpa6130a2_add_controls(struct snd_soc_codec *codec) +static int tpa6130a2_component_probe(struct snd_soc_component *component) {
- struct tpa6130a2_data *data;
- if (tpa6130a2_client == NULL)
return -ENODEV;
- data = i2c_get_clientdata(tpa6130a2_client);
struct tpa6130a2_data *data = snd_soc_component_get_drvdata(component);
if (data->id == TPA6140A2)
return snd_soc_add_codec_controls(codec, tpa6140a2_controls,
ARRAY_SIZE(tpa6140a2_controls));
return snd_soc_add_component_controls(component,
elsetpa6140a2_controls, ARRAY_SIZE(tpa6140a2_controls));
return snd_soc_add_codec_controls(codec, tpa6130a2_controls,
ARRAY_SIZE(tpa6130a2_controls));
return snd_soc_add_component_controls(component,
tpa6130a2_controls, ARRAY_SIZE(tpa6130a2_controls));
} -EXPORT_SYMBOL_GPL(tpa6130a2_add_controls);
+struct snd_soc_component_driver tpa6130a2_component_driver = {
- .name = "tpa6130a2",
- .probe = tpa6130a2_component_probe,
+};
static int tpa6130a2_probe(struct i2c_client *client, const struct i2c_device_id *id) @@ -451,7 +450,8 @@ static int tpa6130a2_probe(struct i2c_client *client, if (ret != 0) goto err_gpio;
- return 0;
- return devm_snd_soc_register_component(&client->dev,
&tpa6130a2_component_driver, NULL, 0);
err_gpio: tpa6130a2_client = NULL; diff --git a/sound/soc/codecs/tpa6130a2.h b/sound/soc/codecs/tpa6130a2.h index 4174440..78ee723 100644 --- a/sound/soc/codecs/tpa6130a2.h +++ b/sound/soc/codecs/tpa6130a2.h @@ -56,7 +56,6 @@ /* TPA6130A2_REG_VERSION (0x04) */ #define TPA6130A2_VERSION_MASK (0x0f)
-extern int tpa6130a2_add_controls(struct snd_soc_codec *codec); extern int tpa6130a2_stereo_enable(struct snd_soc_codec *codec, int enable);
#endif /* __TPA6130A2_H__ */ diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c index 5494924..b59cf89 100644 --- a/sound/soc/omap/rx51.c +++ b/sound/soc/omap/rx51.c @@ -286,16 +286,10 @@ static const struct snd_kcontrol_new aic34_rx51_controls[] = {
static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd) {
struct snd_soc_codec *codec = rtd->codec; struct snd_soc_card *card = rtd->card; struct rx51_audio_pdata *pdata = snd_soc_card_get_drvdata(card); int err;
err = tpa6130a2_add_controls(codec);
if (err < 0) {
dev_err(card->dev, "Failed to add TPA6130A2 controls\n");
return err;
} snd_soc_limit_volume(card, "TPA6130A2 Headphone Playback Volume", 42);
err = omap_mcbsp_st_add_controls(rtd, 2);
@@ -357,6 +351,10 @@ static struct snd_soc_aux_dev rx51_aux_dev[] = { .name = "TLV320AIC34b", .codec_name = "tlv320aic3x-codec.2-0019", },
- {
.name = "TPA61320A2",
.codec_name = "tpa6130a2.2-0060",
- },
};
static struct snd_soc_codec_conf rx51_codec_conf[] = { @@ -364,6 +362,10 @@ static struct snd_soc_codec_conf rx51_codec_conf[] = { .dev_name = "tlv320aic3x-codec.2-0019", .name_prefix = "b", },
- {
.dev_name = "tpa6130a2.2-0060",
.name_prefix = "TPA6130A2",
This results in the control being named "TPA6130A2 TPA6130A2 Headphone Playback Volume", which is too long, so its shortened to "TPA6130A2 TPA6130A2 Headphone Playback Volu". That in turn results in incorrect detection making it playback + capture and the snd_soc_limit_volume() from above does not work.
I suggest to keep the name_prefix here and remove it in the codec instead, so that other boards (esp. those with more than one TPA) can choose another prefix.
- },
};
/* Audio card */ @@ -435,11 +437,10 @@ static int rx51_soc_probe(struct platform_device *pdev) dev_err(&pdev->dev, "Headphone amplifier node is not provided\n"); return -EINVAL; }
/* TODO: tpa6130a2a driver supports only a single instance, so
* this driver ignores the headphone-amplifier node for now.
* It's already mandatory in the DT binding to be future proof.
*/
rx51_aux_dev[1].codec_name = NULL;
rx51_aux_dev[1].codec_of_node = dai_node;
rx51_codec_conf[1].dev_name = NULL;
rx51_codec_conf[1].of_node = dai_node;
}
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
If you fix the double prefix the patch is
Tested-By: Sebastian Reichel sre@kernel.org Reviewed-By: Sebastian Reichel sre@kernel.org
-- Sebastian
Use regmap instead of open-coding IO access and caching
Signed-off-by: Lars-Peter Clausen lars@metafoo.de [koike: port for upstream] Signed-off-by: Helen Koike helen.koike@collabora.co.uk --- sound/soc/codecs/tpa6130a2.c | 166 ++++++++++++------------------------------- sound/soc/codecs/tpa6130a2.h | 2 - 2 files changed, 46 insertions(+), 122 deletions(-)
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index f700d92..0be70a4 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c @@ -32,6 +32,7 @@ #include <sound/tlv.h> #include <linux/of.h> #include <linux/of_gpio.h> +#include <linux/regmap.h>
#include "tpa6130a2.h"
@@ -45,92 +46,16 @@ static struct i2c_client *tpa6130a2_client; /* This struct is used to save the context */ struct tpa6130a2_data { struct mutex mutex; - unsigned char regs[TPA6130A2_CACHEREGNUM]; + struct regmap *regmap; struct regulator *supply; int power_gpio; u8 power_state:1; enum tpa_model id; };
-static int tpa6130a2_i2c_read(int reg) -{ - struct tpa6130a2_data *data; - int val; - - if (WARN_ON(!tpa6130a2_client)) - return -EINVAL; - data = i2c_get_clientdata(tpa6130a2_client); - - /* If powered off, return the cached value */ - if (data->power_state) { - val = i2c_smbus_read_byte_data(tpa6130a2_client, reg); - if (val < 0) - dev_err(&tpa6130a2_client->dev, "Read failed\n"); - else - data->regs[reg] = val; - } else { - val = data->regs[reg]; - } - - return val; -} - -static int tpa6130a2_i2c_write(int reg, u8 value) -{ - struct tpa6130a2_data *data; - int val = 0; - - if (WARN_ON(!tpa6130a2_client)) - return -EINVAL; - data = i2c_get_clientdata(tpa6130a2_client); - - if (data->power_state) { - val = i2c_smbus_write_byte_data(tpa6130a2_client, reg, value); - if (val < 0) { - dev_err(&tpa6130a2_client->dev, "Write failed\n"); - return val; - } - } - - /* Either powered on or off, we save the context */ - data->regs[reg] = value; - - return val; -} - -static u8 tpa6130a2_read(int reg) -{ - struct tpa6130a2_data *data; - - if (WARN_ON(!tpa6130a2_client)) - return 0; - data = i2c_get_clientdata(tpa6130a2_client); - - return data->regs[reg]; -} - -static int tpa6130a2_initialize(void) -{ - struct tpa6130a2_data *data; - int i, ret = 0; - - if (WARN_ON(!tpa6130a2_client)) - return -EINVAL; - data = i2c_get_clientdata(tpa6130a2_client); - - for (i = 1; i < TPA6130A2_REG_VERSION; i++) { - ret = tpa6130a2_i2c_write(i, data->regs[i]); - if (ret < 0) - break; - } - - return ret; -} - static int tpa6130a2_power(u8 power) { struct tpa6130a2_data *data; - u8 val; int ret = 0;
if (WARN_ON(!tpa6130a2_client)) @@ -153,7 +78,7 @@ static int tpa6130a2_power(u8 power) gpio_set_value(data->power_gpio, 1);
data->power_state = 1; - ret = tpa6130a2_initialize(); + ret = regcache_sync(data->regmap); if (ret < 0) { dev_err(&tpa6130a2_client->dev, "Failed to initialize chip\n"); @@ -165,9 +90,8 @@ static int tpa6130a2_power(u8 power) } } else { /* set SWS */ - val = tpa6130a2_read(TPA6130A2_REG_CONTROL); - val |= TPA6130A2_SWS; - tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val); + regmap_update_bits(data->regmap, TPA6130A2_REG_CONTROL, + TPA6130A2_SWS, TPA6130A2_SWS);
/* Power off */ if (data->power_gpio >= 0) @@ -181,6 +105,8 @@ static int tpa6130a2_power(u8 power) }
data->power_state = 0; + /* device regs does not match the cache state anymore */ + regcache_mark_dirty(data->regmap); }
exit: @@ -196,7 +122,7 @@ static int tpa6130a2_get_volsw(struct snd_kcontrol *kcontrol, struct tpa6130a2_data *data; unsigned int reg = mc->reg; unsigned int shift = mc->shift; - int max = mc->max; + int max = mc->max, val; unsigned int mask = (1 << fls(max)) - 1; unsigned int invert = mc->invert;
@@ -206,8 +132,8 @@ static int tpa6130a2_get_volsw(struct snd_kcontrol *kcontrol,
mutex_lock(&data->mutex);
- ucontrol->value.integer.value[0] = - (tpa6130a2_read(reg) >> shift) & mask; + regmap_read(data->regmap, reg, &val); + ucontrol->value.integer.value[0] = (val >> shift) & mask;
if (invert) ucontrol->value.integer.value[0] = @@ -229,7 +155,7 @@ static int tpa6130a2_put_volsw(struct snd_kcontrol *kcontrol, unsigned int mask = (1 << fls(max)) - 1; unsigned int invert = mc->invert; unsigned int val = (ucontrol->value.integer.value[0] & mask); - unsigned int val_reg; + bool change;
if (WARN_ON(!tpa6130a2_client)) return -EINVAL; @@ -239,20 +165,11 @@ static int tpa6130a2_put_volsw(struct snd_kcontrol *kcontrol, val = max - val;
mutex_lock(&data->mutex); - - val_reg = tpa6130a2_read(reg); - if (((val_reg >> shift) & mask) == val) { - mutex_unlock(&data->mutex); - return 0; - } - - val_reg &= ~(mask << shift); - val_reg |= val << shift; - tpa6130a2_i2c_write(reg, val_reg); - + regmap_update_bits_check(data->regmap, reg, mask << shift, val << shift, + &change); mutex_unlock(&data->mutex);
- return 1; + return change; }
/* @@ -301,31 +218,26 @@ static const struct snd_kcontrol_new tpa6140a2_controls[] = { */ static void tpa6130a2_channel_enable(u8 channel, int enable) { - u8 val; + struct tpa6130a2_data *data = i2c_get_clientdata(tpa6130a2_client);
if (enable) { /* Enable channel */ /* Enable amplifier */ - val = tpa6130a2_read(TPA6130A2_REG_CONTROL); - val |= channel; - val &= ~TPA6130A2_SWS; - tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val); + regmap_update_bits(data->regmap, TPA6130A2_REG_CONTROL, + channel | TPA6130A2_SWS, channel & ~TPA6130A2_SWS);
/* Unmute channel */ - val = tpa6130a2_read(TPA6130A2_REG_VOL_MUTE); - val &= ~channel; - tpa6130a2_i2c_write(TPA6130A2_REG_VOL_MUTE, val); + regmap_update_bits(data->regmap, TPA6130A2_REG_VOL_MUTE, + channel, 0); } else { /* Disable channel */ /* Mute channel */ - val = tpa6130a2_read(TPA6130A2_REG_VOL_MUTE); - val |= channel; - tpa6130a2_i2c_write(TPA6130A2_REG_VOL_MUTE, val); + regmap_update_bits(data->regmap, TPA6130A2_REG_VOL_MUTE, + channel, channel);
/* Disable amplifier */ - val = tpa6130a2_read(TPA6130A2_REG_CONTROL); - val &= ~channel; - tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val); + regmap_update_bits(data->regmap, TPA6130A2_REG_CONTROL, + channel, 0); } }
@@ -365,6 +277,20 @@ struct snd_soc_component_driver tpa6130a2_component_driver = { .probe = tpa6130a2_component_probe, };
+static const struct reg_default tpa6130a2_reg_defaults[] = { + { TPA6130A2_REG_CONTROL, TPA6130A2_SWS }, + { TPA6130A2_REG_VOL_MUTE, TPA6130A2_MUTE_R | TPA6130A2_MUTE_L }, +}; + +static const struct regmap_config tpa6130a2_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = TPA6130A2_REG_VERSION, + .reg_defaults = tpa6130a2_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(tpa6130a2_reg_defaults), + .cache_type = REGCACHE_RBTREE, +}; + static int tpa6130a2_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -373,6 +299,7 @@ static int tpa6130a2_probe(struct i2c_client *client, struct tpa6130a2_platform_data *pdata = client->dev.platform_data; struct device_node *np = client->dev.of_node; const char *regulator; + unsigned int version; int ret;
dev = &client->dev; @@ -381,6 +308,10 @@ static int tpa6130a2_probe(struct i2c_client *client, if (!data) return -ENOMEM;
+ data->regmap = devm_regmap_init_i2c(client, &tpa6130a2_regmap_config); + if (IS_ERR(data->regmap)) + return PTR_ERR(data->regmap); + if (pdata) { data->power_gpio = pdata->power_gpio; } else if (np) { @@ -399,11 +330,6 @@ static int tpa6130a2_probe(struct i2c_client *client,
mutex_init(&data->mutex);
- /* Set default register values */ - data->regs[TPA6130A2_REG_CONTROL] = TPA6130A2_SWS; - data->regs[TPA6130A2_REG_VOL_MUTE] = TPA6130A2_MUTE_R | - TPA6130A2_MUTE_L; - if (data->power_gpio >= 0) { ret = devm_gpio_request(dev, data->power_gpio, "tpa6130a2 enable"); @@ -440,10 +366,10 @@ static int tpa6130a2_probe(struct i2c_client *client,
/* Read version */ - ret = tpa6130a2_i2c_read(TPA6130A2_REG_VERSION) & - TPA6130A2_VERSION_MASK; - if ((ret != 1) && (ret != 2)) - dev_warn(dev, "UNTESTED version detected (%d)\n", ret); + regmap_read(data->regmap, TPA6130A2_REG_VERSION, &version); + version &= TPA6130A2_VERSION_MASK; + if ((version != 1) && (version != 2)) + dev_warn(dev, "UNTESTED version detected (%d)\n", version);
/* Disable the chip */ ret = tpa6130a2_power(0); diff --git a/sound/soc/codecs/tpa6130a2.h b/sound/soc/codecs/tpa6130a2.h index 78ee723..ef05a3f 100644 --- a/sound/soc/codecs/tpa6130a2.h +++ b/sound/soc/codecs/tpa6130a2.h @@ -30,8 +30,6 @@ #define TPA6130A2_REG_OUT_IMPEDANCE 0x03 #define TPA6130A2_REG_VERSION 0x04
-#define TPA6130A2_CACHEREGNUM (TPA6130A2_REG_VERSION + 1) - /* Register bits */ /* TPA6130A2_REG_CONTROL (0x01) */ #define TPA6130A2_SWS (0x01 << 0)
Hi,
On Sat, Jun 18, 2016 at 12:26:29AM -0300, Helen Koike wrote:
Use regmap instead of open-coding IO access and caching
Signed-off-by: Lars-Peter Clausen lars@metafoo.de [koike: port for upstream] Signed-off-by: Helen Koike helen.koike@collabora.co.uk
[On N900] Tested-By: Sebastian Reichel sre@kernel.org
-- Sebastian
The patch
ASoC: tap6130a2: Use regmap
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From a0d5ff4496dca6e435ae3adb286d6583cf785aca Mon Sep 17 00:00:00 2001
From: Helen Koike helen.koike@collabora.co.uk Date: Mon, 20 Jun 2016 14:12:30 -0300 Subject: [PATCH] ASoC: tap6130a2: Use regmap
Use regmap instead of open-coding IO access and caching
Signed-off-by: Lars-Peter Clausen lars@metafoo.de [koike: port for upstream] Signed-off-by: Helen Koike helen.koike@collabora.co.uk [On N900] Tested-By: Sebastian Reichel sre@kernel.org Reviewed-By: Sebastian Reichel sre@kernel.org Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/codecs/tpa6130a2.c | 166 ++++++++++++------------------------------- sound/soc/codecs/tpa6130a2.h | 2 - 2 files changed, 46 insertions(+), 122 deletions(-)
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index f31326a332fb..d90388a38903 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c @@ -32,6 +32,7 @@ #include <sound/tlv.h> #include <linux/of.h> #include <linux/of_gpio.h> +#include <linux/regmap.h>
#include "tpa6130a2.h"
@@ -45,92 +46,16 @@ static struct i2c_client *tpa6130a2_client; /* This struct is used to save the context */ struct tpa6130a2_data { struct mutex mutex; - unsigned char regs[TPA6130A2_CACHEREGNUM]; + struct regmap *regmap; struct regulator *supply; int power_gpio; u8 power_state:1; enum tpa_model id; };
-static int tpa6130a2_i2c_read(int reg) -{ - struct tpa6130a2_data *data; - int val; - - if (WARN_ON(!tpa6130a2_client)) - return -EINVAL; - data = i2c_get_clientdata(tpa6130a2_client); - - /* If powered off, return the cached value */ - if (data->power_state) { - val = i2c_smbus_read_byte_data(tpa6130a2_client, reg); - if (val < 0) - dev_err(&tpa6130a2_client->dev, "Read failed\n"); - else - data->regs[reg] = val; - } else { - val = data->regs[reg]; - } - - return val; -} - -static int tpa6130a2_i2c_write(int reg, u8 value) -{ - struct tpa6130a2_data *data; - int val = 0; - - if (WARN_ON(!tpa6130a2_client)) - return -EINVAL; - data = i2c_get_clientdata(tpa6130a2_client); - - if (data->power_state) { - val = i2c_smbus_write_byte_data(tpa6130a2_client, reg, value); - if (val < 0) { - dev_err(&tpa6130a2_client->dev, "Write failed\n"); - return val; - } - } - - /* Either powered on or off, we save the context */ - data->regs[reg] = value; - - return val; -} - -static u8 tpa6130a2_read(int reg) -{ - struct tpa6130a2_data *data; - - if (WARN_ON(!tpa6130a2_client)) - return 0; - data = i2c_get_clientdata(tpa6130a2_client); - - return data->regs[reg]; -} - -static int tpa6130a2_initialize(void) -{ - struct tpa6130a2_data *data; - int i, ret = 0; - - if (WARN_ON(!tpa6130a2_client)) - return -EINVAL; - data = i2c_get_clientdata(tpa6130a2_client); - - for (i = 1; i < TPA6130A2_REG_VERSION; i++) { - ret = tpa6130a2_i2c_write(i, data->regs[i]); - if (ret < 0) - break; - } - - return ret; -} - static int tpa6130a2_power(u8 power) { struct tpa6130a2_data *data; - u8 val; int ret = 0;
if (WARN_ON(!tpa6130a2_client)) @@ -153,7 +78,7 @@ static int tpa6130a2_power(u8 power) gpio_set_value(data->power_gpio, 1);
data->power_state = 1; - ret = tpa6130a2_initialize(); + ret = regcache_sync(data->regmap); if (ret < 0) { dev_err(&tpa6130a2_client->dev, "Failed to initialize chip\n"); @@ -165,9 +90,8 @@ static int tpa6130a2_power(u8 power) } } else { /* set SWS */ - val = tpa6130a2_read(TPA6130A2_REG_CONTROL); - val |= TPA6130A2_SWS; - tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val); + regmap_update_bits(data->regmap, TPA6130A2_REG_CONTROL, + TPA6130A2_SWS, TPA6130A2_SWS);
/* Power off */ if (data->power_gpio >= 0) @@ -181,6 +105,8 @@ static int tpa6130a2_power(u8 power) }
data->power_state = 0; + /* device regs does not match the cache state anymore */ + regcache_mark_dirty(data->regmap); }
exit: @@ -196,7 +122,7 @@ static int tpa6130a2_get_volsw(struct snd_kcontrol *kcontrol, struct tpa6130a2_data *data; unsigned int reg = mc->reg; unsigned int shift = mc->shift; - int max = mc->max; + int max = mc->max, val; unsigned int mask = (1 << fls(max)) - 1; unsigned int invert = mc->invert;
@@ -206,8 +132,8 @@ static int tpa6130a2_get_volsw(struct snd_kcontrol *kcontrol,
mutex_lock(&data->mutex);
- ucontrol->value.integer.value[0] = - (tpa6130a2_read(reg) >> shift) & mask; + regmap_read(data->regmap, reg, &val); + ucontrol->value.integer.value[0] = (val >> shift) & mask;
if (invert) ucontrol->value.integer.value[0] = @@ -229,7 +155,7 @@ static int tpa6130a2_put_volsw(struct snd_kcontrol *kcontrol, unsigned int mask = (1 << fls(max)) - 1; unsigned int invert = mc->invert; unsigned int val = (ucontrol->value.integer.value[0] & mask); - unsigned int val_reg; + bool change;
if (WARN_ON(!tpa6130a2_client)) return -EINVAL; @@ -239,20 +165,11 @@ static int tpa6130a2_put_volsw(struct snd_kcontrol *kcontrol, val = max - val;
mutex_lock(&data->mutex); - - val_reg = tpa6130a2_read(reg); - if (((val_reg >> shift) & mask) == val) { - mutex_unlock(&data->mutex); - return 0; - } - - val_reg &= ~(mask << shift); - val_reg |= val << shift; - tpa6130a2_i2c_write(reg, val_reg); - + regmap_update_bits_check(data->regmap, reg, mask << shift, val << shift, + &change); mutex_unlock(&data->mutex);
- return 1; + return change; }
/* @@ -301,31 +218,26 @@ static const struct snd_kcontrol_new tpa6140a2_controls[] = { */ static void tpa6130a2_channel_enable(u8 channel, int enable) { - u8 val; + struct tpa6130a2_data *data = i2c_get_clientdata(tpa6130a2_client);
if (enable) { /* Enable channel */ /* Enable amplifier */ - val = tpa6130a2_read(TPA6130A2_REG_CONTROL); - val |= channel; - val &= ~TPA6130A2_SWS; - tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val); + regmap_update_bits(data->regmap, TPA6130A2_REG_CONTROL, + channel | TPA6130A2_SWS, channel & ~TPA6130A2_SWS);
/* Unmute channel */ - val = tpa6130a2_read(TPA6130A2_REG_VOL_MUTE); - val &= ~channel; - tpa6130a2_i2c_write(TPA6130A2_REG_VOL_MUTE, val); + regmap_update_bits(data->regmap, TPA6130A2_REG_VOL_MUTE, + channel, 0); } else { /* Disable channel */ /* Mute channel */ - val = tpa6130a2_read(TPA6130A2_REG_VOL_MUTE); - val |= channel; - tpa6130a2_i2c_write(TPA6130A2_REG_VOL_MUTE, val); + regmap_update_bits(data->regmap, TPA6130A2_REG_VOL_MUTE, + channel, channel);
/* Disable amplifier */ - val = tpa6130a2_read(TPA6130A2_REG_CONTROL); - val &= ~channel; - tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val); + regmap_update_bits(data->regmap, TPA6130A2_REG_CONTROL, + channel, 0); } }
@@ -365,6 +277,20 @@ struct snd_soc_component_driver tpa6130a2_component_driver = { .probe = tpa6130a2_component_probe, };
+static const struct reg_default tpa6130a2_reg_defaults[] = { + { TPA6130A2_REG_CONTROL, TPA6130A2_SWS }, + { TPA6130A2_REG_VOL_MUTE, TPA6130A2_MUTE_R | TPA6130A2_MUTE_L }, +}; + +static const struct regmap_config tpa6130a2_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = TPA6130A2_REG_VERSION, + .reg_defaults = tpa6130a2_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(tpa6130a2_reg_defaults), + .cache_type = REGCACHE_RBTREE, +}; + static int tpa6130a2_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -373,6 +299,7 @@ static int tpa6130a2_probe(struct i2c_client *client, struct tpa6130a2_platform_data *pdata = client->dev.platform_data; struct device_node *np = client->dev.of_node; const char *regulator; + unsigned int version; int ret;
dev = &client->dev; @@ -381,6 +308,10 @@ static int tpa6130a2_probe(struct i2c_client *client, if (!data) return -ENOMEM;
+ data->regmap = devm_regmap_init_i2c(client, &tpa6130a2_regmap_config); + if (IS_ERR(data->regmap)) + return PTR_ERR(data->regmap); + if (pdata) { data->power_gpio = pdata->power_gpio; } else if (np) { @@ -399,11 +330,6 @@ static int tpa6130a2_probe(struct i2c_client *client,
mutex_init(&data->mutex);
- /* Set default register values */ - data->regs[TPA6130A2_REG_CONTROL] = TPA6130A2_SWS; - data->regs[TPA6130A2_REG_VOL_MUTE] = TPA6130A2_MUTE_R | - TPA6130A2_MUTE_L; - if (data->power_gpio >= 0) { ret = devm_gpio_request(dev, data->power_gpio, "tpa6130a2 enable"); @@ -440,10 +366,10 @@ static int tpa6130a2_probe(struct i2c_client *client,
/* Read version */ - ret = tpa6130a2_i2c_read(TPA6130A2_REG_VERSION) & - TPA6130A2_VERSION_MASK; - if ((ret != 1) && (ret != 2)) - dev_warn(dev, "UNTESTED version detected (%d)\n", ret); + regmap_read(data->regmap, TPA6130A2_REG_VERSION, &version); + version &= TPA6130A2_VERSION_MASK; + if ((version != 1) && (version != 2)) + dev_warn(dev, "UNTESTED version detected (%d)\n", version);
/* Disable the chip */ ret = tpa6130a2_power(0); diff --git a/sound/soc/codecs/tpa6130a2.h b/sound/soc/codecs/tpa6130a2.h index 78ee7237568b..ef05a3ff189b 100644 --- a/sound/soc/codecs/tpa6130a2.h +++ b/sound/soc/codecs/tpa6130a2.h @@ -30,8 +30,6 @@ #define TPA6130A2_REG_OUT_IMPEDANCE 0x03 #define TPA6130A2_REG_VERSION 0x04
-#define TPA6130A2_CACHEREGNUM (TPA6130A2_REG_VERSION + 1) - /* Register bits */ /* TPA6130A2_REG_CONTROL (0x01) */ #define TPA6130A2_SWS (0x01 << 0)
Use snd_soc_{info,get,put}_volsw instead of custom volume functions
Signed-off-by: Lars-Peter Clausen lars@metafoo.de [koike: port for upstream] Signed-off-by: Helen Koike helen.koike@collabora.co.uk --- sound/soc/codecs/tpa6130a2.c | 64 ++------------------------------------------ 1 file changed, 2 insertions(+), 62 deletions(-)
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index 0be70a4..dc7bfc9 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c @@ -114,64 +114,6 @@ exit: return ret; }
-static int tpa6130a2_get_volsw(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - struct tpa6130a2_data *data; - unsigned int reg = mc->reg; - unsigned int shift = mc->shift; - int max = mc->max, val; - unsigned int mask = (1 << fls(max)) - 1; - unsigned int invert = mc->invert; - - if (WARN_ON(!tpa6130a2_client)) - return -EINVAL; - data = i2c_get_clientdata(tpa6130a2_client); - - mutex_lock(&data->mutex); - - regmap_read(data->regmap, reg, &val); - ucontrol->value.integer.value[0] = (val >> shift) & mask; - - if (invert) - ucontrol->value.integer.value[0] = - max - ucontrol->value.integer.value[0]; - - mutex_unlock(&data->mutex); - return 0; -} - -static int tpa6130a2_put_volsw(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - struct tpa6130a2_data *data; - unsigned int reg = mc->reg; - unsigned int shift = mc->shift; - int max = mc->max; - unsigned int mask = (1 << fls(max)) - 1; - unsigned int invert = mc->invert; - unsigned int val = (ucontrol->value.integer.value[0] & mask); - bool change; - - if (WARN_ON(!tpa6130a2_client)) - return -EINVAL; - data = i2c_get_clientdata(tpa6130a2_client); - - if (invert) - val = max - val; - - mutex_lock(&data->mutex); - regmap_update_bits_check(data->regmap, reg, mask << shift, val << shift, - &change); - mutex_unlock(&data->mutex); - - return change; -} - /* * TPA6130 volume. From -59.5 to 4 dB with increasing step size when going * down in gain. @@ -190,9 +132,8 @@ static const DECLARE_TLV_DB_RANGE(tpa6130_tlv, );
static const struct snd_kcontrol_new tpa6130a2_controls[] = { - SOC_SINGLE_EXT_TLV("TPA6130A2 Headphone Playback Volume", + SOC_SINGLE_TLV("TPA6130A2 Headphone Playback Volume", TPA6130A2_REG_VOL_MUTE, 0, 0x3f, 0, - tpa6130a2_get_volsw, tpa6130a2_put_volsw, tpa6130_tlv), };
@@ -203,9 +144,8 @@ static const DECLARE_TLV_DB_RANGE(tpa6140_tlv, );
static const struct snd_kcontrol_new tpa6140a2_controls[] = { - SOC_SINGLE_EXT_TLV("TPA6140A2 Headphone Playback Volume", + SOC_SINGLE_TLV("TPA6140A2 Headphone Playback Volume", TPA6130A2_REG_VOL_MUTE, 1, 0x1f, 0, - tpa6130a2_get_volsw, tpa6130a2_put_volsw, tpa6140_tlv), };
Hi,
On Sat, Jun 18, 2016 at 12:26:30AM -0300, Helen Koike wrote:
Use snd_soc_{info,get,put}_volsw instead of custom volume functions
Signed-off-by: Lars-Peter Clausen lars@metafoo.de [koike: port for upstream] Signed-off-by: Helen Koike helen.koike@collabora.co.uk
[On N900] Tested-By: Sebastian Reichel sre@kernel.org
-- Sebastian
Add DAPM support and updated rx51 accordingly. As a consequence: - the exported function tpa6130a2_stereo_enable is not needed anymore - the mutex is dealt in the DAPM - the power state is tracked by the DAPM
Signed-off-by: Lars-Peter Clausen lars@metafoo.de [koike: port for upstream] Signed-off-by: Helen Koike helen.koike@collabora.co.uk --- sound/soc/codecs/tpa6130a2.c | 184 +++++++++++++++++-------------------------- sound/soc/codecs/tpa6130a2.h | 11 +-- sound/soc/omap/rx51.c | 22 ++---- 3 files changed, 86 insertions(+), 131 deletions(-)
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index dc7bfc9..7cb5066 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c @@ -41,79 +41,71 @@ enum tpa_model { TPA6140A2, };
-static struct i2c_client *tpa6130a2_client; - /* This struct is used to save the context */ struct tpa6130a2_data { - struct mutex mutex; struct regmap *regmap; struct regulator *supply; int power_gpio; - u8 power_state:1; enum tpa_model id; };
-static int tpa6130a2_power(u8 power) +static int tpa6130a2_power(struct device *dev, bool enable) { - struct tpa6130a2_data *data; - int ret = 0; - - if (WARN_ON(!tpa6130a2_client)) - return -EINVAL; - data = i2c_get_clientdata(tpa6130a2_client); - - mutex_lock(&data->mutex); - if (power == data->power_state) - goto exit; + struct tpa6130a2_data *data = dev_get_drvdata(dev); + int ret;
- if (power) { + if (enable) { ret = regulator_enable(data->supply); if (ret != 0) { - dev_err(&tpa6130a2_client->dev, - "Failed to enable supply: %d\n", ret); - goto exit; + dev_err(dev, "Failed to enable supply: %d\n", ret); + return ret; } /* Power on */ if (data->power_gpio >= 0) gpio_set_value(data->power_gpio, 1); - - data->power_state = 1; - ret = regcache_sync(data->regmap); - if (ret < 0) { - dev_err(&tpa6130a2_client->dev, - "Failed to initialize chip\n"); - if (data->power_gpio >= 0) - gpio_set_value(data->power_gpio, 0); - regulator_disable(data->supply); - data->power_state = 0; - goto exit; - } } else { - /* set SWS */ - regmap_update_bits(data->regmap, TPA6130A2_REG_CONTROL, - TPA6130A2_SWS, TPA6130A2_SWS); - /* Power off */ if (data->power_gpio >= 0) gpio_set_value(data->power_gpio, 0);
ret = regulator_disable(data->supply); if (ret != 0) { - dev_err(&tpa6130a2_client->dev, - "Failed to disable supply: %d\n", ret); - goto exit; + dev_err(dev, "Failed to disable supply: %d\n", ret); + return ret; }
- data->power_state = 0; /* device regs does not match the cache state anymore */ regcache_mark_dirty(data->regmap); }
-exit: - mutex_unlock(&data->mutex); return ret; }
+static int tpa6130a2_power_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kctrl, int event) +{ + struct snd_soc_component *c = snd_soc_dapm_to_component(w->dapm); + struct tpa6130a2_data *data = snd_soc_component_get_drvdata(c); + int ret; + + /* before widget power up */ + if (SND_SOC_DAPM_EVENT_ON(event)) { + /* Turn on the chip */ + tpa6130a2_power(c->dev, true); + /* Sync the registers */ + ret = regcache_sync(data->regmap); + if (ret < 0) { + dev_err(c->dev, "Failed to initialize chip\n"); + tpa6130a2_power(c->dev, false); + return ret; + } + /* after widget power down */ + } else + tpa6130a2_power(c->dev, false); + + return 0; +} + /* * TPA6130 volume. From -59.5 to 4 dB with increasing step size when going * down in gain. @@ -149,57 +141,6 @@ static const struct snd_kcontrol_new tpa6140a2_controls[] = { tpa6140_tlv), };
-/* - * Enable or disable channel (left or right) - * The bit number for mute and amplifier are the same per channel: - * bit 6: Right channel - * bit 7: Left channel - * in both registers. - */ -static void tpa6130a2_channel_enable(u8 channel, int enable) -{ - struct tpa6130a2_data *data = i2c_get_clientdata(tpa6130a2_client); - - if (enable) { - /* Enable channel */ - /* Enable amplifier */ - regmap_update_bits(data->regmap, TPA6130A2_REG_CONTROL, - channel | TPA6130A2_SWS, channel & ~TPA6130A2_SWS); - - /* Unmute channel */ - regmap_update_bits(data->regmap, TPA6130A2_REG_VOL_MUTE, - channel, 0); - } else { - /* Disable channel */ - /* Mute channel */ - regmap_update_bits(data->regmap, TPA6130A2_REG_VOL_MUTE, - channel, channel); - - /* Disable amplifier */ - regmap_update_bits(data->regmap, TPA6130A2_REG_CONTROL, - channel, 0); - } -} - -int tpa6130a2_stereo_enable(struct snd_soc_codec *codec, int enable) -{ - int ret = 0; - if (enable) { - ret = tpa6130a2_power(1); - if (ret < 0) - return ret; - tpa6130a2_channel_enable(TPA6130A2_HP_EN_R | TPA6130A2_HP_EN_L, - 1); - } else { - tpa6130a2_channel_enable(TPA6130A2_HP_EN_R | TPA6130A2_HP_EN_L, - 0); - ret = tpa6130a2_power(0); - } - - return ret; -} -EXPORT_SYMBOL_GPL(tpa6130a2_stereo_enable); - static int tpa6130a2_component_probe(struct snd_soc_component *component) { struct tpa6130a2_data *data = snd_soc_component_get_drvdata(component); @@ -212,9 +153,47 @@ static int tpa6130a2_component_probe(struct snd_soc_component *component) tpa6130a2_controls, ARRAY_SIZE(tpa6130a2_controls)); }
+static const struct snd_soc_dapm_widget tpa6130a2_dapm_widgets[] = { + SND_SOC_DAPM_INPUT("LEFTIN"), + SND_SOC_DAPM_INPUT("RIGHTIN"), + SND_SOC_DAPM_OUTPUT("HPLEFT"), + SND_SOC_DAPM_OUTPUT("HPRIGHT"), + + SND_SOC_DAPM_PGA("Left Mute", TPA6130A2_REG_VOL_MUTE, + TPA6130A2_HP_EN_L_SHIFT, 1, NULL, 0), + SND_SOC_DAPM_PGA("Right Mute", TPA6130A2_REG_VOL_MUTE, + TPA6130A2_HP_EN_R_SHIFT, 1, NULL, 0), + SND_SOC_DAPM_PGA("Left PGA", TPA6130A2_REG_CONTROL, + TPA6130A2_HP_EN_L_SHIFT, 0, NULL, 0), + SND_SOC_DAPM_PGA("Right PGA", TPA6130A2_REG_CONTROL, + TPA6130A2_HP_EN_R_SHIFT, 0, NULL, 0), + + SND_SOC_DAPM_SUPPLY("Power", TPA6130A2_REG_CONTROL, + TPA6130A2_SWS_SHIFT, 1, tpa6130a2_power_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +}; + +static const struct snd_soc_dapm_route tpa6130a2_dapm_routes[] = { + { "Left PGA", NULL, "LEFTIN" }, + { "Right PGA", NULL, "RIGHTIN" }, + + { "Left Mute", NULL, "Left PGA" }, + { "Right Mute", NULL, "Right PGA" }, + + { "HPLEFT", NULL, "Left Mute" }, + { "HPRIGHT", NULL, "Right Mute" }, + + { "Left PGA", NULL, "Power" }, + { "Right PGA", NULL, "Power" }, +}; + struct snd_soc_component_driver tpa6130a2_component_driver = { .name = "tpa6130a2", .probe = tpa6130a2_component_probe, + .dapm_widgets = tpa6130a2_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(tpa6130a2_dapm_widgets), + .dapm_routes = tpa6130a2_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(tpa6130a2_dapm_routes), };
static const struct reg_default tpa6130a2_reg_defaults[] = { @@ -262,14 +241,10 @@ static int tpa6130a2_probe(struct i2c_client *client, return -ENODEV; }
- tpa6130a2_client = client; - - i2c_set_clientdata(tpa6130a2_client, data); + i2c_set_clientdata(client, data);
data->id = id->driver_data;
- mutex_init(&data->mutex); - if (data->power_gpio >= 0) { ret = devm_gpio_request(dev, data->power_gpio, "tpa6130a2 enable"); @@ -300,7 +275,7 @@ static int tpa6130a2_probe(struct i2c_client *client, goto err_gpio; }
- ret = tpa6130a2_power(1); + ret = tpa6130a2_power(dev, true); if (ret != 0) goto err_gpio;
@@ -312,7 +287,7 @@ static int tpa6130a2_probe(struct i2c_client *client, dev_warn(dev, "UNTESTED version detected (%d)\n", version);
/* Disable the chip */ - ret = tpa6130a2_power(0); + ret = tpa6130a2_power(dev, false); if (ret != 0) goto err_gpio;
@@ -320,19 +295,9 @@ static int tpa6130a2_probe(struct i2c_client *client, &tpa6130a2_component_driver, NULL, 0);
err_gpio: - tpa6130a2_client = NULL; - return ret; }
-static int tpa6130a2_remove(struct i2c_client *client) -{ - tpa6130a2_power(0); - tpa6130a2_client = NULL; - - return 0; -} - static const struct i2c_device_id tpa6130a2_id[] = { { "tpa6130a2", TPA6130A2 }, { "tpa6140a2", TPA6140A2 }, @@ -355,7 +320,6 @@ static struct i2c_driver tpa6130a2_i2c_driver = { .of_match_table = of_match_ptr(tpa6130a2_of_match), }, .probe = tpa6130a2_probe, - .remove = tpa6130a2_remove, .id_table = tpa6130a2_id, };
diff --git a/sound/soc/codecs/tpa6130a2.h b/sound/soc/codecs/tpa6130a2.h index ef05a3f..f19cad5 100644 --- a/sound/soc/codecs/tpa6130a2.h +++ b/sound/soc/codecs/tpa6130a2.h @@ -32,15 +32,18 @@
/* Register bits */ /* TPA6130A2_REG_CONTROL (0x01) */ -#define TPA6130A2_SWS (0x01 << 0) +#define TPA6130A2_SWS_SHIFT 0 +#define TPA6130A2_SWS (0x01 << TPA6130A2_SWS_SHIFT) #define TPA6130A2_TERMAL (0x01 << 1) #define TPA6130A2_MODE(x) (x << 4) #define TPA6130A2_MODE_STEREO (0x00) #define TPA6130A2_MODE_DUAL_MONO (0x01) #define TPA6130A2_MODE_BRIDGE (0x02) #define TPA6130A2_MODE_MASK (0x03) -#define TPA6130A2_HP_EN_R (0x01 << 6) -#define TPA6130A2_HP_EN_L (0x01 << 7) +#define TPA6130A2_HP_EN_R_SHIFT 6 +#define TPA6130A2_HP_EN_R (0x01 << TPA6130A2_HP_EN_R_SHIFT) +#define TPA6130A2_HP_EN_L_SHIFT 7 +#define TPA6130A2_HP_EN_L (0x01 << TPA6130A2_HP_EN_L_SHIFT)
/* TPA6130A2_REG_VOL_MUTE (0x02) */ #define TPA6130A2_VOLUME(x) ((x & 0x3f) << 0) @@ -54,6 +57,4 @@ /* TPA6130A2_REG_VERSION (0x04) */ #define TPA6130A2_VERSION_MASK (0x0f)
-extern int tpa6130a2_stereo_enable(struct snd_soc_codec *codec, int enable); - #endif /* __TPA6130A2_H__ */ diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c index b59cf89..8c29a34 100644 --- a/sound/soc/omap/rx51.c +++ b/sound/soc/omap/rx51.c @@ -164,19 +164,6 @@ static int rx51_spk_event(struct snd_soc_dapm_widget *w, return 0; }
-static int rx51_hp_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *k, int event) -{ - struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); - - if (SND_SOC_DAPM_EVENT_ON(event)) - tpa6130a2_stereo_enable(codec, 1); - else - tpa6130a2_stereo_enable(codec, 0); - - return 0; -} - static int rx51_get_input(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -235,7 +222,7 @@ static struct snd_soc_jack_gpio rx51_av_jack_gpios[] = { static const struct snd_soc_dapm_widget aic34_dapm_widgets[] = { SND_SOC_DAPM_SPK("Ext Spk", rx51_spk_event), SND_SOC_DAPM_MIC("DMic", NULL), - SND_SOC_DAPM_HP("Headphone Jack", rx51_hp_event), + SND_SOC_DAPM_HP("Headphone Jack", NULL), SND_SOC_DAPM_MIC("HS Mic", NULL), SND_SOC_DAPM_LINE("FM Transmitter", NULL), SND_SOC_DAPM_SPK("Earphone", NULL), @@ -246,11 +233,14 @@ static const struct snd_soc_dapm_route audio_map[] = { {"Ext Spk", NULL, "HPROUT"}, {"Ext Spk", NULL, "HPLCOM"}, {"Ext Spk", NULL, "HPRCOM"}, - {"Headphone Jack", NULL, "LLOUT"}, - {"Headphone Jack", NULL, "RLOUT"}, {"FM Transmitter", NULL, "LLOUT"}, {"FM Transmitter", NULL, "RLOUT"},
+ {"Headphone Jack", NULL, "TPA6130A2 HPLEFT"}, + {"Headphone Jack", NULL, "TPA6130A2 HPRIGHT"}, + {"TPA6130A2 HPLEFT", NULL, "LLOUT"}, + {"TPA6130A2 HPRIGHT", NULL, "RLOUT"}, + {"DMic Rate 64", NULL, "DMic"}, {"DMic", NULL, "Mic Bias"},
Hi,
On Sat, Jun 18, 2016 at 12:26:31AM -0300, Helen Koike wrote:
Add DAPM support and updated rx51 accordingly. As a consequence:
- the exported function tpa6130a2_stereo_enable is not needed anymore
- the mutex is dealt in the DAPM
- the power state is tracked by the DAPM
This breaks headphone on N900. So far I only checked, that tpa6130a2_power_event() is not called. I guess the DAPM graph is wrong.
-- Sebastian
On 06/19/2016 01:21 AM, Sebastian Reichel wrote:
Hi,
On Sat, Jun 18, 2016 at 12:26:31AM -0300, Helen Koike wrote:
Add DAPM support and updated rx51 accordingly. As a consequence:
- the exported function tpa6130a2_stereo_enable is not needed anymore
- the mutex is dealt in the DAPM
- the power state is tracked by the DAPM
This breaks headphone on N900. So far I only checked, that tpa6130a2_power_event() is not called. I guess the DAPM graph is wrong.
Can you try with
+ {"TPA6130A2 HPLEFT", NULL, "LLOUT"}, + {"TPA6130A2 HPRIGHT", NULL, "RLOUT"}
being replaced with
+ {"TPA6130A2 LEFTIN", NULL, "LLOUT"}, + {"TPA6130A2 RIGHTIN", NULL, "RLOUT"},
Thanks, - Lars
Hi,
On Sun, Jun 19, 2016 at 11:39:15AM +0200, Lars-Peter Clausen wrote:
On 06/19/2016 01:21 AM, Sebastian Reichel wrote:
On Sat, Jun 18, 2016 at 12:26:31AM -0300, Helen Koike wrote:
Add DAPM support and updated rx51 accordingly. As a consequence:
- the exported function tpa6130a2_stereo_enable is not needed anymore
- the mutex is dealt in the DAPM
- the power state is tracked by the DAPM
This breaks headphone on N900. So far I only checked, that tpa6130a2_power_event() is not called. I guess the DAPM graph is wrong.
Can you try with
- {"TPA6130A2 HPLEFT", NULL, "LLOUT"},
- {"TPA6130A2 HPRIGHT", NULL, "RLOUT"}
being replaced with
{"TPA6130A2 LEFTIN", NULL, "LLOUT"},
{"TPA6130A2 RIGHTIN", NULL, "RLOUT"},
With that change:
Tested-By: Sebastian Reichel sre@kernel.org Reviewed-By: Sebastian Reichel sre@kernel.org
-- Sebastian
On 06/18/2016 07:42 AM, Helen Koike wrote:
Add DAPM support and updated rx51 accordingly. As a consequence:
- the exported function tpa6130a2_stereo_enable is not needed anymore
- the mutex is dealt in the DAPM
- the power state is tracked by the DAPM
Signed-off-by: Lars-Peter Clausen lars@metafoo.de [koike: port for upstream] Signed-off-by: Helen Koike helen.koike@collabora.co.uk
sound/soc/codecs/tpa6130a2.c | 184 +++++++++++++++++-------------------------- sound/soc/codecs/tpa6130a2.h | 11 +-- sound/soc/omap/rx51.c | 22 ++---- 3 files changed, 86 insertions(+), 131 deletions(-)
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index dc7bfc9..7cb5066 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c @@ -41,79 +41,71 @@ enum tpa_model { TPA6140A2, };
-static struct i2c_client *tpa6130a2_client;
/* This struct is used to save the context */ struct tpa6130a2_data {
- struct mutex mutex; struct regmap *regmap; struct regulator *supply; int power_gpio;
- u8 power_state:1; enum tpa_model id;
};
-static int tpa6130a2_power(u8 power) +static int tpa6130a2_power(struct device *dev, bool enable)
I would rather add 'struct device *dev' to tpa6130a2_data and pass the pointer to the private struct instead to the device.
{
- struct tpa6130a2_data *data;
- int ret = 0;
- if (WARN_ON(!tpa6130a2_client))
return -EINVAL;
- data = i2c_get_clientdata(tpa6130a2_client);
- mutex_lock(&data->mutex);
- if (power == data->power_state)
goto exit;
- struct tpa6130a2_data *data = dev_get_drvdata(dev);
- int ret;
- if (power) {
- if (enable) {
Hi,
On Sat, Jun 18, 2016 at 12:26:27AM -0300, Helen Koike wrote:
The current tpa6130a2 driver supports only a single instance. This patch series add support for multiple instances by removing the global variable that holds the instance. This is performed by using the component API, regmap, the snd_soc_{info,put,get}_volsw API and DAPM.
yay! *stroking cleanup of the driver from my todo list*
This patch series also touches code from the Nokia RX51 which I didn't tested (as I am testing the tpa6130a2 in another board, that is not upstream). I would appreciate is if someone who possesses the Nokia RX51 (n900) could please test the code.
I had a look at the rx51 parts and will test later/tomorrow. From looking at the source code: You can also remove the "../codecs/tpa6130a2.h" include from rx51.c.
This patch series is based on git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next Available at https://git.collabora.com/cgit/user/koike/linux.git/log/?h=sound/review/tpa6...
Helen Koike (4): ASoC: tpa6130a2: Register component ASoC: tap6130a2: Use regmap ASoC: tpa6130a2: Use snd soc volsw functions ASoC: tpa6130a2: Add DAPM support
sound/soc/codecs/tpa6130a2.c | 382 ++++++++++++------------------------------- sound/soc/codecs/tpa6130a2.h | 14 +- sound/soc/omap/rx51.c | 45 ++--- 3 files changed, 130 insertions(+), 311 deletions(-)
nice stats :)
-- Sebastian
Hi,
On Sat, Jun 18, 2016 at 12:40:38PM +0200, Sebastian Reichel wrote:
On Sat, Jun 18, 2016 at 12:26:27AM -0300, Helen Koike wrote:
The current tpa6130a2 driver supports only a single instance. This patch series add support for multiple instances by removing the global variable that holds the instance. This is performed by using the component API, regmap, the snd_soc_{info,put,get}_volsw API and DAPM.
yay! *stroking cleanup of the driver from my todo list*
This patch series also touches code from the Nokia RX51 which I didn't tested (as I am testing the tpa6130a2 in another board, that is not upstream). I would appreciate is if someone who possesses the Nokia RX51 (n900) could please test the code.
I had a look at the rx51 parts and will test later/tomorrow.
Ok, here are some notes (I used the git branch you provided). First of all kernel messages contain:
[ 4.217163] ALSA: Control name 'TPA6130A2 TPA6130A2 Headphone Playback Volum' truncated to 'TPA6130A2 TPA6130A2 Headphone Playback Volu'
Next here is a amixer output diff:
root@n900:~# amixer > amixer.old (v4.7-rc [without your patches]) root@n900:~# amixer > amixer.new root@n900:~# diff -u amixer.old amixer.new --- amixer.old 2016-06-18 23:08:57.478027343 +0200 +++ amixer.new 2016-06-18 22:26:13.878102558 +0200 @@ -480,11 +480,12 @@ Capabilities: pswitch pswitch-joined Playback channels: Mono Mono: Playback [off] -Simple mixer control 'TPA6130A2 Headphone',0 - Capabilities: pvolume pvolume-joined +Simple mixer control 'TPA6130A2 TPA6130A2 Headphone Playback Volu',0 + Capabilities: volume volume-joined Playback channels: Mono - Limits: Playback 0 - 42 - Mono: Playback 0 [0%] [-59.50dB] + Capture channels: Mono + Limits: 0 - 63 + Mono: 0 [0%] Simple mixer control 'b ADC HPF Cut-off',0 Capabilities: enum Items: 'Disabled' '0.0045xFs' '0.0125xFs' '0.025xFs'
If I remember correctly, the reduced playback limit up to 42 is important on N900, since hardware can be destroyed. It may have been another control, though. Also the capture channel looks wrong.
Last but not least: Audio output doesn't work, but works on a kernel without these changes.
-- Sebastian
The current tpa6130a2 driver supports only a single instance. This patch series add support for multiple instances by removing the global variable that holds the instance. This is performed by using the component API, regmap, the snd_soc_{info,put,get}_volsw API and DAPM.
This patch series also touches code from the Nokia RX51 which I didn't tested (as I am testing the tpa6130a2 in another board that is not upstream). I would appreciate is if someone who possesses the Nokia RX51 (n900) could please test the code.
This patch series is based on git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next Available at https://git.collabora.com/cgit/user/koike/linux.git/log/?h=sound/review/tpa6...
Helen Koike (5): ASoC: tpa6130a2: Register component ASoC: tap6130a2: Use regmap ASoC: tpa6130a2: Use snd soc volsw functions ASoC: tpa6130a2: Add DAPM support ASoC: tpa6130a2: Remove goto err_gpio
sound/soc/codecs/tpa6130a2.c | 393 ++++++++++++------------------------------- sound/soc/codecs/tpa6130a2.h | 14 +- sound/soc/omap/rx51.c | 46 ++--- 3 files changed, 136 insertions(+), 317 deletions(-)
Changes since v1: ASoC: tpa6130a2: Register component - Remove prefix from snd_kcontrol_new in tpa6130a2.c - Add tested-by and reviewd-by from Sebastian ASoC: tap6130a2: Use regmap - Add tested-by from Sebastian ASoC: tpa6130a2: Use snd soc volsw functions - Add tested-by from Sebastian ASoC: tpa6130a2: Add DAPM support - Replace + {"TPA6130A2 HPLEFT", NULL, "LLOUT"}, + {"TPA6130A2 HPRIGHT", NULL, "RLOUT"} by + {"TPA6130A2 LEFTIN", NULL, "LLOUT"}, + {"TPA6130A2 RIGHTIN", NULL, "RLOUT"}, - Add tested-by and reviewed-by from Sebastian - Add struct device dev* in struct tpa6130a2_data and pass data instead of dev to tpa6130a2_power function - remove #include "../codecs/tpa6130a2.h" in rx51.c ASoC: tpa6130a2: Remove goto err_gpio - this is a new patch in the series
Add tpa6130a2 controls by the component API and update rx51 accordingly
Signed-off-by: Lars-Peter Clausen lars@metafoo.de [koike: port for upstream] Signed-off-by: Helen Koike helen.koike@collabora.co.uk Tested-By: Sebastian Reichel sre@kernel.org Reviewed-By: Sebastian Reichel sre@kernel.org
---
Changes since v1: - Remove prefix from snd_kcontrol_new in tpa6130a2.c - Add tested-by and reviewd-by from Sebastian
sound/soc/codecs/tpa6130a2.c | 30 +++++++++++++++--------------- sound/soc/codecs/tpa6130a2.h | 1 - sound/soc/omap/rx51.c | 23 ++++++++++++----------- 3 files changed, 27 insertions(+), 27 deletions(-)
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index 11d85c5..f31326a 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c @@ -273,7 +273,7 @@ static const DECLARE_TLV_DB_RANGE(tpa6130_tlv, );
static const struct snd_kcontrol_new tpa6130a2_controls[] = { - SOC_SINGLE_EXT_TLV("TPA6130A2 Headphone Playback Volume", + SOC_SINGLE_EXT_TLV("Headphone Playback Volume", TPA6130A2_REG_VOL_MUTE, 0, 0x3f, 0, tpa6130a2_get_volsw, tpa6130a2_put_volsw, tpa6130_tlv), @@ -286,7 +286,7 @@ static const DECLARE_TLV_DB_RANGE(tpa6140_tlv, );
static const struct snd_kcontrol_new tpa6140a2_controls[] = { - SOC_SINGLE_EXT_TLV("TPA6140A2 Headphone Playback Volume", + SOC_SINGLE_EXT_TLV("Headphone Playback Volume", TPA6130A2_REG_VOL_MUTE, 1, 0x1f, 0, tpa6130a2_get_volsw, tpa6130a2_put_volsw, tpa6140_tlv), @@ -348,23 +348,22 @@ int tpa6130a2_stereo_enable(struct snd_soc_codec *codec, int enable) } EXPORT_SYMBOL_GPL(tpa6130a2_stereo_enable);
-int tpa6130a2_add_controls(struct snd_soc_codec *codec) +static int tpa6130a2_component_probe(struct snd_soc_component *component) { - struct tpa6130a2_data *data; - - if (tpa6130a2_client == NULL) - return -ENODEV; - - data = i2c_get_clientdata(tpa6130a2_client); + struct tpa6130a2_data *data = snd_soc_component_get_drvdata(component);
if (data->id == TPA6140A2) - return snd_soc_add_codec_controls(codec, tpa6140a2_controls, - ARRAY_SIZE(tpa6140a2_controls)); + return snd_soc_add_component_controls(component, + tpa6140a2_controls, ARRAY_SIZE(tpa6140a2_controls)); else - return snd_soc_add_codec_controls(codec, tpa6130a2_controls, - ARRAY_SIZE(tpa6130a2_controls)); + return snd_soc_add_component_controls(component, + tpa6130a2_controls, ARRAY_SIZE(tpa6130a2_controls)); } -EXPORT_SYMBOL_GPL(tpa6130a2_add_controls); + +struct snd_soc_component_driver tpa6130a2_component_driver = { + .name = "tpa6130a2", + .probe = tpa6130a2_component_probe, +};
static int tpa6130a2_probe(struct i2c_client *client, const struct i2c_device_id *id) @@ -451,7 +450,8 @@ static int tpa6130a2_probe(struct i2c_client *client, if (ret != 0) goto err_gpio;
- return 0; + return devm_snd_soc_register_component(&client->dev, + &tpa6130a2_component_driver, NULL, 0);
err_gpio: tpa6130a2_client = NULL; diff --git a/sound/soc/codecs/tpa6130a2.h b/sound/soc/codecs/tpa6130a2.h index 4174440..78ee723 100644 --- a/sound/soc/codecs/tpa6130a2.h +++ b/sound/soc/codecs/tpa6130a2.h @@ -56,7 +56,6 @@ /* TPA6130A2_REG_VERSION (0x04) */ #define TPA6130A2_VERSION_MASK (0x0f)
-extern int tpa6130a2_add_controls(struct snd_soc_codec *codec); extern int tpa6130a2_stereo_enable(struct snd_soc_codec *codec, int enable);
#endif /* __TPA6130A2_H__ */ diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c index 5494924..b59cf89 100644 --- a/sound/soc/omap/rx51.c +++ b/sound/soc/omap/rx51.c @@ -286,16 +286,10 @@ static const struct snd_kcontrol_new aic34_rx51_controls[] = {
static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd) { - struct snd_soc_codec *codec = rtd->codec; struct snd_soc_card *card = rtd->card; struct rx51_audio_pdata *pdata = snd_soc_card_get_drvdata(card); int err;
- err = tpa6130a2_add_controls(codec); - if (err < 0) { - dev_err(card->dev, "Failed to add TPA6130A2 controls\n"); - return err; - } snd_soc_limit_volume(card, "TPA6130A2 Headphone Playback Volume", 42);
err = omap_mcbsp_st_add_controls(rtd, 2); @@ -357,6 +351,10 @@ static struct snd_soc_aux_dev rx51_aux_dev[] = { .name = "TLV320AIC34b", .codec_name = "tlv320aic3x-codec.2-0019", }, + { + .name = "TPA61320A2", + .codec_name = "tpa6130a2.2-0060", + }, };
static struct snd_soc_codec_conf rx51_codec_conf[] = { @@ -364,6 +362,10 @@ static struct snd_soc_codec_conf rx51_codec_conf[] = { .dev_name = "tlv320aic3x-codec.2-0019", .name_prefix = "b", }, + { + .dev_name = "tpa6130a2.2-0060", + .name_prefix = "TPA6130A2", + }, };
/* Audio card */ @@ -435,11 +437,10 @@ static int rx51_soc_probe(struct platform_device *pdev) dev_err(&pdev->dev, "Headphone amplifier node is not provided\n"); return -EINVAL; } - - /* TODO: tpa6130a2a driver supports only a single instance, so - * this driver ignores the headphone-amplifier node for now. - * It's already mandatory in the DT binding to be future proof. - */ + rx51_aux_dev[1].codec_name = NULL; + rx51_aux_dev[1].codec_of_node = dai_node; + rx51_codec_conf[1].dev_name = NULL; + rx51_codec_conf[1].of_node = dai_node; }
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
The patch
ASoC: tpa6130a2: Register component
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From cb7e62256e99d285e415cf75db67558f0f8bb107 Mon Sep 17 00:00:00 2001
From: Helen Koike helen.koike@collabora.co.uk Date: Mon, 20 Jun 2016 14:12:29 -0300 Subject: [PATCH] ASoC: tpa6130a2: Register component
Add tpa6130a2 controls by the component API and update rx51 accordingly
Signed-off-by: Lars-Peter Clausen lars@metafoo.de [koike: port for upstream] Signed-off-by: Helen Koike helen.koike@collabora.co.uk Tested-By: Sebastian Reichel sre@kernel.org Reviewed-By: Sebastian Reichel sre@kernel.org Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/codecs/tpa6130a2.c | 30 +++++++++++++++--------------- sound/soc/codecs/tpa6130a2.h | 1 - sound/soc/omap/rx51.c | 23 ++++++++++++----------- 3 files changed, 27 insertions(+), 27 deletions(-)
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index 11d85c5c787a..f31326a332fb 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c @@ -273,7 +273,7 @@ static const DECLARE_TLV_DB_RANGE(tpa6130_tlv, );
static const struct snd_kcontrol_new tpa6130a2_controls[] = { - SOC_SINGLE_EXT_TLV("TPA6130A2 Headphone Playback Volume", + SOC_SINGLE_EXT_TLV("Headphone Playback Volume", TPA6130A2_REG_VOL_MUTE, 0, 0x3f, 0, tpa6130a2_get_volsw, tpa6130a2_put_volsw, tpa6130_tlv), @@ -286,7 +286,7 @@ static const DECLARE_TLV_DB_RANGE(tpa6140_tlv, );
static const struct snd_kcontrol_new tpa6140a2_controls[] = { - SOC_SINGLE_EXT_TLV("TPA6140A2 Headphone Playback Volume", + SOC_SINGLE_EXT_TLV("Headphone Playback Volume", TPA6130A2_REG_VOL_MUTE, 1, 0x1f, 0, tpa6130a2_get_volsw, tpa6130a2_put_volsw, tpa6140_tlv), @@ -348,23 +348,22 @@ int tpa6130a2_stereo_enable(struct snd_soc_codec *codec, int enable) } EXPORT_SYMBOL_GPL(tpa6130a2_stereo_enable);
-int tpa6130a2_add_controls(struct snd_soc_codec *codec) +static int tpa6130a2_component_probe(struct snd_soc_component *component) { - struct tpa6130a2_data *data; - - if (tpa6130a2_client == NULL) - return -ENODEV; - - data = i2c_get_clientdata(tpa6130a2_client); + struct tpa6130a2_data *data = snd_soc_component_get_drvdata(component);
if (data->id == TPA6140A2) - return snd_soc_add_codec_controls(codec, tpa6140a2_controls, - ARRAY_SIZE(tpa6140a2_controls)); + return snd_soc_add_component_controls(component, + tpa6140a2_controls, ARRAY_SIZE(tpa6140a2_controls)); else - return snd_soc_add_codec_controls(codec, tpa6130a2_controls, - ARRAY_SIZE(tpa6130a2_controls)); + return snd_soc_add_component_controls(component, + tpa6130a2_controls, ARRAY_SIZE(tpa6130a2_controls)); } -EXPORT_SYMBOL_GPL(tpa6130a2_add_controls); + +struct snd_soc_component_driver tpa6130a2_component_driver = { + .name = "tpa6130a2", + .probe = tpa6130a2_component_probe, +};
static int tpa6130a2_probe(struct i2c_client *client, const struct i2c_device_id *id) @@ -451,7 +450,8 @@ static int tpa6130a2_probe(struct i2c_client *client, if (ret != 0) goto err_gpio;
- return 0; + return devm_snd_soc_register_component(&client->dev, + &tpa6130a2_component_driver, NULL, 0);
err_gpio: tpa6130a2_client = NULL; diff --git a/sound/soc/codecs/tpa6130a2.h b/sound/soc/codecs/tpa6130a2.h index 417444020ba6..78ee7237568b 100644 --- a/sound/soc/codecs/tpa6130a2.h +++ b/sound/soc/codecs/tpa6130a2.h @@ -56,7 +56,6 @@ /* TPA6130A2_REG_VERSION (0x04) */ #define TPA6130A2_VERSION_MASK (0x0f)
-extern int tpa6130a2_add_controls(struct snd_soc_codec *codec); extern int tpa6130a2_stereo_enable(struct snd_soc_codec *codec, int enable);
#endif /* __TPA6130A2_H__ */ diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c index 54949242bc70..b59cf89c5cab 100644 --- a/sound/soc/omap/rx51.c +++ b/sound/soc/omap/rx51.c @@ -286,16 +286,10 @@ static const struct snd_kcontrol_new aic34_rx51_controls[] = {
static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd) { - struct snd_soc_codec *codec = rtd->codec; struct snd_soc_card *card = rtd->card; struct rx51_audio_pdata *pdata = snd_soc_card_get_drvdata(card); int err;
- err = tpa6130a2_add_controls(codec); - if (err < 0) { - dev_err(card->dev, "Failed to add TPA6130A2 controls\n"); - return err; - } snd_soc_limit_volume(card, "TPA6130A2 Headphone Playback Volume", 42);
err = omap_mcbsp_st_add_controls(rtd, 2); @@ -357,6 +351,10 @@ static struct snd_soc_aux_dev rx51_aux_dev[] = { .name = "TLV320AIC34b", .codec_name = "tlv320aic3x-codec.2-0019", }, + { + .name = "TPA61320A2", + .codec_name = "tpa6130a2.2-0060", + }, };
static struct snd_soc_codec_conf rx51_codec_conf[] = { @@ -364,6 +362,10 @@ static struct snd_soc_codec_conf rx51_codec_conf[] = { .dev_name = "tlv320aic3x-codec.2-0019", .name_prefix = "b", }, + { + .dev_name = "tpa6130a2.2-0060", + .name_prefix = "TPA6130A2", + }, };
/* Audio card */ @@ -435,11 +437,10 @@ static int rx51_soc_probe(struct platform_device *pdev) dev_err(&pdev->dev, "Headphone amplifier node is not provided\n"); return -EINVAL; } - - /* TODO: tpa6130a2a driver supports only a single instance, so - * this driver ignores the headphone-amplifier node for now. - * It's already mandatory in the DT binding to be future proof. - */ + rx51_aux_dev[1].codec_name = NULL; + rx51_aux_dev[1].codec_of_node = dai_node; + rx51_codec_conf[1].dev_name = NULL; + rx51_codec_conf[1].of_node = dai_node; }
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
Use regmap instead of open-coding IO access and caching
Signed-off-by: Lars-Peter Clausen lars@metafoo.de [koike: port for upstream] Signed-off-by: Helen Koike helen.koike@collabora.co.uk [On N900] Tested-By: Sebastian Reichel sre@kernel.org
---
Changes since v1: - Add tested-by from Sebastian
sound/soc/codecs/tpa6130a2.c | 166 ++++++++++++------------------------------- sound/soc/codecs/tpa6130a2.h | 2 - 2 files changed, 46 insertions(+), 122 deletions(-)
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index f31326a..d90388a 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c @@ -32,6 +32,7 @@ #include <sound/tlv.h> #include <linux/of.h> #include <linux/of_gpio.h> +#include <linux/regmap.h>
#include "tpa6130a2.h"
@@ -45,92 +46,16 @@ static struct i2c_client *tpa6130a2_client; /* This struct is used to save the context */ struct tpa6130a2_data { struct mutex mutex; - unsigned char regs[TPA6130A2_CACHEREGNUM]; + struct regmap *regmap; struct regulator *supply; int power_gpio; u8 power_state:1; enum tpa_model id; };
-static int tpa6130a2_i2c_read(int reg) -{ - struct tpa6130a2_data *data; - int val; - - if (WARN_ON(!tpa6130a2_client)) - return -EINVAL; - data = i2c_get_clientdata(tpa6130a2_client); - - /* If powered off, return the cached value */ - if (data->power_state) { - val = i2c_smbus_read_byte_data(tpa6130a2_client, reg); - if (val < 0) - dev_err(&tpa6130a2_client->dev, "Read failed\n"); - else - data->regs[reg] = val; - } else { - val = data->regs[reg]; - } - - return val; -} - -static int tpa6130a2_i2c_write(int reg, u8 value) -{ - struct tpa6130a2_data *data; - int val = 0; - - if (WARN_ON(!tpa6130a2_client)) - return -EINVAL; - data = i2c_get_clientdata(tpa6130a2_client); - - if (data->power_state) { - val = i2c_smbus_write_byte_data(tpa6130a2_client, reg, value); - if (val < 0) { - dev_err(&tpa6130a2_client->dev, "Write failed\n"); - return val; - } - } - - /* Either powered on or off, we save the context */ - data->regs[reg] = value; - - return val; -} - -static u8 tpa6130a2_read(int reg) -{ - struct tpa6130a2_data *data; - - if (WARN_ON(!tpa6130a2_client)) - return 0; - data = i2c_get_clientdata(tpa6130a2_client); - - return data->regs[reg]; -} - -static int tpa6130a2_initialize(void) -{ - struct tpa6130a2_data *data; - int i, ret = 0; - - if (WARN_ON(!tpa6130a2_client)) - return -EINVAL; - data = i2c_get_clientdata(tpa6130a2_client); - - for (i = 1; i < TPA6130A2_REG_VERSION; i++) { - ret = tpa6130a2_i2c_write(i, data->regs[i]); - if (ret < 0) - break; - } - - return ret; -} - static int tpa6130a2_power(u8 power) { struct tpa6130a2_data *data; - u8 val; int ret = 0;
if (WARN_ON(!tpa6130a2_client)) @@ -153,7 +78,7 @@ static int tpa6130a2_power(u8 power) gpio_set_value(data->power_gpio, 1);
data->power_state = 1; - ret = tpa6130a2_initialize(); + ret = regcache_sync(data->regmap); if (ret < 0) { dev_err(&tpa6130a2_client->dev, "Failed to initialize chip\n"); @@ -165,9 +90,8 @@ static int tpa6130a2_power(u8 power) } } else { /* set SWS */ - val = tpa6130a2_read(TPA6130A2_REG_CONTROL); - val |= TPA6130A2_SWS; - tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val); + regmap_update_bits(data->regmap, TPA6130A2_REG_CONTROL, + TPA6130A2_SWS, TPA6130A2_SWS);
/* Power off */ if (data->power_gpio >= 0) @@ -181,6 +105,8 @@ static int tpa6130a2_power(u8 power) }
data->power_state = 0; + /* device regs does not match the cache state anymore */ + regcache_mark_dirty(data->regmap); }
exit: @@ -196,7 +122,7 @@ static int tpa6130a2_get_volsw(struct snd_kcontrol *kcontrol, struct tpa6130a2_data *data; unsigned int reg = mc->reg; unsigned int shift = mc->shift; - int max = mc->max; + int max = mc->max, val; unsigned int mask = (1 << fls(max)) - 1; unsigned int invert = mc->invert;
@@ -206,8 +132,8 @@ static int tpa6130a2_get_volsw(struct snd_kcontrol *kcontrol,
mutex_lock(&data->mutex);
- ucontrol->value.integer.value[0] = - (tpa6130a2_read(reg) >> shift) & mask; + regmap_read(data->regmap, reg, &val); + ucontrol->value.integer.value[0] = (val >> shift) & mask;
if (invert) ucontrol->value.integer.value[0] = @@ -229,7 +155,7 @@ static int tpa6130a2_put_volsw(struct snd_kcontrol *kcontrol, unsigned int mask = (1 << fls(max)) - 1; unsigned int invert = mc->invert; unsigned int val = (ucontrol->value.integer.value[0] & mask); - unsigned int val_reg; + bool change;
if (WARN_ON(!tpa6130a2_client)) return -EINVAL; @@ -239,20 +165,11 @@ static int tpa6130a2_put_volsw(struct snd_kcontrol *kcontrol, val = max - val;
mutex_lock(&data->mutex); - - val_reg = tpa6130a2_read(reg); - if (((val_reg >> shift) & mask) == val) { - mutex_unlock(&data->mutex); - return 0; - } - - val_reg &= ~(mask << shift); - val_reg |= val << shift; - tpa6130a2_i2c_write(reg, val_reg); - + regmap_update_bits_check(data->regmap, reg, mask << shift, val << shift, + &change); mutex_unlock(&data->mutex);
- return 1; + return change; }
/* @@ -301,31 +218,26 @@ static const struct snd_kcontrol_new tpa6140a2_controls[] = { */ static void tpa6130a2_channel_enable(u8 channel, int enable) { - u8 val; + struct tpa6130a2_data *data = i2c_get_clientdata(tpa6130a2_client);
if (enable) { /* Enable channel */ /* Enable amplifier */ - val = tpa6130a2_read(TPA6130A2_REG_CONTROL); - val |= channel; - val &= ~TPA6130A2_SWS; - tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val); + regmap_update_bits(data->regmap, TPA6130A2_REG_CONTROL, + channel | TPA6130A2_SWS, channel & ~TPA6130A2_SWS);
/* Unmute channel */ - val = tpa6130a2_read(TPA6130A2_REG_VOL_MUTE); - val &= ~channel; - tpa6130a2_i2c_write(TPA6130A2_REG_VOL_MUTE, val); + regmap_update_bits(data->regmap, TPA6130A2_REG_VOL_MUTE, + channel, 0); } else { /* Disable channel */ /* Mute channel */ - val = tpa6130a2_read(TPA6130A2_REG_VOL_MUTE); - val |= channel; - tpa6130a2_i2c_write(TPA6130A2_REG_VOL_MUTE, val); + regmap_update_bits(data->regmap, TPA6130A2_REG_VOL_MUTE, + channel, channel);
/* Disable amplifier */ - val = tpa6130a2_read(TPA6130A2_REG_CONTROL); - val &= ~channel; - tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val); + regmap_update_bits(data->regmap, TPA6130A2_REG_CONTROL, + channel, 0); } }
@@ -365,6 +277,20 @@ struct snd_soc_component_driver tpa6130a2_component_driver = { .probe = tpa6130a2_component_probe, };
+static const struct reg_default tpa6130a2_reg_defaults[] = { + { TPA6130A2_REG_CONTROL, TPA6130A2_SWS }, + { TPA6130A2_REG_VOL_MUTE, TPA6130A2_MUTE_R | TPA6130A2_MUTE_L }, +}; + +static const struct regmap_config tpa6130a2_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = TPA6130A2_REG_VERSION, + .reg_defaults = tpa6130a2_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(tpa6130a2_reg_defaults), + .cache_type = REGCACHE_RBTREE, +}; + static int tpa6130a2_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -373,6 +299,7 @@ static int tpa6130a2_probe(struct i2c_client *client, struct tpa6130a2_platform_data *pdata = client->dev.platform_data; struct device_node *np = client->dev.of_node; const char *regulator; + unsigned int version; int ret;
dev = &client->dev; @@ -381,6 +308,10 @@ static int tpa6130a2_probe(struct i2c_client *client, if (!data) return -ENOMEM;
+ data->regmap = devm_regmap_init_i2c(client, &tpa6130a2_regmap_config); + if (IS_ERR(data->regmap)) + return PTR_ERR(data->regmap); + if (pdata) { data->power_gpio = pdata->power_gpio; } else if (np) { @@ -399,11 +330,6 @@ static int tpa6130a2_probe(struct i2c_client *client,
mutex_init(&data->mutex);
- /* Set default register values */ - data->regs[TPA6130A2_REG_CONTROL] = TPA6130A2_SWS; - data->regs[TPA6130A2_REG_VOL_MUTE] = TPA6130A2_MUTE_R | - TPA6130A2_MUTE_L; - if (data->power_gpio >= 0) { ret = devm_gpio_request(dev, data->power_gpio, "tpa6130a2 enable"); @@ -440,10 +366,10 @@ static int tpa6130a2_probe(struct i2c_client *client,
/* Read version */ - ret = tpa6130a2_i2c_read(TPA6130A2_REG_VERSION) & - TPA6130A2_VERSION_MASK; - if ((ret != 1) && (ret != 2)) - dev_warn(dev, "UNTESTED version detected (%d)\n", ret); + regmap_read(data->regmap, TPA6130A2_REG_VERSION, &version); + version &= TPA6130A2_VERSION_MASK; + if ((version != 1) && (version != 2)) + dev_warn(dev, "UNTESTED version detected (%d)\n", version);
/* Disable the chip */ ret = tpa6130a2_power(0); diff --git a/sound/soc/codecs/tpa6130a2.h b/sound/soc/codecs/tpa6130a2.h index 78ee723..ef05a3f 100644 --- a/sound/soc/codecs/tpa6130a2.h +++ b/sound/soc/codecs/tpa6130a2.h @@ -30,8 +30,6 @@ #define TPA6130A2_REG_OUT_IMPEDANCE 0x03 #define TPA6130A2_REG_VERSION 0x04
-#define TPA6130A2_CACHEREGNUM (TPA6130A2_REG_VERSION + 1) - /* Register bits */ /* TPA6130A2_REG_CONTROL (0x01) */ #define TPA6130A2_SWS (0x01 << 0)
Hi,
On Mon, Jun 20, 2016 at 02:12:30PM -0300, Helen Koike wrote:
Use regmap instead of open-coding IO access and caching
Signed-off-by: Lars-Peter Clausen lars@metafoo.de [koike: port for upstream] Signed-off-by: Helen Koike helen.koike@collabora.co.uk [On N900] Tested-By: Sebastian Reichel sre@kernel.org
Reviewed-By: Sebastian Reichel sre@kernel.org
-- Sebastian
Use snd_soc_{info,get,put}_volsw instead of custom volume functions
Signed-off-by: Lars-Peter Clausen lars@metafoo.de [koike: port for upstream] Signed-off-by: Helen Koike helen.koike@collabora.co.uk [On N900] Tested-By: Sebastian Reichel sre@kernel.org
---
Changes since v1: - Add tested-by from Sebastian
sound/soc/codecs/tpa6130a2.c | 64 ++------------------------------------------ 1 file changed, 2 insertions(+), 62 deletions(-)
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index d90388a..81bf584 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c @@ -114,64 +114,6 @@ exit: return ret; }
-static int tpa6130a2_get_volsw(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - struct tpa6130a2_data *data; - unsigned int reg = mc->reg; - unsigned int shift = mc->shift; - int max = mc->max, val; - unsigned int mask = (1 << fls(max)) - 1; - unsigned int invert = mc->invert; - - if (WARN_ON(!tpa6130a2_client)) - return -EINVAL; - data = i2c_get_clientdata(tpa6130a2_client); - - mutex_lock(&data->mutex); - - regmap_read(data->regmap, reg, &val); - ucontrol->value.integer.value[0] = (val >> shift) & mask; - - if (invert) - ucontrol->value.integer.value[0] = - max - ucontrol->value.integer.value[0]; - - mutex_unlock(&data->mutex); - return 0; -} - -static int tpa6130a2_put_volsw(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - struct tpa6130a2_data *data; - unsigned int reg = mc->reg; - unsigned int shift = mc->shift; - int max = mc->max; - unsigned int mask = (1 << fls(max)) - 1; - unsigned int invert = mc->invert; - unsigned int val = (ucontrol->value.integer.value[0] & mask); - bool change; - - if (WARN_ON(!tpa6130a2_client)) - return -EINVAL; - data = i2c_get_clientdata(tpa6130a2_client); - - if (invert) - val = max - val; - - mutex_lock(&data->mutex); - regmap_update_bits_check(data->regmap, reg, mask << shift, val << shift, - &change); - mutex_unlock(&data->mutex); - - return change; -} - /* * TPA6130 volume. From -59.5 to 4 dB with increasing step size when going * down in gain. @@ -190,9 +132,8 @@ static const DECLARE_TLV_DB_RANGE(tpa6130_tlv, );
static const struct snd_kcontrol_new tpa6130a2_controls[] = { - SOC_SINGLE_EXT_TLV("Headphone Playback Volume", + SOC_SINGLE_TLV("Headphone Playback Volume", TPA6130A2_REG_VOL_MUTE, 0, 0x3f, 0, - tpa6130a2_get_volsw, tpa6130a2_put_volsw, tpa6130_tlv), };
@@ -203,9 +144,8 @@ static const DECLARE_TLV_DB_RANGE(tpa6140_tlv, );
static const struct snd_kcontrol_new tpa6140a2_controls[] = { - SOC_SINGLE_EXT_TLV("Headphone Playback Volume", + SOC_SINGLE_TLV("Headphone Playback Volume", TPA6130A2_REG_VOL_MUTE, 1, 0x1f, 0, - tpa6130a2_get_volsw, tpa6130a2_put_volsw, tpa6140_tlv), };
Hi,
On Mon, Jun 20, 2016 at 02:12:31PM -0300, Helen Koike wrote:
Use snd_soc_{info,get,put}_volsw instead of custom volume functions
Signed-off-by: Lars-Peter Clausen lars@metafoo.de [koike: port for upstream] Signed-off-by: Helen Koike helen.koike@collabora.co.uk [On N900] Tested-By: Sebastian Reichel sre@kernel.org
Reviewed-By: Sebastian Reichel sre@kernel.org
-- Sebastian
The patch
ASoC: tpa6130a2: Use snd soc volsw functions
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From e01d700c399d8d899850a1e5fad5227a9d976304 Mon Sep 17 00:00:00 2001
From: Helen Koike helen.koike@collabora.co.uk Date: Mon, 20 Jun 2016 14:12:31 -0300 Subject: [PATCH] ASoC: tpa6130a2: Use snd soc volsw functions
Use snd_soc_{info,get,put}_volsw instead of custom volume functions
Signed-off-by: Lars-Peter Clausen lars@metafoo.de [koike: port for upstream] Signed-off-by: Helen Koike helen.koike@collabora.co.uk [On N900] Tested-By: Sebastian Reichel sre@kernel.org Reviewed-By: Sebastian Reichel sre@kernel.org Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/codecs/tpa6130a2.c | 64 ++------------------------------------------ 1 file changed, 2 insertions(+), 62 deletions(-)
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index d90388a38903..81bf5848b743 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c @@ -114,64 +114,6 @@ exit: return ret; }
-static int tpa6130a2_get_volsw(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - struct tpa6130a2_data *data; - unsigned int reg = mc->reg; - unsigned int shift = mc->shift; - int max = mc->max, val; - unsigned int mask = (1 << fls(max)) - 1; - unsigned int invert = mc->invert; - - if (WARN_ON(!tpa6130a2_client)) - return -EINVAL; - data = i2c_get_clientdata(tpa6130a2_client); - - mutex_lock(&data->mutex); - - regmap_read(data->regmap, reg, &val); - ucontrol->value.integer.value[0] = (val >> shift) & mask; - - if (invert) - ucontrol->value.integer.value[0] = - max - ucontrol->value.integer.value[0]; - - mutex_unlock(&data->mutex); - return 0; -} - -static int tpa6130a2_put_volsw(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - struct tpa6130a2_data *data; - unsigned int reg = mc->reg; - unsigned int shift = mc->shift; - int max = mc->max; - unsigned int mask = (1 << fls(max)) - 1; - unsigned int invert = mc->invert; - unsigned int val = (ucontrol->value.integer.value[0] & mask); - bool change; - - if (WARN_ON(!tpa6130a2_client)) - return -EINVAL; - data = i2c_get_clientdata(tpa6130a2_client); - - if (invert) - val = max - val; - - mutex_lock(&data->mutex); - regmap_update_bits_check(data->regmap, reg, mask << shift, val << shift, - &change); - mutex_unlock(&data->mutex); - - return change; -} - /* * TPA6130 volume. From -59.5 to 4 dB with increasing step size when going * down in gain. @@ -190,9 +132,8 @@ static const DECLARE_TLV_DB_RANGE(tpa6130_tlv, );
static const struct snd_kcontrol_new tpa6130a2_controls[] = { - SOC_SINGLE_EXT_TLV("Headphone Playback Volume", + SOC_SINGLE_TLV("Headphone Playback Volume", TPA6130A2_REG_VOL_MUTE, 0, 0x3f, 0, - tpa6130a2_get_volsw, tpa6130a2_put_volsw, tpa6130_tlv), };
@@ -203,9 +144,8 @@ static const DECLARE_TLV_DB_RANGE(tpa6140_tlv, );
static const struct snd_kcontrol_new tpa6140a2_controls[] = { - SOC_SINGLE_EXT_TLV("Headphone Playback Volume", + SOC_SINGLE_TLV("Headphone Playback Volume", TPA6130A2_REG_VOL_MUTE, 1, 0x1f, 0, - tpa6130a2_get_volsw, tpa6130a2_put_volsw, tpa6140_tlv), };
Add DAPM support and updated rx51 accordingly. As a consequence: - the exported function tpa6130a2_stereo_enable is not needed anymore - the mutex is dealt in the DAPM - the power state is tracked by the DAPM
Signed-off-by: Lars-Peter Clausen lars@metafoo.de [koike: port for upstream] Signed-off-by: Helen Koike helen.koike@collabora.co.uk Tested-By: Sebastian Reichel sre@kernel.org Reviewed-By: Sebastian Reichel sre@kernel.org
---
Changes since v1: - Replace + {"TPA6130A2 HPLEFT", NULL, "LLOUT"}, + {"TPA6130A2 HPRIGHT", NULL, "RLOUT"}
by
+ {"TPA6130A2 LEFTIN", NULL, "LLOUT"}, + {"TPA6130A2 RIGHTIN", NULL, "RLOUT"}, - Add tested-by and reviewed-by from Sebastian - Add struct device dev* in struct tpa6130a2_data and pass data instead of dev to tpa6130a2_power function - remove #include "../codecs/tpa6130a2.h" in rx51.c
sound/soc/codecs/tpa6130a2.c | 184 ++++++++++++++++++------------------------- sound/soc/codecs/tpa6130a2.h | 11 +-- sound/soc/omap/rx51.c | 23 ++---- 3 files changed, 88 insertions(+), 130 deletions(-)
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index 81bf584..cc83870 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c @@ -41,79 +41,73 @@ enum tpa_model { TPA6140A2, };
-static struct i2c_client *tpa6130a2_client; - /* This struct is used to save the context */ struct tpa6130a2_data { - struct mutex mutex; + struct device *dev; struct regmap *regmap; struct regulator *supply; int power_gpio; - u8 power_state:1; enum tpa_model id; };
-static int tpa6130a2_power(u8 power) +static int tpa6130a2_power(struct tpa6130a2_data *data, bool enable) { - struct tpa6130a2_data *data; - int ret = 0; - - if (WARN_ON(!tpa6130a2_client)) - return -EINVAL; - data = i2c_get_clientdata(tpa6130a2_client); - - mutex_lock(&data->mutex); - if (power == data->power_state) - goto exit; + int ret;
- if (power) { + if (enable) { ret = regulator_enable(data->supply); if (ret != 0) { - dev_err(&tpa6130a2_client->dev, + dev_err(data->dev, "Failed to enable supply: %d\n", ret); - goto exit; + return ret; } /* Power on */ if (data->power_gpio >= 0) gpio_set_value(data->power_gpio, 1); - - data->power_state = 1; - ret = regcache_sync(data->regmap); - if (ret < 0) { - dev_err(&tpa6130a2_client->dev, - "Failed to initialize chip\n"); - if (data->power_gpio >= 0) - gpio_set_value(data->power_gpio, 0); - regulator_disable(data->supply); - data->power_state = 0; - goto exit; - } } else { - /* set SWS */ - regmap_update_bits(data->regmap, TPA6130A2_REG_CONTROL, - TPA6130A2_SWS, TPA6130A2_SWS); - /* Power off */ if (data->power_gpio >= 0) gpio_set_value(data->power_gpio, 0);
ret = regulator_disable(data->supply); if (ret != 0) { - dev_err(&tpa6130a2_client->dev, + dev_err(data->dev, "Failed to disable supply: %d\n", ret); - goto exit; + return ret; }
- data->power_state = 0; /* device regs does not match the cache state anymore */ regcache_mark_dirty(data->regmap); }
-exit: - mutex_unlock(&data->mutex); return ret; }
+static int tpa6130a2_power_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kctrl, int event) +{ + struct snd_soc_component *c = snd_soc_dapm_to_component(w->dapm); + struct tpa6130a2_data *data = snd_soc_component_get_drvdata(c); + int ret; + + /* before widget power up */ + if (SND_SOC_DAPM_EVENT_ON(event)) { + /* Turn on the chip */ + tpa6130a2_power(data, true); + /* Sync the registers */ + ret = regcache_sync(data->regmap); + if (ret < 0) { + dev_err(c->dev, "Failed to initialize chip\n"); + tpa6130a2_power(data, false); + return ret; + } + /* after widget power down */ + } else + tpa6130a2_power(data, false); + + return 0; +} + /* * TPA6130 volume. From -59.5 to 4 dB with increasing step size when going * down in gain. @@ -149,57 +143,6 @@ static const struct snd_kcontrol_new tpa6140a2_controls[] = { tpa6140_tlv), };
-/* - * Enable or disable channel (left or right) - * The bit number for mute and amplifier are the same per channel: - * bit 6: Right channel - * bit 7: Left channel - * in both registers. - */ -static void tpa6130a2_channel_enable(u8 channel, int enable) -{ - struct tpa6130a2_data *data = i2c_get_clientdata(tpa6130a2_client); - - if (enable) { - /* Enable channel */ - /* Enable amplifier */ - regmap_update_bits(data->regmap, TPA6130A2_REG_CONTROL, - channel | TPA6130A2_SWS, channel & ~TPA6130A2_SWS); - - /* Unmute channel */ - regmap_update_bits(data->regmap, TPA6130A2_REG_VOL_MUTE, - channel, 0); - } else { - /* Disable channel */ - /* Mute channel */ - regmap_update_bits(data->regmap, TPA6130A2_REG_VOL_MUTE, - channel, channel); - - /* Disable amplifier */ - regmap_update_bits(data->regmap, TPA6130A2_REG_CONTROL, - channel, 0); - } -} - -int tpa6130a2_stereo_enable(struct snd_soc_codec *codec, int enable) -{ - int ret = 0; - if (enable) { - ret = tpa6130a2_power(1); - if (ret < 0) - return ret; - tpa6130a2_channel_enable(TPA6130A2_HP_EN_R | TPA6130A2_HP_EN_L, - 1); - } else { - tpa6130a2_channel_enable(TPA6130A2_HP_EN_R | TPA6130A2_HP_EN_L, - 0); - ret = tpa6130a2_power(0); - } - - return ret; -} -EXPORT_SYMBOL_GPL(tpa6130a2_stereo_enable); - static int tpa6130a2_component_probe(struct snd_soc_component *component) { struct tpa6130a2_data *data = snd_soc_component_get_drvdata(component); @@ -212,9 +155,47 @@ static int tpa6130a2_component_probe(struct snd_soc_component *component) tpa6130a2_controls, ARRAY_SIZE(tpa6130a2_controls)); }
+static const struct snd_soc_dapm_widget tpa6130a2_dapm_widgets[] = { + SND_SOC_DAPM_INPUT("LEFTIN"), + SND_SOC_DAPM_INPUT("RIGHTIN"), + SND_SOC_DAPM_OUTPUT("HPLEFT"), + SND_SOC_DAPM_OUTPUT("HPRIGHT"), + + SND_SOC_DAPM_PGA("Left Mute", TPA6130A2_REG_VOL_MUTE, + TPA6130A2_HP_EN_L_SHIFT, 1, NULL, 0), + SND_SOC_DAPM_PGA("Right Mute", TPA6130A2_REG_VOL_MUTE, + TPA6130A2_HP_EN_R_SHIFT, 1, NULL, 0), + SND_SOC_DAPM_PGA("Left PGA", TPA6130A2_REG_CONTROL, + TPA6130A2_HP_EN_L_SHIFT, 0, NULL, 0), + SND_SOC_DAPM_PGA("Right PGA", TPA6130A2_REG_CONTROL, + TPA6130A2_HP_EN_R_SHIFT, 0, NULL, 0), + + SND_SOC_DAPM_SUPPLY("Power", TPA6130A2_REG_CONTROL, + TPA6130A2_SWS_SHIFT, 1, tpa6130a2_power_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +}; + +static const struct snd_soc_dapm_route tpa6130a2_dapm_routes[] = { + { "Left PGA", NULL, "LEFTIN" }, + { "Right PGA", NULL, "RIGHTIN" }, + + { "Left Mute", NULL, "Left PGA" }, + { "Right Mute", NULL, "Right PGA" }, + + { "HPLEFT", NULL, "Left Mute" }, + { "HPRIGHT", NULL, "Right Mute" }, + + { "Left PGA", NULL, "Power" }, + { "Right PGA", NULL, "Power" }, +}; + struct snd_soc_component_driver tpa6130a2_component_driver = { .name = "tpa6130a2", .probe = tpa6130a2_component_probe, + .dapm_widgets = tpa6130a2_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(tpa6130a2_dapm_widgets), + .dapm_routes = tpa6130a2_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(tpa6130a2_dapm_routes), };
static const struct reg_default tpa6130a2_reg_defaults[] = { @@ -248,6 +229,8 @@ static int tpa6130a2_probe(struct i2c_client *client, if (!data) return -ENOMEM;
+ data->dev = dev; + data->regmap = devm_regmap_init_i2c(client, &tpa6130a2_regmap_config); if (IS_ERR(data->regmap)) return PTR_ERR(data->regmap); @@ -262,14 +245,10 @@ static int tpa6130a2_probe(struct i2c_client *client, return -ENODEV; }
- tpa6130a2_client = client; - - i2c_set_clientdata(tpa6130a2_client, data); + i2c_set_clientdata(client, data);
data->id = id->driver_data;
- mutex_init(&data->mutex); - if (data->power_gpio >= 0) { ret = devm_gpio_request(dev, data->power_gpio, "tpa6130a2 enable"); @@ -300,7 +279,7 @@ static int tpa6130a2_probe(struct i2c_client *client, goto err_gpio; }
- ret = tpa6130a2_power(1); + ret = tpa6130a2_power(data, true); if (ret != 0) goto err_gpio;
@@ -312,7 +291,7 @@ static int tpa6130a2_probe(struct i2c_client *client, dev_warn(dev, "UNTESTED version detected (%d)\n", version);
/* Disable the chip */ - ret = tpa6130a2_power(0); + ret = tpa6130a2_power(data, false); if (ret != 0) goto err_gpio;
@@ -320,19 +299,9 @@ static int tpa6130a2_probe(struct i2c_client *client, &tpa6130a2_component_driver, NULL, 0);
err_gpio: - tpa6130a2_client = NULL; - return ret; }
-static int tpa6130a2_remove(struct i2c_client *client) -{ - tpa6130a2_power(0); - tpa6130a2_client = NULL; - - return 0; -} - static const struct i2c_device_id tpa6130a2_id[] = { { "tpa6130a2", TPA6130A2 }, { "tpa6140a2", TPA6140A2 }, @@ -355,7 +324,6 @@ static struct i2c_driver tpa6130a2_i2c_driver = { .of_match_table = of_match_ptr(tpa6130a2_of_match), }, .probe = tpa6130a2_probe, - .remove = tpa6130a2_remove, .id_table = tpa6130a2_id, };
diff --git a/sound/soc/codecs/tpa6130a2.h b/sound/soc/codecs/tpa6130a2.h index ef05a3f..f19cad5 100644 --- a/sound/soc/codecs/tpa6130a2.h +++ b/sound/soc/codecs/tpa6130a2.h @@ -32,15 +32,18 @@
/* Register bits */ /* TPA6130A2_REG_CONTROL (0x01) */ -#define TPA6130A2_SWS (0x01 << 0) +#define TPA6130A2_SWS_SHIFT 0 +#define TPA6130A2_SWS (0x01 << TPA6130A2_SWS_SHIFT) #define TPA6130A2_TERMAL (0x01 << 1) #define TPA6130A2_MODE(x) (x << 4) #define TPA6130A2_MODE_STEREO (0x00) #define TPA6130A2_MODE_DUAL_MONO (0x01) #define TPA6130A2_MODE_BRIDGE (0x02) #define TPA6130A2_MODE_MASK (0x03) -#define TPA6130A2_HP_EN_R (0x01 << 6) -#define TPA6130A2_HP_EN_L (0x01 << 7) +#define TPA6130A2_HP_EN_R_SHIFT 6 +#define TPA6130A2_HP_EN_R (0x01 << TPA6130A2_HP_EN_R_SHIFT) +#define TPA6130A2_HP_EN_L_SHIFT 7 +#define TPA6130A2_HP_EN_L (0x01 << TPA6130A2_HP_EN_L_SHIFT)
/* TPA6130A2_REG_VOL_MUTE (0x02) */ #define TPA6130A2_VOLUME(x) ((x & 0x3f) << 0) @@ -54,6 +57,4 @@ /* TPA6130A2_REG_VERSION (0x04) */ #define TPA6130A2_VERSION_MASK (0x0f)
-extern int tpa6130a2_stereo_enable(struct snd_soc_codec *codec, int enable); - #endif /* __TPA6130A2_H__ */ diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c index b59cf89..a768457 100644 --- a/sound/soc/omap/rx51.c +++ b/sound/soc/omap/rx51.c @@ -33,7 +33,6 @@ #include <sound/pcm.h> #include <sound/soc.h> #include <linux/platform_data/asoc-ti-mcbsp.h> -#include "../codecs/tpa6130a2.h"
#include <asm/mach-types.h>
@@ -164,19 +163,6 @@ static int rx51_spk_event(struct snd_soc_dapm_widget *w, return 0; }
-static int rx51_hp_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *k, int event) -{ - struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); - - if (SND_SOC_DAPM_EVENT_ON(event)) - tpa6130a2_stereo_enable(codec, 1); - else - tpa6130a2_stereo_enable(codec, 0); - - return 0; -} - static int rx51_get_input(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -235,7 +221,7 @@ static struct snd_soc_jack_gpio rx51_av_jack_gpios[] = { static const struct snd_soc_dapm_widget aic34_dapm_widgets[] = { SND_SOC_DAPM_SPK("Ext Spk", rx51_spk_event), SND_SOC_DAPM_MIC("DMic", NULL), - SND_SOC_DAPM_HP("Headphone Jack", rx51_hp_event), + SND_SOC_DAPM_HP("Headphone Jack", NULL), SND_SOC_DAPM_MIC("HS Mic", NULL), SND_SOC_DAPM_LINE("FM Transmitter", NULL), SND_SOC_DAPM_SPK("Earphone", NULL), @@ -246,11 +232,14 @@ static const struct snd_soc_dapm_route audio_map[] = { {"Ext Spk", NULL, "HPROUT"}, {"Ext Spk", NULL, "HPLCOM"}, {"Ext Spk", NULL, "HPRCOM"}, - {"Headphone Jack", NULL, "LLOUT"}, - {"Headphone Jack", NULL, "RLOUT"}, {"FM Transmitter", NULL, "LLOUT"}, {"FM Transmitter", NULL, "RLOUT"},
+ {"Headphone Jack", NULL, "TPA6130A2 HPLEFT"}, + {"Headphone Jack", NULL, "TPA6130A2 HPRIGHT"}, + {"TPA6130A2 LEFTIN", NULL, "LLOUT"}, + {"TPA6130A2 RIGHTIN", NULL, "RLOUT"}, + {"DMic Rate 64", NULL, "DMic"}, {"DMic", NULL, "Mic Bias"},
Hi Sebastian,
Thank you for reviewing the patches.
On 20-06-2016 14:12, Helen Koike wrote:
Add DAPM support and updated rx51 accordingly. As a consequence:
- the exported function tpa6130a2_stereo_enable is not needed anymore
- the mutex is dealt in the DAPM
- the power state is tracked by the DAPM
Signed-off-by: Lars-Peter Clausen lars@metafoo.de [koike: port for upstream] Signed-off-by: Helen Koike helen.koike@collabora.co.uk Tested-By: Sebastian Reichel sre@kernel.org Reviewed-By: Sebastian Reichel sre@kernel.org
Changes since v1:
Replace
- {"TPA6130A2 HPLEFT", NULL, "LLOUT"},
- {"TPA6130A2 HPRIGHT", NULL, "RLOUT"}
by
{"TPA6130A2 LEFTIN", NULL, "LLOUT"},
{"TPA6130A2 RIGHTIN", NULL, "RLOUT"},
Add tested-by and reviewed-by from Sebastian
Add struct device dev* in struct tpa6130a2_data and pass data instead
of dev to tpa6130a2_power function
- remove #include "../codecs/tpa6130a2.h" in rx51.c
I added these changes above and kept your tested-by and reviewed-by, could you please confirm that I can keep them? As I changed more things then you suggested.
Thank you Helen
sound/soc/codecs/tpa6130a2.c | 184 ++++++++++++++++++------------------------- sound/soc/codecs/tpa6130a2.h | 11 +-- sound/soc/omap/rx51.c | 23 ++---- 3 files changed, 88 insertions(+), 130 deletions(-)
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index 81bf584..cc83870 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c @@ -41,79 +41,73 @@ enum tpa_model { TPA6140A2, };
-static struct i2c_client *tpa6130a2_client;
- /* This struct is used to save the context */ struct tpa6130a2_data {
- struct mutex mutex;
- struct device *dev; struct regmap *regmap; struct regulator *supply; int power_gpio;
- u8 power_state:1; enum tpa_model id; };
-static int tpa6130a2_power(u8 power) +static int tpa6130a2_power(struct tpa6130a2_data *data, bool enable) {
- struct tpa6130a2_data *data;
- int ret = 0;
- if (WARN_ON(!tpa6130a2_client))
return -EINVAL;
- data = i2c_get_clientdata(tpa6130a2_client);
- mutex_lock(&data->mutex);
- if (power == data->power_state)
goto exit;
- int ret;
- if (power) {
- if (enable) { ret = regulator_enable(data->supply); if (ret != 0) {
dev_err(&tpa6130a2_client->dev,
dev_err(data->dev, "Failed to enable supply: %d\n", ret);
goto exit;
} /* Power on */ if (data->power_gpio >= 0) gpio_set_value(data->power_gpio, 1);return ret;
data->power_state = 1;
ret = regcache_sync(data->regmap);
if (ret < 0) {
dev_err(&tpa6130a2_client->dev,
"Failed to initialize chip\n");
if (data->power_gpio >= 0)
gpio_set_value(data->power_gpio, 0);
regulator_disable(data->supply);
data->power_state = 0;
goto exit;
}
} else {
/* set SWS */
regmap_update_bits(data->regmap, TPA6130A2_REG_CONTROL,
TPA6130A2_SWS, TPA6130A2_SWS);
/* Power off */ if (data->power_gpio >= 0) gpio_set_value(data->power_gpio, 0);
ret = regulator_disable(data->supply); if (ret != 0) {
dev_err(&tpa6130a2_client->dev,
dev_err(data->dev, "Failed to disable supply: %d\n", ret);
goto exit;
}return ret;
/* device regs does not match the cache state anymore */ regcache_mark_dirty(data->regmap); }data->power_state = 0;
-exit:
- mutex_unlock(&data->mutex); return ret; }
+static int tpa6130a2_power_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kctrl, int event)
+{
- struct snd_soc_component *c = snd_soc_dapm_to_component(w->dapm);
- struct tpa6130a2_data *data = snd_soc_component_get_drvdata(c);
- int ret;
- /* before widget power up */
- if (SND_SOC_DAPM_EVENT_ON(event)) {
/* Turn on the chip */
tpa6130a2_power(data, true);
/* Sync the registers */
ret = regcache_sync(data->regmap);
if (ret < 0) {
dev_err(c->dev, "Failed to initialize chip\n");
tpa6130a2_power(data, false);
return ret;
}
- /* after widget power down */
- } else
tpa6130a2_power(data, false);
- return 0;
+}
- /*
- TPA6130 volume. From -59.5 to 4 dB with increasing step size when going
- down in gain.
@@ -149,57 +143,6 @@ static const struct snd_kcontrol_new tpa6140a2_controls[] = { tpa6140_tlv), };
-/*
- Enable or disable channel (left or right)
- The bit number for mute and amplifier are the same per channel:
- bit 6: Right channel
- bit 7: Left channel
- in both registers.
- */
-static void tpa6130a2_channel_enable(u8 channel, int enable) -{
- struct tpa6130a2_data *data = i2c_get_clientdata(tpa6130a2_client);
- if (enable) {
/* Enable channel */
/* Enable amplifier */
regmap_update_bits(data->regmap, TPA6130A2_REG_CONTROL,
channel | TPA6130A2_SWS, channel & ~TPA6130A2_SWS);
/* Unmute channel */
regmap_update_bits(data->regmap, TPA6130A2_REG_VOL_MUTE,
channel, 0);
- } else {
/* Disable channel */
/* Mute channel */
regmap_update_bits(data->regmap, TPA6130A2_REG_VOL_MUTE,
channel, channel);
/* Disable amplifier */
regmap_update_bits(data->regmap, TPA6130A2_REG_CONTROL,
channel, 0);
- }
-}
-int tpa6130a2_stereo_enable(struct snd_soc_codec *codec, int enable) -{
- int ret = 0;
- if (enable) {
ret = tpa6130a2_power(1);
if (ret < 0)
return ret;
tpa6130a2_channel_enable(TPA6130A2_HP_EN_R | TPA6130A2_HP_EN_L,
1);
- } else {
tpa6130a2_channel_enable(TPA6130A2_HP_EN_R | TPA6130A2_HP_EN_L,
0);
ret = tpa6130a2_power(0);
- }
- return ret;
-} -EXPORT_SYMBOL_GPL(tpa6130a2_stereo_enable);
- static int tpa6130a2_component_probe(struct snd_soc_component *component) { struct tpa6130a2_data *data = snd_soc_component_get_drvdata(component);
@@ -212,9 +155,47 @@ static int tpa6130a2_component_probe(struct snd_soc_component *component) tpa6130a2_controls, ARRAY_SIZE(tpa6130a2_controls)); }
+static const struct snd_soc_dapm_widget tpa6130a2_dapm_widgets[] = {
- SND_SOC_DAPM_INPUT("LEFTIN"),
- SND_SOC_DAPM_INPUT("RIGHTIN"),
- SND_SOC_DAPM_OUTPUT("HPLEFT"),
- SND_SOC_DAPM_OUTPUT("HPRIGHT"),
- SND_SOC_DAPM_PGA("Left Mute", TPA6130A2_REG_VOL_MUTE,
TPA6130A2_HP_EN_L_SHIFT, 1, NULL, 0),
- SND_SOC_DAPM_PGA("Right Mute", TPA6130A2_REG_VOL_MUTE,
TPA6130A2_HP_EN_R_SHIFT, 1, NULL, 0),
- SND_SOC_DAPM_PGA("Left PGA", TPA6130A2_REG_CONTROL,
TPA6130A2_HP_EN_L_SHIFT, 0, NULL, 0),
- SND_SOC_DAPM_PGA("Right PGA", TPA6130A2_REG_CONTROL,
TPA6130A2_HP_EN_R_SHIFT, 0, NULL, 0),
- SND_SOC_DAPM_SUPPLY("Power", TPA6130A2_REG_CONTROL,
TPA6130A2_SWS_SHIFT, 1, tpa6130a2_power_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+};
+static const struct snd_soc_dapm_route tpa6130a2_dapm_routes[] = {
- { "Left PGA", NULL, "LEFTIN" },
- { "Right PGA", NULL, "RIGHTIN" },
- { "Left Mute", NULL, "Left PGA" },
- { "Right Mute", NULL, "Right PGA" },
- { "HPLEFT", NULL, "Left Mute" },
- { "HPRIGHT", NULL, "Right Mute" },
- { "Left PGA", NULL, "Power" },
- { "Right PGA", NULL, "Power" },
+};
struct snd_soc_component_driver tpa6130a2_component_driver = { .name = "tpa6130a2", .probe = tpa6130a2_component_probe,
.dapm_widgets = tpa6130a2_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(tpa6130a2_dapm_widgets),
.dapm_routes = tpa6130a2_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(tpa6130a2_dapm_routes), };
static const struct reg_default tpa6130a2_reg_defaults[] = {
@@ -248,6 +229,8 @@ static int tpa6130a2_probe(struct i2c_client *client, if (!data) return -ENOMEM;
- data->dev = dev;
- data->regmap = devm_regmap_init_i2c(client, &tpa6130a2_regmap_config); if (IS_ERR(data->regmap)) return PTR_ERR(data->regmap);
@@ -262,14 +245,10 @@ static int tpa6130a2_probe(struct i2c_client *client, return -ENODEV; }
- tpa6130a2_client = client;
- i2c_set_clientdata(tpa6130a2_client, data);
i2c_set_clientdata(client, data);
data->id = id->driver_data;
- mutex_init(&data->mutex);
- if (data->power_gpio >= 0) { ret = devm_gpio_request(dev, data->power_gpio, "tpa6130a2 enable");
@@ -300,7 +279,7 @@ static int tpa6130a2_probe(struct i2c_client *client, goto err_gpio; }
- ret = tpa6130a2_power(1);
- ret = tpa6130a2_power(data, true); if (ret != 0) goto err_gpio;
@@ -312,7 +291,7 @@ static int tpa6130a2_probe(struct i2c_client *client, dev_warn(dev, "UNTESTED version detected (%d)\n", version);
/* Disable the chip */
- ret = tpa6130a2_power(0);
- ret = tpa6130a2_power(data, false); if (ret != 0) goto err_gpio;
@@ -320,19 +299,9 @@ static int tpa6130a2_probe(struct i2c_client *client, &tpa6130a2_component_driver, NULL, 0);
err_gpio:
- tpa6130a2_client = NULL;
- return ret; }
-static int tpa6130a2_remove(struct i2c_client *client) -{
- tpa6130a2_power(0);
- tpa6130a2_client = NULL;
- return 0;
-}
- static const struct i2c_device_id tpa6130a2_id[] = { { "tpa6130a2", TPA6130A2 }, { "tpa6140a2", TPA6140A2 },
@@ -355,7 +324,6 @@ static struct i2c_driver tpa6130a2_i2c_driver = { .of_match_table = of_match_ptr(tpa6130a2_of_match), }, .probe = tpa6130a2_probe,
- .remove = tpa6130a2_remove, .id_table = tpa6130a2_id, };
diff --git a/sound/soc/codecs/tpa6130a2.h b/sound/soc/codecs/tpa6130a2.h index ef05a3f..f19cad5 100644 --- a/sound/soc/codecs/tpa6130a2.h +++ b/sound/soc/codecs/tpa6130a2.h @@ -32,15 +32,18 @@
/* Register bits */ /* TPA6130A2_REG_CONTROL (0x01) */ -#define TPA6130A2_SWS (0x01 << 0) +#define TPA6130A2_SWS_SHIFT 0 +#define TPA6130A2_SWS (0x01 << TPA6130A2_SWS_SHIFT) #define TPA6130A2_TERMAL (0x01 << 1) #define TPA6130A2_MODE(x) (x << 4) #define TPA6130A2_MODE_STEREO (0x00) #define TPA6130A2_MODE_DUAL_MONO (0x01) #define TPA6130A2_MODE_BRIDGE (0x02) #define TPA6130A2_MODE_MASK (0x03) -#define TPA6130A2_HP_EN_R (0x01 << 6) -#define TPA6130A2_HP_EN_L (0x01 << 7) +#define TPA6130A2_HP_EN_R_SHIFT 6 +#define TPA6130A2_HP_EN_R (0x01 << TPA6130A2_HP_EN_R_SHIFT) +#define TPA6130A2_HP_EN_L_SHIFT 7 +#define TPA6130A2_HP_EN_L (0x01 << TPA6130A2_HP_EN_L_SHIFT)
/* TPA6130A2_REG_VOL_MUTE (0x02) */ #define TPA6130A2_VOLUME(x) ((x & 0x3f) << 0) @@ -54,6 +57,4 @@ /* TPA6130A2_REG_VERSION (0x04) */ #define TPA6130A2_VERSION_MASK (0x0f)
-extern int tpa6130a2_stereo_enable(struct snd_soc_codec *codec, int enable);
- #endif /* __TPA6130A2_H__ */
diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c index b59cf89..a768457 100644 --- a/sound/soc/omap/rx51.c +++ b/sound/soc/omap/rx51.c @@ -33,7 +33,6 @@ #include <sound/pcm.h> #include <sound/soc.h> #include <linux/platform_data/asoc-ti-mcbsp.h> -#include "../codecs/tpa6130a2.h"
#include <asm/mach-types.h>
@@ -164,19 +163,6 @@ static int rx51_spk_event(struct snd_soc_dapm_widget *w, return 0; }
-static int rx51_hp_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int event)
-{
- struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
- if (SND_SOC_DAPM_EVENT_ON(event))
tpa6130a2_stereo_enable(codec, 1);
- else
tpa6130a2_stereo_enable(codec, 0);
- return 0;
-}
- static int rx51_get_input(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
@@ -235,7 +221,7 @@ static struct snd_soc_jack_gpio rx51_av_jack_gpios[] = { static const struct snd_soc_dapm_widget aic34_dapm_widgets[] = { SND_SOC_DAPM_SPK("Ext Spk", rx51_spk_event), SND_SOC_DAPM_MIC("DMic", NULL),
- SND_SOC_DAPM_HP("Headphone Jack", rx51_hp_event),
- SND_SOC_DAPM_HP("Headphone Jack", NULL), SND_SOC_DAPM_MIC("HS Mic", NULL), SND_SOC_DAPM_LINE("FM Transmitter", NULL), SND_SOC_DAPM_SPK("Earphone", NULL),
@@ -246,11 +232,14 @@ static const struct snd_soc_dapm_route audio_map[] = { {"Ext Spk", NULL, "HPROUT"}, {"Ext Spk", NULL, "HPLCOM"}, {"Ext Spk", NULL, "HPRCOM"},
- {"Headphone Jack", NULL, "LLOUT"},
- {"Headphone Jack", NULL, "RLOUT"}, {"FM Transmitter", NULL, "LLOUT"}, {"FM Transmitter", NULL, "RLOUT"},
- {"Headphone Jack", NULL, "TPA6130A2 HPLEFT"},
- {"Headphone Jack", NULL, "TPA6130A2 HPRIGHT"},
- {"TPA6130A2 LEFTIN", NULL, "LLOUT"},
- {"TPA6130A2 RIGHTIN", NULL, "RLOUT"},
- {"DMic Rate 64", NULL, "DMic"}, {"DMic", NULL, "Mic Bias"},
Hi Helen,
On Mon, Jun 20, 2016 at 04:06:10PM -0300, Helen Koike wrote:
I added these changes above and kept your tested-by and reviewed-by, could you please confirm that I can keep them? As I changed more things then you suggested.
The changes look fine to me, the new patchset works on N900.
-- Sebastian
- /* before widget power up */
- if (SND_SOC_DAPM_EVENT_ON(event)) {
/* Turn on the chip */
tpa6130a2_power(data, true);
/* Sync the registers */
ret = regcache_sync(data->regmap);
if (ret < 0) {
dev_err(c->dev, "Failed to initialize chip\n");
tpa6130a2_power(data, false);
return ret;
}
- /* after widget power down */
- } else
tpa6130a2_power(data, false);
checkpatch.pl should complain about this. Kernel code style is if one branch has branches the other has to have it as well.
On 20-06-2016 16:44, Lars-Peter Clausen wrote:
- /* before widget power up */
- if (SND_SOC_DAPM_EVENT_ON(event)) {
/* Turn on the chip */
tpa6130a2_power(data, true);
/* Sync the registers */
ret = regcache_sync(data->regmap);
if (ret < 0) {
dev_err(c->dev, "Failed to initialize chip\n");
tpa6130a2_power(data, false);
return ret;
}
- /* after widget power down */
- } else
tpa6130a2_power(data, false);
checkpatch.pl should complain about this. Kernel code style is if one branch has branches the other has to have it as well.
Weird, checkpatch.pl doesn't complain. I'll add the braces in v3, thank you for reviewing
Replace goto err_gpio by return ret
Signed-off-by: Helen Koike helen.koike@collabora.co.uk
---
Changes since v1: - this is a new patch in the series
sound/soc/codecs/tpa6130a2.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index cc83870..a919308 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c @@ -255,7 +255,7 @@ static int tpa6130a2_probe(struct i2c_client *client, if (ret < 0) { dev_err(dev, "Failed to request power GPIO (%d)\n", data->power_gpio); - goto err_gpio; + return ret; } gpio_direction_output(data->power_gpio, 0); } @@ -276,12 +276,12 @@ static int tpa6130a2_probe(struct i2c_client *client, if (IS_ERR(data->supply)) { ret = PTR_ERR(data->supply); dev_err(dev, "Failed to request supply: %d\n", ret); - goto err_gpio; + return ret; }
ret = tpa6130a2_power(data, true); if (ret != 0) - goto err_gpio; + return ret;
/* Read version */ @@ -293,13 +293,10 @@ static int tpa6130a2_probe(struct i2c_client *client, /* Disable the chip */ ret = tpa6130a2_power(data, false); if (ret != 0) - goto err_gpio; + return ret;
return devm_snd_soc_register_component(&client->dev, &tpa6130a2_component_driver, NULL, 0); - -err_gpio: - return ret; }
static const struct i2c_device_id tpa6130a2_id[] = {
Hi,
On Mon, Jun 20, 2016 at 02:12:33PM -0300, Helen Koike wrote:
Replace goto err_gpio by return ret
Signed-off-by: Helen Koike helen.koike@collabora.co.uk
Tested-By: Sebastian Reichel sre@kernel.org Reviewed-By: Sebastian Reichel sre@kernel.org
-- Sebastian
The patch
ASoC: tpa6130a2: Remove goto err_gpio
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From 39088c251c69d3b7b288e30228aed06e1d339da5 Mon Sep 17 00:00:00 2001
From: Helen Koike helen.koike@collabora.co.uk Date: Thu, 23 Jun 2016 16:23:14 -0300 Subject: [PATCH] ASoC: tpa6130a2: Remove goto err_gpio
Replace goto err_gpio by return ret
Signed-off-by: Helen Koike helen.koike@collabora.co.uk Tested-by: Sebastian Reichel sre@kernel.org Reviewed-by: Sebastian Reichel sre@kernel.org Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/codecs/tpa6130a2.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index 9da1dd12f839..f1ea052a822e 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c @@ -256,7 +256,7 @@ static int tpa6130a2_probe(struct i2c_client *client, if (ret < 0) { dev_err(dev, "Failed to request power GPIO (%d)\n", data->power_gpio); - goto err_gpio; + return ret; } gpio_direction_output(data->power_gpio, 0); } @@ -277,12 +277,12 @@ static int tpa6130a2_probe(struct i2c_client *client, if (IS_ERR(data->supply)) { ret = PTR_ERR(data->supply); dev_err(dev, "Failed to request supply: %d\n", ret); - goto err_gpio; + return ret; }
ret = tpa6130a2_power(data, true); if (ret != 0) - goto err_gpio; + return ret;
/* Read version */ @@ -294,13 +294,10 @@ static int tpa6130a2_probe(struct i2c_client *client, /* Disable the chip */ ret = tpa6130a2_power(data, false); if (ret != 0) - goto err_gpio; + return ret;
return devm_snd_soc_register_component(&client->dev, &tpa6130a2_component_driver, NULL, 0); - -err_gpio: - return ret; }
static const struct i2c_device_id tpa6130a2_id[] = {
The current tpa6130a2 driver supports only a single instance. This patch series add support for multiple instances by removing the global variable that holds the instance. This is performed by using the component API, regmap, the snd_soc_{info,put,get}_volsw API and DAPM.
The first 3 pathes of this series were already applied, these two are missing
This patch series is based on git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next Available at https://git.collabora.com/cgit/user/koike/linux.git/log/?h=sound/review/tpa6...
Helen Koike (2): ASoC: tpa6130a2: Add DAPM support ASoC: tpa6130a2: Remove goto err_gpio
sound/soc/codecs/tpa6130a2.c | 196 ++++++++++++++++++------------------------- sound/soc/codecs/tpa6130a2.h | 11 +-- sound/soc/omap/rx51.c | 23 ++--- 3 files changed, 93 insertions(+), 137 deletions(-)
Changes since v2: ASoC: tpa6130a2: Add DAPM support - Add braces around else statement in tpa6130a2_power_event ASoC: tpa6130a2: Remove goto err_gpio - Add tested-by and reviewed-by from Sebastian
Add DAPM support and updated rx51 accordingly. As a consequence: - the exported function tpa6130a2_stereo_enable is not needed anymore - the mutex is dealt in the DAPM - the power state is tracked by the DAPM
Signed-off-by: Lars-Peter Clausen lars@metafoo.de [koike: port for upstream] Signed-off-by: Helen Koike helen.koike@collabora.co.uk Tested-by: Sebastian Reichel sre@kernel.org Reviewed-by: Sebastian Reichel sre@kernel.org
--- Changes since v1: - Replace + {"TPA6130A2 HPLEFT", NULL, "LLOUT"}, + {"TPA6130A2 HPRIGHT", NULL, "RLOUT"}
by
+ {"TPA6130A2 LEFTIN", NULL, "LLOUT"}, + {"TPA6130A2 RIGHTIN", NULL, "RLOUT"}, - Add tested-by and reviewed-by from Sebastian - Add struct device dev* in struct tpa6130a2_data and pass data instead of dev to tpa6130a2_power function - remove #include "../codecs/tpa6130a2.h" in rx51.c
Changes since v2: - Add braces around else statement in tpa6130a2_power_event
sound/soc/codecs/tpa6130a2.c | 185 ++++++++++++++++++------------------------- sound/soc/codecs/tpa6130a2.h | 11 +-- sound/soc/omap/rx51.c | 23 ++---- 3 files changed, 89 insertions(+), 130 deletions(-)
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index 81bf584..9da1dd1 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c @@ -41,79 +41,74 @@ enum tpa_model { TPA6140A2, };
-static struct i2c_client *tpa6130a2_client; - /* This struct is used to save the context */ struct tpa6130a2_data { - struct mutex mutex; + struct device *dev; struct regmap *regmap; struct regulator *supply; int power_gpio; - u8 power_state:1; enum tpa_model id; };
-static int tpa6130a2_power(u8 power) +static int tpa6130a2_power(struct tpa6130a2_data *data, bool enable) { - struct tpa6130a2_data *data; - int ret = 0; - - if (WARN_ON(!tpa6130a2_client)) - return -EINVAL; - data = i2c_get_clientdata(tpa6130a2_client); - - mutex_lock(&data->mutex); - if (power == data->power_state) - goto exit; + int ret;
- if (power) { + if (enable) { ret = regulator_enable(data->supply); if (ret != 0) { - dev_err(&tpa6130a2_client->dev, + dev_err(data->dev, "Failed to enable supply: %d\n", ret); - goto exit; + return ret; } /* Power on */ if (data->power_gpio >= 0) gpio_set_value(data->power_gpio, 1); - - data->power_state = 1; - ret = regcache_sync(data->regmap); - if (ret < 0) { - dev_err(&tpa6130a2_client->dev, - "Failed to initialize chip\n"); - if (data->power_gpio >= 0) - gpio_set_value(data->power_gpio, 0); - regulator_disable(data->supply); - data->power_state = 0; - goto exit; - } } else { - /* set SWS */ - regmap_update_bits(data->regmap, TPA6130A2_REG_CONTROL, - TPA6130A2_SWS, TPA6130A2_SWS); - /* Power off */ if (data->power_gpio >= 0) gpio_set_value(data->power_gpio, 0);
ret = regulator_disable(data->supply); if (ret != 0) { - dev_err(&tpa6130a2_client->dev, + dev_err(data->dev, "Failed to disable supply: %d\n", ret); - goto exit; + return ret; }
- data->power_state = 0; /* device regs does not match the cache state anymore */ regcache_mark_dirty(data->regmap); }
-exit: - mutex_unlock(&data->mutex); return ret; }
+static int tpa6130a2_power_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kctrl, int event) +{ + struct snd_soc_component *c = snd_soc_dapm_to_component(w->dapm); + struct tpa6130a2_data *data = snd_soc_component_get_drvdata(c); + int ret; + + /* before widget power up */ + if (SND_SOC_DAPM_EVENT_ON(event)) { + /* Turn on the chip */ + tpa6130a2_power(data, true); + /* Sync the registers */ + ret = regcache_sync(data->regmap); + if (ret < 0) { + dev_err(c->dev, "Failed to initialize chip\n"); + tpa6130a2_power(data, false); + return ret; + } + /* after widget power down */ + } else { + tpa6130a2_power(data, false); + } + + return 0; +} + /* * TPA6130 volume. From -59.5 to 4 dB with increasing step size when going * down in gain. @@ -149,57 +144,6 @@ static const struct snd_kcontrol_new tpa6140a2_controls[] = { tpa6140_tlv), };
-/* - * Enable or disable channel (left or right) - * The bit number for mute and amplifier are the same per channel: - * bit 6: Right channel - * bit 7: Left channel - * in both registers. - */ -static void tpa6130a2_channel_enable(u8 channel, int enable) -{ - struct tpa6130a2_data *data = i2c_get_clientdata(tpa6130a2_client); - - if (enable) { - /* Enable channel */ - /* Enable amplifier */ - regmap_update_bits(data->regmap, TPA6130A2_REG_CONTROL, - channel | TPA6130A2_SWS, channel & ~TPA6130A2_SWS); - - /* Unmute channel */ - regmap_update_bits(data->regmap, TPA6130A2_REG_VOL_MUTE, - channel, 0); - } else { - /* Disable channel */ - /* Mute channel */ - regmap_update_bits(data->regmap, TPA6130A2_REG_VOL_MUTE, - channel, channel); - - /* Disable amplifier */ - regmap_update_bits(data->regmap, TPA6130A2_REG_CONTROL, - channel, 0); - } -} - -int tpa6130a2_stereo_enable(struct snd_soc_codec *codec, int enable) -{ - int ret = 0; - if (enable) { - ret = tpa6130a2_power(1); - if (ret < 0) - return ret; - tpa6130a2_channel_enable(TPA6130A2_HP_EN_R | TPA6130A2_HP_EN_L, - 1); - } else { - tpa6130a2_channel_enable(TPA6130A2_HP_EN_R | TPA6130A2_HP_EN_L, - 0); - ret = tpa6130a2_power(0); - } - - return ret; -} -EXPORT_SYMBOL_GPL(tpa6130a2_stereo_enable); - static int tpa6130a2_component_probe(struct snd_soc_component *component) { struct tpa6130a2_data *data = snd_soc_component_get_drvdata(component); @@ -212,9 +156,47 @@ static int tpa6130a2_component_probe(struct snd_soc_component *component) tpa6130a2_controls, ARRAY_SIZE(tpa6130a2_controls)); }
+static const struct snd_soc_dapm_widget tpa6130a2_dapm_widgets[] = { + SND_SOC_DAPM_INPUT("LEFTIN"), + SND_SOC_DAPM_INPUT("RIGHTIN"), + SND_SOC_DAPM_OUTPUT("HPLEFT"), + SND_SOC_DAPM_OUTPUT("HPRIGHT"), + + SND_SOC_DAPM_PGA("Left Mute", TPA6130A2_REG_VOL_MUTE, + TPA6130A2_HP_EN_L_SHIFT, 1, NULL, 0), + SND_SOC_DAPM_PGA("Right Mute", TPA6130A2_REG_VOL_MUTE, + TPA6130A2_HP_EN_R_SHIFT, 1, NULL, 0), + SND_SOC_DAPM_PGA("Left PGA", TPA6130A2_REG_CONTROL, + TPA6130A2_HP_EN_L_SHIFT, 0, NULL, 0), + SND_SOC_DAPM_PGA("Right PGA", TPA6130A2_REG_CONTROL, + TPA6130A2_HP_EN_R_SHIFT, 0, NULL, 0), + + SND_SOC_DAPM_SUPPLY("Power", TPA6130A2_REG_CONTROL, + TPA6130A2_SWS_SHIFT, 1, tpa6130a2_power_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +}; + +static const struct snd_soc_dapm_route tpa6130a2_dapm_routes[] = { + { "Left PGA", NULL, "LEFTIN" }, + { "Right PGA", NULL, "RIGHTIN" }, + + { "Left Mute", NULL, "Left PGA" }, + { "Right Mute", NULL, "Right PGA" }, + + { "HPLEFT", NULL, "Left Mute" }, + { "HPRIGHT", NULL, "Right Mute" }, + + { "Left PGA", NULL, "Power" }, + { "Right PGA", NULL, "Power" }, +}; + struct snd_soc_component_driver tpa6130a2_component_driver = { .name = "tpa6130a2", .probe = tpa6130a2_component_probe, + .dapm_widgets = tpa6130a2_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(tpa6130a2_dapm_widgets), + .dapm_routes = tpa6130a2_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(tpa6130a2_dapm_routes), };
static const struct reg_default tpa6130a2_reg_defaults[] = { @@ -248,6 +230,8 @@ static int tpa6130a2_probe(struct i2c_client *client, if (!data) return -ENOMEM;
+ data->dev = dev; + data->regmap = devm_regmap_init_i2c(client, &tpa6130a2_regmap_config); if (IS_ERR(data->regmap)) return PTR_ERR(data->regmap); @@ -262,14 +246,10 @@ static int tpa6130a2_probe(struct i2c_client *client, return -ENODEV; }
- tpa6130a2_client = client; - - i2c_set_clientdata(tpa6130a2_client, data); + i2c_set_clientdata(client, data);
data->id = id->driver_data;
- mutex_init(&data->mutex); - if (data->power_gpio >= 0) { ret = devm_gpio_request(dev, data->power_gpio, "tpa6130a2 enable"); @@ -300,7 +280,7 @@ static int tpa6130a2_probe(struct i2c_client *client, goto err_gpio; }
- ret = tpa6130a2_power(1); + ret = tpa6130a2_power(data, true); if (ret != 0) goto err_gpio;
@@ -312,7 +292,7 @@ static int tpa6130a2_probe(struct i2c_client *client, dev_warn(dev, "UNTESTED version detected (%d)\n", version);
/* Disable the chip */ - ret = tpa6130a2_power(0); + ret = tpa6130a2_power(data, false); if (ret != 0) goto err_gpio;
@@ -320,19 +300,9 @@ static int tpa6130a2_probe(struct i2c_client *client, &tpa6130a2_component_driver, NULL, 0);
err_gpio: - tpa6130a2_client = NULL; - return ret; }
-static int tpa6130a2_remove(struct i2c_client *client) -{ - tpa6130a2_power(0); - tpa6130a2_client = NULL; - - return 0; -} - static const struct i2c_device_id tpa6130a2_id[] = { { "tpa6130a2", TPA6130A2 }, { "tpa6140a2", TPA6140A2 }, @@ -355,7 +325,6 @@ static struct i2c_driver tpa6130a2_i2c_driver = { .of_match_table = of_match_ptr(tpa6130a2_of_match), }, .probe = tpa6130a2_probe, - .remove = tpa6130a2_remove, .id_table = tpa6130a2_id, };
diff --git a/sound/soc/codecs/tpa6130a2.h b/sound/soc/codecs/tpa6130a2.h index ef05a3f..f19cad5 100644 --- a/sound/soc/codecs/tpa6130a2.h +++ b/sound/soc/codecs/tpa6130a2.h @@ -32,15 +32,18 @@
/* Register bits */ /* TPA6130A2_REG_CONTROL (0x01) */ -#define TPA6130A2_SWS (0x01 << 0) +#define TPA6130A2_SWS_SHIFT 0 +#define TPA6130A2_SWS (0x01 << TPA6130A2_SWS_SHIFT) #define TPA6130A2_TERMAL (0x01 << 1) #define TPA6130A2_MODE(x) (x << 4) #define TPA6130A2_MODE_STEREO (0x00) #define TPA6130A2_MODE_DUAL_MONO (0x01) #define TPA6130A2_MODE_BRIDGE (0x02) #define TPA6130A2_MODE_MASK (0x03) -#define TPA6130A2_HP_EN_R (0x01 << 6) -#define TPA6130A2_HP_EN_L (0x01 << 7) +#define TPA6130A2_HP_EN_R_SHIFT 6 +#define TPA6130A2_HP_EN_R (0x01 << TPA6130A2_HP_EN_R_SHIFT) +#define TPA6130A2_HP_EN_L_SHIFT 7 +#define TPA6130A2_HP_EN_L (0x01 << TPA6130A2_HP_EN_L_SHIFT)
/* TPA6130A2_REG_VOL_MUTE (0x02) */ #define TPA6130A2_VOLUME(x) ((x & 0x3f) << 0) @@ -54,6 +57,4 @@ /* TPA6130A2_REG_VERSION (0x04) */ #define TPA6130A2_VERSION_MASK (0x0f)
-extern int tpa6130a2_stereo_enable(struct snd_soc_codec *codec, int enable); - #endif /* __TPA6130A2_H__ */ diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c index b59cf89..a768457 100644 --- a/sound/soc/omap/rx51.c +++ b/sound/soc/omap/rx51.c @@ -33,7 +33,6 @@ #include <sound/pcm.h> #include <sound/soc.h> #include <linux/platform_data/asoc-ti-mcbsp.h> -#include "../codecs/tpa6130a2.h"
#include <asm/mach-types.h>
@@ -164,19 +163,6 @@ static int rx51_spk_event(struct snd_soc_dapm_widget *w, return 0; }
-static int rx51_hp_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *k, int event) -{ - struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); - - if (SND_SOC_DAPM_EVENT_ON(event)) - tpa6130a2_stereo_enable(codec, 1); - else - tpa6130a2_stereo_enable(codec, 0); - - return 0; -} - static int rx51_get_input(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -235,7 +221,7 @@ static struct snd_soc_jack_gpio rx51_av_jack_gpios[] = { static const struct snd_soc_dapm_widget aic34_dapm_widgets[] = { SND_SOC_DAPM_SPK("Ext Spk", rx51_spk_event), SND_SOC_DAPM_MIC("DMic", NULL), - SND_SOC_DAPM_HP("Headphone Jack", rx51_hp_event), + SND_SOC_DAPM_HP("Headphone Jack", NULL), SND_SOC_DAPM_MIC("HS Mic", NULL), SND_SOC_DAPM_LINE("FM Transmitter", NULL), SND_SOC_DAPM_SPK("Earphone", NULL), @@ -246,11 +232,14 @@ static const struct snd_soc_dapm_route audio_map[] = { {"Ext Spk", NULL, "HPROUT"}, {"Ext Spk", NULL, "HPLCOM"}, {"Ext Spk", NULL, "HPRCOM"}, - {"Headphone Jack", NULL, "LLOUT"}, - {"Headphone Jack", NULL, "RLOUT"}, {"FM Transmitter", NULL, "LLOUT"}, {"FM Transmitter", NULL, "RLOUT"},
+ {"Headphone Jack", NULL, "TPA6130A2 HPLEFT"}, + {"Headphone Jack", NULL, "TPA6130A2 HPRIGHT"}, + {"TPA6130A2 LEFTIN", NULL, "LLOUT"}, + {"TPA6130A2 RIGHTIN", NULL, "RLOUT"}, + {"DMic Rate 64", NULL, "DMic"}, {"DMic", NULL, "Mic Bias"},
The patch
ASoC: tpa6130a2: Add DAPM support
has been applied to the asoc tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From 6d2de5ab4328718302c54b20222c6b1a574c3fce Mon Sep 17 00:00:00 2001
From: Helen Koike helen.koike@collabora.co.uk Date: Thu, 23 Jun 2016 16:23:13 -0300 Subject: [PATCH] ASoC: tpa6130a2: Add DAPM support
Add DAPM support and updated rx51 accordingly. As a consequence: - the exported function tpa6130a2_stereo_enable is not needed anymore - the mutex is dealt in the DAPM - the power state is tracked by the DAPM
Signed-off-by: Lars-Peter Clausen lars@metafoo.de [koike: port for upstream] Signed-off-by: Helen Koike helen.koike@collabora.co.uk Tested-by: Sebastian Reichel sre@kernel.org Reviewed-by: Sebastian Reichel sre@kernel.org Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/codecs/tpa6130a2.c | 185 ++++++++++++++++++------------------------- sound/soc/codecs/tpa6130a2.h | 11 +-- sound/soc/omap/rx51.c | 23 ++---- 3 files changed, 89 insertions(+), 130 deletions(-)
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index 81bf5848b743..9da1dd12f839 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c @@ -41,79 +41,74 @@ enum tpa_model { TPA6140A2, };
-static struct i2c_client *tpa6130a2_client; - /* This struct is used to save the context */ struct tpa6130a2_data { - struct mutex mutex; + struct device *dev; struct regmap *regmap; struct regulator *supply; int power_gpio; - u8 power_state:1; enum tpa_model id; };
-static int tpa6130a2_power(u8 power) +static int tpa6130a2_power(struct tpa6130a2_data *data, bool enable) { - struct tpa6130a2_data *data; - int ret = 0; - - if (WARN_ON(!tpa6130a2_client)) - return -EINVAL; - data = i2c_get_clientdata(tpa6130a2_client); - - mutex_lock(&data->mutex); - if (power == data->power_state) - goto exit; + int ret;
- if (power) { + if (enable) { ret = regulator_enable(data->supply); if (ret != 0) { - dev_err(&tpa6130a2_client->dev, + dev_err(data->dev, "Failed to enable supply: %d\n", ret); - goto exit; + return ret; } /* Power on */ if (data->power_gpio >= 0) gpio_set_value(data->power_gpio, 1); - - data->power_state = 1; - ret = regcache_sync(data->regmap); - if (ret < 0) { - dev_err(&tpa6130a2_client->dev, - "Failed to initialize chip\n"); - if (data->power_gpio >= 0) - gpio_set_value(data->power_gpio, 0); - regulator_disable(data->supply); - data->power_state = 0; - goto exit; - } } else { - /* set SWS */ - regmap_update_bits(data->regmap, TPA6130A2_REG_CONTROL, - TPA6130A2_SWS, TPA6130A2_SWS); - /* Power off */ if (data->power_gpio >= 0) gpio_set_value(data->power_gpio, 0);
ret = regulator_disable(data->supply); if (ret != 0) { - dev_err(&tpa6130a2_client->dev, + dev_err(data->dev, "Failed to disable supply: %d\n", ret); - goto exit; + return ret; }
- data->power_state = 0; /* device regs does not match the cache state anymore */ regcache_mark_dirty(data->regmap); }
-exit: - mutex_unlock(&data->mutex); return ret; }
+static int tpa6130a2_power_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kctrl, int event) +{ + struct snd_soc_component *c = snd_soc_dapm_to_component(w->dapm); + struct tpa6130a2_data *data = snd_soc_component_get_drvdata(c); + int ret; + + /* before widget power up */ + if (SND_SOC_DAPM_EVENT_ON(event)) { + /* Turn on the chip */ + tpa6130a2_power(data, true); + /* Sync the registers */ + ret = regcache_sync(data->regmap); + if (ret < 0) { + dev_err(c->dev, "Failed to initialize chip\n"); + tpa6130a2_power(data, false); + return ret; + } + /* after widget power down */ + } else { + tpa6130a2_power(data, false); + } + + return 0; +} + /* * TPA6130 volume. From -59.5 to 4 dB with increasing step size when going * down in gain. @@ -149,57 +144,6 @@ static const struct snd_kcontrol_new tpa6140a2_controls[] = { tpa6140_tlv), };
-/* - * Enable or disable channel (left or right) - * The bit number for mute and amplifier are the same per channel: - * bit 6: Right channel - * bit 7: Left channel - * in both registers. - */ -static void tpa6130a2_channel_enable(u8 channel, int enable) -{ - struct tpa6130a2_data *data = i2c_get_clientdata(tpa6130a2_client); - - if (enable) { - /* Enable channel */ - /* Enable amplifier */ - regmap_update_bits(data->regmap, TPA6130A2_REG_CONTROL, - channel | TPA6130A2_SWS, channel & ~TPA6130A2_SWS); - - /* Unmute channel */ - regmap_update_bits(data->regmap, TPA6130A2_REG_VOL_MUTE, - channel, 0); - } else { - /* Disable channel */ - /* Mute channel */ - regmap_update_bits(data->regmap, TPA6130A2_REG_VOL_MUTE, - channel, channel); - - /* Disable amplifier */ - regmap_update_bits(data->regmap, TPA6130A2_REG_CONTROL, - channel, 0); - } -} - -int tpa6130a2_stereo_enable(struct snd_soc_codec *codec, int enable) -{ - int ret = 0; - if (enable) { - ret = tpa6130a2_power(1); - if (ret < 0) - return ret; - tpa6130a2_channel_enable(TPA6130A2_HP_EN_R | TPA6130A2_HP_EN_L, - 1); - } else { - tpa6130a2_channel_enable(TPA6130A2_HP_EN_R | TPA6130A2_HP_EN_L, - 0); - ret = tpa6130a2_power(0); - } - - return ret; -} -EXPORT_SYMBOL_GPL(tpa6130a2_stereo_enable); - static int tpa6130a2_component_probe(struct snd_soc_component *component) { struct tpa6130a2_data *data = snd_soc_component_get_drvdata(component); @@ -212,9 +156,47 @@ static int tpa6130a2_component_probe(struct snd_soc_component *component) tpa6130a2_controls, ARRAY_SIZE(tpa6130a2_controls)); }
+static const struct snd_soc_dapm_widget tpa6130a2_dapm_widgets[] = { + SND_SOC_DAPM_INPUT("LEFTIN"), + SND_SOC_DAPM_INPUT("RIGHTIN"), + SND_SOC_DAPM_OUTPUT("HPLEFT"), + SND_SOC_DAPM_OUTPUT("HPRIGHT"), + + SND_SOC_DAPM_PGA("Left Mute", TPA6130A2_REG_VOL_MUTE, + TPA6130A2_HP_EN_L_SHIFT, 1, NULL, 0), + SND_SOC_DAPM_PGA("Right Mute", TPA6130A2_REG_VOL_MUTE, + TPA6130A2_HP_EN_R_SHIFT, 1, NULL, 0), + SND_SOC_DAPM_PGA("Left PGA", TPA6130A2_REG_CONTROL, + TPA6130A2_HP_EN_L_SHIFT, 0, NULL, 0), + SND_SOC_DAPM_PGA("Right PGA", TPA6130A2_REG_CONTROL, + TPA6130A2_HP_EN_R_SHIFT, 0, NULL, 0), + + SND_SOC_DAPM_SUPPLY("Power", TPA6130A2_REG_CONTROL, + TPA6130A2_SWS_SHIFT, 1, tpa6130a2_power_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +}; + +static const struct snd_soc_dapm_route tpa6130a2_dapm_routes[] = { + { "Left PGA", NULL, "LEFTIN" }, + { "Right PGA", NULL, "RIGHTIN" }, + + { "Left Mute", NULL, "Left PGA" }, + { "Right Mute", NULL, "Right PGA" }, + + { "HPLEFT", NULL, "Left Mute" }, + { "HPRIGHT", NULL, "Right Mute" }, + + { "Left PGA", NULL, "Power" }, + { "Right PGA", NULL, "Power" }, +}; + struct snd_soc_component_driver tpa6130a2_component_driver = { .name = "tpa6130a2", .probe = tpa6130a2_component_probe, + .dapm_widgets = tpa6130a2_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(tpa6130a2_dapm_widgets), + .dapm_routes = tpa6130a2_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(tpa6130a2_dapm_routes), };
static const struct reg_default tpa6130a2_reg_defaults[] = { @@ -248,6 +230,8 @@ static int tpa6130a2_probe(struct i2c_client *client, if (!data) return -ENOMEM;
+ data->dev = dev; + data->regmap = devm_regmap_init_i2c(client, &tpa6130a2_regmap_config); if (IS_ERR(data->regmap)) return PTR_ERR(data->regmap); @@ -262,14 +246,10 @@ static int tpa6130a2_probe(struct i2c_client *client, return -ENODEV; }
- tpa6130a2_client = client; - - i2c_set_clientdata(tpa6130a2_client, data); + i2c_set_clientdata(client, data);
data->id = id->driver_data;
- mutex_init(&data->mutex); - if (data->power_gpio >= 0) { ret = devm_gpio_request(dev, data->power_gpio, "tpa6130a2 enable"); @@ -300,7 +280,7 @@ static int tpa6130a2_probe(struct i2c_client *client, goto err_gpio; }
- ret = tpa6130a2_power(1); + ret = tpa6130a2_power(data, true); if (ret != 0) goto err_gpio;
@@ -312,7 +292,7 @@ static int tpa6130a2_probe(struct i2c_client *client, dev_warn(dev, "UNTESTED version detected (%d)\n", version);
/* Disable the chip */ - ret = tpa6130a2_power(0); + ret = tpa6130a2_power(data, false); if (ret != 0) goto err_gpio;
@@ -320,19 +300,9 @@ static int tpa6130a2_probe(struct i2c_client *client, &tpa6130a2_component_driver, NULL, 0);
err_gpio: - tpa6130a2_client = NULL; - return ret; }
-static int tpa6130a2_remove(struct i2c_client *client) -{ - tpa6130a2_power(0); - tpa6130a2_client = NULL; - - return 0; -} - static const struct i2c_device_id tpa6130a2_id[] = { { "tpa6130a2", TPA6130A2 }, { "tpa6140a2", TPA6140A2 }, @@ -355,7 +325,6 @@ static struct i2c_driver tpa6130a2_i2c_driver = { .of_match_table = of_match_ptr(tpa6130a2_of_match), }, .probe = tpa6130a2_probe, - .remove = tpa6130a2_remove, .id_table = tpa6130a2_id, };
diff --git a/sound/soc/codecs/tpa6130a2.h b/sound/soc/codecs/tpa6130a2.h index ef05a3ff189b..f19cad5d4172 100644 --- a/sound/soc/codecs/tpa6130a2.h +++ b/sound/soc/codecs/tpa6130a2.h @@ -32,15 +32,18 @@
/* Register bits */ /* TPA6130A2_REG_CONTROL (0x01) */ -#define TPA6130A2_SWS (0x01 << 0) +#define TPA6130A2_SWS_SHIFT 0 +#define TPA6130A2_SWS (0x01 << TPA6130A2_SWS_SHIFT) #define TPA6130A2_TERMAL (0x01 << 1) #define TPA6130A2_MODE(x) (x << 4) #define TPA6130A2_MODE_STEREO (0x00) #define TPA6130A2_MODE_DUAL_MONO (0x01) #define TPA6130A2_MODE_BRIDGE (0x02) #define TPA6130A2_MODE_MASK (0x03) -#define TPA6130A2_HP_EN_R (0x01 << 6) -#define TPA6130A2_HP_EN_L (0x01 << 7) +#define TPA6130A2_HP_EN_R_SHIFT 6 +#define TPA6130A2_HP_EN_R (0x01 << TPA6130A2_HP_EN_R_SHIFT) +#define TPA6130A2_HP_EN_L_SHIFT 7 +#define TPA6130A2_HP_EN_L (0x01 << TPA6130A2_HP_EN_L_SHIFT)
/* TPA6130A2_REG_VOL_MUTE (0x02) */ #define TPA6130A2_VOLUME(x) ((x & 0x3f) << 0) @@ -54,6 +57,4 @@ /* TPA6130A2_REG_VERSION (0x04) */ #define TPA6130A2_VERSION_MASK (0x0f)
-extern int tpa6130a2_stereo_enable(struct snd_soc_codec *codec, int enable); - #endif /* __TPA6130A2_H__ */ diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c index b59cf89c5cab..a76845748a10 100644 --- a/sound/soc/omap/rx51.c +++ b/sound/soc/omap/rx51.c @@ -33,7 +33,6 @@ #include <sound/pcm.h> #include <sound/soc.h> #include <linux/platform_data/asoc-ti-mcbsp.h> -#include "../codecs/tpa6130a2.h"
#include <asm/mach-types.h>
@@ -164,19 +163,6 @@ static int rx51_spk_event(struct snd_soc_dapm_widget *w, return 0; }
-static int rx51_hp_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *k, int event) -{ - struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); - - if (SND_SOC_DAPM_EVENT_ON(event)) - tpa6130a2_stereo_enable(codec, 1); - else - tpa6130a2_stereo_enable(codec, 0); - - return 0; -} - static int rx51_get_input(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -235,7 +221,7 @@ static struct snd_soc_jack_gpio rx51_av_jack_gpios[] = { static const struct snd_soc_dapm_widget aic34_dapm_widgets[] = { SND_SOC_DAPM_SPK("Ext Spk", rx51_spk_event), SND_SOC_DAPM_MIC("DMic", NULL), - SND_SOC_DAPM_HP("Headphone Jack", rx51_hp_event), + SND_SOC_DAPM_HP("Headphone Jack", NULL), SND_SOC_DAPM_MIC("HS Mic", NULL), SND_SOC_DAPM_LINE("FM Transmitter", NULL), SND_SOC_DAPM_SPK("Earphone", NULL), @@ -246,11 +232,14 @@ static const struct snd_soc_dapm_route audio_map[] = { {"Ext Spk", NULL, "HPROUT"}, {"Ext Spk", NULL, "HPLCOM"}, {"Ext Spk", NULL, "HPRCOM"}, - {"Headphone Jack", NULL, "LLOUT"}, - {"Headphone Jack", NULL, "RLOUT"}, {"FM Transmitter", NULL, "LLOUT"}, {"FM Transmitter", NULL, "RLOUT"},
+ {"Headphone Jack", NULL, "TPA6130A2 HPLEFT"}, + {"Headphone Jack", NULL, "TPA6130A2 HPRIGHT"}, + {"TPA6130A2 LEFTIN", NULL, "LLOUT"}, + {"TPA6130A2 RIGHTIN", NULL, "RLOUT"}, + {"DMic Rate 64", NULL, "DMic"}, {"DMic", NULL, "Mic Bias"},
Replace goto err_gpio by return ret
Signed-off-by: Helen Koike helen.koike@collabora.co.uk Tested-by: Sebastian Reichel sre@kernel.org Reviewed-by: Sebastian Reichel sre@kernel.org
--- Changes since v1: - this is a new patch in the series
Changes since v2: - Add tested-by and reviewed-by from Sebastian
sound/soc/codecs/tpa6130a2.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index 9da1dd1..f1ea052 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c @@ -256,7 +256,7 @@ static int tpa6130a2_probe(struct i2c_client *client, if (ret < 0) { dev_err(dev, "Failed to request power GPIO (%d)\n", data->power_gpio); - goto err_gpio; + return ret; } gpio_direction_output(data->power_gpio, 0); } @@ -277,12 +277,12 @@ static int tpa6130a2_probe(struct i2c_client *client, if (IS_ERR(data->supply)) { ret = PTR_ERR(data->supply); dev_err(dev, "Failed to request supply: %d\n", ret); - goto err_gpio; + return ret; }
ret = tpa6130a2_power(data, true); if (ret != 0) - goto err_gpio; + return ret;
/* Read version */ @@ -294,13 +294,10 @@ static int tpa6130a2_probe(struct i2c_client *client, /* Disable the chip */ ret = tpa6130a2_power(data, false); if (ret != 0) - goto err_gpio; + return ret;
return devm_snd_soc_register_component(&client->dev, &tpa6130a2_component_driver, NULL, 0); - -err_gpio: - return ret; }
static const struct i2c_device_id tpa6130a2_id[] = {
Hi,
On Sat, Jun 18, 2016 at 12:26:27AM -0300, Helen Koike wrote:
The current tpa6130a2 driver supports only a single instance. This patch series add support for multiple instances by removing the global variable that holds the instance. This is performed by using the component API, regmap, the snd_soc_{info,put,get}_volsw API and DAPM.
This patch series also touches code from the Nokia RX51 which I didn't tested (as I am testing the tpa6130a2 in another board that is not upstream). I would appreciate is if someone who possesses the Nokia RX51 (n900) could please test the code.
This patch series is based on git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next Available at https://git.collabora.com/cgit/user/koike/linux.git/log/?h=sound/review/tpa6...
Locking at the resulting tpa6130a2.c I suggest to add a patch removing the useless "goto err_gpio" in tpa6130a2_probe().
Also switching to gpiod_get() safes some more lines of code. It may make sense to postpone this to 4.9, though (this change involves removing the gpio from the platform data and the rx51 will become DT only in 4.8).
-- Sebastian
participants (5)
-
Helen Koike
-
Lars-Peter Clausen
-
Mark Brown
-
Peter Ujfalusi
-
Sebastian Reichel