summaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/tas2781_hda_i2c.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 18:47:50 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 18:47:50 +0000
commit7c0639a3af697d4ae7a5db4d2ecc09eed43cad35 (patch)
treeb28a6eef28064256422bed5e477ee51f2cbb0c0b /sound/pci/hda/tas2781_hda_i2c.c
parentAdding debian version 6.7.9-2. (diff)
downloadlinux-7c0639a3af697d4ae7a5db4d2ecc09eed43cad35.tar.xz
linux-7c0639a3af697d4ae7a5db4d2ecc09eed43cad35.zip
Merging upstream version 6.7.12.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sound/pci/hda/tas2781_hda_i2c.c')
-rw-r--r--sound/pci/hda/tas2781_hda_i2c.c145
1 files changed, 77 insertions, 68 deletions
diff --git a/sound/pci/hda/tas2781_hda_i2c.c b/sound/pci/hda/tas2781_hda_i2c.c
index 9f98965742..9f3dc13a3b 100644
--- a/sound/pci/hda/tas2781_hda_i2c.c
+++ b/sound/pci/hda/tas2781_hda_i2c.c
@@ -71,7 +71,7 @@ struct tas2781_hda {
struct snd_kcontrol *dsp_prog_ctl;
struct snd_kcontrol *dsp_conf_ctl;
struct snd_kcontrol *prof_ctl;
- struct snd_kcontrol *snd_ctls[3];
+ struct snd_kcontrol *snd_ctls[2];
};
static int tas2781_get_i2c_res(struct acpi_resource *ares, void *data)
@@ -142,11 +142,13 @@ static void tas2781_hda_playback_hook(struct device *dev, int action)
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);
@@ -177,8 +179,12 @@ static int tasdevice_get_profile_id(struct snd_kcontrol *kcontrol,
{
struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
+ mutex_lock(&tas_priv->codec_lock);
+
ucontrol->value.integer.value[0] = tas_priv->rcabin.profile_cfg_id;
+ mutex_unlock(&tas_priv->codec_lock);
+
return 0;
}
@@ -192,11 +198,15 @@ static int tasdevice_set_profile_id(struct snd_kcontrol *kcontrol,
val = clamp(nr_profile, 0, max);
+ mutex_lock(&tas_priv->codec_lock);
+
if (tas_priv->rcabin.profile_cfg_id != val) {
tas_priv->rcabin.profile_cfg_id = val;
ret = 1;
}
+ mutex_unlock(&tas_priv->codec_lock);
+
return ret;
}
@@ -233,8 +243,12 @@ static int tasdevice_program_get(struct snd_kcontrol *kcontrol,
{
struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
+ mutex_lock(&tas_priv->codec_lock);
+
ucontrol->value.integer.value[0] = tas_priv->cur_prog;
+ mutex_unlock(&tas_priv->codec_lock);
+
return 0;
}
@@ -249,11 +263,15 @@ static int tasdevice_program_put(struct snd_kcontrol *kcontrol,
val = clamp(nr_program, 0, max);
+ mutex_lock(&tas_priv->codec_lock);
+
if (tas_priv->cur_prog != val) {
tas_priv->cur_prog = val;
ret = 1;
}
+ mutex_unlock(&tas_priv->codec_lock);
+
return ret;
}
@@ -262,8 +280,12 @@ static int tasdevice_config_get(struct snd_kcontrol *kcontrol,
{
struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
+ mutex_lock(&tas_priv->codec_lock);
+
ucontrol->value.integer.value[0] = tas_priv->cur_conf;
+ mutex_unlock(&tas_priv->codec_lock);
+
return 0;
}
@@ -278,33 +300,16 @@ static int tasdevice_config_put(struct snd_kcontrol *kcontrol,
val = clamp(nr_config, 0, max);
+ mutex_lock(&tas_priv->codec_lock);
+
if (tas_priv->cur_conf != val) {
tas_priv->cur_conf = val;
ret = 1;
}
- return ret;
-}
+ mutex_unlock(&tas_priv->codec_lock);
-/*
- * tas2781_digital_getvol - get the volum control
- * @kcontrol: control pointer
- * @ucontrol: User data
- * Customer Kcontrol for tas2781 is primarily for regmap booking, paging
- * depends on internal regmap mechanism.
- * tas2781 contains book and page two-level register map, especially
- * book switching will set the register BXXP00R7F, after switching to the
- * correct book, then leverage the mechanism for paging to access the
- * register.
- */
-static int tas2781_digital_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;
-
- return tasdevice_digital_getvol(tas_priv, ucontrol, mc);
+ return ret;
}
static int tas2781_amp_getvol(struct snd_kcontrol *kcontrol,
@@ -313,19 +318,15 @@ static int tas2781_amp_getvol(struct snd_kcontrol *kcontrol,
struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
+ int ret;
- return tasdevice_amp_getvol(tas_priv, ucontrol, mc);
-}
+ mutex_lock(&tas_priv->codec_lock);
-static int tas2781_digital_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;
+ ret = tasdevice_amp_getvol(tas_priv, ucontrol, mc);
+
+ mutex_unlock(&tas_priv->codec_lock);
- /* The check of the given value is in tasdevice_digital_putvol. */
- return tasdevice_digital_putvol(tas_priv, ucontrol, mc);
+ return ret;
}
static int tas2781_amp_putvol(struct snd_kcontrol *kcontrol,
@@ -334,9 +335,16 @@ static int tas2781_amp_putvol(struct snd_kcontrol *kcontrol,
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);
/* The check of the given value is in tasdevice_amp_putvol. */
- return tasdevice_amp_putvol(tas_priv, ucontrol, mc);
+ 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,
@@ -344,10 +352,14 @@ static int tas2781_force_fwload_get(struct snd_kcontrol *kcontrol,
{
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 : Force FWload %s\n", __func__,
tas_priv->force_fwload_status ? "ON" : "OFF");
+ mutex_unlock(&tas_priv->codec_lock);
+
return 0;
}
@@ -357,6 +369,8 @@ static int tas2781_force_fwload_put(struct snd_kcontrol *kcontrol,
struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
bool change, val = (bool)ucontrol->value.integer.value[0];
+ mutex_lock(&tas_priv->codec_lock);
+
if (tas_priv->force_fwload_status == val)
change = false;
else {
@@ -366,6 +380,8 @@ static int tas2781_force_fwload_put(struct snd_kcontrol *kcontrol,
dev_dbg(tas_priv->dev, "%s : Force FWload %s\n", __func__,
tas_priv->force_fwload_status ? "ON" : "OFF");
+ mutex_unlock(&tas_priv->codec_lock);
+
return change;
}
@@ -373,9 +389,6 @@ 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_RANGE_EXT_TLV("Speaker Digital Gain", TAS2781_DVC_LVL,
- 0, 0, 200, 1, tas2781_digital_getvol,
- tas2781_digital_putvol, dvc_tlv),
ACARD_SINGLE_BOOL_EXT("Speaker Force Firmware Load", 0,
tas2781_force_fwload_get, tas2781_force_fwload_put),
};
@@ -479,7 +492,7 @@ static int tas2781_save_calibration(struct tasdevice_priv *tas_priv)
dev_dbg(tas_priv->dev, "%4ld-%2d-%2d, %2d:%2d:%2d\n",
tm->tm_year, tm->tm_mon, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
- tas2781_apply_calib(tas_priv);
+ tasdevice_apply_calibration(tas_priv);
} else
tas_priv->cali_data.total_sz = 0;
@@ -582,7 +595,10 @@ static void tasdev_fw_ready(const struct firmware *fmw, void *context)
/* If calibrated data occurs error, dsp will still works with default
* calibrated data inside algo.
*/
- tas2781_save_calibration(tas_priv);
+ tasdevice_save_calibration(tas_priv);
+
+ tasdevice_tuning_switch(tas_hda->priv, 0);
+ tas_hda->priv->playback_started = true;
out:
mutex_unlock(&tas_hda->priv->codec_lock);
@@ -683,10 +699,6 @@ static int tas2781_hda_i2c_probe(struct i2c_client *clt)
const char *device_name;
int ret;
- if (strstr(dev_name(&clt->dev), "TIAS2781"))
- device_name = "TIAS2781";
- else
- return -ENODEV;
tas_hda = devm_kzalloc(&clt->dev, sizeof(*tas_hda), GFP_KERNEL);
if (!tas_hda)
@@ -699,6 +711,13 @@ static int tas2781_hda_i2c_probe(struct i2c_client *clt)
if (!tas_hda->priv)
return -ENOMEM;
+ if (strstr(dev_name(&clt->dev), "TIAS2781")) {
+ device_name = "TIAS2781";
+ tas_hda->priv->save_calibration = tas2781_save_calibration;
+ tas_hda->priv->apply_calibration = tas2781_apply_calib;
+ } else
+ return -ENODEV;
+
tas_hda->priv->irq_info.irq = clt->irq;
ret = tas2781_read_acpi(tas_hda->priv, device_name);
if (ret)
@@ -740,23 +759,19 @@ static void tas2781_hda_i2c_remove(struct i2c_client *clt)
static int tas2781_runtime_suspend(struct device *dev)
{
struct tas2781_hda *tas_hda = dev_get_drvdata(dev);
- int i;
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;
}
- 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;
- }
-
mutex_unlock(&tas_hda->priv->codec_lock);
return 0;
@@ -765,8 +780,6 @@ static int tas2781_runtime_suspend(struct device *dev)
static int tas2781_runtime_resume(struct device *dev)
{
struct tas2781_hda *tas_hda = dev_get_drvdata(dev);
- unsigned long calib_data_sz =
- tas_hda->priv->ndev * TASDEVICE_SPEAKER_CALIBRATION_SIZE;
dev_dbg(tas_hda->dev, "Runtime Resume\n");
@@ -777,8 +790,7 @@ static int tas2781_runtime_resume(struct device *dev)
/* If calibrated data occurs error, dsp will still works with default
* calibrated data inside algo.
*/
- if (tas_hda->priv->cali_data.total_sz > calib_data_sz)
- tas2781_apply_calib(tas_hda->priv);
+ tasdevice_apply_calibration(tas_hda->priv);
mutex_unlock(&tas_hda->priv->codec_lock);
@@ -788,16 +800,16 @@ static int tas2781_runtime_resume(struct device *dev)
static int tas2781_system_suspend(struct device *dev)
{
struct tas2781_hda *tas_hda = dev_get_drvdata(dev);
- int ret;
dev_dbg(tas_hda->priv->dev, "System Suspend\n");
- ret = pm_runtime_force_suspend(dev);
- if (ret)
- return ret;
+ mutex_lock(&tas_hda->priv->codec_lock);
/* Shutdown chip before system suspend */
- tasdevice_tuning_switch(tas_hda->priv, 1);
+ 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.
@@ -809,15 +821,9 @@ static int tas2781_system_suspend(struct device *dev)
static int tas2781_system_resume(struct device *dev)
{
struct tas2781_hda *tas_hda = dev_get_drvdata(dev);
- unsigned long calib_data_sz =
- tas_hda->priv->ndev * TASDEVICE_SPEAKER_CALIBRATION_SIZE;
- int i, ret;
+ int i;
- dev_info(tas_hda->priv->dev, "System Resume\n");
-
- ret = pm_runtime_force_resume(dev);
- if (ret)
- return ret;
+ dev_dbg(tas_hda->priv->dev, "System Resume\n");
mutex_lock(&tas_hda->priv->codec_lock);
@@ -832,8 +838,11 @@ static int tas2781_system_resume(struct device *dev)
/* If calibrated data occurs error, dsp will still work with default
* calibrated data inside algo.
*/
- if (tas_hda->priv->cali_data.total_sz > calib_data_sz)
- tas2781_apply_calib(tas_hda->priv);
+ tasdevice_apply_calibration(tas_hda->priv);
+
+ if (tas_hda->priv->playback_started)
+ tasdevice_tuning_switch(tas_hda->priv, 0);
+
mutex_unlock(&tas_hda->priv->codec_lock);
return 0;