s3c6410(arm11核)的LCD驱动理解一(probe)
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类型结构体sfbsfb->dev = dev;sfb->pdata = pd;//获取时钟结构体bus_clksfb->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获取sfbplatform_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;}