Lines Matching +full:dual +full:- +full:direction
1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
3 // This file is provided under a dual BSD/GPLv2 license. When using or
23 #include "../sof-audio.h"
24 #include "../ipc4-priv.h"
36 if (hstream->direction == SNDRV_PCM_STREAM_PLAYBACK) in hda_hstream_direction_str()
46 if (hstream->substream) in hda_hstream_dbg_get_stream_info_str()
47 rtd = snd_soc_substream_to_rtd(hstream->substream); in hda_hstream_dbg_get_stream_info_str()
48 else if (hstream->cstream) in hda_hstream_dbg_get_stream_info_str()
49 rtd = hstream->cstream->private_data; in hda_hstream_dbg_get_stream_info_str()
51 /* Non audio DMA user, like dma-trace */ in hda_hstream_dbg_get_stream_info_str()
52 return kasprintf(GFP_KERNEL, "-- (%s, stream_tag: %u)", in hda_hstream_dbg_get_stream_info_str()
54 hstream->stream_tag); in hda_hstream_dbg_get_stream_info_str()
57 rtd->dai_link->name, hda_hstream_direction_str(hstream), in hda_hstream_dbg_get_stream_info_str()
58 hstream->stream_tag); in hda_hstream_dbg_get_stream_info_str()
77 if (hstream->frags >= HDA_DSP_MAX_BDL_ENTRIES) { in hda_setup_bdle()
78 dev_err(sdev->dev, "error: stream frags exceeded\n"); in hda_setup_bdle()
79 return -EINVAL; in hda_setup_bdle()
84 bdl->addr_l = cpu_to_le32(lower_32_bits(addr)); in hda_setup_bdle()
85 bdl->addr_h = cpu_to_le32(upper_32_bits(addr)); in hda_setup_bdle()
89 if (bus->align_bdle_4k) { in hda_setup_bdle()
90 u32 remain = 0x1000 - (offset & 0xfff); in hda_setup_bdle()
95 bdl->size = cpu_to_le32(chunk); in hda_setup_bdle()
97 size -= chunk; in hda_setup_bdle()
98 bdl->ioc = (size || !ioc) ? 0 : cpu_to_le32(0x01); in hda_setup_bdle()
100 hstream->frags++; in hda_setup_bdle()
116 struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; in hda_dsp_stream_setup_bdl()
121 period_bytes = hstream->period_bytes; in hda_dsp_stream_setup_bdl()
122 dev_dbg(sdev->dev, "period_bytes:0x%x\n", period_bytes); in hda_dsp_stream_setup_bdl()
124 period_bytes = hstream->bufsize; in hda_dsp_stream_setup_bdl()
126 periods = hstream->bufsize / period_bytes; in hda_dsp_stream_setup_bdl()
128 dev_dbg(sdev->dev, "periods:%d\n", periods); in hda_dsp_stream_setup_bdl()
130 remain = hstream->bufsize % period_bytes; in hda_dsp_stream_setup_bdl()
135 bdl = (struct sof_intel_dsp_bdl *)hstream->bdl.area; in hda_dsp_stream_setup_bdl()
137 hstream->frags = 0; in hda_dsp_stream_setup_bdl()
143 ioc = hda->no_ipc_position ? in hda_dsp_stream_setup_bdl()
144 !hstream->no_period_wakeup : 0; in hda_dsp_stream_setup_bdl()
147 if (i == (periods - 1) && remain) in hda_dsp_stream_setup_bdl()
165 struct hdac_stream *hstream = &hext_stream->hstream; in hda_dsp_stream_spib_config()
168 if (!sdev->bar[HDA_DSP_SPIB_BAR]) { in hda_dsp_stream_spib_config()
169 dev_err(sdev->dev, "error: address of spib capability is NULL\n"); in hda_dsp_stream_spib_config()
170 return -EINVAL; in hda_dsp_stream_spib_config()
173 mask = (1 << hstream->index); in hda_dsp_stream_spib_config()
178 enable << hstream->index); in hda_dsp_stream_spib_config()
181 sof_io_write(sdev, hstream->spib_addr, size); in hda_dsp_stream_spib_config()
188 hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction, u32 flags) in hda_dsp_stream_get() argument
190 const struct sof_intel_dsp_desc *chip_info = get_chip_info(sdev->pdata); in hda_dsp_stream_get()
191 struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; in hda_dsp_stream_get()
197 spin_lock_irq(&bus->reg_lock); in hda_dsp_stream_get()
200 list_for_each_entry(s, &bus->stream_list, list) { in hda_dsp_stream_get()
201 if (s->direction == direction && !s->opened) { in hda_dsp_stream_get()
207 if (hda_stream->host_reserved) in hda_dsp_stream_get()
210 s->opened = true; in hda_dsp_stream_get()
215 spin_unlock_irq(&bus->reg_lock); in hda_dsp_stream_get()
219 dev_err(sdev->dev, "error: no free %s streams\n", snd_pcm_direction_name(direction)); in hda_dsp_stream_get()
223 hda_stream->flags = flags; in hda_dsp_stream_get()
230 if (chip_info->hw_ip_version < SOF_INTEL_ACE_1_0 && in hda_dsp_stream_get()
235 hda->l1_disabled = true; in hda_dsp_stream_get()
242 int hda_dsp_stream_put(struct snd_sof_dev *sdev, int direction, int stream_tag) in hda_dsp_stream_put() argument
244 const struct sof_intel_dsp_desc *chip_info = get_chip_info(sdev->pdata); in hda_dsp_stream_put()
245 struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; in hda_dsp_stream_put()
253 spin_lock_irq(&bus->reg_lock); in hda_dsp_stream_put()
259 list_for_each_entry(s, &bus->stream_list, list) { in hda_dsp_stream_put()
263 if (!s->opened) in hda_dsp_stream_put()
266 if (s->direction == direction && s->stream_tag == stream_tag) { in hda_dsp_stream_put()
267 s->opened = false; in hda_dsp_stream_put()
269 } else if (!(hda_stream->flags & SOF_HDA_STREAM_DMI_L1_COMPATIBLE)) { in hda_dsp_stream_put()
274 spin_unlock_irq(&bus->reg_lock); in hda_dsp_stream_put()
277 if (chip_info->hw_ip_version < SOF_INTEL_ACE_1_0 && dmi_l1_enable) { in hda_dsp_stream_put()
280 hda->l1_disabled = false; in hda_dsp_stream_put()
284 dev_err(sdev->dev, "%s: stream_tag %d not opened!\n", in hda_dsp_stream_put()
286 return -ENODEV; in hda_dsp_stream_put()
305 } while (--timeout); in hda_dsp_stream_reset()
307 dev_err(sdev->dev, "timeout waiting for stream reset\n"); in hda_dsp_stream_reset()
308 return -ETIMEDOUT; in hda_dsp_stream_reset()
322 } while (--timeout); in hda_dsp_stream_reset()
324 dev_err(sdev->dev, "timeout waiting for stream to exit reset\n"); in hda_dsp_stream_reset()
325 return -ETIMEDOUT; in hda_dsp_stream_reset()
334 struct hdac_stream *hstream = &hext_stream->hstream; in hda_dsp_stream_trigger()
343 if (!sdev->dspless_mode_selected) in hda_dsp_stream_trigger()
347 if (hstream->running) in hda_dsp_stream_trigger()
351 1 << hstream->index, in hda_dsp_stream_trigger()
352 1 << hstream->index); in hda_dsp_stream_trigger()
369 hstream->running = true; in hda_dsp_stream_trigger()
373 if (!sdev->dspless_mode_selected) in hda_dsp_stream_trigger()
394 hstream->running = false; in hda_dsp_stream_trigger()
397 1 << hstream->index, 0x0); in hda_dsp_stream_trigger()
401 dev_err(sdev->dev, "error: unknown command: %d\n", cmd); in hda_dsp_stream_trigger()
402 return -EINVAL; in hda_dsp_stream_trigger()
408 dev_err(sdev->dev, in hda_dsp_stream_trigger()
422 struct hdac_stream *hstream = &hext_stream->hstream; in hda_dsp_iccmax_stream_hw_params()
425 u32 mask = 0x1 << hstream->index; in hda_dsp_iccmax_stream_hw_params()
428 dev_err(sdev->dev, "error: no stream available\n"); in hda_dsp_iccmax_stream_hw_params()
429 return -ENODEV; in hda_dsp_iccmax_stream_hw_params()
433 dev_err(sdev->dev, "error: no dma buffer allocated!\n"); in hda_dsp_iccmax_stream_hw_params()
434 return -ENODEV; in hda_dsp_iccmax_stream_hw_params()
437 if (hstream->posbuf) in hda_dsp_iccmax_stream_hw_params()
438 *hstream->posbuf = 0; in hda_dsp_iccmax_stream_hw_params()
448 hstream->frags = 0; in hda_dsp_iccmax_stream_hw_params()
452 dev_err(sdev->dev, "error: set up of BDL failed\n"); in hda_dsp_iccmax_stream_hw_params()
459 (u32)hstream->bdl.addr); in hda_dsp_iccmax_stream_hw_params()
462 upper_32_bits(hstream->bdl.addr)); in hda_dsp_iccmax_stream_hw_params()
467 hstream->bufsize); in hda_dsp_iccmax_stream_hw_params()
472 0xffff, (hstream->frags - 1)); in hda_dsp_iccmax_stream_hw_params()
498 const struct sof_intel_dsp_desc *chip = get_chip_info(sdev->pdata); in hda_dsp_stream_hw_params()
507 dev_err(sdev->dev, "error: no stream available\n"); in hda_dsp_stream_hw_params()
508 return -ENODEV; in hda_dsp_stream_hw_params()
512 dev_err(sdev->dev, "error: no dma buffer allocated!\n"); in hda_dsp_stream_hw_params()
513 return -ENODEV; in hda_dsp_stream_hw_params()
516 hstream = &hext_stream->hstream; in hda_dsp_stream_hw_params()
518 mask = BIT(hstream->index); in hda_dsp_stream_hw_params()
521 if (!sdev->dspless_mode_selected) in hda_dsp_stream_hw_params()
539 dev_err(sdev->dev, in hda_dsp_stream_hw_params()
556 if (hstream->posbuf) in hda_dsp_stream_hw_params()
557 *hstream->posbuf = 0; in hda_dsp_stream_hw_params()
581 dev_err(sdev->dev, in hda_dsp_stream_hw_params()
593 hstream->frags = 0; in hda_dsp_stream_hw_params()
597 dev_err(sdev->dev, "error: set up of BDL failed\n"); in hda_dsp_stream_hw_params()
604 hstream->stream_tag << in hda_dsp_stream_hw_params()
610 hstream->bufsize); in hda_dsp_stream_hw_params()
614 * on earlier platforms - this is not needed on newer platforms in hda_dsp_stream_hw_params()
624 if (!sdev->dspless_mode_selected && (chip->quirks & SOF_INTEL_PROCEN_FMT_QUIRK)) in hda_dsp_stream_hw_params()
633 0xffff, hstream->format_val); in hda_dsp_stream_hw_params()
635 if (!sdev->dspless_mode_selected && (chip->quirks & SOF_INTEL_PROCEN_FMT_QUIRK)) in hda_dsp_stream_hw_params()
643 0xffff, (hstream->frags - 1)); in hda_dsp_stream_hw_params()
648 (u32)hstream->bdl.addr); in hda_dsp_stream_hw_params()
651 upper_32_bits(hstream->bdl.addr)); in hda_dsp_stream_hw_params()
654 if (bus->use_posbuf && bus->posbuf.addr && in hda_dsp_stream_hw_params()
658 upper_32_bits(bus->posbuf.addr)); in hda_dsp_stream_hw_params()
660 (u32)bus->posbuf.addr | in hda_dsp_stream_hw_params()
670 if (hstream->direction == SNDRV_PCM_STREAM_PLAYBACK) { in hda_dsp_stream_hw_params()
671 hstream->fifo_size = in hda_dsp_stream_hw_params()
675 hstream->fifo_size &= SOF_HDA_SD_FIFOSIZE_FIFOS_MASK; in hda_dsp_stream_hw_params()
676 hstream->fifo_size += 1; in hda_dsp_stream_hw_params()
678 hstream->fifo_size = 0; in hda_dsp_stream_hw_params()
687 struct hdac_stream *hstream = substream->runtime->private_data; in hda_dsp_stream_hw_free()
697 if (!sdev->dspless_mode_selected) { in hda_dsp_stream_hw_free()
699 u32 mask = BIT(hstream->index); in hda_dsp_stream_hw_free()
701 spin_lock_irq(&bus->reg_lock); in hda_dsp_stream_hw_free()
703 if (!hext_stream->link_locked) in hda_dsp_stream_hw_free()
706 spin_unlock_irq(&bus->reg_lock); in hda_dsp_stream_hw_free()
711 hstream->substream = NULL; in hda_dsp_stream_hw_free()
724 spin_lock_irq(&bus->reg_lock); in hda_dsp_check_stream_irq()
734 spin_unlock_irq(&bus->reg_lock); in hda_dsp_check_stream_irq()
741 hda_dsp_compr_bytes_transferred(struct hdac_stream *hstream, int direction) in hda_dsp_compr_bytes_transferred() argument
743 u64 buffer_size = hstream->bufsize; in hda_dsp_compr_bytes_transferred()
746 div64_u64_rem(hstream->curr_pos, buffer_size, &prev_pos); in hda_dsp_compr_bytes_transferred()
747 pos = hda_dsp_stream_get_position(hstream, direction, false); in hda_dsp_compr_bytes_transferred()
750 num_bytes = (buffer_size - prev_pos) + pos; in hda_dsp_compr_bytes_transferred()
752 num_bytes = pos - prev_pos; in hda_dsp_compr_bytes_transferred()
754 hstream->curr_pos += num_bytes; in hda_dsp_compr_bytes_transferred()
764 list_for_each_entry(s, &bus->stream_list, list) { in hda_dsp_stream_check()
765 if (status & BIT(s->index) && s->opened) { in hda_dsp_stream_check()
766 sd_status = readb(s->sd_addr + SOF_HDA_ADSP_REG_SD_STS); in hda_dsp_stream_check()
768 trace_sof_intel_hda_dsp_stream_status(bus->dev, s, sd_status); in hda_dsp_stream_check()
770 writeb(sd_status, s->sd_addr + SOF_HDA_ADSP_REG_SD_STS); in hda_dsp_stream_check()
773 if (!s->running) in hda_dsp_stream_check()
777 if (!s->substream && !s->cstream) { in hda_dsp_stream_check()
789 complete(&hda_stream->ioc); in hda_dsp_stream_check()
794 if (s->substream && sof_hda->no_ipc_position) { in hda_dsp_stream_check()
795 snd_sof_pcm_period_elapsed(s->substream); in hda_dsp_stream_check()
796 } else if (s->cstream) { in hda_dsp_stream_check()
797 hda_dsp_compr_bytes_transferred(s, s->cstream->direction); in hda_dsp_stream_check()
798 snd_compr_fragment_elapsed(s->cstream); in hda_dsp_stream_check()
819 spin_lock_irq(&bus->reg_lock); in hda_dsp_stream_threaded_handler()
830 spin_unlock_irq(&bus->reg_lock); in hda_dsp_stream_threaded_handler()
842 struct pci_dev *pci = to_pci_dev(sdev->dev); in hda_dsp_stream_init()
849 dev_dbg(sdev->dev, "hda global caps = 0x%x\n", gcap); in hda_dsp_stream_init()
856 dev_dbg(sdev->dev, "detected %d playback and %d capture streams\n", in hda_dsp_stream_init()
860 dev_err(sdev->dev, "error: too many playback streams %d\n", in hda_dsp_stream_init()
862 return -EINVAL; in hda_dsp_stream_init()
866 dev_err(sdev->dev, "error: too many capture streams %d\n", in hda_dsp_stream_init()
868 return -EINVAL; in hda_dsp_stream_init()
875 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev, in hda_dsp_stream_init()
877 &bus->posbuf); in hda_dsp_stream_init()
879 dev_err(sdev->dev, "error: posbuffer dma alloc failed\n"); in hda_dsp_stream_init()
880 return -ENOMEM; in hda_dsp_stream_init()
884 * mem alloc for the CORB/RIRB ringbuffers - this will be used only for in hda_dsp_stream_init()
887 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev, in hda_dsp_stream_init()
888 PAGE_SIZE, &bus->rb); in hda_dsp_stream_init()
890 dev_err(sdev->dev, "error: RB alloc failed\n"); in hda_dsp_stream_init()
891 return -ENOMEM; in hda_dsp_stream_init()
898 hda_stream = devm_kzalloc(sdev->dev, sizeof(*hda_stream), in hda_dsp_stream_init()
901 return -ENOMEM; in hda_dsp_stream_init()
903 hda_stream->sdev = sdev; in hda_dsp_stream_init()
904 init_completion(&hda_stream->ioc); in hda_dsp_stream_init()
906 hext_stream = &hda_stream->hext_stream; in hda_dsp_stream_init()
908 if (sdev->bar[HDA_DSP_PP_BAR]) { in hda_dsp_stream_init()
909 hext_stream->pphc_addr = sdev->bar[HDA_DSP_PP_BAR] + in hda_dsp_stream_init()
912 hext_stream->pplc_addr = sdev->bar[HDA_DSP_PP_BAR] + in hda_dsp_stream_init()
917 hstream = &hext_stream->hstream; in hda_dsp_stream_init()
920 if (sdev->bar[HDA_DSP_SPIB_BAR]) { in hda_dsp_stream_init()
921 hstream->spib_addr = sdev->bar[HDA_DSP_SPIB_BAR] + in hda_dsp_stream_init()
925 hstream->fifo_addr = sdev->bar[HDA_DSP_SPIB_BAR] + in hda_dsp_stream_init()
930 hstream->bus = bus; in hda_dsp_stream_init()
931 hstream->sd_int_sta_mask = 1 << i; in hda_dsp_stream_init()
932 hstream->index = i; in hda_dsp_stream_init()
934 hstream->sd_addr = sdev->bar[HDA_DSP_HDA_BAR] + sd_offset; in hda_dsp_stream_init()
935 hstream->opened = false; in hda_dsp_stream_init()
936 hstream->running = false; in hda_dsp_stream_init()
939 hstream->stream_tag = i + 1; in hda_dsp_stream_init()
940 hstream->direction = SNDRV_PCM_STREAM_CAPTURE; in hda_dsp_stream_init()
942 hstream->stream_tag = i - num_capture + 1; in hda_dsp_stream_init()
943 hstream->direction = SNDRV_PCM_STREAM_PLAYBACK; in hda_dsp_stream_init()
947 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev, in hda_dsp_stream_init()
948 HDA_DSP_BDL_SIZE, &hstream->bdl); in hda_dsp_stream_init()
950 dev_err(sdev->dev, "error: stream bdl dma alloc failed\n"); in hda_dsp_stream_init()
951 return -ENOMEM; in hda_dsp_stream_init()
954 hstream->posbuf = (__le32 *)(bus->posbuf.area + in hda_dsp_stream_init()
955 (hstream->index) * 8); in hda_dsp_stream_init()
957 list_add_tail(&hstream->list, &bus->stream_list); in hda_dsp_stream_init()
961 sof_hda->stream_max = num_total; in hda_dsp_stream_init()
964 if (sdev->pdata->ipc_type == SOF_IPC_TYPE_4) { in hda_dsp_stream_init()
965 struct sof_ipc4_fw_data *ipc4_data = sdev->private; in hda_dsp_stream_init()
967 ipc4_data->num_playback_streams = num_playback; in hda_dsp_stream_init()
968 ipc4_data->num_capture_streams = num_capture; in hda_dsp_stream_init()
983 if (bus->posbuf.area) in hda_dsp_stream_free()
984 snd_dma_free_pages(&bus->posbuf); in hda_dsp_stream_free()
986 /* free CORB/RIRB buffer - only used for HDaudio codecs */ in hda_dsp_stream_free()
987 if (bus->rb.area) in hda_dsp_stream_free()
988 snd_dma_free_pages(&bus->rb); in hda_dsp_stream_free()
990 list_for_each_entry_safe(s, _s, &bus->stream_list, list) { in hda_dsp_stream_free()
994 if (s->bdl.area) in hda_dsp_stream_free()
995 snd_dma_free_pages(&s->bdl); in hda_dsp_stream_free()
996 list_del(&s->list); in hda_dsp_stream_free()
1000 devm_kfree(sdev->dev, hda_stream); in hda_dsp_stream_free()
1006 int direction, bool can_sleep) in hda_dsp_stream_get_position() argument
1010 struct snd_sof_dev *sdev = hda_stream->sdev; in hda_dsp_stream_get_position()
1021 * what traffic class is used, and on all SOF-enabled platforms in hda_dsp_stream_get_position()
1022 * only VC0 is supported so the work-around was likely not necessary in hda_dsp_stream_get_position()
1033 if (direction == SNDRV_PCM_STREAM_PLAYBACK) { in hda_dsp_stream_get_position()
1037 hstream->index)); in hda_dsp_stream_get_position()
1057 hstream->index)); in hda_dsp_stream_get_position()
1068 hstream->index)); in hda_dsp_stream_get_position()
1079 dev_err_once(sdev->dev, "hda_position_quirk value %d not supported\n", in hda_dsp_stream_get_position()
1085 if (pos >= hstream->bufsize) in hda_dsp_stream_get_position()
1095 * hda_dsp_get_stream_llp - Retrieve the LLP (Linear Link Position) of the stream
1106 struct hdac_stream *hstream = substream->runtime->private_data; in hda_dsp_get_stream_llp()
1113 * pplc_addr = sdev->bar[HDA_DSP_PP_BAR] + in hda_dsp_get_stream_llp()
1118 * Use this pre-calculated address to avoid repeated re-calculation. in hda_dsp_get_stream_llp()
1120 llp_l = readl(hext_stream->pplc_addr + AZX_REG_PPLCLLPL); in hda_dsp_get_stream_llp()
1121 llp_u = readl(hext_stream->pplc_addr + AZX_REG_PPLCLLPU); in hda_dsp_get_stream_llp()
1124 if (hext_stream->pplcllpl || hext_stream->pplcllpu) in hda_dsp_get_stream_llp()
1125 return merge_u64(llp_u, llp_l) - in hda_dsp_get_stream_llp()
1126 merge_u64(hext_stream->pplcllpu, hext_stream->pplcllpl); in hda_dsp_get_stream_llp()
1133 * hda_dsp_get_stream_ldp - Retrieve the LDP (Linear DMA Position) of the stream
1144 struct hdac_stream *hstream = substream->runtime->private_data; in hda_dsp_get_stream_ldp()
1151 * pphc_addr = sdev->bar[HDA_DSP_PP_BAR] + in hda_dsp_get_stream_ldp()
1155 * Use this pre-calculated address to avoid repeated re-calculation. in hda_dsp_get_stream_ldp()
1157 ldp_l = readl(hext_stream->pphc_addr + AZX_REG_PPHCLDPL); in hda_dsp_get_stream_ldp()
1158 ldp_u = readl(hext_stream->pphc_addr + AZX_REG_PPHCLDPU); in hda_dsp_get_stream_ldp()