drm/msm/dp: add connector functionality to configure HDR

Add connector function pointer to configure HDR setting as
per user-space. When user-space sets CONNECTOR_PROP_HDR_METADATA
property with HDR metadata for current HDR video stream,
call config_hdr to let the external interface configure the
hardware with HDR settings.

CRs-Fixed: 2157993
Change-Id: I83b560baadf237ab26cb003cdbc4f8b64b532432
Signed-off-by: Ajay Singh Parmar <aparmar@codeaurora.org>
tirimbino
Ajay Singh Parmar 7 years ago committed by Gerrit - the friendly Code Review server
parent ed44fe7f26
commit 39fdd781e3
  1. 4
      drivers/gpu/drm/msm/dp/dp_debug.c
  2. 26
      drivers/gpu/drm/msm/dp/dp_display.c
  3. 4
      drivers/gpu/drm/msm/dp/dp_display.h
  4. 11
      drivers/gpu/drm/msm/dp/dp_drm.c
  5. 12
      drivers/gpu/drm/msm/dp/dp_drm.h
  6. 46
      drivers/gpu/drm/msm/dp/dp_panel.c
  7. 19
      drivers/gpu/drm/msm/sde/sde_connector.c
  8. 12
      drivers/gpu/drm/msm/sde/sde_connector.h
  9. 2
      drivers/gpu/drm/msm/sde/sde_kms.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;
}

@ -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 <linux/of_irq.h>
#include <linux/hdcp_qseecom.h>
#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) {

@ -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);
};

@ -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)

@ -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

@ -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;
}

@ -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,

@ -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);
};
/**

@ -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;

Loading…
Cancel
Save