diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index a6cbaf3c51f21cd46988f48b48d3fe0734448b52..08f24de406c204b7344c666363fd3209019db2a1 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -43,7 +43,7 @@ static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = { 0x00, /* this register not used */ 0x00, /* REG_CODEC_MODE (0x1) */ - 0xc3, /* REG_OPTION (0x2) */ + 0x00, /* REG_OPTION (0x2) */ 0x00, /* REG_UNKNOWN (0x3) */ 0x00, /* REG_MICBIAS_CTL (0x4) */ 0x00, /* REG_ANAMICL (0x5) */ @@ -243,62 +243,52 @@ static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable) udelay(10); } -static void twl4030_init_chip(struct snd_soc_codec *codec) -{ - u8 *cache = codec->reg_cache; - int i; - - /* clear CODECPDZ prior to setting register defaults */ - twl4030_codec_enable(codec, 0); - - /* set all audio section registers to reasonable defaults */ - for (i = TWL4030_REG_OPTION; i <= TWL4030_REG_MISC_SET_2; i++) - if (i != TWL4030_REG_APLL_CTL) - twl4030_write(codec, i, cache[i]); - -} - -static void twl4030_apll_enable(struct snd_soc_codec *codec, int enable) +static void twl4030_init_chip(struct platform_device *pdev) { + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct twl4030_setup_data *setup = socdev->codec_data; + struct snd_soc_codec *codec = socdev->card->codec; struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); - int status = -1; + u8 reg, byte; + int i = 0; - if (enable) { - twl4030->apll_enabled++; - if (twl4030->apll_enabled == 1) - status = twl4030_codec_enable_resource( - TWL4030_CODEC_RES_APLL); - } else { - twl4030->apll_enabled--; - if (!twl4030->apll_enabled) - status = twl4030_codec_disable_resource( - TWL4030_CODEC_RES_APLL); - } + /* Refresh APLL_CTL register from HW */ + twl4030_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte, + TWL4030_REG_APLL_CTL); + twl4030_write_reg_cache(codec, TWL4030_REG_APLL_CTL, byte); - if (status >= 0) - twl4030_write_reg_cache(codec, TWL4030_REG_APLL_CTL, status); -} + /* anti-pop when changing analog gain */ + reg = twl4030_read_reg_cache(codec, TWL4030_REG_MISC_SET_1); + twl4030_write(codec, TWL4030_REG_MISC_SET_1, + reg | TWL4030_SMOOTH_ANAVOL_EN); -static void twl4030_power_up(struct snd_soc_codec *codec) -{ - struct snd_soc_device *socdev = codec->socdev; - struct twl4030_setup_data *setup = socdev->codec_data; - struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); - u8 anamicl, regmisc1, byte; - int i = 0; + twl4030_write(codec, TWL4030_REG_OPTION, + TWL4030_ATXL1_EN | TWL4030_ATXR1_EN | + TWL4030_ARXL2_EN | TWL4030_ARXR2_EN); - if (twl4030->codec_powered) + /* Machine dependent setup */ + if (!setup) return; - /* set CODECPDZ to turn on codec */ - twl4030_codec_enable(codec, 1); + /* Configuration for headset ramp delay from setup data */ + if (setup->sysclk != twl4030->sysclk) + dev_warn(codec->dev, + "Mismatch in APLL mclk: %u (configured: %u)\n", + setup->sysclk, twl4030->sysclk); + + reg = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET); + reg &= ~TWL4030_RAMP_DELAY; + reg |= (setup->ramp_delay_value << 2); + twl4030_write_reg_cache(codec, TWL4030_REG_HS_POPN_SET, reg); /* initiate offset cancellation */ - anamicl = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL); - anamicl &= ~TWL4030_OFFSET_CNCL_SEL; - anamicl |= setup->offset_cncl_path; + twl4030_codec_enable(codec, 1); + + reg = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL); + reg &= ~TWL4030_OFFSET_CNCL_SEL; + reg |= setup->offset_cncl_path; twl4030_write(codec, TWL4030_REG_ANAMICL, - anamicl | TWL4030_CNCL_OFFSET_START); + reg | TWL4030_CNCL_OFFSET_START); /* wait for offset cancellation to complete */ do { @@ -313,14 +303,28 @@ static void twl4030_power_up(struct snd_soc_codec *codec) /* Make sure that the reg_cache has the same value as the HW */ twl4030_write_reg_cache(codec, TWL4030_REG_ANAMICL, byte); - /* anti-pop when changing analog gain */ - regmisc1 = twl4030_read_reg_cache(codec, TWL4030_REG_MISC_SET_1); - twl4030_write(codec, TWL4030_REG_MISC_SET_1, - regmisc1 | TWL4030_SMOOTH_ANAVOL_EN); - - /* toggle CODECPDZ as per TRM */ twl4030_codec_enable(codec, 0); - twl4030_codec_enable(codec, 1); +} + +static void twl4030_apll_enable(struct snd_soc_codec *codec, int enable) +{ + struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); + int status = -1; + + if (enable) { + twl4030->apll_enabled++; + if (twl4030->apll_enabled == 1) + status = twl4030_codec_enable_resource( + TWL4030_CODEC_RES_APLL); + } else { + twl4030->apll_enabled--; + if (!twl4030->apll_enabled) + status = twl4030_codec_disable_resource( + TWL4030_CODEC_RES_APLL); + } + + if (status >= 0) + twl4030_write_reg_cache(codec, TWL4030_REG_APLL_CTL, status); } /* Earpiece */ @@ -1599,7 +1603,7 @@ static int twl4030_set_bias_level(struct snd_soc_codec *codec, break; case SND_SOC_BIAS_STANDBY: if (codec->bias_level == SND_SOC_BIAS_OFF) - twl4030_power_up(codec); + twl4030_codec_enable(codec, 1); break; case SND_SOC_BIAS_OFF: twl4030_codec_enable(codec, 0); @@ -2196,31 +2200,16 @@ static struct snd_soc_codec *twl4030_codec; static int twl4030_soc_probe(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct twl4030_setup_data *setup = socdev->codec_data; struct snd_soc_codec *codec; - struct twl4030_priv *twl4030; int ret; BUG_ON(!twl4030_codec); codec = twl4030_codec; - twl4030 = snd_soc_codec_get_drvdata(codec); socdev->card->codec = codec; - /* Configuration for headset ramp delay from setup data */ - if (setup) { - unsigned char hs_pop; - - if (setup->sysclk != twl4030->sysclk) - dev_warn(&pdev->dev, - "Mismatch in APLL mclk: %u (configured: %u)\n", - setup->sysclk, twl4030->sysclk); - - hs_pop = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET); - hs_pop &= ~TWL4030_RAMP_DELAY; - hs_pop |= (setup->ramp_delay_value << 2); - twl4030_write_reg_cache(codec, TWL4030_REG_HS_POPN_SET, hs_pop); - } + twl4030_init_chip(pdev); + twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY); /* register pcms */ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); @@ -2296,9 +2285,7 @@ static int __devinit twl4030_codec_probe(struct platform_device *pdev) /* Set the defaults, and power up the codec */ twl4030->sysclk = twl4030_codec_get_mclk() / 1000; - twl4030_init_chip(codec); codec->bias_level = SND_SOC_BIAS_OFF; - twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY); ret = snd_soc_register_codec(codec); if (ret != 0) {