xref: /linux/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_hwseq.c (revision db5d28c0bfe566908719bec8e25443aabecbb802)
1 /* SPDX-License-Identifier: MIT */
2 /*
3  * Copyright 2024 Advanced Micro Devices, Inc.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21  * OTHER DEALINGS IN THE SOFTWARE.
22  *
23  * Authors: AMD
24  *
25  */
26 
27 #include "core_types.h"
28 #include "resource.h"
29 #include "dcn351_hwseq.h"
30 #include "dcn35/dcn35_hwseq.h"
31 
32 #define DC_LOGGER_INIT(logger) \
33 	struct dal_logger *dc_logger = logger
34 
35 #define DC_LOGGER \
36 	dc_logger
37 
dcn351_calc_blocks_to_gate(struct dc * dc,struct dc_state * context,struct pg_block_update * update_state)38 void dcn351_calc_blocks_to_gate(struct dc *dc, struct dc_state *context,
39 	struct pg_block_update *update_state)
40 {
41 	int i, j;
42 
43 	dcn35_calc_blocks_to_gate(dc, context, update_state);
44 
45 	for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) {
46 		if (!update_state->pg_pipe_res_update[PG_HUBP][i] &&
47 			!update_state->pg_pipe_res_update[PG_DPP][i]) {
48 			for (j = i - 1; j >= 0; j--) {
49 				update_state->pg_pipe_res_update[PG_HUBP][j] = false;
50 				update_state->pg_pipe_res_update[PG_DPP][j] = false;
51 			}
52 
53 			break;
54 		}
55 	}
56 }
57 
dcn351_calc_blocks_to_ungate(struct dc * dc,struct dc_state * context,struct pg_block_update * update_state)58 void dcn351_calc_blocks_to_ungate(struct dc *dc, struct dc_state *context,
59 	struct pg_block_update *update_state)
60 {
61 	int i, j;
62 
63 	dcn35_calc_blocks_to_ungate(dc, context, update_state);
64 
65 	for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) {
66 		if (update_state->pg_pipe_res_update[PG_HUBP][i] &&
67 			update_state->pg_pipe_res_update[PG_DPP][i]) {
68 			for (j = i - 1; j >= 0; j--) {
69 				update_state->pg_pipe_res_update[PG_HUBP][j] = true;
70 				update_state->pg_pipe_res_update[PG_DPP][j] = true;
71 			}
72 
73 			break;
74 		}
75 	}
76 }
77 
78 /**
79  * dcn351_hw_block_power_down() - power down sequence
80  *
81  * The following sequence describes the ON-OFF (ONO) for power down:
82  *
83  *	ONO Region 11, DCPG 19: dsc3
84  *	ONO Region 10, DCPG 3: dchubp3, dpp3
85  *	ONO Region 9, DCPG 18: dsc2
86  *	ONO Region 8, DCPG 2: dchubp2, dpp2
87  *	ONO Region 7, DCPG 17: dsc1
88  *	ONO Region 6, DCPG 1: dchubp1, dpp1
89  *	ONO Region 5, DCPG 16: dsc0
90  *	ONO Region 4, DCPG 0: dchubp0, dpp0
91  *	ONO Region 3, DCPG 25: hpo - SKIPPED. Should be kept on
92  *	ONO Region 2, DCPG 24: mpc opp optc dwb
93  *	ONO Region 1, DCPG 23: dchubbub dchvm dchubbubmem - SKIPPED. PMFW will pwr dwn at IPS2 entry
94  *	ONO Region 0, DCPG 22: dccg dio dcio - SKIPPED. will be pwr dwn after lono timer is armed
95  *
96  * @dc: Current DC state
97  * @update_state: update PG sequence states for HW block
98  */
dcn351_hw_block_power_down(struct dc * dc,struct pg_block_update * update_state)99 void dcn351_hw_block_power_down(struct dc *dc,
100 	struct pg_block_update *update_state)
101 {
102 	int i = 0;
103 	struct pg_cntl *pg_cntl = dc->res_pool->pg_cntl;
104 
105 	if (!pg_cntl || dc->debug.ignore_pg)
106 		return;
107 
108 	for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) {
109 		if (update_state->pg_pipe_res_update[PG_DSC][i]) {
110 			if (pg_cntl->funcs->dsc_pg_control)
111 				pg_cntl->funcs->dsc_pg_control(pg_cntl, i, false);
112 		}
113 
114 		if (update_state->pg_pipe_res_update[PG_HUBP][i] &&
115 			update_state->pg_pipe_res_update[PG_DPP][i]) {
116 			if (pg_cntl->funcs->hubp_dpp_pg_control)
117 				pg_cntl->funcs->hubp_dpp_pg_control(pg_cntl, i, false);
118 		}
119 	}
120 
121 	// domain25 currently always on.
122 
123 	/* this will need all the clients to unregister optc interrupts, let dmubfw handle this */
124 	if (pg_cntl->funcs->plane_otg_pg_control)
125 		pg_cntl->funcs->plane_otg_pg_control(pg_cntl, false);
126 
127 	// domain23 currently always on.
128 	// domain22 currently always on.
129 }
130 
131 /**
132  * dcn351_hw_block_power_up() - power up sequence
133  *
134  * The following sequence describes the ON-OFF (ONO) for power up:
135  *
136  *	ONO Region 0, DCPG 22: dccg dio dcio - SKIPPED
137  *	ONO Region 1, DCPG 23: dchubbub dchvm dchubbubmem - SKIPPED. PMFW will power up at IPS2 exit
138  *	ONO Region 2, DCPG 24: mpc opp optc dwb
139  *	ONO Region 3, DCPG 25: hpo - SKIPPED
140  *	ONO Region 4, DCPG 0: dchubp0, dpp0
141  *	ONO Region 5, DCPG 16: dsc0
142  *	ONO Region 6, DCPG 1: dchubp1, dpp1
143  *	ONO Region 7, DCPG 17: dsc1
144  *	ONO Region 8, DCPG 2: dchubp2, dpp2
145  *	ONO Region 9, DCPG 18: dsc2
146  *	ONO Region 10, DCPG 3: dchubp3, dpp3
147  *	ONO Region 11, DCPG 19: dsc3
148  *
149  * @dc: Current DC state
150  * @update_state: update PG sequence states for HW block
151  */
dcn351_hw_block_power_up(struct dc * dc,struct pg_block_update * update_state)152 void dcn351_hw_block_power_up(struct dc *dc,
153 	struct pg_block_update *update_state)
154 {
155 	int i = 0;
156 	struct pg_cntl *pg_cntl = dc->res_pool->pg_cntl;
157 
158 	if (!pg_cntl || dc->debug.ignore_pg)
159 		return;
160 
161 	// domain22 currently always on.
162 	// domain23 currently always on.
163 
164 	/* this will need all the clients to unregister optc interrupts, let dmubfw handle this */
165 	if (pg_cntl->funcs->plane_otg_pg_control)
166 		pg_cntl->funcs->plane_otg_pg_control(pg_cntl, true);
167 
168 	// domain25 currently always on.
169 
170 	for (i = 0; i < dc->res_pool->pipe_count; i++) {
171 		if (update_state->pg_pipe_res_update[PG_HUBP][i] &&
172 			update_state->pg_pipe_res_update[PG_DPP][i]) {
173 			if (pg_cntl->funcs->hubp_dpp_pg_control)
174 				pg_cntl->funcs->hubp_dpp_pg_control(pg_cntl, i, true);
175 		}
176 
177 		if (update_state->pg_pipe_res_update[PG_DSC][i]) {
178 			if (pg_cntl->funcs->dsc_pg_control)
179 				pg_cntl->funcs->dsc_pg_control(pg_cntl, i, true);
180 		}
181 	}
182 }
183