drm/amd/display: move wm ranges reporting to end of init hw
[linux-2.6-microblaze.git] / drivers / gpu / drm / amd / display / dc / dcn10 / dcn10_hw_sequencer.c
index 285a793..eb91432 100644 (file)
@@ -670,6 +670,10 @@ static void dcn10_bios_golden_init(struct dc *dc)
        int i;
        bool allow_self_fresh_force_enable = true;
 
+#if defined(CONFIG_DRM_AMD_DC_DCN2_1)
+       if (dc->hwss.s0i3_golden_init_wa && dc->hwss.s0i3_golden_init_wa(dc))
+               return;
+#endif
        if (dc->res_pool->hubbub->funcs->is_allow_self_refresh_enabled)
                allow_self_fresh_force_enable =
                                dc->res_pool->hubbub->funcs->is_allow_self_refresh_enabled(dc->res_pool->hubbub);
@@ -721,7 +725,8 @@ static void false_optc_underflow_wa(
                dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, old_pipe_ctx);
        }
 
-       tg->funcs->set_blank_data_double_buffer(tg, true);
+       if (tg->funcs->set_blank_data_double_buffer)
+               tg->funcs->set_blank_data_double_buffer(tg, true);
 
        if (tg->funcs->is_optc_underflow_occurred(tg) && !underflow)
                tg->funcs->clear_optc_underflow(tg);
@@ -827,11 +832,23 @@ static void dcn10_reset_back_end_for_pipe(
        if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
                /* DPMS may already disable */
                if (!pipe_ctx->stream->dpms_off)
-                       core_link_disable_stream(pipe_ctx, FREE_ACQUIRED_RESOURCE);
-               else if (pipe_ctx->stream_res.audio) {
-                       dc->hwss.disable_audio_stream(pipe_ctx, FREE_ACQUIRED_RESOURCE);
+                       core_link_disable_stream(pipe_ctx);
+               else if (pipe_ctx->stream_res.audio)
+                       dc->hwss.disable_audio_stream(pipe_ctx);
+
+               if (pipe_ctx->stream_res.audio) {
+                       /*disable az_endpoint*/
+                       pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio);
+
+                       /*free audio*/
+                       if (dc->caps.dynamic_audio == true) {
+                               /*we have to dynamic arbitrate the audio endpoints*/
+                               /*we free the resource, need reset is_audio_acquired*/
+                               update_audio_usage(&dc->current_state->res_ctx, dc->res_pool,
+                                               pipe_ctx->stream_res.audio, false);
+                               pipe_ctx->stream_res.audio = NULL;
+                       }
                }
-
        }
 
        /* by upper caller loop, parent pipe: pipe0, will be reset last.
@@ -1098,9 +1115,16 @@ static void dcn10_init_pipes(struct dc *dc, struct dc_state *context)
                }
        }
 
-       /* Cannot reset the MPC mux if seamless boot */
-       if (!can_apply_seamless_boot)
-               dc->res_pool->mpc->funcs->mpc_init(dc->res_pool->mpc);
+       for (i = 0; i < dc->res_pool->pipe_count; i++) {
+               struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
+
+               /* Cannot reset the MPC mux if seamless boot */
+               if (pipe_ctx->stream != NULL && can_apply_seamless_boot)
+                       continue;
+
+               dc->res_pool->mpc->funcs->mpc_init_single_inst(
+                               dc->res_pool->mpc, i);
+       }
 
        for (i = 0; i < dc->res_pool->pipe_count; i++) {
                struct timing_generator *tg = dc->res_pool->timing_generators[i];
@@ -1189,34 +1213,34 @@ static void dcn10_init_hw(struct dc *dc)
                return;
        }
 
