提交 2026176f 编写于 作者: V vbox

1.匹配, 生成节点

上级 da4e99a7
KERN_DIR = /home/vbox/workspace/qemu/100ask_imx6ull-qemu/linux-4.9.88
all:
make -C $(KERN_DIR) M=`pwd` modules
clean:
make -C $(KERN_DIR) M=`pwd` modules clean
rm -rf modules.order
obj-m += vplatform.o
obj-m += vcodec.o
obj-m += vmachine.o
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
static int vcodec_probe(struct snd_soc_codec *codec)
{
//int ret;
printk("-----%s----\n",__func__);
return 0;
}
static struct snd_soc_codec_driver soc_vcodec_drv = {
.probe = vcodec_probe,
//.remove = vcodec_remove,
//.read = vcodec_read,
//.write = vcodec_write,
//.ignore_pmdown_time = 1,
};
static struct snd_soc_dai_driver vcodec_dai[] = {
{
.name = "vcodec_dai",
.playback = {
.stream_name = "Playback",
.channels_min = 1,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_192000
| SNDRV_PCM_RATE_KNOT,
.formats = SNDRV_PCM_FMTBIT_S16_LE
| SNDRV_PCM_FMTBIT_S24_LE,
},
.capture = {
.stream_name = "Capture",
.channels_min = 1,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_48000
| SNDRV_PCM_RATE_KNOT,
.formats = SNDRV_PCM_FMTBIT_S16_LE
| SNDRV_PCM_FMTBIT_S24_LE,
},
//.ops = &vcodec_dai_ops,
},
};
static int codec_probe(struct platform_device *pdev) {
int ret = 0;
printk("-----%s----\n",__func__);
ret = snd_soc_register_codec(&pdev->dev, &soc_vcodec_drv,
vcodec_dai, ARRAY_SIZE(vcodec_dai));
if (ret < 0) {
dev_err(&pdev->dev, "register codec failed\n");
return -1;
}
return ret;
}
static int codec_remove(struct platform_device *pdev){
printk("-----%s----\n",__func__);
return 0;
}
static void codec_pdev_release(struct device *dev)
{
}
static struct platform_device codec_pdev = {
.name = "vcodec",
.dev.release = codec_pdev_release,
};
static struct platform_driver codec_pdrv = {
.probe = codec_probe,
.remove = codec_remove,
.driver = {
.name = "vcodec",
},
};
static int __init codec_init(void)
{
int ret;
ret = platform_device_register(&codec_pdev);
if (ret)
return ret;
ret = platform_driver_register(&codec_pdrv);
if (ret)
platform_device_unregister(&codec_pdev);
return ret;
}
static void __exit codec_exit(void)
{
platform_driver_unregister(&codec_pdrv);
platform_device_unregister(&codec_pdev);
}
module_init(codec_init);
module_exit(codec_exit);
MODULE_LICENSE("GPL");
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
//static struct snd_soc_ops my_card_ops = {
// .hw_params = my_card_hw_params,
//};
static struct snd_soc_dai_link my_card_dai_link[] = {
{
.name = "my-codec",
.stream_name = "MY-CODEC",
.codec_name = "vcodec.0",
.codec_dai_name = "vcodec_dai",
.cpu_dai_name = "vplat.0",
.platform_name = "vplat.0",
// .init = my_card_init,
// .ops = &my_card_ops,
},
};
static struct snd_soc_card snd_soc_my_card = {
.name = "my-codec",
.owner = THIS_MODULE,
.dai_link = my_card_dai_link,
.num_links = ARRAY_SIZE(my_card_dai_link),
};
static int vmachine_probe(struct platform_device *pdev) {
int ret = 0;
struct snd_soc_card *card = &snd_soc_my_card;
printk("-----%s----\n",__func__);
/* register the soc card */
card->dev = &pdev->dev;
ret = snd_soc_register_card(card);
if (ret < 0) {
dev_err(&pdev->dev, "snd_soc_register_card failed %d\n", ret);
return -1;
}
return ret;
}
static int vmachine_remove(struct platform_device *pdev){
printk("-----%s----\n",__func__);
return 0;
}
static void vmachine_pdev_release(struct device *dev)
{
}
static struct platform_device vmachine_pdev = {
.name = "vmachine",
.dev.release = vmachine_pdev_release,
};
static struct platform_driver vmachine_pdrv = {
.probe = vmachine_probe,
.remove = vmachine_remove,
.driver = {
.name = "vmachine",
},
};
static int __init vmachine_init(void)
{
int ret;
ret = platform_device_register(&vmachine_pdev);
if (ret)
return ret;
ret = platform_driver_register(&vmachine_pdrv);
if (ret)
platform_device_unregister(&vmachine_pdev);
return ret;
}
static void __exit vmachine_exit(void)
{
platform_driver_unregister(&vmachine_pdrv);
platform_device_unregister(&vmachine_pdev);
}
module_init(vmachine_init);
module_exit(vmachine_exit);
MODULE_LICENSE("GPL");
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
static const struct snd_soc_component_driver plat_cpudai_component = {
.name = "plat-cpudai",
};
static struct snd_soc_dai_driver plat_cpudai_dai = {
.name = "plat-cpudai",
.playback = {
.channels_min = 1,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_192000 |
SNDRV_PCM_RATE_KNOT,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.capture = {
.channels_min = 1,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_48000 |
SNDRV_PCM_RATE_KNOT,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S32_LE,
},
.ops = NULL,
};
static struct snd_soc_platform_driver plat_soc_drv = {
//.ops = &s3c2440_dma_ops,
//.pcm_new = s3c2440_dma_new,
//.pcm_free = s3c2440_dma_free,
};
static int plat_probe(struct platform_device *pdev) {
int ret = 0;
printk("-----%s----\n",__func__);
ret = snd_soc_register_component(&pdev->dev, &plat_cpudai_component,
&plat_cpudai_dai, 1);
if (ret < 0) {
dev_err(&pdev->dev, "Could not register CPU DAI: %d\n", ret);
ret = -EBUSY;
return ret;
}
ret = snd_soc_register_platform(&pdev->dev, &plat_soc_drv);
if (ret < 0) {
dev_err(&pdev->dev, "Could not register platform: %d\n", ret);
ret = -EBUSY;
return ret;
}
return ret;
}
static int plat_remove(struct platform_device *pdev){
printk("-----%s----\n",__func__);
return 0;
}
static void plat_pdev_release(struct device *dev)
{
}
static struct platform_device plat_pdev = {
.name = "vplat",
.dev.release = plat_pdev_release,
};
static struct platform_driver plat_pdrv = {
.probe = plat_probe,
.remove = plat_remove,
.driver = {
.name = "vplat",
},
};
static int __init plat_init(void)
{
int ret;
ret = platform_device_register(&plat_pdev);
if (ret)
return ret;
ret = platform_driver_register(&plat_pdrv);
if (ret)
platform_device_unregister(&plat_pdev);
return ret;
}
static void __exit plat_exit(void)
{
platform_driver_unregister(&plat_pdrv);
platform_device_unregister(&plat_pdev);
}
module_init(plat_init);
module_exit(plat_exit);
MODULE_LICENSE("GPL");
  • 上面的操作只能在作者指定的linux版本,或着低版本,比如Linux 4.4可以运行通过,在linux5.10上不能编译通过,alsa的函数调用已经发生变化,需要重新编写

