* [GIT PULL] unify two pxa sound drivers
@ 2008-09-08 8:53 Dmitry Baryshkov
2008-09-08 9:05 ` Liam Girdwood
2008-09-08 9:06 ` [PATCH 1/5] Permit simultaneous compilation of both PXA AC97 drivers Dmitry Baryshkov
0 siblings, 2 replies; 17+ messages in thread
From: Dmitry Baryshkov @ 2008-09-08 8:53 UTC (permalink / raw)
To: alsa-devel
Hi,
Please consider this changeset. It was partially tested, but additional
testing will be appreciated. pxa3xx was only compile tested.
The following changes since commit 6a55617ed5d1aa62b850de2cf66f5ede2eef4825:
Linus Torvalds (1):
Linux v2.6.27-rc4
are available in the git repository at:
git://git.infradead.org/users/dbaryshkov/zaurus-2.6.git pxa2xx-asoc-cleanup
Dmitry Baryshkov (4):
Permit simultaneous compilation of both PXA AC97 drivers
Separate common pxa2xx-ac97 code
Make pxa-ac97-lib separate module
Separate common pxa2xx-pcm code
Russ Dill (1):
pxa2xx-lib: support building for several pxa's
arch/arm/mach-pxa/include/mach/pxa-regs.h | 4 +-
include/sound/pxa2xx-lib.h | 45 +++++
sound/arm/Kconfig | 9 +-
sound/arm/Makefile | 4 +
sound/arm/pxa2xx-ac97-lib.c | 297 +++++++++++++++++++++++++++++
sound/arm/pxa2xx-ac97.c | 247 ++----------------------
sound/arm/pxa2xx-pcm-lib.c | 277 +++++++++++++++++++++++++++
sound/arm/pxa2xx-pcm.c | 252 +-----------------------
sound/arm/pxa2xx-pcm.h | 13 +-
sound/soc/pxa/Kconfig | 3 +
sound/soc/pxa/pxa2xx-ac97.c | 272 +-------------------------
sound/soc/pxa/pxa2xx-i2s.c | 26 ++-
sound/soc/pxa/pxa2xx-pcm.c | 265 +-------------------------
sound/soc/pxa/pxa2xx-pcm.h | 15 --
14 files changed, 707 insertions(+), 1022 deletions(-)
create mode 100644 include/sound/pxa2xx-lib.h
create mode 100644 sound/arm/pxa2xx-ac97-lib.c
create mode 100644 sound/arm/pxa2xx-pcm-lib.c
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 17+ messages in thread* Re: [GIT PULL] unify two pxa sound drivers 2008-09-08 8:53 [GIT PULL] unify two pxa sound drivers Dmitry Baryshkov @ 2008-09-08 9:05 ` Liam Girdwood 2008-09-08 9:06 ` [PATCH 1/5] Permit simultaneous compilation of both PXA AC97 drivers Dmitry Baryshkov 1 sibling, 0 replies; 17+ messages in thread From: Liam Girdwood @ 2008-09-08 9:05 UTC (permalink / raw) To: Dmitry Baryshkov; +Cc: alsa-devel On Mon, 2008-09-08 at 12:53 +0400, Dmitry Baryshkov wrote: > Hi, > > Please consider this changeset. It was partially tested, but additional > testing will be appreciated. pxa3xx was only compile tested. > > The following changes since commit 6a55617ed5d1aa62b850de2cf66f5ede2eef4825: > Linus Torvalds (1): > Linux v2.6.27-rc4 > > are available in the git repository at: > > git://git.infradead.org/users/dbaryshkov/zaurus-2.6.git pxa2xx-asoc-cleanup > > Dmitry Baryshkov (4): > Permit simultaneous compilation of both PXA AC97 drivers > Separate common pxa2xx-ac97 code > Make pxa-ac97-lib separate module > Separate common pxa2xx-pcm code > > Russ Dill (1): > pxa2xx-lib: support building for several pxa's > > arch/arm/mach-pxa/include/mach/pxa-regs.h | 4 +- > include/sound/pxa2xx-lib.h | 45 +++++ > sound/arm/Kconfig | 9 +- > sound/arm/Makefile | 4 + > sound/arm/pxa2xx-ac97-lib.c | 297 +++++++++++++++++++++++++++++ > sound/arm/pxa2xx-ac97.c | 247 ++---------------------- > sound/arm/pxa2xx-pcm-lib.c | 277 +++++++++++++++++++++++++++ > sound/arm/pxa2xx-pcm.c | 252 +----------------------- > sound/arm/pxa2xx-pcm.h | 13 +- > sound/soc/pxa/Kconfig | 3 + > sound/soc/pxa/pxa2xx-ac97.c | 272 +------------------------- > sound/soc/pxa/pxa2xx-i2s.c | 26 ++- > sound/soc/pxa/pxa2xx-pcm.c | 265 +------------------------- > sound/soc/pxa/pxa2xx-pcm.h | 15 -- > 14 files changed, 707 insertions(+), 1022 deletions(-) > create mode 100644 include/sound/pxa2xx-lib.h > create mode 100644 sound/arm/pxa2xx-ac97-lib.c > create mode 100644 sound/arm/pxa2xx-pcm-lib.c > I assume most changes are mechanical. Could you post for review too. Thanks Liam ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 1/5] Permit simultaneous compilation of both PXA AC97 drivers 2008-09-08 8:53 [GIT PULL] unify two pxa sound drivers Dmitry Baryshkov 2008-09-08 9:05 ` Liam Girdwood @ 2008-09-08 9:06 ` Dmitry Baryshkov 2008-09-08 9:06 ` [PATCH 2/5] Separate common pxa2xx-ac97 code Dmitry Baryshkov 2008-09-08 9:30 ` [PATCH 1/5] Permit simultaneous compilation of both PXA AC97 drivers Mark Brown 1 sibling, 2 replies; 17+ messages in thread From: Dmitry Baryshkov @ 2008-09-08 9:06 UTC (permalink / raw) To: alsa-devel; +Cc: Dmitry Baryshkov 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 4345f38..771c592 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); -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 2/5] Separate common pxa2xx-ac97 code 2008-09-08 9:06 ` [PATCH 1/5] Permit simultaneous compilation of both PXA AC97 drivers Dmitry Baryshkov @ 2008-09-08 9:06 ` Dmitry Baryshkov 2008-09-08 9:06 ` [PATCH 3/5] Make pxa-ac97-lib separate module Dmitry Baryshkov 2008-09-08 9:33 ` [PATCH 2/5] Separate common pxa2xx-ac97 code Liam Girdwood 2008-09-08 9:30 ` [PATCH 1/5] Permit simultaneous compilation of both PXA AC97 drivers Mark Brown 1 sibling, 2 replies; 17+ messages in thread From: Dmitry Baryshkov @ 2008-09-08 9:06 UTC (permalink / raw) To: alsa-devel; +Cc: Dmitry Baryshkov 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 199cca3..320ac75 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 d94a495..99f096d 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, -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 3/5] Make pxa-ac97-lib separate module 2008-09-08 9:06 ` [PATCH 2/5] Separate common pxa2xx-ac97 code Dmitry Baryshkov @ 2008-09-08 9:06 ` Dmitry Baryshkov 2008-09-08 9:06 ` [PATCH 4/5] pxa2xx-lib: support building for several pxa's Dmitry Baryshkov 2008-09-08 9:33 ` [PATCH 2/5] Separate common pxa2xx-ac97 code Liam Girdwood 1 sibling, 1 reply; 17+ messages in thread From: Dmitry Baryshkov @ 2008-09-08 9:06 UTC (permalink / raw) To: alsa-devel; +Cc: Dmitry Baryshkov 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 | 6 ++++- sound/arm/Makefile | 3 ++ sound/arm/pxa2xx-ac97-lib.c | 54 ++++++++++++++++++++++++++++++++++-------- sound/arm/pxa2xx-ac97.c | 18 +------------ sound/soc/pxa/Kconfig | 2 + sound/soc/pxa/pxa2xx-ac97.c | 21 ++-------------- 7 files changed, 75 insertions(+), 46 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..3fd2642 100644 --- a/sound/arm/Kconfig +++ b/sound/arm/Kconfig @@ -32,11 +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_AC97_CODEC + select SND_PXA2XX_LIB help Say Y or M if you want to support any AC97 codec attached to the PXA2xx AC97 interface. 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..6c73c49 100644 --- a/sound/arm/pxa2xx-ac97-lib.c +++ b/sound/arm/pxa2xx-ac97-lib.c @@ -1,3 +1,17 @@ +#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 <mach/hardware.h> +#include <mach/pxa-regs.h> +#include <mach/pxa2xx-gpio.h> +#include <mach/audio.h> static DEFINE_MUTEX(car_mutex); static DECLARE_WAIT_QUEUE_HEAD(gsr_wq); @@ -17,7 +31,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 +73,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 +102,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 +129,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 +176,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 +221,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 +242,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 +289,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 +303,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 320ac75..cba71d8 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 <mach/hardware.h> #include <mach/pxa-regs.h> -#include <mach/pxa2xx-gpio.h> #include <mach/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 99f096d..a80ae07 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 <mach/hardware.h> #include <mach/pxa-regs.h> -#include <mach/pxa2xx-gpio.h> -#include <mach/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); } -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 4/5] pxa2xx-lib: support building for several pxa's 2008-09-08 9:06 ` [PATCH 3/5] Make pxa-ac97-lib separate module Dmitry Baryshkov @ 2008-09-08 9:06 ` Dmitry Baryshkov 2008-09-08 9:06 ` [PATCH 5/5] Separate common pxa2xx-pcm code Dmitry Baryshkov 2008-09-08 10:17 ` [PATCH 4/5] pxa2xx-lib: support building for several pxa's Mark Brown 0 siblings, 2 replies; 17+ messages in thread From: Dmitry Baryshkov @ 2008-09-08 9:06 UTC (permalink / raw) To: alsa-devel; +Cc: Russ Dill, Dmitry Baryshkov From: Russ Dill <russ.dill@gmail.com> Here's a version of the third patch in the series without all the cpu_is_pxa3xx())'s around the pxa_gpio_mode's? Also, there was a build error when just building the sound/arm pxa2xx-ac97. Support building pxa2xx-lib for several pxa chip versions by making code run-time selected, not only compile-time Signed-off-by: Russ Dill <russ.dill@gmail.com> Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com> --- arch/arm/mach-pxa/include/mach/pxa-regs.h | 4 +- sound/arm/pxa2xx-ac97-lib.c | 174 ++++++++++++++--------------- sound/soc/pxa/pxa2xx-i2s.c | 16 ++- 3 files changed, 94 insertions(+), 100 deletions(-) diff --git a/arch/arm/mach-pxa/include/mach/pxa-regs.h b/arch/arm/mach-pxa/include/mach/pxa-regs.h index 12288ca..c978dfe 100644 --- a/arch/arm/mach-pxa/include/mach/pxa-regs.h +++ b/arch/arm/mach-pxa/include/mach/pxa-regs.h @@ -520,9 +520,7 @@ #define MCCR_FSRIE (1 << 1) /* FIFO Service Request Interrupt Enable */ #define GCR __REG(0x4050000C) /* Global Control Register */ -#ifdef CONFIG_PXA3xx -#define GCR_CLKBPB (1 << 31) /* Internal clock enable */ -#endif +#define GCR_CLKBPB (1 << 31) /* Internal clock enable, PXA3XX only */ #define GCR_nDMAEN (1 << 24) /* non DMA Enable */ #define GCR_CDONE_IE (1 << 19) /* Command Done Interrupt Enable */ #define GCR_SDONE_IE (1 << 18) /* Status Done Interrupt Enable */ diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/arm/pxa2xx-ac97-lib.c index 6c73c49..3802d68 100644 --- a/sound/arm/pxa2xx-ac97-lib.c +++ b/sound/arm/pxa2xx-ac97-lib.c @@ -17,9 +17,7 @@ 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: @@ -39,14 +37,10 @@ unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg) 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) + if ((cpu_is_pxa21x() || cpu_is_pxa25x()) && 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 */ @@ -82,14 +76,10 @@ void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short 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) + if ((cpu_is_pxa21x() || cpu_is_pxa25x()) && 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; @@ -106,28 +96,26 @@ EXPORT_SYMBOL(pxa2xx_ac97_write); 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 (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); + } else if (cpu_is_pxa3xx()) { + /* Can't use interrupts */ + int timeout = 100; + 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 (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR))) { printk(KERN_INFO "%s: warm reset timeout (GSR=%#lx)\n", @@ -142,39 +130,38 @@ EXPORT_SYMBOL(pxa2xx_ac97_try_warm_reset); 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 + if (cpu_is_pxa3xx()) { + /* Hold CLKBPB for 100us */ + GCR = 0; + GCR = GCR_CLKBPB; + udelay(100); + GCR = 0; + } 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 (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); + } else if (cpu_is_pxa3xx()) { + /* Can't use interrupts on PXA3xx */ + int timeout = 1000; + 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); + } if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR))) { printk(KERN_INFO "%s: cold reset timeout (GSR=%#lx)\n", @@ -205,14 +192,14 @@ static irqreturn_t pxa2xx_ac97_irq(int irq, void *dev_id) 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 + if (cpu_is_pxa27x()) { + MISR = MISR_EOC; + PISR = PISR_EOC; + MCSR = MCSR_EOC; + } return IRQ_HANDLED; } @@ -231,14 +218,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); -#ifdef CONFIG_PXA27x - /* Use GPIO 113 as AC97 Reset on Bulverde */ - pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT); -#endif + 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); + } + if (cpu_is_pxa27x()) { + /* Use GPIO 113 as AC97 Reset on Bulverde */ + pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT); + } clk_enable(ac97_clk); return 0; } @@ -253,20 +242,23 @@ 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); -#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; + 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); + } + + if (cpu_is_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)) { @@ -279,12 +271,10 @@ int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev) 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; @@ -295,10 +285,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; -#endif + if (ac97conf_clk) { + clk_put(ac97conf_clk); + ac97conf_clk = NULL; + } clk_disable(ac97_clk); clk_put(ac97_clk); ac97_clk = NULL; diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c index 8548818..533e1f5 100644 --- a/sound/soc/pxa/pxa2xx-i2s.c +++ b/sound/soc/pxa/pxa2xx-i2s.c @@ -64,11 +64,6 @@ static struct pxa2xx_gpio gpio_bus[] = { .frm = GPIO31_SYNC_I2S_MD, }, { /* I2S SoC Master */ -#ifdef CONFIG_PXA27x - .sys = GPIO113_I2S_SYSCLK_MD, -#else - .sys = GPIO32_SYSCLK_I2S_MD, -#endif .rx = GPIO29_SDATA_IN_I2S_MD, .tx = GPIO30_SDATA_OUT_I2S_MD, .clk = GPIO28_BITCLK_OUT_I2S_MD, @@ -317,6 +312,17 @@ struct snd_soc_dai pxa_i2s_dai = { EXPORT_SYMBOL_GPL(pxa_i2s_dai); +static int __init pxa_i2s_init(void) +{ + if (cpu_is_pxa27x()) + gpio_bus[1].sys = GPIO113_I2S_SYSCLK_MD; + else + gpio_bus[1].sys = GPIO32_SYSCLK_I2S_MD; + return 0; +} + +module_init(pxa_i2s_init); + /* Module information */ MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com"); MODULE_DESCRIPTION("pxa2xx I2S SoC Interface"); -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 5/5] Separate common pxa2xx-pcm code 2008-09-08 9:06 ` [PATCH 4/5] pxa2xx-lib: support building for several pxa's Dmitry Baryshkov @ 2008-09-08 9:06 ` Dmitry Baryshkov 2008-09-08 10:07 ` Eric Miao 2008-09-08 10:33 ` Mark Brown 2008-09-08 10:17 ` [PATCH 4/5] pxa2xx-lib: support building for several pxa's Mark Brown 1 sibling, 2 replies; 17+ messages in thread From: Dmitry Baryshkov @ 2008-09-08 9:06 UTC (permalink / raw) To: alsa-devel; +Cc: Dmitry Baryshkov ASoC and non-ASoC drivers for PCM DMA on PXA share lot's of common code. Move it to pxa2xx-lib. Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com> --- include/sound/pxa2xx-lib.h | 28 +++++ sound/arm/Kconfig | 7 +- sound/arm/Makefile | 3 +- sound/arm/pxa2xx-pcm-lib.c | 277 ++++++++++++++++++++++++++++++++++++++++++++ sound/arm/pxa2xx-pcm.c | 252 ++-------------------------------------- sound/arm/pxa2xx-pcm.h | 13 +- sound/soc/pxa/Kconfig | 3 +- sound/soc/pxa/pxa2xx-i2s.c | 10 ++ sound/soc/pxa/pxa2xx-pcm.c | 261 +---------------------------------------- sound/soc/pxa/pxa2xx-pcm.h | 15 --- 10 files changed, 346 insertions(+), 523 deletions(-) create mode 100644 sound/arm/pxa2xx-pcm-lib.c diff --git a/include/sound/pxa2xx-lib.h b/include/sound/pxa2xx-lib.h index a300e46..2fd3d25 100644 --- a/include/sound/pxa2xx-lib.h +++ b/include/sound/pxa2xx-lib.h @@ -1,6 +1,34 @@ #ifndef PXA2XX_LIB_H #define PXA2XX_LIB_H +#include <linux/platform_device.h> +#include <sound/ac97_codec.h> + +/* PCM */ + +struct pxa2xx_pcm_dma_params { + char *name; /* stream identifier */ + u32 dcmd; /* DMA descriptor dcmd field */ + volatile u32 *drcmr; /* the DMA request channel to use */ + u32 dev_addr; /* device physical address for DMA */ +}; + +extern int __pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params); +extern int __pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream); +extern int pxa2xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd); +extern snd_pcm_uframes_t pxa2xx_pcm_pointer(struct snd_pcm_substream *substream); +extern int __pxa2xx_pcm_prepare(struct snd_pcm_substream *substream); +extern void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id); +extern int __pxa2xx_pcm_open(struct snd_pcm_substream *substream); +extern int __pxa2xx_pcm_close(struct snd_pcm_substream *substream); +extern int pxa2xx_pcm_mmap(struct snd_pcm_substream *substream, + struct vm_area_struct *vma); +extern int pxa2xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream); +extern void pxa2xx_pcm_free_dma_buffers(struct snd_pcm *pcm); + +/* AC97 */ + 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); diff --git a/sound/arm/Kconfig b/sound/arm/Kconfig index 3fd2642..234708e 100644 --- a/sound/arm/Kconfig +++ b/sound/arm/Kconfig @@ -34,13 +34,16 @@ config SND_PXA2XX_PCM config SND_PXA2XX_LIB tristate - select SND_AC97_CODEC + select SND_AC97_CODEC if SND_PXA2XX_LIB_AC97 + +config SND_PXA2XX_LIB_AC97 + bool config SND_PXA2XX_AC97 tristate "AC97 driver for the Intel PXA2xx chip" depends on ARCH_PXA select SND_PXA2XX_PCM - select SND_PXA2XX_LIB + select SND_PXA2XX_LIB_AC97 help Say Y or M if you want to support any AC97 codec attached to the PXA2xx AC97 interface. diff --git a/sound/arm/Makefile b/sound/arm/Makefile index bb2ed88..2054de1 100644 --- a/sound/arm/Makefile +++ b/sound/arm/Makefile @@ -12,7 +12,8 @@ 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 +snd-pxa2xx-lib-y := pxa2xx-pcm-lib.o +snd-pxa2xx-lib-$(CONFIG_SND_PXA2XX_LIB_AC97) += 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-pcm-lib.c b/sound/arm/pxa2xx-pcm-lib.c new file mode 100644 index 0000000..fe20453 --- /dev/null +++ b/sound/arm/pxa2xx-pcm-lib.c @@ -0,0 +1,277 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/module.h> +#include <linux/dma-mapping.h> + +#include <sound/core.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/pxa2xx-lib.h> + +#include <asm/dma.h> +#include <mach/pxa-regs.h> + +#include "pxa2xx-pcm.h" + +static const struct snd_pcm_hardware pxa2xx_pcm_hardware = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_RESUME, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, + .period_bytes_min = 32, + .period_bytes_max = 8192 - 32, + .periods_min = 1, + .periods_max = PAGE_SIZE/sizeof(pxa_dma_desc), + .buffer_bytes_max = 128 * 1024, + .fifo_size = 32, +}; + +int __pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct pxa2xx_runtime_data *rtd = runtime->private_data; + size_t totsize = params_buffer_bytes(params); + size_t period = params_period_bytes(params); + pxa_dma_desc *dma_desc; + dma_addr_t dma_buff_phys, next_desc_phys; + + snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); + runtime->dma_bytes = totsize; + + dma_desc = rtd->dma_desc_array; + next_desc_phys = rtd->dma_desc_array_phys; + dma_buff_phys = runtime->dma_addr; + do { + next_desc_phys += sizeof(pxa_dma_desc); + dma_desc->ddadr = next_desc_phys; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + dma_desc->dsadr = dma_buff_phys; + dma_desc->dtadr = rtd->params->dev_addr; + } else { + dma_desc->dsadr = rtd->params->dev_addr; + dma_desc->dtadr = dma_buff_phys; + } + if (period > totsize) + period = totsize; + dma_desc->dcmd = rtd->params->dcmd | period | DCMD_ENDIRQEN; + dma_desc++; + dma_buff_phys += period; + } while (totsize -= period); + dma_desc[-1].ddadr = rtd->dma_desc_array_phys; + + return 0; +} +EXPORT_SYMBOL(__pxa2xx_pcm_hw_params); + +int __pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream) +{ + struct pxa2xx_runtime_data *rtd = substream->runtime->private_data; + + if (rtd && rtd->params) + *rtd->params->drcmr = 0; + + snd_pcm_set_runtime_buffer(substream, NULL); + return 0; +} +EXPORT_SYMBOL(__pxa2xx_pcm_hw_free); + +int pxa2xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct pxa2xx_runtime_data *prtd = substream->runtime->private_data; + int ret = 0; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + DDADR(prtd->dma_ch) = prtd->dma_desc_array_phys; + DCSR(prtd->dma_ch) = DCSR_RUN; + break; + + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + DCSR(prtd->dma_ch) &= ~DCSR_RUN; + break; + + case SNDRV_PCM_TRIGGER_RESUME: + DCSR(prtd->dma_ch) |= DCSR_RUN; + break; + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + DDADR(prtd->dma_ch) = prtd->dma_desc_array_phys; + DCSR(prtd->dma_ch) |= DCSR_RUN; + break; + + default: + ret = -EINVAL; + } + + return ret; +} +EXPORT_SYMBOL(pxa2xx_pcm_trigger); + +snd_pcm_uframes_t +pxa2xx_pcm_pointer(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct pxa2xx_runtime_data *prtd = runtime->private_data; + + dma_addr_t ptr = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? + DSADR(prtd->dma_ch) : DTADR(prtd->dma_ch); + snd_pcm_uframes_t x = bytes_to_frames(runtime, ptr - runtime->dma_addr); + + if (x == runtime->buffer_size) + x = 0; + return x; +} +EXPORT_SYMBOL(pxa2xx_pcm_pointer); + +int __pxa2xx_pcm_prepare(struct snd_pcm_substream *substream) +{ + struct pxa2xx_runtime_data *prtd = substream->runtime->private_data; + + DCSR(prtd->dma_ch) &= ~DCSR_RUN; + DCSR(prtd->dma_ch) = 0; + DCMD(prtd->dma_ch) = 0; + *prtd->params->drcmr = prtd->dma_ch | DRCMR_MAPVLD; + + return 0; +} +EXPORT_SYMBOL(__pxa2xx_pcm_prepare); + +void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id) +{ + struct snd_pcm_substream *substream = dev_id; + struct pxa2xx_runtime_data *rtd = substream->runtime->private_data; + int dcsr; + + dcsr = DCSR(dma_ch); + DCSR(dma_ch) = dcsr & ~DCSR_STOPIRQEN; + + if (dcsr & DCSR_ENDINTR) { + snd_pcm_period_elapsed(substream); + } else { + printk( KERN_ERR "%s: DMA error on channel %d (DCSR=%#x)\n", + rtd->params->name, dma_ch, dcsr ); + snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); + } +} +EXPORT_SYMBOL(pxa2xx_pcm_dma_irq); + +int __pxa2xx_pcm_open(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct pxa2xx_runtime_data *rtd; + int ret; + + runtime->hw = pxa2xx_pcm_hardware; + + /* + * For mysterious reasons (and despite what the manual says) + * playback samples are lost if the DMA count is not a multiple + * of the DMA burst size. Let's add a rule to enforce that. + */ + ret = snd_pcm_hw_constraint_step(runtime, 0, + SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32); + if (ret) + goto out; + + ret = snd_pcm_hw_constraint_step(runtime, 0, + SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32); + if (ret) + goto out; + + ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); + if (ret < 0) + goto out; + + ret = -ENOMEM; + rtd = kmalloc(sizeof(*rtd), GFP_KERNEL); + if (!rtd) + goto out; + rtd->dma_desc_array = + dma_alloc_writecombine(substream->pcm->card->dev, PAGE_SIZE, + &rtd->dma_desc_array_phys, GFP_KERNEL); + if (!rtd->dma_desc_array) + goto err1; + + runtime->private_data = rtd; + return 0; + + err1: + kfree(rtd); + out: + return ret; +} +EXPORT_SYMBOL(__pxa2xx_pcm_open); + +int __pxa2xx_pcm_close(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct pxa2xx_runtime_data *rtd = runtime->private_data; + + dma_free_writecombine(substream->pcm->card->dev, PAGE_SIZE, + rtd->dma_desc_array, rtd->dma_desc_array_phys); + kfree(rtd); + return 0; +} +EXPORT_SYMBOL(__pxa2xx_pcm_close); + +int pxa2xx_pcm_mmap(struct snd_pcm_substream *substream, + struct vm_area_struct *vma) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + return dma_mmap_writecombine(substream->pcm->card->dev, vma, + runtime->dma_area, + runtime->dma_addr, + runtime->dma_bytes); +} +EXPORT_SYMBOL(pxa2xx_pcm_mmap); + +int pxa2xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) +{ + struct snd_pcm_substream *substream = pcm->streams[stream].substream; + struct snd_dma_buffer *buf = &substream->dma_buffer; + size_t size = pxa2xx_pcm_hardware.buffer_bytes_max; + buf->dev.type = SNDRV_DMA_TYPE_DEV; + buf->dev.dev = pcm->card->dev; + buf->private_data = NULL; + buf->area = dma_alloc_writecombine(pcm->card->dev, size, + &buf->addr, GFP_KERNEL); + if (!buf->area) + return -ENOMEM; + buf->bytes = size; + return 0; +} +EXPORT_SYMBOL(pxa2xx_pcm_preallocate_dma_buffer); + +void pxa2xx_pcm_free_dma_buffers(struct snd_pcm *pcm) +{ + struct snd_pcm_substream *substream; + struct snd_dma_buffer *buf; + int stream; + + for (stream = 0; stream < 2; stream++) { + substream = pcm->streams[stream].substream; + if (!substream) + continue; + buf = &substream->dma_buffer; + if (!buf->area) + continue; + dma_free_writecombine(pcm->card->dev, buf->bytes, + buf->area, buf->addr); + buf->area = NULL; + } +} +EXPORT_SYMBOL(pxa2xx_pcm_free_dma_buffers); + +MODULE_AUTHOR("Nicolas Pitre"); +MODULE_DESCRIPTION("Intel PXA2xx sound library"); +MODULE_LICENSE("GPL"); diff --git a/sound/arm/pxa2xx-pcm.c b/sound/arm/pxa2xx-pcm.c index 381094a..535704f 100644 --- a/sound/arm/pxa2xx-pcm.c +++ b/sound/arm/pxa2xx-pcm.c @@ -10,183 +10,20 @@ * published by the Free Software Foundation. */ -#include <linux/module.h> -#include <linux/init.h> -#include <linux/device.h> -#include <linux/slab.h> -#include <linux/dma-mapping.h> - #include <sound/core.h> -#include <sound/pcm.h> -#include <sound/pcm_params.h> - -#include <asm/dma.h> -#include <mach/hardware.h> -#include <mach/pxa-regs.h> +#include <sound/pxa2xx-lib.h> #include "pxa2xx-pcm.h" - -static const struct snd_pcm_hardware pxa2xx_pcm_hardware = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_PAUSE, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .period_bytes_min = 32, - .period_bytes_max = 8192 - 32, - .periods_min = 1, - .periods_max = PAGE_SIZE/sizeof(pxa_dma_desc), - .buffer_bytes_max = 128 * 1024, - .fifo_size = 32, -}; - -struct pxa2xx_runtime_data { - int dma_ch; - struct pxa2xx_pcm_dma_params *params; - pxa_dma_desc *dma_desc_array; - dma_addr_t dma_desc_array_phys; -}; - -static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct pxa2xx_runtime_data *rtd = runtime->private_data; - size_t totsize = params_buffer_bytes(params); - size_t period = params_period_bytes(params); - pxa_dma_desc *dma_desc; - dma_addr_t dma_buff_phys, next_desc_phys; - - snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); - runtime->dma_bytes = totsize; - - dma_desc = rtd->dma_desc_array; - next_desc_phys = rtd->dma_desc_array_phys; - dma_buff_phys = runtime->dma_addr; - do { - next_desc_phys += sizeof(pxa_dma_desc); - dma_desc->ddadr = next_desc_phys; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - dma_desc->dsadr = dma_buff_phys; - dma_desc->dtadr = rtd->params->dev_addr; - } else { - dma_desc->dsadr = rtd->params->dev_addr; - dma_desc->dtadr = dma_buff_phys; - } - if (period > totsize) - period = totsize; - dma_desc->dcmd = rtd->params->dcmd | period | DCMD_ENDIRQEN; - dma_desc++; - dma_buff_phys += period; - } while (totsize -= period); - dma_desc[-1].ddadr = rtd->dma_desc_array_phys; - - return 0; -} - -static int pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream) -{ - struct pxa2xx_runtime_data *rtd = substream->runtime->private_data; - - *rtd->params->drcmr = 0; - snd_pcm_set_runtime_buffer(substream, NULL); - return 0; -} - static int pxa2xx_pcm_prepare(struct snd_pcm_substream *substream) { struct pxa2xx_pcm_client *client = substream->private_data; - struct snd_pcm_runtime *runtime = substream->runtime; - struct pxa2xx_runtime_data *rtd = runtime->private_data; - DCSR(rtd->dma_ch) &= ~DCSR_RUN; - DCSR(rtd->dma_ch) = 0; - DCMD(rtd->dma_ch) = 0; - *rtd->params->drcmr = rtd->dma_ch | DRCMR_MAPVLD; + __pxa2xx_pcm_prepare(substream); return client->prepare(substream); } -static int pxa2xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct pxa2xx_runtime_data *rtd = substream->runtime->private_data; - int ret = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - DDADR(rtd->dma_ch) = rtd->dma_desc_array_phys; - DCSR(rtd->dma_ch) = DCSR_RUN; - break; - - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - DCSR(rtd->dma_ch) &= ~DCSR_RUN; - break; - - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - DCSR(rtd->dma_ch) |= DCSR_RUN; - break; - - default: - ret = -EINVAL; - } - - return ret; -} - -static void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id) -{ - struct snd_pcm_substream *substream = dev_id; - struct pxa2xx_runtime_data *rtd = substream->runtime->private_data; - int dcsr; - - dcsr = DCSR(dma_ch); - DCSR(dma_ch) = dcsr & ~DCSR_STOPIRQEN; - - if (dcsr & DCSR_ENDINTR) { - snd_pcm_period_elapsed(substream); - } else { - printk( KERN_ERR "%s: DMA error on channel %d (DCSR=%#x)\n", - rtd->params->name, dma_ch, dcsr ); - snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); - } -} - -static snd_pcm_uframes_t pxa2xx_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct pxa2xx_runtime_data *rtd = runtime->private_data; - dma_addr_t ptr = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? - DSADR(rtd->dma_ch) : DTADR(rtd->dma_ch); - snd_pcm_uframes_t x = bytes_to_frames(runtime, ptr - runtime->dma_addr); - if (x == runtime->buffer_size) - x = 0; - return x; -} - -static int -pxa2xx_pcm_hw_rule_mult32(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) -{ - struct snd_interval *i = hw_param_interval(params, rule->var); - int changed = 0; - - if (i->min & 31) { - i->min = (i->min & ~31) + 32; - i->openmin = 0; - changed = 1; - } - - if (i->max & 31) { - i->max &= ~31; - i->openmax = 0; - changed = 1; - } - - return changed; -} - static int pxa2xx_pcm_open(struct snd_pcm_substream *substream) { struct pxa2xx_pcm_client *client = substream->private_data; @@ -194,33 +31,11 @@ static int pxa2xx_pcm_open(struct snd_pcm_substream *substream) struct pxa2xx_runtime_data *rtd; int ret; - runtime->hw = pxa2xx_pcm_hardware; - - /* - * For mysterious reasons (and despite what the manual says) - * playback samples are lost if the DMA count is not a multiple - * of the DMA burst size. Let's add a rule to enforce that. - */ - ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, - pxa2xx_pcm_hw_rule_mult32, NULL, - SNDRV_PCM_HW_PARAM_PERIOD_BYTES, -1); - if (ret) - goto out; - ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, - pxa2xx_pcm_hw_rule_mult32, NULL, - SNDRV_PCM_HW_PARAM_BUFFER_BYTES, -1); + ret = __pxa2xx_pcm_open(substream); if (ret) goto out; - ret = -ENOMEM; - rtd = kmalloc(sizeof(*rtd), GFP_KERNEL); - if (!rtd) - goto out; - rtd->dma_desc_array = - dma_alloc_writecombine(substream->pcm->card->dev, PAGE_SIZE, - &rtd->dma_desc_array_phys, GFP_KERNEL); - if (!rtd->dma_desc_array) - goto err1; + rtd = runtime->private_data; rtd->params = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? client->playback_params : client->capture_params; @@ -230,17 +45,13 @@ static int pxa2xx_pcm_open(struct snd_pcm_substream *substream) goto err2; rtd->dma_ch = ret; - runtime->private_data = rtd; ret = client->startup(substream); if (!ret) goto out; pxa_free_dma(rtd->dma_ch); err2: - dma_free_writecombine(substream->pcm->card->dev, PAGE_SIZE, - rtd->dma_desc_array, rtd->dma_desc_array_phys); - err1: - kfree(rtd); + __pxa2xx_pcm_close(substream); out: return ret; } @@ -252,69 +63,22 @@ static int pxa2xx_pcm_close(struct snd_pcm_substream *substream) pxa_free_dma(rtd->dma_ch); client->shutdown(substream); - dma_free_writecombine(substream->pcm->card->dev, PAGE_SIZE, - rtd->dma_desc_array, rtd->dma_desc_array_phys); - kfree(rtd); - return 0; -} -static int -pxa2xx_pcm_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *vma) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - return dma_mmap_writecombine(substream->pcm->card->dev, vma, - runtime->dma_area, - runtime->dma_addr, - runtime->dma_bytes); + return __pxa2xx_pcm_close(substream); } static struct snd_pcm_ops pxa2xx_pcm_ops = { .open = pxa2xx_pcm_open, .close = pxa2xx_pcm_close, .ioctl = snd_pcm_lib_ioctl, - .hw_params = pxa2xx_pcm_hw_params, - .hw_free = pxa2xx_pcm_hw_free, + .hw_params = __pxa2xx_pcm_hw_params, + .hw_free = __pxa2xx_pcm_hw_free, .prepare = pxa2xx_pcm_prepare, .trigger = pxa2xx_pcm_trigger, .pointer = pxa2xx_pcm_pointer, .mmap = pxa2xx_pcm_mmap, }; -static int pxa2xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) -{ - struct snd_pcm_substream *substream = pcm->streams[stream].substream; - struct snd_dma_buffer *buf = &substream->dma_buffer; - size_t size = pxa2xx_pcm_hardware.buffer_bytes_max; - buf->dev.type = SNDRV_DMA_TYPE_DEV; - buf->dev.dev = pcm->card->dev; - buf->private_data = NULL; - buf->area = dma_alloc_writecombine(pcm->card->dev, size, - &buf->addr, GFP_KERNEL); - if (!buf->area) - return -ENOMEM; - buf->bytes = size; - return 0; -} - -static void pxa2xx_pcm_free_dma_buffers(struct snd_pcm *pcm) -{ - struct snd_pcm_substream *substream; - struct snd_dma_buffer *buf; - int stream; - - for (stream = 0; stream < 2; stream++) { - substream = pcm->streams[stream].substream; - if (!substream) - continue; - buf = &substream->dma_buffer; - if (!buf->area) - continue; - dma_free_writecombine(pcm->card->dev, buf->bytes, - buf->area, buf->addr); - buf->area = NULL; - } -} - static u64 pxa2xx_pcm_dmamask = 0xffffffff; int pxa2xx_pcm_new(struct snd_card *card, struct pxa2xx_pcm_client *client, diff --git a/sound/arm/pxa2xx-pcm.h b/sound/arm/pxa2xx-pcm.h index b79f1e8..5c4a4d3 100644 --- a/sound/arm/pxa2xx-pcm.h +++ b/sound/arm/pxa2xx-pcm.h @@ -9,14 +9,15 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +#include <asm/dma.h> -struct pxa2xx_pcm_dma_params { - char *name; /* stream identifier */ - u32 dcmd; /* DMA descriptor dcmd field */ - volatile u32 *drcmr; /* the DMA request channel to use */ - u32 dev_addr; /* device physical address for DMA */ +struct pxa2xx_runtime_data { + int dma_ch; + struct pxa2xx_pcm_dma_params *params; + pxa_dma_desc *dma_desc_array; + dma_addr_t dma_desc_array_phys; }; - + struct pxa2xx_pcm_client { struct pxa2xx_pcm_dma_params *playback_params; struct pxa2xx_pcm_dma_params *capture_params; diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index d1ccbdc..f8c1cdd 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig @@ -1,6 +1,7 @@ config SND_PXA2XX_SOC tristate "SoC Audio for the Intel PXA2xx chip" depends on ARCH_PXA + select SND_PXA2XX_LIB help Say Y or M if you want to add support for codecs attached to the PXA2xx AC97, I2S or SSP interface. You will also need @@ -14,7 +15,7 @@ config SND_PXA2XX_SOC_AC97 tristate select AC97_BUS select SND_ARM - select SND_PXA2XX_LIB + select SND_PXA2XX_LIB_AC97 select SND_SOC_AC97_BUS config SND_PXA2XX_SOC_I2S diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c index 533e1f5..a733286 100644 --- a/sound/soc/pxa/pxa2xx-i2s.c +++ b/sound/soc/pxa/pxa2xx-i2s.c @@ -20,6 +20,7 @@ #include <sound/pcm.h> #include <sound/initval.h> #include <sound/soc.h> +#include <sound/pxa2xx-lib.h> #include <mach/hardware.h> #include <mach/pxa-regs.h> @@ -29,6 +30,15 @@ #include "pxa2xx-pcm.h" #include "pxa2xx-i2s.h" +struct pxa2xx_gpio { + u32 sys; + u32 rx; + u32 tx; + u32 clk; + u32 frm; +}; + + struct pxa_i2s_port { u32 sadiv; u32 sacr0; diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c index 771c592..afcd892 100644 --- a/sound/soc/pxa/pxa2xx-pcm.c +++ b/sound/soc/pxa/pxa2xx-pcm.c @@ -10,64 +10,14 @@ * published by the Free Software Foundation. */ -#include <linux/module.h> -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/slab.h> #include <linux/dma-mapping.h> #include <sound/core.h> -#include <sound/pcm.h> -#include <sound/pcm_params.h> #include <sound/soc.h> - -#include <asm/dma.h> -#include <mach/hardware.h> -#include <mach/pxa-regs.h> -#include <mach/audio.h> +#include <sound/pxa2xx-lib.h> #include "pxa2xx-pcm.h" - -static const struct snd_pcm_hardware pxa2xx_pcm_hardware = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_RESUME, - .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_S32_LE, - .period_bytes_min = 32, - .period_bytes_max = 8192 - 32, - .periods_min = 1, - .periods_max = PAGE_SIZE/sizeof(pxa_dma_desc), - .buffer_bytes_max = 128 * 1024, - .fifo_size = 32, -}; - -struct pxa2xx_runtime_data { - int dma_ch; - struct pxa2xx_pcm_dma_params *params; - pxa_dma_desc *dma_desc_array; - dma_addr_t dma_desc_array_phys; -}; - -static void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id) -{ - struct snd_pcm_substream *substream = dev_id; - struct pxa2xx_runtime_data *prtd = substream->runtime->private_data; - int dcsr; - - dcsr = DCSR(dma_ch); - DCSR(dma_ch) = dcsr & ~DCSR_STOPIRQEN; - - if (dcsr & DCSR_ENDINTR) { - snd_pcm_period_elapsed(substream); - } else { - printk(KERN_ERR "%s: DMA error on channel %d (DCSR=%#x)\n", - prtd->params->name, dma_ch, dcsr); - } -} +#include "../../arm/pxa2xx-pcm.h" static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) @@ -76,10 +26,6 @@ static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream, struct pxa2xx_runtime_data *prtd = runtime->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data; struct pxa2xx_pcm_dma_params *dma = rtd->dai->cpu_dai->dma_data; - size_t totsize = params_buffer_bytes(params); - size_t period = params_period_bytes(params); - pxa_dma_desc *dma_desc; - dma_addr_t dma_buff_phys, next_desc_phys; int ret; /* return if this is a bufferless transfer e.g. @@ -106,42 +52,16 @@ static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream, prtd->dma_ch = ret; } - snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); - runtime->dma_bytes = totsize; - - dma_desc = prtd->dma_desc_array; - next_desc_phys = prtd->dma_desc_array_phys; - dma_buff_phys = runtime->dma_addr; - do { - next_desc_phys += sizeof(pxa_dma_desc); - dma_desc->ddadr = next_desc_phys; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - dma_desc->dsadr = dma_buff_phys; - dma_desc->dtadr = prtd->params->dev_addr; - } else { - dma_desc->dsadr = prtd->params->dev_addr; - dma_desc->dtadr = dma_buff_phys; - } - if (period > totsize) - period = totsize; - dma_desc->dcmd = prtd->params->dcmd | period | DCMD_ENDIRQEN; - dma_desc++; - dma_buff_phys += period; - } while (totsize -= period); - dma_desc[-1].ddadr = prtd->dma_desc_array_phys; - - return 0; + return __pxa2xx_pcm_hw_params(substream, params); } static int pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream) { struct pxa2xx_runtime_data *prtd = substream->runtime->private_data; - if (prtd && prtd->params) - *prtd->params->drcmr = 0; + __pxa2xx_pcm_hw_free(substream); if (prtd->dma_ch) { - snd_pcm_set_runtime_buffer(substream, NULL); pxa_free_dma(prtd->dma_ch); prtd->dma_ch = 0; } @@ -149,185 +69,18 @@ static int pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream) return 0; } -static int pxa2xx_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct pxa2xx_runtime_data *prtd = substream->runtime->private_data; - - DCSR(prtd->dma_ch) &= ~DCSR_RUN; - DCSR(prtd->dma_ch) = 0; - DCMD(prtd->dma_ch) = 0; - *prtd->params->drcmr = prtd->dma_ch | DRCMR_MAPVLD; - - return 0; -} - -static int pxa2xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct pxa2xx_runtime_data *prtd = substream->runtime->private_data; - int ret = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - DDADR(prtd->dma_ch) = prtd->dma_desc_array_phys; - DCSR(prtd->dma_ch) = DCSR_RUN; - break; - - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - DCSR(prtd->dma_ch) &= ~DCSR_RUN; - break; - - case SNDRV_PCM_TRIGGER_RESUME: - DCSR(prtd->dma_ch) |= DCSR_RUN; - break; - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - DDADR(prtd->dma_ch) = prtd->dma_desc_array_phys; - DCSR(prtd->dma_ch) |= DCSR_RUN; - break; - - default: - ret = -EINVAL; - } - - return ret; -} - -static snd_pcm_uframes_t -pxa2xx_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct pxa2xx_runtime_data *prtd = runtime->private_data; - - dma_addr_t ptr = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? - DSADR(prtd->dma_ch) : DTADR(prtd->dma_ch); - snd_pcm_uframes_t x = bytes_to_frames(runtime, ptr - runtime->dma_addr); - - if (x == runtime->buffer_size) - x = 0; - return x; -} - -static int pxa2xx_pcm_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct pxa2xx_runtime_data *prtd; - int ret; - - snd_soc_set_runtime_hwparams(substream, &pxa2xx_pcm_hardware); - - /* - * For mysterious reasons (and despite what the manual says) - * playback samples are lost if the DMA count is not a multiple - * of the DMA burst size. Let's add a rule to enforce that. - */ - ret = snd_pcm_hw_constraint_step(runtime, 0, - SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32); - if (ret) - goto out; - - ret = snd_pcm_hw_constraint_step(runtime, 0, - SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32); - if (ret) - goto out; - - ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); - if (ret < 0) - goto out; - - prtd = kzalloc(sizeof(struct pxa2xx_runtime_data), GFP_KERNEL); - if (prtd == NULL) { - ret = -ENOMEM; - goto out; - } - - prtd->dma_desc_array = - dma_alloc_writecombine(substream->pcm->card->dev, PAGE_SIZE, - &prtd->dma_desc_array_phys, GFP_KERNEL); - if (!prtd->dma_desc_array) { - ret = -ENOMEM; - goto err1; - } - - runtime->private_data = prtd; - return 0; - - err1: - kfree(prtd); - out: - return ret; -} - -static int pxa2xx_pcm_close(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct pxa2xx_runtime_data *prtd = runtime->private_data; - - dma_free_writecombine(substream->pcm->card->dev, PAGE_SIZE, - prtd->dma_desc_array, prtd->dma_desc_array_phys); - kfree(prtd); - return 0; -} - -static int pxa2xx_pcm_mmap(struct snd_pcm_substream *substream, - struct vm_area_struct *vma) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - return dma_mmap_writecombine(substream->pcm->card->dev, vma, - runtime->dma_area, - runtime->dma_addr, - runtime->dma_bytes); -} - struct snd_pcm_ops pxa2xx_pcm_ops = { - .open = pxa2xx_pcm_open, - .close = pxa2xx_pcm_close, + .open = __pxa2xx_pcm_open, + .close = __pxa2xx_pcm_close, .ioctl = snd_pcm_lib_ioctl, .hw_params = pxa2xx_pcm_hw_params, .hw_free = pxa2xx_pcm_hw_free, - .prepare = pxa2xx_pcm_prepare, + .prepare = __pxa2xx_pcm_prepare, .trigger = pxa2xx_pcm_trigger, .pointer = pxa2xx_pcm_pointer, .mmap = pxa2xx_pcm_mmap, }; -static int pxa2xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) -{ - struct snd_pcm_substream *substream = pcm->streams[stream].substream; - struct snd_dma_buffer *buf = &substream->dma_buffer; - size_t size = pxa2xx_pcm_hardware.buffer_bytes_max; - buf->dev.type = SNDRV_DMA_TYPE_DEV; - buf->dev.dev = pcm->card->dev; - buf->private_data = NULL; - buf->area = dma_alloc_writecombine(pcm->card->dev, size, - &buf->addr, GFP_KERNEL); - if (!buf->area) - return -ENOMEM; - buf->bytes = size; - return 0; -} - -static void pxa2xx_pcm_free_dma_buffers(struct snd_pcm *pcm) -{ - struct snd_pcm_substream *substream; - struct snd_dma_buffer *buf; - int stream; - - for (stream = 0; stream < 2; stream++) { - substream = pcm->streams[stream].substream; - if (!substream) - continue; - - buf = &substream->dma_buffer; - if (!buf->area) - continue; - - dma_free_writecombine(pcm->card->dev, buf->bytes, - buf->area, buf->addr); - buf->area = NULL; - } -} - static u64 pxa2xx_pcm_dmamask = DMA_32BIT_MASK; static int pxa2xx_soc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, diff --git a/sound/soc/pxa/pxa2xx-pcm.h b/sound/soc/pxa/pxa2xx-pcm.h index 54c9c75..60c3b20 100644 --- a/sound/soc/pxa/pxa2xx-pcm.h +++ b/sound/soc/pxa/pxa2xx-pcm.h @@ -13,21 +13,6 @@ #ifndef _PXA2XX_PCM_H #define _PXA2XX_PCM_H -struct pxa2xx_pcm_dma_params { - char *name; /* stream identifier */ - u32 dcmd; /* DMA descriptor dcmd field */ - volatile u32 *drcmr; /* the DMA request channel to use */ - u32 dev_addr; /* device physical address for DMA */ -}; - -struct pxa2xx_gpio { - u32 sys; - u32 rx; - u32 tx; - u32 clk; - u32 frm; -}; - /* platform data */ extern struct snd_soc_platform pxa2xx_soc_platform; -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH 5/5] Separate common pxa2xx-pcm code 2008-09-08 9:06 ` [PATCH 5/5] Separate common pxa2xx-pcm code Dmitry Baryshkov @ 2008-09-08 10:07 ` Eric Miao 2008-09-08 10:13 ` Dmitry 2008-09-08 10:33 ` Mark Brown 1 sibling, 1 reply; 17+ messages in thread From: Eric Miao @ 2008-09-08 10:07 UTC (permalink / raw) To: Dmitry Baryshkov; +Cc: alsa-devel On Mon, Sep 8, 2008 at 5:06 PM, Dmitry Baryshkov <dbaryshkov@gmail.com> wrote: > ASoC and non-ASoC drivers for PCM DMA on PXA share lot's of common code. > Move it to pxa2xx-lib. > I guess you didn't try 'git format-patch -M' here, which is able to recognize most of the code movement, thus making code review a bit easier. This is also true for one of the previous patches. ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 5/5] Separate common pxa2xx-pcm code 2008-09-08 10:07 ` Eric Miao @ 2008-09-08 10:13 ` Dmitry 0 siblings, 0 replies; 17+ messages in thread From: Dmitry @ 2008-09-08 10:13 UTC (permalink / raw) To: Eric Miao; +Cc: alsa-devel 2008/9/8 Eric Miao <eric.y.miao@gmail.com>: > On Mon, Sep 8, 2008 at 5:06 PM, Dmitry Baryshkov <dbaryshkov@gmail.com> wrote: >> ASoC and non-ASoC drivers for PCM DMA on PXA share lot's of common code. >> Move it to pxa2xx-lib. >> > > I guess you didn't try 'git format-patch -M' here, which is able to recognize > most of the code movement, thus making code review a bit easier. > > This is also true for one of the previous patches. Unfortunately it doesn't help too much in this case, imo. Anyway, reposting in a minute. -- With best wishes Dmitry ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 5/5] Separate common pxa2xx-pcm code 2008-09-08 9:06 ` [PATCH 5/5] Separate common pxa2xx-pcm code Dmitry Baryshkov 2008-09-08 10:07 ` Eric Miao @ 2008-09-08 10:33 ` Mark Brown 1 sibling, 0 replies; 17+ messages in thread From: Mark Brown @ 2008-09-08 10:33 UTC (permalink / raw) To: Dmitry Baryshkov; +Cc: alsa-devel On Mon, Sep 08, 2008 at 01:06:13PM +0400, Dmitry Baryshkov wrote: > +#include <linux/platform_device.h> > +#include <sound/ac97_codec.h> ac97_codec.h should've been added earlier on in the patch series - this patch doesn't add a new requirement for ac97. The same thing appears to apply to platform_device.h if it's required at all. > config SND_PXA2XX_LIB > tristate > - select SND_AC97_CODEC > + select SND_AC97_CODEC if SND_PXA2XX_LIB_AC97 > + > +config SND_PXA2XX_LIB_AC97 > + bool > > config SND_PXA2XX_AC97 > tristate "AC97 driver for the Intel PXA2xx chip" > depends on ARCH_PXA > select SND_PXA2XX_PCM > - select SND_PXA2XX_LIB > + select SND_PXA2XX_LIB_AC97 > help > Say Y or M if you want to support any AC97 codec attached to > the PXA2xx AC97 interface. > obj-$(CONFIG_SND_PXA2XX_LIB) += snd-pxa2xx-lib.o > -snd-pxa2xx-lib-objs := pxa2xx-ac97-lib.o > +snd-pxa2xx-lib-y := pxa2xx-pcm-lib.o > +snd-pxa2xx-lib-$(CONFIG_SND_PXA2XX_LIB_AC97) += pxa2xx-ac97-lib.o > +EXPORT_SYMBOL(__pxa2xx_pcm_hw_params); Hrm. The existing ASoC stuff is all EXPORT_SYMBOL_GPL(), as much on the basis of potential churn as anything else. Especially for the __ functions it might be nice to preserve that. > +EXPORT_SYMBOL(pxa2xx_pcm_free_dma_buffers); > + > +MODULE_AUTHOR("Nicolas Pitre"); > +MODULE_DESCRIPTION("Intel PXA2xx sound library"); > +MODULE_LICENSE("GPL"); Probably as well to drop the Intel here :) ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 4/5] pxa2xx-lib: support building for several pxa's 2008-09-08 9:06 ` [PATCH 4/5] pxa2xx-lib: support building for several pxa's Dmitry Baryshkov 2008-09-08 9:06 ` [PATCH 5/5] Separate common pxa2xx-pcm code Dmitry Baryshkov @ 2008-09-08 10:17 ` Mark Brown 1 sibling, 0 replies; 17+ messages in thread From: Mark Brown @ 2008-09-08 10:17 UTC (permalink / raw) To: Dmitry Baryshkov; +Cc: Russ Dill, alsa-devel On Mon, Sep 08, 2008 at 01:06:12PM +0400, Dmitry Baryshkov wrote: > Here's a version of the third patch in the series without all the > cpu_is_pxa3xx())'s around the pxa_gpio_mode's? Also, there was a build > error when just building the sound/arm pxa2xx-ac97. If there's a build error introduced by the earlier patch it ought to be fixed there rather than in a subsequent patch? > -#ifdef CONFIG_PXA3xx > -#define GCR_CLKBPB (1 << 31) /* Internal clock enable */ > -#endif > +#define GCR_CLKBPB (1 << 31) /* Internal clock enable, PXA3XX only */ At least this hunk needs to at least get acked by rmk, and would probably need to go via the ARM tree. > + 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); > + } I'd rather do this by explicitly identifying the PXA2xx CPUs (on the basis that Marvell are producing new PXA variants but the set of PXA2xx CPUs should be fixed now). > --- a/sound/soc/pxa/pxa2xx-i2s.c > +++ b/sound/soc/pxa/pxa2xx-i2s.c This should be split into a separate patch - it's not directly related to the other changes except in terms of the overall goal and covers a different driver. It's also not mentioned in the patch description. ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 2/5] Separate common pxa2xx-ac97 code 2008-09-08 9:06 ` [PATCH 2/5] Separate common pxa2xx-ac97 code Dmitry Baryshkov 2008-09-08 9:06 ` [PATCH 3/5] Make pxa-ac97-lib separate module Dmitry Baryshkov @ 2008-09-08 9:33 ` Liam Girdwood 2008-09-08 9:42 ` Dmitry Baryshkov 1 sibling, 1 reply; 17+ messages in thread From: Liam Girdwood @ 2008-09-08 9:33 UTC (permalink / raw) To: Dmitry Baryshkov; +Cc: alsa-devel On Mon, 2008-09-08 at 13:06 +0400, Dmitry Baryshkov wrote: > 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 199cca3..320ac75 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" > Any reason for not linking with pxa2xx-ac97-lib.o ? > 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 d94a495..99f096d 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" > ditto > 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, Liam ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 2/5] Separate common pxa2xx-ac97 code 2008-09-08 9:33 ` [PATCH 2/5] Separate common pxa2xx-ac97 code Liam Girdwood @ 2008-09-08 9:42 ` Dmitry Baryshkov 2008-09-08 9:51 ` Liam Girdwood 0 siblings, 1 reply; 17+ messages in thread From: Dmitry Baryshkov @ 2008-09-08 9:42 UTC (permalink / raw) To: alsa-devel Liam Girdwood wrote: > On Mon, 2008-09-08 at 13:06 +0400, Dmitry Baryshkov wrote: >> ASoC and non-ASoC drivers for ACLINK on PXA share lot's of common code. >> Move all common code into separate file. >> >> +#include "pxa2xx-ac97-lib.c" >> >> > Any reason for not linking with pxa2xx-ac97-lib.o ? > >> +#include "../../arm/pxa2xx-ac97-lib.c" > > > ditto > >> static void pxa2xx_ac97_warm_reset(struct snd_ac97 *ac97) { > > Liam That is the interim change. In the next patch the file is fully separated into distinct module. I can squash those patches if you'd prefer. -- With best wishes Dmitry ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 2/5] Separate common pxa2xx-ac97 code 2008-09-08 9:42 ` Dmitry Baryshkov @ 2008-09-08 9:51 ` Liam Girdwood 0 siblings, 0 replies; 17+ messages in thread From: Liam Girdwood @ 2008-09-08 9:51 UTC (permalink / raw) To: Dmitry Baryshkov; +Cc: alsa-devel On Mon, 2008-09-08 at 09:42 +0000, Dmitry Baryshkov wrote: > Liam Girdwood wrote: > > > On Mon, 2008-09-08 at 13:06 +0400, Dmitry Baryshkov wrote: > >> ASoC and non-ASoC drivers for ACLINK on PXA share lot's of common code. > >> Move all common code into separate file. > >> > >> +#include "pxa2xx-ac97-lib.c" > >> > >> > > Any reason for not linking with pxa2xx-ac97-lib.o ? > > > > >> +#include "../../arm/pxa2xx-ac97-lib.c" > > > > > > ditto > > > >> static void pxa2xx_ac97_warm_reset(struct snd_ac97 *ac97) { > > > > Liam > > > That is the interim change. In the next patch the file is fully separated > into distinct module. I can squash those patches if you'd prefer. > > Yes, please - makes it easier to read. Liam ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 1/5] Permit simultaneous compilation of both PXA AC97 drivers 2008-09-08 9:06 ` [PATCH 1/5] Permit simultaneous compilation of both PXA AC97 drivers Dmitry Baryshkov 2008-09-08 9:06 ` [PATCH 2/5] Separate common pxa2xx-ac97 code Dmitry Baryshkov @ 2008-09-08 9:30 ` Mark Brown 2008-09-08 10:19 ` Dmitry Baryshkov 1 sibling, 1 reply; 17+ messages in thread From: Mark Brown @ 2008-09-08 9:30 UTC (permalink / raw) To: Dmitry Baryshkov; +Cc: alsa-devel On Mon, Sep 08, 2008 at 01:06:09PM +0400, Dmitry Baryshkov wrote: > Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com> This change was merged some time ago - it's easier if you development against Takashi's tree rather than against an old kernel, especially given the changes going on in ASoC. I haven't checked yet but I expect that some of your later changes will no longer apply with current code. ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 1/5] Permit simultaneous compilation of both PXA AC97 drivers 2008-09-08 9:30 ` [PATCH 1/5] Permit simultaneous compilation of both PXA AC97 drivers Mark Brown @ 2008-09-08 10:19 ` Dmitry Baryshkov 2008-09-08 10:35 ` Mark Brown 0 siblings, 1 reply; 17+ messages in thread From: Dmitry Baryshkov @ 2008-09-08 10:19 UTC (permalink / raw) To: Dmitry Baryshkov, alsa-devel Mark Brown wrote: > On Mon, Sep 08, 2008 at 01:06:09PM +0400, Dmitry Baryshkov wrote: >> Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com> > > This change was merged some time ago - it's easier if you development > against Takashi's tree rather than against an old kernel, especially > given the changes going on in ASoC. I haven't checked yet but I expect > that some of your later changes will no longer apply with current code. Against which tree should I develop? git://opensource.wolfsonmicro.com/linux-2.6-asoc ? -- With best wishes Dmitry ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 1/5] Permit simultaneous compilation of both PXA AC97 drivers 2008-09-08 10:19 ` Dmitry Baryshkov @ 2008-09-08 10:35 ` Mark Brown 0 siblings, 0 replies; 17+ messages in thread From: Mark Brown @ 2008-09-08 10:35 UTC (permalink / raw) To: Dmitry Baryshkov; +Cc: alsa-devel On Mon, Sep 08, 2008 at 02:19:13PM +0400, Dmitry Baryshkov wrote: > Against which tree should I develop? > git://opensource.wolfsonmicro.com/linux-2.6-asoc ? That or the topic/asoc or master branch of Takashi's tree: git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6.git (the two should be in very close sync). ^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2008-09-08 10:35 UTC | newest] Thread overview: 17+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2008-09-08 8:53 [GIT PULL] unify two pxa sound drivers Dmitry Baryshkov 2008-09-08 9:05 ` Liam Girdwood 2008-09-08 9:06 ` [PATCH 1/5] Permit simultaneous compilation of both PXA AC97 drivers Dmitry Baryshkov 2008-09-08 9:06 ` [PATCH 2/5] Separate common pxa2xx-ac97 code Dmitry Baryshkov 2008-09-08 9:06 ` [PATCH 3/5] Make pxa-ac97-lib separate module Dmitry Baryshkov 2008-09-08 9:06 ` [PATCH 4/5] pxa2xx-lib: support building for several pxa's Dmitry Baryshkov 2008-09-08 9:06 ` [PATCH 5/5] Separate common pxa2xx-pcm code Dmitry Baryshkov 2008-09-08 10:07 ` Eric Miao 2008-09-08 10:13 ` Dmitry 2008-09-08 10:33 ` Mark Brown 2008-09-08 10:17 ` [PATCH 4/5] pxa2xx-lib: support building for several pxa's Mark Brown 2008-09-08 9:33 ` [PATCH 2/5] Separate common pxa2xx-ac97 code Liam Girdwood 2008-09-08 9:42 ` Dmitry Baryshkov 2008-09-08 9:51 ` Liam Girdwood 2008-09-08 9:30 ` [PATCH 1/5] Permit simultaneous compilation of both PXA AC97 drivers Mark Brown 2008-09-08 10:19 ` Dmitry Baryshkov 2008-09-08 10:35 ` Mark Brown
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.