From nobody Sun Dec 28 17:32:00 2025 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 3E0AFC4167B for ; Thu, 7 Dec 2023 00:00:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1441914AbjLGAAY (ORCPT ); Wed, 6 Dec 2023 19:00:24 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53408 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1441854AbjLGAAC (ORCPT ); Wed, 6 Dec 2023 19:00:02 -0500 Received: from irl.hu (irl.hu [95.85.9.111]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1E01E137 for ; Wed, 6 Dec 2023 16:00:07 -0800 (PST) Received: from fedori.lan (51b690cd.dsl.pool.telekom.hu [::ffff:81.182.144.205]) (AUTH: CRAM-MD5 soyer@irl.hu, ) by irl.hu with ESMTPSA id 00000000000716F9.0000000065710B06.00119065; Thu, 07 Dec 2023 01:00:06 +0100 From: Gergo Koteles To: Shenghao Ding , Kevin Lu , Baojun Xu , Jaroslav Kysela , Takashi Iwai , Liam Girdwood , Mark Brown Cc: linux-kernel@vger.kernel.org, alsa-devel@alsa-project.org, Gergo Koteles Subject: [PATCH 09/16] ALSA: hda/tas2781: add TAS2563 support for 14ARB7 Date: Thu, 7 Dec 2023 00:59:50 +0100 Message-ID: <1efa4849a6c7fef0fafa000fe558a2633548bba0.1701906455.git.soyer@irl.hu> X-Mailer: git-send-email 2.43.0 In-Reply-To: References: Mime-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Mime-Autoconverted: from 8bit to 7bit by courier 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The INT8866 belongs to the Lenovo Yoga 7 Gen 7 AMD 14ARB7 laptop. It has two TAS2563 amplifier. Add the ACPI UID and calibration functions to handle them. Signed-off-by: Gergo Koteles --- include/sound/tas2781.h | 1 + sound/pci/hda/tas2781_hda_i2c.c | 87 +++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+) diff --git a/include/sound/tas2781.h b/include/sound/tas2781.h index 5f364e4d8995..afe9584daa65 100644 --- a/include/sound/tas2781.h +++ b/include/sound/tas2781.h @@ -22,6 +22,7 @@ #define TAS2781_DRV_VER 1 #define SMARTAMP_MODULE_NAME "tas2781" #define TAS2781_GLOBAL_ADDR 0x40 +#define TAS2563_GLOBAL_ADDR 0x48 #define TASDEVICE_RATES (SNDRV_PCM_RATE_44100 |\ SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 |\ SNDRV_PCM_RATE_88200) diff --git a/sound/pci/hda/tas2781_hda_i2c.c b/sound/pci/hda/tas2781_hda_i2= c.c index 7ebf5d7e4aac..f28383597ca8 100644 --- a/sound/pci/hda/tas2781_hda_i2c.c +++ b/sound/pci/hda/tas2781_hda_i2c.c @@ -65,6 +65,24 @@ enum calib_data { CALIB_MAX }; =20 +#define TAS2563_MAX_CHANNELS 4 + +#define TAS2563_CAL_POWER TASDEVICE_REG(0, 0x0d, 0x3c) +#define TAS2563_CAL_R0 TASDEVICE_REG(0, 0x0f, 0x34) +#define TAS2563_CAL_INVR0 TASDEVICE_REG(0, 0x0f, 0x40) +#define TAS2563_CAL_R0_LOW TASDEVICE_REG(0, 0x0f, 0x48) +#define TAS2563_CAL_TLIM TASDEVICE_REG(0, 0x10, 0x14) +#define TAS2563_CAL_N 5 +#define TAS2563_CAL_DATA_SIZE 4 +#define TAS2563_CAL_CH_SIZE 20 +#define TAS2563_CAL_ARRAY_SIZE 80 + +static unsigned int cal_regs[TAS2563_CAL_N] =3D { + TAS2563_CAL_POWER, TAS2563_CAL_R0, TAS2563_CAL_INVR0, + TAS2563_CAL_R0_LOW, TAS2563_CAL_TLIM, +}; + + static int tas2781_get_i2c_res(struct acpi_resource *ares, void *data) { struct tasdevice_priv *tas_priv =3D data; @@ -395,6 +413,68 @@ static const struct snd_kcontrol_new tas2781_dsp_conf_= ctrl =3D { .put =3D tasdevice_config_put, }; =20 +static void tas2563_apply_calibration(struct tasdevice_priv *tas_priv) +{ + unsigned int data; + int offset =3D 0; + int ret; + + for (int i =3D 0; i < tas_priv->ndev; i++) { + for (int j =3D 0; j < TAS2563_CAL_N; ++j) { + data =3D cpu_to_be32( + *(uint32_t *)&tas_priv->cali_data.data[offset]); + ret =3D tasdevice_dev_bulk_write(tas_priv, i, cal_regs[j], + (unsigned char *)&data, TAS2563_CAL_DATA_SIZE); + if (ret) + dev_err(tas_priv->dev, + "Error writing calib regs\n"); + offset +=3D TAS2563_CAL_DATA_SIZE; + } + } +} + +static int load_calibration_efi_2(struct tasdevice_priv *tas_priv) +{ + static efi_guid_t efi_guid =3D EFI_GUID(0x1f52d2a1, 0xbb3a, 0x457d, 0xbc, + 0x09, 0x43, 0xa3, 0xf4, 0x31, 0x0a, 0x92); + + static efi_char16_t *efi_vars[TAS2563_MAX_CHANNELS][TAS2563_CAL_N] =3D { + { L"Power_1", L"R0_1", L"InvR0_1", L"R0_Low_1", L"TLim_1" }, + { L"Power_2", L"R0_2", L"InvR0_2", L"R0_Low_2", L"TLim_2" }, + { L"Power_3", L"R0_3", L"InvR0_3", L"R0_Low_3", L"TLim_3" }, + { L"Power_4", L"R0_4", L"InvR0_4", L"R0_Low_4", L"TLim_4" }, + }; + + unsigned long max_size =3D TAS2563_CAL_DATA_SIZE; + unsigned int offset =3D 0; + efi_status_t status; + unsigned int attr; + + tas_priv->cali_data.data =3D devm_kzalloc(tas_priv->dev, + TAS2563_CAL_ARRAY_SIZE, GFP_KERNEL); + if (!tas_priv->cali_data.data) + return -ENOMEM; + + for (int i =3D 0; i < tas_priv->ndev; ++i) { + for (int j =3D 0; j < TAS2563_CAL_N; ++j) { + status =3D efi.get_variable(efi_vars[i][j], + &efi_guid, &attr, &max_size, + &tas_priv->cali_data.data[offset]); + if (status !=3D EFI_SUCCESS || + max_size !=3D TAS2563_CAL_DATA_SIZE) { + dev_warn(tas_priv->dev, + "Calibration data read failed %ld\n", status); + return -EINVAL; + } + offset +=3D TAS2563_CAL_DATA_SIZE; + } + } + + tas_priv->cali_data.total_sz =3D offset; + + return 0; +} + static void tas2781_apply_calibration(struct tasdevice_priv *tas_priv) { static const unsigned char page_array[CALIB_MAX] =3D { @@ -658,6 +738,12 @@ static int tas2781_hda_i2c_probe(struct i2c_client *cl= t) device_name =3D "TIAS2781"; tas_priv->load_calibration =3D load_calibration_efi_1; tas_priv->apply_calibration =3D tas2781_apply_calibration; + tas_priv->global_addr =3D TAS2781_GLOBAL_ADDR; + } else if (strstr(dev_name(&clt->dev), "INT8866")) { + device_name =3D "INT8866"; + tas_priv->load_calibration =3D load_calibration_efi_2; + tas_priv->apply_calibration =3D tas2563_apply_calibration; + tas_priv->global_addr =3D TAS2563_GLOBAL_ADDR; } else return -ENODEV; =20 @@ -808,6 +894,7 @@ static const struct i2c_device_id tas2781_hda_i2c_id[] = =3D { =20 static const struct acpi_device_id tas2781_acpi_hda_match[] =3D { {"TIAS2781", 0 }, + {"INT8866", 0 }, {} }; MODULE_DEVICE_TABLE(acpi, tas2781_acpi_hda_match); --=20 2.43.0