xref: /linux/drivers/gpu/drm/i915/display/intel_display_clock_gating.c (revision bba2c3615bd6cfee7456d1130f2e6b01b3f4e9ba)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright 2026 Intel Corporation
4  */
5 
6 #include <drm/intel/intel_gmd_misc_regs.h>
7 
8 #include "intel_de.h"
9 #include "i9xx_plane_regs.h"
10 #include "intel_display.h"
11 #include "intel_display_clock_gating.h"
12 #include "intel_display_core.h"
13 #include "intel_display_regs.h"
14 
15 static void intel_display_gen9_init_clock_gating(struct intel_display *display)
16 {
17 	/* See Bspec note for PSR2_CTL bit 31, Wa#828:skl,bxt,kbl,cfl */
18 	intel_de_rmw(display, CHICKEN_PAR1_1, 0, SKL_EDP_PSR_FIX_RDWRAP);
19 
20 	/* WaEnableChickenDCPR:skl,bxt,kbl,glk,cfl */
21 	intel_de_rmw(display, GEN8_CHICKEN_DCPR_1, 0, MASK_WAKEMEM);
22 
23 	/*
24 	 * WaFbcWakeMemOn:skl,bxt,kbl,glk,cfl
25 	 * Display WA #0859: skl,bxt,kbl,glk,cfl
26 	 */
27 	intel_de_rmw(display, DISP_ARB_CTL, 0, DISP_FBC_MEMORY_WAKE);
28 }
29 
30 void intel_display_skl_init_clock_gating(struct intel_display *display)
31 {
32 	/*
33 	 * WaCompressedResourceDisplayNewHashMode:skl,kbl
34 	 * Display WA #0390: skl,kbl
35 	 *
36 	 * Must match Sampler, Pixel Back End, and Media. See
37 	 * WaCompressedResourceSamplerPbeMediaNewHashMode.
38 	 */
39 	intel_de_rmw(display, CHICKEN_PAR1_1, 0, SKL_DE_COMPRESSED_HASH_MODE);
40 
41 	intel_display_gen9_init_clock_gating(display);
42 
43 	/*
44 	 * WaFbcTurnOffFbcWatermark:skl
45 	 * Display WA #0562: skl
46 	 */
47 	intel_de_rmw(display, DISP_ARB_CTL, 0, DISP_FBC_WM_DIS);
48 }
49 
50 void intel_display_kbl_init_clock_gating(struct intel_display *display)
51 {
52 	/*
53 	 * WaCompressedResourceDisplayNewHashMode:skl,kbl
54 	 * Display WA #0390: skl,kbl
55 	 *
56 	 * Must match Sampler, Pixel Back End, and Media. See
57 	 * WaCompressedResourceSamplerPbeMediaNewHashMode.
58 	 */
59 	intel_de_rmw(display, CHICKEN_PAR1_1, 0, SKL_DE_COMPRESSED_HASH_MODE);
60 
61 	intel_display_gen9_init_clock_gating(display);
62 
63 	/*
64 	 * WaFbcTurnOffFbcWatermark:kbl
65 	 * Display WA #0562: kbl
66 	 */
67 	intel_de_rmw(display, DISP_ARB_CTL, 0, DISP_FBC_WM_DIS);
68 }
69 
70 void intel_display_cfl_init_clock_gating(struct intel_display *display)
71 {
72 	/*
73 	 * WaCompressedResourceDisplayNewHashMode:skl,kbl (and cfl, cml)
74 	 * Display WA #0390: skl,kbl (and cfl, cml)
75 	 *
76 	 * Must match Sampler, Pixel Back End, and Media. See
77 	 * WaCompressedResourceSamplerPbeMediaNewHashMode.
78 	 *
79 	 * NOTE: this is the same workaround used for skl and kbl,
80 	 * because the original implementation was checking HAS_LLC(),
81 	 * which cfl/cml have, even though the comment for the
82 	 * workaround doesn't mention it.
83 	 *
84 	 */
85 	intel_de_rmw(display, CHICKEN_PAR1_1, 0, SKL_DE_COMPRESSED_HASH_MODE);
86 
87 	intel_display_gen9_init_clock_gating(display);
88 
89 	/*
90 	 * WaFbcTurnOffFbcWatermark:cfl
91 	 * Display WA #0562: cfl
92 	 */
93 	intel_de_rmw(display, DISP_ARB_CTL, 0, DISP_FBC_WM_DIS);
94 }
95 
96 void intel_display_bxt_init_clock_gating(struct intel_display *display)
97 {
98 	intel_display_gen9_init_clock_gating(display);
99 
100 	/*
101 	 * Wa: Backlight PWM may stop in the asserted state, causing backlight
102 	 * to stay fully on.
103 	 */
104 	intel_de_write(display, GEN9_CLKGATE_DIS_0,
105 		       intel_de_read(display, GEN9_CLKGATE_DIS_0) |
106 		       PWM1_GATING_DIS | PWM2_GATING_DIS);
107 
108 	/*
109 	 * Lower the display internal timeout.
110 	 * This is needed to avoid any hard hangs when DSI port PLL
111 	 * is off and a MMIO access is attempted by any privilege
112 	 * application, using batch buffers or any other means.
113 	 */
114 	intel_de_write(display, RM_TIMEOUT, MMIO_TIMEOUT_US(950));
115 
116 	/*
117 	 * WaFbcTurnOffFbcWatermark:bxt
118 	 * Display WA #0562: bxt
119 	 */
120 	intel_de_rmw(display, DISP_ARB_CTL, 0, DISP_FBC_WM_DIS);
121 }
122 
123 void intel_display_glk_init_clock_gating(struct intel_display *display)
124 {
125 	intel_display_gen9_init_clock_gating(display);
126 
127 	/*
128 	 * WaDisablePWMClockGating:glk
129 	 * Backlight PWM may stop in the asserted state, causing backlight
130 	 * to stay fully on.
131 	 */
132 	intel_de_write(display, GEN9_CLKGATE_DIS_0,
133 		       intel_de_read(display, GEN9_CLKGATE_DIS_0) |
134 		       PWM1_GATING_DIS | PWM2_GATING_DIS);
135 }
136 
137 void intel_display_bdw_clock_gating_disable_fbcq(struct intel_display *display)
138 {
139 	/* WaFbcAsynchFlipDisableFbcQueue:hsw,bdw */
140 	intel_de_rmw(display, CHICKEN_PIPESL_1(PIPE_A), 0, HSW_FBCQ_DIS);
141 }
142 
143 void intel_display_bdw_clock_gating_vblank_in_srd(struct intel_display *display)
144 {
145 	enum pipe pipe;
146 
147 	/* WaPsrDPAMaskVBlankInSRD:hsw */
148 	intel_de_rmw(display, CHICKEN_PAR1_1, 0, HSW_MASK_VBL_TO_PIPE_IN_SRD);
149 
150 	for_each_pipe(display, pipe) {
151 		/* WaPsrDPRSUnmaskVBlankInSRD:hsw,bdw */
152 		intel_de_rmw(display, CHICKEN_PIPESL_1(pipe), 0,
153 			     BDW_UNMASK_VBL_TO_REGS_IN_SRD);
154 	}
155 }
156 
157 void intel_display_bdw_clock_gating_kvm_notif(struct intel_display *display)
158 {
159 	/* WaKVMNotificationOnConfigChange:bdw */
160 	intel_de_rmw(display, CHICKEN_PAR2_1, 0,
161 		     KVM_CONFIG_CHANGE_NOTIFICATION_SELECT);
162 }
163 
164 void intel_display_hsw_init_clock_gating(struct intel_display *display)
165 {
166 	enum pipe pipe;
167 
168 	/* WaFbcAsynchFlipDisableFbcQueue:hsw,bdw */
169 	intel_de_rmw(display, CHICKEN_PIPESL_1(PIPE_A), 0, HSW_FBCQ_DIS);
170 
171 	/* WaPsrDPAMaskVBlankInSRD:hsw */
172 	intel_de_rmw(display, CHICKEN_PAR1_1, 0, HSW_MASK_VBL_TO_PIPE_IN_SRD);
173 
174 	for_each_pipe(display, pipe) {
175 		/* WaPsrDPRSUnmaskVBlankInSRD:hsw,bdw */
176 		intel_de_rmw(display, CHICKEN_PIPESL_1(pipe), 0,
177 			     HSW_UNMASK_VBL_TO_REGS_IN_SRD);
178 	}
179 }
180 
181 void intel_display_disable_trickle_feed(struct intel_display *display)
182 {
183 	enum pipe pipe;
184 
185 	for_each_pipe(display, pipe) {
186 		intel_de_rmw(display, DSPCNTR(display, pipe), 0,
187 			     DISP_TRICKLE_FEED_DISABLE);
188 
189 		intel_de_rmw(display, DSPSURF(display, pipe), 0, 0);
190 		intel_de_posting_read(display, DSPSURF(display, pipe));
191 	}
192 }
193 
194 void intel_display_ilk_init_clock_gating(struct intel_display *display)
195 {
196 	u32 dspclk_gate = ILK_VRHUNIT_CLOCK_GATE_DISABLE;
197 
198 	/*
199 	 * Required for FBC
200 	 * WaFbcDisableDpfcClockGating:ilk
201 	 */
202 	dspclk_gate |= ILK_DPFCRUNIT_CLOCK_GATE_DISABLE |
203 		       ILK_DPFCUNIT_CLOCK_GATE_DISABLE |
204 		       ILK_DPFDUNIT_CLOCK_GATE_ENABLE;
205 
206 	intel_de_write(display, ILK_DISPLAY_CHICKEN2,
207 		       intel_de_read(display, ILK_DISPLAY_CHICKEN2) |
208 		       ILK_DPARB_GATE | ILK_VSDPFD_FULL);
209 	dspclk_gate |= ILK_DPARBUNIT_CLOCK_GATE_ENABLE;
210 	intel_de_write(display, DISP_ARB_CTL,
211 		       intel_de_read(display, DISP_ARB_CTL) |
212 		       DISP_FBC_WM_DIS);
213 
214 	if (display->platform.ironlake && display->platform.mobile) {
215 		/* WaFbcAsynchFlipDisableFbcQueue:ilk */
216 		intel_de_rmw(display, ILK_DISPLAY_CHICKEN1, 0, ILK_FBCQ_DIS);
217 		intel_de_rmw(display, ILK_DISPLAY_CHICKEN2, 0, ILK_DPARB_GATE);
218 	}
219 
220 	intel_de_write(display, ILK_DSPCLK_GATE_D, dspclk_gate);
221 	intel_de_rmw(display, ILK_DISPLAY_CHICKEN2, 0, ILK_ELPIN_409_SELECT);
222 
223 	intel_display_disable_trickle_feed(display);
224 }
225 
226 void intel_display_gen6_init_clock_gating(struct intel_display *display)
227 {
228 	u32 dspclk_gate = ILK_VRHUNIT_CLOCK_GATE_DISABLE;
229 
230 	intel_de_write(display, ILK_DSPCLK_GATE_D, dspclk_gate);
231 	intel_de_rmw(display, ILK_DISPLAY_CHICKEN2, 0, ILK_ELPIN_409_SELECT);
232 
233 	intel_de_write(display, ILK_DISPLAY_CHICKEN1,
234 		       intel_de_read(display, ILK_DISPLAY_CHICKEN1) |
235 		       ILK_FBCQ_DIS | ILK_PABSTRETCH_DIS);
236 	intel_de_write(display, ILK_DISPLAY_CHICKEN2,
237 		       intel_de_read(display, ILK_DISPLAY_CHICKEN2) |
238 		       ILK_DPARB_GATE | ILK_VSDPFD_FULL);
239 	intel_de_write(display, ILK_DSPCLK_GATE_D,
240 		       intel_de_read(display, ILK_DSPCLK_GATE_D) |
241 		       ILK_DPARBUNIT_CLOCK_GATE_ENABLE |
242 		       ILK_DPFDUNIT_CLOCK_GATE_ENABLE);
243 
244 	intel_display_disable_trickle_feed(display);
245 }
246 
247 void intel_display_ivb_init_clock_gating(struct intel_display *display)
248 {
249 	intel_de_write(display, ILK_DSPCLK_GATE_D, ILK_VRHUNIT_CLOCK_GATE_DISABLE);
250 	intel_de_rmw(display, ILK_DISPLAY_CHICKEN1, 0, ILK_FBCQ_DIS);
251 }
252 
253 void intel_display_g4x_init_clock_gating(struct intel_display *display)
254 {
255 	u32 dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE |
256 			  OVRUNIT_CLOCK_GATE_DISABLE |
257 			  OVCUNIT_CLOCK_GATE_DISABLE;
258 
259 	if (display->platform.gm45)
260 		dspclk_gate |= DSSUNIT_CLOCK_GATE_DISABLE;
261 
262 	intel_de_write(display, DSPCLK_GATE_D, dspclk_gate);
263 
264 	intel_display_disable_trickle_feed(display);
265 }
266 
267 void intel_display_i965gm_init_clock_gating(struct intel_display *display)
268 {
269 	intel_de_write(display, DSPCLK_GATE_D, 0);
270 }
271