1 // SPDX-License-Identifier: MIT
3 * Copyright © 2018 Intel Corp
6 * Manasi Navare <manasi.d.navare@intel.com>
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>
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.
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.
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
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.
43 void drm_dsc_dp_pps_header_init(struct drm_dsc_pps_infoframe
*pps_sdp
)
45 memset(&pps_sdp
->pps_header
, 0, sizeof(pps_sdp
->pps_header
));
47 pps_sdp
->pps_header
.HB1
= DP_SDP_PPS
;
48 pps_sdp
->pps_header
.HB2
= DP_SDP_PPS_HEADER_PAYLOAD_BYTES_MINUS_1
;
50 EXPORT_SYMBOL(drm_dsc_dp_pps_header_init
);
53 * drm_dsc_pps_infoframe_pack() - Populates the DSC PPS infoframe
56 * Secondary data packet for DSC Picture Parameter Set. This is defined
57 * by &struct drm_dsc_pps_infoframe
59 * DSC Configuration data filled by driver as defined by
60 * &struct drm_dsc_config
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.
69 void drm_dsc_pps_infoframe_pack(struct drm_dsc_pps_infoframe
*pps_sdp
,
70 const struct drm_dsc_config
*dsc_cfg
)
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);
78 memset(&pps_sdp
->pps_payload
, 0, sizeof(pps_sdp
->pps_payload
));
81 pps_sdp
->pps_payload
.dsc_version
=
82 dsc_cfg
->dsc_version_minor
|
83 dsc_cfg
->dsc_version_major
<< DSC_PPS_VERSION_MAJOR_SHIFT
;
88 pps_sdp
->pps_payload
.pps_3
=
89 dsc_cfg
->line_buf_depth
|
90 dsc_cfg
->bits_per_component
<< DSC_PPS_BPC_SHIFT
;
93 pps_sdp
->pps_payload
.pps_4
=
94 ((dsc_cfg
->bits_per_pixel
& DSC_PPS_BPP_HIGH_MASK
) >>
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
;
102 pps_sdp
->pps_payload
.bits_per_pixel_low
=
103 (dsc_cfg
->bits_per_pixel
& DSC_PPS_LSB_MASK
);
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.
113 pps_sdp
->pps_payload
.pic_height
= cpu_to_be16(dsc_cfg
->pic_height
);
116 pps_sdp
->pps_payload
.pic_width
= cpu_to_be16(dsc_cfg
->pic_width
);
119 pps_sdp
->pps_payload
.slice_height
= cpu_to_be16(dsc_cfg
->slice_height
);
122 pps_sdp
->pps_payload
.slice_width
= cpu_to_be16(dsc_cfg
->slice_width
);
125 pps_sdp
->pps_payload
.chunk_size
= cpu_to_be16(dsc_cfg
->slice_chunk_size
);
128 pps_sdp
->pps_payload
.initial_xmit_delay_high
=
129 ((dsc_cfg
->initial_xmit_delay
&
130 DSC_PPS_INIT_XMIT_DELAY_HIGH_MASK
) >>
134 pps_sdp
->pps_payload
.initial_xmit_delay_low
=
135 (dsc_cfg
->initial_xmit_delay
& DSC_PPS_LSB_MASK
);
138 pps_sdp
->pps_payload
.initial_dec_delay
=
139 cpu_to_be16(dsc_cfg
->initial_dec_delay
);
144 pps_sdp
->pps_payload
.initial_scale_value
=
145 dsc_cfg
->initial_scale_value
;
148 pps_sdp
->pps_payload
.scale_increment_interval
=
149 cpu_to_be16(dsc_cfg
->scale_increment_interval
);
152 pps_sdp
->pps_payload
.scale_decrement_interval_high
=
153 ((dsc_cfg
->scale_decrement_interval
&
154 DSC_PPS_SCALE_DEC_INT_HIGH_MASK
) >>
158 pps_sdp
->pps_payload
.scale_decrement_interval_low
=
159 (dsc_cfg
->scale_decrement_interval
& DSC_PPS_LSB_MASK
);
161 /* PPS 26[7:0], PPS 27[7:5] RESERVED */
164 pps_sdp
->pps_payload
.first_line_bpg_offset
=
165 dsc_cfg
->first_line_bpg_offset
;
168 pps_sdp
->pps_payload
.nfl_bpg_offset
=
169 cpu_to_be16(dsc_cfg
->nfl_bpg_offset
);
172 pps_sdp
->pps_payload
.slice_bpg_offset
=
173 cpu_to_be16(dsc_cfg
->slice_bpg_offset
);
176 pps_sdp
->pps_payload
.initial_offset
=
177 cpu_to_be16(dsc_cfg
->initial_offset
);
180 pps_sdp
->pps_payload
.final_offset
= cpu_to_be16(dsc_cfg
->final_offset
);
183 pps_sdp
->pps_payload
.flatness_min_qp
= dsc_cfg
->flatness_min_qp
;
186 pps_sdp
->pps_payload
.flatness_max_qp
= dsc_cfg
->flatness_max_qp
;
189 pps_sdp
->pps_payload
.rc_model_size
=
190 cpu_to_be16(DSC_RC_MODEL_SIZE_CONST
);
193 pps_sdp
->pps_payload
.rc_edge_factor
= DSC_RC_EDGE_FACTOR_CONST
;
196 pps_sdp
->pps_payload
.rc_quant_incr_limit0
=
197 dsc_cfg
->rc_quant_incr_limit0
;
200 pps_sdp
->pps_payload
.rc_quant_incr_limit1
=
201 dsc_cfg
->rc_quant_incr_limit1
;
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
;
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
];
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]
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
]);
229 pps_sdp
->pps_payload
.native_422_420
= dsc_cfg
->native_422
|
230 dsc_cfg
->native_420
<< DSC_PPS_NATIVE_420_SHIFT
;
233 pps_sdp
->pps_payload
.second_line_bpg_offset
=
234 dsc_cfg
->second_line_bpg_offset
;
237 pps_sdp
->pps_payload
.nsl_bpg_offset
=
238 cpu_to_be16(dsc_cfg
->nsl_bpg_offset
);
241 pps_sdp
->pps_payload
.second_line_offset_adj
=
242 cpu_to_be16(dsc_cfg
->second_line_offset_adj
);
244 /* PPS 94 - 127 are O */
246 EXPORT_SYMBOL(drm_dsc_pps_infoframe_pack
);