diff --git a/drivers/video/fbdev/msm/mdss_compat_utils.c b/drivers/video/fbdev/msm/mdss_compat_utils.c index 14d998d14eeb..17644e3556b6 100644 --- a/drivers/video/fbdev/msm/mdss_compat_utils.c +++ b/drivers/video/fbdev/msm/mdss_compat_utils.c @@ -125,6 +125,7 @@ static void __copy_atomic_commit_struct(struct mdp_layer_commit *commit, commit32->commit_v1.input_layer_cnt; commit->commit_v1.left_roi = commit32->commit_v1.left_roi; commit->commit_v1.right_roi = commit32->commit_v1.right_roi; + commit->commit_v1.bl_level = commit32->commit_v1.bl_level; memcpy(&commit->commit_v1.reserved, &commit32->commit_v1.reserved, sizeof(commit32->commit_v1.reserved)); } diff --git a/drivers/video/fbdev/msm/mdss_compat_utils.h b/drivers/video/fbdev/msm/mdss_compat_utils.h index 626792925cb6..4f44cd1c9471 100644 --- a/drivers/video/fbdev/msm/mdss_compat_utils.h +++ b/drivers/video/fbdev/msm/mdss_compat_utils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2017, 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 @@ -19,9 +19,9 @@ * To allow proper structure padding for 64bit/32bit target */ #ifdef __LP64 -#define MDP_LAYER_COMMIT_V1_PAD 3 +#define MDP_LAYER_COMMIT_V1_PAD 2 #else -#define MDP_LAYER_COMMIT_V1_PAD 4 +#define MDP_LAYER_COMMIT_V1_PAD 3 #endif struct mdp_buf_sync32 { @@ -537,6 +537,7 @@ struct mdp_layer_commit_v1_32 { compat_caddr_t dest_scaler; uint32_t dest_scaler_cnt; compat_caddr_t frc_info; + uint32_t bl_level; /* BL level to be updated in commit */ uint32_t reserved[MDP_LAYER_COMMIT_V1_PAD]; }; diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c index db27842eaccc..bf66c0cd430c 100644 --- a/drivers/video/fbdev/msm/mdss_fb.c +++ b/drivers/video/fbdev/msm/mdss_fb.c @@ -303,10 +303,23 @@ static void mdss_fb_set_bl_brightness(struct led_classdev *led_cdev, } } +static enum led_brightness mdss_fb_get_bl_brightness( + struct led_classdev *led_cdev) +{ + struct msm_fb_data_type *mfd = dev_get_drvdata(led_cdev->dev->parent); + enum led_brightness value; + + MDSS_BL_TO_BRIGHT(value, mfd->bl_level, mfd->panel_info->bl_max, + mfd->panel_info->brightness_max); + + return value; +} + static struct led_classdev backlight_led = { .name = "lcd-backlight", .brightness = MDSS_MAX_BL_BRIGHTNESS / 2, .brightness_set = mdss_fb_set_bl_brightness, + .brightness_get = mdss_fb_get_bl_brightness, .max_brightness = MDSS_MAX_BL_BRIGHTNESS, }; @@ -3422,6 +3435,14 @@ int mdss_fb_atomic_commit(struct fb_info *info, mfd->msm_fb_backup.disp_commit.l_roi = commit_v1->left_roi; mfd->msm_fb_backup.disp_commit.r_roi = commit_v1->right_roi; mfd->msm_fb_backup.disp_commit.flags = commit_v1->flags; + if (commit_v1->flags & MDP_COMMIT_UPDATE_BRIGHTNESS) { + MDSS_BRIGHT_TO_BL(mfd->bl_extn_level, commit_v1->bl_level, + mfd->panel_info->bl_max, + mfd->panel_info->brightness_max); + if (!mfd->bl_extn_level && commit_v1->bl_level) + mfd->bl_extn_level = 1; + } else + mfd->bl_extn_level = -1; mutex_lock(&mfd->mdp_sync_pt_data.sync_mutex); atomic_inc(&mfd->mdp_sync_pt_data.commit_cnt); diff --git a/drivers/video/fbdev/msm/mdss_fb.h b/drivers/video/fbdev/msm/mdss_fb.h index d64580a35775..321531c72a08 100644 --- a/drivers/video/fbdev/msm/mdss_fb.h +++ b/drivers/video/fbdev/msm/mdss_fb.h @@ -241,6 +241,10 @@ struct msm_mdp_interface { out = (2 * (v) * (bl_max) + max_bright);\ do_div(out, 2 * max_bright);\ } while (0) +#define MDSS_BL_TO_BRIGHT(out, v, bl_max, max_bright) do {\ + out = ((v) * (max_bright));\ + do_div(out, bl_max);\ + } while (0) struct mdss_fb_file_info { struct file *file; @@ -305,6 +309,7 @@ struct msm_fb_data_type { u32 calib_mode_bl; u32 ad_bl_level; u32 bl_level; + int bl_extn_level; u32 bl_scale; u32 unset_bl_level; bool allow_bl_update; diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h index 36a866685f21..0e789781d2c7 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.h +++ b/drivers/video/fbdev/msm/mdss_mdp.h @@ -421,6 +421,9 @@ struct mdss_mdp_ctl_intfs_ops { /* to update lineptr, [1..yres] - enable, 0 - disable */ int (*update_lineptr)(struct mdss_mdp_ctl *ctl, bool enable); int (*avr_ctrl_fnc)(struct mdss_mdp_ctl *, bool enable); + + /* to wait for vsync */ + int (*wait_for_vsync_fnc)(struct mdss_mdp_ctl *ctl); }; struct mdss_mdp_cwb { diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c index 7b0207de101a..37f27aa43fe1 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c +++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c @@ -5704,6 +5704,15 @@ static void mdss_mdp_force_border_color(struct mdss_mdp_ctl *ctl) ctl->mixer_right->params_changed++; } +static bool mdss_mdp_handle_backlight_extn(struct mdss_mdp_ctl *ctl) +{ + if (ctl->intf_type == MDSS_INTF_DSI && !ctl->is_video_mode && + ctl->mfd->bl_extn_level >= 0) + return true; + else + return false; +} + int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg, struct mdss_mdp_commit_cb *commit_cb) { @@ -5872,6 +5881,15 @@ int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg, if (ctl->ops.wait_pingpong && !mdata->serialize_wait4pp) mdss_mdp_display_wait4pingpong(ctl, false); + /* + * If backlight needs to change, wait for 1 vsync before setting + * PCC and kickoff + */ + if (mdss_mdp_handle_backlight_extn(ctl) && + ctl->ops.wait_for_vsync_fnc) { + ret = ctl->ops.wait_for_vsync_fnc(ctl); + } + /* Moved pp programming to post ping pong */ if (!ctl->is_video_mode && ctl->mfd && ctl->mfd->dcm_state != DTM_ENTER) { @@ -6020,6 +6038,17 @@ int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg, if (ret) pr_warn("ctl %d error displaying frame\n", ctl->num); + /* update backlight in commit */ + if (mdss_mdp_handle_backlight_extn(ctl)) { + if (!IS_CALIB_MODE_BL(ctl->mfd) && (!ctl->mfd->ext_bl_ctrl || + !ctl->mfd->bl_level)) { + mutex_lock(&ctl->mfd->bl_lock); + mdss_fb_set_backlight(ctl->mfd, + ctl->mfd->bl_extn_level); + mutex_unlock(&ctl->mfd->bl_lock); + } + } + ctl->play_cnt++; ATRACE_END("flush_kickoff"); diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c index dfd6226ce602..8887ba810d99 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c +++ b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c @@ -2917,6 +2917,41 @@ static void __mdss_mdp_kickoff(struct mdss_mdp_ctl *ctl, } } +int mdss_mdp_cmd_wait4_vsync(struct mdss_mdp_ctl *ctl) +{ + int rc = 0; + struct mdss_mdp_cmd_ctx *ctx = ctl->intf_ctx[MASTER_CTX]; + + if (!ctx) { + pr_err("invalid context to wait for vsync\n"); + return rc; + } + + atomic_inc(&ctx->rdptr_cnt); + + /* enable clks and rd_ptr interrupt */ + mdss_mdp_setup_vsync(ctx, true); + + /* wait for read pointer */ + MDSS_XLOG(atomic_read(&ctx->rdptr_cnt)); + pr_debug("%s: wait for vsync cnt:%d\n", + __func__, atomic_read(&ctx->rdptr_cnt)); + + rc = mdss_mdp_cmd_wait4readptr(ctx); + + /* wait for 1ms to make sure we are out from trigger window */ + usleep_range(1000, 1010); + + /* disable rd_ptr interrupt */ + mdss_mdp_setup_vsync(ctx, false); + + MDSS_XLOG(ctl->num); + pr_debug("%s: out from wait for rd_ptr ctl:%d\n", __func__, ctl->num); + + return rc; +} + + /* * There are 3 partial update possibilities * left only ==> enable left pingpong_done @@ -3373,6 +3408,7 @@ panel_events: ctl->ops.add_vsync_handler = NULL; ctl->ops.remove_vsync_handler = NULL; ctl->ops.reconfigure = NULL; + ctl->ops.wait_for_vsync_fnc = NULL; end: if (!IS_ERR_VALUE(ret)) { @@ -3773,6 +3809,7 @@ int mdss_mdp_cmd_start(struct mdss_mdp_ctl *ctl) ctl->ops.pre_programming = mdss_mdp_cmd_pre_programming; ctl->ops.update_lineptr = mdss_mdp_cmd_update_lineptr; ctl->ops.panel_disable_cfg = mdss_mdp_cmd_panel_disable_cfg; + ctl->ops.wait_for_vsync_fnc = mdss_mdp_cmd_wait4_vsync; pr_debug("%s:-\n", __func__); return 0; diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c index 5173567a3420..b7f9d2e7fb1d 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c +++ b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c @@ -2340,6 +2340,7 @@ int mdss_mdp_video_start(struct mdss_mdp_ctl *ctl) ctl->ops.early_wake_up_fnc = mdss_mdp_video_early_wake_up; ctl->ops.update_lineptr = mdss_mdp_video_lineptr_ctrl; ctl->ops.avr_ctrl_fnc = mdss_mdp_video_avr_ctrl; + ctl->ops.wait_for_vsync_fnc = NULL; return 0; } diff --git a/include/uapi/linux/msm_mdp_ext.h b/include/uapi/linux/msm_mdp_ext.h index ee68675bfe13..35029f227f8b 100644 --- a/include/uapi/linux/msm_mdp_ext.h +++ b/include/uapi/linux/msm_mdp_ext.h @@ -40,9 +40,9 @@ * To allow proper structure padding for 64bit/32bit target */ #ifdef __LP64 -#define MDP_LAYER_COMMIT_V1_PAD 3 +#define MDP_LAYER_COMMIT_V1_PAD 2 #else -#define MDP_LAYER_COMMIT_V1_PAD 4 +#define MDP_LAYER_COMMIT_V1_PAD 3 #endif /********************************************************************** @@ -166,6 +166,9 @@ VALIDATE/COMMIT FLAG CONFIGURATION /* Flag to indicate dual partial ROI update */ #define MDP_COMMIT_PARTIAL_UPDATE_DUAL_ROI 0x20 +/* Flag to update brightness when commit */ +#define MDP_COMMIT_UPDATE_BRIGHTNESS 0x40 + /* Flag to enable concurrent writeback for the frame */ #define MDP_COMMIT_CWB_EN 0x800 @@ -568,6 +571,9 @@ struct mdp_layer_commit_v1 { */ uint32_t dest_scaler_cnt; + /* Backlight level that would update when display commit */ + uint32_t bl_level; + /* 32-bits reserved value for future usage. */ uint32_t reserved[MDP_LAYER_COMMIT_V1_PAD]; };