From: Vitaly Rodionov <vitalyr@opensource.cirrus.com>
To: Jaroslav Kysela <perex@perex.cz>, Takashi Iwai <tiwai@suse.com>,
Mark Brown <broonie@kernel.org>
Cc: <alsa-devel@alsa-project.org>, <patches@opensource.cirrus.com>,
<linux-kernel@vger.kernel.org>,
Stefan Binding <sbinding@opensource.cirrus.com>
Subject: [PATCH v5 10/14] ALSA: hda: cs35l41: Read Speaker Calibration data from UEFI variables
Date: Mon, 20 Jun 2022 21:54:28 +0100 [thread overview]
Message-ID: <20220620205432.3809-11-vitalyr@opensource.cirrus.com> (raw)
In-Reply-To: <20220620205432.3809-1-vitalyr@opensource.cirrus.com>
From: Stefan Binding <sbinding@opensource.cirrus.com>
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 <sbinding@opensource.cirrus.com>
Signed-off-by: Vitaly Rodionov <vitalyr@opensource.cirrus.com>
---
sound/pci/hda/cs35l41_hda.c | 101 ++++++++++++++++++++++++++++++++++++
sound/pci/hda/cs35l41_hda.h | 15 ++++++
2 files changed, 116 insertions(+)
diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c
index b502806fbfa1..ef3dfda7b03e 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
static const struct reg_sequence cs35l41_hda_config[] = {
{ CS35L41_PLL_CLK_CTRL, 0x00000430 }, // 3072000Hz, BCLK Input, PLL_REFCLK_EN = 1
@@ -282,6 +288,96 @@ static int cs35l41_request_firmware_files(struct cs35l41_hda *cs35l41,
return ret;
}
+#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 = 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 = hda_cs_dsp_write_ctl(&cs35l41->cs_dsp, CAL_R_DSP_CTL_NAME, CAL_DSP_CTL_TYPE,
+ CAL_DSP_CTL_ALG, &r0, 4);
+ if (ret) {
+ dev_err(cs35l41->dev, "Cannot Write Control: %s - %d\n", CAL_R_DSP_CTL_NAME, ret);
+ return ret;
+ }
+ ret = hda_cs_dsp_write_ctl(&cs35l41->cs_dsp, CAL_STATUS_DSP_CTL_NAME, CAL_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 = 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_DSP_CTL_NAME,
+ ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int cs35l41_save_calibration(struct cs35l41_hda *cs35l41)
+{
+ static 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"CirrusSmartAmpCalibrationData";
+ const struct cs35l41_amp_efi_data *efi_data;
+ const struct cs35l41_amp_cal_data *cl;
+ unsigned long data_size = 0;
+ efi_status_t status;
+ int ret = 0;
+ u8 *data = NULL;
+ u32 attr;
+
+ /* Get real size of UEFI variable */
+ status = efi.get_variable(efi_name, &efi_guid, &attr, &data_size, data);
+ if (status == EFI_BUFFER_TOO_SMALL) {
+ ret = -ENODEV;
+ /* Allocate data buffer of data_size bytes */
+ data = vmalloc(data_size);
+ if (!data)
+ return -ENOMEM;
+ /* Get variable contents into buffer */
+ status = efi.get_variable(efi_name, &efi_guid, &attr, &data_size, data);
+ if (status == EFI_SUCCESS) {
+ efi_data = (struct cs35l41_amp_efi_data *)data;
+ dev_dbg(cs35l41->dev, "Calibration: Size=%d, Amp Count=%d\n",
+ efi_data->size, efi_data->count);
+ if (efi_data->count > cs35l41->index) {
+ cl = &efi_data->data[cs35l41->index];
+ dev_dbg(cs35l41->dev,
+ "Calibration: Ambient=%02x, Status=%02x, R0=%d\n",
+ cl->calAmbient, cl->calStatus, cl->calR);
+
+ /* Calibration can only be applied whilst the DSP is not running */
+ ret = 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 = NULL;
@@ -314,7 +410,12 @@ static int cs35l41_init_dsp(struct cs35l41_hda *cs35l41)
ret = cs_dsp_power_up(dsp, wmfw_firmware, wmfw_filename, coeff_firmware, coeff_filename,
FW_NAME);
+ if (ret)
+ goto err_release;
+
+ ret = cs35l41_save_calibration(cs35l41);
+err_release:
release_firmware(wmfw_firmware);
release_firmware(coeff_firmware);
kfree(wmfw_filename);
diff --git a/sound/pci/hda/cs35l41_hda.h b/sound/pci/hda/cs35l41_hda.h
index 439c4b705328..59a9461d0444 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__
+#include <linux/efi.h>
#include <linux/regulator/consumer.h>
#include <linux/gpio/consumer.h>
#include <linux/device.h>
@@ -18,6 +19,20 @@
#include <linux/firmware/cirrus/cs_dsp.h>
#include <linux/firmware/cirrus/wmfw.h>
+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,
--
2.34.1
next prev parent reply other threads:[~2022-06-20 20:56 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-06-20 20:54 [PATCH v5 00/14] ALSA: hda: cirrus: Add initial DSP support and firmware loading Vitaly Rodionov
2022-06-20 20:54 ` [PATCH v5 01/14] ALSA: hda: hda_cs_dsp_ctl: Add Library to support CS_DSP ALSA controls Vitaly Rodionov
2022-06-20 20:54 ` [PATCH v5 02/14] ALSA: hda: hda_cs_dsp_ctl: Add apis to write the controls directly Vitaly Rodionov
2022-06-20 20:54 ` [PATCH v5 03/14] ALSA: hda: cs35l41: Save codec object inside component struct Vitaly Rodionov
2022-06-20 20:54 ` [PATCH v5 04/14] ALSA: hda: cs35l41: Add initial DSP support and firmware loading Vitaly Rodionov
2022-06-21 0:52 ` kernel test robot
2022-06-20 20:54 ` [PATCH v5 05/14] ALSA: hda: cs35l41: Save Subsystem ID inside CS35L41 Driver Vitaly Rodionov
2022-06-20 20:54 ` [PATCH v5 06/14] ALSA: hda: cs35l41: Support reading subsystem id from ACPI Vitaly Rodionov
2022-06-20 20:54 ` [PATCH v5 07/14] ALSA: hda: cs35l41: Support multiple load paths for firmware Vitaly Rodionov
2022-06-20 20:54 ` [PATCH v5 08/14] ALSA: hda: cs35l41: Support Speaker ID for laptops Vitaly Rodionov
2022-06-20 20:54 ` [PATCH v5 09/14] ALSA: hda: cs35l41: Support Hibernation during Suspend Vitaly Rodionov
2022-06-20 20:54 ` Vitaly Rodionov [this message]
2022-06-20 20:54 ` [PATCH v5 11/14] ALSA: hda: hda_cs_dsp_ctl: Add fw id strings Vitaly Rodionov
2022-06-20 20:54 ` [PATCH v5 12/14] ALSA: hda: cs35l41: Add defaulted values into dsp bypass config sequence Vitaly Rodionov
2022-06-20 20:54 ` [PATCH v5 13/14] ALSA: hda: cs35l41: Support Firmware switching and reloading Vitaly Rodionov
2022-06-20 20:54 ` [PATCH v5 14/14] ALSA: hda: cs35l41: Add module parameter to control firmware load Vitaly Rodionov
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=20220620205432.3809-11-vitalyr@opensource.cirrus.com \
--to=vitalyr@opensource.cirrus.com \
--cc=alsa-devel@alsa-project.org \
--cc=broonie@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=patches@opensource.cirrus.com \
--cc=perex@perex.cz \
--cc=sbinding@opensource.cirrus.com \
--cc=tiwai@suse.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®