OSDN Git Service

drm/amd/display: dce60_hw_sequencer: add DCE6 specific functions (v2)
authorMauro Rossi <issor.oruam@gmail.com>
Fri, 10 Jul 2020 18:40:01 +0000 (20:40 +0200)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 27 Jul 2020 20:46:37 +0000 (16:46 -0400)
[Why]
DCE6 has no bottom_pipe and no Blender HW
DCE6 needs 'blank_target' set to false in order to turn on the display
DCE6 has a specific dce60_pipe_control_lock() fuction that is a no op

[How]
Add DCE6 specific functions with needed private dce60_* dependent fuctions
Comment DCE6 specific CTRC program visibility implementation
Fix a typo in the initial header includes comment 's/DCE8/DCE6/g'
Use dce60_apply_ctx_for_surface() in dce60_hw_sequencer_construct
Use dce60_pipe_control_lock() in dce60_hw_sequencer_construct

v2: add missing return type (Alex)

Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Mauro Rossi <issor.oruam@gmail.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/dce60/dce60_hw_sequencer.c

index e30e351..9d8797a 100644 (file)
 #include "dce110/dce110_hw_sequencer.h"
 #include "dce100/dce100_hw_sequencer.h"
 
-/* include DCE8 register header files */
+/* include DCE6 register header files */
 #include "dce/dce_6_0_d.h"
 #include "dce/dce_6_0_sh_mask.h"
 
+#define DC_LOGGER_INIT()
+
 /*******************************************************************************
  * Private definitions
  ******************************************************************************/
 
 /***************************PIPE_CONTROL***********************************/
 
