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 tasklet_schedule(&siu_stream->tasklet); 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 tasklet_schedule(&siu_stream->tasklet); 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_tasklet(unsigned long data) 202 { 203 struct siu_stream *siu_stream = (struct siu_stream *)data; 204 struct snd_pcm_substream *substream = siu_stream->substream; 205 struct device *dev = substream->pcm->card->dev; 206 struct snd_pcm_runtime *rt = substream->runtime; 207 struct siu_port *port_info = siu_port_info(substream); 208 209 dev_dbg(dev, "%s: flags %x\n", __func__, siu_stream->rw_flg); 210 211 if (!siu_stream->rw_flg) { 212 dev_dbg(dev, "%s: stream inactive\n", __func__); 213 return; 214 } 215 216 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { 217 dma_addr_t buff; 218 size_t count; 219 u8 *virt; 220 221 buff = (dma_addr_t)PERIOD_OFFSET(rt->dma_addr, 222 siu_stream->cur_period, 223 siu_stream->period_bytes); 224 virt = PERIOD_OFFSET(rt->dma_area, 225 siu_stream->cur_period, 226 siu_stream->period_bytes); 227 count = siu_stream->period_bytes; 228 229 /* DMA transfer start */ 230 siu_pcm_rd_set(port_info, buff, count); 231 } else { 232 siu_pcm_wr_set(port_info, 233 (dma_addr_t)PERIOD_OFFSET(rt->dma_addr, 234 siu_stream->cur_period, 235 siu_stream->period_bytes), 236 siu_stream->period_bytes); 237 } 238 } 239 240 /* Capture */ 241 static int siu_pcm_stmread_start(struct siu_port *port_info) 242 { 243 struct siu_stream *siu_stream = &port_info->capture; 244 245 if (siu_stream->xfer_cnt > 0x1000000) 246 return -EINVAL; 247 if (siu_stream->rw_flg) 248 return -EPERM; 249 250 /* Current period in buffer */ 251 siu_stream->cur_period = 0; 252 253 /* during stmread flag set */ 254 siu_stream->rw_flg = RWF_STM_RD; 255 256 tasklet_schedule(&siu_stream->tasklet); 257 258 return 0; 259 } 260 261 static int siu_pcm_stmread_stop(struct siu_port *port_info) 262 { 263 struct siu_info *info = siu_i2s_data; 264 u32 __iomem *base = info->reg; 265 struct siu_stream *siu_stream = &port_info->capture; 266 struct device *dev = siu_stream->substream->pcm->card->dev; 267 u32 stfifo; 268 269 if (!siu_stream->rw_flg) 270 return -EPERM; 271 272 /* input FIFO disable */ 273 stfifo = siu_read32(base + SIU_STFIFO); 274 siu_write32(base + SIU_STFIFO, stfifo & ~0x13071307); 275 dev_dbg(dev, "%s: STFIFO %x -> %x\n", __func__, 276 stfifo, stfifo & ~0x13071307); 277 278 /* during stmread flag clear */ 279 siu_stream->rw_flg = 0; 280 281 return 0; 282 } 283 284 static bool filter(struct dma_chan *chan, void *secondary) 285 { 286 struct sh_dmae_slave *param = secondary; 287 288 pr_debug("%s: secondary ID %d\n", __func__, param->shdma_slave.slave_id); 289 290 chan->private = ¶m->shdma_slave; 291 return true; 292 } 293 294 static int siu_pcm_open(struct snd_soc_component *component, 295 struct snd_pcm_substream *ss) 296 { 297 /* Playback / Capture */ 298 struct siu_platform *pdata = component->dev->platform_data; 299 struct siu_info *info = siu_i2s_data; 300 struct siu_port *port_info = siu_port_info(ss); 301 struct siu_stream *siu_stream; 302 u32 port = info->port_id; 303 struct device *dev = ss->pcm->card->dev; 304 dma_cap_mask_t mask; 305 struct sh_dmae_slave *param; 306 307 dma_cap_zero(mask); 308 dma_cap_set(DMA_SLAVE, mask); 309 310 dev_dbg(dev, "%s, port=%d@%p\n", __func__, port, port_info); 311 312 if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK) { 313 siu_stream = &port_info->playback; 314 param = &siu_stream->param; 315 param->shdma_slave.slave_id = port ? pdata->dma_slave_tx_b : 316 pdata->dma_slave_tx_a; 317 } else { 318 siu_stream = &port_info->capture; 319 param = &siu_stream->param; 320 param->shdma_slave.slave_id = port ? pdata->dma_slave_rx_b : 321 pdata->dma_slave_rx_a; 322 } 323 324 /* Get DMA channel */ 325 siu_stream->chan = dma_request_channel(mask, filter, param); 326 if (!siu_stream->chan) { 327 dev_err(dev, "DMA channel allocation failed!\n"); 328 return -EBUSY; 329 } 330 331 siu_stream->substream = ss; 332 333 return 0; 334 } 335 336 static int siu_pcm_close(struct snd_soc_component *component, 337 struct snd_pcm_substream *ss) 338 { 339 struct siu_info *info = siu_i2s_data; 340 struct device *dev = ss->pcm->card->dev; 341 struct siu_port *port_info = siu_port_info(ss); 342 struct siu_stream *siu_stream; 343 344 dev_dbg(dev, "%s: port=%d\n", __func__, info->port_id); 345 346 if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK) 347 siu_stream = &port_info->playback; 348 else 349 siu_stream = &port_info->capture; 350 351 dma_release_channel(siu_stream->chan); 352 siu_stream->chan = NULL; 353 354 siu_stream->substream = NULL; 355 356 return 0; 357 } 358 359 static int siu_pcm_prepare(struct snd_soc_component *component, 360 struct snd_pcm_substream *ss) 361 { 362 struct siu_info *info = siu_i2s_data; 363 struct siu_port *port_info = siu_port_info(ss); 364 struct device *dev = ss->pcm->card->dev; 365 struct snd_pcm_runtime *rt = ss->runtime; 366 struct siu_stream *siu_stream; 367 snd_pcm_sframes_t xfer_cnt; 368 369 if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK) 370 siu_stream = &port_info->playback; 371 else 372 siu_stream = &port_info->capture; 373 374 rt = siu_stream->substream->runtime; 375 376 siu_stream->buf_bytes = snd_pcm_lib_buffer_bytes(ss); 377 siu_stream->period_bytes = snd_pcm_lib_period_bytes(ss); 378 379 dev_dbg(dev, "%s: port=%d, %d channels, period=%u bytes\n", __func__, 380 info->port_id, rt->channels, siu_stream->period_bytes); 381 382 /* We only support buffers that are multiples of the period */ 383 if (siu_stream->buf_bytes % siu_stream->period_bytes) { 384 dev_err(dev, "%s() - buffer=%d not multiple of period=%d\n", 385 __func__, siu_stream->buf_bytes, 386 siu_stream->period_bytes); 387 return -EINVAL; 388 } 389 390 xfer_cnt = bytes_to_frames(rt, siu_stream->period_bytes); 391 if (!xfer_cnt || xfer_cnt > 0x1000000) 392 return -EINVAL; 393 394 siu_stream->format = rt->format; 395 siu_stream->xfer_cnt = xfer_cnt; 396 397 dev_dbg(dev, "port=%d buf=%lx buf_bytes=%d period_bytes=%d " 398 "format=%d channels=%d xfer_cnt=%d\n", info->port_id, 399 (unsigned long)rt->dma_addr, siu_stream->buf_bytes, 400 siu_stream->period_bytes, 401 siu_stream->format, rt->channels, (int)xfer_cnt); 402 403 return 0; 404 } 405 406 static int siu_pcm_trigger(struct snd_soc_component *component, 407 struct snd_pcm_substream *ss, int cmd) 408 { 409 struct siu_info *info = siu_i2s_data; 410 struct device *dev = ss->pcm->card->dev; 411 struct siu_port *port_info = siu_port_info(ss); 412 int ret; 413 414 dev_dbg(dev, "%s: port=%d@%p, cmd=%d\n", __func__, 415 info->port_id, port_info, cmd); 416 417 switch (cmd) { 418 case SNDRV_PCM_TRIGGER_START: 419 if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK) 420 ret = siu_pcm_stmwrite_start(port_info); 421 else 422 ret = siu_pcm_stmread_start(port_info); 423 424 if (ret < 0) 425 dev_warn(dev, "%s: start failed on port=%d\n", 426 __func__, info->port_id); 427 428 break; 429 case SNDRV_PCM_TRIGGER_STOP: 430 if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK) 431 siu_pcm_stmwrite_stop(port_info); 432 else 433 siu_pcm_stmread_stop(port_info); 434 ret = 0; 435 436 break; 437 default: 438 dev_err(dev, "%s() unsupported cmd=%d\n", __func__, cmd); 439 ret = -EINVAL; 440 } 441 442 return ret; 443 } 444 445 /* 446 * So far only resolution of one period is supported, subject to extending the 447 * dmangine API 448 */ 449 static snd_pcm_uframes_t 450 siu_pcm_pointer_dma(struct snd_soc_component *component, 451 struct snd_pcm_substream *ss) 452 { 453 struct device *dev = ss->pcm->card->dev; 454 struct siu_info *info = siu_i2s_data; 455 u32 __iomem *base = info->reg; 456 struct siu_port *port_info = siu_port_info(ss); 457 struct snd_pcm_runtime *rt = ss->runtime; 458 size_t ptr; 459 struct siu_stream *siu_stream; 460 461 if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK) 462 siu_stream = &port_info->playback; 463 else 464 siu_stream = &port_info->capture; 465 466 /* 467 * ptr is the offset into the buffer where the dma is currently at. We 468 * check if the dma buffer has just wrapped. 469 */ 470 ptr = PERIOD_OFFSET(rt->dma_addr, 471 siu_stream->cur_period, 472 siu_stream->period_bytes) - rt->dma_addr; 473 474 dev_dbg(dev, 475 "%s: port=%d, events %x, FSTS %x, xferred %u/%u, cookie %d\n", 476 __func__, info->port_id, siu_read32(base + SIU_EVNTC), 477 siu_read32(base + SIU_SBFSTS), ptr, siu_stream->buf_bytes, 478 siu_stream->cookie); 479 480 if (ptr >= siu_stream->buf_bytes) 481 ptr = 0; 482 483 return bytes_to_frames(ss->runtime, ptr); 484 } 485 486 static int siu_pcm_new(struct snd_soc_component *component, 487 struct snd_soc_pcm_runtime *rtd) 488 { 489 /* card->dev == socdev->dev, see snd_soc_new_pcms() */ 490 struct snd_card *card = rtd->card->snd_card; 491 struct snd_pcm *pcm = rtd->pcm; 492 struct siu_info *info = siu_i2s_data; 493 struct platform_device *pdev = to_platform_device(card->dev); 494 int ret; 495 int i; 496 497 /* pdev->id selects between SIUA and SIUB */ 498 if (pdev->id < 0 || pdev->id >= SIU_PORT_NUM) 499 return -EINVAL; 500 501 info->port_id = pdev->id; 502 503 /* 504 * While the siu has 2 ports, only one port can be on at a time (only 1 505 * SPB). So far all the boards using the siu had only one of the ports 506 * wired to a codec. To simplify things, we only register one port with 507 * alsa. In case both ports are needed, it should be changed here 508 */ 509 for (i = pdev->id; i < pdev->id + 1; i++) { 510 struct siu_port **port_info = &siu_ports[i]; 511 512 ret = siu_init_port(i, port_info, card); 513 if (ret < 0) 514 return ret; 515 516 snd_pcm_set_managed_buffer_all(pcm, 517 SNDRV_DMA_TYPE_DEV, card->dev, 518 SIU_BUFFER_BYTES_MAX, SIU_BUFFER_BYTES_MAX); 519 520 (*port_info)->pcm = pcm; 521 522 /* IO tasklets */ 523 tasklet_init(&(*port_info)->playback.tasklet, siu_io_tasklet, 524 (unsigned long)&(*port_info)->playback); 525 tasklet_init(&(*port_info)->capture.tasklet, siu_io_tasklet, 526 (unsigned long)&(*port_info)->capture); 527 } 528 529 dev_info(card->dev, "SuperH SIU driver initialized.\n"); 530 return 0; 531 } 532 533 static void siu_pcm_free(struct snd_soc_component *component, 534 struct snd_pcm *pcm) 535 { 536 struct platform_device *pdev = to_platform_device(pcm->card->dev); 537 struct siu_port *port_info = siu_ports[pdev->id]; 538 539 tasklet_kill(&port_info->capture.tasklet); 540 tasklet_kill(&port_info->playback.tasklet); 541 542 siu_free_port(port_info); 543 544 dev_dbg(pcm->card->dev, "%s\n", __func__); 545 } 546 547 struct const snd_soc_component_driver siu_component = { 548 .name = DRV_NAME, 549 .open = siu_pcm_open, 550 .close = siu_pcm_close, 551 .prepare = siu_pcm_prepare, 552 .trigger = siu_pcm_trigger, 553 .pointer = siu_pcm_pointer_dma, 554 .pcm_construct = siu_pcm_new, 555 .pcm_destruct = siu_pcm_free, 556 }; 557 EXPORT_SYMBOL_GPL(siu_component); 558