提交 4a1e6ac7 编写于 作者: T Takashi Iwai

Merge branch 'for-linus' into for-next

Back-merge of 5.19-rc branch for the futher development, mainly about
USB-audio and HD-audio Cirrus stuff.
Signed-off-by: NTakashi Iwai <tiwai@suse.de>
...@@ -9811,7 +9811,10 @@ INTEL ASoC DRIVERS ...@@ -9811,7 +9811,10 @@ INTEL ASoC DRIVERS
M: Cezary Rojewski <cezary.rojewski@intel.com> M: Cezary Rojewski <cezary.rojewski@intel.com>
M: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> M: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
M: Liam Girdwood <liam.r.girdwood@linux.intel.com> M: Liam Girdwood <liam.r.girdwood@linux.intel.com>
M: Jie Yang <yang.jie@linux.intel.com> M: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
M: Bard Liao <yung-chuan.liao@linux.intel.com>
M: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
M: Kai Vehmanen <kai.vehmanen@linux.intel.com>
L: alsa-devel@alsa-project.org (moderated for non-subscribers) L: alsa-devel@alsa-project.org (moderated for non-subscribers)
S: Supported S: Supported
F: sound/soc/intel/ F: sound/soc/intel/
...@@ -16261,7 +16264,7 @@ F: drivers/crypto/qat/ ...@@ -16261,7 +16264,7 @@ F: drivers/crypto/qat/
QCOM AUDIO (ASoC) DRIVERS QCOM AUDIO (ASoC) DRIVERS
M: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> M: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
M: Banajit Goswami <bgoswami@codeaurora.org> M: Banajit Goswami <bgoswami@quicinc.com>
L: alsa-devel@alsa-project.org (moderated for non-subscribers) L: alsa-devel@alsa-project.org (moderated for non-subscribers)
S: Supported S: Supported
F: sound/soc/codecs/lpass-va-macro.c F: sound/soc/codecs/lpass-va-macro.c
...@@ -18687,8 +18690,10 @@ F: sound/soc/ ...@@ -18687,8 +18690,10 @@ F: sound/soc/
SOUND - SOUND OPEN FIRMWARE (SOF) DRIVERS SOUND - SOUND OPEN FIRMWARE (SOF) DRIVERS
M: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> M: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
M: Liam Girdwood <lgirdwood@gmail.com> M: Liam Girdwood <lgirdwood@gmail.com>
M: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
M: Bard Liao <yung-chuan.liao@linux.intel.com>
M: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> M: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
M: Kai Vehmanen <kai.vehmanen@linux.intel.com> R: Kai Vehmanen <kai.vehmanen@linux.intel.com>
M: Daniel Baluta <daniel.baluta@nxp.com> M: Daniel Baluta <daniel.baluta@nxp.com>
L: sound-open-firmware@alsa-project.org (moderated for non-subscribers) L: sound-open-firmware@alsa-project.org (moderated for non-subscribers)
S: Supported S: Supported
......
...@@ -1211,7 +1211,7 @@ static int ioctl_get_cycle_timer2(struct client *client, union ioctl_arg *arg) ...@@ -1211,7 +1211,7 @@ static int ioctl_get_cycle_timer2(struct client *client, union ioctl_arg *arg)
struct fw_cdev_get_cycle_timer2 *a = &arg->get_cycle_timer2; struct fw_cdev_get_cycle_timer2 *a = &arg->get_cycle_timer2;
struct fw_card *card = client->device->card; struct fw_card *card = client->device->card;
struct timespec64 ts = {0, 0}; struct timespec64 ts = {0, 0};
u32 cycle_time; u32 cycle_time = 0;
int ret = 0; int ret = 0;
local_irq_disable(); local_irq_disable();
......
...@@ -372,8 +372,7 @@ static ssize_t rom_index_show(struct device *dev, ...@@ -372,8 +372,7 @@ static ssize_t rom_index_show(struct device *dev,
struct fw_device *device = fw_device(dev->parent); struct fw_device *device = fw_device(dev->parent);
struct fw_unit *unit = fw_unit(dev); struct fw_unit *unit = fw_unit(dev);
return snprintf(buf, PAGE_SIZE, "%d\n", return sysfs_emit(buf, "%td\n", unit->directory - device->config_rom);
(int)(unit->directory - device->config_rom));
} }
static struct device_attribute fw_unit_attributes[] = { static struct device_attribute fw_unit_attributes[] = {
...@@ -403,8 +402,7 @@ static ssize_t guid_show(struct device *dev, ...@@ -403,8 +402,7 @@ static ssize_t guid_show(struct device *dev,
int ret; int ret;
down_read(&fw_device_rwsem); down_read(&fw_device_rwsem);
ret = snprintf(buf, PAGE_SIZE, "0x%08x%08x\n", ret = sysfs_emit(buf, "0x%08x%08x\n", device->config_rom[3], device->config_rom[4]);
device->config_rom[3], device->config_rom[4]);
up_read(&fw_device_rwsem); up_read(&fw_device_rwsem);
return ret; return ret;
......
...@@ -408,8 +408,6 @@ struct snd_soc_jack_pin; ...@@ -408,8 +408,6 @@ struct snd_soc_jack_pin;
struct snd_soc_jack_gpio; struct snd_soc_jack_gpio;
typedef int (*hw_write_t)(void *,const char* ,int);
enum snd_soc_pcm_subclass { enum snd_soc_pcm_subclass {
SND_SOC_PCM_CLASS_PCM = 0, SND_SOC_PCM_CLASS_PCM = 0,
SND_SOC_PCM_CLASS_BE = 1, SND_SOC_PCM_CLASS_BE = 1,
......
...@@ -431,33 +431,17 @@ static const struct snd_malloc_ops snd_dma_iram_ops = { ...@@ -431,33 +431,17 @@ static const struct snd_malloc_ops snd_dma_iram_ops = {
*/ */
static void *snd_dma_dev_alloc(struct snd_dma_buffer *dmab, size_t size) static void *snd_dma_dev_alloc(struct snd_dma_buffer *dmab, size_t size)
{ {
void *p; return dma_alloc_coherent(dmab->dev.dev, size, &dmab->addr, DEFAULT_GFP);
p = dma_alloc_coherent(dmab->dev.dev, size, &dmab->addr, DEFAULT_GFP);
#ifdef CONFIG_X86
if (p && dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC)
set_memory_wc((unsigned long)p, PAGE_ALIGN(size) >> PAGE_SHIFT);
#endif
return p;
} }
static void snd_dma_dev_free(struct snd_dma_buffer *dmab) static void snd_dma_dev_free(struct snd_dma_buffer *dmab)
{ {
#ifdef CONFIG_X86
if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC)
set_memory_wb((unsigned long)dmab->area,
PAGE_ALIGN(dmab->bytes) >> PAGE_SHIFT);
#endif
dma_free_coherent(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr); dma_free_coherent(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr);
} }
static int snd_dma_dev_mmap(struct snd_dma_buffer *dmab, static int snd_dma_dev_mmap(struct snd_dma_buffer *dmab,
struct vm_area_struct *area) struct vm_area_struct *area)
{ {
#ifdef CONFIG_X86
if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC)
area->vm_page_prot = pgprot_writecombine(area->vm_page_prot);
#endif
return dma_mmap_coherent(dmab->dev.dev, area, return dma_mmap_coherent(dmab->dev.dev, area,
dmab->area, dmab->addr, dmab->bytes); dmab->area, dmab->addr, dmab->bytes);
} }
...@@ -471,10 +455,6 @@ static const struct snd_malloc_ops snd_dma_dev_ops = { ...@@ -471,10 +455,6 @@ static const struct snd_malloc_ops snd_dma_dev_ops = {
/* /*
* Write-combined pages * Write-combined pages
*/ */
#ifdef CONFIG_X86
/* On x86, share the same ops as the standard dev ops */
#define snd_dma_wc_ops snd_dma_dev_ops
#else /* CONFIG_X86 */
static void *snd_dma_wc_alloc(struct snd_dma_buffer *dmab, size_t size) static void *snd_dma_wc_alloc(struct snd_dma_buffer *dmab, size_t size)
{ {
return dma_alloc_wc(dmab->dev.dev, size, &dmab->addr, DEFAULT_GFP); return dma_alloc_wc(dmab->dev.dev, size, &dmab->addr, DEFAULT_GFP);
...@@ -497,7 +477,6 @@ static const struct snd_malloc_ops snd_dma_wc_ops = { ...@@ -497,7 +477,6 @@ static const struct snd_malloc_ops snd_dma_wc_ops = {
.free = snd_dma_wc_free, .free = snd_dma_wc_free,
.mmap = snd_dma_wc_mmap, .mmap = snd_dma_wc_mmap,
}; };
#endif /* CONFIG_X86 */
#ifdef CONFIG_SND_DMA_SGBUF #ifdef CONFIG_SND_DMA_SGBUF
static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size); static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size);
......
...@@ -119,21 +119,18 @@ static int i915_component_master_match(struct device *dev, int subcomponent, ...@@ -119,21 +119,18 @@ static int i915_component_master_match(struct device *dev, int subcomponent,
/* check whether Intel graphics is present and reachable */ /* check whether Intel graphics is present and reachable */
static int i915_gfx_present(struct pci_dev *hdac_pci) static int i915_gfx_present(struct pci_dev *hdac_pci)
{ {
unsigned int class = PCI_BASE_CLASS_DISPLAY << 16;
struct pci_dev *display_dev = NULL; struct pci_dev *display_dev = NULL;
bool match = false;
do { for_each_pci_dev(display_dev) {
display_dev = pci_get_class(class, display_dev); if (display_dev->vendor == PCI_VENDOR_ID_INTEL &&
(display_dev->class >> 16) == PCI_BASE_CLASS_DISPLAY &&
if (display_dev && display_dev->vendor == PCI_VENDOR_ID_INTEL &&
connectivity_check(display_dev, hdac_pci)) { connectivity_check(display_dev, hdac_pci)) {
pci_dev_put(display_dev); pci_dev_put(display_dev);
match = true; return true;
} }
} while (!match && display_dev); }
return match; return false;
} }
/** /**
......
...@@ -196,6 +196,12 @@ static const struct config_entry config_table[] = { ...@@ -196,6 +196,12 @@ static const struct config_entry config_table[] = {
DMI_MATCH(DMI_SYS_VENDOR, "Google"), DMI_MATCH(DMI_SYS_VENDOR, "Google"),
} }
}, },
{
.ident = "UP-WHL",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "AAEON"),
}
},
{} {}
} }
}, },
...@@ -358,6 +364,12 @@ static const struct config_entry config_table[] = { ...@@ -358,6 +364,12 @@ static const struct config_entry config_table[] = {
DMI_MATCH(DMI_SYS_VENDOR, "Google"), DMI_MATCH(DMI_SYS_VENDOR, "Google"),
} }
}, },
{
.ident = "UPX-TGL",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "AAEON"),
}
},
{} {}
} }
}, },
......
...@@ -55,8 +55,8 @@ int intel_nhlt_get_dmic_geo(struct device *dev, struct nhlt_acpi_table *nhlt) ...@@ -55,8 +55,8 @@ int intel_nhlt_get_dmic_geo(struct device *dev, struct nhlt_acpi_table *nhlt)
/* find max number of channels based on format_configuration */ /* find max number of channels based on format_configuration */
if (fmt_configs->fmt_count) { if (fmt_configs->fmt_count) {
dev_dbg(dev, "%s: found %d format definitions\n", dev_dbg(dev, "found %d format definitions\n",
__func__, fmt_configs->fmt_count); fmt_configs->fmt_count);
for (i = 0; i < fmt_configs->fmt_count; i++) { for (i = 0; i < fmt_configs->fmt_count; i++) {
struct wav_fmt_ext *fmt_ext; struct wav_fmt_ext *fmt_ext;
...@@ -66,9 +66,9 @@ int intel_nhlt_get_dmic_geo(struct device *dev, struct nhlt_acpi_table *nhlt) ...@@ -66,9 +66,9 @@ int intel_nhlt_get_dmic_geo(struct device *dev, struct nhlt_acpi_table *nhlt)
if (fmt_ext->fmt.channels > max_ch) if (fmt_ext->fmt.channels > max_ch)
max_ch = fmt_ext->fmt.channels; max_ch = fmt_ext->fmt.channels;
} }
dev_dbg(dev, "%s: max channels found %d\n", __func__, max_ch); dev_dbg(dev, "max channels found %d\n", max_ch);
} else { } else {
dev_dbg(dev, "%s: No format information found\n", __func__); dev_dbg(dev, "No format information found\n");
} }
if (cfg->device_config.config_type != NHLT_CONFIG_TYPE_MIC_ARRAY) { if (cfg->device_config.config_type != NHLT_CONFIG_TYPE_MIC_ARRAY) {
...@@ -95,17 +95,16 @@ int intel_nhlt_get_dmic_geo(struct device *dev, struct nhlt_acpi_table *nhlt) ...@@ -95,17 +95,16 @@ int intel_nhlt_get_dmic_geo(struct device *dev, struct nhlt_acpi_table *nhlt)
} }
if (dmic_geo > 0) { if (dmic_geo > 0) {
dev_dbg(dev, "%s: Array with %d dmics\n", __func__, dmic_geo); dev_dbg(dev, "Array with %d dmics\n", dmic_geo);
} }
if (max_ch > dmic_geo) { if (max_ch > dmic_geo) {
dev_dbg(dev, "%s: max channels %d exceed dmic number %d\n", dev_dbg(dev, "max channels %d exceed dmic number %d\n",
__func__, max_ch, dmic_geo); max_ch, dmic_geo);
} }
} }
} }
dev_dbg(dev, "%s: dmic number %d max_ch %d\n", dev_dbg(dev, "dmic number %d max_ch %d\n", dmic_geo, max_ch);
__func__, dmic_geo, max_ch);
return dmic_geo; return dmic_geo;
} }
......
...@@ -1079,11 +1079,11 @@ static int patch_conexant_auto(struct hda_codec *codec) ...@@ -1079,11 +1079,11 @@ static int patch_conexant_auto(struct hda_codec *codec)
if (err < 0) if (err < 0)
goto error; goto error;
err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg); err = cx_auto_parse_beep(codec);
if (err < 0) if (err < 0)
goto error; goto error;
err = cx_auto_parse_beep(codec); err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg);
if (err < 0) if (err < 0)
goto error; goto error;
......
...@@ -2634,6 +2634,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { ...@@ -2634,6 +2634,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
SND_PCI_QUIRK(0x1558, 0x67e1, "Clevo PB71[DE][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), SND_PCI_QUIRK(0x1558, 0x67e1, "Clevo PB71[DE][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x67e5, "Clevo PC70D[PRS](?:-D|-G)?", ALC1220_FIXUP_CLEVO_PB51ED_PINS), SND_PCI_QUIRK(0x1558, 0x67e5, "Clevo PC70D[PRS](?:-D|-G)?", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x67f1, "Clevo PC70H[PRS]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), SND_PCI_QUIRK(0x1558, 0x67f1, "Clevo PC70H[PRS]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x67f5, "Clevo PD70PN[NRT]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x70d1, "Clevo PC70[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), SND_PCI_QUIRK(0x1558, 0x70d1, "Clevo PC70[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x7714, "Clevo X170SM", ALC1220_FIXUP_CLEVO_PB51ED_PINS), SND_PCI_QUIRK(0x1558, 0x7714, "Clevo X170SM", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x7715, "Clevo X170KM-G", ALC1220_FIXUP_CLEVO_PB51ED), SND_PCI_QUIRK(0x1558, 0x7715, "Clevo X170KM-G", ALC1220_FIXUP_CLEVO_PB51ED),
...@@ -9210,6 +9211,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { ...@@ -9210,6 +9211,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1558, 0x70f3, "Clevo NH77DPQ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x70f3, "Clevo NH77DPQ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0x70f4, "Clevo NH77EPY", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x70f4, "Clevo NH77EPY", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0x70f6, "Clevo NH77DPQ-Y", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x70f6, "Clevo NH77DPQ-Y", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0x7716, "Clevo NS50PU", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0x7718, "Clevo L140PU", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0x8228, "Clevo NR40BU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x8228, "Clevo NR40BU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0x8520, "Clevo NH50D[CD]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x8520, "Clevo NH50D[CD]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0x8521, "Clevo NH77D[CD]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x8521, "Clevo NH77D[CD]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
......
...@@ -518,11 +518,11 @@ static int via_parse_auto_config(struct hda_codec *codec) ...@@ -518,11 +518,11 @@ static int via_parse_auto_config(struct hda_codec *codec)
if (err < 0) if (err < 0)
return err; return err;
err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg); err = auto_parse_beep(codec);
if (err < 0) if (err < 0)
return err; return err;
err = auto_parse_beep(codec); err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg);
if (err < 0) if (err < 0)
return err; return err;
......
...@@ -868,10 +868,12 @@ static void ak4613_parse_of(struct ak4613_priv *priv, ...@@ -868,10 +868,12 @@ static void ak4613_parse_of(struct ak4613_priv *priv,
/* /*
* connected STDI * connected STDI
* TDM support is assuming it is probed via Audio-Graph-Card style here.
* Default is SDTIx1 if it was probed via Simple-Audio-Card for now.
*/ */
sdti_num = of_graph_get_endpoint_count(np); sdti_num = of_graph_get_endpoint_count(np);
if (WARN_ON((sdti_num > 3) || (sdti_num < 1))) if ((sdti_num >= SDTx_MAX) || (sdti_num < 1))
return; sdti_num = 1;
AK4613_CONFIG_SDTI_set(priv, sdti_num); AK4613_CONFIG_SDTI_set(priv, sdti_num);
} }
......
...@@ -37,8 +37,8 @@ static const struct reg_default cs35l41_reg[] = { ...@@ -37,8 +37,8 @@ static const struct reg_default cs35l41_reg[] = {
{ CS35L41_DAC_PCM1_SRC, 0x00000008 }, { CS35L41_DAC_PCM1_SRC, 0x00000008 },
{ CS35L41_ASP_TX1_SRC, 0x00000018 }, { CS35L41_ASP_TX1_SRC, 0x00000018 },
{ CS35L41_ASP_TX2_SRC, 0x00000019 }, { CS35L41_ASP_TX2_SRC, 0x00000019 },
{ CS35L41_ASP_TX3_SRC, 0x00000020 }, { CS35L41_ASP_TX3_SRC, 0x00000000 },
{ CS35L41_ASP_TX4_SRC, 0x00000021 }, { CS35L41_ASP_TX4_SRC, 0x00000000 },
{ CS35L41_DSP1_RX1_SRC, 0x00000008 }, { CS35L41_DSP1_RX1_SRC, 0x00000008 },
{ CS35L41_DSP1_RX2_SRC, 0x00000009 }, { CS35L41_DSP1_RX2_SRC, 0x00000009 },
{ CS35L41_DSP1_RX3_SRC, 0x00000018 }, { CS35L41_DSP1_RX3_SRC, 0x00000018 },
...@@ -644,6 +644,8 @@ static const struct reg_sequence cs35l41_reva0_errata_patch[] = { ...@@ -644,6 +644,8 @@ static const struct reg_sequence cs35l41_reva0_errata_patch[] = {
{ CS35L41_DSP1_XM_ACCEL_PL0_PRI, 0x00000000 }, { CS35L41_DSP1_XM_ACCEL_PL0_PRI, 0x00000000 },
{ CS35L41_PWR_CTRL2, 0x00000000 }, { CS35L41_PWR_CTRL2, 0x00000000 },
{ CS35L41_AMP_GAIN_CTRL, 0x00000000 }, { CS35L41_AMP_GAIN_CTRL, 0x00000000 },
{ CS35L41_ASP_TX3_SRC, 0x00000000 },
{ CS35L41_ASP_TX4_SRC, 0x00000000 },
}; };
static const struct reg_sequence cs35l41_revb0_errata_patch[] = { static const struct reg_sequence cs35l41_revb0_errata_patch[] = {
...@@ -655,6 +657,8 @@ static const struct reg_sequence cs35l41_revb0_errata_patch[] = { ...@@ -655,6 +657,8 @@ static const struct reg_sequence cs35l41_revb0_errata_patch[] = {
{ CS35L41_DSP1_XM_ACCEL_PL0_PRI, 0x00000000 }, { CS35L41_DSP1_XM_ACCEL_PL0_PRI, 0x00000000 },
{ CS35L41_PWR_CTRL2, 0x00000000 }, { CS35L41_PWR_CTRL2, 0x00000000 },
{ CS35L41_AMP_GAIN_CTRL, 0x00000000 }, { CS35L41_AMP_GAIN_CTRL, 0x00000000 },
{ CS35L41_ASP_TX3_SRC, 0x00000000 },
{ CS35L41_ASP_TX4_SRC, 0x00000000 },
}; };
static const struct reg_sequence cs35l41_revb2_errata_patch[] = { static const struct reg_sequence cs35l41_revb2_errata_patch[] = {
...@@ -666,6 +670,8 @@ static const struct reg_sequence cs35l41_revb2_errata_patch[] = { ...@@ -666,6 +670,8 @@ static const struct reg_sequence cs35l41_revb2_errata_patch[] = {
{ CS35L41_DSP1_XM_ACCEL_PL0_PRI, 0x00000000 }, { CS35L41_DSP1_XM_ACCEL_PL0_PRI, 0x00000000 },
{ CS35L41_PWR_CTRL2, 0x00000000 }, { CS35L41_PWR_CTRL2, 0x00000000 },
{ CS35L41_AMP_GAIN_CTRL, 0x00000000 }, { CS35L41_AMP_GAIN_CTRL, 0x00000000 },
{ CS35L41_ASP_TX3_SRC, 0x00000000 },
{ CS35L41_ASP_TX4_SRC, 0x00000000 },
}; };
static const struct reg_sequence cs35l41_fs_errata_patch[] = { static const struct reg_sequence cs35l41_fs_errata_patch[] = {
......
...@@ -333,7 +333,7 @@ static const struct snd_kcontrol_new cs35l41_aud_controls[] = { ...@@ -333,7 +333,7 @@ static const struct snd_kcontrol_new cs35l41_aud_controls[] = {
SOC_SINGLE("HW Noise Gate Enable", CS35L41_NG_CFG, 8, 63, 0), SOC_SINGLE("HW Noise Gate Enable", CS35L41_NG_CFG, 8, 63, 0),
SOC_SINGLE("HW Noise Gate Delay", CS35L41_NG_CFG, 4, 7, 0), SOC_SINGLE("HW Noise Gate Delay", CS35L41_NG_CFG, 4, 7, 0),
SOC_SINGLE("HW Noise Gate Threshold", CS35L41_NG_CFG, 0, 7, 0), SOC_SINGLE("HW Noise Gate Threshold", CS35L41_NG_CFG, 0, 7, 0),
SOC_SINGLE("Aux Noise Gate CH1 Enable", SOC_SINGLE("Aux Noise Gate CH1 Switch",
CS35L41_MIXER_NGATE_CH1_CFG, 16, 1, 0), CS35L41_MIXER_NGATE_CH1_CFG, 16, 1, 0),
SOC_SINGLE("Aux Noise Gate CH1 Entry Delay", SOC_SINGLE("Aux Noise Gate CH1 Entry Delay",
CS35L41_MIXER_NGATE_CH1_CFG, 8, 15, 0), CS35L41_MIXER_NGATE_CH1_CFG, 8, 15, 0),
...@@ -341,15 +341,15 @@ static const struct snd_kcontrol_new cs35l41_aud_controls[] = { ...@@ -341,15 +341,15 @@ static const struct snd_kcontrol_new cs35l41_aud_controls[] = {
CS35L41_MIXER_NGATE_CH1_CFG, 0, 7, 0), CS35L41_MIXER_NGATE_CH1_CFG, 0, 7, 0),
SOC_SINGLE("Aux Noise Gate CH2 Entry Delay", SOC_SINGLE("Aux Noise Gate CH2 Entry Delay",
CS35L41_MIXER_NGATE_CH2_CFG, 8, 15, 0), CS35L41_MIXER_NGATE_CH2_CFG, 8, 15, 0),
SOC_SINGLE("Aux Noise Gate CH2 Enable", SOC_SINGLE("Aux Noise Gate CH2 Switch",
CS35L41_MIXER_NGATE_CH2_CFG, 16, 1, 0), CS35L41_MIXER_NGATE_CH2_CFG, 16, 1, 0),
SOC_SINGLE("Aux Noise Gate CH2 Threshold", SOC_SINGLE("Aux Noise Gate CH2 Threshold",
CS35L41_MIXER_NGATE_CH2_CFG, 0, 7, 0), CS35L41_MIXER_NGATE_CH2_CFG, 0, 7, 0),
SOC_SINGLE("SCLK Force", CS35L41_SP_FORMAT, CS35L41_SCLK_FRC_SHIFT, 1, 0), SOC_SINGLE("SCLK Force Switch", CS35L41_SP_FORMAT, CS35L41_SCLK_FRC_SHIFT, 1, 0),
SOC_SINGLE("LRCLK Force", CS35L41_SP_FORMAT, CS35L41_LRCLK_FRC_SHIFT, 1, 0), SOC_SINGLE("LRCLK Force Switch", CS35L41_SP_FORMAT, CS35L41_LRCLK_FRC_SHIFT, 1, 0),
SOC_SINGLE("Invert Class D", CS35L41_AMP_DIG_VOL_CTRL, SOC_SINGLE("Invert Class D Switch", CS35L41_AMP_DIG_VOL_CTRL,
CS35L41_AMP_INV_PCM_SHIFT, 1, 0), CS35L41_AMP_INV_PCM_SHIFT, 1, 0),
SOC_SINGLE("Amp Gain ZC", CS35L41_AMP_GAIN_CTRL, SOC_SINGLE("Amp Gain ZC Switch", CS35L41_AMP_GAIN_CTRL,
CS35L41_AMP_GAIN_ZC_SHIFT, 1, 0), CS35L41_AMP_GAIN_ZC_SHIFT, 1, 0),
WM_ADSP2_PRELOAD_SWITCH("DSP1", 1), WM_ADSP2_PRELOAD_SWITCH("DSP1", 1),
WM_ADSP_FW_CONTROL("DSP1", 0), WM_ADSP_FW_CONTROL("DSP1", 0),
......
...@@ -122,6 +122,9 @@ static int cs47l15_in1_adc_put(struct snd_kcontrol *kcontrol, ...@@ -122,6 +122,9 @@ static int cs47l15_in1_adc_put(struct snd_kcontrol *kcontrol,
snd_soc_kcontrol_component(kcontrol); snd_soc_kcontrol_component(kcontrol);
struct cs47l15 *cs47l15 = snd_soc_component_get_drvdata(component); struct cs47l15 *cs47l15 = snd_soc_component_get_drvdata(component);
if (!!ucontrol->value.integer.value[0] == cs47l15->in1_lp_mode)
return 0;
switch (ucontrol->value.integer.value[0]) { switch (ucontrol->value.integer.value[0]) {
case 0: case 0:
/* Set IN1 to normal mode */ /* Set IN1 to normal mode */
...@@ -150,7 +153,7 @@ static int cs47l15_in1_adc_put(struct snd_kcontrol *kcontrol, ...@@ -150,7 +153,7 @@ static int cs47l15_in1_adc_put(struct snd_kcontrol *kcontrol,
break; break;
} }
return 0; return 1;
} }
static const struct snd_kcontrol_new cs47l15_snd_controls[] = { static const struct snd_kcontrol_new cs47l15_snd_controls[] = {
......
...@@ -618,7 +618,13 @@ int madera_out1_demux_put(struct snd_kcontrol *kcontrol, ...@@ -618,7 +618,13 @@ int madera_out1_demux_put(struct snd_kcontrol *kcontrol,
end: end:
snd_soc_dapm_mutex_unlock(dapm); snd_soc_dapm_mutex_unlock(dapm);
return snd_soc_dapm_mux_update_power(dapm, kcontrol, mux, e, NULL); ret = snd_soc_dapm_mux_update_power(dapm, kcontrol, mux, e, NULL);
if (ret < 0) {
dev_err(madera->dev, "Failed to update demux power state: %d\n", ret);
return ret;
}
return change;
} }
EXPORT_SYMBOL_GPL(madera_out1_demux_put); EXPORT_SYMBOL_GPL(madera_out1_demux_put);
...@@ -893,7 +899,7 @@ static int madera_adsp_rate_put(struct snd_kcontrol *kcontrol, ...@@ -893,7 +899,7 @@ static int madera_adsp_rate_put(struct snd_kcontrol *kcontrol,
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
const int adsp_num = e->shift_l; const int adsp_num = e->shift_l;
const unsigned int item = ucontrol->value.enumerated.item[0]; const unsigned int item = ucontrol->value.enumerated.item[0];
int ret; int ret = 0;
if (item >= e->items) if (item >= e->items)
return -EINVAL; return -EINVAL;
...@@ -910,10 +916,10 @@ static int madera_adsp_rate_put(struct snd_kcontrol *kcontrol, ...@@ -910,10 +916,10 @@ static int madera_adsp_rate_put(struct snd_kcontrol *kcontrol,
"Cannot change '%s' while in use by active audio paths\n", "Cannot change '%s' while in use by active audio paths\n",
kcontrol->id.name); kcontrol->id.name);
ret = -EBUSY; ret = -EBUSY;
} else { } else if (priv->adsp_rate_cache[adsp_num] != e->values[item]) {
/* Volatile register so defer until the codec is powered up */ /* Volatile register so defer until the codec is powered up */
priv->adsp_rate_cache[adsp_num] = e->values[item]; priv->adsp_rate_cache[adsp_num] = e->values[item];
ret = 0; ret = 1;
} }
mutex_unlock(&priv->rate_lock); mutex_unlock(&priv->rate_lock);
......
...@@ -862,6 +862,16 @@ static int max98373_sdw_probe(struct sdw_slave *slave, ...@@ -862,6 +862,16 @@ static int max98373_sdw_probe(struct sdw_slave *slave,
return max98373_init(slave, regmap); return max98373_init(slave, regmap);
} }
static int max98373_sdw_remove(struct sdw_slave *slave)
{
struct max98373_priv *max98373 = dev_get_drvdata(&slave->dev);
if (max98373->first_hw_init)
pm_runtime_disable(&slave->dev);
return 0;
}
#if defined(CONFIG_OF) #if defined(CONFIG_OF)
static const struct of_device_id max98373_of_match[] = { static const struct of_device_id max98373_of_match[] = {
{ .compatible = "maxim,max98373", }, { .compatible = "maxim,max98373", },
...@@ -893,7 +903,7 @@ static struct sdw_driver max98373_sdw_driver = { ...@@ -893,7 +903,7 @@ static struct sdw_driver max98373_sdw_driver = {
.pm = &max98373_pm, .pm = &max98373_pm,
}, },
.probe = max98373_sdw_probe, .probe = max98373_sdw_probe,
.remove = NULL, .remove = max98373_sdw_remove,
.ops = &max98373_slave_ops, .ops = &max98373_slave_ops,
.id_table = max98373_id, .id_table = max98373_id,
}; };
......
...@@ -691,6 +691,16 @@ static int rt1308_sdw_probe(struct sdw_slave *slave, ...@@ -691,6 +691,16 @@ static int rt1308_sdw_probe(struct sdw_slave *slave,
return 0; return 0;
} }
static int rt1308_sdw_remove(struct sdw_slave *slave)
{
struct rt1308_sdw_priv *rt1308 = dev_get_drvdata(&slave->dev);
if (rt1308->first_hw_init)
pm_runtime_disable(&slave->dev);
return 0;
}
static const struct sdw_device_id rt1308_id[] = { static const struct sdw_device_id rt1308_id[] = {
SDW_SLAVE_ENTRY_EXT(0x025d, 0x1308, 0x2, 0, 0), SDW_SLAVE_ENTRY_EXT(0x025d, 0x1308, 0x2, 0, 0),
{}, {},
...@@ -750,6 +760,7 @@ static struct sdw_driver rt1308_sdw_driver = { ...@@ -750,6 +760,7 @@ static struct sdw_driver rt1308_sdw_driver = {
.pm = &rt1308_pm, .pm = &rt1308_pm,
}, },
.probe = rt1308_sdw_probe, .probe = rt1308_sdw_probe,
.remove = rt1308_sdw_remove,
.ops = &rt1308_slave_ops, .ops = &rt1308_slave_ops,
.id_table = rt1308_id, .id_table = rt1308_id,
}; };
......
...@@ -676,6 +676,16 @@ static int rt1316_sdw_probe(struct sdw_slave *slave, ...@@ -676,6 +676,16 @@ static int rt1316_sdw_probe(struct sdw_slave *slave,
return rt1316_sdw_init(&slave->dev, regmap, slave); return rt1316_sdw_init(&slave->dev, regmap, slave);
} }
static int rt1316_sdw_remove(struct sdw_slave *slave)
{
struct rt1316_sdw_priv *rt1316 = dev_get_drvdata(&slave->dev);
if (rt1316->first_hw_init)
pm_runtime_disable(&slave->dev);
return 0;
}
static const struct sdw_device_id rt1316_id[] = { static const struct sdw_device_id rt1316_id[] = {
SDW_SLAVE_ENTRY_EXT(0x025d, 0x1316, 0x3, 0x1, 0), SDW_SLAVE_ENTRY_EXT(0x025d, 0x1316, 0x3, 0x1, 0),
{}, {},
...@@ -735,6 +745,7 @@ static struct sdw_driver rt1316_sdw_driver = { ...@@ -735,6 +745,7 @@ static struct sdw_driver rt1316_sdw_driver = {
.pm = &rt1316_pm, .pm = &rt1316_pm,
}, },
.probe = rt1316_sdw_probe, .probe = rt1316_sdw_probe,
.remove = rt1316_sdw_remove,
.ops = &rt1316_slave_ops, .ops = &rt1316_slave_ops,
.id_table = rt1316_id, .id_table = rt1316_id,
}; };
......
...@@ -719,9 +719,12 @@ static int rt5682_sdw_remove(struct sdw_slave *slave) ...@@ -719,9 +719,12 @@ static int rt5682_sdw_remove(struct sdw_slave *slave)
{ {
struct rt5682_priv *rt5682 = dev_get_drvdata(&slave->dev); struct rt5682_priv *rt5682 = dev_get_drvdata(&slave->dev);
if (rt5682 && rt5682->hw_init) if (rt5682->hw_init)
cancel_delayed_work_sync(&rt5682->jack_detect_work); cancel_delayed_work_sync(&rt5682->jack_detect_work);
if (rt5682->first_hw_init)
pm_runtime_disable(&slave->dev);
return 0; return 0;
} }
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/soundwire/sdw_type.h> #include <linux/soundwire/sdw_type.h>
#include <linux/soundwire/sdw_registers.h> #include <linux/soundwire/sdw_registers.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <sound/soc.h> #include <sound/soc.h>
#include "rt700.h" #include "rt700.h"
...@@ -463,11 +464,14 @@ static int rt700_sdw_remove(struct sdw_slave *slave) ...@@ -463,11 +464,14 @@ static int rt700_sdw_remove(struct sdw_slave *slave)
{ {
struct rt700_priv *rt700 = dev_get_drvdata(&slave->dev); struct rt700_priv *rt700 = dev_get_drvdata(&slave->dev);
if (rt700 && rt700->hw_init) { if (rt700->hw_init) {
cancel_delayed_work_sync(&rt700->jack_detect_work); cancel_delayed_work_sync(&rt700->jack_detect_work);
cancel_delayed_work_sync(&rt700->jack_btn_check_work); cancel_delayed_work_sync(&rt700->jack_btn_check_work);
} }
if (rt700->first_hw_init)
pm_runtime_disable(&slave->dev);
return 0; return 0;
} }
......
...@@ -162,7 +162,7 @@ static void rt700_jack_detect_handler(struct work_struct *work) ...@@ -162,7 +162,7 @@ static void rt700_jack_detect_handler(struct work_struct *work)
if (!rt700->hs_jack) if (!rt700->hs_jack)
return; return;
if (!rt700->component->card->instantiated) if (!rt700->component->card || !rt700->component->card->instantiated)
return; return;
reg = RT700_VERB_GET_PIN_SENSE | RT700_HP_OUT; reg = RT700_VERB_GET_PIN_SENSE | RT700_HP_OUT;
...@@ -315,17 +315,27 @@ static int rt700_set_jack_detect(struct snd_soc_component *component, ...@@ -315,17 +315,27 @@ static int rt700_set_jack_detect(struct snd_soc_component *component,
struct snd_soc_jack *hs_jack, void *data) struct snd_soc_jack *hs_jack, void *data)
{ {
struct rt700_priv *rt700 = snd_soc_component_get_drvdata(component); struct rt700_priv *rt700 = snd_soc_component_get_drvdata(component);
int ret;
rt700->hs_jack = hs_jack; rt700->hs_jack = hs_jack;
if (!rt700->hw_init) { ret = pm_runtime_resume_and_get(component->dev);
dev_dbg(&rt700->slave->dev, if (ret < 0) {
"%s hw_init not ready yet\n", __func__); if (ret != -EACCES) {
dev_err(component->dev, "%s: failed to resume %d\n", __func__, ret);
return ret;
}
/* pm_runtime not enabled yet */
dev_dbg(component->dev, "%s: skipping jack init for now\n", __func__);
return 0; return 0;
} }
rt700_jack_init(rt700); rt700_jack_init(rt700);
pm_runtime_mark_last_busy(component->dev);
pm_runtime_put_autosuspend(component->dev);
return 0; return 0;
} }
...@@ -1115,6 +1125,11 @@ int rt700_init(struct device *dev, struct regmap *sdw_regmap, ...@@ -1115,6 +1125,11 @@ int rt700_init(struct device *dev, struct regmap *sdw_regmap,
mutex_init(&rt700->disable_irq_lock); mutex_init(&rt700->disable_irq_lock);
INIT_DELAYED_WORK(&rt700->jack_detect_work,
rt700_jack_detect_handler);
INIT_DELAYED_WORK(&rt700->jack_btn_check_work,
rt700_btn_check_handler);
/* /*
* Mark hw_init to false * Mark hw_init to false
* HW init will be performed when device reports present * HW init will be performed when device reports present
...@@ -1209,13 +1224,6 @@ int rt700_io_init(struct device *dev, struct sdw_slave *slave) ...@@ -1209,13 +1224,6 @@ int rt700_io_init(struct device *dev, struct sdw_slave *slave)
/* Finish Initial Settings, set power to D3 */ /* Finish Initial Settings, set power to D3 */
regmap_write(rt700->regmap, RT700_SET_AUDIO_POWER_STATE, AC_PWRST_D3); regmap_write(rt700->regmap, RT700_SET_AUDIO_POWER_STATE, AC_PWRST_D3);
if (!rt700->first_hw_init) {
INIT_DELAYED_WORK(&rt700->jack_detect_work,
rt700_jack_detect_handler);
INIT_DELAYED_WORK(&rt700->jack_btn_check_work,
rt700_btn_check_handler);
}
/* /*
* if set_jack callback occurred early than io_init, * if set_jack callback occurred early than io_init,
* we set up the jack detection function now * we set up the jack detection function now
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/mod_devicetable.h> #include <linux/mod_devicetable.h>
#include <linux/soundwire/sdw_registers.h> #include <linux/soundwire/sdw_registers.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/pm_runtime.h>
#include "rt711-sdca.h" #include "rt711-sdca.h"
#include "rt711-sdca-sdw.h" #include "rt711-sdca-sdw.h"
...@@ -364,11 +365,17 @@ static int rt711_sdca_sdw_remove(struct sdw_slave *slave) ...@@ -364,11 +365,17 @@ static int rt711_sdca_sdw_remove(struct sdw_slave *slave)
{ {
struct rt711_sdca_priv *rt711 = dev_get_drvdata(&slave->dev); struct rt711_sdca_priv *rt711 = dev_get_drvdata(&slave->dev);
if (rt711 && rt711->hw_init) { if (rt711->hw_init) {
cancel_delayed_work_sync(&rt711->jack_detect_work); cancel_delayed_work_sync(&rt711->jack_detect_work);
cancel_delayed_work_sync(&rt711->jack_btn_check_work); cancel_delayed_work_sync(&rt711->jack_btn_check_work);
} }
if (rt711->first_hw_init)
pm_runtime_disable(&slave->dev);
mutex_destroy(&rt711->calibrate_mutex);
mutex_destroy(&rt711->disable_irq_lock);
return 0; return 0;
} }
......
...@@ -34,7 +34,7 @@ static int rt711_sdca_index_write(struct rt711_sdca_priv *rt711, ...@@ -34,7 +34,7 @@ static int rt711_sdca_index_write(struct rt711_sdca_priv *rt711,
ret = regmap_write(regmap, addr, value); ret = regmap_write(regmap, addr, value);
if (ret < 0) if (ret < 0)
dev_err(rt711->component->dev, dev_err(&rt711->slave->dev,
"Failed to set private value: %06x <= %04x ret=%d\n", "Failed to set private value: %06x <= %04x ret=%d\n",
addr, value, ret); addr, value, ret);
...@@ -50,7 +50,7 @@ static int rt711_sdca_index_read(struct rt711_sdca_priv *rt711, ...@@ -50,7 +50,7 @@ static int rt711_sdca_index_read(struct rt711_sdca_priv *rt711,
ret = regmap_read(regmap, addr, value); ret = regmap_read(regmap, addr, value);
if (ret < 0) if (ret < 0)
dev_err(rt711->component->dev, dev_err(&rt711->slave->dev,
"Failed to get private value: %06x => %04x ret=%d\n", "Failed to get private value: %06x => %04x ret=%d\n",
addr, *value, ret); addr, *value, ret);
...@@ -294,7 +294,7 @@ static void rt711_sdca_jack_detect_handler(struct work_struct *work) ...@@ -294,7 +294,7 @@ static void rt711_sdca_jack_detect_handler(struct work_struct *work)
if (!rt711->hs_jack) if (!rt711->hs_jack)
return; return;
if (!rt711->component->card->instantiated) if (!rt711->component->card || !rt711->component->card->instantiated)
return; return;
/* SDW_SCP_SDCA_INT_SDCA_0 is used for jack detection */ /* SDW_SCP_SDCA_INT_SDCA_0 is used for jack detection */
...@@ -487,16 +487,27 @@ static int rt711_sdca_set_jack_detect(struct snd_soc_component *component, ...@@ -487,16 +487,27 @@ static int rt711_sdca_set_jack_detect(struct snd_soc_component *component,
struct snd_soc_jack *hs_jack, void *data) struct snd_soc_jack *hs_jack, void *data)
{ {
struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component);
int ret;
rt711->hs_jack = hs_jack; rt711->hs_jack = hs_jack;
if (!rt711->hw_init) { ret = pm_runtime_resume_and_get(component->dev);
dev_dbg(&rt711->slave->dev, if (ret < 0) {
"%s hw_init not ready yet\n", __func__); if (ret != -EACCES) {
dev_err(component->dev, "%s: failed to resume %d\n", __func__, ret);
return ret;
}
/* pm_runtime not enabled yet */
dev_dbg(component->dev, "%s: skipping jack init for now\n", __func__);
return 0; return 0;
} }
rt711_sdca_jack_init(rt711); rt711_sdca_jack_init(rt711);
pm_runtime_mark_last_busy(component->dev);
pm_runtime_put_autosuspend(component->dev);
return 0; return 0;
} }
...@@ -1190,14 +1201,6 @@ static int rt711_sdca_probe(struct snd_soc_component *component) ...@@ -1190,14 +1201,6 @@ static int rt711_sdca_probe(struct snd_soc_component *component)
return 0; return 0;
} }
static void rt711_sdca_remove(struct snd_soc_component *component)
{
struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component);
regcache_cache_only(rt711->regmap, true);
regcache_cache_only(rt711->mbq_regmap, true);
}
static const struct snd_soc_component_driver soc_sdca_dev_rt711 = { static const struct snd_soc_component_driver soc_sdca_dev_rt711 = {
.probe = rt711_sdca_probe, .probe = rt711_sdca_probe,
.controls = rt711_sdca_snd_controls, .controls = rt711_sdca_snd_controls,
...@@ -1207,7 +1210,6 @@ static const struct snd_soc_component_driver soc_sdca_dev_rt711 = { ...@@ -1207,7 +1210,6 @@ static const struct snd_soc_component_driver soc_sdca_dev_rt711 = {
.dapm_routes = rt711_sdca_audio_map, .dapm_routes = rt711_sdca_audio_map,
.num_dapm_routes = ARRAY_SIZE(rt711_sdca_audio_map), .num_dapm_routes = ARRAY_SIZE(rt711_sdca_audio_map),
.set_jack = rt711_sdca_set_jack_detect, .set_jack = rt711_sdca_set_jack_detect,
.remove = rt711_sdca_remove,
.endianness = 1, .endianness = 1,
}; };
...@@ -1412,8 +1414,12 @@ int rt711_sdca_init(struct device *dev, struct regmap *regmap, ...@@ -1412,8 +1414,12 @@ int rt711_sdca_init(struct device *dev, struct regmap *regmap,
rt711->regmap = regmap; rt711->regmap = regmap;
rt711->mbq_regmap = mbq_regmap; rt711->mbq_regmap = mbq_regmap;
mutex_init(&rt711->calibrate_mutex);
mutex_init(&rt711->disable_irq_lock); mutex_init(&rt711->disable_irq_lock);
INIT_DELAYED_WORK(&rt711->jack_detect_work, rt711_sdca_jack_detect_handler);
INIT_DELAYED_WORK(&rt711->jack_btn_check_work, rt711_sdca_btn_check_handler);
/* /*
* Mark hw_init to false * Mark hw_init to false
* HW init will be performed when device reports present * HW init will be performed when device reports present
...@@ -1545,14 +1551,6 @@ int rt711_sdca_io_init(struct device *dev, struct sdw_slave *slave) ...@@ -1545,14 +1551,6 @@ int rt711_sdca_io_init(struct device *dev, struct sdw_slave *slave)
rt711_sdca_index_update_bits(rt711, RT711_VENDOR_HDA_CTL, rt711_sdca_index_update_bits(rt711, RT711_VENDOR_HDA_CTL,
RT711_PUSH_BTN_INT_CTL0, 0x20, 0x00); RT711_PUSH_BTN_INT_CTL0, 0x20, 0x00);
if (!rt711->first_hw_init) {
INIT_DELAYED_WORK(&rt711->jack_detect_work,
rt711_sdca_jack_detect_handler);
INIT_DELAYED_WORK(&rt711->jack_btn_check_work,
rt711_sdca_btn_check_handler);
mutex_init(&rt711->calibrate_mutex);
}
/* calibration */ /* calibration */
ret = rt711_sdca_calibration(rt711); ret = rt711_sdca_calibration(rt711);
if (ret < 0) if (ret < 0)
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/soundwire/sdw_type.h> #include <linux/soundwire/sdw_type.h>
#include <linux/soundwire/sdw_registers.h> #include <linux/soundwire/sdw_registers.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <sound/soc.h> #include <sound/soc.h>
#include "rt711.h" #include "rt711.h"
...@@ -464,12 +465,18 @@ static int rt711_sdw_remove(struct sdw_slave *slave) ...@@ -464,12 +465,18 @@ static int rt711_sdw_remove(struct sdw_slave *slave)
{ {
struct rt711_priv *rt711 = dev_get_drvdata(&slave->dev); struct rt711_priv *rt711 = dev_get_drvdata(&slave->dev);
if (rt711 && rt711->hw_init) { if (rt711->hw_init) {
cancel_delayed_work_sync(&rt711->jack_detect_work); cancel_delayed_work_sync(&rt711->jack_detect_work);
cancel_delayed_work_sync(&rt711->jack_btn_check_work); cancel_delayed_work_sync(&rt711->jack_btn_check_work);
cancel_work_sync(&rt711->calibration_work); cancel_work_sync(&rt711->calibration_work);
} }
if (rt711->first_hw_init)
pm_runtime_disable(&slave->dev);
mutex_destroy(&rt711->calibrate_mutex);
mutex_destroy(&rt711->disable_irq_lock);
return 0; return 0;
} }
......
...@@ -242,7 +242,7 @@ static void rt711_jack_detect_handler(struct work_struct *work) ...@@ -242,7 +242,7 @@ static void rt711_jack_detect_handler(struct work_struct *work)
if (!rt711->hs_jack) if (!rt711->hs_jack)
return; return;
if (!rt711->component->card->instantiated) if (!rt711->component->card || !rt711->component->card->instantiated)
return; return;
if (pm_runtime_status_suspended(rt711->slave->dev.parent)) { if (pm_runtime_status_suspended(rt711->slave->dev.parent)) {
...@@ -457,17 +457,27 @@ static int rt711_set_jack_detect(struct snd_soc_component *component, ...@@ -457,17 +457,27 @@ static int rt711_set_jack_detect(struct snd_soc_component *component,
struct snd_soc_jack *hs_jack, void *data) struct snd_soc_jack *hs_jack, void *data)
{ {
struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component); struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
int ret;
rt711->hs_jack = hs_jack; rt711->hs_jack = hs_jack;
if (!rt711->hw_init) { ret = pm_runtime_resume_and_get(component->dev);
dev_dbg(&rt711->slave->dev, if (ret < 0) {
"%s hw_init not ready yet\n", __func__); if (ret != -EACCES) {
dev_err(component->dev, "%s: failed to resume %d\n", __func__, ret);
return ret;
}
/* pm_runtime not enabled yet */
dev_dbg(component->dev, "%s: skipping jack init for now\n", __func__);
return 0; return 0;
} }
rt711_jack_init(rt711); rt711_jack_init(rt711);
pm_runtime_mark_last_busy(component->dev);
pm_runtime_put_autosuspend(component->dev);
return 0; return 0;
} }
...@@ -932,13 +942,6 @@ static int rt711_probe(struct snd_soc_component *component) ...@@ -932,13 +942,6 @@ static int rt711_probe(struct snd_soc_component *component)
return 0; return 0;
} }
static void rt711_remove(struct snd_soc_component *component)
{
struct rt711_priv *rt711 = snd_soc_component_get_drvdata(component);
regcache_cache_only(rt711->regmap, true);
}
static const struct snd_soc_component_driver soc_codec_dev_rt711 = { static const struct snd_soc_component_driver soc_codec_dev_rt711 = {
.probe = rt711_probe, .probe = rt711_probe,
.set_bias_level = rt711_set_bias_level, .set_bias_level = rt711_set_bias_level,
...@@ -949,7 +952,6 @@ static const struct snd_soc_component_driver soc_codec_dev_rt711 = { ...@@ -949,7 +952,6 @@ static const struct snd_soc_component_driver soc_codec_dev_rt711 = {
.dapm_routes = rt711_audio_map, .dapm_routes = rt711_audio_map,
.num_dapm_routes = ARRAY_SIZE(rt711_audio_map), .num_dapm_routes = ARRAY_SIZE(rt711_audio_map),
.set_jack = rt711_set_jack_detect, .set_jack = rt711_set_jack_detect,
.remove = rt711_remove,
.endianness = 1, .endianness = 1,
}; };
...@@ -1204,8 +1206,13 @@ int rt711_init(struct device *dev, struct regmap *sdw_regmap, ...@@ -1204,8 +1206,13 @@ int rt711_init(struct device *dev, struct regmap *sdw_regmap,
rt711->sdw_regmap = sdw_regmap; rt711->sdw_regmap = sdw_regmap;
rt711->regmap = regmap; rt711->regmap = regmap;
mutex_init(&rt711->calibrate_mutex);
mutex_init(&rt711->disable_irq_lock); mutex_init(&rt711->disable_irq_lock);
INIT_DELAYED_WORK(&rt711->jack_detect_work, rt711_jack_detect_handler);
INIT_DELAYED_WORK(&rt711->jack_btn_check_work, rt711_btn_check_handler);
INIT_WORK(&rt711->calibration_work, rt711_calibration_work);
/* /*
* Mark hw_init to false * Mark hw_init to false
* HW init will be performed when device reports present * HW init will be performed when device reports present
...@@ -1313,15 +1320,8 @@ int rt711_io_init(struct device *dev, struct sdw_slave *slave) ...@@ -1313,15 +1320,8 @@ int rt711_io_init(struct device *dev, struct sdw_slave *slave)
if (rt711->first_hw_init) if (rt711->first_hw_init)
rt711_calibration(rt711); rt711_calibration(rt711);
else { else
INIT_DELAYED_WORK(&rt711->jack_detect_work,
rt711_jack_detect_handler);
INIT_DELAYED_WORK(&rt711->jack_btn_check_work,
rt711_btn_check_handler);
mutex_init(&rt711->calibrate_mutex);
INIT_WORK(&rt711->calibration_work, rt711_calibration_work);
schedule_work(&rt711->calibration_work); schedule_work(&rt711->calibration_work);
}
/* /*
* if set_jack callback occurred early than io_init, * if set_jack callback occurred early than io_init,
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/soundwire/sdw_type.h> #include <linux/soundwire/sdw_type.h>
#include <linux/soundwire/sdw_registers.h> #include <linux/soundwire/sdw_registers.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <sound/soc.h> #include <sound/soc.h>
#include "rt715-sdca.h" #include "rt715-sdca.h"
...@@ -193,6 +194,16 @@ static int rt715_sdca_sdw_probe(struct sdw_slave *slave, ...@@ -193,6 +194,16 @@ static int rt715_sdca_sdw_probe(struct sdw_slave *slave,
return rt715_sdca_init(&slave->dev, mbq_regmap, regmap, slave); return rt715_sdca_init(&slave->dev, mbq_regmap, regmap, slave);
} }
static int rt715_sdca_sdw_remove(struct sdw_slave *slave)
{
struct rt715_sdca_priv *rt715 = dev_get_drvdata(&slave->dev);
if (rt715->first_hw_init)
pm_runtime_disable(&slave->dev);
return 0;
}
static const struct sdw_device_id rt715_sdca_id[] = { static const struct sdw_device_id rt715_sdca_id[] = {
SDW_SLAVE_ENTRY_EXT(0x025d, 0x715, 0x3, 0x1, 0), SDW_SLAVE_ENTRY_EXT(0x025d, 0x715, 0x3, 0x1, 0),
SDW_SLAVE_ENTRY_EXT(0x025d, 0x714, 0x3, 0x1, 0), SDW_SLAVE_ENTRY_EXT(0x025d, 0x714, 0x3, 0x1, 0),
...@@ -267,6 +278,7 @@ static struct sdw_driver rt715_sdw_driver = { ...@@ -267,6 +278,7 @@ static struct sdw_driver rt715_sdw_driver = {
.pm = &rt715_pm, .pm = &rt715_pm,
}, },
.probe = rt715_sdca_sdw_probe, .probe = rt715_sdca_sdw_probe,
.remove = rt715_sdca_sdw_remove,
.ops = &rt715_sdca_slave_ops, .ops = &rt715_sdca_slave_ops,
.id_table = rt715_sdca_id, .id_table = rt715_sdca_id,
}; };
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/soundwire/sdw_type.h> #include <linux/soundwire/sdw_type.h>
#include <linux/soundwire/sdw_registers.h> #include <linux/soundwire/sdw_registers.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <sound/soc.h> #include <sound/soc.h>
...@@ -514,6 +515,16 @@ static int rt715_sdw_probe(struct sdw_slave *slave, ...@@ -514,6 +515,16 @@ static int rt715_sdw_probe(struct sdw_slave *slave,
return 0; return 0;
} }
static int rt715_sdw_remove(struct sdw_slave *slave)
{
struct rt715_priv *rt715 = dev_get_drvdata(&slave->dev);
if (rt715->first_hw_init)
pm_runtime_disable(&slave->dev);
return 0;
}
static const struct sdw_device_id rt715_id[] = { static const struct sdw_device_id rt715_id[] = {
SDW_SLAVE_ENTRY_EXT(0x025d, 0x714, 0x2, 0, 0), SDW_SLAVE_ENTRY_EXT(0x025d, 0x714, 0x2, 0, 0),
SDW_SLAVE_ENTRY_EXT(0x025d, 0x715, 0x2, 0, 0), SDW_SLAVE_ENTRY_EXT(0x025d, 0x715, 0x2, 0, 0),
...@@ -575,6 +586,7 @@ static struct sdw_driver rt715_sdw_driver = { ...@@ -575,6 +586,7 @@ static struct sdw_driver rt715_sdw_driver = {
.pm = &rt715_pm, .pm = &rt715_pm,
}, },
.probe = rt715_sdw_probe, .probe = rt715_sdw_probe,
.remove = rt715_sdw_remove,
.ops = &rt715_slave_ops, .ops = &rt715_slave_ops,
.id_table = rt715_id, .id_table = rt715_id,
}; };
......
...@@ -1287,11 +1287,17 @@ static int slim_rx_mux_put(struct snd_kcontrol *kc, ...@@ -1287,11 +1287,17 @@ static int slim_rx_mux_put(struct snd_kcontrol *kc,
struct snd_soc_dapm_update *update = NULL; struct snd_soc_dapm_update *update = NULL;
u32 port_id = w->shift; u32 port_id = w->shift;
if (wcd->rx_port_value[port_id] == ucontrol->value.enumerated.item[0])
return 0;
wcd->rx_port_value[port_id] = ucontrol->value.enumerated.item[0]; wcd->rx_port_value[port_id] = ucontrol->value.enumerated.item[0];
/* Remove channel from any list it's in before adding it to a new one */
list_del_init(&wcd->rx_chs[port_id].list);
switch (wcd->rx_port_value[port_id]) { switch (wcd->rx_port_value[port_id]) {
case 0: case 0:
list_del_init(&wcd->rx_chs[port_id].list); /* Channel already removed from lists. Nothing to do here */
break; break;
case 1: case 1:
list_add_tail(&wcd->rx_chs[port_id].list, list_add_tail(&wcd->rx_chs[port_id].list,
......
...@@ -2519,6 +2519,9 @@ static int wcd938x_tx_mode_put(struct snd_kcontrol *kcontrol, ...@@ -2519,6 +2519,9 @@ static int wcd938x_tx_mode_put(struct snd_kcontrol *kcontrol,
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
int path = e->shift_l; int path = e->shift_l;
if (wcd938x->tx_mode[path] == ucontrol->value.enumerated.item[0])
return 0;
wcd938x->tx_mode[path] = ucontrol->value.enumerated.item[0]; wcd938x->tx_mode[path] = ucontrol->value.enumerated.item[0];
return 1; return 1;
...@@ -2541,6 +2544,9 @@ static int wcd938x_rx_hph_mode_put(struct snd_kcontrol *kcontrol, ...@@ -2541,6 +2544,9 @@ static int wcd938x_rx_hph_mode_put(struct snd_kcontrol *kcontrol,
struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
if (wcd938x->hph_mode == ucontrol->value.enumerated.item[0])
return 0;
wcd938x->hph_mode = ucontrol->value.enumerated.item[0]; wcd938x->hph_mode = ucontrol->value.enumerated.item[0];
return 1; return 1;
...@@ -2632,6 +2638,9 @@ static int wcd938x_ldoh_put(struct snd_kcontrol *kcontrol, ...@@ -2632,6 +2638,9 @@ static int wcd938x_ldoh_put(struct snd_kcontrol *kcontrol,
struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
if (wcd938x->ldoh == ucontrol->value.integer.value[0])
return 0;
wcd938x->ldoh = ucontrol->value.integer.value[0]; wcd938x->ldoh = ucontrol->value.integer.value[0];
return 1; return 1;
...@@ -2654,6 +2663,9 @@ static int wcd938x_bcs_put(struct snd_kcontrol *kcontrol, ...@@ -2654,6 +2663,9 @@ static int wcd938x_bcs_put(struct snd_kcontrol *kcontrol,
struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component); struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
if (wcd938x->bcs_dis == ucontrol->value.integer.value[0])
return 0;
wcd938x->bcs_dis = ucontrol->value.integer.value[0]; wcd938x->bcs_dis = ucontrol->value.integer.value[0];
return 1; return 1;
......
...@@ -413,6 +413,7 @@ static int wm5110_put_dre(struct snd_kcontrol *kcontrol, ...@@ -413,6 +413,7 @@ static int wm5110_put_dre(struct snd_kcontrol *kcontrol,
unsigned int rnew = (!!ucontrol->value.integer.value[1]) << mc->rshift; unsigned int rnew = (!!ucontrol->value.integer.value[1]) << mc->rshift;
unsigned int lold, rold; unsigned int lold, rold;
unsigned int lena, rena; unsigned int lena, rena;
bool change = false;
int ret; int ret;
snd_soc_dapm_mutex_lock(dapm); snd_soc_dapm_mutex_lock(dapm);
...@@ -440,8 +441,8 @@ static int wm5110_put_dre(struct snd_kcontrol *kcontrol, ...@@ -440,8 +441,8 @@ static int wm5110_put_dre(struct snd_kcontrol *kcontrol,
goto err; goto err;
} }
ret = regmap_update_bits(arizona->regmap, ARIZONA_DRE_ENABLE, ret = regmap_update_bits_check(arizona->regmap, ARIZONA_DRE_ENABLE,
mask, lnew | rnew); mask, lnew | rnew, &change);
if (ret) { if (ret) {
dev_err(arizona->dev, "Failed to set DRE: %d\n", ret); dev_err(arizona->dev, "Failed to set DRE: %d\n", ret);
goto err; goto err;
...@@ -454,6 +455,9 @@ static int wm5110_put_dre(struct snd_kcontrol *kcontrol, ...@@ -454,6 +455,9 @@ static int wm5110_put_dre(struct snd_kcontrol *kcontrol,
if (!rnew && rold) if (!rnew && rold)
wm5110_clear_pga_volume(arizona, mc->rshift); wm5110_clear_pga_volume(arizona, mc->rshift);
if (change)
ret = 1;
err: err:
snd_soc_dapm_mutex_unlock(dapm); snd_soc_dapm_mutex_unlock(dapm);
......
...@@ -997,7 +997,7 @@ int wm_adsp2_preloader_put(struct snd_kcontrol *kcontrol, ...@@ -997,7 +997,7 @@ int wm_adsp2_preloader_put(struct snd_kcontrol *kcontrol,
snd_soc_dapm_sync(dapm); snd_soc_dapm_sync(dapm);
} }
return 0; return 1;
} }
EXPORT_SYMBOL_GPL(wm_adsp2_preloader_put); EXPORT_SYMBOL_GPL(wm_adsp2_preloader_put);
......
...@@ -128,10 +128,10 @@ struct avs_tplg_token_parser { ...@@ -128,10 +128,10 @@ struct avs_tplg_token_parser {
static int static int
avs_parse_uuid_token(struct snd_soc_component *comp, void *elem, void *object, u32 offset) avs_parse_uuid_token(struct snd_soc_component *comp, void *elem, void *object, u32 offset)
{ {
struct snd_soc_tplg_vendor_value_elem *tuple = elem; struct snd_soc_tplg_vendor_uuid_elem *tuple = elem;
guid_t *val = (guid_t *)((u8 *)object + offset); guid_t *val = (guid_t *)((u8 *)object + offset);
guid_copy((guid_t *)val, (const guid_t *)&tuple->value); guid_copy((guid_t *)val, (const guid_t *)&tuple->uuid);
return 0; return 0;
} }
......
...@@ -421,8 +421,17 @@ static int snd_byt_wm5102_mc_probe(struct platform_device *pdev) ...@@ -421,8 +421,17 @@ static int snd_byt_wm5102_mc_probe(struct platform_device *pdev)
priv->spkvdd_en_gpio = gpiod_get(codec_dev, "wlf,spkvdd-ena", GPIOD_OUT_LOW); priv->spkvdd_en_gpio = gpiod_get(codec_dev, "wlf,spkvdd-ena", GPIOD_OUT_LOW);
put_device(codec_dev); put_device(codec_dev);
if (IS_ERR(priv->spkvdd_en_gpio)) if (IS_ERR(priv->spkvdd_en_gpio)) {
return dev_err_probe(dev, PTR_ERR(priv->spkvdd_en_gpio), "getting spkvdd-GPIO\n"); ret = PTR_ERR(priv->spkvdd_en_gpio);
/*
* The spkvdd gpio-lookup is registered by: drivers/mfd/arizona-spi.c,
* so -ENOENT means that arizona-spi hasn't probed yet.
*/
if (ret == -ENOENT)
ret = -EPROBE_DEFER;
return dev_err_probe(dev, ret, "getting spkvdd-GPIO\n");
}
/* override platform name, if required */ /* override platform name, if required */
byt_wm5102_card.dev = dev; byt_wm5102_card.dev = dev;
......
...@@ -1398,6 +1398,33 @@ static struct snd_soc_card card_sof_sdw = { ...@@ -1398,6 +1398,33 @@ static struct snd_soc_card card_sof_sdw = {
.late_probe = sof_sdw_card_late_probe, .late_probe = sof_sdw_card_late_probe,
}; };
static void mc_dailink_exit_loop(struct snd_soc_card *card)
{
struct snd_soc_dai_link *link;
int ret;
int i, j;
for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) {
if (!codec_info_list[i].exit)
continue;
/*
* We don't need to call .exit function if there is no matched
* dai link found.
*/
for_each_card_prelinks(card, j, link) {
if (!strcmp(link->codecs[0].dai_name,
codec_info_list[i].dai_name)) {
ret = codec_info_list[i].exit(card, link);
if (ret)
dev_warn(card->dev,
"codec exit failed %d\n",
ret);
break;
}
}
}
}
static int mc_probe(struct platform_device *pdev) static int mc_probe(struct platform_device *pdev)
{ {
struct snd_soc_card *card = &card_sof_sdw; struct snd_soc_card *card = &card_sof_sdw;
...@@ -1462,6 +1489,7 @@ static int mc_probe(struct platform_device *pdev) ...@@ -1462,6 +1489,7 @@ static int mc_probe(struct platform_device *pdev)
ret = devm_snd_soc_register_card(&pdev->dev, card); ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret) { if (ret) {
dev_err(card->dev, "snd_soc_register_card failed %d\n", ret); dev_err(card->dev, "snd_soc_register_card failed %d\n", ret);
mc_dailink_exit_loop(card);
return ret; return ret;
} }
...@@ -1473,29 +1501,8 @@ static int mc_probe(struct platform_device *pdev) ...@@ -1473,29 +1501,8 @@ static int mc_probe(struct platform_device *pdev)
static int mc_remove(struct platform_device *pdev) static int mc_remove(struct platform_device *pdev)
{ {
struct snd_soc_card *card = platform_get_drvdata(pdev); struct snd_soc_card *card = platform_get_drvdata(pdev);
struct snd_soc_dai_link *link;
int ret;
int i, j;
for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) { mc_dailink_exit_loop(card);
if (!codec_info_list[i].exit)
continue;
/*
* We don't need to call .exit function if there is no matched
* dai link found.
*/
for_each_card_prelinks(card, j, link) {
if (!strcmp(link->codecs[0].dai_name,
codec_info_list[i].dai_name)) {
ret = codec_info_list[i].exit(card, link);
if (ret)
dev_warn(&pdev->dev,
"codec exit failed %d\n",
ret);
break;
}
}
}
return 0; return 0;
} }
......
...@@ -147,6 +147,12 @@ static int q6apm_dai_prepare(struct snd_soc_component *component, ...@@ -147,6 +147,12 @@ static int q6apm_dai_prepare(struct snd_soc_component *component,
cfg.num_channels = runtime->channels; cfg.num_channels = runtime->channels;
cfg.bit_width = prtd->bits_per_sample; cfg.bit_width = prtd->bits_per_sample;
if (prtd->state) {
/* clear the previous setup if any */
q6apm_graph_stop(prtd->graph);
q6apm_unmap_memory_regions(prtd->graph, substream->stream);
}
prtd->pcm_count = snd_pcm_lib_period_bytes(substream); prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
prtd->pos = 0; prtd->pos = 0;
/* rate and channels are sent to audio driver */ /* rate and channels are sent to audio driver */
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/pinctrl/consumer.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
...@@ -54,8 +55,40 @@ struct rk_i2s_dev { ...@@ -54,8 +55,40 @@ struct rk_i2s_dev {
const struct rk_i2s_pins *pins; const struct rk_i2s_pins *pins;
unsigned int bclk_ratio; unsigned int bclk_ratio;
spinlock_t lock; /* tx/rx lock */ spinlock_t lock; /* tx/rx lock */
struct pinctrl *pinctrl;
struct pinctrl_state *bclk_on;
struct pinctrl_state *bclk_off;
}; };
static int i2s_pinctrl_select_bclk_on(struct rk_i2s_dev *i2s)
{
int ret = 0;
if (!IS_ERR(i2s->pinctrl) && !IS_ERR_OR_NULL(i2s->bclk_on))
ret = pinctrl_select_state(i2s->pinctrl,
i2s->bclk_on);
if (ret)
dev_err(i2s->dev, "bclk enable failed %d\n", ret);
return ret;
}
static int i2s_pinctrl_select_bclk_off(struct rk_i2s_dev *i2s)
{
int ret = 0;
if (!IS_ERR(i2s->pinctrl) && !IS_ERR_OR_NULL(i2s->bclk_off))
ret = pinctrl_select_state(i2s->pinctrl,
i2s->bclk_off);
if (ret)
dev_err(i2s->dev, "bclk disable failed %d\n", ret);
return ret;
}
static int i2s_runtime_suspend(struct device *dev) static int i2s_runtime_suspend(struct device *dev)
{ {
struct rk_i2s_dev *i2s = dev_get_drvdata(dev); struct rk_i2s_dev *i2s = dev_get_drvdata(dev);
...@@ -92,38 +125,49 @@ static inline struct rk_i2s_dev *to_info(struct snd_soc_dai *dai) ...@@ -92,38 +125,49 @@ static inline struct rk_i2s_dev *to_info(struct snd_soc_dai *dai)
return snd_soc_dai_get_drvdata(dai); return snd_soc_dai_get_drvdata(dai);
} }
static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on) static int rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on)
{ {
unsigned int val = 0; unsigned int val = 0;
int retry = 10; int retry = 10;
int ret = 0;
spin_lock(&i2s->lock); spin_lock(&i2s->lock);
if (on) { if (on) {
regmap_update_bits(i2s->regmap, I2S_DMACR, ret = regmap_update_bits(i2s->regmap, I2S_DMACR,
I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_ENABLE); I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_ENABLE);
if (ret < 0)
goto end;
regmap_update_bits(i2s->regmap, I2S_XFER, ret = regmap_update_bits(i2s->regmap, I2S_XFER,
I2S_XFER_TXS_START | I2S_XFER_RXS_START, I2S_XFER_TXS_START | I2S_XFER_RXS_START,
I2S_XFER_TXS_START | I2S_XFER_RXS_START); I2S_XFER_TXS_START | I2S_XFER_RXS_START);
if (ret < 0)
goto end;
i2s->tx_start = true; i2s->tx_start = true;
} else { } else {
i2s->tx_start = false; i2s->tx_start = false;
regmap_update_bits(i2s->regmap, I2S_DMACR, ret = regmap_update_bits(i2s->regmap, I2S_DMACR,
I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_DISABLE); I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_DISABLE);
if (ret < 0)
goto end;
if (!i2s->rx_start) { if (!i2s->rx_start) {
regmap_update_bits(i2s->regmap, I2S_XFER, ret = regmap_update_bits(i2s->regmap, I2S_XFER,
I2S_XFER_TXS_START | I2S_XFER_TXS_START |
I2S_XFER_RXS_START, I2S_XFER_RXS_START,
I2S_XFER_TXS_STOP | I2S_XFER_TXS_STOP |
I2S_XFER_RXS_STOP); I2S_XFER_RXS_STOP);
if (ret < 0)
goto end;
udelay(150); udelay(150);
regmap_update_bits(i2s->regmap, I2S_CLR, ret = regmap_update_bits(i2s->regmap, I2S_CLR,
I2S_CLR_TXC | I2S_CLR_RXC, I2S_CLR_TXC | I2S_CLR_RXC,
I2S_CLR_TXC | I2S_CLR_RXC); I2S_CLR_TXC | I2S_CLR_RXC);
if (ret < 0)
goto end;
regmap_read(i2s->regmap, I2S_CLR, &val); regmap_read(i2s->regmap, I2S_CLR, &val);
...@@ -138,44 +182,57 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on) ...@@ -138,44 +182,57 @@ static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on)
} }
} }
} }
end:
spin_unlock(&i2s->lock); spin_unlock(&i2s->lock);
if (ret < 0)
dev_err(i2s->dev, "lrclk update failed\n");
return ret;
} }
static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on) static int rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on)
{ {
unsigned int val = 0; unsigned int val = 0;
int retry = 10; int retry = 10;
int ret = 0;
spin_lock(&i2s->lock); spin_lock(&i2s->lock);
if (on) { if (on) {
regmap_update_bits(i2s->regmap, I2S_DMACR, ret = regmap_update_bits(i2s->regmap, I2S_DMACR,
I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_ENABLE); I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_ENABLE);
if (ret < 0)
goto end;
regmap_update_bits(i2s->regmap, I2S_XFER, ret = regmap_update_bits(i2s->regmap, I2S_XFER,
I2S_XFER_TXS_START | I2S_XFER_RXS_START, I2S_XFER_TXS_START | I2S_XFER_RXS_START,
I2S_XFER_TXS_START | I2S_XFER_RXS_START); I2S_XFER_TXS_START | I2S_XFER_RXS_START);
if (ret < 0)
goto end;
i2s->rx_start = true; i2s->rx_start = true;
} else { } else {
i2s->rx_start = false; i2s->rx_start = false;
regmap_update_bits(i2s->regmap, I2S_DMACR, ret = regmap_update_bits(i2s->regmap, I2S_DMACR,
I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_DISABLE); I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_DISABLE);
if (ret < 0)
goto end;
if (!i2s->tx_start) { if (!i2s->tx_start) {
regmap_update_bits(i2s->regmap, I2S_XFER, ret = regmap_update_bits(i2s->regmap, I2S_XFER,
I2S_XFER_TXS_START | I2S_XFER_TXS_START |
I2S_XFER_RXS_START, I2S_XFER_RXS_START,
I2S_XFER_TXS_STOP | I2S_XFER_TXS_STOP |
I2S_XFER_RXS_STOP); I2S_XFER_RXS_STOP);
if (ret < 0)
goto end;
udelay(150); udelay(150);
regmap_update_bits(i2s->regmap, I2S_CLR, ret = regmap_update_bits(i2s->regmap, I2S_CLR,
I2S_CLR_TXC | I2S_CLR_RXC, I2S_CLR_TXC | I2S_CLR_RXC,
I2S_CLR_TXC | I2S_CLR_RXC); I2S_CLR_TXC | I2S_CLR_RXC);
if (ret < 0)
goto end;
regmap_read(i2s->regmap, I2S_CLR, &val); regmap_read(i2s->regmap, I2S_CLR, &val);
/* Should wait for clear operation to finish */ /* Should wait for clear operation to finish */
while (val) { while (val) {
regmap_read(i2s->regmap, I2S_CLR, &val); regmap_read(i2s->regmap, I2S_CLR, &val);
...@@ -187,7 +244,12 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on) ...@@ -187,7 +244,12 @@ static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on)
} }
} }
} }
end:
spin_unlock(&i2s->lock); spin_unlock(&i2s->lock);
if (ret < 0)
dev_err(i2s->dev, "lrclk update failed\n");
return ret;
} }
static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai, static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
...@@ -425,17 +487,26 @@ static int rockchip_i2s_trigger(struct snd_pcm_substream *substream, ...@@ -425,17 +487,26 @@ static int rockchip_i2s_trigger(struct snd_pcm_substream *substream,
case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
rockchip_snd_rxctrl(i2s, 1); ret = rockchip_snd_rxctrl(i2s, 1);
else else
rockchip_snd_txctrl(i2s, 1); ret = rockchip_snd_txctrl(i2s, 1);
/* Do not turn on bclk if lrclk open fails. */
if (ret < 0)
return ret;
i2s_pinctrl_select_bclk_on(i2s);
break; break;
case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH: case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
rockchip_snd_rxctrl(i2s, 0); if (!i2s->tx_start)
else i2s_pinctrl_select_bclk_off(i2s);
rockchip_snd_txctrl(i2s, 0); ret = rockchip_snd_rxctrl(i2s, 0);
} else {
if (!i2s->rx_start)
i2s_pinctrl_select_bclk_off(i2s);
ret = rockchip_snd_txctrl(i2s, 0);
}
break; break;
default: default:
ret = -EINVAL; ret = -EINVAL;
...@@ -736,6 +807,33 @@ static int rockchip_i2s_probe(struct platform_device *pdev) ...@@ -736,6 +807,33 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
} }
i2s->bclk_ratio = 64; i2s->bclk_ratio = 64;
i2s->pinctrl = devm_pinctrl_get(&pdev->dev);
if (IS_ERR(i2s->pinctrl))
dev_err(&pdev->dev, "failed to find i2s pinctrl\n");
i2s->bclk_on = pinctrl_lookup_state(i2s->pinctrl,
"bclk_on");
if (IS_ERR_OR_NULL(i2s->bclk_on))
dev_err(&pdev->dev, "failed to find i2s default state\n");
else
dev_dbg(&pdev->dev, "find i2s bclk state\n");
i2s->bclk_off = pinctrl_lookup_state(i2s->pinctrl,
"bclk_off");
if (IS_ERR_OR_NULL(i2s->bclk_off))
dev_err(&pdev->dev, "failed to find i2s gpio state\n");
else
dev_dbg(&pdev->dev, "find i2s bclk_off state\n");
i2s_pinctrl_select_bclk_off(i2s);
i2s->playback_dma_data.addr = res->start + I2S_TXDR;
i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
i2s->playback_dma_data.maxburst = 4;
i2s->capture_dma_data.addr = res->start + I2S_RXDR;
i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
i2s->capture_dma_data.maxburst = 4;
dev_set_drvdata(&pdev->dev, i2s); dev_set_drvdata(&pdev->dev, i2s);
......
...@@ -62,6 +62,8 @@ struct snd_soc_dapm_widget * ...@@ -62,6 +62,8 @@ struct snd_soc_dapm_widget *
snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm, snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm,
const struct snd_soc_dapm_widget *widget); const struct snd_soc_dapm_widget *widget);
static unsigned int soc_dapm_read(struct snd_soc_dapm_context *dapm, int reg);
/* dapm power sequences - make this per codec in the future */ /* dapm power sequences - make this per codec in the future */
static int dapm_up_seq[] = { static int dapm_up_seq[] = {
[snd_soc_dapm_pre] = 1, [snd_soc_dapm_pre] = 1,
...@@ -442,6 +444,9 @@ static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget, ...@@ -442,6 +444,9 @@ static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget,
snd_soc_dapm_add_path(widget->dapm, data->widget, snd_soc_dapm_add_path(widget->dapm, data->widget,
widget, NULL, NULL); widget, NULL, NULL);
} else if (e->reg != SND_SOC_NOPM) {
data->value = soc_dapm_read(widget->dapm, e->reg) &
(e->mask << e->shift_l);
} }
break; break;
default: default:
......
...@@ -526,7 +526,7 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, ...@@ -526,7 +526,7 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol,
return -EINVAL; return -EINVAL;
if (mc->platform_max && tmp > mc->platform_max) if (mc->platform_max && tmp > mc->platform_max)
return -EINVAL; return -EINVAL;
if (tmp > mc->max - mc->min + 1) if (tmp > mc->max - mc->min)
return -EINVAL; return -EINVAL;
if (invert) if (invert)
...@@ -547,7 +547,7 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, ...@@ -547,7 +547,7 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol,
return -EINVAL; return -EINVAL;
if (mc->platform_max && tmp > mc->platform_max) if (mc->platform_max && tmp > mc->platform_max)
return -EINVAL; return -EINVAL;
if (tmp > mc->max - mc->min + 1) if (tmp > mc->max - mc->min)
return -EINVAL; return -EINVAL;
if (invert) if (invert)
......
...@@ -181,12 +181,20 @@ int hda_dsp_core_run(struct snd_sof_dev *sdev, unsigned int core_mask) ...@@ -181,12 +181,20 @@ int hda_dsp_core_run(struct snd_sof_dev *sdev, unsigned int core_mask)
* Power Management. * Power Management.
*/ */
static int hda_dsp_core_power_up(struct snd_sof_dev *sdev, unsigned int core_mask) int hda_dsp_core_power_up(struct snd_sof_dev *sdev, unsigned int core_mask)
{ {
struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
const struct sof_intel_dsp_desc *chip = hda->desc;
unsigned int cpa; unsigned int cpa;
u32 adspcs; u32 adspcs;
int ret; int ret;
/* restrict core_mask to host managed cores mask */
core_mask &= chip->host_managed_cores_mask;
/* return if core_mask is not valid */
if (!core_mask)
return 0;
/* update bits */ /* update bits */
snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPCS, snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPCS,
HDA_DSP_ADSPCS_SPA_MASK(core_mask), HDA_DSP_ADSPCS_SPA_MASK(core_mask),
......
...@@ -95,9 +95,9 @@ struct hdac_ext_stream *hda_cl_stream_prepare(struct snd_sof_dev *sdev, unsigned ...@@ -95,9 +95,9 @@ struct hdac_ext_stream *hda_cl_stream_prepare(struct snd_sof_dev *sdev, unsigned
} }
/* /*
* first boot sequence has some extra steps. core 0 waits for power * first boot sequence has some extra steps.
* status on core 1, so power up core 1 also momentarily, keep it in * power on all host managed cores and only unstall/run the boot core to boot the
* reset/stall and then turn it off * DSP then turn off all non boot cores (if any) is powered on.
*/ */
static int cl_dsp_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot) static int cl_dsp_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot)
{ {
...@@ -110,7 +110,7 @@ static int cl_dsp_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot) ...@@ -110,7 +110,7 @@ static int cl_dsp_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot)
int ret; int ret;
/* step 1: power up corex */ /* step 1: power up corex */
ret = hda_dsp_enable_core(sdev, chip->host_managed_cores_mask); ret = hda_dsp_core_power_up(sdev, chip->host_managed_cores_mask);
if (ret < 0) { if (ret < 0) {
if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS) if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS)
dev_err(sdev->dev, "error: dsp core 0/1 power up failed\n"); dev_err(sdev->dev, "error: dsp core 0/1 power up failed\n");
...@@ -127,7 +127,7 @@ static int cl_dsp_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot) ...@@ -127,7 +127,7 @@ static int cl_dsp_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot)
snd_sof_dsp_write(sdev, HDA_DSP_BAR, chip->ipc_req, ipc_hdr); snd_sof_dsp_write(sdev, HDA_DSP_BAR, chip->ipc_req, ipc_hdr);
/* step 3: unset core 0 reset state & unstall/run core 0 */ /* step 3: unset core 0 reset state & unstall/run core 0 */
ret = hda_dsp_core_run(sdev, BIT(0)); ret = hda_dsp_core_run(sdev, chip->init_core_mask);
if (ret < 0) { if (ret < 0) {
if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS) if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS)
dev_err(sdev->dev, dev_err(sdev->dev,
...@@ -389,7 +389,8 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev) ...@@ -389,7 +389,8 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev)
struct snd_dma_buffer dmab; struct snd_dma_buffer dmab;
int ret, ret1, i; int ret, ret1, i;
if (hda->imrboot_supported && !sdev->first_boot) { if (sdev->system_suspend_target < SOF_SUSPEND_S4 &&
hda->imrboot_supported && !sdev->first_boot) {
dev_dbg(sdev->dev, "IMR restore supported, booting from IMR directly\n"); dev_dbg(sdev->dev, "IMR restore supported, booting from IMR directly\n");
hda->boot_iteration = 0; hda->boot_iteration = 0;
ret = hda_dsp_boot_imr(sdev); ret = hda_dsp_boot_imr(sdev);
......
...@@ -192,79 +192,7 @@ snd_pcm_uframes_t hda_dsp_pcm_pointer(struct snd_sof_dev *sdev, ...@@ -192,79 +192,7 @@ snd_pcm_uframes_t hda_dsp_pcm_pointer(struct snd_sof_dev *sdev,
goto found; goto found;
} }
switch (sof_hda_position_quirk) { pos = hda_dsp_stream_get_position(hstream, substream->stream, true);
case SOF_HDA_POSITION_QUIRK_USE_SKYLAKE_LEGACY:
/*
* This legacy code, inherited from the Skylake driver,
* mixes DPIB registers and DPIB DDR updates and
* does not seem to follow any known hardware recommendations.
* It's not clear e.g. why there is a different flow
* for capture and playback, the only information that matters is
* what traffic class is used, and on all SOF-enabled platforms
* only VC0 is supported so the work-around was likely not necessary
* and quite possibly wrong.
*/
/* DPIB/posbuf position mode:
* For Playback, Use DPIB register from HDA space which
* reflects the actual data transferred.
* For Capture, Use the position buffer for pointer, as DPIB
* is not accurate enough, its update may be completed
* earlier than the data written to DDR.
*/
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
pos = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR,
AZX_REG_VS_SDXDPIB_XBASE +
(AZX_REG_VS_SDXDPIB_XINTERVAL *
hstream->index));
} else {
/*
* For capture stream, we need more workaround to fix the
* position incorrect issue:
*
* 1. Wait at least 20us before reading position buffer after
* the interrupt generated(IOC), to make sure position update
* happens on frame boundary i.e. 20.833uSec for 48KHz.
* 2. Perform a dummy Read to DPIB register to flush DMA
* position value.
* 3. Read the DMA Position from posbuf. Now the readback
* value should be >= period boundary.
*/
usleep_range(20, 21);
snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR,
AZX_REG_VS_SDXDPIB_XBASE +
(AZX_REG_VS_SDXDPIB_XINTERVAL *
hstream->index));
pos = snd_hdac_stream_get_pos_posbuf(hstream);
}
break;
case SOF_HDA_POSITION_QUIRK_USE_DPIB_REGISTERS:
/*
* In case VC1 traffic is disabled this is the recommended option
*/
pos = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR,
AZX_REG_VS_SDXDPIB_XBASE +
(AZX_REG_VS_SDXDPIB_XINTERVAL *
hstream->index));
break;
case SOF_HDA_POSITION_QUIRK_USE_DPIB_DDR_UPDATE:
/*
* This is the recommended option when VC1 is enabled.
* While this isn't needed for SOF platforms it's added for
* consistency and debug.
*/
pos = snd_hdac_stream_get_pos_posbuf(hstream);
break;
default:
dev_err_once(sdev->dev, "hda_position_quirk value %d not supported\n",
sof_hda_position_quirk);
pos = 0;
break;
}
if (pos >= hstream->bufsize)
pos = 0;
found: found:
pos = bytes_to_frames(substream->runtime, pos); pos = bytes_to_frames(substream->runtime, pos);
......
...@@ -707,12 +707,13 @@ bool hda_dsp_check_stream_irq(struct snd_sof_dev *sdev) ...@@ -707,12 +707,13 @@ bool hda_dsp_check_stream_irq(struct snd_sof_dev *sdev)
} }
static void static void
hda_dsp_set_bytes_transferred(struct hdac_stream *hstream, u64 buffer_size) hda_dsp_compr_bytes_transferred(struct hdac_stream *hstream, int direction)
{ {
u64 buffer_size = hstream->bufsize;
u64 prev_pos, pos, num_bytes; u64 prev_pos, pos, num_bytes;
div64_u64_rem(hstream->curr_pos, buffer_size, &prev_pos); div64_u64_rem(hstream->curr_pos, buffer_size, &prev_pos);
pos = snd_hdac_stream_get_pos_posbuf(hstream); pos = hda_dsp_stream_get_position(hstream, direction, false);
if (pos < prev_pos) if (pos < prev_pos)
num_bytes = (buffer_size - prev_pos) + pos; num_bytes = (buffer_size - prev_pos) + pos;
...@@ -748,8 +749,7 @@ static bool hda_dsp_stream_check(struct hdac_bus *bus, u32 status) ...@@ -748,8 +749,7 @@ static bool hda_dsp_stream_check(struct hdac_bus *bus, u32 status)
if (s->substream && sof_hda->no_ipc_position) { if (s->substream && sof_hda->no_ipc_position) {
snd_sof_pcm_period_elapsed(s->substream); snd_sof_pcm_period_elapsed(s->substream);
} else if (s->cstream) { } else if (s->cstream) {
hda_dsp_set_bytes_transferred(s, hda_dsp_compr_bytes_transferred(s, s->cstream->direction);
s->cstream->runtime->buffer_size);
snd_compr_fragment_elapsed(s->cstream); snd_compr_fragment_elapsed(s->cstream);
} }
} }
...@@ -1009,3 +1009,89 @@ void hda_dsp_stream_free(struct snd_sof_dev *sdev) ...@@ -1009,3 +1009,89 @@ void hda_dsp_stream_free(struct snd_sof_dev *sdev)
devm_kfree(sdev->dev, hda_stream); devm_kfree(sdev->dev, hda_stream);
} }
} }
snd_pcm_uframes_t hda_dsp_stream_get_position(struct hdac_stream *hstream,
int direction, bool can_sleep)
{
struct hdac_ext_stream *hext_stream = stream_to_hdac_ext_stream(hstream);
struct sof_intel_hda_stream *hda_stream = hstream_to_sof_hda_stream(hext_stream);
struct snd_sof_dev *sdev = hda_stream->sdev;
snd_pcm_uframes_t pos;
switch (sof_hda_position_quirk) {
case SOF_HDA_POSITION_QUIRK_USE_SKYLAKE_LEGACY:
/*
* This legacy code, inherited from the Skylake driver,
* mixes DPIB registers and DPIB DDR updates and
* does not seem to follow any known hardware recommendations.
* It's not clear e.g. why there is a different flow
* for capture and playback, the only information that matters is
* what traffic class is used, and on all SOF-enabled platforms
* only VC0 is supported so the work-around was likely not necessary
* and quite possibly wrong.
*/
/* DPIB/posbuf position mode:
* For Playback, Use DPIB register from HDA space which
* reflects the actual data transferred.
* For Capture, Use the position buffer for pointer, as DPIB
* is not accurate enough, its update may be completed
* earlier than the data written to DDR.
*/
if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
pos = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR,
AZX_REG_VS_SDXDPIB_XBASE +
(AZX_REG_VS_SDXDPIB_XINTERVAL *
hstream->index));
} else {
/*
* For capture stream, we need more workaround to fix the
* position incorrect issue:
*
* 1. Wait at least 20us before reading position buffer after
* the interrupt generated(IOC), to make sure position update
* happens on frame boundary i.e. 20.833uSec for 48KHz.
* 2. Perform a dummy Read to DPIB register to flush DMA
* position value.
* 3. Read the DMA Position from posbuf. Now the readback
* value should be >= period boundary.
*/
if (can_sleep)
usleep_range(20, 21);
snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR,
AZX_REG_VS_SDXDPIB_XBASE +
(AZX_REG_VS_SDXDPIB_XINTERVAL *
hstream->index));
pos = snd_hdac_stream_get_pos_posbuf(hstream);
}
break;
case SOF_HDA_POSITION_QUIRK_USE_DPIB_REGISTERS:
/*
* In case VC1 traffic is disabled this is the recommended option
*/
pos = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR,
AZX_REG_VS_SDXDPIB_XBASE +
(AZX_REG_VS_SDXDPIB_XINTERVAL *
hstream->index));
break;
case SOF_HDA_POSITION_QUIRK_USE_DPIB_DDR_UPDATE:
/*
* This is the recommended option when VC1 is enabled.
* While this isn't needed for SOF platforms it's added for
* consistency and debug.
*/
pos = snd_hdac_stream_get_pos_posbuf(hstream);
break;
default:
dev_err_once(sdev->dev, "hda_position_quirk value %d not supported\n",
sof_hda_position_quirk);
pos = 0;
break;
}
if (pos >= hstream->bufsize)
pos = 0;
return pos;
}
...@@ -497,6 +497,7 @@ struct sof_intel_hda_stream { ...@@ -497,6 +497,7 @@ struct sof_intel_hda_stream {
*/ */
int hda_dsp_probe(struct snd_sof_dev *sdev); int hda_dsp_probe(struct snd_sof_dev *sdev);
int hda_dsp_remove(struct snd_sof_dev *sdev); int hda_dsp_remove(struct snd_sof_dev *sdev);
int hda_dsp_core_power_up(struct snd_sof_dev *sdev, unsigned int core_mask);
int hda_dsp_core_run(struct snd_sof_dev *sdev, unsigned int core_mask); int hda_dsp_core_run(struct snd_sof_dev *sdev, unsigned int core_mask);
int hda_dsp_enable_core(struct snd_sof_dev *sdev, unsigned int core_mask); int hda_dsp_enable_core(struct snd_sof_dev *sdev, unsigned int core_mask);
int hda_dsp_core_reset_power_down(struct snd_sof_dev *sdev, int hda_dsp_core_reset_power_down(struct snd_sof_dev *sdev,
...@@ -564,6 +565,9 @@ int hda_dsp_stream_setup_bdl(struct snd_sof_dev *sdev, ...@@ -564,6 +565,9 @@ int hda_dsp_stream_setup_bdl(struct snd_sof_dev *sdev,
bool hda_dsp_check_ipc_irq(struct snd_sof_dev *sdev); bool hda_dsp_check_ipc_irq(struct snd_sof_dev *sdev);
bool hda_dsp_check_stream_irq(struct snd_sof_dev *sdev); bool hda_dsp_check_stream_irq(struct snd_sof_dev *sdev);
snd_pcm_uframes_t hda_dsp_stream_get_position(struct hdac_stream *hstream,
int direction, bool can_sleep);
struct hdac_ext_stream * struct hdac_ext_stream *
hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction, u32 flags); hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction, u32 flags);
int hda_dsp_stream_put(struct snd_sof_dev *sdev, int direction, int stream_tag); int hda_dsp_stream_put(struct snd_sof_dev *sdev, int direction, int stream_tag);
......
...@@ -1577,24 +1577,23 @@ static int sof_ipc3_control_load_bytes(struct snd_sof_dev *sdev, struct snd_sof_ ...@@ -1577,24 +1577,23 @@ static int sof_ipc3_control_load_bytes(struct snd_sof_dev *sdev, struct snd_sof_
struct sof_ipc_ctrl_data *cdata; struct sof_ipc_ctrl_data *cdata;
int ret; int ret;
scontrol->ipc_control_data = kzalloc(scontrol->max_size, GFP_KERNEL); if (scontrol->max_size < (sizeof(*cdata) + sizeof(struct sof_abi_hdr))) {
if (!scontrol->ipc_control_data) dev_err(sdev->dev, "%s: insufficient size for a bytes control: %zu.\n",
return -ENOMEM; __func__, scontrol->max_size);
return -EINVAL;
if (scontrol->max_size < sizeof(*cdata) ||
scontrol->max_size < sizeof(struct sof_abi_hdr)) {
ret = -EINVAL;
goto err;
} }
/* init the get/put bytes data */
if (scontrol->priv_size > scontrol->max_size - sizeof(*cdata)) { if (scontrol->priv_size > scontrol->max_size - sizeof(*cdata)) {
dev_err(sdev->dev, "err: bytes data size %zu exceeds max %zu.\n", dev_err(sdev->dev,
"%s: bytes data size %zu exceeds max %zu.\n", __func__,
scontrol->priv_size, scontrol->max_size - sizeof(*cdata)); scontrol->priv_size, scontrol->max_size - sizeof(*cdata));
ret = -EINVAL; return -EINVAL;
goto err;
} }
scontrol->ipc_control_data = kzalloc(scontrol->max_size, GFP_KERNEL);
if (!scontrol->ipc_control_data)
return -ENOMEM;
scontrol->size = sizeof(struct sof_ipc_ctrl_data) + scontrol->priv_size; scontrol->size = sizeof(struct sof_ipc_ctrl_data) + scontrol->priv_size;
cdata = scontrol->ipc_control_data; cdata = scontrol->ipc_control_data;
......
...@@ -392,7 +392,7 @@ static int mt8186_dsp_probe(struct snd_sof_dev *sdev) ...@@ -392,7 +392,7 @@ static int mt8186_dsp_probe(struct snd_sof_dev *sdev)
PLATFORM_DEVID_NONE, PLATFORM_DEVID_NONE,
pdev, sizeof(*pdev)); pdev, sizeof(*pdev));
if (IS_ERR(priv->ipc_dev)) { if (IS_ERR(priv->ipc_dev)) {
ret = IS_ERR(priv->ipc_dev); ret = PTR_ERR(priv->ipc_dev);
dev_err(sdev->dev, "failed to create mtk-adsp-ipc device\n"); dev_err(sdev->dev, "failed to create mtk-adsp-ipc device\n");
goto err_adsp_off; goto err_adsp_off;
} }
......
...@@ -23,6 +23,9 @@ static u32 snd_sof_dsp_power_target(struct snd_sof_dev *sdev) ...@@ -23,6 +23,9 @@ static u32 snd_sof_dsp_power_target(struct snd_sof_dev *sdev)
u32 target_dsp_state; u32 target_dsp_state;
switch (sdev->system_suspend_target) { switch (sdev->system_suspend_target) {
case SOF_SUSPEND_S5:
case SOF_SUSPEND_S4:
/* DSP should be in D3 if the system is suspending to S3+ */
case SOF_SUSPEND_S3: case SOF_SUSPEND_S3:
/* DSP should be in D3 if the system is suspending to S3 */ /* DSP should be in D3 if the system is suspending to S3 */
target_dsp_state = SOF_DSP_PM_D3; target_dsp_state = SOF_DSP_PM_D3;
...@@ -335,8 +338,24 @@ int snd_sof_prepare(struct device *dev) ...@@ -335,8 +338,24 @@ int snd_sof_prepare(struct device *dev)
return 0; return 0;
#if defined(CONFIG_ACPI) #if defined(CONFIG_ACPI)
if (acpi_target_system_state() == ACPI_STATE_S0) switch (acpi_target_system_state()) {
case ACPI_STATE_S0:
sdev->system_suspend_target = SOF_SUSPEND_S0IX; sdev->system_suspend_target = SOF_SUSPEND_S0IX;
break;
case ACPI_STATE_S1:
case ACPI_STATE_S2:
case ACPI_STATE_S3:
sdev->system_suspend_target = SOF_SUSPEND_S3;
break;
case ACPI_STATE_S4:
sdev->system_suspend_target = SOF_SUSPEND_S4;
break;
case ACPI_STATE_S5:
sdev->system_suspend_target = SOF_SUSPEND_S5;
break;
default:
break;
}
#endif #endif
return 0; return 0;
......
...@@ -85,6 +85,8 @@ enum sof_system_suspend_state { ...@@ -85,6 +85,8 @@ enum sof_system_suspend_state {
SOF_SUSPEND_NONE = 0, SOF_SUSPEND_NONE = 0,
SOF_SUSPEND_S0IX, SOF_SUSPEND_S0IX,
SOF_SUSPEND_S3, SOF_SUSPEND_S3,
SOF_SUSPEND_S4,
SOF_SUSPEND_S5,
}; };
enum sof_dfsentry_type { enum sof_dfsentry_type {
......
...@@ -3802,6 +3802,54 @@ YAMAHA_DEVICE(0x7010, "UB99"), ...@@ -3802,6 +3802,54 @@ YAMAHA_DEVICE(0x7010, "UB99"),
} }
}, },
/*
* MacroSilicon MS2100/MS2106 based AV capture cards
*
* These claim 96kHz 1ch in the descriptors, but are actually 48kHz 2ch.
* They also need QUIRK_FLAG_ALIGN_TRANSFER, which makes one wonder if
* they pretend to be 96kHz mono as a workaround for stereo being broken
* by that...
*
* They also have an issue with initial stream alignment that causes the
* channels to be swapped and out of phase, which is dealt with in quirks.c.
*/
{
USB_AUDIO_DEVICE(0x534d, 0x0021),
.driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
.vendor_name = "MacroSilicon",
.product_name = "MS210x",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_COMPOSITE,
.data = &(const struct snd_usb_audio_quirk[]) {
{
.ifnum = 2,
.type = QUIRK_AUDIO_STANDARD_MIXER,
},
{
.ifnum = 3,
.type = QUIRK_AUDIO_FIXED_ENDPOINT,
.data = &(const struct audioformat) {
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.channels = 2,
.iface = 3,
.altsetting = 1,
.altset_idx = 1,
.attributes = 0,
.endpoint = 0x82,
.ep_attr = USB_ENDPOINT_XFER_ISOC |
USB_ENDPOINT_SYNC_ASYNC,
.rates = SNDRV_PCM_RATE_CONTINUOUS,
.rate_min = 48000,
.rate_max = 48000,
}
},
{
.ifnum = -1
}
}
}
},
/* /*
* MacroSilicon MS2109 based HDMI capture cards * MacroSilicon MS2109 based HDMI capture cards
* *
...@@ -4119,6 +4167,206 @@ YAMAHA_DEVICE(0x7010, "UB99"), ...@@ -4119,6 +4167,206 @@ YAMAHA_DEVICE(0x7010, "UB99"),
} }
} }
}, },
{
/*
* Fiero SC-01 (firmware v1.0.0 @ 48 kHz)
*/
USB_DEVICE(0x2b53, 0x0023),
.driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
.vendor_name = "Fiero",
.product_name = "SC-01",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_COMPOSITE,
.data = &(const struct snd_usb_audio_quirk[]) {
{
.ifnum = 0,
.type = QUIRK_AUDIO_STANDARD_INTERFACE
},
/* Playback */
{
.ifnum = 1,
.type = QUIRK_AUDIO_FIXED_ENDPOINT,
.data = &(const struct audioformat) {
.formats = SNDRV_PCM_FMTBIT_S32_LE,
.channels = 2,
.fmt_bits = 24,
.iface = 1,
.altsetting = 1,
.altset_idx = 1,
.endpoint = 0x01,
.ep_attr = USB_ENDPOINT_XFER_ISOC |
USB_ENDPOINT_SYNC_ASYNC,
.rates = SNDRV_PCM_RATE_48000,
.rate_min = 48000,
.rate_max = 48000,
.nr_rates = 1,
.rate_table = (unsigned int[]) { 48000 },
.clock = 0x29
}
},
/* Capture */
{
.ifnum = 2,
.type = QUIRK_AUDIO_FIXED_ENDPOINT,
.data = &(const struct audioformat) {
.formats = SNDRV_PCM_FMTBIT_S32_LE,
.channels = 2,
.fmt_bits = 24,
.iface = 2,
.altsetting = 1,
.altset_idx = 1,
.endpoint = 0x82,
.ep_attr = USB_ENDPOINT_XFER_ISOC |
USB_ENDPOINT_SYNC_ASYNC |
USB_ENDPOINT_USAGE_IMPLICIT_FB,
.rates = SNDRV_PCM_RATE_48000,
.rate_min = 48000,
.rate_max = 48000,
.nr_rates = 1,
.rate_table = (unsigned int[]) { 48000 },
.clock = 0x29
}
},
{
.ifnum = -1
}
}
}
},
{
/*
* Fiero SC-01 (firmware v1.0.0 @ 96 kHz)
*/
USB_DEVICE(0x2b53, 0x0024),
.driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
.vendor_name = "Fiero",
.product_name = "SC-01",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_COMPOSITE,
.data = &(const struct snd_usb_audio_quirk[]) {
{
.ifnum = 0,
.type = QUIRK_AUDIO_STANDARD_INTERFACE
},
/* Playback */
{
.ifnum = 1,
.type = QUIRK_AUDIO_FIXED_ENDPOINT,
.data = &(const struct audioformat) {
.formats = SNDRV_PCM_FMTBIT_S32_LE,
.channels = 2,
.fmt_bits = 24,
.iface = 1,
.altsetting = 1,
.altset_idx = 1,
.endpoint = 0x01,
.ep_attr = USB_ENDPOINT_XFER_ISOC |
USB_ENDPOINT_SYNC_ASYNC,
.rates = SNDRV_PCM_RATE_96000,
.rate_min = 96000,
.rate_max = 96000,
.nr_rates = 1,
.rate_table = (unsigned int[]) { 96000 },
.clock = 0x29
}
},
/* Capture */
{
.ifnum = 2,
.type = QUIRK_AUDIO_FIXED_ENDPOINT,
.data = &(const struct audioformat) {
.formats = SNDRV_PCM_FMTBIT_S32_LE,
.channels = 2,
.fmt_bits = 24,
.iface = 2,
.altsetting = 1,
.altset_idx = 1,
.endpoint = 0x82,
.ep_attr = USB_ENDPOINT_XFER_ISOC |
USB_ENDPOINT_SYNC_ASYNC |
USB_ENDPOINT_USAGE_IMPLICIT_FB,
.rates = SNDRV_PCM_RATE_96000,
.rate_min = 96000,
.rate_max = 96000,
.nr_rates = 1,
.rate_table = (unsigned int[]) { 96000 },
.clock = 0x29
}
},
{
.ifnum = -1
}
}
}
},
{
/*
* Fiero SC-01 (firmware v1.1.0)
*/
USB_DEVICE(0x2b53, 0x0031),
.driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
.vendor_name = "Fiero",
.product_name = "SC-01",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_COMPOSITE,
.data = &(const struct snd_usb_audio_quirk[]) {
{
.ifnum = 0,
.type = QUIRK_AUDIO_STANDARD_INTERFACE
},
/* Playback */
{
.ifnum = 1,
.type = QUIRK_AUDIO_FIXED_ENDPOINT,
.data = &(const struct audioformat) {
.formats = SNDRV_PCM_FMTBIT_S32_LE,
.channels = 2,
.fmt_bits = 24,
.iface = 1,
.altsetting = 1,
.altset_idx = 1,
.endpoint = 0x01,
.ep_attr = USB_ENDPOINT_XFER_ISOC |
USB_ENDPOINT_SYNC_ASYNC,
.rates = SNDRV_PCM_RATE_48000 |
SNDRV_PCM_RATE_96000,
.rate_min = 48000,
.rate_max = 96000,
.nr_rates = 2,
.rate_table = (unsigned int[]) { 48000, 96000 },
.clock = 0x29
}
},
/* Capture */
{
.ifnum = 2,
.type = QUIRK_AUDIO_FIXED_ENDPOINT,
.data = &(const struct audioformat) {
.formats = SNDRV_PCM_FMTBIT_S32_LE,
.channels = 2,
.fmt_bits = 24,
.iface = 2,
.altsetting = 1,
.altset_idx = 1,
.endpoint = 0x82,
.ep_attr = USB_ENDPOINT_XFER_ISOC |
USB_ENDPOINT_SYNC_ASYNC |
USB_ENDPOINT_USAGE_IMPLICIT_FB,
.rates = SNDRV_PCM_RATE_48000 |
SNDRV_PCM_RATE_96000,
.rate_min = 48000,
.rate_max = 96000,
.nr_rates = 2,
.rate_table = (unsigned int[]) { 48000, 96000 },
.clock = 0x29
}
},
{
.ifnum = -1
}
}
}
},
#undef USB_DEVICE_VENDOR_SPEC #undef USB_DEVICE_VENDOR_SPEC
#undef USB_AUDIO_DEVICE #undef USB_AUDIO_DEVICE
...@@ -1478,6 +1478,7 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs, ...@@ -1478,6 +1478,7 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
case USB_ID(0x041e, 0x3f19): /* E-Mu 0204 USB */ case USB_ID(0x041e, 0x3f19): /* E-Mu 0204 USB */
set_format_emu_quirk(subs, fmt); set_format_emu_quirk(subs, fmt);
break; break;
case USB_ID(0x534d, 0x0021): /* MacroSilicon MS2100/MS2106 */
case USB_ID(0x534d, 0x2109): /* MacroSilicon MS2109 */ case USB_ID(0x534d, 0x2109): /* MacroSilicon MS2109 */
subs->stream_offset_adj = 2; subs->stream_offset_adj = 2;
break; break;
...@@ -1842,6 +1843,10 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { ...@@ -1842,6 +1843,10 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER), QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
DEVICE_FLG(0x1395, 0x740a, /* Sennheiser DECT */ DEVICE_FLG(0x1395, 0x740a, /* Sennheiser DECT */
QUIRK_FLAG_GET_SAMPLE_RATE), QUIRK_FLAG_GET_SAMPLE_RATE),
DEVICE_FLG(0x1397, 0x0508, /* Behringer UMC204HD */
QUIRK_FLAG_PLAYBACK_FIRST | QUIRK_FLAG_GENERIC_IMPLICIT_FB),
DEVICE_FLG(0x1397, 0x0509, /* Behringer UMC404HD */
QUIRK_FLAG_PLAYBACK_FIRST | QUIRK_FLAG_GENERIC_IMPLICIT_FB),
DEVICE_FLG(0x13e5, 0x0001, /* Serato Phono */ DEVICE_FLG(0x13e5, 0x0001, /* Serato Phono */
QUIRK_FLAG_IGNORE_CTL_ERROR), QUIRK_FLAG_IGNORE_CTL_ERROR),
DEVICE_FLG(0x154e, 0x1002, /* Denon DCD-1500RE */ DEVICE_FLG(0x154e, 0x1002, /* Denon DCD-1500RE */
...@@ -1904,10 +1909,18 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { ...@@ -1904,10 +1909,18 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
QUIRK_FLAG_IGNORE_CTL_ERROR), QUIRK_FLAG_IGNORE_CTL_ERROR),
DEVICE_FLG(0x413c, 0xa506, /* Dell AE515 sound bar */ DEVICE_FLG(0x413c, 0xa506, /* Dell AE515 sound bar */
QUIRK_FLAG_GET_SAMPLE_RATE), QUIRK_FLAG_GET_SAMPLE_RATE),
DEVICE_FLG(0x534d, 0x0021, /* MacroSilicon MS2100/MS2106 */
QUIRK_FLAG_ALIGN_TRANSFER),
DEVICE_FLG(0x534d, 0x2109, /* MacroSilicon MS2109 */ DEVICE_FLG(0x534d, 0x2109, /* MacroSilicon MS2109 */
QUIRK_FLAG_ALIGN_TRANSFER), QUIRK_FLAG_ALIGN_TRANSFER),
DEVICE_FLG(0x1224, 0x2a25, /* Jieli Technology USB PHY 2.0 */ DEVICE_FLG(0x1224, 0x2a25, /* Jieli Technology USB PHY 2.0 */
QUIRK_FLAG_GET_SAMPLE_RATE), QUIRK_FLAG_GET_SAMPLE_RATE),
DEVICE_FLG(0x2b53, 0x0023, /* Fiero SC-01 (firmware v1.0.0 @ 48 kHz) */
QUIRK_FLAG_GENERIC_IMPLICIT_FB),
DEVICE_FLG(0x2b53, 0x0024, /* Fiero SC-01 (firmware v1.0.0 @ 96 kHz) */
QUIRK_FLAG_GENERIC_IMPLICIT_FB),
DEVICE_FLG(0x2b53, 0x0031, /* Fiero SC-01 (firmware v1.1.0) */
QUIRK_FLAG_GENERIC_IMPLICIT_FB),
/* Vendor matches */ /* Vendor matches */
VENDOR_FLG(0x045e, /* MS Lifecam */ VENDOR_FLG(0x045e, /* MS Lifecam */
......
...@@ -33,6 +33,8 @@ ...@@ -33,6 +33,8 @@
#include <drm/intel_lpe_audio.h> #include <drm/intel_lpe_audio.h>
#include "intel_hdmi_audio.h" #include "intel_hdmi_audio.h"
#define INTEL_HDMI_AUDIO_SUSPEND_DELAY_MS 5000
#define for_each_pipe(card_ctx, pipe) \ #define for_each_pipe(card_ctx, pipe) \
for ((pipe) = 0; (pipe) < (card_ctx)->num_pipes; (pipe)++) for ((pipe) = 0; (pipe) < (card_ctx)->num_pipes; (pipe)++)
#define for_each_port(card_ctx, port) \ #define for_each_port(card_ctx, port) \
...@@ -1066,7 +1068,9 @@ static int had_pcm_open(struct snd_pcm_substream *substream) ...@@ -1066,7 +1068,9 @@ static int had_pcm_open(struct snd_pcm_substream *substream)
intelhaddata = snd_pcm_substream_chip(substream); intelhaddata = snd_pcm_substream_chip(substream);
runtime = substream->runtime; runtime = substream->runtime;
pm_runtime_get_sync(intelhaddata->dev); retval = pm_runtime_resume_and_get(intelhaddata->dev);
if (retval < 0)
return retval;
/* set the runtime hw parameter with local snd_pcm_hardware struct */ /* set the runtime hw parameter with local snd_pcm_hardware struct */
runtime->hw = had_pcm_hardware; runtime->hw = had_pcm_hardware;
...@@ -1534,8 +1538,12 @@ static void had_audio_wq(struct work_struct *work) ...@@ -1534,8 +1538,12 @@ static void had_audio_wq(struct work_struct *work)
container_of(work, struct snd_intelhad, hdmi_audio_wq); container_of(work, struct snd_intelhad, hdmi_audio_wq);
struct intel_hdmi_lpe_audio_pdata *pdata = ctx->dev->platform_data; struct intel_hdmi_lpe_audio_pdata *pdata = ctx->dev->platform_data;
struct intel_hdmi_lpe_audio_port_pdata *ppdata = &pdata->port[ctx->port]; struct intel_hdmi_lpe_audio_port_pdata *ppdata = &pdata->port[ctx->port];
int ret;
ret = pm_runtime_resume_and_get(ctx->dev);
if (ret < 0)
return;
pm_runtime_get_sync(ctx->dev);
mutex_lock(&ctx->mutex); mutex_lock(&ctx->mutex);
if (ppdata->pipe < 0) { if (ppdata->pipe < 0) {
dev_dbg(ctx->dev, "%s: Event: HAD_NOTIFY_HOT_UNPLUG : port = %d\n", dev_dbg(ctx->dev, "%s: Event: HAD_NOTIFY_HOT_UNPLUG : port = %d\n",
...@@ -1802,8 +1810,11 @@ static int __hdmi_lpe_audio_probe(struct platform_device *pdev) ...@@ -1802,8 +1810,11 @@ static int __hdmi_lpe_audio_probe(struct platform_device *pdev)
pdata->notify_audio_lpe = notify_audio_lpe; pdata->notify_audio_lpe = notify_audio_lpe;
spin_unlock_irq(&pdata->lpe_audio_slock); spin_unlock_irq(&pdata->lpe_audio_slock);
pm_runtime_set_autosuspend_delay(&pdev->dev, INTEL_HDMI_AUDIO_SUSPEND_DELAY_MS);
pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_enable(&pdev->dev);
pm_runtime_mark_last_busy(&pdev->dev); pm_runtime_mark_last_busy(&pdev->dev);
pm_runtime_idle(&pdev->dev);
dev_dbg(&pdev->dev, "%s: handle pending notification\n", __func__); dev_dbg(&pdev->dev, "%s: handle pending notification\n", __func__);
for_each_port(card_ctx, port) { for_each_port(card_ctx, port) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册