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