msm: mdss: Add support for FrameBuffer Compression(FBC)

MDSS supports FBC 1.0 and FBC 2.0. Add MDP and DSI configurations
for FBC.

Change-Id: Ia265a726e6660cc349808862ddbbcd380d9840fd
diff --git a/platform/msm_shared/mdp5.c b/platform/msm_shared/mdp5.c
old mode 100644
new mode 100755
index 1c0f1aa..df6f22d
--- a/platform/msm_shared/mdp5.c
+++ b/platform/msm_shared/mdp5.c
@@ -356,11 +356,12 @@
 {
 	uint32_t hsync_period, vsync_period;
 	uint32_t hsync_start_x, hsync_end_x;
-	uint32_t display_hctl, active_hctl, hsync_ctl, display_vstart, display_vend;
+	uint32_t display_hctl, hsync_ctl, display_vstart, display_vend;
 	uint32_t mdss_mdp_intf_off;
 	uint32_t adjust_xres = 0;
 
 	struct lcdc_panel_info *lcdc = NULL;
+	struct intf_timing_params itp = {0};
 
 	if (pinfo == NULL)
 		return ERR_INVALID_ARGS;
@@ -384,41 +385,58 @@
 		writel(BIT(5), MDP_REG_PPB0_CNTL);
 	}
 
+	if (!pinfo->fbc.enabled || !pinfo->fbc.comp_ratio)
+		pinfo->fbc.comp_ratio = 1;
+
+	itp.xres = (adjust_xres / pinfo->fbc.comp_ratio);
+	itp.yres = pinfo->yres;
+	itp.width =((adjust_xres + pinfo->lcdc.xres_pad) / pinfo->fbc.comp_ratio);
+	itp.height = pinfo->yres + pinfo->lcdc.yres_pad;
+	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.vsync_pulse_width = pinfo->lcdc.v_pulse_width;
+
+	itp.border_clr = pinfo->lcdc.border_clr;
+	itp.underflow_clr = pinfo->lcdc.underflow_clr;
+	itp.hsync_skew = pinfo->lcdc.hsync_skew;
+
+
 	mdss_mdp_intf_off = intf_base + mdss_mdp_intf_offset();
 
-	hsync_period = lcdc->h_pulse_width +
-		lcdc->h_back_porch +
-		adjust_xres + lcdc->xres_pad + lcdc->h_front_porch;
-	vsync_period = (lcdc->v_pulse_width +
-			lcdc->v_back_porch +
-			pinfo->yres + lcdc->yres_pad +
-			lcdc->v_front_porch);
+	hsync_period = itp.hsync_pulse_width + itp.h_back_porch +
+			itp.width + itp.h_front_porch;
+
+	vsync_period = itp.vsync_pulse_width + itp.v_back_porch +
+			itp.height + itp.v_front_porch;
 
 	hsync_start_x =
-		lcdc->h_pulse_width +
-		lcdc->h_back_porch;
+		itp.hsync_pulse_width +
+		itp.h_back_porch;
 	hsync_end_x =
-		hsync_period - lcdc->h_front_porch - 1;
+		hsync_period - itp.h_front_porch - 1;
 
-	display_vstart = (lcdc->v_pulse_width +
-			lcdc->v_back_porch)
-		* hsync_period + lcdc->hsync_skew;
-	display_vend = ((vsync_period - lcdc->v_front_porch) * hsync_period)
-		+lcdc->hsync_skew - 1;
+	display_vstart = (itp.vsync_pulse_width +
+			itp.v_back_porch)
+		* hsync_period + itp.hsync_skew;
+	display_vend = ((vsync_period - itp.v_front_porch) * hsync_period)
+		+ itp.hsync_skew - 1;
 
 	if (intf_base == MDP_INTF_0_BASE) { /* eDP */
-		display_vstart += lcdc->h_pulse_width + lcdc->h_back_porch;
-		display_vend -= lcdc->h_front_porch;
+		display_vstart += itp.hsync_pulse_width + itp.h_back_porch;
+		display_vend -= itp.h_front_porch;
 	}
 
