msm8610 display driver analysis and otm8018b enable

1  interface for userspace

static struct fb_ops mdss_fb_ops = {
	.owner = THIS_MODULE,
	.fb_open = mdss_fb_open,
	.fb_release = mdss_fb_release,
	.fb_check_var = mdss_fb_check_var,	/* vinfo check */
	.fb_set_par = mdss_fb_set_par,	/* set the video mode */
	.fb_blank = mdss_fb_blank,	/* blank display */
	.fb_pan_display = mdss_fb_pan_display,	/* pan display */
	.fb_ioctl = mdss_fb_ioctl,	/* perform fb specific ioctl */
	.fb_mmap = mdss_fb_mmap,
};

static const struct dev_pm_ops mdss_fb_pm_ops = {
	SET_SYSTEM_SLEEP_PM_OPS(mdss_fb_pm_suspend, mdss_fb_pm_resume)
};

static const struct of_device_id mdss_fb_dt_match[] = {
	{ .compatible = "qcom,mdss-fb",},
	{}
};
EXPORT_COMPAT("qcom,mdss-fb");

static struct platform_driver mdss_fb_driver = {
	.probe = mdss_fb_probe,
	.remove = mdss_fb_remove,
	.suspend = mdss_fb_suspend,
	.resume = mdss_fb_resume,
	.shutdown = mdss_fb_shutdown,
	.driver = {
		.name = "mdss_fb",
		.of_match_table = mdss_fb_dt_match,
		.pm = &mdss_fb_pm_ops,
	},
};

2  panel related (dsi_panel_v2.c)

static int __devinit dsi_panel_probe(struct platform_device *pdev)
{
	int rc = 0;
	static struct dsi_panel_common_pdata vendor_pdata;
	static const char *panel_name;

	pr_debug("%s:%d, debug info id=%d", __func__, __LINE__, pdev->id);
	if (!pdev->dev.of_node)
		return -ENODEV;

	panel_name = of_get_property(pdev->dev.of_node, "label", NULL);
	if (!panel_name)
		pr_debug("%s:%d, panel name not specified\n",
						__func__, __LINE__);
	else
		pr_debug("%s: Panel Name = %s\n", __func__, panel_name);

	rc = dsi_panel_init();
	if (rc) {
		pr_err("dsi_panel_init failed %d\n", rc);
		goto dsi_panel_probe_error;

	}
	rc = dsi_panel_parse_dt(pdev, &vendor_pdata, &panel_private->bl_ctrl);
	if (rc) {
		pr_err("dsi_panel_parse_dt failed %d\n", rc);
		goto dsi_panel_probe_error;
	}

	vendor_pdata.on = dsi_panel_on; // panel on initial command
	vendor_pdata.off = dsi_panel_off; // panel off command
	vendor_pdata.reset = dsi_panel_reset; // panel reset
	vendor_pdata.bl_fnc = dsi_panel_bl_ctrl; // panel backlight control

	rc = dsi_panel_device_register_v2(pdev, &vendor_pdata,
					panel_private->bl_ctrl); // dsi_v2.c

	if (rc) {
		pr_err("dsi_panel_device_register_v2 failed %d\n", rc);
		goto dsi_panel_probe_error;
	}

	return 0;
dsi_panel_probe_error:
	dsi_panel_deinit();
	return rc;
}

static int __devexit dsi_panel_remove(struct platform_device *pdev)
{
	dsi_panel_deinit();
	return 0;
}


static const struct of_device_id dsi_panel_match[] = {
	{.compatible = "qcom,dsi-panel-v2"}, // the name is used for matching platform device(dtsi)
	{}
};

static struct platform_driver this_driver = {
	.probe  = dsi_panel_probe,
	.remove = __devexit_p(dsi_panel_remove),
	.driver = {
		.name = "dsi_v2_panel",
		.of_match_table = dsi_panel_match,
	},
};

static int __init dsi_panel_module_init(void)
{
	return platform_driver_register(&this_driver);
}
module_init(dsi_panel_module_init);

