forked from thesofproject/linux
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ALSA: cs35l56: Apply calibration from EFI
Merge series from Richard Fitzgerald <[email protected]>: Factory calibration of the speakers stores the calibration information into an EFI variable. This set of patches adds support for applying speaker calibration data from that EFI variable. The HDA patch (thesofproject#5) depends on the ASoC patches #2 and #3
- Loading branch information
Showing
12 changed files
with
529 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
/* SPDX-License-Identifier: GPL-2.0-only */ | ||
/* | ||
* Copyright (C) 2024 Cirrus Logic, Inc. and | ||
* Cirrus Logic International Semiconductor Ltd. | ||
*/ | ||
|
||
#ifndef CS_AMP_LIB_H | ||
#define CS_AMP_LIB_H | ||
|
||
#include <linux/efi.h> | ||
#include <linux/types.h> | ||
|
||
struct cs_dsp; | ||
|
||
struct cirrus_amp_cal_data { | ||
u32 calTarget[2]; | ||
u32 calTime[2]; | ||
s8 calAmbient; | ||
u8 calStatus; | ||
u16 calR; | ||
} __packed; | ||
|
||
struct cirrus_amp_efi_data { | ||
u32 size; | ||
u32 count; | ||
struct cirrus_amp_cal_data data[]; | ||
} __packed; | ||
|
||
/** | ||
* struct cirrus_amp_cal_controls - definition of firmware calibration controls | ||
* @alg_id: ID of algorithm containing the controls. | ||
* @mem_region: DSP memory region containing the controls. | ||
* @ambient: Name of control for calAmbient value. | ||
* @calr: Name of control for calR value. | ||
* @status: Name of control for calStatus value. | ||
* @checksum: Name of control for checksum value. | ||
*/ | ||
struct cirrus_amp_cal_controls { | ||
unsigned int alg_id; | ||
int mem_region; | ||
const char *ambient; | ||
const char *calr; | ||
const char *status; | ||
const char *checksum; | ||
}; | ||
|
||
int cs_amp_write_cal_coeffs(struct cs_dsp *dsp, | ||
const struct cirrus_amp_cal_controls *controls, | ||
const struct cirrus_amp_cal_data *data); | ||
int cs_amp_get_efi_calibration_data(struct device *dev, u64 target_uid, int amp_index, | ||
struct cirrus_amp_cal_data *out_data); | ||
#endif /* CS_AMP_LIB_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,6 +14,7 @@ | |
#include <linux/regmap.h> | ||
#include <linux/slab.h> | ||
#include <sound/core.h> | ||
#include <sound/cs-amp-lib.h> | ||
#include <sound/hda_codec.h> | ||
#include <sound/tlv.h> | ||
#include "cirrus_scodec.h" | ||
|
@@ -547,6 +548,22 @@ static void cs35l56_hda_add_dsp_controls(struct cs35l56_hda *cs35l56) | |
hda_cs_dsp_add_controls(&cs35l56->cs_dsp, &info); | ||
} | ||
|
||
static void cs35l56_hda_apply_calibration(struct cs35l56_hda *cs35l56) | ||
{ | ||
int ret; | ||
|
||
if (!cs35l56->base.cal_data_valid || cs35l56->base.secured) | ||
return; | ||
|
||
ret = cs_amp_write_cal_coeffs(&cs35l56->cs_dsp, | ||
&cs35l56_calibration_controls, | ||
&cs35l56->base.cal_data); | ||
if (ret < 0) | ||
dev_warn(cs35l56->base.dev, "Failed to write calibration: %d\n", ret); | ||
else | ||
dev_info(cs35l56->base.dev, "Calibration applied\n"); | ||
} | ||
|
||
static int cs35l56_hda_fw_load(struct cs35l56_hda *cs35l56) | ||
{ | ||
const struct firmware *coeff_firmware = NULL; | ||
|
@@ -618,12 +635,8 @@ static int cs35l56_hda_fw_load(struct cs35l56_hda *cs35l56) | |
if (coeff_filename) | ||
dev_dbg(cs35l56->base.dev, "Loaded Coefficients: %s\n", coeff_filename); | ||
|
||
if (!firmware_missing) { | ||
ret = cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_AUDIO_REINIT); | ||
if (ret) | ||
goto err_powered_up; | ||
} else if (wmfw_firmware || coeff_firmware) { | ||
/* If we downloaded firmware, reset the device and wait for it to boot */ | ||
/* If we downloaded firmware, reset the device and wait for it to boot */ | ||
if (firmware_missing && (wmfw_firmware || coeff_firmware)) { | ||
cs35l56_system_reset(&cs35l56->base, false); | ||
regcache_mark_dirty(cs35l56->base.regmap); | ||
ret = cs35l56_wait_for_firmware_boot(&cs35l56->base); | ||
|
@@ -646,6 +659,11 @@ static int cs35l56_hda_fw_load(struct cs35l56_hda *cs35l56) | |
if (ret) | ||
dev_dbg(cs35l56->base.dev, "%s: cs_dsp_run ret %d\n", __func__, ret); | ||
|
||
cs35l56_hda_apply_calibration(cs35l56); | ||
ret = cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_AUDIO_REINIT); | ||
if (ret) | ||
cs_dsp_stop(&cs35l56->cs_dsp); | ||
|
||
err_powered_up: | ||
if (!cs35l56->base.fw_patched) | ||
cs_dsp_power_down(&cs35l56->cs_dsp); | ||
|
@@ -953,6 +971,8 @@ int cs35l56_hda_common_probe(struct cs35l56_hda *cs35l56, int id) | |
goto err; | ||
} | ||
|
||
cs35l56->base.cal_index = cs35l56->index; | ||
|
||
cs35l56_init_cs_dsp(&cs35l56->base, &cs35l56->cs_dsp); | ||
cs35l56->cs_dsp.client_ops = &cs35l56_hda_client_ops; | ||
|
||
|
@@ -990,6 +1010,10 @@ int cs35l56_hda_common_probe(struct cs35l56_hda *cs35l56, int id) | |
if (ret) | ||
goto err; | ||
|
||
ret = cs35l56_get_calibration(&cs35l56->base); | ||
if (ret) | ||
goto err; | ||
|
||
ret = cs_dsp_halo_init(&cs35l56->cs_dsp); | ||
if (ret) { | ||
dev_err_probe(cs35l56->base.dev, ret, "cs_dsp_halo_init failed\n"); | ||
|
@@ -1064,10 +1088,11 @@ const struct dev_pm_ops cs35l56_hda_pm_ops = { | |
EXPORT_SYMBOL_NS_GPL(cs35l56_hda_pm_ops, SND_HDA_SCODEC_CS35L56); | ||
|
||
MODULE_DESCRIPTION("CS35L56 HDA Driver"); | ||
MODULE_IMPORT_NS(FW_CS_DSP); | ||
MODULE_IMPORT_NS(SND_HDA_CIRRUS_SCODEC); | ||
MODULE_IMPORT_NS(SND_HDA_CS_DSP_CONTROLS); | ||
MODULE_IMPORT_NS(SND_SOC_CS35L56_SHARED); | ||
MODULE_IMPORT_NS(SND_SOC_CS_AMP_LIB); | ||
MODULE_AUTHOR("Richard Fitzgerald <[email protected]>"); | ||
MODULE_AUTHOR("Simon Trimmer <[email protected]>"); | ||
MODULE_LICENSE("GPL"); | ||
MODULE_IMPORT_NS(FW_CS_DSP); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.