summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2018-12-29 18:00:21 -0500
committerMark Brown <broonie@kernel.org>2019-01-07 14:23:38 -0500
commitc2ec9d957d2bf49d69afb1b872cb2363c6cb5862 (patch)
tree477e4c4458349b4c040056a827c2c0cb8e655b22
parentd306873589c5a4c13df7176cd73d66ebfa690064 (diff)
ASoC: rt5651: Add support for jack detect using an external GPIO
Some board designs hook the jack-detect up to an external GPIO, rather then to one of the codec pins, add support for this. Figuring out which GPIO to use is pretty much board specific so I've chosen to let the machine driver pass the gpio_desc as data argument to snd_soc_component_set_jack() rather then add support for getting the GPIO to the codec driver. This keeps the codec code nice and clean. Note that using an external GPIO for this conflicts with button-press support, so this commit disables button-press support when an external GPIO is used. Acked-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--sound/soc/codecs/rt5651.c54
-rw-r--r--sound/soc/codecs/rt5651.h1
2 files changed, 39 insertions, 16 deletions
diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c
index 9a007c162631..75994297c896 100644
--- a/sound/soc/codecs/rt5651.c
+++ b/sound/soc/codecs/rt5651.c
@@ -13,6 +13,7 @@
13#include <linux/init.h> 13#include <linux/init.h>
14#include <linux/delay.h> 14#include <linux/delay.h>
15#include <linux/pm.h> 15#include <linux/pm.h>
16#include <linux/gpio/consumer.h>
16#include <linux/i2c.h> 17#include <linux/i2c.h>
17#include <linux/regmap.h> 18#include <linux/regmap.h>
18#include <linux/platform_device.h> 19#include <linux/platform_device.h>
@@ -1621,6 +1622,12 @@ static bool rt5651_jack_inserted(struct snd_soc_component *component)
1621 struct rt5651_priv *rt5651 = snd_soc_component_get_drvdata(component); 1622 struct rt5651_priv *rt5651 = snd_soc_component_get_drvdata(component);
1622 int val; 1623 int val;
1623 1624
1625 if (rt5651->gpiod_hp_det) {
1626 val = gpiod_get_value_cansleep(rt5651->gpiod_hp_det);
1627 dev_dbg(component->dev, "jack-detect gpio %d\n", val);
1628 return val;
1629 }
1630
1624 val = snd_soc_component_read32(component, RT5651_INT_IRQ_ST); 1631 val = snd_soc_component_read32(component, RT5651_INT_IRQ_ST);
1625 dev_dbg(component->dev, "irq status %#04x\n", val); 1632 dev_dbg(component->dev, "irq status %#04x\n", val);
1626 1633
@@ -1761,6 +1768,13 @@ static int rt5651_detect_headset(struct snd_soc_component *component)
1761 return SND_JACK_HEADPHONE; 1768 return SND_JACK_HEADPHONE;
1762} 1769}
1763 1770
1771static bool rt5651_support_button_press(struct rt5651_priv *rt5651)
1772{
1773 /* Button press support only works with internal jack-detection */
1774 return (rt5651->hp_jack->status & SND_JACK_MICROPHONE) &&
1775 rt5651->gpiod_hp_det == NULL;
1776}
1777
1764static void rt5651_jack_detect_work(struct work_struct *work) 1778static void rt5651_jack_detect_work(struct work_struct *work)
1765{ 1779{
1766 struct rt5651_priv *rt5651 = 1780 struct rt5651_priv *rt5651 =
@@ -1785,15 +1799,15 @@ static void rt5651_jack_detect_work(struct work_struct *work)
1785 WARN_ON(rt5651->ovcd_irq_enabled); 1799 WARN_ON(rt5651->ovcd_irq_enabled);
1786 rt5651_enable_micbias1_for_ovcd(component); 1800 rt5651_enable_micbias1_for_ovcd(component);
1787 report = rt5651_detect_headset(component); 1801 report = rt5651_detect_headset(component);
1788 if (report == SND_JACK_HEADSET) { 1802 dev_dbg(component->dev, "detect report %#02x\n", report);
1803 snd_soc_jack_report(rt5651->hp_jack, report, SND_JACK_HEADSET);
1804 if (rt5651_support_button_press(rt5651)) {
1789 /* Enable ovcd IRQ for button press detect. */ 1805 /* Enable ovcd IRQ for button press detect. */
1790 rt5651_enable_micbias1_ovcd_irq(component); 1806 rt5651_enable_micbias1_ovcd_irq(component);
1791 } else { 1807 } else {
1792 /* No more need for overcurrent detect. */ 1808 /* No more need for overcurrent detect. */
1793 rt5651_disable_micbias1_for_ovcd(component); 1809 rt5651_disable_micbias1_for_ovcd(component);
1794 } 1810 }
1795 dev_dbg(component->dev, "detect report %#02x\n", report);
1796 snd_soc_jack_report(rt5651->hp_jack, report, SND_JACK_HEADSET);
1797 } else if (rt5651->ovcd_irq_enabled && rt5651_micbias1_ovcd(component)) { 1811 } else if (rt5651->ovcd_irq_enabled && rt5651_micbias1_ovcd(component)) {
1798 dev_dbg(component->dev, "OVCD IRQ\n"); 1812 dev_dbg(component->dev, "OVCD IRQ\n");
1799 1813
@@ -1837,16 +1851,20 @@ static void rt5651_cancel_work(void *data)
1837} 1851}
1838 1852
1839static void rt5651_enable_jack_detect(struct snd_soc_component *component, 1853static void rt5651_enable_jack_detect(struct snd_soc_component *component,
1840 struct snd_soc_jack *hp_jack) 1854 struct snd_soc_jack *hp_jack,
1855 struct gpio_desc *gpiod_hp_det)
1841{ 1856{
1842 struct rt5651_priv *rt5651 = snd_soc_component_get_drvdata(component); 1857 struct rt5651_priv *rt5651 = snd_soc_component_get_drvdata(component);
1843 1858 bool using_internal_jack_detect = true;
1844 /* IRQ output on GPIO1 */
1845 snd_soc_component_update_bits(component, RT5651_GPIO_CTRL1,
1846 RT5651_GP1_PIN_MASK, RT5651_GP1_PIN_IRQ);
1847 1859
1848 /* Select jack detect source */ 1860 /* Select jack detect source */
1849 switch (rt5651->jd_src) { 1861 switch (rt5651->jd_src) {
1862 case RT5651_JD_NULL:
1863 rt5651->gpiod_hp_det = gpiod_hp_det;
1864 if (!rt5651->gpiod_hp_det)
1865 return; /* No jack detect */
1866 using_internal_jack_detect = false;
1867 break;
1850 case RT5651_JD1_1: 1868 case RT5651_JD1_1:
1851 snd_soc_component_update_bits(component, RT5651_JD_CTRL2, 1869 snd_soc_component_update_bits(component, RT5651_JD_CTRL2,
1852 RT5651_JD_TRG_SEL_MASK, RT5651_JD_TRG_SEL_JD1_1); 1870 RT5651_JD_TRG_SEL_MASK, RT5651_JD_TRG_SEL_JD1_1);
@@ -1865,16 +1883,20 @@ static void rt5651_enable_jack_detect(struct snd_soc_component *component,
1865 snd_soc_component_update_bits(component, RT5651_IRQ_CTRL1, 1883 snd_soc_component_update_bits(component, RT5651_IRQ_CTRL1,
1866 RT5651_JD2_IRQ_EN, RT5651_JD2_IRQ_EN); 1884 RT5651_JD2_IRQ_EN, RT5651_JD2_IRQ_EN);
1867 break; 1885 break;
1868 case RT5651_JD_NULL:
1869 return;
1870 default: 1886 default:
1871 dev_err(component->dev, "Currently only JD1_1 / JD1_2 / JD2 are supported\n"); 1887 dev_err(component->dev, "Currently only JD1_1 / JD1_2 / JD2 are supported\n");
1872 return; 1888 return;
1873 } 1889 }
1874 1890
1875 /* Enable jack detect power */ 1891 if (using_internal_jack_detect) {
1876 snd_soc_component_update_bits(component, RT5651_PWR_ANLG2, 1892 /* IRQ output on GPIO1 */
1877 RT5651_PWR_JD_M, RT5651_PWR_JD_M); 1893 snd_soc_component_update_bits(component, RT5651_GPIO_CTRL1,
1894 RT5651_GP1_PIN_MASK, RT5651_GP1_PIN_IRQ);
1895
1896 /* Enable jack detect power */
1897 snd_soc_component_update_bits(component, RT5651_PWR_ANLG2,
1898 RT5651_PWR_JD_M, RT5651_PWR_JD_M);
1899 }
1878 1900
1879 /* Set OVCD threshold current and scale-factor */ 1901 /* Set OVCD threshold current and scale-factor */
1880 snd_soc_component_write(component, RT5651_PR_BASE + RT5651_BIAS_CUR4, 1902 snd_soc_component_write(component, RT5651_PR_BASE + RT5651_BIAS_CUR4,
@@ -1903,7 +1925,7 @@ static void rt5651_enable_jack_detect(struct snd_soc_component *component,
1903 RT5651_MB1_OC_STKY_MASK, RT5651_MB1_OC_STKY_EN); 1925 RT5651_MB1_OC_STKY_MASK, RT5651_MB1_OC_STKY_EN);
1904 1926
1905 rt5651->hp_jack = hp_jack; 1927 rt5651->hp_jack = hp_jack;
1906 if (rt5651->hp_jack->status & SND_JACK_MICROPHONE) { 1928 if (rt5651_support_button_press(rt5651)) {
1907 rt5651_enable_micbias1_for_ovcd(component); 1929 rt5651_enable_micbias1_for_ovcd(component);
1908 rt5651_enable_micbias1_ovcd_irq(component); 1930 rt5651_enable_micbias1_ovcd_irq(component);
1909 } 1931 }
@@ -1920,7 +1942,7 @@ static void rt5651_disable_jack_detect(struct snd_soc_component *component)
1920 disable_irq(rt5651->irq); 1942 disable_irq(rt5651->irq);
1921 rt5651_cancel_work(rt5651); 1943 rt5651_cancel_work(rt5651);
1922 1944
1923 if (rt5651->hp_jack->status & SND_JACK_MICROPHONE) { 1945 if (rt5651_support_button_press(rt5651)) {
1924 rt5651_disable_micbias1_ovcd_irq(component); 1946 rt5651_disable_micbias1_ovcd_irq(component);
1925 rt5651_disable_micbias1_for_ovcd(component); 1947 rt5651_disable_micbias1_for_ovcd(component);
1926 snd_soc_jack_report(rt5651->hp_jack, 0, SND_JACK_BTN_0); 1948 snd_soc_jack_report(rt5651->hp_jack, 0, SND_JACK_BTN_0);
@@ -1933,7 +1955,7 @@ static int rt5651_set_jack(struct snd_soc_component *component,
1933 struct snd_soc_jack *jack, void *data) 1955 struct snd_soc_jack *jack, void *data)
1934{ 1956{
1935 if (jack) 1957 if (jack)
1936 rt5651_enable_jack_detect(component, jack); 1958 rt5651_enable_jack_detect(component, jack, data);
1937 else 1959 else
1938 rt5651_disable_jack_detect(component); 1960 rt5651_disable_jack_detect(component);
1939 1961
diff --git a/sound/soc/codecs/rt5651.h b/sound/soc/codecs/rt5651.h
index ac6de6fb5414..41fcb8b5eb40 100644
--- a/sound/soc/codecs/rt5651.h
+++ b/sound/soc/codecs/rt5651.h
@@ -2073,6 +2073,7 @@ struct rt5651_priv {
2073 struct regmap *regmap; 2073 struct regmap *regmap;
2074 /* Jack and button detect data */ 2074 /* Jack and button detect data */
2075 struct snd_soc_jack *hp_jack; 2075 struct snd_soc_jack *hp_jack;
2076 struct gpio_desc *gpiod_hp_det;
2076 struct work_struct jack_detect_work; 2077 struct work_struct jack_detect_work;
2077 struct delayed_work bp_work; 2078 struct delayed_work bp_work;
2078 bool ovcd_irq_enabled; 2079 bool ovcd_irq_enabled;