Merge branch 'for-linus' into for-next

This commit is contained in:
Takashi Iwai 2021-08-02 09:04:48 +02:00
commit 01099b1ad9
27 changed files with 240 additions and 118 deletions

View File

@ -114,7 +114,7 @@ properties:
ports: ports:
$ref: /schemas/graph.yaml#/properties/ports $ref: /schemas/graph.yaml#/properties/ports
properties: patternProperties:
port(@[0-9a-f]+)?: port(@[0-9a-f]+)?:
$ref: audio-graph-port.yaml# $ref: audio-graph-port.yaml#
unevaluatedProperties: false unevaluatedProperties: false

View File

@ -712,6 +712,12 @@ struct snd_soc_dai_link {
/* Do not create a PCM for this DAI link (Backend link) */ /* Do not create a PCM for this DAI link (Backend link) */
unsigned int ignore:1; unsigned int ignore:1;
/* This flag will reorder stop sequence. By enabling this flag
* DMA controller stop sequence will be invoked first followed by
* CPU DAI driver stop sequence
*/
unsigned int stop_dma_first:1;
#ifdef CONFIG_SND_SOC_TOPOLOGY #ifdef CONFIG_SND_SOC_TOPOLOGY
struct snd_soc_dobj dobj; /* For topology */ struct snd_soc_dobj dobj; /* For topology */
#endif #endif

View File

@ -261,7 +261,7 @@ static int snd_dma_continuous_mmap(struct snd_dma_buffer *dmab,
struct vm_area_struct *area) struct vm_area_struct *area)
{ {
return remap_pfn_range(area, area->vm_start, return remap_pfn_range(area, area->vm_start,
dmab->addr >> PAGE_SHIFT, page_to_pfn(virt_to_page(dmab->area)),
area->vm_end - area->vm_start, area->vm_end - area->vm_start,
area->vm_page_prot); area->vm_page_prot);
} }

View File

@ -246,12 +246,18 @@ static bool hw_support_mmap(struct snd_pcm_substream *substream)
if (!(substream->runtime->hw.info & SNDRV_PCM_INFO_MMAP)) if (!(substream->runtime->hw.info & SNDRV_PCM_INFO_MMAP))
return false; return false;
if (substream->ops->mmap || if (substream->ops->mmap || substream->ops->page)
(substream->dma_buffer.dev.type != SNDRV_DMA_TYPE_DEV &&
substream->dma_buffer.dev.type != SNDRV_DMA_TYPE_DEV_UC))
return true; return true;
return dma_can_mmap(substream->dma_buffer.dev.dev); switch (substream->dma_buffer.dev.type) {
case SNDRV_DMA_TYPE_UNKNOWN:
return false;
case SNDRV_DMA_TYPE_CONTINUOUS:
case SNDRV_DMA_TYPE_VMALLOC:
return true;
default:
return dma_can_mmap(substream->dma_buffer.dev.dev);
}
} }
static int constrain_mask_params(struct snd_pcm_substream *substream, static int constrain_mask_params(struct snd_pcm_substream *substream,
@ -3669,6 +3675,8 @@ static vm_fault_t snd_pcm_mmap_data_fault(struct vm_fault *vmf)
return VM_FAULT_SIGBUS; return VM_FAULT_SIGBUS;
if (substream->ops->page) if (substream->ops->page)
page = substream->ops->page(substream, offset); page = substream->ops->page(substream, offset);
else if (!snd_pcm_get_dma_buf(substream))
page = virt_to_page(runtime->dma_area + offset);
else else
page = snd_sgbuf_get_page(snd_pcm_get_dma_buf(substream), offset); page = snd_sgbuf_get_page(snd_pcm_get_dma_buf(substream), offset);
if (!page) if (!page)

View File

@ -319,6 +319,10 @@ static const struct config_entry config_table[] = {
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC, .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC,
.device = 0x4b55, .device = 0x4b55,
}, },
{
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC,
.device = 0x4b58,
},
#endif #endif
/* Alder Lake */ /* Alder Lake */

View File

@ -816,6 +816,7 @@ static int snd_sb_csp_start(struct snd_sb_csp * p, int sample_width, int channel
mixR = snd_sbmixer_read(p->chip, SB_DSP4_PCM_DEV + 1); mixR = snd_sbmixer_read(p->chip, SB_DSP4_PCM_DEV + 1);
snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL & 0x7); snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL & 0x7);
snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR & 0x7); snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR & 0x7);
spin_unlock_irqrestore(&p->chip->mixer_lock, flags);
spin_lock(&p->chip->reg_lock); spin_lock(&p->chip->reg_lock);
set_mode_register(p->chip, 0xc0); /* c0 = STOP */ set_mode_register(p->chip, 0xc0); /* c0 = STOP */
@ -855,6 +856,7 @@ static int snd_sb_csp_start(struct snd_sb_csp * p, int sample_width, int channel
spin_unlock(&p->chip->reg_lock); spin_unlock(&p->chip->reg_lock);
/* restore PCM volume */ /* restore PCM volume */
spin_lock_irqsave(&p->chip->mixer_lock, flags);
snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL); snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL);
snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR); snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR);
spin_unlock_irqrestore(&p->chip->mixer_lock, flags); spin_unlock_irqrestore(&p->chip->mixer_lock, flags);
@ -880,6 +882,7 @@ static int snd_sb_csp_stop(struct snd_sb_csp * p)
mixR = snd_sbmixer_read(p->chip, SB_DSP4_PCM_DEV + 1); mixR = snd_sbmixer_read(p->chip, SB_DSP4_PCM_DEV + 1);
snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL & 0x7); snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL & 0x7);
snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR & 0x7); snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR & 0x7);
spin_unlock_irqrestore(&p->chip->mixer_lock, flags);
spin_lock(&p->chip->reg_lock); spin_lock(&p->chip->reg_lock);
if (p->running & SNDRV_SB_CSP_ST_QSOUND) { if (p->running & SNDRV_SB_CSP_ST_QSOUND) {
@ -894,6 +897,7 @@ static int snd_sb_csp_stop(struct snd_sb_csp * p)
spin_unlock(&p->chip->reg_lock); spin_unlock(&p->chip->reg_lock);
/* restore PCM volume */ /* restore PCM volume */
spin_lock_irqsave(&p->chip->mixer_lock, flags);
snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL); snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL);
snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR); snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV + 1, mixR);
spin_unlock_irqrestore(&p->chip->mixer_lock, flags); spin_unlock_irqrestore(&p->chip->mixer_lock, flags);

