Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v5.1-rc3 246 lines 7.6 kB view raw
1// SPDX-License-Identifier: MIT 2/* 3 * Copyright © 2018 Intel Corp 4 * 5 * Author: 6 * Manasi Navare <manasi.d.navare@intel.com> 7 */ 8 9#include <linux/kernel.h> 10#include <linux/module.h> 11#include <linux/init.h> 12#include <linux/errno.h> 13#include <linux/byteorder/generic.h> 14#include <drm/drm_dp_helper.h> 15#include <drm/drm_dsc.h> 16 17/** 18 * DOC: dsc helpers 19 * 20 * VESA specification for DP 1.4 adds a new feature called Display Stream 21 * Compression (DSC) used to compress the pixel bits before sending it on 22 * DP/eDP/MIPI DSI interface. DSC is required to be enabled so that the existing 23 * display interfaces can support high resolutions at higher frames rates uisng 24 * the maximum available link capacity of these interfaces. 25 * 26 * These functions contain some common logic and helpers to deal with VESA 27 * Display Stream Compression standard required for DSC on Display Port/eDP or 28 * MIPI display interfaces. 29 */ 30 31/** 32 * drm_dsc_dp_pps_header_init() - Initializes the PPS Header 33 * for DisplayPort as per the DP 1.4 spec. 34 * @pps_sdp: Secondary data packet for DSC Picture Parameter Set 35 * as defined in &struct drm_dsc_pps_infoframe 36 * 37 * DP 1.4 spec defines the secondary data packet for sending the 38 * picture parameter infoframes from the source to the sink. 39 * This function populates the pps header defined in 40 * &struct drm_dsc_pps_infoframe as per the header bytes defined 41 * in &struct dp_sdp_header. 42 */ 43void drm_dsc_dp_pps_header_init(struct drm_dsc_pps_infoframe *pps_sdp) 44{ 45 memset(&pps_sdp->pps_header, 0, sizeof(pps_sdp->pps_header)); 46 47 pps_sdp->pps_header.HB1 = DP_SDP_PPS; 48 pps_sdp->pps_header.HB2 = DP_SDP_PPS_HEADER_PAYLOAD_BYTES_MINUS_1; 49} 50EXPORT_SYMBOL(drm_dsc_dp_pps_header_init); 51 52/** 53 * drm_dsc_pps_infoframe_pack() - Populates the DSC PPS infoframe 54 * 55 * @pps_sdp: 56 * Secondary data packet for DSC Picture Parameter Set. This is defined 57 * by &struct drm_dsc_pps_infoframe 58 * @dsc_cfg: 59 * DSC Configuration data filled by driver as defined by 60 * &struct drm_dsc_config 61 * 62 * DSC source device sends a secondary data packet filled with all the 63 * picture parameter set (PPS) information required by the sink to decode 64 * the compressed frame. Driver populates the dsC PPS infoframe using the DSC 65 * configuration parameters in the order expected by the DSC Display Sink 66 * device. For the DSC, the sink device expects the PPS payload in the big 67 * endian format for the fields that span more than 1 byte. 68 */ 69void drm_dsc_pps_infoframe_pack(struct drm_dsc_pps_infoframe *pps_sdp, 70 const struct drm_dsc_config *dsc_cfg) 71{ 72 int i; 73 74 /* Protect against someone accidently changing struct size */ 75 BUILD_BUG_ON(sizeof(pps_sdp->pps_payload) != 76 DP_SDP_PPS_HEADER_PAYLOAD_BYTES_MINUS_1 + 1); 77 78 memset(&pps_sdp->pps_payload, 0, sizeof(pps_sdp->pps_payload)); 79 80 /* PPS 0 */ 81 pps_sdp->pps_payload.dsc_version = 82 dsc_cfg->dsc_version_minor | 83 dsc_cfg->dsc_version_major << DSC_PPS_VERSION_MAJOR_SHIFT; 84 85 /* PPS 1, 2 is 0 */ 86 87 /* PPS 3 */ 88 pps_sdp->pps_payload.pps_3 = 89 dsc_cfg->line_buf_depth | 90 dsc_cfg->bits_per_component << DSC_PPS_BPC_SHIFT; 91 92 /* PPS 4 */ 93 pps_sdp->pps_payload.pps_4 = 94 ((dsc_cfg->bits_per_pixel & DSC_PPS_BPP_HIGH_MASK) >> 95 DSC_PPS_MSB_SHIFT) | 96 dsc_cfg->vbr_enable << DSC_PPS_VBR_EN_SHIFT | 97 dsc_cfg->enable422 << DSC_PPS_SIMPLE422_SHIFT | 98 dsc_cfg->convert_rgb << DSC_PPS_CONVERT_RGB_SHIFT | 99 dsc_cfg->block_pred_enable << DSC_PPS_BLOCK_PRED_EN_SHIFT; 100 101 /* PPS 5 */ 102 pps_sdp->pps_payload.bits_per_pixel_low = 103 (dsc_cfg->bits_per_pixel & DSC_PPS_LSB_MASK); 104 105 /* 106 * The DSC panel expects the PPS packet to have big endian format 107 * for data spanning 2 bytes. Use a macro cpu_to_be16() to convert 108 * to big endian format. If format is little endian, it will swap 109 * bytes to convert to Big endian else keep it unchanged. 110 */ 111 112 /* PPS 6, 7 */ 113 pps_sdp->pps_payload.pic_height = cpu_to_be16(dsc_cfg->pic_height); 114 115 /* PPS 8, 9 */ 116 pps_sdp->pps_payload.pic_width = cpu_to_be16(dsc_cfg->pic_width); 117 118 /* PPS 10, 11 */ 119 pps_sdp->pps_payload.slice_height = cpu_to_be16(dsc_cfg->slice_height); 120 121 /* PPS 12, 13 */ 122 pps_sdp->pps_payload.slice_width = cpu_to_be16(dsc_cfg->slice_width); 123 124 /* PPS 14, 15 */ 125 pps_sdp->pps_payload.chunk_size = cpu_to_be16(dsc_cfg->slice_chunk_size); 126 127 /* PPS 16 */ 128 pps_sdp->pps_payload.initial_xmit_delay_high = 129 ((dsc_cfg->initial_xmit_delay & 130 DSC_PPS_INIT_XMIT_DELAY_HIGH_MASK) >> 131 DSC_PPS_MSB_SHIFT); 132 133 /* PPS 17 */ 134 pps_sdp->pps_payload.initial_xmit_delay_low = 135 (dsc_cfg->initial_xmit_delay & DSC_PPS_LSB_MASK); 136 137 /* PPS 18, 19 */ 138 pps_sdp->pps_payload.initial_dec_delay = 139 cpu_to_be16(dsc_cfg->initial_dec_delay); 140 141 /* PPS 20 is 0 */ 142 143 /* PPS 21 */ 144 pps_sdp->pps_payload.initial_scale_value = 145 dsc_cfg->initial_scale_value; 146 147 /* PPS 22, 23 */ 148 pps_sdp->pps_payload.scale_increment_interval = 149 cpu_to_be16(dsc_cfg->scale_increment_interval); 150 151 /* PPS 24 */ 152 pps_sdp->pps_payload.scale_decrement_interval_high = 153 ((dsc_cfg->scale_decrement_interval & 154 DSC_PPS_SCALE_DEC_INT_HIGH_MASK) >> 155 DSC_PPS_MSB_SHIFT); 156 157 /* PPS 25 */ 158 pps_sdp->pps_payload.scale_decrement_interval_low = 159 (dsc_cfg->scale_decrement_interval & DSC_PPS_LSB_MASK); 160 161 /* PPS 26[7:0], PPS 27[7:5] RESERVED */ 162 163 /* PPS 27 */ 164 pps_sdp->pps_payload.first_line_bpg_offset = 165 dsc_cfg->first_line_bpg_offset; 166 167 /* PPS 28, 29 */ 168 pps_sdp->pps_payload.nfl_bpg_offset = 169 cpu_to_be16(dsc_cfg->nfl_bpg_offset); 170 171 /* PPS 30, 31 */ 172 pps_sdp->pps_payload.slice_bpg_offset = 173 cpu_to_be16(dsc_cfg->slice_bpg_offset); 174 175 /* PPS 32, 33 */ 176 pps_sdp->pps_payload.initial_offset = 177 cpu_to_be16(dsc_cfg->initial_offset); 178 179 /* PPS 34, 35 */ 180 pps_sdp->pps_payload.final_offset = cpu_to_be16(dsc_cfg->final_offset); 181 182 /* PPS 36 */ 183 pps_sdp->pps_payload.flatness_min_qp = dsc_cfg->flatness_min_qp; 184 185 /* PPS 37 */ 186 pps_sdp->pps_payload.flatness_max_qp = dsc_cfg->flatness_max_qp; 187 188 /* PPS 38, 39 */ 189 pps_sdp->pps_payload.rc_model_size = 190 cpu_to_be16(DSC_RC_MODEL_SIZE_CONST); 191 192 /* PPS 40 */ 193 pps_sdp->pps_payload.rc_edge_factor = DSC_RC_EDGE_FACTOR_CONST; 194 195 /* PPS 41 */ 196 pps_sdp->pps_payload.rc_quant_incr_limit0 = 197 dsc_cfg->rc_quant_incr_limit0; 198 199 /* PPS 42 */ 200 pps_sdp->pps_payload.rc_quant_incr_limit1 = 201 dsc_cfg->rc_quant_incr_limit1; 202 203 /* PPS 43 */ 204 pps_sdp->pps_payload.rc_tgt_offset = DSC_RC_TGT_OFFSET_LO_CONST | 205 DSC_RC_TGT_OFFSET_HI_CONST << DSC_PPS_RC_TGT_OFFSET_HI_SHIFT; 206 207 /* PPS 44 - 57 */ 208 for (i = 0; i < DSC_NUM_BUF_RANGES - 1; i++) 209 pps_sdp->pps_payload.rc_buf_thresh[i] = 210 dsc_cfg->rc_buf_thresh[i]; 211 212 /* PPS 58 - 87 */ 213 /* 214 * For DSC sink programming the RC Range parameter fields 215 * are as follows: Min_qp[15:11], max_qp[10:6], offset[5:0] 216 */ 217 for (i = 0; i < DSC_NUM_BUF_RANGES; i++) { 218 pps_sdp->pps_payload.rc_range_parameters[i] = 219 ((dsc_cfg->rc_range_params[i].range_min_qp << 220 DSC_PPS_RC_RANGE_MINQP_SHIFT) | 221 (dsc_cfg->rc_range_params[i].range_max_qp << 222 DSC_PPS_RC_RANGE_MAXQP_SHIFT) | 223 (dsc_cfg->rc_range_params[i].range_bpg_offset)); 224 pps_sdp->pps_payload.rc_range_parameters[i] = 225 cpu_to_be16(pps_sdp->pps_payload.rc_range_parameters[i]); 226 } 227 228 /* PPS 88 */ 229 pps_sdp->pps_payload.native_422_420 = dsc_cfg->native_422 | 230 dsc_cfg->native_420 << DSC_PPS_NATIVE_420_SHIFT; 231 232 /* PPS 89 */ 233 pps_sdp->pps_payload.second_line_bpg_offset = 234 dsc_cfg->second_line_bpg_offset; 235 236 /* PPS 90, 91 */ 237 pps_sdp->pps_payload.nsl_bpg_offset = 238 cpu_to_be16(dsc_cfg->nsl_bpg_offset); 239 240 /* PPS 92, 93 */ 241 pps_sdp->pps_payload.second_line_offset_adj = 242 cpu_to_be16(dsc_cfg->second_line_offset_adj); 243 244 /* PPS 94 - 127 are O */ 245} 246EXPORT_SYMBOL(drm_dsc_pps_infoframe_pack);