diff options
Diffstat (limited to 'sound/soc/codecs/wm8728.c')
-rw-r--r-- | sound/soc/codecs/wm8728.c | 294 |
1 files changed, 95 insertions, 199 deletions
diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c index 34be2d2b69ef..ae2292444783 100644 --- a/sound/soc/codecs/wm8728.c +++ b/sound/soc/codecs/wm8728.c @@ -29,8 +29,6 @@ #include "wm8728.h" -struct snd_soc_codec_device soc_codec_dev_wm8728; - /* * We can't read the WM8728 register space so we cache them instead. * Note that the defaults here aren't the physical defaults, we latch @@ -44,6 +42,12 @@ static const u16 wm8728_reg_defaults[] = { 0x100, }; +/* codec private data */ +struct wm8728_priv { + enum snd_soc_control_type control_type; + void *control_data; +}; + static const DECLARE_TLV_DB_SCALE(wm8728_tlv, -12750, 50, 1); static const struct snd_kcontrol_new wm8728_snd_controls[] = { @@ -96,8 +100,7 @@ static int wm8728_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct snd_soc_codec *codec = rtd->codec; u16 dac = snd_soc_read(codec, WM8728_DACCTL); dac &= ~0x18; @@ -210,8 +213,8 @@ static struct snd_soc_dai_ops wm8728_dai_ops = { .set_fmt = wm8728_set_dai_fmt, }; -struct snd_soc_dai wm8728_dai = { - .name = "WM8728", +static struct snd_soc_dai_driver wm8728_dai = { + .name = "wm8728-hifi", .playback = { .stream_name = "Playback", .channels_min = 2, @@ -221,63 +224,32 @@ struct snd_soc_dai wm8728_dai = { }, .ops = &wm8728_dai_ops, }; -EXPORT_SYMBOL_GPL(wm8728_dai); -static int wm8728_suspend(struct platform_device *pdev, pm_message_t state) +static int wm8728_suspend(struct snd_soc_codec *codec, pm_message_t state) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -static int wm8728_resume(struct platform_device *pdev) +static int wm8728_resume(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - wm8728_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; } -/* - * initialise the WM8728 driver - * register the mixer and dsp interfaces with the kernel - */ -static int wm8728_init(struct snd_soc_device *socdev, - enum snd_soc_control_type control) +static int wm8728_probe(struct snd_soc_codec *codec) { - struct snd_soc_codec *codec = socdev->card->codec; - int ret = 0; - - codec->name = "WM8728"; - codec->owner = THIS_MODULE; - codec->set_bias_level = wm8728_set_bias_level; - codec->dai = &wm8728_dai; - codec->num_dai = 1; - codec->bias_level = SND_SOC_BIAS_OFF; - codec->reg_cache_size = ARRAY_SIZE(wm8728_reg_defaults); - codec->reg_cache = kmemdup(wm8728_reg_defaults, - sizeof(wm8728_reg_defaults), - GFP_KERNEL); - if (codec->reg_cache == NULL) - return -ENOMEM; + struct wm8728_priv *wm8728 = snd_soc_codec_get_drvdata(codec); + int ret; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); + codec->control_data = wm8728->control_data; + ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8728->control_type); if (ret < 0) { printk(KERN_ERR "wm8728: failed to configure cache I/O: %d\n", ret); - goto err; - } - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - printk(KERN_ERR "wm8728: failed to create pcms\n"); - goto err; + return ret; } /* power on device */ @@ -288,128 +260,56 @@ static int wm8728_init(struct snd_soc_device *socdev, wm8728_add_widgets(codec); return ret; - -err: - kfree(codec->reg_cache); - return ret; } -static struct snd_soc_device *wm8728_socdev; - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - -/* - * WM8728 2 wire address is determined by GPIO5 - * state during powerup. - * low = 0x1a - * high = 0x1b - */ - -static int wm8728_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +static int wm8728_remove(struct snd_soc_codec *codec) { - struct snd_soc_device *socdev = wm8728_socdev; - struct snd_soc_codec *codec = socdev->card->codec; - int ret; - - i2c_set_clientdata(i2c, codec); - codec->control_data = i2c; - - ret = wm8728_init(socdev, SND_SOC_I2C); - if (ret < 0) - pr_err("failed to initialise WM8728\n"); - - return ret; -} - -static int wm8728_i2c_remove(struct i2c_client *client) -{ - struct snd_soc_codec *codec = i2c_get_clientdata(client); - kfree(codec->reg_cache); + wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } -static const struct i2c_device_id wm8728_i2c_id[] = { - { "wm8728", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8728_i2c_id); - -static struct i2c_driver wm8728_i2c_driver = { - .driver = { - .name = "WM8728 I2C Codec", - .owner = THIS_MODULE, - }, - .probe = wm8728_i2c_probe, - .remove = wm8728_i2c_remove, - .id_table = wm8728_i2c_id, +static struct snd_soc_codec_driver soc_codec_dev_wm8728 = { + .probe = wm8728_probe, + .remove = wm8728_remove, + .suspend = wm8728_suspend, + .resume = wm8728_resume, + .set_bias_level = wm8728_set_bias_level, + .reg_cache_size = sizeof(wm8728_reg_defaults), + .reg_word_size = sizeof(u16), + .reg_cache_default = wm8728_reg_defaults, }; -static int wm8728_add_i2c_device(struct platform_device *pdev, - const struct wm8728_setup_data *setup) -{ - struct i2c_board_info info; - struct i2c_adapter *adapter; - struct i2c_client *client; - int ret; - - ret = i2c_add_driver(&wm8728_i2c_driver); - if (ret != 0) { - dev_err(&pdev->dev, "can't add i2c driver\n"); - return ret; - } - - memset(&info, 0, sizeof(struct i2c_board_info)); - info.addr = setup->i2c_address; - strlcpy(info.type, "wm8728", I2C_NAME_SIZE); - - adapter = i2c_get_adapter(setup->i2c_bus); - if (!adapter) { - dev_err(&pdev->dev, "can't get i2c adapter %d\n", - setup->i2c_bus); - goto err_driver; - } - - client = i2c_new_device(adapter, &info); - i2c_put_adapter(adapter); - if (!client) { - dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", - (unsigned int)info.addr); - goto err_driver; - } - - return 0; - -err_driver: - i2c_del_driver(&wm8728_i2c_driver); - return -ENODEV; -} -#endif - #if defined(CONFIG_SPI_MASTER) static int __devinit wm8728_spi_probe(struct spi_device *spi) { - struct snd_soc_device *socdev = wm8728_socdev; - struct snd_soc_codec *codec = socdev->card->codec; + struct wm8728_priv *wm8728; int ret; - codec->control_data = spi; + wm8728 = kzalloc(sizeof(struct wm8728_priv), GFP_KERNEL); + if (wm8728 == NULL) + return -ENOMEM; - ret = wm8728_init(socdev, SND_SOC_SPI); - if (ret < 0) - dev_err(&spi->dev, "failed to initialise WM8728\n"); + wm8728->control_data = spi; + wm8728->control_type = SND_SOC_SPI; + spi_set_drvdata(spi, wm8728); + ret = snd_soc_register_codec(&spi->dev, + &soc_codec_dev_wm8728, &wm8728_dai, 1); + if (ret < 0) + kfree(wm8728); return ret; } static int __devexit wm8728_spi_remove(struct spi_device *spi) { + snd_soc_unregister_codec(&spi->dev); + kfree(spi_get_drvdata(spi)); return 0; } static struct spi_driver wm8728_spi_driver = { .driver = { - .name = "wm8728", + .name = "wm8728-codec", .bus = &spi_bus_type, .owner = THIS_MODULE, }, @@ -418,85 +318,81 @@ static struct spi_driver wm8728_spi_driver = { }; #endif /* CONFIG_SPI_MASTER */ -static int wm8728_probe(struct platform_device *pdev) +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) +static __devinit int wm8728_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct wm8728_setup_data *setup; - struct snd_soc_codec *codec; - int ret = 0; + struct wm8728_priv *wm8728; + int ret; - setup = socdev->codec_data; - codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); - if (codec == NULL) + wm8728 = kzalloc(sizeof(struct wm8728_priv), GFP_KERNEL); + if (wm8728 == NULL) return -ENOMEM; - socdev->card->codec = codec; - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); + i2c_set_clientdata(i2c, wm8728); + wm8728->control_data = i2c; + wm8728->control_type = SND_SOC_I2C; + + ret = snd_soc_register_codec(&i2c->dev, + &soc_codec_dev_wm8728, &wm8728_dai, 1); + if (ret < 0) + kfree(wm8728); + return ret; +} + +static __devexit int wm8728_i2c_remove(struct i2c_client *client) +{ + snd_soc_unregister_codec(&client->dev); + kfree(i2c_get_clientdata(client)); + return 0; +} - wm8728_socdev = socdev; - ret = -ENODEV; +static const struct i2c_device_id wm8728_i2c_id[] = { + { "wm8728", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, wm8728_i2c_id); + +static struct i2c_driver wm8728_i2c_driver = { + .driver = { + .name = "wm8728-codec", + .owner = THIS_MODULE, + }, + .probe = wm8728_i2c_probe, + .remove = __devexit_p(wm8728_i2c_remove), + .id_table = wm8728_i2c_id, +}; +#endif +static int __init wm8728_modinit(void) +{ + int ret = 0; #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - if (setup->i2c_address) { - ret = wm8728_add_i2c_device(pdev, setup); + ret = i2c_add_driver(&wm8728_i2c_driver); + if (ret != 0) { + printk(KERN_ERR "Failed to register wm8728 I2C driver: %d\n", + ret); } #endif #if defined(CONFIG_SPI_MASTER) - if (setup->spi) { - ret = spi_register_driver(&wm8728_spi_driver); - if (ret != 0) - printk(KERN_ERR "can't add spi driver"); + ret = spi_register_driver(&wm8728_spi_driver); + if (ret != 0) { + printk(KERN_ERR "Failed to register wm8728 SPI driver: %d\n", + ret); } #endif - - if (ret != 0) - kfree(codec); - return ret; } +module_init(wm8728_modinit); -/* power down chip */ -static int wm8728_remove(struct platform_device *pdev) +static void __exit wm8728_exit(void) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - - if (codec->control_data) - wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_unregister_device(codec->control_data); i2c_del_driver(&wm8728_i2c_driver); #endif #if defined(CONFIG_SPI_MASTER) spi_unregister_driver(&wm8728_spi_driver); #endif - kfree(codec); - - return 0; -} - -struct snd_soc_codec_device soc_codec_dev_wm8728 = { - .probe = wm8728_probe, - .remove = wm8728_remove, - .suspend = wm8728_suspend, - .resume = wm8728_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8728); - -static int __init wm8728_modinit(void) -{ - return snd_soc_register_dai(&wm8728_dai); -} -module_init(wm8728_modinit); - -static void __exit wm8728_exit(void) -{ - snd_soc_unregister_dai(&wm8728_dai); } module_exit(wm8728_exit); |