View File

@ -1944,6 +1944,8 @@ static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t cvt_nid)
static const struct snd_pci_quirk force_connect_list[] = { static const struct snd_pci_quirk force_connect_list[] = {
SND_PCI_QUIRK(0x103c, 0x870f, "HP", 1), SND_PCI_QUIRK(0x103c, 0x870f, "HP", 1),
SND_PCI_QUIRK(0x103c, 0x871a, "HP", 1), SND_PCI_QUIRK(0x103c, 0x871a, "HP", 1),
SND_PCI_QUIRK(0x1462, 0xec94, "MS-7C94", 1),
SND_PCI_QUIRK(0x8086, 0x2081, "Intel NUC 10", 1),
{} {}
}; };

View File

@ -8274,9 +8274,11 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1025, 0x1290, "Acer Veriton Z4860G", ALC286_FIXUP_ACER_AIO_HEADSET_MIC), SND_PCI_QUIRK(0x1025, 0x1290, "Acer Veriton Z4860G", ALC286_FIXUP_ACER_AIO_HEADSET_MIC),
SND_PCI_QUIRK(0x1025, 0x1291, "Acer Veriton Z4660G", ALC286_FIXUP_ACER_AIO_HEADSET_MIC), SND_PCI_QUIRK(0x1025, 0x1291, "Acer Veriton Z4660G", ALC286_FIXUP_ACER_AIO_HEADSET_MIC),
SND_PCI_QUIRK(0x1025, 0x129c, "Acer SWIFT SF314-55", ALC256_FIXUP_ACER_HEADSET_MIC), SND_PCI_QUIRK(0x1025, 0x129c, "Acer SWIFT SF314-55", ALC256_FIXUP_ACER_HEADSET_MIC),
SND_PCI_QUIRK(0x1025, 0x1300, "Acer SWIFT SF314-56", ALC256_FIXUP_ACER_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1025, 0x1308, "Acer Aspire Z24-890", ALC286_FIXUP_ACER_AIO_HEADSET_MIC), SND_PCI_QUIRK(0x1025, 0x1308, "Acer Aspire Z24-890", ALC286_FIXUP_ACER_AIO_HEADSET_MIC),
SND_PCI_QUIRK(0x1025, 0x132a, "Acer TravelMate B114-21", ALC233_FIXUP_ACER_HEADSET_MIC), SND_PCI_QUIRK(0x1025, 0x132a, "Acer TravelMate B114-21", ALC233_FIXUP_ACER_HEADSET_MIC),
SND_PCI_QUIRK(0x1025, 0x1330, "Acer TravelMate X514-51T", ALC255_FIXUP_ACER_HEADSET_MIC), SND_PCI_QUIRK(0x1025, 0x1330, "Acer TravelMate X514-51T", ALC255_FIXUP_ACER_HEADSET_MIC),
SND_PCI_QUIRK(0x1025, 0x142b, "Acer Swift SF314-42", ALC255_FIXUP_ACER_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1025, 0x1430, "Acer TravelMate B311R-31", ALC256_FIXUP_ACER_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1025, 0x1430, "Acer TravelMate B311R-31", ALC256_FIXUP_ACER_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1025, 0x1466, "Acer Aspire A515-56", ALC255_FIXUP_ACER_HEADPHONE_AND_MIC), SND_PCI_QUIRK(0x1025, 0x1466, "Acer Aspire A515-56", ALC255_FIXUP_ACER_HEADPHONE_AND_MIC),
SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z), SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
@ -8626,6 +8628,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x3151, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC), SND_PCI_QUIRK(0x17aa, 0x3151, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x17aa, 0x3176, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC), SND_PCI_QUIRK(0x17aa, 0x3176, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x17aa, 0x3178, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC), SND_PCI_QUIRK(0x17aa, 0x3178, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x17aa, 0x31af, "ThinkCentre Station", ALC623_FIXUP_LENOVO_THINKSTATION_P340),
SND_PCI_QUIRK(0x17aa, 0x3818, "Lenovo C940", ALC298_FIXUP_LENOVO_SPK_VOLUME), SND_PCI_QUIRK(0x17aa, 0x3818, "Lenovo C940", ALC298_FIXUP_LENOVO_SPK_VOLUME),
SND_PCI_QUIRK(0x17aa, 0x3827, "Ideapad S740", ALC285_FIXUP_IDEAPAD_S740_COEF), SND_PCI_QUIRK(0x17aa, 0x3827, "Ideapad S740", ALC285_FIXUP_IDEAPAD_S740_COEF),
SND_PCI_QUIRK(0x17aa, 0x3843, "Yoga 9i", ALC287_FIXUP_IDEAPAD_BASS_SPK_AMP), SND_PCI_QUIRK(0x17aa, 0x3843, "Yoga 9i", ALC287_FIXUP_IDEAPAD_BASS_SPK_AMP),

View File