-       if (!dcb->funcs->is_accelerated_mode(dcb)) {
-               dc->hwss.bios_golden_init(dc);
-               if (dc->ctx->dc_bios->fw_info_valid) {
-                       res_pool->ref_clocks.xtalin_clock_inKhz =
-                                       dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency;
-
-                       if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
-                               if (res_pool->dccg && res_pool->hubbub) {
-
-                                       (res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg,
-                                                       dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency,
-                                                       &res_pool->ref_clocks.dccg_ref_clock_inKhz);
-
-                                       (res_pool->hubbub->funcs->get_dchub_ref_freq)(res_pool->hubbub,
-                                                       res_pool->ref_clocks.dccg_ref_clock_inKhz,
-                                                       &res_pool->ref_clocks.dchub_ref_clock_inKhz);
-                               } else {
-                                       // Not all ASICs have DCCG sw component
-                                       res_pool->ref_clocks.dccg_ref_clock_inKhz =
-                                                       res_pool->ref_clocks.xtalin_clock_inKhz;
-                                       res_pool->ref_clocks.dchub_ref_clock_inKhz =
-                                                       res_pool->ref_clocks.xtalin_clock_inKhz;
-                               }
-                       }
-               } else
-                       ASSERT_CRITICAL(false);
+       if (!dcb->funcs->is_accelerated_mode(dcb))
                dc->hwss.disable_vga(dc->hwseq);
-       }
+
+       dc->hwss.bios_golden_init(dc);
+       if (dc->ctx->dc_bios->fw_info_valid) {
+               res_pool->ref_clocks.xtalin_clock_inKhz =
+                               dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency;
+
+               if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
+                       if (res_pool->dccg && res_pool->hubbub) {
+
+                               (res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg,
+                                               dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency,
+                                               &res_pool->ref_clocks.dccg_ref_clock_inKhz);
+
+                               (res_pool->hubbub->funcs->get_dchub_ref_freq)(res_pool->hubbub,
+                                               res_pool->ref_clocks.dccg_ref_clock_inKhz,
+                                               &res_pool->ref_clocks.dchub_ref_clock_inKhz);
+                       } else {
+                               // Not all ASICs have DCCG sw component
+                               res_pool->ref_clocks.dccg_ref_clock_inKhz =
+                                               res_pool->ref_clocks.xtalin_clock_inKhz;
+                               res_pool->ref_clocks.dchub_ref_clock_inKhz =
+                                               res_pool->ref_clocks.xtalin_clock_inKhz;
+                       }
+               }
+       } else
+               ASSERT_CRITICAL(false);
 
        for (i = 0; i < dc->link_count; i++) {
                /* Power up AND update implementation according to the
@@ -1248,19 +1272,8 @@ static void dcn10_init_hw(struct dc *dc)
         */
        if (dcb->funcs->is_accelerated_mode(dcb) || dc->config.power_down_display_on_boot) {
                dc->hwss.init_pipes(dc, dc->current_state);
-               for (i = 0; i < res_pool->pipe_count; i++) {
-                       struct hubp *hubp = res_pool->hubps[i];
-                       struct dpp *dpp = res_pool->dpps[i];
-
-                       hubp->funcs->hubp_init(hubp);
-                       res_pool->opps[i]->mpc_tree_params.opp_id = res_pool->opps[i]->inst;
-                       dc->hwss.plane_atomic_power_down(dc, dpp, hubp);
-               }
-
-               apply_DEGVIDCN10_253_wa(dc);
        }
 
-
        for (i = 0; i < res_pool->audio_count; i++) {
                struct audio *audio = res_pool->audios[i];
 
@@ -1291,6 +1304,10 @@ static void dcn10_init_hw(struct dc *dc)
        }
 
        dc->hwss.enable_power_gating_plane(dc->hwseq, true);
+
+       if (dc->clk_mgr->funcs->notify_wm_ranges)
+               dc->clk_mgr->funcs->notify_wm_ranges(dc->clk_mgr);
+
 }
 
 static void dcn10_reset_hw_ctx_wrap(
@@ -1427,6 +1444,34 @@ static bool dcn10_set_input_transfer_func(struct pipe_ctx *pipe_ctx,
        return result;
 }
 
+#define MAX_NUM_HW_POINTS 0x200
+
+static void log_tf(struct dc_context *ctx,
+                               struct dc_transfer_func *tf, uint32_t hw_points_num)
+{
+       // DC_LOG_GAMMA is default logging of all hw points
+       // DC_LOG_ALL_GAMMA logs all points, not only hw points
+       // DC_LOG_ALL_TF_POINTS logs all channels of the tf
+       int i = 0;
+
+       DC_LOGGER_INIT(ctx->logger);
+       DC_LOG_GAMMA("Gamma Correction TF");
+       DC_LOG_ALL_GAMMA("Logging all tf points...");
+       DC_LOG_ALL_TF_CHANNELS("Logging all channels...");
+
+       for (i = 0; i < hw_points_num; i++) {
+               DC_LOG_GAMMA("R\t%d\t%llu", i, tf->tf_pts.red[i].value);
+               DC_LOG_ALL_TF_CHANNELS("G\t%d\t%llu", i, tf->tf_pts.green[i].value);
+               DC_LOG_ALL_TF_CHANNELS("B\t%d\t%llu", i, tf->tf_pts.blue[i].value);
+       }
+
+       for (i = hw_points_num; i < MAX_NUM_HW_POINTS; i++) {
+               DC_LOG_ALL_GAMMA("R\t%d\t%llu", i, tf->tf_pts.red[i].value);
+               DC_LOG_ALL_TF_CHANNELS("G\t%d\t%llu", i, tf->tf_pts.green[i].value);
+               DC_LOG_ALL_TF_CHANNELS("B\t%d\t%llu", i, tf->tf_pts.blue[i].value);
+       }
+}
+
 static bool
 dcn10_set_output_transfer_func(struct pipe_ctx *pipe_ctx,
                               const struct dc_stream_state *stream)
@@ -1455,6 +1500,13 @@ dcn10_set_output_transfer_func(struct pipe_ctx *pipe_ctx,
        } else
                dpp->funcs->dpp_program_regamma_pwl(dpp, NULL, OPP_REGAMMA_BYPASS);
 
+       if (stream != NULL && stream->ctx != NULL &&
+                       stream->out_transfer_func != NULL) {
+               log_tf(stream->ctx,
+                               stream->out_transfer_func,
+                               dpp->regamma_params.hw_points_num);
+       }
+
        return true;
 }
 
