lkml.org 
[lkml]   [2022]   [Jun]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v7 10/14] ALSA: hda: cs35l41: Read Speaker Calibration data from UEFI variables
    Date
    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
    \
     
     \ /
      Last update: 2022-06-22 09:48    [W:3.489 / U:0.064 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site