root/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dwb.c

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

DEFINITIONS

This source file includes following definitions.
  1. dwb2_get_caps
  2. dwb2_config_dwb_cnv
  3. dwb2_enable
  4. dwb2_disable
  5. dwb2_update
  6. dwb2_is_enabled
  7. dwb2_set_stereo
  8. dwb2_set_new_content
  9. dwb2_set_warmup
  10. dwb2_set_scaler
  11. dcn20_dwbc_construct

   1 /*
   2  * Copyright 2012-17 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 
  27 #include "reg_helper.h"
  28 #include "resource.h"
  29 #include "dwb.h"
  30 #include "dcn20_dwb.h"
  31 
  32 
  33 #define REG(reg)\
  34         dwbc20->dwbc_regs->reg
  35 
  36 #define CTX \
  37         dwbc20->base.ctx
  38 
  39 #define DC_LOGGER \
  40         dwbc20->base.ctx->logger
  41 #undef FN
  42 #define FN(reg_name, field_name) \
  43         dwbc20->dwbc_shift->field_name, dwbc20->dwbc_mask->field_name
  44 
  45 enum dwb_outside_pix_strategy {
  46         DWB_OUTSIDE_PIX_STRATEGY_BLACK = 0,
  47         DWB_OUTSIDE_PIX_STRATEGY_EDGE  = 1
  48 };
  49 
  50 static bool dwb2_get_caps(struct dwbc *dwbc, struct dwb_caps *caps)
  51 {
  52         struct dcn20_dwbc *dwbc20 = TO_DCN20_DWBC(dwbc);
  53         if (caps) {
  54                 caps->adapter_id = 0;   /* we only support 1 adapter currently */
  55                 caps->hw_version = DCN_VERSION_2_0;
  56                 caps->num_pipes = 1;
  57                 memset(&caps->reserved, 0, sizeof(caps->reserved));
  58                 memset(&caps->reserved2, 0, sizeof(caps->reserved2));
  59                 caps->sw_version = dwb_ver_1_0;
  60                 caps->caps.support_dwb = true;
  61                 caps->caps.support_ogam = false;
  62                 caps->caps.support_wbscl = false;
  63                 caps->caps.support_ocsc = false;
  64                 DC_LOG_DWB("%s SUPPORTED! inst = %d", __func__, dwbc20->base.inst);
  65                 return true;
  66         } else {
  67                 DC_LOG_DWB("%s NOT SUPPORTED! inst = %d", __func__, dwbc20->base.inst);
  68                 return false;
  69         }
  70 }
  71 
  72 void dwb2_config_dwb_cnv(struct dwbc *dwbc, struct dc_dwb_params *params)
  73 {
  74         struct dcn20_dwbc *dwbc20 = TO_DCN20_DWBC(dwbc);
  75         DC_LOG_DWB("%s inst = %d", __func__, dwbc20->base.inst);
  76 
  77         /* Set DWB source size */
  78         REG_UPDATE_2(CNV_SOURCE_SIZE, CNV_SOURCE_WIDTH, params->cnv_params.src_width,
  79                         CNV_SOURCE_HEIGHT, params->cnv_params.src_height);
  80 
  81         /* source size is not equal the source size, then enable cropping. */
  82         if (params->cnv_params.crop_en) {
  83                 REG_UPDATE(CNV_MODE, CNV_WINDOW_CROP_EN, 1);
  84                 REG_UPDATE(CNV_WINDOW_START, CNV_WINDOW_START_X, params->cnv_params.crop_x);
  85                 REG_UPDATE(CNV_WINDOW_START, CNV_WINDOW_START_Y, params->cnv_params.crop_y);
  86                 REG_UPDATE(CNV_WINDOW_SIZE,  CNV_WINDOW_WIDTH,   params->cnv_params.crop_width);
  87                 REG_UPDATE(CNV_WINDOW_SIZE,  CNV_WINDOW_HEIGHT,  params->cnv_params.crop_height);
  88         } else {
  89                 REG_UPDATE(CNV_MODE, CNV_WINDOW_CROP_EN, 0);
  90         }
  91 
  92         /* Set CAPTURE_RATE */
  93         REG_UPDATE(CNV_MODE, CNV_FRAME_CAPTURE_RATE, params->capture_rate);
  94 
  95         /* Set CNV output pixel depth */
  96         REG_UPDATE(CNV_MODE, CNV_OUT_BPC, params->cnv_params.cnv_out_bpc);
  97 }
  98 
  99 static bool dwb2_enable(struct dwbc *dwbc, struct dc_dwb_params *params)
 100 {
 101         struct dcn20_dwbc *dwbc20 = TO_DCN20_DWBC(dwbc);
 102 
 103         /* Only chroma scaling (sub-sampling) is supported in DCN2 */
 104 if ((params->cnv_params.src_width  != params->dest_width) ||
 105                 (params->cnv_params.src_height != params->dest_height)) {
 106 
 107                 DC_LOG_DWB("%s inst = %d, FAILED!LUMA SCALING NOT SUPPORTED", __func__, dwbc20->base.inst);
 108                 return false;
 109         }
 110         DC_LOG_DWB("%s inst = %d, ENABLED", __func__, dwbc20->base.inst);
 111 
 112         /* disable power gating */
 113         //REG_UPDATE_5(WB_EC_CONFIG, DISPCLK_R_WB_GATE_DIS, 1,
 114         //                       DISPCLK_G_WB_GATE_DIS, 1, DISPCLK_G_WBSCL_GATE_DIS, 1,
 115         //                       WB_LB_LS_DIS, 1, WB_LUT_LS_DIS, 1);
 116 
 117         /* Set WB_ENABLE (not double buffered; capture not enabled) */
 118         REG_UPDATE(WB_ENABLE, WB_ENABLE, 1);
 119 
 120         /* Set CNV parameters */
 121         dwb2_config_dwb_cnv(dwbc, params);
 122 
 123         /* Set scaling parameters */
 124         dwb2_set_scaler(dwbc, params);
 125 
 126         /* Enable DWB capture enable (double buffered) */
 127         REG_UPDATE(CNV_MODE, CNV_FRAME_CAPTURE_EN, DWB_FRAME_CAPTURE_ENABLE);
 128 
 129         // disable warmup
 130         REG_UPDATE(WB_WARM_UP_MODE_CTL1, GMC_WARM_UP_ENABLE, 0);
 131 
 132         return true;
 133 }
 134 
 135 bool dwb2_disable(struct dwbc *dwbc)
 136 {
 137         struct dcn20_dwbc *dwbc20 = TO_DCN20_DWBC(dwbc);
 138         DC_LOG_DWB("%s inst = %d, Disabled", __func__, dwbc20->base.inst);
 139 
 140         /* disable CNV */
 141         REG_UPDATE(CNV_MODE, CNV_FRAME_CAPTURE_EN, DWB_FRAME_CAPTURE_DISABLE);
 142 
 143         /* disable WB */
 144         REG_UPDATE(WB_ENABLE, WB_ENABLE, 0);
 145 
 146         /* soft reset */
 147         REG_UPDATE(WB_SOFT_RESET, WB_SOFT_RESET, 1);
 148         REG_UPDATE(WB_SOFT_RESET, WB_SOFT_RESET, 0);
 149 
 150         /* enable power gating */
 151         //REG_UPDATE_5(WB_EC_CONFIG, DISPCLK_R_WB_GATE_DIS, 0,
 152         //                       DISPCLK_G_WB_GATE_DIS, 0, DISPCLK_G_WBSCL_GATE_DIS, 0,
 153         //                       WB_LB_LS_DIS, 0, WB_LUT_LS_DIS, 0);
 154 
 155         return true;
 156 }
 157 
 158 static bool dwb2_update(struct dwbc *dwbc, struct dc_dwb_params *params)
 159 {
 160         struct dcn20_dwbc *dwbc20 = TO_DCN20_DWBC(dwbc);
 161         unsigned int pre_locked;
 162 
 163         /* Only chroma scaling (sub-sampling) is supported in DCN2 */
 164         if ((params->cnv_params.src_width != params->dest_width) ||
 165                         (params->cnv_params.src_height != params->dest_height)) {
 166                 DC_LOG_DWB("%s inst = %d, FAILED!LUMA SCALING NOT SUPPORTED", __func__, dwbc20->base.inst);
 167                 return false;
 168         }
 169         DC_LOG_DWB("%s inst = %d, scaling", __func__, dwbc20->base.inst);
 170 
 171         /*
 172          * Check if the caller has already locked CNV registers.
 173          * If so: assume the caller will unlock, so don't touch the lock.
 174          * If not: lock them for this update, then unlock after the
 175          * update is complete.
 176          */
 177         REG_GET(CNV_UPDATE, CNV_UPDATE_LOCK, &pre_locked);
 178 
 179         if (pre_locked == 0) {
 180                 /* Lock DWB registers */
 181                 REG_UPDATE(CNV_UPDATE, CNV_UPDATE_LOCK, 1);
 182         }
 183 
 184         /* Set CNV parameters */
 185         dwb2_config_dwb_cnv(dwbc, params);
 186 
 187         /* Set scaling parameters */
 188         dwb2_set_scaler(dwbc, params);
 189 
 190         if (pre_locked == 0) {
 191                 /* Unlock DWB registers */
 192                 REG_UPDATE(CNV_UPDATE, CNV_UPDATE_LOCK, 0);
 193         }
 194 
 195         return true;
 196 }
 197 
 198 bool dwb2_is_enabled(struct dwbc *dwbc)
 199 {
 200         struct dcn20_dwbc *dwbc20 = TO_DCN20_DWBC(dwbc);
 201         unsigned int wb_enabled = 0;
 202         unsigned int cnv_frame_capture_en = 0;
 203 
 204         REG_GET(WB_ENABLE, WB_ENABLE, &wb_enabled);
 205         REG_GET(CNV_MODE, CNV_FRAME_CAPTURE_EN, &cnv_frame_capture_en);
 206 
 207         return ((wb_enabled != 0) && (cnv_frame_capture_en != 0));
 208 }
 209 
 210 void dwb2_set_stereo(struct dwbc *dwbc,
 211                 struct dwb_stereo_params *stereo_params)
 212 {
 213         struct dcn20_dwbc *dwbc20 = TO_DCN20_DWBC(dwbc);
 214         DC_LOG_DWB("%s inst = %d, enabled =%d", __func__,\
 215                 dwbc20->base.inst, stereo_params->stereo_enabled);
 216 
 217         if (stereo_params->stereo_enabled) {
 218                 REG_UPDATE(CNV_MODE, CNV_STEREO_TYPE,     stereo_params->stereo_type);
 219                 REG_UPDATE(CNV_MODE, CNV_EYE_SELECTION,   stereo_params->stereo_eye_select);
 220                 REG_UPDATE(CNV_MODE, CNV_STEREO_POLARITY, stereo_params->stereo_polarity);
 221         } else {
 222                 REG_UPDATE(CNV_MODE, CNV_EYE_SELECTION, 0);
 223         }
 224 }
 225 
 226 void dwb2_set_new_content(struct dwbc *dwbc,
 227                                                 bool is_new_content)
 228 {
 229         struct dcn20_dwbc *dwbc20 = TO_DCN20_DWBC(dwbc);
 230         DC_LOG_DWB("%s inst = %d", __func__, dwbc20->base.inst);
 231 
 232         REG_UPDATE(CNV_MODE, CNV_NEW_CONTENT, is_new_content);
 233 }
 234 
 235 static void dwb2_set_warmup(struct dwbc *dwbc,
 236                 struct dwb_warmup_params *warmup_params)
 237 {
 238         struct dcn20_dwbc *dwbc20 = TO_DCN20_DWBC(dwbc);
 239         DC_LOG_DWB("%s inst = %d", __func__, dwbc20->base.inst);
 240 
 241         REG_UPDATE(WB_WARM_UP_MODE_CTL1, GMC_WARM_UP_ENABLE, warmup_params->warmup_en);
 242         REG_UPDATE(WB_WARM_UP_MODE_CTL1, WIDTH_WARMUP, warmup_params->warmup_width);
 243         REG_UPDATE(WB_WARM_UP_MODE_CTL1, HEIGHT_WARMUP, warmup_params->warmup_height);
 244 
 245         REG_UPDATE(WB_WARM_UP_MODE_CTL2, DATA_VALUE_WARMUP, warmup_params->warmup_data);
 246         REG_UPDATE(WB_WARM_UP_MODE_CTL2, MODE_WARMUP, warmup_params->warmup_mode);
 247         REG_UPDATE(WB_WARM_UP_MODE_CTL2, DATA_DEPTH_WARMUP, warmup_params->warmup_depth);
 248 }
 249 
 250 void dwb2_set_scaler(struct dwbc *dwbc, struct dc_dwb_params *params)
 251 {
 252         struct dcn20_dwbc *dwbc20 = TO_DCN20_DWBC(dwbc);
 253         DC_LOG_DWB("%s inst = %d", __func__, dwbc20->base.inst);
 254 
 255         /* Program scaling mode */
 256         REG_UPDATE_2(WBSCL_MODE, WBSCL_MODE, params->out_format,
 257                         WBSCL_OUT_BIT_DEPTH, params->output_depth);
 258 
 259         if (params->out_format != dwb_scaler_mode_bypass444) {
 260                 /* Program output size */
 261                 REG_UPDATE(WBSCL_DEST_SIZE, WBSCL_DEST_WIDTH,   params->dest_width);
 262                 REG_UPDATE(WBSCL_DEST_SIZE, WBSCL_DEST_HEIGHT,  params->dest_height);
 263 
 264                 /* Program round offsets */
 265                 REG_UPDATE(WBSCL_ROUND_OFFSET, WBSCL_ROUND_OFFSET_Y_RGB, 0x40);
 266                 REG_UPDATE(WBSCL_ROUND_OFFSET, WBSCL_ROUND_OFFSET_CBCR,  0x200);
 267 
 268                 /* Program clamp values */
 269                 REG_UPDATE(WBSCL_CLAMP_Y_RGB,   WBSCL_CLAMP_UPPER_Y_RGB,        0x3fe);
 270                 REG_UPDATE(WBSCL_CLAMP_Y_RGB,   WBSCL_CLAMP_LOWER_Y_RGB,        0x1);
 271                 REG_UPDATE(WBSCL_CLAMP_CBCR,    WBSCL_CLAMP_UPPER_CBCR,         0x3fe);
 272                 REG_UPDATE(WBSCL_CLAMP_CBCR,    WBSCL_CLAMP_LOWER_CBCR,         0x1);
 273 
 274                 /* Program outside pixel strategy to use edge pixels */
 275                 REG_UPDATE(WBSCL_OUTSIDE_PIX_STRATEGY, WBSCL_OUTSIDE_PIX_STRATEGY, DWB_OUTSIDE_PIX_STRATEGY_EDGE);
 276 
 277                 if (params->cnv_params.crop_en) {
 278                         /* horizontal scale */
 279                         dwb_program_horz_scalar(dwbc20, params->cnv_params.crop_width,
 280                                                         params->dest_width,
 281                                                         params->scaler_taps);
 282 
 283                         /* vertical scale */
 284                         dwb_program_vert_scalar(dwbc20, params->cnv_params.crop_height,
 285                                                         params->dest_height,
 286                                                         params->scaler_taps,
 287                                                         params->subsample_position);
 288                 } else {
 289                         /* horizontal scale */
 290                         dwb_program_horz_scalar(dwbc20, params->cnv_params.src_width,
 291                                                         params->dest_width,
 292                                                         params->scaler_taps);
 293 
 294                         /* vertical scale */
 295                         dwb_program_vert_scalar(dwbc20, params->cnv_params.src_height,
 296                                                         params->dest_height,
 297                                                         params->scaler_taps,
 298                                                         params->subsample_position);
 299                 }
 300         }
 301 
 302 }
 303 
 304 const struct dwbc_funcs dcn20_dwbc_funcs = {
 305         .get_caps               = dwb2_get_caps,
 306         .enable                 = dwb2_enable,
 307         .disable                = dwb2_disable,
 308         .update                 = dwb2_update,
 309         .is_enabled             = dwb2_is_enabled,
 310         .set_stereo             = dwb2_set_stereo,
 311         .set_new_content        = dwb2_set_new_content,
 312         .set_warmup             = dwb2_set_warmup,
 313         .dwb_set_scaler         = dwb2_set_scaler,
 314 };
 315 
 316 void dcn20_dwbc_construct(struct dcn20_dwbc *dwbc20,
 317                 struct dc_context *ctx,
 318                 const struct dcn20_dwbc_registers *dwbc_regs,
 319                 const struct dcn20_dwbc_shift *dwbc_shift,
 320                 const struct dcn20_dwbc_mask *dwbc_mask,
 321                 int inst)
 322 {
 323         dwbc20->base.ctx = ctx;
 324 
 325         dwbc20->base.inst = inst;
 326         dwbc20->base.funcs = &dcn20_dwbc_funcs;
 327 
 328         dwbc20->dwbc_regs = dwbc_regs;
 329         dwbc20->dwbc_shift = dwbc_shift;
 330         dwbc20->dwbc_mask = dwbc_mask;
 331 }
 332 

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