该系列文章总目录链接与各部分简介: Android Qcom Display学习(零)
本章主要是基于MIPI Payload传输接口的学习,包括Generic和DCS的接口不同。
底层都是基于dsi_ctrl_cmd_transfer去封装的,下面第一部分调用原生接口,第二部分分析高通是如何进行读写操作的
MIPI Generic和DCS指令的区别在于DCS会将CMD作为data[0]传入,即使根据size的type会有不同,但到最后还是只有两类
mipi_dsi_packet_format_is_short or mipi_dsi_packet_format_is_long,DCS会有标准命令集,理论上Generic应该是兼容,为了一些屏客制化的部分。
mipi_dsi_generic_write/mipi_dsi_generic_read \
—— mipi_dsi_device_transfer —— dsi_host_transfer —— dsi_ctrl_cmd_transfer
mipi_dsi_dcs_read/mipi_dsi_dcs_write /
Generic:
mipi_dsi_generic_write(dsi, (u8[]){0xB0, 0x00}, 2);
struct mipi_dsi_msg msg = {
.channel = dsi->channel,
.tx_buf = data,
.tx_len = len
};
msg.type = MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM; size = 2
DCS:
u8 payload[2] = { brightness & 0xff, brightness >> 8 };
mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_BRIGHTNESS, payload, sizeof(payload));
size = len + 1;
t[0] = cmd; //data[0] 作为cmd
memcpy(&tx[1], data, len);
msg.type = MIPI_DSI_DCS_LONG_WRITE; //size = 3
DCS标准化命令集 /* MIPI DCS commands */
MIPI_DCS_SET_DISPLAY_BRIGHTNESS = 0x51, 适用于OLED等CMD屏 DCS控制背光 bl_ctrl_dcs
(1)测试Generic的函数接口,发现没有值返回
u8 data = 0;
u8 data2 = 0;
rc = mipi_dsi_generic_read(&(display->panel->mipi_device), (u8[]) {0x0A} , 1, &data, sizeof(data) );
rc = mipi_dsi_dcs_read(&(display->panel->mipi_device), (u8) 0x0A, &data2, 1); //MIPI_DCS_GET_POWER_MODE
(2)发现在dsi_ctrl_cmd_transfer中有用cmd_flags DSI_CTRL_CMD_READ区分读写操作,高通的接口中dsi_display_read_status有设
dsi_host_transfer
if(*(u8 *)msg->tx_buf == 0x0A){
cmd_flags |= DSI_CTRL_CMD_READ | DSI_CTRL_CMD_CUSTOM_DMA_SCHED | DSI_CTRL_CMD_FETCH_MEMORY ;
}
dsi_ctrl_cmd_transfer
所以在dsi_ctrl_cmd_transfer函数前传入带DSI_CTRL_CMD_READ的cmd_flags
(3)两个接口返回的值出现不同,在dsi_message_rx中进行分析
mipi_dsi_generic_read
返回的packet 0x11 0x9D 0x9D 0x1B MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE = 0x11,
mipi_dsi_dcs_read
返回的packet 0x0A 0x9D 0xEB 0x40 data[0] 是返回的响应,这里会返回一个error无法解析到0x9D
dsi_display_read_status
返回的packet 0x1C 0x03 0x00 0x16 0x9D 0x9D MIPI_DSI_RX_DCS_LONG_READ_RESPONSE = 0x1c,
data[0] 是返回的响应 ,mipi_dsi_dcs_read返回的响应值0x0A,没有对应的响应,与mipi_dsi_generic_read相比就msg->type不同(将mipi_dsi_dcs_read的msg->type与mipi_dsi_generic_read保持一致,现象同mipi_dsi_generic_read一致没问题,可以正常读取);与dsi_display_read_status(rx_len = 3 FAE提供的 qcom,mdss-dsi-panel-status-read-length )相比就rx_len不同,虽然说都能读到0x9D,无法解析,将dsi_display_read_status (rx_len = 1) 也会出现mipi_dsi_dcs_read的现象,esd返回值有问题导致一直闪屏, 后续换了不同IC厂商的屏幕,调用接口未发现上述的问题,就这个屏调用mipi_dsi_dcs_read返回的data[0]一直是0x0A。
(1)parse dtsi
mdss_panel_parse_dt -> mdss_panel_parse_display_timings -> mdss_dsi_panel_config_res_properties
mdss_dsi_parse_dcs_cmds(np, &pt->on_cmds, "qcom,mdss-dsi-on-command",
(2)map cmd type to dtsi and packet
dsi_panel_parse_cmd_sets -> dsi_panel_parse_cmd_sets_sub -> dsi_panel_create_cmd_packets ↓↓↓
dsi_cmd_set_type —— cmd_set_prop_map
DSI_CMD_SET_ON "qcom,mdss-dsi-on-command"
(3)set settings
dsi_panel_enable type = DSI_CMD_SET_ON
dsi_panel_tx_cmd_set —— dsi_host_transfer —— dsi_ctrl_cmd_transfer
以qcom,mdss-dsi-on-command第一组setting为例子
39 01 00 00 00 00 04 B9 FF 83 99
cmd.msg.type = data[0] = DCS Long Write 39 cmd type
cmd.last_command = (data[1] == 1) 01 flags MIPI_DSI_MSG_LASTCOMMAND 区分独立包
cmd.msg.channel = data[2]; 00 dsi_panel_drv_init channel = 0
cmd.msg.flag | = data[3]; 00 flags MIPI_DSI_MSG_USE_LPM LP Mode传输
cmd.post.wait_ms = data[4]; 00 delay time
cmd.msg.tx_len = (data[5]<<8 | data[6]) 04 payload size
for (j = 0; j < cmd[i].msg.tx_len; j++)
payload[j] = data[7 + j]; B9 FF 83 99 payload data
cmd[i].msg.tx_buf = payload;
plane的更新只发生在crtc enable被启动的过程,所以在sde_crtc_enable中调度workqueue,
sde_crtc_enable
sde_connector_schedule_status_work(cstate->connectors[i], true);
schedule_delayed_work(&c_conn->status_work, msecs_to_jiffies(interval));
sde_connector_check_status_work
dsi_display_check_status
dsi_display_status_reg_read
dsi_display_validate_status
dsi_display_read_status
dsi_display_validate_reg_read
其中注意
dsi_display_read_status —— dsi_ctrl_cmd_transfer (payload transfer flow)
中断处理esd的问题,检测到状态不对后执行soft_reset进行复位
dsi_ctrl_isr ddevm_request_threaded_irq
dsi_ctrl_handle_error_status
dsi_ctrl->hw.ops.soft_reset(&dsi_ctrl->hw);
这个一般还是需要原厂进行支持,需要注意的就是格式个数对应,以免esd check的流程中出现问题
devicetree
qcom,esd-check-enabled;
qcom,mdss-dsi-panel-status-check-mode="reg_read";
qcom,mdss-dsi-panel-status-command = [
06 01 00 01 05 00 01 09
06 01 00 01 05 00 01 68];
qcom,mdss-dsi-panel-status-command-state = "dsi_lp_mode";
qcom,mdss-dsi-panel-status-value = <0x80 0x73 0x04>, <0xC0>;
qcom,mdss-dsi-panel-status-read-length = <3 1>;
qcom,mdss-dsi-panel-max-error-count = <2>;