// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__ #include "msm_drv.h" #include "sde_dsc_helper.h" #include "sde_kms.h" #define SDE_DSC_PPS_SIZE 128 enum sde_dsc_ratio_type { DSC_V11_8BPC_8BPP, DSC_V11_10BPC_8BPP, DSC_V11_10BPC_10BPP, DSC_V11_SCR1_8BPC_8BPP, DSC_V11_SCR1_10BPC_8BPP, DSC_V11_SCR1_10BPC_10BPP, DSC_V12_444_8BPC_8BPP = DSC_V11_SCR1_8BPC_8BPP, DSC_V12_444_10BPC_8BPP = DSC_V11_SCR1_10BPC_8BPP, DSC_V12_444_10BPC_10BPP = DSC_V11_SCR1_10BPC_10BPP, DSC_V12_422_8BPC_7BPP, DSC_V12_422_8BPC_8BPP, DSC_V12_422_10BPC_7BPP, DSC_V12_422_10BPC_8BPP, DSC_V12_422_10BPC_10BPP, DSC_V12_420_8BPC_6BPP, DSC_V12_420_10BPC_6BPP, DSC_V12_420_10BPC_7_5BPP, DSC_RATIO_TYPE_MAX }; static u16 sde_dsc_rc_buf_thresh[DSC_NUM_BUF_RANGES - 1] = {0x0e, 0x1c, 0x2a, 0x38, 0x46, 0x54, 0x62, 0x69, 0x70, 0x77, 0x79, 0x7b, 0x7d, 0x7e}; /* * Rate control - Min QP values for each ratio type in sde_dsc_ratio_type */ static char sde_dsc_rc_range_min_qp[DSC_RATIO_TYPE_MAX][DSC_NUM_BUF_RANGES] = { /* DSC v1.1 */ {0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 13}, {0, 4, 5, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 11, 17}, {0, 4, 5, 6, 7, 7, 7, 7, 7, 7, 9, 9, 9, 11, 15}, /* DSC v1.1 SCR and DSC v1.2 RGB 444 */ {0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 9, 12}, {0, 4, 5, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 13, 16}, {0, 4, 5, 6, 7, 7, 7, 7, 7, 7, 9, 9, 9, 11, 15}, /* DSC v1.2 YUV422 */ {0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 11}, {0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 10}, {0, 4, 5, 6, 7, 7, 7, 7, 7, 7, 9, 9, 9, 11, 15}, {0, 2, 3, 4, 6, 7, 7, 7, 7, 7, 9, 9, 9, 11, 14}, {0, 2, 3, 4, 5, 5, 5, 6, 6, 7, 8, 8, 9, 11, 12}, /* DSC v1.2 YUV420 */ {0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 10}, {0, 2, 3, 4, 6, 7, 7, 7, 7, 7, 9, 9, 9, 11, 14}, {0, 2, 3, 4, 5, 5, 5, 6, 6, 7, 8, 8, 9, 11, 12}, }; /* * Rate control - Max QP values for each ratio type in sde_dsc_ratio_type */ static char sde_dsc_rc_range_max_qp[DSC_RATIO_TYPE_MAX][DSC_NUM_BUF_RANGES] = { /* DSC v1.1 */ {4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 11, 12, 13, 13, 15}, {4, 8, 9, 10, 11, 11, 11, 12, 13, 14, 15, 16, 17, 17, 19}, {7, 8, 9, 10, 11, 11, 11, 12, 13, 13, 14, 14, 15, 15, 16}, /* DSC v1.1 SCR and DSC v1.2 RGB 444 */ {4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 10, 11, 11, 12, 13}, {8, 8, 9, 10, 11, 11, 11, 12, 13, 14, 14, 15, 15, 16, 17}, {7, 8, 9, 10, 11, 11, 11, 12, 13, 13, 14, 14, 15, 15, 16}, /* DSC v1.2 YUV422 */ {3, 4, 5, 6, 7, 7, 7, 8, 9, 9, 10, 10, 11, 11, 12}, {2, 4, 5, 6, 7, 7, 7, 8, 8, 9, 9, 9, 9, 10, 11}, {7, 8, 9, 10, 11, 11, 11, 12, 13, 13, 14, 14, 15, 15, 16}, {2, 5, 7, 8, 9, 10, 11, 12, 12, 13, 13, 13, 13, 14, 15}, {2, 5, 5, 6, 6, 7, 7, 8, 9, 9, 10, 11, 11, 12, 13}, /* DSC v1.2 YUV420 */ {2, 4, 5, 6, 7, 7, 7, 8, 8, 9, 9, 9, 9, 10, 12}, {2, 5, 7, 8, 9, 10, 11, 12, 12, 13, 13, 13, 13, 14, 15}, {2, 5, 5, 6, 6, 7, 7, 8, 9, 9, 10, 11, 11, 12, 13}, }; /* * Rate control - bpg offset values for each ratio type in sde_dsc_ratio_type */ static char sde_dsc_rc_range_bpg[DSC_RATIO_TYPE_MAX][DSC_NUM_BUF_RANGES] = { /* DSC v1.1 */ {2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12}, {2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12}, {2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12}, /* DSC v1.1 SCR and DSC V1.2 RGB 444 */ {2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12}, {2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12}, {2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12}, /* DSC v1.2 YUV422 */ {2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12}, {2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12}, {2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12}, {2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12}, {10, 8, 6, 4, 2, 0, -2, -4, -6, -8, -10, -10, -12, -12, -12}, /* DSC v1.2 YUV420 */ {2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12}, {2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12}, {10, 8, 6, 4, 2, 0, -2, -4, -6, -8, -10, -10, -12, -12, -12}, }; static struct sde_dsc_rc_init_params_lut { u32 rc_quant_incr_limit0; u32 rc_quant_incr_limit1; u32 initial_fullness_offset; u32 initial_xmit_delay; u32 second_line_bpg_offset; u32 second_line_offset_adj; u32 flatness_min_qp; u32 flatness_max_qp; } sde_dsc_rc_init_param_lut[] = { /* DSC v1.1 */ {11, 11, 6144, 512, 0, 0, 3, 12}, /* DSC_V11_8BPC_8BPP */ {15, 15, 6144, 512, 0, 0, 7, 16}, /* DSC_V11_10BPC_8BPP */ {15, 15, 5632, 410, 0, 0, 7, 16}, /* DSC_V11_10BPC_10BPP */ /* DSC v1.1 SCR and DSC v1.2 RGB 444 */ {11, 11, 6144, 512, 0, 0, 3, 12}, /* DSC_V12_444_8BPC_8BPP or DSC_V11_SCR1_8BPC_8BPP */ {15, 15, 6144, 512, 0, 0, 7, 16}, /* DSC_V12_444_10BPC_8BPP or DSC_V11_SCR1_10BPC_8BPP */ {15, 15, 5632, 410, 0, 0, 7, 16}, /* DSC_V12_444_10BPC_10BPP or DSC_V11_SCR1_10BPC_10BPP */ /* DSC v1.2 YUV422 */ {11, 11, 5632, 410, 0, 0, 3, 12}, /* DSC_V12_422_8BPC_7BPP */ {11, 11, 2048, 341, 0, 0, 3, 12}, /* DSC_V12_422_8BPC_8BPP */ {15, 15, 5632, 410, 0, 0, 7, 16}, /* DSC_V12_422_10BPC_7BPP */ {15, 15, 2048, 341, 0, 0, 7, 16}, /* DSC_V12_422_10BPC_8BPP */ {15, 15, 2048, 273, 0, 0, 7, 16}, /* DSC_V12_422_10BPC_10BPP */ /* DSC v1.2 YUV420 */ {11, 11, 5632, 410, 0, 0, 3, 12}, /* DSC_V12_422_8BPC_7BPP */ {11, 11, 2048, 341, 12, 512, 3, 12}, /* DSC_V12_420_8BPC_6BPP */ {15, 15, 2048, 341, 12, 512, 7, 16}, /* DSC_V12_420_10BPC_6BPP */ {15, 15, 2048, 256, 12, 512, 7, 16}, /* DSC_V12_420_10BPC_7_5BPP */ }; /** * Maps to lookup the sde_dsc_ratio_type index used in rate control tables */ static struct sde_dsc_table_index_lut { u32 fmt; u32 scr_ver; u32 minor_ver; u32 bpc; u32 bpp; u32 type; } sde_dsc_index_map[] = { /* DSC 1.1 formats - scr version is considered */ {MSM_CHROMA_444, 0, 1, 8, 8, DSC_V11_8BPC_8BPP}, {MSM_CHROMA_444, 0, 1, 10, 8, DSC_V11_10BPC_8BPP}, {MSM_CHROMA_444, 0, 1, 10, 10, DSC_V11_10BPC_10BPP}, {MSM_CHROMA_444, 1, 1, 8, 8, DSC_V11_SCR1_8BPC_8BPP}, {MSM_CHROMA_444, 1, 1, 10, 8, DSC_V11_SCR1_10BPC_8BPP}, {MSM_CHROMA_444, 1, 1, 10, 10, DSC_V11_SCR1_10BPC_10BPP}, /* DSC 1.2 formats - scr version is no-op */ {MSM_CHROMA_444, -1, 2, 8, 8, DSC_V12_444_8BPC_8BPP}, {MSM_CHROMA_444, -1, 2, 10, 8, DSC_V12_444_10BPC_8BPP}, {MSM_CHROMA_444, -1, 2, 10, 10, DSC_V12_444_10BPC_10BPP}, {MSM_CHROMA_422, -1, 2, 8, 7, DSC_V12_422_8BPC_7BPP}, {MSM_CHROMA_422, -1, 2, 8, 8, DSC_V12_422_8BPC_8BPP}, {MSM_CHROMA_422, -1, 2, 10, 7, DSC_V12_422_10BPC_7BPP}, {MSM_CHROMA_422, -1, 2, 10, 8, DSC_V12_422_10BPC_8BPP}, {MSM_CHROMA_422, -1, 2, 10, 10, DSC_V12_422_10BPC_10BPP}, {MSM_CHROMA_420, -1, 2, 8, 6, DSC_V12_420_8BPC_6BPP}, {MSM_CHROMA_420, -1, 2, 10, 6, DSC_V12_420_10BPC_6BPP}, }; static int _get_rc_table_index(struct drm_dsc_config *dsc, int scr_ver) { u32 bpp, bpc, i, fmt = MSM_CHROMA_444; if (dsc->dsc_version_major != 0x1) { SDE_ERROR("unsupported major version %d\n", dsc->dsc_version_major); return -EINVAL; } bpc = dsc->bits_per_component; bpp = DSC_BPP(*dsc); if (dsc->native_422) fmt = MSM_CHROMA_422; else if (dsc->native_420) fmt = MSM_CHROMA_420; for (i = 0; i < ARRAY_SIZE(sde_dsc_index_map); i++) { if (dsc->dsc_version_minor == sde_dsc_index_map[i].minor_ver && fmt == sde_dsc_index_map[i].fmt && bpc == sde_dsc_index_map[i].bpc && bpp == sde_dsc_index_map[i].bpp && (dsc->dsc_version_minor != 0x1 || scr_ver == sde_dsc_index_map[i].scr_ver)) return sde_dsc_index_map[i].type; } SDE_ERROR("unsupported DSC v%d.%dr%d, bpc:%d, bpp:%d, fmt:0x%x\n", dsc->dsc_version_major, dsc->dsc_version_minor, scr_ver, bpc, bpp, fmt); return -EINVAL; } u8 _get_dsc_v1_2_bpg_offset(struct drm_dsc_config *dsc) { u8 bpg_offset = 0; u8 uncompressed_bpg_rate; u8 bpp = DSC_BPP(*dsc); if (dsc->slice_height < 8) bpg_offset = 2 * (dsc->slice_height - 1); else if (dsc->slice_height < 20) bpg_offset = 12; else if (dsc->slice_height <= 30) bpg_offset = 13; else if (dsc->slice_height < 42) bpg_offset = 14; else bpg_offset = 15; if (dsc->native_422) uncompressed_bpg_rate = 3 * bpp * 4; else if (dsc->native_420) uncompressed_bpg_rate = 3 * bpp; else uncompressed_bpg_rate = (3 * bpp + 2) * 3; if (bpg_offset < (uncompressed_bpg_rate - (3 * bpp))) return bpg_offset; else return (uncompressed_bpg_rate - (3 * bpp)); } int sde_dsc_populate_dsc_config(struct drm_dsc_config *dsc, int scr_ver) { int bpp, bpc; int groups_per_line, groups_total; int min_rate_buffer_size; int hrd_delay; int pre_num_extra_mux_bits, num_extra_mux_bits; int slice_bits; int data; int final_value, final_scale; struct sde_dsc_rc_init_params_lut *rc_param_lut; u32 slice_width_mod; int i, ratio_idx; dsc->rc_model_size = 8192; if ((dsc->dsc_version_major == 0x1) && (dsc->dsc_version_minor == 0x1)) { if (scr_ver == 0x1) dsc->first_line_bpg_offset = 15; else dsc->first_line_bpg_offset = 12; } else if (dsc->dsc_version_minor == 0x2) { dsc->first_line_bpg_offset = _get_dsc_v1_2_bpg_offset(dsc); } dsc->rc_edge_factor = 6; dsc->rc_tgt_offset_high = 3; dsc->rc_tgt_offset_low = 3; dsc->simple_422 = 0; dsc->convert_rgb = !(dsc->native_422 | dsc->native_420); dsc->vbr_enable = 0; bpp = DSC_BPP(*dsc); bpc = dsc->bits_per_component; ratio_idx = _get_rc_table_index(dsc, scr_ver); if ((ratio_idx < 0) || (ratio_idx >= DSC_RATIO_TYPE_MAX)) return -EINVAL; for (i = 0; i < DSC_NUM_BUF_RANGES - 1; i++) dsc->rc_buf_thresh[i] = sde_dsc_rc_buf_thresh[i]; for (i = 0; i < DSC_NUM_BUF_RANGES; i++) { dsc->rc_range_params[i].range_min_qp = sde_dsc_rc_range_min_qp[ratio_idx][i]; dsc->rc_range_params[i].range_max_qp = sde_dsc_rc_range_max_qp[ratio_idx][i]; dsc->rc_range_params[i].range_bpg_offset = sde_dsc_rc_range_bpg[ratio_idx][i]; } rc_param_lut = &sde_dsc_rc_init_param_lut[ratio_idx]; dsc->rc_quant_incr_limit0 = rc_param_lut->rc_quant_incr_limit0; dsc->rc_quant_incr_limit1 = rc_param_lut->rc_quant_incr_limit1; dsc->initial_offset = rc_param_lut->initial_fullness_offset; dsc->initial_xmit_delay = rc_param_lut->initial_xmit_delay; dsc->second_line_bpg_offset = rc_param_lut->second_line_bpg_offset; dsc->second_line_offset_adj = rc_param_lut->second_line_offset_adj; dsc->flatness_min_qp = rc_param_lut->flatness_min_qp; dsc->flatness_max_qp = rc_param_lut->flatness_max_qp; slice_width_mod = dsc->slice_width; if (dsc->native_422 || dsc->native_420) { slice_width_mod = dsc->slice_width / 2; bpp = bpp * 2; } dsc->line_buf_depth = bpc + 1; dsc->mux_word_size = bpc > 10 ? DSC_MUX_WORD_SIZE_12_BPC: DSC_MUX_WORD_SIZE_8_10_BPC; if ((dsc->dsc_version_minor == 0x2) && (dsc->native_420)) dsc->nsl_bpg_offset = (2048 * (DIV_ROUND_UP(dsc->second_line_bpg_offset, (dsc->slice_height - 1)))); groups_per_line = DIV_ROUND_UP(slice_width_mod, 3); dsc->slice_chunk_size = slice_width_mod * bpp / 8; if ((slice_width_mod * bpp) % 8) dsc->slice_chunk_size++; /* rbs-min */ min_rate_buffer_size = dsc->rc_model_size - dsc->initial_offset + dsc->initial_xmit_delay * bpp + groups_per_line * dsc->first_line_bpg_offset; hrd_delay = DIV_ROUND_UP(min_rate_buffer_size, bpp); dsc->initial_dec_delay = hrd_delay - dsc->initial_xmit_delay; dsc->initial_scale_value = 8 * dsc->rc_model_size / (dsc->rc_model_size - dsc->initial_offset); slice_bits = 8 * dsc->slice_chunk_size * dsc->slice_height; groups_total = groups_per_line * dsc->slice_height; data = dsc->first_line_bpg_offset * 2048; dsc->nfl_bpg_offset = DIV_ROUND_UP(data, (dsc->slice_height - 1)); if (dsc->native_422) pre_num_extra_mux_bits = 4 * dsc->mux_word_size + (4 * bpc + 4) + (3 * 4 * bpc) - 2; else if (dsc->native_420) pre_num_extra_mux_bits = 3 * dsc->mux_word_size + (4 * bpc + 4) + (2 * 4 * bpc) - 2; else pre_num_extra_mux_bits = 3 * (dsc->mux_word_size + (4 * bpc + 4) - 2); num_extra_mux_bits = pre_num_extra_mux_bits - (dsc->mux_word_size - ((slice_bits - pre_num_extra_mux_bits) % dsc->mux_word_size)); data = 2048 * (dsc->rc_model_size - dsc->initial_offset + num_extra_mux_bits); dsc->slice_bpg_offset = DIV_ROUND_UP(data, groups_total); data = dsc->initial_xmit_delay * bpp; final_value = dsc->rc_model_size - data + num_extra_mux_bits; final_scale = 8 * dsc->rc_model_size / (dsc->rc_model_size - final_value); dsc->final_offset = final_value; data = (final_scale - 9) * (dsc->nfl_bpg_offset + dsc->slice_bpg_offset); dsc->scale_increment_interval = (2048 * dsc->final_offset) / data; dsc->scale_decrement_interval = groups_per_line / (dsc->initial_scale_value - 8); return 0; } int sde_dsc_populate_dsc_private_params(struct msm_display_dsc_info *dsc_info, int intf_width, bool widebus_en) { int mod_offset; int slice_per_pkt, slice_per_intf; int bytes_in_slice, total_bytes_per_intf; u16 bpp; u16 bpc; u32 bytes_in_dsc_pair; u32 total_bytes_in_dsc_pair; if (!dsc_info || !dsc_info->config.slice_width || !dsc_info->config.slice_height || intf_width < dsc_info->config.slice_width) { SDE_ERROR("invalid input, intf_width=%d slice_width=%d\n", intf_width, dsc_info ? dsc_info->config.slice_width : -1); return -EINVAL; } mod_offset = dsc_info->config.slice_width % 3; switch (mod_offset) { case 0: dsc_info->slice_last_group_size = 2; break; case 1: dsc_info->slice_last_group_size = 0; break; case 2: dsc_info->slice_last_group_size = 1; break; default: break; } dsc_info->det_thresh_flatness = 2 << (dsc_info->config.bits_per_component - 8); slice_per_pkt = dsc_info->slice_per_pkt; slice_per_intf = DIV_ROUND_UP(intf_width, dsc_info->config.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 = DSC_BPP(dsc_info->config); bpc = DSC_BPC(dsc_info->config); bytes_in_slice = DIV_ROUND_UP(dsc_info->config.slice_width * bpp, 8); total_bytes_per_intf = bytes_in_slice * slice_per_intf; dsc_info->eol_byte_num = total_bytes_per_intf % 3; /* * In DATABUS-WIDEN mode, MDP always sends out 48-bit compressed data per pclk * and on average, DSI consumes an amount of compressed data equivalent to the * uncompressed pixel depth per pclk. * * In NON-DATABUS-WIDEN mode, MDP always sends out 24-bit compressed data per * pclk and DSI always consumes 24-bit compressed data per pclk. */ if (widebus_en) dsc_info->pclk_per_line = DIV_ROUND_UP(total_bytes_per_intf * 8, msm_get_src_bpc(dsc_info->chroma_format, bpc)); else dsc_info->pclk_per_line = DIV_ROUND_UP(total_bytes_per_intf * 8, 24); dsc_info->bytes_in_slice = bytes_in_slice; dsc_info->bytes_per_pkt = bytes_in_slice * slice_per_pkt; dsc_info->pkt_per_line = slice_per_intf / slice_per_pkt; bytes_in_dsc_pair = DIV_ROUND_UP(bytes_in_slice * 2, 3); if (bytes_in_dsc_pair % 8) { dsc_info->dsc_4hsmerge_padding = 8 - (bytes_in_dsc_pair % 8); total_bytes_in_dsc_pair = bytes_in_dsc_pair + dsc_info->dsc_4hsmerge_padding; if (total_bytes_in_dsc_pair % 16) dsc_info->dsc_4hsmerge_alignment = 16 - (total_bytes_in_dsc_pair % 16); } return 0; } int sde_dsc_create_pps_buf_cmd(struct msm_display_dsc_info *dsc_info, char *buf, int pps_id, u32 len) { struct drm_dsc_config *dsc = &dsc_info->config; char *bp = buf; char data; u32 i, bpp; if (len < SDE_DSC_PPS_SIZE) return -EINVAL; memset(buf, 0, len); /* pps0 */ *bp++ = (dsc->dsc_version_minor | dsc->dsc_version_major << 4); *bp++ = (pps_id & 0xff); /* pps1 */ bp++; /* pps2, reserved */ data = dsc->line_buf_depth & 0x0f; data |= ((dsc->bits_per_component & 0xf) << DSC_PPS_BPC_SHIFT); *bp++ = data; /* pps3 */ bpp = dsc->bits_per_pixel; if (dsc->native_422 || dsc->native_420) bpp = 2 * bpp; data = (bpp >> DSC_PPS_MSB_SHIFT); data &= 0x03; /* upper two bits */ data |= ((dsc->block_pred_enable & 0x1) << 5); data |= ((dsc->convert_rgb & 0x1) << 4); data |= ((dsc->simple_422 & 0x1) << 3); data |= ((dsc->vbr_enable & 0x1) << 2); *bp++ = data; /* pps4 */ *bp++ = (bpp & DSC_PPS_LSB_MASK); /* pps5 */ *bp++ = ((dsc->pic_height >> 8) & 0xff); /* pps6 */ *bp++ = (dsc->pic_height & 0x0ff); /* pps7 */ *bp++ = ((dsc->pic_width >> 8) & 0xff); /* pps8 */ *bp++ = (dsc->pic_width & 0x0ff); /* pps9 */ *bp++ = ((dsc->slice_height >> 8) & 0xff);/* pps10 */ *bp++ = (dsc->slice_height & 0x0ff); /* pps11 */ *bp++ = ((dsc->slice_width >> 8) & 0xff); /* pps12 */ *bp++ = (dsc->slice_width & 0x0ff); /* pps13 */ *bp++ = ((dsc->slice_chunk_size >> 8) & 0xff);/* pps14 */ *bp++ = (dsc->slice_chunk_size & 0x0ff); /* pps15 */ *bp++ = (dsc->initial_xmit_delay >> 8) & 0x3; /* pps16 */ *bp++ = (dsc->initial_xmit_delay & 0xff);/* pps17 */ *bp++ = ((dsc->initial_dec_delay >> 8) & 0xff); /* pps18 */ *bp++ = (dsc->initial_dec_delay & 0xff);/* pps19 */ bp++; /* pps20, reserved */ *bp++ = (dsc->initial_scale_value & 0x3f); /* pps21 */ *bp++ = ((dsc->scale_increment_interval >> 8) & 0xff); /* pps22 */ *bp++ = (dsc->scale_increment_interval & 0xff); /* pps23 */ *bp++ = ((dsc->scale_decrement_interval >> 8) & 0xf); /* pps24 */ *bp++ = (dsc->scale_decrement_interval & 0x0ff);/* pps25 */ bp++; /* pps26, reserved */ *bp++ = (dsc->first_line_bpg_offset & 0x1f);/* pps27 */ *bp++ = ((dsc->nfl_bpg_offset >> 8) & 0xff);/* pps28 */ *bp++ = (dsc->nfl_bpg_offset & 0x0ff); /* pps29 */ *bp++ = ((dsc->slice_bpg_offset >> 8) & 0xff);/* pps30 */ *bp++ = (dsc->slice_bpg_offset & 0x0ff);/* pps31 */ *bp++ = ((dsc->initial_offset >> 8) & 0xff);/* pps32 */ *bp++ = (dsc->initial_offset & 0x0ff); /* pps33 */ *bp++ = ((dsc->final_offset >> 8) & 0xff);/* pps34 */ *bp++ = (dsc->final_offset & 0x0ff); /* pps35 */ *bp++ = (dsc->flatness_min_qp & 0x1f); /* pps36 */ *bp++ = (dsc->flatness_max_qp & 0x1f); /* pps37 */ *bp++ = ((dsc->rc_model_size >> 8) & 0xff);/* pps38 */ *bp++ = (dsc->rc_model_size & 0x0ff); /* pps39 */ *bp++ = (dsc->rc_edge_factor & 0x0f); /* pps40 */ *bp++ = (dsc->rc_quant_incr_limit0 & 0x1f); /* pps41 */ *bp++ = (dsc->rc_quant_incr_limit1 & 0x1f); /* pps42 */ data = ((dsc->rc_tgt_offset_high & 0xf) << 4); data |= (dsc->rc_tgt_offset_low & 0x0f); *bp++ = data; /* pps43 */ for (i = 0; i < DSC_NUM_BUF_RANGES - 1; i++) *bp++ = (dsc->rc_buf_thresh[i] & 0xff); /* pps44 - pps57 */ for (i = 0; i < DSC_NUM_BUF_RANGES; i++) { /* pps58 - pps87 */ data = (dsc->rc_range_params[i].range_min_qp & 0x1f); data <<= 3; data |= ((dsc->rc_range_params[i].range_max_qp >> 2) & 0x07); *bp++ = data; data = (dsc->rc_range_params[i].range_max_qp & 0x03); data <<= 6; data |= (dsc->rc_range_params[i].range_bpg_offset & 0x3f); *bp++ = data; } if (dsc->dsc_version_minor == 0x2) { if (dsc->native_422) data = BIT(0); else if (dsc->native_420) data = BIT(1); *bp++ = data; /* pps88 */ *bp++ = dsc->second_line_bpg_offset; /* pps89 */ *bp++ = ((dsc->nsl_bpg_offset >> 8) & 0xff);/* pps90 */ *bp++ = (dsc->nsl_bpg_offset & 0x0ff); /* pps91 */ *bp++ = ((dsc->second_line_offset_adj >> 8) & 0xff); /* pps92*/ *bp++ = (dsc->second_line_offset_adj & 0x0ff); /* pps93 */ /* rest bytes are reserved and set to 0 */ } return 0; }