1 /* Copyright 2022 Advanced Micro Devices, Inc.
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining a
4 * copy of this software and associated documentation files (the "Software"),
5 * to deal in the Software without restriction, including without limitation
6 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
7 * and/or sell copies of the Software, and to permit persons to whom the
8 * Software is furnished to do so, subject to the following conditions:
9 *
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
16 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
17 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
18 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
19 * OTHER DEALINGS IN THE SOFTWARE.
20 *
21 * Authors: AMD
22 *
23 */
24
25 #include <string.h>
26 #include "common.h"
27 #include "vpe_priv.h"
28 #include "vpe10_opp.h"
29 #include "hw_shared.h"
30 #include "reg_helper.h"
31
32 #define CTX_BASE opp
33 #define CTX vpe10_opp
34
35 static struct opp_funcs opp_funcs = {
36 .program_pipe_alpha = vpe10_opp_program_pipe_alpha,
37 .program_pipe_bypass = vpe10_opp_program_pipe_bypass,
38 .program_pipe_crc = vpe10_opp_program_pipe_crc,
39 .set_clamping = vpe10_opp_set_clamping,
40 .set_truncation = vpe10_opp_set_truncation,
41 .set_spatial_dither = vpe10_opp_set_spatial_dither,
42 .program_bit_depth_reduction = vpe10_opp_program_bit_depth_reduction,
43 .set_dyn_expansion = vpe10_opp_set_dyn_expansion,
44 .program_fmt = vpe10_opp_program_fmt,
45 };
46
vpe10_construct_opp(struct vpe_priv * vpe_priv,struct opp * opp)47 void vpe10_construct_opp(struct vpe_priv *vpe_priv, struct opp *opp)
48 {
49 opp->vpe_priv = vpe_priv;
50 opp->funcs = &opp_funcs;
51 }
52
vpe10_opp_set_clamping(struct opp * opp,const struct clamping_and_pixel_encoding_params * params)53 void vpe10_opp_set_clamping(
54 struct opp *opp, const struct clamping_and_pixel_encoding_params *params)
55 {
56 PROGRAM_ENTRY();
57
58 //OCSC operations are handled in output gamma sequence to allow
59 // full range bg color fill. Hence, no clamping should be done on the output.
60 switch (params->clamping_level) {
61 case CLAMPING_LIMITED_RANGE_8BPC:
62 case CLAMPING_LIMITED_RANGE_10BPC:
63 case CLAMPING_LIMITED_RANGE_12BPC:
64 case CLAMPING_LIMITED_RANGE_PROGRAMMABLE:
65 case CLAMPING_FULL_RANGE:
66 default:
67 REG_SET_2(VPFMT_CLAMP_CNTL, 0, VPFMT_CLAMP_DATA_EN, 0, VPFMT_CLAMP_COLOR_FORMAT, 0);
68 break;
69 }
70 }
71
vpe10_opp_set_dyn_expansion(struct opp * opp,bool enable,enum color_depth color_dpth)72 void vpe10_opp_set_dyn_expansion(struct opp *opp, bool enable, enum color_depth color_dpth)
73 {
74 PROGRAM_ENTRY();
75
76 if (!enable) {
77 REG_SET_2(VPFMT_DYNAMIC_EXP_CNTL, 0, VPFMT_DYNAMIC_EXP_EN, 0, VPFMT_DYNAMIC_EXP_MODE, 0);
78 return;
79 }
80
81 /*00 - 10-bit -> 12-bit dynamic expansion*/
82 /*01 - 8-bit -> 12-bit dynamic expansion*/
83 switch (color_dpth) {
84 case COLOR_DEPTH_888:
85 REG_SET_2(VPFMT_DYNAMIC_EXP_CNTL, 0, VPFMT_DYNAMIC_EXP_EN, 1, VPFMT_DYNAMIC_EXP_MODE, 1);
86 break;
87 case COLOR_DEPTH_101010:
88 REG_SET_2(VPFMT_DYNAMIC_EXP_CNTL, 0, VPFMT_DYNAMIC_EXP_EN, 1, VPFMT_DYNAMIC_EXP_MODE, 0);
89 break;
90 case COLOR_DEPTH_121212:
91 REG_SET_2(VPFMT_DYNAMIC_EXP_CNTL, 0, VPFMT_DYNAMIC_EXP_EN,
92 1, /*otherwise last two bits are zero*/
93 VPFMT_DYNAMIC_EXP_MODE, 0);
94 break;
95 default:
96 REG_SET_2(VPFMT_DYNAMIC_EXP_CNTL, 0, VPFMT_DYNAMIC_EXP_EN, 0, VPFMT_DYNAMIC_EXP_MODE, 0);
97 break;
98 }
99 }
100
vpe10_opp_set_truncation(struct opp * opp,const struct bit_depth_reduction_params * params)101 void vpe10_opp_set_truncation(struct opp *opp, const struct bit_depth_reduction_params *params)
102 {
103 PROGRAM_ENTRY();
104
105 REG_UPDATE_3(VPFMT_BIT_DEPTH_CONTROL, VPFMT_TRUNCATE_EN, params->flags.TRUNCATE_ENABLED,
106 VPFMT_TRUNCATE_DEPTH, params->flags.TRUNCATE_DEPTH, VPFMT_TRUNCATE_MODE,
107 params->flags.TRUNCATE_MODE);
108 }
109
vpe10_opp_set_spatial_dither(struct opp * opp,const struct bit_depth_reduction_params * params)110 void vpe10_opp_set_spatial_dither(struct opp *opp, const struct bit_depth_reduction_params *params)
111 {
112 PROGRAM_ENTRY();
113
114 /*Disable spatial (random) dithering*/
115 REG_UPDATE_6(VPFMT_BIT_DEPTH_CONTROL, VPFMT_SPATIAL_DITHER_EN, 0, VPFMT_SPATIAL_DITHER_MODE, 0,
116 VPFMT_SPATIAL_DITHER_DEPTH, 0, VPFMT_HIGHPASS_RANDOM_ENABLE, 0, VPFMT_FRAME_RANDOM_ENABLE,
117 0, VPFMT_RGB_RANDOM_ENABLE, 0);
118
119 if (params->flags.SPATIAL_DITHER_ENABLED == 0)
120 return;
121
122 /* only use FRAME_COUNTER_MAX if frameRandom == 1*/
123 if (params->flags.FRAME_RANDOM == 1) {
124 if (params->flags.SPATIAL_DITHER_DEPTH == 0 || params->flags.SPATIAL_DITHER_DEPTH == 1) {
125 REG_UPDATE_2(VPFMT_CONTROL, VPFMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 15,
126 VPFMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 2);
127 } else if (params->flags.SPATIAL_DITHER_DEPTH == 2) {
128 REG_UPDATE_2(VPFMT_CONTROL, VPFMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 3,
129 VPFMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 1);
130 } else
131 return;
132 } else {
133 REG_UPDATE_2(VPFMT_CONTROL, VPFMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 0,
134 VPFMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 0);
135 }
136
137 /* Set seed for random values for
138 * spatial dithering for R,G,B channels
139 */
140 REG_SET(VPFMT_DITHER_RAND_R_SEED, 0, VPFMT_RAND_R_SEED, params->r_seed_value);
141
142 REG_SET(VPFMT_DITHER_RAND_G_SEED, 0, VPFMT_RAND_G_SEED, params->g_seed_value);
143
144 REG_SET(VPFMT_DITHER_RAND_B_SEED, 0, VPFMT_RAND_B_SEED, params->b_seed_value);
145
146 /* FMT_OFFSET_R_Cr 31:16 0x0 Setting the zero
147 * offset for the R/Cr channel, lower 4LSB
148 * is forced to zeros. Typically set to 0
149 * RGB and 0x80000 YCbCr.
150 */
151 /* FMT_OFFSET_G_Y 31:16 0x0 Setting the zero
152 * offset for the G/Y channel, lower 4LSB is
153 * forced to zeros. Typically set to 0 RGB
154 * and 0x80000 YCbCr.
155 */
156 /* FMT_OFFSET_B_Cb 31:16 0x0 Setting the zero
157 * offset for the B/Cb channel, lower 4LSB is
158 * forced to zeros. Typically set to 0 RGB and
159 * 0x80000 YCbCr.
160 */
161
162 REG_UPDATE_6(VPFMT_BIT_DEPTH_CONTROL,
163 /*Enable spatial dithering*/
164 VPFMT_SPATIAL_DITHER_EN, params->flags.SPATIAL_DITHER_ENABLED,
165 /* Set spatial dithering mode
166 * (default is Seed patterrn AAAA...)
167 */
168 VPFMT_SPATIAL_DITHER_MODE, params->flags.SPATIAL_DITHER_MODE,
169 /*Set spatial dithering bit depth*/
170 VPFMT_SPATIAL_DITHER_DEPTH, params->flags.SPATIAL_DITHER_DEPTH,
171 /*Disable High pass filter*/
172 VPFMT_HIGHPASS_RANDOM_ENABLE, params->flags.HIGHPASS_RANDOM,
173 /*Reset only at startup*/
174 VPFMT_FRAME_RANDOM_ENABLE, params->flags.FRAME_RANDOM,
175 /*Set RGB data dithered with x^28+x^3+1*/
176 VPFMT_RGB_RANDOM_ENABLE, params->flags.RGB_RANDOM);
177 }
178
vpe10_opp_program_bit_depth_reduction(struct opp * opp,const struct bit_depth_reduction_params * fmt_bit_depth)179 void vpe10_opp_program_bit_depth_reduction(
180 struct opp *opp, const struct bit_depth_reduction_params *fmt_bit_depth)
181 {
182 opp->funcs->set_truncation(opp, fmt_bit_depth);
183 opp->funcs->set_spatial_dither(opp, fmt_bit_depth);
184 }
185
vpe10_opp_program_fmt(struct opp * opp,struct bit_depth_reduction_params * fmt_bit_depth,struct clamping_and_pixel_encoding_params * clamping)186 void vpe10_opp_program_fmt(struct opp *opp, struct bit_depth_reduction_params *fmt_bit_depth,
187 struct clamping_and_pixel_encoding_params *clamping)
188 {
189 opp->funcs->program_bit_depth_reduction(opp, fmt_bit_depth);
190 opp->funcs->set_clamping(opp, clamping);
191 }
192
vpe10_opp_program_pipe_alpha(struct opp * opp,uint16_t alpha)193 void vpe10_opp_program_pipe_alpha(struct opp *opp, uint16_t alpha)
194 {
195 PROGRAM_ENTRY();
196 REG_UPDATE(VPOPP_PIPE_CONTROL, VPOPP_PIPE_ALPHA, alpha);
197 }
198
vpe10_opp_program_pipe_bypass(struct opp * opp,bool enable)199 void vpe10_opp_program_pipe_bypass(struct opp *opp, bool enable)
200 {
201 PROGRAM_ENTRY();
202 REG_UPDATE(VPOPP_PIPE_CONTROL, VPOPP_PIPE_DIGITAL_BYPASS_EN, enable);
203 }
204
vpe10_opp_program_pipe_crc(struct opp * opp,bool enable)205 void vpe10_opp_program_pipe_crc(struct opp *opp, bool enable)
206 {
207 PROGRAM_ENTRY();
208 REG_UPDATE(VPOPP_PIPE_CRC_CONTROL, VPOPP_PIPE_CRC_EN, enable);
209 }
210
211