Ignore:
Timestamp:
Apr 19, 2025, 8:08:37 PM (4 months ago)
Author:
David Azarewicz
Message:

Merge in changes from 6.6-LTS branch.
Fixed additional 25+ problems.

Location:
GPL/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • GPL/trunk

  • GPL/trunk/alsa-kernel/hda/hdac_stream.c

    r717 r772  
    88#include <linux/export.h>
    99#include <linux/clocksource.h>
     10#include <sound/compress_driver.h>
    1011#include <sound/core.h>
    1112#include <sound/pcm.h>
     
    1920#endif
    2021
     22/*
     23 * the hdac_stream library is intended to be used with the following
     24 * transitions. The states are not formally defined in the code but loosely
     25 * inspired by boolean variables. Note that the 'prepared' field is not used
     26 * in this library but by the callers during the hw_params/prepare transitions
     27 *
     28 *                         |
     29 *      stream_init()      |
     30 *                         v
     31 *                      +--+-------+
     32 *                      |  unused  |
     33 *                      +--+----+--+
     34 *                         |    ^
     35 *      stream_assign()    |    |    stream_release()
     36 *                         v    |
     37 *                      +--+----+--+
     38 *                      |  opened  |
     39 *                      +--+----+--+
     40 *                         |    ^
     41 *      stream_reset()     |    |
     42 *      stream_setup()     |    |    stream_cleanup()
     43 *                         v    |
     44 *                      +--+----+--+
     45 *                      | prepared |
     46 *                      +--+----+--+
     47 *                         |    ^
     48 *      stream_start()     |    |    stream_stop()
     49 *                         v    |
     50 *                      +--+----+--+
     51 *                      |  running |
     52 *                      +----------+
     53 */
     54
    2155/**
    2256 * snd_hdac_get_stream_stripe_ctl - get stripe control value
     
    76110        snd_hdac_dsp_lock_init(azx_dev);
    77111        list_add_tail(&azx_dev->list, &bus->stream_list);
     112
     113        if (bus->spbcap) {
     114                azx_dev->spib_addr = (void*)bus->spbcap + AZX_SPB_BASE +
     115                                        AZX_SPB_INTERVAL * idx +
     116                                        AZX_SPB_SPIB;
     117
     118                azx_dev->fifo_addr = (void*)bus->spbcap + AZX_SPB_BASE +
     119                                        AZX_SPB_INTERVAL * idx +
     120                                        AZX_SPB_MAXFIFO;
     121        }
     122
     123        if (bus->drsmcap)
     124                azx_dev->dpibr_addr = (void*)bus->drsmcap + AZX_DRSM_BASE +
     125                                        AZX_DRSM_INTERVAL * idx;
    78126}
    79127EXPORT_SYMBOL_GPL(snd_hdac_stream_init);
     
    82130 * snd_hdac_stream_start - start a stream
    83131 * @azx_dev: HD-audio core stream to start
    84  * @fresh_start: false = wallclock timestamp relative to period wallclock
    85132 *
    86133 * Start a stream, set start_wallclk and set the running flag.
    87134 */
    88 void snd_hdac_stream_start(struct hdac_stream *azx_dev, bool fresh_start)
     135void snd_hdac_stream_start(struct hdac_stream *azx_dev)
    89136{
    90137        struct hdac_bus *bus = azx_dev->bus;
     
    94141
    95142        azx_dev->start_wallclk = snd_hdac_chip_readl(bus, WALLCLK);
    96         if (!fresh_start)
    97                 azx_dev->start_wallclk -= azx_dev->period_wallclk;
    98143
    99144        /* enable SIE */
     
    111156        }
    112157        /* set DMA start and interrupt mask */
    113         snd_hdac_stream_updateb(azx_dev, SD_CTL,
     158        if (bus->access_sdnctl_in_dword)
     159                snd_hdac_stream_updatel(azx_dev, SD_CTL,
     160                                0, SD_CTL_DMA_START | SD_INT_MASK);
     161        else
     162                snd_hdac_stream_updateb(azx_dev, SD_CTL,
    114163                                0, SD_CTL_DMA_START | SD_INT_MASK);
    115164        azx_dev->running = true;
     
    118167
    119168/**
    120  * snd_hdac_stream_clear - stop a stream DMA
     169 * snd_hdac_stream_clear - helper to clear stream registers and stop DMA transfers
    121170 * @azx_dev: HD-audio core stream to stop
    122171 */
    123 void snd_hdac_stream_clear(struct hdac_stream *azx_dev)
     172static void snd_hdac_stream_clear(struct hdac_stream *azx_dev)
    124173{
    125174        snd_hdac_stream_updateb(azx_dev, SD_CTL,
     
    130179        azx_dev->running = false;
    131180}
    132 EXPORT_SYMBOL_GPL(snd_hdac_stream_clear);
    133181
    134182/**
     
    149197
    150198/**
     199 * snd_hdac_stop_streams - stop all streams
     200 * @bus: HD-audio core bus
     201 */
     202void snd_hdac_stop_streams(struct hdac_bus *bus)
     203{
     204        struct hdac_stream *stream;
     205
     206        list_for_each_entry(stream, &bus->stream_list, list, struct hdac_stream)
     207                snd_hdac_stream_stop(stream);
     208}
     209EXPORT_SYMBOL_GPL(snd_hdac_stop_streams);
     210
     211/**
     212 * snd_hdac_stop_streams_and_chip - stop all streams and chip if running
     213 * @bus: HD-audio core bus
     214 */
     215void snd_hdac_stop_streams_and_chip(struct hdac_bus *bus)
     216{
     217        if (bus->chip_init) {
     218                snd_hdac_stop_streams(bus);
     219                snd_hdac_bus_stop_chip(bus);
     220        }
     221}
     222EXPORT_SYMBOL_GPL(snd_hdac_stop_streams_and_chip);
     223
     224/**
    151225 * snd_hdac_stream_reset - reset a stream
    152226 * @azx_dev: HD-audio core stream to reset
     
    155229{
    156230        unsigned char val;
     231#ifdef TARGET_OS2
    157232        int timeout;
     233#endif
    158234        int dma_run_state;
    159235
     
    163239
    164240        snd_hdac_stream_updateb(azx_dev, SD_CTL, 0, SD_CTL_STREAM_RESET);
     241
     242#ifndef TARGET_OS2
     243        /* wait for hardware to report that the stream entered reset */
     244        snd_hdac_stream_readb_poll(azx_dev, SD_CTL, val, (val & SD_CTL_STREAM_RESET), 3, 300);
     245#else
    165246        udelay(3);
    166247        timeout = 300;
     
    171252                        break;
    172253        } while (--timeout);
    173 
     254#endif
    174255        if (azx_dev->bus->dma_stop_delay && dma_run_state)
    175256                udelay(azx_dev->bus->dma_stop_delay);
    176257
    177         val &= ~SD_CTL_STREAM_RESET;
    178         snd_hdac_stream_writeb(azx_dev, SD_CTL, val);
     258        snd_hdac_stream_updateb(azx_dev, SD_CTL, SD_CTL_STREAM_RESET, 0);
     259
     260#ifndef TARGET_OS2
     261        /* wait for hardware to report that the stream is out of reset */
     262        snd_hdac_stream_readb_poll(azx_dev, SD_CTL, val, !(val & SD_CTL_STREAM_RESET), 3, 300);
     263#else
    179264        udelay(3);
    180265
     
    187272                        break;
    188273        } while (--timeout);
    189 
     274#endif
    190275        /* reset first position - may not be synced with hw at this time */
    191276        if (azx_dev->posbuf)
     
    299384
    300385        /* make a non-zero unique key for the substream */
    301         int key = (substream->pcm->device << 16) | (substream->number << 2) |
    302                 (substream->stream + 1);
     386        int key = (substream->number << 2) | (substream->stream + 1);
     387
     388        if (substream->pcm)
     389                key |= (substream->pcm->device << 16);
    303390
    304391        spin_lock_irq(&bus->reg_lock);
     
    327414
    328415/**
    329  * snd_hdac_stream_release - release the assigned stream
     416 * snd_hdac_stream_release_locked - release the assigned stream
    330417 * @azx_dev: HD-audio core stream to release
    331418 *
    332419 * Release the stream that has been assigned by snd_hdac_stream_assign().
    333  */
    334 void snd_hdac_stream_release(struct hdac_stream *azx_dev)
    335 {
    336         struct hdac_bus *bus = azx_dev->bus;
    337 
    338         spin_lock_irq(&bus->reg_lock);
     420 * The bus->reg_lock needs to be taken at a higher level
     421 */
     422void snd_hdac_stream_release_locked(struct hdac_stream *azx_dev)
     423{
    339424        azx_dev->opened = 0;
    340425        azx_dev->running = 0;
    341426        azx_dev->substream = NULL;
     427}
     428EXPORT_SYMBOL_GPL(snd_hdac_stream_release_locked);
     429
     430/**
     431 * snd_hdac_stream_release - release the assigned stream
     432 * @azx_dev: HD-audio core stream to release
     433 *
     434 * Release the stream that has been assigned by snd_hdac_stream_assign().
     435 */
     436void snd_hdac_stream_release(struct hdac_stream *azx_dev)
     437{
     438        struct hdac_bus *bus = azx_dev->bus;
     439
     440        spin_lock_irq(&bus->reg_lock);
     441        snd_hdac_stream_release_locked(azx_dev);
    342442        spin_unlock_irq(&bus->reg_lock);
    343443}
     
    421521        struct hdac_bus *bus = azx_dev->bus;
    422522        struct snd_pcm_substream *substream = azx_dev->substream;
    423         struct snd_pcm_runtime *runtime = substream->runtime;
     523        struct snd_compr_stream *cstream = azx_dev->cstream;
     524        struct snd_pcm_runtime *runtime = NULL;
     525        struct snd_dma_buffer *dmab;
    424526        __le32 *bdl;
    425527        int i, ofs, periods, period_bytes;
    426528        int pos_adj, pos_align;
     529
     530        if (substream) {
     531                runtime = substream->runtime;
     532                dmab = snd_pcm_get_dma_buf(substream);
     533        } else if (cstream) {
     534                dmab = snd_pcm_get_dma_buf(cstream);
     535        } else {
     536                WARN(1, "No substream or cstream assigned\n");
     537                return -EINVAL;
     538        }
    427539
    428540        /* reset BDL address */
     
    439551
    440552        pos_adj = bus->bdl_pos_adj;
    441         if (!azx_dev->no_period_wakeup && pos_adj > 0) {
     553        if (runtime && !azx_dev->no_period_wakeup && pos_adj > 0) {
    442554                pos_align = pos_adj;
    443555                pos_adj = DIV_ROUND_UP(pos_adj * runtime->rate, 48000);
     
    452564                        pos_adj = 0;
    453565                } else {
    454                         ofs = setup_bdle(bus, snd_pcm_get_dma_buf(substream),
    455                                          azx_dev,
     566                        ofs = setup_bdle(bus, dmab, azx_dev,
    456567                                         &bdl, ofs, pos_adj, true);
    457568                        if (ofs < 0)
     
    463574        for (i = 0; i < periods; i++) {
    464575                if (i == periods - 1 && pos_adj)
    465                         ofs = setup_bdle(bus, snd_pcm_get_dma_buf(substream),
    466                                          azx_dev, &bdl, ofs,
    467                                          period_bytes - pos_adj, 0);
     576                        ofs = setup_bdle(bus, dmab, azx_dev,
     577                                         &bdl, ofs, period_bytes - pos_adj, 0);
    468578                else
    469                         ofs = setup_bdle(bus, snd_pcm_get_dma_buf(substream),
    470                                          azx_dev, &bdl, ofs,
    471                                          period_bytes,
     579                        ofs = setup_bdle(bus, dmab, azx_dev,
     580                                         &bdl, ofs, period_bytes,
    472581                                         !azx_dev->no_period_wakeup);
    473582                if (ofs < 0)
     
    494603                                 unsigned int format_val)
    495604{
    496 
     605        struct snd_pcm_substream *substream = azx_dev->substream;
     606        struct snd_compr_stream *cstream = azx_dev->cstream;
    497607        unsigned int bufsize, period_bytes;
    498         struct snd_pcm_substream *substream = azx_dev->substream;
    499         struct snd_pcm_runtime *runtime;
     608        unsigned int no_period_wakeup;
    500609        int err;
    501610
    502         if (!substream)
     611        if (substream) {
     612                bufsize = snd_pcm_lib_buffer_bytes(substream);
     613                period_bytes = snd_pcm_lib_period_bytes(substream);
     614                no_period_wakeup = substream->runtime->no_period_wakeup;
     615        } else if (cstream) {
     616                bufsize = cstream->runtime->buffer_size;
     617                period_bytes = cstream->runtime->fragment_size;
     618                no_period_wakeup = 0;
     619        } else {
    503620                return -EINVAL;
    504         runtime = substream->runtime;
    505         bufsize = snd_pcm_lib_buffer_bytes(substream);
    506         period_bytes = snd_pcm_lib_period_bytes(substream);
     621        }
    507622
    508623        if (bufsize != azx_dev->bufsize ||
    509624            period_bytes != azx_dev->period_bytes ||
    510625            format_val != azx_dev->format_val ||
    511             runtime->no_period_wakeup != azx_dev->no_period_wakeup) {
     626            no_period_wakeup != azx_dev->no_period_wakeup) {
    512627                azx_dev->bufsize = bufsize;
    513628                azx_dev->period_bytes = period_bytes;
    514629                azx_dev->format_val = format_val;
    515                 azx_dev->no_period_wakeup = runtime->no_period_wakeup;
     630                azx_dev->no_period_wakeup = no_period_wakeup;
    516631                err = snd_hdac_stream_setup_periods(azx_dev);
    517632                if (err < 0)
     
    589704        bool inited = false;
    590705        u64 cycle_last = 0;
    591         int i = 0;
    592706
    593707        list_for_each_entry(s, &bus->stream_list, list, struct hdac_stream) {
    594                 if (streams & (1 << i)) {
     708                if ((streams & (1 << s->index))) {
    595709                        azx_timecounter_init(s, inited, cycle_last);
    596710                        if (!inited) {
     
    599713                        }
    600714                }
    601                 i++;
    602715        }
    603716
     
    644757{
    645758        struct hdac_bus *bus = azx_dev->bus;
    646         int i, nwait, timeout;
     759        int nwait, timeout;
    647760        struct hdac_stream *s;
    648761
    649762        for (timeout = 5000; timeout; timeout--) {
    650763                nwait = 0;
    651                 i = 0;
    652764                list_for_each_entry(s, &bus->stream_list, list, struct hdac_stream) {
    653                         if (!(streams & (1 << i++)))
     765                        if (!(streams & (1 << s->index)))
    654766                                continue;
    655767
     
    680792EXPORT_SYMBOL_GPL(snd_hdac_stream_sync);
    681793
     794/**
     795 * snd_hdac_stream_spbcap_enable - enable SPIB for a stream
     796 * @bus: HD-audio core bus
     797 * @enable: flag to enable/disable SPIB
     798 * @index: stream index for which SPIB need to be enabled
     799 */
     800void snd_hdac_stream_spbcap_enable(struct hdac_bus *bus,
     801                                   bool enable, int index)
     802{
     803        u32 mask = 0;
     804
     805        if (!bus->spbcap) {
     806                dev_err(bus->dev, "Address of SPB capability is NULL\n");
     807                return;
     808        }
     809
     810        mask |= (1 << index);
     811
     812        if (enable)
     813                snd_hdac_updatel(bus->spbcap, AZX_REG_SPB_SPBFCCTL, mask, mask);
     814        else
     815                snd_hdac_updatel(bus->spbcap, AZX_REG_SPB_SPBFCCTL, mask, 0);
     816}
     817EXPORT_SYMBOL_GPL(snd_hdac_stream_spbcap_enable);
     818
     819/**
     820 * snd_hdac_stream_set_spib - sets the spib value of a stream
     821 * @bus: HD-audio core bus
     822 * @azx_dev: hdac_stream
     823 * @value: spib value to set
     824 */
     825int snd_hdac_stream_set_spib(struct hdac_bus *bus,
     826                             struct hdac_stream *azx_dev, u32 value)
     827{
     828        if (!bus->spbcap) {
     829                dev_err(bus->dev, "Address of SPB capability is NULL\n");
     830                return -EINVAL;
     831        }
     832
     833        writel(value, azx_dev->spib_addr);
     834
     835        return 0;
     836}
     837EXPORT_SYMBOL_GPL(snd_hdac_stream_set_spib);
     838
     839/**
     840 * snd_hdac_stream_get_spbmaxfifo - gets the spib value of a stream
     841 * @bus: HD-audio core bus
     842 * @azx_dev: hdac_stream
     843 *
     844 * Return maxfifo for the stream
     845 */
     846int snd_hdac_stream_get_spbmaxfifo(struct hdac_bus *bus,
     847                                   struct hdac_stream *azx_dev)
     848{
     849        if (!bus->spbcap) {
     850                dev_err(bus->dev, "Address of SPB capability is NULL\n");
     851                return -EINVAL;
     852        }
     853
     854        return readl(azx_dev->fifo_addr);
     855}
     856EXPORT_SYMBOL_GPL(snd_hdac_stream_get_spbmaxfifo);
     857
     858/**
     859 * snd_hdac_stream_drsm_enable - enable DMA resume for a stream
     860 * @bus: HD-audio core bus
     861 * @enable: flag to enable/disable DRSM
     862 * @index: stream index for which DRSM need to be enabled
     863 */
     864void snd_hdac_stream_drsm_enable(struct hdac_bus *bus,
     865                                 bool enable, int index)
     866{
     867        u32 mask = 0;
     868
     869        if (!bus->drsmcap) {
     870                dev_err(bus->dev, "Address of DRSM capability is NULL\n");
     871                return;
     872        }
     873
     874        mask |= (1 << index);
     875
     876        if (enable)
     877                snd_hdac_updatel(bus->drsmcap, AZX_REG_DRSM_CTL, mask, mask);
     878        else
     879                snd_hdac_updatel(bus->drsmcap, AZX_REG_DRSM_CTL, mask, 0);
     880}
     881EXPORT_SYMBOL_GPL(snd_hdac_stream_drsm_enable);
     882
     883#ifndef TARGET_OS2
     884/*
     885 * snd_hdac_stream_wait_drsm - wait for HW to clear RSM for a stream
     886 * @azx_dev: HD-audio core stream to await RSM for
     887 *
     888 * Returns 0 on success and -ETIMEDOUT upon a timeout.
     889 */
     890int snd_hdac_stream_wait_drsm(struct hdac_stream *azx_dev)
     891{
     892        struct hdac_bus *bus = azx_dev->bus;
     893        u32 mask, reg;
     894        int ret;
     895
     896        mask = 1 << azx_dev->index;
     897
     898        ret = read_poll_timeout(snd_hdac_reg_readl, reg, !(reg & mask), 250, 2000, false, bus,
     899                                bus->drsmcap + AZX_REG_DRSM_CTL);
     900        if (ret)
     901                dev_dbg(bus->dev, "polling RSM 0x%08x failed: %d\n", mask, ret);
     902        return ret;
     903}
     904EXPORT_SYMBOL_GPL(snd_hdac_stream_wait_drsm);
     905#endif
     906
     907/**
     908 * snd_hdac_stream_set_dpibr - sets the dpibr value of a stream
     909 * @bus: HD-audio core bus
     910 * @azx_dev: hdac_stream
     911 * @value: dpib value to set
     912 */
     913int snd_hdac_stream_set_dpibr(struct hdac_bus *bus,
     914                              struct hdac_stream *azx_dev, u32 value)
     915{
     916        if (!bus->drsmcap) {
     917                dev_err(bus->dev, "Address of DRSM capability is NULL\n");
     918                return -EINVAL;
     919        }
     920
     921        writel(value, azx_dev->dpibr_addr);
     922
     923        return 0;
     924}
     925EXPORT_SYMBOL_GPL(snd_hdac_stream_set_dpibr);
     926
     927/**
     928 * snd_hdac_stream_set_lpib - sets the lpib value of a stream
     929 * @azx_dev: hdac_stream
     930 * @value: lpib value to set
     931 */
     932int snd_hdac_stream_set_lpib(struct hdac_stream *azx_dev, u32 value)
     933{
     934        snd_hdac_stream_writel(azx_dev, SD_LPIB, value);
     935
     936        return 0;
     937}
     938EXPORT_SYMBOL_GPL(snd_hdac_stream_set_lpib);
     939
    682940#ifdef CONFIG_SND_HDA_DSP_LOADER
    683941/**
     
    7541012{
    7551013        if (start)
    756                 snd_hdac_stream_start(azx_dev, true);
     1014                snd_hdac_stream_start(azx_dev);
    7571015        else
    7581016                snd_hdac_stream_stop(azx_dev);
Note: See TracChangeset for help on using the changeset viewer.