summaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/cs35l56_hda.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/hda/cs35l56_hda.c')
-rw-r--r--sound/pci/hda/cs35l56_hda.c69
1 files changed, 50 insertions, 19 deletions
diff --git a/sound/pci/hda/cs35l56_hda.c b/sound/pci/hda/cs35l56_hda.c
index de58a953b4..6b77c38a0e 100644
--- a/sound/pci/hda/cs35l56_hda.c
+++ b/sound/pci/hda/cs35l56_hda.c
@@ -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"
@@ -458,13 +459,15 @@ static void cs35l56_hda_request_firmware_files(struct cs35l56_hda *cs35l56,
if (preloaded_fw_ver) {
snprintf(base_name, sizeof(base_name),
- "cirrus/cs35l56-%02x%s-%06x-dsp1-misc",
+ "cirrus/cs35l%02x-%02x%s-%06x-dsp1-misc",
+ cs35l56->base.type,
cs35l56->base.rev,
cs35l56->base.secured ? "-s" : "",
preloaded_fw_ver & 0xffffff);
} else {
snprintf(base_name, sizeof(base_name),
- "cirrus/cs35l56-%02x%s-dsp1-misc",
+ "cirrus/cs35l%02x-%02x%s-dsp1-misc",
+ cs35l56->base.type,
cs35l56->base.rev,
cs35l56->base.secured ? "-s" : "");
}
@@ -547,6 +550,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 +637,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);
@@ -648,6 +663,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);
@@ -712,8 +732,6 @@ static void cs35l56_hda_unbind(struct device *dev, struct device *master, void *
if (cs35l56->base.fw_patched)
cs_dsp_power_down(&cs35l56->cs_dsp);
- cs_dsp_remove(&cs35l56->cs_dsp);
-
if (comps[cs35l56->index].dev == dev)
memset(&comps[cs35l56->index], 0, sizeof(*comps));
@@ -836,9 +854,10 @@ static int cs35l56_hda_system_resume(struct device *dev)
return 0;
}
-static int cs35l56_hda_read_acpi(struct cs35l56_hda *cs35l56, int id)
+static int cs35l56_hda_read_acpi(struct cs35l56_hda *cs35l56, int hid, int id)
{
u32 values[HDA_MAX_COMPONENTS];
+ char hid_string[8];
struct acpi_device *adev;
const char *property, *sub;
size_t nval;
@@ -849,7 +868,8 @@ static int cs35l56_hda_read_acpi(struct cs35l56_hda *cs35l56, int id)
* the serial-multi-instantiate driver, so lookup the node by HID
*/
if (!ACPI_COMPANION(cs35l56->base.dev)) {
- adev = acpi_dev_get_first_match_dev("CSC3556", NULL, -1);
+ snprintf(hid_string, sizeof(hid_string), "CSC%04X", hid);
+ adev = acpi_dev_get_first_match_dev(hid_string, NULL, -1);
if (!adev) {
dev_err(cs35l56->base.dev, "Failed to find an ACPI device for %s\n",
dev_name(cs35l56->base.dev));
@@ -937,14 +957,14 @@ err:
return ret;
}
-int cs35l56_hda_common_probe(struct cs35l56_hda *cs35l56, int id)
+int cs35l56_hda_common_probe(struct cs35l56_hda *cs35l56, int hid, int id)
{
int ret;
mutex_init(&cs35l56->base.irq_lock);
dev_set_drvdata(cs35l56->base.dev, cs35l56);
- ret = cs35l56_hda_read_acpi(cs35l56, id);
+ ret = cs35l56_hda_read_acpi(cs35l56, hid, id);
if (ret)
goto err;
@@ -955,6 +975,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;
@@ -994,20 +1016,24 @@ 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");
goto err;
}
- dev_dbg(cs35l56->base.dev, "DSP system name: '%s', amp name: '%s'\n",
- cs35l56->system_name, cs35l56->amp_name);
+ dev_info(cs35l56->base.dev, "DSP system name: '%s', amp name: '%s'\n",
+ cs35l56->system_name, cs35l56->amp_name);
regmap_multi_reg_write(cs35l56->base.regmap, cs35l56_hda_dai_config,
ARRAY_SIZE(cs35l56_hda_dai_config));
ret = cs35l56_force_sync_asp1_registers_from_cache(&cs35l56->base);
if (ret)
- goto err;
+ goto dsp_err;
/*
* By default only enable one ASP1TXn, where n=amplifier index,
@@ -1033,6 +1059,8 @@ int cs35l56_hda_common_probe(struct cs35l56_hda *cs35l56, int id)
pm_err:
pm_runtime_disable(cs35l56->base.dev);
+dsp_err:
+ cs_dsp_remove(&cs35l56->cs_dsp);
err:
gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0);
@@ -1044,11 +1072,13 @@ void cs35l56_hda_remove(struct device *dev)
{
struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev);
+ component_del(cs35l56->base.dev, &cs35l56_hda_comp_ops);
+
pm_runtime_dont_use_autosuspend(cs35l56->base.dev);
pm_runtime_get_sync(cs35l56->base.dev);
pm_runtime_disable(cs35l56->base.dev);
- component_del(cs35l56->base.dev, &cs35l56_hda_comp_ops);
+ cs_dsp_remove(&cs35l56->cs_dsp);
kfree(cs35l56->system_name);
pm_runtime_put_noidle(cs35l56->base.dev);
@@ -1068,10 +1098,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 <rf@opensource.cirrus.com>");
MODULE_AUTHOR("Simon Trimmer <simont@opensource.cirrus.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(FW_CS_DSP);