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

1 // SPDX-License-Identifier: GPL-2.0-only
3 * HD-audio stream operations
17 * snd_hdac_get_stream_stripe_ctl - get stripe control value
18 * @bus: HD-audio core bus
24 struct snd_pcm_runtime *runtime = substream->runtime; in snd_hdac_get_stream_stripe_ctl()
25 unsigned int channels = runtime->channels, in snd_hdac_get_stream_stripe_ctl()
26 rate = runtime->rate, in snd_hdac_get_stream_stripe_ctl()
27 bits_per_sample = runtime->sample_bits, in snd_hdac_get_stream_stripe_ctl()
41 if (value >= bus->sdo_limit) in snd_hdac_get_stream_stripe_ctl()
51 * snd_hdac_stream_init - initialize each stream (aka device)
52 * @bus: HD-audio core bus
53 * @azx_dev: HD-audio core stream object to initialize
63 azx_dev->bus = bus; in snd_hdac_stream_init()
65 azx_dev->sd_addr = bus->remap_addr + (0x20 * idx + 0x80); in snd_hdac_stream_init()
67 azx_dev->sd_int_sta_mask = 1 << idx; in snd_hdac_stream_init()
68 azx_dev->index = idx; in snd_hdac_stream_init()
69 azx_dev->direction = direction; in snd_hdac_stream_init()
70 azx_dev->stream_tag = tag; in snd_hdac_stream_init()
72 list_add_tail(&azx_dev->list, &bus->stream_list); in snd_hdac_stream_init()
77 * snd_hdac_stream_start - start a stream
78 * @azx_dev: HD-audio core stream to start
81 * Start a stream, set start_wallclk and set the running flag.
85 struct hdac_bus *bus = azx_dev->bus; in snd_hdac_stream_start()
90 azx_dev->start_wallclk = snd_hdac_chip_readl(bus, WALLCLK); in snd_hdac_stream_start()
92 azx_dev->start_wallclk -= azx_dev->period_wallclk; in snd_hdac_stream_start()
96 1 << azx_dev->index, in snd_hdac_stream_start()
97 1 << azx_dev->index); in snd_hdac_stream_start()
99 if (azx_dev->stripe) { in snd_hdac_stream_start()
100 if (azx_dev->substream) in snd_hdac_stream_start()
101 stripe_ctl = snd_hdac_get_stream_stripe_ctl(bus, azx_dev->substream); in snd_hdac_stream_start()
107 /* set DMA start and interrupt mask */ in snd_hdac_stream_start()
110 azx_dev->running = true; in snd_hdac_stream_start()
115 * snd_hdac_stream_clear - stop a stream DMA
116 * @azx_dev: HD-audio core stream to stop
123 if (azx_dev->stripe) in snd_hdac_stream_clear()
125 azx_dev->running = false; in snd_hdac_stream_clear()
130 * snd_hdac_stream_stop - stop a stream
131 * @azx_dev: HD-audio core stream to stop
137 trace_snd_hdac_stream_stop(azx_dev->bus, azx_dev); in snd_hdac_stream_stop()
141 snd_hdac_chip_updatel(azx_dev->bus, INTCTL, 1 << azx_dev->index, 0); in snd_hdac_stream_stop()
146 * snd_hdac_stream_reset - reset a stream
147 * @azx_dev: HD-audio core stream to reset
167 } while (--timeout); in snd_hdac_stream_reset()
169 if (azx_dev->bus->dma_stop_delay && dma_run_state) in snd_hdac_stream_reset()
170 udelay(azx_dev->bus->dma_stop_delay); in snd_hdac_stream_reset()
183 } while (--timeout); in snd_hdac_stream_reset()
185 /* reset first position - may not be synced with hw at this time */ in snd_hdac_stream_reset()
186 if (azx_dev->posbuf) in snd_hdac_stream_reset()
187 *azx_dev->posbuf = 0; in snd_hdac_stream_reset()
192 * snd_hdac_stream_setup - set up the SD for streaming
193 * @azx_dev: HD-audio core stream to set up
197 struct hdac_bus *bus = azx_dev->bus; in snd_hdac_stream_setup()
201 if (azx_dev->substream) in snd_hdac_stream_setup()
202 runtime = azx_dev->substream->runtime; in snd_hdac_stream_setup()
210 (azx_dev->stream_tag << SD_CTL_STREAM_TAG_SHIFT); in snd_hdac_stream_setup()
211 if (!bus->snoop) in snd_hdac_stream_setup()
216 snd_hdac_stream_writel(azx_dev, SD_CBL, azx_dev->bufsize); in snd_hdac_stream_setup()
220 snd_hdac_stream_writew(azx_dev, SD_FORMAT, azx_dev->format_val); in snd_hdac_stream_setup()
223 snd_hdac_stream_writew(azx_dev, SD_LVI, azx_dev->frags - 1); in snd_hdac_stream_setup()
227 snd_hdac_stream_writel(azx_dev, SD_BDLPL, (u32)azx_dev->bdl.addr); in snd_hdac_stream_setup()
230 upper_32_bits(azx_dev->bdl.addr)); in snd_hdac_stream_setup()
233 if (bus->use_posbuf && bus->posbuf.addr) { in snd_hdac_stream_setup()
236 (u32)bus->posbuf.addr | AZX_DPLBASE_ENABLE); in snd_hdac_stream_setup()
242 azx_dev->fifo_size = snd_hdac_stream_readw(azx_dev, SD_FIFOSIZE) + 1; in snd_hdac_stream_setup()
248 if (runtime && runtime->period_size > 64) in snd_hdac_stream_setup()
249 azx_dev->delay_negative_threshold = in snd_hdac_stream_setup()
250 -frames_to_bytes(runtime, 64); in snd_hdac_stream_setup()
252 azx_dev->delay_negative_threshold = 0; in snd_hdac_stream_setup()
256 azx_dev->period_wallclk = (((runtime->period_size * 24000) / in snd_hdac_stream_setup()
257 runtime->rate) * 1000); in snd_hdac_stream_setup()
264 * snd_hdac_stream_cleanup - cleanup a stream
265 * @azx_dev: HD-audio core stream to clean up
272 azx_dev->bufsize = 0; in snd_hdac_stream_cleanup()
273 azx_dev->period_bytes = 0; in snd_hdac_stream_cleanup()
274 azx_dev->format_val = 0; in snd_hdac_stream_cleanup()
279 * snd_hdac_stream_assign - assign a stream for the PCM
280 * @bus: HD-audio core bus
286 * beforehand. Also, when bus->reverse_assign flag is set, the last free
295 /* make a non-zero unique key for the substream */ in snd_hdac_stream_assign()
296 int key = (substream->pcm->device << 16) | (substream->number << 2) | in snd_hdac_stream_assign()
297 (substream->stream + 1); in snd_hdac_stream_assign()
299 list_for_each_entry(azx_dev, &bus->stream_list, list) { in snd_hdac_stream_assign()
300 if (azx_dev->direction != substream->stream) in snd_hdac_stream_assign()
302 if (azx_dev->opened) in snd_hdac_stream_assign()
304 if (azx_dev->assigned_key == key) { in snd_hdac_stream_assign()
308 if (!res || bus->reverse_assign) in snd_hdac_stream_assign()
312 spin_lock_irq(&bus->reg_lock); in snd_hdac_stream_assign()
313 res->opened = 1; in snd_hdac_stream_assign()
314 res->running = 0; in snd_hdac_stream_assign()
315 res->assigned_key = key; in snd_hdac_stream_assign()
316 res->substream = substream; in snd_hdac_stream_assign()
317 spin_unlock_irq(&bus->reg_lock); in snd_hdac_stream_assign()
324 * snd_hdac_stream_release - release the assigned stream
325 * @azx_dev: HD-audio core stream to release
331 struct hdac_bus *bus = azx_dev->bus; in snd_hdac_stream_release()
333 spin_lock_irq(&bus->reg_lock); in snd_hdac_stream_release()
334 azx_dev->opened = 0; in snd_hdac_stream_release()
335 azx_dev->running = 0; in snd_hdac_stream_release()
336 azx_dev->substream = NULL; in snd_hdac_stream_release()
337 spin_unlock_irq(&bus->reg_lock); in snd_hdac_stream_release()
342 * snd_hdac_get_stream - return hdac_stream based on stream_tag and
345 * @bus: HD-audio core bus
354 list_for_each_entry(s, &bus->stream_list, list) { in snd_hdac_get_stream()
355 if (s->direction == dir && s->stream_tag == stream_tag) in snd_hdac_get_stream()
364 * set up a BDL entry
377 if (azx_dev->frags >= AZX_MAX_BDL_ENTRIES) in setup_bdle()
378 return -EINVAL; in setup_bdle()
387 if (bus->align_bdle_4k) { in setup_bdle()
388 u32 remain = 0x1000 - (ofs & 0xfff); in setup_bdle()
397 size -= chunk; in setup_bdle()
400 azx_dev->frags++; in setup_bdle()
408 * snd_hdac_stream_setup_periods - set up BDL entries
409 * @azx_dev: HD-audio core stream to set up
411 * Set up the buffer descriptor table of the given stream based on the
416 struct hdac_bus *bus = azx_dev->bus; in snd_hdac_stream_setup_periods()
417 struct snd_pcm_substream *substream = azx_dev->substream; in snd_hdac_stream_setup_periods()
418 struct snd_pcm_runtime *runtime = substream->runtime; in snd_hdac_stream_setup_periods()
427 period_bytes = azx_dev->period_bytes; in snd_hdac_stream_setup_periods()
428 periods = azx_dev->bufsize / period_bytes; in snd_hdac_stream_setup_periods()
431 bdl = (__le32 *)azx_dev->bdl.area; in snd_hdac_stream_setup_periods()
433 azx_dev->frags = 0; in snd_hdac_stream_setup_periods()
435 pos_adj = bus->bdl_pos_adj; in snd_hdac_stream_setup_periods()
436 if (!azx_dev->no_period_wakeup && pos_adj > 0) { in snd_hdac_stream_setup_periods()
438 pos_adj = (pos_adj * runtime->rate + 47999) / 48000; in snd_hdac_stream_setup_periods()
442 pos_adj = ((pos_adj + pos_align - 1) / pos_align) * in snd_hdac_stream_setup_periods()
446 dev_warn(bus->dev, "Too big adjustment %d\n", in snd_hdac_stream_setup_periods()
460 if (i == periods - 1 && pos_adj) in snd_hdac_stream_setup_periods()
463 period_bytes - pos_adj, 0); in snd_hdac_stream_setup_periods()
468 !azx_dev->no_period_wakeup); in snd_hdac_stream_setup_periods()
475 dev_err(bus->dev, "Too many BDL entries: buffer=%d, period=%d\n", in snd_hdac_stream_setup_periods()
476 azx_dev->bufsize, period_bytes); in snd_hdac_stream_setup_periods()
477 return -EINVAL; in snd_hdac_stream_setup_periods()
482 * snd_hdac_stream_set_params - set stream parameters
483 * @azx_dev: HD-audio core stream for which parameters are to be set
486 * Setup the HD-audio core stream parameters from substream of the stream
494 struct snd_pcm_substream *substream = azx_dev->substream; in snd_hdac_stream_set_params()
499 return -EINVAL; in snd_hdac_stream_set_params()
500 runtime = substream->runtime; in snd_hdac_stream_set_params()
504 if (bufsize != azx_dev->bufsize || in snd_hdac_stream_set_params()
505 period_bytes != azx_dev->period_bytes || in snd_hdac_stream_set_params()
506 format_val != azx_dev->format_val || in snd_hdac_stream_set_params()
507 runtime->no_period_wakeup != azx_dev->no_period_wakeup) { in snd_hdac_stream_set_params()
508 azx_dev->bufsize = bufsize; in snd_hdac_stream_set_params()
509 azx_dev->period_bytes = period_bytes; in snd_hdac_stream_set_params()
510 azx_dev->format_val = format_val; in snd_hdac_stream_set_params()
511 azx_dev->no_period_wakeup = runtime->no_period_wakeup; in snd_hdac_stream_set_params()
524 return snd_hdac_chip_readl(azx_dev->bus, WALLCLK); in azx_cc_read()
530 struct timecounter *tc = &azx_dev->tc; in azx_timecounter_init()
531 struct cyclecounter *cc = &azx_dev->cc; in azx_timecounter_init()
534 cc->read = azx_cc_read; in azx_timecounter_init()
535 cc->mask = CLOCKSOURCE_MASK(32); in azx_timecounter_init()
547 cc->mult = 125; /* saturation after 195 years */ in azx_timecounter_init()
548 cc->shift = 0; in azx_timecounter_init()
557 tc->cycle_last = last; in azx_timecounter_init()
562 * snd_hdac_stream_timecounter_init - initialize time counter
563 * @azx_dev: HD-audio core stream (master stream)
564 * @streams: bit flags of streams to set up
574 struct hdac_bus *bus = azx_dev->bus; in snd_hdac_stream_timecounter_init()
575 struct snd_pcm_runtime *runtime = azx_dev->substream->runtime; in snd_hdac_stream_timecounter_init()
581 list_for_each_entry(s, &bus->stream_list, list) { in snd_hdac_stream_timecounter_init()
586 cycle_last = s->tc.cycle_last; in snd_hdac_stream_timecounter_init()
592 snd_pcm_gettime(runtime, &runtime->trigger_tstamp); in snd_hdac_stream_timecounter_init()
593 runtime->trigger_tstamp_latched = true; in snd_hdac_stream_timecounter_init()
598 * snd_hdac_stream_sync_trigger - turn on/off stream sync register
599 * @azx_dev: HD-audio core stream (master stream)
607 struct hdac_bus *bus = azx_dev->bus; in snd_hdac_stream_sync_trigger()
622 * snd_hdac_stream_sync - sync with start/strop trigger operation
623 * @azx_dev: HD-audio core stream (master stream)
624 * @start: true = start, false = stop
627 * For @start = true, wait until all FIFOs get ready.
628 * For @start = false, wait until all RUN bits are cleared.
630 void snd_hdac_stream_sync(struct hdac_stream *azx_dev, bool start, in snd_hdac_stream_sync() argument
633 struct hdac_bus *bus = azx_dev->bus; in snd_hdac_stream_sync()
637 for (timeout = 5000; timeout; timeout--) { in snd_hdac_stream_sync()
640 list_for_each_entry(s, &bus->stream_list, list) { in snd_hdac_stream_sync()
644 if (start) { in snd_hdac_stream_sync()
672 * snd_hdac_dsp_prepare - prepare for DSP loading
673 * @azx_dev: HD-audio core stream used for DSP loading
674 * @format: HD-audio stream format
678 * Allocate the buffer for the given size and set up the given stream for
684 struct hdac_bus *bus = azx_dev->bus; in snd_hdac_dsp_prepare()
689 spin_lock_irq(&bus->reg_lock); in snd_hdac_dsp_prepare()
690 if (azx_dev->running || azx_dev->locked) { in snd_hdac_dsp_prepare()
691 spin_unlock_irq(&bus->reg_lock); in snd_hdac_dsp_prepare()
692 err = -EBUSY; in snd_hdac_dsp_prepare()
695 azx_dev->locked = true; in snd_hdac_dsp_prepare()
696 spin_unlock_irq(&bus->reg_lock); in snd_hdac_dsp_prepare()
698 err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, bus->dev, in snd_hdac_dsp_prepare()
703 azx_dev->substream = NULL; in snd_hdac_dsp_prepare()
704 azx_dev->bufsize = byte_size; in snd_hdac_dsp_prepare()
705 azx_dev->period_bytes = byte_size; in snd_hdac_dsp_prepare()
706 azx_dev->format_val = format; in snd_hdac_dsp_prepare()
714 azx_dev->frags = 0; in snd_hdac_dsp_prepare()
715 bdl = (__le32 *)azx_dev->bdl.area; in snd_hdac_dsp_prepare()
722 return azx_dev->stream_tag; in snd_hdac_dsp_prepare()
727 spin_lock_irq(&bus->reg_lock); in snd_hdac_dsp_prepare()
728 azx_dev->locked = false; in snd_hdac_dsp_prepare()
729 spin_unlock_irq(&bus->reg_lock); in snd_hdac_dsp_prepare()
737 * snd_hdac_dsp_trigger - start / stop DSP loading
738 * @azx_dev: HD-audio core stream used for DSP loading
739 * @start: trigger start or stop
741 void snd_hdac_dsp_trigger(struct hdac_stream *azx_dev, bool start) in snd_hdac_dsp_trigger() argument
743 if (start) in snd_hdac_dsp_trigger()
751 * snd_hdac_dsp_cleanup - clean up the stream from DSP loading to normal
752 * @azx_dev: HD-audio core stream used for DSP loading
758 struct hdac_bus *bus = azx_dev->bus; in snd_hdac_dsp_cleanup()
760 if (!dmab->area || !azx_dev->locked) in snd_hdac_dsp_cleanup()
768 azx_dev->bufsize = 0; in snd_hdac_dsp_cleanup()
769 azx_dev->period_bytes = 0; in snd_hdac_dsp_cleanup()
770 azx_dev->format_val = 0; in snd_hdac_dsp_cleanup()
773 dmab->area = NULL; in snd_hdac_dsp_cleanup()
775 spin_lock_irq(&bus->reg_lock); in snd_hdac_dsp_cleanup()
776 azx_dev->locked = false; in snd_hdac_dsp_cleanup()
777 spin_unlock_irq(&bus->reg_lock); in snd_hdac_dsp_cleanup()