  • vmachine.c

    #include <linux/init.h> #include <linux/module.h> #include <linux/platform_device.h> #include <sound/pcm.h> #include <sound/pcm_params.h> #include <sound/soc.h>

    static struct snd_soc_dai_link_component cpus = { .name = "vcpus.0", .dai_name = "vcpus.0", };

    static struct snd_soc_dai_link_component codecs = { .name = "vcodec.0", .dai_name = "vcodec.0", };

    static struct snd_soc_dai_link_component platforms = { .name = "vplat.0", .dai_name = "vplat.0", };

    static struct snd_soc_dai_link my_card_dai_link[] = { { .name = "my-codec", .stream_name = "MY-CODEC", .codecs = &codecs, .cpus = &cpus, .platforms = &platforms, // .init = my_card_init, // .ops = &my_card_ops, }, };

    static const struct snd_soc_dapm_widget vmachine_widget[] = { SND_SOC_DAPM_MIC("vMachine mic",NULL), SND_SOC_DAPM_HP("Headphone hp",NULL), };

    static const struct snd_soc_dapm_route snd_proto_route[] = { /*speaker connected to LHPOUT/RHPOUT */ {"Headphone hp",NULL,"LHPOUT"}, {"Headphone hp",NULL,"RHPOUT"},

        /*mic is connected to Mic Jack, with WM8731 Mic Bias*/
        {"MICIN", NULL, "Mic Bias"},
        {"Mic Bias", NULL,"Microphone hp"},

    };

