1 /*
2 * Copyright 2012-15 Advanced Micro Devices, Inc.
3 *
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:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
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.
21 *
22 * Authors: AMD
23 *
24 */
25
26 #include "core_types.h"
27 #include "dm_services.h"
28 #include "dcn20_opp.h"
29 #include "reg_helper.h"
30
31 #define REG(reg) \
32 (oppn20->regs->reg)
33
34 #undef FN
35 #define FN(reg_name, field_name) \
36 oppn20->opp_shift->field_name, oppn20->opp_mask->field_name
37
38 #define CTX \
39 oppn20->base.ctx
40
41
opp2_set_disp_pattern_generator(struct output_pixel_processor * opp,enum controller_dp_test_pattern test_pattern,enum controller_dp_color_space color_space,enum dc_color_depth color_depth,const struct tg_color * solid_color,int width,int height,int offset)42 void opp2_set_disp_pattern_generator(
43 struct output_pixel_processor *opp,
44 enum controller_dp_test_pattern test_pattern,
45 enum controller_dp_color_space color_space,
46 enum dc_color_depth color_depth,
47 const struct tg_color *solid_color,
48 int width,
49 int height,
50 int offset)
51 {
52 struct dcn20_opp *oppn20 = TO_DCN20_OPP(opp);
53 enum test_pattern_color_format bit_depth;
54 enum test_pattern_dyn_range dyn_range;
55 enum test_pattern_mode mode;
56
57 /* color ramp generator mixes 16-bits color */
58 uint32_t src_bpc = 16;
59 /* requested bpc */
60 uint32_t dst_bpc;
61 uint32_t index;
62 /* RGB values of the color bars.
63 * Produce two RGB colors: RGB0 - white (all Fs)
64 * and RGB1 - black (all 0s)
65 * (three RGB components for two colors)
66 */
67 uint16_t src_color[6] = {0xFFFF, 0xFFFF, 0xFFFF, 0x0000,
68 0x0000, 0x0000};
69 /* dest color (converted to the specified color format) */
70 uint16_t dst_color[6];
71 uint32_t inc_base;
72
73 /* translate to bit depth */
74 switch (color_depth) {
75 case COLOR_DEPTH_666:
76 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_6;
77 break;
78 case COLOR_DEPTH_888:
79 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
80 break;
81 case COLOR_DEPTH_101010:
82 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_10;
83 break;
84 case COLOR_DEPTH_121212:
85 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_12;
86 break;
87 default:
88 bit_depth = TEST_PATTERN_COLOR_FORMAT_BPC_8;
89 break;
90 }
91
92 /* set DPG dimentions */
93 REG_SET_2(DPG_DIMENSIONS, 0,
94 DPG_ACTIVE_WIDTH, width,
95 DPG_ACTIVE_HEIGHT, height);
96
97 /* set DPG offset */
98 REG_SET_2(DPG_OFFSET_SEGMENT, 0,
99 DPG_X_OFFSET, offset,
100 DPG_SEGMENT_WIDTH, 0);
101
102 switch (test_pattern) {
103 case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES:
104 case CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA:
105 {
106 dyn_range = (test_pattern ==
107 CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA ?
108 TEST_PATTERN_DYN_RANGE_CEA :
109 TEST_PATTERN_DYN_RANGE_VESA);
110
111 switch (color_space) {
112 case CONTROLLER_DP_COLOR_SPACE_YCBCR601:
113 mode = TEST_PATTERN_MODE_COLORSQUARES_YCBCR601;
114 break;
115 case CONTROLLER_DP_COLOR_SPACE_YCBCR709:
116 mode = TEST_PATTERN_MODE_COLORSQUARES_YCBCR709;
117 break;
118 case CONTROLLER_DP_COLOR_SPACE_RGB:
119 default:
120 mode = TEST_PATTERN_MODE_COLORSQUARES_RGB;
121 break;
122 }
123
124 REG_UPDATE_6(DPG_CONTROL,
125 DPG_EN, 1,
126 DPG_MODE, mode,
127 DPG_DYNAMIC_RANGE, dyn_range,
128 DPG_BIT_DEPTH, bit_depth,
129 DPG_VRES, 6,
130 DPG_HRES, 6);
131 }
132 break;
133
134 case CONTROLLER_DP_TEST_PATTERN_VERTICALBARS:
135 case CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS:
136 {
137 mode = (test_pattern ==
138 CONTROLLER_DP_TEST_PATTERN_VERTICALBARS ?
139 TEST_PATTERN_MODE_VERTICALBARS :
140 TEST_PATTERN_MODE_HORIZONTALBARS);
141
142 switch (bit_depth) {
143 case TEST_PATTERN_COLOR_FORMAT_BPC_6:
144 dst_bpc = 6;
145 break;
146 case TEST_PATTERN_COLOR_FORMAT_BPC_8:
147 dst_bpc = 8;
148 break;
149 case TEST_PATTERN_COLOR_FORMAT_BPC_10:
150 dst_bpc = 10;
151 break;
152 default:
153 dst_bpc = 8;
154 break;
155 }
156
157 /* adjust color to the required colorFormat */
158 for (index = 0; index < 6; index++) {
159 /* dst = 2^dstBpc * src / 2^srcBpc = src >>
160 * (srcBpc - dstBpc);
161 */
162 dst_color[index] =
163 src_color[index] >> (src_bpc - dst_bpc);
164 /* DPG_COLOUR registers are 16-bit MSB aligned value with bits 3:0 hardwired to ZERO.
165 * XXXXXXXXXX000000 for 10 bit,
166 * XXXXXXXX00000000 for 8 bit,
167 * XXXXXX0000000000 for 6 bits
168 */
169 dst_color[index] <<= (16 - dst_bpc);
170 }
171
172 REG_SET_2(DPG_COLOUR_R_CR, 0,
173 DPG_COLOUR1_R_CR, dst_color[0],
174 DPG_COLOUR0_R_CR, dst_color[3]);
175 REG_SET_2(DPG_COLOUR_G_Y, 0,
176 DPG_COLOUR1_G_Y, dst_color[1],
177 DPG_COLOUR0_G_Y, dst_color[4]);
178 REG_SET_2(DPG_COLOUR_B_CB, 0,
179 DPG_COLOUR1_B_CB, dst_color[2],
180 DPG_COLOUR0_B_CB, dst_color[5]);
181
182 /* enable test pattern */
183 REG_UPDATE_6(DPG_CONTROL,
184 DPG_EN, 1,
185 DPG_MODE, mode,
186 DPG_DYNAMIC_RANGE, 0,
187 DPG_BIT_DEPTH, bit_depth,
188 DPG_VRES, 0,
189 DPG_HRES, 0);
190 }
191 break;
192
193 case CONTROLLER_DP_TEST_PATTERN_COLORRAMP:
194 {
195 mode = (bit_depth ==
196 TEST_PATTERN_COLOR_FORMAT_BPC_10 ?
197 TEST_PATTERN_MODE_DUALRAMP_RGB :
198 TEST_PATTERN_MODE_SINGLERAMP_RGB);
199
200 switch (bit_depth) {
201 case TEST_PATTERN_COLOR_FORMAT_BPC_6:
202 dst_bpc = 6;
203 break;
204 case TEST_PATTERN_COLOR_FORMAT_BPC_8:
205 dst_bpc = 8;
206 break;
207 case TEST_PATTERN_COLOR_FORMAT_BPC_10:
208 dst_bpc = 10;
209 break;
210 default:
211 dst_bpc = 8;
212 break;
213 }
214
215 /* increment for the first ramp for one color gradation
216 * 1 gradation for 6-bit color is 2^10
217 * gradations in 16-bit color
218 */
219 inc_base = (src_bpc - dst_bpc);
220
221 switch (bit_depth) {
222 case TEST_PATTERN_COLOR_FORMAT_BPC_6:
223 {
224 REG_SET_3(DPG_RAMP_CONTROL, 0,
225 DPG_RAMP0_OFFSET, 0,
226 DPG_INC0, inc_base,
227 DPG_INC1, 0);
228 REG_UPDATE_2(DPG_CONTROL,
229 DPG_VRES, 6,
230 DPG_HRES, 6);
231 }
232 break;
233 case TEST_PATTERN_COLOR_FORMAT_BPC_8:
234 {
235 REG_SET_3(DPG_RAMP_CONTROL, 0,
236 DPG_RAMP0_OFFSET, 0,
237 DPG_INC0, inc_base,
238 DPG_INC1, 0);
239 REG_UPDATE_2(DPG_CONTROL,
240 DPG_VRES, 6,
241 DPG_HRES, 8);
242 }
243 break;
244 case TEST_PATTERN_COLOR_FORMAT_BPC_10:
245 {
246 REG_SET_3(DPG_RAMP_CONTROL, 0,
247 DPG_RAMP0_OFFSET, 384 << 6,
248 DPG_INC0, inc_base,
249 DPG_INC1, inc_base + 2);
250 REG_UPDATE_2(DPG_CONTROL,
251 DPG_VRES, 5,
252 DPG_HRES, 8);
253 }
254 break;
255 default:
256 break;
257 }
258
259 /* enable test pattern */
260 REG_UPDATE_4(DPG_CONTROL,
261 DPG_EN, 1,
262 DPG_MODE, mode,
263 DPG_DYNAMIC_RANGE, 0,
264 DPG_BIT_DEPTH, bit_depth);
265 }
266 break;
267 case CONTROLLER_DP_TEST_PATTERN_VIDEOMODE:
268 {
269 REG_WRITE(DPG_CONTROL, 0);
270 REG_WRITE(DPG_COLOUR_R_CR, 0);
271 REG_WRITE(DPG_COLOUR_G_Y, 0);
272 REG_WRITE(DPG_COLOUR_B_CB, 0);
273 REG_WRITE(DPG_RAMP_CONTROL, 0);
274 }
275 break;
276 case CONTROLLER_DP_TEST_PATTERN_SOLID_COLOR:
277 {
278 opp2_dpg_set_blank_color(opp, solid_color);
279 REG_UPDATE_2(DPG_CONTROL,
280 DPG_EN, 1,
281 DPG_MODE, TEST_PATTERN_MODE_HORIZONTALBARS);
282
283 REG_SET_2(DPG_DIMENSIONS, 0,
284 DPG_ACTIVE_WIDTH, width,
285 DPG_ACTIVE_HEIGHT, height);
286 }
287 break;
288 default:
289 break;
290
291 }
292 }
293
opp2_program_dpg_dimensions(struct output_pixel_processor * opp,int width,int height)294 void opp2_program_dpg_dimensions(
295 struct output_pixel_processor *opp,
296 int width, int height)
297 {
298 struct dcn20_opp *oppn20 = TO_DCN20_OPP(opp);
299
300 REG_SET_2(DPG_DIMENSIONS, 0,
301 DPG_ACTIVE_WIDTH, width,
302 DPG_ACTIVE_HEIGHT, height);
303 }
304
opp2_dpg_set_blank_color(struct output_pixel_processor * opp,const struct tg_color * color)305 void opp2_dpg_set_blank_color(
306 struct output_pixel_processor *opp,
307 const struct tg_color *color)
308 {
309 struct dcn20_opp *oppn20 = TO_DCN20_OPP(opp);
310
311 /* 16-bit MSB aligned value. Bits 3:0 of this field are hardwired to ZERO */
312 ASSERT(color);
313 REG_SET_2(DPG_COLOUR_B_CB, 0,
314 DPG_COLOUR1_B_CB, color->color_b_cb << 6,
315 DPG_COLOUR0_B_CB, color->color_b_cb << 6);
316 REG_SET_2(DPG_COLOUR_G_Y, 0,
317 DPG_COLOUR1_G_Y, color->color_g_y << 6,
318 DPG_COLOUR0_G_Y, color->color_g_y << 6);
319 REG_SET_2(DPG_COLOUR_R_CR, 0,
320 DPG_COLOUR1_R_CR, color->color_r_cr << 6,
321 DPG_COLOUR0_R_CR, color->color_r_cr << 6);
322 }
323
opp2_dpg_is_blanked(struct output_pixel_processor * opp)324 bool opp2_dpg_is_blanked(struct output_pixel_processor *opp)
325 {
326 struct dcn20_opp *oppn20 = TO_DCN20_OPP(opp);
327 uint32_t dpg_en, dpg_mode;
328 uint32_t double_buffer_pending;
329
330 REG_GET_2(DPG_CONTROL,
331 DPG_EN, &dpg_en,
332 DPG_MODE, &dpg_mode);
333
334 REG_GET(DPG_STATUS,
335 DPG_DOUBLE_BUFFER_PENDING, &double_buffer_pending);
336
337 return (dpg_en == 1) &&
338 (double_buffer_pending == 0);
339 }
340
opp2_dpg_is_pending(struct output_pixel_processor * opp)341 bool opp2_dpg_is_pending(struct output_pixel_processor *opp)
342 {
343 struct dcn20_opp *oppn20 = TO_DCN20_OPP(opp);
344 uint32_t double_buffer_pending;
345 uint32_t dpg_en;
346
347 REG_GET(DPG_CONTROL, DPG_EN, &dpg_en);
348
349 REG_GET(DPG_STATUS, DPG_DOUBLE_BUFFER_PENDING, &double_buffer_pending);
350
351 return (dpg_en == 1 && double_buffer_pending == 1);
352 }
353
opp2_program_left_edge_extra_pixel(struct output_pixel_processor * opp,enum dc_pixel_encoding pixel_encoding,bool is_primary)354 void opp2_program_left_edge_extra_pixel(
355 struct output_pixel_processor *opp,
356 enum dc_pixel_encoding pixel_encoding,
357 bool is_primary)
358 {
359 struct dcn20_opp *oppn20 = TO_DCN20_OPP(opp);
360 uint32_t count = opp2_get_left_edge_extra_pixel_count(opp, pixel_encoding, is_primary);
361
362 /*
363 * Specifies the number of extra left edge pixels that are supplied to
364 * the 422 horizontal chroma sub-sample filter.
365 */
366 REG_UPDATE(FMT_422_CONTROL, FMT_LEFT_EDGE_EXTRA_PIXEL_COUNT, count);
367 }
368
opp2_get_left_edge_extra_pixel_count(struct output_pixel_processor * opp,enum dc_pixel_encoding pixel_encoding,bool is_primary)369 uint32_t opp2_get_left_edge_extra_pixel_count(struct output_pixel_processor *opp,
370 enum dc_pixel_encoding pixel_encoding, bool is_primary)
371 {
372 if ((pixel_encoding == PIXEL_ENCODING_YCBCR422 || pixel_encoding == PIXEL_ENCODING_YCBCR420) &&
373 !opp->ctx->dc->debug.force_chroma_subsampling_1tap &&
374 !is_primary)
375 return 1;
376 else
377 return 0;
378 }
379
380 /*****************************************/
381 /* Constructor, Destructor */
382 /*****************************************/
383
384 static struct opp_funcs dcn20_opp_funcs = {
385 .opp_set_dyn_expansion = opp1_set_dyn_expansion,
386 .opp_program_fmt = opp1_program_fmt,
387 .opp_program_bit_depth_reduction = opp1_program_bit_depth_reduction,
388 .opp_program_stereo = opp1_program_stereo,
389 .opp_pipe_clock_control = opp1_pipe_clock_control,
390 .opp_set_disp_pattern_generator = opp2_set_disp_pattern_generator,
391 .opp_program_dpg_dimensions = opp2_program_dpg_dimensions,
392 .dpg_is_blanked = opp2_dpg_is_blanked,
393 .dpg_is_pending = opp2_dpg_is_pending,
394 .opp_dpg_set_blank_color = opp2_dpg_set_blank_color,
395 .opp_destroy = opp1_destroy,
396 .opp_program_left_edge_extra_pixel = opp2_program_left_edge_extra_pixel,
397 .opp_get_left_edge_extra_pixel_count = opp2_get_left_edge_extra_pixel_count,
398 };
399
dcn20_opp_construct(struct dcn20_opp * oppn20,struct dc_context * ctx,uint32_t inst,const struct dcn20_opp_registers * regs,const struct dcn20_opp_shift * opp_shift,const struct dcn20_opp_mask * opp_mask)400 void dcn20_opp_construct(struct dcn20_opp *oppn20,
401 struct dc_context *ctx,
402 uint32_t inst,
403 const struct dcn20_opp_registers *regs,
404 const struct dcn20_opp_shift *opp_shift,
405 const struct dcn20_opp_mask *opp_mask)
406 {
407 oppn20->base.ctx = ctx;
408 oppn20->base.inst = inst;
409 oppn20->base.funcs = &dcn20_opp_funcs;
410
411 oppn20->regs = regs;
412 oppn20->opp_shift = opp_shift;
413 oppn20->opp_mask = opp_mask;
414 }
415
416