-	hsync_ctl = (hsync_period << 16) | lcdc->h_pulse_width;
+	hsync_ctl = (hsync_period << 16) | itp.hsync_pulse_width;
 	display_hctl = (hsync_end_x << 16) | hsync_start_x;
 
 	writel(hsync_ctl, MDP_HSYNC_CTL + mdss_mdp_intf_off);
 	writel(vsync_period*hsync_period, MDP_VSYNC_PERIOD_F0 +
 			mdss_mdp_intf_off);
 	writel(0x00, MDP_VSYNC_PERIOD_F1 + mdss_mdp_intf_off);
-	writel(lcdc->v_pulse_width*hsync_period,
+	writel(itp.vsync_pulse_width*hsync_period,
 			MDP_VSYNC_PULSE_WIDTH_F0 +
 			mdss_mdp_intf_off);
 	writel(0x00, MDP_VSYNC_PULSE_WIDTH_F1 + mdss_mdp_intf_off);
@@ -507,6 +525,57 @@
 	}
 }
 
+void mdss_fbc_cfg(struct msm_panel_info *pinfo)
+{
+	uint32_t mode = 0;
+	uint32_t budget_ctl = 0;
+	uint32_t lossy_mode = 0;
+	uint32_t xres;
+	struct fbc_panel_info *fbc;
+	uint32_t enc_mode;
+
+	fbc = &pinfo->fbc;
+	xres = pinfo->xres;
+
+	if (!pinfo->fbc.enabled)
+		return;
+
+	if (pinfo->mipi.dual_dsi)
+		xres /= 2;
+
+	/* enc_mode defines FBC version. 0 = FBC 1.0 and 1 = FBC 2.0 */
+	enc_mode = (fbc->comp_ratio == 2) ? 0 : 1;
+
+	mode = ((xres) << 16) | (enc_mode) << 9 | ((fbc->comp_mode) << 8) |
+		((fbc->qerr_enable) << 7) | ((fbc->cd_bias) << 4) |
+		((fbc->pat_enable) << 3) | ((fbc->vlc_enable) << 2) |
+		((fbc->bflc_enable) << 1) | 1;
+
+	dprintf(SPEW, "xres = %d, comp_mode %d, qerr_enable = %d, cd_bias = %d\n",
+			xres, fbc->comp_mode, fbc->qerr_enable, fbc->cd_bias);
+	dprintf(SPEW, "pat_enable %d, vlc_enable = %d, bflc_enable\n",
+			fbc->pat_enable, fbc->vlc_enable, fbc->bflc_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) << 4) | fbc->lossy_mode_idx;
+
+	writel(mode, MDP_PP_0_BASE + MDSS_MDP_REG_PP_FBC_MODE);
+	writel(budget_ctl, MDP_PP_0_BASE + MDSS_MDP_REG_PP_FBC_BUDGET_CTL);
+	writel(lossy_mode, MDP_PP_0_BASE + MDSS_MDP_REG_PP_FBC_LOSSY_MODE);
+
+	if (pinfo->mipi.dual_dsi) {
+		writel(mode, MDP_PP_1_BASE + MDSS_MDP_REG_PP_FBC_MODE);
+		writel(budget_ctl, MDP_PP_1_BASE +
+				MDSS_MDP_REG_PP_FBC_BUDGET_CTL);
+		writel(lossy_mode, MDP_PP_1_BASE +
+				MDSS_MDP_REG_PP_FBC_LOSSY_MODE);
+	}
+}
+
 void mdss_qos_remapper_setup(void)
 {
 	uint32_t mdp_hw_rev = readl(MDP_HW_REV);
@@ -627,6 +696,8 @@
 	/*If dst_split is enabled only intf 2 needs to be enabled.
 	CTL_1 path should not be set since CTL_0 itself is going
 	to split after DSPP block*/
+	if (pinfo->fbc.enabled)
+		mdss_fbc_cfg(pinfo);
 
 	if (pinfo->mipi.dual_dsi) {
 		if (!pinfo->lcdc.dst_split) {
@@ -771,6 +842,9 @@
 	reg = 0x21f00 | mdss_mdp_ctl_out_sel(pinfo, 1);
 	writel(reg, MDP_CTL_0_BASE + CTL_TOP);
 
+	if (pinfo->fbc.enabled)
+		mdss_fbc_cfg(pinfo);
+
 	if (pinfo->mipi.dual_dsi) {
 		writel(0x213F, MDP_INTF_2_BASE + MDP_PANEL_FORMAT + mdss_mdp_intf_off);
 		reg = 0x21f00 | mdss_mdp_ctl_out_sel(pinfo, 0);