Loading include/sound/tlv320aic3x.h 0 → 100644 +17 −0 Original line number Diff line number Diff line /* * Platform data for Texas Instruments TLV320AIC3x codec * * Author: Jarkko Nikula <jhnikula@gmail.com> * * 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. */ #ifndef __TLV320AIC3x_H__ #define __TLV320AIC3x_H__ struct aic3x_pdata { int gpio_reset; /* < 0 if not used */ }; #endif No newline at end of file include/sound/tpa6130a2-plat.h +1 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ enum tpa_model { struct tpa6130a2_platform_data { enum tpa_model id; int power_gpio; int limit_gain; }; #endif sound/soc/codecs/tlv320aic3x.c +25 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ #include <linux/delay.h> #include <linux/pm.h> #include <linux/i2c.h> #include <linux/gpio.h> #include <linux/regulator/consumer.h> #include <linux/platform_device.h> #include <sound/core.h> Loading @@ -47,6 +48,7 @@ #include <sound/soc-dapm.h> #include <sound/initval.h> #include <sound/tlv.h> #include <sound/tlv320aic3x.h> #include "tlv320aic3x.h" Loading @@ -64,6 +66,7 @@ struct aic3x_priv { struct regulator_bulk_data supplies[AIC3X_NUM_SUPPLIES]; unsigned int sysclk; int master; int gpio_reset; }; /* Loading Loading @@ -1278,6 +1281,10 @@ static int aic3x_unregister(struct aic3x_priv *aic3x) snd_soc_unregister_dai(&aic3x_dai); snd_soc_unregister_codec(&aic3x->codec); if (aic3x->gpio_reset >= 0) { gpio_set_value(aic3x->gpio_reset, 0); gpio_free(aic3x->gpio_reset); } regulator_bulk_disable(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); Loading @@ -1302,6 +1309,7 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, { struct snd_soc_codec *codec; struct aic3x_priv *aic3x; struct aic3x_pdata *pdata = i2c->dev.platform_data; int ret, i; aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL); Loading @@ -1318,6 +1326,15 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, i2c_set_clientdata(i2c, aic3x); aic3x->gpio_reset = -1; if (pdata && pdata->gpio_reset >= 0) { ret = gpio_request(pdata->gpio_reset, "tlv320aic3x reset"); if (ret != 0) goto err_gpio; aic3x->gpio_reset = pdata->gpio_reset; gpio_direction_output(aic3x->gpio_reset, 0); } for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) aic3x->supplies[i].supply = aic3x_supply_names[i]; Loading @@ -1335,11 +1352,19 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, goto err_enable; } if (aic3x->gpio_reset >= 0) { udelay(1); gpio_set_value(aic3x->gpio_reset, 1); } return aic3x_register(codec); err_enable: regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); err_get: if (aic3x->gpio_reset >= 0) gpio_free(aic3x->gpio_reset); err_gpio: kfree(aic3x); return ret; } Loading sound/soc/codecs/tlv320dac33.c +118 −105 Original line number Diff line number Diff line Loading @@ -61,6 +61,8 @@ #define US_TO_SAMPLES(rate, us) \ (rate / (1000000 / us)) static void dac33_calculate_times(struct snd_pcm_substream *substream); static int dac33_prepare_chip(struct snd_pcm_substream *substream); static struct snd_soc_codec *tlv320dac33_codec; Loading Loading @@ -91,6 +93,7 @@ struct tlv320dac33_priv { struct work_struct work; struct snd_soc_codec codec; struct regulator_bulk_data supplies[DAC33_NUM_SUPPLIES]; struct snd_pcm_substream *substream; int power_gpio; int chip_power; int irq; Loading Loading @@ -284,45 +287,47 @@ static int dac33_write16(struct snd_soc_codec *codec, unsigned int reg, return ret; } static void dac33_restore_regs(struct snd_soc_codec *codec) static void dac33_init_chip(struct snd_soc_codec *codec) { struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); u8 *cache = codec->reg_cache; u8 data[2]; int i, ret; if (!dac33->chip_power) if (unlikely(!dac33->chip_power)) return; for (i = DAC33_PWR_CTRL; i <= DAC33_INTP_CTRL_B; i++) { data[0] = i; data[1] = cache[i]; /* Skip the read only registers */ if ((i >= DAC33_INT_OSC_STATUS && i <= DAC33_INT_OSC_FREQ_RAT_READ_B) || (i >= DAC33_FIFO_WPTR_MSB && i <= DAC33_FIFO_IRQ_FLAG) || i == DAC33_DAC_STATUS_FLAGS || i == DAC33_SRC_EST_REF_CLK_RATIO_A || i == DAC33_SRC_EST_REF_CLK_RATIO_B) continue; ret = codec->hw_write(codec->control_data, data, 2); if (ret != 2) dev_err(codec->dev, "Write failed (%d)\n", ret); } for (i = DAC33_LDAC_PWR_CTRL; i <= DAC33_LINEL_TO_LLO_VOL; i++) { data[0] = i; data[1] = cache[i]; ret = codec->hw_write(codec->control_data, data, 2); if (ret != 2) dev_err(codec->dev, "Write failed (%d)\n", ret); } for (i = DAC33_LINER_TO_RLO_VOL; i <= DAC33_OSC_TRIM; i++) { data[0] = i; data[1] = cache[i]; ret = codec->hw_write(codec->control_data, data, 2); if (ret != 2) dev_err(codec->dev, "Write failed (%d)\n", ret); /* 44-46: DAC Control Registers */ /* A : DAC sample rate Fsref/1.5 */ dac33_write(codec, DAC33_DAC_CTRL_A, DAC33_DACRATE(0)); /* B : DAC src=normal, not muted */ dac33_write(codec, DAC33_DAC_CTRL_B, DAC33_DACSRCR_RIGHT | DAC33_DACSRCL_LEFT); /* C : (defaults) */ dac33_write(codec, DAC33_DAC_CTRL_C, 0x00); /* 73 : volume soft stepping control, clock source = internal osc (?) */ dac33_write(codec, DAC33_ANA_VOL_SOFT_STEP_CTRL, DAC33_VOLCLKEN); dac33_write(codec, DAC33_PWR_CTRL, DAC33_PDNALLB); /* Restore only selected registers (gains mostly) */ dac33_write(codec, DAC33_LDAC_DIG_VOL_CTRL, dac33_read_reg_cache(codec, DAC33_LDAC_DIG_VOL_CTRL)); dac33_write(codec, DAC33_RDAC_DIG_VOL_CTRL, dac33_read_reg_cache(codec, DAC33_RDAC_DIG_VOL_CTRL)); dac33_write(codec, DAC33_LINEL_TO_LLO_VOL, dac33_read_reg_cache(codec, DAC33_LINEL_TO_LLO_VOL)); dac33_write(codec, DAC33_LINER_TO_RLO_VOL, dac33_read_reg_cache(codec, DAC33_LINER_TO_RLO_VOL)); } static inline void dac33_read_id(struct snd_soc_codec *codec) { u8 reg; dac33_read(codec, DAC33_DEVICE_ID_MSB, ®); dac33_read(codec, DAC33_DEVICE_ID_LSB, ®); dac33_read(codec, DAC33_DEVICE_REV_ID, ®); } static inline void dac33_soft_power(struct snd_soc_codec *codec, int power) Loading @@ -341,9 +346,17 @@ static inline void dac33_soft_power(struct snd_soc_codec *codec, int power) static int dac33_hard_power(struct snd_soc_codec *codec, int power) { struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); int ret; int ret = 0; mutex_lock(&dac33->mutex); /* Safety check */ if (unlikely(power == dac33->chip_power)) { dev_warn(codec->dev, "Trying to set the same power state: %s\n", power ? "ON" : "OFF"); goto exit; } if (power) { ret = regulator_bulk_enable(ARRAY_SIZE(dac33->supplies), dac33->supplies); Loading @@ -357,11 +370,6 @@ static int dac33_hard_power(struct snd_soc_codec *codec, int power) gpio_set_value(dac33->power_gpio, 1); dac33->chip_power = 1; /* Restore registers */ dac33_restore_regs(codec); dac33_soft_power(codec, 1); } else { dac33_soft_power(codec, 0); if (dac33->power_gpio >= 0) Loading @@ -383,6 +391,22 @@ static int dac33_hard_power(struct snd_soc_codec *codec, int power) return ret; } static int playback_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(w->codec); switch (event) { case SND_SOC_DAPM_PRE_PMU: if (likely(dac33->substream)) { dac33_calculate_times(dac33->substream); dac33_prepare_chip(dac33->substream); } break; } return 0; } static int dac33_get_nsample(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { Loading Loading @@ -512,6 +536,8 @@ static const struct snd_soc_dapm_widget dac33_dapm_widgets[] = { DAC33_OUT_AMP_PWR_CTRL, 6, 3, 3, 0), SND_SOC_DAPM_REG(snd_soc_dapm_mixer, "Output Right Amp Power", DAC33_OUT_AMP_PWR_CTRL, 4, 3, 3, 0), SND_SOC_DAPM_PRE("Prepare Playback", playback_event), }; static const struct snd_soc_dapm_route audio_map[] = { Loading Loading @@ -554,18 +580,18 @@ static int dac33_set_bias_level(struct snd_soc_codec *codec, break; case SND_SOC_BIAS_STANDBY: if (codec->bias_level == SND_SOC_BIAS_OFF) { /* Coming from OFF, switch on the codec */ ret = dac33_hard_power(codec, 1); if (ret != 0) return ret; } dac33_soft_power(codec, 0); dac33_init_chip(codec); } break; case SND_SOC_BIAS_OFF: ret = dac33_hard_power(codec, 0); if (ret != 0) return ret; break; } codec->bias_level = level; Loading Loading @@ -708,6 +734,31 @@ static void dac33_oscwait(struct snd_soc_codec *codec) "internal oscillator calibration failed\n"); } static int dac33_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_codec *codec = socdev->card->codec; struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); /* Stream started, save the substream pointer */ dac33->substream = substream; return 0; } static void dac33_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_codec *codec = socdev->card->codec; struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); dac33->substream = NULL; } static int dac33_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) Loading Loading @@ -791,6 +842,16 @@ static int dac33_prepare_chip(struct snd_pcm_substream *substream) } mutex_lock(&dac33->mutex); if (!dac33->chip_power) { /* * Chip is not powered yet. * Do the init in the dac33_set_bias_level later. */ mutex_unlock(&dac33->mutex); return 0; } dac33_soft_power(codec, 0); dac33_soft_power(codec, 1); Loading Loading @@ -997,15 +1058,6 @@ static void dac33_calculate_times(struct snd_pcm_substream *substream) } static int dac33_pcm_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { dac33_calculate_times(substream); dac33_prepare_chip(substream); return 0; } static int dac33_pcm_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { Loading Loading @@ -1269,35 +1321,6 @@ static int dac33_set_dai_fmt(struct snd_soc_dai *codec_dai, return 0; } static void dac33_init_chip(struct snd_soc_codec *codec) { /* 44-46: DAC Control Registers */ /* A : DAC sample rate Fsref/1.5 */ dac33_write(codec, DAC33_DAC_CTRL_A, DAC33_DACRATE(0)); /* B : DAC src=normal, not muted */ dac33_write(codec, DAC33_DAC_CTRL_B, DAC33_DACSRCR_RIGHT | DAC33_DACSRCL_LEFT); /* C : (defaults) */ dac33_write(codec, DAC33_DAC_CTRL_C, 0x00); /* 64-65 : L&R DAC power control Line In -> OUT 1V/V Gain, DAC -> OUT 4V/V Gain*/ dac33_write(codec, DAC33_LDAC_PWR_CTRL, DAC33_LROUT_GAIN(2)); dac33_write(codec, DAC33_RDAC_PWR_CTRL, DAC33_LROUT_GAIN(2)); /* 73 : volume soft stepping control, clock source = internal osc (?) */ dac33_write(codec, DAC33_ANA_VOL_SOFT_STEP_CTRL, DAC33_VOLCLKEN); /* 66 : LOP/LOM Modes */ dac33_write(codec, DAC33_OUT_AMP_CM_CTRL, 0xff); /* 68 : LOM inverted from LOP */ dac33_write(codec, DAC33_OUT_AMP_CTRL, (3<<2)); dac33_write(codec, DAC33_PWR_CTRL, DAC33_PDNALLB); } static int dac33_soc_probe(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); Loading @@ -1311,11 +1334,6 @@ static int dac33_soc_probe(struct platform_device *pdev) socdev->card->codec = codec; dac33 = snd_soc_codec_get_drvdata(codec); /* Power up the codec */ dac33_hard_power(codec, 1); /* Set default configuration */ dac33_init_chip(codec); /* register pcms */ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); if (ret < 0) { Loading @@ -1332,12 +1350,6 @@ static int dac33_soc_probe(struct platform_device *pdev) dac33_add_widgets(codec); /* power on device */ dac33_set_bias_level(codec, SND_SOC_BIAS_STANDBY); /* Bias level configuration has enabled regulator an extra time */ regulator_bulk_disable(ARRAY_SIZE(dac33->supplies), dac33->supplies); return 0; pcm_err: Loading Loading @@ -1374,6 +1386,8 @@ static int dac33_soc_resume(struct platform_device *pdev) struct snd_soc_codec *codec = socdev->card->codec; dac33_set_bias_level(codec, SND_SOC_BIAS_STANDBY); if (codec->suspend_bias_level == SND_SOC_BIAS_ON) dac33_set_bias_level(codec, SND_SOC_BIAS_PREPARE); dac33_set_bias_level(codec, codec->suspend_bias_level); return 0; Loading @@ -1392,8 +1406,9 @@ EXPORT_SYMBOL_GPL(soc_codec_dev_tlv320dac33); #define DAC33_FORMATS SNDRV_PCM_FMTBIT_S16_LE static struct snd_soc_dai_ops dac33_dai_ops = { .startup = dac33_startup, .shutdown = dac33_shutdown, .hw_params = dac33_hw_params, .prepare = dac33_pcm_prepare, .trigger = dac33_pcm_trigger, .delay = dac33_dai_delay, .set_sysclk = dac33_set_dai_sysclk, Loading Loading @@ -1447,6 +1462,7 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client, codec->hw_write = (hw_write_t) i2c_master_send; codec->bias_level = SND_SOC_BIAS_OFF; codec->set_bias_level = dac33_set_bias_level; codec->idle_bias_off = 1; codec->dai = &dac33_dai; codec->num_dai = 1; codec->reg_cache_size = ARRAY_SIZE(dac33_reg); Loading Loading @@ -1487,8 +1503,6 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client, goto error_gpio; } gpio_direction_output(dac33->power_gpio, 0); } else { dac33->chip_power = 1; } /* Check if the IRQ number is valid and request it */ Loading Loading @@ -1526,12 +1540,14 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client, goto err_get; } ret = regulator_bulk_enable(ARRAY_SIZE(dac33->supplies), dac33->supplies); /* Read the tlv320dac33 ID registers */ ret = dac33_hard_power(codec, 1); if (ret != 0) { dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); goto err_enable; dev_err(codec->dev, "Failed to power up codec: %d\n", ret); goto error_codec; } dac33_read_id(codec); dac33_hard_power(codec, 0); ret = snd_soc_register_codec(codec); if (ret != 0) { Loading @@ -1546,14 +1562,9 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client, goto error_codec; } /* Shut down the codec for now */ dac33_hard_power(codec, 0); return ret; error_codec: regulator_bulk_disable(ARRAY_SIZE(dac33->supplies), dac33->supplies); err_enable: regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies); err_get: if (dac33->irq >= 0) { Loading @@ -1577,6 +1588,8 @@ static int __devexit dac33_i2c_remove(struct i2c_client *client) struct tlv320dac33_priv *dac33; dac33 = i2c_get_clientdata(client); if (unlikely(dac33->chip_power)) dac33_hard_power(&dac33->codec, 0); if (dac33->power_gpio >= 0) Loading sound/soc/codecs/tpa6130a2.c +92 −7 Original line number Diff line number Diff line Loading @@ -46,6 +46,9 @@ static const char *tpa6140a2_supply_names[TPA6130A2_NUM_SUPPLIES] = { "AVdd", }; #define TPA6130A2_GAIN_MAX 0x3f #define TPA6140A2_GAIN_MAX 0x1f /* This struct is used to save the context */ struct tpa6130a2_data { struct mutex mutex; Loading @@ -53,6 +56,8 @@ struct tpa6130a2_data { struct regulator_bulk_data supplies[TPA6130A2_NUM_SUPPLIES]; int power_gpio; unsigned char power_state; enum tpa_model id; int gain_limit; }; static int tpa6130a2_i2c_read(int reg) Loading Loading @@ -175,6 +180,40 @@ static int tpa6130a2_power(int power) return ret; } static int tpa6130a2_info_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; struct tpa6130a2_data *data; BUG_ON(tpa6130a2_client == NULL); data = i2c_get_clientdata(tpa6130a2_client); mutex_lock(&data->mutex); switch (mc->reg) { case TPA6130A2_REG_VOL_MUTE: if (data->gain_limit != mc->max) mc->max = data->gain_limit; break; default: dev_err(&tpa6130a2_client->dev, "Invalid register: 0x02%x\n", mc->reg); goto out; } if (unlikely(mc->max == 1)) uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; else uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 1; uinfo->value.integer.min = 0; uinfo->value.integer.max = mc->max; out: mutex_unlock(&data->mutex); return 0; } static int tpa6130a2_get_reg(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { Loading Loading @@ -238,6 +277,15 @@ static int tpa6130a2_set_reg(struct snd_kcontrol *kcontrol, return 1; } #define SOC_SINGLE_EXT_TLV_TPA(xname, xreg, xshift, xmax, 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 = tpa6130a2_info_volsw, \ .get = tpa6130a2_get_reg, .put = tpa6130a2_set_reg, \ .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) } /* * TPA6130 volume. From -59.5 to 4 dB with increasing step size when going * down in gain. Loading @@ -257,12 +305,24 @@ static const unsigned int tpa6130_tlv[] = { }; static const struct snd_kcontrol_new tpa6130a2_controls[] = { SOC_SINGLE_EXT_TLV("TPA6130A2 Headphone Playback Volume", TPA6130A2_REG_VOL_MUTE, 0, 0x3f, 0, tpa6130a2_get_reg, tpa6130a2_set_reg, SOC_SINGLE_EXT_TLV_TPA("TPA6130A2 Headphone Playback Volume", TPA6130A2_REG_VOL_MUTE, 0, TPA6130A2_GAIN_MAX, 0, tpa6130_tlv), }; static const unsigned int tpa6140_tlv[] = { TLV_DB_RANGE_HEAD(3), 0, 8, TLV_DB_SCALE_ITEM(-5900, 400, 0), 9, 16, TLV_DB_SCALE_ITEM(-2500, 200, 0), 17, 31, TLV_DB_SCALE_ITEM(-1000, 100, 0), }; static const struct snd_kcontrol_new tpa6140a2_controls[] = { SOC_SINGLE_EXT_TLV_TPA("TPA6140A2 Headphone Playback Volume", TPA6130A2_REG_VOL_MUTE, 1, TPA6140A2_GAIN_MAX, 0, tpa6140_tlv), }; /* * Enable or disable channel (left or right) * The bit number for mute and amplifier are the same per channel: Loading Loading @@ -368,11 +428,20 @@ static const struct snd_soc_dapm_route audio_map[] = { int tpa6130a2_add_controls(struct snd_soc_codec *codec) { struct tpa6130a2_data *data; BUG_ON(tpa6130a2_client == NULL); data = i2c_get_clientdata(tpa6130a2_client); snd_soc_dapm_new_controls(codec, tpa6130a2_dapm_widgets, ARRAY_SIZE(tpa6130a2_dapm_widgets)); snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); if (data->id == TPA6140A2) return snd_soc_add_controls(codec, tpa6140a2_controls, ARRAY_SIZE(tpa6140a2_controls)); else return snd_soc_add_controls(codec, tpa6130a2_controls, ARRAY_SIZE(tpa6130a2_controls)); Loading Loading @@ -407,6 +476,7 @@ static int __devinit tpa6130a2_probe(struct i2c_client *client, pdata = client->dev.platform_data; data->power_gpio = pdata->power_gpio; data->id = pdata->id; mutex_init(&data->mutex); Loading @@ -425,20 +495,35 @@ static int __devinit tpa6130a2_probe(struct i2c_client *client, gpio_direction_output(data->power_gpio, 0); } switch (pdata->id) { switch (data->id) { case TPA6130A2: for (i = 0; i < ARRAY_SIZE(data->supplies); i++) data->supplies[i].supply = tpa6130a2_supply_names[i]; if (pdata->limit_gain > 0 && pdata->limit_gain < TPA6130A2_GAIN_MAX) data->gain_limit = pdata->limit_gain; else data->gain_limit = TPA6130A2_GAIN_MAX; break; case TPA6140A2: for (i = 0; i < ARRAY_SIZE(data->supplies); i++) data->supplies[i].supply = tpa6140a2_supply_names[i];; if (pdata->limit_gain > 0 && pdata->limit_gain < TPA6140A2_GAIN_MAX) data->gain_limit = pdata->limit_gain; else data->gain_limit = TPA6140A2_GAIN_MAX; break; default: dev_warn(dev, "Unknown TPA model (%d). Assuming 6130A2\n", pdata->id); for (i = 0; i < ARRAY_SIZE(data->supplies); i++) data->supplies[i].supply = tpa6130a2_supply_names[i]; if (pdata->limit_gain > 0 && pdata->limit_gain < TPA6130A2_GAIN_MAX) data->gain_limit = pdata->limit_gain; else data->gain_limit = TPA6130A2_GAIN_MAX; } ret = regulator_bulk_get(dev, ARRAY_SIZE(data->supplies), Loading Loading
include/sound/tlv320aic3x.h 0 → 100644 +17 −0 Original line number Diff line number Diff line /* * Platform data for Texas Instruments TLV320AIC3x codec * * Author: Jarkko Nikula <jhnikula@gmail.com> * * 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. */ #ifndef __TLV320AIC3x_H__ #define __TLV320AIC3x_H__ struct aic3x_pdata { int gpio_reset; /* < 0 if not used */ }; #endif No newline at end of file
include/sound/tpa6130a2-plat.h +1 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ enum tpa_model { struct tpa6130a2_platform_data { enum tpa_model id; int power_gpio; int limit_gain; }; #endif
sound/soc/codecs/tlv320aic3x.c +25 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ #include <linux/delay.h> #include <linux/pm.h> #include <linux/i2c.h> #include <linux/gpio.h> #include <linux/regulator/consumer.h> #include <linux/platform_device.h> #include <sound/core.h> Loading @@ -47,6 +48,7 @@ #include <sound/soc-dapm.h> #include <sound/initval.h> #include <sound/tlv.h> #include <sound/tlv320aic3x.h> #include "tlv320aic3x.h" Loading @@ -64,6 +66,7 @@ struct aic3x_priv { struct regulator_bulk_data supplies[AIC3X_NUM_SUPPLIES]; unsigned int sysclk; int master; int gpio_reset; }; /* Loading Loading @@ -1278,6 +1281,10 @@ static int aic3x_unregister(struct aic3x_priv *aic3x) snd_soc_unregister_dai(&aic3x_dai); snd_soc_unregister_codec(&aic3x->codec); if (aic3x->gpio_reset >= 0) { gpio_set_value(aic3x->gpio_reset, 0); gpio_free(aic3x->gpio_reset); } regulator_bulk_disable(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); Loading @@ -1302,6 +1309,7 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, { struct snd_soc_codec *codec; struct aic3x_priv *aic3x; struct aic3x_pdata *pdata = i2c->dev.platform_data; int ret, i; aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL); Loading @@ -1318,6 +1326,15 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, i2c_set_clientdata(i2c, aic3x); aic3x->gpio_reset = -1; if (pdata && pdata->gpio_reset >= 0) { ret = gpio_request(pdata->gpio_reset, "tlv320aic3x reset"); if (ret != 0) goto err_gpio; aic3x->gpio_reset = pdata->gpio_reset; gpio_direction_output(aic3x->gpio_reset, 0); } for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) aic3x->supplies[i].supply = aic3x_supply_names[i]; Loading @@ -1335,11 +1352,19 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, goto err_enable; } if (aic3x->gpio_reset >= 0) { udelay(1); gpio_set_value(aic3x->gpio_reset, 1); } return aic3x_register(codec); err_enable: regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); err_get: if (aic3x->gpio_reset >= 0) gpio_free(aic3x->gpio_reset); err_gpio: kfree(aic3x); return ret; } Loading
sound/soc/codecs/tlv320dac33.c +118 −105 Original line number Diff line number Diff line Loading @@ -61,6 +61,8 @@ #define US_TO_SAMPLES(rate, us) \ (rate / (1000000 / us)) static void dac33_calculate_times(struct snd_pcm_substream *substream); static int dac33_prepare_chip(struct snd_pcm_substream *substream); static struct snd_soc_codec *tlv320dac33_codec; Loading Loading @@ -91,6 +93,7 @@ struct tlv320dac33_priv { struct work_struct work; struct snd_soc_codec codec; struct regulator_bulk_data supplies[DAC33_NUM_SUPPLIES]; struct snd_pcm_substream *substream; int power_gpio; int chip_power; int irq; Loading Loading @@ -284,45 +287,47 @@ static int dac33_write16(struct snd_soc_codec *codec, unsigned int reg, return ret; } static void dac33_restore_regs(struct snd_soc_codec *codec) static void dac33_init_chip(struct snd_soc_codec *codec) { struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); u8 *cache = codec->reg_cache; u8 data[2]; int i, ret; if (!dac33->chip_power) if (unlikely(!dac33->chip_power)) return; for (i = DAC33_PWR_CTRL; i <= DAC33_INTP_CTRL_B; i++) { data[0] = i; data[1] = cache[i]; /* Skip the read only registers */ if ((i >= DAC33_INT_OSC_STATUS && i <= DAC33_INT_OSC_FREQ_RAT_READ_B) || (i >= DAC33_FIFO_WPTR_MSB && i <= DAC33_FIFO_IRQ_FLAG) || i == DAC33_DAC_STATUS_FLAGS || i == DAC33_SRC_EST_REF_CLK_RATIO_A || i == DAC33_SRC_EST_REF_CLK_RATIO_B) continue; ret = codec->hw_write(codec->control_data, data, 2); if (ret != 2) dev_err(codec->dev, "Write failed (%d)\n", ret); } for (i = DAC33_LDAC_PWR_CTRL; i <= DAC33_LINEL_TO_LLO_VOL; i++) { data[0] = i; data[1] = cache[i]; ret = codec->hw_write(codec->control_data, data, 2); if (ret != 2) dev_err(codec->dev, "Write failed (%d)\n", ret); } for (i = DAC33_LINER_TO_RLO_VOL; i <= DAC33_OSC_TRIM; i++) { data[0] = i; data[1] = cache[i]; ret = codec->hw_write(codec->control_data, data, 2); if (ret != 2) dev_err(codec->dev, "Write failed (%d)\n", ret); /* 44-46: DAC Control Registers */ /* A : DAC sample rate Fsref/1.5 */ dac33_write(codec, DAC33_DAC_CTRL_A, DAC33_DACRATE(0)); /* B : DAC src=normal, not muted */ dac33_write(codec, DAC33_DAC_CTRL_B, DAC33_DACSRCR_RIGHT | DAC33_DACSRCL_LEFT); /* C : (defaults) */ dac33_write(codec, DAC33_DAC_CTRL_C, 0x00); /* 73 : volume soft stepping control, clock source = internal osc (?) */ dac33_write(codec, DAC33_ANA_VOL_SOFT_STEP_CTRL, DAC33_VOLCLKEN); dac33_write(codec, DAC33_PWR_CTRL, DAC33_PDNALLB); /* Restore only selected registers (gains mostly) */ dac33_write(codec, DAC33_LDAC_DIG_VOL_CTRL, dac33_read_reg_cache(codec, DAC33_LDAC_DIG_VOL_CTRL)); dac33_write(codec, DAC33_RDAC_DIG_VOL_CTRL, dac33_read_reg_cache(codec, DAC33_RDAC_DIG_VOL_CTRL)); dac33_write(codec, DAC33_LINEL_TO_LLO_VOL, dac33_read_reg_cache(codec, DAC33_LINEL_TO_LLO_VOL)); dac33_write(codec, DAC33_LINER_TO_RLO_VOL, dac33_read_reg_cache(codec, DAC33_LINER_TO_RLO_VOL)); } static inline void dac33_read_id(struct snd_soc_codec *codec) { u8 reg; dac33_read(codec, DAC33_DEVICE_ID_MSB, ®); dac33_read(codec, DAC33_DEVICE_ID_LSB, ®); dac33_read(codec, DAC33_DEVICE_REV_ID, ®); } static inline void dac33_soft_power(struct snd_soc_codec *codec, int power) Loading @@ -341,9 +346,17 @@ static inline void dac33_soft_power(struct snd_soc_codec *codec, int power) static int dac33_hard_power(struct snd_soc_codec *codec, int power) { struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); int ret; int ret = 0; mutex_lock(&dac33->mutex); /* Safety check */ if (unlikely(power == dac33->chip_power)) { dev_warn(codec->dev, "Trying to set the same power state: %s\n", power ? "ON" : "OFF"); goto exit; } if (power) { ret = regulator_bulk_enable(ARRAY_SIZE(dac33->supplies), dac33->supplies); Loading @@ -357,11 +370,6 @@ static int dac33_hard_power(struct snd_soc_codec *codec, int power) gpio_set_value(dac33->power_gpio, 1); dac33->chip_power = 1; /* Restore registers */ dac33_restore_regs(codec); dac33_soft_power(codec, 1); } else { dac33_soft_power(codec, 0); if (dac33->power_gpio >= 0) Loading @@ -383,6 +391,22 @@ static int dac33_hard_power(struct snd_soc_codec *codec, int power) return ret; } static int playback_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(w->codec); switch (event) { case SND_SOC_DAPM_PRE_PMU: if (likely(dac33->substream)) { dac33_calculate_times(dac33->substream); dac33_prepare_chip(dac33->substream); } break; } return 0; } static int dac33_get_nsample(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { Loading Loading @@ -512,6 +536,8 @@ static const struct snd_soc_dapm_widget dac33_dapm_widgets[] = { DAC33_OUT_AMP_PWR_CTRL, 6, 3, 3, 0), SND_SOC_DAPM_REG(snd_soc_dapm_mixer, "Output Right Amp Power", DAC33_OUT_AMP_PWR_CTRL, 4, 3, 3, 0), SND_SOC_DAPM_PRE("Prepare Playback", playback_event), }; static const struct snd_soc_dapm_route audio_map[] = { Loading Loading @@ -554,18 +580,18 @@ static int dac33_set_bias_level(struct snd_soc_codec *codec, break; case SND_SOC_BIAS_STANDBY: if (codec->bias_level == SND_SOC_BIAS_OFF) { /* Coming from OFF, switch on the codec */ ret = dac33_hard_power(codec, 1); if (ret != 0) return ret; } dac33_soft_power(codec, 0); dac33_init_chip(codec); } break; case SND_SOC_BIAS_OFF: ret = dac33_hard_power(codec, 0); if (ret != 0) return ret; break; } codec->bias_level = level; Loading Loading @@ -708,6 +734,31 @@ static void dac33_oscwait(struct snd_soc_codec *codec) "internal oscillator calibration failed\n"); } static int dac33_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_codec *codec = socdev->card->codec; struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); /* Stream started, save the substream pointer */ dac33->substream = substream; return 0; } static void dac33_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_codec *codec = socdev->card->codec; struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); dac33->substream = NULL; } static int dac33_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) Loading Loading @@ -791,6 +842,16 @@ static int dac33_prepare_chip(struct snd_pcm_substream *substream) } mutex_lock(&dac33->mutex); if (!dac33->chip_power) { /* * Chip is not powered yet. * Do the init in the dac33_set_bias_level later. */ mutex_unlock(&dac33->mutex); return 0; } dac33_soft_power(codec, 0); dac33_soft_power(codec, 1); Loading Loading @@ -997,15 +1058,6 @@ static void dac33_calculate_times(struct snd_pcm_substream *substream) } static int dac33_pcm_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { dac33_calculate_times(substream); dac33_prepare_chip(substream); return 0; } static int dac33_pcm_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { Loading Loading @@ -1269,35 +1321,6 @@ static int dac33_set_dai_fmt(struct snd_soc_dai *codec_dai, return 0; } static void dac33_init_chip(struct snd_soc_codec *codec) { /* 44-46: DAC Control Registers */ /* A : DAC sample rate Fsref/1.5 */ dac33_write(codec, DAC33_DAC_CTRL_A, DAC33_DACRATE(0)); /* B : DAC src=normal, not muted */ dac33_write(codec, DAC33_DAC_CTRL_B, DAC33_DACSRCR_RIGHT | DAC33_DACSRCL_LEFT); /* C : (defaults) */ dac33_write(codec, DAC33_DAC_CTRL_C, 0x00); /* 64-65 : L&R DAC power control Line In -> OUT 1V/V Gain, DAC -> OUT 4V/V Gain*/ dac33_write(codec, DAC33_LDAC_PWR_CTRL, DAC33_LROUT_GAIN(2)); dac33_write(codec, DAC33_RDAC_PWR_CTRL, DAC33_LROUT_GAIN(2)); /* 73 : volume soft stepping control, clock source = internal osc (?) */ dac33_write(codec, DAC33_ANA_VOL_SOFT_STEP_CTRL, DAC33_VOLCLKEN); /* 66 : LOP/LOM Modes */ dac33_write(codec, DAC33_OUT_AMP_CM_CTRL, 0xff); /* 68 : LOM inverted from LOP */ dac33_write(codec, DAC33_OUT_AMP_CTRL, (3<<2)); dac33_write(codec, DAC33_PWR_CTRL, DAC33_PDNALLB); } static int dac33_soc_probe(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); Loading @@ -1311,11 +1334,6 @@ static int dac33_soc_probe(struct platform_device *pdev) socdev->card->codec = codec; dac33 = snd_soc_codec_get_drvdata(codec); /* Power up the codec */ dac33_hard_power(codec, 1); /* Set default configuration */ dac33_init_chip(codec); /* register pcms */ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); if (ret < 0) { Loading @@ -1332,12 +1350,6 @@ static int dac33_soc_probe(struct platform_device *pdev) dac33_add_widgets(codec); /* power on device */ dac33_set_bias_level(codec, SND_SOC_BIAS_STANDBY); /* Bias level configuration has enabled regulator an extra time */ regulator_bulk_disable(ARRAY_SIZE(dac33->supplies), dac33->supplies); return 0; pcm_err: Loading Loading @@ -1374,6 +1386,8 @@ static int dac33_soc_resume(struct platform_device *pdev) struct snd_soc_codec *codec = socdev->card->codec; dac33_set_bias_level(codec, SND_SOC_BIAS_STANDBY); if (codec->suspend_bias_level == SND_SOC_BIAS_ON) dac33_set_bias_level(codec, SND_SOC_BIAS_PREPARE); dac33_set_bias_level(codec, codec->suspend_bias_level); return 0; Loading @@ -1392,8 +1406,9 @@ EXPORT_SYMBOL_GPL(soc_codec_dev_tlv320dac33); #define DAC33_FORMATS SNDRV_PCM_FMTBIT_S16_LE static struct snd_soc_dai_ops dac33_dai_ops = { .startup = dac33_startup, .shutdown = dac33_shutdown, .hw_params = dac33_hw_params, .prepare = dac33_pcm_prepare, .trigger = dac33_pcm_trigger, .delay = dac33_dai_delay, .set_sysclk = dac33_set_dai_sysclk, Loading Loading @@ -1447,6 +1462,7 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client, codec->hw_write = (hw_write_t) i2c_master_send; codec->bias_level = SND_SOC_BIAS_OFF; codec->set_bias_level = dac33_set_bias_level; codec->idle_bias_off = 1; codec->dai = &dac33_dai; codec->num_dai = 1; codec->reg_cache_size = ARRAY_SIZE(dac33_reg); Loading Loading @@ -1487,8 +1503,6 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client, goto error_gpio; } gpio_direction_output(dac33->power_gpio, 0); } else { dac33->chip_power = 1; } /* Check if the IRQ number is valid and request it */ Loading Loading @@ -1526,12 +1540,14 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client, goto err_get; } ret = regulator_bulk_enable(ARRAY_SIZE(dac33->supplies), dac33->supplies); /* Read the tlv320dac33 ID registers */ ret = dac33_hard_power(codec, 1); if (ret != 0) { dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); goto err_enable; dev_err(codec->dev, "Failed to power up codec: %d\n", ret); goto error_codec; } dac33_read_id(codec); dac33_hard_power(codec, 0); ret = snd_soc_register_codec(codec); if (ret != 0) { Loading @@ -1546,14 +1562,9 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client, goto error_codec; } /* Shut down the codec for now */ dac33_hard_power(codec, 0); return ret; error_codec: regulator_bulk_disable(ARRAY_SIZE(dac33->supplies), dac33->supplies); err_enable: regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies); err_get: if (dac33->irq >= 0) { Loading @@ -1577,6 +1588,8 @@ static int __devexit dac33_i2c_remove(struct i2c_client *client) struct tlv320dac33_priv *dac33; dac33 = i2c_get_clientdata(client); if (unlikely(dac33->chip_power)) dac33_hard_power(&dac33->codec, 0); if (dac33->power_gpio >= 0) Loading
sound/soc/codecs/tpa6130a2.c +92 −7 Original line number Diff line number Diff line Loading @@ -46,6 +46,9 @@ static const char *tpa6140a2_supply_names[TPA6130A2_NUM_SUPPLIES] = { "AVdd", }; #define TPA6130A2_GAIN_MAX 0x3f #define TPA6140A2_GAIN_MAX 0x1f /* This struct is used to save the context */ struct tpa6130a2_data { struct mutex mutex; Loading @@ -53,6 +56,8 @@ struct tpa6130a2_data { struct regulator_bulk_data supplies[TPA6130A2_NUM_SUPPLIES]; int power_gpio; unsigned char power_state; enum tpa_model id; int gain_limit; }; static int tpa6130a2_i2c_read(int reg) Loading Loading @@ -175,6 +180,40 @@ static int tpa6130a2_power(int power) return ret; } static int tpa6130a2_info_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; struct tpa6130a2_data *data; BUG_ON(tpa6130a2_client == NULL); data = i2c_get_clientdata(tpa6130a2_client); mutex_lock(&data->mutex); switch (mc->reg) { case TPA6130A2_REG_VOL_MUTE: if (data->gain_limit != mc->max) mc->max = data->gain_limit; break; default: dev_err(&tpa6130a2_client->dev, "Invalid register: 0x02%x\n", mc->reg); goto out; } if (unlikely(mc->max == 1)) uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; else uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 1; uinfo->value.integer.min = 0; uinfo->value.integer.max = mc->max; out: mutex_unlock(&data->mutex); return 0; } static int tpa6130a2_get_reg(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { Loading Loading @@ -238,6 +277,15 @@ static int tpa6130a2_set_reg(struct snd_kcontrol *kcontrol, return 1; } #define SOC_SINGLE_EXT_TLV_TPA(xname, xreg, xshift, xmax, 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 = tpa6130a2_info_volsw, \ .get = tpa6130a2_get_reg, .put = tpa6130a2_set_reg, \ .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) } /* * TPA6130 volume. From -59.5 to 4 dB with increasing step size when going * down in gain. Loading @@ -257,12 +305,24 @@ static const unsigned int tpa6130_tlv[] = { }; static const struct snd_kcontrol_new tpa6130a2_controls[] = { SOC_SINGLE_EXT_TLV("TPA6130A2 Headphone Playback Volume", TPA6130A2_REG_VOL_MUTE, 0, 0x3f, 0, tpa6130a2_get_reg, tpa6130a2_set_reg, SOC_SINGLE_EXT_TLV_TPA("TPA6130A2 Headphone Playback Volume", TPA6130A2_REG_VOL_MUTE, 0, TPA6130A2_GAIN_MAX, 0, tpa6130_tlv), }; static const unsigned int tpa6140_tlv[] = { TLV_DB_RANGE_HEAD(3), 0, 8, TLV_DB_SCALE_ITEM(-5900, 400, 0), 9, 16, TLV_DB_SCALE_ITEM(-2500, 200, 0), 17, 31, TLV_DB_SCALE_ITEM(-1000, 100, 0), }; static const struct snd_kcontrol_new tpa6140a2_controls[] = { SOC_SINGLE_EXT_TLV_TPA("TPA6140A2 Headphone Playback Volume", TPA6130A2_REG_VOL_MUTE, 1, TPA6140A2_GAIN_MAX, 0, tpa6140_tlv), }; /* * Enable or disable channel (left or right) * The bit number for mute and amplifier are the same per channel: Loading Loading @@ -368,11 +428,20 @@ static const struct snd_soc_dapm_route audio_map[] = { int tpa6130a2_add_controls(struct snd_soc_codec *codec) { struct tpa6130a2_data *data; BUG_ON(tpa6130a2_client == NULL); data = i2c_get_clientdata(tpa6130a2_client); snd_soc_dapm_new_controls(codec, tpa6130a2_dapm_widgets, ARRAY_SIZE(tpa6130a2_dapm_widgets)); snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); if (data->id == TPA6140A2) return snd_soc_add_controls(codec, tpa6140a2_controls, ARRAY_SIZE(tpa6140a2_controls)); else return snd_soc_add_controls(codec, tpa6130a2_controls, ARRAY_SIZE(tpa6130a2_controls)); Loading Loading @@ -407,6 +476,7 @@ static int __devinit tpa6130a2_probe(struct i2c_client *client, pdata = client->dev.platform_data; data->power_gpio = pdata->power_gpio; data->id = pdata->id; mutex_init(&data->mutex); Loading @@ -425,20 +495,35 @@ static int __devinit tpa6130a2_probe(struct i2c_client *client, gpio_direction_output(data->power_gpio, 0); } switch (pdata->id) { switch (data->id) { case TPA6130A2: for (i = 0; i < ARRAY_SIZE(data->supplies); i++) data->supplies[i].supply = tpa6130a2_supply_names[i]; if (pdata->limit_gain > 0 && pdata->limit_gain < TPA6130A2_GAIN_MAX) data->gain_limit = pdata->limit_gain; else data->gain_limit = TPA6130A2_GAIN_MAX; break; case TPA6140A2: for (i = 0; i < ARRAY_SIZE(data->supplies); i++) data->supplies[i].supply = tpa6140a2_supply_names[i];; if (pdata->limit_gain > 0 && pdata->limit_gain < TPA6140A2_GAIN_MAX) data->gain_limit = pdata->limit_gain; else data->gain_limit = TPA6140A2_GAIN_MAX; break; default: dev_warn(dev, "Unknown TPA model (%d). Assuming 6130A2\n", pdata->id); for (i = 0; i < ARRAY_SIZE(data->supplies); i++) data->supplies[i].supply = tpa6130a2_supply_names[i]; if (pdata->limit_gain > 0 && pdata->limit_gain < TPA6130A2_GAIN_MAX) data->gain_limit = pdata->limit_gain; else data->gain_limit = TPA6130A2_GAIN_MAX; } ret = regulator_bulk_get(dev, ARRAY_SIZE(data->supplies), Loading