ASoC: ac97: Support multi-platform AC'97
Subsystems (9)
Mark Brown
maintainerPATCH 1/1 ASoC: ac97: Support multi-platform AC'97
From: Mark Brown <[email protected]>
Currently we can only have a single platform built in with AC'97 support due to the use of a global variable to provide the bus operations. Fix this by making that variable a pointer and having the bus drivers set the operations prior to registering.
This is not a particularly good or nice approach but it avoids blocking multiplatform and a real fix involves fixing the fairly deep problems with AC'97 support - we should be converting it to a real bus.
--- include/sound/soc.h | 4 +++- sound/soc/au1x/ac97c.c | 7 +++++-- sound/soc/au1x/psc-ac97.c | 7 +++++-- sound/soc/blackfin/bf5xx-ac97.c | 11 +++++++++-- sound/soc/cirrus/ep93xx-ac97.c | 10 ++++++++-- sound/soc/codecs/ac97.c | 7 ++++--- sound/soc/codecs/ad1980.c | 12 ++++++------ sound/soc/codecs/stac9766.c | 22 +++++++++++----------- sound/soc/codecs/wm9705.c | 14 +++++++------- sound/soc/codecs/wm9712.c | 18 +++++++++--------- sound/soc/codecs/wm9713.c | 18 +++++++++--------- sound/soc/fsl/imx-ssi.c | 11 +++++++++-- sound/soc/fsl/mpc5200_psc_ac97.c | 10 ++++++++-- sound/soc/nuc900/nuc900-ac97.c | 11 ++++++++--- sound/soc/pxa/pxa2xx-ac97.c | 8 ++++++-- sound/soc/samsung/ac97.c | 12 +++++++++--- sound/soc/sh/hac.c | 8 ++++++-- sound/soc/soc-core.c | 16 ++++++++++++++++ sound/soc/tegra/tegra20_ac97.c | 12 ++++++++++-- sound/soc/txx9/txx9aclc-ac97.c | 8 ++++++-- 20 files changed, 154 insertions(+), 72 deletions(-)
include/sound/soc.h +3 -1
@@ -340,7 +340,7 @@ struct snd_soc_jack_gpio;typedef int (*hw_write_t )(void *,const char * ,int ); -extern struct snd_ac97_bus_ops soc_ac97_ops; +extern struct snd_ac97_bus_ops *soc_ac97_ops;enum snd_soc_control_type {SND_SOC_I2C =1 ,
@@ -467,6 +467,8 @@ int snd_soc_new_ac97_codec(struct snd_soc_codec *codec, struct snd_ac97_bus_ops *ops, int num);void snd_soc_free_ac97_codec (struct snd_soc_codec *codec); +int snd_soc_set_ac97_ops (struct snd_ac97_bus_ops *ops); +/* *Controls */
sound/soc/au1x/ac97c.c +5 -2
@@ -179,13 +179,12 @@ static void au1xac97c_ac97_cold_reset(struct snd_ac97 *ac97) }/* AC97 controller operations */ -struct snd_ac97_bus_ops soc_ac97_ops = { +static struct snd_ac97_bus_ops ac97c_bus_ops = { .read = au1xac97c_ac97_read, .write = au1xac97c_ac97_write, .reset = au1xac97c_ac97_cold_reset, .warm_reset = au1xac97c_ac97_warm_reset, }; -EXPORT_SYMBOL_GPL (soc_ac97_ops);/* globals be gone! */ static int alchemy_ac97c_startup (struct snd_pcm_substream *substream,struct snd_soc_dai *dai)
@@ -272,6 +271,10 @@ static int au1xac97c_drvprobe(struct platform_device *pdev)platform_set_drvdata (pdev, ctx); + ret =snd_soc_set_ac97_ops (&ac97c_bus_ops); +if (ret) +return ret; + ret =snd_soc_register_component (&pdev->dev, &au1xac97c_component, &au1xac97c_dai_driver,1 );if (ret)
sound/soc/au1x/psc-ac97.c +5 -2
@@ -201,13 +201,12 @@ static void au1xpsc_ac97_cold_reset(struct snd_ac97 *ac97) }/* AC97 controller operations */ -struct snd_ac97_bus_ops soc_ac97_ops = { +static struct snd_ac97_bus_ops psc_ac97_ops = { .read = au1xpsc_ac97_read, .write = au1xpsc_ac97_write, .reset = au1xpsc_ac97_cold_reset, .warm_reset = au1xpsc_ac97_warm_reset, }; -EXPORT_SYMBOL_GPL (soc_ac97_ops); static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params,
@@ -417,6 +416,10 @@ static int au1xpsc_ac97_drvprobe(struct platform_device *pdev)platform_set_drvdata (pdev, wd); + ret =snd_soc_set_ac97_ops (&psc_ac97_ops); +if (ret) +return ret; + ret =snd_soc_register_component (&pdev->dev, &au1xpsc_ac97_component, &wd->dai_drv,1 );if (ret)
sound/soc/blackfin/bf5xx-ac97.c +9 -2
@@ -198,13 +198,12 @@ static void bf5xx_ac97_cold_reset(struct snd_ac97 *ac97)#endif } -struct snd_ac97_bus_ops soc_ac97_ops = { +static struct snd_ac97_bus_ops bf5xx_ac97_ops = { .read = bf5xx_ac97_read, .write = bf5xx_ac97_write, .warm_reset = bf5xx_ac97_warm_reset, .reset = bf5xx_ac97_cold_reset, }; -EXPORT_SYMBOL_GPL (soc_ac97_ops);#ifdef CONFIG_PM static int bf5xx_ac97_suspend (struct snd_soc_dai *dai)
@@ -336,6 +335,12 @@ static int asoc_bfin_ac97_probe(struct platform_device *pdev) goto sport_config_err; } + ret =snd_soc_set_ac97_ops (&bf5xx_ac97_ops); +if (ret !=0 ) { +dev_err (&pdev->dev,"Failed to set AC'97 ops: %d\n" , ret); + goto sport_config_err; + } + ret =snd_soc_register_component (&pdev->dev, &bfin_ac97_component, &bfin_ac97_dai,1 );if (ret) {
@@ -350,6 +355,7 @@ static int asoc_bfin_ac97_probe(struct platform_device *pdev) sport_config_err:sport_done (sport_handle); sport_err: +snd_soc_set_ac97_ops (NULL );return ret; }
@@ -360,6 +366,7 @@ static int asoc_bfin_ac97_remove(struct platform_device *pdev)snd_soc_unregister_component (&pdev->dev);sport_done (sport_handle); +snd_soc_set_ac97_ops (NULL );return 0 ; }
sound/soc/cirrus/ep93xx-ac97.c +8 -2
@@ -237,13 +237,12 @@ static irqreturn_t ep93xx_ac97_interrupt(int irq, void *dev_id)return IRQ_HANDLED ; } -struct snd_ac97_bus_ops soc_ac97_ops = { +static struct snd_ac97_bus_ops ep93xx_ac97_ops = { .read = ep93xx_ac97_read, .write = ep93xx_ac97_write, .reset = ep93xx_ac97_cold_reset, .warm_reset = ep93xx_ac97_warm_reset, }; -EXPORT_SYMBOL_GPL (soc_ac97_ops);static int ep93xx_ac97_trigger (struct snd_pcm_substream *substream,int cmd,struct snd_soc_dai *dai)
@@ -389,6 +388,10 @@ static int ep93xx_ac97_probe(struct platform_device *pdev) ep93xx_ac97_info = info;platform_set_drvdata (pdev, info); + ret =snd_soc_set_ac97_ops (&ep93xx_ac97_ops); +if (ret) + goto fail; + ret =snd_soc_register_component (&pdev->dev, &ep93xx_ac97_component, &ep93xx_ac97_dai,1 );if (ret)
@@ -398,6 +401,7 @@ static int ep93xx_ac97_probe(struct platform_device *pdev) fail: ep93xx_ac97_info =NULL ; +snd_soc_set_ac97_ops (NULL );return ret; }
@@ -412,6 +416,8 @@ static int ep93xx_ac97_remove(struct platform_device *pdev) ep93xx_ac97_info =NULL ; +snd_soc_set_ac97_ops (NULL ); +return 0 ; }
sound/soc/codecs/ac97.c +4 -3
@@ -62,13 +62,13 @@ static struct snd_soc_dai_driver ac97_dai = {static unsigned int ac97_read (struct snd_soc_codec *codec,unsigned int reg) { -return soc_ac97_ops.read (codec->ac97, reg); +return soc_ac97_ops->read (codec->ac97, reg); }static int ac97_write (struct snd_soc_codec *codec,unsigned int reg,unsigned int val) { - soc_ac97_ops.write (codec->ac97, reg, val); + soc_ac97_ops->write (codec->ac97, reg, val);return 0 ; }
@@ -79,7 +79,8 @@ static int ac97_soc_probe(struct snd_soc_codec *codec)int ret;/* add codec as bus device for standard ac97 */ - ret =snd_ac97_bus (codec->card->snd_card,0 , &soc_ac97_ops,NULL , &ac97_bus); + ret =snd_ac97_bus (codec->card->snd_card,0 , soc_ac97_ops,NULL , + &ac97_bus);if (ret <0 )return ret;
sound/soc/codecs/ad1980.c +6 -6
@@ -108,7 +108,7 @@ static unsigned int ac97_read(struct snd_soc_codec *codec,case AC97_EXTENDED_STATUS :case AC97_VENDOR_ID1 :case AC97_VENDOR_ID2 : -return soc_ac97_ops.read (codec->ac97, reg); +return soc_ac97_ops->read (codec->ac97, reg);default : reg = reg >>1 ;
@@ -124,7 +124,7 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, {u16 *cache = codec->reg_cache; - soc_ac97_ops.write (codec->ac97, reg, val); + soc_ac97_ops->write (codec->ac97, reg, val); reg = reg >>1 ;if (reg <ARRAY_SIZE (ad1980_reg)) cache[reg] = val;
@@ -154,13 +154,13 @@ static int ad1980_reset(struct snd_soc_codec *codec, int try_warm)u16 retry_cnt =0 ; retry: -if (try_warm && soc_ac97_ops.warm_reset) { - soc_ac97_ops.warm_reset (codec->ac97); +if (try_warm && soc_ac97_ops->warm_reset) { + soc_ac97_ops->warm_reset (codec->ac97);if (ac97_read (codec,AC97_RESET ) ==0x0090 )return 1 ; } - soc_ac97_ops.reset (codec->ac97); + soc_ac97_ops->reset (codec->ac97);/* Set bit 16slot in register 74h, then every slot will has only 16 * bits. This command is sent out in 20bit mode, in which case the * first nibble of data is eaten by the addr. (Tag is always 16 bit)*/
@@ -186,7 +186,7 @@ static int ad1980_soc_probe(struct snd_soc_codec *codec)printk (KERN_INFO "AD1980 SoC Audio Codec\n" ); - ret =snd_soc_new_ac97_codec (codec, &soc_ac97_ops,0 ); + ret =snd_soc_new_ac97_codec (codec, soc_ac97_ops,0 );if (ret <0 ) {printk (KERN_ERR "ad1980: failed to register AC97 codec\n" );return ret;
sound/soc/codecs/stac9766.c +11 -11
@@ -143,14 +143,14 @@ static int stac9766_ac97_write(struct snd_soc_codec *codec, unsigned int reg,if (reg >AC97_STAC_PAGE0 ) {stac9766_ac97_write (codec,AC97_INT_PAGING ,0 ); - soc_ac97_ops.write (codec->ac97, reg, val); + soc_ac97_ops->write (codec->ac97, reg, val);stac9766_ac97_write (codec,AC97_INT_PAGING ,1 );return 0 ; }if (reg /2 >=ARRAY_SIZE (stac9766_reg))return -EIO ; - soc_ac97_ops.write (codec->ac97, reg, val); + soc_ac97_ops->write (codec->ac97, reg, val); cache[reg /2 ] = val;return 0 ; }
@@ -162,7 +162,7 @@ static unsigned int stac9766_ac97_read(struct snd_soc_codec *codec,if (reg >AC97_STAC_PAGE0 ) {stac9766_ac97_write (codec,AC97_INT_PAGING ,0 ); - val = soc_ac97_ops.read (codec->ac97, reg -AC97_STAC_PAGE0 ); + val = soc_ac97_ops->read (codec->ac97, reg -AC97_STAC_PAGE0 );stac9766_ac97_write (codec,AC97_INT_PAGING ,1 );return val; }
@@ -173,7 +173,7 @@ static unsigned int stac9766_ac97_read(struct snd_soc_codec *codec, reg == AC97_INT_PAGING || reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2) { - val = soc_ac97_ops.read (codec->ac97, reg); + val = soc_ac97_ops->read (codec->ac97, reg);return val; }return cache[reg /2 ];
@@ -240,15 +240,15 @@ static int stac9766_set_bias_level(struct snd_soc_codec *codec,static int stac9766_reset (struct snd_soc_codec *codec,int try_warm) { -if (try_warm && soc_ac97_ops.warm_reset) { - soc_ac97_ops.warm_reset (codec->ac97); +if (try_warm && soc_ac97_ops->warm_reset) { + soc_ac97_ops->warm_reset (codec->ac97);if (stac9766_ac97_read (codec,0 ) == stac9766_reg[0 ])return 1 ; } - soc_ac97_ops.reset (codec->ac97); -if (soc_ac97_ops.warm_reset) - soc_ac97_ops.warm_reset (codec->ac97); + soc_ac97_ops->reset (codec->ac97); +if (soc_ac97_ops->warm_reset) + soc_ac97_ops->warm_reset (codec->ac97);if (stac9766_ac97_read (codec,0 ) != stac9766_reg[0 ])return -EIO ;return 0 ;
@@ -272,7 +272,7 @@ reset:return -EIO ; } codec->ac97->bus->ops->warm_reset (codec->ac97); - id = soc_ac97_ops.read (codec->ac97,AC97_VENDOR_ID2 ); + id = soc_ac97_ops->read (codec->ac97,AC97_VENDOR_ID2 );if (id !=0x4c13 ) {stac9766_reset (codec,0 ); reset++;
@@ -336,7 +336,7 @@ static int stac9766_codec_probe(struct snd_soc_codec *codec) {int ret =0 ; - ret =snd_soc_new_ac97_codec (codec, &soc_ac97_ops,0 ); + ret =snd_soc_new_ac97_codec (codec, soc_ac97_ops,0 );if (ret <0 ) goto codec_err;
sound/soc/codecs/wm9705.c +7 -7
@@ -209,7 +209,7 @@ static unsigned int ac97_read(struct snd_soc_codec *codec, unsigned int reg)case AC97_RESET :case AC97_VENDOR_ID1 :case AC97_VENDOR_ID2 : -return soc_ac97_ops.read (codec->ac97, reg); +return soc_ac97_ops->read (codec->ac97, reg);default : reg = reg >>1 ;
@@ -225,7 +225,7 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, {u16 *cache = codec->reg_cache; - soc_ac97_ops.write (codec->ac97, reg, val); + soc_ac97_ops->write (codec->ac97, reg, val); reg = reg >>1 ;if (reg < (ARRAY_SIZE (wm9705_reg))) cache[reg] = val;
@@ -294,8 +294,8 @@ static struct snd_soc_dai_driver wm9705_dai[] = {static int wm9705_reset (struct snd_soc_codec *codec) { -if (soc_ac97_ops.reset) { - soc_ac97_ops.reset (codec->ac97); +if (soc_ac97_ops->reset) { + soc_ac97_ops->reset (codec->ac97);if (ac97_read (codec,0 ) == wm9705_reg[0 ])return 0 ;/* Success */ }
@@ -306,7 +306,7 @@ static int wm9705_reset(struct snd_soc_codec *codec)#ifdef CONFIG_PM static int wm9705_soc_suspend (struct snd_soc_codec *codec) { - soc_ac97_ops.write (codec->ac97,AC97_POWERDOWN ,0xffff ); + soc_ac97_ops->write (codec->ac97,AC97_POWERDOWN ,0xffff );return 0 ; }
@@ -323,7 +323,7 @@ static int wm9705_soc_resume(struct snd_soc_codec *codec) }for (i =2 ; i <ARRAY_SIZE (wm9705_reg) <<1 ; i +=2 ) { - soc_ac97_ops.write (codec->ac97, i, cache[i>>1 ]); + soc_ac97_ops->write (codec->ac97, i, cache[i>>1 ]); }return 0 ;
@@ -337,7 +337,7 @@ static int wm9705_soc_probe(struct snd_soc_codec *codec) {int ret =0 ; - ret =snd_soc_new_ac97_codec (codec, &soc_ac97_ops,0 ); + ret =snd_soc_new_ac97_codec (codec, soc_ac97_ops,0 );if (ret <0 ) {printk (KERN_ERR "wm9705: failed to register AC97 codec\n" );return ret;
sound/soc/codecs/wm9712.c +9 -9
@@ -455,7 +455,7 @@ static unsigned int ac97_read(struct snd_soc_codec *codec,if (reg ==AC97_RESET || reg ==AC97_GPIO_STATUS || reg ==AC97_VENDOR_ID1 || reg ==AC97_VENDOR_ID2 || reg ==AC97_REC_GAIN ) -return soc_ac97_ops.read (codec->ac97, reg); +return soc_ac97_ops->read (codec->ac97, reg);else { reg = reg >>1 ;
@@ -472,7 +472,7 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,u16 *cache = codec->reg_cache;if (reg <0x7c ) - soc_ac97_ops.write (codec->ac97, reg, val); + soc_ac97_ops->write (codec->ac97, reg, val); reg = reg >>1 ;if (reg < (ARRAY_SIZE (wm9712_reg))) cache[reg] = val;
@@ -581,15 +581,15 @@ static int wm9712_set_bias_level(struct snd_soc_codec *codec,static int wm9712_reset (struct snd_soc_codec *codec,int try_warm) { -if (try_warm && soc_ac97_ops.warm_reset) { - soc_ac97_ops.warm_reset (codec->ac97); +if (try_warm && soc_ac97_ops->warm_reset) { + soc_ac97_ops->warm_reset (codec->ac97);if (ac97_read (codec,0 ) == wm9712_reg[0 ])return 1 ; } - soc_ac97_ops.reset (codec->ac97); -if (soc_ac97_ops.warm_reset) - soc_ac97_ops.warm_reset (codec->ac97); + soc_ac97_ops->reset (codec->ac97); +if (soc_ac97_ops->warm_reset) + soc_ac97_ops->warm_reset (codec->ac97);if (ac97_read (codec,0 ) != wm9712_reg[0 ]) goto err;return 0 ;
@@ -624,7 +624,7 @@ static int wm9712_soc_resume(struct snd_soc_codec *codec)if (i ==AC97_INT_PAGING || i ==AC97_POWERDOWN || (i >0x58 && i !=0x5c ))continue ; - soc_ac97_ops.write (codec->ac97, i, cache[i>>1 ]); + soc_ac97_ops->write (codec->ac97, i, cache[i>>1 ]); } }
@@ -635,7 +635,7 @@ static int wm9712_soc_probe(struct snd_soc_codec *codec) {int ret =0 ; - ret =snd_soc_new_ac97_codec (codec, &soc_ac97_ops,0 ); + ret =snd_soc_new_ac97_codec (codec, soc_ac97_ops,0 );if (ret <0 ) {printk (KERN_ERR "wm9712: failed to register AC97 codec\n" );return ret;
sound/soc/codecs/wm9713.c +9 -9
@@ -652,7 +652,7 @@ static unsigned int ac97_read(struct snd_soc_codec *codec,if (reg ==AC97_RESET || reg ==AC97_GPIO_STATUS || reg ==AC97_VENDOR_ID1 || reg ==AC97_VENDOR_ID2 || reg ==AC97_CD ) -return soc_ac97_ops.read (codec->ac97, reg); +return soc_ac97_ops->read (codec->ac97, reg);else { reg = reg >>1 ;
@@ -668,7 +668,7 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, {u16 *cache = codec->reg_cache;if (reg <0x7c ) - soc_ac97_ops.write (codec->ac97, reg, val); + soc_ac97_ops->write (codec->ac97, reg, val); reg = reg >>1 ;if (reg < (ARRAY_SIZE (wm9713_reg))) cache[reg] = val;
@@ -1095,15 +1095,15 @@ static struct snd_soc_dai_driver wm9713_dai[] = {int wm9713_reset (struct snd_soc_codec *codec,int try_warm) { -if (try_warm && soc_ac97_ops.warm_reset) { - soc_ac97_ops.warm_reset (codec->ac97); +if (try_warm && soc_ac97_ops->warm_reset) { + soc_ac97_ops->warm_reset (codec->ac97);if (ac97_read (codec,0 ) == wm9713_reg[0 ])return 1 ; } - soc_ac97_ops.reset (codec->ac97); -if (soc_ac97_ops.warm_reset) - soc_ac97_ops.warm_reset (codec->ac97); + soc_ac97_ops->reset (codec->ac97); +if (soc_ac97_ops->warm_reset) + soc_ac97_ops->warm_reset (codec->ac97);if (ac97_read (codec,0 ) != wm9713_reg[0 ])return -EIO ;return 0 ;
@@ -1180,7 +1180,7 @@ static int wm9713_soc_resume(struct snd_soc_codec *codec)if (i ==AC97_POWERDOWN || i ==AC97_EXTENDED_MID || i ==AC97_EXTENDED_MSTATUS || i >0x66 )continue ; - soc_ac97_ops.write (codec->ac97, i, cache[i>>1 ]); + soc_ac97_ops->write (codec->ac97, i, cache[i>>1 ]); } }
@@ -1197,7 +1197,7 @@ static int wm9713_soc_probe(struct snd_soc_codec *codec)return -ENOMEM ;snd_soc_codec_set_drvdata (codec, wm9713); - ret =snd_soc_new_ac97_codec (codec, &soc_ac97_ops,0 ); + ret =snd_soc_new_ac97_codec (codec, soc_ac97_ops,0 );if (ret <0 ) goto codec_err;
sound/soc/fsl/imx-ssi.c +9 -2
@@ -501,13 +501,12 @@ static void imx_ssi_ac97_warm_reset(struct snd_ac97 *ac97)imx_ssi_ac97_read (ac97,0 ); } -struct snd_ac97_bus_ops soc_ac97_ops = { +static struct snd_ac97_bus_ops imx_ssi_ac97_ops = { .read = imx_ssi_ac97_read, .write = imx_ssi_ac97_write, .reset = imx_ssi_ac97_reset, .warm_reset = imx_ssi_ac97_warm_reset }; -EXPORT_SYMBOL_GPL (soc_ac97_ops);static int imx_ssi_probe (struct platform_device *pdev) {
@@ -583,6 +582,12 @@ static int imx_ssi_probe(struct platform_device *pdev)platform_set_drvdata (pdev, ssi); + ret =snd_soc_set_ac97_ops (&imx_ssi_ac97_ops); +if (ret !=0 ) { +dev_err (&pdev->dev,"Failed to set AC'97 ops: %d\n" , ret); + goto failed_register; + } + ret =snd_soc_register_component (&pdev->dev, &imx_component, dai,1 );if (ret) {
@@ -608,6 +613,7 @@ failed_register:release_mem_region (res->start,resource_size (res));clk_disable_unprepare (ssi->clk); failed_clk: +snd_soc_set_ac97_ops (NULL );return ret; }
@@ -627,6 +633,7 @@ static int imx_ssi_remove(struct platform_device *pdev)release_mem_region (res->start,resource_size (res));clk_disable_unprepare (ssi->clk); +snd_soc_set_ac97_ops (NULL );return 0 ; }
sound/soc/fsl/mpc5200_psc_ac97.c +8 -2
@@ -131,13 +131,12 @@ static void psc_ac97_cold_reset(struct snd_ac97 *ac97)psc_ac97_warm_reset (ac97); } -struct snd_ac97_bus_ops soc_ac97_ops = { +static struct snd_ac97_bus_ops psc_ac97_ops = { .read = psc_ac97_read, .write = psc_ac97_write, .reset = psc_ac97_cold_reset, .warm_reset = psc_ac97_warm_reset, }; -EXPORT_SYMBOL_GPL (soc_ac97_ops); static int psc_ac97_hw_analog_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params,
@@ -290,6 +289,12 @@ static int psc_ac97_of_probe(struct platform_device *op)if (rc !=0 )return rc; + rc =snd_soc_set_ac97_ops (&psc_ac97_ops); +if (rc !=0 ) { +dev_err (&op->dev,"Failed to set AC'97 ops: %d\n" , ret); +return rc; + } + rc =snd_soc_register_component (&op->dev, &psc_ac97_component, psc_ac97_dai,ARRAY_SIZE (psc_ac97_dai));if (rc !=0 ) {
@@ -318,6 +323,7 @@ static int psc_ac97_of_remove(struct platform_device *op) {mpc5200_audio_dma_destroy (op);snd_soc_unregister_component (&op->dev); +snd_soc_set_ac97_ops (NULL );return 0 ; }
sound/soc/nuc900/nuc900-ac97.c +8 -3
@@ -197,13 +197,12 @@ static void nuc900_ac97_cold_reset(struct snd_ac97 *ac97) }/* AC97 controller operations */ -struct snd_ac97_bus_ops soc_ac97_ops = { +static struct snd_ac97_bus_ops nuc900_ac97_ops = { .read = nuc900_ac97_read, .write = nuc900_ac97_write, .reset = nuc900_ac97_cold_reset, .warm_reset = nuc900_ac97_warm_reset, -} -EXPORT_SYMBOL_GPL (soc_ac97_ops); +};static int nuc900_ac97_trigger (struct snd_pcm_substream *substream,int cmd,struct snd_soc_dai *dai)
@@ -356,6 +355,10 @@ static int nuc900_ac97_drvprobe(struct platform_device *pdev) nuc900_ac97_data = nuc900_audio; + ret =snd_soc_set_ac97_ops (&nuc900_ac97_ops); +if (ret) + goto out; + ret =snd_soc_register_component (&pdev->dev, &nuc900_ac97_component, &nuc900_ac97_dai,1 );if (ret)
@@ -367,6 +370,7 @@ static int nuc900_ac97_drvprobe(struct platform_device *pdev)return 0 ; out: +snd_soc_set_ac97_ops (NULL );return ret; }
@@ -375,6 +379,7 @@ static int nuc900_ac97_drvremove(struct platform_device *pdev)snd_soc_unregister_component (&pdev->dev); nuc900_ac97_data =NULL ; +snd_soc_set_ac97_ops (NULL );return 0 ; }
sound/soc/pxa/pxa2xx-ac97.c +6 -2
@@ -41,13 +41,12 @@ static void pxa2xx_ac97_cold_reset(struct snd_ac97 *ac97)pxa2xx_ac97_finish_reset (ac97); } -struct snd_ac97_bus_ops soc_ac97_ops = { +static struct snd_ac97_bus_ops pxa2xx_ac97_ops = { .read = pxa2xx_ac97_read, .write = pxa2xx_ac97_write, .warm_reset = pxa2xx_ac97_warm_reset, .reset = pxa2xx_ac97_cold_reset, }; -EXPORT_SYMBOL_GPL (soc_ac97_ops);static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_out = { .name ="AC97 PCM Stereo out" ,
@@ -244,6 +243,10 @@ static int pxa2xx_ac97_dev_probe(struct platform_device *pdev)return -ENXIO ; } + ret =snd_soc_set_ac97_ops (&pxa2xx_ac97_ops); +if (ret !=0 ) +return ret; +/* Punt most of the init to the SoC probe; we may need the machine * driver to do interesting things with the clocking to get us up * and running.
@@ -255,6 +258,7 @@ static int pxa2xx_ac97_dev_probe(struct platform_device *pdev)static int pxa2xx_ac97_dev_remove (struct platform_device *pdev) {snd_soc_unregister_component (&pdev->dev); +snd_soc_set_ac97_ops (NULL );return 0 ; }
sound/soc/samsung/ac97.c +9 -3
@@ -214,13 +214,12 @@ static irqreturn_t s3c_ac97_irq(int irq, void *dev_id)return IRQ_HANDLED ; } -struct snd_ac97_bus_ops soc_ac97_ops = { +static struct snd_ac97_bus_ops s3c_ac97_ops = { .read = s3c_ac97_read, .write = s3c_ac97_write, .warm_reset = s3c_ac97_warm_reset, .reset = s3c_ac97_cold_reset, }; -EXPORT_SYMBOL_GPL (soc_ac97_ops); static int s3c_ac97_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params,
@@ -452,6 +451,12 @@ static int s3c_ac97_probe(struct platform_device *pdev) goto err4; } + ret =snd_soc_set_ac97_ops (&s3c_ac97_ops); +if (ret !=0 ) { +dev_err (&pdev->dev,"Failed to set AC'97 ops: %d\n" , ret); + goto err4; + } + ret =snd_soc_register_component (&pdev->dev, &s3c_ac97_component, s3c_ac97_dai,ARRAY_SIZE (s3c_ac97_dai));if (ret)
@@ -472,7 +477,7 @@ err4: err3:clk_disable_unprepare (s3c_ac97.ac97_clk); err2: - +snd_soc_set_ac97_ops (NULL );return ret; }
@@ -488,6 +493,7 @@ static int s3c_ac97_remove(struct platform_device *pdev)free_irq (irq_res->start,NULL );clk_disable_unprepare (s3c_ac97.ac97_clk); +snd_soc_set_ac97_ops (NULL );return 0 ; }
sound/soc/sh/hac.c +6 -2
@@ -227,13 +227,12 @@ static void hac_ac97_coldrst(struct snd_ac97 *ac97)hac_ac97_warmrst (ac97); } -struct snd_ac97_bus_ops soc_ac97_ops = { +static struct snd_ac97_bus_ops hac_ac97_ops = { .read = hac_ac97_read, .write = hac_ac97_write, .reset = hac_ac97_coldrst, .warm_reset = hac_ac97_warmrst, }; -EXPORT_SYMBOL_GPL (soc_ac97_ops); static int hac_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params,
@@ -316,6 +315,10 @@ static const struct snd_soc_component_driver sh4_hac_component = {static int hac_soc_platform_probe (struct platform_device *pdev) { + ret =snd_soc_set_ac97_ops (&hac_ac97_ops); +if (ret !=0 ) +return ret; +return snd_soc_register_component (&pdev->dev, &sh4_hac_component, sh4_hac_dai,ARRAY_SIZE (sh4_hac_dai)); }
@@ -323,6 +326,7 @@ static int hac_soc_platform_probe(struct platform_device *pdev)static int hac_soc_platform_remove (struct platform_device *pdev) {snd_soc_unregister_component (&pdev->dev); +snd_soc_set_ac97_ops (NULL );return 0 ; }
sound/soc/soc-core.c +16 -0
@@ -2080,6 +2080,22 @@ int snd_soc_new_ac97_codec(struct snd_soc_codec *codec, }EXPORT_SYMBOL_GPL (snd_soc_new_ac97_codec); +struct snd_ac97_bus_ops *soc_ac97_ops; + +int snd_soc_set_ac97_ops (struct snd_ac97_bus_ops *ops) +{ +if (ops == soc_ac97_ops) +return 0 ; + +if (soc_ac97_ops && ops) +return -EBUSY ; + + soc_ac97_ops = ops; + +return 0 ; +} +EXPORT_SYMBOL_GPL (snd_soc_set_ac97_ops); +/** * snd_soc_free_ac97_codec - free AC97 codec device * @codec: audio codec
sound/soc/tegra/tegra20_ac97.c +10 -2
@@ -142,13 +142,12 @@ static void tegra20_ac97_codec_write(struct snd_ac97 *ac97_snd, }while (!time_after (jiffies, timeout)); } -struct snd_ac97_bus_ops soc_ac97_ops = { +static struct snd_ac97_bus_ops tegra20_ac97_ops = { .read = tegra20_ac97_codec_read, .write = tegra20_ac97_codec_write, .reset = tegra20_ac97_codec_reset, .warm_reset = tegra20_ac97_codec_warm_reset, }; -EXPORT_SYMBOL_GPL (soc_ac97_ops);static inline void tegra20_ac97_start_playback (struct tegra20_ac97 *ac97) {
@@ -409,6 +408,12 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev) goto err_asoc_utils_fini; } + ret =snd_soc_set_ac97_ops (&tegra20_ac97_ops); +if (ret) { +dev_err (&pdev->dev,"Failed to set AC'97 ops: %d\n" , ret); + goto err_asoc_utils_fini; + } + ret =snd_soc_register_component (&pdev->dev, &tegra20_ac97_component, &tegra20_ac97_dai,1 );if (ret) {
@@ -436,6 +441,7 @@ err_asoc_utils_fini:tegra_asoc_utils_fini (&ac97->util_data); err_clk_put: err: +snd_soc_set_ac97_ops (NULL );return ret; }
@@ -450,6 +456,8 @@ static int tegra20_ac97_platform_remove(struct platform_device *pdev)clk_disable_unprepare (ac97->clk_ac97); +snd_soc_set_ac97_ops (NULL ); +return 0 ; }
sound/soc/txx9/txx9aclc-ac97.c +6 -2
@@ -119,12 +119,11 @@ static void txx9aclc_ac97_cold_reset(struct snd_ac97 *ac97) }/* AC97 controller operations */ -struct snd_ac97_bus_ops soc_ac97_ops = { +static struct snd_ac97_bus_ops txx9aclc_ac97_ops = { .read = txx9aclc_ac97_read, .write = txx9aclc_ac97_write, .reset = txx9aclc_ac97_cold_reset, }; -EXPORT_SYMBOL_GPL (soc_ac97_ops);static irqreturn_t txx9aclc_ac97_irq (int irq,void *dev_id) {
@@ -206,6 +205,10 @@ static int txx9aclc_ac97_dev_probe(struct platform_device *pdev)if (err <0 )return err; + err =snd_soc_set_ac97_ops (&txx9aclc_ac97_ops); +if (err <0 ) +return err; +return snd_soc_register_component (&pdev->dev, &txx9aclc_ac97_component, &txx9aclc_ac97_dai,1 ); }
@@ -213,6 +216,7 @@ static int txx9aclc_ac97_dev_probe(struct platform_device *pdev)static int txx9aclc_ac97_dev_remove (struct platform_device *pdev) {snd_soc_unregister_component (&pdev->dev); +snd_soc_set_ac97_ops (NULL );return 0 ; }
Signature · 1 line
1.8.3.1
Quoted 10 lines · On Wednesday 26 June 2013 12:48:16 Mark Brown wrote:
From: Mark Brown <[email protected]>
Currently we can only have a single platform built in with AC'97 support due to the use of a global variable to provide the bus operations. Fix this by making that variable a pointer and having the bus drivers set the operations prior to registering.
This is not a particularly good or nice approach but it avoids blocking multiplatform and a real fix involves fixing the fairly deep problems with AC'97 support - we should be converting it to a real bus.
It is nicer than the Kconfig hack I posted though. I had started yet another approach at some point but that grew to a rather large patch and I got bored before it was complete:
The idea is to turn the ac97 ops into a pointer that is passed around the structures that actually use it. See below for how far I got with this.
Quoted 1 line
Signed-off-by Mark Brown <[email protected]>
-----
commit 093119e386b2093b9f76a0fd908dcc080080e1a0
Author: Arnd Bergmann <[email protected]> Date: Tue Apr 23 16:59:42 2013 +0200
[incomplete] ASoC: move soc_ac97_ops into card structure
include/sound/soc.h +5 -2
@@ -463,8 +463,7 @@ int snd_soc_update_bits_locked(struct snd_soc_codec *codec,int snd_soc_test_bits (struct snd_soc_codec *codec,unsigned short reg,unsigned int mask,unsigned int value); -int snd_soc_new_ac97_codec (struct snd_soc_codec *codec, -struct snd_ac97_bus_ops *ops,int num); +int snd_soc_new_ac97_codec (struct snd_soc_codec *codec);void snd_soc_free_ac97_codec (struct snd_soc_codec *codec);/*
@@ -932,6 +931,7 @@ struct snd_soc_dai_link {/* machine stream operations */ const struct snd_soc_ops *ops;const struct snd_soc_compr_ops *compr_ops; +const struct snd_ac97_bus_ops *ac97_ops; };struct snd_soc_codec_conf {
@@ -992,6 +992,8 @@ struct snd_soc_card {struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level); +struct snd_ac97_bus_ops *ac97_ops; +long pmdown_time;/* CPU <--> Codec DAI links */
@@ -1004,6 +1006,7 @@ struct snd_soc_card {struct snd_soc_codec_conf *codec_conf;int num_configs; +/* * optional auxiliary devices such as amplifiers or codecs with DAI * link unused
sound/soc/au1x/ac97c.c +2 -2
@@ -179,13 +179,13 @@ static void au1xac97c_ac97_cold_reset(struct snd_ac97 *ac97) }/* AC97 controller operations */ -struct snd_ac97_bus_ops soc_ac97_ops = { +struct snd_ac97_bus_ops au1x_ac97_ops = { .read = au1xac97c_ac97_read, .write = au1xac97c_ac97_write, .reset = au1xac97c_ac97_cold_reset, .warm_reset = au1xac97c_ac97_warm_reset, }; -EXPORT_SYMBOL_GPL (soc_ac97_ops);/* globals be gone! */ +EXPORT_SYMBOL_GPL (au1x_ac97_ops);/* globals be gone! */ static int alchemy_ac97c_startup (struct snd_pcm_substream *substream,struct snd_soc_dai *dai)
sound/soc/au1x/db1000.c +1 -0
@@ -32,6 +32,7 @@ static struct snd_soc_card db1000_ac97 = { .owner = THIS_MODULE, .dai_link = &db1000_ac97_dai, .num_links = 1, + .ac97_ops = &au1x_ac97_ops, };static int db1000_audio_probe (struct platform_device *pdev)
sound/soc/au1x/db1200.c +3 -0
@@ -60,6 +60,7 @@ static struct snd_soc_card db1200_ac97_machine = { .owner = THIS_MODULE, .dai_link = &db1200_ac97_dai, .num_links = 1, + .ac97_ops = &au1xpsc_ac97_ops, };static struct snd_soc_dai_link db1300_ac97_dai = {
@@ -75,12 +76,14 @@ static struct snd_soc_card db1300_ac97_machine = { .name = "DB1300_AC97", .dai_link = &db1300_ac97_dai, .num_links = 1, + .ac97_ops = &au1xpsc_ac97_ops, };static struct snd_soc_card db1550_ac97_machine = { .name ="DB1550_AC97" , .dai_link = &db1200_ac97_dai, .num_links =1 , + .ac97_ops = &au1xpsc_ac97_ops, };/*------------------------- I2S PART ---------------------------*/
sound/soc/au1x/psc-ac97.c +2 -2
@@ -201,13 +201,13 @@ static void au1xpsc_ac97_cold_reset(struct snd_ac97 *ac97) }/* AC97 controller operations */ -struct snd_ac97_bus_ops soc_ac97_ops = { +struct snd_ac97_bus_ops au1xpsc_ac97_ops = { .read = au1xpsc_ac97_read, .write = au1xpsc_ac97_write, .reset = au1xpsc_ac97_cold_reset, .warm_reset = au1xpsc_ac97_warm_reset, }; -EXPORT_SYMBOL_GPL (soc_ac97_ops); +EXPORT_SYMBOL_GPL (au1xpsc_ac97_ops); static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params,
sound/soc/au1x/psc.h +3 -0
@@ -26,6 +26,9 @@ struct au1xpsc_audio_data {int dmaids[2 ]; }; +extern struct snd_ac97_bus_ops au1xpsc_ac97_ops; +extern struct snd_ac97_bus_ops au1x_ac97_ops; +/* easy access macros */ #define PSC_CTRL (x) ((unsigned long)((x)->mmio) + PSC_CTRL_OFFSET)#define PSC_SEL (x) ((unsigned long)((x)->mmio) + PSC_SEL_OFFSET)
sound/soc/cirrus/ep93xx-ac97.c +2 -2
@@ -237,13 +237,13 @@ static irqreturn_t ep93xx_ac97_interrupt(int irq, void *dev_id)return IRQ_HANDLED ; } -struct snd_ac97_bus_ops soc_ac97_ops = { +struct snd_ac97_bus_ops ep93xx_ac97_ops = { .read = ep93xx_ac97_read, .write = ep93xx_ac97_write, .reset = ep93xx_ac97_cold_reset, .warm_reset = ep93xx_ac97_warm_reset, }; -EXPORT_SYMBOL_GPL (soc_ac97_ops); +EXPORT_SYMBOL_GPL (ep93xx_ac97_ops);static int ep93xx_ac97_trigger (struct snd_pcm_substream *substream,int cmd,struct snd_soc_dai *dai)
sound/soc/cirrus/simone.c +1 -0
@@ -35,6 +35,7 @@ static struct snd_soc_card snd_soc_simone = { .owner = THIS_MODULE, .dai_link = &simone_dai, .num_links = 1, + .ac97_ops = &ep93xx_ac97_ops, };static struct platform_device *simone_snd_ac97_device;
sound/soc/codecs/ac97.c +3 -3
@@ -62,13 +62,13 @@ static struct snd_soc_dai_driver ac97_dai = {static unsigned int ac97_read (struct snd_soc_codec *codec,unsigned int reg) { -return codec->bus->ops->read (codec->ac97, reg); +return codec->ac97->bus->ops->read (codec->ac97, reg); }static int ac97_write (struct snd_soc_codec *codec,unsigned int reg,unsigned int val) { - codec->bus->ops->write (codec->ac97, reg, val); + codec->ac97->bus->ops->write (codec->ac97, reg, val);return 0 ; }
@@ -79,7 +79,7 @@ static int ac97_soc_probe(struct snd_soc_codec *codec)int ret;/* add codec as bus device for standard ac97 */ - ret =snd_ac97_bus (codec->card->snd_card,0 , &soc_ac97_ops,NULL , &ac97_bus); + ret =snd_ac97_bus (codec->card->snd_card,0 , codec->card->ac97_ops,NULL , &ac97_bus);if (ret <0 )return ret;
sound/soc/codecs/ad1980.c +1 -1
@@ -186,7 +186,7 @@ static int ad1980_soc_probe(struct snd_soc_codec *codec)printk (KERN_INFO "AD1980 SoC Audio Codec\n" ); - ret =snd_soc_new_ac97_codec (codec, &soc_ac97_ops,0 ); + ret =snd_soc_new_ac97_codec (codec);if (ret <0 ) {printk (KERN_ERR "ad1980: failed to register AC97 codec\n" );return ret;
sound/soc/codecs/stac9766.c +1 -1
@@ -340,7 +340,7 @@ static int stac9766_codec_probe(struct snd_soc_codec *codec)printk (KERN_INFO "STAC9766 SoC Audio Codec %s\n" ,STAC9766_VERSION ); - ret =snd_soc_new_ac97_codec (codec, &soc_ac97_ops,0 ); + ret =snd_soc_new_ac97_codec (codec);if (ret <0 ) goto codec_err;
sound/soc/codecs/wm9705.c +1 -1
@@ -339,7 +339,7 @@ static int wm9705_soc_probe(struct snd_soc_codec *codec)printk (KERN_INFO "WM9705 SoC Audio Codec\n" ); - ret =snd_soc_new_ac97_codec (codec, &soc_ac97_ops,0 ); + ret =snd_soc_new_ac97_codec (codec);if (ret <0 ) {printk (KERN_ERR "wm9705: failed to register AC97 codec\n" );return ret;
sound/soc/codecs/wm9712.c +1 -1
@@ -635,7 +635,7 @@ static int wm9712_soc_probe(struct snd_soc_codec *codec) {int ret =0 ; - ret =snd_soc_new_ac97_codec (codec, &soc_ac97_ops,0 ); + ret =snd_soc_new_ac97_codec (codec);if (ret <0 ) {printk (KERN_ERR "wm9712: failed to register AC97 codec\n" );return ret;
sound/soc/codecs/wm9713.c +1 -1
@@ -1197,7 +1197,7 @@ static int wm9713_soc_probe(struct snd_soc_codec *codec)return -ENOMEM ;snd_soc_codec_set_drvdata (codec, wm9713); - ret =snd_soc_new_ac97_codec (codec, &soc_ac97_ops,0 ); + ret =snd_soc_new_ac97_codec (codec);if (ret <0 ) goto codec_err;
sound/soc/fsl/imx-ssi.c +2 -2
@@ -501,13 +501,13 @@ static void imx_ssi_ac97_warm_reset(struct snd_ac97 *ac97)imx_ssi_ac97_read (ac97,0 ); } -struct snd_ac97_bus_ops soc_ac97_ops = { +struct snd_ac97_bus_ops imx_ssi_ac97_ops = { .read = imx_ssi_ac97_read, .write = imx_ssi_ac97_write, .reset = imx_ssi_ac97_reset, .warm_reset = imx_ssi_ac97_warm_reset }; -EXPORT_SYMBOL_GPL (soc_ac97_ops); +EXPORT_SYMBOL_GPL (imx_ssi_ac97_ops);static int imx_ssi_probe (struct platform_device *pdev) {
sound/soc/fsl/imx-ssi.h +2 -0
@@ -216,4 +216,6 @@ struct imx_ssi { struct platform_device *soc_platform_pdev_fiq; }; +extern struct snd_ac97_bus_ops imx_ssi_ac97_ops; +#endif /* _IMX_SSI_H */
sound/soc/fsl/mpc5200_psc_ac97.c +2 -2
@@ -131,13 +131,13 @@ static void psc_ac97_cold_reset(struct snd_ac97 *ac97)psc_ac97_warm_reset (ac97); } -struct snd_ac97_bus_ops soc_ac97_ops = { +struct snd_ac97_bus_ops psc_ac97_ops = { .read = psc_ac97_read, .write = psc_ac97_write, .reset = psc_ac97_cold_reset, .warm_reset = psc_ac97_warm_reset, }; -EXPORT_SYMBOL_GPL (soc_ac97_ops); +EXPORT_SYMBOL_GPL (psc_ac97_ops); static int psc_ac97_hw_analog_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params,
sound/soc/fsl/mpc5200_psc_ac97.h +2 -0
@@ -10,4 +10,6 @@#define MPC5200_AC97_NORMAL 0#define MPC5200_AC97_SPDIF 1 +extern struct snd_ac97_bus_ops *psc_ac97_ops; +#endif /* __SOUND_SOC_FSL_MPC52xx_PSC_AC97_H__ */
sound/soc/nuc900/nuc900-ac97.c +2 -2
@@ -197,13 +197,13 @@ static void nuc900_ac97_cold_reset(struct snd_ac97 *ac97) }/* AC97 controller operations */ -struct snd_ac97_bus_ops soc_ac97_ops = { +struct snd_ac97_bus_ops nuc900_ac97_ops = { .read = nuc900_ac97_read, .write = nuc900_ac97_write, .reset = nuc900_ac97_cold_reset, .warm_reset = nuc900_ac97_warm_reset, } -EXPORT_SYMBOL_GPL (soc_ac97_ops); +EXPORT_SYMBOL_GPL (nuc900_ac97_ops);static int nuc900_ac97_trigger (struct snd_pcm_substream *substream,int cmd,struct snd_soc_dai *dai)
sound/soc/nuc900/nuc900-audio.c +1 -0
@@ -35,6 +35,7 @@ static struct snd_soc_card nuc900evb_audio_machine = { .owner = THIS_MODULE, .dai_link = &nuc900evb_ac97_dai, .num_links = 1, + .ac97_ops = &nuc900_ac97_ops, };static struct platform_device *nuc900evb_asoc_dev;
sound/soc/nuc900/nuc900-audio.h +1 -0
@@ -111,5 +111,6 @@ struct nuc900_audio { };extern struct nuc900_audio *nuc900_ac97_data; +extern struct snd_ac97_bus_ops *nuc900_ac97_ops;#endif /*end _NUC900_AUDIO_H */
sound/soc/pxa/pxa2xx-ac97.c +2 -2
@@ -41,13 +41,13 @@ static void pxa2xx_ac97_cold_reset(struct snd_ac97 *ac97)pxa2xx_ac97_finish_reset (ac97); } -struct snd_ac97_bus_ops soc_ac97_ops = { +struct snd_ac97_bus_ops pxa2xx_ac97_ops = { .read = pxa2xx_ac97_read, .write = pxa2xx_ac97_write, .warm_reset = pxa2xx_ac97_warm_reset, .reset = pxa2xx_ac97_cold_reset, }; -EXPORT_SYMBOL_GPL (soc_ac97_ops); +EXPORT_SYMBOL_GPL (pxa2xx_ac97_ops);static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_out = { .name ="AC97 PCM Stereo out" ,
sound/soc/samsung/ac97.c +2 -2
@@ -214,13 +214,13 @@ static irqreturn_t s3c_ac97_irq(int irq, void *dev_id)return IRQ_HANDLED ; } -struct snd_ac97_bus_ops soc_ac97_ops = { +struct snd_ac97_bus_ops s3c_ac97_ops = { .read = s3c_ac97_read, .write = s3c_ac97_write, .warm_reset = s3c_ac97_warm_reset, .reset = s3c_ac97_cold_reset, }; -EXPORT_SYMBOL_GPL (soc_ac97_ops); +EXPORT_SYMBOL_GPL (s3c_ac97_ops); static int s3c_ac97_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params,
sound/soc/samsung/ln2440sbc_alc650.c +1 -0
@@ -37,6 +37,7 @@ static struct snd_soc_card ln2440sbc = { .owner = THIS_MODULE, .dai_link = ln2440sbc_dai, .num_links = ARRAY_SIZE(ln2440sbc_dai), + .ac97_ops = &samsung_ac97_ops, };static struct platform_device *ln2440sbc_snd_ac97_device;
sound/soc/samsung/regs-ac97.h +2 -0
@@ -64,4 +64,6 @@#define S3C_AC97_PCM_DATA (0x18)#define S3C_AC97_MIC_DATA (0x1C) +extern struct snd_ac97_bus_ops *s3c_ac97_ops; +#endif /* __ASM_ARCH_REGS_AC97_H */
sound/soc/samsung/smdk2443_wm9710.c +1 -0
@@ -33,6 +33,7 @@ static struct snd_soc_card smdk2443 = { .owner = THIS_MODULE, .dai_link = smdk2443_dai, .num_links = ARRAY_SIZE(smdk2443_dai), + .ac97_ops = &samsung_ac97_ops, };static struct platform_device *smdk2443_snd_ac97_device;
sound/soc/sh/sh7760-ac97.c +1 -0
@@ -31,6 +31,7 @@ static struct snd_soc_card sh7760_ac97_soc_machine = { .owner = THIS_MODULE, .dai_link = &sh7760_ac97_dai, .num_links = 1, + .ac97_ops = &sh_ac97_ops, };static struct platform_device *sh7760_ac97_snd_device;
sound/soc/soc-core.c +3 -4
@@ -2046,8 +2046,7 @@ EXPORT_SYMBOL_GPL(snd_soc_platform_write);* * Initialises AC97 codec resources for use by ad-hoc devices only. */ -int snd_soc_new_ac97_codec (struct snd_soc_codec *codec, -struct snd_ac97_bus_ops *ops,int num) +int snd_soc_new_ac97_codec (struct snd_soc_codec *codec) {mutex_lock (&codec->mutex);
@@ -2065,8 +2064,8 @@ int snd_soc_new_ac97_codec(struct snd_soc_codec *codec,return -ENOMEM ; } - codec->ac97->bus->ops = ops; - codec->ac97->num = num; + codec->ac97->bus->ops = codec->card->ac97_ops; + codec->ac97->num =0 ;/* * Mark the AC97 device to be created by us. This way we ensure that the
sound/soc/tegra/tegra20_ac97.c +2 -2
@@ -142,13 +142,13 @@ static void tegra20_ac97_codec_write(struct snd_ac97 *ac97_snd, }while (!time_after (jiffies, timeout)); } -struct snd_ac97_bus_ops soc_ac97_ops = { +struct snd_ac97_bus_ops tegra20_ac97_ops = { .read = tegra20_ac97_codec_read, .write = tegra20_ac97_codec_write, .reset = tegra20_ac97_codec_reset, .warm_reset = tegra20_ac97_codec_warm_reset, }; -EXPORT_SYMBOL_GPL (soc_ac97_ops); +EXPORT_SYMBOL_GPL (tegra20_ac97_ops);static inline void tegra20_ac97_start_playback (struct tegra20_ac97 *ac97) {
sound/soc/tegra/tegra20_ac97.h +3 -0
@@ -92,4 +92,7 @@ struct tegra20_ac97 {int sync_gpio; struct tegra_asoc_utils_data util_data; }; + +extern struct snd_ac97_bus_ops tegra_ac97_ops; +#endif /* __TEGRA20_AC97_H__ */
sound/soc/txx9/txx9aclc-generic.c +1 -0
@@ -35,6 +35,7 @@ static struct snd_soc_card txx9aclc_generic_card = { .owner = THIS_MODULE, .dai_link = &txx9aclc_generic_dai, .num_links = 1, + .ac97_ops = &txx9_ac97_ops, };static struct platform_device *soc_pdev;
commit 3319b5d42f24524aad47312105355bc7b6ce6ba6
Author: Arnd Bergmann <[email protected]> Date: Mon Apr 22 22:09:38 2013 +0200
ASoC: remove most references to soc_ac97_ops
sound/soc/codecs/ac97.c +2 -2
@@ -62,13 +62,13 @@ static struct snd_soc_dai_driver ac97_dai = {static unsigned int ac97_read (struct snd_soc_codec *codec,unsigned int reg) { -return soc_ac97_ops.read (codec->ac97, reg); +return codec->bus->ops->read (codec->ac97, reg); }static int ac97_write (struct snd_soc_codec *codec,unsigned int reg,unsigned int val) { - soc_ac97_ops.write (codec->ac97, reg, val); + codec->bus->ops->write (codec->ac97, reg, val);return 0 ; }
sound/soc/codecs/ad1980.c +5 -5
@@ -108,7 +108,7 @@ static unsigned int ac97_read(struct snd_soc_codec *codec,case AC97_EXTENDED_STATUS :case AC97_VENDOR_ID1 :case AC97_VENDOR_ID2 : -return soc_ac97_ops.read (codec->ac97, reg); +return codec->ac97->bus->ops->read (codec->ac97, reg);default : reg = reg >>1 ;
@@ -124,7 +124,7 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, {u16 *cache = codec->reg_cache; - soc_ac97_ops.write (codec->ac97, reg, val); + codec->ac97->bus->ops->write (codec->ac97, reg, val); reg = reg >>1 ;if (reg <ARRAY_SIZE (ad1980_reg)) cache[reg] = val;
@@ -154,13 +154,13 @@ static int ad1980_reset(struct snd_soc_codec *codec, int try_warm)u16 retry_cnt =0 ; retry: -if (try_warm && soc_ac97_ops.warm_reset) { - soc_ac97_ops.warm_reset (codec->ac97); +if (try_warm && codec->ac97->bus->ops->warm_reset) { + codec->ac97->bus->ops->warm_reset (codec->ac97);if (ac97_read (codec,AC97_RESET ) ==0x0090 )return 1 ; } - soc_ac97_ops.reset (codec->ac97); + codec->ac97->bus->ops->reset (codec->ac97);/* Set bit 16slot in register 74h, then every slot will has only 16 * bits. This command is sent out in 20bit mode, in which case the * first nibble of data is eaten by the addr. (Tag is always 16 bit)*/
sound/soc/codecs/stac9766.c +10 -10
@@ -145,14 +145,14 @@ static int stac9766_ac97_write(struct snd_soc_codec *codec, unsigned int reg,if (reg >AC97_STAC_PAGE0 ) {stac9766_ac97_write (codec,AC97_INT_PAGING ,0 ); - soc_ac97_ops.write (codec->ac97, reg, val); + codec->ac97->bus->ops->write (codec->ac97, reg, val);stac9766_ac97_write (codec,AC97_INT_PAGING ,1 );return 0 ; }if (reg /2 >=ARRAY_SIZE (stac9766_reg))return -EIO ; - soc_ac97_ops.write (codec->ac97, reg, val); + codec->ac97->bus->ops->write (codec->ac97, reg, val); cache[reg /2 ] = val;return 0 ; }
@@ -164,7 +164,7 @@ static unsigned int stac9766_ac97_read(struct snd_soc_codec *codec,if (reg >AC97_STAC_PAGE0 ) {stac9766_ac97_write (codec,AC97_INT_PAGING ,0 ); - val = soc_ac97_ops.read (codec->ac97, reg -AC97_STAC_PAGE0 ); + val = codec->ac97->bus->ops->read (codec->ac97, reg -AC97_STAC_PAGE0 );stac9766_ac97_write (codec,AC97_INT_PAGING ,1 );return val; }
@@ -175,7 +175,7 @@ static unsigned int stac9766_ac97_read(struct snd_soc_codec *codec, reg == AC97_INT_PAGING || reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2) { - val = soc_ac97_ops.read (codec->ac97, reg); + val = codec->ac97->bus->ops->read (codec->ac97, reg);return val; }return cache[reg /2 ];
@@ -242,15 +242,15 @@ static int stac9766_set_bias_level(struct snd_soc_codec *codec,static int stac9766_reset (struct snd_soc_codec *codec,int try_warm) { -if (try_warm && soc_ac97_ops.warm_reset) { - soc_ac97_ops.warm_reset (codec->ac97); +if (try_warm && codec->ac97->bus->ops->warm_reset) { + codec->ac97->bus->ops->warm_reset (codec->ac97);if (stac9766_ac97_read (codec,0 ) == stac9766_reg[0 ])return 1 ; } - soc_ac97_ops.reset (codec->ac97); -if (soc_ac97_ops.warm_reset) - soc_ac97_ops.warm_reset (codec->ac97); + codec->ac97->bus->ops->reset (codec->ac97); +if (codec->ac97->bus->ops->warm_reset) + codec->ac97->bus->ops->warm_reset (codec->ac97);if (stac9766_ac97_read (codec,0 ) != stac9766_reg[0 ])return -EIO ;return 0 ;
@@ -274,7 +274,7 @@ reset:return -EIO ; } codec->ac97->bus->ops->warm_reset (codec->ac97); - id = soc_ac97_ops.read (codec->ac97,AC97_VENDOR_ID2 ); + id = codec->ac97->bus->ops->read (codec->ac97,AC97_VENDOR_ID2 );if (id !=0x4c13 ) {stac9766_reset (codec,0 ); reset++;
sound/soc/codecs/wm9705.c +6 -6
@@ -209,7 +209,7 @@ static unsigned int ac97_read(struct snd_soc_codec *codec, unsigned int reg)case AC97_RESET :case AC97_VENDOR_ID1 :case AC97_VENDOR_ID2 : -return soc_ac97_ops.read (codec->ac97, reg); +return codec->ac97->bus->ops->read (codec->ac97, reg);default : reg = reg >>1 ;
@@ -225,7 +225,7 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, {u16 *cache = codec->reg_cache; - soc_ac97_ops.write (codec->ac97, reg, val); + codec->ac97->bus->ops->write (codec->ac97, reg, val); reg = reg >>1 ;if (reg < (ARRAY_SIZE (wm9705_reg))) cache[reg] = val;
@@ -294,8 +294,8 @@ static struct snd_soc_dai_driver wm9705_dai[] = {static int wm9705_reset (struct snd_soc_codec *codec) { -if (soc_ac97_ops.reset) { - soc_ac97_ops.reset (codec->ac97); +if (codec->ac97->bus->ops->reset) { + codec->ac97->bus->ops->reset (codec->ac97);if (ac97_read (codec,0 ) == wm9705_reg[0 ])return 0 ;/* Success */ }
@@ -306,7 +306,7 @@ static int wm9705_reset(struct snd_soc_codec *codec)#ifdef CONFIG_PM static int wm9705_soc_suspend (struct snd_soc_codec *codec) { - soc_ac97_ops.write (codec->ac97,AC97_POWERDOWN ,0xffff ); + codec->ac97->bus->ops->write (codec->ac97,AC97_POWERDOWN ,0xffff );return 0 ; }
@@ -323,7 +323,7 @@ static int wm9705_soc_resume(struct snd_soc_codec *codec) }for (i =2 ; i <ARRAY_SIZE (wm9705_reg) <<1 ; i +=2 ) { - soc_ac97_ops.write (codec->ac97, i, cache[i>>1 ]); + codec->ac97->bus->ops->write (codec->ac97, i, cache[i>>1 ]); }return 0 ;
sound/soc/codecs/wm9712.c +8 -8
@@ -455,7 +455,7 @@ static unsigned int ac97_read(struct snd_soc_codec *codec,if (reg ==AC97_RESET || reg ==AC97_GPIO_STATUS || reg ==AC97_VENDOR_ID1 || reg ==AC97_VENDOR_ID2 || reg ==AC97_REC_GAIN ) -return soc_ac97_ops.read (codec->ac97, reg); +return codec->ac97->bus->ops->read (codec->ac97, reg);else { reg = reg >>1 ;
@@ -472,7 +472,7 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,u16 *cache = codec->reg_cache;if (reg <0x7c ) - soc_ac97_ops.write (codec->ac97, reg, val); + codec->ac97->bus->ops->write (codec->ac97, reg, val); reg = reg >>1 ;if (reg < (ARRAY_SIZE (wm9712_reg))) cache[reg] = val;
@@ -581,15 +581,15 @@ static int wm9712_set_bias_level(struct snd_soc_codec *codec,static int wm9712_reset (struct snd_soc_codec *codec,int try_warm) { -if (try_warm && soc_ac97_ops.warm_reset) { - soc_ac97_ops.warm_reset (codec->ac97); +if (try_warm && codec->ac97->bus->ops->warm_reset) { + codec->ac97->bus->ops->warm_reset (codec->ac97);if (ac97_read (codec,0 ) == wm9712_reg[0 ])return 1 ; } - soc_ac97_ops.reset (codec->ac97); -if (soc_ac97_ops.warm_reset) - soc_ac97_ops.warm_reset (codec->ac97); + codec->ac97->bus->ops->reset (codec->ac97); +if (codec->ac97->bus->ops->warm_reset) + codec->ac97->bus->ops->warm_reset (codec->ac97);if (ac97_read (codec,0 ) != wm9712_reg[0 ]) goto err;return 0 ;
@@ -624,7 +624,7 @@ static int wm9712_soc_resume(struct snd_soc_codec *codec)if (i ==AC97_INT_PAGING || i ==AC97_POWERDOWN || (i >0x58 && i !=0x5c ))continue ; - soc_ac97_ops.write (codec->ac97, i, cache[i>>1 ]); + codec->ac97->bus->ops->write (codec->ac97, i, cache[i>>1 ]); } }
sound/soc/codecs/wm9713.c +8 -8
@@ -652,7 +652,7 @@ static unsigned int ac97_read(struct snd_soc_codec *codec,if (reg ==AC97_RESET || reg ==AC97_GPIO_STATUS || reg ==AC97_VENDOR_ID1 || reg ==AC97_VENDOR_ID2 || reg ==AC97_CD ) -return soc_ac97_ops.read (codec->ac97, reg); +return codec->ac97->bus->ops->read (codec->ac97, reg);else { reg = reg >>1 ;
@@ -668,7 +668,7 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, {u16 *cache = codec->reg_cache;if (reg <0x7c ) - soc_ac97_ops.write (codec->ac97, reg, val); + codec->ac97->bus->ops->write (codec->ac97, reg, val); reg = reg >>1 ;if (reg < (ARRAY_SIZE (wm9713_reg))) cache[reg] = val;
@@ -1095,15 +1095,15 @@ static struct snd_soc_dai_driver wm9713_dai[] = {int wm9713_reset (struct snd_soc_codec *codec,int try_warm) { -if (try_warm && soc_ac97_ops.warm_reset) { - soc_ac97_ops.warm_reset (codec->ac97); +if (try_warm && codec->ac97->bus->ops->warm_reset) { + codec->ac97->bus->ops->warm_reset (codec->ac97);if (ac97_read (codec,0 ) == wm9713_reg[0 ])return 1 ; } - soc_ac97_ops.reset (codec->ac97); -if (soc_ac97_ops.warm_reset) - soc_ac97_ops.warm_reset (codec->ac97); + codec->ac97->bus->ops->reset (codec->ac97); +if (codec->ac97->bus->ops->warm_reset) + codec->ac97->bus->ops->warm_reset (codec->ac97);if (ac97_read (codec,0 ) != wm9713_reg[0 ])return -EIO ;return 0 ;
@@ -1180,7 +1180,7 @@ static int wm9713_soc_resume(struct snd_soc_codec *codec)if (i ==AC97_POWERDOWN || i ==AC97_EXTENDED_MID || i ==AC97_EXTENDED_MSTATUS || i >0x66 )continue ; - soc_ac97_ops.write (codec->ac97, i, cache[i>>1 ]); + codec->ac97->bus->ops->write (codec->ac97, i, cache[i>>1 ]); } }
Mark Brown
maintainerQuoted 3 lines · Arnd Bergmann
The idea is to turn the ac97 ops into a pointer that is passed around the structures that actually use it. See below for how far I got with this.
We already have a perfectly good way of doing this called a bus - if we get this working properly we may as well just get the bus thing working properly.
Quoted 10 lines · Mark Brown
From: Mark Brown <[email protected]>
Currently we can only have a single platform built in with AC'97 support due to the use of a global variable to provide the bus operations. Fix this by making that variable a pointer and having the bus drivers set the operations prior to registering.
This is not a particularly good or nice approach but it avoids blocking multiplatform and a real fix involves fixing the fairly deep problems with AC'97 support - we should be converting it to a real bus.