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