.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * HD-audio stream operations |
---|
3 | 4 | */ |
---|
.. | .. |
---|
11 | 12 | #include <sound/hdaudio.h> |
---|
12 | 13 | #include <sound/hda_register.h> |
---|
13 | 14 | #include "trace.h" |
---|
| 15 | + |
---|
| 16 | +/** |
---|
| 17 | + * snd_hdac_get_stream_stripe_ctl - get stripe control value |
---|
| 18 | + * @bus: HD-audio core bus |
---|
| 19 | + * @substream: PCM substream |
---|
| 20 | + */ |
---|
| 21 | +int snd_hdac_get_stream_stripe_ctl(struct hdac_bus *bus, |
---|
| 22 | + struct snd_pcm_substream *substream) |
---|
| 23 | +{ |
---|
| 24 | + struct snd_pcm_runtime *runtime = substream->runtime; |
---|
| 25 | + unsigned int channels = runtime->channels, |
---|
| 26 | + rate = runtime->rate, |
---|
| 27 | + bits_per_sample = runtime->sample_bits, |
---|
| 28 | + max_sdo_lines, value, sdo_line; |
---|
| 29 | + |
---|
| 30 | + /* T_AZA_GCAP_NSDO is 1:2 bitfields in GCAP */ |
---|
| 31 | + max_sdo_lines = snd_hdac_chip_readl(bus, GCAP) & AZX_GCAP_NSDO; |
---|
| 32 | + |
---|
| 33 | + /* following is from HD audio spec */ |
---|
| 34 | + for (sdo_line = max_sdo_lines; sdo_line > 0; sdo_line >>= 1) { |
---|
| 35 | + if (rate > 48000) |
---|
| 36 | + value = (channels * bits_per_sample * |
---|
| 37 | + (rate / 48000)) / sdo_line; |
---|
| 38 | + else |
---|
| 39 | + value = (channels * bits_per_sample) / sdo_line; |
---|
| 40 | + |
---|
| 41 | + if (value >= bus->sdo_limit) |
---|
| 42 | + break; |
---|
| 43 | + } |
---|
| 44 | + |
---|
| 45 | + /* stripe value: 0 for 1SDO, 1 for 2SDO, 2 for 4SDO lines */ |
---|
| 46 | + return sdo_line >> 1; |
---|
| 47 | +} |
---|
| 48 | +EXPORT_SYMBOL_GPL(snd_hdac_get_stream_stripe_ctl); |
---|
14 | 49 | |
---|
15 | 50 | /** |
---|
16 | 51 | * snd_hdac_stream_init - initialize each stream (aka device) |
---|
.. | .. |
---|
48 | 83 | void snd_hdac_stream_start(struct hdac_stream *azx_dev, bool fresh_start) |
---|
49 | 84 | { |
---|
50 | 85 | struct hdac_bus *bus = azx_dev->bus; |
---|
| 86 | + int stripe_ctl; |
---|
51 | 87 | |
---|
52 | 88 | trace_snd_hdac_stream_start(bus, azx_dev); |
---|
53 | 89 | |
---|
.. | .. |
---|
56 | 92 | azx_dev->start_wallclk -= azx_dev->period_wallclk; |
---|
57 | 93 | |
---|
58 | 94 | /* enable SIE */ |
---|
59 | | - snd_hdac_chip_updatel(bus, INTCTL, 0, 1 << azx_dev->index); |
---|
| 95 | + snd_hdac_chip_updatel(bus, INTCTL, |
---|
| 96 | + 1 << azx_dev->index, |
---|
| 97 | + 1 << azx_dev->index); |
---|
| 98 | + /* set stripe control */ |
---|
| 99 | + if (azx_dev->stripe) { |
---|
| 100 | + if (azx_dev->substream) |
---|
| 101 | + stripe_ctl = snd_hdac_get_stream_stripe_ctl(bus, azx_dev->substream); |
---|
| 102 | + else |
---|
| 103 | + stripe_ctl = 0; |
---|
| 104 | + snd_hdac_stream_updateb(azx_dev, SD_CTL_3B, SD_CTL_STRIPE_MASK, |
---|
| 105 | + stripe_ctl); |
---|
| 106 | + } |
---|
60 | 107 | /* set DMA start and interrupt mask */ |
---|
61 | 108 | snd_hdac_stream_updateb(azx_dev, SD_CTL, |
---|
62 | 109 | 0, SD_CTL_DMA_START | SD_INT_MASK); |
---|
.. | .. |
---|
73 | 120 | snd_hdac_stream_updateb(azx_dev, SD_CTL, |
---|
74 | 121 | SD_CTL_DMA_START | SD_INT_MASK, 0); |
---|
75 | 122 | snd_hdac_stream_writeb(azx_dev, SD_STS, SD_INT_MASK); /* to be sure */ |
---|
| 123 | + if (azx_dev->stripe) |
---|
| 124 | + snd_hdac_stream_updateb(azx_dev, SD_CTL_3B, SD_CTL_STRIPE_MASK, 0); |
---|
76 | 125 | azx_dev->running = false; |
---|
77 | 126 | } |
---|
78 | 127 | EXPORT_SYMBOL_GPL(snd_hdac_stream_clear); |
---|
.. | .. |
---|
101 | 150 | { |
---|
102 | 151 | unsigned char val; |
---|
103 | 152 | int timeout; |
---|
| 153 | + int dma_run_state; |
---|
104 | 154 | |
---|
105 | 155 | snd_hdac_stream_clear(azx_dev); |
---|
| 156 | + |
---|
| 157 | + dma_run_state = snd_hdac_stream_readb(azx_dev, SD_CTL) & SD_CTL_DMA_START; |
---|
106 | 158 | |
---|
107 | 159 | snd_hdac_stream_updateb(azx_dev, SD_CTL, 0, SD_CTL_STREAM_RESET); |
---|
108 | 160 | udelay(3); |
---|
.. | .. |
---|
113 | 165 | if (val) |
---|
114 | 166 | break; |
---|
115 | 167 | } while (--timeout); |
---|
| 168 | + |
---|
| 169 | + if (azx_dev->bus->dma_stop_delay && dma_run_state) |
---|
| 170 | + udelay(azx_dev->bus->dma_stop_delay); |
---|
| 171 | + |
---|
116 | 172 | val &= ~SD_CTL_STREAM_RESET; |
---|
117 | 173 | snd_hdac_stream_writeb(azx_dev, SD_CTL, val); |
---|
118 | 174 | udelay(3); |
---|
.. | .. |
---|
183 | 239 | /* set the interrupt enable bits in the descriptor control register */ |
---|
184 | 240 | snd_hdac_stream_updatel(azx_dev, SD_CTL, 0, SD_INT_MASK); |
---|
185 | 241 | |
---|
186 | | - if (azx_dev->direction == SNDRV_PCM_STREAM_PLAYBACK) |
---|
187 | | - azx_dev->fifo_size = |
---|
188 | | - snd_hdac_stream_readw(azx_dev, SD_FIFOSIZE) + 1; |
---|
189 | | - else |
---|
190 | | - azx_dev->fifo_size = 0; |
---|
| 242 | + azx_dev->fifo_size = snd_hdac_stream_readw(azx_dev, SD_FIFOSIZE) + 1; |
---|
191 | 243 | |
---|
192 | 244 | /* when LPIB delay correction gives a small negative value, |
---|
193 | 245 | * we ignore it; currently set the threshold statically to |
---|
.. | .. |
---|
244 | 296 | int key = (substream->pcm->device << 16) | (substream->number << 2) | |
---|
245 | 297 | (substream->stream + 1); |
---|
246 | 298 | |
---|
| 299 | + spin_lock_irq(&bus->reg_lock); |
---|
247 | 300 | list_for_each_entry(azx_dev, &bus->stream_list, list) { |
---|
248 | 301 | if (azx_dev->direction != substream->stream) |
---|
249 | 302 | continue; |
---|
.. | .. |
---|
257 | 310 | res = azx_dev; |
---|
258 | 311 | } |
---|
259 | 312 | if (res) { |
---|
260 | | - spin_lock_irq(&bus->reg_lock); |
---|
261 | 313 | res->opened = 1; |
---|
262 | 314 | res->running = 0; |
---|
263 | 315 | res->assigned_key = key; |
---|
264 | 316 | res->substream = substream; |
---|
265 | | - spin_unlock_irq(&bus->reg_lock); |
---|
266 | 317 | } |
---|
| 318 | + spin_unlock_irq(&bus->reg_lock); |
---|
267 | 319 | return res; |
---|
268 | 320 | } |
---|
269 | 321 | EXPORT_SYMBOL_GPL(snd_hdac_stream_assign); |
---|
.. | .. |
---|
545 | 597 | /** |
---|
546 | 598 | * snd_hdac_stream_sync_trigger - turn on/off stream sync register |
---|
547 | 599 | * @azx_dev: HD-audio core stream (master stream) |
---|
| 600 | + * @set: true = set, false = clear |
---|
548 | 601 | * @streams: bit flags of streams to sync |
---|
| 602 | + * @reg: the stream sync register address |
---|
549 | 603 | */ |
---|
550 | 604 | void snd_hdac_stream_sync_trigger(struct hdac_stream *azx_dev, bool set, |
---|
551 | 605 | unsigned int streams, unsigned int reg) |
---|
.. | .. |
---|
584 | 638 | nwait = 0; |
---|
585 | 639 | i = 0; |
---|
586 | 640 | list_for_each_entry(s, &bus->stream_list, list) { |
---|
587 | | - if (streams & (1 << i)) { |
---|
588 | | - if (start) { |
---|
589 | | - /* check FIFO gets ready */ |
---|
590 | | - if (!(snd_hdac_stream_readb(s, SD_STS) & |
---|
591 | | - SD_STS_FIFO_READY)) |
---|
592 | | - nwait++; |
---|
593 | | - } else { |
---|
594 | | - /* check RUN bit is cleared */ |
---|
595 | | - if (snd_hdac_stream_readb(s, SD_CTL) & |
---|
596 | | - SD_CTL_DMA_START) |
---|
597 | | - nwait++; |
---|
| 641 | + if (!(streams & (1 << i++))) |
---|
| 642 | + continue; |
---|
| 643 | + |
---|
| 644 | + if (start) { |
---|
| 645 | + /* check FIFO gets ready */ |
---|
| 646 | + if (!(snd_hdac_stream_readb(s, SD_STS) & |
---|
| 647 | + SD_STS_FIFO_READY)) |
---|
| 648 | + nwait++; |
---|
| 649 | + } else { |
---|
| 650 | + /* check RUN bit is cleared */ |
---|
| 651 | + if (snd_hdac_stream_readb(s, SD_CTL) & |
---|
| 652 | + SD_CTL_DMA_START) { |
---|
| 653 | + nwait++; |
---|
| 654 | + /* |
---|
| 655 | + * Perform stream reset if DMA RUN |
---|
| 656 | + * bit not cleared within given timeout |
---|
| 657 | + */ |
---|
| 658 | + if (timeout == 1) |
---|
| 659 | + snd_hdac_stream_reset(s); |
---|
598 | 660 | } |
---|
599 | 661 | } |
---|
600 | | - i++; |
---|
601 | 662 | } |
---|
602 | 663 | if (!nwait) |
---|
603 | 664 | break; |
---|
.. | .. |
---|
634 | 695 | azx_dev->locked = true; |
---|
635 | 696 | spin_unlock_irq(&bus->reg_lock); |
---|
636 | 697 | |
---|
637 | | - err = bus->io_ops->dma_alloc_pages(bus, SNDRV_DMA_TYPE_DEV_SG, |
---|
638 | | - byte_size, bufp); |
---|
| 698 | + err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, bus->dev, |
---|
| 699 | + byte_size, bufp); |
---|
639 | 700 | if (err < 0) |
---|
640 | 701 | goto err_alloc; |
---|
641 | 702 | |
---|
.. | .. |
---|
661 | 722 | return azx_dev->stream_tag; |
---|
662 | 723 | |
---|
663 | 724 | error: |
---|
664 | | - bus->io_ops->dma_free_pages(bus, bufp); |
---|
| 725 | + snd_dma_free_pages(bufp); |
---|
665 | 726 | err_alloc: |
---|
666 | 727 | spin_lock_irq(&bus->reg_lock); |
---|
667 | 728 | azx_dev->locked = false; |
---|
.. | .. |
---|
708 | 769 | azx_dev->period_bytes = 0; |
---|
709 | 770 | azx_dev->format_val = 0; |
---|
710 | 771 | |
---|
711 | | - bus->io_ops->dma_free_pages(bus, dmab); |
---|
| 772 | + snd_dma_free_pages(dmab); |
---|
712 | 773 | dmab->area = NULL; |
---|
713 | 774 | |
---|
714 | 775 | spin_lock_irq(&bus->reg_lock); |
---|