Lines Matching +full:omap +full:- +full:sdma
1 // SPDX-License-Identifier: GPL-2.0-only
3 * omap-mcpdm.c -- OMAP ALSA SoC DAI driver using McPDM port
5 * Copyright (C) 2009 - 2011 Texas Instruments
30 #include "omap-mcpdm.h"
31 #include "sdma-pcm.h"
69 writel_relaxed(val, mcpdm->io_base + reg); in omap_mcpdm_write()
74 return readl_relaxed(mcpdm->io_base + reg); in omap_mcpdm_read()
80 dev_dbg(mcpdm->dev, "***********************\n"); in omap_mcpdm_reg_dump()
81 dev_dbg(mcpdm->dev, "IRQSTATUS_RAW: 0x%04x\n", in omap_mcpdm_reg_dump()
83 dev_dbg(mcpdm->dev, "IRQSTATUS: 0x%04x\n", in omap_mcpdm_reg_dump()
85 dev_dbg(mcpdm->dev, "IRQENABLE_SET: 0x%04x\n", in omap_mcpdm_reg_dump()
87 dev_dbg(mcpdm->dev, "IRQENABLE_CLR: 0x%04x\n", in omap_mcpdm_reg_dump()
89 dev_dbg(mcpdm->dev, "IRQWAKE_EN: 0x%04x\n", in omap_mcpdm_reg_dump()
91 dev_dbg(mcpdm->dev, "DMAENABLE_SET: 0x%04x\n", in omap_mcpdm_reg_dump()
93 dev_dbg(mcpdm->dev, "DMAENABLE_CLR: 0x%04x\n", in omap_mcpdm_reg_dump()
95 dev_dbg(mcpdm->dev, "DMAWAKEEN: 0x%04x\n", in omap_mcpdm_reg_dump()
97 dev_dbg(mcpdm->dev, "CTRL: 0x%04x\n", in omap_mcpdm_reg_dump()
99 dev_dbg(mcpdm->dev, "DN_DATA: 0x%04x\n", in omap_mcpdm_reg_dump()
101 dev_dbg(mcpdm->dev, "UP_DATA: 0x%04x\n", in omap_mcpdm_reg_dump()
103 dev_dbg(mcpdm->dev, "FIFO_CTRL_DN: 0x%04x\n", in omap_mcpdm_reg_dump()
105 dev_dbg(mcpdm->dev, "FIFO_CTRL_UP: 0x%04x\n", in omap_mcpdm_reg_dump()
107 dev_dbg(mcpdm->dev, "***********************\n"); in omap_mcpdm_reg_dump()
120 u32 link_mask = mcpdm->config[0].link_mask | mcpdm->config[1].link_mask; in omap_mcpdm_start()
176 if (mcpdm->dn_rx_offset) { in omap_mcpdm_open_streams()
177 u32 dn_offset = mcpdm->dn_rx_offset; in omap_mcpdm_open_streams()
185 mcpdm->config[SNDRV_PCM_STREAM_PLAYBACK].threshold); in omap_mcpdm_open_streams()
187 mcpdm->config[SNDRV_PCM_STREAM_CAPTURE].threshold); in omap_mcpdm_open_streams()
214 if (mcpdm->dn_rx_offset) in omap_mcpdm_close_streams()
229 dev_dbg(mcpdm->dev, "DN (playback) FIFO Full\n"); in omap_mcpdm_irq_handler()
232 dev_dbg(mcpdm->dev, "DN (playback) FIFO Empty\n"); in omap_mcpdm_irq_handler()
235 dev_dbg(mcpdm->dev, "DN (playback) write request\n"); in omap_mcpdm_irq_handler()
238 dev_dbg(mcpdm->dev, "UP (capture) FIFO Full\n"); in omap_mcpdm_irq_handler()
241 dev_dbg(mcpdm->dev, "UP (capture) FIFO Empty\n"); in omap_mcpdm_irq_handler()
244 dev_dbg(mcpdm->dev, "UP (capture) write request\n"); in omap_mcpdm_irq_handler()
254 mutex_lock(&mcpdm->mutex); in omap_mcpdm_dai_startup()
259 mutex_unlock(&mcpdm->mutex); in omap_mcpdm_dai_startup()
268 int tx = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); in omap_mcpdm_dai_shutdown()
272 mutex_lock(&mcpdm->mutex); in omap_mcpdm_dai_shutdown()
278 mcpdm->config[0].link_mask = 0; in omap_mcpdm_dai_shutdown()
279 mcpdm->config[1].link_mask = 0; in omap_mcpdm_dai_shutdown()
283 if (mcpdm->latency[stream2]) in omap_mcpdm_dai_shutdown()
284 cpu_latency_qos_update_request(&mcpdm->pm_qos_req, in omap_mcpdm_dai_shutdown()
285 mcpdm->latency[stream2]); in omap_mcpdm_dai_shutdown()
286 else if (mcpdm->latency[stream1]) in omap_mcpdm_dai_shutdown()
287 cpu_latency_qos_remove_request(&mcpdm->pm_qos_req); in omap_mcpdm_dai_shutdown()
289 mcpdm->latency[stream1] = 0; in omap_mcpdm_dai_shutdown()
291 mutex_unlock(&mcpdm->mutex); in omap_mcpdm_dai_shutdown()
299 int stream = substream->stream; in omap_mcpdm_dai_hw_params()
310 return -EINVAL; in omap_mcpdm_dai_hw_params()
316 return -EINVAL; in omap_mcpdm_dai_hw_params()
330 return -EINVAL; in omap_mcpdm_dai_hw_params()
335 threshold = mcpdm->config[stream].threshold; in omap_mcpdm_dai_hw_params()
341 if (!mcpdm->config[!stream].link_mask) in omap_mcpdm_dai_hw_params()
342 mcpdm->config[!stream].link_mask = 0x3; in omap_mcpdm_dai_hw_params()
344 dma_data->maxburst = in omap_mcpdm_dai_hw_params()
345 (MCPDM_DN_THRES_MAX - threshold) * channels; in omap_mcpdm_dai_hw_params()
349 if (!mcpdm->config[!stream].link_mask) in omap_mcpdm_dai_hw_params()
350 mcpdm->config[!stream].link_mask = (0x3 << 3); in omap_mcpdm_dai_hw_params()
352 dma_data->maxburst = threshold * channels; in omap_mcpdm_dai_hw_params()
353 latency = (MCPDM_DN_THRES_MAX - threshold); in omap_mcpdm_dai_hw_params()
360 mcpdm->latency[stream] = latency * USEC_PER_SEC / params_rate(params); in omap_mcpdm_dai_hw_params()
362 if (!mcpdm->latency[stream]) in omap_mcpdm_dai_hw_params()
363 mcpdm->latency[stream] = 10; in omap_mcpdm_dai_hw_params()
366 if (mcpdm->config[stream].link_mask && in omap_mcpdm_dai_hw_params()
367 mcpdm->config[stream].link_mask != link_mask) in omap_mcpdm_dai_hw_params()
368 mcpdm->restart = true; in omap_mcpdm_dai_hw_params()
370 mcpdm->config[stream].link_mask = link_mask; in omap_mcpdm_dai_hw_params()
379 struct pm_qos_request *pm_qos_req = &mcpdm->pm_qos_req; in omap_mcpdm_prepare()
380 int tx = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); in omap_mcpdm_prepare()
383 int latency = mcpdm->latency[stream2]; in omap_mcpdm_prepare()
385 /* Prevent omap hardware from hitting off between FIFO fills */ in omap_mcpdm_prepare()
386 if (!latency || mcpdm->latency[stream1] < latency) in omap_mcpdm_prepare()
387 latency = mcpdm->latency[stream1]; in omap_mcpdm_prepare()
397 } else if (mcpdm->restart) { in omap_mcpdm_prepare()
400 mcpdm->restart = false; in omap_mcpdm_prepare()
419 pm_runtime_enable(mcpdm->dev); in omap_mcpdm_probe()
422 pm_runtime_get_sync(mcpdm->dev); in omap_mcpdm_probe()
425 ret = request_irq(mcpdm->irq, omap_mcpdm_irq_handler, 0, "McPDM", in omap_mcpdm_probe()
428 pm_runtime_put_sync(mcpdm->dev); in omap_mcpdm_probe()
431 dev_err(mcpdm->dev, "Request for IRQ failed\n"); in omap_mcpdm_probe()
432 pm_runtime_disable(mcpdm->dev); in omap_mcpdm_probe()
436 mcpdm->config[SNDRV_PCM_STREAM_PLAYBACK].threshold = 2; in omap_mcpdm_probe()
437 mcpdm->config[SNDRV_PCM_STREAM_CAPTURE].threshold = in omap_mcpdm_probe()
438 MCPDM_UP_THRES_MAX - 3; in omap_mcpdm_probe()
441 &mcpdm->dma_data[SNDRV_PCM_STREAM_PLAYBACK], in omap_mcpdm_probe()
442 &mcpdm->dma_data[SNDRV_PCM_STREAM_CAPTURE]); in omap_mcpdm_probe()
451 free_irq(mcpdm->irq, (void *)mcpdm); in omap_mcpdm_remove()
452 pm_runtime_disable(mcpdm->dev); in omap_mcpdm_remove()
454 if (cpu_latency_qos_request_active(&mcpdm->pm_qos_req)) in omap_mcpdm_remove()
455 cpu_latency_qos_remove_request(&mcpdm->pm_qos_req); in omap_mcpdm_remove()
470 mcpdm->pm_active_count = 0; in omap_mcpdm_suspend()
471 while (pm_runtime_active(mcpdm->dev)) { in omap_mcpdm_suspend()
472 pm_runtime_put_sync(mcpdm->dev); in omap_mcpdm_suspend()
473 mcpdm->pm_active_count++; in omap_mcpdm_suspend()
483 if (mcpdm->pm_active_count) { in omap_mcpdm_resume()
484 while (mcpdm->pm_active_count--) in omap_mcpdm_resume()
485 pm_runtime_get_sync(mcpdm->dev); in omap_mcpdm_resume()
527 .name = "omap-mcpdm",
537 mcpdm->dn_rx_offset = MCPDM_DNOFST_RX1(rx1) | MCPDM_DNOFST_RX2(rx2); in omap_mcpdm_configure_dn_offsets()
547 mcpdm = devm_kzalloc(&pdev->dev, sizeof(struct omap_mcpdm), GFP_KERNEL); in asoc_mcpdm_probe()
549 return -ENOMEM; in asoc_mcpdm_probe()
553 mutex_init(&mcpdm->mutex); in asoc_mcpdm_probe()
557 return -ENOMEM; in asoc_mcpdm_probe()
559 mcpdm->dma_data[0].addr = res->start + MCPDM_REG_DN_DATA; in asoc_mcpdm_probe()
560 mcpdm->dma_data[1].addr = res->start + MCPDM_REG_UP_DATA; in asoc_mcpdm_probe()
562 mcpdm->dma_data[0].filter_data = "dn_link"; in asoc_mcpdm_probe()
563 mcpdm->dma_data[1].filter_data = "up_link"; in asoc_mcpdm_probe()
566 mcpdm->io_base = devm_ioremap_resource(&pdev->dev, res); in asoc_mcpdm_probe()
567 if (IS_ERR(mcpdm->io_base)) in asoc_mcpdm_probe()
568 return PTR_ERR(mcpdm->io_base); in asoc_mcpdm_probe()
570 mcpdm->irq = platform_get_irq(pdev, 0); in asoc_mcpdm_probe()
571 if (mcpdm->irq < 0) in asoc_mcpdm_probe()
572 return mcpdm->irq; in asoc_mcpdm_probe()
574 mcpdm->dev = &pdev->dev; in asoc_mcpdm_probe()
576 ret = devm_snd_soc_register_component(&pdev->dev, in asoc_mcpdm_probe()
582 return sdma_pcm_platform_register(&pdev->dev, "dn_link", "up_link"); in asoc_mcpdm_probe()
586 { .compatible = "ti,omap4-mcpdm", },
593 .name = "omap-mcpdm",
602 MODULE_ALIAS("platform:omap-mcpdm");
604 MODULE_DESCRIPTION("OMAP PDM SoC Interface");