Path: blob/master/sound/hda/codecs/side-codecs/cs35l41_hda.c
26481 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);625626mutex_lock(&cs35l41->fw_mutex);627cs35l41_shutdown_dsp(cs35l41);628cs_dsp_remove(dsp);629cs35l41->halo_initialized = false;630mutex_unlock(&cs35l41->fw_mutex);631}632633/* Protection release cycle to get the speaker out of Safe-Mode */634static void cs35l41_error_release(struct device *dev, struct regmap *regmap, unsigned int mask)635{636regmap_write(regmap, CS35L41_PROTECT_REL_ERR_IGN, 0);637regmap_set_bits(regmap, CS35L41_PROTECT_REL_ERR_IGN, mask);638regmap_clear_bits(regmap, CS35L41_PROTECT_REL_ERR_IGN, mask);639}640641/* Clear all errors to release safe mode. Global Enable must be cleared first. */642static void cs35l41_irq_release(struct cs35l41_hda *cs35l41)643{644cs35l41_error_release(cs35l41->dev, cs35l41->regmap, cs35l41->irq_errors);645cs35l41->irq_errors = 0;646}647648static void cs35l41_update_mixer(struct cs35l41_hda *cs35l41)649{650struct regmap *reg = cs35l41->regmap;651unsigned int asp_en = 0;652unsigned int dsp1rx2_src = 0;653654regmap_multi_reg_write(reg, cs35l41_hda_config, ARRAY_SIZE(cs35l41_hda_config));655656if (cs35l41->cs_dsp.running) {657asp_en |= CS35L41_ASP_TX1_EN_MASK; // ASP_TX1_EN = 1658regmap_multi_reg_write(reg, cs35l41_hda_config_dsp,659ARRAY_SIZE(cs35l41_hda_config_dsp));660if (cs35l41->hw_cfg.bst_type == CS35L41_INT_BOOST)661regmap_write(reg, CS35L41_DSP1_RX5_SRC, CS35L41_INPUT_SRC_VPMON);662else663regmap_write(reg, CS35L41_DSP1_RX5_SRC, CS35L41_INPUT_SRC_VBSTMON);664} else {665regmap_multi_reg_write(reg, cs35l41_hda_config_no_dsp,666ARRAY_SIZE(cs35l41_hda_config_no_dsp));667}668669if (cs35l41->hw_cfg.spk_pos == CS35L41_CENTER) {670asp_en |= CS35L41_ASP_RX2_EN_MASK; // ASP_RX2_EN = 1671dsp1rx2_src = 0x00000009; // DSP1RX2 SRC = ASPRX2672} else {673dsp1rx2_src = 0x00000008; // DSP1RX2 SRC = ASPRX1674}675676asp_en |= CS35L41_ASP_RX1_EN_MASK; // ASP_RX1_EN = 1677678regmap_write(reg, CS35L41_SP_ENABLES, asp_en);679regmap_write(reg, CS35L41_DSP1_RX1_SRC, 0x00000008); // DSP1RX1 SRC = ASPRX1680regmap_write(reg, CS35L41_DSP1_RX2_SRC, dsp1rx2_src);681}682683static void cs35l41_hda_play_start(struct device *dev)684{685struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);686struct regmap *reg = cs35l41->regmap;687688dev_dbg(dev, "Play (Start)\n");689690if (cs35l41->playback_started) {691dev_dbg(dev, "Playback already started.");692return;693}694695cs35l41->playback_started = true;696697cs35l41_update_mixer(cs35l41);698699if (cs35l41->cs_dsp.running) {700regmap_update_bits(reg, CS35L41_PWR_CTRL2,701CS35L41_VMON_EN_MASK | CS35L41_IMON_EN_MASK,7021 << CS35L41_VMON_EN_SHIFT | 1 << CS35L41_IMON_EN_SHIFT);703cs35l41_set_cspl_mbox_cmd(cs35l41->dev, reg, CSPL_MBOX_CMD_RESUME);704}705regmap_update_bits(reg, CS35L41_PWR_CTRL2, CS35L41_AMP_EN_MASK, 1 << CS35L41_AMP_EN_SHIFT);706if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST)707regmap_write(reg, CS35L41_GPIO1_CTRL1, 0x00008001);708709}710711static void cs35l41_mute(struct device *dev, bool mute)712{713struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);714struct regmap *reg = cs35l41->regmap;715unsigned int amp_gain;716717dev_dbg(dev, "Mute(%d:%d) Playback Started: %d\n", mute, cs35l41->mute_override,718cs35l41->playback_started);719720if (cs35l41->playback_started) {721if (mute || cs35l41->mute_override) {722dev_dbg(dev, "Muting\n");723regmap_multi_reg_write(reg, cs35l41_hda_mute, ARRAY_SIZE(cs35l41_hda_mute));724} else {725dev_dbg(dev, "Unmuting\n");726if (cs35l41->cs_dsp.running) {727dev_dbg(dev, "Using Tuned Gain: %d\n", cs35l41->tuning_gain);728amp_gain = (cs35l41->tuning_gain << CS35L41_AMP_GAIN_PCM_SHIFT) |729(DEFAULT_AMP_GAIN_PDM << CS35L41_AMP_GAIN_PDM_SHIFT);730731/* AMP_HPF_PCM_EN = 1, AMP_VOL_PCM 0.0 dB */732regmap_write(reg, CS35L41_AMP_DIG_VOL_CTRL, 0x00008000);733regmap_write(reg, CS35L41_AMP_GAIN_CTRL, amp_gain);734} else {735regmap_multi_reg_write(reg, cs35l41_hda_unmute,736ARRAY_SIZE(cs35l41_hda_unmute));737}738}739}740}741742static void cs35l41_hda_play_done(struct device *dev)743{744struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);745struct regmap *reg = cs35l41->regmap;746747dev_dbg(dev, "Play (Complete)\n");748749cs35l41_global_enable(dev, reg, cs35l41->hw_cfg.bst_type, 1,750&cs35l41->cs_dsp);751cs35l41_mute(dev, false);752}753754static void cs35l41_hda_pause_start(struct device *dev)755{756struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);757struct regmap *reg = cs35l41->regmap;758759dev_dbg(dev, "Pause (Start)\n");760761cs35l41_mute(dev, true);762cs35l41_global_enable(dev, reg, cs35l41->hw_cfg.bst_type, 0,763&cs35l41->cs_dsp);764}765766static void cs35l41_hda_pause_done(struct device *dev)767{768struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);769struct regmap *reg = cs35l41->regmap;770771dev_dbg(dev, "Pause (Complete)\n");772773regmap_update_bits(reg, CS35L41_PWR_CTRL2, CS35L41_AMP_EN_MASK, 0 << CS35L41_AMP_EN_SHIFT);774if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST)775regmap_write(reg, CS35L41_GPIO1_CTRL1, 0x00000001);776if (cs35l41->cs_dsp.running) {777cs35l41_set_cspl_mbox_cmd(dev, reg, CSPL_MBOX_CMD_PAUSE);778regmap_update_bits(reg, CS35L41_PWR_CTRL2,779CS35L41_VMON_EN_MASK | CS35L41_IMON_EN_MASK,7800 << CS35L41_VMON_EN_SHIFT | 0 << CS35L41_IMON_EN_SHIFT);781}782cs35l41_irq_release(cs35l41);783cs35l41->playback_started = false;784}785786static void cs35l41_hda_pre_playback_hook(struct device *dev, int action)787{788struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);789790switch (action) {791case HDA_GEN_PCM_ACT_CLEANUP:792mutex_lock(&cs35l41->fw_mutex);793cs35l41_hda_pause_start(dev);794mutex_unlock(&cs35l41->fw_mutex);795break;796default:797break;798}799}800static void cs35l41_hda_playback_hook(struct device *dev, int action)801{802struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);803804switch (action) {805case HDA_GEN_PCM_ACT_OPEN:806/*807* All amps must be resumed before we can start playing back.808* This ensures, for external boost, that all amps are in AMP_SAFE mode.809* Do this in HDA_GEN_PCM_ACT_OPEN, since this is run prior to any of the810* other actions.811*/812pm_runtime_get_sync(dev);813break;814case HDA_GEN_PCM_ACT_PREPARE:815mutex_lock(&cs35l41->fw_mutex);816cs35l41_hda_play_start(dev);817mutex_unlock(&cs35l41->fw_mutex);818break;819case HDA_GEN_PCM_ACT_CLEANUP:820mutex_lock(&cs35l41->fw_mutex);821cs35l41_hda_pause_done(dev);822mutex_unlock(&cs35l41->fw_mutex);823break;824case HDA_GEN_PCM_ACT_CLOSE:825mutex_lock(&cs35l41->fw_mutex);826if (!cs35l41->cs_dsp.running && cs35l41->request_fw_load &&827!cs35l41->fw_request_ongoing) {828dev_info(dev, "Requesting Firmware Load after HDA_GEN_PCM_ACT_CLOSE\n");829cs35l41->fw_request_ongoing = true;830schedule_work(&cs35l41->fw_load_work);831}832mutex_unlock(&cs35l41->fw_mutex);833834/*835* Playback must be finished for all amps before we start runtime suspend.836* This ensures no amps are playing back when we start putting them to sleep.837*/838pm_runtime_put_autosuspend(dev);839break;840default:841break;842}843}844845static void cs35l41_hda_post_playback_hook(struct device *dev, int action)846{847struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);848849switch (action) {850case HDA_GEN_PCM_ACT_PREPARE:851mutex_lock(&cs35l41->fw_mutex);852cs35l41_hda_play_done(dev);853mutex_unlock(&cs35l41->fw_mutex);854break;855default:856break;857}858}859860static int cs35l41_hda_channel_map(struct cs35l41_hda *cs35l41)861{862unsigned int tx_num = 0;863unsigned int *tx_slot = NULL;864unsigned int rx_num;865unsigned int *rx_slot;866unsigned int mono = 0;867868if (!cs35l41->amp_name) {869if (cs35l41->hw_cfg.spk_pos >= ARRAY_SIZE(channel_name))870return -EINVAL;871872cs35l41->amp_name = devm_kasprintf(cs35l41->dev, GFP_KERNEL, "%c%d",873channel_name[cs35l41->hw_cfg.spk_pos],874cs35l41->channel_index);875if (!cs35l41->amp_name)876return -ENOMEM;877}878879rx_num = 1;880if (cs35l41->hw_cfg.spk_pos == CS35L41_CENTER)881rx_slot = &mono;882else883rx_slot = &cs35l41->hw_cfg.spk_pos;884885return cs35l41_set_channels(cs35l41->dev, cs35l41->regmap, tx_num, tx_slot, rx_num,886rx_slot);887}888889static int cs35l41_verify_id(struct cs35l41_hda *cs35l41, unsigned int *regid, unsigned int *reg_revid)890{891unsigned int mtl_revid, chipid;892int ret;893894ret = regmap_read(cs35l41->regmap, CS35L41_DEVID, regid);895if (ret) {896dev_err_probe(cs35l41->dev, ret, "Get Device ID failed\n");897return ret;898}899900ret = regmap_read(cs35l41->regmap, CS35L41_REVID, reg_revid);901if (ret) {902dev_err_probe(cs35l41->dev, ret, "Get Revision ID failed\n");903return ret;904}905906mtl_revid = *reg_revid & CS35L41_MTLREVID_MASK;907908chipid = (mtl_revid % 2) ? CS35L41R_CHIP_ID : CS35L41_CHIP_ID;909if (*regid != chipid) {910dev_err(cs35l41->dev, "CS35L41 Device ID (%X). Expected ID %X\n", *regid, chipid);911return -ENODEV;912}913914return 0;915}916917static int cs35l41_ready_for_reset(struct cs35l41_hda *cs35l41)918{919mutex_lock(&cs35l41->fw_mutex);920if (cs35l41->cs_dsp.running) {921cs35l41->cs_dsp.running = false;922cs35l41->cs_dsp.booted = false;923}924regcache_mark_dirty(cs35l41->regmap);925mutex_unlock(&cs35l41->fw_mutex);926927return 0;928}929930static int cs35l41_system_suspend_prep(struct device *dev)931{932struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);933934dev_dbg(cs35l41->dev, "System Suspend Prepare\n");935936if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST_NO_VSPK_SWITCH) {937dev_err_once(cs35l41->dev, "System Suspend not supported\n");938return 0; /* don't block the whole system suspend */939}940941mutex_lock(&cs35l41->fw_mutex);942if (cs35l41->playback_started)943cs35l41_hda_pause_start(dev);944mutex_unlock(&cs35l41->fw_mutex);945946return 0;947}948949static int cs35l41_system_suspend(struct device *dev)950{951struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);952int ret;953954dev_dbg(cs35l41->dev, "System Suspend\n");955956if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST_NO_VSPK_SWITCH) {957dev_err_once(cs35l41->dev, "System Suspend not supported\n");958return 0; /* don't block the whole system suspend */959}960961mutex_lock(&cs35l41->fw_mutex);962if (cs35l41->playback_started)963cs35l41_hda_pause_done(dev);964mutex_unlock(&cs35l41->fw_mutex);965966ret = pm_runtime_force_suspend(dev);967if (ret) {968dev_err(dev, "System Suspend Failed, unable to runtime suspend: %d\n", ret);969return ret;970}971972/* Shutdown DSP before system suspend */973ret = cs35l41_ready_for_reset(cs35l41);974if (ret)975dev_err(dev, "System Suspend Failed, not ready for Reset: %d\n", ret);976977if (cs35l41->reset_gpio) {978dev_info(cs35l41->dev, "Asserting Reset\n");979gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);980usleep_range(2000, 2100);981}982983dev_dbg(cs35l41->dev, "System Suspended\n");984985return ret;986}987988static int cs35l41_wait_boot_done(struct cs35l41_hda *cs35l41)989{990unsigned int int_status;991int ret;992993ret = regmap_read_poll_timeout(cs35l41->regmap, CS35L41_IRQ1_STATUS4, int_status,994int_status & CS35L41_OTP_BOOT_DONE, 1000, 100000);995if (ret) {996dev_err(cs35l41->dev, "Failed waiting for OTP_BOOT_DONE\n");997return ret;998}9991000ret = regmap_read(cs35l41->regmap, CS35L41_IRQ1_STATUS3, &int_status);1001if (ret || (int_status & CS35L41_OTP_BOOT_ERR)) {1002dev_err(cs35l41->dev, "OTP Boot status %x error\n",1003int_status & CS35L41_OTP_BOOT_ERR);1004if (!ret)1005ret = -EIO;1006return ret;1007}10081009return 0;1010}10111012static int cs35l41_system_resume(struct device *dev)1013{1014struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);1015int ret;10161017dev_dbg(cs35l41->dev, "System Resume\n");10181019if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST_NO_VSPK_SWITCH) {1020dev_err_once(cs35l41->dev, "System Resume not supported\n");1021return 0; /* don't block the whole system resume */1022}10231024if (cs35l41->reset_gpio) {1025gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);1026usleep_range(2000, 2100);1027gpiod_set_value_cansleep(cs35l41->reset_gpio, 1);1028}10291030usleep_range(2000, 2100);10311032regcache_cache_only(cs35l41->regmap, false);10331034regmap_write(cs35l41->regmap, CS35L41_SFT_RESET, CS35L41_SOFTWARE_RESET);1035usleep_range(2000, 2100);10361037ret = cs35l41_wait_boot_done(cs35l41);1038if (ret)1039return ret;10401041regcache_cache_only(cs35l41->regmap, true);10421043ret = pm_runtime_force_resume(dev);1044if (ret) {1045dev_err(dev, "System Resume Failed: Unable to runtime resume: %d\n", ret);1046return ret;1047}10481049mutex_lock(&cs35l41->fw_mutex);10501051if (cs35l41->request_fw_load && !cs35l41->fw_request_ongoing) {1052cs35l41->fw_request_ongoing = true;1053schedule_work(&cs35l41->fw_load_work);1054}1055mutex_unlock(&cs35l41->fw_mutex);10561057return ret;1058}10591060static int cs35l41_runtime_idle(struct device *dev)1061{1062struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);10631064if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST_NO_VSPK_SWITCH)1065return -EBUSY; /* suspend not supported yet on this model */1066return 0;1067}10681069static int cs35l41_runtime_suspend(struct device *dev)1070{1071struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);1072int ret = 0;10731074dev_dbg(cs35l41->dev, "Runtime Suspend\n");10751076if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST_NO_VSPK_SWITCH) {1077dev_dbg(cs35l41->dev, "Runtime Suspend not supported\n");1078return 0;1079}10801081mutex_lock(&cs35l41->fw_mutex);10821083if (cs35l41->cs_dsp.running) {1084ret = cs35l41_enter_hibernate(cs35l41->dev, cs35l41->regmap,1085cs35l41->hw_cfg.bst_type);1086if (ret)1087goto err;1088} else {1089cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type);1090}10911092regcache_cache_only(cs35l41->regmap, true);1093regcache_mark_dirty(cs35l41->regmap);10941095err:1096mutex_unlock(&cs35l41->fw_mutex);10971098return ret;1099}11001101static int cs35l41_runtime_resume(struct device *dev)1102{1103struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);1104unsigned int regid, reg_revid;1105int ret = 0;11061107dev_dbg(cs35l41->dev, "Runtime Resume\n");11081109if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST_NO_VSPK_SWITCH) {1110dev_dbg(cs35l41->dev, "Runtime Resume not supported\n");1111return 0;1112}11131114mutex_lock(&cs35l41->fw_mutex);11151116regcache_cache_only(cs35l41->regmap, false);11171118if (cs35l41->cs_dsp.running) {1119ret = cs35l41_exit_hibernate(cs35l41->dev, cs35l41->regmap);1120if (ret) {1121dev_warn(cs35l41->dev, "Unable to exit Hibernate.");1122goto err;1123}1124}11251126ret = cs35l41_verify_id(cs35l41, ®id, ®_revid);1127if (ret)1128goto err;11291130/* Test key needs to be unlocked to allow the OTP settings to re-apply */1131cs35l41_test_key_unlock(cs35l41->dev, cs35l41->regmap);1132ret = regcache_sync(cs35l41->regmap);1133cs35l41_test_key_lock(cs35l41->dev, cs35l41->regmap);1134if (ret) {1135dev_err(cs35l41->dev, "Failed to restore register cache: %d\n", ret);1136goto err;1137}11381139if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST)1140cs35l41_init_boost(cs35l41->dev, cs35l41->regmap, &cs35l41->hw_cfg);11411142dev_dbg(cs35l41->dev, "CS35L41 Resumed (%x), Revision: %02X\n", regid, reg_revid);11431144err:1145mutex_unlock(&cs35l41->fw_mutex);11461147return ret;1148}11491150static int cs35l41_hda_read_ctl(struct cs_dsp *dsp, const char *name, int type,1151unsigned int alg, void *buf, size_t len)1152{1153int ret;11541155mutex_lock(&dsp->pwr_lock);1156ret = cs_dsp_coeff_read_ctrl(cs_dsp_get_ctl(dsp, name, type, alg), 0, buf, len);1157mutex_unlock(&dsp->pwr_lock);11581159return ret;1160}11611162static int cs35l41_smart_amp(struct cs35l41_hda *cs35l41)1163{1164unsigned int fw_status;1165__be32 halo_sts;1166int ret;11671168if (cs35l41->bypass_fw) {1169dev_warn(cs35l41->dev, "Bypassing Firmware.\n");1170return 0;1171}11721173ret = cs35l41_init_dsp(cs35l41);1174if (ret) {1175dev_warn(cs35l41->dev, "Cannot Initialize Firmware. Error: %d\n", ret);1176goto clean_dsp;1177}11781179ret = cs35l41_write_fs_errata(cs35l41->dev, cs35l41->regmap);1180if (ret) {1181dev_err(cs35l41->dev, "Cannot Write FS Errata: %d\n", ret);1182goto clean_dsp;1183}11841185ret = cs_dsp_run(&cs35l41->cs_dsp);1186if (ret) {1187dev_err(cs35l41->dev, "Fail to start dsp: %d\n", ret);1188goto clean_dsp;1189}11901191ret = read_poll_timeout(cs35l41_hda_read_ctl, ret,1192be32_to_cpu(halo_sts) == HALO_STATE_CODE_RUN,11931000, 15000, false, &cs35l41->cs_dsp, HALO_STATE_DSP_CTL_NAME,1194HALO_STATE_DSP_CTL_TYPE, HALO_STATE_DSP_CTL_ALG,1195&halo_sts, sizeof(halo_sts));11961197if (ret) {1198dev_err(cs35l41->dev, "Timeout waiting for HALO Core to start. State: %u\n",1199halo_sts);1200goto clean_dsp;1201}12021203ret = regmap_read(cs35l41->regmap, CS35L41_DSP_MBOX_2, &fw_status);1204if (ret < 0) {1205dev_err(cs35l41->dev,1206"Failed to read firmware status: %d\n", ret);1207goto clean_dsp;1208}12091210switch (fw_status) {1211case CSPL_MBOX_STS_RUNNING:1212case CSPL_MBOX_STS_PAUSED:1213break;1214default:1215dev_err(cs35l41->dev, "Firmware status is invalid: %u\n",1216fw_status);1217ret = -EINVAL;1218goto clean_dsp;1219}12201221ret = cs35l41_set_cspl_mbox_cmd(cs35l41->dev, cs35l41->regmap, CSPL_MBOX_CMD_PAUSE);1222if (ret) {1223dev_err(cs35l41->dev, "Error waiting for DSP to pause: %u\n", ret);1224goto clean_dsp;1225}12261227dev_info(cs35l41->dev, "Firmware Loaded - Type: %s, Gain: %d\n",1228cs35l41_hda_fw_ids[cs35l41->firmware_type], cs35l41->tuning_gain);12291230return 0;12311232clean_dsp:1233cs35l41_shutdown_dsp(cs35l41);1234return ret;1235}12361237static void cs35l41_load_firmware(struct cs35l41_hda *cs35l41, bool load)1238{1239if (cs35l41->cs_dsp.running && !load) {1240dev_dbg(cs35l41->dev, "Unloading Firmware\n");1241cs35l41_shutdown_dsp(cs35l41);1242} else if (!cs35l41->cs_dsp.running && load) {1243dev_dbg(cs35l41->dev, "Loading Firmware\n");1244cs35l41_smart_amp(cs35l41);1245} else {1246dev_dbg(cs35l41->dev, "Unable to Load firmware.\n");1247}1248}12491250static int cs35l41_fw_load_ctl_get(struct snd_kcontrol *kcontrol,1251struct snd_ctl_elem_value *ucontrol)1252{1253struct cs35l41_hda *cs35l41 = snd_kcontrol_chip(kcontrol);12541255ucontrol->value.integer.value[0] = cs35l41->request_fw_load;1256return 0;1257}12581259static int cs35l41_mute_override_ctl_get(struct snd_kcontrol *kcontrol,1260struct snd_ctl_elem_value *ucontrol)1261{1262struct cs35l41_hda *cs35l41 = snd_kcontrol_chip(kcontrol);12631264ucontrol->value.integer.value[0] = cs35l41->mute_override;1265return 0;1266}12671268static void cs35l41_fw_load_work(struct work_struct *work)1269{1270struct cs35l41_hda *cs35l41 = container_of(work, struct cs35l41_hda, fw_load_work);12711272pm_runtime_get_sync(cs35l41->dev);12731274mutex_lock(&cs35l41->fw_mutex);12751276/* Recheck if playback is ongoing, mutex will block playback during firmware loading */1277if (cs35l41->playback_started)1278dev_err(cs35l41->dev, "Cannot Load/Unload firmware during Playback. Retrying...\n");1279else1280cs35l41_load_firmware(cs35l41, cs35l41->request_fw_load);12811282cs35l41->fw_request_ongoing = false;1283mutex_unlock(&cs35l41->fw_mutex);12841285pm_runtime_put_autosuspend(cs35l41->dev);1286}12871288static int cs35l41_fw_load_ctl_put(struct snd_kcontrol *kcontrol,1289struct snd_ctl_elem_value *ucontrol)1290{1291struct cs35l41_hda *cs35l41 = snd_kcontrol_chip(kcontrol);12921293if (cs35l41->request_fw_load == ucontrol->value.integer.value[0])1294return 0;12951296if (cs35l41->fw_request_ongoing) {1297dev_dbg(cs35l41->dev, "Existing request not complete\n");1298return -EBUSY;1299}13001301/* Check if playback is ongoing when initial request is made */1302if (cs35l41->playback_started) {1303dev_err(cs35l41->dev, "Cannot Load/Unload firmware during Playback\n");1304return -EBUSY;1305}13061307cs35l41->fw_request_ongoing = true;1308cs35l41->request_fw_load = ucontrol->value.integer.value[0];1309schedule_work(&cs35l41->fw_load_work);13101311return 1;1312}13131314static int cs35l41_fw_type_ctl_get(struct snd_kcontrol *kcontrol,1315struct snd_ctl_elem_value *ucontrol)1316{1317struct cs35l41_hda *cs35l41 = snd_kcontrol_chip(kcontrol);13181319ucontrol->value.enumerated.item[0] = cs35l41->firmware_type;13201321return 0;1322}13231324static int cs35l41_fw_type_ctl_put(struct snd_kcontrol *kcontrol,1325struct snd_ctl_elem_value *ucontrol)1326{1327struct cs35l41_hda *cs35l41 = snd_kcontrol_chip(kcontrol);13281329if (ucontrol->value.enumerated.item[0] < CS35L41_HDA_NUM_FW) {1330if (cs35l41->firmware_type != ucontrol->value.enumerated.item[0]) {1331cs35l41->firmware_type = ucontrol->value.enumerated.item[0];1332return 1;1333} else {1334return 0;1335}1336}13371338return -EINVAL;1339}13401341static int cs35l41_fw_type_ctl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)1342{1343return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(cs35l41_hda_fw_ids), cs35l41_hda_fw_ids);1344}13451346static int cs35l41_create_controls(struct cs35l41_hda *cs35l41)1347{1348char fw_type_ctl_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];1349char fw_load_ctl_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];1350char mute_override_ctl_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];1351struct snd_kcontrol_new fw_type_ctl = {1352.name = fw_type_ctl_name,1353.iface = SNDRV_CTL_ELEM_IFACE_CARD,1354.info = cs35l41_fw_type_ctl_info,1355.get = cs35l41_fw_type_ctl_get,1356.put = cs35l41_fw_type_ctl_put,1357};1358struct snd_kcontrol_new fw_load_ctl = {1359.name = fw_load_ctl_name,1360.iface = SNDRV_CTL_ELEM_IFACE_CARD,1361.info = snd_ctl_boolean_mono_info,1362.get = cs35l41_fw_load_ctl_get,1363.put = cs35l41_fw_load_ctl_put,1364};1365struct snd_kcontrol_new mute_override_ctl = {1366.name = mute_override_ctl_name,1367.iface = SNDRV_CTL_ELEM_IFACE_CARD,1368.info = snd_ctl_boolean_mono_info,1369.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,1370.get = cs35l41_mute_override_ctl_get,1371};1372int ret;13731374scnprintf(fw_type_ctl_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s DSP1 Firmware Type",1375cs35l41->amp_name);1376scnprintf(fw_load_ctl_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s DSP1 Firmware Load",1377cs35l41->amp_name);1378scnprintf(mute_override_ctl_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s Forced Mute Status",1379cs35l41->amp_name);13801381ret = snd_ctl_add(cs35l41->codec->card, snd_ctl_new1(&fw_type_ctl, cs35l41));1382if (ret) {1383dev_err(cs35l41->dev, "Failed to add KControl %s = %d\n", fw_type_ctl.name, ret);1384return ret;1385}13861387dev_dbg(cs35l41->dev, "Added Control %s\n", fw_type_ctl.name);13881389ret = snd_ctl_add(cs35l41->codec->card, snd_ctl_new1(&fw_load_ctl, cs35l41));1390if (ret) {1391dev_err(cs35l41->dev, "Failed to add KControl %s = %d\n", fw_load_ctl.name, ret);1392return ret;1393}13941395dev_dbg(cs35l41->dev, "Added Control %s\n", fw_load_ctl.name);13961397ret = snd_ctl_add(cs35l41->codec->card, snd_ctl_new1(&mute_override_ctl, cs35l41));1398if (ret) {1399dev_err(cs35l41->dev, "Failed to add KControl %s = %d\n", mute_override_ctl.name,1400ret);1401return ret;1402}14031404dev_dbg(cs35l41->dev, "Added Control %s\n", mute_override_ctl.name);14051406return 0;1407}14081409static bool cs35l41_dsm_supported(acpi_handle handle, unsigned int commands)1410{1411guid_t guid;14121413guid_parse(CS35L41_UUID, &guid);14141415return acpi_check_dsm(handle, &guid, 0, BIT(commands));1416}14171418static int cs35l41_get_acpi_mute_state(struct cs35l41_hda *cs35l41, acpi_handle handle)1419{1420guid_t guid;1421union acpi_object *ret;1422int mute = -ENODEV;14231424guid_parse(CS35L41_UUID, &guid);14251426if (cs35l41_dsm_supported(handle, CS35L41_DSM_GET_MUTE)) {1427ret = acpi_evaluate_dsm(handle, &guid, 0, CS35L41_DSM_GET_MUTE, NULL);1428mute = *ret->buffer.pointer;1429dev_dbg(cs35l41->dev, "CS35L41_DSM_GET_MUTE: %d\n", mute);1430}14311432dev_dbg(cs35l41->dev, "%s: %d\n", __func__, mute);14331434return mute;1435}14361437static void cs35l41_acpi_device_notify(acpi_handle handle, u32 event, struct device *dev)1438{1439struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);1440int mute;14411442if (event != CS35L41_NOTIFY_EVENT)1443return;14441445mute = cs35l41_get_acpi_mute_state(cs35l41, handle);1446if (mute < 0) {1447dev_warn(cs35l41->dev, "Unable to retrieve mute state: %d\n", mute);1448return;1449}14501451dev_dbg(cs35l41->dev, "Requesting mute value: %d\n", mute);1452cs35l41->mute_override = (mute > 0);1453cs35l41_mute(cs35l41->dev, cs35l41->mute_override);1454}14551456static int cs35l41_hda_bind(struct device *dev, struct device *master, void *master_data)1457{1458struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);1459struct hda_component_parent *parent = master_data;1460struct hda_component *comp;1461unsigned int sleep_flags;1462int ret = 0;14631464comp = hda_component_from_index(parent, cs35l41->index);1465if (!comp)1466return -EINVAL;14671468if (comp->dev)1469return -EBUSY;14701471pm_runtime_get_sync(dev);14721473mutex_lock(&cs35l41->fw_mutex);14741475comp->dev = dev;1476cs35l41->codec = parent->codec;1477if (!cs35l41->acpi_subsystem_id)1478cs35l41->acpi_subsystem_id = kasprintf(GFP_KERNEL, "%.8x",1479cs35l41->codec->core.subsystem_id);14801481strscpy(comp->name, dev_name(dev), sizeof(comp->name));14821483cs35l41->firmware_type = CS35L41_HDA_FW_SPK_PROT;14841485if (firmware_autostart) {1486dev_dbg(cs35l41->dev, "Firmware Autostart.\n");1487cs35l41->request_fw_load = true;1488if (cs35l41_smart_amp(cs35l41) < 0)1489dev_warn(cs35l41->dev, "Cannot Run Firmware, reverting to dsp bypass...\n");1490} else {1491dev_dbg(cs35l41->dev, "Firmware Autostart is disabled.\n");1492}14931494ret = cs35l41_create_controls(cs35l41);14951496comp->playback_hook = cs35l41_hda_playback_hook;1497comp->pre_playback_hook = cs35l41_hda_pre_playback_hook;1498comp->post_playback_hook = cs35l41_hda_post_playback_hook;1499comp->acpi_notify = cs35l41_acpi_device_notify;1500comp->adev = cs35l41->dacpi;15011502comp->acpi_notifications_supported = cs35l41_dsm_supported(acpi_device_handle(comp->adev),1503CS35L41_DSM_GET_MUTE);15041505cs35l41->mute_override = cs35l41_get_acpi_mute_state(cs35l41,1506acpi_device_handle(cs35l41->dacpi)) > 0;15071508mutex_unlock(&cs35l41->fw_mutex);15091510sleep_flags = lock_system_sleep();1511if (!device_link_add(&cs35l41->codec->core.dev, cs35l41->dev, DL_FLAG_STATELESS))1512dev_warn(dev, "Unable to create device link\n");1513unlock_system_sleep(sleep_flags);15141515pm_runtime_put_autosuspend(dev);15161517dev_info(cs35l41->dev,1518"CS35L41 Bound - SSID: %s, BST: %d, VSPK: %d, CH: %c, FW EN: %d, SPKID: %d\n",1519cs35l41->acpi_subsystem_id, cs35l41->hw_cfg.bst_type,1520cs35l41->hw_cfg.gpio1.func == CS35l41_VSPK_SWITCH,1521channel_name[cs35l41->hw_cfg.spk_pos],1522cs35l41->cs_dsp.running, cs35l41->speaker_id);15231524return ret;1525}15261527static void cs35l41_hda_unbind(struct device *dev, struct device *master, void *master_data)1528{1529struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);1530struct hda_component_parent *parent = master_data;1531struct hda_component *comp;1532unsigned int sleep_flags;15331534comp = hda_component_from_index(parent, cs35l41->index);1535if (!comp)1536return;15371538if (comp->dev == dev) {1539sleep_flags = lock_system_sleep();1540device_link_remove(&cs35l41->codec->core.dev, cs35l41->dev);1541unlock_system_sleep(sleep_flags);1542memset(comp, 0, sizeof(*comp));1543}1544}15451546static const struct component_ops cs35l41_hda_comp_ops = {1547.bind = cs35l41_hda_bind,1548.unbind = cs35l41_hda_unbind,1549};15501551static irqreturn_t cs35l41_bst_short_err(int irq, void *data)1552{1553struct cs35l41_hda *cs35l41 = data;15541555dev_crit_ratelimited(cs35l41->dev, "LBST Error\n");1556set_bit(CS35L41_BST_SHORT_ERR_RLS_SHIFT, &cs35l41->irq_errors);15571558return IRQ_HANDLED;1559}15601561static irqreturn_t cs35l41_bst_dcm_uvp_err(int irq, void *data)1562{1563struct cs35l41_hda *cs35l41 = data;15641565dev_crit_ratelimited(cs35l41->dev, "DCM VBST Under Voltage Error\n");1566set_bit(CS35L41_BST_UVP_ERR_RLS_SHIFT, &cs35l41->irq_errors);15671568return IRQ_HANDLED;1569}15701571static irqreturn_t cs35l41_bst_ovp_err(int irq, void *data)1572{1573struct cs35l41_hda *cs35l41 = data;15741575dev_crit_ratelimited(cs35l41->dev, "VBST Over Voltage error\n");1576set_bit(CS35L41_BST_OVP_ERR_RLS_SHIFT, &cs35l41->irq_errors);15771578return IRQ_HANDLED;1579}15801581static irqreturn_t cs35l41_temp_err(int irq, void *data)1582{1583struct cs35l41_hda *cs35l41 = data;15841585dev_crit_ratelimited(cs35l41->dev, "Over temperature error\n");1586set_bit(CS35L41_TEMP_ERR_RLS_SHIFT, &cs35l41->irq_errors);15871588return IRQ_HANDLED;1589}15901591static irqreturn_t cs35l41_temp_warn(int irq, void *data)1592{1593struct cs35l41_hda *cs35l41 = data;15941595dev_crit_ratelimited(cs35l41->dev, "Over temperature warning\n");1596set_bit(CS35L41_TEMP_WARN_ERR_RLS_SHIFT, &cs35l41->irq_errors);15971598return IRQ_HANDLED;1599}16001601static irqreturn_t cs35l41_amp_short(int irq, void *data)1602{1603struct cs35l41_hda *cs35l41 = data;16041605dev_crit_ratelimited(cs35l41->dev, "Amp short error\n");1606set_bit(CS35L41_AMP_SHORT_ERR_RLS_SHIFT, &cs35l41->irq_errors);16071608return IRQ_HANDLED;1609}16101611static const struct cs35l41_irq cs35l41_irqs[] = {1612CS35L41_IRQ(BST_OVP_ERR, "Boost Overvoltage Error", cs35l41_bst_ovp_err),1613CS35L41_IRQ(BST_DCM_UVP_ERR, "Boost Undervoltage Error", cs35l41_bst_dcm_uvp_err),1614CS35L41_IRQ(BST_SHORT_ERR, "Boost Inductor Short Error", cs35l41_bst_short_err),1615CS35L41_IRQ(TEMP_WARN, "Temperature Warning", cs35l41_temp_warn),1616CS35L41_IRQ(TEMP_ERR, "Temperature Error", cs35l41_temp_err),1617CS35L41_IRQ(AMP_SHORT_ERR, "Amp Short", cs35l41_amp_short),1618};16191620static const struct regmap_irq cs35l41_reg_irqs[] = {1621CS35L41_REG_IRQ(IRQ1_STATUS1, BST_OVP_ERR),1622CS35L41_REG_IRQ(IRQ1_STATUS1, BST_DCM_UVP_ERR),1623CS35L41_REG_IRQ(IRQ1_STATUS1, BST_SHORT_ERR),1624CS35L41_REG_IRQ(IRQ1_STATUS1, TEMP_WARN),1625CS35L41_REG_IRQ(IRQ1_STATUS1, TEMP_ERR),1626CS35L41_REG_IRQ(IRQ1_STATUS1, AMP_SHORT_ERR),1627};16281629static const struct regmap_irq_chip cs35l41_regmap_irq_chip = {1630.name = "cs35l41 IRQ1 Controller",1631.status_base = CS35L41_IRQ1_STATUS1,1632.mask_base = CS35L41_IRQ1_MASK1,1633.ack_base = CS35L41_IRQ1_STATUS1,1634.num_regs = 4,1635.irqs = cs35l41_reg_irqs,1636.num_irqs = ARRAY_SIZE(cs35l41_reg_irqs),1637.runtime_pm = true,1638};16391640static void cs35l41_configure_interrupt(struct cs35l41_hda *cs35l41, int irq_pol)1641{1642int irq;1643int ret;1644int i;16451646if (!cs35l41->irq) {1647dev_warn(cs35l41->dev, "No Interrupt Found");1648goto err;1649}16501651ret = devm_regmap_add_irq_chip(cs35l41->dev, cs35l41->regmap, cs35l41->irq,1652IRQF_ONESHOT | IRQF_SHARED | irq_pol,16530, &cs35l41_regmap_irq_chip, &cs35l41->irq_data);1654if (ret) {1655dev_dbg(cs35l41->dev, "Unable to add IRQ Chip: %d.", ret);1656goto err;1657}16581659for (i = 0; i < ARRAY_SIZE(cs35l41_irqs); i++) {1660irq = regmap_irq_get_virq(cs35l41->irq_data, cs35l41_irqs[i].irq);1661if (irq < 0) {1662ret = irq;1663dev_dbg(cs35l41->dev, "Unable to map IRQ %s: %d.", cs35l41_irqs[i].name,1664ret);1665goto err;1666}16671668ret = devm_request_threaded_irq(cs35l41->dev, irq, NULL,1669cs35l41_irqs[i].handler,1670IRQF_ONESHOT | IRQF_SHARED | irq_pol,1671cs35l41_irqs[i].name, cs35l41);1672if (ret) {1673dev_dbg(cs35l41->dev, "Unable to allocate IRQ %s:: %d.",1674cs35l41_irqs[i].name, ret);1675goto err;1676}1677}1678return;1679err:1680dev_warn(cs35l41->dev,1681"IRQ Config Failed. Amp errors may not be recoverable without reboot.");1682}16831684static int cs35l41_hda_apply_properties(struct cs35l41_hda *cs35l41)1685{1686struct cs35l41_hw_cfg *hw_cfg = &cs35l41->hw_cfg;1687bool using_irq = false;1688int irq_pol;1689int ret;16901691if (!cs35l41->hw_cfg.valid)1692return -EINVAL;16931694ret = cs35l41_init_boost(cs35l41->dev, cs35l41->regmap, hw_cfg);1695if (ret)1696return ret;16971698if (hw_cfg->gpio1.valid) {1699switch (hw_cfg->gpio1.func) {1700case CS35L41_NOT_USED:1701break;1702case CS35l41_VSPK_SWITCH:1703hw_cfg->gpio1.func = CS35L41_GPIO1_GPIO;1704hw_cfg->gpio1.out_en = true;1705break;1706case CS35l41_SYNC:1707hw_cfg->gpio1.func = CS35L41_GPIO1_MDSYNC;1708break;1709default:1710dev_err(cs35l41->dev, "Invalid function %d for GPIO1\n",1711hw_cfg->gpio1.func);1712return -EINVAL;1713}1714}17151716if (hw_cfg->gpio2.valid) {1717switch (hw_cfg->gpio2.func) {1718case CS35L41_NOT_USED:1719break;1720case CS35L41_INTERRUPT:1721using_irq = true;1722hw_cfg->gpio2.func = CS35L41_GPIO2_INT_OPEN_DRAIN;1723break;1724default:1725dev_err(cs35l41->dev, "Invalid GPIO2 function %d\n", hw_cfg->gpio2.func);1726return -EINVAL;1727}1728}17291730irq_pol = cs35l41_gpio_config(cs35l41->regmap, hw_cfg);17311732if (using_irq)1733cs35l41_configure_interrupt(cs35l41, irq_pol);17341735return cs35l41_hda_channel_map(cs35l41);1736}17371738int cs35l41_get_speaker_id(struct device *dev, int amp_index, int num_amps, int fixed_gpio_id)1739{1740struct gpio_desc *speaker_id_desc;1741int speaker_id = -ENODEV;17421743if (fixed_gpio_id >= 0) {1744dev_dbg(dev, "Found Fixed Speaker ID GPIO (index = %d)\n", fixed_gpio_id);1745speaker_id_desc = gpiod_get_index(dev, NULL, fixed_gpio_id, GPIOD_IN);1746if (IS_ERR(speaker_id_desc)) {1747speaker_id = PTR_ERR(speaker_id_desc);1748return speaker_id;1749}1750speaker_id = gpiod_get_value_cansleep(speaker_id_desc);1751gpiod_put(speaker_id_desc);1752dev_dbg(dev, "Speaker ID = %d\n", speaker_id);1753} else {1754int base_index;1755int gpios_per_amp;1756int count;1757int tmp;1758int i;17591760count = gpiod_count(dev, "spk-id");1761if (count > 0) {1762speaker_id = 0;1763gpios_per_amp = count / num_amps;1764base_index = gpios_per_amp * amp_index;17651766if (count % num_amps)1767return -EINVAL;17681769dev_dbg(dev, "Found %d Speaker ID GPIOs per Amp\n", gpios_per_amp);17701771for (i = 0; i < gpios_per_amp; i++) {1772speaker_id_desc = gpiod_get_index(dev, "spk-id", i + base_index,1773GPIOD_IN);1774if (IS_ERR(speaker_id_desc)) {1775speaker_id = PTR_ERR(speaker_id_desc);1776break;1777}1778tmp = gpiod_get_value_cansleep(speaker_id_desc);1779gpiod_put(speaker_id_desc);1780if (tmp < 0) {1781speaker_id = tmp;1782break;1783}1784speaker_id |= tmp << i;1785}1786dev_dbg(dev, "Speaker ID = %d\n", speaker_id);1787}1788}1789return speaker_id;1790}17911792int cs35l41_hda_parse_acpi(struct cs35l41_hda *cs35l41, struct device *physdev, int id)1793{1794struct cs35l41_hw_cfg *hw_cfg = &cs35l41->hw_cfg;1795u32 values[HDA_MAX_COMPONENTS];1796char *property;1797size_t nval;1798int i, ret;17991800property = "cirrus,dev-index";1801ret = device_property_count_u32(physdev, property);1802if (ret <= 0)1803goto err;18041805if (ret > ARRAY_SIZE(values)) {1806ret = -EINVAL;1807goto err;1808}1809nval = ret;18101811ret = device_property_read_u32_array(physdev, property, values, nval);1812if (ret)1813goto err;18141815cs35l41->index = -1;1816for (i = 0; i < nval; i++) {1817if (values[i] == id) {1818cs35l41->index = i;1819break;1820}1821}1822if (cs35l41->index == -1) {1823dev_err(cs35l41->dev, "No index found in %s\n", property);1824ret = -ENODEV;1825goto err;1826}18271828/* To use the same release code for all laptop variants we can't use devm_ version of1829* gpiod_get here, as CLSA010* don't have a fully functional bios with an _DSD node1830*/1831cs35l41->reset_gpio = fwnode_gpiod_get_index(acpi_fwnode_handle(cs35l41->dacpi), "reset",1832cs35l41->index, GPIOD_OUT_LOW,1833"cs35l41-reset");18341835property = "cirrus,speaker-position";1836ret = device_property_read_u32_array(physdev, property, values, nval);1837if (ret)1838goto err;1839hw_cfg->spk_pos = values[cs35l41->index];18401841cs35l41->channel_index = 0;1842for (i = 0; i < cs35l41->index; i++)1843if (values[i] == hw_cfg->spk_pos)1844cs35l41->channel_index++;18451846property = "cirrus,gpio1-func";1847ret = device_property_read_u32_array(physdev, property, values, nval);1848if (ret)1849goto err;1850hw_cfg->gpio1.func = values[cs35l41->index];1851hw_cfg->gpio1.valid = true;18521853property = "cirrus,gpio2-func";1854ret = device_property_read_u32_array(physdev, property, values, nval);1855if (ret)1856goto err;1857hw_cfg->gpio2.func = values[cs35l41->index];1858hw_cfg->gpio2.valid = true;18591860property = "cirrus,boost-peak-milliamp";1861ret = device_property_read_u32_array(physdev, property, values, nval);1862if (ret == 0)1863hw_cfg->bst_ipk = values[cs35l41->index];1864else1865hw_cfg->bst_ipk = -1;18661867property = "cirrus,boost-ind-nanohenry";1868ret = device_property_read_u32_array(physdev, property, values, nval);1869if (ret == 0)1870hw_cfg->bst_ind = values[cs35l41->index];1871else1872hw_cfg->bst_ind = -1;18731874property = "cirrus,boost-cap-microfarad";1875ret = device_property_read_u32_array(physdev, property, values, nval);1876if (ret == 0)1877hw_cfg->bst_cap = values[cs35l41->index];1878else1879hw_cfg->bst_cap = -1;18801881cs35l41->speaker_id = cs35l41_get_speaker_id(physdev, cs35l41->index, nval, -1);18821883if (hw_cfg->bst_ind > 0 || hw_cfg->bst_cap > 0 || hw_cfg->bst_ipk > 0)1884hw_cfg->bst_type = CS35L41_INT_BOOST;1885else1886hw_cfg->bst_type = CS35L41_EXT_BOOST;18871888hw_cfg->valid = true;18891890return 0;1891err:1892dev_err(cs35l41->dev, "Failed property %s: %d\n", property, ret);1893hw_cfg->valid = false;1894hw_cfg->gpio1.valid = false;1895hw_cfg->gpio2.valid = false;1896acpi_dev_put(cs35l41->dacpi);18971898return ret;1899}19001901static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, int id)1902{1903struct acpi_device *adev;1904struct device *physdev;1905struct spi_device *spi;1906const char *sub;1907int ret;19081909adev = acpi_dev_get_first_match_dev(hid, NULL, -1);1910if (!adev) {1911dev_err(cs35l41->dev, "Failed to find an ACPI device for %s\n", hid);1912return -ENODEV;1913}19141915cs35l41->dacpi = adev;1916physdev = get_device(acpi_get_first_physical_node(adev));19171918sub = acpi_get_subsystem_id(ACPI_HANDLE(physdev));1919if (IS_ERR(sub))1920sub = NULL;1921cs35l41->acpi_subsystem_id = sub;19221923ret = cs35l41_add_dsd_properties(cs35l41, physdev, id, hid);1924if (!ret) {1925dev_info(cs35l41->dev, "Using extra _DSD properties, bypassing _DSD in ACPI\n");1926goto out;1927}19281929ret = cs35l41_hda_parse_acpi(cs35l41, physdev, id);1930if (ret) {1931put_device(physdev);1932return ret;1933}1934out:1935put_device(physdev);19361937cs35l41->bypass_fw = false;1938if (cs35l41->control_bus == SPI) {1939spi = to_spi_device(cs35l41->dev);1940if (spi->max_speed_hz < CS35L41_MAX_ACCEPTABLE_SPI_SPEED_HZ) {1941dev_warn(cs35l41->dev,1942"SPI speed is too slow to support firmware download: %d Hz.\n",1943spi->max_speed_hz);1944cs35l41->bypass_fw = true;1945}1946}19471948return 0;1949}19501951int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int irq,1952struct regmap *regmap, enum control_bus control_bus)1953{1954unsigned int regid, reg_revid;1955struct cs35l41_hda *cs35l41;1956int ret;19571958BUILD_BUG_ON(ARRAY_SIZE(cs35l41_irqs) != ARRAY_SIZE(cs35l41_reg_irqs));1959BUILD_BUG_ON(ARRAY_SIZE(cs35l41_irqs) != CS35L41_NUM_IRQ);19601961if (IS_ERR(regmap))1962return PTR_ERR(regmap);19631964cs35l41 = devm_kzalloc(dev, sizeof(*cs35l41), GFP_KERNEL);1965if (!cs35l41)1966return -ENOMEM;19671968cs35l41->dev = dev;1969cs35l41->irq = irq;1970cs35l41->regmap = regmap;1971cs35l41->control_bus = control_bus;1972dev_set_drvdata(dev, cs35l41);19731974ret = cs35l41_hda_read_acpi(cs35l41, device_name, id);1975if (ret)1976return dev_err_probe(cs35l41->dev, ret, "Platform not supported\n");19771978if (IS_ERR(cs35l41->reset_gpio)) {1979ret = PTR_ERR(cs35l41->reset_gpio);1980cs35l41->reset_gpio = NULL;1981if (ret == -EBUSY) {1982dev_info(cs35l41->dev, "Reset line busy, assuming shared reset\n");1983} else {1984dev_err_probe(cs35l41->dev, ret, "Failed to get reset GPIO\n");1985goto err;1986}1987}1988if (cs35l41->reset_gpio) {1989gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);1990usleep_range(2000, 2100);1991gpiod_set_value_cansleep(cs35l41->reset_gpio, 1);1992}19931994usleep_range(2000, 2100);1995regmap_write(cs35l41->regmap, CS35L41_SFT_RESET, CS35L41_SOFTWARE_RESET);1996usleep_range(2000, 2100);19971998ret = cs35l41_wait_boot_done(cs35l41);1999if (ret)2000goto err;20012002ret = cs35l41_verify_id(cs35l41, ®id, ®_revid);2003if (ret)2004goto err;20052006ret = cs35l41_test_key_unlock(cs35l41->dev, cs35l41->regmap);2007if (ret)2008goto err;20092010ret = cs35l41_register_errata_patch(cs35l41->dev, cs35l41->regmap, reg_revid);2011if (ret)2012goto err;20132014ret = cs35l41_otp_unpack(cs35l41->dev, cs35l41->regmap);2015if (ret) {2016dev_err_probe(cs35l41->dev, ret, "OTP Unpack failed\n");2017goto err;2018}20192020ret = cs35l41_test_key_lock(cs35l41->dev, cs35l41->regmap);2021if (ret)2022goto err;20232024ret = cs35l41_get_calibration(cs35l41);2025if (ret && ret != -ENOENT)2026goto err;20272028cs35l41_mute(cs35l41->dev, true);20292030INIT_WORK(&cs35l41->fw_load_work, cs35l41_fw_load_work);2031mutex_init(&cs35l41->fw_mutex);20322033pm_runtime_set_autosuspend_delay(cs35l41->dev, 3000);2034pm_runtime_use_autosuspend(cs35l41->dev);2035pm_runtime_set_active(cs35l41->dev);2036pm_runtime_get_noresume(cs35l41->dev);2037pm_runtime_enable(cs35l41->dev);20382039ret = cs35l41_hda_apply_properties(cs35l41);2040if (ret)2041goto err_pm;20422043pm_runtime_put_autosuspend(cs35l41->dev);20442045ret = component_add(cs35l41->dev, &cs35l41_hda_comp_ops);2046if (ret) {2047dev_err_probe(cs35l41->dev, ret, "Register component failed\n");2048goto err_pm;2049}20502051dev_info(cs35l41->dev, "Cirrus Logic CS35L41 (%x), Revision: %02X\n", regid, reg_revid);20522053return 0;20542055err_pm:2056pm_runtime_dont_use_autosuspend(cs35l41->dev);2057pm_runtime_disable(cs35l41->dev);2058pm_runtime_put_noidle(cs35l41->dev);20592060err:2061if (cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type))2062gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);2063gpiod_put(cs35l41->reset_gpio);2064gpiod_put(cs35l41->cs_gpio);2065acpi_dev_put(cs35l41->dacpi);2066kfree(cs35l41->acpi_subsystem_id);20672068return ret;2069}2070EXPORT_SYMBOL_NS_GPL(cs35l41_hda_probe, "SND_HDA_SCODEC_CS35L41");20712072void cs35l41_hda_remove(struct device *dev)2073{2074struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);20752076component_del(cs35l41->dev, &cs35l41_hda_comp_ops);20772078pm_runtime_get_sync(cs35l41->dev);2079pm_runtime_dont_use_autosuspend(cs35l41->dev);2080pm_runtime_disable(cs35l41->dev);20812082if (cs35l41->halo_initialized)2083cs35l41_remove_dsp(cs35l41);20842085acpi_dev_put(cs35l41->dacpi);20862087pm_runtime_put_noidle(cs35l41->dev);20882089if (cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type))2090gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);2091gpiod_put(cs35l41->reset_gpio);2092gpiod_put(cs35l41->cs_gpio);2093kfree(cs35l41->acpi_subsystem_id);2094}2095EXPORT_SYMBOL_NS_GPL(cs35l41_hda_remove, "SND_HDA_SCODEC_CS35L41");20962097const struct dev_pm_ops cs35l41_hda_pm_ops = {2098RUNTIME_PM_OPS(cs35l41_runtime_suspend, cs35l41_runtime_resume,2099cs35l41_runtime_idle)2100.prepare = cs35l41_system_suspend_prep,2101SYSTEM_SLEEP_PM_OPS(cs35l41_system_suspend, cs35l41_system_resume)2102};2103EXPORT_SYMBOL_NS_GPL(cs35l41_hda_pm_ops, "SND_HDA_SCODEC_CS35L41");21042105MODULE_DESCRIPTION("CS35L41 HDA Driver");2106MODULE_IMPORT_NS("SND_SOC_CS_AMP_LIB");2107MODULE_AUTHOR("Lucas Tanure, Cirrus Logic Inc, <[email protected]>");2108MODULE_LICENSE("GPL");2109MODULE_IMPORT_NS("FW_CS_DSP");2110MODULE_FIRMWARE("cirrus/cs35l41-*.wmfw");2111MODULE_FIRMWARE("cirrus/cs35l41-*.bin");211221132114