diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index a9acce7b6cca..d9878173ff89 100644 --- a/sound/soc/codecs/rt5682.c +++ b/sound/soc/codecs/rt5682.c @@ -43,6 +43,7 @@ static const struct reg_sequence patch_list[] = { {RT5682_DAC_ADC_DIG_VOL1, 0xa020}, {RT5682_I2C_CTRL, 0x000f}, {RT5682_PLL2_INTERNAL, 0x8266}, + {RT5682_SAR_IL_CMD_3, 0x8365}, }; void rt5682_apply_patch_list(struct rt5682_priv *rt5682, struct device *dev) diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index bcf18bf15a02..e61d00486c65 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -1937,6 +1937,7 @@ static int wm_adsp_load(struct wm_adsp *dsp) mem = wm_adsp_find_region(dsp, type); if (!mem) { adsp_err(dsp, "No region of type: %x\n", type); + ret = -EINVAL; goto out_fw; } diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 9dadf6561444..f790514a147d 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -520,10 +520,10 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { .driver_data = (void *)(BYT_RT5640_IN1_MAP | BYT_RT5640_MCLK_EN), }, - { /* HP Pavilion x2 10-n000nd */ + { /* HP Pavilion x2 10-k0XX, 10-n0XX */ .matches = { - DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"), + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"), }, .driver_data = (void *)(BYT_RT5640_DMIC1_MAP | BYT_RT5640_JD_SRC_JD2_IN4N | @@ -532,6 +532,17 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { BYT_RT5640_SSP0_AIF1 | BYT_RT5640_MCLK_EN), }, + { /* HP Pavilion x2 10-p0XX */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP x2 Detachable 10-p0XX"), + }, + .driver_data = (void *)(BYT_RT5640_DMIC1_MAP | + BYT_RT5640_JD_SRC_JD1_IN4P | + BYT_RT5640_OVCD_TH_1500UA | + BYT_RT5640_OVCD_SF_0P75 | + BYT_RT5640_MCLK_EN), + }, { /* HP Stream 7 */ .matches = { DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index 9d17c87445a9..426235a217ec 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c @@ -263,28 +263,6 @@ static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream, return 0; } -static int lpass_cpu_daiops_prepare(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); - struct lpaif_i2sctl *i2sctl = drvdata->i2sctl; - unsigned int id = dai->driver->id; - int ret; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - ret = regmap_fields_write(i2sctl->spken, id, - LPAIF_I2SCTL_SPKEN_ENABLE); - } else { - ret = regmap_fields_write(i2sctl->micen, id, - LPAIF_I2SCTL_MICEN_ENABLE); - } - - if (ret) - dev_err(dai->dev, "error writing to i2sctl enable: %d\n", ret); - - return ret; -} - static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { @@ -292,6 +270,18 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream, struct lpaif_i2sctl *i2sctl = drvdata->i2sctl; unsigned int id = dai->driver->id; int ret = -EINVAL; + unsigned int val = 0; + + ret = regmap_read(drvdata->lpaif_map, + LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id), &val); + if (ret) { + dev_err(dai->dev, "error reading from i2sctl reg: %d\n", ret); + return ret; + } + if (val == LPAIF_I2SCTL_RESET_STATE) { + dev_err(dai->dev, "error in i2sctl register state\n"); + return -ENOTRECOVERABLE; + } switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -308,11 +298,14 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream, dev_err(dai->dev, "error writing to i2sctl reg: %d\n", ret); - ret = clk_enable(drvdata->mi2s_bit_clk[id]); - if (ret) { - dev_err(dai->dev, "error in enabling mi2s bit clk: %d\n", ret); - clk_disable(drvdata->mi2s_osr_clk[id]); - return ret; + if (drvdata->bit_clk_state[id] == LPAIF_BIT_CLK_DISABLE) { + ret = clk_enable(drvdata->mi2s_bit_clk[id]); + if (ret) { + dev_err(dai->dev, "error in enabling mi2s bit clk: %d\n", ret); + clk_disable(drvdata->mi2s_osr_clk[id]); + return ret; + } + drvdata->bit_clk_state[id] = LPAIF_BIT_CLK_ENABLE; } break; @@ -329,7 +322,10 @@ static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream, if (ret) dev_err(dai->dev, "error writing to i2sctl reg: %d\n", ret); - clk_disable(drvdata->mi2s_bit_clk[dai->driver->id]); + if (drvdata->bit_clk_state[id] == LPAIF_BIT_CLK_ENABLE) { + clk_disable(drvdata->mi2s_bit_clk[dai->driver->id]); + drvdata->bit_clk_state[id] = LPAIF_BIT_CLK_DISABLE; + } break; } @@ -341,7 +337,6 @@ const struct snd_soc_dai_ops asoc_qcom_lpass_cpu_dai_ops = { .startup = lpass_cpu_daiops_startup, .shutdown = lpass_cpu_daiops_shutdown, .hw_params = lpass_cpu_daiops_hw_params, - .prepare = lpass_cpu_daiops_prepare, .trigger = lpass_cpu_daiops_trigger, }; EXPORT_SYMBOL_GPL(asoc_qcom_lpass_cpu_dai_ops); @@ -459,16 +454,20 @@ static bool lpass_cpu_regmap_volatile(struct device *dev, unsigned int reg) struct lpass_variant *v = drvdata->variant; int i; + for (i = 0; i < v->i2s_ports; ++i) + if (reg == LPAIF_I2SCTL_REG(v, i)) + return true; for (i = 0; i < v->irq_ports; ++i) if (reg == LPAIF_IRQSTAT_REG(v, i)) return true; for (i = 0; i < v->rdma_channels; ++i) - if (reg == LPAIF_RDMACURR_REG(v, i)) + if (reg == LPAIF_RDMACURR_REG(v, i) || reg == LPAIF_RDMACTL_REG(v, i)) return true; for (i = 0; i < v->wrdma_channels; ++i) - if (reg == LPAIF_WRDMACURR_REG(v, i + v->wrdma_channel_start)) + if (reg == LPAIF_WRDMACURR_REG(v, i + v->wrdma_channel_start) || + reg == LPAIF_WRDMACTL_REG(v, i + v->wrdma_channel_start)) return true; return false; @@ -861,6 +860,7 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) PTR_ERR(drvdata->mi2s_bit_clk[dai_id])); return PTR_ERR(drvdata->mi2s_bit_clk[dai_id]); } + drvdata->bit_clk_state[dai_id] = LPAIF_BIT_CLK_DISABLE; } /* Allocation for i2sctl regmap fields */ diff --git a/sound/soc/qcom/lpass-lpaif-reg.h b/sound/soc/qcom/lpass-lpaif-reg.h index 08f3fe508b85..405542832e99 100644 --- a/sound/soc/qcom/lpass-lpaif-reg.h +++ b/sound/soc/qcom/lpass-lpaif-reg.h @@ -60,6 +60,13 @@ #define LPAIF_I2SCTL_BITWIDTH_24 1 #define LPAIF_I2SCTL_BITWIDTH_32 2 +#define LPAIF_BIT_CLK_DISABLE 0 +#define LPAIF_BIT_CLK_ENABLE 1 + +#define LPAIF_I2SCTL_RESET_STATE 0x003C0004 +#define LPAIF_DMACTL_RESET_STATE 0x00200000 + + /* LPAIF IRQ */ #define LPAIF_IRQ_REG_ADDR(v, addr, port) \ (v->irq_reg_base + (addr) + v->irq_reg_stride * (port)) diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c index 7a3fdf89968a..80b09dede5f9 100644 --- a/sound/soc/qcom/lpass-platform.c +++ b/sound/soc/qcom/lpass-platform.c @@ -110,6 +110,7 @@ static int lpass_platform_pcmops_open(struct snd_soc_component *component, struct regmap *map; unsigned int dai_id = cpu_dai->driver->id; + component->id = dai_id; data = kzalloc(sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; @@ -451,19 +452,34 @@ static int lpass_platform_pcmops_trigger(struct snd_soc_component *component, unsigned int reg_irqclr = 0, val_irqclr = 0; unsigned int reg_irqen = 0, val_irqen = 0, val_mask = 0; unsigned int dai_id = cpu_dai->driver->id; + unsigned int dma_ctrl_reg = 0; ch = pcm_data->dma_ch; if (dir == SNDRV_PCM_STREAM_PLAYBACK) { id = pcm_data->dma_ch; - if (dai_id == LPASS_DP_RX) + if (dai_id == LPASS_DP_RX) { dmactl = drvdata->hdmi_rd_dmactl; - else + map = drvdata->hdmiif_map; + } else { dmactl = drvdata->rd_dmactl; + map = drvdata->lpaif_map; + } } else { dmactl = drvdata->wr_dmactl; id = pcm_data->dma_ch - v->wrdma_channel_start; + map = drvdata->lpaif_map; + } + ret = regmap_read(map, LPAIF_DMACTL_REG(v, ch, dir, dai_id), &dma_ctrl_reg); + if (ret) { + dev_err(soc_runtime->dev, "error reading from rdmactl reg: %d\n", ret); + return ret; } + if (dma_ctrl_reg == LPAIF_DMACTL_RESET_STATE || + dma_ctrl_reg == LPAIF_DMACTL_RESET_STATE + 1) { + dev_err(soc_runtime->dev, "error in rdmactl register state\n"); + return -ENOTRECOVERABLE; + } switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: diff --git a/sound/soc/qcom/lpass.h b/sound/soc/qcom/lpass.h index b4830f353796..bccd1a05d771 100644 --- a/sound/soc/qcom/lpass.h +++ b/sound/soc/qcom/lpass.h @@ -68,6 +68,7 @@ struct lpass_data { unsigned int mi2s_playback_sd_mode[LPASS_MAX_MI2S_PORTS]; unsigned int mi2s_capture_sd_mode[LPASS_MAX_MI2S_PORTS]; int hdmi_port_enable; + int bit_clk_state[LPASS_MAX_MI2S_PORTS]; /* low-power audio interface (LPAIF) registers */ void __iomem *lpaif;