diff --git a/drivers/video/fbdev/msm/mdss.h b/drivers/video/fbdev/msm/mdss.h index 911c4e2e6637..43bcd48ba246 100644 --- a/drivers/video/fbdev/msm/mdss.h +++ b/drivers/video/fbdev/msm/mdss.h @@ -171,7 +171,7 @@ struct mdss_data_type { u8 has_non_scalar_rgb; bool has_src_split; bool idle_pc_enabled; - bool has_dst_split; + bool has_pingpong_split; bool has_pixel_ram; bool needs_hist_vote; diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c index 328fb1400eb3..c070759eace7 100644 --- a/drivers/video/fbdev/msm/mdss_fb.c +++ b/drivers/video/fbdev/msm/mdss_fb.c @@ -301,6 +301,11 @@ static inline int mdss_fb_validate_split(int left, int right, { int rc = -EINVAL; u32 panel_xres = mdss_fb_get_panel_xres(mfd->panel_info); + + pr_debug("%pS: split_mode = %d left=%d right=%d panel_xres=%d\n", + __builtin_return_address(0), mfd->split_mode, + left, right, panel_xres); + /* more validate condition could be added if needed */ if (left && right) { if (panel_xres == left + right) { @@ -309,7 +314,7 @@ static inline int mdss_fb_validate_split(int left, int right, rc = 0; } } else { - if (is_split_lm(mfd)) { + if (mfd->split_mode == MDP_DUAL_LM_DUAL_DISPLAY) { mfd->split_fb_left = mfd->panel_info->xres; mfd->split_fb_right = panel_xres - mfd->split_fb_left; rc = 0; @@ -330,7 +335,8 @@ static void mdss_fb_parse_dt_split(struct msm_fb_data_type *mfd) "qcom,mdss-fb-split", data, 2); if (!mdss_fb_validate_split(data[0], data[1], mfd)) - pr_debug("dt split_left=%d split_right=%d\n", data[0], data[1]); + pr_info_once("device tree split left=%d right=%d\n", + data[0], data[1]); } static ssize_t mdss_fb_store_split(struct device *dev, @@ -370,9 +376,28 @@ static void mdss_fb_get_split(struct msm_fb_data_type *mfd) if (!mfd->mdss_fb_split_stored) mdss_fb_parse_dt_split(mfd); - if (mfd->split_fb_left || mfd->split_fb_right) - pr_debug("split framebuffer left=%d right=%d\n", - mfd->split_fb_left, mfd->split_fb_right); + if ((mfd->split_mode == MDP_SPLIT_MODE_NONE) && + (mfd->split_fb_left || mfd->split_fb_right)) + mfd->split_mode = MDP_DUAL_LM_SINGLE_DISPLAY; + + pr_debug("split framebuffer left=%d right=%d mode=%d\n", + mfd->split_fb_left, mfd->split_fb_right, mfd->split_mode); +} + +static ssize_t mdss_fb_get_src_split_info(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int ret = 0; + struct fb_info *fbi = dev_get_drvdata(dev); + struct msm_fb_data_type *mfd = fbi->par; + + if (is_split_lm(mfd) && (fbi->var.yres > fbi->var.xres)) { + pr_debug("always split mode enabled\n"); + ret = scnprintf(buf, PAGE_SIZE, + "src_split_always\n"); + } + + return ret; } static ssize_t mdss_fb_get_thermal_level(struct device *dev, @@ -588,21 +613,6 @@ static int mdss_fb_lpm_enable(struct msm_fb_data_type *mfd, int mode) return 0; } -static ssize_t mdss_fb_get_src_split_info(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct fb_info *fbi = dev_get_drvdata(dev); - struct msm_fb_data_type *mfd = fbi->par; - int ret = 0; - - if ((mfd->split_mode == MDP_SPLIT_MODE_LM) && - (fbi->var.yres > 2048) && (fbi->var.yres > fbi->var.xres)) - ret = scnprintf(buf, PAGE_SIZE, - "src_split_always\n"); - - return ret; -} - static DEVICE_ATTR(msm_fb_type, S_IRUGO, mdss_fb_get_type, NULL); static DEVICE_ATTR(msm_fb_split, S_IRUGO | S_IWUSR, mdss_fb_show_split, mdss_fb_store_split); @@ -699,9 +709,11 @@ static int mdss_fb_probe(struct platform_device *pdev) mfd->fb_imgType = MDP_RGBA_8888; mfd->pdev = pdev; + mfd->split_mode = MDP_SPLIT_MODE_NONE; if (pdata->next) - mfd->split_mode = MDP_SPLIT_MODE_LM; + mfd->split_mode = MDP_DUAL_LM_DUAL_DISPLAY; + mfd->mdp = *mdp_instance; INIT_LIST_HEAD(&mfd->proc_list); @@ -715,6 +727,8 @@ static int mdss_fb_probe(struct platform_device *pdev) if (rc) return rc; + mdss_fb_get_split(mfd); + if (mfd->mdp.init_fnc) { rc = mfd->mdp.init_fnc(mfd); if (rc) { @@ -1136,6 +1150,7 @@ static int mdss_fb_start_disp_thread(struct msm_fb_data_type *mfd) pr_debug("%pS: start display thread fb%d\n", __builtin_return_address(0), mfd->index); + /* this is needed for new split request from debugfs */ mdss_fb_get_split(mfd); atomic_set(&mfd->commits_pending, 0); diff --git a/drivers/video/fbdev/msm/mdss_fb.h b/drivers/video/fbdev/msm/mdss_fb.h index b1f41d8b4099..258a099607ae 100644 --- a/drivers/video/fbdev/msm/mdss_fb.h +++ b/drivers/video/fbdev/msm/mdss_fb.h @@ -84,15 +84,26 @@ enum mdp_notify_event { /** * enum mdp_split_mode - Lists the possible split modes in the device * - * @MDP_SPLIT_MODE_NONE: Not a Dual display, no panel split. - * @MDP_SPLIT_MODE_LM: Dual Display is true, Split across layer mixers - * @MDP_SPLIT_MODE_DST: Dual Display is true, Split is in the Destination - * i.e ping pong split. + * @MDP_SPLIT_MODE_NONE: Single physical display with single ctl path + * and single layer mixer. + * i.e. 1080p single DSI with single LM. + * #MDP_DUAL_LM_SINGLE_DISPLAY: Single physical display with signle ctl + * path but two layer mixers. + * i.e. WQXGA eDP or 4K HDMI primary or 1080p + * single DSI with split LM to reduce power. + * @MDP_DUAL_LM_DUAL_DISPLAY: Two physically separate displays with two + * separate but synchronized ctl paths. Each ctl + * path with its own layer mixer. + * i.e. 1440x2560 with two DSI interfaces. + * @MDP_PINGPONG_SPLIT: Two physically separate display but single ctl path with + * single layer mixer. Data is split at pingpong module. + * i.e. 1440x2560 on chipsets with single DSI interface. */ enum mdp_split_mode { MDP_SPLIT_MODE_NONE, - MDP_SPLIT_MODE_LM, - MDP_SPLIT_MODE_DST, + MDP_DUAL_LM_SINGLE_DISPLAY, + MDP_DUAL_LM_DUAL_DISPLAY, + MDP_PINGPONG_SPLIT, }; struct disp_info_type_suspend { @@ -298,20 +309,24 @@ static inline void mdss_fb_update_notify_update(struct msm_fb_data_type *mfd) } } -/* Function returns true for either Layer Mixer split or Ping pong split */ +/* Function returns true for either any kind of dual display */ static inline bool is_panel_split(struct msm_fb_data_type *mfd) { - return (mfd && (!(mfd->split_mode == MDP_SPLIT_MODE_NONE))); + return mfd && + (mfd->split_mode == MDP_DUAL_LM_DUAL_DISPLAY || + mfd->split_mode == MDP_PINGPONG_SPLIT); } -/* Function returns true, if Layer Mixer split is Set*/ +/* Function returns true, if Layer Mixer split is Set */ static inline bool is_split_lm(struct msm_fb_data_type *mfd) { - return (mfd && (mfd->split_mode == MDP_SPLIT_MODE_LM)); + return mfd && + (mfd->split_mode == MDP_DUAL_LM_DUAL_DISPLAY || + mfd->split_mode == MDP_DUAL_LM_SINGLE_DISPLAY); } /* Function returns true, if Ping pong split is Set*/ -static inline bool is_split_dst(struct msm_fb_data_type *mfd) +static inline bool is_pingpong_split(struct msm_fb_data_type *mfd) { - return (mfd && (mfd->split_mode == MDP_SPLIT_MODE_DST)); + return mfd && (mfd->split_mode == MDP_PINGPONG_SPLIT); } static inline bool mdss_fb_is_power_off(struct msm_fb_data_type *mfd) diff --git a/drivers/video/fbdev/msm/mdss_mdp.c b/drivers/video/fbdev/msm/mdss_mdp.c index 22e1f038ca19..e2c58a5186c7 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.c +++ b/drivers/video/fbdev/msm/mdss_mdp.c @@ -2731,7 +2731,7 @@ static int mdss_mdp_parse_dt_misc(struct platform_device *pdev) if (rc) pr_debug("Could not read optional property: highest bank bit\n"); - mdata->has_dst_split = of_property_read_bool(pdev->dev.of_node, + mdata->has_pingpong_split = of_property_read_bool(pdev->dev.of_node, "qcom,mdss-has-dst-split"); /* diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c index 5f2c701c5b10..34ab946ee55b 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c +++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c @@ -1888,7 +1888,7 @@ static inline u32 get_panel_width(struct mdss_mdp_ctl *ctl) u32 width; width = get_panel_xres(&ctl->panel_data->panel_info); - if (ctl->panel_data->next && is_split_dst(ctl->mfd)) + if (ctl->panel_data->next && is_pingpong_split(ctl->mfd)) width += get_panel_xres(&ctl->panel_data->next->panel_info); return width; @@ -1959,8 +1959,8 @@ int mdss_mdp_ctl_setup(struct mdss_mdp_ctl *ctl) ctl->mixer_left->height = height; ctl->mixer_left->roi = (struct mdss_rect) {0, 0, width, height}; - if (is_panel_split(ctl->mfd)) { - pr_debug("split display detected\n"); + if (ctl->mfd->split_mode == MDP_DUAL_LM_DUAL_DISPLAY) { + pr_debug("dual display detected\n"); return 0; } @@ -2423,7 +2423,7 @@ static int mdss_mdp_ctl_start_sub(struct mdss_mdp_ctl *ctl, bool handoff) temp = readl_relaxed(ctl->mdata->mdp_base + MDSS_MDP_REG_DISP_INTF_SEL); temp |= (ctl->intf_type << ((ctl->intf_num - MDSS_MDP_INTF0) * 8)); - if (is_split_dst(ctl->mfd)) + if (is_pingpong_split(ctl->mfd)) temp |= (ctl->intf_type << (ctl->intf_num * 8)); writel_relaxed(temp, ctl->mdata->mdp_base + @@ -2487,7 +2487,8 @@ int mdss_mdp_ctl_start(struct mdss_mdp_ctl *ctl, bool handoff) ret = mdss_mdp_ctl_start_sub(ctl, handoff); if (ret == 0) { - if (sctl && is_split_lm(ctl->mfd)) { + if (sctl && ctl->mfd && + ctl->mfd->split_mode == MDP_DUAL_LM_DUAL_DISPLAY) { /*split display available */ ret = mdss_mdp_ctl_start_sub(sctl, handoff); if (!ret) @@ -2501,7 +2502,7 @@ int mdss_mdp_ctl_start(struct mdss_mdp_ctl *ctl, bool handoff) out = (mixer->height << 16) | mixer->width; mdp_mixer_write(mixer, MDSS_MDP_REG_LM_OUT_SIZE, out); mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_PACK_3D, 0); - } else if (is_split_dst(ctl->mfd)) { + } else if (is_pingpong_split(ctl->mfd)) { mdss_mdp_ctl_dst_split_display_enable(1, ctl); } } diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c index 2ce4ed678870..9271031738eb 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c +++ b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c @@ -168,7 +168,7 @@ static int mdss_mdp_cmd_tearcheck_cfg(struct mdss_mdp_ctl *ctl, pingpong_base = mixer->pingpong_base; /* for dst split pp_num is cmd session (0 and 1) */ - if (is_split_dst(ctl->mfd)) + if (is_pingpong_split(ctl->mfd)) pingpong_base += ctx->pp_num * SPLIT_MIXER_OFFSET; mdss_mdp_pingpong_write(pingpong_base, @@ -866,7 +866,7 @@ int mdss_mdp_cmd_intfs_stop(struct mdss_mdp_ctl *ctl, int session, if (session >= MAX_SESSIONS) return 0; - if (is_split_dst(ctl->mfd)) { + if (is_pingpong_split(ctl->mfd)) { ret = mdss_mdp_cmd_intfs_stop(ctl, (session + 1), panel_power_state); if (IS_ERR_VALUE(ret)) @@ -1096,7 +1096,7 @@ static int mdss_mdp_cmd_intfs_setup(struct mdss_mdp_ctl *ctl, if (session >= MAX_SESSIONS) return 0; - if (is_split_dst(ctl->mfd)) { + if (is_pingpong_split(ctl->mfd)) { ret = mdss_mdp_cmd_intfs_setup(ctl, (session + 1)); if (IS_ERR_VALUE(ret)) return ret; @@ -1140,7 +1140,7 @@ static int mdss_mdp_cmd_intfs_setup(struct mdss_mdp_ctl *ctl, } ctx->ctl = ctl; - ctx->pp_num = (is_split_dst(ctl->mfd) ? session : mixer->num); + ctx->pp_num = (is_pingpong_split(ctl->mfd) ? session : mixer->num); ctx->pp_timeout_report_cnt = 0; init_waitqueue_head(&ctx->pp_waitq); init_completion(&ctx->stop_comp); diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c index 783a3650fbdf..f05677228da6 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c +++ b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c @@ -425,7 +425,7 @@ static int mdss_mdp_video_intfs_stop(struct mdss_mdp_ctl *ctl, if (pdata == NULL) return 0; - if (is_split_dst(ctl->mfd)) { + if (is_pingpong_split(ctl->mfd)) { ret = mdss_mdp_video_intfs_stop(ctl, pdata->next, (inum + 1)); if (IS_ERR_VALUE(ret)) return ret; @@ -849,7 +849,7 @@ static int mdss_mdp_video_config_fps(struct mdss_mdp_ctl *ctl, pr_err("invalid ctx\n"); return -ENODEV; } - } else if (is_split_dst(ctl->mfd)) { + } else if (is_pingpong_split(ctl->mfd)) { /* * On targets when destination split is enabled, mixer swap * is not valid. So we can safely assume that ctl->intf_num @@ -1080,7 +1080,7 @@ int mdss_mdp_video_reconfigure_splash_done(struct mdss_mdp_ctl *ctl, pdata->panel_info.cont_splash_enabled = 0; if (sctl) sctl->panel_data->panel_info.cont_splash_enabled = 0; - else if (ctl->panel_data->next && is_split_dst(ctl->mfd)) + else if (ctl->panel_data->next && is_pingpong_split(ctl->mfd)) ctl->panel_data->next->panel_info.cont_splash_enabled = 0; if (!handoff) { @@ -1229,7 +1229,7 @@ static int mdss_mdp_video_intfs_setup(struct mdss_mdp_ctl *ctl, if (pdata == NULL) return 0; - if (is_split_dst(ctl->mfd)) { + if (is_pingpong_split(ctl->mfd)) { ret = mdss_mdp_video_intfs_setup(ctl, pdata->next, (inum + 1)); if (IS_ERR_VALUE(ret)) return ret; diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c index e55691027d8a..901313a3ee35 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c +++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c @@ -3551,7 +3551,7 @@ static struct mdss_mdp_ctl *__mdss_mdp_overlay_ctl_init( INIT_WORK(&ctl->remove_underrun_handler, remove_underrun_vsync_handler); - if (is_split_lm(mfd)) { + if (mfd->split_mode == MDP_DUAL_LM_DUAL_DISPLAY) { /* enable split display */ rc = mdss_mdp_ctl_split_display_setup(ctl, pdata->next); if (rc) { @@ -3840,7 +3840,7 @@ static int mdss_mdp_overlay_handoff(struct msm_fb_data_type *mfd) goto error; } - if (is_split_lm(mfd)) { + if (mfd->split_mode == MDP_DUAL_LM_DUAL_DISPLAY) { sctl = mdss_mdp_get_split_ctl(ctl); if (!sctl) { pr_err("cannot get secondary ctl. fail the handoff\n"); @@ -4058,8 +4058,8 @@ int mdss_mdp_overlay_init(struct msm_fb_data_type *mfd) } mfd->mdp.private1 = mdp5_data; mfd->wait_for_kickoff = true; - if (is_panel_split(mfd) && mdp5_data->mdata->has_dst_split) - mfd->split_mode = MDP_SPLIT_MODE_DST; + if (is_panel_split(mfd) && mdp5_data->mdata->has_pingpong_split) + mfd->split_mode = MDP_PINGPONG_SPLIT; if (mfd->panel_info->partial_update_enabled && is_split_lm(mfd)) mdp5_data->mdata->has_src_split = false; @@ -4084,7 +4084,7 @@ int mdss_mdp_overlay_init(struct msm_fb_data_type *mfd) mfd->panel_orientation = mfd->panel_info->panel_orientation; if ((mfd->panel_info->panel_orientation & MDP_FLIP_LR) && - (is_split_lm(mfd))) + (mfd->split_mode == MDP_DUAL_LM_DUAL_DISPLAY)) mdp5_data->mixer_swap = true; rc = sysfs_create_group(&dev->kobj, &mdp_overlay_sysfs_group);