mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-25 22:23:14 -04:00
Merge commit '452e643352' into display-kernel.lnx.5.4.r8-rel
Change-Id: I5e9066dcb3f69b8123621056c60b322af4897a62 Signed-off-by: Venkata Prahlad Valluru <quic_vvalluru@quicinc.com>
This commit is contained in:
commit
73d4a4007a
10 changed files with 476 additions and 47 deletions
|
|
@ -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=<display node>:<configX> where <display node> is 'primary dp display node name' and <configX> where x represents index in the topology list");
|
||||
=======
|
||||
"msm_drm.edp_display0=<display node>: where <display node> is 'primary dp display node name' ");
|
||||
>>>>>>> 452e643352bd41612f5634d8b38d7be9cbc9a875
|
||||
|
|
|
|||
|
|
@ -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_ */
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "dp_panel.h"
|
||||
#include <linux/unistd.h>
|
||||
#include <linux/pwm.h>
|
||||
#include <drm/drm_fixed.h>
|
||||
#include "dp_debug.h"
|
||||
#include <drm/drm_dsc.h>
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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 <linux/string.h>
|
||||
#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;
|
||||
|
|
|
|||
|
|
@ -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: <r1.start r1.end r2.start r2.end ... rn.start, rn.end>
|
||||
*/
|
||||
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;
|
||||
|
|
|
|||
Loading…
Reference in a new issue