summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c')
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c568
1 files changed, 155 insertions, 413 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
index 8e2ddbc2129c..82572863acab 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
@@ -32,7 +32,7 @@
#include "dce/dce_hwseq.h"
#include "abm.h"
#include "dmcu.h"
-#include "dcn10/dcn10_timing_generator.h"
+#include "dcn10_optc.h"
#include "dcn10/dcn10_dpp.h"
#include "dcn10/dcn10_mpc.h"
#include "timing_generator.h"
@@ -43,6 +43,7 @@
#include "custom_float.h"
#include "dcn10_hubp.h"
#include "dcn10_hubbub.h"
+#include "dcn10_cm_common.h"
#define CTX \
hws->ctx
@@ -158,7 +159,7 @@ void dcn10_log_hw_state(struct dc *dc)
struct timing_generator *tg = pool->timing_generators[i];
struct dcn_otg_state s = {0};
- tgn10_read_otg_state(DCN10TG_FROM_TG(tg), &s);
+ optc1_read_otg_state(DCN10TG_FROM_TG(tg), &s);
//only print if OTG master is enabled
if ((s.otg_enabled & 1) == 0)
@@ -425,6 +426,34 @@ static void bios_golden_init(struct dc *dc)
}
}
+static void false_optc_underflow_wa(
+ struct dc *dc,
+ const struct dc_stream_state *stream,
+ struct timing_generator *tg)
+{
+ int i;
+ bool underflow;
+
+ if (!dc->hwseq->wa.false_optc_underflow)
+ return;
+
+ underflow = tg->funcs->is_optc_underflow_occurred(tg);
+
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
+
+ if (old_pipe_ctx->stream != stream)
+ continue;
+
+ 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->is_optc_underflow_occurred(tg) && !underflow)
+ tg->funcs->clear_optc_underflow(tg);
+}
+
static enum dc_status dcn10_prog_pixclk_crtc_otg(
struct pipe_ctx *pipe_ctx,
struct dc_state *context,
@@ -433,9 +462,6 @@ static enum dc_status dcn10_prog_pixclk_crtc_otg(
struct dc_stream_state *stream = pipe_ctx->stream;
enum dc_color_space color_space;
struct tg_color black_color = {0};
- bool enableStereo = stream->timing.timing_3d_format == TIMING_3D_FORMAT_NONE ?
- false:true;
- bool rightEyePolarity = stream->timing.flags.RIGHT_EYE_3D_POLARITY;
/* by upper caller loop, pipe0 is parent pipe and be called first.
* back end is set up by for pipe0. Other children pipe share back end
@@ -470,11 +496,6 @@ static enum dc_status dcn10_prog_pixclk_crtc_otg(
&stream->timing,
true);
- pipe_ctx->stream_res.opp->funcs->opp_set_stereo_polarity(
- pipe_ctx->stream_res.opp,
- enableStereo,
- rightEyePolarity);
-
#if 0 /* move to after enable_crtc */
/* TODO: OPP FMT, ABM. etc. should be done here. */
/* or FPGA now. instance 0 only. TODO: move to opp.c */
@@ -489,12 +510,18 @@ static enum dc_status dcn10_prog_pixclk_crtc_otg(
/* program otg blank color */
color_space = stream->output_color_space;
color_space_to_black_color(dc, color_space, &black_color);
- pipe_ctx->stream_res.tg->funcs->set_blank_color(
- pipe_ctx->stream_res.tg,
- &black_color);
- pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, true);
- hwss_wait_for_blank_complete(pipe_ctx->stream_res.tg);
+ if (pipe_ctx->stream_res.tg->funcs->set_blank_color)
+ pipe_ctx->stream_res.tg->funcs->set_blank_color(
+ pipe_ctx->stream_res.tg,
+ &black_color);
+
+ if (pipe_ctx->stream_res.tg->funcs->is_blanked &&
+ !pipe_ctx->stream_res.tg->funcs->is_blanked(pipe_ctx->stream_res.tg)) {
+ pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, true);
+ hwss_wait_for_blank_complete(pipe_ctx->stream_res.tg);
+ false_optc_underflow_wa(dc, pipe_ctx->stream, pipe_ctx->stream_res.tg);
+ }
/* VTG is within DCHUB command block. DCFCLK is always on */
if (false == pipe_ctx->stream_res.tg->funcs->enable_crtc(pipe_ctx->stream_res.tg)) {
@@ -573,41 +600,34 @@ static void plane_atomic_disconnect(struct dc *dc, struct pipe_ctx *pipe_ctx)
int fe_idx = pipe_ctx->pipe_idx;
struct hubp *hubp = dc->res_pool->hubps[fe_idx];
struct mpc *mpc = dc->res_pool->mpc;
- int opp_id, z_idx;
- int mpcc_id = -1;
+ int opp_id;
+ struct mpc_tree *mpc_tree_params;
+ struct mpcc *mpcc_to_remove = NULL;
/* look at tree rather than mi here to know if we already reset */
for (opp_id = 0; opp_id < dc->res_pool->pipe_count; opp_id++) {
struct output_pixel_processor *opp = dc->res_pool->opps[opp_id];
- for (z_idx = 0; z_idx < opp->mpc_tree.num_pipes; z_idx++) {
- if (opp->mpc_tree.dpp[z_idx] == fe_idx) {
- mpcc_id = opp->mpc_tree.mpcc[z_idx];
- break;
- }
- }
- if (mpcc_id != -1)
+ mpc_tree_params = &(opp->mpc_tree_params);
+ mpcc_to_remove = mpc->funcs->get_mpcc_for_dpp(mpc_tree_params, fe_idx);
+ if (mpcc_to_remove != NULL)
break;
}
+
/*Already reset*/
if (opp_id == dc->res_pool->pipe_count)
return;
- mpc->funcs->remove(mpc, &(dc->res_pool->opps[opp_id]->mpc_tree),
- dc->res_pool->opps[opp_id]->inst, fe_idx);
+ mpc->funcs->remove_mpcc(mpc, mpc_tree_params, mpcc_to_remove);
+ dc->res_pool->opps[opp_id]->mpcc_disconnect_pending[fe_idx] = true;
+
+ dc->optimized_required = true;
if (hubp->funcs->hubp_disconnect)
hubp->funcs->hubp_disconnect(hubp);
if (dc->debug.sanity_checks)
dcn10_verify_allow_pstate_change_high(dc);
-
- pipe_ctx->stream = NULL;
- memset(&pipe_ctx->stream_res, 0, sizeof(pipe_ctx->stream_res));
- memset(&pipe_ctx->plane_res, 0, sizeof(pipe_ctx->plane_res));
- pipe_ctx->top_pipe = NULL;
- pipe_ctx->bottom_pipe = NULL;
- pipe_ctx->plane_state = NULL;
}
static void plane_atomic_power_down(struct dc *dc, int fe_idx)
@@ -636,29 +656,30 @@ static void plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx)
int fe_idx = pipe_ctx->pipe_idx;
struct dce_hwseq *hws = dc->hwseq;
struct hubp *hubp = dc->res_pool->hubps[fe_idx];
- struct mpc *mpc = dc->res_pool->mpc;
int opp_id = hubp->opp_id;
- struct output_pixel_processor *opp;
- if (opp_id != 0xf) {
- mpc->funcs->wait_for_idle(mpc, hubp->mpcc_id);
- opp = dc->res_pool->opps[hubp->opp_id];
- opp->mpcc_disconnect_pending[hubp->mpcc_id] = false;
- hubp->funcs->set_blank(hubp, true);
- }
+ dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe_ctx);
REG_UPDATE(HUBP_CLK_CNTL[fe_idx],
HUBP_CLOCK_ENABLE, 0);
REG_UPDATE(DPP_CONTROL[fe_idx],
DPP_CLOCK_ENABLE, 0);
- if (opp_id != 0xf && dc->res_pool->opps[opp_id]->mpc_tree.num_pipes == 0)
+ if (opp_id != 0xf && dc->res_pool->opps[opp_id]->mpc_tree_params.opp_list == NULL)
REG_UPDATE(OPP_PIPE_CONTROL[opp_id],
OPP_PIPE_CLOCK_EN, 0);
hubp->power_gated = true;
+ dc->optimized_required = false; /* We're powering off, no need to optimize */
plane_atomic_power_down(dc, fe_idx);
+
+ pipe_ctx->stream = NULL;
+ memset(&pipe_ctx->stream_res, 0, sizeof(pipe_ctx->stream_res));
+ memset(&pipe_ctx->plane_res, 0, sizeof(pipe_ctx->plane_res));
+ pipe_ctx->top_pipe = NULL;
+ pipe_ctx->bottom_pipe = NULL;
+ pipe_ctx->plane_state = NULL;
}
static void dcn10_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx)
@@ -740,25 +761,27 @@ static void dcn10_init_hw(struct dc *dc)
}
}
+ /* Reset all MPCC muxes */
+ dc->res_pool->mpc->funcs->mpc_init(dc->res_pool->mpc);
+
for (i = 0; i < dc->res_pool->pipe_count; i++) {
struct timing_generator *tg = dc->res_pool->timing_generators[i];
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
- struct output_pixel_processor *opp = dc->res_pool->opps[i];
- struct mpc_tree_cfg *mpc_tree = &opp->mpc_tree;
struct hubp *hubp = dc->res_pool->hubps[i];
- mpc_tree->dpp[0] = i;
- mpc_tree->mpcc[0] = i;
- mpc_tree->num_pipes = 1;
-
pipe_ctx->stream_res.tg = tg;
pipe_ctx->pipe_idx = i;
pipe_ctx->plane_res.hubp = hubp;
hubp->mpcc_id = i;
- hubp->opp_id = dc->res_pool->mpc->funcs->get_opp_id(dc->res_pool->mpc, i);
+ hubp->opp_id = 0xf;
hubp->power_gated = false;
+ dc->res_pool->opps[i]->mpc_tree_params.opp_id = dc->res_pool->opps[i]->inst;
+ dc->res_pool->opps[i]->mpc_tree_params.opp_list = NULL;
+ dc->res_pool->opps[i]->mpcc_disconnect_pending[i] = true;
+ pipe_ctx->stream_res.opp = dc->res_pool->opps[i];
+
plane_atomic_disconnect(dc, pipe_ctx);
}
@@ -929,280 +952,10 @@ static bool dcn10_set_input_transfer_func(struct pipe_ctx *pipe_ctx,
return result;
}
-/*modify the method to handle rgb for arr_points*/
-static bool convert_to_custom_float(
- struct pwl_result_data *rgb_resulted,
- struct curve_points *arr_points,
- uint32_t hw_points_num)
-{
- struct custom_float_format fmt;
-
- struct pwl_result_data *rgb = rgb_resulted;
-
- uint32_t i = 0;
-
- fmt.exponenta_bits = 6;
- fmt.mantissa_bits = 12;
- fmt.sign = false;
-
- if (!convert_to_custom_float_format(arr_points[0].x, &fmt,
- &arr_points[0].custom_float_x)) {
- BREAK_TO_DEBUGGER();
- return false;
- }
-
- if (!convert_to_custom_float_format(arr_points[0].offset, &fmt,
- &arr_points[0].custom_float_offset)) {
- BREAK_TO_DEBUGGER();
- return false;
- }
-
- if (!convert_to_custom_float_format(arr_points[0].slope, &fmt,
- &arr_points[0].custom_float_slope)) {
- BREAK_TO_DEBUGGER();
- return false;
- }
-
- fmt.mantissa_bits = 10;
- fmt.sign = false;
-
- if (!convert_to_custom_float_format(arr_points[1].x, &fmt,
- &arr_points[1].custom_float_x)) {
- BREAK_TO_DEBUGGER();
- return false;
- }
-
- if (!convert_to_custom_float_format(arr_points[1].y, &fmt,
- &arr_points[1].custom_float_y)) {
- BREAK_TO_DEBUGGER();
- return false;
- }
-
- if (!convert_to_custom_float_format(arr_points[1].slope, &fmt,
- &arr_points[1].custom_float_slope)) {
- BREAK_TO_DEBUGGER();
- return false;
- }
- fmt.mantissa_bits = 12;
- fmt.sign = true;
- while (i != hw_points_num) {
- if (!convert_to_custom_float_format(rgb->red, &fmt,
- &rgb->red_reg)) {
- BREAK_TO_DEBUGGER();
- return false;
- }
-
- if (!convert_to_custom_float_format(rgb->green, &fmt,
- &rgb->green_reg)) {
- BREAK_TO_DEBUGGER();
- return false;
- }
- if (!convert_to_custom_float_format(rgb->blue, &fmt,
- &rgb->blue_reg)) {
- BREAK_TO_DEBUGGER();
- return false;
- }
- if (!convert_to_custom_float_format(rgb->delta_red, &fmt,
- &rgb->delta_red_reg)) {
- BREAK_TO_DEBUGGER();
- return false;
- }
-
- if (!convert_to_custom_float_format(rgb->delta_green, &fmt,
- &rgb->delta_green_reg)) {
- BREAK_TO_DEBUGGER();
- return false;
- }
-
- if (!convert_to_custom_float_format(rgb->delta_blue, &fmt,
- &rgb->delta_blue_reg)) {
- BREAK_TO_DEBUGGER();
- return false;
- }
-
- ++rgb;
- ++i;
- }
-
- return true;
-}
-#define MAX_REGIONS_NUMBER 34
-#define MAX_LOW_POINT 25
-#define NUMBER_SEGMENTS 32
-
-static bool
-dcn10_translate_regamma_to_hw_format(const struct dc_transfer_func *output_tf,
- struct pwl_params *regamma_params)
-{
- struct curve_points *arr_points;
- struct pwl_result_data *rgb_resulted;
- struct pwl_result_data *rgb;
- struct pwl_result_data *rgb_plus_1;
- struct fixed31_32 y_r;
- struct fixed31_32 y_g;
- struct fixed31_32 y_b;
- struct fixed31_32 y1_min;
- struct fixed31_32 y3_max;
-
- int32_t segment_start, segment_end;
- int32_t i;
- uint32_t j, k, seg_distr[MAX_REGIONS_NUMBER], increment, start_index, hw_points;
-
- if (output_tf == NULL || regamma_params == NULL || output_tf->type == TF_TYPE_BYPASS)
- return false;
-
- PERF_TRACE();
-
- arr_points = regamma_params->arr_points;
- rgb_resulted = regamma_params->rgb_resulted;
- hw_points = 0;
-
- memset(regamma_params, 0, sizeof(struct pwl_params));
- memset(seg_distr, 0, sizeof(seg_distr));
-
- if (output_tf->tf == TRANSFER_FUNCTION_PQ) {
- /* 32 segments
- * segments are from 2^-25 to 2^7
- */
- for (i = 0; i < 32 ; i++)
- seg_distr[i] = 3;
-
- segment_start = -25;
- segment_end = 7;
- } else {
- /* 10 segments
- * segment is from 2^-10 to 2^0
- * There are less than 256 points, for optimization
- */
- seg_distr[0] = 3;
- seg_distr[1] = 4;
- seg_distr[2] = 4;
- seg_distr[3] = 4;
- seg_distr[4] = 4;
- seg_distr[5] = 4;
- seg_distr[6] = 4;
- seg_distr[7] = 4;
- seg_distr[8] = 5;
- seg_distr[9] = 5;
-
- segment_start = -10;
- segment_end = 0;
- }
-
- for (i = segment_end - segment_start; i < MAX_REGIONS_NUMBER ; i++)
- seg_distr[i] = -1;
-
- for (k = 0; k < MAX_REGIONS_NUMBER; k++) {
- if (seg_distr[k] != -1)
- hw_points += (1 << seg_distr[k]);
- }
-
- j = 0;
- for (k = 0; k < (segment_end - segment_start); k++) {
- increment = NUMBER_SEGMENTS / (1 << seg_distr[k]);
- start_index = (segment_start + k + MAX_LOW_POINT) * NUMBER_SEGMENTS;
- for (i = start_index; i < start_index + NUMBER_SEGMENTS; i += increment) {
- if (j == hw_points - 1)
- break;
- rgb_resulted[j].red = output_tf->tf_pts.red[i];
- rgb_resulted[j].green = output_tf->tf_pts.green[i];
- rgb_resulted[j].blue = output_tf->tf_pts.blue[i];
- j++;
- }
- }
-
- /* last point */
- start_index = (segment_end + MAX_LOW_POINT) * NUMBER_SEGMENTS;
- rgb_resulted[hw_points - 1].red = output_tf->tf_pts.red[start_index];
- rgb_resulted[hw_points - 1].green = output_tf->tf_pts.green[start_index];
- rgb_resulted[hw_points - 1].blue = output_tf->tf_pts.blue[start_index];
-
- arr_points[0].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2),
- dal_fixed31_32_from_int(segment_start));
- arr_points[1].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2),
- dal_fixed31_32_from_int(segment_end));
-
- y_r = rgb_resulted[0].red;
- y_g = rgb_resulted[0].green;
- y_b = rgb_resulted[0].blue;
-
- y1_min = dal_fixed31_32_min(y_r, dal_fixed31_32_min(y_g, y_b));
-
- arr_points[0].y = y1_min;
- arr_points[0].slope = dal_fixed31_32_div(arr_points[0].y, arr_points[0].x);
- y_r = rgb_resulted[hw_points - 1].red;
- y_g = rgb_resulted[hw_points - 1].green;
- y_b = rgb_resulted[hw_points - 1].blue;
-
- /* see comment above, m_arrPoints[1].y should be the Y value for the
- * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1)
- */
- y3_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b));
-
- arr_points[1].y = y3_max;
-
- arr_points[1].slope = dal_fixed31_32_zero;
-
- if (output_tf->tf == TRANSFER_FUNCTION_PQ) {
- /* for PQ, we want to have a straight line from last HW X point,
- * and the slope to be such that we hit 1.0 at 10000 nits.
- */
- const struct fixed31_32 end_value =
- dal_fixed31_32_from_int(125);
-
- arr_points[1].slope = dal_fixed31_32_div(
- dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y),
- dal_fixed31_32_sub(end_value, arr_points[1].x));
- }
-
- regamma_params->hw_points_num = hw_points;
-
- i = 1;
- for (k = 0; k < MAX_REGIONS_NUMBER && i < MAX_REGIONS_NUMBER; k++) {
- if (seg_distr[k] != -1) {
- regamma_params->arr_curve_points[k].segments_num =
- seg_distr[k];
- regamma_params->arr_curve_points[i].offset =
- regamma_params->arr_curve_points[k].offset + (1 << seg_distr[k]);
- }
- i++;
- }
-
- if (seg_distr[k] != -1)
- regamma_params->arr_curve_points[k].segments_num = seg_distr[k];
-
- rgb = rgb_resulted;
- rgb_plus_1 = rgb_resulted + 1;
-
- i = 1;
-
- while (i != hw_points + 1) {
- if (dal_fixed31_32_lt(rgb_plus_1->red, rgb->red))
- rgb_plus_1->red = rgb->red;
- if (dal_fixed31_32_lt(rgb_plus_1->green, rgb->green))
- rgb_plus_1->green = rgb->green;
- if (dal_fixed31_32_lt(rgb_plus_1->blue, rgb->blue))
- rgb_plus_1->blue = rgb->blue;
-
- rgb->delta_red = dal_fixed31_32_sub(rgb_plus_1->red, rgb->red);
- rgb->delta_green = dal_fixed31_32_sub(rgb_plus_1->green, rgb->green);
- rgb->delta_blue = dal_fixed31_32_sub(rgb_plus_1->blue, rgb->blue);
-
- ++rgb_plus_1;
- ++rgb;
- ++i;
- }
-
- convert_to_custom_float(rgb_resulted, arr_points, hw_points);
-
- PERF_TRACE();
-
- return true;
-}
static bool
dcn10_set_output_transfer_func(struct pipe_ctx *pipe_ctx,
@@ -1223,9 +976,9 @@ dcn10_set_output_transfer_func(struct pipe_ctx *pipe_ctx,
/* dcn10_translate_regamma_to_hw_format takes 750us, only do it when full
* update.
*/
- else if (dcn10_translate_regamma_to_hw_format(
+ else if (cm_helper_translate_curve_to_hw_format(
stream->out_transfer_func,
- &dpp->regamma_params)) {
+ &dpp->regamma_params, false)) {
dpp->funcs->dpp_program_regamma_pwl(
dpp,
&dpp->regamma_params, OPP_REGAMMA_USER);
@@ -1579,7 +1332,6 @@ static void dcn10_enable_plane(
/* make sure OPP_PIPE_CLOCK_EN = 1 */
REG_UPDATE(OPP_PIPE_CONTROL[pipe_ctx->stream_res.tg->inst],
OPP_PIPE_CLOCK_EN, 1);
- /*TODO: REG_UPDATE(DENTIST_DISPCLK_CNTL, DENTIST_DPPCLK_WDIVIDER, 0x1f);*/
/* TODO: enable/disable in dm as per update type.
if (plane_state) {
@@ -1672,60 +1424,15 @@ static void program_csc_matrix(struct pipe_ctx *pipe_ctx,
enum dc_color_space colorspace,
uint16_t *matrix)
{
- int i;
- struct out_csc_color_matrix tbl_entry;
-
if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) {
- enum dc_color_space color_space =
- pipe_ctx->stream->output_color_space;
-
- //uint16_t matrix[12];
- for (i = 0; i < 12; i++)
- tbl_entry.regval[i] = pipe_ctx->stream->csc_color_matrix.matrix[i];
-
- tbl_entry.color_space = color_space;
- //tbl_entry.regval = matrix;
-
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, &tbl_entry);
+ 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);
}
}
-static void set_mpc_output_csc(struct dc *dc,
- struct pipe_ctx *pipe_ctx,
- enum dc_color_space colorspace,
- uint16_t *matrix,
- int opp_id)
-{
- struct mpc *mpc = dc->res_pool->mpc;
- int i;
- struct out_csc_color_matrix tbl_entry;
- enum mpc_output_csc_mode ocsc_mode = MPC_OUTPUT_CSC_COEF_A;
-
-
- if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) {
- //uint16_t matrix[12];
- for (i = 0; i < 12; i++)
- tbl_entry.regval[i] = matrix[i];
- tbl_entry.color_space = colorspace;
-
- if (mpc->funcs->set_output_csc != NULL)
- mpc->funcs->set_output_csc(mpc,
- opp_id,
- &tbl_entry,
- ocsc_mode);
- } else {
- if (mpc->funcs->set_ocsc_default != NULL)
- mpc->funcs->set_ocsc_default(mpc,
- opp_id,
- colorspace,
- ocsc_mode);
- }
-}
-
static void program_output_csc(struct dc *dc,
struct pipe_ctx *pipe_ctx,
enum dc_color_space colorspace,
@@ -1736,13 +1443,6 @@ static void program_output_csc(struct dc *dc,
program_csc_matrix(pipe_ctx,
colorspace,
matrix);
- else
- set_mpc_output_csc(dc,
- pipe_ctx,
- colorspace,
- matrix,
- opp_id);
-
}
static bool is_lower_pipe_tree_visible(struct pipe_ctx *pipe_ctx)
@@ -1914,35 +1614,73 @@ static void update_dpp(struct dpp *dpp, struct dc_plane_state *plane_state)
static void update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx)
{
- struct mpcc_cfg mpcc_cfg = {0};
struct hubp *hubp = pipe_ctx->plane_res.hubp;
- struct pipe_ctx *top_pipe;
- bool per_pixel_alpha =
- pipe_ctx->plane_state->per_pixel_alpha && pipe_ctx->bottom_pipe;
+ struct mpcc_blnd_cfg blnd_cfg;
+ bool per_pixel_alpha = pipe_ctx->plane_state->per_pixel_alpha && pipe_ctx->bottom_pipe;
+ int mpcc_id;
+ struct mpcc *new_mpcc;
+ struct mpc *mpc = dc->res_pool->mpc;
+ struct mpc_tree *mpc_tree_params = &(pipe_ctx->stream_res.opp->mpc_tree_params);
/* TODO: proper fix once fpga works */
- mpcc_cfg.dpp_id = hubp->inst;
- mpcc_cfg.opp_id = pipe_ctx->stream_res.opp->inst;
- mpcc_cfg.tree_cfg = &(pipe_ctx->stream_res.opp->mpc_tree);
- for (top_pipe = pipe_ctx->top_pipe; top_pipe; top_pipe = top_pipe->top_pipe)
- mpcc_cfg.z_index++;
if (dc->debug.surface_visual_confirm)
dcn10_get_surface_visual_confirm_color(
- pipe_ctx, &mpcc_cfg.black_color);
+ pipe_ctx, &blnd_cfg.black_color);
else
color_space_to_black_color(
dc, pipe_ctx->stream->output_color_space,
- &mpcc_cfg.black_color);
- mpcc_cfg.per_pixel_alpha = per_pixel_alpha;
+ &blnd_cfg.black_color);
+
+ if (per_pixel_alpha)
+ blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA;
+ else
+ blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_GLOBAL_ALPHA;
+
+ blnd_cfg.overlap_only = false;
+ blnd_cfg.global_alpha = 0xff;
+ blnd_cfg.global_gain = 0xff;
+
/* DCN1.0 has output CM before MPC which seems to screw with
* pre-multiplied alpha.
*/
- mpcc_cfg.pre_multiplied_alpha = is_rgb_cspace(
+ blnd_cfg.pre_multiplied_alpha = is_rgb_cspace(
pipe_ctx->stream->output_color_space)
&& per_pixel_alpha;
- hubp->mpcc_id = dc->res_pool->mpc->funcs->add(dc->res_pool->mpc, &mpcc_cfg);
- hubp->opp_id = mpcc_cfg.opp_id;
+
+ /*
+ * TODO: remove hack
+ * Note: currently there is a bug in init_hw such that
+ * on resume from hibernate, BIOS sets up MPCC0, and
+ * we do mpcc_remove but the mpcc cannot go to idle
+ * after remove. This cause us to pick mpcc1 here,
+ * which causes a pstate hang for yet unknown reason.
+ */
+ mpcc_id = hubp->inst;
+
+ /* check if this MPCC is already being used */
+ new_mpcc = mpc->funcs->get_mpcc_for_dpp(mpc_tree_params, mpcc_id);
+ /* remove MPCC if being used */
+ if (new_mpcc != NULL)
+ mpc->funcs->remove_mpcc(mpc, mpc_tree_params, new_mpcc);
+ else
+ if (dc->debug.sanity_checks)
+ mpc->funcs->assert_mpcc_idle_before_connect(
+ dc->res_pool->mpc, mpcc_id);
+
+ /* Call MPC to insert new plane */
+ new_mpcc = mpc->funcs->insert_plane(dc->res_pool->mpc,
+ mpc_tree_params,
+ &blnd_cfg,
+ NULL,
+ NULL,
+ hubp->inst,
+ mpcc_id);
+
+ ASSERT(new_mpcc != NULL);
+
+ hubp->opp_id = pipe_ctx->stream_res.opp->inst;
+ hubp->mpcc_id = mpcc_id;
}
static void update_scaler(struct pipe_ctx *pipe_ctx)
@@ -1971,7 +1709,7 @@ static void update_dchubp_dpp(
union plane_size size = plane_state->plane_size;
/* depends on DML calculation, DPP clock value may change dynamically */
- if (pipe_ctx->plane_state->update_flags.raw != 0) {
+ if (plane_state->update_flags.bits.full_update) {
enable_dppclk(
dc->hwseq,
pipe_ctx->pipe_idx,
@@ -2015,7 +1753,8 @@ static void update_dchubp_dpp(
}
if (plane_state->update_flags.bits.full_update ||
- plane_state->update_flags.bits.scaling_change) {
+ plane_state->update_flags.bits.scaling_change ||
+ plane_state->update_flags.bits.position_change) {
hubp->funcs->mem_program_viewport(
hubp,
&pipe_ctx->plane_res.scl_data.viewport,
@@ -2037,7 +1776,9 @@ static void update_dchubp_dpp(
plane_state->update_flags.bits.horizontal_mirror_change ||
plane_state->update_flags.bits.rotation_change ||
plane_state->update_flags.bits.swizzle_change ||
- plane_state->update_flags.bits.bpp_change) {
+ plane_state->update_flags.bits.dcc_change ||
+ plane_state->update_flags.bits.bpp_change ||
+ plane_state->update_flags.bits.scaling_change) {
hubp->funcs->hubp_program_surface_config(
hubp,
plane_state->format,
@@ -2062,6 +1803,7 @@ static void program_all_pipe_in_tree(
struct pipe_ctx *pipe_ctx,
struct dc_state *context)
{
+
if (pipe_ctx->top_pipe == NULL) {
pipe_ctx->stream_res.tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset;
@@ -2072,7 +1814,11 @@ static void program_all_pipe_in_tree(
pipe_ctx->stream_res.tg->funcs->program_global_sync(
pipe_ctx->stream_res.tg);
- pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, !is_pipe_tree_visible(pipe_ctx));
+
+ if (pipe_ctx->stream_res.tg->funcs->set_blank)
+ pipe_ctx->stream_res.tg->funcs->set_blank(
+ pipe_ctx->stream_res.tg,
+ !is_pipe_tree_visible(pipe_ctx));
}
if (pipe_ctx->plane_state != NULL) {
@@ -2179,6 +1925,7 @@ static void dcn10_apply_ctx_for_surface(
{
int i;
struct timing_generator *tg;
+ struct output_pixel_processor *opp;
bool removed_pipe[4] = { false };
unsigned int ref_clk_mhz = dc->res_pool->ref_clock_inKhz/1000;
bool program_water_mark = false;
@@ -2189,6 +1936,8 @@ static void dcn10_apply_ctx_for_surface(
if (!top_pipe_to_program)
return;
+ opp = top_pipe_to_program->stream_res.opp;
+
tg = top_pipe_to_program->stream_res.tg;
tg->funcs->lock(tg);
@@ -2196,7 +1945,8 @@ static void dcn10_apply_ctx_for_surface(
if (num_planes == 0) {
/* OTG blank before remove all front end */
- tg->funcs->set_blank(tg, true);
+ if (tg->funcs->set_blank)
+ tg->funcs->set_blank(tg, true);
}
/* Disconnect unused mpcc */
@@ -2236,24 +1986,14 @@ static void dcn10_apply_ctx_for_surface(
}
}
- if (num_planes > 0) {
+ if (num_planes > 0)
program_all_pipe_in_tree(dc, top_pipe_to_program, context);
- /* TODO: this is a hack w/a for switching from mpo to pipe split */
- if (stream->cursor_attributes.address.quad_part != 0) {
- struct dc_cursor_position position = { 0 };
-
- dc_stream_set_cursor_position(
- (struct dc_stream_state *)stream,
- &position);
- dc_stream_set_cursor_attributes(
- (struct dc_stream_state *)stream,
- &stream->cursor_attributes);
- }
- }
-
tg->funcs->unlock(tg);
+ if (num_planes == 0)
+ false_optc_underflow_wa(dc, stream, tg);
+
for (i = 0; i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *old_pipe_ctx =
&dc->current_state->res_ctx.pipe_ctx[i];
@@ -2264,7 +2004,7 @@ static void dcn10_apply_ctx_for_surface(
pipe_ctx->plane_state->update_flags.bits.full_update)
program_water_mark = true;
- if (removed_pipe[i] && num_planes == 0)
+ if (removed_pipe[i])
dcn10_disable_plane(dc, old_pipe_ctx);
}
@@ -2273,6 +2013,7 @@ static void dcn10_apply_ctx_for_surface(
/* pstate stuck check after watermark update */
dcn10_verify_allow_pstate_change_high(dc);
}
+
/* watermark is for all pipes */
hubbub1_program_watermarks(dc->res_pool->hubbub,
&context->bw.dcn.watermarks, ref_clk_mhz);
@@ -2502,10 +2243,10 @@ static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct dc *dc)
dcn10_config_stereo_parameters(stream, &flags);
- pipe_ctx->stream_res.opp->funcs->opp_set_stereo_polarity(
+ pipe_ctx->stream_res.opp->funcs->opp_program_stereo(
pipe_ctx->stream_res.opp,
flags.PROGRAM_STEREO == 1 ? true:false,
- stream->timing.flags.RIGHT_EYE_3D_POLARITY == 1 ? true:false);
+ &stream->timing);
pipe_ctx->stream_res.tg->funcs->program_stereo(
pipe_ctx->stream_res.tg,
@@ -2619,7 +2360,8 @@ static const struct hw_sequencer_funcs dcn10_funcs = {
.pplib_apply_display_requirements =
dcn10_pplib_apply_display_requirements,
.edp_backlight_control = hwss_edp_backlight_control,
- .edp_power_control = hwss_edp_power_control
+ .edp_power_control = hwss_edp_power_control,
+ .edp_wait_for_hpd_ready = hwss_edp_wait_for_hpd_ready,
};