在Linux驅動開發中,成功案例分享對于理解驅動開發的實踐和應用非常有幫助。以下是兩個具體的成功案例:
背景:
I2S(Inter-IC Sound)是一種常見的音頻接口標準,廣泛應用于各種音頻設備中。下面是一個基于Linux的I2S驅動案例分析。
案例描述:
static const struct of_device_id rockchip_i2s_match[] = {
{ .compatible = "rockchip,rk3066-i2s", },
{ .compatible = "rockchip,rk3188-i2s", },
{ .compatible = "rockchip,rk3288-i2s", },
{ .compatible = "rockchip,rk3399-i2s", .data = &rk3399_i2s_pins },
};
MODULE_DEVICE_TABLE(of, rockchip_i2s_match);
static struct platform_driver rockchip_i2s_driver = {
.probe = rockchip_i2s_probe,
.remove = rockchip_i2s_remove,
.driver = {
.name = "rockchip_i2s",
.of_match_table = of_match_ptr(rockchip_i2s_match),
.pm = &rockchip_i2s_pm_ops,
},
};
module_platform_driver(rockchip_i2s_driver);
static int rockchip_i2s_probe(struct platform_device *pdev) {
struct device_node *node = pdev->dev.of_node;
const struct of_device_id *of_id;
struct rk_i2s_dev *i2s;
struct snd_soc_dai_driver *soc_dai;
struct resource *res;
void __iomem *regs;
int ret;
int val;
i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL);
if (!i2s) {
ret = -ENOMEM;
goto err;
}
i2s->dev = &pdev->dev;
ret = clk_prepare_enable(i2s->hclk);
if (ret) {
dev_err(&pdev->dev, "Failed to enable hclk: %d\n", ret);
goto err;
}
i2s->mclk = devm_clk_get(&pdev->dev, "i2s_clk");
if (IS_ERR(i2s->mclk)) {
dev_err(&pdev->dev, "Failed to get mclk: %ld\n", PTR_ERR(i2s->mclk));
goto err;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "Failed to get resource: %d\n", ret);
ret = -ENOMEM;
goto err;
}
regs = devm_platform_get_and_ioremap_resource(pdev, 0, res);
if (!regs) {
dev_err(&pdev->dev, "Failed to map resource: %d\n", ret);
ret = -ENOMEM;
goto err;
}
i2s->regmap = devm_regmap_init_mmio(&pdev->dev, regs, &rockchip_i2s_regmap_config);
if (IS_ERR(i2s->regmap)) {
dev_err(&pdev->dev, "Failed to initialize regmap: %ld\n", PTR_ERR(i2s->regmap));
ret = -ENOMEM;
goto err;
}
i2s->playback_DMA_data.addr = res->start + I2S_TXDR;
i2s->playback_DMA_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
i2s->playback_DMA_data.maxburst = 4;
i2s->capture_DMA_data.addr = res->start + I2S_RXDR;
i2s->capture_DMA_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
i2s->capture_DMA_data.maxburst = 4;
soc_dai = devm_kmemdup(&pdev->dev, &rockchip_i2s_dai, sizeof(*soc_dai), GFP_KERNEL);
if (!soc_dai) {
dev_err(&pdev->dev, "Failed to allocate dai driver: %d\n", ret);
ret = -ENOMEM;
goto err;
}
ret = snd_soc_register_dai(soc_dai);
if (ret) {
dev_err(&pdev->dev, "Failed to register dai: %d\n", ret);
goto err;
}
return 0;
err:
return ret;
}
案例解析:
of_device_id
數組匹配具體的設備型號。snd_soc_register_dai
注冊I2S驅動。背景:
CDC(Communication Device Class)設備在Windows下正常工作,但在Linux下無法正常工作。通過WSL2(Windows Subsystem for Linux 2)可以在Windows下進行Linux內核調試。
案例描述:
#undef DEBUG
#undef VERBOSE_DEBUG
#define DEBUG
#define VERBOSE_DEBUG
make -j$(nproc) KCONFIG_CONFIG=.config && make modules_install -j$(nproc) && make install -j$(nproc)
sudo cp vmlinux /mnt/d/
案例解析:
以上兩個案例展示了Linux驅動開發在不同場景下的具體應用和解決方案。通過這些案例,可以更好地理解和掌握Linux驅動開發的實踐技巧。