Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * HD-audio controller helpers
0004  */
0005 
0006 #include <linux/kernel.h>
0007 #include <linux/delay.h>
0008 #include <linux/export.h>
0009 #include <sound/core.h>
0010 #include <sound/hdaudio.h>
0011 #include <sound/hda_register.h>
0012 #include "local.h"
0013 
0014 /* clear CORB read pointer properly */
0015 static void azx_clear_corbrp(struct hdac_bus *bus)
0016 {
0017     int timeout;
0018 
0019     for (timeout = 1000; timeout > 0; timeout--) {
0020         if (snd_hdac_chip_readw(bus, CORBRP) & AZX_CORBRP_RST)
0021             break;
0022         udelay(1);
0023     }
0024     if (timeout <= 0)
0025         dev_err(bus->dev, "CORB reset timeout#1, CORBRP = %d\n",
0026             snd_hdac_chip_readw(bus, CORBRP));
0027 
0028     snd_hdac_chip_writew(bus, CORBRP, 0);
0029     for (timeout = 1000; timeout > 0; timeout--) {
0030         if (snd_hdac_chip_readw(bus, CORBRP) == 0)
0031             break;
0032         udelay(1);
0033     }
0034     if (timeout <= 0)
0035         dev_err(bus->dev, "CORB reset timeout#2, CORBRP = %d\n",
0036             snd_hdac_chip_readw(bus, CORBRP));
0037 }
0038 
0039 /**
0040  * snd_hdac_bus_init_cmd_io - set up CORB/RIRB buffers
0041  * @bus: HD-audio core bus
0042  */
0043 void snd_hdac_bus_init_cmd_io(struct hdac_bus *bus)
0044 {
0045     WARN_ON_ONCE(!bus->rb.area);
0046 
0047     spin_lock_irq(&bus->reg_lock);
0048     /* CORB set up */
0049     bus->corb.addr = bus->rb.addr;
0050     bus->corb.buf = (__le32 *)bus->rb.area;
0051     snd_hdac_chip_writel(bus, CORBLBASE, (u32)bus->corb.addr);
0052     snd_hdac_chip_writel(bus, CORBUBASE, upper_32_bits(bus->corb.addr));
0053 
0054     /* set the corb size to 256 entries (ULI requires explicitly) */
0055     snd_hdac_chip_writeb(bus, CORBSIZE, 0x02);
0056     /* set the corb write pointer to 0 */
0057     snd_hdac_chip_writew(bus, CORBWP, 0);
0058 
0059     /* reset the corb hw read pointer */
0060     snd_hdac_chip_writew(bus, CORBRP, AZX_CORBRP_RST);
0061     if (!bus->corbrp_self_clear)
0062         azx_clear_corbrp(bus);
0063 
0064     /* enable corb dma */
0065     snd_hdac_chip_writeb(bus, CORBCTL, AZX_CORBCTL_RUN);
0066 
0067     /* RIRB set up */
0068     bus->rirb.addr = bus->rb.addr + 2048;
0069     bus->rirb.buf = (__le32 *)(bus->rb.area + 2048);
0070     bus->rirb.wp = bus->rirb.rp = 0;
0071     memset(bus->rirb.cmds, 0, sizeof(bus->rirb.cmds));
0072     snd_hdac_chip_writel(bus, RIRBLBASE, (u32)bus->rirb.addr);
0073     snd_hdac_chip_writel(bus, RIRBUBASE, upper_32_bits(bus->rirb.addr));
0074 
0075     /* set the rirb size to 256 entries (ULI requires explicitly) */
0076     snd_hdac_chip_writeb(bus, RIRBSIZE, 0x02);
0077     /* reset the rirb hw write pointer */
0078     snd_hdac_chip_writew(bus, RIRBWP, AZX_RIRBWP_RST);
0079     /* set N=1, get RIRB response interrupt for new entry */
0080     snd_hdac_chip_writew(bus, RINTCNT, 1);
0081     /* enable rirb dma and response irq */
0082     snd_hdac_chip_writeb(bus, RIRBCTL, AZX_RBCTL_DMA_EN | AZX_RBCTL_IRQ_EN);
0083     /* Accept unsolicited responses */
0084     snd_hdac_chip_updatel(bus, GCTL, AZX_GCTL_UNSOL, AZX_GCTL_UNSOL);
0085     spin_unlock_irq(&bus->reg_lock);
0086 }
0087 EXPORT_SYMBOL_GPL(snd_hdac_bus_init_cmd_io);
0088 
0089 /* wait for cmd dmas till they are stopped */
0090 static void hdac_wait_for_cmd_dmas(struct hdac_bus *bus)
0091 {
0092     unsigned long timeout;
0093 
0094     timeout = jiffies + msecs_to_jiffies(100);
0095     while ((snd_hdac_chip_readb(bus, RIRBCTL) & AZX_RBCTL_DMA_EN)
0096         && time_before(jiffies, timeout))
0097         udelay(10);
0098 
0099     timeout = jiffies + msecs_to_jiffies(100);
0100     while ((snd_hdac_chip_readb(bus, CORBCTL) & AZX_CORBCTL_RUN)
0101         && time_before(jiffies, timeout))
0102         udelay(10);
0103 }
0104 
0105 /**
0106  * snd_hdac_bus_stop_cmd_io - clean up CORB/RIRB buffers
0107  * @bus: HD-audio core bus
0108  */
0109 void snd_hdac_bus_stop_cmd_io(struct hdac_bus *bus)
0110 {
0111     spin_lock_irq(&bus->reg_lock);
0112     /* disable ringbuffer DMAs */
0113     snd_hdac_chip_writeb(bus, RIRBCTL, 0);
0114     snd_hdac_chip_writeb(bus, CORBCTL, 0);
0115     spin_unlock_irq(&bus->reg_lock);
0116 
0117     hdac_wait_for_cmd_dmas(bus);
0118 
0119     spin_lock_irq(&bus->reg_lock);
0120     /* disable unsolicited responses */
0121     snd_hdac_chip_updatel(bus, GCTL, AZX_GCTL_UNSOL, 0);
0122     spin_unlock_irq(&bus->reg_lock);
0123 }
0124 EXPORT_SYMBOL_GPL(snd_hdac_bus_stop_cmd_io);
0125 
0126 static unsigned int azx_command_addr(u32 cmd)
0127 {
0128     unsigned int addr = cmd >> 28;
0129 
0130     if (snd_BUG_ON(addr >= HDA_MAX_CODECS))
0131         addr = 0;
0132     return addr;
0133 }
0134 
0135 /**
0136  * snd_hdac_bus_send_cmd - send a command verb via CORB
0137  * @bus: HD-audio core bus
0138  * @val: encoded verb value to send
0139  *
0140  * Returns zero for success or a negative error code.
0141  */
0142 int snd_hdac_bus_send_cmd(struct hdac_bus *bus, unsigned int val)
0143 {
0144     unsigned int addr = azx_command_addr(val);
0145     unsigned int wp, rp;
0146 
0147     spin_lock_irq(&bus->reg_lock);
0148 
0149     bus->last_cmd[azx_command_addr(val)] = val;
0150 
0151     /* add command to corb */
0152     wp = snd_hdac_chip_readw(bus, CORBWP);
0153     if (wp == 0xffff) {
0154         /* something wrong, controller likely turned to D3 */
0155         spin_unlock_irq(&bus->reg_lock);
0156         return -EIO;
0157     }
0158     wp++;
0159     wp %= AZX_MAX_CORB_ENTRIES;
0160 
0161     rp = snd_hdac_chip_readw(bus, CORBRP);
0162     if (wp == rp) {
0163         /* oops, it's full */
0164         spin_unlock_irq(&bus->reg_lock);
0165         return -EAGAIN;
0166     }
0167 
0168     bus->rirb.cmds[addr]++;
0169     bus->corb.buf[wp] = cpu_to_le32(val);
0170     snd_hdac_chip_writew(bus, CORBWP, wp);
0171 
0172     spin_unlock_irq(&bus->reg_lock);
0173 
0174     return 0;
0175 }
0176 EXPORT_SYMBOL_GPL(snd_hdac_bus_send_cmd);
0177 
0178 #define AZX_RIRB_EX_UNSOL_EV    (1<<4)
0179 
0180 /**
0181  * snd_hdac_bus_update_rirb - retrieve RIRB entries
0182  * @bus: HD-audio core bus
0183  *
0184  * Usually called from interrupt handler.
0185  * The caller needs bus->reg_lock spinlock before calling this.
0186  */
0187 void snd_hdac_bus_update_rirb(struct hdac_bus *bus)
0188 {
0189     unsigned int rp, wp;
0190     unsigned int addr;
0191     u32 res, res_ex;
0192 
0193     wp = snd_hdac_chip_readw(bus, RIRBWP);
0194     if (wp == 0xffff) {
0195         /* something wrong, controller likely turned to D3 */
0196         return;
0197     }
0198 
0199     if (wp == bus->rirb.wp)
0200         return;
0201     bus->rirb.wp = wp;
0202 
0203     while (bus->rirb.rp != wp) {
0204         bus->rirb.rp++;
0205         bus->rirb.rp %= AZX_MAX_RIRB_ENTRIES;
0206 
0207         rp = bus->rirb.rp << 1; /* an RIRB entry is 8-bytes */
0208         res_ex = le32_to_cpu(bus->rirb.buf[rp + 1]);
0209         res = le32_to_cpu(bus->rirb.buf[rp]);
0210         addr = res_ex & 0xf;
0211         if (addr >= HDA_MAX_CODECS) {
0212             dev_err(bus->dev,
0213                 "spurious response %#x:%#x, rp = %d, wp = %d",
0214                 res, res_ex, bus->rirb.rp, wp);
0215             snd_BUG();
0216         } else if (res_ex & AZX_RIRB_EX_UNSOL_EV)
0217             snd_hdac_bus_queue_event(bus, res, res_ex);
0218         else if (bus->rirb.cmds[addr]) {
0219             bus->rirb.res[addr] = res;
0220             bus->rirb.cmds[addr]--;
0221             if (!bus->rirb.cmds[addr] &&
0222                 waitqueue_active(&bus->rirb_wq))
0223                 wake_up(&bus->rirb_wq);
0224         } else {
0225             dev_err_ratelimited(bus->dev,
0226                 "spurious response %#x:%#x, last cmd=%#08x\n",
0227                 res, res_ex, bus->last_cmd[addr]);
0228         }
0229     }
0230 }
0231 EXPORT_SYMBOL_GPL(snd_hdac_bus_update_rirb);
0232 
0233 /**
0234  * snd_hdac_bus_get_response - receive a response via RIRB
0235  * @bus: HD-audio core bus
0236  * @addr: codec address
0237  * @res: pointer to store the value, NULL when not needed
0238  *
0239  * Returns zero if a value is read, or a negative error code.
0240  */
0241 int snd_hdac_bus_get_response(struct hdac_bus *bus, unsigned int addr,
0242                   unsigned int *res)
0243 {
0244     unsigned long timeout;
0245     unsigned long loopcounter;
0246     wait_queue_entry_t wait;
0247     bool warned = false;
0248 
0249     init_wait_entry(&wait, 0);
0250     timeout = jiffies + msecs_to_jiffies(1000);
0251 
0252     for (loopcounter = 0;; loopcounter++) {
0253         spin_lock_irq(&bus->reg_lock);
0254         if (!bus->polling_mode)
0255             prepare_to_wait(&bus->rirb_wq, &wait,
0256                     TASK_UNINTERRUPTIBLE);
0257         if (bus->polling_mode)
0258             snd_hdac_bus_update_rirb(bus);
0259         if (!bus->rirb.cmds[addr]) {
0260             if (res)
0261                 *res = bus->rirb.res[addr]; /* the last value */
0262             if (!bus->polling_mode)
0263                 finish_wait(&bus->rirb_wq, &wait);
0264             spin_unlock_irq(&bus->reg_lock);
0265             return 0;
0266         }
0267         spin_unlock_irq(&bus->reg_lock);
0268         if (time_after(jiffies, timeout))
0269             break;
0270 #define LOOP_COUNT_MAX  3000
0271         if (!bus->polling_mode) {
0272             schedule_timeout(msecs_to_jiffies(2));
0273         } else if (bus->needs_damn_long_delay ||
0274                loopcounter > LOOP_COUNT_MAX) {
0275             if (loopcounter > LOOP_COUNT_MAX && !warned) {
0276                 dev_dbg_ratelimited(bus->dev,
0277                             "too slow response, last cmd=%#08x\n",
0278                             bus->last_cmd[addr]);
0279                 warned = true;
0280             }
0281             msleep(2); /* temporary workaround */
0282         } else {
0283             udelay(10);
0284             cond_resched();
0285         }
0286     }
0287 
0288     if (!bus->polling_mode)
0289         finish_wait(&bus->rirb_wq, &wait);
0290 
0291     return -EIO;
0292 }
0293 EXPORT_SYMBOL_GPL(snd_hdac_bus_get_response);
0294 
0295 #define HDAC_MAX_CAPS 10
0296 /**
0297  * snd_hdac_bus_parse_capabilities - parse capability structure
0298  * @bus: the pointer to bus object
0299  *
0300  * Returns 0 if successful, or a negative error code.
0301  */
0302 int snd_hdac_bus_parse_capabilities(struct hdac_bus *bus)
0303 {
0304     unsigned int cur_cap;
0305     unsigned int offset;
0306     unsigned int counter = 0;
0307 
0308     offset = snd_hdac_chip_readw(bus, LLCH);
0309 
0310     /* Lets walk the linked capabilities list */
0311     do {
0312         cur_cap = _snd_hdac_chip_readl(bus, offset);
0313 
0314         dev_dbg(bus->dev, "Capability version: 0x%x\n",
0315             (cur_cap & AZX_CAP_HDR_VER_MASK) >> AZX_CAP_HDR_VER_OFF);
0316 
0317         dev_dbg(bus->dev, "HDA capability ID: 0x%x\n",
0318             (cur_cap & AZX_CAP_HDR_ID_MASK) >> AZX_CAP_HDR_ID_OFF);
0319 
0320         if (cur_cap == -1) {
0321             dev_dbg(bus->dev, "Invalid capability reg read\n");
0322             break;
0323         }
0324 
0325         switch ((cur_cap & AZX_CAP_HDR_ID_MASK) >> AZX_CAP_HDR_ID_OFF) {
0326         case AZX_ML_CAP_ID:
0327             dev_dbg(bus->dev, "Found ML capability\n");
0328             bus->mlcap = bus->remap_addr + offset;
0329             break;
0330 
0331         case AZX_GTS_CAP_ID:
0332             dev_dbg(bus->dev, "Found GTS capability offset=%x\n", offset);
0333             bus->gtscap = bus->remap_addr + offset;
0334             break;
0335 
0336         case AZX_PP_CAP_ID:
0337             /* PP capability found, the Audio DSP is present */
0338             dev_dbg(bus->dev, "Found PP capability offset=%x\n", offset);
0339             bus->ppcap = bus->remap_addr + offset;
0340             break;
0341 
0342         case AZX_SPB_CAP_ID:
0343             /* SPIB capability found, handler function */
0344             dev_dbg(bus->dev, "Found SPB capability\n");
0345             bus->spbcap = bus->remap_addr + offset;
0346             break;
0347 
0348         case AZX_DRSM_CAP_ID:
0349             /* DMA resume  capability found, handler function */
0350             dev_dbg(bus->dev, "Found DRSM capability\n");
0351             bus->drsmcap = bus->remap_addr + offset;
0352             break;
0353 
0354         default:
0355             dev_err(bus->dev, "Unknown capability %d\n", cur_cap);
0356             cur_cap = 0;
0357             break;
0358         }
0359 
0360         counter++;
0361 
0362         if (counter > HDAC_MAX_CAPS) {
0363             dev_err(bus->dev, "We exceeded HDAC capabilities!!!\n");
0364             break;
0365         }
0366 
0367         /* read the offset of next capability */
0368         offset = cur_cap & AZX_CAP_HDR_NXT_PTR_MASK;
0369 
0370     } while (offset);
0371 
0372     return 0;
0373 }
0374 EXPORT_SYMBOL_GPL(snd_hdac_bus_parse_capabilities);
0375 
0376 /*
0377  * Lowlevel interface
0378  */
0379 
0380 /**
0381  * snd_hdac_bus_enter_link_reset - enter link reset
0382  * @bus: HD-audio core bus
0383  *
0384  * Enter to the link reset state.
0385  */
0386 void snd_hdac_bus_enter_link_reset(struct hdac_bus *bus)
0387 {
0388     unsigned long timeout;
0389 
0390     /* reset controller */
0391     snd_hdac_chip_updatel(bus, GCTL, AZX_GCTL_RESET, 0);
0392 
0393     timeout = jiffies + msecs_to_jiffies(100);
0394     while ((snd_hdac_chip_readb(bus, GCTL) & AZX_GCTL_RESET) &&
0395            time_before(jiffies, timeout))
0396         usleep_range(500, 1000);
0397 }
0398 EXPORT_SYMBOL_GPL(snd_hdac_bus_enter_link_reset);
0399 
0400 /**
0401  * snd_hdac_bus_exit_link_reset - exit link reset
0402  * @bus: HD-audio core bus
0403  *
0404  * Exit from the link reset state.
0405  */
0406 void snd_hdac_bus_exit_link_reset(struct hdac_bus *bus)
0407 {
0408     unsigned long timeout;
0409 
0410     snd_hdac_chip_updateb(bus, GCTL, AZX_GCTL_RESET, AZX_GCTL_RESET);
0411 
0412     timeout = jiffies + msecs_to_jiffies(100);
0413     while (!snd_hdac_chip_readb(bus, GCTL) && time_before(jiffies, timeout))
0414         usleep_range(500, 1000);
0415 }
0416 EXPORT_SYMBOL_GPL(snd_hdac_bus_exit_link_reset);
0417 
0418 /* reset codec link */
0419 int snd_hdac_bus_reset_link(struct hdac_bus *bus, bool full_reset)
0420 {
0421     if (!full_reset)
0422         goto skip_reset;
0423 
0424     /* clear STATESTS if not in reset */
0425     if (snd_hdac_chip_readb(bus, GCTL) & AZX_GCTL_RESET)
0426         snd_hdac_chip_writew(bus, STATESTS, STATESTS_INT_MASK);
0427 
0428     /* reset controller */
0429     snd_hdac_bus_enter_link_reset(bus);
0430 
0431     /* delay for >= 100us for codec PLL to settle per spec
0432      * Rev 0.9 section 5.5.1
0433      */
0434     usleep_range(500, 1000);
0435 
0436     /* Bring controller out of reset */
0437     snd_hdac_bus_exit_link_reset(bus);
0438 
0439     /* Brent Chartrand said to wait >= 540us for codecs to initialize */
0440     usleep_range(1000, 1200);
0441 
0442  skip_reset:
0443     /* check to see if controller is ready */
0444     if (!snd_hdac_chip_readb(bus, GCTL)) {
0445         dev_dbg(bus->dev, "controller not ready!\n");
0446         return -EBUSY;
0447     }
0448 
0449     /* detect codecs */
0450     if (!bus->codec_mask) {
0451         bus->codec_mask = snd_hdac_chip_readw(bus, STATESTS);
0452         dev_dbg(bus->dev, "codec_mask = 0x%lx\n", bus->codec_mask);
0453     }
0454 
0455     return 0;
0456 }
0457 EXPORT_SYMBOL_GPL(snd_hdac_bus_reset_link);
0458 
0459 /* enable interrupts */
0460 static void azx_int_enable(struct hdac_bus *bus)
0461 {
0462     /* enable controller CIE and GIE */
0463     snd_hdac_chip_updatel(bus, INTCTL,
0464                   AZX_INT_CTRL_EN | AZX_INT_GLOBAL_EN,
0465                   AZX_INT_CTRL_EN | AZX_INT_GLOBAL_EN);
0466 }
0467 
0468 /* disable interrupts */
0469 static void azx_int_disable(struct hdac_bus *bus)
0470 {
0471     struct hdac_stream *azx_dev;
0472 
0473     /* disable interrupts in stream descriptor */
0474     list_for_each_entry(azx_dev, &bus->stream_list, list)
0475         snd_hdac_stream_updateb(azx_dev, SD_CTL, SD_INT_MASK, 0);
0476 
0477     /* disable SIE for all streams & disable controller CIE and GIE */
0478     snd_hdac_chip_writel(bus, INTCTL, 0);
0479 }
0480 
0481 /* clear interrupts */
0482 static void azx_int_clear(struct hdac_bus *bus)
0483 {
0484     struct hdac_stream *azx_dev;
0485 
0486     /* clear stream status */
0487     list_for_each_entry(azx_dev, &bus->stream_list, list)
0488         snd_hdac_stream_writeb(azx_dev, SD_STS, SD_INT_MASK);
0489 
0490     /* clear STATESTS */
0491     snd_hdac_chip_writew(bus, STATESTS, STATESTS_INT_MASK);
0492 
0493     /* clear rirb status */
0494     snd_hdac_chip_writeb(bus, RIRBSTS, RIRB_INT_MASK);
0495 
0496     /* clear int status */
0497     snd_hdac_chip_writel(bus, INTSTS, AZX_INT_CTRL_EN | AZX_INT_ALL_STREAM);
0498 }
0499 
0500 /**
0501  * snd_hdac_bus_init_chip - reset and start the controller registers
0502  * @bus: HD-audio core bus
0503  * @full_reset: Do full reset
0504  */
0505 bool snd_hdac_bus_init_chip(struct hdac_bus *bus, bool full_reset)
0506 {
0507     if (bus->chip_init)
0508         return false;
0509 
0510     /* reset controller */
0511     snd_hdac_bus_reset_link(bus, full_reset);
0512 
0513     /* clear interrupts */
0514     azx_int_clear(bus);
0515 
0516     /* initialize the codec command I/O */
0517     snd_hdac_bus_init_cmd_io(bus);
0518 
0519     /* enable interrupts after CORB/RIRB buffers are initialized above */
0520     azx_int_enable(bus);
0521 
0522     /* program the position buffer */
0523     if (bus->use_posbuf && bus->posbuf.addr) {
0524         snd_hdac_chip_writel(bus, DPLBASE, (u32)bus->posbuf.addr);
0525         snd_hdac_chip_writel(bus, DPUBASE, upper_32_bits(bus->posbuf.addr));
0526     }
0527 
0528     bus->chip_init = true;
0529 
0530     return true;
0531 }
0532 EXPORT_SYMBOL_GPL(snd_hdac_bus_init_chip);
0533 
0534 /**
0535  * snd_hdac_bus_stop_chip - disable the whole IRQ and I/Os
0536  * @bus: HD-audio core bus
0537  */
0538 void snd_hdac_bus_stop_chip(struct hdac_bus *bus)
0539 {
0540     if (!bus->chip_init)
0541         return;
0542 
0543     /* disable interrupts */
0544     azx_int_disable(bus);
0545     azx_int_clear(bus);
0546 
0547     /* disable CORB/RIRB */
0548     snd_hdac_bus_stop_cmd_io(bus);
0549 
0550     /* disable position buffer */
0551     if (bus->posbuf.addr) {
0552         snd_hdac_chip_writel(bus, DPLBASE, 0);
0553         snd_hdac_chip_writel(bus, DPUBASE, 0);
0554     }
0555 
0556     bus->chip_init = false;
0557 }
0558 EXPORT_SYMBOL_GPL(snd_hdac_bus_stop_chip);
0559 
0560 /**
0561  * snd_hdac_bus_handle_stream_irq - interrupt handler for streams
0562  * @bus: HD-audio core bus
0563  * @status: INTSTS register value
0564  * @ack: callback to be called for woken streams
0565  *
0566  * Returns the bits of handled streams, or zero if no stream is handled.
0567  */
0568 int snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status,
0569                     void (*ack)(struct hdac_bus *,
0570                         struct hdac_stream *))
0571 {
0572     struct hdac_stream *azx_dev;
0573     u8 sd_status;
0574     int handled = 0;
0575 
0576     list_for_each_entry(azx_dev, &bus->stream_list, list) {
0577         if (status & azx_dev->sd_int_sta_mask) {
0578             sd_status = snd_hdac_stream_readb(azx_dev, SD_STS);
0579             snd_hdac_stream_writeb(azx_dev, SD_STS, SD_INT_MASK);
0580             handled |= 1 << azx_dev->index;
0581             if (!azx_dev->substream || !azx_dev->running ||
0582                 !(sd_status & SD_INT_COMPLETE))
0583                 continue;
0584             if (ack)
0585                 ack(bus, azx_dev);
0586         }
0587     }
0588     return handled;
0589 }
0590 EXPORT_SYMBOL_GPL(snd_hdac_bus_handle_stream_irq);
0591 
0592 /**
0593  * snd_hdac_bus_alloc_stream_pages - allocate BDL and other buffers
0594  * @bus: HD-audio core bus
0595  *
0596  * Call this after assigning the all streams.
0597  * Returns zero for success, or a negative error code.
0598  */
0599 int snd_hdac_bus_alloc_stream_pages(struct hdac_bus *bus)
0600 {
0601     struct hdac_stream *s;
0602     int num_streams = 0;
0603     int dma_type = bus->dma_type ? bus->dma_type : SNDRV_DMA_TYPE_DEV;
0604     int err;
0605 
0606     list_for_each_entry(s, &bus->stream_list, list) {
0607         /* allocate memory for the BDL for each stream */
0608         err = snd_dma_alloc_pages(dma_type, bus->dev,
0609                       BDL_SIZE, &s->bdl);
0610         num_streams++;
0611         if (err < 0)
0612             return -ENOMEM;
0613     }
0614 
0615     if (WARN_ON(!num_streams))
0616         return -EINVAL;
0617     /* allocate memory for the position buffer */
0618     err = snd_dma_alloc_pages(dma_type, bus->dev,
0619                   num_streams * 8, &bus->posbuf);
0620     if (err < 0)
0621         return -ENOMEM;
0622     list_for_each_entry(s, &bus->stream_list, list)
0623         s->posbuf = (__le32 *)(bus->posbuf.area + s->index * 8);
0624 
0625     /* single page (at least 4096 bytes) must suffice for both ringbuffes */
0626     return snd_dma_alloc_pages(dma_type, bus->dev, PAGE_SIZE, &bus->rb);
0627 }
0628 EXPORT_SYMBOL_GPL(snd_hdac_bus_alloc_stream_pages);
0629 
0630 /**
0631  * snd_hdac_bus_free_stream_pages - release BDL and other buffers
0632  * @bus: HD-audio core bus
0633  */
0634 void snd_hdac_bus_free_stream_pages(struct hdac_bus *bus)
0635 {
0636     struct hdac_stream *s;
0637 
0638     list_for_each_entry(s, &bus->stream_list, list) {
0639         if (s->bdl.area)
0640             snd_dma_free_pages(&s->bdl);
0641     }
0642 
0643     if (bus->rb.area)
0644         snd_dma_free_pages(&bus->rb);
0645     if (bus->posbuf.area)
0646         snd_dma_free_pages(&bus->posbuf);
0647 }
0648 EXPORT_SYMBOL_GPL(snd_hdac_bus_free_stream_pages);
0649 
0650 /**
0651  * snd_hdac_bus_link_power - power up/down codec link
0652  * @codec: HD-audio device
0653  * @enable: whether to power-up the link
0654  */
0655 void snd_hdac_bus_link_power(struct hdac_device *codec, bool enable)
0656 {
0657     if (enable)
0658         set_bit(codec->addr, &codec->bus->codec_powered);
0659     else
0660         clear_bit(codec->addr, &codec->bus->codec_powered);
0661 }
0662 EXPORT_SYMBOL_GPL(snd_hdac_bus_link_power);