at v6.19 1689 lines 48 kB view raw
1/* 2 * Copyright 2012-16 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 "dce_transform.h" 27#include "reg_helper.h" 28#include "opp.h" 29#include "basics/conversion.h" 30#include "dc.h" 31 32#define REG(reg) \ 33 (xfm_dce->regs->reg) 34 35#undef FN 36#define FN(reg_name, field_name) \ 37 xfm_dce->xfm_shift->field_name, xfm_dce->xfm_mask->field_name 38 39#define CTX \ 40 xfm_dce->base.ctx 41#define DC_LOGGER \ 42 xfm_dce->base.ctx->logger 43 44#define IDENTITY_RATIO(ratio) (dc_fixpt_u2d19(ratio) == (1 << 19)) 45#define GAMUT_MATRIX_SIZE 12 46#define SCL_PHASES 16 47 48enum dcp_out_trunc_round_mode { 49 DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE, 50 DCP_OUT_TRUNC_ROUND_MODE_ROUND 51}; 52 53enum dcp_out_trunc_round_depth { 54 DCP_OUT_TRUNC_ROUND_DEPTH_14BIT, 55 DCP_OUT_TRUNC_ROUND_DEPTH_13BIT, 56 DCP_OUT_TRUNC_ROUND_DEPTH_12BIT, 57 DCP_OUT_TRUNC_ROUND_DEPTH_11BIT, 58 DCP_OUT_TRUNC_ROUND_DEPTH_10BIT, 59 DCP_OUT_TRUNC_ROUND_DEPTH_9BIT, 60 DCP_OUT_TRUNC_ROUND_DEPTH_8BIT 61}; 62 63/* defines the various methods of bit reduction available for use */ 64enum dcp_bit_depth_reduction_mode { 65 DCP_BIT_DEPTH_REDUCTION_MODE_DITHER, 66 DCP_BIT_DEPTH_REDUCTION_MODE_ROUND, 67 DCP_BIT_DEPTH_REDUCTION_MODE_TRUNCATE, 68 DCP_BIT_DEPTH_REDUCTION_MODE_DISABLED, 69 DCP_BIT_DEPTH_REDUCTION_MODE_INVALID 70}; 71 72enum dcp_spatial_dither_mode { 73 DCP_SPATIAL_DITHER_MODE_AAAA, 74 DCP_SPATIAL_DITHER_MODE_A_AA_A, 75 DCP_SPATIAL_DITHER_MODE_AABBAABB, 76 DCP_SPATIAL_DITHER_MODE_AABBCCAABBCC, 77 DCP_SPATIAL_DITHER_MODE_INVALID 78}; 79 80enum dcp_spatial_dither_depth { 81 DCP_SPATIAL_DITHER_DEPTH_30BPP, 82 DCP_SPATIAL_DITHER_DEPTH_24BPP 83}; 84 85enum csc_color_mode { 86 /* 00 - BITS2:0 Bypass */ 87 CSC_COLOR_MODE_GRAPHICS_BYPASS, 88 /* 01 - hard coded coefficient TV RGB */ 89 CSC_COLOR_MODE_GRAPHICS_PREDEFINED, 90 /* 04 - programmable OUTPUT CSC coefficient */ 91 CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC, 92}; 93 94enum grph_color_adjust_option { 95 GRPH_COLOR_MATRIX_HW_DEFAULT = 1, 96 GRPH_COLOR_MATRIX_SW 97}; 98 99static const struct out_csc_color_matrix global_color_matrix[] = { 100{ COLOR_SPACE_SRGB, 101 { 0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} }, 102{ COLOR_SPACE_SRGB_LIMITED, 103 { 0x1B60, 0, 0, 0x200, 0, 0x1B60, 0, 0x200, 0, 0, 0x1B60, 0x200} }, 104{ COLOR_SPACE_YCBCR601, 105 { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x82F, 0x1012, 0x31F, 0x200, 0xFB47, 106 0xF6B9, 0xE00, 0x1000} }, 107{ COLOR_SPACE_YCBCR709, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x5D2, 0x1394, 0x1FA, 108 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} }, 109/* TODO: correct values below */ 110{ COLOR_SPACE_YCBCR601_LIMITED, { 0xE00, 0xF447, 0xFDB9, 0x1000, 0x991, 111 0x12C9, 0x3A6, 0x200, 0xFB47, 0xF6B9, 0xE00, 0x1000} }, 112{ COLOR_SPACE_YCBCR709_LIMITED, { 0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3, 113 0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} } 114}; 115 116static bool setup_scaling_configuration( 117 struct dce_transform *xfm_dce, 118 const struct scaler_data *data) 119{ 120 REG_SET(SCL_BYPASS_CONTROL, 0, SCL_BYPASS_MODE, 0); 121 122 if (data->taps.h_taps + data->taps.v_taps <= 2) { 123 /* Set bypass */ 124 if (xfm_dce->xfm_mask->SCL_PSCL_EN != 0) 125 REG_UPDATE_2(SCL_MODE, SCL_MODE, 0, SCL_PSCL_EN, 0); 126 else 127 REG_UPDATE(SCL_MODE, SCL_MODE, 0); 128 return false; 129 } 130 131 REG_SET_2(SCL_TAP_CONTROL, 0, 132 SCL_H_NUM_OF_TAPS, data->taps.h_taps - 1, 133 SCL_V_NUM_OF_TAPS, data->taps.v_taps - 1); 134 135 if (data->format <= PIXEL_FORMAT_GRPH_END) 136 REG_UPDATE(SCL_MODE, SCL_MODE, 1); 137 else 138 REG_UPDATE(SCL_MODE, SCL_MODE, 2); 139 140 if (xfm_dce->xfm_mask->SCL_PSCL_EN != 0) 141 REG_UPDATE(SCL_MODE, SCL_PSCL_EN, 1); 142 143 /* 1 - Replace out of bound pixels with edge */ 144 REG_SET(SCL_CONTROL, 0, SCL_BOUNDARY_MODE, 1); 145 146 return true; 147} 148 149#if defined(CONFIG_DRM_AMD_DC_SI) 150static bool dce60_setup_scaling_configuration( 151 struct dce_transform *xfm_dce, 152 const struct scaler_data *data) 153{ 154 REG_SET(SCL_BYPASS_CONTROL, 0, SCL_BYPASS_MODE, 0); 155 156 if (data->taps.h_taps + data->taps.v_taps <= 2) { 157 /* Disable scaler functionality */ 158 REG_WRITE(SCL_SCALER_ENABLE, 0); 159 160 /* Clear registers that can cause glitches even when the scaler is off */ 161 REG_WRITE(SCL_TAP_CONTROL, 0); 162 REG_WRITE(SCL_AUTOMATIC_MODE_CONTROL, 0); 163 REG_WRITE(SCL_F_SHARP_CONTROL, 0); 164 return false; 165 } 166 167 REG_SET_2(SCL_TAP_CONTROL, 0, 168 SCL_H_NUM_OF_TAPS, data->taps.h_taps - 1, 169 SCL_V_NUM_OF_TAPS, data->taps.v_taps - 1); 170 171 REG_WRITE(SCL_SCALER_ENABLE, 1); 172 173 /* DCE6 has no SCL_BOUNDARY_MODE bit, skip replace out of bound pixels */ 174 175 return true; 176} 177#endif 178 179static void program_overscan( 180 struct dce_transform *xfm_dce, 181 const struct scaler_data *data) 182{ 183 int overscan_right = data->h_active 184 - data->recout.x - data->recout.width; 185 int overscan_bottom = data->v_active 186 - data->recout.y - data->recout.height; 187 188 if (xfm_dce->base.ctx->dc->debug.visual_confirm != VISUAL_CONFIRM_DISABLE) { 189 overscan_bottom += 2; 190 overscan_right += 2; 191 } 192 193 if (overscan_right < 0) { 194 BREAK_TO_DEBUGGER(); 195 overscan_right = 0; 196 } 197 if (overscan_bottom < 0) { 198 BREAK_TO_DEBUGGER(); 199 overscan_bottom = 0; 200 } 201 202 REG_SET_2(EXT_OVERSCAN_LEFT_RIGHT, 0, 203 EXT_OVERSCAN_LEFT, data->recout.x, 204 EXT_OVERSCAN_RIGHT, overscan_right); 205 REG_SET_2(EXT_OVERSCAN_TOP_BOTTOM, 0, 206 EXT_OVERSCAN_TOP, data->recout.y, 207 EXT_OVERSCAN_BOTTOM, overscan_bottom); 208} 209 210static void program_multi_taps_filter( 211 struct dce_transform *xfm_dce, 212 int taps, 213 const uint16_t *coeffs, 214 enum ram_filter_type filter_type) 215{ 216 int phase, pair; 217 int array_idx = 0; 218 int taps_pairs = (taps + 1) / 2; 219 int phases_to_program = SCL_PHASES / 2 + 1; 220 221 uint32_t power_ctl = 0; 222 223 if (!coeffs) 224 return; 225 226 /*We need to disable power gating on coeff memory to do programming*/ 227 if (REG(DCFE_MEM_PWR_CTRL)) { 228 power_ctl = REG_READ(DCFE_MEM_PWR_CTRL); 229 REG_SET(DCFE_MEM_PWR_CTRL, power_ctl, SCL_COEFF_MEM_PWR_DIS, 1); 230 231 REG_WAIT(DCFE_MEM_PWR_STATUS, SCL_COEFF_MEM_PWR_STATE, 0, 1, 10); 232 } 233 for (phase = 0; phase < phases_to_program; phase++) { 234 /*we always program N/2 + 1 phases, total phases N, but N/2-1 are just mirror 235 phase 0 is unique and phase N/2 is unique if N is even*/ 236 for (pair = 0; pair < taps_pairs; pair++) { 237 uint16_t odd_coeff = 0; 238 uint16_t even_coeff = coeffs[array_idx]; 239 240 REG_SET_3(SCL_COEF_RAM_SELECT, 0, 241 SCL_C_RAM_FILTER_TYPE, filter_type, 242 SCL_C_RAM_PHASE, phase, 243 SCL_C_RAM_TAP_PAIR_IDX, pair); 244 245 if (taps % 2 && pair == taps_pairs - 1) 246 array_idx++; 247 else { 248 odd_coeff = coeffs[array_idx + 1]; 249 array_idx += 2; 250 } 251 252 REG_SET_4(SCL_COEF_RAM_TAP_DATA, 0, 253 SCL_C_RAM_EVEN_TAP_COEF_EN, 1, 254 SCL_C_RAM_EVEN_TAP_COEF, even_coeff, 255 SCL_C_RAM_ODD_TAP_COEF_EN, 1, 256 SCL_C_RAM_ODD_TAP_COEF, odd_coeff); 257 } 258 } 259 260 /*We need to restore power gating on coeff memory to initial state*/ 261 if (REG(DCFE_MEM_PWR_CTRL)) 262 REG_WRITE(DCFE_MEM_PWR_CTRL, power_ctl); 263} 264 265static void program_viewport( 266 struct dce_transform *xfm_dce, 267 const struct rect *view_port) 268{ 269 REG_SET_2(VIEWPORT_START, 0, 270 VIEWPORT_X_START, view_port->x, 271 VIEWPORT_Y_START, view_port->y); 272 273 REG_SET_2(VIEWPORT_SIZE, 0, 274 VIEWPORT_HEIGHT, view_port->height, 275 VIEWPORT_WIDTH, view_port->width); 276 277 /* TODO: add stereo support */ 278} 279 280static void calculate_inits( 281 struct dce_transform *xfm_dce, 282 const struct scaler_data *data, 283 struct scl_ratios_inits *inits) 284{ 285 struct fixed31_32 h_init; 286 struct fixed31_32 v_init; 287 288 inits->h_int_scale_ratio = 289 dc_fixpt_u2d19(data->ratios.horz) << 5; 290 inits->v_int_scale_ratio = 291 dc_fixpt_u2d19(data->ratios.vert) << 5; 292 293 h_init = 294 dc_fixpt_div_int( 295 dc_fixpt_add( 296 data->ratios.horz, 297 dc_fixpt_from_int(data->taps.h_taps + 1)), 298 2); 299 inits->h_init.integer = dc_fixpt_floor(h_init); 300 inits->h_init.fraction = dc_fixpt_u0d19(h_init) << 5; 301 302 v_init = 303 dc_fixpt_div_int( 304 dc_fixpt_add( 305 data->ratios.vert, 306 dc_fixpt_from_int(data->taps.v_taps + 1)), 307 2); 308 inits->v_init.integer = dc_fixpt_floor(v_init); 309 inits->v_init.fraction = dc_fixpt_u0d19(v_init) << 5; 310} 311 312#if defined(CONFIG_DRM_AMD_DC_SI) 313static void dce60_calculate_inits( 314 struct dce_transform *xfm_dce, 315 const struct scaler_data *data, 316 struct sclh_ratios_inits *inits) 317{ 318 struct fixed31_32 v_init; 319 320 inits->h_int_scale_ratio = 321 dc_fixpt_u2d19(data->ratios.horz) << 5; 322 inits->v_int_scale_ratio = 323 dc_fixpt_u2d19(data->ratios.vert) << 5; 324 325 /* DCE6 h_init_luma setting inspired by DCE110 */ 326 inits->h_init_luma.integer = 1; 327 328 /* DCE6 h_init_chroma setting inspired by DCE110 */ 329 inits->h_init_chroma.integer = 1; 330 331 v_init = 332 dc_fixpt_div_int( 333 dc_fixpt_add( 334 data->ratios.vert, 335 dc_fixpt_from_int(data->taps.v_taps + 1)), 336 2); 337 inits->v_init.integer = dc_fixpt_floor(v_init); 338 inits->v_init.fraction = dc_fixpt_u0d19(v_init) << 5; 339} 340#endif 341 342static void program_scl_ratios_inits( 343 struct dce_transform *xfm_dce, 344 struct scl_ratios_inits *inits) 345{ 346 347 REG_SET(SCL_HORZ_FILTER_SCALE_RATIO, 0, 348 SCL_H_SCALE_RATIO, inits->h_int_scale_ratio); 349 350 REG_SET(SCL_VERT_FILTER_SCALE_RATIO, 0, 351 SCL_V_SCALE_RATIO, inits->v_int_scale_ratio); 352 353 REG_SET_2(SCL_HORZ_FILTER_INIT, 0, 354 SCL_H_INIT_INT, inits->h_init.integer, 355 SCL_H_INIT_FRAC, inits->h_init.fraction); 356 357 REG_SET_2(SCL_VERT_FILTER_INIT, 0, 358 SCL_V_INIT_INT, inits->v_init.integer, 359 SCL_V_INIT_FRAC, inits->v_init.fraction); 360 361 REG_WRITE(SCL_AUTOMATIC_MODE_CONTROL, 0); 362} 363 364#if defined(CONFIG_DRM_AMD_DC_SI) 365static void dce60_program_scl_ratios_inits( 366 struct dce_transform *xfm_dce, 367 struct sclh_ratios_inits *inits) 368{ 369 370 REG_SET(SCL_HORZ_FILTER_SCALE_RATIO, 0, 371 SCL_H_SCALE_RATIO, inits->h_int_scale_ratio); 372 373 REG_SET(SCL_VERT_FILTER_SCALE_RATIO, 0, 374 SCL_V_SCALE_RATIO, inits->v_int_scale_ratio); 375 376 /* DCE6 has SCL_HORZ_FILTER_INIT_RGB_LUMA register */ 377 REG_SET_2(SCL_HORZ_FILTER_INIT_RGB_LUMA, 0, 378 SCL_H_INIT_INT_RGB_Y, inits->h_init_luma.integer, 379 SCL_H_INIT_FRAC_RGB_Y, inits->h_init_luma.fraction); 380 381 /* DCE6 has SCL_HORZ_FILTER_INIT_CHROMA register */ 382 REG_SET_2(SCL_HORZ_FILTER_INIT_CHROMA, 0, 383 SCL_H_INIT_INT_CBCR, inits->h_init_chroma.integer, 384 SCL_H_INIT_FRAC_CBCR, inits->h_init_chroma.fraction); 385 386 REG_SET_2(SCL_VERT_FILTER_INIT, 0, 387 SCL_V_INIT_INT, inits->v_init.integer, 388 SCL_V_INIT_FRAC, inits->v_init.fraction); 389 390 REG_WRITE(SCL_AUTOMATIC_MODE_CONTROL, 0); 391} 392#endif 393 394static const uint16_t *get_filter_coeffs_16p(int taps, struct fixed31_32 ratio) 395{ 396 if (taps == 4) 397 return get_filter_4tap_16p(ratio); 398 else if (taps == 3) 399 return get_filter_3tap_16p(ratio); 400 else if (taps == 2) 401 return get_filter_2tap_16p(); 402 else if (taps == 1) 403 return NULL; 404 else { 405 /* should never happen, bug */ 406 BREAK_TO_DEBUGGER(); 407 return NULL; 408 } 409} 410 411static void dce_transform_set_scaler( 412 struct transform *xfm, 413 const struct scaler_data *data) 414{ 415 struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); 416 bool is_scaling_required; 417 bool filter_updated = false; 418 const uint16_t *coeffs_v, *coeffs_h; 419 420 /*Use all three pieces of memory always*/ 421 REG_SET_2(LB_MEMORY_CTRL, 0, 422 LB_MEMORY_CONFIG, 0, 423 LB_MEMORY_SIZE, xfm_dce->lb_memory_size); 424 425 /* Clear SCL_F_SHARP_CONTROL value to 0 */ 426 REG_WRITE(SCL_F_SHARP_CONTROL, 0); 427 428 /* 1. Program overscan */ 429 program_overscan(xfm_dce, data); 430 431 /* 2. Program taps and configuration */ 432 is_scaling_required = setup_scaling_configuration(xfm_dce, data); 433 434 if (is_scaling_required) { 435 /* 3. Calculate and program ratio, filter initialization */ 436 struct scl_ratios_inits inits = { 0 }; 437 438 calculate_inits(xfm_dce, data, &inits); 439 440 program_scl_ratios_inits(xfm_dce, &inits); 441 442 coeffs_v = get_filter_coeffs_16p(data->taps.v_taps, data->ratios.vert); 443 coeffs_h = get_filter_coeffs_16p(data->taps.h_taps, data->ratios.horz); 444 445 if (coeffs_v != xfm_dce->filter_v || coeffs_h != xfm_dce->filter_h) { 446 /* 4. Program vertical filters */ 447 if (xfm_dce->filter_v == NULL) 448 REG_SET(SCL_VERT_FILTER_CONTROL, 0, 449 SCL_V_2TAP_HARDCODE_COEF_EN, 0); 450 program_multi_taps_filter( 451 xfm_dce, 452 data->taps.v_taps, 453 coeffs_v, 454 FILTER_TYPE_RGB_Y_VERTICAL); 455 program_multi_taps_filter( 456 xfm_dce, 457 data->taps.v_taps, 458 coeffs_v, 459 FILTER_TYPE_ALPHA_VERTICAL); 460 461 /* 5. Program horizontal filters */ 462 if (xfm_dce->filter_h == NULL) 463 REG_SET(SCL_HORZ_FILTER_CONTROL, 0, 464 SCL_H_2TAP_HARDCODE_COEF_EN, 0); 465 program_multi_taps_filter( 466 xfm_dce, 467 data->taps.h_taps, 468 coeffs_h, 469 FILTER_TYPE_RGB_Y_HORIZONTAL); 470 program_multi_taps_filter( 471 xfm_dce, 472 data->taps.h_taps, 473 coeffs_h, 474 FILTER_TYPE_ALPHA_HORIZONTAL); 475 476 xfm_dce->filter_v = coeffs_v; 477 xfm_dce->filter_h = coeffs_h; 478 filter_updated = true; 479 } 480 } 481 482 /* 6. Program the viewport */ 483 program_viewport(xfm_dce, &data->viewport); 484 485 /* 7. Set bit to flip to new coefficient memory */ 486 if (filter_updated) 487 REG_UPDATE(SCL_UPDATE, SCL_COEF_UPDATE_COMPLETE, 1); 488 489 REG_UPDATE(LB_DATA_FORMAT, ALPHA_EN, data->lb_params.alpha_en); 490} 491 492#if defined(CONFIG_DRM_AMD_DC_SI) 493static void dce60_transform_set_scaler( 494 struct transform *xfm, 495 const struct scaler_data *data) 496{ 497 struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); 498 bool is_scaling_required; 499 const uint16_t *coeffs_v, *coeffs_h; 500 501 /*Use whole line buffer memory always*/ 502 REG_SET(DC_LB_MEMORY_SPLIT, 0, 503 DC_LB_MEMORY_CONFIG, 0); 504 505 REG_SET(DC_LB_MEM_SIZE, 0, 506 DC_LB_MEM_SIZE, xfm_dce->lb_memory_size); 507 508 REG_WRITE(SCL_UPDATE, 0x00010000); 509 510 /* Clear SCL_F_SHARP_CONTROL value to 0 */ 511 REG_WRITE(SCL_F_SHARP_CONTROL, 0); 512 513 /* 1. Program overscan */ 514 program_overscan(xfm_dce, data); 515 516 /* 2. Program taps and configuration */ 517 is_scaling_required = dce60_setup_scaling_configuration(xfm_dce, data); 518 519 if (is_scaling_required) { 520 /* 3. Calculate and program ratio, DCE6 filter initialization */ 521 struct sclh_ratios_inits inits = { 0 }; 522 523 /* DCE6 has specific calculate_inits() function */ 524 dce60_calculate_inits(xfm_dce, data, &inits); 525 526 /* DCE6 has specific program_scl_ratios_inits() function */ 527 dce60_program_scl_ratios_inits(xfm_dce, &inits); 528 529 coeffs_v = get_filter_coeffs_16p(data->taps.v_taps, data->ratios.vert); 530 coeffs_h = get_filter_coeffs_16p(data->taps.h_taps, data->ratios.horz); 531 532 if (coeffs_v != xfm_dce->filter_v || coeffs_h != xfm_dce->filter_h) { 533 /* 4. Program vertical filters */ 534 if (xfm_dce->filter_v == NULL) 535 REG_WRITE(SCL_VERT_FILTER_CONTROL, 0); 536 program_multi_taps_filter( 537 xfm_dce, 538 data->taps.v_taps, 539 coeffs_v, 540 FILTER_TYPE_RGB_Y_VERTICAL); 541 program_multi_taps_filter( 542 xfm_dce, 543 data->taps.v_taps, 544 coeffs_v, 545 FILTER_TYPE_ALPHA_VERTICAL); 546 547 /* 5. Program horizontal filters */ 548 if (xfm_dce->filter_h == NULL) 549 REG_WRITE(SCL_HORZ_FILTER_CONTROL, 0); 550 program_multi_taps_filter( 551 xfm_dce, 552 data->taps.h_taps, 553 coeffs_h, 554 FILTER_TYPE_RGB_Y_HORIZONTAL); 555 program_multi_taps_filter( 556 xfm_dce, 557 data->taps.h_taps, 558 coeffs_h, 559 FILTER_TYPE_ALPHA_HORIZONTAL); 560 561 xfm_dce->filter_v = coeffs_v; 562 xfm_dce->filter_h = coeffs_h; 563 } 564 } 565 566 /* 6. Program the viewport */ 567 program_viewport(xfm_dce, &data->viewport); 568 569 /* DCE6 has no SCL_COEF_UPDATE_COMPLETE bit to flip to new coefficient memory */ 570 571 /* DCE6 DATA_FORMAT register does not support ALPHA_EN */ 572 573 REG_WRITE(SCL_UPDATE, 0); 574} 575#endif 576 577/***************************************************************************** 578 * set_clamp 579 * 580 * @param depth : bit depth to set the clamp to (should match denorm) 581 * 582 * @brief 583 * Programs clamp according to panel bit depth. 584 * 585 *******************************************************************************/ 586static void set_clamp( 587 struct dce_transform *xfm_dce, 588 enum dc_color_depth depth) 589{ 590 int clamp_max = 0; 591 592 /* At the clamp block the data will be MSB aligned, so we set the max 593 * clamp accordingly. 594 * For example, the max value for 6 bits MSB aligned (14 bit bus) would 595 * be "11 1111 0000 0000" in binary, so 0x3F00. 596 */ 597 switch (depth) { 598 case COLOR_DEPTH_666: 599 /* 6bit MSB aligned on 14 bit bus '11 1111 0000 0000' */ 600 clamp_max = 0x3F00; 601 break; 602 case COLOR_DEPTH_888: 603 /* 8bit MSB aligned on 14 bit bus '11 1111 1100 0000' */ 604 clamp_max = 0x3FC0; 605 break; 606 case COLOR_DEPTH_101010: 607 /* 10bit MSB aligned on 14 bit bus '11 1111 1111 0000' */ 608 clamp_max = 0x3FF0; 609 break; 610 case COLOR_DEPTH_121212: 611 /* 12bit MSB aligned on 14 bit bus '11 1111 1111 1100' */ 612 clamp_max = 0x3FFC; 613 break; 614 default: 615 clamp_max = 0x3FC0; 616 BREAK_TO_DEBUGGER(); /* Invalid clamp bit depth */ 617 } 618 REG_SET_2(OUT_CLAMP_CONTROL_B_CB, 0, 619 OUT_CLAMP_MIN_B_CB, 0, 620 OUT_CLAMP_MAX_B_CB, clamp_max); 621 622 REG_SET_2(OUT_CLAMP_CONTROL_G_Y, 0, 623 OUT_CLAMP_MIN_G_Y, 0, 624 OUT_CLAMP_MAX_G_Y, clamp_max); 625 626 REG_SET_2(OUT_CLAMP_CONTROL_R_CR, 0, 627 OUT_CLAMP_MIN_R_CR, 0, 628 OUT_CLAMP_MAX_R_CR, clamp_max); 629} 630 631/******************************************************************************* 632 * set_round 633 * 634 * @brief 635 * Programs Round/Truncate 636 * 637 * @param [in] mode :round or truncate 638 * @param [in] depth :bit depth to round/truncate to 639 OUT_ROUND_TRUNC_MODE 3:0 0xA Output data round or truncate mode 640 POSSIBLE VALUES: 641 00 - truncate to u0.12 642 01 - truncate to u0.11 643 02 - truncate to u0.10 644 03 - truncate to u0.9 645 04 - truncate to u0.8 646 05 - reserved 647 06 - truncate to u0.14 648 07 - truncate to u0.13 set_reg_field_value( 649 value, 650 clamp_max, 651 OUT_CLAMP_CONTROL_R_CR, 652 OUT_CLAMP_MAX_R_CR); 653 08 - round to u0.12 654 09 - round to u0.11 655 10 - round to u0.10 656 11 - round to u0.9 657 12 - round to u0.8 658 13 - reserved 659 14 - round to u0.14 660 15 - round to u0.13 661 662 ******************************************************************************/ 663static void set_round( 664 struct dce_transform *xfm_dce, 665 enum dcp_out_trunc_round_mode mode, 666 enum dcp_out_trunc_round_depth depth) 667{ 668 int depth_bits = 0; 669 int mode_bit = 0; 670 671 /* set up bit depth */ 672 switch (depth) { 673 case DCP_OUT_TRUNC_ROUND_DEPTH_14BIT: 674 depth_bits = 6; 675 break; 676 case DCP_OUT_TRUNC_ROUND_DEPTH_13BIT: 677 depth_bits = 7; 678 break; 679 case DCP_OUT_TRUNC_ROUND_DEPTH_12BIT: 680 depth_bits = 0; 681 break; 682 case DCP_OUT_TRUNC_ROUND_DEPTH_11BIT: 683 depth_bits = 1; 684 break; 685 case DCP_OUT_TRUNC_ROUND_DEPTH_10BIT: 686 depth_bits = 2; 687 break; 688 case DCP_OUT_TRUNC_ROUND_DEPTH_9BIT: 689 depth_bits = 3; 690 break; 691 case DCP_OUT_TRUNC_ROUND_DEPTH_8BIT: 692 depth_bits = 4; 693 break; 694 default: 695 depth_bits = 4; 696 BREAK_TO_DEBUGGER(); /* Invalid dcp_out_trunc_round_depth */ 697 } 698 699 /* set up round or truncate */ 700 switch (mode) { 701 case DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE: 702 mode_bit = 0; 703 break; 704 case DCP_OUT_TRUNC_ROUND_MODE_ROUND: 705 mode_bit = 1; 706 break; 707 default: 708 BREAK_TO_DEBUGGER(); /* Invalid dcp_out_trunc_round_mode */ 709 } 710 711 depth_bits |= mode_bit << 3; 712 713 REG_SET(OUT_ROUND_CONTROL, 0, OUT_ROUND_TRUNC_MODE, depth_bits); 714} 715 716/***************************************************************************** 717 * set_dither 718 * 719 * @brief 720 * Programs Dither 721 * 722 * @param [in] dither_enable : enable dither 723 * @param [in] dither_mode : dither mode to set 724 * @param [in] dither_depth : bit depth to dither to 725 * @param [in] frame_random_enable : enable frame random 726 * @param [in] rgb_random_enable : enable rgb random 727 * @param [in] highpass_random_enable : enable highpass random 728 * 729 ******************************************************************************/ 730 731static void set_dither( 732 struct dce_transform *xfm_dce, 733 bool dither_enable, 734 enum dcp_spatial_dither_mode dither_mode, 735 enum dcp_spatial_dither_depth dither_depth, 736 bool frame_random_enable, 737 bool rgb_random_enable, 738 bool highpass_random_enable) 739{ 740 int dither_depth_bits = 0; 741 int dither_mode_bits = 0; 742 743 switch (dither_mode) { 744 case DCP_SPATIAL_DITHER_MODE_AAAA: 745 dither_mode_bits = 0; 746 break; 747 case DCP_SPATIAL_DITHER_MODE_A_AA_A: 748 dither_mode_bits = 1; 749 break; 750 case DCP_SPATIAL_DITHER_MODE_AABBAABB: 751 dither_mode_bits = 2; 752 break; 753 case DCP_SPATIAL_DITHER_MODE_AABBCCAABBCC: 754 dither_mode_bits = 3; 755 break; 756 default: 757 /* Invalid dcp_spatial_dither_mode */ 758 BREAK_TO_DEBUGGER(); 759 } 760 761 switch (dither_depth) { 762 case DCP_SPATIAL_DITHER_DEPTH_30BPP: 763 dither_depth_bits = 0; 764 break; 765 case DCP_SPATIAL_DITHER_DEPTH_24BPP: 766 dither_depth_bits = 1; 767 break; 768 default: 769 /* Invalid dcp_spatial_dither_depth */ 770 BREAK_TO_DEBUGGER(); 771 } 772 773 /* write the register */ 774 REG_SET_6(DCP_SPATIAL_DITHER_CNTL, 0, 775 DCP_SPATIAL_DITHER_EN, dither_enable, 776 DCP_SPATIAL_DITHER_MODE, dither_mode_bits, 777 DCP_SPATIAL_DITHER_DEPTH, dither_depth_bits, 778 DCP_FRAME_RANDOM_ENABLE, frame_random_enable, 779 DCP_RGB_RANDOM_ENABLE, rgb_random_enable, 780 DCP_HIGHPASS_RANDOM_ENABLE, highpass_random_enable); 781} 782 783/***************************************************************************** 784 * dce_transform_bit_depth_reduction_program 785 * 786 * @brief 787 * Programs the DCP bit depth reduction registers (Clamp, Round/Truncate, 788 * Dither) for dce 789 * 790 * @param depth : bit depth to set the clamp to (should match denorm) 791 * 792 ******************************************************************************/ 793static void program_bit_depth_reduction( 794 struct dce_transform *xfm_dce, 795 enum dc_color_depth depth, 796 const struct bit_depth_reduction_params *bit_depth_params) 797{ 798 enum dcp_out_trunc_round_depth trunc_round_depth; 799 enum dcp_out_trunc_round_mode trunc_mode; 800 bool spatial_dither_enable; 801 802 ASSERT(depth <= COLOR_DEPTH_121212); /* Invalid clamp bit depth */ 803 804 spatial_dither_enable = bit_depth_params->flags.SPATIAL_DITHER_ENABLED; 805 /* Default to 12 bit truncation without rounding */ 806 trunc_round_depth = DCP_OUT_TRUNC_ROUND_DEPTH_12BIT; 807 trunc_mode = DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE; 808 809 if (bit_depth_params->flags.TRUNCATE_ENABLED) { 810 /* Don't enable dithering if truncation is enabled */ 811 spatial_dither_enable = false; 812 trunc_mode = bit_depth_params->flags.TRUNCATE_MODE ? 813 DCP_OUT_TRUNC_ROUND_MODE_ROUND : 814 DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE; 815 816 if (bit_depth_params->flags.TRUNCATE_DEPTH == 0 || 817 bit_depth_params->flags.TRUNCATE_DEPTH == 1) 818 trunc_round_depth = DCP_OUT_TRUNC_ROUND_DEPTH_8BIT; 819 else if (bit_depth_params->flags.TRUNCATE_DEPTH == 2) 820 trunc_round_depth = DCP_OUT_TRUNC_ROUND_DEPTH_10BIT; 821 else { 822 /* 823 * Invalid truncate/round depth. Setting here to 12bit 824 * to prevent use-before-initialize errors. 825 */ 826 trunc_round_depth = DCP_OUT_TRUNC_ROUND_DEPTH_12BIT; 827 BREAK_TO_DEBUGGER(); 828 } 829 } 830 831 set_clamp(xfm_dce, depth); 832 set_round(xfm_dce, trunc_mode, trunc_round_depth); 833 set_dither(xfm_dce, 834 spatial_dither_enable, 835 DCP_SPATIAL_DITHER_MODE_A_AA_A, 836 DCP_SPATIAL_DITHER_DEPTH_30BPP, 837 bit_depth_params->flags.FRAME_RANDOM, 838 bit_depth_params->flags.RGB_RANDOM, 839 bit_depth_params->flags.HIGHPASS_RANDOM); 840} 841 842#if defined(CONFIG_DRM_AMD_DC_SI) 843/***************************************************************************** 844 * dce60_transform_bit_depth_reduction program 845 * 846 * @brief 847 * Programs the DCP bit depth reduction registers (Clamp, Round/Truncate, 848 * Dither) for dce 849 * 850 * @param depth : bit depth to set the clamp to (should match denorm) 851 * 852 ******************************************************************************/ 853static void dce60_program_bit_depth_reduction( 854 struct dce_transform *xfm_dce, 855 enum dc_color_depth depth, 856 const struct bit_depth_reduction_params *bit_depth_params) 857{ 858 enum dcp_out_trunc_round_depth trunc_round_depth; 859 enum dcp_out_trunc_round_mode trunc_mode; 860 bool spatial_dither_enable; 861 862 ASSERT(depth <= COLOR_DEPTH_121212); /* Invalid clamp bit depth */ 863 864 spatial_dither_enable = bit_depth_params->flags.SPATIAL_DITHER_ENABLED; 865 /* Default to 12 bit truncation without rounding */ 866 trunc_round_depth = DCP_OUT_TRUNC_ROUND_DEPTH_12BIT; 867 trunc_mode = DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE; 868 869 if (bit_depth_params->flags.TRUNCATE_ENABLED) { 870 /* Don't enable dithering if truncation is enabled */ 871 spatial_dither_enable = false; 872 trunc_mode = bit_depth_params->flags.TRUNCATE_MODE ? 873 DCP_OUT_TRUNC_ROUND_MODE_ROUND : 874 DCP_OUT_TRUNC_ROUND_MODE_TRUNCATE; 875 876 if (bit_depth_params->flags.TRUNCATE_DEPTH == 0 || 877 bit_depth_params->flags.TRUNCATE_DEPTH == 1) 878 trunc_round_depth = DCP_OUT_TRUNC_ROUND_DEPTH_8BIT; 879 else if (bit_depth_params->flags.TRUNCATE_DEPTH == 2) 880 trunc_round_depth = DCP_OUT_TRUNC_ROUND_DEPTH_10BIT; 881 else { 882 /* 883 * Invalid truncate/round depth. Setting here to 12bit 884 * to prevent use-before-initialize errors. 885 */ 886 trunc_round_depth = DCP_OUT_TRUNC_ROUND_DEPTH_12BIT; 887 BREAK_TO_DEBUGGER(); 888 } 889 } 890 891 /* DCE6 has no OUT_CLAMP_CONTROL_* registers - set_clamp() is skipped */ 892 set_round(xfm_dce, trunc_mode, trunc_round_depth); 893 set_dither(xfm_dce, 894 spatial_dither_enable, 895 DCP_SPATIAL_DITHER_MODE_A_AA_A, 896 DCP_SPATIAL_DITHER_DEPTH_30BPP, 897 bit_depth_params->flags.FRAME_RANDOM, 898 bit_depth_params->flags.RGB_RANDOM, 899 bit_depth_params->flags.HIGHPASS_RANDOM); 900} 901#endif 902 903static int dce_transform_get_max_num_of_supported_lines( 904 struct dce_transform *xfm_dce, 905 enum lb_pixel_depth depth, 906 int pixel_width) 907{ 908 int pixels_per_entries = 0; 909 int max_pixels_supports = 0; 910 911 ASSERT(pixel_width); 912 913 /* Find number of pixels that can fit into a single LB entry and 914 * take floor of the value since we cannot store a single pixel 915 * across multiple entries. */ 916 switch (depth) { 917 case LB_PIXEL_DEPTH_18BPP: 918 pixels_per_entries = xfm_dce->lb_bits_per_entry / 18; 919 break; 920 921 case LB_PIXEL_DEPTH_24BPP: 922 pixels_per_entries = xfm_dce->lb_bits_per_entry / 24; 923 break; 924 925 case LB_PIXEL_DEPTH_30BPP: 926 pixels_per_entries = xfm_dce->lb_bits_per_entry / 30; 927 break; 928 929 case LB_PIXEL_DEPTH_36BPP: 930 pixels_per_entries = xfm_dce->lb_bits_per_entry / 36; 931 break; 932 933 default: 934 DC_LOG_WARNING("%s: Invalid LB pixel depth", 935 __func__); 936 BREAK_TO_DEBUGGER(); 937 break; 938 } 939 940 ASSERT(pixels_per_entries); 941 942 max_pixels_supports = 943 pixels_per_entries * 944 xfm_dce->lb_memory_size; 945 946 return (max_pixels_supports / pixel_width); 947} 948 949static void set_denormalization( 950 struct dce_transform *xfm_dce, 951 enum dc_color_depth depth) 952{ 953 int denorm_mode = 0; 954 955 switch (depth) { 956 case COLOR_DEPTH_666: 957 /* 63/64 for 6 bit output color depth */ 958 denorm_mode = 1; 959 break; 960 case COLOR_DEPTH_888: 961 /* Unity for 8 bit output color depth 962 * because prescale is disabled by default */ 963 denorm_mode = 0; 964 break; 965 case COLOR_DEPTH_101010: 966 /* 1023/1024 for 10 bit output color depth */ 967 denorm_mode = 3; 968 break; 969 case COLOR_DEPTH_121212: 970 /* 4095/4096 for 12 bit output color depth */ 971 denorm_mode = 5; 972 break; 973 case COLOR_DEPTH_141414: 974 case COLOR_DEPTH_161616: 975 default: 976 /* not valid used case! */ 977 break; 978 } 979 980 REG_SET(DENORM_CONTROL, 0, DENORM_MODE, denorm_mode); 981} 982 983static void dce_transform_set_pixel_storage_depth( 984 struct transform *xfm, 985 enum lb_pixel_depth depth, 986 const struct bit_depth_reduction_params *bit_depth_params) 987{ 988 struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); 989 int pixel_depth, expan_mode; 990 enum dc_color_depth color_depth; 991 992 switch (depth) { 993 case LB_PIXEL_DEPTH_18BPP: 994 color_depth = COLOR_DEPTH_666; 995 pixel_depth = 2; 996 expan_mode = 1; 997 break; 998 case LB_PIXEL_DEPTH_24BPP: 999 color_depth = COLOR_DEPTH_888; 1000 pixel_depth = 1; 1001 expan_mode = 1; 1002 break; 1003 case LB_PIXEL_DEPTH_30BPP: 1004 color_depth = COLOR_DEPTH_101010; 1005 pixel_depth = 0; 1006 expan_mode = 1; 1007 break; 1008 case LB_PIXEL_DEPTH_36BPP: 1009 color_depth = COLOR_DEPTH_121212; 1010 pixel_depth = 3; 1011 expan_mode = 0; 1012 break; 1013 default: 1014 color_depth = COLOR_DEPTH_101010; 1015 pixel_depth = 0; 1016 expan_mode = 1; 1017 DC_LOG_DC("The pixel depth %d is not valid, set COLOR_DEPTH_101010 instead.", depth); 1018 break; 1019 } 1020 1021 set_denormalization(xfm_dce, color_depth); 1022 program_bit_depth_reduction(xfm_dce, color_depth, bit_depth_params); 1023 1024 REG_UPDATE_2(LB_DATA_FORMAT, 1025 PIXEL_DEPTH, pixel_depth, 1026 PIXEL_EXPAN_MODE, expan_mode); 1027 1028 if (!(xfm_dce->lb_pixel_depth_supported & depth)) { 1029 /*we should use unsupported capabilities 1030 * unless it is required by w/a*/ 1031 DC_LOG_DC("%s: Capability not supported", __func__); 1032 } 1033} 1034 1035#if defined(CONFIG_DRM_AMD_DC_SI) 1036static void dce60_transform_set_pixel_storage_depth( 1037 struct transform *xfm, 1038 enum lb_pixel_depth depth, 1039 const struct bit_depth_reduction_params *bit_depth_params) 1040{ 1041 struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); 1042 enum dc_color_depth color_depth; 1043 1044 switch (depth) { 1045 case LB_PIXEL_DEPTH_18BPP: 1046 color_depth = COLOR_DEPTH_666; 1047 break; 1048 case LB_PIXEL_DEPTH_24BPP: 1049 color_depth = COLOR_DEPTH_888; 1050 break; 1051 case LB_PIXEL_DEPTH_30BPP: 1052 color_depth = COLOR_DEPTH_101010; 1053 break; 1054 case LB_PIXEL_DEPTH_36BPP: 1055 color_depth = COLOR_DEPTH_121212; 1056 break; 1057 default: 1058 color_depth = COLOR_DEPTH_101010; 1059 BREAK_TO_DEBUGGER(); 1060 break; 1061 } 1062 1063 set_denormalization(xfm_dce, color_depth); 1064 dce60_program_bit_depth_reduction(xfm_dce, color_depth, bit_depth_params); 1065 1066 /* DATA_FORMAT in DCE6 does not have PIXEL_DEPTH and PIXEL_EXPAN_MODE masks */ 1067 1068 if (!(xfm_dce->lb_pixel_depth_supported & depth)) { 1069 /*we should use unsupported capabilities 1070 * unless it is required by w/a*/ 1071 DC_LOG_WARNING("%s: Capability not supported", 1072 __func__); 1073 } 1074} 1075#endif 1076 1077static void program_gamut_remap( 1078 struct dce_transform *xfm_dce, 1079 const uint16_t *reg_val) 1080{ 1081 if (reg_val) { 1082 REG_SET_2(GAMUT_REMAP_C11_C12, 0, 1083 GAMUT_REMAP_C11, reg_val[0], 1084 GAMUT_REMAP_C12, reg_val[1]); 1085 REG_SET_2(GAMUT_REMAP_C13_C14, 0, 1086 GAMUT_REMAP_C13, reg_val[2], 1087 GAMUT_REMAP_C14, reg_val[3]); 1088 REG_SET_2(GAMUT_REMAP_C21_C22, 0, 1089 GAMUT_REMAP_C21, reg_val[4], 1090 GAMUT_REMAP_C22, reg_val[5]); 1091 REG_SET_2(GAMUT_REMAP_C23_C24, 0, 1092 GAMUT_REMAP_C23, reg_val[6], 1093 GAMUT_REMAP_C24, reg_val[7]); 1094 REG_SET_2(GAMUT_REMAP_C31_C32, 0, 1095 GAMUT_REMAP_C31, reg_val[8], 1096 GAMUT_REMAP_C32, reg_val[9]); 1097 REG_SET_2(GAMUT_REMAP_C33_C34, 0, 1098 GAMUT_REMAP_C33, reg_val[10], 1099 GAMUT_REMAP_C34, reg_val[11]); 1100 1101 REG_SET(GAMUT_REMAP_CONTROL, 0, GRPH_GAMUT_REMAP_MODE, 1); 1102 } else 1103 REG_SET(GAMUT_REMAP_CONTROL, 0, GRPH_GAMUT_REMAP_MODE, 0); 1104 1105} 1106 1107/* 1108 ***************************************************************************** 1109 * Function: dal_transform_wide_gamut_set_gamut_remap 1110 * 1111 * @param [in] const struct xfm_grph_csc_adjustment *adjust 1112 * 1113 * @return 1114 * void 1115 * 1116 * @note calculate and apply color temperature adjustment to in Rgb color space 1117 * 1118 * @see 1119 * 1120 ***************************************************************************** 1121 */ 1122static void dce_transform_set_gamut_remap( 1123 struct transform *xfm, 1124 const struct xfm_grph_csc_adjustment *adjust) 1125{ 1126 struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); 1127 int i = 0; 1128 1129 if (adjust->gamut_adjust_type != GRAPHICS_GAMUT_ADJUST_TYPE_SW) 1130 /* Bypass if type is bypass or hw */ 1131 program_gamut_remap(xfm_dce, NULL); 1132 else { 1133 struct fixed31_32 arr_matrix[GAMUT_MATRIX_SIZE]; 1134 uint16_t arr_reg_val[GAMUT_MATRIX_SIZE]; 1135 1136 for (i = 0; i < GAMUT_MATRIX_SIZE; i++) 1137 arr_matrix[i] = adjust->temperature_matrix[i]; 1138 1139 convert_float_matrix( 1140 arr_reg_val, arr_matrix, GAMUT_MATRIX_SIZE); 1141 1142 program_gamut_remap(xfm_dce, arr_reg_val); 1143 } 1144} 1145 1146static uint32_t decide_taps(struct fixed31_32 ratio, uint32_t in_taps, bool chroma) 1147{ 1148 uint32_t taps; 1149 1150 if (IDENTITY_RATIO(ratio)) { 1151 return 1; 1152 } else if (in_taps != 0) { 1153 taps = in_taps; 1154 } else { 1155 taps = 4; 1156 } 1157 1158 if (chroma) { 1159 taps /= 2; 1160 if (taps < 2) 1161 taps = 2; 1162 } 1163 1164 return taps; 1165} 1166 1167 1168bool dce_transform_get_optimal_number_of_taps( 1169 struct transform *xfm, 1170 struct scaler_data *scl_data, 1171 const struct scaling_taps *in_taps) 1172{ 1173 struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); 1174 int pixel_width = scl_data->viewport.width; 1175 int max_num_of_lines; 1176 1177 if (xfm_dce->prescaler_on && 1178 (scl_data->viewport.width > scl_data->recout.width)) 1179 pixel_width = scl_data->recout.width; 1180 1181 max_num_of_lines = dce_transform_get_max_num_of_supported_lines( 1182 xfm_dce, 1183 scl_data->lb_params.depth, 1184 pixel_width); 1185 1186 /* Fail if in_taps are impossible */ 1187 if (in_taps->v_taps >= max_num_of_lines) 1188 return false; 1189 1190 /* 1191 * Set taps according to this policy (in this order) 1192 * - Use 1 for no scaling 1193 * - Use input taps 1194 * - Use 4 and reduce as required by line buffer size 1195 * - Decide chroma taps if chroma is scaled 1196 * 1197 * Ignore input chroma taps. Decide based on non-chroma 1198 */ 1199 scl_data->taps.h_taps = decide_taps(scl_data->ratios.horz, in_taps->h_taps, false); 1200 scl_data->taps.v_taps = decide_taps(scl_data->ratios.vert, in_taps->v_taps, false); 1201 scl_data->taps.h_taps_c = decide_taps(scl_data->ratios.horz_c, in_taps->h_taps, true); 1202 scl_data->taps.v_taps_c = decide_taps(scl_data->ratios.vert_c, in_taps->v_taps, true); 1203 1204 if (!IDENTITY_RATIO(scl_data->ratios.vert)) { 1205 /* reduce v_taps if needed but ensure we have at least two */ 1206 if (in_taps->v_taps == 0 1207 && max_num_of_lines <= scl_data->taps.v_taps 1208 && scl_data->taps.v_taps > 1) { 1209 scl_data->taps.v_taps = max_num_of_lines - 1; 1210 } 1211 1212 if (scl_data->taps.v_taps <= 1) 1213 return false; 1214 } 1215 1216 if (!IDENTITY_RATIO(scl_data->ratios.vert_c)) { 1217 /* reduce chroma v_taps if needed but ensure we have at least two */ 1218 if (max_num_of_lines <= scl_data->taps.v_taps_c && scl_data->taps.v_taps_c > 1) { 1219 scl_data->taps.v_taps_c = max_num_of_lines - 1; 1220 } 1221 1222 if (scl_data->taps.v_taps_c <= 1) 1223 return false; 1224 } 1225 1226 /* we've got valid taps */ 1227 return true; 1228} 1229 1230static void dce_transform_reset(struct transform *xfm) 1231{ 1232 struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); 1233 1234 xfm_dce->filter_h = NULL; 1235 xfm_dce->filter_v = NULL; 1236} 1237 1238static void program_color_matrix( 1239 struct dce_transform *xfm_dce, 1240 const struct out_csc_color_matrix *tbl_entry, 1241 enum grph_color_adjust_option options) 1242{ 1243 { 1244 REG_SET_2(OUTPUT_CSC_C11_C12, 0, 1245 OUTPUT_CSC_C11, tbl_entry->regval[0], 1246 OUTPUT_CSC_C12, tbl_entry->regval[1]); 1247 } 1248 { 1249 REG_SET_2(OUTPUT_CSC_C13_C14, 0, 1250 OUTPUT_CSC_C11, tbl_entry->regval[2], 1251 OUTPUT_CSC_C12, tbl_entry->regval[3]); 1252 } 1253 { 1254 REG_SET_2(OUTPUT_CSC_C21_C22, 0, 1255 OUTPUT_CSC_C11, tbl_entry->regval[4], 1256 OUTPUT_CSC_C12, tbl_entry->regval[5]); 1257 } 1258 { 1259 REG_SET_2(OUTPUT_CSC_C23_C24, 0, 1260 OUTPUT_CSC_C11, tbl_entry->regval[6], 1261 OUTPUT_CSC_C12, tbl_entry->regval[7]); 1262 } 1263 { 1264 REG_SET_2(OUTPUT_CSC_C31_C32, 0, 1265 OUTPUT_CSC_C11, tbl_entry->regval[8], 1266 OUTPUT_CSC_C12, tbl_entry->regval[9]); 1267 } 1268 { 1269 REG_SET_2(OUTPUT_CSC_C33_C34, 0, 1270 OUTPUT_CSC_C11, tbl_entry->regval[10], 1271 OUTPUT_CSC_C12, tbl_entry->regval[11]); 1272 } 1273} 1274 1275static bool configure_graphics_mode( 1276 struct dce_transform *xfm_dce, 1277 enum csc_color_mode config, 1278 enum graphics_csc_adjust_type csc_adjust_type, 1279 enum dc_color_space color_space) 1280{ 1281 REG_SET(OUTPUT_CSC_CONTROL, 0, 1282 OUTPUT_CSC_GRPH_MODE, 0); 1283 1284 if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_SW) { 1285 if (config == CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC) { 1286 REG_SET(OUTPUT_CSC_CONTROL, 0, 1287 OUTPUT_CSC_GRPH_MODE, 4); 1288 } else { 1289 1290 switch (color_space) { 1291 case COLOR_SPACE_SRGB: 1292 /* by pass */ 1293 REG_SET(OUTPUT_CSC_CONTROL, 0, 1294 OUTPUT_CSC_GRPH_MODE, 0); 1295 break; 1296 case COLOR_SPACE_SRGB_LIMITED: 1297 /* TV RGB */ 1298 REG_SET(OUTPUT_CSC_CONTROL, 0, 1299 OUTPUT_CSC_GRPH_MODE, 1); 1300 break; 1301 case COLOR_SPACE_YCBCR601: 1302 case COLOR_SPACE_YCBCR601_LIMITED: 1303 /* YCbCr601 */ 1304 REG_SET(OUTPUT_CSC_CONTROL, 0, 1305 OUTPUT_CSC_GRPH_MODE, 2); 1306 break; 1307 case COLOR_SPACE_YCBCR709: 1308 case COLOR_SPACE_YCBCR709_LIMITED: 1309 /* YCbCr709 */ 1310 REG_SET(OUTPUT_CSC_CONTROL, 0, 1311 OUTPUT_CSC_GRPH_MODE, 3); 1312 break; 1313 default: 1314 return false; 1315 } 1316 } 1317 } else if (csc_adjust_type == GRAPHICS_CSC_ADJUST_TYPE_HW) { 1318 switch (color_space) { 1319 case COLOR_SPACE_SRGB: 1320 /* by pass */ 1321 REG_SET(OUTPUT_CSC_CONTROL, 0, 1322 OUTPUT_CSC_GRPH_MODE, 0); 1323 break; 1324 case COLOR_SPACE_SRGB_LIMITED: 1325 /* TV RGB */ 1326 REG_SET(OUTPUT_CSC_CONTROL, 0, 1327 OUTPUT_CSC_GRPH_MODE, 1); 1328 break; 1329 case COLOR_SPACE_YCBCR601: 1330 case COLOR_SPACE_YCBCR601_LIMITED: 1331 /* YCbCr601 */ 1332 REG_SET(OUTPUT_CSC_CONTROL, 0, 1333 OUTPUT_CSC_GRPH_MODE, 2); 1334 break; 1335 case COLOR_SPACE_YCBCR709: 1336 case COLOR_SPACE_YCBCR709_LIMITED: 1337 /* YCbCr709 */ 1338 REG_SET(OUTPUT_CSC_CONTROL, 0, 1339 OUTPUT_CSC_GRPH_MODE, 3); 1340 break; 1341 default: 1342 return false; 1343 } 1344 1345 } else 1346 /* by pass */ 1347 REG_SET(OUTPUT_CSC_CONTROL, 0, 1348 OUTPUT_CSC_GRPH_MODE, 0); 1349 1350 return true; 1351} 1352 1353void dce110_opp_set_csc_adjustment( 1354 struct transform *xfm, 1355 const struct out_csc_color_matrix *tbl_entry) 1356{ 1357 struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); 1358 enum csc_color_mode config = 1359 CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; 1360 1361 program_color_matrix( 1362 xfm_dce, tbl_entry, GRPH_COLOR_MATRIX_SW); 1363 1364 /* We did everything ,now program DxOUTPUT_CSC_CONTROL */ 1365 configure_graphics_mode(xfm_dce, config, GRAPHICS_CSC_ADJUST_TYPE_SW, 1366 tbl_entry->color_space); 1367} 1368 1369void dce110_opp_set_csc_default( 1370 struct transform *xfm, 1371 const struct default_adjustment *default_adjust) 1372{ 1373 struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); 1374 enum csc_color_mode config = 1375 CSC_COLOR_MODE_GRAPHICS_PREDEFINED; 1376 1377 if (default_adjust->force_hw_default == false) { 1378 const struct out_csc_color_matrix *elm; 1379 /* currently parameter not in use */ 1380 enum grph_color_adjust_option option = 1381 GRPH_COLOR_MATRIX_HW_DEFAULT; 1382 uint32_t i; 1383 /* 1384 * HW default false we program locally defined matrix 1385 * HW default true we use predefined hw matrix and we 1386 * do not need to program matrix 1387 * OEM wants the HW default via runtime parameter. 1388 */ 1389 option = GRPH_COLOR_MATRIX_SW; 1390 1391 for (i = 0; i < ARRAY_SIZE(global_color_matrix); ++i) { 1392 elm = &global_color_matrix[i]; 1393 if (elm->color_space != default_adjust->out_color_space) 1394 continue; 1395 /* program the matrix with default values from this 1396 * file */ 1397 program_color_matrix(xfm_dce, elm, option); 1398 config = CSC_COLOR_MODE_GRAPHICS_OUTPUT_CSC; 1399 break; 1400 } 1401 } 1402 1403 /* configure the what we programmed : 1404 * 1. Default values from this file 1405 * 2. Use hardware default from ROM_A and we do not need to program 1406 * matrix */ 1407 1408 configure_graphics_mode(xfm_dce, config, 1409 default_adjust->csc_adjust_type, 1410 default_adjust->out_color_space); 1411} 1412 1413static void program_pwl(struct dce_transform *xfm_dce, 1414 const struct pwl_params *params) 1415{ 1416 uint32_t retval; 1417 uint8_t max_tries = 10; 1418 uint8_t counter = 0; 1419 uint32_t i = 0; 1420 const struct pwl_result_data *rgb = params->rgb_resulted; 1421 1422 /* Power on LUT memory */ 1423 if (REG(DCFE_MEM_PWR_CTRL)) 1424 REG_UPDATE(DCFE_MEM_PWR_CTRL, 1425 DCP_REGAMMA_MEM_PWR_DIS, 1); 1426 else 1427 REG_UPDATE(DCFE_MEM_LIGHT_SLEEP_CNTL, 1428 REGAMMA_LUT_LIGHT_SLEEP_DIS, 1); 1429 1430 while (counter < max_tries) { 1431 if (REG(DCFE_MEM_PWR_STATUS)) { 1432 REG_GET(DCFE_MEM_PWR_STATUS, 1433 DCP_REGAMMA_MEM_PWR_STATE, 1434 &retval); 1435 1436 if (retval == 0) 1437 break; 1438 ++counter; 1439 } else { 1440 REG_GET(DCFE_MEM_LIGHT_SLEEP_CNTL, 1441 REGAMMA_LUT_MEM_PWR_STATE, 1442 &retval); 1443 1444 if (retval == 0) 1445 break; 1446 ++counter; 1447 } 1448 } 1449 1450 if (counter == max_tries) { 1451 DC_LOG_WARNING("%s: regamma lut was not powered on " 1452 "in a timely manner," 1453 " programming still proceeds\n", 1454 __func__); 1455 } 1456 1457 REG_UPDATE(REGAMMA_LUT_WRITE_EN_MASK, 1458 REGAMMA_LUT_WRITE_EN_MASK, 7); 1459 1460 REG_WRITE(REGAMMA_LUT_INDEX, 0); 1461 1462 /* Program REGAMMA_LUT_DATA */ 1463 while (i != params->hw_points_num) { 1464 1465 REG_WRITE(REGAMMA_LUT_DATA, rgb->red_reg); 1466 REG_WRITE(REGAMMA_LUT_DATA, rgb->green_reg); 1467 REG_WRITE(REGAMMA_LUT_DATA, rgb->blue_reg); 1468 REG_WRITE(REGAMMA_LUT_DATA, rgb->delta_red_reg); 1469 REG_WRITE(REGAMMA_LUT_DATA, rgb->delta_green_reg); 1470 REG_WRITE(REGAMMA_LUT_DATA, rgb->delta_blue_reg); 1471 1472 ++rgb; 1473 ++i; 1474 } 1475 1476 /* we are done with DCP LUT memory; re-enable low power mode */ 1477 if (REG(DCFE_MEM_PWR_CTRL)) 1478 REG_UPDATE(DCFE_MEM_PWR_CTRL, 1479 DCP_REGAMMA_MEM_PWR_DIS, 0); 1480 else 1481 REG_UPDATE(DCFE_MEM_LIGHT_SLEEP_CNTL, 1482 REGAMMA_LUT_LIGHT_SLEEP_DIS, 0); 1483} 1484 1485static void regamma_config_regions_and_segments(struct dce_transform *xfm_dce, 1486 const struct pwl_params *params) 1487{ 1488 const struct gamma_curve *curve; 1489 1490 REG_SET_2(REGAMMA_CNTLA_START_CNTL, 0, 1491 REGAMMA_CNTLA_EXP_REGION_START, params->arr_points[0].custom_float_x, 1492 REGAMMA_CNTLA_EXP_REGION_START_SEGMENT, 0); 1493 1494 REG_SET(REGAMMA_CNTLA_SLOPE_CNTL, 0, 1495 REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE, params->arr_points[0].custom_float_slope); 1496 1497 REG_SET(REGAMMA_CNTLA_END_CNTL1, 0, 1498 REGAMMA_CNTLA_EXP_REGION_END, params->arr_points[1].custom_float_x); 1499 1500 REG_SET_2(REGAMMA_CNTLA_END_CNTL2, 0, 1501 REGAMMA_CNTLA_EXP_REGION_END_BASE, params->arr_points[1].custom_float_y, 1502 REGAMMA_CNTLA_EXP_REGION_END_SLOPE, params->arr_points[1].custom_float_slope); 1503 1504 curve = params->arr_curve_points; 1505 1506 REG_SET_4(REGAMMA_CNTLA_REGION_0_1, 0, 1507 REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, 1508 REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, 1509 REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, 1510 REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); 1511 curve += 2; 1512 1513 REG_SET_4(REGAMMA_CNTLA_REGION_2_3, 0, 1514 REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, 1515 REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, 1516 REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, 1517 REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); 1518 curve += 2; 1519 1520 REG_SET_4(REGAMMA_CNTLA_REGION_4_5, 0, 1521 REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, 1522 REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, 1523 REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, 1524 REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); 1525 curve += 2; 1526 1527 REG_SET_4(REGAMMA_CNTLA_REGION_6_7, 0, 1528 REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, 1529 REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, 1530 REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, 1531 REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); 1532 curve += 2; 1533 1534 REG_SET_4(REGAMMA_CNTLA_REGION_8_9, 0, 1535 REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, 1536 REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, 1537 REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, 1538 REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); 1539 curve += 2; 1540 1541 REG_SET_4(REGAMMA_CNTLA_REGION_10_11, 0, 1542 REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, 1543 REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, 1544 REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, 1545 REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); 1546 curve += 2; 1547 1548 REG_SET_4(REGAMMA_CNTLA_REGION_12_13, 0, 1549 REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, 1550 REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, 1551 REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, 1552 REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); 1553 curve += 2; 1554 1555 REG_SET_4(REGAMMA_CNTLA_REGION_14_15, 0, 1556 REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET, curve[0].offset, 1557 REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num, 1558 REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET, curve[1].offset, 1559 REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num); 1560} 1561 1562 1563 1564void dce110_opp_program_regamma_pwl(struct transform *xfm, 1565 const struct pwl_params *params) 1566{ 1567 struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); 1568 1569 /* Setup regions */ 1570 regamma_config_regions_and_segments(xfm_dce, params); 1571 1572 /* Program PWL */ 1573 program_pwl(xfm_dce, params); 1574} 1575 1576void dce110_opp_power_on_regamma_lut(struct transform *xfm, 1577 bool power_on) 1578{ 1579 struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); 1580 1581 if (REG(DCFE_MEM_PWR_CTRL)) 1582 REG_UPDATE_2(DCFE_MEM_PWR_CTRL, 1583 DCP_REGAMMA_MEM_PWR_DIS, power_on, 1584 DCP_LUT_MEM_PWR_DIS, power_on); 1585 else 1586 REG_UPDATE_2(DCFE_MEM_LIGHT_SLEEP_CNTL, 1587 REGAMMA_LUT_LIGHT_SLEEP_DIS, power_on, 1588 DCP_LUT_LIGHT_SLEEP_DIS, power_on); 1589 1590} 1591 1592void dce110_opp_set_regamma_mode(struct transform *xfm, 1593 enum opp_regamma mode) 1594{ 1595 struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); 1596 1597 REG_SET(REGAMMA_CONTROL, 0, 1598 GRPH_REGAMMA_MODE, mode); 1599} 1600 1601static const struct transform_funcs dce_transform_funcs = { 1602 .transform_reset = dce_transform_reset, 1603 .transform_set_scaler = dce_transform_set_scaler, 1604 .transform_set_gamut_remap = dce_transform_set_gamut_remap, 1605 .opp_set_csc_adjustment = dce110_opp_set_csc_adjustment, 1606 .opp_set_csc_default = dce110_opp_set_csc_default, 1607 .opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut, 1608 .opp_program_regamma_pwl = dce110_opp_program_regamma_pwl, 1609 .opp_set_regamma_mode = dce110_opp_set_regamma_mode, 1610 .transform_set_pixel_storage_depth = dce_transform_set_pixel_storage_depth, 1611 .transform_get_optimal_number_of_taps = dce_transform_get_optimal_number_of_taps 1612}; 1613 1614#if defined(CONFIG_DRM_AMD_DC_SI) 1615static const struct transform_funcs dce60_transform_funcs = { 1616 .transform_reset = dce_transform_reset, 1617 .transform_set_scaler = dce60_transform_set_scaler, 1618 .transform_set_gamut_remap = dce_transform_set_gamut_remap, 1619 .opp_set_csc_adjustment = dce110_opp_set_csc_adjustment, 1620 .opp_set_csc_default = dce110_opp_set_csc_default, 1621 .opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut, 1622 .opp_program_regamma_pwl = dce110_opp_program_regamma_pwl, 1623 .opp_set_regamma_mode = dce110_opp_set_regamma_mode, 1624 .transform_set_pixel_storage_depth = dce60_transform_set_pixel_storage_depth, 1625 .transform_get_optimal_number_of_taps = dce_transform_get_optimal_number_of_taps 1626}; 1627#endif 1628 1629/*****************************************/ 1630/* Constructor, Destructor */ 1631/*****************************************/ 1632 1633void dce_transform_construct( 1634 struct dce_transform *xfm_dce, 1635 struct dc_context *ctx, 1636 uint32_t inst, 1637 const struct dce_transform_registers *regs, 1638 const struct dce_transform_shift *xfm_shift, 1639 const struct dce_transform_mask *xfm_mask) 1640{ 1641 xfm_dce->base.ctx = ctx; 1642 1643 xfm_dce->base.inst = inst; 1644 xfm_dce->base.funcs = &dce_transform_funcs; 1645 1646 xfm_dce->regs = regs; 1647 xfm_dce->xfm_shift = xfm_shift; 1648 xfm_dce->xfm_mask = xfm_mask; 1649 1650 xfm_dce->prescaler_on = true; 1651 xfm_dce->lb_pixel_depth_supported = 1652 LB_PIXEL_DEPTH_18BPP | 1653 LB_PIXEL_DEPTH_24BPP | 1654 LB_PIXEL_DEPTH_30BPP | 1655 LB_PIXEL_DEPTH_36BPP; 1656 1657 xfm_dce->lb_bits_per_entry = LB_BITS_PER_ENTRY; 1658 xfm_dce->lb_memory_size = LB_TOTAL_NUMBER_OF_ENTRIES; /*0x6B0*/ 1659} 1660 1661#if defined(CONFIG_DRM_AMD_DC_SI) 1662void dce60_transform_construct( 1663 struct dce_transform *xfm_dce, 1664 struct dc_context *ctx, 1665 uint32_t inst, 1666 const struct dce_transform_registers *regs, 1667 const struct dce_transform_shift *xfm_shift, 1668 const struct dce_transform_mask *xfm_mask) 1669{ 1670 xfm_dce->base.ctx = ctx; 1671 1672 xfm_dce->base.inst = inst; 1673 xfm_dce->base.funcs = &dce60_transform_funcs; 1674 1675 xfm_dce->regs = regs; 1676 xfm_dce->xfm_shift = xfm_shift; 1677 xfm_dce->xfm_mask = xfm_mask; 1678 1679 xfm_dce->prescaler_on = true; 1680 xfm_dce->lb_pixel_depth_supported = 1681 LB_PIXEL_DEPTH_18BPP | 1682 LB_PIXEL_DEPTH_24BPP | 1683 LB_PIXEL_DEPTH_30BPP | 1684 LB_PIXEL_DEPTH_36BPP; 1685 1686 xfm_dce->lb_bits_per_entry = LB_BITS_PER_ENTRY; 1687 xfm_dce->lb_memory_size = LB_TOTAL_NUMBER_OF_ENTRIES; /*0x6B0*/ 1688} 1689#endif