aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/soc/codecs/wm8915.c82
1 files changed, 53 insertions, 29 deletions
diff --git a/sound/soc/codecs/wm8915.c b/sound/soc/codecs/wm8915.c
index a1d8618f7e2e..423baa9be241 100644
--- a/sound/soc/codecs/wm8915.c
+++ b/sound/soc/codecs/wm8915.c
@@ -75,6 +75,7 @@ struct wm8915_priv {
75 struct wm8915_pdata pdata; 75 struct wm8915_pdata pdata;
76 76
77 int rx_rate[WM8915_AIFS]; 77 int rx_rate[WM8915_AIFS];
78 int bclk_rate[WM8915_AIFS];
78 79
79 /* Platform dependant ReTune mobile configuration */ 80 /* Platform dependant ReTune mobile configuration */
80 int num_retune_mobile_texts; 81 int num_retune_mobile_texts;
@@ -1562,6 +1563,50 @@ static int wm8915_reset(struct snd_soc_codec *codec)
1562 return snd_soc_write(codec, WM8915_SOFTWARE_RESET, 0x8915); 1563 return snd_soc_write(codec, WM8915_SOFTWARE_RESET, 0x8915);
1563} 1564}
1564 1565
1566static const int bclk_divs[] = {
1567 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96
1568};
1569
1570static void wm8915_update_bclk(struct snd_soc_codec *codec)
1571{
1572 struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec);
1573 int aif, best, cur_val, bclk_rate, bclk_reg, i;
1574
1575 /* Don't bother if we're in a low frequency idle mode that
1576 * can't support audio.
1577 */
1578 if (wm8915->sysclk < 64000)
1579 return;
1580
1581 for (aif = 0; aif < WM8915_AIFS; aif++) {
1582 switch (aif) {
1583 case 0:
1584 bclk_reg = WM8915_AIF1_BCLK;
1585 break;
1586 case 1:
1587 bclk_reg = WM8915_AIF2_BCLK;
1588 break;
1589 }
1590
1591 bclk_rate = wm8915->bclk_rate[aif];
1592
1593 /* Pick a divisor for BCLK as close as we can get to ideal */
1594 best = 0;
1595 for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) {
1596 cur_val = (wm8915->sysclk / bclk_divs[i]) - bclk_rate;
1597 if (cur_val < 0) /* BCLK table is sorted */
1598 break;
1599 best = i;
1600 }
1601 bclk_rate = wm8915->sysclk / bclk_divs[best];
1602 dev_dbg(codec->dev, "Using BCLK_DIV %d for actual BCLK %dHz\n",
1603 bclk_divs[best], bclk_rate);
1604
1605 snd_soc_update_bits(codec, bclk_reg,
1606 WM8915_AIF1_BCLK_DIV_MASK, best);
1607 }
1608}
1609
1565static int wm8915_set_bias_level(struct snd_soc_codec *codec, 1610static int wm8915_set_bias_level(struct snd_soc_codec *codec,
1566 enum snd_soc_bias_level level) 1611 enum snd_soc_bias_level level)
1567{ 1612{
@@ -1714,10 +1759,6 @@ static int wm8915_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
1714 return 0; 1759 return 0;
1715} 1760}
1716 1761
1717static const int bclk_divs[] = {
1718 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96
1719};
1720
1721static const int dsp_divs[] = { 1762static const int dsp_divs[] = {
1722 48000, 32000, 16000, 8000 1763 48000, 32000, 16000, 8000
1723}; 1764};
@@ -1728,17 +1769,11 @@ static int wm8915_hw_params(struct snd_pcm_substream *substream,
1728{ 1769{
1729 struct snd_soc_codec *codec = dai->codec; 1770 struct snd_soc_codec *codec = dai->codec;
1730 struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec); 1771 struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec);
1731 int bits, i, bclk_rate, best, cur_val; 1772 int bits, i, bclk_rate;
1732 int aifdata = 0; 1773 int aifdata = 0;
1733 int bclk = 0;
1734 int lrclk = 0; 1774 int lrclk = 0;
1735 int dsp = 0; 1775 int dsp = 0;
1736 int aifdata_reg, bclk_reg, lrclk_reg, dsp_shift; 1776 int aifdata_reg, lrclk_reg, dsp_shift;
1737
1738 if (!wm8915->sysclk) {
1739 dev_err(codec->dev, "SYSCLK not configured\n");
1740 return -EINVAL;
1741 }
1742 1777
1743 switch (dai->id) { 1778 switch (dai->id) {
1744 case 0: 1779 case 0:
@@ -1750,7 +1785,6 @@ static int wm8915_hw_params(struct snd_pcm_substream *substream,
1750 aifdata_reg = WM8915_AIF1TX_DATA_CONFIGURATION_1; 1785 aifdata_reg = WM8915_AIF1TX_DATA_CONFIGURATION_1;
1751 lrclk_reg = WM8915_AIF1_TX_LRCLK_1; 1786 lrclk_reg = WM8915_AIF1_TX_LRCLK_1;
1752 } 1787 }
1753 bclk_reg = WM8915_AIF1_BCLK;
1754 dsp_shift = 0; 1788 dsp_shift = 0;
1755 break; 1789 break;
1756 case 1: 1790 case 1:
@@ -1762,7 +1796,6 @@ static int wm8915_hw_params(struct snd_pcm_substream *substream,
1762 aifdata_reg = WM8915_AIF2TX_DATA_CONFIGURATION_1; 1796 aifdata_reg = WM8915_AIF2TX_DATA_CONFIGURATION_1;
1763 lrclk_reg = WM8915_AIF2_TX_LRCLK_1; 1797 lrclk_reg = WM8915_AIF2_TX_LRCLK_1;
1764 } 1798 }
1765 bclk_reg = WM8915_AIF2_BCLK;
1766 dsp_shift = WM8915_DSP2_DIV_SHIFT; 1799 dsp_shift = WM8915_DSP2_DIV_SHIFT;
1767 break; 1800 break;
1768 default: 1801 default:
@@ -1776,6 +1809,9 @@ static int wm8915_hw_params(struct snd_pcm_substream *substream,
1776 return bclk_rate; 1809 return bclk_rate;
1777 } 1810 }
1778 1811
1812 wm8915->bclk_rate[dai->id] = bclk_rate;
1813 wm8915->rx_rate[dai->id] = params_rate(params);
1814
1779 /* Needs looking at for TDM */ 1815 /* Needs looking at for TDM */
1780 bits = snd_pcm_format_width(params_format(params)); 1816 bits = snd_pcm_format_width(params_format(params));
1781 if (bits < 0) 1817 if (bits < 0)
@@ -1793,18 +1829,7 @@ static int wm8915_hw_params(struct snd_pcm_substream *substream,
1793 } 1829 }
1794 dsp |= i << dsp_shift; 1830 dsp |= i << dsp_shift;
1795 1831
1796 /* Pick a divisor for BCLK as close as we can get to ideal */ 1832 wm8915_update_bclk(codec);
1797 best = 0;
1798 for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) {
1799 cur_val = (wm8915->sysclk / bclk_divs[i]) - bclk_rate;
1800 if (cur_val < 0) /* BCLK table is sorted */
1801 break;
1802 best = i;
1803 }
1804 bclk_rate = wm8915->sysclk / bclk_divs[best];
1805 dev_dbg(dai->dev, "Using BCLK_DIV %d for actual BCLK %dHz\n",
1806 bclk_divs[best], bclk_rate);
1807 bclk |= best;
1808 1833
1809 lrclk = bclk_rate / params_rate(params); 1834 lrclk = bclk_rate / params_rate(params);
1810 dev_dbg(dai->dev, "Using LRCLK rate %d for actual LRCLK %dHz\n", 1835 dev_dbg(dai->dev, "Using LRCLK rate %d for actual LRCLK %dHz\n",
@@ -1814,14 +1839,11 @@ static int wm8915_hw_params(struct snd_pcm_substream *substream,
1814 WM8915_AIF1TX_WL_MASK | 1839 WM8915_AIF1TX_WL_MASK |
1815 WM8915_AIF1TX_SLOT_LEN_MASK, 1840 WM8915_AIF1TX_SLOT_LEN_MASK,
1816 aifdata); 1841 aifdata);
1817 snd_soc_update_bits(codec, bclk_reg, WM8915_AIF1_BCLK_DIV_MASK, bclk);
1818 snd_soc_update_bits(codec, lrclk_reg, WM8915_AIF1RX_RATE_MASK, 1842 snd_soc_update_bits(codec, lrclk_reg, WM8915_AIF1RX_RATE_MASK,
1819 lrclk); 1843 lrclk);
1820 snd_soc_update_bits(codec, WM8915_AIF_CLOCKING_2, 1844 snd_soc_update_bits(codec, WM8915_AIF_CLOCKING_2,
1821 WM8915_DSP1_DIV_SHIFT << dsp_shift, dsp); 1845 WM8915_DSP1_DIV_SHIFT << dsp_shift, dsp);
1822 1846
1823 wm8915->rx_rate[dai->id] = params_rate(params);
1824
1825 return 0; 1847 return 0;
1826} 1848}
1827 1849
@@ -1882,6 +1904,8 @@ static int wm8915_set_sysclk(struct snd_soc_dai *dai,
1882 return -EINVAL; 1904 return -EINVAL;
1883 } 1905 }
1884 1906
1907 wm8915_update_bclk(codec);
1908
1885 snd_soc_update_bits(codec, WM8915_AIF_CLOCKING_1, 1909 snd_soc_update_bits(codec, WM8915_AIF_CLOCKING_1,
1886 WM8915_SYSCLK_SRC_MASK | WM8915_SYSCLK_DIV_MASK, 1910 WM8915_SYSCLK_SRC_MASK | WM8915_SYSCLK_DIV_MASK,
1887 src << WM8915_SYSCLK_SRC_SHIFT | ratediv); 1911 src << WM8915_SYSCLK_SRC_SHIFT | ratediv);