Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ASoC: Merge fixes

Needed for new development.

+272 -130
+1 -1
MAINTAINERS
··· 16247 16247 16248 16248 QCOM AUDIO (ASoC) DRIVERS 16249 16249 M: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> 16250 - M: Banajit Goswami <bgoswami@codeaurora.org> 16250 + M: Banajit Goswami <bgoswami@quicinc.com> 16251 16251 L: alsa-devel@alsa-project.org (moderated for non-subscribers) 16252 16252 S: Supported 16253 16253 F: sound/soc/codecs/lpass-va-macro.c
+8 -7
drivers/base/regmap/regmap.c
··· 1880 1880 */ 1881 1881 bool regmap_can_raw_write(struct regmap *map) 1882 1882 { 1883 - return map->bus && map->bus->write && map->format.format_val && 1884 - map->format.format_reg; 1883 + return map->write && map->format.format_val && map->format.format_reg; 1885 1884 } 1886 1885 EXPORT_SYMBOL_GPL(regmap_can_raw_write); 1887 1886 ··· 2154 2155 size_t write_len; 2155 2156 int ret; 2156 2157 2157 - if (!map->bus) 2158 - return -EINVAL; 2159 - if (!map->bus->write) 2158 + if (!map->write) 2160 2159 return -ENOTSUPP; 2160 + 2161 2161 if (val_len % map->format.val_bytes) 2162 2162 return -EINVAL; 2163 2163 if (!IS_ALIGNED(reg, map->reg_stride)) ··· 2298 2300 * Some devices don't support bulk write, for them we have a series of 2299 2301 * single write operations. 2300 2302 */ 2301 - if (!map->bus || !map->format.parse_inplace) { 2303 + if (!map->write || !map->format.parse_inplace) { 2302 2304 map->lock(map->lock_arg); 2303 2305 for (i = 0; i < val_count; i++) { 2304 2306 unsigned int ival; ··· 2924 2926 size_t read_len; 2925 2927 int ret; 2926 2928 2929 + if (!map->read) 2930 + return -ENOTSUPP; 2931 + 2927 2932 if (val_len % map->format.val_bytes) 2928 2933 return -EINVAL; 2929 2934 if (!IS_ALIGNED(reg, map->reg_stride)) ··· 3040 3039 if (val_count == 0) 3041 3040 return -EINVAL; 3042 3041 3043 - if (map->format.parse_inplace && (vol || map->cache_type == REGCACHE_NONE)) { 3042 + if (map->read && map->format.parse_inplace && (vol || map->cache_type == REGCACHE_NONE)) { 3044 3043 ret = regmap_raw_read(map, reg, val, val_bytes * val_count); 3045 3044 if (ret != 0) 3046 3045 return ret;
+6 -6
sound/soc/codecs/cs35l41.c
··· 333 333 SOC_SINGLE("HW Noise Gate Enable", CS35L41_NG_CFG, 8, 63, 0), 334 334 SOC_SINGLE("HW Noise Gate Delay", CS35L41_NG_CFG, 4, 7, 0), 335 335 SOC_SINGLE("HW Noise Gate Threshold", CS35L41_NG_CFG, 0, 7, 0), 336 - SOC_SINGLE("Aux Noise Gate CH1 Enable", 336 + SOC_SINGLE("Aux Noise Gate CH1 Switch", 337 337 CS35L41_MIXER_NGATE_CH1_CFG, 16, 1, 0), 338 338 SOC_SINGLE("Aux Noise Gate CH1 Entry Delay", 339 339 CS35L41_MIXER_NGATE_CH1_CFG, 8, 15, 0), ··· 341 341 CS35L41_MIXER_NGATE_CH1_CFG, 0, 7, 0), 342 342 SOC_SINGLE("Aux Noise Gate CH2 Entry Delay", 343 343 CS35L41_MIXER_NGATE_CH2_CFG, 8, 15, 0), 344 - SOC_SINGLE("Aux Noise Gate CH2 Enable", 344 + SOC_SINGLE("Aux Noise Gate CH2 Switch", 345 345 CS35L41_MIXER_NGATE_CH2_CFG, 16, 1, 0), 346 346 SOC_SINGLE("Aux Noise Gate CH2 Threshold", 347 347 CS35L41_MIXER_NGATE_CH2_CFG, 0, 7, 0), 348 - SOC_SINGLE("SCLK Force", CS35L41_SP_FORMAT, CS35L41_SCLK_FRC_SHIFT, 1, 0), 349 - SOC_SINGLE("LRCLK Force", CS35L41_SP_FORMAT, CS35L41_LRCLK_FRC_SHIFT, 1, 0), 350 - SOC_SINGLE("Invert Class D", CS35L41_AMP_DIG_VOL_CTRL, 348 + SOC_SINGLE("SCLK Force Switch", CS35L41_SP_FORMAT, CS35L41_SCLK_FRC_SHIFT, 1, 0), 349 + SOC_SINGLE("LRCLK Force Switch", CS35L41_SP_FORMAT, CS35L41_LRCLK_FRC_SHIFT, 1, 0), 350 + SOC_SINGLE("Invert Class D Switch", CS35L41_AMP_DIG_VOL_CTRL, 351 351 CS35L41_AMP_INV_PCM_SHIFT, 1, 0), 352 - SOC_SINGLE("Amp Gain ZC", CS35L41_AMP_GAIN_CTRL, 352 + SOC_SINGLE("Amp Gain ZC Switch", CS35L41_AMP_GAIN_CTRL, 353 353 CS35L41_AMP_GAIN_ZC_SHIFT, 1, 0), 354 354 WM_ADSP2_PRELOAD_SWITCH("DSP1", 1), 355 355 WM_ADSP_FW_CONTROL("DSP1", 0),
+2 -2
sound/soc/codecs/rt711-sdca.c
··· 34 34 35 35 ret = regmap_write(regmap, addr, value); 36 36 if (ret < 0) 37 - dev_err(rt711->component->dev, 37 + dev_err(&rt711->slave->dev, 38 38 "Failed to set private value: %06x <= %04x ret=%d\n", 39 39 addr, value, ret); 40 40 ··· 50 50 51 51 ret = regmap_read(regmap, addr, value); 52 52 if (ret < 0) 53 - dev_err(rt711->component->dev, 53 + dev_err(&rt711->slave->dev, 54 54 "Failed to get private value: %06x => %04x ret=%d\n", 55 55 addr, *value, ret); 56 56
+6 -2
sound/soc/codecs/wm5110.c
··· 413 413 unsigned int rnew = (!!ucontrol->value.integer.value[1]) << mc->rshift; 414 414 unsigned int lold, rold; 415 415 unsigned int lena, rena; 416 + bool change = false; 416 417 int ret; 417 418 418 419 snd_soc_dapm_mutex_lock(dapm); ··· 441 440 goto err; 442 441 } 443 442 444 - ret = regmap_update_bits(arizona->regmap, ARIZONA_DRE_ENABLE, 445 - mask, lnew | rnew); 443 + ret = regmap_update_bits_check(arizona->regmap, ARIZONA_DRE_ENABLE, 444 + mask, lnew | rnew, &change); 446 445 if (ret) { 447 446 dev_err(arizona->dev, "Failed to set DRE: %d\n", ret); 448 447 goto err; ··· 454 453 455 454 if (!rnew && rold) 456 455 wm5110_clear_pga_volume(arizona, mc->rshift); 456 + 457 + if (change) 458 + ret = 1; 457 459 458 460 err: 459 461 snd_soc_dapm_mutex_unlock(dapm);
+1 -1
sound/soc/codecs/wm_adsp.c
··· 997 997 snd_soc_dapm_sync(dapm); 998 998 } 999 999 1000 - return 0; 1000 + return 1; 1001 1001 } 1002 1002 EXPORT_SYMBOL_GPL(wm_adsp2_preloader_put); 1003 1003
+129 -31
sound/soc/rockchip/rockchip_i2s.c
··· 13 13 #include <linux/of_gpio.h> 14 14 #include <linux/of_device.h> 15 15 #include <linux/clk.h> 16 + #include <linux/pinctrl/consumer.h> 16 17 #include <linux/pm_runtime.h> 17 18 #include <linux/regmap.h> 18 19 #include <linux/spinlock.h> ··· 55 54 const struct rk_i2s_pins *pins; 56 55 unsigned int bclk_ratio; 57 56 spinlock_t lock; /* tx/rx lock */ 57 + struct pinctrl *pinctrl; 58 + struct pinctrl_state *bclk_on; 59 + struct pinctrl_state *bclk_off; 58 60 }; 61 + 62 + static int i2s_pinctrl_select_bclk_on(struct rk_i2s_dev *i2s) 63 + { 64 + int ret = 0; 65 + 66 + if (!IS_ERR(i2s->pinctrl) && !IS_ERR_OR_NULL(i2s->bclk_on)) 67 + ret = pinctrl_select_state(i2s->pinctrl, 68 + i2s->bclk_on); 69 + 70 + if (ret) 71 + dev_err(i2s->dev, "bclk enable failed %d\n", ret); 72 + 73 + return ret; 74 + } 75 + 76 + static int i2s_pinctrl_select_bclk_off(struct rk_i2s_dev *i2s) 77 + { 78 + 79 + int ret = 0; 80 + 81 + if (!IS_ERR(i2s->pinctrl) && !IS_ERR_OR_NULL(i2s->bclk_off)) 82 + ret = pinctrl_select_state(i2s->pinctrl, 83 + i2s->bclk_off); 84 + 85 + if (ret) 86 + dev_err(i2s->dev, "bclk disable failed %d\n", ret); 87 + 88 + return ret; 89 + } 59 90 60 91 static int i2s_runtime_suspend(struct device *dev) 61 92 { ··· 125 92 return snd_soc_dai_get_drvdata(dai); 126 93 } 127 94 128 - static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on) 95 + static int rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on) 129 96 { 130 97 unsigned int val = 0; 131 98 int retry = 10; 99 + int ret = 0; 132 100 133 101 spin_lock(&i2s->lock); 134 102 if (on) { 135 - regmap_update_bits(i2s->regmap, I2S_DMACR, 136 - I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_ENABLE); 103 + ret = regmap_update_bits(i2s->regmap, I2S_DMACR, 104 + I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_ENABLE); 105 + if (ret < 0) 106 + goto end; 137 107 138 - regmap_update_bits(i2s->regmap, I2S_XFER, 139 - I2S_XFER_TXS_START | I2S_XFER_RXS_START, 140 - I2S_XFER_TXS_START | I2S_XFER_RXS_START); 108 + ret = regmap_update_bits(i2s->regmap, I2S_XFER, 109 + I2S_XFER_TXS_START | I2S_XFER_RXS_START, 110 + I2S_XFER_TXS_START | I2S_XFER_RXS_START); 111 + if (ret < 0) 112 + goto end; 141 113 142 114 i2s->tx_start = true; 143 115 } else { 144 116 i2s->tx_start = false; 145 117 146 - regmap_update_bits(i2s->regmap, I2S_DMACR, 147 - I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_DISABLE); 118 + ret = regmap_update_bits(i2s->regmap, I2S_DMACR, 119 + I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_DISABLE); 120 + if (ret < 0) 121 + goto end; 148 122 149 123 if (!i2s->rx_start) { 150 - regmap_update_bits(i2s->regmap, I2S_XFER, 151 - I2S_XFER_TXS_START | 152 - I2S_XFER_RXS_START, 153 - I2S_XFER_TXS_STOP | 154 - I2S_XFER_RXS_STOP); 124 + ret = regmap_update_bits(i2s->regmap, I2S_XFER, 125 + I2S_XFER_TXS_START | 126 + I2S_XFER_RXS_START, 127 + I2S_XFER_TXS_STOP | 128 + I2S_XFER_RXS_STOP); 129 + if (ret < 0) 130 + goto end; 155 131 156 132 udelay(150); 157 - regmap_update_bits(i2s->regmap, I2S_CLR, 158 - I2S_CLR_TXC | I2S_CLR_RXC, 159 - I2S_CLR_TXC | I2S_CLR_RXC); 133 + ret = regmap_update_bits(i2s->regmap, I2S_CLR, 134 + I2S_CLR_TXC | I2S_CLR_RXC, 135 + I2S_CLR_TXC | I2S_CLR_RXC); 136 + if (ret < 0) 137 + goto end; 160 138 161 139 regmap_read(i2s->regmap, I2S_CLR, &val); 162 140 ··· 182 138 } 183 139 } 184 140 } 141 + end: 185 142 spin_unlock(&i2s->lock); 143 + if (ret < 0) 144 + dev_err(i2s->dev, "lrclk update failed\n"); 145 + 146 + return ret; 186 147 } 187 148 188 - static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on) 149 + static int rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on) 189 150 { 190 151 unsigned int val = 0; 191 152 int retry = 10; 153 + int ret = 0; 192 154 193 155 spin_lock(&i2s->lock); 194 156 if (on) { 195 - regmap_update_bits(i2s->regmap, I2S_DMACR, 157 + ret = regmap_update_bits(i2s->regmap, I2S_DMACR, 196 158 I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_ENABLE); 159 + if (ret < 0) 160 + goto end; 197 161 198 - regmap_update_bits(i2s->regmap, I2S_XFER, 162 + ret = regmap_update_bits(i2s->regmap, I2S_XFER, 199 163 I2S_XFER_TXS_START | I2S_XFER_RXS_START, 200 164 I2S_XFER_TXS_START | I2S_XFER_RXS_START); 165 + if (ret < 0) 166 + goto end; 201 167 202 168 i2s->rx_start = true; 203 169 } else { 204 170 i2s->rx_start = false; 205 171 206 - regmap_update_bits(i2s->regmap, I2S_DMACR, 172 + ret = regmap_update_bits(i2s->regmap, I2S_DMACR, 207 173 I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_DISABLE); 174 + if (ret < 0) 175 + goto end; 208 176 209 177 if (!i2s->tx_start) { 210 - regmap_update_bits(i2s->regmap, I2S_XFER, 178 + ret = regmap_update_bits(i2s->regmap, I2S_XFER, 211 179 I2S_XFER_TXS_START | 212 180 I2S_XFER_RXS_START, 213 181 I2S_XFER_TXS_STOP | 214 182 I2S_XFER_RXS_STOP); 215 - 183 + if (ret < 0) 184 + goto end; 216 185 udelay(150); 217 - regmap_update_bits(i2s->regmap, I2S_CLR, 186 + ret = regmap_update_bits(i2s->regmap, I2S_CLR, 218 187 I2S_CLR_TXC | I2S_CLR_RXC, 219 188 I2S_CLR_TXC | I2S_CLR_RXC); 220 - 189 + if (ret < 0) 190 + goto end; 221 191 regmap_read(i2s->regmap, I2S_CLR, &val); 222 - 223 192 /* Should wait for clear operation to finish */ 224 193 while (val) { 225 194 regmap_read(i2s->regmap, I2S_CLR, &val); ··· 244 187 } 245 188 } 246 189 } 190 + end: 247 191 spin_unlock(&i2s->lock); 192 + if (ret < 0) 193 + dev_err(i2s->dev, "lrclk update failed\n"); 194 + 195 + return ret; 248 196 } 249 197 250 198 static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai, ··· 487 425 case SNDRV_PCM_TRIGGER_RESUME: 488 426 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 489 427 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) 490 - rockchip_snd_rxctrl(i2s, 1); 428 + ret = rockchip_snd_rxctrl(i2s, 1); 491 429 else 492 - rockchip_snd_txctrl(i2s, 1); 430 + ret = rockchip_snd_txctrl(i2s, 1); 431 + /* Do not turn on bclk if lrclk open fails. */ 432 + if (ret < 0) 433 + return ret; 434 + i2s_pinctrl_select_bclk_on(i2s); 493 435 break; 494 436 case SNDRV_PCM_TRIGGER_SUSPEND: 495 437 case SNDRV_PCM_TRIGGER_STOP: 496 438 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 497 - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) 498 - rockchip_snd_rxctrl(i2s, 0); 499 - else 500 - rockchip_snd_txctrl(i2s, 0); 439 + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { 440 + if (!i2s->tx_start) 441 + i2s_pinctrl_select_bclk_off(i2s); 442 + ret = rockchip_snd_rxctrl(i2s, 0); 443 + } else { 444 + if (!i2s->rx_start) 445 + i2s_pinctrl_select_bclk_off(i2s); 446 + ret = rockchip_snd_txctrl(i2s, 0); 447 + } 501 448 break; 502 449 default: 503 450 ret = -EINVAL; ··· 807 736 } 808 737 809 738 i2s->bclk_ratio = 64; 739 + i2s->pinctrl = devm_pinctrl_get(&pdev->dev); 740 + if (IS_ERR(i2s->pinctrl)) 741 + dev_err(&pdev->dev, "failed to find i2s pinctrl\n"); 742 + 743 + i2s->bclk_on = pinctrl_lookup_state(i2s->pinctrl, 744 + "bclk_on"); 745 + if (IS_ERR_OR_NULL(i2s->bclk_on)) 746 + dev_err(&pdev->dev, "failed to find i2s default state\n"); 747 + else 748 + dev_dbg(&pdev->dev, "find i2s bclk state\n"); 749 + 750 + i2s->bclk_off = pinctrl_lookup_state(i2s->pinctrl, 751 + "bclk_off"); 752 + if (IS_ERR_OR_NULL(i2s->bclk_off)) 753 + dev_err(&pdev->dev, "failed to find i2s gpio state\n"); 754 + else 755 + dev_dbg(&pdev->dev, "find i2s bclk_off state\n"); 756 + 757 + i2s_pinctrl_select_bclk_off(i2s); 758 + 759 + i2s->playback_dma_data.addr = res->start + I2S_TXDR; 760 + i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 761 + i2s->playback_dma_data.maxburst = 4; 762 + 763 + i2s->capture_dma_data.addr = res->start + I2S_RXDR; 764 + i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 765 + i2s->capture_dma_data.maxburst = 4; 810 766 811 767 dev_set_drvdata(&pdev->dev, i2s); 812 768
+2 -1
sound/soc/sof/intel/hda-loader.c
··· 395 395 struct snd_dma_buffer dmab; 396 396 int ret, ret1, i; 397 397 398 - if (hda->imrboot_supported && !sdev->first_boot) { 398 + if (sdev->system_suspend_target < SOF_SUSPEND_S4 && 399 + hda->imrboot_supported && !sdev->first_boot) { 399 400 dev_dbg(sdev->dev, "IMR restore supported, booting from IMR directly\n"); 400 401 hda->boot_iteration = 0; 401 402 ret = hda_dsp_boot_imr(sdev);
+1 -73
sound/soc/sof/intel/hda-pcm.c
··· 192 192 goto found; 193 193 } 194 194 195 - switch (sof_hda_position_quirk) { 196 - case SOF_HDA_POSITION_QUIRK_USE_SKYLAKE_LEGACY: 197 - /* 198 - * This legacy code, inherited from the Skylake driver, 199 - * mixes DPIB registers and DPIB DDR updates and 200 - * does not seem to follow any known hardware recommendations. 201 - * It's not clear e.g. why there is a different flow 202 - * for capture and playback, the only information that matters is 203 - * what traffic class is used, and on all SOF-enabled platforms 204 - * only VC0 is supported so the work-around was likely not necessary 205 - * and quite possibly wrong. 206 - */ 207 - 208 - /* DPIB/posbuf position mode: 209 - * For Playback, Use DPIB register from HDA space which 210 - * reflects the actual data transferred. 211 - * For Capture, Use the position buffer for pointer, as DPIB 212 - * is not accurate enough, its update may be completed 213 - * earlier than the data written to DDR. 214 - */ 215 - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 216 - pos = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, 217 - AZX_REG_VS_SDXDPIB_XBASE + 218 - (AZX_REG_VS_SDXDPIB_XINTERVAL * 219 - hstream->index)); 220 - } else { 221 - /* 222 - * For capture stream, we need more workaround to fix the 223 - * position incorrect issue: 224 - * 225 - * 1. Wait at least 20us before reading position buffer after 226 - * the interrupt generated(IOC), to make sure position update 227 - * happens on frame boundary i.e. 20.833uSec for 48KHz. 228 - * 2. Perform a dummy Read to DPIB register to flush DMA 229 - * position value. 230 - * 3. Read the DMA Position from posbuf. Now the readback 231 - * value should be >= period boundary. 232 - */ 233 - usleep_range(20, 21); 234 - snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, 235 - AZX_REG_VS_SDXDPIB_XBASE + 236 - (AZX_REG_VS_SDXDPIB_XINTERVAL * 237 - hstream->index)); 238 - pos = snd_hdac_stream_get_pos_posbuf(hstream); 239 - } 240 - break; 241 - case SOF_HDA_POSITION_QUIRK_USE_DPIB_REGISTERS: 242 - /* 243 - * In case VC1 traffic is disabled this is the recommended option 244 - */ 245 - pos = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, 246 - AZX_REG_VS_SDXDPIB_XBASE + 247 - (AZX_REG_VS_SDXDPIB_XINTERVAL * 248 - hstream->index)); 249 - break; 250 - case SOF_HDA_POSITION_QUIRK_USE_DPIB_DDR_UPDATE: 251 - /* 252 - * This is the recommended option when VC1 is enabled. 253 - * While this isn't needed for SOF platforms it's added for 254 - * consistency and debug. 255 - */ 256 - pos = snd_hdac_stream_get_pos_posbuf(hstream); 257 - break; 258 - default: 259 - dev_err_once(sdev->dev, "hda_position_quirk value %d not supported\n", 260 - sof_hda_position_quirk); 261 - pos = 0; 262 - break; 263 - } 264 - 265 - if (pos >= hstream->bufsize) 266 - pos = 0; 267 - 195 + pos = hda_dsp_stream_get_position(hstream, substream->stream, true); 268 196 found: 269 197 pos = bytes_to_frames(substream->runtime, pos); 270 198
+90 -4
sound/soc/sof/intel/hda-stream.c
··· 707 707 } 708 708 709 709 static void 710 - hda_dsp_set_bytes_transferred(struct hdac_stream *hstream, u64 buffer_size) 710 + hda_dsp_compr_bytes_transferred(struct hdac_stream *hstream, int direction) 711 711 { 712 + u64 buffer_size = hstream->bufsize; 712 713 u64 prev_pos, pos, num_bytes; 713 714 714 715 div64_u64_rem(hstream->curr_pos, buffer_size, &prev_pos); 715 - pos = snd_hdac_stream_get_pos_posbuf(hstream); 716 + pos = hda_dsp_stream_get_position(hstream, direction, false); 716 717 717 718 if (pos < prev_pos) 718 719 num_bytes = (buffer_size - prev_pos) + pos; ··· 749 748 if (s->substream && sof_hda->no_ipc_position) { 750 749 snd_sof_pcm_period_elapsed(s->substream); 751 750 } else if (s->cstream) { 752 - hda_dsp_set_bytes_transferred(s, 753 - s->cstream->runtime->buffer_size); 751 + hda_dsp_compr_bytes_transferred(s, s->cstream->direction); 754 752 snd_compr_fragment_elapsed(s->cstream); 755 753 } 756 754 } ··· 1008 1008 hext_stream); 1009 1009 devm_kfree(sdev->dev, hda_stream); 1010 1010 } 1011 + } 1012 + 1013 + snd_pcm_uframes_t hda_dsp_stream_get_position(struct hdac_stream *hstream, 1014 + int direction, bool can_sleep) 1015 + { 1016 + struct hdac_ext_stream *hext_stream = stream_to_hdac_ext_stream(hstream); 1017 + struct sof_intel_hda_stream *hda_stream = hstream_to_sof_hda_stream(hext_stream); 1018 + struct snd_sof_dev *sdev = hda_stream->sdev; 1019 + snd_pcm_uframes_t pos; 1020 + 1021 + switch (sof_hda_position_quirk) { 1022 + case SOF_HDA_POSITION_QUIRK_USE_SKYLAKE_LEGACY: 1023 + /* 1024 + * This legacy code, inherited from the Skylake driver, 1025 + * mixes DPIB registers and DPIB DDR updates and 1026 + * does not seem to follow any known hardware recommendations. 1027 + * It's not clear e.g. why there is a different flow 1028 + * for capture and playback, the only information that matters is 1029 + * what traffic class is used, and on all SOF-enabled platforms 1030 + * only VC0 is supported so the work-around was likely not necessary 1031 + * and quite possibly wrong. 1032 + */ 1033 + 1034 + /* DPIB/posbuf position mode: 1035 + * For Playback, Use DPIB register from HDA space which 1036 + * reflects the actual data transferred. 1037 + * For Capture, Use the position buffer for pointer, as DPIB 1038 + * is not accurate enough, its update may be completed 1039 + * earlier than the data written to DDR. 1040 + */ 1041 + if (direction == SNDRV_PCM_STREAM_PLAYBACK) { 1042 + pos = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, 1043 + AZX_REG_VS_SDXDPIB_XBASE + 1044 + (AZX_REG_VS_SDXDPIB_XINTERVAL * 1045 + hstream->index)); 1046 + } else { 1047 + /* 1048 + * For capture stream, we need more workaround to fix the 1049 + * position incorrect issue: 1050 + * 1051 + * 1. Wait at least 20us before reading position buffer after 1052 + * the interrupt generated(IOC), to make sure position update 1053 + * happens on frame boundary i.e. 20.833uSec for 48KHz. 1054 + * 2. Perform a dummy Read to DPIB register to flush DMA 1055 + * position value. 1056 + * 3. Read the DMA Position from posbuf. Now the readback 1057 + * value should be >= period boundary. 1058 + */ 1059 + if (can_sleep) 1060 + usleep_range(20, 21); 1061 + 1062 + snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, 1063 + AZX_REG_VS_SDXDPIB_XBASE + 1064 + (AZX_REG_VS_SDXDPIB_XINTERVAL * 1065 + hstream->index)); 1066 + pos = snd_hdac_stream_get_pos_posbuf(hstream); 1067 + } 1068 + break; 1069 + case SOF_HDA_POSITION_QUIRK_USE_DPIB_REGISTERS: 1070 + /* 1071 + * In case VC1 traffic is disabled this is the recommended option 1072 + */ 1073 + pos = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, 1074 + AZX_REG_VS_SDXDPIB_XBASE + 1075 + (AZX_REG_VS_SDXDPIB_XINTERVAL * 1076 + hstream->index)); 1077 + break; 1078 + case SOF_HDA_POSITION_QUIRK_USE_DPIB_DDR_UPDATE: 1079 + /* 1080 + * This is the recommended option when VC1 is enabled. 1081 + * While this isn't needed for SOF platforms it's added for 1082 + * consistency and debug. 1083 + */ 1084 + pos = snd_hdac_stream_get_pos_posbuf(hstream); 1085 + break; 1086 + default: 1087 + dev_err_once(sdev->dev, "hda_position_quirk value %d not supported\n", 1088 + sof_hda_position_quirk); 1089 + pos = 0; 1090 + break; 1091 + } 1092 + 1093 + if (pos >= hstream->bufsize) 1094 + pos = 0; 1095 + 1096 + return pos; 1011 1097 }
+3
sound/soc/sof/intel/hda.h
··· 565 565 bool hda_dsp_check_ipc_irq(struct snd_sof_dev *sdev); 566 566 bool hda_dsp_check_stream_irq(struct snd_sof_dev *sdev); 567 567 568 + snd_pcm_uframes_t hda_dsp_stream_get_position(struct hdac_stream *hstream, 569 + int direction, bool can_sleep); 570 + 568 571 struct hdac_ext_stream * 569 572 hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction, u32 flags); 570 573 int hda_dsp_stream_put(struct snd_sof_dev *sdev, int direction, int stream_tag);
+1 -1
sound/soc/sof/mediatek/mt8186/mt8186.c
··· 392 392 PLATFORM_DEVID_NONE, 393 393 pdev, sizeof(*pdev)); 394 394 if (IS_ERR(priv->ipc_dev)) { 395 - ret = IS_ERR(priv->ipc_dev); 395 + ret = PTR_ERR(priv->ipc_dev); 396 396 dev_err(sdev->dev, "failed to create mtk-adsp-ipc device\n"); 397 397 goto err_adsp_off; 398 398 }
+20 -1
sound/soc/sof/pm.c
··· 23 23 u32 target_dsp_state; 24 24 25 25 switch (sdev->system_suspend_target) { 26 + case SOF_SUSPEND_S5: 27 + case SOF_SUSPEND_S4: 28 + /* DSP should be in D3 if the system is suspending to S3+ */ 26 29 case SOF_SUSPEND_S3: 27 30 /* DSP should be in D3 if the system is suspending to S3 */ 28 31 target_dsp_state = SOF_DSP_PM_D3; ··· 338 335 return 0; 339 336 340 337 #if defined(CONFIG_ACPI) 341 - if (acpi_target_system_state() == ACPI_STATE_S0) 338 + switch (acpi_target_system_state()) { 339 + case ACPI_STATE_S0: 342 340 sdev->system_suspend_target = SOF_SUSPEND_S0IX; 341 + break; 342 + case ACPI_STATE_S1: 343 + case ACPI_STATE_S2: 344 + case ACPI_STATE_S3: 345 + sdev->system_suspend_target = SOF_SUSPEND_S3; 346 + break; 347 + case ACPI_STATE_S4: 348 + sdev->system_suspend_target = SOF_SUSPEND_S4; 349 + break; 350 + case ACPI_STATE_S5: 351 + sdev->system_suspend_target = SOF_SUSPEND_S5; 352 + break; 353 + default: 354 + break; 355 + } 343 356 #endif 344 357 345 358 return 0;
+2
sound/soc/sof/sof-priv.h
··· 91 91 SOF_SUSPEND_NONE = 0, 92 92 SOF_SUSPEND_S0IX, 93 93 SOF_SUSPEND_S3, 94 + SOF_SUSPEND_S4, 95 + SOF_SUSPEND_S5, 94 96 }; 95 97 96 98 enum sof_dfsentry_type {