aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorOder Chiou <oder_chiou@realtek.com>2014-09-19 07:15:45 -0400
committerMark Brown <broonie@kernel.org>2014-10-01 14:28:44 -0400
commitf3fa1bbd836a7d6efb2abd506ed8e24096f39062 (patch)
tree7edd4838322132d185385252d7f46d608d7c6197 /sound
parent7d1311b93e58ed55f3a31cc8f94c4b8fe988a2b9 (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.c99
-rw-r--r--sound/soc/codecs/rt5645.h5
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
2107static 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
2156int 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}
2167EXPORT_SYMBOL_GPL(rt5645_set_jack_detect);
2168
2169static 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
2106static int rt5645_probe(struct snd_soc_codec *codec) 2178static 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
2352static int rt5645_i2c_remove(struct i2c_client *i2c) 2443static 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
2183int rt5645_set_jack_detect(struct snd_soc_codec *codec,
2184 struct snd_soc_jack *jack);
2185
2181#endif /* __RT5645_H__ */ 2186#endif /* __RT5645_H__ */