3  dsi of host and dsi engine

These functionality are in dsi_v2.c, as follow:
dsi_on
dsi_panel_handler
dsi

4  Enabling new lcd in lk

4.1 Add the following code in dev/panel/msm/rules.mk
ifeq ($(PLATFORM),msm8610)
OBJS += \
        $(LOCAL_DIR)/xx_mipi_otm8018b_video_fwvga.o \
        $(LOCAL_DIR)/mipi_otm8018b_video_fwvga.o \
        $(LOCAL_DIR)/mipi_truly_video_wvga.o \
        $(LOCAL_DIR)/mipi_truly_cmd_wvga.o
endif
4.2  Add the specfic initial funcition in target/msm8610/target_display.c in the corresponding function: display_init
void display_init(void)
{
	uint32_t hw_id = board_hardware_id();

	dprintf(SPEW, "display_init(),target_id=%d.\n", hw_id);

	switch (hw_id) {
	case HW_PLATFORM_QRD:
	case HW_PLATFORM_MTP:
	case HW_PLATFORM_SURF:
		mipi_truly_video_wvga_init(&(panel.panel_info)); 
		panel.clk_func = msm8610_mdss_dsi_panel_clock;
		panel.power_func = msm8610_mipi_panel_power;
		panel.fb.base = MIPI_FB_ADDR;
		panel.fb.width =  panel.panel_info.xres;
		panel.fb.height =  panel.panel_info.yres;
		panel.fb.stride =  panel.panel_info.xres;
		panel.fb.bpp =  panel.panel_info.bpp;
		panel.fb.format = FB_FORMAT_RGB888;
		panel.mdp_rev = MDP_REV_304;
		break;
	default:
		return;
	};

	if (msm_display_init(&panel)) // This function is the real initial function
	{
		dprintf(CRITICAL, "Display init failed!\n");
		return;
	}

	display_enable = 1;
}
msm_display_init, msm_display_off, msm_display_on, msm_display_config, msm_fb_alloc are in platform/msm_shared/display.c, dsi related is in  platform/msm_shared/mipi_dsi.c, such as  mipi_dsi_cmds_tx, mipi_dsi_cmd_bta_sw_trigger, mdss_dsi_panel_initialize, mdss_dsi_config, mipi_dsi_on, mipi_dsi_off and so on. mdp3 related is in platform/msm_shared/mdp3.c, mdp3.h, such as mdp_dsi_video_config, mdp_disable, mdp_set_version, mdp_dma_on, mdp_dsi_video_on , and so on.

4.3  Implement the functionality for the specific lcd
void mipi_booyi_video_fwvga_init(struct msm_panel_info *pinfo)
{
...
	pinfo->xres = BOOYI_CPT_FB_WIDTH;
	pinfo->yres = BOOYI_CPT_FB_HEIGHT;
	pinfo->mipi.mode = DSI_VIDEO_MODE;
	pinfo->mipi.traffic_mode = 1;
	pinfo->mipi.dst_format = DSI_VIDEO_DST_FORMAT_RGB888;
	pinfo->mipi.mdss_dsi_phy_db = &dsi_video_mode_phy_db;
	pinfo->mipi.tx_eot_append = TRUE;

	pinfo->mipi.lane_swap = 1;
...
}
int mipi_panel_video_fwvga_config(void *pdata)
{
...
	ret = mdss_dsi_video_mode_config((pinfo->xres),
			(pinfo->yres),
			(pinfo->xres),
			(pinfo->yres),
			(lcdc->h_front_porch),
			(lcdc->h_back_porch),
			(lcdc->v_front_porch),
			(lcdc->v_back_porch),
			(lcdc->h_pulse_width),
			(lcdc->v_pulse_width),
			pinfo->mipi.dst_format,
			pinfo->mipi.traffic_mode,
			lane_en,
			low_pwr_stop_mode,
			eof_bllp_pwr,
			interleav,
			MIPI_DSI0_BASE);
	return ret;
}

