linux lcd设备驱动剖析二

该博客详细剖析了Linux系统中s3c24xxfb平台驱动的probe函数,从获取平台数据的角度出发,深入探讨了LCD设备驱动的内部工作原理。
摘要由CSDN通过智能技术生成

上一节中,分析了s3c2410fb,c的入口出口函数,以及一些重要结构体的分析,初步知道了这是一个平台驱动的架构。

上一节文章链接:http://blog.csdn.net/lwj103862095/article/details/18188259

上一节讲到probe函数就没继续往下深究了,这一节里,我们来详细分析s3c24xxfb_probe函数,整体分析如下:

static int __init s3c24xxfb_probe(struct platform_device *pdev,
				  enum s3c_drv_type drv_type)
{
	struct s3c2410fb_info *info;
	struct s3c2410fb_display *display;
	struct fb_info *fbinfo;
	struct s3c2410fb_mach_info *mach_info;  /* 包含s3c2410fb_display */
	struct resource *res;
	int ret;
	int irq;
	int i;
	int size;
	u32 lcdcon1;

	/*  s3c24xx_fb_set_platdata()里会设置platform_data
	 *  tq2440_machine_init()函数调用s3c24xx_fb_set_platdata(&tq2440_fb_info);
	 *  所以这里传入来的platform_data就是tq2440_fb_info结构体实例
	 */
	mach_info = pdev->dev.platform_data;

	/* 执行完上面的语句后mach_info指向tq2440_fb_info结构体,而不为NULL  */
	if (mach_info == NULL) {
		dev_err(&pdev->dev,
			"no platform data for lcd, cannot attach\n");
		return -EINVAL;		/* 表示无效的参数 */
	}

	/* tq2440_fb_info设置了default_display = 0,num_displays = 1,故这句不会执行 */
	if (mach_info->default_display >= mach_info->num_displays) {
		dev_err(&pdev->dev, "default is %d but only %d displays\n",
			mach_info->default_display, mach_info->num_displays);
		return -EINVAL;
	}

	/* display指向tq2440_lcd_cfg,关于LCD屏相关参数的设置 */
	display = mach_info->displays + mach_info->default_display;

	/* 通过平台设备platform_device获得IRQ
	 * platform_get_irq其实是调用platform_get_resource(dev, IORESOURCE_IRQ, num)
	 */
	irq = platform_get_irq(pdev, 0);
	if (irq < 0) {
		dev_err(&pdev->dev, "no irq for device\n");
		return -ENOENT;
	}

	/* 	分配一个fb_info结构体,第一参数不为0表示,额外多申请的空间
	 *	用来存放额外的数据,这里用来存放s3c2410fb_info额外的数据
	 *  比如:clk,resource,io,irq_base,drv_type等额外信息
	 */
	fbinfo = framebuffer_alloc(sizeof(struct s3c2410fb_info), &pdev->dev);
	if (!fbinfo)
		return -ENOMEM;		/* 返回NULL表示失败 */

	/* 相当于pdev->dev->driver_data = fbinfo */
	platform_set_drvdata(pdev, fbinfo);

	/* 在framebuffer_alloc函数里info->par指向了额外多申请内存空间的首地址 */
	info = fbinfo->par;			/* 将私有数据赋给info指针变量 */
	info->dev = &pdev->dev;		/* 指定struct s3c2410fb_info中dev为平台设备中的dev */
	info->drv_type = drv_type;	/* 驱动类型, DRV_S3C2410还是DRV_S3C2412 */

	/*  通过平台设备platform_device获得资源(IO) */
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (res == NULL) {
		dev_err(&pdev->dev, "failed to get memory registers\n");
		ret = -ENXIO;
		goto dealloc_fb;
	}

	size = (res->end - res->start) + 1;		/* 资源的大小 */

	/* 申请以res->start地址开始大小为size的I/O内存 */
	info->mem = request_mem_region(res->start, size, pdev->name);
	if (info->mem == NULL) {
		dev_err(&pdev->dev, "failed to get memory region\n");
		ret = -ENOENT;
		goto dealloc_fb;
	}

	/* 映射I/O地址,其实就是将S3C2440的LCD首寄存器(LCDCON1)的物理地址映射为虚拟地址 */
	info->io = ioremap(res->start, size);
	if (info->io == NULL) {
		dev_err(&pdev->dev, &#
  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值