On Fri, Jan 22, 2021 at 6:41 PM Hans de Goede <hdegoede@xxxxxxxxxx> wrote: > > Convert the arizona extcon driver into a helper library for direct use > from the arizona codec-drivers, rather then being bound to a separate > MFD cell. > > Note the probe (and remove) sequence is split into 2 parts: > > 1. The arizona_jack_codec_dev_probe() function inits a bunch of > jack-detect specific variables in struct arizona_priv and tries to get > a number of resources where getting them may fail with -EPROBE_DEFER. > > 2. Then once the machine driver has create a snd_sock_jack through > snd_soc_card_jack_new() it calls snd_soc_component_set_jack() on > the codec component, which will call the new arizona_jack_set_jack(), > which sets up jack-detection and requests the IRQs. > > This split is necessary, because the IRQ handlers need access to the > arizona->dapm pointer and the snd_sock_jack which are not available > when the codec-driver's probe function runs. > > Note this requires that machine-drivers for codecs which are converted > to use the new helper functions from arizona-jack.c are modified to > create a snd_soc_jack through snd_soc_card_jack_new() and register > this jack with the codec through snd_soc_component_set_jack(). Okay, it seems that messages are on behalf of the parent while managed resources are being attached to the actual device. Reviewed-by: Andy Shevchenko <andy.shevchenko@xxxxxxxxx> > Signed-off-by: Hans de Goede <hdegoede@xxxxxxxxxx> > --- > Changes in v3: > - Pass dev (the codec-device) to devm_regulator_get instead of > passing arizona->dev. This is necessary so that the regulator gets > properly released when the coded driver unbinds. > --- > sound/soc/codecs/Makefile | 2 +- > sound/soc/codecs/arizona-jack.c | 125 +++++++++++++++----------------- > sound/soc/codecs/arizona.h | 6 ++ > 3 files changed, 65 insertions(+), 68 deletions(-) > > diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile > index d277f0366e09..2e976cfaa862 100644 > --- a/sound/soc/codecs/Makefile > +++ b/sound/soc/codecs/Makefile > @@ -43,7 +43,7 @@ snd-soc-ak4642-objs := ak4642.o > snd-soc-ak4671-objs := ak4671.o > snd-soc-ak5386-objs := ak5386.o > snd-soc-ak5558-objs := ak5558.o > -snd-soc-arizona-objs := arizona.o > +snd-soc-arizona-objs := arizona.o arizona-jack.o > snd-soc-bd28623-objs := bd28623.o > snd-soc-bt-sco-objs := bt-sco.o > snd-soc-cpcap-objs := cpcap.o > diff --git a/sound/soc/codecs/arizona-jack.c b/sound/soc/codecs/arizona-jack.c > index a6e8071f84ab..e121490eb379 100644 > --- a/sound/soc/codecs/arizona-jack.c > +++ b/sound/soc/codecs/arizona-jack.c > @@ -7,14 +7,12 @@ > > #include <linux/kernel.h> > #include <linux/module.h> > -#include <linux/i2c.h> > #include <linux/slab.h> > #include <linux/interrupt.h> > #include <linux/err.h> > #include <linux/gpio/consumer.h> > #include <linux/gpio.h> > #include <linux/input.h> > -#include <linux/platform_device.h> > #include <linux/pm_runtime.h> > #include <linux/property.h> > #include <linux/regulator/consumer.h> > @@ -1337,27 +1335,16 @@ static int arizona_extcon_device_get_pdata(struct device *dev, > return 0; > } > > -static int arizona_extcon_probe(struct platform_device *pdev) > +int arizona_jack_codec_dev_probe(struct arizona_priv *info, struct device *dev) > { > - struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); > + struct arizona *arizona = info->arizona; > struct arizona_pdata *pdata = &arizona->pdata; > - struct arizona_priv *info; > - unsigned int val; > - unsigned int clamp_mode; > - int jack_irq_fall, jack_irq_rise; > - int ret, mode, i, j; > - > - if (!arizona->dapm || !arizona->dapm->card) > - return -EPROBE_DEFER; > - > - info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); > - if (!info) > - return -ENOMEM; > + int ret, mode; > > if (!dev_get_platdata(arizona->dev)) > - arizona_extcon_device_get_pdata(&pdev->dev, arizona); > + arizona_extcon_device_get_pdata(dev, arizona); > > - info->micvdd = devm_regulator_get(&pdev->dev, "MICVDD"); > + info->micvdd = devm_regulator_get(dev, "MICVDD"); > if (IS_ERR(info->micvdd)) { > ret = PTR_ERR(info->micvdd); > dev_err(arizona->dev, "Failed to get MICVDD: %d\n", ret); > @@ -1365,12 +1352,10 @@ static int arizona_extcon_probe(struct platform_device *pdev) > } > > mutex_init(&info->lock); > - info->arizona = arizona; > info->last_jackdet = ~(ARIZONA_MICD_CLAMP_STS | ARIZONA_JD1_STS); > INIT_DELAYED_WORK(&info->hpdet_work, arizona_hpdet_work); > INIT_DELAYED_WORK(&info->micd_detect_work, arizona_micd_detect); > INIT_DELAYED_WORK(&info->micd_timeout_work, arizona_micd_timeout_work); > - platform_set_drvdata(pdev, info); > > switch (arizona->type) { > case WM5102: > @@ -1404,20 +1389,20 @@ static int arizona_extcon_probe(struct platform_device *pdev) > break; > } > > - info->edev = devm_extcon_dev_allocate(&pdev->dev, arizona_cable); > + info->edev = devm_extcon_dev_allocate(dev, arizona_cable); > if (IS_ERR(info->edev)) { > - dev_err(&pdev->dev, "failed to allocate extcon device\n"); > + dev_err(arizona->dev, "failed to allocate extcon device\n"); > return -ENOMEM; > } > > - ret = devm_extcon_dev_register(&pdev->dev, info->edev); > + ret = devm_extcon_dev_register(dev, info->edev); > if (ret < 0) { > dev_err(arizona->dev, "extcon_dev_register() failed: %d\n", > ret); > return ret; > } > > - info->input = devm_input_allocate_device(&pdev->dev); > + info->input = devm_input_allocate_device(dev); > if (!info->input) { > dev_err(arizona->dev, "Can't allocate input dev\n"); > ret = -ENOMEM; > @@ -1448,7 +1433,7 @@ static int arizona_extcon_probe(struct platform_device *pdev) > else > mode = GPIOF_OUT_INIT_LOW; > > - ret = devm_gpio_request_one(&pdev->dev, pdata->micd_pol_gpio, > + ret = devm_gpio_request_one(dev, pdata->micd_pol_gpio, > mode, "MICD polarity"); > if (ret != 0) { > dev_err(arizona->dev, "Failed to request GPIO%d: %d\n", > @@ -1481,17 +1466,38 @@ static int arizona_extcon_probe(struct platform_device *pdev) > } > > if (arizona->pdata.hpdet_id_gpio > 0) { > - ret = devm_gpio_request_one(&pdev->dev, > - arizona->pdata.hpdet_id_gpio, > + ret = devm_gpio_request_one(dev, arizona->pdata.hpdet_id_gpio, > GPIOF_OUT_INIT_LOW, > "HPDET"); > if (ret != 0) { > dev_err(arizona->dev, "Failed to request GPIO%d: %d\n", > arizona->pdata.hpdet_id_gpio, ret); > - goto err_gpio; > + gpiod_put(info->micd_pol_gpio); > + return ret; > } > } > > + return 0; > +} > +EXPORT_SYMBOL_GPL(arizona_jack_codec_dev_probe); > + > +int arizona_jack_codec_dev_remove(struct arizona_priv *info) > +{ > + gpiod_put(info->micd_pol_gpio); > + return 0; > +} > +EXPORT_SYMBOL_GPL(arizona_jack_codec_dev_remove); > + > +static int arizona_jack_enable_jack_detect(struct arizona_priv *info, > + struct snd_soc_jack *jack) > +{ > + struct arizona *arizona = info->arizona; > + struct arizona_pdata *pdata = &arizona->pdata; > + unsigned int val; > + unsigned int clamp_mode; > + int jack_irq_fall, jack_irq_rise; > + int ret, i, j; > + > if (arizona->pdata.micd_bias_start_time) > regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1, > ARIZONA_MICD_BIAS_STARTTIME_MASK, > @@ -1532,16 +1538,15 @@ static int arizona_extcon_probe(struct platform_device *pdev) > if (arizona->pdata.num_micd_ranges > ARIZONA_MAX_MICD_RANGE) { > dev_err(arizona->dev, "Too many MICD ranges: %d\n", > arizona->pdata.num_micd_ranges); > + return -EINVAL; > } > > if (info->num_micd_ranges > 1) { > for (i = 1; i < info->num_micd_ranges; i++) { > if (info->micd_ranges[i - 1].max > > info->micd_ranges[i].max) { > - dev_err(arizona->dev, > - "MICD ranges must be sorted\n"); > - ret = -EINVAL; > - goto err_gpio; > + dev_err(arizona->dev, "MICD ranges must be sorted\n"); > + return -EINVAL; > } > } > } > @@ -1559,8 +1564,7 @@ static int arizona_extcon_probe(struct platform_device *pdev) > if (j == ARIZONA_NUM_MICD_BUTTON_LEVELS) { > dev_err(arizona->dev, "Unsupported MICD level %d\n", > info->micd_ranges[i].max); > - ret = -EINVAL; > - goto err_gpio; > + return -EINVAL; > } > > dev_dbg(arizona->dev, "%d ohms for MICD threshold %d\n", > @@ -1629,43 +1633,40 @@ static int arizona_extcon_probe(struct platform_device *pdev) > ret = arizona_request_irq(arizona, jack_irq_rise, > "JACKDET rise", arizona_jackdet, info); > if (ret != 0) { > - dev_err(&pdev->dev, "Failed to get JACKDET rise IRQ: %d\n", > - ret); > + dev_err(arizona->dev, "Failed to get JACKDET rise IRQ: %d\n", ret); > goto err_pm; > } > > ret = arizona_set_irq_wake(arizona, jack_irq_rise, 1); > if (ret != 0) { > - dev_err(&pdev->dev, "Failed to set JD rise IRQ wake: %d\n", > - ret); > + dev_err(arizona->dev, "Failed to set JD rise IRQ wake: %d\n", ret); > goto err_rise; > } > > ret = arizona_request_irq(arizona, jack_irq_fall, > "JACKDET fall", arizona_jackdet, info); > if (ret != 0) { > - dev_err(&pdev->dev, "Failed to get JD fall IRQ: %d\n", ret); > + dev_err(arizona->dev, "Failed to get JD fall IRQ: %d\n", ret); > goto err_rise_wake; > } > > ret = arizona_set_irq_wake(arizona, jack_irq_fall, 1); > if (ret != 0) { > - dev_err(&pdev->dev, "Failed to set JD fall IRQ wake: %d\n", > - ret); > + dev_err(arizona->dev, "Failed to set JD fall IRQ wake: %d\n", ret); > goto err_fall; > } > > ret = arizona_request_irq(arizona, ARIZONA_IRQ_MICDET, > "MICDET", arizona_micdet, info); > if (ret != 0) { > - dev_err(&pdev->dev, "Failed to get MICDET IRQ: %d\n", ret); > + dev_err(arizona->dev, "Failed to get MICDET IRQ: %d\n", ret); > goto err_fall_wake; > } > > ret = arizona_request_irq(arizona, ARIZONA_IRQ_HPDET, > "HPDET", arizona_hpdet_irq, info); > if (ret != 0) { > - dev_err(&pdev->dev, "Failed to get HPDET IRQ: %d\n", ret); > + dev_err(arizona->dev, "Failed to get HPDET IRQ: %d\n", ret); > goto err_micdet; > } > > @@ -1677,12 +1678,11 @@ static int arizona_extcon_probe(struct platform_device *pdev) > > ret = regulator_allow_bypass(info->micvdd, true); > if (ret != 0) > - dev_warn(arizona->dev, "Failed to set MICVDD to bypass: %d\n", > - ret); > + dev_warn(arizona->dev, "Failed to set MICVDD to bypass: %d\n", ret); > > ret = input_register_device(info->input); > if (ret) { > - dev_err(&pdev->dev, "Can't register input device: %d\n", ret); > + dev_err(arizona->dev, "Can't register input device: %d\n", ret); > goto err_hpdet; > } > > @@ -1704,14 +1704,11 @@ static int arizona_extcon_probe(struct platform_device *pdev) > arizona_free_irq(arizona, jack_irq_rise, info); > err_pm: > pm_runtime_put(arizona->dev); > -err_gpio: > - gpiod_put(info->micd_pol_gpio); > return ret; > } > > -static int arizona_extcon_remove(struct platform_device *pdev) > +static int arizona_jack_disable_jack_detect(struct arizona_priv *info) > { > - struct arizona_priv *info = platform_get_drvdata(pdev); > struct arizona *arizona = info->arizona; > int jack_irq_rise, jack_irq_fall; > bool change; > @@ -1739,8 +1736,7 @@ static int arizona_extcon_remove(struct platform_device *pdev) > ARIZONA_MICD_ENA, 0, > &change); > if (ret < 0) { > - dev_err(&pdev->dev, "Failed to disable micd on remove: %d\n", > - ret); > + dev_err(arizona->dev, "Failed to disable micd on remove: %d\n", ret); > } else if (change) { > regulator_disable(info->micvdd); > pm_runtime_put(arizona->dev); > @@ -1753,22 +1749,17 @@ static int arizona_extcon_remove(struct platform_device *pdev) > ARIZONA_JD1_ENA, 0); > arizona_clk32k_disable(arizona); > > - gpiod_put(info->micd_pol_gpio); > - > return 0; > } > > -static struct platform_driver arizona_extcon_driver = { > - .driver = { > - .name = "arizona-extcon", > - }, > - .probe = arizona_extcon_probe, > - .remove = arizona_extcon_remove, > -}; > - > -module_platform_driver(arizona_extcon_driver); > +int arizona_jack_set_jack(struct snd_soc_component *component, > + struct snd_soc_jack *jack, void *data) > +{ > + struct arizona_priv *info = snd_soc_component_get_drvdata(component); > > -MODULE_DESCRIPTION("Arizona Extcon driver"); > -MODULE_AUTHOR("Mark Brown <broonie@xxxxxxxxxxxxxxxxxxxxxxxxxxx>"); > -MODULE_LICENSE("GPL"); > -MODULE_ALIAS("platform:extcon-arizona"); > + if (jack) > + return arizona_jack_enable_jack_detect(info, jack); > + else > + return arizona_jack_disable_jack_detect(info); > +} > +EXPORT_SYMBOL_GPL(arizona_jack_set_jack); > diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h > index 7132dbc3c840..fc515845a3e6 100644 > --- a/sound/soc/codecs/arizona.h > +++ b/sound/soc/codecs/arizona.h > @@ -386,4 +386,10 @@ static inline int arizona_unregister_notifier(struct snd_soc_component *componen > > int arizona_of_get_audio_pdata(struct arizona *arizona); > > +int arizona_jack_codec_dev_probe(struct arizona_priv *info, struct device *dev); > +int arizona_jack_codec_dev_remove(struct arizona_priv *info); > + > +int arizona_jack_set_jack(struct snd_soc_component *component, > + struct snd_soc_jack *jack, void *data); > + > #endif > -- > 2.28.0 > -- With Best Regards, Andy Shevchenko