现在的位置: 首页 > 综合 > 正文

s3c6410(arm11核)的LCD驱动理解一(probe)

2013年03月28日 ⁄ 综合 ⁄ 共 2073字 ⁄ 字号 评论关闭
static int __devinit s3c_fb_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	//私有数据结构体
	struct s3c_fb_platdata *pd;
	struct s3c_fb *sfb;
	struct resource *res;
	int win;
	int ret = 0;

	pd = pdev->dev.platform_data;
	if (!pd) {
		dev_err(dev, "no platform data specified\n");
		return -EINVAL;
	}
	//申请一段struct s3c_fb内存
	sfb = kzalloc(sizeof(struct s3c_fb), GFP_KERNEL);
	if (!sfb) {
		dev_err(dev, "no memory for framebuffers\n");
		return -ENOMEM;
	}
	//下面一大段程序就是初始化struct s3c_fb类型结构体sfb
	sfb->dev = dev;
	sfb->pdata = pd;
	//获取时钟结构体bus_clk
	sfb->bus_clk = clk_get(dev, "lcd");
	//判断该指针是否有效
	if (IS_ERR(sfb->bus_clk)) {
		dev_err(dev, "failed to get bus clock\n");
		goto err_sfb;
	}
	//使能LCD时钟
	clk_enable(sfb->bus_clk);
	//IO映射
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		dev_err(dev, "failed to find registers\n");
		ret = -ENOENT;
		goto err_clk;
	}

	sfb->regs_res = request_mem_region(res->start, resource_size(res),
					   dev_name(dev));
	if (!sfb->regs_res) {
		dev_err(dev, "failed to claim register region\n");
		ret = -ENOENT;
		goto err_clk;
	}

	sfb->regs = ioremap(res->start, resource_size(res));
	if (!sfb->regs) {
		dev_err(dev, "failed to map registers\n");
		ret = -ENXIO;
		goto err_req_region;
	}

	dev_dbg(dev, "got resources (regs %p), probing windows\n", sfb->regs);

	/* setup gpio and output polarity controls */
	//setup_gpio,这个函数需要在板级配置文件(smdk6410.c)中实现
	pd->setup_gpio();
	//vidcon1也是要在板级配置文件中配置,看数据手册可知,VIDCON1是LCD控制寄存器
	writel(pd->vidcon1, sfb->regs + VIDCON1);

	/* zero all windows before we do anything */
	//初始化s3c6410的window寄存器
	for (win = 0; win < S3C_FB_MAX_WIN; win++)
		s3c_fb_clear_win(sfb, win);

	/* we have the register setup, start allocating framebuffers */

	for (win = 0; win < S3C_FB_MAX_WIN; win++) {
		//判断这个win在板级配置文件中是否被配置,若未被配置,跳过此操作
		//在我的板级配置文件中是配置成win[0]
		if (!pd->win[win])
			continue;
		//probe最重要的函数,是关于framebuffer的操作
		ret = s3c_fb_probe_win(sfb, win, &sfb->windows[win]);
		if (ret < 0) {
			dev_err(dev, "failed to create window %d\n", win);
			for (; win >= 0; win--)
				s3c_fb_release_win(sfb, sfb->windows[win]);
			goto err_ioremap;
		}
	}
 	//把sfb保存为平台设备私有数据,在后面就可以调用platform_get_drvdata获取sfb
	platform_set_drvdata(pdev, sfb);

	return 0;

err_ioremap:
	iounmap(sfb->regs);

err_req_region:
	release_resource(sfb->regs_res);
	kfree(sfb->regs_res);

err_clk:
	clk_disable(sfb->bus_clk);
	clk_put(sfb->bus_clk);

err_sfb:
	kfree(sfb);
	return ret;
}

抱歉!评论已关闭.