aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorRhyland Klein <rklein@nvidia.com>2012-03-15 18:07:47 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-04-01 06:28:24 -0400
commit9dd90c5db0401061009183e6407feff3724ebc8b (patch)
tree462b883850965aba52919f438474e5888f7de6a5 /sound
parent5f1cba63a3a65b01a70ac09914176bb3719725d6 (diff)
ASoC: max98095: add jack detection
This change adds the logic to support using the jack detect mechanism built in to the codec to detect both when a jack was inserted and what type of jack is present. This change also supports the use of an external mechanism for headphone detection. If this mechanism exists, when the max98095_jack_detect function is called, the hp_jack is simply passed NULL. This change supports both simple headphones, powered headphones, microphones and headsets with both headphones and a mic. Signed-off-by: Rhyland Klein <rklein@nvidia.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/codecs/max98095.c158
-rw-r--r--sound/soc/codecs/max98095.h22
2 files changed, 179 insertions, 1 deletions
diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c
index 0bb511a0388d..0752840e01c2 100644
--- a/sound/soc/codecs/max98095.c
+++ b/sound/soc/codecs/max98095.c
@@ -24,6 +24,7 @@
24#include <linux/slab.h> 24#include <linux/slab.h>
25#include <asm/div64.h> 25#include <asm/div64.h>
26#include <sound/max98095.h> 26#include <sound/max98095.h>
27#include <sound/jack.h>
27#include "max98095.h" 28#include "max98095.h"
28 29
29enum max98095_type { 30enum max98095_type {
@@ -51,6 +52,8 @@ struct max98095_priv {
51 u8 lin_state; 52 u8 lin_state;
52 unsigned int mic1pre; 53 unsigned int mic1pre;
53 unsigned int mic2pre; 54 unsigned int mic2pre;
55 struct snd_soc_jack *headphone_jack;
56 struct snd_soc_jack *mic_jack;
54}; 57};
55 58
56static const u8 max98095_reg_def[M98095_REG_CNT] = { 59static const u8 max98095_reg_def[M98095_REG_CNT] = {
@@ -2173,9 +2176,125 @@ static void max98095_handle_pdata(struct snd_soc_codec *codec)
2173 max98095_handle_bq_pdata(codec); 2176 max98095_handle_bq_pdata(codec);
2174} 2177}
2175 2178
2179static irqreturn_t max98095_report_jack(int irq, void *data)
2180{
2181 struct snd_soc_codec *codec = data;
2182 struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
2183 unsigned int value;
2184 int hp_report = 0;
2185 int mic_report = 0;
2186
2187 /* Read the Jack Status Register */
2188 value = snd_soc_read(codec, M98095_007_JACK_AUTO_STS);
2189
2190 /* If ddone is not set, then detection isn't finished yet */
2191 if ((value & M98095_DDONE) == 0)
2192 return IRQ_NONE;
2193
2194 /* if hp, check its bit, and if set, clear it */
2195 if ((value & M98095_HP_IN || value & M98095_LO_IN) &&
2196 max98095->headphone_jack)
2197 hp_report |= SND_JACK_HEADPHONE;
2198
2199 /* if mic, check its bit, and if set, clear it */
2200 if ((value & M98095_MIC_IN) && max98095->mic_jack)
2201 mic_report |= SND_JACK_MICROPHONE;
2202
2203 if (max98095->headphone_jack == max98095->mic_jack) {
2204 snd_soc_jack_report(max98095->headphone_jack,
2205 hp_report | mic_report,
2206 SND_JACK_HEADSET);
2207 } else {
2208 if (max98095->headphone_jack)
2209 snd_soc_jack_report(max98095->headphone_jack,
2210 hp_report, SND_JACK_HEADPHONE);
2211 if (max98095->mic_jack)
2212 snd_soc_jack_report(max98095->mic_jack,
2213 mic_report, SND_JACK_MICROPHONE);
2214 }
2215
2216 return IRQ_HANDLED;
2217}
2218
2219int max98095_jack_detect_enable(struct snd_soc_codec *codec)
2220{
2221 struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
2222 int ret = 0;
2223 int detect_enable = M98095_JDEN;
2224 unsigned int slew = M98095_DEFAULT_SLEW_DELAY;
2225
2226 if (max98095->pdata->jack_detect_pin5en)
2227 detect_enable |= M98095_PIN5EN;
2228
2229 if (max98095->jack_detect_delay)
2230 slew = max98095->jack_detect_delay;
2231
2232 ret = snd_soc_write(codec, M98095_08E_JACK_DC_SLEW, slew);
2233 if (ret < 0) {
2234 dev_err(codec->dev, "Failed to cfg auto detect %d\n", ret);
2235 return ret;
2236 }
2237
2238 /* configure auto detection to be enabled */
2239 ret = snd_soc_write(codec, M98095_089_JACK_DET_AUTO, detect_enable);
2240 if (ret < 0) {
2241 dev_err(codec->dev, "Failed to cfg auto detect %d\n", ret);
2242 return ret;
2243 }
2244
2245 return ret;
2246}
2247
2248int max98095_jack_detect_disable(struct snd_soc_codec *codec)
2249{
2250 int ret = 0;
2251
2252 /* configure auto detection to be disabled */
2253 ret = snd_soc_write(codec, M98095_089_JACK_DET_AUTO, 0x0);
2254 if (ret < 0) {
2255 dev_err(codec->dev, "Failed to cfg auto detect %d\n", ret);
2256 return ret;
2257 }
2258
2259 return ret;
2260}
2261
2262int max98095_jack_detect(struct snd_soc_codec *codec,
2263 struct snd_soc_jack *hp_jack, struct snd_soc_jack *mic_jack)
2264{
2265 struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
2266 struct i2c_client *client = to_i2c_client(codec->dev);
2267 int ret = 0;
2268
2269 max98095->headphone_jack = hp_jack;
2270 max98095->mic_jack = mic_jack;
2271
2272 /* only progress if we have at least 1 jack pointer */
2273 if (!hp_jack && !mic_jack)
2274 return -EINVAL;
2275
2276 max98095_jack_detect_enable(codec);
2277
2278 /* enable interrupts for headphone jack detection */
2279 ret = snd_soc_update_bits(codec, M98095_013_JACK_INT_EN,
2280 M98095_IDDONE, M98095_IDDONE);
2281 if (ret < 0) {
2282 dev_err(codec->dev, "Failed to cfg jack irqs %d\n", ret);
2283 return ret;
2284 }
2285
2286 max98095_report_jack(client->irq, codec);
2287 return 0;
2288}
2289
2176#ifdef CONFIG_PM 2290#ifdef CONFIG_PM
2177static int max98095_suspend(struct snd_soc_codec *codec) 2291static int max98095_suspend(struct snd_soc_codec *codec)
2178{ 2292{
2293 struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
2294
2295 if (max98095->headphone_jack || max98095->mic_jack)
2296 max98095_jack_detect_disable(codec);
2297
2179 max98095_set_bias_level(codec, SND_SOC_BIAS_OFF); 2298 max98095_set_bias_level(codec, SND_SOC_BIAS_OFF);
2180 2299
2181 return 0; 2300 return 0;
@@ -2183,8 +2302,16 @@ static int max98095_suspend(struct snd_soc_codec *codec)
2183 2302
2184static int max98095_resume(struct snd_soc_codec *codec) 2303static int max98095_resume(struct snd_soc_codec *codec)
2185{ 2304{
2305 struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
2306 struct i2c_client *client = to_i2c_client(codec->dev);
2307
2186 max98095_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 2308 max98095_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
2187 2309
2310 if (max98095->headphone_jack || max98095->mic_jack) {
2311 max98095_jack_detect_enable(codec);
2312 max98095_report_jack(client->irq, codec);
2313 }
2314
2188 return 0; 2315 return 0;
2189} 2316}
2190#else 2317#else
@@ -2227,6 +2354,7 @@ static int max98095_probe(struct snd_soc_codec *codec)
2227{ 2354{
2228 struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); 2355 struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
2229 struct max98095_cdata *cdata; 2356 struct max98095_cdata *cdata;
2357 struct i2c_client *client;
2230 int ret = 0; 2358 int ret = 0;
2231 2359
2232 ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); 2360 ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
@@ -2238,6 +2366,8 @@ static int max98095_probe(struct snd_soc_codec *codec)
2238 /* reset the codec, the DSP core, and disable all interrupts */ 2366 /* reset the codec, the DSP core, and disable all interrupts */
2239 max98095_reset(codec); 2367 max98095_reset(codec);
2240 2368
2369 client = to_i2c_client(codec->dev);
2370
2241 /* initialize private data */ 2371 /* initialize private data */
2242 2372
2243 max98095->sysclk = (unsigned)-1; 2373 max98095->sysclk = (unsigned)-1;
@@ -2266,11 +2396,23 @@ static int max98095_probe(struct snd_soc_codec *codec)
2266 max98095->mic1pre = 0; 2396 max98095->mic1pre = 0;
2267 max98095->mic2pre = 0; 2397 max98095->mic2pre = 0;
2268 2398
2399 if (client->irq) {
2400 /* register an audio interrupt */
2401 ret = request_threaded_irq(client->irq, NULL,
2402 max98095_report_jack,
2403 IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
2404 "max98095", codec);
2405 if (ret) {
2406 dev_err(codec->dev, "Failed to request IRQ: %d\n", ret);
2407 goto err_access;
2408 }
2409 }
2410
2269 ret = snd_soc_read(codec, M98095_0FF_REV_ID); 2411 ret = snd_soc_read(codec, M98095_0FF_REV_ID);
2270 if (ret < 0) { 2412 if (ret < 0) {
2271 dev_err(codec->dev, "Failure reading hardware revision: %d\n", 2413 dev_err(codec->dev, "Failure reading hardware revision: %d\n",
2272 ret); 2414 ret);
2273 goto err_access; 2415 goto err_irq;
2274 } 2416 }
2275 dev_info(codec->dev, "Hardware revision: %c\n", ret - 0x40 + 'A'); 2417 dev_info(codec->dev, "Hardware revision: %c\n", ret - 0x40 + 'A');
2276 2418
@@ -2306,14 +2448,28 @@ static int max98095_probe(struct snd_soc_codec *codec)
2306 2448
2307 max98095_add_widgets(codec); 2449 max98095_add_widgets(codec);
2308 2450
2451 return 0;
2452
2453err_irq:
2454 if (client->irq)
2455 free_irq(client->irq, codec);
2309err_access: 2456err_access:
2310 return ret; 2457 return ret;
2311} 2458}
2312 2459
2313static int max98095_remove(struct snd_soc_codec *codec) 2460static int max98095_remove(struct snd_soc_codec *codec)
2314{ 2461{
2462 struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
2463 struct i2c_client *client = to_i2c_client(codec->dev);
2464
2315 max98095_set_bias_level(codec, SND_SOC_BIAS_OFF); 2465 max98095_set_bias_level(codec, SND_SOC_BIAS_OFF);
2316 2466
2467 if (max98095->headphone_jack || max98095->mic_jack)
2468 max98095_jack_detect_disable(codec);
2469
2470 if (client->irq)
2471 free_irq(client->irq, codec);
2472
2317 return 0; 2473 return 0;
2318} 2474}
2319 2475
diff --git a/sound/soc/codecs/max98095.h b/sound/soc/codecs/max98095.h
index 891584a0eb03..2ebbe4e894bf 100644
--- a/sound/soc/codecs/max98095.h
+++ b/sound/soc/codecs/max98095.h
@@ -175,11 +175,23 @@
175 175
176/* MAX98095 Registers Bit Fields */ 176/* MAX98095 Registers Bit Fields */
177 177
178/* M98095_007_JACK_AUTO_STS */
179 #define M98095_MIC_IN (1<<3)
180 #define M98095_LO_IN (1<<5)
181 #define M98095_HP_IN (1<<6)
182 #define M98095_DDONE (1<<7)
183
178/* M98095_00F_HOST_CFG */ 184/* M98095_00F_HOST_CFG */
179 #define M98095_SEG (1<<0) 185 #define M98095_SEG (1<<0)
180 #define M98095_XTEN (1<<1) 186 #define M98095_XTEN (1<<1)
181 #define M98095_MDLLEN (1<<2) 187 #define M98095_MDLLEN (1<<2)
182 188
189/* M98095_013_JACK_INT_EN */
190 #define M98095_IMIC_IN (1<<3)
191 #define M98095_ILO_IN (1<<5)
192 #define M98095_IHP_IN (1<<6)
193 #define M98095_IDDONE (1<<7)
194
183/* M98095_027_DAI1_CLKMODE, M98095_031_DAI2_CLKMODE, M98095_03B_DAI3_CLKMODE */ 195/* M98095_027_DAI1_CLKMODE, M98095_031_DAI2_CLKMODE, M98095_03B_DAI3_CLKMODE */
184 #define M98095_CLKMODE_MASK 0xFF 196 #define M98095_CLKMODE_MASK 0xFF
185 197
@@ -255,6 +267,10 @@
255 #define M98095_EQ2EN (1<<1) 267 #define M98095_EQ2EN (1<<1)
256 #define M98095_EQ1EN (1<<0) 268 #define M98095_EQ1EN (1<<0)
257 269
270/* M98095_089_JACK_DET_AUTO */
271 #define M98095_PIN5EN (1<<2)
272 #define M98095_JDEN (1<<7)
273
258/* M98095_090_PWR_EN_IN */ 274/* M98095_090_PWR_EN_IN */
259 #define M98095_INEN (1<<7) 275 #define M98095_INEN (1<<7)
260 #define M98095_MB2EN (1<<3) 276 #define M98095_MB2EN (1<<3)
@@ -296,4 +312,10 @@
296#define M98095_174_DAI1_BQ_BASE 0x74 312#define M98095_174_DAI1_BQ_BASE 0x74
297#define M98095_17E_DAI2_BQ_BASE 0x7E 313#define M98095_17E_DAI2_BQ_BASE 0x7E
298 314
315/* Default Delay used in Slew Rate Calculation for Jack detection */
316#define M98095_DEFAULT_SLEW_DELAY 0x18
317
318extern int max98095_jack_detect(struct snd_soc_codec *codec,
319 struct snd_soc_jack *hp_jack, struct snd_soc_jack *mic_jack);
320
299#endif 321#endif