Merge branch 'for-2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/lrg/asoc-2.6 into topic/asoc

Conflicts:
	sound/soc/codecs/tpa6130a2.c
This commit is contained in:
Takashi Iwai 2010-11-23 12:45:05 +01:00
commit 2ab46c9390
3 changed files with 56 additions and 19 deletions

View File

@ -61,6 +61,8 @@ static const char *aic3x_supply_names[AIC3X_NUM_SUPPLIES] = {
"DRVDD", /* ADC Analog and Output Driver Voltage */ "DRVDD", /* ADC Analog and Output Driver Voltage */
}; };
static LIST_HEAD(reset_list);
struct aic3x_priv; struct aic3x_priv;
struct aic3x_disable_nb { struct aic3x_disable_nb {
@ -77,6 +79,7 @@ struct aic3x_priv {
struct aic3x_setup_data *setup; struct aic3x_setup_data *setup;
void *control_data; void *control_data;
unsigned int sysclk; unsigned int sysclk;
struct list_head list;
int master; int master;
int gpio_reset; int gpio_reset;
int power; int power;
@ -1077,7 +1080,7 @@ static int aic3x_regulator_event(struct notifier_block *nb,
* Put codec to reset and require cache sync as at least one * Put codec to reset and require cache sync as at least one
* of the supplies was disabled * of the supplies was disabled
*/ */
if (aic3x->gpio_reset >= 0) if (gpio_is_valid(aic3x->gpio_reset))
gpio_set_value(aic3x->gpio_reset, 0); gpio_set_value(aic3x->gpio_reset, 0);
aic3x->codec->cache_sync = 1; aic3x->codec->cache_sync = 1;
} }
@ -1104,7 +1107,7 @@ static int aic3x_set_power(struct snd_soc_codec *codec, int power)
if (!codec->cache_sync) if (!codec->cache_sync)
goto out; goto out;
if (aic3x->gpio_reset >= 0) { if (gpio_is_valid(aic3x->gpio_reset)) {
udelay(1); udelay(1);
gpio_set_value(aic3x->gpio_reset, 1); gpio_set_value(aic3x->gpio_reset, 1);
} }
@ -1346,11 +1349,25 @@ static int aic3x_init(struct snd_soc_codec *codec)
return 0; return 0;
} }
static bool aic3x_is_shared_reset(struct aic3x_priv *aic3x)
{
struct aic3x_priv *a;
list_for_each_entry(a, &reset_list, list) {
if (gpio_is_valid(aic3x->gpio_reset) &&
aic3x->gpio_reset == a->gpio_reset)
return true;
}
return false;
}
static int aic3x_probe(struct snd_soc_codec *codec) static int aic3x_probe(struct snd_soc_codec *codec)
{ {
struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
int ret, i; int ret, i;
INIT_LIST_HEAD(&aic3x->list);
codec->control_data = aic3x->control_data; codec->control_data = aic3x->control_data;
aic3x->codec = codec; aic3x->codec = codec;
codec->dapm.idle_bias_off = 1; codec->dapm.idle_bias_off = 1;
@ -1361,7 +1378,8 @@ static int aic3x_probe(struct snd_soc_codec *codec)
return ret; return ret;
} }
if (aic3x->gpio_reset >= 0) { if (gpio_is_valid(aic3x->gpio_reset) &&
!aic3x_is_shared_reset(aic3x)) {
ret = gpio_request(aic3x->gpio_reset, "tlv320aic3x reset"); ret = gpio_request(aic3x->gpio_reset, "tlv320aic3x reset");
if (ret != 0) if (ret != 0)
goto err_gpio; goto err_gpio;
@ -1407,6 +1425,7 @@ static int aic3x_probe(struct snd_soc_codec *codec)
snd_soc_add_controls(codec, &aic3x_classd_amp_gain_ctrl, 1); snd_soc_add_controls(codec, &aic3x_classd_amp_gain_ctrl, 1);
aic3x_add_widgets(codec); aic3x_add_widgets(codec);
list_add(&aic3x->list, &reset_list);
return 0; return 0;
@ -1416,7 +1435,8 @@ err_notif:
&aic3x->disable_nb[i].nb); &aic3x->disable_nb[i].nb);
regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
err_get: err_get:
if (aic3x->gpio_reset >= 0) if (gpio_is_valid(aic3x->gpio_reset) &&
!aic3x_is_shared_reset(aic3x))
gpio_free(aic3x->gpio_reset); gpio_free(aic3x->gpio_reset);
err_gpio: err_gpio:
return ret; return ret;
@ -1428,7 +1448,9 @@ static int aic3x_remove(struct snd_soc_codec *codec)
int i; int i;
aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF); aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF);
if (aic3x->gpio_reset >= 0) { list_del(&aic3x->list);
if (gpio_is_valid(aic3x->gpio_reset) &&
!aic3x_is_shared_reset(aic3x)) {
gpio_set_value(aic3x->gpio_reset, 0); gpio_set_value(aic3x->gpio_reset, 0);
gpio_free(aic3x->gpio_reset); gpio_free(aic3x->gpio_reset);
} }

View File

