Path: blob/master/sound/hda/codecs/side-codecs/tas2781_hda_i2c.c
52655 views
// SPDX-License-Identifier: GPL-2.01//2// TAS2781 HDA I2C driver3//4// Copyright 2023 - 2026 Texas Instruments, Inc.5//6// Author: Shenghao Ding <[email protected]>7// Current maintainer: Baojun Xu <[email protected]>89#include <linux/unaligned.h>10#include <linux/acpi.h>11#include <linux/crc8.h>12#include <linux/crc32.h>13#include <linux/efi.h>14#include <linux/firmware.h>15#include <linux/i2c.h>16#include <linux/mod_devicetable.h>17#include <linux/module.h>18#include <linux/pci_ids.h>19#include <linux/pm_runtime.h>20#include <linux/regmap.h>21#include <sound/hda_codec.h>22#include <sound/soc.h>23#include <sound/tas2781.h>24#include <sound/tas2781-comlib-i2c.h>25#include <sound/tlv.h>26#include <sound/tas2770-tlv.h>27#include <sound/tas2781-tlv.h>28#include <sound/tas5825-tlv.h>2930#include "hda_local.h"31#include "hda_auto_parser.h"32#include "hda_component.h"33#include "hda_jack.h"34#include "../generic.h"35#include "tas2781_hda.h"3637#define TAS2563_CAL_VAR_NAME_MAX 1638#define TAS2563_CAL_ARRAY_SIZE 8039#define TAS2563_CAL_DATA_SIZE 440#define TAS2563_MAX_CHANNELS 441#define TAS2563_CAL_CH_SIZE 204243#define TAS2563_CAL_R0_LOW TASDEVICE_REG(0, 0x0f, 0x48)44#define TAS2563_CAL_POWER TASDEVICE_REG(0, 0x0d, 0x3c)45#define TAS2563_CAL_INVR0 TASDEVICE_REG(0, 0x0f, 0x40)46#define TAS2563_CAL_TLIM TASDEVICE_REG(0, 0x10, 0x14)47#define TAS2563_CAL_R0 TASDEVICE_REG(0, 0x0f, 0x34)4849enum device_chip_id {50HDA_TAS2563,51HDA_TAS2770,52HDA_TAS2781,53HDA_TAS5825,54HDA_OTHERS55};5657struct tas2781_hda_i2c_priv {58struct snd_kcontrol *snd_ctls[2];59int (*save_calibration)(struct tas2781_hda *h);6061int hda_chip_id;62bool skip_calibration;63};6465static int tas2781_get_i2c_res(struct acpi_resource *ares, void *data)66{67struct tasdevice_priv *tas_priv = data;68struct acpi_resource_i2c_serialbus *sb;6970if (i2c_acpi_get_i2c_resource(ares, &sb)) {71if (tas_priv->ndev < TASDEVICE_MAX_CHANNELS &&72sb->slave_address != tas_priv->global_addr) {73tas_priv->tasdevice[tas_priv->ndev].dev_addr =74(unsigned int)sb->slave_address;75tas_priv->ndev++;76}77}78return 1;79}8081static const struct acpi_gpio_params speakerid_gpios = { 0, 0, false };8283static const struct acpi_gpio_mapping tas2781_speaker_id_gpios[] = {84{ "speakerid-gpios", &speakerid_gpios, 1 },85{ }86};8788static int tas2781_read_acpi(struct tasdevice_priv *p, const char *hid)89{90struct gpio_desc *speaker_id;91struct acpi_device *adev;92struct device *physdev;93LIST_HEAD(resources);94const char *sub;95uint32_t subid;96int ret;9798adev = acpi_dev_get_first_match_dev(hid, NULL, -1);99if (!adev) {100dev_err(p->dev,101"Failed to find an ACPI device for %s\n", hid);102return -ENODEV;103}104105physdev = get_device(acpi_get_first_physical_node(adev));106ret = acpi_dev_get_resources(adev, &resources, tas2781_get_i2c_res, p);107if (ret < 0) {108dev_err(p->dev, "Failed to get ACPI resource.\n");109goto err;110}111sub = acpi_get_subsystem_id(ACPI_HANDLE(physdev));112if (IS_ERR(sub)) {113/* No subsys id in older tas2563 projects. */114if (!strncmp(hid, "INT8866", sizeof("INT8866"))) {115p->speaker_id = -1;116goto end_2563;117}118dev_err(p->dev, "Failed to get SUBSYS ID.\n");119ret = PTR_ERR(sub);120goto err;121}122/* Speaker id was needed for ASUS projects. */123ret = kstrtou32(sub, 16, &subid);124if (!ret && upper_16_bits(subid) == PCI_VENDOR_ID_ASUSTEK) {125ret = acpi_dev_add_driver_gpios(adev, tas2781_speaker_id_gpios);126if (ret < 0) {127dev_err(p->dev, "Failed to add driver gpio %d.\n",128ret);129p->speaker_id = -1;130goto end_2563;131}132133speaker_id = fwnode_gpiod_get_index(acpi_fwnode_handle(adev),134"speakerid", 0, GPIOD_IN, NULL);135if (!IS_ERR(speaker_id)) {136p->speaker_id = gpiod_get_value_cansleep(speaker_id);137dev_dbg(p->dev, "Got speaker id gpio from ACPI: %d.\n",138p->speaker_id);139gpiod_put(speaker_id);140} else {141p->speaker_id = -1;142ret = PTR_ERR(speaker_id);143dev_err(p->dev, "Get speaker id gpio failed %d.\n",144ret);145}146147acpi_dev_remove_driver_gpios(adev);148} else {149p->speaker_id = -1;150}151152end_2563:153acpi_dev_free_resource_list(&resources);154strscpy(p->dev_name, hid, sizeof(p->dev_name));155put_device(physdev);156acpi_dev_put(adev);157158return 0;159160err:161dev_err(p->dev, "read acpi error, ret: %d\n", ret);162put_device(physdev);163acpi_dev_put(adev);164165return ret;166}167168static void tas2781_hda_playback_hook(struct device *dev, int action)169{170struct tas2781_hda *tas_hda = dev_get_drvdata(dev);171172dev_dbg(tas_hda->dev, "%s: action = %d\n", __func__, action);173switch (action) {174case HDA_GEN_PCM_ACT_OPEN:175pm_runtime_get_sync(dev);176scoped_guard(mutex, &tas_hda->priv->codec_lock) {177tasdevice_tuning_switch(tas_hda->priv, 0);178tas_hda->priv->playback_started = true;179}180break;181case HDA_GEN_PCM_ACT_CLOSE:182scoped_guard(mutex, &tas_hda->priv->codec_lock) {183tasdevice_tuning_switch(tas_hda->priv, 1);184tas_hda->priv->playback_started = false;185}186187pm_runtime_put_autosuspend(dev);188break;189default:190break;191}192}193194static int tas2781_amp_getvol(struct snd_kcontrol *kcontrol,195struct snd_ctl_elem_value *ucontrol)196{197struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);198struct soc_mixer_control *mc =199(struct soc_mixer_control *)kcontrol->private_value;200int ret;201202guard(mutex)(&tas_priv->codec_lock);203204ret = tasdevice_amp_getvol(tas_priv, ucontrol, mc);205206dev_dbg(tas_priv->dev, "%s: kcontrol %s: %ld\n",207__func__, kcontrol->id.name, ucontrol->value.integer.value[0]);208209return ret;210}211212static int tas2781_amp_putvol(struct snd_kcontrol *kcontrol,213struct snd_ctl_elem_value *ucontrol)214{215struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);216struct soc_mixer_control *mc =217(struct soc_mixer_control *)kcontrol->private_value;218219guard(mutex)(&tas_priv->codec_lock);220221dev_dbg(tas_priv->dev, "%s: kcontrol %s: -> %ld\n",222__func__, kcontrol->id.name, ucontrol->value.integer.value[0]);223224/* The check of the given value is in tasdevice_amp_putvol. */225return tasdevice_amp_putvol(tas_priv, ucontrol, mc);226}227228static int tas2781_force_fwload_get(struct snd_kcontrol *kcontrol,229struct snd_ctl_elem_value *ucontrol)230{231struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);232233guard(mutex)(&tas_priv->codec_lock);234235ucontrol->value.integer.value[0] = (int)tas_priv->force_fwload_status;236dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d\n",237__func__, kcontrol->id.name, tas_priv->force_fwload_status);238239return 0;240}241242static int tas2781_force_fwload_put(struct snd_kcontrol *kcontrol,243struct snd_ctl_elem_value *ucontrol)244{245struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);246bool change, val = (bool)ucontrol->value.integer.value[0];247248guard(mutex)(&tas_priv->codec_lock);249250dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d -> %d\n",251__func__, kcontrol->id.name,252tas_priv->force_fwload_status, val);253254if (tas_priv->force_fwload_status == val)255change = false;256else {257change = true;258tas_priv->force_fwload_status = val;259}260261return change;262}263264static const struct snd_kcontrol_new tas2770_snd_controls[] = {265ACARD_SINGLE_RANGE_EXT_TLV("Speaker Analog Volume", TAS2770_AMP_LEVEL,2660, 0, 20, 0, tas2781_amp_getvol,267tas2781_amp_putvol, tas2770_amp_tlv),268ACARD_SINGLE_RANGE_EXT_TLV("Speaker Digital Volume", TAS2770_DVC_LEVEL,2690, 0, 200, 1, tas2781_amp_getvol,270tas2781_amp_putvol, tas2770_dvc_tlv),271};272273static const struct snd_kcontrol_new tas2781_snd_controls[] = {274ACARD_SINGLE_RANGE_EXT_TLV("Speaker Analog Volume", TAS2781_AMP_LEVEL,2751, 0, 20, 0, tas2781_amp_getvol,276tas2781_amp_putvol, tas2781_amp_tlv),277ACARD_SINGLE_BOOL_EXT("Speaker Force Firmware Load", 0,278tas2781_force_fwload_get, tas2781_force_fwload_put),279};280281static const struct snd_kcontrol_new tas5825_snd_controls[] = {282ACARD_SINGLE_RANGE_EXT_TLV("Speaker Analog Volume", TAS5825_AMP_LEVEL,2830, 0, 31, 1, tas2781_amp_getvol,284tas2781_amp_putvol, tas5825_amp_tlv),285ACARD_SINGLE_RANGE_EXT_TLV("Speaker Digital Volume", TAS5825_DVC_LEVEL,2860, 0, 254, 1, tas2781_amp_getvol,287tas2781_amp_putvol, tas5825_dvc_tlv),288ACARD_SINGLE_BOOL_EXT("Speaker Force Firmware Load", 0,289tas2781_force_fwload_get, tas2781_force_fwload_put),290};291292static const struct snd_kcontrol_new tasdevice_prof_ctrl = {293.name = "Speaker Profile Id",294.iface = SNDRV_CTL_ELEM_IFACE_CARD,295.info = tasdevice_info_profile,296.get = tasdevice_get_profile_id,297.put = tasdevice_set_profile_id,298};299300static const struct snd_kcontrol_new tasdevice_dsp_prog_ctrl = {301.name = "Speaker Program Id",302.iface = SNDRV_CTL_ELEM_IFACE_CARD,303.info = tasdevice_info_programs,304.get = tasdevice_program_get,305.put = tasdevice_program_put,306};307308static const struct snd_kcontrol_new tasdevice_dsp_conf_ctrl = {309.name = "Speaker Config Id",310.iface = SNDRV_CTL_ELEM_IFACE_CARD,311.info = tasdevice_info_config,312.get = tasdevice_config_get,313.put = tasdevice_config_put,314};315316static int tas2563_save_calibration(struct tas2781_hda *h)317{318efi_guid_t efi_guid = tasdev_fct_efi_guid[LENOVO];319char *vars[TASDEV_CALIB_N] = {320"R0_%d", "R0_Low_%d", "InvR0_%d", "Power_%d", "TLim_%d"321};322efi_char16_t efi_name[TAS2563_CAL_VAR_NAME_MAX];323unsigned long max_size = TAS2563_CAL_DATA_SIZE;324unsigned char var8[TAS2563_CAL_VAR_NAME_MAX];325struct tasdevice_priv *p = h->priv;326struct calidata *cd = &p->cali_data;327struct cali_reg *r = &cd->cali_reg_array;328unsigned int offset = 0;329unsigned char *data;330__be32 bedata;331efi_status_t status;332unsigned int attr;333int ret, i, j, k;334335if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE)) {336dev_err(p->dev, "%s: NO EFI FOUND!\n", __func__);337return -EINVAL;338}339340cd->cali_dat_sz_per_dev = TAS2563_CAL_DATA_SIZE * TASDEV_CALIB_N;341342/* extra byte for each device is the device number */343cd->total_sz = (cd->cali_dat_sz_per_dev + 1) * p->ndev;344data = cd->data = devm_kzalloc(p->dev, cd->total_sz,345GFP_KERNEL);346if (!data)347return -ENOMEM;348349for (i = 0; i < p->ndev; ++i) {350data[offset] = i;351offset++;352for (j = 0; j < TASDEV_CALIB_N; ++j) {353/* EFI name for calibration started with 1, not 0 */354ret = snprintf(var8, sizeof(var8), vars[j], i + 1);355if (ret < 0 || ret >= sizeof(var8) - 1) {356dev_err(p->dev, "%s: Read %s failed\n",357__func__, var8);358return -EINVAL;359}360/*361* Our variable names are ASCII by construction, but362* EFI names are wide chars. Convert and zero-pad.363*/364memset(efi_name, 0, sizeof(efi_name));365for (k = 0; k < sizeof(var8) && var8[k]; k++)366efi_name[k] = var8[k];367status = efi.get_variable(efi_name,368&efi_guid, &attr, &max_size,369&data[offset]);370if (status != EFI_SUCCESS ||371max_size != TAS2563_CAL_DATA_SIZE) {372dev_warn(p->dev,373"Dev %d: Caldat[%d] read failed %ld\n",374i, j, status);375return -EINVAL;376}377bedata = cpu_to_be32(*(uint32_t *)&data[offset]);378memcpy(&data[offset], &bedata, sizeof(bedata));379offset += TAS2563_CAL_DATA_SIZE;380}381}382383if (cd->total_sz != offset) {384dev_err(p->dev, "%s: tot_size(%lu) and offset(%u) mismatch\n",385__func__, cd->total_sz, offset);386return -EINVAL;387}388389r->r0_reg = TAS2563_CAL_R0;390r->invr0_reg = TAS2563_CAL_INVR0;391r->r0_low_reg = TAS2563_CAL_R0_LOW;392r->pow_reg = TAS2563_CAL_POWER;393r->tlimit_reg = TAS2563_CAL_TLIM;394395return 0;396}397398static void tas2781_hda_remove_controls(struct tas2781_hda *tas_hda)399{400struct tas2781_hda_i2c_priv *hda_priv = tas_hda->hda_priv;401struct hda_codec *codec = tas_hda->priv->codec;402403snd_ctl_remove(codec->card, tas_hda->dsp_prog_ctl);404snd_ctl_remove(codec->card, tas_hda->dsp_conf_ctl);405406for (int i = ARRAY_SIZE(hda_priv->snd_ctls) - 1; i >= 0; i--)407snd_ctl_remove(codec->card, hda_priv->snd_ctls[i]);408409snd_ctl_remove(codec->card, tas_hda->prof_ctl);410}411412static void tasdev_add_kcontrols(struct tasdevice_priv *tas_priv,413struct snd_kcontrol **ctls, struct hda_codec *codec,414const struct snd_kcontrol_new *tas_snd_ctrls, int num_ctls)415{416int i, ret;417418for (i = 0; i < num_ctls; i++) {419ctls[i] = snd_ctl_new1(420&tas_snd_ctrls[i], tas_priv);421ret = snd_ctl_add(codec->card, ctls[i]);422if (ret) {423dev_err(tas_priv->dev,424"Failed to add KControl %s = %d\n",425tas_snd_ctrls[i].name, ret);426break;427}428}429}430431static void tasdevice_dspfw_init(void *context)432{433struct tasdevice_priv *tas_priv = context;434struct tas2781_hda *tas_hda = dev_get_drvdata(tas_priv->dev);435struct tas2781_hda_i2c_priv *hda_priv = tas_hda->hda_priv;436struct hda_codec *codec = tas_priv->codec;437int ret;438439tasdevice_dsp_remove(tas_priv);440tas_priv->fw_state = TASDEVICE_DSP_FW_PENDING;441if (tas_priv->speaker_id >= 0) {442snprintf(tas_priv->coef_binaryname,443sizeof(tas_priv->coef_binaryname),444"TAS2XXX%04X%d.bin",445lower_16_bits(codec->core.subsystem_id),446tas_priv->speaker_id);447} else {448snprintf(tas_priv->coef_binaryname,449sizeof(tas_priv->coef_binaryname),450"TAS2XXX%04X.bin",451lower_16_bits(codec->core.subsystem_id));452}453ret = tasdevice_dsp_parser(tas_priv);454if (ret) {455dev_err(tas_priv->dev, "dspfw load %s error\n",456tas_priv->coef_binaryname);457tas_priv->fw_state = TASDEVICE_DSP_FW_FAIL;458return;459}460tasdev_add_kcontrols(tas_priv, &tas_hda->dsp_prog_ctl, codec,461&tasdevice_dsp_prog_ctrl, 1);462tasdev_add_kcontrols(tas_priv, &tas_hda->dsp_conf_ctl, codec,463&tasdevice_dsp_conf_ctrl, 1);464465tas_priv->fw_state = TASDEVICE_DSP_FW_ALL_OK;466tasdevice_prmg_load(tas_priv, 0);467if (tas_priv->fmw->nr_programs > 0)468tas_priv->cur_prog = 0;469if (tas_priv->fmw->nr_configurations > 0)470tas_priv->cur_conf = 0;471472/* Init common setting for different audio profiles */473if (tas_priv->rcabin.init_profile_id >= 0)474tasdevice_select_cfg_blk(tas_priv,475tas_priv->rcabin.init_profile_id,476TASDEVICE_BIN_BLK_PRE_POWER_UP);477478/* If calibrated data occurs error, dsp will still works with default479* calibrated data inside algo.480*/481if (!hda_priv->skip_calibration)482hda_priv->save_calibration(tas_hda);483}484485static void tasdev_fw_ready(const struct firmware *fmw, void *context)486{487struct tasdevice_priv *tas_priv = context;488struct tas2781_hda *tas_hda = dev_get_drvdata(tas_priv->dev);489struct tas2781_hda_i2c_priv *hda_priv = tas_hda->hda_priv;490struct hda_codec *codec = tas_priv->codec;491int ret;492493guard(pm_runtime_active_auto)(tas_priv->dev);494guard(mutex)(&tas_priv->codec_lock);495496ret = tasdevice_rca_parser(tas_priv, fmw);497if (ret)498goto out;499500tas_priv->fw_state = TASDEVICE_RCA_FW_OK;501tasdev_add_kcontrols(tas_priv, &tas_hda->prof_ctl, codec,502&tasdevice_prof_ctrl, 1);503504switch (hda_priv->hda_chip_id) {505case HDA_TAS2770:506tasdev_add_kcontrols(tas_priv, hda_priv->snd_ctls, codec,507&tas2770_snd_controls[0],508ARRAY_SIZE(tas2770_snd_controls));509break;510case HDA_TAS2781:511tasdev_add_kcontrols(tas_priv, hda_priv->snd_ctls, codec,512&tas2781_snd_controls[0],513ARRAY_SIZE(tas2781_snd_controls));514tasdevice_dspfw_init(context);515break;516case HDA_TAS5825:517tasdev_add_kcontrols(tas_priv, hda_priv->snd_ctls, codec,518&tas5825_snd_controls[0],519ARRAY_SIZE(tas5825_snd_controls));520tasdevice_dspfw_init(context);521break;522case HDA_TAS2563:523tasdevice_dspfw_init(context);524break;525default:526break;527}528529out:530release_firmware(fmw);531}532533static int tas2781_hda_bind(struct device *dev, struct device *master,534void *master_data)535{536struct tas2781_hda *tas_hda = dev_get_drvdata(dev);537struct tas2781_hda_i2c_priv *hda_priv = tas_hda->hda_priv;538struct hda_component_parent *parent = master_data;539struct hda_component *comp;540struct hda_codec *codec;541unsigned int subid;542int ret;543544comp = hda_component_from_index(parent, tas_hda->priv->index);545if (!comp)546return -EINVAL;547548if (comp->dev)549return -EBUSY;550551codec = parent->codec;552subid = codec->core.subsystem_id >> 16;553554switch (subid) {555case 0x1028:556tas_hda->catlog_id = DELL;557break;558case 0x103C:559tas_hda->catlog_id = HP;560break;561default:562tas_hda->catlog_id = LENOVO;563break;564}565566/*567* Using ASUS ROG Xbox Ally X (RC73XA) UEFI calibration data568* causes audio dropouts during playback, use fallback data569* from DSP firmware as a workaround.570*/571if (codec->core.subsystem_id == 0x10431384)572hda_priv->skip_calibration = true;573574guard(pm_runtime_active_auto)(dev);575576comp->dev = dev;577578strscpy(comp->name, dev_name(dev), sizeof(comp->name));579580ret = tascodec_init(tas_hda->priv, codec, THIS_MODULE, tasdev_fw_ready);581if (!ret)582comp->playback_hook = tas2781_hda_playback_hook;583584return ret;585}586587static void tas2781_hda_unbind(struct device *dev,588struct device *master, void *master_data)589{590struct tas2781_hda *tas_hda = dev_get_drvdata(dev);591struct hda_component_parent *parent = master_data;592struct hda_component *comp;593594comp = hda_component_from_index(parent, tas_hda->priv->index);595if (comp && (comp->dev == dev)) {596comp->dev = NULL;597memset(comp->name, 0, sizeof(comp->name));598comp->playback_hook = NULL;599}600601tas2781_hda_remove_controls(tas_hda);602603tasdevice_config_info_remove(tas_hda->priv);604tasdevice_dsp_remove(tas_hda->priv);605606tas_hda->priv->fw_state = TASDEVICE_DSP_FW_PENDING;607}608609static const struct component_ops tas2781_hda_comp_ops = {610.bind = tas2781_hda_bind,611.unbind = tas2781_hda_unbind,612};613614static int tas2781_hda_i2c_probe(struct i2c_client *clt)615{616struct tas2781_hda_i2c_priv *hda_priv;617struct tas2781_hda *tas_hda;618const char *device_name;619int ret;620621tas_hda = devm_kzalloc(&clt->dev, sizeof(*tas_hda), GFP_KERNEL);622if (!tas_hda)623return -ENOMEM;624625hda_priv = devm_kzalloc(&clt->dev, sizeof(*hda_priv), GFP_KERNEL);626if (!hda_priv)627return -ENOMEM;628629tas_hda->hda_priv = hda_priv;630631dev_set_drvdata(&clt->dev, tas_hda);632tas_hda->dev = &clt->dev;633634tas_hda->priv = tasdevice_kzalloc(clt);635if (!tas_hda->priv)636return -ENOMEM;637638if (strstr(dev_name(&clt->dev), "TIAS2781")) {639/*640* TAS2781, integrated on-chip DSP with641* global I2C address supported.642*/643device_name = "TIAS2781";644hda_priv->hda_chip_id = HDA_TAS2781;645hda_priv->save_calibration = tas2781_save_calibration;646tas_hda->priv->global_addr = TAS2781_GLOBAL_ADDR;647} else if (strstarts(dev_name(&clt->dev), "i2c-TXNW2770")) {648/*649* TAS2770, has no on-chip DSP, so no calibration data650* required; has no global I2C address supported.651*/652device_name = "TXNW2770";653hda_priv->hda_chip_id = HDA_TAS2770;654} else if (strstarts(dev_name(&clt->dev),655"i2c-TXNW2781:00-tas2781-hda.0")) {656device_name = "TXNW2781";657hda_priv->hda_chip_id = HDA_TAS2781;658hda_priv->save_calibration = tas2781_save_calibration;659tas_hda->priv->global_addr = TAS2781_GLOBAL_ADDR;660} else if (strstr(dev_name(&clt->dev), "INT8866")) {661/*662* TAS2563, integrated on-chip DSP with663* global I2C address supported.664*/665device_name = "INT8866";666hda_priv->hda_chip_id = HDA_TAS2563;667hda_priv->save_calibration = tas2563_save_calibration;668tas_hda->priv->global_addr = TAS2563_GLOBAL_ADDR;669} else if (strstarts(dev_name(&clt->dev), "i2c-TXNW5825")) {670/*671* TAS5825, integrated on-chip DSP without672* global I2C address and calibration supported.673*/674device_name = "TXNW5825";675hda_priv->hda_chip_id = HDA_TAS5825;676tas_hda->priv->chip_id = TAS5825;677} else {678return -ENODEV;679}680681tas_hda->priv->irq = clt->irq;682ret = tas2781_read_acpi(tas_hda->priv, device_name);683if (ret)684return dev_err_probe(tas_hda->dev, ret,685"Platform not supported\n");686687ret = tasdevice_init(tas_hda->priv);688if (ret)689goto err;690691pm_runtime_set_autosuspend_delay(tas_hda->dev, 3000);692pm_runtime_use_autosuspend(tas_hda->dev);693pm_runtime_mark_last_busy(tas_hda->dev);694pm_runtime_set_active(tas_hda->dev);695pm_runtime_enable(tas_hda->dev);696697tasdevice_reset(tas_hda->priv);698699ret = component_add(tas_hda->dev, &tas2781_hda_comp_ops);700if (ret) {701dev_err(tas_hda->dev, "Register component failed: %d\n", ret);702pm_runtime_disable(tas_hda->dev);703}704705err:706if (ret)707tas2781_hda_remove(&clt->dev, &tas2781_hda_comp_ops);708return ret;709}710711static void tas2781_hda_i2c_remove(struct i2c_client *clt)712{713tas2781_hda_remove(&clt->dev, &tas2781_hda_comp_ops);714}715716static int tas2781_runtime_suspend(struct device *dev)717{718struct tas2781_hda *tas_hda = dev_get_drvdata(dev);719720dev_dbg(tas_hda->dev, "Runtime Suspend\n");721722guard(mutex)(&tas_hda->priv->codec_lock);723724/* The driver powers up the amplifiers at module load time.725* Stop the playback if it's unused.726*/727if (tas_hda->priv->playback_started) {728tasdevice_tuning_switch(tas_hda->priv, 1);729tas_hda->priv->playback_started = false;730}731732return 0;733}734735static int tas2781_runtime_resume(struct device *dev)736{737struct tas2781_hda *tas_hda = dev_get_drvdata(dev);738739dev_dbg(tas_hda->dev, "Runtime Resume\n");740741guard(mutex)(&tas_hda->priv->codec_lock);742743tasdevice_prmg_load(tas_hda->priv, tas_hda->priv->cur_prog);744745return 0;746}747748static int tas2781_system_suspend(struct device *dev)749{750struct tas2781_hda *tas_hda = dev_get_drvdata(dev);751752dev_dbg(tas_hda->priv->dev, "System Suspend\n");753754guard(mutex)(&tas_hda->priv->codec_lock);755756/* Shutdown chip before system suspend */757if (tas_hda->priv->playback_started)758tasdevice_tuning_switch(tas_hda->priv, 1);759760/*761* Reset GPIO may be shared, so cannot reset here.762* However beyond this point, amps may be powered down.763*/764return 0;765}766767static int tas2781_system_resume(struct device *dev)768{769struct tas2781_hda *tas_hda = dev_get_drvdata(dev);770int i;771772dev_dbg(tas_hda->priv->dev, "System Resume\n");773774guard(mutex)(&tas_hda->priv->codec_lock);775776for (i = 0; i < tas_hda->priv->ndev; i++) {777tas_hda->priv->tasdevice[i].cur_book = -1;778tas_hda->priv->tasdevice[i].cur_prog = -1;779tas_hda->priv->tasdevice[i].cur_conf = -1;780}781tasdevice_reset(tas_hda->priv);782tasdevice_prmg_load(tas_hda->priv, tas_hda->priv->cur_prog);783784/* Init common setting for different audio profiles */785if (tas_hda->priv->rcabin.init_profile_id >= 0)786tasdevice_select_cfg_blk(tas_hda->priv,787tas_hda->priv->rcabin.init_profile_id,788TASDEVICE_BIN_BLK_PRE_POWER_UP);789790if (tas_hda->priv->playback_started)791tasdevice_tuning_switch(tas_hda->priv, 0);792793return 0;794}795796static const struct dev_pm_ops tas2781_hda_pm_ops = {797RUNTIME_PM_OPS(tas2781_runtime_suspend, tas2781_runtime_resume, NULL)798SYSTEM_SLEEP_PM_OPS(tas2781_system_suspend, tas2781_system_resume)799};800801static const struct i2c_device_id tas2781_hda_i2c_id[] = {802{ "tas2781-hda" },803{}804};805806static const struct acpi_device_id tas2781_acpi_hda_match[] = {807{"INT8866", 0 },808{"TIAS2781", 0 },809{"TXNW2770", 0 },810{"TXNW2781", 0 },811{"TXNW5825", 0 },812{}813};814MODULE_DEVICE_TABLE(acpi, tas2781_acpi_hda_match);815816static struct i2c_driver tas2781_hda_i2c_driver = {817.driver = {818.name = "tas2781-hda",819.acpi_match_table = tas2781_acpi_hda_match,820.pm = &tas2781_hda_pm_ops,821},822.id_table = tas2781_hda_i2c_id,823.probe = tas2781_hda_i2c_probe,824.remove = tas2781_hda_i2c_remove,825};826module_i2c_driver(tas2781_hda_i2c_driver);827828MODULE_DESCRIPTION("TAS2781 HDA Driver");829MODULE_AUTHOR("Shenghao Ding, TI, <[email protected]>");830MODULE_LICENSE("GPL");831MODULE_IMPORT_NS("SND_SOC_TAS2781_FMWLIB");832MODULE_IMPORT_NS("SND_HDA_SCODEC_TAS2781");833834835