dcn10_mpc.c 4.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
/*
 * Copyright 2012-15 Advanced Micro Devices, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 * Authors: AMD
 *
 */

#include "reg_helper.h"
#include "dcn10_mpc.h"
28
#include "dc.h"
29 30

#define REG(reg)\
31
	mpcc10->mpcc_regs->reg
32 33

#define CTX \
34
	mpcc10->base.ctx
35 36 37

#undef FN
#define FN(reg_name, field_name) \
38
	mpcc10->mpcc_shift->field_name, mpcc10->mpcc_mask->field_name
39

40 41
#define MODE_TOP_ONLY 1
#define MODE_BLEND 3
42 43
#define BLND_PP_ALPHA 0
#define BLND_GLOBAL_ALPHA 2
44

45

46 47 48
void dcn10_mpcc_set_bg_color(
		struct mpcc *mpcc,
		struct tg_color *bg_color)
49
{
50
	struct dcn10_mpcc *mpcc10 = TO_DCN10_MPCC(mpcc);
51 52 53 54 55 56 57 58
	/* mpc color is 12 bit.  tg_color is 10 bit */
	/* todo: might want to use 16 bit to represent color and have each
	 * hw block translate to correct color depth.
	 */
	uint32_t bg_r_cr = bg_color->color_r_cr << 2;
	uint32_t bg_g_y = bg_color->color_g_y << 2;
	uint32_t bg_b_cb = bg_color->color_b_cb << 2;

59
	REG_SET(MPCC_BG_R_CR, 0,
60
			MPCC_BG_R_CR, bg_r_cr);
61
	REG_SET(MPCC_BG_G_Y, 0,
62
			MPCC_BG_G_Y, bg_g_y);
63
	REG_SET(MPCC_BG_B_CB, 0,
64 65 66
			MPCC_BG_B_CB, bg_b_cb);
}

67
static void set_output_mux(struct dcn10_mpcc *mpcc10, int opp_id, int mpcc_id)
68
{
69 70
	ASSERT(mpcc10->base.opp_id == 0xf || opp_id == mpcc10->base.opp_id);
	mpcc10->base.opp_id = opp_id;
71
	REG_SET(MUX[opp_id], 0, MPC_OUT_MUX, mpcc_id);
72 73
}

74
static void reset_output_mux(struct dcn10_mpcc *mpcc10)
75
{
76 77
	REG_SET(MUX[mpcc10->base.opp_id], 0, MPC_OUT_MUX, 0xf);
	mpcc10->base.opp_id = 0xf;
78 79
}

80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
static void assert_mpcc_idle_before_connect(struct dcn10_mpcc *mpcc10)
{
	unsigned int top_sel;
	unsigned int mpcc_busy, mpcc_idle, mpcc_status;

	REG_GET(MPCC_TOP_SEL,
			MPCC_TOP_SEL, &top_sel);

	if (top_sel == 0xf) {
		mpcc_status = REG_GET_2(MPCC_STATUS,
				MPCC_BUSY, &mpcc_busy,
				MPCC_IDLE, &mpcc_idle);

		ASSERT(mpcc_busy == 0);
		ASSERT(mpcc_idle == 1);
	}
}

98
static void dcn10_mpcc_set(struct mpcc *mpcc, struct mpcc_cfg *cfg)
99
{
100 101 102 103 104
	struct dcn10_mpcc *mpcc10 = TO_DCN10_MPCC(mpcc);
	int alpha_blnd_mode = cfg->per_pixel_alpha ?
			BLND_PP_ALPHA : BLND_GLOBAL_ALPHA;
	int mpcc_mode = cfg->bot_mpcc_id != 0xf ?
				MODE_BLEND : MODE_TOP_ONLY;
105 106
	bool blend_active_only = cfg->top_of_tree &&
			!mpcc->ctx->dc->debug.surface_visual_confirm;
107

108 109 110
	if (mpcc->ctx->dc->debug.sanity_checks)
		assert_mpcc_idle_before_connect(mpcc10);

111 112 113 114 115 116 117 118 119 120 121 122
	REG_SET(MPCC_OPP_ID, 0,
		MPCC_OPP_ID, cfg->opp_id);

	REG_SET(MPCC_TOP_SEL, 0,
		MPCC_TOP_SEL, cfg->top_dpp_id);

	REG_SET(MPCC_BOT_SEL, 0,
		MPCC_BOT_SEL, cfg->bot_mpcc_id);

	REG_SET_4(MPCC_CONTROL, 0xffffffff,
		MPCC_MODE, mpcc_mode,
		MPCC_ALPHA_BLND_MODE, alpha_blnd_mode,
123
		MPCC_ALPHA_MULTIPLIED_MODE, cfg->pre_multiplied_alpha,
124
		MPCC_BLND_ACTIVE_OVERLAP_ONLY, blend_active_only);
125 126 127 128

	if (cfg->top_of_tree) {
		if (cfg->opp_id != 0xf)
			set_output_mux(mpcc10, cfg->opp_id, mpcc->inst);
129
		else if (mpcc->opp_id != 0xf)
130
			reset_output_mux(mpcc10);
131
	}
132
	mpcc10->base.opp_id = cfg->opp_id;
133 134
}

135
static void dcn10_mpcc_wait_idle(struct mpcc *mpcc)
136
{
137
	struct dcn10_mpcc *mpcc10 = TO_DCN10_MPCC(mpcc);
138

139 140 141
	REG_WAIT(MPCC_STATUS,
			MPCC_BUSY, 0,
			1000, 1000);
142
}
143 144


145 146 147 148 149
const struct mpcc_funcs dcn10_mpcc_funcs = {
		.set = dcn10_mpcc_set,
		.wait_for_idle = dcn10_mpcc_wait_idle,
		.set_bg_color = dcn10_mpcc_set_bg_color,
};
150

151 152 153 154 155 156 157 158
void dcn10_mpcc_construct(struct dcn10_mpcc *mpcc10,
	struct dc_context *ctx,
	const struct dcn_mpcc_registers *mpcc_regs,
	const struct dcn_mpcc_shift *mpcc_shift,
	const struct dcn_mpcc_mask *mpcc_mask,
	int inst)
{
	mpcc10->base.ctx = ctx;
159

160 161
	mpcc10->base.inst = inst;
	mpcc10->base.funcs = &dcn10_mpcc_funcs;
162

163 164 165
	mpcc10->mpcc_regs = mpcc_regs;
	mpcc10->mpcc_shift = mpcc_shift;
	mpcc10->mpcc_mask = mpcc_mask;
166

167
	mpcc10->base.opp_id = inst;
168
}