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: void 226 */ 227 static void program_overscan( 228 struct dce_transform *xfm_dce, 229 const struct scaler_data *data) 230 { 231 uint32_t overscan_left_right = 0; 232 uint32_t overscan_top_bottom = 0; 233 234 int overscan_right = data->h_active - data->recout.x - data->recout.width; 235 int overscan_bottom = data->v_active - data->recout.y - data->recout.height; 236 237 if (xfm_dce->base.ctx->dc->debug.visual_confirm != VISUAL_CONFIRM_DISABLE) { 238 overscan_bottom += 2; 239 overscan_right += 2; 240 } 241 242 if (overscan_right < 0) { 243 BREAK_TO_DEBUGGER(); 244 overscan_right = 0; 245 } 246 if (overscan_bottom < 0) { 247 BREAK_TO_DEBUGGER(); 248 overscan_bottom = 0; 249 } 250 251 set_reg_field_value(overscan_left_right, data->recout.x, 252 EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT); 253 254 set_reg_field_value(overscan_left_right, overscan_right, 255 EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT); 256 257 set_reg_field_value(overscan_top_bottom, data->recout.y, 258 EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP); 259 260 set_reg_field_value(overscan_top_bottom, overscan_bottom, 261 EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM); 262 263 dm_write_reg(xfm_dce->base.ctx, 264 mmSCLV_EXT_OVERSCAN_LEFT_RIGHT, 265 overscan_left_right); 266 267 dm_write_reg(xfm_dce->base.ctx, 268 mmSCLV_EXT_OVERSCAN_TOP_BOTTOM, 269 overscan_top_bottom); 270 } 271 272 static void set_coeff_update_complete( 273 struct dce_transform *xfm_dce) 274 { 275 uint32_t value; 276 277 value = dm_read_reg(xfm_dce->base.ctx, mmSCLV_UPDATE); 278 set_reg_field_value(value, 1, SCLV_UPDATE, SCL_COEF_UPDATE_COMPLETE); 279 dm_write_reg(xfm_dce->base.ctx, mmSCLV_UPDATE, value); 280 } 281 282 static void program_multi_taps_filter( 283 struct dce_transform *xfm_dce, 284 int taps, 285 const uint16_t *coeffs, 286 enum ram_filter_type filter_type) 287 { 288 struct dc_context *ctx = xfm_dce->base.ctx; 289 int i, phase, pair; 290 int array_idx = 0; 291 int taps_pairs = (taps + 1) / 2; 292 int phases_to_program = SCLV_PHASES / 2 + 1; 293 294 uint32_t select = 0; 295 uint32_t power_ctl, power_ctl_off; 296 297 if (!coeffs) 298 return; 299 300 /*We need to disable power gating on coeff memory to do programming*/ 301 power_ctl = dm_read_reg(ctx, mmDCFEV_MEM_PWR_CTRL); 302 power_ctl_off = power_ctl; 303 set_reg_field_value(power_ctl_off, 1, DCFEV_MEM_PWR_CTRL, SCLV_COEFF_MEM_PWR_DIS); 304 dm_write_reg(ctx, mmDCFEV_MEM_PWR_CTRL, power_ctl_off); 305 306 /*Wait to disable gating:*/ 307 for (i = 0; i < 10; i++) { 308 if (get_reg_field_value( 309 dm_read_reg(ctx, mmDCFEV_MEM_PWR_STATUS), 310 DCFEV_MEM_PWR_STATUS, 311 SCLV_COEFF_MEM_PWR_STATE) == 0) 312 break; 313 314 udelay(1); 315 } 316 317 set_reg_field_value(select, filter_type, SCLV_COEF_RAM_SELECT, SCL_C_RAM_FILTER_TYPE); 318 319 for (phase = 0; phase < phases_to_program; phase++) { 320 /*we always program N/2 + 1 phases, total phases N, but N/2-1 are just mirror 321 phase 0 is unique and phase N/2 is unique if N is even*/ 322 set_reg_field_value(select, phase, SCLV_COEF_RAM_SELECT, SCL_C_RAM_PHASE); 323 for (pair = 0; pair < taps_pairs; pair++) { 324 uint32_t data = 0; 325 326 set_reg_field_value(select, pair, 327 SCLV_COEF_RAM_SELECT, SCL_C_RAM_TAP_PAIR_IDX); 328 329 dm_write_reg(ctx, mmSCLV_COEF_RAM_SELECT, select); 330 331 set_reg_field_value( 332 data, 1, 333 SCLV_COEF_RAM_TAP_DATA, 334 SCL_C_RAM_EVEN_TAP_COEF_EN); 335 set_reg_field_value( 336 data, coeffs[array_idx], 337 SCLV_COEF_RAM_TAP_DATA, 338 SCL_C_RAM_EVEN_TAP_COEF); 339 340 if (taps % 2 && pair == taps_pairs - 1) { 341 set_reg_field_value( 342 data, 0, 343 SCLV_COEF_RAM_TAP_DATA, 344 SCL_C_RAM_ODD_TAP_COEF_EN); 345 array_idx++; 346 } else { 347 set_reg_field_value( 348 data, 1, 349 SCLV_COEF_RAM_TAP_DATA, 350 SCL_C_RAM_ODD_TAP_COEF_EN); 351 set_reg_field_value( 352 data, coeffs[array_idx + 1], 353 SCLV_COEF_RAM_TAP_DATA, 354 SCL_C_RAM_ODD_TAP_COEF); 355 356 array_idx += 2; 357 } 358 359 dm_write_reg(ctx, mmSCLV_COEF_RAM_TAP_DATA, data); 360 } 361 } 362 363 /*We need to restore power gating on coeff memory to initial state*/ 364 dm_write_reg(ctx, mmDCFEV_MEM_PWR_CTRL, power_ctl); 365 } 366 367 static void calculate_inits( 368 struct dce_transform *xfm_dce, 369 const struct scaler_data *data, 370 struct sclv_ratios_inits *inits, 371 struct rect *luma_viewport, 372 struct rect *chroma_viewport) 373 { 374 inits->h_int_scale_ratio_luma = 375 dc_fixpt_u2d19(data->ratios.horz) << 5; 376 inits->v_int_scale_ratio_luma = 377 dc_fixpt_u2d19(data->ratios.vert) << 5; 378 inits->h_int_scale_ratio_chroma = 379 dc_fixpt_u2d19(data->ratios.horz_c) << 5; 380 inits->v_int_scale_ratio_chroma = 381 dc_fixpt_u2d19(data->ratios.vert_c) << 5; 382 383 inits->h_init_luma.integer = 1; 384 inits->v_init_luma.integer = 1; 385 inits->h_init_chroma.integer = 1; 386 inits->v_init_chroma.integer = 1; 387 } 388 389 static void program_scl_ratios_inits( 390 struct dce_transform *xfm_dce, 391 struct sclv_ratios_inits *inits) 392 { 393 struct dc_context *ctx = xfm_dce->base.ctx; 394 uint32_t addr = mmSCLV_HORZ_FILTER_SCALE_RATIO; 395 uint32_t value = 0; 396 397 set_reg_field_value( 398 value, 399 inits->h_int_scale_ratio_luma, 400 SCLV_HORZ_FILTER_SCALE_RATIO, 401 SCL_H_SCALE_RATIO); 402 dm_write_reg(ctx, addr, value); 403 404 addr = mmSCLV_VERT_FILTER_SCALE_RATIO; 405 value = 0; 406 set_reg_field_value( 407 value, 408 inits->v_int_scale_ratio_luma, 409 SCLV_VERT_FILTER_SCALE_RATIO, 410 SCL_V_SCALE_RATIO); 411 dm_write_reg(ctx, addr, value); 412 413 addr = mmSCLV_HORZ_FILTER_SCALE_RATIO_C; 414 value = 0; 415 set_reg_field_value( 416 value, 417 inits->h_int_scale_ratio_chroma, 418 SCLV_HORZ_FILTER_SCALE_RATIO_C, 419 SCL_H_SCALE_RATIO_C); 420 dm_write_reg(ctx, addr, value); 421 422 addr = mmSCLV_VERT_FILTER_SCALE_RATIO_C; 423 value = 0; 424 set_reg_field_value( 425 value, 426 inits->v_int_scale_ratio_chroma, 427 SCLV_VERT_FILTER_SCALE_RATIO_C, 428 SCL_V_SCALE_RATIO_C); 429 dm_write_reg(ctx, addr, value); 430 431 addr = mmSCLV_HORZ_FILTER_INIT; 432 value = 0; 433 set_reg_field_value( 434 value, 435 inits->h_init_luma.fraction, 436 SCLV_HORZ_FILTER_INIT, 437 SCL_H_INIT_FRAC); 438 set_reg_field_value( 439 value, 440 inits->h_init_luma.integer, 441 SCLV_HORZ_FILTER_INIT, 442 SCL_H_INIT_INT); 443 dm_write_reg(ctx, addr, value); 444 445 addr = mmSCLV_VERT_FILTER_INIT; 446 value = 0; 447 set_reg_field_value( 448 value, 449 inits->v_init_luma.fraction, 450 SCLV_VERT_FILTER_INIT, 451 SCL_V_INIT_FRAC); 452 set_reg_field_value( 453 value, 454 inits->v_init_luma.integer, 455 SCLV_VERT_FILTER_INIT, 456 SCL_V_INIT_INT); 457 dm_write_reg(ctx, addr, value); 458 459 addr = mmSCLV_HORZ_FILTER_INIT_C; 460 value = 0; 461 set_reg_field_value( 462 value, 463 inits->h_init_chroma.fraction, 464 SCLV_HORZ_FILTER_INIT_C, 465 SCL_H_INIT_FRAC_C); 466 set_reg_field_value( 467 value, 468 inits->h_init_chroma.integer, 469 SCLV_HORZ_FILTER_INIT_C, 470 SCL_H_INIT_INT_C); 471 dm_write_reg(ctx, addr, value); 472 473 addr = mmSCLV_VERT_FILTER_INIT_C; 474 value = 0; 475 set_reg_field_value( 476 value, 477 inits->v_init_chroma.fraction, 478 SCLV_VERT_FILTER_INIT_C, 479 SCL_V_INIT_FRAC_C); 480 set_reg_field_value( 481 value, 482 inits->v_init_chroma.integer, 483 SCLV_VERT_FILTER_INIT_C, 484 SCL_V_INIT_INT_C); 485 dm_write_reg(ctx, addr, value); 486 } 487 488 static const uint16_t *get_filter_coeffs_64p(int taps, struct fixed31_32 ratio) 489 { 490 if (taps == 4) 491 return get_filter_4tap_64p(ratio); 492 else if (taps == 2) 493 return get_filter_2tap_64p(); 494 else if (taps == 1) 495 return NULL; 496 else { 497 /* should never happen, bug */ 498 BREAK_TO_DEBUGGER(); 499 return NULL; 500 } 501 } 502 503 static bool dce110_xfmv_power_up_line_buffer(struct transform *xfm) 504 { 505 struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); 506 uint32_t value; 507 508 value = dm_read_reg(xfm_dce->base.ctx, mmLBV_MEMORY_CTRL); 509 510 /*Use all three pieces of memory always*/ 511 set_reg_field_value(value, 0, LBV_MEMORY_CTRL, LB_MEMORY_CONFIG); 512 /*hard coded number DCE11 1712(0x6B0) Partitions: 720/960/1712*/ 513 set_reg_field_value(value, xfm_dce->lb_memory_size, LBV_MEMORY_CTRL, 514 LB_MEMORY_SIZE); 515 516 dm_write_reg(xfm_dce->base.ctx, mmLBV_MEMORY_CTRL, value); 517 518 return true; 519 } 520 521 static void dce110_xfmv_set_scaler( 522 struct transform *xfm, 523 const struct scaler_data *data) 524 { 525 struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); 526 bool is_scaling_required = false; 527 bool filter_updated = false; 528 const uint16_t *coeffs_v, *coeffs_h, *coeffs_h_c, *coeffs_v_c; 529 struct rect luma_viewport = {0}; 530 struct rect chroma_viewport = {0}; 531 532 dce110_xfmv_power_up_line_buffer(xfm); 533 /* 1. Calculate viewport, viewport programming should happen after init 534 * calculations as they may require an adjustment in the viewport. 535 */ 536 537 calculate_viewport(data, &luma_viewport, &chroma_viewport); 538 539 /* 2. Program overscan */ 540 program_overscan(xfm_dce, data); 541 542 /* 3. Program taps and configuration */ 543 is_scaling_required = setup_scaling_configuration(xfm_dce, data); 544 545 if (is_scaling_required) { 546 /* 4. Calculate and program ratio, filter initialization */ 547 548 struct sclv_ratios_inits inits = { 0 }; 549 550 calculate_inits( 551 xfm_dce, 552 data, 553 &inits, 554 &luma_viewport, 555 &chroma_viewport); 556 557 program_scl_ratios_inits(xfm_dce, &inits); 558 559 coeffs_v = get_filter_coeffs_64p(data->taps.v_taps, data->ratios.vert); 560 coeffs_h = get_filter_coeffs_64p(data->taps.h_taps, data->ratios.horz); 561 coeffs_v_c = get_filter_coeffs_64p(data->taps.v_taps_c, data->ratios.vert_c); 562 coeffs_h_c = get_filter_coeffs_64p(data->taps.h_taps_c, data->ratios.horz_c); 563 564 if (coeffs_v != xfm_dce->filter_v 565 || coeffs_v_c != xfm_dce->filter_v_c 566 || coeffs_h != xfm_dce->filter_h 567 || coeffs_h_c != xfm_dce->filter_h_c) { 568 /* 5. Program vertical filters */ 569 program_multi_taps_filter( 570 xfm_dce, 571 data->taps.v_taps, 572 coeffs_v, 573 FILTER_TYPE_RGB_Y_VERTICAL); 574 program_multi_taps_filter( 575 xfm_dce, 576 data->taps.v_taps_c, 577 coeffs_v_c, 578 FILTER_TYPE_CBCR_VERTICAL); 579 580 /* 6. Program horizontal filters */ 581 program_multi_taps_filter( 582 xfm_dce, 583 data->taps.h_taps, 584 coeffs_h, 585 FILTER_TYPE_RGB_Y_HORIZONTAL); 586 program_multi_taps_filter( 587 xfm_dce, 588 data->taps.h_taps_c, 589 coeffs_h_c, 590 FILTER_TYPE_CBCR_HORIZONTAL); 591 592 xfm_dce->filter_v = coeffs_v; 593 xfm_dce->filter_v_c = coeffs_v_c; 594 xfm_dce->filter_h = coeffs_h; 595 xfm_dce->filter_h_c = coeffs_h_c; 596 filter_updated = true; 597 } 598 } 599 600 /* 7. Program the viewport */ 601 program_viewport(xfm_dce, &luma_viewport, &chroma_viewport); 602 603 /* 8. Set bit to flip to new coefficient memory */ 604 if (filter_updated) 605 set_coeff_update_complete(xfm_dce); 606 } 607 608 static void dce110_xfmv_reset(struct transform *xfm) 609 { 610 struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); 611 612 xfm_dce->filter_h = NULL; 613 xfm_dce->filter_v = NULL; 614 xfm_dce->filter_h_c = NULL; 615 xfm_dce->filter_v_c = NULL; 616 } 617 618 static void dce110_xfmv_set_gamut_remap( 619 struct transform *xfm, 620 const struct xfm_grph_csc_adjustment *adjust) 621 { 622 /* DO NOTHING*/ 623 } 624 625 static void dce110_xfmv_set_pixel_storage_depth( 626 struct transform *xfm, 627 enum lb_pixel_depth depth, 628 const struct bit_depth_reduction_params *bit_depth_params) 629 { 630 struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm); 631 int pixel_depth = 0; 632 int expan_mode = 0; 633 uint32_t reg_data = 0; 634 635 switch (depth) { 636 case LB_PIXEL_DEPTH_18BPP: 637 pixel_depth = 2; 638 expan_mode = 1; 639 break; 640 case LB_PIXEL_DEPTH_24BPP: 641 pixel_depth = 1; 642 expan_mode = 1; 643 break; 644 case LB_PIXEL_DEPTH_30BPP: 645 pixel_depth = 0; 646 expan_mode = 1; 647 break; 648 case LB_PIXEL_DEPTH_36BPP: 649 pixel_depth = 3; 650 expan_mode = 0; 651 break; 652 default: 653 BREAK_TO_DEBUGGER(); 654 break; 655 } 656 657 set_reg_field_value( 658 reg_data, 659 expan_mode, 660 LBV_DATA_FORMAT, 661 PIXEL_EXPAN_MODE); 662 663 set_reg_field_value( 664 reg_data, 665 pixel_depth, 666 LBV_DATA_FORMAT, 667 PIXEL_DEPTH); 668 669 dm_write_reg(xfm->ctx, mmLBV_DATA_FORMAT, reg_data); 670 671 if (!(xfm_dce->lb_pixel_depth_supported & depth)) { 672 /*we should use unsupported capabilities 673 * unless it is required by w/a*/ 674 DC_LOG_WARNING("%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 LB_PIXEL_DEPTH_36BPP; 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