diff options
-rw-r--r-- | sound/soc/codecs/rt5651.c | 54 | ||||
-rw-r--r-- | sound/soc/codecs/rt5651.h | 1 |
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 | ||
1771 | static 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 | |||
1764 | static void rt5651_jack_detect_work(struct work_struct *work) | 1778 | static 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 | ||
1839 | static void rt5651_enable_jack_detect(struct snd_soc_component *component, | 1853 | static 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; |