ASoC: codecs: tas5720: add TAS5722 specific volume control
PATCH v2 1/2 ASoC: codecs: tas5720: add TAS5722 specific volume control
From: Andreas Dannenberg <[email protected]>
The TAS5722 supports modifying volume in 0.25dB steps (as opposed to 0.5dB steps on the TAS5720). Introduce a custom mixer control that allows taking advantage of this finer output volume granularity.
Also add custom getters/setters for access as the TAS5722 digital volume controls are split over two registers.
---
Changes from v1:
- Revise commit message
- codec -> component
sound/soc/codecs/tas5720.c | 88 ++++++++++++++++++++++++++++++++++---- 1 file changed, 80 insertions(+), 8 deletions(-)
sound/soc/codecs/tas5720.c +80 -8
@@ -485,15 +485,56 @@ static const DECLARE_TLV_DB_RANGE(dac_analog_tlv, );/* -* DAC digital volumes. From -103.5 to 24 dB in 0.5 dB steps. Note that -* setting the gain below -100 dB (register value <0x7) is effectively a MUTE -* as per device datasheet. +* DAC digital volumes. From -103.5 to 24 dB in 0.5 dB or 0.25 dB steps +* depending on the device. Note that setting the gain below -100 dB +* (register value <0x7) is effectively a MUTE as per device datasheet. +* +* Note that for the TAS5722 the digital volume controls are actually split +* over two registers, so we need custom getters/setters for access. */ -static DECLARE_TLV_DB_SCALE(dac_tlv, -10350, 50, 0); +static DECLARE_TLV_DB_SCALE(tas5720_dac_tlv, -10350, 50, 0); +static DECLARE_TLV_DB_SCALE(tas5722_dac_tlv, -10350, 25, 0); + +static int tas5722_volume_get (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *component =snd_soc_kcontrol_component (kcontrol); +unsigned int val; + +snd_soc_component_read (component,TAS5720_VOLUME_CTRL_REG , &val); + ucontrol->value.integer.value[0 ] = val <<1 ; + +snd_soc_component_read (component,TAS5722_DIGITAL_CTRL2_REG , &val); + ucontrol->value.integer.value[0 ] |= val &TAS5722_VOL_CONTROL_LSB ; + +return 0 ; +} + +static int tas5722_volume_set (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *component =snd_soc_kcontrol_component (kcontrol); +unsigned int sel = ucontrol->value.integer.value[0 ]; + +snd_soc_component_write (component,TAS5720_VOLUME_CTRL_REG , sel >>1 ); +snd_soc_component_update_bits (component,TAS5722_DIGITAL_CTRL2_REG , +TAS5722_VOL_CONTROL_LSB , sel); + +return 0 ; +}static const struct snd_kcontrol_new tas5720_snd_controls[] = {SOC_SINGLE_TLV ("Speaker Driver Playback Volume" , -TAS5720_VOLUME_CTRL_REG ,0 ,0xff ,0 , dac_tlv), +TAS5720_VOLUME_CTRL_REG ,0 ,0xff ,0 , tas5720_dac_tlv), +SOC_SINGLE_TLV ("Speaker Driver Analog Gain" ,TAS5720_ANALOG_CTRL_REG , +TAS5720_ANALOG_GAIN_SHIFT ,3 ,0 , dac_analog_tlv), +}; + +static const struct snd_kcontrol_new tas5722_snd_controls[] = { +SOC_SINGLE_EXT_TLV ("Speaker Driver Playback Volume" , +0 ,0 ,511 ,0 , + tas5722_volume_get, tas5722_volume_set, + tas5722_dac_tlv),SOC_SINGLE_TLV ("Speaker Driver Analog Gain" ,TAS5720_ANALOG_CTRL_REG ,TAS5720_ANALOG_GAIN_SHIFT ,3 ,0 , dac_analog_tlv), };
@@ -527,6 +568,23 @@ static const struct snd_soc_component_driver soc_component_dev_tas5720 = { .non_legacy_dai_naming = 1, }; +static const struct snd_soc_component_driver soc_component_dev_tas5722 = { + .probe = tas5720_codec_probe, + .remove = tas5720_codec_remove, + .suspend = tas5720_suspend, + .resume = tas5720_resume, + .controls = tas5722_snd_controls, + .num_controls =ARRAY_SIZE (tas5722_snd_controls), + .dapm_widgets = tas5720_dapm_widgets, + .num_dapm_widgets =ARRAY_SIZE (tas5720_dapm_widgets), + .dapm_routes = tas5720_audio_map, + .num_dapm_routes =ARRAY_SIZE (tas5720_audio_map), + .idle_bias_on =1 , + .use_pmdown_time =1 , + .endianness =1 , + .non_legacy_dai_naming =1 , +}; +/* PCM rates supported by the TAS5720 driver */ #define TAS5720_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\ SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
@@ -613,9 +671,23 @@ static int tas5720_probe(struct i2c_client *client,dev_set_drvdata (dev, data); - ret =devm_snd_soc_register_component (&client->dev, - &soc_component_dev_tas5720, - tas5720_dai,ARRAY_SIZE (tas5720_dai)); +switch (id->driver_data) { +case TAS5720 : + ret =devm_snd_soc_register_component (&client->dev, + &soc_component_dev_tas5720, + tas5720_dai, +ARRAY_SIZE (tas5720_dai)); +break ; +case TAS5722 : + ret =devm_snd_soc_register_component (&client->dev, + &soc_component_dev_tas5722, + tas5720_dai, +ARRAY_SIZE (tas5720_dai)); +break ; +default : +dev_err (dev,"unexpected private driver data\n" ); +return -EINVAL ; + }if (ret <0 ) {dev_err (dev,"failed to register component: %d\n" , ret);return ret;
Signature · 1 line
2.18.0
PATCH v2 2/2 ASoC: codecs: tas5720: add TAS5722 TDM slot width setting support
From: Andreas Dannenberg <[email protected]>
Unlike the TAS5720, the TAS5722 can be configured to utilize 16-bit wide slots in TDM mode. This can help easing audio clocking/frequency requirements.
---
Changes from v1:
- Use switch over if
sound/soc/codecs/tas5720.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
sound/soc/codecs/tas5720.c +15 -0
@@ -152,6 +152,7 @@ static int tas5720_set_dai_tdm_slot(struct snd_soc_dai *dai, int slots, int slot_width) {struct snd_soc_component *component = dai->component; +struct tas5720_data *tas5720 =snd_soc_component_get_drvdata (component);unsigned int first_slot;int ret;
@@ -185,6 +186,20 @@ static int tas5720_set_dai_tdm_slot(struct snd_soc_dai *dai,if (ret <0 ) goto error_snd_soc_component_update_bits; +/* Configure TDM slot width. This is only applicable to TAS5722. */ +switch (tas5720->devtype) { +case TAS5722 : + ret =snd_soc_component_update_bits (component,TAS5722_DIGITAL_CTRL2_REG , +TAS5722_TDM_SLOT_16B , + slot_width ==16 ? +TAS5722_TDM_SLOT_16B :0 ); +if (ret <0 ) + goto error_snd_soc_component_update_bits; +break ; +default : +break ; + } +return 0 ; error_snd_soc_component_update_bits:
Signature · 1 line
2.18.0
Mark Brown
maintainerApplied "ASoC: codecs: tas5720: add TAS5722 TDM slot width setting support" to the asoc tree
The patch
ASoC: codecs: tas5720: add TAS5722 TDM slot width setting support
has been applied to the asoc tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks,
Mark
Quoted 1 line
From
db658f40cae33a9fddbd9ca5c35c6bbfbd593a82Mon Sep 17 00:00:00 2001
From: Andreas Dannenberg <[email protected]>
Date: Fri, 31 Aug 2018 09:47:14 -0500
Subject: [PATCH] ASoC: codecs: tas5720: add TAS5722 TDM slot width setting
support
Unlike the TAS5720, the TAS5722 can be configured to utilize 16-bit wide slots in TDM mode. This can help easing audio clocking/frequency requirements.
--- sound/soc/codecs/tas5720.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
sound/soc/codecs/tas5720.c +15 -0
@@ -152,6 +152,7 @@ static int tas5720_set_dai_tdm_slot(struct snd_soc_dai *dai, int slots, int slot_width) {struct snd_soc_component *component = dai->component; +struct tas5720_data *tas5720 =snd_soc_component_get_drvdata (component);unsigned int first_slot;int ret;
@@ -185,6 +186,20 @@ static int tas5720_set_dai_tdm_slot(struct snd_soc_dai *dai,if (ret <0 ) goto error_snd_soc_component_update_bits; +/* Configure TDM slot width. This is only applicable to TAS5722. */ +switch (tas5720->devtype) { +case TAS5722 : + ret =snd_soc_component_update_bits (component,TAS5722_DIGITAL_CTRL2_REG , +TAS5722_TDM_SLOT_16B , + slot_width ==16 ? +TAS5722_TDM_SLOT_16B :0 ); +if (ret <0 ) + goto error_snd_soc_component_update_bits; +break ; +default : +break ; + } +return 0 ; error_snd_soc_component_update_bits:
Signature · 1 line
2.19.0.rc1
Mark Brown
maintainerApplied "ASoC: codecs: tas5720: add TAS5722 specific volume control" to the asoc tree
In reply to Andrew F. DavisThe patch
ASoC: codecs: tas5720: add TAS5722 specific volume control
has been applied to the asoc tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks,
Mark
Quoted 1 line
From
ec94c177bf3700ce44c53c375a3fb4c347f2b08fMon Sep 17 00:00:00 2001
From: Andreas Dannenberg <[email protected]>
Date: Fri, 31 Aug 2018 09:47:13 -0500
Subject: [PATCH] ASoC: codecs: tas5720: add TAS5722 specific volume control
The TAS5722 supports modifying volume in 0.25dB steps (as opposed to 0.5dB steps on the TAS5720). Introduce a custom mixer control that allows taking advantage of this finer output volume granularity.
Also add custom getters/setters for access as the TAS5722 digital volume controls are split over two registers.
--- sound/soc/codecs/tas5720.c | 88 ++++++++++++++++++++++++++++++++++---- 1 file changed, 80 insertions(+), 8 deletions(-)
sound/soc/codecs/tas5720.c +80 -8
@@ -485,15 +485,56 @@ static const DECLARE_TLV_DB_RANGE(dac_analog_tlv, );/* -* DAC digital volumes. From -103.5 to 24 dB in 0.5 dB steps. Note that -* setting the gain below -100 dB (register value <0x7) is effectively a MUTE -* as per device datasheet. +* DAC digital volumes. From -103.5 to 24 dB in 0.5 dB or 0.25 dB steps +* depending on the device. Note that setting the gain below -100 dB +* (register value <0x7) is effectively a MUTE as per device datasheet. +* +* Note that for the TAS5722 the digital volume controls are actually split +* over two registers, so we need custom getters/setters for access. */ -static DECLARE_TLV_DB_SCALE(dac_tlv, -10350, 50, 0); +static DECLARE_TLV_DB_SCALE(tas5720_dac_tlv, -10350, 50, 0); +static DECLARE_TLV_DB_SCALE(tas5722_dac_tlv, -10350, 25, 0); + +static int tas5722_volume_get (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *component =snd_soc_kcontrol_component (kcontrol); +unsigned int val; + +snd_soc_component_read (component,TAS5720_VOLUME_CTRL_REG , &val); + ucontrol->value.integer.value[0 ] = val <<1 ; + +snd_soc_component_read (component,TAS5722_DIGITAL_CTRL2_REG , &val); + ucontrol->value.integer.value[0 ] |= val &TAS5722_VOL_CONTROL_LSB ; + +return 0 ; +} + +static int tas5722_volume_set (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +struct snd_soc_component *component =snd_soc_kcontrol_component (kcontrol); +unsigned int sel = ucontrol->value.integer.value[0 ]; + +snd_soc_component_write (component,TAS5720_VOLUME_CTRL_REG , sel >>1 ); +snd_soc_component_update_bits (component,TAS5722_DIGITAL_CTRL2_REG , +TAS5722_VOL_CONTROL_LSB , sel); + +return 0 ; +}static const struct snd_kcontrol_new tas5720_snd_controls[] = {SOC_SINGLE_TLV ("Speaker Driver Playback Volume" , -TAS5720_VOLUME_CTRL_REG ,0 ,0xff ,0 , dac_tlv), +TAS5720_VOLUME_CTRL_REG ,0 ,0xff ,0 , tas5720_dac_tlv), +SOC_SINGLE_TLV ("Speaker Driver Analog Gain" ,TAS5720_ANALOG_CTRL_REG , +TAS5720_ANALOG_GAIN_SHIFT ,3 ,0 , dac_analog_tlv), +}; + +static const struct snd_kcontrol_new tas5722_snd_controls[] = { +SOC_SINGLE_EXT_TLV ("Speaker Driver Playback Volume" , +0 ,0 ,511 ,0 , + tas5722_volume_get, tas5722_volume_set, + tas5722_dac_tlv),SOC_SINGLE_TLV ("Speaker Driver Analog Gain" ,TAS5720_ANALOG_CTRL_REG ,TAS5720_ANALOG_GAIN_SHIFT ,3 ,0 , dac_analog_tlv), };
@@ -527,6 +568,23 @@ static const struct snd_soc_component_driver soc_component_dev_tas5720 = { .non_legacy_dai_naming = 1, }; +static const struct snd_soc_component_driver soc_component_dev_tas5722 = { + .probe = tas5720_codec_probe, + .remove = tas5720_codec_remove, + .suspend = tas5720_suspend, + .resume = tas5720_resume, + .controls = tas5722_snd_controls, + .num_controls =ARRAY_SIZE (tas5722_snd_controls), + .dapm_widgets = tas5720_dapm_widgets, + .num_dapm_widgets =ARRAY_SIZE (tas5720_dapm_widgets), + .dapm_routes = tas5720_audio_map, + .num_dapm_routes =ARRAY_SIZE (tas5720_audio_map), + .idle_bias_on =1 , + .use_pmdown_time =1 , + .endianness =1 , + .non_legacy_dai_naming =1 , +}; +/* PCM rates supported by the TAS5720 driver */ #define TAS5720_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\ SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
@@ -613,9 +671,23 @@ static int tas5720_probe(struct i2c_client *client,dev_set_drvdata (dev, data); - ret =devm_snd_soc_register_component (&client->dev, - &soc_component_dev_tas5720, - tas5720_dai,ARRAY_SIZE (tas5720_dai)); +switch (id->driver_data) { +case TAS5720 : + ret =devm_snd_soc_register_component (&client->dev, + &soc_component_dev_tas5720, + tas5720_dai, +ARRAY_SIZE (tas5720_dai)); +break ; +case TAS5722 : + ret =devm_snd_soc_register_component (&client->dev, + &soc_component_dev_tas5722, + tas5720_dai, +ARRAY_SIZE (tas5720_dai)); +break ; +default : +dev_err (dev,"unexpected private driver data\n" ); +return -EINVAL ; + }if (ret <0 ) {dev_err (dev,"failed to register component: %d\n" , ret);return ret;
Signature · 1 line
2.19.0.rc1