4.4  Show green color in lk
static void show_color(unsigned int x, unsigned int y,
							unsigned char pixel[4])
{
	unsigned int i = 0;
	unsigned int j = 0;

	for (i = y; i < (y + config->height); i++) {
		for (j = x; j < (x + config->width); j++) {
			/* B */
			*((unsigned char *)((int)config->base +
					(i * config->width + j) * 3) + 0) = pixel[0];
			/* G */
			*((unsigned char *)((int)config->base +
					(i * config->width + j) * 3) + 1) = pixel[1];
			   /* R */
			*((unsigned char *)((int)config->base +
					(i * config->width + j) * 3) + 2) = pixel[2];
		}
	}
}

void show_green_color(unsigned int x, unsigned int y)
{
	unsigned char pixel[4];

	/* green */
	pixel[0] = 0x00;   /* B */
	pixel[1] = 0xFF;   /* G */
	pixel[2] = 0x00;   /* R */
	pixel[3] = 0xFF;   /* A */

	show_color(x, y, pixel);
}

5  Remember that dsi timing and lane swap are quite important

If dsi timing is wrong, normally, lcd can't show any picture, it would remain white or black. The timing and other parameters can be got from an excel from qualcomm. Sometimes lane is swapped, because these lanes maybe connect oppositely. So if sometimes lcd can't show any picture, the lane between host and driver ic is maybe opposite.

6  The commands for initialize lcd can be defined as following

#define CMD(cnt, len, cmds...) \
static char booyi_disp_init##cnt[len] = { \
	cmds \
}

