mipi接口连接如下(图中没包括供电和复位信号)
三种不同的时序
Non-Burst Mode with Sync Pulses
Non-Burst Mode with Sync Events
Burst Mode (比较常见)
HSS:Horizontal Sync Start
HSE:Horizontal Sync End
HSA:Horizontal Sync Active
VSA:Vertical Sync Active
VSE:Vertical Sync End
VSS:Vertical Sync Start
如0x29开显示,0x28关显示
LP模式下,命令的类型
写命令分为dcs和generic两种,比较常见的是dcs,如展讯平台的lcd初始化流程
static int sprd_panel_send_cmds(struct mipi_dsi_device *dsi,
const void *data, int size)
{
struct sprd_panel *panel;
const struct dsi_cmd_desc *cmds = data;
u16 len;
if ((cmds == NULL) || (dsi == NULL))
return -EINVAL;
panel = mipi_dsi_get_drvdata(dsi);
while (size > 0) {
len = (cmds->wc_h << 8) | cmds->wc_l;
if (panel->info.use_dcs)
mipi_dsi_dcs_write_buffer(dsi, cmds->payload, len);
else
mipi_dsi_generic_write(dsi, cmds->payload, len);
if (cmds->wait)
msleep(cmds->wait);
cmds = (const struct dsi_cmd_desc *)(cmds->payload + len);
size -= (len + 4);
}
return 0;
}
/**
* mipi_dsi_dcs_write_buffer() - transmit a DCS command with payload
* @dsi: DSI peripheral device
* @data: buffer containing data to be transmitted
* @len: size of transmission buffer
*
* This function will automatically choose the right data type depending on
* the command payload length.
*
* Return: The number of bytes successfully transmitted or a negative error
* code on failure.
*/
ssize_t mipi_dsi_dcs_write_buffer(struct mipi_dsi_device *dsi,
const void *data, size_t len)
{
struct mipi_dsi_msg msg = {
.channel = dsi->channel,
.tx_buf = data,
.tx_len = len
};
switch (len) {
case 0:
return -EINVAL;
case 1:
msg.type = MIPI_DSI_DCS_SHORT_WRITE;
break;
case 2:
msg.type = MIPI_DSI_DCS_SHORT_WRITE_PARAM;
break;
default:
msg.type = MIPI_DSI_DCS_LONG_WRITE;
break;
}
return mipi_dsi_device_transfer(dsi, &msg);
}
/**
* mipi_dsi_generic_write() - transmit data using a generic write packet
* @dsi: DSI peripheral device
* @payload: buffer containing the payload
* @size: size of payload buffer
*
* This function will automatically choose the right data type depending on
* the payload length.
*
* Return: The number of bytes transmitted on success or a negative error code
* on failure.
*/
ssize_t mipi_dsi_generic_write(struct mipi_dsi_device *dsi, const void *payload,
size_t size)
{
struct mipi_dsi_msg msg = {
.channel = dsi->channel,
.tx_buf = payload,
.tx_len = size
};
switch (size) {
case 0:
msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM;
break;
case 1:
msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM;
break;
case 2:
msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM;
break;
default:
msg.type = MIPI_DSI_GENERIC_LONG_WRITE;
break;
}
return mipi_dsi_device_transfer(dsi, &msg);
}
MIPI_DSI_DCS_SHORT_WRITE = 0x05,
MIPI_DSI_DCS_SHORT_WRITE_PARAM = 0x15,
MIPI_DSI_DCS_LONG_WRITE = 0x39,
MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM = 0x03,
MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM = 0x13,
MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM = 0x23,
MIPI_DSI_GENERIC_LONG_WRITE = 0x29,
如
05 78 00 01 29
15 00 00 02 41 5A
39 00 00 03 41 5A 03
13 0a 00 01 29
23 00 00 02 FF 01
29 00 00 03 51 FF 00
static ssize_t mipi_dsi_device_transfer(struct mipi_dsi_device *dsi,
struct mipi_dsi_msg *msg)
{
const struct mipi_dsi_host_ops *ops = dsi->host->ops;
if (!ops || !ops->transfer)
return -ENOSYS;
if (dsi->mode_flags & MIPI_DSI_MODE_LPM)
msg->flags |= MIPI_DSI_MSG_USE_LPM;
return ops->transfer(dsi->host, msg);
}
/**
* Send a packet on the generic interface
* @param dsi pointer to structure holding the DSI Host core information
* @param vc destination virtual channel
* @param data_type type of command, inserted in first byte of header
* @param params byte array of command parameters
* @param param_length length of the above array
* @return error code
* @note this function has an active delay to wait for the buffer to clear.
* The delay is limited to:
* (param_length / 4) x DSIH_FIFO_ACTIVE_WAIT x register access time
* @note the controller restricts the sending of .
* This function will not be able to send Null and Blanking packets due to
* controller restriction
*/
int sprd_dsi_wr_pkt(struct sprd_dsi *dsi, u8 vc, u8 type,
const u8 *param, u16 len)
{
int i = 0;
int j = 0;
u32 payload;
u8 wc_lsbyte, wc_msbyte;
if (vc > 3)
return -EINVAL;
/* 1st: for long packet, must config payload first */
if (!dsi_hal_wait_tx_payload_fifo_empty(dsi))
return -1;
if (len > 2) {
for (i = 0; i < len; i += j) {
payload = 0;
for (j = 0; (j < 4) && ((j + i) < (len)); j++)
payload |= param[i + j] << (j * 8);
dsi_hal_set_packet_payload(dsi, payload);
}
wc_lsbyte = len & 0xff;
wc_msbyte = len >> 8;
} else {
wc_lsbyte = (len > 0) ? param[0] : 0;
wc_msbyte = (len > 1) ? param[1] : 0;
}
/* 2nd: then set packet header */
if (!dsi_hal_wait_tx_cmd_fifo_empty(dsi))
return -EINVAL;
dsi_hal_set_packet_header(dsi, vc, type, wc_lsbyte, wc_msbyte);
return 0;
}
static ssize_t sprd_dsi_host_transfer(struct mipi_dsi_host *host,
const struct mipi_dsi_msg *msg)
{
struct sprd_dsi *dsi = host_to_dsi(host);
const u8 *tx_buf = msg->tx_buf;
if (msg->rx_buf && msg->rx_len) {
u8 lsb = (msg->tx_len > 0) ? tx_buf[0] : 0;
u8 msb = (msg->tx_len > 1) ? tx_buf[1] : 0;
return sprd_dsi_rd_pkt(dsi, msg->channel, msg->type,
msb, lsb, msg->rx_buf, msg->rx_len);
}
if (msg->tx_buf && msg->tx_len)
return sprd_dsi_wr_pkt(dsi, msg->channel, msg->type,
tx_buf, msg->tx_len);
return 0;
}
static const struct mipi_dsi_host_ops sprd_dsi_host_ops = {
.transfer = sprd_dsi_host_transfer,
};
从lti8998c摘录的dcs写格式
DCSWN-S(DCS write 短包没参数)
DCSW1-S (DCS write 短包一个参数)
DCSW-L(DCS write 长包带参数)
遇到屏幕不显示的情况,可以检查下上电时序(同时确保有电压输出),配置是否有写错。另外可以使用屏幕的自测模式来排查问题。还有些是硬件问题,比如lcd的fpc不对应,导致信号没有输送到屏幕的引脚,或者fpc接口接触不良(可以尝试按压或者将fpc往前推下)。