Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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");