X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=sound%2Farm%2Fpxa2xx-ac97.c;h=5b3274b465eb5b22cdf525bc26d4855e4c371096;hb=14defd90f5281da8a1bf43bc789efbafe5991cd8;hp=55c6c822bec13eb82cb18a764b28678bf2c31558;hpb=88fb61e4ba263685a0d5b82c7e9cd6f22a9e6a9d;p=linux-2.6 diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c index 55c6c822be..5b3274b465 100644 --- a/sound/arm/pxa2xx-ac97.c +++ b/sound/arm/pxa2xx-ac97.c @@ -16,9 +16,9 @@ #include #include #include +#include #include -#include #include #include #include @@ -28,6 +28,7 @@ #include #include #include +#include #include #include "pxa2xx-pcm.h" @@ -36,6 +37,10 @@ static DEFINE_MUTEX(car_mutex); static DECLARE_WAIT_QUEUE_HEAD(gsr_wq); static volatile long gsr_bits; +static struct clk *ac97_clk; +#ifdef CONFIG_PXA27x +static struct clk *ac97conf_clk; +#endif /* * Beware PXA27x bugs: @@ -67,7 +72,7 @@ static unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg if (wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1) <= 0 && !((GSR | gsr_bits) & GSR_SDONE)) { printk(KERN_ERR "%s: read error (ac97_reg=%d GSR=%#lx)\n", - __FUNCTION__, reg, GSR | gsr_bits); + __func__, reg, GSR | gsr_bits); val = -1; goto out; } @@ -99,7 +104,7 @@ static void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigne if (wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_CDONE, 1) <= 0 && !((GSR | gsr_bits) & GSR_CDONE)) printk(KERN_ERR "%s: write error (ac97_reg=%d GSR=%#lx)\n", - __FUNCTION__, reg, GSR | gsr_bits); + __func__, reg, GSR | gsr_bits); mutex_unlock(&car_mutex); } @@ -107,17 +112,35 @@ static void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigne static void pxa2xx_ac97_reset(struct snd_ac97 *ac97) { /* First, try cold reset */ +#ifdef CONFIG_PXA3xx + int timeout; + + /* Hold CLKBPB for 100us */ + GCR = 0; + GCR = GCR_CLKBPB; + udelay(100); + GCR = 0; +#endif + GCR &= GCR_COLD_RST; /* clear everything but nCRST */ GCR &= ~GCR_COLD_RST; /* then assert nCRST */ gsr_bits = 0; #ifdef CONFIG_PXA27x /* PXA27x Developers Manual section 13.5.2.2.1 */ - pxa_set_cken(CKEN_AC97CONF, 1); + clk_enable(ac97conf_clk); udelay(5); - pxa_set_cken(CKEN_AC97CONF, 0); + clk_disable(ac97conf_clk); GCR = GCR_COLD_RST; udelay(50); +#elif defined(CONFIG_PXA3xx) + timeout = 1000; + /* Can't use interrupts on PXA3xx */ + GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN); + + GCR = GCR_WARM_RST | GCR_COLD_RST; + while (!(GSR & (GSR_PCR | GSR_SCR)) && timeout--) + mdelay(10); #else GCR = GCR_COLD_RST; GCR |= GCR_CDONE_IE|GCR_SDONE_IE; @@ -126,7 +149,7 @@ static void pxa2xx_ac97_reset(struct snd_ac97 *ac97) if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR))) { printk(KERN_INFO "%s: cold reset timeout (GSR=%#lx)\n", - __FUNCTION__, gsr_bits); + __func__, gsr_bits); /* let's try warm reset */ gsr_bits = 0; @@ -138,6 +161,12 @@ static void pxa2xx_ac97_reset(struct snd_ac97 *ac97) GCR |= GCR_WARM_RST; pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT); udelay(500); +#elif defined(CONFIG_PXA3xx) + timeout = 100; + /* Can't use interrupts */ + GCR |= GCR_WARM_RST; + while (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--) + mdelay(1); #else GCR |= GCR_WARM_RST|GCR_PRIRDY_IEN|GCR_SECRDY_IEN; wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1); @@ -145,7 +174,7 @@ static void pxa2xx_ac97_reset(struct snd_ac97 *ac97) if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR))) printk(KERN_INFO "%s: warm reset timeout (GSR=%#lx)\n", - __FUNCTION__, gsr_bits); + __func__, gsr_bits); } GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN); @@ -260,7 +289,7 @@ static int pxa2xx_ac97_do_suspend(struct snd_card *card, pm_message_t state) if (platform_ops && platform_ops->suspend) platform_ops->suspend(platform_ops->priv); GCR |= GCR_ACLINK_OFF; - pxa_set_cken(CKEN_AC97, 0); + clk_disable(ac97_clk); return 0; } @@ -269,7 +298,7 @@ static int pxa2xx_ac97_do_resume(struct snd_card *card) { pxa2xx_audio_ops_t *platform_ops = card->dev->platform_data; - pxa_set_cken(CKEN_AC97, 1); + clk_enable(ac97_clk); if (platform_ops && platform_ops->resume) platform_ops->resume(platform_ops->priv); snd_ac97_resume(pxa2xx_ac97_ac97); @@ -336,8 +365,21 @@ static int __devinit pxa2xx_ac97_probe(struct platform_device *dev) #ifdef CONFIG_PXA27x /* Use GPIO 113 as AC97 Reset on Bulverde */ pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT); + ac97conf_clk = clk_get(&dev->dev, "AC97CONFCLK"); + if (IS_ERR(ac97conf_clk)) { + ret = PTR_ERR(ac97conf_clk); + ac97conf_clk = NULL; + goto err; + } #endif - pxa_set_cken(CKEN_AC97, 1); + + ac97_clk = clk_get(&dev->dev, "AC97CLK"); + if (IS_ERR(ac97_clk)) { + ret = PTR_ERR(ac97_clk); + ac97_clk = NULL; + goto err; + } + clk_enable(ac97_clk); ret = snd_ac97_bus(card, 0, &pxa2xx_ac97_ops, NULL, &ac97_bus); if (ret) @@ -352,6 +394,7 @@ static int __devinit pxa2xx_ac97_probe(struct platform_device *dev) snprintf(card->longname, sizeof(card->longname), "%s (%s)", dev->dev.driver->name, card->mixername); + snd_card_set_dev(card, &dev->dev); ret = snd_card_register(card); if (ret == 0) { platform_set_drvdata(dev, card); @@ -361,11 +404,19 @@ static int __devinit pxa2xx_ac97_probe(struct platform_device *dev) err: if (card) snd_card_free(card); - if (CKEN & (1 << CKEN_AC97)) { + if (ac97_clk) { GCR |= GCR_ACLINK_OFF; free_irq(IRQ_AC97, NULL); - pxa_set_cken(CKEN_AC97, 0); + clk_disable(ac97_clk); + clk_put(ac97_clk); + ac97_clk = NULL; + } +#ifdef CONFIG_PXA27x + if (ac97conf_clk) { + clk_put(ac97conf_clk); + ac97conf_clk = NULL; } +#endif return ret; } @@ -378,7 +429,13 @@ static int __devexit pxa2xx_ac97_remove(struct platform_device *dev) platform_set_drvdata(dev, NULL); GCR |= GCR_ACLINK_OFF; free_irq(IRQ_AC97, NULL); - pxa_set_cken(CKEN_AC97, 0); + clk_disable(ac97_clk); + clk_put(ac97_clk); + ac97_clk = NULL; +#ifdef CONFIG_PXA27x + clk_put(ac97conf_clk); + ac97conf_clk = NULL; +#endif } return 0; @@ -391,6 +448,7 @@ static struct platform_driver pxa2xx_ac97_driver = { .resume = pxa2xx_ac97_resume, .driver = { .name = "pxa2xx-ac97", + .owner = THIS_MODULE, }, }; @@ -410,3 +468,4 @@ module_exit(pxa2xx_ac97_exit); MODULE_AUTHOR("Nicolas Pitre"); MODULE_DESCRIPTION("AC97 driver for the Intel PXA2xx chip"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:pxa2xx-ac97");