Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8F457C433F5 for ; Thu, 25 Nov 2021 07:18:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231828AbhKYHVv (ORCPT ); Thu, 25 Nov 2021 02:21:51 -0500 Received: from smtp-out2.suse.de ([195.135.220.29]:46764 "EHLO smtp-out2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1349638AbhKYHTs (ORCPT ); Thu, 25 Nov 2021 02:19:48 -0500 Received: from relay2.suse.de (relay2.suse.de [149.44.160.134]) by smtp-out2.suse.de (Postfix) with ESMTP id DE7B31FD37; Thu, 25 Nov 2021 07:16:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1637824595; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=Bivuk8+TOfI88WAx+Dq2CA6QO4hbkTvK3r7JmyxWBDo=; b=BPAh724KjTcaM7uKk1k7LXxFUb04i9xuI0sFmsosYE17XXCS58y0e82FN+Jql8lEeZkqZX WDihlsdgUZwHdjJrNoCoxxF7oweC7y+hvwl03rAqqvY8iYOLSV3IqyAMi6kxqp8q8r2CgP oSk2MlNpo6ZcrNadlFneTPvEaT9y3Uw= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1637824595; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=Bivuk8+TOfI88WAx+Dq2CA6QO4hbkTvK3r7JmyxWBDo=; b=PZfSu3jh/frN9T5YmYM9ooocboq/KcoVOCFcQrgUW5DrMyUIjvaO4AInEAg/vZu/ibEOas gu2FFZL6qKCeeyDg== Received: from alsa1.suse.de (alsa1.suse.de [10.160.4.42]) by relay2.suse.de (Postfix) with ESMTP id C3CEFA3B83; Thu, 25 Nov 2021 07:16:35 +0000 (UTC) Date: Thu, 25 Nov 2021 08:16:35 +0100 Message-ID: From: Takashi Iwai To: Vitaly Rodionov Cc: James Schulman , David Rhodes , Liam Girdwood , Mark Brown , Jaroslav Kysela , Takashi Iwai , , , , Stefan Binding Subject: Re: [PATCH] ALSA: hda/cs8409: Schedule delayed work for jack detect on resume In-Reply-To: <20211124181908.50672-1-vitalyr@opensource.cirrus.com> References: <20211124181908.50672-1-vitalyr@opensource.cirrus.com> User-Agent: Wanderlust/2.15.9 (Almost Unreal) SEMI/1.14.6 (Maruoka) FLIM/1.14.9 (=?UTF-8?B?R29qxY0=?=) APEL/10.8 Emacs/25.3 (x86_64-suse-linux-gnu) MULE/6.0 (HANACHIRUSATO) MIME-Version: 1.0 (generated by SEMI 1.14.6 - "Maruoka") Content-Type: text/plain; charset=US-ASCII Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Wed, 24 Nov 2021 19:19:08 +0100, Vitaly Rodionov wrote: > > From: Stefan Binding > > CS42L42 runs jack detect on resume, however this requires unsol > events, and unsol events are ignored whilst the power state is > not set to ON. The power state is set to ON only after the resume > finishes. This statement isn't clear to me: which power state and who ignores? In the basic design of hda_jack, the all jack states get updated once after the resume by reading the pin sense. Doesn't this work in the case of cs8409 because the code relies on unsol event? > Schedule a delayed work timer to run jack detect > after the resume call finishes. This kind of approach is OK-ish as a last resort workaround, but I think it'd be cleaner to rewrite the code to use directly snd_jack stuff like HDMI codec driver without hda_jack stuff, supposing that all jack states on cs8409 are read rather via i2c. HDMI codec driver re-probes jacks at its own resume callback, and issue snd_jack_report() accordingly, as well as the same check for the unsol_event. Or, just faked unsol event handling at the resume callback would be minimalistic change, I suppose. thanks, Takashi > > Signed-off-by: Stefan Binding > Signed-off-by: Vitaly Rodionov > --- > sound/pci/hda/patch_cs8409.c | 79 +++++++++++++++++++++++++++++------- > sound/pci/hda/patch_cs8409.h | 1 + > 2 files changed, 65 insertions(+), 15 deletions(-) > > diff --git a/sound/pci/hda/patch_cs8409.c b/sound/pci/hda/patch_cs8409.c > index 31ff11ab868e..88213e95f0b3 100644 > --- a/sound/pci/hda/patch_cs8409.c > +++ b/sound/pci/hda/patch_cs8409.c > @@ -634,6 +634,30 @@ static void cs42l42_run_jack_detect(struct sub_codec *cs42l42) > cs8409_i2c_write(cs42l42, 0x1120, 0xc0); > } > > +static void cs42l42_run_jack_detect_all(struct hda_codec *codec) > +{ > + struct cs8409_spec *spec = codec->spec; > + struct sub_codec *cs42l42; > + int i; > + > + for (i = 0; i < spec->num_scodecs; i++) { > + cs42l42 = spec->scodecs[i]; > + cs42l42_enable_jack_detect(cs42l42); > + if (!cs42l42->hp_jack_in) > + cs42l42_run_jack_detect(cs42l42); > + } > +} > + > +/* > + * cs42l42_jack_detect_worker - Worker that retries jack detect > + */ > +static void cs42l42_jack_detect_worker(struct work_struct *work) > +{ > + struct cs8409_spec *spec = container_of(work, struct cs8409_spec, jack_detect_work.work); > + > + cs42l42_run_jack_detect_all(spec->codec); > +} > + > static int cs42l42_handle_tip_sense(struct sub_codec *cs42l42, unsigned int reg_ts_status) > { > int status_changed = 0; > @@ -749,8 +773,6 @@ static void cs42l42_resume(struct sub_codec *cs42l42) > > if (cs42l42->full_scale_vol) > cs8409_i2c_write(cs42l42, 0x2001, 0x01); > - > - cs42l42_enable_jack_detect(cs42l42); > } > > #ifdef CONFIG_PM > @@ -800,6 +822,7 @@ static void cs8409_free(struct hda_codec *codec) > > /* Cancel i2c clock disable timer, and disable clock if left enabled */ > cancel_delayed_work_sync(&spec->i2c_clk_work); > + cancel_delayed_work_sync(&spec->jack_detect_work); > cs8409_disable_i2c_clock(codec); > > snd_hda_gen_free(codec); > @@ -863,6 +886,7 @@ static int cs8409_cs42l42_suspend(struct hda_codec *codec) > > /* Cancel i2c clock disable timer, and disable clock if left enabled */ > cancel_delayed_work_sync(&spec->i2c_clk_work); > + cancel_delayed_work_sync(&spec->jack_detect_work); > cs8409_disable_i2c_clock(codec); > > snd_hda_shutup_pins(codec); > @@ -970,6 +994,8 @@ void cs8409_cs42l42_fixups(struct hda_codec *codec, const struct hda_fixup *fix, > spec->scodecs[CS8409_CODEC0]->codec = codec; > codec->patch_ops = cs8409_cs42l42_patch_ops; > > + INIT_DELAYED_WORK(&spec->jack_detect_work, cs42l42_jack_detect_worker); > + > spec->gen.suppress_auto_mute = 1; > spec->gen.no_primary_hp = 1; > spec->gen.suppress_vmaster = 1; > @@ -1029,9 +1055,16 @@ void cs8409_cs42l42_fixups(struct hda_codec *codec, const struct hda_fixup *fix, > case HDA_FIXUP_ACT_INIT: > cs8409_cs42l42_hw_init(codec); > spec->init_done = 1; > - if (spec->init_done && spec->build_ctrl_done > - && !spec->scodecs[CS8409_CODEC0]->hp_jack_in) > - cs42l42_run_jack_detect(spec->scodecs[CS8409_CODEC0]); > + if (spec->init_done && spec->build_ctrl_done) { > + /* No point in running jack detect until we have fully resumed */ > + if (codec->core.dev.power.power_state.event != PM_EVENT_ON) { > + codec_warn(codec, "Not ready to detect jack, deferring...\n"); > + schedule_delayed_work(&spec->jack_detect_work, msecs_to_jiffies(25)); > + return; > + } else { > + cs42l42_run_jack_detect_all(codec); > + } > + } > break; > case HDA_FIXUP_ACT_BUILD: > spec->build_ctrl_done = 1; > @@ -1040,9 +1073,16 @@ void cs8409_cs42l42_fixups(struct hda_codec *codec, const struct hda_fixup *fix, > * been already plugged in. > * Run immediately after init. > */ > - if (spec->init_done && spec->build_ctrl_done > - && !spec->scodecs[CS8409_CODEC0]->hp_jack_in) > - cs42l42_run_jack_detect(spec->scodecs[CS8409_CODEC0]); > + if (spec->init_done && spec->build_ctrl_done) { > + /* No point in running jack detect until we have fully resumed */ > + if (codec->core.dev.power.power_state.event != PM_EVENT_ON) { > + codec_warn(codec, "Not ready to detect jack, deferring...\n"); > + schedule_delayed_work(&spec->jack_detect_work, msecs_to_jiffies(25)); > + return; > + } else { > + cs42l42_run_jack_detect_all(codec); > + } > + } > break; > default: > break; > @@ -1178,7 +1218,6 @@ void dolphin_fixups(struct hda_codec *codec, const struct hda_fixup *fix, int ac > { > struct cs8409_spec *spec = codec->spec; > struct snd_kcontrol_new *kctrl; > - int i; > > switch (action) { > case HDA_FIXUP_ACT_PRE_PROBE: > @@ -1193,6 +1232,8 @@ void dolphin_fixups(struct hda_codec *codec, const struct hda_fixup *fix, int ac > spec->scodecs[CS8409_CODEC1]->codec = codec; > spec->num_scodecs = 2; > > + INIT_DELAYED_WORK(&spec->jack_detect_work, cs42l42_jack_detect_worker); > + > codec->patch_ops = cs8409_dolphin_patch_ops; > > /* GPIO 1,5 out, 0,4 in */ > @@ -1237,9 +1278,13 @@ void dolphin_fixups(struct hda_codec *codec, const struct hda_fixup *fix, int ac > dolphin_hw_init(codec); > spec->init_done = 1; > if (spec->init_done && spec->build_ctrl_done) { > - for (i = 0; i < spec->num_scodecs; i++) { > - if (!spec->scodecs[i]->hp_jack_in) > - cs42l42_run_jack_detect(spec->scodecs[i]); > + /* No point in running jack detect until we have fully resumed */ > + if (codec->core.dev.power.power_state.event != PM_EVENT_ON) { > + codec_warn(codec, "Not ready to detect jack, deferring...\n"); > + schedule_delayed_work(&spec->jack_detect_work, msecs_to_jiffies(25)); > + return; > + } else { > + cs42l42_run_jack_detect_all(codec); > } > } > break; > @@ -1251,9 +1296,13 @@ void dolphin_fixups(struct hda_codec *codec, const struct hda_fixup *fix, int ac > * Run immediately after init. > */ > if (spec->init_done && spec->build_ctrl_done) { > - for (i = 0; i < spec->num_scodecs; i++) { > - if (!spec->scodecs[i]->hp_jack_in) > - cs42l42_run_jack_detect(spec->scodecs[i]); > + /* No point in running jack detect until we have fully resumed */ > + if (codec->core.dev.power.power_state.event != PM_EVENT_ON) { > + codec_warn(codec, "Not ready to detect jack, deferring...\n"); > + schedule_delayed_work(&spec->jack_detect_work, msecs_to_jiffies(25)); > + return; > + } else { > + cs42l42_run_jack_detect_all(codec); > } > } > break; > diff --git a/sound/pci/hda/patch_cs8409.h b/sound/pci/hda/patch_cs8409.h > index ade2b838590c..632d3ec8322d 100644 > --- a/sound/pci/hda/patch_cs8409.h > +++ b/sound/pci/hda/patch_cs8409.h > @@ -330,6 +330,7 @@ struct cs8409_spec { > unsigned int i2c_clck_enabled; > unsigned int dev_addr; > struct delayed_work i2c_clk_work; > + struct delayed_work jack_detect_work; > > unsigned int playback_started:1; > unsigned int capture_started:1; > -- > 2.25.1 >