root/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. dpp1_dscl_set_overscan
  2. dpp1_dscl_set_otg_blank
  3. dpp1_dscl_get_pixel_depth_val
  4. dpp1_dscl_is_video_format
  5. dpp1_dscl_is_420_format
  6. dpp1_dscl_get_dscl_mode
  7. dpp1_dscl_set_lb
  8. dpp1_dscl_get_filter_coeffs_64p
  9. dpp1_dscl_set_scaler_filter
  10. dpp1_dscl_set_scl_filter
  11. dpp1_dscl_get_lb_depth_bpc
  12. dpp1_dscl_calc_lb_num_partitions
  13. dpp1_dscl_is_lb_conf_valid
  14. dpp1_dscl_find_lb_memory_config
  15. dpp1_dscl_set_scaler_auto_scale
  16. dpp1_dscl_set_manual_ratio_init
  17. dpp1_dscl_set_recout
  18. dpp1_dscl_set_scaler_manual_scale

   1 /*
   2  * Copyright 2016 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 "dm_services.h"
  27 
  28 #include "core_types.h"
  29 
  30 #include "reg_helper.h"
  31 #include "dcn10_dpp.h"
  32 #include "basics/conversion.h"
  33 
  34 
  35 #define NUM_PHASES    64
  36 #define HORZ_MAX_TAPS 8
  37 #define VERT_MAX_TAPS 8
  38 
  39 #define BLACK_OFFSET_RGB_Y 0x0
  40 #define BLACK_OFFSET_CBCR  0x8000
  41 
  42 #define REG(reg)\
  43         dpp->tf_regs->reg
  44 
  45 #define CTX \
  46         dpp->base.ctx
  47 
  48 #undef FN
  49 #define FN(reg_name, field_name) \
  50         dpp->tf_shift->field_name, dpp->tf_mask->field_name
  51 
  52 enum dcn10_coef_filter_type_sel {
  53         SCL_COEF_LUMA_VERT_FILTER = 0,
  54         SCL_COEF_LUMA_HORZ_FILTER = 1,
  55         SCL_COEF_CHROMA_VERT_FILTER = 2,
  56         SCL_COEF_CHROMA_HORZ_FILTER = 3,
  57         SCL_COEF_ALPHA_VERT_FILTER = 4,
  58         SCL_COEF_ALPHA_HORZ_FILTER = 5
  59 };
  60 
  61 enum dscl_autocal_mode {
  62         AUTOCAL_MODE_OFF = 0,
  63 
  64         /* Autocal calculate the scaling ratio and initial phase and the
  65          * DSCL_MODE_SEL must be set to 1
  66          */
  67         AUTOCAL_MODE_AUTOSCALE = 1,
  68         /* Autocal perform auto centering without replication and the
  69          * DSCL_MODE_SEL must be set to 0
  70          */
  71         AUTOCAL_MODE_AUTOCENTER = 2,
  72         /* Autocal perform auto centering and auto replication and the
  73          * DSCL_MODE_SEL must be set to 0
  74          */
  75         AUTOCAL_MODE_AUTOREPLICATE = 3
  76 };
  77 
  78 enum dscl_mode_sel {
  79         DSCL_MODE_SCALING_444_BYPASS = 0,
  80         DSCL_MODE_SCALING_444_RGB_ENABLE = 1,
  81         DSCL_MODE_SCALING_444_YCBCR_ENABLE = 2,
  82         DSCL_MODE_SCALING_420_YCBCR_ENABLE = 3,
  83         DSCL_MODE_SCALING_420_LUMA_BYPASS = 4,
  84         DSCL_MODE_SCALING_420_CHROMA_BYPASS = 5,
  85         DSCL_MODE_DSCL_BYPASS = 6
  86 };
  87 
  88 static void dpp1_dscl_set_overscan(
  89         struct dcn10_dpp *dpp,
  90         const struct scaler_data *data)
  91 {
  92         uint32_t left = data->recout.x;
  93         uint32_t top = data->recout.y;
  94 
  95         int right = data->h_active - data->recout.x - data->recout.width;
  96         int bottom = data->v_active - data->recout.y - data->recout.height;
  97 
  98         if (right < 0) {
  99                 BREAK_TO_DEBUGGER();
 100                 right = 0;
 101         }
 102         if (bottom < 0) {
 103                 BREAK_TO_DEBUGGER();
 104                 bottom = 0;
 105         }
 106 
 107         REG_SET_2(DSCL_EXT_OVERSCAN_LEFT_RIGHT, 0,
 108                 EXT_OVERSCAN_LEFT, left,
 109                 EXT_OVERSCAN_RIGHT, right);
 110 
 111         REG_SET_2(DSCL_EXT_OVERSCAN_TOP_BOTTOM, 0,
 112                 EXT_OVERSCAN_BOTTOM, bottom,
 113                 EXT_OVERSCAN_TOP, top);
 114 }
 115 
 116 static void dpp1_dscl_set_otg_blank(
 117                 struct dcn10_dpp *dpp, const struct scaler_data *data)
 118 {
 119         uint32_t h_blank_start = data->h_active;
 120         uint32_t h_blank_end = 0;
 121         uint32_t v_blank_start = data->v_active;
 122         uint32_t v_blank_end = 0;
 123 
 124         REG_SET_2(OTG_H_BLANK, 0,
 125                         OTG_H_BLANK_START, h_blank_start,
 126                         OTG_H_BLANK_END, h_blank_end);
 127 
 128         REG_SET_2(OTG_V_BLANK, 0,
 129                         OTG_V_BLANK_START, v_blank_start,
 130                         OTG_V_BLANK_END, v_blank_end);
 131 }
 132 
 133 static int dpp1_dscl_get_pixel_depth_val(enum lb_pixel_depth depth)
 134 {
 135         if (depth == LB_PIXEL_DEPTH_30BPP)
 136                 return 0; /* 10 bpc */
 137         else if (depth == LB_PIXEL_DEPTH_24BPP)
 138                 return 1; /* 8 bpc */
 139         else if (depth == LB_PIXEL_DEPTH_18BPP)
 140                 return 2; /* 6 bpc */
 141         else if (depth == LB_PIXEL_DEPTH_36BPP)
 142                 return 3; /* 12 bpc */
 143         else {
 144                 ASSERT(0);
 145                 return -1; /* Unsupported */
 146         }
 147 }
 148 
 149 static bool dpp1_dscl_is_video_format(enum pixel_format format)
 150 {
 151         if (format >= PIXEL_FORMAT_VIDEO_BEGIN
 152                         && format <= PIXEL_FORMAT_VIDEO_END)
 153                 return true;
 154         else
 155                 return false;
 156 }
 157 
 158 static bool dpp1_dscl_is_420_format(enum pixel_format format)
 159 {
 160         if (format == PIXEL_FORMAT_420BPP8 ||
 161                         format == PIXEL_FORMAT_420BPP10)
 162                 return true;
 163         else
 164                 return false;
 165 }
 166 
 167 static enum dscl_mode_sel dpp1_dscl_get_dscl_mode(
 168                 struct dpp *dpp_base,
 169                 const struct scaler_data *data,
 170                 bool dbg_always_scale)
 171 {
 172         const long long one = dc_fixpt_one.value;
 173 
 174         if (dpp_base->caps->dscl_data_proc_format == DSCL_DATA_PRCESSING_FIXED_FORMAT) {
 175                 /* DSCL is processing data in fixed format */
 176                 if (data->format == PIXEL_FORMAT_FP16)
 177                         return DSCL_MODE_DSCL_BYPASS;
 178         }
 179 
 180         if (data->ratios.horz.value == one
 181                         && data->ratios.vert.value == one
 182                         && data->ratios.horz_c.value == one
 183                         && data->ratios.vert_c.value == one
 184                         && !dbg_always_scale)
 185                 return DSCL_MODE_SCALING_444_BYPASS;
 186 
 187         if (!dpp1_dscl_is_420_format(data->format)) {
 188                 if (dpp1_dscl_is_video_format(data->format))
 189                         return DSCL_MODE_SCALING_444_YCBCR_ENABLE;
 190                 else
 191                         return DSCL_MODE_SCALING_444_RGB_ENABLE;
 192         }
 193         if (data->ratios.horz.value == one && data->ratios.vert.value == one)
 194                 return DSCL_MODE_SCALING_420_LUMA_BYPASS;
 195         if (data->ratios.horz_c.value == one && data->ratios.vert_c.value == one)
 196                 return DSCL_MODE_SCALING_420_CHROMA_BYPASS;
 197 
 198         return DSCL_MODE_SCALING_420_YCBCR_ENABLE;
 199 }
 200 
 201 static void dpp1_dscl_set_lb(
 202         struct dcn10_dpp *dpp,
 203         const struct line_buffer_params *lb_params,
 204         enum lb_memory_config mem_size_config)
 205 {
 206         /* LB */
 207         if (dpp->base.caps->dscl_data_proc_format == DSCL_DATA_PRCESSING_FIXED_FORMAT) {
 208                 /* DSCL caps: pixel data processed in fixed format */
 209                 uint32_t pixel_depth = dpp1_dscl_get_pixel_depth_val(lb_params->depth);
 210                 uint32_t dyn_pix_depth = lb_params->dynamic_pixel_depth;
 211 
 212                 REG_SET_7(LB_DATA_FORMAT, 0,
 213                         PIXEL_DEPTH, pixel_depth, /* Pixel depth stored in LB */
 214                         PIXEL_EXPAN_MODE, lb_params->pixel_expan_mode, /* Pixel expansion mode */
 215                         PIXEL_REDUCE_MODE, 1, /* Pixel reduction mode: Rounding */
 216                         DYNAMIC_PIXEL_DEPTH, dyn_pix_depth, /* Dynamic expansion pixel depth */
 217                         DITHER_EN, 0, /* Dithering enable: Disabled */
 218                         INTERLEAVE_EN, lb_params->interleave_en, /* Interleave source enable */
 219                         LB_DATA_FORMAT__ALPHA_EN, lb_params->alpha_en); /* Alpha enable */
 220         }
 221 #if defined(CONFIG_DRM_AMD_DC_DCN2_0)
 222         else {
 223                 /* DSCL caps: pixel data processed in float format */
 224                 REG_SET_2(LB_DATA_FORMAT, 0,
 225                         INTERLEAVE_EN, lb_params->interleave_en, /* Interleave source enable */
 226                         LB_DATA_FORMAT__ALPHA_EN, lb_params->alpha_en); /* Alpha enable */
 227         }
 228 #endif
 229 
 230         REG_SET_2(LB_MEMORY_CTRL, 0,
 231                 MEMORY_CONFIG, mem_size_config,
 232                 LB_MAX_PARTITIONS, 63);
 233 }
 234 
 235 static const uint16_t *dpp1_dscl_get_filter_coeffs_64p(int taps, struct fixed31_32 ratio)
 236 {
 237         if (taps == 8)
 238                 return get_filter_8tap_64p(ratio);
 239         else if (taps == 7)
 240                 return get_filter_7tap_64p(ratio);
 241         else if (taps == 6)
 242                 return get_filter_6tap_64p(ratio);
 243         else if (taps == 5)
 244                 return get_filter_5tap_64p(ratio);
 245         else if (taps == 4)
 246                 return get_filter_4tap_64p(ratio);
 247         else if (taps == 3)
 248                 return get_filter_3tap_64p(ratio);
 249         else if (taps == 2)
 250                 return get_filter_2tap_64p();
 251         else if (taps == 1)
 252                 return NULL;
 253         else {
 254                 /* should never happen, bug */
 255                 BREAK_TO_DEBUGGER();
 256                 return NULL;
 257         }
 258 }
 259 
 260 static void dpp1_dscl_set_scaler_filter(
 261                 struct dcn10_dpp *dpp,
 262                 uint32_t taps,
 263                 enum dcn10_coef_filter_type_sel filter_type,
 264                 const uint16_t *filter)
 265 {
 266         const int tap_pairs = (taps + 1) / 2;
 267         int phase;
 268         int pair;
 269         uint16_t odd_coef, even_coef;
 270 
 271         REG_SET_3(SCL_COEF_RAM_TAP_SELECT, 0,
 272                 SCL_COEF_RAM_TAP_PAIR_IDX, 0,
 273                 SCL_COEF_RAM_PHASE, 0,
 274                 SCL_COEF_RAM_FILTER_TYPE, filter_type);
 275 
 276         for (phase = 0; phase < (NUM_PHASES / 2 + 1); phase++) {
 277                 for (pair = 0; pair < tap_pairs; pair++) {
 278                         even_coef = filter[phase * taps + 2 * pair];
 279                         if ((pair * 2 + 1) < taps)
 280                                 odd_coef = filter[phase * taps + 2 * pair + 1];
 281                         else
 282                                 odd_coef = 0;
 283 
 284                         REG_SET_4(SCL_COEF_RAM_TAP_DATA, 0,
 285                                 /* Even tap coefficient (bits 1:0 fixed to 0) */
 286                                 SCL_COEF_RAM_EVEN_TAP_COEF, even_coef,
 287                                 /* Write/read control for even coefficient */
 288                                 SCL_COEF_RAM_EVEN_TAP_COEF_EN, 1,
 289                                 /* Odd tap coefficient (bits 1:0 fixed to 0) */
 290                                 SCL_COEF_RAM_ODD_TAP_COEF, odd_coef,
 291                                 /* Write/read control for odd coefficient */
 292                                 SCL_COEF_RAM_ODD_TAP_COEF_EN, 1);
 293                 }
 294         }
 295 
 296 }
 297 
 298 static void dpp1_dscl_set_scl_filter(
 299                 struct dcn10_dpp *dpp,
 300                 const struct scaler_data *scl_data,
 301                 bool chroma_coef_mode)
 302 {
 303         bool h_2tap_hardcode_coef_en = false;
 304         bool v_2tap_hardcode_coef_en = false;
 305         bool h_2tap_sharp_en = false;
 306         bool v_2tap_sharp_en = false;
 307         uint32_t h_2tap_sharp_factor = scl_data->sharpness.horz;
 308         uint32_t v_2tap_sharp_factor = scl_data->sharpness.vert;
 309         bool coef_ram_current;
 310         const uint16_t *filter_h = NULL;
 311         const uint16_t *filter_v = NULL;
 312         const uint16_t *filter_h_c = NULL;
 313         const uint16_t *filter_v_c = NULL;
 314 
 315         h_2tap_hardcode_coef_en = scl_data->taps.h_taps < 3
 316                                         && scl_data->taps.h_taps_c < 3
 317                 && (scl_data->taps.h_taps > 1 && scl_data->taps.h_taps_c > 1);
 318         v_2tap_hardcode_coef_en = scl_data->taps.v_taps < 3
 319                                         && scl_data->taps.v_taps_c < 3
 320                 && (scl_data->taps.v_taps > 1 && scl_data->taps.v_taps_c > 1);
 321 
 322         h_2tap_sharp_en = h_2tap_hardcode_coef_en && h_2tap_sharp_factor != 0;
 323         v_2tap_sharp_en = v_2tap_hardcode_coef_en && v_2tap_sharp_factor != 0;
 324 
 325         REG_UPDATE_6(DSCL_2TAP_CONTROL,
 326                 SCL_H_2TAP_HARDCODE_COEF_EN, h_2tap_hardcode_coef_en,
 327                 SCL_H_2TAP_SHARP_EN, h_2tap_sharp_en,
 328                 SCL_H_2TAP_SHARP_FACTOR, h_2tap_sharp_factor,
 329                 SCL_V_2TAP_HARDCODE_COEF_EN, v_2tap_hardcode_coef_en,
 330                 SCL_V_2TAP_SHARP_EN, v_2tap_sharp_en,
 331                 SCL_V_2TAP_SHARP_FACTOR, v_2tap_sharp_factor);
 332 
 333         if (!v_2tap_hardcode_coef_en || !h_2tap_hardcode_coef_en) {
 334                 bool filter_updated = false;
 335 
 336                 filter_h = dpp1_dscl_get_filter_coeffs_64p(
 337                                 scl_data->taps.h_taps, scl_data->ratios.horz);
 338                 filter_v = dpp1_dscl_get_filter_coeffs_64p(
 339                                 scl_data->taps.v_taps, scl_data->ratios.vert);
 340 
 341                 filter_updated = (filter_h && (filter_h != dpp->filter_h))
 342                                 || (filter_v && (filter_v != dpp->filter_v));
 343 
 344                 if (chroma_coef_mode) {
 345                         filter_h_c = dpp1_dscl_get_filter_coeffs_64p(
 346                                         scl_data->taps.h_taps_c, scl_data->ratios.horz_c);
 347                         filter_v_c = dpp1_dscl_get_filter_coeffs_64p(
 348                                         scl_data->taps.v_taps_c, scl_data->ratios.vert_c);
 349                         filter_updated = filter_updated || (filter_h_c && (filter_h_c != dpp->filter_h_c))
 350                                                         || (filter_v_c && (filter_v_c != dpp->filter_v_c));
 351                 }
 352 
 353                 if (filter_updated) {
 354                         uint32_t scl_mode = REG_READ(SCL_MODE);
 355 
 356                         if (!h_2tap_hardcode_coef_en && filter_h) {
 357                                 dpp1_dscl_set_scaler_filter(
 358                                         dpp, scl_data->taps.h_taps,
 359                                         SCL_COEF_LUMA_HORZ_FILTER, filter_h);
 360                         }
 361                         dpp->filter_h = filter_h;
 362                         if (!v_2tap_hardcode_coef_en && filter_v) {
 363                                 dpp1_dscl_set_scaler_filter(
 364                                         dpp, scl_data->taps.v_taps,
 365                                         SCL_COEF_LUMA_VERT_FILTER, filter_v);
 366                         }
 367                         dpp->filter_v = filter_v;
 368                         if (chroma_coef_mode) {
 369                                 if (!h_2tap_hardcode_coef_en && filter_h_c) {
 370                                         dpp1_dscl_set_scaler_filter(
 371                                                 dpp, scl_data->taps.h_taps_c,
 372                                                 SCL_COEF_CHROMA_HORZ_FILTER, filter_h_c);
 373                                 }
 374                                 if (!v_2tap_hardcode_coef_en && filter_v_c) {
 375                                         dpp1_dscl_set_scaler_filter(
 376                                                 dpp, scl_data->taps.v_taps_c,
 377                                                 SCL_COEF_CHROMA_VERT_FILTER, filter_v_c);
 378                                 }
 379                         }
 380                         dpp->filter_h_c = filter_h_c;
 381                         dpp->filter_v_c = filter_v_c;
 382 
 383                         coef_ram_current = get_reg_field_value_ex(
 384                                 scl_mode, dpp->tf_mask->SCL_COEF_RAM_SELECT_CURRENT,
 385                                 dpp->tf_shift->SCL_COEF_RAM_SELECT_CURRENT);
 386 
 387                         /* Swap coefficient RAM and set chroma coefficient mode */
 388                         REG_SET_2(SCL_MODE, scl_mode,
 389                                         SCL_COEF_RAM_SELECT, !coef_ram_current,
 390                                         SCL_CHROMA_COEF_MODE, chroma_coef_mode);
 391                 }
 392         }
 393 }
 394 
 395 static int dpp1_dscl_get_lb_depth_bpc(enum lb_pixel_depth depth)
 396 {
 397         if (depth == LB_PIXEL_DEPTH_30BPP)
 398                 return 10;
 399         else if (depth == LB_PIXEL_DEPTH_24BPP)
 400                 return 8;
 401         else if (depth == LB_PIXEL_DEPTH_18BPP)
 402                 return 6;
 403         else if (depth == LB_PIXEL_DEPTH_36BPP)
 404                 return 12;
 405         else {
 406                 BREAK_TO_DEBUGGER();
 407                 return -1; /* Unsupported */
 408         }
 409 }
 410 
 411 void dpp1_dscl_calc_lb_num_partitions(
 412                 const struct scaler_data *scl_data,
 413                 enum lb_memory_config lb_config,
 414                 int *num_part_y,
 415                 int *num_part_c)
 416 {
 417         int lb_memory_size, lb_memory_size_c, lb_memory_size_a, num_partitions_a,
 418         lb_bpc, memory_line_size_y, memory_line_size_c, memory_line_size_a;
 419 
 420         int line_size = scl_data->viewport.width < scl_data->recout.width ?
 421                         scl_data->viewport.width : scl_data->recout.width;
 422         int line_size_c = scl_data->viewport_c.width < scl_data->recout.width ?
 423                         scl_data->viewport_c.width : scl_data->recout.width;
 424 
 425         if (line_size == 0)
 426                 line_size = 1;
 427 
 428         if (line_size_c == 0)
 429                 line_size_c = 1;
 430 
 431 
 432         lb_bpc = dpp1_dscl_get_lb_depth_bpc(scl_data->lb_params.depth);
 433         memory_line_size_y = (line_size * lb_bpc + 71) / 72; /* +71 to ceil */
 434         memory_line_size_c = (line_size_c * lb_bpc + 71) / 72; /* +71 to ceil */
 435         memory_line_size_a = (line_size + 5) / 6; /* +5 to ceil */
 436 
 437         if (lb_config == LB_MEMORY_CONFIG_1) {
 438                 lb_memory_size = 816;
 439                 lb_memory_size_c = 816;
 440                 lb_memory_size_a = 984;
 441         } else if (lb_config == LB_MEMORY_CONFIG_2) {
 442                 lb_memory_size = 1088;
 443                 lb_memory_size_c = 1088;
 444                 lb_memory_size_a = 1312;
 445         } else if (lb_config == LB_MEMORY_CONFIG_3) {
 446                 /* 420 mode: using 3rd mem from Y, Cr and Cb */
 447                 lb_memory_size = 816 + 1088 + 848 + 848 + 848;
 448                 lb_memory_size_c = 816 + 1088;
 449                 lb_memory_size_a = 984 + 1312 + 456;
 450         } else {
 451                 lb_memory_size = 816 + 1088 + 848;
 452                 lb_memory_size_c = 816 + 1088 + 848;
 453                 lb_memory_size_a = 984 + 1312 + 456;
 454         }
 455         *num_part_y = lb_memory_size / memory_line_size_y;
 456         *num_part_c = lb_memory_size_c / memory_line_size_c;
 457         num_partitions_a = lb_memory_size_a / memory_line_size_a;
 458 
 459         if (scl_data->lb_params.alpha_en
 460                         && (num_partitions_a < *num_part_y))
 461                 *num_part_y = num_partitions_a;
 462 
 463         if (*num_part_y > 64)
 464                 *num_part_y = 64;
 465         if (*num_part_c > 64)
 466                 *num_part_c = 64;
 467 
 468 }
 469 
 470 bool dpp1_dscl_is_lb_conf_valid(int ceil_vratio, int num_partitions, int vtaps)
 471 {
 472         if (ceil_vratio > 2)
 473                 return vtaps <= (num_partitions - ceil_vratio + 2);
 474         else
 475                 return vtaps <= num_partitions;
 476 }
 477 
 478 /*find first match configuration which meets the min required lb size*/
 479 static enum lb_memory_config dpp1_dscl_find_lb_memory_config(struct dcn10_dpp *dpp,
 480                 const struct scaler_data *scl_data)
 481 {
 482         int num_part_y, num_part_c;
 483         int vtaps = scl_data->taps.v_taps;
 484         int vtaps_c = scl_data->taps.v_taps_c;
 485         int ceil_vratio = dc_fixpt_ceil(scl_data->ratios.vert);
 486         int ceil_vratio_c = dc_fixpt_ceil(scl_data->ratios.vert_c);
 487         enum lb_memory_config mem_cfg = LB_MEMORY_CONFIG_0;
 488 
 489         if (dpp->base.ctx->dc->debug.use_max_lb)
 490                 return mem_cfg;
 491 
 492         dpp->base.caps->dscl_calc_lb_num_partitions(
 493                         scl_data, LB_MEMORY_CONFIG_1, &num_part_y, &num_part_c);
 494 
 495         if (dpp1_dscl_is_lb_conf_valid(ceil_vratio, num_part_y, vtaps)
 496                         && dpp1_dscl_is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c))
 497                 return LB_MEMORY_CONFIG_1;
 498 
 499         dpp->base.caps->dscl_calc_lb_num_partitions(
 500                         scl_data, LB_MEMORY_CONFIG_2, &num_part_y, &num_part_c);
 501 
 502         if (dpp1_dscl_is_lb_conf_valid(ceil_vratio, num_part_y, vtaps)
 503                         && dpp1_dscl_is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c))
 504                 return LB_MEMORY_CONFIG_2;
 505 
 506         if (scl_data->format == PIXEL_FORMAT_420BPP8
 507                         || scl_data->format == PIXEL_FORMAT_420BPP10) {
 508                 dpp->base.caps->dscl_calc_lb_num_partitions(
 509                                 scl_data, LB_MEMORY_CONFIG_3, &num_part_y, &num_part_c);
 510 
 511                 if (dpp1_dscl_is_lb_conf_valid(ceil_vratio, num_part_y, vtaps)
 512                                 && dpp1_dscl_is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c))
 513                         return LB_MEMORY_CONFIG_3;
 514         }
 515 
 516         dpp->base.caps->dscl_calc_lb_num_partitions(
 517                         scl_data, LB_MEMORY_CONFIG_0, &num_part_y, &num_part_c);
 518 
 519         /*Ensure we can support the requested number of vtaps*/
 520         ASSERT(dpp1_dscl_is_lb_conf_valid(ceil_vratio, num_part_y, vtaps)
 521                         && dpp1_dscl_is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c));
 522 
 523         return LB_MEMORY_CONFIG_0;
 524 }
 525 
 526 void dpp1_dscl_set_scaler_auto_scale(
 527         struct dpp *dpp_base,
 528         const struct scaler_data *scl_data)
 529 {
 530         enum lb_memory_config lb_config;
 531         struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
 532         enum dscl_mode_sel dscl_mode = dpp1_dscl_get_dscl_mode(
 533                         dpp_base, scl_data, dpp_base->ctx->dc->debug.always_scale);
 534         bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN
 535                                 && scl_data->format <= PIXEL_FORMAT_VIDEO_END;
 536 
 537         dpp1_dscl_set_overscan(dpp, scl_data);
 538 
 539         dpp1_dscl_set_otg_blank(dpp, scl_data);
 540 
 541         REG_UPDATE(SCL_MODE, DSCL_MODE, dscl_mode);
 542 
 543         if (dscl_mode == DSCL_MODE_DSCL_BYPASS)
 544                 return;
 545 
 546         lb_config =  dpp1_dscl_find_lb_memory_config(dpp, scl_data);
 547         dpp1_dscl_set_lb(dpp, &scl_data->lb_params, lb_config);
 548 
 549         if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS)
 550                 return;
 551 
 552         /* TODO: v_min */
 553         REG_SET_3(DSCL_AUTOCAL, 0,
 554                 AUTOCAL_MODE, AUTOCAL_MODE_AUTOSCALE,
 555                 AUTOCAL_NUM_PIPE, 0,
 556                 AUTOCAL_PIPE_ID, 0);
 557 
 558         /* Black offsets */
 559         if (ycbcr)
 560                 REG_SET_2(SCL_BLACK_OFFSET, 0,
 561                                 SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y,
 562                                 SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_CBCR);
 563         else
 564 
 565                 REG_SET_2(SCL_BLACK_OFFSET, 0,
 566                                 SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y,
 567                                 SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_RGB_Y);
 568 
 569         REG_SET_4(SCL_TAP_CONTROL, 0,
 570                 SCL_V_NUM_TAPS, scl_data->taps.v_taps - 1,
 571                 SCL_H_NUM_TAPS, scl_data->taps.h_taps - 1,
 572                 SCL_V_NUM_TAPS_C, scl_data->taps.v_taps_c - 1,
 573                 SCL_H_NUM_TAPS_C, scl_data->taps.h_taps_c - 1);
 574 
 575         dpp1_dscl_set_scl_filter(dpp, scl_data, ycbcr);
 576 }
 577 
 578 
 579 static void dpp1_dscl_set_manual_ratio_init(
 580                 struct dcn10_dpp *dpp, const struct scaler_data *data)
 581 {
 582         uint32_t init_frac = 0;
 583         uint32_t init_int = 0;
 584 
 585         REG_SET(SCL_HORZ_FILTER_SCALE_RATIO, 0,
 586                         SCL_H_SCALE_RATIO, dc_fixpt_u3d19(data->ratios.horz) << 5);
 587 
 588         REG_SET(SCL_VERT_FILTER_SCALE_RATIO, 0,
 589                         SCL_V_SCALE_RATIO, dc_fixpt_u3d19(data->ratios.vert) << 5);
 590 
 591         REG_SET(SCL_HORZ_FILTER_SCALE_RATIO_C, 0,
 592                         SCL_H_SCALE_RATIO_C, dc_fixpt_u3d19(data->ratios.horz_c) << 5);
 593 
 594         REG_SET(SCL_VERT_FILTER_SCALE_RATIO_C, 0,
 595                         SCL_V_SCALE_RATIO_C, dc_fixpt_u3d19(data->ratios.vert_c) << 5);
 596 
 597         /*
 598          * 0.24 format for fraction, first five bits zeroed
 599          */
 600         init_frac = dc_fixpt_u0d19(data->inits.h) << 5;
 601         init_int = dc_fixpt_floor(data->inits.h);
 602         REG_SET_2(SCL_HORZ_FILTER_INIT, 0,
 603                 SCL_H_INIT_FRAC, init_frac,
 604                 SCL_H_INIT_INT, init_int);
 605 
 606         init_frac = dc_fixpt_u0d19(data->inits.h_c) << 5;
 607         init_int = dc_fixpt_floor(data->inits.h_c);
 608         REG_SET_2(SCL_HORZ_FILTER_INIT_C, 0,
 609                 SCL_H_INIT_FRAC_C, init_frac,
 610                 SCL_H_INIT_INT_C, init_int);
 611 
 612         init_frac = dc_fixpt_u0d19(data->inits.v) << 5;
 613         init_int = dc_fixpt_floor(data->inits.v);
 614         REG_SET_2(SCL_VERT_FILTER_INIT, 0,
 615                 SCL_V_INIT_FRAC, init_frac,
 616                 SCL_V_INIT_INT, init_int);
 617 
 618         if (REG(SCL_VERT_FILTER_INIT_BOT)) {
 619                 init_frac = dc_fixpt_u0d19(data->inits.v_bot) << 5;
 620                 init_int = dc_fixpt_floor(data->inits.v_bot);
 621                 REG_SET_2(SCL_VERT_FILTER_INIT_BOT, 0,
 622                         SCL_V_INIT_FRAC_BOT, init_frac,
 623                         SCL_V_INIT_INT_BOT, init_int);
 624         }
 625 
 626         init_frac = dc_fixpt_u0d19(data->inits.v_c) << 5;
 627         init_int = dc_fixpt_floor(data->inits.v_c);
 628         REG_SET_2(SCL_VERT_FILTER_INIT_C, 0,
 629                 SCL_V_INIT_FRAC_C, init_frac,
 630                 SCL_V_INIT_INT_C, init_int);
 631 
 632         if (REG(SCL_VERT_FILTER_INIT_BOT_C)) {
 633                 init_frac = dc_fixpt_u0d19(data->inits.v_c_bot) << 5;
 634                 init_int = dc_fixpt_floor(data->inits.v_c_bot);
 635                 REG_SET_2(SCL_VERT_FILTER_INIT_BOT_C, 0,
 636                         SCL_V_INIT_FRAC_BOT_C, init_frac,
 637                         SCL_V_INIT_INT_BOT_C, init_int);
 638         }
 639 }
 640 
 641 
 642 
 643 static void dpp1_dscl_set_recout(
 644                         struct dcn10_dpp *dpp, const struct rect *recout)
 645 {
 646         int visual_confirm_on = 0;
 647         if (dpp->base.ctx->dc->debug.visual_confirm != VISUAL_CONFIRM_DISABLE)
 648                 visual_confirm_on = 1;
 649 
 650         REG_SET_2(RECOUT_START, 0,
 651                 /* First pixel of RECOUT */
 652                          RECOUT_START_X, recout->x,
 653                 /* First line of RECOUT */
 654                          RECOUT_START_Y, recout->y);
 655 
 656         REG_SET_2(RECOUT_SIZE, 0,
 657                 /* Number of RECOUT horizontal pixels */
 658                          RECOUT_WIDTH, recout->width,
 659                 /* Number of RECOUT vertical lines */
 660                          RECOUT_HEIGHT, recout->height
 661                          - visual_confirm_on * 4 * (dpp->base.inst + 1));
 662 }
 663 
 664 /* Main function to program scaler and line buffer in manual scaling mode */
 665 void dpp1_dscl_set_scaler_manual_scale(
 666         struct dpp *dpp_base,
 667         const struct scaler_data *scl_data)
 668 {
 669         enum lb_memory_config lb_config;
 670         struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base);
 671         enum dscl_mode_sel dscl_mode = dpp1_dscl_get_dscl_mode(
 672                         dpp_base, scl_data, dpp_base->ctx->dc->debug.always_scale);
 673         bool ycbcr = scl_data->format >= PIXEL_FORMAT_VIDEO_BEGIN
 674                                 && scl_data->format <= PIXEL_FORMAT_VIDEO_END;
 675 
 676         if (memcmp(&dpp->scl_data, scl_data, sizeof(*scl_data)) == 0)
 677                 return;
 678 
 679         PERF_TRACE();
 680 
 681         dpp->scl_data = *scl_data;
 682 
 683         /* Autocal off */
 684         REG_SET_3(DSCL_AUTOCAL, 0,
 685                 AUTOCAL_MODE, AUTOCAL_MODE_OFF,
 686                 AUTOCAL_NUM_PIPE, 0,
 687                 AUTOCAL_PIPE_ID, 0);
 688 
 689         /* Recout */
 690         dpp1_dscl_set_recout(dpp, &scl_data->recout);
 691 
 692         /* MPC Size */
 693         REG_SET_2(MPC_SIZE, 0,
 694                 /* Number of horizontal pixels of MPC */
 695                          MPC_WIDTH, scl_data->h_active,
 696                 /* Number of vertical lines of MPC */
 697                          MPC_HEIGHT, scl_data->v_active);
 698 
 699         /* SCL mode */
 700         REG_UPDATE(SCL_MODE, DSCL_MODE, dscl_mode);
 701 
 702         if (dscl_mode == DSCL_MODE_DSCL_BYPASS)
 703                 return;
 704 
 705         /* LB */
 706         lb_config =  dpp1_dscl_find_lb_memory_config(dpp, scl_data);
 707         dpp1_dscl_set_lb(dpp, &scl_data->lb_params, lb_config);
 708 
 709         if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS)
 710                 return;
 711 
 712         /* Black offsets */
 713         if (REG(SCL_BLACK_OFFSET)) {
 714                 if (ycbcr)
 715                         REG_SET_2(SCL_BLACK_OFFSET, 0,
 716                                         SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y,
 717                                         SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_CBCR);
 718                 else
 719 
 720                         REG_SET_2(SCL_BLACK_OFFSET, 0,
 721                                         SCL_BLACK_OFFSET_RGB_Y, BLACK_OFFSET_RGB_Y,
 722                                         SCL_BLACK_OFFSET_CBCR, BLACK_OFFSET_RGB_Y);
 723         }
 724 
 725         /* Manually calculate scale ratio and init values */
 726         dpp1_dscl_set_manual_ratio_init(dpp, scl_data);
 727 
 728         /* HTaps/VTaps */
 729         REG_SET_4(SCL_TAP_CONTROL, 0,
 730                 SCL_V_NUM_TAPS, scl_data->taps.v_taps - 1,
 731                 SCL_H_NUM_TAPS, scl_data->taps.h_taps - 1,
 732                 SCL_V_NUM_TAPS_C, scl_data->taps.v_taps_c - 1,
 733                 SCL_H_NUM_TAPS_C, scl_data->taps.h_taps_c - 1);
 734 
 735         dpp1_dscl_set_scl_filter(dpp, scl_data, ycbcr);
 736         PERF_TRACE();
 737 }

/* [<][>][^][v][top][bottom][index][help] */