Lines Matching +full:stm32h7 +full:- +full:spdifrx
2 * STM32 ALSA SoC Digital Audio Interface (SPDIF-rx) driver.
4 * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
30 /* SPDIF-rx Register Map */
201 * struct stm32_spdifrx_data - private data of SPDIFRX
204 * @regmap: SPDIFRX register map pointer
205 * @regmap_conf: SPDIFRX register map configuration pointer
207 * @kclk: kernel clock feeding the SPDIFRX clock generator
214 * @phys_addr: SPDIFRX registers physical base address
219 * @irq: SPDIFRX interrupt line
246 struct stm32_spdifrx_data *spdifrx = (struct stm32_spdifrx_data *)data; in stm32_spdifrx_dma_complete() local
247 struct platform_device *pdev = spdifrx->pdev; in stm32_spdifrx_dma_complete()
248 u32 *p_start = (u32 *)spdifrx->dmab->area; in stm32_spdifrx_dma_complete()
249 u32 *p_end = p_start + (2 * SPDIFRX_CS_BYTES_NB) - 1; in stm32_spdifrx_dma_complete()
251 u16 *ub_ptr = (short *)spdifrx->ub; in stm32_spdifrx_dma_complete()
254 regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR, in stm32_spdifrx_dma_complete()
258 if (!spdifrx->dmab->area) in stm32_spdifrx_dma_complete()
268 dev_err(&pdev->dev, "Start of S/PDIF block not found\n"); in stm32_spdifrx_dma_complete()
273 spdifrx->cs[i] = (unsigned char)SPDIFRX_CSR_CSGET(*ptr); in stm32_spdifrx_dma_complete()
276 dev_err(&pdev->dev, "Failed to get channel status\n"); in stm32_spdifrx_dma_complete()
282 complete(&spdifrx->cs_completion); in stm32_spdifrx_dma_complete()
285 static int stm32_spdifrx_dma_ctrl_start(struct stm32_spdifrx_data *spdifrx) in stm32_spdifrx_dma_ctrl_start() argument
290 spdifrx->desc = dmaengine_prep_slave_single(spdifrx->ctrl_chan, in stm32_spdifrx_dma_ctrl_start()
291 spdifrx->dmab->addr, in stm32_spdifrx_dma_ctrl_start()
295 if (!spdifrx->desc) in stm32_spdifrx_dma_ctrl_start()
296 return -EINVAL; in stm32_spdifrx_dma_ctrl_start()
298 spdifrx->desc->callback = stm32_spdifrx_dma_complete; in stm32_spdifrx_dma_ctrl_start()
299 spdifrx->desc->callback_param = spdifrx; in stm32_spdifrx_dma_ctrl_start()
300 cookie = dmaengine_submit(spdifrx->desc); in stm32_spdifrx_dma_ctrl_start()
303 return -EINVAL; in stm32_spdifrx_dma_ctrl_start()
305 dma_async_issue_pending(spdifrx->ctrl_chan); in stm32_spdifrx_dma_ctrl_start()
310 static void stm32_spdifrx_dma_ctrl_stop(struct stm32_spdifrx_data *spdifrx) in stm32_spdifrx_dma_ctrl_stop() argument
312 dmaengine_terminate_async(spdifrx->ctrl_chan); in stm32_spdifrx_dma_ctrl_stop()
315 static int stm32_spdifrx_start_sync(struct stm32_spdifrx_data *spdifrx) in stm32_spdifrx_start_sync() argument
322 ret = regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_IMR, imr, imr); in stm32_spdifrx_start_sync()
326 spin_lock_irqsave(&spdifrx->lock, flags); in stm32_spdifrx_start_sync()
328 spdifrx->refcount++; in stm32_spdifrx_start_sync()
330 regmap_read(spdifrx->regmap, STM32_SPDIFRX_CR, &cr); in stm32_spdifrx_start_sync()
334 * Start sync if SPDIFRX is still in idle state. in stm32_spdifrx_start_sync()
335 * SPDIFRX reception enabled when sync done in stm32_spdifrx_start_sync()
337 dev_dbg(&spdifrx->pdev->dev, "start synchronization\n"); in stm32_spdifrx_start_sync()
340 * SPDIFRX configuration: in stm32_spdifrx_start_sync()
352 ret = regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR, in stm32_spdifrx_start_sync()
355 dev_err(&spdifrx->pdev->dev, in stm32_spdifrx_start_sync()
359 spin_unlock_irqrestore(&spdifrx->lock, flags); in stm32_spdifrx_start_sync()
364 static void stm32_spdifrx_stop(struct stm32_spdifrx_data *spdifrx) in stm32_spdifrx_stop() argument
369 spin_lock_irqsave(&spdifrx->lock, flags); in stm32_spdifrx_stop()
371 if (--spdifrx->refcount) { in stm32_spdifrx_stop()
372 spin_unlock_irqrestore(&spdifrx->lock, flags); in stm32_spdifrx_stop()
379 regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR, cr_mask, cr); in stm32_spdifrx_stop()
381 regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_IMR, in stm32_spdifrx_stop()
384 regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_IFCR, in stm32_spdifrx_stop()
388 regmap_read(spdifrx->regmap, STM32_SPDIFRX_DR, ®); in stm32_spdifrx_stop()
389 regmap_read(spdifrx->regmap, STM32_SPDIFRX_CSR, ®); in stm32_spdifrx_stop()
391 spin_unlock_irqrestore(&spdifrx->lock, flags); in stm32_spdifrx_stop()
395 struct stm32_spdifrx_data *spdifrx) in stm32_spdifrx_dma_ctrl_register() argument
399 spdifrx->ctrl_chan = dma_request_chan(dev, "rx-ctrl"); in stm32_spdifrx_dma_ctrl_register()
400 if (IS_ERR(spdifrx->ctrl_chan)) { in stm32_spdifrx_dma_ctrl_register()
402 return PTR_ERR(spdifrx->ctrl_chan); in stm32_spdifrx_dma_ctrl_register()
405 spdifrx->dmab = devm_kzalloc(dev, sizeof(struct snd_dma_buffer), in stm32_spdifrx_dma_ctrl_register()
407 if (!spdifrx->dmab) in stm32_spdifrx_dma_ctrl_register()
408 return -ENOMEM; in stm32_spdifrx_dma_ctrl_register()
410 spdifrx->dmab->dev.type = SNDRV_DMA_TYPE_DEV_IRAM; in stm32_spdifrx_dma_ctrl_register()
411 spdifrx->dmab->dev.dev = dev; in stm32_spdifrx_dma_ctrl_register()
412 ret = snd_dma_alloc_pages(spdifrx->dmab->dev.type, dev, in stm32_spdifrx_dma_ctrl_register()
413 SPDIFRX_CSR_BUF_LENGTH, spdifrx->dmab); in stm32_spdifrx_dma_ctrl_register()
419 spdifrx->slave_config.direction = DMA_DEV_TO_MEM; in stm32_spdifrx_dma_ctrl_register()
420 spdifrx->slave_config.src_addr = (dma_addr_t)(spdifrx->phys_addr + in stm32_spdifrx_dma_ctrl_register()
422 spdifrx->slave_config.dst_addr = spdifrx->dmab->addr; in stm32_spdifrx_dma_ctrl_register()
423 spdifrx->slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; in stm32_spdifrx_dma_ctrl_register()
424 spdifrx->slave_config.src_maxburst = 1; in stm32_spdifrx_dma_ctrl_register()
426 ret = dmaengine_slave_config(spdifrx->ctrl_chan, in stm32_spdifrx_dma_ctrl_register()
427 &spdifrx->slave_config); in stm32_spdifrx_dma_ctrl_register()
430 spdifrx->ctrl_chan = NULL; in stm32_spdifrx_dma_ctrl_register()
456 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; in stm32_spdifrx_info()
457 uinfo->count = 1; in stm32_spdifrx_info()
465 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; in stm32_spdifrx_ub_info()
466 uinfo->count = 1; in stm32_spdifrx_ub_info()
471 static int stm32_spdifrx_get_ctrl_data(struct stm32_spdifrx_data *spdifrx) in stm32_spdifrx_get_ctrl_data() argument
475 memset(spdifrx->cs, 0, SPDIFRX_CS_BYTES_NB); in stm32_spdifrx_get_ctrl_data()
476 memset(spdifrx->ub, 0, SPDIFRX_UB_BYTES_NB); in stm32_spdifrx_get_ctrl_data()
478 ret = stm32_spdifrx_dma_ctrl_start(spdifrx); in stm32_spdifrx_get_ctrl_data()
482 ret = clk_prepare_enable(spdifrx->kclk); in stm32_spdifrx_get_ctrl_data()
484 dev_err(&spdifrx->pdev->dev, "Enable kclk failed: %d\n", ret); in stm32_spdifrx_get_ctrl_data()
488 ret = regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR, in stm32_spdifrx_get_ctrl_data()
493 ret = stm32_spdifrx_start_sync(spdifrx); in stm32_spdifrx_get_ctrl_data()
497 if (wait_for_completion_interruptible_timeout(&spdifrx->cs_completion, in stm32_spdifrx_get_ctrl_data()
500 dev_err(&spdifrx->pdev->dev, "Failed to get control data\n"); in stm32_spdifrx_get_ctrl_data()
501 ret = -EAGAIN; in stm32_spdifrx_get_ctrl_data()
504 stm32_spdifrx_stop(spdifrx); in stm32_spdifrx_get_ctrl_data()
505 stm32_spdifrx_dma_ctrl_stop(spdifrx); in stm32_spdifrx_get_ctrl_data()
508 clk_disable_unprepare(spdifrx->kclk); in stm32_spdifrx_get_ctrl_data()
517 struct stm32_spdifrx_data *spdifrx = snd_soc_dai_get_drvdata(cpu_dai); in stm32_spdifrx_capture_get() local
519 stm32_spdifrx_get_ctrl_data(spdifrx); in stm32_spdifrx_capture_get()
521 ucontrol->value.iec958.status[0] = spdifrx->cs[0]; in stm32_spdifrx_capture_get()
522 ucontrol->value.iec958.status[1] = spdifrx->cs[1]; in stm32_spdifrx_capture_get()
523 ucontrol->value.iec958.status[2] = spdifrx->cs[2]; in stm32_spdifrx_capture_get()
524 ucontrol->value.iec958.status[3] = spdifrx->cs[3]; in stm32_spdifrx_capture_get()
525 ucontrol->value.iec958.status[4] = spdifrx->cs[4]; in stm32_spdifrx_capture_get()
534 struct stm32_spdifrx_data *spdifrx = snd_soc_dai_get_drvdata(cpu_dai); in stm32_spdif_user_bits_get() local
536 stm32_spdifrx_get_ctrl_data(spdifrx); in stm32_spdif_user_bits_get()
538 ucontrol->value.iec958.status[0] = spdifrx->ub[0]; in stm32_spdif_user_bits_get()
539 ucontrol->value.iec958.status[1] = spdifrx->ub[1]; in stm32_spdif_user_bits_get()
540 ucontrol->value.iec958.status[2] = spdifrx->ub[2]; in stm32_spdif_user_bits_get()
541 ucontrol->value.iec958.status[3] = spdifrx->ub[3]; in stm32_spdif_user_bits_get()
542 ucontrol->value.iec958.status[4] = spdifrx->ub[4]; in stm32_spdif_user_bits_get()
569 SOC_ENUM("SPDIFRX input", ctrl_enum_input),
570 SOC_ENUM("SPDIFRX CS channel", ctrl_enum_cs_channel),
582 return snd_soc_add_component_controls(cpu_dai->component, in stm32_spdifrx_dai_register_ctrls()
589 struct stm32_spdifrx_data *spdifrx = dev_get_drvdata(cpu_dai->dev); in stm32_spdifrx_dai_probe() local
591 spdifrx->dma_params.addr = (dma_addr_t)(spdifrx->phys_addr + in stm32_spdifrx_dai_probe()
593 spdifrx->dma_params.maxburst = 1; in stm32_spdifrx_dai_probe()
595 snd_soc_dai_init_dma_data(cpu_dai, NULL, &spdifrx->dma_params); in stm32_spdifrx_dai_probe()
649 struct stm32_spdifrx_data *spdifrx = (struct stm32_spdifrx_data *)devid; in stm32_spdifrx_isr() local
650 struct platform_device *pdev = spdifrx->pdev; in stm32_spdifrx_isr()
655 regmap_read(spdifrx->regmap, STM32_SPDIFRX_SR, &sr); in stm32_spdifrx_isr()
656 regmap_read(spdifrx->regmap, STM32_SPDIFRX_IMR, &imr); in stm32_spdifrx_isr()
665 dev_err(&pdev->dev, "Unexpected IRQ. rflags=%#x, imr=%#x\n", in stm32_spdifrx_isr()
671 regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_IFCR, in stm32_spdifrx_isr()
675 dev_dbg(&pdev->dev, "Parity error\n"); in stm32_spdifrx_isr()
680 dev_dbg(&pdev->dev, "Overrun error\n"); in stm32_spdifrx_isr()
685 dev_dbg(&pdev->dev, "Synchronization block detected\n"); in stm32_spdifrx_isr()
688 dev_dbg(&pdev->dev, "Synchronization done\n"); in stm32_spdifrx_isr()
690 /* Enable spdifrx */ in stm32_spdifrx_isr()
692 regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR, in stm32_spdifrx_isr()
697 dev_dbg(&pdev->dev, "Frame error\n"); in stm32_spdifrx_isr()
702 dev_dbg(&pdev->dev, "Synchronization error\n"); in stm32_spdifrx_isr()
707 dev_dbg(&pdev->dev, "Timeout error\n"); in stm32_spdifrx_isr()
712 /* SPDIFRX in STATE_STOP. Disable SPDIFRX to clear errors */ in stm32_spdifrx_isr()
714 regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR, in stm32_spdifrx_isr()
717 spin_lock(&spdifrx->irq_lock); in stm32_spdifrx_isr()
718 if (spdifrx->substream) in stm32_spdifrx_isr()
719 snd_pcm_stop(spdifrx->substream, in stm32_spdifrx_isr()
721 spin_unlock(&spdifrx->irq_lock); in stm32_spdifrx_isr()
726 spin_lock(&spdifrx->irq_lock); in stm32_spdifrx_isr()
727 if (err_xrun && spdifrx->substream) in stm32_spdifrx_isr()
728 snd_pcm_stop_xrun(spdifrx->substream); in stm32_spdifrx_isr()
729 spin_unlock(&spdifrx->irq_lock); in stm32_spdifrx_isr()
737 struct stm32_spdifrx_data *spdifrx = snd_soc_dai_get_drvdata(cpu_dai); in stm32_spdifrx_startup() local
741 spin_lock_irqsave(&spdifrx->irq_lock, flags); in stm32_spdifrx_startup()
742 spdifrx->substream = substream; in stm32_spdifrx_startup()
743 spin_unlock_irqrestore(&spdifrx->irq_lock, flags); in stm32_spdifrx_startup()
745 ret = clk_prepare_enable(spdifrx->kclk); in stm32_spdifrx_startup()
747 dev_err(&spdifrx->pdev->dev, "Enable kclk failed: %d\n", ret); in stm32_spdifrx_startup()
756 struct stm32_spdifrx_data *spdifrx = snd_soc_dai_get_drvdata(cpu_dai); in stm32_spdifrx_hw_params() local
768 dev_err(&spdifrx->pdev->dev, "Unexpected data format\n"); in stm32_spdifrx_hw_params()
769 return -EINVAL; in stm32_spdifrx_hw_params()
777 spdifrx->dma_params.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; in stm32_spdifrx_hw_params()
778 snd_soc_dai_init_dma_data(cpu_dai, NULL, &spdifrx->dma_params); in stm32_spdifrx_hw_params()
780 return regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR, in stm32_spdifrx_hw_params()
788 struct stm32_spdifrx_data *spdifrx = snd_soc_dai_get_drvdata(cpu_dai); in stm32_spdifrx_trigger() local
795 regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_IMR, in stm32_spdifrx_trigger()
798 regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR, in stm32_spdifrx_trigger()
801 ret = stm32_spdifrx_start_sync(spdifrx); in stm32_spdifrx_trigger()
806 stm32_spdifrx_stop(spdifrx); in stm32_spdifrx_trigger()
809 return -EINVAL; in stm32_spdifrx_trigger()
818 struct stm32_spdifrx_data *spdifrx = snd_soc_dai_get_drvdata(cpu_dai); in stm32_spdifrx_shutdown() local
821 spin_lock_irqsave(&spdifrx->irq_lock, flags); in stm32_spdifrx_shutdown()
822 spdifrx->substream = NULL; in stm32_spdifrx_shutdown()
823 spin_unlock_irqrestore(&spdifrx->irq_lock, flags); in stm32_spdifrx_shutdown()
825 clk_disable_unprepare(spdifrx->kclk); in stm32_spdifrx_shutdown()
839 .stream_name = "CPU-Capture",
859 .name = "stm32-spdifrx",
869 .compatible = "st,stm32h7-spdifrx",
876 struct stm32_spdifrx_data *spdifrx) in stm32_spdifrx_parse_of() argument
878 struct device_node *np = pdev->dev.of_node; in stm32_spdifrx_parse_of()
883 return -ENODEV; in stm32_spdifrx_parse_of()
885 of_id = of_match_device(stm32_spdifrx_ids, &pdev->dev); in stm32_spdifrx_parse_of()
887 spdifrx->regmap_conf = in stm32_spdifrx_parse_of()
888 (const struct regmap_config *)of_id->data; in stm32_spdifrx_parse_of()
890 return -EINVAL; in stm32_spdifrx_parse_of()
893 spdifrx->base = devm_ioremap_resource(&pdev->dev, res); in stm32_spdifrx_parse_of()
894 if (IS_ERR(spdifrx->base)) in stm32_spdifrx_parse_of()
895 return PTR_ERR(spdifrx->base); in stm32_spdifrx_parse_of()
897 spdifrx->phys_addr = res->start; in stm32_spdifrx_parse_of()
899 spdifrx->kclk = devm_clk_get(&pdev->dev, "kclk"); in stm32_spdifrx_parse_of()
900 if (IS_ERR(spdifrx->kclk)) { in stm32_spdifrx_parse_of()
901 dev_err(&pdev->dev, "Could not get kclk\n"); in stm32_spdifrx_parse_of()
902 return PTR_ERR(spdifrx->kclk); in stm32_spdifrx_parse_of()
905 spdifrx->irq = platform_get_irq(pdev, 0); in stm32_spdifrx_parse_of()
906 if (spdifrx->irq < 0) { in stm32_spdifrx_parse_of()
907 dev_err(&pdev->dev, "No irq for node %s\n", pdev->name); in stm32_spdifrx_parse_of()
908 return spdifrx->irq; in stm32_spdifrx_parse_of()
916 struct stm32_spdifrx_data *spdifrx; in stm32_spdifrx_probe() local
921 spdifrx = devm_kzalloc(&pdev->dev, sizeof(*spdifrx), GFP_KERNEL); in stm32_spdifrx_probe()
922 if (!spdifrx) in stm32_spdifrx_probe()
923 return -ENOMEM; in stm32_spdifrx_probe()
925 spdifrx->pdev = pdev; in stm32_spdifrx_probe()
926 init_completion(&spdifrx->cs_completion); in stm32_spdifrx_probe()
927 spin_lock_init(&spdifrx->lock); in stm32_spdifrx_probe()
928 spin_lock_init(&spdifrx->irq_lock); in stm32_spdifrx_probe()
930 platform_set_drvdata(pdev, spdifrx); in stm32_spdifrx_probe()
932 ret = stm32_spdifrx_parse_of(pdev, spdifrx); in stm32_spdifrx_probe()
936 spdifrx->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "kclk", in stm32_spdifrx_probe()
937 spdifrx->base, in stm32_spdifrx_probe()
938 spdifrx->regmap_conf); in stm32_spdifrx_probe()
939 if (IS_ERR(spdifrx->regmap)) { in stm32_spdifrx_probe()
940 dev_err(&pdev->dev, "Regmap init failed\n"); in stm32_spdifrx_probe()
941 return PTR_ERR(spdifrx->regmap); in stm32_spdifrx_probe()
944 ret = devm_request_irq(&pdev->dev, spdifrx->irq, stm32_spdifrx_isr, 0, in stm32_spdifrx_probe()
945 dev_name(&pdev->dev), spdifrx); in stm32_spdifrx_probe()
947 dev_err(&pdev->dev, "IRQ request returned %d\n", ret); in stm32_spdifrx_probe()
951 rst = devm_reset_control_get_exclusive(&pdev->dev, NULL); in stm32_spdifrx_probe()
958 ret = devm_snd_soc_register_component(&pdev->dev, in stm32_spdifrx_probe()
965 ret = stm32_spdifrx_dma_ctrl_register(&pdev->dev, spdifrx); in stm32_spdifrx_probe()
970 ret = devm_snd_dmaengine_pcm_register(&pdev->dev, pcm_config, 0); in stm32_spdifrx_probe()
972 dev_err(&pdev->dev, "PCM DMA register returned %d\n", ret); in stm32_spdifrx_probe()
979 if (!IS_ERR(spdifrx->ctrl_chan)) in stm32_spdifrx_probe()
980 dma_release_channel(spdifrx->ctrl_chan); in stm32_spdifrx_probe()
981 if (spdifrx->dmab) in stm32_spdifrx_probe()
982 snd_dma_free_pages(spdifrx->dmab); in stm32_spdifrx_probe()
989 struct stm32_spdifrx_data *spdifrx = platform_get_drvdata(pdev); in stm32_spdifrx_remove() local
991 if (spdifrx->ctrl_chan) in stm32_spdifrx_remove()
992 dma_release_channel(spdifrx->ctrl_chan); in stm32_spdifrx_remove()
994 if (spdifrx->dmab) in stm32_spdifrx_remove()
995 snd_dma_free_pages(spdifrx->dmab); in stm32_spdifrx_remove()
1004 .name = "st,stm32-spdifrx",
1013 MODULE_DESCRIPTION("STM32 Soc spdifrx Interface");
1015 MODULE_ALIAS("platform:stm32-spdifrx");