diff options
author | Oder Chiou <oder_chiou@realtek.com> | 2014-09-19 07:15:45 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2014-10-01 14:28:44 -0400 |
commit | f3fa1bbd836a7d6efb2abd506ed8e24096f39062 (patch) | |
tree | 7edd4838322132d185385252d7f46d608d7c6197 /sound | |
parent | 7d1311b93e58ed55f3a31cc8f94c4b8fe988a2b9 (diff) |
ASoC: rt5645: Add headset detect function
Add headset detect function
Signed-off-by: Oder Chiou <oder_chiou@realtek.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/codecs/rt5645.c | 99 | ||||
-rw-r--r-- | sound/soc/codecs/rt5645.h | 5 |
2 files changed, 104 insertions, 0 deletions
diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index a7762d0a623e..3fb83bf09768 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/i2c.h> | 17 | #include <linux/i2c.h> |
18 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
19 | #include <linux/spi/spi.h> | 19 | #include <linux/spi/spi.h> |
20 | #include <linux/gpio.h> | ||
20 | #include <sound/core.h> | 21 | #include <sound/core.h> |
21 | #include <sound/pcm.h> | 22 | #include <sound/pcm.h> |
22 | #include <sound/pcm_params.h> | 23 | #include <sound/pcm_params.h> |
@@ -2103,6 +2104,77 @@ static int rt5645_set_bias_level(struct snd_soc_codec *codec, | |||
2103 | return 0; | 2104 | return 0; |
2104 | } | 2105 | } |
2105 | 2106 | ||
2107 | static int rt5645_jack_detect(struct snd_soc_codec *codec, | ||
2108 | struct snd_soc_jack *jack) | ||
2109 | { | ||
2110 | struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec); | ||
2111 | int gpio_state, jack_type = 0; | ||
2112 | unsigned int val; | ||
2113 | |||
2114 | gpio_state = gpio_get_value(rt5645->pdata.hp_det_gpio); | ||
2115 | |||
2116 | dev_dbg(codec->dev, "gpio = %d(%d)\n", rt5645->pdata.hp_det_gpio, | ||
2117 | gpio_state); | ||
2118 | |||
2119 | if ((rt5645->pdata.gpio_hp_det_active_high && gpio_state) || | ||
2120 | (!rt5645->pdata.gpio_hp_det_active_high && !gpio_state)) { | ||
2121 | snd_soc_dapm_force_enable_pin(&codec->dapm, "micbias1"); | ||
2122 | snd_soc_dapm_force_enable_pin(&codec->dapm, "micbias2"); | ||
2123 | snd_soc_dapm_force_enable_pin(&codec->dapm, "LDO2"); | ||
2124 | snd_soc_dapm_force_enable_pin(&codec->dapm, "Mic Det Power"); | ||
2125 | snd_soc_dapm_sync(&codec->dapm); | ||
2126 | |||
2127 | snd_soc_write(codec, RT5645_IN1_CTRL1, 0x0006); | ||
2128 | snd_soc_write(codec, RT5645_JD_CTRL3, 0x00b0); | ||
2129 | |||
2130 | snd_soc_update_bits(codec, RT5645_IN1_CTRL2, | ||
2131 | RT5645_CBJ_MN_JD, 0); | ||
2132 | snd_soc_update_bits(codec, RT5645_IN1_CTRL2, | ||
2133 | RT5645_CBJ_MN_JD, RT5645_CBJ_MN_JD); | ||
2134 | |||
2135 | msleep(400); | ||
2136 | val = snd_soc_read(codec, RT5645_IN1_CTRL3) & 0x7; | ||
2137 | dev_dbg(codec->dev, "val = %d\n", val); | ||
2138 | |||
2139 | if (val == 1 || val == 2) | ||
2140 | jack_type = SND_JACK_HEADSET; | ||
2141 | else | ||
2142 | jack_type = SND_JACK_HEADPHONE; | ||
2143 | |||
2144 | snd_soc_dapm_disable_pin(&codec->dapm, "micbias1"); | ||
2145 | snd_soc_dapm_disable_pin(&codec->dapm, "micbias2"); | ||
2146 | snd_soc_dapm_disable_pin(&codec->dapm, "LDO2"); | ||
2147 | snd_soc_dapm_disable_pin(&codec->dapm, "Mic Det Power"); | ||
2148 | snd_soc_dapm_sync(&codec->dapm); | ||
2149 | } | ||
2150 | |||
2151 | snd_soc_jack_report(rt5645->jack, jack_type, SND_JACK_HEADSET); | ||
2152 | |||
2153 | return 0; | ||
2154 | } | ||
2155 | |||
2156 | int rt5645_set_jack_detect(struct snd_soc_codec *codec, | ||
2157 | struct snd_soc_jack *jack) | ||
2158 | { | ||
2159 | struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec); | ||
2160 | |||
2161 | rt5645->jack = jack; | ||
2162 | |||
2163 | rt5645_jack_detect(codec, rt5645->jack); | ||
2164 | |||
2165 | return 0; | ||
2166 | } | ||
2167 | EXPORT_SYMBOL_GPL(rt5645_set_jack_detect); | ||
2168 | |||
2169 | static irqreturn_t rt5645_irq(int irq, void *data) | ||
2170 | { | ||
2171 | struct rt5645_priv *rt5645 = data; | ||
2172 | |||
2173 | rt5645_jack_detect(rt5645->codec, rt5645->jack); | ||
2174 | |||
2175 | return IRQ_HANDLED; | ||
2176 | } | ||
2177 | |||
2106 | static int rt5645_probe(struct snd_soc_codec *codec) | 2178 | static int rt5645_probe(struct snd_soc_codec *codec) |
2107 | { | 2179 | { |
2108 | struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec); | 2180 | struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec); |
@@ -2250,6 +2322,7 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, | |||
2250 | if (rt5645 == NULL) | 2322 | if (rt5645 == NULL) |
2251 | return -ENOMEM; | 2323 | return -ENOMEM; |
2252 | 2324 | ||
2325 | rt5645->i2c = i2c; | ||
2253 | i2c_set_clientdata(i2c, rt5645); | 2326 | i2c_set_clientdata(i2c, rt5645); |
2254 | 2327 | ||
2255 | if (pdata) | 2328 | if (pdata) |
@@ -2345,12 +2418,38 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, | |||
2345 | 2418 | ||
2346 | } | 2419 | } |
2347 | 2420 | ||
2421 | if (rt5645->i2c->irq) { | ||
2422 | ret = request_threaded_irq(rt5645->i2c->irq, NULL, rt5645_irq, | ||
2423 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | ||
2424 | | IRQF_ONESHOT, "rt5645", rt5645); | ||
2425 | if (ret) | ||
2426 | dev_err(&i2c->dev, "Failed to reguest IRQ: %d\n", ret); | ||
2427 | } | ||
2428 | |||
2429 | if (gpio_is_valid(rt5645->pdata.hp_det_gpio)) { | ||
2430 | ret = gpio_request(rt5645->pdata.hp_det_gpio, "rt5645"); | ||
2431 | if (ret) | ||
2432 | dev_err(&i2c->dev, "Fail gpio_request hp_det_gpio\n"); | ||
2433 | |||
2434 | ret = gpio_direction_input(rt5645->pdata.hp_det_gpio); | ||
2435 | if (ret) | ||
2436 | dev_err(&i2c->dev, "Fail gpio_direction hp_det_gpio\n"); | ||
2437 | } | ||
2438 | |||
2348 | return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5645, | 2439 | return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5645, |
2349 | rt5645_dai, ARRAY_SIZE(rt5645_dai)); | 2440 | rt5645_dai, ARRAY_SIZE(rt5645_dai)); |
2350 | } | 2441 | } |
2351 | 2442 | ||
2352 | static int rt5645_i2c_remove(struct i2c_client *i2c) | 2443 | static int rt5645_i2c_remove(struct i2c_client *i2c) |
2353 | { | 2444 | { |
2445 | struct rt5645_priv *rt5645 = i2c_get_clientdata(i2c); | ||
2446 | |||
2447 | if (i2c->irq) | ||
2448 | free_irq(i2c->irq, rt5645); | ||
2449 | |||
2450 | if (gpio_is_valid(rt5645->pdata.hp_det_gpio)) | ||
2451 | gpio_free(rt5645->pdata.hp_det_gpio); | ||
2452 | |||
2354 | snd_soc_unregister_codec(&i2c->dev); | 2453 | snd_soc_unregister_codec(&i2c->dev); |
2355 | 2454 | ||
2356 | return 0; | 2455 | return 0; |
diff --git a/sound/soc/codecs/rt5645.h b/sound/soc/codecs/rt5645.h index 355b7e9eefab..50c62c5668ea 100644 --- a/sound/soc/codecs/rt5645.h +++ b/sound/soc/codecs/rt5645.h | |||
@@ -2166,6 +2166,8 @@ struct rt5645_priv { | |||
2166 | struct snd_soc_codec *codec; | 2166 | struct snd_soc_codec *codec; |
2167 | struct rt5645_platform_data pdata; | 2167 | struct rt5645_platform_data pdata; |
2168 | struct regmap *regmap; | 2168 | struct regmap *regmap; |
2169 | struct i2c_client *i2c; | ||
2170 | struct snd_soc_jack *jack; | ||
2169 | 2171 | ||
2170 | int sysclk; | 2172 | int sysclk; |
2171 | int sysclk_src; | 2173 | int sysclk_src; |
@@ -2178,4 +2180,7 @@ struct rt5645_priv { | |||
2178 | int pll_out; | 2180 | int pll_out; |
2179 | }; | 2181 | }; |
2180 | 2182 | ||
2183 | int rt5645_set_jack_detect(struct snd_soc_codec *codec, | ||
2184 | struct snd_soc_jack *jack); | ||
2185 | |||
2181 | #endif /* __RT5645_H__ */ | 2186 | #endif /* __RT5645_H__ */ |