diff options
Diffstat (limited to 'sound/pci/hda/cs35l56_hda.c')
-rw-r--r-- | sound/pci/hda/cs35l56_hda.c | 69 |
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); |