    static struct snd_soc_card snd_soc_my_card = { .name = "my-codec", .owner = THIS_MODULE, .dai_link = my_card_dai_link, .num_links = ARRAY_SIZE(my_card_dai_link), // .dapm_widgets = vmachine_widget, // .num_dapm_widgets=ARRAY_SIZE(vmachine_widget), // .dapm_routes = snd_proto_route, // .num_dapm_routes=ARRAY_SIZE(snd_proto_route), };

    #define SNDRV_DEFAULT_IDX1 (-1) #define SNDRV_DEFAULT_STR1 NULL #define soc_setup_card_name(name,name1,name2,norm)
    __soc_setup_card_name(name, sizeof(name),name1,name2,norm) static int isalnum(int c){ if(c>=0&&c<=9) return 1; if(c>='a'&&c<='z'||c>='A'&&c<='Z') return 1; return 0; } static void __soc_setup_card_name(char *name, int len,const char *name1,const char *name2, int normalization) { int i; snprintf(name, len, "%s", name1?name1:name2); if(!normalization) return;

    /*
     * Name normalization
     *
     * The driver name is somewhat specia, as it's used as a key for
     * searches in the user-space.
     *
     * ex)
     * "abcd??efg"->"abcd__efg"
     */
    for(i = 0;i<len;i++){
       switch (name[i]) {
    	   case '_':
    	   case '-':
    	   case '\0':
    		   break;
    	   default:
    		   if(!isalnum(name[i]))
    			   name[i]='_';
    		   break;
    }}

    }

    static int vmachine_probe(struct platform_device *pdev) { int ret = 0; struct snd_soc_card *card = &snd_soc_my_card; struct snd_soc_component *component; printk("vmachine_probe-----%s----\n",func);

    printk(KERN_ERR "pdev->name=%s\n",pdev->name);
    printk(KERN_ERR "pdev->dev=%p",pdev->dev);
    printk(KERN_ERR "card=%p",card);
    printk(KERN_ERR "card->dev=%p",card->dev);
    /* register the soc card */
    card->dev = &pdev->dev;
        printk(KERN_ERR "++++card->dev=%p",card->dev);
        printk(KERN_ERR "card->widgets=%p",card->widgets);
    
    printk(KERN_ERR "card->paths=%p",card->paths);
    printk(KERN_ERR "card->dapm_list=%p",card->dapm_list);
    printk(KERN_ERR "card->aux_comp_list=%p",card->aux_comp_list);
    printk(KERN_ERR "card->component_dev_list=%p",card->component_dev_list);
    printk(KERN_ERR "card->list=%p",card->list);
    printk(KERN_ERR "card->dapm_dirty=%p",card->dapm_dirty);
    printk(KERN_ERR "card->dobj_list=%p",card->dobj_list);
    printk(KERN_ERR "card->mutex=%p",card->mutex);
    printk(KERN_ERR "card->dapm_mutex=%p",card->dapm_mutex);
    printk(KERN_ERR "card->pcm_mutex=%p",card->pcm_mutex);

    // INIT_LIST_HEAD(&card->dobj_list); if(!card->name || !card->dev) { printk("card->name || !card->dev"); }

        dev_set_drvdata(card->dev,card);
    INIT_LIST_HEAD(&card->widgets);
    INIT_LIST_HEAD(&card->paths);
    INIT_LIST_HEAD(&card->dapm_list);
    INIT_LIST_HEAD(&card->aux_comp_list);
    INIT_LIST_HEAD(&card->component_dev_list);
    INIT_LIST_HEAD(&card->list);
    INIT_LIST_HEAD(&card->rtd_list);
    INIT_LIST_HEAD(&card->dapm_dirty);
    INIT_LIST_HEAD(&card->dobj_list);
    
    card->instantiated = 0;
    mutex_init(&card->mutex);
    mutex_init(&card->dapm_mutex);
    mutex_init(&card->pcm_mutex);
    spin_lock_init(&card->dpcm_lock);
    
    //	ret = devm_snd_soc_register_card(card->dev,card);
    //snd_soc_bind_card(card);
    snd_soc_dapm_init(&card->dapm,card,NULL);
        //soc_check_tplg_fes(card);
    //ret = soc_bind_aux_dev(card);
    
    card->num_rtd=0;
    int i;
    struct snd_soc_dai_link *dai_link;
    for_each_card_prelinks(card,i,dai_link){
    	ret=snd_soc_add_pcm_runtime(card,dai_link);
    	if(ret<0) {
    	    printk(KERN_ERR "snd_soc_add_pcm_runtime failed");
    		return -1;
    	}
    }

    ret=snd_card_new(card->dev,SNDRV_DEFAULT_IDX1,SNDRV_DEFAULT_STR1,card->owner,0,&card->snd_card);

    //soc_init_card_debugfs(card);

    //soc_resumd_init(card);

    //ret = snd_soc_dapm_new_controls(&card->dapm,card->dapm_widgets,card->num_dapm_widgets);

    //ret = snd_soc_dapm_new_controls(&card->dapm,card->of_dapm_widgets,card->num_of_dapm_widgets);

    //ret = snd_soc_card_probe(card);

    //ret = soc_probe_link_components(card);

    //ret = soc_probe_link_dais(card);

    /for_each_card_rtds(card,rtd){ ret=soc_init_pcm_runtime(card,rtd); if(ret<0) goto probe_end; }/

    //snd_soc_dapm_link_dai_widgets(card); //snd_soc_dapm_connect_dai_link_widgets(card);

    ret=snd_soc_dapm_add_routes(&card->dapm,card->dapm_routes,card->num_dapm_routes);

    snd_soc_set_dmi_name(card, NULL); soc_setup_card_name(card->snd_card->shortname, card->name,NULL,0); soc_setup_card_name(card->snd_card->longname,card->long_name,card->name,0); soc_setup_card_name(card->snd_card->driver, card->driver_name,card->name,1);

    if(card->components) { ret = snd_component_add(card->snd_card,card->components);

        if(ret<0){
        goto probe_end;
    }

    }

    //ret = snd_soc_card_late_probe(card);

    snd_soc_dapm_new_widgets(card); ret = snd_card_register(card->snd_card);

    card->instantiated=1; dapm_mark_endpoints_dirty(card); snd_soc_dapm_sync(&card->dapm);

    for_each_card_components(card,component) if(!snd_soc_component_active(component)) // pinctrl_pm_select_sleep_state(component->dev); printk(KERN_ERR,"5.15.0-71-generic");

    probe_end: printk(KERN_ERR "++++++++++++ ret=%d\n",ret); if (ret < 0) { dev_err(&pdev->dev, "snd_soc_register_card failed %d\n", ret); return -1; }

    return ret;

    }

    static int vmachine_remove(struct platform_device *pdev){ printk("-----%s----\n",func);

    return 0;

    }