@@ -1865,6 +1917,36 @@ static void dcn10_program_gamut_remap(struct pipe_ctx *pipe_ctx)
        pipe_ctx->plane_res.dpp->funcs->dpp_set_gamut_remap(pipe_ctx->plane_res.dpp, &adjust);
 }
 
+
+static bool dcn10_is_rear_mpo_fix_required(struct pipe_ctx *pipe_ctx, enum dc_color_space colorspace)
+{
+       if (pipe_ctx->plane_state && pipe_ctx->plane_state->layer_index > 0 && is_rgb_cspace(colorspace)) {
+               if (pipe_ctx->top_pipe) {
+                       struct pipe_ctx *top = pipe_ctx->top_pipe;
+
+                       while (top->top_pipe)
+                               top = top->top_pipe; // Traverse to top pipe_ctx
+                       if (top->plane_state && top->plane_state->layer_index == 0)
+                               return true; // Front MPO plane not hidden
+               }
+       }
+       return false;
+}
+
+static void dcn10_set_csc_adjustment_rgb_mpo_fix(struct pipe_ctx *pipe_ctx, uint16_t *matrix)
+{
+       // Override rear plane RGB bias to fix MPO brightness
+       uint16_t rgb_bias = matrix[3];
+
+       matrix[3] = 0;
+       matrix[7] = 0;
+       matrix[11] = 0;
+       pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment(pipe_ctx->plane_res.dpp, matrix);
+       matrix[3] = rgb_bias;
+       matrix[7] = rgb_bias;
+       matrix[11] = rgb_bias;
+}
+
 static void dcn10_program_output_csc(struct dc *dc,
                struct pipe_ctx *pipe_ctx,
                enum dc_color_space colorspace,
@@ -1872,8 +1954,25 @@ static void dcn10_program_output_csc(struct dc *dc,
                int opp_id)
 {
        if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) {
-               if (pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment != NULL)
-                       pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment(pipe_ctx->plane_res.dpp, matrix);
+               if (pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment != NULL) {
+
+                       /* MPO is broken with RGB colorspaces when OCSC matrix
+                        * brightness offset >= 0 on DCN1 due to OCSC before MPC
+                        * Blending adds offsets from front + rear to rear plane
+                        *
+                        * Fix is to set RGB bias to 0 on rear plane, top plane
+                        * black value pixels add offset instead of rear + front
+                        */
+
+                       int16_t rgb_bias = matrix[3];
+                       // matrix[3/7/11] are all the same offset value
+
+                       if (rgb_bias > 0 && dcn10_is_rear_mpo_fix_required(pipe_ctx, colorspace)) {
+                               dcn10_set_csc_adjustment_rgb_mpo_fix(pipe_ctx, matrix);
+                       } else {
+                               pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment(pipe_ctx->plane_res.dpp, matrix);
+                       }
+               }
        } else {
                if (pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_default != NULL)
                        pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_default(pipe_ctx->plane_res.dpp, colorspace);
@@ -2213,8 +2312,7 @@ void update_dchubp_dpp(
                        dc->res_pool->dccg->funcs->update_dpp_dto(
                                        dc->res_pool->dccg,
                                        dpp->inst,
-                                       pipe_ctx->plane_res.bw.dppclk_khz,
-                                       false);
+                                       pipe_ctx->plane_res.bw.dppclk_khz);
                else
                        dc->clk_mgr->clks.dppclk_khz = should_divided_by_2 ?
                                                dc->clk_mgr->clks.dispclk_khz / 2 :
@@ -2421,8 +2519,10 @@ static void program_all_pipe_in_tree(
                pipe_ctx->stream_res.tg->funcs->set_vtg_params(
                                pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
 
-               dc->hwss.blank_pixel_data(dc, pipe_ctx, blank);
+               if (dc->hwss.setup_vupdate_interrupt)
+                       dc->hwss.setup_vupdate_interrupt(pipe_ctx);
 
+               dc->hwss.blank_pixel_data(dc, pipe_ctx, blank);
        }
 
        if (pipe_ctx->plane_state != NULL)
@@ -2450,7 +2550,7 @@ struct pipe_ctx *find_top_pipe_for_stream(
                if (pipe_ctx->stream != stream)
                        continue;
 
-               if (!pipe_ctx->top_pipe)
+               if (!pipe_ctx->top_pipe && !pipe_ctx->prev_odm_pipe)
                        return pipe_ctx;
        }
        return NULL;
@@ -2656,7 +2756,8 @@ static void dcn10_optimize_bandwidth(
 }
 
 static void dcn10_set_drr(struct pipe_ctx **pipe_ctx,
-               int num_pipes, int vmin, int vmax)
+               int num_pipes, unsigned int vmin, unsigned int vmax,
+               unsigned int vmid, unsigned int vmid_frame_number)
 {
        int i = 0;
        struct drr_params params = {0};
@@ -2665,6 +2766,8 @@ static void dcn10_set_drr(struct pipe_ctx **pipe_ctx,
 
        params.vertical_total_max = vmax;
        params.vertical_total_min = vmin;
+       params.vertical_total_mid = vmid;
+       params.vertical_total_mid_frame_num = vmid_frame_number;
 
        /* TODO: If multiple pipes are to be supported, you need
         * some GSL stuff. Static screen triggers may be programmed differently
@@ -2851,14 +2954,10 @@ static void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx)
 
 static void dcn10_update_dchub(struct dce_hwseq *hws, struct dchub_init_data *dh_data)
 {
-       if (hws->ctx->dc->res_pool->hubbub != NULL) {
-               struct hubp *hubp = hws->ctx->dc->res_pool->hubps[0];
+       struct hubbub *hubbub = hws->ctx->dc->res_pool->hubbub;
 
-               if (hubp->funcs->hubp_update_dchub)
-                       hubp->funcs->hubp_update_dchub(hubp, dh_data);
-               else
-                       hubbub1_update_dchub(hws->ctx->dc->res_pool->hubbub, dh_data);
-       }
+       /* In DCN, this programming sequence is owned by the hubbub */
+       hubbub->funcs->update_dchub(hubbub, dh_data);
 }
 
 static void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx)
@@ -2889,6 +2988,40 @@ static void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx)
                        == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE)
                pos_cpy.enable = false;
 