@ -576,6 +576,7 @@ static struct snd_soc_dai_link cz_dai_5682_98357[] = {
| SND_SOC_DAIFMT_CBM_CFM, | SND_SOC_DAIFMT_CBM_CFM,
.init = cz_rt5682_init, .init = cz_rt5682_init,
.dpcm_playback = 1, .dpcm_playback = 1,
.stop_dma_first = 1,
.ops = &cz_rt5682_play_ops, .ops = &cz_rt5682_play_ops,
SND_SOC_DAILINK_REG(designware1, rt5682, platform), SND_SOC_DAILINK_REG(designware1, rt5682, platform),
}, },
@ -585,6 +586,7 @@ static struct snd_soc_dai_link cz_dai_5682_98357[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFM, | SND_SOC_DAIFMT_CBM_CFM,
.dpcm_capture = 1, .dpcm_capture = 1,
.stop_dma_first = 1,
.ops = &cz_rt5682_cap_ops, .ops = &cz_rt5682_cap_ops,
SND_SOC_DAILINK_REG(designware2, rt5682, platform), SND_SOC_DAILINK_REG(designware2, rt5682, platform),
}, },
@ -594,6 +596,7 @@ static struct snd_soc_dai_link cz_dai_5682_98357[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFM, | SND_SOC_DAIFMT_CBM_CFM,
.dpcm_playback = 1, .dpcm_playback = 1,
.stop_dma_first = 1,
.ops = &cz_rt5682_max_play_ops, .ops = &cz_rt5682_max_play_ops,
SND_SOC_DAILINK_REG(designware3, mx, platform), SND_SOC_DAILINK_REG(designware3, mx, platform),
}, },
@ -604,6 +607,7 @@ static struct snd_soc_dai_link cz_dai_5682_98357[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFM, | SND_SOC_DAIFMT_CBM_CFM,
.dpcm_capture = 1, .dpcm_capture = 1,
.stop_dma_first = 1,
.ops = &cz_rt5682_dmic0_cap_ops, .ops = &cz_rt5682_dmic0_cap_ops,
SND_SOC_DAILINK_REG(designware3, adau, platform), SND_SOC_DAILINK_REG(designware3, adau, platform),
}, },
@ -614,6 +618,7 @@ static struct snd_soc_dai_link cz_dai_5682_98357[] = {
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFM, | SND_SOC_DAIFMT_CBM_CFM,
.dpcm_capture = 1, .dpcm_capture = 1,
.stop_dma_first = 1,
.ops = &cz_rt5682_dmic1_cap_ops, .ops = &cz_rt5682_dmic1_cap_ops,
SND_SOC_DAILINK_REG(designware2, adau, platform), SND_SOC_DAILINK_REG(designware2, adau, platform),
}, },

View File

@ -1325,7 +1325,7 @@ config SND_SOC_SSM2305
high-efficiency mono Class-D audio power amplifiers. high-efficiency mono Class-D audio power amplifiers.
config SND_SOC_SSM2518 config SND_SOC_SSM2518
tristate tristate "Analog Devices SSM2518 Class-D Amplifier"
depends on I2C depends on I2C
config SND_SOC_SSM2602 config SND_SOC_SSM2602
@ -1557,6 +1557,7 @@ config SND_SOC_WCD934X
Qualcomm SoCs like SDM845. Qualcomm SoCs like SDM845.
config SND_SOC_WCD938X config SND_SOC_WCD938X
depends on SND_SOC_WCD938X_SDW
tristate tristate
config SND_SOC_WCD938X_SDW config SND_SOC_WCD938X_SDW
@ -1813,11 +1814,6 @@ config SND_SOC_ZL38060
which consists of a Digital Signal Processor (DSP), several Digital which consists of a Digital Signal Processor (DSP), several Digital
Audio Interfaces (DAIs), analog outputs, and a block of 14 GPIOs. Audio Interfaces (DAIs), analog outputs, and a block of 14 GPIOs.
config SND_SOC_ZX_AUD96P22
tristate "ZTE ZX AUD96P22 CODEC"
depends on I2C
select REGMAP_I2C
# Amp # Amp
config SND_SOC_LM4857 config SND_SOC_LM4857
tristate tristate

View File

@ -1695,6 +1695,8 @@ static const struct regmap_config rt5631_regmap_config = {
.reg_defaults = rt5631_reg, .reg_defaults = rt5631_reg,
.num_reg_defaults = ARRAY_SIZE(rt5631_reg), .num_reg_defaults = ARRAY_SIZE(rt5631_reg),
.cache_type = REGCACHE_RBTREE, .cache_type = REGCACHE_RBTREE,
.use_single_read = true,
.use_single_write = true,
}; };
static int rt5631_i2c_probe(struct i2c_client *i2c, static int rt5631_i2c_probe(struct i2c_client *i2c,

View File

@ -973,10 +973,14 @@ int rt5682_headset_detect(struct snd_soc_component *component, int jack_insert)
rt5682_enable_push_button_irq(component, false); rt5682_enable_push_button_irq(component, false);
snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_1, snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_1,
RT5682_TRIG_JD_MASK, RT5682_TRIG_JD_LOW); RT5682_TRIG_JD_MASK, RT5682_TRIG_JD_LOW);
if (!snd_soc_dapm_get_pin_status(dapm, "MICBIAS")) if (!snd_soc_dapm_get_pin_status(dapm, "MICBIAS") &&
!snd_soc_dapm_get_pin_status(dapm, "PLL1") &&
!snd_soc_dapm_get_pin_status(dapm, "PLL2B"))
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
RT5682_PWR_ANLG_1, RT5682_PWR_MB, 0); RT5682_PWR_ANLG_1, RT5682_PWR_MB, 0);
if (!snd_soc_dapm_get_pin_status(dapm, "Vref2")) if (!snd_soc_dapm_get_pin_status(dapm, "Vref2") &&
!snd_soc_dapm_get_pin_status(dapm, "PLL1") &&
!snd_soc_dapm_get_pin_status(dapm, "PLL2B"))
snd_soc_component_update_bits(component, snd_soc_component_update_bits(component,
RT5682_PWR_ANLG_1, RT5682_PWR_VREF2, 0); RT5682_PWR_ANLG_1, RT5682_PWR_VREF2, 0);
snd_soc_component_update_bits(component, RT5682_PWR_ANLG_3, snd_soc_component_update_bits(component, RT5682_PWR_ANLG_3,

View File

@ -1604,6 +1604,8 @@ static int aic31xx_i2c_probe(struct i2c_client *i2c,
ret); ret);
return ret; return ret;
} }
regcache_cache_only(aic31xx->regmap, true);
aic31xx->dev = &i2c->dev; aic31xx->dev = &i2c->dev;
aic31xx->irq = i2c->irq; aic31xx->irq = i2c->irq;

View File

