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