Lines Matching +full:sama7g5 +full:- +full:spdiftx
1 // SPDX-License-Identifier: GPL-2.0
22 * ---- S/PDIF Transmitter Controller Register map ----
39 * ---- Control Register (Write-only) ----
45 * ---- Mode Register (Read/Write) ----
92 * ---- Interrupt Enable/Disable/Mask/Status Register (Write/Read-only) ----
205 regmap_read(dev->regmap, SPDIFTX_MR, &mr); in mchp_spdiftx_is_running()
211 struct mchp_spdiftx_mixer_control *ctrl = &dev->control; in mchp_spdiftx_channel_status_write()
215 for (i = 0; i < ARRAY_SIZE(ctrl->ch_stat) / 4; i++) { in mchp_spdiftx_channel_status_write()
216 val = (ctrl->ch_stat[(i * 4) + 0] << 0) | in mchp_spdiftx_channel_status_write()
217 (ctrl->ch_stat[(i * 4) + 1] << 8) | in mchp_spdiftx_channel_status_write()
218 (ctrl->ch_stat[(i * 4) + 2] << 16) | in mchp_spdiftx_channel_status_write()
219 (ctrl->ch_stat[(i * 4) + 3] << 24); in mchp_spdiftx_channel_status_write()
221 regmap_write(dev->regmap, SPDIFTX_CH1S(i), val); in mchp_spdiftx_channel_status_write()
227 struct mchp_spdiftx_mixer_control *ctrl = &dev->control; in mchp_spdiftx_user_data_write()
231 for (i = 0; i < ARRAY_SIZE(ctrl->user_data) / 4; i++) { in mchp_spdiftx_user_data_write()
232 val = (ctrl->user_data[(i * 4) + 0] << 0) | in mchp_spdiftx_user_data_write()
233 (ctrl->user_data[(i * 4) + 1] << 8) | in mchp_spdiftx_user_data_write()
234 (ctrl->user_data[(i * 4) + 2] << 16) | in mchp_spdiftx_user_data_write()
235 (ctrl->user_data[(i * 4) + 3] << 24); in mchp_spdiftx_user_data_write()
237 regmap_write(dev->regmap, SPDIFTX_CH1UD(i), val); in mchp_spdiftx_user_data_write()
244 struct mchp_spdiftx_mixer_control *ctrl = &dev->control; in mchp_spdiftx_interrupt()
247 regmap_read(dev->regmap, SPDIFTX_ISR, &sr); in mchp_spdiftx_interrupt()
248 regmap_read(dev->regmap, SPDIFTX_IMR, &imr); in mchp_spdiftx_interrupt()
255 dev_warn(dev->dev, "underflow detected\n"); in mchp_spdiftx_interrupt()
260 dev_warn(dev->dev, "overflow detected\n"); in mchp_spdiftx_interrupt()
265 spin_lock(&ctrl->lock); in mchp_spdiftx_interrupt()
267 spin_unlock(&ctrl->lock); in mchp_spdiftx_interrupt()
272 spin_lock(&ctrl->lock); in mchp_spdiftx_interrupt()
274 spin_unlock(&ctrl->lock); in mchp_spdiftx_interrupt()
278 regmap_write(dev->regmap, SPDIFTX_IDR, idr); in mchp_spdiftx_interrupt()
289 regmap_write(dev->regmap, SPDIFTX_CR, in mchp_spdiftx_dai_startup()
301 regmap_write(dev->regmap, SPDIFTX_IDR, 0xffffffff); in mchp_spdiftx_dai_shutdown()
308 struct mchp_spdiftx_mixer_control *ctrl = &dev->control; in mchp_spdiftx_trigger()
312 spin_lock(&ctrl->lock); in mchp_spdiftx_trigger()
316 regmap_write(dev->regmap, SPDIFTX_IER, dev->suspend_irq | in mchp_spdiftx_trigger()
318 dev->suspend_irq = 0; in mchp_spdiftx_trigger()
321 ret = regmap_update_bits(dev->regmap, SPDIFTX_MR, SPDIFTX_MR_TXEN_MASK, in mchp_spdiftx_trigger()
325 regmap_read(dev->regmap, SPDIFTX_IMR, &dev->suspend_irq); in mchp_spdiftx_trigger()
328 regmap_write(dev->regmap, SPDIFTX_IDR, dev->suspend_irq | in mchp_spdiftx_trigger()
332 ret = regmap_update_bits(dev->regmap, SPDIFTX_MR, SPDIFTX_MR_TXEN_MASK, in mchp_spdiftx_trigger()
336 ret = -EINVAL; in mchp_spdiftx_trigger()
338 spin_unlock(&ctrl->lock); in mchp_spdiftx_trigger()
340 dev_err(dev->dev, "unable to start/stop TX: %d\n", ret); in mchp_spdiftx_trigger()
351 struct mchp_spdiftx_mixer_control *ctrl = &dev->control; in mchp_spdiftx_hw_params()
357 dev_dbg(dev->dev, "%s() rate=%u format=%#x width=%u channels=%u\n", in mchp_spdiftx_hw_params()
361 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { in mchp_spdiftx_hw_params()
362 dev_err(dev->dev, "Capture is not supported\n"); in mchp_spdiftx_hw_params()
363 return -EINVAL; in mchp_spdiftx_hw_params()
366 regmap_read(dev->regmap, SPDIFTX_MR, &mr); in mchp_spdiftx_hw_params()
369 dev_err(dev->dev, "PCM already running\n"); in mchp_spdiftx_hw_params()
370 return -EBUSY; in mchp_spdiftx_hw_params()
375 dev->playback.maxburst = 1; in mchp_spdiftx_hw_params()
383 dev->playback.maxburst = 2; in mchp_spdiftx_hw_params()
386 dev_err(dev->dev, "unsupported number of channels: %d\n", in mchp_spdiftx_hw_params()
388 return -EINVAL; in mchp_spdiftx_hw_params()
390 mr |= FIELD_PREP(SPDIFTX_MR_CHUNK_MASK, dev->playback.maxburst); in mchp_spdiftx_hw_params()
433 dev_err(dev->dev, "unsupported PCM format: %d\n", in mchp_spdiftx_hw_params()
435 return -EINVAL; in mchp_spdiftx_hw_params()
438 mr |= FIELD_PREP(SPDIFTX_MR_BPS_MASK, bps - 1); in mchp_spdiftx_hw_params()
475 dev_err(dev->dev, "unsupported sample frequency: %u\n", in mchp_spdiftx_hw_params()
477 return -EINVAL; in mchp_spdiftx_hw_params()
479 spin_lock_irqsave(&ctrl->lock, flags); in mchp_spdiftx_hw_params()
480 ctrl->ch_stat[3] &= ~IEC958_AES3_CON_FS; in mchp_spdiftx_hw_params()
481 ctrl->ch_stat[3] |= aes3; in mchp_spdiftx_hw_params()
483 spin_unlock_irqrestore(&ctrl->lock, flags); in mchp_spdiftx_hw_params()
486 clk_disable_unprepare(dev->gclk); in mchp_spdiftx_hw_params()
488 ret = clk_set_rate(dev->gclk, params_rate(params) * in mchp_spdiftx_hw_params()
491 dev_err(dev->dev, in mchp_spdiftx_hw_params()
496 ret = clk_prepare_enable(dev->gclk); in mchp_spdiftx_hw_params()
498 dev_err(dev->dev, "unable to enable gclk: %d\n", ret); in mchp_spdiftx_hw_params()
502 dev_dbg(dev->dev, "%s(): GCLK set to %d\n", __func__, in mchp_spdiftx_hw_params()
505 regmap_write(dev->regmap, SPDIFTX_MR, mr); in mchp_spdiftx_hw_params()
515 return regmap_write(dev->regmap, SPDIFTX_CR, in mchp_spdiftx_hw_free()
539 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; in mchp_spdiftx_info()
540 uinfo->count = 1; in mchp_spdiftx_info()
551 struct mchp_spdiftx_mixer_control *ctrl = &dev->control; in mchp_spdiftx_cs_get()
553 spin_lock_irqsave(&ctrl->lock, flags); in mchp_spdiftx_cs_get()
554 memcpy(uvalue->value.iec958.status, ctrl->ch_stat, in mchp_spdiftx_cs_get()
555 sizeof(ctrl->ch_stat)); in mchp_spdiftx_cs_get()
556 spin_unlock_irqrestore(&ctrl->lock, flags); in mchp_spdiftx_cs_get()
567 struct mchp_spdiftx_mixer_control *ctrl = &dev->control; in mchp_spdiftx_cs_put()
571 spin_lock_irqsave(&ctrl->lock, flags); in mchp_spdiftx_cs_put()
572 for (i = 0; i < ARRAY_SIZE(ctrl->ch_stat); i++) { in mchp_spdiftx_cs_put()
573 if (ctrl->ch_stat[i] != uvalue->value.iec958.status[i]) in mchp_spdiftx_cs_put()
575 ctrl->ch_stat[i] = uvalue->value.iec958.status[i]; in mchp_spdiftx_cs_put()
585 regmap_write(dev->regmap, SPDIFTX_IER, in mchp_spdiftx_cs_put()
591 spin_unlock_irqrestore(&ctrl->lock, flags); in mchp_spdiftx_cs_put()
599 memset(uvalue->value.iec958.status, 0xff, in mchp_spdiftx_cs_mask()
600 sizeof(uvalue->value.iec958.status)); in mchp_spdiftx_cs_mask()
610 struct mchp_spdiftx_mixer_control *ctrl = &dev->control; in mchp_spdiftx_subcode_get()
613 spin_lock_irqsave(&ctrl->lock, flags); in mchp_spdiftx_subcode_get()
614 memcpy(uvalue->value.iec958.subcode, ctrl->user_data, in mchp_spdiftx_subcode_get()
615 sizeof(ctrl->user_data)); in mchp_spdiftx_subcode_get()
616 spin_unlock_irqrestore(&ctrl->lock, flags); in mchp_spdiftx_subcode_get()
627 struct mchp_spdiftx_mixer_control *ctrl = &dev->control; in mchp_spdiftx_subcode_put()
631 spin_lock_irqsave(&ctrl->lock, flags); in mchp_spdiftx_subcode_put()
632 for (i = 0; i < ARRAY_SIZE(ctrl->user_data); i++) { in mchp_spdiftx_subcode_put()
633 if (ctrl->user_data[i] != uvalue->value.iec958.subcode[i]) in mchp_spdiftx_subcode_put()
636 ctrl->user_data[i] = uvalue->value.iec958.subcode[i]; in mchp_spdiftx_subcode_put()
644 regmap_write(dev->regmap, SPDIFTX_IER, in mchp_spdiftx_subcode_put()
650 spin_unlock_irqrestore(&ctrl->lock, flags); in mchp_spdiftx_subcode_put()
689 snd_soc_dai_init_dma_data(dai, &dev->playback, NULL); in mchp_spdiftx_dai_probe()
708 .name = "mchp-spdiftx",
720 .name = "mchp-spdiftx",
726 .compatible = "microchip,sama7g5-spdiftx",
734 struct mchp_spdiftx_dev *spdiftx = dev_get_drvdata(dev); in mchp_spdiftx_runtime_suspend() local
736 regcache_cache_only(spdiftx->regmap, true); in mchp_spdiftx_runtime_suspend()
738 clk_disable_unprepare(spdiftx->gclk); in mchp_spdiftx_runtime_suspend()
739 clk_disable_unprepare(spdiftx->pclk); in mchp_spdiftx_runtime_suspend()
746 struct mchp_spdiftx_dev *spdiftx = dev_get_drvdata(dev); in mchp_spdiftx_runtime_resume() local
749 ret = clk_prepare_enable(spdiftx->pclk); in mchp_spdiftx_runtime_resume()
751 dev_err(spdiftx->dev, in mchp_spdiftx_runtime_resume()
755 ret = clk_prepare_enable(spdiftx->gclk); in mchp_spdiftx_runtime_resume()
757 dev_err(spdiftx->dev, in mchp_spdiftx_runtime_resume()
762 regcache_cache_only(spdiftx->regmap, false); in mchp_spdiftx_runtime_resume()
763 regcache_mark_dirty(spdiftx->regmap); in mchp_spdiftx_runtime_resume()
764 ret = regcache_sync(spdiftx->regmap); in mchp_spdiftx_runtime_resume()
766 regcache_cache_only(spdiftx->regmap, true); in mchp_spdiftx_runtime_resume()
767 clk_disable_unprepare(spdiftx->gclk); in mchp_spdiftx_runtime_resume()
769 clk_disable_unprepare(spdiftx->pclk); in mchp_spdiftx_runtime_resume()
792 dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); in mchp_spdiftx_probe()
794 return -ENOMEM; in mchp_spdiftx_probe()
801 regmap = devm_regmap_init_mmio(&pdev->dev, base, in mchp_spdiftx_probe()
811 err = devm_request_irq(&pdev->dev, irq, mchp_spdiftx_interrupt, 0, in mchp_spdiftx_probe()
812 dev_name(&pdev->dev), dev); in mchp_spdiftx_probe()
817 dev->pclk = devm_clk_get(&pdev->dev, "pclk"); in mchp_spdiftx_probe()
818 if (IS_ERR(dev->pclk)) { in mchp_spdiftx_probe()
819 err = PTR_ERR(dev->pclk); in mchp_spdiftx_probe()
820 dev_err(&pdev->dev, in mchp_spdiftx_probe()
826 dev->gclk = devm_clk_get(&pdev->dev, "gclk"); in mchp_spdiftx_probe()
827 if (IS_ERR(dev->gclk)) { in mchp_spdiftx_probe()
828 err = PTR_ERR(dev->gclk); in mchp_spdiftx_probe()
829 dev_err(&pdev->dev, in mchp_spdiftx_probe()
834 ctrl = &dev->control; in mchp_spdiftx_probe()
835 spin_lock_init(&ctrl->lock); in mchp_spdiftx_probe()
838 ctrl->ch_stat[0] = IEC958_AES0_CON_NOT_COPYRIGHT | in mchp_spdiftx_probe()
841 dev->dev = &pdev->dev; in mchp_spdiftx_probe()
842 dev->regmap = regmap; in mchp_spdiftx_probe()
845 pm_runtime_enable(dev->dev); in mchp_spdiftx_probe()
846 if (!pm_runtime_enabled(dev->dev)) { in mchp_spdiftx_probe()
847 err = mchp_spdiftx_runtime_resume(dev->dev); in mchp_spdiftx_probe()
852 dev->playback.addr = (dma_addr_t)mem->start + SPDIFTX_CDR; in mchp_spdiftx_probe()
853 dev->playback.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; in mchp_spdiftx_probe()
855 err = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); in mchp_spdiftx_probe()
857 dev_err(&pdev->dev, "failed to register PMC: %d\n", err); in mchp_spdiftx_probe()
861 err = devm_snd_soc_register_component(&pdev->dev, in mchp_spdiftx_probe()
865 dev_err(&pdev->dev, "failed to register component: %d\n", err); in mchp_spdiftx_probe()
872 if (!pm_runtime_status_suspended(dev->dev)) in mchp_spdiftx_probe()
873 mchp_spdiftx_runtime_suspend(dev->dev); in mchp_spdiftx_probe()
874 pm_runtime_disable(dev->dev); in mchp_spdiftx_probe()
883 if (!pm_runtime_status_suspended(dev->dev)) in mchp_spdiftx_remove()
884 mchp_spdiftx_runtime_suspend(dev->dev); in mchp_spdiftx_remove()
886 pm_runtime_disable(dev->dev); in mchp_spdiftx_remove()