linux/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb.c
<<
>>
Prefs
   1/*
   2 * Copyright 2020 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 "dcn30_dwb.h"
  31
  32
  33#define REG(reg)\
  34        dwbc30->dwbc_regs->reg
  35
  36#define CTX \
  37        dwbc30->base.ctx
  38
  39#undef FN
  40#define FN(reg_name, field_name) \
  41        dwbc30->dwbc_shift->field_name, dwbc30->dwbc_mask->field_name
  42
  43#define DC_LOGGER \
  44        dwbc30->base.ctx->logger
  45
  46static bool dwb3_get_caps(struct dwbc *dwbc, struct dwb_caps *caps)
  47{
  48        if (caps) {
  49                caps->adapter_id = 0;   /* we only support 1 adapter currently */
  50                caps->hw_version = DCN_VERSION_3_0;
  51                caps->num_pipes = 2;
  52                memset(&caps->reserved, 0, sizeof(caps->reserved));
  53                memset(&caps->reserved2, 0, sizeof(caps->reserved2));
  54                caps->sw_version = dwb_ver_2_0;
  55                caps->caps.support_dwb = true;
  56                caps->caps.support_ogam = true;
  57                caps->caps.support_wbscl = true;
  58                caps->caps.support_ocsc = false;
  59                caps->caps.support_stereo = true;
  60                return true;
  61        } else {
  62                return false;
  63        }
  64}
  65
  66void dwb3_config_fc(struct dwbc *dwbc, struct dc_dwb_params *params)
  67{
  68        struct dcn30_dwbc *dwbc30 = TO_DCN30_DWBC(dwbc);
  69
  70        /* Set DWB source size */
  71        REG_UPDATE_2(FC_SOURCE_SIZE, FC_SOURCE_WIDTH, params->cnv_params.src_width,
  72                        FC_SOURCE_HEIGHT, params->cnv_params.src_height);
  73
  74        /* source size is not equal the source size, then enable cropping. */
  75        if (params->cnv_params.crop_en) {
  76                REG_UPDATE(FC_MODE_CTRL,    FC_WINDOW_CROP_EN, 1);
  77                REG_UPDATE(FC_WINDOW_START, FC_WINDOW_START_X, params->cnv_params.crop_x);
  78                REG_UPDATE(FC_WINDOW_START, FC_WINDOW_START_Y, params->cnv_params.crop_y);
  79                REG_UPDATE(FC_WINDOW_SIZE,  FC_WINDOW_WIDTH,   params->cnv_params.crop_width);
  80                REG_UPDATE(FC_WINDOW_SIZE,  FC_WINDOW_HEIGHT,  params->cnv_params.crop_height);
  81        } else {
  82                REG_UPDATE(FC_MODE_CTRL,    FC_WINDOW_CROP_EN, 0);
  83        }
  84
  85        /* Set CAPTURE_RATE */
  86        REG_UPDATE(FC_MODE_CTRL, FC_FRAME_CAPTURE_RATE, params->capture_rate);
  87
  88        dwb3_set_stereo(dwbc, &params->stereo_params);
  89}
  90
  91bool dwb3_enable(struct dwbc *dwbc, struct dc_dwb_params *params)
  92{
  93        struct dcn30_dwbc *dwbc30 = TO_DCN30_DWBC(dwbc);
  94        DC_LOG_DWB("%s dwb3_enabled at inst = %d", __func__, dwbc->inst);
  95
  96        /* Set WB_ENABLE (not double buffered; capture not enabled) */
  97        REG_UPDATE(DWB_ENABLE_CLK_CTRL, DWB_ENABLE, 1);
  98
  99        /* Set FC parameters */
 100        dwb3_config_fc(dwbc, params);
 101
 102        /* Program color processing unit */
 103        dwb3_program_hdr_mult(dwbc, params);
 104        dwb3_set_gamut_remap(dwbc, params);
 105        dwb3_ogam_set_input_transfer_func(dwbc, params->out_transfer_func);
 106
 107        /* Program output denorm */
 108        dwb3_set_denorm(dwbc, params);
 109
 110        /* Enable DWB capture enable (double buffered) */
 111        REG_UPDATE(FC_MODE_CTRL, FC_FRAME_CAPTURE_EN, DWB_FRAME_CAPTURE_ENABLE);
 112
 113        /* First pixel count */
 114        REG_UPDATE(FC_FLOW_CTRL, FC_FIRST_PIXEL_DELAY_COUNT, 96);
 115
 116        return true;
 117}
 118
 119bool dwb3_disable(struct dwbc *dwbc)
 120{
 121        struct dcn30_dwbc *dwbc30 = TO_DCN30_DWBC(dwbc);
 122
 123        /* disable FC */
 124        REG_UPDATE(FC_MODE_CTRL, FC_FRAME_CAPTURE_EN, DWB_FRAME_CAPTURE_DISABLE);
 125
 126        /* disable WB */
 127        REG_UPDATE(DWB_ENABLE_CLK_CTRL, DWB_ENABLE, 0);
 128
 129        DC_LOG_DWB("%s dwb3_disabled at inst = %d", __func__, dwbc->inst);
 130        return true;
 131}
 132
 133bool dwb3_update(struct dwbc *dwbc, struct dc_dwb_params *params)
 134{
 135        struct dcn30_dwbc *dwbc30 = TO_DCN30_DWBC(dwbc);
 136        unsigned int pre_locked;
 137
 138        /*
 139         * Check if the caller has already locked DWB registers.
 140         * If so: assume the caller will unlock, so don't touch the lock.
 141         * If not: lock them for this update, then unlock after the
 142         * update is complete.
 143         */
 144        REG_GET(DWB_UPDATE_CTRL, DWB_UPDATE_LOCK, &pre_locked);
 145        DC_LOG_DWB("%s dwb update, inst = %d", __func__, dwbc->inst);
 146
 147        if (pre_locked == 0) {
 148                /* Lock DWB registers */
 149                REG_UPDATE(DWB_UPDATE_CTRL, DWB_UPDATE_LOCK, 1);
 150        }
 151
 152        /* Set FC parameters */
 153        dwb3_config_fc(dwbc, params);
 154
 155        /* Program color processing unit */
 156        dwb3_program_hdr_mult(dwbc, params);
 157        dwb3_set_gamut_remap(dwbc, params);
 158        dwb3_ogam_set_input_transfer_func(dwbc, params->out_transfer_func);
 159
 160        /* Program output denorm */
 161        dwb3_set_denorm(dwbc, params);
 162
 163        if (pre_locked == 0) {
 164                /* Unlock DWB registers */
 165                REG_UPDATE(DWB_UPDATE_CTRL, DWB_UPDATE_LOCK, 0);
 166        }
 167
 168        return true;
 169}
 170
 171bool dwb3_is_enabled(struct dwbc *dwbc)
 172{
 173        struct dcn30_dwbc *dwbc30 = TO_DCN30_DWBC(dwbc);
 174        unsigned int dwb_enabled = 0;
 175        unsigned int fc_frame_capture_en = 0;
 176
 177        REG_GET(DWB_ENABLE_CLK_CTRL, DWB_ENABLE, &dwb_enabled);
 178        REG_GET(FC_MODE_CTRL, FC_FRAME_CAPTURE_EN, &fc_frame_capture_en);
 179
 180        return ((dwb_enabled != 0) && (fc_frame_capture_en != 0));
 181}
 182
 183void dwb3_set_stereo(struct dwbc *dwbc,
 184                struct dwb_stereo_params *stereo_params)
 185{
 186        struct dcn30_dwbc *dwbc30 = TO_DCN30_DWBC(dwbc);
 187
 188        if (stereo_params->stereo_enabled) {
 189                REG_UPDATE(FC_MODE_CTRL, FC_EYE_SELECTION,       stereo_params->stereo_eye_select);
 190                REG_UPDATE(FC_MODE_CTRL, FC_STEREO_EYE_POLARITY, stereo_params->stereo_polarity);
 191                DC_LOG_DWB("%s dwb stereo enabled", __func__);
 192        } else {
 193                REG_UPDATE(FC_MODE_CTRL, FC_EYE_SELECTION, 0);
 194                DC_LOG_DWB("%s dwb stereo disabled", __func__);
 195        }
 196}
 197
 198void dwb3_set_new_content(struct dwbc *dwbc,
 199                                                bool is_new_content)
 200{
 201        struct dcn30_dwbc *dwbc30 = TO_DCN30_DWBC(dwbc);
 202
 203        REG_UPDATE(FC_MODE_CTRL, FC_NEW_CONTENT, is_new_content);
 204}
 205
 206void dwb3_set_denorm(struct dwbc *dwbc, struct dc_dwb_params *params)
 207{
 208        struct dcn30_dwbc *dwbc30 = TO_DCN30_DWBC(dwbc);
 209
 210        /* Set output format*/
 211        REG_UPDATE(DWB_OUT_CTRL, OUT_FORMAT, params->cnv_params.fc_out_format);
 212
 213        /* Set output denorm */
 214        if (params->cnv_params.fc_out_format == DWB_OUT_FORMAT_32BPP_ARGB ||
 215                        params->cnv_params.fc_out_format == DWB_OUT_FORMAT_32BPP_RGBA) {
 216                REG_UPDATE(DWB_OUT_CTRL, OUT_DENORM, params->cnv_params.out_denorm_mode);
 217                REG_UPDATE(DWB_OUT_CTRL, OUT_MAX,    params->cnv_params.out_max_pix_val);
 218                REG_UPDATE(DWB_OUT_CTRL, OUT_MIN,    params->cnv_params.out_min_pix_val);
 219        }
 220}
 221
 222
 223const struct dwbc_funcs dcn30_dwbc_funcs = {
 224        .get_caps               = dwb3_get_caps,
 225        .enable                 = dwb3_enable,
 226        .disable                = dwb3_disable,
 227        .update                 = dwb3_update,
 228        .is_enabled             = dwb3_is_enabled,
 229        .set_stereo             = dwb3_set_stereo,
 230        .set_new_content        = dwb3_set_new_content,
 231        .dwb_program_output_csc = NULL,
 232        .dwb_ogam_set_input_transfer_func       = dwb3_ogam_set_input_transfer_func, //TODO: rename
 233        .dwb_set_scaler         = NULL,
 234};
 235
 236void dcn30_dwbc_construct(struct dcn30_dwbc *dwbc30,
 237                struct dc_context *ctx,
 238                const struct dcn30_dwbc_registers *dwbc_regs,
 239                const struct dcn30_dwbc_shift *dwbc_shift,
 240                const struct dcn30_dwbc_mask *dwbc_mask,
 241                int inst)
 242{
 243        dwbc30->base.ctx = ctx;
 244
 245        dwbc30->base.inst = inst;
 246        dwbc30->base.funcs = &dcn30_dwbc_funcs;
 247
 248        dwbc30->dwbc_regs = dwbc_regs;
 249        dwbc30->dwbc_shift = dwbc_shift;
 250        dwbc30->dwbc_mask = dwbc_mask;
 251}
 252
 253void dwb3_set_host_read_rate_control(struct dwbc *dwbc, bool host_read_delay)
 254{
 255        struct dcn30_dwbc *dwbc30 = TO_DCN30_DWBC(dwbc);
 256
 257        /*
 258         * Set maximum delay of host read access to DWBSCL LUT or OGAM LUT if there are no
 259         * idle cycles in HW pipeline (in number of clock cycles times 4)
 260         */
 261        REG_UPDATE(DWB_HOST_READ_CONTROL, DWB_HOST_READ_RATE_CONTROL, host_read_delay);
 262
 263        DC_LOG_DWB("%s dwb3_rate_control at inst = %d", __func__, dwbc->inst);
 264}
 265