@ -151,8 +151,8 @@ struct aic31xx_pdata {
#define AIC31XX_WORD_LEN_24BITS 0x02 #define AIC31XX_WORD_LEN_24BITS 0x02
#define AIC31XX_WORD_LEN_32BITS 0x03 #define AIC31XX_WORD_LEN_32BITS 0x03
#define AIC31XX_IFACE1_MASTER_MASK GENMASK(3, 2) #define AIC31XX_IFACE1_MASTER_MASK GENMASK(3, 2)
#define AIC31XX_BCLK_MASTER BIT(2) #define AIC31XX_BCLK_MASTER BIT(3)
#define AIC31XX_WCLK_MASTER BIT(3) #define AIC31XX_WCLK_MASTER BIT(2)
/* AIC31XX_DATA_OFFSET */ /* AIC31XX_DATA_OFFSET */
#define AIC31XX_DATA_OFFSET_MASK GENMASK(7, 0) #define AIC31XX_DATA_OFFSET_MASK GENMASK(7, 0)

View File

@ -250,8 +250,8 @@ static DECLARE_TLV_DB_SCALE(tlv_pcm, -6350, 50, 0);
static DECLARE_TLV_DB_SCALE(tlv_driver_gain, -600, 100, 0); static DECLARE_TLV_DB_SCALE(tlv_driver_gain, -600, 100, 0);
/* -12dB min, 0.5dB steps */ /* -12dB min, 0.5dB steps */
static DECLARE_TLV_DB_SCALE(tlv_adc_vol, -1200, 50, 0); static DECLARE_TLV_DB_SCALE(tlv_adc_vol, -1200, 50, 0);
/* -6dB min, 1dB steps */
static DECLARE_TLV_DB_LINEAR(tlv_spk_vol, TLV_DB_GAIN_MUTE, 0); static DECLARE_TLV_DB_SCALE(tlv_tas_driver_gain, -5850, 50, 0);
static DECLARE_TLV_DB_SCALE(tlv_amp_vol, 0, 600, 1); static DECLARE_TLV_DB_SCALE(tlv_amp_vol, 0, 600, 1);
static const char * const lo_cm_text[] = { static const char * const lo_cm_text[] = {
@ -1063,21 +1063,20 @@ static const struct snd_soc_component_driver soc_component_dev_aic32x4 = {
}; };
static const struct snd_kcontrol_new aic32x4_tas2505_snd_controls[] = { static const struct snd_kcontrol_new aic32x4_tas2505_snd_controls[] = {
SOC_DOUBLE_R_S_TLV("PCM Playback Volume", AIC32X4_LDACVOL, SOC_SINGLE_S8_TLV("PCM Playback Volume",
AIC32X4_LDACVOL, 0, -0x7f, 0x30, 7, 0, tlv_pcm), AIC32X4_LDACVOL, -0x7f, 0x30, tlv_pcm),
SOC_ENUM("DAC Playback PowerTune Switch", l_ptm_enum), SOC_ENUM("DAC Playback PowerTune Switch", l_ptm_enum),
SOC_DOUBLE_R_S_TLV("HP Driver Playback Volume", AIC32X4_HPLGAIN,
AIC32X4_HPLGAIN, 0, -0x6, 0x1d, 5, 0, SOC_SINGLE_TLV("HP Driver Gain Volume",
tlv_driver_gain), AIC32X4_HPLGAIN, 0, 0x74, 1, tlv_tas_driver_gain),
SOC_DOUBLE_R("HP DAC Playback Switch", AIC32X4_HPLGAIN, SOC_SINGLE("HP DAC Playback Switch", AIC32X4_HPLGAIN, 6, 1, 1),
AIC32X4_HPLGAIN, 6, 0x01, 1),
SOC_SINGLE_TLV("Speaker Driver Playback Volume",
TAS2505_SPKVOL1, 0, 0x74, 1, tlv_tas_driver_gain),
SOC_SINGLE_TLV("Speaker Amplifier Playback Volume",
TAS2505_SPKVOL2, 4, 5, 0, tlv_amp_vol),
SOC_SINGLE("Auto-mute Switch", AIC32X4_DACMUTE, 4, 7, 0), SOC_SINGLE("Auto-mute Switch", AIC32X4_DACMUTE, 4, 7, 0),
SOC_SINGLE_RANGE_TLV("Speaker Driver Playback Volume", TAS2505_SPKVOL1,
0, 0, 117, 1, tlv_spk_vol),
SOC_SINGLE_TLV("Speaker Amplifier Playback Volume", TAS2505_SPKVOL2,
4, 5, 0, tlv_amp_vol),
}; };
static const struct snd_kcontrol_new hp_output_mixer_controls[] = { static const struct snd_kcontrol_new hp_output_mixer_controls[] = {

View File

@ -3317,13 +3317,6 @@ static int wcd938x_soc_codec_probe(struct snd_soc_component *component)
(WCD938X_DIGITAL_INTR_LEVEL_0 + i), 0); (WCD938X_DIGITAL_INTR_LEVEL_0 + i), 0);
} }
ret = wcd938x_irq_init(wcd938x, component->dev);
if (ret) {
dev_err(component->dev, "%s: IRQ init failed: %d\n",
__func__, ret);
return ret;
}
wcd938x->hphr_pdm_wd_int = regmap_irq_get_virq(wcd938x->irq_chip, wcd938x->hphr_pdm_wd_int = regmap_irq_get_virq(wcd938x->irq_chip,
WCD938X_IRQ_HPHR_PDM_WD_INT); WCD938X_IRQ_HPHR_PDM_WD_INT);
wcd938x->hphl_pdm_wd_int = regmap_irq_get_virq(wcd938x->irq_chip, wcd938x->hphl_pdm_wd_int = regmap_irq_get_virq(wcd938x->irq_chip,
@ -3553,7 +3546,6 @@ static int wcd938x_bind(struct device *dev)
} }
wcd938x->sdw_priv[AIF1_PB] = dev_get_drvdata(wcd938x->rxdev); wcd938x->sdw_priv[AIF1_PB] = dev_get_drvdata(wcd938x->rxdev);
wcd938x->sdw_priv[AIF1_PB]->wcd938x = wcd938x; wcd938x->sdw_priv[AIF1_PB]->wcd938x = wcd938x;
wcd938x->sdw_priv[AIF1_PB]->slave_irq = wcd938x->virq;
wcd938x->txdev = wcd938x_sdw_device_get(wcd938x->txnode); wcd938x->txdev = wcd938x_sdw_device_get(wcd938x->txnode);
if (!wcd938x->txdev) { if (!wcd938x->txdev) {
@ -3562,7 +3554,6 @@ static int wcd938x_bind(struct device *dev)
} }
wcd938x->sdw_priv[AIF1_CAP] = dev_get_drvdata(wcd938x->txdev); wcd938x->sdw_priv[AIF1_CAP] = dev_get_drvdata(wcd938x->txdev);
wcd938x->sdw_priv[AIF1_CAP]->wcd938x = wcd938x; wcd938x->sdw_priv[AIF1_CAP]->wcd938x = wcd938x;
wcd938x->sdw_priv[AIF1_CAP]->slave_irq = wcd938x->virq;
wcd938x->tx_sdw_dev = dev_to_sdw_dev(wcd938x->txdev); wcd938x->tx_sdw_dev = dev_to_sdw_dev(wcd938x->txdev);
if (!wcd938x->tx_sdw_dev) { if (!wcd938x->tx_sdw_dev) {
dev_err(dev, "could not get txslave with matching of dev\n"); dev_err(dev, "could not get txslave with matching of dev\n");
@ -3595,6 +3586,15 @@ static int wcd938x_bind(struct device *dev)
return PTR_ERR(wcd938x->regmap); return PTR_ERR(wcd938x->regmap);
} }
ret = wcd938x_irq_init(wcd938x, dev);
if (ret) {
dev_err(dev, "%s: IRQ init failed: %d\n", __func__, ret);
return ret;
}
wcd938x->sdw_priv[AIF1_PB]->slave_irq = wcd938x->virq;
wcd938x->sdw_priv[AIF1_CAP]->slave_irq = wcd938x->virq;
ret = wcd938x_set_micbias_data(wcd938x); ret = wcd938x_set_micbias_data(wcd938x);
if (ret < 0) { if (ret < 0) {
dev_err(dev, "%s: bad micbias pdata\n", __func__); dev_err(dev, "%s: bad micbias pdata\n", __func__);

View File

@ -282,6 +282,7 @@
/* /*
* HALO_CCM_CORE_CONTROL * HALO_CCM_CORE_CONTROL
*/ */
#define HALO_CORE_RESET 0x00000200
#define HALO_CORE_EN 0x00000001 #define HALO_CORE_EN 0x00000001
/* /*
@ -1213,7 +1214,7 @@ static int wm_coeff_tlv_get(struct snd_kcontrol *kctl,
mutex_lock(&ctl->dsp->pwr_lock); mutex_lock(&ctl->dsp->pwr_lock);
ret = wm_coeff_read_ctrl_raw(ctl, ctl->cache, size); ret = wm_coeff_read_ctrl(ctl, ctl->cache, size);
if (!ret && copy_to_user(bytes, ctl->cache, size)) if (!ret && copy_to_user(bytes, ctl->cache, size))
ret = -EFAULT; ret = -EFAULT;
@ -3333,7 +3334,8 @@ static int wm_halo_start_core(struct wm_adsp *dsp)
{ {
return regmap_update_bits(dsp->regmap, return regmap_update_bits(dsp->regmap,
dsp->base + HALO_CCM_CORE_CONTROL, dsp->base + HALO_CCM_CORE_CONTROL,
HALO_CORE_EN, HALO_CORE_EN); HALO_CORE_RESET | HALO_CORE_EN,
HALO_CORE_RESET | HALO_CORE_EN);
} }
static void wm_halo_stop_core(struct wm_adsp *dsp) static void wm_halo_stop_core(struct wm_adsp *dsp)

View File

@ -55,43 +55,68 @@ static int spk_init(struct snd_soc_pcm_runtime *rtd)
return ret; return ret;
} }
static int max98373_sdw_trigger(struct snd_pcm_substream *substream, int cmd) static int mx8373_enable_spk_pin(struct snd_pcm_substream *substream, bool enable)
{ {
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_dai *codec_dai;
struct snd_soc_dai *cpu_dai;
int ret; int ret;
int j;
switch (cmd) { /* set spk pin by playback only */
case SNDRV_PCM_TRIGGER_START: if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
case SNDRV_PCM_TRIGGER_RESUME: return 0;
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
/* enable max98373 first */
ret = max_98373_trigger(substream, cmd);
if (ret < 0)
break;
ret = sdw_trigger(substream, cmd); cpu_dai = asoc_rtd_to_cpu(rtd, 0);
break; for_each_rtd_codec_dais(rtd, j, codec_dai) {
case SNDRV_PCM_TRIGGER_STOP: struct snd_soc_dapm_context *dapm =
case SNDRV_PCM_TRIGGER_SUSPEND: snd_soc_component_get_dapm(cpu_dai->component);
case SNDRV_PCM_TRIGGER_PAUSE_PUSH: char pin_name[16];
ret = sdw_trigger(substream, cmd);
if (ret < 0)
break;
ret = max_98373_trigger(substream, cmd); snprintf(pin_name, ARRAY_SIZE(pin_name), "%s Spk",
break; codec_dai->component->name_prefix);
default:
ret = -EINVAL; if (enable)
break; ret = snd_soc_dapm_enable_pin(dapm, pin_name);
else
ret = snd_soc_dapm_disable_pin(dapm, pin_name);
if (!ret)
snd_soc_dapm_sync(dapm);
} }
return ret; return 0;
}
static int mx8373_sdw_prepare(struct snd_pcm_substream *substream)
{
int ret = 0;
/* according to soc_pcm_prepare dai link prepare is called first */
ret = sdw_prepare(substream);
if (ret < 0)
return ret;
return mx8373_enable_spk_pin(substream, true);
}
static int mx8373_sdw_hw_free(struct snd_pcm_substream *substream)
{
int ret = 0;
/* according to soc_pcm_hw_free dai link free is called first */
ret = sdw_hw_free(substream);
if (ret < 0)
return ret;
return mx8373_enable_spk_pin(substream, false);
} }
static const struct snd_soc_ops max_98373_sdw_ops = { static const struct snd_soc_ops max_98373_sdw_ops = {
.startup = sdw_startup, .startup = sdw_startup,
.prepare = sdw_prepare, .prepare = mx8373_sdw_prepare,
.trigger = max98373_sdw_trigger, .trigger = sdw_trigger,
.hw_free = sdw_hw_free, .hw_free = mx8373_sdw_hw_free,
.shutdown = sdw_shutdown, .shutdown = sdw_shutdown,
}; };

