Browse Source

disp: msm: add VDC-m parameter calculation support

Add support to calculate the parameters needed to configure
the VDC-m encoder. These are also needed to configure the PPS
command which shall be sent to the decoder.

Change-Id: I36db93f7555aee34b5b893e389a7eb88d0e05f68
Signed-off-by: Abhinav Kumar <[email protected]>
Abhinav Kumar 5 years ago
parent
commit
497fe7758b
5 changed files with 1077 additions and 21 deletions
  1. 1 0
      msm/Makefile
  2. 22 2
      msm/dsi/dsi_panel.c
  3. 213 19
      msm/msm_drv.h
  4. 792 0
      msm/sde_vdc_helper.c
  5. 49 0
      msm/sde_vdc_helper.h

+ 1 - 0
msm/Makefile

@@ -74,6 +74,7 @@ msm_drm-$(CONFIG_DRM_MSM_SDE) += sde/sde_crtc.o \
 	sde/sde_fence.o \
 	sde/sde_hw_qdss.o \
 	sde_dsc_helper.o \
+	sde_vdc_helper.o \
 
 msm_drm-$(CONFIG_DRM_SDE_WB) += sde/sde_wb.o \
 	sde/sde_encoder_phys_wb.o \

+ 22 - 2
msm/dsi/dsi_panel.c

@@ -14,6 +14,7 @@
 #include "dsi_ctrl_hw.h"
 #include "dsi_parser.h"
 #include "sde_dsc_helper.h"
