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 "vpe10_command.h"
30 #include "hw_shared.h"
31 #include "reg_helper.h"
32
33 #define CTX_BASE opp
34 #define CTX vpe10_opp
35
36 static struct opp_funcs opp_funcs = {
37 .program_pipe_alpha = vpe10_opp_program_pipe_alpha,
38 .program_pipe_bypass = vpe10_opp_program_pipe_bypass,
39 .program_pipe_crc = vpe10_opp_program_pipe_crc,
40 .set_clamping = vpe10_opp_set_clamping,
41 .set_truncation = vpe10_opp_set_truncation,
42 .set_spatial_dither = vpe10_opp_set_spatial_dither,
43 .program_bit_depth_reduction = vpe10_opp_program_bit_depth_reduction,
44 .set_dyn_expansion = vpe10_opp_set_dyn_expansion,
45 .program_fmt = vpe10_opp_program_fmt,
46 };
47
vpe10_construct_opp(struct vpe_priv * vpe_priv,struct opp * opp)48 void vpe10_construct_opp(struct vpe_priv *vpe_priv, struct opp *opp)
49 {
50 opp->vpe_priv = vpe_priv;
51 opp->funcs = &opp_funcs;
52 }
53
vpe10_opp_set_clamping(struct opp * opp,const struct clamping_and_pixel_encoding_params * params)54 void vpe10_opp_set_clamping(
55 struct opp *opp, const struct clamping_and_pixel_encoding_params *params)
56 {
57 PROGRAM_ENTRY();
58
59 //OCSC operations are handled in output gamma sequence to allow
60 // full range bg color fill. Hence, no clamping should be done on the output.
61 switch (params->clamping_level) {
62 case CLAMPING_LIMITED_RANGE_8BPC:
63 case CLAMPING_LIMITED_RANGE_10BPC:
64 case CLAMPING_LIMITED_RANGE_12BPC:
65 case CLAMPING_LIMITED_RANGE_PROGRAMMABLE:
66 case CLAMPING_FULL_RANGE:
67 default:
68 REG_SET_2(VPFMT_CLAMP_CNTL, 0, VPFMT_CLAMP_DATA_EN, 0, VPFMT_CLAMP_COLOR_FORMAT, 0);
69 break;
70 }
71 }
72
vpe10_opp_set_dyn_expansion(struct opp * opp,bool enable,enum color_depth color_dpth)73 void vpe10_opp_set_dyn_expansion(struct opp *opp, bool enable, enum color_depth color_dpth)
74 {
75 PROGRAM_ENTRY();
76
77 if (!enable) {
78 REG_SET_2(VPFMT_DYNAMIC_EXP_CNTL, 0, VPFMT_DYNAMIC_EXP_EN, 0, VPFMT_DYNAMIC_EXP_MODE, 0);
79 return;
80 }
81
82 /*00 - 10-bit -> 12-bit dynamic expansion*/
83 /*01 - 8-bit -> 12-bit dynamic expansion*/
84 switch (color_dpth) {
85 case COLOR_DEPTH_888:
86 REG_SET_2(VPFMT_DYNAMIC_EXP_CNTL, 0, VPFMT_DYNAMIC_EXP_EN, 1, VPFMT_DYNAMIC_EXP_MODE, 1);
87 break;
88 case COLOR_DEPTH_101010:
89 REG_SET_2(VPFMT_DYNAMIC_EXP_CNTL, 0, VPFMT_DYNAMIC_EXP_EN, 1, VPFMT_DYNAMIC_EXP_MODE, 0);
90 break;
91 case COLOR_DEPTH_121212:
92 REG_SET_2(VPFMT_DYNAMIC_EXP_CNTL, 0, VPFMT_DYNAMIC_EXP_EN,
93 1, /*otherwise last two bits are zero*/
94 VPFMT_DYNAMIC_EXP_MODE, 0);
95 break;
96 default:
97 REG_SET_2(VPFMT_DYNAMIC_EXP_CNTL, 0, VPFMT_DYNAMIC_EXP_EN, 0, VPFMT_DYNAMIC_EXP_MODE, 0);
98 break;
99 }
100 }
101
vpe10_opp_set_truncation(struct opp * opp,const struct bit_depth_reduction_params * params)102 void vpe10_opp_set_truncation(struct opp *opp, const struct bit_depth_reduction_params *params)
103 {
104 PROGRAM_ENTRY();
105
106 REG_UPDATE_3(VPFMT_BIT_DEPTH_CONTROL, VPFMT_TRUNCATE_EN, params->flags.TRUNCATE_ENABLED,
107 VPFMT_TRUNCATE_DEPTH, params->flags.TRUNCATE_DEPTH, VPFMT_TRUNCATE_MODE,
108 params->flags.TRUNCATE_MODE);
109 }
110
vpe10_opp_set_spatial_dither(struct opp * opp,const struct bit_depth_reduction_params * params)111 void vpe10_opp_set_spatial_dither(struct opp *opp, const struct bit_depth_reduction_params *params)
112 {
113 PROGRAM_ENTRY();
114
115 /*Disable spatial (random) dithering*/
116 REG_UPDATE_6(VPFMT_BIT_DEPTH_CONTROL, VPFMT_SPATIAL_DITHER_EN, 0, VPFMT_SPATIAL_DITHER_MODE, 0,
117 VPFMT_SPATIAL_DITHER_DEPTH, 0, VPFMT_HIGHPASS_RANDOM_ENABLE, 0, VPFMT_FRAME_RANDOM_ENABLE,
118 0, VPFMT_RGB_RANDOM_ENABLE, 0);
119
120 if (params->flags.SPATIAL_DITHER_ENABLED == 0)
121 return;
122
123 /* only use FRAME_COUNTER_MAX if frameRandom == 1*/
124 if (params->flags.FRAME_RANDOM == 1) {
125 if (params->flags.SPATIAL_DITHER_DEPTH == 0 || params->flags.SPATIAL_DITHER_DEPTH == 1) {
126 REG_UPDATE_2(VPFMT_CONTROL, VPFMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 15,
127 VPFMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 2);
128 } else if (params->flags.SPATIAL_DITHER_DEPTH == 2) {
129 REG_UPDATE_2(VPFMT_CONTROL, VPFMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 3,
130 VPFMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 1);
131 } else
132 return;
133 } else {
134 REG_UPDATE_2(VPFMT_CONTROL, VPFMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, 0,
135 VPFMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, 0);
136 }
137
138 /* Set seed for random values for
139 * spatial dithering for R,G,B channels
140 */
141 REG_SET(VPFMT_DITHER_RAND_R_SEED, 0, VPFMT_RAND_R_SEED, params->r_seed_value);
142
143 REG_SET(VPFMT_DITHER_RAND_G_SEED, 0, VPFMT_RAND_G_SEED, params->g_seed_value);
144
145 REG_SET(VPFMT_DITHER_RAND_B_SEED, 0, VPFMT_RAND_B_SEED, params->b_seed_value);
146
147 /* FMT_OFFSET_R_Cr 31:16 0x0 Setting the zero
148 * offset for the R/Cr channel, lower 4LSB
149 * is forced to zeros. Typically set to 0
150 * RGB and 0x80000 YCbCr.
151 */
152 /* FMT_OFFSET_G_Y 31:16 0x0 Setting the zero
153 * offset for the G/Y channel, lower 4LSB is
154 * forced to zeros. Typically set to 0 RGB
155 * and 0x80000 YCbCr.
156 */
157 /* FMT_OFFSET_B_Cb 31:16 0x0 Setting the zero
158 * offset for the B/Cb channel, lower 4LSB is
159 * forced to zeros. Typically set to 0 RGB and
160 * 0x80000 YCbCr.
161 */
162
163 REG_UPDATE_6(VPFMT_BIT_DEPTH_CONTROL,
164 /*Enable spatial dithering*/
165 VPFMT_SPATIAL_DITHER_EN, params->flags.SPATIAL_DITHER_ENABLED,
166 /* Set spatial dithering mode
167 * (default is Seed patterrn AAAA...)
168 */
169 VPFMT_SPATIAL_DITHER_MODE, params->flags.SPATIAL_DITHER_MODE,
170 /*Set spatial dithering bit depth*/
171 VPFMT_SPATIAL_DITHER_DEPTH, params->flags.SPATIAL_DITHER_DEPTH,
172 /*Disable High pass filter*/
173 VPFMT_HIGHPASS_RANDOM_ENABLE, params->flags.HIGHPASS_RANDOM,
174 /*Reset only at startup*/
175 VPFMT_FRAME_RANDOM_ENABLE, params->flags.FRAME_RANDOM,
176 /*Set RGB data dithered with x^28+x^3+1*/
177 VPFMT_RGB_RANDOM_ENABLE, params->flags.RGB_RANDOM);
178 }
179
vpe10_opp_program_bit_depth_reduction(struct opp * opp,const struct bit_depth_reduction_params * fmt_bit_depth)180 void vpe10_opp_program_bit_depth_reduction(
181 struct opp *opp, const struct bit_depth_reduction_params *fmt_bit_depth)
182 {
183 opp->funcs->set_truncation(opp, fmt_bit_depth);
184 opp->funcs->set_spatial_dither(opp, fmt_bit_depth);
185 }
186
vpe10_opp_program_fmt(struct opp * opp,struct bit_depth_reduction_params * fmt_bit_depth,struct clamping_and_pixel_encoding_params * clamping)187 void vpe10_opp_program_fmt(struct opp *opp, struct bit_depth_reduction_params *fmt_bit_depth,
188 struct clamping_and_pixel_encoding_params *clamping)
189 {
190 opp->funcs->program_bit_depth_reduction(opp, fmt_bit_depth);
191 opp->funcs->set_clamping(opp, clamping);
192 }
193
vpe10_opp_program_pipe_alpha(struct opp * opp,uint16_t alpha)194 void vpe10_opp_program_pipe_alpha(struct opp *opp, uint16_t alpha)
195 {
196 PROGRAM_ENTRY();
197 REG_UPDATE(VPOPP_PIPE_CONTROL, VPOPP_PIPE_ALPHA, alpha);
198 }
199
vpe10_opp_program_pipe_bypass(struct opp * opp,bool enable)200 void vpe10_opp_program_pipe_bypass(struct opp *opp, bool enable)
201 {
202 PROGRAM_ENTRY();
203 REG_UPDATE(VPOPP_PIPE_CONTROL, VPOPP_PIPE_DIGITAL_BYPASS_EN, enable);
204 }
205
vpe10_opp_program_pipe_crc(struct opp * opp,bool enable)206 void vpe10_opp_program_pipe_crc(struct opp *opp, bool enable)
207 {
208 PROGRAM_ENTRY();
209 REG_UPDATE(VPOPP_PIPE_CRC_CONTROL, VPOPP_PIPE_CRC_EN, enable);
210 }
211
212