Qcom_lcd_driver 之一 -- 总体架构

本文深入探讨了LCD控制器设备(如lcdc)如何与显示设备进行交互的完整流程,包括设备注册、驱动匹配及初始化过程。通过分析源码,详细解释了设备与驱动之间的绑定机制以及硬件配置细节。
/*
//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;
};


403.879732: RNDIS_IPA NetDev was opened 403.891277: IPv6: ADDRCONF(NETDEV_CHANGE): rndis0: link becomes ready 403.891428: dwc3 4e00000.dwc3: Clr_TRB ring of ep1in 403.893656: RNDIS_IPA@rndis_ipa_start_xmit@1027@ctx:kworker/1:0: Missing pipe connected and/or iface up 403.908086: dwc3 4e00000.dwc3: gsi_prepare_trbs(): trb_pool:0000000000000000 trb_pool_dma:73c08000 403.908113: dwc3 4e00000.dwc3: 0: page_link:fffffffe00cf0202 offset:0 length:1000 address:0 403.908122: dwc3 4e00000.dwc3: gsi_prepare_trbs: Initialized TRB Ring for ep1in 403.908141: dwc3 4e00000.dwc3: XferRsc = 3 403.908152: dwc3 4e00000.dwc3: depcmd_laddr=4e0c83c last_trb_addr=8650 gevtcnt_laddr=4e0c42c gevtcnt_haddr=0 403.908168: dwc3 4e00000.dwc3: Clr_TRB ring of ep1out 403.912576: dwc3 4e00000.dwc3: gsi_prepare_trbs(): trb_pool:0000000000000000 trb_pool_dma:45224000 403.912603: dwc3 4e00000.dwc3: 0: page_link:fffffffe00148902 offset:0 length:1000 address:0 403.912611: dwc3 4e00000.dwc3: gsi_prepare_trbs: Initialized TRB Ring for ep1out 403.912630: dwc3 4e00000.dwc3: XferRsc = 2 403.912642: dwc3 4e00000.dwc3: depcmd_laddr=4e0c82c last_trb_addr=40f0 gevtcnt_laddr=4e0c41c gevtcnt_haddr=0 403.920331: Unable to handle kernel paging request at virtual address ffffffc013fce000 403.920349: Mem abort info: 403.920351: ESR = 0x96000047 403.920354: EC = 0x25: DABT (current EL), IL = 32 bits 403.920357: SET = 0, FnV = 0 403.920359: EA = 0, S1PTW = 0 403.920361: FSC = 0x07: level 3 translation fault 403.920364: Data abort info: 403.920365: ISV = 0, ISS = 0x00000047 403.920367: CM = 0, WnR = 1 403.920370: swapper pgtable: 4k pages, 39-bit VAs, pgdp=0000000042a8a000 403.920373: [ffffffc013fce000] pgd=10000000434a8003, p4d=10000000434a8003, pud=10000000434a8003, pmd=100000007b038003, pte=0000000000000000 403.920386: Internal error: Oops: 96000047 [#1] PREEMPT SMP 403.920599: Skip md ftrace buffer dump for: 0x1609e0 403.920604: Modules linked in: wlan(OE) msm_kgsl(OE) msm_drm(OE) ipa_clientsm(OE) camera(OE) rndisipam(OE) ipanetm(OE) rmnet_wlan(OE) icnss2(OE) msm_video(OE) cnss_nl(OE) cnss_prealloc(OE) ipam(OE) rmnet_core(OE) wlan_firmware_service(OE) ilitek2131(OE) bt_fm_slim(OE) msm_mmrm(OE) btpower(OE) cnss_utils(OE) gsim(OE) rmnet_ctl(OE) radio_i2c_rtc6226_qca(OE) usb_f_gsi(E) usb_f_qdss(E) landi_usb7016_i2c(E) va_macro_dlkm(OE) smcinvoke_dlkm(OE) machine_dlkm(OE) qcedev_mod_dlkm(OE) qcrypto_msm_dlkm(OE) rx_macro_dlkm(OE) wcd937x_dlkm(OE) tx_macro_dlkm(OE) tz_log_dlkm(OE) audio_pkt_dlkm(OE) wsa881x_analog_dlkm(OE) wcd9xxx_dlkm(OE) pinctrl_lpi_dlkm(OE) audio_prm_dlkm(OE) adsp_loader_dlkm(OE) hdcp_qseecom_dlkm(OE) q6_dlkm(OE) swr_ctrl_dlkm(OE) wcd_core_dlkm(OE) bolero_cdc_dlkm(OE) qce50_dlkm(OE) mbhc_dlkm(OE) wcd937x_slave_dlkm(OE) stub_dlkm(OE) swr_dlkm(OE) spf_core_dlkm(OE) gpr_dlkm(OE) snd_event_dlkm(OE) cfg80211(E) q6_notifier_dlkm(OE) msm_qmp(E) leds_gpio(E) 403.920680: leds_qpnp_vibrator_ldo(E) leds_qti_tri_led(E) qrtr_smd(E) qcom_q6v5_pas(E) qcom_pil_info(E) qcom_spss(E) qcom_q6v5(E) cpufreq_userspace(E) q6_pdr_dlkm(OE) qcom_spmi_adc5(E) snd_usb_audio_qmi(E) ipa_fmwk(E) icc_test(E) audpkt_ion_dlkm(OE) rpm_smd_cooling_device(E) cpufreq_ondemand(E) qcom_sysmon(E) qti_cpufreq_cdev(E) cx_ipeak_cdev(E) bcl_pmic5(E) qti_userspace_cdev(E) qcom_lpm(E) msm_tsens_driver(E) leds_qti_flash(E) qti_devfreq_cdev(E) regulator_cdev(E) qti_qmi_cdev(E) bcl_soc(E) qti_qmi_sensor(E) qcom_cpufreq_hw_debug(E) msm_lmh_dcvs(E) thermal_pause(E) qcom_spmi_temp_alarm(E) qcom_spmi_adc_tm5(E) cpu_hotplug(E) qcom_pon(E) qcom_smb1398_charger(E) lmh_cpu_vdd_cdev(E) qpnp_smb5_main(E) qcom_tsens(E) qcom_vadc_common(E) qcom_qpnp_qg(E) qti_battery_charger(E) rtc_pm8xxx(E) qcom_smb1355_charger(E) reboot_mode(E) i2c_msm_geni(E) gms_battery_prop(E) sgm7220(E) msm_sharedmem(E) frpc_adsprpc(E) pm8941_pwrkey(E) qpnp_pdphy(E) usb_f_ccid(E) ucsi_glink(E) 403.920748: usb_f_cdev(E) ehset(E) cx_ipeak(E) usb_f_diag(E) spmi_glink_debug(E) phy_qcom_emu(E) ld_class_drv(E) usb_bam(E) sg(E) lt6911_ver(E) dwc3_msm(E) spi_msm_geni(E) core_hang_detect(E) rpm_smd_debug(E) rq_stats(E) phy_msm_ssusb_qmp(E) apex_drv(E) f_fs_ipc_log(E) smp2p_sleepstate(E) gpucc_khaje(E) memlat(E) pinctrl_spmi_gpio(E) phy_msm_snps_hs(E) clk_rpm(E) aw9523b_key(E) mdt_loader(E) leds_aw99703(E) boot_stats(E) qcom_i2c_pmic(E) hung_task_enh(E) eud(E) qcom_iommu_debug(E) phy_generic(E) qcom_aoss(E) rpm_master_stat(E) msm_geni_serial(E) qcom_ramdump(E) altmode_glink(E) ch341(E) qfprom_sys(E) qcom_rpm(E) debugcc_khaje(E) sps_drv(E) rdbg(E) phy_qcom_ufs_qmp_v4(E) msm_memshare(E) liandi_gpiodemo(E) sub_lcd_lt9721(E) panel_event_notifier(E) guestvm_loader(E) ch34x(E) charger_ulog_glink(E) qcom_va_minidump(E) qti_battery_debug(E) phy_xgene(E) cdsprm(E) bwmon(E) msm_performance(E) nxpnfc_i2c(E) qcom_dcvs(E) cdsp_loader(E) msm_gpi(E) glink_pkt(E) 403.920826: landi_event_notifier(E) heap_mem_ext_v01(E) qcom_pm8008_regulator(E) dispcc_khaje(E) pinctrl_spmi_mpp(E) refgen(E) pmic_glink(E) pwm_qti_lpg(E) pinctrl_aw9523b(E) phy_qcom_ufs_qmp_v4_waipio(E) phy_qcom_ufs_qmp_v4_kalama(E) msm_sysstats(E) zram zsmalloc slim_qcom_ngd_ctrl(E) glink_probe(E) pdr_interface(E) rproc_qcom_common(E) qmi_helpers(E) ufs_qcom(E) sdhci_msm(E) qrtr(E) qcom_glink_smem(E) qcom_glink_rpm(E) qcom_glink_spss(E) arm_smmu(E) clk_smd_rpm(E) bam_dma(E) clk_dummy(E) cqhci(E) gcc_khaje(E) mem_buf(E) ns(E) phy_qcom_ufs_qmp_v4_khaje(E) qcom_dma_heaps(E) qseecom_dlkm(OE) phy_qcom_ufs_qrbtc_sdm845(E) qcom_glink(E) qnoc_bengal(E) qcom_soc_wdt(E) smp2p(E) usbpd(E) ufshcd_crypto_qti(E) clk_qcom(E) crypto_qti_common(E) icc_rpm(E) dcc_v2(E) mem_offline(E) mem_buf_dev(E) memory_dump_v2(E) qcom_iommu_util(E) pinctrl_bengal(E) pinctrl_khaje(E) qcom_ipc_logging(E) phy_qcom_ufs(E) msm_poweroff(E) rpm_smd_regulator(E) qcom_logbuf_vh(E) qcom_wdt_core(E) 403.920897: sched_walt(E) crypto_qti_tz(E) gdsc_regulator(E) minidump(E) pinctrl_msm(E) qcom_smd(E) rpm_smd(E) qcom_spmi_pmic(E) socinfo(E) secure_buffer(E) stub_regulator(E) debug_regulator(E) soc_sleep_stats(E) icc_debug(E) iommu_logger(E) msm_dma_iommu_mapping(E) nvmem_qcom_spmi_sdam(E) nvmem_qfprom(E) proxy_consumer(E) qcom_apcs_ipc_mailbox(E) smem(E) qcom_mpm(E) qcom_cpu_vendor_hooks(E) qcom_cpufreq_hw(E) qcom_pmu_lib(E) qcom_scm(E) qpnp_power_on(E) qnoc_qos_rpm(E) qrng_dlkm(OE) qti_regmap_debugfs(E) slimbus(E) regmap_spmi(E) qcom_hwspinlock(E) spmi_pmic_arb(E) 403.920942: CPU: 7 PID: 12183 Comm: kworker/u16:13 Tainted: G W OE 5.15.168-android13-8-gc3eb426f91e1-dirty #1 403.920947: Hardware name: Qualcomm Technologies, Inc. KHAJE IDP nopmi (DT) 403.920951: Workqueue: k_ipa_usb ipa_work_handler.cfi_jt [usb_f_gsi] 403.920978: pstate: 20400005 (nzCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) 403.920983: pc : av8l_fast_map_pages+0xc8/0x128 [qcom_iommu_util] 403.921004: lr : arm_smmu_map_pages+0xcc/0x260 [arm_smmu] 403.921041: sp : ffffffc024df3680 403.921043: x29: ffffffc024df3680 x28: ffffffdf62a620f0 x27: ffffff803c173f68 403.921049: x26: 00000000f9c00000 x25: 0000000000000003 x24: ffffffc024df3740 403.921054: x23: 0000000000000a20 x22: ffffff80361c3200 x21: 00000000f9c00000 403.921059: x20: 00000000000c8000 x19: ffffffc024df3740 x18: ffffffc0136c7078 403.921064: x17: ffffffc013fce008 x16: 00000000000c8000 x15: 00000000000000c8 403.921069: x14: 00000000000000c8 x13: 00000000f9c00000 x12: 0060000000000e43 403.921074: x11: 00000000000000c8 x10: 00000000000f9c00 x9 : ffffff803c173f00 403.921079: x8 : ffffffc013800000 x7 : ffffffc024df3740 x6 : 0000000000000a20 403.921084: x5 : 0000000000000003 x4 : 00600000f9c00e43 x3 : 00600000f9c01e43 403.921089: x2 : 00000000000000c6 x1 : ffffffc013fce000 x0 : 00000000f9c02000 403.921094: Call trace: 403.921097: av8l_fast_map_pages+0xc8/0x128 [qcom_iommu_util] 403.921116: arm_smmu_map_pages+0xcc/0x260 [arm_smmu] 403.921145: __iommu_map+0x180/0x3b4 403.921153: iommu_map+0x34/0x94 403.921157: ipa3_iommu_map+0x41c/0x75c [ipam] 403.921383: ipa3_smmu_map_peer_buff+0x1a4/0x6bc [ipam] 403.921591: ipa3_usb_smmu_map_xdci_channel+0x158/0x414 [ipa_clientsm] 403.921613: ipa3_usb_request_xdci_channel+0x46c/0x9a8 [ipa_clientsm] 403.921630: ipa_usb_xdci_connect_internal+0x2ac/0xe28 [ipa_clientsm] 403.921648: ipa_usb_xdci_connect+0x3c/0xd0 [ipa_fmwk] 403.921690: ipa_connect_channels+0x3c0/0x7c4 [usb_f_gsi] 403.921711: ipa_work_handler+0x7f8/0xbb4 [usb_f_gsi] 403.921730: process_one_work+0x254/0x5a0 403.921737: worker_thread+0x398/0x790 403.921741: kthread+0x168/0x1dc 403.921745: ret_from_fork+0x10/0x20 403.921751: Code: aa000184 aa030183 f1000842 91400800 (a93f8e24) 403.921755: ---[ end trace 40473a25e6f92a4e ]--- 403.921760: Kernel panic - not syncing: Oops: Fatal exception 403.921763: SMP: stopping secondary CPUs 403.921773: VendorHooks: CPU3: stopping 403.921789: CPU: 3 PID: 1406 Comm: kworker/u17:3 Tainted: G D W OE 5.15.168-android13-8-gc3eb426f91e1-dirty #1 403.921797: Hardware name: Qualcomm Technologies, Inc. KHAJE IDP nopmi (DT) 403.921804: Workqueue: fsverity_read_queue f2fs_verify_bio.cfi_jt 403.921818: pstate: 60400005 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) 403.921825: pc : super_cache_count+0xf4/0x244 403.921834: lr : super_cache_count+0x6c/0x244 403.921841: sp : ffffffc00f9eb390
最新发布
08-02
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值