/*
//devices-xxx.c
static struct platform_device msm_lcdc_device = {
.name = "lcdc",
.id = 0,
};
//board-xxx.c
static struct lcdc_platform_data lcdc_pdata = {
.lcdc_power_save = lcdc_panel_power,
};
//board-msmxxx.c
static void __init msm7x30_init(void)
+-- msm_fb_add_devices();
+-- msm_fb_register_device("mdp", &mdp_pdata);
+-- msm_fb_register_device("pmdh", &mddi_pdata);
+-- msm_fb_register_device("lcdc", &lcdc_pdata); //注册id=0的"lcdc"设备
+-- msm_register_device(&msm_lcdc_device, data); //将lcdc_device.dev.platform_data置为lcdc_pdata
+-- pdev->dev.platform_data = data;
+-- platform_device_register(pdev);
+-- msm_fb_register_device("dtv", &dtv_pdata);
+-- msm_fb_register_device("tvenc", &atv_pdata);
*/
#################################################################################################################
//@kernel/drivers/video/msm/Makefile
obj-$(CONFIG_FB_MSM_LCDC_HIMAX_WQVGA727) += lcdc_panel_wqvga727.o
//kernel/arch/arm/configs/msm7630_xxx_defconfig
CONFIG_FB_MSM_LCDC_HIMAX_WQVGA727=y
//因此,kernel/drivers/video/msm/lcdc_panel_wqvga727.c将被编入kernel.
//@kernel/drivers/video/msm/lcdc_panel_wqvga727.c
static struct platform_driver this_driver = {
.probe = lcdc_panel_probe,
.driver = {
.name = "lcdc_panel_xx",
},
};
static struct platform_device this_device = {
.name = "lcdc_panel_xx",
.id = 1,
.dev = {
.platform_data = &lcdc_himax_panel_data,
}
};
@kernel/drivers/video/msm/lcdc_panel_wqvga727.c
module_init(lcdc_himax_panel_init);
static int __init lcdc_himax_panel_init(void)
+-- platform_driver_register(&this_driver); //注册“lcdc_panel_xx”驱动
+-- pinfo = &lcdc_himax_panel_data.panel_info;
+-- pinfo->xres = 240;
+-- pinfo->yres = 400;
+-- pinfo->type = LCDC_PANEL; //这里将panel_info->type初始化为LCDC_TYPE
+-- pinfo->pdest = DISPLAY_1;
+-- pinfo->wait_cycle = 0;
+-- pinfo->bpp = 18;
+-- pinfo->fb_num = 2;
+-- pinfo->clk_rate = 8192000;
+-- pinfo->lcdc.h_back_porch = 4;
+-- pinfo->lcdc.h_front_porch = 4;
+-- pinfo->lcdc.h_pulse_width = 4;
+-- pinfo->lcdc.v_back_porch = 3;
+-- pinfo->lcdc.v_front_porch = 3;
+-- pinfo->lcdc.v_pulse_width = 1;
+-- pinfo->lcdc.border_clr = 0; /* blk */
+-- pinfo->lcdc.underflow_clr = 0xff; /* blue */
+-- pinfo->lcdc.hsync_skew = 0;
+-- platform_device_register(&this_device); //注册“lcdc_panel_xx”设备
//因此在lcdc_himax_panel_init()执行之后,lcdc_panel_probe()
static int __init
lcdc_panel_probe(struct platform_device *pdev)
+-- msm_fb_add_device(pdev); //在这里会设置driver_data.并把“lcdc_panel_xx”设备加入platform总线上
+-- struct fb_info *fbi;
+-- pdata = pdev->dev.platform_data; //这里platform_data就是lcdc_himax_panel_data
//对于lcdc_panel_wqvga727.c,pdata->panel_info.type在lcdc_himax_panel_init()里面初始化为LCDC_PANEL
+-- type = pdata->panel_info.type;
+-- fb_num = pdata->panel_info.fb_num;
+-- this_dev = msm_fb_device_alloc(pdata, type, id); //这里__重新__创建一个platform_device
+-- struct platform_device *this_dev = NULL;
//根据type来确定新的platform_device的name
+-- switch (type) {
case EBI2_PANEL:
snprintf(dev_name, sizeof(dev_name), "ebi2_lcd");
break;
case MDDI_PANEL:
snprintf(dev_name, sizeof(dev_name), "mddi");
break;
case EXT_MDDI_PANEL:
snprintf(dev_name, sizeof(dev_name), "mddi_ext");
break;
case TV_PANEL:
snprintf(dev_name, sizeof(dev_name), "tvenc");
break;
case HDMI_PANEL:
case LCDC_PANEL:
//因此对于lcdc_panel_wqvga727.c,type就是LCDC_PANEL,于是dev_name就被初始化为"lcdc"
printk("msm_fb_device_alloc: inside type!\n");
snprintf(dev_name, sizeof(dev_name), "lcdc");
break;
case DTV_PANEL:
snprintf(dev_name, sizeof(dev_name), "dtv");
break;
case MIPI_VIDEO_PANEL:
case MIPI_CMD_PANEL:
snprintf(dev_name, sizeof(dev_name), "mipi_dsi");
break;
default:
return NULL;
}
//创建新的platform_device,并将其platform_data指向lcdc_himax_panel_data这个struct msm_fb_panel_data结构实例
+-- this_dev = platform_device_alloc(dev_name, ((u32) type << 16) | (u32) id);
+-- platform_device_add_data(this_dev, pdata, sizeof(struct msm_fb_panel_data))
+-- void *d = kmemdup(data, size, GFP_KERNEL);
+-- pdev->dev.platform_data = d;
+-- return this_dev; //返回新的platform_device
//开辟一段sizeof(fb_info)+sizeof(struct msm_fb_data_type)大小的内存,并用info->par指针指向后者
+-- fbi = framebuffer_alloc(sizeof(struct msm_fb_data_type), NULL);
+-- int fb_info_size = sizeof(struct fb_info);
+-- struct fb_info *info;
+-- p = kzalloc(fb_info_size + size, GFP_KERNEL);
+-- info = (struct fb_info *) p;
+-- info->par = p + fb_info_size;
+-- info->device = dev;
+-- return info;
//将sizeof(struct msm_fb_data_type)那段内存单独提出来,用mfd指针指向之.
+-- mfd = (struct msm_fb_data_type *)fbi->par;
+-- mfd->key = MFD_KEY;
+-- mfd->fbi = fbi;
+-- mfd->panel.type = type;
+-- mfd->panel.id = id;
+-- mfd->fb_page = fb_num;
+-- mfd->index = fbi_list_index;
+-- mfd->mdp_fb_page_protection = MDP_FB_PAGE_PROTECTION_WRITECOMBINE;
+-- mfd->pdev = this_dev;
+-- mfd_list[mfd_list_index++] = mfd;
+-- fbi_list[fbi_list_index++] = fbi;
+-- platform_set_drvdata(this_dev, mfd); //把新创建的platform_device设备的dev->p->driver_data设置为mfd
+-- dev_set_drvdata(&(_dev)->dev, (data))
+-- dev->p->driver_data = data;
+-- platform_device_add(this_dev) //把新创建的platform_device设备挂到platform总线上.
board-msmxxx.c中注册了一个名为"lcdc"的platform_device,该platform_device在arch/arm/mach-msm/devices-msm7xxx.c
中定义.此platform设备将和lcdc_driver匹配,id为0.
lcdc_panel_wqvga727.c中也注册了一个名为"lcdc"的platform设备,也将匹配lcdc_driver,id为1.
lcdc_driver的定义在drivers/video/msm/lcdc.c中.
//@drivers/video/msm/lcdc.c
static struct platform_driver lcdc_driver = {
.probe = lcdc_probe,
.remove = lcdc_remove,
.suspend = NULL,
.resume = NULL,
.shutdown = NULL,
.driver = {
.name = "lcdc",
},
};
//@module_init(lcdc_driver_init);
static int __init lcdc_driver_init(void)
+-- pixel_mdp_clk = clk_get(NULL, "pixel_mdp_clk");
?-- pixel_lcdc_clk = clk_get(NULL, "pixel_lcdc_clk");
?-- pixel_mdp_clk = clk_get(NULL, "mdp_lcdc_pclk_clk");
?-- pixel_lcdc_clk = clk_get(NULL, "mdp_lcdc_pad_pclk_clk");
+-- pm_qos_add_requirement(PM_QOS_SYSTEM_BUS_FREQ , "lcdc", PM_QOS_DEFAULT_VALUE);
+-- lcdc_register_driver();
+-- platform_driver_register(&lcdc_driver); //注册“lcdc”驱动
//设备&驱动匹配之后调用lcdc_probe()
static int lcdc_probe(struct platform_device *pdev)
+-- if (pdev->id == 0) { //id为0的"lcdc"设备没有dev->p->driver_data
lcdc_pdata = pdev->dev.platform_data; //取出lcdc_himax_panel_data结构,用lcdc_pdata指向之
return 0;
}
+-- mfd = platform_get_drvdata(pdev); //取出id不为0的"lcdc"设备的dev->p->driver_data,用mfd指向之
+-- platform_driver_register(&lcdc_driver);
//创建一个名为"mdp"的platform_device,并将其platform_data指向一个struct msm_fb_panel_data结构.
+-- mdp_dev = platform_device_alloc("mdp", pdev->id);
+-- mfd->pdev = mdp_dev;
+-- mfd->dest = DISPLAY_LCDC;
+-- platform_device_add_data(mdp_dev, pdev->dev.platform_data, sizeof(struct msm_fb_panel_data))
+-- void *d = kmemdup(data, size, GFP_KERNEL);
+-- pdev->dev.platform_data = d;
//初始化"mdp"设备的platform_data
+-- pdata = (struct msm_fb_panel_data *)mdp_dev->dev.platform_data; //取出lcdc_himax_panel_data结构,用pdata指向之
+-- pdata->on = lcdc_on;
+-- pdata->off = lcdc_off;
+-- pdata->next = pdev;
+-- mfd->panel_info = pdata->panel_info; //实际上就是lcdc_himax_panel_data.panel_info
+-- if (mfd->index == 0)
mfd->fb_imgType = MSMFB_DEFAULT_TYPE;
else
mfd->fb_imgType = MDP_RGB_565;
+-- fbi = mfd->fbi;
+-- fbi->var.pixclock = clk_round_rate(pixel_mdp_clk,mfd->panel_info.clk_rate);
+-- fbi->var.left_margin = mfd->panel_info.lcdc.h_back_porch;
+-- fbi->var.right_margin = mfd->panel_info.lcdc.h_front_porch;
+-- fbi->var.upper_margin = mfd->panel_info.lcdc.v_back_porch;
+-- fbi->var.lower_margin = mfd->panel_info.lcdc.v_front_porch;
+-- fbi->var.hsync_len = mfd->panel_info.lcdc.h_pulse_width;
+-- fbi->var.vsync_len = mfd->panel_info.lcdc.v_pulse_width;
//将"mdp"设备的dev->p->driver_data指向id不为0的"lcdc"设备的dev->p->driver_data指向的数据
//即lcdc_panel_probe()函数中创建的struct msm_fb_data_type
+-- platform_set_drvdata(mdp_dev, mfd);
+-- platform_device_add(mdp_dev); //将"mdp"设备添加到platform总线,id不为0
+-- pdev_list[pdev_list_cnt++] = pdev;
/*
static struct platform_device msm_mdp_device = {
.name = "mdp",
.id = 0,
.num_resources = ARRAY_SIZE(msm_mdp_resources),
.resource = msm_mdp_resources,
};
static void __init msm7x30_init(void)
+-- msm_fb_add_devices();
+-- msm_fb_register_device("mdp", &mdp_pdata); //注册id=0的"mdp"设备
+-- msm_register_device(&msm_mdp_device, data); //将msm_mdp_device.dev.platform_data置为mdp_data
+-- pdev->dev.platform_data = data;
+-- platform_device_register(pdev);
+-- msm_fb_register_device("pmdh", &mddi_pdata);
+-- msm_fb_register_device("lcdc", &lcdc_pdata);
+-- msm_fb_register_device("dtv", &dtv_pdata);
+-- msm_fb_register_device("tvenc", &atv_pdata);
*/
//@drivers/video/msm/mdp.c
static struct platform_driver mdp_driver = {
.probe = mdp_probe,
.remove = mdp_remove,
#ifndef CONFIG_HAS_EARLYSUSPEND
.suspend = mdp_suspend,
.resume = NULL,
#endif
.shutdown = NULL,
.driver = {
.name = "mdp",
.pm = &mdp_dev_pm_ops,
},
};
//module_init(mdp_driver_init);
static int __init mdp_driver_init(void)
+-- mdp_drv_init();
+-- mdp_register_driver();
+-- early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 1;
+-- early_suspend.suspend = mdp_early_suspend;
+-- register_early_suspend(&early_suspend);
+-- platform_driver_register(&mdp_driver); //注册"mdp"驱动
+-- mdp4_debugfs_init();
//“mdp”设备/驱动匹配后调用mdp_probe()
//MDP -- Mobile Display Processor
static int mdp_probe(struct platform_device *pdev)
//id为0的设备最先初始化,在其初始化期间初始化mdp硬件
+-- if ((pdev->id == 0) && (pdev->num_resources > 0)) {
mdp_pdata = pdev->dev.platform_data;
size = resource_size(&pdev->resource[0]);
msm_mdp_base = ioremap(pdev->resource[0].start, size);
mdp_irq_clk_setup();
#ifdef CONFIG_FB_MSM_MDP40
mdp4_hw_init();
mdp4_fetch_cfg(clk_get_rate(mdp_clk));
#else
mdp_hw_init();
#endif
mdp_resource_initialized = 1;
return 0;
}
+-- if (!mdp_resource_initialized)
return -EPERM;
+-- mfd = platform_get_drvdata(pdev);
+-- msm_fb_dev = platform_device_alloc("msm_fb", pdev->id); //创建"msm_fb"设备
+-- mfd->pdev = msm_fb_dev;
+-- platform_device_add_data(msm_fb_dev, pdev->dev.platform_data, sizeof(struct msm_fb_panel_data))
+-- pdata = msm_fb_dev->dev.platform_data;
+-- pdata->on = mdp_on;
+-- pdata->off = mdp_off;
+-- pdata->next = pdev;
+-- switch (mfd->panel.type) {
case EXT_MDDI_PANEL:
case MDDI_PANEL:
case EBI2_PANEL:
...
break;
case HDMI_PANEL:
case LCDC_PANEL:
pdata->on = mdp_lcdc_on;
pdata->off = mdp_lcdc_off;
mfd->hw_refresh = TRUE;
mfd->cursor_update = mdp_hw_cursor_update;
mfd->dma_fnc = mdp_lcdc_update;
mfd->dma = &dma2_data;
spin_lock_irqsave(&mdp_spin_lock, flag);
mdp_intr_mask &= ~MDP_DMA_P_DONE;
outp32(MDP_INTR_ENABLE, mdp_intr_mask);
spin_unlock_irqrestore(&mdp_spin_lock, flag);
break;
...
}
+-- platform_set_drvdata(msm_fb_dev, mfd); //将"msm_fb"设备的platform_data指向mfd指向的数据
+-- platform_device_add(msm_fb_dev); //将"msm_fb"设备添加到platform总线上
+-- pm_runtime_set_active(&pdev->dev);
+-- pm_runtime_enable(&pdev->dev);
+-- pdev_list[pdev_list_cnt++] = pdev;
/*
//"msm_fb"设备的定义在board文件中
@arch/arm/mach-msm/board-xxx.c
static struct platform_device msm_fb_device = {
.name = "msm_fb"
.id = 0,
.num_resources = ARRAY_SIZE(msm_fb_resources),
//这个resources的mem资源并没有在定义里面直接给出,但是在设备的probe里面却用到了,那么他是哪来的呢?
.resource = msm_fb_resources, //...
.dev = {
.platform_data = &msm_fb_pdata,
}
};
MACHINE_START(MSM7X30_SURF, "QCT MSM7X30 SURF")
#ifdef CONFIG_MSM_DEBUG_UART
.phys_io = MSM_DEBUG_UART_PHYS,
.io_pg_offst = ((MSM_DEBUG_UART_BASE) >> 18) & 0xfffc,
#endif
.boot_params = PHYS_OFFSET + 0x100,
.map_io = msm7x30_map_io, //msm7x30_map_io()...
.init_irq = msm7x30_init_irq,
.init_machine = msm7x30_init,
.timer = &msm_timer,
MACHINE_END
*/
//msm_fb_resources[0]就是在这里初始化的:
msm7x30_map_io()
+-- msm_shared_ram_phys = 0x00100000;
+-- msm_map_msm7x30_io();
+-- msm7x30_allocate_memory_regions();
//Request allocation of Hardware accessible PMEM regions at the beginning to make sure they are
//allocated in EBI-0. This will allow 7x30 with two mem banks enter the second mem bank into
//Self-Refresh State during Idle Power Collapse.
//The current HW accessible PMEM regions are
//1. Frame Buffer.
// LCDC HW can access msm_fb_resources during Idle-PC.
//2. Audio
// LPA HW can access android_pmem_audio_pdata during Idle-PC.
+-- size = fb_size ? : MSM_FB_SIZE;
addr = alloc_bootmem(size);
msm_fb_resources[0].start = __pa(addr);
msm_fb_resources[0].end = msm_fb_resources[0].start + size - 1;
+-- size = pmem_audio_size;
if (size) {
addr = alloc_bootmem(size);
android_pmem_audio_pdata.start = __pa(addr);
android_pmem_audio_pdata.size = size;
}
+-- size = gpu_phys_size;
if (size) {
addr = alloc_bootmem(size);
kgsl_resources[1].start = __pa(addr);
kgsl_resources[1].end = kgsl_resources[1].start + size - 1;
}
+-- size = pmem_kernel_ebi1_size;
if (size) {
addr = alloc_bootmem_aligned(size, 0x100000);
android_pmem_kernel_ebi1_pdata.start = __pa(addr);
android_pmem_kernel_ebi1_pdata.size = size;
}
+-- size = pmem_sf_size;
if (size) {
addr = alloc_bootmem(size);
android_pmem_pdata.start = __pa(addr);
android_pmem_pdata.size = size;
}
+-- if machine_is_msm7x30_fluid()
size = fluid_pmem_adsp_size;
else
size = pmem_adsp_size;
if (size) {
addr = alloc_bootmem(size);
android_pmem_adsp_pdata.start = __pa(addr);
android_pmem_adsp_pdata.size = size;
}
/*
static struct platform_device *devices[] __initdata = {
...
&msm_fb_device,
...
}
static void __init msm7x30_init(void)
+-- platform_add_devices(devices, ARRAY_SIZE(devices));
*/
//"msm_fb"驱动的定义在drivers/video/msm/msm_fb.c文件中:
static struct platform_driver msm_fb_driver = {
.probe = msm_fb_probe,
.remove = msm_fb_remove,
#ifndef CONFIG_HAS_EARLYSUSPEND
.suspend = msm_fb_suspend,
.resume = msm_fb_resume,
#endif
.shutdown = NULL,
.driver = {
/* Driver name must match the device name added in platform.c. */
.name = "msm_fb",
.pm = &msm_fb_dev_pm_ops,
},
};
//驱动在module_init阶段注册
module_init(msm_fb_init);
int __init
msm_fb_init(void)
+-- msm_fb_register_driver(); //注册"msm_fb"驱动
+-- root = msm_fb_get_debugfs_root()
+-- msm_fb_debugfs_file_create(root, "msm_fb_msg_printing_level", (u32 *) &msm_fb_msg_level);
+-- msm_fb_debugfs_file_create(root, "mddi_msg_printing_level", (u32 *) &mddi_msg_level);
+-- msm_fb_debugfs_file_create(root, "msm_fb_debug_enabled", (u32 *) &msm_fb_debug_enabled);
//msm_fb设备/驱动匹配后 msm_fb_probe()函数被调用
static int msm_fb_probe(struct platform_device *pdev)
+-- if ((pdev->id == 0) && (pdev->num_resources > 0)) {
msm_fb_pdata = pdev->dev.platform_data;
fbram_size = pdev->resource[0].end - pdev->resource[0].start + 1;
fbram_phys = (char *)pdev->resource[0].start;
fbram = ioremap((unsigned long)fbram_phys, fbram_size);
if (!fbram) {
printk(KERN_ERR "fbram ioremap failed!\n");
return -ENOMEM;
}
MSM_FB_INFO("msm_fb_probe: phy_Addr = 0x%x virt = 0x%x\n",
(int)fbram_phys, (int)fbram);
msm_fb_resource_initialized = 1;
return 0;
}
+-- mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev); //从driver data中拿到mfd
+-- err = pm_runtime_set_active(&pdev->dev);
+-- mfd->panel_info.frame_count = 0;
+-- mfd->bl_level = mfd->panel_info.bl_max;
+-- mfd->overlay_play_enable = 1;
+-- rc = msm_fb_register(mfd); //msm_fb_register...
+-- msm_fb_config_backlight(mfd);
+-- pm_runtime_enable(&pdev->dev);
+-- pdev_list[pdev_list_cnt++] = pdev;
+-- msm_fb_create_sysfs(pdev);
static int msm_fb_register(struct msm_fb_data_type *mfd)
+-- struct msm_panel_info *panel_info = &mfd->panel_info;
+-- struct fb_info *fbi = mfd->fbi;
+-- struct fb_fix_screeninfo *fix;
+-- struct fb_var_screeninfo *var;
+-- struct fb_info *fbi = mfd->fbi;
+-- struct fb_fix_screeninfo *fix;
+-- struct fb_var_screeninfo *var;
+-- 初始化fix和var的各个成员
+-- fbram_offset = PAGE_ALIGN((int)fbram)-(int)fbram;
+-- fbram += fbram_offset;
+-- fbram_phys += fbram_offset;
+-- fbram_size -= fbram_offset;
+-- fbi->screen_base = fbram; //screen_base是page aligned的,screen_base就是帧缓存对应的物理内存
+-- fbi->fix.smem_start = (unsigned long)fbram_phys; //帧缓存的物理地址
+-- memset(fbi->screen_base, 0x0, fix->smem_len);
+-- mfd->op_enable = TRUE;
+-- mfd->panel_power_on = FALSE;
+-- if (mfd->cursor_update) {
mfd->cursor_buf = dma_alloc_coherent(NULL, MDP_CURSOR_SIZE,
(dma_addr_t *) &mfd->cursor_buf_phys, GFP_KERNEL);
}
+-- if (mfd->lut_update) {
ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
}
+-- register_framebuffer(fbi) //将framebuffer注册到registered_fb[]数组中去.这样就和帧缓存框架真正联系起来了.
+-- fbram += fix->smem_len;
+-- fbram_phys += fix->smem_len;
+-- fbram_size -= fix->smem_len;
+-- if (!load_565rle_image(INIT_IMAGE_FILE)) ; //这里需要看一看...
+-- if (mfd->panel_info.type != DTV_PANEL) {
mfd->early_suspend.suspend = msmfb_early_suspend;
mfd->early_suspend.resume = msmfb_early_resume;
mfd->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 2;
register_early_suspend(&mfd->early_suspend);
}
+-- root = msm_fb_get_debugfs_root();
+-- sub_name[0] = (char)(mfd->index + 0x30);
+-- sub_name[1] = '\0';
+-- sub_dir = debugfs_create_dir(sub_name, root);
+-- mfd->sub_dir = sub_dir;
+-- msm_fb_debugfs_file_create(sub_dir, "op_enable", (u32 *) &mfd->op_enable);
+-- msm_fb_debugfs_file_create(sub_dir, "panel_power_on", (u32 *) &mfd->panel_power_on);
...
+-- switch (mfd->dest) ...
probe() probe() probe() probe()
"lcdc_panel_xx" ----------> "lcdc" ----------> "mdp" ----------> "msm_fb" ----------> .
struct msm_fb_data_type {
__u32 key;
__u32 index;
__u32 ref_cnt;
__u32 fb_page;
panel_id_type panel;
struct msm_panel_info panel_info;
DISP_TARGET dest;
struct fb_info *fbi;
boolean op_enable;
uint32 fb_imgType;
boolean sw_currently_refreshing;
boolean sw_refreshing_enable;
boolean hw_refresh;
#ifdef CONFIG_FB_MSM_OVERLAY
int overlay_play_enable;
#endif
MDPIBUF ibuf;
boolean ibuf_flushed;
struct timer_list refresh_timer;
struct completion refresher_comp;
boolean pan_waiting;
struct completion pan_comp;
/* vsync */
boolean use_mdp_vsync;
__u32 vsync_gpio;
__u32 total_lcd_lines;
__u32 total_porch_lines;
__u32 lcd_ref_usec_time;
__u32 refresh_timer_duration;
struct hrtimer dma_hrtimer;
boolean panel_power_on;
struct work_struct dma_update_worker;
struct semaphore sem;
struct timer_list vsync_resync_timer;
boolean vsync_handler_pending;
struct work_struct vsync_resync_worker;
ktime_t last_vsync_timetick;
__u32 *vsync_width_boundary;
unsigned int pmem_id;
struct disp_info_type_suspend suspend;
__u32 channel_irq;
struct mdp_dma_data *dma;
void (*dma_fnc) (struct msm_fb_data_type *mfd);
int (*cursor_update) (struct fb_info *info,
struct fb_cursor *cursor);
int (*lut_update) (struct fb_info *info,
struct fb_cmap *cmap);
int (*do_histogram) (struct fb_info *info,
struct mdp_histogram *hist);
void *cursor_buf;
void *cursor_buf_phys;
void *cmd_port;
void *data_port;
void *data_port_phys;
__u32 bl_level;
struct platform_device *pdev;
__u32 var_xres;
__u32 var_yres;
__u32 var_pixclock;
#ifdef MSM_FB_ENABLE_DBGFS
struct dentry *sub_dir;
#endif
#ifdef CONFIG_HAS_EARLYSUSPEND
struct early_suspend early_suspend;
struct early_suspend mddi_early_suspend;
struct early_suspend mddi_ext_early_suspend;
#endif
u32 mdp_fb_page_protection;
};