From 718e224640c6b93eeb8d89b15d2d9465e82887d9 Mon Sep 17 00:00:00 2001 From: Gopikrishnaiah Anandan Date: Wed, 7 Aug 2019 17:59:14 -0700 Subject: [PATCH] disp: msm: Install demura properties on connector If DPU hardware supports demura feature, install the connector properties related to demura feature. Change-Id: Ieaddfc695e9f57e3c45e2bc0bd2c2e103f895ba8 Signed-off-by: Gopikrishnaiah Anandan --- msm/dsi/dsi_ctrl.h | 4 +++- msm/dsi/dsi_display.c | 36 +++++++++++++++++++++++++++- msm/dsi/dsi_display.h | 3 +++ msm/msm_drv.h | 1 + msm/sde/sde_connector.c | 52 ++++++++++++++++++++++++++++++++++++++++ msm/sde/sde_connector.h | 5 +++- msm/sde/sde_hw_catalog.c | 1 + msm/sde/sde_hw_catalog.h | 1 + 8 files changed, 100 insertions(+), 3 deletions(-) diff --git a/msm/dsi/dsi_ctrl.h b/msm/dsi/dsi_ctrl.h index 134c111055..2b73181697 100644 --- a/msm/dsi/dsi_ctrl.h +++ b/msm/dsi/dsi_ctrl.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. */ #ifndef _DSI_CTRL_H_ @@ -195,6 +195,7 @@ struct dsi_ctrl_interrupts { * @clk_cb: Callback for DSI clock control. * @irq_info: Interrupt information. * @recovery_cb: Recovery call back to SDE. + * @panel_id_cb: Callback for reporting panel id. * @clk_info: Clock information. * @clk_freq: DSi Link clock frequency information. * @pwr_info: Power information. @@ -247,6 +248,7 @@ struct dsi_ctrl { struct dsi_ctrl_interrupts irq_info; struct dsi_event_cb_info recovery_cb; + struct dsi_event_cb_info panel_id_cb; /* Clock and power states */ struct dsi_ctrl_clk_info clk_info; diff --git a/msm/dsi/dsi_display.c b/msm/dsi/dsi_display.c index a8dcb66efb..b9806a42a1 100644 --- a/msm/dsi/dsi_display.c +++ b/msm/dsi/dsi_display.c @@ -2044,6 +2044,12 @@ void dsi_display_enable_event(struct drm_connector *connector, *event_info; } break; + case SDE_CONN_EVENT_PANEL_ID: + if (event_info) + display_for_each_ctrl(i, display) + display->ctrl[i].ctrl->panel_id_cb + = *event_info; + break; default: /* nothing to do */ DSI_DEBUG("[%s] unhandled event %d\n", display->name, event_idx); @@ -2151,6 +2157,7 @@ static void dsi_display_parse_cmdline_topology(struct dsi_display *display, char *sw_te = NULL; unsigned long cmdline_topology = NO_OVERRIDE; unsigned long cmdline_timing = NO_OVERRIDE; + unsigned long panel_id = NO_OVERRIDE; if (display_type >= MAX_DSI_ACTIVE_DISPLAY) { DSI_ERR("display_type=%d not supported\n", display_type); @@ -2166,6 +2173,17 @@ static void dsi_display_parse_cmdline_topology(struct dsi_display *display, if (sw_te) display->sw_te_using_wd = true; + str = strnstr(boot_str, ":panelid", strlen(boot_str)); + if (str) { + if (kstrtol(str + strlen(":panelid"), INT_BASE_10, + (unsigned long *)&panel_id)) { + DSI_INFO("panel id not found: %s\n", boot_str); + } else { + DSI_INFO("panel id found: %lx\n", panel_id); + display->panel_id = panel_id; + } + } + str = strnstr(boot_str, ":config", strlen(boot_str)); if (!str) goto end; @@ -5193,6 +5211,8 @@ int dsi_display_dev_probe(struct platform_device *pdev) rc = -EINVAL; goto end; } + /* initialize panel id to UINT64_MAX */ + display->panel_id = ~0x0; display->display_type = of_get_property(pdev->dev.of_node, "label", NULL); @@ -7314,6 +7334,18 @@ int dsi_display_pre_commit(void *display, return rc; } +static void dsi_display_panel_id_notification(struct dsi_display *display) +{ + if (display->panel_id != ~0x0 && + display->ctrl[0].ctrl->panel_id_cb.event_cb) { + display->ctrl[0].ctrl->panel_id_cb.event_cb( + display->ctrl[0].ctrl->panel_id_cb.event_usr_ptr, + display->ctrl[0].ctrl->panel_id_cb.event_idx, + 0, ((display->panel_id & 0xffffffff00000000) >> 31), + (display->panel_id & 0xffffffff), 0, 0); + } +} + int dsi_display_enable(struct dsi_display *display) { int rc = 0; @@ -7346,6 +7378,8 @@ int dsi_display_enable(struct dsi_display *display) display->panel->panel_initialized = true; DSI_DEBUG("cont splash enabled, display enable not required\n"); + dsi_display_panel_id_notification(display); + return 0; } @@ -7369,7 +7403,7 @@ int dsi_display_enable(struct dsi_display *display) goto error; } } - + dsi_display_panel_id_notification(display); /* Block sending pps command if modeset is due to fps difference */ if ((mode->priv_info->dsc_enabled || mode->priv_info->vdc_enabled) && diff --git a/msm/dsi/dsi_display.h b/msm/dsi/dsi_display.h index 21762c891c..a287f4fe3a 100644 --- a/msm/dsi/dsi_display.h +++ b/msm/dsi/dsi_display.h @@ -275,6 +275,9 @@ struct dsi_display { u32 clk_gating_config; bool queue_cmd_waits; struct workqueue_struct *dma_cmd_workq; + + /* panel id of the display */ + u64 panel_id; }; int dsi_display_dev_probe(struct platform_device *pdev); diff --git a/msm/msm_drv.h b/msm/msm_drv.h index 2b47bab93e..1843a53a76 100644 --- a/msm/msm_drv.h +++ b/msm/msm_drv.h @@ -184,6 +184,7 @@ enum msm_mdp_conn_property { CONNECTOR_PROP_EXT_HDR_INFO, CONNECTOR_PROP_PP_DITHER, CONNECTOR_PROP_HDR_METADATA, + CONNECTOR_PROP_DEMURA_PANEL_ID, /* # of blob properties */ CONNECTOR_PROP_BLOBCOUNT, diff --git a/msm/sde/sde_connector.c b/msm/sde/sde_connector.c index 4278916821..22d5f61e86 100644 --- a/msm/sde/sde_connector.c +++ b/msm/sde/sde_connector.c @@ -378,6 +378,37 @@ int sde_connector_state_get_mode_info(struct drm_connector_state *conn_state, return 0; } +static int sde_connector_handle_panel_id(uint32_t event_idx, + uint32_t instance_idx, void *usr, + uint32_t data0, uint32_t data1, + uint32_t data2, uint32_t data3) +{ + struct sde_connector *c_conn = usr; + int i; + u64 panel_id; + u8 arr[8], shift; + u64 mask = 0xff; + + if (!c_conn) + return -EINVAL; + + panel_id = (((u64)data0) << 31) | data1; + if (panel_id == ~0x0) + return 0; + + for (i = 0; i < 8; i++) { + shift = 8 * i; + arr[7 - i] = (u8)((panel_id & (mask << shift)) >> shift); + } + /* update the panel id */ + msm_property_set_blob(&c_conn->property_info, + &c_conn->blob_panel_id, arr, sizeof(arr), + CONNECTOR_PROP_DEMURA_PANEL_ID); + sde_connector_register_event(&c_conn->base, + SDE_CONN_EVENT_PANEL_ID, NULL, c_conn); + return 0; +} + static int sde_connector_handle_disp_recovery(uint32_t event_idx, uint32_t instance_idx, void *usr, uint32_t data0, uint32_t data1, @@ -2397,6 +2428,7 @@ static int _sde_connector_install_properties(struct drm_device *dev, struct dsi_display *dsi_display; int rc; struct drm_connector *connector; + u64 panel_id = ~0x0; msm_property_install_blob(&c_conn->property_info, "capabilities", DRM_MODE_PROP_IMMUTABLE, CONNECTOR_PROP_SDE_INFO); @@ -2484,6 +2516,17 @@ static int _sde_connector_install_properties(struct drm_device *dev, e_frame_trigger_mode, ARRAY_SIZE(e_frame_trigger_mode), CONNECTOR_PROP_CMD_FRAME_TRIGGER_MODE); + + if (sde_kms->catalog->has_demura) { + msm_property_install_blob(&c_conn->property_info, + "DEMURA_PANEL_ID", DRM_MODE_PROP_IMMUTABLE, + CONNECTOR_PROP_DEMURA_PANEL_ID); + msm_property_set_blob(&c_conn->property_info, + &c_conn->blob_panel_id, + &panel_id, + sizeof(panel_id), + CONNECTOR_PROP_DEMURA_PANEL_ID); + } } msm_property_install_range(&c_conn->property_info, "bl_scale", @@ -2652,6 +2695,15 @@ struct drm_connector *sde_connector_init(struct drm_device *dev, if (rc) goto error_cleanup_fence; + if (connector_type == DRM_MODE_CONNECTOR_DSI && + sde_kms->catalog->has_demura) { + rc = sde_connector_register_event(&c_conn->base, + SDE_CONN_EVENT_PANEL_ID, + sde_connector_handle_panel_id, c_conn); + if (rc) + SDE_ERROR("register panel id event err %d\n", rc); + } + rc = msm_property_install_get_status(&c_conn->property_info); if (rc) { SDE_ERROR("failed to create one or more properties\n"); diff --git a/msm/sde/sde_connector.h b/msm/sde/sde_connector.h index ff2ce118d1..3f1674463a 100644 --- a/msm/sde/sde_connector.h +++ b/msm/sde/sde_connector.h @@ -358,6 +358,7 @@ enum sde_connector_events { SDE_CONN_EVENT_CMD_DONE, /* command mode frame done */ SDE_CONN_EVENT_VID_FIFO_OVERFLOW, /* dsi fifo overflow error */ SDE_CONN_EVENT_CMD_FIFO_UNDERFLOW, /* dsi fifo underflow error */ + SDE_CONN_EVENT_PANEL_ID, /* returns read panel id from ddic */ SDE_CONN_EVENT_COUNT, }; @@ -406,6 +407,7 @@ struct sde_connector_dyn_hdr_metadata { * @blob_ext_hdr: Pointer to blob structure for 'ext_hdr_properties' property * @blob_dither: Pointer to blob structure for default dither config * @blob_mode_info: Pointer to blob structure for mode info + * @blob_panel_id: Pointer to blob structure for blob_panel_id * @fb_kmap: true if kernel mapping of framebuffer is requested * @event_table: Array of registered events * @event_lock: Lock object for event_table @@ -429,7 +431,7 @@ struct sde_connector_dyn_hdr_metadata { * @qsync_mode: Cached Qsync mode, 0=disabled, 1=continuous mode * @qsync_updated: Qsync settings were updated * @colorspace_updated: Colorspace property was updated - * last_cmd_tx_sts: status of the last command transfer + * @last_cmd_tx_sts: status of the last command transfer * @hdr_capable: external hdr support present * @core_clk_rate: MDP core clk rate used for dynamic HDR packet calculation */ @@ -461,6 +463,7 @@ struct sde_connector { struct drm_property_blob *blob_ext_hdr; struct drm_property_blob *blob_dither; struct drm_property_blob *blob_mode_info; + struct drm_property_blob *blob_panel_id; bool fb_kmap; struct sde_connector_evt event_table[SDE_CONN_EVENT_COUNT]; diff --git a/msm/sde/sde_hw_catalog.c b/msm/sde/sde_hw_catalog.c index c4961537f5..20d8fa78f4 100644 --- a/msm/sde/sde_hw_catalog.c +++ b/msm/sde/sde_hw_catalog.c @@ -4684,6 +4684,7 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev) sde_cfg->has_sui_blendstage = true; sde_cfg->vbif_disable_inner_outer_shareable = true; } else if (IS_LAHAINA_TARGET(hw_rev)) { + sde_cfg->has_demura = true; sde_cfg->has_cwb_support = true; sde_cfg->has_wb_ubwc = true; sde_cfg->has_qsync = true; diff --git a/msm/sde/sde_hw_catalog.h b/msm/sde/sde_hw_catalog.h index db0418c85e..58f6b2a80f 100644 --- a/msm/sde/sde_hw_catalog.h +++ b/msm/sde/sde_hw_catalog.h @@ -1480,6 +1480,7 @@ struct sde_mdss_cfg { bool inline_disable_const_clr; bool dither_luma_mode_support; bool has_base_layer; + bool has_demura; struct sde_sc_cfg sc_cfg;