1 // SPDX-License-Identifier: GPL-2.0+ 2 // 3 // siu_pcm.c - ALSA driver for Renesas SH7343, SH7722 SIU peripheral. 4 // 5 // Copyright (C) 2009-2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de> 6 // Copyright (C) 2006 Carlos Munoz <carlos@kenati.com> 7 8 #include <linux/delay.h> 9 #include <linux/dma-mapping.h> 10 #include <linux/dmaengine.h> 11 #include <linux/interrupt.h> 12 #include <linux/module.h> 13 #include <linux/platform_device.h> 14 15 #include <sound/control.h> 16 #include <sound/core.h> 17 #include <sound/pcm.h> 18 #include <sound/pcm_params.h> 19 #include <sound/soc.h> 20 21 #include <asm/siu.h> 22 23 #include "siu.h" 24 25 #define DRV_NAME "siu-i2s" 26 #define GET_MAX_PERIODS(buf_bytes, period_bytes) \ 27 ((buf_bytes) / (period_bytes)) 28 #define PERIOD_OFFSET(buf_addr, period_num, period_bytes) \ 29 ((buf_addr) + ((period_num) * (period_bytes))) 30 31 #define RWF_STM_RD 0x01 /* Read in progress */ 32 #define RWF_STM_WT 0x02 /* Write in progress */ 33 34 struct siu_port *siu_ports[SIU_PORT_NUM]; 35 36 /* transfersize is number of u32 dma transfers per period */ 37 static int siu_pcm_stmwrite_stop(struct siu_port *port_info) 38 { 39 struct siu_info *info = siu_i2s_data; 40 u32 __iomem *base = info->reg; 41 struct siu_stream *siu_stream = &port_info->playback; 42 u32 stfifo; 43 44 if (!siu_stream->rw_flg) 45 return -EPERM; 46 47 /* output FIFO disable */ 48 stfifo = siu_read32(base + SIU_STFIFO); 49 siu_write32(base + SIU_STFIFO, stfifo & ~0x0c180c18); 50 pr_debug("%s: STFIFO %x -> %x\n", __func__, 51 stfifo, stfifo & ~0x0c180c18); 52 53 /* during stmwrite clear */ 54 siu_stream->rw_flg = 0; 55 56 return 0; 57 } 58 59 static int siu_pcm_stmwrite_start(struct siu_port *port_info) 60 { 61 struct siu_stream *siu_stream = &port_info->playback; 62 63 if (siu_stream->rw_flg) 64 return -EPERM; 65 66 /* Current period in buffer */ 67 port_info->playback.cur_period = 0; 68 69 /* during stmwrite flag set */ 70 siu_stream->rw_flg = RWF_STM_WT; 71 72 /* DMA transfer start */ 73 queue_work(system_highpri_wq, &siu_stream->work); 74 75 return 0; 76 } 77 78 static void siu_dma_tx_complete(void *arg) 79 { 80 struct siu_stream *siu_stream = arg; 81 82 if (!siu_stream->rw_flg) 83 return; 84 85 /* Update completed period count */ 86 if (++siu_stream->cur_period >= 87 GET_MAX_PERIODS(siu_stream->buf_bytes, 88 siu_stream->period_bytes)) 89 siu_stream->cur_period = 0; 90 91 pr_debug("%s: done period #%d (%u/%u bytes), cookie %d\n", 92 __func__, siu_stream->cur_period, 93 siu_stream->cur_period * siu_stream->period_bytes, 94 siu_stream->buf_bytes, siu_stream->cookie); 95 96 queue_work(system_highpri_wq, &siu_stream->work); 97 98 /* Notify alsa: a period is done */ 99 snd_pcm_period_elapsed(siu_stream->substream); 100 } 101 102 static int siu_pcm_wr_set(struct siu_port *port_info, 103 dma_addr_t buff, u32 size) 104 { 105 struct siu_info *info = siu_i2s_data; 106 u32 __iomem *base = info->reg; 107 struct siu_stream *siu_stream = &port_info->playback; 108 struct snd_pcm_substream *substream = siu_stream->substream; 109 struct device *dev = substream->pcm->card->dev; 110 struct dma_async_tx_descriptor *desc; 111 dma_cookie_t cookie; 112 struct scatterlist sg; 113 u32 stfifo; 114 115 sg_init_table(&sg, 1); 116 sg_set_page(&sg, pfn_to_page(PFN_DOWN(buff)), 117 size, offset_in_page(buff)); 118 sg_dma_len(&sg) = size; 119 sg_dma_address(&sg) = buff; 120 121 desc = dmaengine_prep_slave_sg(siu_stream->chan, 122 &sg, 1, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); 123 if (!desc) { 124 dev_err(dev, "Failed to allocate a dma descriptor\n"); 125 return -ENOMEM; 126 } 127 128 desc->callback = siu_dma_tx_complete; 129 desc->callback_param = siu_stream; 130 cookie = dmaengine_submit(desc); 131 if (cookie < 0) { 132 dev_err(dev, "Failed to submit a dma transfer\n"); 133 return cookie; 134 } 135 136 siu_stream->tx_desc = desc; 137 siu_stream->cookie = cookie; 138 139 dma_async_issue_pending(siu_stream->chan); 140 141 /* only output FIFO enable */ 142 stfifo = siu_read32(base + SIU_STFIFO); 143 siu_write32(base + SIU_STFIFO, stfifo | (port_info->stfifo & 0x0c180c18)); 144 dev_dbg(dev, "%s: STFIFO %x -> %x\n", __func__, 145 stfifo, stfifo | (port_info->stfifo & 0x0c180c18)); 146 147 return 0; 148 } 149 150 static int siu_pcm_rd_set(struct siu_port *port_info, 151 dma_addr_t buff, size_t size) 152 { 153 struct siu_info *info = siu_i2s_data; 154 u32 __iomem *base = info->reg; 155 struct siu_stream *siu_stream = &port_info->capture; 156 struct snd_pcm_substream *substream = siu_stream->substream; 157 struct device *dev = substream->pcm->card->dev; 158 struct dma_async_tx_descriptor *desc; 159 dma_cookie_t cookie; 160 struct scatterlist sg; 161 u32 stfifo; 162 163 dev_dbg(dev, "%s: %u@%llx\n", __func__, size, (unsigned long long)buff); 164 165 sg_init_table(&sg, 1); 166 sg_set_page(&sg, pfn_to_page(PFN_DOWN(buff)), 167 size, offset_in_page(buff)); 168 sg_dma_len(&sg) = size; 169 sg_dma_address(&sg) = buff; 170 171 desc = dmaengine_prep_slave_sg(siu_stream->chan, 172 &sg, 1, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); 173 if (!desc) { 174 dev_err(dev, "Failed to allocate dma descriptor\n"); 175 return -ENOMEM; 176 } 177 178 desc->callback = siu_dma_tx_complete; 179 desc->callback_param = siu_stream; 180 cookie = dmaengine_submit(desc); 181 if (cookie < 0) { 182 dev_err(dev, "Failed to submit dma descriptor\n"); 183 return cookie; 184 } 185 186 siu_stream->tx_desc = desc; 187 siu_stream->cookie = cookie; 188 189 dma_async_issue_pending(siu_stream->chan); 190 191 /* only input FIFO enable */ 192 stfifo = siu_read32(base + SIU_STFIFO); 193 siu_write32(base + SIU_STFIFO, siu_read32(base + SIU_STFIFO) | 194 (port_info->stfifo & 0x13071307)); 195 dev_dbg(dev, "%s: STFIFO %x -> %x\n", __func__, 196 stfifo, stfifo | (port_info->stfifo & 0x13071307)); 197 198 return 0; 199 } 200 201 static void siu_io_work(struct work_struct *work) 202 { 203 struct siu_stream *siu_stream = container_of(work, struct siu_stream, 204 work); 205 struct snd_pcm_substream *substream = siu_stream->substream; 206 struct device *dev = substream->pcm->card->dev; 207 struct snd_pcm_runtime *rt = substream->runtime; 208 struct siu_port *port_info = siu_port_info(substream); 209 210 dev_dbg(dev, "%s: flags %x\n", __func__, siu_stream->rw_flg); 211 212 if (!siu_stream->rw_flg) { 213 dev_dbg(dev, "%s: stream inactive\n", __func__); 214 return; 215 } 216 217 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { 218 dma_addr_t buff; 219 size_t count; 220 221 buff = (dma_addr_t)PERIOD_OFFSET(rt->dma_addr, 222 siu_stream->cur_period, 223 siu_stream->period_bytes); 224 count = siu_stream->period_bytes; 225 226 /* DMA transfer start */ 227 siu_pcm_rd_set(port_info, buff, count); 228 } else { 229 siu_pcm_wr_set(port_info, 230 (dma_addr_t)PERIOD_OFFSET(rt->dma_addr, 231 siu_stream->cur_period, 232 siu_stream->period_bytes), 233 siu_stream->period_bytes); 234 } 235 } 236 237 /* Capture */ 238 static int siu_pcm_stmread_start(struct siu_port *port_info) 239 { 240 struct siu_stream *siu_stream = &port_info->capture; 241 242 if (siu_stream->xfer_cnt > 0x1000000) 243 return -EINVAL; 244 if (siu_stream->rw_flg) 245 return -EPERM; 246 247 /* Current period in buffer */ 248 siu_stream->cur_period = 0; 249 250 /* during stmread flag set */ 251 siu_stream->rw_flg = RWF_STM_RD; 252 253 queue_work(system_highpri_wq, &siu_stream->work); 254 255 return 0; 256 } 257 258 static int siu_pcm_stmread_stop(struct siu_port *port_info) 259 { 260 struct siu_info *info = siu_i2s_data; 261 u32 __iomem *base = info->reg; 262 struct siu_stream *siu_stream = &port_info->capture; 263 struct device *dev = siu_stream->substream->pcm->card->dev; 264 u32 stfifo; 265 266 if (!siu_stream->rw_flg) 267 return -EPERM; 268 269 /* input FIFO disable */ 270 stfifo = siu_read32(base + SIU_STFIFO); 271 siu_write32(base + SIU_STFIFO, stfifo & ~0x13071307); 272 dev_dbg(dev, "%s: STFIFO %x -> %x\n", __func__, 273 stfifo, stfifo & ~0x13071307); 274 275 /* during stmread flag clear */ 276 siu_stream->rw_flg = 0; 277 278 return 0; 279 } 280 281 static bool filter(struct dma_chan *chan, void *secondary) 282 { 283 struct sh_dmae_slave *param = secondary; 284 285 pr_debug("%s: secondary ID %d\n", __func__, param->shdma_slave.slave_id); 286 287 chan->private = ¶m->shdma_slave; 288 return true; 289 } 290 291 static int siu_pcm_open(struct snd_soc_component *component, 292 struct snd_pcm_substream *ss) 293 { 294 /* Playback / Capture */ 295 struct siu_platform *pdata = component->dev->platform_data; 296 struct siu_info *info = siu_i2s_data; 297 struct siu_port *port_info = siu_port_info(ss); 298 struct siu_stream *siu_stream; 299 u32 port = info->port_id; 300 struct device *dev = ss->pcm->card->dev; 301 dma_cap_mask_t mask; 302 struct sh_dmae_slave *param; 303 304 dma_cap_zero(mask); 305 dma_cap_set(DMA_SLAVE, mask); 306 307 dev_dbg(dev, "%s, port=%d@%p\n", __func__, port, port_info); 308 309 if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK) { 310 siu_stream = &port_info->playback; 311 param = &siu_stream->param; 312 param->shdma_slave.slave_id = port ? pdata->dma_slave_tx_b : 313 pdata->dma_slave_tx_a; 314 } else { 315 siu_stream = &port_info->capture; 316 param = &siu_stream->param; 317 param->shdma_slave.slave_id = port ? pdata->dma_slave_rx_b : 318 pdata->dma_slave_rx_a; 319 } 320 321 /* Get DMA channel */ 322 siu_stream->chan = dma_request_channel(mask, filter, param); 323 if (!siu_stream->chan) { 324 dev_err(dev, "DMA channel allocation failed!\n"); 325 return -EBUSY; 326 } 327 328 siu_stream->substream = ss; 329 330 return 0; 331 } 332 333 static int siu_pcm_close(struct snd_soc_component *component, 334 struct snd_pcm_substream *ss) 335 { 336 struct siu_info *info = siu_i2s_data; 337 struct device *dev = ss->pcm->card->dev; 338 struct siu_port *port_info = siu_port_info(ss); 339 struct siu_stream *siu_stream; 340 341 dev_dbg(dev, "%s: port=%d\n", __func__, info->port_id); 342 343 if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK) 344 siu_stream = &port_info->playback; 345 else 346 siu_stream = &port_info->capture; 347 348 dma_release_channel(siu_stream->chan); 349 siu_stream->chan = NULL; 350 351 siu_stream->substream = NULL; 352 353 return 0; 354 } 355 356 static int siu_pcm_prepare(struct snd_soc_component *component, 357 struct snd_pcm_substream *ss) 358 { 359 struct siu_info *info = siu_i2s_data; 360 struct siu_port *port_info = siu_port_info(ss); 361 struct device *dev = ss->pcm->card->dev; 362 struct snd_pcm_runtime *rt; 363 struct siu_stream *siu_stream; 364 snd_pcm_sframes_t xfer_cnt; 365 366 if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK) 367 siu_stream = &port_info->playback; 368 else 369 siu_stream = &port_info->capture; 370 371 rt = siu_stream->substream->runtime; 372 373 siu_stream->buf_bytes = snd_pcm_lib_buffer_bytes(ss); 374 siu_stream->period_bytes = snd_pcm_lib_period_bytes(ss); 375 376 dev_dbg(dev, "%s: port=%d, %d channels, period=%u bytes\n", __func__, 377 info->port_id, rt->channels, siu_stream->period_bytes); 378 379 /* We only support buffers that are multiples of the period */ 380 if (siu_stream->buf_bytes % siu_stream->period_bytes) { 381 dev_err(dev, "%s() - buffer=%d not multiple of period=%d\n", 382 __func__, siu_stream->buf_bytes, 383 siu_stream->period_bytes); 384 return -EINVAL; 385 } 386 387 xfer_cnt = bytes_to_frames(rt, siu_stream->period_bytes); 388 if (!xfer_cnt || xfer_cnt > 0x1000000) 389 return -EINVAL; 390 391 siu_stream->format = rt->format; 392 siu_stream->xfer_cnt = xfer_cnt; 393 394 dev_dbg(dev, "port=%d buf=%lx buf_bytes=%d period_bytes=%d " 395 "format=%d channels=%d xfer_cnt=%d\n", info->port_id, 396 (unsigned long)rt->dma_addr, siu_stream->buf_bytes, 397 siu_stream->period_bytes, 398 siu_stream->format, rt->channels, (int)xfer_cnt); 399 400 return 0; 401 } 402 403 static int siu_pcm_trigger(struct snd_soc_component *component, 404 struct snd_pcm_substream *ss, int cmd) 405 { 406 struct siu_info *info = siu_i2s_data; 407 struct device *dev = ss->pcm->card->dev; 408 struct siu_port *port_info = siu_port_info(ss); 409 int ret; 410 411 dev_dbg(dev, "%s: port=%d@%p, cmd=%d\n", __func__, 412 info->port_id, port_info, cmd); 413 414 switch (cmd) { 415 case SNDRV_PCM_TRIGGER_START: 416 if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK) 417 ret = siu_pcm_stmwrite_start(port_info); 418 else 419 ret = siu_pcm_stmread_start(port_info); 420 421 if (ret < 0) 422 dev_warn(dev, "%s: start failed on port=%d\n", 423 __func__, info->port_id); 424 425 break; 426 case SNDRV_PCM_TRIGGER_STOP: 427 if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK) 428 siu_pcm_stmwrite_stop(port_info); 429 else 430 siu_pcm_stmread_stop(port_info); 431 ret = 0; 432 433 break; 434 default: 435 dev_err(dev, "%s() unsupported cmd=%d\n", __func__, cmd); 436 ret = -EINVAL; 437 } 438 439 return ret; 440 } 441 442 /* 443 * So far only resolution of one period is supported, subject to extending the 444 * dmangine API 445 */ 446 static snd_pcm_uframes_t 447 siu_pcm_pointer_dma(struct snd_soc_component *component, 448 struct snd_pcm_substream *ss) 449 { 450 struct device *dev = ss->pcm->card->dev; 451 struct siu_info *info = siu_i2s_data; 452 u32 __iomem *base = info->reg; 453 struct siu_port *port_info = siu_port_info(ss); 454 struct snd_pcm_runtime *rt = ss->runtime; 455 size_t ptr; 456 struct siu_stream *siu_stream; 457 458 if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK) 459 siu_stream = &port_info->playback; 460 else 461 siu_stream = &port_info->capture; 462 463 /* 464 * ptr is the offset into the buffer where the dma is currently at. We 465 * check if the dma buffer has just wrapped. 466 */ 467 ptr = PERIOD_OFFSET(rt->dma_addr, 468 siu_stream->cur_period, 469 siu_stream->period_bytes) - rt->dma_addr; 470 471 dev_dbg(dev, 472 "%s: port=%d, events %x, FSTS %x, xferred %u/%u, cookie %d\n", 473 __func__, info->port_id, siu_read32(base + SIU_EVNTC), 474 siu_read32(base + SIU_SBFSTS), ptr, siu_stream->buf_bytes, 475 siu_stream->cookie); 476 477 if (ptr >= siu_stream->buf_bytes) 478 ptr = 0; 479 480 return bytes_to_frames(ss->runtime, ptr); 481 } 482 483 static int siu_pcm_new(struct snd_soc_component *component, 484 struct snd_soc_pcm_runtime *rtd) 485 { 486 /* card->dev == socdev->dev, see snd_soc_new_pcms() */ 487 struct snd_card *card = rtd->card->snd_card; 488 struct snd_pcm *pcm = rtd->pcm; 489 struct siu_info *info = siu_i2s_data; 490 struct platform_device *pdev = to_platform_device(card->dev); 491 int ret; 492 int i; 493 494 /* pdev->id selects between SIUA and SIUB */ 495 if (pdev->id < 0 || pdev->id >= SIU_PORT_NUM) 496 return -EINVAL; 497 498 info->port_id = pdev->id; 499 500 /* 501 * While the siu has 2 ports, only one port can be on at a time (only 1 502 * SPB). So far all the boards using the siu had only one of the ports 503 * wired to a codec. To simplify things, we only register one port with 504 * alsa. In case both ports are needed, it should be changed here 505 */ 506 for (i = pdev->id; i < pdev->id + 1; i++) { 507 struct siu_port **port_info = &siu_ports[i]; 508 509 ret = siu_init_port(i, port_info, card); 510 if (ret < 0) 511 return ret; 512 513 snd_pcm_set_managed_buffer_all(pcm, 514 SNDRV_DMA_TYPE_DEV, card->dev, 515 SIU_BUFFER_BYTES_MAX, SIU_BUFFER_BYTES_MAX); 516 517 (*port_info)->pcm = pcm; 518 519 /* IO works */ 520 INIT_WORK(&(*port_info)->playback.work, siu_io_work); 521 INIT_WORK(&(*port_info)->capture.work, siu_io_work); 522 } 523 524 dev_info(card->dev, "SuperH SIU driver initialized.\n"); 525 return 0; 526 } 527 528 static void siu_pcm_free(struct snd_soc_component *component, 529 struct snd_pcm *pcm) 530 { 531 struct platform_device *pdev = to_platform_device(pcm->card->dev); 532 struct siu_port *port_info = siu_ports[pdev->id]; 533 534 cancel_work_sync(&port_info->capture.work); 535 cancel_work_sync(&port_info->playback.work); 536 537 siu_free_port(port_info); 538 539 dev_dbg(pcm->card->dev, "%s\n", __func__); 540 } 541 542 const struct snd_soc_component_driver siu_component = { 543 .name = DRV_NAME, 544 .open = siu_pcm_open, 545 .close = siu_pcm_close, 546 .prepare = siu_pcm_prepare, 547 .trigger = siu_pcm_trigger, 548 .pointer = siu_pcm_pointer_dma, 549 .pcm_construct = siu_pcm_new, 550 .pcm_destruct = siu_pcm_free, 551 .legacy_dai_naming = 1, 552 }; 553 EXPORT_SYMBOL_GPL(siu_component); 554
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.