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 "dce110_transform_v.h" 27 #include "dm_services.h" 28 #include "dc.h" 29 #include "dce/dce_11_0_d.h" 30 #include "dce/dce_11_0_sh_mask.h" 31 32 #define SCLV_PHASES 64 33 34 struct sclv_ratios_inits { 35 uint32_t h_int_scale_ratio_luma; 36 uint32_t h_int_scale_ratio_chroma; 37 uint32_t v_int_scale_ratio_luma; 38 uint32_t v_int_scale_ratio_chroma; 39 struct init_int_and_frac h_init_luma; 40 struct init_int_and_frac h_init_chroma; 41 struct init_int_and_frac v_init_luma; 42 struct init_int_and_frac v_init_chroma; 43 }; 44 45 static void calculate_viewport( 46 const struct scaler_data *scl_data, 47 struct rect *luma_viewport, 48 struct rect *chroma_viewport) 49 { 50 /*Do not set chroma vp for rgb444 pixel format*/ 51 luma_viewport->x = scl_data->viewport.x - scl_data->viewport.x % 2; 52 luma_viewport->y = scl_data->viewport.y - scl_data->viewport.y % 2; 53 luma_viewport->width = 54 scl_data->viewport.width - scl_data->viewport.width % 2; 55 luma_viewport->height = 56 scl_data->viewport.height - scl_data->viewport.height % 2; 57 chroma_viewport->x = luma_viewport->x; 58 chroma_viewport->y = luma_viewport->y; 59 chroma_viewport->height = luma_viewport->height; 60 chroma_viewport->width = luma_viewport->width; 61 62 if (scl_data->format == PIXEL_FORMAT_420BPP8) { 63 luma_viewport->height += luma_viewport->height % 2; 64 luma_viewport->width += luma_viewport->width % 2; 65 /*for 420 video chroma is 1/4 the area of luma, scaled 66 *vertically and horizontally 67 */ 68 chroma_viewport->x = luma_viewport->x / 2; 69 chroma_viewport->y = luma_viewport->y / 2; 70 chroma_viewport->height = luma_viewport->height / 2; 71 chroma_viewport->width = luma_viewport->width / 2; 72 } 73 } 74 75 static void program_viewport( 76 struct dce_transform *xfm_dce, 77 struct rect *luma_view_port, 78 struct rect *chroma_view_port) 79 { 80 struct dc_context *ctx = xfm_dce->base.ctx; 81 uint32_t value = 0; 82 uint32_t addr = 0; 83 84 if (luma_view_port->width != 0 && luma_view_port->height != 0) { 85 addr = mmSCLV_VIEWPORT_START; 86 value = 0; 87 set_reg_field_value( 88 value, 89 luma_view_port->x, 90 SCLV_VIEWPORT_START, 91 VIEWPORT_X_START); 92 set_reg_field_value( 93 value, 94 luma_view_port->y, 95 SCLV_VIEWPORT_START, 96 VIEWPORT_Y_START); 97 dm_write_reg(ctx, addr, value); 98 99 addr = mmSCLV_VIEWPORT_SIZE; 100 value = 0; 101 set_reg_field_value( 102 value, 103 luma_view_port->height, 104 SCLV_VIEWPORT_SIZE, 105 VIEWPORT_HEIGHT); 106 set_reg_field_value( 107 value, 108 luma_view_port->width, 109 SCLV_VIEWPORT_SIZE, 110 VIEWPORT_WIDTH); 111 dm_write_reg(ctx, addr, value); 112 } 113 114 if (chroma_view_port->width != 0 && chroma_view_port->height != 0) { 115 addr = mmSCLV_VIEWPORT_START_C; 116 value = 0; 117 set_reg_field_value( 118 value, 119 chroma_view_port->x, 120 SCLV_VIEWPORT_START_C, 121 VIEWPORT_X_START_C); 122 set_reg_field_value( 123 value, 124 chroma_view_port->y, 125 SCLV_VIEWPORT_START_C, 126 VIEWPORT_Y_START_C); 127 dm_write_reg(ctx, addr, value); 128 129 addr = mmSCLV_VIEWPORT_SIZE_C; 130 value = 0; 131 set_reg_field_value( 132 value, 133 chroma_view_port->height, 134 SCLV_VIEWPORT_SIZE_C, 135 VIEWPORT_HEIGHT_C); 136 set_reg_field_value( 137 value, 138 chroma_view_port->width, 139 SCLV_VIEWPORT_SIZE_C, 140 VIEWPORT_WIDTH_C); 141 dm_write_reg(ctx, addr, value); 142 } 143 } 144 145 /* 146 * Function: 147 * void setup_scaling_configuration 148 * 149 * Purpose: setup scaling mode : bypass, RGb, YCbCr and nummber of taps 150 * Input: data 151 * 152 * Output: 153 * void 154 */ 155 static bool setup_scaling_configuration( 156 struct dce_transform *xfm_dce, 157 const struct scaler_data *data) 158 { 159 bool is_scaling_needed = false; 160 struct dc_context *ctx = xfm_dce->base.ctx; 161 uint32_t value = 0; 162 163 set_reg_field_value(value, data->taps.h_taps - 1, 164 SCLV_TAP_CONTROL, SCL_H_NUM_OF_TAPS); 165 set_reg_field_value(value, data->taps.v_taps - 1, 166 SCLV_TAP_CONTROL, SCL_V_NUM_OF_TAPS); 167 set_reg_field_value(value, data->taps.h_taps_c - 1, 168 SCLV_TAP_CONTROL, SCL_H_NUM_OF_TAPS_C); 169 set_reg_field_value(value, data->taps.v_taps_c - 1, 170 SCLV_TAP_CONTROL, SCL_V_NUM_OF_TAPS_C); 171 dm_write_reg(ctx, mmSCLV_TAP_CONTROL, value); 172 173 value = 0; 174 if (data->taps.h_taps + data->taps.v_taps > 2) { 175 set_reg_field_value(value, 1, SCLV_MODE, SCL_MODE); 176 set_reg_field_value(value, 1, SCLV_MODE, SCL_PSCL_EN); 177 is_scaling_needed = true; 178 } else { 179 set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE); 180 set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN); 181 } 182 183 if (data->taps.h_taps_c + data->taps.v_taps_c > 2) { 184 set_reg_field_value(value, 1, SCLV_MODE, SCL_MODE_C); 185 set_reg_field_value(value, 1, SCLV_MODE, SCL_PSCL_EN_C); 186 is_scaling_needed = true; 187 } else if (data->format != PIXEL_FORMAT_420BPP8) { 188 set_reg_field_value( 189 value, 190 get_reg_field_value(value, SCLV_MODE, SCL_MODE), 191 SCLV_MODE, 192 SCL_MODE_C); 193 set_reg_field_value( 194 value, 195 get_reg_field_value(value, SCLV_MODE, SCL_PSCL_EN), 196 SCLV_MODE, 197 SCL_PSCL_EN_C); 198 } else { 199 set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE_C); 200 set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN_C); 201 } 202 dm_write_reg(ctx, mmSCLV_MODE, value); 203 204 value = 0; 205 /* 206 * 0 - Replaced out of bound pixels with black pixel 207 * (or any other required color) 208 * 1 - Replaced out of bound pixels with the edge pixel 209 */ 210 set_reg_field_value(value, 1, SCLV_CONTROL, SCL_BOUNDARY_MODE); 211 dm_write_reg(ctx, mmSCLV_CONTROL, value); 212 213 return is_scaling_needed; 214 } 215 216 /** 217 * Function: 218 * void program_overscan 219 * 220 * Purpose: Programs overscan border 221 * Input: overscan 222 * 223 * Output: 224 void 225 */ 226 static void program_overscan( 227 struct dce_transform *xfm_dce, 228 const struct scaler_data *data) 229 { 230 uint32_t overscan_left_right = 0; 231 uint32_t overscan_top_bottom = 0; 232 233 int overscan_right = data->h_active - data->recout.x - data->recout.width; 234 int overscan_bottom = data->v_active - data->recout.y - data->recout.height; 235 236 if (xfm_dce->base.ctx->dc->debug.surface_visual_confirm) { 237 overscan_bottom += 2; 238 overscan_right += 2; 239 } 240 241 if (overscan_right < 0) { 242 BREAK_TO_DEBUGGER(); 243 overscan_right = 0; 244 } 245 if (overscan_bottom < 0) { 246 BREAK_TO_DEBUGGER(); 247 overscan_bottom = 0; 248 } 249 250 set_reg_field_value(overscan_left_right, data->recout.x, 251 EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT); 252 253 set_reg_field_value(overscan_left_right, overscan_right, 254 EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT); 255 256 set_reg_field_value(overscan_top_bottom, data->recout.y, 257 EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP); 258 259 set_reg_field_value(overscan_top_bottom, overscan_bottom, 260 EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM); 261 262 dm_write_reg(xfm_dce->base.ctx, 263 mmSCLV_EXT_OVERSCAN_LEFT_RIGHT, 264 overscan_left_right); 265 266 dm_write_reg(xfm_dce->base.ctx, 267 mmSCLV_EXT_OVERSCAN_TOP_BOTTOM, 268 overscan_top_bottom); 269 } 270 271 static void set_coeff_update_complete( 272 struct dce_transform *xfm_dce) 273 { 274 uint32_t value; 275 276 value = dm_read_reg(xfm_dce->base.ctx, mmSCLV_UPDATE); 277 set_reg_field_value(value, 1, SCLV_UPDATE, SCL_COEF_UPDATE_COMPLETE); 278 dm_write_reg(xfm_dce->base.ctx, mmSCLV_UPDATE, value); 279 } 280 281 static void program_multi_taps_filter( 282 struct dce_transform *xfm_dce, 283 int taps, 284 const uint16_t *coeffs, 285 enum ram_filter_type filter_type) 286 { 287 struct dc_context *ctx = xfm_dce->base.ctx; 288 int i, phase, pair; 289 int array_idx = 0; 290 int taps_pairs = (taps + 1) / 2; 291 int phases_to_program = SCLV_PHASES / 2 + 1; 292 293 uint32_t select = 0; 294 uint32_t power_ctl, power_ctl_off; 295 296 if (!coeffs) 297 return; 298 299 /*We need to disable power gating on coeff memory to do programming*/ 300 power_ctl = dm_read_reg(ctx, mmDCFEV_MEM_PWR_CTRL); 301 power_ctl_off = power_ctl; 302 set_reg_field_value(power_ctl_off, 1, DCFEV_MEM_PWR_CTRL, SCLV_COEFF_MEM_PWR_DIS); 303 dm_write_reg(ctx, mmDCFEV_MEM_PWR_CTRL, power_ctl_off); 304 305 /*Wait to disable gating:*/ 306 for (i = 0; i < 10; i++) { 307 if (get_reg_field_value( 308 dm_read_reg(ctx, mmDCFEV_MEM_PWR_STATUS), 309 DCFEV_MEM_PWR_STATUS, 310 SCLV_COEFF_MEM_PWR_STATE) == 0) 311 break; 312 313 udelay(1); 314 } 315 316 set_reg_field_value(select, filter_type, SCLV_COEF_RAM_SELECT, SCL_C_RAM_FILTER_TYPE); 317 318 for (phase = 0; phase < phases_to_program; phase++) { 319 /*we always program N/2 + 1 phases, total phases N, but N/2-1 are just mirror 320 phase 0 is unique and phase N/2 is unique if N is even*/ 321 set_reg_field_value(select, phase, SCLV_COEF_RAM_SELECT, SCL_C_RAM_PHASE); 322 for (pair = 0; pair < taps_pairs; pair++) { 323 uint32_t data = 0; 324 325 set_reg_field_value(select, pair, 326 SCLV_COEF_RAM_SELECT, SCL_C_RAM_TAP_PAIR_IDX); 327 328 dm_write_reg(ctx, mmSCLV_COEF_RAM_SELECT, select); 329 330 set_reg_field_value( 331 data, 1, 332 SCLV_COEF_RAM_TAP_DATA, 333 SCL_C_RAM_EVEN_TAP_COEF_EN); 334 set_reg_field_value( 335 data, coeffs[array_idx], 336 SCLV_COEF_RAM_TAP_DATA, 337 SCL_C_RAM_EVEN_TAP_COEF); 338 339 if (taps % 2 && pair == taps_pairs - 1) { 340 set_reg_field_value( 341 data, 0, 342 SCLV_COEF_RAM_TAP_DATA, 343 SCL_C_RAM_ODD_TAP_COEF_EN); 344 array_idx++; 345 } else { 346 set_reg_field_value( 347 data, 1, 348 SCLV_COEF_RAM_TAP_DATA, 349 SCL_C_RAM_ODD_TAP_COEF_EN); 350 set_reg_field_value( 351 data, coeffs[array_idx + 1], 352 SCLV_COEF_RAM_TAP_DATA, 353 SCL_C_RAM_ODD_TAP_COEF); 354 355 array_idx += 2; 356 } 357 358 dm_write_reg(ctx, mmSCLV_COEF_RAM_TAP_DATA, data); 359 } 360 } 361 362 /*We need to restore power gating on coeff memory to initial state*/ 363 dm_write_reg(ctx, mmDCFEV_MEM_PWR_CTRL, power_ctl); 364 } 365 366 static void calculate_inits( 367 struct dce_transform *xfm_dce, 368 const struct scaler_data *data, 369 struct sclv_ratios_inits *inits, 370 struct rect *luma_viewport, 371 struct rect *chroma_viewport) 372 { 373 inits->h_int_scale_ratio_luma = 374 dal_fixed31_32_u2d19(data->ratios.horz) << 5; 375 inits->v_int_scale_ratio_luma = 376 dal_fixed31_32_u2d19(data->ratios.vert) << 5; 377 inits->h_int_scale_ratio_chroma = 378 dal_fixed31_32_u2d19(data->ratios.horz_c) << 5; 379 inits->v_int_scale_ratio_chroma = 380 dal_fixed31_32_u2d19(data->ratios.vert_c) << 5; 381 382 inits->h_init_luma.integer = 1; 383 inits->v_init_luma.integer = 1; 384 inits->h_init_chroma.integer = 1; 385 inits->v_init_chroma.integer = 1; 386 } 387 388 static void program_scl_ratios_inits( 389 struct dce_transform *xfm_dce, 390 struct sclv_ratios_inits *inits) 391 { 392 struct dc_context *ctx = xfm_dce->base.ctx; 393 uint32_t addr = mmSCLV_HORZ_FILTER_SCALE_RATIO; 394 uint32_t value = 0; 395 396 set_reg_field_value( 397 value, 398 inits->h_int_scale_ratio_luma, 399 SCLV_HORZ_FILTER_SCALE_RATIO, 400 SCL_H_SCALE_RATIO); 401 dm_write_reg(ctx, addr, value); 402 403 addr = mmSCLV_VERT_FILTER_SCALE_RATIO; 404 value = 0; 405 set_reg_field_value( 406 value, 407 inits->v_int_scale_ratio_luma, 408 SCLV_VERT_FILTER_SCALE_RATIO, 409 SCL_V_SCALE_RATIO); 410 dm_write_reg(ctx, addr, value); 411 412 addr = mmSCLV_HORZ_FILTER_SCALE_RATIO_C; 413 value = 0; 414 set_reg_field_value( 415 value, 416 inits->h_int_scale_ratio_chroma, 417 SCLV_HORZ_FILTER_SCALE_RATIO_C, 418 SCL_H_SCALE_RATIO_C); 419 dm_write_reg(ctx, addr, value); 420 421 addr = mmSCLV_VERT_FILTER_SCALE_RATIO_C; 422 value = 0; 423 set_reg_field_value( 424 value, 425 inits->v_int_scale_ratio_chroma, 426 SCLV_VERT_FILTER_SCALE_RATIO_C, 427 SCL_V_SCALE_RATIO_C); 428 dm_write_reg(ctx, addr, value); 429 430 addr = mmSCLV_HORZ_FILTER_INIT; 431 value = 0; 432 set_reg_field_value( 433 value, 434 inits->h_init_luma.fraction, 435 SCLV_HORZ_FILTER_INIT, 436 SCL_H_INIT_FRAC); 437 set_reg_field_value( 438 value, 439 inits->h_init_luma.integer, 440 SCLV_HORZ_FILTER_INIT, 441 SCL_H_INIT_INT); 442 dm_write_reg(ctx, addr, value); 443 444 addr = mmSCLV_VERT_FILTER_INIT; 445 value = 0; 446 set_reg_field_value( 447 value, 448 inits->v_init_luma.fraction, 449 SCLV_VERT_FILTER_INIT, 450 SCL_V_INIT_FRAC); 451 set_reg_field_value( 452 value, 453 inits->v_init_luma.integer, 454 SCLV_VERT_FILTER_INIT, 455 SCL_V_INIT_INT); 456 dm_write_reg(ctx, addr, value); 457 458 addr = mmSCLV_HORZ_FILTER_INIT_C; 459 value = 0; 460 set_reg_field_value( 461 value, 462 inits->h_init_chroma.fraction, 463 SCLV_HORZ_FILTER_INIT_C, 464 SCL_H_INIT_FRAC_C); 465 set_reg_field_value( 466 value, 467 inits->h_init_chroma.integer, 468 SCLV_HORZ_FILTER_INIT_C, 469 SCL_H_INIT_INT_C); 470 dm_write_reg(ctx, addr, value); 471 472 addr = mmSCLV_VERT_FILTER_INIT_C; 473 value = 0; 474 set_reg_field_value( 475 value, 476 inits->v_init_chroma.fraction, 477 SCLV_VERT_FILTER_INIT_C, 478 SCL_V_INIT_FRAC_C); 479 set_reg_field_value( 480 value, 481 inits->v_init_chroma.integer, 482 SCLV_VERT_FILTER_INIT_C, 483 SCL_V_INIT_INT_C); 484 dm_write_reg(ctx, addr, value); 485 } 486 487 static const uint16_t *get_filter_coeffs_64p(int taps, struct fixed31_32 ratio) 488 { 489 if (taps == 4) 490 return get_filter_4tap_64p(ratio); 491 else if (taps == 2) 492 return get_filter_2tap_64p(); 493 else if (taps == 1) 494 return NULL; 495 else { 496 /* should never happen, bug */ 497 BREAK_TO_DEBUGGER(); 498 return NULL; 499 } 500 } 501 502 static bool dce110_xfmv_power_up_line_buffer(struct transform *xfm) 503 { 504 struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); 505 uint32_t value; 506 507 value = dm_read_reg(xfm_dce->base.ctx, mmLBV_MEMORY_CTRL); 508 509 /*Use all three pieces of memory always*/ 510 set_reg_field_value(value, 0, LBV_MEMORY_CTRL, LB_MEMORY_CONFIG); 511 /*hard coded number DCE11 1712(0x6B0) Partitions: 720/960/1712*/ 512 set_reg_field_value(value, xfm_dce->lb_memory_size, LBV_MEMORY_CTRL, 513 LB_MEMORY_SIZE); 514 515 dm_write_reg(xfm_dce->base.ctx, mmLBV_MEMORY_CTRL, value); 516 517 return true; 518 } 519 520 static void dce110_xfmv_set_scaler( 521 struct transform *xfm, 522 const struct scaler_data *data) 523 { 524 struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); 525 bool is_scaling_required = false; 526 bool filter_updated = false; 527 const uint16_t *coeffs_v, *coeffs_h, *coeffs_h_c, *coeffs_v_c; 528 struct rect luma_viewport = {0}; 529 struct rect chroma_viewport = {0}; 530 531 dce110_xfmv_power_up_line_buffer(xfm); 532 /* 1. Calculate viewport, viewport programming should happen after init 533 * calculations as they may require an adjustment in the viewport. 534 */ 535 536 calculate_viewport(data, &luma_viewport, &chroma_viewport); 537 538 /* 2. Program overscan */ 539 program_overscan(xfm_dce, data); 540 541 /* 3. Program taps and configuration */ 542 is_scaling_required = setup_scaling_configuration(xfm_dce, data); 543 544 if (is_scaling_required) { 545 /* 4. Calculate and program ratio, filter initialization */ 546 547 struct sclv_ratios_inits inits = { 0 }; 548 549 calculate_inits( 550 xfm_dce, 551 data, 552 &inits, 553 &luma_viewport, 554 &chroma_viewport); 555 556 program_scl_ratios_inits(xfm_dce, &inits); 557 558 coeffs_v = get_filter_coeffs_64p(data->taps.v_taps, data->ratios.vert); 559 coeffs_h = get_filter_coeffs_64p(data->taps.h_taps, data->ratios.horz); 560 coeffs_v_c = get_filter_coeffs_64p(data->taps.v_taps_c, data->ratios.vert_c); 561 coeffs_h_c = get_filter_coeffs_64p(data->taps.h_taps_c, data->ratios.horz_c); 562 563 if (coeffs_v != xfm_dce->filter_v 564 || coeffs_v_c != xfm_dce->filter_v_c 565 || coeffs_h != xfm_dce->filter_h 566 || coeffs_h_c != xfm_dce->filter_h_c) { 567 /* 5. Program vertical filters */ 568 program_multi_taps_filter( 569 xfm_dce, 570 data->taps.v_taps, 571 coeffs_v, 572 FILTER_TYPE_RGB_Y_VERTICAL); 573 program_multi_taps_filter( 574 xfm_dce, 575 data->taps.v_taps_c, 576 coeffs_v_c, 577 FILTER_TYPE_CBCR_VERTICAL); 578 579 /* 6. Program horizontal filters */ 580 program_multi_taps_filter( 581 xfm_dce, 582 data->taps.h_taps, 583 coeffs_h, 584 FILTER_TYPE_RGB_Y_HORIZONTAL); 585 program_multi_taps_filter( 586 xfm_dce, 587 data->taps.h_taps_c, 588 coeffs_h_c, 589 FILTER_TYPE_CBCR_HORIZONTAL); 590 591 xfm_dce->filter_v = coeffs_v; 592 xfm_dce->filter_v_c = coeffs_v_c; 593 xfm_dce->filter_h = coeffs_h; 594 xfm_dce->filter_h_c = coeffs_h_c; 595 filter_updated = true; 596 } 597 } 598 599 /* 7. Program the viewport */ 600 program_viewport(xfm_dce, &luma_viewport, &chroma_viewport); 601 602 /* 8. Set bit to flip to new coefficient memory */ 603 if (filter_updated) 604 set_coeff_update_complete(xfm_dce); 605 } 606 607 static void dce110_xfmv_reset(struct transform *xfm) 608 { 609 struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); 610 611 xfm_dce->filter_h = NULL; 612 xfm_dce->filter_v = NULL; 613 xfm_dce->filter_h_c = NULL; 614 xfm_dce->filter_v_c = NULL; 615 } 616 617 static void dce110_xfmv_set_gamut_remap( 618 struct transform *xfm, 619 const struct xfm_grph_csc_adjustment *adjust) 620 { 621 /* DO NOTHING*/ 622 } 623 624 static void dce110_xfmv_set_pixel_storage_depth( 625 struct transform *xfm, 626 enum lb_pixel_depth depth, 627 const struct bit_depth_reduction_params *bit_depth_params) 628 { 629 struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); 630 int pixel_depth = 0; 631 int expan_mode = 0; 632 uint32_t reg_data = 0; 633 634 switch (depth) { 635 case LB_PIXEL_DEPTH_18BPP: 636 pixel_depth = 2; 637 expan_mode = 1; 638 break; 639 case LB_PIXEL_DEPTH_24BPP: 640 pixel_depth = 1; 641 expan_mode = 1; 642 break; 643 case LB_PIXEL_DEPTH_30BPP: 644 pixel_depth = 0; 645 expan_mode = 1; 646 break; 647 case LB_PIXEL_DEPTH_36BPP: 648 pixel_depth = 3; 649 expan_mode = 0; 650 break; 651 default: 652 BREAK_TO_DEBUGGER(); 653 break; 654 } 655 656 set_reg_field_value( 657 reg_data, 658 expan_mode, 659 LBV_DATA_FORMAT, 660 PIXEL_EXPAN_MODE); 661 662 set_reg_field_value( 663 reg_data, 664 pixel_depth, 665 LBV_DATA_FORMAT, 666 PIXEL_DEPTH); 667 668 dm_write_reg(xfm->ctx, mmLBV_DATA_FORMAT, reg_data); 669 670 if (!(xfm_dce->lb_pixel_depth_supported & depth)) { 671 /*we should use unsupported capabilities 672 * unless it is required by w/a*/ 673 DC_LOG_WARNING(xfm->ctx->logger, 674 "%s: Capability not supported", 675 __func__); 676 } 677 } 678 679 static const struct transform_funcs dce110_xfmv_funcs = { 680 .transform_reset = dce110_xfmv_reset, 681 .transform_set_scaler = dce110_xfmv_set_scaler, 682 .transform_set_gamut_remap = 683 dce110_xfmv_set_gamut_remap, 684 .opp_set_csc_default = dce110_opp_v_set_csc_default, 685 .opp_set_csc_adjustment = dce110_opp_v_set_csc_adjustment, 686 .opp_power_on_regamma_lut = dce110_opp_power_on_regamma_lut_v, 687 .opp_program_regamma_pwl = dce110_opp_program_regamma_pwl_v, 688 .opp_set_regamma_mode = dce110_opp_set_regamma_mode_v, 689 .transform_set_pixel_storage_depth = 690 dce110_xfmv_set_pixel_storage_depth, 691 .transform_get_optimal_number_of_taps = 692 dce_transform_get_optimal_number_of_taps 693 }; 694 /*****************************************/ 695 /* Constructor, Destructor */ 696 /*****************************************/ 697 698 bool dce110_transform_v_construct( 699 struct dce_transform *xfm_dce, 700 struct dc_context *ctx) 701 { 702 xfm_dce->base.ctx = ctx; 703 704 xfm_dce->base.funcs = &dce110_xfmv_funcs; 705 706 xfm_dce->lb_pixel_depth_supported = 707 LB_PIXEL_DEPTH_18BPP | 708 LB_PIXEL_DEPTH_24BPP | 709 LB_PIXEL_DEPTH_30BPP; 710 711 xfm_dce->prescaler_on = true; 712 xfm_dce->lb_bits_per_entry = LB_BITS_PER_ENTRY; 713 xfm_dce->lb_memory_size = LB_TOTAL_NUMBER_OF_ENTRIES; /*0x6B0*/ 714 715 return true; 716 } 717