Merge branch 'topic/asoc' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6 into for-2.6.38
This commit is contained in:
@@ -60,6 +60,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 {
|
||||||
@@ -76,6 +78,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;
|
||||||
@@ -1076,7 +1079,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;
|
||||||
}
|
}
|
||||||
@@ -1103,7 +1106,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);
|
||||||
}
|
}
|
||||||
@@ -1345,11 +1348,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;
|
||||||
@@ -1360,7 +1377,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;
|
||||||
@@ -1406,6 +1424,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;
|
||||||
|
|
||||||
@@ -1415,7 +1434,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;
|
||||||
@@ -1427,7 +1447,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);
|
||||||
}
|
}
|
||||||
|
@@ -127,9 +127,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) {
|
||||||
@@ -137,6 +134,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();
|
||||||
|
@@ -232,6 +232,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);
|
||||||
@@ -337,10 +347,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) &&
|
||||||
@@ -724,9 +738,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 */
|
||||||
@@ -750,16 +767,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),
|
||||||
@@ -834,7 +849,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2257,9 +2272,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2291,10 +2309,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user