drm/msm/dsi-staging: handle several on-commands for shift gamma handling
Change-Id: I4407e81232eb707db037accc8aa5b4b6757006c8
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h b/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h
index a6ada73..2839a14 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h
@@ -37,6 +37,9 @@
})
#define DSI_DEBUG_NAME_LEN 32
+
+#define SHIFT_GAMMA_CMD_MAX 3
+
/**
* enum dsi_pixel_format - DSI pixel formats
* @DSI_PIXEL_FORMAT_RGB565:
@@ -334,6 +337,7 @@ struct dsi_cmd_desc {
* @count: number of cmds
* @ctrl_idx: index of the dsi control
* @cmds: arry of cmds
+ * @name: command name
*/
struct dsi_panel_cmd_set {
enum dsi_cmd_set_type type;
@@ -341,6 +345,7 @@ struct dsi_panel_cmd_set {
u32 count;
u32 ctrl_idx;
struct dsi_cmd_desc *cmds;
+ char name[DRM_DISPLAY_MODE_LEN];
};
/**
@@ -506,6 +511,10 @@ struct dsi_host_config {
* struct dsi_display_mode_priv_info - private mode info that will be attached
* with each drm mode
* @cmd_sets: Command sets of the mode
+ * @shift_on_commands: SHIFT: on-commands for gamma settings
+ * @shift_curr_gamma: SHIFT: index of shift_on_commands[] for current gamma
+ * @shift_max_gamma_dtb: SHIFT: max number of gamma settings setup in DTBO
+ * @shift_def_gamma: SHIFT: index of shift_on_commands[] for default gamma (as defined in DTBO)
* @phy_timing_val: Phy timing values
* @phy_timing_len: Phy timing array length
* @panel_jitter: Panel jitter for RSC backoff
@@ -518,6 +527,11 @@ struct dsi_host_config {
*/
struct dsi_display_mode_priv_info {
struct dsi_panel_cmd_set cmd_sets[DSI_CMD_SET_MAX];
+ struct dsi_panel_cmd_set shift_on_commands[SHIFT_GAMMA_CMD_MAX];
+
+ u16 shift_curr_gamma;
+ u16 shift_max_gamma_dtb;
+ s16 shift_def_gamma;
u32 *phy_timing_val;
u32 phy_timing_len;
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
index e2584cd..69a43a5ca 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
@@ -781,6 +781,65 @@ static int dsi_panel_tx_cmd_set(struct dsi_panel *panel,
return rc;
}
+static int dsi_panel_tx_shift_cmd_set_on(struct dsi_panel *panel)
+{
+ int rc = 0, i = 0;
+ ssize_t len;
+ struct dsi_cmd_desc *cmds;
+ u32 count;
+ enum dsi_cmd_set_state state;
+ struct dsi_display_mode *mode;
+ const struct mipi_dsi_host_ops *ops = panel->host->ops;
+ u16 cur = 0;
+
+ if (!panel || !panel->cur_mode)
+ return -EINVAL;
+
+ if (panel->type == EXT_BRIDGE)
+ return 0;
+
+ mode = panel->cur_mode;
+
+ if (!mode->priv_info) {
+ pr_err("%s: priv_info is empty\n", __func__);
+ return -EINVAL;
+ }
+
+ pr_debug("%s: shift_cur_gamma(%d)\n", __func__, mode->priv_info->shift_curr_gamma);
+
+ /* Get current gamma setting */
+ cur = mode->priv_info->shift_curr_gamma;
+ cmds = mode->priv_info->shift_on_commands[cur].cmds;
+ count = mode->priv_info->shift_on_commands[cur].count;
+ state = mode->priv_info->shift_on_commands[cur].state;
+
+ if (count == 0) {
+ pr_debug("[%s] No SHIFT on-commands(%d) to be sent\n", panel->name, cur);
+ goto error;
+ }
+
+ for (i = 0; i < count; i++) {
+ if (state == DSI_CMD_SET_STATE_LP)
+ cmds->msg.flags |= MIPI_DSI_MSG_USE_LPM;
+
+ if (cmds->last_command)
+ cmds->msg.flags |= MIPI_DSI_MSG_LASTCOMMAND;
+
+ len = ops->transfer(panel->host, &cmds->msg);
+ if (len < 0) {
+ rc = len;
+ pr_err("failed to set SHIFT on-commandcmds(%d), rc=%d\n", cur, rc);
+ goto error;
+ }
+ if (cmds->post_wait_ms)
+ usleep_range(cmds->post_wait_ms*1000,
+ ((cmds->post_wait_ms*1000)+10));
+ cmds++;
+ }
+error:
+ return rc;
+}
+
static int dsi_panel_pinctrl_deinit(struct dsi_panel *panel)
{
int rc = 0;
@@ -1934,6 +1993,83 @@ static int dsi_panel_parse_cmd_sets_sub(struct dsi_panel_cmd_set *cmd,
}
+static int dsi_panel_parse_shift_on_cmd(
+ struct dsi_display_mode_priv_info *priv, u32 idx,
+ struct device_node *of_node)
+{
+ int rc = 0;
+ u32 length = 0;
+ const char *data;
+ const char *state;
+ u32 packet_count = 0;
+ const char *name;
+ struct dsi_panel_cmd_set *cmd = &priv->shift_on_commands[idx];
+ bool def = false;
+
+ memset(cmd->name, 0, DRM_DISPLAY_MODE_LEN);
+ name = of_get_property(of_node, "shift,on-cmd-name", NULL);
+ if (name) {
+ snprintf(cmd->name, DRM_DISPLAY_MODE_LEN, "%s", name);
+ }
+
+ def = of_property_read_bool(of_node, "shift,on-cmd-default");
+ if (def) {
+ if (priv->shift_def_gamma != -1) {
+ pr_warn("Ambiguous settings for property \"shift,on-cmd-default\"\n");
+ priv->shift_def_gamma = 0;
+ } else {
+ priv->shift_def_gamma = idx;
+ }
+ }
+
+ data = of_get_property(of_node, "shift,on-cmd-command", &length);
+ if (!data) {
+ pr_debug("no on-command[%d] defined\n", idx);
+ rc = -ENOTSUPP;
+ goto error;
+ }
+
+ rc = dsi_panel_get_cmd_pkt_count(data, length, &packet_count);
+ if (rc) {
+ pr_err("commands failed, rc=%d\n", rc);
+ goto error;
+ }
+ pr_debug("[shift on-command[%d]] packet-count=%d, %d\n", idx,
+ packet_count, length);
+
+ rc = dsi_panel_alloc_cmd_packets(cmd, packet_count);
+ if (rc) {
+ pr_err("[shift on-command[%d]] failed to allocate cmd packets, rc=%d\n", idx, rc);
+ goto error;
+ }
+
+ rc = dsi_panel_create_cmd_packets(data, length, packet_count,
+ cmd->cmds);
+ if (rc) {
+ pr_err("[shift on-command[%d]] failed to create cmd packets, rc=%d\n", idx, rc);
+ goto error_free_mem;
+ }
+
+ state = of_get_property(of_node, "shift,on-cmd-state", NULL);
+ if (!state || !strcmp(state, "dsi_lp_mode")) {
+ cmd->state = DSI_CMD_SET_STATE_LP;
+ } else if (!strcmp(state, "dsi_hs_mode")) {
+ cmd->state = DSI_CMD_SET_STATE_HS;
+ } else {
+ pr_err("[shift on-command[%d]] command state unrecognized-%s\n",
+ idx, state);
+ goto error_free_mem;
+ }
+
+ return rc;
+error_free_mem:
+ kfree(cmd->cmds);
+ cmd->cmds = NULL;
+error:
+ return rc;
+
+}
+
static int dsi_panel_parse_cmd_sets(
struct dsi_display_mode_priv_info *priv_info,
struct device_node *of_node)
@@ -1941,6 +2077,9 @@ static int dsi_panel_parse_cmd_sets(
int rc = 0;
struct dsi_panel_cmd_set *set;
u32 i;
+ struct device_node *shift_np, *child_np;
+ int num_shift_on_cmds = 0;
+ u32 child_idx = 0;
if (!priv_info) {
pr_err("invalid mode priv info\n");
@@ -1965,7 +2104,39 @@ static int dsi_panel_parse_cmd_sets(
}
}
+ /* Parse SHIFT on-commands */
+ shift_np = of_get_child_by_name(of_node, "shift,on-commands");
+ if (!shift_np) {
+ pr_warning("no shift on-commands defined\n");
+ goto end;
+ }
+
+ num_shift_on_cmds = of_get_child_count(shift_np);
+ if (!num_shift_on_cmds || num_shift_on_cmds > SHIFT_GAMMA_CMD_MAX) {
+ pr_err("invalid count of shift on-commands %d\n", num_shift_on_cmds);
+ rc = -EINVAL;
+ goto parse_fail;
+ }
+
+ priv_info->shift_def_gamma = -1;
+ for_each_child_of_node(shift_np, child_np) {
+ rc = dsi_panel_parse_shift_on_cmd(priv_info, child_idx, child_np);
+ if (rc) {
+ pr_err("failed to parse shift on-command, rc=%d\n", rc);
+ goto parse_fail;
+ }
+
+ ++child_idx;
+ }
+ priv_info->shift_max_gamma_dtb = num_shift_on_cmds;
+
+ if (priv_info->shift_def_gamma < 0)
+ priv_info->shift_def_gamma = 0;
+
+end:
rc = 0;
+
+parse_fail:
return rc;
}
@@ -4043,7 +4214,8 @@ int dsi_panel_enable(struct dsi_panel *panel)
mutex_lock(&panel->panel_lock);
- rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_ON);
+ /* SHIFT handles gamma settings with different on commands */
+ rc = dsi_panel_tx_shift_cmd_set_on(panel);
if (rc) {
pr_err("[%s] failed to send DSI_CMD_SET_ON cmds, rc=%d\n",
panel->name, rc);