Lines Matching +full:start +full:- +full:up

1 // SPDX-License-Identifier: GPL-2.0-only
3 * HD-audio stream operations
25 * +--+-------+
27 * +--+----+--+
31 * +--+----+--+
33 * +--+----+--+
38 * +--+----+--+
40 * +--+----+--+
44 * +--+----+--+
46 * +----------+
50 * snd_hdac_get_stream_stripe_ctl - get stripe control value
51 * @bus: HD-audio core bus
57 struct snd_pcm_runtime *runtime = substream->runtime; in snd_hdac_get_stream_stripe_ctl()
58 unsigned int channels = runtime->channels, in snd_hdac_get_stream_stripe_ctl()
59 rate = runtime->rate, in snd_hdac_get_stream_stripe_ctl()
60 bits_per_sample = runtime->sample_bits, in snd_hdac_get_stream_stripe_ctl()
74 if (value >= bus->sdo_limit) in snd_hdac_get_stream_stripe_ctl()
84 * snd_hdac_stream_init - initialize each stream (aka device)
85 * @bus: HD-audio core bus
86 * @azx_dev: HD-audio core stream object to initialize
96 azx_dev->bus = bus; in snd_hdac_stream_init()
98 azx_dev->sd_addr = bus->remap_addr + (0x20 * idx + 0x80); in snd_hdac_stream_init()
100 azx_dev->sd_int_sta_mask = 1 << idx; in snd_hdac_stream_init()
101 azx_dev->index = idx; in snd_hdac_stream_init()
102 azx_dev->direction = direction; in snd_hdac_stream_init()
103 azx_dev->stream_tag = tag; in snd_hdac_stream_init()
105 list_add_tail(&azx_dev->list, &bus->stream_list); in snd_hdac_stream_init()
110 * snd_hdac_stream_start - start a stream
111 * @azx_dev: HD-audio core stream to start
114 * Start a stream, set start_wallclk and set the running flag.
118 struct hdac_bus *bus = azx_dev->bus; in snd_hdac_stream_start()
123 azx_dev->start_wallclk = snd_hdac_chip_readl(bus, WALLCLK); in snd_hdac_stream_start()
125 azx_dev->start_wallclk -= azx_dev->period_wallclk; in snd_hdac_stream_start()
129 1 << azx_dev->index, in snd_hdac_stream_start()
130 1 << azx_dev->index); in snd_hdac_stream_start()
132 if (azx_dev->stripe) { in snd_hdac_stream_start()
133 if (azx_dev->substream) in snd_hdac_stream_start()
134 stripe_ctl = snd_hdac_get_stream_stripe_ctl(bus, azx_dev->substream); in snd_hdac_stream_start()
140 /* set DMA start and interrupt mask */ in snd_hdac_stream_start()
143 azx_dev->running = true; in snd_hdac_stream_start()
148 * snd_hdac_stream_clear - helper to clear stream registers and stop DMA transfers
149 * @azx_dev: HD-audio core stream to stop
156 if (azx_dev->stripe) in snd_hdac_stream_clear()
158 azx_dev->running = false; in snd_hdac_stream_clear()
162 * snd_hdac_stream_stop - stop a stream
163 * @azx_dev: HD-audio core stream to stop
169 trace_snd_hdac_stream_stop(azx_dev->bus, azx_dev); in snd_hdac_stream_stop()
173 snd_hdac_chip_updatel(azx_dev->bus, INTCTL, 1 << azx_dev->index, 0); in snd_hdac_stream_stop()
178 * snd_hdac_stop_streams - stop all streams
179 * @bus: HD-audio core bus
185 list_for_each_entry(stream, &bus->stream_list, list) in snd_hdac_stop_streams()
191 * snd_hdac_stop_streams_and_chip - stop all streams and chip if running
192 * @bus: HD-audio core bus
197 if (bus->chip_init) { in snd_hdac_stop_streams_and_chip()
205 * snd_hdac_stream_reset - reset a stream
206 * @azx_dev: HD-audio core stream to reset
222 if (azx_dev->bus->dma_stop_delay && dma_run_state) in snd_hdac_stream_reset()
223 udelay(azx_dev->bus->dma_stop_delay); in snd_hdac_stream_reset()
230 /* reset first position - may not be synced with hw at this time */ in snd_hdac_stream_reset()
231 if (azx_dev->posbuf) in snd_hdac_stream_reset()
232 *azx_dev->posbuf = 0; in snd_hdac_stream_reset()
237 * snd_hdac_stream_setup - set up the SD for streaming
238 * @azx_dev: HD-audio core stream to set up
242 struct hdac_bus *bus = azx_dev->bus; in snd_hdac_stream_setup()
246 if (azx_dev->substream) in snd_hdac_stream_setup()
247 runtime = azx_dev->substream->runtime; in snd_hdac_stream_setup()
255 (azx_dev->stream_tag << SD_CTL_STREAM_TAG_SHIFT); in snd_hdac_stream_setup()
256 if (!bus->snoop) in snd_hdac_stream_setup()
261 snd_hdac_stream_writel(azx_dev, SD_CBL, azx_dev->bufsize); in snd_hdac_stream_setup()
265 snd_hdac_stream_writew(azx_dev, SD_FORMAT, azx_dev->format_val); in snd_hdac_stream_setup()
268 snd_hdac_stream_writew(azx_dev, SD_LVI, azx_dev->frags - 1); in snd_hdac_stream_setup()
272 snd_hdac_stream_writel(azx_dev, SD_BDLPL, (u32)azx_dev->bdl.addr); in snd_hdac_stream_setup()
275 upper_32_bits(azx_dev->bdl.addr)); in snd_hdac_stream_setup()
278 if (bus->use_posbuf && bus->posbuf.addr) { in snd_hdac_stream_setup()
281 (u32)bus->posbuf.addr | AZX_DPLBASE_ENABLE); in snd_hdac_stream_setup()
287 azx_dev->fifo_size = snd_hdac_stream_readw(azx_dev, SD_FIFOSIZE) + 1; in snd_hdac_stream_setup()
293 if (runtime && runtime->period_size > 64) in snd_hdac_stream_setup()
294 azx_dev->delay_negative_threshold = in snd_hdac_stream_setup()
295 -frames_to_bytes(runtime, 64); in snd_hdac_stream_setup()
297 azx_dev->delay_negative_threshold = 0; in snd_hdac_stream_setup()
301 azx_dev->period_wallclk = (((runtime->period_size * 24000) / in snd_hdac_stream_setup()
302 runtime->rate) * 1000); in snd_hdac_stream_setup()
309 * snd_hdac_stream_cleanup - cleanup a stream
310 * @azx_dev: HD-audio core stream to clean up
317 azx_dev->bufsize = 0; in snd_hdac_stream_cleanup()
318 azx_dev->period_bytes = 0; in snd_hdac_stream_cleanup()
319 azx_dev->format_val = 0; in snd_hdac_stream_cleanup()
324 * snd_hdac_stream_assign - assign a stream for the PCM
325 * @bus: HD-audio core bus
331 * beforehand. Also, when bus->reverse_assign flag is set, the last free
340 /* make a non-zero unique key for the substream */ in snd_hdac_stream_assign()
341 int key = (substream->pcm->device << 16) | (substream->number << 2) | in snd_hdac_stream_assign()
342 (substream->stream + 1); in snd_hdac_stream_assign()
344 spin_lock_irq(&bus->reg_lock); in snd_hdac_stream_assign()
345 list_for_each_entry(azx_dev, &bus->stream_list, list) { in snd_hdac_stream_assign()
346 if (azx_dev->direction != substream->stream) in snd_hdac_stream_assign()
348 if (azx_dev->opened) in snd_hdac_stream_assign()
350 if (azx_dev->assigned_key == key) { in snd_hdac_stream_assign()
354 if (!res || bus->reverse_assign) in snd_hdac_stream_assign()
358 res->opened = 1; in snd_hdac_stream_assign()
359 res->running = 0; in snd_hdac_stream_assign()
360 res->assigned_key = key; in snd_hdac_stream_assign()
361 res->substream = substream; in snd_hdac_stream_assign()
363 spin_unlock_irq(&bus->reg_lock); in snd_hdac_stream_assign()
369 * snd_hdac_stream_release_locked - release the assigned stream
370 * @azx_dev: HD-audio core stream to release
373 * The bus->reg_lock needs to be taken at a higher level
377 azx_dev->opened = 0; in snd_hdac_stream_release_locked()
378 azx_dev->running = 0; in snd_hdac_stream_release_locked()
379 azx_dev->substream = NULL; in snd_hdac_stream_release_locked()
384 * snd_hdac_stream_release - release the assigned stream
385 * @azx_dev: HD-audio core stream to release
391 struct hdac_bus *bus = azx_dev->bus; in snd_hdac_stream_release()
393 spin_lock_irq(&bus->reg_lock); in snd_hdac_stream_release()
395 spin_unlock_irq(&bus->reg_lock); in snd_hdac_stream_release()
400 * snd_hdac_get_stream - return hdac_stream based on stream_tag and
403 * @bus: HD-audio core bus
412 list_for_each_entry(s, &bus->stream_list, list) { in snd_hdac_get_stream()
413 if (s->direction == dir && s->stream_tag == stream_tag) in snd_hdac_get_stream()
422 * set up a BDL entry
435 if (azx_dev->frags >= AZX_MAX_BDL_ENTRIES) in setup_bdle()
436 return -EINVAL; in setup_bdle()
445 if (bus->align_bdle_4k) { in setup_bdle()
446 u32 remain = 0x1000 - (ofs & 0xfff); in setup_bdle()
455 size -= chunk; in setup_bdle()
458 azx_dev->frags++; in setup_bdle()
466 * snd_hdac_stream_setup_periods - set up BDL entries
467 * @azx_dev: HD-audio core stream to set up
469 * Set up the buffer descriptor table of the given stream based on the
474 struct hdac_bus *bus = azx_dev->bus; in snd_hdac_stream_setup_periods()
475 struct snd_pcm_substream *substream = azx_dev->substream; in snd_hdac_stream_setup_periods()
476 struct snd_pcm_runtime *runtime = substream->runtime; in snd_hdac_stream_setup_periods()
485 period_bytes = azx_dev->period_bytes; in snd_hdac_stream_setup_periods()
486 periods = azx_dev->bufsize / period_bytes; in snd_hdac_stream_setup_periods()
489 bdl = (__le32 *)azx_dev->bdl.area; in snd_hdac_stream_setup_periods()
491 azx_dev->frags = 0; in snd_hdac_stream_setup_periods()
493 pos_adj = bus->bdl_pos_adj; in snd_hdac_stream_setup_periods()
494 if (!azx_dev->no_period_wakeup && pos_adj > 0) { in snd_hdac_stream_setup_periods()
496 pos_adj = DIV_ROUND_UP(pos_adj * runtime->rate, 48000); in snd_hdac_stream_setup_periods()
503 dev_warn(bus->dev, "Too big adjustment %d\n", in snd_hdac_stream_setup_periods()
517 if (i == periods - 1 && pos_adj) in snd_hdac_stream_setup_periods()
520 period_bytes - pos_adj, 0); in snd_hdac_stream_setup_periods()
525 !azx_dev->no_period_wakeup); in snd_hdac_stream_setup_periods()
532 dev_err(bus->dev, "Too many BDL entries: buffer=%d, period=%d\n", in snd_hdac_stream_setup_periods()
533 azx_dev->bufsize, period_bytes); in snd_hdac_stream_setup_periods()
534 return -EINVAL; in snd_hdac_stream_setup_periods()
539 * snd_hdac_stream_set_params - set stream parameters
540 * @azx_dev: HD-audio core stream for which parameters are to be set
543 * Setup the HD-audio core stream parameters from substream of the stream
551 struct snd_pcm_substream *substream = azx_dev->substream; in snd_hdac_stream_set_params()
556 return -EINVAL; in snd_hdac_stream_set_params()
557 runtime = substream->runtime; in snd_hdac_stream_set_params()
561 if (bufsize != azx_dev->bufsize || in snd_hdac_stream_set_params()
562 period_bytes != azx_dev->period_bytes || in snd_hdac_stream_set_params()
563 format_val != azx_dev->format_val || in snd_hdac_stream_set_params()
564 runtime->no_period_wakeup != azx_dev->no_period_wakeup) { in snd_hdac_stream_set_params()
565 azx_dev->bufsize = bufsize; in snd_hdac_stream_set_params()
566 azx_dev->period_bytes = period_bytes; in snd_hdac_stream_set_params()
567 azx_dev->format_val = format_val; in snd_hdac_stream_set_params()
568 azx_dev->no_period_wakeup = runtime->no_period_wakeup; in snd_hdac_stream_set_params()
581 return snd_hdac_chip_readl(azx_dev->bus, WALLCLK); in azx_cc_read()
587 struct timecounter *tc = &azx_dev->tc; in azx_timecounter_init()
588 struct cyclecounter *cc = &azx_dev->cc; in azx_timecounter_init()
591 cc->read = azx_cc_read; in azx_timecounter_init()
592 cc->mask = CLOCKSOURCE_MASK(32); in azx_timecounter_init()
598 clocks_calc_mult_shift(&cc->mult, &cc->shift, 24000000, in azx_timecounter_init()
608 tc->cycle_last = last; in azx_timecounter_init()
613 * snd_hdac_stream_timecounter_init - initialize time counter
614 * @azx_dev: HD-audio core stream (master stream)
615 * @streams: bit flags of streams to set up
625 struct hdac_bus *bus = azx_dev->bus; in snd_hdac_stream_timecounter_init()
626 struct snd_pcm_runtime *runtime = azx_dev->substream->runtime; in snd_hdac_stream_timecounter_init()
632 list_for_each_entry(s, &bus->stream_list, list) { in snd_hdac_stream_timecounter_init()
637 cycle_last = s->tc.cycle_last; in snd_hdac_stream_timecounter_init()
643 snd_pcm_gettime(runtime, &runtime->trigger_tstamp); in snd_hdac_stream_timecounter_init()
644 runtime->trigger_tstamp_latched = true; in snd_hdac_stream_timecounter_init()
649 * snd_hdac_stream_sync_trigger - turn on/off stream sync register
650 * @azx_dev: HD-audio core stream (master stream)
658 struct hdac_bus *bus = azx_dev->bus; in snd_hdac_stream_sync_trigger()
673 * snd_hdac_stream_sync - sync with start/stop trigger operation
674 * @azx_dev: HD-audio core stream (master stream)
675 * @start: true = start, false = stop
678 * For @start = true, wait until all FIFOs get ready.
679 * For @start = false, wait until all RUN bits are cleared.
681 void snd_hdac_stream_sync(struct hdac_stream *azx_dev, bool start, in snd_hdac_stream_sync() argument
684 struct hdac_bus *bus = azx_dev->bus; in snd_hdac_stream_sync()
688 for (timeout = 5000; timeout; timeout--) { in snd_hdac_stream_sync()
691 list_for_each_entry(s, &bus->stream_list, list) { in snd_hdac_stream_sync()
695 if (start) { in snd_hdac_stream_sync()
723 * snd_hdac_dsp_prepare - prepare for DSP loading
724 * @azx_dev: HD-audio core stream used for DSP loading
725 * @format: HD-audio stream format
729 * Allocate the buffer for the given size and set up the given stream for
735 struct hdac_bus *bus = azx_dev->bus; in snd_hdac_dsp_prepare()
740 spin_lock_irq(&bus->reg_lock); in snd_hdac_dsp_prepare()
741 if (azx_dev->running || azx_dev->locked) { in snd_hdac_dsp_prepare()
742 spin_unlock_irq(&bus->reg_lock); in snd_hdac_dsp_prepare()
743 err = -EBUSY; in snd_hdac_dsp_prepare()
746 azx_dev->locked = true; in snd_hdac_dsp_prepare()
747 spin_unlock_irq(&bus->reg_lock); in snd_hdac_dsp_prepare()
749 err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, bus->dev, in snd_hdac_dsp_prepare()
754 azx_dev->substream = NULL; in snd_hdac_dsp_prepare()
755 azx_dev->bufsize = byte_size; in snd_hdac_dsp_prepare()
756 azx_dev->period_bytes = byte_size; in snd_hdac_dsp_prepare()
757 azx_dev->format_val = format; in snd_hdac_dsp_prepare()
765 azx_dev->frags = 0; in snd_hdac_dsp_prepare()
766 bdl = (__le32 *)azx_dev->bdl.area; in snd_hdac_dsp_prepare()
773 return azx_dev->stream_tag; in snd_hdac_dsp_prepare()
778 spin_lock_irq(&bus->reg_lock); in snd_hdac_dsp_prepare()
779 azx_dev->locked = false; in snd_hdac_dsp_prepare()
780 spin_unlock_irq(&bus->reg_lock); in snd_hdac_dsp_prepare()
788 * snd_hdac_dsp_trigger - start / stop DSP loading
789 * @azx_dev: HD-audio core stream used for DSP loading
790 * @start: trigger start or stop
792 void snd_hdac_dsp_trigger(struct hdac_stream *azx_dev, bool start) in snd_hdac_dsp_trigger() argument
794 if (start) in snd_hdac_dsp_trigger()
802 * snd_hdac_dsp_cleanup - clean up the stream from DSP loading to normal
803 * @azx_dev: HD-audio core stream used for DSP loading
809 struct hdac_bus *bus = azx_dev->bus; in snd_hdac_dsp_cleanup()
811 if (!dmab->area || !azx_dev->locked) in snd_hdac_dsp_cleanup()
819 azx_dev->bufsize = 0; in snd_hdac_dsp_cleanup()
820 azx_dev->period_bytes = 0; in snd_hdac_dsp_cleanup()
821 azx_dev->format_val = 0; in snd_hdac_dsp_cleanup()
824 dmab->area = NULL; in snd_hdac_dsp_cleanup()
826 spin_lock_irq(&bus->reg_lock); in snd_hdac_dsp_cleanup()
827 azx_dev->locked = false; in snd_hdac_dsp_cleanup()
828 spin_unlock_irq(&bus->reg_lock); in snd_hdac_dsp_cleanup()