2 * Copyright 2012-17 Advanced Micro Devices, Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
26 #include <drm/drm_dsc.h>
27 #include "dscc_types.h"
30 double dsc_ceil(double num
);
32 static void copy_pps_fields(struct drm_dsc_config
*to
, const struct drm_dsc_config
*from
)
34 to
->line_buf_depth
= from
->line_buf_depth
;
35 to
->bits_per_component
= from
->bits_per_component
;
36 to
->convert_rgb
= from
->convert_rgb
;
37 to
->slice_width
= from
->slice_width
;
38 to
->slice_height
= from
->slice_height
;
39 to
->simple_422
= from
->simple_422
;
40 to
->native_422
= from
->native_422
;
41 to
->native_420
= from
->native_420
;
42 to
->pic_width
= from
->pic_width
;
43 to
->pic_height
= from
->pic_height
;
44 to
->rc_tgt_offset_high
= from
->rc_tgt_offset_high
;
45 to
->rc_tgt_offset_low
= from
->rc_tgt_offset_low
;
46 to
->bits_per_pixel
= from
->bits_per_pixel
;
47 to
->rc_edge_factor
= from
->rc_edge_factor
;
48 to
->rc_quant_incr_limit1
= from
->rc_quant_incr_limit1
;
49 to
->rc_quant_incr_limit0
= from
->rc_quant_incr_limit0
;
50 to
->initial_xmit_delay
= from
->initial_xmit_delay
;
51 to
->initial_dec_delay
= from
->initial_dec_delay
;
52 to
->block_pred_enable
= from
->block_pred_enable
;
53 to
->first_line_bpg_offset
= from
->first_line_bpg_offset
;
54 to
->second_line_bpg_offset
= from
->second_line_bpg_offset
;
55 to
->initial_offset
= from
->initial_offset
;
56 memcpy(&to
->rc_buf_thresh
, &from
->rc_buf_thresh
, sizeof(from
->rc_buf_thresh
));
57 memcpy(&to
->rc_range_params
, &from
->rc_range_params
, sizeof(from
->rc_range_params
));
58 to
->rc_model_size
= from
->rc_model_size
;
59 to
->flatness_min_qp
= from
->flatness_min_qp
;
60 to
->flatness_max_qp
= from
->flatness_max_qp
;
61 to
->initial_scale_value
= from
->initial_scale_value
;
62 to
->scale_decrement_interval
= from
->scale_decrement_interval
;
63 to
->scale_increment_interval
= from
->scale_increment_interval
;
64 to
->nfl_bpg_offset
= from
->nfl_bpg_offset
;
65 to
->nsl_bpg_offset
= from
->nsl_bpg_offset
;
66 to
->slice_bpg_offset
= from
->slice_bpg_offset
;
67 to
->final_offset
= from
->final_offset
;
68 to
->vbr_enable
= from
->vbr_enable
;
69 to
->slice_chunk_size
= from
->slice_chunk_size
;
70 to
->second_line_offset_adj
= from
->second_line_offset_adj
;
71 to
->dsc_version_minor
= from
->dsc_version_minor
;
74 static void copy_rc_to_cfg(struct drm_dsc_config
*dsc_cfg
, const struct rc_params
*rc
)
78 dsc_cfg
->rc_quant_incr_limit0
= rc
->rc_quant_incr_limit0
;
79 dsc_cfg
->rc_quant_incr_limit1
= rc
->rc_quant_incr_limit1
;
80 dsc_cfg
->initial_offset
= rc
->initial_fullness_offset
;
81 dsc_cfg
->initial_xmit_delay
= rc
->initial_xmit_delay
;
82 dsc_cfg
->first_line_bpg_offset
= rc
->first_line_bpg_offset
;
83 dsc_cfg
->second_line_bpg_offset
= rc
->second_line_bpg_offset
;
84 dsc_cfg
->flatness_min_qp
= rc
->flatness_min_qp
;
85 dsc_cfg
->flatness_max_qp
= rc
->flatness_max_qp
;
86 for (i
= 0; i
< QP_SET_SIZE
; ++i
) {
87 dsc_cfg
->rc_range_params
[i
].range_min_qp
= rc
->qp_min
[i
];
88 dsc_cfg
->rc_range_params
[i
].range_max_qp
= rc
->qp_max
[i
];
89 /* Truncate 8-bit signed value to 6-bit signed value */
90 dsc_cfg
->rc_range_params
[i
].range_bpg_offset
= 0x3f & rc
->ofs
[i
];
92 dsc_cfg
->rc_model_size
= rc
->rc_model_size
;
93 dsc_cfg
->rc_edge_factor
= rc
->rc_edge_factor
;
94 dsc_cfg
->rc_tgt_offset_high
= rc
->rc_tgt_offset_hi
;
95 dsc_cfg
->rc_tgt_offset_low
= rc
->rc_tgt_offset_lo
;
97 for (i
= 0; i
< QP_SET_SIZE
- 1; ++i
)
98 dsc_cfg
->rc_buf_thresh
[i
] = rc
->rc_buf_thresh
[i
];
101 int dscc_compute_dsc_parameters(const struct drm_dsc_config
*pps
, struct dsc_parameters
*dsc_params
)
103 enum colour_mode mode
= pps
->convert_rgb
? CM_RGB
:
104 (pps
->simple_422
? CM_444
:
105 (pps
->native_422
? CM_422
:
106 pps
->native_420
? CM_420
: CM_444
));
107 enum bits_per_comp bpc
= (pps
->bits_per_component
== 8) ? BPC_8
:
108 (pps
->bits_per_component
== 10) ? BPC_10
: BPC_12
;
109 float bpp
= ((float) pps
->bits_per_pixel
/ 16.0);
110 int slice_width
= pps
->slice_width
;
111 int slice_height
= pps
->slice_height
;
114 struct drm_dsc_config dsc_cfg
;
116 double d_bytes_per_pixel
= dsc_ceil(bpp
* slice_width
/ 8.0) / slice_width
;
118 // TODO: Make sure the formula for calculating this is precise (ceiling vs. floor, and at what point they should be applied)
119 if (pps
->native_422
|| pps
->native_420
)
120 d_bytes_per_pixel
/= 2;
122 dsc_params
->bytes_per_pixel
= (uint32_t)dsc_ceil(d_bytes_per_pixel
* 0x10000000);
124 /* in native_422 or native_420 modes, the bits_per_pixel is double the target bpp
125 * (the latter is what calc_rc_params expects)
127 if (pps
->native_422
|| pps
->native_420
)
130 calc_rc_params(&rc
, mode
, bpc
, bpp
, slice_width
, slice_height
, pps
->dsc_version_minor
);
131 dsc_params
->pps
= *pps
;
132 dsc_params
->pps
.initial_scale_value
= 8 * rc
.rc_model_size
/ (rc
.rc_model_size
- rc
.initial_fullness_offset
);
134 copy_pps_fields(&dsc_cfg
, &dsc_params
->pps
);
135 copy_rc_to_cfg(&dsc_cfg
, &rc
);
137 dsc_cfg
.mux_word_size
= dsc_params
->pps
.bits_per_component
<= 10 ? 48 : 64;
139 ret
= drm_dsc_compute_rc_parameters(&dsc_cfg
);
141 copy_pps_fields(&dsc_params
->pps
, &dsc_cfg
);
142 dsc_params
->rc_buffer_model_size
= dsc_cfg
.rc_bits
;