View File

@ -1015,6 +1015,7 @@ out:
static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{ {
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
int ret = -EINVAL, _ret = 0; int ret = -EINVAL, _ret = 0;
int rollback = 0; int rollback = 0;
@ -1055,14 +1056,23 @@ start_err:
case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH: case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
ret = snd_soc_pcm_dai_trigger(substream, cmd, rollback); if (rtd->dai_link->stop_dma_first) {
if (ret < 0) ret = snd_soc_pcm_component_trigger(substream, cmd, rollback);
break; if (ret < 0)
break;
ret = snd_soc_pcm_component_trigger(substream, cmd, rollback); ret = snd_soc_pcm_dai_trigger(substream, cmd, rollback);
if (ret < 0) if (ret < 0)
break; break;
} else {
ret = snd_soc_pcm_dai_trigger(substream, cmd, rollback);
if (ret < 0)
break;
ret = snd_soc_pcm_component_trigger(substream, cmd, rollback);
if (ret < 0)
break;
}
ret = snd_soc_link_trigger(substream, cmd, rollback); ret = snd_soc_link_trigger(substream, cmd, rollback);
break; break;
} }

View File

@ -89,6 +89,7 @@ static const struct sof_dev_desc adls_desc = {
static const struct sof_dev_desc adl_desc = { static const struct sof_dev_desc adl_desc = {
.machines = snd_soc_acpi_intel_adl_machines, .machines = snd_soc_acpi_intel_adl_machines,
.alt_machines = snd_soc_acpi_intel_adl_sdw_machines, .alt_machines = snd_soc_acpi_intel_adl_sdw_machines,
.use_acpi_target_states = true,
.resindex_lpe_base = 0, .resindex_lpe_base = 0,
.resindex_pcicfg_base = -1, .resindex_pcicfg_base = -1,
.resindex_imr_base = -1, .resindex_imr_base = -1,

View File

@ -213,19 +213,19 @@ snd_pcm_uframes_t tegra_pcm_pointer(struct snd_soc_component *component,
} }
EXPORT_SYMBOL_GPL(tegra_pcm_pointer); EXPORT_SYMBOL_GPL(tegra_pcm_pointer);
static int tegra_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream, static int tegra_pcm_preallocate_dma_buffer(struct device *dev, struct snd_pcm *pcm, int stream,
size_t size) size_t size)
{ {
struct snd_pcm_substream *substream = pcm->streams[stream].substream; struct snd_pcm_substream *substream = pcm->streams[stream].substream;
struct snd_dma_buffer *buf = &substream->dma_buffer; struct snd_dma_buffer *buf = &substream->dma_buffer;
buf->area = dma_alloc_wc(pcm->card->dev, size, &buf->addr, GFP_KERNEL); buf->area = dma_alloc_wc(dev, size, &buf->addr, GFP_KERNEL);
if (!buf->area) if (!buf->area)
return -ENOMEM; return -ENOMEM;
buf->private_data = NULL; buf->private_data = NULL;
buf->dev.type = SNDRV_DMA_TYPE_DEV; buf->dev.type = SNDRV_DMA_TYPE_DEV;
buf->dev.dev = pcm->card->dev; buf->dev.dev = dev;
buf->bytes = size; buf->bytes = size;
return 0; return 0;
@ -244,31 +244,28 @@ static void tegra_pcm_deallocate_dma_buffer(struct snd_pcm *pcm, int stream)
if (!buf->area) if (!buf->area)
return; return;
dma_free_wc(pcm->card->dev, buf->bytes, buf->area, buf->addr); dma_free_wc(buf->dev.dev, buf->bytes, buf->area, buf->addr);
buf->area = NULL; buf->area = NULL;
} }
static int tegra_pcm_dma_allocate(struct snd_soc_pcm_runtime *rtd, static int tegra_pcm_dma_allocate(struct device *dev, struct snd_soc_pcm_runtime *rtd,
size_t size) size_t size)
{ {
struct snd_card *card = rtd->card->snd_card;
struct snd_pcm *pcm = rtd->pcm; struct snd_pcm *pcm = rtd->pcm;
int ret; int ret;
ret = dma_set_mask_and_coherent(card->dev, DMA_BIT_MASK(32)); ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
if (ret < 0) if (ret < 0)
return ret; return ret;
if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
ret = tegra_pcm_preallocate_dma_buffer(pcm, ret = tegra_pcm_preallocate_dma_buffer(dev, pcm, SNDRV_PCM_STREAM_PLAYBACK, size);
SNDRV_PCM_STREAM_PLAYBACK, size);
if (ret) if (ret)
goto err; goto err;
} }
if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
ret = tegra_pcm_preallocate_dma_buffer(pcm, ret = tegra_pcm_preallocate_dma_buffer(dev, pcm, SNDRV_PCM_STREAM_CAPTURE, size);
SNDRV_PCM_STREAM_CAPTURE, size);
if (ret) if (ret)
goto err_free_play; goto err_free_play;
} }
@ -284,7 +281,16 @@ err:
int tegra_pcm_construct(struct snd_soc_component *component, int tegra_pcm_construct(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd) struct snd_soc_pcm_runtime *rtd)
{ {
return tegra_pcm_dma_allocate(rtd, tegra_pcm_hardware.buffer_bytes_max); struct device *dev = component->dev;
/*
* Fallback for backwards-compatibility with older device trees that
* have the iommus property in the virtual, top-level "sound" node.
*/
if (!of_get_property(dev->of_node, "iommus", NULL))
dev = rtd->card->snd_card->dev;
return tegra_pcm_dma_allocate(dev, rtd, tegra_pcm_hardware.buffer_bytes_max);
} }
EXPORT_SYMBOL_GPL(tegra_pcm_construct); EXPORT_SYMBOL_GPL(tegra_pcm_construct);