+       // Swap axis and mirror horizontally
+       if (param.rotation == ROTATION_ANGLE_90) {
+               uint32_t temp_x = pos_cpy.x;
+               pos_cpy.x = pipe_ctx->plane_res.scl_data.viewport.width -
+                               (pos_cpy.y - pipe_ctx->plane_res.scl_data.viewport.x) + pipe_ctx->plane_res.scl_data.viewport.x;
+               pos_cpy.y = temp_x;
+       }
+       // Swap axis and mirror vertically
+       else if (param.rotation == ROTATION_ANGLE_270) {
+               uint32_t temp_y = pos_cpy.y;
+               if (pos_cpy.x >  pipe_ctx->plane_res.scl_data.viewport.height) {
+                       pos_cpy.x = pos_cpy.x - pipe_ctx->plane_res.scl_data.viewport.height;
+                       pos_cpy.y = pipe_ctx->plane_res.scl_data.viewport.height - pos_cpy.x;
+               } else {
+                       pos_cpy.y = 2 * pipe_ctx->plane_res.scl_data.viewport.height - pos_cpy.x;
+               }
+               pos_cpy.x = temp_y;
+       }
+       // Mirror horizontally and vertically
+       else if (param.rotation == ROTATION_ANGLE_180) {
+               if (pos_cpy.x >= pipe_ctx->plane_res.scl_data.viewport.width + pipe_ctx->plane_res.scl_data.viewport.x) {
+                       pos_cpy.x = 2 * pipe_ctx->plane_res.scl_data.viewport.width
+                                       - pos_cpy.x + 2 * pipe_ctx->plane_res.scl_data.viewport.x;
+               } else {
+                       uint32_t temp_x = pos_cpy.x;
+                       pos_cpy.x = 2 * pipe_ctx->plane_res.scl_data.viewport.x - pos_cpy.x;
+                       if (temp_x >= pipe_ctx->plane_res.scl_data.viewport.x + (int)hubp->curs_attr.width
+                                       || pos_cpy.x <= (int)hubp->curs_attr.width + pipe_ctx->plane_state->src_rect.x) {
+                               pos_cpy.x = temp_x + pipe_ctx->plane_res.scl_data.viewport.width;
+                       }
+               }
+               pos_cpy.y = pipe_ctx->plane_res.scl_data.viewport.height - pos_cpy.y;
+       }
+
        hubp->funcs->set_cursor_position(hubp, &pos_cpy, &param);
        dpp->funcs->set_cursor_position(dpp, &pos_cpy, &param, hubp->curs_attr.width, hubp->curs_attr.height);
 }
@@ -2900,7 +3033,7 @@ static void dcn10_set_cursor_attribute(struct pipe_ctx *pipe_ctx)
        pipe_ctx->plane_res.hubp->funcs->set_cursor_attributes(
                        pipe_ctx->plane_res.hubp, attributes);
        pipe_ctx->plane_res.dpp->funcs->set_cursor_attributes(
-               pipe_ctx->plane_res.dpp, attributes->color_format);
+               pipe_ctx->plane_res.dpp, attributes);
 }
 
 static void dcn10_set_cursor_sdr_white_level(struct pipe_ctx *pipe_ctx)