xref: /openbmc/linux/sound/arm/pxa2xx-ac97-lib.c (revision 9d1cf39be6709761be3ce0a00e5c9ee5dc805ac5)
19c636342SDmitry Baryshkov /*
29c636342SDmitry Baryshkov  * Based on sound/arm/pxa2xx-ac97.c and sound/soc/pxa/pxa2xx-ac97.c
39c636342SDmitry Baryshkov  * which contain:
49c636342SDmitry Baryshkov  *
59c636342SDmitry Baryshkov  * Author:	Nicolas Pitre
69c636342SDmitry Baryshkov  * Created:	Dec 02, 2004
79c636342SDmitry Baryshkov  * Copyright:	MontaVista Software Inc.
89c636342SDmitry Baryshkov  *
99c636342SDmitry Baryshkov  * This program is free software; you can redistribute it and/or modify
109c636342SDmitry Baryshkov  * it under the terms of the GNU General Public License version 2 as
119c636342SDmitry Baryshkov  * published by the Free Software Foundation.
129c636342SDmitry Baryshkov  */
139c636342SDmitry Baryshkov 
149c636342SDmitry Baryshkov #include <linux/kernel.h>
159c636342SDmitry Baryshkov #include <linux/platform_device.h>
169c636342SDmitry Baryshkov #include <linux/interrupt.h>
179c636342SDmitry Baryshkov #include <linux/clk.h>
189c636342SDmitry Baryshkov #include <linux/delay.h>
199c636342SDmitry Baryshkov 
209c636342SDmitry Baryshkov #include <sound/ac97_codec.h>
219c636342SDmitry Baryshkov #include <sound/pxa2xx-lib.h>
229c636342SDmitry Baryshkov 
239c636342SDmitry Baryshkov #include <asm/irq.h>
249c636342SDmitry Baryshkov #include <mach/hardware.h>
259c636342SDmitry Baryshkov #include <mach/pxa-regs.h>
269c636342SDmitry Baryshkov #include <mach/pxa2xx-gpio.h>
279c636342SDmitry Baryshkov #include <mach/audio.h>
289c636342SDmitry Baryshkov 
299c636342SDmitry Baryshkov static DEFINE_MUTEX(car_mutex);
309c636342SDmitry Baryshkov static DECLARE_WAIT_QUEUE_HEAD(gsr_wq);
319c636342SDmitry Baryshkov static volatile long gsr_bits;
329c636342SDmitry Baryshkov static struct clk *ac97_clk;
339c636342SDmitry Baryshkov static struct clk *ac97conf_clk;
349c636342SDmitry Baryshkov 
359c636342SDmitry Baryshkov /*
369c636342SDmitry Baryshkov  * Beware PXA27x bugs:
379c636342SDmitry Baryshkov  *
389c636342SDmitry Baryshkov  *   o Slot 12 read from modem space will hang controller.
399c636342SDmitry Baryshkov  *   o CDONE, SDONE interrupt fails after any slot 12 IO.
409c636342SDmitry Baryshkov  *
419c636342SDmitry Baryshkov  * We therefore have an hybrid approach for waiting on SDONE (interrupt or
429c636342SDmitry Baryshkov  * 1 jiffy timeout if interrupt never comes).
439c636342SDmitry Baryshkov  */
449c636342SDmitry Baryshkov 
459c636342SDmitry Baryshkov unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
469c636342SDmitry Baryshkov {
479c636342SDmitry Baryshkov 	unsigned short val = -1;
489c636342SDmitry Baryshkov 	volatile u32 *reg_addr;
499c636342SDmitry Baryshkov 
509c636342SDmitry Baryshkov 	mutex_lock(&car_mutex);
519c636342SDmitry Baryshkov 
529c636342SDmitry Baryshkov 	/* set up primary or secondary codec space */
53*9d1cf39bSDmitry Baryshkov 	if ((cpu_is_pxa21x() || cpu_is_pxa25x()) && reg == AC97_GPIO_STATUS)
549c636342SDmitry Baryshkov 		reg_addr = ac97->num ? &SMC_REG_BASE : &PMC_REG_BASE;
559c636342SDmitry Baryshkov 	else
569c636342SDmitry Baryshkov 		reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
579c636342SDmitry Baryshkov 	reg_addr += (reg >> 1);
589c636342SDmitry Baryshkov 
599c636342SDmitry Baryshkov 	/* start read access across the ac97 link */
609c636342SDmitry Baryshkov 	GSR = GSR_CDONE | GSR_SDONE;
619c636342SDmitry Baryshkov 	gsr_bits = 0;
629c636342SDmitry Baryshkov 	val = *reg_addr;
639c636342SDmitry Baryshkov 	if (reg == AC97_GPIO_STATUS)
649c636342SDmitry Baryshkov 		goto out;
659c636342SDmitry Baryshkov 	if (wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1) <= 0 &&
669c636342SDmitry Baryshkov 	    !((GSR | gsr_bits) & GSR_SDONE)) {
679c636342SDmitry Baryshkov 		printk(KERN_ERR "%s: read error (ac97_reg=%d GSR=%#lx)\n",
689c636342SDmitry Baryshkov 				__func__, reg, GSR | gsr_bits);
699c636342SDmitry Baryshkov 		val = -1;
709c636342SDmitry Baryshkov 		goto out;
719c636342SDmitry Baryshkov 	}
729c636342SDmitry Baryshkov 
739c636342SDmitry Baryshkov 	/* valid data now */
749c636342SDmitry Baryshkov 	GSR = GSR_CDONE | GSR_SDONE;
759c636342SDmitry Baryshkov 	gsr_bits = 0;
769c636342SDmitry Baryshkov 	val = *reg_addr;
779c636342SDmitry Baryshkov 	/* but we've just started another cycle... */
789c636342SDmitry Baryshkov 	wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1);
799c636342SDmitry Baryshkov 
809c636342SDmitry Baryshkov out:	mutex_unlock(&car_mutex);
819c636342SDmitry Baryshkov 	return val;
829c636342SDmitry Baryshkov }
839c636342SDmitry Baryshkov EXPORT_SYMBOL_GPL(pxa2xx_ac97_read);
849c636342SDmitry Baryshkov 
859c636342SDmitry Baryshkov void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
869c636342SDmitry Baryshkov 			unsigned short val)
879c636342SDmitry Baryshkov {
889c636342SDmitry Baryshkov 	volatile u32 *reg_addr;
899c636342SDmitry Baryshkov 
909c636342SDmitry Baryshkov 	mutex_lock(&car_mutex);
919c636342SDmitry Baryshkov 
929c636342SDmitry Baryshkov 	/* set up primary or secondary codec space */
93*9d1cf39bSDmitry Baryshkov 	if ((cpu_is_pxa21x() || cpu_is_pxa25x()) && reg == AC97_GPIO_STATUS)
949c636342SDmitry Baryshkov 		reg_addr = ac97->num ? &SMC_REG_BASE : &PMC_REG_BASE;
959c636342SDmitry Baryshkov 	else
969c636342SDmitry Baryshkov 		reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
979c636342SDmitry Baryshkov 	reg_addr += (reg >> 1);
989c636342SDmitry Baryshkov 
999c636342SDmitry Baryshkov 	GSR = GSR_CDONE | GSR_SDONE;
1009c636342SDmitry Baryshkov 	gsr_bits = 0;
1019c636342SDmitry Baryshkov 	*reg_addr = val;
1029c636342SDmitry Baryshkov 	if (wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_CDONE, 1) <= 0 &&
1039c636342SDmitry Baryshkov 	    !((GSR | gsr_bits) & GSR_CDONE))
1049c636342SDmitry Baryshkov 		printk(KERN_ERR "%s: write error (ac97_reg=%d GSR=%#lx)\n",
1059c636342SDmitry Baryshkov 				__func__, reg, GSR | gsr_bits);
1069c636342SDmitry Baryshkov 
1079c636342SDmitry Baryshkov 	mutex_unlock(&car_mutex);
1089c636342SDmitry Baryshkov }
1099c636342SDmitry Baryshkov EXPORT_SYMBOL_GPL(pxa2xx_ac97_write);
1109c636342SDmitry Baryshkov 
111*9d1cf39bSDmitry Baryshkov #ifdef CONFIG_PXA25x
112*9d1cf39bSDmitry Baryshkov static inline void pxa_ac97_warm_pxa25x(void)
1139c636342SDmitry Baryshkov {
1149c636342SDmitry Baryshkov 	gsr_bits = 0;
1159c636342SDmitry Baryshkov 
116*9d1cf39bSDmitry Baryshkov 	GCR |= GCR_WARM_RST | GCR_PRIRDY_IEN | GCR_SECRDY_IEN;
117*9d1cf39bSDmitry Baryshkov 	wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1);
118*9d1cf39bSDmitry Baryshkov }
119*9d1cf39bSDmitry Baryshkov 
120*9d1cf39bSDmitry Baryshkov static inline void pxa_ac97_cold_pxa25x(void)
121*9d1cf39bSDmitry Baryshkov {
122*9d1cf39bSDmitry Baryshkov 	GCR &=  GCR_COLD_RST;  /* clear everything but nCRST */
123*9d1cf39bSDmitry Baryshkov 	GCR &= ~GCR_COLD_RST;  /* then assert nCRST */
124*9d1cf39bSDmitry Baryshkov 
125*9d1cf39bSDmitry Baryshkov 	gsr_bits = 0;
126*9d1cf39bSDmitry Baryshkov 
127*9d1cf39bSDmitry Baryshkov 	GCR = GCR_COLD_RST;
128*9d1cf39bSDmitry Baryshkov 	GCR |= GCR_CDONE_IE|GCR_SDONE_IE;
129*9d1cf39bSDmitry Baryshkov 	wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1);
130*9d1cf39bSDmitry Baryshkov }
131*9d1cf39bSDmitry Baryshkov #endif
132*9d1cf39bSDmitry Baryshkov 
1339c636342SDmitry Baryshkov #ifdef CONFIG_PXA27x
134*9d1cf39bSDmitry Baryshkov static inline void pxa_ac97_warm_pxa27x(void)
135*9d1cf39bSDmitry Baryshkov {
136*9d1cf39bSDmitry Baryshkov 	gsr_bits = 0;
137*9d1cf39bSDmitry Baryshkov 
1389c636342SDmitry Baryshkov 	/* warm reset broken on Bulverde,
1399c636342SDmitry Baryshkov 	   so manually keep AC97 reset high */
1409c636342SDmitry Baryshkov 	pxa_gpio_mode(113 | GPIO_OUT | GPIO_DFLT_HIGH);
1419c636342SDmitry Baryshkov 	udelay(10);
1429c636342SDmitry Baryshkov 	GCR |= GCR_WARM_RST;
1439c636342SDmitry Baryshkov 	pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
1449c636342SDmitry Baryshkov 	udelay(500);
145*9d1cf39bSDmitry Baryshkov }
146*9d1cf39bSDmitry Baryshkov 
147*9d1cf39bSDmitry Baryshkov static inline void pxa_ac97_cold_pxa27x(void)
148*9d1cf39bSDmitry Baryshkov {
149*9d1cf39bSDmitry Baryshkov 	GCR &=  GCR_COLD_RST;  /* clear everything but nCRST */
150*9d1cf39bSDmitry Baryshkov 	GCR &= ~GCR_COLD_RST;  /* then assert nCRST */
151*9d1cf39bSDmitry Baryshkov 
152*9d1cf39bSDmitry Baryshkov 	gsr_bits = 0;
153*9d1cf39bSDmitry Baryshkov 
154*9d1cf39bSDmitry Baryshkov 	/* PXA27x Developers Manual section 13.5.2.2.1 */
155*9d1cf39bSDmitry Baryshkov 	clk_enable(ac97conf_clk);
156*9d1cf39bSDmitry Baryshkov 	udelay(5);
157*9d1cf39bSDmitry Baryshkov 	clk_disable(ac97conf_clk);
158*9d1cf39bSDmitry Baryshkov 	GCR = GCR_COLD_RST;
159*9d1cf39bSDmitry Baryshkov 	udelay(50);
160*9d1cf39bSDmitry Baryshkov }
161*9d1cf39bSDmitry Baryshkov #endif
162*9d1cf39bSDmitry Baryshkov 
163*9d1cf39bSDmitry Baryshkov #ifdef CONFIG_PXA3xx
164*9d1cf39bSDmitry Baryshkov static inline void pxa_ac97_warm_pxa3xx(void)
165*9d1cf39bSDmitry Baryshkov {
166*9d1cf39bSDmitry Baryshkov 	int timeout = 100;
167*9d1cf39bSDmitry Baryshkov 
168*9d1cf39bSDmitry Baryshkov 	gsr_bits = 0;
169*9d1cf39bSDmitry Baryshkov 
1709c636342SDmitry Baryshkov 	/* Can't use interrupts */
1719c636342SDmitry Baryshkov 	GCR |= GCR_WARM_RST;
1729c636342SDmitry Baryshkov 	while (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--)
1739c636342SDmitry Baryshkov 		mdelay(1);
174*9d1cf39bSDmitry Baryshkov }
175*9d1cf39bSDmitry Baryshkov 
176*9d1cf39bSDmitry Baryshkov static inline void pxa_ac97_cold_pxa3xx(void)
177*9d1cf39bSDmitry Baryshkov {
178*9d1cf39bSDmitry Baryshkov 	int timeout = 1000;
179*9d1cf39bSDmitry Baryshkov 
180*9d1cf39bSDmitry Baryshkov 	/* Hold CLKBPB for 100us */
181*9d1cf39bSDmitry Baryshkov 	GCR = 0;
182*9d1cf39bSDmitry Baryshkov 	GCR = GCR_CLKBPB;
183*9d1cf39bSDmitry Baryshkov 	udelay(100);
184*9d1cf39bSDmitry Baryshkov 	GCR = 0;
185*9d1cf39bSDmitry Baryshkov 
186*9d1cf39bSDmitry Baryshkov 	GCR &=  GCR_COLD_RST;  /* clear everything but nCRST */
187*9d1cf39bSDmitry Baryshkov 	GCR &= ~GCR_COLD_RST;  /* then assert nCRST */
188*9d1cf39bSDmitry Baryshkov 
189*9d1cf39bSDmitry Baryshkov 	gsr_bits = 0;
190*9d1cf39bSDmitry Baryshkov 
191*9d1cf39bSDmitry Baryshkov 	/* Can't use interrupts on PXA3xx */
192*9d1cf39bSDmitry Baryshkov 	GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
193*9d1cf39bSDmitry Baryshkov 
194*9d1cf39bSDmitry Baryshkov 	GCR = GCR_WARM_RST | GCR_COLD_RST;
195*9d1cf39bSDmitry Baryshkov 	while (!(GSR & (GSR_PCR | GSR_SCR)) && timeout--)
196*9d1cf39bSDmitry Baryshkov 		mdelay(10);
197*9d1cf39bSDmitry Baryshkov }
1989c636342SDmitry Baryshkov #endif
1999c636342SDmitry Baryshkov 
200*9d1cf39bSDmitry Baryshkov bool pxa2xx_ac97_try_warm_reset(struct snd_ac97 *ac97)
201*9d1cf39bSDmitry Baryshkov {
202*9d1cf39bSDmitry Baryshkov #ifdef CONFIG_PXA25x
203*9d1cf39bSDmitry Baryshkov 	if (cpu_is_pxa21x() || cpu_is_pxa25x())
204*9d1cf39bSDmitry Baryshkov 		pxa_ac97_warm_pxa25x();
205*9d1cf39bSDmitry Baryshkov 	else
206*9d1cf39bSDmitry Baryshkov #endif
207*9d1cf39bSDmitry Baryshkov #ifdef CONFIG_PXA27x
208*9d1cf39bSDmitry Baryshkov 	if (cpu_is_pxa27x())
209*9d1cf39bSDmitry Baryshkov 		pxa_ac97_warm_pxa27x();
210*9d1cf39bSDmitry Baryshkov 	else
211*9d1cf39bSDmitry Baryshkov #endif
212*9d1cf39bSDmitry Baryshkov #ifdef CONFIG_PXA3xx
213*9d1cf39bSDmitry Baryshkov 	if (cpu_is_pxa3xx())
214*9d1cf39bSDmitry Baryshkov 		pxa_ac97_warm_pxa3xx();
215*9d1cf39bSDmitry Baryshkov 	else
216*9d1cf39bSDmitry Baryshkov #endif
217*9d1cf39bSDmitry Baryshkov 		BUG();
218*9d1cf39bSDmitry Baryshkov 
2199c636342SDmitry Baryshkov 	if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR))) {
2209c636342SDmitry Baryshkov 		printk(KERN_INFO "%s: warm reset timeout (GSR=%#lx)\n",
2219c636342SDmitry Baryshkov 				 __func__, gsr_bits);
2229c636342SDmitry Baryshkov 
2239c636342SDmitry Baryshkov 		return false;
2249c636342SDmitry Baryshkov 	}
2259c636342SDmitry Baryshkov 
2269c636342SDmitry Baryshkov 	return true;
2279c636342SDmitry Baryshkov }
2289c636342SDmitry Baryshkov EXPORT_SYMBOL_GPL(pxa2xx_ac97_try_warm_reset);
2299c636342SDmitry Baryshkov 
2309c636342SDmitry Baryshkov bool pxa2xx_ac97_try_cold_reset(struct snd_ac97 *ac97)
2319c636342SDmitry Baryshkov {
232*9d1cf39bSDmitry Baryshkov #ifdef CONFIG_PXA25x
233*9d1cf39bSDmitry Baryshkov 	if (cpu_is_pxa21x() || cpu_is_pxa25x())
234*9d1cf39bSDmitry Baryshkov 		pxa_ac97_cold_pxa25x();
235*9d1cf39bSDmitry Baryshkov 	else
2369c636342SDmitry Baryshkov #endif
2379c636342SDmitry Baryshkov #ifdef CONFIG_PXA27x
238*9d1cf39bSDmitry Baryshkov 	if (cpu_is_pxa27x())
239*9d1cf39bSDmitry Baryshkov 		pxa_ac97_cold_pxa27x();
240*9d1cf39bSDmitry Baryshkov 	else
2419c636342SDmitry Baryshkov #endif
242*9d1cf39bSDmitry Baryshkov #ifdef CONFIG_PXA3xx
243*9d1cf39bSDmitry Baryshkov 	if (cpu_is_pxa3xx())
244*9d1cf39bSDmitry Baryshkov 		pxa_ac97_cold_pxa3xx();
245*9d1cf39bSDmitry Baryshkov 	else
246*9d1cf39bSDmitry Baryshkov #endif
247*9d1cf39bSDmitry Baryshkov 		BUG();
2489c636342SDmitry Baryshkov 
2499c636342SDmitry Baryshkov 	if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR))) {
2509c636342SDmitry Baryshkov 		printk(KERN_INFO "%s: cold reset timeout (GSR=%#lx)\n",
2519c636342SDmitry Baryshkov 				 __func__, gsr_bits);
2529c636342SDmitry Baryshkov 
2539c636342SDmitry Baryshkov 		return false;
2549c636342SDmitry Baryshkov 	}
2559c636342SDmitry Baryshkov 
2569c636342SDmitry Baryshkov 	return true;
2579c636342SDmitry Baryshkov }
2589c636342SDmitry Baryshkov EXPORT_SYMBOL_GPL(pxa2xx_ac97_try_cold_reset);
2599c636342SDmitry Baryshkov 
2609c636342SDmitry Baryshkov 
2619c636342SDmitry Baryshkov void pxa2xx_ac97_finish_reset(struct snd_ac97 *ac97)
2629c636342SDmitry Baryshkov {
2639c636342SDmitry Baryshkov 	GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
2649c636342SDmitry Baryshkov 	GCR |= GCR_SDONE_IE|GCR_CDONE_IE;
2659c636342SDmitry Baryshkov }
2669c636342SDmitry Baryshkov EXPORT_SYMBOL_GPL(pxa2xx_ac97_finish_reset);
2679c636342SDmitry Baryshkov 
2689c636342SDmitry Baryshkov static irqreturn_t pxa2xx_ac97_irq(int irq, void *dev_id)
2699c636342SDmitry Baryshkov {
2709c636342SDmitry Baryshkov 	long status;
2719c636342SDmitry Baryshkov 
2729c636342SDmitry Baryshkov 	status = GSR;
2739c636342SDmitry Baryshkov 	if (status) {
2749c636342SDmitry Baryshkov 		GSR = status;
2759c636342SDmitry Baryshkov 		gsr_bits |= status;
2769c636342SDmitry Baryshkov 		wake_up(&gsr_wq);
2779c636342SDmitry Baryshkov 
2789c636342SDmitry Baryshkov 		/* Although we don't use those we still need to clear them
2799c636342SDmitry Baryshkov 		   since they tend to spuriously trigger when MMC is used
2809c636342SDmitry Baryshkov 		   (hardware bug? go figure)... */
281*9d1cf39bSDmitry Baryshkov 		if (cpu_is_pxa27x()) {
2829c636342SDmitry Baryshkov 			MISR = MISR_EOC;
2839c636342SDmitry Baryshkov 			PISR = PISR_EOC;
2849c636342SDmitry Baryshkov 			MCSR = MCSR_EOC;
285*9d1cf39bSDmitry Baryshkov 		}
2869c636342SDmitry Baryshkov 
2879c636342SDmitry Baryshkov 		return IRQ_HANDLED;
2889c636342SDmitry Baryshkov 	}
2899c636342SDmitry Baryshkov 
2909c636342SDmitry Baryshkov 	return IRQ_NONE;
2919c636342SDmitry Baryshkov }
2929c636342SDmitry Baryshkov 
2939c636342SDmitry Baryshkov #ifdef CONFIG_PM
2949c636342SDmitry Baryshkov int pxa2xx_ac97_hw_suspend(void)
2959c636342SDmitry Baryshkov {
2969c636342SDmitry Baryshkov 	GCR |= GCR_ACLINK_OFF;
2979c636342SDmitry Baryshkov 	clk_disable(ac97_clk);
2989c636342SDmitry Baryshkov 	return 0;
2999c636342SDmitry Baryshkov }
3009c636342SDmitry Baryshkov EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_suspend);
3019c636342SDmitry Baryshkov 
3029c636342SDmitry Baryshkov int pxa2xx_ac97_hw_resume(void)
3039c636342SDmitry Baryshkov {
304*9d1cf39bSDmitry Baryshkov 	if (cpu_is_pxa21x() || cpu_is_pxa25x() || cpu_is_pxa27x()) {
3059c636342SDmitry Baryshkov 		pxa_gpio_mode(GPIO31_SYNC_AC97_MD);
3069c636342SDmitry Baryshkov 		pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD);
3079c636342SDmitry Baryshkov 		pxa_gpio_mode(GPIO28_BITCLK_AC97_MD);
3089c636342SDmitry Baryshkov 		pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD);
309*9d1cf39bSDmitry Baryshkov 	}
310*9d1cf39bSDmitry Baryshkov 	if (cpu_is_pxa27x()) {
3119c636342SDmitry Baryshkov 		/* Use GPIO 113 as AC97 Reset on Bulverde */
3129c636342SDmitry Baryshkov 		pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
313*9d1cf39bSDmitry Baryshkov 	}
3149c636342SDmitry Baryshkov 	clk_enable(ac97_clk);
3159c636342SDmitry Baryshkov 	return 0;
3169c636342SDmitry Baryshkov }
3179c636342SDmitry Baryshkov EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_resume);
3189c636342SDmitry Baryshkov #endif
3199c636342SDmitry Baryshkov 
3209c636342SDmitry Baryshkov int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev)
3219c636342SDmitry Baryshkov {
3229c636342SDmitry Baryshkov 	int ret;
3239c636342SDmitry Baryshkov 
3249c636342SDmitry Baryshkov 	ret = request_irq(IRQ_AC97, pxa2xx_ac97_irq, 0, "AC97", NULL);
3259c636342SDmitry Baryshkov 	if (ret < 0)
3269c636342SDmitry Baryshkov 		goto err;
3279c636342SDmitry Baryshkov 
328*9d1cf39bSDmitry Baryshkov 	if (cpu_is_pxa21x() || cpu_is_pxa25x() || cpu_is_pxa27x()) {
3299c636342SDmitry Baryshkov 		pxa_gpio_mode(GPIO31_SYNC_AC97_MD);
3309c636342SDmitry Baryshkov 		pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD);
3319c636342SDmitry Baryshkov 		pxa_gpio_mode(GPIO28_BITCLK_AC97_MD);
3329c636342SDmitry Baryshkov 		pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD);
333*9d1cf39bSDmitry Baryshkov 	}
334*9d1cf39bSDmitry Baryshkov 
335*9d1cf39bSDmitry Baryshkov 	if (cpu_is_pxa27x()) {
3369c636342SDmitry Baryshkov 		/* Use GPIO 113 as AC97 Reset on Bulverde */
3379c636342SDmitry Baryshkov 		pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
3389c636342SDmitry Baryshkov 		ac97conf_clk = clk_get(&dev->dev, "AC97CONFCLK");
3399c636342SDmitry Baryshkov 		if (IS_ERR(ac97conf_clk)) {
3409c636342SDmitry Baryshkov 			ret = PTR_ERR(ac97conf_clk);
3419c636342SDmitry Baryshkov 			ac97conf_clk = NULL;
3429c636342SDmitry Baryshkov 			goto err_irq;
3439c636342SDmitry Baryshkov 		}
344*9d1cf39bSDmitry Baryshkov 	}
3459c636342SDmitry Baryshkov 
3469c636342SDmitry Baryshkov 	ac97_clk = clk_get(&dev->dev, "AC97CLK");
3479c636342SDmitry Baryshkov 	if (IS_ERR(ac97_clk)) {
3489c636342SDmitry Baryshkov 		ret = PTR_ERR(ac97_clk);
3499c636342SDmitry Baryshkov 		ac97_clk = NULL;
3509c636342SDmitry Baryshkov 		goto err_irq;
3519c636342SDmitry Baryshkov 	}
3529c636342SDmitry Baryshkov 
3539c636342SDmitry Baryshkov 	return clk_enable(ac97_clk);
3549c636342SDmitry Baryshkov 
3559c636342SDmitry Baryshkov err_irq:
3569c636342SDmitry Baryshkov 	GCR |= GCR_ACLINK_OFF;
3579c636342SDmitry Baryshkov 	if (ac97conf_clk) {
3589c636342SDmitry Baryshkov 		clk_put(ac97conf_clk);
3599c636342SDmitry Baryshkov 		ac97conf_clk = NULL;
3609c636342SDmitry Baryshkov 	}
3619c636342SDmitry Baryshkov 	free_irq(IRQ_AC97, NULL);
3629c636342SDmitry Baryshkov err:
3639c636342SDmitry Baryshkov 	return ret;
3649c636342SDmitry Baryshkov }
3659c636342SDmitry Baryshkov EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_probe);
3669c636342SDmitry Baryshkov 
3679c636342SDmitry Baryshkov void pxa2xx_ac97_hw_remove(struct platform_device *dev)
3689c636342SDmitry Baryshkov {
3699c636342SDmitry Baryshkov 	GCR |= GCR_ACLINK_OFF;
3709c636342SDmitry Baryshkov 	free_irq(IRQ_AC97, NULL);
371*9d1cf39bSDmitry Baryshkov 	if (ac97conf_clk) {
3729c636342SDmitry Baryshkov 		clk_put(ac97conf_clk);
3739c636342SDmitry Baryshkov 		ac97conf_clk = NULL;
374*9d1cf39bSDmitry Baryshkov 	}
3759c636342SDmitry Baryshkov 	clk_disable(ac97_clk);
3769c636342SDmitry Baryshkov 	clk_put(ac97_clk);
3779c636342SDmitry Baryshkov 	ac97_clk = NULL;
3789c636342SDmitry Baryshkov }
3799c636342SDmitry Baryshkov EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_remove);
3809c636342SDmitry Baryshkov 
3819c636342SDmitry Baryshkov MODULE_AUTHOR("Nicolas Pitre");
3829c636342SDmitry Baryshkov MODULE_DESCRIPTION("Intel/Marvell PXA sound library");
3839c636342SDmitry Baryshkov MODULE_LICENSE("GPL");
3849c636342SDmitry Baryshkov 
385