+#include "sde_vdc_helper.h"
 
 /**
  * topology is currently defined by a set of following 3 values:
@@ -2366,12 +2367,13 @@ error:
 }
 
 static int dsi_panel_parse_vdc_params(struct dsi_display_mode *mode,
-				struct dsi_parser_utils *utils)
+	struct dsi_parser_utils *utils, int traffic_mode, int panel_mode)
 {
 	u32 data;
 	int rc = -EINVAL;
 	const char *compression;
 	struct dsi_display_mode_priv_info *priv_info;
+	int intf_width;
 
 	if (!mode || !mode->priv_info)
 		return -EINVAL;
@@ -2389,6 +2391,9 @@ static int dsi_panel_parse_vdc_params(struct dsi_display_mode *mode,
 		return 0;
 	}
 
+	priv_info->vdc.panel_mode = panel_mode;
+	priv_info->vdc.traffic_mode = traffic_mode;
+
 	rc = utils->read_u32(utils->data, "qcom,vdc-version", &data);
 	if (rc) {
 		priv_info->vdc.version_major = 0x1;
@@ -2477,6 +2482,8 @@ static int dsi_panel_parse_vdc_params(struct dsi_display_mode *mode,
 		rc = -EINVAL;
 		goto error;
 	}
+
+	intf_width = mode->timing.h_active;
 	priv_info->vdc.slice_per_pkt = data;
 
 	priv_info->vdc.frame_width = mode->timing.h_active;
@@ -2523,6 +2530,14 @@ static int dsi_panel_parse_vdc_params(struct dsi_display_mode *mode,
 	}
 	priv_info->vdc.source_color_space = data;
 
+	rc = sde_vdc_populate_config(&priv_info->vdc,
+		intf_width, traffic_mode);
+	if (rc) {
+		DSI_DEBUG("failed populating vdc config\n");
+		rc = -EINVAL;
+		goto error;
+	}
+
 	mode->timing.vdc_enabled = true;
 	mode->timing.vdc = &priv_info->vdc;
 
@@ -3555,6 +3570,8 @@ int dsi_panel_get_mode(struct dsi_panel *panel,
 	struct dsi_display_mode_priv_info *prv_info;
 	u32 child_idx = 0;
 	int rc = 0, num_timings;
+	int traffic_mode;
+	int panel_mode;
 	void *utils_data = NULL;
 
 	if (!panel || !mode) {
@@ -3589,6 +3606,8 @@ int dsi_panel_get_mode(struct dsi_panel *panel,
 	}
 
 	utils_data = utils->data;
+	traffic_mode = panel->video_config.traffic_mode;
+	panel_mode = panel->panel_mode;
 
 	dsi_for_each_child_node(timings_np, child_np) {
 		if (index != child_idx++)
@@ -3608,7 +3627,8 @@ int dsi_panel_get_mode(struct dsi_panel *panel,
 			goto parse_fail;
 		}
 
-		rc = dsi_panel_parse_vdc_params(mode, utils);
+		rc = dsi_panel_parse_vdc_params(mode, utils, traffic_mode,
+			panel_mode);
 		if (rc) {
 			DSI_ERR("failed to parse vdc params, rc=%d\n", rc);
 			goto parse_fail;

+ 213 - 19
msm/msm_drv.h

@@ -357,38 +357,232 @@ struct msm_display_dsc_info {
 
 /**
  * struct msm_display_vdc_info - defines vdc configuration
- * @version_major:           major version number of VDC encoder.
- * @version_minor:           minor version number of VDC encoder.
- * @source_color_space:      source color space of VDC encoder
- * @chroma_format:           chroma_format of VDC encoder.
- * @slice_height:            slice height configuration of encoder.
- * @slice_width:             slice width configuration of encoder.
- * @bytes_in_slice:          number of bytes per slice .
- * @slice_per_pkt:           number of slices per packet.
- * @bits_per_component:      number of bits per component.
- * @bits_per_pixel:          number of bits per pixel.
- * @frame_width:             frame width configuration of encoder
- * @frame_height:            frame height configuration of encoder
- * @pps_delay_ms:            Post PPS command delay in milliseconds.
- * @version_release:		 release version of VDC encoder.
+ * @version_major:              major version number of VDC encoder.
+ * @version_minor:              minor version number of VDC encoder.
+ * @source_color_space:         source color space of VDC encoder
+ * @chroma_format:              chroma_format of VDC encoder.
+ * @mppf_bpc_r_y:               MPPF bpc for R/Y color component
+ * @mppf_bpc_g_cb:              MPPF bpc for G/Cb color component
+ * @mppf_bpc_b_cr:              MPPF bpc for B/Cr color component
+ * @mppf_bpc_y:                 MPPF bpc for Y color component
+ * @mppf_bpc_co:                MPPF bpc for Co color component
+ * @mppf_bpc_cg:                MPPF bpc for Cg color component
+ * @flatqp_vf_fbls:             flatness qp very flat FBLs
+ * @flatqp_vf_nbls:             flatness qp very flat NBLs
+ * @flatqp_sw_fbls:             flatness qp somewhat flat FBLs
+ * @flatqp_sw_nbls:             flatness qp somewhat flat NBLs
+ * @chroma_samples:             number of chroma samples
+ * @split_panel_enable:         indicates whether split panel is enabled
+ * @panel_mode:                 indicates panel is in video or cmd mode
+ * @traffic_mode:               indicates burst/non-burst mode
+ * @flatness_qp_lut:            LUT used to determine flatness QP
+ * @max_qp_lut:                 LUT used to determine maximum QP
+ * @tar_del_lut:                LUT used to calculate RC target rate
+ * @lbda_brate_lut:             lambda bitrate LUT for encoder
+ * @lbda_bf_lut:                lambda buffer fullness lut for encoder
+ * @lbda_brate_lut_interp:      interpolated lambda bitrate LUT
+ * @lbda_bf_lut_interp:         interpolated lambda buffer fullness lut
+ * @num_of_active_ss:           number of active soft slices
+ * @bits_per_component:         number of bits per component.
+ * @max_pixels_per_line:        maximum pixels per line
+ * @max_pixels_per_hs_line:     maximum pixels per hs line
+ * @max_lines_per_frame:        maximum lines per frame
+ * @max_lines_per_slice:        maximum lines per slice
+ * @chunk_size:                 chunk size for encoder
+ * @chunk_size_bits:            number of bits in the chunk
+ * @avg_block_bits:             average block bits
+ * @per_chunk_pad_bits:         number of bits per chunk pad
+ * @tot_pad_bits:               total padding bits
+ * @rc_stuffing_bits:           rate control stuffing bits
+ * @chunk_adj_bits:             number of adjacent bits in the chunk
+ * @rc_buf_init_size_temp:      temporary rate control buffer init size
+ * @init_tx_delay_temp:         initial tx delay
+ * @rc_buffer_init_size:        rate control buffer init size
+ * @rc_init_tx_delay:           rate control buffer init tx delay
+ * @rc_init_tx_delay_px_times:  rate control buffer init tx
+ *                              delay times pixels
+ * @rc_buffer_max_size:         max size of rate control buffer
+ * @rc_tar_rate_scale_temp_a:   rate control target rate scale parameter
+ * @rc_tar_rate_scale_temp_b:	rate control target rate scale parameter
+ * @rc_tar_rate_scale:          rate control target rate scale
+ * @block_max_bits:             max bits in the block
+ * @rc_lambda_bitrate_scale:    rate control lambda bitrate scale
+ * @rc_buffer_fullness_scale:   rate control lambda fullness scale
+ * @rc_fullness_offset_thresh:  rate control lambda fullness threshold
+ * @ramp_blocks:                number of ramp blocks
+ * @bits_per_pixel:             number of bits per pixel.
+ * @num_extra_mux_bits_init:    initial value of number of extra mux bits
+ * @extra_crop_bits:            number of extra crop bits
+ * @num_extra_mux_bits:         value of number of extra mux bits
+ * @mppf_bits_comp_0:           mppf bits in color component 0
+ * @mppf_bits_comp_1:           mppf bits in color component 1
+ * @mppf_bits_comp_2:           mppf bits in color component 2
+ * @min_block_bits:             min number of block bits
+ * @slice_height:               slice height configuration of encoder.
+ * @slice_width:                slice width configuration of encoder.
+ * @frame_width:                frame width configuration of encoder
+ * @frame_height:               frame height configuration of encoder
+ * @bytes_in_slice:             Number of bytes in slice.
+ * @bytes_per_pkt:              Number of bytes in packet.
+ * @eol_byte_num:               Valid bytes at the end of line.
+ * @pclk_per_line:              Compressed width.
+ * @slice_per_pkt:              Number of slices per packet.
+ * @pkt_per_line:               Number of packets per line.
+ * @min_ssm_delay:              Min Sub-stream multiplexing delay
+ * @max_ssm_delay:              Max Sub-stream multiplexing delay
+ * @input_ssm_out_latency:      input Sub-stream multiplexing output latency
+ * @input_ssm_out_latency_min:  min input Sub-stream multiplexing output latency
+ * @obuf_latency:               Output buffer latency
+ * @base_hs_latency:            base hard-slice latency
+ * @base_hs_latency_min:        base hard-slice min latency
+ * @base_hs_latency_pixels:     base hard-slice latency pixels
+ * @base_hs_latency_pixels_min: base hard-slice latency pixels(min)
+ * @base_initial_lines:         base initial lines
+ * @base_top_up:                base top up
+ * @output_rate:                output rate
+ * @output_rate_ratio_100:      output rate times 100
+ * @burst_accum_pixels:         burst accumulated pixels
+ * @ss_initial_lines:           soft-slice initial lines
+ * @burst_initial_lines:        burst mode initial lines
+ * @initial_lines:              initial lines
+ * @obuf_base:                  output buffer base
+ * @obuf_extra_ss0:             output buffer extra ss0
+ * @obuf_extra_ss1:             output buffer extra ss1
+ * @obuf_extra_burst:           output buffer extra burst
+ * @obuf_ss0:                   output buffer ss0
+ * @obuf_ss1:                   output buffer ss1
+ * @obuf_margin_words:          output buffer margin words
+ * @ob0_max_addr:               output buffer 0 max address
+ * @ob1_max_addr:               output buffer 1 max address
+ * @slice_width_orig:           original slice width
+ * @r2b0_max_addr:              r2b0 max addr
+ * @r2b1_max_addr:              r1b1 max addr
+ * @slice_num_px:               number of pixels per slice
+ * @rc_target_rate_threshold:   rate control target rate threshold
+ * @rc_fullness_offset_slope:   rate control fullness offset slop
+ * @pps_delay_ms:               Post PPS command delay in milliseconds.
+ * @version_release:            release version of VDC encoder.
+ * @slice_num_bits:             number of bits per slice
+ * @ramp_bits:                  number of ramp bits
  */
 struct msm_display_vdc_info {
 	u8 version_major;
 	u8 version_minor;
-	u8 chroma_format;
+
 	u8 source_color_space;
+	u8 chroma_format;
+	u8 mppf_bpc_r_y;
+	u8 mppf_bpc_g_cb;
+	u8 mppf_bpc_b_cr;
+	u8 mppf_bpc_y;
+	u8 mppf_bpc_co;
+	u8 mppf_bpc_cg;
+	u8 flatqp_vf_fbls;
+	u8 flatqp_vf_nbls;
+	u8 flatqp_sw_fbls;
+	u8 flatqp_sw_nbls;
+	u8 chroma_samples;
+	u8 split_panel_enable;
+	u8 panel_mode;
+	u8 traffic_mode;
+
+	u16 flatness_qp_lut[8];
+	u16 max_qp_lut[8];
+	u16 tar_del_lut[16];
+	u16 lbda_brate_lut[16];
+	u16 lbda_bf_lut[16];
+	u16 lbda_brate_lut_interp[64];
+	u16 lbda_bf_lut_interp[64];
+
+	u8 num_of_active_ss;
+	u8 bits_per_component;
+
+	u16 max_pixels_per_line;
+	u16 max_pixels_per_hs_line;
+	u16 max_lines_per_frame;
+	u16 max_lines_per_slice;
+
+	u16 chunk_size;
+	u16 chunk_size_bits;
+
+	u16 avg_block_bits;
+	u16 per_chunk_pad_bits;
+	u16 tot_pad_bits;
+	u16 rc_stuffing_bits;
+	u16 chunk_adj_bits;
+	u16 rc_buf_init_size_temp;
+	u16 init_tx_delay_temp;
+	u16 rc_buffer_init_size;
+	u16 rc_init_tx_delay;
+	u16 rc_init_tx_delay_px_times;
+	u16 rc_buffer_max_size;
+	u16 rc_tar_rate_scale_temp_a;
+	u16 rc_tar_rate_scale_temp_b;
+	u16 rc_tar_rate_scale;
+	u16 block_max_bits;
+	u16 rc_lambda_bitrate_scale;
+	u16 rc_buffer_fullness_scale;
+	u16 rc_fullness_offset_thresh;
+	u16 ramp_blocks;
+	u16 bits_per_pixel;
+	u16 num_extra_mux_bits_init;
+	u16 extra_crop_bits;
+	u16 num_extra_mux_bits;
+	u16 mppf_bits_comp_0;
+	u16 mppf_bits_comp_1;
+	u16 mppf_bits_comp_2;
+	u16 min_block_bits;
 
 	int slice_height;
 	int slice_width;
-	int bytes_in_slice;
-	int slice_per_pkt;
-	int bits_per_component;
-	int bits_per_pixel;
 	int frame_width;
 	int frame_height;
 
+	int bytes_in_slice;
+	int bytes_per_pkt;
+	int eol_byte_num;
+	int pclk_per_line;
+	int slice_per_pkt;
+	int pkt_per_line;
+
+	int min_ssm_delay;
+	int max_ssm_delay;
+	int input_ssm_out_latency;
+	int input_ssm_out_latency_min;
+	int obuf_latency;
+	int base_hs_latency;
+	int base_hs_latency_min;
+	int base_hs_latency_pixels;
+	int base_hs_latency_pixels_min;
+	int base_initial_lines;
+	int base_top_up;
+	int output_rate;
+	int output_rate_ratio_100;
+	int burst_accum_pixels;
+	int ss_initial_lines;
+	int burst_initial_lines;
+	int initial_lines;
+	int obuf_base;
+	int obuf_extra_ss0;
+	int obuf_extra_ss1;
+	int obuf_extra_burst;
+	int obuf_ss0;
+	int obuf_ss1;
+	int obuf_margin_words;
+	int ob0_max_addr;
+	int ob1_max_addr;
+	int slice_width_orig;
+	int r2b0_max_addr;
+	int r2b1_max_addr;
+
+	u32 slice_num_px;
+	u32 rc_target_rate_threshold;
+	u32 rc_fullness_offset_slope;
 	u32 pps_delay_ms;
 	u32 version_release;
+
+	u64 slice_num_bits;
+	u64 ramp_bits;
 };
 
 /**

+ 792 - 0
msm/sde_vdc_helper.c

@@ -0,0 +1,792 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ */
+
+#include "msm_drv.h"
+#include "sde_vdc_helper.h"
+
+enum sde_vdc_profile_type {
+	VDC_RGB_444_8BPC_8BPP,
+	VDC_RGB_444_8BPC_6BPP,
+	VDC_RGB_444_10BPC_10BPP,
+	VDC_RGB_444_108BPC_8BPP,
+	VDC_RGB_444_10BPC_7BPP,
+	VDC_RGB_444_10BPC_6BPP,
+	VDC_YUV_422_8BPC_6BPP,
+	VDC_YUV_422_8BPC_5BPP,
+	VDC_YUV_422_8BPC_4_75BPP,
+	VDC_YUV_422_10BPC_8BPP,
+	VDC_YUV_422_10BPC_6BPP,
+	VDC_YUV_422_10BPC_5_5BPP,
+	VDC_YUV_422_10BPC_5PP,
+	VDC_PROFILE_MAX
+};
+
+static u8 sde_vdc_mppf_bpc_r_y[VDC_PROFILE_MAX] = {
+	2, 1, 3, 2, 2, 1, 3, 2, 2, 4, 3, 2, 2};
+
+static u8 sde_vdc_mppf_bpc_g_cb[VDC_PROFILE_MAX] = {
+	2, 2, 3, 2, 2, 2, 2, 2, 1, 3, 2, 2, 2};
+
+static u8 sde_vdc_mppf_bpc_b_cr[VDC_PROFILE_MAX] = {
+	2, 1, 3, 2, 2, 1, 2, 2, 1, 3, 2, 2, 2};
+
+static u8 sde_vdc_mppf_bpc_y[VDC_PROFILE_MAX] = {
+	2, 2, 3, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0};
+
+static u8 sde_vdc_mppf_bpc_co[VDC_PROFILE_MAX] = {
+	2, 1, 3, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0};
+
+static u8 sde_vdc_mppf_bpc_cg[VDC_PROFILE_MAX] = {
+	2, 1, 3, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0};
+
+static u8 sde_vdc_flat_qp_vf_fbls[VDC_PROFILE_MAX] = {
+	20, 24, 24, 24, 24, 24, 24, 24, 24, 8, 20, 18, 24};
+
+static u8 sde_vdc_flat_qp_vf_nfbls[VDC_PROFILE_MAX] = {
+	24, 28, 28, 28, 28, 28, 28, 28, 28, 16, 24, 20, 28};
+
+static u8 sde_vdc_flat_qp_sf_fbls[VDC_PROFILE_MAX] = {
+	24, 28, 28, 28, 28, 28, 28, 28, 28, 16, 24, 20, 28};
+
+static u8 sde_vdc_flat_qp_sf_nbls[VDC_PROFILE_MAX] = {
+	28, 40, 32, 28, 32, 28, 36, 36, 36, 16, 24, 24, 28};
+
+static u16 sde_vdc_flat_qp_lut[VDC_PROFILE_MAX][VDC_FLAT_QP_LUT_SIZE] = {
+	{20, 20, 24, 24, 28, 32, 36, 40},
+	{24, 24, 28, 32, 36, 40, 40, 40},
+	{24, 24, 28, 32, 32, 36, 36, 36},
+	{20, 24, 28, 28, 32, 36, 40, 44},
+	{20, 24, 28, 32, 32, 36, 36, 40},
+	{24, 28, 32, 32, 36, 40, 40, 40},
+	{24, 28, 32, 34, 36, 38, 40, 40},
+	{24, 28, 32, 36, 40, 42, 44, 44},
+	{24, 28, 32, 36, 40, 42, 44, 44},
+	{0, 8, 10, 12, 14, 16, 18, 20},
+	{12, 16, 20, 20, 20, 24, 24, 28},
+	{16, 18, 20, 22, 24, 26, 28, 28},
+	{20, 22, 24, 26, 28, 28, 32, 32},
+};
+
+static u16 sde_vdc_max_qp_lut[VDC_PROFILE_MAX][VDC_MAX_QP_LUT_SIZE] = {
+	{28, 28, 32, 32, 36, 42, 42, 48},
+	{32, 32, 36, 40, 44, 48, 48, 52},
+	{32, 32, 36, 36, 36, 40, 44, 48},
+	{24, 28, 32, 32, 36, 40, 44, 48},
+	{28, 28, 32, 32, 36, 42, 42, 48},
+	{28, 32, 36, 40, 44, 44, 46, 52},
+	{32, 32, 36, 40, 40, 44, 48, 48},
+	{32, 32, 36, 40, 44, 48, 50, 52},
+	{32, 32, 36, 40, 44, 48, 50, 52},
+	{8, 12, 12, 16, 20, 24, 28, 28},
+	{18, 20, 22, 24, 28, 30, 32, 40},
+	{18, 20, 22, 24, 28, 30, 32, 40},
+	{20, 20, 24, 24, 28, 28, 32, 36},
+};
+
+static u16 sde_vdc_tar_del_lut[VDC_PROFILE_MAX][VDC_TAR_DEL_LUT_SIZE] = {
+	{128, 117, 107, 96, 85, 75, 64, 53, 43, 32, 24, 11, 0, 0, 0, 0},
+	{96, 88, 80, 72, 64, 56, 48, 40, 32, 24, 16, 8, 0, 0, 0, 0},
+	{160, 147, 133, 120, 107, 93, 80, 67, 53, 40, 27, 13, 0, 0, 0, 0},
+	{128, 117, 107, 96, 85, 75, 64, 53, 43, 32, 21, 11, 0, 0, 0, 0},
+	{112, 103, 93, 84, 75, 95, 56, 47, 37, 28, 19, 9, 0, 0, 0, 0},
+	{96, 88, 80, 72, 64, 56, 48, 40, 32, 24, 16, 8, 0, 0, 0, 0},
+	{96, 88, 80, 72, 64, 56, 48, 40, 32, 24, 16, 8, 0, 0, 0, 0},
+	{80, 73, 67, 60, 53, 47, 40, 33, 27, 20, 13, 7, 0, 0, 0, 0},
+	{76, 70, 63, 57, 51, 44, 38, 32, 25, 19, 13, 6, 0, 0, 0, 0},
+	{128, 117, 107, 96, 85, 75, 64, 53, 43, 32, 21, 11, 0, 0, 0, 0},
+	{96, 88, 80, 72, 64, 56, 48, 40, 32, 24, 16, 8, 0, 0, 0, 0},
+	{88, 81, 73, 66, 59, 51, 44, 37, 29, 22, 15, 7, 0, 0, 0, 0},
+	{80, 73, 67, 60, 53, 47, 40, 33, 27, 20, 13, 7, 0, 0, 0, 0},
+};
+
+static u16 sde_vdc_lbda_brate_lut[VDC_PROFILE_MAX][VDC_LBDA_BRATE_LUT_SIZE] = {
+	{4, 6, 10, 16, 25, 40, 64, 102, 161, 256, 406, 645, 1024, 1625,
+	2580, 4095},
+	{8, 12, 18, 28, 42, 64, 97, 147, 223, 338, 512, 776, 1176, 1782,
+	2702, 4095},
+	{16, 23, 34, 48, 70, 102, 147, 213, 308, 446, 645, 933, 1351,
+	1955, 2829, 4095},
+	{8, 12, 18, 28, 42, 64, 97, 147, 223, 338, 512, 776, 1176, 1782,
+	2702, 4095},
+	{32, 44, 61, 84, 117, 161, 223, 308, 425, 588, 813, 1123, 1552, 2144,
+	2963, 4095},
+	{64, 84, 111, 147, 194, 256, 338, 446, 588, 776, 1024, 1351, 1782,
+	2352, 3103, 4095},
+	{1, 2, 3, 5, 9, 16, 28, 48, 84, 147, 256, 446, 776, 1351, 2352, 4095},
+	{4, 6, 10, 16, 25, 40, 64, 102, 161, 256, 406, 645, 1024, 1625,
+	2580, 4095},
+	{4, 6, 10, 16, 25, 40, 64, 102, 161, 256, 406, 645, 1024, 1625,
+	2580, 4095},
+	{1, 2, 3, 5, 9, 16, 28, 48, 84, 147, 256, 446, 776, 1351, 2352, 4095},
+	{1, 2, 3, 5, 9, 16, 28, 48, 84, 147, 256, 446, 776, 1351, 2352, 4095},
+	{1, 2, 3, 5, 9, 16, 28, 48, 84, 147, 256, 446, 776, 1351, 2352, 4095},
+	{1, 2, 3, 5, 9, 16, 28, 48, 84, 147, 256, 446, 776, 1351, 2352, 4095},
+};
+
+static u16 sde_vdc_lbda_bf_lut[VDC_PROFILE_MAX][VDC_LBDA_BF_LUT_SIZE] = {
+	{1, 1, 2, 3, 4, 6, 9, 13, 19, 28, 40, 58, 84, 122, 176, 255},
+	{1, 1, 2, 3, 4, 6, 9, 13, 19, 28, 40, 58, 84, 122, 176, 255},
+	{1, 1, 2, 3, 4, 6, 9, 13, 19, 28, 40, 58, 84, 122, 176, 255},
+	{1, 1, 2, 3, 4, 6, 9, 13, 19, 28, 40, 58, 84, 122, 176, 255},
+	{4, 5, 7, 9, 12, 16, 21, 28, 37, 48, 64, 84, 111, 146, 193, 255},
+	{1, 1, 1, 2, 3, 4, 6, 9, 14, 21, 32, 48, 73, 111, 168, 255},
+	{1, 1, 1, 1, 2, 3, 4, 6, 10, 16, 25, 40, 64, 101, 161, 255},
+	{1, 1, 1, 1, 2, 3, 4, 6, 10, 16, 25, 40, 64, 101, 161, 255},
+	{1, 1, 1, 1, 2, 3, 4, 6, 10, 16, 25, 40, 64, 101, 161, 255},
+	{1, 1, 1, 1, 2, 3, 4, 6, 10, 16, 25, 40, 64, 101, 161, 255},
+	{1, 1, 1, 1, 2, 3, 4, 6, 10, 16, 25, 40, 64, 101, 161, 255},
+	{1, 1, 1, 1, 2, 3, 4, 6, 10, 16, 25, 40, 64, 101, 161, 255},
+	{1, 1, 1, 1, 2, 3, 4, 6, 10, 16, 25, 40, 64, 101, 161, 255},
+};
+
+static int _get_vdc_profile_index(struct msm_display_vdc_info *vdc_info)
+{
+	int bpp, bpc;
+	int rc = -EINVAL;
+
+	bpp = VDC_BPP(vdc_info->bits_per_pixel);
+	bpc = vdc_info->bits_per_component;
+
+	if (vdc_info->chroma_format == MSM_CHROMA_444) {
+		if ((bpc == 8) && (bpp == 8))
+			return VDC_RGB_444_8BPC_8BPP;
+		else if ((bpc == 8) && (bpp == 6))
+			return VDC_RGB_444_8BPC_6BPP;
+		else if ((bpc == 10) && (bpp == 10))
+			return VDC_RGB_444_10BPC_10BPP;
+		else if ((bpc == 10) && (bpp == 10))
+			return VDC_RGB_444_10BPC_10BPP;
+		else if ((bpc == 10) && (bpp == 8))
+			return VDC_RGB_444_108BPC_8BPP;
+		else if ((bpc == 10) && (bpp == 7))
+			return VDC_RGB_444_10BPC_7BPP;
+		else if ((bpc == 10) && (bpp == 6))
+			return VDC_RGB_444_10BPC_6BPP;
+	} else if (vdc_info->chroma_format == MSM_CHROMA_422) {
+		if ((bpc == 8) && (bpp == 6))
+			return VDC_YUV_422_8BPC_6BPP;
+		else if ((bpc == 8) && (bpp == 5))
+			return VDC_YUV_422_8BPC_5BPP;
+		else if ((bpc == 10) && (bpp == 8))
+			return VDC_YUV_422_10BPC_8BPP;
+		else if ((bpc == 10) && (bpp == 6))
+			return VDC_YUV_422_10BPC_6BPP;
+		else if ((bpc == 10) && (bpp == 5))
+			return VDC_YUV_422_10BPC_5PP;
+	}
+
+	pr_err("unsupported bpc:%d, bpp:%d\n", bpc, bpp);
+
+	return rc;
+}
+
+static void sde_vdc_dump_lut_params(struct msm_display_vdc_info *vdc_info)
+{
+	int i;
+
+	pr_debug("vdc_info->mppf_bpc_r_y = %d\n", vdc_info->mppf_bpc_r_y);
+	pr_debug("vdc_info->mppf_bpc_g_cb = %d\n", vdc_info->mppf_bpc_g_cb);
+	pr_debug("vdc_info->mppf_bpc_b_cr = %d\n", vdc_info->mppf_bpc_b_cr);
+	pr_debug("vdc_info->mppf_bpc_y = %d\n", vdc_info->mppf_bpc_y);
+	pr_debug("vdc_info->mppf_bpc_co = %d\n", vdc_info->mppf_bpc_co);
+	pr_debug("vdc_info->mppf_bpc_cg = %d\n", vdc_info->mppf_bpc_cg);
+	pr_debug("vdc_info->flatqp_vf_fbls = %d\n", vdc_info->flatqp_vf_fbls);
+	pr_debug("vdc_info->flatqp_vf_nbls = %d\n", vdc_info->flatqp_vf_nbls);
+	pr_debug("vdc_info->flatqp_sw_fbls = %d\n", vdc_info->flatqp_sw_fbls);
+	pr_debug("vdc_info->flatqp_sw_nbls = %d\n", vdc_info->flatqp_sw_nbls);
+
+	for (i = 0; i < VDC_FLAT_QP_LUT_SIZE; i++)
+		pr_debug("vdc_info->flatness_qp_lut[%d] = %d\n",
+				 i, vdc_info->flatness_qp_lut[i]);
+
+	for (i = 0; i < VDC_MAX_QP_LUT_SIZE; i++)
+		pr_debug("vdc_info->max_qp_lut[%d] = %d\n",
+				 i, vdc_info->max_qp_lut[i]);
+
+	for (i = 0; i < VDC_TAR_DEL_LUT_SIZE; i++)
+		pr_debug("vdc_info->tar_del_lut[%d] = %d\n",
+				 i, vdc_info->tar_del_lut[i]);
+
+	for (i = 0; i < VDC_LBDA_BRATE_LUT_SIZE; i++)
+		pr_debug("vdc_info->lbda_brate_lut[%d] = %d\n",
+				 i, vdc_info->lbda_brate_lut[i]);
+
+	for (i = 0; i < VDC_LBDA_BF_LUT_SIZE; i++)
+		pr_debug("vdc_info->lbda_bf_lut[%d] = %d\n",
+				 i, vdc_info->lbda_bf_lut[i]);
+
+	for (i = 0; i < VDC_LBDA_BRATE_REG_SIZE; i++)
+		pr_debug("vdc_info->lbda_brate_lut_interp[%d] = %d\n",
+				 i, vdc_info->lbda_brate_lut_interp[i]);
+
+	for (i = 0; i < VDC_LBDA_BRATE_REG_SIZE; i++)
+		pr_debug("vdc_info->lbda_bf_lut_interp[%d] = %d\n",
+				 i, vdc_info->lbda_bf_lut_interp[i]);
+}
+
+static void sde_vdc_dump_core_params(struct msm_display_vdc_info *vdc_info)
+{
+	pr_debug("vdc_info->num_of_active_ss = %d\n",
+			 vdc_info->num_of_active_ss);
+	pr_debug("vdc_info->chunk_size = %d\n",
+			 vdc_info->chunk_size);
+	pr_debug("vdc_info->chunk_size_bits = %d\n",
+			 vdc_info->chunk_size_bits);
+	pr_debug("vdc_info->slice_num_px = %d\n",
+			 vdc_info->slice_num_px);
+	pr_debug("vdc_info->avg_block_bits = %d\n",
+			 vdc_info->avg_block_bits);
+	pr_debug("vdc_info->per_chunk_pad_bits = %d\n",
+			 vdc_info->per_chunk_pad_bits);
+	pr_debug("vdc_info->tot_pad_bits = %d\n",
+			 vdc_info->tot_pad_bits);
+	pr_debug("vdc_info->rc_stuffing_bits = %d\n",
+			 vdc_info->rc_stuffing_bits);
+	pr_debug("vdc_info->slice_num_bits = %d\n",
+			vdc_info->slice_num_bits);
+	pr_debug("vdc_info->chunk_adj_bits = %d\n",
+			 vdc_info->chunk_adj_bits);
+	pr_debug("vdc_info->rc_buf_init_size_temp = %d\n",
+			 vdc_info->rc_buf_init_size_temp);
+	pr_debug("vdc_info->init_tx_delay_temp = %d\n",
+			 vdc_info->init_tx_delay_temp);
+	pr_debug("vdc_info->rc_buffer_init_size = %d\n",
+			 vdc_info->rc_buffer_init_size);
+	pr_debug("vdc_info->rc_init_tx_delay = %d\n",
+			 vdc_info->rc_init_tx_delay);
+	pr_debug("vdc_info->rc_init_tx_delay_px_times = %d\n",
+			 vdc_info->rc_init_tx_delay_px_times);
+	pr_debug("vdc_info->rc_buffer_max_size = %d\n",
+			 vdc_info->rc_buffer_max_size);
+	pr_debug("vdc_info->rc_tar_rate_scale_temp_a = %d\n",
+			 vdc_info->rc_tar_rate_scale_temp_a);
+	pr_debug("vdc_info->rc_tar_rate_scale_temp_b = %d\n",
+			 vdc_info->rc_tar_rate_scale_temp_b);
+	pr_debug("vdc_info->rc_tar_rate_scale = %d\n",
+			 vdc_info->rc_tar_rate_scale);
+	pr_debug("vdc_info->rc_target_rate_threshold = %d\n",
+			 vdc_info->rc_target_rate_threshold);
+	pr_debug("vdc_info->chroma_samples = %d\n",
+			 vdc_info->chroma_samples);
+	pr_debug("vdc_info->block_max_bits = %d\n",
+			 vdc_info->block_max_bits);
+	pr_debug("vdc_info->rc_lambda_bitrate_scale = %d\n",
+			 vdc_info->rc_lambda_bitrate_scale);
+	pr_debug("vdc_info->rc_buffer_fullness_scale = %d\n",
+			 vdc_info->rc_buffer_fullness_scale);
+	pr_debug("vdc_info->rc_fullness_offset_thresh = %d\n",
+			 vdc_info->rc_fullness_offset_thresh);
+	pr_debug("vdc_info->ramp_blocks = %d\n",
+			 vdc_info->ramp_blocks);
+	pr_debug("vdc_info->ramp_bits = %d\n",
+			 vdc_info->ramp_bits);
+	pr_debug("vdc_info->rc_fullness_offset_slope = %d\n",
+			 vdc_info->rc_fullness_offset_slope);
+	pr_debug("vdc_info->num_extra_mux_bits_init = %d\n",
+			 vdc_info->num_extra_mux_bits_init);
+	pr_debug("vdc_info->extra_crop_bits = %d\n",
+			 vdc_info->extra_crop_bits);
+	pr_debug("vdc_info->num_extra_mux_bits = %d\n",
+			 vdc_info->num_extra_mux_bits);
+	pr_debug("vdc_info->mppf_bits_comp_0 = %d\n",
+			 vdc_info->mppf_bits_comp_0);
+	pr_debug("vdc_info->mppf_bits_comp_1 = %d\n",
+			 vdc_info->mppf_bits_comp_1);
+	pr_debug("vdc_info->mppf_bits_comp_2 = %d\n",
+			 vdc_info->mppf_bits_comp_2);
+	pr_debug("vdc_info->min_block_bits = %d\n",
+			vdc_info->min_block_bits);
+}
+
+static void sde_vdc_dump_ext_core_params(struct msm_display_vdc_info *vdc_info)
+{
+	pr_debug("vdc_info->input_ssm_out_latency = %d\n",
+			 vdc_info->input_ssm_out_latency);
+	pr_debug("vdc_info->input_ssm_out_latency_min = %d\n",
+			 vdc_info->input_ssm_out_latency_min);
+	pr_debug("vdc_info->obuf_latency = %d\n",
+			 vdc_info->obuf_latency);
+	pr_debug("vdc_info->base_hs_latency = %d\n",
+			 vdc_info->base_hs_latency);
+	pr_debug("vdc_info->base_hs_latency_pixels = %d\n",
+			 vdc_info->base_hs_latency_pixels);
+	pr_debug("vdc_info->base_hs_latency_pixels_min = %d\n",
+			 vdc_info->base_hs_latency_pixels_min);
+	pr_debug("vdc_info->base_initial_lines = %d\n",
+			 vdc_info->base_initial_lines);
+	pr_debug("vdc_info->base_top_up = %d\n",
+			 vdc_info->base_top_up);
+	pr_debug("vdc_info->output_rate = %d\n",
+			 vdc_info->output_rate);
+	pr_debug("vdc_info->output_rate_ratio_100 = %d\n",
+			 vdc_info->output_rate_ratio_100);
+	pr_debug("vdc_info->burst_accum_pixels = %d\n",
+			 vdc_info->burst_accum_pixels);
+	pr_debug("vdc_info->ss_initial_lines = %d\n",
+			 vdc_info->ss_initial_lines);
+	pr_debug("vdc_info->burst_initial_lines = %d\n",
+			 vdc_info->burst_initial_lines);
+	pr_debug("vdc_info->initial_lines = %d\n",
+			 vdc_info->initial_lines);
+	pr_debug("vdc_info->obuf_base = %d\n",
+			 vdc_info->obuf_base);
+	pr_debug("vdc_info->obuf_extra_ss0 = %d\n",
+			 vdc_info->obuf_extra_ss0);
+	pr_debug("vdc_info->obuf_extra_ss1 = %d\n",
+			 vdc_info->obuf_extra_ss1);
+	pr_debug("vdc_info->obuf_extra_burst = %d\n",
+			 vdc_info->obuf_extra_burst);
+	pr_debug("vdc_info->obuf_ss0 = %d\n",
+			 vdc_info->obuf_ss0);
+	pr_debug("vdc_info->obuf_ss1 = %d\n",
+			 vdc_info->obuf_ss1);
+	pr_debug("vdc_info->obuf_margin_words = %d\n",
+			 vdc_info->obuf_margin_words);
+
+	pr_debug("vdc_info->ob0_max_addr = %d\n",
+			 vdc_info->ob0_max_addr);
+	pr_debug("vdc_info->ob1_max_addr = %d\n",
+			 vdc_info->ob1_max_addr);
+
+	pr_debug("vdc_info->slice_width_orig = %d\n",
+			 vdc_info->slice_width_orig);
+	pr_debug("vdc_info->r2b0_max_addr = %d\n",
+			 vdc_info->r2b0_max_addr);
+	pr_debug("vdc_info->r2b1_max_addr = %d\n",
+			 vdc_info->r2b1_max_addr);
+}
+
+static int sde_vdc_populate_lut_params(struct msm_display_vdc_info *vdc_info)
+{
+	int bpp, bpc;
+	int i, profile_idx;
+	int x_0, x_1, lambda, idx_mod;
+	int x_0_idx, x_1_idx;
+	int idx;
+
+	bpp = VDC_BPP(vdc_info->bits_per_pixel);
+	bpc = vdc_info->bits_per_component;
+
+	profile_idx = _get_vdc_profile_index(vdc_info);
+	if (profile_idx == -EINVAL) {
+		pr_err("no matching profile found\n");
+		return profile_idx;
+	}
+
+	vdc_info->mppf_bpc_r_y = sde_vdc_mppf_bpc_r_y[profile_idx];
+	vdc_info->mppf_bpc_g_cb = sde_vdc_mppf_bpc_g_cb[profile_idx];
+	vdc_info->mppf_bpc_b_cr = sde_vdc_mppf_bpc_b_cr[profile_idx];
+	vdc_info->mppf_bpc_y = sde_vdc_mppf_bpc_y[profile_idx];
+	vdc_info->mppf_bpc_co = sde_vdc_mppf_bpc_co[profile_idx];
+	vdc_info->mppf_bpc_cg = sde_vdc_mppf_bpc_cg[profile_idx];
+	vdc_info->flatqp_vf_fbls = sde_vdc_flat_qp_vf_fbls[profile_idx];
+	vdc_info->flatqp_vf_nbls = sde_vdc_flat_qp_vf_nfbls[profile_idx];
+	vdc_info->flatqp_sw_fbls = sde_vdc_flat_qp_sf_fbls[profile_idx];
+	vdc_info->flatqp_sw_nbls = sde_vdc_flat_qp_sf_nbls[profile_idx];
+
+	idx = profile_idx;
+
+	for (i = 0; i < VDC_FLAT_QP_LUT_SIZE; i++)
+		vdc_info->flatness_qp_lut[i] = sde_vdc_flat_qp_lut[idx][i];
+
+	for (i = 0; i < VDC_MAX_QP_LUT_SIZE; i++)
+		vdc_info->max_qp_lut[i] = sde_vdc_max_qp_lut[idx][i];
+
+	for (i = 0; i < VDC_TAR_DEL_LUT_SIZE; i++)
+		vdc_info->tar_del_lut[i] = sde_vdc_tar_del_lut[idx][i];
+
+	for (i = 0; i < VDC_LBDA_BRATE_LUT_SIZE; i++)
+		vdc_info->lbda_brate_lut[i] = sde_vdc_lbda_brate_lut[idx][i];
+
+	for (i = 0; i < VDC_LBDA_BF_LUT_SIZE; i++)
+		vdc_info->lbda_bf_lut[i] = sde_vdc_lbda_bf_lut[idx][i];
+
+	for (i = 0; i < VDC_LBDA_BRATE_REG_SIZE; i++) {
+		idx_mod = i & 0x03;
+
+		x_0_idx = i >> 2;
+		if (x_0_idx > VDC_LBDA_BRATE_LUT_SIZE - 1)
+			x_0_idx = VDC_LBDA_BRATE_LUT_SIZE - 1;
+
+		x_1_idx = (i >> 2) + 1;
+		if (x_1_idx > VDC_LBDA_BRATE_LUT_SIZE - 1)
+			x_1_idx = VDC_LBDA_BRATE_LUT_SIZE - 1;
+
+		x_0 = vdc_info->lbda_brate_lut[x_0_idx];
+		x_1 = vdc_info->lbda_brate_lut[x_1_idx];
+
+		lambda = (((4 - idx_mod) * x_0 + idx_mod * x_1 + 2) >> 2);
+		vdc_info->lbda_brate_lut_interp[i] = lambda;
+
+		x_0 = vdc_info->lbda_bf_lut[x_0_idx];
+		x_1 = vdc_info->lbda_bf_lut[x_1_idx];
+
+		lambda = (((4 - idx_mod) * x_0 + idx_mod * x_1 + 2) >> 2);
+		vdc_info->lbda_bf_lut_interp[i] = lambda;
+	}
+
+	sde_vdc_dump_lut_params(vdc_info);
+	return 0;
+}
+
+static int sde_vdc_populate_core_params(struct msm_display_vdc_info *vdc_info,
+	int intf_width)
+{
+	u16 bpp;
+	u16 bpc;
+	u32 bpp_codec;
+	u64 temp, diff;
+
+	if (!vdc_info)
+		return -EINVAL;
+
+	if (!vdc_info->slice_width ||
+			!vdc_info->slice_height ||
+			intf_width < vdc_info->slice_width) {
+		pr_err("invalid input, intf_width=%d slice_width=%d\n",
+			intf_width, vdc_info->slice_width);
+		return -EINVAL;
+	}
+
+	bpp = VDC_BPP(vdc_info->bits_per_pixel);
+	bpp_codec = 16 * bpp;
+	bpc = vdc_info->bits_per_component;
+
+	vdc_info->num_of_active_ss = intf_width / vdc_info->slice_width;
+
+	temp = vdc_info->slice_width * bpp_codec;
+	temp += 15;
+	temp >>= 4;
+	temp += 7;
+	temp >>= 3;
+	vdc_info->chunk_size = temp;
+	vdc_info->chunk_size_bits = temp * 8;
+	vdc_info->slice_num_px = vdc_info->slice_width *
+		vdc_info->slice_height;
+
+	/* slice_num_px should be atleast 4096 */
+	if (vdc_info->slice_num_px < 4096) {
+		pr_err("insufficient slice_num_px:%d\n",
+			vdc_info->slice_num_px);
+		return -EINVAL;
+	}
+
+	vdc_info->avg_block_bits = bpp_codec;
+
+	temp = (16 * vdc_info->chunk_size);
+	temp -= (vdc_info->slice_width * 2 * bpp_codec) >> 4;
+	vdc_info->per_chunk_pad_bits = temp;
+
+	vdc_info->tot_pad_bits = (vdc_info->avg_block_bits +
+		vdc_info->per_chunk_pad_bits - 8);
+
+	vdc_info->rc_stuffing_bits = ((vdc_info->tot_pad_bits + 8) / 9);
+	vdc_info->slice_num_bits = (8 * vdc_info->chunk_size *
+		vdc_info->slice_height);
+
+	temp = (16 * vdc_info->chunk_size);
+	vdc_info->chunk_adj_bits = temp -
+		((2 * vdc_info->slice_width * bpp_codec) >> 4);
+
+	if (vdc_info->slice_width <= 720)
+		vdc_info->rc_buf_init_size_temp = 4096;
+	else if (vdc_info->slice_width <= 2048)
+		vdc_info->rc_buf_init_size_temp = 8192;
+	else
+		vdc_info->rc_buf_init_size_temp = 10752;
+
+	vdc_info->init_tx_delay_temp = (vdc_info->rc_buf_init_size_temp /
+		vdc_info->avg_block_bits);
+
+	temp = (vdc_info->init_tx_delay_temp * 16 * bpp_codec);
+	vdc_info->rc_buffer_init_size = temp >> 4;
+
+	vdc_info->rc_init_tx_delay = vdc_info->rc_buffer_init_size /
+		vdc_info->avg_block_bits;
+
+	vdc_info->rc_init_tx_delay_px_times = vdc_info->rc_init_tx_delay * 16;
+
+	temp = (2 * vdc_info->rc_buffer_init_size);
+	temp = temp + (2 * vdc_info->slice_width *
+		RC_TARGET_RATE_EXTRA_FTBLS);
+	vdc_info->rc_buffer_max_size = temp;
+
+	vdc_info->rc_tar_rate_scale_temp_a = ilog2(vdc_info->slice_num_px) + 1;
+	vdc_info->rc_tar_rate_scale_temp_b = ilog2(vdc_info->slice_num_px);
+
+	vdc_info->rc_tar_rate_scale = 1 + vdc_info->rc_tar_rate_scale_temp_a;
+
+	vdc_info->rc_target_rate_threshold = (1 <<
+		(vdc_info->rc_tar_rate_scale - 1));
+
+	if (vdc_info->chroma_format == MSM_CHROMA_444)
+		vdc_info->chroma_samples = 16;
+	else if (vdc_info->chroma_format == MSM_CHROMA_422)
+		vdc_info->chroma_samples = 8;
+	else
+		vdc_info->chroma_samples = 4;
+
+	temp = (2 * vdc_info->chroma_samples) + 16;
+	vdc_info->block_max_bits = (temp * bpc) + 7;
+
+	temp = (1 << 12);
+	temp += (vdc_info->block_max_bits >> 1);
+	temp /= vdc_info->block_max_bits;
+	vdc_info->rc_lambda_bitrate_scale = temp;
+
+	temp = (1 << 20);
+	temp /= vdc_info->rc_buffer_max_size;
+	vdc_info->rc_buffer_fullness_scale = temp;
+
+	vdc_info->rc_fullness_offset_thresh = (vdc_info->slice_height / 6);
+
+	temp = (vdc_info->slice_width >> 3);
+	temp = temp * vdc_info->rc_fullness_offset_thresh;
+	vdc_info->ramp_blocks = temp;
+
+	temp = (vdc_info->rc_buffer_max_size - vdc_info->rc_buffer_init_size);
+	temp = temp << 16;
+	vdc_info->ramp_bits = temp;
+
+	temp = vdc_info->ramp_bits / vdc_info->ramp_blocks;
+	vdc_info->rc_fullness_offset_slope = temp;
+
+	temp = (2 * SSM_MAX_SE_SIZE) - 2;
+	vdc_info->num_extra_mux_bits_init = temp * 4;
+
+	temp = vdc_info->slice_num_bits - vdc_info->num_extra_mux_bits_init;
+	if ((temp % SSM_MAX_SE_SIZE) == 0) {
+		vdc_info->extra_crop_bits = 0;
+	} else {
+		diff = vdc_info->slice_num_bits -
+			vdc_info->num_extra_mux_bits_init;
+		vdc_info->extra_crop_bits = (SSM_MAX_SE_SIZE -
+			(diff % SSM_MAX_SE_SIZE));
+	}
+
+	vdc_info->num_extra_mux_bits = vdc_info->num_extra_mux_bits_init -
+		vdc_info->extra_crop_bits;
+
+	vdc_info->mppf_bits_comp_0 = 16 * vdc_info->mppf_bpc_r_y;
+	vdc_info->mppf_bits_comp_1 = vdc_info->chroma_samples *
+		vdc_info->mppf_bpc_g_cb;
+	vdc_info->mppf_bits_comp_2 = vdc_info->chroma_samples *
+		vdc_info->mppf_bpc_b_cr;
+
+	vdc_info->min_block_bits = 8 + vdc_info->mppf_bits_comp_0 +
+		vdc_info->mppf_bits_comp_1 + vdc_info->mppf_bits_comp_2;
+
+	sde_vdc_dump_core_params(vdc_info);
+	return 0;
+}
+
+static void sde_vdc_intf_prog_params(struct msm_display_vdc_info *vdc_info,
+	int intf_width)
+{
+	int slice_per_pkt, slice_per_intf;
+	int bytes_in_slice, total_bytes_per_intf;
+	u16 bpp;
+
+	slice_per_pkt = vdc_info->slice_per_pkt;
+	// is mode->timing.h_active always intf_width?
+	slice_per_intf = DIV_ROUND_UP(intf_width,
+			vdc_info->slice_width);
+
+	/*
+	 * If slice_per_pkt is greater than slice_per_intf then default to 1.
+	 * This can happen during partial update.
+	 */
+	if (slice_per_pkt > slice_per_intf)
+		slice_per_pkt = 1;
+
+	bpp = VDC_BPP(vdc_info->bits_per_pixel);
+	bytes_in_slice = DIV_ROUND_UP(vdc_info->slice_width *
+			bpp, 8);
+	total_bytes_per_intf = bytes_in_slice * slice_per_intf;
+
+	vdc_info->eol_byte_num = total_bytes_per_intf % 3;
+	vdc_info->pclk_per_line =  DIV_ROUND_UP(total_bytes_per_intf, 3);
+	vdc_info->bytes_in_slice = bytes_in_slice;
+	vdc_info->bytes_per_pkt = bytes_in_slice * slice_per_pkt;
+	vdc_info->pkt_per_line = slice_per_intf / slice_per_pkt;
+
+	pr_debug("eol_byte_num = %d pclk_per_line = %d\n",
+			 vdc_info->eol_byte_num, vdc_info->pclk_per_line);
+	pr_debug("bytes_in_slice = %d bytes_per_pkt = %d\n",
+			 vdc_info->bytes_in_slice, vdc_info->bytes_per_pkt);
+	pr_debug("pkt_per_line = %d\n", vdc_info->pkt_per_line);
+}
+
+static void sde_vdc_ext_core_params(struct msm_display_vdc_info *vdc_info,
+	int traffic_mode)
+{
+	int temp;
+	int bpp;
+	int rc_init_tx_delay_px_times;
+
+	bpp = VDC_BPP(vdc_info->bits_per_pixel);
+
+	vdc_info->min_ssm_delay = SSM_MAX_SE_SIZE;
+	vdc_info->max_ssm_delay = SSM_MAX_SE_SIZE + 1;
+
+	vdc_info->input_ssm_out_latency = MAX_PIPELINE_LATENCY +
+		(8 * vdc_info->max_ssm_delay);
+
+	vdc_info->input_ssm_out_latency_min = (8 * vdc_info->min_ssm_delay);
+
+	temp = (7 + OUT_BUF_UF_MARGIN);
+	temp *= OB_DATA_WIDTH;
+	temp += (SSM_MAX_SE_SIZE / 2);
+
+	temp /= (bpp * 2);
+	temp += 1;
+
+	vdc_info->obuf_latency = temp;
+
+	temp = vdc_info->input_ssm_out_latency +
+		vdc_info->obuf_latency;
+	rc_init_tx_delay_px_times = vdc_info->rc_init_tx_delay_px_times;
+	rc_init_tx_delay_px_times /= 2;
+
+	vdc_info->base_hs_latency = rc_init_tx_delay_px_times + temp;
+
+	temp = vdc_info->rc_init_tx_delay_px_times;
+	temp /= 2;
+	temp += vdc_info->input_ssm_out_latency_min;
+	vdc_info->base_hs_latency_min = temp;
+	vdc_info->base_hs_latency_pixels = (vdc_info->base_hs_latency * 2);
+
+	vdc_info->base_hs_latency_pixels_min = (2 *
+			vdc_info->base_hs_latency_min);
+
+	temp = DIV_ROUND_UP(vdc_info->base_hs_latency_pixels,
+		vdc_info->slice_width);
+
+	vdc_info->base_initial_lines = temp;
+
+	temp = vdc_info->base_initial_lines * vdc_info->slice_width;
+	temp -= vdc_info->base_hs_latency_pixels;
+	vdc_info->base_top_up =  temp;
+
+	if (traffic_mode == VDC_TRAFFIC_BURST_MODE)
+		vdc_info->output_rate = OUTPUT_DATA_WIDTH;
+	else
+		vdc_info->output_rate = bpp * 2;
+
+	temp = (bpp * 2 * 100);
+	temp /= vdc_info->output_rate;
+
+	vdc_info->output_rate_ratio_100 = temp;
+
+	if (traffic_mode == VDC_TRAFFIC_BURST_MODE) {
+		temp = vdc_info->output_rate_ratio_100 *
+			vdc_info->slice_width;
+		temp *= vdc_info->num_of_active_ss;
+		temp /= 100;
+		vdc_info->burst_accum_pixels = temp;
+	} else {
+		vdc_info->burst_accum_pixels = 0;
+	}
+
+	if (vdc_info->num_of_active_ss > 1)
+		vdc_info->ss_initial_lines = 1;
+	else
+		vdc_info->ss_initial_lines = 0;
+
+	if (traffic_mode == VDC_TRAFFIC_BURST_MODE) {
+		if ((vdc_info->burst_accum_pixels +
+			 vdc_info->base_top_up) < vdc_info->slice_width)
+			vdc_info->burst_initial_lines = 1;
+		else
+			vdc_info->burst_initial_lines = 0;
+	} else {
+		vdc_info->burst_initial_lines = 0;
+	}
+
+	vdc_info->initial_lines = 1 + vdc_info->base_initial_lines +
+		vdc_info->ss_initial_lines +
+		vdc_info->burst_initial_lines;
+
+	temp = (vdc_info->base_initial_lines * vdc_info->slice_width);
+	temp -= vdc_info->base_hs_latency_pixels_min;
+	temp *= bpp;
+	vdc_info->obuf_base = temp;
+
+	if (vdc_info->num_of_active_ss > 1) {
+		vdc_info->obuf_extra_ss0 = 2 * vdc_info->chunk_size_bits;
+		vdc_info->obuf_extra_ss1 = vdc_info->chunk_size_bits;
+	} else {
+		vdc_info->obuf_extra_ss0 = 0;
+		vdc_info->obuf_extra_ss1 = 0;
+	}
+
+	vdc_info->obuf_extra_burst = vdc_info->burst_initial_lines *
+		vdc_info->chunk_size_bits;
+
+	vdc_info->obuf_ss0 = vdc_info->rc_buffer_max_size +
+		vdc_info->obuf_base + vdc_info->obuf_extra_ss0 +
+			vdc_info->obuf_extra_burst;
+
+	vdc_info->obuf_ss1 = vdc_info->rc_buffer_max_size +
+		vdc_info->obuf_base + vdc_info->obuf_extra_ss1 +
+			vdc_info->obuf_extra_burst;
+
+	temp = OUT_BUF_OF_MARGIN_TC_10 *
+		vdc_info->chunk_size_bits;
+	temp /= 10;
+	temp /= SSM_MAX_SE_SIZE;
+	vdc_info->obuf_margin_words = max(OUT_BUF_OF_MARGIN_OB,
+		temp);
+
+	if (vdc_info->num_of_active_ss == 2) {
+		vdc_info->ob0_max_addr = OB0_RAM_DEPTH - 1;
+		vdc_info->ob1_max_addr = OB1_RAM_DEPTH - 1;
+	} else {
+		vdc_info->ob0_max_addr = (2 * OB1_RAM_DEPTH) - 1;
+		vdc_info->ob1_max_addr = 0;
+	}
+
+	if (vdc_info->split_panel_enable) {
+		temp = vdc_info->frame_width / vdc_info->num_of_active_ss;
+		temp /= NUM_ACTIVE_HS;
+	} else {
+		temp = vdc_info->frame_width / vdc_info->num_of_active_ss;
+	}
+
+	vdc_info->slice_width_orig = temp;
+
+	vdc_info->r2b0_max_addr = (MAX_PIXELS_PER_HS_LINE / 4);
+	vdc_info->r2b0_max_addr += 3;
+
+	vdc_info->r2b1_max_addr = (MAX_PIXELS_PER_HS_LINE / 4);
+	vdc_info->r2b1_max_addr /= 2;
+	vdc_info->r2b1_max_addr += 3;
+
+	sde_vdc_dump_ext_core_params(vdc_info);
+}
+
+int sde_vdc_populate_config(struct msm_display_vdc_info *vdc_info,
+	int intf_width, int traffic_mode)
+{
+	int ret = 0;
+
+	ret = sde_vdc_populate_core_params(vdc_info, intf_width);
+	if (ret) {
+		pr_err("failed to populate vdc core params %d\n", ret);
+		return ret;
+	}
+
+	ret = sde_vdc_populate_lut_params(vdc_info);
+	if (ret) {
+		pr_err("failed to populate lut params %d\n", ret);
+		return ret;
+	}
+
+	sde_vdc_intf_prog_params(vdc_info, intf_width);
+
+	sde_vdc_ext_core_params(vdc_info, traffic_mode);
+
+	return ret;
+}

