Loading sound/soc/codecs/wm8711.c +129 −168 Original line number Diff line number Diff line Loading @@ -28,11 +28,12 @@ #include "wm8711.h" #define AUDIO_NAME "wm8711" #define WM8711_VERSION "0.3" static struct snd_soc_codec *wm8711_codec; /* codec private data */ struct wm8711_priv { struct snd_soc_codec codec; u16 reg_cache[WM8711_CACHEREGNUM]; unsigned int sysclk; }; Loading Loading @@ -442,241 +443,201 @@ static int wm8711_resume(struct platform_device *pdev) return 0; } /* * initialise the WM8711 driver * register the mixer and dsp interfaces with the kernel */ static int wm8711_init(struct snd_soc_device *socdev) static int wm8711_probe(struct platform_device *pdev) { struct snd_soc_codec *codec = socdev->card->codec; int reg, ret = 0; codec->name = "WM8711"; codec->owner = THIS_MODULE; codec->read = wm8711_read_reg_cache; codec->write = wm8711_write; codec->set_bias_level = wm8711_set_bias_level; codec->dai = &wm8711_dai; codec->num_dai = 1; codec->reg_cache_size = ARRAY_SIZE(wm8711_reg); codec->reg_cache = kmemdup(wm8711_reg, sizeof(wm8711_reg), GFP_KERNEL); struct snd_soc_device *socdev = platform_get_drvdata(pdev); struct snd_soc_codec *codec; int ret = 0; if (codec->reg_cache == NULL) return -ENOMEM; if (wm8711_codec == NULL) { dev_err(&pdev->dev, "Codec device not registered\n"); return -ENODEV; } wm8711_reset(codec); socdev->card->codec = wm8711_codec; codec = wm8711_codec; /* register pcms */ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); if (ret < 0) { printk(KERN_ERR "wm8711: failed to create pcms\n"); dev_err(codec->dev, "failed to create pcms: %d\n", ret); goto pcm_err; } /* power on device */ wm8711_set_bias_level(codec, SND_SOC_BIAS_STANDBY); /* set the update bits */ reg = wm8711_read_reg_cache(codec, WM8711_LOUT1V); wm8711_write(codec, WM8711_LOUT1V, reg | 0x0100); reg = wm8711_read_reg_cache(codec, WM8711_ROUT1V); wm8711_write(codec, WM8711_ROUT1V, reg | 0x0100); wm8711_add_controls(codec); snd_soc_add_controls(codec, wm8711_snd_controls, ARRAY_SIZE(wm8711_snd_controls)); wm8711_add_widgets(codec); ret = snd_soc_init_card(socdev); if (ret < 0) { printk(KERN_ERR "wm8711: failed to register card\n"); dev_err(codec->dev, "failed to register card: %d\n", ret); goto card_err; } return ret; card_err: snd_soc_free_pcms(socdev); snd_soc_dapm_free(socdev); pcm_err: kfree(codec->reg_cache); return ret; } static struct snd_soc_device *wm8711_socdev; #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) /* * WM8711 2 wire address is determined by GPIO5 * state during powerup. * low = 0x1a * high = 0x1b */ #define I2C_DRIVERID_WM8711 0xfefe /* liam - need a proper id */ static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END }; /* power down chip */ static int wm8711_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); /* Magic definition of all other variables and things */ I2C_CLIENT_INSMOD; snd_soc_free_pcms(socdev); snd_soc_dapm_free(socdev); static struct i2c_driver wm8711_i2c_driver; static struct i2c_client client_template; return 0; } /* If the i2c layer weren't so broken, we could pass this kind of data around */ struct snd_soc_codec_device soc_codec_dev_wm8711 = { .probe = wm8711_probe, .remove = wm8711_remove, .suspend = wm8711_suspend, .resume = wm8711_resume, }; EXPORT_SYMBOL_GPL(soc_codec_dev_wm8711); static int wm8711_codec_probe(struct i2c_adapter *adap, int addr, int kind) static int wm8711_register(struct wm8711_priv *wm8711) { struct snd_soc_device *socdev = wm8711_socdev; struct wm8711_setup_data *setup = socdev->codec_data; struct snd_soc_codec *codec = socdev->card->codec; struct i2c_client *i2c; int ret; struct snd_soc_codec *codec = &wm8711->codec; u16 reg; if (addr != setup->i2c_address) return -ENODEV; client_template.adapter = adap; client_template.addr = addr; i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL); if (i2c == NULL) { kfree(codec); return -ENOMEM; if (wm8711_codec) { dev_err(codec->dev, "Another WM8711 is registered\n"); return -EINVAL; } i2c_set_clientdata(i2c, codec); mutex_init(&codec->mutex); INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_paths); codec->control_data = i2c; codec->private_data = wm8711; codec->name = "WM8711"; codec->owner = THIS_MODULE; codec->read = wm8711_read_reg_cache; codec->write = wm8711_write; codec->bias_level = SND_SOC_BIAS_OFF; codec->set_bias_level = wm8711_set_bias_level; codec->dai = &wm8711_dai; codec->num_dai = 1; codec->reg_cache_size = WM8711_CACHEREGNUM; codec->reg_cache = &wm8711->reg_cache; ret = i2c_attach_client(i2c); if (ret < 0) { pr_err("failed to attach codec at addr %x\n", addr); goto err; } memcpy(codec->reg_cache, wm8711_reg, sizeof(wm8711_reg)); ret = wm8711_init(socdev); ret = wm8711_reset(codec); if (ret < 0) { pr_err("failed to initialise WM8711\n"); goto err; } dev_err(codec->dev, "Failed to issue reset\n"); return ret; } wm8711_dai.dev = codec->dev; wm8711_set_bias_level(codec, SND_SOC_BIAS_STANDBY); /* Latch the update bits */ reg = wm8711_read_reg_cache(codec, WM8711_LOUT1V); wm8711_write(codec, WM8711_LOUT1V, reg | 0x0100); reg = wm8711_read_reg_cache(codec, WM8711_ROUT1V); wm8711_write(codec, WM8711_ROUT1V, reg | 0x0100); wm8711_codec = codec; err: kfree(codec); kfree(i2c); ret = snd_soc_register_codec(codec); if (ret != 0) { dev_err(codec->dev, "Failed to register codec: %d\n", ret); return ret; } static int wm8711_i2c_detach(struct i2c_client *client) { struct snd_soc_codec *codec = i2c_get_clientdata(client); ret = snd_soc_register_dai(&wm8711_dai); if (ret != 0) { dev_err(codec->dev, "Failed to register DAI: %d\n", ret); snd_soc_unregister_codec(codec); return ret; } i2c_detach_client(client); kfree(codec->reg_cache); kfree(client); return 0; } static int wm8711_i2c_attach(struct i2c_adapter *adap) static void wm8711_unregister(struct wm8711_priv *wm8711) { return i2c_probe(adap, &addr_data, wm8711_codec_probe); wm8711_set_bias_level(&wm8711->codec, SND_SOC_BIAS_OFF); snd_soc_unregister_dai(&wm8711_dai); snd_soc_unregister_codec(&wm8711->codec); kfree(wm8711); wm8711_codec = NULL; } /* corgi i2c codec control layer */ static struct i2c_driver wm8711_i2c_driver = { .driver = { .name = "WM8711 I2C Codec", .owner = THIS_MODULE, }, .id = I2C_DRIVERID_WM8711, .attach_adapter = wm8711_i2c_attach, .detach_client = wm8711_i2c_detach, .command = NULL, }; static struct i2c_client client_template = { .name = "WM8711", .driver = &wm8711_i2c_driver, }; #endif static int wm8711_probe(struct platform_device *pdev) #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) static __devinit int wm8711_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); struct wm8711_setup_data *setup; struct snd_soc_codec *codec; struct wm8711_priv *wm8711; int ret = 0; pr_info("WM8711 Audio Codec %s", WM8711_VERSION); setup = socdev->codec_data; codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); if (codec == NULL) return -ENOMEM; struct snd_soc_codec *codec; wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL); if (wm8711 == NULL) { kfree(codec); if (wm8711 == NULL) return -ENOMEM; } codec->private_data = wm8711; socdev->card->codec = codec; mutex_init(&codec->mutex); INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_paths); wm8711_socdev = socdev; #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) if (setup->i2c_address) { normal_i2c[0] = setup->i2c_address; codec = &wm8711->codec; codec->hw_write = (hw_write_t)i2c_master_send; ret = i2c_add_driver(&wm8711_i2c_driver); if (ret != 0) printk(KERN_ERR "can't add i2c driver"); } #else /* Add other interfaces here */ #endif return ret; } /* power down chip */ static int wm8711_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); struct snd_soc_codec *codec = socdev->card->codec; i2c_set_clientdata(i2c, wm8711); codec->control_data = i2c; if (codec->control_data) wm8711_set_bias_level(codec, SND_SOC_BIAS_OFF); codec->dev = &i2c->dev; snd_soc_free_pcms(socdev); snd_soc_dapm_free(socdev); #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) i2c_del_driver(&wm8711_i2c_driver); #endif kfree(codec->private_data); kfree(codec); return wm8711_register(wm8711); } static __devexit int wm8711_i2c_remove(struct i2c_client *client) { struct wm8711_priv *wm8711 = i2c_get_clientdata(client); wm8711_unregister(wm8711); return 0; } struct snd_soc_codec_device soc_codec_dev_wm8711 = { .probe = wm8711_probe, .remove = wm8711_remove, .suspend = wm8711_suspend, .resume = wm8711_resume, static const struct i2c_device_id wm8711_i2c_id[] = { { "wm8711", 0 }, { } }; EXPORT_SYMBOL_GPL(soc_codec_dev_wm8711); MODULE_DEVICE_TABLE(i2c, wm8711_i2c_id); static struct i2c_driver wm8711_i2c_driver = { .driver = { .name = "WM8711 I2C Codec", .owner = THIS_MODULE, }, .probe = wm8711_i2c_probe, .remove = __devexit_p(wm8711_i2c_remove), .id_table = wm8711_i2c_id, }; #endif static int __init wm8711_modinit(void) { return snd_soc_register_dai(&wm8711_dai); int ret; #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) ret = i2c_add_driver(&wm8711_i2c_driver); if (ret != 0) { printk(KERN_ERR "Failed to register WM8711 I2C driver: %d\n", ret); } #endif return 0; } module_init(wm8711_modinit); static void __exit wm8711_exit(void) { snd_soc_unregister_dai(&wm8711_dai); #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) i2c_del_driver(&wm8711_i2c_driver); #endif } module_exit(wm8711_exit); Loading Loading
sound/soc/codecs/wm8711.c +129 −168 Original line number Diff line number Diff line Loading @@ -28,11 +28,12 @@ #include "wm8711.h" #define AUDIO_NAME "wm8711" #define WM8711_VERSION "0.3" static struct snd_soc_codec *wm8711_codec; /* codec private data */ struct wm8711_priv { struct snd_soc_codec codec; u16 reg_cache[WM8711_CACHEREGNUM]; unsigned int sysclk; }; Loading Loading @@ -442,241 +443,201 @@ static int wm8711_resume(struct platform_device *pdev) return 0; } /* * initialise the WM8711 driver * register the mixer and dsp interfaces with the kernel */ static int wm8711_init(struct snd_soc_device *socdev) static int wm8711_probe(struct platform_device *pdev) { struct snd_soc_codec *codec = socdev->card->codec; int reg, ret = 0; codec->name = "WM8711"; codec->owner = THIS_MODULE; codec->read = wm8711_read_reg_cache; codec->write = wm8711_write; codec->set_bias_level = wm8711_set_bias_level; codec->dai = &wm8711_dai; codec->num_dai = 1; codec->reg_cache_size = ARRAY_SIZE(wm8711_reg); codec->reg_cache = kmemdup(wm8711_reg, sizeof(wm8711_reg), GFP_KERNEL); struct snd_soc_device *socdev = platform_get_drvdata(pdev); struct snd_soc_codec *codec; int ret = 0; if (codec->reg_cache == NULL) return -ENOMEM; if (wm8711_codec == NULL) { dev_err(&pdev->dev, "Codec device not registered\n"); return -ENODEV; } wm8711_reset(codec); socdev->card->codec = wm8711_codec; codec = wm8711_codec; /* register pcms */ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); if (ret < 0) { printk(KERN_ERR "wm8711: failed to create pcms\n"); dev_err(codec->dev, "failed to create pcms: %d\n", ret); goto pcm_err; } /* power on device */ wm8711_set_bias_level(codec, SND_SOC_BIAS_STANDBY); /* set the update bits */ reg = wm8711_read_reg_cache(codec, WM8711_LOUT1V); wm8711_write(codec, WM8711_LOUT1V, reg | 0x0100); reg = wm8711_read_reg_cache(codec, WM8711_ROUT1V); wm8711_write(codec, WM8711_ROUT1V, reg | 0x0100); wm8711_add_controls(codec); snd_soc_add_controls(codec, wm8711_snd_controls, ARRAY_SIZE(wm8711_snd_controls)); wm8711_add_widgets(codec); ret = snd_soc_init_card(socdev); if (ret < 0) { printk(KERN_ERR "wm8711: failed to register card\n"); dev_err(codec->dev, "failed to register card: %d\n", ret); goto card_err; } return ret; card_err: snd_soc_free_pcms(socdev); snd_soc_dapm_free(socdev); pcm_err: kfree(codec->reg_cache); return ret; } static struct snd_soc_device *wm8711_socdev; #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) /* * WM8711 2 wire address is determined by GPIO5 * state during powerup. * low = 0x1a * high = 0x1b */ #define I2C_DRIVERID_WM8711 0xfefe /* liam - need a proper id */ static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END }; /* power down chip */ static int wm8711_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); /* Magic definition of all other variables and things */ I2C_CLIENT_INSMOD; snd_soc_free_pcms(socdev); snd_soc_dapm_free(socdev); static struct i2c_driver wm8711_i2c_driver; static struct i2c_client client_template; return 0; } /* If the i2c layer weren't so broken, we could pass this kind of data around */ struct snd_soc_codec_device soc_codec_dev_wm8711 = { .probe = wm8711_probe, .remove = wm8711_remove, .suspend = wm8711_suspend, .resume = wm8711_resume, }; EXPORT_SYMBOL_GPL(soc_codec_dev_wm8711); static int wm8711_codec_probe(struct i2c_adapter *adap, int addr, int kind) static int wm8711_register(struct wm8711_priv *wm8711) { struct snd_soc_device *socdev = wm8711_socdev; struct wm8711_setup_data *setup = socdev->codec_data; struct snd_soc_codec *codec = socdev->card->codec; struct i2c_client *i2c; int ret; struct snd_soc_codec *codec = &wm8711->codec; u16 reg; if (addr != setup->i2c_address) return -ENODEV; client_template.adapter = adap; client_template.addr = addr; i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL); if (i2c == NULL) { kfree(codec); return -ENOMEM; if (wm8711_codec) { dev_err(codec->dev, "Another WM8711 is registered\n"); return -EINVAL; } i2c_set_clientdata(i2c, codec); mutex_init(&codec->mutex); INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_paths); codec->control_data = i2c; codec->private_data = wm8711; codec->name = "WM8711"; codec->owner = THIS_MODULE; codec->read = wm8711_read_reg_cache; codec->write = wm8711_write; codec->bias_level = SND_SOC_BIAS_OFF; codec->set_bias_level = wm8711_set_bias_level; codec->dai = &wm8711_dai; codec->num_dai = 1; codec->reg_cache_size = WM8711_CACHEREGNUM; codec->reg_cache = &wm8711->reg_cache; ret = i2c_attach_client(i2c); if (ret < 0) { pr_err("failed to attach codec at addr %x\n", addr); goto err; } memcpy(codec->reg_cache, wm8711_reg, sizeof(wm8711_reg)); ret = wm8711_init(socdev); ret = wm8711_reset(codec); if (ret < 0) { pr_err("failed to initialise WM8711\n"); goto err; } dev_err(codec->dev, "Failed to issue reset\n"); return ret; } wm8711_dai.dev = codec->dev; wm8711_set_bias_level(codec, SND_SOC_BIAS_STANDBY); /* Latch the update bits */ reg = wm8711_read_reg_cache(codec, WM8711_LOUT1V); wm8711_write(codec, WM8711_LOUT1V, reg | 0x0100); reg = wm8711_read_reg_cache(codec, WM8711_ROUT1V); wm8711_write(codec, WM8711_ROUT1V, reg | 0x0100); wm8711_codec = codec; err: kfree(codec); kfree(i2c); ret = snd_soc_register_codec(codec); if (ret != 0) { dev_err(codec->dev, "Failed to register codec: %d\n", ret); return ret; } static int wm8711_i2c_detach(struct i2c_client *client) { struct snd_soc_codec *codec = i2c_get_clientdata(client); ret = snd_soc_register_dai(&wm8711_dai); if (ret != 0) { dev_err(codec->dev, "Failed to register DAI: %d\n", ret); snd_soc_unregister_codec(codec); return ret; } i2c_detach_client(client); kfree(codec->reg_cache); kfree(client); return 0; } static int wm8711_i2c_attach(struct i2c_adapter *adap) static void wm8711_unregister(struct wm8711_priv *wm8711) { return i2c_probe(adap, &addr_data, wm8711_codec_probe); wm8711_set_bias_level(&wm8711->codec, SND_SOC_BIAS_OFF); snd_soc_unregister_dai(&wm8711_dai); snd_soc_unregister_codec(&wm8711->codec); kfree(wm8711); wm8711_codec = NULL; } /* corgi i2c codec control layer */ static struct i2c_driver wm8711_i2c_driver = { .driver = { .name = "WM8711 I2C Codec", .owner = THIS_MODULE, }, .id = I2C_DRIVERID_WM8711, .attach_adapter = wm8711_i2c_attach, .detach_client = wm8711_i2c_detach, .command = NULL, }; static struct i2c_client client_template = { .name = "WM8711", .driver = &wm8711_i2c_driver, }; #endif static int wm8711_probe(struct platform_device *pdev) #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) static __devinit int wm8711_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); struct wm8711_setup_data *setup; struct snd_soc_codec *codec; struct wm8711_priv *wm8711; int ret = 0; pr_info("WM8711 Audio Codec %s", WM8711_VERSION); setup = socdev->codec_data; codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); if (codec == NULL) return -ENOMEM; struct snd_soc_codec *codec; wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL); if (wm8711 == NULL) { kfree(codec); if (wm8711 == NULL) return -ENOMEM; } codec->private_data = wm8711; socdev->card->codec = codec; mutex_init(&codec->mutex); INIT_LIST_HEAD(&codec->dapm_widgets); INIT_LIST_HEAD(&codec->dapm_paths); wm8711_socdev = socdev; #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) if (setup->i2c_address) { normal_i2c[0] = setup->i2c_address; codec = &wm8711->codec; codec->hw_write = (hw_write_t)i2c_master_send; ret = i2c_add_driver(&wm8711_i2c_driver); if (ret != 0) printk(KERN_ERR "can't add i2c driver"); } #else /* Add other interfaces here */ #endif return ret; } /* power down chip */ static int wm8711_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); struct snd_soc_codec *codec = socdev->card->codec; i2c_set_clientdata(i2c, wm8711); codec->control_data = i2c; if (codec->control_data) wm8711_set_bias_level(codec, SND_SOC_BIAS_OFF); codec->dev = &i2c->dev; snd_soc_free_pcms(socdev); snd_soc_dapm_free(socdev); #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) i2c_del_driver(&wm8711_i2c_driver); #endif kfree(codec->private_data); kfree(codec); return wm8711_register(wm8711); } static __devexit int wm8711_i2c_remove(struct i2c_client *client) { struct wm8711_priv *wm8711 = i2c_get_clientdata(client); wm8711_unregister(wm8711); return 0; } struct snd_soc_codec_device soc_codec_dev_wm8711 = { .probe = wm8711_probe, .remove = wm8711_remove, .suspend = wm8711_suspend, .resume = wm8711_resume, static const struct i2c_device_id wm8711_i2c_id[] = { { "wm8711", 0 }, { } }; EXPORT_SYMBOL_GPL(soc_codec_dev_wm8711); MODULE_DEVICE_TABLE(i2c, wm8711_i2c_id); static struct i2c_driver wm8711_i2c_driver = { .driver = { .name = "WM8711 I2C Codec", .owner = THIS_MODULE, }, .probe = wm8711_i2c_probe, .remove = __devexit_p(wm8711_i2c_remove), .id_table = wm8711_i2c_id, }; #endif static int __init wm8711_modinit(void) { return snd_soc_register_dai(&wm8711_dai); int ret; #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) ret = i2c_add_driver(&wm8711_i2c_driver); if (ret != 0) { printk(KERN_ERR "Failed to register WM8711 I2C driver: %d\n", ret); } #endif return 0; } module_init(wm8711_modinit); static void __exit wm8711_exit(void) { snd_soc_unregister_dai(&wm8711_dai); #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) i2c_del_driver(&wm8711_i2c_driver); #endif } module_exit(wm8711_exit); Loading