Lines Matching +full:audio +full:- +full:core

1 // SPDX-License-Identifier: GPL-2.0-only
3 * HD-audio stream operations
11 #include <sound/core.h>
26 * +--+-------+
28 * +--+----+--+
32 * +--+----+--+
34 * +--+----+--+
39 * +--+----+--+
41 * +--+----+--+
45 * +--+----+--+
47 * +----------+
51 * snd_hdac_get_stream_stripe_ctl - get stripe control value
52 * @bus: HD-audio core bus
58 struct snd_pcm_runtime *runtime = substream->runtime; in snd_hdac_get_stream_stripe_ctl()
59 unsigned int channels = runtime->channels, in snd_hdac_get_stream_stripe_ctl()
60 rate = runtime->rate, in snd_hdac_get_stream_stripe_ctl()
61 bits_per_sample = runtime->sample_bits, in snd_hdac_get_stream_stripe_ctl()
67 /* following is from HD audio spec */ in snd_hdac_get_stream_stripe_ctl()
75 if (value >= bus->sdo_limit) in snd_hdac_get_stream_stripe_ctl()
85 * snd_hdac_stream_init - initialize each stream (aka device)
86 * @bus: HD-audio core bus
87 * @azx_dev: HD-audio core stream object to initialize
97 azx_dev->bus = bus; in snd_hdac_stream_init()
99 azx_dev->sd_addr = bus->remap_addr + (0x20 * idx + 0x80); in snd_hdac_stream_init()
101 azx_dev->sd_int_sta_mask = 1 << idx; in snd_hdac_stream_init()
102 azx_dev->index = idx; in snd_hdac_stream_init()
103 azx_dev->direction = direction; in snd_hdac_stream_init()
104 azx_dev->stream_tag = tag; in snd_hdac_stream_init()
106 list_add_tail(&azx_dev->list, &bus->stream_list); in snd_hdac_stream_init()
108 if (bus->spbcap) { in snd_hdac_stream_init()
109 azx_dev->spib_addr = bus->spbcap + AZX_SPB_BASE + in snd_hdac_stream_init()
113 azx_dev->fifo_addr = bus->spbcap + AZX_SPB_BASE + in snd_hdac_stream_init()
118 if (bus->drsmcap) in snd_hdac_stream_init()
119 azx_dev->dpibr_addr = bus->drsmcap + AZX_DRSM_BASE + in snd_hdac_stream_init()
125 * snd_hdac_stream_start - start a stream
126 * @azx_dev: HD-audio core stream to start
132 struct hdac_bus *bus = azx_dev->bus; in snd_hdac_stream_start()
137 azx_dev->start_wallclk = snd_hdac_chip_readl(bus, WALLCLK); in snd_hdac_stream_start()
141 1 << azx_dev->index, in snd_hdac_stream_start()
142 1 << azx_dev->index); in snd_hdac_stream_start()
144 if (azx_dev->stripe) { in snd_hdac_stream_start()
145 if (azx_dev->substream) in snd_hdac_stream_start()
146 stripe_ctl = snd_hdac_get_stream_stripe_ctl(bus, azx_dev->substream); in snd_hdac_stream_start()
153 if (bus->access_sdnctl_in_dword) in snd_hdac_stream_start()
159 azx_dev->running = true; in snd_hdac_stream_start()
164 * snd_hdac_stream_clear - helper to clear stream registers and stop DMA transfers
165 * @azx_dev: HD-audio core stream to stop
172 if (azx_dev->stripe) in snd_hdac_stream_clear()
174 azx_dev->running = false; in snd_hdac_stream_clear()
178 * snd_hdac_stream_stop - stop a stream
179 * @azx_dev: HD-audio core stream to stop
185 trace_snd_hdac_stream_stop(azx_dev->bus, azx_dev); in snd_hdac_stream_stop()
189 snd_hdac_chip_updatel(azx_dev->bus, INTCTL, 1 << azx_dev->index, 0); in snd_hdac_stream_stop()
194 * snd_hdac_stop_streams - stop all streams
195 * @bus: HD-audio core bus
201 list_for_each_entry(stream, &bus->stream_list, list) in snd_hdac_stop_streams()
207 * snd_hdac_stop_streams_and_chip - stop all streams and chip if running
208 * @bus: HD-audio core bus
213 if (bus->chip_init) { in snd_hdac_stop_streams_and_chip()
221 * snd_hdac_stream_reset - reset a stream
222 * @azx_dev: HD-audio core stream to reset
238 if (azx_dev->bus->dma_stop_delay && dma_run_state) in snd_hdac_stream_reset()
239 udelay(azx_dev->bus->dma_stop_delay); in snd_hdac_stream_reset()
246 /* reset first position - may not be synced with hw at this time */ in snd_hdac_stream_reset()
247 if (azx_dev->posbuf) in snd_hdac_stream_reset()
248 *azx_dev->posbuf = 0; in snd_hdac_stream_reset()
253 * snd_hdac_stream_setup - set up the SD for streaming
254 * @azx_dev: HD-audio core stream to set up
255 * @code_loading: Whether the stream is for PCM or code-loading.
259 struct hdac_bus *bus = azx_dev->bus; in snd_hdac_stream_setup()
265 if (azx_dev->substream) in snd_hdac_stream_setup()
266 runtime = azx_dev->substream->runtime; in snd_hdac_stream_setup()
274 (azx_dev->stream_tag << SD_CTL_STREAM_TAG_SHIFT); in snd_hdac_stream_setup()
275 if (!bus->snoop) in snd_hdac_stream_setup()
280 snd_hdac_stream_writel(azx_dev, SD_CBL, azx_dev->bufsize); in snd_hdac_stream_setup()
284 snd_hdac_stream_writew(azx_dev, SD_FORMAT, azx_dev->format_val); in snd_hdac_stream_setup()
287 snd_hdac_stream_writew(azx_dev, SD_LVI, azx_dev->frags - 1); in snd_hdac_stream_setup()
291 snd_hdac_stream_writel(azx_dev, SD_BDLPL, (u32)azx_dev->bdl.addr); in snd_hdac_stream_setup()
294 upper_32_bits(azx_dev->bdl.addr)); in snd_hdac_stream_setup()
297 if (bus->use_posbuf && bus->posbuf.addr) { in snd_hdac_stream_setup()
300 (u32)bus->posbuf.addr | AZX_DPLBASE_ENABLE); in snd_hdac_stream_setup()
307 /* Once SDxFMT is set, the controller programs SDxFIFOS to non-zero value. */ in snd_hdac_stream_setup()
311 dev_dbg(bus->dev, "polling SD_FIFOSIZE 0x%04x failed: %d\n", in snd_hdac_stream_setup()
313 azx_dev->fifo_size = reg; in snd_hdac_stream_setup()
320 if (runtime && runtime->period_size > 64) in snd_hdac_stream_setup()
321 azx_dev->delay_negative_threshold = in snd_hdac_stream_setup()
322 -frames_to_bytes(runtime, 64); in snd_hdac_stream_setup()
324 azx_dev->delay_negative_threshold = 0; in snd_hdac_stream_setup()
328 azx_dev->period_wallclk = (((runtime->period_size * 24000) / in snd_hdac_stream_setup()
329 runtime->rate) * 1000); in snd_hdac_stream_setup()
336 * snd_hdac_stream_cleanup - cleanup a stream
337 * @azx_dev: HD-audio core stream to clean up
344 azx_dev->bufsize = 0; in snd_hdac_stream_cleanup()
345 azx_dev->period_bytes = 0; in snd_hdac_stream_cleanup()
346 azx_dev->format_val = 0; in snd_hdac_stream_cleanup()
351 * snd_hdac_stream_assign - assign a stream for the PCM
352 * @bus: HD-audio core bus
358 * beforehand. Also, when bus->reverse_assign flag is set, the last free
367 /* make a non-zero unique key for the substream */ in snd_hdac_stream_assign()
368 int key = (substream->number << 2) | (substream->stream + 1); in snd_hdac_stream_assign()
370 if (substream->pcm) in snd_hdac_stream_assign()
371 key |= (substream->pcm->device << 16); in snd_hdac_stream_assign()
373 spin_lock_irq(&bus->reg_lock); in snd_hdac_stream_assign()
374 list_for_each_entry(azx_dev, &bus->stream_list, list) { in snd_hdac_stream_assign()
375 if (azx_dev->direction != substream->stream) in snd_hdac_stream_assign()
377 if (azx_dev->opened) in snd_hdac_stream_assign()
379 if (azx_dev->assigned_key == key) { in snd_hdac_stream_assign()
383 if (!res || bus->reverse_assign) in snd_hdac_stream_assign()
387 res->opened = 1; in snd_hdac_stream_assign()
388 res->running = 0; in snd_hdac_stream_assign()
389 res->assigned_key = key; in snd_hdac_stream_assign()
390 res->substream = substream; in snd_hdac_stream_assign()
392 spin_unlock_irq(&bus->reg_lock); in snd_hdac_stream_assign()
398 * snd_hdac_stream_release_locked - release the assigned stream
399 * @azx_dev: HD-audio core stream to release
402 * The bus->reg_lock needs to be taken at a higher level
406 azx_dev->opened = 0; in snd_hdac_stream_release_locked()
407 azx_dev->running = 0; in snd_hdac_stream_release_locked()
408 azx_dev->substream = NULL; in snd_hdac_stream_release_locked()
413 * snd_hdac_stream_release - release the assigned stream
414 * @azx_dev: HD-audio core stream to release
420 struct hdac_bus *bus = azx_dev->bus; in snd_hdac_stream_release()
422 spin_lock_irq(&bus->reg_lock); in snd_hdac_stream_release()
424 spin_unlock_irq(&bus->reg_lock); in snd_hdac_stream_release()
429 * snd_hdac_get_stream - return hdac_stream based on stream_tag and
432 * @bus: HD-audio core bus
441 list_for_each_entry(s, &bus->stream_list, list) { in snd_hdac_get_stream()
442 if (s->direction == dir && s->stream_tag == stream_tag) in snd_hdac_get_stream()
464 if (azx_dev->frags >= AZX_MAX_BDL_ENTRIES) in setup_bdle()
465 return -EINVAL; in setup_bdle()
474 if (bus->align_bdle_4k) { in setup_bdle()
475 u32 remain = 0x1000 - (ofs & 0xfff); in setup_bdle()
484 size -= chunk; in setup_bdle()
487 azx_dev->frags++; in setup_bdle()
495 * snd_hdac_stream_setup_periods - set up BDL entries
496 * @azx_dev: HD-audio core stream to set up
503 struct hdac_bus *bus = azx_dev->bus; in snd_hdac_stream_setup_periods()
504 struct snd_pcm_substream *substream = azx_dev->substream; in snd_hdac_stream_setup_periods()
505 struct snd_compr_stream *cstream = azx_dev->cstream; in snd_hdac_stream_setup_periods()
513 runtime = substream->runtime; in snd_hdac_stream_setup_periods()
519 return -EINVAL; in snd_hdac_stream_setup_periods()
526 period_bytes = azx_dev->period_bytes; in snd_hdac_stream_setup_periods()
527 periods = azx_dev->bufsize / period_bytes; in snd_hdac_stream_setup_periods()
530 bdl = (__le32 *)azx_dev->bdl.area; in snd_hdac_stream_setup_periods()
532 azx_dev->frags = 0; in snd_hdac_stream_setup_periods()
534 pos_adj = bus->bdl_pos_adj; in snd_hdac_stream_setup_periods()
535 if (runtime && !azx_dev->no_period_wakeup && pos_adj > 0) { in snd_hdac_stream_setup_periods()
537 pos_adj = DIV_ROUND_UP(pos_adj * runtime->rate, 48000); in snd_hdac_stream_setup_periods()
544 dev_warn(bus->dev, "Too big adjustment %d\n", in snd_hdac_stream_setup_periods()
557 if (i == periods - 1 && pos_adj) in snd_hdac_stream_setup_periods()
559 &bdl, ofs, period_bytes - pos_adj, 0); in snd_hdac_stream_setup_periods()
563 !azx_dev->no_period_wakeup); in snd_hdac_stream_setup_periods()
570 dev_dbg(bus->dev, "Too many BDL entries: buffer=%d, period=%d\n", in snd_hdac_stream_setup_periods()
571 azx_dev->bufsize, period_bytes); in snd_hdac_stream_setup_periods()
572 return -EINVAL; in snd_hdac_stream_setup_periods()
577 * snd_hdac_stream_set_params - set stream parameters
578 * @azx_dev: HD-audio core stream for which parameters are to be set
581 * Setup the HD-audio core stream parameters from substream of the stream
587 struct snd_pcm_substream *substream = azx_dev->substream; in snd_hdac_stream_set_params()
588 struct snd_compr_stream *cstream = azx_dev->cstream; in snd_hdac_stream_set_params()
596 no_period_wakeup = substream->runtime->no_period_wakeup; in snd_hdac_stream_set_params()
598 bufsize = cstream->runtime->buffer_size; in snd_hdac_stream_set_params()
599 period_bytes = cstream->runtime->fragment_size; in snd_hdac_stream_set_params()
602 return -EINVAL; in snd_hdac_stream_set_params()
605 if (bufsize != azx_dev->bufsize || in snd_hdac_stream_set_params()
606 period_bytes != azx_dev->period_bytes || in snd_hdac_stream_set_params()
607 format_val != azx_dev->format_val || in snd_hdac_stream_set_params()
608 no_period_wakeup != azx_dev->no_period_wakeup) { in snd_hdac_stream_set_params()
609 azx_dev->bufsize = bufsize; in snd_hdac_stream_set_params()
610 azx_dev->period_bytes = period_bytes; in snd_hdac_stream_set_params()
611 azx_dev->format_val = format_val; in snd_hdac_stream_set_params()
612 azx_dev->no_period_wakeup = no_period_wakeup; in snd_hdac_stream_set_params()
625 return snd_hdac_chip_readl(azx_dev->bus, WALLCLK); in azx_cc_read()
631 struct timecounter *tc = &azx_dev->tc; in azx_timecounter_init()
632 struct cyclecounter *cc = &azx_dev->cc; in azx_timecounter_init()
635 cc->read = azx_cc_read; in azx_timecounter_init()
636 cc->mask = CLOCKSOURCE_MASK(32); in azx_timecounter_init()
642 clocks_calc_mult_shift(&cc->mult, &cc->shift, 24000000, in azx_timecounter_init()
645 nsec = 0; /* audio time is elapsed time since trigger */ in azx_timecounter_init()
652 tc->cycle_last = last; in azx_timecounter_init()
657 * snd_hdac_stream_timecounter_init - initialize time counter
658 * @azx_dev: HD-audio core stream (master stream)
670 struct hdac_bus *bus = azx_dev->bus; in snd_hdac_stream_timecounter_init()
671 struct snd_pcm_runtime *runtime = azx_dev->substream->runtime; in snd_hdac_stream_timecounter_init()
679 list_for_each_entry(s, &bus->stream_list, list) { in snd_hdac_stream_timecounter_init()
680 if ((streams & (1 << s->index))) { in snd_hdac_stream_timecounter_init()
684 cycle_last = s->tc.cycle_last; in snd_hdac_stream_timecounter_init()
690 snd_pcm_gettime(runtime, &runtime->trigger_tstamp); in snd_hdac_stream_timecounter_init()
691 runtime->trigger_tstamp_latched = true; in snd_hdac_stream_timecounter_init()
696 * snd_hdac_stream_sync_trigger - turn on/off stream sync register
697 * @azx_dev: HD-audio core stream (master stream)
705 struct hdac_bus *bus = azx_dev->bus; in snd_hdac_stream_sync_trigger()
720 * snd_hdac_stream_sync - sync with start/stop trigger operation
721 * @azx_dev: HD-audio core stream (master stream)
731 struct hdac_bus *bus = azx_dev->bus; in snd_hdac_stream_sync()
735 for (timeout = 5000; timeout; timeout--) { in snd_hdac_stream_sync()
737 list_for_each_entry(s, &bus->stream_list, list) { in snd_hdac_stream_sync()
738 if (!(streams & (1 << s->index))) in snd_hdac_stream_sync()
768 * snd_hdac_stream_spbcap_enable - enable SPIB for a stream
769 * @bus: HD-audio core bus
778 if (!bus->spbcap) { in snd_hdac_stream_spbcap_enable()
779 dev_err(bus->dev, "Address of SPB capability is NULL\n"); in snd_hdac_stream_spbcap_enable()
786 snd_hdac_updatel(bus->spbcap, AZX_REG_SPB_SPBFCCTL, mask, mask); in snd_hdac_stream_spbcap_enable()
788 snd_hdac_updatel(bus->spbcap, AZX_REG_SPB_SPBFCCTL, mask, 0); in snd_hdac_stream_spbcap_enable()
793 * snd_hdac_stream_set_spib - sets the spib value of a stream
794 * @bus: HD-audio core bus
801 if (!bus->spbcap) { in snd_hdac_stream_set_spib()
802 dev_err(bus->dev, "Address of SPB capability is NULL\n"); in snd_hdac_stream_set_spib()
803 return -EINVAL; in snd_hdac_stream_set_spib()
806 writel(value, azx_dev->spib_addr); in snd_hdac_stream_set_spib()
813 * snd_hdac_stream_get_spbmaxfifo - gets the spib value of a stream
814 * @bus: HD-audio core bus
822 if (!bus->spbcap) { in snd_hdac_stream_get_spbmaxfifo()
823 dev_err(bus->dev, "Address of SPB capability is NULL\n"); in snd_hdac_stream_get_spbmaxfifo()
824 return -EINVAL; in snd_hdac_stream_get_spbmaxfifo()
827 return readl(azx_dev->fifo_addr); in snd_hdac_stream_get_spbmaxfifo()
832 * snd_hdac_stream_drsm_enable - enable DMA resume for a stream
833 * @bus: HD-audio core bus
842 if (!bus->drsmcap) { in snd_hdac_stream_drsm_enable()
843 dev_err(bus->dev, "Address of DRSM capability is NULL\n"); in snd_hdac_stream_drsm_enable()
850 snd_hdac_updatel(bus->drsmcap, AZX_REG_DRSM_CTL, mask, mask); in snd_hdac_stream_drsm_enable()
852 snd_hdac_updatel(bus->drsmcap, AZX_REG_DRSM_CTL, mask, 0); in snd_hdac_stream_drsm_enable()
857 * snd_hdac_stream_wait_drsm - wait for HW to clear RSM for a stream
858 * @azx_dev: HD-audio core stream to await RSM for
860 * Returns 0 on success and -ETIMEDOUT upon a timeout.
864 struct hdac_bus *bus = azx_dev->bus; in snd_hdac_stream_wait_drsm()
868 mask = 1 << azx_dev->index; in snd_hdac_stream_wait_drsm()
871 bus->drsmcap + AZX_REG_DRSM_CTL); in snd_hdac_stream_wait_drsm()
873 dev_dbg(bus->dev, "polling RSM 0x%08x failed: %d\n", mask, ret); in snd_hdac_stream_wait_drsm()
879 * snd_hdac_stream_set_dpibr - sets the dpibr value of a stream
880 * @bus: HD-audio core bus
887 if (!bus->drsmcap) { in snd_hdac_stream_set_dpibr()
888 dev_err(bus->dev, "Address of DRSM capability is NULL\n"); in snd_hdac_stream_set_dpibr()
889 return -EINVAL; in snd_hdac_stream_set_dpibr()
892 writel(value, azx_dev->dpibr_addr); in snd_hdac_stream_set_dpibr()
899 * snd_hdac_stream_set_lpib - sets the lpib value of a stream
913 * snd_hdac_dsp_prepare - prepare for DSP loading
914 * @azx_dev: HD-audio core stream used for DSP loading
915 * @format: HD-audio stream format
925 struct hdac_bus *bus = azx_dev->bus; in snd_hdac_dsp_prepare()
930 spin_lock_irq(&bus->reg_lock); in snd_hdac_dsp_prepare()
931 if (azx_dev->running || azx_dev->locked) { in snd_hdac_dsp_prepare()
932 spin_unlock_irq(&bus->reg_lock); in snd_hdac_dsp_prepare()
933 err = -EBUSY; in snd_hdac_dsp_prepare()
936 azx_dev->locked = true; in snd_hdac_dsp_prepare()
937 spin_unlock_irq(&bus->reg_lock); in snd_hdac_dsp_prepare()
939 err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, bus->dev, in snd_hdac_dsp_prepare()
944 azx_dev->substream = NULL; in snd_hdac_dsp_prepare()
945 azx_dev->bufsize = byte_size; in snd_hdac_dsp_prepare()
946 azx_dev->period_bytes = byte_size; in snd_hdac_dsp_prepare()
947 azx_dev->format_val = format; in snd_hdac_dsp_prepare()
955 azx_dev->frags = 0; in snd_hdac_dsp_prepare()
956 bdl = (__le32 *)azx_dev->bdl.area; in snd_hdac_dsp_prepare()
963 return azx_dev->stream_tag; in snd_hdac_dsp_prepare()
968 spin_lock_irq(&bus->reg_lock); in snd_hdac_dsp_prepare()
969 azx_dev->locked = false; in snd_hdac_dsp_prepare()
970 spin_unlock_irq(&bus->reg_lock); in snd_hdac_dsp_prepare()
978 * snd_hdac_dsp_trigger - start / stop DSP loading
979 * @azx_dev: HD-audio core stream used for DSP loading
992 * snd_hdac_dsp_cleanup - clean up the stream from DSP loading to normal
993 * @azx_dev: HD-audio core stream used for DSP loading
999 struct hdac_bus *bus = azx_dev->bus; in snd_hdac_dsp_cleanup()
1001 if (!dmab->area || !azx_dev->locked) in snd_hdac_dsp_cleanup()
1009 azx_dev->bufsize = 0; in snd_hdac_dsp_cleanup()
1010 azx_dev->period_bytes = 0; in snd_hdac_dsp_cleanup()
1011 azx_dev->format_val = 0; in snd_hdac_dsp_cleanup()
1014 dmab->area = NULL; in snd_hdac_dsp_cleanup()
1016 spin_lock_irq(&bus->reg_lock); in snd_hdac_dsp_cleanup()
1017 azx_dev->locked = false; in snd_hdac_dsp_cleanup()
1018 spin_unlock_irq(&bus->reg_lock); in snd_hdac_dsp_cleanup()