From 7d1cb2fa9651532d38cd8536c12836cdec02816b Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Mon, 8 Aug 2022 15:15:52 +0800 Subject: [PATCH] ASoC: rockchip: multicodecs: fix the invalid jack reference without codec_hp_det and gpio detection The crash log: ======== [ 6.807722] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000 [ 6.812273] Mem abort info: [ 6.812596] ESR = 0x96000006 [ 6.812899] EC = 0x25: DABT (current EL), IL = 32 bits [ 6.813439] SET = 0, FnV = 0 [ 6.813737] EA = 0, S1PTW = 0 [ 6.814037] Data abort info: [ 6.814316] ISV = 0, ISS = 0x00000006 [ 6.814733] CM = 0, WnR = 0 [ 6.815042] user pgtable: 4k pages, 39-bit VAs, pgdp=0000000002585000 [ 6.815676] [0000000000000000] pgd=0000000002584003, p4d=0000000002584003, pud=0000000002584003, pmd=0000000000000000 [ 6.816819] Internal error: Oops: 96000006 [#1] PREEMPT SMP [ 6.817341] Modules linked in: [ 6.817664] CPU: 1 PID: 64 Comm: kworker/u8:1 Not tainted 5.10.110 #151 [ 6.818268] Hardware name: Rockchip RK3308B-S evb analog mic v11 board (DT) [ 6.818923] Workqueue: events_power_efficient rk3308_codec_hpdetect_work [ 6.819549] pstate: 80000005 (Nzcv daif -PAN -UAO -TCO BTYPE=--) [ 6.820112] pc : __pi_strcmp+0x90/0x158 [ 6.820480] lr : dapm_find_widget+0xb0/0xec [ 6.820871] sp : ffffffc010cfbc20 Signed-off-by: Xing Zheng Change-Id: I6b0e8823353c34eb669e57a633e83a9945275a14 --- sound/soc/rockchip/rockchip_multicodecs.c | 74 +++++++++++++---------- 1 file changed, 43 insertions(+), 31 deletions(-) diff --git a/sound/soc/rockchip/rockchip_multicodecs.c b/sound/soc/rockchip/rockchip_multicodecs.c index cd1130f6e3cb..4529c3cb5b39 100644 --- a/sound/soc/rockchip/rockchip_multicodecs.c +++ b/sound/soc/rockchip/rockchip_multicodecs.c @@ -75,32 +75,6 @@ struct multicodecs_data { struct input_dev_poller *poller; }; -static struct snd_soc_jack_pin jack_pins[] = { - { - .pin = "Headphone", - .mask = SND_JACK_HEADPHONE, - }, { - .pin = "Headset Mic", - .mask = SND_JACK_MICROPHONE, - }, -}; - -static struct snd_soc_jack_zone headset_zones[] = { - { - .min_mv = 0, - .max_mv = 222, - .jack_type = SND_JACK_HEADPHONE, - }, { - .min_mv = 223, - .max_mv = 1500, - .jack_type = SND_JACK_HEADSET, - }, { - .min_mv = 1501, - .max_mv = UINT_MAX, - .jack_type = SND_JACK_HEADPHONE, - } -}; - static const unsigned int headset_extcon_cable[] = { EXTCON_JACK_MICROPHONE, EXTCON_JACK_HEADPHONE, @@ -397,19 +371,59 @@ static int rk_dailink_init(struct snd_soc_pcm_runtime *rtd) struct snd_soc_card *card = rtd->card; struct snd_soc_jack *jack_headset; int ret, irq; + struct snd_soc_jack_pin *pins; + struct snd_soc_jack_zone *zones; + struct snd_soc_jack_pin jack_pins[] = { + { + .pin = "Headphone", + .mask = SND_JACK_HEADPHONE, + }, { + .pin = "Headset Mic", + .mask = SND_JACK_MICROPHONE, + }, + }; + struct snd_soc_jack_zone headset_zones[] = { + { + .min_mv = 0, + .max_mv = 222, + .jack_type = SND_JACK_HEADPHONE, + }, { + .min_mv = 223, + .max_mv = 1500, + .jack_type = SND_JACK_HEADSET, + }, { + .min_mv = 1501, + .max_mv = UINT_MAX, + .jack_type = SND_JACK_HEADPHONE, + } + }; + + if ((!mc_data->codec_hp_det) && (gpiod_to_irq(mc_data->hp_det_gpio) < 0)) { + dev_info(card->dev, "Don't need to map headset detect gpio to irq\n"); + return 0; + } jack_headset = devm_kzalloc(card->dev, sizeof(*jack_headset), GFP_KERNEL); if (!jack_headset) return -ENOMEM; + pins = devm_kmemdup(card->dev, jack_pins, + sizeof(*jack_pins) * ARRAY_SIZE(jack_pins), GFP_KERNEL); + if (!pins) + return -ENOMEM; + + zones = devm_kmemdup(card->dev, headset_zones, + sizeof(*headset_zones) * ARRAY_SIZE(headset_zones), GFP_KERNEL); + if (!zones) + return -ENOMEM; + ret = snd_soc_card_jack_new(card, "Headset", SND_JACK_HEADSET, jack_headset, - jack_pins, ARRAY_SIZE(jack_pins)); + pins, ARRAY_SIZE(jack_pins)); if (ret) return ret; - ret = snd_soc_jack_add_zones(jack_headset, ARRAY_SIZE(headset_zones), - headset_zones); + ret = snd_soc_jack_add_zones(jack_headset, ARRAY_SIZE(headset_zones), zones); if (ret) return ret; @@ -436,8 +450,6 @@ static int rk_dailink_init(struct snd_soc_pcm_runtime *rtd) queue_delayed_work(system_power_efficient_wq, &mc_data->handler, msecs_to_jiffies(50)); - } else { - dev_warn(card->dev, "Failed to map headset detect gpio to irq"); } }