View File

@ -197,7 +197,7 @@ static int j721e_configure_refclk(struct j721e_priv *priv,
return ret; return ret;
} }
if (priv->hsdiv_rates[domain->parent_clk_id] != scki) { if (domain->parent_clk_id == -1 || priv->hsdiv_rates[domain->parent_clk_id] != scki) {
dev_dbg(priv->dev, dev_dbg(priv->dev,
"%s configuration for %u Hz: %s, %dxFS (SCKI: %u Hz)\n", "%s configuration for %u Hz: %s, %dxFS (SCKI: %u Hz)\n",
audio_domain == J721E_AUDIO_DOMAIN_CPB ? "CPB" : "IVI", audio_domain == J721E_AUDIO_DOMAIN_CPB ? "CPB" : "IVI",
@ -278,23 +278,29 @@ static int j721e_audio_startup(struct snd_pcm_substream *substream)
j721e_rule_rate, &priv->rate_range, j721e_rule_rate, &priv->rate_range,
SNDRV_PCM_HW_PARAM_RATE, -1); SNDRV_PCM_HW_PARAM_RATE, -1);
mutex_unlock(&priv->mutex);
if (ret) if (ret)
return ret; goto out;
/* Reset TDM slots to 32 */ /* Reset TDM slots to 32 */
ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 2, 32); ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 2, 32);
if (ret && ret != -ENOTSUPP) if (ret && ret != -ENOTSUPP)
return ret; goto out;
for_each_rtd_codec_dais(rtd, i, codec_dai) { for_each_rtd_codec_dais(rtd, i, codec_dai) {
ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x3, 0x3, 2, 32); ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x3, 0x3, 2, 32);
if (ret && ret != -ENOTSUPP) if (ret && ret != -ENOTSUPP)
return ret; goto out;
} }
return 0; if (ret == -ENOTSUPP)
ret = 0;
out:
if (ret)
domain->active--;
mutex_unlock(&priv->mutex);
return ret;
} }
static int j721e_audio_hw_params(struct snd_pcm_substream *substream, static int j721e_audio_hw_params(struct snd_pcm_substream *substream,

View File

@ -907,7 +907,7 @@ static void usb_audio_disconnect(struct usb_interface *intf)
} }
} }
if (chip->quirk_type & QUIRK_SETUP_DISABLE_AUTOSUSPEND) if (chip->quirk_type == QUIRK_SETUP_DISABLE_AUTOSUSPEND)
usb_enable_autosuspend(interface_to_usbdev(intf)); usb_enable_autosuspend(interface_to_usbdev(intf));
chip->num_interfaces--; chip->num_interfaces--;

