Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2012-17 Advanced Micro Devices, Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  * Authors: AMD
0023  *
0024  */
0025 
0026 
0027 #include "reg_helper.h"
0028 #include "resource.h"
0029 #include "dwb.h"
0030 #include "dcn20_dwb.h"
0031 
0032 
0033 #define REG(reg)\
0034     dwbc20->dwbc_regs->reg
0035 
0036 #define CTX \
0037     dwbc20->base.ctx
0038 
0039 #define DC_LOGGER \
0040     dwbc20->base.ctx->logger
0041 #undef FN
0042 #define FN(reg_name, field_name) \
0043     dwbc20->dwbc_shift->field_name, dwbc20->dwbc_mask->field_name
0044 
0045 enum dwb_outside_pix_strategy {
0046     DWB_OUTSIDE_PIX_STRATEGY_BLACK = 0,
0047     DWB_OUTSIDE_PIX_STRATEGY_EDGE  = 1
0048 };
0049 
0050 static bool dwb2_get_caps(struct dwbc *dwbc, struct dwb_caps *caps)
0051 {
0052     struct dcn20_dwbc *dwbc20 = TO_DCN20_DWBC(dwbc);
0053     if (caps) {
0054         caps->adapter_id = 0;   /* we only support 1 adapter currently */
0055         caps->hw_version = DCN_VERSION_2_0;
0056         caps->num_pipes = 1;
0057         memset(&caps->reserved, 0, sizeof(caps->reserved));
0058         memset(&caps->reserved2, 0, sizeof(caps->reserved2));
0059         caps->sw_version = dwb_ver_1_0;
0060         caps->caps.support_dwb = true;
0061         caps->caps.support_ogam = false;
0062         caps->caps.support_wbscl = false;
0063         caps->caps.support_ocsc = false;
0064         DC_LOG_DWB("%s SUPPORTED! inst = %d", __func__, dwbc20->base.inst);
0065         return true;
0066     } else {
0067         DC_LOG_DWB("%s NOT SUPPORTED! inst = %d", __func__, dwbc20->base.inst);
0068         return false;
0069     }
0070 }
0071 
0072 void dwb2_config_dwb_cnv(struct dwbc *dwbc, struct dc_dwb_params *params)
0073 {
0074     struct dcn20_dwbc *dwbc20 = TO_DCN20_DWBC(dwbc);
0075     DC_LOG_DWB("%s inst = %d", __func__, dwbc20->base.inst);
0076 
0077     /* Set DWB source size */
0078     REG_UPDATE_2(CNV_SOURCE_SIZE, CNV_SOURCE_WIDTH, params->cnv_params.src_width,
0079             CNV_SOURCE_HEIGHT, params->cnv_params.src_height);
0080 
0081     /* source size is not equal the source size, then enable cropping. */
0082     if (params->cnv_params.crop_en) {
0083         REG_UPDATE(CNV_MODE, CNV_WINDOW_CROP_EN, 1);
0084         REG_UPDATE(CNV_WINDOW_START, CNV_WINDOW_START_X, params->cnv_params.crop_x);
0085         REG_UPDATE(CNV_WINDOW_START, CNV_WINDOW_START_Y, params->cnv_params.crop_y);
0086         REG_UPDATE(CNV_WINDOW_SIZE,  CNV_WINDOW_WIDTH,   params->cnv_params.crop_width);
0087         REG_UPDATE(CNV_WINDOW_SIZE,  CNV_WINDOW_HEIGHT,  params->cnv_params.crop_height);
0088     } else {
0089         REG_UPDATE(CNV_MODE, CNV_WINDOW_CROP_EN, 0);
0090     }
0091 
0092     /* Set CAPTURE_RATE */
0093     REG_UPDATE(CNV_MODE, CNV_FRAME_CAPTURE_RATE, params->capture_rate);
0094 
0095     /* Set CNV output pixel depth */
0096     REG_UPDATE(CNV_MODE, CNV_OUT_BPC, params->cnv_params.cnv_out_bpc);
0097 }
0098 
0099 static bool dwb2_enable(struct dwbc *dwbc, struct dc_dwb_params *params)
0100 {
0101     struct dcn20_dwbc *dwbc20 = TO_DCN20_DWBC(dwbc);
0102 
0103     /* Only chroma scaling (sub-sampling) is supported in DCN2 */
0104     if ((params->cnv_params.src_width  != params->dest_width) ||
0105         (params->cnv_params.src_height != params->dest_height)) {
0106 
0107         DC_LOG_DWB("%s inst = %d, FAILED!LUMA SCALING NOT SUPPORTED", __func__, dwbc20->base.inst);
0108         return false;
0109     }
0110     DC_LOG_DWB("%s inst = %d, ENABLED", __func__, dwbc20->base.inst);
0111 
0112     /* disable power gating */
0113     //REG_UPDATE_5(WB_EC_CONFIG, DISPCLK_R_WB_GATE_DIS, 1,
0114     //           DISPCLK_G_WB_GATE_DIS, 1, DISPCLK_G_WBSCL_GATE_DIS, 1,
0115     //           WB_LB_LS_DIS, 1, WB_LUT_LS_DIS, 1);
0116 
0117     /* Set WB_ENABLE (not double buffered; capture not enabled) */
0118     REG_UPDATE(WB_ENABLE, WB_ENABLE, 1);
0119 
0120     /* Set CNV parameters */
0121     dwb2_config_dwb_cnv(dwbc, params);
0122 
0123     /* Set scaling parameters */
0124     dwb2_set_scaler(dwbc, params);
0125 
0126     /* Enable DWB capture enable (double buffered) */
0127     REG_UPDATE(CNV_MODE, CNV_FRAME_CAPTURE_EN, DWB_FRAME_CAPTURE_ENABLE);
0128 
0129     // disable warmup
0130     REG_UPDATE(WB_WARM_UP_MODE_CTL1, GMC_WARM_UP_ENABLE, 0);
0131 
0132     return true;
0133 }
0134 
0135 bool dwb2_disable(struct dwbc *dwbc)
0136 {
0137     struct dcn20_dwbc *dwbc20 = TO_DCN20_DWBC(dwbc);
0138     DC_LOG_DWB("%s inst = %d, Disabled", __func__, dwbc20->base.inst);
0139 
0140     /* disable CNV */
0141     REG_UPDATE(CNV_MODE, CNV_FRAME_CAPTURE_EN, DWB_FRAME_CAPTURE_DISABLE);
0142 
0143     /* disable WB */
0144     REG_UPDATE(WB_ENABLE, WB_ENABLE, 0);
0145 
0146     /* soft reset */
0147     REG_UPDATE(WB_SOFT_RESET, WB_SOFT_RESET, 1);
0148     REG_UPDATE(WB_SOFT_RESET, WB_SOFT_RESET, 0);
0149 
0150     /* enable power gating */
0151     //REG_UPDATE_5(WB_EC_CONFIG, DISPCLK_R_WB_GATE_DIS, 0,
0152     //           DISPCLK_G_WB_GATE_DIS, 0, DISPCLK_G_WBSCL_GATE_DIS, 0,
0153     //           WB_LB_LS_DIS, 0, WB_LUT_LS_DIS, 0);
0154 
0155     return true;
0156 }
0157 
0158 static bool dwb2_update(struct dwbc *dwbc, struct dc_dwb_params *params)
0159 {
0160     struct dcn20_dwbc *dwbc20 = TO_DCN20_DWBC(dwbc);
0161     unsigned int pre_locked;
0162 
0163     /* Only chroma scaling (sub-sampling) is supported in DCN2 */
0164     if ((params->cnv_params.src_width != params->dest_width) ||
0165             (params->cnv_params.src_height != params->dest_height)) {
0166         DC_LOG_DWB("%s inst = %d, FAILED!LUMA SCALING NOT SUPPORTED", __func__, dwbc20->base.inst);
0167         return false;
0168     }
0169     DC_LOG_DWB("%s inst = %d, scaling", __func__, dwbc20->base.inst);
0170 
0171     /*
0172      * Check if the caller has already locked CNV registers.
0173      * If so: assume the caller will unlock, so don't touch the lock.
0174      * If not: lock them for this update, then unlock after the
0175      * update is complete.
0176      */
0177     REG_GET(CNV_UPDATE, CNV_UPDATE_LOCK, &pre_locked);
0178 
0179     if (pre_locked == 0) {
0180         /* Lock DWB registers */
0181         REG_UPDATE(CNV_UPDATE, CNV_UPDATE_LOCK, 1);
0182     }
0183 
0184     /* Set CNV parameters */
0185     dwb2_config_dwb_cnv(dwbc, params);
0186 
0187     /* Set scaling parameters */
0188     dwb2_set_scaler(dwbc, params);
0189 
0190     if (pre_locked == 0) {
0191         /* Unlock DWB registers */
0192         REG_UPDATE(CNV_UPDATE, CNV_UPDATE_LOCK, 0);
0193     }
0194 
0195     return true;
0196 }
0197 
0198 bool dwb2_is_enabled(struct dwbc *dwbc)
0199 {
0200     struct dcn20_dwbc *dwbc20 = TO_DCN20_DWBC(dwbc);
0201     unsigned int wb_enabled = 0;
0202     unsigned int cnv_frame_capture_en = 0;
0203 
0204     REG_GET(WB_ENABLE, WB_ENABLE, &wb_enabled);
0205     REG_GET(CNV_MODE, CNV_FRAME_CAPTURE_EN, &cnv_frame_capture_en);
0206 
0207     return ((wb_enabled != 0) && (cnv_frame_capture_en != 0));
0208 }
0209 
0210 void dwb2_set_stereo(struct dwbc *dwbc,
0211         struct dwb_stereo_params *stereo_params)
0212 {
0213     struct dcn20_dwbc *dwbc20 = TO_DCN20_DWBC(dwbc);
0214     DC_LOG_DWB("%s inst = %d, enabled =%d", __func__,\
0215         dwbc20->base.inst, stereo_params->stereo_enabled);
0216 
0217     if (stereo_params->stereo_enabled) {
0218         REG_UPDATE(CNV_MODE, CNV_STEREO_TYPE,     stereo_params->stereo_type);
0219         REG_UPDATE(CNV_MODE, CNV_EYE_SELECTION,   stereo_params->stereo_eye_select);
0220         REG_UPDATE(CNV_MODE, CNV_STEREO_POLARITY, stereo_params->stereo_polarity);
0221     } else {
0222         REG_UPDATE(CNV_MODE, CNV_EYE_SELECTION, 0);
0223     }
0224 }
0225 
0226 void dwb2_set_new_content(struct dwbc *dwbc,
0227                         bool is_new_content)
0228 {
0229     struct dcn20_dwbc *dwbc20 = TO_DCN20_DWBC(dwbc);
0230     DC_LOG_DWB("%s inst = %d", __func__, dwbc20->base.inst);
0231 
0232     REG_UPDATE(CNV_MODE, CNV_NEW_CONTENT, is_new_content);
0233 }
0234 
0235 static void dwb2_set_warmup(struct dwbc *dwbc,
0236         struct dwb_warmup_params *warmup_params)
0237 {
0238     struct dcn20_dwbc *dwbc20 = TO_DCN20_DWBC(dwbc);
0239     DC_LOG_DWB("%s inst = %d", __func__, dwbc20->base.inst);
0240 
0241     REG_UPDATE(WB_WARM_UP_MODE_CTL1, GMC_WARM_UP_ENABLE, warmup_params->warmup_en);
0242     REG_UPDATE(WB_WARM_UP_MODE_CTL1, WIDTH_WARMUP, warmup_params->warmup_width);
0243     REG_UPDATE(WB_WARM_UP_MODE_CTL1, HEIGHT_WARMUP, warmup_params->warmup_height);
0244 
0245     REG_UPDATE(WB_WARM_UP_MODE_CTL2, DATA_VALUE_WARMUP, warmup_params->warmup_data);
0246     REG_UPDATE(WB_WARM_UP_MODE_CTL2, MODE_WARMUP, warmup_params->warmup_mode);
0247     REG_UPDATE(WB_WARM_UP_MODE_CTL2, DATA_DEPTH_WARMUP, warmup_params->warmup_depth);
0248 }
0249 
0250 void dwb2_set_scaler(struct dwbc *dwbc, struct dc_dwb_params *params)
0251 {
0252     struct dcn20_dwbc *dwbc20 = TO_DCN20_DWBC(dwbc);
0253     DC_LOG_DWB("%s inst = %d", __func__, dwbc20->base.inst);
0254 
0255     /* Program scaling mode */
0256     REG_UPDATE_2(WBSCL_MODE, WBSCL_MODE, params->out_format,
0257             WBSCL_OUT_BIT_DEPTH, params->output_depth);
0258 
0259     if (params->out_format != dwb_scaler_mode_bypass444) {
0260         /* Program output size */
0261         REG_UPDATE(WBSCL_DEST_SIZE, WBSCL_DEST_WIDTH,   params->dest_width);
0262         REG_UPDATE(WBSCL_DEST_SIZE, WBSCL_DEST_HEIGHT,  params->dest_height);
0263 
0264         /* Program round offsets */
0265         REG_UPDATE(WBSCL_ROUND_OFFSET, WBSCL_ROUND_OFFSET_Y_RGB, 0x40);
0266         REG_UPDATE(WBSCL_ROUND_OFFSET, WBSCL_ROUND_OFFSET_CBCR,  0x200);
0267 
0268         /* Program clamp values */
0269         REG_UPDATE(WBSCL_CLAMP_Y_RGB,   WBSCL_CLAMP_UPPER_Y_RGB,    0x3fe);
0270         REG_UPDATE(WBSCL_CLAMP_Y_RGB,   WBSCL_CLAMP_LOWER_Y_RGB,    0x1);
0271         REG_UPDATE(WBSCL_CLAMP_CBCR,    WBSCL_CLAMP_UPPER_CBCR,     0x3fe);
0272         REG_UPDATE(WBSCL_CLAMP_CBCR,    WBSCL_CLAMP_LOWER_CBCR,     0x1);
0273 
0274         /* Program outside pixel strategy to use edge pixels */
0275         REG_UPDATE(WBSCL_OUTSIDE_PIX_STRATEGY, WBSCL_OUTSIDE_PIX_STRATEGY, DWB_OUTSIDE_PIX_STRATEGY_EDGE);
0276 
0277         if (params->cnv_params.crop_en) {
0278             /* horizontal scale */
0279             dwb_program_horz_scalar(dwbc20, params->cnv_params.crop_width,
0280                             params->dest_width,
0281                             params->scaler_taps);
0282 
0283             /* vertical scale */
0284             dwb_program_vert_scalar(dwbc20, params->cnv_params.crop_height,
0285                             params->dest_height,
0286                             params->scaler_taps,
0287                             params->subsample_position);
0288         } else {
0289             /* horizontal scale */
0290             dwb_program_horz_scalar(dwbc20, params->cnv_params.src_width,
0291                             params->dest_width,
0292                             params->scaler_taps);
0293 
0294             /* vertical scale */
0295             dwb_program_vert_scalar(dwbc20, params->cnv_params.src_height,
0296                             params->dest_height,
0297                             params->scaler_taps,
0298                             params->subsample_position);
0299         }
0300     }
0301 
0302 }
0303 
0304 const struct dwbc_funcs dcn20_dwbc_funcs = {
0305     .get_caps       = dwb2_get_caps,
0306     .enable         = dwb2_enable,
0307     .disable        = dwb2_disable,
0308     .update         = dwb2_update,
0309     .is_enabled     = dwb2_is_enabled,
0310     .set_stereo     = dwb2_set_stereo,
0311     .set_new_content    = dwb2_set_new_content,
0312     .set_warmup     = dwb2_set_warmup,
0313     .dwb_set_scaler     = dwb2_set_scaler,
0314 };
0315 
0316 void dcn20_dwbc_construct(struct dcn20_dwbc *dwbc20,
0317         struct dc_context *ctx,
0318         const struct dcn20_dwbc_registers *dwbc_regs,
0319         const struct dcn20_dwbc_shift *dwbc_shift,
0320         const struct dcn20_dwbc_mask *dwbc_mask,
0321         int inst)
0322 {
0323     dwbc20->base.ctx = ctx;
0324 
0325     dwbc20->base.inst = inst;
0326     dwbc20->base.funcs = &dcn20_dwbc_funcs;
0327 
0328     dwbc20->dwbc_regs = dwbc_regs;
0329     dwbc20->dwbc_shift = dwbc_shift;
0330     dwbc20->dwbc_mask = dwbc_mask;
0331 }
0332