1137 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2//3// HDA audio driver for Cirrus Logic CS35L56 smart amp4//5// Copyright (C) 2023 Cirrus Logic, Inc. and6// Cirrus Logic International Semiconductor Ltd.7//8 9#include <linux/acpi.h>10#include <linux/debugfs.h>11#include <linux/gpio/consumer.h>12#include <linux/module.h>13#include <linux/pm_runtime.h>14#include <linux/regmap.h>15#include <linux/slab.h>16#include <sound/core.h>17#include <sound/cs-amp-lib.h>18#include <sound/hda_codec.h>19#include <sound/tlv.h>20#include "cirrus_scodec.h"21#include "cs35l56_hda.h"22#include "hda_component.h"23#include "hda_cs_dsp_ctl.h"24#include "hda_generic.h"25 26 /*27 * The cs35l56_hda_dai_config[] reg sequence configures the device as28 * ASP1_BCLK_FREQ = 3.072 MHz29 * ASP1_RX_WIDTH = 32 cycles per slot, ASP1_TX_WIDTH = 32 cycles per slot, ASP1_FMT = I2S30 * ASP1_DOUT_HIZ_CONTROL = Hi-Z during unused timeslots31 * ASP1_RX_WL = 24 bits per sample32 * ASP1_TX_WL = 24 bits per sample33 * ASP1_RXn_EN 1..3 and ASP1_TXn_EN 1..4 disabled34 *35 * Override any Windows-specific mixer settings applied by the firmware.36 */37static const struct reg_sequence cs35l56_hda_dai_config[] = {38 { CS35L56_ASP1_CONTROL1, 0x00000021 },39 { CS35L56_ASP1_CONTROL2, 0x20200200 },40 { CS35L56_ASP1_CONTROL3, 0x00000003 },41 { CS35L56_ASP1_FRAME_CONTROL1, 0x03020100 },42 { CS35L56_ASP1_FRAME_CONTROL5, 0x00020100 },43 { CS35L56_ASP1_DATA_CONTROL5, 0x00000018 },44 { CS35L56_ASP1_DATA_CONTROL1, 0x00000018 },45 { CS35L56_ASP1_ENABLES1, 0x00000000 },46 { CS35L56_ASP1TX1_INPUT, 0x00000018 },47 { CS35L56_ASP1TX2_INPUT, 0x00000019 },48 { CS35L56_ASP1TX3_INPUT, 0x00000020 },49 { CS35L56_ASP1TX4_INPUT, 0x00000028 },50 51};52 53static void cs35l56_hda_wait_dsp_ready(struct cs35l56_hda *cs35l56)54{55 /* Wait for patching to complete */56 flush_work(&cs35l56->dsp_work);57}58 59static void cs35l56_hda_play(struct cs35l56_hda *cs35l56)60{61 unsigned int val;62 int ret;63 64 cs35l56_hda_wait_dsp_ready(cs35l56);65 66 pm_runtime_get_sync(cs35l56->base.dev);67 ret = cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_AUDIO_PLAY);68 if (ret == 0) {69 /* Wait for firmware to enter PS0 power state */70 ret = regmap_read_poll_timeout(cs35l56->base.regmap,71 CS35L56_TRANSDUCER_ACTUAL_PS,72 val, (val == CS35L56_PS0),73 CS35L56_PS0_POLL_US,74 CS35L56_PS0_TIMEOUT_US);75 if (ret)76 dev_warn(cs35l56->base.dev, "PS0 wait failed: %d\n", ret);77 }78 regmap_set_bits(cs35l56->base.regmap, CS35L56_ASP1_ENABLES1,79 BIT(CS35L56_ASP_RX1_EN_SHIFT) | BIT(CS35L56_ASP_RX2_EN_SHIFT) |80 cs35l56->asp_tx_mask);81 cs35l56->playing = true;82}83 84static void cs35l56_hda_pause(struct cs35l56_hda *cs35l56)85{86 cs35l56->playing = false;87 cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_AUDIO_PAUSE);88 regmap_clear_bits(cs35l56->base.regmap, CS35L56_ASP1_ENABLES1,89 BIT(CS35L56_ASP_RX1_EN_SHIFT) | BIT(CS35L56_ASP_RX2_EN_SHIFT) |90 BIT(CS35L56_ASP_TX1_EN_SHIFT) | BIT(CS35L56_ASP_TX2_EN_SHIFT) |91 BIT(CS35L56_ASP_TX3_EN_SHIFT) | BIT(CS35L56_ASP_TX4_EN_SHIFT));92 93 pm_runtime_mark_last_busy(cs35l56->base.dev);94 pm_runtime_put_autosuspend(cs35l56->base.dev);95}96 97static void cs35l56_hda_playback_hook(struct device *dev, int action)98{99 struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev);100 101 dev_dbg(cs35l56->base.dev, "%s()%d: action: %d\n", __func__, __LINE__, action);102 103 switch (action) {104 case HDA_GEN_PCM_ACT_PREPARE:105 if (cs35l56->playing)106 break;107 108 /* If we're suspended: flag that resume should start playback */109 if (cs35l56->suspended) {110 cs35l56->playing = true;111 break;112 }113 114 cs35l56_hda_play(cs35l56);115 break;116 case HDA_GEN_PCM_ACT_CLEANUP:117 if (!cs35l56->playing)118 break;119 120 cs35l56_hda_pause(cs35l56);121 break;122 default:123 break;124 }125}126 127static int cs35l56_hda_runtime_suspend(struct device *dev)128{129 struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev);130 131 if (cs35l56->cs_dsp.booted)132 cs_dsp_stop(&cs35l56->cs_dsp);133 134 return cs35l56_runtime_suspend_common(&cs35l56->base);135}136 137static int cs35l56_hda_runtime_resume(struct device *dev)138{139 struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev);140 int ret;141 142 ret = cs35l56_runtime_resume_common(&cs35l56->base, false);143 if (ret < 0)144 return ret;145 146 if (cs35l56->cs_dsp.booted) {147 ret = cs_dsp_run(&cs35l56->cs_dsp);148 if (ret) {149 dev_dbg(cs35l56->base.dev, "%s: cs_dsp_run ret %d\n", __func__, ret);150 goto err;151 }152 }153 154 ret = cs35l56_force_sync_asp1_registers_from_cache(&cs35l56->base);155 if (ret)156 goto err;157 158 return 0;159 160err:161 cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_ALLOW_AUTO_HIBERNATE);162 regmap_write(cs35l56->base.regmap, CS35L56_DSP_VIRTUAL1_MBOX_1,163 CS35L56_MBOX_CMD_HIBERNATE_NOW);164 165 regcache_cache_only(cs35l56->base.regmap, true);166 167 return ret;168}169 170static int cs35l56_hda_mixer_info(struct snd_kcontrol *kcontrol,171 struct snd_ctl_elem_info *uinfo)172{173 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;174 uinfo->count = 1;175 uinfo->value.enumerated.items = CS35L56_NUM_INPUT_SRC;176 if (uinfo->value.enumerated.item >= CS35L56_NUM_INPUT_SRC)177 uinfo->value.enumerated.item = CS35L56_NUM_INPUT_SRC - 1;178 strscpy(uinfo->value.enumerated.name, cs35l56_tx_input_texts[uinfo->value.enumerated.item],179 sizeof(uinfo->value.enumerated.name));180 181 return 0;182}183 184static int cs35l56_hda_mixer_get(struct snd_kcontrol *kcontrol,185 struct snd_ctl_elem_value *ucontrol)186{187 struct cs35l56_hda *cs35l56 = (struct cs35l56_hda *)kcontrol->private_data;188 unsigned int reg_val;189 int i;190 191 cs35l56_hda_wait_dsp_ready(cs35l56);192 193 regmap_read(cs35l56->base.regmap, kcontrol->private_value, ®_val);194 reg_val &= CS35L56_ASP_TXn_SRC_MASK;195 196 for (i = 0; i < CS35L56_NUM_INPUT_SRC; ++i) {197 if (cs35l56_tx_input_values[i] == reg_val) {198 ucontrol->value.enumerated.item[0] = i;199 break;200 }201 }202 203 return 0;204}205 206static int cs35l56_hda_mixer_put(struct snd_kcontrol *kcontrol,207 struct snd_ctl_elem_value *ucontrol)208{209 struct cs35l56_hda *cs35l56 = (struct cs35l56_hda *)kcontrol->private_data;210 unsigned int item = ucontrol->value.enumerated.item[0];211 bool changed;212 213 if (item >= CS35L56_NUM_INPUT_SRC)214 return -EINVAL;215 216 cs35l56_hda_wait_dsp_ready(cs35l56);217 218 regmap_update_bits_check(cs35l56->base.regmap, kcontrol->private_value,219 CS35L56_INPUT_MASK, cs35l56_tx_input_values[item],220 &changed);221 222 return changed;223}224 225static int cs35l56_hda_posture_info(struct snd_kcontrol *kcontrol,226 struct snd_ctl_elem_info *uinfo)227{228 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;229 uinfo->count = 1;230 uinfo->value.integer.min = CS35L56_MAIN_POSTURE_MIN;231 uinfo->value.integer.max = CS35L56_MAIN_POSTURE_MAX;232 return 0;233}234 235static int cs35l56_hda_posture_get(struct snd_kcontrol *kcontrol,236 struct snd_ctl_elem_value *ucontrol)237{238 struct cs35l56_hda *cs35l56 = (struct cs35l56_hda *)kcontrol->private_data;239 unsigned int pos;240 int ret;241 242 cs35l56_hda_wait_dsp_ready(cs35l56);243 244 ret = regmap_read(cs35l56->base.regmap, CS35L56_MAIN_POSTURE_NUMBER, &pos);245 if (ret)246 return ret;247 248 ucontrol->value.integer.value[0] = pos;249 250 return 0;251}252 253static int cs35l56_hda_posture_put(struct snd_kcontrol *kcontrol,254 struct snd_ctl_elem_value *ucontrol)255{256 struct cs35l56_hda *cs35l56 = (struct cs35l56_hda *)kcontrol->private_data;257 unsigned long pos = ucontrol->value.integer.value[0];258 bool changed;259 int ret;260 261 if ((pos < CS35L56_MAIN_POSTURE_MIN) ||262 (pos > CS35L56_MAIN_POSTURE_MAX))263 return -EINVAL;264 265 cs35l56_hda_wait_dsp_ready(cs35l56);266 267 ret = regmap_update_bits_check(cs35l56->base.regmap,268 CS35L56_MAIN_POSTURE_NUMBER,269 CS35L56_MAIN_POSTURE_MASK,270 pos, &changed);271 if (ret)272 return ret;273 274 return changed;275}276 277static const struct {278 const char *name;279 unsigned int reg;280} cs35l56_hda_mixer_controls[] = {281 { "ASP1 TX1 Source", CS35L56_ASP1TX1_INPUT },282 { "ASP1 TX2 Source", CS35L56_ASP1TX2_INPUT },283 { "ASP1 TX3 Source", CS35L56_ASP1TX3_INPUT },284 { "ASP1 TX4 Source", CS35L56_ASP1TX4_INPUT },285};286 287static const DECLARE_TLV_DB_SCALE(cs35l56_hda_vol_tlv, -10000, 25, 0);288 289static int cs35l56_hda_vol_info(struct snd_kcontrol *kcontrol,290 struct snd_ctl_elem_info *uinfo)291{292 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;293 uinfo->count = 1;294 uinfo->value.integer.step = 1;295 uinfo->value.integer.min = 0;296 uinfo->value.integer.max = CS35L56_MAIN_RENDER_USER_VOLUME_MAX -297 CS35L56_MAIN_RENDER_USER_VOLUME_MIN;298 299 return 0;300}301 302static int cs35l56_hda_vol_get(struct snd_kcontrol *kcontrol,303 struct snd_ctl_elem_value *ucontrol)304{305 struct cs35l56_hda *cs35l56 = (struct cs35l56_hda *)kcontrol->private_data;306 unsigned int raw_vol;307 int vol;308 int ret;309 310 cs35l56_hda_wait_dsp_ready(cs35l56);311 312 ret = regmap_read(cs35l56->base.regmap, CS35L56_MAIN_RENDER_USER_VOLUME, &raw_vol);313 314 if (ret)315 return ret;316 317 vol = (s16)(raw_vol & 0xFFFF);318 vol >>= CS35L56_MAIN_RENDER_USER_VOLUME_SHIFT;319 320 if (vol & BIT(CS35L56_MAIN_RENDER_USER_VOLUME_SIGNBIT))321 vol |= ~((int)(BIT(CS35L56_MAIN_RENDER_USER_VOLUME_SIGNBIT) - 1));322 323 ucontrol->value.integer.value[0] = vol - CS35L56_MAIN_RENDER_USER_VOLUME_MIN;324 325 return 0;326}327 328static int cs35l56_hda_vol_put(struct snd_kcontrol *kcontrol,329 struct snd_ctl_elem_value *ucontrol)330{331 struct cs35l56_hda *cs35l56 = (struct cs35l56_hda *)kcontrol->private_data;332 long vol = ucontrol->value.integer.value[0];333 unsigned int raw_vol;334 bool changed;335 int ret;336 337 if ((vol < 0) || (vol > (CS35L56_MAIN_RENDER_USER_VOLUME_MAX -338 CS35L56_MAIN_RENDER_USER_VOLUME_MIN)))339 return -EINVAL;340 341 raw_vol = (vol + CS35L56_MAIN_RENDER_USER_VOLUME_MIN) <<342 CS35L56_MAIN_RENDER_USER_VOLUME_SHIFT;343 344 cs35l56_hda_wait_dsp_ready(cs35l56);345 346 ret = regmap_update_bits_check(cs35l56->base.regmap,347 CS35L56_MAIN_RENDER_USER_VOLUME,348 CS35L56_MAIN_RENDER_USER_VOLUME_MASK,349 raw_vol, &changed);350 if (ret)351 return ret;352 353 return changed;354}355 356static void cs35l56_hda_create_controls(struct cs35l56_hda *cs35l56)357{358 struct snd_kcontrol_new ctl_template = {359 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,360 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,361 .info = cs35l56_hda_posture_info,362 .get = cs35l56_hda_posture_get,363 .put = cs35l56_hda_posture_put,364 };365 char name[64];366 int i;367 368 snprintf(name, sizeof(name), "%s Posture Number", cs35l56->amp_name);369 ctl_template.name = name;370 cs35l56->posture_ctl = snd_ctl_new1(&ctl_template, cs35l56);371 if (snd_ctl_add(cs35l56->codec->card, cs35l56->posture_ctl))372 dev_err(cs35l56->base.dev, "Failed to add KControl: %s\n", ctl_template.name);373 374 /* Mixer controls */375 ctl_template.info = cs35l56_hda_mixer_info;376 ctl_template.get = cs35l56_hda_mixer_get;377 ctl_template.put = cs35l56_hda_mixer_put;378 379 BUILD_BUG_ON(ARRAY_SIZE(cs35l56->mixer_ctl) != ARRAY_SIZE(cs35l56_hda_mixer_controls));380 381 for (i = 0; i < ARRAY_SIZE(cs35l56_hda_mixer_controls); ++i) {382 snprintf(name, sizeof(name), "%s %s", cs35l56->amp_name,383 cs35l56_hda_mixer_controls[i].name);384 ctl_template.private_value = cs35l56_hda_mixer_controls[i].reg;385 cs35l56->mixer_ctl[i] = snd_ctl_new1(&ctl_template, cs35l56);386 if (snd_ctl_add(cs35l56->codec->card, cs35l56->mixer_ctl[i])) {387 dev_err(cs35l56->base.dev, "Failed to add KControl: %s\n",388 ctl_template.name);389 }390 }391 392 ctl_template.info = cs35l56_hda_vol_info;393 ctl_template.get = cs35l56_hda_vol_get;394 ctl_template.put = cs35l56_hda_vol_put;395 ctl_template.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ);396 ctl_template.tlv.p = cs35l56_hda_vol_tlv;397 snprintf(name, sizeof(name), "%s Speaker Playback Volume", cs35l56->amp_name);398 ctl_template.name = name;399 cs35l56->volume_ctl = snd_ctl_new1(&ctl_template, cs35l56);400 if (snd_ctl_add(cs35l56->codec->card, cs35l56->volume_ctl))401 dev_err(cs35l56->base.dev, "Failed to add KControl: %s\n", ctl_template.name);402}403 404static void cs35l56_hda_remove_controls(struct cs35l56_hda *cs35l56)405{406 int i;407 408 for (i = ARRAY_SIZE(cs35l56->mixer_ctl) - 1; i >= 0; i--)409 snd_ctl_remove(cs35l56->codec->card, cs35l56->mixer_ctl[i]);410 411 snd_ctl_remove(cs35l56->codec->card, cs35l56->posture_ctl);412 snd_ctl_remove(cs35l56->codec->card, cs35l56->volume_ctl);413}414 415static const struct cs_dsp_client_ops cs35l56_hda_client_ops = {416 /* cs_dsp requires the client to provide this even if it is empty */417};418 419static int cs35l56_hda_request_firmware_file(struct cs35l56_hda *cs35l56,420 const struct firmware **firmware, char **filename,421 const char *base_name, const char *system_name,422 const char *amp_name,423 const char *filetype)424{425 char *s, c;426 int ret = 0;427 428 if (system_name && amp_name)429 *filename = kasprintf(GFP_KERNEL, "%s-%s-%s.%s", base_name,430 system_name, amp_name, filetype);431 else if (system_name)432 *filename = kasprintf(GFP_KERNEL, "%s-%s.%s", base_name,433 system_name, filetype);434 else435 *filename = kasprintf(GFP_KERNEL, "%s.%s", base_name, filetype);436 437 if (!*filename)438 return -ENOMEM;439 440 /*441 * Make sure that filename is lower-case and any non alpha-numeric442 * characters except full stop and forward slash are replaced with443 * hyphens.444 */445 s = *filename;446 while (*s) {447 c = *s;448 if (isalnum(c))449 *s = tolower(c);450 else if (c != '.' && c != '/')451 *s = '-';452 s++;453 }454 455 ret = firmware_request_nowarn(firmware, *filename, cs35l56->base.dev);456 if (ret) {457 dev_dbg(cs35l56->base.dev, "Failed to request '%s'\n", *filename);458 kfree(*filename);459 *filename = NULL;460 return ret;461 }462 463 dev_dbg(cs35l56->base.dev, "Found '%s'\n", *filename);464 465 return 0;466}467 468static void cs35l56_hda_request_firmware_files(struct cs35l56_hda *cs35l56,469 unsigned int preloaded_fw_ver,470 const struct firmware **wmfw_firmware,471 char **wmfw_filename,472 const struct firmware **coeff_firmware,473 char **coeff_filename)474{475 const char *system_name = cs35l56->system_name;476 const char *amp_name = cs35l56->amp_name;477 char base_name[37];478 int ret;479 480 if (preloaded_fw_ver) {481 snprintf(base_name, sizeof(base_name),482 "cirrus/cs35l%02x-%02x%s-%06x-dsp1-misc",483 cs35l56->base.type,484 cs35l56->base.rev,485 cs35l56->base.secured ? "-s" : "",486 preloaded_fw_ver & 0xffffff);487 } else {488 snprintf(base_name, sizeof(base_name),489 "cirrus/cs35l%02x-%02x%s-dsp1-misc",490 cs35l56->base.type,491 cs35l56->base.rev,492 cs35l56->base.secured ? "-s" : "");493 }494 495 if (system_name && amp_name) {496 if (!cs35l56_hda_request_firmware_file(cs35l56, wmfw_firmware, wmfw_filename,497 base_name, system_name, amp_name, "wmfw")) {498 cs35l56_hda_request_firmware_file(cs35l56, coeff_firmware, coeff_filename,499 base_name, system_name, amp_name, "bin");500 return;501 }502 }503 504 if (system_name) {505 if (!cs35l56_hda_request_firmware_file(cs35l56, wmfw_firmware, wmfw_filename,506 base_name, system_name, NULL, "wmfw")) {507 if (amp_name)508 cs35l56_hda_request_firmware_file(cs35l56,509 coeff_firmware, coeff_filename,510 base_name, system_name,511 amp_name, "bin");512 if (!*coeff_firmware)513 cs35l56_hda_request_firmware_file(cs35l56,514 coeff_firmware, coeff_filename,515 base_name, system_name,516 NULL, "bin");517 return;518 }519 520 /*521 * Check for system-specific bin files without wmfw before522 * falling back to generic firmware523 */524 if (amp_name)525 cs35l56_hda_request_firmware_file(cs35l56, coeff_firmware, coeff_filename,526 base_name, system_name, amp_name, "bin");527 if (!*coeff_firmware)528 cs35l56_hda_request_firmware_file(cs35l56, coeff_firmware, coeff_filename,529 base_name, system_name, NULL, "bin");530 531 if (*coeff_firmware)532 return;533 }534 535 ret = cs35l56_hda_request_firmware_file(cs35l56, wmfw_firmware, wmfw_filename,536 base_name, NULL, NULL, "wmfw");537 if (!ret) {538 cs35l56_hda_request_firmware_file(cs35l56, coeff_firmware, coeff_filename,539 base_name, NULL, NULL, "bin");540 return;541 }542 543 if (!*coeff_firmware)544 cs35l56_hda_request_firmware_file(cs35l56, coeff_firmware, coeff_filename,545 base_name, NULL, NULL, "bin");546}547 548static void cs35l56_hda_release_firmware_files(const struct firmware *wmfw_firmware,549 char *wmfw_filename,550 const struct firmware *coeff_firmware,551 char *coeff_filename)552{553 if (wmfw_firmware)554 release_firmware(wmfw_firmware);555 kfree(wmfw_filename);556 557 if (coeff_firmware)558 release_firmware(coeff_firmware);559 kfree(coeff_filename);560}561 562static void cs35l56_hda_apply_calibration(struct cs35l56_hda *cs35l56)563{564 int ret;565 566 if (!cs35l56->base.cal_data_valid || cs35l56->base.secured)567 return;568 569 ret = cs_amp_write_cal_coeffs(&cs35l56->cs_dsp,570 &cs35l56_calibration_controls,571 &cs35l56->base.cal_data);572 if (ret < 0)573 dev_warn(cs35l56->base.dev, "Failed to write calibration: %d\n", ret);574 else575 dev_info(cs35l56->base.dev, "Calibration applied\n");576}577 578static void cs35l56_hda_fw_load(struct cs35l56_hda *cs35l56)579{580 const struct firmware *coeff_firmware = NULL;581 const struct firmware *wmfw_firmware = NULL;582 char *coeff_filename = NULL;583 char *wmfw_filename = NULL;584 unsigned int preloaded_fw_ver;585 bool firmware_missing;586 int ret;587 588 /*589 * Prepare for a new DSP power-up. If the DSP has had firmware590 * downloaded previously then it needs to be powered down so that it591 * can be updated.592 */593 if (cs35l56->base.fw_patched)594 cs_dsp_power_down(&cs35l56->cs_dsp);595 596 cs35l56->base.fw_patched = false;597 598 ret = pm_runtime_resume_and_get(cs35l56->base.dev);599 if (ret < 0) {600 dev_err(cs35l56->base.dev, "Failed to resume and get %d\n", ret);601 return;602 }603 604 /*605 * The firmware can only be upgraded if it is currently running606 * from the built-in ROM. If not, the wmfw/bin must be for the607 * version of firmware that is running on the chip.608 */609 ret = cs35l56_read_prot_status(&cs35l56->base, &firmware_missing, &preloaded_fw_ver);610 if (ret)611 goto err_pm_put;612 613 if (firmware_missing)614 preloaded_fw_ver = 0;615 616 cs35l56_hda_request_firmware_files(cs35l56, preloaded_fw_ver,617 &wmfw_firmware, &wmfw_filename,618 &coeff_firmware, &coeff_filename);619 620 /*621 * If the BIOS didn't patch the firmware a bin file is mandatory to622 * enable the ASP·623 */624 if (!coeff_firmware && firmware_missing) {625 dev_err(cs35l56->base.dev, ".bin file required but not found\n");626 goto err_fw_release;627 }628 629 mutex_lock(&cs35l56->base.irq_lock);630 631 /*632 * If the firmware hasn't been patched it must be shutdown before633 * doing a full patch and reset afterwards. If it is already634 * running a patched version the firmware files only contain635 * tunings and we can use the lower cost reinit sequence instead.636 */637 if (firmware_missing && (wmfw_firmware || coeff_firmware)) {638 ret = cs35l56_firmware_shutdown(&cs35l56->base);639 if (ret)640 goto err;641 }642 643 ret = cs_dsp_power_up(&cs35l56->cs_dsp, wmfw_firmware, wmfw_filename,644 coeff_firmware, coeff_filename, "misc");645 if (ret) {646 dev_dbg(cs35l56->base.dev, "%s: cs_dsp_power_up ret %d\n", __func__, ret);647 goto err;648 }649 650 if (wmfw_filename)651 dev_dbg(cs35l56->base.dev, "Loaded WMFW Firmware: %s\n", wmfw_filename);652 653 if (coeff_filename)654 dev_dbg(cs35l56->base.dev, "Loaded Coefficients: %s\n", coeff_filename);655 656 /* If we downloaded firmware, reset the device and wait for it to boot */657 if (firmware_missing && (wmfw_firmware || coeff_firmware)) {658 cs35l56_system_reset(&cs35l56->base, false);659 regcache_mark_dirty(cs35l56->base.regmap);660 ret = cs35l56_wait_for_firmware_boot(&cs35l56->base);661 if (ret)662 goto err_powered_up;663 664 regcache_cache_only(cs35l56->base.regmap, false);665 }666 667 /* Disable auto-hibernate so that runtime_pm has control */668 ret = cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_PREVENT_AUTO_HIBERNATE);669 if (ret)670 goto err_powered_up;671 672 regcache_sync(cs35l56->base.regmap);673 674 regmap_clear_bits(cs35l56->base.regmap, CS35L56_PROTECTION_STATUS,675 CS35L56_FIRMWARE_MISSING);676 cs35l56->base.fw_patched = true;677 678 ret = cs_dsp_run(&cs35l56->cs_dsp);679 if (ret)680 dev_dbg(cs35l56->base.dev, "%s: cs_dsp_run ret %d\n", __func__, ret);681 682 cs35l56_hda_apply_calibration(cs35l56);683 ret = cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_AUDIO_REINIT);684 if (ret)685 cs_dsp_stop(&cs35l56->cs_dsp);686 687err_powered_up:688 if (!cs35l56->base.fw_patched)689 cs_dsp_power_down(&cs35l56->cs_dsp);690err:691 mutex_unlock(&cs35l56->base.irq_lock);692err_fw_release:693 cs35l56_hda_release_firmware_files(wmfw_firmware, wmfw_filename,694 coeff_firmware, coeff_filename);695err_pm_put:696 pm_runtime_put(cs35l56->base.dev);697}698 699static void cs35l56_hda_dsp_work(struct work_struct *work)700{701 struct cs35l56_hda *cs35l56 = container_of(work, struct cs35l56_hda, dsp_work);702 703 cs35l56_hda_fw_load(cs35l56);704}705 706static int cs35l56_hda_bind(struct device *dev, struct device *master, void *master_data)707{708 struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev);709 struct hda_component_parent *parent = master_data;710 struct hda_component *comp;711 712 comp = hda_component_from_index(parent, cs35l56->index);713 if (!comp)714 return -EINVAL;715 716 if (comp->dev)717 return -EBUSY;718 719 comp->dev = dev;720 cs35l56->codec = parent->codec;721 strscpy(comp->name, dev_name(dev), sizeof(comp->name));722 comp->playback_hook = cs35l56_hda_playback_hook;723 724 queue_work(system_long_wq, &cs35l56->dsp_work);725 726 cs35l56_hda_create_controls(cs35l56);727 728#if IS_ENABLED(CONFIG_SND_DEBUG)729 cs35l56->debugfs_root = debugfs_create_dir(dev_name(cs35l56->base.dev), sound_debugfs_root);730 cs_dsp_init_debugfs(&cs35l56->cs_dsp, cs35l56->debugfs_root);731#endif732 733 dev_dbg(cs35l56->base.dev, "Bound\n");734 735 return 0;736}737 738static void cs35l56_hda_unbind(struct device *dev, struct device *master, void *master_data)739{740 struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev);741 struct hda_component_parent *parent = master_data;742 struct hda_component *comp;743 744 cancel_work_sync(&cs35l56->dsp_work);745 746 cs35l56_hda_remove_controls(cs35l56);747 748#if IS_ENABLED(CONFIG_SND_DEBUG)749 cs_dsp_cleanup_debugfs(&cs35l56->cs_dsp);750 debugfs_remove_recursive(cs35l56->debugfs_root);751#endif752 753 if (cs35l56->base.fw_patched)754 cs_dsp_power_down(&cs35l56->cs_dsp);755 756 comp = hda_component_from_index(parent, cs35l56->index);757 if (comp && (comp->dev == dev))758 memset(comp, 0, sizeof(*comp));759 760 cs35l56->codec = NULL;761 762 dev_dbg(cs35l56->base.dev, "Unbound\n");763}764 765static const struct component_ops cs35l56_hda_comp_ops = {766 .bind = cs35l56_hda_bind,767 .unbind = cs35l56_hda_unbind,768};769 770static int cs35l56_hda_system_suspend(struct device *dev)771{772 struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev);773 774 cs35l56_hda_wait_dsp_ready(cs35l56);775 776 if (cs35l56->playing)777 cs35l56_hda_pause(cs35l56);778 779 cs35l56->suspended = true;780 781 /*782 * The interrupt line is normally shared, but after we start suspending783 * we can't check if our device is the source of an interrupt, and can't784 * clear it. Prevent this race by temporarily disabling the parent irq785 * until we reach _no_irq.786 */787 if (cs35l56->base.irq)788 disable_irq(cs35l56->base.irq);789 790 return pm_runtime_force_suspend(dev);791}792 793static int cs35l56_hda_system_suspend_late(struct device *dev)794{795 struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev);796 797 /*798 * RESET is usually shared by all amps so it must not be asserted until799 * all driver instances have done their suspend() stage.800 */801 if (cs35l56->base.reset_gpio) {802 gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0);803 cs35l56_wait_min_reset_pulse();804 }805 806 return 0;807}808 809static int cs35l56_hda_system_suspend_no_irq(struct device *dev)810{811 struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev);812 813 /* Handlers are now disabled so the parent IRQ can safely be re-enabled. */814 if (cs35l56->base.irq)815 enable_irq(cs35l56->base.irq);816 817 return 0;818}819 820static int cs35l56_hda_system_resume_no_irq(struct device *dev)821{822 struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev);823 824 /*825 * WAKE interrupts unmask if the CS35L56 hibernates, which can cause826 * spurious interrupts, and the interrupt line is normally shared.827 * We can't check if our device is the source of an interrupt, and can't828 * clear it, until it has fully resumed. Prevent this race by temporarily829 * disabling the parent irq until we complete resume().830 */831 if (cs35l56->base.irq)832 disable_irq(cs35l56->base.irq);833 834 return 0;835}836 837static int cs35l56_hda_system_resume_early(struct device *dev)838{839 struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev);840 841 /* Ensure a spec-compliant RESET pulse. */842 if (cs35l56->base.reset_gpio) {843 gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0);844 cs35l56_wait_min_reset_pulse();845 846 /* Release shared RESET before drivers start resume(). */847 gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 1);848 cs35l56_wait_control_port_ready();849 }850 851 return 0;852}853 854static int cs35l56_hda_system_resume(struct device *dev)855{856 struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev);857 int ret;858 859 /* Undo pm_runtime_force_suspend() before re-enabling the irq */860 ret = pm_runtime_force_resume(dev);861 if (cs35l56->base.irq)862 enable_irq(cs35l56->base.irq);863 864 if (ret)865 return ret;866 867 cs35l56->suspended = false;868 869 if (!cs35l56->codec)870 return 0;871 872 ret = cs35l56_is_fw_reload_needed(&cs35l56->base);873 dev_dbg(cs35l56->base.dev, "fw_reload_needed: %d\n", ret);874 if (ret > 0)875 queue_work(system_long_wq, &cs35l56->dsp_work);876 877 if (cs35l56->playing)878 cs35l56_hda_play(cs35l56);879 880 return 0;881}882 883static int cs35l56_hda_read_acpi(struct cs35l56_hda *cs35l56, int hid, int id)884{885 u32 values[HDA_MAX_COMPONENTS];886 char hid_string[8];887 struct acpi_device *adev;888 const char *property, *sub;889 size_t nval;890 int i, ret;891 892 /*893 * ACPI_COMPANION isn't available when this driver was instantiated by894 * the serial-multi-instantiate driver, so lookup the node by HID895 */896 if (!ACPI_COMPANION(cs35l56->base.dev)) {897 snprintf(hid_string, sizeof(hid_string), "CSC%04X", hid);898 adev = acpi_dev_get_first_match_dev(hid_string, NULL, -1);899 if (!adev) {900 dev_err(cs35l56->base.dev, "Failed to find an ACPI device for %s\n",901 dev_name(cs35l56->base.dev));902 return -ENODEV;903 }904 ACPI_COMPANION_SET(cs35l56->base.dev, adev);905 }906 907 property = "cirrus,dev-index";908 ret = device_property_count_u32(cs35l56->base.dev, property);909 if (ret <= 0)910 goto err;911 912 if (ret > ARRAY_SIZE(values)) {913 ret = -EINVAL;914 goto err;915 }916 nval = ret;917 918 ret = device_property_read_u32_array(cs35l56->base.dev, property, values, nval);919 if (ret)920 goto err;921 922 cs35l56->index = -1;923 for (i = 0; i < nval; i++) {924 if (values[i] == id) {925 cs35l56->index = i;926 break;927 }928 }929 /*930 * It's not an error for the ID to be missing: for I2C there can be931 * an alias address that is not a real device. So reject silently.932 */933 if (cs35l56->index == -1) {934 dev_dbg(cs35l56->base.dev, "No index found in %s\n", property);935 ret = -ENODEV;936 goto err;937 }938 939 sub = acpi_get_subsystem_id(ACPI_HANDLE(cs35l56->base.dev));940 941 if (IS_ERR(sub)) {942 dev_info(cs35l56->base.dev,943 "Read ACPI _SUB failed(%ld): fallback to generic firmware\n",944 PTR_ERR(sub));945 } else {946 ret = cirrus_scodec_get_speaker_id(cs35l56->base.dev, cs35l56->index, nval, -1);947 if (ret == -ENOENT) {948 cs35l56->system_name = sub;949 } else if (ret >= 0) {950 cs35l56->system_name = kasprintf(GFP_KERNEL, "%s-spkid%d", sub, ret);951 kfree(sub);952 if (!cs35l56->system_name)953 return -ENOMEM;954 } else {955 return ret;956 }957 }958 959 cs35l56->base.reset_gpio = devm_gpiod_get_index_optional(cs35l56->base.dev,960 "reset",961 cs35l56->index,962 GPIOD_OUT_LOW);963 if (IS_ERR(cs35l56->base.reset_gpio)) {964 ret = PTR_ERR(cs35l56->base.reset_gpio);965 966 /*967 * If RESET is shared the first amp to probe will grab the reset968 * line and reset all the amps969 */970 if (ret != -EBUSY)971 return dev_err_probe(cs35l56->base.dev, ret, "Failed to get reset GPIO\n");972 973 dev_info(cs35l56->base.dev, "Reset GPIO busy, assume shared reset\n");974 cs35l56->base.reset_gpio = NULL;975 }976 977 return 0;978 979err:980 if (ret != -ENODEV)981 dev_err(cs35l56->base.dev, "Failed property %s: %d\n", property, ret);982 983 return ret;984}985 986int cs35l56_hda_common_probe(struct cs35l56_hda *cs35l56, int hid, int id)987{988 int ret;989 990 mutex_init(&cs35l56->base.irq_lock);991 dev_set_drvdata(cs35l56->base.dev, cs35l56);992 993 INIT_WORK(&cs35l56->dsp_work, cs35l56_hda_dsp_work);994 995 ret = cs35l56_hda_read_acpi(cs35l56, hid, id);996 if (ret)997 goto err;998 999 cs35l56->amp_name = devm_kasprintf(cs35l56->base.dev, GFP_KERNEL, "AMP%d",1000 cs35l56->index + 1);1001 if (!cs35l56->amp_name) {1002 ret = -ENOMEM;1003 goto err;1004 }1005 1006 cs35l56->base.cal_index = -1;1007 1008 cs35l56_init_cs_dsp(&cs35l56->base, &cs35l56->cs_dsp);1009 cs35l56->cs_dsp.client_ops = &cs35l56_hda_client_ops;1010 1011 if (cs35l56->base.reset_gpio) {1012 dev_dbg(cs35l56->base.dev, "Hard reset\n");1013 1014 /*1015 * The GPIOD_OUT_LOW to *_gpiod_get_*() will be ignored if the1016 * ACPI defines a different default state. So explicitly set low.1017 */1018 gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0);1019 cs35l56_wait_min_reset_pulse();1020 gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 1);1021 }1022 1023 ret = cs35l56_hw_init(&cs35l56->base);1024 if (ret < 0)1025 goto err;1026 1027 /* Reset the device and wait for it to boot */1028 cs35l56_system_reset(&cs35l56->base, false);1029 ret = cs35l56_wait_for_firmware_boot(&cs35l56->base);1030 if (ret)1031 goto err;1032 1033 regcache_cache_only(cs35l56->base.regmap, false);1034 1035 ret = cs35l56_set_patch(&cs35l56->base);1036 if (ret)1037 goto err;1038 1039 regcache_mark_dirty(cs35l56->base.regmap);1040 regcache_sync(cs35l56->base.regmap);1041 1042 /* Disable auto-hibernate so that runtime_pm has control */1043 ret = cs35l56_mbox_send(&cs35l56->base, CS35L56_MBOX_CMD_PREVENT_AUTO_HIBERNATE);1044 if (ret)1045 goto err;1046 1047 ret = cs35l56_get_calibration(&cs35l56->base);1048 if (ret)1049 goto err;1050 1051 ret = cs_dsp_halo_init(&cs35l56->cs_dsp);1052 if (ret) {1053 dev_err_probe(cs35l56->base.dev, ret, "cs_dsp_halo_init failed\n");1054 goto err;1055 }1056 1057 dev_info(cs35l56->base.dev, "DSP system name: '%s', amp name: '%s'\n",1058 cs35l56->system_name, cs35l56->amp_name);1059 1060 regmap_multi_reg_write(cs35l56->base.regmap, cs35l56_hda_dai_config,1061 ARRAY_SIZE(cs35l56_hda_dai_config));1062 ret = cs35l56_force_sync_asp1_registers_from_cache(&cs35l56->base);1063 if (ret)1064 goto dsp_err;1065 1066 /*1067 * By default only enable one ASP1TXn, where n=amplifier index,1068 * This prevents multiple amps trying to drive the same slot.1069 */1070 cs35l56->asp_tx_mask = BIT(cs35l56->index);1071 1072 pm_runtime_set_autosuspend_delay(cs35l56->base.dev, 3000);1073 pm_runtime_use_autosuspend(cs35l56->base.dev);1074 pm_runtime_set_active(cs35l56->base.dev);1075 pm_runtime_mark_last_busy(cs35l56->base.dev);1076 pm_runtime_enable(cs35l56->base.dev);1077 1078 cs35l56->base.init_done = true;1079 1080 ret = component_add(cs35l56->base.dev, &cs35l56_hda_comp_ops);1081 if (ret) {1082 dev_err(cs35l56->base.dev, "Register component failed: %d\n", ret);1083 goto pm_err;1084 }1085 1086 return 0;1087 1088pm_err:1089 pm_runtime_disable(cs35l56->base.dev);1090dsp_err:1091 cs_dsp_remove(&cs35l56->cs_dsp);1092err:1093 gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0);1094 1095 return ret;1096}1097EXPORT_SYMBOL_NS_GPL(cs35l56_hda_common_probe, SND_HDA_SCODEC_CS35L56);1098 1099void cs35l56_hda_remove(struct device *dev)1100{1101 struct cs35l56_hda *cs35l56 = dev_get_drvdata(dev);1102 1103 component_del(cs35l56->base.dev, &cs35l56_hda_comp_ops);1104 1105 pm_runtime_dont_use_autosuspend(cs35l56->base.dev);1106 pm_runtime_get_sync(cs35l56->base.dev);1107 pm_runtime_disable(cs35l56->base.dev);1108 1109 cs_dsp_remove(&cs35l56->cs_dsp);1110 1111 kfree(cs35l56->system_name);1112 pm_runtime_put_noidle(cs35l56->base.dev);1113 1114 gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0);1115}1116EXPORT_SYMBOL_NS_GPL(cs35l56_hda_remove, SND_HDA_SCODEC_CS35L56);1117 1118const struct dev_pm_ops cs35l56_hda_pm_ops = {1119 RUNTIME_PM_OPS(cs35l56_hda_runtime_suspend, cs35l56_hda_runtime_resume, NULL)1120 SYSTEM_SLEEP_PM_OPS(cs35l56_hda_system_suspend, cs35l56_hda_system_resume)1121 LATE_SYSTEM_SLEEP_PM_OPS(cs35l56_hda_system_suspend_late,1122 cs35l56_hda_system_resume_early)1123 NOIRQ_SYSTEM_SLEEP_PM_OPS(cs35l56_hda_system_suspend_no_irq,1124 cs35l56_hda_system_resume_no_irq)1125};1126EXPORT_SYMBOL_NS_GPL(cs35l56_hda_pm_ops, SND_HDA_SCODEC_CS35L56);1127 1128MODULE_DESCRIPTION("CS35L56 HDA Driver");1129MODULE_IMPORT_NS(FW_CS_DSP);1130MODULE_IMPORT_NS(SND_HDA_CIRRUS_SCODEC);1131MODULE_IMPORT_NS(SND_HDA_CS_DSP_CONTROLS);1132MODULE_IMPORT_NS(SND_SOC_CS35L56_SHARED);1133MODULE_IMPORT_NS(SND_SOC_CS_AMP_LIB);1134MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");1135MODULE_AUTHOR("Simon Trimmer <simont@opensource.cirrus.com>");1136MODULE_LICENSE("GPL");1137