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

原文地址:https://www.cnblogs.com/fellow1988/p/12539356.html