LCOV - code coverage report
Current view: top level - sound/hda - hdac_controller.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 259 0.0 %
Date: 2022-03-28 15:32:58 Functions: 0 15 0.0 %
Branches: 0 124 0.0 %

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

Generated by: LCOV version 1.14