Commit 4536579b authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'sound-5.16-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound

Pull sound fixes from Takashi Iwai:
 "A collection of small fixes. A large series is found for ASoC tegra
  drivers to correct the control element handlings, while others are
  mostly for device-specific quirks and fix-ups"

* tag 'sound-5.16-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (25 commits)
  ALSA: hda/hdmi: fix HDA codec entry table order for ADL-P
  ALSA: hda: Add Intel DG2 PCI ID and HDMI codec vid
  ALSA: hda/cs8409: Set PMSG_ON earlier inside cs8409 driver
  ASoC: SOF: hda: reset DAI widget before reconfiguring it
  ASoC: cs35l41: Set the max SPI speed for the whole device
  ALSA: intel-dsp-config: add quirk for CML devices based on ES8336 codec
  ASoC: Intel: soc-acpi: add entry for ESSX8336 on CML
  ASoC: rk817: Add module alias for rk817-codec
  ASoC: soc-acpi: Set mach->id field on comp_ids matches
  ASoC: tegra: Fix kcontrol put callback in Mixer
  ASoC: tegra: Fix kcontrol put callback in ADX
  ASoC: tegra: Fix kcontrol put callback in AMX
  ASoC: tegra: Fix kcontrol put callback in SFC
  ASoC: tegra: Fix kcontrol put callback in MVC
  ASoC: tegra: Fix kcontrol put callback in AHUB
  ASoC: tegra: Fix kcontrol put callback in DSPK
  ASoC: tegra: Fix kcontrol put callback in DMIC
  ASoC: tegra: Fix kcontrol put callback in I2S
  ASoC: tegra: Fix kcontrol put callback in ADMAIF
  ASoC: tegra: Fix wrong value type in MVC
  ...
