LCOV - code coverage report
Current view: top level - drivers/gpu/drm/amd/display/dc/dcn10 - dcn10_dpp_dscl.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 257 0.0 %
Date: 2022-12-09 01:23:36 Functions: 0 14 0.0 %

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

Generated by: LCOV version 1.14