summaryrefslogtreecommitdiff
path: root/sound/soc/codecs/tas5720.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-10-25 09:00:15 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2018-10-25 09:00:15 -0700
commit3acbd2de6bc3af215c6ed7732dfc097d1e238503 (patch)
tree5152e90a4d2d586dd6ad1cf0b8f28c4de2e46e66 /sound/soc/codecs/tas5720.c
parentd49f8a52b15bf35db778035340d8a673149f9f93 (diff)
parentde7d83da84bdf0b5ec50b3b09249e608c0e4b81d (diff)
Merge tag 'sound-4.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai: "There have been little changes in ALSA core stuff, but ASoC core still kept rolling for the continued restructuring. The rest are lots of small driver-specific changes and some minor API updates. Here are highlights: General: - Appropriate fall-through annotations everywhere - Some code cleanup in memalloc code, handling non-cacahed pages more commonly in the helper - Deployment of SNDRV_PCM_INFO_SYNC_APPLPTR flag consistently Drivers: - More HD-audio CA0132 codec improvement for supporting other Creative boards - Plumbing legacy HD-audio codecs as ASoC BE on Intel SST; this will give move support of existing HD-audio devices with DSP - A few device-specific HD-audio quirks as usual - New quirk for RME CC devices and correction for B&W PX for USB-audio - FireWire: code refactoring including devres usages ASoC Core: - Continued componentization works; it's almost done! - A bunch of new for_each_foo macros - Cleanups and fixes in DAPM code ASoC Drivers: - MCLK support for several different devices, including CS42L51, STM32 SAI, and MAX98373 - Support for Allwinner A64 CODEC analog, Intel boards with DA7219 and MAX98927, Meson AXG PDM inputs, Nuvoton NAU8822, Renesas R8A7744 and TI PCM3060" * tag 'sound-4.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (299 commits) ASoC: stm32: sai: fix master clock naming ASoC: stm32: add clock dependency for sai ALSA: hda/ca0132 - Actually fix microphone issue ASoC: sun4i-i2s: move code from startup/shutdown hooks into pm_runtime hooks ASoC: wm2000: Remove wm2000_read helper function ASoC: cs42l51: fix mclk support ASoC: wm_adsp: Log addresses as 8 digits in wm_adsp_buffer_populate ASoC: wm_adsp: Rename memory fields in wm_adsp_buffer ASoC: cs42l51: add mclk support ASoC: stm32: sai: set sai as mclk clock provider ASoC: dt-bindings: add mclk support to cs42l51 ASoC: dt-bindings: add mclk provider support to stm32 sai ASoC: soc-core: fix trivial checkpatch issues ASoC: dapm: Add support for hw_free on CODEC to CODEC links ASoC: Intel: kbl_da7219_max98927: minor white space clean up ALSA: i2c/cs8427: Fix int to char conversion ALSA: doc: Brush up the old writing-an-alsa-driver ASoC: rsnd: tidyup SSICR::SWSP for TDM ASoC: rsnd: enable TDM settings for SSI parent ASoC: pcm3168a: add hw constraint for capture channel ...
Diffstat (limited to 'sound/soc/codecs/tas5720.c')
-rw-r--r--sound/soc/codecs/tas5720.c103
1 files changed, 95 insertions, 8 deletions
diff --git a/sound/soc/codecs/tas5720.c b/sound/soc/codecs/tas5720.c
index ae3d032ac35a..6bd0e5d5347f 100644
--- a/sound/soc/codecs/tas5720.c
+++ b/sound/soc/codecs/tas5720.c
@@ -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:
@@ -485,15 +500,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 +583,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 +686,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;