View File

@ -324,6 +324,12 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
sources[ret - 1], sources[ret - 1],
visited, validate); visited, validate);
if (ret > 0) { if (ret > 0) {
/*
* For Samsung USBC Headset (AKG), setting clock selector again
* will result in incorrect default clock setting problems
*/
if (chip->usb_id == USB_ID(0x04e8, 0xa051))
return ret;
err = uac_clock_selector_set_val(chip, entity_id, cur); err = uac_clock_selector_set_val(chip, entity_id, cur);
if (err < 0) if (err < 0)
return err; return err;

View File

@ -1816,6 +1816,15 @@ static void get_connector_control_name(struct usb_mixer_interface *mixer,
strlcat(name, " - Output Jack", name_size); strlcat(name, " - Output Jack", name_size);
} }
/* get connector value to "wake up" the USB audio */
static int connector_mixer_resume(struct usb_mixer_elem_list *list)
{
struct usb_mixer_elem_info *cval = mixer_elem_list_to_info(list);
get_connector_value(cval, NULL, NULL);
return 0;
}
/* Build a mixer control for a UAC connector control (jack-detect) */ /* Build a mixer control for a UAC connector control (jack-detect) */
static void build_connector_control(struct usb_mixer_interface *mixer, static void build_connector_control(struct usb_mixer_interface *mixer,
const struct usbmix_name_map *imap, const struct usbmix_name_map *imap,
@ -1833,6 +1842,10 @@ static void build_connector_control(struct usb_mixer_interface *mixer,
if (!cval) if (!cval)
return; return;
snd_usb_mixer_elem_init_std(&cval->head, mixer, term->id); snd_usb_mixer_elem_init_std(&cval->head, mixer, term->id);
/* set up a specific resume callback */
cval->head.resume = connector_mixer_resume;
/* /*
* UAC2: The first byte from reading the UAC2_TE_CONNECTOR control returns the * UAC2: The first byte from reading the UAC2_TE_CONNECTOR control returns the
* number of channels connected. * number of channels connected.
@ -3295,7 +3308,15 @@ static void snd_usb_mixer_dump_cval(struct snd_info_buffer *buffer,
{ {
struct usb_mixer_elem_info *cval = mixer_elem_list_to_info(list); struct usb_mixer_elem_info *cval = mixer_elem_list_to_info(list);
static const char * const val_types[] = { static const char * const val_types[] = {
"BOOLEAN", "INV_BOOLEAN", "S8", "U8", "S16", "U16", "S32", "U32", [USB_MIXER_BOOLEAN] = "BOOLEAN",
[USB_MIXER_INV_BOOLEAN] = "INV_BOOLEAN",
[USB_MIXER_S8] = "S8",
[USB_MIXER_U8] = "U8",
[USB_MIXER_S16] = "S16",
[USB_MIXER_U16] = "U16",
[USB_MIXER_S32] = "S32",
[USB_MIXER_U32] = "U32",
[USB_MIXER_BESPOKEN] = "BESPOKEN",
}; };
snd_iprintf(buffer, " Info: id=%i, control=%i, cmask=0x%x, " snd_iprintf(buffer, " Info: id=%i, control=%i, cmask=0x%x, "
"channels=%i, type=\"%s\"\n", cval->head.id, "channels=%i, type=\"%s\"\n", cval->head.id,
@ -3634,23 +3655,15 @@ static int restore_mixer_value(struct usb_mixer_elem_list *list)
return 0; return 0;
} }
static int default_mixer_resume(struct usb_mixer_elem_list *list)
{
struct usb_mixer_elem_info *cval = mixer_elem_list_to_info(list);
/* get connector value to "wake up" the USB audio */
if (cval->val_type == USB_MIXER_BOOLEAN && cval->channels == 1)
get_connector_value(cval, NULL, NULL);
return 0;
}
static int default_mixer_reset_resume(struct usb_mixer_elem_list *list) static int default_mixer_reset_resume(struct usb_mixer_elem_list *list)
{ {
int err = default_mixer_resume(list); int err;
if (err < 0) if (list->resume) {
return err; err = list->resume(list);
if (err < 0)
return err;
}
return restore_mixer_value(list); return restore_mixer_value(list);
} }
@ -3689,7 +3702,7 @@ void snd_usb_mixer_elem_init_std(struct usb_mixer_elem_list *list,
list->id = unitid; list->id = unitid;
list->dump = snd_usb_mixer_dump_cval; list->dump = snd_usb_mixer_dump_cval;
#ifdef CONFIG_PM #ifdef CONFIG_PM
list->resume = default_mixer_resume; list->resume = NULL;
list->reset_resume = default_mixer_reset_resume; list->reset_resume = default_mixer_reset_resume;
#endif #endif
} }

View File

@ -228,7 +228,7 @@ enum {
}; };
static const char *const scarlett2_dim_mute_names[SCARLETT2_DIM_MUTE_COUNT] = { static const char *const scarlett2_dim_mute_names[SCARLETT2_DIM_MUTE_COUNT] = {
"Mute", "Dim" "Mute Playback Switch", "Dim Playback Switch"
}; };
/* Description of each hardware port type: /* Description of each hardware port type:
@ -1856,9 +1856,15 @@ static int scarlett2_mute_ctl_get(struct snd_kcontrol *kctl,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
struct usb_mixer_elem_info *elem = kctl->private_data; struct usb_mixer_elem_info *elem = kctl->private_data;
struct scarlett2_data *private = elem->head.mixer->private_data; struct usb_mixer_interface *mixer = elem->head.mixer;
struct scarlett2_data *private = mixer->private_data;
int index = line_out_remap(private, elem->control); int index = line_out_remap(private, elem->control);
mutex_lock(&private->data_mutex);
if (private->vol_updated)
scarlett2_update_volumes(mixer);
mutex_unlock(&private->data_mutex);
ucontrol->value.integer.value[0] = private->mute_switch[index]; ucontrol->value.integer.value[0] = private->mute_switch[index];
return 0; return 0;
} }
@ -1955,10 +1961,12 @@ static void scarlett2_vol_ctl_set_writable(struct usb_mixer_interface *mixer,
~SNDRV_CTL_ELEM_ACCESS_WRITE; ~SNDRV_CTL_ELEM_ACCESS_WRITE;
} }
/* Notify of write bit change */ /* Notify of write bit and possible value change */
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO, snd_ctl_notify(card,
SNDRV_CTL_EVENT_MASK_VALUE | SNDRV_CTL_EVENT_MASK_INFO,
&private->vol_ctls[index]->id); &private->vol_ctls[index]->id);
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO, snd_ctl_notify(card,
SNDRV_CTL_EVENT_MASK_VALUE | SNDRV_CTL_EVENT_MASK_INFO,
&private->mute_ctls[index]->id); &private->mute_ctls[index]->id);
} }
@ -2530,14 +2538,18 @@ static int scarlett2_add_direct_monitor_ctl(struct usb_mixer_interface *mixer)
{ {
struct scarlett2_data *private = mixer->private_data; struct scarlett2_data *private = mixer->private_data;
const struct scarlett2_device_info *info = private->info; const struct scarlett2_device_info *info = private->info;
const char *s;
if (!info->direct_monitor) if (!info->direct_monitor)
return 0; return 0;
s = info->direct_monitor == 1
? "Direct Monitor Playback Switch"
: "Direct Monitor Playback Enum";
return scarlett2_add_new_ctl( return scarlett2_add_new_ctl(
mixer, &scarlett2_direct_monitor_ctl[info->direct_monitor - 1], mixer, &scarlett2_direct_monitor_ctl[info->direct_monitor - 1],
0, 1, "Direct Monitor Playback Switch", 0, 1, s, &private->direct_monitor_ctl);
&private->direct_monitor_ctl);
} }
/*** Speaker Switching Control ***/ /*** Speaker Switching Control ***/
@ -2589,7 +2601,9 @@ static int scarlett2_speaker_switch_enable(struct usb_mixer_interface *mixer)
/* disable the line out SW/HW switch */ /* disable the line out SW/HW switch */
scarlett2_sw_hw_ctl_ro(private, i); scarlett2_sw_hw_ctl_ro(private, i);
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO, snd_ctl_notify(card,
SNDRV_CTL_EVENT_MASK_VALUE |
SNDRV_CTL_EVENT_MASK_INFO,
&private->sw_hw_ctls[i]->id); &private->sw_hw_ctls[i]->id);
} }
@ -2913,7 +2927,7 @@ static int scarlett2_dim_mute_ctl_put(struct snd_kcontrol *kctl,
if (private->vol_sw_hw_switch[line_index]) { if (private->vol_sw_hw_switch[line_index]) {
private->mute_switch[line_index] = val; private->mute_switch[line_index] = val;
snd_ctl_notify(mixer->chip->card, snd_ctl_notify(mixer->chip->card,
SNDRV_CTL_EVENT_MASK_INFO, SNDRV_CTL_EVENT_MASK_VALUE,
&private->mute_ctls[i]->id); &private->mute_ctls[i]->id);
} }
} }
@ -3455,7 +3469,7 @@ static int scarlett2_add_msd_ctl(struct usb_mixer_interface *mixer)
/* Add MSD control */ /* Add MSD control */
return scarlett2_add_new_ctl(mixer, &scarlett2_msd_ctl, return scarlett2_add_new_ctl(mixer, &scarlett2_msd_ctl,
0, 1, "MSD Mode", NULL); 0, 1, "MSD Mode Switch", NULL);
} }
/*** Cleanup/Suspend Callbacks ***/ /*** Cleanup/Suspend Callbacks ***/

