Machine(sound/soc/pxa/corgi.c):
/* corgi digital audio interface glue - connects codec <--> CPU */ static struct snd_soc_dai_link corgi_dai = { .name = "WM8731", .stream_name = "WM8731", .cpu_dai_name = "pxa2xx-i2s", .codec_dai_name = "wm8731-hifi", .platform_name = "pxa-pcm-audio", .codec_name = "wm8731.0-001b", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, .ops = &corgi_ops, }; /* corgi audio machine driver */ static struct snd_soc_card corgi = { .name = "Corgi", .owner = THIS_MODULE, .dai_link = &corgi_dai, .num_links = 1, .controls = wm8731_corgi_controls, .num_controls = ARRAY_SIZE(wm8731_corgi_controls), .dapm_widgets = wm8731_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(wm8731_dapm_widgets), .dapm_routes = corgi_audio_map, .num_dapm_routes = ARRAY_SIZE(corgi_audio_map), .fully_routed = true, }; static int corgi_probe(struct platform_device *pdev) { struct snd_soc_card *card = &corgi; int ret; card->dev = &pdev->dev; ret = devm_snd_soc_register_card(&pdev->dev, card); if (ret) dev_err(&pdev->dev, "snd_soc_register_card() failed: %d ", ret); return ret; } static struct platform_driver corgi_driver = { .driver = { .name = "corgi-audio", .pm = &snd_soc_pm_ops, }, .probe = corgi_probe, }; module_platform_driver(corgi_driver);
Platform(sound/soc/pxa/pxa2xx-pcm.c):
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, .prepare = __pxa2xx_pcm_prepare, .trigger = pxa2xx_pcm_trigger, .pointer = pxa2xx_pcm_pointer, .mmap = pxa2xx_pcm_mmap, }; static struct snd_soc_platform_driver pxa2xx_soc_platform = { .ops = &pxa2xx_pcm_ops, .pcm_new = pxa2xx_soc_pcm_new, .pcm_free = pxa2xx_pcm_free_dma_buffers, }; static int pxa2xx_soc_platform_probe(struct platform_device *pdev) { return devm_snd_soc_register_platform(&pdev->dev, &pxa2xx_soc_platform); } #ifdef CONFIG_OF static const struct of_device_id snd_soc_pxa_audio_match[] = { { .compatible = "mrvl,pxa-pcm-audio" }, { } }; MODULE_DEVICE_TABLE(of, snd_soc_pxa_audio_match); #endif static struct platform_driver pxa_pcm_driver = { .driver = { .name = "pxa-pcm-audio", .of_match_table = of_match_ptr(snd_soc_pxa_audio_match), }, .probe = pxa2xx_soc_platform_probe, }; module_platform_driver(pxa_pcm_driver);
dai_driver(sound/soc/pxa/pxa2xx-i2s.c):
cpu_dai_driver:
static const struct snd_soc_dai_ops pxa_i2s_dai_ops = { .startup = pxa2xx_i2s_startup, .shutdown = pxa2xx_i2s_shutdown, .trigger = pxa2xx_i2s_trigger, .hw_params = pxa2xx_i2s_hw_params, .set_fmt = pxa2xx_i2s_set_dai_fmt, .set_sysclk = pxa2xx_i2s_set_dai_sysclk, }; static struct snd_soc_dai_driver pxa_i2s_dai = { .probe = pxa2xx_i2s_probe, .remove = pxa2xx_i2s_remove, .suspend = pxa2xx_i2s_suspend, .resume = pxa2xx_i2s_resume, .playback = { .channels_min = 2, .channels_max = 2, .rates = PXA2XX_I2S_RATES, .formats = SNDRV_PCM_FMTBIT_S16_LE,}, .capture = { .channels_min = 2, .channels_max = 2, .rates = PXA2XX_I2S_RATES, .formats = SNDRV_PCM_FMTBIT_S16_LE,}, .ops = &pxa_i2s_dai_ops, .symmetric_rates = 1, }; static const struct snd_soc_component_driver pxa_i2s_component = { .name = "pxa-i2s", }; static int pxa2xx_i2s_drv_probe(struct platform_device *pdev) { return devm_snd_soc_register_component(&pdev->dev, &pxa_i2s_component, &pxa_i2s_dai, 1); } static struct platform_driver pxa2xx_i2s_driver = { .probe = pxa2xx_i2s_drv_probe, .driver = { .name = "pxa2xx-i2s", }, }; static int __init pxa2xx_i2s_init(void) { clk_i2s = ERR_PTR(-ENOENT); return platform_driver_register(&pxa2xx_i2s_driver); } static void __exit pxa2xx_i2s_exit(void) { platform_driver_unregister(&pxa2xx_i2s_driver); } module_init(pxa2xx_i2s_init); module_exit(pxa2xx_i2s_exit);
Codec(sound/soc/codecs/wm8731.c):
codec_dai driver
static const struct snd_soc_dai_ops wm8731_dai_ops = { .startup = wm8731_startup, .hw_params = wm8731_hw_params, .digital_mute = wm8731_mute, .set_sysclk = wm8731_set_dai_sysclk, .set_fmt = wm8731_set_dai_fmt, }; static struct snd_soc_dai_driver wm8731_dai = { .name = "wm8731-hifi", .playback = { .stream_name = "Playback", .channels_min = 1, .channels_max = 2, .rates = WM8731_RATES, .formats = WM8731_FORMATS,}, .capture = { .stream_name = "Capture", .channels_min = 1, .channels_max = 2, .rates = WM8731_RATES, .formats = WM8731_FORMATS,}, .ops = &wm8731_dai_ops, .symmetric_rates = 1, }; static int wm8731_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct wm8731_priv *wm8731; int ret; wm8731 = devm_kzalloc(&i2c->dev, sizeof(struct wm8731_priv), GFP_KERNEL); if (wm8731 == NULL) return -ENOMEM; wm8731->mclk = devm_clk_get(&i2c->dev, "mclk"); if (IS_ERR(wm8731->mclk)) { ret = PTR_ERR(wm8731->mclk); if (ret == -ENOENT) { wm8731->mclk = NULL; dev_warn(&i2c->dev, "Assuming static MCLK "); } else { dev_err(&i2c->dev, "Failed to get MCLK: %d ", ret); return ret; } } mutex_init(&wm8731->lock); i2c_set_clientdata(i2c, wm8731); ret = wm8731_request_supplies(&i2c->dev, wm8731); if (ret != 0) return ret; wm8731->regmap = devm_regmap_init_i2c(i2c, &wm8731_regmap); if (IS_ERR(wm8731->regmap)) { ret = PTR_ERR(wm8731->regmap); dev_err(&i2c->dev, "Failed to allocate register map: %d ", ret); return ret; } ret = wm8731_hw_init(&i2c->dev, wm8731); if (ret != 0) return ret; ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8731, &wm8731_dai, 1); if (ret != 0) { dev_err(&i2c->dev, "Failed to register CODEC: %d ", ret); return ret; } return 0; } static int wm8731_i2c_remove(struct i2c_client *client) { snd_soc_unregister_codec(&client->dev); return 0; } static const struct i2c_device_id wm8731_i2c_id[] = { { "wm8731", 0 }, { } }; MODULE_DEVICE_TABLE(i2c, wm8731_i2c_id); static struct i2c_driver wm8731_i2c_driver = { .driver = { .name = "wm8731", .of_match_table = wm8731_of_match, }, .probe = wm8731_i2c_probe, .remove = wm8731_i2c_remove, .id_table = wm8731_i2c_id, }; #endif static int __init wm8731_modinit(void) { int ret = 0; #if IS_ENABLED(CONFIG_I2C) ret = i2c_add_driver(&wm8731_i2c_driver); if (ret != 0) { printk(KERN_ERR "Failed to register WM8731 I2C driver: %d ", ret); } #endif #if defined(CONFIG_SPI_MASTER) ret = spi_register_driver(&wm8731_spi_driver); if (ret != 0) { printk(KERN_ERR "Failed to register WM8731 SPI driver: %d ", ret); } #endif return ret; } module_init(wm8731_modinit); static void __exit wm8731_exit(void) { #if IS_ENABLED(CONFIG_I2C) i2c_del_driver(&wm8731_i2c_driver); #endif #if defined(CONFIG_SPI_MASTER) spi_unregister_driver(&wm8731_spi_driver); #endif } module_exit(wm8731_exit);