diff options
| author | Takashi Iwai <tiwai@suse.de> | 2025-12-02 07:12:56 +0100 |
|---|---|---|
| committer | Takashi Iwai <tiwai@suse.de> | 2025-12-02 07:12:56 +0100 |
| commit | 9747b22a417d2a7c478678143863b9777de104e4 (patch) | |
| tree | 2690242ac1e95570c3e56a3106752af4cc2b5472 /sound/hda/codecs/side-codecs/cs35l56_hda.c | |
| parent | ef5e0a02d842b2c6dfcfd9b80feb185769b892ef (diff) | |
| parent | c5fae31f60a91dbe884ef2789fb3440bb4cddf05 (diff) | |
Merge tag 'asoc-v6.19' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus
ASoC: Updates for v6.19
This is a very large set of updates, as well as some more extensive
cleanup work from Morimto-san we've also added a generic SCDA class
driver for SoundWire devices enabling us to support many chips with
no custom code. There's also a batch of new drivers added for both
SoCs and CODECs.
- Added a SoundWire SCDA generic class driver, pulling in a little
regmap work to support it.
- A *lot* of cleaup and API improvement work from Morimoto-san.
- Lots of work on the existing Cirrus, Intel, Maxim and Qualcomm
drivers.
- Support for Allwinner A523, Mediatek MT8189, Qualcomm QCM2290,
QRB2210 and SM6115, SpacemiT K1, and TI TAS2568, TAS5802, TAS5806,
TAS5815, TAS5828 and TAS5830.
This also pulls in some gpiolib changes supporting shared GPIOs in the
core there so we can convert some of the ASoC drivers open coding
handling of that to the core functionality.
Diffstat (limited to 'sound/hda/codecs/side-codecs/cs35l56_hda.c')
| -rw-r--r-- | sound/hda/codecs/side-codecs/cs35l56_hda.c | 116 |
1 files changed, 110 insertions, 6 deletions
diff --git a/sound/hda/codecs/side-codecs/cs35l56_hda.c b/sound/hda/codecs/side-codecs/cs35l56_hda.c index 5bb1c4ebeaf3..f7ba92e11957 100644 --- a/sound/hda/codecs/side-codecs/cs35l56_hda.c +++ b/sound/hda/codecs/side-codecs/cs35l56_hda.c @@ -548,20 +548,24 @@ static void cs35l56_hda_release_firmware_files(const struct firmware *wmfw_firmw kfree(coeff_filename); } -static void cs35l56_hda_apply_calibration(struct cs35l56_hda *cs35l56) +static int cs35l56_hda_apply_calibration(struct cs35l56_hda *cs35l56) { int ret; if (!cs35l56->base.cal_data_valid || cs35l56->base.secured) - return; + return -EACCES; ret = cs_amp_write_cal_coeffs(&cs35l56->cs_dsp, &cs35l56_calibration_controls, &cs35l56->base.cal_data); - if (ret < 0) + if (ret < 0) { dev_warn(cs35l56->base.dev, "Failed to write calibration: %d\n", ret); - else - dev_info(cs35l56->base.dev, "Calibration applied\n"); + return ret; + } + + dev_info(cs35l56->base.dev, "Calibration applied\n"); + + return 0; } static void cs35l56_hda_fw_load(struct cs35l56_hda *cs35l56) @@ -669,7 +673,9 @@ static void cs35l56_hda_fw_load(struct cs35l56_hda *cs35l56) if (ret) dev_dbg(cs35l56->base.dev, "%s: cs_dsp_run ret %d\n", __func__, ret); + /* Don't need to check return code, it's not fatal if this fails */ cs35l56_hda_apply_calibration(cs35l56); + ret = cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_AUDIO_REINIT); if (ret) cs_dsp_stop(&cs35l56->cs_dsp); @@ -695,6 +701,100 @@ static void cs35l56_hda_dsp_work(struct work_struct *work) cs35l56_hda_fw_load(cs35l56); } +static ssize_t cs35l56_hda_debugfs_calibrate_write(struct file *file, + const char __user *from, + size_t count, loff_t *ppos) +{ + struct cs35l56_base *cs35l56_base = file->private_data; + ssize_t ret; + + ret = pm_runtime_resume_and_get(cs35l56_base->dev); + if (ret) + return ret; + + ret = cs35l56_calibrate_debugfs_write(cs35l56_base, from, count, ppos); + pm_runtime_autosuspend(cs35l56_base->dev); + + return ret; +} + +static ssize_t cs35l56_hda_debugfs_cal_temperature_write(struct file *file, + const char __user *from, + size_t count, loff_t *ppos) +{ + struct cs35l56_base *cs35l56_base = file->private_data; + ssize_t ret; + + ret = pm_runtime_resume_and_get(cs35l56_base->dev); + if (ret) + return ret; + + ret = cs35l56_cal_ambient_debugfs_write(cs35l56_base, from, count, ppos); + pm_runtime_autosuspend(cs35l56_base->dev); + + return ret; +} + +static ssize_t cs35l56_hda_debugfs_cal_data_read(struct file *file, + char __user *to, + size_t count, loff_t *ppos) +{ + struct cs35l56_base *cs35l56_base = file->private_data; + ssize_t ret; + + ret = pm_runtime_resume_and_get(cs35l56_base->dev); + if (ret) + return ret; + + ret = cs35l56_cal_data_debugfs_read(cs35l56_base, to, count, ppos); + pm_runtime_autosuspend(cs35l56_base->dev); + + return ret; +} + +static ssize_t cs35l56_hda_debugfs_cal_data_write(struct file *file, + const char __user *from, + size_t count, loff_t *ppos) +{ + struct cs35l56_base *cs35l56_base = file->private_data; + struct cs35l56_hda *cs35l56 = cs35l56_hda_from_base(cs35l56_base); + ssize_t ret; + + ret = cs35l56_cal_data_debugfs_write(cs35l56_base, from, count, ppos); + if (ret == -ENODATA) + return count; /* Ignore writes of empty cal blobs */ + + if (ret < 0) + return ret; + + ret = pm_runtime_resume_and_get(cs35l56_base->dev); + if (ret) + return ret; + + ret = cs35l56_hda_apply_calibration(cs35l56); + if (ret == 0) + cs35l56_mbox_send(cs35l56_base, CS35L56_MBOX_CMD_AUDIO_REINIT); + else + count = -EIO; + + pm_runtime_autosuspend(cs35l56_base->dev); + + return count; +} + +static const struct cs35l56_cal_debugfs_fops cs35l56_hda_cal_debugfs_fops = { + .calibrate = { + .write = cs35l56_hda_debugfs_calibrate_write, + }, + .cal_temperature = { + .write = cs35l56_hda_debugfs_cal_temperature_write, + }, + .cal_data = { + .read = cs35l56_hda_debugfs_cal_data_read, + .write = cs35l56_hda_debugfs_cal_data_write, + }, +}; + static int cs35l56_hda_bind(struct device *dev, struct device *master, void *master_data) { struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev); @@ -722,6 +822,9 @@ static int cs35l56_hda_bind(struct device *dev, struct device *master, void *mas cs_dsp_init_debugfs(&cs35l56->cs_dsp, cs35l56->debugfs_root); #endif + if (IS_ENABLED(CONFIG_SND_HDA_SCODEC_CS35L56_CAL_DEBUGFS)) + cs35l56_create_cal_debugfs(&cs35l56->base, &cs35l56_hda_cal_debugfs_fops); + dev_dbg(cs35l56->base.dev, "Bound\n"); return 0; @@ -735,6 +838,7 @@ static void cs35l56_hda_unbind(struct device *dev, struct device *master, void * cancel_work_sync(&cs35l56->dsp_work); + cs35l56_remove_cal_debugfs(&cs35l56->base); cs35l56_hda_remove_controls(cs35l56); #if IS_ENABLED(CONFIG_SND_DEBUG) @@ -1050,7 +1154,7 @@ int cs35l56_hda_common_probe(struct cs35l56_hda *cs35l56, int hid, int id) } cs35l56->base.type = hid & 0xff; - cs35l56->base.cal_index = -1; + cs35l56->base.cal_index = cs35l56->index; cs35l56_init_cs_dsp(&cs35l56->base, &cs35l56->cs_dsp); cs35l56->cs_dsp.client_ops = &cs35l56_hda_client_ops; |