| .. | .. |
|---|
| 70 | 70 | siu_stream->rw_flg = RWF_STM_WT; |
|---|
| 71 | 71 | |
|---|
| 72 | 72 | /* DMA transfer start */ |
|---|
| 73 | | - tasklet_schedule(&siu_stream->tasklet); |
|---|
| 73 | + queue_work(system_highpri_wq, &siu_stream->work); |
|---|
| 74 | 74 | |
|---|
| 75 | 75 | return 0; |
|---|
| 76 | 76 | } |
|---|
| .. | .. |
|---|
| 93 | 93 | siu_stream->cur_period * siu_stream->period_bytes, |
|---|
| 94 | 94 | siu_stream->buf_bytes, siu_stream->cookie); |
|---|
| 95 | 95 | |
|---|
| 96 | | - tasklet_schedule(&siu_stream->tasklet); |
|---|
| 96 | + queue_work(system_highpri_wq, &siu_stream->work); |
|---|
| 97 | 97 | |
|---|
| 98 | 98 | /* Notify alsa: a period is done */ |
|---|
| 99 | 99 | snd_pcm_period_elapsed(siu_stream->substream); |
|---|
| .. | .. |
|---|
| 198 | 198 | return 0; |
|---|
| 199 | 199 | } |
|---|
| 200 | 200 | |
|---|
| 201 | | -static void siu_io_tasklet(unsigned long data) |
|---|
| 201 | +static void siu_io_work(struct work_struct *work) |
|---|
| 202 | 202 | { |
|---|
| 203 | | - struct siu_stream *siu_stream = (struct siu_stream *)data; |
|---|
| 203 | + struct siu_stream *siu_stream = container_of(work, struct siu_stream, |
|---|
| 204 | + work); |
|---|
| 204 | 205 | struct snd_pcm_substream *substream = siu_stream->substream; |
|---|
| 205 | 206 | struct device *dev = substream->pcm->card->dev; |
|---|
| 206 | 207 | struct snd_pcm_runtime *rt = substream->runtime; |
|---|
| .. | .. |
|---|
| 253 | 254 | /* during stmread flag set */ |
|---|
| 254 | 255 | siu_stream->rw_flg = RWF_STM_RD; |
|---|
| 255 | 256 | |
|---|
| 256 | | - tasklet_schedule(&siu_stream->tasklet); |
|---|
| 257 | + queue_work(system_highpri_wq, &siu_stream->work); |
|---|
| 257 | 258 | |
|---|
| 258 | 259 | return 0; |
|---|
| 259 | 260 | } |
|---|
| .. | .. |
|---|
| 281 | 282 | return 0; |
|---|
| 282 | 283 | } |
|---|
| 283 | 284 | |
|---|
| 284 | | -static int siu_pcm_hw_params(struct snd_pcm_substream *ss, |
|---|
| 285 | | - struct snd_pcm_hw_params *hw_params) |
|---|
| 285 | +static bool filter(struct dma_chan *chan, void *secondary) |
|---|
| 286 | 286 | { |
|---|
| 287 | | - struct siu_info *info = siu_i2s_data; |
|---|
| 288 | | - struct device *dev = ss->pcm->card->dev; |
|---|
| 289 | | - int ret; |
|---|
| 287 | + struct sh_dmae_slave *param = secondary; |
|---|
| 290 | 288 | |
|---|
| 291 | | - dev_dbg(dev, "%s: port=%d\n", __func__, info->port_id); |
|---|
| 292 | | - |
|---|
| 293 | | - ret = snd_pcm_lib_malloc_pages(ss, params_buffer_bytes(hw_params)); |
|---|
| 294 | | - if (ret < 0) |
|---|
| 295 | | - dev_err(dev, "snd_pcm_lib_malloc_pages() failed\n"); |
|---|
| 296 | | - |
|---|
| 297 | | - return ret; |
|---|
| 298 | | -} |
|---|
| 299 | | - |
|---|
| 300 | | -static int siu_pcm_hw_free(struct snd_pcm_substream *ss) |
|---|
| 301 | | -{ |
|---|
| 302 | | - struct siu_info *info = siu_i2s_data; |
|---|
| 303 | | - struct siu_port *port_info = siu_port_info(ss); |
|---|
| 304 | | - struct device *dev = ss->pcm->card->dev; |
|---|
| 305 | | - struct siu_stream *siu_stream; |
|---|
| 306 | | - |
|---|
| 307 | | - if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK) |
|---|
| 308 | | - siu_stream = &port_info->playback; |
|---|
| 309 | | - else |
|---|
| 310 | | - siu_stream = &port_info->capture; |
|---|
| 311 | | - |
|---|
| 312 | | - dev_dbg(dev, "%s: port=%d\n", __func__, info->port_id); |
|---|
| 313 | | - |
|---|
| 314 | | - return snd_pcm_lib_free_pages(ss); |
|---|
| 315 | | -} |
|---|
| 316 | | - |
|---|
| 317 | | -static bool filter(struct dma_chan *chan, void *slave) |
|---|
| 318 | | -{ |
|---|
| 319 | | - struct sh_dmae_slave *param = slave; |
|---|
| 320 | | - |
|---|
| 321 | | - pr_debug("%s: slave ID %d\n", __func__, param->shdma_slave.slave_id); |
|---|
| 289 | + pr_debug("%s: secondary ID %d\n", __func__, param->shdma_slave.slave_id); |
|---|
| 322 | 290 | |
|---|
| 323 | 291 | chan->private = ¶m->shdma_slave; |
|---|
| 324 | 292 | return true; |
|---|
| 325 | 293 | } |
|---|
| 326 | 294 | |
|---|
| 327 | | -static int siu_pcm_open(struct snd_pcm_substream *ss) |
|---|
| 295 | +static int siu_pcm_open(struct snd_soc_component *component, |
|---|
| 296 | + struct snd_pcm_substream *ss) |
|---|
| 328 | 297 | { |
|---|
| 329 | 298 | /* Playback / Capture */ |
|---|
| 330 | | - struct snd_soc_pcm_runtime *rtd = ss->private_data; |
|---|
| 331 | | - struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME); |
|---|
| 332 | 299 | struct siu_platform *pdata = component->dev->platform_data; |
|---|
| 333 | 300 | struct siu_info *info = siu_i2s_data; |
|---|
| 334 | 301 | struct siu_port *port_info = siu_port_info(ss); |
|---|
| .. | .. |
|---|
| 367 | 334 | return 0; |
|---|
| 368 | 335 | } |
|---|
| 369 | 336 | |
|---|
| 370 | | -static int siu_pcm_close(struct snd_pcm_substream *ss) |
|---|
| 337 | +static int siu_pcm_close(struct snd_soc_component *component, |
|---|
| 338 | + struct snd_pcm_substream *ss) |
|---|
| 371 | 339 | { |
|---|
| 372 | 340 | struct siu_info *info = siu_i2s_data; |
|---|
| 373 | 341 | struct device *dev = ss->pcm->card->dev; |
|---|
| .. | .. |
|---|
| 389 | 357 | return 0; |
|---|
| 390 | 358 | } |
|---|
| 391 | 359 | |
|---|
| 392 | | -static int siu_pcm_prepare(struct snd_pcm_substream *ss) |
|---|
| 360 | +static int siu_pcm_prepare(struct snd_soc_component *component, |
|---|
| 361 | + struct snd_pcm_substream *ss) |
|---|
| 393 | 362 | { |
|---|
| 394 | 363 | struct siu_info *info = siu_i2s_data; |
|---|
| 395 | 364 | struct siu_port *port_info = siu_port_info(ss); |
|---|
| .. | .. |
|---|
| 435 | 404 | return 0; |
|---|
| 436 | 405 | } |
|---|
| 437 | 406 | |
|---|
| 438 | | -static int siu_pcm_trigger(struct snd_pcm_substream *ss, int cmd) |
|---|
| 407 | +static int siu_pcm_trigger(struct snd_soc_component *component, |
|---|
| 408 | + struct snd_pcm_substream *ss, int cmd) |
|---|
| 439 | 409 | { |
|---|
| 440 | 410 | struct siu_info *info = siu_i2s_data; |
|---|
| 441 | 411 | struct device *dev = ss->pcm->card->dev; |
|---|
| .. | .. |
|---|
| 477 | 447 | * So far only resolution of one period is supported, subject to extending the |
|---|
| 478 | 448 | * dmangine API |
|---|
| 479 | 449 | */ |
|---|
| 480 | | -static snd_pcm_uframes_t siu_pcm_pointer_dma(struct snd_pcm_substream *ss) |
|---|
| 450 | +static snd_pcm_uframes_t |
|---|
| 451 | +siu_pcm_pointer_dma(struct snd_soc_component *component, |
|---|
| 452 | + struct snd_pcm_substream *ss) |
|---|
| 481 | 453 | { |
|---|
| 482 | 454 | struct device *dev = ss->pcm->card->dev; |
|---|
| 483 | 455 | struct siu_info *info = siu_i2s_data; |
|---|
| .. | .. |
|---|
| 512 | 484 | return bytes_to_frames(ss->runtime, ptr); |
|---|
| 513 | 485 | } |
|---|
| 514 | 486 | |
|---|
| 515 | | -static int siu_pcm_new(struct snd_soc_pcm_runtime *rtd) |
|---|
| 487 | +static int siu_pcm_new(struct snd_soc_component *component, |
|---|
| 488 | + struct snd_soc_pcm_runtime *rtd) |
|---|
| 516 | 489 | { |
|---|
| 517 | 490 | /* card->dev == socdev->dev, see snd_soc_new_pcms() */ |
|---|
| 518 | 491 | struct snd_card *card = rtd->card->snd_card; |
|---|
| .. | .. |
|---|
| 541 | 514 | if (ret < 0) |
|---|
| 542 | 515 | return ret; |
|---|
| 543 | 516 | |
|---|
| 544 | | - ret = snd_pcm_lib_preallocate_pages_for_all(pcm, |
|---|
| 545 | | - SNDRV_DMA_TYPE_DEV, NULL, |
|---|
| 517 | + snd_pcm_set_managed_buffer_all(pcm, |
|---|
| 518 | + SNDRV_DMA_TYPE_DEV, card->dev, |
|---|
| 546 | 519 | SIU_BUFFER_BYTES_MAX, SIU_BUFFER_BYTES_MAX); |
|---|
| 547 | | - if (ret < 0) { |
|---|
| 548 | | - dev_err(card->dev, |
|---|
| 549 | | - "snd_pcm_lib_preallocate_pages_for_all() err=%d", |
|---|
| 550 | | - ret); |
|---|
| 551 | | - goto fail; |
|---|
| 552 | | - } |
|---|
| 553 | 520 | |
|---|
| 554 | 521 | (*port_info)->pcm = pcm; |
|---|
| 555 | 522 | |
|---|
| 556 | | - /* IO tasklets */ |
|---|
| 557 | | - tasklet_init(&(*port_info)->playback.tasklet, siu_io_tasklet, |
|---|
| 558 | | - (unsigned long)&(*port_info)->playback); |
|---|
| 559 | | - tasklet_init(&(*port_info)->capture.tasklet, siu_io_tasklet, |
|---|
| 560 | | - (unsigned long)&(*port_info)->capture); |
|---|
| 523 | + /* IO works */ |
|---|
| 524 | + INIT_WORK(&(*port_info)->playback.work, siu_io_work); |
|---|
| 525 | + INIT_WORK(&(*port_info)->capture.work, siu_io_work); |
|---|
| 561 | 526 | } |
|---|
| 562 | 527 | |
|---|
| 563 | 528 | dev_info(card->dev, "SuperH SIU driver initialized.\n"); |
|---|
| 564 | 529 | return 0; |
|---|
| 565 | | - |
|---|
| 566 | | -fail: |
|---|
| 567 | | - siu_free_port(siu_ports[pdev->id]); |
|---|
| 568 | | - dev_err(card->dev, "SIU: failed to initialize.\n"); |
|---|
| 569 | | - return ret; |
|---|
| 570 | 530 | } |
|---|
| 571 | 531 | |
|---|
| 572 | | -static void siu_pcm_free(struct snd_pcm *pcm) |
|---|
| 532 | +static void siu_pcm_free(struct snd_soc_component *component, |
|---|
| 533 | + struct snd_pcm *pcm) |
|---|
| 573 | 534 | { |
|---|
| 574 | 535 | struct platform_device *pdev = to_platform_device(pcm->card->dev); |
|---|
| 575 | 536 | struct siu_port *port_info = siu_ports[pdev->id]; |
|---|
| 576 | 537 | |
|---|
| 577 | | - tasklet_kill(&port_info->capture.tasklet); |
|---|
| 578 | | - tasklet_kill(&port_info->playback.tasklet); |
|---|
| 538 | + cancel_work_sync(&port_info->capture.work); |
|---|
| 539 | + cancel_work_sync(&port_info->playback.work); |
|---|
| 579 | 540 | |
|---|
| 580 | 541 | siu_free_port(port_info); |
|---|
| 581 | 542 | |
|---|
| 582 | 543 | dev_dbg(pcm->card->dev, "%s\n", __func__); |
|---|
| 583 | 544 | } |
|---|
| 584 | 545 | |
|---|
| 585 | | -static const struct snd_pcm_ops siu_pcm_ops = { |
|---|
| 546 | +const struct snd_soc_component_driver siu_component = { |
|---|
| 547 | + .name = DRV_NAME, |
|---|
| 586 | 548 | .open = siu_pcm_open, |
|---|
| 587 | 549 | .close = siu_pcm_close, |
|---|
| 588 | | - .ioctl = snd_pcm_lib_ioctl, |
|---|
| 589 | | - .hw_params = siu_pcm_hw_params, |
|---|
| 590 | | - .hw_free = siu_pcm_hw_free, |
|---|
| 591 | 550 | .prepare = siu_pcm_prepare, |
|---|
| 592 | 551 | .trigger = siu_pcm_trigger, |
|---|
| 593 | 552 | .pointer = siu_pcm_pointer_dma, |
|---|
| 594 | | -}; |
|---|
| 595 | | - |
|---|
| 596 | | -struct snd_soc_component_driver siu_component = { |
|---|
| 597 | | - .name = DRV_NAME, |
|---|
| 598 | | - .ops = &siu_pcm_ops, |
|---|
| 599 | | - .pcm_new = siu_pcm_new, |
|---|
| 600 | | - .pcm_free = siu_pcm_free, |
|---|
| 553 | + .pcm_construct = siu_pcm_new, |
|---|
| 554 | + .pcm_destruct = siu_pcm_free, |
|---|
| 601 | 555 | }; |
|---|
| 602 | 556 | EXPORT_SYMBOL_GPL(siu_component); |
|---|