linux/drivers/gpu/drm/amd/display/dc/dce60/dce60_hw_sequencer.c
<<
>>
Prefs
   1/*
   2 * Copyright 2020 Mauro Rossi <issor.oruam@gmail.com>
   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#include "dc.h"
  28#include "core_types.h"
  29#include "dce60_hw_sequencer.h"
  30
  31#include "dce/dce_hwseq.h"
  32#include "dce110/dce110_hw_sequencer.h"
  33#include "dce100/dce100_hw_sequencer.h"
  34
  35/* include DCE6 register header files */
  36#include "dce/dce_6_0_d.h"
  37#include "dce/dce_6_0_sh_mask.h"
  38
  39#define DC_LOGGER_INIT()
  40
  41/*******************************************************************************
  42 * Private definitions
  43 ******************************************************************************/
  44
  45/***************************PIPE_CONTROL***********************************/
  46
  47/*
  48 *  Check if FBC can be enabled
  49 */
  50static bool dce60_should_enable_fbc(struct dc *dc,
  51                struct dc_state *context,
  52                uint32_t *pipe_idx)
  53{
  54        uint32_t i;
  55        struct pipe_ctx *pipe_ctx = NULL;
  56        struct resource_context *res_ctx = &context->res_ctx;
  57        unsigned int underlay_idx = dc->res_pool->underlay_pipe_index;
  58
  59
  60        ASSERT(dc->fbc_compressor);
  61
  62        /* FBC memory should be allocated */
  63        if (!dc->ctx->fbc_gpu_addr)
  64                return false;
  65
  66        /* Only supports single display */
  67        if (context->stream_count != 1)
  68                return false;
  69
  70        for (i = 0; i < dc->res_pool->pipe_count; i++) {
  71                if (res_ctx->pipe_ctx[i].stream) {
  72
  73                        pipe_ctx = &res_ctx->pipe_ctx[i];
  74
  75                        if (!pipe_ctx)
  76                                continue;
  77
  78                        /* fbc not applicable on underlay pipe */
  79                        if (pipe_ctx->pipe_idx != underlay_idx) {
  80                                *pipe_idx = i;
  81                                break;
  82                        }
  83                }
  84        }
  85
  86        if (i == dc->res_pool->pipe_count)
  87                return false;
  88
  89        if (!pipe_ctx->stream->link)
  90                return false;
  91
  92        /* Only supports eDP */
  93        if (pipe_ctx->stream->link->connector_signal != SIGNAL_TYPE_EDP)
  94                return false;
  95
  96        /* PSR should not be enabled */
  97        if (pipe_ctx->stream->link->psr_settings.psr_feature_enabled)
  98                return false;
  99
 100        /* Nothing to compress */
 101        if (!pipe_ctx->plane_state)
 102                return false;
 103
 104        /* Only for non-linear tiling */
 105        if (pipe_ctx->plane_state->tiling_info.gfx8.array_mode == DC_ARRAY_LINEAR_GENERAL)
 106                return false;
 107
 108        return true;
 109}
 110
 111/*
 112 *  Enable FBC
 113 */
 114static void dce60_enable_fbc(
 115                struct dc *dc,
 116                struct dc_state *context)
 117{
 118        uint32_t pipe_idx = 0;
 119
 120        if (dce60_should_enable_fbc(dc, context, &pipe_idx)) {
 121                /* Program GRPH COMPRESSED ADDRESS and PITCH */
 122                struct compr_addr_and_pitch_params params = {0, 0, 0};
 123                struct compressor *compr = dc->fbc_compressor;
 124                struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx];
 125
 126                params.source_view_width = pipe_ctx->stream->timing.h_addressable;
 127                params.source_view_height = pipe_ctx->stream->timing.v_addressable;
 128                params.inst = pipe_ctx->stream_res.tg->inst;
 129                compr->compr_surface_address.quad_part = dc->ctx->fbc_gpu_addr;
 130
 131                compr->funcs->surface_address_and_pitch(compr, &params);
 132                compr->funcs->set_fbc_invalidation_triggers(compr, 1);
 133
 134                compr->funcs->enable_fbc(compr, &params);
 135        }
 136}
 137
 138
 139/*******************************************************************************
 140 * Front End programming
 141 ******************************************************************************/
 142
 143static void dce60_set_default_colors(struct pipe_ctx *pipe_ctx)
 144{
 145        struct default_adjustment default_adjust = { 0 };
 146
 147        default_adjust.force_hw_default = false;
 148        default_adjust.in_color_space = pipe_ctx->plane_state->color_space;
 149        default_adjust.out_color_space = pipe_ctx->stream->output_color_space;
 150        default_adjust.csc_adjust_type = GRAPHICS_CSC_ADJUST_TYPE_SW;
 151        default_adjust.surface_pixel_format = pipe_ctx->plane_res.scl_data.format;
 152
 153        /* display color depth */
 154        default_adjust.color_depth =
 155                pipe_ctx->stream->timing.display_color_depth;
 156
 157        /* Lb color depth */
 158        default_adjust.lb_color_depth = pipe_ctx->plane_res.scl_data.lb_params.depth;
 159
 160        pipe_ctx->plane_res.xfm->funcs->opp_set_csc_default(
 161                                        pipe_ctx->plane_res.xfm, &default_adjust);
 162}
 163
 164/*******************************************************************************
 165 * In order to turn on surface we will program
 166 * CRTC
 167 *
 168 * DCE6 has no bottom_pipe and no Blender HW
 169 * We need to set 'blank_target' to false in order to turn on the display
 170 *
 171 * |-----------|------------|---------|
 172 * |curr pipe  | set_blank  |         |
 173 * |Surface    |blank_target|  CRCT   |
 174 * |visibility |  argument  |         |
 175 * |-----------|------------|---------|
 176 * |    off    |   true     | blank   |
 177 * |    on     |   false    | unblank |
 178 * |-----------|------------|---------|
 179 *
 180 ******************************************************************************/
 181static void dce60_program_surface_visibility(const struct dc *dc,
 182                struct pipe_ctx *pipe_ctx)
 183{
 184        bool blank_target = false;
 185
 186        /* DCE6 has no bottom_pipe and no Blender HW */
 187
 188        if (!pipe_ctx->plane_state->visible)
 189                blank_target = true;
 190
 191        /* DCE6 skip dce_set_blender_mode() but then proceed to 'unblank' CRTC */
 192        pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, blank_target);
 193
 194}
 195
 196
 197static void dce60_get_surface_visual_confirm_color(const struct pipe_ctx *pipe_ctx,
 198                struct tg_color *color)
 199{
 200        uint32_t color_value = MAX_TG_COLOR_VALUE * (4 - pipe_ctx->stream_res.tg->inst) / 4;
 201
 202        switch (pipe_ctx->plane_res.scl_data.format) {
 203        case PIXEL_FORMAT_ARGB8888:
 204                /* set boarder color to red */
 205                color->color_r_cr = color_value;
 206                break;
 207
 208        case PIXEL_FORMAT_ARGB2101010:
 209                /* set boarder color to blue */
 210                color->color_b_cb = color_value;
 211                break;
 212        case PIXEL_FORMAT_420BPP8:
 213                /* set boarder color to green */
 214                color->color_g_y = color_value;
 215                break;
 216        case PIXEL_FORMAT_420BPP10:
 217                /* set boarder color to yellow */
 218                color->color_g_y = color_value;
 219                color->color_r_cr = color_value;
 220                break;
 221        case PIXEL_FORMAT_FP16:
 222                /* set boarder color to white */
 223                color->color_r_cr = color_value;
 224                color->color_b_cb = color_value;
 225                color->color_g_y = color_value;
 226                break;
 227        default:
 228                break;
 229        }
 230}
 231
 232static void dce60_program_scaler(const struct dc *dc,
 233                const struct pipe_ctx *pipe_ctx)
 234{
 235        struct tg_color color = {0};
 236
 237        /* DCE6 skips DCN TOFPGA check for transform_set_pixel_storage_depth == NULL */
 238
 239        if (dc->debug.visual_confirm == VISUAL_CONFIRM_SURFACE)
 240                dce60_get_surface_visual_confirm_color(pipe_ctx, &color);
 241        else
 242                color_space_to_black_color(dc,
 243                                pipe_ctx->stream->output_color_space,
 244                                &color);
 245
 246        pipe_ctx->plane_res.xfm->funcs->transform_set_pixel_storage_depth(
 247                pipe_ctx->plane_res.xfm,
 248                pipe_ctx->plane_res.scl_data.lb_params.depth,
 249                &pipe_ctx->stream->bit_depth_params);
 250
 251        if (pipe_ctx->stream_res.tg->funcs->set_overscan_blank_color) {
 252                /*
 253                 * The way 420 is packed, 2 channels carry Y component, 1 channel
 254                 * alternate between Cb and Cr, so both channels need the pixel
 255                 * value for Y
 256                 */
 257                if (pipe_ctx->stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420)
 258                        color.color_r_cr = color.color_g_y;
 259
 260                pipe_ctx->stream_res.tg->funcs->set_overscan_blank_color(
 261                                pipe_ctx->stream_res.tg,
 262                                &color);
 263        }
 264
 265        pipe_ctx->plane_res.xfm->funcs->transform_set_scaler(pipe_ctx->plane_res.xfm,
 266                &pipe_ctx->plane_res.scl_data);
 267}
 268
 269static void
 270dce60_program_front_end_for_pipe(
 271                struct dc *dc, struct pipe_ctx *pipe_ctx)
 272{
 273        struct mem_input *mi = pipe_ctx->plane_res.mi;
 274        struct dc_plane_state *plane_state = pipe_ctx->plane_state;
 275        struct xfm_grph_csc_adjustment adjust;
 276        struct out_csc_color_matrix tbl_entry;
 277        unsigned int i;
 278        struct dce_hwseq *hws = dc->hwseq;
 279
 280        DC_LOGGER_INIT();
 281        memset(&tbl_entry, 0, sizeof(tbl_entry));
 282
 283        memset(&adjust, 0, sizeof(adjust));
 284        adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
 285
 286        dce_enable_fe_clock(dc->hwseq, mi->inst, true);
 287
 288        dce60_set_default_colors(pipe_ctx);
 289        if (pipe_ctx->stream->csc_color_matrix.enable_adjustment
 290                        == true) {
 291                tbl_entry.color_space =
 292                        pipe_ctx->stream->output_color_space;
 293
 294                for (i = 0; i < 12; i++)
 295                        tbl_entry.regval[i] =
 296                        pipe_ctx->stream->csc_color_matrix.matrix[i];
 297
 298                pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment
 299                                (pipe_ctx->plane_res.xfm, &tbl_entry);
 300        }
 301
 302        if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) {
 303                adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
 304
 305                for (i = 0; i < CSC_TEMPERATURE_MATRIX_SIZE; i++)
 306                        adjust.temperature_matrix[i] =
 307                                pipe_ctx->stream->gamut_remap_matrix.matrix[i];
 308        }
 309
 310        pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust);
 311
 312        pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0;
 313
 314        dce60_program_scaler(dc, pipe_ctx);
 315
 316        mi->funcs->mem_input_program_surface_config(
 317                        mi,
 318                        plane_state->format,
 319                        &plane_state->tiling_info,
 320                        &plane_state->plane_size,
 321                        plane_state->rotation,
 322                        NULL,
 323                        false);
 324        if (mi->funcs->set_blank)
 325                mi->funcs->set_blank(mi, pipe_ctx->plane_state->visible);
 326
 327        if (dc->config.gpu_vm_support)
 328                mi->funcs->mem_input_program_pte_vm(
 329                                pipe_ctx->plane_res.mi,
 330                                plane_state->format,
 331                                &plane_state->tiling_info,
 332                                plane_state->rotation);
 333
 334        /* Moved programming gamma from dc to hwss */
 335        if (pipe_ctx->plane_state->update_flags.bits.full_update ||
 336                        pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change ||
 337                        pipe_ctx->plane_state->update_flags.bits.gamma_change)
 338                hws->funcs.set_input_transfer_func(dc, pipe_ctx, pipe_ctx->plane_state);
 339
 340        if (pipe_ctx->plane_state->update_flags.bits.full_update)
 341                hws->funcs.set_output_transfer_func(dc, pipe_ctx, pipe_ctx->stream);
 342
 343        DC_LOG_SURFACE(
 344                        "Pipe:%d %p: addr hi:0x%x, "
 345                        "addr low:0x%x, "
 346                        "src: %d, %d, %d,"
 347                        " %d; dst: %d, %d, %d, %d;"
 348                        "clip: %d, %d, %d, %d\n",
 349                        pipe_ctx->pipe_idx,
 350                        (void *) pipe_ctx->plane_state,
 351                        pipe_ctx->plane_state->address.grph.addr.high_part,
 352                        pipe_ctx->plane_state->address.grph.addr.low_part,
 353                        pipe_ctx->plane_state->src_rect.x,
 354                        pipe_ctx->plane_state->src_rect.y,
 355                        pipe_ctx->plane_state->src_rect.width,
 356                        pipe_ctx->plane_state->src_rect.height,
 357                        pipe_ctx->plane_state->dst_rect.x,
 358                        pipe_ctx->plane_state->dst_rect.y,
 359                        pipe_ctx->plane_state->dst_rect.width,
 360                        pipe_ctx->plane_state->dst_rect.height,
 361                        pipe_ctx->plane_state->clip_rect.x,
 362                        pipe_ctx->plane_state->clip_rect.y,
 363                        pipe_ctx->plane_state->clip_rect.width,
 364                        pipe_ctx->plane_state->clip_rect.height);
 365
 366        DC_LOG_SURFACE(
 367                        "Pipe %d: width, height, x, y\n"
 368                        "viewport:%d, %d, %d, %d\n"
 369                        "recout:  %d, %d, %d, %d\n",
 370                        pipe_ctx->pipe_idx,
 371                        pipe_ctx->plane_res.scl_data.viewport.width,
 372                        pipe_ctx->plane_res.scl_data.viewport.height,
 373                        pipe_ctx->plane_res.scl_data.viewport.x,
 374                        pipe_ctx->plane_res.scl_data.viewport.y,
 375                        pipe_ctx->plane_res.scl_data.recout.width,
 376                        pipe_ctx->plane_res.scl_data.recout.height,
 377                        pipe_ctx->plane_res.scl_data.recout.x,
 378                        pipe_ctx->plane_res.scl_data.recout.y);
 379}
 380
 381static void dce60_apply_ctx_for_surface(
 382                struct dc *dc,
 383                const struct dc_stream_state *stream,
 384                int num_planes,
 385                struct dc_state *context)
 386{
 387        int i;
 388
 389        if (num_planes == 0)
 390                return;
 391
 392        if (dc->fbc_compressor)
 393                dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor);
 394
 395        for (i = 0; i < dc->res_pool->pipe_count; i++) {
 396                struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
 397
 398                if (pipe_ctx->stream != stream)
 399                        continue;
 400
 401                /* Need to allocate mem before program front end for Fiji */
 402                pipe_ctx->plane_res.mi->funcs->allocate_mem_input(
 403                                pipe_ctx->plane_res.mi,
 404                                pipe_ctx->stream->timing.h_total,
 405                                pipe_ctx->stream->timing.v_total,
 406                                pipe_ctx->stream->timing.pix_clk_100hz / 10,
 407                                context->stream_count);
 408
 409                dce60_program_front_end_for_pipe(dc, pipe_ctx);
 410
 411                dc->hwss.update_plane_addr(dc, pipe_ctx);
 412
 413                dce60_program_surface_visibility(dc, pipe_ctx);
 414
 415        }
 416
 417        if (dc->fbc_compressor)
 418                dce60_enable_fbc(dc, context);
 419}
 420
 421void dce60_hw_sequencer_construct(struct dc *dc)
 422{
 423        dce110_hw_sequencer_construct(dc);
 424
 425        dc->hwseq->funcs.enable_display_power_gating = dce100_enable_display_power_gating;
 426        dc->hwss.apply_ctx_for_surface = dce60_apply_ctx_for_surface;
 427        dc->hwss.cursor_lock = dce60_pipe_control_lock;
 428        dc->hwss.pipe_control_lock = dce60_pipe_control_lock;
 429        dc->hwss.prepare_bandwidth = dce100_prepare_bandwidth;
 430        dc->hwss.optimize_bandwidth = dce100_optimize_bandwidth;
 431}
 432
 433