Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2020 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 "dcn30_dwb.h"
0031 
0032 
0033 #define REG(reg)\
0034     dwbc30->dwbc_regs->reg
0035 
0036 #define CTX \
0037     dwbc30->base.ctx
0038 
0039 #undef FN
0040 #define FN(reg_name, field_name) \
0041     dwbc30->dwbc_shift->field_name, dwbc30->dwbc_mask->field_name
0042 
0043 #define DC_LOGGER \
0044     dwbc30->base.ctx->logger
0045 
0046 static bool dwb3_get_caps(struct dwbc *dwbc, struct dwb_caps *caps)
0047 {
0048     if (caps) {
0049         caps->adapter_id = 0;   /* we only support 1 adapter currently */
0050         caps->hw_version = DCN_VERSION_3_0;
0051         caps->num_pipes = 2;
0052         memset(&caps->reserved, 0, sizeof(caps->reserved));
0053         memset(&caps->reserved2, 0, sizeof(caps->reserved2));
0054         caps->sw_version = dwb_ver_2_0;
0055         caps->caps.support_dwb = true;
0056         caps->caps.support_ogam = true;
0057         caps->caps.support_wbscl = true;
0058         caps->caps.support_ocsc = false;
0059         caps->caps.support_stereo = true;
0060         return true;
0061     } else {
0062         return false;
0063     }
0064 }
0065 
0066 void dwb3_config_fc(struct dwbc *dwbc, struct dc_dwb_params *params)
0067 {
0068     struct dcn30_dwbc *dwbc30 = TO_DCN30_DWBC(dwbc);
0069 
0070     /* Set DWB source size */
0071     REG_UPDATE_2(FC_SOURCE_SIZE, FC_SOURCE_WIDTH, params->cnv_params.src_width,
0072             FC_SOURCE_HEIGHT, params->cnv_params.src_height);
0073 
0074     /* source size is not equal the source size, then enable cropping. */
0075     if (params->cnv_params.crop_en) {
0076         REG_UPDATE(FC_MODE_CTRL,    FC_WINDOW_CROP_EN, 1);
0077         REG_UPDATE(FC_WINDOW_START, FC_WINDOW_START_X, params->cnv_params.crop_x);
0078         REG_UPDATE(FC_WINDOW_START, FC_WINDOW_START_Y, params->cnv_params.crop_y);
0079         REG_UPDATE(FC_WINDOW_SIZE,  FC_WINDOW_WIDTH,   params->cnv_params.crop_width);
0080         REG_UPDATE(FC_WINDOW_SIZE,  FC_WINDOW_HEIGHT,  params->cnv_params.crop_height);
0081     } else {
0082         REG_UPDATE(FC_MODE_CTRL,    FC_WINDOW_CROP_EN, 0);
0083     }
0084 
0085     /* Set CAPTURE_RATE */
0086     REG_UPDATE(FC_MODE_CTRL, FC_FRAME_CAPTURE_RATE, params->capture_rate);
0087 
0088     dwb3_set_stereo(dwbc, &params->stereo_params);
0089 }
0090 
0091 bool dwb3_enable(struct dwbc *dwbc, struct dc_dwb_params *params)
0092 {
0093     struct dcn30_dwbc *dwbc30 = TO_DCN30_DWBC(dwbc);
0094     DC_LOG_DWB("%s dwb3_enabled at inst = %d", __func__, dwbc->inst);
0095 
0096     /* Set WB_ENABLE (not double buffered; capture not enabled) */
0097     REG_UPDATE(DWB_ENABLE_CLK_CTRL, DWB_ENABLE, 1);
0098 
0099     /* Set FC parameters */
0100     dwb3_config_fc(dwbc, params);
0101 
0102     /* Program color processing unit */
0103     dwb3_program_hdr_mult(dwbc, params);
0104     dwb3_set_gamut_remap(dwbc, params);
0105     dwb3_ogam_set_input_transfer_func(dwbc, params->out_transfer_func);
0106 
0107     /* Program output denorm */
0108     dwb3_set_denorm(dwbc, params);
0109 
0110     /* Enable DWB capture enable (double buffered) */
0111     REG_UPDATE(FC_MODE_CTRL, FC_FRAME_CAPTURE_EN, DWB_FRAME_CAPTURE_ENABLE);
0112 
0113     /* First pixel count */
0114     REG_UPDATE(FC_FLOW_CTRL, FC_FIRST_PIXEL_DELAY_COUNT, 96);
0115 
0116     return true;
0117 }
0118 
0119 bool dwb3_disable(struct dwbc *dwbc)
0120 {
0121     struct dcn30_dwbc *dwbc30 = TO_DCN30_DWBC(dwbc);
0122 
0123     /* disable FC */
0124     REG_UPDATE(FC_MODE_CTRL, FC_FRAME_CAPTURE_EN, DWB_FRAME_CAPTURE_DISABLE);
0125 
0126     /* disable WB */
0127     REG_UPDATE(DWB_ENABLE_CLK_CTRL, DWB_ENABLE, 0);
0128 
0129     DC_LOG_DWB("%s dwb3_disabled at inst = %d", __func__, dwbc->inst);
0130     return true;
0131 }
0132 
0133 bool dwb3_update(struct dwbc *dwbc, struct dc_dwb_params *params)
0134 {
0135     struct dcn30_dwbc *dwbc30 = TO_DCN30_DWBC(dwbc);
0136     unsigned int pre_locked;
0137 
0138     /*
0139      * Check if the caller has already locked DWB registers.
0140      * If so: assume the caller will unlock, so don't touch the lock.
0141      * If not: lock them for this update, then unlock after the
0142      * update is complete.
0143      */
0144     REG_GET(DWB_UPDATE_CTRL, DWB_UPDATE_LOCK, &pre_locked);
0145     DC_LOG_DWB("%s dwb update, inst = %d", __func__, dwbc->inst);
0146 
0147     if (pre_locked == 0) {
0148         /* Lock DWB registers */
0149         REG_UPDATE(DWB_UPDATE_CTRL, DWB_UPDATE_LOCK, 1);
0150     }
0151 
0152     /* Set FC parameters */
0153     dwb3_config_fc(dwbc, params);
0154 
0155     /* Program color processing unit */
0156     dwb3_program_hdr_mult(dwbc, params);
0157     dwb3_set_gamut_remap(dwbc, params);
0158     dwb3_ogam_set_input_transfer_func(dwbc, params->out_transfer_func);
0159 
0160     /* Program output denorm */
0161     dwb3_set_denorm(dwbc, params);
0162 
0163     if (pre_locked == 0) {
0164         /* Unlock DWB registers */
0165         REG_UPDATE(DWB_UPDATE_CTRL, DWB_UPDATE_LOCK, 0);
0166     }
0167 
0168     return true;
0169 }
0170 
0171 bool dwb3_is_enabled(struct dwbc *dwbc)
0172 {
0173     struct dcn30_dwbc *dwbc30 = TO_DCN30_DWBC(dwbc);
0174     unsigned int dwb_enabled = 0;
0175     unsigned int fc_frame_capture_en = 0;
0176 
0177     REG_GET(DWB_ENABLE_CLK_CTRL, DWB_ENABLE, &dwb_enabled);
0178     REG_GET(FC_MODE_CTRL, FC_FRAME_CAPTURE_EN, &fc_frame_capture_en);
0179 
0180     return ((dwb_enabled != 0) && (fc_frame_capture_en != 0));
0181 }
0182 
0183 void dwb3_set_stereo(struct dwbc *dwbc,
0184         struct dwb_stereo_params *stereo_params)
0185 {
0186     struct dcn30_dwbc *dwbc30 = TO_DCN30_DWBC(dwbc);
0187 
0188     if (stereo_params->stereo_enabled) {
0189         REG_UPDATE(FC_MODE_CTRL, FC_EYE_SELECTION,       stereo_params->stereo_eye_select);
0190         REG_UPDATE(FC_MODE_CTRL, FC_STEREO_EYE_POLARITY, stereo_params->stereo_polarity);
0191         DC_LOG_DWB("%s dwb stereo enabled", __func__);
0192     } else {
0193         REG_UPDATE(FC_MODE_CTRL, FC_EYE_SELECTION, 0);
0194         DC_LOG_DWB("%s dwb stereo disabled", __func__);
0195     }
0196 }
0197 
0198 void dwb3_set_new_content(struct dwbc *dwbc,
0199                         bool is_new_content)
0200 {
0201     struct dcn30_dwbc *dwbc30 = TO_DCN30_DWBC(dwbc);
0202 
0203     REG_UPDATE(FC_MODE_CTRL, FC_NEW_CONTENT, is_new_content);
0204 }
0205 
0206 void dwb3_set_denorm(struct dwbc *dwbc, struct dc_dwb_params *params)
0207 {
0208     struct dcn30_dwbc *dwbc30 = TO_DCN30_DWBC(dwbc);
0209 
0210     /* Set output format*/
0211     REG_UPDATE(DWB_OUT_CTRL, OUT_FORMAT, params->cnv_params.fc_out_format);
0212 
0213     /* Set output denorm */
0214     if (params->cnv_params.fc_out_format == DWB_OUT_FORMAT_32BPP_ARGB ||
0215             params->cnv_params.fc_out_format == DWB_OUT_FORMAT_32BPP_RGBA) {
0216         REG_UPDATE(DWB_OUT_CTRL, OUT_DENORM, params->cnv_params.out_denorm_mode);
0217         REG_UPDATE(DWB_OUT_CTRL, OUT_MAX,    params->cnv_params.out_max_pix_val);
0218         REG_UPDATE(DWB_OUT_CTRL, OUT_MIN,    params->cnv_params.out_min_pix_val);
0219     }
0220 }
0221 
0222 
0223 const struct dwbc_funcs dcn30_dwbc_funcs = {
0224     .get_caps       = dwb3_get_caps,
0225     .enable         = dwb3_enable,
0226     .disable        = dwb3_disable,
0227     .update         = dwb3_update,
0228     .is_enabled     = dwb3_is_enabled,
0229     .set_stereo     = dwb3_set_stereo,
0230     .set_new_content    = dwb3_set_new_content,
0231     .dwb_program_output_csc = NULL,
0232     .dwb_ogam_set_input_transfer_func   = dwb3_ogam_set_input_transfer_func, //TODO: rename
0233     .dwb_set_scaler     = NULL,
0234 };
0235 
0236 void dcn30_dwbc_construct(struct dcn30_dwbc *dwbc30,
0237         struct dc_context *ctx,
0238         const struct dcn30_dwbc_registers *dwbc_regs,
0239         const struct dcn30_dwbc_shift *dwbc_shift,
0240         const struct dcn30_dwbc_mask *dwbc_mask,
0241         int inst)
0242 {
0243     dwbc30->base.ctx = ctx;
0244 
0245     dwbc30->base.inst = inst;
0246     dwbc30->base.funcs = &dcn30_dwbc_funcs;
0247 
0248     dwbc30->dwbc_regs = dwbc_regs;
0249     dwbc30->dwbc_shift = dwbc_shift;
0250     dwbc30->dwbc_mask = dwbc_mask;
0251 }
0252 
0253 void dwb3_set_host_read_rate_control(struct dwbc *dwbc, bool host_read_delay)
0254 {
0255     struct dcn30_dwbc *dwbc30 = TO_DCN30_DWBC(dwbc);
0256 
0257     /*
0258      * Set maximum delay of host read access to DWBSCL LUT or OGAM LUT if there are no
0259      * idle cycles in HW pipeline (in number of clock cycles times 4)
0260      */
0261     REG_UPDATE(DWB_HOST_READ_CONTROL, DWB_HOST_READ_RATE_CONTROL, host_read_delay);
0262 
0263     DC_LOG_DWB("%s dwb3_rate_control at inst = %d", __func__, dwbc->inst);
0264 }