Path: blob/master/sound/hda/codecs/side-codecs/cs35l41_hda.c
51055 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);12561257guard(pm_runtime_active_auto)(cs35l41->dev);12581259guard(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}12681269static int cs35l41_fw_load_ctl_put(struct snd_kcontrol *kcontrol,1270struct snd_ctl_elem_value *ucontrol)1271{1272struct cs35l41_hda *cs35l41 = snd_kcontrol_chip(kcontrol);12731274if (cs35l41->request_fw_load == ucontrol->value.integer.value[0])1275return 0;12761277if (cs35l41->fw_request_ongoing) {1278dev_dbg(cs35l41->dev, "Existing request not complete\n");1279return -EBUSY;1280}12811282/* Check if playback is ongoing when initial request is made */1283if (cs35l41->playback_started) {1284dev_err(cs35l41->dev, "Cannot Load/Unload firmware during Playback\n");1285return -EBUSY;1286}12871288cs35l41->fw_request_ongoing = true;1289cs35l41->request_fw_load = ucontrol->value.integer.value[0];1290schedule_work(&cs35l41->fw_load_work);12911292return 1;1293}12941295static int cs35l41_fw_type_ctl_get(struct snd_kcontrol *kcontrol,1296struct snd_ctl_elem_value *ucontrol)1297{1298struct cs35l41_hda *cs35l41 = snd_kcontrol_chip(kcontrol);12991300ucontrol->value.enumerated.item[0] = cs35l41->firmware_type;13011302return 0;1303}13041305static int cs35l41_fw_type_ctl_put(struct snd_kcontrol *kcontrol,1306struct snd_ctl_elem_value *ucontrol)1307{1308struct cs35l41_hda *cs35l41 = snd_kcontrol_chip(kcontrol);13091310if (ucontrol->value.enumerated.item[0] < CS35L41_HDA_NUM_FW) {1311if (cs35l41->firmware_type != ucontrol->value.enumerated.item[0]) {1312cs35l41->firmware_type = ucontrol->value.enumerated.item[0];1313return 1;1314} else {1315return 0;1316}1317}13181319return -EINVAL;1320}13211322static int cs35l41_fw_type_ctl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)1323{1324return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(cs35l41_hda_fw_ids), cs35l41_hda_fw_ids);1325}13261327static int cs35l41_create_controls(struct cs35l41_hda *cs35l41)1328{1329char fw_type_ctl_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];1330char fw_load_ctl_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];1331char mute_override_ctl_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];1332struct snd_kcontrol_new fw_type_ctl = {1333.name = fw_type_ctl_name,1334.iface = SNDRV_CTL_ELEM_IFACE_CARD,1335.info = cs35l41_fw_type_ctl_info,1336.get = cs35l41_fw_type_ctl_get,1337.put = cs35l41_fw_type_ctl_put,1338};1339struct snd_kcontrol_new fw_load_ctl = {1340.name = fw_load_ctl_name,1341.iface = SNDRV_CTL_ELEM_IFACE_CARD,1342.info = snd_ctl_boolean_mono_info,1343.get = cs35l41_fw_load_ctl_get,1344.put = cs35l41_fw_load_ctl_put,1345};1346struct snd_kcontrol_new mute_override_ctl = {1347.name = mute_override_ctl_name,1348.iface = SNDRV_CTL_ELEM_IFACE_CARD,1349.info = snd_ctl_boolean_mono_info,1350.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,1351.get = cs35l41_mute_override_ctl_get,1352};1353int ret;13541355scnprintf(fw_type_ctl_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s DSP1 Firmware Type",1356cs35l41->amp_name);1357scnprintf(fw_load_ctl_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s DSP1 Firmware Load",1358cs35l41->amp_name);1359scnprintf(mute_override_ctl_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s Forced Mute Status",1360cs35l41->amp_name);13611362ret = snd_ctl_add(cs35l41->codec->card, snd_ctl_new1(&fw_type_ctl, cs35l41));1363if (ret) {1364dev_err(cs35l41->dev, "Failed to add KControl %s = %d\n", fw_type_ctl.name, ret);1365return ret;1366}13671368dev_dbg(cs35l41->dev, "Added Control %s\n", fw_type_ctl.name);13691370ret = snd_ctl_add(cs35l41->codec->card, snd_ctl_new1(&fw_load_ctl, cs35l41));1371if (ret) {1372dev_err(cs35l41->dev, "Failed to add KControl %s = %d\n", fw_load_ctl.name, ret);1373return ret;1374}13751376dev_dbg(cs35l41->dev, "Added Control %s\n", fw_load_ctl.name);13771378ret = snd_ctl_add(cs35l41->codec->card, snd_ctl_new1(&mute_override_ctl, cs35l41));1379if (ret) {1380dev_err(cs35l41->dev, "Failed to add KControl %s = %d\n", mute_override_ctl.name,1381ret);1382return ret;1383}13841385dev_dbg(cs35l41->dev, "Added Control %s\n", mute_override_ctl.name);13861387return 0;1388}13891390static bool cs35l41_dsm_supported(acpi_handle handle, unsigned int commands)1391{1392guid_t guid;13931394guid_parse(CS35L41_UUID, &guid);13951396return acpi_check_dsm(handle, &guid, 0, BIT(commands));1397}13981399static int cs35l41_get_acpi_mute_state(struct cs35l41_hda *cs35l41, acpi_handle handle)1400{1401guid_t guid;1402union acpi_object *ret;1403int mute = -ENODEV;14041405guid_parse(CS35L41_UUID, &guid);14061407if (cs35l41_dsm_supported(handle, CS35L41_DSM_GET_MUTE)) {1408ret = acpi_evaluate_dsm(handle, &guid, 0, CS35L41_DSM_GET_MUTE, NULL);1409if (!ret)1410return -EINVAL;1411mute = *ret->buffer.pointer;1412dev_dbg(cs35l41->dev, "CS35L41_DSM_GET_MUTE: %d\n", mute);1413}14141415dev_dbg(cs35l41->dev, "%s: %d\n", __func__, mute);14161417return mute;1418}14191420static void cs35l41_acpi_device_notify(acpi_handle handle, u32 event, struct device *dev)1421{1422struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);1423int mute;14241425if (event != CS35L41_NOTIFY_EVENT)1426return;14271428mute = cs35l41_get_acpi_mute_state(cs35l41, handle);1429if (mute < 0) {1430dev_warn(cs35l41->dev, "Unable to retrieve mute state: %d\n", mute);1431return;1432}14331434dev_dbg(cs35l41->dev, "Requesting mute value: %d\n", mute);1435cs35l41->mute_override = (mute > 0);1436cs35l41_mute(cs35l41->dev, cs35l41->mute_override);1437}14381439static int cs35l41_hda_bind(struct device *dev, struct device *master, void *master_data)1440{1441struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);1442struct hda_component_parent *parent = master_data;1443struct hda_component *comp;1444unsigned int sleep_flags;1445int ret = 0;14461447comp = hda_component_from_index(parent, cs35l41->index);1448if (!comp)1449return -EINVAL;14501451if (comp->dev)1452return -EBUSY;14531454guard(pm_runtime_active_auto)(dev);14551456mutex_lock(&cs35l41->fw_mutex);14571458comp->dev = dev;1459cs35l41->codec = parent->codec;1460if (!cs35l41->acpi_subsystem_id)1461cs35l41->acpi_subsystem_id = kasprintf(GFP_KERNEL, "%.8x",1462cs35l41->codec->core.subsystem_id);14631464strscpy(comp->name, dev_name(dev), sizeof(comp->name));14651466cs35l41->firmware_type = CS35L41_HDA_FW_SPK_PROT;14671468if (firmware_autostart) {1469dev_dbg(cs35l41->dev, "Firmware Autostart.\n");1470cs35l41->request_fw_load = true;1471if (cs35l41_smart_amp(cs35l41) < 0)1472dev_warn(cs35l41->dev, "Cannot Run Firmware, reverting to dsp bypass...\n");1473} else {1474dev_dbg(cs35l41->dev, "Firmware Autostart is disabled.\n");1475}14761477ret = cs35l41_create_controls(cs35l41);14781479comp->playback_hook = cs35l41_hda_playback_hook;1480comp->pre_playback_hook = cs35l41_hda_pre_playback_hook;1481comp->post_playback_hook = cs35l41_hda_post_playback_hook;1482comp->acpi_notify = cs35l41_acpi_device_notify;1483comp->adev = cs35l41->dacpi;14841485comp->acpi_notifications_supported = cs35l41_dsm_supported(acpi_device_handle(comp->adev),1486CS35L41_DSM_GET_MUTE);14871488cs35l41->mute_override = cs35l41_get_acpi_mute_state(cs35l41,1489acpi_device_handle(cs35l41->dacpi)) > 0;14901491mutex_unlock(&cs35l41->fw_mutex);14921493sleep_flags = lock_system_sleep();1494if (!device_link_add(&cs35l41->codec->core.dev, cs35l41->dev, DL_FLAG_STATELESS))1495dev_warn(dev, "Unable to create device link\n");1496unlock_system_sleep(sleep_flags);14971498dev_info(cs35l41->dev,1499"CS35L41 Bound - SSID: %s, BST: %d, VSPK: %d, CH: %c, FW EN: %d, SPKID: %d\n",1500cs35l41->acpi_subsystem_id, cs35l41->hw_cfg.bst_type,1501cs35l41->hw_cfg.gpio1.func == CS35l41_VSPK_SWITCH,1502channel_name[cs35l41->hw_cfg.spk_pos],1503cs35l41->cs_dsp.running, cs35l41->speaker_id);15041505return ret;1506}15071508static void cs35l41_hda_unbind(struct device *dev, struct device *master, void *master_data)1509{1510struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);1511struct hda_component_parent *parent = master_data;1512struct hda_component *comp;1513unsigned int sleep_flags;15141515comp = hda_component_from_index(parent, cs35l41->index);1516if (!comp)1517return;15181519if (comp->dev == dev) {1520sleep_flags = lock_system_sleep();1521device_link_remove(&cs35l41->codec->core.dev, cs35l41->dev);1522unlock_system_sleep(sleep_flags);1523memset(comp, 0, sizeof(*comp));1524}1525}15261527static const struct component_ops cs35l41_hda_comp_ops = {1528.bind = cs35l41_hda_bind,1529.unbind = cs35l41_hda_unbind,1530};15311532static irqreturn_t cs35l41_bst_short_err(int irq, void *data)1533{1534struct cs35l41_hda *cs35l41 = data;15351536dev_crit_ratelimited(cs35l41->dev, "LBST Error\n");1537set_bit(CS35L41_BST_SHORT_ERR_RLS_SHIFT, &cs35l41->irq_errors);15381539return IRQ_HANDLED;1540}15411542static irqreturn_t cs35l41_bst_dcm_uvp_err(int irq, void *data)1543{1544struct cs35l41_hda *cs35l41 = data;15451546dev_crit_ratelimited(cs35l41->dev, "DCM VBST Under Voltage Error\n");1547set_bit(CS35L41_BST_UVP_ERR_RLS_SHIFT, &cs35l41->irq_errors);15481549return IRQ_HANDLED;1550}15511552static irqreturn_t cs35l41_bst_ovp_err(int irq, void *data)1553{1554struct cs35l41_hda *cs35l41 = data;15551556dev_crit_ratelimited(cs35l41->dev, "VBST Over Voltage error\n");1557set_bit(CS35L41_BST_OVP_ERR_RLS_SHIFT, &cs35l41->irq_errors);15581559return IRQ_HANDLED;1560}15611562static irqreturn_t cs35l41_temp_err(int irq, void *data)1563{1564struct cs35l41_hda *cs35l41 = data;15651566dev_crit_ratelimited(cs35l41->dev, "Over temperature error\n");1567set_bit(CS35L41_TEMP_ERR_RLS_SHIFT, &cs35l41->irq_errors);15681569return IRQ_HANDLED;1570}15711572static irqreturn_t cs35l41_temp_warn(int irq, void *data)1573{1574struct cs35l41_hda *cs35l41 = data;15751576dev_crit_ratelimited(cs35l41->dev, "Over temperature warning\n");1577set_bit(CS35L41_TEMP_WARN_ERR_RLS_SHIFT, &cs35l41->irq_errors);15781579return IRQ_HANDLED;1580}15811582static irqreturn_t cs35l41_amp_short(int irq, void *data)1583{1584struct cs35l41_hda *cs35l41 = data;15851586dev_crit_ratelimited(cs35l41->dev, "Amp short error\n");1587set_bit(CS35L41_AMP_SHORT_ERR_RLS_SHIFT, &cs35l41->irq_errors);15881589return IRQ_HANDLED;1590}15911592static const struct cs35l41_irq cs35l41_irqs[] = {1593CS35L41_IRQ(BST_OVP_ERR, "Boost Overvoltage Error", cs35l41_bst_ovp_err),1594CS35L41_IRQ(BST_DCM_UVP_ERR, "Boost Undervoltage Error", cs35l41_bst_dcm_uvp_err),1595CS35L41_IRQ(BST_SHORT_ERR, "Boost Inductor Short Error", cs35l41_bst_short_err),1596CS35L41_IRQ(TEMP_WARN, "Temperature Warning", cs35l41_temp_warn),1597CS35L41_IRQ(TEMP_ERR, "Temperature Error", cs35l41_temp_err),1598CS35L41_IRQ(AMP_SHORT_ERR, "Amp Short", cs35l41_amp_short),1599};16001601static const struct regmap_irq cs35l41_reg_irqs[] = {1602CS35L41_REG_IRQ(IRQ1_STATUS1, BST_OVP_ERR),1603CS35L41_REG_IRQ(IRQ1_STATUS1, BST_DCM_UVP_ERR),1604CS35L41_REG_IRQ(IRQ1_STATUS1, BST_SHORT_ERR),1605CS35L41_REG_IRQ(IRQ1_STATUS1, TEMP_WARN),1606CS35L41_REG_IRQ(IRQ1_STATUS1, TEMP_ERR),1607CS35L41_REG_IRQ(IRQ1_STATUS1, AMP_SHORT_ERR),1608};16091610static const struct regmap_irq_chip cs35l41_regmap_irq_chip = {1611.name = "cs35l41 IRQ1 Controller",1612.status_base = CS35L41_IRQ1_STATUS1,1613.mask_base = CS35L41_IRQ1_MASK1,1614.ack_base = CS35L41_IRQ1_STATUS1,1615.num_regs = 4,1616.irqs = cs35l41_reg_irqs,1617.num_irqs = ARRAY_SIZE(cs35l41_reg_irqs),1618.runtime_pm = true,1619};16201621static void cs35l41_configure_interrupt(struct cs35l41_hda *cs35l41, int irq_pol)1622{1623int irq;1624int ret;1625int i;16261627if (!cs35l41->irq) {1628dev_warn(cs35l41->dev, "No Interrupt Found");1629goto err;1630}16311632ret = devm_regmap_add_irq_chip(cs35l41->dev, cs35l41->regmap, cs35l41->irq,1633IRQF_ONESHOT | IRQF_SHARED | irq_pol,16340, &cs35l41_regmap_irq_chip, &cs35l41->irq_data);1635if (ret) {1636dev_dbg(cs35l41->dev, "Unable to add IRQ Chip: %d.", ret);1637goto err;1638}16391640for (i = 0; i < ARRAY_SIZE(cs35l41_irqs); i++) {1641irq = regmap_irq_get_virq(cs35l41->irq_data, cs35l41_irqs[i].irq);1642if (irq < 0) {1643ret = irq;1644dev_dbg(cs35l41->dev, "Unable to map IRQ %s: %d.", cs35l41_irqs[i].name,1645ret);1646goto err;1647}16481649ret = devm_request_threaded_irq(cs35l41->dev, irq, NULL,1650cs35l41_irqs[i].handler,1651IRQF_ONESHOT | IRQF_SHARED | irq_pol,1652cs35l41_irqs[i].name, cs35l41);1653if (ret) {1654dev_dbg(cs35l41->dev, "Unable to allocate IRQ %s:: %d.",1655cs35l41_irqs[i].name, ret);1656goto err;1657}1658}1659return;1660err:1661dev_warn(cs35l41->dev,1662"IRQ Config Failed. Amp errors may not be recoverable without reboot.");1663}16641665static int cs35l41_hda_apply_properties(struct cs35l41_hda *cs35l41)1666{1667struct cs35l41_hw_cfg *hw_cfg = &cs35l41->hw_cfg;1668bool using_irq = false;1669int irq_pol;1670int ret;16711672if (!cs35l41->hw_cfg.valid)1673return -EINVAL;16741675ret = cs35l41_init_boost(cs35l41->dev, cs35l41->regmap, hw_cfg);1676if (ret)1677return ret;16781679if (hw_cfg->gpio1.valid) {1680switch (hw_cfg->gpio1.func) {1681case CS35L41_NOT_USED:1682break;1683case CS35l41_VSPK_SWITCH:1684hw_cfg->gpio1.func = CS35L41_GPIO1_GPIO;1685hw_cfg->gpio1.out_en = true;1686break;1687case CS35l41_SYNC:1688hw_cfg->gpio1.func = CS35L41_GPIO1_MDSYNC;1689break;1690default:1691dev_err(cs35l41->dev, "Invalid function %d for GPIO1\n",1692hw_cfg->gpio1.func);1693return -EINVAL;1694}1695}16961697if (hw_cfg->gpio2.valid) {1698switch (hw_cfg->gpio2.func) {1699case CS35L41_NOT_USED:1700break;1701case CS35L41_INTERRUPT:1702using_irq = true;1703hw_cfg->gpio2.func = CS35L41_GPIO2_INT_OPEN_DRAIN;1704break;1705default:1706dev_err(cs35l41->dev, "Invalid GPIO2 function %d\n", hw_cfg->gpio2.func);1707return -EINVAL;1708}1709}17101711irq_pol = cs35l41_gpio_config(cs35l41->regmap, hw_cfg);17121713if (using_irq)1714cs35l41_configure_interrupt(cs35l41, irq_pol);17151716return cs35l41_hda_channel_map(cs35l41);1717}17181719int cs35l41_get_speaker_id(struct device *dev, int amp_index, int num_amps, int fixed_gpio_id)1720{1721struct gpio_desc *speaker_id_desc;1722int speaker_id = -ENODEV;17231724if (fixed_gpio_id >= 0) {1725dev_dbg(dev, "Found Fixed Speaker ID GPIO (index = %d)\n", fixed_gpio_id);1726speaker_id_desc = gpiod_get_index(dev, NULL, fixed_gpio_id, GPIOD_IN);1727if (IS_ERR(speaker_id_desc)) {1728speaker_id = PTR_ERR(speaker_id_desc);1729return speaker_id;1730}1731speaker_id = gpiod_get_value_cansleep(speaker_id_desc);1732gpiod_put(speaker_id_desc);1733dev_dbg(dev, "Speaker ID = %d\n", speaker_id);1734} else {1735int base_index;1736int gpios_per_amp;1737int count;1738int tmp;1739int i;17401741count = gpiod_count(dev, "spk-id");1742if (count > 0) {1743speaker_id = 0;1744gpios_per_amp = count / num_amps;1745base_index = gpios_per_amp * amp_index;17461747if (count % num_amps)1748return -EINVAL;17491750dev_dbg(dev, "Found %d Speaker ID GPIOs per Amp\n", gpios_per_amp);17511752for (i = 0; i < gpios_per_amp; i++) {1753speaker_id_desc = gpiod_get_index(dev, "spk-id", i + base_index,1754GPIOD_IN);1755if (IS_ERR(speaker_id_desc)) {1756speaker_id = PTR_ERR(speaker_id_desc);1757break;1758}1759tmp = gpiod_get_value_cansleep(speaker_id_desc);1760gpiod_put(speaker_id_desc);1761if (tmp < 0) {1762speaker_id = tmp;1763break;1764}1765speaker_id |= tmp << i;1766}1767dev_dbg(dev, "Speaker ID = %d\n", speaker_id);1768}1769}1770return speaker_id;1771}17721773int cs35l41_hda_parse_acpi(struct cs35l41_hda *cs35l41, struct device *physdev, int id)1774{1775struct cs35l41_hw_cfg *hw_cfg = &cs35l41->hw_cfg;1776u32 values[HDA_MAX_COMPONENTS];1777char *property;1778size_t nval;1779int i, ret;17801781property = "cirrus,dev-index";1782ret = device_property_count_u32(physdev, property);1783if (ret <= 0)1784goto err;17851786if (ret > ARRAY_SIZE(values)) {1787ret = -EINVAL;1788goto err;1789}1790nval = ret;17911792ret = device_property_read_u32_array(physdev, property, values, nval);1793if (ret)1794goto err;17951796cs35l41->index = -1;1797for (i = 0; i < nval; i++) {1798if (values[i] == id) {1799cs35l41->index = i;1800break;1801}1802}1803if (cs35l41->index == -1) {1804dev_err(cs35l41->dev, "No index found in %s\n", property);1805ret = -ENODEV;1806goto err;1807}18081809/* To use the same release code for all laptop variants we can't use devm_ version of1810* gpiod_get here, as CLSA010* don't have a fully functional bios with an _DSD node1811*/1812cs35l41->reset_gpio = fwnode_gpiod_get_index(acpi_fwnode_handle(cs35l41->dacpi), "reset",1813cs35l41->index, GPIOD_OUT_LOW,1814"cs35l41-reset");18151816property = "cirrus,speaker-position";1817ret = device_property_read_u32_array(physdev, property, values, nval);1818if (ret)1819goto err;1820hw_cfg->spk_pos = values[cs35l41->index];18211822cs35l41->channel_index = 0;1823for (i = 0; i < cs35l41->index; i++)1824if (values[i] == hw_cfg->spk_pos)1825cs35l41->channel_index++;18261827property = "cirrus,gpio1-func";1828ret = device_property_read_u32_array(physdev, property, values, nval);1829if (ret)1830goto err;1831hw_cfg->gpio1.func = values[cs35l41->index];1832hw_cfg->gpio1.valid = true;18331834property = "cirrus,gpio2-func";1835ret = device_property_read_u32_array(physdev, property, values, nval);1836if (ret)1837goto err;1838hw_cfg->gpio2.func = values[cs35l41->index];1839hw_cfg->gpio2.valid = true;18401841property = "cirrus,boost-peak-milliamp";1842ret = device_property_read_u32_array(physdev, property, values, nval);1843if (ret == 0)1844hw_cfg->bst_ipk = values[cs35l41->index];1845else1846hw_cfg->bst_ipk = -1;18471848property = "cirrus,boost-ind-nanohenry";1849ret = device_property_read_u32_array(physdev, property, values, nval);1850if (ret == 0)1851hw_cfg->bst_ind = values[cs35l41->index];1852else1853hw_cfg->bst_ind = -1;18541855property = "cirrus,boost-cap-microfarad";1856ret = device_property_read_u32_array(physdev, property, values, nval);1857if (ret == 0)1858hw_cfg->bst_cap = values[cs35l41->index];1859else1860hw_cfg->bst_cap = -1;18611862cs35l41->speaker_id = cs35l41_get_speaker_id(physdev, cs35l41->index, nval, -1);18631864if (hw_cfg->bst_ind > 0 || hw_cfg->bst_cap > 0 || hw_cfg->bst_ipk > 0)1865hw_cfg->bst_type = CS35L41_INT_BOOST;1866else1867hw_cfg->bst_type = CS35L41_EXT_BOOST;18681869hw_cfg->valid = true;18701871return 0;1872err:1873dev_err(cs35l41->dev, "Failed property %s: %d\n", property, ret);1874hw_cfg->valid = false;1875hw_cfg->gpio1.valid = false;1876hw_cfg->gpio2.valid = false;1877acpi_dev_put(cs35l41->dacpi);18781879return ret;1880}18811882static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, int id)1883{1884struct acpi_device *adev;1885struct device *physdev;1886struct spi_device *spi;1887const char *sub;1888int ret;18891890adev = acpi_dev_get_first_match_dev(hid, NULL, -1);1891if (!adev) {1892dev_err(cs35l41->dev, "Failed to find an ACPI device for %s\n", hid);1893return -ENODEV;1894}18951896cs35l41->dacpi = adev;1897physdev = get_device(acpi_get_first_physical_node(adev));1898if (!physdev)1899return -ENODEV;19001901sub = acpi_get_subsystem_id(ACPI_HANDLE(physdev));1902if (IS_ERR(sub))1903sub = NULL;1904cs35l41->acpi_subsystem_id = sub;19051906ret = cs35l41_add_dsd_properties(cs35l41, physdev, id, hid);1907if (!ret) {1908dev_info(cs35l41->dev, "Using extra _DSD properties, bypassing _DSD in ACPI\n");1909goto out;1910}19111912ret = cs35l41_hda_parse_acpi(cs35l41, physdev, id);1913if (ret) {1914put_device(physdev);1915return ret;1916}1917out:1918put_device(physdev);19191920cs35l41->bypass_fw = false;1921if (cs35l41->control_bus == SPI) {1922spi = to_spi_device(cs35l41->dev);1923if (spi->max_speed_hz < CS35L41_MAX_ACCEPTABLE_SPI_SPEED_HZ) {1924dev_warn(cs35l41->dev,1925"SPI speed is too slow to support firmware download: %d Hz.\n",1926spi->max_speed_hz);1927cs35l41->bypass_fw = true;1928}1929}19301931return 0;1932}19331934int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int irq,1935struct regmap *regmap, enum control_bus control_bus)1936{1937unsigned int regid, reg_revid;1938struct cs35l41_hda *cs35l41;1939int ret;19401941BUILD_BUG_ON(ARRAY_SIZE(cs35l41_irqs) != ARRAY_SIZE(cs35l41_reg_irqs));1942BUILD_BUG_ON(ARRAY_SIZE(cs35l41_irqs) != CS35L41_NUM_IRQ);19431944if (IS_ERR(regmap))1945return PTR_ERR(regmap);19461947cs35l41 = devm_kzalloc(dev, sizeof(*cs35l41), GFP_KERNEL);1948if (!cs35l41)1949return -ENOMEM;19501951cs35l41->dev = dev;1952cs35l41->irq = irq;1953cs35l41->regmap = regmap;1954cs35l41->control_bus = control_bus;1955dev_set_drvdata(dev, cs35l41);19561957ret = cs35l41_hda_read_acpi(cs35l41, device_name, id);1958if (ret)1959return dev_err_probe(cs35l41->dev, ret, "Platform not supported\n");19601961if (IS_ERR(cs35l41->reset_gpio)) {1962ret = PTR_ERR(cs35l41->reset_gpio);1963cs35l41->reset_gpio = NULL;1964if (ret == -EBUSY) {1965dev_info(cs35l41->dev, "Reset line busy, assuming shared reset\n");1966} else {1967dev_err_probe(cs35l41->dev, ret, "Failed to get reset GPIO\n");1968goto err;1969}1970}1971if (cs35l41->reset_gpio) {1972gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);1973usleep_range(2000, 2100);1974gpiod_set_value_cansleep(cs35l41->reset_gpio, 1);1975}19761977usleep_range(2000, 2100);1978regmap_write(cs35l41->regmap, CS35L41_SFT_RESET, CS35L41_SOFTWARE_RESET);1979usleep_range(2000, 2100);19801981ret = cs35l41_wait_boot_done(cs35l41);1982if (ret)1983goto err;19841985ret = cs35l41_verify_id(cs35l41, ®id, ®_revid);1986if (ret)1987goto err;19881989ret = cs35l41_test_key_unlock(cs35l41->dev, cs35l41->regmap);1990if (ret)1991goto err;19921993ret = cs35l41_register_errata_patch(cs35l41->dev, cs35l41->regmap, reg_revid);1994if (ret)1995goto err;19961997ret = cs35l41_otp_unpack(cs35l41->dev, cs35l41->regmap);1998if (ret) {1999dev_err_probe(cs35l41->dev, ret, "OTP Unpack failed\n");2000goto err;2001}20022003ret = cs35l41_test_key_lock(cs35l41->dev, cs35l41->regmap);2004if (ret)2005goto err;20062007ret = cs35l41_get_calibration(cs35l41);2008if (ret && ret != -ENOENT)2009goto err;20102011cs35l41_mute(cs35l41->dev, true);20122013INIT_WORK(&cs35l41->fw_load_work, cs35l41_fw_load_work);2014mutex_init(&cs35l41->fw_mutex);20152016pm_runtime_set_autosuspend_delay(cs35l41->dev, 3000);2017pm_runtime_use_autosuspend(cs35l41->dev);2018pm_runtime_set_active(cs35l41->dev);2019pm_runtime_get_noresume(cs35l41->dev);2020pm_runtime_enable(cs35l41->dev);20212022ret = cs35l41_hda_apply_properties(cs35l41);2023if (ret)2024goto err_pm;20252026pm_runtime_put_autosuspend(cs35l41->dev);20272028ret = component_add(cs35l41->dev, &cs35l41_hda_comp_ops);2029if (ret) {2030dev_err_probe(cs35l41->dev, ret, "Register component failed\n");2031goto err_pm;2032}20332034dev_info(cs35l41->dev, "Cirrus Logic CS35L41 (%x), Revision: %02X\n", regid, reg_revid);20352036return 0;20372038err_pm:2039pm_runtime_dont_use_autosuspend(cs35l41->dev);2040pm_runtime_disable(cs35l41->dev);2041pm_runtime_put_noidle(cs35l41->dev);20422043err:2044if (cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type))2045gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);2046gpiod_put(cs35l41->reset_gpio);2047gpiod_put(cs35l41->cs_gpio);2048acpi_dev_put(cs35l41->dacpi);2049kfree(cs35l41->acpi_subsystem_id);20502051return ret;2052}2053EXPORT_SYMBOL_NS_GPL(cs35l41_hda_probe, "SND_HDA_SCODEC_CS35L41");20542055void cs35l41_hda_remove(struct device *dev)2056{2057struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);20582059component_del(cs35l41->dev, &cs35l41_hda_comp_ops);20602061pm_runtime_get_sync(cs35l41->dev);2062pm_runtime_dont_use_autosuspend(cs35l41->dev);2063pm_runtime_disable(cs35l41->dev);20642065if (cs35l41->halo_initialized)2066cs35l41_remove_dsp(cs35l41);20672068acpi_dev_put(cs35l41->dacpi);20692070pm_runtime_put_noidle(cs35l41->dev);20712072if (cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type))2073gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);2074gpiod_put(cs35l41->reset_gpio);2075gpiod_put(cs35l41->cs_gpio);2076kfree(cs35l41->acpi_subsystem_id);2077}2078EXPORT_SYMBOL_NS_GPL(cs35l41_hda_remove, "SND_HDA_SCODEC_CS35L41");20792080const struct dev_pm_ops cs35l41_hda_pm_ops = {2081RUNTIME_PM_OPS(cs35l41_runtime_suspend, cs35l41_runtime_resume,2082cs35l41_runtime_idle)2083.prepare = cs35l41_system_suspend_prep,2084SYSTEM_SLEEP_PM_OPS(cs35l41_system_suspend, cs35l41_system_resume)2085};2086EXPORT_SYMBOL_NS_GPL(cs35l41_hda_pm_ops, "SND_HDA_SCODEC_CS35L41");20872088MODULE_DESCRIPTION("CS35L41 HDA Driver");2089MODULE_IMPORT_NS("SND_SOC_CS_AMP_LIB");2090MODULE_AUTHOR("Lucas Tanure, Cirrus Logic Inc, <[email protected]>");2091MODULE_LICENSE("GPL");2092MODULE_IMPORT_NS("FW_CS_DSP");2093MODULE_FIRMWARE("cirrus/cs35l41-*.wmfw");2094MODULE_FIRMWARE("cirrus/cs35l41-*.bin");209520962097