^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) * linux/sound/arm/aaci.c - ARM PrimeCell AACI PL041 driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2003 Deep Blue Solutions Ltd, All Rights Reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Documentation: ARM DDI 0173B
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/amba/bus.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <sound/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <sound/initval.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <sound/ac97_codec.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <sound/pcm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <sound/pcm_params.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include "aaci.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define DRIVER_NAME "aaci-pl041"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define FRAME_PERIOD_US 21
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * PM support is not complete. Turn it off.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #undef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) static void aaci_ac97_select_codec(struct aaci *aaci, struct snd_ac97 *ac97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) u32 v, maincr = aaci->maincr | MAINCR_SCRA(ac97->num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * Ensure that the slot 1/2 RX registers are empty.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) v = readl(aaci->base + AACI_SLFR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) if (v & SLFR_2RXV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) readl(aaci->base + AACI_SL2RX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) if (v & SLFR_1RXV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) readl(aaci->base + AACI_SL1RX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) if (maincr != readl(aaci->base + AACI_MAINCR)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) writel(maincr, aaci->base + AACI_MAINCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) readl(aaci->base + AACI_MAINCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * P29:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * The recommended use of programming the external codec through slot 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * and slot 2 data is to use the channels during setup routines and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * slot register at any other time. The data written into slot 1, slot 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * and slot 12 registers is transmitted only when their corresponding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * SI1TxEn, SI2TxEn and SI12TxEn bits are set in the AACI_MAINCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) static void aaci_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) unsigned short val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) struct aaci *aaci = ac97->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) int timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) u32 v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (ac97->num >= 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) mutex_lock(&aaci->ac97_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) aaci_ac97_select_codec(aaci, ac97);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * P54: You must ensure that AACI_SL2TX is always written
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) * to, if required, before data is written to AACI_SL1TX.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) writel(val << 4, aaci->base + AACI_SL2TX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) writel(reg << 12, aaci->base + AACI_SL1TX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) /* Initially, wait one frame period */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) udelay(FRAME_PERIOD_US);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) /* And then wait an additional eight frame periods for it to be sent */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) timeout = FRAME_PERIOD_US * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) v = readl(aaci->base + AACI_SLFR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) } while ((v & (SLFR_1TXB|SLFR_2TXB)) && --timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) if (v & (SLFR_1TXB|SLFR_2TXB))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) dev_err(&aaci->dev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) "timeout waiting for write to complete\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) mutex_unlock(&aaci->ac97_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^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) * Read an AC'97 register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) static unsigned short aaci_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) struct aaci *aaci = ac97->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) int timeout, retries = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) u32 v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (ac97->num >= 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) return ~0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) mutex_lock(&aaci->ac97_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) aaci_ac97_select_codec(aaci, ac97);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * Write the register address to slot 1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) writel((reg << 12) | (1 << 19), aaci->base + AACI_SL1TX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) /* Initially, wait one frame period */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) udelay(FRAME_PERIOD_US);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) /* And then wait an additional eight frame periods for it to be sent */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) timeout = FRAME_PERIOD_US * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) v = readl(aaci->base + AACI_SLFR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) } while ((v & SLFR_1TXB) && --timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) if (v & SLFR_1TXB) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) dev_err(&aaci->dev->dev, "timeout on slot 1 TX busy\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) v = ~0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) /* Now wait for the response frame */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) udelay(FRAME_PERIOD_US);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) /* And then wait an additional eight frame periods for data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) timeout = FRAME_PERIOD_US * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) cond_resched();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) v = readl(aaci->base + AACI_SLFR) & (SLFR_1RXV|SLFR_2RXV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) } while ((v != (SLFR_1RXV|SLFR_2RXV)) && --timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if (v != (SLFR_1RXV|SLFR_2RXV)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) dev_err(&aaci->dev->dev, "timeout on RX valid\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) v = ~0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) v = readl(aaci->base + AACI_SL1RX) >> 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (v == reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) v = readl(aaci->base + AACI_SL2RX) >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) } else if (--retries) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) dev_warn(&aaci->dev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) "ac97 read back fail. retry\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) dev_warn(&aaci->dev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) "wrong ac97 register read back (%x != %x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) v, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) v = ~0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) } while (retries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) mutex_unlock(&aaci->ac97_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) return v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) aaci_chan_wait_ready(struct aaci_runtime *aacirun, unsigned long mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) int timeout = 5000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) val = readl(aacirun->base + AACI_SR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) } while (val & mask && timeout--);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * Interrupt support.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (mask & ISR_ORINTR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) dev_warn(&aaci->dev->dev, "RX overrun on chan %d\n", channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) writel(ICLR_RXOEC1 << channel, aaci->base + AACI_INTCLR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (mask & ISR_RXTOINTR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) dev_warn(&aaci->dev->dev, "RX timeout on chan %d\n", channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) writel(ICLR_RXTOFEC1 << channel, aaci->base + AACI_INTCLR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (mask & ISR_RXINTR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) struct aaci_runtime *aacirun = &aaci->capture;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) bool period_elapsed = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) void *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (!aacirun->substream || !aacirun->start) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) dev_warn(&aaci->dev->dev, "RX interrupt???\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) writel(0, aacirun->base + AACI_IE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) spin_lock(&aacirun->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) ptr = aacirun->ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) unsigned int len = aacirun->fifo_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) if (aacirun->bytes <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) aacirun->bytes += aacirun->period;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) period_elapsed = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if (!(aacirun->cr & CR_EN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) val = readl(aacirun->base + AACI_SR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) if (!(val & SR_RXHF))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if (!(val & SR_RXFF))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) len >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) aacirun->bytes -= len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) /* reading 16 bytes at a time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) for( ; len > 0; len -= 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) asm(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) "ldmia %1, {r0, r1, r2, r3}\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) "stmia %0!, {r0, r1, r2, r3}"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) : "+r" (ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) : "r" (aacirun->fifo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) : "r0", "r1", "r2", "r3", "cc");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) if (ptr >= aacirun->end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) ptr = aacirun->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) } while(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) aacirun->ptr = ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) spin_unlock(&aacirun->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (period_elapsed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) snd_pcm_period_elapsed(aacirun->substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (mask & ISR_URINTR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) dev_dbg(&aaci->dev->dev, "TX underrun on chan %d\n", channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) writel(ICLR_TXUEC1 << channel, aaci->base + AACI_INTCLR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) if (mask & ISR_TXINTR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) struct aaci_runtime *aacirun = &aaci->playback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) bool period_elapsed = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) void *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if (!aacirun->substream || !aacirun->start) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) dev_warn(&aaci->dev->dev, "TX interrupt???\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) writel(0, aacirun->base + AACI_IE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) spin_lock(&aacirun->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) ptr = aacirun->ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) unsigned int len = aacirun->fifo_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) if (aacirun->bytes <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) aacirun->bytes += aacirun->period;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) period_elapsed = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) if (!(aacirun->cr & CR_EN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) val = readl(aacirun->base + AACI_SR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) if (!(val & SR_TXHE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) if (!(val & SR_TXFE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) len >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) aacirun->bytes -= len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) /* writing 16 bytes at a time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) for ( ; len > 0; len -= 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) asm(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) "ldmia %0!, {r0, r1, r2, r3}\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) "stmia %1, {r0, r1, r2, r3}"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) : "+r" (ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) : "r" (aacirun->fifo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) : "r0", "r1", "r2", "r3", "cc");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) if (ptr >= aacirun->end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) ptr = aacirun->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) } while (1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) aacirun->ptr = ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) spin_unlock(&aacirun->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (period_elapsed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) snd_pcm_period_elapsed(aacirun->substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) static irqreturn_t aaci_irq(int irq, void *devid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) struct aaci *aaci = devid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) u32 mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) mask = readl(aaci->base + AACI_ALLINTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) if (mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) u32 m = mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) for (i = 0; i < 4; i++, m >>= 7) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (m & 0x7f) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) aaci_fifo_irq(aaci, i, m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) return mask ? IRQ_HANDLED : IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) * ALSA support.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) static const struct snd_pcm_hardware aaci_hw_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) .info = SNDRV_PCM_INFO_MMAP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) SNDRV_PCM_INFO_MMAP_VALID |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) SNDRV_PCM_INFO_INTERLEAVED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) SNDRV_PCM_INFO_BLOCK_TRANSFER |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) SNDRV_PCM_INFO_RESUME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) * ALSA doesn't support 18-bit or 20-bit packed into 32-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) * words. It also doesn't support 12-bit at all.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) .formats = SNDRV_PCM_FMTBIT_S16_LE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) /* rates are setup from the AC'97 codec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) .channels_min = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) .channels_max = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) .buffer_bytes_max = 64 * 1024,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) .period_bytes_min = 256,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) .period_bytes_max = PAGE_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) .periods_min = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) .periods_max = PAGE_SIZE / 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) * We can support two and four channel audio. Unfortunately
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) * six channel audio requires a non-standard channel ordering:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) * 2 -> FL(3), FR(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) * 4 -> FL(3), FR(4), SL(7), SR(8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) * 6 -> FL(3), FR(4), SL(7), SR(8), C(6), LFE(9) (required)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) * FL(3), FR(4), C(6), SL(7), SR(8), LFE(9) (actual)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) * This requires an ALSA configuration file to correct.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) static int aaci_rule_channels(struct snd_pcm_hw_params *p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) struct snd_pcm_hw_rule *rule)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) static const unsigned int channel_list[] = { 2, 4, 6 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) struct aaci *aaci = rule->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) unsigned int mask = 1 << 0, slots;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) /* pcms[0] is the our 5.1 PCM instance. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) slots = aaci->ac97_bus->pcms[0].r[0].slots;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) if (slots & (1 << AC97_SLOT_PCM_SLEFT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) mask |= 1 << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) if (slots & (1 << AC97_SLOT_LFE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) mask |= 1 << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) return snd_interval_list(hw_param_interval(p, rule->var),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) ARRAY_SIZE(channel_list), channel_list, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) static int aaci_pcm_open(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) struct aaci *aaci = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) struct aaci_runtime *aacirun;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) aacirun = &aaci->playback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) aacirun = &aaci->capture;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) aacirun->substream = substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) runtime->private_data = aacirun;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) runtime->hw = aaci_hw_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) runtime->hw.rates = aacirun->pcm->rates;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) snd_pcm_limit_hw_rates(runtime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) runtime->hw.channels_max = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) /* Add rule describing channel dependency. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) ret = snd_pcm_hw_rule_add(substream->runtime, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) SNDRV_PCM_HW_PARAM_CHANNELS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) aaci_rule_channels, aaci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) SNDRV_PCM_HW_PARAM_CHANNELS, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) if (aacirun->pcm->r[1].slots)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) snd_ac97_pcm_double_rate_rules(runtime);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) * ALSA wants the byte-size of the FIFOs. As we only support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) * 16-bit samples, this is twice the FIFO depth irrespective
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) * of whether it's in compact mode or not.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) runtime->hw.fifo_size = aaci->fifo_depth * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) mutex_lock(&aaci->irq_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) if (!aaci->users++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) ret = request_irq(aaci->dev->irq[0], aaci_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) IRQF_SHARED, DRIVER_NAME, aaci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) aaci->users--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) mutex_unlock(&aaci->irq_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) * Common ALSA stuff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) static int aaci_pcm_close(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) struct aaci *aaci = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) struct aaci_runtime *aacirun = substream->runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) WARN_ON(aacirun->cr & CR_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) aacirun->substream = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) mutex_lock(&aaci->irq_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if (!--aaci->users)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) free_irq(aaci->dev->irq[0], aaci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) mutex_unlock(&aaci->irq_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) static int aaci_pcm_hw_free(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) struct aaci_runtime *aacirun = substream->runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) * This must not be called with the device enabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) WARN_ON(aacirun->cr & CR_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) if (aacirun->pcm_open)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) snd_ac97_pcm_close(aacirun->pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) aacirun->pcm_open = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) /* Channel to slot mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) static const u32 channels_to_slotmask[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) [2] = CR_SL3 | CR_SL4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) [4] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) [6] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8 | CR_SL6 | CR_SL9,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) static int aaci_pcm_hw_params(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) struct snd_pcm_hw_params *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) struct aaci_runtime *aacirun = substream->runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) struct aaci *aaci = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) unsigned int channels = params_channels(params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) unsigned int rate = params_rate(params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) int dbl = rate > 48000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) aaci_pcm_hw_free(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) if (aacirun->pcm_open) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) snd_ac97_pcm_close(aacirun->pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) aacirun->pcm_open = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) /* channels is already limited to 2, 4, or 6 by aaci_rule_channels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) if (dbl && channels != 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) err = snd_ac97_pcm_open(aacirun->pcm, rate, channels,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) aacirun->pcm->r[dbl].slots);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) aacirun->pcm_open = err == 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) aacirun->cr = CR_FEN | CR_COMPACT | CR_SZ16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) aacirun->cr |= channels_to_slotmask[channels + dbl * 2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) * fifo_bytes is the number of bytes we transfer to/from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) * the FIFO, including padding. So that's x4. As we're
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) * in compact mode, the FIFO is half the size.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) aacirun->fifo_bytes = aaci->fifo_depth * 4 / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) static int aaci_pcm_prepare(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) struct aaci_runtime *aacirun = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) aacirun->period = snd_pcm_lib_period_bytes(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) aacirun->start = runtime->dma_area;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) aacirun->end = aacirun->start + snd_pcm_lib_buffer_bytes(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) aacirun->ptr = aacirun->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) aacirun->bytes = aacirun->period;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) static snd_pcm_uframes_t aaci_pcm_pointer(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) struct aaci_runtime *aacirun = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) ssize_t bytes = aacirun->ptr - aacirun->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) return bytes_to_frames(runtime, bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) * Playback specific ALSA stuff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) static void aaci_pcm_playback_stop(struct aaci_runtime *aacirun)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) u32 ie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) ie = readl(aacirun->base + AACI_IE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) ie &= ~(IE_URIE|IE_TXIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) writel(ie, aacirun->base + AACI_IE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) aacirun->cr &= ~CR_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) aaci_chan_wait_ready(aacirun, SR_TXB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) writel(aacirun->cr, aacirun->base + AACI_TXCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) static void aaci_pcm_playback_start(struct aaci_runtime *aacirun)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) u32 ie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) aaci_chan_wait_ready(aacirun, SR_TXB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) aacirun->cr |= CR_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) ie = readl(aacirun->base + AACI_IE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) ie |= IE_URIE | IE_TXIE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) writel(ie, aacirun->base + AACI_IE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) writel(aacirun->cr, aacirun->base + AACI_TXCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) static int aaci_pcm_playback_trigger(struct snd_pcm_substream *substream, int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) struct aaci_runtime *aacirun = substream->runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) spin_lock_irqsave(&aacirun->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) case SNDRV_PCM_TRIGGER_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) aaci_pcm_playback_start(aacirun);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) case SNDRV_PCM_TRIGGER_RESUME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) aaci_pcm_playback_start(aacirun);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) case SNDRV_PCM_TRIGGER_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) aaci_pcm_playback_stop(aacirun);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) case SNDRV_PCM_TRIGGER_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) aaci_pcm_playback_stop(aacirun);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) spin_unlock_irqrestore(&aacirun->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) static const struct snd_pcm_ops aaci_playback_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) .open = aaci_pcm_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) .close = aaci_pcm_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) .hw_params = aaci_pcm_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) .hw_free = aaci_pcm_hw_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) .prepare = aaci_pcm_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) .trigger = aaci_pcm_playback_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) .pointer = aaci_pcm_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) static void aaci_pcm_capture_stop(struct aaci_runtime *aacirun)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) u32 ie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) aaci_chan_wait_ready(aacirun, SR_RXB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) ie = readl(aacirun->base + AACI_IE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) ie &= ~(IE_ORIE | IE_RXIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) writel(ie, aacirun->base+AACI_IE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) aacirun->cr &= ~CR_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) writel(aacirun->cr, aacirun->base + AACI_RXCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) static void aaci_pcm_capture_start(struct aaci_runtime *aacirun)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) u32 ie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) aaci_chan_wait_ready(aacirun, SR_RXB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) #ifdef DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) /* RX Timeout value: bits 28:17 in RXCR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) aacirun->cr |= 0xf << 17;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) aacirun->cr |= CR_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) writel(aacirun->cr, aacirun->base + AACI_RXCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) ie = readl(aacirun->base + AACI_IE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) ie |= IE_ORIE |IE_RXIE; // overrun and rx interrupt -- half full
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) writel(ie, aacirun->base + AACI_IE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) static int aaci_pcm_capture_trigger(struct snd_pcm_substream *substream, int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) struct aaci_runtime *aacirun = substream->runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) spin_lock_irqsave(&aacirun->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) case SNDRV_PCM_TRIGGER_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) aaci_pcm_capture_start(aacirun);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) case SNDRV_PCM_TRIGGER_RESUME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) aaci_pcm_capture_start(aacirun);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) case SNDRV_PCM_TRIGGER_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) aaci_pcm_capture_stop(aacirun);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) case SNDRV_PCM_TRIGGER_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) aaci_pcm_capture_stop(aacirun);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) spin_unlock_irqrestore(&aacirun->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) static int aaci_pcm_capture_prepare(struct snd_pcm_substream *substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) struct snd_pcm_runtime *runtime = substream->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) struct aaci *aaci = substream->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) aaci_pcm_prepare(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) /* allow changing of sample rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) aaci_ac97_write(aaci->ac97, AC97_EXTENDED_STATUS, 0x0001); /* VRA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) aaci_ac97_write(aaci->ac97, AC97_PCM_LR_ADC_RATE, runtime->rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) aaci_ac97_write(aaci->ac97, AC97_PCM_MIC_ADC_RATE, runtime->rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) /* Record select: Mic: 0, Aux: 3, Line: 4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) aaci_ac97_write(aaci->ac97, AC97_REC_SEL, 0x0404);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) static const struct snd_pcm_ops aaci_capture_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) .open = aaci_pcm_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) .close = aaci_pcm_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) .hw_params = aaci_pcm_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) .hw_free = aaci_pcm_hw_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) .prepare = aaci_pcm_capture_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) .trigger = aaci_pcm_capture_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) .pointer = aaci_pcm_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) * Power Management.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) static int aaci_do_suspend(struct snd_card *card)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) struct aaci *aaci = card->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) snd_power_change_state(card, SNDRV_CTL_POWER_D3cold);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) static int aaci_do_resume(struct snd_card *card)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) snd_power_change_state(card, SNDRV_CTL_POWER_D0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) static int aaci_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) struct snd_card *card = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) return card ? aaci_do_suspend(card) : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) static int aaci_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) struct snd_card *card = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) return card ? aaci_do_resume(card) : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) static SIMPLE_DEV_PM_OPS(aaci_dev_pm_ops, aaci_suspend, aaci_resume);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) #define AACI_DEV_PM_OPS (&aaci_dev_pm_ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) #define AACI_DEV_PM_OPS NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) static const struct ac97_pcm ac97_defs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) [0] = { /* Front PCM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) .exclusive = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) .r = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) [0] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) .slots = (1 << AC97_SLOT_PCM_LEFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) (1 << AC97_SLOT_PCM_RIGHT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) (1 << AC97_SLOT_PCM_CENTER) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) (1 << AC97_SLOT_PCM_SLEFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) (1 << AC97_SLOT_PCM_SRIGHT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) (1 << AC97_SLOT_LFE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) [1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) .slots = (1 << AC97_SLOT_PCM_LEFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) (1 << AC97_SLOT_PCM_RIGHT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) (1 << AC97_SLOT_PCM_LEFT_0) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) (1 << AC97_SLOT_PCM_RIGHT_0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) [1] = { /* PCM in */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) .stream = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) .exclusive = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) .r = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) [0] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) .slots = (1 << AC97_SLOT_PCM_LEFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) (1 << AC97_SLOT_PCM_RIGHT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) [2] = { /* Mic in */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) .stream = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) .exclusive = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) .r = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) [0] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) .slots = (1 << AC97_SLOT_MIC),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) static const struct snd_ac97_bus_ops aaci_bus_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) .write = aaci_ac97_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) .read = aaci_ac97_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) static int aaci_probe_ac97(struct aaci *aaci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) struct snd_ac97_template ac97_template;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) struct snd_ac97_bus *ac97_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) struct snd_ac97 *ac97;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) * Assert AACIRESET for 2us
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) writel(0, aaci->base + AACI_RESET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) udelay(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) writel(RESET_NRST, aaci->base + AACI_RESET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) * Give the AC'97 codec more than enough time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) * to wake up. (42us = ~2 frames at 48kHz.)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) udelay(FRAME_PERIOD_US * 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) ret = snd_ac97_bus(aaci->card, 0, &aaci_bus_ops, aaci, &ac97_bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) ac97_bus->clock = 48000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) aaci->ac97_bus = ac97_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) memset(&ac97_template, 0, sizeof(struct snd_ac97_template));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) ac97_template.private_data = aaci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) ac97_template.num = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) ac97_template.scaps = AC97_SCAP_SKIP_MODEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) ret = snd_ac97_mixer(ac97_bus, &ac97_template, &ac97);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) aaci->ac97 = ac97;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) * Disable AC97 PC Beep input on audio codecs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) if (ac97_is_audio(ac97))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) snd_ac97_write_cache(ac97, AC97_PC_BEEP, 0x801e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) ret = snd_ac97_pcm_assign(ac97_bus, ARRAY_SIZE(ac97_defs), ac97_defs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) aaci->playback.pcm = &ac97_bus->pcms[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) aaci->capture.pcm = &ac97_bus->pcms[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) static void aaci_free_card(struct snd_card *card)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) struct aaci *aaci = card->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) iounmap(aaci->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) static struct aaci *aaci_init_card(struct amba_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) struct aaci *aaci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) struct snd_card *card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) err = snd_card_new(&dev->dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) THIS_MODULE, sizeof(struct aaci), &card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) card->private_free = aaci_free_card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) strlcpy(card->driver, DRIVER_NAME, sizeof(card->driver));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) strlcpy(card->shortname, "ARM AC'97 Interface", sizeof(card->shortname));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) snprintf(card->longname, sizeof(card->longname),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) "%s PL%03x rev%u at 0x%08llx, irq %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) card->shortname, amba_part(dev), amba_rev(dev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) (unsigned long long)dev->res.start, dev->irq[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) aaci = card->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) mutex_init(&aaci->ac97_sem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) mutex_init(&aaci->irq_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) aaci->card = card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) aaci->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) /* Set MAINCR to allow slot 1 and 2 data IO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) aaci->maincr = MAINCR_IE | MAINCR_SL1RXEN | MAINCR_SL1TXEN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) MAINCR_SL2RXEN | MAINCR_SL2TXEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) return aaci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) static int aaci_init_pcm(struct aaci *aaci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) struct snd_pcm *pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) ret = snd_pcm_new(aaci->card, "AACI AC'97", 0, 1, 1, &pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) if (ret == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) aaci->pcm = pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) pcm->private_data = aaci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) pcm->info_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) strlcpy(pcm->name, DRIVER_NAME, sizeof(pcm->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &aaci_playback_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &aaci_capture_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) aaci->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) 0, 64 * 1024);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) static unsigned int aaci_size_fifo(struct aaci *aaci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) struct aaci_runtime *aacirun = &aaci->playback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) * Enable the channel, but don't assign it to any slots, so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) * it won't empty onto the AC'97 link.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) writel(CR_FEN | CR_SZ16 | CR_EN, aacirun->base + AACI_TXCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) for (i = 0; !(readl(aacirun->base + AACI_SR) & SR_TXFF) && i < 4096; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) writel(0, aacirun->fifo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) writel(0, aacirun->base + AACI_TXCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) * Re-initialise the AACI after the FIFO depth test, to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) * ensure that the FIFOs are empty. Unfortunately, merely
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) * disabling the channel doesn't clear the FIFO.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) writel(aaci->maincr & ~MAINCR_IE, aaci->base + AACI_MAINCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) readl(aaci->base + AACI_MAINCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) writel(aaci->maincr, aaci->base + AACI_MAINCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) * If we hit 4096 entries, we failed. Go back to the specified
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) * fifo depth.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) if (i == 4096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) i = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) static int aaci_probe(struct amba_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) const struct amba_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) struct aaci *aaci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) int ret, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) ret = amba_request_regions(dev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) aaci = aaci_init_card(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) if (!aaci) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) aaci->base = ioremap(dev->res.start, resource_size(&dev->res));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) if (!aaci->base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) * Playback uses AACI channel 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) spin_lock_init(&aaci->playback.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) aaci->playback.base = aaci->base + AACI_CSCH1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) aaci->playback.fifo = aaci->base + AACI_DR1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) * Capture uses AACI channel 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) spin_lock_init(&aaci->capture.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) aaci->capture.base = aaci->base + AACI_CSCH1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) aaci->capture.fifo = aaci->base + AACI_DR1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) void __iomem *base = aaci->base + i * 0x14;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) writel(0, base + AACI_IE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) writel(0, base + AACI_TXCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) writel(0, base + AACI_RXCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) writel(0x1fff, aaci->base + AACI_INTCLR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) writel(aaci->maincr, aaci->base + AACI_MAINCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) * Fix: ac97 read back fail errors by reading
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) * from any arbitrary aaci register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) readl(aaci->base + AACI_CSCH1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) ret = aaci_probe_ac97(aaci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) * Size the FIFOs (must be multiple of 16).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) * This is the number of entries in the FIFO.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) aaci->fifo_depth = aaci_size_fifo(aaci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) if (aaci->fifo_depth & 15) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) printk(KERN_WARNING "AACI: FIFO depth %d not supported\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) aaci->fifo_depth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) ret = aaci_init_pcm(aaci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) ret = snd_card_register(aaci->card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) if (ret == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) dev_info(&dev->dev, "%s\n", aaci->card->longname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) dev_info(&dev->dev, "FIFO %u entries\n", aaci->fifo_depth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) amba_set_drvdata(dev, aaci->card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) if (aaci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) snd_card_free(aaci->card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) amba_release_regions(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) static void aaci_remove(struct amba_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) struct snd_card *card = amba_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) if (card) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) struct aaci *aaci = card->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) writel(0, aaci->base + AACI_MAINCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) snd_card_free(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) amba_release_regions(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) static struct amba_id aaci_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) .id = 0x00041041,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) .mask = 0x000fffff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) { 0, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) MODULE_DEVICE_TABLE(amba, aaci_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) static struct amba_driver aaci_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) .drv = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) .name = DRIVER_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) .pm = AACI_DEV_PM_OPS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) .probe = aaci_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) .remove = aaci_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) .id_table = aaci_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) module_amba_driver(aaci_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) MODULE_DESCRIPTION("ARM PrimeCell PL041 Advanced Audio CODEC Interface driver");