+ 49 - 0
msm/sde_vdc_helper.h

@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef __SDE_VDC_HELPER_H__
+#define __SDE_VDC_HELPER_H__
+
+#include "msm_drv.h"
+
+#define VDC_BPP(bits_per_pixel) (bits_per_pixel >> 4)
+
+#define VDC_NUM_BUF_RANGES (DSC_NUM_BUF_RANGES - 1)
+
+#define VDC_FLAT_QP_LUT_SIZE 8
+#define VDC_MAX_QP_LUT_SIZE 8
+#define VDC_TAR_DEL_LUT_SIZE 16
+#define VDC_LBDA_BRATE_LUT_SIZE 16
+#define VDC_LBDA_BF_LUT_SIZE 16
+#define VDC_LBDA_BRATE_REG_SIZE 64
+
+#define VDC_VIDEO_MODE 0
+#define VDC_CMD_MODE 1
+
+#define VDC_TRAFFIC_SYNC_PULSES 0
+#define VDC_TRAFFIC_SYNC_START_EVENTS 1
+#define VDC_TRAFFIC_BURST_MODE 2
+
+#define MAX_PIPELINE_LATENCY 68
+#define OB_DATA_WIDTH 128
+#define OUT_BUF_FULL_THRESH 2
+#define OUT_BUF_UF_MARGIN 3
+#define OUT_BUF_OF_MARGIN_TC_10 5
+#define OUT_BUF_OF_MARGIN_OB 3
+#define OUTPUT_DATA_WIDTH 64
+#define OB0_RAM_DEPTH 912
+#define OB1_RAM_DEPTH 736
+
+#define SSM_MAX_SE_SIZE 128
+#define RC_TARGET_RATE_EXTRA_FTBLS 2
+
+#define NUM_ACTIVE_HS 1
+#define MAX_PIXELS_PER_HS_LINE 5120
+
+int sde_vdc_populate_config(struct msm_display_vdc_info *vdc_info,
+	int intf_width, int traffic_mode);
+
+#endif /* __SDE_VDC_HELPER_H__ */
+