aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm8915.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/wm8915.c')
-rw-r--r--sound/soc/codecs/wm8915.c156
1 files changed, 110 insertions, 46 deletions
diff --git a/sound/soc/codecs/wm8915.c b/sound/soc/codecs/wm8915.c
index e2ab4fac281..423baa9be24 100644
--- a/sound/soc/codecs/wm8915.c
+++ b/sound/soc/codecs/wm8915.c
@@ -41,14 +41,12 @@
41#define HPOUT2L 4 41#define HPOUT2L 4
42#define HPOUT2R 8 42#define HPOUT2R 8
43 43
44#define WM8915_NUM_SUPPLIES 6 44#define WM8915_NUM_SUPPLIES 4
45static const char *wm8915_supply_names[WM8915_NUM_SUPPLIES] = { 45static const char *wm8915_supply_names[WM8915_NUM_SUPPLIES] = {
46 "DCVDD",
47 "DBVDD", 46 "DBVDD",
48 "AVDD1", 47 "AVDD1",
49 "AVDD2", 48 "AVDD2",
50 "CPVDD", 49 "CPVDD",
51 "MICVDD",
52}; 50};
53 51
54struct wm8915_priv { 52struct wm8915_priv {
@@ -57,6 +55,7 @@ struct wm8915_priv {
57 int ldo1ena; 55 int ldo1ena;
58 56
59 int sysclk; 57 int sysclk;
58 int sysclk_src;
60 59
61 int fll_src; 60 int fll_src;
62 int fll_fref; 61 int fll_fref;
@@ -76,6 +75,7 @@ struct wm8915_priv {
76 struct wm8915_pdata pdata; 75 struct wm8915_pdata pdata;
77 76
78 int rx_rate[WM8915_AIFS]; 77 int rx_rate[WM8915_AIFS];
78 int bclk_rate[WM8915_AIFS];
79 79
80 /* Platform dependant ReTune mobile configuration */ 80 /* Platform dependant ReTune mobile configuration */
81 int num_retune_mobile_texts; 81 int num_retune_mobile_texts;
@@ -113,8 +113,6 @@ WM8915_REGULATOR_EVENT(0)
113WM8915_REGULATOR_EVENT(1) 113WM8915_REGULATOR_EVENT(1)
114WM8915_REGULATOR_EVENT(2) 114WM8915_REGULATOR_EVENT(2)
115WM8915_REGULATOR_EVENT(3) 115WM8915_REGULATOR_EVENT(3)
116WM8915_REGULATOR_EVENT(4)
117WM8915_REGULATOR_EVENT(5)
118 116
119static const u16 wm8915_reg[WM8915_MAX_REGISTER] = { 117static const u16 wm8915_reg[WM8915_MAX_REGISTER] = {
120 [WM8915_SOFTWARE_RESET] = 0x8915, 118 [WM8915_SOFTWARE_RESET] = 0x8915,
@@ -1565,6 +1563,50 @@ static int wm8915_reset(struct snd_soc_codec *codec)
1565 return snd_soc_write(codec, WM8915_SOFTWARE_RESET, 0x8915); 1563 return snd_soc_write(codec, WM8915_SOFTWARE_RESET, 0x8915);
1566} 1564}
1567 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
1568static int wm8915_set_bias_level(struct snd_soc_codec *codec, 1610static int wm8915_set_bias_level(struct snd_soc_codec *codec,
1569 enum snd_soc_bias_level level) 1611 enum snd_soc_bias_level level)
1570{ 1612{
@@ -1717,10 +1759,6 @@ static int wm8915_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
1717 return 0; 1759 return 0;
1718} 1760}
1719 1761
1720static const int bclk_divs[] = {
1721 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96
1722};
1723
1724static const int dsp_divs[] = { 1762static const int dsp_divs[] = {
1725 48000, 32000, 16000, 8000 1763 48000, 32000, 16000, 8000
1726}; 1764};
@@ -1731,17 +1769,11 @@ static int wm8915_hw_params(struct snd_pcm_substream *substream,
1731{ 1769{
1732 struct snd_soc_codec *codec = dai->codec; 1770 struct snd_soc_codec *codec = dai->codec;
1733 struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec); 1771 struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec);
1734 int bits, i, bclk_rate, best, cur_val; 1772 int bits, i, bclk_rate;
1735 int aifdata = 0; 1773 int aifdata = 0;
1736 int bclk = 0;
1737 int lrclk = 0; 1774 int lrclk = 0;
1738 int dsp = 0; 1775 int dsp = 0;
1739 int aifdata_reg, bclk_reg, lrclk_reg, dsp_shift; 1776 int aifdata_reg, lrclk_reg, dsp_shift;
1740
1741 if (!wm8915->sysclk) {
1742 dev_err(codec->dev, "SYSCLK not configured\n");
1743 return -EINVAL;
1744 }
1745 1777
1746 switch (dai->id) { 1778 switch (dai->id) {
1747 case 0: 1779 case 0:
@@ -1753,7 +1785,6 @@ static int wm8915_hw_params(struct snd_pcm_substream *substream,
1753 aifdata_reg = WM8915_AIF1TX_DATA_CONFIGURATION_1; 1785 aifdata_reg = WM8915_AIF1TX_DATA_CONFIGURATION_1;
1754 lrclk_reg = WM8915_AIF1_TX_LRCLK_1; 1786 lrclk_reg = WM8915_AIF1_TX_LRCLK_1;
1755 } 1787 }
1756 bclk_reg = WM8915_AIF1_BCLK;
1757 dsp_shift = 0; 1788 dsp_shift = 0;
1758 break; 1789 break;
1759 case 1: 1790 case 1:
@@ -1765,7 +1796,6 @@ static int wm8915_hw_params(struct snd_pcm_substream *substream,
1765 aifdata_reg = WM8915_AIF2TX_DATA_CONFIGURATION_1; 1796 aifdata_reg = WM8915_AIF2TX_DATA_CONFIGURATION_1;
1766 lrclk_reg = WM8915_AIF2_TX_LRCLK_1; 1797 lrclk_reg = WM8915_AIF2_TX_LRCLK_1;
1767 } 1798 }
1768 bclk_reg = WM8915_AIF2_BCLK;
1769 dsp_shift = WM8915_DSP2_DIV_SHIFT; 1799 dsp_shift = WM8915_DSP2_DIV_SHIFT;
1770 break; 1800 break;
1771 default: 1801 default:
@@ -1779,6 +1809,9 @@ static int wm8915_hw_params(struct snd_pcm_substream *substream,
1779 return bclk_rate; 1809 return bclk_rate;
1780 } 1810 }
1781 1811
1812 wm8915->bclk_rate[dai->id] = bclk_rate;
1813 wm8915->rx_rate[dai->id] = params_rate(params);
1814
1782 /* Needs looking at for TDM */ 1815 /* Needs looking at for TDM */
1783 bits = snd_pcm_format_width(params_format(params)); 1816 bits = snd_pcm_format_width(params_format(params));
1784 if (bits < 0) 1817 if (bits < 0)
@@ -1796,18 +1829,7 @@ static int wm8915_hw_params(struct snd_pcm_substream *substream,
1796 } 1829 }
1797 dsp |= i << dsp_shift; 1830 dsp |= i << dsp_shift;
1798 1831
1799 /* Pick a divisor for BCLK as close as we can get to ideal */ 1832 wm8915_update_bclk(codec);
1800 best = 0;
1801 for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) {
1802 cur_val = (wm8915->sysclk / bclk_divs[i]) - bclk_rate;
1803 if (cur_val < 0) /* BCLK table is sorted */
1804 break;
1805 best = i;
1806 }
1807 bclk_rate = wm8915->sysclk / bclk_divs[best];
1808 dev_dbg(dai->dev, "Using BCLK_DIV %d for actual BCLK %dHz\n",
1809 bclk_divs[best], bclk_rate);
1810 bclk |= best;
1811 1833
1812 lrclk = bclk_rate / params_rate(params); 1834 lrclk = bclk_rate / params_rate(params);
1813 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",
@@ -1817,14 +1839,11 @@ static int wm8915_hw_params(struct snd_pcm_substream *substream,
1817 WM8915_AIF1TX_WL_MASK | 1839 WM8915_AIF1TX_WL_MASK |
1818 WM8915_AIF1TX_SLOT_LEN_MASK, 1840 WM8915_AIF1TX_SLOT_LEN_MASK,
1819 aifdata); 1841 aifdata);
1820 snd_soc_update_bits(codec, bclk_reg, WM8915_AIF1_BCLK_DIV_MASK, bclk);
1821 snd_soc_update_bits(codec, lrclk_reg, WM8915_AIF1RX_RATE_MASK, 1842 snd_soc_update_bits(codec, lrclk_reg, WM8915_AIF1RX_RATE_MASK,
1822 lrclk); 1843 lrclk);
1823 snd_soc_update_bits(codec, WM8915_AIF_CLOCKING_2, 1844 snd_soc_update_bits(codec, WM8915_AIF_CLOCKING_2,
1824 WM8915_DSP1_DIV_SHIFT << dsp_shift, dsp); 1845 WM8915_DSP1_DIV_SHIFT << dsp_shift, dsp);
1825 1846
1826 wm8915->rx_rate[dai->id] = params_rate(params);
1827
1828 return 0; 1847 return 0;
1829} 1848}
1830 1849
@@ -1838,6 +1857,9 @@ static int wm8915_set_sysclk(struct snd_soc_dai *dai,
1838 int src; 1857 int src;
1839 int old; 1858 int old;
1840 1859
1860 if (freq == wm8915->sysclk && clk_id == wm8915->sysclk_src)
1861 return 0;
1862
1841 /* Disable SYSCLK while we reconfigure */ 1863 /* Disable SYSCLK while we reconfigure */
1842 old = snd_soc_read(codec, WM8915_AIF_CLOCKING_1) & WM8915_SYSCLK_ENA; 1864 old = snd_soc_read(codec, WM8915_AIF_CLOCKING_1) & WM8915_SYSCLK_ENA;
1843 snd_soc_update_bits(codec, WM8915_AIF_CLOCKING_1, 1865 snd_soc_update_bits(codec, WM8915_AIF_CLOCKING_1,
@@ -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);
@@ -1889,6 +1913,8 @@ static int wm8915_set_sysclk(struct snd_soc_dai *dai,
1889 snd_soc_update_bits(codec, WM8915_AIF_CLOCKING_1, 1913 snd_soc_update_bits(codec, WM8915_AIF_CLOCKING_1,
1890 WM8915_SYSCLK_ENA, old); 1914 WM8915_SYSCLK_ENA, old);
1891 1915
1916 wm8915->sysclk_src = clk_id;
1917
1892 return 0; 1918 return 0;
1893} 1919}
1894 1920
@@ -2007,6 +2033,7 @@ static int wm8915_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
2007 unsigned int Fref, unsigned int Fout) 2033 unsigned int Fref, unsigned int Fout)
2008{ 2034{
2009 struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec); 2035 struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec);
2036 struct i2c_client *i2c = to_i2c_client(codec->dev);
2010 struct _fll_div fll_div; 2037 struct _fll_div fll_div;
2011 unsigned long timeout; 2038 unsigned long timeout;
2012 int ret, reg; 2039 int ret, reg;
@@ -2093,7 +2120,18 @@ static int wm8915_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
2093 else 2120 else
2094 timeout = msecs_to_jiffies(2); 2121 timeout = msecs_to_jiffies(2);
2095 2122
2096 wait_for_completion_timeout(&wm8915->fll_lock, timeout); 2123 /* Allow substantially longer if we've actually got the IRQ */
2124 if (i2c->irq)
2125 timeout *= 1000;
2126
2127 ret = wait_for_completion_timeout(&wm8915->fll_lock, timeout);
2128
2129 if (ret == 0 && i2c->irq) {
2130 dev_err(codec->dev, "Timed out waiting for FLL\n");
2131 ret = -ETIMEDOUT;
2132 } else {
2133 ret = 0;
2134 }
2097 2135
2098 dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout); 2136 dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout);
2099 2137
@@ -2101,7 +2139,7 @@ static int wm8915_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
2101 wm8915->fll_fout = Fout; 2139 wm8915->fll_fout = Fout;
2102 wm8915->fll_src = source; 2140 wm8915->fll_src = source;
2103 2141
2104 return 0; 2142 return ret;
2105} 2143}
2106 2144
2107#ifdef CONFIG_GPIOLIB 2145#ifdef CONFIG_GPIOLIB
@@ -2293,6 +2331,12 @@ static void wm8915_micd(struct snd_soc_codec *codec)
2293 SND_JACK_HEADSET | SND_JACK_BTN_0); 2331 SND_JACK_HEADSET | SND_JACK_BTN_0);
2294 wm8915->jack_mic = true; 2332 wm8915->jack_mic = true;
2295 wm8915->detecting = false; 2333 wm8915->detecting = false;
2334
2335 /* Increase poll rate to give better responsiveness
2336 * for buttons */
2337 snd_soc_update_bits(codec, WM8915_MIC_DETECT_1,
2338 WM8915_MICD_RATE_MASK,
2339 5 << WM8915_MICD_RATE_SHIFT);
2296 } 2340 }
2297 2341
2298 /* If we detected a lower impedence during initial startup 2342 /* If we detected a lower impedence during initial startup
@@ -2333,15 +2377,17 @@ static void wm8915_micd(struct snd_soc_codec *codec)
2333 SND_JACK_HEADPHONE, 2377 SND_JACK_HEADPHONE,
2334 SND_JACK_HEADSET | 2378 SND_JACK_HEADSET |
2335 SND_JACK_BTN_0); 2379 SND_JACK_BTN_0);
2380
2381 /* Increase the detection rate a bit for
2382 * responsiveness.
2383 */
2384 snd_soc_update_bits(codec, WM8915_MIC_DETECT_1,
2385 WM8915_MICD_RATE_MASK,
2386 7 << WM8915_MICD_RATE_SHIFT);
2387
2336 wm8915->detecting = false; 2388 wm8915->detecting = false;
2337 } 2389 }
2338 } 2390 }
2339
2340 /* Increase poll rate to give better responsiveness for buttons */
2341 if (!wm8915->detecting)
2342 snd_soc_update_bits(codec, WM8915_MIC_DETECT_1,
2343 WM8915_MICD_RATE_MASK,
2344 5 << WM8915_MICD_RATE_SHIFT);
2345} 2391}
2346 2392
2347static irqreturn_t wm8915_irq(int irq, void *data) 2393static irqreturn_t wm8915_irq(int irq, void *data)
@@ -2383,6 +2429,20 @@ static irqreturn_t wm8915_irq(int irq, void *data)
2383 } 2429 }
2384} 2430}
2385 2431
2432static irqreturn_t wm8915_edge_irq(int irq, void *data)
2433{
2434 irqreturn_t ret = IRQ_NONE;
2435 irqreturn_t val;
2436
2437 do {
2438 val = wm8915_irq(irq, data);
2439 if (val != IRQ_NONE)
2440 ret = val;
2441 } while (val != IRQ_NONE);
2442
2443 return ret;
2444}
2445
2386static void wm8915_retune_mobile_pdata(struct snd_soc_codec *codec) 2446static void wm8915_retune_mobile_pdata(struct snd_soc_codec *codec)
2387{ 2447{
2388 struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec); 2448 struct wm8915_priv *wm8915 = snd_soc_codec_get_drvdata(codec);
@@ -2482,8 +2542,6 @@ static int wm8915_probe(struct snd_soc_codec *codec)
2482 wm8915->disable_nb[1].notifier_call = wm8915_regulator_event_1; 2542 wm8915->disable_nb[1].notifier_call = wm8915_regulator_event_1;
2483 wm8915->disable_nb[2].notifier_call = wm8915_regulator_event_2; 2543 wm8915->disable_nb[2].notifier_call = wm8915_regulator_event_2;
2484 wm8915->disable_nb[3].notifier_call = wm8915_regulator_event_3; 2544 wm8915->disable_nb[3].notifier_call = wm8915_regulator_event_3;
2485 wm8915->disable_nb[4].notifier_call = wm8915_regulator_event_4;
2486 wm8915->disable_nb[5].notifier_call = wm8915_regulator_event_5;
2487 2545
2488 /* This should really be moved into the regulator core */ 2546 /* This should really be moved into the regulator core */
2489 for (i = 0; i < ARRAY_SIZE(wm8915->supplies); i++) { 2547 for (i = 0; i < ARRAY_SIZE(wm8915->supplies); i++) {
@@ -2709,8 +2767,14 @@ static int wm8915_probe(struct snd_soc_codec *codec)
2709 2767
2710 irq_flags |= IRQF_ONESHOT; 2768 irq_flags |= IRQF_ONESHOT;
2711 2769
2712 ret = request_threaded_irq(i2c->irq, NULL, wm8915_irq, 2770 if (irq_flags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING))
2713 irq_flags, "wm8915", codec); 2771 ret = request_threaded_irq(i2c->irq, NULL,
2772 wm8915_edge_irq,
2773 irq_flags, "wm8915", codec);
2774 else
2775 ret = request_threaded_irq(i2c->irq, NULL, wm8915_irq,
2776 irq_flags, "wm8915", codec);
2777
2714 if (ret == 0) { 2778 if (ret == 0) {
2715 /* Unmask the interrupt */ 2779 /* Unmask the interrupt */
2716 snd_soc_update_bits(codec, WM8915_INTERRUPT_CONTROL, 2780 snd_soc_update_bits(codec, WM8915_INTERRUPT_CONTROL,