Lines Matching +full:dma +full:- +full:info
1 // SPDX-License-Identifier: GPL-2.0+
3 // siu_pcm.c - ALSA driver for Renesas SH7343, SH7722 SIU peripheral.
5 // Copyright (C) 2009-2010 Guennadi Liakhovetski <[email protected]>
9 #include <linux/dma-mapping.h>
25 #define DRV_NAME "siu-i2s"
36 /* transfersize is number of u32 dma transfers per period */
39 struct siu_info *info = siu_i2s_data; in siu_pcm_stmwrite_stop() local
40 u32 __iomem *base = info->reg; in siu_pcm_stmwrite_stop()
41 struct siu_stream *siu_stream = &port_info->playback; in siu_pcm_stmwrite_stop()
44 if (!siu_stream->rw_flg) in siu_pcm_stmwrite_stop()
45 return -EPERM; in siu_pcm_stmwrite_stop()
50 pr_debug("%s: STFIFO %x -> %x\n", __func__, in siu_pcm_stmwrite_stop()
54 siu_stream->rw_flg = 0; in siu_pcm_stmwrite_stop()
61 struct siu_stream *siu_stream = &port_info->playback; in siu_pcm_stmwrite_start()
63 if (siu_stream->rw_flg) in siu_pcm_stmwrite_start()
64 return -EPERM; in siu_pcm_stmwrite_start()
67 port_info->playback.cur_period = 0; in siu_pcm_stmwrite_start()
70 siu_stream->rw_flg = RWF_STM_WT; in siu_pcm_stmwrite_start()
72 /* DMA transfer start */ in siu_pcm_stmwrite_start()
73 queue_work(system_highpri_wq, &siu_stream->work); in siu_pcm_stmwrite_start()
82 if (!siu_stream->rw_flg) in siu_dma_tx_complete()
86 if (++siu_stream->cur_period >= in siu_dma_tx_complete()
87 GET_MAX_PERIODS(siu_stream->buf_bytes, in siu_dma_tx_complete()
88 siu_stream->period_bytes)) in siu_dma_tx_complete()
89 siu_stream->cur_period = 0; in siu_dma_tx_complete()
92 __func__, siu_stream->cur_period, in siu_dma_tx_complete()
93 siu_stream->cur_period * siu_stream->period_bytes, in siu_dma_tx_complete()
94 siu_stream->buf_bytes, siu_stream->cookie); in siu_dma_tx_complete()
96 queue_work(system_highpri_wq, &siu_stream->work); in siu_dma_tx_complete()
99 snd_pcm_period_elapsed(siu_stream->substream); in siu_dma_tx_complete()
105 struct siu_info *info = siu_i2s_data; in siu_pcm_wr_set() local
106 u32 __iomem *base = info->reg; in siu_pcm_wr_set()
107 struct siu_stream *siu_stream = &port_info->playback; in siu_pcm_wr_set()
108 struct snd_pcm_substream *substream = siu_stream->substream; in siu_pcm_wr_set()
109 struct device *dev = substream->pcm->card->dev; in siu_pcm_wr_set()
121 desc = dmaengine_prep_slave_sg(siu_stream->chan, in siu_pcm_wr_set()
124 dev_err(dev, "Failed to allocate a dma descriptor\n"); in siu_pcm_wr_set()
125 return -ENOMEM; in siu_pcm_wr_set()
128 desc->callback = siu_dma_tx_complete; in siu_pcm_wr_set()
129 desc->callback_param = siu_stream; in siu_pcm_wr_set()
132 dev_err(dev, "Failed to submit a dma transfer\n"); in siu_pcm_wr_set()
136 siu_stream->tx_desc = desc; in siu_pcm_wr_set()
137 siu_stream->cookie = cookie; in siu_pcm_wr_set()
139 dma_async_issue_pending(siu_stream->chan); in siu_pcm_wr_set()
143 siu_write32(base + SIU_STFIFO, stfifo | (port_info->stfifo & 0x0c180c18)); in siu_pcm_wr_set()
144 dev_dbg(dev, "%s: STFIFO %x -> %x\n", __func__, in siu_pcm_wr_set()
145 stfifo, stfifo | (port_info->stfifo & 0x0c180c18)); in siu_pcm_wr_set()
153 struct siu_info *info = siu_i2s_data; in siu_pcm_rd_set() local
154 u32 __iomem *base = info->reg; in siu_pcm_rd_set()
155 struct siu_stream *siu_stream = &port_info->capture; in siu_pcm_rd_set()
156 struct snd_pcm_substream *substream = siu_stream->substream; in siu_pcm_rd_set()
157 struct device *dev = substream->pcm->card->dev; in siu_pcm_rd_set()
171 desc = dmaengine_prep_slave_sg(siu_stream->chan, in siu_pcm_rd_set()
174 dev_err(dev, "Failed to allocate dma descriptor\n"); in siu_pcm_rd_set()
175 return -ENOMEM; in siu_pcm_rd_set()
178 desc->callback = siu_dma_tx_complete; in siu_pcm_rd_set()
179 desc->callback_param = siu_stream; in siu_pcm_rd_set()
182 dev_err(dev, "Failed to submit dma descriptor\n"); in siu_pcm_rd_set()
186 siu_stream->tx_desc = desc; in siu_pcm_rd_set()
187 siu_stream->cookie = cookie; in siu_pcm_rd_set()
189 dma_async_issue_pending(siu_stream->chan); in siu_pcm_rd_set()
194 (port_info->stfifo & 0x13071307)); in siu_pcm_rd_set()
195 dev_dbg(dev, "%s: STFIFO %x -> %x\n", __func__, in siu_pcm_rd_set()
196 stfifo, stfifo | (port_info->stfifo & 0x13071307)); in siu_pcm_rd_set()
205 struct snd_pcm_substream *substream = siu_stream->substream; in siu_io_work()
206 struct device *dev = substream->pcm->card->dev; in siu_io_work()
207 struct snd_pcm_runtime *rt = substream->runtime; in siu_io_work()
210 dev_dbg(dev, "%s: flags %x\n", __func__, siu_stream->rw_flg); in siu_io_work()
212 if (!siu_stream->rw_flg) { in siu_io_work()
217 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { in siu_io_work()
221 buff = (dma_addr_t)PERIOD_OFFSET(rt->dma_addr, in siu_io_work()
222 siu_stream->cur_period, in siu_io_work()
223 siu_stream->period_bytes); in siu_io_work()
224 count = siu_stream->period_bytes; in siu_io_work()
226 /* DMA transfer start */ in siu_io_work()
230 (dma_addr_t)PERIOD_OFFSET(rt->dma_addr, in siu_io_work()
231 siu_stream->cur_period, in siu_io_work()
232 siu_stream->period_bytes), in siu_io_work()
233 siu_stream->period_bytes); in siu_io_work()
240 struct siu_stream *siu_stream = &port_info->capture; in siu_pcm_stmread_start()
242 if (siu_stream->xfer_cnt > 0x1000000) in siu_pcm_stmread_start()
243 return -EINVAL; in siu_pcm_stmread_start()
244 if (siu_stream->rw_flg) in siu_pcm_stmread_start()
245 return -EPERM; in siu_pcm_stmread_start()
248 siu_stream->cur_period = 0; in siu_pcm_stmread_start()
251 siu_stream->rw_flg = RWF_STM_RD; in siu_pcm_stmread_start()
253 queue_work(system_highpri_wq, &siu_stream->work); in siu_pcm_stmread_start()
260 struct siu_info *info = siu_i2s_data; in siu_pcm_stmread_stop() local
261 u32 __iomem *base = info->reg; in siu_pcm_stmread_stop()
262 struct siu_stream *siu_stream = &port_info->capture; in siu_pcm_stmread_stop()
263 struct device *dev = siu_stream->substream->pcm->card->dev; in siu_pcm_stmread_stop()
266 if (!siu_stream->rw_flg) in siu_pcm_stmread_stop()
267 return -EPERM; in siu_pcm_stmread_stop()
272 dev_dbg(dev, "%s: STFIFO %x -> %x\n", __func__, in siu_pcm_stmread_stop()
276 siu_stream->rw_flg = 0; in siu_pcm_stmread_stop()
285 pr_debug("%s: secondary ID %d\n", __func__, param->shdma_slave.slave_id); in filter()
287 chan->private = ¶m->shdma_slave; in filter()
295 struct siu_platform *pdata = component->dev->platform_data; in siu_pcm_open()
296 struct siu_info *info = siu_i2s_data; in siu_pcm_open() local
299 u32 port = info->port_id; in siu_pcm_open()
300 struct device *dev = ss->pcm->card->dev; in siu_pcm_open()
309 if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK) { in siu_pcm_open()
310 siu_stream = &port_info->playback; in siu_pcm_open()
311 param = &siu_stream->param; in siu_pcm_open()
312 param->shdma_slave.slave_id = port ? pdata->dma_slave_tx_b : in siu_pcm_open()
313 pdata->dma_slave_tx_a; in siu_pcm_open()
315 siu_stream = &port_info->capture; in siu_pcm_open()
316 param = &siu_stream->param; in siu_pcm_open()
317 param->shdma_slave.slave_id = port ? pdata->dma_slave_rx_b : in siu_pcm_open()
318 pdata->dma_slave_rx_a; in siu_pcm_open()
321 /* Get DMA channel */ in siu_pcm_open()
322 siu_stream->chan = dma_request_channel(mask, filter, param); in siu_pcm_open()
323 if (!siu_stream->chan) { in siu_pcm_open()
324 dev_err(dev, "DMA channel allocation failed!\n"); in siu_pcm_open()
325 return -EBUSY; in siu_pcm_open()
328 siu_stream->substream = ss; in siu_pcm_open()
336 struct siu_info *info = siu_i2s_data; in siu_pcm_close() local
337 struct device *dev = ss->pcm->card->dev; in siu_pcm_close()
341 dev_dbg(dev, "%s: port=%d\n", __func__, info->port_id); in siu_pcm_close()
343 if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK) in siu_pcm_close()
344 siu_stream = &port_info->playback; in siu_pcm_close()
346 siu_stream = &port_info->capture; in siu_pcm_close()
348 dma_release_channel(siu_stream->chan); in siu_pcm_close()
349 siu_stream->chan = NULL; in siu_pcm_close()
351 siu_stream->substream = NULL; in siu_pcm_close()
359 struct siu_info *info = siu_i2s_data; in siu_pcm_prepare() local
361 struct device *dev = ss->pcm->card->dev; in siu_pcm_prepare()
366 if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK) in siu_pcm_prepare()
367 siu_stream = &port_info->playback; in siu_pcm_prepare()
369 siu_stream = &port_info->capture; in siu_pcm_prepare()
371 rt = siu_stream->substream->runtime; in siu_pcm_prepare()
373 siu_stream->buf_bytes = snd_pcm_lib_buffer_bytes(ss); in siu_pcm_prepare()
374 siu_stream->period_bytes = snd_pcm_lib_period_bytes(ss); in siu_pcm_prepare()
377 info->port_id, rt->channels, siu_stream->period_bytes); in siu_pcm_prepare()
380 if (siu_stream->buf_bytes % siu_stream->period_bytes) { in siu_pcm_prepare()
381 dev_err(dev, "%s() - buffer=%d not multiple of period=%d\n", in siu_pcm_prepare()
382 __func__, siu_stream->buf_bytes, in siu_pcm_prepare()
383 siu_stream->period_bytes); in siu_pcm_prepare()
384 return -EINVAL; in siu_pcm_prepare()
387 xfer_cnt = bytes_to_frames(rt, siu_stream->period_bytes); in siu_pcm_prepare()
389 return -EINVAL; in siu_pcm_prepare()
391 siu_stream->format = rt->format; in siu_pcm_prepare()
392 siu_stream->xfer_cnt = xfer_cnt; in siu_pcm_prepare()
395 "format=%d channels=%d xfer_cnt=%d\n", info->port_id, in siu_pcm_prepare()
396 (unsigned long)rt->dma_addr, siu_stream->buf_bytes, in siu_pcm_prepare()
397 siu_stream->period_bytes, in siu_pcm_prepare()
398 siu_stream->format, rt->channels, (int)xfer_cnt); in siu_pcm_prepare()
406 struct siu_info *info = siu_i2s_data; in siu_pcm_trigger() local
407 struct device *dev = ss->pcm->card->dev; in siu_pcm_trigger()
412 info->port_id, port_info, cmd); in siu_pcm_trigger()
416 if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK) in siu_pcm_trigger()
423 __func__, info->port_id); in siu_pcm_trigger()
427 if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK) in siu_pcm_trigger()
436 ret = -EINVAL; in siu_pcm_trigger()
450 struct device *dev = ss->pcm->card->dev; in siu_pcm_pointer_dma()
451 struct siu_info *info = siu_i2s_data; in siu_pcm_pointer_dma() local
452 u32 __iomem *base = info->reg; in siu_pcm_pointer_dma()
454 struct snd_pcm_runtime *rt = ss->runtime; in siu_pcm_pointer_dma()
458 if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK) in siu_pcm_pointer_dma()
459 siu_stream = &port_info->playback; in siu_pcm_pointer_dma()
461 siu_stream = &port_info->capture; in siu_pcm_pointer_dma()
464 * ptr is the offset into the buffer where the dma is currently at. We in siu_pcm_pointer_dma()
465 * check if the dma buffer has just wrapped. in siu_pcm_pointer_dma()
467 ptr = PERIOD_OFFSET(rt->dma_addr, in siu_pcm_pointer_dma()
468 siu_stream->cur_period, in siu_pcm_pointer_dma()
469 siu_stream->period_bytes) - rt->dma_addr; in siu_pcm_pointer_dma()
473 __func__, info->port_id, siu_read32(base + SIU_EVNTC), in siu_pcm_pointer_dma()
474 siu_read32(base + SIU_SBFSTS), ptr, siu_stream->buf_bytes, in siu_pcm_pointer_dma()
475 siu_stream->cookie); in siu_pcm_pointer_dma()
477 if (ptr >= siu_stream->buf_bytes) in siu_pcm_pointer_dma()
480 return bytes_to_frames(ss->runtime, ptr); in siu_pcm_pointer_dma()
486 /* card->dev == socdev->dev, see snd_soc_new_pcms() */ in siu_pcm_new()
487 struct snd_card *card = rtd->card->snd_card; in siu_pcm_new()
488 struct snd_pcm *pcm = rtd->pcm; in siu_pcm_new()
489 struct siu_info *info = siu_i2s_data; in siu_pcm_new() local
490 struct platform_device *pdev = to_platform_device(card->dev); in siu_pcm_new()
494 /* pdev->id selects between SIUA and SIUB */ in siu_pcm_new()
495 if (pdev->id < 0 || pdev->id >= SIU_PORT_NUM) in siu_pcm_new()
496 return -EINVAL; in siu_pcm_new()
498 info->port_id = pdev->id; in siu_pcm_new()
506 for (i = pdev->id; i < pdev->id + 1; i++) { in siu_pcm_new()
514 SNDRV_DMA_TYPE_DEV, card->dev, in siu_pcm_new()
517 (*port_info)->pcm = pcm; in siu_pcm_new()
520 INIT_WORK(&(*port_info)->playback.work, siu_io_work); in siu_pcm_new()
521 INIT_WORK(&(*port_info)->capture.work, siu_io_work); in siu_pcm_new()
524 dev_info(card->dev, "SuperH SIU driver initialized.\n"); in siu_pcm_new()
531 struct platform_device *pdev = to_platform_device(pcm->card->dev); in siu_pcm_free()
532 struct siu_port *port_info = siu_ports[pdev->id]; in siu_pcm_free()
534 cancel_work_sync(&port_info->capture.work); in siu_pcm_free()
535 cancel_work_sync(&port_info->playback.work); in siu_pcm_free()
539 dev_dbg(pcm->card->dev, "%s\n", __func__); in siu_pcm_free()