From nobody Tue May 5 10:00:43 2026 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 94137C433EF for ; Wed, 25 May 2022 13:17:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238254AbiEYNRR (ORCPT ); Wed, 25 May 2022 09:17:17 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34240 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229534AbiEYNQ5 (ORCPT ); Wed, 25 May 2022 09:16:57 -0400 Received: from mx0b-001ae601.pphosted.com (mx0b-001ae601.pphosted.com [67.231.152.168]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 07FECDFD7 for ; Wed, 25 May 2022 06:16:54 -0700 (PDT) Received: from pps.filterd (m0077474.ppops.net [127.0.0.1]) by mx0b-001ae601.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 24PCRmjC022096; Wed, 25 May 2022 08:16:41 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=JHd1cEuGVI49jnAS3O/MQco4oRcUWHd5HhuRNAkkA3U=; b=mC4tldRLl+uJywnn33bkHoJc2yipgYLSk3fdQnnQx9uQnoCBHKPfsiOkB00bzMQ3Vbph eVYHDrQNC0RcSS4YRF7S24WSXdaSJdqcGgEuKsPuQjmsOdn1dQXRpyIovK5ubvc3qKVX HrA8DmzTZekGG2Q7XFGqybhbQjasgV9hJqMP4l8DTP11UehkJqzWO4XM3PPstUjCNKi+ 2yQoUZAEn5Y1CjmvszlEEAaGHe8dyrp1JIaAWSNAHj0IP9E/+Fe6W1by9LtOruqi6MT9 akBEL9anIuSIWxRJYlGwGXzFiR7AJOKTKZFqt9CzOCytkTQQOhj6AuhFF7m0zNDq6cuz RA== Received: from ediex01.ad.cirrus.com ([84.19.233.68]) by mx0b-001ae601.pphosted.com (PPS) with ESMTPS id 3g93u20we6-2 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT); Wed, 25 May 2022 08:16:41 -0500 Received: from EDIEX01.ad.cirrus.com (198.61.84.80) by EDIEX01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.24; Wed, 25 May 2022 14:16:40 +0100 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by EDIEX01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server id 15.1.2375.24 via Frontend Transport; Wed, 25 May 2022 14:16:40 +0100 Received: from vitaly-Legion-7-16ACHg6.ad.cirrus.com (unknown [198.90.238.233]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id 41DEF46C; Wed, 25 May 2022 13:16:39 +0000 (UTC) From: Vitaly Rodionov To: Jaroslav Kysela , Takashi Iwai , Mark Brown CC: , , , Stefan Binding Subject: [PATCH v4 01/17] ALSA: hda: hda_cs_dsp_ctl: Add Library to support CS_DSP ALSA controls Date: Wed, 25 May 2022 14:16:22 +0100 Message-ID: <20220525131638.5512-2-vitalyr@opensource.cirrus.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220525131638.5512-1-vitalyr@opensource.cirrus.com> References: <20220525131638.5512-1-vitalyr@opensource.cirrus.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-ORIG-GUID: -9QvG60Jo91qrcHRzEAqQ6bryUsF_3QG X-Proofpoint-GUID: -9QvG60Jo91qrcHRzEAqQ6bryUsF_3QG X-Proofpoint-Spam-Reason: safe Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" From: Stefan Binding The cs35l41 part contains a DSP which is able to run firmware. The cs_dsp library can be used to control the DSP. These controls can be exposed to userspace using ALSA controls. This library adds apis to be able to interface between cs_dsp and hda drivers and expose the relevant controls as ALSA controls. The apis to add and remove the controls start new threads when adding/removing controls since it is possible that setting an ALSA control would end up calling this api, which would then deadlock. In the future, it will be necessary to load/unload firmware (and firmware ALSA controls) using a separate ALSA control, which means that the ability to call these apis from another ALSA control is required. Signed-off-by: Stefan Binding Signed-off-by: Vitaly Rodionov --- =20 Changes since v2: - Updated commit message to describe reasons for adding/removing controls asynchronously - Removed unnecessary code which handled unused tlv or acked controls. - Removed code which handled outdate firmware versions when adding controls =20 MAINTAINERS | 1 + sound/pci/hda/Kconfig | 4 + sound/pci/hda/Makefile | 2 + sound/pci/hda/hda_cs_dsp_ctl.c | 242 +++++++++++++++++++++++++++++++++ sound/pci/hda/hda_cs_dsp_ctl.h | 34 +++++ 5 files changed, 283 insertions(+) create mode 100644 sound/pci/hda/hda_cs_dsp_ctl.c create mode 100644 sound/pci/hda/hda_cs_dsp_ctl.h diff --git a/MAINTAINERS b/MAINTAINERS index 15674926a506..c47845b1332b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4695,6 +4695,7 @@ S: Maintained F: Documentation/devicetree/bindings/sound/cirrus,cs* F: include/dt-bindings/sound/cs* F: sound/pci/hda/cs* +F: sound/pci/hda/hda_cs_dsp_ctl.* F: sound/soc/codecs/cs* =20 CIRRUS LOGIC DSP FIRMWARE DRIVER diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig index 79ade4787d95..d1fd6cf82beb 100644 --- a/sound/pci/hda/Kconfig +++ b/sound/pci/hda/Kconfig @@ -94,6 +94,10 @@ config SND_HDA_PATCH_LOADER config SND_HDA_SCODEC_CS35L41 tristate =20 +config SND_HDA_CS_DSP_CONTROLS + tristate + depends on CS_DSP + config SND_HDA_SCODEC_CS35L41_I2C tristate "Build CS35L41 HD-audio side codec support for I2C Bus" depends on I2C diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile index 3e7bc608d45f..00d306104484 100644 --- a/sound/pci/hda/Makefile +++ b/sound/pci/hda/Makefile @@ -31,6 +31,7 @@ snd-hda-codec-hdmi-objs :=3D patch_hdmi.o hda_eld.o snd-hda-scodec-cs35l41-objs :=3D cs35l41_hda.o snd-hda-scodec-cs35l41-i2c-objs :=3D cs35l41_hda_i2c.o snd-hda-scodec-cs35l41-spi-objs :=3D cs35l41_hda_spi.o +snd-hda-cs-dsp-ctls-objs :=3D hda_cs_dsp_ctl.o =20 # common driver obj-$(CONFIG_SND_HDA) :=3D snd-hda-codec.o @@ -54,6 +55,7 @@ obj-$(CONFIG_SND_HDA_CODEC_HDMI) +=3D snd-hda-codec-hdmi.o obj-$(CONFIG_SND_HDA_SCODEC_CS35L41) +=3D snd-hda-scodec-cs35l41.o obj-$(CONFIG_SND_HDA_SCODEC_CS35L41_I2C) +=3D snd-hda-scodec-cs35l41-i2c.o obj-$(CONFIG_SND_HDA_SCODEC_CS35L41_SPI) +=3D snd-hda-scodec-cs35l41-spi.o +obj-$(CONFIG_SND_HDA_CS_DSP_CONTROLS) +=3D snd-hda-cs-dsp-ctls.o =20 # this must be the last entry after codec drivers; # otherwise the codec patches won't be hooked before the PCI probe diff --git a/sound/pci/hda/hda_cs_dsp_ctl.c b/sound/pci/hda/hda_cs_dsp_ctl.c new file mode 100644 index 000000000000..46df48ff2ae1 --- /dev/null +++ b/sound/pci/hda/hda_cs_dsp_ctl.c @@ -0,0 +1,242 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// HDA DSP ALSA Control Driver +// +// Copyright 2022 Cirrus Logic, Inc. +// +// Author: Stefan Binding + +#include +#include +#include +#include +#include "hda_cs_dsp_ctl.h" + +#define ADSP_MAX_STD_CTRL_SIZE 512 + +struct hda_cs_dsp_coeff_ctl { + const char *name; + struct cs_dsp_coeff_ctl *cs_ctl; + struct snd_card *card; + struct soc_bytes_ext bytes_ext; + struct work_struct add_work; + struct work_struct remove_work; +}; + +static const char * const hda_cs_dsp_fw_text[HDA_CS_DSP_NUM_FW] =3D { + [HDA_CS_DSP_FW_SPK_PROT] =3D "Prot", + [HDA_CS_DSP_FW_SPK_CALI] =3D "Cali", + [HDA_CS_DSP_FW_SPK_DIAG] =3D "Diag", + [HDA_CS_DSP_FW_MISC] =3D "Misc", +}; + +static inline struct hda_cs_dsp_coeff_ctl *bytes_ext_to_ctl(struct soc_byt= es_ext *ext) +{ + return container_of(ext, struct hda_cs_dsp_coeff_ctl, bytes_ext); +} + +static int hda_cs_dsp_coeff_info(struct snd_kcontrol *kctl, struct snd_ctl= _elem_info *uinfo) +{ + struct soc_bytes_ext *bytes_ext =3D + (struct soc_bytes_ext *)kctl->private_value; + struct hda_cs_dsp_coeff_ctl *ctl =3D bytes_ext_to_ctl(bytes_ext); + struct cs_dsp_coeff_ctl *cs_ctl =3D ctl->cs_ctl; + + uinfo->type =3D SNDRV_CTL_ELEM_TYPE_BYTES; + uinfo->count =3D cs_ctl->len; + + return 0; +} + +static int hda_cs_dsp_coeff_put(struct snd_kcontrol *kctl, struct snd_ctl_= elem_value *ucontrol) +{ + struct soc_bytes_ext *bytes_ext =3D + (struct soc_bytes_ext *)kctl->private_value; + struct hda_cs_dsp_coeff_ctl *ctl =3D bytes_ext_to_ctl(bytes_ext); + struct cs_dsp_coeff_ctl *cs_ctl =3D ctl->cs_ctl; + char *p =3D ucontrol->value.bytes.data; + int ret =3D 0; + + mutex_lock(&cs_ctl->dsp->pwr_lock); + ret =3D cs_dsp_coeff_write_ctrl(cs_ctl, 0, p, cs_ctl->len); + mutex_unlock(&cs_ctl->dsp->pwr_lock); + + return ret; +} + +static int hda_cs_dsp_coeff_get(struct snd_kcontrol *kctl, struct snd_ctl_= elem_value *ucontrol) +{ + struct soc_bytes_ext *bytes_ext =3D + (struct soc_bytes_ext *)kctl->private_value; + struct hda_cs_dsp_coeff_ctl *ctl =3D bytes_ext_to_ctl(bytes_ext); + struct cs_dsp_coeff_ctl *cs_ctl =3D ctl->cs_ctl; + char *p =3D ucontrol->value.bytes.data; + int ret; + + mutex_lock(&cs_ctl->dsp->pwr_lock); + ret =3D cs_dsp_coeff_read_ctrl(cs_ctl, 0, p, cs_ctl->len); + mutex_unlock(&cs_ctl->dsp->pwr_lock); + + return ret; +} + +static unsigned int wmfw_convert_flags(unsigned int in, unsigned int len) +{ + unsigned int out, rd, wr, vol; + + if (len > ADSP_MAX_STD_CTRL_SIZE) { + rd =3D SNDRV_CTL_ELEM_ACCESS_TLV_READ; + wr =3D SNDRV_CTL_ELEM_ACCESS_TLV_WRITE; + vol =3D SNDRV_CTL_ELEM_ACCESS_VOLATILE; + + out =3D SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK; + } else { + rd =3D SNDRV_CTL_ELEM_ACCESS_READ; + wr =3D SNDRV_CTL_ELEM_ACCESS_WRITE; + vol =3D SNDRV_CTL_ELEM_ACCESS_VOLATILE; + + out =3D 0; + } + + if (in) { + out |=3D rd; + if (in & WMFW_CTL_FLAG_WRITEABLE) + out |=3D wr; + if (in & WMFW_CTL_FLAG_VOLATILE) + out |=3D vol; + } else { + out |=3D rd | wr | vol; + } + + return out; +} + +static void hda_cs_dsp_ctl_add_work(struct work_struct *work) +{ + struct hda_cs_dsp_coeff_ctl *ctl =3D container_of(work, + struct hda_cs_dsp_coeff_ctl, + add_work); + struct cs_dsp_coeff_ctl *cs_ctl =3D ctl->cs_ctl; + struct snd_kcontrol_new *kcontrol; + + kcontrol =3D kzalloc(sizeof(*kcontrol), GFP_KERNEL); + if (!kcontrol) + return; + + kcontrol->name =3D ctl->name; + kcontrol->info =3D hda_cs_dsp_coeff_info; + kcontrol->iface =3D SNDRV_CTL_ELEM_IFACE_MIXER; + kcontrol->tlv.c =3D snd_soc_bytes_tlv_callback; + kcontrol->private_value =3D (unsigned long)&ctl->bytes_ext; + kcontrol->access =3D wmfw_convert_flags(cs_ctl->flags, cs_ctl->len); + + kcontrol->get =3D hda_cs_dsp_coeff_get; + kcontrol->put =3D hda_cs_dsp_coeff_put; + + if (snd_ctl_add(ctl->card, snd_ctl_new1(kcontrol, NULL))) + dev_err(cs_ctl->dsp->dev, "Failed to add KControl: %s\n", kcontrol->name= ); + else + dev_dbg(cs_ctl->dsp->dev, "Added KControl: %s\n", kcontrol->name); + + kfree(kcontrol); +} + +int hda_cs_dsp_control_add(struct cs_dsp_coeff_ctl *cs_ctl, struct hda_cs_= dsp_ctl_info *info) +{ + struct cs_dsp *cs_dsp =3D cs_ctl->dsp; + char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; + struct hda_cs_dsp_coeff_ctl *ctl; + const char *region_name; + int ret; + + if (cs_ctl->flags & WMFW_CTL_FLAG_SYS) { + dev_dbg(cs_dsp->dev, "cs_ctl->flags =3D WMFW_CTL_FLAG_SYS\n"); + return 0; + } + + region_name =3D cs_dsp_mem_region_name(cs_ctl->alg_region.type); + if (!region_name) { + dev_err(cs_dsp->dev, "Unknown region type: %d\n", cs_ctl->alg_region.typ= e); + return -EINVAL; + } + + ret =3D scnprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s %s %.12s %x", = info->amp_name, + cs_dsp->name, hda_cs_dsp_fw_text[info->fw_type], cs_ctl->alg_region.alg= ); + + if (cs_ctl->subname) { + int avail =3D SNDRV_CTL_ELEM_ID_NAME_MAXLEN - ret - 2; + int skip =3D 0; + + /* Truncate the subname from the start if it is too long */ + if (cs_ctl->subname_len > avail) + skip =3D cs_ctl->subname_len - avail; + + snprintf(name + ret, SNDRV_CTL_ELEM_ID_NAME_MAXLEN - ret, + " %.*s", cs_ctl->subname_len - skip, cs_ctl->subname + skip); + } + + ctl =3D kzalloc(sizeof(*ctl), GFP_KERNEL); + if (!ctl) + return -ENOMEM; + ctl->cs_ctl =3D cs_ctl; + ctl->card =3D info->card; + + ctl->name =3D kmemdup(name, strlen(name) + 1, GFP_KERNEL); + if (!ctl->name) { + ret =3D -ENOMEM; + dev_err(cs_dsp->dev, "Cannot save ctl name\n"); + goto err_ctl; + } + + cs_ctl->priv =3D ctl; + + INIT_WORK(&ctl->add_work, hda_cs_dsp_ctl_add_work); + schedule_work(&ctl->add_work); + + return 0; + +err_ctl: + dev_err(cs_dsp->dev, "Error adding control: %s\n", name); + kfree(ctl); + return ret; +} +EXPORT_SYMBOL_NS_GPL(hda_cs_dsp_control_add, SND_HDA_CS_DSP_CONTROLS); + +int hda_cs_dsp_remove_kcontrol(struct snd_card *card, const char *name) +{ + struct snd_kcontrol *kctl; + + list_for_each_entry(kctl, &card->controls, list) + if (!strncmp(kctl->id.name, name, sizeof(kctl->id.name))) + return snd_ctl_remove_id(card, &kctl->id); + + return -EINVAL; +} +EXPORT_SYMBOL_NS_GPL(hda_cs_dsp_remove_kcontrol, SND_HDA_CS_DSP_CONTROLS); + +static void hda_cs_dsp_ctl_del_work(struct work_struct *work) +{ + struct hda_cs_dsp_coeff_ctl *ctl =3D container_of(work, + struct hda_cs_dsp_coeff_ctl, + remove_work); + + cancel_work_sync(&ctl->add_work); + + hda_cs_dsp_remove_kcontrol(ctl->card, ctl->name); + + kfree(ctl->name); + kfree(ctl); +} + +void hda_cs_dsp_control_remove(struct cs_dsp_coeff_ctl *cs_ctl) +{ + struct hda_cs_dsp_coeff_ctl *ctl =3D cs_ctl->priv; + + INIT_WORK(&ctl->remove_work, hda_cs_dsp_ctl_del_work); + schedule_work(&ctl->remove_work); +} +EXPORT_SYMBOL_NS_GPL(hda_cs_dsp_control_remove, SND_HDA_CS_DSP_CONTROLS); + +MODULE_DESCRIPTION("CS_DSP ALSA Control HDA Library"); +MODULE_AUTHOR("Stefan Binding, "); +MODULE_LICENSE("GPL"); diff --git a/sound/pci/hda/hda_cs_dsp_ctl.h b/sound/pci/hda/hda_cs_dsp_ctl.h new file mode 100644 index 000000000000..3c90312b45d6 --- /dev/null +++ b/sound/pci/hda/hda_cs_dsp_ctl.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * HDA DSP ALSA Control Driver + * + * Copyright 2022 Cirrus Logic, Inc. + * + * Author: Stefan Binding + */ + +#ifndef __HDA_CS_DSP_CTL_H__ +#define __HDA_CS_DSP_CTL_H__ + +#include +#include + +enum hda_cs_dsp_fw_id { + HDA_CS_DSP_FW_SPK_PROT, + HDA_CS_DSP_FW_SPK_CALI, + HDA_CS_DSP_FW_SPK_DIAG, + HDA_CS_DSP_FW_MISC, + HDA_CS_DSP_NUM_FW +}; + +struct hda_cs_dsp_ctl_info { + struct snd_card *card; + enum hda_cs_dsp_fw_id fw_type; + const char *amp_name; +}; + +int hda_cs_dsp_control_add(struct cs_dsp_coeff_ctl *cs_ctl, struct hda_cs_= dsp_ctl_info *info); +void hda_cs_dsp_control_remove(struct cs_dsp_coeff_ctl *cs_ctl); +int hda_cs_dsp_remove_kcontrol(struct snd_card *card, const char *name); + +#endif /*__HDA_CS_DSP_CTL_H__*/ --=20 2.34.1 From nobody Tue May 5 10:00:43 2026 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 3D249C433EF for ; Wed, 25 May 2022 13:18:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244312AbiEYNSO (ORCPT ); Wed, 25 May 2022 09:18:14 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34664 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244091AbiEYNRE (ORCPT ); Wed, 25 May 2022 09:17:04 -0400 Received: from mx0b-001ae601.pphosted.com (mx0a-001ae601.pphosted.com [67.231.149.25]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C2281DFFE for ; Wed, 25 May 2022 06:17:02 -0700 (PDT) Received: from pps.filterd (m0077473.ppops.net [127.0.0.1]) by mx0a-001ae601.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 24PBxMvb005635; Wed, 25 May 2022 08:16:42 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=J0fR9KNlFufNc0MdSXybhI4lFVPpHlH9P+kE1CluQgE=; b=ZertTB1lJ1Tkn3b7rDKVsZH1nQ51SPMOzFc/u8kqPDRtbsU52Y8Nza29N8arOX6zp2Mc ompu5q+ovPeeDQJYlTN47v1Wahu7mWW0NNHymlaz1RK2IIH5fkOc1cIH/KTYmlJjjh55 hHa4xOaTtW6igQdorYeYGQQa3uNZ3pDx4uq293LiKsoBt78a+F0biQ6yPrppe81kkZ+P sQEcH9NWoAhnW8J983J6zedDz0ltXluh+6mJRoKAn+rAx7/KoQB4mOp8JtXrWYsOJq2e Tz3YEuPSDfuN3C1XK28Z9ZJLLiytzNTga6dU/8o6I72Nq+s2kaswIdEpHcJxlEsCcEtO LQ== Received: from ediex02.ad.cirrus.com ([84.19.233.68]) by mx0a-001ae601.pphosted.com (PPS) with ESMTPS id 3g93u4gx4s-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT); Wed, 25 May 2022 08:16:42 -0500 Received: from EDIEX01.ad.cirrus.com (198.61.84.80) by EDIEX02.ad.cirrus.com (198.61.84.81) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.24; Wed, 25 May 2022 14:16:40 +0100 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by EDIEX01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server id 15.1.2375.24 via Frontend Transport; Wed, 25 May 2022 14:16:40 +0100 Received: from vitaly-Legion-7-16ACHg6.ad.cirrus.com (unknown [198.90.238.233]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id 2A8B5468; Wed, 25 May 2022 13:16:40 +0000 (UTC) From: Vitaly Rodionov To: Jaroslav Kysela , Takashi Iwai , Mark Brown CC: , , , Stefan Binding Subject: [PATCH v4 02/17] ALSA: hda: hda_cs_dsp_ctl: Add apis to write the controls directly Date: Wed, 25 May 2022 14:16:23 +0100 Message-ID: <20220525131638.5512-3-vitalyr@opensource.cirrus.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220525131638.5512-1-vitalyr@opensource.cirrus.com> References: <20220525131638.5512-1-vitalyr@opensource.cirrus.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-ORIG-GUID: r0-ty98q_QKxfTnhHLoiMuyOT_uSqERn X-Proofpoint-GUID: r0-ty98q_QKxfTnhHLoiMuyOT_uSqERn X-Proofpoint-Spam-Reason: safe Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" From: Stefan Binding DSP controls are exposed as ALSA controls, however, some of these controls are required to be accessed by the driver. Add apis which allow read/write of these controls. The write api will also notify the ALSA control on value change. Signed-off-by: Stefan Binding Signed-off-by: Vitaly Rodionov --- Changes since v2: - No change sound/pci/hda/hda_cs_dsp_ctl.c | 52 ++++++++++++++++++++++++++++++++++ sound/pci/hda/hda_cs_dsp_ctl.h | 4 +++ 2 files changed, 56 insertions(+) diff --git a/sound/pci/hda/hda_cs_dsp_ctl.c b/sound/pci/hda/hda_cs_dsp_ctl.c index 46df48ff2ae1..3b837d000a00 100644 --- a/sound/pci/hda/hda_cs_dsp_ctl.c +++ b/sound/pci/hda/hda_cs_dsp_ctl.c @@ -237,6 +237,58 @@ void hda_cs_dsp_control_remove(struct cs_dsp_coeff_ctl= *cs_ctl) } EXPORT_SYMBOL_NS_GPL(hda_cs_dsp_control_remove, SND_HDA_CS_DSP_CONTROLS); =20 +int hda_cs_dsp_write_ctl(struct cs_dsp *dsp, const char *name, int type, + unsigned int alg, void *buf, size_t len) +{ + struct cs_dsp_coeff_ctl *cs_ctl; + struct hda_cs_dsp_coeff_ctl *ctl; + struct snd_kcontrol *kctl; + int ret; + + cs_ctl =3D cs_dsp_get_ctl(dsp, name, type, alg); + if (!cs_ctl) + return -EINVAL; + + ctl =3D cs_ctl->priv; + + if (len > cs_ctl->len) + return -EINVAL; + + ret =3D cs_dsp_coeff_write_ctrl(cs_ctl, 0, buf, len); + if (ret) + return ret; + + if (cs_ctl->flags & WMFW_CTL_FLAG_SYS) + return 0; + + list_for_each_entry(kctl, &ctl->card->controls, list) + if (!strncmp(kctl->id.name, ctl->name, sizeof(kctl->id.name))) { + snd_ctl_notify(ctl->card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id); + return 0; + } + + dev_warn(dsp->dev, "Cannot find Control for %s\n", name); + + return 0; +} +EXPORT_SYMBOL_NS_GPL(hda_cs_dsp_write_ctl, SND_HDA_CS_DSP_CONTROLS); + +int hda_cs_dsp_read_ctl(struct cs_dsp *dsp, const char *name, int type, + unsigned int alg, void *buf, size_t len) +{ + struct cs_dsp_coeff_ctl *cs_ctl; + + cs_ctl =3D cs_dsp_get_ctl(dsp, name, type, alg); + if (!cs_ctl) + return -EINVAL; + + if (len > cs_ctl->len) + return -EINVAL; + + return cs_dsp_coeff_read_ctrl(cs_ctl, 0, buf, len); +} +EXPORT_SYMBOL_NS_GPL(hda_cs_dsp_read_ctl, SND_HDA_CS_DSP_CONTROLS); + MODULE_DESCRIPTION("CS_DSP ALSA Control HDA Library"); MODULE_AUTHOR("Stefan Binding, "); MODULE_LICENSE("GPL"); diff --git a/sound/pci/hda/hda_cs_dsp_ctl.h b/sound/pci/hda/hda_cs_dsp_ctl.h index 3c90312b45d6..65b9c5c68957 100644 --- a/sound/pci/hda/hda_cs_dsp_ctl.h +++ b/sound/pci/hda/hda_cs_dsp_ctl.h @@ -30,5 +30,9 @@ struct hda_cs_dsp_ctl_info { int hda_cs_dsp_control_add(struct cs_dsp_coeff_ctl *cs_ctl, struct hda_cs_= dsp_ctl_info *info); void hda_cs_dsp_control_remove(struct cs_dsp_coeff_ctl *cs_ctl); int hda_cs_dsp_remove_kcontrol(struct snd_card *card, const char *name); +int hda_cs_dsp_write_ctl(struct cs_dsp *dsp, const char *name, int type, + unsigned int alg, void *buf, size_t len); +int hda_cs_dsp_read_ctl(struct cs_dsp *dsp, const char *name, int type, + unsigned int alg, void *buf, size_t len); =20 #endif /*__HDA_CS_DSP_CTL_H__*/ --=20 2.34.1 From nobody Tue May 5 10:00:43 2026 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 90534C433F5 for ; Wed, 25 May 2022 13:17:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244299AbiEYNR3 (ORCPT ); Wed, 25 May 2022 09:17:29 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34364 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234869AbiEYNQ7 (ORCPT ); Wed, 25 May 2022 09:16:59 -0400 Received: from mx0b-001ae601.pphosted.com (mx0b-001ae601.pphosted.com [67.231.152.168]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9375AE000 for ; Wed, 25 May 2022 06:16:55 -0700 (PDT) Received: from pps.filterd (m0077474.ppops.net [127.0.0.1]) by mx0b-001ae601.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 24PCRmjD022096; Wed, 25 May 2022 08:16:42 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=i7lw6DOkLlBNhuFgnm6YHtLKyoQAfOY/+S/HCRu3sx8=; b=cMF1YJ+bB/91I6V+BAzdglfZmsg8XyxKs3JBuuX96ZEqDQByDNbUATghpAq1KqNilQTk Fw4tTZ8x/NRpkcriKmtbAXx0MT6Epxl0EgrcLZZJK5wm/i5Kq/7TILAm+4AHhxik8Qtt dXslTCNLfw+QChDHKTtNgrwX3s5vNYoyV7WbOkjOfBN9yeI8YVXn5sJxZjQpndTAsbtm +fM12vX5rNUqDS3i4RW/TjJj5O1Zi6+2m1m0gWtLCD/Ifudox6TDdb4tTZZ7+6/Lwd6k 1hTzaDLR0CrruRxh5BNmO9FHzovh2RjKEy6FFscGVD1DcWFpZvbqFeILTewL+PkDcy0U yw== Received: from ediex01.ad.cirrus.com ([84.19.233.68]) by mx0b-001ae601.pphosted.com (PPS) with ESMTPS id 3g93u20we6-3 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT); Wed, 25 May 2022 08:16:42 -0500 Received: from EDIEX01.ad.cirrus.com (198.61.84.80) by EDIEX01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.24; Wed, 25 May 2022 14:16:40 +0100 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by EDIEX01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server id 15.1.2375.24 via Frontend Transport; Wed, 25 May 2022 14:16:40 +0100 Received: from vitaly-Legion-7-16ACHg6.ad.cirrus.com (unknown [198.90.238.233]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id 8D02546C; Wed, 25 May 2022 13:16:40 +0000 (UTC) From: Vitaly Rodionov To: Jaroslav Kysela , Takashi Iwai , Mark Brown CC: , , , Stefan Binding Subject: [PATCH v4 03/17] ALSA: hda: cs35l41: Save codec object inside component struct Date: Wed, 25 May 2022 14:16:24 +0100 Message-ID: <20220525131638.5512-4-vitalyr@opensource.cirrus.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220525131638.5512-1-vitalyr@opensource.cirrus.com> References: <20220525131638.5512-1-vitalyr@opensource.cirrus.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-ORIG-GUID: 24KTQH9yo1OnROhtqO6VGewz92BYlJ7B X-Proofpoint-GUID: 24KTQH9yo1OnROhtqO6VGewz92BYlJ7B X-Proofpoint-Spam-Reason: safe Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" From: Stefan Binding This is required for ALSA control support. Signed-off-by: Stefan Binding Signed-off-by: Vitaly Rodionov --- Changes since v2: - No change =20 sound/pci/hda/cs35l41_hda.c | 1 + sound/pci/hda/cs35l41_hda.h | 1 + sound/pci/hda/hda_component.h | 1 + sound/pci/hda/patch_realtek.c | 1 + 4 files changed, 4 insertions(+) diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c index cce27a86267f..bbbaafac50c3 100644 --- a/sound/pci/hda/cs35l41_hda.c +++ b/sound/pci/hda/cs35l41_hda.c @@ -117,6 +117,7 @@ static int cs35l41_hda_bind(struct device *dev, struct = device *master, void *mas return -EBUSY; =20 comps->dev =3D dev; + cs35l41->codec =3D comps->codec; strscpy(comps->name, dev_name(dev), sizeof(comps->name)); comps->playback_hook =3D cs35l41_hda_playback_hook; =20 diff --git a/sound/pci/hda/cs35l41_hda.h b/sound/pci/hda/cs35l41_hda.h index a52ffd1f7999..aaf9e16684c2 100644 --- a/sound/pci/hda/cs35l41_hda.h +++ b/sound/pci/hda/cs35l41_hda.h @@ -32,6 +32,7 @@ struct cs35l41_hda { struct regmap *regmap; struct gpio_desc *reset_gpio; struct cs35l41_hw_cfg hw_cfg; + struct hda_codec *codec; =20 int irq; int index; diff --git a/sound/pci/hda/hda_component.h b/sound/pci/hda/hda_component.h index e26c896a13f3..534e845b9cd1 100644 --- a/sound/pci/hda/hda_component.h +++ b/sound/pci/hda/hda_component.h @@ -14,5 +14,6 @@ struct hda_component { struct device *dev; char name[HDA_MAX_NAME_SIZE]; + struct hda_codec *codec; void (*playback_hook)(struct device *dev, int action); }; diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 80e4955e8c10..cd289b17ca13 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6631,6 +6631,7 @@ static void cs35l41_generic_fixup(struct hda_codec *c= dc, int action, const char "%s-%s:00-cs35l41-hda.%d", bus, hid, i); if (!name) return; + spec->comps[i].codec =3D cdc; component_match_add(dev, &spec->match, component_compare_dev_name, name= ); } ret =3D component_master_add_with_match(dev, &comp_master_ops, spec->mat= ch); --=20 2.34.1 From nobody Tue May 5 10:00:43 2026 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 B1F7FC433EF for ; Wed, 25 May 2022 13:18:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243984AbiEYNSf (ORCPT ); Wed, 25 May 2022 09:18:35 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37726 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244405AbiEYNRl (ORCPT ); Wed, 25 May 2022 09:17:41 -0400 Received: from mx0b-001ae601.pphosted.com (mx0a-001ae601.pphosted.com [67.231.149.25]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B563D11160 for ; Wed, 25 May 2022 06:17:35 -0700 (PDT) Received: from pps.filterd (m0077473.ppops.net [127.0.0.1]) by mx0a-001ae601.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 24PBxMvc005635; Wed, 25 May 2022 08:16:43 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=9mk8bGRr0pPSUQM7ozDYripyLIZEGJAyaNtwJgsEZqw=; b=loP1Fv7e4SU42LGMwD7QIMIO+dLnuh/I2gGRQ4ueUBsQVgZhJPEy8G/p429eUQgzMm3p vIIU6P5AKZ425FvhEJXUvvZMEsWN+JKQLAVETHYI7AcrTUP4wfzrRBtESPD8R7mi1BMd MHYSlVvhpM3n/mggynF/QY44wn0vqH+tgULkFq+PT/OGsn3YrCTk5ukBjDSVL3UZ29HF H6Sd0ZePRg/fhLKWD8VSVxWFBXTSNRF5odmANrGTwOhaT0EejSyuJUQ23MHtGMQe3TmE IvNvIY99tkl2Uvl8j/OrC32EXLgz+wWsWTMNow/IsCRlwvtlAdnfQdaQZnBKM/x7qn2m vg== Received: from ediex02.ad.cirrus.com ([84.19.233.68]) by mx0a-001ae601.pphosted.com (PPS) with ESMTPS id 3g93u4gx4s-2 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT); Wed, 25 May 2022 08:16:43 -0500 Received: from EDIEX01.ad.cirrus.com (198.61.84.80) by EDIEX02.ad.cirrus.com (198.61.84.81) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.24; Wed, 25 May 2022 14:16:41 +0100 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by EDIEX01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server id 15.1.2375.24 via Frontend Transport; Wed, 25 May 2022 14:16:41 +0100 Received: from vitaly-Legion-7-16ACHg6.ad.cirrus.com (unknown [198.90.238.233]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id F35F411D1; Wed, 25 May 2022 13:16:40 +0000 (UTC) From: Vitaly Rodionov To: Jaroslav Kysela , Takashi Iwai , "Mark Brown" CC: , , , Vitaly Rodionov Subject: [PATCH v4 04/17] ALSA: hda: cs35l41: Add initial DSP support and firmware loading Date: Wed, 25 May 2022 14:16:25 +0100 Message-ID: <20220525131638.5512-5-vitalyr@opensource.cirrus.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220525131638.5512-1-vitalyr@opensource.cirrus.com> References: <20220525131638.5512-1-vitalyr@opensource.cirrus.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-ORIG-GUID: rwzsaCbprE5Bfx8vixY_CD1L253_r4z4 X-Proofpoint-GUID: rwzsaCbprE5Bfx8vixY_CD1L253_r4z4 X-Proofpoint-Spam-Reason: safe Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" From: Vitaly Rodionov This patch adds support for the CS35L41 DSP. The DSP allows for extra features, such as running speaker protection algorithms and hibernations. To utilize these features, the driver must load firmware into the DSP, as well as various tuning files which allow for cusomtization for specific models. Signed-off-by: Vitaly Rodionov Signed-off-by: Vitaly Rodionov --- Changes since v2: - No change =20 include/sound/cs35l41.h | 4 + sound/pci/hda/Kconfig | 4 + sound/pci/hda/cs35l41_hda.c | 238 +++++++++++++++++++++++++++++++++++- sound/pci/hda/cs35l41_hda.h | 12 ++ 4 files changed, 257 insertions(+), 1 deletion(-) diff --git a/include/sound/cs35l41.h b/include/sound/cs35l41.h index 8972fa697622..8887087815a7 100644 --- a/include/sound/cs35l41.h +++ b/include/sound/cs35l41.h @@ -665,6 +665,10 @@ #define CS35L41_BST_EN_DEFAULT 0x2 #define CS35L41_AMP_EN_SHIFT 0 #define CS35L41_AMP_EN_MASK 1 +#define CS35L41_VMON_EN_MASK 0x1000 +#define CS35L41_VMON_EN_SHIFT 12 +#define CS35L41_IMON_EN_MASK 0x2000 +#define CS35L41_IMON_EN_SHIFT 13 =20 #define CS35L41_PDN_DONE_MASK 0x00800000 #define CS35L41_PDN_DONE_SHIFT 23 diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig index d1fd6cf82beb..1c378cca5dac 100644 --- a/sound/pci/hda/Kconfig +++ b/sound/pci/hda/Kconfig @@ -106,6 +106,8 @@ config SND_HDA_SCODEC_CS35L41_I2C select SND_HDA_GENERIC select SND_SOC_CS35L41_LIB select SND_HDA_SCODEC_CS35L41 + select SND_HDA_CS_DSP_CONTROLS + select CS_DSP select REGMAP_IRQ help Say Y or M here to include CS35L41 I2C HD-audio side codec support @@ -122,6 +124,8 @@ config SND_HDA_SCODEC_CS35L41_SPI select SND_HDA_GENERIC select SND_SOC_CS35L41_LIB select SND_HDA_SCODEC_CS35L41 + select SND_HDA_CS_DSP_CONTROLS + select CS_DSP select REGMAP_IRQ help Say Y or M here to include CS35L41 SPI HD-audio side codec support diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c index bbbaafac50c3..fe2ba03e602b 100644 --- a/sound/pci/hda/cs35l41_hda.c +++ b/sound/pci/hda/cs35l41_hda.c @@ -9,12 +9,22 @@ #include #include #include +#include #include "hda_local.h" #include "hda_auto_parser.h" #include "hda_jack.h" #include "hda_generic.h" #include "hda_component.h" #include "cs35l41_hda.h" +#include "hda_cs_dsp_ctl.h" + +#define CS35L41_FIRMWARE_ROOT "cirrus/" +#define CS35L41_PART "cs35l41" +#define FW_NAME "CSPL" + +#define HALO_STATE_DSP_CTL_NAME "HALO_STATE" +#define HALO_STATE_DSP_CTL_TYPE 5 +#define HALO_STATE_DSP_CTL_ALG 262308 =20 static const struct reg_sequence cs35l41_hda_config[] =3D { { CS35L41_PLL_CLK_CTRL, 0x00000430 }, // 3072000Hz, BCLK Input, PLL_REFC= LK_EN =3D 1 @@ -27,11 +37,167 @@ static const struct reg_sequence cs35l41_hda_config[] = =3D { { CS35L41_AMP_GAIN_CTRL, 0x00000084 }, // AMP_GAIN_PCM 4.5 dB }; =20 +static const struct reg_sequence cs35l41_hda_config_dsp[] =3D { + { CS35L41_PLL_CLK_CTRL, 0x00000430 }, // 3072000Hz, BCLK Input, PLL_REFC= LK_EN =3D 1 + { CS35L41_DSP_CLK_CTRL, 0x00000003 }, // DSP CLK EN + { CS35L41_GLOBAL_CLK_CTRL, 0x00000003 }, // GLOBAL_FS =3D 48 kHz + { CS35L41_SP_ENABLES, 0x00010001 }, // ASP_RX1_EN =3D 1, ASP_TX1_EN =3D 1 + { CS35L41_SP_RATE_CTRL, 0x00000021 }, // ASP_BCLK_FREQ =3D 3.072 MHz + { CS35L41_SP_FORMAT, 0x20200200 }, // 32 bits RX/TX slots, I2S, clk cons= umer + { CS35L41_SP_HIZ_CTRL, 0x00000003 }, // Hi-Z unused/disabled + { CS35L41_SP_TX_WL, 0x00000018 }, // 24 cycles/slot + { CS35L41_SP_RX_WL, 0x00000018 }, // 24 cycles/slot + { CS35L41_DAC_PCM1_SRC, 0x00000032 }, // DACPCM1_SRC =3D ERR_VOL + { CS35L41_ASP_TX1_SRC, 0x00000018 }, // ASPTX1 SRC =3D VMON + { CS35L41_ASP_TX2_SRC, 0x00000019 }, // ASPTX2 SRC =3D IMON + { CS35L41_ASP_TX3_SRC, 0x00000028 }, // ASPTX3 SRC =3D VPMON + { CS35L41_ASP_TX4_SRC, 0x00000029 }, // ASPTX4 SRC =3D VBSTMON + { CS35L41_DSP1_RX1_SRC, 0x00000008 }, // DSP1RX1 SRC =3D ASPRX1 + { CS35L41_DSP1_RX2_SRC, 0x00000008 }, // DSP1RX2 SRC =3D ASPRX1 + { CS35L41_DSP1_RX3_SRC, 0x00000018 }, // DSP1RX3 SRC =3D VMON + { CS35L41_DSP1_RX4_SRC, 0x00000019 }, // DSP1RX4 SRC =3D IMON + { CS35L41_DSP1_RX5_SRC, 0x00000029 }, // DSP1RX5 SRC =3D VBSTMON + { CS35L41_AMP_DIG_VOL_CTRL, 0x00000000 }, // AMP_VOL_PCM 0.0 dB + { CS35L41_AMP_GAIN_CTRL, 0x00000233 }, // AMP_GAIN_PCM =3D 17.5dB AMP_GAI= N_PDM =3D 19.5dB +}; + static const struct reg_sequence cs35l41_hda_mute[] =3D { { CS35L41_AMP_GAIN_CTRL, 0x00000000 }, // AMP_GAIN_PCM 0.5 dB { CS35L41_AMP_DIG_VOL_CTRL, 0x0000A678 }, // AMP_VOL_PCM Mute }; =20 +static int cs35l41_control_add(struct cs_dsp_coeff_ctl *cs_ctl) +{ + struct cs35l41_hda *cs35l41 =3D container_of(cs_ctl->dsp, struct cs35l41_= hda, cs_dsp); + struct hda_cs_dsp_ctl_info info; + + info.amp_name =3D cs35l41->amp_name; + info.fw_type =3D HDA_CS_DSP_FW_SPK_PROT; + info.card =3D cs35l41->codec->card; + + return hda_cs_dsp_control_add(cs_ctl, &info); +} + +static const struct cs_dsp_client_ops client_ops =3D { + .control_add =3D cs35l41_control_add, + .control_remove =3D hda_cs_dsp_control_remove, +}; + +static int cs35l41_request_firmware_file(struct cs35l41_hda *cs35l41, + const struct firmware **firmware, char **filename, + const char *dir, const char *filetype) +{ + const char * const dsp_name =3D cs35l41->cs_dsp.name; + char *s, c; + int ret =3D 0; + + *filename =3D kasprintf(GFP_KERNEL, "%s%s-%s-%s.%s", dir, CS35L41_PART, d= sp_name, "spk-prot", + filetype); + + if (*filename =3D=3D NULL) + return -ENOMEM; + + /* + * Make sure that filename is lower-case and any non alpha-numeric + * characters except full stop and '/' are replaced with hyphens. + */ + s =3D *filename; + while (*s) { + c =3D *s; + if (isalnum(c)) + *s =3D tolower(c); + else if (c !=3D '.' && c !=3D '/') + *s =3D '-'; + s++; + } + + ret =3D firmware_request_nowarn(firmware, *filename, cs35l41->dev); + if (ret !=3D 0) { + dev_dbg(cs35l41->dev, "Failed to request '%s'\n", *filename); + kfree(*filename); + *filename =3D NULL; + } + + return ret; +} + +static int cs35l41_request_firmware_files(struct cs35l41_hda *cs35l41, + const struct firmware **wmfw_firmware, + char **wmfw_filename, + const struct firmware **coeff_firmware, + char **coeff_filename) +{ + int ret; + + /* cirrus/part-dspN-fwtype.wmfw */ + ret =3D cs35l41_request_firmware_file(cs35l41, wmfw_firmware, wmfw_filena= me, + CS35L41_FIRMWARE_ROOT, "wmfw"); + if (!ret) { + cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename, + CS35L41_FIRMWARE_ROOT, "bin"); + return 0; + } + + dev_warn(cs35l41->dev, "Failed to request firmware\n"); + + return ret; +} + + +static int cs35l41_init_dsp(struct cs35l41_hda *cs35l41) +{ + const struct firmware *coeff_firmware =3D NULL; + const struct firmware *wmfw_firmware =3D NULL; + struct cs_dsp *dsp =3D &cs35l41->cs_dsp; + char *coeff_filename =3D NULL; + char *wmfw_filename =3D NULL; + int ret; + + cs35l41_configure_cs_dsp(cs35l41->dev, cs35l41->regmap, dsp); + dsp->client_ops =3D &client_ops; + + if (!cs35l41->halo_initialized) { + ret =3D cs_dsp_halo_init(&cs35l41->cs_dsp); + if (ret) + return ret; + cs35l41->halo_initialized =3D true; + } + + ret =3D cs35l41_request_firmware_files(cs35l41, &wmfw_firmware, &wmfw_fil= ename, + &coeff_firmware, &coeff_filename); + if (ret < 0) + return ret; + + dev_dbg(cs35l41->dev, "Loaded WMFW Firmware: %s\n", wmfw_filename); + if (coeff_filename) + dev_dbg(cs35l41->dev, "Loaded Coefficient File: %s\n", coeff_filename); + else + dev_warn(cs35l41->dev, "No Coefficient File available.\n"); + + ret =3D cs_dsp_power_up(dsp, wmfw_firmware, wmfw_filename, coeff_firmware= , coeff_filename, + FW_NAME); + + if (wmfw_firmware) + release_firmware(wmfw_firmware); + if (coeff_firmware) + release_firmware(coeff_firmware); + kfree(wmfw_filename); + kfree(coeff_filename); + + return ret; +} + +static void cs35l41_remove_dsp(struct cs35l41_hda *cs35l41) +{ + struct cs_dsp *dsp =3D &cs35l41->cs_dsp; + + cs_dsp_stop(dsp); + cs_dsp_power_down(dsp); + cs_dsp_remove(dsp); + cs35l41->firmware_running =3D false; + dev_dbg(cs35l41->dev, "Unloaded Firmware\n"); +} + /* Protection release cycle to get the speaker out of Safe-Mode */ static void cs35l41_error_release(struct device *dev, struct regmap *regma= p, unsigned int mask) { @@ -55,7 +221,18 @@ static void cs35l41_hda_playback_hook(struct device *de= v, int action) =20 switch (action) { case HDA_GEN_PCM_ACT_OPEN: - regmap_multi_reg_write(reg, cs35l41_hda_config, ARRAY_SIZE(cs35l41_hda_c= onfig)); + if (cs35l41->firmware_running) { + regmap_multi_reg_write(reg, cs35l41_hda_config_dsp, + ARRAY_SIZE(cs35l41_hda_config_dsp)); + regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2, + CS35L41_VMON_EN_MASK | CS35L41_IMON_EN_MASK, + 1 << CS35L41_VMON_EN_SHIFT | 1 << CS35L41_IMON_EN_SHIFT); + cs35l41_set_cspl_mbox_cmd(cs35l41->dev, cs35l41->regmap, + CSPL_MBOX_CMD_RESUME); + } else { + regmap_multi_reg_write(reg, cs35l41_hda_config, + ARRAY_SIZE(cs35l41_hda_config)); + } ret =3D regmap_update_bits(reg, CS35L41_PWR_CTRL2, CS35L41_AMP_EN_MASK, 1 << CS35L41_AMP_EN_SHIFT); if (cs35l41->hw_cfg.bst_type =3D=3D CS35L41_EXT_BOOST) @@ -73,6 +250,13 @@ static void cs35l41_hda_playback_hook(struct device *de= v, int action) CS35L41_AMP_EN_MASK, 0 << CS35L41_AMP_EN_SHIFT); if (cs35l41->hw_cfg.bst_type =3D=3D CS35L41_EXT_BOOST) regmap_write(reg, CS35L41_GPIO1_CTRL1, 0x00000001); + if (cs35l41->firmware_running) { + cs35l41_set_cspl_mbox_cmd(cs35l41->dev, cs35l41->regmap, + CSPL_MBOX_CMD_PAUSE); + regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2, + CS35L41_VMON_EN_MASK | CS35L41_IMON_EN_MASK, + 0 << CS35L41_VMON_EN_SHIFT | 0 << CS35L41_IMON_EN_SHIFT); + } cs35l41_irq_release(cs35l41); break; default: @@ -104,6 +288,51 @@ static int cs35l41_hda_channel_map(struct device *dev,= unsigned int tx_num, unsi rx_slot); } =20 +static int cs35l41_smart_amp(struct cs35l41_hda *cs35l41) +{ + int halo_sts; + int ret; + + ret =3D cs35l41_init_dsp(cs35l41); + if (ret) { + dev_warn(cs35l41->dev, "Cannot Initialize Firmware. Error: %d\n", ret); + goto clean_dsp; + } + + ret =3D cs35l41_write_fs_errata(cs35l41->dev, cs35l41->regmap); + if (ret) { + dev_err(cs35l41->dev, "Cannot Write FS Errata: %d\n", ret); + goto clean_dsp; + } + + ret =3D cs_dsp_run(&cs35l41->cs_dsp); + if (ret) { + dev_err(cs35l41->dev, "Fail to start dsp: %d\n", ret); + goto clean_dsp; + } + + ret =3D read_poll_timeout(hda_cs_dsp_read_ctl, ret, + be32_to_cpu(halo_sts) =3D=3D HALO_STATE_CODE_RUN, + 1000, 15000, false, &cs35l41->cs_dsp, HALO_STATE_DSP_CTL_NAME, + HALO_STATE_DSP_CTL_TYPE, HALO_STATE_DSP_CTL_ALG, + &halo_sts, sizeof(halo_sts)); + + if (ret) { + dev_err(cs35l41->dev, "Timeout waiting for HALO Core to start. State: %d= \n", + halo_sts); + goto clean_dsp; + } + + cs35l41_set_cspl_mbox_cmd(cs35l41->dev, cs35l41->regmap, CSPL_MBOX_CMD_PA= USE); + cs35l41->firmware_running =3D true; + + return 0; + +clean_dsp: + cs35l41_remove_dsp(cs35l41); + return ret; +} + static int cs35l41_hda_bind(struct device *dev, struct device *master, voi= d *master_data) { struct cs35l41_hda *cs35l41 =3D dev_get_drvdata(dev); @@ -121,6 +350,9 @@ static int cs35l41_hda_bind(struct device *dev, struct = device *master, void *mas strscpy(comps->name, dev_name(dev), sizeof(comps->name)); comps->playback_hook =3D cs35l41_hda_playback_hook; =20 + if (cs35l41_smart_amp(cs35l41) < 0) + dev_warn(cs35l41->dev, "Cannot Run Firmware, reverting to dsp bypass...\= n"); + return 0; } =20 @@ -564,6 +796,9 @@ void cs35l41_hda_remove(struct device *dev) { struct cs35l41_hda *cs35l41 =3D dev_get_drvdata(dev); =20 + if (cs35l41->firmware_running) + cs35l41_remove_dsp(cs35l41); + component_del(cs35l41->dev, &cs35l41_hda_comp_ops); =20 if (cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type)) @@ -573,5 +808,6 @@ void cs35l41_hda_remove(struct device *dev) EXPORT_SYMBOL_NS_GPL(cs35l41_hda_remove, SND_HDA_SCODEC_CS35L41); =20 MODULE_DESCRIPTION("CS35L41 HDA Driver"); +MODULE_IMPORT_NS(SND_HDA_CS_DSP_CONTROLS); MODULE_AUTHOR("Lucas Tanure, Cirrus Logic Inc, "); MODULE_LICENSE("GPL"); diff --git a/sound/pci/hda/cs35l41_hda.h b/sound/pci/hda/cs35l41_hda.h index aaf9e16684c2..03c5f14631dd 100644 --- a/sound/pci/hda/cs35l41_hda.h +++ b/sound/pci/hda/cs35l41_hda.h @@ -15,6 +15,9 @@ #include #include =20 +#include +#include + enum cs35l41_hda_spk_pos { CS35l41_LEFT, CS35l41_RIGHT, @@ -40,6 +43,15 @@ struct cs35l41_hda { unsigned volatile long irq_errors; const char *amp_name; struct regmap_irq_chip_data *irq_data; + bool firmware_running; + bool halo_initialized; + struct cs_dsp cs_dsp; +}; + +enum halo_state { + HALO_STATE_CODE_INIT_DOWNLOAD =3D 0, + HALO_STATE_CODE_START, + HALO_STATE_CODE_RUN }; =20 int cs35l41_hda_probe(struct device *dev, const char *device_name, int id,= int irq, --=20 2.34.1 From nobody Tue May 5 10:00:43 2026 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 0E077C433F5 for ; Wed, 25 May 2022 13:17:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244174AbiEYNRK (ORCPT ); Wed, 25 May 2022 09:17:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34154 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233564AbiEYNQ4 (ORCPT ); Wed, 25 May 2022 09:16:56 -0400 Received: from mx0b-001ae601.pphosted.com (mx0b-001ae601.pphosted.com [67.231.152.168]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EAED5DFC6 for ; Wed, 25 May 2022 06:16:54 -0700 (PDT) Received: from pps.filterd (m0077474.ppops.net [127.0.0.1]) by mx0b-001ae601.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 24PCRmjE022096; Wed, 25 May 2022 08:16:43 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=sv5kg+VufeHGb940jrq8D6qqQDoRuEKRbumnfanmMv8=; b=FxKy8798cBwhDDXigWFbcpa+8rZ+TtkihGdse6UPYwUKey9thnQTF0/yA2e1cYXy7eZV oBiV2F6z087PH0fn7okLmaynFdQEhuTM1B9qeL5lqQFRmNxSYN1OhNd6KLGEtpLr+HbN LVAh+iI7c744iuT3JFTKc84u8xzVx7SMhLDEcDe2//Jik99+1N6ATu3/8oIBbVJvvHMr CTvdiHSaSXp3oPebMBB35Swbr1/bC+pwYjfeUxWCnpv6AAlZIcbjLMe8DMRb321Sx3yL gbcFMP4si++LtzFt5V0CUHhrgYWLMUaQE0Yb/5GAWDw/+r6a9JFVjSOTTlsY4rAtImzJ VA== Received: from ediex01.ad.cirrus.com ([84.19.233.68]) by mx0b-001ae601.pphosted.com (PPS) with ESMTPS id 3g93u20we6-4 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT); Wed, 25 May 2022 08:16:42 -0500 Received: from EDIEX01.ad.cirrus.com (198.61.84.80) by EDIEX01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.24; Wed, 25 May 2022 14:16:41 +0100 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by EDIEX01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server id 15.1.2375.24 via Frontend Transport; Wed, 25 May 2022 14:16:41 +0100 Received: from vitaly-Legion-7-16ACHg6.ad.cirrus.com (unknown [198.90.238.233]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id 5D01B468; Wed, 25 May 2022 13:16:41 +0000 (UTC) From: Vitaly Rodionov To: Jaroslav Kysela , Takashi Iwai , Mark Brown CC: , , , Stefan Binding Subject: [PATCH v4 05/17] ALSA: hda: cs35l41: Save Subsystem ID inside CS35L41 Driver Date: Wed, 25 May 2022 14:16:26 +0100 Message-ID: <20220525131638.5512-6-vitalyr@opensource.cirrus.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220525131638.5512-1-vitalyr@opensource.cirrus.com> References: <20220525131638.5512-1-vitalyr@opensource.cirrus.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-ORIG-GUID: FcsxwZ4VLbEU8EyuUianABwHp20ubK-R X-Proofpoint-GUID: FcsxwZ4VLbEU8EyuUianABwHp20ubK-R X-Proofpoint-Spam-Reason: safe Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" From: Stefan Binding The Subsystem ID is read from the HDA driver, and will be used by the CS35L41 driver to be able to uniquely identify the laptop, which is required to be able to define firmware to be used by specific models. Signed-off-by: Stefan Binding Signed-off-by: Vitaly Rodionov --- Changes since v2: - No change sound/pci/hda/cs35l41_hda.c | 3 +++ sound/pci/hda/cs35l41_hda.h | 1 + sound/pci/hda/hda_component.h | 1 + sound/pci/hda/patch_realtek.c | 1 + 4 files changed, 6 insertions(+) diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c index fe2ba03e602b..c235b899aa04 100644 --- a/sound/pci/hda/cs35l41_hda.c +++ b/sound/pci/hda/cs35l41_hda.c @@ -346,6 +346,9 @@ static int cs35l41_hda_bind(struct device *dev, struct = device *master, void *mas return -EBUSY; =20 comps->dev =3D dev; + if (!cs35l41->acpi_subsystem_id) + cs35l41->acpi_subsystem_id =3D devm_kasprintf(dev, GFP_KERNEL, + "%.8x", comps->subsystem_id); cs35l41->codec =3D comps->codec; strscpy(comps->name, dev_name(dev), sizeof(comps->name)); comps->playback_hook =3D cs35l41_hda_playback_hook; diff --git a/sound/pci/hda/cs35l41_hda.h b/sound/pci/hda/cs35l41_hda.h index 03c5f14631dd..b8352088a5cb 100644 --- a/sound/pci/hda/cs35l41_hda.h +++ b/sound/pci/hda/cs35l41_hda.h @@ -42,6 +42,7 @@ struct cs35l41_hda { int channel_index; unsigned volatile long irq_errors; const char *amp_name; + const char *acpi_subsystem_id; struct regmap_irq_chip_data *irq_data; bool firmware_running; bool halo_initialized; diff --git a/sound/pci/hda/hda_component.h b/sound/pci/hda/hda_component.h index 534e845b9cd1..fa6df52e7855 100644 --- a/sound/pci/hda/hda_component.h +++ b/sound/pci/hda/hda_component.h @@ -14,6 +14,7 @@ struct hda_component { struct device *dev; char name[HDA_MAX_NAME_SIZE]; + int subsystem_id; struct hda_codec *codec; void (*playback_hook)(struct device *dev, int action); }; diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index cd289b17ca13..b8249c4dcb1d 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6632,6 +6632,7 @@ static void cs35l41_generic_fixup(struct hda_codec *c= dc, int action, const char if (!name) return; spec->comps[i].codec =3D cdc; + spec->comps[i].subsystem_id =3D cdc->core.subsystem_id; component_match_add(dev, &spec->match, component_compare_dev_name, name= ); } ret =3D component_master_add_with_match(dev, &comp_master_ops, spec->mat= ch); --=20 2.34.1 From nobody Tue May 5 10:00:43 2026 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 09B7FC433EF for ; Wed, 25 May 2022 13:18:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234948AbiEYNSK (ORCPT ); Wed, 25 May 2022 09:18:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34662 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233689AbiEYNRE (ORCPT ); Wed, 25 May 2022 09:17:04 -0400 Received: from mx0b-001ae601.pphosted.com (mx0a-001ae601.pphosted.com [67.231.149.25]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C2138DFC6 for ; Wed, 25 May 2022 06:17:02 -0700 (PDT) Received: from pps.filterd (m0077473.ppops.net [127.0.0.1]) by mx0a-001ae601.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 24PBxMvd005635; Wed, 25 May 2022 08:16:44 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=fYmjIggmqaxp0xE4Jpga+Pd2F4S8iC+s9X3j+VD0f1I=; b=qBsJ1N/ufcvuqQLEEKmfPmBYLgAnEey94giICd0fqTMLOEu770H9WA9DbGJ6n/lTGGvb In/znK2MGyLx5ulitBPsrG6/WSpwkuBeJzKA9PLsvj1Mr8nVs/m9vYMzlBtjYzFIbJlW yK72sDWuZGBHtH4E/dIp67mZlskfpEedDTZjTkI6M0u3rx4bUoMQev/fHR4cT5+xwzpK qArl3qgoZi6YBDywowuE8VplF5p+cBeNE2iDERAsW1FSz92Wb9zVLkPK4DcXlxdFleot jY02yymLmBndd9uVX4NB5emhaINddayENZBp+OSmSMVV1acsYEPdfSk8GWMcToR3IQwd vA== Received: from ediex02.ad.cirrus.com ([84.19.233.68]) by mx0a-001ae601.pphosted.com (PPS) with ESMTPS id 3g93u4gx4s-3 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT); Wed, 25 May 2022 08:16:44 -0500 Received: from EDIEX01.ad.cirrus.com (198.61.84.80) by EDIEX02.ad.cirrus.com (198.61.84.81) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.24; Wed, 25 May 2022 14:16:42 +0100 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by EDIEX01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server id 15.1.2375.24 via Frontend Transport; Wed, 25 May 2022 14:16:42 +0100 Received: from vitaly-Legion-7-16ACHg6.ad.cirrus.com (unknown [198.90.238.233]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id B981146C; Wed, 25 May 2022 13:16:41 +0000 (UTC) From: Vitaly Rodionov To: Jaroslav Kysela , Takashi Iwai , Mark Brown CC: , , , Stefan Binding Subject: [PATCH v4 06/17] ALSA: hda: cs35l41: Support reading subsystem id from ACPI Date: Wed, 25 May 2022 14:16:27 +0100 Message-ID: <20220525131638.5512-7-vitalyr@opensource.cirrus.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220525131638.5512-1-vitalyr@opensource.cirrus.com> References: <20220525131638.5512-1-vitalyr@opensource.cirrus.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-ORIG-GUID: zfURDhiPKTx7faHmnBKypcdwQrNU_jX6 X-Proofpoint-GUID: zfURDhiPKTx7faHmnBKypcdwQrNU_jX6 X-Proofpoint-Spam-Reason: safe Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" From: Stefan Binding On some laptop models, the ACPI contains the unique Subsystem ID, and this value should be preferred over the value from the HDA driver. Signed-off-by: Stefan Binding Signed-off-by: Vitaly Rodionov --- Changes since v2: - No change =20 sound/pci/hda/cs35l41_hda.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c index c235b899aa04..81d6f4cf0166 100644 --- a/sound/pci/hda/cs35l41_hda.c +++ b/sound/pci/hda/cs35l41_hda.c @@ -533,6 +533,36 @@ static int cs35l41_hda_apply_properties(struct cs35l41= _hda *cs35l41) return cs35l41_hda_channel_map(cs35l41->dev, 0, NULL, 1, &hw_cfg->spk_pos= ); } =20 +static int cs35l41_get_acpi_sub_string(struct device *dev, struct acpi_dev= ice *adev, + const char **subsysid) +{ + struct acpi_buffer buffer =3D { ACPI_ALLOCATE_BUFFER, NULL }; + union acpi_object *obj; + acpi_status status; + int ret =3D 0; + + status =3D acpi_evaluate_object(adev->handle, "_SUB", NULL, &buffer); + if (ACPI_SUCCESS(status)) { + obj =3D buffer.pointer; + if (obj->type =3D=3D ACPI_TYPE_STRING) { + *subsysid =3D devm_kstrdup(dev, obj->string.pointer, GFP_KERNEL); + if (*subsysid =3D=3D NULL) { + dev_err(dev, "Cannot allocate Subsystem ID"); + ret =3D -ENOMEM; + } + } else { + dev_warn(dev, "Warning ACPI _SUB did not return a string\n"); + ret =3D -ENODEV; + } + acpi_os_free(buffer.pointer); + } else { + dev_dbg(dev, "Warning ACPI _SUB failed: %#x\n", status); + ret =3D -ENODEV; + } + + return ret; +} + static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *= hid, int id) { struct cs35l41_hw_cfg *hw_cfg =3D &cs35l41->hw_cfg; @@ -552,6 +582,12 @@ static int cs35l41_hda_read_acpi(struct cs35l41_hda *c= s35l41, const char *hid, i physdev =3D get_device(acpi_get_first_physical_node(adev)); acpi_dev_put(adev); =20 + ret =3D cs35l41_get_acpi_sub_string(cs35l41->dev, adev, &cs35l41->acpi_su= bsystem_id); + if (ret) + dev_info(cs35l41->dev, "No Subsystem ID found in ACPI: %d", ret); + else + dev_dbg(cs35l41->dev, "Subsystem ID %s found", cs35l41->acpi_subsystem_i= d); + property =3D "cirrus,dev-index"; ret =3D device_property_count_u32(physdev, property); if (ret <=3D 0) --=20 2.34.1 From nobody Tue May 5 10:00:43 2026 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 EF2BFC433F5 for ; Wed, 25 May 2022 13:17:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244166AbiEYNRN (ORCPT ); Wed, 25 May 2022 09:17:13 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34156 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233105AbiEYNQ4 (ORCPT ); Wed, 25 May 2022 09:16:56 -0400 Received: from mx0b-001ae601.pphosted.com (mx0b-001ae601.pphosted.com [67.231.152.168]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 30BFBDFFE for ; Wed, 25 May 2022 06:16:55 -0700 (PDT) Received: from pps.filterd (m0077474.ppops.net [127.0.0.1]) by mx0b-001ae601.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 24PCRmjF022096; Wed, 25 May 2022 08:16:43 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=CzXHR0GocBNOj0BfbZGkVZXbGMIVdRauzKeaNK4Hhqo=; b=jRGdYt+YKZmWqcQ+w5zkh7HW9LSuDG8qgHNqLjzsiFXXIxdbPYmwcxRhXkOuwonk5abr hckKQ6zGlsRX8ehV5i23O/jLSdaBnSy3SM6F8VRQ+Ozumh/ZuNTvMMmXn/9u1pYB/ee3 74a6Q8uANTY3zq90ZJTWW8JAtXO2rMAq0sVEcfo+jzRgVOPH79yNBXvimPGX+VXlZmCb G+lNmRxQb3Tn7Rp0e5r4HfHxuZwdH7BsCFCtIFdQFTncp02XtVIRIWw3HDQyUXSFs9c+ drApmr3kw/aYsnXk6xhGz8+wqbxyfhZak9EX7fXPHGPYfTHzClVtAP3Cc4UkbQ4rcWIl Aw== Received: from ediex01.ad.cirrus.com ([84.19.233.68]) by mx0b-001ae601.pphosted.com (PPS) with ESMTPS id 3g93u20we6-5 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT); Wed, 25 May 2022 08:16:43 -0500 Received: from EDIEX01.ad.cirrus.com (198.61.84.80) by EDIEX01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.24; Wed, 25 May 2022 14:16:42 +0100 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by EDIEX01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server id 15.1.2375.24 via Frontend Transport; Wed, 25 May 2022 14:16:42 +0100 Received: from vitaly-Legion-7-16ACHg6.ad.cirrus.com (unknown [198.90.238.233]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id 2C54111D1; Wed, 25 May 2022 13:16:42 +0000 (UTC) From: Vitaly Rodionov To: Jaroslav Kysela , Takashi Iwai , Mark Brown CC: , , , Stefan Binding Subject: [PATCH v4 07/17] ALSA: hda: cs35l41: Support multiple load paths for firmware Date: Wed, 25 May 2022 14:16:28 +0100 Message-ID: <20220525131638.5512-8-vitalyr@opensource.cirrus.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220525131638.5512-1-vitalyr@opensource.cirrus.com> References: <20220525131638.5512-1-vitalyr@opensource.cirrus.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-ORIG-GUID: WbFfvCJmA8Wvp0_oj-77hoi8Aw_1eS4X X-Proofpoint-GUID: WbFfvCJmA8Wvp0_oj-77hoi8Aw_1eS4X X-Proofpoint-Spam-Reason: safe Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" From: Stefan Binding To be able to support different firmwares and tuning for different models, the driver needs to be able to load a different firmware and coefficient file based on its Subsystem ID. The driver attempts to load the firmware in the following order: /lib/firmware/cirrus/cs35l41-dsp1---dev<#>.wmfw /lib/firmware/cirrus/cs35l41-dsp1--.wmfw /lib/firmware/cirrus/cs35l41-dsp1-.wmfw Signed-off-by: Stefan Binding Signed-off-by: Vitaly Rodionov --- Changes since v2: - No change =20 sound/pci/hda/cs35l41_hda.c | 53 ++++++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 7 deletions(-) diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c index 81d6f4cf0166..0957b4984143 100644 --- a/sound/pci/hda/cs35l41_hda.c +++ b/sound/pci/hda/cs35l41_hda.c @@ -85,14 +85,23 @@ static const struct cs_dsp_client_ops client_ops =3D { =20 static int cs35l41_request_firmware_file(struct cs35l41_hda *cs35l41, const struct firmware **firmware, char **filename, - const char *dir, const char *filetype) + const char *dir, const char *ssid, const char *amp_name, + const char *filetype) { const char * const dsp_name =3D cs35l41->cs_dsp.name; char *s, c; int ret =3D 0; =20 - *filename =3D kasprintf(GFP_KERNEL, "%s%s-%s-%s.%s", dir, CS35L41_PART, d= sp_name, "spk-prot", - filetype); + if (ssid && amp_name) + *filename =3D kasprintf(GFP_KERNEL, "%s%s-%s-%s-%s-%s.%s", dir, CS35L41_= PART, + dsp_name, "spk-prot", ssid, amp_name, + filetype); + else if (ssid) + *filename =3D kasprintf(GFP_KERNEL, "%s%s-%s-%s-%s.%s", dir, CS35L41_PAR= T, + dsp_name, "spk-prot", ssid, filetype); + else + *filename =3D kasprintf(GFP_KERNEL, "%s%s-%s-%s.%s", dir, CS35L41_PART, + dsp_name, "spk-prot", filetype); =20 if (*filename =3D=3D NULL) return -ENOMEM; @@ -129,12 +138,43 @@ static int cs35l41_request_firmware_files(struct cs35= l41_hda *cs35l41, { int ret; =20 - /* cirrus/part-dspN-fwtype.wmfw */ + /* try cirrus/part-dspN-fwtype-sub<-ampname>.wmfw */ + ret =3D cs35l41_request_firmware_file(cs35l41, wmfw_firmware, wmfw_filena= me, + CS35L41_FIRMWARE_ROOT, cs35l41->acpi_subsystem_id, + cs35l41->amp_name, "wmfw"); + if (!ret) { + /* try cirrus/part-dspN-fwtype-sub<-ampname>.bin */ + cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename, + CS35L41_FIRMWARE_ROOT, cs35l41->acpi_subsystem_id, + cs35l41->amp_name, "bin"); + return 0; + } + + /* try cirrus/part-dspN-fwtype-sub.wmfw */ ret =3D cs35l41_request_firmware_file(cs35l41, wmfw_firmware, wmfw_filena= me, - CS35L41_FIRMWARE_ROOT, "wmfw"); + CS35L41_FIRMWARE_ROOT, cs35l41->acpi_subsystem_id, + NULL, "wmfw"); if (!ret) { + /* try cirrus/part-dspN-fwtype-sub<-ampname>.bin */ + ret =3D cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_fil= ename, + CS35L41_FIRMWARE_ROOT, + cs35l41->acpi_subsystem_id, + cs35l41->amp_name, "bin"); + if (ret) + /* try cirrus/part-dspN-fwtype-sub.bin */ + cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename, + CS35L41_FIRMWARE_ROOT, + cs35l41->acpi_subsystem_id, NULL, "bin"); + return 0; + } + + /* fallback try cirrus/part-dspN-fwtype.wmfw */ + ret =3D cs35l41_request_firmware_file(cs35l41, wmfw_firmware, wmfw_filena= me, + CS35L41_FIRMWARE_ROOT, NULL, NULL, "wmfw"); + if (!ret) { + /* fallback try cirrus/part-dspN-fwtype.bin */ cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename, - CS35L41_FIRMWARE_ROOT, "bin"); + CS35L41_FIRMWARE_ROOT, NULL, NULL, "bin"); return 0; } =20 @@ -143,7 +183,6 @@ static int cs35l41_request_firmware_files(struct cs35l4= 1_hda *cs35l41, return ret; } =20 - static int cs35l41_init_dsp(struct cs35l41_hda *cs35l41) { const struct firmware *coeff_firmware =3D NULL; --=20 2.34.1 From nobody Tue May 5 10:00:43 2026 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 1D1B9C433F5 for ; Wed, 25 May 2022 13:18:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238303AbiEYNSD (ORCPT ); Wed, 25 May 2022 09:18:03 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34586 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244023AbiEYNRD (ORCPT ); Wed, 25 May 2022 09:17:03 -0400 Received: from mx0b-001ae601.pphosted.com (mx0b-001ae601.pphosted.com [67.231.152.168]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C1DF8DFD7 for ; Wed, 25 May 2022 06:17:01 -0700 (PDT) Received: from pps.filterd (m0077474.ppops.net [127.0.0.1]) by mx0b-001ae601.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 24PCRmjG022096; Wed, 25 May 2022 08:16:45 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=tpyrRQDCE+mCubpIJjzgOXShj8ICnUR2kNBsPdlkh9g=; b=EOJH7Zs+OGm/KO8PNdpXvZ3WxVfVSNRn0GjMPSmkunRh5isfay4EdUx7hAoPWzi+hT76 m00noDhg8S7VkCJ5xAs+/LrkiajMe75FfCaRhGUpZrk7+l/AbYRImb2dhslHZ1REDgJ6 4TLEV+Me7316In+E5DjEGAHYnR95NXshIFlGtX7jCbyc4xHTqGxwdfrION3jkRN7mRWg 2YTnL+4ggjEeMBOJwXcAqKNIV9SbBRbjxtJqj/B004WjnUYGPvKF6s2W2QKoR1s8Kwx8 aHliu5ItyebdxkwRTECNyRgI8SqPxlVcEj+IlaPYva75CLqmwzgn3NOE87RqH/z+pjcH SQ== Received: from ediex01.ad.cirrus.com ([84.19.233.68]) by mx0b-001ae601.pphosted.com (PPS) with ESMTPS id 3g93u20we6-6 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT); Wed, 25 May 2022 08:16:44 -0500 Received: from EDIEX01.ad.cirrus.com (198.61.84.80) by EDIEX01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.24; Wed, 25 May 2022 14:16:42 +0100 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by EDIEX01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server id 15.1.2375.24 via Frontend Transport; Wed, 25 May 2022 14:16:42 +0100 Received: from vitaly-Legion-7-16ACHg6.ad.cirrus.com (unknown [198.90.238.233]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id 86BB5468; Wed, 25 May 2022 13:16:42 +0000 (UTC) From: Vitaly Rodionov To: Jaroslav Kysela , Takashi Iwai , Mark Brown CC: , , , Stefan Binding Subject: [PATCH v4 08/17] ALSA: hda: cs35l41: Support Speaker ID for laptops Date: Wed, 25 May 2022 14:16:29 +0100 Message-ID: <20220525131638.5512-9-vitalyr@opensource.cirrus.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220525131638.5512-1-vitalyr@opensource.cirrus.com> References: <20220525131638.5512-1-vitalyr@opensource.cirrus.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-ORIG-GUID: Mwy6xPOuFBE_oJ74-LA2-tm9upIapbOW X-Proofpoint-GUID: Mwy6xPOuFBE_oJ74-LA2-tm9upIapbOW X-Proofpoint-Spam-Reason: safe Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" From: Stefan Binding Some Laptops use a number of gpios to define which vendor is used for a particular laptop. Different coefficient files are used for different vendors. Signed-off-by: Stefan Binding Signed-off-by: Vitaly Rodionov --- Changes since v2: - No change =20 sound/pci/hda/cs35l41_hda.c | 174 ++++++++++++++++++++++++++++++++++-- sound/pci/hda/cs35l41_hda.h | 1 + 2 files changed, 166 insertions(+), 9 deletions(-) diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c index 0957b4984143..1d62a41fbc75 100644 --- a/sound/pci/hda/cs35l41_hda.c +++ b/sound/pci/hda/cs35l41_hda.c @@ -86,13 +86,19 @@ static const struct cs_dsp_client_ops client_ops =3D { static int cs35l41_request_firmware_file(struct cs35l41_hda *cs35l41, const struct firmware **firmware, char **filename, const char *dir, const char *ssid, const char *amp_name, - const char *filetype) + int spkid, const char *filetype) { const char * const dsp_name =3D cs35l41->cs_dsp.name; char *s, c; int ret =3D 0; =20 - if (ssid && amp_name) + if (spkid > -1 && ssid && amp_name) + *filename =3D kasprintf(GFP_KERNEL, "%s%s-%s-%s-%s-spkid%d-%s.%s", dir, = CS35L41_PART, + dsp_name, "spk-prot", ssid, spkid, amp_name, filetype); + else if (spkid > -1 && ssid) + *filename =3D kasprintf(GFP_KERNEL, "%s%s-%s-%s-%s-spkid%d.%s", dir, CS3= 5L41_PART, + dsp_name, "spk-prot", ssid, spkid, filetype); + else if (ssid && amp_name) *filename =3D kasprintf(GFP_KERNEL, "%s%s-%s-%s-%s-%s.%s", dir, CS35L41_= PART, dsp_name, "spk-prot", ssid, amp_name, filetype); @@ -130,6 +136,93 @@ static int cs35l41_request_firmware_file(struct cs35l4= 1_hda *cs35l41, return ret; } =20 +static int cs35l41_request_firmware_files_spkid(struct cs35l41_hda *cs35l4= 1, + const struct firmware **wmfw_firmware, + char **wmfw_filename, + const struct firmware **coeff_firmware, + char **coeff_filename) +{ + int ret; + + /* try cirrus/part-dspN-fwtype-sub<-spkidN><-ampname>.wmfw */ + ret =3D cs35l41_request_firmware_file(cs35l41, wmfw_firmware, wmfw_filena= me, + CS35L41_FIRMWARE_ROOT, + cs35l41->acpi_subsystem_id, cs35l41->amp_name, + cs35l41->speaker_id, "wmfw"); + if (!ret) { + /* try cirrus/part-dspN-fwtype-sub<-spkidN><-ampname>.bin */ + cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename, + CS35L41_FIRMWARE_ROOT, + cs35l41->acpi_subsystem_id, cs35l41->amp_name, + cs35l41->speaker_id, "bin"); + return 0; + } + + /* try cirrus/part-dspN-fwtype-sub<-ampname>.wmfw */ + ret =3D cs35l41_request_firmware_file(cs35l41, wmfw_firmware, wmfw_filena= me, + CS35L41_FIRMWARE_ROOT, cs35l41->acpi_subsystem_id, + cs35l41->amp_name, -1, "wmfw"); + if (!ret) { + /* try cirrus/part-dspN-fwtype-sub<-spkidN><-ampname>.bin */ + cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename, + CS35L41_FIRMWARE_ROOT, cs35l41->acpi_subsystem_id, + cs35l41->amp_name, cs35l41->speaker_id, "bin"); + return 0; + } + + /* try cirrus/part-dspN-fwtype-sub<-spkidN>.wmfw */ + ret =3D cs35l41_request_firmware_file(cs35l41, wmfw_firmware, wmfw_filena= me, + CS35L41_FIRMWARE_ROOT, cs35l41->acpi_subsystem_id, + NULL, cs35l41->speaker_id, "wmfw"); + if (!ret) { + /* try cirrus/part-dspN-fwtype-sub<-spkidN><-ampname>.bin */ + ret =3D cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_fil= ename, + CS35L41_FIRMWARE_ROOT, + cs35l41->acpi_subsystem_id, + cs35l41->amp_name, cs35l41->speaker_id, "bin"); + if (ret) + /* try cirrus/part-dspN-fwtype-sub<-spkidN>.bin */ + cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename, + CS35L41_FIRMWARE_ROOT, + cs35l41->acpi_subsystem_id, + NULL, cs35l41->speaker_id, "bin"); + return 0; + } + + /* try cirrus/part-dspN-fwtype-sub.wmfw */ + ret =3D cs35l41_request_firmware_file(cs35l41, wmfw_firmware, wmfw_filena= me, + CS35L41_FIRMWARE_ROOT, cs35l41->acpi_subsystem_id, + NULL, -1, "wmfw"); + if (!ret) { + /* try cirrus/part-dspN-fwtype-sub<-spkidN><-ampname>.bin */ + ret =3D cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_fil= ename, + CS35L41_FIRMWARE_ROOT, + cs35l41->acpi_subsystem_id, + cs35l41->amp_name, cs35l41->speaker_id, "bin"); + if (ret) + /* try cirrus/part-dspN-fwtype-sub<-spkidN>.bin */ + cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename, + CS35L41_FIRMWARE_ROOT, + cs35l41->acpi_subsystem_id, + NULL, cs35l41->speaker_id, "bin"); + return 0; + } + + /* fallback try cirrus/part-dspN-fwtype.wmfw */ + ret =3D cs35l41_request_firmware_file(cs35l41, wmfw_firmware, wmfw_filena= me, + CS35L41_FIRMWARE_ROOT, NULL, NULL, -1, "wmfw"); + if (!ret) { + /* fallback try cirrus/part-dspN-fwtype.bin */ + cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename, + CS35L41_FIRMWARE_ROOT, NULL, NULL, -1, "bin"); + return 0; + } + + dev_warn(cs35l41->dev, "Failed to request firmware\n"); + + return ret; +} + static int cs35l41_request_firmware_files(struct cs35l41_hda *cs35l41, const struct firmware **wmfw_firmware, char **wmfw_filename, @@ -138,43 +231,48 @@ static int cs35l41_request_firmware_files(struct cs35= l41_hda *cs35l41, { int ret; =20 + if (cs35l41->speaker_id > -1) + return cs35l41_request_firmware_files_spkid(cs35l41, wmfw_firmware, wmfw= _filename, + coeff_firmware, coeff_filename); + /* try cirrus/part-dspN-fwtype-sub<-ampname>.wmfw */ ret =3D cs35l41_request_firmware_file(cs35l41, wmfw_firmware, wmfw_filena= me, CS35L41_FIRMWARE_ROOT, cs35l41->acpi_subsystem_id, - cs35l41->amp_name, "wmfw"); + cs35l41->amp_name, -1, "wmfw"); if (!ret) { /* try cirrus/part-dspN-fwtype-sub<-ampname>.bin */ cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename, CS35L41_FIRMWARE_ROOT, cs35l41->acpi_subsystem_id, - cs35l41->amp_name, "bin"); + cs35l41->amp_name, -1, "bin"); return 0; } =20 /* try cirrus/part-dspN-fwtype-sub.wmfw */ ret =3D cs35l41_request_firmware_file(cs35l41, wmfw_firmware, wmfw_filena= me, CS35L41_FIRMWARE_ROOT, cs35l41->acpi_subsystem_id, - NULL, "wmfw"); + NULL, -1, "wmfw"); if (!ret) { /* try cirrus/part-dspN-fwtype-sub<-ampname>.bin */ ret =3D cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_fil= ename, CS35L41_FIRMWARE_ROOT, cs35l41->acpi_subsystem_id, - cs35l41->amp_name, "bin"); + cs35l41->amp_name, -1, "bin"); if (ret) /* try cirrus/part-dspN-fwtype-sub.bin */ cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename, CS35L41_FIRMWARE_ROOT, - cs35l41->acpi_subsystem_id, NULL, "bin"); + cs35l41->acpi_subsystem_id, + NULL, -1, "bin"); return 0; } =20 /* fallback try cirrus/part-dspN-fwtype.wmfw */ ret =3D cs35l41_request_firmware_file(cs35l41, wmfw_firmware, wmfw_filena= me, - CS35L41_FIRMWARE_ROOT, NULL, NULL, "wmfw"); + CS35L41_FIRMWARE_ROOT, NULL, NULL, -1, "wmfw"); if (!ret) { /* fallback try cirrus/part-dspN-fwtype.bin */ cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename, - CS35L41_FIRMWARE_ROOT, NULL, NULL, "bin"); + CS35L41_FIRMWARE_ROOT, NULL, NULL, -1, "bin"); return 0; } =20 @@ -602,6 +700,61 @@ static int cs35l41_get_acpi_sub_string(struct device *= dev, struct acpi_device *a return ret; } =20 +static int cs35l41_get_speaker_id(struct device *dev, int amp_index, + int num_amps, int fixed_gpio_id) +{ + struct gpio_desc *speaker_id_desc; + int speaker_id =3D -ENODEV; + + if (fixed_gpio_id >=3D 0) { + dev_dbg(dev, "Found Fixed Speaker ID GPIO (index =3D %d)\n", fixed_gpio_= id); + speaker_id_desc =3D gpiod_get_index(dev, NULL, fixed_gpio_id, GPIOD_IN); + if (IS_ERR(speaker_id_desc)) { + speaker_id =3D PTR_ERR(speaker_id_desc); + return speaker_id; + } + speaker_id =3D gpiod_get_value_cansleep(speaker_id_desc); + gpiod_put(speaker_id_desc); + dev_dbg(dev, "Speaker ID =3D %d\n", speaker_id); + } else { + int base_index; + int gpios_per_amp; + int count; + int tmp; + int i; + + count =3D gpiod_count(dev, "spk-id"); + if (count > 0) { + speaker_id =3D 0; + gpios_per_amp =3D count / num_amps; + base_index =3D gpios_per_amp * amp_index; + + if (count % num_amps) + return -EINVAL; + + dev_dbg(dev, "Found %d Speaker ID GPIOs per Amp\n", gpios_per_amp); + + for (i =3D 0; i < gpios_per_amp; i++) { + speaker_id_desc =3D gpiod_get_index(dev, "spk-id", i + base_index, + GPIOD_IN); + if (IS_ERR(speaker_id_desc)) { + speaker_id =3D PTR_ERR(speaker_id_desc); + break; + } + tmp =3D gpiod_get_value_cansleep(speaker_id_desc); + gpiod_put(speaker_id_desc); + if (tmp < 0) { + speaker_id =3D tmp; + break; + } + speaker_id |=3D tmp << i; + } + dev_dbg(dev, "Speaker ID =3D %d\n", speaker_id); + } + } + return speaker_id; +} + static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *= hid, int id) { struct cs35l41_hw_cfg *hw_cfg =3D &cs35l41->hw_cfg; @@ -707,6 +860,8 @@ static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs= 35l41, const char *hid, i else hw_cfg->bst_cap =3D -1; =20 + cs35l41->speaker_id =3D cs35l41_get_speaker_id(physdev, cs35l41->index, n= val, -1); + if (hw_cfg->bst_ind > 0 || hw_cfg->bst_cap > 0 || hw_cfg->bst_ipk > 0) hw_cfg->bst_type =3D CS35L41_INT_BOOST; else @@ -740,6 +895,7 @@ static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs= 35l41, const char *hid, i cs35l41->channel_index =3D 0; cs35l41->reset_gpio =3D gpiod_get_index(physdev, NULL, 0, GPIOD_OUT_HIGH); cs35l41->hw_cfg.bst_type =3D CS35L41_EXT_BOOST_NO_VSPK_SWITCH; + cs35l41->speaker_id =3D cs35l41_get_speaker_id(physdev, 0, 0, 2); hw_cfg->gpio2.func =3D CS35L41_GPIO2_INT_OPEN_DRAIN; hw_cfg->gpio2.valid =3D true; cs35l41->hw_cfg.valid =3D true; diff --git a/sound/pci/hda/cs35l41_hda.h b/sound/pci/hda/cs35l41_hda.h index b8352088a5cb..717b30a2e33b 100644 --- a/sound/pci/hda/cs35l41_hda.h +++ b/sound/pci/hda/cs35l41_hda.h @@ -43,6 +43,7 @@ struct cs35l41_hda { unsigned volatile long irq_errors; const char *amp_name; const char *acpi_subsystem_id; + int speaker_id; struct regmap_irq_chip_data *irq_data; bool firmware_running; bool halo_initialized; --=20 2.34.1 From nobody Tue May 5 10:00:43 2026 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 DAE62C433F5 for ; Wed, 25 May 2022 13:18:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244380AbiEYNSR (ORCPT ); Wed, 25 May 2022 09:18:17 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37648 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244390AbiEYNRk (ORCPT ); Wed, 25 May 2022 09:17:40 -0400 Received: from mx0b-001ae601.pphosted.com (mx0b-001ae601.pphosted.com [67.231.152.168]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C9BD311152 for ; Wed, 25 May 2022 06:17:30 -0700 (PDT) Received: from pps.filterd (m0077474.ppops.net [127.0.0.1]) by mx0b-001ae601.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 24PCRmjH022096; Wed, 25 May 2022 08:16:45 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=VKkphNH8QA4Izj/k6GEo35fXfHV4R/YMLEy/KzQdSnU=; b=jP7fT1ej2z2m41sBzlDseWlKV99LTN8gfPvg51F/7GnvoJMJhrr9DJw7rp1TlfNNejs+ TuYVyGzHM40wNumeQiIhDhcw/4rc+jXAK8Y4FB07H3USS+7lVtxTSLxuziAK8C2v8RCA E8j9qrPCI0ougajNBLbP3I6FfoX5i0yA89ikzi3d8uaVRUKXXZ05m+NSz7+8Fgt4jT5n dD54KiwOYp4SXxyt73EH8shCc9tXJK+iiDRUBkHFtDJeby5q/z2cAYxr1UD3SkWgDept qtqZ3FAZaNrxCRl70fGMtjpJc0wkamRZu28wn0/T1HFVQEckuAuKBwOqZie9J/Ch1ZUE ew== Received: from ediex01.ad.cirrus.com ([84.19.233.68]) by mx0b-001ae601.pphosted.com (PPS) with ESMTPS id 3g93u20we6-7 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT); Wed, 25 May 2022 08:16:45 -0500 Received: from EDIEX01.ad.cirrus.com (198.61.84.80) by EDIEX01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.24; Wed, 25 May 2022 14:16:43 +0100 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by EDIEX01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server id 15.1.2375.24 via Frontend Transport; Wed, 25 May 2022 14:16:43 +0100 Received: from vitaly-Legion-7-16ACHg6.ad.cirrus.com (unknown [198.90.238.233]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id F3B83468; Wed, 25 May 2022 13:16:42 +0000 (UTC) From: Vitaly Rodionov To: Jaroslav Kysela , Takashi Iwai , Mark Brown CC: , , , Stefan Binding , Charles Keepax Subject: [PATCH v4 09/17] ASoC: cs35l41: Move cs35l41 exit hibernate function into shared code Date: Wed, 25 May 2022 14:16:30 +0100 Message-ID: <20220525131638.5512-10-vitalyr@opensource.cirrus.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220525131638.5512-1-vitalyr@opensource.cirrus.com> References: <20220525131638.5512-1-vitalyr@opensource.cirrus.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-ORIG-GUID: dnloY0RABqJh7uxlYje9FcPNbQuiYcmI X-Proofpoint-GUID: dnloY0RABqJh7uxlYje9FcPNbQuiYcmI X-Proofpoint-Spam-Reason: safe Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" From: Stefan Binding CS35L41 HDA Driver will support hibernation using DSP firmware, move the exit hibernate function into shared code so this can be reused. Acked-by: Charles Keepax Signed-off-by: Stefan Binding Signed-off-by: Vitaly Rodionov --- Changes since v2: - No change =20 include/sound/cs35l41.h | 1 + sound/soc/codecs/cs35l41-lib.c | 60 +++++++++++++++++++++++++++++++++ sound/soc/codecs/cs35l41.c | 61 +--------------------------------- 3 files changed, 62 insertions(+), 60 deletions(-) diff --git a/include/sound/cs35l41.h b/include/sound/cs35l41.h index 8887087815a7..f848ba1e75b3 100644 --- a/include/sound/cs35l41.h +++ b/include/sound/cs35l41.h @@ -885,6 +885,7 @@ void cs35l41_configure_cs_dsp(struct device *dev, struc= t regmap *reg, struct cs_ int cs35l41_set_cspl_mbox_cmd(struct device *dev, struct regmap *regmap, enum cs35l41_cspl_mbox_cmd cmd); int cs35l41_write_fs_errata(struct device *dev, struct regmap *regmap); +int cs35l41_exit_hibernate(struct device *dev, struct regmap *regmap); int cs35l41_init_boost(struct device *dev, struct regmap *regmap, struct cs35l41_hw_cfg *hw_cfg); bool cs35l41_safe_reset(struct regmap *regmap, enum cs35l41_boost_type b_t= ype); diff --git a/sound/soc/codecs/cs35l41-lib.c b/sound/soc/codecs/cs35l41-lib.c index 6d3070ea9e06..cc5366c8bdd6 100644 --- a/sound/soc/codecs/cs35l41-lib.c +++ b/sound/soc/codecs/cs35l41-lib.c @@ -1321,6 +1321,66 @@ int cs35l41_write_fs_errata(struct device *dev, stru= ct regmap *regmap) } EXPORT_SYMBOL_GPL(cs35l41_write_fs_errata); =20 +static void cs35l41_wait_for_pwrmgt_sts(struct device *dev, struct regmap = *regmap) +{ + const int pwrmgt_retries =3D 10; + unsigned int sts; + int i, ret; + + for (i =3D 0; i < pwrmgt_retries; i++) { + ret =3D regmap_read(regmap, CS35L41_PWRMGT_STS, &sts); + if (ret) + dev_err(dev, "Failed to read PWRMGT_STS: %d\n", ret); + else if (!(sts & CS35L41_WR_PEND_STS_MASK)) + return; + + udelay(20); + } + + dev_err(dev, "Timed out reading PWRMGT_STS\n"); +} + +int cs35l41_exit_hibernate(struct device *dev, struct regmap *regmap) +{ + const int wake_retries =3D 20; + const int sleep_retries =3D 5; + int ret, i, j; + + for (i =3D 0; i < sleep_retries; i++) { + dev_dbg(dev, "Exit hibernate\n"); + + for (j =3D 0; j < wake_retries; j++) { + ret =3D cs35l41_set_cspl_mbox_cmd(dev, regmap, + CSPL_MBOX_CMD_OUT_OF_HIBERNATE); + if (!ret) + break; + + usleep_range(100, 200); + } + + if (j < wake_retries) { + dev_dbg(dev, "Wake success at cycle: %d\n", j); + return 0; + } + + dev_err(dev, "Wake failed, re-enter hibernate: %d\n", ret); + + cs35l41_wait_for_pwrmgt_sts(dev, regmap); + regmap_write(regmap, CS35L41_WAKESRC_CTL, 0x0088); + + cs35l41_wait_for_pwrmgt_sts(dev, regmap); + regmap_write(regmap, CS35L41_WAKESRC_CTL, 0x0188); + + cs35l41_wait_for_pwrmgt_sts(dev, regmap); + regmap_write(regmap, CS35L41_PWRMGT_CTL, 0x3); + } + + dev_err(dev, "Timed out waking device\n"); + + return -ETIMEDOUT; +} +EXPORT_SYMBOL_GPL(cs35l41_exit_hibernate); + MODULE_DESCRIPTION("CS35L41 library"); MODULE_AUTHOR("David Rhodes, Cirrus Logic Inc, "); MODULE_AUTHOR("Lucas Tanure, Cirrus Logic Inc, "); diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c index 3e68a07a3c8e..be7d02517739 100644 --- a/sound/soc/codecs/cs35l41.c +++ b/sound/soc/codecs/cs35l41.c @@ -1351,65 +1351,6 @@ static int __maybe_unused cs35l41_runtime_suspend(st= ruct device *dev) return 0; } =20 -static void cs35l41_wait_for_pwrmgt_sts(struct cs35l41_private *cs35l41) -{ - const int pwrmgt_retries =3D 10; - unsigned int sts; - int i, ret; - - for (i =3D 0; i < pwrmgt_retries; i++) { - ret =3D regmap_read(cs35l41->regmap, CS35L41_PWRMGT_STS, &sts); - if (ret) - dev_err(cs35l41->dev, "Failed to read PWRMGT_STS: %d\n", ret); - else if (!(sts & CS35L41_WR_PEND_STS_MASK)) - return; - - udelay(20); - } - - dev_err(cs35l41->dev, "Timed out reading PWRMGT_STS\n"); -} - -static int cs35l41_exit_hibernate(struct cs35l41_private *cs35l41) -{ - const int wake_retries =3D 20; - const int sleep_retries =3D 5; - int ret, i, j; - - for (i =3D 0; i < sleep_retries; i++) { - dev_dbg(cs35l41->dev, "Exit hibernate\n"); - - for (j =3D 0; j < wake_retries; j++) { - ret =3D cs35l41_set_cspl_mbox_cmd(cs35l41->dev, cs35l41->regmap, - CSPL_MBOX_CMD_OUT_OF_HIBERNATE); - if (!ret) - break; - - usleep_range(100, 200); - } - - if (j < wake_retries) { - dev_dbg(cs35l41->dev, "Wake success at cycle: %d\n", j); - return 0; - } - - dev_err(cs35l41->dev, "Wake failed, re-enter hibernate: %d\n", ret); - - cs35l41_wait_for_pwrmgt_sts(cs35l41); - regmap_write(cs35l41->regmap, CS35L41_WAKESRC_CTL, 0x0088); - - cs35l41_wait_for_pwrmgt_sts(cs35l41); - regmap_write(cs35l41->regmap, CS35L41_WAKESRC_CTL, 0x0188); - - cs35l41_wait_for_pwrmgt_sts(cs35l41); - regmap_write(cs35l41->regmap, CS35L41_PWRMGT_CTL, 0x3); - } - - dev_err(cs35l41->dev, "Timed out waking device\n"); - - return -ETIMEDOUT; -} - static int __maybe_unused cs35l41_runtime_resume(struct device *dev) { struct cs35l41_private *cs35l41 =3D dev_get_drvdata(dev); @@ -1422,7 +1363,7 @@ static int __maybe_unused cs35l41_runtime_resume(stru= ct device *dev) =20 regcache_cache_only(cs35l41->regmap, false); =20 - ret =3D cs35l41_exit_hibernate(cs35l41); + ret =3D cs35l41_exit_hibernate(cs35l41->dev, cs35l41->regmap); if (ret) return ret; =20 --=20 2.34.1 From nobody Tue May 5 10:00:43 2026 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 697CDC433F5 for ; Wed, 25 May 2022 13:17:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231299AbiEYNRZ (ORCPT ); Wed, 25 May 2022 09:17:25 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34368 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239122AbiEYNQ7 (ORCPT ); Wed, 25 May 2022 09:16:59 -0400 Received: from mx0b-001ae601.pphosted.com (mx0b-001ae601.pphosted.com [67.231.152.168]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 64C0CE00B for ; Wed, 25 May 2022 06:16:57 -0700 (PDT) Received: from pps.filterd (m0077474.ppops.net [127.0.0.1]) by mx0b-001ae601.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 24PCRmjI022096; Wed, 25 May 2022 08:16:46 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=VovP2fjHmWUZWiLciMKSnLk1aUbcDY4P7rblNQN7RKM=; b=XfqjvFfnpEY8n8ORa4hJO4LxzKZ3gcSWFo8woA9SzWd4yMB6k42SvpnUvZDLWTcmX/mJ lRJfIAbaJAnBmzyzZLooJ7I5/G4S9nQcOj+vXguJ33MFs7JUTgxuNporxAbr6xSb8hkH FWwgKQkdEuNLRbRxLiFJkVzA/67erJBpUzh5FUx8YLOrO+OEs+hqvE2Y71BUA0kjyk9h OAqlbrgrfrH0cZiwmivZInD+Ja02iPL6UAiH3MnRLOel97NJ47p5AxdMSfbmvQ4IX8Cf yu8L7MxFtXPJMbmPG2pOwE7NX9+PYWBrcCqDZG00g5Npxgo3xfo8dPEuu2SwQo8C0IFG kQ== Received: from ediex01.ad.cirrus.com ([84.19.233.68]) by mx0b-001ae601.pphosted.com (PPS) with ESMTPS id 3g93u20we6-8 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT); Wed, 25 May 2022 08:16:46 -0500 Received: from EDIEX01.ad.cirrus.com (198.61.84.80) by EDIEX01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.24; Wed, 25 May 2022 14:16:43 +0100 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by EDIEX01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server id 15.1.2375.24 via Frontend Transport; Wed, 25 May 2022 14:16:43 +0100 Received: from vitaly-Legion-7-16ACHg6.ad.cirrus.com (unknown [198.90.238.233]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id 620A846C; Wed, 25 May 2022 13:16:43 +0000 (UTC) From: Vitaly Rodionov To: Jaroslav Kysela , Takashi Iwai , Mark Brown CC: , , , Stefan Binding Subject: [PATCH v4 10/17] ASoC: cs35l41: Do not print error when waking from hibernation Date: Wed, 25 May 2022 14:16:31 +0100 Message-ID: <20220525131638.5512-11-vitalyr@opensource.cirrus.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220525131638.5512-1-vitalyr@opensource.cirrus.com> References: <20220525131638.5512-1-vitalyr@opensource.cirrus.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-ORIG-GUID: UpThctazHpv93Cr7d4kdTzKRFBHrtW7C X-Proofpoint-GUID: UpThctazHpv93Cr7d4kdTzKRFBHrtW7C X-Proofpoint-Spam-Reason: safe Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" From: Stefan Binding When waking from hibernation, it is possible for the function which sends the wake command to fail initially, but after a retry it will succeed. There is no need to print an error if the initial attempts fail. Signed-off-by: Stefan Binding Signed-off-by: Vitaly Rodionov Acked-by: Charles Keepax --- Changes since v2: - No change =20 sound/soc/codecs/cs35l41-lib.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/cs35l41-lib.c b/sound/soc/codecs/cs35l41-lib.c index cc5366c8bdd6..e726a38f1997 100644 --- a/sound/soc/codecs/cs35l41-lib.c +++ b/sound/soc/codecs/cs35l41-lib.c @@ -1302,7 +1302,8 @@ int cs35l41_set_cspl_mbox_cmd(struct device *dev, str= uct regmap *regmap, return 0; } =20 - dev_err(dev, "Failed to set mailbox cmd %u (status %u)\n", cmd, sts); + if (cmd !=3D CSPL_MBOX_CMD_OUT_OF_HIBERNATE) + dev_err(dev, "Failed to set mailbox cmd %u (status %u)\n", cmd, sts); =20 return -ENOMSG; } --=20 2.34.1 From nobody Tue May 5 10:00:43 2026 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 22D9FC433EF for ; Wed, 25 May 2022 13:17:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244189AbiEYNRi (ORCPT ); Wed, 25 May 2022 09:17:38 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34472 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241789AbiEYNRB (ORCPT ); Wed, 25 May 2022 09:17:01 -0400 Received: from mx0b-001ae601.pphosted.com (mx0b-001ae601.pphosted.com [67.231.152.168]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6B8F2DFC6 for ; Wed, 25 May 2022 06:16:59 -0700 (PDT) Received: from pps.filterd (m0077474.ppops.net [127.0.0.1]) by mx0b-001ae601.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 24PCRmjJ022096; Wed, 25 May 2022 08:16:47 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=WCDKyNszpTkK132PkGJoQgMJ3LGwxsgI4k0HIIXEq10=; b=ea111qRqFbBxflDk2F/Zm8w0Ue0vy+0VmLrsrHcOILt6nTE+gsFzjlr5ZVxQGwGPXEY8 6USRUDwto7esljUqo1sfKbOQ9x86/SQora5fymIptsAz+mZLRAU9Edy47a2yoUwoUxyN nUowAeXniJrN8wwm4EbvF795nKHeBFqBTno6SNv7Bi0jxbghyx6H8GVVV1EP3QUrZhPz yxoTzxnQQ2LCnGc1Sno7xeCXK1eOtvXpbpdhBws6iObPu4CbemZq8wog26c6LuFJPoyw DM0rt/6yg2Z6lDnoy/k0U2BNetct1v+68prOxHKybwFVplqS2oSOn4N/d0bXhHCkkB7m qA== Received: from ediex01.ad.cirrus.com ([84.19.233.68]) by mx0b-001ae601.pphosted.com (PPS) with ESMTPS id 3g93u20we6-9 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT); Wed, 25 May 2022 08:16:47 -0500 Received: from EDIEX01.ad.cirrus.com (198.61.84.80) by EDIEX01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.24; Wed, 25 May 2022 14:16:44 +0100 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by EDIEX01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server id 15.1.2375.24 via Frontend Transport; Wed, 25 May 2022 14:16:44 +0100 Received: from vitaly-Legion-7-16ACHg6.ad.cirrus.com (unknown [198.90.238.233]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id C90B2468; Wed, 25 May 2022 13:16:43 +0000 (UTC) From: Vitaly Rodionov To: Jaroslav Kysela , Takashi Iwai , Mark Brown CC: , , , Stefan Binding , Charles Keepax Subject: [PATCH v4 11/17] ASoC: cs35l41: Add common cs35l41 enter hibernate function Date: Wed, 25 May 2022 14:16:32 +0100 Message-ID: <20220525131638.5512-12-vitalyr@opensource.cirrus.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220525131638.5512-1-vitalyr@opensource.cirrus.com> References: <20220525131638.5512-1-vitalyr@opensource.cirrus.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-ORIG-GUID: dyGbDR_D487PA2xikFLn3BxseetkF1-G X-Proofpoint-GUID: dyGbDR_D487PA2xikFLn3BxseetkF1-G X-Proofpoint-Spam-Reason: safe Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" From: Stefan Binding Since the CS35L41 HDA driver also support hibernation, it makes sense to move code from the ASoC driver to enter hibernation into common code. Since HDA must support laptops which do not support hibernation due to lack of external boost GPIO it is necessary to ensure the function returns an error when an unsupported boost type is in use. Acked-by: Charles Keepax Signed-off-by: Stefan Binding Signed-off-by: Vitaly Rodionov --- Changes since v2: - No change =20 include/sound/cs35l41.h | 2 ++ sound/soc/codecs/cs35l41-lib.c | 19 +++++++++++++++++++ sound/soc/codecs/cs35l41.c | 10 +--------- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/include/sound/cs35l41.h b/include/sound/cs35l41.h index f848ba1e75b3..9ac5918269a5 100644 --- a/include/sound/cs35l41.h +++ b/include/sound/cs35l41.h @@ -885,6 +885,8 @@ void cs35l41_configure_cs_dsp(struct device *dev, struc= t regmap *reg, struct cs_ int cs35l41_set_cspl_mbox_cmd(struct device *dev, struct regmap *regmap, enum cs35l41_cspl_mbox_cmd cmd); int cs35l41_write_fs_errata(struct device *dev, struct regmap *regmap); +int cs35l41_enter_hibernate(struct device *dev, struct regmap *regmap, + enum cs35l41_boost_type b_type); int cs35l41_exit_hibernate(struct device *dev, struct regmap *regmap); int cs35l41_init_boost(struct device *dev, struct regmap *regmap, struct cs35l41_hw_cfg *hw_cfg); diff --git a/sound/soc/codecs/cs35l41-lib.c b/sound/soc/codecs/cs35l41-lib.c index e726a38f1997..0c7d1c791279 100644 --- a/sound/soc/codecs/cs35l41-lib.c +++ b/sound/soc/codecs/cs35l41-lib.c @@ -1322,6 +1322,25 @@ int cs35l41_write_fs_errata(struct device *dev, stru= ct regmap *regmap) } EXPORT_SYMBOL_GPL(cs35l41_write_fs_errata); =20 +int cs35l41_enter_hibernate(struct device *dev, struct regmap *regmap, + enum cs35l41_boost_type b_type) +{ + if (!cs35l41_safe_reset(regmap, b_type)) { + dev_dbg(dev, "System does not support Suspend\n"); + return -EINVAL; + } + + dev_dbg(dev, "Enter hibernate\n"); + regmap_write(regmap, CS35L41_WAKESRC_CTL, 0x0088); + regmap_write(regmap, CS35L41_WAKESRC_CTL, 0x0188); + + // Don't wait for ACK since bus activity would wake the device + regmap_write(regmap, CS35L41_DSP_VIRT1_MBOX_1, CSPL_MBOX_CMD_HIBERNATE); + + return 0; +} +EXPORT_SYMBOL_GPL(cs35l41_enter_hibernate); + static void cs35l41_wait_for_pwrmgt_sts(struct device *dev, struct regmap = *regmap) { const int pwrmgt_retries =3D 10; diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c index be7d02517739..a115ea35b92d 100644 --- a/sound/soc/codecs/cs35l41.c +++ b/sound/soc/codecs/cs35l41.c @@ -1335,15 +1335,7 @@ static int __maybe_unused cs35l41_runtime_suspend(st= ruct device *dev) if (!cs35l41->dsp.preloaded || !cs35l41->dsp.cs_dsp.running) return 0; =20 - dev_dbg(cs35l41->dev, "Enter hibernate\n"); - - cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type); - regmap_write(cs35l41->regmap, CS35L41_WAKESRC_CTL, 0x0088); - regmap_write(cs35l41->regmap, CS35L41_WAKESRC_CTL, 0x0188); - - // Don't wait for ACK since bus activity would wake the device - regmap_write(cs35l41->regmap, CS35L41_DSP_VIRT1_MBOX_1, - CSPL_MBOX_CMD_HIBERNATE); + cs35l41_enter_hibernate(dev, cs35l41->regmap, cs35l41->hw_cfg.bst_type); =20 regcache_cache_only(cs35l41->regmap, true); regcache_mark_dirty(cs35l41->regmap); --=20 2.34.1 From nobody Tue May 5 10:00:43 2026 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 3692AC433F5 for ; Wed, 25 May 2022 13:17:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242829AbiEYNRr (ORCPT ); Wed, 25 May 2022 09:17:47 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34566 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244014AbiEYNRC (ORCPT ); Wed, 25 May 2022 09:17:02 -0400 Received: from mx0b-001ae601.pphosted.com (mx0b-001ae601.pphosted.com [67.231.152.168]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 745F8DFD4 for ; Wed, 25 May 2022 06:17:01 -0700 (PDT) Received: from pps.filterd (m0077474.ppops.net [127.0.0.1]) by mx0b-001ae601.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 24PCRmjK022096; Wed, 25 May 2022 08:16:49 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=x6uQoyctrHPlWbuzGaH2qzzAbxTQ0aD3UXrmL74s7YY=; b=ZddpSmtVhBv7aKGOzcot4OinWyp6whoxl8GNe/Dbq5xjlwMUuBThBpDWz5ttSFepcRXv KDB+kmrcFva8FUHuC0eh9N93mPtyPxDmUZ3mQa+8XUXJksnA845YbsCmfFFUp8JPat9E Wcdrqh2kYeqsL/rM5dhygfrRJPCoiQol5A/5yLctOg4AAkc0UzGHjY00t8D4CetIHyDI DQjQ2zdseXYyo25/GkNobZg6wUk4ec+VMKClLYDvZ+oyQ1j+lBnQf7Siakzzb4TIKCPB vcujh9RgDzI/AeiLb3Tj0q9gGxH3Z10EBuZ6Lt6CnjyuV2RwrG0AHZGUADratqrcn7y1 Sw== Received: from ediex01.ad.cirrus.com ([84.19.233.68]) by mx0b-001ae601.pphosted.com (PPS) with ESMTPS id 3g93u20we6-10 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT); Wed, 25 May 2022 08:16:48 -0500 Received: from EDIEX01.ad.cirrus.com (198.61.84.80) by EDIEX01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.24; Wed, 25 May 2022 14:16:44 +0100 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by EDIEX01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server id 15.1.2375.24 via Frontend Transport; Wed, 25 May 2022 14:16:44 +0100 Received: from vitaly-Legion-7-16ACHg6.ad.cirrus.com (unknown [198.90.238.233]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id 495F511D1; Wed, 25 May 2022 13:16:44 +0000 (UTC) From: Vitaly Rodionov To: Jaroslav Kysela , Takashi Iwai , Mark Brown CC: , , , Stefan Binding Subject: [PATCH v4 12/17] ALSA: hda: cs35l41: Support Hibernation during Suspend Date: Wed, 25 May 2022 14:16:33 +0100 Message-ID: <20220525131638.5512-13-vitalyr@opensource.cirrus.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220525131638.5512-1-vitalyr@opensource.cirrus.com> References: <20220525131638.5512-1-vitalyr@opensource.cirrus.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-ORIG-GUID: LhCULscjGxo92_th9vUrPZFCohOJ_4Mg X-Proofpoint-GUID: LhCULscjGxo92_th9vUrPZFCohOJ_4Mg X-Proofpoint-Spam-Reason: safe Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" From: Stefan Binding CS35L41 supports hibernation during suspend when using DSP firmware. When the driver suspends it will hibernate the part, if firmware is running, and resume will wake from hibernation. CS35L41 driver will suspend/resume when requested by hda driver. Note that suspend/resume and hibernation is only supported when firmware is running. Signed-off-by: Stefan Binding Signed-off-by: Vitaly Rodionov --- Changes since v2: - No change =20 sound/pci/hda/cs35l41_hda.c | 109 +++++++++++++++++++++++++++++++- sound/pci/hda/cs35l41_hda.h | 2 + sound/pci/hda/cs35l41_hda_i2c.c | 1 + sound/pci/hda/cs35l41_hda_spi.c | 1 + sound/pci/hda/hda_component.h | 2 + sound/pci/hda/patch_realtek.c | 25 +++++++- 6 files changed, 136 insertions(+), 4 deletions(-) diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c index 1d62a41fbc75..9c622104bf01 100644 --- a/sound/pci/hda/cs35l41_hda.c +++ b/sound/pci/hda/cs35l41_hda.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "hda_local.h" #include "hda_auto_parser.h" #include "hda_jack.h" @@ -425,6 +426,75 @@ static int cs35l41_hda_channel_map(struct device *dev,= unsigned int tx_num, unsi rx_slot); } =20 +static int cs35l41_runtime_suspend(struct device *dev) +{ + struct cs35l41_hda *cs35l41 =3D dev_get_drvdata(dev); + + dev_dbg(cs35l41->dev, "Suspend\n"); + + if (!cs35l41->firmware_running) + return 0; + + if (cs35l41_enter_hibernate(cs35l41->dev, cs35l41->regmap, cs35l41->hw_cf= g.bst_type) < 0) + return 0; + + regcache_cache_only(cs35l41->regmap, true); + regcache_mark_dirty(cs35l41->regmap); + + return 0; +} + +static int cs35l41_runtime_resume(struct device *dev) +{ + struct cs35l41_hda *cs35l41 =3D dev_get_drvdata(dev); + int ret; + + dev_dbg(cs35l41->dev, "Resume.\n"); + + if (cs35l41->hw_cfg.bst_type =3D=3D CS35L41_EXT_BOOST_NO_VSPK_SWITCH) { + dev_dbg(cs35l41->dev, "System does not support Resume\n"); + return 0; + } + + if (!cs35l41->firmware_running) + return 0; + + regcache_cache_only(cs35l41->regmap, false); + + ret =3D cs35l41_exit_hibernate(cs35l41->dev, cs35l41->regmap); + if (ret) { + regcache_cache_only(cs35l41->regmap, true); + return ret; + } + + /* Test key needs to be unlocked to allow the OTP settings to re-apply */ + cs35l41_test_key_unlock(cs35l41->dev, cs35l41->regmap); + ret =3D regcache_sync(cs35l41->regmap); + cs35l41_test_key_lock(cs35l41->dev, cs35l41->regmap); + if (ret) { + dev_err(cs35l41->dev, "Failed to restore register cache: %d\n", ret); + return ret; + } + + if (cs35l41->hw_cfg.bst_type =3D=3D CS35L41_EXT_BOOST) + cs35l41_init_boost(cs35l41->dev, cs35l41->regmap, &cs35l41->hw_cfg); + + return 0; +} + +static int cs35l41_hda_suspend_hook(struct device *dev) +{ + dev_dbg(dev, "Request Suspend\n"); + pm_runtime_mark_last_busy(dev); + return pm_runtime_put_autosuspend(dev); +} + +static int cs35l41_hda_resume_hook(struct device *dev) +{ + dev_dbg(dev, "Request Resume\n"); + return pm_runtime_get_sync(dev); +} + static int cs35l41_smart_amp(struct cs35l41_hda *cs35l41) { int halo_sts; @@ -482,17 +552,25 @@ static int cs35l41_hda_bind(struct device *dev, struc= t device *master, void *mas if (comps->dev) return -EBUSY; =20 + pm_runtime_get_sync(dev); + comps->dev =3D dev; if (!cs35l41->acpi_subsystem_id) cs35l41->acpi_subsystem_id =3D devm_kasprintf(dev, GFP_KERNEL, "%.8x", comps->subsystem_id); cs35l41->codec =3D comps->codec; strscpy(comps->name, dev_name(dev), sizeof(comps->name)); - comps->playback_hook =3D cs35l41_hda_playback_hook; =20 if (cs35l41_smart_amp(cs35l41) < 0) dev_warn(cs35l41->dev, "Cannot Run Firmware, reverting to dsp bypass...\= n"); =20 + comps->playback_hook =3D cs35l41_hda_playback_hook; + comps->suspend_hook =3D cs35l41_hda_suspend_hook; + comps->resume_hook =3D cs35l41_hda_resume_hook; + + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + return 0; } =20 @@ -588,7 +666,7 @@ static const struct regmap_irq cs35l41_reg_irqs[] =3D { CS35L41_REG_IRQ(IRQ1_STATUS1, AMP_SHORT_ERR), }; =20 -static const struct regmap_irq_chip cs35l41_regmap_irq_chip =3D { +static struct regmap_irq_chip cs35l41_regmap_irq_chip =3D { .name =3D "cs35l41 IRQ1 Controller", .status_base =3D CS35L41_IRQ1_STATUS1, .mask_base =3D CS35L41_IRQ1_MASK1, @@ -596,6 +674,7 @@ static const struct regmap_irq_chip cs35l41_regmap_irq_= chip =3D { .num_regs =3D 4, .irqs =3D cs35l41_reg_irqs, .num_irqs =3D ARRAY_SIZE(cs35l41_reg_irqs), + .runtime_pm =3D true, }; =20 static int cs35l41_hda_apply_properties(struct cs35l41_hda *cs35l41) @@ -1003,13 +1082,23 @@ int cs35l41_hda_probe(struct device *dev, const cha= r *device_name, int id, int i if (ret) goto err; =20 + pm_runtime_set_autosuspend_delay(cs35l41->dev, 3000); + pm_runtime_use_autosuspend(cs35l41->dev); + pm_runtime_mark_last_busy(cs35l41->dev); + pm_runtime_set_active(cs35l41->dev); + pm_runtime_get_noresume(cs35l41->dev); + pm_runtime_enable(cs35l41->dev); + ret =3D cs35l41_hda_apply_properties(cs35l41); if (ret) - goto err; + goto err_pm; + + pm_runtime_put_autosuspend(cs35l41->dev); =20 ret =3D component_add(cs35l41->dev, &cs35l41_hda_comp_ops); if (ret) { dev_err(cs35l41->dev, "Register component failed: %d\n", ret); + pm_runtime_disable(cs35l41->dev); goto err; } =20 @@ -1017,6 +1106,10 @@ int cs35l41_hda_probe(struct device *dev, const char= *device_name, int id, int i =20 return 0; =20 +err_pm: + pm_runtime_disable(cs35l41->dev); + pm_runtime_put_noidle(cs35l41->dev); + err: if (cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type)) gpiod_set_value_cansleep(cs35l41->reset_gpio, 0); @@ -1030,17 +1123,27 @@ void cs35l41_hda_remove(struct device *dev) { struct cs35l41_hda *cs35l41 =3D dev_get_drvdata(dev); =20 + pm_runtime_get_sync(cs35l41->dev); + pm_runtime_disable(cs35l41->dev); + if (cs35l41->firmware_running) cs35l41_remove_dsp(cs35l41); =20 component_del(cs35l41->dev, &cs35l41_hda_comp_ops); =20 + pm_runtime_put_noidle(cs35l41->dev); + if (cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type)) gpiod_set_value_cansleep(cs35l41->reset_gpio, 0); gpiod_put(cs35l41->reset_gpio); } EXPORT_SYMBOL_NS_GPL(cs35l41_hda_remove, SND_HDA_SCODEC_CS35L41); =20 +const struct dev_pm_ops cs35l41_hda_pm_ops =3D { + SET_RUNTIME_PM_OPS(cs35l41_runtime_suspend, cs35l41_runtime_resume, NULL) +}; +EXPORT_SYMBOL_NS_GPL(cs35l41_hda_pm_ops, SND_HDA_SCODEC_CS35L41); + MODULE_DESCRIPTION("CS35L41 HDA Driver"); MODULE_IMPORT_NS(SND_HDA_CS_DSP_CONTROLS); MODULE_AUTHOR("Lucas Tanure, Cirrus Logic Inc, "); diff --git a/sound/pci/hda/cs35l41_hda.h b/sound/pci/hda/cs35l41_hda.h index 717b30a2e33b..54521a013e78 100644 --- a/sound/pci/hda/cs35l41_hda.h +++ b/sound/pci/hda/cs35l41_hda.h @@ -56,6 +56,8 @@ enum halo_state { HALO_STATE_CODE_RUN }; =20 +extern const struct dev_pm_ops cs35l41_hda_pm_ops; + int cs35l41_hda_probe(struct device *dev, const char *device_name, int id,= int irq, struct regmap *regmap); void cs35l41_hda_remove(struct device *dev); diff --git a/sound/pci/hda/cs35l41_hda_i2c.c b/sound/pci/hda/cs35l41_hda_i2= c.c index e810b278fb91..a669090a18e8 100644 --- a/sound/pci/hda/cs35l41_hda_i2c.c +++ b/sound/pci/hda/cs35l41_hda_i2c.c @@ -55,6 +55,7 @@ static struct i2c_driver cs35l41_i2c_driver =3D { .driver =3D { .name =3D "cs35l41-hda", .acpi_match_table =3D ACPI_PTR(cs35l41_acpi_hda_match), + .pm =3D &cs35l41_hda_pm_ops, }, .id_table =3D cs35l41_hda_i2c_id, .probe =3D cs35l41_hda_i2c_probe, diff --git a/sound/pci/hda/cs35l41_hda_spi.c b/sound/pci/hda/cs35l41_hda_sp= i.c index 22e088f28438..d7f15e2abe66 100644 --- a/sound/pci/hda/cs35l41_hda_spi.c +++ b/sound/pci/hda/cs35l41_hda_spi.c @@ -50,6 +50,7 @@ static struct spi_driver cs35l41_spi_driver =3D { .driver =3D { .name =3D "cs35l41-hda", .acpi_match_table =3D ACPI_PTR(cs35l41_acpi_hda_match), + .pm =3D &cs35l41_hda_pm_ops, }, .id_table =3D cs35l41_hda_spi_id, .probe =3D cs35l41_hda_spi_probe, diff --git a/sound/pci/hda/hda_component.h b/sound/pci/hda/hda_component.h index fa6df52e7855..72ec0d865a28 100644 --- a/sound/pci/hda/hda_component.h +++ b/sound/pci/hda/hda_component.h @@ -17,4 +17,6 @@ struct hda_component { int subsystem_id; struct hda_codec *codec; void (*playback_hook)(struct device *dev, int action); + int (*suspend_hook)(struct device *dev); + int (*resume_hook)(struct device *dev); }; diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index b8249c4dcb1d..fc2467d03b8a 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4006,15 +4006,22 @@ static void alc5505_dsp_init(struct hda_codec *code= c) static int alc269_suspend(struct hda_codec *codec) { struct alc_spec *spec =3D codec->spec; + int i; =20 if (spec->has_alc5505_dsp) alc5505_dsp_suspend(codec); + + for (i =3D 0; i < HDA_MAX_COMPONENTS; i++) + if (spec->comps[i].suspend_hook) + spec->comps[i].suspend_hook(spec->comps[i].dev); + return alc_suspend(codec); } =20 static int alc269_resume(struct hda_codec *codec) { struct alc_spec *spec =3D codec->spec; + int i; =20 if (spec->codec_variant =3D=3D ALC269_TYPE_ALC269VB) alc269vb_toggle_power_output(codec, 0); @@ -4045,6 +4052,10 @@ static int alc269_resume(struct hda_codec *codec) if (spec->has_alc5505_dsp) alc5505_dsp_resume(codec); =20 + for (i =3D 0; i < HDA_MAX_COMPONENTS; i++) + if (spec->comps[i].resume_hook) + spec->comps[i].resume_hook(spec->comps[i].dev); + return 0; } #endif /* CONFIG_PM */ @@ -6587,8 +6598,20 @@ static int comp_bind(struct device *dev) { struct hda_codec *cdc =3D dev_to_hda_codec(dev); struct alc_spec *spec =3D cdc->spec; + int ret, i; + + ret =3D component_bind_all(dev, spec->comps); + if (ret) + return ret; =20 - return component_bind_all(dev, spec->comps); + if (snd_hdac_is_power_on(&cdc->core)) { + codec_dbg(cdc, "Resuming after bind.\n"); + for (i =3D 0; i < HDA_MAX_COMPONENTS; i++) + if (spec->comps[i].resume_hook) + spec->comps[i].resume_hook(spec->comps[i].dev); + } + + return 0; } =20 static void comp_unbind(struct device *dev) --=20 2.34.1 From nobody Tue May 5 10:00:43 2026 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 1D675C433F5 for ; Wed, 25 May 2022 13:18:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244373AbiEYNR5 (ORCPT ); Wed, 25 May 2022 09:17:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34564 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244021AbiEYNRC (ORCPT ); Wed, 25 May 2022 09:17:02 -0400 Received: from mx0b-001ae601.pphosted.com (mx0b-001ae601.pphosted.com [67.231.152.168]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BFC00DFC9 for ; Wed, 25 May 2022 06:17:00 -0700 (PDT) Received: from pps.filterd (m0077474.ppops.net [127.0.0.1]) by mx0b-001ae601.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 24P7Sjcq031231; Wed, 25 May 2022 08:16:48 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=nj95x6g/zXz5WSnriv9Mczq2+wtNnkHGVv5u2T8w09U=; b=VUGBBkJzq2m7OEL74Dt1/+IjbtTWRSwhkPZOJ4b3Gjfp+71gq4+lx3Rebifi6EBqJ7fi RjV1haBIPwHvv6rM/VZOdw7aEQ0U1DjZJLvBlIvOakLfP0Y3TQ1JDWYnIIiZMVoJWGAy l7FEgUUtrb5vQ6gDkHcnHrgQaaIlsvsurZHnaXWmVeUiuxcbduHvC6oUZuBO+QLnjXfM Cayid4MALgB3oxr/FnOhJ+jUaztSEPA+iJlprRuFQctPgHTAi/PFfeH7FvFRXCEjNO4J pkgC//Gt0GI9ySNQzfxwSu16y4c/kv6BIos74az5FXe3jauvATykn+rjGKGMfdBTR7Vn CQ== Received: from ediex02.ad.cirrus.com ([84.19.233.68]) by mx0b-001ae601.pphosted.com (PPS) with ESMTPS id 3g93u20web-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT); Wed, 25 May 2022 08:16:47 -0500 Received: from EDIEX01.ad.cirrus.com (198.61.84.80) by EDIEX02.ad.cirrus.com (198.61.84.81) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.24; Wed, 25 May 2022 14:16:44 +0100 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by EDIEX01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server id 15.1.2375.24 via Frontend Transport; Wed, 25 May 2022 14:16:44 +0100 Received: from vitaly-Legion-7-16ACHg6.ad.cirrus.com (unknown [198.90.238.233]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id A383C468; Wed, 25 May 2022 13:16:44 +0000 (UTC) From: Vitaly Rodionov To: Jaroslav Kysela , Takashi Iwai , Mark Brown CC: , , , Stefan Binding Subject: [PATCH v4 13/17] ALSA: hda: cs35l41: Read Speaker Calibration data from UEFI variables Date: Wed, 25 May 2022 14:16:34 +0100 Message-ID: <20220525131638.5512-14-vitalyr@opensource.cirrus.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220525131638.5512-1-vitalyr@opensource.cirrus.com> References: <20220525131638.5512-1-vitalyr@opensource.cirrus.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-ORIG-GUID: p64f2TUdz9T-P8EcBwySXmIvCrlLigAh X-Proofpoint-GUID: p64f2TUdz9T-P8EcBwySXmIvCrlLigAh X-Proofpoint-Spam-Reason: safe Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" From: Stefan Binding Speaker Calibration data, specific to an individual speaker is stored inside UEFI variables during calibration, and can be used by the DSP. Signed-off-by: Stefan Binding Signed-off-by: Vitaly Rodionov --- Changes since v2: - Fixed building without CONFIG_EFI Changes since v3: - Apply all 4 calibration parameters after fw download =20 sound/pci/hda/cs35l41_hda.c | 63 +++++++++++++++++++++++++++++++++++++ sound/pci/hda/cs35l41_hda.h | 15 +++++++++ 2 files changed, 78 insertions(+) diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c index 9c622104bf01..b4087d548646 100644 --- a/sound/pci/hda/cs35l41_hda.c +++ b/sound/pci/hda/cs35l41_hda.c @@ -26,6 +26,12 @@ #define HALO_STATE_DSP_CTL_NAME "HALO_STATE" #define HALO_STATE_DSP_CTL_TYPE 5 #define HALO_STATE_DSP_CTL_ALG 262308 +#define CAL_R_DSP_CTL_NAME "CAL_R" +#define CAL_STATUS_DSP_CTL_NAME "CAL_STATUS" +#define CAL_CHECKSUM_DSP_CTL_NAME "CAL_CHECKSUM" +#define CAL_AMBIENT_DSP_CTL_NAME "CAL_AMBIENT" +#define CAL_DSP_CTL_TYPE 5 +#define CAL_DSP_CTL_ALG 205 =20 static const struct reg_sequence cs35l41_hda_config[] =3D { { CS35L41_PLL_CLK_CTRL, 0x00000430 }, // 3072000Hz, BCLK Input, PLL_REFC= LK_EN =3D 1 @@ -282,6 +288,96 @@ static int cs35l41_request_firmware_files(struct cs35l= 41_hda *cs35l41, return ret; } =20 +#if IS_ENABLED(CONFIG_EFI) +static int cs35l41_apply_calibration(struct cs35l41_hda *cs35l41, unsigned= int ambient, + unsigned int r0, unsigned int status, unsigned int checksum) +{ + int ret; + + ret =3D hda_cs_dsp_write_ctl(&cs35l41->cs_dsp, CAL_AMBIENT_DSP_CTL_NAME, = CAL_DSP_CTL_TYPE, + CAL_DSP_CTL_ALG, &ambient, 4); + if (ret) { + dev_err(cs35l41->dev, "Cannot Write Control: %s - %d\n", CAL_AMBIENT_DSP= _CTL_NAME, + ret); + return ret; + } + ret =3D hda_cs_dsp_write_ctl(&cs35l41->cs_dsp, CAL_R_DSP_CTL_NAME, CAL_DS= P_CTL_TYPE, + CAL_DSP_CTL_ALG, &r0, 4); + if (ret) { + dev_err(cs35l41->dev, "Cannot Write Control: %s - %d\n", CAL_R_DSP_CTL_N= AME, ret); + return ret; + } + ret =3D hda_cs_dsp_write_ctl(&cs35l41->cs_dsp, CAL_STATUS_DSP_CTL_NAME, C= AL_DSP_CTL_TYPE, + CAL_DSP_CTL_ALG, &status, 4); + if (ret) { + dev_err(cs35l41->dev, "Cannot Write Control: %s - %d\n", CAL_STATUS_DSP_= CTL_NAME, + ret); + return ret; + } + ret =3D hda_cs_dsp_write_ctl(&cs35l41->cs_dsp, CAL_CHECKSUM_DSP_CTL_NAME,= CAL_DSP_CTL_TYPE, + CAL_DSP_CTL_ALG, &checksum, 4); + if (ret) { + dev_err(cs35l41->dev, "Cannot Write Control: %s - %d\n", CAL_CHECKSUM_DS= P_CTL_NAME, + ret); + return ret; + } + + return 0; +} + +static int cs35l41_save_calibration(struct cs35l41_hda *cs35l41) +{ + static efi_guid_t efi_guid =3D EFI_GUID(0x02f9af02, 0x7734, 0x4233, 0xb4,= 0x3d, 0x93, 0xfe, + 0x5a, 0xa3, 0x5d, 0xb3); + static efi_char16_t efi_name[] =3D L"CirrusSmartAmpCalibrationData"; + const struct cs35l41_amp_efi_data *efi_data; + const struct cs35l41_amp_cal_data *cl; + unsigned long data_size =3D 0; + efi_status_t status; + int ret =3D 0; + u8 *data =3D NULL; + u32 attr; + + /* Get real size of UEFI variable */ + status =3D efi.get_variable(efi_name, &efi_guid, &attr, &data_size, data); + if (status =3D=3D EFI_BUFFER_TOO_SMALL) { + ret =3D -ENODEV; + /* Allocate data buffer of data_size bytes */ + data =3D vmalloc(data_size); + if (!data) + return -ENOMEM; + /* Get variable contents into buffer */ + status =3D efi.get_variable(efi_name, &efi_guid, &attr, &data_size, data= ); + if (status =3D=3D EFI_SUCCESS) { + efi_data =3D (struct cs35l41_amp_efi_data *)data; + dev_dbg(cs35l41->dev, "Calibration: Size=3D%d, Amp Count=3D%d\n", + efi_data->size, efi_data->count); + if (efi_data->count > cs35l41->index) { + cl =3D &efi_data->data[cs35l41->index]; + dev_dbg(cs35l41->dev, + "Calibration: Ambient=3D%02x, Status=3D%02x, R0=3D%d\n", + cl->calAmbient, cl->calStatus, cl->calR); + + /* Calibration can only be applied whilst the DSP is not running */ + ret =3D cs35l41_apply_calibration(cs35l41, + cpu_to_be32(cl->calAmbient), + cpu_to_be32(cl->calR), + cpu_to_be32(cl->calStatus), + cpu_to_be32(cl->calR + 1)); + } + } + vfree(data); + } + return ret; +} +#else +static int cs35l41_save_calibration(struct cs35l41_hda *cs35l41) +{ + dev_warn(cs35l41->dev, "Calibration not supported without EFI support.\n"= ); + return 0; +} +#endif + static int cs35l41_init_dsp(struct cs35l41_hda *cs35l41) { const struct firmware *coeff_firmware =3D NULL; @@ -314,7 +410,12 @@ static int cs35l41_init_dsp(struct cs35l41_hda *cs35l4= 1) =20 ret =3D cs_dsp_power_up(dsp, wmfw_firmware, wmfw_filename, coeff_firmware= , coeff_filename, FW_NAME); + if (ret) + goto err_release; + + ret =3D cs35l41_save_calibration(cs35l41); =20 +err_release: if (wmfw_firmware) release_firmware(wmfw_firmware); if (coeff_firmware) diff --git a/sound/pci/hda/cs35l41_hda.h b/sound/pci/hda/cs35l41_hda.h index 54521a013e78..3cf9871fbed2 100644 --- a/sound/pci/hda/cs35l41_hda.h +++ b/sound/pci/hda/cs35l41_hda.h @@ -10,6 +10,7 @@ #ifndef __CS35L41_HDA_H__ #define __CS35L41_HDA_H__ =20 +#include #include #include #include @@ -18,6 +19,20 @@ #include #include =20 +struct cs35l41_amp_cal_data { + u32 calTarget[2]; + u32 calTime[2]; + s8 calAmbient; + u8 calStatus; + u16 calR; +} __packed; + +struct cs35l41_amp_efi_data { + u32 size; + u32 count; + struct cs35l41_amp_cal_data data[]; +} __packed; + enum cs35l41_hda_spk_pos { CS35l41_LEFT, CS35l41_RIGHT, --=20 2.34.1 From nobody Tue May 5 10:00:43 2026 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 2150FC433EF for ; Wed, 25 May 2022 13:17:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244254AbiEYNRV (ORCPT ); Wed, 25 May 2022 09:17:21 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34366 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236925AbiEYNQ7 (ORCPT ); Wed, 25 May 2022 09:16:59 -0400 Received: from mx0b-001ae601.pphosted.com (mx0b-001ae601.pphosted.com [67.231.152.168]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B0E90E002 for ; Wed, 25 May 2022 06:16:56 -0700 (PDT) Received: from pps.filterd (m0077474.ppops.net [127.0.0.1]) by mx0b-001ae601.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 24P7Sjcr031231; Wed, 25 May 2022 08:16:49 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=i1KBfpmWq85BkKRplVpoCF4sGjk4Y2NdJNchd02pEJA=; b=nt9dKgx/6wwZD/E6yEuUvionppErET5wgK0O3dDPSIKMW34I4kjP8HuTJbYGeKuQrIR3 NuFyL/n9gixEb+TLFWOZMXTc4WqDuhD4unQ/Spw5GeBgFHy4X/ZKZ05CRXfvVwMv1nZg WVmPiQTZOBaGDMbelhxhtQfTsnoXjuhYgk5/NXTCPRi7z9I9MSar95qFW8gWGClTLl29 2qA2zzRA3nTNqOBoPmomdmk1TEi7uH1dL1Q3m8hZid0Un/uOF0AF6hNsFlHn7FzTf8GU TuQKr7QGJBbGzV8NqoFE42hXtoke3ugLLUjGDZwVc3iR7UHk81zpsYvxGWyqtNnyvj7I og== Received: from ediex02.ad.cirrus.com ([84.19.233.68]) by mx0b-001ae601.pphosted.com (PPS) with ESMTPS id 3g93u20web-2 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT); Wed, 25 May 2022 08:16:48 -0500 Received: from EDIEX01.ad.cirrus.com (198.61.84.80) by EDIEX02.ad.cirrus.com (198.61.84.81) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.24; Wed, 25 May 2022 14:16:45 +0100 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by EDIEX01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server id 15.1.2375.24 via Frontend Transport; Wed, 25 May 2022 14:16:45 +0100 Received: from vitaly-Legion-7-16ACHg6.ad.cirrus.com (unknown [198.90.238.233]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id 13BE046C; Wed, 25 May 2022 13:16:45 +0000 (UTC) From: Vitaly Rodionov To: Jaroslav Kysela , Takashi Iwai , Mark Brown CC: , , , Stefan Binding Subject: [PATCH v4 14/17] ALSA: hda: hda_cs_dsp_ctl: Add fw id strings Date: Wed, 25 May 2022 14:16:35 +0100 Message-ID: <20220525131638.5512-15-vitalyr@opensource.cirrus.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220525131638.5512-1-vitalyr@opensource.cirrus.com> References: <20220525131638.5512-1-vitalyr@opensource.cirrus.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-ORIG-GUID: 4svRktvXs-WOUTjLWTNw70CPr-v42idL X-Proofpoint-GUID: 4svRktvXs-WOUTjLWTNw70CPr-v42idL X-Proofpoint-Spam-Reason: safe Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" From: Stefan Binding This will be used to define the firmware names. Signed-off-by: Stefan Binding Signed-off-by: Vitaly Rodionov --- Changes since v2: - No change =20 sound/pci/hda/hda_cs_dsp_ctl.c | 8 ++++++++ sound/pci/hda/hda_cs_dsp_ctl.h | 2 ++ 2 files changed, 10 insertions(+) diff --git a/sound/pci/hda/hda_cs_dsp_ctl.c b/sound/pci/hda/hda_cs_dsp_ctl.c index 3b837d000a00..4cf5f7c2e267 100644 --- a/sound/pci/hda/hda_cs_dsp_ctl.c +++ b/sound/pci/hda/hda_cs_dsp_ctl.c @@ -30,6 +30,14 @@ static const char * const hda_cs_dsp_fw_text[HDA_CS_DSP_= NUM_FW] =3D { [HDA_CS_DSP_FW_MISC] =3D "Misc", }; =20 +const char * const hda_cs_dsp_fw_ids[HDA_CS_DSP_NUM_FW] =3D { + [HDA_CS_DSP_FW_SPK_PROT] =3D "spk-prot", + [HDA_CS_DSP_FW_SPK_CALI] =3D "spk-cali", + [HDA_CS_DSP_FW_SPK_DIAG] =3D "spk-diag", + [HDA_CS_DSP_FW_MISC] =3D "misc", +}; +EXPORT_SYMBOL_NS_GPL(hda_cs_dsp_fw_ids, SND_HDA_CS_DSP_CONTROLS); + static inline struct hda_cs_dsp_coeff_ctl *bytes_ext_to_ctl(struct soc_byt= es_ext *ext) { return container_of(ext, struct hda_cs_dsp_coeff_ctl, bytes_ext); diff --git a/sound/pci/hda/hda_cs_dsp_ctl.h b/sound/pci/hda/hda_cs_dsp_ctl.h index 65b9c5c68957..265d8024eec9 100644 --- a/sound/pci/hda/hda_cs_dsp_ctl.h +++ b/sound/pci/hda/hda_cs_dsp_ctl.h @@ -27,6 +27,8 @@ struct hda_cs_dsp_ctl_info { const char *amp_name; }; =20 +extern const char * const hda_cs_dsp_fw_ids[HDA_CS_DSP_NUM_FW]; + int hda_cs_dsp_control_add(struct cs_dsp_coeff_ctl *cs_ctl, struct hda_cs_= dsp_ctl_info *info); void hda_cs_dsp_control_remove(struct cs_dsp_coeff_ctl *cs_ctl); int hda_cs_dsp_remove_kcontrol(struct snd_card *card, const char *name); --=20 2.34.1 From nobody Tue May 5 10:00:43 2026 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 EE8E2C433EF for ; Wed, 25 May 2022 13:18:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237987AbiEYNSW (ORCPT ); Wed, 25 May 2022 09:18:22 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36934 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244399AbiEYNRl (ORCPT ); Wed, 25 May 2022 09:17:41 -0400 Received: from mx0b-001ae601.pphosted.com (mx0b-001ae601.pphosted.com [67.231.152.168]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C248DEE1E for ; Wed, 25 May 2022 06:17:33 -0700 (PDT) Received: from pps.filterd (m0077474.ppops.net [127.0.0.1]) by mx0b-001ae601.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 24P7Sjcs031231; Wed, 25 May 2022 08:16:50 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=YY7pX14arfYdyxLm/NOk5hebMgT/zTyDYFlP9QJ69vY=; b=Mr0i9UjYBTjYf5WV2cQKKwNbxmM/9vREtbuRjIF3Ul/A34v8JIAnZ1RIxSgJ0J4FYQEl OaFxhbMSC45YPtNJVSvj0ZfEleUDzImJwrFHHtc3YwzG6fsf16Tmk/2SbZEPbuq5irjO HQgZlLp6cWe066EbCNYAzoOktwp77XdBQ/JKeIuItI576sDJFoPDe7SXHeUcMle82oS9 fxvPQAl0veeKusEsn22uiSRgDZib8rvhX5INZwxF47qQtTnI4CRxO8b+3AcFpoEfp+XY SLzj6zrbiqV0UBtrGoYM0FrAVayr0xa+mY5TAmbT3V06zWNW9896PS6cY9esZ6XHcn0F yg== Received: from ediex02.ad.cirrus.com ([84.19.233.68]) by mx0b-001ae601.pphosted.com (PPS) with ESMTPS id 3g93u20web-3 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT); Wed, 25 May 2022 08:16:49 -0500 Received: from EDIEX01.ad.cirrus.com (198.61.84.80) by EDIEX02.ad.cirrus.com (198.61.84.81) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.24; Wed, 25 May 2022 14:16:45 +0100 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by EDIEX01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server id 15.1.2375.24 via Frontend Transport; Wed, 25 May 2022 14:16:45 +0100 Received: from vitaly-Legion-7-16ACHg6.ad.cirrus.com (unknown [198.90.238.233]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id 7050911D3; Wed, 25 May 2022 13:16:45 +0000 (UTC) From: Vitaly Rodionov To: Jaroslav Kysela , Takashi Iwai , Mark Brown CC: , , , Stefan Binding Subject: [PATCH v4 15/17] ALSA: hda: cs35l41: Add defaulted values into dsp bypass config sequence Date: Wed, 25 May 2022 14:16:36 +0100 Message-ID: <20220525131638.5512-16-vitalyr@opensource.cirrus.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220525131638.5512-1-vitalyr@opensource.cirrus.com> References: <20220525131638.5512-1-vitalyr@opensource.cirrus.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-ORIG-GUID: 0sQS18HOJ853hdbjbYSxHWIODfGjbU6y X-Proofpoint-GUID: 0sQS18HOJ853hdbjbYSxHWIODfGjbU6y X-Proofpoint-Spam-Reason: safe Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" From: Stefan Binding The config sequences for running with and without firmware and DSP are different. The original behavior assumed that we would only run without DSP only in the case where firmware load failed. This meant the non-firmware sequence was written with the assumtion that various registers would be set to their default value. However, to support the ability to unload the firmware, the non-firmware register sequence must be updated to update all required registers, including values that would be defaulted, in case the firmware sequence, which could have already run, has changed their value. Signed-off-by: Stefan Binding Signed-off-by: Vitaly Rodionov --- Changes since v2: - No change =20 sound/pci/hda/cs35l41_hda.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c index b4087d548646..8de956e6850c 100644 --- a/sound/pci/hda/cs35l41_hda.c +++ b/sound/pci/hda/cs35l41_hda.c @@ -35,11 +35,24 @@ =20 static const struct reg_sequence cs35l41_hda_config[] =3D { { CS35L41_PLL_CLK_CTRL, 0x00000430 }, // 3072000Hz, BCLK Input, PLL_REFC= LK_EN =3D 1 + { CS35L41_DSP_CLK_CTRL, 0x00000003 }, // DSP CLK EN { CS35L41_GLOBAL_CLK_CTRL, 0x00000003 }, // GLOBAL_FS =3D 48 kHz { CS35L41_SP_ENABLES, 0x00010000 }, // ASP_RX1_EN =3D 1 { CS35L41_SP_RATE_CTRL, 0x00000021 }, // ASP_BCLK_FREQ =3D 3.072 MHz { CS35L41_SP_FORMAT, 0x20200200 }, // 32 bits RX/TX slots, I2S, clk cons= umer + { CS35L41_SP_HIZ_CTRL, 0x00000002 }, // Hi-Z unused + { CS35L41_SP_TX_WL, 0x00000018 }, // 24 cycles/slot + { CS35L41_SP_RX_WL, 0x00000018 }, // 24 cycles/slot { CS35L41_DAC_PCM1_SRC, 0x00000008 }, // DACPCM1_SRC =3D ASPRX1 + { CS35L41_ASP_TX1_SRC, 0x00000018 }, // ASPTX1 SRC =3D VMON + { CS35L41_ASP_TX2_SRC, 0x00000019 }, // ASPTX2 SRC =3D IMON + { CS35L41_ASP_TX3_SRC, 0x00000032 }, // ASPTX3 SRC =3D ERRVOL + { CS35L41_ASP_TX4_SRC, 0x00000033 }, // ASPTX4 SRC =3D CLASSH_TGT + { CS35L41_DSP1_RX1_SRC, 0x00000008 }, // DSP1RX1 SRC =3D ASPRX1 + { CS35L41_DSP1_RX2_SRC, 0x00000009 }, // DSP1RX2 SRC =3D ASPRX2 + { CS35L41_DSP1_RX3_SRC, 0x00000018 }, // DSP1RX3 SRC =3D VMON + { CS35L41_DSP1_RX4_SRC, 0x00000019 }, // DSP1RX4 SRC =3D IMON + { CS35L41_DSP1_RX5_SRC, 0x00000020 }, // DSP1RX5 SRC =3D ERRVOL { CS35L41_AMP_DIG_VOL_CTRL, 0x00000000 }, // AMP_VOL_PCM 0.0 dB { CS35L41_AMP_GAIN_CTRL, 0x00000084 }, // AMP_GAIN_PCM 4.5 dB }; --=20 2.34.1 From nobody Tue May 5 10:00:43 2026 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 7D211C433EF for ; Wed, 25 May 2022 13:18:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230146AbiEYNS0 (ORCPT ); Wed, 25 May 2022 09:18:26 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37718 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244403AbiEYNRl (ORCPT ); Wed, 25 May 2022 09:17:41 -0400 Received: from mx0b-001ae601.pphosted.com (mx0b-001ae601.pphosted.com [67.231.152.168]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 96B4B10FF5 for ; Wed, 25 May 2022 06:17:34 -0700 (PDT) Received: from pps.filterd (m0077474.ppops.net [127.0.0.1]) by mx0b-001ae601.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 24PCRmjL022096; Wed, 25 May 2022 08:16:49 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=SdH8ia3qSCQdREnp9xrzfWcqJ+zxm8KWhqDEaNAZy1Q=; b=DCe12RJ321uJnjX+r1SXut4gaTq6BAjUPASSBjSzvW1kualAjvBwek7UlqX7EjZ2t62M Qa3bd5Ivv3nWJzQ2HudbUkcWI81nPrMpLQZmd7qgLMjw7kQqSd4v9q1kHX7l6n/mxh1S v0T9bRxt2OsOYQEN4T5wm/6spZbGE3ZQFP3WrMy7W2cyn6MqfMoNvVNZYgNpLTElCpYS WduEvl+TFWDEtaXJAh4wWBvgd5dajx62ZeZ9JyV1pZOTmlj5aUTRwjpTcb3xP0hxmXXj MySd2+0xBmZvZHMuZDXqF0GzmsP/xes5Xaj/+F2vlvQt3DfwMAvDfxceYUPUlluYs6EE kw== Received: from ediex01.ad.cirrus.com ([84.19.233.68]) by mx0b-001ae601.pphosted.com (PPS) with ESMTPS id 3g93u20we6-11 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT); Wed, 25 May 2022 08:16:49 -0500 Received: from EDIEX01.ad.cirrus.com (198.61.84.80) by EDIEX01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.24; Wed, 25 May 2022 14:16:46 +0100 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by EDIEX01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server id 15.1.2375.24 via Frontend Transport; Wed, 25 May 2022 14:16:46 +0100 Received: from vitaly-Legion-7-16ACHg6.ad.cirrus.com (unknown [198.90.238.233]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id C8CAA46C; Wed, 25 May 2022 13:16:45 +0000 (UTC) From: Vitaly Rodionov To: Jaroslav Kysela , Takashi Iwai , Mark Brown CC: , , , Stefan Binding Subject: [PATCH v4 16/17] ALSA: hda: cs35l41: Support Firmware switching and reloading Date: Wed, 25 May 2022 14:16:37 +0100 Message-ID: <20220525131638.5512-17-vitalyr@opensource.cirrus.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220525131638.5512-1-vitalyr@opensource.cirrus.com> References: <20220525131638.5512-1-vitalyr@opensource.cirrus.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-ORIG-GUID: Gmp0fGDJqaZLM2LaG02kyCCsldnNpJ9s X-Proofpoint-GUID: Gmp0fGDJqaZLM2LaG02kyCCsldnNpJ9s X-Proofpoint-Spam-Reason: safe Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" From: Stefan Binding This is required to support CS35L41 calibration. By default, speaker protection firmware will be loaded, if available. However, different firmware is required to run the calibration sequence, so it is necessary to add support to be able to unload, switch and reload firmware. This patch adds 2 ALSA Controls for each amp: "DSP1 Firmware Load" "DSP1 Firmware Type" "DSP1 Firmware Load" can be used to unload and load the firmware. "DSP1 Firmware Type" can be used to switch the target firmware to be loaded by "DSP1 Firmware Load" Signed-off-by: Stefan Binding Signed-off-by: Vitaly Rodionov --- Changes since v2: - No change =20 sound/pci/hda/cs35l41_hda.c | 163 ++++++++++++++++++++++++++++++++++-- sound/pci/hda/cs35l41_hda.h | 5 ++ 2 files changed, 161 insertions(+), 7 deletions(-) diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c index 8de956e6850c..4a164b7ebab1 100644 --- a/sound/pci/hda/cs35l41_hda.c +++ b/sound/pci/hda/cs35l41_hda.c @@ -92,7 +92,7 @@ static int cs35l41_control_add(struct cs_dsp_coeff_ctl *c= s_ctl) struct hda_cs_dsp_ctl_info info; =20 info.amp_name =3D cs35l41->amp_name; - info.fw_type =3D HDA_CS_DSP_FW_SPK_PROT; + info.fw_type =3D cs35l41->firmware_type; info.card =3D cs35l41->codec->card; =20 return hda_cs_dsp_control_add(cs_ctl, &info); @@ -114,20 +114,24 @@ static int cs35l41_request_firmware_file(struct cs35l= 41_hda *cs35l41, =20 if (spkid > -1 && ssid && amp_name) *filename =3D kasprintf(GFP_KERNEL, "%s%s-%s-%s-%s-spkid%d-%s.%s", dir, = CS35L41_PART, - dsp_name, "spk-prot", ssid, spkid, amp_name, filetype); + dsp_name, hda_cs_dsp_fw_ids[cs35l41->firmware_type], + ssid, spkid, amp_name, filetype); else if (spkid > -1 && ssid) *filename =3D kasprintf(GFP_KERNEL, "%s%s-%s-%s-%s-spkid%d.%s", dir, CS3= 5L41_PART, - dsp_name, "spk-prot", ssid, spkid, filetype); + dsp_name, hda_cs_dsp_fw_ids[cs35l41->firmware_type], + ssid, spkid, filetype); else if (ssid && amp_name) *filename =3D kasprintf(GFP_KERNEL, "%s%s-%s-%s-%s-%s.%s", dir, CS35L41_= PART, - dsp_name, "spk-prot", ssid, amp_name, - filetype); + dsp_name, hda_cs_dsp_fw_ids[cs35l41->firmware_type], + ssid, amp_name, filetype); else if (ssid) *filename =3D kasprintf(GFP_KERNEL, "%s%s-%s-%s-%s.%s", dir, CS35L41_PAR= T, - dsp_name, "spk-prot", ssid, filetype); + dsp_name, hda_cs_dsp_fw_ids[cs35l41->firmware_type], + ssid, filetype); else *filename =3D kasprintf(GFP_KERNEL, "%s%s-%s-%s.%s", dir, CS35L41_PART, - dsp_name, "spk-prot", filetype); + dsp_name, hda_cs_dsp_fw_ids[cs35l41->firmware_type], + filetype); =20 if (*filename =3D=3D NULL) return -ENOMEM; @@ -471,8 +475,11 @@ static void cs35l41_hda_playback_hook(struct device *d= ev, int action) struct regmap *reg =3D cs35l41->regmap; int ret =3D 0; =20 + mutex_lock(&cs35l41->fw_mutex); + switch (action) { case HDA_GEN_PCM_ACT_OPEN: + cs35l41->playback_started =3D true; if (cs35l41->firmware_running) { regmap_multi_reg_write(reg, cs35l41_hda_config_dsp, ARRAY_SIZE(cs35l41_hda_config_dsp)); @@ -510,12 +517,15 @@ static void cs35l41_hda_playback_hook(struct device *= dev, int action) 0 << CS35L41_VMON_EN_SHIFT | 0 << CS35L41_IMON_EN_SHIFT); } cs35l41_irq_release(cs35l41); + cs35l41->playback_started =3D false; break; default: dev_warn(cs35l41->dev, "Playback action not supported: %d\n", action); break; } =20 + mutex_unlock(&cs35l41->fw_mutex); + if (ret) dev_err(cs35l41->dev, "Regmap access fail: %d\n", ret); } @@ -654,6 +664,136 @@ static int cs35l41_smart_amp(struct cs35l41_hda *cs35= l41) return ret; } =20 +static void cs35l41_load_firmware(struct cs35l41_hda *cs35l41, bool load) +{ + pm_runtime_get_sync(cs35l41->dev); + + if (cs35l41->firmware_running && !load) { + dev_dbg(cs35l41->dev, "Unloading Firmware\n"); + cs35l41_remove_dsp(cs35l41); + } else if (!cs35l41->firmware_running && load) { + dev_dbg(cs35l41->dev, "Loading Firmware\n"); + cs35l41_smart_amp(cs35l41); + } else { + dev_dbg(cs35l41->dev, "Unable to Load firmware.\n"); + } + + pm_runtime_mark_last_busy(cs35l41->dev); + pm_runtime_put_autosuspend(cs35l41->dev); +} + +static int cs35l41_fw_load_ctl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct cs35l41_hda *cs35l41 =3D snd_kcontrol_chip(kcontrol); + + ucontrol->value.integer.value[0] =3D cs35l41->request_fw_load; + return 0; +} + +static int cs35l41_fw_load_ctl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct cs35l41_hda *cs35l41 =3D snd_kcontrol_chip(kcontrol); + int ret =3D 0; + + mutex_lock(&cs35l41->fw_mutex); + if (cs35l41->request_fw_load !=3D ucontrol->value.integer.value[0]) { + if (cs35l41->playback_started) { + dev_err(cs35l41->dev, "Cannot Load/Unload firmware during Playback\n"); + ret =3D -EBUSY; + } else { + cs35l41->request_fw_load =3D ucontrol->value.integer.value[0]; + cs35l41_load_firmware(cs35l41, ucontrol->value.integer.value[0]); + } + } + + mutex_unlock(&cs35l41->fw_mutex); + + return ret; +} + +static int cs35l41_fw_type_ctl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct cs35l41_hda *cs35l41 =3D snd_kcontrol_chip(kcontrol); + + ucontrol->value.enumerated.item[0] =3D cs35l41->firmware_type; + + return 0; +} + +static int cs35l41_fw_type_ctl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct cs35l41_hda *cs35l41 =3D snd_kcontrol_chip(kcontrol); + + if (ucontrol->value.enumerated.item[0] < HDA_CS_DSP_NUM_FW) { + cs35l41->firmware_type =3D ucontrol->value.enumerated.item[0]; + return 0; + } + + return -EINVAL; +} + +static int cs35l41_fw_type_ctl_info(struct snd_kcontrol *kcontrol, struct = snd_ctl_elem_info *uinfo) +{ + return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(hda_cs_dsp_fw_ids), hda_cs_= dsp_fw_ids); +} + +static int cs35l41_create_controls(struct cs35l41_hda *cs35l41) +{ + struct snd_kcontrol_new fw_type_ctl =3D { + .iface =3D SNDRV_CTL_ELEM_IFACE_MIXER, + .info =3D cs35l41_fw_type_ctl_info, + .get =3D cs35l41_fw_type_ctl_get, + .put =3D cs35l41_fw_type_ctl_put, + }; + struct snd_kcontrol_new fw_load_ctl =3D { + .iface =3D SNDRV_CTL_ELEM_IFACE_MIXER, + .info =3D snd_ctl_boolean_mono_info, + .get =3D cs35l41_fw_load_ctl_get, + .put =3D cs35l41_fw_load_ctl_put, + }; + int ret =3D 0; + + fw_load_ctl.name =3D kasprintf(GFP_KERNEL, "%s DSP1 Firmware Load", cs35l= 41->amp_name); + if (!fw_load_ctl.name) { + ret =3D -ENOMEM; + goto err; + } + + fw_type_ctl.name =3D kasprintf(GFP_KERNEL, "%s DSP1 Firmware Type", cs35l= 41->amp_name); + if (!fw_type_ctl.name) { + ret =3D -ENOMEM; + goto err; + } + + if (snd_ctl_add(cs35l41->codec->card, snd_ctl_new1(&fw_type_ctl, cs35l41)= )) { + ret =3D -ENODEV; + dev_err(cs35l41->dev, "Failed to add KControl: %s\n", fw_type_ctl.name); + goto err; + } + + dev_dbg(cs35l41->dev, "Added Control %s\n", fw_type_ctl.name); + + if (snd_ctl_add(cs35l41->codec->card, snd_ctl_new1(&fw_load_ctl, cs35l41)= )) { + ret =3D -ENODEV; + dev_err(cs35l41->dev, "Failed to add KControl: %s, removing all controls= \n", + fw_load_ctl.name); + hda_cs_dsp_remove_kcontrol(cs35l41->codec->card, fw_type_ctl.name); + goto err; + } + + dev_dbg(cs35l41->dev, "Added Control %s\n", fw_load_ctl.name); + +err: + kfree(fw_load_ctl.name); + kfree(fw_type_ctl.name); + + return ret; +} + static int cs35l41_hda_bind(struct device *dev, struct device *master, voi= d *master_data) { struct cs35l41_hda *cs35l41 =3D dev_get_drvdata(dev); @@ -675,8 +815,15 @@ static int cs35l41_hda_bind(struct device *dev, struct= device *master, void *mas cs35l41->codec =3D comps->codec; strscpy(comps->name, dev_name(dev), sizeof(comps->name)); =20 + cs35l41->firmware_type =3D HDA_CS_DSP_FW_SPK_PROT; + + cs35l41->request_fw_load =3D true; + mutex_lock(&cs35l41->fw_mutex); if (cs35l41_smart_amp(cs35l41) < 0) dev_warn(cs35l41->dev, "Cannot Run Firmware, reverting to dsp bypass...\= n"); + mutex_unlock(&cs35l41->fw_mutex); + + cs35l41_create_controls(cs35l41); =20 comps->playback_hook =3D cs35l41_hda_playback_hook; comps->suspend_hook =3D cs35l41_hda_suspend_hook; @@ -1196,6 +1343,8 @@ int cs35l41_hda_probe(struct device *dev, const char = *device_name, int id, int i if (ret) goto err; =20 + mutex_init(&cs35l41->fw_mutex); + pm_runtime_set_autosuspend_delay(cs35l41->dev, 3000); pm_runtime_use_autosuspend(cs35l41->dev); pm_runtime_mark_last_busy(cs35l41->dev); diff --git a/sound/pci/hda/cs35l41_hda.h b/sound/pci/hda/cs35l41_hda.h index 3cf9871fbed2..19f0585d12db 100644 --- a/sound/pci/hda/cs35l41_hda.h +++ b/sound/pci/hda/cs35l41_hda.h @@ -58,10 +58,15 @@ struct cs35l41_hda { unsigned volatile long irq_errors; const char *amp_name; const char *acpi_subsystem_id; + int firmware_type; int speaker_id; + struct mutex fw_mutex; + struct regmap_irq_chip_data *irq_data; bool firmware_running; + bool request_fw_load; bool halo_initialized; + bool playback_started; struct cs_dsp cs_dsp; }; =20 --=20 2.34.1 From nobody Tue May 5 10:00:43 2026 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 6017BC433EF for ; Wed, 25 May 2022 13:18:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240527AbiEYNSq (ORCPT ); Wed, 25 May 2022 09:18:46 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36938 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244400AbiEYNRl (ORCPT ); Wed, 25 May 2022 09:17:41 -0400 Received: from mx0b-001ae601.pphosted.com (mx0b-001ae601.pphosted.com [67.231.152.168]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C42AFE0B2 for ; Wed, 25 May 2022 06:17:32 -0700 (PDT) Received: from pps.filterd (m0077474.ppops.net [127.0.0.1]) by mx0b-001ae601.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 24P7Sjct031231; Wed, 25 May 2022 08:16:51 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=zfY69P7pEy7Ti9ODGavDNoDFkIDCMhTvPP8FmRf6wG0=; b=nCNgBgeU+d6D0Pq+laIYFZ2Flx6o9Cd3ToBHRzwIirNtzvgEIxkPZSAaxiRFKD/9upob 7gxPj1bZou9mfKpgJ1tN0qimx2glN5pQbZ1M+0hR0Yyl7UmayFgYWNZrVztshj0pgkw+ Ldzu1M4wHa3RMpV0VcmZM27EGrpCc41HgtCSyol0xKQGEYLTB+OaVKGJR1PO7CGPv0pb ot+wkwqbzxOzsYHa5v5dYylBLOR0FxNMdN1ef3ezys+TQERjvafB2fB/oM3kXwu2/C/b 1iHr+0Mfnlbl35TEre/5Hdur0ftFlfluh2xDs2EO8HF9f2RxD5MmcNKRjTTrHqTzZ2YD Ow== Received: from ediex02.ad.cirrus.com ([84.19.233.68]) by mx0b-001ae601.pphosted.com (PPS) with ESMTPS id 3g93u20web-4 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT); Wed, 25 May 2022 08:16:50 -0500 Received: from EDIEX01.ad.cirrus.com (198.61.84.80) by EDIEX02.ad.cirrus.com (198.61.84.81) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.24; Wed, 25 May 2022 14:16:46 +0100 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by EDIEX01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server id 15.1.2375.24 via Frontend Transport; Wed, 25 May 2022 14:16:46 +0100 Received: from vitaly-Legion-7-16ACHg6.ad.cirrus.com (unknown [198.90.238.233]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id 332DD468; Wed, 25 May 2022 13:16:46 +0000 (UTC) From: Vitaly Rodionov To: Jaroslav Kysela , Takashi Iwai , Mark Brown CC: , , , Stefan Binding Subject: [PATCH v4 17/17] ALSA: hda: cs35l41: Add module parameter to control firmware load Date: Wed, 25 May 2022 14:16:38 +0100 Message-ID: <20220525131638.5512-18-vitalyr@opensource.cirrus.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220525131638.5512-1-vitalyr@opensource.cirrus.com> References: <20220525131638.5512-1-vitalyr@opensource.cirrus.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-ORIG-GUID: OOguHXURhwrnlex9HUVOBe_8ajCWKS5Q X-Proofpoint-GUID: OOguHXURhwrnlex9HUVOBe_8ajCWKS5Q X-Proofpoint-Spam-Reason: safe Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" From: Stefan Binding By default, the driver will automatically load DSP firmware for the amps, if available. Adding this option allows the autoload to be optional, which allows for different configurations. Signed-off-by: Stefan Binding Signed-off-by: Vitaly Rodionov --- Changes since v2: - Added module paramter to control firmware loading =20 sound/pci/hda/cs35l41_hda.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c index 4a164b7ebab1..c836323a8aaf 100644 --- a/sound/pci/hda/cs35l41_hda.c +++ b/sound/pci/hda/cs35l41_hda.c @@ -33,6 +33,11 @@ #define CAL_DSP_CTL_TYPE 5 #define CAL_DSP_CTL_ALG 205 =20 +static bool firmware_autostart =3D 1; +module_param(firmware_autostart, bool, 0444); +MODULE_PARM_DESC(firmware_autostart, "Allow automatic firmware download on= boot" + "(0=3DDisable, 1=3DEnable) (default=3D1); "); + static const struct reg_sequence cs35l41_hda_config[] =3D { { CS35L41_PLL_CLK_CTRL, 0x00000430 }, // 3072000Hz, BCLK Input, PLL_REFC= LK_EN =3D 1 { CS35L41_DSP_CLK_CTRL, 0x00000003 }, // DSP CLK EN @@ -817,11 +822,16 @@ static int cs35l41_hda_bind(struct device *dev, struc= t device *master, void *mas =20 cs35l41->firmware_type =3D HDA_CS_DSP_FW_SPK_PROT; =20 - cs35l41->request_fw_load =3D true; - mutex_lock(&cs35l41->fw_mutex); - if (cs35l41_smart_amp(cs35l41) < 0) - dev_warn(cs35l41->dev, "Cannot Run Firmware, reverting to dsp bypass...\= n"); - mutex_unlock(&cs35l41->fw_mutex); + if (firmware_autostart) { + dev_dbg(cs35l41->dev, "Firmware Autostart.\n"); + cs35l41->request_fw_load =3D true; + mutex_lock(&cs35l41->fw_mutex); + if (cs35l41_smart_amp(cs35l41) < 0) + dev_warn(cs35l41->dev, "Cannot Run Firmware, reverting to dsp bypass...= \n"); + mutex_unlock(&cs35l41->fw_mutex); + } else { + dev_dbg(cs35l41->dev, "Firmware Autostart is disabled.\n"); + } =20 cs35l41_create_controls(cs35l41); =20 --=20 2.34.1