+/*
+ *  Check if FBC can be enabled
+ */
+static bool dce60_should_enable_fbc(struct dc *dc,
+               struct dc_state *context,
+               uint32_t *pipe_idx)
+{
+       uint32_t i;
+       struct pipe_ctx *pipe_ctx = NULL;
+       struct resource_context *res_ctx = &context->res_ctx;
+       unsigned int underlay_idx = dc->res_pool->underlay_pipe_index;
+
+
+       ASSERT(dc->fbc_compressor);
+
+       /* FBC memory should be allocated */
+       if (!dc->ctx->fbc_gpu_addr)
+               return false;
+
+       /* Only supports single display */
+       if (context->stream_count != 1)
+               return false;
+
+       for (i = 0; i < dc->res_pool->pipe_count; i++) {
+               if (res_ctx->pipe_ctx[i].stream) {
+
+                       pipe_ctx = &res_ctx->pipe_ctx[i];
+
+                       if (!pipe_ctx)
+                               continue;
+
+                       /* fbc not applicable on underlay pipe */
+                       if (pipe_ctx->pipe_idx != underlay_idx) {
+                               *pipe_idx = i;
+                               break;
+                       }
+               }
+       }
+
+       if (i == dc->res_pool->pipe_count)
+               return false;
+
+       if (!pipe_ctx->stream->link)
+               return false;
+
+       /* Only supports eDP */
+       if (pipe_ctx->stream->link->connector_signal != SIGNAL_TYPE_EDP)
+               return false;
+
+       /* PSR should not be enabled */
+       if (pipe_ctx->stream->link->psr_settings.psr_feature_enabled)
+               return false;
+
+       /* Nothing to compress */
+       if (!pipe_ctx->plane_state)
+               return false;
+
+       /* Only for non-linear tiling */
+       if (pipe_ctx->plane_state->tiling_info.gfx8.array_mode == DC_ARRAY_LINEAR_GENERAL)
+               return false;
+
+       return true;
+}
+
+/*
+ *  Enable FBC
+ */
+static void dce60_enable_fbc(
+               struct dc *dc,
+               struct dc_state *context)
+{
+       uint32_t pipe_idx = 0;
+
+       if (dce60_should_enable_fbc(dc, context, &pipe_idx)) {
+               /* Program GRPH COMPRESSED ADDRESS and PITCH */
+               struct compr_addr_and_pitch_params params = {0, 0, 0};
+               struct compressor *compr = dc->fbc_compressor;
+               struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx];
+
+               params.source_view_width = pipe_ctx->stream->timing.h_addressable;
+               params.source_view_height = pipe_ctx->stream->timing.v_addressable;
+               params.inst = pipe_ctx->stream_res.tg->inst;
+               compr->compr_surface_address.quad_part = dc->ctx->fbc_gpu_addr;
+
+               compr->funcs->surface_address_and_pitch(compr, &params);
+               compr->funcs->set_fbc_invalidation_triggers(compr, 1);
+
+               compr->funcs->enable_fbc(compr, &params);
+       }
+}
+
+
+/*******************************************************************************
+ * Front End programming
+ ******************************************************************************/
+
+static void dce60_set_default_colors(struct pipe_ctx *pipe_ctx)
+{
+       struct default_adjustment default_adjust = { 0 };
+
+       default_adjust.force_hw_default = false;
+       default_adjust.in_color_space = pipe_ctx->plane_state->color_space;
+       default_adjust.out_color_space = pipe_ctx->stream->output_color_space;
+       default_adjust.csc_adjust_type = GRAPHICS_CSC_ADJUST_TYPE_SW;
+       default_adjust.surface_pixel_format = pipe_ctx->plane_res.scl_data.format;
+
+       /* display color depth */
+       default_adjust.color_depth =
+               pipe_ctx->stream->timing.display_color_depth;
+
+       /* Lb color depth */
+       default_adjust.lb_color_depth = pipe_ctx->plane_res.scl_data.lb_params.depth;
+
+       pipe_ctx->plane_res.xfm->funcs->opp_set_csc_default(
+                                       pipe_ctx->plane_res.xfm, &default_adjust);
+}
+
+/*******************************************************************************
+ * In order to turn on surface we will program
+ * CRTC
+ *
+ * DCE6 has no bottom_pipe and no Blender HW
+ * We need to set 'blank_target' to false in order to turn on the display
+ *
+ * |-----------|------------|---------|
+ * |curr pipe  | set_blank  |         |
+ * |Surface    |blank_target|  CRCT   |
+ * |visibility |  argument  |         |
+ * |-----------|------------|---------|
+ * |    off    |   true     | blank   |
+ * |    on     |   false    | unblank |
+ * |-----------|------------|---------|
+ *
+ ******************************************************************************/
+static void dce60_program_surface_visibility(const struct dc *dc,
+               struct pipe_ctx *pipe_ctx)
+{
+       bool blank_target = false;
+
+       /* DCE6 has no bottom_pipe and no Blender HW */
+
+       if (!pipe_ctx->plane_state->visible)
+               blank_target = true;
+
+       /* DCE6 skip dce_set_blender_mode() but then proceed to 'unblank' CRTC */
+       pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, blank_target);
+
+}
+
+
+static void dce60_get_surface_visual_confirm_color(const struct pipe_ctx *pipe_ctx,
+               struct tg_color *color)
+{
+       uint32_t color_value = MAX_TG_COLOR_VALUE * (4 - pipe_ctx->stream_res.tg->inst) / 4;
+
+       switch (pipe_ctx->plane_res.scl_data.format) {
+       case PIXEL_FORMAT_ARGB8888:
+               /* set boarder color to red */
+               color->color_r_cr = color_value;
+               break;
+
+       case PIXEL_FORMAT_ARGB2101010:
+               /* set boarder color to blue */
+               color->color_b_cb = color_value;
+               break;
+       case PIXEL_FORMAT_420BPP8:
+               /* set boarder color to green */
+               color->color_g_y = color_value;
+               break;
+       case PIXEL_FORMAT_420BPP10:
+               /* set boarder color to yellow */
+               color->color_g_y = color_value;
+               color->color_r_cr = color_value;
+               break;
+       case PIXEL_FORMAT_FP16:
+               /* set boarder color to white */
+               color->color_r_cr = color_value;
+               color->color_b_cb = color_value;
+               color->color_g_y = color_value;
+               break;
+       default:
+               break;
+       }
+}
+
+static void dce60_program_scaler(const struct dc *dc,
+               const struct pipe_ctx *pipe_ctx)
+{
+       struct tg_color color = {0};
+
+       /* DCE6 skips DCN TOFPGA check for transform_set_pixel_storage_depth == NULL */
+
+       if (dc->debug.visual_confirm == VISUAL_CONFIRM_SURFACE)
+               dce60_get_surface_visual_confirm_color(pipe_ctx, &color);
+       else
+               color_space_to_black_color(dc,
+                               pipe_ctx->stream->output_color_space,
+                               &color);
+
+       pipe_ctx->plane_res.xfm->funcs->transform_set_pixel_storage_depth(
+               pipe_ctx->plane_res.xfm,
+               pipe_ctx->plane_res.scl_data.lb_params.depth,
+               &pipe_ctx->stream->bit_depth_params);
+
+       if (pipe_ctx->stream_res.tg->funcs->set_overscan_blank_color) {
+               /*
+                * The way 420 is packed, 2 channels carry Y component, 1 channel
+                * alternate between Cb and Cr, so both channels need the pixel
+                * value for Y
+                */
+               if (pipe_ctx->stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420)
+                       color.color_r_cr = color.color_g_y;
+
+               pipe_ctx->stream_res.tg->funcs->set_overscan_blank_color(
+                               pipe_ctx->stream_res.tg,
+                               &color);
+       }
+
+       pipe_ctx->plane_res.xfm->funcs->transform_set_scaler(pipe_ctx->plane_res.xfm,
+               &pipe_ctx->plane_res.scl_data);
+}
+
+static void
+dce60_program_front_end_for_pipe(
+               struct dc *dc, struct pipe_ctx *pipe_ctx)
+{
+       struct mem_input *mi = pipe_ctx->plane_res.mi;
+       struct dc_plane_state *plane_state = pipe_ctx->plane_state;
+       struct xfm_grph_csc_adjustment adjust;
+       struct out_csc_color_matrix tbl_entry;
+       unsigned int i;
+       struct dce_hwseq *hws = dc->hwseq;
+
+       DC_LOGGER_INIT();
+       memset(&tbl_entry, 0, sizeof(tbl_entry));
+
+       memset(&adjust, 0, sizeof(adjust));
+       adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
+
+       dce_enable_fe_clock(dc->hwseq, mi->inst, true);
+
+       dce60_set_default_colors(pipe_ctx);
+       if (pipe_ctx->stream->csc_color_matrix.enable_adjustment
+                       == true) {
+               tbl_entry.color_space =
+                       pipe_ctx->stream->output_color_space;
+
+               for (i = 0; i < 12; i++)
+                       tbl_entry.regval[i] =
+                       pipe_ctx->stream->csc_color_matrix.matrix[i];
+
+               pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment
+                               (pipe_ctx->plane_res.xfm, &tbl_entry);
+       }
+
+       if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) {
+               adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
+
+               for (i = 0; i < CSC_TEMPERATURE_MATRIX_SIZE; i++)
+                       adjust.temperature_matrix[i] =
+                               pipe_ctx->stream->gamut_remap_matrix.matrix[i];
+       }
+
+       pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust);
+
+       pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0;
+
+       dce60_program_scaler(dc, pipe_ctx);
+
+       mi->funcs->mem_input_program_surface_config(
+                       mi,
+                       plane_state->format,
+                       &plane_state->tiling_info,
+                       &plane_state->plane_size,
+                       plane_state->rotation,
+                       NULL,
+                       false);
+       if (mi->funcs->set_blank)
+               mi->funcs->set_blank(mi, pipe_ctx->plane_state->visible);
+
+       if (dc->config.gpu_vm_support)
+               mi->funcs->mem_input_program_pte_vm(
+                               pipe_ctx->plane_res.mi,
+                               plane_state->format,
+                               &plane_state->tiling_info,
+                               plane_state->rotation);
+
+       /* Moved programming gamma from dc to hwss */
+       if (pipe_ctx->plane_state->update_flags.bits.full_update ||
+                       pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change ||
+                       pipe_ctx->plane_state->update_flags.bits.gamma_change)
+               hws->funcs.set_input_transfer_func(dc, pipe_ctx, pipe_ctx->plane_state);
+
+       if (pipe_ctx->plane_state->update_flags.bits.full_update)
+               hws->funcs.set_output_transfer_func(dc, pipe_ctx, pipe_ctx->stream);
+
+       DC_LOG_SURFACE(
+                       "Pipe:%d %p: addr hi:0x%x, "
+                       "addr low:0x%x, "
+                       "src: %d, %d, %d,"
+                       " %d; dst: %d, %d, %d, %d;"
+                       "clip: %d, %d, %d, %d\n",
+                       pipe_ctx->pipe_idx,
+                       (void *) pipe_ctx->plane_state,
+                       pipe_ctx->plane_state->address.grph.addr.high_part,
+                       pipe_ctx->plane_state->address.grph.addr.low_part,
+                       pipe_ctx->plane_state->src_rect.x,
+                       pipe_ctx->plane_state->src_rect.y,
+                       pipe_ctx->plane_state->src_rect.width,
+                       pipe_ctx->plane_state->src_rect.height,
+                       pipe_ctx->plane_state->dst_rect.x,
+                       pipe_ctx->plane_state->dst_rect.y,
+                       pipe_ctx->plane_state->dst_rect.width,
+                       pipe_ctx->plane_state->dst_rect.height,
+                       pipe_ctx->plane_state->clip_rect.x,
+                       pipe_ctx->plane_state->clip_rect.y,
+                       pipe_ctx->plane_state->clip_rect.width,
+                       pipe_ctx->plane_state->clip_rect.height);
+
+       DC_LOG_SURFACE(
+                       "Pipe %d: width, height, x, y\n"
+                       "viewport:%d, %d, %d, %d\n"
+                       "recout:  %d, %d, %d, %d\n",
+                       pipe_ctx->pipe_idx,
+                       pipe_ctx->plane_res.scl_data.viewport.width,
+                       pipe_ctx->plane_res.scl_data.viewport.height,
+                       pipe_ctx->plane_res.scl_data.viewport.x,
+                       pipe_ctx->plane_res.scl_data.viewport.y,
+                       pipe_ctx->plane_res.scl_data.recout.width,
+                       pipe_ctx->plane_res.scl_data.recout.height,
+                       pipe_ctx->plane_res.scl_data.recout.x,
+                       pipe_ctx->plane_res.scl_data.recout.y);
+}
+
+static void dce60_apply_ctx_for_surface(
+               struct dc *dc,
+               const struct dc_stream_state *stream,
+               int num_planes,
+               struct dc_state *context)
+{
+       int i;
+
+       if (num_planes == 0)
+               return;
+
+       if (dc->fbc_compressor)
+               dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor);
+
+       for (i = 0; i < dc->res_pool->pipe_count; i++) {
+               struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
+
+               if (pipe_ctx->stream != stream)
+                       continue;
+
+               /* Need to allocate mem before program front end for Fiji */
+               pipe_ctx->plane_res.mi->funcs->allocate_mem_input(
+                               pipe_ctx->plane_res.mi,
+                               pipe_ctx->stream->timing.h_total,
+                               pipe_ctx->stream->timing.v_total,
+                               pipe_ctx->stream->timing.pix_clk_100hz / 10,
+                               context->stream_count);
+
+               dce60_program_front_end_for_pipe(dc, pipe_ctx);
+
+               dc->hwss.update_plane_addr(dc, pipe_ctx);
+
+               dce60_program_surface_visibility(dc, pipe_ctx);
+
+       }
+
+       if (dc->fbc_compressor)
+               dce60_enable_fbc(dc, context);
+}
+
 void dce60_hw_sequencer_construct(struct dc *dc)
 {
        dce110_hw_sequencer_construct(dc);
 
        dc->hwseq->funcs.enable_display_power_gating = dce100_enable_display_power_gating;
-       dc->hwss.pipe_control_lock = dce_pipe_control_lock;
+       dc->hwss.apply_ctx_for_surface = dce60_apply_ctx_for_surface;
+       dc->hwss.pipe_control_lock = dce60_pipe_control_lock;
        dc->hwss.prepare_bandwidth = dce100_prepare_bandwidth;
        dc->hwss.optimize_bandwidth = dce100_optimize_bandwidth;
 }