diff options
Diffstat (limited to 'sound/soc/codecs/tas2781-i2c.c')
-rw-r--r-- | sound/soc/codecs/tas2781-i2c.c | 190 |
1 files changed, 142 insertions, 48 deletions
diff --git a/sound/soc/codecs/tas2781-i2c.c b/sound/soc/codecs/tas2781-i2c.c index 0e09d794516f..1539b70881d1 100644 --- a/sound/soc/codecs/tas2781-i2c.c +++ b/sound/soc/codecs/tas2781-i2c.c @@ -30,8 +30,10 @@ #include <sound/tas2781.h> #include <sound/tas2781-comlib-i2c.h> #include <sound/tlv.h> +#include <sound/tas2x20-tlv.h> #include <sound/tas2563-tlv.h> #include <sound/tas2781-tlv.h> +#include <sound/tas5825-tlv.h> #include <linux/unaligned.h> #define X2563_CL_STT_VAL(xreg, xval) \ @@ -98,16 +100,32 @@ static const struct bulk_reg_val tas2781_cali_start_reg[] = { }; static const struct i2c_device_id tasdevice_id[] = { + { "tas2020", TAS2020 }, + { "tas2118", TAS2118 }, + { "tas2120", TAS2120 }, + { "tas2320", TAS2320 }, { "tas2563", TAS2563 }, + { "tas2570", TAS2570 }, + { "tas2572", TAS2572 }, { "tas2781", TAS2781 }, + { "tas5825", TAS5825 }, + { "tas5827", TAS5827 }, {} }; MODULE_DEVICE_TABLE(i2c, tasdevice_id); #ifdef CONFIG_OF static const struct of_device_id tasdevice_of_match[] = { + { .compatible = "ti,tas2020" }, + { .compatible = "ti,tas2118" }, + { .compatible = "ti,tas2120" }, + { .compatible = "ti,tas2320" }, { .compatible = "ti,tas2563" }, + { .compatible = "ti,tas2570" }, + { .compatible = "ti,tas2572" }, { .compatible = "ti,tas2781" }, + { .compatible = "ti,tas5825" }, + { .compatible = "ti,tas5827" }, {}, }; MODULE_DEVICE_TABLE(of, tasdevice_of_match); @@ -797,7 +815,7 @@ static int tasdev_nop_get( return 0; } -static int tas2563_digital_gain_get( +static int tasdevice_digital_gain_get( struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -823,15 +841,15 @@ static int tas2563_digital_gain_get( while (r > 1 + l) { mid = (l + r) / 2; - ar_mid = get_unaligned_be32(tas2563_dvc_table[mid]); + ar_mid = get_unaligned_be32(tas_dev->dvc_tlv_table[mid]); if (target < ar_mid) r = mid; else l = mid; } - ar_l = get_unaligned_be32(tas2563_dvc_table[l]); - ar_r = get_unaligned_be32(tas2563_dvc_table[r]); + ar_l = get_unaligned_be32(tas_dev->dvc_tlv_table[l]); + ar_r = get_unaligned_be32(tas_dev->dvc_tlv_table[r]); /* find out the member same as or closer to the current volume */ ucontrol->value.integer.value[0] = @@ -841,7 +859,7 @@ out: return 0; } -static int tas2563_digital_gain_put( +static int tasdevice_digital_gain_put( struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -867,7 +885,7 @@ static int tas2563_digital_gain_put( } volrd = get_unaligned_be32(&data[0]); - volwr = get_unaligned_be32(tas2563_dvc_table[vol]); + volwr = get_unaligned_be32(tas_dev->dvc_tlv_table[vol]); if (volrd == volwr) { rc = 0; @@ -876,7 +894,7 @@ static int tas2563_digital_gain_put( for (i = 0; i < tas_dev->ndev; i++) { ret = tasdevice_dev_bulk_write(tas_dev, i, reg, - (unsigned char *)tas2563_dvc_table[vol], 4); + (unsigned char *)tas_dev->dvc_tlv_table[vol], 4); if (ret) { dev_err(tas_dev->dev, "%s, set digital vol error in dev %d\n", @@ -892,11 +910,6 @@ out: return rc; } -static const struct snd_kcontrol_new tasdevice_snd_controls[] = { - SOC_SINGLE_BOOL_EXT("Speaker Force Firmware Load", 0, - tasdev_force_fwload_get, tasdev_force_fwload_put), -}; - static const struct snd_kcontrol_new tasdevice_cali_controls[] = { SOC_SINGLE_EXT("Calibration Stop", SND_SOC_NOPM, 0, 1, 0, tasdev_nop_get, tasdev_calib_stop_put), @@ -907,6 +920,16 @@ static const struct snd_kcontrol_new tasdevice_cali_controls[] = { SND_SOC_BYTES_EXT("Amp XMA2 Data", 6, tasdev_XMA2_data_get, NULL), }; +static const struct snd_kcontrol_new tas2x20_snd_controls[] = { + SOC_SINGLE_RANGE_EXT_TLV("Speaker Analog Volume", TAS2X20_AMP_LEVEL, + 0, 0, 42, 1, tas2781_amp_getvol, + tas2781_amp_putvol, tas2x20_amp_tlv), + SOC_SINGLE_RANGE_EXT_TLV("Speaker Digital Volume", TAS2X20_DVC_LEVEL, + 0, 0, ARRAY_SIZE(tas2x20_dvc_table) - 1, 0, + tasdevice_digital_gain_get, tasdevice_digital_gain_put, + tas2x20_dvc_tlv), +}; + static const struct snd_kcontrol_new tas2781_snd_controls[] = { SOC_SINGLE_RANGE_EXT_TLV("Speaker Analog Volume", TAS2781_AMP_LEVEL, 1, 0, 20, 0, tas2781_amp_getvol, @@ -916,6 +939,15 @@ static const struct snd_kcontrol_new tas2781_snd_controls[] = { tas2781_digital_putvol, tas2781_dvc_tlv), }; +static const struct snd_kcontrol_new tas5825_snd_controls[] = { + SOC_SINGLE_RANGE_EXT_TLV("Speaker Analog Volume", TAS5825_AMP_LEVEL, + 0, 0, 31, 1, tas2781_amp_getvol, + tas2781_amp_putvol, tas5825_amp_tlv), + SOC_SINGLE_RANGE_EXT_TLV("Speaker Digital Volume", TAS5825_DVC_LEVEL, + 0, 0, 254, 1, tas2781_amp_getvol, + tas2781_amp_putvol, tas5825_dvc_tlv), +}; + static const struct snd_kcontrol_new tas2781_cali_controls[] = { SND_SOC_BYTES_EXT("Amp Latch Data", 3, tas2781_latch_reg_get, NULL), }; @@ -923,7 +955,7 @@ static const struct snd_kcontrol_new tas2781_cali_controls[] = { static const struct snd_kcontrol_new tas2563_snd_controls[] = { SOC_SINGLE_RANGE_EXT_TLV("Speaker Digital Volume", TAS2563_DVC_LVL, 0, 0, ARRAY_SIZE(tas2563_dvc_table) - 1, 0, - tas2563_digital_gain_get, tas2563_digital_gain_put, + tasdevice_digital_gain_get, tasdevice_digital_gain_put, tas2563_dvc_tlv), }; @@ -968,8 +1000,8 @@ static int tasdevice_info_chip_id(struct snd_kcontrol *kcontrol, { uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 1; - uinfo->value.integer.min = TAS2563; - uinfo->value.integer.max = TAS2781; + uinfo->value.integer.min = TAS2020; + uinfo->value.integer.max = TAS_OTHERS; return 0; } @@ -1168,9 +1200,9 @@ static int tasdevice_active_num_put(struct snd_kcontrol *kcontrol, static int tasdevice_dsp_create_ctrls(struct tasdevice_priv *tas_priv) { struct snd_kcontrol_new *dsp_ctrls; - char *active_dev_num, *chip_id; + char *active_dev_num, *chip_id, *fw_load; char *conf_name, *prog_name; - int nr_controls = 4; + int nr_controls = 5; int mix_index = 0; /* Alloc kcontrol via devm_kzalloc, which don't manually @@ -1228,6 +1260,19 @@ static int tasdevice_dsp_create_ctrls(struct tasdevice_priv *tas_priv) dsp_ctrls[mix_index].get = tasdevice_get_chip_id; mix_index++; + fw_load = devm_kstrdup(tas_priv->dev, "Speaker Force Firmware Load", + GFP_KERNEL); + if (!fw_load) + return -ENOMEM; + + dsp_ctrls[mix_index].name = fw_load; + dsp_ctrls[mix_index].iface = SNDRV_CTL_ELEM_IFACE_MIXER; + dsp_ctrls[mix_index].info = snd_soc_info_bool_ext; + dsp_ctrls[mix_index].put = tasdev_force_fwload_put; + dsp_ctrls[mix_index].get = tasdev_force_fwload_get; + dsp_ctrls[mix_index].private_value = 0UL; + mix_index++; + return snd_soc_add_component_controls(tas_priv->codec, dsp_ctrls, nr_controls < mix_index ? nr_controls : mix_index); } @@ -1587,6 +1632,16 @@ static void tasdevice_fw_ready(const struct firmware *fmw, * failing to load DSP firmware is NOT an error. */ tas_priv->fw_state = TASDEVICE_RCA_FW_OK; + /* There is no DSP firmware required for TAS2118/2X20/257X. */ + switch (tas_priv->chip_id) { + case TAS2020: + case TAS2118: + case TAS2120: + case TAS2320: + case TAS2570: + case TAS2572: + goto out; + } if (tas_priv->name_prefix) scnprintf(tas_priv->coef_binaryname, 64, "%s-%s_coef.bin", tas_priv->name_prefix, tas_priv->dev_name); @@ -1608,39 +1663,48 @@ static void tasdevice_fw_ready(const struct firmware *fmw, dev_err(tas_priv->dev, "dsp controls error\n"); goto out; } - - ret = tasdevice_create_cali_ctrls(tas_priv); - if (ret) { - dev_err(tas_priv->dev, "cali controls error\n"); - goto out; - } - tas_priv->fw_state = TASDEVICE_DSP_FW_ALL_OK; - /* If calibrated data occurs error, dsp will still works with default - * calibrated data inside algo. - */ - for (i = 0; i < tas_priv->ndev; i++) { - if (tas_priv->name_prefix) - scnprintf(tas_priv->cal_binaryname[i], 64, - "%s-%s_cal_0x%02x.bin", tas_priv->name_prefix, - tas_priv->dev_name, - tas_priv->tasdevice[i].dev_addr); - else - scnprintf(tas_priv->cal_binaryname[i], 64, - "%s_cal_0x%02x.bin", tas_priv->dev_name, - tas_priv->tasdevice[i].dev_addr); - ret = tas2781_load_calibration(tas_priv, - tas_priv->cal_binaryname[i], i); - if (ret != 0) - dev_err(tas_priv->dev, - "%s: load %s error, default will effect\n", - __func__, tas_priv->cal_binaryname[i]); + /* There is no calibration required for TAS5825/TAS5827. */ + if (tas_priv->chip_id < TAS5825) { + ret = tasdevice_create_cali_ctrls(tas_priv); + if (ret) { + dev_err(tas_priv->dev, "cali controls error\n"); + goto out; + } + /* If calibrated data occurs error, dsp will still works + * with default calibrated data inside algo. + */ + for (i = 0; i < tas_priv->ndev; i++) { + if (tas_priv->name_prefix) + scnprintf(tas_priv->cal_binaryname[i], 64, + "%s-%s_cal_0x%02x.bin", + tas_priv->name_prefix, + tas_priv->dev_name, + tas_priv->tasdevice[i].dev_addr); + else + scnprintf(tas_priv->cal_binaryname[i], 64, + "%s_cal_0x%02x.bin", + tas_priv->dev_name, + tas_priv->tasdevice[i].dev_addr); + ret = tas2781_load_calibration(tas_priv, + tas_priv->cal_binaryname[i], i); + if (ret != 0) + dev_err(tas_priv->dev, + "%s: load %s error, keep default.\n", + __func__, tas_priv->cal_binaryname[i]); + } } tasdevice_prmg_load(tas_priv, 0); tas_priv->cur_prog = 0; + /* Init common setting for different audio profiles */ + if (tas_priv->rcabin.init_profile_id >= 0) + tasdevice_select_cfg_blk(tas_priv, + tas_priv->rcabin.init_profile_id, + TASDEVICE_BIN_BLK_PRE_POWER_UP); + #ifdef CONFIG_SND_SOC_TAS2781_ACOUST_I2C if (tas_priv->name_prefix) acoustic_debugfs_node = devm_kasprintf(tas_priv->dev, @@ -1653,8 +1717,14 @@ static void tasdevice_fw_ready(const struct firmware *fmw, #endif out: if (tas_priv->fw_state == TASDEVICE_RCA_FW_OK) { - /* If DSP FW fail, DSP kcontrol won't be created. */ - tasdevice_dsp_remove(tas_priv); + switch (tas_priv->chip_id) { + case TAS2563: + case TAS2781: + case TAS5825: + case TAS5827: + /* If DSP FW fail, DSP kcontrol won't be created. */ + tasdevice_dsp_remove(tas_priv); + } } mutex_unlock(&tas_priv->codec_lock); release_firmware(fmw); @@ -1798,13 +1868,30 @@ static int tasdevice_codec_probe(struct snd_soc_component *codec) int rc; switch (tas_priv->chip_id) { + case TAS2020: + case TAS2118: + case TAS2120: + case TAS2320: + case TAS2570: + case TAS2572: + p = (struct snd_kcontrol_new *)tas2x20_snd_controls; + size = ARRAY_SIZE(tas2x20_snd_controls); + tas_priv->dvc_tlv_table = tas2x20_dvc_table; + break; case TAS2781: p = (struct snd_kcontrol_new *)tas2781_snd_controls; size = ARRAY_SIZE(tas2781_snd_controls); break; + case TAS5825: + case TAS5827: + p = (struct snd_kcontrol_new *)tas5825_snd_controls; + size = ARRAY_SIZE(tas5825_snd_controls); + break; default: p = (struct snd_kcontrol_new *)tas2563_snd_controls; size = ARRAY_SIZE(tas2563_snd_controls); + tas_priv->dvc_tlv_table = tas2563_dvc_table; + break; } rc = snd_soc_add_component_controls(codec, p, size); @@ -1844,8 +1931,6 @@ static const struct snd_soc_component_driver soc_codec_driver_tasdevice = { .probe = tasdevice_codec_probe, .remove = tasdevice_codec_remove, - .controls = tasdevice_snd_controls, - .num_controls = ARRAY_SIZE(tasdevice_snd_controls), .dapm_widgets = tasdevice_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(tasdevice_dapm_widgets), .dapm_routes = tasdevice_audio_map, @@ -1961,7 +2046,16 @@ static void tasdevice_i2c_remove(struct i2c_client *client) #ifdef CONFIG_ACPI static const struct acpi_device_id tasdevice_acpi_match[] = { - { "TAS2781", TAS2781 }, + { "TXNW2020", TAS2020 }, + { "TXNW2118", TAS2118 }, + { "TXNW2120", TAS2120 }, + { "TXNW2320", TAS2320 }, + { "TXNW2563", TAS2563 }, + { "TXNW2570", TAS2570 }, + { "TXNW2572", TAS2572 }, + { "TXNW2781", TAS2781 }, + { "TXNW5825", TAS5825 }, + { "TXNW5827", TAS5827 }, {}, }; |