diff options
author | Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com> | 2017-06-02 19:00:45 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2017-09-26 18:07:49 -0400 |
commit | 1a2c82a2f161f68deb5f0519c315bfc92ede8e01 (patch) | |
tree | 6e0318b2dbafde9e86d67d65f9369a375bd2ae2e /drivers/gpu | |
parent | 8eee20139a63c6b53abc71c9a937f2b2047176c2 (diff) |
drm/amd/display: fix mpc alpha programming
Signed-off-by: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com>
Reviewed-by: Tony Cheng <Tony.Cheng@amd.com>
Acked-by: Harry Wentland <Harry.Wentland@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 78 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c | 201 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h | 19 |
4 files changed, 115 insertions, 189 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 0e677f9db96a..447f6bf4644c 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 | |||
@@ -125,14 +125,8 @@ static void lock_otg_master_update( | |||
125 | HWSEQ_REG_UPDATE(OTG0_OTG_GLOBAL_CONTROL0, | 125 | HWSEQ_REG_UPDATE(OTG0_OTG_GLOBAL_CONTROL0, |
126 | OTG_MASTER_UPDATE_LOCK_SEL, inst); | 126 | OTG_MASTER_UPDATE_LOCK_SEL, inst); |
127 | 127 | ||
128 | /* unlock master locker */ | ||
129 | HWSEQ_REG_UPDATE(OTG0_OTG_MASTER_UPDATE_LOCK, | 128 | HWSEQ_REG_UPDATE(OTG0_OTG_MASTER_UPDATE_LOCK, |
130 | OTG_MASTER_UPDATE_LOCK, 1); | 129 | OTG_MASTER_UPDATE_LOCK, 1); |
131 | |||
132 | /* wait for unlock happens */ | ||
133 | if (!wait_reg(ctx, inst_offset, OTG0_OTG_MASTER_UPDATE_LOCK, UPDATE_LOCK_STATUS, 1)) | ||
134 | BREAK_TO_DEBUGGER(); | ||
135 | |||
136 | } | 130 | } |
137 | 131 | ||
138 | static bool unlock_master_tg_and_wait( | 132 | static bool unlock_master_tg_and_wait( |
@@ -1562,8 +1556,9 @@ static void update_dchubp_dpp( | |||
1562 | enum dc_color_space color_space; | 1556 | enum dc_color_space color_space; |
1563 | struct tg_color black_color = {0}; | 1557 | struct tg_color black_color = {0}; |
1564 | struct dcn10_mpc *mpc = TO_DCN10_MPC(dc->res_pool->mpc); | 1558 | struct dcn10_mpc *mpc = TO_DCN10_MPC(dc->res_pool->mpc); |
1565 | 1559 | struct pipe_ctx *temp_pipe; | |
1566 | struct pipe_ctx *cur_pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[pipe_ctx->pipe_idx]; | 1560 | int i; |
1561 | int tree_pos = 0; | ||
1567 | 1562 | ||
1568 | /* depends on DML calculation, DPP clock value may change dynamically */ | 1563 | /* depends on DML calculation, DPP clock value may change dynamically */ |
1569 | enable_dppclk( | 1564 | enable_dppclk( |
@@ -1609,41 +1604,30 @@ static void update_dchubp_dpp( | |||
1609 | /* TODO: build stream pipes group id. For now, use stream otg | 1604 | /* TODO: build stream pipes group id. For now, use stream otg |
1610 | * id as pipe group id | 1605 | * id as pipe group id |
1611 | */ | 1606 | */ |
1612 | pipe_ctx->mpc_idx = pipe_ctx->tg->inst; | 1607 | /*pipe_ctx->scl_data.lb_params.alpha_en = pipe_ctx->surface->public.per_pixel_alpha;*/ |
1613 | tree_cfg = &context->res_ctx.mpc_tree[pipe_ctx->mpc_idx]; | 1608 | if (pipe_ctx->bottom_pipe && surface != pipe_ctx->bottom_pipe->surface) |
1614 | |||
1615 | /* enable when bottom pipe is present and | ||
1616 | * it does not share a surface with current pipe | ||
1617 | */ | ||
1618 | if (pipe_ctx->bottom_pipe && surface != pipe_ctx->bottom_pipe->surface) { | ||
1619 | pipe_ctx->scl_data.lb_params.alpha_en = 1; | 1609 | pipe_ctx->scl_data.lb_params.alpha_en = 1; |
1620 | tree_cfg->mode = TOP_BLND; | 1610 | else |
1621 | } else { | ||
1622 | pipe_ctx->scl_data.lb_params.alpha_en = 0; | 1611 | pipe_ctx->scl_data.lb_params.alpha_en = 0; |
1623 | tree_cfg->mode = TOP_PASSTHRU; | 1612 | pipe_ctx->mpc_idx = pipe_ctx->tg->inst; |
1624 | } | 1613 | tree_cfg = &context->res_ctx.mpc_tree[pipe_ctx->mpc_idx]; |
1625 | if (!pipe_ctx->top_pipe && !cur_pipe_ctx->bottom_pipe) { | 1614 | if (tree_cfg->num_pipes == 0) { |
1626 | /* primary pipe, set mpc tree index 0 only */ | ||
1627 | tree_cfg->num_pipes = 1; | ||
1628 | tree_cfg->opp_id = pipe_ctx->tg->inst; | 1615 | tree_cfg->opp_id = pipe_ctx->tg->inst; |
1629 | tree_cfg->dpp[0] = pipe_ctx->pipe_idx; | 1616 | for (i = 0; i < MAX_PIPES; i++) { |
1630 | tree_cfg->mpcc[0] = pipe_ctx->pipe_idx; | 1617 | tree_cfg->dpp[i] = 0xf; |
1618 | tree_cfg->mpcc[i] = 0xf; | ||
1619 | } | ||
1631 | } | 1620 | } |
1632 | 1621 | ||
1633 | if (!cur_pipe_ctx->top_pipe && !pipe_ctx->top_pipe) { | 1622 | for (temp_pipe = pipe_ctx->top_pipe; |
1634 | 1623 | temp_pipe != NULL; temp_pipe = temp_pipe->top_pipe) | |
1635 | if (!cur_pipe_ctx->bottom_pipe) | 1624 | tree_pos++; |
1636 | dcn10_set_mpc_tree(mpc, tree_cfg); | ||
1637 | |||
1638 | } else if (!cur_pipe_ctx->top_pipe && pipe_ctx->top_pipe) { | ||
1639 | |||
1640 | dcn10_add_dpp(mpc, tree_cfg, | ||
1641 | pipe_ctx->pipe_idx, pipe_ctx->pipe_idx, 1); | ||
1642 | } else { | ||
1643 | /* nothing to be done here */ | ||
1644 | ASSERT(cur_pipe_ctx->top_pipe && pipe_ctx->top_pipe); | ||
1645 | } | ||
1646 | 1625 | ||
1626 | tree_cfg->dpp[tree_pos] = pipe_ctx->pipe_idx; | ||
1627 | tree_cfg->mpcc[tree_pos] = pipe_ctx->pipe_idx; | ||
1628 | tree_cfg->per_pixel_alpha[tree_pos] = pipe_ctx->scl_data.lb_params.alpha_en; | ||
1629 | tree_cfg->num_pipes = tree_pos + 1; | ||
1630 | dcn10_set_mpc_tree(mpc, tree_cfg); | ||
1647 | 1631 | ||
1648 | color_space = pipe_ctx->stream->public.output_color_space; | 1632 | color_space = pipe_ctx->stream->public.output_color_space; |
1649 | color_space_to_black_color(dc, color_space, &black_color); | 1633 | color_space_to_black_color(dc, color_space, &black_color); |
@@ -1680,18 +1664,15 @@ static void program_all_pipe_in_tree( | |||
1680 | { | 1664 | { |
1681 | unsigned int ref_clk_mhz = dc->res_pool->ref_clock_inKhz/1000; | 1665 | unsigned int ref_clk_mhz = dc->res_pool->ref_clock_inKhz/1000; |
1682 | 1666 | ||
1683 | if (pipe_ctx->surface->public.visible || pipe_ctx->top_pipe == NULL) { | 1667 | if (pipe_ctx->top_pipe == NULL) { |
1684 | dcn10_power_on_fe(dc, pipe_ctx, context); | ||
1685 | 1668 | ||
1686 | /* lock otg_master_update to process all pipes associated with | 1669 | /* lock otg_master_update to process all pipes associated with |
1687 | * this OTG. this is done only one time. | 1670 | * this OTG. this is done only one time. |
1688 | */ | 1671 | */ |
1689 | if (pipe_ctx->top_pipe == NULL) { | 1672 | /* watermark is for all pipes */ |
1690 | /* watermark is for all pipes */ | 1673 | pipe_ctx->mi->funcs->program_watermarks( |
1691 | pipe_ctx->mi->funcs->program_watermarks( | 1674 | pipe_ctx->mi, &context->bw.dcn.watermarks, ref_clk_mhz); |
1692 | pipe_ctx->mi, &context->bw.dcn.watermarks, ref_clk_mhz); | 1675 | lock_otg_master_update(dc->ctx, pipe_ctx->tg->inst); |
1693 | lock_otg_master_update(dc->ctx, pipe_ctx->tg->inst); | ||
1694 | } | ||
1695 | 1676 | ||
1696 | pipe_ctx->tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset; | 1677 | pipe_ctx->tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset; |
1697 | pipe_ctx->tg->dlg_otg_param.vstartup_start = pipe_ctx->pipe_dlg_param.vstartup_start; | 1678 | pipe_ctx->tg->dlg_otg_param.vstartup_start = pipe_ctx->pipe_dlg_param.vstartup_start; |
@@ -1702,12 +1683,11 @@ static void program_all_pipe_in_tree( | |||
1702 | pipe_ctx->tg->funcs->program_global_sync( | 1683 | pipe_ctx->tg->funcs->program_global_sync( |
1703 | pipe_ctx->tg); | 1684 | pipe_ctx->tg); |
1704 | pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, !is_pipe_tree_visible(pipe_ctx)); | 1685 | pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, !is_pipe_tree_visible(pipe_ctx)); |
1686 | } | ||
1705 | 1687 | ||
1706 | 1688 | if (pipe_ctx->surface->public.visible) { | |
1707 | 1689 | dcn10_power_on_fe(dc, pipe_ctx, context); | |
1708 | update_dchubp_dpp(dc, pipe_ctx, context); | 1690 | update_dchubp_dpp(dc, pipe_ctx, context); |
1709 | |||
1710 | /* Only support one plane for now. */ | ||
1711 | } | 1691 | } |
1712 | 1692 | ||
1713 | if (pipe_ctx->bottom_pipe != NULL) | 1693 | if (pipe_ctx->bottom_pipe != NULL) |
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c index cb22cd130e1a..58f80114e36b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c | |||
@@ -36,6 +36,9 @@ | |||
36 | #define FN(reg_name, field_name) \ | 36 | #define FN(reg_name, field_name) \ |
37 | mpc->mpc_shift->field_name, mpc->mpc_mask->field_name | 37 | mpc->mpc_shift->field_name, mpc->mpc_mask->field_name |
38 | 38 | ||
39 | #define MODE_TOP_ONLY 1 | ||
40 | #define MODE_BLEND 3 | ||
41 | |||
39 | /* Internal function to set mpc output mux */ | 42 | /* Internal function to set mpc output mux */ |
40 | static void set_output_mux(struct dcn10_mpc *mpc, | 43 | static void set_output_mux(struct dcn10_mpc *mpc, |
41 | uint8_t opp_id, | 44 | uint8_t opp_id, |
@@ -45,32 +48,7 @@ static void set_output_mux(struct dcn10_mpc *mpc, | |||
45 | REG_UPDATE(OPP_PIPE_CONTROL[opp_id], | 48 | REG_UPDATE(OPP_PIPE_CONTROL[opp_id], |
46 | OPP_PIPE_CLOCK_EN, 1); | 49 | OPP_PIPE_CLOCK_EN, 1); |
47 | 50 | ||
48 | REG_SET(MUX[opp_id], 0, | 51 | REG_SET(MUX[opp_id], 0, MPC_OUT_MUX, mpcc_id); |
49 | MPC_OUT_MUX, mpcc_id); | ||
50 | |||
51 | /* TODO: Move to post when ready. | ||
52 | if (mpcc_id == 0xf) { | ||
53 | MPCC_REG_UPDATE(OPP_PIPE0_OPP_PIPE_CONTROL, | ||
54 | OPP_PIPE_CLOCK_EN, 0); | ||
55 | } | ||
56 | */ | ||
57 | } | ||
58 | |||
59 | static void set_blend_mode(struct dcn10_mpc *mpc, | ||
60 | enum blend_mode mode, | ||
61 | uint8_t mpcc_id) | ||
62 | { | ||
63 | /* Enable per-pixel alpha on this pipe */ | ||
64 | if (mode == TOP_BLND) | ||
65 | REG_UPDATE_3(MPCC_CONTROL[mpcc_id], | ||
66 | MPCC_ALPHA_BLND_MODE, 0, | ||
67 | MPCC_ALPHA_MULTIPLIED_MODE, 0, | ||
68 | MPCC_BLND_ACTIVE_OVERLAP_ONLY, 0); | ||
69 | else | ||
70 | REG_UPDATE_3(MPCC_CONTROL[mpcc_id], | ||
71 | MPCC_ALPHA_BLND_MODE, 0, | ||
72 | MPCC_ALPHA_MULTIPLIED_MODE, 1, | ||
73 | MPCC_BLND_ACTIVE_OVERLAP_ONLY, 1); | ||
74 | } | 52 | } |
75 | 53 | ||
76 | void dcn10_set_mpc_background_color(struct dcn10_mpc *mpc, | 54 | void dcn10_set_mpc_background_color(struct dcn10_mpc *mpc, |
@@ -121,44 +99,27 @@ void dcn10_set_mpc_tree(struct dcn10_mpc *mpc, | |||
121 | REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, | 99 | REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, |
122 | MPCC_BOT_SEL, 0xF); | 100 | MPCC_BOT_SEL, 0xF); |
123 | 101 | ||
124 | /* MPCC_CONTROL->MPCC_MODE */ | ||
125 | REG_UPDATE(MPCC_CONTROL[mpcc_inst], | 102 | REG_UPDATE(MPCC_CONTROL[mpcc_inst], |
126 | MPCC_MODE, tree_cfg->mode); | 103 | MPCC_MODE, MODE_TOP_ONLY); |
127 | } else { | 104 | } else { |
128 | REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, | 105 | REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, |
129 | MPCC_BOT_SEL, tree_cfg->dpp[i+1]); | 106 | MPCC_BOT_SEL, tree_cfg->dpp[i+1]); |
130 | 107 | ||
131 | /* MPCC_CONTROL->MPCC_MODE */ | ||
132 | REG_UPDATE(MPCC_CONTROL[mpcc_inst], | 108 | REG_UPDATE(MPCC_CONTROL[mpcc_inst], |
133 | MPCC_MODE, 3); | 109 | MPCC_MODE, MODE_BLEND); |
134 | } | 110 | } |
135 | 111 | ||
136 | if (i == 0) | 112 | if (i == 0) |
137 | set_output_mux( | 113 | set_output_mux( |
138 | mpc, tree_cfg->opp_id, mpcc_inst); | 114 | mpc, tree_cfg->opp_id, mpcc_inst); |
139 | 115 | ||
140 | set_blend_mode(mpc, tree_cfg->mode, mpcc_inst); | 116 | REG_UPDATE_2(MPCC_CONTROL[mpcc_inst], |
117 | MPCC_ALPHA_BLND_MODE, | ||
118 | tree_cfg->per_pixel_alpha[i] ? 0 : 2, | ||
119 | MPCC_ALPHA_MULTIPLIED_MODE, 0); | ||
141 | } | 120 | } |
142 | } | 121 | } |
143 | 122 | ||
144 | void dcn10_set_mpc_passthrough(struct dcn10_mpc *mpc, | ||
145 | uint8_t dpp_idx, | ||
146 | uint8_t mpcc_idx, | ||
147 | uint8_t opp_idx) | ||
148 | { | ||
149 | struct mpc_tree_cfg tree_cfg = { 0 }; | ||
150 | |||
151 | tree_cfg.num_pipes = 1; | ||
152 | tree_cfg.opp_id = opp_idx; | ||
153 | tree_cfg.mode = TOP_PASSTHRU; | ||
154 | /* TODO: FPGA bring up one MPC has only 1 DPP and 1 MPCC | ||
155 | * For blend case, need fill mode DPP and cascade MPCC | ||
156 | */ | ||
157 | tree_cfg.dpp[0] = dpp_idx; | ||
158 | tree_cfg.mpcc[0] = mpcc_idx; | ||
159 | dcn10_set_mpc_tree(mpc, &tree_cfg); | ||
160 | } | ||
161 | |||
162 | /* | 123 | /* |
163 | * This is the function to remove current MPC tree specified by tree_cfg | 124 | * This is the function to remove current MPC tree specified by tree_cfg |
164 | * Before invoke this function, ensure that master lock of OPTC specified | 125 | * Before invoke this function, ensure that master lock of OPTC specified |
@@ -188,6 +149,7 @@ void dcn10_delete_mpc_tree(struct dcn10_mpc *mpc, | |||
188 | */ | 149 | */ |
189 | tree_cfg->dpp[i] = 0xf; | 150 | tree_cfg->dpp[i] = 0xf; |
190 | tree_cfg->mpcc[i] = 0xf; | 151 | tree_cfg->mpcc[i] = 0xf; |
152 | tree_cfg->per_pixel_alpha[i] = false; | ||
191 | } | 153 | } |
192 | set_output_mux(mpc, tree_cfg->opp_id, 0xf); | 154 | set_output_mux(mpc, tree_cfg->opp_id, 0xf); |
193 | tree_cfg->opp_id = 0xf; | 155 | tree_cfg->opp_id = 0xf; |
@@ -208,6 +170,7 @@ bool dcn10_remove_dpp(struct dcn10_mpc *mpc, | |||
208 | uint8_t idx) | 170 | uint8_t idx) |
209 | { | 171 | { |
210 | int i; | 172 | int i; |
173 | uint8_t mpcc_inst; | ||
211 | bool found = false; | 174 | bool found = false; |
212 | 175 | ||
213 | /* find dpp_idx from dpp array of tree_cfg */ | 176 | /* find dpp_idx from dpp array of tree_cfg */ |
@@ -218,54 +181,53 @@ bool dcn10_remove_dpp(struct dcn10_mpc *mpc, | |||
218 | } | 181 | } |
219 | } | 182 | } |
220 | 183 | ||
221 | if (found) { | 184 | if (!found) { |
222 | /* add remove dpp/mpcc pair into pending list */ | 185 | BREAK_TO_DEBUGGER(); |
186 | return false; | ||
187 | } | ||
188 | mpcc_inst = tree_cfg->mpcc[i]; | ||
223 | 189 | ||
224 | /* TODO FPGA AddToPendingList if empty from pseudo code | 190 | REG_SET(MPCC_OPP_ID[mpcc_inst], 0, |
225 | * AddToPendingList(tree_cfg->dpp[i],tree_cfg->mpcc[i]); | 191 | MPCC_OPP_ID, 0xf); |
226 | */ | ||
227 | uint8_t mpcc_inst = tree_cfg->mpcc[i]; | ||
228 | 192 | ||
229 | REG_SET(MPCC_OPP_ID[mpcc_inst], 0, | 193 | REG_SET(MPCC_TOP_SEL[mpcc_inst], 0, |
230 | MPCC_OPP_ID, 0xf); | 194 | MPCC_TOP_SEL, 0xf); |
231 | 195 | ||
232 | REG_SET(MPCC_TOP_SEL[mpcc_inst], 0, | 196 | REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, |
233 | MPCC_TOP_SEL, 0xf); | 197 | MPCC_BOT_SEL, 0xf); |
198 | |||
199 | if (i == 0) { | ||
200 | if (tree_cfg->num_pipes > 1) | ||
201 | set_output_mux(mpc, | ||
202 | tree_cfg->opp_id, tree_cfg->mpcc[i+1]); | ||
203 | else | ||
204 | set_output_mux(mpc, tree_cfg->opp_id, 0xf); | ||
205 | } else if (i == tree_cfg->num_pipes-1) { | ||
206 | mpcc_inst = tree_cfg->mpcc[i - 1]; | ||
234 | 207 | ||
235 | REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, | 208 | REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, |
236 | MPCC_BOT_SEL, 0xF); | 209 | MPCC_BOT_SEL, 0xF); |
237 | 210 | ||
238 | if (i == 0) { | 211 | /* prev mpc is now last, set to top only*/ |
239 | if (tree_cfg->num_pipes > 1) | 212 | REG_UPDATE(MPCC_CONTROL[mpcc_inst], |
240 | set_output_mux(mpc, | 213 | MPCC_MODE, MODE_TOP_ONLY); |
241 | tree_cfg->opp_id, tree_cfg->mpcc[i+1]); | 214 | } else { |
242 | else | 215 | mpcc_inst = tree_cfg->mpcc[i - 1]; |
243 | set_output_mux(mpc, tree_cfg->opp_id, 0xf); | ||
244 | } else if (i == tree_cfg->num_pipes-1) { | ||
245 | mpcc_inst = tree_cfg->mpcc[i - 1]; | ||
246 | |||
247 | REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, | ||
248 | MPCC_BOT_SEL, 0xF); | ||
249 | |||
250 | REG_UPDATE(MPCC_CONTROL[mpcc_inst], | ||
251 | MPCC_MODE, tree_cfg->mode); | ||
252 | } else { | ||
253 | mpcc_inst = tree_cfg->mpcc[i - 1]; | ||
254 | 216 | ||
255 | REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, | 217 | REG_SET(MPCC_BOT_SEL[mpcc_inst], 0, |
256 | MPCC_BOT_SEL, tree_cfg->mpcc[i+1]); | 218 | MPCC_BOT_SEL, tree_cfg->mpcc[i+1]); |
257 | } | 219 | } |
258 | set_blend_mode(mpc, tree_cfg->mode, mpcc_inst); | ||
259 | 220 | ||
260 | /* update tree_cfg structure */ | 221 | /* update tree_cfg structure */ |
261 | while (i < tree_cfg->num_pipes - 1) { | 222 | while (i < tree_cfg->num_pipes - 1) { |
262 | tree_cfg->dpp[i] = tree_cfg->dpp[i+1]; | 223 | tree_cfg->dpp[i] = tree_cfg->dpp[i+1]; |
263 | tree_cfg->mpcc[i] = tree_cfg->mpcc[i+1]; | 224 | tree_cfg->mpcc[i] = tree_cfg->mpcc[i+1]; |
264 | i++; | 225 | tree_cfg->per_pixel_alpha[i] = tree_cfg->per_pixel_alpha[i+1]; |
265 | } | 226 | i++; |
266 | tree_cfg->num_pipes--; | ||
267 | } | 227 | } |
268 | return found; | 228 | tree_cfg->num_pipes--; |
229 | |||
230 | return true; | ||
269 | } | 231 | } |
270 | 232 | ||
271 | /* TODO FPGA: how to handle DPP? | 233 | /* TODO FPGA: how to handle DPP? |
@@ -284,14 +246,14 @@ void dcn10_add_dpp(struct dcn10_mpc *mpc, | |||
284 | struct mpc_tree_cfg *tree_cfg, | 246 | struct mpc_tree_cfg *tree_cfg, |
285 | uint8_t dpp_idx, | 247 | uint8_t dpp_idx, |
286 | uint8_t mpcc_idx, | 248 | uint8_t mpcc_idx, |
249 | uint8_t per_pixel_alpha, | ||
287 | uint8_t position) | 250 | uint8_t position) |
288 | { | 251 | { |
289 | uint8_t temp; | 252 | uint8_t prev; |
290 | uint8_t temp1; | 253 | uint8_t next; |
291 | 254 | ||
292 | REG_SET(MPCC_OPP_ID[mpcc_idx], 0, | 255 | REG_SET(MPCC_OPP_ID[mpcc_idx], 0, |
293 | MPCC_OPP_ID, tree_cfg->opp_id); | 256 | MPCC_OPP_ID, tree_cfg->opp_id); |
294 | |||
295 | REG_SET(MPCC_TOP_SEL[mpcc_idx], 0, | 257 | REG_SET(MPCC_TOP_SEL[mpcc_idx], 0, |
296 | MPCC_TOP_SEL, dpp_idx); | 258 | MPCC_TOP_SEL, dpp_idx); |
297 | 259 | ||
@@ -299,70 +261,71 @@ void dcn10_add_dpp(struct dcn10_mpc *mpc, | |||
299 | /* idle dpp/mpcc is added to the top layer of tree */ | 261 | /* idle dpp/mpcc is added to the top layer of tree */ |
300 | REG_SET(MPCC_BOT_SEL[mpcc_idx], 0, | 262 | REG_SET(MPCC_BOT_SEL[mpcc_idx], 0, |
301 | MPCC_BOT_SEL, tree_cfg->mpcc[0]); | 263 | MPCC_BOT_SEL, tree_cfg->mpcc[0]); |
302 | REG_UPDATE(MPCC_CONTROL[mpcc_idx], | ||
303 | MPCC_MODE, 3); | ||
304 | 264 | ||
265 | /* bottom mpc is always top only */ | ||
266 | REG_UPDATE(MPCC_CONTROL[mpcc_idx], | ||
267 | MPCC_MODE, MODE_TOP_ONLY); | ||
305 | /* opp will get new output. from new added mpcc */ | 268 | /* opp will get new output. from new added mpcc */ |
306 | set_output_mux(mpc, tree_cfg->opp_id, mpcc_idx); | 269 | set_output_mux(mpc, tree_cfg->opp_id, mpcc_idx); |
307 | 270 | ||
308 | set_blend_mode(mpc, tree_cfg->mode, mpcc_idx); | ||
309 | |||
310 | } else if (position == tree_cfg->num_pipes) { | 271 | } else if (position == tree_cfg->num_pipes) { |
311 | /* idle dpp/mpcc is added to the bottom layer of tree */ | 272 | /* idle dpp/mpcc is added to the bottom layer of tree */ |
312 | 273 | ||
313 | /* get instance of previous bottom mpcc, set to middle layer */ | 274 | /* get instance of previous bottom mpcc, set to middle layer */ |
314 | temp = tree_cfg->mpcc[tree_cfg->num_pipes - 1]; | 275 | prev = tree_cfg->mpcc[position - 1]; |
315 | 276 | ||
316 | REG_SET(MPCC_BOT_SEL[temp], 0, | 277 | REG_SET(MPCC_BOT_SEL[prev], 0, |
317 | MPCC_BOT_SEL, mpcc_idx); | 278 | MPCC_BOT_SEL, mpcc_idx); |
318 | 279 | ||
319 | REG_UPDATE(MPCC_CONTROL[temp], | 280 | /* all mpcs other than bottom need to blend */ |
320 | MPCC_MODE, 3); | 281 | REG_UPDATE(MPCC_CONTROL[prev], |
282 | MPCC_MODE, MODE_BLEND); | ||
321 | 283 | ||
322 | /* mpcc_idx become new bottom mpcc*/ | 284 | /* mpcc_idx become new bottom mpcc*/ |
323 | REG_SET(MPCC_BOT_SEL[mpcc_idx], 0, | 285 | REG_SET(MPCC_BOT_SEL[mpcc_idx], 0, |
324 | MPCC_BOT_SEL, 0xf); | 286 | MPCC_BOT_SEL, 0xf); |
325 | 287 | ||
288 | /* bottom mpc is always top only */ | ||
326 | REG_UPDATE(MPCC_CONTROL[mpcc_idx], | 289 | REG_UPDATE(MPCC_CONTROL[mpcc_idx], |
327 | MPCC_MODE, tree_cfg->mode); | 290 | MPCC_MODE, MODE_TOP_ONLY); |
328 | |||
329 | set_blend_mode(mpc, tree_cfg->mode, mpcc_idx); | ||
330 | } else { | 291 | } else { |
331 | /* idle dpp/mpcc is added to middle of tree */ | 292 | /* idle dpp/mpcc is added to middle of tree */ |
332 | temp = tree_cfg->mpcc[position - 1]; | 293 | prev = tree_cfg->mpcc[position - 1]; /* mpc a */ |
333 | temp1 = tree_cfg->mpcc[position]; | 294 | next = tree_cfg->mpcc[position]; /* mpc b */ |
334 | 295 | ||
335 | /* new mpcc instance temp1 is added right after temp*/ | 296 | /* connect mpc inserted below mpc a*/ |
336 | REG_SET(MPCC_BOT_SEL[temp], 0, | 297 | REG_SET(MPCC_BOT_SEL[prev], 0, |
337 | MPCC_BOT_SEL, mpcc_idx); | 298 | MPCC_BOT_SEL, mpcc_idx); |
338 | 299 | ||
339 | /* mpcc_idx connect previous temp+1 to new mpcc */ | 300 | /* blend on mpc being inserted */ |
340 | REG_SET(MPCC_BOT_SEL[mpcc_idx], 0, | 301 | REG_UPDATE(MPCC_CONTROL[mpcc_idx], |
341 | MPCC_BOT_SEL, temp1); | 302 | MPCC_MODE, MODE_BLEND); |
342 | 303 | ||
343 | /* temp TODO: may not need*/ | 304 | /* Connect mpc b below one inserted */ |
344 | REG_UPDATE(MPCC_CONTROL[temp], | 305 | REG_SET(MPCC_BOT_SEL[mpcc_idx], 0, |
345 | MPCC_MODE, 3); | 306 | MPCC_BOT_SEL, next); |
346 | 307 | ||
347 | set_blend_mode(mpc, tree_cfg->mode, temp); | ||
348 | } | 308 | } |
349 | 309 | /* premultiplied mode only if alpha is on for the layer*/ | |
350 | /* update tree_cfg structure */ | 310 | REG_UPDATE_2(MPCC_CONTROL[mpcc_idx], |
351 | temp = tree_cfg->num_pipes - 1; | 311 | MPCC_ALPHA_BLND_MODE, |
312 | tree_cfg->per_pixel_alpha[position] ? 0 : 2, | ||
313 | MPCC_ALPHA_MULTIPLIED_MODE, 0); | ||
352 | 314 | ||
353 | /* | 315 | /* |
354 | * iterating from the last mpc/dpp pair to the one being added, shift | 316 | * iterating from the last mpc/dpp pair to the one being added, shift |
355 | * them down one position | 317 | * them down one position |
356 | */ | 318 | */ |
357 | while (temp > position) { | 319 | for (next = tree_cfg->num_pipes; next > position; next--) { |
358 | tree_cfg->dpp[temp + 1] = tree_cfg->dpp[temp]; | 320 | tree_cfg->dpp[next] = tree_cfg->dpp[next - 1]; |
359 | tree_cfg->mpcc[temp + 1] = tree_cfg->mpcc[temp]; | 321 | tree_cfg->mpcc[next] = tree_cfg->mpcc[next - 1]; |
360 | temp--; | 322 | tree_cfg->per_pixel_alpha[next] = tree_cfg->per_pixel_alpha[next - 1]; |
361 | } | 323 | } |
362 | 324 | ||
363 | /* insert the new mpc/dpp pair into the tree_cfg*/ | 325 | /* insert the new mpc/dpp pair into the tree_cfg*/ |
364 | tree_cfg->dpp[position] = dpp_idx; | 326 | tree_cfg->dpp[position] = dpp_idx; |
365 | tree_cfg->mpcc[position] = mpcc_idx; | 327 | tree_cfg->mpcc[position] = mpcc_idx; |
328 | tree_cfg->per_pixel_alpha[position] = per_pixel_alpha; | ||
366 | tree_cfg->num_pipes++; | 329 | tree_cfg->num_pipes++; |
367 | } | 330 | } |
368 | 331 | ||
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h index 6550b93c9254..3e4eb655e913 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.h | |||
@@ -105,11 +105,6 @@ struct dcn10_mpc { | |||
105 | const struct dcn_mpc_mask *mpc_mask; | 105 | const struct dcn_mpc_mask *mpc_mask; |
106 | }; | 106 | }; |
107 | 107 | ||
108 | void dcn10_set_mpc_passthrough(struct dcn10_mpc *mpc, | ||
109 | uint8_t dpp_idx, | ||
110 | uint8_t mpcc_idx, | ||
111 | uint8_t opp_idx); | ||
112 | |||
113 | void dcn10_delete_mpc_tree(struct dcn10_mpc *mpc, | 108 | void dcn10_delete_mpc_tree(struct dcn10_mpc *mpc, |
114 | struct mpc_tree_cfg *tree_cfg); | 109 | struct mpc_tree_cfg *tree_cfg); |
115 | 110 | ||
@@ -121,6 +116,7 @@ void dcn10_add_dpp(struct dcn10_mpc *mpc, | |||
121 | struct mpc_tree_cfg *tree_cfg, | 116 | struct mpc_tree_cfg *tree_cfg, |
122 | uint8_t dpp_idx, | 117 | uint8_t dpp_idx, |
123 | uint8_t mpcc_idx, | 118 | uint8_t mpcc_idx, |
119 | uint8_t per_pixel_alpha, | ||
124 | uint8_t position); | 120 | uint8_t position); |
125 | 121 | ||
126 | void wait_mpcc_idle(struct dcn10_mpc *mpc, | 122 | void wait_mpcc_idle(struct dcn10_mpc *mpc, |
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h index 2e86ebe5eeda..ec1a201747f2 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h | |||
@@ -25,19 +25,6 @@ | |||
25 | #ifndef __DC_MPC_H__ | 25 | #ifndef __DC_MPC_H__ |
26 | #define __DC_MPC_H__ | 26 | #define __DC_MPC_H__ |
27 | 27 | ||
28 | /* define the maximum number of pipes | ||
29 | * MAX_NUM_PIPPES = MAX_PIPES defined in core_type.h | ||
30 | */ | ||
31 | enum { | ||
32 | MAX_NUM_PIPPES = 6 | ||
33 | }; | ||
34 | |||
35 | enum blend_mode { | ||
36 | DIGI_BYPASS = 0, /* digital bypass */ | ||
37 | TOP_PASSTHRU, /* top layer pass through */ | ||
38 | TOP_BLND /* top layer blend */ | ||
39 | }; | ||
40 | |||
41 | /* This structure define the mpc tree configuration | 28 | /* This structure define the mpc tree configuration |
42 | * num_pipes - number of pipes of the tree | 29 | * num_pipes - number of pipes of the tree |
43 | * opp_id - instance id of OPP to drive MPC | 30 | * opp_id - instance id of OPP to drive MPC |
@@ -60,10 +47,10 @@ struct mpc_tree_cfg { | |||
60 | uint8_t num_pipes; | 47 | uint8_t num_pipes; |
61 | uint8_t opp_id; | 48 | uint8_t opp_id; |
62 | /* dpp pipes for blend */ | 49 | /* dpp pipes for blend */ |
63 | uint8_t dpp[MAX_NUM_PIPPES]; | 50 | uint8_t dpp[6]; |
64 | /* mpcc insatnces for blend */ | 51 | /* mpcc insatnces for blend */ |
65 | uint8_t mpcc[MAX_NUM_PIPPES]; | 52 | uint8_t mpcc[6]; |
66 | enum blend_mode mode; | 53 | bool per_pixel_alpha[6]; |
67 | }; | 54 | }; |
68 | 55 | ||
69 | struct mpcc_blnd_cfg { | 56 | struct mpcc_blnd_cfg { |