diff options
-rw-r--r-- | include/sound/pxa2xx-lib.h | 15 | ||||
-rw-r--r-- | sound/arm/pxa2xx-ac97-lib.c | 71 | ||||
-rw-r--r-- | sound/soc/codecs/twl4030.c | 12 | ||||
-rw-r--r-- | sound/soc/pxa/pxa2xx-ac97.c | 16 | ||||
-rw-r--r-- | sound/soc/s3c24xx/s3c64xx-i2s.c | 8 | ||||
-rw-r--r-- | sound/soc/sh/hac.c | 12 | ||||
-rw-r--r-- | sound/soc/soc-core.c | 3 |
7 files changed, 113 insertions, 24 deletions
diff --git a/include/sound/pxa2xx-lib.h b/include/sound/pxa2xx-lib.h index 2fd3d251d9a..2c894b600e5 100644 --- a/include/sound/pxa2xx-lib.h +++ b/include/sound/pxa2xx-lib.h @@ -42,4 +42,19 @@ 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); +/* AC97 platform_data */ +/** + * struct pxa2xx_ac97_platform_data - pxa ac97 platform data + * @reset_gpio: AC97 reset gpio (normally gpio113 or gpio95) + * a -1 value means no gpio will be used for reset + * + * Platform data should only be specified for pxa27x CPUs where a silicon bug + * prevents correct operation of the reset line. If not specified, the default + * behaviour is to consider gpio 113 as the AC97 reset line, which is the + * default on most boards. + */ +struct pxa2xx_ac97_platform_data { + int reset_gpio; +}; + #endif diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/arm/pxa2xx-ac97-lib.c index 35afd0c33be..d721ea7cae8 100644 --- a/sound/arm/pxa2xx-ac97-lib.c +++ b/sound/arm/pxa2xx-ac97-lib.c @@ -31,6 +31,7 @@ static DECLARE_WAIT_QUEUE_HEAD(gsr_wq); static volatile long gsr_bits; static struct clk *ac97_clk; static struct clk *ac97conf_clk; +static int reset_gpio; /* * Beware PXA27x bugs: @@ -42,6 +43,45 @@ static struct clk *ac97conf_clk; * 1 jiffy timeout if interrupt never comes). */ +enum { + RESETGPIO_FORCE_HIGH, + RESETGPIO_FORCE_LOW, + RESETGPIO_NORMAL_ALTFUNC +}; + +/** + * set_resetgpio_mode - computes and sets the AC97_RESET gpio mode on PXA + * @mode: chosen action + * + * As the PXA27x CPUs suffer from a AC97 bug, a manual control of the reset line + * must be done to insure proper work of AC97 reset line. This function + * computes the correct gpio_mode for further use by reset functions, and + * applied the change through pxa_gpio_mode. + */ +static void set_resetgpio_mode(int resetgpio_action) +{ + int mode = 0; + + if (reset_gpio) + switch (resetgpio_action) { + case RESETGPIO_NORMAL_ALTFUNC: + if (reset_gpio == 113) + mode = 113 | GPIO_OUT | GPIO_DFLT_LOW; + if (reset_gpio == 95) + mode = 95 | GPIO_ALT_FN_1_OUT; + break; + case RESETGPIO_FORCE_LOW: + mode = reset_gpio | GPIO_OUT | GPIO_DFLT_LOW; + break; + case RESETGPIO_FORCE_HIGH: + mode = reset_gpio | GPIO_OUT | GPIO_DFLT_HIGH; + break; + }; + + if (mode) + pxa_gpio_mode(mode); +} + unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg) { unsigned short val = -1; @@ -137,10 +177,10 @@ static inline void pxa_ac97_warm_pxa27x(void) /* warm reset broken on Bulverde, so manually keep AC97 reset high */ - pxa_gpio_mode(113 | GPIO_OUT | GPIO_DFLT_HIGH); + set_resetgpio_mode(RESETGPIO_FORCE_HIGH); udelay(10); GCR |= GCR_WARM_RST; - pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT); + set_resetgpio_mode(RESETGPIO_NORMAL_ALTFUNC); udelay(500); } @@ -308,8 +348,8 @@ int pxa2xx_ac97_hw_resume(void) 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); + /* Use GPIO 113 or 95 as AC97 Reset on Bulverde */ + set_resetgpio_mode(RESETGPIO_NORMAL_ALTFUNC); } clk_enable(ac97_clk); return 0; @@ -320,6 +360,27 @@ EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_resume); int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev) { int ret; + struct pxa2xx_ac97_platform_data *pdata = dev->dev.platform_data; + + if (pdata) { + switch (pdata->reset_gpio) { + case 95: + case 113: + reset_gpio = pdata->reset_gpio; + break; + case 0: + reset_gpio = 113; + break; + case -1: + break; + default: + dev_err(dev, "Invalid reset GPIO %d\n", + pdata->reset_gpio); + } + } else { + if (cpu_is_pxa27x()) + reset_gpio = 113; + } if (cpu_is_pxa25x() || cpu_is_pxa27x()) { pxa_gpio_mode(GPIO31_SYNC_AC97_MD); @@ -330,7 +391,7 @@ int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev) if (cpu_is_pxa27x()) { /* Use GPIO 113 as AC97 Reset on Bulverde */ - pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT); + set_resetgpio_mode(RESETGPIO_NORMAL_ALTFUNC); ac97conf_clk = clk_get(&dev->dev, "AC97CONFCLK"); if (IS_ERR(ac97conf_clk)) { ret = PTR_ERR(ac97conf_clk); diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 86bb15cc82c..97738e2ece0 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -1383,6 +1383,12 @@ static int twl4030_set_dai_fmt(struct snd_soc_dai *codec_dai, #define TWL4030_RATES (SNDRV_PCM_RATE_8000_48000) #define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE) +static struct snd_soc_dai_ops twl4030_dai_ops = { + .hw_params = twl4030_hw_params, + .set_sysclk = twl4030_set_dai_sysclk, + .set_fmt = twl4030_set_dai_fmt, +}; + struct snd_soc_dai twl4030_dai = { .name = "twl4030", .playback = { @@ -1397,11 +1403,7 @@ struct snd_soc_dai twl4030_dai = { .channels_max = 2, .rates = TWL4030_RATES, .formats = TWL4030_FORMATS,}, - .ops = { - .hw_params = twl4030_hw_params, - .set_sysclk = twl4030_set_dai_sysclk, - .set_fmt = twl4030_set_dai_fmt, - } + .ops = &twl4030_dai_ops, }; EXPORT_SYMBOL_GPL(twl4030_dai); diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c index cf809049272..01c21c6cdbb 100644 --- a/sound/soc/pxa/pxa2xx-ac97.c +++ b/sound/soc/pxa/pxa2xx-ac97.c @@ -164,10 +164,18 @@ static int pxa2xx_ac97_hw_mic_params(struct snd_pcm_substream *substream, SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \ SNDRV_PCM_RATE_48000) -static struct snd_soc_dai_ops pxa_ac97_dai_ops = { +static struct snd_soc_dai_ops pxa_ac97_hifi_dai_ops = { .hw_params = pxa2xx_ac97_hw_params, }; +static struct snd_soc_dai_ops pxa_ac97_aux_dai_ops = { + .hw_params = pxa2xx_ac97_hw_aux_params, +}; + +static struct snd_soc_dai_ops pxa_ac97_mic_dai_ops = { + .hw_params = pxa2xx_ac97_hw_mic_params, +}; + /* * There is only 1 physical AC97 interface for pxa2xx, but it * has extra fifo's that can be used for aux DACs and ADCs. @@ -193,7 +201,7 @@ struct snd_soc_dai pxa_ac97_dai[] = { .channels_max = 2, .rates = PXA2XX_AC97_RATES, .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .ops = &pxa_ac97_dai_ops, + .ops = &pxa_ac97_hifi_dai_ops, }, { .name = "pxa2xx-ac97-aux", @@ -211,7 +219,7 @@ struct snd_soc_dai pxa_ac97_dai[] = { .channels_max = 1, .rates = PXA2XX_AC97_RATES, .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .ops = &pxa_ac97_dai_ops, + .ops = &pxa_ac97_aux_dai_ops, }, { .name = "pxa2xx-ac97-mic", @@ -223,7 +231,7 @@ struct snd_soc_dai pxa_ac97_dai[] = { .channels_max = 1, .rates = PXA2XX_AC97_RATES, .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .ops = &pxa_ac97_dai_ops, + .ops = &pxa_ac97_mic_dai_ops, }, }; diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.c b/sound/soc/s3c24xx/s3c64xx-i2s.c index 6e1e85dc1ff..33c5de7e255 100644 --- a/sound/soc/s3c24xx/s3c64xx-i2s.c +++ b/sound/soc/s3c24xx/s3c64xx-i2s.c @@ -177,6 +177,10 @@ static int s3c64xx_i2s_probe(struct platform_device *pdev, #define S3C64XX_I2S_FMTS \ (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE) +static struct snd_soc_dai_ops s3c64xx_i2s_dai_ops = { + .set_sysclk = s3c64xx_i2s_set_sysclk, +}; + struct snd_soc_dai s3c64xx_i2s_dai = { .name = "s3c64xx-i2s", .id = 0, @@ -193,9 +197,7 @@ struct snd_soc_dai s3c64xx_i2s_dai = { .rates = S3C64XX_I2S_RATES, .formats = S3C64XX_I2S_FMTS, }, - .ops = { - .set_sysclk = s3c64xx_i2s_set_sysclk, - }, + .ops = &s3c64xx_i2s_dai_ops, }; EXPORT_SYMBOL_GPL(s3c64xx_i2s_dai); diff --git a/sound/soc/sh/hac.c b/sound/soc/sh/hac.c index eab31838bad..41db75af3c6 100644 --- a/sound/soc/sh/hac.c +++ b/sound/soc/sh/hac.c @@ -267,6 +267,10 @@ static int hac_hw_params(struct snd_pcm_substream *substream, #define AC97_FMTS \ SNDRV_PCM_FMTBIT_S16_LE +static struct snd_soc_dai_ops hac_dai_ops = { + .hw_params = hac_hw_params, +}; + struct snd_soc_dai sh4_hac_dai[] = { { .name = "HAC0", @@ -284,9 +288,7 @@ struct snd_soc_dai sh4_hac_dai[] = { .channels_min = 2, .channels_max = 2, }, - .ops = { - .hw_params = hac_hw_params, - }, + .ops = &hac_dai_ops, }, #ifdef CONFIG_CPU_SUBTYPE_SH7760 { @@ -305,9 +307,7 @@ struct snd_soc_dai sh4_hac_dai[] = { .channels_min = 2, .channels_max = 2, }, - .ops = { - .hw_params = hac_hw_params, - }, + .ops = &hac_dai_ops, }, #endif diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 16518329f6b..6e710f705a7 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1432,7 +1432,8 @@ void snd_soc_free_pcms(struct snd_soc_device *socdev) #ifdef CONFIG_SND_SOC_AC97_BUS for (i = 0; i < codec->num_dai; i++) { codec_dai = &codec->dai[i]; - if (codec_dai->ac97_control && codec->ac97) { + if (codec_dai->ac97_control && codec->ac97 && + strcmp(codec->name, "AC97") != 0) { soc_ac97_dev_unregister(codec); goto free_card; } |