#define INSERT(cnt, wait) \
{ sizeof(booyi_disp_init##cnt), booyi_disp_init##cnt, wait }

7  dsi bit/core/byte/pixel clk calculation

void dsi_calc_clk_rate(uint32_t *dsiclk_rate, uint32_t *byteclk_rate)
{
	uint32_t hbp, hfp, vbp, vfp, hspw, vspw, width, height;
	uint32_t bitclk_rate;
	int frame_rate, lanes;

	width = panel.panel_info.xres;
	height = panel.panel_info.yres;
	hbp = panel.panel_info.lcdc.h_back_porch;
	hfp = panel.panel_info.lcdc.h_front_porch;
	hspw = panel.panel_info.lcdc.h_pulse_width;
	vbp = panel.panel_info.lcdc.v_back_porch;
	vfp = panel.panel_info.lcdc.v_front_porch;
	vspw = panel.panel_info.lcdc.v_pulse_width;
	lanes = panel.panel_info.mipi.num_of_lanes;
	frame_rate = panel.panel_info.mipi.frame_rate;

	bitclk_rate = (width + hbp + hfp + hspw) * (height + vbp + vfp + vspw);
	bitclk_rate *= frame_rate;
	bitclk_rate *= panel.panel_info.bpp;
	bitclk_rate /= lanes;

	*byteclk_rate = bitclk_rate / 8;
	*dsiclk_rate = *byteclk_rate * lanes;
}
8
root@xx:/sys/class/leds # ll
lrwxrwxrwx root     root              2009-01-02 13:00 button-backlight -> ../../devices/leds-qpnp-d8b0de00/leds/button-
backlight
lrwxrwxrwx root     root              1970-01-02 15:13 flashlight -> ../../devices/qcom,leds-gpio-flash.57/leds/flashlig
ht
lrwxrwxrwx root     root              2009-01-02 13:00 lcd-backlight -> ../../devices/fd900000.qcom,mdss_mdp/qcom,mdss_f
b_primary.119/leds/lcd-backlight
lrwxrwxrwx root     root              1970-01-02 15:13 mmc0:: -> ../../devices/msm_sdcc.1/leds/mmc0::
lrwxrwxrwx root     root              1970-01-02 15:13 mmc1:: -> ../../devices/msm_sdcc.2/leds/mmc1::
lrwxrwxrwx root     root              1970-01-02 15:13 rgb -> ../../devices/leds-qpnp-d8b10000/leds/rgb

root@xx:/sys/class/graphics/fb0 # ll
-rw-r--r-- root     root         4096 1970-01-02 15:13 bits_per_pixel // 32bits
-rw-r--r-- root     root         4096 1970-01-02 15:13 blank // 
-rw-r--r-- root     root         4096 1970-01-02 15:13 console
-rw-r--r-- root     root         4096 1970-01-02 15:13 cursor
-r--r--r-- root     root         4096 1970-01-02 15:13 dev
-rw-r--r-- root     root         4096 1970-01-02 15:13 mode
-rw-r--r-- root     root         4096 1970-01-02 15:13 modes // U:480*854p-5
-r--r--r-- root     root         4096 1970-01-02 15:13 msm_fb_split
-r--r--r-- root     root         4096 1970-01-01 01:28 msm_fb_type // mipi dsi video panel
-r--r--r-- root     root         4096 1970-01-02 15:13 name // mdss_fb_80000
-rw-r--r-- root     root         4096 1970-01-02 15:13 pan
drwxr-xr-x root     root              1970-01-01 01:28 power
-rw-r--r-- root     root         4096 1970-01-02 15:13 rotate
-r--r--r-- root     root         4096 1970-01-02 15:13 show_blank_event // panel_power_on = 0
-rw-r--r-- root     root         4096 1970-01-02 15:13 state
-r--r--r-- root     root         4096 1970-01-02 15:13 stride
lrwxrwxrwx root     root              1970-01-02 15:13 subsystem -> ../../../../class/graphics
-rw-r--r-- root     root         4096 1970-01-01 01:28 uevent
-rw-r--r-- root     root         4096 1970-01-02 15:13 virtual_size // 480, 1708
-r--r--r-- root     root         4096 1970-01-01 01:28 vsync_event

root@xx:/sys/devices/soc0 # ll
-r--r--r-- root     root         4096 1970-01-02 15:23 accessory_chip
-r--r--r-- root     root         4096 1970-01-02 15:23 build_id // 8x10A-DAAAANAZA-40000000
-r--r--r-- root     root         4096 1970-01-01 01:28 hw_platform
-r--r--r-- root     root         4096 1970-01-02 15:23 machine // Snapdragon
-r--r--r-- root     root         4096 1970-01-02 15:23 platform_subtype
-r--r--r-- root     root         4096 1970-01-01 01:28 platform_version
-r--r--r-- root     root         4096 1970-01-02 15:23 pmic_die_revision
-r--r--r-- root     root         4096 1970-01-02 15:23 pmic_model
drwxr-xr-x root     root              1970-01-02 15:23 power
-r--r--r-- root     root         4096 1970-01-02 15:23 raw_id
-r--r--r-- root     root         4096 1970-01-02 15:23 raw_version
-r--r--r-- root     root         4096 1970-01-02 15:23 revision // 1.1
-r--r--r-- root     root         4096 1970-01-01 01:28 soc_id // 162
lrwxrwxrwx root     root              1970-01-02 15:23 subsystem -> ../../bus/soc
-rw-r--r-- root     root         4096 1970-01-02 15:23 uevent
-r--r--r-- root     root         4096 1970-01-02 15:23 vendor // qualcomm

root@xx:/sys/devices/fd900000.qcom,mdss_mdp # ll
lrwxrwxrwx root     root              1970-01-02 15:27 driver -> ../../bus/platform/drivers/mdp3
-r--r--r-- root     root         4096 1970-01-02 15:27 modalias
drwxr-xr-x root     root              1970-01-01 01:28 power
drwxr-xr-x root     root              1970-01-01 01:28 qcom,mdss_fb_primary.119
lrwxrwxrwx root     root              1970-01-02 15:27 subsystem -> ../../bus/platform
-rw-r--r-- root     root         4096 1970-01-01 01:28 uevent
root@VodafoneSmart4:/sys/devices/fd900000.qcom,mdss_mdp # cat uevent
DRIVER=mdp3
OF_NAME=qcom,mdss_mdp
OF_FULLNAME=/soc/qcom,mdss_mdp@fd900000
OF_COMPATIBLE_0=qcom,mdss_mdp3
OF_COMPATIBLE_N=1
MODALIAS=of:Nqcom,mdss_mdpT<NULL>Cqcom,mdss_mdp3

# mount -t debugfs debugfs /sys/kernel/debug
root@xx:/sys/kernel/debug/ion # ll
-rw-rw-r-- root     root            0 1970-01-01 01:28 250
-rw-rw-r-- root     root            0 1970-01-02 15:33 4080
-rw-rw-r-- root     root            0 1970-01-02 15:33 4083
-rw-rw-r-- root     root            0 1970-01-01 01:28 415
-rw-rw-r-- root     root            0 2009-01-02 13:00 adsprpc-smd
-rw-rw-r-- root     root            0 1970-01-02 15:33 audio_acdb_client
-rw-rw-r-- root     root            0 1970-01-02 15:33 audio_client
-rw-rw-r-- root     root            0 1970-01-01 00:00 fd900000.qcom,mdss_mdp
-rw-rw-r-- root     root            0 1970-01-01 00:00 iommu
-rw-rw-r-- root     root            0 1970-01-01 00:00 kmalloc
-rw-rw-r-- root     root            0 1970-01-01 00:00 pil
-rw-rw-r-- root     root            0 1970-01-01 00:00 pil_1
-rw-rw-r-- root     root            0 1970-01-01 00:00 pil_2
-rw-rw-r-- root     root            0 1970-01-01 00:00 qsecom
-rw-rw-r-- root     root            0 1970-01-01 00:00 qsee_log
-rw-rw-r-- root     root            0 1970-01-01 00:00 qseecom-kernel
-rw-rw-r-- root     root            0 1970-01-01 00:00 vmalloc
-rw-rw-r-- root     root            0 1970-01-01 01:28 voc_cal
-rw-rw-r-- root     root            0 1970-01-01 01:28 voip_client

root@xx:/sys/kernel/debug/ion # cat fd900000.qcom*
cat fd900000.qcom*
       heap_name:    size_in_bytes :  handle refcount :       buffer
           iommu:           195000 :                1 :     d7144100 // decimal size is 1658880, actual size is 1639680. need to align
           iommu:           195000 :                1 :     d27d6780

root@VodafoneSmart4:/sys/kernel/debug/ion # cat iommu
          client              pid             size
----------------------------------------------------
            init                1             8192
fd900000.qcom,mdss_mdp                1          3317760 // Total framebuffer decimal size
----------------------------------------------------
orphaned allocations (info is from last known client):
        Binder_2              250          1658880 0 1
        Binder_2              250          1658880 0 1
        Binder_2              250          1658880 0 1
----------------------------------------------------
  total orphaned          4976640
          total           8302592
----------------------------------------------------
Cached Pools:
0 order 9 highmem pages in pool = 0 total
0 order 9 lowmem pages in pool = 0 total
0 order 8 highmem pages in pool = 0 total
0 order 8 lowmem pages in pool = 0 total
0 order 4 highmem pages in pool = 0 total
0 order 4 lowmem pages in pool = 0 total
0 order 0 highmem pages in pool = 0 total
1971 order 0 lowmem pages in pool = 7b3000 total
Uncached Pools:
0 order 9 highmem pages in pool = 0 total
0 order 9 lowmem pages in pool = 0 total
0 order 8 highmem pages in pool = 0 total
1 order 8 lowmem pages in pool = 100000 total
0 order 4 highmem pages in pool = 0 total
59 order 4 lowmem pages in pool = 3b0000 total
0 order 0 highmem pages in pool = 0 total
42 order 0 lowmem pages in pool = 2a000 total
Total bytes in pool: c8d000



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值