    /*static void vmachine_pdev_release(struct device dev) { }/

    /static struct platform_device vmachine_pdev = { .name = "vmachine", .dev.release = vmachine_pdev_release, };/

    static struct platform_device *vmachine_pdev;

    static struct platform_driver vmachine_pdrv = { .probe = vmachine_probe, .remove = vmachine_remove, .driver = { .name = "vmachine", }, };

    static int __init vmachine_init(void) { int ret; vmachine_pdev = platform_device_register_simple("vmachine",-1,NULL,0); /if (ret) return ret;/ ret = platform_driver_register(&vmachine_pdrv); if (ret) platform_device_unregister(vmachine_pdev); return ret; }

    static void __exit vmachine_exit(void) { platform_driver_unregister(&vmachine_pdrv); platform_device_unregister(vmachine_pdev); }

    module_init(vmachine_init); module_exit(vmachine_exit); MODULE_LICENSE("GPL");

  • vplatform.c

    #include <linux/init.h> #include <linux/module.h> #include <linux/platform_device.h> #include <sound/pcm.h> #include <sound/pcm_params.h> #include <sound/soc.h>

    static const struct snd_soc_component_driver plat_cpudai_component = { .name = "plat-cpudai", };

    static struct snd_soc_dai_driver plat_cpudai_dai = { .name = "plat-cpudai", .playback = { .channels_min = 1, .channels_max = 2, .rates = SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATE_KNOT, .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, }, .capture = { .channels_min = 1, .channels_max = 2, .rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_KNOT, .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE, }, .ops = NULL, };

    static int plat_probe(struct platform_device *pdev) { int ret = 0;

    printk("vplatform -----%s----\n",__func__);
    
    ret = devm_snd_soc_register_component(&pdev->dev, &plat_cpudai_component,
    				&plat_cpudai_dai, 1);
    if (ret) {
    	dev_err(&pdev->dev, "Could not register CPU DAI: %d\n", ret);
    //	ret = -EBUSY;
    	return ret;
    }

    /* ret = snd_soc_register_platform(&pdev->dev, &plat_soc_drv); if (ret < 0) { dev_err(&pdev->dev, "Could not register platform: %d\n", ret); ret = -EBUSY; return ret; }*/

    // ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL,0); return ret; }

    static int plat_remove(struct platform_device *pdev){ printk("-----%s----\n",func);

    return 0;

    }

    static void plat_pdev_release(struct device *dev) { }

    static struct platform_device plat_pdev = { .name = "vplat", .dev.release = plat_pdev_release, };

    static struct platform_driver plat_pdrv = { .probe = plat_probe, .remove = plat_remove, .driver = { .name = "vplat", }, };

    static int __init plat_init(void) { int ret;

    ret = platform_device_register(&plat_pdev);
    if (ret)
    	return ret;
    
    ret = platform_driver_register(&plat_pdrv);
    if (ret)
    	platform_device_unregister(&plat_pdev);
    
    return ret;

    }

    static void __exit plat_exit(void) { platform_driver_unregister(&plat_pdrv); platform_device_unregister(&plat_pdev); }

    module_init(plat_init); module_exit(plat_exit); MODULE_LICENSE("GPL");

  • vcodec.c

    #include <linux/init.h> #include <linux/module.h> #include <linux/platform_device.h> #include <sound/pcm.h> #include <sound/pcm_params.h> #include <sound/soc.h>

    /*static const struct snd_soc_component_driver soc_component_dev = { .probe = codec_soc_probe }

    static int vcodec_probe(struct platform_device *codec) { //int ret; printk("-----%s----\n",func);

    return 0;

    }

    static struct snd_soc_codec_driver soc_vcodec_drv = { .probe = vcodec_probe, //.remove = vcodec_remove, //.read = vcodec_read, //.write = vcodec_write, //.ignore_pmdown_time = 1, };*/

    static int codec_soc_probe(struct snd_soc_component *component) { printk("-----%s----\n",func); return 0; }

    static struct snd_soc_dai_driver vcodec_dai[] = { { .name = "vcodec_dai", .playback = { .stream_name = "Playback", .channels_min = 1, .channels_max = 2, .rates = SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATE_KNOT, .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, }, .capture = { .stream_name = "Capture", .channels_min = 1, .channels_max = 2, .rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_KNOT, .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, }, //.ops = &vcodec_dai_ops, }, };

    static const struct snd_soc_dapm_widget vcodec_widget[] = { SND_SOC_DAPM_MIC("vCodec mic",NULL), SND_SOC_DAPM_HP("Headphone hp",NULL), };

    static const struct snd_soc_dapm_route snd_proto_route[] = { /*speaker connected to LHPOUT/RHPOUT */ {"Headphone hp",NULL,"LHPOUT"}, {"Headphone hp",NULL,"RHPOUT"},

        /*mic is connected to Mic Jack, with WM8731 Mic Bias*/
        {"MICIN", NULL, "Mic Bias"},
        {"Mic Bias", NULL,"Microphone hp"},

    };

    static const struct snd_soc_component_driver soc_component_dev = { .name = "vcodec_dev", .dapm_widgets = vcodec_widget, .num_dapm_widgets=ARRAY_SIZE(vcodec_widget), .dapm_routes = snd_proto_route, .num_dapm_routes=ARRAY_SIZE(snd_proto_route), };

    /*static int vcodec_probe(struct platform_device *codec) { //int ret; printk("-----%s----\n",func);

        return 0;

    }*/

    static int codec_probe(struct platform_device *pdev) { /*int ret = 0;

    printk("-----%s----\n",__func__);
    
    ret = snd_soc_register_codec(&pdev->dev, &soc_vcodec_drv,
    			vcodec_dai, ARRAY_SIZE(vcodec_dai));
    if (ret < 0) {
    	dev_err(&pdev->dev, "register codec failed\n");
    	return -1;
    }
    
    return ret;*/
    
    struct device *dev = &pdev->dev;
    //struct jz_codec *codec;
    int ret;
    
    //codec = devm_kzalloc(dev, sizeof(*codec), GFP_KERNEL);
    //if (!codec)
    //	return -ENOMEM;
    
    //codec->dev = dev;
    
    //codec->base = devm_platform_ioremap_resource(pdev, 0);

    // if (IS_ERR(codec->base)) { // ret = PTR_ERR(codec->base); // dev_err(dev, "Failed to ioremap mmio memory: %d\n", ret); // return ret; // }

    // codec->regmap = devm_regmap_init(dev, NULL, codec, // &jz4770_codec_regmap_config); // if (IS_ERR(codec->regmap)) // return PTR_ERR(codec->regmap);

    // codec->clk = devm_clk_get(dev, "aic"); // if (IS_ERR(codec->clk)) // return PTR_ERR(codec->clk);

    // platform_set_drvdata(pdev, codec);

    ret = devm_snd_soc_register_component(dev, &soc_component_dev,
    				      vcodec_dai, ARRAY_SIZE(vcodec_dai));
    if (ret) {
    	dev_err(dev, "Failed to register codec: %d\n", ret);
    	return ret;
    }
    
    return 0;

    }

    static int codec_remove(struct platform_device *pdev){ printk("-----%s----\n",func);

    return 0;

    }

    /*static void codec_pdev_release(struct device dev) { }/

    /static struct platform_device codec_pdev = { .name = "vcodec", .dev.release = codec_pdev_release, };/

    static struct platform_driver codec_pdrv = { .probe = codec_probe, .remove = codec_remove, .driver = { .name = "vcodec", }, };

    //struct platform_device_info pdevinfo;

    static struct platform_device *codec_pdev;

    static int __init codec_init(void) { int ret;

    codec_pdev = platform_device_register_simple("codec", -1, NULL, 0);
    
    if (IS_ERR(codec_pdev))
    	return PTR_ERR(codec_pdev);
    
    ret = platform_driver_register(&codec_pdrv);
    if (ret)
    	platform_device_unregister(codec_pdev);
    
    return ret;

    }

    static void __exit codec_exit(void) { platform_driver_unregister(&codec_pdrv); platform_device_unregister(codec_pdev); }

    module_init(codec_init); module_exit(codec_exit); MODULE_LICENSE("GPL");

  • Makefile

    #KERN_DIR = /home/vbox/workspace/qemu/100ask_imx6ull-qemu/linux-4.9.88 KERN_DIR = /usr/src/linux-headers-5.15.0-71-generic all: make -C $(KERN_DIR) M=pwd modules

    clean: make -C $(KERN_DIR) M=pwd modules clean rm -rf modules.order

    obj-m += vplatform.o obj-m += vcodec.o obj-m += vmachine.o

Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册