diff options
Diffstat (limited to 'sound/pci/hda/tas2781_hda_i2c.c')
-rw-r--r-- | sound/pci/hda/tas2781_hda_i2c.c | 747 |
1 files changed, 0 insertions, 747 deletions
diff --git a/sound/pci/hda/tas2781_hda_i2c.c b/sound/pci/hda/tas2781_hda_i2c.c deleted file mode 100644 index d91eed9f7804..000000000000 --- a/sound/pci/hda/tas2781_hda_i2c.c +++ /dev/null @@ -1,747 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -// -// TAS2781 HDA I2C driver -// -// Copyright 2023 - 2025 Texas Instruments, Inc. -// -// Author: Shenghao Ding <shenghao-ding@ti.com> -// Current maintainer: Baojun Xu <baojun.xu@ti.com> - -#include <linux/unaligned.h> -#include <linux/acpi.h> -#include <linux/crc8.h> -#include <linux/crc32.h> -#include <linux/efi.h> -#include <linux/firmware.h> -#include <linux/i2c.h> -#include <linux/mod_devicetable.h> -#include <linux/module.h> -#include <linux/pci_ids.h> -#include <linux/pm_runtime.h> -#include <linux/regmap.h> -#include <sound/hda_codec.h> -#include <sound/soc.h> -#include <sound/tas2781.h> -#include <sound/tas2781-comlib-i2c.h> -#include <sound/tlv.h> -#include <sound/tas2781-tlv.h> - -#include "hda_local.h" -#include "hda_auto_parser.h" -#include "hda_component.h" -#include "hda_jack.h" -#include "hda_generic.h" -#include "tas2781_hda.h" - -#define TAS2563_CAL_VAR_NAME_MAX 16 -#define TAS2563_CAL_ARRAY_SIZE 80 -#define TAS2563_CAL_DATA_SIZE 4 -#define TAS2563_MAX_CHANNELS 4 -#define TAS2563_CAL_CH_SIZE 20 - -#define TAS2563_CAL_R0_LOW TASDEVICE_REG(0, 0x0f, 0x48) -#define TAS2563_CAL_POWER TASDEVICE_REG(0, 0x0d, 0x3c) -#define TAS2563_CAL_INVR0 TASDEVICE_REG(0, 0x0f, 0x40) -#define TAS2563_CAL_TLIM TASDEVICE_REG(0, 0x10, 0x14) -#define TAS2563_CAL_R0 TASDEVICE_REG(0, 0x0f, 0x34) - -struct tas2781_hda_i2c_priv { - struct snd_kcontrol *snd_ctls[2]; - int (*save_calibration)(struct tas2781_hda *h); -}; - -static int tas2781_get_i2c_res(struct acpi_resource *ares, void *data) -{ - struct tasdevice_priv *tas_priv = data; - struct acpi_resource_i2c_serialbus *sb; - - if (i2c_acpi_get_i2c_resource(ares, &sb)) { - if (tas_priv->ndev < TASDEVICE_MAX_CHANNELS && - sb->slave_address != tas_priv->global_addr) { - tas_priv->tasdevice[tas_priv->ndev].dev_addr = - (unsigned int)sb->slave_address; - tas_priv->ndev++; - } - } - return 1; -} - -static const struct acpi_gpio_params speakerid_gpios = { 0, 0, false }; - -static const struct acpi_gpio_mapping tas2781_speaker_id_gpios[] = { - { "speakerid-gpios", &speakerid_gpios, 1 }, - { } -}; - -static int tas2781_read_acpi(struct tasdevice_priv *p, const char *hid) -{ - struct acpi_device *adev; - struct device *physdev; - LIST_HEAD(resources); - const char *sub; - uint32_t subid; - int ret; - - adev = acpi_dev_get_first_match_dev(hid, NULL, -1); - if (!adev) { - dev_err(p->dev, - "Failed to find an ACPI device for %s\n", hid); - return -ENODEV; - } - - physdev = get_device(acpi_get_first_physical_node(adev)); - ret = acpi_dev_get_resources(adev, &resources, tas2781_get_i2c_res, p); - if (ret < 0) { - dev_err(p->dev, "Failed to get ACPI resource.\n"); - goto err; - } - sub = acpi_get_subsystem_id(ACPI_HANDLE(physdev)); - if (IS_ERR(sub)) { - /* No subsys id in older tas2563 projects. */ - if (!strncmp(hid, "INT8866", sizeof("INT8866"))) - goto end_2563; - dev_err(p->dev, "Failed to get SUBSYS ID.\n"); - ret = PTR_ERR(sub); - goto err; - } - /* Speaker id was needed for ASUS projects. */ - ret = kstrtou32(sub, 16, &subid); - if (!ret && upper_16_bits(subid) == PCI_VENDOR_ID_ASUSTEK) { - ret = devm_acpi_dev_add_driver_gpios(p->dev, - tas2781_speaker_id_gpios); - if (ret < 0) - dev_err(p->dev, "Failed to add driver gpio %d.\n", - ret); - p->speaker_id = devm_gpiod_get(p->dev, "speakerid", GPIOD_IN); - if (IS_ERR(p->speaker_id)) { - dev_err(p->dev, "Failed to get Speaker id.\n"); - ret = PTR_ERR(p->speaker_id); - goto err; - } - } else { - p->speaker_id = NULL; - } - -end_2563: - acpi_dev_free_resource_list(&resources); - strscpy(p->dev_name, hid, sizeof(p->dev_name)); - put_device(physdev); - acpi_dev_put(adev); - - return 0; - -err: - dev_err(p->dev, "read acpi error, ret: %d\n", ret); - put_device(physdev); - acpi_dev_put(adev); - - return ret; -} - -static void tas2781_hda_playback_hook(struct device *dev, int action) -{ - struct tas2781_hda *tas_hda = dev_get_drvdata(dev); - - dev_dbg(tas_hda->dev, "%s: action = %d\n", __func__, action); - switch (action) { - case HDA_GEN_PCM_ACT_OPEN: - pm_runtime_get_sync(dev); - mutex_lock(&tas_hda->priv->codec_lock); - tasdevice_tuning_switch(tas_hda->priv, 0); - tas_hda->priv->playback_started = true; - mutex_unlock(&tas_hda->priv->codec_lock); - break; - case HDA_GEN_PCM_ACT_CLOSE: - mutex_lock(&tas_hda->priv->codec_lock); - tasdevice_tuning_switch(tas_hda->priv, 1); - tas_hda->priv->playback_started = false; - mutex_unlock(&tas_hda->priv->codec_lock); - - pm_runtime_mark_last_busy(dev); - pm_runtime_put_autosuspend(dev); - break; - default: - break; - } -} - -static int tas2781_amp_getvol(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol); - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - int ret; - - mutex_lock(&tas_priv->codec_lock); - - ret = tasdevice_amp_getvol(tas_priv, ucontrol, mc); - - dev_dbg(tas_priv->dev, "%s: kcontrol %s: %ld\n", - __func__, kcontrol->id.name, ucontrol->value.integer.value[0]); - - mutex_unlock(&tas_priv->codec_lock); - - return ret; -} - -static int tas2781_amp_putvol(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol); - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - int ret; - - mutex_lock(&tas_priv->codec_lock); - - dev_dbg(tas_priv->dev, "%s: kcontrol %s: -> %ld\n", - __func__, kcontrol->id.name, ucontrol->value.integer.value[0]); - - /* The check of the given value is in tasdevice_amp_putvol. */ - ret = tasdevice_amp_putvol(tas_priv, ucontrol, mc); - - mutex_unlock(&tas_priv->codec_lock); - - return ret; -} - -static int tas2781_force_fwload_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol); - - mutex_lock(&tas_priv->codec_lock); - - ucontrol->value.integer.value[0] = (int)tas_priv->force_fwload_status; - dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d\n", - __func__, kcontrol->id.name, tas_priv->force_fwload_status); - - mutex_unlock(&tas_priv->codec_lock); - - return 0; -} - -static int tas2781_force_fwload_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol); - bool change, val = (bool)ucontrol->value.integer.value[0]; - - mutex_lock(&tas_priv->codec_lock); - - dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d -> %d\n", - __func__, kcontrol->id.name, - tas_priv->force_fwload_status, val); - - if (tas_priv->force_fwload_status == val) - change = false; - else { - change = true; - tas_priv->force_fwload_status = val; - } - - mutex_unlock(&tas_priv->codec_lock); - - return change; -} - -static const struct snd_kcontrol_new tas2781_snd_controls[] = { - ACARD_SINGLE_RANGE_EXT_TLV("Speaker Analog Gain", TAS2781_AMP_LEVEL, - 1, 0, 20, 0, tas2781_amp_getvol, - tas2781_amp_putvol, amp_vol_tlv), - ACARD_SINGLE_BOOL_EXT("Speaker Force Firmware Load", 0, - tas2781_force_fwload_get, tas2781_force_fwload_put), -}; - -static const struct snd_kcontrol_new tas2781_prof_ctrl = { - .name = "Speaker Profile Id", - .iface = SNDRV_CTL_ELEM_IFACE_CARD, - .info = tasdevice_info_profile, - .get = tasdevice_get_profile_id, - .put = tasdevice_set_profile_id, -}; - -static const struct snd_kcontrol_new tas2781_dsp_prog_ctrl = { - .name = "Speaker Program Id", - .iface = SNDRV_CTL_ELEM_IFACE_CARD, - .info = tasdevice_info_programs, - .get = tasdevice_program_get, - .put = tasdevice_program_put, -}; - -static const struct snd_kcontrol_new tas2781_dsp_conf_ctrl = { - .name = "Speaker Config Id", - .iface = SNDRV_CTL_ELEM_IFACE_CARD, - .info = tasdevice_info_config, - .get = tasdevice_config_get, - .put = tasdevice_config_put, -}; - -static int tas2563_save_calibration(struct tas2781_hda *h) -{ - efi_guid_t efi_guid = tasdev_fct_efi_guid[LENOVO]; - char *vars[TASDEV_CALIB_N] = { - "R0_%d", "InvR0_%d", "R0_Low_%d", "Power_%d", "TLim_%d" - }; - efi_char16_t efi_name[TAS2563_CAL_VAR_NAME_MAX]; - unsigned long max_size = TAS2563_CAL_DATA_SIZE; - unsigned char var8[TAS2563_CAL_VAR_NAME_MAX]; - struct tasdevice_priv *p = h->hda_priv; - struct calidata *cd = &p->cali_data; - struct cali_reg *r = &cd->cali_reg_array; - unsigned int offset = 0; - unsigned char *data; - efi_status_t status; - unsigned int attr; - int ret, i, j, k; - - cd->cali_dat_sz_per_dev = TAS2563_CAL_DATA_SIZE * TASDEV_CALIB_N; - - /* extra byte for each device is the device number */ - cd->total_sz = (cd->cali_dat_sz_per_dev + 1) * p->ndev; - data = cd->data = devm_kzalloc(p->dev, cd->total_sz, - GFP_KERNEL); - if (!data) - return -ENOMEM; - - for (i = 0; i < p->ndev; ++i) { - data[offset] = i; - offset++; - for (j = 0; j < TASDEV_CALIB_N; ++j) { - ret = snprintf(var8, sizeof(var8), vars[j], i); - - if (ret < 0 || ret >= sizeof(var8) - 1) { - dev_err(p->dev, "%s: Read %s failed\n", - __func__, var8); - return -EINVAL; - } - /* - * Our variable names are ASCII by construction, but - * EFI names are wide chars. Convert and zero-pad. - */ - memset(efi_name, 0, sizeof(efi_name)); - for (k = 0; k < sizeof(var8) && var8[k]; k++) - efi_name[k] = var8[k]; - status = efi.get_variable(efi_name, - &efi_guid, &attr, &max_size, - &data[offset]); - if (status != EFI_SUCCESS || - max_size != TAS2563_CAL_DATA_SIZE) { - dev_warn(p->dev, - "Dev %d: Caldat[%d] read failed %ld\n", - i, j, status); - return -EINVAL; - } - offset += TAS2563_CAL_DATA_SIZE; - } - } - - if (cd->total_sz != offset) { - dev_err(p->dev, "%s: tot_size(%lu) and offset(%u) dismatch\n", - __func__, cd->total_sz, offset); - return -EINVAL; - } - - r->r0_reg = TAS2563_CAL_R0; - r->invr0_reg = TAS2563_CAL_INVR0; - r->r0_low_reg = TAS2563_CAL_R0_LOW; - r->pow_reg = TAS2563_CAL_POWER; - r->tlimit_reg = TAS2563_CAL_TLIM; - - /* - * TAS2781_FMWLIB supports two solutions of calibrated data. One is - * from the driver itself: driver reads the calibrated files directly - * during probe; The other from user space: during init of audio hal, - * the audio hal will pass the calibrated data via kcontrol interface. - * Driver will store this data in "struct calidata" for use. For hda - * device, calibrated data are usunally saved into UEFI. So Hda side - * codec driver use the mixture of these two solutions, driver reads - * the data from UEFI, then store this data in "struct calidata" for - * use. - */ - p->is_user_space_calidata = true; - - return 0; -} - -static void tas2781_hda_remove_controls(struct tas2781_hda *tas_hda) -{ - struct tas2781_hda_i2c_priv *hda_priv = tas_hda->hda_priv; - struct hda_codec *codec = tas_hda->priv->codec; - - snd_ctl_remove(codec->card, tas_hda->dsp_prog_ctl); - snd_ctl_remove(codec->card, tas_hda->dsp_conf_ctl); - - for (int i = ARRAY_SIZE(hda_priv->snd_ctls) - 1; i >= 0; i--) - snd_ctl_remove(codec->card, hda_priv->snd_ctls[i]); - - snd_ctl_remove(codec->card, tas_hda->prof_ctl); -} - -static void tasdev_fw_ready(const struct firmware *fmw, void *context) -{ - struct tasdevice_priv *tas_priv = context; - struct tas2781_hda *tas_hda = dev_get_drvdata(tas_priv->dev); - struct tas2781_hda_i2c_priv *hda_priv = tas_hda->hda_priv; - struct hda_codec *codec = tas_priv->codec; - int i, ret, spk_id; - - pm_runtime_get_sync(tas_priv->dev); - mutex_lock(&tas_priv->codec_lock); - - ret = tasdevice_rca_parser(tas_priv, fmw); - if (ret) - goto out; - - tas_hda->prof_ctl = snd_ctl_new1(&tas2781_prof_ctrl, tas_priv); - ret = snd_ctl_add(codec->card, tas_hda->prof_ctl); - if (ret) { - dev_err(tas_priv->dev, - "Failed to add KControl %s = %d\n", - tas2781_prof_ctrl.name, ret); - goto out; - } - - for (i = 0; i < ARRAY_SIZE(tas2781_snd_controls); i++) { - hda_priv->snd_ctls[i] = snd_ctl_new1(&tas2781_snd_controls[i], - tas_priv); - ret = snd_ctl_add(codec->card, hda_priv->snd_ctls[i]); - if (ret) { - dev_err(tas_priv->dev, - "Failed to add KControl %s = %d\n", - tas2781_snd_controls[i].name, ret); - goto out; - } - } - - tasdevice_dsp_remove(tas_priv); - - tas_priv->fw_state = TASDEVICE_DSP_FW_PENDING; - if (tas_priv->speaker_id != NULL) { - // Speaker id need to be checked for ASUS only. - spk_id = gpiod_get_value(tas_priv->speaker_id); - if (spk_id < 0) { - // Speaker id is not valid, use default. - dev_dbg(tas_priv->dev, "Wrong spk_id = %d\n", spk_id); - spk_id = 0; - } - snprintf(tas_priv->coef_binaryname, - sizeof(tas_priv->coef_binaryname), - "TAS2XXX%04X%d.bin", - lower_16_bits(codec->core.subsystem_id), - spk_id); - } else { - snprintf(tas_priv->coef_binaryname, - sizeof(tas_priv->coef_binaryname), - "TAS2XXX%04X.bin", - lower_16_bits(codec->core.subsystem_id)); - } - ret = tasdevice_dsp_parser(tas_priv); - if (ret) { - dev_err(tas_priv->dev, "dspfw load %s error\n", - tas_priv->coef_binaryname); - tas_priv->fw_state = TASDEVICE_DSP_FW_FAIL; - goto out; - } - - tas_hda->dsp_prog_ctl = snd_ctl_new1(&tas2781_dsp_prog_ctrl, - tas_priv); - ret = snd_ctl_add(codec->card, tas_hda->dsp_prog_ctl); - if (ret) { - dev_err(tas_priv->dev, - "Failed to add KControl %s = %d\n", - tas2781_dsp_prog_ctrl.name, ret); - goto out; - } - - tas_hda->dsp_conf_ctl = snd_ctl_new1(&tas2781_dsp_conf_ctrl, - tas_priv); - ret = snd_ctl_add(codec->card, tas_hda->dsp_conf_ctl); - if (ret) { - dev_err(tas_priv->dev, - "Failed to add KControl %s = %d\n", - tas2781_dsp_conf_ctrl.name, ret); - goto out; - } - - tas_priv->fw_state = TASDEVICE_DSP_FW_ALL_OK; - tasdevice_prmg_load(tas_priv, 0); - if (tas_priv->fmw->nr_programs > 0) - tas_priv->cur_prog = 0; - if (tas_priv->fmw->nr_configurations > 0) - tas_priv->cur_conf = 0; - - /* If calibrated data occurs error, dsp will still works with default - * calibrated data inside algo. - */ - hda_priv->save_calibration(tas_hda); - - tasdevice_tuning_switch(tas_hda->priv, 0); - tas_hda->priv->playback_started = true; - -out: - mutex_unlock(&tas_hda->priv->codec_lock); - release_firmware(fmw); - pm_runtime_mark_last_busy(tas_hda->dev); - pm_runtime_put_autosuspend(tas_hda->dev); -} - -static int tas2781_hda_bind(struct device *dev, struct device *master, - void *master_data) -{ - struct tas2781_hda *tas_hda = dev_get_drvdata(dev); - struct hda_component_parent *parent = master_data; - struct hda_component *comp; - struct hda_codec *codec; - unsigned int subid; - int ret; - - comp = hda_component_from_index(parent, tas_hda->priv->index); - if (!comp) - return -EINVAL; - - if (comp->dev) - return -EBUSY; - - codec = parent->codec; - subid = codec->core.subsystem_id >> 16; - - switch (subid) { - case 0x1028: - tas_hda->catlog_id = DELL; - break; - default: - tas_hda->catlog_id = LENOVO; - break; - } - - pm_runtime_get_sync(dev); - - comp->dev = dev; - - strscpy(comp->name, dev_name(dev), sizeof(comp->name)); - - ret = tascodec_init(tas_hda->priv, codec, THIS_MODULE, tasdev_fw_ready); - if (!ret) - comp->playback_hook = tas2781_hda_playback_hook; - - pm_runtime_mark_last_busy(dev); - pm_runtime_put_autosuspend(dev); - - return ret; -} - -static void tas2781_hda_unbind(struct device *dev, - struct device *master, void *master_data) -{ - struct tas2781_hda *tas_hda = dev_get_drvdata(dev); - struct hda_component_parent *parent = master_data; - struct hda_component *comp; - - comp = hda_component_from_index(parent, tas_hda->priv->index); - if (comp && (comp->dev == dev)) { - comp->dev = NULL; - memset(comp->name, 0, sizeof(comp->name)); - comp->playback_hook = NULL; - } - - tas2781_hda_remove_controls(tas_hda); - - tasdevice_config_info_remove(tas_hda->priv); - tasdevice_dsp_remove(tas_hda->priv); - - tas_hda->priv->fw_state = TASDEVICE_DSP_FW_PENDING; -} - -static const struct component_ops tas2781_hda_comp_ops = { - .bind = tas2781_hda_bind, - .unbind = tas2781_hda_unbind, -}; - -static int tas2781_hda_i2c_probe(struct i2c_client *clt) -{ - struct tas2781_hda_i2c_priv *hda_priv; - struct tas2781_hda *tas_hda; - const char *device_name; - int ret; - - tas_hda = devm_kzalloc(&clt->dev, sizeof(*tas_hda), GFP_KERNEL); - if (!tas_hda) - return -ENOMEM; - - hda_priv = devm_kzalloc(&clt->dev, sizeof(*hda_priv), GFP_KERNEL); - if (!hda_priv) - return -ENOMEM; - - tas_hda->hda_priv = hda_priv; - - dev_set_drvdata(&clt->dev, tas_hda); - tas_hda->dev = &clt->dev; - - tas_hda->priv = tasdevice_kzalloc(clt); - if (!tas_hda->priv) - return -ENOMEM; - - if (strstr(dev_name(&clt->dev), "TIAS2781")) { - device_name = "TIAS2781"; - hda_priv->save_calibration = tas2781_save_calibration; - tas_hda->priv->global_addr = TAS2781_GLOBAL_ADDR; - } else if (strstr(dev_name(&clt->dev), "INT8866")) { - device_name = "INT8866"; - hda_priv->save_calibration = tas2563_save_calibration; - tas_hda->priv->global_addr = TAS2563_GLOBAL_ADDR; - } else - return -ENODEV; - - tas_hda->priv->irq = clt->irq; - ret = tas2781_read_acpi(tas_hda->priv, device_name); - if (ret) - return dev_err_probe(tas_hda->dev, ret, - "Platform not supported\n"); - - ret = tasdevice_init(tas_hda->priv); - if (ret) - goto err; - - pm_runtime_set_autosuspend_delay(tas_hda->dev, 3000); - pm_runtime_use_autosuspend(tas_hda->dev); - pm_runtime_mark_last_busy(tas_hda->dev); - pm_runtime_set_active(tas_hda->dev); - pm_runtime_enable(tas_hda->dev); - - tasdevice_reset(tas_hda->priv); - - ret = component_add(tas_hda->dev, &tas2781_hda_comp_ops); - if (ret) { - dev_err(tas_hda->dev, "Register component failed: %d\n", ret); - pm_runtime_disable(tas_hda->dev); - } - -err: - if (ret) - tas2781_hda_remove(&clt->dev, &tas2781_hda_comp_ops); - return ret; -} - -static void tas2781_hda_i2c_remove(struct i2c_client *clt) -{ - tas2781_hda_remove(&clt->dev, &tas2781_hda_comp_ops); -} - -static int tas2781_runtime_suspend(struct device *dev) -{ - struct tas2781_hda *tas_hda = dev_get_drvdata(dev); - - dev_dbg(tas_hda->dev, "Runtime Suspend\n"); - - mutex_lock(&tas_hda->priv->codec_lock); - - /* The driver powers up the amplifiers at module load time. - * Stop the playback if it's unused. - */ - if (tas_hda->priv->playback_started) { - tasdevice_tuning_switch(tas_hda->priv, 1); - tas_hda->priv->playback_started = false; - } - - mutex_unlock(&tas_hda->priv->codec_lock); - - return 0; -} - -static int tas2781_runtime_resume(struct device *dev) -{ - struct tas2781_hda *tas_hda = dev_get_drvdata(dev); - - dev_dbg(tas_hda->dev, "Runtime Resume\n"); - - mutex_lock(&tas_hda->priv->codec_lock); - - tasdevice_prmg_load(tas_hda->priv, tas_hda->priv->cur_prog); - - mutex_unlock(&tas_hda->priv->codec_lock); - - return 0; -} - -static int tas2781_system_suspend(struct device *dev) -{ - struct tas2781_hda *tas_hda = dev_get_drvdata(dev); - - dev_dbg(tas_hda->priv->dev, "System Suspend\n"); - - mutex_lock(&tas_hda->priv->codec_lock); - - /* Shutdown chip before system suspend */ - if (tas_hda->priv->playback_started) - tasdevice_tuning_switch(tas_hda->priv, 1); - - mutex_unlock(&tas_hda->priv->codec_lock); - - /* - * Reset GPIO may be shared, so cannot reset here. - * However beyond this point, amps may be powered down. - */ - return 0; -} - -static int tas2781_system_resume(struct device *dev) -{ - struct tas2781_hda *tas_hda = dev_get_drvdata(dev); - int i; - - dev_dbg(tas_hda->priv->dev, "System Resume\n"); - - mutex_lock(&tas_hda->priv->codec_lock); - - for (i = 0; i < tas_hda->priv->ndev; i++) { - tas_hda->priv->tasdevice[i].cur_book = -1; - tas_hda->priv->tasdevice[i].cur_prog = -1; - tas_hda->priv->tasdevice[i].cur_conf = -1; - } - tasdevice_reset(tas_hda->priv); - tasdevice_prmg_load(tas_hda->priv, tas_hda->priv->cur_prog); - - if (tas_hda->priv->playback_started) - tasdevice_tuning_switch(tas_hda->priv, 0); - - mutex_unlock(&tas_hda->priv->codec_lock); - - return 0; -} - -static const struct dev_pm_ops tas2781_hda_pm_ops = { - RUNTIME_PM_OPS(tas2781_runtime_suspend, tas2781_runtime_resume, NULL) - SYSTEM_SLEEP_PM_OPS(tas2781_system_suspend, tas2781_system_resume) -}; - -static const struct i2c_device_id tas2781_hda_i2c_id[] = { - { "tas2781-hda" }, - {} -}; - -static const struct acpi_device_id tas2781_acpi_hda_match[] = { - {"TIAS2781", 0 }, - {"INT8866", 0 }, - {} -}; -MODULE_DEVICE_TABLE(acpi, tas2781_acpi_hda_match); - -static struct i2c_driver tas2781_hda_i2c_driver = { - .driver = { - .name = "tas2781-hda", - .acpi_match_table = tas2781_acpi_hda_match, - .pm = &tas2781_hda_pm_ops, - }, - .id_table = tas2781_hda_i2c_id, - .probe = tas2781_hda_i2c_probe, - .remove = tas2781_hda_i2c_remove, -}; -module_i2c_driver(tas2781_hda_i2c_driver); - -MODULE_DESCRIPTION("TAS2781 HDA Driver"); -MODULE_AUTHOR("Shenghao Ding, TI, <shenghao-ding@ti.com>"); -MODULE_LICENSE("GPL"); -MODULE_IMPORT_NS("SND_SOC_TAS2781_FMWLIB"); -MODULE_IMPORT_NS("SND_HDA_SCODEC_TAS2781"); |