diff options
Diffstat (limited to 'sound/soc/codecs/wm8903.c')
-rw-r--r-- | sound/soc/codecs/wm8903.c | 48 |
1 files changed, 29 insertions, 19 deletions
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index 43e3d760766..0218d6ce055 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c | |||
@@ -1268,9 +1268,9 @@ static int wm8903_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
1268 | aif1 |= 0x2; | 1268 | aif1 |= 0x2; |
1269 | break; | 1269 | break; |
1270 | case SND_SOC_DAIFMT_RIGHT_J: | 1270 | case SND_SOC_DAIFMT_RIGHT_J: |
1271 | aif1 |= 0x1; | ||
1272 | break; | 1271 | break; |
1273 | case SND_SOC_DAIFMT_LEFT_J: | 1272 | case SND_SOC_DAIFMT_LEFT_J: |
1273 | aif1 |= 0x1; | ||
1274 | break; | 1274 | break; |
1275 | default: | 1275 | default: |
1276 | return -EINVAL; | 1276 | return -EINVAL; |
@@ -1457,6 +1457,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, | |||
1457 | int fs = params_rate(params); | 1457 | int fs = params_rate(params); |
1458 | int bclk; | 1458 | int bclk; |
1459 | int bclk_div; | 1459 | int bclk_div; |
1460 | int real_bclk_div; | ||
1460 | int i; | 1461 | int i; |
1461 | int dsp_config; | 1462 | int dsp_config; |
1462 | int clk_config; | 1463 | int clk_config; |
@@ -1493,7 +1494,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, | |||
1493 | clock1 |= sample_rates[dsp_config].value; | 1494 | clock1 |= sample_rates[dsp_config].value; |
1494 | 1495 | ||
1495 | aif1 &= ~WM8903_AIF_WL_MASK; | 1496 | aif1 &= ~WM8903_AIF_WL_MASK; |
1496 | bclk = 2 * fs; | 1497 | bclk = 4 * fs; |
1497 | switch (params_format(params)) { | 1498 | switch (params_format(params)) { |
1498 | case SNDRV_PCM_FORMAT_S16_LE: | 1499 | case SNDRV_PCM_FORMAT_S16_LE: |
1499 | bclk *= 16; | 1500 | bclk *= 16; |
@@ -1561,27 +1562,22 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, | |||
1561 | * higher than the target (we need to ensure that there enough | 1562 | * higher than the target (we need to ensure that there enough |
1562 | * BCLKs to clock out the samples). | 1563 | * BCLKs to clock out the samples). |
1563 | */ | 1564 | */ |
1564 | bclk_div = 0; | ||
1565 | best_val = ((clk_sys * 10) / bclk_divs[0].ratio) - bclk; | ||
1566 | i = 1; | ||
1567 | while (i < ARRAY_SIZE(bclk_divs)) { | ||
1568 | cur_val = ((clk_sys * 10) / bclk_divs[i].ratio) - bclk; | ||
1569 | if (cur_val < 0) /* BCLK table is sorted */ | ||
1570 | break; | ||
1571 | bclk_div = i; | ||
1572 | best_val = cur_val; | ||
1573 | i++; | ||
1574 | } | ||
1575 | 1565 | ||
1576 | aif2 &= ~WM8903_BCLK_DIV_MASK; | 1566 | aif2 &= ~WM8903_BCLK_DIV_MASK; |
1577 | aif3 &= ~WM8903_LRCLK_RATE_MASK; | 1567 | aif3 &= ~WM8903_LRCLK_RATE_MASK; |
1578 | 1568 | ||
1579 | dev_dbg(codec->dev, "BCLK ratio %d for %dHz - actual BCLK = %dHz\n", | 1569 | bclk_div = real_bclk_div = 0; |
1580 | bclk_divs[bclk_div].ratio / 10, bclk, | 1570 | cur_val = clk_sys; |
1581 | (clk_sys * 10) / bclk_divs[bclk_div].ratio); | 1571 | best_val = clk_sys; |
1582 | 1572 | while(!(best_val % fs) && | |
1583 | aif2 |= bclk_divs[bclk_div].div; | 1573 | (cur_val >= bclk)){ |
1584 | aif3 |= bclk / fs; | 1574 | real_bclk_div = bclk_div; |
1575 | bclk_div++; | ||
1576 | cur_val = best_val; | ||
1577 | best_val /= 2; | ||
1578 | } | ||
1579 | aif2 |= (real_bclk_div ? 1<<real_bclk_div : 0); | ||
1580 | aif3 |= cur_val / fs; | ||
1585 | 1581 | ||
1586 | wm8903->fs = params_rate(params); | 1582 | wm8903->fs = params_rate(params); |
1587 | wm8903_set_deemph(codec); | 1583 | wm8903_set_deemph(codec); |
@@ -1761,6 +1757,11 @@ static struct snd_soc_dai_driver wm8903_dai = { | |||
1761 | 1757 | ||
1762 | static int wm8903_suspend(struct snd_soc_codec *codec, pm_message_t state) | 1758 | static int wm8903_suspend(struct snd_soc_codec *codec, pm_message_t state) |
1763 | { | 1759 | { |
1760 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | ||
1761 | |||
1762 | if (wm8903->irq) | ||
1763 | disable_irq(wm8903->irq); | ||
1764 | |||
1764 | wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1765 | wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1765 | 1766 | ||
1766 | return 0; | 1767 | return 0; |
@@ -1768,11 +1769,15 @@ static int wm8903_suspend(struct snd_soc_codec *codec, pm_message_t state) | |||
1768 | 1769 | ||
1769 | static int wm8903_resume(struct snd_soc_codec *codec) | 1770 | static int wm8903_resume(struct snd_soc_codec *codec) |
1770 | { | 1771 | { |
1772 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | ||
1771 | int i; | 1773 | int i; |
1772 | u16 *reg_cache = codec->reg_cache; | 1774 | u16 *reg_cache = codec->reg_cache; |
1773 | u16 *tmp_cache = kmemdup(reg_cache, sizeof(wm8903_reg_defaults), | 1775 | u16 *tmp_cache = kmemdup(reg_cache, sizeof(wm8903_reg_defaults), |
1774 | GFP_KERNEL); | 1776 | GFP_KERNEL); |
1775 | 1777 | ||
1778 | if (wm8903->irq) | ||
1779 | enable_irq(wm8903->irq); | ||
1780 | |||
1776 | /* Bring the codec back up to standby first to minimise pop/clicks */ | 1781 | /* Bring the codec back up to standby first to minimise pop/clicks */ |
1777 | wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1782 | wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1778 | 1783 | ||
@@ -2046,8 +2051,13 @@ static int wm8903_probe(struct snd_soc_codec *codec) | |||
2046 | /* power down chip */ | 2051 | /* power down chip */ |
2047 | static int wm8903_remove(struct snd_soc_codec *codec) | 2052 | static int wm8903_remove(struct snd_soc_codec *codec) |
2048 | { | 2053 | { |
2054 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | ||
2055 | |||
2049 | wm8903_free_gpio(codec); | 2056 | wm8903_free_gpio(codec); |
2050 | wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); | 2057 | wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); |
2058 | if (wm8903->irq) | ||
2059 | free_irq(wm8903->irq, codec); | ||
2060 | |||
2051 | return 0; | 2061 | return 0; |
2052 | } | 2062 | } |
2053 | 2063 | ||