--- a/drivers/video/msm/mdss/mdss_fb.c.orig 2019-06-08 13:45:24.053712000 +0200 +++ b/drivers/video/msm/mdss/mdss_fb.c 2019-06-10 22:37:30.194743429 +0200 @@ -310,6 +310,20 @@ static ssize_t mdss_fb_get_type(struct d return ret; } +static int mdss_fb_get_panel_xres(struct mdss_panel_info *pinfo) +{ + struct mdss_panel_data *pdata; + int xres; + + pdata = container_of(pinfo, struct mdss_panel_data, panel_info); + + xres = pinfo->xres; + if (pdata->next && pdata->next->active) + xres += mdss_fb_get_panel_xres(&pdata->next->panel_info); + + return xres; +} + static void mdss_fb_parse_dt(struct msm_fb_data_type *mfd) { u32 data[2] = {0}; @@ -1156,6 +1170,8 @@ static int mdss_fb_blank_unblank(struct } if (mfd->mdp.on_fnc) { + struct mdss_panel_info *panel_info = mfd->panel_info; + struct fb_var_screeninfo *var = &mfd->fbi->var; ret = mfd->mdp.on_fnc(mfd); if (ret) { mdss_fb_stop_disp_thread(mfd); @@ -1168,6 +1184,12 @@ static int mdss_fb_blank_unblank(struct mfd->update.type = NOTIFY_TYPE_UPDATE; mfd->update.is_suspend = 0; mutex_unlock(&mfd->update.lock); + /* + * Panel info can change depending in the information + * programmed in the controller. + * Update this info in the upstream structs. + */ + mdss_panelinfo_to_fb_var(panel_info, var); /* Start the work thread to signal idle time */ if (mfd->idle_time) @@ -1687,6 +1709,7 @@ static int mdss_fb_register(struct msm_f { int ret = -ENODEV; int bpp; + char panel_name[20]; struct mdss_panel_info *panel_info = mfd->panel_info; struct fb_info *fbi = mfd->fbi; struct fb_fix_screeninfo *fix; @@ -1827,9 +1850,7 @@ static int mdss_fb_register(struct msm_f return ret; } - var->xres = panel_info->xres; - if (mfd->split_display) - var->xres *= 2; + mdss_panelinfo_to_fb_var(panel_info, var); fix->type = panel_info->is_3d_panel; if (mfd->mdp.fb_stride) @@ -1838,21 +1859,9 @@ static int mdss_fb_register(struct msm_f else fix->line_length = var->xres * bpp; - var->yres = panel_info->yres; - if (panel_info->physical_width) - var->width = panel_info->physical_width; - if (panel_info->physical_height) - var->height = panel_info->physical_height; var->xres_virtual = var->xres; var->yres_virtual = panel_info->yres * mfd->fb_page; var->bits_per_pixel = bpp * 8; /* FrameBuffer color depth */ - var->upper_margin = panel_info->lcdc.v_back_porch; - var->lower_margin = panel_info->lcdc.v_front_porch; - var->vsync_len = panel_info->lcdc.v_pulse_width; - var->left_margin = panel_info->lcdc.h_back_porch; - var->right_margin = panel_info->lcdc.h_front_porch; - var->hsync_len = panel_info->lcdc.h_pulse_width; - var->pixclock = panel_info->clk_rate / 1000; /* * Populate smem length here for uspace to get the @@ -1915,6 +1924,8 @@ static int mdss_fb_register(struct msm_f return -EPERM; } + snprintf(panel_name, ARRAY_SIZE(panel_name), "mdss_panel_fb%d", + mfd->index); pr_info("FrameBuffer[%d] %dx%d registered successfully!\n", mfd->index, fbi->var.xres, fbi->var.yres); @@ -2598,9 +2609,59 @@ static void mdss_fb_var_to_panelinfo(str pinfo->lcdc.h_front_porch = var->right_margin; pinfo->lcdc.h_back_porch = var->left_margin; pinfo->lcdc.h_pulse_width = var->hsync_len; - pinfo->clk_rate = var->pixclock; + /* + * if greater than 1M, then rate would fall below 1mhz which is not + * even supported. In this case it means clock rate is actually + * passed directly in hz. + */ + if (var->pixclock > SZ_1M) + pinfo->clk_rate = var->pixclock; + else + pinfo->clk_rate = PICOS2KHZ(var->pixclock) * 1000; } +void mdss_panelinfo_to_fb_var(struct mdss_panel_info *pinfo, + struct fb_var_screeninfo *var) +{ + u32 frame_rate; + + var->xres = mdss_fb_get_panel_xres(pinfo); + var->yres = pinfo->yres; + var->lower_margin = pinfo->lcdc.v_front_porch - + pinfo->prg_fet; + var->upper_margin = pinfo->lcdc.v_back_porch + + pinfo->prg_fet; + var->vsync_len = pinfo->lcdc.v_pulse_width; + var->right_margin = pinfo->lcdc.h_front_porch; + var->left_margin = pinfo->lcdc.h_back_porch; + var->hsync_len = pinfo->lcdc.h_pulse_width; + + frame_rate = mdss_panel_get_framerate(pinfo, + FPS_RESOLUTION_HZ); + if (frame_rate) { + unsigned long clk_rate, h_total, v_total; + + h_total = var->xres + var->left_margin + + var->right_margin + var->hsync_len; + v_total = var->yres + var->lower_margin + + var->upper_margin + var->vsync_len; + clk_rate = h_total * v_total * frame_rate; + var->pixclock = KHZ2PICOS(clk_rate / 1000); + } else if (pinfo->clk_rate) { + var->pixclock = KHZ2PICOS( + (unsigned long int) pinfo->clk_rate / 1000); + } + + if (pinfo->physical_width) + var->width = pinfo->physical_width; + if (pinfo->physical_height) + var->height = pinfo->physical_height; + + pr_debug("ScreenInfo: res=%dx%d [%d, %d] [%d, %d]\n", + var->xres, var->yres, var->left_margin, + var->right_margin, var->upper_margin, + var->lower_margin); +} /** * __mdss_fb_perform_commit() - process a frame to display * @mfd: Framebuffer data structure for display @@ -3329,6 +3390,7 @@ int mdss_register_panel(struct platform_ goto mdss_notfound; } + pdata->active = true; fb_pdev = of_find_device_by_node(node); if (fb_pdev) { rc = mdss_fb_register_extra_panel(fb_pdev, pdata); --- a/drivers/video/msm/mdss/mdss_fb.h.orig 2019-06-08 13:45:24.053712000 +0200 +++ b/drivers/video/msm/mdss/mdss_fb.h 2019-06-09 23:22:43.940850298 +0200 @@ -309,4 +309,6 @@ struct sync_fence *mdss_fb_sync_get_fenc int mdss_fb_register_mdp_instance(struct msm_mdp_interface *mdp); int mdss_fb_dcm(struct msm_fb_data_type *mfd, int req_state); int mdss_fb_suspres_panel(struct device *dev, void *data); +void mdss_panelinfo_to_fb_var(struct mdss_panel_info *pinfo, + struct fb_var_screeninfo *var); #endif /* MDSS_FB_H */ --- a/drivers/video/msm/mdss/mdss_panel.h.orig 2019-06-08 13:45:24.061712000 +0200 +++ b/drivers/video/msm/mdss/mdss_panel.h 2019-06-10 15:44:12.295557101 +0200 @@ -18,12 +18,20 @@ #include #include +#define KHZ_TO_HZ 1000 + /* panel id type */ struct panel_id { u16 id; u16 type; }; +enum fps_resolution { + FPS_RESOLUTION_DEFAULT, + FPS_RESOLUTION_HZ, + FPS_RESOLUTION_KHZ, +}; + #define DEFAULT_FRAME_RATE 60 #define MDSS_DSI_RST_SEQ_LEN 10 @@ -352,7 +360,7 @@ struct mdss_panel_info { u32 min_height; u32 min_fps; u32 max_fps; - + u32 prg_fet; u32 cont_splash_enabled; u32 partial_update_enabled; struct ion_handle *splash_ihdl; @@ -393,7 +401,7 @@ struct mdss_panel_data { * and teardown. */ int (*event_handler) (struct mdss_panel_data *pdata, int e, void *arg); - + bool active; struct mdss_panel_data *next; }; @@ -401,12 +409,17 @@ struct mdss_panel_data { * mdss_get_panel_framerate() - get panel frame rate based on panel information * @panel_info: Pointer to panel info containing all panel information */ -static inline u32 mdss_panel_get_framerate(struct mdss_panel_info *panel_info) +static inline u32 mdss_panel_get_framerate(struct mdss_panel_info *panel_info, + u32 flags) { u32 frame_rate, pixel_total; + u64 rate; - if (panel_info == NULL) + if (panel_info == NULL) { return DEFAULT_FRAME_RATE; + goto end; + } + switch (panel_info->type) { case MIPI_VIDEO_PANEL: @@ -428,13 +441,25 @@ static inline u32 mdss_panel_get_framera panel_info->lcdc.v_front_porch + panel_info->lcdc.v_pulse_width + panel_info->yres); - if (pixel_total) - frame_rate = panel_info->clk_rate / pixel_total; - else + if (pixel_total) { + rate = panel_info->clk_rate * KHZ_TO_HZ; + do_div(rate, pixel_total); + frame_rate = (u32)rate; + } else { frame_rate = DEFAULT_FRAME_RATE; - + } break; } + +end: + if (flags == FPS_RESOLUTION_KHZ) { + if (!(frame_rate / KHZ_TO_HZ)) + frame_rate *= KHZ_TO_HZ; + } else if (flags == FPS_RESOLUTION_HZ) { + if (frame_rate / KHZ_TO_HZ) + frame_rate /= KHZ_TO_HZ; + } + return frame_rate; } --- a/drivers/video/msm/mdss/mdss_dsi.c.orig 2019-06-08 13:45:24.049712000 +0200 +++ b/drivers/video/msm/mdss/mdss_dsi.c 2019-06-10 00:49:41.148334433 +0200 @@ -1582,7 +1582,8 @@ int dsi_panel_device_register(struct dev ctrl_pdata->shared_pdata.broadcast_enable = of_property_read_bool( pan_node, "qcom,mdss-dsi-panel-broadcast-mode"); - pinfo->panel_max_fps = mdss_panel_get_framerate(pinfo); + pinfo->panel_max_fps = mdss_panel_get_framerate(pinfo, + FPS_RESOLUTION_HZ); pinfo->panel_max_vtotal = mdss_panel_get_vtotal(pinfo); ctrl_pdata->disp_en_gpio = of_get_named_gpio(ctrl_pdev->dev.of_node, "qcom,platform-enable-gpio", 0); --- a/drivers/video/msm/mdss/mdss_mdp_ctl.c.orig 2019-06-08 13:45:24.057712000 +0200 +++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c 2019-06-10 22:41:26.524149757 +0200 @@ -344,7 +344,8 @@ int mdss_mdp_perf_calc_pipe(struct mdss_ fps = pinfo->panel_max_fps; v_total = pinfo->panel_max_vtotal; } else { - fps = mdss_panel_get_framerate(pinfo); + fps = mdss_panel_get_framerate(pinfo, + FPS_RESOLUTION_HZ); v_total = mdss_panel_get_vtotal(pinfo); } xres = pinfo->xres; @@ -470,7 +471,8 @@ static void mdss_mdp_perf_calc_mixer(str fps = pinfo->panel_max_fps; v_total = pinfo->panel_max_vtotal; } else { - fps = mdss_panel_get_framerate(pinfo); + fps = mdss_panel_get_framerate(pinfo, + FPS_RESOLUTION_HZ); v_total = mdss_panel_get_vtotal(pinfo); } @@ -595,9 +597,12 @@ static u32 mdss_mdp_get_vbp_factor(struc return 0; pinfo = &ctl->panel_data->panel_info; - fps = mdss_panel_get_framerate(pinfo); + fps = mdss_panel_get_framerate(pinfo, + FPS_RESOLUTION_HZ); v_total = mdss_panel_get_vtotal(pinfo); vbp = pinfo->lcdc.v_back_porch + pinfo->lcdc.v_pulse_width; + vbp += pinfo->prg_fet; + vbp_fac = (vbp) ? fps * v_total / vbp : 0; pr_debug("vbp_fac=%d vbp=%d v_total=%d\n", vbp_fac, vbp, v_total); @@ -1740,7 +1745,7 @@ int mdss_mdp_ctl_intf_event(struct mdss_ if (pdata->event_handler) rc = pdata->event_handler(pdata, event, arg); pdata = pdata->next; - } while (rc == 0 && pdata); + } while (rc == 0 && pdata && pdata->active); return rc; } --- a/drivers/video/msm/mdss/mdss_mdp_overlay.c.orig 2019-06-08 13:45:24.057712000 +0200 +++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c 2019-06-10 22:10:05.072953787 +0200 @@ -2266,6 +2266,7 @@ static ssize_t dynamic_fps_sysfs_wta_dfp mutex_unlock(&mdp5_data->dfps_lock); return rc; } + pdata->panel_info.prg_fet = 0; pdata->panel_info.new_fps = dfps; mutex_unlock(&mdp5_data->dfps_lock); return count; @@ -2790,7 +2791,8 @@ static int mdss_fb_get_metadata(struct m switch (metadata->op) { case metadata_op_frame_rate: metadata->data.panel_frame_rate = - mdss_panel_get_framerate(mfd->panel_info); + mdss_panel_get_framerate(mfd->panel_info, + FPS_RESOLUTION_DEFAULT); break; case metadata_op_get_caps: ret = mdss_fb_get_hw_caps(mfd, &metadata->data.caps); @@ -3325,7 +3327,8 @@ static int mdss_mdp_overlay_off(struct m * As a last resort signal the timeline if vsync doesn't arrive. */ if (mdp5_data->retire_cnt) { - u32 fps = mdss_panel_get_framerate(mfd->panel_info); + u32 fps = mdss_panel_get_framerate(mfd->panel_info, + FPS_RESOLUTION_HZ); u32 vsync_time = 1000 / (fps ? : DEFAULT_FRAME_RATE); msleep(vsync_time); --- a/drivers/video/msm/mdss/mdss_mdp_intf_video.c.orig 2019-06-08 13:45:24.057712000 +0200 +++ b/drivers/video/msm/mdss/mdss_mdp_intf_video.c 2019-06-10 21:53:02.826870697 +0200 @@ -329,7 +329,7 @@ static int mdss_mdp_video_stop(struct md /* wait for at least one VSYNC on HDMI intf for proper TG OFF */ if (MDSS_INTF_HDMI == ctx->intf_type) { frame_rate = mdss_panel_get_framerate - (&(ctl->panel_data->panel_info)); + (&(ctl->panel_data->panel_info), FPS_RESOLUTION_HZ); if (!(frame_rate >= 24 && frame_rate <= 240)) frame_rate = 24; msleep((1000/frame_rate) + 1); @@ -531,7 +531,7 @@ static int mdss_mdp_video_vfp_fps_update vsync_period = mdss_panel_get_vtotal(&pdata->panel_info); hsync_period = mdss_panel_get_htotal(&pdata->panel_info, true); - curr_fps = mdss_panel_get_framerate(&pdata->panel_info); + curr_fps = mdss_panel_get_framerate(&pdata->panel_info, FPS_RESOLUTION_HZ); if (curr_fps > new_fps) { add_v_lines = mult_frac(vsync_period, @@ -887,6 +887,9 @@ int mdss_mdp_video_start(struct mdss_mdp pinfo->bpp); itp.vsync_pulse_width = pinfo->lcdc.v_pulse_width; + pinfo->prg_fet = 0; + pr_debug("programmable fetch is not supported\n"); + if (mdss_mdp_video_timegen_setup(ctl, &itp)) { pr_err("unable to get timing parameters\n"); return -EINVAL; --- a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c.orig 2019-06-08 13:45:24.057712000 +0200 +++ b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c 2019-06-10 15:10:56.025186537 +0200 @@ -836,7 +836,8 @@ int mdss_mdp_cmd_stop(struct mdss_mdp_ct } spin_unlock_irqrestore(&ctx->clk_lock, flags); - hz = mdss_panel_get_framerate(&ctl->panel_data->panel_info); + hz = mdss_panel_get_framerate(&ctl->panel_data->panel_info, + FPS_RESOLUTION_HZ); if (need_wait) { if (wait_for_completion_timeout(&ctx->stop_comp,