| .. | .. | 
|---|
| 1 |  | -// SPDX-License-Identifier: GPL-2.0 | 
|---|
|  | 1 | +// SPDX-License-Identifier: GPL-2.0-or-later | 
|---|
| 2 | 2 | /* | 
|---|
| 3 | 3 | * ALSA SoC Audio Layer - Rockchip Multi-DAIS-PCM driver | 
|---|
| 4 | 4 | * | 
|---|
| .. | .. | 
|---|
| 16 | 16 | #include <sound/soc.h> | 
|---|
| 17 | 17 |  | 
|---|
| 18 | 18 | #include "rockchip_multi_dais.h" | 
|---|
|  | 19 | +#include "rockchip_dlp.h" | 
|---|
| 19 | 20 |  | 
|---|
| 20 |  | -#define MAX_FIFO_SIZE	32 /* max fifo size in frames */ | 
|---|
| 21 |  | -#define SND_DMAENGINE_MPCM_DRV_NAME "snd_dmaengine_mpcm" | 
|---|
|  | 21 | +#define I2S_TXFIFOLR			0xc | 
|---|
|  | 22 | +#define I2S_RXFIFOLR			0x2c | 
|---|
|  | 23 | +#define SAI_TXFIFOLR			0x1c | 
|---|
|  | 24 | +#define SAI_RXFIFOLR			0x20 | 
|---|
|  | 25 | + | 
|---|
|  | 26 | +/* XFL4 is compatible for old version */ | 
|---|
|  | 27 | +#define I2S_FIFOLR_XFL4(v)		(((v) & GENMASK(29, 24)) >> 24) | 
|---|
|  | 28 | +#define I2S_FIFOLR_XFL3(v)		(((v) & GENMASK(23, 18)) >> 18) | 
|---|
|  | 29 | +#define I2S_FIFOLR_XFL2(v)		(((v) & GENMASK(17, 12)) >> 12) | 
|---|
|  | 30 | +#define I2S_FIFOLR_XFL1(v)		(((v) & GENMASK(11, 6)) >> 6) | 
|---|
|  | 31 | +#define I2S_FIFOLR_XFL0(v)		(((v) & GENMASK(5, 0)) >> 0) | 
|---|
|  | 32 | + | 
|---|
|  | 33 | +/* XFIFOLR: Transfer / Receive FIFO Level Register */ | 
|---|
|  | 34 | +#define SAI_FIFOLR_XFL3(v)		(((v) & GENMASK(23, 18)) >> 18) | 
|---|
|  | 35 | +#define SAI_FIFOLR_XFL2(v)		(((v) & GENMASK(17, 12)) >> 12) | 
|---|
|  | 36 | +#define SAI_FIFOLR_XFL1(v)		(((v) & GENMASK(11, 6)) >> 6) | 
|---|
|  | 37 | +#define SAI_FIFOLR_XFL0(v)		(((v) & GENMASK(5, 0)) >> 0) | 
|---|
|  | 38 | + | 
|---|
|  | 39 | +#define MAX_FIFO_SIZE			32 /* max fifo size in frames */ | 
|---|
|  | 40 | +#define SND_DMAENGINE_MPCM_DRV_NAME	"snd_dmaengine_mpcm" | 
|---|
|  | 41 | + | 
|---|
|  | 42 | +static unsigned int prealloc_buffer_size_kbytes = 512; | 
|---|
|  | 43 | +module_param(prealloc_buffer_size_kbytes, uint, 0444); | 
|---|
|  | 44 | +MODULE_PARM_DESC(prealloc_buffer_size_kbytes, "Preallocate DMA buffer size (KB)."); | 
|---|
| 22 | 45 |  | 
|---|
| 23 | 46 | struct dmaengine_mpcm { | 
|---|
|  | 47 | +	struct dlp dlp; | 
|---|
| 24 | 48 | struct rk_mdais_dev *mdais; | 
|---|
| 25 | 49 | struct dma_chan *tx_chans[MAX_DAIS]; | 
|---|
| 26 | 50 | struct dma_chan *rx_chans[MAX_DAIS]; | 
|---|
| 27 |  | -	struct snd_soc_component component; | 
|---|
| 28 | 51 | }; | 
|---|
| 29 | 52 |  | 
|---|
| 30 | 53 | struct dmaengine_mpcm_runtime_data { | 
|---|
|  | 54 | +	struct dlp_runtime_data drd; | 
|---|
| 31 | 55 | struct dma_chan *chans[MAX_DAIS]; | 
|---|
|  | 56 | +	struct dma_interleaved_template *xt; | 
|---|
| 32 | 57 | dma_cookie_t cookies[MAX_DAIS]; | 
|---|
| 33 | 58 | unsigned int *channel_maps; | 
|---|
| 34 | 59 | int num_chans; | 
|---|
| .. | .. | 
|---|
| 44 | 69 | static inline struct dmaengine_mpcm_runtime_data *substream_to_prtd( | 
|---|
| 45 | 70 | const struct snd_pcm_substream *substream) | 
|---|
| 46 | 71 | { | 
|---|
| 47 |  | -	return substream->runtime->private_data; | 
|---|
|  | 72 | +	struct dlp_runtime_data *drd = substream_to_drd(substream); | 
|---|
|  | 73 | + | 
|---|
|  | 74 | +	if (!drd) | 
|---|
|  | 75 | +		return NULL; | 
|---|
|  | 76 | + | 
|---|
|  | 77 | +	return container_of(drd, struct dmaengine_mpcm_runtime_data, drd); | 
|---|
| 48 | 78 | } | 
|---|
| 49 | 79 |  | 
|---|
| 50 | 80 | static struct dmaengine_mpcm *soc_component_to_mpcm(struct snd_soc_component *p) | 
|---|
| 51 | 81 | { | 
|---|
| 52 |  | -	return container_of(p, struct dmaengine_mpcm, component); | 
|---|
|  | 82 | +	return container_of(soc_component_to_dlp(p), struct dmaengine_mpcm, dlp); | 
|---|
| 53 | 83 | } | 
|---|
| 54 | 84 |  | 
|---|
| 55 | 85 | static struct dma_chan *to_chan(struct dmaengine_mpcm *pcm, | 
|---|
| .. | .. | 
|---|
| 101 | 131 | { | 
|---|
| 102 | 132 | struct snd_pcm_substream *substream = arg; | 
|---|
| 103 | 133 | #ifdef CONFIG_SND_SOC_ROCKCHIP_VAD | 
|---|
| 104 |  | -	struct dmaengine_mpcm_runtime_data *prtd = substream_to_prtd(substream); | 
|---|
|  | 134 | +	struct dmaengine_mpcm_runtime_data *prtd; | 
|---|
|  | 135 | +#endif | 
|---|
|  | 136 | +	struct dlp_runtime_data *drd; | 
|---|
|  | 137 | +	struct dlp *dlp; | 
|---|
|  | 138 | + | 
|---|
|  | 139 | +	snd_pcm_stream_lock_irq(substream); | 
|---|
|  | 140 | +	if (!substream->runtime) { | 
|---|
|  | 141 | +		snd_pcm_stream_unlock_irq(substream); | 
|---|
|  | 142 | +		return; | 
|---|
|  | 143 | +	} | 
|---|
|  | 144 | +#ifdef CONFIG_SND_SOC_ROCKCHIP_VAD | 
|---|
|  | 145 | +	prtd = substream_to_prtd(substream); | 
|---|
|  | 146 | +	if (unlikely(!prtd)) | 
|---|
|  | 147 | +		return; | 
|---|
| 105 | 148 |  | 
|---|
| 106 | 149 | if (snd_pcm_vad_attached(substream) && | 
|---|
| 107 | 150 | substream->stream == SNDRV_PCM_STREAM_CAPTURE) { | 
|---|
| .. | .. | 
|---|
| 116 | 159 | prtd->pos = 0; | 
|---|
| 117 | 160 |  | 
|---|
| 118 | 161 | #endif | 
|---|
|  | 162 | +	drd = substream_to_drd(substream); | 
|---|
|  | 163 | +	dlp = drd->parent; | 
|---|
|  | 164 | + | 
|---|
|  | 165 | +	dlp_dma_complete(dlp, drd); | 
|---|
|  | 166 | +	snd_pcm_stream_unlock_irq(substream); | 
|---|
|  | 167 | + | 
|---|
| 119 | 168 | snd_pcm_period_elapsed(substream); | 
|---|
| 120 | 169 | } | 
|---|
| 121 | 170 |  | 
|---|
| 122 | 171 | static void dmaengine_mpcm_get_master_chan(struct dmaengine_mpcm_runtime_data *prtd) | 
|---|
| 123 | 172 | { | 
|---|
| 124 | 173 | int i; | 
|---|
|  | 174 | + | 
|---|
|  | 175 | +	if (unlikely(!prtd)) | 
|---|
|  | 176 | +		return; | 
|---|
| 125 | 177 |  | 
|---|
| 126 | 178 | for (i = prtd->num_chans; i > 0; i--) { | 
|---|
| 127 | 179 | if (prtd->chans[i - 1]) { | 
|---|
| .. | .. | 
|---|
| 131 | 183 | } | 
|---|
| 132 | 184 | } | 
|---|
| 133 | 185 |  | 
|---|
|  | 186 | +static int dmaengine_config_interleaved(struct snd_pcm_substream *substream, | 
|---|
|  | 187 | +					struct dma_interleaved_template *xt, | 
|---|
|  | 188 | +					int offset, int sample_bytes, int nump, int numf) | 
|---|
|  | 189 | +{ | 
|---|
|  | 190 | +	struct snd_pcm_runtime *runtime = substream->runtime; | 
|---|
|  | 191 | +	int frame_bytes; | 
|---|
|  | 192 | + | 
|---|
|  | 193 | +	frame_bytes = frames_to_bytes(runtime, 1); | 
|---|
|  | 194 | + | 
|---|
|  | 195 | +	xt->frame_size = 1; | 
|---|
|  | 196 | +	xt->sgl[0].size = sample_bytes; | 
|---|
|  | 197 | +	xt->sgl[0].icg = frame_bytes - sample_bytes; | 
|---|
|  | 198 | + | 
|---|
|  | 199 | +#ifdef CONFIG_NO_GKI | 
|---|
|  | 200 | +	xt->nump = nump; | 
|---|
|  | 201 | +#endif | 
|---|
|  | 202 | +	xt->numf = numf; | 
|---|
|  | 203 | + | 
|---|
|  | 204 | +	xt->dir = snd_pcm_substream_to_dma_direction(substream); | 
|---|
|  | 205 | + | 
|---|
|  | 206 | +	if (xt->dir == DMA_MEM_TO_DEV) { | 
|---|
|  | 207 | +		xt->src_start = runtime->dma_addr + offset; | 
|---|
|  | 208 | +		xt->src_inc = true; | 
|---|
|  | 209 | +		xt->src_sgl = true; | 
|---|
|  | 210 | +		xt->dst_inc = false; | 
|---|
|  | 211 | +		xt->dst_sgl = false; | 
|---|
|  | 212 | +	} else { | 
|---|
|  | 213 | +		xt->dst_start = runtime->dma_addr + offset; | 
|---|
|  | 214 | +		xt->src_inc = false; | 
|---|
|  | 215 | +		xt->src_sgl = false; | 
|---|
|  | 216 | +		xt->dst_inc = true; | 
|---|
|  | 217 | +		xt->dst_sgl = true; | 
|---|
|  | 218 | +	} | 
|---|
|  | 219 | + | 
|---|
|  | 220 | +	return 0; | 
|---|
|  | 221 | +} | 
|---|
|  | 222 | + | 
|---|
| 134 | 223 | static int dmaengine_mpcm_prepare_and_submit(struct snd_pcm_substream *substream) | 
|---|
| 135 | 224 | { | 
|---|
| 136 | 225 | struct dmaengine_mpcm_runtime_data *prtd = substream_to_prtd(substream); | 
|---|
| 137 | 226 | struct snd_pcm_runtime *runtime = substream->runtime; | 
|---|
| 138 | 227 | struct dma_async_tx_descriptor *desc = NULL; | 
|---|
| 139 |  | -	enum dma_transfer_direction direction; | 
|---|
|  | 228 | +	struct dma_interleaved_template *xt; | 
|---|
| 140 | 229 | unsigned long flags = DMA_CTRL_ACK; | 
|---|
| 141 |  | -	unsigned int *maps = prtd->channel_maps; | 
|---|
| 142 |  | -	int offset, buffer_bytes, period_bytes; | 
|---|
|  | 230 | +	unsigned int *maps; | 
|---|
|  | 231 | +	int offset; | 
|---|
| 143 | 232 | int i; | 
|---|
| 144 | 233 |  | 
|---|
| 145 |  | -	direction = snd_pcm_substream_to_dma_direction(substream); | 
|---|
|  | 234 | +	if (unlikely(!prtd || !runtime)) | 
|---|
|  | 235 | +		return -EINVAL; | 
|---|
| 146 | 236 |  | 
|---|
| 147 | 237 | if (!substream->runtime->no_period_wakeup) | 
|---|
| 148 | 238 | flags |= DMA_PREP_INTERRUPT; | 
|---|
| 149 | 239 |  | 
|---|
| 150 | 240 | prtd->pos = 0; | 
|---|
| 151 | 241 | offset = 0; | 
|---|
| 152 |  | -	period_bytes = snd_pcm_lib_period_bytes(substream); | 
|---|
| 153 |  | -	buffer_bytes = snd_pcm_lib_buffer_bytes(substream); | 
|---|
|  | 242 | + | 
|---|
|  | 243 | +	xt = prtd->xt; | 
|---|
|  | 244 | +	maps = prtd->channel_maps; | 
|---|
| 154 | 245 | for (i = 0; i < prtd->num_chans; i++) { | 
|---|
| 155 | 246 | if (!prtd->chans[i]) | 
|---|
| 156 | 247 | continue; | 
|---|
| 157 |  | -		desc = dmaengine_prep_dma_cyclic(prtd->chans[i], | 
|---|
| 158 |  | -						 runtime->dma_addr + offset, | 
|---|
| 159 |  | -						 buffer_bytes, period_bytes, | 
|---|
| 160 |  | -						 direction, flags); | 
|---|
|  | 248 | + | 
|---|
|  | 249 | +		dmaengine_config_interleaved(substream, xt, offset, | 
|---|
|  | 250 | +					     samples_to_bytes(runtime, maps[i]), | 
|---|
|  | 251 | +					     runtime->period_size, | 
|---|
|  | 252 | +					     runtime->buffer_size); | 
|---|
|  | 253 | + | 
|---|
|  | 254 | +		desc = dmaengine_prep_interleaved_dma(prtd->chans[i], xt, | 
|---|
|  | 255 | +						      flags | DMA_PREP_REPEAT); | 
|---|
| 161 | 256 |  | 
|---|
| 162 | 257 | if (!desc) | 
|---|
| 163 | 258 | return -ENOMEM; | 
|---|
| .. | .. | 
|---|
| 181 | 276 | { | 
|---|
| 182 | 277 | int i; | 
|---|
| 183 | 278 |  | 
|---|
|  | 279 | +	if (unlikely(!prtd)) | 
|---|
|  | 280 | +		return; | 
|---|
|  | 281 | + | 
|---|
| 184 | 282 | for (i = 0; i < prtd->num_chans; i++) { | 
|---|
| 185 | 283 | if (prtd->chans[i]) | 
|---|
| 186 | 284 | dma_async_issue_pending(prtd->chans[i]); | 
|---|
| .. | .. | 
|---|
| 190 | 288 | static void mpcm_dmaengine_resume(struct dmaengine_mpcm_runtime_data *prtd) | 
|---|
| 191 | 289 | { | 
|---|
| 192 | 290 | int i; | 
|---|
|  | 291 | + | 
|---|
|  | 292 | +	if (unlikely(!prtd)) | 
|---|
|  | 293 | +		return; | 
|---|
| 193 | 294 |  | 
|---|
| 194 | 295 | for (i = 0; i < prtd->num_chans; i++) { | 
|---|
| 195 | 296 | if (prtd->chans[i]) | 
|---|
| .. | .. | 
|---|
| 201 | 302 | { | 
|---|
| 202 | 303 | int i; | 
|---|
| 203 | 304 |  | 
|---|
|  | 305 | +	if (unlikely(!prtd)) | 
|---|
|  | 306 | +		return; | 
|---|
|  | 307 | + | 
|---|
| 204 | 308 | for (i = 0; i < prtd->num_chans; i++) { | 
|---|
| 205 | 309 | if (prtd->chans[i]) | 
|---|
| 206 | 310 | dmaengine_pause(prtd->chans[i]); | 
|---|
| .. | .. | 
|---|
| 210 | 314 | static void mpcm_dmaengine_terminate_all(struct dmaengine_mpcm_runtime_data *prtd) | 
|---|
| 211 | 315 | { | 
|---|
| 212 | 316 | int i; | 
|---|
|  | 317 | + | 
|---|
|  | 318 | +	if (unlikely(!prtd)) | 
|---|
|  | 319 | +		return; | 
|---|
| 213 | 320 |  | 
|---|
| 214 | 321 | for (i = 0; i < prtd->num_chans; i++) { | 
|---|
| 215 | 322 | if (prtd->chans[i]) | 
|---|
| .. | .. | 
|---|
| 224 | 331 | struct dmaengine_mpcm_runtime_data *prtd = substream_to_prtd(substream); | 
|---|
| 225 | 332 | unsigned int pos, size; | 
|---|
| 226 | 333 | void *buf; | 
|---|
|  | 334 | + | 
|---|
|  | 335 | +	if (unlikely(!prtd)) | 
|---|
|  | 336 | +		return; | 
|---|
| 227 | 337 |  | 
|---|
| 228 | 338 | if (snd_pcm_vad_attached(substream) && | 
|---|
| 229 | 339 | substream->stream == SNDRV_PCM_STREAM_CAPTURE) { | 
|---|
| .. | .. | 
|---|
| 245 | 355 | } | 
|---|
| 246 | 356 |  | 
|---|
| 247 | 357 | static int __mpcm_prepare_single_and_submit(struct snd_pcm_substream *substream, | 
|---|
| 248 |  | -					    dma_addr_t buf_start, int size) | 
|---|
|  | 358 | +					    int buf_offset, int size) | 
|---|
| 249 | 359 | { | 
|---|
| 250 | 360 | struct dmaengine_mpcm_runtime_data *prtd = substream_to_prtd(substream); | 
|---|
|  | 361 | +	struct dma_interleaved_template *xt; | 
|---|
| 251 | 362 | struct snd_pcm_runtime *runtime = substream->runtime; | 
|---|
| 252 | 363 | struct dma_async_tx_descriptor *desc; | 
|---|
| 253 |  | -	enum dma_transfer_direction direction; | 
|---|
| 254 | 364 | unsigned long flags = DMA_CTRL_ACK; | 
|---|
| 255 |  | -	unsigned int *maps = prtd->channel_maps; | 
|---|
|  | 365 | +	unsigned int *maps; | 
|---|
| 256 | 366 | int offset, i; | 
|---|
| 257 | 367 | bool callback = false; | 
|---|
| 258 | 368 |  | 
|---|
| 259 |  | -	direction = snd_pcm_substream_to_dma_direction(substream); | 
|---|
|  | 369 | +	if (unlikely(!prtd || !runtime)) | 
|---|
|  | 370 | +		return -EINVAL; | 
|---|
| 260 | 371 |  | 
|---|
| 261 | 372 | if (!substream->runtime->no_period_wakeup) | 
|---|
| 262 | 373 | flags |= DMA_PREP_INTERRUPT; | 
|---|
| 263 | 374 |  | 
|---|
| 264 |  | -	offset = 0; | 
|---|
|  | 375 | +	offset = buf_offset; | 
|---|
|  | 376 | +	xt = prtd->xt; | 
|---|
|  | 377 | +	maps = prtd->channel_maps; | 
|---|
| 265 | 378 | for (i = 0; i < prtd->num_chans; i++) { | 
|---|
| 266 | 379 | if (!prtd->chans[i]) | 
|---|
| 267 | 380 | continue; | 
|---|
| 268 |  | -		desc = dmaengine_prep_slave_single(prtd->chans[i], | 
|---|
| 269 |  | -						   buf_start + offset, | 
|---|
| 270 |  | -						   size, | 
|---|
| 271 |  | -						   direction, flags); | 
|---|
| 272 | 381 |  | 
|---|
|  | 382 | +		dmaengine_config_interleaved(substream, xt, offset, | 
|---|
|  | 383 | +					     samples_to_bytes(runtime, maps[i]), | 
|---|
|  | 384 | +					     0, | 
|---|
|  | 385 | +					     bytes_to_frames(runtime, size)); | 
|---|
|  | 386 | + | 
|---|
|  | 387 | +		desc = dmaengine_prep_interleaved_dma(prtd->chans[i], xt, flags); | 
|---|
| 273 | 388 | if (!desc) | 
|---|
| 274 | 389 | return -ENOMEM; | 
|---|
|  | 390 | + | 
|---|
| 275 | 391 | if (!callback) { | 
|---|
| 276 | 392 | desc->callback = dmaengine_mpcm_single_dma_complete; | 
|---|
| 277 | 393 | desc->callback_param = substream; | 
|---|
| .. | .. | 
|---|
| 294 | 410 | int offset, i, count, ret; | 
|---|
| 295 | 411 | int buffer_bytes, period_bytes, residue_bytes; | 
|---|
| 296 | 412 |  | 
|---|
|  | 413 | +	if (unlikely(!prtd)) | 
|---|
|  | 414 | +		return -EINVAL; | 
|---|
|  | 415 | + | 
|---|
| 297 | 416 | direction = snd_pcm_substream_to_dma_direction(substream); | 
|---|
| 298 | 417 |  | 
|---|
| 299 | 418 | if (!substream->runtime->no_period_wakeup) | 
|---|
| .. | .. | 
|---|
| 312 | 431 | pr_debug("%s: offset: %d, buffer_bytes: %d\n", __func__, offset, buffer_bytes); | 
|---|
| 313 | 432 | pr_debug("%s: count: %d, residue_bytes: %d\n", __func__, count, residue_bytes); | 
|---|
| 314 | 433 | for (i = 0; i < count; i++) { | 
|---|
| 315 |  | -		ret = __mpcm_prepare_single_and_submit(substream, buf_start, | 
|---|
|  | 434 | +		ret = __mpcm_prepare_single_and_submit(substream, offset, | 
|---|
| 316 | 435 | period_bytes); | 
|---|
| 317 | 436 | if (ret) | 
|---|
| 318 | 437 | return ret; | 
|---|
| 319 |  | -		buf_start += period_bytes; | 
|---|
|  | 438 | +		offset += period_bytes; | 
|---|
| 320 | 439 | } | 
|---|
| 321 | 440 |  | 
|---|
| 322 | 441 | if (residue_bytes) { | 
|---|
| 323 |  | -		ret = __mpcm_prepare_single_and_submit(substream, buf_start, | 
|---|
|  | 442 | +		ret = __mpcm_prepare_single_and_submit(substream, offset, | 
|---|
| 324 | 443 | residue_bytes); | 
|---|
| 325 | 444 | if (ret) | 
|---|
| 326 | 445 | return ret; | 
|---|
| .. | .. | 
|---|
| 330 | 449 | } | 
|---|
| 331 | 450 | #endif | 
|---|
| 332 | 451 |  | 
|---|
| 333 |  | -static int snd_dmaengine_mpcm_trigger(struct snd_pcm_substream *substream, int cmd) | 
|---|
|  | 452 | +static snd_pcm_uframes_t dmaengine_mpcm_raw_pointer(struct snd_soc_component *component, | 
|---|
|  | 453 | +						    struct snd_pcm_substream *substream) | 
|---|
|  | 454 | +{ | 
|---|
|  | 455 | +	struct dmaengine_mpcm_runtime_data *prtd = substream_to_prtd(substream); | 
|---|
|  | 456 | +	struct dma_tx_state state; | 
|---|
|  | 457 | +	unsigned int buf_size; | 
|---|
|  | 458 | +	unsigned int pos = 0; | 
|---|
|  | 459 | +	unsigned int master; | 
|---|
|  | 460 | + | 
|---|
|  | 461 | +	if (unlikely(!prtd)) | 
|---|
|  | 462 | +		return 0; | 
|---|
|  | 463 | + | 
|---|
|  | 464 | +	master = prtd->master_chan; | 
|---|
|  | 465 | +	buf_size = snd_pcm_lib_buffer_bytes(substream); | 
|---|
|  | 466 | +	dmaengine_tx_status(prtd->chans[master], prtd->cookies[master], &state); | 
|---|
|  | 467 | +	if (state.residue > 0 && state.residue <= buf_size) | 
|---|
|  | 468 | +		pos = buf_size - state.residue; | 
|---|
|  | 469 | + | 
|---|
|  | 470 | +	return bytes_to_frames(substream->runtime, pos); | 
|---|
|  | 471 | +} | 
|---|
|  | 472 | + | 
|---|
|  | 473 | +static int dmaengine_mpcm_dlp_start(struct snd_soc_component *component, | 
|---|
|  | 474 | +				    struct snd_pcm_substream *substream) | 
|---|
|  | 475 | +{ | 
|---|
|  | 476 | +	struct dmaengine_mpcm *pcm = soc_component_to_mpcm(component); | 
|---|
|  | 477 | + | 
|---|
|  | 478 | +	return dlp_start(component, substream, pcm->mdais->dev, dmaengine_mpcm_raw_pointer); | 
|---|
|  | 479 | +} | 
|---|
|  | 480 | + | 
|---|
|  | 481 | +static void dmaengine_mpcm_dlp_stop(struct snd_soc_component *component, | 
|---|
|  | 482 | +				       struct snd_pcm_substream *substream) | 
|---|
|  | 483 | +{ | 
|---|
|  | 484 | +	dlp_stop(component, substream, dmaengine_mpcm_raw_pointer); | 
|---|
|  | 485 | +} | 
|---|
|  | 486 | + | 
|---|
|  | 487 | +static int dmaengine_mpcm_trigger(struct snd_soc_component *component, | 
|---|
|  | 488 | +				  struct snd_pcm_substream *substream, int cmd) | 
|---|
| 334 | 489 | { | 
|---|
| 335 | 490 | struct dmaengine_mpcm_runtime_data *prtd = substream_to_prtd(substream); | 
|---|
| 336 | 491 | struct snd_pcm_runtime *runtime = substream->runtime; | 
|---|
| 337 | 492 | int ret; | 
|---|
|  | 493 | + | 
|---|
|  | 494 | +	if (unlikely(!prtd || !runtime)) | 
|---|
|  | 495 | +		return -EINVAL; | 
|---|
| 338 | 496 |  | 
|---|
| 339 | 497 | switch (cmd) { | 
|---|
| 340 | 498 | case SNDRV_PCM_TRIGGER_START: | 
|---|
| .. | .. | 
|---|
| 350 | 508 | if (ret) | 
|---|
| 351 | 509 | return ret; | 
|---|
| 352 | 510 | mpcm_dma_async_issue_pending(prtd); | 
|---|
|  | 511 | +		dmaengine_mpcm_dlp_start(component, substream); | 
|---|
| 353 | 512 | break; | 
|---|
| 354 | 513 | case SNDRV_PCM_TRIGGER_RESUME: | 
|---|
| 355 | 514 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 
|---|
| 356 | 515 | mpcm_dmaengine_resume(prtd); | 
|---|
| 357 | 516 | break; | 
|---|
| 358 | 517 | case SNDRV_PCM_TRIGGER_SUSPEND: | 
|---|
| 359 |  | -		if (runtime->info & SNDRV_PCM_INFO_PAUSE) | 
|---|
|  | 518 | +		if (runtime->info & SNDRV_PCM_INFO_PAUSE) { | 
|---|
| 360 | 519 | mpcm_dmaengine_pause(prtd); | 
|---|
| 361 |  | -		else | 
|---|
|  | 520 | +		} else { | 
|---|
|  | 521 | +			dmaengine_mpcm_dlp_stop(component, substream); | 
|---|
| 362 | 522 | mpcm_dmaengine_terminate_all(prtd); | 
|---|
|  | 523 | +		} | 
|---|
| 363 | 524 | prtd->start_flag = false; | 
|---|
| 364 | 525 | break; | 
|---|
| 365 | 526 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 
|---|
| .. | .. | 
|---|
| 367 | 528 | prtd->start_flag = false; | 
|---|
| 368 | 529 | break; | 
|---|
| 369 | 530 | case SNDRV_PCM_TRIGGER_STOP: | 
|---|
|  | 531 | +		dmaengine_mpcm_dlp_stop(component, substream); | 
|---|
| 370 | 532 | mpcm_dmaengine_terminate_all(prtd); | 
|---|
| 371 | 533 | prtd->start_flag = false; | 
|---|
| 372 | 534 | break; | 
|---|
| .. | .. | 
|---|
| 377 | 539 | return 0; | 
|---|
| 378 | 540 | } | 
|---|
| 379 | 541 |  | 
|---|
| 380 |  | -static int dmaengine_mpcm_hw_params(struct snd_pcm_substream *substream, | 
|---|
|  | 542 | +static int dmaengine_mpcm_hw_params(struct snd_soc_component *component, | 
|---|
|  | 543 | +				    struct snd_pcm_substream *substream, | 
|---|
| 381 | 544 | struct snd_pcm_hw_params *params) | 
|---|
| 382 | 545 | { | 
|---|
| 383 |  | -	struct snd_soc_pcm_runtime *rtd = substream->private_data; | 
|---|
| 384 |  | -	struct snd_soc_component *component = | 
|---|
| 385 |  | -		snd_soc_rtdcom_lookup(rtd, SND_DMAENGINE_MPCM_DRV_NAME); | 
|---|
| 386 | 546 | struct dmaengine_mpcm *pcm = soc_component_to_mpcm(component); | 
|---|
| 387 | 547 | struct dma_chan *chan; | 
|---|
| 388 | 548 | struct snd_dmaengine_dai_dma_data *dma_data; | 
|---|
| .. | .. | 
|---|
| 420 | 580 | sz = snd_pcm_format_size(format, maps[i]); | 
|---|
| 421 | 581 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 
|---|
| 422 | 582 | chan = pcm->tx_chans[i]; | 
|---|
| 423 |  | -			if (sz) { | 
|---|
| 424 |  | -				slave_config.src_interlace_size = frame_bytes - sz; | 
|---|
| 425 |  | -				if (slave_config.src_interlace_size) | 
|---|
| 426 |  | -					slave_config.dst_maxburst = sz / slave_config.dst_addr_width; | 
|---|
| 427 |  | -			} | 
|---|
|  | 583 | +			if (sz && (frame_bytes - sz) > 0) | 
|---|
|  | 584 | +				slave_config.dst_maxburst = sz / slave_config.dst_addr_width; | 
|---|
| 428 | 585 | } else { | 
|---|
| 429 | 586 | chan = pcm->rx_chans[i]; | 
|---|
| 430 |  | -			if (sz) { | 
|---|
| 431 |  | -				slave_config.dst_interlace_size = frame_bytes - sz; | 
|---|
| 432 |  | -				if (slave_config.dst_interlace_size) | 
|---|
| 433 |  | -					slave_config.src_maxburst = sz / slave_config.src_addr_width; | 
|---|
| 434 |  | -			} | 
|---|
|  | 587 | +			if (sz && (frame_bytes - sz) > 0) | 
|---|
|  | 588 | +				slave_config.src_maxburst = sz / slave_config.src_addr_width; | 
|---|
| 435 | 589 | } | 
|---|
| 436 | 590 | if (!chan) | 
|---|
| 437 | 591 | continue; | 
|---|
| .. | .. | 
|---|
| 440 | 594 | if (ret) | 
|---|
| 441 | 595 | return ret; | 
|---|
| 442 | 596 | } | 
|---|
|  | 597 | + | 
|---|
|  | 598 | +	ret = dlp_hw_params(component, substream, params); | 
|---|
|  | 599 | +	if (ret) | 
|---|
|  | 600 | +		return ret; | 
|---|
|  | 601 | + | 
|---|
| 443 | 602 | return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); | 
|---|
| 444 | 603 | } | 
|---|
| 445 | 604 |  | 
|---|
| .. | .. | 
|---|
| 460 | 619 | int ret; | 
|---|
| 461 | 620 |  | 
|---|
| 462 | 621 | chan = to_chan(pcm, substream); | 
|---|
| 463 |  | -	if (!chan) | 
|---|
|  | 622 | +	if (!chan || !dma_dev) | 
|---|
| 464 | 623 | return -EINVAL; | 
|---|
| 465 | 624 |  | 
|---|
| 466 | 625 | memset(&hw, 0, sizeof(hw)); | 
|---|
| 467 | 626 | hw.info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | | 
|---|
| 468 |  | -			SNDRV_PCM_INFO_INTERLEAVED; | 
|---|
|  | 627 | +		  SNDRV_PCM_INFO_INTERLEAVED; | 
|---|
| 469 | 628 | hw.periods_min = 2; | 
|---|
| 470 | 629 | hw.periods_max = UINT_MAX; | 
|---|
| 471 | 630 | hw.period_bytes_min = 256; | 
|---|
| .. | .. | 
|---|
| 515 | 674 | return snd_soc_set_runtime_hwparams(substream, &hw); | 
|---|
| 516 | 675 | } | 
|---|
| 517 | 676 |  | 
|---|
| 518 |  | -static int dmaengine_mpcm_open(struct snd_pcm_substream *substream) | 
|---|
|  | 677 | +static int dmaengine_mpcm_open(struct snd_soc_component *component, | 
|---|
|  | 678 | +			       struct snd_pcm_substream *substream) | 
|---|
| 519 | 679 | { | 
|---|
| 520 |  | -	struct snd_soc_pcm_runtime *rtd = substream->private_data; | 
|---|
| 521 |  | -	struct snd_soc_component *component = | 
|---|
| 522 |  | -		snd_soc_rtdcom_lookup(rtd, SND_DMAENGINE_MPCM_DRV_NAME); | 
|---|
| 523 | 680 | struct dmaengine_mpcm *pcm = soc_component_to_mpcm(component); | 
|---|
| 524 | 681 | struct dmaengine_mpcm_runtime_data *prtd; | 
|---|
| 525 | 682 | int ret, i; | 
|---|
| .. | .. | 
|---|
| 537 | 694 | if (!prtd) | 
|---|
| 538 | 695 | return -ENOMEM; | 
|---|
| 539 | 696 |  | 
|---|
|  | 697 | +	prtd->xt = kzalloc(sizeof(struct dma_interleaved_template) + | 
|---|
|  | 698 | +			   sizeof(struct data_chunk), GFP_KERNEL); | 
|---|
|  | 699 | +	if (!prtd->xt) { | 
|---|
|  | 700 | +		kfree(prtd); | 
|---|
|  | 701 | +		return -ENOMEM; | 
|---|
|  | 702 | +	} | 
|---|
|  | 703 | + | 
|---|
| 540 | 704 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 
|---|
| 541 | 705 | prtd->channel_maps = pcm->mdais->playback_channel_maps; | 
|---|
| 542 | 706 | for (i = 0; i < pcm->mdais->num_dais; i++) | 
|---|
| .. | .. | 
|---|
| 549 | 713 |  | 
|---|
| 550 | 714 | prtd->num_chans = pcm->mdais->num_dais; | 
|---|
| 551 | 715 | prtd->start_flag = false; | 
|---|
| 552 |  | -	substream->runtime->private_data = prtd; | 
|---|
|  | 716 | + | 
|---|
|  | 717 | +	dlp_open(&pcm->dlp, &prtd->drd, substream); | 
|---|
| 553 | 718 |  | 
|---|
| 554 | 719 | return 0; | 
|---|
| 555 | 720 | } | 
|---|
| 556 | 721 |  | 
|---|
| 557 |  | -static int dmaengine_mpcm_new(struct snd_soc_pcm_runtime *rtd) | 
|---|
|  | 722 | +static int dmaengine_mpcm_new(struct snd_soc_component *component, struct snd_soc_pcm_runtime *rtd) | 
|---|
| 558 | 723 | { | 
|---|
| 559 |  | -	struct snd_soc_component *component = | 
|---|
| 560 |  | -		snd_soc_rtdcom_lookup(rtd, SND_DMAENGINE_MPCM_DRV_NAME); | 
|---|
| 561 | 724 | struct dmaengine_mpcm *pcm = soc_component_to_mpcm(component); | 
|---|
| 562 | 725 | struct snd_pcm_substream *substream; | 
|---|
|  | 726 | +	struct device *dma_dev; | 
|---|
| 563 | 727 | size_t prealloc_buffer_size; | 
|---|
| 564 | 728 | size_t max_buffer_size; | 
|---|
| 565 | 729 | unsigned int i; | 
|---|
| 566 |  | -	int ret; | 
|---|
| 567 | 730 |  | 
|---|
| 568 |  | -	prealloc_buffer_size = 512 * 1024; | 
|---|
|  | 731 | +	prealloc_buffer_size = prealloc_buffer_size_kbytes * 1024; | 
|---|
| 569 | 732 | max_buffer_size = SIZE_MAX; | 
|---|
| 570 | 733 |  | 
|---|
| 571 | 734 | for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; i++) { | 
|---|
| .. | .. | 
|---|
| 573 | 736 | if (!substream) | 
|---|
| 574 | 737 | continue; | 
|---|
| 575 | 738 |  | 
|---|
| 576 |  | -		ret = snd_pcm_lib_preallocate_pages(substream, | 
|---|
| 577 |  | -						    SNDRV_DMA_TYPE_DEV_IRAM, | 
|---|
| 578 |  | -						    dmaengine_dma_dev(pcm, substream), | 
|---|
| 579 |  | -						    prealloc_buffer_size, | 
|---|
| 580 |  | -						    max_buffer_size); | 
|---|
| 581 |  | -		if (ret) | 
|---|
| 582 |  | -			return ret; | 
|---|
|  | 739 | +		dma_dev = dmaengine_dma_dev(pcm, substream); | 
|---|
|  | 740 | +		if (!dma_dev) { | 
|---|
|  | 741 | +			dev_err(component->dev, "No chan found, should assign 'rockchip,no-dmaengine' in DT\n"); | 
|---|
|  | 742 | +			return -EINVAL; | 
|---|
|  | 743 | +		} | 
|---|
|  | 744 | + | 
|---|
|  | 745 | +		snd_pcm_lib_preallocate_pages(substream, | 
|---|
|  | 746 | +					      SNDRV_DMA_TYPE_DEV_IRAM, | 
|---|
|  | 747 | +					      dma_dev, | 
|---|
|  | 748 | +					      prealloc_buffer_size, | 
|---|
|  | 749 | +					      max_buffer_size); | 
|---|
| 583 | 750 | } | 
|---|
| 584 | 751 |  | 
|---|
| 585 | 752 | return 0; | 
|---|
| 586 | 753 | } | 
|---|
| 587 | 754 |  | 
|---|
| 588 |  | -static snd_pcm_uframes_t dmaengine_mpcm_pointer(struct snd_pcm_substream *substream) | 
|---|
|  | 755 | +static snd_pcm_uframes_t dmaengine_mpcm_pointer(struct snd_soc_component *component, | 
|---|
|  | 756 | +						struct snd_pcm_substream *substream) | 
|---|
| 589 | 757 | { | 
|---|
| 590 | 758 | struct dmaengine_mpcm_runtime_data *prtd = substream_to_prtd(substream); | 
|---|
| 591 | 759 | struct snd_pcm_runtime *runtime = substream->runtime; | 
|---|
| .. | .. | 
|---|
| 593 | 761 | snd_pcm_uframes_t frames; | 
|---|
| 594 | 762 | unsigned int buf_size; | 
|---|
| 595 | 763 | unsigned int pos = 0; | 
|---|
| 596 |  | -	unsigned int master = prtd->master_chan; | 
|---|
|  | 764 | +	unsigned int master; | 
|---|
| 597 | 765 |  | 
|---|
|  | 766 | +	if (unlikely(!prtd || !runtime)) | 
|---|
|  | 767 | +		return 0; | 
|---|
|  | 768 | + | 
|---|
|  | 769 | +	master = prtd->master_chan; | 
|---|
| 598 | 770 | buf_size = snd_pcm_lib_buffer_bytes(substream); | 
|---|
| 599 | 771 | dmaengine_tx_status(prtd->chans[master], prtd->cookies[master], &state); | 
|---|
| 600 | 772 | if (state.residue > 0 && state.residue <= buf_size) | 
|---|
| .. | .. | 
|---|
| 623 | 795 | return frames; | 
|---|
| 624 | 796 | } | 
|---|
| 625 | 797 |  | 
|---|
| 626 |  | -static int dmaengine_mpcm_close(struct snd_pcm_substream *substream) | 
|---|
|  | 798 | +static int dmaengine_mpcm_ioctl(struct snd_soc_component *component, | 
|---|
|  | 799 | +				struct snd_pcm_substream *substream, | 
|---|
|  | 800 | +				unsigned int cmd, void *arg) | 
|---|
| 627 | 801 | { | 
|---|
|  | 802 | +	return snd_pcm_lib_ioctl(substream, cmd, arg); | 
|---|
|  | 803 | +} | 
|---|
|  | 804 | + | 
|---|
|  | 805 | +static int dmaengine_mpcm_hw_free(struct snd_soc_component *component, | 
|---|
|  | 806 | +				  struct snd_pcm_substream *substream) | 
|---|
|  | 807 | +{ | 
|---|
|  | 808 | +	return snd_pcm_lib_free_pages(substream); | 
|---|
|  | 809 | +} | 
|---|
|  | 810 | + | 
|---|
|  | 811 | +static int dmaengine_mpcm_close(struct snd_soc_component *component, | 
|---|
|  | 812 | +				struct snd_pcm_substream *substream) | 
|---|
|  | 813 | +{ | 
|---|
|  | 814 | +	struct dmaengine_mpcm *pcm = soc_component_to_mpcm(component); | 
|---|
| 628 | 815 | struct dmaengine_mpcm_runtime_data *prtd = substream_to_prtd(substream); | 
|---|
| 629 | 816 |  | 
|---|
|  | 817 | +	if (unlikely(!prtd)) | 
|---|
|  | 818 | +		return -EINVAL; | 
|---|
|  | 819 | + | 
|---|
|  | 820 | +	dlp_close(&pcm->dlp, &prtd->drd, substream); | 
|---|
|  | 821 | + | 
|---|
|  | 822 | +	kfree(prtd->xt); | 
|---|
| 630 | 823 | kfree(prtd); | 
|---|
| 631 | 824 |  | 
|---|
| 632 | 825 | return 0; | 
|---|
| 633 | 826 | } | 
|---|
| 634 | 827 |  | 
|---|
| 635 |  | -static const struct snd_pcm_ops dmaengine_mpcm_ops = { | 
|---|
| 636 |  | -	.open		= dmaengine_mpcm_open, | 
|---|
| 637 |  | -	.close		= dmaengine_mpcm_close, | 
|---|
| 638 |  | -	.ioctl		= snd_pcm_lib_ioctl, | 
|---|
| 639 |  | -	.hw_params	= dmaengine_mpcm_hw_params, | 
|---|
| 640 |  | -	.hw_free	= snd_pcm_lib_free_pages, | 
|---|
| 641 |  | -	.trigger	= snd_dmaengine_mpcm_trigger, | 
|---|
| 642 |  | -	.pointer	= dmaengine_mpcm_pointer, | 
|---|
| 643 |  | -}; | 
|---|
|  | 828 | +static int dmaengine_mpcm_copy_user(struct snd_soc_component *component, | 
|---|
|  | 829 | +				    struct snd_pcm_substream *substream, | 
|---|
|  | 830 | +				    int channel, unsigned long hwoff, | 
|---|
|  | 831 | +				    void __user *buf, unsigned long bytes) | 
|---|
|  | 832 | +{ | 
|---|
|  | 833 | +	return dlp_copy_user(component, substream, channel, hwoff, buf, bytes); | 
|---|
|  | 834 | +} | 
|---|
|  | 835 | + | 
|---|
|  | 836 | + | 
|---|
|  | 837 | +static int dmaengine_mpcm_prepare(struct snd_soc_component *component, | 
|---|
|  | 838 | +				  struct snd_pcm_substream *substream) | 
|---|
|  | 839 | +{ | 
|---|
|  | 840 | +	return dlp_prepare(component, substream); | 
|---|
|  | 841 | +} | 
|---|
|  | 842 | + | 
|---|
|  | 843 | +static int dmaengine_mpcm_probe(struct snd_soc_component *component) | 
|---|
|  | 844 | +{ | 
|---|
|  | 845 | +	return dlp_probe(component); | 
|---|
|  | 846 | +} | 
|---|
| 644 | 847 |  | 
|---|
| 645 | 848 | static const struct snd_soc_component_driver dmaengine_mpcm_platform = { | 
|---|
| 646 | 849 | .name		= SND_DMAENGINE_MPCM_DRV_NAME, | 
|---|
| 647 | 850 | .probe_order	= SND_SOC_COMP_ORDER_LATE, | 
|---|
| 648 |  | -	.ops		= &dmaengine_mpcm_ops, | 
|---|
| 649 |  | -	.pcm_new	= dmaengine_mpcm_new, | 
|---|
|  | 851 | +	.probe		= dmaengine_mpcm_probe, | 
|---|
|  | 852 | +	.pcm_construct	= dmaengine_mpcm_new, | 
|---|
|  | 853 | +	.open		= dmaengine_mpcm_open, | 
|---|
|  | 854 | +	.close		= dmaengine_mpcm_close, | 
|---|
|  | 855 | +	.ioctl		= dmaengine_mpcm_ioctl, | 
|---|
|  | 856 | +	.hw_params	= dmaengine_mpcm_hw_params, | 
|---|
|  | 857 | +	.hw_free	= dmaengine_mpcm_hw_free, | 
|---|
|  | 858 | +	.prepare	= dmaengine_mpcm_prepare, | 
|---|
|  | 859 | +	.trigger	= dmaengine_mpcm_trigger, | 
|---|
|  | 860 | +	.pointer	= dmaengine_mpcm_pointer, | 
|---|
|  | 861 | +	.copy_user	= dmaengine_mpcm_copy_user, | 
|---|
| 650 | 862 | }; | 
|---|
| 651 | 863 |  | 
|---|
| 652 | 864 | static void dmaengine_mpcm_release_chan(struct dmaengine_mpcm *pcm) | 
|---|
| .. | .. | 
|---|
| 660 | 872 | dma_release_channel(pcm->rx_chans[i]); | 
|---|
| 661 | 873 | } | 
|---|
| 662 | 874 | } | 
|---|
|  | 875 | + | 
|---|
|  | 876 | +static int dmaengine_mpcm_get_fifo_count(struct device *dev, | 
|---|
|  | 877 | +					 struct snd_pcm_substream *substream) | 
|---|
|  | 878 | +{ | 
|---|
|  | 879 | +	struct rk_mdais_dev *mdais = dev_get_drvdata(dev); | 
|---|
|  | 880 | +	struct dmaengine_mpcm_runtime_data *prtd = substream_to_prtd(substream); | 
|---|
|  | 881 | +	struct snd_soc_component *component; | 
|---|
|  | 882 | +	unsigned int tx, rx, reg; | 
|---|
|  | 883 | +	int val = 0; | 
|---|
|  | 884 | + | 
|---|
|  | 885 | +	if (unlikely(!prtd)) | 
|---|
|  | 886 | +		return -EINVAL; | 
|---|
|  | 887 | + | 
|---|
|  | 888 | +	component = mdais->dais[prtd->master_chan].dai->component; | 
|---|
|  | 889 | +	if (unlikely(!component)) | 
|---|
|  | 890 | +		return -EINVAL; | 
|---|
|  | 891 | + | 
|---|
|  | 892 | +	if (strstr(dev_driver_string(component->dev), "i2s")) { | 
|---|
|  | 893 | +		/* compatible for both I2S and I2STDM controller */ | 
|---|
|  | 894 | +		tx = snd_soc_component_read(component, I2S_TXFIFOLR); | 
|---|
|  | 895 | +		rx = snd_soc_component_read(component, I2S_RXFIFOLR); | 
|---|
|  | 896 | + | 
|---|
|  | 897 | +		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 
|---|
|  | 898 | +			val = I2S_FIFOLR_XFL3(tx) + | 
|---|
|  | 899 | +			      I2S_FIFOLR_XFL2(tx) + | 
|---|
|  | 900 | +			      I2S_FIFOLR_XFL1(tx) + | 
|---|
|  | 901 | +			      I2S_FIFOLR_XFL0(tx); | 
|---|
|  | 902 | +		else | 
|---|
|  | 903 | +			/* XFL4 is compatible for old version */ | 
|---|
|  | 904 | +			val = I2S_FIFOLR_XFL4(tx) + | 
|---|
|  | 905 | +			      I2S_FIFOLR_XFL3(rx) + | 
|---|
|  | 906 | +			      I2S_FIFOLR_XFL2(rx) + | 
|---|
|  | 907 | +			      I2S_FIFOLR_XFL1(rx) + | 
|---|
|  | 908 | +			      I2S_FIFOLR_XFL0(rx); | 
|---|
|  | 909 | +	} else if (strstr(dev_driver_string(component->dev), "sai")) { | 
|---|
|  | 910 | +		reg = substream->stream ? SAI_RXFIFOLR : SAI_TXFIFOLR; | 
|---|
|  | 911 | + | 
|---|
|  | 912 | +		val = SAI_FIFOLR_XFL3(reg) + | 
|---|
|  | 913 | +		      SAI_FIFOLR_XFL2(reg) + | 
|---|
|  | 914 | +		      SAI_FIFOLR_XFL1(reg) + | 
|---|
|  | 915 | +		      SAI_FIFOLR_XFL0(reg); | 
|---|
|  | 916 | +	} | 
|---|
|  | 917 | + | 
|---|
|  | 918 | +	return val; | 
|---|
|  | 919 | +} | 
|---|
|  | 920 | + | 
|---|
|  | 921 | +static const struct snd_dlp_config dconfig = { | 
|---|
|  | 922 | +	.get_fifo_count = dmaengine_mpcm_get_fifo_count, | 
|---|
|  | 923 | +}; | 
|---|
| 663 | 924 |  | 
|---|
| 664 | 925 | int snd_dmaengine_mpcm_register(struct rk_mdais_dev *mdais) | 
|---|
| 665 | 926 | { | 
|---|
| .. | .. | 
|---|
| 696 | 957 | } | 
|---|
| 697 | 958 | } | 
|---|
| 698 | 959 |  | 
|---|
| 699 |  | -	ret = snd_soc_add_component(dev, &pcm->component, | 
|---|
| 700 |  | -				    &dmaengine_mpcm_platform, NULL, 0); | 
|---|
|  | 960 | +	ret = dlp_register(&pcm->dlp, dev, &dmaengine_mpcm_platform, &dconfig); | 
|---|
| 701 | 961 | if (ret) | 
|---|
| 702 | 962 | goto err_free_dma; | 
|---|
| 703 | 963 |  | 
|---|