From: Takashi Iwai <tiwai@suse.de>
To: Shenghao Ding <13916275206@139.com>
Cc: broonie@kernel.org, devicetree@vger.kernel.org,
krzysztof.kozlowski+dt@linaro.org, robh+dt@kernel.org,
lgirdwood@gmail.com, perex@perex.cz,
pierre-louis.bossart@linux.intel.com, kevin-lu@ti.com,
shenghao-ding@ti.com, alsa-devel@alsa-project.org,
linux-kernel@vger.kernel.org, x1077012@ti.com, peeyush@ti.com,
navada@ti.com, gentuser@gmail.com, Ryan_Chu@wistron.com,
Sam_Wu@wistron.com
Subject: Re: [PATCH v3 4/5] ALSA: hda/tas2781: Add tas2781 HDA driver
Date: Sun, 21 May 2023 10:02:44 +0200 [thread overview]
Message-ID: <871qjayuvv.wl-tiwai@suse.de> (raw)
In-Reply-To: <20230519080227.20224-1-13916275206@139.com>
On Fri, 19 May 2023 10:02:27 +0200,
Shenghao Ding wrote:
>
> Create tas2781 HDA driver.
>
> Signed-off-by: Shenghao Ding <13916275206@139.com>
First of all, please give more description. It's far more changes
than written in four words.
Also, don't forget to put me on Cc. I almost overlooked this one.
> diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
> index 172ffc2c332b..f5b912f90018 100644
> --- a/sound/pci/hda/patch_realtek.c
> +++ b/sound/pci/hda/patch_realtek.c
> +static int comp_match_tas2781_dev_name(struct device *dev, void *data)
> +{
> + struct scodec_dev_name *p = data;
> + const char *d = dev_name(dev);
> + int n = strlen(p->bus);
> + char tmp[32];
> +
> + /* check the bus name */
> + if (strncmp(d, p->bus, n))
> + return 0;
> + /* skip the bus number */
> + if (isdigit(d[n]))
> + n++;
> + /* the rest must be exact matching */
> + snprintf(tmp, sizeof(tmp), "-%s:00", p->hid);
> +
> + return !strcmp(d + n, tmp);
> +}
You don't use the index here...
> +static void tas2781_generic_fixup(struct hda_codec *cdc, int action,
> + const char *bus, const char *hid, int count)
> +{
> + struct device *dev = hda_codec_dev(cdc);
> + struct alc_spec *spec = cdc->spec;
> + struct scodec_dev_name *rec;
> + int ret, i;
> +
> + switch (action) {
> + case HDA_FIXUP_ACT_PRE_PROBE:
> + for (i = 0; i < count; i++) {
> + rec = devm_kmalloc(dev, sizeof(*rec), GFP_KERNEL);
> + if (!rec)
> + return;
> + rec->bus = bus;
> + rec->hid = hid;
> + rec->index = i;
... and assigning here. It means that the multiple instances would
silently break. It's better to catch here instead.
> +static void tas2781_fixup_i2c(struct hda_codec *cdc,
> + const struct hda_fixup *fix, int action)
> +{
> + tas2781_generic_fixup(cdc, action, "i2c", "TIAS2781", 1);
> +}
> +
> /* for alc295_fixup_hp_top_speakers */
> #include "hp_x360_helper.c"
>
> @@ -7201,6 +7260,8 @@ enum {
> ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN,
> ALC295_FIXUP_DELL_INSPIRON_TOP_SPEAKERS,
> ALC236_FIXUP_DELL_DUAL_CODECS,
> + ALC287_FIXUP_TAS2781_I2C_2,
> + ALC287_FIXUP_TAS2781_I2C_4
> };
>
> /* A special fixup for Lenovo C940 and Yoga Duet 7;
> @@ -9189,6 +9250,18 @@ static const struct hda_fixup alc269_fixups[] = {
> .chained = true,
> .chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
> },
> + [ALC287_FIXUP_TAS2781_I2C_2] = {
> + .type = HDA_FIXUP_FUNC,
> + .v.func = tas2781_fixup_i2c,
> + .chained = true,
> + .chain_id = ALC269_FIXUP_THINKPAD_ACPI,
> + },
> + [ALC287_FIXUP_TAS2781_I2C_4] = {
> + .type = HDA_FIXUP_FUNC,
> + .v.func = tas2781_fixup_i2c,
> + .chained = true,
> + .chain_id = ALC269_FIXUP_THINKPAD_ACPI,
> + },
What's a difference between *_2 and *_4?
> --- /dev/null
> +++ b/sound/pci/hda/tas2781_hda_i2c.c
> +static int tas2781_acpi_get_i2c_resource(struct acpi_resource
> + *ares, void *data)
> +{
> + struct tasdevice_priv *tas_priv = (struct tasdevice_priv *)data;
> + struct acpi_resource_i2c_serialbus *sb;
> +
> + if (i2c_acpi_get_i2c_resource(ares, &sb)) {
> + if (sb->slave_address != TAS2781_GLOBAL_ADDR) {
> + tas_priv->tasdevice[tas_priv->ndev].dev_addr =
> + (unsigned int) sb->slave_address;
> + tas_priv->ndev++;
> + } else
> + tas_priv->glb_addr.dev_addr = TAS2781_GLOBAL_ADDR;
> +
Did you run checkpatch.pl? I thought it would complain.
> +static void tas2781_hda_playback_hook(struct device *dev, int action)
> +{
> + struct tasdevice_priv *tas_priv = dev_get_drvdata(dev);
> + int ret = 0;
> +
> + dev_info(tas_priv->dev, "%s: action = %d\n", __func__, action);
Don't use dev_info(). It'd be dev_dbg() at most.
> + switch (action) {
> + case HDA_GEN_PCM_ACT_OPEN:
> + pm_runtime_get_sync(dev);
> + mutex_lock(&tas_priv->codec_lock);
> + tas_priv->cur_conf = 0;
> + tas_priv->rcabin.profile_cfg_id = 1;
> + tasdevice_tuning_switch(tas_priv, 0);
> + mutex_unlock(&tas_priv->codec_lock);
> + break;
> + case HDA_GEN_PCM_ACT_CLOSE:
> + mutex_lock(&tas_priv->codec_lock);
> + tasdevice_tuning_switch(tas_priv, 1);
> + mutex_unlock(&tas_priv->codec_lock);
> +
> + pm_runtime_mark_last_busy(dev);
> + pm_runtime_put_autosuspend(dev);
> + break;
> + default:
> + dev_warn(tas_priv->dev, "Playback action not supported: %d\n",
> + action);
> + break;
> + }
> +
> + if (ret)
> + dev_err(tas_priv->dev, "Regmap access fail: %d\n", ret);
The ret is never used.
> +static int tasdevice_set_profile_id(struct snd_kcontrol *kcontrol,
> + struct snd_ctl_elem_value *ucontrol)
> +{
> + struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
> +
> + tas_priv->rcabin.profile_cfg_id = ucontrol->value.integer.value[0];
> +
> + return 1;
It should return 0 if the value is unchanged.
(Ditto for other *_put functions)
> +static int tasdevice_create_control(struct tasdevice_priv *tas_priv)
> +{
> + char prof_ctrl_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
> + struct hda_codec *codec = tas_priv->codec;
> + struct snd_kcontrol_new prof_ctrl = {
> + .name = prof_ctrl_name,
> + .iface = SNDRV_CTL_ELEM_IFACE_CARD,
> + .info = tasdevice_info_profile,
> + .get = tasdevice_get_profile_id,
> + .put = tasdevice_set_profile_id,
> + };
> + int ret;
> +
> + /* Create a mixer item for selecting the active profile */
> + scnprintf(prof_ctrl_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,
> + "tasdev-profile-id");
A too bad name as a control element. Use a more readable one.
> +static int tasdevice_info_programs(struct snd_kcontrol *kcontrol,
> + struct snd_ctl_elem_info *uinfo)
> +{
> + struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
> + struct tasdevice_fw *tas_fw = tas_priv->fmw;
> +
> + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
> + uinfo->count = 1;
> + uinfo->value.integer.min = 0;
> + uinfo->value.integer.max = (int)tas_fw->nr_programs;
The cast is superfluous.
> +static int tasdevice_info_configurations(
> + struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
> +{
> + struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
> + struct tasdevice_fw *tas_fw = tas_priv->fmw;
> +
> + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
> + uinfo->count = 1;
> + uinfo->value.integer.min = 0;
> + uinfo->value.integer.max = (int)tas_fw->nr_configurations - 1;
Ditto.
> +/**
> + * tas2781_digital_getvol - get the volum control
> + * @kcontrol: control pointer
> + * @ucontrol: User data
> + * Customer Kcontrol for tas2781 is primarily for regmap booking, paging
> + * depends on internal regmap mechanism.
> + * tas2781 contains book and page two-level register map, especially
> + * book switching will set the register BXXP00R7F, after switching to the
> + * correct book, then leverage the mechanism for paging to access the
> + * register.
> + */
You shouldn't use the kerneldoc marker "/**" for local static
functions. It's not a part of API.
> +static int tasdevice_dsp_create_ctrls(struct tasdevice_priv
> + *tas_priv)
> +{
> + char prog_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
> + char conf_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
> + struct hda_codec *codec = tas_priv->codec;
> + struct snd_kcontrol_new prog_ctl = {
> + .name = prog_name,
> + .iface = SNDRV_CTL_ELEM_IFACE_CARD,
> + .info = tasdevice_info_programs,
> + .get = tasdevice_program_get,
> + .put = tasdevice_program_put,
> + };
> + struct snd_kcontrol_new conf_ctl = {
> + .name = conf_name,
> + .iface = SNDRV_CTL_ELEM_IFACE_CARD,
> + .info = tasdevice_info_configurations,
> + .get = tasdevice_config_get,
> + .put = tasdevice_config_put,
> + };
> + int ret;
> +
> + scnprintf(prog_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "tasdev-prog-id");
> + scnprintf(conf_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "tasdev-conf-id");
Please use better names.
> +static void tas2781_apply_calib(struct tasdevice_priv *tas_priv)
> +{
> + unsigned char page_array[CALIB_MAX] = {0x17, 0x18, 0x18, 0x0d, 0x18};
> + unsigned char rgno_array[CALIB_MAX] = {0x74, 0x0c, 0x14, 0x3c, 0x7c};
Should be static const arrays.
> +static int tas2781_save_calibration(struct tasdevice_priv *tas_priv)
> +{
> + efi_guid_t efi_guid = EFI_GUID(0x02f9af02, 0x7734, 0x4233, 0xb4, 0x3d,
> + 0x93, 0xfe, 0x5a, 0xa3, 0x5d, 0xb3);
> + static efi_char16_t efi_name[] = L"CALI_DATA";
> + struct hda_codec *codec = tas_priv->codec;
> + unsigned int subid = codec->core.subsystem_id & 0xFFFF;
> + struct tm *tm = &tas_priv->tm;
> + unsigned int attr, crc;
> + unsigned int *tmp_val;
> + efi_status_t status;
> + int ret = 0;
> +
> + //Lenovo devices
> + if ((subid == 0x387d) || (subid == 0x387e) || (subid == 0x3881)
> + || (subid == 0x3884) || (subid == 0x3886) || (subid == 0x38a7)
> + || (subid == 0x38a8) || (subid == 0x38ba) || (subid == 0x38bb)
> + || (subid == 0x38be) || (subid == 0x38bf) || (subid == 0x38c3)
> + || (subid == 0x38cb) || (subid == 0x38cd))
> + efi_guid = EFI_GUID(0x1f52d2a1, 0xbb3a, 0x457d, 0xbc, 0x09,
> + 0x43, 0xa3, 0xf4, 0x31, 0x0a, 0x92);
Here can be a problem: the device ID is embedded here, and it's hard
to find out. You'd better to make it some quirk flag that is set in a
common place and check the flag here instead of checking ID at each
place.
> + crc = crc32(~0, tas_priv->cali_data.data, 84) ^ ~0;
> + dev_info(tas_priv->dev, "cali crc 0x%08x PK tmp_val 0x%08x\n",
> + crc, tmp_val[21]);
If it's a dev_info() output, make it more understandable.
> + if (crc == tmp_val[21]) {
> + time64_to_tm(tmp_val[20], 0, tm);
> + dev_info(tas_priv->dev, "%4ld-%2d-%2d, %2d:%2d:%2d\n",
> + tm->tm_year, tm->tm_mon, tm->tm_mday,
> + tm->tm_hour, tm->tm_min, tm->tm_sec);
Ditto. Or, make them a debug print instead.
> +static int tas2781_runtime_suspend(struct device *dev)
> +{
> + struct tasdevice_priv *tas_priv = dev_get_drvdata(dev);
> + int i, ret = 0;
> +
> + dev_info(tas_priv->dev, "Runtime Suspend\n");
It must be a debug print. Otherwise it'll be too annoying.
Also, as a minor nitpicking, there are many functions that set ret = 0
at the beginning but never used. The unconditional 0 initialization
is often a bad sign indicating that the author doesn't think fully of
the code flow. Please revisit those.
thanks,
Takashi
next prev parent reply other threads:[~2023-05-21 8:04 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-05-19 8:02 [PATCH v3 4/5] ALSA: hda/tas2781: Add tas2781 HDA driver Shenghao Ding
2023-05-21 8:02 ` Takashi Iwai [this message]
2023-05-23 11:22 ` [EXTERNAL] " Ding, Shenghao
2023-05-23 11:42 ` Takashi Iwai
2023-05-25 12:53 ` Ding, Shenghao
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=871qjayuvv.wl-tiwai@suse.de \
--to=tiwai@suse.de \
--cc=13916275206@139.com \
--cc=Ryan_Chu@wistron.com \
--cc=Sam_Wu@wistron.com \
--cc=alsa-devel@alsa-project.org \
--cc=broonie@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=gentuser@gmail.com \
--cc=kevin-lu@ti.com \
--cc=krzysztof.kozlowski+dt@linaro.org \
--cc=lgirdwood@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=navada@ti.com \
--cc=peeyush@ti.com \
--cc=perex@perex.cz \
--cc=pierre-louis.bossart@linux.intel.com \
--cc=robh+dt@kernel.org \
--cc=shenghao-ding@ti.com \
--cc=x1077012@ti.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.