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