xref: /openbmc/linux/sound/soc/pxa/pxa2xx-ac97.c (revision 942de47b)
175b41027SLiam Girdwood /*
275b41027SLiam Girdwood  * linux/sound/pxa2xx-ac97.c -- AC97 support for the Intel PXA2xx chip.
375b41027SLiam Girdwood  *
475b41027SLiam Girdwood  * Author:	Nicolas Pitre
575b41027SLiam Girdwood  * Created:	Dec 02, 2004
675b41027SLiam Girdwood  * Copyright:	MontaVista Software Inc.
775b41027SLiam Girdwood  *
875b41027SLiam Girdwood  * This program is free software; you can redistribute it and/or modify
975b41027SLiam Girdwood  * it under the terms of the GNU General Public License version 2 as
1075b41027SLiam Girdwood  * published by the Free Software Foundation.
1175b41027SLiam Girdwood  */
1275b41027SLiam Girdwood 
1375b41027SLiam Girdwood #include <linux/init.h>
1475b41027SLiam Girdwood #include <linux/module.h>
1575b41027SLiam Girdwood #include <linux/platform_device.h>
1675b41027SLiam Girdwood #include <linux/interrupt.h>
1775b41027SLiam Girdwood #include <linux/wait.h>
18942de47bSMark Brown #include <linux/clk.h>
1975b41027SLiam Girdwood #include <linux/delay.h>
2075b41027SLiam Girdwood 
2175b41027SLiam Girdwood #include <sound/core.h>
2275b41027SLiam Girdwood #include <sound/pcm.h>
2375b41027SLiam Girdwood #include <sound/ac97_codec.h>
2475b41027SLiam Girdwood #include <sound/initval.h>
2575b41027SLiam Girdwood #include <sound/soc.h>
2675b41027SLiam Girdwood 
2775b41027SLiam Girdwood #include <asm/irq.h>
2875b41027SLiam Girdwood #include <linux/mutex.h>
2975b41027SLiam Girdwood #include <asm/hardware.h>
3075b41027SLiam Girdwood #include <asm/arch/pxa-regs.h>
3175b41027SLiam Girdwood #include <asm/arch/audio.h>
3275b41027SLiam Girdwood 
3375b41027SLiam Girdwood #include "pxa2xx-pcm.h"
34596ce32bSLiam Girdwood #include "pxa2xx-ac97.h"
3575b41027SLiam Girdwood 
3675b41027SLiam Girdwood static DEFINE_MUTEX(car_mutex);
3775b41027SLiam Girdwood static DECLARE_WAIT_QUEUE_HEAD(gsr_wq);
3875b41027SLiam Girdwood static volatile long gsr_bits;
39942de47bSMark Brown static struct clk *ac97_clk;
40942de47bSMark Brown #ifdef CONFIG_PXA27x
41942de47bSMark Brown static struct clk *ac97conf_clk;
42942de47bSMark Brown #endif
4375b41027SLiam Girdwood 
4475b41027SLiam Girdwood /*
4575b41027SLiam Girdwood  * Beware PXA27x bugs:
4675b41027SLiam Girdwood  *
4775b41027SLiam Girdwood  *   o Slot 12 read from modem space will hang controller.
4875b41027SLiam Girdwood  *   o CDONE, SDONE interrupt fails after any slot 12 IO.
4975b41027SLiam Girdwood  *
5075b41027SLiam Girdwood  * We therefore have an hybrid approach for waiting on SDONE (interrupt or
5175b41027SLiam Girdwood  * 1 jiffy timeout if interrupt never comes).
5275b41027SLiam Girdwood  */
5375b41027SLiam Girdwood 
5475b41027SLiam Girdwood static unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97,
5575b41027SLiam Girdwood 	unsigned short reg)
5675b41027SLiam Girdwood {
5775b41027SLiam Girdwood 	unsigned short val = -1;
5875b41027SLiam Girdwood 	volatile u32 *reg_addr;
5975b41027SLiam Girdwood 
6075b41027SLiam Girdwood 	mutex_lock(&car_mutex);
6175b41027SLiam Girdwood 
6275b41027SLiam Girdwood 	/* set up primary or secondary codec/modem space */
6375b41027SLiam Girdwood #ifdef CONFIG_PXA27x
6475b41027SLiam Girdwood 	reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
6575b41027SLiam Girdwood #else
6675b41027SLiam Girdwood 	if (reg == AC97_GPIO_STATUS)
6775b41027SLiam Girdwood 		reg_addr = ac97->num ? &SMC_REG_BASE : &PMC_REG_BASE;
6875b41027SLiam Girdwood 	else
6975b41027SLiam Girdwood 		reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
7075b41027SLiam Girdwood #endif
7175b41027SLiam Girdwood 	reg_addr += (reg >> 1);
7275b41027SLiam Girdwood 
7375b41027SLiam Girdwood #ifndef CONFIG_PXA27x
7475b41027SLiam Girdwood 	if (reg == AC97_GPIO_STATUS) {
7575b41027SLiam Girdwood 		/* read from controller cache */
7675b41027SLiam Girdwood 		val = *reg_addr;
7775b41027SLiam Girdwood 		goto out;
7875b41027SLiam Girdwood 	}
7975b41027SLiam Girdwood #endif
8075b41027SLiam Girdwood 
8175b41027SLiam Girdwood 	/* start read access across the ac97 link */
8275b41027SLiam Girdwood 	GSR = GSR_CDONE | GSR_SDONE;
8375b41027SLiam Girdwood 	gsr_bits = 0;
8475b41027SLiam Girdwood 	val = *reg_addr;
8575b41027SLiam Girdwood 
8675b41027SLiam Girdwood 	wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1);
8775b41027SLiam Girdwood 	if (!((GSR | gsr_bits) & GSR_SDONE)) {
8875b41027SLiam Girdwood 		printk(KERN_ERR "%s: read error (ac97_reg=%x GSR=%#lx)\n",
8975b41027SLiam Girdwood 				__FUNCTION__, reg, GSR | gsr_bits);
9075b41027SLiam Girdwood 		val = -1;
9175b41027SLiam Girdwood 		goto out;
9275b41027SLiam Girdwood 	}
9375b41027SLiam Girdwood 
9475b41027SLiam Girdwood 	/* valid data now */
9575b41027SLiam Girdwood 	GSR = GSR_CDONE | GSR_SDONE;
9675b41027SLiam Girdwood 	gsr_bits = 0;
9775b41027SLiam Girdwood 	val = *reg_addr;
9875b41027SLiam Girdwood 	/* but we've just started another cycle... */
9975b41027SLiam Girdwood 	wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1);
10075b41027SLiam Girdwood 
10175b41027SLiam Girdwood out:	mutex_unlock(&car_mutex);
10275b41027SLiam Girdwood 	return val;
10375b41027SLiam Girdwood }
10475b41027SLiam Girdwood 
10575b41027SLiam Girdwood static void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
10675b41027SLiam Girdwood 	unsigned short val)
10775b41027SLiam Girdwood {
10875b41027SLiam Girdwood 	volatile u32 *reg_addr;
10975b41027SLiam Girdwood 
11075b41027SLiam Girdwood 	mutex_lock(&car_mutex);
11175b41027SLiam Girdwood 
11275b41027SLiam Girdwood 	/* set up primary or secondary codec/modem space */
11375b41027SLiam Girdwood #ifdef CONFIG_PXA27x
11475b41027SLiam Girdwood 	reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
11575b41027SLiam Girdwood #else
11675b41027SLiam Girdwood 	if (reg == AC97_GPIO_STATUS)
11775b41027SLiam Girdwood 		reg_addr = ac97->num ? &SMC_REG_BASE : &PMC_REG_BASE;
11875b41027SLiam Girdwood 	else
11975b41027SLiam Girdwood 		reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
12075b41027SLiam Girdwood #endif
12175b41027SLiam Girdwood 	reg_addr += (reg >> 1);
12275b41027SLiam Girdwood 
12375b41027SLiam Girdwood 	GSR = GSR_CDONE | GSR_SDONE;
12475b41027SLiam Girdwood 	gsr_bits = 0;
12575b41027SLiam Girdwood 	*reg_addr = val;
12675b41027SLiam Girdwood 	wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_CDONE, 1);
12775b41027SLiam Girdwood 	if (!((GSR | gsr_bits) & GSR_CDONE))
12875b41027SLiam Girdwood 		printk(KERN_ERR "%s: write error (ac97_reg=%x GSR=%#lx)\n",
12975b41027SLiam Girdwood 				__FUNCTION__, reg, GSR | gsr_bits);
13075b41027SLiam Girdwood 
13175b41027SLiam Girdwood 	mutex_unlock(&car_mutex);
13275b41027SLiam Girdwood }
13375b41027SLiam Girdwood 
13475b41027SLiam Girdwood static void pxa2xx_ac97_warm_reset(struct snd_ac97 *ac97)
13575b41027SLiam Girdwood {
13675b41027SLiam Girdwood 	gsr_bits = 0;
13775b41027SLiam Girdwood 
13875b41027SLiam Girdwood #ifdef CONFIG_PXA27x
13975b41027SLiam Girdwood 	/* warm reset broken on Bulverde,
14075b41027SLiam Girdwood 	   so manually keep AC97 reset high */
14175b41027SLiam Girdwood 	pxa_gpio_mode(113 | GPIO_OUT | GPIO_DFLT_HIGH);
14275b41027SLiam Girdwood 	udelay(10);
14375b41027SLiam Girdwood 	GCR |= GCR_WARM_RST;
14475b41027SLiam Girdwood 	pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
14575b41027SLiam Girdwood 	udelay(500);
14675b41027SLiam Girdwood #else
14775b41027SLiam Girdwood 	GCR |= GCR_WARM_RST | GCR_PRIRDY_IEN | GCR_SECRDY_IEN;
14875b41027SLiam Girdwood 	wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1);
14975b41027SLiam Girdwood #endif
15075b41027SLiam Girdwood 
15175b41027SLiam Girdwood 	if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)))
15275b41027SLiam Girdwood 		printk(KERN_INFO "%s: warm reset timeout (GSR=%#lx)\n",
15375b41027SLiam Girdwood 				 __FUNCTION__, gsr_bits);
15475b41027SLiam Girdwood 
15575b41027SLiam Girdwood 	GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
15675b41027SLiam Girdwood 	GCR |= GCR_SDONE_IE|GCR_CDONE_IE;
15775b41027SLiam Girdwood }
15875b41027SLiam Girdwood 
15975b41027SLiam Girdwood static void pxa2xx_ac97_cold_reset(struct snd_ac97 *ac97)
16075b41027SLiam Girdwood {
16175b41027SLiam Girdwood 	GCR &=  GCR_COLD_RST;  /* clear everything but nCRST */
16275b41027SLiam Girdwood 	GCR &= ~GCR_COLD_RST;  /* then assert nCRST */
16375b41027SLiam Girdwood 
16475b41027SLiam Girdwood 	gsr_bits = 0;
16575b41027SLiam Girdwood #ifdef CONFIG_PXA27x
16675b41027SLiam Girdwood 	/* PXA27x Developers Manual section 13.5.2.2.1 */
167942de47bSMark Brown 	clk_enable(ac97conf_clk);
16875b41027SLiam Girdwood 	udelay(5);
169942de47bSMark Brown 	clk_disable(ac97conf_clk);
17075b41027SLiam Girdwood 	GCR = GCR_COLD_RST;
17175b41027SLiam Girdwood 	udelay(50);
17275b41027SLiam Girdwood #else
17375b41027SLiam Girdwood 	GCR = GCR_COLD_RST;
17475b41027SLiam Girdwood 	GCR |= GCR_CDONE_IE|GCR_SDONE_IE;
17575b41027SLiam Girdwood 	wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1);
17675b41027SLiam Girdwood #endif
17775b41027SLiam Girdwood 
17875b41027SLiam Girdwood 	if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)))
17975b41027SLiam Girdwood 		printk(KERN_INFO "%s: cold reset timeout (GSR=%#lx)\n",
18075b41027SLiam Girdwood 				 __FUNCTION__, gsr_bits);
18175b41027SLiam Girdwood 
18275b41027SLiam Girdwood 	GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
18375b41027SLiam Girdwood 	GCR |= GCR_SDONE_IE|GCR_CDONE_IE;
18475b41027SLiam Girdwood }
18575b41027SLiam Girdwood 
18675b41027SLiam Girdwood static irqreturn_t pxa2xx_ac97_irq(int irq, void *dev_id)
18775b41027SLiam Girdwood {
18875b41027SLiam Girdwood 	long status;
18975b41027SLiam Girdwood 
19075b41027SLiam Girdwood 	status = GSR;
19175b41027SLiam Girdwood 	if (status) {
19275b41027SLiam Girdwood 		GSR = status;
19375b41027SLiam Girdwood 		gsr_bits |= status;
19475b41027SLiam Girdwood 		wake_up(&gsr_wq);
19575b41027SLiam Girdwood 
19675b41027SLiam Girdwood #ifdef CONFIG_PXA27x
19775b41027SLiam Girdwood 		/* Although we don't use those we still need to clear them
19875b41027SLiam Girdwood 		   since they tend to spuriously trigger when MMC is used
19975b41027SLiam Girdwood 		   (hardware bug? go figure)... */
20075b41027SLiam Girdwood 		MISR = MISR_EOC;
20175b41027SLiam Girdwood 		PISR = PISR_EOC;
20275b41027SLiam Girdwood 		MCSR = MCSR_EOC;
20375b41027SLiam Girdwood #endif
20475b41027SLiam Girdwood 
20575b41027SLiam Girdwood 		return IRQ_HANDLED;
20675b41027SLiam Girdwood 	}
20775b41027SLiam Girdwood 
20875b41027SLiam Girdwood 	return IRQ_NONE;
20975b41027SLiam Girdwood }
21075b41027SLiam Girdwood 
21175b41027SLiam Girdwood struct snd_ac97_bus_ops soc_ac97_ops = {
21275b41027SLiam Girdwood 	.read	= pxa2xx_ac97_read,
21375b41027SLiam Girdwood 	.write	= pxa2xx_ac97_write,
21475b41027SLiam Girdwood 	.warm_reset	= pxa2xx_ac97_warm_reset,
21575b41027SLiam Girdwood 	.reset	= pxa2xx_ac97_cold_reset,
21675b41027SLiam Girdwood };
21775b41027SLiam Girdwood 
21875b41027SLiam Girdwood static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_out = {
21975b41027SLiam Girdwood 	.name			= "AC97 PCM Stereo out",
22075b41027SLiam Girdwood 	.dev_addr		= __PREG(PCDR),
22175b41027SLiam Girdwood 	.drcmr			= &DRCMRTXPCDR,
22275b41027SLiam Girdwood 	.dcmd			= DCMD_INCSRCADDR | DCMD_FLOWTRG |
22375b41027SLiam Girdwood 				  DCMD_BURST32 | DCMD_WIDTH4,
22475b41027SLiam Girdwood };
22575b41027SLiam Girdwood 
22675b41027SLiam Girdwood static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_in = {
22775b41027SLiam Girdwood 	.name			= "AC97 PCM Stereo in",
22875b41027SLiam Girdwood 	.dev_addr		= __PREG(PCDR),
22975b41027SLiam Girdwood 	.drcmr			= &DRCMRRXPCDR,
23075b41027SLiam Girdwood 	.dcmd			= DCMD_INCTRGADDR | DCMD_FLOWSRC |
23175b41027SLiam Girdwood 				  DCMD_BURST32 | DCMD_WIDTH4,
23275b41027SLiam Girdwood };
23375b41027SLiam Girdwood 
23475b41027SLiam Girdwood static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_aux_mono_out = {
23575b41027SLiam Girdwood 	.name			= "AC97 Aux PCM (Slot 5) Mono out",
23675b41027SLiam Girdwood 	.dev_addr		= __PREG(MODR),
23775b41027SLiam Girdwood 	.drcmr			= &DRCMRTXMODR,
23875b41027SLiam Girdwood 	.dcmd			= DCMD_INCSRCADDR | DCMD_FLOWTRG |
23975b41027SLiam Girdwood 				  DCMD_BURST16 | DCMD_WIDTH2,
24075b41027SLiam Girdwood };
24175b41027SLiam Girdwood 
24275b41027SLiam Girdwood static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_aux_mono_in = {
24375b41027SLiam Girdwood 	.name			= "AC97 Aux PCM (Slot 5) Mono in",
24475b41027SLiam Girdwood 	.dev_addr		= __PREG(MODR),
24575b41027SLiam Girdwood 	.drcmr			= &DRCMRRXMODR,
24675b41027SLiam Girdwood 	.dcmd			= DCMD_INCTRGADDR | DCMD_FLOWSRC |
24775b41027SLiam Girdwood 				  DCMD_BURST16 | DCMD_WIDTH2,
24875b41027SLiam Girdwood };
24975b41027SLiam Girdwood 
25075b41027SLiam Girdwood static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_mic_mono_in = {
25175b41027SLiam Girdwood 	.name			= "AC97 Mic PCM (Slot 6) Mono in",
25275b41027SLiam Girdwood 	.dev_addr		= __PREG(MCDR),
25375b41027SLiam Girdwood 	.drcmr			= &DRCMRRXMCDR,
25475b41027SLiam Girdwood 	.dcmd			= DCMD_INCTRGADDR | DCMD_FLOWSRC |
25575b41027SLiam Girdwood 				  DCMD_BURST16 | DCMD_WIDTH2,
25675b41027SLiam Girdwood };
25775b41027SLiam Girdwood 
25875b41027SLiam Girdwood #ifdef CONFIG_PM
25975b41027SLiam Girdwood static int pxa2xx_ac97_suspend(struct platform_device *pdev,
26075b41027SLiam Girdwood 	struct snd_soc_cpu_dai *dai)
26175b41027SLiam Girdwood {
26275b41027SLiam Girdwood 	GCR |= GCR_ACLINK_OFF;
263942de47bSMark Brown 	clk_disable(ac97_clk);
26475b41027SLiam Girdwood 	return 0;
26575b41027SLiam Girdwood }
26675b41027SLiam Girdwood 
26775b41027SLiam Girdwood static int pxa2xx_ac97_resume(struct platform_device *pdev,
26875b41027SLiam Girdwood 	struct snd_soc_cpu_dai *dai)
26975b41027SLiam Girdwood {
27075b41027SLiam Girdwood 	pxa_gpio_mode(GPIO31_SYNC_AC97_MD);
27175b41027SLiam Girdwood 	pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD);
27275b41027SLiam Girdwood 	pxa_gpio_mode(GPIO28_BITCLK_AC97_MD);
27375b41027SLiam Girdwood 	pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD);
27475b41027SLiam Girdwood #ifdef CONFIG_PXA27x
27575b41027SLiam Girdwood 	/* Use GPIO 113 as AC97 Reset on Bulverde */
27675b41027SLiam Girdwood 	pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
27775b41027SLiam Girdwood #endif
278942de47bSMark Brown 	clk_enable(ac97_clk);
27975b41027SLiam Girdwood 	return 0;
28075b41027SLiam Girdwood }
28175b41027SLiam Girdwood 
28275b41027SLiam Girdwood #else
28375b41027SLiam Girdwood #define pxa2xx_ac97_suspend	NULL
28475b41027SLiam Girdwood #define pxa2xx_ac97_resume	NULL
28575b41027SLiam Girdwood #endif
28675b41027SLiam Girdwood 
28775b41027SLiam Girdwood static int pxa2xx_ac97_probe(struct platform_device *pdev)
28875b41027SLiam Girdwood {
28975b41027SLiam Girdwood 	int ret;
29075b41027SLiam Girdwood 
29175b41027SLiam Girdwood 	ret = request_irq(IRQ_AC97, pxa2xx_ac97_irq, IRQF_DISABLED, "AC97", NULL);
29275b41027SLiam Girdwood 	if (ret < 0)
29375b41027SLiam Girdwood 		goto err;
29475b41027SLiam Girdwood 
29575b41027SLiam Girdwood 	pxa_gpio_mode(GPIO31_SYNC_AC97_MD);
29675b41027SLiam Girdwood 	pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD);
29775b41027SLiam Girdwood 	pxa_gpio_mode(GPIO28_BITCLK_AC97_MD);
29875b41027SLiam Girdwood 	pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD);
29975b41027SLiam Girdwood #ifdef CONFIG_PXA27x
30075b41027SLiam Girdwood 	/* Use GPIO 113 as AC97 Reset on Bulverde */
30175b41027SLiam Girdwood 	pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
302942de47bSMark Brown 
303942de47bSMark Brown 	ac97conf_clk = clk_get(&pdev->dev, "AC97CONFCLK");
304942de47bSMark Brown 	if (IS_ERR(ac97conf_clk)) {
305942de47bSMark Brown 		ret = PTR_ERR(ac97conf_clk);
306942de47bSMark Brown 		ac97conf_clk = NULL;
307942de47bSMark Brown 		goto err_irq;
308942de47bSMark Brown 	}
30975b41027SLiam Girdwood #endif
310942de47bSMark Brown 	ac97_clk = clk_get(&pdev->dev, "AC97CLK");
311942de47bSMark Brown 	if (IS_ERR(ac97_clk)) {
312942de47bSMark Brown 		ret = PTR_ERR(ac97_clk);
313942de47bSMark Brown 		ac97_clk = NULL;
314942de47bSMark Brown 		goto err_irq;
315942de47bSMark Brown 	}
31675b41027SLiam Girdwood 	return 0;
31775b41027SLiam Girdwood 
318942de47bSMark Brown  err_irq:
31975b41027SLiam Girdwood 	GCR |= GCR_ACLINK_OFF;
320942de47bSMark Brown #ifdef CONFIG_PXA27x
321942de47bSMark Brown 	if (ac97conf_clk) {
322942de47bSMark Brown 		clk_put(ac97conf_clk);
323942de47bSMark Brown 		ac97conf_clk = NULL;
32475b41027SLiam Girdwood 	}
325942de47bSMark Brown #endif
326942de47bSMark Brown 	free_irq(IRQ_AC97, NULL);
327942de47bSMark Brown  err:
32875b41027SLiam Girdwood 	return ret;
32975b41027SLiam Girdwood }
33075b41027SLiam Girdwood 
33175b41027SLiam Girdwood static void pxa2xx_ac97_remove(struct platform_device *pdev)
33275b41027SLiam Girdwood {
33375b41027SLiam Girdwood 	GCR |= GCR_ACLINK_OFF;
33475b41027SLiam Girdwood 	free_irq(IRQ_AC97, NULL);
335942de47bSMark Brown #ifdef CONFIG_PXA27x
336942de47bSMark Brown 	clk_put(ac97conf_clk);
337942de47bSMark Brown 	ac97conf_clk = NULL;
338942de47bSMark Brown #endif
339942de47bSMark Brown 	clk_disable(ac97_clk);
340942de47bSMark Brown 	clk_put(ac97_clk);
341942de47bSMark Brown 	ac97_clk = NULL;
34275b41027SLiam Girdwood }
34375b41027SLiam Girdwood 
34475b41027SLiam Girdwood static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream,
34575b41027SLiam Girdwood 				struct snd_pcm_hw_params *params)
34675b41027SLiam Girdwood {
34775b41027SLiam Girdwood 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
348596ce32bSLiam Girdwood 	struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
34975b41027SLiam Girdwood 
35075b41027SLiam Girdwood 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
351596ce32bSLiam Girdwood 		cpu_dai->dma_data = &pxa2xx_ac97_pcm_stereo_out;
35275b41027SLiam Girdwood 	else
353596ce32bSLiam Girdwood 		cpu_dai->dma_data = &pxa2xx_ac97_pcm_stereo_in;
35475b41027SLiam Girdwood 
35575b41027SLiam Girdwood 	return 0;
35675b41027SLiam Girdwood }
35775b41027SLiam Girdwood 
35875b41027SLiam Girdwood static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream *substream,
35975b41027SLiam Girdwood 	struct snd_pcm_hw_params *params)
36075b41027SLiam Girdwood {
36175b41027SLiam Girdwood 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
362596ce32bSLiam Girdwood 	struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
36375b41027SLiam Girdwood 
36475b41027SLiam Girdwood 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
365596ce32bSLiam Girdwood 		cpu_dai->dma_data = &pxa2xx_ac97_pcm_aux_mono_out;
36675b41027SLiam Girdwood 	else
367596ce32bSLiam Girdwood 		cpu_dai->dma_data = &pxa2xx_ac97_pcm_aux_mono_in;
36875b41027SLiam Girdwood 
36975b41027SLiam Girdwood 	return 0;
37075b41027SLiam Girdwood }
37175b41027SLiam Girdwood 
37275b41027SLiam Girdwood static int pxa2xx_ac97_hw_mic_params(struct snd_pcm_substream *substream,
37375b41027SLiam Girdwood 	struct snd_pcm_hw_params *params)
37475b41027SLiam Girdwood {
37575b41027SLiam Girdwood 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
376596ce32bSLiam Girdwood 	struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
37775b41027SLiam Girdwood 
37875b41027SLiam Girdwood 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
37975b41027SLiam Girdwood 		return -ENODEV;
38075b41027SLiam Girdwood 	else
381596ce32bSLiam Girdwood 		cpu_dai->dma_data = &pxa2xx_ac97_pcm_mic_mono_in;
38275b41027SLiam Girdwood 
38375b41027SLiam Girdwood 	return 0;
38475b41027SLiam Girdwood }
38575b41027SLiam Girdwood 
386596ce32bSLiam Girdwood #define PXA2XX_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
387596ce32bSLiam Girdwood 		SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
388596ce32bSLiam Girdwood 		SNDRV_PCM_RATE_48000)
389596ce32bSLiam Girdwood 
39075b41027SLiam Girdwood /*
39175b41027SLiam Girdwood  * There is only 1 physical AC97 interface for pxa2xx, but it
39275b41027SLiam Girdwood  * has extra fifo's that can be used for aux DACs and ADCs.
39375b41027SLiam Girdwood  */
39475b41027SLiam Girdwood struct snd_soc_cpu_dai pxa_ac97_dai[] = {
39575b41027SLiam Girdwood {
39675b41027SLiam Girdwood 	.name = "pxa2xx-ac97",
39775b41027SLiam Girdwood 	.id = 0,
39875b41027SLiam Girdwood 	.type = SND_SOC_DAI_AC97,
39975b41027SLiam Girdwood 	.probe = pxa2xx_ac97_probe,
40075b41027SLiam Girdwood 	.remove = pxa2xx_ac97_remove,
40175b41027SLiam Girdwood 	.suspend = pxa2xx_ac97_suspend,
40275b41027SLiam Girdwood 	.resume = pxa2xx_ac97_resume,
40375b41027SLiam Girdwood 	.playback = {
40475b41027SLiam Girdwood 		.stream_name = "AC97 Playback",
40575b41027SLiam Girdwood 		.channels_min = 2,
406596ce32bSLiam Girdwood 		.channels_max = 2,
407596ce32bSLiam Girdwood 		.rates = PXA2XX_AC97_RATES,
408596ce32bSLiam Girdwood 		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
40975b41027SLiam Girdwood 	.capture = {
41075b41027SLiam Girdwood 		.stream_name = "AC97 Capture",
41175b41027SLiam Girdwood 		.channels_min = 2,
412596ce32bSLiam Girdwood 		.channels_max = 2,
413596ce32bSLiam Girdwood 		.rates = PXA2XX_AC97_RATES,
414596ce32bSLiam Girdwood 		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
41575b41027SLiam Girdwood 	.ops = {
41675b41027SLiam Girdwood 		.hw_params = pxa2xx_ac97_hw_params,},
41775b41027SLiam Girdwood },
41875b41027SLiam Girdwood {
41975b41027SLiam Girdwood 	.name = "pxa2xx-ac97-aux",
42075b41027SLiam Girdwood 	.id = 1,
42175b41027SLiam Girdwood 	.type = SND_SOC_DAI_AC97,
42275b41027SLiam Girdwood 	.playback = {
42375b41027SLiam Girdwood 		.stream_name = "AC97 Aux Playback",
42475b41027SLiam Girdwood 		.channels_min = 1,
425596ce32bSLiam Girdwood 		.channels_max = 1,
426596ce32bSLiam Girdwood 		.rates = PXA2XX_AC97_RATES,
427596ce32bSLiam Girdwood 		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
42875b41027SLiam Girdwood 	.capture = {
42975b41027SLiam Girdwood 		.stream_name = "AC97 Aux Capture",
43075b41027SLiam Girdwood 		.channels_min = 1,
431596ce32bSLiam Girdwood 		.channels_max = 1,
432596ce32bSLiam Girdwood 		.rates = PXA2XX_AC97_RATES,
433596ce32bSLiam Girdwood 		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
43475b41027SLiam Girdwood 	.ops = {
43575b41027SLiam Girdwood 		.hw_params = pxa2xx_ac97_hw_aux_params,},
43675b41027SLiam Girdwood },
43775b41027SLiam Girdwood {
43875b41027SLiam Girdwood 	.name = "pxa2xx-ac97-mic",
43975b41027SLiam Girdwood 	.id = 2,
44075b41027SLiam Girdwood 	.type = SND_SOC_DAI_AC97,
44175b41027SLiam Girdwood 	.capture = {
44275b41027SLiam Girdwood 		.stream_name = "AC97 Mic Capture",
44375b41027SLiam Girdwood 		.channels_min = 1,
444596ce32bSLiam Girdwood 		.channels_max = 1,
445596ce32bSLiam Girdwood 		.rates = PXA2XX_AC97_RATES,
446596ce32bSLiam Girdwood 		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
44775b41027SLiam Girdwood 	.ops = {
44875b41027SLiam Girdwood 		.hw_params = pxa2xx_ac97_hw_mic_params,},
449596ce32bSLiam Girdwood },
45075b41027SLiam Girdwood };
45175b41027SLiam Girdwood 
45275b41027SLiam Girdwood EXPORT_SYMBOL_GPL(pxa_ac97_dai);
45375b41027SLiam Girdwood EXPORT_SYMBOL_GPL(soc_ac97_ops);
45475b41027SLiam Girdwood 
45575b41027SLiam Girdwood MODULE_AUTHOR("Nicolas Pitre");
45675b41027SLiam Girdwood MODULE_DESCRIPTION("AC97 driver for the Intel PXA2xx chip");
45775b41027SLiam Girdwood MODULE_LICENSE("GPL");
458