HI WayneWWW,
I use command #cat /sys/kernel/debug/tegra_dsi/read_panel
Return result:
max ret payload size:0x4
panel reg addr:0xc9
read 0 read 0 read 0 read 0 read 0 read 0 read 0 read 0 read 0 read 0 read 0
Read data[0] 0 0 0 0
Invalid read response
Invalid response packet.
read 0 is the result I print, every byte.
According to Mipi protocol, the first byte should be 0x87, but we are 0, and the other bytes are not correct.
In addition, in order to eliminate image interference, I temporarily deleted gdm3, which means that Ubuntu interface will not be generated when the system is started.
We test our mobile screen. The steps are as follows: first send 0xbd, 0x00. Then send the payload size 4 and the read command 0xc9. We use other platforms to send data according to the above steps, read 0xc9, and the result can return to the normal read value. I used Mipi analyzer to grab the data sent by both of them, including the written data graphs of 0xbd, 4 and 0xc9.The waveform data written by the two devices is exactly the same.
In addition, 0xc9 is the NVIDIA, DSI init CMD used when the mobile screen starts. Here are some initialization commands that I can drive this mobile screen: NVIDIA, DSI init CMD=
<TEGRA_DSI_PACKET_CMD DSI_DCS_LONG_WRITE 0x04 0x0 0x0 0xB9 0x83 0x10 0x2D 0x0 0x0>,
<TEGRA_DSI_PACKET_CMD DSI_DCS_LONG_WRITE 0x0f 0x0 0x0 0xB1 0x22 0x44 0x31 0x31 0x22 0x34 0x2F 0x57 0x08 0x08 0x08 0x67 0x67 0x71 0x0 0x0>,
<TEGRA_DSI_PACKET_CMD DSI_DCS_LONG_WRITE 0x04 0x0 0x0 0xD3 0x01 0x00 0x39 0x0 0x0>,
<TEGRA_DSI_PACKET_CMD DSI_DCS_WRITE_1_PARAM 0xBD 0x00 0x00>,
<TEGRA_DSI_PACKET_CMD DSI_DCS_LONG_WRITE 0x05 0x0 0x0 0xC9 0x04 0x65 0x90 0x01 0x0 0x0>,
we read 0xC9 Should return 0x04 0x65 0x90 0x01. At least one return correct ID 0x87 appears.
But it fails.
##cat /sys/kernel/debug/tegra_dsi/read_panel
It actually calls the following functions.
static u32 max_ret_payload_size = 4;
static u32 panel_reg_addr = 0xc9;
static int read_panel_get(struct seq_file *s, void *unused)
{
struct tegra_dc_dsi_data *dsi = s->private;
struct tegra_dc *dc = dsi->dc;
int err = 0;
u8 buf[MAX_PANEL_REG_READ_SIZE] = {0};
int j = 0 , b = 0 , k,i=0;
u32 payload_size = 0;
u8 del = 100;
struct tegra_dsi_cmd user_command[] = {
DSI_CMD_SHORT(0x15, 0xBD, 0x00),
//DSI_DLY_MS(20),
};
if (!dsi->enabled) {
dev_info(&dc->ndev->dev, " controller suspended\n");
return -EINVAL;
}
seq_printf(s, "max ret payload size:0x%x\npanel reg addr:0x%x\n",
max_ret_payload_size, panel_reg_addr);
if ((max_ret_payload_size > MAX_PANEL_REG_READ_SIZE) ||
(max_ret_payload_size == 0)) {
seq_printf(s, "max reg payload size should be a positive value below 0x%x\n",
MAX_PANEL_REG_READ_SIZE);
return err;
}
//seq_printf(s, "data_id taken :0x%x\n", data_id);
//seq_printf(s, "command value taken :0x%x\n", command_value);
//seq_printf(s, "second command value taken :0x%x\n", command_value1);
err = tegra_dsi_write_data(dc, dsi, user_command, del);
err = tegra_dsi_read_data(dsi->dc, dsi,
max_ret_payload_size,
panel_reg_addr, buf);
for (i = 0; i < 11; i++) {
seq_printf(s, "read %x ", buf[i]);
}
for (b = 0; b < max_ret_payload_size; b += 4) {
seq_printf(s, "\n Read data[%d] ", j++);
for (k = b+4; k > b; k--)
seq_printf(s, " %x ", buf[k-1]);
}
seq_puts(s, "\n");
switch (buf[0]) {
case DSI_ESCAPE_CMD:
seq_printf(s, "escape cmd[0x%x]\n", buf[0]);
break;
case DSI_ACK_NO_ERR:
seq_printf(s,
"Panel ack, no err[0x%x]\n", buf[0]);
goto fail;
break;
default:
seq_puts(s, "Invalid read response\n");
break;
}
switch (buf[4] & 0xff) {
case GEN_LONG_RD_RES:
/* Fall through */
case DCS_LONG_RD_RES:
payload_size = (buf[5] |
(buf[6] << 8)) & 0xFFFF;
seq_printf(s, "Long read response Packet\n"
"payload_size[0x%x]\n", payload_size);
break;
case GEN_1_BYTE_SHORT_RD_RES:
/* Fall through */
case DCS_1_BYTE_SHORT_RD_RES:
payload_size = 1;
seq_printf(s, "Short read response Packet\n"
"payload_size[0x%x]\n", payload_size);
break;
case GEN_2_BYTE_SHORT_RD_RES:
/* Fall through */
case DCS_2_BYTE_SHORT_RD_RES:
payload_size = 2;
seq_printf(s, "Short read response Packet\n"
"payload_size[0x%x]\n", payload_size);
break;
case ACK_ERR_RES:
payload_size = 2;
seq_printf(s, "Acknowledge error report response\n"
"Packet payload_size[0x%x]\n", payload_size);
break;
default:
seq_puts(s, "Invalid response packet\n");
break;
}
fail:
return err;
}
/////////////////////////
int tegra_dsi_read_data(struct tegra_dc *dc,
struct tegra_dc_dsi_data *dsi,
u16 max_ret_payload_size,
u8 panel_reg_addr, u8 *read_data)
{
int err = 0;
struct dsi_status *init_status;
static struct tegra_dsi_cmd temp_cmd;
if (!dsi->enabled) {
dev_err(&dc->ndev->dev, "DSI controller suspended\n");
return -EINVAL;
}
tegra_dc_dsi_hold_host(dc);
mutex_lock(&dsi->lock);
tegra_dc_io_start(dc);
if (dsi->dsi_fixed_clk)
tegra_disp_clk_prepare_enable(dsi->dsi_fixed_clk);
tegra_dsi_lp_clk_enable(dsi);
init_status = tegra_dsi_prepare_host_transmission(
dc, dsi, DSI_LP_OP_WRITE);
if (IS_ERR_OR_NULL(init_status)) {
dev_err(&dc->ndev->dev, "DSI host config failed\n");
goto fail;
}
/* Set max return payload size in words */
temp_cmd.data_id = dsi_command_max_return_pkt_size;
temp_cmd.sp_len_dly.data_len = max_ret_payload_size;
err = _tegra_dsi_write_data(dsi, &temp_cmd);
if (err < 0) {
dev_err(&dc->ndev->dev,
"DSI write failed\n");
goto fail;
}
/* DCS to read given panel register */
temp_cmd.data_id = dsi_command_dcs_read_with_no_params;
temp_cmd.sp_len_dly.sp.data0 = panel_reg_addr;
temp_cmd.sp_len_dly.sp.data1 = 0;
err = _tegra_dsi_write_data(dsi, &temp_cmd);
if (err < 0) {
dev_err(&dc->ndev->dev,
"DSI write failed\n");
goto fail;
}
tegra_dsi_reset_read_count(dsi);
if (dsi->status.lp_op == DSI_LP_OP_WRITE) {
err = tegra_dsi_set_to_lp_mode(dc, dsi, DSI_LP_OP_READ);
if (err < 0) {
dev_err(&dc->ndev->dev,
"DSI failed to go to LP read mode\n");
goto fail;
}
}
err = tegra_dsi_bta(dsi);
if (err < 0) {
dev_err(&dc->ndev->dev,
"DSI IMM BTA timeout\n");
goto fail;
}
err = tegra_dsi_read_fifo(dc, dsi, read_data);
if (err < 0) {
dev_err(&dc->ndev->dev, "DSI read fifo failure\n");
goto fail;
}
fail:
err = tegra_dsi_restore_state(dc, dsi, init_status);
if (err < 0)
dev_err(&dc->ndev->dev, "Failed to restore prev state\n");
tegra_dsi_lp_clk_disable(dsi);
if (dsi->dsi_fixed_clk)
tegra_disp_clk_disable_unprepare(dsi->dsi_fixed_clk);
tegra_dc_io_end(dc);
mutex_unlock(&dsi->lock);
tegra_dc_dsi_release_host(dc);
return err;
}
Thanks!!