parents 58e1100f 289047db
...@@ -147,7 +147,7 @@ struct snd_soc_acpi_link_adr { ...@@ -147,7 +147,7 @@ struct snd_soc_acpi_link_adr {
*/ */
/* Descriptor for SST ASoC machine driver */ /* Descriptor for SST ASoC machine driver */
struct snd_soc_acpi_mach { struct snd_soc_acpi_mach {
const u8 id[ACPI_ID_LEN]; u8 id[ACPI_ID_LEN];
const struct snd_soc_acpi_codecs *comp_ids; const struct snd_soc_acpi_codecs *comp_ids;
const u32 link_mask; const u32 link_mask;
const struct snd_soc_acpi_link_adr *links; const struct snd_soc_acpi_link_adr *links;
......
...@@ -252,6 +252,11 @@ static const struct config_entry config_table[] = { ...@@ -252,6 +252,11 @@ static const struct config_entry config_table[] = {
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
.device = 0x02c8, .device = 0x02c8,
}, },
{
.flags = FLAG_SOF,
.device = 0x02c8,
.codec_hid = "ESSX8336",
},
/* Cometlake-H */ /* Cometlake-H */
{ {
.flags = FLAG_SOF, .flags = FLAG_SOF,
...@@ -276,6 +281,11 @@ static const struct config_entry config_table[] = { ...@@ -276,6 +281,11 @@ static const struct config_entry config_table[] = {
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
.device = 0x06c8, .device = 0x06c8,
}, },
{
.flags = FLAG_SOF,
.device = 0x06c8,
.codec_hid = "ESSX8336",
},
#endif #endif
/* Icelake */ /* Icelake */
......
...@@ -335,7 +335,10 @@ enum { ...@@ -335,7 +335,10 @@ enum {
((pci)->device == 0x0c0c) || \ ((pci)->device == 0x0c0c) || \
((pci)->device == 0x0d0c) || \ ((pci)->device == 0x0d0c) || \
((pci)->device == 0x160c) || \ ((pci)->device == 0x160c) || \
((pci)->device == 0x490d)) ((pci)->device == 0x490d) || \
((pci)->device == 0x4f90) || \
((pci)->device == 0x4f91) || \
((pci)->device == 0x4f92))
#define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98) #define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98)
...@@ -2473,6 +2476,13 @@ static const struct pci_device_id azx_ids[] = { ...@@ -2473,6 +2476,13 @@ static const struct pci_device_id azx_ids[] = {
/* DG1 */ /* DG1 */
{ PCI_DEVICE(0x8086, 0x490d), { PCI_DEVICE(0x8086, 0x490d),
.driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
/* DG2 */
{ PCI_DEVICE(0x8086, 0x4f90),
.driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
{ PCI_DEVICE(0x8086, 0x4f91),
.driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
{ PCI_DEVICE(0x8086, 0x4f92),
.driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
/* Alderlake-S */ /* Alderlake-S */
{ PCI_DEVICE(0x8086, 0x7ad0), { PCI_DEVICE(0x8086, 0x7ad0),
.driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
......
...@@ -438,6 +438,15 @@ int snd_hda_codec_set_pin_target(struct hda_codec *codec, hda_nid_t nid, ...@@ -438,6 +438,15 @@ int snd_hda_codec_set_pin_target(struct hda_codec *codec, hda_nid_t nid,
#define for_each_hda_codec_node(nid, codec) \ #define for_each_hda_codec_node(nid, codec) \
for ((nid) = (codec)->core.start_nid; (nid) < (codec)->core.end_nid; (nid)++) for ((nid) = (codec)->core.start_nid; (nid) < (codec)->core.end_nid; (nid)++)
/* Set the codec power_state flag to indicate to allow unsol event handling;
* see hda_codec_unsol_event() in hda_bind.c. Calling this might confuse the
* state tracking, so use with care.
*/
static inline void snd_hda_codec_allow_unsol_events(struct hda_codec *codec)
{
codec->core.dev.power.power_state = PMSG_ON;
}
/* /*
* get widget capabilities * get widget capabilities
*/ */
......
...@@ -750,6 +750,11 @@ static void cs42l42_resume(struct sub_codec *cs42l42) ...@@ -750,6 +750,11 @@ static void cs42l42_resume(struct sub_codec *cs42l42)
if (cs42l42->full_scale_vol) if (cs42l42->full_scale_vol)
cs8409_i2c_write(cs42l42, 0x2001, 0x01); cs8409_i2c_write(cs42l42, 0x2001, 0x01);
/* we have to explicitly allow unsol event handling even during the
* resume phase so that the jack event is processed properly
*/
snd_hda_codec_allow_unsol_events(cs42l42->codec);
cs42l42_enable_jack_detect(cs42l42); cs42l42_enable_jack_detect(cs42l42);
} }
......
...@@ -4380,10 +4380,11 @@ HDA_CODEC_ENTRY(0x8086280f, "Icelake HDMI", patch_i915_icl_hdmi), ...@@ -4380,10 +4380,11 @@ HDA_CODEC_ENTRY(0x8086280f, "Icelake HDMI", patch_i915_icl_hdmi),
HDA_CODEC_ENTRY(0x80862812, "Tigerlake HDMI", patch_i915_tgl_hdmi), HDA_CODEC_ENTRY(0x80862812, "Tigerlake HDMI", patch_i915_tgl_hdmi),
HDA_CODEC_ENTRY(0x80862814, "DG1 HDMI", patch_i915_tgl_hdmi), HDA_CODEC_ENTRY(0x80862814, "DG1 HDMI", patch_i915_tgl_hdmi),
HDA_CODEC_ENTRY(0x80862815, "Alderlake HDMI", patch_i915_tgl_hdmi), HDA_CODEC_ENTRY(0x80862815, "Alderlake HDMI", patch_i915_tgl_hdmi),
HDA_CODEC_ENTRY(0x8086281c, "Alderlake-P HDMI", patch_i915_tgl_hdmi),
HDA_CODEC_ENTRY(0x80862816, "Rocketlake HDMI", patch_i915_tgl_hdmi), HDA_CODEC_ENTRY(0x80862816, "Rocketlake HDMI", patch_i915_tgl_hdmi),
HDA_CODEC_ENTRY(0x80862819, "DG2 HDMI", patch_i915_tgl_hdmi),
HDA_CODEC_ENTRY(0x8086281a, "Jasperlake HDMI", patch_i915_icl_hdmi), HDA_CODEC_ENTRY(0x8086281a, "Jasperlake HDMI", patch_i915_icl_hdmi),
HDA_CODEC_ENTRY(0x8086281b, "Elkhartlake HDMI", patch_i915_icl_hdmi), HDA_CODEC_ENTRY(0x8086281b, "Elkhartlake HDMI", patch_i915_icl_hdmi),
HDA_CODEC_ENTRY(0x8086281c, "Alderlake-P HDMI", patch_i915_tgl_hdmi),
HDA_CODEC_ENTRY(0x80862880, "CedarTrail HDMI", patch_generic_hdmi), HDA_CODEC_ENTRY(0x80862880, "CedarTrail HDMI", patch_generic_hdmi),
HDA_CODEC_ENTRY(0x80862882, "Valleyview2 HDMI", patch_i915_byt_hdmi), HDA_CODEC_ENTRY(0x80862882, "Valleyview2 HDMI", patch_i915_byt_hdmi),
HDA_CODEC_ENTRY(0x80862883, "Braswell HDMI", patch_i915_byt_hdmi), HDA_CODEC_ENTRY(0x80862883, "Braswell HDMI", patch_i915_byt_hdmi),
......
...@@ -42,34 +42,6 @@ static const struct spi_device_id cs35l41_id_spi[] = { ...@@ -42,34 +42,6 @@ static const struct spi_device_id cs35l41_id_spi[] = {
MODULE_DEVICE_TABLE(spi, cs35l41_id_spi); MODULE_DEVICE_TABLE(spi, cs35l41_id_spi);
static void cs35l41_spi_otp_setup(struct cs35l41_private *cs35l41,
bool is_pre_setup, unsigned int *freq)
{
struct spi_device *spi;
u32 orig_spi_freq;
spi = to_spi_device(cs35l41->dev);
if (!spi) {
dev_err(cs35l41->dev, "%s: No SPI device\n", __func__);
return;
}
if (is_pre_setup) {
orig_spi_freq = spi->max_speed_hz;
if (orig_spi_freq > CS35L41_SPI_MAX_FREQ_OTP) {
spi->max_speed_hz = CS35L41_SPI_MAX_FREQ_OTP;
spi_setup(spi);
}
*freq = orig_spi_freq;
} else {
if (spi->max_speed_hz != *freq) {
spi->max_speed_hz = *freq;
spi_setup(spi);
}
}
}
static int cs35l41_spi_probe(struct spi_device *spi) static int cs35l41_spi_probe(struct spi_device *spi)
{ {
const struct regmap_config *regmap_config = &cs35l41_regmap_spi; const struct regmap_config *regmap_config = &cs35l41_regmap_spi;
...@@ -81,6 +53,9 @@ static int cs35l41_spi_probe(struct spi_device *spi) ...@@ -81,6 +53,9 @@ static int cs35l41_spi_probe(struct spi_device *spi)
if (!cs35l41) if (!cs35l41)
return -ENOMEM; return -ENOMEM;
spi->max_speed_hz = CS35L41_SPI_MAX_FREQ;
spi_setup(spi);
spi_set_drvdata(spi, cs35l41); spi_set_drvdata(spi, cs35l41);
cs35l41->regmap = devm_regmap_init_spi(spi, regmap_config); cs35l41->regmap = devm_regmap_init_spi(spi, regmap_config);
if (IS_ERR(cs35l41->regmap)) { if (IS_ERR(cs35l41->regmap)) {
...@@ -91,7 +66,6 @@ static int cs35l41_spi_probe(struct spi_device *spi) ...@@ -91,7 +66,6 @@ static int cs35l41_spi_probe(struct spi_device *spi)
cs35l41->dev = &spi->dev; cs35l41->dev = &spi->dev;
cs35l41->irq = spi->irq; cs35l41->irq = spi->irq;
cs35l41->otp_setup = cs35l41_spi_otp_setup;
return cs35l41_probe(cs35l41, pdata); return cs35l41_probe(cs35l41, pdata);
} }
......
...@@ -302,7 +302,6 @@ static int cs35l41_otp_unpack(void *data) ...@@ -302,7 +302,6 @@ static int cs35l41_otp_unpack(void *data)
const struct cs35l41_otp_packed_element_t *otp_map; const struct cs35l41_otp_packed_element_t *otp_map;
struct cs35l41_private *cs35l41 = data; struct cs35l41_private *cs35l41 = data;
int bit_offset, word_offset, ret, i; int bit_offset, word_offset, ret, i;
unsigned int orig_spi_freq;
unsigned int bit_sum = 8; unsigned int bit_sum = 8;
u32 otp_val, otp_id_reg; u32 otp_val, otp_id_reg;
u32 *otp_mem; u32 *otp_mem;
...@@ -326,9 +325,6 @@ static int cs35l41_otp_unpack(void *data) ...@@ -326,9 +325,6 @@ static int cs35l41_otp_unpack(void *data)
goto err_otp_unpack; goto err_otp_unpack;
} }
if (cs35l41->otp_setup)
cs35l41->otp_setup(cs35l41, true, &orig_spi_freq);
ret = regmap_bulk_read(cs35l41->regmap, CS35L41_OTP_MEM0, otp_mem, ret = regmap_bulk_read(cs35l41->regmap, CS35L41_OTP_MEM0, otp_mem,
CS35L41_OTP_SIZE_WORDS); CS35L41_OTP_SIZE_WORDS);
if (ret < 0) { if (ret < 0) {
...@@ -336,9 +332,6 @@ static int cs35l41_otp_unpack(void *data) ...@@ -336,9 +332,6 @@ static int cs35l41_otp_unpack(void *data)
goto err_otp_unpack; goto err_otp_unpack;
} }
if (cs35l41->otp_setup)
cs35l41->otp_setup(cs35l41, false, &orig_spi_freq);
otp_map = otp_map_match->map; otp_map = otp_map_match->map;
bit_offset = otp_map_match->bit_offset; bit_offset = otp_map_match->bit_offset;
......
...@@ -726,7 +726,7 @@ ...@@ -726,7 +726,7 @@
#define CS35L41_FS2_WINDOW_MASK 0x00FFF800 #define CS35L41_FS2_WINDOW_MASK 0x00FFF800
#define CS35L41_FS2_WINDOW_SHIFT 12 #define CS35L41_FS2_WINDOW_SHIFT 12
#define CS35L41_SPI_MAX_FREQ_OTP 4000000 #define CS35L41_SPI_MAX_FREQ 4000000
#define CS35L41_RX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) #define CS35L41_RX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
#define CS35L41_TX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) #define CS35L41_TX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
...@@ -764,8 +764,6 @@ struct cs35l41_private { ...@@ -764,8 +764,6 @@ struct cs35l41_private {
int irq; int irq;
/* GPIO for /RST */ /* GPIO for /RST */
struct gpio_desc *reset_gpio; struct gpio_desc *reset_gpio;
void (*otp_setup)(struct cs35l41_private *cs35l41, bool is_pre_setup,
unsigned int *freq);
}; };
int cs35l41_probe(struct cs35l41_private *cs35l41, int cs35l41_probe(struct cs35l41_private *cs35l41,
......
...@@ -539,3 +539,4 @@ module_platform_driver(rk817_codec_driver); ...@@ -539,3 +539,4 @@ module_platform_driver(rk817_codec_driver);
MODULE_DESCRIPTION("ASoC RK817 codec driver"); MODULE_DESCRIPTION("ASoC RK817 codec driver");
MODULE_AUTHOR("binyuan <kevan.lan@rock-chips.com>"); MODULE_AUTHOR("binyuan <kevan.lan@rock-chips.com>");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:rk817-codec");
...@@ -81,6 +81,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_cml_machines[] = { ...@@ -81,6 +81,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_cml_machines[] = {
.sof_fw_filename = "sof-cml.ri", .sof_fw_filename = "sof-cml.ri",
.sof_tplg_filename = "sof-cml-da7219-max98390.tplg", .sof_tplg_filename = "sof-cml-da7219-max98390.tplg",
}, },
{
.id = "ESSX8336",
.drv_name = "sof-essx8336",
.sof_fw_filename = "sof-cml.ri",
.sof_tplg_filename = "sof-cml-es8336.tplg",
},
{}, {},
}; };
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_cml_machines); EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_cml_machines);
......
...@@ -20,10 +20,12 @@ static bool snd_soc_acpi_id_present(struct snd_soc_acpi_mach *machine) ...@@ -20,10 +20,12 @@ static bool snd_soc_acpi_id_present(struct snd_soc_acpi_mach *machine)
if (comp_ids) { if (comp_ids) {
for (i = 0; i < comp_ids->num_codecs; i++) { for (i = 0; i < comp_ids->num_codecs; i++) {
if (acpi_dev_present(comp_ids->codecs[i], NULL, -1)) if (acpi_dev_present(comp_ids->codecs[i], NULL, -1)) {
strscpy(machine->id, comp_ids->codecs[i], ACPI_ID_LEN);
return true; return true;
} }
} }
}
return false; return false;
} }
......
...@@ -58,6 +58,13 @@ int hda_ctrl_dai_widget_setup(struct snd_soc_dapm_widget *w) ...@@ -58,6 +58,13 @@ int hda_ctrl_dai_widget_setup(struct snd_soc_dapm_widget *w)
return -EINVAL; return -EINVAL;
} }
/* DAI already configured, reset it before reconfiguring it */
if (sof_dai->configured) {
ret = hda_ctrl_dai_widget_free(w);
if (ret < 0)
return ret;
}
config = &sof_dai->dai_config[sof_dai->current_config]; config = &sof_dai->dai_config[sof_dai->current_config];
/* /*
......
...@@ -26,49 +26,160 @@ static const struct reg_default tegra186_dspk_reg_defaults[] = { ...@@ -26,49 +26,160 @@ static const struct reg_default tegra186_dspk_reg_defaults[] = {
{ TEGRA186_DSPK_CODEC_CTRL, 0x03000000 }, { TEGRA186_DSPK_CODEC_CTRL, 0x03000000 },
}; };
static int tegra186_dspk_get_control(struct snd_kcontrol *kcontrol, static int tegra186_dspk_get_fifo_th(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
if (strstr(kcontrol->id.name, "FIFO Threshold"))
ucontrol->value.integer.value[0] = dspk->rx_fifo_th; ucontrol->value.integer.value[0] = dspk->rx_fifo_th;
else if (strstr(kcontrol->id.name, "OSR Value"))
ucontrol->value.integer.value[0] = dspk->osr_val;
else if (strstr(kcontrol->id.name, "LR Polarity Select"))
ucontrol->value.integer.value[0] = dspk->lrsel;
else if (strstr(kcontrol->id.name, "Channel Select"))
ucontrol->value.integer.value[0] = dspk->ch_sel;
else if (strstr(kcontrol->id.name, "Mono To Stereo"))
ucontrol->value.integer.value[0] = dspk->mono_to_stereo;
else if (strstr(kcontrol->id.name, "Stereo To Mono"))
ucontrol->value.integer.value[0] = dspk->stereo_to_mono;
return 0; return 0;
} }
static int tegra186_dspk_put_control(struct snd_kcontrol *kcontrol, static int tegra186_dspk_put_fifo_th(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
int val = ucontrol->value.integer.value[0]; int value = ucontrol->value.integer.value[0];
if (strstr(kcontrol->id.name, "FIFO Threshold"))
dspk->rx_fifo_th = val;
else if (strstr(kcontrol->id.name, "OSR Value"))
dspk->osr_val = val;
else if (strstr(kcontrol->id.name, "LR Polarity Select"))
dspk->lrsel = val;
else if (strstr(kcontrol->id.name, "Channel Select"))
dspk->ch_sel = val;
else if (strstr(kcontrol->id.name, "Mono To Stereo"))
dspk->mono_to_stereo = val;
else if (strstr(kcontrol->id.name, "Stereo To Mono"))
dspk->stereo_to_mono = val;
if (value == dspk->rx_fifo_th)
return 0; return 0;
dspk->rx_fifo_th = value;
return 1;
}
static int tegra186_dspk_get_osr_val(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
ucontrol->value.enumerated.item[0] = dspk->osr_val;
return 0;
}
static int tegra186_dspk_put_osr_val(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
unsigned int value = ucontrol->value.enumerated.item[0];
if (value == dspk->osr_val)
return 0;
dspk->osr_val = value;
return 1;
}
static int tegra186_dspk_get_pol_sel(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
ucontrol->value.enumerated.item[0] = dspk->lrsel;
return 0;
}
static int tegra186_dspk_put_pol_sel(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
unsigned int value = ucontrol->value.enumerated.item[0];
if (value == dspk->lrsel)
return 0;
dspk->lrsel = value;
return 1;
}
static int tegra186_dspk_get_ch_sel(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
ucontrol->value.enumerated.item[0] = dspk->ch_sel;
return 0;
}
static int tegra186_dspk_put_ch_sel(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
unsigned int value = ucontrol->value.enumerated.item[0];
if (value == dspk->ch_sel)
return 0;
dspk->ch_sel = value;
return 1;
}
static int tegra186_dspk_get_mono_to_stereo(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
ucontrol->value.enumerated.item[0] = dspk->mono_to_stereo;
return 0;
}
static int tegra186_dspk_put_mono_to_stereo(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
unsigned int value = ucontrol->value.enumerated.item[0];
if (value == dspk->mono_to_stereo)
return 0;
dspk->mono_to_stereo = value;
return 1;
}
static int tegra186_dspk_get_stereo_to_mono(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
ucontrol->value.enumerated.item[0] = dspk->stereo_to_mono;
return 0;
}
static int tegra186_dspk_put_stereo_to_mono(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol);
struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec);
unsigned int value = ucontrol->value.enumerated.item[0];
if (value == dspk->stereo_to_mono)
return 0;
dspk->stereo_to_mono = value;
return 1;
} }
static int __maybe_unused tegra186_dspk_runtime_suspend(struct device *dev) static int __maybe_unused tegra186_dspk_runtime_suspend(struct device *dev)
...@@ -279,17 +390,19 @@ static const struct soc_enum tegra186_dspk_lrsel_enum = ...@@ -279,17 +390,19 @@ static const struct soc_enum tegra186_dspk_lrsel_enum =
static const struct snd_kcontrol_new tegrat186_dspk_controls[] = { static const struct snd_kcontrol_new tegrat186_dspk_controls[] = {
SOC_SINGLE_EXT("FIFO Threshold", SND_SOC_NOPM, 0, SOC_SINGLE_EXT("FIFO Threshold", SND_SOC_NOPM, 0,
TEGRA186_DSPK_RX_FIFO_DEPTH - 1, 0, TEGRA186_DSPK_RX_FIFO_DEPTH - 1, 0,
tegra186_dspk_get_control, tegra186_dspk_put_control), tegra186_dspk_get_fifo_th, tegra186_dspk_put_fifo_th),
SOC_ENUM_EXT("OSR Value", tegra186_dspk_osr_enum, SOC_ENUM_EXT("OSR Value", tegra186_dspk_osr_enum,
tegra186_dspk_get_control, tegra186_dspk_put_control), tegra186_dspk_get_osr_val, tegra186_dspk_put_osr_val),
SOC_ENUM_EXT("LR Polarity Select", tegra186_dspk_lrsel_enum, SOC_ENUM_EXT("LR Polarity Select", tegra186_dspk_lrsel_enum,
tegra186_dspk_get_control, tegra186_dspk_put_control), tegra186_dspk_get_pol_sel, tegra186_dspk_put_pol_sel),
SOC_ENUM_EXT("Channel Select", tegra186_dspk_ch_sel_enum, SOC_ENUM_EXT("Channel Select", tegra186_dspk_ch_sel_enum,
tegra186_dspk_get_control, tegra186_dspk_put_control), tegra186_dspk_get_ch_sel, tegra186_dspk_put_ch_sel),
SOC_ENUM_EXT("Mono To Stereo", tegra186_dspk_mono_conv_enum, SOC_ENUM_EXT("Mono To Stereo", tegra186_dspk_mono_conv_enum,
tegra186_dspk_get_control, tegra186_dspk_put_control), tegra186_dspk_get_mono_to_stereo,
tegra186_dspk_put_mono_to_stereo),
SOC_ENUM_EXT("Stereo To Mono", tegra186_dspk_stereo_conv_enum, SOC_ENUM_EXT("Stereo To Mono", tegra186_dspk_stereo_conv_enum,
tegra186_dspk_get_control, tegra186_dspk_put_control), tegra186_dspk_get_stereo_to_mono,
tegra186_dspk_put_stereo_to_mono),
}; };
static const struct snd_soc_component_driver tegra186_dspk_cmpnt = { static const struct snd_soc_component_driver tegra186_dspk_cmpnt = {
......
...@@ -424,46 +424,122 @@ static const struct snd_soc_dai_ops tegra_admaif_dai_ops = { ...@@ -424,46 +424,122 @@ static const struct snd_soc_dai_ops tegra_admaif_dai_ops = {
.trigger = tegra_admaif_trigger, .trigger = tegra_admaif_trigger,
}; };
static int tegra_admaif_get_control(struct snd_kcontrol *kcontrol, static int tegra210_admaif_pget_mono_to_stereo(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt); struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
long *uctl_val = &ucontrol->value.integer.value[0]; struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
if (strstr(kcontrol->id.name, "Playback Mono To Stereo")) ucontrol->value.enumerated.item[0] =
*uctl_val = admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg]; admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg];
else if (strstr(kcontrol->id.name, "Capture Mono To Stereo"))
*uctl_val = admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg];
else if (strstr(kcontrol->id.name, "Playback Stereo To Mono"))
*uctl_val = admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg];
else if (strstr(kcontrol->id.name, "Capture Stereo To Mono"))
*uctl_val = admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg];
return 0; return 0;
} }
static int tegra_admaif_put_control(struct snd_kcontrol *kcontrol, static int tegra210_admaif_pput_mono_to_stereo(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt); struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
int value = ucontrol->value.integer.value[0]; struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
unsigned int value = ucontrol->value.enumerated.item[0];
if (value == admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg])
return 0;
if (strstr(kcontrol->id.name, "Playback Mono To Stereo"))
admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg] = value; admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg] = value;
else if (strstr(kcontrol->id.name, "Capture Mono To Stereo"))
return 1;
}
static int tegra210_admaif_cget_mono_to_stereo(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
ucontrol->value.enumerated.item[0] =
admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg];
return 0;
}
static int tegra210_admaif_cput_mono_to_stereo(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
unsigned int value = ucontrol->value.enumerated.item[0];
if (value == admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg])
return 0;
admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg] = value; admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg] = value;
else if (strstr(kcontrol->id.name, "Playback Stereo To Mono"))
return 1;
}
static int tegra210_admaif_pget_stereo_to_mono(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
ucontrol->value.enumerated.item[0] =
admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg];
return 0;
}
static int tegra210_admaif_pput_stereo_to_mono(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
unsigned int value = ucontrol->value.enumerated.item[0];
if (value == admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg])
return 0;
admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg] = value; admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg] = value;
else if (strstr(kcontrol->id.name, "Capture Stereo To Mono"))
admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg] = value; return 1;
}
static int tegra210_admaif_cget_stereo_to_mono(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
ucontrol->value.enumerated.item[0] =
admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg];
return 0; return 0;
} }
static int tegra210_admaif_cput_stereo_to_mono(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt);
struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value;
unsigned int value = ucontrol->value.enumerated.item[0];
if (value == admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg])
return 0;
admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg] = value;
return 1;
}
static int tegra_admaif_dai_probe(struct snd_soc_dai *dai) static int tegra_admaif_dai_probe(struct snd_soc_dai *dai)
{ {
struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai); struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai);
...@@ -559,17 +635,21 @@ static const char * const tegra_admaif_mono_conv_text[] = { ...@@ -559,17 +635,21 @@ static const char * const tegra_admaif_mono_conv_text[] = {
} }
#define TEGRA_ADMAIF_CIF_CTRL(reg) \ #define TEGRA_ADMAIF_CIF_CTRL(reg) \
NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Mono To Stereo", reg - 1,\ NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Mono To Stereo", reg - 1, \
tegra_admaif_get_control, tegra_admaif_put_control, \ tegra210_admaif_pget_mono_to_stereo, \
tegra210_admaif_pput_mono_to_stereo, \
tegra_admaif_mono_conv_text), \ tegra_admaif_mono_conv_text), \
NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Stereo To Mono", reg - 1,\ NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Stereo To Mono", reg - 1, \
tegra_admaif_get_control, tegra_admaif_put_control, \ tegra210_admaif_pget_stereo_to_mono, \
tegra210_admaif_pput_stereo_to_mono, \
tegra_admaif_stereo_conv_text), \ tegra_admaif_stereo_conv_text), \
NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Mono To Stereo", reg - 1, \ NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Mono To Stereo", reg - 1, \
tegra_admaif_get_control, tegra_admaif_put_control, \ tegra210_admaif_cget_mono_to_stereo, \
tegra210_admaif_cput_mono_to_stereo, \
tegra_admaif_mono_conv_text), \ tegra_admaif_mono_conv_text), \
NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Stereo To Mono", reg - 1, \ NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Stereo To Mono", reg - 1, \
tegra_admaif_get_control, tegra_admaif_put_control, \ tegra210_admaif_cget_stereo_to_mono, \
tegra210_admaif_cput_stereo_to_mono, \
tegra_admaif_stereo_conv_text) tegra_admaif_stereo_conv_text)
static struct snd_kcontrol_new tegra210_admaif_controls[] = { static struct snd_kcontrol_new tegra210_admaif_controls[] = {
......
...@@ -193,6 +193,9 @@ static int tegra210_adx_put_byte_map(struct snd_kcontrol *kcontrol, ...@@ -193,6 +193,9 @@ static int tegra210_adx_put_byte_map(struct snd_kcontrol *kcontrol,
struct soc_mixer_control *mc = struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;; (struct soc_mixer_control *)kcontrol->private_value;;
if (value == bytes_map[mc->reg])
return 0;
if (value >= 0 && value <= 255) { if (value >= 0 && value <= 255) {
/* update byte map and enable slot */ /* update byte map and enable slot */
bytes_map[mc->reg] = value; bytes_map[mc->reg] = value;
......
...@@ -62,6 +62,7 @@ static int tegra_ahub_put_value_enum(struct snd_kcontrol *kctl, ...@@ -62,6 +62,7 @@ static int tegra_ahub_put_value_enum(struct snd_kcontrol *kctl,
unsigned int *item = uctl->value.enumerated.item; unsigned int *item = uctl->value.enumerated.item;
unsigned int value = e->values[item[0]]; unsigned int value = e->values[item[0]];
unsigned int i, bit_pos, reg_idx = 0, reg_val = 0; unsigned int i, bit_pos, reg_idx = 0, reg_val = 0;
int change = 0;
if (item[0] >= e->items) if (item[0] >= e->items)
return -EINVAL; return -EINVAL;
...@@ -86,12 +87,14 @@ static int tegra_ahub_put_value_enum(struct snd_kcontrol *kctl, ...@@ -86,12 +87,14 @@ static int tegra_ahub_put_value_enum(struct snd_kcontrol *kctl,
/* Update widget power if state has changed */ /* Update widget power if state has changed */
if (snd_soc_component_test_bits(cmpnt, update[i].reg, if (snd_soc_component_test_bits(cmpnt, update[i].reg,
update[i].mask, update[i].val)) update[i].mask,
snd_soc_dapm_mux_update_power(dapm, kctl, item[0], e, update[i].val))
change |= snd_soc_dapm_mux_update_power(dapm, kctl,
item[0], e,
&update[i]); &update[i]);
} }
return 0; return change;
} }
static struct snd_soc_dai_driver tegra210_ahub_dais[] = { static struct snd_soc_dai_driver tegra210_ahub_dais[] = {
......
...@@ -222,6 +222,9 @@ static int tegra210_amx_put_byte_map(struct snd_kcontrol *kcontrol, ...@@ -222,6 +222,9 @@ static int tegra210_amx_put_byte_map(struct snd_kcontrol *kcontrol,
int reg = mc->reg; int reg = mc->reg;
int value = ucontrol->value.integer.value[0]; int value = ucontrol->value.integer.value[0];
if (value == bytes_map[reg])
return 0;
if (value >= 0 && value <= 255) { if (value >= 0 && value <= 255) {
/* Update byte map and enable slot */ /* Update byte map and enable slot */
bytes_map[reg] = value; bytes_map[reg] = value;
......
...@@ -156,49 +156,160 @@ static int tegra210_dmic_hw_params(struct snd_pcm_substream *substream, ...@@ -156,49 +156,160 @@ static int tegra210_dmic_hw_params(struct snd_pcm_substream *substream,
return 0; return 0;
} }
static int tegra210_dmic_get_control(struct snd_kcontrol *kcontrol, static int tegra210_dmic_get_boost_gain(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp);
if (strstr(kcontrol->id.name, "Boost Gain Volume"))
ucontrol->value.integer.value[0] = dmic->boost_gain; ucontrol->value.integer.value[0] = dmic->boost_gain;
else if (strstr(kcontrol->id.name, "Channel Select"))
ucontrol->value.integer.value[0] = dmic->ch_select;
else if (strstr(kcontrol->id.name, "Mono To Stereo"))
ucontrol->value.integer.value[0] = dmic->mono_to_stereo;
else if (strstr(kcontrol->id.name, "Stereo To Mono"))
ucontrol->value.integer.value[0] = dmic->stereo_to_mono;
else if (strstr(kcontrol->id.name, "OSR Value"))
ucontrol->value.integer.value[0] = dmic->osr_val;
else if (strstr(kcontrol->id.name, "LR Polarity Select"))
ucontrol->value.integer.value[0] = dmic->lrsel;
return 0; return 0;
} }
static int tegra210_dmic_put_control(struct snd_kcontrol *kcontrol, static int tegra210_dmic_put_boost_gain(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp);
int value = ucontrol->value.integer.value[0]; int value = ucontrol->value.integer.value[0];
if (strstr(kcontrol->id.name, "Boost Gain Volume")) if (value == dmic->boost_gain)
return 0;
dmic->boost_gain = value; dmic->boost_gain = value;
else if (strstr(kcontrol->id.name, "Channel Select"))
dmic->ch_select = ucontrol->value.integer.value[0]; return 1;
else if (strstr(kcontrol->id.name, "Mono To Stereo")) }
static int tegra210_dmic_get_ch_select(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp);
ucontrol->value.enumerated.item[0] = dmic->ch_select;
return 0;
}
static int tegra210_dmic_put_ch_select(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp);
unsigned int value = ucontrol->value.enumerated.item[0];
if (value == dmic->ch_select)
return 0;
dmic->ch_select = value;
return 1;
}
static int tegra210_dmic_get_mono_to_stereo(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp);
ucontrol->value.enumerated.item[0] = dmic->mono_to_stereo;
return 0;
}
static int tegra210_dmic_put_mono_to_stereo(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp);
unsigned int value = ucontrol->value.enumerated.item[0];
if (value == dmic->mono_to_stereo)
return 0;
dmic->mono_to_stereo = value; dmic->mono_to_stereo = value;
else if (strstr(kcontrol->id.name, "Stereo To Mono"))
return 1;
}
static int tegra210_dmic_get_stereo_to_mono(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp);
ucontrol->value.enumerated.item[0] = dmic->stereo_to_mono;
return 0;
}
static int tegra210_dmic_put_stereo_to_mono(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp);
unsigned int value = ucontrol->value.enumerated.item[0];
if (value == dmic->stereo_to_mono)
return 0;
dmic->stereo_to_mono = value; dmic->stereo_to_mono = value;
else if (strstr(kcontrol->id.name, "OSR Value"))
return 1;
}
static int tegra210_dmic_get_osr_val(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp);
ucontrol->value.enumerated.item[0] = dmic->osr_val;
return 0;
}
static int tegra210_dmic_put_osr_val(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp);
unsigned int value = ucontrol->value.enumerated.item[0];
if (value == dmic->osr_val)
return 0;
dmic->osr_val = value; dmic->osr_val = value;
else if (strstr(kcontrol->id.name, "LR Polarity Select"))
dmic->lrsel = value;
return 1;
}
static int tegra210_dmic_get_pol_sel(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp);
ucontrol->value.enumerated.item[0] = dmic->lrsel;
return 0;
}
static int tegra210_dmic_put_pol_sel(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp);
unsigned int value = ucontrol->value.enumerated.item[0];
if (value == dmic->lrsel)
return 0; return 0;
dmic->lrsel = value;
return 1;
} }
static const struct snd_soc_dai_ops tegra210_dmic_dai_ops = { static const struct snd_soc_dai_ops tegra210_dmic_dai_ops = {
...@@ -287,19 +398,22 @@ static const struct soc_enum tegra210_dmic_lrsel_enum = ...@@ -287,19 +398,22 @@ static const struct soc_enum tegra210_dmic_lrsel_enum =
static const struct snd_kcontrol_new tegra210_dmic_controls[] = { static const struct snd_kcontrol_new tegra210_dmic_controls[] = {
SOC_SINGLE_EXT("Boost Gain Volume", 0, 0, MAX_BOOST_GAIN, 0, SOC_SINGLE_EXT("Boost Gain Volume", 0, 0, MAX_BOOST_GAIN, 0,
tegra210_dmic_get_control, tegra210_dmic_put_control), tegra210_dmic_get_boost_gain,
tegra210_dmic_put_boost_gain),
SOC_ENUM_EXT("Channel Select", tegra210_dmic_ch_enum, SOC_ENUM_EXT("Channel Select", tegra210_dmic_ch_enum,
tegra210_dmic_get_control, tegra210_dmic_put_control), tegra210_dmic_get_ch_select, tegra210_dmic_put_ch_select),
SOC_ENUM_EXT("Mono To Stereo", SOC_ENUM_EXT("Mono To Stereo",
tegra210_dmic_mono_conv_enum, tegra210_dmic_get_control, tegra210_dmic_mono_conv_enum,
tegra210_dmic_put_control), tegra210_dmic_get_mono_to_stereo,
tegra210_dmic_put_mono_to_stereo),
SOC_ENUM_EXT("Stereo To Mono", SOC_ENUM_EXT("Stereo To Mono",
tegra210_dmic_stereo_conv_enum, tegra210_dmic_get_control, tegra210_dmic_stereo_conv_enum,
tegra210_dmic_put_control), tegra210_dmic_get_stereo_to_mono,
tegra210_dmic_put_stereo_to_mono),
SOC_ENUM_EXT("OSR Value", tegra210_dmic_osr_enum, SOC_ENUM_EXT("OSR Value", tegra210_dmic_osr_enum,
tegra210_dmic_get_control, tegra210_dmic_put_control), tegra210_dmic_get_osr_val, tegra210_dmic_put_osr_val),
SOC_ENUM_EXT("LR Polarity Select", tegra210_dmic_lrsel_enum, SOC_ENUM_EXT("LR Polarity Select", tegra210_dmic_lrsel_enum,
tegra210_dmic_get_control, tegra210_dmic_put_control), tegra210_dmic_get_pol_sel, tegra210_dmic_put_pol_sel),
}; };
static const struct snd_soc_component_driver tegra210_dmic_compnt = { static const struct snd_soc_component_driver tegra210_dmic_compnt = {
......
This diff is collapsed.
...@@ -192,24 +192,24 @@ static int tegra210_mixer_get_gain(struct snd_kcontrol *kcontrol, ...@@ -192,24 +192,24 @@ static int tegra210_mixer_get_gain(struct snd_kcontrol *kcontrol,
return 0; return 0;
} }
static int tegra210_mixer_put_gain(struct snd_kcontrol *kcontrol, static int tegra210_mixer_apply_gain(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol,
bool instant_gain)
{ {
struct soc_mixer_control *mc = struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value; (struct soc_mixer_control *)kcontrol->private_value;
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
struct tegra210_mixer *mixer = snd_soc_component_get_drvdata(cmpnt); struct tegra210_mixer *mixer = snd_soc_component_get_drvdata(cmpnt);
unsigned int reg = mc->reg, id; unsigned int reg = mc->reg, id;
bool instant_gain = false;
int err; int err;
if (strstr(kcontrol->id.name, "Instant Gain Volume"))
instant_gain = true;
/* Save gain value for specific MIXER input */ /* Save gain value for specific MIXER input */
id = (reg - TEGRA210_MIXER_GAIN_CFG_RAM_ADDR_0) / id = (reg - TEGRA210_MIXER_GAIN_CFG_RAM_ADDR_0) /
TEGRA210_MIXER_GAIN_CFG_RAM_ADDR_STRIDE; TEGRA210_MIXER_GAIN_CFG_RAM_ADDR_STRIDE;
if (mixer->gain_value[id] == ucontrol->value.integer.value[0])
return 0;
mixer->gain_value[id] = ucontrol->value.integer.value[0]; mixer->gain_value[id] = ucontrol->value.integer.value[0];
err = tegra210_mixer_configure_gain(cmpnt, id, instant_gain); err = tegra210_mixer_configure_gain(cmpnt, id, instant_gain);
...@@ -221,6 +221,18 @@ static int tegra210_mixer_put_gain(struct snd_kcontrol *kcontrol, ...@@ -221,6 +221,18 @@ static int tegra210_mixer_put_gain(struct snd_kcontrol *kcontrol,
return 1; return 1;
} }
static int tegra210_mixer_put_gain(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
return tegra210_mixer_apply_gain(kcontrol, ucontrol, false);
}
static int tegra210_mixer_put_instant_gain(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
return tegra210_mixer_apply_gain(kcontrol, ucontrol, true);
}
static int tegra210_mixer_set_audio_cif(struct tegra210_mixer *mixer, static int tegra210_mixer_set_audio_cif(struct tegra210_mixer *mixer,
struct snd_pcm_hw_params *params, struct snd_pcm_hw_params *params,
unsigned int reg, unsigned int reg,
...@@ -388,7 +400,7 @@ ADDER_CTRL_DECL(adder5, TEGRA210_MIXER_TX5_ADDER_CONFIG); ...@@ -388,7 +400,7 @@ ADDER_CTRL_DECL(adder5, TEGRA210_MIXER_TX5_ADDER_CONFIG);
SOC_SINGLE_EXT("RX" #id " Instant Gain Volume", \ SOC_SINGLE_EXT("RX" #id " Instant Gain Volume", \
MIXER_GAIN_CFG_RAM_ADDR((id) - 1), 0, \ MIXER_GAIN_CFG_RAM_ADDR((id) - 1), 0, \
0x20000, 0, tegra210_mixer_get_gain, \ 0x20000, 0, tegra210_mixer_get_gain, \
tegra210_mixer_put_gain), tegra210_mixer_put_instant_gain),
/* Volume controls for all MIXER inputs */ /* Volume controls for all MIXER inputs */
static const struct snd_kcontrol_new tegra210_mixer_gain_ctls[] = { static const struct snd_kcontrol_new tegra210_mixer_gain_ctls[] = {
......
...@@ -136,7 +136,7 @@ static int tegra210_mvc_put_mute(struct snd_kcontrol *kcontrol, ...@@ -136,7 +136,7 @@ static int tegra210_mvc_put_mute(struct snd_kcontrol *kcontrol,
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
struct tegra210_mvc *mvc = snd_soc_component_get_drvdata(cmpnt); struct tegra210_mvc *mvc = snd_soc_component_get_drvdata(cmpnt);
unsigned int value; unsigned int value;
u8 mute_mask; u8 new_mask, old_mask;
int err; int err;
pm_runtime_get_sync(cmpnt->dev); pm_runtime_get_sync(cmpnt->dev);
...@@ -148,11 +148,19 @@ static int tegra210_mvc_put_mute(struct snd_kcontrol *kcontrol, ...@@ -148,11 +148,19 @@ static int tegra210_mvc_put_mute(struct snd_kcontrol *kcontrol,
if (err < 0) if (err < 0)
goto end; goto end;
mute_mask = ucontrol->value.integer.value[0]; regmap_read(mvc->regmap, TEGRA210_MVC_CTRL, &value);
old_mask = (value >> TEGRA210_MVC_MUTE_SHIFT) & TEGRA210_MUTE_MASK_EN;
new_mask = ucontrol->value.integer.value[0];
if (new_mask == old_mask) {
err = 0;
goto end;
}
err = regmap_update_bits(mvc->regmap, mc->reg, err = regmap_update_bits(mvc->regmap, mc->reg,
TEGRA210_MVC_MUTE_MASK, TEGRA210_MVC_MUTE_MASK,
mute_mask << TEGRA210_MVC_MUTE_SHIFT); new_mask << TEGRA210_MVC_MUTE_SHIFT);
if (err < 0) if (err < 0)
goto end; goto end;
...@@ -195,7 +203,7 @@ static int tegra210_mvc_put_vol(struct snd_kcontrol *kcontrol, ...@@ -195,7 +203,7 @@ static int tegra210_mvc_put_vol(struct snd_kcontrol *kcontrol,
unsigned int reg = mc->reg; unsigned int reg = mc->reg;
unsigned int value; unsigned int value;
u8 chan; u8 chan;
int err; int err, old_volume;
pm_runtime_get_sync(cmpnt->dev); pm_runtime_get_sync(cmpnt->dev);
...@@ -207,10 +215,16 @@ static int tegra210_mvc_put_vol(struct snd_kcontrol *kcontrol, ...@@ -207,10 +215,16 @@ static int tegra210_mvc_put_vol(struct snd_kcontrol *kcontrol,
goto end; goto end;
chan = (reg - TEGRA210_MVC_TARGET_VOL) / REG_SIZE; chan = (reg - TEGRA210_MVC_TARGET_VOL) / REG_SIZE;
old_volume = mvc->volume[chan];
tegra210_mvc_conv_vol(mvc, chan, tegra210_mvc_conv_vol(mvc, chan,
ucontrol->value.integer.value[0]); ucontrol->value.integer.value[0]);
if (mvc->volume[chan] == old_volume) {
err = 0;
goto end;
}
/* Configure init volume same as target volume */ /* Configure init volume same as target volume */
regmap_write(mvc->regmap, regmap_write(mvc->regmap,
TEGRA210_MVC_REG_OFFSET(TEGRA210_MVC_INIT_VOL, chan), TEGRA210_MVC_REG_OFFSET(TEGRA210_MVC_INIT_VOL, chan),
...@@ -275,7 +289,7 @@ static int tegra210_mvc_get_curve_type(struct snd_kcontrol *kcontrol, ...@@ -275,7 +289,7 @@ static int tegra210_mvc_get_curve_type(struct snd_kcontrol *kcontrol,
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
struct tegra210_mvc *mvc = snd_soc_component_get_drvdata(cmpnt); struct tegra210_mvc *mvc = snd_soc_component_get_drvdata(cmpnt);
ucontrol->value.integer.value[0] = mvc->curve_type; ucontrol->value.enumerated.item[0] = mvc->curve_type;
return 0; return 0;
} }
...@@ -285,7 +299,7 @@ static int tegra210_mvc_put_curve_type(struct snd_kcontrol *kcontrol, ...@@ -285,7 +299,7 @@ static int tegra210_mvc_put_curve_type(struct snd_kcontrol *kcontrol,
{ {
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
struct tegra210_mvc *mvc = snd_soc_component_get_drvdata(cmpnt); struct tegra210_mvc *mvc = snd_soc_component_get_drvdata(cmpnt);
int value; unsigned int value;
regmap_read(mvc->regmap, TEGRA210_MVC_ENABLE, &value); regmap_read(mvc->regmap, TEGRA210_MVC_ENABLE, &value);
if (value & TEGRA210_MVC_EN) { if (value & TEGRA210_MVC_EN) {
...@@ -294,10 +308,10 @@ static int tegra210_mvc_put_curve_type(struct snd_kcontrol *kcontrol, ...@@ -294,10 +308,10 @@ static int tegra210_mvc_put_curve_type(struct snd_kcontrol *kcontrol,
return -EINVAL; return -EINVAL;
} }
if (mvc->curve_type == ucontrol->value.integer.value[0]) if (mvc->curve_type == ucontrol->value.enumerated.item[0])
return 0; return 0;
mvc->curve_type = ucontrol->value.integer.value[0]; mvc->curve_type = ucontrol->value.enumerated.item[0];
tegra210_mvc_reset_vol_settings(mvc, cmpnt->dev); tegra210_mvc_reset_vol_settings(mvc, cmpnt->dev);
......
...@@ -3244,46 +3244,107 @@ static int tegra210_sfc_init(struct snd_soc_dapm_widget *w, ...@@ -3244,46 +3244,107 @@ static int tegra210_sfc_init(struct snd_soc_dapm_widget *w,
return tegra210_sfc_write_coeff_ram(cmpnt); return tegra210_sfc_write_coeff_ram(cmpnt);
} }
static int tegra210_sfc_get_control(struct snd_kcontrol *kcontrol, static int tegra210_sfc_iget_stereo_to_mono(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
struct tegra210_sfc *sfc = snd_soc_component_get_drvdata(cmpnt); struct tegra210_sfc *sfc = snd_soc_component_get_drvdata(cmpnt);
if (strstr(kcontrol->id.name, "Input Stereo To Mono")) ucontrol->value.enumerated.item[0] = sfc->stereo_to_mono[SFC_RX_PATH];
ucontrol->value.integer.value[0] =
sfc->stereo_to_mono[SFC_RX_PATH];
else if (strstr(kcontrol->id.name, "Input Mono To Stereo"))
ucontrol->value.integer.value[0] =
sfc->mono_to_stereo[SFC_RX_PATH];
else if (strstr(kcontrol->id.name, "Output Stereo To Mono"))
ucontrol->value.integer.value[0] =
sfc->stereo_to_mono[SFC_TX_PATH];
else if (strstr(kcontrol->id.name, "Output Mono To Stereo"))
ucontrol->value.integer.value[0] =
sfc->mono_to_stereo[SFC_TX_PATH];
return 0; return 0;
} }
static int tegra210_sfc_put_control(struct snd_kcontrol *kcontrol, static int tegra210_sfc_iput_stereo_to_mono(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
struct tegra210_sfc *sfc = snd_soc_component_get_drvdata(cmpnt); struct tegra210_sfc *sfc = snd_soc_component_get_drvdata(cmpnt);
int value = ucontrol->value.integer.value[0]; unsigned int value = ucontrol->value.enumerated.item[0];
if (value == sfc->stereo_to_mono[SFC_RX_PATH])
return 0;
if (strstr(kcontrol->id.name, "Input Stereo To Mono"))
sfc->stereo_to_mono[SFC_RX_PATH] = value; sfc->stereo_to_mono[SFC_RX_PATH] = value;
else if (strstr(kcontrol->id.name, "Input Mono To Stereo"))
return 1;
}
static int tegra210_sfc_iget_mono_to_stereo(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
struct tegra210_sfc *sfc = snd_soc_component_get_drvdata(cmpnt);
ucontrol->value.enumerated.item[0] = sfc->mono_to_stereo[SFC_RX_PATH];
return 0;
}
static int tegra210_sfc_iput_mono_to_stereo(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
struct tegra210_sfc *sfc = snd_soc_component_get_drvdata(cmpnt);
unsigned int value = ucontrol->value.enumerated.item[0];
if (value == sfc->mono_to_stereo[SFC_RX_PATH])
return 0;
sfc->mono_to_stereo[SFC_RX_PATH] = value; sfc->mono_to_stereo[SFC_RX_PATH] = value;
else if (strstr(kcontrol->id.name, "Output Stereo To Mono"))
return 1;
}
static int tegra210_sfc_oget_stereo_to_mono(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
struct tegra210_sfc *sfc = snd_soc_component_get_drvdata(cmpnt);
ucontrol->value.enumerated.item[0] = sfc->stereo_to_mono[SFC_TX_PATH];
return 0;
}
static int tegra210_sfc_oput_stereo_to_mono(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
struct tegra210_sfc *sfc = snd_soc_component_get_drvdata(cmpnt);
unsigned int value = ucontrol->value.enumerated.item[0];
if (value == sfc->stereo_to_mono[SFC_TX_PATH])
return 0;
sfc->stereo_to_mono[SFC_TX_PATH] = value; sfc->stereo_to_mono[SFC_TX_PATH] = value;
else if (strstr(kcontrol->id.name, "Output Mono To Stereo"))
sfc->mono_to_stereo[SFC_TX_PATH] = value; return 1;
else }
static int tegra210_sfc_oget_mono_to_stereo(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
struct tegra210_sfc *sfc = snd_soc_component_get_drvdata(cmpnt);
ucontrol->value.enumerated.item[0] = sfc->mono_to_stereo[SFC_TX_PATH];
return 0;
}
static int tegra210_sfc_oput_mono_to_stereo(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol);
struct tegra210_sfc *sfc = snd_soc_component_get_drvdata(cmpnt);
unsigned int value = ucontrol->value.enumerated.item[0];
if (value == sfc->mono_to_stereo[SFC_TX_PATH])
return 0; return 0;
sfc->mono_to_stereo[SFC_TX_PATH] = value;
return 1; return 1;
} }
...@@ -3384,13 +3445,17 @@ static const struct soc_enum tegra210_sfc_mono_conv_enum = ...@@ -3384,13 +3445,17 @@ static const struct soc_enum tegra210_sfc_mono_conv_enum =
static const struct snd_kcontrol_new tegra210_sfc_controls[] = { static const struct snd_kcontrol_new tegra210_sfc_controls[] = {
SOC_ENUM_EXT("Input Stereo To Mono", tegra210_sfc_stereo_conv_enum, SOC_ENUM_EXT("Input Stereo To Mono", tegra210_sfc_stereo_conv_enum,
tegra210_sfc_get_control, tegra210_sfc_put_control), tegra210_sfc_iget_stereo_to_mono,
tegra210_sfc_iput_stereo_to_mono),
SOC_ENUM_EXT("Input Mono To Stereo", tegra210_sfc_mono_conv_enum, SOC_ENUM_EXT("Input Mono To Stereo", tegra210_sfc_mono_conv_enum,
tegra210_sfc_get_control, tegra210_sfc_put_control), tegra210_sfc_iget_mono_to_stereo,
tegra210_sfc_iput_mono_to_stereo),
SOC_ENUM_EXT("Output Stereo To Mono", tegra210_sfc_stereo_conv_enum, SOC_ENUM_EXT("Output Stereo To Mono", tegra210_sfc_stereo_conv_enum,
tegra210_sfc_get_control, tegra210_sfc_put_control), tegra210_sfc_oget_stereo_to_mono,
tegra210_sfc_oput_stereo_to_mono),
SOC_ENUM_EXT("Output Mono To Stereo", tegra210_sfc_mono_conv_enum, SOC_ENUM_EXT("Output Mono To Stereo", tegra210_sfc_mono_conv_enum,
tegra210_sfc_get_control, tegra210_sfc_put_control), tegra210_sfc_oget_mono_to_stereo,
tegra210_sfc_oput_mono_to_stereo),
}; };
static const struct snd_soc_component_driver tegra210_sfc_cmpnt = { static const struct snd_soc_component_driver tegra210_sfc_cmpnt = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment