您的位置:首页 > 运维架构 > Linux

linux lcd驱动分析一

2012-07-04 23:20 267 查看
硬件平台:mini2440 + TD035STED4 软件平台:linux-2.6.32.2 日期:2012/07/04

首先看驱动模块的初始化函数和卸载函数:

/* drivers/video/s3c2410fb.c */

1119 int __init s3c2410fb_init(void)

1120 {

1121 int ret = platform_driver_register(&s3c2410fb_driver);

1122

1123 if (ret == 0)

1124 ret = platform_driver_register(&s3c2412fb_driver);

1125

1126 return ret;

1127 }

1128

1129 static void __exit s3c2410fb_cleanup(void)

1130 {

1131 platform_driver_unregister(&s3c2410fb_driver);

1132 platform_driver_unregister(&s3c2412fb_driver);

1133 }

初始化函数里面就注册了一个平台设备驱动。卸载函数当然是注销掉这个平台设备驱动。

s3c2440自然采用的是s3c2410fb_driver,我们来看这个结构的定义:

1097 static struct platform_driver s3c2410fb_driver = {

1098 .probe = s3c2410fb_probe,

1099 .remove = s3c2410fb_remove,

1100 .suspend = s3c2410fb_suspend,

1101 .resume = s3c2410fb_resume,

1102 .driver = {

1103 .name = "s3c2410-lcd",

1104 .owner = THIS_MODULE,

1105 },

1106 };

我们看driver中的name字段为s3c2410-lcd,那自然去找与之对应的平台设备。

我们在devs.c中找到了这个平台设备的定义:

/* arch/arm/plat-s3c24xx/devs.c */

141 /* LCD Controller */

142

143 static struct resource s3c_lcd_resource[] = {

144 [0] = {

145 .start = S3C24XX_PA_LCD,

146 .end = S3C24XX_PA_LCD + S3C24XX_SZ_LCD - 1,

147 .flags = IORESOURCE_MEM,

148 },

149 [1] = {

150 .start = IRQ_LCD,

151 .end = IRQ_LCD,

152 .flags = IORESOURCE_IRQ,

153 }

154

155 };

156

157 static u64 s3c_device_lcd_dmamask = 0xffffffffUL;

158

159 struct platform_device s3c_device_lcd = {

160 .name = "s3c2410-lcd",

161 .id = -1,

162 .num_resources = ARRAY_SIZE(s3c_lcd_resource),

163 .resource = s3c_lcd_resource,

164 .dev = {

165 .dma_mask = &s3c_device_lcd_dmamask,

166 .coherent_dma_mask = 0xffffffffUL

167 }

168 };

169

170 EXPORT_SYMBOL(s3c_device_lcd);

平台设备也有了,平台设备注册进了内核之后,那自然会调用驱动中的probe函数。

815 static char driver_name[] = "s3c2410fb";

816

817 static int __init s3c24xxfb_probe(struct platform_device *pdev,

818 enum s3c_drv_type drv_type)

819 {

820 struct s3c2410fb_info *info;

821 struct s3c2410fb_display *display;

822 struct fb_info *fbinfo;

823 struct s3c2410fb_mach_info *mach_info;

824 struct resource *res;

825 int ret;

826 int irq;

827 int i;

828 int size;

829 u32 lcdcon1;

830

831 mach_info = pdev->dev.platform_data;

832 if (mach_info == NULL) {

833 dev_err(&pdev->dev,

834 "no platform data for lcd, cannot attach\n");

835 return -EINVAL;

836 }

837

838 if (mach_info->default_display >= mach_info->num_displays) {

839 dev_err(&pdev->dev, "default is %d but only %d displays\n",

840 mach_info->default_display, mach_info->num_displays);

841 return -EINVAL;

842 }

843

844 display = mach_info->displays + mach_info->default_display;

845

846 irq = platform_get_irq(pdev, 0);

847 if (irq < 0) {

848 dev_err(&pdev->dev, "no irq for device\n");

849 return -ENOENT;

850 }

851

852 fbinfo = framebuffer_alloc(sizeof(struct s3c2410fb_info), &pdev->dev);

853 if (!fbinfo)

854 return -ENOMEM;

855

856 platform_set_drvdata(pdev, fbinfo);

857

858 info = fbinfo->par;

859 info->dev = &pdev->dev;

860 info->drv_type = drv_type;

861

862 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);

863 if (res == NULL) {

864 dev_err(&pdev->dev, "failed to get memory registers\n");

865 ret = -ENXIO;

866 goto dealloc_fb;

867 }

868

869 size = (res->end - res->start) + 1;

870 info->mem = request_mem_region(res->start, size, pdev->name);

871 if (info->mem == NULL) {

872 dev_err(&pdev->dev, "failed to get memory region\n");

873 ret = -ENOENT;

874 goto dealloc_fb;

875 }

876

877 info->io = ioremap(res->start, size);

878 if (info->io == NULL) {

879 dev_err(&pdev->dev, "ioremap() of registers failed\n");

880 ret = -ENXIO;

881 goto release_mem;

882 }

883

884 info->irq_base = info->io + ((drv_type == DRV_S3C2412) ? S3C2412_LCDINTBASE : S3C2410_LCDINTBAS E);

885

886 dprintk("devinit\n");

887

888 strcpy(fbinfo->fix.id, driver_name);

889

890 /* Stop the video */

891 lcdcon1 = readl(info->io + S3C2410_LCDCON1);

892 writel(lcdcon1 & ~S3C2410_LCDCON1_ENVID, info->io + S3C2410_LCDCON1);

893

894 fbinfo->fix.type = FB_TYPE_PACKED_PIXELS;

895 fbinfo->fix.type_aux = 0;

896 fbinfo->fix.xpanstep = 0;

897 fbinfo->fix.ypanstep = 0;

898 fbinfo->fix.ywrapstep = 0;

899 fbinfo->fix.accel = FB_ACCEL_NONE;

900

901 fbinfo->var.nonstd = 0;

902 fbinfo->var.activate = FB_ACTIVATE_NOW;

903 fbinfo->var.accel_flags = 0;

904 fbinfo->var.vmode = FB_VMODE_NONINTERLACED;

905

906 fbinfo->fbops = &s3c2410fb_ops;

907 fbinfo->flags = FBINFO_FLAG_DEFAULT;

908 fbinfo->pseudo_palette = &info->pseudo_pal;

909

910 for (i = 0; i < 256; i++)

911 info->palette_buffer[i] = PALETTE_BUFF_CLEAR;

912

913 ret = request_irq(irq, s3c2410fb_irq, IRQF_DISABLED, pdev->name, info);

914 if (ret) {

915 dev_err(&pdev->dev, "cannot get irq %d - err %d\n", irq, ret);

916 ret = -EBUSY;

917 goto release_regs;

918 }

919

920 info->clk = clk_get(NULL, "lcd");

921 if (!info->clk || IS_ERR(info->clk)) {

922 printk(KERN_ERR "failed to get lcd clock source\n");

923 ret = -ENOENT;

924 goto release_irq;

925 }

926

927 clk_enable(info->clk);

928 dprintk("got and enabled clock\n");

929

930 msleep(1);

931

932 info->clk_rate = clk_get_rate(info->clk);

933

934 /* find maximum required memory size for display */

935 for (i = 0; i < mach_info->num_displays; i++) {

936 unsigned long smem_len = mach_info->displays[i].xres;

937

938 smem_len *= mach_info->displays[i].yres;

939 smem_len *= mach_info->displays[i].bpp;

940 smem_len >>= 3;

941 if (fbinfo->fix.smem_len < smem_len)

942 fbinfo->fix.smem_len = smem_len;

943 }

944

945 /* Initialize video memory */

946 ret = s3c2410fb_map_video_memory(fbinfo);

947 if (ret) {

948 printk(KERN_ERR "Failed to allocate video RAM: %d\n", ret);

949 ret = -ENOMEM;

950 goto release_clock;

951 }

952

953 dprintk("got video memory\n");

954

955 fbinfo->var.xres = display->xres;

956 fbinfo->var.yres = display->yres;

957 fbinfo->var.bits_per_pixel = display->bpp;

958

959 s3c2410fb_init_registers(fbinfo);

960

961 s3c2410fb_check_var(&fbinfo->var, fbinfo);

962

963 ret = s3c2410fb_cpufreq_register(info);

964 if (ret < 0) {

965 dev_err(&pdev->dev, "Failed to register cpufreq\n");

966 goto free_video_memory;

967 }

968

969 ret = register_framebuffer(fbinfo);

970 if (ret < 0) {

971 printk(KERN_ERR "Failed to register framebuffer device: %d\n",

972 ret);

973 goto free_cpufreq;

974 }

975

976 /* create device files */

977 ret = device_create_file(&pdev->dev, &dev_attr_debug);

978 if (ret) {

979 printk(KERN_ERR "failed to add debug attribute\n");

980 }

981

982 printk(KERN_INFO "fb%d: %s frame buffer device\n",

983 fbinfo->node, fbinfo->fix.id);

984

985 return 0;

986

987 free_cpufreq:

988 s3c2410fb_cpufreq_deregister(info);

989 free_video_memory:

990 s3c2410fb_unmap_video_memory(fbinfo);

991 release_clock:

992 clk_disable(info->clk);

993 clk_put(info->clk);

994 release_irq:

995 free_irq(irq, info);

996 release_regs:

997 iounmap(info->io);

998 release_mem:

999 release_resource(info->mem);

1000 kfree(info->mem);

1001 dealloc_fb:

1002 platform_set_drvdata(pdev, NULL);

1003 framebuffer_release(fbinfo);

1004 return ret;

1005 }

1006

1007 static int __init s3c2410fb_probe(struct platform_device *pdev)

1008 {

1009 return s3c24xxfb_probe(pdev, DRV_S3C2410);

1010 }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: