From a07dfdc7ca6cc7accc251e7a5bdf91ef9ef8d4c8 Mon Sep 17 00:00:00 2001 From: Bang Nguyen Date: Tue, 20 Aug 2019 14:22:52 -0500 Subject: [PATCH] disp: msm: Adding KMS property testing for motUtil tool Adding the KMS property (HBM/ACL) testing functionality to motUtil tool so these KMS property can be tested and verified as standalone without supporting of the Android FW apk. Port from: b345943 Change-Id: I825a1450f5b151025cc005fe45748bbae40c30bc Signed-off-by: Bang Nguyen Reviewed-on: https://gerrit.mot.com/1444401 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1509803 Reviewed-by: Hua Tan --- msm/dsi/dsi_panel.c | 40 +++++++--- msm/dsi/dsi_panel.h | 5 ++ msm/msm_drv.h | 7 ++ msm/sde/sde_connector.c | 26 +++++-- msm/sde/sde_motUtil.c | 161 ++++++++++++++++++++++++++++++++++------ msm/sde/sde_motUtil.h | 89 +++++++++++++++++++++- 6 files changed, 285 insertions(+), 43 deletions(-) diff --git a/msm/dsi/dsi_panel.c b/msm/dsi/dsi_panel.c index 52cbef5f41af..36185ba2f8b5 100755 --- a/msm/dsi/dsi_panel.c +++ b/msm/dsi/dsi_panel.c @@ -106,8 +106,11 @@ static struct panel_param_val_map hbm_map[HBM_STATE_NUM] = { {HBM_ON_STATE, DSI_CMD_SET_HBM_ON, NULL}, }; -static struct panel_param dsi_panel_param[PARAM_ID_NUM] = { - {"HBM", hbm_map, HBM_STATE_NUM, HBM_OFF_STATE, HBM_OFF_STATE, false}, +static struct panel_param dsi_panel_param[PANEL_IDX_MAX][PARAM_ID_NUM] = { + { + {"HBM", hbm_map, HBM_STATE_NUM, HBM_OFF_STATE, + HBM_OFF_STATE, false}, + }, }; int dsi_dsc_create_pps_buf_cmd(struct msm_display_dsc_info *dsc, char *buf, @@ -839,7 +842,7 @@ static int dsi_panel_pwm_register(struct dsi_panel *panel) return 0; } -static int dsi_panel_send_param_cmd (struct dsi_panel *panel, +static int dsi_panel_send_param_cmd(struct dsi_panel *panel, struct msm_param_info *param_info) { int rc = 0; @@ -874,6 +877,12 @@ static int dsi_panel_send_param_cmd (struct dsi_panel *panel, param_map = panel->param_cmds[param_info->param_idx].val_map; param_map_state = ¶m_map[param_info->value]; + if (!param_map_state->cmds || !param_map_state->cmds->cmds) { + DSI_ERR("Invalid cmds or cmds->cmds\n"); + rc = -EINVAL; + goto end; + } + cmds = param_map_state->cmds->cmds; if (param_map_state->cmds->state == DSI_CMD_SET_STATE_LP) cmds->msg.flags |= MIPI_DSI_MSG_USE_LPM | @@ -3538,7 +3547,7 @@ end: } static int dsi_panel_parse_param_prop(struct dsi_panel *panel, - struct device_node *of_node) + struct device_node *of_node, u32 param_idx) { int i, j, rc =0; struct panel_param *param; @@ -3549,9 +3558,15 @@ static int dsi_panel_parse_param_prop(struct dsi_panel *panel, struct dsi_parser_utils *utils = &panel->utils; for (i = 0; i < PARAM_ID_NUM; i++) { - param = &dsi_panel_param[i]; + param = &dsi_panel_param[param_idx][i]; - for (j = 0; j < param->val_max; j++) { + if (!param) { + pr_err("Invalid param\n"); + goto err; + } + + rc = -EINVAL; + for (j = 0; j < param->val_max && param->val_max > 0 ; j++) { param_map = ¶m->val_map[j]; param_map->cmds = NULL; cmds = kcalloc(param->val_max, @@ -3577,15 +3592,17 @@ static int dsi_panel_parse_param_prop(struct dsi_panel *panel, } } - param->is_supported = true; - DSI_INFO("%s: feature enabled.\n", param->param_name); + if (!rc) { + param->is_supported = true; + DSI_INFO("%s: feature enabled.\n", param->param_name); + } } return rc; parse_err: for (i = 0; i < ARRAY_SIZE(dsi_panel_param); i++) { - param = &dsi_panel_param[i]; + param = &dsi_panel_param[param_idx][i]; for (j = 0; j < param->val_max; j++) { if (param->val_map[j].cmds) { kfree(param->val_map[j].cmds); @@ -3695,6 +3712,7 @@ struct dsi_panel *dsi_panel_get(struct device *parent, struct dsi_parser_utils *utils; const char *panel_physical_type; int rc = 0; + u32 param_idx = 0; /* Since only panel support for now */ panel = kzalloc(sizeof(*panel), GFP_KERNEL); if (!panel) @@ -3725,8 +3743,8 @@ struct dsi_panel *dsi_panel_get(struct device *parent, if (rc) DSI_DEBUG("failed to parse mot_panel_config, rc = %d\n", rc); - panel->param_cmds = &dsi_panel_param[0]; - rc = dsi_panel_parse_param_prop(panel, of_node); + panel->param_cmds = dsi_panel_param[param_idx]; + rc = dsi_panel_parse_param_prop(panel, of_node, param_idx ); if (rc) pr_debug("failed to parse panel param prop, rc =%d\n", rc); diff --git a/msm/dsi/dsi_panel.h b/msm/dsi/dsi_panel.h index dbdcb1ad94b2..b02cff6edf61 100644 --- a/msm/dsi/dsi_panel.h +++ b/msm/dsi/dsi_panel.h @@ -178,6 +178,11 @@ struct drm_panel_esd_config { u32 groups; }; +enum panel_idx { + MAIN_IDX = 0, + PANEL_IDX_MAX, +}; + enum hbm_state { HBM_OFF_STATE = 0, HBM_ON_STATE, diff --git a/msm/msm_drv.h b/msm/msm_drv.h index 44210badce15..04c5d57fd80c 100644 --- a/msm/msm_drv.h +++ b/msm/msm_drv.h @@ -312,6 +312,13 @@ struct msm_roi_caps { struct msm_roi_alignment align; }; +enum msm_param_state { + PARAM_STATE_OFF = 0, + PARAM_STATE_ON, + PARAM_STATE_NUM, + PARAM_STATE_DISABLE = 0xFFFF, +}; + enum msm_param_id { PARAM_HBM_ID = 0, PARAM_ID_NUM diff --git a/msm/sde/sde_connector.c b/msm/sde/sde_connector.c index 0f53f9da4ec9..b98a0a34c7ed 100644 --- a/msm/sde/sde_connector.c +++ b/msm/sde/sde_connector.c @@ -1495,7 +1495,9 @@ static int sde_connector_atomic_set_property(struct drm_connector *connector, connector->state, CONNECTOR_PROP_HBM); param_info.param_idx = PARAM_HBM_ID; param_info.param_conn_idx = CONNECTOR_PROP_HBM; - _sde_connector_update_param(c_conn, ¶m_info); + rc = _sde_connector_update_param(c_conn, ¶m_info); + if (rc) + goto end; break; default: break; @@ -2385,7 +2387,7 @@ static int sde_connector_install_panel_params(struct sde_connector *c_conn) uint32_t prop_idx; int i; struct dsi_display *dsi_display; - + u16 prop_max, prop_min, prop_init; if (c_conn->connector_type != DRM_MODE_CONNECTOR_DSI) return 0; @@ -2405,12 +2407,20 @@ static int sde_connector_install_panel_params(struct sde_connector *c_conn) return -EINVAL; } - if (param_cmds->is_supported) - msm_property_install_volatile_range( - &c_conn->property_info, - param_cmds->param_name, - 0x0, 0, param_cmds->val_max, - param_cmds->default_value, prop_idx); + if (param_cmds->is_supported) { + prop_max = param_cmds->val_max; + prop_min = PARAM_STATE_OFF; + prop_init = param_cmds->default_value; + } else { + prop_max = PARAM_STATE_OFF; + prop_min = PARAM_STATE_OFF; + prop_init = PARAM_STATE_DISABLE; + } + + msm_property_install_volatile_range( &c_conn->property_info, + param_cmds->param_name, 0x0, + prop_min, prop_max, + prop_init, prop_idx); param_cmds++; } diff --git a/msm/sde/sde_motUtil.c b/msm/sde/sde_motUtil.c index ef41494c76da..d33f11222533 100644 --- a/msm/sde/sde_motUtil.c +++ b/msm/sde/sde_motUtil.c @@ -61,6 +61,7 @@ static ssize_t _sde_debugfs_motUtil_string2num(const char __user *buf, while (token) { rc = kstrtoint(token, 0, &strtoint); if (rc) { + rc = -EIO; SDE_ERROR("input buffer conversion failed\n"); goto end; } @@ -84,13 +85,12 @@ end: return rc; } -static struct sde_connector *_sde_debugfs_motUtil_get_sde_conn( +static struct drm_connector *_sde_debugfs_motUtil_get_drm_conn( struct sde_kms *kms, size_t count, char input[]) { struct drm_device *dev = kms->dev; struct drm_connector *conn = NULL; - struct sde_connector *sde_conn = NULL; int found_conn = 0; enum sde_motUtil_disp_cmd panel_type = input[DISPUTIL_PANEL_TYPE]; struct drm_connector_list_iter conn_iter; @@ -113,20 +113,30 @@ static struct sde_connector *_sde_debugfs_motUtil_get_sde_conn( } } - if (found_conn) { - SDE_DEBUG("found SDE Connector for %s\n", - (panel_type == MOTUTIL_MAIN_DISP) ? - "Main Display" : "CLI Display"); - sde_conn = to_sde_connector(conn); - } else { - SDE_ERROR("Can not find SDE Connector for %s\n", - (panel_type == MOTUTIL_MAIN_DISP) ? - "Main Display" : "CLI Display"); - } - drm_connector_list_iter_end(&conn_iter); mutex_unlock(&dev->mode_config.mutex); + if (found_conn) + return conn; + else + return NULL; +} + +static struct sde_connector *_sde_debugfs_motUtil_get_sde_conn( + struct sde_kms *kms, + size_t count, char input[]) +{ + struct drm_connector *conn = NULL; + struct sde_connector *sde_conn = NULL; + + conn = _sde_debugfs_motUtil_get_drm_conn(kms, count, input); + if (conn) + sde_conn = to_sde_connector(conn); + else + DRM_ERROR("Can not find SDE Connector for %s\n", + (input[DISPUTIL_PANEL_TYPE] == MOTUTIL_MAIN_DISP) ? + "Main Display" : "CLI Display"); + return sde_conn; } @@ -159,7 +169,7 @@ static int _sde_debugfs_motUtil_transfer(struct sde_kms *kms, mutex_lock(&sde_conn->lock); ret = sde_conn->ops.motUtil_transfer(sde_conn->display, input, count, &motUtil_data); - motUtil_data.last_cmd_tx_status = !ret ? true : false; + motUtil_data.cmd_status = ret; motUtil_data.read_len = ret; mutex_unlock(&sde_conn->lock); @@ -171,6 +181,98 @@ end: } +static int _sde_debugfs_motUtil_kms_prop_test(struct sde_kms *kms, + size_t count, char input[]) +{ + struct drm_connector *conn = NULL; + struct sde_connector *sde_conn = NULL; + struct drm_property *property; + + int ret = 0; + enum msm_mdp_conn_property conn_prop_idx; + uint64_t prop_val; + + conn = _sde_debugfs_motUtil_get_drm_conn(kms, count, input); + if (!conn) { + ret = -EINVAL; + goto end; + } + + sde_conn = to_sde_connector(conn); + if (!sde_conn) { + ret = -EINVAL; + goto end; + } + + if (count < KMSPROPTEST_NEW_VAL) { + DRM_ERROR(" Number of Input data is invalid (%zu).\n", count); + ret = -EINVAL; + goto end; + } + + switch (input[KMSPROPTEST_PROP_INDEX]) { + case KMSPROPTEST_TYPE_HBM: + conn_prop_idx = CONNECTOR_PROP_HBM; + break; +/* case KMSPROPTEST_TYPE_ACL: + conn_prop_idx = CONNECTOR_PROP_ACL; + break; +*/ + default: + DRM_ERROR(" Invalid KMSPROPTEST_PROP_INDEX = %d\n", + input[KMSPROPTEST_PROP_INDEX]); + ret = -EINVAL; + break; + } + + if (ret) + goto end; + + property = msm_property_index_to_drm_property(&sde_conn->property_info, + conn_prop_idx); + if (!property) { + SDE_ERROR("invalid property index %d for sde_conn_name=%s\n", + conn_prop_idx, sde_conn->name); + ret = -EINVAL; + goto end; + } + + prop_val = sde_connector_get_property(conn->state, conn_prop_idx); + if (prop_val == PARAM_STATE_DISABLE) { + DRM_ERROR("This KMS Property=%d is disabled\n", conn_prop_idx); + ret = -EPERM; + goto end; + } + + switch(input[KMSPROPTEST_PROP_TYPE]) { + case KMSPROPTEST_GETPROP: + motUtil_data.read_cmd = true; + motUtil_data.val = (int)prop_val; + break; + case KMSPROPTEST_SETPROP: + motUtil_data.read_cmd = false; + if (conn->funcs && conn->funcs->atomic_set_property) { + ret = conn->funcs->atomic_set_property(conn, + conn->state, property, + input[KMSPROPTEST_NEW_VAL]); + } else { + ret = -EINVAL; + DRM_ERROR("Unsupport KMS set property\n"); + } + + break; + default: + DRM_ERROR("Invalid KMSPROPTEST_PROP_TYPE = %d\n", + input[KMSPROPTEST_PROP_TYPE]); + ret = -EINVAL; + break; + } + +end: + motUtil_data.cmd_status = ret; + return ret; +} + static ssize_t _sde_debugfs_motUtil_exe_command(struct sde_kms *kms, size_t count, char input[]) { @@ -182,6 +284,9 @@ static ssize_t _sde_debugfs_motUtil_exe_command(struct sde_kms *kms, case MOTUTIL_DISP_UTIL: ret = _sde_debugfs_motUtil_transfer(kms, count, input); break; + case MOTUTIL_KMS_PROP_TEST: + ret = _sde_debugfs_motUtil_kms_prop_test(kms, count, input); + break; default: SDE_ERROR("Un-support motUtil type = %d\n", motUtil_type); ret = -EINVAL; @@ -207,22 +312,26 @@ static ssize_t _sde_debugfs_motUtil_write(struct file *file, u32 buf_size = 0; char buffer[MAX_CMD_PAYLOAD_SIZE]; struct sde_kms *kms = (struct sde_kms *)file->private_data; + int ret = 0; if (*ppos || !kms) { SDE_ERROR("invalid argument(s)\n"); - return 0; + ret = -EINVAL; + goto end; } buf_size = _sde_debugfs_motUtil_string2num(buf, count, buffer); - if (!buf_size){ + if (buf_size <= 0){ SDE_ERROR("invalid input\n"); - return count; + ret = -EINVAL; + goto end; } mutex_lock(&motUtil_data.lock); - _sde_debugfs_motUtil_exe_command(kms, count, buffer); + ret = _sde_debugfs_motUtil_exe_command(kms, count, buffer); mutex_unlock(&motUtil_data.lock); - +end: + motUtil_data.cmd_status = ret; return count; } @@ -253,13 +362,19 @@ static ssize_t _sde_debugfs_motUtil_read(struct file *file, return 0; mutex_lock(&motUtil_data.lock); - if (!motUtil_data.read_cmd) { + if (motUtil_data.cmd_status < 0 || !motUtil_data.read_cmd) { blen = snprintf(buffer, MAX_CMD_PAYLOAD_SIZE, - "motUtil_status: 0x%x\n", - motUtil_data.last_cmd_tx_status); + "motUtil_status: %d\n", + motUtil_data.cmd_status); } else if (motUtil_data.motUtil_type == MOTUTIL_DISP_UTIL) { blen = _sde_debugfs_motUtil_dispUtil_read(buffer); - } + } else if (motUtil_data.motUtil_type == MOTUTIL_KMS_PROP_TEST) { + blen = snprintf(buffer, 16, "motUtil_read: "); + blen += snprintf((buffer + blen), 12, "0x%08x ", + motUtil_data.val); + blen += snprintf((buffer + blen), 2, "\n"); + } + SDE_INFO("%s\n", buffer); diff --git a/msm/sde/sde_motUtil.h b/msm/sde/sde_motUtil.h index bc83b35e5d77..329977ae6ac1 100644 --- a/msm/sde/sde_motUtil.h +++ b/msm/sde/sde_motUtil.h @@ -18,8 +18,78 @@ #include #include +/***************************************************************************** + * /d/dri/0/debug/motUtil sysfs * + * - This is Mot debug sysfs to provide some tools to test panel and panel * + * features. This tool only exist with the userdebug and Engineering build * + * - Currently, this motUtil will provide 3 kind of tests and it can enhance * + * to test more if needed * + * - Test#1: DispUtil: This test is able to send any MIPI DSI command and * + * it can read any data back from the panel * + * - Test#2: TeTest: This test will be used to test the TE trace between * + * the panels and MDSS to make sure it works * + * - Test#3: kmsPropTest: This test will test the panel features such as * + * HBM, ACL, CABC, etc. It can read these features configurations* + * in the KMS property and it can change these setting from KMS * + * property. * + * - Usage: * + * - 1st byte will indicate which motUtil test will be run. * + * 0x00 = dispUtil, 0x01 = TeTest, 0x02 = kmsPropTest * + * --------------------------------------------------------------------------* + * - dispUtil: * + * 1st byte: 0x00: dispUtil * + * 2nd byte: 0x00: primary panel and 0x01: Secondary panel * + * 3rd byte: 0x00: MIPI write cmd to panel and 0x01: MIPI read * + * 4th byte: 0x00: MIPI HS mode and 0x01: MIPI LP mode * + * 5th byte: 0x00: MIPI DCS cmd and 0x01: MIPI generaic cmd * + * 6th byte: Indicate number of bytes to read from panel * + * 7th and 8th: Indicate number of bytes for the payload cmd * + * 9th and .. :the payload cmd * + * - Example: * + * echo "0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x28" > motUtil * + * - This will send a mipi DSC command "0x28" to panel and * + * which will request the panel to turn off the panel * + * cat motUtil * + * - This will report a sending previous cmd status * + * 0: send success or errno if it fails * + * echo "0x00 0x01 0x01 0x00 0x00 0x01 0x00 0x01 0x0a" > motUtil * + * - This will send MIPI read cmd "0xa" to the panel. * + * cat motUtil * + * - number of reading bytes from previous command or errno if it fails* + *---------------------------------------------------------------------------* + * - TeTest: This test has been removed * + *---------------------------------------------------------------------------* + * - kmsPropTest * + * 1st byte: kmsPropTest * + * 2nd byte: 0x00: primary panel and 0x01: Secondary panel * + * 3rd byte: 0x00: get KMS property and 0x01: set KMS property * + * 4th byte: 0x00: HBM 0x01: ACL for the KMS property/panel feature * + * 5th byte: new data for a "set KMS property" operation * + * - Example * + * echo "0x02 0x00 0x010 0x00 0x00" > motUtil * + * - This will read the HBM setting of the primary panel in the KMS * + * property. * + * cat motUtil * + * - This will return the status of previous cmd. * + * 0 if success or errno if it fails * + * echo "0x02 0x00 0x01 0x00 0x01" > motUtil * + * - This will turn on the HBM feature of the primary panel in the KMS * + * property. The panel's backlight will be brighter when HBM is on * + * cat motUtil * + * - This will return the status of previous cmd. * + * 0 if success or errno if it fails * + * echo "0x02 0x00 0x010 0x00 0x00" > motUtil * + * - This will read back the HBM setting in KMS property * + * echo "0x02 0x00 0x01 0x00 0x00" > motUtil * + * - This will turn off the HBM feature of the primary panel in the KMS * + * property. The panel's backlight will be dimmer when HBM is off * + * * + ****************************************************************************/ + enum sde_motUtil_type { MOTUTIL_DISP_UTIL = 0, + MOTUTIL_TE_TEST, + MOTUTIL_KMS_PROP_TEST, }; enum sde_motUtil_disp_cmd { @@ -34,11 +104,25 @@ enum sde_motUtil_disp_cmd { DISPUTIL_PAYLOAD, }; +enum sde_motUtil_kmsPropTest_cmd { + KMSPROPTEST_TYPE, + KMSPROPTEST_PANEL_TYPE, + KMSPROPTEST_PROP_TYPE, + KMSPROPTEST_PROP_INDEX, + KMSPROPTEST_NEW_VAL, +}; + +enum sde_motUtil_kmsPropTest_ConnPropType { + KMSPROPTEST_TYPE_HBM, + KMSPROPTEST_TYPE_ACL, + KMSPROPTEST_TYPE_CABC, +}; + struct motUtil { struct mutex lock; enum sde_motUtil_type motUtil_type; bool read_cmd; - bool last_cmd_tx_status; + int cmd_status; u16 read_len; u8 *rd_buf; int val; @@ -54,6 +138,9 @@ struct motUtil { #define DISPUTIL_DSI_HS_MODE 0 #define DISPUTIL_DSI_LP_MODE 1 +#define KMSPROPTEST_GETPROP 0 +#define KMSPROPTEST_SETPROP 1 + #define MOTUTIL_MAIN_DISP 0 #define MOTUTIL_CLI_DISP 1