diff --git a/msm/dp/dp_display.c b/msm/dp/dp_display.c index e306bfb23f65..67e807116f9d 100644 --- a/msm/dp/dp_display.c +++ b/msm/dp/dp_display.c @@ -177,6 +177,7 @@ struct dp_display_private { struct dentry *root; struct completion notification_comp; struct completion attention_comp; + struct completion res_init_comp; struct dp_hpd *hpd; struct dp_parser *parser; @@ -317,6 +318,41 @@ static void dp_audio_enable(struct dp_display_private *dp, bool enable) } } +/** + * dp_display_cont_splash_config() - Initialize resources for continuous splash + * @dp_display: Pointer to dp display + * Returns: Zero on success + */ +int dp_display_cont_splash_config(void *display) +{ + struct dp_display *dp_display = display; + struct dp_display_private *dp; + int rc = 0; + + /* Vote for gdsc required to read register address space */ + if (!dp_display) { + DP_ERR("invalid input display param\n"); + return -EINVAL; + } + + dp = container_of(dp_display, struct dp_display_private, dp_display); + + if (!dp_display->is_edp) { + DP_ERR("splash handoff for dp not supported\n"); + return -EOPNOTSUPP; + } + + /* wait for the all the resource initialization and voting to + * complete, before we exit driver probe + */ + if (!wait_for_completion_timeout(&dp->res_init_comp, HZ * 10)) { + DP_WARN("timeout waiting for splash_res_init\n"); + rc = -ETIMEDOUT; + } + + return rc; +} + static int dp_display_parse_boot_display_selection(void) { char *pos = NULL; @@ -1122,10 +1158,14 @@ static int dp_display_host_init(struct dp_display_private *dp) return rc; } +<<<<<<< HEAD /* Skip hpd config when cont. splash is enbaled*/ if (!skip_op) dp->hpd->host_init(dp->hpd, &dp->catalog->hpd); +======= + dp->hpd->host_init(dp->hpd, &dp->catalog->hpd); +>>>>>>> 452e643352bd41612f5634d8b38d7be9cbc9a875 rc = dp->ctrl->init(dp->ctrl, flip, reset, skip_op); if (rc) { DP_WARN("Ctrl init Failed.\n"); @@ -1361,6 +1401,9 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp) dp->process_hpd_connect = false; dp_display_set_mst_mgr_state(dp, true); + + /* all dp resource init are complete */ + complete_all(&dp->res_init_comp); end: mutex_unlock(&dp->session_lock); @@ -2630,7 +2673,11 @@ static void dp_display_stream_post_enable(struct dp_display_private *dp, struct dp_panel *dp_panel) { +<<<<<<< HEAD if (dp->dp_display.is_edp) { +======= + if (dp->dp_display.cont_splash_enabled) { +>>>>>>> 452e643352bd41612f5634d8b38d7be9cbc9a875 dp->dp_display.cont_splash_enabled = false; dp->pll->cont_splash_enabled = false; } @@ -2642,6 +2689,9 @@ static int dp_display_post_enable(struct dp_display *dp_display, void *panel) { struct dp_display_private *dp; struct dp_panel *dp_panel; + struct drm_connector *connector; + struct sde_connector *sde_conn; + struct backlight_device *bl_device; int rc = 0; if (!dp_display || !panel) { @@ -2687,6 +2737,15 @@ static int dp_display_post_enable(struct dp_display *dp_display, void *panel) DP_ERR("Cannot turn edp backlight power on"); goto end; } + connector = dp_display->base_connector; + sde_conn = to_sde_connector(connector); + + sde_conn->allow_bl_update = true; + if (sde_conn->bl_device) { + bl_device = sde_conn->bl_device; + bl_device->props.power = FB_BLANK_UNBLANK; + bl_device->props.state &= ~BL_CORE_FBBLANK; + } } cancel_delayed_work_sync(&dp->hdcp_cb_work); @@ -3344,6 +3403,37 @@ static int dp_display_config_hdr(struct dp_display *dp_display, void *panel, core_clk_rate, flush_hdr); } +static int dp_display_set_backlight(struct dp_display *dp_display, + void *panel, u32 bl_lvl) +{ + struct dp_panel *dp_panel; + struct dp_display_private *dp; + u32 bl_scale, bl_scale_sv; + u64 bl_temp; + + if (!dp_display || !panel) { + DP_ERR("invalid input\n"); + return -EINVAL; + } + + dp = container_of(dp_display, struct dp_display_private, dp_display); + dp_panel = panel; + + dp_panel->bl_config.bl_level = bl_lvl; + + /* scale backlight */ + bl_scale = dp_panel->bl_config.bl_scale; + bl_temp = bl_lvl * bl_scale / MAX_BL_SCALE_LEVEL; + + bl_scale_sv = dp_panel->bl_config.bl_scale_sv; + bl_temp = (u32)bl_temp * bl_scale_sv / MAX_SV_BL_SCALE_LEVEL; + + DP_DEBUG("bl_scale = %u, bl_scale_sv = %u, bl_lvl = %u\n", + bl_scale, bl_scale_sv, (u32)bl_temp); + + return dp_panel->set_backlight(dp_panel, (u32)bl_temp); +} + static int dp_display_setup_colospace(struct dp_display *dp_display, void *panel, u32 colorspace) @@ -3950,6 +4040,7 @@ static int dp_display_probe(struct platform_device *pdev) init_completion(&dp->notification_comp); init_completion(&dp->attention_comp); + init_completion(&dp->res_init_comp); dp->pdev = pdev; dp->name = "drm_dp"; @@ -4005,6 +4096,7 @@ static int dp_display_probe(struct platform_device *pdev) dp_display->wakeup_phy_layer = dp_display_wakeup_phy_layer; dp_display->set_colorspace = dp_display_setup_colospace; + dp_display->set_backlight = dp_display_set_backlight; dp_display->get_available_dp_resources = dp_display_get_available_dp_resources; dp_display->get_display_type = dp_display_get_display_type; @@ -4238,4 +4330,8 @@ void __exit dp_display_unregister(void) module_param_string(edp_display0, edp_display_primary, MAX_CMDLINE_PARAM_LEN, 0600); MODULE_PARM_DESC(edp_display0, +<<<<<<< HEAD "msm_drm.edp_display0=: where is 'primary dp display node name' and where x represents index in the topology list"); +======= + "msm_drm.edp_display0=: where is 'primary dp display node name' "); +>>>>>>> 452e643352bd41612f5634d8b38d7be9cbc9a875 diff --git a/msm/dp/dp_display.h b/msm/dp/dp_display.h index f99e2fd72328..7e75e2f5a7df 100644 --- a/msm/dp/dp_display.h +++ b/msm/dp/dp_display.h @@ -121,6 +121,8 @@ struct dp_display { bool dhdr_update); int (*set_colorspace)(struct dp_display *dp_display, void *panel, u32 colorspace); + int (*set_backlight)(struct dp_display *dp_display, void *panel, + u32 bl_lvl); int (*post_init)(struct dp_display *dp_display); int (*mst_install)(struct dp_display *dp_display, struct dp_mst_drm_install_info *mst_install_info); @@ -160,17 +162,23 @@ struct dp_display { u32 strm_id, const char **display_type); int (*edp_detect)(struct dp_display *dp_display); }; -int dp_display_get_num_of_boot_displays(void); + #if IS_ENABLED(CONFIG_DRM_MSM_DP) int dp_display_get_num_of_displays(void); +int dp_display_get_num_of_boot_displays(void); int dp_display_get_displays(void **displays, int count); int dp_display_get_num_of_streams(void); int dp_display_get_info(void *dp_display, struct dp_display_info *dp_info); +int dp_display_cont_splash_config(void *display); #else static inline int dp_display_get_num_of_displays(void) { return 0; } +static inline int dp_display_get_num_of_boot_displays(void) +{ + return 0; +} static inline int dp_display_get_displays(void **displays, int count) { return 0; @@ -188,5 +196,9 @@ static inline int dp_connector_update_pps(struct drm_connector *connector, { return 0; } +static inline int dp_display_cont_splash_config(void *display) +{ + return 0; +} #endif /* CONFIG_DRM_MSM_DP */ #endif /* _DP_DISPLAY_H_ */ diff --git a/msm/dp/dp_drm.c b/msm/dp/dp_drm.c index 1342726043e8..1bb2d4a1d9e9 100644 --- a/msm/dp/dp_drm.c +++ b/msm/dp/dp_drm.c @@ -326,6 +326,27 @@ int dp_connector_config_hdr(struct drm_connector *connector, void *display, c_state->dyn_hdr_meta.dynamic_hdr_update); } +int dp_connector_set_backlight(struct drm_connector *connector, + void *display, u32 bl_lvl) +{ + struct dp_display *dp_display = display; + struct sde_connector *sde_conn; + + if (!dp_display || !connector) { + DP_ERR("invalid dp display\n"); + return -EINVAL; + } + + sde_conn = to_sde_connector(connector); + if (!sde_conn->drv_panel) { + DP_ERR("invalid dp panel\n"); + return -EINVAL; + } + + return dp_display->set_backlight(dp_display, + sde_conn->drv_panel, bl_lvl); +} + int dp_connector_set_colorspace(struct drm_connector *connector, void *display) { diff --git a/msm/dp/dp_drm.h b/msm/dp/dp_drm.h index 647705c2706d..a99ab9c86f9d 100644 --- a/msm/dp/dp_drm.h +++ b/msm/dp/dp_drm.h @@ -49,6 +49,15 @@ int dp_connector_atomic_check(struct drm_connector *connector, void *display, struct drm_atomic_state *state); +/** + * dp_connector_set_backlight - callback to set backlight + * @connector: Pointer to drm connector structure + * @display: Pointer to private display handle + * Returns: Zero on success + */ +int dp_connector_set_backlight(struct drm_connector *connector, + void *display, u32 bl_lvl); + /** * dp_connector_set_colorspace - callback to set new colorspace * @connector: Pointer to drm connector structure diff --git a/msm/dp/dp_panel.c b/msm/dp/dp_panel.c index 6c24c52b0004..8fc1b13c3e32 100644 --- a/msm/dp/dp_panel.c +++ b/msm/dp/dp_panel.c @@ -6,6 +6,7 @@ #include "dp_panel.h" #include +#include #include #include "dp_debug.h" #include @@ -2295,6 +2296,91 @@ static int dp_panel_set_stream_info(struct dp_panel *dp_panel, return 0; } +static int dp_panel_pwm_register(struct dp_panel *dp_panel) +{ + int rc = 0; + struct dp_backlight_config *bl = &dp_panel->bl_config; + struct platform_device *pdev; + struct device *dev; + struct dp_panel_private *panel; + + panel = container_of(dp_panel, struct dp_panel_private, dp_panel); + pdev = panel->parser->pdev; + dev = &pdev->dev; + + bl->pwm_bl = devm_of_pwm_get(dev, dev->of_node, NULL); + if (IS_ERR_OR_NULL(bl->pwm_bl)) { + rc = PTR_ERR(bl->pwm_bl); + DP_ERR("failed to request pwm, rc=%d\n", rc); + return rc; + } + + return 0; +} + +static void dp_panel_pwm_unregister(struct dp_panel *dp_panel) +{ + struct dp_backlight_config *bl = &dp_panel->bl_config; + struct platform_device *pdev; + struct dp_panel_private *panel; + + panel = container_of(dp_panel, struct dp_panel_private, dp_panel); + pdev = panel->parser->pdev; + + if (bl->pwm_bl) + devm_pwm_put(&pdev->dev, bl->pwm_bl); +} + +static int dp_panel_set_backlight(struct dp_panel *panel, u32 bl_lvl) +{ + int rc = 0; + u32 duty = 0; + u32 period_ns = 0; + struct dp_backlight_config *bl; + + if (!panel) { + DP_ERR("Invalid Params\n"); + return -EINVAL; + } + + bl = &panel->bl_config; + if (!bl->pwm_bl) { + DP_ERR("pwm device not found\n"); + return -EINVAL; + } + + DP_DEBUG("backlight lvl:%d\n", bl_lvl); + + period_ns = bl->pwm_period_usecs * NSEC_PER_USEC; + duty = bl_lvl * period_ns; + duty /= bl->bl_max_level; + + rc = pwm_config(bl->pwm_bl, duty, period_ns); + if (rc) { + DP_ERR("failed to change pwm config, rc=\n", rc); + goto error; + } + + if (bl_lvl == 0 && bl->pwm_enabled) { + pwm_disable(bl->pwm_bl); + bl->pwm_enabled = false; + return 0; + } + + if (bl_lvl != 0 && !bl->pwm_enabled) { + rc = pwm_enable(bl->pwm_bl); + if (rc) { + DP_ERR("failed to enable pwm, rc=\n", rc); + goto error; + } + + bl->pwm_enabled = true; + } + +error: + return rc; +} + static int dp_panel_init_panel_info(struct dp_panel *dp_panel) { int rc = 0; @@ -3058,6 +3144,15 @@ struct dp_panel *dp_panel_get(struct dp_panel_in *in) dp_panel->fec_feature_enable = panel->parser->fec_feature_enable; dp_panel->dsc_continuous_pps = panel->parser->dsc_continuous_pps; + /* backlight config for edp */ + dp_panel->bl_config.bl_min_level = panel->parser->bl_min_level; + dp_panel->bl_config.bl_max_level = panel->parser->bl_max_level; + dp_panel->bl_config.brightness_max_level = panel->parser->brightness_max_level; + dp_panel->bl_config.pwm_period_usecs = panel->parser->pwm_period_usecs; + dp_panel->bl_config.bl_scale = MAX_BL_SCALE_LEVEL; + dp_panel->bl_config.bl_scale_sv = MAX_SV_BL_SCALE_LEVEL; + + if (in->base_panel) { memcpy(dp_panel->dpcd, in->base_panel->dpcd, DP_RECEIVER_CAP_SIZE + 1); @@ -3085,6 +3180,7 @@ struct dp_panel *dp_panel_get(struct dp_panel_in *in) dp_panel->spd_config = dp_panel_spd_config; dp_panel->setup_hdr = dp_panel_setup_hdr; dp_panel->set_colorspace = dp_panel_set_colorspace; + dp_panel->set_backlight = dp_panel_set_backlight; dp_panel->hdr_supported = dp_panel_hdr_supported; dp_panel->set_stream_info = dp_panel_set_stream_info; dp_panel->read_sink_status = dp_panel_read_sink_sts; @@ -3115,6 +3211,12 @@ struct dp_panel *dp_panel_get(struct dp_panel_in *in) } } + if (in->is_edp) { + rc = dp_panel_pwm_register(dp_panel); + if (rc) + DP_ERR("Failed to register pwm\n"); + } + return dp_panel; error: return ERR_PTR(rc); @@ -3132,6 +3234,9 @@ void dp_panel_put(struct dp_panel *dp_panel) dp_panel_edid_deregister(panel); sde_conn = to_sde_connector(dp_panel->connector); + + dp_panel_pwm_unregister(dp_panel); + if (sde_conn) sde_conn->drv_panel = NULL; diff --git a/msm/dp/dp_panel.h b/msm/dp/dp_panel.h index 822393143ab8..3abb41297584 100644 --- a/msm/dp/dp_panel.h +++ b/msm/dp/dp_panel.h @@ -18,6 +18,9 @@ #define DP_RECEIVER_DSC_CAP_SIZE 15 #define DP_RECEIVER_FEC_STATUS_SIZE 3 #define DP_RECEIVER_EXT_CAP_SIZE 4 +#define MAX_BL_LEVEL 4096 +#define MAX_BL_SCALE_LEVEL 1024 +#define MAX_SV_BL_SCALE_LEVEL 65535 /* * A source initiated power down flag is set * when the DP is powered off while physical @@ -86,6 +89,22 @@ struct dp_dsc_caps { u8 color_depth; }; +struct dp_backlight_config { + u32 bl_min_level; + u32 bl_max_level; + u32 brightness_max_level; + u32 bl_level; + u32 bl_scale; + u32 bl_scale_sv; + + int en_gpio; + /* PWM params */ + struct pwm_device *pwm_bl; + bool pwm_enabled; + u32 pwm_period_usecs; +}; + + struct dp_audio; #define DP_PANEL_CAPS_DSC BIT(0) @@ -102,6 +121,7 @@ struct dp_panel { struct drm_dp_link link_info; struct sde_edid_ctrl *edid_ctrl; struct dp_panel_info pinfo; + struct dp_backlight_config bl_config; bool video_test; bool spd_enabled; @@ -159,6 +179,7 @@ struct dp_panel { bool dhdr_update, u64 core_clk_rate, bool flush); int (*set_colorspace)(struct dp_panel *dp_panel, u32 colorspace); + int (*set_backlight)(struct dp_panel *dp_panel, u32 bl_lvl); void (*tpg_config)(struct dp_panel *dp_panel, bool enable); int (*spd_config)(struct dp_panel *dp_panel); bool (*hdr_supported)(struct dp_panel *dp_panel); diff --git a/msm/dp/dp_parser.c b/msm/dp/dp_parser.c index 7f5501a136bf..4503df56a81d 100644 --- a/msm/dp/dp_parser.c +++ b/msm/dp/dp_parser.c @@ -256,6 +256,47 @@ error: return rc; } +static void dp_parser_bl_config(struct dp_parser *parser) +{ + int rc = 0; + u32 val = 0; + struct device_node *of_node = parser->pdev->dev.of_node; + + rc = of_property_read_u32(of_node, "qcom,edp-bl-min-level", &val); + if (rc) { + DP_DEBUG("bl-min-level unspecified, defaulting to zero\n"); + parser->bl_min_level = 0; + } else { + parser->bl_min_level = val; + } + + rc = of_property_read_u32(of_node, "qcom,edp-bl-max-level", &val); + if (rc) { + DP_DEBUG("bl-max-level unspecified, defaulting to 4096\n"); + parser->bl_max_level = 4096; + } else { + parser->bl_max_level = val; + } + + rc = of_property_read_u32(of_node, "qcom,edp-brightness-max-level", + &val); + if (rc) { + DP_DEBUG("brigheness-max-level unspecified, defaulting to 255\n"); + parser->brightness_max_level = 255; + } else { + parser->brightness_max_level = val; + } + + rc = of_property_read_u32(of_node, "qcom,bl-pmic-pwm-period-usecs", + &val); + if (rc) { + DP_DEBUG("bl-pmic-pwm-period-usecs unspecified, default 100\n"); + parser->pwm_period_usecs = 100; + } else { + parser->pwm_period_usecs = val; + } +} + static int dp_parser_gpio(struct dp_parser *parser) { int i = 0; @@ -854,6 +895,7 @@ static int dp_parser_parse(struct dp_parser *parser) if (rc) goto err; + dp_parser_bl_config(parser); dp_parser_dsc(parser); dp_parser_fec(parser); dp_parser_widebus(parser); diff --git a/msm/dp/dp_parser.h b/msm/dp/dp_parser.h index 5444ee9e7050..da70b5674d51 100644 --- a/msm/dp/dp_parser.h +++ b/msm/dp/dp_parser.h @@ -235,7 +235,11 @@ static inline char *dp_phy_aux_config_type_to_string(u32 cfg_type) * @fec_feature_enable: FEC feature enable status * @dsc_continuous_pps: PPS sent every frame by HW * @has_widebus: widebus (2PPC) feature eanble status - *@mst_fixed_port: mst port_num reserved for fixed topology + * @bl_min_level: minimum brightness value for backlight + * @bl_max_level: maximum brightness value for backlight + * @brightness_max_level: maximum brightness level for backlight + * @pwm_period_usecs: pwm period in usecs for backlight pwm + * @mst_fixed_port: mst port_num reserved for fixed topology * @parse: function to be called by client to parse device tree. * @get_io: function to be called by client to get io data. * @get_io_buf: function to be called by client to get io buffers. @@ -267,6 +271,10 @@ struct dp_parser { bool gpio_aux_switch; bool lphw_hpd; bool panel_notifier_support; + u32 bl_min_level; + u32 bl_max_level; + u32 brightness_max_level; + u32 pwm_period_usecs; u32 mst_fixed_port[MAX_DP_MST_STREAMS]; u32 pixel_base_off[MAX_DP_MST_STREAMS]; const char *mst_fixed_display_type[MAX_DP_MST_STREAMS]; diff --git a/msm/sde/sde_connector.c b/msm/sde/sde_connector.c index 404e8af8c80f..8c23f622a97b 100644 --- a/msm/sde/sde_connector.c +++ b/msm/sde/sde_connector.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ @@ -16,6 +16,7 @@ #include #include "dsi_drm.h" #include "dsi_display.h" +#include "dp_panel.h" #include "sde_crtc.h" #include "sde_rm.h" #include "sde_vm.h" @@ -23,6 +24,7 @@ #define BL_NODE_NAME_SIZE 32 #define HDR10_PLUS_VSIF_TYPE_CODE 0x81 +#define MAX_BRIGHTNESS_LEVEL 255 /* Autorefresh will occur after FRAME_CNT frames. Large values are unlikely */ #define AUTOREFRESH_MAX_FRAME_CNT 6 @@ -93,13 +95,16 @@ static inline struct sde_kms *_sde_connector_get_kms(struct drm_connector *conn) static int sde_backlight_device_update_status(struct backlight_device *bd) { int brightness; - struct dsi_display *display; + struct dsi_display *dsi_display; + struct dp_panel *dp_panel; struct sde_connector *c_conn = bl_get_data(bd); int bl_lvl; struct drm_event event; int rc = 0; struct sde_kms *sde_kms; struct sde_vm_ops *vm_ops; + u32 bl_max_level = 0; + u32 brightness_max_level = 0; sde_kms = _sde_connector_get_kms(&c_conn->base); if (!sde_kms) { @@ -114,15 +119,27 @@ static int sde_backlight_device_update_status(struct backlight_device *bd) (bd->props.state & BL_CORE_SUSPENDED)) brightness = 0; - display = (struct dsi_display *) c_conn->display; - if (brightness > display->panel->bl_config.bl_max_level) - brightness = display->panel->bl_config.bl_max_level; + if (c_conn->connector_type == DRM_MODE_CONNECTOR_DSI) { + dsi_display = (struct dsi_display *) c_conn->display; + bl_max_level = dsi_display->panel->bl_config.bl_max_level; + brightness_max_level = + dsi_display->panel->bl_config.brightness_max_level; + } else if (c_conn->connector_type == DRM_MODE_CONNECTOR_eDP) { + dp_panel = (struct dp_panel *) c_conn->drv_panel; + if (dp_panel) { + bl_max_level = dp_panel->bl_config.bl_max_level; + brightness_max_level = + dp_panel->bl_config.brightness_max_level; + } + } + + if (brightness > bl_max_level) + brightness = bl_max_level; if (brightness > c_conn->thermal_max_brightness) brightness = c_conn->thermal_max_brightness; /* map UI brightness into driver backlight level with rounding */ - bl_lvl = mult_frac(brightness, display->panel->bl_config.bl_max_level, - display->panel->bl_config.brightness_max_level); + bl_lvl = mult_frac(brightness, bl_max_level, brightness_max_level); if (!bl_lvl && brightness) bl_lvl = 1; @@ -188,31 +205,46 @@ static int sde_backlight_setup(struct sde_connector *c_conn, { struct backlight_properties props; struct dsi_display *display; - struct dsi_backlight_config *bl_config; + struct dp_panel *dp_panel; + struct dsi_backlight_config *dsi_bl_config; struct sde_kms *sde_kms; static int display_count; char bl_node_name[BL_NODE_NAME_SIZE]; + u32 brightness_max_level = 0; sde_kms = _sde_connector_get_kms(&c_conn->base); if (!sde_kms) { SDE_ERROR("invalid kms\n"); return -EINVAL; - } else if (c_conn->connector_type != DRM_MODE_CONNECTOR_DSI) { + } + + if (c_conn->connector_type == DRM_MODE_CONNECTOR_DSI) { + display = (struct dsi_display *) c_conn->display; + dsi_bl_config = &display->panel->bl_config; + brightness_max_level = dsi_bl_config->brightness_max_level; + if (dsi_bl_config->type != DSI_BACKLIGHT_DCS && + sde_in_trusted_vm(sde_kms)) + return 0; + } else if (c_conn->connector_type == DRM_MODE_CONNECTOR_eDP) { + dp_panel = (struct dp_panel *) c_conn->drv_panel; + if (dp_panel) + brightness_max_level = + dp_panel->bl_config.brightness_max_level; + else { + brightness_max_level = MAX_BRIGHTNESS_LEVEL; + } + } else { + SDE_DEBUG("invalid connector type %d\n", + c_conn->connector_type); return 0; } - display = (struct dsi_display *) c_conn->display; - bl_config = &display->panel->bl_config; - - if (bl_config->type != DSI_BACKLIGHT_DCS && - sde_in_trusted_vm(sde_kms)) - return 0; memset(&props, 0, sizeof(props)); props.type = BACKLIGHT_RAW; props.power = FB_BLANK_UNBLANK; - props.max_brightness = bl_config->brightness_max_level; - props.brightness = bl_config->brightness_max_level; + props.max_brightness = brightness_max_level; + props.brightness = brightness_max_level; snprintf(bl_node_name, BL_NODE_NAME_SIZE, "panel%u-backlight", display_count); c_conn->bl_device = backlight_device_register(bl_node_name, dev->dev, @@ -223,7 +255,7 @@ static int sde_backlight_setup(struct sde_connector *c_conn, c_conn->bl_device = NULL; return -ENODEV; } - c_conn->thermal_max_brightness = bl_config->brightness_max_level; + c_conn->thermal_max_brightness = brightness_max_level; /** * In TVM, thermal cooling device is not enabled. Registering with dummy @@ -639,42 +671,62 @@ static int _sde_connector_update_power_locked(struct sde_connector *c_conn) static int _sde_connector_update_bl_scale(struct sde_connector *c_conn) { struct dsi_display *dsi_display; - struct dsi_backlight_config *bl_config; + struct dp_display *dp_display; + struct dsi_backlight_config *dsi_bl_config; + struct dp_backlight_config *dp_bl_config; + struct dp_panel *dp_panel; int rc = 0; + u32 bl_scale, bl_scale_sv; if (!c_conn) { SDE_ERROR("Invalid params sde_connector null\n"); return -EINVAL; } - dsi_display = c_conn->display; - if (!dsi_display || !dsi_display->panel) { - SDE_ERROR("Invalid params(s) dsi_display %pK, panel %pK\n", - dsi_display, - ((dsi_display) ? dsi_display->panel : NULL)); - return -EINVAL; - } - - bl_config = &dsi_display->panel->bl_config; - - if (!c_conn->allow_bl_update) { - c_conn->unset_bl_level = bl_config->bl_level; - return 0; - } - - if (c_conn->unset_bl_level) - bl_config->bl_level = c_conn->unset_bl_level; - - bl_config->bl_scale = c_conn->bl_scale > MAX_BL_SCALE_LEVEL ? + bl_scale = c_conn->bl_scale > MAX_BL_SCALE_LEVEL ? MAX_BL_SCALE_LEVEL : c_conn->bl_scale; - bl_config->bl_scale_sv = c_conn->bl_scale_sv > MAX_SV_BL_SCALE_LEVEL ? + bl_scale_sv = c_conn->bl_scale_sv > MAX_SV_BL_SCALE_LEVEL ? MAX_SV_BL_SCALE_LEVEL : c_conn->bl_scale_sv; - SDE_DEBUG("bl_scale = %u, bl_scale_sv = %u, bl_level = %u\n", - bl_config->bl_scale, bl_config->bl_scale_sv, - bl_config->bl_level); - rc = c_conn->ops.set_backlight(&c_conn->base, - dsi_display, bl_config->bl_level); + if (c_conn->connector_type == DRM_MODE_CONNECTOR_DSI) { + dsi_display = c_conn->display; + if (!dsi_display || !dsi_display->panel) { + SDE_ERROR("Invalid params dsi_display %pK, panel %pK\n", + dsi_display, + ((dsi_display) ? dsi_display->panel : NULL)); + return -EINVAL; + } + dsi_bl_config = &dsi_display->panel->bl_config; + if (!c_conn->allow_bl_update) { + c_conn->unset_bl_level = dsi_bl_config->bl_level; + return 0; + } + dsi_bl_config->bl_scale = bl_scale; + dsi_bl_config->bl_scale_sv = bl_scale_sv; + if (c_conn->unset_bl_level) + dsi_bl_config->bl_level = c_conn->unset_bl_level; + + rc = c_conn->ops.set_backlight(&c_conn->base, + dsi_display, dsi_bl_config->bl_level); + } else if (c_conn->connector_type == DRM_MODE_CONNECTOR_eDP) { + dp_display = c_conn->display; + dp_panel = (struct dp_panel *) c_conn->drv_panel; + if (dp_panel) { + dp_bl_config = &dp_panel->bl_config; + if (!c_conn->allow_bl_update) { + c_conn->unset_bl_level = dp_bl_config->bl_level; + return 0; + } + dp_bl_config->bl_scale = bl_scale; + dp_bl_config->bl_scale_sv = bl_scale_sv; + if (c_conn->unset_bl_level) + dp_bl_config->bl_level = c_conn->unset_bl_level; + rc = c_conn->ops.set_backlight(&c_conn->base, + dp_display, dp_bl_config->bl_level); + } else + SDE_ERROR("Invalid dp_panel null\n"); + } + c_conn->unset_bl_level = 0; return rc; diff --git a/msm/sde/sde_kms.c b/msm/sde/sde_kms.c index a24662dfaf52..e0df3cc96fd8 100644 --- a/msm/sde/sde_kms.c +++ b/msm/sde/sde_kms.c @@ -1255,6 +1255,16 @@ static void _sde_kms_release_splash_resource(struct sde_kms *sde_kms, SDE_EVT32(DRMID(crtc), crtc->state->active, sde_kms->splash_data.num_splash_displays); + /*remove all votes if eDP displays are done with splash*/ + if (dp_display_get_num_of_boot_displays()) { + for (i = 0; i < SDE_POWER_HANDLE_DBUS_ID_MAX; i++) + sde_power_data_bus_set_quota(phandle, i, + SDE_POWER_HANDLE_ENABLE_BUS_AB_QUOTA, + phandle->ib_quota[i]); + pm_runtime_put_sync(sde_kms->dev->dev); + sde_kms->splash_data.num_splash_displays--; + } + for (i = 0; i < MAX_DSI_DISPLAYS; i++) { splash_display = &sde_kms->splash_data.splash_display[i]; if (splash_display->encoder && @@ -1785,11 +1795,12 @@ static int _sde_kms_setup_displays(struct drm_device *dev, .get_info = dp_connector_get_info, .get_mode_info = dp_connector_get_mode_info, .post_open = dp_connector_post_open, + .set_backlight = dp_connector_set_backlight, .check_status = NULL, .set_colorspace = dp_connector_set_colorspace, .config_hdr = dp_connector_config_hdr, .cmd_transfer = NULL, - .cont_splash_config = NULL, + .cont_splash_config = dp_display_cont_splash_config, .cont_splash_res_disable = NULL, .get_panel_vfp = NULL, .update_pps = dp_connector_update_pps, @@ -3370,6 +3381,7 @@ static int sde_kms_cont_splash_config(struct msm_kms *kms, { void *display; struct dsi_display *dsi_display; + struct dp_display *dp_display; struct msm_display_info info; struct drm_encoder *encoder = NULL; struct drm_crtc *crtc = NULL; @@ -3520,6 +3532,57 @@ static int sde_kms_cont_splash_config(struct msm_kms *kms, } } + /* dp */ + for (i = 0; i < sde_kms->dp_display_count; ++i) { + display = sde_kms->dp_displays[i]; + dp_display = (struct dp_display *)display; + + if (!dp_display->cont_splash_enabled) { + SDE_DEBUG("DP-%d splash not enabled\n", i); + continue; + } + + if (dp_display->bridge->base.encoder) { + encoder = dp_display->bridge->base.encoder; + SDE_DEBUG("encoder name = %s\n", encoder->name); + } else { + SDE_DEBUG("Invalid encoder\n"); + break; + } + + mutex_lock(&dev->mode_config.mutex); + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { + /** + * SDE_KMS doesn't attach more than one encoder to + * a DSI connector. So it is safe to check only with + * the first encoder entry. Revisit this logic if we + * ever have to support continuous splash for + * external displays in MST configuration. + */ + if (connector->encoder_ids[0] == encoder->base.id) + break; + } + + drm_connector_list_iter_end(&conn_iter); + if (!connector) { + SDE_ERROR("connector not initialized\n"); + mutex_unlock(&dev->mode_config.mutex); + return -EINVAL; + } + mutex_unlock(&dev->mode_config.mutex); + + /* Enable all irqs */ + sde_irq_update(kms, true); + + sde_conn = to_sde_connector(connector); + if (sde_conn && sde_conn->ops.cont_splash_config) + sde_conn->ops.cont_splash_config(sde_conn->display); + + /* Disable irqs */ + sde_irq_update(kms, false); + } + return rc; } @@ -4427,7 +4490,7 @@ static int _sde_kms_get_splash_data(struct sde_kms *sde_kms, * Ex: */ num_displays = dsi_display_get_num_of_displays() - +dp_display_get_num_of_boot_displays(); + + dp_display_get_num_of_boot_displays(); num_regions = of_property_count_u64_elems(node, "reg") / 2; data->num_splash_displays = num_displays;