^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * HD-audio controller helpers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <sound/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <sound/hdaudio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <sound/hda_register.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "local.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) /* clear CORB read pointer properly */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) static void azx_clear_corbrp(struct hdac_bus *bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) int timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) for (timeout = 1000; timeout > 0; timeout--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) if (snd_hdac_chip_readw(bus, CORBRP) & AZX_CORBRP_RST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) if (timeout <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) dev_err(bus->dev, "CORB reset timeout#1, CORBRP = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) snd_hdac_chip_readw(bus, CORBRP));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) snd_hdac_chip_writew(bus, CORBRP, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) for (timeout = 1000; timeout > 0; timeout--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) if (snd_hdac_chip_readw(bus, CORBRP) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) if (timeout <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) dev_err(bus->dev, "CORB reset timeout#2, CORBRP = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) snd_hdac_chip_readw(bus, CORBRP));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * snd_hdac_bus_init_cmd_io - set up CORB/RIRB buffers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * @bus: HD-audio core bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) void snd_hdac_bus_init_cmd_io(struct hdac_bus *bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) WARN_ON_ONCE(!bus->rb.area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) spin_lock_irq(&bus->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /* CORB set up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) bus->corb.addr = bus->rb.addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) bus->corb.buf = (__le32 *)bus->rb.area;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) snd_hdac_chip_writel(bus, CORBLBASE, (u32)bus->corb.addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) snd_hdac_chip_writel(bus, CORBUBASE, upper_32_bits(bus->corb.addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) /* set the corb size to 256 entries (ULI requires explicitly) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) snd_hdac_chip_writeb(bus, CORBSIZE, 0x02);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) /* set the corb write pointer to 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) snd_hdac_chip_writew(bus, CORBWP, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) /* reset the corb hw read pointer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) snd_hdac_chip_writew(bus, CORBRP, AZX_CORBRP_RST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (!bus->corbrp_self_clear)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) azx_clear_corbrp(bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) /* enable corb dma */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) snd_hdac_chip_writeb(bus, CORBCTL, AZX_CORBCTL_RUN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) /* RIRB set up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) bus->rirb.addr = bus->rb.addr + 2048;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) bus->rirb.buf = (__le32 *)(bus->rb.area + 2048);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) bus->rirb.wp = bus->rirb.rp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) memset(bus->rirb.cmds, 0, sizeof(bus->rirb.cmds));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) snd_hdac_chip_writel(bus, RIRBLBASE, (u32)bus->rirb.addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) snd_hdac_chip_writel(bus, RIRBUBASE, upper_32_bits(bus->rirb.addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) /* set the rirb size to 256 entries (ULI requires explicitly) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) snd_hdac_chip_writeb(bus, RIRBSIZE, 0x02);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) /* reset the rirb hw write pointer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) snd_hdac_chip_writew(bus, RIRBWP, AZX_RIRBWP_RST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) /* set N=1, get RIRB response interrupt for new entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) snd_hdac_chip_writew(bus, RINTCNT, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) /* enable rirb dma and response irq */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) snd_hdac_chip_writeb(bus, RIRBCTL, AZX_RBCTL_DMA_EN | AZX_RBCTL_IRQ_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) /* Accept unsolicited responses */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) snd_hdac_chip_updatel(bus, GCTL, AZX_GCTL_UNSOL, AZX_GCTL_UNSOL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) spin_unlock_irq(&bus->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) EXPORT_SYMBOL_GPL(snd_hdac_bus_init_cmd_io);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) /* wait for cmd dmas till they are stopped */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) static void hdac_wait_for_cmd_dmas(struct hdac_bus *bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) unsigned long timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) timeout = jiffies + msecs_to_jiffies(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) while ((snd_hdac_chip_readb(bus, RIRBCTL) & AZX_RBCTL_DMA_EN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) && time_before(jiffies, timeout))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) timeout = jiffies + msecs_to_jiffies(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) while ((snd_hdac_chip_readb(bus, CORBCTL) & AZX_CORBCTL_RUN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) && time_before(jiffies, timeout))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * snd_hdac_bus_stop_cmd_io - clean up CORB/RIRB buffers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * @bus: HD-audio core bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) void snd_hdac_bus_stop_cmd_io(struct hdac_bus *bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) spin_lock_irq(&bus->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /* disable ringbuffer DMAs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) snd_hdac_chip_writeb(bus, RIRBCTL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) snd_hdac_chip_writeb(bus, CORBCTL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) spin_unlock_irq(&bus->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) hdac_wait_for_cmd_dmas(bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) spin_lock_irq(&bus->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) /* disable unsolicited responses */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) snd_hdac_chip_updatel(bus, GCTL, AZX_GCTL_UNSOL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) spin_unlock_irq(&bus->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) EXPORT_SYMBOL_GPL(snd_hdac_bus_stop_cmd_io);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static unsigned int azx_command_addr(u32 cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) unsigned int addr = cmd >> 28;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) if (snd_BUG_ON(addr >= HDA_MAX_CODECS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) addr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) return addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) * snd_hdac_bus_send_cmd - send a command verb via CORB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) * @bus: HD-audio core bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) * @val: encoded verb value to send
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * Returns zero for success or a negative error code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) int snd_hdac_bus_send_cmd(struct hdac_bus *bus, unsigned int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) unsigned int addr = azx_command_addr(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) unsigned int wp, rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) spin_lock_irq(&bus->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) bus->last_cmd[azx_command_addr(val)] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) /* add command to corb */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) wp = snd_hdac_chip_readw(bus, CORBWP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) if (wp == 0xffff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) /* something wrong, controller likely turned to D3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) spin_unlock_irq(&bus->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) wp++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) wp %= AZX_MAX_CORB_ENTRIES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) rp = snd_hdac_chip_readw(bus, CORBRP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (wp == rp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) /* oops, it's full */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) spin_unlock_irq(&bus->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) bus->rirb.cmds[addr]++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) bus->corb.buf[wp] = cpu_to_le32(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) snd_hdac_chip_writew(bus, CORBWP, wp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) spin_unlock_irq(&bus->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) EXPORT_SYMBOL_GPL(snd_hdac_bus_send_cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) #define AZX_RIRB_EX_UNSOL_EV (1<<4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) * snd_hdac_bus_update_rirb - retrieve RIRB entries
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) * @bus: HD-audio core bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * Usually called from interrupt handler.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) * The caller needs bus->reg_lock spinlock before calling this.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) void snd_hdac_bus_update_rirb(struct hdac_bus *bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) unsigned int rp, wp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) unsigned int addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) u32 res, res_ex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) wp = snd_hdac_chip_readw(bus, RIRBWP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) if (wp == 0xffff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) /* something wrong, controller likely turned to D3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) if (wp == bus->rirb.wp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) bus->rirb.wp = wp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) while (bus->rirb.rp != wp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) bus->rirb.rp++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) bus->rirb.rp %= AZX_MAX_RIRB_ENTRIES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) rp = bus->rirb.rp << 1; /* an RIRB entry is 8-bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) res_ex = le32_to_cpu(bus->rirb.buf[rp + 1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) res = le32_to_cpu(bus->rirb.buf[rp]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) addr = res_ex & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) if (addr >= HDA_MAX_CODECS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) dev_err(bus->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) "spurious response %#x:%#x, rp = %d, wp = %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) res, res_ex, bus->rirb.rp, wp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) snd_BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) } else if (res_ex & AZX_RIRB_EX_UNSOL_EV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) snd_hdac_bus_queue_event(bus, res, res_ex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) else if (bus->rirb.cmds[addr]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) bus->rirb.res[addr] = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) bus->rirb.cmds[addr]--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (!bus->rirb.cmds[addr] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) waitqueue_active(&bus->rirb_wq))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) wake_up(&bus->rirb_wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) dev_err_ratelimited(bus->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) "spurious response %#x:%#x, last cmd=%#08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) res, res_ex, bus->last_cmd[addr]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) EXPORT_SYMBOL_GPL(snd_hdac_bus_update_rirb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) * snd_hdac_bus_get_response - receive a response via RIRB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) * @bus: HD-audio core bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) * @addr: codec address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) * @res: pointer to store the value, NULL when not needed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) * Returns zero if a value is read, or a negative error code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) int snd_hdac_bus_get_response(struct hdac_bus *bus, unsigned int addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) unsigned int *res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) unsigned long timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) unsigned long loopcounter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) wait_queue_entry_t wait;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) bool warned = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) init_wait_entry(&wait, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) timeout = jiffies + msecs_to_jiffies(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) for (loopcounter = 0;; loopcounter++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) spin_lock_irq(&bus->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) if (!bus->polling_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) prepare_to_wait(&bus->rirb_wq, &wait,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) TASK_UNINTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if (bus->polling_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) snd_hdac_bus_update_rirb(bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (!bus->rirb.cmds[addr]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) *res = bus->rirb.res[addr]; /* the last value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) if (!bus->polling_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) finish_wait(&bus->rirb_wq, &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) spin_unlock_irq(&bus->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) spin_unlock_irq(&bus->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) if (time_after(jiffies, timeout))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) #define LOOP_COUNT_MAX 3000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (!bus->polling_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) schedule_timeout(msecs_to_jiffies(2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) } else if (bus->needs_damn_long_delay ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) loopcounter > LOOP_COUNT_MAX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) if (loopcounter > LOOP_COUNT_MAX && !warned) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) dev_dbg_ratelimited(bus->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) "too slow response, last cmd=%#08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) bus->last_cmd[addr]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) warned = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) msleep(2); /* temporary workaround */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) cond_resched();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if (!bus->polling_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) finish_wait(&bus->rirb_wq, &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) EXPORT_SYMBOL_GPL(snd_hdac_bus_get_response);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) #define HDAC_MAX_CAPS 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) * snd_hdac_bus_parse_capabilities - parse capability structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) * @bus: the pointer to bus object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) * Returns 0 if successful, or a negative error code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) int snd_hdac_bus_parse_capabilities(struct hdac_bus *bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) unsigned int cur_cap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) unsigned int offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) unsigned int counter = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) offset = snd_hdac_chip_readw(bus, LLCH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) /* Lets walk the linked capabilities list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) cur_cap = _snd_hdac_chip_readl(bus, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) dev_dbg(bus->dev, "Capability version: 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) (cur_cap & AZX_CAP_HDR_VER_MASK) >> AZX_CAP_HDR_VER_OFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) dev_dbg(bus->dev, "HDA capability ID: 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) (cur_cap & AZX_CAP_HDR_ID_MASK) >> AZX_CAP_HDR_ID_OFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) if (cur_cap == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) dev_dbg(bus->dev, "Invalid capability reg read\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) switch ((cur_cap & AZX_CAP_HDR_ID_MASK) >> AZX_CAP_HDR_ID_OFF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) case AZX_ML_CAP_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) dev_dbg(bus->dev, "Found ML capability\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) bus->mlcap = bus->remap_addr + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) case AZX_GTS_CAP_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) dev_dbg(bus->dev, "Found GTS capability offset=%x\n", offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) bus->gtscap = bus->remap_addr + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) case AZX_PP_CAP_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) /* PP capability found, the Audio DSP is present */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) dev_dbg(bus->dev, "Found PP capability offset=%x\n", offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) bus->ppcap = bus->remap_addr + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) case AZX_SPB_CAP_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) /* SPIB capability found, handler function */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) dev_dbg(bus->dev, "Found SPB capability\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) bus->spbcap = bus->remap_addr + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) case AZX_DRSM_CAP_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) /* DMA resume capability found, handler function */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) dev_dbg(bus->dev, "Found DRSM capability\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) bus->drsmcap = bus->remap_addr + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) dev_err(bus->dev, "Unknown capability %d\n", cur_cap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) cur_cap = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) counter++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) if (counter > HDAC_MAX_CAPS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) dev_err(bus->dev, "We exceeded HDAC capabilities!!!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) /* read the offset of next capability */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) offset = cur_cap & AZX_CAP_HDR_NXT_PTR_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) } while (offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) EXPORT_SYMBOL_GPL(snd_hdac_bus_parse_capabilities);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) * Lowlevel interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) * snd_hdac_bus_enter_link_reset - enter link reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) * @bus: HD-audio core bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) * Enter to the link reset state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) void snd_hdac_bus_enter_link_reset(struct hdac_bus *bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) unsigned long timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) /* reset controller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) snd_hdac_chip_updatel(bus, GCTL, AZX_GCTL_RESET, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) timeout = jiffies + msecs_to_jiffies(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) while ((snd_hdac_chip_readb(bus, GCTL) & AZX_GCTL_RESET) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) time_before(jiffies, timeout))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) usleep_range(500, 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) EXPORT_SYMBOL_GPL(snd_hdac_bus_enter_link_reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) * snd_hdac_bus_exit_link_reset - exit link reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) * @bus: HD-audio core bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) * Exit from the link reset state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) void snd_hdac_bus_exit_link_reset(struct hdac_bus *bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) unsigned long timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) snd_hdac_chip_updateb(bus, GCTL, AZX_GCTL_RESET, AZX_GCTL_RESET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) timeout = jiffies + msecs_to_jiffies(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) while (!snd_hdac_chip_readb(bus, GCTL) && time_before(jiffies, timeout))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) usleep_range(500, 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) EXPORT_SYMBOL_GPL(snd_hdac_bus_exit_link_reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) /* reset codec link */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) int snd_hdac_bus_reset_link(struct hdac_bus *bus, bool full_reset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) if (!full_reset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) goto skip_reset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) /* clear STATESTS if not in reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) if (snd_hdac_chip_readb(bus, GCTL) & AZX_GCTL_RESET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) snd_hdac_chip_writew(bus, STATESTS, STATESTS_INT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) /* reset controller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) snd_hdac_bus_enter_link_reset(bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) /* delay for >= 100us for codec PLL to settle per spec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) * Rev 0.9 section 5.5.1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) usleep_range(500, 1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) /* Bring controller out of reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) snd_hdac_bus_exit_link_reset(bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) /* Brent Chartrand said to wait >= 540us for codecs to initialize */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) usleep_range(1000, 1200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) skip_reset:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) /* check to see if controller is ready */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) if (!snd_hdac_chip_readb(bus, GCTL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) dev_dbg(bus->dev, "controller not ready!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) /* detect codecs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) if (!bus->codec_mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) bus->codec_mask = snd_hdac_chip_readw(bus, STATESTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) dev_dbg(bus->dev, "codec_mask = 0x%lx\n", bus->codec_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) EXPORT_SYMBOL_GPL(snd_hdac_bus_reset_link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) /* enable interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) static void azx_int_enable(struct hdac_bus *bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) /* enable controller CIE and GIE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) snd_hdac_chip_updatel(bus, INTCTL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) AZX_INT_CTRL_EN | AZX_INT_GLOBAL_EN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) AZX_INT_CTRL_EN | AZX_INT_GLOBAL_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) /* disable interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) static void azx_int_disable(struct hdac_bus *bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) struct hdac_stream *azx_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) /* disable interrupts in stream descriptor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) list_for_each_entry(azx_dev, &bus->stream_list, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) snd_hdac_stream_updateb(azx_dev, SD_CTL, SD_INT_MASK, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) /* disable SIE for all streams */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) snd_hdac_chip_writeb(bus, INTCTL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) /* disable controller CIE and GIE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) snd_hdac_chip_updatel(bus, INTCTL, AZX_INT_CTRL_EN | AZX_INT_GLOBAL_EN, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) /* clear interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) static void azx_int_clear(struct hdac_bus *bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) struct hdac_stream *azx_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) /* clear stream status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) list_for_each_entry(azx_dev, &bus->stream_list, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) snd_hdac_stream_writeb(azx_dev, SD_STS, SD_INT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) /* clear STATESTS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) snd_hdac_chip_writew(bus, STATESTS, STATESTS_INT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) /* clear rirb status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) snd_hdac_chip_writeb(bus, RIRBSTS, RIRB_INT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) /* clear int status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) snd_hdac_chip_writel(bus, INTSTS, AZX_INT_CTRL_EN | AZX_INT_ALL_STREAM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) * snd_hdac_bus_init_chip - reset and start the controller registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) * @bus: HD-audio core bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) * @full_reset: Do full reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) bool snd_hdac_bus_init_chip(struct hdac_bus *bus, bool full_reset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) if (bus->chip_init)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) /* reset controller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) snd_hdac_bus_reset_link(bus, full_reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) /* clear interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) azx_int_clear(bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) /* initialize the codec command I/O */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) snd_hdac_bus_init_cmd_io(bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) /* enable interrupts after CORB/RIRB buffers are initialized above */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) azx_int_enable(bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) /* program the position buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) if (bus->use_posbuf && bus->posbuf.addr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) snd_hdac_chip_writel(bus, DPLBASE, (u32)bus->posbuf.addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) snd_hdac_chip_writel(bus, DPUBASE, upper_32_bits(bus->posbuf.addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) bus->chip_init = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) EXPORT_SYMBOL_GPL(snd_hdac_bus_init_chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) * snd_hdac_bus_stop_chip - disable the whole IRQ and I/Os
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) * @bus: HD-audio core bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) void snd_hdac_bus_stop_chip(struct hdac_bus *bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) if (!bus->chip_init)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) /* disable interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) azx_int_disable(bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) azx_int_clear(bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) /* disable CORB/RIRB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) snd_hdac_bus_stop_cmd_io(bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) /* disable position buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) if (bus->posbuf.addr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) snd_hdac_chip_writel(bus, DPLBASE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) snd_hdac_chip_writel(bus, DPUBASE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) bus->chip_init = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) EXPORT_SYMBOL_GPL(snd_hdac_bus_stop_chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) * snd_hdac_bus_handle_stream_irq - interrupt handler for streams
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) * @bus: HD-audio core bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) * @status: INTSTS register value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) * @ack: callback to be called for woken streams
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) * Returns the bits of handled streams, or zero if no stream is handled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) int snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) void (*ack)(struct hdac_bus *,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) struct hdac_stream *))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) struct hdac_stream *azx_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) u8 sd_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) int handled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) list_for_each_entry(azx_dev, &bus->stream_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) if (status & azx_dev->sd_int_sta_mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) sd_status = snd_hdac_stream_readb(azx_dev, SD_STS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) snd_hdac_stream_writeb(azx_dev, SD_STS, SD_INT_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) handled |= 1 << azx_dev->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) if (!azx_dev->substream || !azx_dev->running ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) !(sd_status & SD_INT_COMPLETE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) if (ack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) ack(bus, azx_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) return handled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) EXPORT_SYMBOL_GPL(snd_hdac_bus_handle_stream_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) * snd_hdac_bus_alloc_stream_pages - allocate BDL and other buffers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) * @bus: HD-audio core bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) * Call this after assigning the all streams.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) * Returns zero for success, or a negative error code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) int snd_hdac_bus_alloc_stream_pages(struct hdac_bus *bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) struct hdac_stream *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) int num_streams = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) int dma_type = bus->dma_type ? bus->dma_type : SNDRV_DMA_TYPE_DEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) list_for_each_entry(s, &bus->stream_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) /* allocate memory for the BDL for each stream */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) err = snd_dma_alloc_pages(dma_type, bus->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) BDL_SIZE, &s->bdl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) num_streams++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) if (WARN_ON(!num_streams))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) /* allocate memory for the position buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) err = snd_dma_alloc_pages(dma_type, bus->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) num_streams * 8, &bus->posbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) list_for_each_entry(s, &bus->stream_list, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) s->posbuf = (__le32 *)(bus->posbuf.area + s->index * 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) /* single page (at least 4096 bytes) must suffice for both ringbuffes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) return snd_dma_alloc_pages(dma_type, bus->dev, PAGE_SIZE, &bus->rb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) EXPORT_SYMBOL_GPL(snd_hdac_bus_alloc_stream_pages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) * snd_hdac_bus_free_stream_pages - release BDL and other buffers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) * @bus: HD-audio core bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) void snd_hdac_bus_free_stream_pages(struct hdac_bus *bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) struct hdac_stream *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) list_for_each_entry(s, &bus->stream_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) if (s->bdl.area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) snd_dma_free_pages(&s->bdl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) if (bus->rb.area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) snd_dma_free_pages(&bus->rb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) if (bus->posbuf.area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) snd_dma_free_pages(&bus->posbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) EXPORT_SYMBOL_GPL(snd_hdac_bus_free_stream_pages);