Merge branch 'for-linus' into for-next
This commit is contained in:
Коммит
01099b1ad9
|
@ -114,7 +114,7 @@ properties:
|
|||
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
properties:
|
||||
patternProperties:
|
||||
port(@[0-9a-f]+)?:
|
||||
$ref: audio-graph-port.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
|
|
@ -712,6 +712,12 @@ struct snd_soc_dai_link {
|
|||
/* Do not create a PCM for this DAI link (Backend link) */
|
||||
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
|
||||
struct snd_soc_dobj dobj; /* For topology */
|
||||
#endif
|
||||
|
|
|
@ -261,7 +261,7 @@ static int snd_dma_continuous_mmap(struct snd_dma_buffer *dmab,
|
|||
struct vm_area_struct *area)
|
||||
{
|
||||
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_page_prot);
|
||||
}
|
||||
|
|
|
@ -246,12 +246,18 @@ static bool hw_support_mmap(struct snd_pcm_substream *substream)
|
|||
if (!(substream->runtime->hw.info & SNDRV_PCM_INFO_MMAP))
|
||||
return false;
|
||||
|
||||
if (substream->ops->mmap ||
|
||||
(substream->dma_buffer.dev.type != SNDRV_DMA_TYPE_DEV &&
|
||||
substream->dma_buffer.dev.type != SNDRV_DMA_TYPE_DEV_UC))
|
||||
if (substream->ops->mmap || substream->ops->page)
|
||||
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,
|
||||
|
@ -3669,6 +3675,8 @@ static vm_fault_t snd_pcm_mmap_data_fault(struct vm_fault *vmf)
|
|||
return VM_FAULT_SIGBUS;
|
||||
if (substream->ops->page)
|
||||
page = substream->ops->page(substream, offset);
|
||||
else if (!snd_pcm_get_dma_buf(substream))
|
||||
page = virt_to_page(runtime->dma_area + offset);
|
||||
else
|
||||
page = snd_sgbuf_get_page(snd_pcm_get_dma_buf(substream), offset);
|
||||
if (!page)
|
||||
|
|
|
@ -319,6 +319,10 @@ static const struct config_entry config_table[] = {
|
|||
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC,
|
||||
.device = 0x4b55,
|
||||
},
|
||||
{
|
||||
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC,
|
||||
.device = 0x4b58,
|
||||
},
|
||||
#endif
|
||||
|
||||
/* Alder Lake */
|
||||
|
|
|
@ -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);
|
||||
snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL & 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);
|
||||
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);
|
||||
|
||||
/* 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 + 1, mixR);
|
||||
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);
|
||||
snd_sbmixer_write(p->chip, SB_DSP4_PCM_DEV, mixL & 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);
|
||||
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);
|
||||
|
||||
/* 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 + 1, mixR);
|
||||
spin_unlock_irqrestore(&p->chip->mixer_lock, flags);
|
||||
|
|
|
@ -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[] = {
|
||||
SND_PCI_QUIRK(0x103c, 0x870f, "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),
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
|
@ -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, 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, 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, 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, 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, 0x1466, "Acer Aspire A515-56", ALC255_FIXUP_ACER_HEADPHONE_AND_MIC),
|
||||
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, 0x3176, "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, 0x3827, "Ideapad S740", ALC285_FIXUP_IDEAPAD_S740_COEF),
|
||||
SND_PCI_QUIRK(0x17aa, 0x3843, "Yoga 9i", ALC287_FIXUP_IDEAPAD_BASS_SPK_AMP),
|
||||
|
|
|
@ -576,6 +576,7 @@ static struct snd_soc_dai_link cz_dai_5682_98357[] = {
|
|||
| SND_SOC_DAIFMT_CBM_CFM,
|
||||
.init = cz_rt5682_init,
|
||||
.dpcm_playback = 1,
|
||||
.stop_dma_first = 1,
|
||||
.ops = &cz_rt5682_play_ops,
|
||||
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
|
||||
| SND_SOC_DAIFMT_CBM_CFM,
|
||||
.dpcm_capture = 1,
|
||||
.stop_dma_first = 1,
|
||||
.ops = &cz_rt5682_cap_ops,
|
||||
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
|
||||
| SND_SOC_DAIFMT_CBM_CFM,
|
||||
.dpcm_playback = 1,
|
||||
.stop_dma_first = 1,
|
||||
.ops = &cz_rt5682_max_play_ops,
|
||||
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
|
||||
| SND_SOC_DAIFMT_CBM_CFM,
|
||||
.dpcm_capture = 1,
|
||||
.stop_dma_first = 1,
|
||||
.ops = &cz_rt5682_dmic0_cap_ops,
|
||||
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
|
||||
| SND_SOC_DAIFMT_CBM_CFM,
|
||||
.dpcm_capture = 1,
|
||||
.stop_dma_first = 1,
|
||||
.ops = &cz_rt5682_dmic1_cap_ops,
|
||||
SND_SOC_DAILINK_REG(designware2, adau, platform),
|
||||
},
|
||||
|
|
|
@ -1325,7 +1325,7 @@ config SND_SOC_SSM2305
|
|||
high-efficiency mono Class-D audio power amplifiers.
|
||||
|
||||
config SND_SOC_SSM2518
|
||||
tristate
|
||||
tristate "Analog Devices SSM2518 Class-D Amplifier"
|
||||
depends on I2C
|
||||
|
||||
config SND_SOC_SSM2602
|
||||
|
@ -1557,6 +1557,7 @@ config SND_SOC_WCD934X
|
|||
Qualcomm SoCs like SDM845.
|
||||
|
||||
config SND_SOC_WCD938X
|
||||
depends on SND_SOC_WCD938X_SDW
|
||||
tristate
|
||||
|
||||
config SND_SOC_WCD938X_SDW
|
||||
|
@ -1813,11 +1814,6 @@ config SND_SOC_ZL38060
|
|||
which consists of a Digital Signal Processor (DSP), several Digital
|
||||
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
|
||||
config SND_SOC_LM4857
|
||||
tristate
|
||||
|
|
|
@ -1695,6 +1695,8 @@ static const struct regmap_config rt5631_regmap_config = {
|
|||
.reg_defaults = rt5631_reg,
|
||||
.num_reg_defaults = ARRAY_SIZE(rt5631_reg),
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
.use_single_read = true,
|
||||
.use_single_write = true,
|
||||
};
|
||||
|
||||
static int rt5631_i2c_probe(struct i2c_client *i2c,
|
||||
|
|
|
@ -973,10 +973,14 @@ int rt5682_headset_detect(struct snd_soc_component *component, int jack_insert)
|
|||
rt5682_enable_push_button_irq(component, false);
|
||||
snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_1,
|
||||
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,
|
||||
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,
|
||||
RT5682_PWR_ANLG_1, RT5682_PWR_VREF2, 0);
|
||||
snd_soc_component_update_bits(component, RT5682_PWR_ANLG_3,
|
||||
|
|
|
@ -1604,6 +1604,8 @@ static int aic31xx_i2c_probe(struct i2c_client *i2c,
|
|||
ret);
|
||||
return ret;
|
||||
}
|
||||
regcache_cache_only(aic31xx->regmap, true);
|
||||
|
||||
aic31xx->dev = &i2c->dev;
|
||||
aic31xx->irq = i2c->irq;
|
||||
|
||||
|
|
|
@ -151,8 +151,8 @@ struct aic31xx_pdata {
|
|||
#define AIC31XX_WORD_LEN_24BITS 0x02
|
||||
#define AIC31XX_WORD_LEN_32BITS 0x03
|
||||
#define AIC31XX_IFACE1_MASTER_MASK GENMASK(3, 2)
|
||||
#define AIC31XX_BCLK_MASTER BIT(2)
|
||||
#define AIC31XX_WCLK_MASTER BIT(3)
|
||||
#define AIC31XX_BCLK_MASTER BIT(3)
|
||||
#define AIC31XX_WCLK_MASTER BIT(2)
|
||||
|
||||
/* AIC31XX_DATA_OFFSET */
|
||||
#define AIC31XX_DATA_OFFSET_MASK GENMASK(7, 0)
|
||||
|
|
|
@ -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);
|
||||
/* -12dB min, 0.5dB steps */
|
||||
static DECLARE_TLV_DB_SCALE(tlv_adc_vol, -1200, 50, 0);
|
||||
|
||||
static DECLARE_TLV_DB_LINEAR(tlv_spk_vol, TLV_DB_GAIN_MUTE, 0);
|
||||
/* -6dB min, 1dB steps */
|
||||
static DECLARE_TLV_DB_SCALE(tlv_tas_driver_gain, -5850, 50, 0);
|
||||
static DECLARE_TLV_DB_SCALE(tlv_amp_vol, 0, 600, 1);
|
||||
|
||||
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[] = {
|
||||
SOC_DOUBLE_R_S_TLV("PCM Playback Volume", AIC32X4_LDACVOL,
|
||||
AIC32X4_LDACVOL, 0, -0x7f, 0x30, 7, 0, tlv_pcm),
|
||||
SOC_SINGLE_S8_TLV("PCM Playback Volume",
|
||||
AIC32X4_LDACVOL, -0x7f, 0x30, tlv_pcm),
|
||||
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,
|
||||
tlv_driver_gain),
|
||||
SOC_DOUBLE_R("HP DAC Playback Switch", AIC32X4_HPLGAIN,
|
||||
AIC32X4_HPLGAIN, 6, 0x01, 1),
|
||||
|
||||
SOC_SINGLE_TLV("HP Driver Gain Volume",
|
||||
AIC32X4_HPLGAIN, 0, 0x74, 1, tlv_tas_driver_gain),
|
||||
SOC_SINGLE("HP DAC Playback Switch", AIC32X4_HPLGAIN, 6, 1, 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_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[] = {
|
||||
|
|
|
@ -3317,13 +3317,6 @@ static int wcd938x_soc_codec_probe(struct snd_soc_component *component)
|
|||
(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_IRQ_HPHR_PDM_WD_INT);
|
||||
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]->wcd938x = wcd938x;
|
||||
wcd938x->sdw_priv[AIF1_PB]->slave_irq = wcd938x->virq;
|
||||
|
||||
wcd938x->txdev = wcd938x_sdw_device_get(wcd938x->txnode);
|
||||
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]->wcd938x = wcd938x;
|
||||
wcd938x->sdw_priv[AIF1_CAP]->slave_irq = wcd938x->virq;
|
||||
wcd938x->tx_sdw_dev = dev_to_sdw_dev(wcd938x->txdev);
|
||||
if (!wcd938x->tx_sdw_dev) {
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "%s: bad micbias pdata\n", __func__);
|
||||
|
|
|
@ -282,6 +282,7 @@
|
|||
/*
|
||||
* HALO_CCM_CORE_CONTROL
|
||||
*/
|
||||
#define HALO_CORE_RESET 0x00000200
|
||||
#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);
|
||||
|
||||
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))
|
||||
ret = -EFAULT;
|
||||
|
@ -3333,7 +3334,8 @@ static int wm_halo_start_core(struct wm_adsp *dsp)
|
|||
{
|
||||
return regmap_update_bits(dsp->regmap,
|
||||
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)
|
||||
|
|
|
@ -55,43 +55,68 @@ static int spk_init(struct snd_soc_pcm_runtime *rtd)
|
|||
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 j;
|
||||
|
||||
switch (cmd) {
|
||||
case SNDRV_PCM_TRIGGER_START:
|
||||
case SNDRV_PCM_TRIGGER_RESUME:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
||||
/* enable max98373 first */
|
||||
ret = max_98373_trigger(substream, cmd);
|
||||
if (ret < 0)
|
||||
break;
|
||||
/* set spk pin by playback only */
|
||||
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
|
||||
return 0;
|
||||
|
||||
ret = sdw_trigger(substream, cmd);
|
||||
break;
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||
ret = sdw_trigger(substream, cmd);
|
||||
if (ret < 0)
|
||||
break;
|
||||
cpu_dai = asoc_rtd_to_cpu(rtd, 0);
|
||||
for_each_rtd_codec_dais(rtd, j, codec_dai) {
|
||||
struct snd_soc_dapm_context *dapm =
|
||||
snd_soc_component_get_dapm(cpu_dai->component);
|
||||
char pin_name[16];
|
||||
|
||||
ret = max_98373_trigger(substream, cmd);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
snprintf(pin_name, ARRAY_SIZE(pin_name), "%s Spk",
|
||||
codec_dai->component->name_prefix);
|
||||
|
||||
if (enable)
|
||||
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 = {
|
||||
.startup = sdw_startup,
|
||||
.prepare = sdw_prepare,
|
||||
.trigger = max98373_sdw_trigger,
|
||||
.hw_free = sdw_hw_free,
|
||||
.prepare = mx8373_sdw_prepare,
|
||||
.trigger = sdw_trigger,
|
||||
.hw_free = mx8373_sdw_hw_free,
|
||||
.shutdown = sdw_shutdown,
|
||||
};
|
||||
|
||||
|
|
|
@ -1015,6 +1015,7 @@ out:
|
|||
|
||||
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 rollback = 0;
|
||||
|
||||
|
@ -1055,14 +1056,23 @@ start_err:
|
|||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||
ret = snd_soc_pcm_dai_trigger(substream, cmd, rollback);
|
||||
if (ret < 0)
|
||||
break;
|
||||
if (rtd->dai_link->stop_dma_first) {
|
||||
ret = snd_soc_pcm_component_trigger(substream, cmd, rollback);
|
||||
if (ret < 0)
|
||||
break;
|
||||
|
||||
ret = snd_soc_pcm_component_trigger(substream, cmd, rollback);
|
||||
if (ret < 0)
|
||||
break;
|
||||
ret = snd_soc_pcm_dai_trigger(substream, cmd, rollback);
|
||||
if (ret < 0)
|
||||
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);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -89,6 +89,7 @@ static const struct sof_dev_desc adls_desc = {
|
|||
static const struct sof_dev_desc adl_desc = {
|
||||
.machines = snd_soc_acpi_intel_adl_machines,
|
||||
.alt_machines = snd_soc_acpi_intel_adl_sdw_machines,
|
||||
.use_acpi_target_states = true,
|
||||
.resindex_lpe_base = 0,
|
||||
.resindex_pcicfg_base = -1,
|
||||
.resindex_imr_base = -1,
|
||||
|
|
|
@ -213,19 +213,19 @@ snd_pcm_uframes_t tegra_pcm_pointer(struct snd_soc_component *component,
|
|||
}
|
||||
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)
|
||||
{
|
||||
struct snd_pcm_substream *substream = pcm->streams[stream].substream;
|
||||
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)
|
||||
return -ENOMEM;
|
||||
|
||||
buf->private_data = NULL;
|
||||
buf->dev.type = SNDRV_DMA_TYPE_DEV;
|
||||
buf->dev.dev = pcm->card->dev;
|
||||
buf->dev.dev = dev;
|
||||
buf->bytes = size;
|
||||
|
||||
return 0;
|
||||
|
@ -244,31 +244,28 @@ static void tegra_pcm_deallocate_dma_buffer(struct snd_pcm *pcm, int stream)
|
|||
if (!buf->area)
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct snd_card *card = rtd->card->snd_card;
|
||||
struct snd_pcm *pcm = rtd->pcm;
|
||||
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)
|
||||
return ret;
|
||||
|
||||
if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
|
||||
ret = tegra_pcm_preallocate_dma_buffer(pcm,
|
||||
SNDRV_PCM_STREAM_PLAYBACK, size);
|
||||
ret = tegra_pcm_preallocate_dma_buffer(dev, pcm, SNDRV_PCM_STREAM_PLAYBACK, size);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
|
||||
ret = tegra_pcm_preallocate_dma_buffer(pcm,
|
||||
SNDRV_PCM_STREAM_CAPTURE, size);
|
||||
ret = tegra_pcm_preallocate_dma_buffer(dev, pcm, SNDRV_PCM_STREAM_CAPTURE, size);
|
||||
if (ret)
|
||||
goto err_free_play;
|
||||
}
|
||||
|
@ -284,7 +281,16 @@ err:
|
|||
int tegra_pcm_construct(struct snd_soc_component *component,
|
||||
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);
|
||||
|
||||
|
|
|
@ -197,7 +197,7 @@ static int j721e_configure_refclk(struct j721e_priv *priv,
|
|||
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,
|
||||
"%s configuration for %u Hz: %s, %dxFS (SCKI: %u Hz)\n",
|
||||
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,
|
||||
SNDRV_PCM_HW_PARAM_RATE, -1);
|
||||
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
goto out;
|
||||
|
||||
/* Reset TDM slots to 32 */
|
||||
ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 2, 32);
|
||||
if (ret && ret != -ENOTSUPP)
|
||||
return ret;
|
||||
goto out;
|
||||
|
||||
for_each_rtd_codec_dais(rtd, i, codec_dai) {
|
||||
ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x3, 0x3, 2, 32);
|
||||
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,
|
||||
|
|
|
@ -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));
|
||||
|
||||
chip->num_interfaces--;
|
||||
|
|
|
@ -324,6 +324,12 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
|
|||
sources[ret - 1],
|
||||
visited, validate);
|
||||
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);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
|
|
@ -1816,6 +1816,15 @@ static void get_connector_control_name(struct usb_mixer_interface *mixer,
|
|||
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) */
|
||||
static void build_connector_control(struct usb_mixer_interface *mixer,
|
||||
const struct usbmix_name_map *imap,
|
||||
|
@ -1833,6 +1842,10 @@ static void build_connector_control(struct usb_mixer_interface *mixer,
|
|||
if (!cval)
|
||||
return;
|
||||
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
|
||||
* 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);
|
||||
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, "
|
||||
"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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
int err = default_mixer_resume(list);
|
||||
int err;
|
||||
|
||||
if (err < 0)
|
||||
return err;
|
||||
if (list->resume) {
|
||||
err = list->resume(list);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
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->dump = snd_usb_mixer_dump_cval;
|
||||
#ifdef CONFIG_PM
|
||||
list->resume = default_mixer_resume;
|
||||
list->resume = NULL;
|
||||
list->reset_resume = default_mixer_reset_resume;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -228,7 +228,7 @@ enum {
|
|||
};
|
||||
|
||||
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:
|
||||
|
@ -1856,9 +1856,15 @@ static int scarlett2_mute_ctl_get(struct snd_kcontrol *kctl,
|
|||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
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);
|
||||
|
||||
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];
|
||||
return 0;
|
||||
}
|
||||
|
@ -1955,10 +1961,12 @@ static void scarlett2_vol_ctl_set_writable(struct usb_mixer_interface *mixer,
|
|||
~SNDRV_CTL_ELEM_ACCESS_WRITE;
|
||||
}
|
||||
|
||||
/* Notify of write bit change */
|
||||
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO,
|
||||
/* Notify of write bit and possible value change */
|
||||
snd_ctl_notify(card,
|
||||
SNDRV_CTL_EVENT_MASK_VALUE | SNDRV_CTL_EVENT_MASK_INFO,
|
||||
&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);
|
||||
}
|
||||
|
||||
|
@ -2530,14 +2538,18 @@ static int scarlett2_add_direct_monitor_ctl(struct usb_mixer_interface *mixer)
|
|||
{
|
||||
struct scarlett2_data *private = mixer->private_data;
|
||||
const struct scarlett2_device_info *info = private->info;
|
||||
const char *s;
|
||||
|
||||
if (!info->direct_monitor)
|
||||
return 0;
|
||||
|
||||
s = info->direct_monitor == 1
|
||||
? "Direct Monitor Playback Switch"
|
||||
: "Direct Monitor Playback Enum";
|
||||
|
||||
return scarlett2_add_new_ctl(
|
||||
mixer, &scarlett2_direct_monitor_ctl[info->direct_monitor - 1],
|
||||
0, 1, "Direct Monitor Playback Switch",
|
||||
&private->direct_monitor_ctl);
|
||||
0, 1, s, &private->direct_monitor_ctl);
|
||||
}
|
||||
|
||||
/*** 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 */
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -2913,7 +2927,7 @@ static int scarlett2_dim_mute_ctl_put(struct snd_kcontrol *kctl,
|
|||
if (private->vol_sw_hw_switch[line_index]) {
|
||||
private->mute_switch[line_index] = val;
|
||||
snd_ctl_notify(mixer->chip->card,
|
||||
SNDRV_CTL_EVENT_MASK_INFO,
|
||||
SNDRV_CTL_EVENT_MASK_VALUE,
|
||||
&private->mute_ctls[i]->id);
|
||||
}
|
||||
}
|
||||
|
@ -3455,7 +3469,7 @@ static int scarlett2_add_msd_ctl(struct usb_mixer_interface *mixer)
|
|||
|
||||
/* Add MSD control */
|
||||
return scarlett2_add_new_ctl(mixer, &scarlett2_msd_ctl,
|
||||
0, 1, "MSD Mode", NULL);
|
||||
0, 1, "MSD Mode Switch", NULL);
|
||||
}
|
||||
|
||||
/*** Cleanup/Suspend Callbacks ***/
|
||||
|
|
|
@ -1897,6 +1897,10 @@ static const struct registration_quirk registration_quirks[] = {
|
|||
REG_QUIRK_ENTRY(0x0951, 0x16d8, 2), /* Kingston HyperX AMP */
|
||||
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(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 */
|
||||
};
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче