xref: /openbmc/linux/sound/soc/pxa/pxa2xx-ac97.c (revision a683b14d)
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>
31a683b14dSeric miao #include <asm/arch/pxa2xx-gpio.h>
3275b41027SLiam Girdwood #include <asm/arch/audio.h>
3375b41027SLiam Girdwood 
3475b41027SLiam Girdwood #include "pxa2xx-pcm.h"
35596ce32bSLiam Girdwood #include "pxa2xx-ac97.h"
3675b41027SLiam Girdwood 
3775b41027SLiam Girdwood static DEFINE_MUTEX(car_mutex);
3875b41027SLiam Girdwood static DECLARE_WAIT_QUEUE_HEAD(gsr_wq);
3975b41027SLiam Girdwood static volatile long gsr_bits;
40942de47bSMark Brown static struct clk *ac97_clk;
41942de47bSMark Brown #ifdef CONFIG_PXA27x
42942de47bSMark Brown static struct clk *ac97conf_clk;
43942de47bSMark Brown #endif
4475b41027SLiam Girdwood 
4575b41027SLiam Girdwood /*
4675b41027SLiam Girdwood  * Beware PXA27x bugs:
4775b41027SLiam Girdwood  *
4875b41027SLiam Girdwood  *   o Slot 12 read from modem space will hang controller.
4975b41027SLiam Girdwood  *   o CDONE, SDONE interrupt fails after any slot 12 IO.
5075b41027SLiam Girdwood  *
5175b41027SLiam Girdwood  * We therefore have an hybrid approach for waiting on SDONE (interrupt or
5275b41027SLiam Girdwood  * 1 jiffy timeout if interrupt never comes).
5375b41027SLiam Girdwood  */
5475b41027SLiam Girdwood 
5575b41027SLiam Girdwood static unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97,
5675b41027SLiam Girdwood 	unsigned short reg)
5775b41027SLiam Girdwood {
5875b41027SLiam Girdwood 	unsigned short val = -1;
5975b41027SLiam Girdwood 	volatile u32 *reg_addr;
6075b41027SLiam Girdwood 
6175b41027SLiam Girdwood 	mutex_lock(&car_mutex);
6275b41027SLiam Girdwood 
6375b41027SLiam Girdwood 	/* set up primary or secondary codec/modem space */
6475b41027SLiam Girdwood #ifdef CONFIG_PXA27x
6575b41027SLiam Girdwood 	reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
6675b41027SLiam Girdwood #else
6775b41027SLiam Girdwood 	if (reg == AC97_GPIO_STATUS)
6875b41027SLiam Girdwood 		reg_addr = ac97->num ? &SMC_REG_BASE : &PMC_REG_BASE;
6975b41027SLiam Girdwood 	else
7075b41027SLiam Girdwood 		reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
7175b41027SLiam Girdwood #endif
7275b41027SLiam Girdwood 	reg_addr += (reg >> 1);
7375b41027SLiam Girdwood 
7475b41027SLiam Girdwood #ifndef CONFIG_PXA27x
7575b41027SLiam Girdwood 	if (reg == AC97_GPIO_STATUS) {
7675b41027SLiam Girdwood 		/* read from controller cache */
7775b41027SLiam Girdwood 		val = *reg_addr;
7875b41027SLiam Girdwood 		goto out;
7975b41027SLiam Girdwood 	}
8075b41027SLiam Girdwood #endif
8175b41027SLiam Girdwood 
8275b41027SLiam Girdwood 	/* start read access across the ac97 link */
8375b41027SLiam Girdwood 	GSR = GSR_CDONE | GSR_SDONE;
8475b41027SLiam Girdwood 	gsr_bits = 0;
8575b41027SLiam Girdwood 	val = *reg_addr;
8675b41027SLiam Girdwood 
8775b41027SLiam Girdwood 	wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1);
8875b41027SLiam Girdwood 	if (!((GSR | gsr_bits) & GSR_SDONE)) {
8975b41027SLiam Girdwood 		printk(KERN_ERR "%s: read error (ac97_reg=%x GSR=%#lx)\n",
9075b41027SLiam Girdwood 				__FUNCTION__, reg, GSR | gsr_bits);
9175b41027SLiam Girdwood 		val = -1;
9275b41027SLiam Girdwood 		goto out;
9375b41027SLiam Girdwood 	}
9475b41027SLiam Girdwood 
9575b41027SLiam Girdwood 	/* valid data now */
9675b41027SLiam Girdwood 	GSR = GSR_CDONE | GSR_SDONE;
9775b41027SLiam Girdwood 	gsr_bits = 0;
9875b41027SLiam Girdwood 	val = *reg_addr;
9975b41027SLiam Girdwood 	/* but we've just started another cycle... */
10075b41027SLiam Girdwood 	wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1);
10175b41027SLiam Girdwood 
10275b41027SLiam Girdwood out:	mutex_unlock(&car_mutex);
10375b41027SLiam Girdwood 	return val;
10475b41027SLiam Girdwood }
10575b41027SLiam Girdwood 
10675b41027SLiam Girdwood static void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
10775b41027SLiam Girdwood 	unsigned short val)
10875b41027SLiam Girdwood {
10975b41027SLiam Girdwood 	volatile u32 *reg_addr;
11075b41027SLiam Girdwood 
11175b41027SLiam Girdwood 	mutex_lock(&car_mutex);
11275b41027SLiam Girdwood 
11375b41027SLiam Girdwood 	/* set up primary or secondary codec/modem space */
11475b41027SLiam Girdwood #ifdef CONFIG_PXA27x
11575b41027SLiam Girdwood 	reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
11675b41027SLiam Girdwood #else
11775b41027SLiam Girdwood 	if (reg == AC97_GPIO_STATUS)
11875b41027SLiam Girdwood 		reg_addr = ac97->num ? &SMC_REG_BASE : &PMC_REG_BASE;
11975b41027SLiam Girdwood 	else
12075b41027SLiam Girdwood 		reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
12175b41027SLiam Girdwood #endif
12275b41027SLiam Girdwood 	reg_addr += (reg >> 1);
12375b41027SLiam Girdwood 
12475b41027SLiam Girdwood 	GSR = GSR_CDONE | GSR_SDONE;
12575b41027SLiam Girdwood 	gsr_bits = 0;
12675b41027SLiam Girdwood 	*reg_addr = val;
12775b41027SLiam Girdwood 	wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_CDONE, 1);
12875b41027SLiam Girdwood 	if (!((GSR | gsr_bits) & GSR_CDONE))
12975b41027SLiam Girdwood 		printk(KERN_ERR "%s: write error (ac97_reg=%x GSR=%#lx)\n",
13075b41027SLiam Girdwood 				__FUNCTION__, reg, GSR | gsr_bits);
13175b41027SLiam Girdwood 
13275b41027SLiam Girdwood 	mutex_unlock(&car_mutex);
13375b41027SLiam Girdwood }
13475b41027SLiam Girdwood 
13575b41027SLiam Girdwood static void pxa2xx_ac97_warm_reset(struct snd_ac97 *ac97)
13675b41027SLiam Girdwood {
13775b41027SLiam Girdwood 	gsr_bits = 0;
13875b41027SLiam Girdwood 
13975b41027SLiam Girdwood #ifdef CONFIG_PXA27x
14075b41027SLiam Girdwood 	/* warm reset broken on Bulverde,
14175b41027SLiam Girdwood 	   so manually keep AC97 reset high */
14275b41027SLiam Girdwood 	pxa_gpio_mode(113 | GPIO_OUT | GPIO_DFLT_HIGH);
14375b41027SLiam Girdwood 	udelay(10);
14475b41027SLiam Girdwood 	GCR |= GCR_WARM_RST;
14575b41027SLiam Girdwood 	pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
14675b41027SLiam Girdwood 	udelay(500);
14775b41027SLiam Girdwood #else
14875b41027SLiam Girdwood 	GCR |= GCR_WARM_RST | GCR_PRIRDY_IEN | GCR_SECRDY_IEN;
14975b41027SLiam Girdwood 	wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1);
15075b41027SLiam Girdwood #endif
15175b41027SLiam Girdwood 
15275b41027SLiam Girdwood 	if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)))
15375b41027SLiam Girdwood 		printk(KERN_INFO "%s: warm reset timeout (GSR=%#lx)\n",
15475b41027SLiam Girdwood 				 __FUNCTION__, gsr_bits);
15575b41027SLiam Girdwood 
15675b41027SLiam Girdwood 	GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
15775b41027SLiam Girdwood 	GCR |= GCR_SDONE_IE|GCR_CDONE_IE;
15875b41027SLiam Girdwood }
15975b41027SLiam Girdwood 
16075b41027SLiam Girdwood static void pxa2xx_ac97_cold_reset(struct snd_ac97 *ac97)
16175b41027SLiam Girdwood {
16275b41027SLiam Girdwood 	GCR &=  GCR_COLD_RST;  /* clear everything but nCRST */
16375b41027SLiam Girdwood 	GCR &= ~GCR_COLD_RST;  /* then assert nCRST */
16475b41027SLiam Girdwood 
16575b41027SLiam Girdwood 	gsr_bits = 0;
16675b41027SLiam Girdwood #ifdef CONFIG_PXA27x
16775b41027SLiam Girdwood 	/* PXA27x Developers Manual section 13.5.2.2.1 */
168942de47bSMark Brown 	clk_enable(ac97conf_clk);
16975b41027SLiam Girdwood 	udelay(5);
170942de47bSMark Brown 	clk_disable(ac97conf_clk);
17175b41027SLiam Girdwood 	GCR = GCR_COLD_RST;
17275b41027SLiam Girdwood 	udelay(50);
17375b41027SLiam Girdwood #else
17475b41027SLiam Girdwood 	GCR = GCR_COLD_RST;
17575b41027SLiam Girdwood 	GCR |= GCR_CDONE_IE|GCR_SDONE_IE;
17675b41027SLiam Girdwood 	wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1);
17775b41027SLiam Girdwood #endif
17875b41027SLiam Girdwood 
17975b41027SLiam Girdwood 	if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)))
18075b41027SLiam Girdwood 		printk(KERN_INFO "%s: cold reset timeout (GSR=%#lx)\n",
18175b41027SLiam Girdwood 				 __FUNCTION__, gsr_bits);
18275b41027SLiam Girdwood 
18375b41027SLiam Girdwood 	GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
18475b41027SLiam Girdwood 	GCR |= GCR_SDONE_IE|GCR_CDONE_IE;
18575b41027SLiam Girdwood }
18675b41027SLiam Girdwood 
18775b41027SLiam Girdwood static irqreturn_t pxa2xx_ac97_irq(int irq, void *dev_id)
18875b41027SLiam Girdwood {
18975b41027SLiam Girdwood 	long status;
19075b41027SLiam Girdwood 
19175b41027SLiam Girdwood 	status = GSR;
19275b41027SLiam Girdwood 	if (status) {
19375b41027SLiam Girdwood 		GSR = status;
19475b41027SLiam Girdwood 		gsr_bits |= status;
19575b41027SLiam Girdwood 		wake_up(&gsr_wq);
19675b41027SLiam Girdwood 
19775b41027SLiam Girdwood #ifdef CONFIG_PXA27x
19875b41027SLiam Girdwood 		/* Although we don't use those we still need to clear them
19975b41027SLiam Girdwood 		   since they tend to spuriously trigger when MMC is used
20075b41027SLiam Girdwood 		   (hardware bug? go figure)... */
20175b41027SLiam Girdwood 		MISR = MISR_EOC;
20275b41027SLiam Girdwood 		PISR = PISR_EOC;
20375b41027SLiam Girdwood 		MCSR = MCSR_EOC;
20475b41027SLiam Girdwood #endif
20575b41027SLiam Girdwood 
20675b41027SLiam Girdwood 		return IRQ_HANDLED;
20775b41027SLiam Girdwood 	}
20875b41027SLiam Girdwood 
20975b41027SLiam Girdwood 	return IRQ_NONE;
21075b41027SLiam Girdwood }
21175b41027SLiam Girdwood 
21275b41027SLiam Girdwood struct snd_ac97_bus_ops soc_ac97_ops = {
21375b41027SLiam Girdwood 	.read	= pxa2xx_ac97_read,
21475b41027SLiam Girdwood 	.write	= pxa2xx_ac97_write,
21575b41027SLiam Girdwood 	.warm_reset	= pxa2xx_ac97_warm_reset,
21675b41027SLiam Girdwood 	.reset	= pxa2xx_ac97_cold_reset,
21775b41027SLiam Girdwood };
21875b41027SLiam Girdwood 
21975b41027SLiam Girdwood static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_out = {
22075b41027SLiam Girdwood 	.name			= "AC97 PCM Stereo out",
22175b41027SLiam Girdwood 	.dev_addr		= __PREG(PCDR),
22275b41027SLiam Girdwood 	.drcmr			= &DRCMRTXPCDR,
22375b41027SLiam Girdwood 	.dcmd			= DCMD_INCSRCADDR | DCMD_FLOWTRG |
22475b41027SLiam Girdwood 				  DCMD_BURST32 | DCMD_WIDTH4,
22575b41027SLiam Girdwood };
22675b41027SLiam Girdwood 
22775b41027SLiam Girdwood static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_in = {
22875b41027SLiam Girdwood 	.name			= "AC97 PCM Stereo in",
22975b41027SLiam Girdwood 	.dev_addr		= __PREG(PCDR),
23075b41027SLiam Girdwood 	.drcmr			= &DRCMRRXPCDR,
23175b41027SLiam Girdwood 	.dcmd			= DCMD_INCTRGADDR | DCMD_FLOWSRC |
23275b41027SLiam Girdwood 				  DCMD_BURST32 | DCMD_WIDTH4,
23375b41027SLiam Girdwood };
23475b41027SLiam Girdwood 
23575b41027SLiam Girdwood static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_aux_mono_out = {
23675b41027SLiam Girdwood 	.name			= "AC97 Aux PCM (Slot 5) Mono out",
23775b41027SLiam Girdwood 	.dev_addr		= __PREG(MODR),
23875b41027SLiam Girdwood 	.drcmr			= &DRCMRTXMODR,
23975b41027SLiam Girdwood 	.dcmd			= DCMD_INCSRCADDR | DCMD_FLOWTRG |
24075b41027SLiam Girdwood 				  DCMD_BURST16 | DCMD_WIDTH2,
24175b41027SLiam Girdwood };
24275b41027SLiam Girdwood 
24375b41027SLiam Girdwood static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_aux_mono_in = {
24475b41027SLiam Girdwood 	.name			= "AC97 Aux PCM (Slot 5) Mono in",
24575b41027SLiam Girdwood 	.dev_addr		= __PREG(MODR),
24675b41027SLiam Girdwood 	.drcmr			= &DRCMRRXMODR,
24775b41027SLiam Girdwood 	.dcmd			= DCMD_INCTRGADDR | DCMD_FLOWSRC |
24875b41027SLiam Girdwood 				  DCMD_BURST16 | DCMD_WIDTH2,
24975b41027SLiam Girdwood };
25075b41027SLiam Girdwood 
25175b41027SLiam Girdwood static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_mic_mono_in = {
25275b41027SLiam Girdwood 	.name			= "AC97 Mic PCM (Slot 6) Mono in",
25375b41027SLiam Girdwood 	.dev_addr		= __PREG(MCDR),
25475b41027SLiam Girdwood 	.drcmr			= &DRCMRRXMCDR,
25575b41027SLiam Girdwood 	.dcmd			= DCMD_INCTRGADDR | DCMD_FLOWSRC |
25675b41027SLiam Girdwood 				  DCMD_BURST16 | DCMD_WIDTH2,
25775b41027SLiam Girdwood };
25875b41027SLiam Girdwood 
25975b41027SLiam Girdwood #ifdef CONFIG_PM
26075b41027SLiam Girdwood static int pxa2xx_ac97_suspend(struct platform_device *pdev,
26175b41027SLiam Girdwood 	struct snd_soc_cpu_dai *dai)
26275b41027SLiam Girdwood {
26375b41027SLiam Girdwood 	GCR |= GCR_ACLINK_OFF;
264942de47bSMark Brown 	clk_disable(ac97_clk);
26575b41027SLiam Girdwood 	return 0;
26675b41027SLiam Girdwood }
26775b41027SLiam Girdwood 
26875b41027SLiam Girdwood static int pxa2xx_ac97_resume(struct platform_device *pdev,
26975b41027SLiam Girdwood 	struct snd_soc_cpu_dai *dai)
27075b41027SLiam Girdwood {
27175b41027SLiam Girdwood 	pxa_gpio_mode(GPIO31_SYNC_AC97_MD);
27275b41027SLiam Girdwood 	pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD);
27375b41027SLiam Girdwood 	pxa_gpio_mode(GPIO28_BITCLK_AC97_MD);
27475b41027SLiam Girdwood 	pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD);
27575b41027SLiam Girdwood #ifdef CONFIG_PXA27x
27675b41027SLiam Girdwood 	/* Use GPIO 113 as AC97 Reset on Bulverde */
27775b41027SLiam Girdwood 	pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
27875b41027SLiam Girdwood #endif
279942de47bSMark Brown 	clk_enable(ac97_clk);
28075b41027SLiam Girdwood 	return 0;
28175b41027SLiam Girdwood }
28275b41027SLiam Girdwood 
28375b41027SLiam Girdwood #else
28475b41027SLiam Girdwood #define pxa2xx_ac97_suspend	NULL
28575b41027SLiam Girdwood #define pxa2xx_ac97_resume	NULL
28675b41027SLiam Girdwood #endif
28775b41027SLiam Girdwood 
28875b41027SLiam Girdwood static int pxa2xx_ac97_probe(struct platform_device *pdev)
28975b41027SLiam Girdwood {
29075b41027SLiam Girdwood 	int ret;
29175b41027SLiam Girdwood 
29275b41027SLiam Girdwood 	ret = request_irq(IRQ_AC97, pxa2xx_ac97_irq, IRQF_DISABLED, "AC97", NULL);
29375b41027SLiam Girdwood 	if (ret < 0)
29475b41027SLiam Girdwood 		goto err;
29575b41027SLiam Girdwood 
29675b41027SLiam Girdwood 	pxa_gpio_mode(GPIO31_SYNC_AC97_MD);
29775b41027SLiam Girdwood 	pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD);
29875b41027SLiam Girdwood 	pxa_gpio_mode(GPIO28_BITCLK_AC97_MD);
29975b41027SLiam Girdwood 	pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD);
30075b41027SLiam Girdwood #ifdef CONFIG_PXA27x
30175b41027SLiam Girdwood 	/* Use GPIO 113 as AC97 Reset on Bulverde */
30275b41027SLiam Girdwood 	pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
303942de47bSMark Brown 
304942de47bSMark Brown 	ac97conf_clk = clk_get(&pdev->dev, "AC97CONFCLK");
305942de47bSMark Brown 	if (IS_ERR(ac97conf_clk)) {
306942de47bSMark Brown 		ret = PTR_ERR(ac97conf_clk);
307942de47bSMark Brown 		ac97conf_clk = NULL;
308942de47bSMark Brown 		goto err_irq;
309942de47bSMark Brown 	}
31075b41027SLiam Girdwood #endif
311942de47bSMark Brown 	ac97_clk = clk_get(&pdev->dev, "AC97CLK");
312942de47bSMark Brown 	if (IS_ERR(ac97_clk)) {
313942de47bSMark Brown 		ret = PTR_ERR(ac97_clk);
314942de47bSMark Brown 		ac97_clk = NULL;
315942de47bSMark Brown 		goto err_irq;
316942de47bSMark Brown 	}
31775b41027SLiam Girdwood 	return 0;
31875b41027SLiam Girdwood 
319942de47bSMark Brown  err_irq:
32075b41027SLiam Girdwood 	GCR |= GCR_ACLINK_OFF;
321942de47bSMark Brown #ifdef CONFIG_PXA27x
322942de47bSMark Brown 	if (ac97conf_clk) {
323942de47bSMark Brown 		clk_put(ac97conf_clk);
324942de47bSMark Brown 		ac97conf_clk = NULL;
32575b41027SLiam Girdwood 	}
326942de47bSMark Brown #endif
327942de47bSMark Brown 	free_irq(IRQ_AC97, NULL);
328942de47bSMark Brown  err:
32975b41027SLiam Girdwood 	return ret;
33075b41027SLiam Girdwood }
33175b41027SLiam Girdwood 
33275b41027SLiam Girdwood static void pxa2xx_ac97_remove(struct platform_device *pdev)
33375b41027SLiam Girdwood {
33475b41027SLiam Girdwood 	GCR |= GCR_ACLINK_OFF;
33575b41027SLiam Girdwood 	free_irq(IRQ_AC97, NULL);
336942de47bSMark Brown #ifdef CONFIG_PXA27x
337942de47bSMark Brown 	clk_put(ac97conf_clk);
338942de47bSMark Brown 	ac97conf_clk = NULL;
339942de47bSMark Brown #endif
340942de47bSMark Brown 	clk_disable(ac97_clk);
341942de47bSMark Brown 	clk_put(ac97_clk);
342942de47bSMark Brown 	ac97_clk = NULL;
34375b41027SLiam Girdwood }
34475b41027SLiam Girdwood 
34575b41027SLiam Girdwood static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream,
34675b41027SLiam Girdwood 				struct snd_pcm_hw_params *params)
34775b41027SLiam Girdwood {
34875b41027SLiam Girdwood 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
349596ce32bSLiam Girdwood 	struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
35075b41027SLiam Girdwood 
35175b41027SLiam Girdwood 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
352596ce32bSLiam Girdwood 		cpu_dai->dma_data = &pxa2xx_ac97_pcm_stereo_out;
35375b41027SLiam Girdwood 	else
354596ce32bSLiam Girdwood 		cpu_dai->dma_data = &pxa2xx_ac97_pcm_stereo_in;
35575b41027SLiam Girdwood 
35675b41027SLiam Girdwood 	return 0;
35775b41027SLiam Girdwood }
35875b41027SLiam Girdwood 
35975b41027SLiam Girdwood static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream *substream,
36075b41027SLiam Girdwood 	struct snd_pcm_hw_params *params)
36175b41027SLiam Girdwood {
36275b41027SLiam Girdwood 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
363596ce32bSLiam Girdwood 	struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
36475b41027SLiam Girdwood 
36575b41027SLiam Girdwood 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
366596ce32bSLiam Girdwood 		cpu_dai->dma_data = &pxa2xx_ac97_pcm_aux_mono_out;
36775b41027SLiam Girdwood 	else
368596ce32bSLiam Girdwood 		cpu_dai->dma_data = &pxa2xx_ac97_pcm_aux_mono_in;
36975b41027SLiam Girdwood 
37075b41027SLiam Girdwood 	return 0;
37175b41027SLiam Girdwood }
37275b41027SLiam Girdwood 
37375b41027SLiam Girdwood static int pxa2xx_ac97_hw_mic_params(struct snd_pcm_substream *substream,
37475b41027SLiam Girdwood 	struct snd_pcm_hw_params *params)
37575b41027SLiam Girdwood {
37675b41027SLiam Girdwood 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
377596ce32bSLiam Girdwood 	struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
37875b41027SLiam Girdwood 
37975b41027SLiam Girdwood 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
38075b41027SLiam Girdwood 		return -ENODEV;
38175b41027SLiam Girdwood 	else
382596ce32bSLiam Girdwood 		cpu_dai->dma_data = &pxa2xx_ac97_pcm_mic_mono_in;
38375b41027SLiam Girdwood 
38475b41027SLiam Girdwood 	return 0;
38575b41027SLiam Girdwood }
38675b41027SLiam Girdwood 
387596ce32bSLiam Girdwood #define PXA2XX_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
388596ce32bSLiam Girdwood 		SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
389596ce32bSLiam Girdwood 		SNDRV_PCM_RATE_48000)
390596ce32bSLiam Girdwood 
39175b41027SLiam Girdwood /*
39275b41027SLiam Girdwood  * There is only 1 physical AC97 interface for pxa2xx, but it
39375b41027SLiam Girdwood  * has extra fifo's that can be used for aux DACs and ADCs.
39475b41027SLiam Girdwood  */
39575b41027SLiam Girdwood struct snd_soc_cpu_dai pxa_ac97_dai[] = {
39675b41027SLiam Girdwood {
39775b41027SLiam Girdwood 	.name = "pxa2xx-ac97",
39875b41027SLiam Girdwood 	.id = 0,
39975b41027SLiam Girdwood 	.type = SND_SOC_DAI_AC97,
40075b41027SLiam Girdwood 	.probe = pxa2xx_ac97_probe,
40175b41027SLiam Girdwood 	.remove = pxa2xx_ac97_remove,
40275b41027SLiam Girdwood 	.suspend = pxa2xx_ac97_suspend,
40375b41027SLiam Girdwood 	.resume = pxa2xx_ac97_resume,
40475b41027SLiam Girdwood 	.playback = {
40575b41027SLiam Girdwood 		.stream_name = "AC97 Playback",
40675b41027SLiam Girdwood 		.channels_min = 2,
407596ce32bSLiam Girdwood 		.channels_max = 2,
408596ce32bSLiam Girdwood 		.rates = PXA2XX_AC97_RATES,
409596ce32bSLiam Girdwood 		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
41075b41027SLiam Girdwood 	.capture = {
41175b41027SLiam Girdwood 		.stream_name = "AC97 Capture",
41275b41027SLiam Girdwood 		.channels_min = 2,
413596ce32bSLiam Girdwood 		.channels_max = 2,
414596ce32bSLiam Girdwood 		.rates = PXA2XX_AC97_RATES,
415596ce32bSLiam Girdwood 		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
41675b41027SLiam Girdwood 	.ops = {
41775b41027SLiam Girdwood 		.hw_params = pxa2xx_ac97_hw_params,},
41875b41027SLiam Girdwood },
41975b41027SLiam Girdwood {
42075b41027SLiam Girdwood 	.name = "pxa2xx-ac97-aux",
42175b41027SLiam Girdwood 	.id = 1,
42275b41027SLiam Girdwood 	.type = SND_SOC_DAI_AC97,
42375b41027SLiam Girdwood 	.playback = {
42475b41027SLiam Girdwood 		.stream_name = "AC97 Aux Playback",
42575b41027SLiam Girdwood 		.channels_min = 1,
426596ce32bSLiam Girdwood 		.channels_max = 1,
427596ce32bSLiam Girdwood 		.rates = PXA2XX_AC97_RATES,
428596ce32bSLiam Girdwood 		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
42975b41027SLiam Girdwood 	.capture = {
43075b41027SLiam Girdwood 		.stream_name = "AC97 Aux Capture",
43175b41027SLiam Girdwood 		.channels_min = 1,
432596ce32bSLiam Girdwood 		.channels_max = 1,
433596ce32bSLiam Girdwood 		.rates = PXA2XX_AC97_RATES,
434596ce32bSLiam Girdwood 		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
43575b41027SLiam Girdwood 	.ops = {
43675b41027SLiam Girdwood 		.hw_params = pxa2xx_ac97_hw_aux_params,},
43775b41027SLiam Girdwood },
43875b41027SLiam Girdwood {
43975b41027SLiam Girdwood 	.name = "pxa2xx-ac97-mic",
44075b41027SLiam Girdwood 	.id = 2,
44175b41027SLiam Girdwood 	.type = SND_SOC_DAI_AC97,
44275b41027SLiam Girdwood 	.capture = {
44375b41027SLiam Girdwood 		.stream_name = "AC97 Mic Capture",
44475b41027SLiam Girdwood 		.channels_min = 1,
445596ce32bSLiam Girdwood 		.channels_max = 1,
446596ce32bSLiam Girdwood 		.rates = PXA2XX_AC97_RATES,
447596ce32bSLiam Girdwood 		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
44875b41027SLiam Girdwood 	.ops = {
44975b41027SLiam Girdwood 		.hw_params = pxa2xx_ac97_hw_mic_params,},
450596ce32bSLiam Girdwood },
45175b41027SLiam Girdwood };
45275b41027SLiam Girdwood 
45375b41027SLiam Girdwood EXPORT_SYMBOL_GPL(pxa_ac97_dai);
45475b41027SLiam Girdwood EXPORT_SYMBOL_GPL(soc_ac97_ops);
45575b41027SLiam Girdwood 
45675b41027SLiam Girdwood MODULE_AUTHOR("Nicolas Pitre");
45775b41027SLiam Girdwood MODULE_DESCRIPTION("AC97 driver for the Intel PXA2xx chip");
45875b41027SLiam Girdwood MODULE_LICENSE("GPL");
459