Lines Matching +full:sama7g5 +full:- +full:spdifrx
1 // SPDX-License-Identifier: GPL-2.0
20 * ---- S/PDIF Receiver Controller Register map ----
44 * ---- Control Register (Write-only) ----
49 * ---- Mode Register (Read/Write) ----
76 (((6 - (width) / 4) << 4) & SPDIFRX_MR_DATAWIDTH_MASK)
94 * ---- Interrupt Enable/Disable/Mask/Status Register (Write/Read-only) ----
112 * ---- Receiver Status Register (Read/Write) ----
124 * ---- Version Register (Read-only) ----
247 struct mchp_spdifrx_mixer_control *ctrl = &dev->control; in mchp_spdifrx_channel_status_read()
248 u8 *ch_stat = &ctrl->ch_stat[channel].data[0]; in mchp_spdifrx_channel_status_read()
252 for (i = 0; i < ARRAY_SIZE(ctrl->ch_stat[channel].data) / 4; i++) { in mchp_spdifrx_channel_status_read()
253 regmap_read(dev->regmap, SPDIFRX_CHSR(channel, i), &val); in mchp_spdifrx_channel_status_read()
264 struct mchp_spdifrx_mixer_control *ctrl = &dev->control; in mchp_spdifrx_channel_user_data_read()
265 u8 *user_data = &ctrl->user_data[channel].data[0]; in mchp_spdifrx_channel_user_data_read()
269 for (i = 0; i < ARRAY_SIZE(ctrl->user_data[channel].data) / 4; i++) { in mchp_spdifrx_channel_user_data_read()
270 regmap_read(dev->regmap, SPDIFRX_CHUD(channel, i), &val); in mchp_spdifrx_channel_user_data_read()
278 /* called from non-atomic context only */
283 spin_lock_irqsave(&dev->blockend_lock, flags); in mchp_spdifrx_isr_blockend_en()
284 dev->blockend_refcount++; in mchp_spdifrx_isr_blockend_en()
286 if (dev->blockend_refcount == 1) in mchp_spdifrx_isr_blockend_en()
287 regmap_write(dev->regmap, SPDIFRX_IER, SPDIFRX_IR_BLOCKEND); in mchp_spdifrx_isr_blockend_en()
288 spin_unlock_irqrestore(&dev->blockend_lock, flags); in mchp_spdifrx_isr_blockend_en()
291 /* called from atomic/non-atomic context */
296 spin_lock_irqsave(&dev->blockend_lock, flags); in mchp_spdifrx_isr_blockend_dis()
297 dev->blockend_refcount--; in mchp_spdifrx_isr_blockend_dis()
299 if (dev->blockend_refcount == 0) in mchp_spdifrx_isr_blockend_dis()
300 regmap_write(dev->regmap, SPDIFRX_IDR, SPDIFRX_IR_BLOCKEND); in mchp_spdifrx_isr_blockend_dis()
301 spin_unlock_irqrestore(&dev->blockend_lock, flags); in mchp_spdifrx_isr_blockend_dis()
307 struct mchp_spdifrx_mixer_control *ctrl = &dev->control; in mchp_spdif_interrupt()
312 regmap_read(dev->regmap, SPDIFRX_ISR, &sr); in mchp_spdif_interrupt()
313 regmap_read(dev->regmap, SPDIFRX_IMR, &imr); in mchp_spdif_interrupt()
315 dev_dbg(dev->dev, "ISR: %#x, IMR: %#x, pending: %#x\n", sr, imr, in mchp_spdif_interrupt()
323 spin_lock(&ctrl->user_data[ch].lock); in mchp_spdif_interrupt()
325 spin_unlock(&ctrl->user_data[ch].lock); in mchp_spdif_interrupt()
327 complete(&ctrl->user_data[ch].done); in mchp_spdif_interrupt()
336 complete(&ctrl->ch_stat[ch].done); in mchp_spdif_interrupt()
343 dev_warn(dev->dev, "Overrun detected\n"); in mchp_spdif_interrupt()
347 regmap_write(dev->regmap, SPDIFRX_IDR, idr); in mchp_spdif_interrupt()
360 regmap_read(dev->regmap, SPDIFRX_MR, &mr); in mchp_spdifrx_trigger()
371 regmap_write(dev->regmap, SPDIFRX_IER, in mchp_spdifrx_trigger()
382 regmap_write(dev->regmap, SPDIFRX_IDR, in mchp_spdifrx_trigger()
387 return -EINVAL; in mchp_spdifrx_trigger()
390 ret = regmap_write(dev->regmap, SPDIFRX_MR, mr); in mchp_spdifrx_trigger()
392 dev_err(dev->dev, "unable to enable/disable RX: %d\n", ret); in mchp_spdifrx_trigger()
407 dev_dbg(dev->dev, "%s() rate=%u format=%#x width=%u channels=%u\n", in mchp_spdifrx_hw_params()
411 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { in mchp_spdifrx_hw_params()
412 dev_err(dev->dev, "Playback is not supported\n"); in mchp_spdifrx_hw_params()
413 return -EINVAL; in mchp_spdifrx_hw_params()
416 regmap_read(dev->regmap, SPDIFRX_MR, &mr); in mchp_spdifrx_hw_params()
419 dev_err(dev->dev, "PCM already running\n"); in mchp_spdifrx_hw_params()
420 return -EBUSY; in mchp_spdifrx_hw_params()
424 dev_err(dev->dev, "unsupported number of channels: %d\n", in mchp_spdifrx_hw_params()
426 return -EINVAL; in mchp_spdifrx_hw_params()
443 dev_err(dev->dev, "unsupported PCM format: %d\n", in mchp_spdifrx_hw_params()
445 return -EINVAL; in mchp_spdifrx_hw_params()
448 if (dev->gclk_enabled) { in mchp_spdifrx_hw_params()
449 clk_disable_unprepare(dev->gclk); in mchp_spdifrx_hw_params()
450 dev->gclk_enabled = 0; in mchp_spdifrx_hw_params()
452 ret = clk_set_min_rate(dev->gclk, params_rate(params) * in mchp_spdifrx_hw_params()
455 dev_err(dev->dev, in mchp_spdifrx_hw_params()
460 ret = clk_prepare_enable(dev->gclk); in mchp_spdifrx_hw_params()
462 dev_err(dev->dev, "unable to enable gclk: %d\n", ret); in mchp_spdifrx_hw_params()
465 dev->gclk_enabled = 1; in mchp_spdifrx_hw_params()
467 dev_dbg(dev->dev, "GCLK range min set to %d\n", in mchp_spdifrx_hw_params()
470 return regmap_write(dev->regmap, SPDIFRX_MR, mr); in mchp_spdifrx_hw_params()
478 if (dev->gclk_enabled) { in mchp_spdifrx_hw_free()
479 clk_disable_unprepare(dev->gclk); in mchp_spdifrx_hw_free()
480 dev->gclk_enabled = 0; in mchp_spdifrx_hw_free()
506 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; in mchp_spdifrx_info()
507 uinfo->count = 1; in mchp_spdifrx_info()
516 struct mchp_spdifrx_mixer_control *ctrl = &dev->control; in mchp_spdifrx_cs_get()
517 struct mchp_spdifrx_ch_stat *ch_stat = &ctrl->ch_stat[channel]; in mchp_spdifrx_cs_get()
520 regmap_write(dev->regmap, SPDIFRX_IER, SPDIFRX_IR_CSC(channel)); in mchp_spdifrx_cs_get()
522 ret = wait_for_completion_interruptible_timeout(&ch_stat->done, in mchp_spdifrx_cs_get()
526 dev_dbg(dev->dev, "channel status for channel %d timeout\n", in mchp_spdifrx_cs_get()
530 memcpy(uvalue->value.iec958.status, ch_stat->data, in mchp_spdifrx_cs_get()
531 sizeof(ch_stat->data)); in mchp_spdifrx_cs_get()
557 memset(uvalue->value.iec958.status, 0xff, in mchp_spdifrx_cs_mask()
558 sizeof(uvalue->value.iec958.status)); in mchp_spdifrx_cs_mask()
568 struct mchp_spdifrx_mixer_control *ctrl = &dev->control; in mchp_spdifrx_subcode_ch_get()
569 struct mchp_spdifrx_user_data *user_data = &ctrl->user_data[channel]; in mchp_spdifrx_subcode_ch_get()
572 reinit_completion(&user_data->done); in mchp_spdifrx_subcode_ch_get()
574 ret = wait_for_completion_interruptible_timeout(&user_data->done, in mchp_spdifrx_subcode_ch_get()
578 dev_dbg(dev->dev, "user data for channel %d timeout\n", in mchp_spdifrx_subcode_ch_get()
584 spin_lock_irqsave(&user_data->lock, flags); in mchp_spdifrx_subcode_ch_get()
585 memcpy(uvalue->value.iec958.subcode, user_data->data, in mchp_spdifrx_subcode_ch_get()
586 sizeof(user_data->data)); in mchp_spdifrx_subcode_ch_get()
587 spin_unlock_irqrestore(&user_data->lock, flags); in mchp_spdifrx_subcode_ch_get()
613 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; in mchp_spdifrx_boolean_info()
614 uinfo->count = 1; in mchp_spdifrx_boolean_info()
615 uinfo->value.integer.min = 0; in mchp_spdifrx_boolean_info()
616 uinfo->value.integer.max = 1; in mchp_spdifrx_boolean_info()
626 struct mchp_spdifrx_mixer_control *ctrl = &dev->control; in mchp_spdifrx_ulock_get()
628 bool ulock_old = ctrl->ulock; in mchp_spdifrx_ulock_get()
630 regmap_read(dev->regmap, SPDIFRX_RSR, &val); in mchp_spdifrx_ulock_get()
631 ctrl->ulock = !(val & SPDIFRX_RSR_ULOCK); in mchp_spdifrx_ulock_get()
632 uvalue->value.integer.value[0] = ctrl->ulock; in mchp_spdifrx_ulock_get()
634 return ulock_old != ctrl->ulock; in mchp_spdifrx_ulock_get()
642 struct mchp_spdifrx_mixer_control *ctrl = &dev->control; in mchp_spdifrx_badf_get()
644 bool badf_old = ctrl->badf; in mchp_spdifrx_badf_get()
646 regmap_read(dev->regmap, SPDIFRX_RSR, &val); in mchp_spdifrx_badf_get()
647 ctrl->badf = !!(val & SPDIFRX_RSR_BADF); in mchp_spdifrx_badf_get()
648 uvalue->value.integer.value[0] = ctrl->badf; in mchp_spdifrx_badf_get()
650 return badf_old != ctrl->badf; in mchp_spdifrx_badf_get()
658 struct mchp_spdifrx_mixer_control *ctrl = &dev->control; in mchp_spdifrx_signal_get()
660 bool signal_old = ctrl->signal; in mchp_spdifrx_signal_get()
662 regmap_read(dev->regmap, SPDIFRX_RSR, &val); in mchp_spdifrx_signal_get()
663 ctrl->signal = !(val & SPDIFRX_RSR_NOSIGNAL); in mchp_spdifrx_signal_get()
664 uvalue->value.integer.value[0] = ctrl->signal; in mchp_spdifrx_signal_get()
666 return signal_old != ctrl->signal; in mchp_spdifrx_signal_get()
672 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; in mchp_spdifrx_rate_info()
673 uinfo->count = 1; in mchp_spdifrx_rate_info()
674 uinfo->value.integer.min = 0; in mchp_spdifrx_rate_info()
675 uinfo->value.integer.max = 192000; in mchp_spdifrx_rate_info()
688 regmap_read(dev->regmap, SPDIFRX_RSR, &val); in mchp_spdifrx_rate_get()
692 ucontrol->value.integer.value[0] = 0; in mchp_spdifrx_rate_get()
696 rate = clk_get_rate(dev->gclk); in mchp_spdifrx_rate_get()
698 ucontrol->value.integer.value[0] = rate / (32 * SPDIFRX_RSR_IFS(val)); in mchp_spdifrx_rate_get()
788 struct mchp_spdifrx_mixer_control *ctrl = &dev->control; in mchp_spdifrx_dai_probe()
792 err = clk_prepare_enable(dev->pclk); in mchp_spdifrx_dai_probe()
794 dev_err(dev->dev, in mchp_spdifrx_dai_probe()
799 snd_soc_dai_init_dma_data(dai, NULL, &dev->capture); in mchp_spdifrx_dai_probe()
802 regmap_write(dev->regmap, SPDIFRX_CR, SPDIFRX_CR_SWRST); in mchp_spdifrx_dai_probe()
805 regmap_write(dev->regmap, SPDIFRX_MR, in mchp_spdifrx_dai_probe()
811 dev->blockend_refcount = 0; in mchp_spdifrx_dai_probe()
813 init_completion(&ctrl->ch_stat[ch].done); in mchp_spdifrx_dai_probe()
814 init_completion(&ctrl->user_data[ch].done); in mchp_spdifrx_dai_probe()
815 spin_lock_init(&ctrl->user_data[ch].lock); in mchp_spdifrx_dai_probe()
830 regmap_write(dev->regmap, SPDIFRX_IDR, 0xFF); in mchp_spdifrx_dai_remove()
832 clk_disable_unprepare(dev->pclk); in mchp_spdifrx_dai_remove()
838 .name = "mchp-spdifrx",
852 .name = "mchp-spdifrx",
857 .compatible = "microchip,sama7g5-spdifrx",
874 dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); in mchp_spdifrx_probe()
876 return -ENOMEM; in mchp_spdifrx_probe()
883 regmap = devm_regmap_init_mmio(&pdev->dev, base, in mchp_spdifrx_probe()
893 err = devm_request_irq(&pdev->dev, irq, mchp_spdif_interrupt, 0, in mchp_spdifrx_probe()
894 dev_name(&pdev->dev), dev); in mchp_spdifrx_probe()
899 dev->pclk = devm_clk_get(&pdev->dev, "pclk"); in mchp_spdifrx_probe()
900 if (IS_ERR(dev->pclk)) { in mchp_spdifrx_probe()
901 err = PTR_ERR(dev->pclk); in mchp_spdifrx_probe()
902 dev_err(&pdev->dev, "failed to get the peripheral clock: %d\n", in mchp_spdifrx_probe()
908 dev->gclk = devm_clk_get(&pdev->dev, "gclk"); in mchp_spdifrx_probe()
909 if (IS_ERR(dev->gclk)) { in mchp_spdifrx_probe()
910 err = PTR_ERR(dev->gclk); in mchp_spdifrx_probe()
911 dev_err(&pdev->dev, in mchp_spdifrx_probe()
915 spin_lock_init(&dev->blockend_lock); in mchp_spdifrx_probe()
917 dev->dev = &pdev->dev; in mchp_spdifrx_probe()
918 dev->regmap = regmap; in mchp_spdifrx_probe()
921 dev->capture.addr = (dma_addr_t)mem->start + SPDIFRX_RHR; in mchp_spdifrx_probe()
922 dev->capture.maxburst = 1; in mchp_spdifrx_probe()
924 err = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); in mchp_spdifrx_probe()
926 dev_err(&pdev->dev, "failed to register PMC: %d\n", err); in mchp_spdifrx_probe()
930 err = devm_snd_soc_register_component(&pdev->dev, in mchp_spdifrx_probe()
934 dev_err(&pdev->dev, "fail to register dai\n"); in mchp_spdifrx_probe()
939 dev_info(&pdev->dev, "hw version: %#lx\n", vers & SPDIFRX_VERSION_MASK); in mchp_spdifrx_probe()