disp: msm: dp: add debug node to capture source and sink crc

This change adds a debug node named 'crc' to drm_dp to read
the frame CRC values for DP controller and DP Sink. In order
to facilitate the immediate read of the CRC values when
accessed, it enables the CRC calculation on the controller
and sink automatically when the stream is enabled. In addition
to the frame CRC values it also reads the MISR values from
controller and PHY to validate the data flow from controller
to PHY.

Change-Id: I1acee2dba931e4635caf4a400e336a72c86e88bf
Signed-off-by: Rajkumar Subbiah <quic_rsubbia@quicinc.com>
This commit is contained in:
Rajkumar Subbiah
2022-04-12 11:13:55 -04:00
committad av Gerrit - the friendly Code Review server
förälder 51775dd093
incheckning 7eef92843d
9 ändrade filer med 332 tillägg och 1 borttagningar

Visa fil

@@ -333,7 +333,7 @@ static ssize_t dp_debug_read_dpcd(struct file *file,
}
}
len += scnprintf(buf + len , buf_size - len, "%04x: ", debug->dpcd_offset);
len += scnprintf(buf + len, buf_size - len, "%04x: ", debug->dpcd_offset);
while (offset < debug->dpcd_size)
len += scnprintf(buf + len, buf_size - len, "%02x ", dpcd[offset++]);
@@ -351,6 +351,90 @@ bail:
return len;
}
static ssize_t dp_debug_read_crc(struct file *file, char __user *user_buff, size_t count,
loff_t *ppos)
{
struct dp_debug_private *debug = file->private_data;
char *buf;
int const buf_size = SZ_4K;
u32 len = 0;
u16 src_crc[3] = {0};
u16 sink_crc[3] = {0};
struct dp_misr40_data misr40 = {0};
u32 retries = 2;
struct drm_connector *drm_conn;
struct sde_connector *sde_conn;
struct dp_panel *panel;
int i;
int rc;
if (!debug || !debug->aux)
return -ENODEV;
if (*ppos)
return 0;
buf = kzalloc(buf_size, GFP_KERNEL);
if (!buf)
return -ENOMEM;
mutex_lock(&debug->lock);
if (!debug->panel || !debug->ctrl)
goto bail;
if (debug->panel->mst_state) {
drm_conn = drm_connector_lookup((*debug->connector)->dev, NULL, debug->mst_con_id);
if (!drm_conn) {
DP_ERR("connector %u not in mst list\n", debug->mst_con_id);
goto bail;
}
sde_conn = to_sde_connector(drm_conn);
panel = sde_conn->drv_panel;
} else {
panel = debug->panel;
}
panel->get_src_crc(panel, src_crc);
panel->get_sink_crc(panel, sink_crc);
len += scnprintf(buf + len, buf_size - len, "FRAME_CRC:\nSource vs Sink\n");
len += scnprintf(buf + len, buf_size - len, "CRC_R: %04X %04X\n", src_crc[0], sink_crc[0]);
len += scnprintf(buf + len, buf_size - len, "CRC_G: %04X %04X\n", src_crc[1], sink_crc[1]);
len += scnprintf(buf + len, buf_size - len, "CRC_B: %04X %04X\n", src_crc[2], sink_crc[2]);
debug->ctrl->setup_misr(debug->ctrl);
while (retries--) {
mutex_unlock(&debug->lock);
msleep(30);
mutex_lock(&debug->lock);
rc = debug->ctrl->read_misr(debug->ctrl, &misr40);
if (rc != -EAGAIN)
break;
}
len += scnprintf(buf + len, buf_size - len, "\nMISR40:\nCTLR vs PHY\n");
for (i = 0; i < 4; i++) {
len += scnprintf(buf + len, buf_size - len, "Lane%d %08X%08X %08X%08X\n", i,
misr40.ctrl_misr[2 * i], misr40.ctrl_misr[(2 * i) + 1],
misr40.phy_misr[2 * i], misr40.phy_misr[(2 * i) + 1]);
}
len = min_t(size_t, count, len);
if (!copy_to_user(user_buff, buf, len))
*ppos += len;
bail:
mutex_unlock(&debug->lock);
kfree(buf);
return len;
}
static ssize_t dp_debug_write_hpd(struct file *file,
const char __user *user_buff, size_t count, loff_t *ppos)
{
@@ -1871,6 +1955,11 @@ static const struct file_operations dpcd_fops = {
.read = dp_debug_read_dpcd,
};
static const struct file_operations crc_fops = {
.open = simple_open,
.read = dp_debug_read_crc,
};
static const struct file_operations connected_fops = {
.open = simple_open,
.read = dp_debug_read_connected,
@@ -2104,6 +2193,13 @@ static int dp_debug_init_sink_caps(struct dp_debug_private *debug,
return rc;
}
file = debugfs_create_file("crc", 0644, dir, debug, &crc_fops);
if (IS_ERR_OR_NULL(file)) {
rc = PTR_ERR(file);
DP_ERR("[%s] debugfs crc failed, rc=%d\n", DEBUG_NAME, rc);
return rc;
}
return rc;
}