Lines Matching +full:playback +full:- +full:only
1 // SPDX-License-Identifier: GPL-2.0+
3 // siu_dai.c - ALSA SoC driver for Renesas SH7343, SH7722 SIU peripheral.
5 // Copyright (C) 2009-2010 Guennadi Liakhovetski <[email protected]>
45 * SPDIF is only available on port A and on some SIU implementations it is only
57 struct format_flag playback; member
65 .playback = {
79 .playback = {
82 .spdif = 0, /* impossible - turn off */
88 .spdif = 0, /* impossible - turn off */
97 u32 __iomem *base = info->reg; in siu_dai_start()
99 dev_dbg(port_info->pcm->card->dev, "%s\n", __func__); in siu_dai_start()
107 port_info->stfifo = 0; in siu_dai_start()
108 port_info->trdat = 0; in siu_dai_start()
133 siu_write32(base + SIU_SBDVCA, port_info->playback.volume); in siu_dai_start()
134 siu_write32(base + SIU_SBDVCB, port_info->capture.volume); in siu_dai_start()
140 u32 __iomem *base = info->reg; in siu_dai_stop()
149 struct siu_firmware *fw = &info->fw; in siu_dai_spbAselect()
150 u32 *ydef = fw->yram0; in siu_dai_spbAselect()
154 if (!info->port_id) in siu_dai_spbAselect()
159 ydef[0] = (fw->spbpar[idx].ab1a << 16) | in siu_dai_spbAselect()
160 (fw->spbpar[idx].ab0a << 8) | in siu_dai_spbAselect()
161 (fw->spbpar[idx].dir << 7) | 3; in siu_dai_spbAselect()
162 ydef[1] = fw->yram0[1]; /* 0x03000300 */ in siu_dai_spbAselect()
164 ydef[3] = fw->yram0[3]; /* 0 */ in siu_dai_spbAselect()
165 ydef[4] = fw->yram0[4]; /* 0 */ in siu_dai_spbAselect()
166 ydef[7] = fw->spbpar[idx].event; in siu_dai_spbAselect()
167 port_info->stfifo |= fw->spbpar[idx].stfifo; in siu_dai_spbAselect()
168 port_info->trdat |= fw->spbpar[idx].trdat; in siu_dai_spbAselect()
174 struct siu_firmware *fw = &info->fw; in siu_dai_spbBselect()
175 u32 *ydef = fw->yram0; in siu_dai_spbBselect()
179 if (!info->port_id) in siu_dai_spbBselect()
184 ydef[5] = (fw->spbpar[idx].ab1a << 16) | in siu_dai_spbBselect()
185 (fw->spbpar[idx].ab0a << 8) | 1; in siu_dai_spbBselect()
186 ydef[6] = fw->spbpar[idx].event; in siu_dai_spbBselect()
187 port_info->stfifo |= fw->spbpar[idx].stfifo; in siu_dai_spbBselect()
188 port_info->trdat |= fw->spbpar[idx].trdat; in siu_dai_spbBselect()
194 u32 __iomem *base = info->reg; in siu_dai_open()
200 switch (info->port_id) { in siu_dai_open()
219 * At the moment only fixed Left-upper, Left-lower, Right-upper, Right-lower
225 u32 __iomem *base = info->reg; in siu_dai_pcmdatapack()
230 switch (info->port_id) { in siu_dai_pcmdatapack()
245 u32 __iomem *base = info->reg; in siu_dai_spbstart()
246 struct siu_firmware *fw = &info->fw; in siu_dai_spbstart()
247 u32 *ydef = fw->yram0; in siu_dai_spbstart()
253 ptr = fw->pram0; in siu_dai_spbstart()
254 add = info->pram; in siu_dai_spbstart()
258 ptr = fw->pram1; in siu_dai_spbstart()
259 add = info->pram + (0x0100 / sizeof(u32)); in siu_dai_spbstart()
264 add = info->xram; in siu_dai_spbstart()
269 add = info->yram; in siu_dai_spbstart()
274 add = info->yram + (0x0200 / sizeof(u32)); in siu_dai_spbstart()
276 siu_write32(add, fw->yram_fir_coeff[cnt]); in siu_dai_spbstart()
279 add = info->yram + (0x0600 / sizeof(u32)); in siu_dai_spbstart()
283 siu_write32(base + SIU_TRDAT, port_info->trdat); in siu_dai_spbstart()
284 port_info->trdat = 0x0; in siu_dai_spbstart()
293 while (--cnt && siu_read32(base + SIU_SBCTL) != 0x80000000) in siu_dai_spbstart()
297 return -EBUSY; in siu_dai_spbstart()
310 u32 __iomem *base = info->reg; in siu_dai_spbstop()
316 port_info->stfifo = 0; in siu_dai_spbstop()
321 /* Playback and capture hardware properties are identical */
342 dev_dbg(port_info->pcm->card->dev, "%s\n", __func__); in siu_dai_info_volume()
344 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; in siu_dai_info_volume()
345 uinfo->count = 2; in siu_dai_info_volume()
346 uinfo->value.integer.min = 0; in siu_dai_info_volume()
347 uinfo->value.integer.max = SIU_MAX_VOLUME; in siu_dai_info_volume()
356 struct device *dev = port_info->pcm->card->dev; in siu_dai_get_volume()
361 switch (kctrl->private_value) { in siu_dai_get_volume()
363 /* Playback is always on port 0 */ in siu_dai_get_volume()
364 vol = port_info->playback.volume; in siu_dai_get_volume()
365 ucontrol->value.integer.value[0] = vol & 0xffff; in siu_dai_get_volume()
366 ucontrol->value.integer.value[1] = vol >> 16 & 0xffff; in siu_dai_get_volume()
370 vol = port_info->capture.volume; in siu_dai_get_volume()
371 ucontrol->value.integer.value[0] = vol & 0xffff; in siu_dai_get_volume()
372 ucontrol->value.integer.value[1] = vol >> 16 & 0xffff; in siu_dai_get_volume()
376 __func__, kctrl->private_value); in siu_dai_get_volume()
377 return -EINVAL; in siu_dai_get_volume()
387 struct device *dev = port_info->pcm->card->dev; in siu_dai_put_volume()
389 u32 __iomem *base = info->reg; in siu_dai_put_volume()
395 if (ucontrol->value.integer.value[0] < 0 || in siu_dai_put_volume()
396 ucontrol->value.integer.value[0] > SIU_MAX_VOLUME || in siu_dai_put_volume()
397 ucontrol->value.integer.value[1] < 0 || in siu_dai_put_volume()
398 ucontrol->value.integer.value[1] > SIU_MAX_VOLUME) in siu_dai_put_volume()
399 return -EINVAL; in siu_dai_put_volume()
401 new_vol = ucontrol->value.integer.value[0] | in siu_dai_put_volume()
402 ucontrol->value.integer.value[1] << 16; in siu_dai_put_volume()
404 /* See comment above - DSP firmware implementation */ in siu_dai_put_volume()
405 switch (kctrl->private_value) { in siu_dai_put_volume()
407 /* Playback is always on port 0 */ in siu_dai_put_volume()
408 cur_vol = port_info->playback.volume; in siu_dai_put_volume()
410 port_info->playback.volume = new_vol; in siu_dai_put_volume()
414 cur_vol = port_info->capture.volume; in siu_dai_put_volume()
416 port_info->capture.volume = new_vol; in siu_dai_put_volume()
420 __func__, kctrl->private_value); in siu_dai_put_volume()
421 return -EINVAL; in siu_dai_put_volume()
432 .name = "PCM Playback Volume",
452 struct device *dev = card->dev; in siu_init_port()
458 return -ENOMEM; in siu_init_port()
462 (*port_info)->playback.volume = DFLT_VOLUME_LEVEL; in siu_init_port()
463 (*port_info)->capture.volume = DFLT_VOLUME_LEVEL; in siu_init_port()
467 * ports use the same SPB. Therefore, we only register one in siu_init_port()
475 "failed to add playback controls %p port=%d err=%d\n", in siu_init_port()
497 struct snd_pcm_runtime *rt = substream->runtime; in siu_dai_startup()
501 dev_dbg(substream->pcm->card->dev, "%s: port=%d@%p\n", __func__, in siu_dai_startup()
502 info->port_id, port_info); in siu_dai_startup()
521 dev_dbg(substream->pcm->card->dev, "%s: port=%d@%p\n", __func__, in siu_dai_shutdown()
522 info->port_id, port_info); in siu_dai_shutdown()
524 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) in siu_dai_shutdown()
525 port_info->play_cap &= ~PLAYBACK_ENABLED; in siu_dai_shutdown()
527 port_info->play_cap &= ~CAPTURE_ENABLED; in siu_dai_shutdown()
530 if (!port_info->play_cap) { in siu_dai_shutdown()
532 if (WARN_ON(port_info->playback.rw_flg || port_info->capture.rw_flg)) in siu_dai_shutdown()
544 struct snd_pcm_runtime *rt = substream->runtime; in siu_dai_prepare()
549 dev_dbg(substream->pcm->card->dev, in siu_dai_prepare()
551 __func__, info->port_id, port_info->play_cap, rt->channels); in siu_dai_prepare()
553 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { in siu_dai_prepare()
555 siu_stream = &port_info->playback; in siu_dai_prepare()
558 siu_stream = &port_info->capture; in siu_dai_prepare()
562 if (!port_info->play_cap) { in siu_dai_prepare()
563 siu_stream->rw_flg = 0; /* stream-data transfer flag */ in siu_dai_prepare()
579 port_info->play_cap |= self; in siu_dai_prepare()
586 * SIU can set bus format to I2S / PCM / SPDIF independently for playback and
593 u32 __iomem *base = info->reg; in siu_dai_set_fmt()
596 dev_dbg(dai->dev, "%s: fmt 0x%x on port %d\n", in siu_dai_set_fmt()
597 __func__, fmt, info->port_id); in siu_dai_set_fmt()
599 if (info->port_id < 0) in siu_dai_set_fmt()
600 return -ENODEV; in siu_dai_set_fmt()
605 ifctl = siu_flags[info->port_id].playback.i2s | in siu_dai_set_fmt()
606 siu_flags[info->port_id].capture.i2s; in siu_dai_set_fmt()
609 ifctl = siu_flags[info->port_id].playback.pcm | in siu_dai_set_fmt()
610 siu_flags[info->port_id].capture.pcm; in siu_dai_set_fmt()
612 /* SPDIF disabled - see comment at the top */ in siu_dai_set_fmt()
614 return -EINVAL; in siu_dai_set_fmt()
617 ifctl |= ~(siu_flags[info->port_id].playback.mask | in siu_dai_set_fmt()
618 siu_flags[info->port_id].capture.mask) & in siu_dai_set_fmt()
633 return -EINVAL; in siu_dai_set_sysclk()
635 dev_dbg(dai->dev, "%s: using clock %d\n", __func__, clk_id); in siu_dai_set_sysclk()
655 return -EINVAL; in siu_dai_set_sysclk()
658 siu_clk = clk_get(dai->dev, siu_name); in siu_dai_set_sysclk()
660 dev_err(dai->dev, "%s: cannot get a SIU clock: %ld\n", __func__, in siu_dai_set_sysclk()
665 parent_clk = clk_get(dai->dev, parent_name); in siu_dai_set_sysclk()
668 dev_err(dai->dev, "cannot get a SIU clock parent: %d\n", ret); in siu_dai_set_sysclk()
674 dev_err(dai->dev, "cannot reparent the SIU clock: %d\n", ret); in siu_dai_set_sysclk()
680 dev_err(dai->dev, "cannot set SIU clock rate: %d\n", ret); in siu_dai_set_sysclk()
700 .name = "siu-i2s-dai",
701 .playback = {
723 info = devm_kmalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); in siu_probe()
725 return -ENOMEM; in siu_probe()
727 info->dev = &pdev->dev; in siu_probe()
729 ret = request_firmware(&fw_entry, "siu_spb.bin", &pdev->dev); in siu_probe()
734 * Loaded firmware is "const" - read only, but we have to modify it in in siu_probe()
737 memcpy(&info->fw, fw_entry->data, fw_entry->size); in siu_probe()
743 return -ENODEV; in siu_probe()
745 region = devm_request_mem_region(&pdev->dev, res->start, in siu_probe()
746 resource_size(res), pdev->name); in siu_probe()
748 dev_err(&pdev->dev, "SIU region already claimed\n"); in siu_probe()
749 return -EBUSY; in siu_probe()
752 info->pram = devm_ioremap(&pdev->dev, res->start, PRAM_SIZE); in siu_probe()
753 if (!info->pram) in siu_probe()
754 return -ENOMEM; in siu_probe()
755 info->xram = devm_ioremap(&pdev->dev, res->start + XRAM_OFFSET, in siu_probe()
757 if (!info->xram) in siu_probe()
758 return -ENOMEM; in siu_probe()
759 info->yram = devm_ioremap(&pdev->dev, res->start + YRAM_OFFSET, in siu_probe()
761 if (!info->yram) in siu_probe()
762 return -ENOMEM; in siu_probe()
763 info->reg = devm_ioremap(&pdev->dev, res->start + REG_OFFSET, in siu_probe()
764 resource_size(res) - REG_OFFSET); in siu_probe()
765 if (!info->reg) in siu_probe()
766 return -ENOMEM; in siu_probe()
768 dev_set_drvdata(&pdev->dev, info); in siu_probe()
771 ret = devm_snd_soc_register_component(&pdev->dev, &siu_component, in siu_probe()
776 pm_runtime_enable(&pdev->dev); in siu_probe()
783 pm_runtime_disable(&pdev->dev); in siu_remove()
788 .name = "siu-pcm-audio",