diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c b/drivers/gpu/drm/msm/dp/dp_debug.c index 0b3d903171e2..054b3c849e65 100644 --- a/drivers/gpu/drm/msm/dp/dp_debug.c +++ b/drivers/gpu/drm/msm/dp/dp_debug.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -665,6 +665,8 @@ static ssize_t dp_debug_write_hdr(struct file *file, pr_err("invalid input\n"); len = -EINVAL; } + + debug->panel->setup_hdr(debug->panel, &c_state->hdr_meta); end: return len; } diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index cec00dac8225..65bbd20831da 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -22,6 +22,8 @@ #include #include +#include "sde_connector.h" + #include "msm_drv.h" #include "dp_usbpd.h" #include "dp_parser.h" @@ -1079,6 +1081,8 @@ static int dp_display_post_enable(struct dp_display *dp_display) dp->hdcp_status = HDCP_STATE_AUTHENTICATING; queue_delayed_work(dp->wq, &dp->hdcp_cb_work, HZ / 2); } + + dp->panel->setup_hdr(dp->panel, NULL); end: /* clear framework event notifier */ dp_display->post_open = NULL; @@ -1123,6 +1127,8 @@ end: static int dp_display_disable(struct dp_display *dp_display) { struct dp_display_private *dp; + struct drm_connector *connector; + struct sde_connector_state *c_state; if (!dp_display) { pr_err("invalid input\n"); @@ -1130,6 +1136,8 @@ static int dp_display_disable(struct dp_display *dp_display) } dp = container_of(dp_display, struct dp_display_private, dp_display); + connector = dp->dp_display.connector; + c_state = to_sde_connector_state(connector->state); mutex_lock(&dp->session_lock); @@ -1141,6 +1149,14 @@ static int dp_display_disable(struct dp_display *dp_display) dp->ctrl->off(dp->ctrl); dp->panel->deinit(dp->panel); + connector->hdr_eotf = 0; + connector->hdr_metadata_type_one = 0; + connector->hdr_max_luminance = 0; + connector->hdr_avg_luminance = 0; + connector->hdr_min_luminance = 0; + + memset(&c_state->hdr_meta, 0, sizeof(c_state->hdr_meta)); + dp->power_on = false; end: @@ -1250,8 +1266,7 @@ static int dp_display_get_modes(struct dp_display *dp, return ret; } - -static int dp_display_pre_kickoff(struct dp_display *dp_display, +static int dp_display_config_hdr(struct dp_display *dp_display, struct drm_msm_ext_hdr_metadata *hdr) { int rc = 0; @@ -1264,8 +1279,7 @@ static int dp_display_pre_kickoff(struct dp_display *dp_display, dp = container_of(dp_display, struct dp_display_private, dp_display); - if (hdr->hdr_supported && dp->panel->hdr_supported(dp->panel)) - rc = dp->panel->setup_hdr(dp->panel, hdr); + rc = dp->panel->setup_hdr(dp->panel, hdr); return rc; } @@ -1330,7 +1344,7 @@ static int dp_display_probe(struct platform_device *pdev) g_dp_display->get_debug = dp_get_debug; g_dp_display->post_open = dp_display_post_open; g_dp_display->post_init = dp_display_post_init; - g_dp_display->pre_kickoff = dp_display_pre_kickoff; + g_dp_display->config_hdr = dp_display_config_hdr; rc = component_add(&pdev->dev, &dp_display_comp_ops); if (rc) { diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h index c55e6c8e881e..266de5fe174b 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.h +++ b/drivers/gpu/drm/msm/dp/dp_display.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -43,7 +43,7 @@ struct dp_display { int (*request_irq)(struct dp_display *dp_display); struct dp_debug *(*get_debug)(struct dp_display *dp_display); void (*post_open)(struct dp_display *dp_display); - int (*pre_kickoff)(struct dp_display *dp_display, + int (*config_hdr)(struct dp_display *dp_display, struct drm_msm_ext_hdr_metadata *hdr_meta); void (*post_init)(struct dp_display *dp_display); }; diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c index 0b1b4088aaeb..8ef8d87ff7c0 100644 --- a/drivers/gpu/drm/msm/dp/dp_drm.c +++ b/drivers/gpu/drm/msm/dp/dp_drm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -276,18 +276,17 @@ static const struct drm_bridge_funcs dp_bridge_ops = { .mode_set = dp_bridge_mode_set, }; -int dp_connector_pre_kickoff(struct drm_connector *connector, - void *display, - struct msm_display_kickoff_params *params) +int dp_connector_config_hdr(void *display, + struct sde_connector_state *c_state) { struct dp_display *dp = display; - if (!connector || !display || !params) { + if (!display || !c_state) { pr_err("invalid params\n"); return -EINVAL; } - return dp->pre_kickoff(dp, params->hdr_meta); + return dp->config_hdr(dp, &c_state->hdr_meta); } int dp_connector_post_init(struct drm_connector *connector, void *display) diff --git a/drivers/gpu/drm/msm/dp/dp_drm.h b/drivers/gpu/drm/msm/dp/dp_drm.h index 89b0a7ee84cf..3ca10c2c9c5c 100644 --- a/drivers/gpu/drm/msm/dp/dp_drm.h +++ b/drivers/gpu/drm/msm/dp/dp_drm.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -32,15 +32,13 @@ struct dp_bridge { }; /** - * dp_connector_pre_kickoff - callback to perform pre kickoff initialization - * @connector: Pointer to drm connector structure + * dp_connector_config_hdr - callback to configure HDR * @display: Pointer to private display handle - * @params: Pointer to kickoff parameters + * @c_state: connect state data * Returns: Zero on success */ -int dp_connector_pre_kickoff(struct drm_connector *connector, - void *display, - struct msm_display_kickoff_params *params); +int dp_connector_config_hdr(void *display, + struct sde_connector_state *c_state); /** * dp_connector_post_init - callback to perform additional initialization steps diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c index 7a685ffac756..78847e5959fb 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.c +++ b/drivers/gpu/drm/msm/dp/dp_panel.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -645,6 +645,7 @@ static int dp_panel_deinit_panel_info(struct dp_panel *dp_panel) { int rc = 0; struct dp_panel_private *panel; + struct dp_catalog_hdr_data *hdr; if (!dp_panel) { pr_err("invalid input\n"); @@ -652,11 +653,13 @@ static int dp_panel_deinit_panel_info(struct dp_panel *dp_panel) } panel = container_of(dp_panel, struct dp_panel_private, dp_panel); + hdr = &panel->catalog->hdr_data; if (!panel->custom_edid) sde_free_edid((void **)&dp_panel->edid_ctrl); memset(&dp_panel->pinfo, 0, sizeof(dp_panel->pinfo)); + memset(&hdr->hdr_meta, 0, sizeof(hdr->hdr_meta)); panel->panel_on = false; return rc; @@ -703,30 +706,6 @@ static bool dp_panel_hdr_supported(struct dp_panel *dp_panel) (panel->minor >= 4 || panel->vscext_supported); } -static bool dp_panel_is_validate_hdr_state(struct dp_panel_private *panel, - struct drm_msm_ext_hdr_metadata *hdr_meta) -{ - struct drm_msm_ext_hdr_metadata *panel_hdr_meta = - &panel->catalog->hdr_data.hdr_meta; - - if (!hdr_meta) - goto end; - - /* bail out if HDR not active */ - if (hdr_meta->hdr_state == HDR_DISABLED && - panel->hdr_state == HDR_DISABLED) - goto end; - - /* bail out if same meta data is received */ - if (hdr_meta->hdr_state == HDR_ENABLED && - panel_hdr_meta->eotf == hdr_meta->eotf) - goto end; - - return true; -end: - return false; -} - static int dp_panel_setup_hdr(struct dp_panel *dp_panel, struct drm_msm_ext_hdr_metadata *hdr_meta) { @@ -741,14 +720,18 @@ static int dp_panel_setup_hdr(struct dp_panel *dp_panel, } panel = container_of(dp_panel, struct dp_panel_private, dp_panel); + hdr = &panel->catalog->hdr_data; - if (!dp_panel_is_validate_hdr_state(panel, hdr_meta)) - goto end; + /* use cached meta data in case meta data not provided */ + if (!hdr_meta) { + if (hdr->hdr_meta.hdr_state) + goto cached; + else + goto end; + } panel->hdr_state = hdr_meta->hdr_state; - hdr = &panel->catalog->hdr_data; - hdr->ext_header_byte0 = 0x00; hdr->ext_header_byte1 = 0x04; hdr->ext_header_byte2 = 0x1F; @@ -783,8 +766,9 @@ static int dp_panel_setup_hdr(struct dp_panel *dp_panel, memcpy(&hdr->hdr_meta, hdr_meta, sizeof(hdr->hdr_meta)); else memset(&hdr->hdr_meta, 0, sizeof(hdr->hdr_meta)); - - panel->catalog->config_hdr(panel->catalog, panel->hdr_state); +cached: + if (panel->panel_on) + panel->catalog->config_hdr(panel->catalog, panel->hdr_state); end: return rc; } diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c index 26d408a457c3..86002524308d 100644 --- a/drivers/gpu/drm/msm/sde/sde_connector.c +++ b/drivers/gpu/drm/msm/sde/sde_connector.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -939,34 +939,38 @@ static int _sde_connector_set_ext_hdr_info( struct sde_connector_state *c_state, void *usr_ptr) { + int rc = 0; struct drm_connector *connector; struct drm_msm_ext_hdr_metadata *hdr_meta; int i; if (!c_conn || !c_state) { SDE_ERROR_CONN(c_conn, "invalid args\n"); - return -EINVAL; + rc = -EINVAL; + goto end; } connector = &c_conn->base; if (!connector->hdr_supported) { SDE_ERROR_CONN(c_conn, "sink doesn't support HDR\n"); - return -ENOTSUPP; + rc = -ENOTSUPP; + goto end; } memset(&c_state->hdr_meta, 0, sizeof(c_state->hdr_meta)); if (!usr_ptr) { SDE_DEBUG_CONN(c_conn, "hdr metadata cleared\n"); - return 0; + goto end; } if (copy_from_user(&c_state->hdr_meta, (void __user *)usr_ptr, sizeof(*hdr_meta))) { SDE_ERROR_CONN(c_conn, "failed to copy hdr metadata\n"); - return -EFAULT; + rc = -EFAULT; + goto end; } hdr_meta = &c_state->hdr_meta; @@ -989,7 +993,10 @@ static int _sde_connector_set_ext_hdr_info( hdr_meta->display_primaries_y[i]); } - return 0; + if (c_conn->ops.config_hdr) + rc = c_conn->ops.config_hdr(c_conn->display, c_state); +end: + return rc; } static int sde_connector_atomic_set_property(struct drm_connector *connector, diff --git a/drivers/gpu/drm/msm/sde/sde_connector.h b/drivers/gpu/drm/msm/sde/sde_connector.h index 7cf09b7fb568..9c37869d35bd 100644 --- a/drivers/gpu/drm/msm/sde/sde_connector.h +++ b/drivers/gpu/drm/msm/sde/sde_connector.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -241,6 +241,16 @@ struct sde_connector_ops { */ int (*cmd_transfer)(void *display, const char *cmd_buf, u32 cmd_buf_len); + + /** + * config_hdr - configure HDR + * @display: Pointer to private display handle + * @c_state: Pointer to connector state + * Returns: Zero on success, negative error code for failures + */ + int (*config_hdr)(void *display, + struct sde_connector_state *c_state); + }; /** diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c index 3523111af588..846cd14024c6 100644 --- a/drivers/gpu/drm/msm/sde/sde_kms.c +++ b/drivers/gpu/drm/msm/sde/sde_kms.c @@ -949,7 +949,7 @@ static int _sde_kms_setup_displays(struct drm_device *dev, .get_mode_info = dp_connector_get_mode_info, .post_open = dp_connector_post_open, .check_status = NULL, - .pre_kickoff = dp_connector_pre_kickoff, + .config_hdr = dp_connector_config_hdr, .cmd_transfer = NULL, }; struct msm_display_info info;