Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2020 Mauro Rossi <issor.oruam@gmail.com>
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 #include "dm_services.h"
0027 #include "dc.h"
0028 #include "core_types.h"
0029 #include "dce60_hw_sequencer.h"
0030 
0031 #include "dce/dce_hwseq.h"
0032 #include "dce110/dce110_hw_sequencer.h"
0033 #include "dce100/dce100_hw_sequencer.h"
0034 
0035 /* include DCE6 register header files */
0036 #include "dce/dce_6_0_d.h"
0037 #include "dce/dce_6_0_sh_mask.h"
0038 
0039 #define DC_LOGGER_INIT()
0040 
0041 /*******************************************************************************
0042  * Private definitions
0043  ******************************************************************************/
0044 
0045 /***************************PIPE_CONTROL***********************************/
0046 
0047 /*
0048  *  Check if FBC can be enabled
0049  */
0050 static bool dce60_should_enable_fbc(struct dc *dc,
0051         struct dc_state *context,
0052         uint32_t *pipe_idx)
0053 {
0054     uint32_t i;
0055     struct pipe_ctx *pipe_ctx = NULL;
0056     struct resource_context *res_ctx = &context->res_ctx;
0057     unsigned int underlay_idx = dc->res_pool->underlay_pipe_index;
0058 
0059 
0060     ASSERT(dc->fbc_compressor);
0061 
0062     /* FBC memory should be allocated */
0063     if (!dc->ctx->fbc_gpu_addr)
0064         return false;
0065 
0066     /* Only supports single display */
0067     if (context->stream_count != 1)
0068         return false;
0069 
0070     for (i = 0; i < dc->res_pool->pipe_count; i++) {
0071         if (res_ctx->pipe_ctx[i].stream) {
0072 
0073             pipe_ctx = &res_ctx->pipe_ctx[i];
0074 
0075             if (!pipe_ctx)
0076                 continue;
0077 
0078             /* fbc not applicable on underlay pipe */
0079             if (pipe_ctx->pipe_idx != underlay_idx) {
0080                 *pipe_idx = i;
0081                 break;
0082             }
0083         }
0084     }
0085 
0086     if (i == dc->res_pool->pipe_count)
0087         return false;
0088 
0089     if (!pipe_ctx->stream->link)
0090         return false;
0091 
0092     /* Only supports eDP */
0093     if (pipe_ctx->stream->link->connector_signal != SIGNAL_TYPE_EDP)
0094         return false;
0095 
0096     /* PSR should not be enabled */
0097     if (pipe_ctx->stream->link->psr_settings.psr_feature_enabled)
0098         return false;
0099 
0100     /* Nothing to compress */
0101     if (!pipe_ctx->plane_state)
0102         return false;
0103 
0104     /* Only for non-linear tiling */
0105     if (pipe_ctx->plane_state->tiling_info.gfx8.array_mode == DC_ARRAY_LINEAR_GENERAL)
0106         return false;
0107 
0108     return true;
0109 }
0110 
0111 /*
0112  *  Enable FBC
0113  */
0114 static void dce60_enable_fbc(
0115         struct dc *dc,
0116         struct dc_state *context)
0117 {
0118     uint32_t pipe_idx = 0;
0119 
0120     if (dce60_should_enable_fbc(dc, context, &pipe_idx)) {
0121         /* Program GRPH COMPRESSED ADDRESS and PITCH */
0122         struct compr_addr_and_pitch_params params = {0, 0, 0};
0123         struct compressor *compr = dc->fbc_compressor;
0124         struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx];
0125 
0126         params.source_view_width = pipe_ctx->stream->timing.h_addressable;
0127         params.source_view_height = pipe_ctx->stream->timing.v_addressable;
0128         params.inst = pipe_ctx->stream_res.tg->inst;
0129         compr->compr_surface_address.quad_part = dc->ctx->fbc_gpu_addr;
0130 
0131         compr->funcs->surface_address_and_pitch(compr, &params);
0132         compr->funcs->set_fbc_invalidation_triggers(compr, 1);
0133 
0134         compr->funcs->enable_fbc(compr, &params);
0135     }
0136 }
0137 
0138 
0139 /*******************************************************************************
0140  * Front End programming
0141  ******************************************************************************/
0142 
0143 static void dce60_set_default_colors(struct pipe_ctx *pipe_ctx)
0144 {
0145     struct default_adjustment default_adjust = { 0 };
0146 
0147     default_adjust.force_hw_default = false;
0148     default_adjust.in_color_space = pipe_ctx->plane_state->color_space;
0149     default_adjust.out_color_space = pipe_ctx->stream->output_color_space;
0150     default_adjust.csc_adjust_type = GRAPHICS_CSC_ADJUST_TYPE_SW;
0151     default_adjust.surface_pixel_format = pipe_ctx->plane_res.scl_data.format;
0152 
0153     /* display color depth */
0154     default_adjust.color_depth =
0155         pipe_ctx->stream->timing.display_color_depth;
0156 
0157     /* Lb color depth */
0158     default_adjust.lb_color_depth = pipe_ctx->plane_res.scl_data.lb_params.depth;
0159 
0160     pipe_ctx->plane_res.xfm->funcs->opp_set_csc_default(
0161                     pipe_ctx->plane_res.xfm, &default_adjust);
0162 }
0163 
0164 /*******************************************************************************
0165  * In order to turn on surface we will program
0166  * CRTC
0167  *
0168  * DCE6 has no bottom_pipe and no Blender HW
0169  * We need to set 'blank_target' to false in order to turn on the display
0170  *
0171  * |-----------|------------|---------|
0172  * |curr pipe  | set_blank  |         |
0173  * |Surface    |blank_target|  CRCT   |
0174  * |visibility |  argument  |         |
0175  * |-----------|------------|---------|
0176  * |    off    |   true     | blank   |
0177  * |    on     |   false    | unblank |
0178  * |-----------|------------|---------|
0179  *
0180  ******************************************************************************/
0181 static void dce60_program_surface_visibility(const struct dc *dc,
0182         struct pipe_ctx *pipe_ctx)
0183 {
0184     bool blank_target = false;
0185 
0186     /* DCE6 has no bottom_pipe and no Blender HW */
0187 
0188     if (!pipe_ctx->plane_state->visible)
0189         blank_target = true;
0190 
0191     /* DCE6 skip dce_set_blender_mode() but then proceed to 'unblank' CRTC */
0192     pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, blank_target);
0193 
0194 }
0195 
0196 
0197 static void dce60_get_surface_visual_confirm_color(const struct pipe_ctx *pipe_ctx,
0198         struct tg_color *color)
0199 {
0200     uint32_t color_value = MAX_TG_COLOR_VALUE * (4 - pipe_ctx->stream_res.tg->inst) / 4;
0201 
0202     switch (pipe_ctx->plane_res.scl_data.format) {
0203     case PIXEL_FORMAT_ARGB8888:
0204         /* set boarder color to red */
0205         color->color_r_cr = color_value;
0206         break;
0207 
0208     case PIXEL_FORMAT_ARGB2101010:
0209         /* set boarder color to blue */
0210         color->color_b_cb = color_value;
0211         break;
0212     case PIXEL_FORMAT_420BPP8:
0213         /* set boarder color to green */
0214         color->color_g_y = color_value;
0215         break;
0216     case PIXEL_FORMAT_420BPP10:
0217         /* set boarder color to yellow */
0218         color->color_g_y = color_value;
0219         color->color_r_cr = color_value;
0220         break;
0221     case PIXEL_FORMAT_FP16:
0222         /* set boarder color to white */
0223         color->color_r_cr = color_value;
0224         color->color_b_cb = color_value;
0225         color->color_g_y = color_value;
0226         break;
0227     default:
0228         break;
0229     }
0230 }
0231 
0232 static void dce60_program_scaler(const struct dc *dc,
0233         const struct pipe_ctx *pipe_ctx)
0234 {
0235     struct tg_color color = {0};
0236 
0237     /* DCE6 skips DCN TOFPGA check for transform_set_pixel_storage_depth == NULL */
0238 
0239     if (dc->debug.visual_confirm == VISUAL_CONFIRM_SURFACE)
0240         dce60_get_surface_visual_confirm_color(pipe_ctx, &color);
0241     else
0242         color_space_to_black_color(dc,
0243                 pipe_ctx->stream->output_color_space,
0244                 &color);
0245 
0246     pipe_ctx->plane_res.xfm->funcs->transform_set_pixel_storage_depth(
0247         pipe_ctx->plane_res.xfm,
0248         pipe_ctx->plane_res.scl_data.lb_params.depth,
0249         &pipe_ctx->stream->bit_depth_params);
0250 
0251     if (pipe_ctx->stream_res.tg->funcs->set_overscan_blank_color) {
0252         /*
0253          * The way 420 is packed, 2 channels carry Y component, 1 channel
0254          * alternate between Cb and Cr, so both channels need the pixel
0255          * value for Y
0256          */
0257         if (pipe_ctx->stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420)
0258             color.color_r_cr = color.color_g_y;
0259 
0260         pipe_ctx->stream_res.tg->funcs->set_overscan_blank_color(
0261                 pipe_ctx->stream_res.tg,
0262                 &color);
0263     }
0264 
0265     pipe_ctx->plane_res.xfm->funcs->transform_set_scaler(pipe_ctx->plane_res.xfm,
0266         &pipe_ctx->plane_res.scl_data);
0267 }
0268 
0269 static void
0270 dce60_program_front_end_for_pipe(
0271         struct dc *dc, struct pipe_ctx *pipe_ctx)
0272 {
0273     struct mem_input *mi = pipe_ctx->plane_res.mi;
0274     struct dc_plane_state *plane_state = pipe_ctx->plane_state;
0275     struct xfm_grph_csc_adjustment adjust;
0276     struct out_csc_color_matrix tbl_entry;
0277     unsigned int i;
0278     struct dce_hwseq *hws = dc->hwseq;
0279 
0280     DC_LOGGER_INIT();
0281     memset(&tbl_entry, 0, sizeof(tbl_entry));
0282 
0283     memset(&adjust, 0, sizeof(adjust));
0284     adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
0285 
0286     dce_enable_fe_clock(dc->hwseq, mi->inst, true);
0287 
0288     dce60_set_default_colors(pipe_ctx);
0289     if (pipe_ctx->stream->csc_color_matrix.enable_adjustment
0290             == true) {
0291         tbl_entry.color_space =
0292             pipe_ctx->stream->output_color_space;
0293 
0294         for (i = 0; i < 12; i++)
0295             tbl_entry.regval[i] =
0296             pipe_ctx->stream->csc_color_matrix.matrix[i];
0297 
0298         pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment
0299                 (pipe_ctx->plane_res.xfm, &tbl_entry);
0300     }
0301 
0302     if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) {
0303         adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
0304 
0305         for (i = 0; i < CSC_TEMPERATURE_MATRIX_SIZE; i++)
0306             adjust.temperature_matrix[i] =
0307                 pipe_ctx->stream->gamut_remap_matrix.matrix[i];
0308     }
0309 
0310     pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust);
0311 
0312     pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0;
0313 
0314     dce60_program_scaler(dc, pipe_ctx);
0315 
0316     mi->funcs->mem_input_program_surface_config(
0317             mi,
0318             plane_state->format,
0319             &plane_state->tiling_info,
0320             &plane_state->plane_size,
0321             plane_state->rotation,
0322             NULL,
0323             false);
0324     if (mi->funcs->set_blank)
0325         mi->funcs->set_blank(mi, pipe_ctx->plane_state->visible);
0326 
0327     if (dc->config.gpu_vm_support)
0328         mi->funcs->mem_input_program_pte_vm(
0329                 pipe_ctx->plane_res.mi,
0330                 plane_state->format,
0331                 &plane_state->tiling_info,
0332                 plane_state->rotation);
0333 
0334     /* Moved programming gamma from dc to hwss */
0335     if (pipe_ctx->plane_state->update_flags.bits.full_update ||
0336             pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change ||
0337             pipe_ctx->plane_state->update_flags.bits.gamma_change)
0338         hws->funcs.set_input_transfer_func(dc, pipe_ctx, pipe_ctx->plane_state);
0339 
0340     if (pipe_ctx->plane_state->update_flags.bits.full_update)
0341         hws->funcs.set_output_transfer_func(dc, pipe_ctx, pipe_ctx->stream);
0342 
0343     DC_LOG_SURFACE(
0344             "Pipe:%d %p: addr hi:0x%x, "
0345             "addr low:0x%x, "
0346             "src: %d, %d, %d,"
0347             " %d; dst: %d, %d, %d, %d;"
0348             "clip: %d, %d, %d, %d\n",
0349             pipe_ctx->pipe_idx,
0350             (void *) pipe_ctx->plane_state,
0351             pipe_ctx->plane_state->address.grph.addr.high_part,
0352             pipe_ctx->plane_state->address.grph.addr.low_part,
0353             pipe_ctx->plane_state->src_rect.x,
0354             pipe_ctx->plane_state->src_rect.y,
0355             pipe_ctx->plane_state->src_rect.width,
0356             pipe_ctx->plane_state->src_rect.height,
0357             pipe_ctx->plane_state->dst_rect.x,
0358             pipe_ctx->plane_state->dst_rect.y,
0359             pipe_ctx->plane_state->dst_rect.width,
0360             pipe_ctx->plane_state->dst_rect.height,
0361             pipe_ctx->plane_state->clip_rect.x,
0362             pipe_ctx->plane_state->clip_rect.y,
0363             pipe_ctx->plane_state->clip_rect.width,
0364             pipe_ctx->plane_state->clip_rect.height);
0365 
0366     DC_LOG_SURFACE(
0367             "Pipe %d: width, height, x, y\n"
0368             "viewport:%d, %d, %d, %d\n"
0369             "recout:  %d, %d, %d, %d\n",
0370             pipe_ctx->pipe_idx,
0371             pipe_ctx->plane_res.scl_data.viewport.width,
0372             pipe_ctx->plane_res.scl_data.viewport.height,
0373             pipe_ctx->plane_res.scl_data.viewport.x,
0374             pipe_ctx->plane_res.scl_data.viewport.y,
0375             pipe_ctx->plane_res.scl_data.recout.width,
0376             pipe_ctx->plane_res.scl_data.recout.height,
0377             pipe_ctx->plane_res.scl_data.recout.x,
0378             pipe_ctx->plane_res.scl_data.recout.y);
0379 }
0380 
0381 static void dce60_apply_ctx_for_surface(
0382         struct dc *dc,
0383         const struct dc_stream_state *stream,
0384         int num_planes,
0385         struct dc_state *context)
0386 {
0387     int i;
0388 
0389     if (num_planes == 0)
0390         return;
0391 
0392     if (dc->fbc_compressor)
0393         dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor);
0394 
0395     for (i = 0; i < dc->res_pool->pipe_count; i++) {
0396         struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
0397 
0398         if (pipe_ctx->stream != stream)
0399             continue;
0400 
0401         /* Need to allocate mem before program front end for Fiji */
0402         pipe_ctx->plane_res.mi->funcs->allocate_mem_input(
0403                 pipe_ctx->plane_res.mi,
0404                 pipe_ctx->stream->timing.h_total,
0405                 pipe_ctx->stream->timing.v_total,
0406                 pipe_ctx->stream->timing.pix_clk_100hz / 10,
0407                 context->stream_count);
0408 
0409         dce60_program_front_end_for_pipe(dc, pipe_ctx);
0410 
0411         dc->hwss.update_plane_addr(dc, pipe_ctx);
0412 
0413         dce60_program_surface_visibility(dc, pipe_ctx);
0414 
0415     }
0416 
0417     if (dc->fbc_compressor)
0418         dce60_enable_fbc(dc, context);
0419 }
0420 
0421 void dce60_hw_sequencer_construct(struct dc *dc)
0422 {
0423     dce110_hw_sequencer_construct(dc);
0424 
0425     dc->hwseq->funcs.enable_display_power_gating = dce100_enable_display_power_gating;
0426     dc->hwss.apply_ctx_for_surface = dce60_apply_ctx_for_surface;
0427     dc->hwss.cursor_lock = dce60_pipe_control_lock;
0428     dc->hwss.pipe_control_lock = dce60_pipe_control_lock;
0429     dc->hwss.prepare_bandwidth = dce100_prepare_bandwidth;
0430     dc->hwss.optimize_bandwidth = dce100_optimize_bandwidth;
0431 }
0432