[alsa-devel] [PATCH] Permit simultaneous compilation of both PXA AC97 drivers
Signed-off-by: Dmitry Baryshkov dbaryshkov@gmail.com --- sound/soc/pxa/pxa2xx-pcm.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c index 2df03ee..45ac468 100644 --- a/sound/soc/pxa/pxa2xx-pcm.c +++ b/sound/soc/pxa/pxa2xx-pcm.c @@ -330,7 +330,7 @@ static void pxa2xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
static u64 pxa2xx_pcm_dmamask = DMA_32BIT_MASK;
-int pxa2xx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, +static int pxa2xx_soc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, struct snd_pcm *pcm) { int ret = 0; @@ -360,7 +360,7 @@ int pxa2xx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, struct snd_soc_platform pxa2xx_soc_platform = { .name = "pxa2xx-audio", .pcm_ops = &pxa2xx_pcm_ops, - .pcm_new = pxa2xx_pcm_new, + .pcm_new = pxa2xx_soc_pcm_new, .pcm_free = pxa2xx_pcm_free_dma_buffers, }; EXPORT_SYMBOL_GPL(pxa2xx_soc_platform);
ASoC and non-ASoC drivers for ACLINK on PXA share lot's of common code. Move all common code into separate file.
Signed-off-by: Dmitry Baryshkov dbaryshkov@gmail.com --- sound/arm/pxa2xx-ac97-lib.c | 275 +++++++++++++++++++++++++++++++++++++++++++ sound/arm/pxa2xx-ac97.c | 233 +++--------------------------------- sound/soc/pxa/pxa2xx-ac97.c | 257 ++-------------------------------------- 3 files changed, 302 insertions(+), 463 deletions(-) create mode 100644 sound/arm/pxa2xx-ac97-lib.c
diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/arm/pxa2xx-ac97-lib.c new file mode 100644 index 0000000..ee0de4d --- /dev/null +++ b/sound/arm/pxa2xx-ac97-lib.c @@ -0,0 +1,275 @@ + +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: + * + * o Slot 12 read from modem space will hang controller. + * o CDONE, SDONE interrupt fails after any slot 12 IO. + * + * We therefore have an hybrid approach for waiting on SDONE (interrupt or + * 1 jiffy timeout if interrupt never comes). + */ + +static unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg) +{ + unsigned short val = -1; + volatile u32 *reg_addr; + + mutex_lock(&car_mutex); + + /* set up primary or secondary codec space */ +#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) + reg_addr = (ac97->num & 1) ? &SAC_REG_BASE : &PAC_REG_BASE; +#else + if (reg == AC97_GPIO_STATUS) + reg_addr = ac97->num ? &SMC_REG_BASE : &PMC_REG_BASE; + else + reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE; +#endif + reg_addr += (reg >> 1); + + /* start read access across the ac97 link */ + GSR = GSR_CDONE | GSR_SDONE; + gsr_bits = 0; + val = *reg_addr; + if (reg == AC97_GPIO_STATUS) + goto out; + 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", + __func__, reg, GSR | gsr_bits); + val = -1; + goto out; + } + + /* valid data now */ + GSR = GSR_CDONE | GSR_SDONE; + gsr_bits = 0; + val = *reg_addr; + /* but we've just started another cycle... */ + wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1); + +out: mutex_unlock(&car_mutex); + return val; +} + +static void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val) +{ + volatile u32 *reg_addr; + + mutex_lock(&car_mutex); + + /* set up primary or secondary codec space */ +#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) + reg_addr = (ac97->num & 1) ? &SAC_REG_BASE : &PAC_REG_BASE; +#else + if (reg == AC97_GPIO_STATUS) + reg_addr = ac97->num ? &SMC_REG_BASE : &PMC_REG_BASE; + else + reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE; +#endif + reg_addr += (reg >> 1); + + GSR = GSR_CDONE | GSR_SDONE; + gsr_bits = 0; + *reg_addr = val; + 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", + __func__, reg, GSR | gsr_bits); + + mutex_unlock(&car_mutex); +} + +static bool pxa2xx_ac97_try_warm_reset(struct snd_ac97 *ac97) +{ +#ifdef CONFIG_PXA3xx + int timeout = 100; +#endif + gsr_bits = 0; + +#ifdef CONFIG_PXA27x + /* warm reset broken on Bulverde, + so manually keep AC97 reset high */ + pxa_gpio_mode(113 | GPIO_OUT | GPIO_DFLT_HIGH); + udelay(10); + GCR |= GCR_WARM_RST; + pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT); + udelay(500); +#elif defined(CONFIG_PXA3xx) + /* 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); +#endif + + if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR))) + return false; + + return true; +} + +static bool pxa2xx_ac97_try_cold_reset(struct snd_ac97 *ac97) +{ +#ifdef CONFIG_PXA3xx + int timeout = 1000; + + /* 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 */ + clk_enable(ac97conf_clk); + udelay(5); + clk_disable(ac97conf_clk); + GCR = GCR_COLD_RST; + udelay(50); +#elif defined(CONFIG_PXA3xx) + /* 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; + wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1); +#endif + + if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR))) + return false; + + return true; +} + + +static void pxa2xx_ac97_finish_reset(struct snd_ac97 *ac97) +{ + GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN); + GCR |= GCR_SDONE_IE|GCR_CDONE_IE; +} + +static irqreturn_t pxa2xx_ac97_irq(int irq, void *dev_id) +{ + long status; + + status = GSR; + if (status) { + GSR = status; + gsr_bits |= status; + wake_up(&gsr_wq); + +#ifdef CONFIG_PXA27x + /* Although we don't use those we still need to clear them + since they tend to spuriously trigger when MMC is used + (hardware bug? go figure)... */ + MISR = MISR_EOC; + PISR = PISR_EOC; + MCSR = MCSR_EOC; +#endif + + return IRQ_HANDLED; + } + + return IRQ_NONE; +} + +#ifdef CONFIG_PM +static int pxa2xx_ac97_hw_suspend(void) +{ + GCR |= GCR_ACLINK_OFF; + clk_disable(ac97_clk); + return 0; +} + +static int pxa2xx_ac97_hw_resume(void) +{ + pxa_gpio_mode(GPIO31_SYNC_AC97_MD); + pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD); + pxa_gpio_mode(GPIO28_BITCLK_AC97_MD); + pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD); +#ifdef CONFIG_PXA27x + /* Use GPIO 113 as AC97 Reset on Bulverde */ + pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT); +#endif + clk_enable(ac97_clk); + return 0; +} +#endif + +static int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev) +{ + int ret; + + ret = request_irq(IRQ_AC97, pxa2xx_ac97_irq, 0, "AC97", NULL); + if (ret < 0) + goto err; + + pxa_gpio_mode(GPIO31_SYNC_AC97_MD); + pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD); + pxa_gpio_mode(GPIO28_BITCLK_AC97_MD); + pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD); +#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_irq; + } +#endif + + ac97_clk = clk_get(&dev->dev, "AC97CLK"); + if (IS_ERR(ac97_clk)) { + ret = PTR_ERR(ac97_clk); + ac97_clk = NULL; + goto err_irq; + } + + return clk_enable(ac97_clk); + +err_irq: + GCR |= GCR_ACLINK_OFF; +#ifdef CONFIG_PXA27x + if (ac97conf_clk) { + clk_put(ac97conf_clk); + ac97conf_clk = NULL; + } +#endif + free_irq(IRQ_AC97, NULL); +err: + return ret; +} + +static void pxa2xx_ac97_hw_remove(struct platform_device *dev) +{ + GCR |= GCR_ACLINK_OFF; + free_irq(IRQ_AC97, NULL); +#ifdef CONFIG_PXA27x + clk_put(ac97conf_clk); + ac97conf_clk = NULL; +#endif + clk_disable(ac97_clk); + clk_put(ac97_clk); + ac97_clk = NULL; +} diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c index 5b3274b..cb29076 100644 --- a/sound/arm/pxa2xx-ac97.c +++ b/sound/arm/pxa2xx-ac97.c @@ -33,177 +33,20 @@
#include "pxa2xx-pcm.h"
- -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: - * - * o Slot 12 read from modem space will hang controller. - * o CDONE, SDONE interrupt fails after any slot 12 IO. - * - * We therefore have an hybrid approach for waiting on SDONE (interrupt or - * 1 jiffy timeout if interrupt never comes). - */ - -static unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg) -{ - unsigned short val = -1; - volatile u32 *reg_addr; - - mutex_lock(&car_mutex); - - /* set up primary or secondary codec space */ - reg_addr = (ac97->num & 1) ? &SAC_REG_BASE : &PAC_REG_BASE; - reg_addr += (reg >> 1); - - /* start read access across the ac97 link */ - GSR = GSR_CDONE | GSR_SDONE; - gsr_bits = 0; - val = *reg_addr; - if (reg == AC97_GPIO_STATUS) - goto out; - 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", - __func__, reg, GSR | gsr_bits); - val = -1; - goto out; - } - - /* valid data now */ - GSR = GSR_CDONE | GSR_SDONE; - gsr_bits = 0; - val = *reg_addr; - /* but we've just started another cycle... */ - wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1); - -out: mutex_unlock(&car_mutex); - return val; -} - -static void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val) -{ - volatile u32 *reg_addr; - - mutex_lock(&car_mutex); - - /* set up primary or secondary codec space */ - reg_addr = (ac97->num & 1) ? &SAC_REG_BASE : &PAC_REG_BASE; - reg_addr += (reg >> 1); - - GSR = GSR_CDONE | GSR_SDONE; - gsr_bits = 0; - *reg_addr = val; - 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", - __func__, reg, GSR | gsr_bits); - - mutex_unlock(&car_mutex); -} +#include "pxa2xx-ac97-lib.c"
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 */ - clk_enable(ac97conf_clk); - udelay(5); - 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; - wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1); -#endif - - if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR))) { + if (!pxa2xx_ac97_try_cold_reset(ac97)) { printk(KERN_INFO "%s: cold reset timeout (GSR=%#lx)\n", __func__, gsr_bits);
- /* let's try warm reset */ - gsr_bits = 0; -#ifdef CONFIG_PXA27x - /* warm reset broken on Bulverde, - so manually keep AC97 reset high */ - pxa_gpio_mode(113 | GPIO_OUT | GPIO_DFLT_HIGH); - udelay(10); - 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); -#endif - - if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR))) + if (!pxa2xx_ac97_try_warm_reset(ac97)) printk(KERN_INFO "%s: warm reset timeout (GSR=%#lx)\n", __func__, gsr_bits); }
- GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN); - GCR |= GCR_SDONE_IE|GCR_CDONE_IE; -} - -static irqreturn_t pxa2xx_ac97_irq(int irq, void *dev_id) -{ - long status; - - status = GSR; - if (status) { - GSR = status; - gsr_bits |= status; - wake_up(&gsr_wq); - -#ifdef CONFIG_PXA27x - /* Although we don't use those we still need to clear them - since they tend to spuriously trigger when MMC is used - (hardware bug? go figure)... */ - MISR = MISR_EOC; - PISR = PISR_EOC; - MCSR = MCSR_EOC; -#endif - - return IRQ_HANDLED; - } - - return IRQ_NONE; + pxa2xx_ac97_finish_reset(ac97); }
static struct snd_ac97_bus_ops pxa2xx_ac97_ops = { @@ -288,17 +131,19 @@ static int pxa2xx_ac97_do_suspend(struct snd_card *card, pm_message_t state) snd_ac97_suspend(pxa2xx_ac97_ac97); if (platform_ops && platform_ops->suspend) platform_ops->suspend(platform_ops->priv); - GCR |= GCR_ACLINK_OFF; - clk_disable(ac97_clk);
- return 0; + return pxa2xx_ac97_hw_suspend(); }
static int pxa2xx_ac97_do_resume(struct snd_card *card) { pxa2xx_audio_ops_t *platform_ops = card->dev->platform_data; + int rc; + + rc = pxa2xx_ac97_hw_resume(); + if (rc) + return rc;
- clk_enable(ac97_clk); if (platform_ops && platform_ops->resume) platform_ops->resume(platform_ops->priv); snd_ac97_resume(pxa2xx_ac97_ac97); @@ -354,40 +199,17 @@ static int __devinit pxa2xx_ac97_probe(struct platform_device *dev) if (ret) goto err;
- ret = request_irq(IRQ_AC97, pxa2xx_ac97_irq, 0, "AC97", NULL); - if (ret < 0) - goto err; - - pxa_gpio_mode(GPIO31_SYNC_AC97_MD); - pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD); - pxa_gpio_mode(GPIO28_BITCLK_AC97_MD); - pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD); -#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 - - ac97_clk = clk_get(&dev->dev, "AC97CLK"); - if (IS_ERR(ac97_clk)) { - ret = PTR_ERR(ac97_clk); - ac97_clk = NULL; + ret = pxa2xx_ac97_hw_probe(dev); + if (ret) goto err; - } - clk_enable(ac97_clk);
ret = snd_ac97_bus(card, 0, &pxa2xx_ac97_ops, NULL, &ac97_bus); if (ret) - goto err; + goto err_remove; memset(&ac97_template, 0, sizeof(ac97_template)); ret = snd_ac97_mixer(ac97_bus, &ac97_template, &pxa2xx_ac97_ac97); if (ret) - goto err; + goto err_remove;
snprintf(card->shortname, sizeof(card->shortname), "%s", snd_ac97_get_short_name(pxa2xx_ac97_ac97)); @@ -401,22 +223,11 @@ static int __devinit pxa2xx_ac97_probe(struct platform_device *dev) return 0; }
- err: +err_remove: + pxa2xx_ac97_hw_remove(dev); +err: if (card) snd_card_free(card); - if (ac97_clk) { - GCR |= GCR_ACLINK_OFF; - free_irq(IRQ_AC97, NULL); - 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; }
@@ -427,15 +238,7 @@ static int __devexit pxa2xx_ac97_remove(struct platform_device *dev) if (card) { snd_card_free(card); platform_set_drvdata(dev, NULL); - GCR |= GCR_ACLINK_OFF; - free_irq(IRQ_AC97, NULL); - clk_disable(ac97_clk); - clk_put(ac97_clk); - ac97_clk = NULL; -#ifdef CONFIG_PXA27x - clk_put(ac97conf_clk); - ac97conf_clk = NULL; -#endif + pxa2xx_ac97_hw_remove(dev); }
return 0; diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c index 059af81..0b5a920 100644 --- a/sound/soc/pxa/pxa2xx-ac97.c +++ b/sound/soc/pxa/pxa2xx-ac97.c @@ -34,204 +34,24 @@ #include "pxa2xx-pcm.h" #include "pxa2xx-ac97.h"
-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: - * - * o Slot 12 read from modem space will hang controller. - * o CDONE, SDONE interrupt fails after any slot 12 IO. - * - * We therefore have an hybrid approach for waiting on SDONE (interrupt or - * 1 jiffy timeout if interrupt never comes). - */ - -static unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97, - unsigned short reg) -{ - unsigned short val = -1; - volatile u32 *reg_addr; - - mutex_lock(&car_mutex); - - /* set up primary or secondary codec/modem space */ -#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) - reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE; -#else - if (reg == AC97_GPIO_STATUS) - reg_addr = ac97->num ? &SMC_REG_BASE : &PMC_REG_BASE; - else - reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE; -#endif - reg_addr += (reg >> 1); - -#ifndef CONFIG_PXA27x - if (reg == AC97_GPIO_STATUS) { - /* read from controller cache */ - val = *reg_addr; - goto out; - } -#endif - - /* start read access across the ac97 link */ - GSR = GSR_CDONE | GSR_SDONE; - gsr_bits = 0; - val = *reg_addr; - - wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1); - if (!((GSR | gsr_bits) & GSR_SDONE)) { - printk(KERN_ERR "%s: read error (ac97_reg=%x GSR=%#lx)\n", - __func__, reg, GSR | gsr_bits); - val = -1; - goto out; - } - - /* valid data now */ - GSR = GSR_CDONE | GSR_SDONE; - gsr_bits = 0; - val = *reg_addr; - /* but we've just started another cycle... */ - wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1); - -out: mutex_unlock(&car_mutex); - return val; -} - -static void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg, - unsigned short val) -{ - volatile u32 *reg_addr; - - mutex_lock(&car_mutex); - - /* set up primary or secondary codec/modem space */ -#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) - reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE; -#else - if (reg == AC97_GPIO_STATUS) - reg_addr = ac97->num ? &SMC_REG_BASE : &PMC_REG_BASE; - else - reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE; -#endif - reg_addr += (reg >> 1); - - GSR = GSR_CDONE | GSR_SDONE; - gsr_bits = 0; - *reg_addr = val; - wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_CDONE, 1); - if (!((GSR | gsr_bits) & GSR_CDONE)) - printk(KERN_ERR "%s: write error (ac97_reg=%x GSR=%#lx)\n", - __func__, reg, GSR | gsr_bits); - - mutex_unlock(&car_mutex); -} +#include "../../arm/pxa2xx-ac97-lib.c"
static void pxa2xx_ac97_warm_reset(struct snd_ac97 *ac97) { -#ifdef CONFIG_PXA3xx - int timeout = 100; -#endif - gsr_bits = 0; - -#ifdef CONFIG_PXA27x - /* warm reset broken on Bulverde, - so manually keep AC97 reset high */ - pxa_gpio_mode(113 | GPIO_OUT | GPIO_DFLT_HIGH); - udelay(10); - GCR |= GCR_WARM_RST; - pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT); - udelay(500); -#elif defined(CONFIG_PXA3xx) - /* 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); -#endif - - if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR))) + if (!pxa2xx_ac97_try_warm_reset(ac97)) printk(KERN_INFO "%s: warm reset timeout (GSR=%#lx)\n", __func__, gsr_bits);
- GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN); - GCR |= GCR_SDONE_IE|GCR_CDONE_IE; + pxa2xx_ac97_finish_reset(ac97); }
static void pxa2xx_ac97_cold_reset(struct snd_ac97 *ac97) { -#ifdef CONFIG_PXA3xx - int timeout = 1000; - - /* 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 */ - clk_enable(ac97conf_clk); - udelay(5); - clk_disable(ac97conf_clk); - GCR = GCR_COLD_RST; - udelay(50); -#elif defined(CONFIG_PXA3xx) - /* 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; - wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1); -#endif - - if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR))) + if (!pxa2xx_ac97_try_cold_reset(ac97)) printk(KERN_INFO "%s: cold reset timeout (GSR=%#lx)\n", __func__, gsr_bits);
- GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN); - GCR |= GCR_SDONE_IE|GCR_CDONE_IE; -} - -static irqreturn_t pxa2xx_ac97_irq(int irq, void *dev_id) -{ - long status; - - status = GSR; - if (status) { - GSR = status; - gsr_bits |= status; - wake_up(&gsr_wq); - -#ifdef CONFIG_PXA27x - /* Although we don't use those we still need to clear them - since they tend to spuriously trigger when MMC is used - (hardware bug? go figure)... */ - MISR = MISR_EOC; - PISR = PISR_EOC; - MCSR = MCSR_EOC; -#endif - - return IRQ_HANDLED; - } - - return IRQ_NONE; + pxa2xx_ac97_finish_reset(ac97); }
struct snd_ac97_bus_ops soc_ac97_ops = { @@ -285,24 +105,13 @@ static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_mic_mono_in = { static int pxa2xx_ac97_suspend(struct platform_device *pdev, struct snd_soc_dai *dai) { - GCR |= GCR_ACLINK_OFF; - clk_disable(ac97_clk); - return 0; + return pxa2xx_ac97_hw_suspend(); }
static int pxa2xx_ac97_resume(struct platform_device *pdev, struct snd_soc_dai *dai) { - pxa_gpio_mode(GPIO31_SYNC_AC97_MD); - pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD); - pxa_gpio_mode(GPIO28_BITCLK_AC97_MD); - pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD); -#ifdef CONFIG_PXA27x - /* Use GPIO 113 as AC97 Reset on Bulverde */ - pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT); -#endif - clk_enable(ac97_clk); - return 0; + return pxa2xx_ac97_hw_resume(); }
#else @@ -313,61 +122,13 @@ static int pxa2xx_ac97_resume(struct platform_device *pdev, static int pxa2xx_ac97_probe(struct platform_device *pdev, struct snd_soc_dai *dai) { - int ret; - - ret = request_irq(IRQ_AC97, pxa2xx_ac97_irq, IRQF_DISABLED, "AC97", NULL); - if (ret < 0) - goto err; - - pxa_gpio_mode(GPIO31_SYNC_AC97_MD); - pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD); - pxa_gpio_mode(GPIO28_BITCLK_AC97_MD); - pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD); -#ifdef CONFIG_PXA27x - /* Use GPIO 113 as AC97 Reset on Bulverde */ - pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT); - - ac97conf_clk = clk_get(&pdev->dev, "AC97CONFCLK"); - if (IS_ERR(ac97conf_clk)) { - ret = PTR_ERR(ac97conf_clk); - ac97conf_clk = NULL; - goto err_irq; - } -#endif - ac97_clk = clk_get(&pdev->dev, "AC97CLK"); - if (IS_ERR(ac97_clk)) { - ret = PTR_ERR(ac97_clk); - ac97_clk = NULL; - goto err_irq; - } - clk_enable(ac97_clk); - return 0; - - err_irq: - GCR |= GCR_ACLINK_OFF; -#ifdef CONFIG_PXA27x - if (ac97conf_clk) { - clk_put(ac97conf_clk); - ac97conf_clk = NULL; - } -#endif - free_irq(IRQ_AC97, NULL); - err: - return ret; + return pxa2xx_ac97_hw_probe(pdev); }
static void pxa2xx_ac97_remove(struct platform_device *pdev, struct snd_soc_dai *dai) { - GCR |= GCR_ACLINK_OFF; - free_irq(IRQ_AC97, NULL); -#ifdef CONFIG_PXA27x - clk_put(ac97conf_clk); - ac97conf_clk = NULL; -#endif - clk_disable(ac97_clk); - clk_put(ac97_clk); - ac97_clk = NULL; + pxa2xx_ac97_hw_remove(pdev); }
static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream,
Make pxa-ac97-lib separate compilation unit, thus cleaning up all dependencies.
Signed-off-by: Dmitry Baryshkov dbaryshkov@gmail.com --- include/sound/pxa2xx-lib.h | 17 +++++++++++++ sound/arm/Kconfig | 5 ++++ sound/arm/Makefile | 3 ++ sound/arm/pxa2xx-ac97-lib.c | 55 ++++++++++++++++++++++++++++++++++-------- sound/arm/pxa2xx-ac97.c | 18 +------------ sound/soc/pxa/Kconfig | 2 + sound/soc/pxa/pxa2xx-ac97.c | 21 ++-------------- 7 files changed, 76 insertions(+), 45 deletions(-) create mode 100644 include/sound/pxa2xx-lib.h
diff --git a/include/sound/pxa2xx-lib.h b/include/sound/pxa2xx-lib.h new file mode 100644 index 0000000..a300e46 --- /dev/null +++ b/include/sound/pxa2xx-lib.h @@ -0,0 +1,17 @@ +#ifndef PXA2XX_LIB_H +#define PXA2XX_LIB_H + +extern unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg); +extern void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val); + +extern bool pxa2xx_ac97_try_warm_reset(struct snd_ac97 *ac97); +extern bool pxa2xx_ac97_try_cold_reset(struct snd_ac97 *ac97); +extern void pxa2xx_ac97_finish_reset(struct snd_ac97 *ac97); + +extern int pxa2xx_ac97_hw_suspend(void); +extern int pxa2xx_ac97_hw_resume(void); + +extern int pxa2xx_ac97_hw_probe(struct platform_device *dev); +extern void pxa2xx_ac97_hw_remove(struct platform_device *dev); + +#endif diff --git a/sound/arm/Kconfig b/sound/arm/Kconfig index 351e19e..556ed8b 100644 --- a/sound/arm/Kconfig +++ b/sound/arm/Kconfig @@ -32,10 +32,15 @@ config SND_PXA2XX_PCM tristate select SND_PCM
+config SND_PXA2XX_LIB + tristate + select SND_AC97_CODEC + config SND_PXA2XX_AC97 tristate "AC97 driver for the Intel PXA2xx chip" depends on ARCH_PXA select SND_PXA2XX_PCM + select SND_PXA2XX select SND_AC97_CODEC help Say Y or M if you want to support any AC97 codec attached to diff --git a/sound/arm/Makefile b/sound/arm/Makefile index 4ef6dd0..bb2ed88 100644 --- a/sound/arm/Makefile +++ b/sound/arm/Makefile @@ -11,5 +11,8 @@ snd-aaci-objs := aaci.o devdma.o obj-$(CONFIG_SND_PXA2XX_PCM) += snd-pxa2xx-pcm.o snd-pxa2xx-pcm-objs := pxa2xx-pcm.o
+obj-$(CONFIG_SND_PXA2XX_LIB) += snd-pxa2xx-lib.o +snd-pxa2xx-lib-objs := pxa2xx-ac97-lib.o + obj-$(CONFIG_SND_PXA2XX_AC97) += snd-pxa2xx-ac97.o snd-pxa2xx-ac97-objs := pxa2xx-ac97.o diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/arm/pxa2xx-ac97-lib.c index ee0de4d..87c75b9 100644 --- a/sound/arm/pxa2xx-ac97-lib.c +++ b/sound/arm/pxa2xx-ac97-lib.c @@ -1,3 +1,18 @@ +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/interrupt.h> +#include <linux/clk.h> +#include <linux/delay.h> + +#include <sound/ac97_codec.h> +#include <sound/pxa2xx-lib.h> + +#include <asm/irq.h> +#include <asm/hardware.h> + +#include <asm/arch/pxa-regs.h> +#include <asm/arch/pxa2xx-gpio.h> +#include <asm/arch/audio.h>
static DEFINE_MUTEX(car_mutex); static DECLARE_WAIT_QUEUE_HEAD(gsr_wq); @@ -17,7 +32,7 @@ static struct clk *ac97conf_clk; * 1 jiffy timeout if interrupt never comes). */
-static unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg) +unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg) { unsigned short val = -1; volatile u32 *reg_addr; @@ -59,8 +74,9 @@ static unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg out: mutex_unlock(&car_mutex); return val; } +EXPORT_SYMBOL(pxa2xx_ac97_read);
-static void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val) +void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val) { volatile u32 *reg_addr;
@@ -87,8 +103,9 @@ static void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigne
mutex_unlock(&car_mutex); } +EXPORT_SYMBOL(pxa2xx_ac97_write);
-static bool pxa2xx_ac97_try_warm_reset(struct snd_ac97 *ac97) +bool pxa2xx_ac97_try_warm_reset(struct snd_ac97 *ac97) { #ifdef CONFIG_PXA3xx int timeout = 100; @@ -113,13 +130,18 @@ static bool pxa2xx_ac97_try_warm_reset(struct snd_ac97 *ac97) wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1); #endif
- if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR))) + if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR))) { + printk(KERN_INFO "%s: warm reset timeout (GSR=%#lx)\n", + __func__, gsr_bits); + return false; + }
return true; } +EXPORT_SYMBOL(pxa2xx_ac97_try_warm_reset);
-static bool pxa2xx_ac97_try_cold_reset(struct snd_ac97 *ac97) +bool pxa2xx_ac97_try_cold_reset(struct snd_ac97 *ac97) { #ifdef CONFIG_PXA3xx int timeout = 1000; @@ -155,18 +177,24 @@ static bool pxa2xx_ac97_try_cold_reset(struct snd_ac97 *ac97) wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1); #endif
- if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR))) + if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR))) { + printk(KERN_INFO "%s: cold reset timeout (GSR=%#lx)\n", + __func__, gsr_bits); + return false; + }
return true; } +EXPORT_SYMBOL(pxa2xx_ac97_try_cold_reset);
-static void pxa2xx_ac97_finish_reset(struct snd_ac97 *ac97) +void pxa2xx_ac97_finish_reset(struct snd_ac97 *ac97) { GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN); GCR |= GCR_SDONE_IE|GCR_CDONE_IE; } +EXPORT_SYMBOL(pxa2xx_ac97_finish_reset);
static irqreturn_t pxa2xx_ac97_irq(int irq, void *dev_id) { @@ -194,14 +222,15 @@ static irqreturn_t pxa2xx_ac97_irq(int irq, void *dev_id) }
#ifdef CONFIG_PM -static int pxa2xx_ac97_hw_suspend(void) +int pxa2xx_ac97_hw_suspend(void) { GCR |= GCR_ACLINK_OFF; clk_disable(ac97_clk); return 0; } +EXPORT_SYMBOL(pxa2xx_ac97_hw_suspend);
-static int pxa2xx_ac97_hw_resume(void) +int pxa2xx_ac97_hw_resume(void) { pxa_gpio_mode(GPIO31_SYNC_AC97_MD); pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD); @@ -214,9 +243,10 @@ static int pxa2xx_ac97_hw_resume(void) clk_enable(ac97_clk); return 0; } +EXPORT_SYMBOL(pxa2xx_ac97_hw_resume); #endif
-static int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev) +int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev) { int ret;
@@ -260,8 +290,9 @@ err_irq: err: return ret; } +EXPORT_SYMBOL(pxa2xx_ac97_hw_probe);
-static void pxa2xx_ac97_hw_remove(struct platform_device *dev) +void pxa2xx_ac97_hw_remove(struct platform_device *dev) { GCR |= GCR_ACLINK_OFF; free_irq(IRQ_AC97, NULL); @@ -273,3 +304,5 @@ static void pxa2xx_ac97_hw_remove(struct platform_device *dev) clk_put(ac97_clk); ac97_clk = NULL; } +EXPORT_SYMBOL(pxa2xx_ac97_hw_remove); + diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c index cb29076..52f3f50 100644 --- a/sound/arm/pxa2xx-ac97.c +++ b/sound/arm/pxa2xx-ac97.c @@ -12,38 +12,24 @@
#include <linux/init.h> #include <linux/module.h> -#include <linux/kernel.h> #include <linux/platform_device.h> -#include <linux/interrupt.h> -#include <linux/wait.h> -#include <linux/clk.h> -#include <linux/delay.h>
#include <sound/core.h> #include <sound/pcm.h> #include <sound/ac97_codec.h> #include <sound/initval.h> +#include <sound/pxa2xx-lib.h>
-#include <asm/irq.h> -#include <linux/mutex.h> #include <asm/hardware.h> #include <asm/arch/pxa-regs.h> -#include <asm/arch/pxa2xx-gpio.h> #include <asm/arch/audio.h>
#include "pxa2xx-pcm.h"
-#include "pxa2xx-ac97-lib.c" - static void pxa2xx_ac97_reset(struct snd_ac97 *ac97) { if (!pxa2xx_ac97_try_cold_reset(ac97)) { - printk(KERN_INFO "%s: cold reset timeout (GSR=%#lx)\n", - __func__, gsr_bits); - - if (!pxa2xx_ac97_try_warm_reset(ac97)) - printk(KERN_INFO "%s: warm reset timeout (GSR=%#lx)\n", - __func__, gsr_bits); + pxa2xx_ac97_try_warm_reset(ac97); }
pxa2xx_ac97_finish_reset(ac97); diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index 9212c37..d1ccbdc 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig @@ -13,6 +13,8 @@ config SND_PXA2XX_AC97 config SND_PXA2XX_SOC_AC97 tristate select AC97_BUS + select SND_ARM + select SND_PXA2XX_LIB select SND_SOC_AC97_BUS
config SND_PXA2XX_SOC_I2S diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c index 0b5a920..3db5630 100644 --- a/sound/soc/pxa/pxa2xx-ac97.c +++ b/sound/soc/pxa/pxa2xx-ac97.c @@ -13,43 +13,28 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/platform_device.h> -#include <linux/interrupt.h> -#include <linux/wait.h> -#include <linux/clk.h> -#include <linux/delay.h>
#include <sound/core.h> -#include <sound/pcm.h> #include <sound/ac97_codec.h> -#include <sound/initval.h> #include <sound/soc.h> +#include <sound/pxa2xx-lib.h>
-#include <asm/irq.h> -#include <linux/mutex.h> #include <asm/hardware.h> #include <asm/arch/pxa-regs.h> -#include <asm/arch/pxa2xx-gpio.h> -#include <asm/arch/audio.h>
#include "pxa2xx-pcm.h" #include "pxa2xx-ac97.h"
-#include "../../arm/pxa2xx-ac97-lib.c" - static void pxa2xx_ac97_warm_reset(struct snd_ac97 *ac97) { - if (!pxa2xx_ac97_try_warm_reset(ac97)) - printk(KERN_INFO "%s: warm reset timeout (GSR=%#lx)\n", - __func__, gsr_bits); + pxa2xx_ac97_try_warm_reset(ac97);
pxa2xx_ac97_finish_reset(ac97); }
static void pxa2xx_ac97_cold_reset(struct snd_ac97 *ac97) { - if (!pxa2xx_ac97_try_cold_reset(ac97)) - printk(KERN_INFO "%s: cold reset timeout (GSR=%#lx)\n", - __func__, gsr_bits); + pxa2xx_ac97_try_cold_reset(ac97);
pxa2xx_ac97_finish_reset(ac97); }
Support building pxa2xx-lib for several pxa chip versions by making code run-time selected, not only compile-time
Signed-off-by: Dmitry Baryshkov dbaryshkov@gmail.com --- sound/arm/pxa2xx-ac97-lib.c | 183 ++++++++++++++++++++++++++----------------- 1 files changed, 111 insertions(+), 72 deletions(-)
diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/arm/pxa2xx-ac97-lib.c index 87c75b9..9576d24 100644 --- a/sound/arm/pxa2xx-ac97-lib.c +++ b/sound/arm/pxa2xx-ac97-lib.c @@ -35,18 +35,22 @@ static struct clk *ac97conf_clk; unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg) { unsigned short val = -1; - volatile u32 *reg_addr; + volatile u32 *reg_addr = NULL;
mutex_lock(&car_mutex);
/* set up primary or secondary codec space */ #if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) - reg_addr = (ac97->num & 1) ? &SAC_REG_BASE : &PAC_REG_BASE; -#else - if (reg == AC97_GPIO_STATUS) - reg_addr = ac97->num ? &SMC_REG_BASE : &PMC_REG_BASE; - else - reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE; + if (cpu_is_pxa27x() || cpu_is_pxa3xx()) + reg_addr = (ac97->num & 1) ? &SAC_REG_BASE : &PAC_REG_BASE; +#endif +#ifdef CONFIG_PXA25x + if (cpu_is_pxa21x() || cpu_is_pxa25x()) { + if (reg == AC97_GPIO_STATUS) + reg_addr = ac97->num ? &SMC_REG_BASE : &PMC_REG_BASE; + else + reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE; + } #endif reg_addr += (reg >> 1);
@@ -78,18 +82,22 @@ EXPORT_SYMBOL(pxa2xx_ac97_read);
void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short val) { - volatile u32 *reg_addr; + volatile u32 *reg_addr = NULL;
mutex_lock(&car_mutex);
/* set up primary or secondary codec space */ #if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) - reg_addr = (ac97->num & 1) ? &SAC_REG_BASE : &PAC_REG_BASE; -#else - if (reg == AC97_GPIO_STATUS) - reg_addr = ac97->num ? &SMC_REG_BASE : &PMC_REG_BASE; - else - reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE; + if (cpu_is_pxa27x() || cpu_is_pxa3xx()) + reg_addr = (ac97->num & 1) ? &SAC_REG_BASE : &PAC_REG_BASE; +#endif +#ifdef CONFIG_PXA25x + if (cpu_is_pxa21x() || cpu_is_pxa25x()) { + if (reg == AC97_GPIO_STATUS) + reg_addr = ac97->num ? &SMC_REG_BASE : &PMC_REG_BASE; + else + reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE; + } #endif reg_addr += (reg >> 1);
@@ -113,21 +121,29 @@ bool pxa2xx_ac97_try_warm_reset(struct snd_ac97 *ac97) gsr_bits = 0;
#ifdef CONFIG_PXA27x - /* warm reset broken on Bulverde, - so manually keep AC97 reset high */ - pxa_gpio_mode(113 | GPIO_OUT | GPIO_DFLT_HIGH); - udelay(10); - GCR |= GCR_WARM_RST; - pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT); - udelay(500); -#elif defined(CONFIG_PXA3xx) - /* 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); + if (cpu_is_pxa27x()) { + /* warm reset broken on Bulverde, + so manually keep AC97 reset high */ + pxa_gpio_mode(113 | GPIO_OUT | GPIO_DFLT_HIGH); + udelay(10); + GCR |= GCR_WARM_RST; + pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT); + udelay(500); + } +#endif +#ifdef CONFIG_PXA3xx + if (cpu_is_pxa3xx()) { + /* Can't use interrupts */ + GCR |= GCR_WARM_RST; + while (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--) + mdelay(1); + } +#endif +#ifdef CONFIG_PXA25x + if (cpu_is_pxa21x() || cpu_is_pxa25x()) { + GCR |= GCR_WARM_RST | GCR_PRIRDY_IEN | GCR_SECRDY_IEN; + wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1); + } #endif
if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR))) { @@ -146,11 +162,13 @@ bool pxa2xx_ac97_try_cold_reset(struct snd_ac97 *ac97) #ifdef CONFIG_PXA3xx int timeout = 1000;
- /* Hold CLKBPB for 100us */ - GCR = 0; - GCR = GCR_CLKBPB; - udelay(100); - GCR = 0; + if (cpu_is_pxa3xx()) { + /* Hold CLKBPB for 100us */ + GCR = 0; + GCR = GCR_CLKBPB; + udelay(100); + GCR = 0; + } #endif
GCR &= GCR_COLD_RST; /* clear everything but nCRST */ @@ -158,23 +176,31 @@ bool pxa2xx_ac97_try_cold_reset(struct snd_ac97 *ac97)
gsr_bits = 0; #ifdef CONFIG_PXA27x - /* PXA27x Developers Manual section 13.5.2.2.1 */ - clk_enable(ac97conf_clk); - udelay(5); - clk_disable(ac97conf_clk); - GCR = GCR_COLD_RST; - udelay(50); -#elif defined(CONFIG_PXA3xx) - /* Can't use interrupts on PXA3xx */ - GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN); + if (cpu_is_pxa27x()) { + /* PXA27x Developers Manual section 13.5.2.2.1 */ + clk_enable(ac97conf_clk); + udelay(5); + clk_disable(ac97conf_clk); + GCR = GCR_COLD_RST; + udelay(50); + } +#endif +#ifdef CONFIG_PXA3xx + if (cpu_is_pxa3xx()) { + /* 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; - wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1); + GCR = GCR_WARM_RST | GCR_COLD_RST; + while (!(GSR & (GSR_PCR | GSR_SCR)) && timeout--) + mdelay(10); + } +#endif +#ifdef CONFIG_PXA25x + if (cpu_is_pxa21x() || cpu_is_pxa25x()) { + GCR = GCR_COLD_RST; + GCR |= GCR_CDONE_IE|GCR_SDONE_IE; + wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1); + } #endif
if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR))) { @@ -210,9 +236,11 @@ static irqreturn_t pxa2xx_ac97_irq(int irq, void *dev_id) /* Although we don't use those we still need to clear them since they tend to spuriously trigger when MMC is used (hardware bug? go figure)... */ - MISR = MISR_EOC; - PISR = PISR_EOC; - MCSR = MCSR_EOC; + if (cpu_is_pxa27x()) { + MISR = MISR_EOC; + PISR = PISR_EOC; + MCSR = MCSR_EOC; + } #endif
return IRQ_HANDLED; @@ -232,14 +260,16 @@ EXPORT_SYMBOL(pxa2xx_ac97_hw_suspend);
int pxa2xx_ac97_hw_resume(void) { - pxa_gpio_mode(GPIO31_SYNC_AC97_MD); - pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD); - pxa_gpio_mode(GPIO28_BITCLK_AC97_MD); - pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD); + if (!cpu_is_pxa3xx()) { + pxa_gpio_mode(GPIO31_SYNC_AC97_MD); + pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD); + pxa_gpio_mode(GPIO28_BITCLK_AC97_MD); + pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD); #ifdef CONFIG_PXA27x - /* Use GPIO 113 as AC97 Reset on Bulverde */ - pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT); + /* Use GPIO 113 as AC97 Reset on Bulverde */ + pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT); #endif + } clk_enable(ac97_clk); return 0; } @@ -254,18 +284,25 @@ int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev) if (ret < 0) goto err;
- pxa_gpio_mode(GPIO31_SYNC_AC97_MD); - pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD); - pxa_gpio_mode(GPIO28_BITCLK_AC97_MD); - pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD); + if (!cpu_is_pxa3xx()) { + pxa_gpio_mode(GPIO31_SYNC_AC97_MD); + pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD); + pxa_gpio_mode(GPIO28_BITCLK_AC97_MD); + pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD); #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_irq; + /* Use GPIO 113 as AC97 Reset on Bulverde */ + pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT); +#endif + } + +#ifdef CONFIG_PXA27x + if (cpu_is_pxa27x()) { + ac97conf_clk = clk_get(&dev->dev, "AC97CONFCLK"); + if (IS_ERR(ac97conf_clk)) { + ret = PTR_ERR(ac97conf_clk); + ac97conf_clk = NULL; + goto err_irq; + } } #endif
@@ -297,8 +334,10 @@ void pxa2xx_ac97_hw_remove(struct platform_device *dev) GCR |= GCR_ACLINK_OFF; free_irq(IRQ_AC97, NULL); #ifdef CONFIG_PXA27x - clk_put(ac97conf_clk); - ac97conf_clk = NULL; + if (ac97conf_clk) { + clk_put(ac97conf_clk); + ac97conf_clk = NULL; + } #endif clk_disable(ac97_clk); clk_put(ac97_clk);
[...]
(in pxa2xx_ac97_hw_resume)
pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD);
#ifdef CONFIG_PXA27x
- /* Use GPIO 113 as AC97 Reset on Bulverde */
- pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
/* Use GPIO 113 as AC97 Reset on Bulverde */
pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
#endif
forgot a cpu_is_pxa27x()
[...]
(in pxa2xx_ac97_hw_probe
goto err_irq;
/* Use GPIO 113 as AC97 Reset on Bulverde */
pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
+#endif
another one
On Sat, Jul 26, 2008 at 01:51:51AM +0400, Dmitry Baryshkov wrote:
Signed-off-by: Dmitry Baryshkov dbaryshkov@gmail.com
I should have said, that these patches are largely untested. Please test before applying.
On Sat, Jul 26, 2008 at 02:15:17AM +0400, Dmitry Baryshkov wrote:
I should have said, that these patches are largely untested. Please test before applying.
Yeah, unfortunately it's kind of hard to get good test coverage due to the number of variants :/ . On the basis of the diffs these patches look good, though the volume of code motion means that I'll do another pass later. I'll also test with the hardware I have and then push up to Takashi (assuming I don't spot any issues) - it may be the middle of next week before that happens. Other test reports would be appreciated.
This is certainly a very welcome cleanup - thanks a lot for doing it!
On Sat, 2008-07-26 at 12:06 +0100, Mark Brown wrote:
On Sat, Jul 26, 2008 at 02:15:17AM +0400, Dmitry Baryshkov wrote:
I should have said, that these patches are largely untested. Please test before applying.
Yeah, unfortunately it's kind of hard to get good test coverage due to the number of variants :/ . On the basis of the diffs these patches look good, though the volume of code motion means that I'll do another pass later. I'll also test with the hardware I have and then push up to Takashi (assuming I don't spot any issues) - it may be the middle of next week before that happens. Other test reports would be appreciated.
This is certainly a very welcome cleanup - thanks a lot for doing it!
Agreed, thanks for the cleanup. :)
However this really *must* be tested on all pxa variants before upstreaming. The pxa family all have slightly different AC97 controller hardware (and quirks) and subsequently it may work fine on your board but break others :-/
We can certainly test on pxa270 and pxa320. Can someone else do the other variants.
Btw, the tests should also include AC97 slot 12 IO. i.e read and write codec register 0x54.
Thanks
Liam
Yep, I can do all the verfication on all pxa3xx variants and platforms :-)
-----Original Message----- From: Liam Girdwood [mailto:lg@opensource.wolfsonmicro.com] Sent: Saturday, July 26, 2008 8:23 PM To: Dmitry Baryshkov Cc: Mark Brown; alsa-devel@alsa-project.org; Eric Miao; rmk@arm.linux.org.uk Subject: Re: [alsa-devel] [PATCH] Permit simultaneous compilation ofboth PXA AC97 drivers
On Sat, 2008-07-26 at 12:06 +0100, Mark Brown wrote:
On Sat, Jul 26, 2008 at 02:15:17AM +0400, Dmitry Baryshkov wrote:
I should have said, that these patches are largely untested. Please test before applying.
Yeah, unfortunately it's kind of hard to get good test coverage due to the number of variants :/ . On the basis of the diffs these patches look good, though the volume of code motion means that I'll do another pass later. I'll also test with the hardware I have and then push up to Takashi (assuming I don't spot any issues) - it may be the middle of next week before that happens. Other test reports would be appreciated.
This is certainly a very welcome cleanup - thanks a lot for doing it!
Agreed, thanks for the cleanup. :)
However this really *must* be tested on all pxa variants before upstreaming. The pxa family all have slightly different AC97 controller hardware (and quirks) and subsequently it may work fine on your board but break others :-/
We can certainly test on pxa270 and pxa320. Can someone else do the other variants.
Btw, the tests should also include AC97 slot 12 IO. i.e read and write codec register 0x54.
Thanks
Liam
participants (5)
-
Dmitry Baryshkov
-
Eric Miao
-
Liam Girdwood
-
Mark Brown
-
Russ Dill