Path: blob/master/sound/hda/codecs/side-codecs/cs35l41_hda.c
29268 views
// SPDX-License-Identifier: GPL-2.01//2// CS35l41 ALSA HDA audio driver3//4// Copyright 2021 Cirrus Logic, Inc.5//6// Author: Lucas Tanure <[email protected]>78#include <linux/acpi.h>9#include <linux/module.h>10#include <linux/moduleparam.h>11#include <sound/hda_codec.h>12#include <sound/soc.h>13#include <linux/pm_runtime.h>14#include <linux/spi/spi.h>15#include <linux/vmalloc.h>16#include "hda_local.h"17#include "hda_auto_parser.h"18#include "hda_jack.h"19#include "../generic.h"20#include "hda_component.h"21#include "cs35l41_hda.h"22#include "cs35l41_hda_property.h"2324#define CS35L41_PART "cs35l41"2526#define HALO_STATE_DSP_CTL_NAME "HALO_STATE"27#define HALO_STATE_DSP_CTL_TYPE 528#define HALO_STATE_DSP_CTL_ALG 26230829#define CAL_R_DSP_CTL_NAME "CAL_R"30#define CAL_STATUS_DSP_CTL_NAME "CAL_STATUS"31#define CAL_CHECKSUM_DSP_CTL_NAME "CAL_CHECKSUM"32#define CAL_AMBIENT_DSP_CTL_NAME "CAL_AMBIENT"33#define CAL_DSP_CTL_TYPE 534#define CAL_DSP_CTL_ALG 20535#define CS35L41_UUID "50d90cdc-3de4-4f18-b528-c7fe3b71f40d"36#define CS35L41_DSM_GET_MUTE 537#define CS35L41_NOTIFY_EVENT 0x9138#define CS35L41_TUNING_SIG 0x109A4A353940enum cs35l41_tuning_param_types {41TUNING_PARAM_GAIN,42};4344struct cs35l41_tuning_param_hdr {45__le32 tuning_index;46__le32 type;47__le32 size;48} __packed;4950struct cs35l41_tuning_param {51struct cs35l41_tuning_param_hdr hdr;52union {53__le32 gain;54};55} __packed;5657struct cs35l41_tuning_params {58__le32 signature;59__le32 version;60__le32 size;61__le32 num_entries;62u8 data[];63} __packed;6465/* Firmware calibration controls */66static const struct cirrus_amp_cal_controls cs35l41_calibration_controls = {67.alg_id = CAL_DSP_CTL_ALG,68.mem_region = CAL_DSP_CTL_TYPE,69.ambient = CAL_AMBIENT_DSP_CTL_NAME,70.calr = CAL_R_DSP_CTL_NAME,71.status = CAL_STATUS_DSP_CTL_NAME,72.checksum = CAL_CHECKSUM_DSP_CTL_NAME,73};7475enum cs35l41_hda_fw_id {76CS35L41_HDA_FW_SPK_PROT,77CS35L41_HDA_FW_SPK_CALI,78CS35L41_HDA_FW_SPK_DIAG,79CS35L41_HDA_FW_MISC,80CS35L41_HDA_NUM_FW81};8283static const char * const cs35l41_hda_fw_ids[CS35L41_HDA_NUM_FW] = {84[CS35L41_HDA_FW_SPK_PROT] = "spk-prot",85[CS35L41_HDA_FW_SPK_CALI] = "spk-cali",86[CS35L41_HDA_FW_SPK_DIAG] = "spk-diag",87[CS35L41_HDA_FW_MISC] = "misc",88};8990static bool firmware_autostart = 1;91module_param(firmware_autostart, bool, 0444);92MODULE_PARM_DESC(firmware_autostart, "Allow automatic firmware download on boot"93"(0=Disable, 1=Enable) (default=1); ");9495static const char channel_name[3] = { 'L', 'R', 'C' };9697static const struct reg_sequence cs35l41_hda_config[] = {98{ CS35L41_PLL_CLK_CTRL, 0x00000430 }, // 3072000Hz, BCLK Input, PLL_REFCLK_EN = 199{ CS35L41_DSP_CLK_CTRL, 0x00000003 }, // DSP CLK EN100{ CS35L41_GLOBAL_CLK_CTRL, 0x00000003 }, // GLOBAL_FS = 48 kHz101{ CS35L41_SP_RATE_CTRL, 0x00000021 }, // ASP_BCLK_FREQ = 3.072 MHz102{ CS35L41_SP_FORMAT, 0x20200200 }, // 32 bits RX/TX slots, I2S, clk consumer103{ CS35L41_SP_TX_WL, 0x00000018 }, // 24 cycles/slot104{ CS35L41_SP_RX_WL, 0x00000018 }, // 24 cycles/slot105{ CS35L41_ASP_TX1_SRC, 0x00000018 }, // ASPTX1 SRC = VMON106{ CS35L41_ASP_TX2_SRC, 0x00000019 }, // ASPTX2 SRC = IMON107{ CS35L41_DSP1_RX3_SRC, 0x00000018 }, // DSP1RX3 SRC = VMON108{ CS35L41_DSP1_RX4_SRC, 0x00000019 }, // DSP1RX4 SRC = IMON109};110111static const struct reg_sequence cs35l41_hda_config_no_dsp[] = {112{ CS35L41_SP_HIZ_CTRL, 0x00000002 }, // Hi-Z unused113{ CS35L41_DAC_PCM1_SRC, 0x00000008 }, // DACPCM1_SRC = ASPRX1114{ CS35L41_ASP_TX3_SRC, 0x00000000 }, // ASPTX3 SRC = ZERO FILL115{ CS35L41_ASP_TX4_SRC, 0x00000000 }, // ASPTX4 SRC = ZERO FILL116{ CS35L41_DSP1_RX5_SRC, 0x00000020 }, // DSP1RX5 SRC = ERRVOL117{ CS35L41_DSP1_RX6_SRC, 0x00000021 }, // DSP1RX6 SRC = CLASSH_TGT118};119120static const struct reg_sequence cs35l41_hda_config_dsp[] = {121{ CS35L41_SP_HIZ_CTRL, 0x00000003 }, // Hi-Z unused/disabled122{ CS35L41_DAC_PCM1_SRC, 0x00000032 }, // DACPCM1_SRC = DSP1TX1123{ CS35L41_ASP_TX3_SRC, 0x00000028 }, // ASPTX3 SRC = VPMON124{ CS35L41_ASP_TX4_SRC, 0x00000029 }, // ASPTX4 SRC = VBSTMON125{ CS35L41_DSP1_RX6_SRC, 0x00000029 }, // DSP1RX6 SRC = VBSTMON126};127128static const struct reg_sequence cs35l41_hda_unmute[] = {129{ CS35L41_AMP_DIG_VOL_CTRL, 0x00008000 }, // AMP_HPF_PCM_EN = 1, AMP_VOL_PCM 0.0 dB130{ CS35L41_AMP_GAIN_CTRL, 0x00000084 }, // AMP_GAIN_PCM 4.5 dB131};132133static const struct reg_sequence cs35l41_hda_mute[] = {134{ CS35L41_AMP_GAIN_CTRL, 0x00000000 }, // AMP_GAIN_PCM 0.5 dB135{ CS35L41_AMP_DIG_VOL_CTRL, 0x0000A678 }, // AMP_HPF_PCM_EN = 1, AMP_VOL_PCM Mute136};137138static const struct cs_dsp_client_ops client_ops = {139/* cs_dsp requires the client to provide this even if it is empty */140};141142static int cs35l41_request_tuning_param_file(struct cs35l41_hda *cs35l41, char *tuning_filename,143const struct firmware **firmware, char **filename,144const char *ssid)145{146int ret = 0;147148/* Filename is the same as the tuning file with "cfg" suffix */149*filename = kasprintf(GFP_KERNEL, "%scfg", tuning_filename);150if (*filename == NULL)151return -ENOMEM;152153ret = firmware_request_nowarn(firmware, *filename, cs35l41->dev);154if (ret != 0) {155dev_dbg(cs35l41->dev, "Failed to request '%s'\n", *filename);156kfree(*filename);157*filename = NULL;158}159160return ret;161}162163static int cs35l41_request_firmware_file(struct cs35l41_hda *cs35l41,164const struct firmware **firmware, char **filename,165const char *ssid, const char *amp_name,166int spkid, const char *filetype)167{168const char * const dsp_name = cs35l41->cs_dsp.name;169char *s, c;170int ret = 0;171172if (spkid > -1 && ssid && amp_name)173*filename = kasprintf(GFP_KERNEL, "cirrus/%s-%s-%s-%s-spkid%d-%s.%s", CS35L41_PART,174dsp_name, cs35l41_hda_fw_ids[cs35l41->firmware_type],175ssid, spkid, amp_name, filetype);176else if (spkid > -1 && ssid)177*filename = kasprintf(GFP_KERNEL, "cirrus/%s-%s-%s-%s-spkid%d.%s", CS35L41_PART,178dsp_name, cs35l41_hda_fw_ids[cs35l41->firmware_type],179ssid, spkid, filetype);180else if (ssid && amp_name)181*filename = kasprintf(GFP_KERNEL, "cirrus/%s-%s-%s-%s-%s.%s", CS35L41_PART,182dsp_name, cs35l41_hda_fw_ids[cs35l41->firmware_type],183ssid, amp_name, filetype);184else if (ssid)185*filename = kasprintf(GFP_KERNEL, "cirrus/%s-%s-%s-%s.%s", CS35L41_PART,186dsp_name, cs35l41_hda_fw_ids[cs35l41->firmware_type],187ssid, filetype);188else189*filename = kasprintf(GFP_KERNEL, "cirrus/%s-%s-%s.%s", CS35L41_PART,190dsp_name, cs35l41_hda_fw_ids[cs35l41->firmware_type],191filetype);192193if (*filename == NULL)194return -ENOMEM;195196/*197* Make sure that filename is lower-case and any non alpha-numeric198* characters except full stop and '/' are replaced with hyphens.199*/200s = *filename;201while (*s) {202c = *s;203if (isalnum(c))204*s = tolower(c);205else if (c != '.' && c != '/')206*s = '-';207s++;208}209210ret = firmware_request_nowarn(firmware, *filename, cs35l41->dev);211if (ret != 0) {212dev_dbg(cs35l41->dev, "Failed to request '%s'\n", *filename);213kfree(*filename);214*filename = NULL;215}216217return ret;218}219220static int cs35l41_request_firmware_files_spkid(struct cs35l41_hda *cs35l41,221const struct firmware **wmfw_firmware,222char **wmfw_filename,223const struct firmware **coeff_firmware,224char **coeff_filename)225{226int ret;227228/* try cirrus/part-dspN-fwtype-sub<-spkidN><-ampname>.wmfw */229ret = cs35l41_request_firmware_file(cs35l41, wmfw_firmware, wmfw_filename,230cs35l41->acpi_subsystem_id, cs35l41->amp_name,231cs35l41->speaker_id, "wmfw");232if (!ret) {233/* try cirrus/part-dspN-fwtype-sub<-spkidN><-ampname>.bin */234ret = cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename,235cs35l41->acpi_subsystem_id, cs35l41->amp_name,236cs35l41->speaker_id, "bin");237if (ret)238goto coeff_err;239240return 0;241}242243/* try cirrus/part-dspN-fwtype-sub<-ampname>.wmfw */244ret = cs35l41_request_firmware_file(cs35l41, wmfw_firmware, wmfw_filename,245cs35l41->acpi_subsystem_id,246cs35l41->amp_name, -1, "wmfw");247if (!ret) {248/* try cirrus/part-dspN-fwtype-sub<-spkidN><-ampname>.bin */249ret = cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename,250cs35l41->acpi_subsystem_id, cs35l41->amp_name,251cs35l41->speaker_id, "bin");252if (ret)253goto coeff_err;254255return 0;256}257258/* try cirrus/part-dspN-fwtype-sub<-spkidN>.wmfw */259ret = cs35l41_request_firmware_file(cs35l41, wmfw_firmware, wmfw_filename,260cs35l41->acpi_subsystem_id,261NULL, cs35l41->speaker_id, "wmfw");262if (!ret) {263/* try cirrus/part-dspN-fwtype-sub<-spkidN><-ampname>.bin */264ret = cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename,265cs35l41->acpi_subsystem_id,266cs35l41->amp_name, cs35l41->speaker_id, "bin");267if (ret)268/* try cirrus/part-dspN-fwtype-sub<-spkidN>.bin */269ret = cs35l41_request_firmware_file(cs35l41, coeff_firmware,270coeff_filename,271cs35l41->acpi_subsystem_id, NULL,272cs35l41->speaker_id, "bin");273if (ret)274goto coeff_err;275276return 0;277}278279/* try cirrus/part-dspN-fwtype-sub.wmfw */280ret = cs35l41_request_firmware_file(cs35l41, wmfw_firmware, wmfw_filename,281cs35l41->acpi_subsystem_id,282NULL, -1, "wmfw");283if (!ret) {284/* try cirrus/part-dspN-fwtype-sub<-spkidN><-ampname>.bin */285ret = cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename,286cs35l41->acpi_subsystem_id, cs35l41->amp_name,287cs35l41->speaker_id, "bin");288if (ret)289/* try cirrus/part-dspN-fwtype-sub<-spkidN>.bin */290ret = cs35l41_request_firmware_file(cs35l41, coeff_firmware,291coeff_filename,292cs35l41->acpi_subsystem_id, NULL,293cs35l41->speaker_id, "bin");294if (ret)295goto coeff_err;296}297298return ret;299coeff_err:300release_firmware(*wmfw_firmware);301kfree(*wmfw_filename);302return ret;303}304305static int cs35l41_fallback_firmware_file(struct cs35l41_hda *cs35l41,306const struct firmware **wmfw_firmware,307char **wmfw_filename,308const struct firmware **coeff_firmware,309char **coeff_filename)310{311int ret;312313/* Handle fallback */314dev_warn(cs35l41->dev, "Falling back to default firmware.\n");315316/* fallback try cirrus/part-dspN-fwtype.wmfw */317ret = cs35l41_request_firmware_file(cs35l41, wmfw_firmware, wmfw_filename,318NULL, NULL, -1, "wmfw");319if (ret)320goto err;321322/* fallback try cirrus/part-dspN-fwtype.bin */323ret = cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename,324NULL, NULL, -1, "bin");325if (ret) {326release_firmware(*wmfw_firmware);327kfree(*wmfw_filename);328goto err;329}330return 0;331332err:333dev_warn(cs35l41->dev, "Unable to find firmware and tuning\n");334return ret;335}336337static int cs35l41_request_firmware_files(struct cs35l41_hda *cs35l41,338const struct firmware **wmfw_firmware,339char **wmfw_filename,340const struct firmware **coeff_firmware,341char **coeff_filename)342{343int ret;344345if (cs35l41->speaker_id > -1) {346ret = cs35l41_request_firmware_files_spkid(cs35l41, wmfw_firmware, wmfw_filename,347coeff_firmware, coeff_filename);348goto out;349}350351/* try cirrus/part-dspN-fwtype-sub<-ampname>.wmfw */352ret = cs35l41_request_firmware_file(cs35l41, wmfw_firmware, wmfw_filename,353cs35l41->acpi_subsystem_id,354cs35l41->amp_name, -1, "wmfw");355if (!ret) {356/* try cirrus/part-dspN-fwtype-sub<-ampname>.bin */357ret = cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename,358cs35l41->acpi_subsystem_id, cs35l41->amp_name,359-1, "bin");360if (ret)361goto coeff_err;362363goto out;364}365366/* try cirrus/part-dspN-fwtype-sub.wmfw */367ret = cs35l41_request_firmware_file(cs35l41, wmfw_firmware, wmfw_filename,368cs35l41->acpi_subsystem_id,369NULL, -1, "wmfw");370if (!ret) {371/* try cirrus/part-dspN-fwtype-sub<-ampname>.bin */372ret = cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename,373cs35l41->acpi_subsystem_id,374cs35l41->amp_name, -1, "bin");375if (ret)376/* try cirrus/part-dspN-fwtype-sub.bin */377ret = cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename,378cs35l41->acpi_subsystem_id, NULL, -1,379"bin");380if (ret)381goto coeff_err;382}383384out:385if (ret)386/* if all attempts at finding firmware fail, try fallback */387goto fallback;388389return 0;390391coeff_err:392release_firmware(*wmfw_firmware);393kfree(*wmfw_filename);394fallback:395return cs35l41_fallback_firmware_file(cs35l41, wmfw_firmware, wmfw_filename,396coeff_firmware, coeff_filename);397}398399400static void cs35l41_hda_apply_calibration(struct cs35l41_hda *cs35l41)401{402int ret;403404if (!cs35l41->cal_data_valid)405return;406407ret = cs_amp_write_cal_coeffs(&cs35l41->cs_dsp, &cs35l41_calibration_controls,408&cs35l41->cal_data);409if (ret < 0)410dev_warn(cs35l41->dev, "Failed to apply calibration: %d\n", ret);411else412dev_info(cs35l41->dev, "Calibration applied: R0=%d\n", cs35l41->cal_data.calR);413}414415static int cs35l41_read_silicon_uid(struct cs35l41_hda *cs35l41, u64 *uid)416{417u32 tmp;418int ret;419420ret = regmap_read(cs35l41->regmap, CS35L41_DIE_STS2, &tmp);421if (ret) {422dev_err(cs35l41->dev, "Cannot obtain CS35L41_DIE_STS2: %d\n", ret);423return ret;424}425426*uid = tmp;427*uid <<= 32;428429ret = regmap_read(cs35l41->regmap, CS35L41_DIE_STS1, &tmp);430if (ret) {431dev_err(cs35l41->dev, "Cannot obtain CS35L41_DIE_STS1: %d\n", ret);432return ret;433}434435*uid |= tmp;436437dev_dbg(cs35l41->dev, "UniqueID = %#llx\n", *uid);438439return 0;440}441442static int cs35l41_get_calibration(struct cs35l41_hda *cs35l41)443{444u64 silicon_uid;445int ret;446447ret = cs35l41_read_silicon_uid(cs35l41, &silicon_uid);448if (ret < 0)449return ret;450451ret = cs_amp_get_efi_calibration_data(cs35l41->dev, silicon_uid,452cs35l41->index,453&cs35l41->cal_data);454455/* Only return an error status if probe should be aborted */456if ((ret == -ENOENT) || (ret == -EOVERFLOW))457return 0;458459if (ret < 0)460return ret;461462cs35l41->cal_data_valid = true;463464return 0;465}466467468static void cs35l41_set_default_tuning_params(struct cs35l41_hda *cs35l41)469{470cs35l41->tuning_gain = DEFAULT_AMP_GAIN_PCM;471}472473static int cs35l41_read_tuning_params(struct cs35l41_hda *cs35l41, const struct firmware *firmware)474{475struct cs35l41_tuning_params *params;476unsigned int offset = 0;477unsigned int end;478int i;479480params = (void *)&firmware->data[0];481482if (le32_to_cpu(params->size) != firmware->size) {483dev_err(cs35l41->dev, "Wrong Size for Tuning Param file. Expected %d got %zu\n",484le32_to_cpu(params->size), firmware->size);485return -EINVAL;486}487488if (le32_to_cpu(params->version) != 1) {489dev_err(cs35l41->dev, "Unsupported Tuning Param Version: %d\n",490le32_to_cpu(params->version));491return -EINVAL;492}493494if (le32_to_cpu(params->signature) != CS35L41_TUNING_SIG) {495dev_err(cs35l41->dev,496"Mismatched Signature for Tuning Param file. Expected %#x got %#x\n",497CS35L41_TUNING_SIG, le32_to_cpu(params->signature));498return -EINVAL;499}500501end = firmware->size - sizeof(struct cs35l41_tuning_params);502503for (i = 0; i < le32_to_cpu(params->num_entries); i++) {504struct cs35l41_tuning_param *param;505506if ((offset >= end) || ((offset + sizeof(struct cs35l41_tuning_param_hdr)) >= end))507return -EFAULT;508509param = (void *)¶ms->data[offset];510offset += le32_to_cpu(param->hdr.size);511512if (offset > end)513return -EFAULT;514515switch (le32_to_cpu(param->hdr.type)) {516case TUNING_PARAM_GAIN:517cs35l41->tuning_gain = le32_to_cpu(param->gain);518dev_dbg(cs35l41->dev, "Applying Gain: %d\n", cs35l41->tuning_gain);519break;520default:521break;522}523}524525return 0;526}527528static int cs35l41_load_tuning_params(struct cs35l41_hda *cs35l41, char *tuning_filename)529{530const struct firmware *tuning_param_file = NULL;531char *tuning_param_filename = NULL;532int ret;533534ret = cs35l41_request_tuning_param_file(cs35l41, tuning_filename, &tuning_param_file,535&tuning_param_filename, cs35l41->acpi_subsystem_id);536if (ret) {537dev_dbg(cs35l41->dev, "Missing Tuning Param for file: %s: %d\n", tuning_filename,538ret);539return 0;540}541542ret = cs35l41_read_tuning_params(cs35l41, tuning_param_file);543if (ret) {544dev_err(cs35l41->dev, "Error reading Tuning Params from file: %s: %d\n",545tuning_param_filename, ret);546/* Reset to default Tuning Parameters */547cs35l41_set_default_tuning_params(cs35l41);548}549550release_firmware(tuning_param_file);551kfree(tuning_param_filename);552553return ret;554}555556static int cs35l41_init_dsp(struct cs35l41_hda *cs35l41)557{558const struct firmware *coeff_firmware = NULL;559const struct firmware *wmfw_firmware = NULL;560struct cs_dsp *dsp = &cs35l41->cs_dsp;561char *coeff_filename = NULL;562char *wmfw_filename = NULL;563int ret;564565if (!cs35l41->halo_initialized) {566cs35l41_configure_cs_dsp(cs35l41->dev, cs35l41->regmap, dsp);567dsp->client_ops = &client_ops;568569ret = cs_dsp_halo_init(&cs35l41->cs_dsp);570if (ret)571return ret;572cs35l41->halo_initialized = true;573}574575cs35l41_set_default_tuning_params(cs35l41);576577ret = cs35l41_request_firmware_files(cs35l41, &wmfw_firmware, &wmfw_filename,578&coeff_firmware, &coeff_filename);579if (ret < 0)580return ret;581582dev_dbg(cs35l41->dev, "Loading WMFW Firmware: %s\n", wmfw_filename);583if (coeff_filename) {584dev_dbg(cs35l41->dev, "Loading Coefficient File: %s\n", coeff_filename);585ret = cs35l41_load_tuning_params(cs35l41, coeff_filename);586if (ret)587dev_warn(cs35l41->dev, "Unable to load Tuning Parameters: %d\n", ret);588} else {589dev_warn(cs35l41->dev, "No Coefficient File available.\n");590}591592ret = cs_dsp_power_up(dsp, wmfw_firmware, wmfw_filename, coeff_firmware, coeff_filename,593cs35l41_hda_fw_ids[cs35l41->firmware_type]);594if (ret)595goto err;596597cs35l41_hda_apply_calibration(cs35l41);598599err:600if (ret)601cs35l41_set_default_tuning_params(cs35l41);602release_firmware(wmfw_firmware);603release_firmware(coeff_firmware);604kfree(wmfw_filename);605kfree(coeff_filename);606607return ret;608}609610static void cs35l41_shutdown_dsp(struct cs35l41_hda *cs35l41)611{612struct cs_dsp *dsp = &cs35l41->cs_dsp;613614cs35l41_set_default_tuning_params(cs35l41);615cs_dsp_stop(dsp);616cs_dsp_power_down(dsp);617dev_dbg(cs35l41->dev, "Unloaded Firmware\n");618}619620static void cs35l41_remove_dsp(struct cs35l41_hda *cs35l41)621{622struct cs_dsp *dsp = &cs35l41->cs_dsp;623624cancel_work_sync(&cs35l41->fw_load_work);625626guard(mutex)(&cs35l41->fw_mutex);627cs35l41_shutdown_dsp(cs35l41);628cs_dsp_remove(dsp);629cs35l41->halo_initialized = false;630}631632/* Protection release cycle to get the speaker out of Safe-Mode */633static void cs35l41_error_release(struct device *dev, struct regmap *regmap, unsigned int mask)634{635regmap_write(regmap, CS35L41_PROTECT_REL_ERR_IGN, 0);636regmap_set_bits(regmap, CS35L41_PROTECT_REL_ERR_IGN, mask);637regmap_clear_bits(regmap, CS35L41_PROTECT_REL_ERR_IGN, mask);638}639640/* Clear all errors to release safe mode. Global Enable must be cleared first. */641static void cs35l41_irq_release(struct cs35l41_hda *cs35l41)642{643cs35l41_error_release(cs35l41->dev, cs35l41->regmap, cs35l41->irq_errors);644cs35l41->irq_errors = 0;645}646647static void cs35l41_update_mixer(struct cs35l41_hda *cs35l41)648{649struct regmap *reg = cs35l41->regmap;650unsigned int asp_en = 0;651unsigned int dsp1rx2_src = 0;652653regmap_multi_reg_write(reg, cs35l41_hda_config, ARRAY_SIZE(cs35l41_hda_config));654655if (cs35l41->cs_dsp.running) {656asp_en |= CS35L41_ASP_TX1_EN_MASK; // ASP_TX1_EN = 1657regmap_multi_reg_write(reg, cs35l41_hda_config_dsp,658ARRAY_SIZE(cs35l41_hda_config_dsp));659if (cs35l41->hw_cfg.bst_type == CS35L41_INT_BOOST)660regmap_write(reg, CS35L41_DSP1_RX5_SRC, CS35L41_INPUT_SRC_VPMON);661else662regmap_write(reg, CS35L41_DSP1_RX5_SRC, CS35L41_INPUT_SRC_VBSTMON);663} else {664regmap_multi_reg_write(reg, cs35l41_hda_config_no_dsp,665ARRAY_SIZE(cs35l41_hda_config_no_dsp));666}667668if (cs35l41->hw_cfg.spk_pos == CS35L41_CENTER) {669asp_en |= CS35L41_ASP_RX2_EN_MASK; // ASP_RX2_EN = 1670dsp1rx2_src = 0x00000009; // DSP1RX2 SRC = ASPRX2671} else {672dsp1rx2_src = 0x00000008; // DSP1RX2 SRC = ASPRX1673}674675asp_en |= CS35L41_ASP_RX1_EN_MASK; // ASP_RX1_EN = 1676677regmap_write(reg, CS35L41_SP_ENABLES, asp_en);678regmap_write(reg, CS35L41_DSP1_RX1_SRC, 0x00000008); // DSP1RX1 SRC = ASPRX1679regmap_write(reg, CS35L41_DSP1_RX2_SRC, dsp1rx2_src);680}681682static void cs35l41_hda_play_start(struct device *dev)683{684struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);685struct regmap *reg = cs35l41->regmap;686687dev_dbg(dev, "Play (Start)\n");688689if (cs35l41->playback_started) {690dev_dbg(dev, "Playback already started.");691return;692}693694cs35l41->playback_started = true;695696cs35l41_update_mixer(cs35l41);697698if (cs35l41->cs_dsp.running) {699regmap_update_bits(reg, CS35L41_PWR_CTRL2,700CS35L41_VMON_EN_MASK | CS35L41_IMON_EN_MASK,7011 << CS35L41_VMON_EN_SHIFT | 1 << CS35L41_IMON_EN_SHIFT);702cs35l41_set_cspl_mbox_cmd(cs35l41->dev, reg, CSPL_MBOX_CMD_RESUME);703}704regmap_update_bits(reg, CS35L41_PWR_CTRL2, CS35L41_AMP_EN_MASK, 1 << CS35L41_AMP_EN_SHIFT);705if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST)706regmap_write(reg, CS35L41_GPIO1_CTRL1, 0x00008001);707708}709710static void cs35l41_mute(struct device *dev, bool mute)711{712struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);713struct regmap *reg = cs35l41->regmap;714unsigned int amp_gain;715716dev_dbg(dev, "Mute(%d:%d) Playback Started: %d\n", mute, cs35l41->mute_override,717cs35l41->playback_started);718719if (cs35l41->playback_started) {720if (mute || cs35l41->mute_override) {721dev_dbg(dev, "Muting\n");722regmap_multi_reg_write(reg, cs35l41_hda_mute, ARRAY_SIZE(cs35l41_hda_mute));723} else {724dev_dbg(dev, "Unmuting\n");725if (cs35l41->cs_dsp.running) {726dev_dbg(dev, "Using Tuned Gain: %d\n", cs35l41->tuning_gain);727amp_gain = (cs35l41->tuning_gain << CS35L41_AMP_GAIN_PCM_SHIFT) |728(DEFAULT_AMP_GAIN_PDM << CS35L41_AMP_GAIN_PDM_SHIFT);729730/* AMP_HPF_PCM_EN = 1, AMP_VOL_PCM 0.0 dB */731regmap_write(reg, CS35L41_AMP_DIG_VOL_CTRL, 0x00008000);732regmap_write(reg, CS35L41_AMP_GAIN_CTRL, amp_gain);733} else {734regmap_multi_reg_write(reg, cs35l41_hda_unmute,735ARRAY_SIZE(cs35l41_hda_unmute));736}737}738}739}740741static void cs35l41_hda_play_done(struct device *dev)742{743struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);744struct regmap *reg = cs35l41->regmap;745746dev_dbg(dev, "Play (Complete)\n");747748cs35l41_global_enable(dev, reg, cs35l41->hw_cfg.bst_type, 1,749&cs35l41->cs_dsp);750cs35l41_mute(dev, false);751}752753static void cs35l41_hda_pause_start(struct device *dev)754{755struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);756struct regmap *reg = cs35l41->regmap;757758dev_dbg(dev, "Pause (Start)\n");759760cs35l41_mute(dev, true);761cs35l41_global_enable(dev, reg, cs35l41->hw_cfg.bst_type, 0,762&cs35l41->cs_dsp);763}764765static void cs35l41_hda_pause_done(struct device *dev)766{767struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);768struct regmap *reg = cs35l41->regmap;769770dev_dbg(dev, "Pause (Complete)\n");771772regmap_update_bits(reg, CS35L41_PWR_CTRL2, CS35L41_AMP_EN_MASK, 0 << CS35L41_AMP_EN_SHIFT);773if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST)774regmap_write(reg, CS35L41_GPIO1_CTRL1, 0x00000001);775if (cs35l41->cs_dsp.running) {776cs35l41_set_cspl_mbox_cmd(dev, reg, CSPL_MBOX_CMD_PAUSE);777regmap_update_bits(reg, CS35L41_PWR_CTRL2,778CS35L41_VMON_EN_MASK | CS35L41_IMON_EN_MASK,7790 << CS35L41_VMON_EN_SHIFT | 0 << CS35L41_IMON_EN_SHIFT);780}781cs35l41_irq_release(cs35l41);782cs35l41->playback_started = false;783}784785static void cs35l41_hda_pre_playback_hook(struct device *dev, int action)786{787struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);788789switch (action) {790case HDA_GEN_PCM_ACT_CLEANUP:791scoped_guard(mutex, &cs35l41->fw_mutex) {792cs35l41_hda_pause_start(dev);793}794break;795default:796break;797}798}799static void cs35l41_hda_playback_hook(struct device *dev, int action)800{801struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);802803switch (action) {804case HDA_GEN_PCM_ACT_OPEN:805/*806* All amps must be resumed before we can start playing back.807* This ensures, for external boost, that all amps are in AMP_SAFE mode.808* Do this in HDA_GEN_PCM_ACT_OPEN, since this is run prior to any of the809* other actions.810*/811pm_runtime_get_sync(dev);812break;813case HDA_GEN_PCM_ACT_PREPARE:814scoped_guard(mutex, &cs35l41->fw_mutex) {815cs35l41_hda_play_start(dev);816}817break;818case HDA_GEN_PCM_ACT_CLEANUP:819scoped_guard(mutex, &cs35l41->fw_mutex) {820cs35l41_hda_pause_done(dev);821}822break;823case HDA_GEN_PCM_ACT_CLOSE:824scoped_guard(mutex, &cs35l41->fw_mutex) {825if (!cs35l41->cs_dsp.running && cs35l41->request_fw_load &&826!cs35l41->fw_request_ongoing) {827dev_info(dev, "Requesting Firmware Load after HDA_GEN_PCM_ACT_CLOSE\n");828cs35l41->fw_request_ongoing = true;829schedule_work(&cs35l41->fw_load_work);830}831}832833/*834* Playback must be finished for all amps before we start runtime suspend.835* This ensures no amps are playing back when we start putting them to sleep.836*/837pm_runtime_put_autosuspend(dev);838break;839default:840break;841}842}843844static void cs35l41_hda_post_playback_hook(struct device *dev, int action)845{846struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);847848switch (action) {849case HDA_GEN_PCM_ACT_PREPARE:850scoped_guard(mutex, &cs35l41->fw_mutex) {851cs35l41_hda_play_done(dev);852}853break;854default:855break;856}857}858859static int cs35l41_hda_channel_map(struct cs35l41_hda *cs35l41)860{861unsigned int tx_num = 0;862unsigned int *tx_slot = NULL;863unsigned int rx_num;864unsigned int *rx_slot;865unsigned int mono = 0;866867if (!cs35l41->amp_name) {868if (cs35l41->hw_cfg.spk_pos >= ARRAY_SIZE(channel_name))869return -EINVAL;870871cs35l41->amp_name = devm_kasprintf(cs35l41->dev, GFP_KERNEL, "%c%d",872channel_name[cs35l41->hw_cfg.spk_pos],873cs35l41->channel_index);874if (!cs35l41->amp_name)875return -ENOMEM;876}877878rx_num = 1;879if (cs35l41->hw_cfg.spk_pos == CS35L41_CENTER)880rx_slot = &mono;881else882rx_slot = &cs35l41->hw_cfg.spk_pos;883884return cs35l41_set_channels(cs35l41->dev, cs35l41->regmap, tx_num, tx_slot, rx_num,885rx_slot);886}887888static int cs35l41_verify_id(struct cs35l41_hda *cs35l41, unsigned int *regid, unsigned int *reg_revid)889{890unsigned int mtl_revid, chipid;891int ret;892893ret = regmap_read(cs35l41->regmap, CS35L41_DEVID, regid);894if (ret) {895dev_err_probe(cs35l41->dev, ret, "Get Device ID failed\n");896return ret;897}898899ret = regmap_read(cs35l41->regmap, CS35L41_REVID, reg_revid);900if (ret) {901dev_err_probe(cs35l41->dev, ret, "Get Revision ID failed\n");902return ret;903}904905mtl_revid = *reg_revid & CS35L41_MTLREVID_MASK;906907chipid = (mtl_revid % 2) ? CS35L41R_CHIP_ID : CS35L41_CHIP_ID;908if (*regid != chipid) {909dev_err(cs35l41->dev, "CS35L41 Device ID (%X). Expected ID %X\n", *regid, chipid);910return -ENODEV;911}912913return 0;914}915916static int cs35l41_ready_for_reset(struct cs35l41_hda *cs35l41)917{918guard(mutex)(&cs35l41->fw_mutex);919if (cs35l41->cs_dsp.running) {920cs35l41->cs_dsp.running = false;921cs35l41->cs_dsp.booted = false;922}923regcache_mark_dirty(cs35l41->regmap);924925return 0;926}927928static int cs35l41_system_suspend_prep(struct device *dev)929{930struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);931932dev_dbg(cs35l41->dev, "System Suspend Prepare\n");933934if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST_NO_VSPK_SWITCH) {935dev_err_once(cs35l41->dev, "System Suspend not supported\n");936return 0; /* don't block the whole system suspend */937}938939guard(mutex)(&cs35l41->fw_mutex);940if (cs35l41->playback_started)941cs35l41_hda_pause_start(dev);942943return 0;944}945946static int cs35l41_system_suspend(struct device *dev)947{948struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);949int ret;950951dev_dbg(cs35l41->dev, "System Suspend\n");952953if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST_NO_VSPK_SWITCH) {954dev_err_once(cs35l41->dev, "System Suspend not supported\n");955return 0; /* don't block the whole system suspend */956}957958scoped_guard(mutex, &cs35l41->fw_mutex) {959if (cs35l41->playback_started)960cs35l41_hda_pause_done(dev);961}962963ret = pm_runtime_force_suspend(dev);964if (ret) {965dev_err(dev, "System Suspend Failed, unable to runtime suspend: %d\n", ret);966return ret;967}968969/* Shutdown DSP before system suspend */970ret = cs35l41_ready_for_reset(cs35l41);971if (ret)972dev_err(dev, "System Suspend Failed, not ready for Reset: %d\n", ret);973974if (cs35l41->reset_gpio) {975dev_info(cs35l41->dev, "Asserting Reset\n");976gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);977usleep_range(2000, 2100);978}979980dev_dbg(cs35l41->dev, "System Suspended\n");981982return ret;983}984985static int cs35l41_wait_boot_done(struct cs35l41_hda *cs35l41)986{987unsigned int int_status;988int ret;989990ret = regmap_read_poll_timeout(cs35l41->regmap, CS35L41_IRQ1_STATUS4, int_status,991int_status & CS35L41_OTP_BOOT_DONE, 1000, 100000);992if (ret) {993dev_err(cs35l41->dev, "Failed waiting for OTP_BOOT_DONE\n");994return ret;995}996997ret = regmap_read(cs35l41->regmap, CS35L41_IRQ1_STATUS3, &int_status);998if (ret || (int_status & CS35L41_OTP_BOOT_ERR)) {999dev_err(cs35l41->dev, "OTP Boot status %x error\n",1000int_status & CS35L41_OTP_BOOT_ERR);1001if (!ret)1002ret = -EIO;1003return ret;1004}10051006return 0;1007}10081009static int cs35l41_system_resume(struct device *dev)1010{1011struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);1012int ret;10131014dev_dbg(cs35l41->dev, "System Resume\n");10151016if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST_NO_VSPK_SWITCH) {1017dev_err_once(cs35l41->dev, "System Resume not supported\n");1018return 0; /* don't block the whole system resume */1019}10201021if (cs35l41->reset_gpio) {1022gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);1023usleep_range(2000, 2100);1024gpiod_set_value_cansleep(cs35l41->reset_gpio, 1);1025}10261027usleep_range(2000, 2100);10281029regcache_cache_only(cs35l41->regmap, false);10301031regmap_write(cs35l41->regmap, CS35L41_SFT_RESET, CS35L41_SOFTWARE_RESET);1032usleep_range(2000, 2100);10331034ret = cs35l41_wait_boot_done(cs35l41);1035if (ret)1036return ret;10371038regcache_cache_only(cs35l41->regmap, true);10391040ret = pm_runtime_force_resume(dev);1041if (ret) {1042dev_err(dev, "System Resume Failed: Unable to runtime resume: %d\n", ret);1043return ret;1044}10451046guard(mutex)(&cs35l41->fw_mutex);10471048if (cs35l41->request_fw_load && !cs35l41->fw_request_ongoing) {1049cs35l41->fw_request_ongoing = true;1050schedule_work(&cs35l41->fw_load_work);1051}10521053return ret;1054}10551056static int cs35l41_runtime_idle(struct device *dev)1057{1058struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);10591060if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST_NO_VSPK_SWITCH)1061return -EBUSY; /* suspend not supported yet on this model */1062return 0;1063}10641065static int cs35l41_runtime_suspend(struct device *dev)1066{1067struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);1068int ret;10691070dev_dbg(cs35l41->dev, "Runtime Suspend\n");10711072if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST_NO_VSPK_SWITCH) {1073dev_dbg(cs35l41->dev, "Runtime Suspend not supported\n");1074return 0;1075}10761077guard(mutex)(&cs35l41->fw_mutex);10781079if (cs35l41->cs_dsp.running) {1080ret = cs35l41_enter_hibernate(cs35l41->dev, cs35l41->regmap,1081cs35l41->hw_cfg.bst_type);1082if (ret)1083return ret;1084} else {1085cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type);1086}10871088regcache_cache_only(cs35l41->regmap, true);1089regcache_mark_dirty(cs35l41->regmap);10901091return 0;1092}10931094static int cs35l41_runtime_resume(struct device *dev)1095{1096struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);1097unsigned int regid, reg_revid;1098int ret;10991100dev_dbg(cs35l41->dev, "Runtime Resume\n");11011102if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST_NO_VSPK_SWITCH) {1103dev_dbg(cs35l41->dev, "Runtime Resume not supported\n");1104return 0;1105}11061107guard(mutex)(&cs35l41->fw_mutex);11081109regcache_cache_only(cs35l41->regmap, false);11101111if (cs35l41->cs_dsp.running) {1112ret = cs35l41_exit_hibernate(cs35l41->dev, cs35l41->regmap);1113if (ret) {1114dev_warn(cs35l41->dev, "Unable to exit Hibernate.");1115return ret;1116}1117}11181119ret = cs35l41_verify_id(cs35l41, ®id, ®_revid);1120if (ret)1121return ret;11221123/* Test key needs to be unlocked to allow the OTP settings to re-apply */1124cs35l41_test_key_unlock(cs35l41->dev, cs35l41->regmap);1125ret = regcache_sync(cs35l41->regmap);1126cs35l41_test_key_lock(cs35l41->dev, cs35l41->regmap);1127if (ret) {1128dev_err(cs35l41->dev, "Failed to restore register cache: %d\n", ret);1129return ret;1130}11311132if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST)1133cs35l41_init_boost(cs35l41->dev, cs35l41->regmap, &cs35l41->hw_cfg);11341135dev_dbg(cs35l41->dev, "CS35L41 Resumed (%x), Revision: %02X\n", regid, reg_revid);11361137return 0;1138}11391140static int cs35l41_hda_read_ctl(struct cs_dsp *dsp, const char *name, int type,1141unsigned int alg, void *buf, size_t len)1142{1143guard(mutex)(&dsp->pwr_lock);1144return cs_dsp_coeff_read_ctrl(cs_dsp_get_ctl(dsp, name, type, alg), 0, buf, len);1145}11461147static int cs35l41_smart_amp(struct cs35l41_hda *cs35l41)1148{1149unsigned int fw_status;1150__be32 halo_sts;1151int ret;11521153if (cs35l41->bypass_fw) {1154dev_warn(cs35l41->dev, "Bypassing Firmware.\n");1155return 0;1156}11571158ret = cs35l41_init_dsp(cs35l41);1159if (ret) {1160dev_warn(cs35l41->dev, "Cannot Initialize Firmware. Error: %d\n", ret);1161goto clean_dsp;1162}11631164ret = cs35l41_write_fs_errata(cs35l41->dev, cs35l41->regmap);1165if (ret) {1166dev_err(cs35l41->dev, "Cannot Write FS Errata: %d\n", ret);1167goto clean_dsp;1168}11691170ret = cs_dsp_run(&cs35l41->cs_dsp);1171if (ret) {1172dev_err(cs35l41->dev, "Fail to start dsp: %d\n", ret);1173goto clean_dsp;1174}11751176ret = read_poll_timeout(cs35l41_hda_read_ctl, ret,1177be32_to_cpu(halo_sts) == HALO_STATE_CODE_RUN,11781000, 15000, false, &cs35l41->cs_dsp, HALO_STATE_DSP_CTL_NAME,1179HALO_STATE_DSP_CTL_TYPE, HALO_STATE_DSP_CTL_ALG,1180&halo_sts, sizeof(halo_sts));11811182if (ret) {1183dev_err(cs35l41->dev, "Timeout waiting for HALO Core to start. State: %u\n",1184halo_sts);1185goto clean_dsp;1186}11871188ret = regmap_read(cs35l41->regmap, CS35L41_DSP_MBOX_2, &fw_status);1189if (ret < 0) {1190dev_err(cs35l41->dev,1191"Failed to read firmware status: %d\n", ret);1192goto clean_dsp;1193}11941195switch (fw_status) {1196case CSPL_MBOX_STS_RUNNING:1197case CSPL_MBOX_STS_PAUSED:1198break;1199default:1200dev_err(cs35l41->dev, "Firmware status is invalid: %u\n",1201fw_status);1202ret = -EINVAL;1203goto clean_dsp;1204}12051206ret = cs35l41_set_cspl_mbox_cmd(cs35l41->dev, cs35l41->regmap, CSPL_MBOX_CMD_PAUSE);1207if (ret) {1208dev_err(cs35l41->dev, "Error waiting for DSP to pause: %u\n", ret);1209goto clean_dsp;1210}12111212dev_info(cs35l41->dev, "Firmware Loaded - Type: %s, Gain: %d\n",1213cs35l41_hda_fw_ids[cs35l41->firmware_type], cs35l41->tuning_gain);12141215return 0;12161217clean_dsp:1218cs35l41_shutdown_dsp(cs35l41);1219return ret;1220}12211222static void cs35l41_load_firmware(struct cs35l41_hda *cs35l41, bool load)1223{1224if (cs35l41->cs_dsp.running && !load) {1225dev_dbg(cs35l41->dev, "Unloading Firmware\n");1226cs35l41_shutdown_dsp(cs35l41);1227} else if (!cs35l41->cs_dsp.running && load) {1228dev_dbg(cs35l41->dev, "Loading Firmware\n");1229cs35l41_smart_amp(cs35l41);1230} else {1231dev_dbg(cs35l41->dev, "Unable to Load firmware.\n");1232}1233}12341235static int cs35l41_fw_load_ctl_get(struct snd_kcontrol *kcontrol,1236struct snd_ctl_elem_value *ucontrol)1237{1238struct cs35l41_hda *cs35l41 = snd_kcontrol_chip(kcontrol);12391240ucontrol->value.integer.value[0] = cs35l41->request_fw_load;1241return 0;1242}12431244static int cs35l41_mute_override_ctl_get(struct snd_kcontrol *kcontrol,1245struct snd_ctl_elem_value *ucontrol)1246{1247struct cs35l41_hda *cs35l41 = snd_kcontrol_chip(kcontrol);12481249ucontrol->value.integer.value[0] = cs35l41->mute_override;1250return 0;1251}12521253static void cs35l41_fw_load_work(struct work_struct *work)1254{1255struct cs35l41_hda *cs35l41 = container_of(work, struct cs35l41_hda, fw_load_work);12561257pm_runtime_get_sync(cs35l41->dev);12581259scoped_guard(mutex, &cs35l41->fw_mutex) {1260/* Recheck if playback is ongoing, mutex will block playback during firmware loading */1261if (cs35l41->playback_started)1262dev_err(cs35l41->dev, "Cannot Load/Unload firmware during Playback. Retrying...\n");1263else1264cs35l41_load_firmware(cs35l41, cs35l41->request_fw_load);12651266cs35l41->fw_request_ongoing = false;1267}12681269pm_runtime_put_autosuspend(cs35l41->dev);1270}12711272static int cs35l41_fw_load_ctl_put(struct snd_kcontrol *kcontrol,1273struct snd_ctl_elem_value *ucontrol)1274{1275struct cs35l41_hda *cs35l41 = snd_kcontrol_chip(kcontrol);12761277if (cs35l41->request_fw_load == ucontrol->value.integer.value[0])1278return 0;12791280if (cs35l41->fw_request_ongoing) {1281dev_dbg(cs35l41->dev, "Existing request not complete\n");1282return -EBUSY;1283}12841285/* Check if playback is ongoing when initial request is made */1286if (cs35l41->playback_started) {1287dev_err(cs35l41->dev, "Cannot Load/Unload firmware during Playback\n");1288return -EBUSY;1289}12901291cs35l41->fw_request_ongoing = true;1292cs35l41->request_fw_load = ucontrol->value.integer.value[0];1293schedule_work(&cs35l41->fw_load_work);12941295return 1;1296}12971298static int cs35l41_fw_type_ctl_get(struct snd_kcontrol *kcontrol,1299struct snd_ctl_elem_value *ucontrol)1300{1301struct cs35l41_hda *cs35l41 = snd_kcontrol_chip(kcontrol);13021303ucontrol->value.enumerated.item[0] = cs35l41->firmware_type;13041305return 0;1306}13071308static int cs35l41_fw_type_ctl_put(struct snd_kcontrol *kcontrol,1309struct snd_ctl_elem_value *ucontrol)1310{1311struct cs35l41_hda *cs35l41 = snd_kcontrol_chip(kcontrol);13121313if (ucontrol->value.enumerated.item[0] < CS35L41_HDA_NUM_FW) {1314if (cs35l41->firmware_type != ucontrol->value.enumerated.item[0]) {1315cs35l41->firmware_type = ucontrol->value.enumerated.item[0];1316return 1;1317} else {1318return 0;1319}1320}13211322return -EINVAL;1323}13241325static int cs35l41_fw_type_ctl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)1326{1327return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(cs35l41_hda_fw_ids), cs35l41_hda_fw_ids);1328}13291330static int cs35l41_create_controls(struct cs35l41_hda *cs35l41)1331{1332char fw_type_ctl_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];1333char fw_load_ctl_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];1334char mute_override_ctl_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];1335struct snd_kcontrol_new fw_type_ctl = {1336.name = fw_type_ctl_name,1337.iface = SNDRV_CTL_ELEM_IFACE_CARD,1338.info = cs35l41_fw_type_ctl_info,1339.get = cs35l41_fw_type_ctl_get,1340.put = cs35l41_fw_type_ctl_put,1341};1342struct snd_kcontrol_new fw_load_ctl = {1343.name = fw_load_ctl_name,1344.iface = SNDRV_CTL_ELEM_IFACE_CARD,1345.info = snd_ctl_boolean_mono_info,1346.get = cs35l41_fw_load_ctl_get,1347.put = cs35l41_fw_load_ctl_put,1348};1349struct snd_kcontrol_new mute_override_ctl = {1350.name = mute_override_ctl_name,1351.iface = SNDRV_CTL_ELEM_IFACE_CARD,1352.info = snd_ctl_boolean_mono_info,1353.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,1354.get = cs35l41_mute_override_ctl_get,1355};1356int ret;13571358scnprintf(fw_type_ctl_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s DSP1 Firmware Type",1359cs35l41->amp_name);1360scnprintf(fw_load_ctl_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s DSP1 Firmware Load",1361cs35l41->amp_name);1362scnprintf(mute_override_ctl_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s Forced Mute Status",1363cs35l41->amp_name);13641365ret = snd_ctl_add(cs35l41->codec->card, snd_ctl_new1(&fw_type_ctl, cs35l41));1366if (ret) {1367dev_err(cs35l41->dev, "Failed to add KControl %s = %d\n", fw_type_ctl.name, ret);1368return ret;1369}13701371dev_dbg(cs35l41->dev, "Added Control %s\n", fw_type_ctl.name);13721373ret = snd_ctl_add(cs35l41->codec->card, snd_ctl_new1(&fw_load_ctl, cs35l41));1374if (ret) {1375dev_err(cs35l41->dev, "Failed to add KControl %s = %d\n", fw_load_ctl.name, ret);1376return ret;1377}13781379dev_dbg(cs35l41->dev, "Added Control %s\n", fw_load_ctl.name);13801381ret = snd_ctl_add(cs35l41->codec->card, snd_ctl_new1(&mute_override_ctl, cs35l41));1382if (ret) {1383dev_err(cs35l41->dev, "Failed to add KControl %s = %d\n", mute_override_ctl.name,1384ret);1385return ret;1386}13871388dev_dbg(cs35l41->dev, "Added Control %s\n", mute_override_ctl.name);13891390return 0;1391}13921393static bool cs35l41_dsm_supported(acpi_handle handle, unsigned int commands)1394{1395guid_t guid;13961397guid_parse(CS35L41_UUID, &guid);13981399return acpi_check_dsm(handle, &guid, 0, BIT(commands));1400}14011402static int cs35l41_get_acpi_mute_state(struct cs35l41_hda *cs35l41, acpi_handle handle)1403{1404guid_t guid;1405union acpi_object *ret;1406int mute = -ENODEV;14071408guid_parse(CS35L41_UUID, &guid);14091410if (cs35l41_dsm_supported(handle, CS35L41_DSM_GET_MUTE)) {1411ret = acpi_evaluate_dsm(handle, &guid, 0, CS35L41_DSM_GET_MUTE, NULL);1412mute = *ret->buffer.pointer;1413dev_dbg(cs35l41->dev, "CS35L41_DSM_GET_MUTE: %d\n", mute);1414}14151416dev_dbg(cs35l41->dev, "%s: %d\n", __func__, mute);14171418return mute;1419}14201421static void cs35l41_acpi_device_notify(acpi_handle handle, u32 event, struct device *dev)1422{1423struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);1424int mute;14251426if (event != CS35L41_NOTIFY_EVENT)1427return;14281429mute = cs35l41_get_acpi_mute_state(cs35l41, handle);1430if (mute < 0) {1431dev_warn(cs35l41->dev, "Unable to retrieve mute state: %d\n", mute);1432return;1433}14341435dev_dbg(cs35l41->dev, "Requesting mute value: %d\n", mute);1436cs35l41->mute_override = (mute > 0);1437cs35l41_mute(cs35l41->dev, cs35l41->mute_override);1438}14391440static int cs35l41_hda_bind(struct device *dev, struct device *master, void *master_data)1441{1442struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);1443struct hda_component_parent *parent = master_data;1444struct hda_component *comp;1445unsigned int sleep_flags;1446int ret = 0;14471448comp = hda_component_from_index(parent, cs35l41->index);1449if (!comp)1450return -EINVAL;14511452if (comp->dev)1453return -EBUSY;14541455pm_runtime_get_sync(dev);14561457mutex_lock(&cs35l41->fw_mutex);14581459comp->dev = dev;1460cs35l41->codec = parent->codec;1461if (!cs35l41->acpi_subsystem_id)1462cs35l41->acpi_subsystem_id = kasprintf(GFP_KERNEL, "%.8x",1463cs35l41->codec->core.subsystem_id);14641465strscpy(comp->name, dev_name(dev), sizeof(comp->name));14661467cs35l41->firmware_type = CS35L41_HDA_FW_SPK_PROT;14681469if (firmware_autostart) {1470dev_dbg(cs35l41->dev, "Firmware Autostart.\n");1471cs35l41->request_fw_load = true;1472if (cs35l41_smart_amp(cs35l41) < 0)1473dev_warn(cs35l41->dev, "Cannot Run Firmware, reverting to dsp bypass...\n");1474} else {1475dev_dbg(cs35l41->dev, "Firmware Autostart is disabled.\n");1476}14771478ret = cs35l41_create_controls(cs35l41);14791480comp->playback_hook = cs35l41_hda_playback_hook;1481comp->pre_playback_hook = cs35l41_hda_pre_playback_hook;1482comp->post_playback_hook = cs35l41_hda_post_playback_hook;1483comp->acpi_notify = cs35l41_acpi_device_notify;1484comp->adev = cs35l41->dacpi;14851486comp->acpi_notifications_supported = cs35l41_dsm_supported(acpi_device_handle(comp->adev),1487CS35L41_DSM_GET_MUTE);14881489cs35l41->mute_override = cs35l41_get_acpi_mute_state(cs35l41,1490acpi_device_handle(cs35l41->dacpi)) > 0;14911492mutex_unlock(&cs35l41->fw_mutex);14931494sleep_flags = lock_system_sleep();1495if (!device_link_add(&cs35l41->codec->core.dev, cs35l41->dev, DL_FLAG_STATELESS))1496dev_warn(dev, "Unable to create device link\n");1497unlock_system_sleep(sleep_flags);14981499pm_runtime_put_autosuspend(dev);15001501dev_info(cs35l41->dev,1502"CS35L41 Bound - SSID: %s, BST: %d, VSPK: %d, CH: %c, FW EN: %d, SPKID: %d\n",1503cs35l41->acpi_subsystem_id, cs35l41->hw_cfg.bst_type,1504cs35l41->hw_cfg.gpio1.func == CS35l41_VSPK_SWITCH,1505channel_name[cs35l41->hw_cfg.spk_pos],1506cs35l41->cs_dsp.running, cs35l41->speaker_id);15071508return ret;1509}15101511static void cs35l41_hda_unbind(struct device *dev, struct device *master, void *master_data)1512{1513struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);1514struct hda_component_parent *parent = master_data;1515struct hda_component *comp;1516unsigned int sleep_flags;15171518comp = hda_component_from_index(parent, cs35l41->index);1519if (!comp)1520return;15211522if (comp->dev == dev) {1523sleep_flags = lock_system_sleep();1524device_link_remove(&cs35l41->codec->core.dev, cs35l41->dev);1525unlock_system_sleep(sleep_flags);1526memset(comp, 0, sizeof(*comp));1527}1528}15291530static const struct component_ops cs35l41_hda_comp_ops = {1531.bind = cs35l41_hda_bind,1532.unbind = cs35l41_hda_unbind,1533};15341535static irqreturn_t cs35l41_bst_short_err(int irq, void *data)1536{1537struct cs35l41_hda *cs35l41 = data;15381539dev_crit_ratelimited(cs35l41->dev, "LBST Error\n");1540set_bit(CS35L41_BST_SHORT_ERR_RLS_SHIFT, &cs35l41->irq_errors);15411542return IRQ_HANDLED;1543}15441545static irqreturn_t cs35l41_bst_dcm_uvp_err(int irq, void *data)1546{1547struct cs35l41_hda *cs35l41 = data;15481549dev_crit_ratelimited(cs35l41->dev, "DCM VBST Under Voltage Error\n");1550set_bit(CS35L41_BST_UVP_ERR_RLS_SHIFT, &cs35l41->irq_errors);15511552return IRQ_HANDLED;1553}15541555static irqreturn_t cs35l41_bst_ovp_err(int irq, void *data)1556{1557struct cs35l41_hda *cs35l41 = data;15581559dev_crit_ratelimited(cs35l41->dev, "VBST Over Voltage error\n");1560set_bit(CS35L41_BST_OVP_ERR_RLS_SHIFT, &cs35l41->irq_errors);15611562return IRQ_HANDLED;1563}15641565static irqreturn_t cs35l41_temp_err(int irq, void *data)1566{1567struct cs35l41_hda *cs35l41 = data;15681569dev_crit_ratelimited(cs35l41->dev, "Over temperature error\n");1570set_bit(CS35L41_TEMP_ERR_RLS_SHIFT, &cs35l41->irq_errors);15711572return IRQ_HANDLED;1573}15741575static irqreturn_t cs35l41_temp_warn(int irq, void *data)1576{1577struct cs35l41_hda *cs35l41 = data;15781579dev_crit_ratelimited(cs35l41->dev, "Over temperature warning\n");1580set_bit(CS35L41_TEMP_WARN_ERR_RLS_SHIFT, &cs35l41->irq_errors);15811582return IRQ_HANDLED;1583}15841585static irqreturn_t cs35l41_amp_short(int irq, void *data)1586{1587struct cs35l41_hda *cs35l41 = data;15881589dev_crit_ratelimited(cs35l41->dev, "Amp short error\n");1590set_bit(CS35L41_AMP_SHORT_ERR_RLS_SHIFT, &cs35l41->irq_errors);15911592return IRQ_HANDLED;1593}15941595static const struct cs35l41_irq cs35l41_irqs[] = {1596CS35L41_IRQ(BST_OVP_ERR, "Boost Overvoltage Error", cs35l41_bst_ovp_err),1597CS35L41_IRQ(BST_DCM_UVP_ERR, "Boost Undervoltage Error", cs35l41_bst_dcm_uvp_err),1598CS35L41_IRQ(BST_SHORT_ERR, "Boost Inductor Short Error", cs35l41_bst_short_err),1599CS35L41_IRQ(TEMP_WARN, "Temperature Warning", cs35l41_temp_warn),1600CS35L41_IRQ(TEMP_ERR, "Temperature Error", cs35l41_temp_err),1601CS35L41_IRQ(AMP_SHORT_ERR, "Amp Short", cs35l41_amp_short),1602};16031604static const struct regmap_irq cs35l41_reg_irqs[] = {1605CS35L41_REG_IRQ(IRQ1_STATUS1, BST_OVP_ERR),1606CS35L41_REG_IRQ(IRQ1_STATUS1, BST_DCM_UVP_ERR),1607CS35L41_REG_IRQ(IRQ1_STATUS1, BST_SHORT_ERR),1608CS35L41_REG_IRQ(IRQ1_STATUS1, TEMP_WARN),1609CS35L41_REG_IRQ(IRQ1_STATUS1, TEMP_ERR),1610CS35L41_REG_IRQ(IRQ1_STATUS1, AMP_SHORT_ERR),1611};16121613static const struct regmap_irq_chip cs35l41_regmap_irq_chip = {1614.name = "cs35l41 IRQ1 Controller",1615.status_base = CS35L41_IRQ1_STATUS1,1616.mask_base = CS35L41_IRQ1_MASK1,1617.ack_base = CS35L41_IRQ1_STATUS1,1618.num_regs = 4,1619.irqs = cs35l41_reg_irqs,1620.num_irqs = ARRAY_SIZE(cs35l41_reg_irqs),1621.runtime_pm = true,1622};16231624static void cs35l41_configure_interrupt(struct cs35l41_hda *cs35l41, int irq_pol)1625{1626int irq;1627int ret;1628int i;16291630if (!cs35l41->irq) {1631dev_warn(cs35l41->dev, "No Interrupt Found");1632goto err;1633}16341635ret = devm_regmap_add_irq_chip(cs35l41->dev, cs35l41->regmap, cs35l41->irq,1636IRQF_ONESHOT | IRQF_SHARED | irq_pol,16370, &cs35l41_regmap_irq_chip, &cs35l41->irq_data);1638if (ret) {1639dev_dbg(cs35l41->dev, "Unable to add IRQ Chip: %d.", ret);1640goto err;1641}16421643for (i = 0; i < ARRAY_SIZE(cs35l41_irqs); i++) {1644irq = regmap_irq_get_virq(cs35l41->irq_data, cs35l41_irqs[i].irq);1645if (irq < 0) {1646ret = irq;1647dev_dbg(cs35l41->dev, "Unable to map IRQ %s: %d.", cs35l41_irqs[i].name,1648ret);1649goto err;1650}16511652ret = devm_request_threaded_irq(cs35l41->dev, irq, NULL,1653cs35l41_irqs[i].handler,1654IRQF_ONESHOT | IRQF_SHARED | irq_pol,1655cs35l41_irqs[i].name, cs35l41);1656if (ret) {1657dev_dbg(cs35l41->dev, "Unable to allocate IRQ %s:: %d.",1658cs35l41_irqs[i].name, ret);1659goto err;1660}1661}1662return;1663err:1664dev_warn(cs35l41->dev,1665"IRQ Config Failed. Amp errors may not be recoverable without reboot.");1666}16671668static int cs35l41_hda_apply_properties(struct cs35l41_hda *cs35l41)1669{1670struct cs35l41_hw_cfg *hw_cfg = &cs35l41->hw_cfg;1671bool using_irq = false;1672int irq_pol;1673int ret;16741675if (!cs35l41->hw_cfg.valid)1676return -EINVAL;16771678ret = cs35l41_init_boost(cs35l41->dev, cs35l41->regmap, hw_cfg);1679if (ret)1680return ret;16811682if (hw_cfg->gpio1.valid) {1683switch (hw_cfg->gpio1.func) {1684case CS35L41_NOT_USED:1685break;1686case CS35l41_VSPK_SWITCH:1687hw_cfg->gpio1.func = CS35L41_GPIO1_GPIO;1688hw_cfg->gpio1.out_en = true;1689break;1690case CS35l41_SYNC:1691hw_cfg->gpio1.func = CS35L41_GPIO1_MDSYNC;1692break;1693default:1694dev_err(cs35l41->dev, "Invalid function %d for GPIO1\n",1695hw_cfg->gpio1.func);1696return -EINVAL;1697}1698}16991700if (hw_cfg->gpio2.valid) {1701switch (hw_cfg->gpio2.func) {1702case CS35L41_NOT_USED:1703break;1704case CS35L41_INTERRUPT:1705using_irq = true;1706hw_cfg->gpio2.func = CS35L41_GPIO2_INT_OPEN_DRAIN;1707break;1708default:1709dev_err(cs35l41->dev, "Invalid GPIO2 function %d\n", hw_cfg->gpio2.func);1710return -EINVAL;1711}1712}17131714irq_pol = cs35l41_gpio_config(cs35l41->regmap, hw_cfg);17151716if (using_irq)1717cs35l41_configure_interrupt(cs35l41, irq_pol);17181719return cs35l41_hda_channel_map(cs35l41);1720}17211722int cs35l41_get_speaker_id(struct device *dev, int amp_index, int num_amps, int fixed_gpio_id)1723{1724struct gpio_desc *speaker_id_desc;1725int speaker_id = -ENODEV;17261727if (fixed_gpio_id >= 0) {1728dev_dbg(dev, "Found Fixed Speaker ID GPIO (index = %d)\n", fixed_gpio_id);1729speaker_id_desc = gpiod_get_index(dev, NULL, fixed_gpio_id, GPIOD_IN);1730if (IS_ERR(speaker_id_desc)) {1731speaker_id = PTR_ERR(speaker_id_desc);1732return speaker_id;1733}1734speaker_id = gpiod_get_value_cansleep(speaker_id_desc);1735gpiod_put(speaker_id_desc);1736dev_dbg(dev, "Speaker ID = %d\n", speaker_id);1737} else {1738int base_index;1739int gpios_per_amp;1740int count;1741int tmp;1742int i;17431744count = gpiod_count(dev, "spk-id");1745if (count > 0) {1746speaker_id = 0;1747gpios_per_amp = count / num_amps;1748base_index = gpios_per_amp * amp_index;17491750if (count % num_amps)1751return -EINVAL;17521753dev_dbg(dev, "Found %d Speaker ID GPIOs per Amp\n", gpios_per_amp);17541755for (i = 0; i < gpios_per_amp; i++) {1756speaker_id_desc = gpiod_get_index(dev, "spk-id", i + base_index,1757GPIOD_IN);1758if (IS_ERR(speaker_id_desc)) {1759speaker_id = PTR_ERR(speaker_id_desc);1760break;1761}1762tmp = gpiod_get_value_cansleep(speaker_id_desc);1763gpiod_put(speaker_id_desc);1764if (tmp < 0) {1765speaker_id = tmp;1766break;1767}1768speaker_id |= tmp << i;1769}1770dev_dbg(dev, "Speaker ID = %d\n", speaker_id);1771}1772}1773return speaker_id;1774}17751776int cs35l41_hda_parse_acpi(struct cs35l41_hda *cs35l41, struct device *physdev, int id)1777{1778struct cs35l41_hw_cfg *hw_cfg = &cs35l41->hw_cfg;1779u32 values[HDA_MAX_COMPONENTS];1780char *property;1781size_t nval;1782int i, ret;17831784property = "cirrus,dev-index";1785ret = device_property_count_u32(physdev, property);1786if (ret <= 0)1787goto err;17881789if (ret > ARRAY_SIZE(values)) {1790ret = -EINVAL;1791goto err;1792}1793nval = ret;17941795ret = device_property_read_u32_array(physdev, property, values, nval);1796if (ret)1797goto err;17981799cs35l41->index = -1;1800for (i = 0; i < nval; i++) {1801if (values[i] == id) {1802cs35l41->index = i;1803break;1804}1805}1806if (cs35l41->index == -1) {1807dev_err(cs35l41->dev, "No index found in %s\n", property);1808ret = -ENODEV;1809goto err;1810}18111812/* To use the same release code for all laptop variants we can't use devm_ version of1813* gpiod_get here, as CLSA010* don't have a fully functional bios with an _DSD node1814*/1815cs35l41->reset_gpio = fwnode_gpiod_get_index(acpi_fwnode_handle(cs35l41->dacpi), "reset",1816cs35l41->index, GPIOD_OUT_LOW,1817"cs35l41-reset");18181819property = "cirrus,speaker-position";1820ret = device_property_read_u32_array(physdev, property, values, nval);1821if (ret)1822goto err;1823hw_cfg->spk_pos = values[cs35l41->index];18241825cs35l41->channel_index = 0;1826for (i = 0; i < cs35l41->index; i++)1827if (values[i] == hw_cfg->spk_pos)1828cs35l41->channel_index++;18291830property = "cirrus,gpio1-func";1831ret = device_property_read_u32_array(physdev, property, values, nval);1832if (ret)1833goto err;1834hw_cfg->gpio1.func = values[cs35l41->index];1835hw_cfg->gpio1.valid = true;18361837property = "cirrus,gpio2-func";1838ret = device_property_read_u32_array(physdev, property, values, nval);1839if (ret)1840goto err;1841hw_cfg->gpio2.func = values[cs35l41->index];1842hw_cfg->gpio2.valid = true;18431844property = "cirrus,boost-peak-milliamp";1845ret = device_property_read_u32_array(physdev, property, values, nval);1846if (ret == 0)1847hw_cfg->bst_ipk = values[cs35l41->index];1848else1849hw_cfg->bst_ipk = -1;18501851property = "cirrus,boost-ind-nanohenry";1852ret = device_property_read_u32_array(physdev, property, values, nval);1853if (ret == 0)1854hw_cfg->bst_ind = values[cs35l41->index];1855else1856hw_cfg->bst_ind = -1;18571858property = "cirrus,boost-cap-microfarad";1859ret = device_property_read_u32_array(physdev, property, values, nval);1860if (ret == 0)1861hw_cfg->bst_cap = values[cs35l41->index];1862else1863hw_cfg->bst_cap = -1;18641865cs35l41->speaker_id = cs35l41_get_speaker_id(physdev, cs35l41->index, nval, -1);18661867if (hw_cfg->bst_ind > 0 || hw_cfg->bst_cap > 0 || hw_cfg->bst_ipk > 0)1868hw_cfg->bst_type = CS35L41_INT_BOOST;1869else1870hw_cfg->bst_type = CS35L41_EXT_BOOST;18711872hw_cfg->valid = true;18731874return 0;1875err:1876dev_err(cs35l41->dev, "Failed property %s: %d\n", property, ret);1877hw_cfg->valid = false;1878hw_cfg->gpio1.valid = false;1879hw_cfg->gpio2.valid = false;1880acpi_dev_put(cs35l41->dacpi);18811882return ret;1883}18841885static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, int id)1886{1887struct acpi_device *adev;1888struct device *physdev;1889struct spi_device *spi;1890const char *sub;1891int ret;18921893adev = acpi_dev_get_first_match_dev(hid, NULL, -1);1894if (!adev) {1895dev_err(cs35l41->dev, "Failed to find an ACPI device for %s\n", hid);1896return -ENODEV;1897}18981899cs35l41->dacpi = adev;1900physdev = get_device(acpi_get_first_physical_node(adev));19011902sub = acpi_get_subsystem_id(ACPI_HANDLE(physdev));1903if (IS_ERR(sub))1904sub = NULL;1905cs35l41->acpi_subsystem_id = sub;19061907ret = cs35l41_add_dsd_properties(cs35l41, physdev, id, hid);1908if (!ret) {1909dev_info(cs35l41->dev, "Using extra _DSD properties, bypassing _DSD in ACPI\n");1910goto out;1911}19121913ret = cs35l41_hda_parse_acpi(cs35l41, physdev, id);1914if (ret) {1915put_device(physdev);1916return ret;1917}1918out:1919put_device(physdev);19201921cs35l41->bypass_fw = false;1922if (cs35l41->control_bus == SPI) {1923spi = to_spi_device(cs35l41->dev);1924if (spi->max_speed_hz < CS35L41_MAX_ACCEPTABLE_SPI_SPEED_HZ) {1925dev_warn(cs35l41->dev,1926"SPI speed is too slow to support firmware download: %d Hz.\n",1927spi->max_speed_hz);1928cs35l41->bypass_fw = true;1929}1930}19311932return 0;1933}19341935int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int irq,1936struct regmap *regmap, enum control_bus control_bus)1937{1938unsigned int regid, reg_revid;1939struct cs35l41_hda *cs35l41;1940int ret;19411942BUILD_BUG_ON(ARRAY_SIZE(cs35l41_irqs) != ARRAY_SIZE(cs35l41_reg_irqs));1943BUILD_BUG_ON(ARRAY_SIZE(cs35l41_irqs) != CS35L41_NUM_IRQ);19441945if (IS_ERR(regmap))1946return PTR_ERR(regmap);19471948cs35l41 = devm_kzalloc(dev, sizeof(*cs35l41), GFP_KERNEL);1949if (!cs35l41)1950return -ENOMEM;19511952cs35l41->dev = dev;1953cs35l41->irq = irq;1954cs35l41->regmap = regmap;1955cs35l41->control_bus = control_bus;1956dev_set_drvdata(dev, cs35l41);19571958ret = cs35l41_hda_read_acpi(cs35l41, device_name, id);1959if (ret)1960return dev_err_probe(cs35l41->dev, ret, "Platform not supported\n");19611962if (IS_ERR(cs35l41->reset_gpio)) {1963ret = PTR_ERR(cs35l41->reset_gpio);1964cs35l41->reset_gpio = NULL;1965if (ret == -EBUSY) {1966dev_info(cs35l41->dev, "Reset line busy, assuming shared reset\n");1967} else {1968dev_err_probe(cs35l41->dev, ret, "Failed to get reset GPIO\n");1969goto err;1970}1971}1972if (cs35l41->reset_gpio) {1973gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);1974usleep_range(2000, 2100);1975gpiod_set_value_cansleep(cs35l41->reset_gpio, 1);1976}19771978usleep_range(2000, 2100);1979regmap_write(cs35l41->regmap, CS35L41_SFT_RESET, CS35L41_SOFTWARE_RESET);1980usleep_range(2000, 2100);19811982ret = cs35l41_wait_boot_done(cs35l41);1983if (ret)1984goto err;19851986ret = cs35l41_verify_id(cs35l41, ®id, ®_revid);1987if (ret)1988goto err;19891990ret = cs35l41_test_key_unlock(cs35l41->dev, cs35l41->regmap);1991if (ret)1992goto err;19931994ret = cs35l41_register_errata_patch(cs35l41->dev, cs35l41->regmap, reg_revid);1995if (ret)1996goto err;19971998ret = cs35l41_otp_unpack(cs35l41->dev, cs35l41->regmap);1999if (ret) {2000dev_err_probe(cs35l41->dev, ret, "OTP Unpack failed\n");2001goto err;2002}20032004ret = cs35l41_test_key_lock(cs35l41->dev, cs35l41->regmap);2005if (ret)2006goto err;20072008ret = cs35l41_get_calibration(cs35l41);2009if (ret && ret != -ENOENT)2010goto err;20112012cs35l41_mute(cs35l41->dev, true);20132014INIT_WORK(&cs35l41->fw_load_work, cs35l41_fw_load_work);2015mutex_init(&cs35l41->fw_mutex);20162017pm_runtime_set_autosuspend_delay(cs35l41->dev, 3000);2018pm_runtime_use_autosuspend(cs35l41->dev);2019pm_runtime_set_active(cs35l41->dev);2020pm_runtime_get_noresume(cs35l41->dev);2021pm_runtime_enable(cs35l41->dev);20222023ret = cs35l41_hda_apply_properties(cs35l41);2024if (ret)2025goto err_pm;20262027pm_runtime_put_autosuspend(cs35l41->dev);20282029ret = component_add(cs35l41->dev, &cs35l41_hda_comp_ops);2030if (ret) {2031dev_err_probe(cs35l41->dev, ret, "Register component failed\n");2032goto err_pm;2033}20342035dev_info(cs35l41->dev, "Cirrus Logic CS35L41 (%x), Revision: %02X\n", regid, reg_revid);20362037return 0;20382039err_pm:2040pm_runtime_dont_use_autosuspend(cs35l41->dev);2041pm_runtime_disable(cs35l41->dev);2042pm_runtime_put_noidle(cs35l41->dev);20432044err:2045if (cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type))2046gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);2047gpiod_put(cs35l41->reset_gpio);2048gpiod_put(cs35l41->cs_gpio);2049acpi_dev_put(cs35l41->dacpi);2050kfree(cs35l41->acpi_subsystem_id);20512052return ret;2053}2054EXPORT_SYMBOL_NS_GPL(cs35l41_hda_probe, "SND_HDA_SCODEC_CS35L41");20552056void cs35l41_hda_remove(struct device *dev)2057{2058struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);20592060component_del(cs35l41->dev, &cs35l41_hda_comp_ops);20612062pm_runtime_get_sync(cs35l41->dev);2063pm_runtime_dont_use_autosuspend(cs35l41->dev);2064pm_runtime_disable(cs35l41->dev);20652066if (cs35l41->halo_initialized)2067cs35l41_remove_dsp(cs35l41);20682069acpi_dev_put(cs35l41->dacpi);20702071pm_runtime_put_noidle(cs35l41->dev);20722073if (cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type))2074gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);2075gpiod_put(cs35l41->reset_gpio);2076gpiod_put(cs35l41->cs_gpio);2077kfree(cs35l41->acpi_subsystem_id);2078}2079EXPORT_SYMBOL_NS_GPL(cs35l41_hda_remove, "SND_HDA_SCODEC_CS35L41");20802081const struct dev_pm_ops cs35l41_hda_pm_ops = {2082RUNTIME_PM_OPS(cs35l41_runtime_suspend, cs35l41_runtime_resume,2083cs35l41_runtime_idle)2084.prepare = cs35l41_system_suspend_prep,2085SYSTEM_SLEEP_PM_OPS(cs35l41_system_suspend, cs35l41_system_resume)2086};2087EXPORT_SYMBOL_NS_GPL(cs35l41_hda_pm_ops, "SND_HDA_SCODEC_CS35L41");20882089MODULE_DESCRIPTION("CS35L41 HDA Driver");2090MODULE_IMPORT_NS("SND_SOC_CS_AMP_LIB");2091MODULE_AUTHOR("Lucas Tanure, Cirrus Logic Inc, <[email protected]>");2092MODULE_LICENSE("GPL");2093MODULE_IMPORT_NS("FW_CS_DSP");2094MODULE_FIRMWARE("cirrus/cs35l41-*.wmfw");2095MODULE_FIRMWARE("cirrus/cs35l41-*.bin");209620972098