zoukankan      html  css  js  c++  java
  • ALSA driver---Asoc Machine/platform/Codec register flow

    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);

  • 相关阅读:
    jquery层级选择器学习笔记
    html 大于号 小于号 空格显示
    MySql存储过程二---变量
    MySql 存储过程一--基本语法及参数介绍
    MySql delimiter
    MySql 关联查询
    MySql 数据库导入导出
    markdown 换行
    WPF 之 MVVM
    对memtester源码分析
  • 原文地址:https://www.cnblogs.com/fellow1988/p/12539356.html
Copyright © 2011-2022 走看看