Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Improve cs42l43 suspend/IRQ interactions

Merge series from Charles Keepax <ckeepax@opensource.cirrus.com>:

cs42l43 uses pm_runtime_force_suspend() during system suspend, however
this means care must be taken that IRQ handler code isn't running when
entering system suspend as force suspend will ignore that the handler
is holding a pm reference. Typically the result of this is just a few
error messages, but better to improve the handling and ensure that all
IRQ processing is synchronised in before system suspend.

+86 -34
+5 -3
sound/soc/codecs/cs42l43-jack.c
··· 684 684 } 685 685 } 686 686 687 - static void cs42l43_clear_jack(struct cs42l43_codec *priv) 687 + void cs42l43_clear_jack(struct cs42l43_codec *priv) 688 688 { 689 689 struct cs42l43 *cs42l43 = priv->core; 690 690 ··· 703 703 regmap_update_bits(cs42l43->regmap, CS42L43_HS2, 704 704 CS42L43_HSDET_MODE_MASK | CS42L43_HSDET_MANUAL_MODE_MASK, 705 705 0x2 << CS42L43_HSDET_MODE_SHIFT); 706 - 707 - snd_soc_jack_report(priv->jack_hp, 0, 0xFFFF); 708 706 } 709 707 710 708 void cs42l43_tip_sense_work(struct work_struct *work) ··· 750 752 priv->jack_override = 0; 751 753 752 754 cs42l43_clear_jack(priv); 755 + 756 + snd_soc_jack_report(priv->jack_hp, 0, 0xFFFF); 753 757 754 758 if (cs42l43->sdw && priv->jack_present) { 755 759 pm_runtime_put(priv->dev); ··· 902 902 priv->jack_override = override; 903 903 904 904 cs42l43_clear_jack(priv); 905 + 906 + snd_soc_jack_report(priv->jack_hp, 0, 0xFFFF); 905 907 906 908 if (!override) { 907 909 queue_delayed_work(system_long_wq, &priv->tip_sense_work, 0);
+78 -31
sound/soc/codecs/cs42l43.c
··· 2210 2210 }; 2211 2211 2212 2212 static int cs42l43_request_irq(struct cs42l43_codec *priv, 2213 - struct irq_domain *dom, const char * const name, 2214 - unsigned int irq, irq_handler_t handler, 2215 - unsigned long flags) 2213 + const char * const name, unsigned int irq, 2214 + irq_handler_t handler, unsigned long flags) 2216 2215 { 2217 2216 int ret; 2218 2217 2219 - ret = irq_create_mapping(dom, irq); 2218 + ret = irq_create_mapping(priv->dom, irq); 2220 2219 if (ret < 0) 2221 2220 return dev_err_probe(priv->dev, ret, "Failed to map IRQ %s\n", name); 2222 2221 ··· 2229 2230 return 0; 2230 2231 } 2231 2232 2232 - static int cs42l43_shutter_irq(struct cs42l43_codec *priv, 2233 - struct irq_domain *dom, unsigned int shutter, 2234 - const char * const open_name, 2235 - const char * const close_name, 2233 + static void cs42l43_disable_irq(struct cs42l43_codec *priv, unsigned int irq) 2234 + { 2235 + int ret; 2236 + 2237 + ret = irq_find_mapping(priv->dom, irq); 2238 + if (ret > 0) 2239 + disable_irq(ret); 2240 + } 2241 + 2242 + static void cs42l43_enable_irq(struct cs42l43_codec *priv, unsigned int irq) 2243 + { 2244 + int ret; 2245 + 2246 + ret = irq_find_mapping(priv->dom, irq); 2247 + if (ret > 0) 2248 + enable_irq(ret); 2249 + } 2250 + 2251 + static int cs42l43_shutter_irq(struct cs42l43_codec *priv, unsigned int shutter, 2252 + const char * const open_name, unsigned int *open_irq, 2253 + const char * const close_name, unsigned int *close_irq, 2236 2254 irq_handler_t handler) 2237 2255 { 2238 - unsigned int open_irq, close_irq; 2239 2256 int ret; 2240 2257 2241 2258 switch (shutter) { ··· 2259 2244 dev_warn(priv->dev, "Manual shutters, notifications not available\n"); 2260 2245 return 0; 2261 2246 case 0x2: 2262 - open_irq = CS42L43_GPIO1_RISE; 2263 - close_irq = CS42L43_GPIO1_FALL; 2247 + *open_irq = CS42L43_GPIO1_RISE; 2248 + *close_irq = CS42L43_GPIO1_FALL; 2264 2249 break; 2265 2250 case 0x4: 2266 - open_irq = CS42L43_GPIO2_RISE; 2267 - close_irq = CS42L43_GPIO2_FALL; 2251 + *open_irq = CS42L43_GPIO2_RISE; 2252 + *close_irq = CS42L43_GPIO2_FALL; 2268 2253 break; 2269 2254 case 0x8: 2270 - open_irq = CS42L43_GPIO3_RISE; 2271 - close_irq = CS42L43_GPIO3_FALL; 2255 + *open_irq = CS42L43_GPIO3_RISE; 2256 + *close_irq = CS42L43_GPIO3_FALL; 2272 2257 break; 2273 2258 default: 2274 2259 return 0; 2275 2260 } 2276 2261 2277 - ret = cs42l43_request_irq(priv, dom, close_name, close_irq, handler, IRQF_SHARED); 2262 + ret = cs42l43_request_irq(priv, close_name, *close_irq, handler, IRQF_SHARED); 2278 2263 if (ret) 2279 2264 return ret; 2280 2265 2281 - return cs42l43_request_irq(priv, dom, open_name, open_irq, handler, IRQF_SHARED); 2266 + return cs42l43_request_irq(priv, open_name, *open_irq, handler, IRQF_SHARED); 2282 2267 } 2283 2268 2284 2269 static int cs42l43_codec_probe(struct platform_device *pdev) 2285 2270 { 2286 2271 struct cs42l43 *cs42l43 = dev_get_drvdata(pdev->dev.parent); 2287 2272 struct cs42l43_codec *priv; 2288 - struct irq_domain *dom; 2289 2273 unsigned int val; 2290 2274 int i, ret; 2291 - 2292 - dom = irq_find_matching_fwnode(dev_fwnode(cs42l43->dev), DOMAIN_BUS_ANY); 2293 - if (!dom) 2294 - return -EPROBE_DEFER; 2295 2275 2296 2276 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 2297 2277 if (!priv) ··· 2294 2284 2295 2285 priv->dev = &pdev->dev; 2296 2286 priv->core = cs42l43; 2287 + 2288 + priv->dom = irq_find_matching_fwnode(dev_fwnode(cs42l43->dev), DOMAIN_BUS_ANY); 2289 + if (!priv->dom) 2290 + return -EPROBE_DEFER; 2297 2291 2298 2292 platform_set_drvdata(pdev, priv); 2299 2293 ··· 2328 2314 goto err_pm; 2329 2315 2330 2316 for (i = 0; i < ARRAY_SIZE(cs42l43_irqs); i++) { 2331 - ret = cs42l43_request_irq(priv, dom, cs42l43_irqs[i].name, 2317 + ret = cs42l43_request_irq(priv, cs42l43_irqs[i].name, 2332 2318 cs42l43_irqs[i].irq, 2333 2319 cs42l43_irqs[i].handler, 0); 2334 2320 if (ret) ··· 2341 2327 goto err_pm; 2342 2328 } 2343 2329 2344 - ret = cs42l43_shutter_irq(priv, dom, val & CS42L43_MIC_SHUTTER_CFG_MASK, 2345 - "mic shutter open", "mic shutter close", 2330 + ret = cs42l43_shutter_irq(priv, val & CS42L43_MIC_SHUTTER_CFG_MASK, 2331 + "mic shutter open", &priv->shutter_irqs[0], 2332 + "mic shutter close", &priv->shutter_irqs[1], 2346 2333 cs42l43_mic_shutter); 2347 2334 if (ret) 2348 2335 goto err_pm; 2349 2336 2350 - ret = cs42l43_shutter_irq(priv, dom, (val & CS42L43_SPK_SHUTTER_CFG_MASK) >> 2337 + ret = cs42l43_shutter_irq(priv, (val & CS42L43_SPK_SHUTTER_CFG_MASK) >> 2351 2338 CS42L43_SPK_SHUTTER_CFG_SHIFT, 2352 - "spk shutter open", "spk shutter close", 2339 + "spk shutter open", &priv->shutter_irqs[2], 2340 + "spk shutter close", &priv->shutter_irqs[3], 2353 2341 cs42l43_spk_shutter); 2354 2342 if (ret) 2355 2343 goto err_pm; ··· 2402 2386 return 0; 2403 2387 } 2404 2388 2405 - static int cs42l43_codec_runtime_force_suspend(struct device *dev) 2389 + static int cs42l43_codec_suspend(struct device *dev) 2406 2390 { 2407 2391 struct cs42l43_codec *priv = dev_get_drvdata(dev); 2392 + int i; 2408 2393 2409 - dev_dbg(priv->dev, "Runtime suspend\n"); 2394 + dev_dbg(priv->dev, "System suspend\n"); 2410 2395 2411 2396 priv->suspend_jack_debounce = true; 2412 2397 2413 - pm_runtime_force_suspend(dev); 2398 + for (i = 0; i < ARRAY_SIZE(cs42l43_irqs); i++) 2399 + cs42l43_disable_irq(priv, cs42l43_irqs[i].irq); 2400 + 2401 + for (i = 0; i < ARRAY_SIZE(priv->shutter_irqs); i++) 2402 + if (priv->shutter_irqs[i]) 2403 + cs42l43_disable_irq(priv, priv->shutter_irqs[i]); 2404 + 2405 + cancel_delayed_work_sync(&priv->bias_sense_timeout); 2406 + cancel_delayed_work_sync(&priv->tip_sense_work); 2407 + cancel_delayed_work_sync(&priv->hp_ilimit_clear_work); 2408 + 2409 + cs42l43_clear_jack(priv); 2410 + 2411 + return pm_runtime_force_suspend(dev); 2412 + } 2413 + 2414 + static int cs42l43_codec_resume(struct device *dev) 2415 + { 2416 + struct cs42l43_codec *priv = dev_get_drvdata(dev); 2417 + int ret, i; 2418 + 2419 + ret = pm_runtime_force_resume(dev); 2420 + if (ret) 2421 + return ret; 2422 + 2423 + for (i = 0; i < ARRAY_SIZE(cs42l43_irqs); i++) 2424 + cs42l43_enable_irq(priv, cs42l43_irqs[i].irq); 2425 + 2426 + for (i = 0; i < ARRAY_SIZE(priv->shutter_irqs); i++) 2427 + if (priv->shutter_irqs[i]) 2428 + cs42l43_enable_irq(priv, priv->shutter_irqs[i]); 2414 2429 2415 2430 return 0; 2416 2431 } 2417 2432 2418 2433 static const struct dev_pm_ops cs42l43_codec_pm_ops = { 2419 2434 RUNTIME_PM_OPS(NULL, cs42l43_codec_runtime_resume, NULL) 2420 - SYSTEM_SLEEP_PM_OPS(cs42l43_codec_runtime_force_suspend, pm_runtime_force_resume) 2435 + SYSTEM_SLEEP_PM_OPS(cs42l43_codec_suspend, cs42l43_codec_resume) 2421 2436 }; 2422 2437 2423 2438 static const struct platform_device_id cs42l43_codec_id_table[] = {
+3
sound/soc/codecs/cs42l43.h
··· 44 44 struct device *dev; 45 45 struct cs42l43 *core; 46 46 struct snd_soc_component *component; 47 + struct irq_domain *dom; 48 + unsigned int shutter_irqs[4]; 47 49 48 50 struct clk *mclk; 49 51 ··· 132 130 int cs42l43_set_jack(struct snd_soc_component *component, 133 131 struct snd_soc_jack *jack, void *d); 134 132 void cs42l43_bias_sense_timeout(struct work_struct *work); 133 + void cs42l43_clear_jack(struct cs42l43_codec *priv); 135 134 void cs42l43_tip_sense_work(struct work_struct *work); 136 135 irqreturn_t cs42l43_bias_detect_clamp(int irq, void *data); 137 136 irqreturn_t cs42l43_button_press(int irq, void *data);