diff options
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_dsi.c | 23 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_dsi_panel.c | 49 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_ctl.c | 53 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_hwio.h | 4 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_intf_video.c | 23 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_panel.h | 21 |
6 files changed, 159 insertions, 14 deletions
diff --git a/drivers/video/fbdev/msm/mdss_dsi.c b/drivers/video/fbdev/msm/mdss_dsi.c index 7d03d635156e..fd79453e98f6 100644 --- a/drivers/video/fbdev/msm/mdss_dsi.c +++ b/drivers/video/fbdev/msm/mdss_dsi.c @@ -477,7 +477,7 @@ int mdss_dsi_on(struct mdss_panel_data *pdata) struct mdss_panel_info *pinfo; struct mipi_panel_info *mipi; u32 hbp, hfp, vbp, vfp, hspw, vspw, width, height; - u32 ystride, bpp, data; + u32 ystride, bpp, data, dst_bpp; u32 dummy_xres, dummy_yres; struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; @@ -516,13 +516,22 @@ int mdss_dsi_on(struct mdss_panel_data *pdata) clk_rate = pdata->panel_info.clk_rate; clk_rate = min(clk_rate, pdata->panel_info.clk_max); - hbp = pdata->panel_info.lcdc.h_back_porch; - hfp = pdata->panel_info.lcdc.h_front_porch; - vbp = pdata->panel_info.lcdc.v_back_porch; - vfp = pdata->panel_info.lcdc.v_front_porch; - hspw = pdata->panel_info.lcdc.h_pulse_width; + dst_bpp = pdata->panel_info.fbc.enabled ? + (pdata->panel_info.fbc.target_bpp) : (pinfo->bpp); + + hbp = mult_frac(pdata->panel_info.lcdc.h_back_porch, dst_bpp, + pdata->panel_info.bpp); + hfp = mult_frac(pdata->panel_info.lcdc.h_front_porch, dst_bpp, + pdata->panel_info.bpp); + vbp = mult_frac(pdata->panel_info.lcdc.v_back_porch, dst_bpp, + pdata->panel_info.bpp); + vfp = mult_frac(pdata->panel_info.lcdc.v_front_porch, dst_bpp, + pdata->panel_info.bpp); + hspw = mult_frac(pdata->panel_info.lcdc.h_pulse_width, dst_bpp, + pdata->panel_info.bpp); vspw = pdata->panel_info.lcdc.v_pulse_width; - width = pdata->panel_info.xres; + width = mult_frac(pdata->panel_info.xres, dst_bpp, + pdata->panel_info.bpp); height = pdata->panel_info.yres; mipi = &pdata->panel_info.mipi; diff --git a/drivers/video/fbdev/msm/mdss_dsi_panel.c b/drivers/video/fbdev/msm/mdss_dsi_panel.c index 85bd268d4753..485874dcfa0a 100644 --- a/drivers/video/fbdev/msm/mdss_dsi_panel.c +++ b/drivers/video/fbdev/msm/mdss_dsi_panel.c @@ -227,6 +227,7 @@ static int mdss_panel_parse_dt(struct platform_device *pdev, { struct device_node *np = pdev->dev.of_node; u32 res[6], tmp; + u32 fbc_res[7]; int rc, i, len; int cmd_plen, data_offset; const char *data; @@ -234,6 +235,7 @@ static int mdss_panel_parse_dt(struct platform_device *pdev, static const char *on_cmds_state, *off_cmds_state; char *on_cmds = NULL, *off_cmds = NULL; int num_of_on_cmds = 0, num_of_off_cmds = 0; + bool fbc_enabled = false; rc = of_property_read_u32_array(np, "qcom,mdss-pan-res", res, 2); if (rc) { @@ -480,6 +482,53 @@ static int mdss_panel_parse_dt(struct platform_device *pdev, panel_data->panel_info.mipi.dsi_phy_db = &phy_params; + fbc_enabled = of_property_read_bool(np, + "qcom,fbc-enabled"); + if (fbc_enabled) { + pr_debug("%s:%d FBC panel enabled.\n", __func__, __LINE__); + panel_data->panel_info.fbc.enabled = 1; + + rc = of_property_read_u32_array(np, + "qcom,fbc-mode", fbc_res, 7); + panel_data->panel_info.fbc.target_bpp = + (!rc ? fbc_res[0] : panel_data->panel_info.bpp); + panel_data->panel_info.fbc.comp_mode = (!rc ? fbc_res[1] : 0); + panel_data->panel_info.fbc.qerr_enable = + (!rc ? fbc_res[2] : 0); + panel_data->panel_info.fbc.cd_bias = (!rc ? fbc_res[3] : 0); + panel_data->panel_info.fbc.pat_enable = (!rc ? fbc_res[4] : 0); + panel_data->panel_info.fbc.vlc_enable = (!rc ? fbc_res[5] : 0); + panel_data->panel_info.fbc.bflc_enable = + (!rc ? fbc_res[6] : 0); + + rc = of_property_read_u32_array(np, + "qcom,fbc-budget-ctl", fbc_res, 3); + panel_data->panel_info.fbc.line_x_budget = + (!rc ? fbc_res[0] : 0); + panel_data->panel_info.fbc.block_x_budget = + (!rc ? fbc_res[1] : 0); + panel_data->panel_info.fbc.block_budget = + (!rc ? fbc_res[2] : 0); + + rc = of_property_read_u32_array(np, + "qcom,fbc-lossy-mode", fbc_res, 4); + panel_data->panel_info.fbc.lossless_mode_thd = + (!rc ? fbc_res[0] : 0); + panel_data->panel_info.fbc.lossy_mode_thd = + (!rc ? fbc_res[1] : 0); + panel_data->panel_info.fbc.lossy_rgb_thd = + (!rc ? fbc_res[2] : 0); + panel_data->panel_info.fbc.lossy_mode_idx = + (!rc ? fbc_res[3] : 0); + + } else { + pr_debug("%s:%d Panel does not support FBC.\n", + __func__, __LINE__); + panel_data->panel_info.fbc.enabled = 0; + panel_data->panel_info.fbc.target_bpp = + panel_data->panel_info.bpp; + } + data = of_get_property(np, "qcom,panel-on-cmds", &len); if (!data) { pr_err("%s:%d, Unable to read ON cmds", __func__, __LINE__); diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c index 10b8d3ebf926..1ced2009b868 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c +++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c @@ -465,6 +465,54 @@ static inline struct mdss_mdp_ctl *mdss_mdp_get_split_ctl( return NULL; } +static int mdss_mdp_ctl_fbc_enable(int enable, + struct mdss_mdp_mixer *mixer, struct mdss_panel_info *pdata) +{ + struct fbc_panel_info *fbc; + u32 mode = 0, budget_ctl = 0, lossy_mode = 0; + + if (!pdata) { + pr_err("Invalid pdata\n"); + return -EINVAL; + } + + fbc = &pdata->fbc; + + if (!fbc || !fbc->enabled) { + pr_err("Invalid FBC structure\n"); + return -EINVAL; + } + + if (mixer->num == MDSS_MDP_INTF_LAYERMIXER0) + pr_debug("Mixer supports FBC.\n"); + else { + pr_debug("Mixer doesn't support FBC.\n"); + return -EINVAL; + } + + if (enable) { + mode = ((pdata->xres) << 16) | ((fbc->comp_mode) << 8) | + ((fbc->qerr_enable) << 7) | ((fbc->cd_bias) << 4) | + ((fbc->pat_enable) << 3) | ((fbc->vlc_enable) << 2) | + ((fbc->bflc_enable) << 1) | enable; + + budget_ctl = ((fbc->line_x_budget) << 12) | + ((fbc->block_x_budget) << 8) | fbc->block_budget; + + lossy_mode = ((fbc->lossless_mode_thd) << 16) | + ((fbc->lossy_mode_thd) << 8) | + ((fbc->lossy_rgb_thd) << 3) | fbc->lossy_mode_idx; + } + + mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_FBC_MODE, mode); + mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_FBC_BUDGET_CTL, + budget_ctl); + mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_FBC_LOSSY_MODE, + lossy_mode); + + return 0; +} + int mdss_mdp_ctl_setup(struct mdss_mdp_ctl *ctl) { struct mdss_mdp_ctl *split_ctl; @@ -841,6 +889,11 @@ static int mdss_mdp_ctl_start_sub(struct mdss_mdp_ctl *ctl) outsize = (mixer->height << 16) | mixer->width; mdp_mixer_write(mixer, MDSS_MDP_REG_LM_OUT_SIZE, outsize); + if (ctl->panel_data->panel_info.fbc.enabled) { + ret = mdss_mdp_ctl_fbc_enable(1, ctl->mixer_left, + &ctl->panel_data->panel_info); + } + return ret; } diff --git a/drivers/video/fbdev/msm/mdss_mdp_hwio.h b/drivers/video/fbdev/msm/mdss_mdp_hwio.h index bf78c6186dac..d50f47e0f247 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_hwio.h +++ b/drivers/video/fbdev/msm/mdss_mdp_hwio.h @@ -445,6 +445,10 @@ enum mdss_mdp_pingpong_index { #define MDSS_MDP_REG_PP_LINE_COUNT 0x02C #define MDSS_MDP_REG_PP_AUTOREFRESH_CONFIG 0x030 +#define MDSS_MDP_REG_PP_FBC_MODE 0x034 +#define MDSS_MDP_REG_PP_FBC_BUDGET_CTL 0x038 +#define MDSS_MDP_REG_PP_FBC_LOSSY_MODE 0x03C + #define MDSS_MDP_REG_SMP_ALLOC_W0 0x00180 #define MDSS_MDP_REG_SMP_ALLOC_R0 0x00230 diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c index e7f70b6c9d5c..8c57c8c569fb 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c +++ b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c @@ -373,6 +373,7 @@ int mdss_mdp_video_start(struct mdss_mdp_ctl *ctl) struct mdss_mdp_video_ctx *ctx; struct mdss_mdp_mixer *mixer; struct intf_timing_params itp = {0}; + u32 dst_bpp; int i; mdata = ctl->mdata; @@ -411,19 +412,27 @@ int mdss_mdp_video_start(struct mdss_mdp_ctl *ctl) mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_UNDER_RUN, ctl->intf_num, mdss_mdp_video_underrun_intr_done, ctl); - itp.width = pinfo->xres + pinfo->lcdc.xres_pad; + dst_bpp = pinfo->fbc.enabled ? (pinfo->fbc.target_bpp) : (pinfo->bpp); + + itp.width = mult_frac((pinfo->xres + pinfo->lcdc.xres_pad), + dst_bpp, pinfo->bpp); itp.height = pinfo->yres + pinfo->lcdc.yres_pad; itp.border_clr = pinfo->lcdc.border_clr; itp.underflow_clr = pinfo->lcdc.underflow_clr; itp.hsync_skew = pinfo->lcdc.hsync_skew; - itp.xres = pinfo->xres; + itp.xres = mult_frac(pinfo->xres, dst_bpp, pinfo->bpp); itp.yres = pinfo->yres; - itp.h_back_porch = pinfo->lcdc.h_back_porch; - itp.h_front_porch = pinfo->lcdc.h_front_porch; - itp.v_back_porch = pinfo->lcdc.v_back_porch; - itp.v_front_porch = pinfo->lcdc.v_front_porch; - itp.hsync_pulse_width = pinfo->lcdc.h_pulse_width; + itp.h_back_porch = mult_frac(pinfo->lcdc.h_back_porch, dst_bpp, + pinfo->bpp); + itp.h_front_porch = mult_frac(pinfo->lcdc.h_front_porch, dst_bpp, + pinfo->bpp); + itp.v_back_porch = mult_frac(pinfo->lcdc.v_back_porch, dst_bpp, + pinfo->bpp); + itp.v_front_porch = mult_frac(pinfo->lcdc.v_front_porch, dst_bpp, + pinfo->bpp); + itp.hsync_pulse_width = mult_frac(pinfo->lcdc.h_pulse_width, dst_bpp, + pinfo->bpp); itp.vsync_pulse_width = pinfo->lcdc.v_pulse_width; if (mdss_mdp_video_timegen_setup(ctx, &itp)) { diff --git a/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h index 23f7445804bf..d230100c8724 100644 --- a/drivers/video/fbdev/msm/mdss_panel.h +++ b/drivers/video/fbdev/msm/mdss_panel.h @@ -157,6 +157,26 @@ struct lvds_panel_info { char channel_swap; }; +struct fbc_panel_info { + u32 enabled; + u32 target_bpp; + u32 comp_mode; + u32 qerr_enable; + u32 cd_bias; + u32 pat_enable; + u32 vlc_enable; + u32 bflc_enable; + + u32 line_x_budget; + u32 block_x_budget; + u32 block_budget; + + u32 lossless_mode_thd; + u32 lossy_mode_thd; + u32 lossy_rgb_thd; + u32 lossy_mode_idx; +}; + struct mdss_panel_info { u32 xres; u32 yres; @@ -184,6 +204,7 @@ struct mdss_panel_info { u32 panel_power_on; struct lcd_panel_info lcdc; + struct fbc_panel_info fbc; struct mipi_panel_info mipi; struct lvds_panel_info lvds; }; |