View File

@ -1897,6 +1897,10 @@ static const struct registration_quirk registration_quirks[] = {
REG_QUIRK_ENTRY(0x0951, 0x16d8, 2), /* Kingston HyperX AMP */ REG_QUIRK_ENTRY(0x0951, 0x16d8, 2), /* Kingston HyperX AMP */
REG_QUIRK_ENTRY(0x0951, 0x16ed, 2), /* Kingston HyperX Cloud Alpha S */ REG_QUIRK_ENTRY(0x0951, 0x16ed, 2), /* Kingston HyperX Cloud Alpha S */
REG_QUIRK_ENTRY(0x0951, 0x16ea, 2), /* Kingston HyperX Cloud Flight S */ REG_QUIRK_ENTRY(0x0951, 0x16ea, 2), /* Kingston HyperX Cloud Flight S */
REG_QUIRK_ENTRY(0x0ecb, 0x1f46, 2), /* JBL Quantum 600 */
REG_QUIRK_ENTRY(0x0ecb, 0x2039, 2), /* JBL Quantum 400 */
REG_QUIRK_ENTRY(0x0ecb, 0x203c, 2), /* JBL Quantum 600 */
REG_QUIRK_ENTRY(0x0ecb, 0x203e, 2), /* JBL Quantum 800 */
{ 0 } /* terminator */ { 0 } /* terminator */
}; };