struct snd_pcm_hw_params *params);
void asoc_simple_parse_convert(struct device_node *np, char *prefix,
struct asoc_simple_data *data);
+bool asoc_simple_is_convert_required(const struct asoc_simple_data *data);
int asoc_simple_parse_routing(struct snd_soc_card *card,
char *prefix);
config SND_SOC_TLV320ADC3XXX
tristate "Texas Instruments TLV320ADC3001/3101 audio ADC"
depends on I2C
+ depends on GPIOLIB
help
Enable support for Texas Instruments TLV320ADC3001 and TLV320ADC3101
ADCs.
#define CX2072X_PLBK_DRC_PARM_LEN 9
#define CX2072X_CLASSD_AMP_LEN 6
-/* DAI interfae type */
+/* DAI interface type */
#define CX2072X_DAI_HIFI 1
#define CX2072X_DAI_DSP 2
#define CX2072X_DAI_DSP_PWM 3 /* 4 ch, including mic and AEC */
dev_err(chip->dev, "read chip revision fail\n");
goto probe_fail;
}
+ pm_runtime_set_active(chip->dev);
+ pm_runtime_enable(chip->dev);
ret = devm_snd_soc_register_component(chip->dev,
&mt6660_component_driver,
&mt6660_codec_dai, 1);
- if (!ret) {
- pm_runtime_set_active(chip->dev);
- pm_runtime_enable(chip->dev);
- }
+ if (ret)
+ pm_runtime_disable(chip->dev);
return ret;
unsigned int rx_mask, int slots, int slot_width)
{
struct snd_soc_component *component = dai->component;
- unsigned int val = 0, rx_slotnum;
+ unsigned int cn = 0, cl = 0, rx_slotnum;
int ret = 0, first_bit;
switch (slots) {
case 4:
- val |= RT1019_I2S_TX_4CH;
+ cn = RT1019_I2S_TX_4CH;
break;
case 6:
- val |= RT1019_I2S_TX_6CH;
+ cn = RT1019_I2S_TX_6CH;
break;
case 8:
- val |= RT1019_I2S_TX_8CH;
+ cn = RT1019_I2S_TX_8CH;
break;
case 2:
break;
switch (slot_width) {
case 20:
- val |= RT1019_I2S_DL_20;
+ cl = RT1019_TDM_CL_20;
break;
case 24:
- val |= RT1019_I2S_DL_24;
+ cl = RT1019_TDM_CL_24;
break;
case 32:
- val |= RT1019_I2S_DL_32;
+ cl = RT1019_TDM_CL_32;
break;
case 8:
- val |= RT1019_I2S_DL_8;
+ cl = RT1019_TDM_CL_8;
break;
case 16:
break;
goto _set_tdm_err_;
}
+ snd_soc_component_update_bits(component, RT1019_TDM_1,
+ RT1019_TDM_CL_MASK, cl);
snd_soc_component_update_bits(component, RT1019_TDM_2,
- RT1019_I2S_CH_TX_MASK | RT1019_I2S_DF_MASK, val);
+ RT1019_I2S_CH_TX_MASK, cn);
_set_tdm_err_:
return ret;
#define RT1019_TDM_BCLK_MASK (0x1 << 6)
#define RT1019_TDM_BCLK_NORM (0x0 << 6)
#define RT1019_TDM_BCLK_INV (0x1 << 6)
+#define RT1019_TDM_CL_MASK (0x7)
+#define RT1019_TDM_CL_8 (0x4)
+#define RT1019_TDM_CL_32 (0x3)
+#define RT1019_TDM_CL_24 (0x2)
+#define RT1019_TDM_CL_20 (0x1)
+#define RT1019_TDM_CL_16 (0x0)
/* 0x0401 TDM Control-2 */
#define RT1019_I2S_CH_TX_MASK (0x3 << 6)
case 0x3008:
case 0x300a:
case 0xc000:
+ case 0xc710:
case 0xc860 ... 0xc863:
case 0xc870 ... 0xc873:
return true;
{
struct rt1308_sdw_priv *rt1308 = dev_get_drvdata(dev);
int ret = 0;
+ unsigned int tmp;
if (rt1308->hw_init)
return 0;
/* sw reset */
regmap_write(rt1308->regmap, RT1308_SDW_RESET, 0);
+ regmap_read(rt1308->regmap, 0xc710, &tmp);
+ rt1308->hw_ver = tmp;
+ dev_dbg(dev, "%s, hw_ver=0x%x\n", __func__, rt1308->hw_ver);
+
/* initial settings */
regmap_write(rt1308->regmap, 0xc103, 0xc0);
regmap_write(rt1308->regmap, 0xc030, 0x17);
regmap_write(rt1308->regmap, 0xc062, 0x05);
regmap_write(rt1308->regmap, 0xc171, 0x07);
regmap_write(rt1308->regmap, 0xc173, 0x0d);
- regmap_write(rt1308->regmap, 0xc311, 0x7f);
- regmap_write(rt1308->regmap, 0xc900, 0x90);
+ if (rt1308->hw_ver == RT1308_VER_C) {
+ regmap_write(rt1308->regmap, 0xc311, 0x7f);
+ regmap_write(rt1308->regmap, 0xc300, 0x09);
+ } else {
+ regmap_write(rt1308->regmap, 0xc311, 0x4f);
+ regmap_write(rt1308->regmap, 0xc300, 0x0b);
+ }
+ regmap_write(rt1308->regmap, 0xc900, 0x5a);
regmap_write(rt1308->regmap, 0xc1a0, 0x84);
regmap_write(rt1308->regmap, 0xc1a1, 0x01);
regmap_write(rt1308->regmap, 0xc360, 0x78);
regmap_write(rt1308->regmap, 0xc070, 0x00);
regmap_write(rt1308->regmap, 0xc100, 0xd7);
regmap_write(rt1308->regmap, 0xc101, 0xd7);
- regmap_write(rt1308->regmap, 0xc300, 0x09);
if (rt1308->first_hw_init) {
regcache_cache_bypass(rt1308->regmap, false);
{ 0x3005, 0x23 },
{ 0x3008, 0x02 },
{ 0x300a, 0x00 },
+ { 0xc000 | (RT1308_DATA_PATH << 4), 0x00 },
{ 0xc003 | (RT1308_DAC_SET << 4), 0x00 },
{ 0xc000 | (RT1308_POWER << 4), 0x00 },
{ 0xc001 | (RT1308_POWER << 4), 0x00 },
{ 0xc002 | (RT1308_POWER << 4), 0x00 },
+ { 0xc000 | (RT1308_POWER_STATUS << 4), 0x00 },
};
#define RT1308_SDW_OFFSET 0xc000
bool first_hw_init;
int rx_mask;
int slots;
+ int hw_ver;
};
struct sdw_stream_data {
RT1308_AIFS
};
+enum rt1308_hw_ver {
+ RT1308_VER_C = 2,
+ RT1308_VER_D
+};
+
#endif /* end of _RT1308_H_ */
unsigned int rx_mask, int slots, int slot_width)
{
struct snd_soc_component *component = dai->component;
- unsigned int cl, val = 0;
+ unsigned int cl, val = 0, tx_slotnum;
if (tx_mask || rx_mask)
snd_soc_component_update_bits(component,
snd_soc_component_update_bits(component,
RT5682S_TDM_ADDA_CTRL_2, RT5682S_TDM_EN, 0);
+ /* Tx slot configuration */
+ tx_slotnum = hweight_long(tx_mask);
+ if (tx_slotnum) {
+ if (tx_slotnum > slots) {
+ dev_err(component->dev, "Invalid or oversized Tx slots.\n");
+ return -EINVAL;
+ }
+ val |= (tx_slotnum - 1) << RT5682S_TDM_ADC_DL_SFT;
+ }
+
switch (slots) {
case 4:
val |= RT5682S_TDM_TX_CH_4;
}
snd_soc_component_update_bits(component, RT5682S_TDM_CTRL,
- RT5682S_TDM_TX_CH_MASK | RT5682S_TDM_RX_CH_MASK, val);
+ RT5682S_TDM_TX_CH_MASK | RT5682S_TDM_RX_CH_MASK |
+ RT5682S_TDM_ADC_DL_MASK, val);
switch (slot_width) {
case 8:
#define RT5682S_TDM_RX_CH_8 (0x3 << 8)
#define RT5682S_TDM_ADC_LCA_MASK (0x7 << 4)
#define RT5682S_TDM_ADC_LCA_SFT 4
+#define RT5682S_TDM_ADC_DL_MASK (0x3 << 0)
#define RT5682S_TDM_ADC_DL_SFT 0
/* TDM control 2 (0x007a) */
.of_match_table = tlv320adc3xxx_of_match,
},
.probe_new = adc3xxx_i2c_probe,
- .remove = adc3xxx_i2c_remove,
+ .remove = __exit_p(adc3xxx_i2c_remove),
.id_table = adc3xxx_i2c_id,
};
regmap_update_bits(arizona->regmap, wm5102_digital_vu[i],
WM5102_DIG_VU, WM5102_DIG_VU);
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_idle(&pdev->dev);
+
ret = arizona_request_irq(arizona, ARIZONA_IRQ_DSP_IRQ1,
"ADSP2 Compressed IRQ", wm5102_adsp2_irq,
wm5102);
goto err_spk_irqs;
}
- pm_runtime_enable(&pdev->dev);
- pm_runtime_idle(&pdev->dev);
-
return ret;
err_spk_irqs:
arizona_set_irq_wake(arizona, ARIZONA_IRQ_DSP_IRQ1, 0);
arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, wm5102);
err_jack_codec_dev:
+ pm_runtime_disable(&pdev->dev);
arizona_jack_codec_dev_remove(&wm5102->core);
return ret;
regmap_update_bits(arizona->regmap, wm5110_digital_vu[i],
WM5110_DIG_VU, WM5110_DIG_VU);
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_idle(&pdev->dev);
+
ret = arizona_request_irq(arizona, ARIZONA_IRQ_DSP_IRQ1,
"ADSP2 Compressed IRQ", wm5110_adsp2_irq,
wm5110);
goto err_spk_irqs;
}
- pm_runtime_enable(&pdev->dev);
- pm_runtime_idle(&pdev->dev);
-
return ret;
err_spk_irqs:
arizona_set_irq_wake(arizona, ARIZONA_IRQ_DSP_IRQ1, 0);
arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, wm5110);
err_jack_codec_dev:
+ pm_runtime_disable(&pdev->dev);
arizona_jack_codec_dev_remove(&wm5110->core);
return ret;
4, 1, 0, inmix_tlv),
};
+static int tp_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ int ret, reg, val, mask;
+ struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
+
+ ret = pm_runtime_resume_and_get(component->dev);
+ if (ret < 0) {
+ dev_err(component->dev, "Failed to resume device: %d\n", ret);
+ return ret;
+ }
+
+ reg = WM8962_ADDITIONAL_CONTROL_4;
+
+ if (!strcmp(w->name, "TEMP_HP")) {
+ mask = WM8962_TEMP_ENA_HP_MASK;
+ val = WM8962_TEMP_ENA_HP;
+ } else if (!strcmp(w->name, "TEMP_SPK")) {
+ mask = WM8962_TEMP_ENA_SPK_MASK;
+ val = WM8962_TEMP_ENA_SPK;
+ } else {
+ pm_runtime_put(component->dev);
+ return -EINVAL;
+ }
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMD:
+ val = 0;
+ fallthrough;
+ case SND_SOC_DAPM_POST_PMU:
+ ret = snd_soc_component_update_bits(component, reg, mask, val);
+ break;
+ default:
+ WARN(1, "Invalid event %d\n", event);
+ pm_runtime_put(component->dev);
+ return -EINVAL;
+ }
+
+ pm_runtime_put(component->dev);
+
+ return 0;
+}
+
static int cp_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
SND_SOC_DAPM_SUPPLY_S("DSP2", 1, WM8962_DSP2_POWER_MANAGEMENT,
WM8962_DSP2_ENA_SHIFT, 0, dsp2_event,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
-SND_SOC_DAPM_SUPPLY("TEMP_HP", WM8962_ADDITIONAL_CONTROL_4, 2, 0, NULL, 0),
-SND_SOC_DAPM_SUPPLY("TEMP_SPK", WM8962_ADDITIONAL_CONTROL_4, 1, 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("TEMP_HP", SND_SOC_NOPM, 0, 0, tp_event,
+ SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
+SND_SOC_DAPM_SUPPLY("TEMP_SPK", SND_SOC_NOPM, 0, 0, tp_event,
+ SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MIXER("INPGAL", WM8962_LEFT_INPUT_PGA_CONTROL, 4, 0,
inpgal, ARRAY_SIZE(inpgal)),
if (ret < 0)
goto err_pm_runtime;
+ regmap_update_bits(wm8962->regmap, WM8962_ADDITIONAL_CONTROL_4,
+ WM8962_TEMP_ENA_HP_MASK, 0);
+ regmap_update_bits(wm8962->regmap, WM8962_ADDITIONAL_CONTROL_4,
+ WM8962_TEMP_ENA_SPK_MASK, 0);
+
regcache_cache_only(wm8962->regmap, true);
/* The drivers should power up as needed */
regmap_update_bits(arizona->regmap, wm8997_digital_vu[i],
WM8997_DIG_VU, WM8997_DIG_VU);
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_idle(&pdev->dev);
+
arizona_init_common(arizona);
ret = arizona_init_vol_limit(arizona);
goto err_spk_irqs;
}
- pm_runtime_enable(&pdev->dev);
- pm_runtime_idle(&pdev->dev);
-
return ret;
err_spk_irqs:
arizona_free_spk_irqs(arizona);
err_jack_codec_dev:
+ pm_runtime_disable(&pdev->dev);
arizona_jack_codec_dev_remove(&wm8997->core);
return ret;
* or has convert-xxx property
*/
if ((of_get_child_count(codec_port) > 1) ||
- (adata->convert_rate || adata->convert_channels))
+ asoc_simple_is_convert_required(adata))
return true;
return false;
}
EXPORT_SYMBOL_GPL(asoc_simple_parse_convert);
+/**
+ * asoc_simple_is_convert_required() - Query if HW param conversion was requested
+ * @data: Link data.
+ *
+ * Returns true if any HW param conversion was requested for this DAI link with
+ * any "convert-xxx" properties.
+ */
+bool asoc_simple_is_convert_required(const struct asoc_simple_data *data)
+{
+ return data->convert_rate ||
+ data->convert_channels ||
+ data->convert_sample_format;
+}
+EXPORT_SYMBOL_GPL(asoc_simple_is_convert_required);
+
int asoc_simple_parse_daifmt(struct device *dev,
struct device_node *node,
struct device_node *codec,
* or has convert-xxx property
*/
if (dpcm_selectable &&
- (num > 2 ||
- adata.convert_rate || adata.convert_channels)) {
+ (num > 2 || asoc_simple_is_convert_required(&adata))) {
/*
* np
* |1(CPU)|0(Codec) li->cpu
SOF_RT5682_SSP_AMP(2) |
SOF_RT5682_NUM_HDMIDEV(4)),
},
+ {
+ .callback = sof_rt5682_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Rex"),
+ },
+ .driver_data = (void *)(SOF_RT5682_MCLK_EN |
+ SOF_RT5682_SSP_CODEC(2) |
+ SOF_SPEAKER_AMP_PRESENT |
+ SOF_RT5682_SSP_AMP(0) |
+ SOF_RT5682_NUM_HDMIDEV(4)
+ ),
+ },
{}
};
SOF_SDW_PCH_DMIC |
RT711_JD1),
},
+ {
+ /* NUC15 LAPBC710 skews */
+ .callback = sof_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
+ DMI_MATCH(DMI_BOARD_NAME, "LAPBC710"),
+ },
+ .driver_data = (void *)(SOF_SDW_TGL_HDMI |
+ SOF_SDW_PCH_DMIC |
+ RT711_JD1),
+ },
/* TigerLake-SDCA devices */
{
.callback = sof_sdw_quirk_cb,
config SND_SOC_SC7180
tristate "SoC Machine driver for SC7180 boards"
depends on I2C && GPIOLIB
+ depends on SOUNDWIRE || SOUNDWIRE=n
select SND_SOC_QCOM_COMMON
select SND_SOC_LPASS_SC7180
select SND_SOC_MAX98357A
return true;
if (reg == LPASS_HDMI_TX_LEGACY_ADDR(v))
return true;
+ if (reg == LPASS_HDMI_TX_VBIT_CTL_ADDR(v))
+ return true;
for (i = 0; i < v->hdmi_rdma_channels; ++i) {
if (reg == LPAIF_HDMI_RDMACURR_REG(v, i))
return true;
+ if (reg == LPASS_HDMI_TX_DMA_ADDR(v, i))
+ return true;
+ if (reg == LPASS_HDMI_TX_CH_LSB_ADDR(v, i))
+ return true;
+ if (reg == LPASS_HDMI_TX_CH_MSB_ADDR(v, i))
+ return true;
}
return false;
}
int i;
for_each_rtd_components(rtd, i, component) {
- int ret = pm_runtime_resume_and_get(component->dev);
- if (ret < 0 && ret != -EACCES)
+ int ret = pm_runtime_get_sync(component->dev);
+ if (ret < 0 && ret != -EACCES) {
+ pm_runtime_put_noidle(component->dev);
return soc_component_ret(component, ret);
+ }
/* mark stream if succeeded */
soc_component_mark_push(component, stream, pm);
}
[SOF_INTEL_IPC4] = "intel/sof-ace-tplg",
},
.default_fw_filename = {
- [SOF_INTEL_IPC4] = "dsp_basefw.bin",
+ [SOF_INTEL_IPC4] = "sof-mtl.ri",
},
.nocodec_tplg_filename = "sof-mtl-nocodec.tplg",
.ops = &sof_mtl_ops,
int id;
u32 slot_offset;
void *log_buffer;
+ struct mutex buffer_lock; /* for log_buffer alloc/free */
u32 host_read_ptr;
u32 dsp_write_ptr;
/* pos update IPC arrived before the slot offset is known, queried */
struct sof_mtrace_core_data *core_data = inode->i_private;
int ret;
+ mutex_lock(&core_data->buffer_lock);
+
+ if (core_data->log_buffer) {
+ ret = -EBUSY;
+ goto out;
+ }
+
ret = debugfs_file_get(file->f_path.dentry);
if (unlikely(ret))
- return ret;
+ goto out;
core_data->log_buffer = kmalloc(SOF_MTRACE_SLOT_SIZE, GFP_KERNEL);
if (!core_data->log_buffer) {
debugfs_file_put(file->f_path.dentry);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto out;
}
ret = simple_open(inode, file);
debugfs_file_put(file->f_path.dentry);
}
+out:
+ mutex_unlock(&core_data->buffer_lock);
+
return ret;
}
debugfs_file_put(file->f_path.dentry);
+ mutex_lock(&core_data->buffer_lock);
kfree(core_data->log_buffer);
+ core_data->log_buffer = NULL;
+ mutex_unlock(&core_data->buffer_lock);
return 0;
}
struct sof_mtrace_core_data *core_data = &priv->cores[i];
init_waitqueue_head(&core_data->trace_sleep);
+ mutex_init(&core_data->buffer_lock);
core_data->sdev = sdev;
core_data->id = i;
}