From f227b88f0fce5f9b82aa934f8829a741c2e06d82 Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Thu, 16 Jan 2014 16:02:10 +0100 Subject: ASoC: core: Add signed register volume control logic Some codecs use signed volume control representation with non standard register sizes, e.g. 6 or 7 bit signed integers. This patch adds generic signed register volume control logic to soc-core. Instead of a fixed width signed register control, this implementation uses a 'min' value and the signed bit location to translate it to an absolute volume. Using the 'sign_bit' we can calculate a correct mask for the register values and translate it back into signed integers of standard size. Signed-off-by: Markus Pargmann Signed-off-by: Mark Brown --- include/sound/soc.h | 1 + sound/soc/soc-core.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 62 insertions(+), 7 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 9a001472b96a..a25f3ccb3fde 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1067,6 +1067,7 @@ struct soc_mixer_control { int min, max, platform_max; int reg, rreg; unsigned int shift, rshift; + unsigned int sign_bit; unsigned int invert:1; unsigned int autodisable:1; }; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index fe1df50805a3..c1d9d8539ee9 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2715,6 +2715,48 @@ int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol, } EXPORT_SYMBOL_GPL(snd_soc_put_value_enum_double); +/** + * snd_soc_read_signed - Read a codec register and interprete as signed value + * @codec: codec + * @reg: Register to read + * @mask: Mask to use after shifting the register value + * @shift: Right shift of register value + * @sign_bit: Bit that describes if a number is negative or not. + * + * This functions reads a codec register. The register value is shifted right + * by 'shift' bits and masked with the given 'mask'. Afterwards it translates + * the given registervalue into a signed integer if sign_bit is non-zero. + * + * Returns the register value as signed int. + */ +static int snd_soc_read_signed(struct snd_soc_codec *codec, unsigned int reg, + unsigned int mask, unsigned int shift, unsigned int sign_bit) +{ + int ret; + unsigned int val; + + val = (snd_soc_read(codec, reg) >> shift) & mask; + + if (!sign_bit) + return val; + + /* non-negative number */ + if (!(val & BIT(sign_bit))) + return val; + + ret = val; + + /* + * The register most probably does not contain a full-sized int. + * Instead we have an arbitrary number of bits in a signed + * representation which has to be translated into a full-sized int. + * This is done by filling up all bits above the sign-bit. + */ + ret |= ~((int)(BIT(sign_bit) - 1)); + + return ret; +} + /** * snd_soc_info_volsw - single mixer info callback * @kcontrol: mixer control @@ -2743,7 +2785,7 @@ int snd_soc_info_volsw(struct snd_kcontrol *kcontrol, uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1; uinfo->value.integer.min = 0; - uinfo->value.integer.max = platform_max; + uinfo->value.integer.max = platform_max - mc->min; return 0; } EXPORT_SYMBOL_GPL(snd_soc_info_volsw); @@ -2769,11 +2811,16 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, unsigned int shift = mc->shift; unsigned int rshift = mc->rshift; int max = mc->max; + int min = mc->min; + int sign_bit = mc->sign_bit; unsigned int mask = (1 << fls(max)) - 1; unsigned int invert = mc->invert; - ucontrol->value.integer.value[0] = - (snd_soc_read(codec, reg) >> shift) & mask; + if (sign_bit) + mask = BIT(sign_bit + 1) - 1; + + ucontrol->value.integer.value[0] = snd_soc_read_signed(codec, reg, mask, + shift, sign_bit) - min; if (invert) ucontrol->value.integer.value[0] = max - ucontrol->value.integer.value[0]; @@ -2781,10 +2828,12 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, if (snd_soc_volsw_is_stereo(mc)) { if (reg == reg2) ucontrol->value.integer.value[1] = - (snd_soc_read(codec, reg) >> rshift) & mask; + snd_soc_read_signed(codec, reg, mask, rshift, + sign_bit) - min; else ucontrol->value.integer.value[1] = - (snd_soc_read(codec, reg2) >> shift) & mask; + snd_soc_read_signed(codec, reg2, mask, shift, + sign_bit) - min; if (invert) ucontrol->value.integer.value[1] = max - ucontrol->value.integer.value[1]; @@ -2815,6 +2864,8 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, unsigned int shift = mc->shift; unsigned int rshift = mc->rshift; int max = mc->max; + int min = mc->min; + unsigned int sign_bit = mc->sign_bit; unsigned int mask = (1 << fls(max)) - 1; unsigned int invert = mc->invert; int err; @@ -2822,13 +2873,16 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, unsigned int val2 = 0; unsigned int val, val_mask; - val = (ucontrol->value.integer.value[0] & mask); + if (sign_bit) + mask = BIT(sign_bit + 1) - 1; + + val = ((ucontrol->value.integer.value[0] + min) & mask); if (invert) val = max - val; val_mask = mask << shift; val = val << shift; if (snd_soc_volsw_is_stereo(mc)) { - val2 = (ucontrol->value.integer.value[1] & mask); + val2 = ((ucontrol->value.integer.value[1] + min) & mask); if (invert) val2 = max - val2; if (reg == reg2) { -- cgit v1.2.3 From cd21b123346c6a2f033d8c3bd2bf240198b5712a Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Thu, 16 Jan 2014 16:02:11 +0100 Subject: ASoC: core: Add SOC_DOUBLE_R_S_TLV Add a macro for signed mixer with two registers and tlv array. Signed-off-by: Markus Pargmann Signed-off-by: Mark Brown --- include/sound/soc.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/include/sound/soc.h b/include/sound/soc.h index a25f3ccb3fde..c4be7ab89399 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -45,6 +45,11 @@ ((unsigned long)&(struct soc_mixer_control) \ {.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \ .max = xmax, .platform_max = xmax, .invert = xinvert}) +#define SOC_DOUBLE_R_S_VALUE(xlreg, xrreg, xshift, xmin, xmax, xsign_bit, xinvert) \ + ((unsigned long)&(struct soc_mixer_control) \ + {.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \ + .max = xmax, .min = xmin, .platform_max = xmax, .sign_bit = xsign_bit, \ + .invert = xinvert}) #define SOC_DOUBLE_R_RANGE_VALUE(xlreg, xrreg, xshift, xmin, xmax, xinvert) \ ((unsigned long)&(struct soc_mixer_control) \ {.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \ @@ -152,6 +157,15 @@ {.reg = xreg, .rreg = xrreg, \ .shift = xshift, .rshift = xshift, \ .max = xmax, .min = xmin} } +#define SOC_DOUBLE_R_S_TLV(xname, reg_left, reg_right, xshift, xmin, xmax, xsign_bit, xinvert, tlv_array) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ + .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ + SNDRV_CTL_ELEM_ACCESS_READWRITE,\ + .tlv.p = (tlv_array), \ + .info = snd_soc_info_volsw, \ + .get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \ + .private_value = SOC_DOUBLE_R_S_VALUE(reg_left, reg_right, xshift, \ + xmin, xmax, xsign_bit, xinvert) } #define SOC_DOUBLE_S8_TLV(xname, xreg, xmin, xmax, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ -- cgit v1.2.3 From a74ab5121f8d91fb7f13ac1c86e72e9d35e0bc29 Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Thu, 16 Jan 2014 16:30:25 +0100 Subject: ASoC: tlv320aic32x4: Use gpio_is_valid Use function gpio_is_valid to check for gpio ports. Signed-off-by: Markus Pargmann Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic32x4.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index 688151ba309a..36a9cb90a585 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -588,7 +588,7 @@ static int aic32x4_probe(struct snd_soc_codec *codec) snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); - if (aic32x4->rstn_gpio >= 0) { + if (gpio_is_valid(aic32x4->rstn_gpio)) { ndelay(10); gpio_set_value(aic32x4->rstn_gpio, 1); } @@ -693,7 +693,7 @@ static int aic32x4_i2c_probe(struct i2c_client *i2c, aic32x4->rstn_gpio = -1; } - if (aic32x4->rstn_gpio >= 0) { + if (gpio_is_valid(aic32x4->rstn_gpio)) { ret = devm_gpio_request_one(&i2c->dev, aic32x4->rstn_gpio, GPIOF_OUT_INIT_LOW, "tlv320aic32x4 rstn"); if (ret != 0) -- cgit v1.2.3 From c671e79d6c2d5a525496fbf18103841c68fe3305 Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Mon, 27 Jan 2014 13:03:07 +0100 Subject: ASoC: tlv320aic32x4: Use signed int mixer controls There are a number of mixer controls that support negative values. They use signed values for this with different number of bits for the values. Currently they only support the positive range. This patch replaces the unsigned mixers with signed mixers to support the full range. Signed-off-by: Markus Pargmann Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic32x4.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index 36a9cb90a585..c541213b1edf 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -68,18 +68,24 @@ struct aic32x4_priv { int rstn_gpio; }; -/* 0dB min, 1dB steps */ -static DECLARE_TLV_DB_SCALE(tlv_step_1, 0, 100, 0); /* 0dB min, 0.5dB steps */ static DECLARE_TLV_DB_SCALE(tlv_step_0_5, 0, 50, 0); +/* -63.5dB min, 0.5dB steps */ +static DECLARE_TLV_DB_SCALE(tlv_pcm, -6350, 50, 0); +/* -6dB min, 1dB steps */ +static DECLARE_TLV_DB_SCALE(tlv_driver_gain, -600, 100, 0); +/* -12dB min, 0.5dB steps */ +static DECLARE_TLV_DB_SCALE(tlv_adc_vol, -1200, 50, 0); static const struct snd_kcontrol_new aic32x4_snd_controls[] = { - SOC_DOUBLE_R_TLV("PCM Playback Volume", AIC32X4_LDACVOL, - AIC32X4_RDACVOL, 0, 0x30, 0, tlv_step_0_5), - SOC_DOUBLE_R_TLV("HP Driver Gain Volume", AIC32X4_HPLGAIN, - AIC32X4_HPRGAIN, 0, 0x1D, 0, tlv_step_1), - SOC_DOUBLE_R_TLV("LO Driver Gain Volume", AIC32X4_LOLGAIN, - AIC32X4_LORGAIN, 0, 0x1D, 0, tlv_step_1), + SOC_DOUBLE_R_S_TLV("PCM Playback Volume", AIC32X4_LDACVOL, + AIC32X4_RDACVOL, 0, -0x7f, 0x30, 7, 0, tlv_pcm), + SOC_DOUBLE_R_S_TLV("HP Driver Gain Volume", AIC32X4_HPLGAIN, + AIC32X4_HPRGAIN, 0, -0x6, 0x1d, 5, 0, + tlv_driver_gain), + SOC_DOUBLE_R_S_TLV("LO Driver Gain Volume", AIC32X4_LOLGAIN, + AIC32X4_LORGAIN, 0, -0x6, 0x1d, 5, 0, + tlv_driver_gain), SOC_DOUBLE_R("HP DAC Playback Switch", AIC32X4_HPLGAIN, AIC32X4_HPRGAIN, 6, 0x01, 1), SOC_DOUBLE_R("LO DAC Playback Switch", AIC32X4_LOLGAIN, @@ -90,8 +96,8 @@ static const struct snd_kcontrol_new aic32x4_snd_controls[] = { SOC_SINGLE("ADCFGA Left Mute Switch", AIC32X4_ADCFGA, 7, 1, 0), SOC_SINGLE("ADCFGA Right Mute Switch", AIC32X4_ADCFGA, 3, 1, 0), - SOC_DOUBLE_R_TLV("ADC Level Volume", AIC32X4_LADCVOL, - AIC32X4_RADCVOL, 0, 0x28, 0, tlv_step_0_5), + SOC_DOUBLE_R_S_TLV("ADC Level Volume", AIC32X4_LADCVOL, + AIC32X4_RADCVOL, 0, -0x18, 0x28, 6, 0, tlv_adc_vol), SOC_DOUBLE_R_TLV("PGA Level Volume", AIC32X4_LMICPGAVOL, AIC32X4_RMICPGAVOL, 0, 0x5f, 0, tlv_step_0_5), -- cgit v1.2.3 From 4d16700dd926d4c4a66a91a138c34eef4fd342b4 Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Mon, 27 Jan 2014 13:03:08 +0100 Subject: ASoC: tlv320aic32x4: DT support Add DT support for this codec. The bindings differ a bit from the aic3x codec bindings, so I created a new binding documentation. Signed-off-by: Markus Pargmann Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/tlv320aic32x4.txt | 18 ++++++++++++++++ sound/soc/codecs/tlv320aic32x4.c | 25 ++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/tlv320aic32x4.txt diff --git a/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt b/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt new file mode 100644 index 000000000000..db0551088cc4 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt @@ -0,0 +1,18 @@ +Texas Instruments - tlv320aic32x4 Codec module + +The tlv320aic32x4 serial control bus communicates through I2C protocols + +Required properties: + - compatible: Should be "ti,tlv320aic32x4" + - reg: I2C slave address + +Optional properties: + - reset-gpios: Reset-GPIO phandle with args as described in gpio/gpio.txt + + +Example: + +codec: tlv320aic32x4@18 { + compatible = "ti,tlv320aic32x4"; + reg = <0x18>; +}; diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index c541213b1edf..1dd50e48934c 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -669,11 +670,22 @@ static struct snd_soc_codec_driver soc_codec_dev_aic32x4 = { .num_dapm_routes = ARRAY_SIZE(aic32x4_dapm_routes), }; +static int aic32x4_parse_dt(struct aic32x4_priv *aic32x4, + struct device_node *np) +{ + aic32x4->swapdacs = false; + aic32x4->micpga_routing = 0; + aic32x4->rstn_gpio = of_get_named_gpio(np, "reset-gpios", 0); + + return 0; +} + static int aic32x4_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct aic32x4_pdata *pdata = i2c->dev.platform_data; struct aic32x4_priv *aic32x4; + struct device_node *np = i2c->dev.of_node; int ret; aic32x4 = devm_kzalloc(&i2c->dev, sizeof(struct aic32x4_priv), @@ -692,6 +704,12 @@ static int aic32x4_i2c_probe(struct i2c_client *i2c, aic32x4->swapdacs = pdata->swapdacs; aic32x4->micpga_routing = pdata->micpga_routing; aic32x4->rstn_gpio = pdata->rstn_gpio; + } else if (np) { + ret = aic32x4_parse_dt(aic32x4, np); + if (ret) { + dev_err(&i2c->dev, "Failed to parse DT node\n"); + return ret; + } } else { aic32x4->power_cfg = 0; aic32x4->swapdacs = false; @@ -723,10 +741,17 @@ static const struct i2c_device_id aic32x4_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, aic32x4_i2c_id); +static const struct of_device_id aic32x4_of_id[] = { + { .compatible = "ti,tlv320aic32x4", }, + { /* senitel */ } +}; +MODULE_DEVICE_TABLE(of, aic32x4_of_id); + static struct i2c_driver aic32x4_i2c_driver = { .driver = { .name = "tlv320aic32x4", .owner = THIS_MODULE, + .of_match_table = aic32x4_of_id, }, .probe = aic32x4_i2c_probe, .remove = aic32x4_i2c_remove, -- cgit v1.2.3 From e156291c7bab1771df34acd583c3c1b1ad71231c Mon Sep 17 00:00:00 2001 From: Christian Engelmayer Date: Fri, 7 Feb 2014 19:43:19 +0100 Subject: ASoC: wm8991: Remove unused pointer in wm8991_probe() Remove unused pointer 'wm8991' in function wm8991_probe(). The last user vanished with a86652e5 (ASoC: wm8991: Convert to direct regmap API usage) Detected by Coverity: CID 1162831 Signed-off-by: Christian Engelmayer Signed-off-by: Mark Brown --- sound/soc/codecs/wm8991.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c index dba0306c42a5..244eb09ffa43 100644 --- a/sound/soc/codecs/wm8991.c +++ b/sound/soc/codecs/wm8991.c @@ -1251,11 +1251,8 @@ static int wm8991_remove(struct snd_soc_codec *codec) static int wm8991_probe(struct snd_soc_codec *codec) { - struct wm8991_priv *wm8991; int ret; - wm8991 = snd_soc_codec_get_drvdata(codec); - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); if (ret < 0) { dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); -- cgit v1.2.3 From 6c3d713e6d32706999689e379a9098afb4cd8a2c Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 17 Feb 2014 13:16:54 +0100 Subject: ASoC: ad193x: Split SPI and I2C code into different modules There are a few known (minor) problems with having the support code for both I2C and SPI in the same module: * We need to be extra careful to make sure to not build the driver into the kernel if one of the subsystems is build as a module (Currently only I2C can be build as a module). * The module init path error handling is rather ugly. E.g. what should be done if either the SPI or the I2C driver fails to register? Most drivers that implement SPI and I2C in the same module currently fallback to undefined behavior in that case. Splitting the the driver into two modules, one for each bus, allows the registration of the other bus driver to continue without problems if one of them fails. This patch splits the AD193X driver into 3 modules. One core module that implements the device logic, but is independent of the bus method used. And one module for SPI and I2C each that registers the drivers and sets up the regmap struct for the bus. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/blackfin/Kconfig | 3 +- sound/soc/codecs/Kconfig | 11 +++- sound/soc/codecs/Makefile | 4 ++ sound/soc/codecs/ad193x-i2c.c | 54 ++++++++++++++++ sound/soc/codecs/ad193x-spi.c | 48 +++++++++++++++ sound/soc/codecs/ad193x.c | 140 +++++------------------------------------- sound/soc/codecs/ad193x.h | 7 +++ 7 files changed, 140 insertions(+), 127 deletions(-) create mode 100644 sound/soc/codecs/ad193x-i2c.c create mode 100644 sound/soc/codecs/ad193x-spi.c diff --git a/sound/soc/blackfin/Kconfig b/sound/soc/blackfin/Kconfig index 54f74f8cbb75..359136777c4d 100644 --- a/sound/soc/blackfin/Kconfig +++ b/sound/soc/blackfin/Kconfig @@ -68,7 +68,8 @@ config SND_BF5XX_SOC_AD193X tristate "SoC AD193X Audio support for Blackfin" depends on SND_BF5XX_I2S select SND_BF5XX_SOC_I2S - select SND_SOC_AD193X + select SND_SOC_AD193X_I2C if I2C + select SND_SOC_AD193X_SPI if SPI_MASTER help Say Y if you want to add support for AD193X codec on Blackfin. This driver supports AD1936, AD1937, AD1938 and AD1939. diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 983d087aa92a..d7da6191fc55 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -16,7 +16,8 @@ config SND_SOC_ALL_CODECS select SND_SOC_AB8500_CODEC if ABX500_CORE select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS select SND_SOC_AD1836 if SPI_MASTER - select SND_SOC_AD193X if SND_SOC_I2C_AND_SPI + select SND_SOC_AD193X_SPI if SPI_MASTER + select SND_SOC_AD193X_I2C if I2C select SND_SOC_AD1980 if SND_SOC_AC97_BUS select SND_SOC_AD73311 select SND_SOC_ADAU1373 if I2C @@ -182,6 +183,14 @@ config SND_SOC_AD1836 config SND_SOC_AD193X tristate +config SND_SOC_AD193X_SPI + tristate + select SND_SOC_AD193X + +config SND_SOC_AD193X_I2C + tristate + select SND_SOC_AD193X + config SND_SOC_AD1980 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index bc126764a44d..7795e37d313f 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -3,6 +3,8 @@ snd-soc-ab8500-codec-objs := ab8500-codec.o snd-soc-ac97-objs := ac97.o snd-soc-ad1836-objs := ad1836.o snd-soc-ad193x-objs := ad193x.o +snd-soc-ad193x-spi-objs := ad193x-spi.o +snd-soc-ad193x-i2c-objs := ad193x-i2c.o snd-soc-ad1980-objs := ad1980.o snd-soc-ad73311-objs := ad73311.o snd-soc-adau1701-objs := adau1701.o @@ -134,6 +136,8 @@ obj-$(CONFIG_SND_SOC_AB8500_CODEC) += snd-soc-ab8500-codec.o obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o obj-$(CONFIG_SND_SOC_AD193X) += snd-soc-ad193x.o +obj-$(CONFIG_SND_SOC_AD193X_SPI) += snd-soc-ad193x-spi.o +obj-$(CONFIG_SND_SOC_AD193X_I2C) += snd-soc-ad193x-i2c.o obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o obj-$(CONFIG_SND_SOC_ADAU1373) += snd-soc-adau1373.o diff --git a/sound/soc/codecs/ad193x-i2c.c b/sound/soc/codecs/ad193x-i2c.c new file mode 100644 index 000000000000..df3a1a415825 --- /dev/null +++ b/sound/soc/codecs/ad193x-i2c.c @@ -0,0 +1,54 @@ +/* + * AD1936/AD1937 audio driver + * + * Copyright 2014 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include + +#include + +#include "ad193x.h" + +static const struct i2c_device_id ad193x_id[] = { + { "ad1936", 0 }, + { "ad1937", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ad193x_id); + +static int ad193x_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct regmap_config config; + + config = ad193x_regmap_config; + config.val_bits = 8; + config.reg_bits = 8; + + return ad193x_probe(&client->dev, devm_regmap_init_i2c(client, &config)); +} + +static int ad193x_i2c_remove(struct i2c_client *client) +{ + snd_soc_unregister_codec(&client->dev); + return 0; +} + +static struct i2c_driver ad193x_i2c_driver = { + .driver = { + .name = "ad193x", + }, + .probe = ad193x_i2c_probe, + .remove = ad193x_i2c_remove, + .id_table = ad193x_id, +}; +module_i2c_driver(ad193x_i2c_driver); + +MODULE_DESCRIPTION("ASoC AD1936/AD1937 audio CODEC driver"); +MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/ad193x-spi.c b/sound/soc/codecs/ad193x-spi.c new file mode 100644 index 000000000000..390cef9b9dc2 --- /dev/null +++ b/sound/soc/codecs/ad193x-spi.c @@ -0,0 +1,48 @@ +/* + * AD1938/AD1939 audio driver + * + * Copyright 2014 Analog Devices Inc. + * + * Licensed under the GPL-2. + */ + +#include +#include +#include + +#include + +#include "ad193x.h" + +static int ad193x_spi_probe(struct spi_device *spi) +{ + struct regmap_config config; + + config = ad193x_regmap_config; + config.val_bits = 8; + config.reg_bits = 16; + config.read_flag_mask = 0x09; + config.write_flag_mask = 0x08; + + return ad193x_probe(&spi->dev, devm_regmap_init_spi(spi, &config)); +} + +static int ad193x_spi_remove(struct spi_device *spi) +{ + snd_soc_unregister_codec(&spi->dev); + return 0; +} + +static struct spi_driver ad193x_spi_driver = { + .driver = { + .name = "ad193x", + .owner = THIS_MODULE, + }, + .probe = ad193x_spi_probe, + .remove = ad193x_spi_remove, +}; +module_spi_driver(ad193x_spi_driver); + +MODULE_DESCRIPTION("ASoC AD1938/AD1939 audio CODEC driver"); +MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index 5a42dca535b7..f644a34a28de 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c @@ -6,12 +6,10 @@ * Licensed under the GPL-2 or later. */ -#include #include #include #include -#include -#include +#include #include #include #include @@ -19,6 +17,7 @@ #include #include #include + #include "ad193x.h" /* codec private data */ @@ -320,7 +319,7 @@ static struct snd_soc_dai_driver ad193x_dai = { .ops = &ad193x_dai_ops, }; -static int ad193x_probe(struct snd_soc_codec *codec) +static int ad193x_codec_probe(struct snd_soc_codec *codec) { struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec); int ret; @@ -352,7 +351,7 @@ static int ad193x_probe(struct snd_soc_codec *codec) } static struct snd_soc_codec_driver soc_codec_dev_ad193x = { - .probe = ad193x_probe, + .probe = ad193x_codec_probe, .controls = ad193x_snd_controls, .num_controls = ARRAY_SIZE(ad193x_snd_controls), .dapm_widgets = ad193x_dapm_widgets, @@ -366,140 +365,31 @@ static bool adau193x_reg_volatile(struct device *dev, unsigned int reg) return false; } -#if defined(CONFIG_SPI_MASTER) - -static const struct regmap_config ad193x_spi_regmap_config = { - .val_bits = 8, - .reg_bits = 16, - .read_flag_mask = 0x09, - .write_flag_mask = 0x08, - +const struct regmap_config ad193x_regmap_config = { .max_register = AD193X_NUM_REGS - 1, .volatile_reg = adau193x_reg_volatile, }; +EXPORT_SYMBOL_GPL(ad193x_regmap_config); -static int ad193x_spi_probe(struct spi_device *spi) +int ad193x_probe(struct device *dev, struct regmap *regmap) { struct ad193x_priv *ad193x; - ad193x = devm_kzalloc(&spi->dev, sizeof(struct ad193x_priv), - GFP_KERNEL); - if (ad193x == NULL) - return -ENOMEM; - - ad193x->regmap = devm_regmap_init_spi(spi, &ad193x_spi_regmap_config); - if (IS_ERR(ad193x->regmap)) - return PTR_ERR(ad193x->regmap); - - spi_set_drvdata(spi, ad193x); - - return snd_soc_register_codec(&spi->dev, &soc_codec_dev_ad193x, - &ad193x_dai, 1); -} - -static int ad193x_spi_remove(struct spi_device *spi) -{ - snd_soc_unregister_codec(&spi->dev); - return 0; -} - -static struct spi_driver ad193x_spi_driver = { - .driver = { - .name = "ad193x", - .owner = THIS_MODULE, - }, - .probe = ad193x_spi_probe, - .remove = ad193x_spi_remove, -}; -#endif - -#if IS_ENABLED(CONFIG_I2C) - -static const struct regmap_config ad193x_i2c_regmap_config = { - .val_bits = 8, - .reg_bits = 8, - - .max_register = AD193X_NUM_REGS - 1, - .volatile_reg = adau193x_reg_volatile, -}; - -static const struct i2c_device_id ad193x_id[] = { - { "ad1936", 0 }, - { "ad1937", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, ad193x_id); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); -static int ad193x_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct ad193x_priv *ad193x; - - ad193x = devm_kzalloc(&client->dev, sizeof(struct ad193x_priv), - GFP_KERNEL); + ad193x = devm_kzalloc(dev, sizeof(*ad193x), GFP_KERNEL); if (ad193x == NULL) return -ENOMEM; - ad193x->regmap = devm_regmap_init_i2c(client, &ad193x_i2c_regmap_config); - if (IS_ERR(ad193x->regmap)) - return PTR_ERR(ad193x->regmap); - - i2c_set_clientdata(client, ad193x); - - return snd_soc_register_codec(&client->dev, &soc_codec_dev_ad193x, - &ad193x_dai, 1); -} - -static int ad193x_i2c_remove(struct i2c_client *client) -{ - snd_soc_unregister_codec(&client->dev); - return 0; -} + ad193x->regmap = regmap; -static struct i2c_driver ad193x_i2c_driver = { - .driver = { - .name = "ad193x", - }, - .probe = ad193x_i2c_probe, - .remove = ad193x_i2c_remove, - .id_table = ad193x_id, -}; -#endif - -static int __init ad193x_modinit(void) -{ - int ret; - -#if IS_ENABLED(CONFIG_I2C) - ret = i2c_add_driver(&ad193x_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register AD193X I2C driver: %d\n", - ret); - } -#endif - -#if defined(CONFIG_SPI_MASTER) - ret = spi_register_driver(&ad193x_spi_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register AD193X SPI driver: %d\n", - ret); - } -#endif - return ret; -} -module_init(ad193x_modinit); - -static void __exit ad193x_modexit(void) -{ -#if defined(CONFIG_SPI_MASTER) - spi_unregister_driver(&ad193x_spi_driver); -#endif + dev_set_drvdata(dev, ad193x); -#if IS_ENABLED(CONFIG_I2C) - i2c_del_driver(&ad193x_i2c_driver); -#endif + return snd_soc_register_codec(dev, &soc_codec_dev_ad193x, + &ad193x_dai, 1); } -module_exit(ad193x_modexit); +EXPORT_SYMBOL_GPL(ad193x_probe); MODULE_DESCRIPTION("ASoC ad193x driver"); MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); diff --git a/sound/soc/codecs/ad193x.h b/sound/soc/codecs/ad193x.h index 473388049992..ab9a998f15be 100644 --- a/sound/soc/codecs/ad193x.h +++ b/sound/soc/codecs/ad193x.h @@ -9,6 +9,13 @@ #ifndef __AD193X_H__ #define __AD193X_H__ +#include + +struct device; + +extern const struct regmap_config ad193x_regmap_config; +int ad193x_probe(struct device *dev, struct regmap *regmap); + #define AD193X_PLL_CLK_CTRL0 0x00 #define AD193X_PLL_POWERDOWN 0x01 #define AD193X_PLL_INPUT_MASK 0x6 -- cgit v1.2.3 From d07338b0f2e1697c99fcd52bf1895227ce5e1a14 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:44:23 +0100 Subject: ASoC: wm8991: Fix the wrong number of enum items wm8991 codec driver has a few places wrongly defining the number of enum items. Use SOC_ENUM_SINGLE_DECL() macro and they are automatically fixed. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Charles Keepax Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/wm8991.c | 41 +++++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c index 244eb09ffa43..32d219570cca 100644 --- a/sound/soc/codecs/wm8991.c +++ b/sound/soc/codecs/wm8991.c @@ -171,26 +171,23 @@ static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol, static const char *wm8991_digital_sidetone[] = {"None", "Left ADC", "Right ADC", "Reserved"}; -static const struct soc_enum wm8991_left_digital_sidetone_enum = - SOC_ENUM_SINGLE(WM8991_DIGITAL_SIDE_TONE, - WM8991_ADC_TO_DACL_SHIFT, - WM8991_ADC_TO_DACL_MASK, - wm8991_digital_sidetone); - -static const struct soc_enum wm8991_right_digital_sidetone_enum = - SOC_ENUM_SINGLE(WM8991_DIGITAL_SIDE_TONE, - WM8991_ADC_TO_DACR_SHIFT, - WM8991_ADC_TO_DACR_MASK, - wm8991_digital_sidetone); +static SOC_ENUM_SINGLE_DECL(wm8991_left_digital_sidetone_enum, + WM8991_DIGITAL_SIDE_TONE, + WM8991_ADC_TO_DACL_SHIFT, + wm8991_digital_sidetone); + +static SOC_ENUM_SINGLE_DECL(wm8991_right_digital_sidetone_enum, + WM8991_DIGITAL_SIDE_TONE, + WM8991_ADC_TO_DACR_SHIFT, + wm8991_digital_sidetone); static const char *wm8991_adcmode[] = {"Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"}; -static const struct soc_enum wm8991_right_adcmode_enum = - SOC_ENUM_SINGLE(WM8991_ADC_CTRL, - WM8991_ADC_HPF_CUT_SHIFT, - WM8991_ADC_HPF_CUT_MASK, - wm8991_adcmode); +static SOC_ENUM_SINGLE_DECL(wm8991_right_adcmode_enum, + WM8991_ADC_CTRL, + WM8991_ADC_HPF_CUT_SHIFT, + wm8991_adcmode); static const struct snd_kcontrol_new wm8991_snd_controls[] = { /* INMIXL */ @@ -486,9 +483,9 @@ static const struct snd_kcontrol_new wm8991_dapm_inmixr_controls[] = { static const char *wm8991_ainlmux[] = {"INMIXL Mix", "RXVOICE Mix", "DIFFINL Mix"}; -static const struct soc_enum wm8991_ainlmux_enum = - SOC_ENUM_SINGLE(WM8991_INPUT_MIXER1, WM8991_AINLMODE_SHIFT, - ARRAY_SIZE(wm8991_ainlmux), wm8991_ainlmux); +static SOC_ENUM_SINGLE_DECL(wm8991_ainlmux_enum, + WM8991_INPUT_MIXER1, WM8991_AINLMODE_SHIFT, + wm8991_ainlmux); static const struct snd_kcontrol_new wm8991_dapm_ainlmux_controls = SOC_DAPM_ENUM("Route", wm8991_ainlmux_enum); @@ -499,9 +496,9 @@ static const struct snd_kcontrol_new wm8991_dapm_ainlmux_controls = static const char *wm8991_ainrmux[] = {"INMIXR Mix", "RXVOICE Mix", "DIFFINR Mix"}; -static const struct soc_enum wm8991_ainrmux_enum = - SOC_ENUM_SINGLE(WM8991_INPUT_MIXER1, WM8991_AINRMODE_SHIFT, - ARRAY_SIZE(wm8991_ainrmux), wm8991_ainrmux); +static SOC_ENUM_SINGLE_DECL(wm8991_ainrmux_enum, + WM8991_INPUT_MIXER1, WM8991_AINRMODE_SHIFT, + wm8991_ainrmux); static const struct snd_kcontrol_new wm8991_dapm_ainrmux_controls = SOC_DAPM_ENUM("Route", wm8991_ainrmux_enum); -- cgit v1.2.3 From b6592d88ec37440c88cc3bc2c9c08a61d0de3eec Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 09:55:27 +0100 Subject: ASoC: ad193x: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/ad193x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index f644a34a28de..9381a767e75f 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c @@ -31,8 +31,8 @@ struct ad193x_priv { */ static const char * const ad193x_deemp[] = {"None", "48kHz", "44.1kHz", "32kHz"}; -static const struct soc_enum ad193x_deemp_enum = - SOC_ENUM_SINGLE(AD193X_DAC_CTRL2, 1, 4, ad193x_deemp); +static SOC_ENUM_SINGLE_DECL(ad193x_deemp_enum, AD193X_DAC_CTRL2, 1, + ad193x_deemp); static const DECLARE_TLV_DB_MINMAX(adau193x_tlv, -9563, 0); -- cgit v1.2.3 From 806057cc75ef641cd9b012b0278c1f179090bab2 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Feb 2014 10:45:53 +0100 Subject: ASoC: tlv320aic23: Use SOC_ENUM_SINGLE_DECL() Just replace with the helper macro. No functional change at all. Signed-off-by: Takashi Iwai Acked-by: Liam Girdwood Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic23.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index 5d430cc56f51..139f11f4dd8b 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c @@ -64,16 +64,16 @@ static const struct regmap_config tlv320aic23_regmap = { static const char *rec_src_text[] = { "Line", "Mic" }; static const char *deemph_text[] = {"None", "32Khz", "44.1Khz", "48Khz"}; -static const struct soc_enum rec_src_enum = - SOC_ENUM_SINGLE(TLV320AIC23_ANLG, 2, 2, rec_src_text); +static SOC_ENUM_SINGLE_DECL(rec_src_enum, + TLV320AIC23_ANLG, 2, rec_src_text); static const struct snd_kcontrol_new tlv320aic23_rec_src_mux_controls = SOC_DAPM_ENUM("Input Select", rec_src_enum); -static const struct soc_enum tlv320aic23_rec_src = - SOC_ENUM_SINGLE(TLV320AIC23_ANLG, 2, 2, rec_src_text); -static const struct soc_enum tlv320aic23_deemph = - SOC_ENUM_SINGLE(TLV320AIC23_DIGT, 1, 4, deemph_text); +static SOC_ENUM_SINGLE_DECL(tlv320aic23_rec_src, + TLV320AIC23_ANLG, 2, rec_src_text); +static SOC_ENUM_SINGLE_DECL(tlv320aic23_deemph, + TLV320AIC23_DIGT, 1, deemph_text); static const DECLARE_TLV_DB_SCALE(out_gain_tlv, -12100, 100, 0); static const DECLARE_TLV_DB_SCALE(input_gain_tlv, -1725, 75, 0); -- cgit v1.2.3 From 98b664e2ceddd40120e8cd2aa56f7eb9a51870cf Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Thu, 20 Feb 2014 18:22:58 +0100 Subject: ASoC: tlv320aic32x4: Support for master clock Add support for a master clock passed through DT. The master clock of the codec is only active when the codec is in use. Signed-off-by: Markus Pargmann Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/tlv320aic32x4.txt | 4 ++++ sound/soc/codecs/tlv320aic32x4.c | 21 +++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt b/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt index db0551088cc4..352be7b1f7e2 100644 --- a/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt +++ b/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt @@ -8,6 +8,8 @@ Required properties: Optional properties: - reset-gpios: Reset-GPIO phandle with args as described in gpio/gpio.txt + - clocks/clock-names: Clock named 'mclk' for the master clock of the codec. + See clock/clock-bindings.txt for information about the detailed format. Example: @@ -15,4 +17,6 @@ Example: codec: tlv320aic32x4@18 { compatible = "ti,tlv320aic32x4"; reg = <0x18>; + clocks = <&clks 201>; + clock-names = "mclk"; }; diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index 1dd50e48934c..643fa53beaab 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -67,6 +68,7 @@ struct aic32x4_priv { u32 micpga_routing; bool swapdacs; int rstn_gpio; + struct clk *mclk; }; /* 0dB min, 0.5dB steps */ @@ -487,8 +489,18 @@ static int aic32x4_mute(struct snd_soc_dai *dai, int mute) static int aic32x4_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { + struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec); + int ret; + switch (level) { case SND_SOC_BIAS_ON: + /* Switch on master clock */ + ret = clk_prepare_enable(aic32x4->mclk); + if (ret) { + dev_err(codec->dev, "Failed to enable master clock\n"); + return ret; + } + /* Switch on PLL */ snd_soc_update_bits(codec, AIC32X4_PLLPR, AIC32X4_PLLEN, AIC32X4_PLLEN); @@ -539,6 +551,9 @@ static int aic32x4_set_bias_level(struct snd_soc_codec *codec, /* Switch off BCLK_N Divider */ snd_soc_update_bits(codec, AIC32X4_BCLKN, AIC32X4_BCLKEN, 0); + + /* Switch off master clock */ + clk_disable_unprepare(aic32x4->mclk); break; case SND_SOC_BIAS_OFF: break; @@ -717,6 +732,12 @@ static int aic32x4_i2c_probe(struct i2c_client *i2c, aic32x4->rstn_gpio = -1; } + aic32x4->mclk = devm_clk_get(&i2c->dev, "mclk"); + if (IS_ERR(aic32x4->mclk)) { + dev_err(&i2c->dev, "Failed getting the mclk. The current implementation does not support the usage of this codec without mclk\n"); + return PTR_ERR(aic32x4->mclk); + } + if (gpio_is_valid(aic32x4->rstn_gpio)) { ret = devm_gpio_request_one(&i2c->dev, aic32x4->rstn_gpio, GPIOF_OUT_INIT_LOW, "tlv320aic32x4 rstn"); -- cgit v1.2.3 From 239b669b2dedc46d5e6b07d87c3d1dedf8d9477c Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Thu, 20 Feb 2014 18:22:59 +0100 Subject: ASoC: tlv320aic32x4: Support for regulators Support regulators to power up the codec. This patch also enables the AVDD LDO if no AV regulator was found. Signed-off-by: Markus Pargmann Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/tlv320aic32x4.txt | 8 ++ sound/soc/codecs/tlv320aic32x4.c | 126 ++++++++++++++++++++- 2 files changed, 133 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt b/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt index 352be7b1f7e2..5e2741af27be 100644 --- a/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt +++ b/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt @@ -5,6 +5,14 @@ The tlv320aic32x4 serial control bus communicates through I2C protocols Required properties: - compatible: Should be "ti,tlv320aic32x4" - reg: I2C slave address + - supply-*: Required supply regulators are: + "iov" - digital IO power supply + "ldoin" - LDO power supply + "dv" - Digital core power supply + "av" - Analog core power supply + If you supply ldoin, dv and av are optional. Otherwise they are required + See regulator/regulator.txt for more information about the detailed binding + format. Optional properties: - reset-gpios: Reset-GPIO phandle with args as described in gpio/gpio.txt diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index 643fa53beaab..d69c61ffcda8 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -69,6 +70,11 @@ struct aic32x4_priv { bool swapdacs; int rstn_gpio; struct clk *mclk; + + struct regulator *supply_ldo; + struct regulator *supply_iov; + struct regulator *supply_dv; + struct regulator *supply_av; }; /* 0dB min, 0.5dB steps */ @@ -695,6 +701,106 @@ static int aic32x4_parse_dt(struct aic32x4_priv *aic32x4, return 0; } +static void aic32x4_disable_regulators(struct aic32x4_priv *aic32x4) +{ + regulator_disable(aic32x4->supply_iov); + + if (!IS_ERR(aic32x4->supply_ldo)) + regulator_disable(aic32x4->supply_ldo); + + if (!IS_ERR(aic32x4->supply_dv)) + regulator_disable(aic32x4->supply_dv); + + if (!IS_ERR(aic32x4->supply_av)) + regulator_disable(aic32x4->supply_av); +} + +static int aic32x4_setup_regulators(struct device *dev, + struct aic32x4_priv *aic32x4) +{ + int ret = 0; + + aic32x4->supply_ldo = devm_regulator_get_optional(dev, "ldoin"); + aic32x4->supply_iov = devm_regulator_get(dev, "iov"); + aic32x4->supply_dv = devm_regulator_get_optional(dev, "dv"); + aic32x4->supply_av = devm_regulator_get_optional(dev, "av"); + + /* Check if the regulator requirements are fulfilled */ + + if (IS_ERR(aic32x4->supply_iov)) { + dev_err(dev, "Missing supply 'iov'\n"); + return PTR_ERR(aic32x4->supply_iov); + } + + if (IS_ERR(aic32x4->supply_ldo)) { + if (PTR_ERR(aic32x4->supply_ldo) == -EPROBE_DEFER) + return -EPROBE_DEFER; + + if (IS_ERR(aic32x4->supply_dv)) { + dev_err(dev, "Missing supply 'dv' or 'ldoin'\n"); + return PTR_ERR(aic32x4->supply_dv); + } + if (IS_ERR(aic32x4->supply_av)) { + dev_err(dev, "Missing supply 'av' or 'ldoin'\n"); + return PTR_ERR(aic32x4->supply_av); + } + } else { + if (IS_ERR(aic32x4->supply_dv) && + PTR_ERR(aic32x4->supply_dv) == -EPROBE_DEFER) + return -EPROBE_DEFER; + if (IS_ERR(aic32x4->supply_av) && + PTR_ERR(aic32x4->supply_av) == -EPROBE_DEFER) + return -EPROBE_DEFER; + } + + ret = regulator_enable(aic32x4->supply_iov); + if (ret) { + dev_err(dev, "Failed to enable regulator iov\n"); + return ret; + } + + if (!IS_ERR(aic32x4->supply_ldo)) { + ret = regulator_enable(aic32x4->supply_ldo); + if (ret) { + dev_err(dev, "Failed to enable regulator ldo\n"); + goto error_ldo; + } + } + + if (!IS_ERR(aic32x4->supply_dv)) { + ret = regulator_enable(aic32x4->supply_dv); + if (ret) { + dev_err(dev, "Failed to enable regulator dv\n"); + goto error_dv; + } + } + + if (!IS_ERR(aic32x4->supply_av)) { + ret = regulator_enable(aic32x4->supply_av); + if (ret) { + dev_err(dev, "Failed to enable regulator av\n"); + goto error_av; + } + } + + if (!IS_ERR(aic32x4->supply_ldo) && IS_ERR(aic32x4->supply_av)) + aic32x4->power_cfg |= AIC32X4_PWR_AIC32X4_LDO_ENABLE; + + return 0; + +error_av: + if (!IS_ERR(aic32x4->supply_dv)) + regulator_disable(aic32x4->supply_dv); + +error_dv: + if (!IS_ERR(aic32x4->supply_ldo)) + regulator_disable(aic32x4->supply_ldo); + +error_ldo: + regulator_disable(aic32x4->supply_iov); + return ret; +} + static int aic32x4_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { @@ -745,13 +851,31 @@ static int aic32x4_i2c_probe(struct i2c_client *i2c, return ret; } + ret = aic32x4_setup_regulators(&i2c->dev, aic32x4); + if (ret) { + dev_err(&i2c->dev, "Failed to setup regulators\n"); + return ret; + } + ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_aic32x4, &aic32x4_dai, 1); - return ret; + if (ret) { + dev_err(&i2c->dev, "Failed to register codec\n"); + aic32x4_disable_regulators(aic32x4); + return ret; + } + + i2c_set_clientdata(i2c, aic32x4); + + return 0; } static int aic32x4_i2c_remove(struct i2c_client *client) { + struct aic32x4_priv *aic32x4 = i2c_get_clientdata(client); + + aic32x4_disable_regulators(aic32x4); + snd_soc_unregister_codec(&client->dev); return 0; } -- cgit v1.2.3 From 3154cc7404506700ff270b6f123ec9c734f002fd Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Thu, 20 Feb 2014 18:23:00 +0100 Subject: ASoC: tlv320aic32x4: Rearrange clock tree shutdown Rearrange clock tree shutdown to disable them in the reversed order of startup. First disable all dividers, then PLL followed by master clock. Signed-off-by: Markus Pargmann Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic32x4.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index d69c61ffcda8..c6bd7e75352d 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -534,29 +534,29 @@ static int aic32x4_set_bias_level(struct snd_soc_codec *codec, case SND_SOC_BIAS_PREPARE: break; case SND_SOC_BIAS_STANDBY: - /* Switch off PLL */ - snd_soc_update_bits(codec, AIC32X4_PLLPR, - AIC32X4_PLLEN, 0); - - /* Switch off NDAC Divider */ - snd_soc_update_bits(codec, AIC32X4_NDAC, - AIC32X4_NDACEN, 0); + /* Switch off BCLK_N Divider */ + snd_soc_update_bits(codec, AIC32X4_BCLKN, + AIC32X4_BCLKEN, 0); - /* Switch off MDAC Divider */ - snd_soc_update_bits(codec, AIC32X4_MDAC, - AIC32X4_MDACEN, 0); + /* Switch off MADC Divider */ + snd_soc_update_bits(codec, AIC32X4_MADC, + AIC32X4_MADCEN, 0); /* Switch off NADC Divider */ snd_soc_update_bits(codec, AIC32X4_NADC, AIC32X4_NADCEN, 0); - /* Switch off MADC Divider */ - snd_soc_update_bits(codec, AIC32X4_MADC, - AIC32X4_MADCEN, 0); + /* Switch off MDAC Divider */ + snd_soc_update_bits(codec, AIC32X4_MDAC, + AIC32X4_MDACEN, 0); - /* Switch off BCLK_N Divider */ - snd_soc_update_bits(codec, AIC32X4_BCLKN, - AIC32X4_BCLKEN, 0); + /* Switch off NDAC Divider */ + snd_soc_update_bits(codec, AIC32X4_NDAC, + AIC32X4_NDACEN, 0); + + /* Switch off PLL */ + snd_soc_update_bits(codec, AIC32X4_PLLPR, + AIC32X4_PLLEN, 0); /* Switch off master clock */ clk_disable_unprepare(aic32x4->mclk); -- cgit v1.2.3 From b3fc5725967cea8b661383742ccce21fdeb3ef72 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Thu, 6 Mar 2014 14:04:41 +0400 Subject: ASoC: tlv320aic23: add support for SPI control mode tlv320aic23 chip control interface may work in either I2C or SPI mode depending on the MODE pin state. Functionality and register layout are independent of the control mode. Implement bus-specific parts as separate modules. Signed-off-by: Max Filippov Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 11 ++++++- sound/soc/codecs/Makefile | 4 +++ sound/soc/codecs/tlv320aic23-i2c.c | 59 ++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/tlv320aic23-spi.c | 57 ++++++++++++++++++++++++++++++++++++ sound/soc/codecs/tlv320aic23.c | 55 +++++++---------------------------- sound/soc/codecs/tlv320aic23.h | 6 ++++ 6 files changed, 147 insertions(+), 45 deletions(-) create mode 100644 sound/soc/codecs/tlv320aic23-i2c.c create mode 100644 sound/soc/codecs/tlv320aic23-spi.c diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 983d087aa92a..5e4fc048d42a 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -71,7 +71,8 @@ config SND_SOC_ALL_CODECS select SND_SOC_STA529 if I2C select SND_SOC_STAC9766 if SND_SOC_AC97_BUS select SND_SOC_TAS5086 if I2C - select SND_SOC_TLV320AIC23 if I2C + select SND_SOC_TLV320AIC23_I2C if I2C + select SND_SOC_TLV320AIC23_SPI if SPI_MASTER select SND_SOC_TLV320AIC26 if SPI_MASTER select SND_SOC_TLV320AIC32X4 if I2C select SND_SOC_TLV320AIC3X if I2C @@ -357,6 +358,14 @@ config SND_SOC_TAS5086 config SND_SOC_TLV320AIC23 tristate +config SND_SOC_TLV320AIC23_I2C + tristate + select SND_SOC_TLV320AIC23 + +config SND_SOC_TLV320AIC23_SPI + tristate + select SND_SOC_TLV320AIC23 + config SND_SOC_TLV320AIC26 tristate depends on SPI diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index bc126764a44d..ed1fd8925e43 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -63,6 +63,8 @@ snd-soc-sta529-objs := sta529.o snd-soc-stac9766-objs := stac9766.o snd-soc-tas5086-objs := tas5086.o snd-soc-tlv320aic23-objs := tlv320aic23.o +snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o +snd-soc-tlv320aic23-spi-objs := tlv320aic23-spi.o snd-soc-tlv320aic26-objs := tlv320aic26.o snd-soc-tlv320aic3x-objs := tlv320aic3x.o snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o @@ -193,6 +195,8 @@ obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o +obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o +obj-$(CONFIG_SND_SOC_TLV320AIC23_SPI) += snd-soc-tlv320aic23-spi.o obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o obj-$(CONFIG_SND_SOC_TLV320AIC32X4) += snd-soc-tlv320aic32x4.o diff --git a/sound/soc/codecs/tlv320aic23-i2c.c b/sound/soc/codecs/tlv320aic23-i2c.c new file mode 100644 index 000000000000..20fc46092c2c --- /dev/null +++ b/sound/soc/codecs/tlv320aic23-i2c.c @@ -0,0 +1,59 @@ +/* + * ALSA SoC TLV320AIC23 codec driver I2C interface + * + * Author: Arun KS, + * Copyright: (C) 2008 Mistral Solutions Pvt Ltd., + * + * Based on sound/soc/codecs/wm8731.c by Richard Purdie + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include + +#include "tlv320aic23.h" + +static int tlv320aic23_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *i2c_id) +{ + struct regmap *regmap; + + if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -EINVAL; + + regmap = devm_regmap_init_i2c(i2c, &tlv320aic23_regmap); + return tlv320aic23_probe(&i2c->dev, regmap); +} + +static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c) +{ + snd_soc_unregister_codec(&i2c->dev); + return 0; +} + +static const struct i2c_device_id tlv320aic23_id[] = { + {"tlv320aic23", 0}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, tlv320aic23_id); + +static struct i2c_driver tlv320aic23_i2c_driver = { + .driver = { + .name = "tlv320aic23-codec", + }, + .probe = tlv320aic23_i2c_probe, + .remove = __exit_p(tlv320aic23_i2c_remove), + .id_table = tlv320aic23_id, +}; + +module_i2c_driver(tlv320aic23_i2c_driver); + +MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver I2C"); +MODULE_AUTHOR("Arun KS "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/tlv320aic23-spi.c b/sound/soc/codecs/tlv320aic23-spi.c new file mode 100644 index 000000000000..585aea436c6a --- /dev/null +++ b/sound/soc/codecs/tlv320aic23-spi.c @@ -0,0 +1,57 @@ +/* + * ALSA SoC TLV320AIC23 codec driver SPI interface + * + * Author: Arun KS, + * Copyright: (C) 2008 Mistral Solutions Pvt Ltd., + * + * Based on sound/soc/codecs/wm8731.c by Richard Purdie + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include + +#include "tlv320aic23.h" + +static int aic23_spi_probe(struct spi_device *spi) +{ + int ret; + struct regmap *regmap; + + dev_dbg(&spi->dev, "probing tlv320aic23 spi device\n"); + + spi->bits_per_word = 16; + spi->mode = SPI_MODE_0; + ret = spi_setup(spi); + if (ret < 0) + return ret; + + regmap = devm_regmap_init_spi(spi, &tlv320aic23_regmap); + return tlv320aic23_probe(&spi->dev, regmap); +} + +static int aic23_spi_remove(struct spi_device *spi) +{ + snd_soc_unregister_codec(&spi->dev); + return 0; +} + +static struct spi_driver aic23_spi = { + .driver = { + .name = "tlv320aic23", + .owner = THIS_MODULE, + }, + .probe = aic23_spi_probe, + .remove = aic23_spi_remove, +}; + +module_spi_driver(aic23_spi); + +MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver SPI"); +MODULE_AUTHOR("Arun KS "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index 139f11f4dd8b..ab369ae76b8c 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -51,7 +50,7 @@ static const struct reg_default tlv320aic23_reg[] = { { 9, 0x0000 }, }; -static const struct regmap_config tlv320aic23_regmap = { +const struct regmap_config tlv320aic23_regmap = { .reg_bits = 7, .val_bits = 9, @@ -557,7 +556,7 @@ static int tlv320aic23_resume(struct snd_soc_codec *codec) return 0; } -static int tlv320aic23_probe(struct snd_soc_codec *codec) +static int tlv320aic23_codec_probe(struct snd_soc_codec *codec) { int ret; @@ -604,7 +603,7 @@ static int tlv320aic23_remove(struct snd_soc_codec *codec) } static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = { - .probe = tlv320aic23_probe, + .probe = tlv320aic23_codec_probe, .remove = tlv320aic23_remove, .suspend = tlv320aic23_suspend, .resume = tlv320aic23_resume, @@ -617,57 +616,25 @@ static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = { .num_dapm_routes = ARRAY_SIZE(tlv320aic23_intercon), }; -/* - * If the i2c layer weren't so broken, we could pass this kind of data - * around - */ -static int tlv320aic23_codec_probe(struct i2c_client *i2c, - const struct i2c_device_id *i2c_id) +int tlv320aic23_probe(struct device *dev, struct regmap *regmap) { struct aic23 *aic23; - int ret; - if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -EINVAL; + if (IS_ERR(regmap)) + return PTR_ERR(regmap); - aic23 = devm_kzalloc(&i2c->dev, sizeof(struct aic23), GFP_KERNEL); + aic23 = devm_kzalloc(dev, sizeof(struct aic23), GFP_KERNEL); if (aic23 == NULL) return -ENOMEM; - aic23->regmap = devm_regmap_init_i2c(i2c, &tlv320aic23_regmap); - if (IS_ERR(aic23->regmap)) - return PTR_ERR(aic23->regmap); + aic23->regmap = regmap; - i2c_set_clientdata(i2c, aic23); + dev_set_drvdata(dev, aic23); - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_tlv320aic23, &tlv320aic23_dai, 1); - return ret; -} -static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c) -{ - snd_soc_unregister_codec(&i2c->dev); - return 0; + return snd_soc_register_codec(dev, &soc_codec_dev_tlv320aic23, + &tlv320aic23_dai, 1); } -static const struct i2c_device_id tlv320aic23_id[] = { - {"tlv320aic23", 0}, - {} -}; - -MODULE_DEVICE_TABLE(i2c, tlv320aic23_id); - -static struct i2c_driver tlv320aic23_i2c_driver = { - .driver = { - .name = "tlv320aic23-codec", - }, - .probe = tlv320aic23_codec_probe, - .remove = __exit_p(tlv320aic23_i2c_remove), - .id_table = tlv320aic23_id, -}; - -module_i2c_driver(tlv320aic23_i2c_driver); - MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver"); MODULE_AUTHOR("Arun KS "); MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/tlv320aic23.h b/sound/soc/codecs/tlv320aic23.h index e804120bd3da..3a7235a04a89 100644 --- a/sound/soc/codecs/tlv320aic23.h +++ b/sound/soc/codecs/tlv320aic23.h @@ -12,6 +12,12 @@ #ifndef _TLV320AIC23_H #define _TLV320AIC23_H +struct device; +struct regmap_config; + +extern const struct regmap_config tlv320aic23_regmap; +int tlv320aic23_probe(struct device *dev, struct regmap *regmap); + /* Codec TLV320AIC23 */ #define TLV320AIC23_LINVOL 0x00 #define TLV320AIC23_RINVOL 0x01 -- cgit v1.2.3 From cc1bc54aa787c39125fe843e81bd693e8f507c32 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Thu, 6 Mar 2014 14:04:42 +0400 Subject: ASoC: update Kconfig of AIC23 users to select I2C variant Now that AIC23 supports two control interfaces all existing I2C users should select I2C variant. Signed-off-by: Max Filippov Signed-off-by: Mark Brown --- sound/soc/atmel/Kconfig | 2 +- sound/soc/cirrus/Kconfig | 2 +- sound/soc/fsl/Kconfig | 2 +- sound/soc/omap/Kconfig | 4 ++-- sound/soc/samsung/Kconfig | 2 +- sound/soc/tegra/Kconfig | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig index e634eb78ed03..4789619a52d8 100644 --- a/sound/soc/atmel/Kconfig +++ b/sound/soc/atmel/Kconfig @@ -58,6 +58,6 @@ config SND_AT91_SOC_AFEB9260 depends on ARCH_AT91 && ATMEL_SSC && ARCH_AT91 && MACH_AFEB9260 && SND_ATMEL_SOC select SND_ATMEL_SOC_PDC select SND_ATMEL_SOC_SSC - select SND_SOC_TLV320AIC23 + select SND_SOC_TLV320AIC23_I2C help Say Y here to support sound on AFEB9260 board. diff --git a/sound/soc/cirrus/Kconfig b/sound/soc/cirrus/Kconfig index 06f938deda15..a0bf4a610397 100644 --- a/sound/soc/cirrus/Kconfig +++ b/sound/soc/cirrus/Kconfig @@ -18,7 +18,7 @@ config SND_EP93XX_SOC_SNAPPERCL15 tristate "SoC Audio support for Bluewater Systems Snapper CL15 module" depends on SND_EP93XX_SOC && MACH_SNAPPER_CL15 select SND_EP93XX_SOC_I2S - select SND_SOC_TLV320AIC23 + select SND_SOC_TLV320AIC23_I2C help Say Y or M here if you want to add support for I2S audio on the Bluewater Systems Snapper CL15 module. diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 07f8f141727d..19a18a4f133a 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -170,7 +170,7 @@ config SND_SOC_EUKREA_TLV320 || MACH_EUKREA_MBIMXSD35_BASEBOARD \ || MACH_EUKREA_MBIMXSD51_BASEBOARD depends on I2C - select SND_SOC_TLV320AIC23 + select SND_SOC_TLV320AIC23_I2C select SND_SOC_IMX_PCM_FIQ select SND_SOC_IMX_AUDMUX select SND_SOC_IMX_SSI diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig index 22ad9c5654b5..e00659351a4e 100644 --- a/sound/soc/omap/Kconfig +++ b/sound/soc/omap/Kconfig @@ -58,7 +58,7 @@ config SND_OMAP_SOC_OSK5912 tristate "SoC Audio support for omap osk5912" depends on SND_OMAP_SOC && MACH_OMAP_OSK && I2C select SND_OMAP_SOC_MCBSP - select SND_SOC_TLV320AIC23 + select SND_SOC_TLV320AIC23_I2C help Say Y if you want to add support for SoC audio on osk5912. @@ -66,7 +66,7 @@ config SND_OMAP_SOC_AM3517EVM tristate "SoC Audio support for OMAP3517 / AM3517 EVM" depends on SND_OMAP_SOC && MACH_OMAP3517EVM && I2C select SND_OMAP_SOC_MCBSP - select SND_SOC_TLV320AIC23 + select SND_SOC_TLV320AIC23_I2C help Say Y if you want to add support for SoC audio on the OMAP3517 / AM3517 EVM. diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index 454f41cfc828..47a7a1b633ae 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig @@ -117,7 +117,7 @@ config SND_SOC_SAMSUNG_SIMTEC_TLV320AIC23 tristate "SoC I2S Audio support for TLV320AIC23 on Simtec boards" depends on SND_SOC_SAMSUNG && ARCH_S3C24XX select SND_S3C24XX_I2S - select SND_SOC_TLV320AIC23 + select SND_SOC_TLV320AIC23_I2C select SND_SOC_SAMSUNG_SIMTEC config SND_SOC_SAMSUNG_SIMTEC_HERMES diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig index 9f9c1856f822..31198cf7f88d 100644 --- a/sound/soc/tegra/Kconfig +++ b/sound/soc/tegra/Kconfig @@ -105,7 +105,7 @@ config SND_SOC_TEGRA_TRIMSLICE tristate "SoC Audio support for TrimSlice board" depends on SND_SOC_TEGRA && I2C select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC - select SND_SOC_TLV320AIC23 + select SND_SOC_TLV320AIC23_I2C help Say Y or M here if you want to add support for SoC audio on the TrimSlice platform. -- cgit v1.2.3 From 40423285a10e317b8e89e430779633eaef0b4add Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sat, 8 Mar 2014 13:31:06 +0400 Subject: ASoC: tlv320aic23: add missing EXPORT_SYMBOLs This fixes the following build errors when aic23 is configured as module: >> ERROR: "tlv320aic23_probe" >> [sound/soc/codecs/snd-soc-tlv320aic23-i2c.ko] undefined! >> ERROR: "tlv320aic23_regmap" >> [sound/soc/codecs/snd-soc-tlv320aic23-i2c.ko] undefined! Signed-off-by: Max Filippov Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic23.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index ab369ae76b8c..7b4cfef232ea 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c @@ -59,6 +59,7 @@ const struct regmap_config tlv320aic23_regmap = { .num_reg_defaults = ARRAY_SIZE(tlv320aic23_reg), .cache_type = REGCACHE_RBTREE, }; +EXPORT_SYMBOL(tlv320aic23_regmap); static const char *rec_src_text[] = { "Line", "Mic" }; static const char *deemph_text[] = {"None", "32Khz", "44.1Khz", "48Khz"}; @@ -634,6 +635,7 @@ int tlv320aic23_probe(struct device *dev, struct regmap *regmap) return snd_soc_register_codec(dev, &soc_codec_dev_tlv320aic23, &tlv320aic23_dai, 1); } +EXPORT_SYMBOL(tlv320aic23_probe); MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver"); MODULE_AUTHOR("Arun KS "); -- cgit v1.2.3 From b46f2c5c0054153a6e5f76b6a943df5d837879f6 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Fri, 7 Mar 2014 14:58:32 +0200 Subject: ASoC: tlv320aic32x4: Sort Makefile in alphabetic order The tlv320aic32x4 related lines were wrongly placed after tlv320aic3x lines. Signed-off-by: Jyri Sarha Signed-off-by: Mark Brown --- sound/soc/codecs/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index bc126764a44d..1deeb20fd411 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -64,8 +64,8 @@ snd-soc-stac9766-objs := stac9766.o snd-soc-tas5086-objs := tas5086.o snd-soc-tlv320aic23-objs := tlv320aic23.o snd-soc-tlv320aic26-objs := tlv320aic26.o -snd-soc-tlv320aic3x-objs := tlv320aic3x.o snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o +snd-soc-tlv320aic3x-objs := tlv320aic3x.o snd-soc-tlv320dac33-objs := tlv320dac33.o snd-soc-twl4030-objs := twl4030.o snd-soc-twl6040-objs := twl6040.o @@ -194,8 +194,8 @@ obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o -obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o obj-$(CONFIG_SND_SOC_TLV320AIC32X4) += snd-soc-tlv320aic32x4.o +obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o -- cgit v1.2.3 From 58d4d3c976b33784a1443c446a3d7203bf2153f0 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 4 Mar 2014 09:41:53 +0100 Subject: ASoC: si476x: Fix IO setup The si476x is a MFD device and the CODEC driver is using the regmap struct of the parent device, hence automatic IO setup will not work and we need to manually call snd_soc_codec_set_cache_io(). The issue was introduced commit d6173df35f ("ASoC: si476x: Remove custom register I/O implementation") Fixes: d6173df35f ("ASoC: si476x: Remove custom register I/O implementation") Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/codecs/si476x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/si476x.c b/sound/soc/codecs/si476x.c index 52e7cb08434b..fa2b8e07f420 100644 --- a/sound/soc/codecs/si476x.c +++ b/sound/soc/codecs/si476x.c @@ -210,7 +210,7 @@ out: static int si476x_codec_probe(struct snd_soc_codec *codec) { codec->control_data = dev_get_regmap(codec->dev->parent, NULL); - return 0; + return snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); } static struct snd_soc_dai_ops si476x_dai_ops = { -- cgit v1.2.3 From 8eeb5c15131d7b5061c10423eda3ae4c68db4eaf Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 4 Mar 2014 09:39:24 +0100 Subject: ASoC: 88pm860: Fix IO setup The 88pm860 is a MFD device and the CODEC driver is using the regmap struct of the parent device, hence automatic IO setup will not work and we need to manually call snd_soc_codec_set_cache_io(). The issue was introduced in commit f9ded3b2e7 ("ASoC: 88pm860x: Use regmap for I/O"). Fixes: f9ded3b2e7 ("ASoC: 88pm860x: Use regmap for I/O"). Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/codecs/88pm860x-codec.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c index 75d0ad5d2dcb..647a72cda005 100644 --- a/sound/soc/codecs/88pm860x-codec.c +++ b/sound/soc/codecs/88pm860x-codec.c @@ -1328,6 +1328,9 @@ static int pm860x_probe(struct snd_soc_codec *codec) pm860x->codec = codec; codec->control_data = pm860x->regmap; + ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); + if (ret) + return ret; for (i = 0; i < 4; i++) { ret = request_threaded_irq(pm860x->irq[i], NULL, -- cgit v1.2.3