diff --git a/msm/Makefile b/msm/Makefile index 502575302f..dd8f770268 100644 --- a/msm/Makefile +++ b/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 \ diff --git a/msm/dsi/dsi_panel.c b/msm/dsi/dsi_panel.c index 93045e5c8c..09f30b2dec 100644 --- a/msm/dsi/dsi_panel.c +++ b/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; diff --git a/msm/msm_drv.h b/msm/msm_drv.h index 14ec198710..02d95d872d 100644 --- a/msm/msm_drv.h +++ b/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; }; /** diff --git a/msm/sde_vdc_helper.c b/msm/sde_vdc_helper.c new file mode 100644 index 0000000000..9272289883 --- /dev/null +++ b/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; +} diff --git a/msm/sde_vdc_helper.h b/msm/sde_vdc_helper.h new file mode 100644 index 0000000000..d72716d1af --- /dev/null +++ b/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__ */ +