Commit 9dd90c5db0401061009183e6407feff3724ebc8b
Committed by
Mark Brown
1 parent
5f1cba63a3
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
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>
Showing 3 changed files with 191 additions and 1 deletions Side-by-side Diff
include/sound/max98095.h
... | ... | @@ -49,6 +49,18 @@ |
49 | 49 | */ |
50 | 50 | unsigned int digmic_left_mode:1; |
51 | 51 | unsigned int digmic_right_mode:1; |
52 | + | |
53 | + /* Pin5 is the mechanical method of sensing jack insertion | |
54 | + * but it is something that might not be supported. | |
55 | + * 0 = PIN5 not supported | |
56 | + * 1 = PIN5 supported | |
57 | + */ | |
58 | + int jack_detect_pin5en:1; | |
59 | + | |
60 | + /* Slew amount for jack detection. Calculated as 4 * (delay + 1). | |
61 | + * Default delay is 24 to get a time of 100ms. | |
62 | + */ | |
63 | + unsigned int jack_detect_delay; | |
52 | 64 | }; |
53 | 65 | |
54 | 66 | #endif |
sound/soc/codecs/max98095.c
... | ... | @@ -24,6 +24,7 @@ |
24 | 24 | #include <linux/slab.h> |
25 | 25 | #include <asm/div64.h> |
26 | 26 | #include <sound/max98095.h> |
27 | +#include <sound/jack.h> | |
27 | 28 | #include "max98095.h" |
28 | 29 | |
29 | 30 | enum max98095_type { |
... | ... | @@ -51,6 +52,8 @@ |
51 | 52 | u8 lin_state; |
52 | 53 | unsigned int mic1pre; |
53 | 54 | unsigned int mic2pre; |
55 | + struct snd_soc_jack *headphone_jack; | |
56 | + struct snd_soc_jack *mic_jack; | |
54 | 57 | }; |
55 | 58 | |
56 | 59 | static const u8 max98095_reg_def[M98095_REG_CNT] = { |
57 | 60 | |
... | ... | @@ -2173,9 +2176,125 @@ |
2173 | 2176 | max98095_handle_bq_pdata(codec); |
2174 | 2177 | } |
2175 | 2178 | |
2179 | +static 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 | + | |
2219 | +int 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 | + | |
2248 | +int 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 | + | |
2262 | +int 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 | 2290 | #ifdef CONFIG_PM |
2177 | 2291 | static 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 | 2298 | max98095_set_bias_level(codec, SND_SOC_BIAS_OFF); |
2180 | 2299 | |
2181 | 2300 | return 0; |
2182 | 2301 | |
... | ... | @@ -2183,8 +2302,16 @@ |
2183 | 2302 | |
2184 | 2303 | static 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 | 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 | 2315 | return 0; |
2189 | 2316 | } |
2190 | 2317 | #else |
... | ... | @@ -2227,6 +2354,7 @@ |
2227 | 2354 | { |
2228 | 2355 | struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec); |
2229 | 2356 | struct max98095_cdata *cdata; |
2357 | + struct i2c_client *client; | |
2230 | 2358 | int ret = 0; |
2231 | 2359 | |
2232 | 2360 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); |
... | ... | @@ -2238,6 +2366,8 @@ |
2238 | 2366 | /* reset the codec, the DSP core, and disable all interrupts */ |
2239 | 2367 | max98095_reset(codec); |
2240 | 2368 | |
2369 | + client = to_i2c_client(codec->dev); | |
2370 | + | |
2241 | 2371 | /* initialize private data */ |
2242 | 2372 | |
2243 | 2373 | max98095->sysclk = (unsigned)-1; |
2244 | 2374 | |
... | ... | @@ -2266,11 +2396,23 @@ |
2266 | 2396 | max98095->mic1pre = 0; |
2267 | 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 | 2411 | ret = snd_soc_read(codec, M98095_0FF_REV_ID); |
2270 | 2412 | if (ret < 0) { |
2271 | 2413 | dev_err(codec->dev, "Failure reading hardware revision: %d\n", |
2272 | 2414 | ret); |
2273 | - goto err_access; | |
2415 | + goto err_irq; | |
2274 | 2416 | } |
2275 | 2417 | dev_info(codec->dev, "Hardware revision: %c\n", ret - 0x40 + 'A'); |
2276 | 2418 | |
2277 | 2419 | |
2278 | 2420 | |
... | ... | @@ -2306,13 +2448,27 @@ |
2306 | 2448 | |
2307 | 2449 | max98095_add_widgets(codec); |
2308 | 2450 | |
2451 | + return 0; | |
2452 | + | |
2453 | +err_irq: | |
2454 | + if (client->irq) | |
2455 | + free_irq(client->irq, codec); | |
2309 | 2456 | err_access: |
2310 | 2457 | return ret; |
2311 | 2458 | } |
2312 | 2459 | |
2313 | 2460 | static 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 | 2465 | max98095_set_bias_level(codec, SND_SOC_BIAS_OFF); |
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); | |
2316 | 2472 | |
2317 | 2473 | return 0; |
2318 | 2474 | } |
sound/soc/codecs/max98095.h
... | ... | @@ -175,11 +175,23 @@ |
175 | 175 | |
176 | 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 | 184 | /* M98095_00F_HOST_CFG */ |
179 | 185 | #define M98095_SEG (1<<0) |
180 | 186 | #define M98095_XTEN (1<<1) |
181 | 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 | 195 | /* M98095_027_DAI1_CLKMODE, M98095_031_DAI2_CLKMODE, M98095_03B_DAI3_CLKMODE */ |
184 | 196 | #define M98095_CLKMODE_MASK 0xFF |
185 | 197 | |
... | ... | @@ -255,6 +267,10 @@ |
255 | 267 | #define M98095_EQ2EN (1<<1) |
256 | 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 | 274 | /* M98095_090_PWR_EN_IN */ |
259 | 275 | #define M98095_INEN (1<<7) |
260 | 276 | #define M98095_MB2EN (1<<3) |
... | ... | @@ -295,6 +311,12 @@ |
295 | 311 | /* Biquad filter coefficients */ |
296 | 312 | #define M98095_174_DAI1_BQ_BASE 0x74 |
297 | 313 | #define M98095_17E_DAI2_BQ_BASE 0x7E |
314 | + | |
315 | +/* Default Delay used in Slew Rate Calculation for Jack detection */ | |
316 | +#define M98095_DEFAULT_SLEW_DELAY 0x18 | |
317 | + | |
318 | +extern int max98095_jack_detect(struct snd_soc_codec *codec, | |
319 | + struct snd_soc_jack *hp_jack, struct snd_soc_jack *mic_jack); | |
298 | 320 | |
299 | 321 | #endif |