From 586da5d998bec129cd7291a3f4b0ac94a99e330c Mon Sep 17 00:00:00 2001 From: Huaibin Yang Date: Fri, 7 Dec 2012 20:23:53 -0800 Subject: [PATCH] msm_fb: display: add mdp bandwidth runtime calculation Currently mdp bandwidth request logic is based on source image size and number of layers. This logic can not support complicated mdp usecases and it is not power efficient. The logic is improved by calculating mdp bandwidth request at runtime from all pipes and mixers. Conflicts: drivers/video/msm/mdp.c drivers/video/msm/mdp4_overlay.c drivers/video/msm/mipi_dsi.c CRs-fixed: 425823 Change-Id: I63206f00f8d3017a2449f8ac617fce3ba2a4d36c Signed-off-by: Huaibin Yang --- drivers/video/msm/lcdc.c | 6 +- drivers/video/msm/lvds.c | 7 - drivers/video/msm/mddi.c | 8 +- drivers/video/msm/mdp.c | 134 ++++++++--- drivers/video/msm/mdp.h | 8 +- drivers/video/msm/mdp4.h | 26 ++- drivers/video/msm/mdp4_overlay.c | 255 +++++++++++++-------- drivers/video/msm/mdp4_overlay_dsi_video.c | 1 + drivers/video/msm/mdp4_overlay_dtv.c | 1 + drivers/video/msm/mdp4_overlay_lcdc.c | 1 + drivers/video/msm/mdp4_overlay_writeback.c | 1 + drivers/video/msm/mdp4_util.c | 3 +- drivers/video/msm/mipi_dsi.c | 9 +- 13 files changed, 297 insertions(+), 163 deletions(-) diff --git a/drivers/video/msm/lcdc.c b/drivers/video/msm/lcdc.c index 2170abe6132..1bd4302f4a0 100644 --- a/drivers/video/msm/lcdc.c +++ b/drivers/video/msm/lcdc.c @@ -84,8 +84,6 @@ static int lcdc_off(struct platform_device *pdev) } clk_disable_unprepare(mfd->ebi1_clk); } -#else - mdp_bus_scale_update_request(0); #endif return ret; @@ -108,9 +106,7 @@ static int lcdc_on(struct platform_device *pdev) if (!panel_pixclock_freq) panel_pixclock_freq = mfd->fbi->var.pixclock; -#ifdef CONFIG_MSM_BUS_SCALING - mdp_bus_scale_update_request(2); -#else +#ifndef CONFIG_MSM_BUS_SCALING if (panel_pixclock_freq > 65000000) /* pm_qos_rate should be in Khz */ pm_qos_rate = panel_pixclock_freq / 1000 ; diff --git a/drivers/video/msm/lvds.c b/drivers/video/msm/lvds.c index 13bb9e33673..e9bbceb1128 100644 --- a/drivers/video/msm/lvds.c +++ b/drivers/video/msm/lvds.c @@ -254,10 +254,6 @@ static int lvds_off(struct platform_device *pdev) if (lvds_pdata && lvds_pdata->lcdc_gpio_config) ret = lvds_pdata->lcdc_gpio_config(0); -#ifdef CONFIG_MSM_BUS_SCALING - mdp_bus_scale_update_request(0); -#endif - return ret; } @@ -273,9 +269,6 @@ static int lvds_on(struct platform_device *pdev) if (!panel_pixclock_freq) panel_pixclock_freq = mfd->fbi->var.pixclock; -#ifdef CONFIG_MSM_BUS_SCALING - mdp_bus_scale_update_request(2); -#endif mfd = platform_get_drvdata(pdev); if (lvds_clk) { diff --git a/drivers/video/msm/mddi.c b/drivers/video/msm/mddi.c index 115491387f2..b4c1e76e308 100644 --- a/drivers/video/msm/mddi.c +++ b/drivers/video/msm/mddi.c @@ -212,9 +212,7 @@ static int mddi_off(struct platform_device *pdev) if (mddi_pdata && mddi_pdata->mddi_power_save) mddi_pdata->mddi_power_save(0); -#ifdef CONFIG_MSM_BUS_SCALING - mdp_bus_scale_update_request(0); -#else +#ifndef CONFIG_MSM_BUS_SCALING if (mfd->ebi1_clk) clk_disable_unprepare(mfd->ebi1_clk); #endif @@ -275,9 +273,7 @@ static int mddi_on(struct platform_device *pdev) printk(KERN_ERR "%s: clk_set_rate failed\n", __func__); -#ifdef CONFIG_MSM_BUS_SCALING - mdp_bus_scale_update_request(2); -#else +#ifndef CONFIG_MSM_BUS_SCALING if (mfd->ebi1_clk) clk_prepare_enable(mfd->ebi1_clk); #endif diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c index e2e2df675d9..b80bfdf0a36 100644 --- a/drivers/video/msm/mdp.c +++ b/drivers/video/msm/mdp.c @@ -51,6 +51,7 @@ static struct clk *mdp_lut_clk; int mdp_rev; int mdp_iommu_split_domain; u32 mdp_max_clk = 266667000; +u64 mdp_max_bw = 2000000000; static struct platform_device *mdp_init_pdev; static struct regulator *footswitch; @@ -1413,6 +1414,39 @@ int mdp_ppp_pipe_wait(void) return ret; } +#define DEFAULT_FRAME_RATE 60 + +u32 mdp_get_panel_framerate(struct msm_fb_data_type *mfd) +{ + u32 frame_rate = 0, total_pixel; + struct msm_panel_info *panel_info = &mfd->panel_info; + if (mfd->dest == DISPLAY_LCD) { + if (panel_info->type == MDDI_PANEL && panel_info->mddi.is_type1) + frame_rate = panel_info->lcd.refx100 / (100 * 2); + else + frame_rate = panel_info->lcd.refx100 / 100; + } else { + if (panel_info->type == MIPI_VIDEO_PANEL) { + frame_rate = panel_info->mipi.frame_rate; + } else { + total_pixel = (panel_info->lcdc.h_back_porch + + panel_info->lcdc.h_front_porch + + panel_info->lcdc.h_pulse_width + + panel_info->xres) * + (panel_info->lcdc.v_back_porch + + panel_info->lcdc.v_front_porch + + panel_info->lcdc.v_pulse_width + + panel_info->yres); + if (total_pixel) + frame_rate = panel_info->clk_rate / + total_pixel; + } + } + if (frame_rate == 0) + frame_rate = DEFAULT_FRAME_RATE; + return frame_rate; +} + static DEFINE_SPINLOCK(mdp_lock); static int mdp_irq_mask; static int mdp_irq_enabled; @@ -2169,7 +2203,9 @@ static int mdp_off(struct platform_device *pdev) ret = panel_next_off(pdev); mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); mdp_clk_ctrl(0); - +#ifdef CONFIG_MSM_BUS_SCALING + mdp_bus_scale_update_request(0, 0); +#endif if (mdp_rev >= MDP_REV_41 && mfd->panel.type == MIPI_CMD_PANEL) mdp_dsi_cmd_overlay_suspend(mfd); pr_debug("%s:-\n", __func__); @@ -2279,20 +2315,77 @@ void mdp_hw_version(void) } #ifdef CONFIG_MSM_BUS_SCALING + +#ifndef MDP_BUS_VECTOR_ENTRY +#define MDP_BUS_VECTOR_ENTRY(ab_val, ib_val) \ + { \ + .src = MSM_BUS_MASTER_MDP_PORT0, \ + .dst = MSM_BUS_SLAVE_EBI_CH0, \ + .ab = (ab_val), \ + .ib = (ib_val), \ + } +#endif +/* + * Entry 0 hold 0 request + * Entry 1 and 2 do ping pong request + */ +static struct msm_bus_vectors mdp_bus_vectors[] = { + MDP_BUS_VECTOR_ENTRY(0, 0), + MDP_BUS_VECTOR_ENTRY( 128000000, 160000000), + MDP_BUS_VECTOR_ENTRY( 128000000, 160000000), +}; + +static struct msm_bus_paths mdp_bus_usecases[ARRAY_SIZE(mdp_bus_vectors)]; +static struct msm_bus_scale_pdata mdp_bus_scale_table = { + .usecase = mdp_bus_usecases, + .num_usecases = ARRAY_SIZE(mdp_bus_usecases), + .name = "mdp", +}; static uint32_t mdp_bus_scale_handle; -int mdp_bus_scale_update_request(uint32_t index) +static int mdp_bus_scale_register(void) { - if (!mdp_pdata && (!mdp_pdata->mdp_bus_scale_table - || index > (mdp_pdata->mdp_bus_scale_table->num_usecases - 1))) { - printk(KERN_ERR "%s invalid table or index\n", __func__); - return -EINVAL; + struct msm_bus_scale_pdata *bus_pdata = &mdp_bus_scale_table; + int i; + for (i = 0; i < bus_pdata->num_usecases; i++) { + mdp_bus_usecases[i].num_paths = 1; + mdp_bus_usecases[i].vectors = &mdp_bus_vectors[i]; } + mdp_bus_scale_handle = msm_bus_scale_register_client(bus_pdata); + if (!mdp_bus_scale_handle) { + pr_err("%s: not able to get bus scale!\n", __func__); + return -ENOMEM; + } + return 0; +} + +int mdp_bus_scale_update_request(u64 ab, u64 ib) +{ + static int bus_index = 1; + if (mdp_bus_scale_handle < 1) { - pr_debug("%s invalid bus handle\n", __func__); + pr_err("%s invalid bus handle\n", __func__); return -EINVAL; } - return msm_bus_scale_client_update_request(mdp_bus_scale_handle, - index); + + if (!ab) + return msm_bus_scale_client_update_request + (mdp_bus_scale_handle, 0); + + /* ping pong bus_index between table entry 1 and 2 */ + bus_index++; + bus_index = (bus_index > 2) ? 1 : bus_index; + + mdp_bus_usecases[bus_index].vectors->ab = min(ab, mdp_max_bw); + ib = max(ib, ab); + mdp_bus_usecases[bus_index].vectors->ib = min(ib, mdp_max_bw); + + pr_debug("%s: handle=%d index=%d ab=%llu ib=%llu\n", __func__, + (u32)mdp_bus_scale_handle, bus_index, + mdp_bus_usecases[bus_index].vectors->ab, + mdp_bus_usecases[bus_index].vectors->ib); + + return msm_bus_scale_client_update_request + (mdp_bus_scale_handle, bus_index); } #endif DEFINE_MUTEX(mdp_clk_lock); @@ -2820,22 +2913,13 @@ static int mdp_probe(struct platform_device *pdev) mdp_clk_ctrl(0); #ifdef CONFIG_MSM_BUS_SCALING - if (!mdp_bus_scale_handle && mdp_pdata && - mdp_pdata->mdp_bus_scale_table) { - mdp_bus_scale_handle = - msm_bus_scale_register_client( - mdp_pdata->mdp_bus_scale_table); - if (!mdp_bus_scale_handle) { - printk(KERN_ERR "%s not able to get bus scale\n", - __func__); - return -ENOMEM; - } - } + if (mdp_bus_scale_register()) + return -ENOMEM; /* req bus bandwidth immediately */ if (!(mfd->cont_splash_done)) - mdp_bus_scale_update_request(5); - + mdp_bus_scale_update_request + (MDP_BUS_SCALE_INIT, MDP_BUS_SCALE_INIT); #endif /* set driver data */ @@ -2879,8 +2963,7 @@ static int mdp_probe(struct platform_device *pdev) mdp_probe_err: platform_device_put(msm_fb_dev); #ifdef CONFIG_MSM_BUS_SCALING - if (mdp_pdata && mdp_pdata->mdp_bus_scale_table && - mdp_bus_scale_handle > 0) + if (mdp_bus_scale_handle > 0) msm_bus_scale_unregister_client(mdp_bus_scale_handle); #endif return rc; @@ -2977,8 +3060,7 @@ static int mdp_remove(struct platform_device *pdev) iounmap(msm_mdp_base); pm_runtime_disable(&pdev->dev); #ifdef CONFIG_MSM_BUS_SCALING - if (mdp_pdata && mdp_pdata->mdp_bus_scale_table && - mdp_bus_scale_handle > 0) + if (mdp_bus_scale_handle > 0) msm_bus_scale_unregister_client(mdp_bus_scale_handle); #endif return 0; diff --git a/drivers/video/msm/mdp.h b/drivers/video/msm/mdp.h index 8f540aa7dc0..0653869a062 100644 --- a/drivers/video/msm/mdp.h +++ b/drivers/video/msm/mdp.h @@ -830,12 +830,12 @@ int mdp_set_core_clk(u32 rate); int mdp_clk_round_rate(u32 rate); unsigned long mdp_get_core_clk(void); -unsigned long mdp_perf_level2clk_rate(uint32 perf_level); #ifdef CONFIG_MSM_BUS_SCALING -int mdp_bus_scale_update_request(uint32_t index); +int mdp_bus_scale_update_request(u64 ab, u64 ib); #else -static inline int mdp_bus_scale_update_request(uint32_t index) +static inline int mdp_bus_scale_update_request(u64 ab, + u64 ib) { return 0; } @@ -912,6 +912,8 @@ int mdp_ppp_v4l2_overlay_play(struct fb_info *info, unsigned long srcp0_addr, unsigned long srcp0_size, unsigned long srcp1_addr, unsigned long srcp1_size); +u32 mdp_get_panel_framerate(struct msm_fb_data_type *mfd); + #ifdef CONFIG_FB_MSM_DTV void mdp_vid_quant_set(void); #else diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h index a40a0fb0ede..ba099c3787b 100644 --- a/drivers/video/msm/mdp4.h +++ b/drivers/video/msm/mdp4.h @@ -29,6 +29,12 @@ extern char *mmss_cc_base; /* mutimedia sub system clock control */ extern spinlock_t dsi_clk_lock; extern u32 mdp_max_clk; +extern u64 mdp_max_bw; +#define MDP4_BW_AB_FACTOR (115) /* 1.15 */ +#define MDP4_BW_IB_FACTOR (125) /* 1.25 */ +#define MDP_BUS_SCALE_AB_STEP (0x4000000) +#define MDP_BUS_SCALE_INIT (0x10000000) + #define MDP4_OVERLAYPROC0_BASE 0x10000 #define MDP4_OVERLAYPROC1_BASE 0x18000 #define MDP4_OVERLAYPROC2_BASE 0x88000 @@ -44,13 +50,6 @@ extern u32 mdp_max_clk; #define CS_CONTROLLER_0 0x0707ffff #define CS_CONTROLLER_1 0x03073f3f -enum { - OVERLAY_PERF_LEVEL1 = 1, - OVERLAY_PERF_LEVEL2, - OVERLAY_PERF_LEVEL3, - OVERLAY_PERF_LEVEL4 -}; - typedef int (*cmd_fxn_t)(struct platform_device *pdev); enum { /* display */ @@ -243,6 +242,12 @@ enum { #define MDP4_MAX_PLANE 4 #define VSYNC_PERIOD 16 +#ifdef BLT_RGB565 +#define BLT_BPP 2 +#else +#define BLT_BPP 3 +#endif + struct mdp4_hsic_regs { int32_t params[NUM_HSIC_PARAM]; int32_t conv_matrix[3][3]; @@ -368,7 +373,8 @@ struct mdp4_overlay_pipe { uint32 blt_dmap_done; uint32 blt_forced; uint32 req_clk; - uint32 req_bw; + uint64 bw_ab_quota; + uint64 bw_ib_quota; uint32 luma_align_size; struct mdp_overlay_pp_params pp_cfg; struct mdp_overlay req_data; @@ -932,7 +938,9 @@ int mdp4_v4l2_overlay_play(struct fb_info *info, struct mdp4_overlay_pipe *pipe, unsigned long srcp0_addr, unsigned long srcp1_addr, unsigned long srcp2_addr); int mdp4_overlay_mdp_pipe_req(struct mdp4_overlay_pipe *pipe, - struct msm_fb_data_type *mfd); + struct msm_fb_data_type *mfd); +int mdp4_calc_blt_mdp_bw(struct msm_fb_data_type *mfd, + struct mdp4_overlay_pipe *pipe); int mdp4_overlay_mdp_perf_req(struct msm_fb_data_type *mfd, struct mdp4_overlay_pipe *plist); void mdp4_overlay_mdp_perf_upd(struct msm_fb_data_type *mfd, int flag); diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c index ee40a71725f..a2b32c81801 100644 --- a/drivers/video/msm/mdp4_overlay.c +++ b/drivers/video/msm/mdp4_overlay.c @@ -106,17 +106,15 @@ static struct mdp4_overlay_ctrl *ctrl = &mdp4_overlay_db; struct mdp4_overlay_perf { u32 mdp_clk_rate; - u32 use_ov0_blt; - u32 use_ov1_blt; - u32 mdp_bw; + u32 use_ov_blt[MDP4_MIXER_MAX]; + u64 mdp_ov_ab_bw[MDP4_MIXER_MAX]; + u64 mdp_ov_ib_bw[MDP4_MIXER_MAX]; + u32 mdp_ab_bw; + u32 mdp_ib_bw; }; -struct mdp4_overlay_perf perf_request = { - .mdp_bw = OVERLAY_PERF_LEVEL4, -}; -struct mdp4_overlay_perf perf_current = { - .mdp_bw = OVERLAY_PERF_LEVEL4, -}; +struct mdp4_overlay_perf perf_request; +struct mdp4_overlay_perf perf_current; static struct ion_client *display_iclient; @@ -2439,12 +2437,10 @@ static int mdp4_calc_pipe_mdp_clk(struct msm_fb_data_type *mfd, if (!pipe) { pr_err("%s: pipe is null!\n", __func__); - pipe->req_bw = OVERLAY_PERF_LEVEL4; return ret; } if (!mfd) { pr_err("%s: mfd is null!\n", __func__); - pipe->req_bw = OVERLAY_PERF_LEVEL4; return ret; } @@ -2623,18 +2619,13 @@ static int mdp4_calc_pipe_mdp_clk(struct msm_fb_data_type *mfd, return 0; } -#define OVERLAY_VGA_SIZE 0x04B000 -#define OVERLAY_720P_TILE_SIZE 0x0E6000 -#define OVERLAY_WSVGA_SIZE 0x98000 /* 1024x608, align 600 to 32bit */ - -#define OVERLAY_BUS_SCALE_TABLE_BASE 6 - - static int mdp4_calc_pipe_mdp_bw(struct msm_fb_data_type *mfd, - struct mdp4_overlay_pipe *pipe) + struct mdp4_overlay_pipe *pipe) { - u32 res; + u32 fps; int ret = -EINVAL; + u32 quota; + u32 shift = 16; if (!pipe) { pr_err("%s: pipe is null!\n", __func__); @@ -2645,28 +2636,79 @@ static int mdp4_calc_pipe_mdp_bw(struct msm_fb_data_type *mfd, return ret; } - if (pipe->flags & MDP_DEINTERLACE) { - pr_info("%s deinterlace requires max mdp bw.\n", - __func__); - pipe->req_bw = OVERLAY_PERF_LEVEL1; - return 0; + fps = mdp_get_panel_framerate(mfd); + quota = pipe->src_w * pipe->src_h * fps * pipe->bpp; + + quota >>= shift; + /* factor 1.15 for ab */ + pipe->bw_ab_quota = quota * MDP4_BW_AB_FACTOR / 100; + /* factor 1.25 for ib */ + pipe->bw_ib_quota = quota * MDP4_BW_IB_FACTOR / 100; + /* down scaling factor for ib */ + if ((!pipe->dst_h) && (!pipe->src_h) && + (pipe->src_h > pipe->dst_h)) { + u64 ib = quota; + ib *= pipe->src_h; + ib /= pipe->dst_h; + pipe->bw_ib_quota = max(ib, pipe->bw_ib_quota); + pr_debug("%s: src_h=%d dst_h=%d mdp ib %llu, ib_quota=%llu\n", + __func__, pipe->src_h, pipe->dst_h, + ib<bw_ib_quota<pipe_type == OVERLAY_TYPE_BF) { - pipe->req_bw = OVERLAY_PERF_LEVEL4; - return 0; + pipe->bw_ab_quota <<= shift; + pipe->bw_ib_quota <<= shift; + + pr_debug("%s: pipe ndx=%d src(h,w)(%d, %d) fps=%d bpp=%d\n", + __func__, pipe->pipe_ndx, pipe->src_h, pipe->src_w, + fps, pipe->bpp); + pr_debug("%s: ab_quota=%llu ib_quota=%llu\n", __func__, + pipe->bw_ab_quota, pipe->bw_ib_quota); + + return 0; +} + +int mdp4_calc_blt_mdp_bw(struct msm_fb_data_type *mfd, + struct mdp4_overlay_pipe *pipe) +{ + struct mdp4_overlay_perf *perf_req = &perf_request; + u32 fps; + int bpp; + int ret = -EINVAL; + u32 quota; + u32 shift = 16; + if (!pipe) { + pr_err("%s: pipe is null!\n", __func__); + return ret; + } + if (!mfd) { + pr_err("%s: mfd is null!\n", __func__); + return ret; } - res = pipe->src_w * pipe->src_h; + bpp = BLT_BPP; + fps = mdp_get_panel_framerate(mfd); - if (res <= OVERLAY_WSVGA_SIZE) - pipe->req_bw = OVERLAY_PERF_LEVEL4; - else if (res <= OVERLAY_VGA_SIZE) - pipe->req_bw = OVERLAY_PERF_LEVEL3; - else if (res <= OVERLAY_720P_TILE_SIZE) - pipe->req_bw = OVERLAY_PERF_LEVEL2; - else - pipe->req_bw = OVERLAY_PERF_LEVEL1; + /* read and write bw*/ + quota = pipe->dst_w * pipe->dst_h * fps * bpp * 2; + quota >>= shift; + + perf_req->mdp_ov_ab_bw[pipe->mixer_num] = + quota * MDP4_BW_AB_FACTOR / 100; + + perf_req->mdp_ov_ib_bw[pipe->mixer_num] = + quota * MDP4_BW_IB_FACTOR / 100; + + perf_req->mdp_ov_ab_bw[pipe->mixer_num] <<= shift; + perf_req->mdp_ov_ib_bw[pipe->mixer_num] <<= shift; + + pr_debug("%s: pipe ndx=%d dst(h,w)(%d, %d) fps=%d bpp=%d\n", + __func__, pipe->pipe_ndx, pipe->dst_h, pipe->dst_w, + fps, bpp); + pr_debug("%s: overlay=%d ab_bw=%llu ib_bw=%llu\n", __func__, + pipe->mixer_num, + perf_req->mdp_ov_ab_bw[pipe->mixer_num], + perf_req->mdp_ov_ib_bw[pipe->mixer_num]); return 0; } @@ -2675,12 +2717,12 @@ int mdp4_overlay_mdp_perf_req(struct msm_fb_data_type *mfd, struct mdp4_overlay_pipe *plist) { u32 worst_mdp_clk = 0; - u32 worst_mdp_bw = OVERLAY_PERF_LEVEL4; int i; struct mdp4_overlay_perf *perf_req = &perf_request; struct mdp4_overlay_pipe *pipe = plist; u32 cnt = 0; int ret = -EINVAL; + u64 ab_quota_total = 0, ib_quota_total = 0; if (!mfd) { pr_err("%s: mfd is null!\n", __func__); @@ -2692,8 +2734,8 @@ int mdp4_overlay_mdp_perf_req(struct msm_fb_data_type *mfd, return ret; } - perf_req->use_ov0_blt = 0; - perf_req->use_ov1_blt = 0; + for (i = 0; i < MDP4_MIXER_MAX; i++) + perf_req->use_ov_blt[i] = 0; for (i = 0; i < OVERLAY_PIPE_MAX; i++, pipe++) { @@ -2705,25 +2747,17 @@ int mdp4_overlay_mdp_perf_req(struct msm_fb_data_type *mfd, cnt++; if (worst_mdp_clk < pipe->req_clk) worst_mdp_clk = pipe->req_clk; - if (pipe->req_clk > mdp_max_clk) { - if (pipe->mixer_num == MDP4_MIXER0) - perf_req->use_ov0_blt = 1; - if (pipe->mixer_num == MDP4_MIXER1) - perf_req->use_ov1_blt = 1; - } - if (!pipe->req_bw) { - pr_err("%s mdp pipe bw request should not be zero!\n", - __func__); - pr_debug("%s %d pid %d num %d idx %d mix %d bw %d\n", - __func__, __LINE__, current->pid, - pipe->pipe_num, pipe->pipe_ndx, - pipe->mixer_num, pipe->req_bw); - pipe->req_bw = OVERLAY_PERF_LEVEL4; - } + if (pipe->req_clk > mdp_max_clk) + perf_req->use_ov_blt[pipe->mixer_num] = 1; - if (pipe->req_bw < worst_mdp_bw) - worst_mdp_bw = pipe->req_bw; + if (pipe->mixer_num == MDP4_MIXER2) + perf_req->use_ov_blt[MDP4_MIXER2] = 1; + + if (pipe->pipe_type != OVERLAY_TYPE_BF) { + ab_quota_total += pipe->bw_ab_quota; + ib_quota_total += pipe->bw_ib_quota; + } if (mfd->mdp_rev == MDP_REV_41) { /* @@ -2732,32 +2766,45 @@ int mdp4_overlay_mdp_perf_req(struct msm_fb_data_type *mfd, */ if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD) { if (pipe->dst_x != 0) - perf_req->use_ov0_blt = 1; + perf_req->use_ov_blt[MDP4_MIXER0] = 1; } if ((mfd->panel_info.xres > 1280) && (mfd->panel_info.type != DTV_PANEL)) { - perf_req->use_ov0_blt = 1; + perf_req->use_ov_blt[MDP4_MIXER0] = 1; } } } - perf_req->mdp_clk_rate = worst_mdp_clk; - if (perf_req->mdp_clk_rate > mdp_max_clk) - perf_req->mdp_clk_rate = mdp_max_clk; - + perf_req->mdp_clk_rate = min(worst_mdp_clk, mdp_max_clk); perf_req->mdp_clk_rate = mdp_clk_round_rate(perf_req->mdp_clk_rate); - perf_req->mdp_bw = worst_mdp_bw; + for (i = 0; i < MDP4_MIXER_MAX; i++) { + if (perf_req->use_ov_blt[i]) { + ab_quota_total += perf_req->mdp_ov_ab_bw[i]; + ib_quota_total += perf_req->mdp_ov_ib_bw[i]; + } + } - if (cnt >= 3) - perf_req->mdp_bw = OVERLAY_PERF_LEVEL1; + perf_req->mdp_ab_bw = roundup(ab_quota_total, MDP_BUS_SCALE_AB_STEP); + perf_req->mdp_ib_bw = roundup(ib_quota_total, MDP_BUS_SCALE_AB_STEP); - pr_debug("%s %d pid %d cnt %d clk %d ov0_blt %d, ov1_blt %d bw %d\n", + pr_debug("%s %d: ab_quota_total=(%llu, %d) ib_quota_total=(%llu, %d)\n", + __func__, __LINE__, + ab_quota_total, perf_req->mdp_ab_bw, + ib_quota_total, perf_req->mdp_ib_bw); + + if (ab_quota_total > mdp_max_bw) + pr_warn("%s: req ab bw=%llu is larger than max bw=%llu", + __func__, ab_quota_total, mdp_max_bw); + if (ib_quota_total > mdp_max_bw) + pr_warn("%s: req ib bw=%llu is larger than max bw=%llu", + __func__, ib_quota_total, mdp_max_bw); + + pr_debug("%s %d: pid %d cnt %d clk %d ov0_blt %d, ov1_blt %d\n", __func__, __LINE__, current->pid, cnt, perf_req->mdp_clk_rate, - perf_req->use_ov0_blt, - perf_req->use_ov1_blt, - perf_req->mdp_bw); + perf_req->use_ov_blt[0], + perf_req->use_ov_blt[1]); return 0; } @@ -2793,7 +2840,7 @@ void mdp4_overlay_mdp_perf_upd(struct msm_fb_data_type *mfd, flag); if (!mdp4_extn_disp) - perf_cur->use_ov1_blt = 0; + perf_cur->use_ov_blt[1] = 0; if (flag) { if (perf_req->mdp_clk_rate > perf_cur->mdp_clk_rate) { @@ -2806,19 +2853,26 @@ void mdp4_overlay_mdp_perf_upd(struct msm_fb_data_type *mfd, perf_cur->mdp_clk_rate = perf_req->mdp_clk_rate; } - if (perf_req->mdp_bw < perf_cur->mdp_bw) { + if ((perf_req->mdp_ab_bw > perf_cur->mdp_ab_bw) || + (perf_req->mdp_ib_bw > perf_cur->mdp_ib_bw)) { mdp_bus_scale_update_request - (OVERLAY_BUS_SCALE_TABLE_BASE - - perf_req->mdp_bw); - pr_info("%s mdp bw is changed [%d] from %d to %d\n", + (perf_req->mdp_ab_bw, perf_req->mdp_ib_bw); + pr_debug("%s mdp ab_bw is changed [%d] from %d to %d\n", __func__, flag, - perf_cur->mdp_bw, - perf_req->mdp_bw); - perf_cur->mdp_bw = perf_req->mdp_bw; + perf_cur->mdp_ab_bw, + perf_req->mdp_ab_bw); + pr_debug("%s mdp ib_bw is changed [%d] from %d to %d\n", + __func__, + flag, + perf_cur->mdp_ib_bw, + perf_req->mdp_ib_bw); + perf_cur->mdp_ab_bw = perf_req->mdp_ab_bw; + perf_cur->mdp_ib_bw = perf_req->mdp_ib_bw; } - if (mfd->panel_info.pdest == DISPLAY_1 && - perf_req->use_ov0_blt && !perf_cur->use_ov0_blt) { + + if ((mfd->panel_info.pdest == DISPLAY_1 && + perf_req->use_ov_blt[0] && !perf_cur->use_ov_blt[0])) { if (mfd->panel_info.type == LCDC_PANEL || mfd->panel_info.type == LVDS_PANEL) mdp4_lcdc_overlay_blt_start(mfd); @@ -2829,9 +2883,9 @@ void mdp4_overlay_mdp_perf_upd(struct msm_fb_data_type *mfd, pr_info("%s mixer0 start blt [%d] from %d to %d.\n", __func__, flag, - perf_cur->use_ov0_blt, - perf_req->use_ov0_blt); - perf_cur->use_ov0_blt = perf_req->use_ov0_blt; + perf_cur->use_ov_blt[0], + perf_req->use_ov_blt[0]); + perf_cur->use_ov_blt[0] = perf_req->use_ov_blt[0]; } } else { if (perf_req->mdp_clk_rate < perf_cur->mdp_clk_rate) { @@ -2844,19 +2898,26 @@ void mdp4_overlay_mdp_perf_upd(struct msm_fb_data_type *mfd, perf_cur->mdp_clk_rate = perf_req->mdp_clk_rate; } - if (perf_req->mdp_bw > perf_cur->mdp_bw) { - pr_info("%s mdp bw is changed [%d] from %d to %d\n", + if (perf_req->mdp_ab_bw < perf_cur->mdp_ab_bw || + perf_req->mdp_ib_bw < perf_cur->mdp_ib_bw) { + mdp_bus_scale_update_request + (perf_req->mdp_ab_bw, perf_req->mdp_ib_bw); + pr_debug("%s mdp ab bw is changed [%d] from %d to %d\n", __func__, flag, - perf_cur->mdp_bw, - perf_req->mdp_bw); - mdp_bus_scale_update_request - (OVERLAY_BUS_SCALE_TABLE_BASE - - perf_req->mdp_bw); - perf_cur->mdp_bw = perf_req->mdp_bw; + perf_cur->mdp_ab_bw, + perf_req->mdp_ab_bw); + pr_debug("%s mdp ib bw is changed [%d] from %d to %d\n", + __func__, + flag, + perf_cur->mdp_ib_bw, + perf_req->mdp_ib_bw); + perf_cur->mdp_ab_bw = perf_req->mdp_ab_bw; + perf_cur->mdp_ib_bw = perf_req->mdp_ib_bw; } - if (mfd->panel_info.pdest == DISPLAY_1 && - !perf_req->use_ov0_blt && perf_cur->use_ov0_blt) { + + if ((mfd->panel_info.pdest == DISPLAY_1 && + !perf_req->use_ov_blt[0] && perf_cur->use_ov_blt[0])) { if (mfd->panel_info.type == LCDC_PANEL || mfd->panel_info.type == LVDS_PANEL) mdp4_lcdc_overlay_blt_stop(mfd); @@ -2867,9 +2928,9 @@ void mdp4_overlay_mdp_perf_upd(struct msm_fb_data_type *mfd, pr_info("%s mixer0 stop blt [%d] from %d to %d.\n", __func__, flag, - perf_cur->use_ov0_blt, - perf_req->use_ov0_blt); - perf_cur->use_ov0_blt = perf_req->use_ov0_blt; + perf_cur->use_ov_blt[0], + perf_req->use_ov_blt[0]); + perf_cur->use_ov_blt[0] = perf_req->use_ov_blt[0]; } } return; @@ -3706,7 +3767,5 @@ int mdp4_overlay_reset() { memset(&perf_request, 0, sizeof(perf_request)); memset(&perf_current, 0, sizeof(perf_current)); - perf_request.mdp_bw = OVERLAY_PERF_LEVEL4; - perf_current.mdp_bw = OVERLAY_PERF_LEVEL4; return 0; } diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c index 5076e11bf4d..1ab063df624 100644 --- a/drivers/video/msm/mdp4_overlay_dsi_video.c +++ b/drivers/video/msm/mdp4_overlay_dsi_video.c @@ -575,6 +575,7 @@ int mdp4_dsi_video_on(struct platform_device *pdev) pipe->dst_w = fbi->var.xres; mdp4_overlay_mdp_pipe_req(pipe, mfd); + mdp4_calc_blt_mdp_bw(mfd, pipe); atomic_set(&vctrl->suspend, 0); diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c index 20e769ae750..d7daa05836d 100644 --- a/drivers/video/msm/mdp4_overlay_dtv.c +++ b/drivers/video/msm/mdp4_overlay_dtv.c @@ -768,6 +768,7 @@ static void mdp4_overlay_dtv_alloc_pipe(struct msm_fb_data_type *mfd, pipe->srcp0_ystride = fbi->fix.line_length; mdp4_overlay_mdp_pipe_req(pipe, mfd); + mdp4_calc_blt_mdp_bw(mfd, pipe); ret = mdp4_overlay_format2pipe(pipe); if (ret < 0) diff --git a/drivers/video/msm/mdp4_overlay_lcdc.c b/drivers/video/msm/mdp4_overlay_lcdc.c index b67c59839d6..c4e4ad949b2 100644 --- a/drivers/video/msm/mdp4_overlay_lcdc.c +++ b/drivers/video/msm/mdp4_overlay_lcdc.c @@ -544,6 +544,7 @@ int mdp4_lcdc_on(struct platform_device *pdev) pipe->bpp = bpp; mdp4_overlay_mdp_pipe_req(pipe, mfd); + mdp4_calc_blt_mdp_bw(mfd, pipe); atomic_set(&vctrl->suspend, 0); diff --git a/drivers/video/msm/mdp4_overlay_writeback.c b/drivers/video/msm/mdp4_overlay_writeback.c index aa50d94b888..42b748c93b9 100644 --- a/drivers/video/msm/mdp4_overlay_writeback.c +++ b/drivers/video/msm/mdp4_overlay_writeback.c @@ -260,6 +260,7 @@ static int mdp4_overlay_writeback_update(struct msm_fb_data_type *mfd) pipe->dst_x = 0; mdp4_overlay_mdp_pipe_req(pipe, mfd); + mdp4_calc_blt_mdp_bw(mfd, pipe); if (mfd->display_iova) pipe->srcp0_addr = mfd->display_iova + buf_offset; diff --git a/drivers/video/msm/mdp4_util.c b/drivers/video/msm/mdp4_util.c index d880be49e77..632354ba9a2 100644 --- a/drivers/video/msm/mdp4_util.c +++ b/drivers/video/msm/mdp4_util.c @@ -392,7 +392,8 @@ void mdp4_hw_init(void) /* MDP cmd block enable */ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); - mdp_bus_scale_update_request(5); + mdp_bus_scale_update_request + (MDP_BUS_SCALE_INIT, MDP_BUS_SCALE_INIT); #ifdef MDP4_ERROR /* diff --git a/drivers/video/msm/mipi_dsi.c b/drivers/video/msm/mipi_dsi.c index 493b102966e..9a712f7977d 100644 --- a/drivers/video/msm/mipi_dsi.c +++ b/drivers/video/msm/mipi_dsi.c @@ -106,11 +106,8 @@ static int mipi_dsi_off(struct platform_device *pdev) ret = panel_next_off(pdev); -#ifdef CONFIG_MSM_BUS_SCALING - mdp_bus_scale_update_request(0); -#endif - spin_lock_bh(&dsi_clk_lock); + mipi_dsi_clk_disable(); /* disbale dsi engine */ @@ -316,10 +313,6 @@ static int mipi_dsi_on(struct platform_device *pdev) mipi_dsi_unprepare_clocks(); } -#ifdef CONFIG_MSM_BUS_SCALING - mdp_bus_scale_update_request(2); -#endif - if (mdp_rev >= MDP_REV_41) mutex_unlock(&mfd->dma->ov_mutex); else