@ -126,9 +126,6 @@ static int tpa6130a2_power(int power)
mutex_lock(&data->mutex); mutex_lock(&data->mutex);
if (power && !data->power_state) { if (power && !data->power_state) {
/* Power on */
if (data->power_gpio >= 0)
gpio_set_value(data->power_gpio, 1);
ret = regulator_enable(data->supply); ret = regulator_enable(data->supply);
if (ret != 0) { if (ret != 0) {
@ -136,6 +133,9 @@ static int tpa6130a2_power(int power)
"Failed to enable supply: %d\n", ret); "Failed to enable supply: %d\n", ret);
goto exit; goto exit;
} }
/* Power on */
if (data->power_gpio >= 0)
gpio_set_value(data->power_gpio, 1);
data->power_state = 1; data->power_state = 1;
ret = tpa6130a2_initialize(); ret = tpa6130a2_initialize();

View File

@ -233,6 +233,16 @@ static int twl4030_write(struct snd_soc_codec *codec,
return 0; return 0;
} }
static inline void twl4030_wait_ms(int time)
{
if (time < 60) {
time *= 1000;
usleep_range(time, time + 500);
} else {
msleep(time);
}
}
static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable) static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable)
{ {
struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
@ -338,10 +348,14 @@ static void twl4030_init_chip(struct snd_soc_codec *codec)
twl4030_write(codec, TWL4030_REG_ANAMICL, twl4030_write(codec, TWL4030_REG_ANAMICL,
reg | TWL4030_CNCL_OFFSET_START); reg | TWL4030_CNCL_OFFSET_START);
/* wait for offset cancellation to complete */ /*
* Wait for offset cancellation to complete.
* Since this takes a while, do not slam the i2c.
* Start polling the status after ~20ms.
*/
msleep(20);
do { do {
/* this takes a little while, so don't slam i2c */ usleep_range(1000, 2000);
udelay(2000);
twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte, twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte,
TWL4030_REG_ANAMICL); TWL4030_REG_ANAMICL);
} while ((i++ < 100) && } while ((i++ < 100) &&
@ -725,9 +739,12 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp)
/* Base values for ramp delay calculation: 2^19 - 2^26 */ /* Base values for ramp delay calculation: 2^19 - 2^26 */
unsigned int ramp_base[] = {524288, 1048576, 2097152, 4194304, unsigned int ramp_base[] = {524288, 1048576, 2097152, 4194304,
8388608, 16777216, 33554432, 67108864}; 8388608, 16777216, 33554432, 67108864};
unsigned int delay;
hs_gain = twl4030_read_reg_cache(codec, TWL4030_REG_HS_GAIN_SET); hs_gain = twl4030_read_reg_cache(codec, TWL4030_REG_HS_GAIN_SET);
hs_pop = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET); hs_pop = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET);
delay = (ramp_base[(hs_pop & TWL4030_RAMP_DELAY) >> 2] /
twl4030->sysclk) + 1;
/* Enable external mute control, this dramatically reduces /* Enable external mute control, this dramatically reduces
* the pop-noise */ * the pop-noise */
@ -751,16 +768,14 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp)
hs_pop |= TWL4030_RAMP_EN; hs_pop |= TWL4030_RAMP_EN;
twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
/* Wait ramp delay time + 1, so the VMID can settle */ /* Wait ramp delay time + 1, so the VMID can settle */
mdelay((ramp_base[(hs_pop & TWL4030_RAMP_DELAY) >> 2] / twl4030_wait_ms(delay);
twl4030->sysclk) + 1);
} else { } else {
/* Headset ramp-down _not_ according to /* Headset ramp-down _not_ according to
* the TRM, but in a way that it is working */ * the TRM, but in a way that it is working */
hs_pop &= ~TWL4030_RAMP_EN; hs_pop &= ~TWL4030_RAMP_EN;
twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
/* Wait ramp delay time + 1, so the VMID can settle */ /* Wait ramp delay time + 1, so the VMID can settle */
mdelay((ramp_base[(hs_pop & TWL4030_RAMP_DELAY) >> 2] / twl4030_wait_ms(delay);
twl4030->sysclk) + 1);
/* Bypass the reg_cache to mute the headset */ /* Bypass the reg_cache to mute the headset */
twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
hs_gain & (~0x0f), hs_gain & (~0x0f),
@ -835,7 +850,7 @@ static int digimic_event(struct snd_soc_dapm_widget *w,
struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(w->codec); struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(w->codec);
if (twl4030->digimic_delay) if (twl4030->digimic_delay)
mdelay(twl4030->digimic_delay); twl4030_wait_ms(twl4030->digimic_delay);
return 0; return 0;
} }
@ -2258,9 +2273,12 @@ static int twl4030_soc_probe(struct snd_soc_codec *codec)
static int twl4030_soc_remove(struct snd_soc_codec *codec) static int twl4030_soc_remove(struct snd_soc_codec *codec)
{ {
struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
/* Reset registers to their chip default before leaving */ /* Reset registers to their chip default before leaving */
twl4030_reset_registers(codec); twl4030_reset_registers(codec);
twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF); twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF);
kfree(twl4030);
return 0; return 0;
} }
@ -2292,10 +2310,7 @@ static int __devinit twl4030_codec_probe(struct platform_device *pdev)
static int __devexit twl4030_codec_remove(struct platform_device *pdev) static int __devexit twl4030_codec_remove(struct platform_device *pdev)
{ {
struct twl4030_priv *twl4030 = dev_get_drvdata(&pdev->dev);
snd_soc_unregister_codec(&pdev->dev); snd_soc_unregister_codec(&pdev->dev);
kfree(twl4030);
return 0; return 0;
} }