File: | dev/pci/drm/i915/display/intel_panel.c |
Warning: | line 484, column 15 Division by zero |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | |||
2 | * Copyright © 2006-2010 Intel Corporation | |||
3 | * Copyright (c) 2006 Dave Airlie <airlied@linux.ie> | |||
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 (including the next | |||
13 | * paragraph) shall be included in all copies or substantial portions of the | |||
14 | * Software. | |||
15 | * | |||
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |||
19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
22 | * DEALINGS IN THE SOFTWARE. | |||
23 | * | |||
24 | * Authors: | |||
25 | * Eric Anholt <eric@anholt.net> | |||
26 | * Dave Airlie <airlied@linux.ie> | |||
27 | * Jesse Barnes <jesse.barnes@intel.com> | |||
28 | * Chris Wilson <chris@chris-wilson.co.uk> | |||
29 | */ | |||
30 | ||||
31 | #define pr_fmt(fmt)KBUILD_MODNAME ": " fmt KBUILD_MODNAME ": " fmt | |||
32 | ||||
33 | #include <linux/kernel.h> | |||
34 | #include <linux/moduleparam.h> | |||
35 | #include <linux/pwm.h> | |||
36 | ||||
37 | #include "intel_connector.h" | |||
38 | #include "intel_display_types.h" | |||
39 | #include "intel_dp_aux_backlight.h" | |||
40 | #include "intel_dsi_dcs_backlight.h" | |||
41 | #include "intel_panel.h" | |||
42 | ||||
43 | void | |||
44 | intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode, | |||
45 | struct drm_display_mode *adjusted_mode) | |||
46 | { | |||
47 | drm_mode_copy(adjusted_mode, fixed_mode); | |||
48 | ||||
49 | drm_mode_set_crtcinfo(adjusted_mode, 0); | |||
50 | } | |||
51 | ||||
52 | static bool_Bool is_downclock_mode(const struct drm_display_mode *downclock_mode, | |||
53 | const struct drm_display_mode *fixed_mode) | |||
54 | { | |||
55 | return drm_mode_match(downclock_mode, fixed_mode, | |||
56 | DRM_MODE_MATCH_TIMINGS(1 << 0) | | |||
57 | DRM_MODE_MATCH_FLAGS(1 << 2) | | |||
58 | DRM_MODE_MATCH_3D_FLAGS(1 << 3)) && | |||
59 | downclock_mode->clock < fixed_mode->clock; | |||
60 | } | |||
61 | ||||
62 | struct drm_display_mode * | |||
63 | intel_panel_edid_downclock_mode(struct intel_connector *connector, | |||
64 | const struct drm_display_mode *fixed_mode) | |||
65 | { | |||
66 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
67 | const struct drm_display_mode *scan, *best_mode = NULL((void *)0); | |||
68 | struct drm_display_mode *downclock_mode; | |||
69 | int best_clock = fixed_mode->clock; | |||
70 | ||||
71 | list_for_each_entry(scan, &connector->base.probed_modes, head)for (scan = ({ const __typeof( ((__typeof(*scan) *)0)->head ) *__mptr = ((&connector->base.probed_modes)->next ); (__typeof(*scan) *)( (char *)__mptr - __builtin_offsetof(__typeof (*scan), head) );}); &scan->head != (&connector-> base.probed_modes); scan = ({ const __typeof( ((__typeof(*scan ) *)0)->head ) *__mptr = (scan->head.next); (__typeof(* scan) *)( (char *)__mptr - __builtin_offsetof(__typeof(*scan) , head) );})) { | |||
72 | /* | |||
73 | * If one mode has the same resolution with the fixed_panel | |||
74 | * mode while they have the different refresh rate, it means | |||
75 | * that the reduced downclock is found. In such | |||
76 | * case we can set the different FPx0/1 to dynamically select | |||
77 | * between low and high frequency. | |||
78 | */ | |||
79 | if (is_downclock_mode(scan, fixed_mode) && | |||
80 | scan->clock < best_clock) { | |||
81 | /* | |||
82 | * The downclock is already found. But we | |||
83 | * expect to find the lower downclock. | |||
84 | */ | |||
85 | best_clock = scan->clock; | |||
86 | best_mode = scan; | |||
87 | } | |||
88 | } | |||
89 | ||||
90 | if (!best_mode) | |||
91 | return NULL((void *)0); | |||
92 | ||||
93 | downclock_mode = drm_mode_duplicate(&dev_priv->drm, best_mode); | |||
94 | if (!downclock_mode) | |||
95 | return NULL((void *)0); | |||
96 | ||||
97 | drm_dbg_kms(&dev_priv->drm,drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "[CONNECTOR:%d:%s] using downclock mode from EDID: " , connector->base.base.id, connector->base.name) | |||
98 | "[CONNECTOR:%d:%s] using downclock mode from EDID: ",drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "[CONNECTOR:%d:%s] using downclock mode from EDID: " , connector->base.base.id, connector->base.name) | |||
99 | connector->base.base.id, connector->base.name)drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "[CONNECTOR:%d:%s] using downclock mode from EDID: " , connector->base.base.id, connector->base.name); | |||
100 | drm_mode_debug_printmodeline(downclock_mode); | |||
101 | ||||
102 | return downclock_mode; | |||
103 | } | |||
104 | ||||
105 | struct drm_display_mode * | |||
106 | intel_panel_edid_fixed_mode(struct intel_connector *connector) | |||
107 | { | |||
108 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
109 | const struct drm_display_mode *scan; | |||
110 | struct drm_display_mode *fixed_mode; | |||
111 | ||||
112 | if (list_empty(&connector->base.probed_modes)) | |||
113 | return NULL((void *)0); | |||
114 | ||||
115 | /* prefer fixed mode from EDID if available */ | |||
116 | list_for_each_entry(scan, &connector->base.probed_modes, head)for (scan = ({ const __typeof( ((__typeof(*scan) *)0)->head ) *__mptr = ((&connector->base.probed_modes)->next ); (__typeof(*scan) *)( (char *)__mptr - __builtin_offsetof(__typeof (*scan), head) );}); &scan->head != (&connector-> base.probed_modes); scan = ({ const __typeof( ((__typeof(*scan ) *)0)->head ) *__mptr = (scan->head.next); (__typeof(* scan) *)( (char *)__mptr - __builtin_offsetof(__typeof(*scan) , head) );})) { | |||
117 | if ((scan->type & DRM_MODE_TYPE_PREFERRED(1<<3)) == 0) | |||
118 | continue; | |||
119 | ||||
120 | fixed_mode = drm_mode_duplicate(&dev_priv->drm, scan); | |||
121 | if (!fixed_mode) | |||
122 | return NULL((void *)0); | |||
123 | ||||
124 | drm_dbg_kms(&dev_priv->drm,drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "[CONNECTOR:%d:%s] using preferred mode from EDID: " , connector->base.base.id, connector->base.name) | |||
125 | "[CONNECTOR:%d:%s] using preferred mode from EDID: ",drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "[CONNECTOR:%d:%s] using preferred mode from EDID: " , connector->base.base.id, connector->base.name) | |||
126 | connector->base.base.id, connector->base.name)drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "[CONNECTOR:%d:%s] using preferred mode from EDID: " , connector->base.base.id, connector->base.name); | |||
127 | drm_mode_debug_printmodeline(fixed_mode); | |||
128 | ||||
129 | return fixed_mode; | |||
130 | } | |||
131 | ||||
132 | scan = list_first_entry(&connector->base.probed_modes,({ const __typeof( ((typeof(*scan) *)0)->head ) *__mptr = ( (&connector->base.probed_modes)->next); (typeof(*scan ) *)( (char *)__mptr - __builtin_offsetof(typeof(*scan), head ) );}) | |||
133 | typeof(*scan), head)({ const __typeof( ((typeof(*scan) *)0)->head ) *__mptr = ( (&connector->base.probed_modes)->next); (typeof(*scan ) *)( (char *)__mptr - __builtin_offsetof(typeof(*scan), head ) );}); | |||
134 | ||||
135 | fixed_mode = drm_mode_duplicate(&dev_priv->drm, scan); | |||
136 | if (!fixed_mode) | |||
137 | return NULL((void *)0); | |||
138 | ||||
139 | fixed_mode->type |= DRM_MODE_TYPE_PREFERRED(1<<3); | |||
140 | ||||
141 | drm_dbg_kms(&dev_priv->drm,drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "[CONNECTOR:%d:%s] using first mode from EDID: " , connector->base.base.id, connector->base.name) | |||
142 | "[CONNECTOR:%d:%s] using first mode from EDID: ",drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "[CONNECTOR:%d:%s] using first mode from EDID: " , connector->base.base.id, connector->base.name) | |||
143 | connector->base.base.id, connector->base.name)drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "[CONNECTOR:%d:%s] using first mode from EDID: " , connector->base.base.id, connector->base.name); | |||
144 | drm_mode_debug_printmodeline(fixed_mode); | |||
145 | ||||
146 | return fixed_mode; | |||
147 | } | |||
148 | ||||
149 | struct drm_display_mode * | |||
150 | intel_panel_vbt_fixed_mode(struct intel_connector *connector) | |||
151 | { | |||
152 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
153 | struct drm_display_info *info = &connector->base.display_info; | |||
154 | struct drm_display_mode *fixed_mode; | |||
155 | ||||
156 | if (!dev_priv->vbt.lfp_lvds_vbt_mode) | |||
157 | return NULL((void *)0); | |||
158 | ||||
159 | fixed_mode = drm_mode_duplicate(&dev_priv->drm, | |||
160 | dev_priv->vbt.lfp_lvds_vbt_mode); | |||
161 | if (!fixed_mode) | |||
162 | return NULL((void *)0); | |||
163 | ||||
164 | fixed_mode->type |= DRM_MODE_TYPE_PREFERRED(1<<3); | |||
165 | ||||
166 | drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s] using mode from VBT: ",drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "[CONNECTOR:%d:%s] using mode from VBT: " , connector->base.base.id, connector->base.name) | |||
167 | connector->base.base.id, connector->base.name)drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "[CONNECTOR:%d:%s] using mode from VBT: " , connector->base.base.id, connector->base.name); | |||
168 | drm_mode_debug_printmodeline(fixed_mode); | |||
169 | ||||
170 | info->width_mm = fixed_mode->width_mm; | |||
171 | info->height_mm = fixed_mode->height_mm; | |||
172 | ||||
173 | return fixed_mode; | |||
174 | } | |||
175 | ||||
176 | /* adjusted_mode has been preset to be the panel's fixed mode */ | |||
177 | int intel_pch_panel_fitting(struct intel_crtc_state *crtc_state, | |||
178 | const struct drm_connector_state *conn_state) | |||
179 | { | |||
180 | const struct drm_display_mode *adjusted_mode = | |||
181 | &crtc_state->hw.adjusted_mode; | |||
182 | int x, y, width, height; | |||
183 | ||||
184 | /* Native modes don't need fitting */ | |||
185 | if (adjusted_mode->crtc_hdisplay == crtc_state->pipe_src_w && | |||
186 | adjusted_mode->crtc_vdisplay == crtc_state->pipe_src_h && | |||
187 | crtc_state->output_format != INTEL_OUTPUT_FORMAT_YCBCR420) | |||
188 | return 0; | |||
189 | ||||
190 | switch (conn_state->scaling_mode) { | |||
191 | case DRM_MODE_SCALE_CENTER2: | |||
192 | width = crtc_state->pipe_src_w; | |||
193 | height = crtc_state->pipe_src_h; | |||
194 | x = (adjusted_mode->crtc_hdisplay - width + 1)/2; | |||
195 | y = (adjusted_mode->crtc_vdisplay - height + 1)/2; | |||
196 | break; | |||
197 | ||||
198 | case DRM_MODE_SCALE_ASPECT3: | |||
199 | /* Scale but preserve the aspect ratio */ | |||
200 | { | |||
201 | u32 scaled_width = adjusted_mode->crtc_hdisplay | |||
202 | * crtc_state->pipe_src_h; | |||
203 | u32 scaled_height = crtc_state->pipe_src_w | |||
204 | * adjusted_mode->crtc_vdisplay; | |||
205 | if (scaled_width > scaled_height) { /* pillar */ | |||
206 | width = scaled_height / crtc_state->pipe_src_h; | |||
207 | if (width & 1) | |||
208 | width++; | |||
209 | x = (adjusted_mode->crtc_hdisplay - width + 1) / 2; | |||
210 | y = 0; | |||
211 | height = adjusted_mode->crtc_vdisplay; | |||
212 | } else if (scaled_width < scaled_height) { /* letter */ | |||
213 | height = scaled_width / crtc_state->pipe_src_w; | |||
214 | if (height & 1) | |||
215 | height++; | |||
216 | y = (adjusted_mode->crtc_vdisplay - height + 1) / 2; | |||
217 | x = 0; | |||
218 | width = adjusted_mode->crtc_hdisplay; | |||
219 | } else { | |||
220 | x = y = 0; | |||
221 | width = adjusted_mode->crtc_hdisplay; | |||
222 | height = adjusted_mode->crtc_vdisplay; | |||
223 | } | |||
224 | } | |||
225 | break; | |||
226 | ||||
227 | case DRM_MODE_SCALE_NONE0: | |||
228 | WARN_ON(adjusted_mode->crtc_hdisplay != crtc_state->pipe_src_w)({ int __ret = !!((adjusted_mode->crtc_hdisplay != crtc_state ->pipe_src_w)); if (__ret) printf("%s", "WARN_ON(" "adjusted_mode->crtc_hdisplay != crtc_state->pipe_src_w" ")"); __builtin_expect(!!(__ret), 0); }); | |||
229 | WARN_ON(adjusted_mode->crtc_vdisplay != crtc_state->pipe_src_h)({ int __ret = !!((adjusted_mode->crtc_vdisplay != crtc_state ->pipe_src_h)); if (__ret) printf("%s", "WARN_ON(" "adjusted_mode->crtc_vdisplay != crtc_state->pipe_src_h" ")"); __builtin_expect(!!(__ret), 0); }); | |||
230 | fallthroughdo {} while (0); | |||
231 | case DRM_MODE_SCALE_FULLSCREEN1: | |||
232 | x = y = 0; | |||
233 | width = adjusted_mode->crtc_hdisplay; | |||
234 | height = adjusted_mode->crtc_vdisplay; | |||
235 | break; | |||
236 | ||||
237 | default: | |||
238 | MISSING_CASE(conn_state->scaling_mode)({ int __ret = !!(1); if (__ret) printf("Missing case (%s == %ld)\n" , "conn_state->scaling_mode", (long)(conn_state->scaling_mode )); __builtin_expect(!!(__ret), 0); }); | |||
239 | return -EINVAL22; | |||
240 | } | |||
241 | ||||
242 | drm_rect_init(&crtc_state->pch_pfit.dst, | |||
243 | x, y, width, height); | |||
244 | crtc_state->pch_pfit.enabled = true1; | |||
245 | ||||
246 | return 0; | |||
247 | } | |||
248 | ||||
249 | static void | |||
250 | centre_horizontally(struct drm_display_mode *adjusted_mode, | |||
251 | int width) | |||
252 | { | |||
253 | u32 border, sync_pos, blank_width, sync_width; | |||
254 | ||||
255 | /* keep the hsync and hblank widths constant */ | |||
256 | sync_width = adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start; | |||
257 | blank_width = adjusted_mode->crtc_hblank_end - adjusted_mode->crtc_hblank_start; | |||
258 | sync_pos = (blank_width - sync_width + 1) / 2; | |||
259 | ||||
260 | border = (adjusted_mode->crtc_hdisplay - width + 1) / 2; | |||
261 | border += border & 1; /* make the border even */ | |||
262 | ||||
263 | adjusted_mode->crtc_hdisplay = width; | |||
264 | adjusted_mode->crtc_hblank_start = width + border; | |||
265 | adjusted_mode->crtc_hblank_end = adjusted_mode->crtc_hblank_start + blank_width; | |||
266 | ||||
267 | adjusted_mode->crtc_hsync_start = adjusted_mode->crtc_hblank_start + sync_pos; | |||
268 | adjusted_mode->crtc_hsync_end = adjusted_mode->crtc_hsync_start + sync_width; | |||
269 | } | |||
270 | ||||
271 | static void | |||
272 | centre_vertically(struct drm_display_mode *adjusted_mode, | |||
273 | int height) | |||
274 | { | |||
275 | u32 border, sync_pos, blank_width, sync_width; | |||
276 | ||||
277 | /* keep the vsync and vblank widths constant */ | |||
278 | sync_width = adjusted_mode->crtc_vsync_end - adjusted_mode->crtc_vsync_start; | |||
279 | blank_width = adjusted_mode->crtc_vblank_end - adjusted_mode->crtc_vblank_start; | |||
280 | sync_pos = (blank_width - sync_width + 1) / 2; | |||
281 | ||||
282 | border = (adjusted_mode->crtc_vdisplay - height + 1) / 2; | |||
283 | ||||
284 | adjusted_mode->crtc_vdisplay = height; | |||
285 | adjusted_mode->crtc_vblank_start = height + border; | |||
286 | adjusted_mode->crtc_vblank_end = adjusted_mode->crtc_vblank_start + blank_width; | |||
287 | ||||
288 | adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vblank_start + sync_pos; | |||
289 | adjusted_mode->crtc_vsync_end = adjusted_mode->crtc_vsync_start + sync_width; | |||
290 | } | |||
291 | ||||
292 | static u32 panel_fitter_scaling(u32 source, u32 target) | |||
293 | { | |||
294 | /* | |||
295 | * Floating point operation is not supported. So the FACTOR | |||
296 | * is defined, which can avoid the floating point computation | |||
297 | * when calculating the panel ratio. | |||
298 | */ | |||
299 | #define ACCURACY12 12 | |||
300 | #define FACTOR(1 << 12) (1 << ACCURACY12) | |||
301 | u32 ratio = source * FACTOR(1 << 12) / target; | |||
302 | return (FACTOR(1 << 12) * ratio + FACTOR(1 << 12)/2) / FACTOR(1 << 12); | |||
303 | } | |||
304 | ||||
305 | static void i965_scale_aspect(struct intel_crtc_state *crtc_state, | |||
306 | u32 *pfit_control) | |||
307 | { | |||
308 | const struct drm_display_mode *adjusted_mode = | |||
309 | &crtc_state->hw.adjusted_mode; | |||
310 | u32 scaled_width = adjusted_mode->crtc_hdisplay * | |||
311 | crtc_state->pipe_src_h; | |||
312 | u32 scaled_height = crtc_state->pipe_src_w * | |||
313 | adjusted_mode->crtc_vdisplay; | |||
314 | ||||
315 | /* 965+ is easy, it does everything in hw */ | |||
316 | if (scaled_width > scaled_height) | |||
317 | *pfit_control |= PFIT_ENABLE(1 << 31) | | |||
318 | PFIT_SCALING_PILLAR(2 << 26); | |||
319 | else if (scaled_width < scaled_height) | |||
320 | *pfit_control |= PFIT_ENABLE(1 << 31) | | |||
321 | PFIT_SCALING_LETTER(3 << 26); | |||
322 | else if (adjusted_mode->crtc_hdisplay != crtc_state->pipe_src_w) | |||
323 | *pfit_control |= PFIT_ENABLE(1 << 31) | PFIT_SCALING_AUTO(0 << 26); | |||
324 | } | |||
325 | ||||
326 | static void i9xx_scale_aspect(struct intel_crtc_state *crtc_state, | |||
327 | u32 *pfit_control, u32 *pfit_pgm_ratios, | |||
328 | u32 *border) | |||
329 | { | |||
330 | struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; | |||
331 | u32 scaled_width = adjusted_mode->crtc_hdisplay * | |||
332 | crtc_state->pipe_src_h; | |||
333 | u32 scaled_height = crtc_state->pipe_src_w * | |||
334 | adjusted_mode->crtc_vdisplay; | |||
335 | u32 bits; | |||
336 | ||||
337 | /* | |||
338 | * For earlier chips we have to calculate the scaling | |||
339 | * ratio by hand and program it into the | |||
340 | * PFIT_PGM_RATIO register | |||
341 | */ | |||
342 | if (scaled_width > scaled_height) { /* pillar */ | |||
343 | centre_horizontally(adjusted_mode, | |||
344 | scaled_height / | |||
345 | crtc_state->pipe_src_h); | |||
346 | ||||
347 | *border = LVDS_BORDER_ENABLE(1 << 15); | |||
348 | if (crtc_state->pipe_src_h != adjusted_mode->crtc_vdisplay) { | |||
349 | bits = panel_fitter_scaling(crtc_state->pipe_src_h, | |||
350 | adjusted_mode->crtc_vdisplay); | |||
351 | ||||
352 | *pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT4 | | |||
353 | bits << PFIT_VERT_SCALE_SHIFT20); | |||
354 | *pfit_control |= (PFIT_ENABLE(1 << 31) | | |||
355 | VERT_INTERP_BILINEAR(1 << 10) | | |||
356 | HORIZ_INTERP_BILINEAR(1 << 6)); | |||
357 | } | |||
358 | } else if (scaled_width < scaled_height) { /* letter */ | |||
359 | centre_vertically(adjusted_mode, | |||
360 | scaled_width / | |||
361 | crtc_state->pipe_src_w); | |||
362 | ||||
363 | *border = LVDS_BORDER_ENABLE(1 << 15); | |||
364 | if (crtc_state->pipe_src_w != adjusted_mode->crtc_hdisplay) { | |||
365 | bits = panel_fitter_scaling(crtc_state->pipe_src_w, | |||
366 | adjusted_mode->crtc_hdisplay); | |||
367 | ||||
368 | *pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT4 | | |||
369 | bits << PFIT_VERT_SCALE_SHIFT20); | |||
370 | *pfit_control |= (PFIT_ENABLE(1 << 31) | | |||
371 | VERT_INTERP_BILINEAR(1 << 10) | | |||
372 | HORIZ_INTERP_BILINEAR(1 << 6)); | |||
373 | } | |||
374 | } else { | |||
375 | /* Aspects match, Let hw scale both directions */ | |||
376 | *pfit_control |= (PFIT_ENABLE(1 << 31) | | |||
377 | VERT_AUTO_SCALE(1 << 9) | HORIZ_AUTO_SCALE(1 << 5) | | |||
378 | VERT_INTERP_BILINEAR(1 << 10) | | |||
379 | HORIZ_INTERP_BILINEAR(1 << 6)); | |||
380 | } | |||
381 | } | |||
382 | ||||
383 | int intel_gmch_panel_fitting(struct intel_crtc_state *crtc_state, | |||
384 | const struct drm_connector_state *conn_state) | |||
385 | { | |||
386 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc)({ const __typeof( ((struct intel_crtc *)0)->base ) *__mptr = (crtc_state->uapi.crtc); (struct intel_crtc *)( (char * )__mptr - __builtin_offsetof(struct intel_crtc, base) );}); | |||
387 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(crtc->base.dev); | |||
388 | u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0; | |||
389 | struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; | |||
390 | ||||
391 | /* Native modes don't need fitting */ | |||
392 | if (adjusted_mode->crtc_hdisplay == crtc_state->pipe_src_w && | |||
393 | adjusted_mode->crtc_vdisplay == crtc_state->pipe_src_h) | |||
394 | goto out; | |||
395 | ||||
396 | switch (conn_state->scaling_mode) { | |||
397 | case DRM_MODE_SCALE_CENTER2: | |||
398 | /* | |||
399 | * For centered modes, we have to calculate border widths & | |||
400 | * heights and modify the values programmed into the CRTC. | |||
401 | */ | |||
402 | centre_horizontally(adjusted_mode, crtc_state->pipe_src_w); | |||
403 | centre_vertically(adjusted_mode, crtc_state->pipe_src_h); | |||
404 | border = LVDS_BORDER_ENABLE(1 << 15); | |||
405 | break; | |||
406 | case DRM_MODE_SCALE_ASPECT3: | |||
407 | /* Scale but preserve the aspect ratio */ | |||
408 | if (INTEL_GEN(dev_priv)((&(dev_priv)->__info)->gen) >= 4) | |||
409 | i965_scale_aspect(crtc_state, &pfit_control); | |||
410 | else | |||
411 | i9xx_scale_aspect(crtc_state, &pfit_control, | |||
412 | &pfit_pgm_ratios, &border); | |||
413 | break; | |||
414 | case DRM_MODE_SCALE_FULLSCREEN1: | |||
415 | /* | |||
416 | * Full scaling, even if it changes the aspect ratio. | |||
417 | * Fortunately this is all done for us in hw. | |||
418 | */ | |||
419 | if (crtc_state->pipe_src_h != adjusted_mode->crtc_vdisplay || | |||
420 | crtc_state->pipe_src_w != adjusted_mode->crtc_hdisplay) { | |||
421 | pfit_control |= PFIT_ENABLE(1 << 31); | |||
422 | if (INTEL_GEN(dev_priv)((&(dev_priv)->__info)->gen) >= 4) | |||
423 | pfit_control |= PFIT_SCALING_AUTO(0 << 26); | |||
424 | else | |||
425 | pfit_control |= (VERT_AUTO_SCALE(1 << 9) | | |||
426 | VERT_INTERP_BILINEAR(1 << 10) | | |||
427 | HORIZ_AUTO_SCALE(1 << 5) | | |||
428 | HORIZ_INTERP_BILINEAR(1 << 6)); | |||
429 | } | |||
430 | break; | |||
431 | default: | |||
432 | MISSING_CASE(conn_state->scaling_mode)({ int __ret = !!(1); if (__ret) printf("Missing case (%s == %ld)\n" , "conn_state->scaling_mode", (long)(conn_state->scaling_mode )); __builtin_expect(!!(__ret), 0); }); | |||
433 | return -EINVAL22; | |||
434 | } | |||
435 | ||||
436 | /* 965+ wants fuzzy fitting */ | |||
437 | /* FIXME: handle multiple panels by failing gracefully */ | |||
438 | if (INTEL_GEN(dev_priv)((&(dev_priv)->__info)->gen) >= 4) | |||
439 | pfit_control |= PFIT_PIPE(crtc->pipe)((crtc->pipe) << 29) | PFIT_FILTER_FUZZY(0 << 24); | |||
440 | ||||
441 | out: | |||
442 | if ((pfit_control & PFIT_ENABLE(1 << 31)) == 0) { | |||
443 | pfit_control = 0; | |||
444 | pfit_pgm_ratios = 0; | |||
445 | } | |||
446 | ||||
447 | /* Make sure pre-965 set dither correctly for 18bpp panels. */ | |||
448 | if (INTEL_GEN(dev_priv)((&(dev_priv)->__info)->gen) < 4 && crtc_state->pipe_bpp == 18) | |||
449 | pfit_control |= PANEL_8TO6_DITHER_ENABLE(1 << 3); | |||
450 | ||||
451 | crtc_state->gmch_pfit.control = pfit_control; | |||
452 | crtc_state->gmch_pfit.pgm_ratios = pfit_pgm_ratios; | |||
453 | crtc_state->gmch_pfit.lvds_border_bits = border; | |||
454 | ||||
455 | return 0; | |||
456 | } | |||
457 | ||||
458 | /** | |||
459 | * scale - scale values from one range to another | |||
460 | * @source_val: value in range [@source_min..@source_max] | |||
461 | * @source_min: minimum legal value for @source_val | |||
462 | * @source_max: maximum legal value for @source_val | |||
463 | * @target_min: corresponding target value for @source_min | |||
464 | * @target_max: corresponding target value for @source_max | |||
465 | * | |||
466 | * Return @source_val in range [@source_min..@source_max] scaled to range | |||
467 | * [@target_min..@target_max]. | |||
468 | */ | |||
469 | static u32 scale(u32 source_val, | |||
470 | u32 source_min, u32 source_max, | |||
471 | u32 target_min, u32 target_max) | |||
472 | { | |||
473 | u64 target_val; | |||
474 | ||||
475 | WARN_ON(source_min > source_max)({ int __ret = !!((source_min > source_max)); if (__ret) printf ("%s", "WARN_ON(" "source_min > source_max" ")"); __builtin_expect (!!(__ret), 0); }); | |||
476 | WARN_ON(target_min > target_max)({ int __ret = !!((target_min > target_max)); if (__ret) printf ("%s", "WARN_ON(" "target_min > target_max" ")"); __builtin_expect (!!(__ret), 0); }); | |||
477 | ||||
478 | /* defensive */ | |||
479 | source_val = clamp(source_val, source_min, source_max)({ __typeof(source_val) __min_a = (({ __typeof(source_val) __max_a = (source_val); __typeof(source_val) __max_b = (source_min); __max_a > __max_b ? __max_a : __max_b; })); __typeof(source_val ) __min_b = (source_max); __min_a < __min_b ? __min_a : __min_b ; }); | |||
480 | ||||
481 | /* avoid overflows */ | |||
482 | target_val = mul_u32_u32(source_val - source_min, | |||
483 | target_max - target_min); | |||
484 | target_val = DIV_ROUND_CLOSEST_ULL(target_val, source_max - source_min)(((target_val) + ((source_max - source_min) / 2)) / (source_max - source_min)); | |||
| ||||
485 | target_val += target_min; | |||
486 | ||||
487 | return target_val; | |||
488 | } | |||
489 | ||||
490 | /* Scale user_level in range [0..user_max] to [0..hw_max], clamping the result | |||
491 | * to [hw_min..hw_max]. */ | |||
492 | static u32 clamp_user_to_hw(struct intel_connector *connector, | |||
493 | u32 user_level, u32 user_max) | |||
494 | { | |||
495 | struct intel_panel *panel = &connector->panel; | |||
496 | u32 hw_level; | |||
497 | ||||
498 | hw_level = scale(user_level, 0, user_max, 0, panel->backlight.max); | |||
499 | hw_level = clamp(hw_level, panel->backlight.min, panel->backlight.max)({ __typeof(hw_level) __min_a = (({ __typeof(hw_level) __max_a = (hw_level); __typeof(hw_level) __max_b = (panel->backlight .min); __max_a > __max_b ? __max_a : __max_b; })); __typeof (hw_level) __min_b = (panel->backlight.max); __min_a < __min_b ? __min_a : __min_b; }); | |||
500 | ||||
501 | return hw_level; | |||
502 | } | |||
503 | ||||
504 | /* Scale hw_level in range [hw_min..hw_max] to [0..user_max]. */ | |||
505 | static u32 scale_hw_to_user(struct intel_connector *connector, | |||
506 | u32 hw_level, u32 user_max) | |||
507 | { | |||
508 | struct intel_panel *panel = &connector->panel; | |||
509 | ||||
510 | return scale(hw_level, panel->backlight.min, panel->backlight.max, | |||
511 | 0, user_max); | |||
512 | } | |||
513 | ||||
514 | static u32 intel_panel_compute_brightness(struct intel_connector *connector, | |||
515 | u32 val) | |||
516 | { | |||
517 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
518 | struct intel_panel *panel = &connector->panel; | |||
519 | ||||
520 | drm_WARN_ON(&dev_priv->drm, panel->backlight.max == 0)({ int __ret = !!((panel->backlight.max == 0)); if (__ret) printf("%s %s: " "%s", dev_driver_string(((&dev_priv-> drm))->dev), "", "drm_WARN_ON(" "panel->backlight.max == 0" ")"); __builtin_expect(!!(__ret), 0); }); | |||
521 | ||||
522 | if (dev_priv->params.invert_brightness < 0) | |||
523 | return val; | |||
524 | ||||
525 | if (dev_priv->params.invert_brightness > 0 || | |||
526 | dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS(1<<2)) { | |||
527 | return panel->backlight.max - val + panel->backlight.min; | |||
528 | } | |||
529 | ||||
530 | return val; | |||
531 | } | |||
532 | ||||
533 | static u32 lpt_get_backlight(struct intel_connector *connector) | |||
534 | { | |||
535 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
536 | ||||
537 | return intel_de_read(dev_priv, BLC_PWM_PCH_CTL2((const i915_reg_t){ .reg = (0xc8254) })) & BACKLIGHT_DUTY_CYCLE_MASK(0xffff); | |||
538 | } | |||
539 | ||||
540 | static u32 pch_get_backlight(struct intel_connector *connector) | |||
541 | { | |||
542 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
543 | ||||
544 | return intel_de_read(dev_priv, BLC_PWM_CPU_CTL((const i915_reg_t){ .reg = (0x48254) })) & BACKLIGHT_DUTY_CYCLE_MASK(0xffff); | |||
545 | } | |||
546 | ||||
547 | static u32 i9xx_get_backlight(struct intel_connector *connector) | |||
548 | { | |||
549 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
550 | struct intel_panel *panel = &connector->panel; | |||
551 | u32 val; | |||
552 | ||||
553 | val = intel_de_read(dev_priv, BLC_PWM_CTL((const i915_reg_t){ .reg = (((&(dev_priv)->__info)-> display_mmio_offset) + 0x61254) })) & BACKLIGHT_DUTY_CYCLE_MASK(0xffff); | |||
554 | if (INTEL_GEN(dev_priv)((&(dev_priv)->__info)->gen) < 4) | |||
555 | val >>= 1; | |||
556 | ||||
557 | if (panel->backlight.combination_mode) { | |||
558 | u8 lbpc; | |||
559 | ||||
560 | pci_read_config_byte(dev_priv->drm.pdev, LBPC0xf4, &lbpc); | |||
561 | val *= lbpc; | |||
562 | } | |||
563 | ||||
564 | return val; | |||
565 | } | |||
566 | ||||
567 | static u32 _vlv_get_backlight(struct drm_i915_privateinteldrm_softc *dev_priv, enum pipe pipe) | |||
568 | { | |||
569 | if (drm_WARN_ON(&dev_priv->drm, pipe != PIPE_A && pipe != PIPE_B)({ int __ret = !!((pipe != PIPE_A && pipe != PIPE_B)) ; if (__ret) printf("%s %s: " "%s", dev_driver_string(((& dev_priv->drm))->dev), "", "drm_WARN_ON(" "pipe != PIPE_A && pipe != PIPE_B" ")"); __builtin_expect(!!(__ret), 0); })) | |||
570 | return 0; | |||
571 | ||||
572 | return intel_de_read(dev_priv, VLV_BLC_PWM_CTL(pipe)((const i915_reg_t){ .reg = ((((((&(dev_priv)->__info) ->display_mmio_offset) + 0x61254)) + (pipe) * (((((&(dev_priv )->__info)->display_mmio_offset) + 0x61354)) - ((((& (dev_priv)->__info)->display_mmio_offset) + 0x61254)))) ) })) & BACKLIGHT_DUTY_CYCLE_MASK(0xffff); | |||
573 | } | |||
574 | ||||
575 | static u32 vlv_get_backlight(struct intel_connector *connector) | |||
576 | { | |||
577 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
578 | enum pipe pipe = intel_connector_get_pipe(connector); | |||
579 | ||||
580 | return _vlv_get_backlight(dev_priv, pipe); | |||
581 | } | |||
582 | ||||
583 | static u32 bxt_get_backlight(struct intel_connector *connector) | |||
584 | { | |||
585 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
586 | struct intel_panel *panel = &connector->panel; | |||
587 | ||||
588 | return intel_de_read(dev_priv, | |||
589 | BXT_BLC_PWM_DUTY(panel->backlight.controller)((const i915_reg_t){ .reg = (((0xC8258) + (panel->backlight .controller) * ((0xC8358) - (0xC8258)))) })); | |||
590 | } | |||
591 | ||||
592 | static u32 pwm_get_backlight(struct intel_connector *connector) | |||
593 | { | |||
594 | STUB()do { printf("%s: stub\n", __func__); } while(0); | |||
595 | return 0; | |||
596 | #ifdef notyet | |||
597 | struct intel_panel *panel = &connector->panel; | |||
598 | struct pwm_state state; | |||
599 | ||||
600 | pwm_get_state(panel->backlight.pwm, &state); | |||
601 | return pwm_get_relative_duty_cycle(&state, 100); | |||
602 | #endif | |||
603 | } | |||
604 | ||||
605 | static void lpt_set_backlight(const struct drm_connector_state *conn_state, u32 level) | |||
606 | { | |||
607 | struct intel_connector *connector = to_intel_connector(conn_state->connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (conn_state->connector); (struct intel_connector * )( (char *)__mptr - __builtin_offsetof(struct intel_connector , base) );}); | |||
608 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
609 | ||||
610 | u32 val = intel_de_read(dev_priv, BLC_PWM_PCH_CTL2((const i915_reg_t){ .reg = (0xc8254) })) & ~BACKLIGHT_DUTY_CYCLE_MASK(0xffff); | |||
611 | intel_de_write(dev_priv, BLC_PWM_PCH_CTL2((const i915_reg_t){ .reg = (0xc8254) }), val | level); | |||
612 | } | |||
613 | ||||
614 | static void pch_set_backlight(const struct drm_connector_state *conn_state, u32 level) | |||
615 | { | |||
616 | struct intel_connector *connector = to_intel_connector(conn_state->connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (conn_state->connector); (struct intel_connector * )( (char *)__mptr - __builtin_offsetof(struct intel_connector , base) );}); | |||
617 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
618 | u32 tmp; | |||
619 | ||||
620 | tmp = intel_de_read(dev_priv, BLC_PWM_CPU_CTL((const i915_reg_t){ .reg = (0x48254) })) & ~BACKLIGHT_DUTY_CYCLE_MASK(0xffff); | |||
621 | intel_de_write(dev_priv, BLC_PWM_CPU_CTL((const i915_reg_t){ .reg = (0x48254) }), tmp | level); | |||
622 | } | |||
623 | ||||
624 | static void i9xx_set_backlight(const struct drm_connector_state *conn_state, u32 level) | |||
625 | { | |||
626 | struct intel_connector *connector = to_intel_connector(conn_state->connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (conn_state->connector); (struct intel_connector * )( (char *)__mptr - __builtin_offsetof(struct intel_connector , base) );}); | |||
627 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
628 | struct intel_panel *panel = &connector->panel; | |||
629 | u32 tmp, mask; | |||
630 | ||||
631 | drm_WARN_ON(&dev_priv->drm, panel->backlight.max == 0)({ int __ret = !!((panel->backlight.max == 0)); if (__ret) printf("%s %s: " "%s", dev_driver_string(((&dev_priv-> drm))->dev), "", "drm_WARN_ON(" "panel->backlight.max == 0" ")"); __builtin_expect(!!(__ret), 0); }); | |||
632 | ||||
633 | if (panel->backlight.combination_mode) { | |||
634 | u8 lbpc; | |||
635 | ||||
636 | lbpc = level * 0xfe / panel->backlight.max + 1; | |||
637 | level /= lbpc; | |||
638 | pci_write_config_byte(dev_priv->drm.pdev, LBPC0xf4, lbpc); | |||
639 | } | |||
640 | ||||
641 | if (IS_GEN(dev_priv, 4)(0 + (&(dev_priv)->__info)->gen == (4))) { | |||
642 | mask = BACKLIGHT_DUTY_CYCLE_MASK(0xffff); | |||
643 | } else { | |||
644 | level <<= 1; | |||
645 | mask = BACKLIGHT_DUTY_CYCLE_MASK_PNV(0xfffe); | |||
646 | } | |||
647 | ||||
648 | tmp = intel_de_read(dev_priv, BLC_PWM_CTL((const i915_reg_t){ .reg = (((&(dev_priv)->__info)-> display_mmio_offset) + 0x61254) })) & ~mask; | |||
649 | intel_de_write(dev_priv, BLC_PWM_CTL((const i915_reg_t){ .reg = (((&(dev_priv)->__info)-> display_mmio_offset) + 0x61254) }), tmp | level); | |||
650 | } | |||
651 | ||||
652 | static void vlv_set_backlight(const struct drm_connector_state *conn_state, u32 level) | |||
653 | { | |||
654 | struct intel_connector *connector = to_intel_connector(conn_state->connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (conn_state->connector); (struct intel_connector * )( (char *)__mptr - __builtin_offsetof(struct intel_connector , base) );}); | |||
655 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
656 | enum pipe pipe = to_intel_crtc(conn_state->crtc)({ const __typeof( ((struct intel_crtc *)0)->base ) *__mptr = (conn_state->crtc); (struct intel_crtc *)( (char *)__mptr - __builtin_offsetof(struct intel_crtc, base) );})->pipe; | |||
657 | u32 tmp; | |||
658 | ||||
659 | tmp = intel_de_read(dev_priv, VLV_BLC_PWM_CTL(pipe)((const i915_reg_t){ .reg = ((((((&(dev_priv)->__info) ->display_mmio_offset) + 0x61254)) + (pipe) * (((((&(dev_priv )->__info)->display_mmio_offset) + 0x61354)) - ((((& (dev_priv)->__info)->display_mmio_offset) + 0x61254)))) ) })) & ~BACKLIGHT_DUTY_CYCLE_MASK(0xffff); | |||
660 | intel_de_write(dev_priv, VLV_BLC_PWM_CTL(pipe)((const i915_reg_t){ .reg = ((((((&(dev_priv)->__info) ->display_mmio_offset) + 0x61254)) + (pipe) * (((((&(dev_priv )->__info)->display_mmio_offset) + 0x61354)) - ((((& (dev_priv)->__info)->display_mmio_offset) + 0x61254)))) ) }), tmp | level); | |||
661 | } | |||
662 | ||||
663 | static void bxt_set_backlight(const struct drm_connector_state *conn_state, u32 level) | |||
664 | { | |||
665 | struct intel_connector *connector = to_intel_connector(conn_state->connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (conn_state->connector); (struct intel_connector * )( (char *)__mptr - __builtin_offsetof(struct intel_connector , base) );}); | |||
666 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
667 | struct intel_panel *panel = &connector->panel; | |||
668 | ||||
669 | intel_de_write(dev_priv, | |||
670 | BXT_BLC_PWM_DUTY(panel->backlight.controller)((const i915_reg_t){ .reg = (((0xC8258) + (panel->backlight .controller) * ((0xC8358) - (0xC8258)))) }), level); | |||
671 | } | |||
672 | ||||
673 | static void pwm_set_backlight(const struct drm_connector_state *conn_state, u32 level) | |||
674 | { | |||
675 | STUB()do { printf("%s: stub\n", __func__); } while(0); | |||
676 | #ifdef notyet | |||
677 | struct intel_panel *panel = &to_intel_connector(conn_state->connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (conn_state->connector); (struct intel_connector * )( (char *)__mptr - __builtin_offsetof(struct intel_connector , base) );})->panel; | |||
678 | ||||
679 | pwm_set_relative_duty_cycle(&panel->backlight.pwm_state, level, 100); | |||
680 | pwm_apply_state(panel->backlight.pwm, &panel->backlight.pwm_state); | |||
681 | #endif | |||
682 | } | |||
683 | ||||
684 | static void | |||
685 | intel_panel_actually_set_backlight(const struct drm_connector_state *conn_state, u32 level) | |||
686 | { | |||
687 | struct intel_connector *connector = to_intel_connector(conn_state->connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (conn_state->connector); (struct intel_connector * )( (char *)__mptr - __builtin_offsetof(struct intel_connector , base) );}); | |||
688 | struct drm_i915_privateinteldrm_softc *i915 = to_i915(connector->base.dev); | |||
689 | struct intel_panel *panel = &connector->panel; | |||
690 | ||||
691 | drm_dbg_kms(&i915->drm, "set backlight PWM = %d\n", level)drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "set backlight PWM = %d\n" , level); | |||
692 | ||||
693 | level = intel_panel_compute_brightness(connector, level); | |||
694 | panel->backlight.set(conn_state, level); | |||
695 | } | |||
696 | ||||
697 | /* set backlight brightness to level in range [0..max], assuming hw min is | |||
698 | * respected. | |||
699 | */ | |||
700 | void intel_panel_set_backlight_acpi(const struct drm_connector_state *conn_state, | |||
701 | u32 user_level, u32 user_max) | |||
702 | { | |||
703 | struct intel_connector *connector = to_intel_connector(conn_state->connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (conn_state->connector); (struct intel_connector * )( (char *)__mptr - __builtin_offsetof(struct intel_connector , base) );}); | |||
704 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
705 | struct intel_panel *panel = &connector->panel; | |||
706 | u32 hw_level; | |||
707 | ||||
708 | /* | |||
709 | * Lack of crtc may occur during driver init because | |||
710 | * connection_mutex isn't held across the entire backlight | |||
711 | * setup + modeset readout, and the BIOS can issue the | |||
712 | * requests at any time. | |||
713 | */ | |||
714 | if (!panel->backlight.present || !conn_state->crtc) | |||
715 | return; | |||
716 | ||||
717 | mutex_lock(&dev_priv->backlight_lock)rw_enter_write(&dev_priv->backlight_lock); | |||
718 | ||||
719 | drm_WARN_ON(&dev_priv->drm, panel->backlight.max == 0)({ int __ret = !!((panel->backlight.max == 0)); if (__ret) printf("%s %s: " "%s", dev_driver_string(((&dev_priv-> drm))->dev), "", "drm_WARN_ON(" "panel->backlight.max == 0" ")"); __builtin_expect(!!(__ret), 0); }); | |||
720 | ||||
721 | hw_level = clamp_user_to_hw(connector, user_level, user_max); | |||
722 | panel->backlight.level = hw_level; | |||
723 | ||||
724 | if (panel->backlight.device) | |||
725 | panel->backlight.device->props.brightness = | |||
726 | scale_hw_to_user(connector, | |||
727 | panel->backlight.level, | |||
728 | panel->backlight.device->props.max_brightness); | |||
729 | ||||
730 | if (panel->backlight.enabled) | |||
731 | intel_panel_actually_set_backlight(conn_state, hw_level); | |||
732 | ||||
733 | mutex_unlock(&dev_priv->backlight_lock)rw_exit_write(&dev_priv->backlight_lock); | |||
734 | } | |||
735 | ||||
736 | static void lpt_disable_backlight(const struct drm_connector_state *old_conn_state) | |||
737 | { | |||
738 | struct intel_connector *connector = to_intel_connector(old_conn_state->connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (old_conn_state->connector); (struct intel_connector *)( (char *)__mptr - __builtin_offsetof(struct intel_connector , base) );}); | |||
739 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
740 | u32 tmp; | |||
741 | ||||
742 | intel_panel_actually_set_backlight(old_conn_state, 0); | |||
743 | ||||
744 | /* | |||
745 | * Although we don't support or enable CPU PWM with LPT/SPT based | |||
746 | * systems, it may have been enabled prior to loading the | |||
747 | * driver. Disable to avoid warnings on LCPLL disable. | |||
748 | * | |||
749 | * This needs rework if we need to add support for CPU PWM on PCH split | |||
750 | * platforms. | |||
751 | */ | |||
752 | tmp = intel_de_read(dev_priv, BLC_PWM_CPU_CTL2((const i915_reg_t){ .reg = (0x48250) })); | |||
753 | if (tmp & BLM_PWM_ENABLE(1 << 31)) { | |||
754 | drm_dbg_kms(&dev_priv->drm,drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "cpu backlight was enabled, disabling\n" ) | |||
755 | "cpu backlight was enabled, disabling\n")drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "cpu backlight was enabled, disabling\n" ); | |||
756 | intel_de_write(dev_priv, BLC_PWM_CPU_CTL2((const i915_reg_t){ .reg = (0x48250) }), | |||
757 | tmp & ~BLM_PWM_ENABLE(1 << 31)); | |||
758 | } | |||
759 | ||||
760 | tmp = intel_de_read(dev_priv, BLC_PWM_PCH_CTL1((const i915_reg_t){ .reg = (0xc8250) })); | |||
761 | intel_de_write(dev_priv, BLC_PWM_PCH_CTL1((const i915_reg_t){ .reg = (0xc8250) }), tmp & ~BLM_PCH_PWM_ENABLE(1 << 31)); | |||
762 | } | |||
763 | ||||
764 | static void pch_disable_backlight(const struct drm_connector_state *old_conn_state) | |||
765 | { | |||
766 | struct intel_connector *connector = to_intel_connector(old_conn_state->connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (old_conn_state->connector); (struct intel_connector *)( (char *)__mptr - __builtin_offsetof(struct intel_connector , base) );}); | |||
767 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
768 | u32 tmp; | |||
769 | ||||
770 | intel_panel_actually_set_backlight(old_conn_state, 0); | |||
771 | ||||
772 | tmp = intel_de_read(dev_priv, BLC_PWM_CPU_CTL2((const i915_reg_t){ .reg = (0x48250) })); | |||
773 | intel_de_write(dev_priv, BLC_PWM_CPU_CTL2((const i915_reg_t){ .reg = (0x48250) }), tmp & ~BLM_PWM_ENABLE(1 << 31)); | |||
774 | ||||
775 | tmp = intel_de_read(dev_priv, BLC_PWM_PCH_CTL1((const i915_reg_t){ .reg = (0xc8250) })); | |||
776 | intel_de_write(dev_priv, BLC_PWM_PCH_CTL1((const i915_reg_t){ .reg = (0xc8250) }), tmp & ~BLM_PCH_PWM_ENABLE(1 << 31)); | |||
777 | } | |||
778 | ||||
779 | static void i9xx_disable_backlight(const struct drm_connector_state *old_conn_state) | |||
780 | { | |||
781 | intel_panel_actually_set_backlight(old_conn_state, 0); | |||
782 | } | |||
783 | ||||
784 | static void i965_disable_backlight(const struct drm_connector_state *old_conn_state) | |||
785 | { | |||
786 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(old_conn_state->connector->dev); | |||
787 | u32 tmp; | |||
788 | ||||
789 | intel_panel_actually_set_backlight(old_conn_state, 0); | |||
790 | ||||
791 | tmp = intel_de_read(dev_priv, BLC_PWM_CTL2((const i915_reg_t){ .reg = (((&(dev_priv)->__info)-> display_mmio_offset) + 0x61250) })); | |||
792 | intel_de_write(dev_priv, BLC_PWM_CTL2((const i915_reg_t){ .reg = (((&(dev_priv)->__info)-> display_mmio_offset) + 0x61250) }), tmp & ~BLM_PWM_ENABLE(1 << 31)); | |||
793 | } | |||
794 | ||||
795 | static void vlv_disable_backlight(const struct drm_connector_state *old_conn_state) | |||
796 | { | |||
797 | struct intel_connector *connector = to_intel_connector(old_conn_state->connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (old_conn_state->connector); (struct intel_connector *)( (char *)__mptr - __builtin_offsetof(struct intel_connector , base) );}); | |||
798 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
799 | enum pipe pipe = to_intel_crtc(old_conn_state->crtc)({ const __typeof( ((struct intel_crtc *)0)->base ) *__mptr = (old_conn_state->crtc); (struct intel_crtc *)( (char *) __mptr - __builtin_offsetof(struct intel_crtc, base) );})->pipe; | |||
800 | u32 tmp; | |||
801 | ||||
802 | intel_panel_actually_set_backlight(old_conn_state, 0); | |||
803 | ||||
804 | tmp = intel_de_read(dev_priv, VLV_BLC_PWM_CTL2(pipe)((const i915_reg_t){ .reg = ((((((&(dev_priv)->__info) ->display_mmio_offset) + 0x61250)) + (pipe) * (((((&(dev_priv )->__info)->display_mmio_offset) + 0x61350)) - ((((& (dev_priv)->__info)->display_mmio_offset) + 0x61250)))) ) })); | |||
805 | intel_de_write(dev_priv, VLV_BLC_PWM_CTL2(pipe)((const i915_reg_t){ .reg = ((((((&(dev_priv)->__info) ->display_mmio_offset) + 0x61250)) + (pipe) * (((((&(dev_priv )->__info)->display_mmio_offset) + 0x61350)) - ((((& (dev_priv)->__info)->display_mmio_offset) + 0x61250)))) ) }), | |||
806 | tmp & ~BLM_PWM_ENABLE(1 << 31)); | |||
807 | } | |||
808 | ||||
809 | static void bxt_disable_backlight(const struct drm_connector_state *old_conn_state) | |||
810 | { | |||
811 | struct intel_connector *connector = to_intel_connector(old_conn_state->connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (old_conn_state->connector); (struct intel_connector *)( (char *)__mptr - __builtin_offsetof(struct intel_connector , base) );}); | |||
812 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
813 | struct intel_panel *panel = &connector->panel; | |||
814 | u32 tmp, val; | |||
815 | ||||
816 | intel_panel_actually_set_backlight(old_conn_state, 0); | |||
817 | ||||
818 | tmp = intel_de_read(dev_priv, | |||
819 | BXT_BLC_PWM_CTL(panel->backlight.controller)((const i915_reg_t){ .reg = (((0xC8250) + (panel->backlight .controller) * ((0xC8350) - (0xC8250)))) })); | |||
820 | intel_de_write(dev_priv, BXT_BLC_PWM_CTL(panel->backlight.controller)((const i915_reg_t){ .reg = (((0xC8250) + (panel->backlight .controller) * ((0xC8350) - (0xC8250)))) }), | |||
821 | tmp & ~BXT_BLC_PWM_ENABLE(1 << 31)); | |||
822 | ||||
823 | if (panel->backlight.controller == 1) { | |||
824 | val = intel_de_read(dev_priv, UTIL_PIN_CTL((const i915_reg_t){ .reg = (0x48400) })); | |||
825 | val &= ~UTIL_PIN_ENABLE(1 << 31); | |||
826 | intel_de_write(dev_priv, UTIL_PIN_CTL((const i915_reg_t){ .reg = (0x48400) }), val); | |||
827 | } | |||
828 | } | |||
829 | ||||
830 | static void cnp_disable_backlight(const struct drm_connector_state *old_conn_state) | |||
831 | { | |||
832 | struct intel_connector *connector = to_intel_connector(old_conn_state->connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (old_conn_state->connector); (struct intel_connector *)( (char *)__mptr - __builtin_offsetof(struct intel_connector , base) );}); | |||
833 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
834 | struct intel_panel *panel = &connector->panel; | |||
835 | u32 tmp; | |||
836 | ||||
837 | intel_panel_actually_set_backlight(old_conn_state, 0); | |||
838 | ||||
839 | tmp = intel_de_read(dev_priv, | |||
840 | BXT_BLC_PWM_CTL(panel->backlight.controller)((const i915_reg_t){ .reg = (((0xC8250) + (panel->backlight .controller) * ((0xC8350) - (0xC8250)))) })); | |||
841 | intel_de_write(dev_priv, BXT_BLC_PWM_CTL(panel->backlight.controller)((const i915_reg_t){ .reg = (((0xC8250) + (panel->backlight .controller) * ((0xC8350) - (0xC8250)))) }), | |||
842 | tmp & ~BXT_BLC_PWM_ENABLE(1 << 31)); | |||
843 | } | |||
844 | ||||
845 | static void pwm_disable_backlight(const struct drm_connector_state *old_conn_state) | |||
846 | { | |||
847 | STUB()do { printf("%s: stub\n", __func__); } while(0); | |||
848 | #ifdef notyet | |||
849 | struct intel_connector *connector = to_intel_connector(old_conn_state->connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (old_conn_state->connector); (struct intel_connector *)( (char *)__mptr - __builtin_offsetof(struct intel_connector , base) );}); | |||
850 | struct intel_panel *panel = &connector->panel; | |||
851 | ||||
852 | panel->backlight.pwm_state.enabled = false0; | |||
853 | pwm_apply_state(panel->backlight.pwm, &panel->backlight.pwm_state); | |||
854 | #endif | |||
855 | } | |||
856 | ||||
857 | void intel_panel_disable_backlight(const struct drm_connector_state *old_conn_state) | |||
858 | { | |||
859 | struct intel_connector *connector = to_intel_connector(old_conn_state->connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (old_conn_state->connector); (struct intel_connector *)( (char *)__mptr - __builtin_offsetof(struct intel_connector , base) );}); | |||
860 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
861 | struct intel_panel *panel = &connector->panel; | |||
862 | ||||
863 | if (!panel->backlight.present) | |||
864 | return; | |||
865 | ||||
866 | /* | |||
867 | * Do not disable backlight on the vga_switcheroo path. When switching | |||
868 | * away from i915, the other client may depend on i915 to handle the | |||
869 | * backlight. This will leave the backlight on unnecessarily when | |||
870 | * another client is not activated. | |||
871 | */ | |||
872 | if (dev_priv->drm.switch_power_state == DRM_SWITCH_POWER_CHANGING) { | |||
873 | drm_dbg_kms(&dev_priv->drm,drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "Skipping backlight disable on vga switch\n" ) | |||
874 | "Skipping backlight disable on vga switch\n")drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "Skipping backlight disable on vga switch\n" ); | |||
875 | return; | |||
876 | } | |||
877 | ||||
878 | mutex_lock(&dev_priv->backlight_lock)rw_enter_write(&dev_priv->backlight_lock); | |||
879 | ||||
880 | if (panel->backlight.device) | |||
881 | panel->backlight.device->props.power = FB_BLANK_POWERDOWN4; | |||
882 | panel->backlight.enabled = false0; | |||
883 | panel->backlight.disable(old_conn_state); | |||
884 | ||||
885 | mutex_unlock(&dev_priv->backlight_lock)rw_exit_write(&dev_priv->backlight_lock); | |||
886 | } | |||
887 | ||||
888 | static void lpt_enable_backlight(const struct intel_crtc_state *crtc_state, | |||
889 | const struct drm_connector_state *conn_state) | |||
890 | { | |||
891 | struct intel_connector *connector = to_intel_connector(conn_state->connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (conn_state->connector); (struct intel_connector * )( (char *)__mptr - __builtin_offsetof(struct intel_connector , base) );}); | |||
892 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
893 | struct intel_panel *panel = &connector->panel; | |||
894 | u32 pch_ctl1, pch_ctl2, schicken; | |||
895 | ||||
896 | pch_ctl1 = intel_de_read(dev_priv, BLC_PWM_PCH_CTL1((const i915_reg_t){ .reg = (0xc8250) })); | |||
897 | if (pch_ctl1 & BLM_PCH_PWM_ENABLE(1 << 31)) { | |||
898 | drm_dbg_kms(&dev_priv->drm, "pch backlight already enabled\n")drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "pch backlight already enabled\n" ); | |||
899 | pch_ctl1 &= ~BLM_PCH_PWM_ENABLE(1 << 31); | |||
900 | intel_de_write(dev_priv, BLC_PWM_PCH_CTL1((const i915_reg_t){ .reg = (0xc8250) }), pch_ctl1); | |||
901 | } | |||
902 | ||||
903 | if (HAS_PCH_LPT(dev_priv)(((dev_priv)->pch_type) == PCH_LPT)) { | |||
904 | schicken = intel_de_read(dev_priv, SOUTH_CHICKEN2((const i915_reg_t){ .reg = (0xc2004) })); | |||
905 | if (panel->backlight.alternate_pwm_increment) | |||
906 | schicken |= LPT_PWM_GRANULARITY(1 << 5); | |||
907 | else | |||
908 | schicken &= ~LPT_PWM_GRANULARITY(1 << 5); | |||
909 | intel_de_write(dev_priv, SOUTH_CHICKEN2((const i915_reg_t){ .reg = (0xc2004) }), schicken); | |||
910 | } else { | |||
911 | schicken = intel_de_read(dev_priv, SOUTH_CHICKEN1((const i915_reg_t){ .reg = (0xc2000) })); | |||
912 | if (panel->backlight.alternate_pwm_increment) | |||
913 | schicken |= SPT_PWM_GRANULARITY(1 << 0); | |||
914 | else | |||
915 | schicken &= ~SPT_PWM_GRANULARITY(1 << 0); | |||
916 | intel_de_write(dev_priv, SOUTH_CHICKEN1((const i915_reg_t){ .reg = (0xc2000) }), schicken); | |||
917 | } | |||
918 | ||||
919 | pch_ctl2 = panel->backlight.max << 16; | |||
920 | intel_de_write(dev_priv, BLC_PWM_PCH_CTL2((const i915_reg_t){ .reg = (0xc8254) }), pch_ctl2); | |||
921 | ||||
922 | pch_ctl1 = 0; | |||
923 | if (panel->backlight.active_low_pwm) | |||
924 | pch_ctl1 |= BLM_PCH_POLARITY(1 << 29); | |||
925 | ||||
926 | /* After LPT, override is the default. */ | |||
927 | if (HAS_PCH_LPT(dev_priv)(((dev_priv)->pch_type) == PCH_LPT)) | |||
928 | pch_ctl1 |= BLM_PCH_OVERRIDE_ENABLE(1 << 30); | |||
929 | ||||
930 | intel_de_write(dev_priv, BLC_PWM_PCH_CTL1((const i915_reg_t){ .reg = (0xc8250) }), pch_ctl1); | |||
931 | intel_de_posting_read(dev_priv, BLC_PWM_PCH_CTL1((const i915_reg_t){ .reg = (0xc8250) })); | |||
932 | intel_de_write(dev_priv, BLC_PWM_PCH_CTL1((const i915_reg_t){ .reg = (0xc8250) }), | |||
933 | pch_ctl1 | BLM_PCH_PWM_ENABLE(1 << 31)); | |||
934 | ||||
935 | /* This won't stick until the above enable. */ | |||
936 | intel_panel_actually_set_backlight(conn_state, panel->backlight.level); | |||
937 | } | |||
938 | ||||
939 | static void pch_enable_backlight(const struct intel_crtc_state *crtc_state, | |||
940 | const struct drm_connector_state *conn_state) | |||
941 | { | |||
942 | struct intel_connector *connector = to_intel_connector(conn_state->connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (conn_state->connector); (struct intel_connector * )( (char *)__mptr - __builtin_offsetof(struct intel_connector , base) );}); | |||
943 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
944 | struct intel_panel *panel = &connector->panel; | |||
945 | enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; | |||
946 | u32 cpu_ctl2, pch_ctl1, pch_ctl2; | |||
947 | ||||
948 | cpu_ctl2 = intel_de_read(dev_priv, BLC_PWM_CPU_CTL2((const i915_reg_t){ .reg = (0x48250) })); | |||
949 | if (cpu_ctl2 & BLM_PWM_ENABLE(1 << 31)) { | |||
950 | drm_dbg_kms(&dev_priv->drm, "cpu backlight already enabled\n")drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "cpu backlight already enabled\n" ); | |||
951 | cpu_ctl2 &= ~BLM_PWM_ENABLE(1 << 31); | |||
952 | intel_de_write(dev_priv, BLC_PWM_CPU_CTL2((const i915_reg_t){ .reg = (0x48250) }), cpu_ctl2); | |||
953 | } | |||
954 | ||||
955 | pch_ctl1 = intel_de_read(dev_priv, BLC_PWM_PCH_CTL1((const i915_reg_t){ .reg = (0xc8250) })); | |||
956 | if (pch_ctl1 & BLM_PCH_PWM_ENABLE(1 << 31)) { | |||
957 | drm_dbg_kms(&dev_priv->drm, "pch backlight already enabled\n")drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "pch backlight already enabled\n" ); | |||
958 | pch_ctl1 &= ~BLM_PCH_PWM_ENABLE(1 << 31); | |||
959 | intel_de_write(dev_priv, BLC_PWM_PCH_CTL1((const i915_reg_t){ .reg = (0xc8250) }), pch_ctl1); | |||
960 | } | |||
961 | ||||
962 | if (cpu_transcoder == TRANSCODER_EDP) | |||
963 | cpu_ctl2 = BLM_TRANSCODER_EDP(3 << 29); | |||
964 | else | |||
965 | cpu_ctl2 = BLM_PIPE(cpu_transcoder)((cpu_transcoder) << 29); | |||
966 | intel_de_write(dev_priv, BLC_PWM_CPU_CTL2((const i915_reg_t){ .reg = (0x48250) }), cpu_ctl2); | |||
967 | intel_de_posting_read(dev_priv, BLC_PWM_CPU_CTL2((const i915_reg_t){ .reg = (0x48250) })); | |||
968 | intel_de_write(dev_priv, BLC_PWM_CPU_CTL2((const i915_reg_t){ .reg = (0x48250) }), cpu_ctl2 | BLM_PWM_ENABLE(1 << 31)); | |||
969 | ||||
970 | /* This won't stick until the above enable. */ | |||
971 | intel_panel_actually_set_backlight(conn_state, panel->backlight.level); | |||
972 | ||||
973 | pch_ctl2 = panel->backlight.max << 16; | |||
974 | intel_de_write(dev_priv, BLC_PWM_PCH_CTL2((const i915_reg_t){ .reg = (0xc8254) }), pch_ctl2); | |||
975 | ||||
976 | pch_ctl1 = 0; | |||
977 | if (panel->backlight.active_low_pwm) | |||
978 | pch_ctl1 |= BLM_PCH_POLARITY(1 << 29); | |||
979 | ||||
980 | intel_de_write(dev_priv, BLC_PWM_PCH_CTL1((const i915_reg_t){ .reg = (0xc8250) }), pch_ctl1); | |||
981 | intel_de_posting_read(dev_priv, BLC_PWM_PCH_CTL1((const i915_reg_t){ .reg = (0xc8250) })); | |||
982 | intel_de_write(dev_priv, BLC_PWM_PCH_CTL1((const i915_reg_t){ .reg = (0xc8250) }), | |||
983 | pch_ctl1 | BLM_PCH_PWM_ENABLE(1 << 31)); | |||
984 | } | |||
985 | ||||
986 | static void i9xx_enable_backlight(const struct intel_crtc_state *crtc_state, | |||
987 | const struct drm_connector_state *conn_state) | |||
988 | { | |||
989 | struct intel_connector *connector = to_intel_connector(conn_state->connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (conn_state->connector); (struct intel_connector * )( (char *)__mptr - __builtin_offsetof(struct intel_connector , base) );}); | |||
990 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
991 | struct intel_panel *panel = &connector->panel; | |||
992 | u32 ctl, freq; | |||
993 | ||||
994 | ctl = intel_de_read(dev_priv, BLC_PWM_CTL((const i915_reg_t){ .reg = (((&(dev_priv)->__info)-> display_mmio_offset) + 0x61254) })); | |||
995 | if (ctl & BACKLIGHT_DUTY_CYCLE_MASK_PNV(0xfffe)) { | |||
996 | drm_dbg_kms(&dev_priv->drm, "backlight already enabled\n")drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "backlight already enabled\n" ); | |||
997 | intel_de_write(dev_priv, BLC_PWM_CTL((const i915_reg_t){ .reg = (((&(dev_priv)->__info)-> display_mmio_offset) + 0x61254) }), 0); | |||
998 | } | |||
999 | ||||
1000 | freq = panel->backlight.max; | |||
1001 | if (panel->backlight.combination_mode) | |||
1002 | freq /= 0xff; | |||
1003 | ||||
1004 | ctl = freq << 17; | |||
1005 | if (panel->backlight.combination_mode) | |||
1006 | ctl |= BLM_LEGACY_MODE(1 << 16); | |||
1007 | if (IS_PINEVIEW(dev_priv)IS_PLATFORM(dev_priv, INTEL_PINEVIEW) && panel->backlight.active_low_pwm) | |||
1008 | ctl |= BLM_POLARITY_PNV(1 << 0); | |||
1009 | ||||
1010 | intel_de_write(dev_priv, BLC_PWM_CTL((const i915_reg_t){ .reg = (((&(dev_priv)->__info)-> display_mmio_offset) + 0x61254) }), ctl); | |||
1011 | intel_de_posting_read(dev_priv, BLC_PWM_CTL((const i915_reg_t){ .reg = (((&(dev_priv)->__info)-> display_mmio_offset) + 0x61254) })); | |||
1012 | ||||
1013 | /* XXX: combine this into above write? */ | |||
1014 | intel_panel_actually_set_backlight(conn_state, panel->backlight.level); | |||
1015 | ||||
1016 | /* | |||
1017 | * Needed to enable backlight on some 855gm models. BLC_HIST_CTL is | |||
1018 | * 855gm only, but checking for gen2 is safe, as 855gm is the only gen2 | |||
1019 | * that has backlight. | |||
1020 | */ | |||
1021 | if (IS_GEN(dev_priv, 2)(0 + (&(dev_priv)->__info)->gen == (2))) | |||
1022 | intel_de_write(dev_priv, BLC_HIST_CTL((const i915_reg_t){ .reg = (((&(dev_priv)->__info)-> display_mmio_offset) + 0x61260) }), BLM_HISTOGRAM_ENABLE(1 << 31)); | |||
1023 | } | |||
1024 | ||||
1025 | static void i965_enable_backlight(const struct intel_crtc_state *crtc_state, | |||
1026 | const struct drm_connector_state *conn_state) | |||
1027 | { | |||
1028 | struct intel_connector *connector = to_intel_connector(conn_state->connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (conn_state->connector); (struct intel_connector * )( (char *)__mptr - __builtin_offsetof(struct intel_connector , base) );}); | |||
1029 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
1030 | struct intel_panel *panel = &connector->panel; | |||
1031 | enum pipe pipe = to_intel_crtc(conn_state->crtc)({ const __typeof( ((struct intel_crtc *)0)->base ) *__mptr = (conn_state->crtc); (struct intel_crtc *)( (char *)__mptr - __builtin_offsetof(struct intel_crtc, base) );})->pipe; | |||
1032 | u32 ctl, ctl2, freq; | |||
1033 | ||||
1034 | ctl2 = intel_de_read(dev_priv, BLC_PWM_CTL2((const i915_reg_t){ .reg = (((&(dev_priv)->__info)-> display_mmio_offset) + 0x61250) })); | |||
1035 | if (ctl2 & BLM_PWM_ENABLE(1 << 31)) { | |||
1036 | drm_dbg_kms(&dev_priv->drm, "backlight already enabled\n")drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "backlight already enabled\n" ); | |||
1037 | ctl2 &= ~BLM_PWM_ENABLE(1 << 31); | |||
1038 | intel_de_write(dev_priv, BLC_PWM_CTL2((const i915_reg_t){ .reg = (((&(dev_priv)->__info)-> display_mmio_offset) + 0x61250) }), ctl2); | |||
1039 | } | |||
1040 | ||||
1041 | freq = panel->backlight.max; | |||
1042 | if (panel->backlight.combination_mode) | |||
1043 | freq /= 0xff; | |||
1044 | ||||
1045 | ctl = freq << 16; | |||
1046 | intel_de_write(dev_priv, BLC_PWM_CTL((const i915_reg_t){ .reg = (((&(dev_priv)->__info)-> display_mmio_offset) + 0x61254) }), ctl); | |||
1047 | ||||
1048 | ctl2 = BLM_PIPE(pipe)((pipe) << 29); | |||
1049 | if (panel->backlight.combination_mode) | |||
1050 | ctl2 |= BLM_COMBINATION_MODE(1 << 30); | |||
1051 | if (panel->backlight.active_low_pwm) | |||
1052 | ctl2 |= BLM_POLARITY_I965(1 << 28); | |||
1053 | intel_de_write(dev_priv, BLC_PWM_CTL2((const i915_reg_t){ .reg = (((&(dev_priv)->__info)-> display_mmio_offset) + 0x61250) }), ctl2); | |||
1054 | intel_de_posting_read(dev_priv, BLC_PWM_CTL2((const i915_reg_t){ .reg = (((&(dev_priv)->__info)-> display_mmio_offset) + 0x61250) })); | |||
1055 | intel_de_write(dev_priv, BLC_PWM_CTL2((const i915_reg_t){ .reg = (((&(dev_priv)->__info)-> display_mmio_offset) + 0x61250) }), ctl2 | BLM_PWM_ENABLE(1 << 31)); | |||
1056 | ||||
1057 | intel_panel_actually_set_backlight(conn_state, panel->backlight.level); | |||
1058 | } | |||
1059 | ||||
1060 | static void vlv_enable_backlight(const struct intel_crtc_state *crtc_state, | |||
1061 | const struct drm_connector_state *conn_state) | |||
1062 | { | |||
1063 | struct intel_connector *connector = to_intel_connector(conn_state->connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (conn_state->connector); (struct intel_connector * )( (char *)__mptr - __builtin_offsetof(struct intel_connector , base) );}); | |||
1064 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
1065 | struct intel_panel *panel = &connector->panel; | |||
1066 | enum pipe pipe = to_intel_crtc(crtc_state->uapi.crtc)({ const __typeof( ((struct intel_crtc *)0)->base ) *__mptr = (crtc_state->uapi.crtc); (struct intel_crtc *)( (char * )__mptr - __builtin_offsetof(struct intel_crtc, base) );})->pipe; | |||
1067 | u32 ctl, ctl2; | |||
1068 | ||||
1069 | ctl2 = intel_de_read(dev_priv, VLV_BLC_PWM_CTL2(pipe)((const i915_reg_t){ .reg = ((((((&(dev_priv)->__info) ->display_mmio_offset) + 0x61250)) + (pipe) * (((((&(dev_priv )->__info)->display_mmio_offset) + 0x61350)) - ((((& (dev_priv)->__info)->display_mmio_offset) + 0x61250)))) ) })); | |||
1070 | if (ctl2 & BLM_PWM_ENABLE(1 << 31)) { | |||
1071 | drm_dbg_kms(&dev_priv->drm, "backlight already enabled\n")drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "backlight already enabled\n" ); | |||
1072 | ctl2 &= ~BLM_PWM_ENABLE(1 << 31); | |||
1073 | intel_de_write(dev_priv, VLV_BLC_PWM_CTL2(pipe)((const i915_reg_t){ .reg = ((((((&(dev_priv)->__info) ->display_mmio_offset) + 0x61250)) + (pipe) * (((((&(dev_priv )->__info)->display_mmio_offset) + 0x61350)) - ((((& (dev_priv)->__info)->display_mmio_offset) + 0x61250)))) ) }), ctl2); | |||
1074 | } | |||
1075 | ||||
1076 | ctl = panel->backlight.max << 16; | |||
1077 | intel_de_write(dev_priv, VLV_BLC_PWM_CTL(pipe)((const i915_reg_t){ .reg = ((((((&(dev_priv)->__info) ->display_mmio_offset) + 0x61254)) + (pipe) * (((((&(dev_priv )->__info)->display_mmio_offset) + 0x61354)) - ((((& (dev_priv)->__info)->display_mmio_offset) + 0x61254)))) ) }), ctl); | |||
1078 | ||||
1079 | /* XXX: combine this into above write? */ | |||
1080 | intel_panel_actually_set_backlight(conn_state, panel->backlight.level); | |||
1081 | ||||
1082 | ctl2 = 0; | |||
1083 | if (panel->backlight.active_low_pwm) | |||
1084 | ctl2 |= BLM_POLARITY_I965(1 << 28); | |||
1085 | intel_de_write(dev_priv, VLV_BLC_PWM_CTL2(pipe)((const i915_reg_t){ .reg = ((((((&(dev_priv)->__info) ->display_mmio_offset) + 0x61250)) + (pipe) * (((((&(dev_priv )->__info)->display_mmio_offset) + 0x61350)) - ((((& (dev_priv)->__info)->display_mmio_offset) + 0x61250)))) ) }), ctl2); | |||
1086 | intel_de_posting_read(dev_priv, VLV_BLC_PWM_CTL2(pipe)((const i915_reg_t){ .reg = ((((((&(dev_priv)->__info) ->display_mmio_offset) + 0x61250)) + (pipe) * (((((&(dev_priv )->__info)->display_mmio_offset) + 0x61350)) - ((((& (dev_priv)->__info)->display_mmio_offset) + 0x61250)))) ) })); | |||
1087 | intel_de_write(dev_priv, VLV_BLC_PWM_CTL2(pipe)((const i915_reg_t){ .reg = ((((((&(dev_priv)->__info) ->display_mmio_offset) + 0x61250)) + (pipe) * (((((&(dev_priv )->__info)->display_mmio_offset) + 0x61350)) - ((((& (dev_priv)->__info)->display_mmio_offset) + 0x61250)))) ) }), | |||
1088 | ctl2 | BLM_PWM_ENABLE(1 << 31)); | |||
1089 | } | |||
1090 | ||||
1091 | static void bxt_enable_backlight(const struct intel_crtc_state *crtc_state, | |||
1092 | const struct drm_connector_state *conn_state) | |||
1093 | { | |||
1094 | struct intel_connector *connector = to_intel_connector(conn_state->connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (conn_state->connector); (struct intel_connector * )( (char *)__mptr - __builtin_offsetof(struct intel_connector , base) );}); | |||
1095 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
1096 | struct intel_panel *panel = &connector->panel; | |||
1097 | enum pipe pipe = to_intel_crtc(crtc_state->uapi.crtc)({ const __typeof( ((struct intel_crtc *)0)->base ) *__mptr = (crtc_state->uapi.crtc); (struct intel_crtc *)( (char * )__mptr - __builtin_offsetof(struct intel_crtc, base) );})->pipe; | |||
1098 | u32 pwm_ctl, val; | |||
1099 | ||||
1100 | /* Controller 1 uses the utility pin. */ | |||
1101 | if (panel->backlight.controller == 1) { | |||
1102 | val = intel_de_read(dev_priv, UTIL_PIN_CTL((const i915_reg_t){ .reg = (0x48400) })); | |||
1103 | if (val & UTIL_PIN_ENABLE(1 << 31)) { | |||
1104 | drm_dbg_kms(&dev_priv->drm,drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "util pin already enabled\n" ) | |||
1105 | "util pin already enabled\n")drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "util pin already enabled\n" ); | |||
1106 | val &= ~UTIL_PIN_ENABLE(1 << 31); | |||
1107 | intel_de_write(dev_priv, UTIL_PIN_CTL((const i915_reg_t){ .reg = (0x48400) }), val); | |||
1108 | } | |||
1109 | ||||
1110 | val = 0; | |||
1111 | if (panel->backlight.util_pin_active_low) | |||
1112 | val |= UTIL_PIN_POLARITY(1 << 22); | |||
1113 | intel_de_write(dev_priv, UTIL_PIN_CTL((const i915_reg_t){ .reg = (0x48400) }), | |||
1114 | val | UTIL_PIN_PIPE(pipe)((pipe) << 29) | UTIL_PIN_MODE_PWM(1 << 24) | UTIL_PIN_ENABLE(1 << 31)); | |||
1115 | } | |||
1116 | ||||
1117 | pwm_ctl = intel_de_read(dev_priv, | |||
1118 | BXT_BLC_PWM_CTL(panel->backlight.controller)((const i915_reg_t){ .reg = (((0xC8250) + (panel->backlight .controller) * ((0xC8350) - (0xC8250)))) })); | |||
1119 | if (pwm_ctl & BXT_BLC_PWM_ENABLE(1 << 31)) { | |||
1120 | drm_dbg_kms(&dev_priv->drm, "backlight already enabled\n")drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "backlight already enabled\n" ); | |||
1121 | pwm_ctl &= ~BXT_BLC_PWM_ENABLE(1 << 31); | |||
1122 | intel_de_write(dev_priv, | |||
1123 | BXT_BLC_PWM_CTL(panel->backlight.controller)((const i915_reg_t){ .reg = (((0xC8250) + (panel->backlight .controller) * ((0xC8350) - (0xC8250)))) }), | |||
1124 | pwm_ctl); | |||
1125 | } | |||
1126 | ||||
1127 | intel_de_write(dev_priv, | |||
1128 | BXT_BLC_PWM_FREQ(panel->backlight.controller)((const i915_reg_t){ .reg = (((0xC8254) + (panel->backlight .controller) * ((0xC8354) - (0xC8254)))) }), | |||
1129 | panel->backlight.max); | |||
1130 | ||||
1131 | intel_panel_actually_set_backlight(conn_state, panel->backlight.level); | |||
1132 | ||||
1133 | pwm_ctl = 0; | |||
1134 | if (panel->backlight.active_low_pwm) | |||
1135 | pwm_ctl |= BXT_BLC_PWM_POLARITY(1 << 29); | |||
1136 | ||||
1137 | intel_de_write(dev_priv, BXT_BLC_PWM_CTL(panel->backlight.controller)((const i915_reg_t){ .reg = (((0xC8250) + (panel->backlight .controller) * ((0xC8350) - (0xC8250)))) }), | |||
1138 | pwm_ctl); | |||
1139 | intel_de_posting_read(dev_priv, | |||
1140 | BXT_BLC_PWM_CTL(panel->backlight.controller)((const i915_reg_t){ .reg = (((0xC8250) + (panel->backlight .controller) * ((0xC8350) - (0xC8250)))) })); | |||
1141 | intel_de_write(dev_priv, BXT_BLC_PWM_CTL(panel->backlight.controller)((const i915_reg_t){ .reg = (((0xC8250) + (panel->backlight .controller) * ((0xC8350) - (0xC8250)))) }), | |||
1142 | pwm_ctl | BXT_BLC_PWM_ENABLE(1 << 31)); | |||
1143 | } | |||
1144 | ||||
1145 | static void cnp_enable_backlight(const struct intel_crtc_state *crtc_state, | |||
1146 | const struct drm_connector_state *conn_state) | |||
1147 | { | |||
1148 | struct intel_connector *connector = to_intel_connector(conn_state->connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (conn_state->connector); (struct intel_connector * )( (char *)__mptr - __builtin_offsetof(struct intel_connector , base) );}); | |||
1149 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
1150 | struct intel_panel *panel = &connector->panel; | |||
1151 | u32 pwm_ctl; | |||
1152 | ||||
1153 | pwm_ctl = intel_de_read(dev_priv, | |||
1154 | BXT_BLC_PWM_CTL(panel->backlight.controller)((const i915_reg_t){ .reg = (((0xC8250) + (panel->backlight .controller) * ((0xC8350) - (0xC8250)))) })); | |||
1155 | if (pwm_ctl & BXT_BLC_PWM_ENABLE(1 << 31)) { | |||
1156 | drm_dbg_kms(&dev_priv->drm, "backlight already enabled\n")drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "backlight already enabled\n" ); | |||
1157 | pwm_ctl &= ~BXT_BLC_PWM_ENABLE(1 << 31); | |||
1158 | intel_de_write(dev_priv, | |||
1159 | BXT_BLC_PWM_CTL(panel->backlight.controller)((const i915_reg_t){ .reg = (((0xC8250) + (panel->backlight .controller) * ((0xC8350) - (0xC8250)))) }), | |||
1160 | pwm_ctl); | |||
1161 | } | |||
1162 | ||||
1163 | intel_de_write(dev_priv, | |||
1164 | BXT_BLC_PWM_FREQ(panel->backlight.controller)((const i915_reg_t){ .reg = (((0xC8254) + (panel->backlight .controller) * ((0xC8354) - (0xC8254)))) }), | |||
1165 | panel->backlight.max); | |||
1166 | ||||
1167 | intel_panel_actually_set_backlight(conn_state, panel->backlight.level); | |||
1168 | ||||
1169 | pwm_ctl = 0; | |||
1170 | if (panel->backlight.active_low_pwm) | |||
1171 | pwm_ctl |= BXT_BLC_PWM_POLARITY(1 << 29); | |||
1172 | ||||
1173 | intel_de_write(dev_priv, BXT_BLC_PWM_CTL(panel->backlight.controller)((const i915_reg_t){ .reg = (((0xC8250) + (panel->backlight .controller) * ((0xC8350) - (0xC8250)))) }), | |||
1174 | pwm_ctl); | |||
1175 | intel_de_posting_read(dev_priv, | |||
1176 | BXT_BLC_PWM_CTL(panel->backlight.controller)((const i915_reg_t){ .reg = (((0xC8250) + (panel->backlight .controller) * ((0xC8350) - (0xC8250)))) })); | |||
1177 | intel_de_write(dev_priv, BXT_BLC_PWM_CTL(panel->backlight.controller)((const i915_reg_t){ .reg = (((0xC8250) + (panel->backlight .controller) * ((0xC8350) - (0xC8250)))) }), | |||
1178 | pwm_ctl | BXT_BLC_PWM_ENABLE(1 << 31)); | |||
1179 | } | |||
1180 | ||||
1181 | static void pwm_enable_backlight(const struct intel_crtc_state *crtc_state, | |||
1182 | const struct drm_connector_state *conn_state) | |||
1183 | { | |||
1184 | STUB()do { printf("%s: stub\n", __func__); } while(0); | |||
1185 | #ifdef notyet | |||
1186 | struct intel_connector *connector = to_intel_connector(conn_state->connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (conn_state->connector); (struct intel_connector * )( (char *)__mptr - __builtin_offsetof(struct intel_connector , base) );}); | |||
1187 | struct intel_panel *panel = &connector->panel; | |||
1188 | int level = panel->backlight.level; | |||
1189 | ||||
1190 | level = intel_panel_compute_brightness(connector, level); | |||
1191 | pwm_set_relative_duty_cycle(&panel->backlight.pwm_state, level, 100); | |||
1192 | panel->backlight.pwm_state.enabled = true1; | |||
1193 | pwm_apply_state(panel->backlight.pwm, &panel->backlight.pwm_state); | |||
1194 | #endif | |||
1195 | } | |||
1196 | ||||
1197 | static void __intel_panel_enable_backlight(const struct intel_crtc_state *crtc_state, | |||
1198 | const struct drm_connector_state *conn_state) | |||
1199 | { | |||
1200 | struct intel_connector *connector = to_intel_connector(conn_state->connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (conn_state->connector); (struct intel_connector * )( (char *)__mptr - __builtin_offsetof(struct intel_connector , base) );}); | |||
1201 | struct intel_panel *panel = &connector->panel; | |||
1202 | ||||
1203 | WARN_ON(panel->backlight.max == 0)({ int __ret = !!((panel->backlight.max == 0)); if (__ret) printf("%s", "WARN_ON(" "panel->backlight.max == 0" ")"); __builtin_expect(!!(__ret), 0); }); | |||
1204 | ||||
1205 | if (panel->backlight.level <= panel->backlight.min) { | |||
1206 | panel->backlight.level = panel->backlight.max; | |||
1207 | if (panel->backlight.device) | |||
1208 | panel->backlight.device->props.brightness = | |||
1209 | scale_hw_to_user(connector, | |||
1210 | panel->backlight.level, | |||
1211 | panel->backlight.device->props.max_brightness); | |||
1212 | } | |||
1213 | ||||
1214 | panel->backlight.enable(crtc_state, conn_state); | |||
1215 | panel->backlight.enabled = true1; | |||
1216 | if (panel->backlight.device) | |||
1217 | panel->backlight.device->props.power = FB_BLANK_UNBLANK0; | |||
1218 | } | |||
1219 | ||||
1220 | void intel_panel_enable_backlight(const struct intel_crtc_state *crtc_state, | |||
1221 | const struct drm_connector_state *conn_state) | |||
1222 | { | |||
1223 | struct intel_connector *connector = to_intel_connector(conn_state->connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (conn_state->connector); (struct intel_connector * )( (char *)__mptr - __builtin_offsetof(struct intel_connector , base) );}); | |||
1224 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
1225 | struct intel_panel *panel = &connector->panel; | |||
1226 | enum pipe pipe = to_intel_crtc(crtc_state->uapi.crtc)({ const __typeof( ((struct intel_crtc *)0)->base ) *__mptr = (crtc_state->uapi.crtc); (struct intel_crtc *)( (char * )__mptr - __builtin_offsetof(struct intel_crtc, base) );})->pipe; | |||
1227 | ||||
1228 | if (!panel->backlight.present) | |||
1229 | return; | |||
1230 | ||||
1231 | drm_dbg_kms(&dev_priv->drm, "pipe %c\n", pipe_name(pipe))drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "pipe %c\n" , ((pipe) + 'A')); | |||
1232 | ||||
1233 | mutex_lock(&dev_priv->backlight_lock)rw_enter_write(&dev_priv->backlight_lock); | |||
1234 | ||||
1235 | __intel_panel_enable_backlight(crtc_state, conn_state); | |||
1236 | ||||
1237 | mutex_unlock(&dev_priv->backlight_lock)rw_exit_write(&dev_priv->backlight_lock); | |||
1238 | } | |||
1239 | ||||
1240 | #if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE)1 | |||
1241 | static u32 intel_panel_get_backlight(struct intel_connector *connector) | |||
1242 | { | |||
1243 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
1244 | struct intel_panel *panel = &connector->panel; | |||
1245 | u32 val = 0; | |||
1246 | ||||
1247 | mutex_lock(&dev_priv->backlight_lock)rw_enter_write(&dev_priv->backlight_lock); | |||
1248 | ||||
1249 | if (panel->backlight.enabled) { | |||
1250 | val = panel->backlight.get(connector); | |||
1251 | val = intel_panel_compute_brightness(connector, val); | |||
1252 | } | |||
1253 | ||||
1254 | mutex_unlock(&dev_priv->backlight_lock)rw_exit_write(&dev_priv->backlight_lock); | |||
1255 | ||||
1256 | drm_dbg_kms(&dev_priv->drm, "get backlight PWM = %d\n", val)drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "get backlight PWM = %d\n" , val); | |||
1257 | return val; | |||
1258 | } | |||
1259 | ||||
1260 | /* Scale user_level in range [0..user_max] to [hw_min..hw_max]. */ | |||
1261 | static u32 scale_user_to_hw(struct intel_connector *connector, | |||
1262 | u32 user_level, u32 user_max) | |||
1263 | { | |||
1264 | struct intel_panel *panel = &connector->panel; | |||
1265 | ||||
1266 | return scale(user_level, 0, user_max, | |||
1267 | panel->backlight.min, panel->backlight.max); | |||
1268 | } | |||
1269 | ||||
1270 | /* set backlight brightness to level in range [0..max], scaling wrt hw min */ | |||
1271 | static void intel_panel_set_backlight(const struct drm_connector_state *conn_state, | |||
1272 | u32 user_level, u32 user_max) | |||
1273 | { | |||
1274 | struct intel_connector *connector = to_intel_connector(conn_state->connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (conn_state->connector); (struct intel_connector * )( (char *)__mptr - __builtin_offsetof(struct intel_connector , base) );}); | |||
1275 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
1276 | struct intel_panel *panel = &connector->panel; | |||
1277 | u32 hw_level; | |||
1278 | ||||
1279 | if (!panel->backlight.present) | |||
1280 | return; | |||
1281 | ||||
1282 | mutex_lock(&dev_priv->backlight_lock)rw_enter_write(&dev_priv->backlight_lock); | |||
1283 | ||||
1284 | drm_WARN_ON(&dev_priv->drm, panel->backlight.max == 0)({ int __ret = !!((panel->backlight.max == 0)); if (__ret) printf("%s %s: " "%s", dev_driver_string(((&dev_priv-> drm))->dev), "", "drm_WARN_ON(" "panel->backlight.max == 0" ")"); __builtin_expect(!!(__ret), 0); }); | |||
1285 | ||||
1286 | hw_level = scale_user_to_hw(connector, user_level, user_max); | |||
1287 | panel->backlight.level = hw_level; | |||
1288 | ||||
1289 | if (panel->backlight.enabled) | |||
1290 | intel_panel_actually_set_backlight(conn_state, hw_level); | |||
1291 | ||||
1292 | mutex_unlock(&dev_priv->backlight_lock)rw_exit_write(&dev_priv->backlight_lock); | |||
1293 | } | |||
1294 | ||||
1295 | static int intel_backlight_device_update_status(struct backlight_device *bd) | |||
1296 | { | |||
1297 | struct intel_connector *connector = bl_get_data(bd)(bd)->data; | |||
1298 | struct intel_panel *panel = &connector->panel; | |||
1299 | struct drm_device *dev = connector->base.dev; | |||
1300 | ||||
1301 | drm_modeset_lock(&dev->mode_config.connection_mutex, NULL((void *)0)); | |||
1302 | DRM_DEBUG_KMS("updating intel_backlight, brightness=%d/%d\n",__drm_dbg(DRM_UT_KMS, "updating intel_backlight, brightness=%d/%d\n" , bd->props.brightness, bd->props.max_brightness) | |||
1303 | bd->props.brightness, bd->props.max_brightness)__drm_dbg(DRM_UT_KMS, "updating intel_backlight, brightness=%d/%d\n" , bd->props.brightness, bd->props.max_brightness); | |||
1304 | intel_panel_set_backlight(connector->base.state, bd->props.brightness, | |||
1305 | bd->props.max_brightness); | |||
1306 | ||||
1307 | /* | |||
1308 | * Allow flipping bl_power as a sub-state of enabled. Sadly the | |||
1309 | * backlight class device does not make it easy to to differentiate | |||
1310 | * between callbacks for brightness and bl_power, so our backlight_power | |||
1311 | * callback needs to take this into account. | |||
1312 | */ | |||
1313 | if (panel->backlight.enabled) { | |||
1314 | if (panel->backlight.power) { | |||
1315 | bool_Bool enable = bd->props.power == FB_BLANK_UNBLANK0 && | |||
1316 | bd->props.brightness != 0; | |||
1317 | panel->backlight.power(connector, enable); | |||
1318 | } | |||
1319 | } else { | |||
1320 | bd->props.power = FB_BLANK_POWERDOWN4; | |||
1321 | } | |||
1322 | ||||
1323 | drm_modeset_unlock(&dev->mode_config.connection_mutex); | |||
1324 | return 0; | |||
1325 | } | |||
1326 | ||||
1327 | static int intel_backlight_device_get_brightness(struct backlight_device *bd) | |||
1328 | { | |||
1329 | struct intel_connector *connector = bl_get_data(bd)(bd)->data; | |||
1330 | struct drm_device *dev = connector->base.dev; | |||
1331 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(dev); | |||
1332 | intel_wakeref_t wakeref; | |||
1333 | int ret = 0; | |||
1334 | ||||
1335 | with_intel_runtime_pm(&dev_priv->runtime_pm, wakeref)for ((wakeref) = intel_runtime_pm_get(&dev_priv->runtime_pm ); (wakeref); intel_runtime_pm_put((&dev_priv->runtime_pm ), (wakeref)), (wakeref) = 0) { | |||
| ||||
1336 | u32 hw_level; | |||
1337 | ||||
1338 | drm_modeset_lock(&dev->mode_config.connection_mutex, NULL((void *)0)); | |||
1339 | ||||
1340 | hw_level = intel_panel_get_backlight(connector); | |||
1341 | ret = scale_hw_to_user(connector, | |||
1342 | hw_level, bd->props.max_brightness); | |||
1343 | ||||
1344 | drm_modeset_unlock(&dev->mode_config.connection_mutex); | |||
1345 | } | |||
1346 | ||||
1347 | return ret; | |||
1348 | } | |||
1349 | ||||
1350 | static const struct backlight_ops intel_backlight_device_ops = { | |||
1351 | .update_status = intel_backlight_device_update_status, | |||
1352 | .get_brightness = intel_backlight_device_get_brightness, | |||
1353 | }; | |||
1354 | ||||
1355 | int intel_backlight_device_register(struct intel_connector *connector) | |||
1356 | { | |||
1357 | struct drm_i915_privateinteldrm_softc *i915 = to_i915(connector->base.dev); | |||
1358 | struct intel_panel *panel = &connector->panel; | |||
1359 | struct backlight_properties props; | |||
1360 | ||||
1361 | if (WARN_ON(panel->backlight.device)({ int __ret = !!((panel->backlight.device)); if (__ret) printf ("%s", "WARN_ON(" "panel->backlight.device" ")"); __builtin_expect (!!(__ret), 0); })) | |||
1362 | return -ENODEV19; | |||
1363 | ||||
1364 | if (!panel->backlight.present) | |||
1365 | return 0; | |||
1366 | ||||
1367 | WARN_ON(panel->backlight.max == 0)({ int __ret = !!((panel->backlight.max == 0)); if (__ret) printf("%s", "WARN_ON(" "panel->backlight.max == 0" ")"); __builtin_expect(!!(__ret), 0); }); | |||
1368 | ||||
1369 | memset(&props, 0, sizeof(props))__builtin_memset((&props), (0), (sizeof(props))); | |||
1370 | props.type = BACKLIGHT_RAW0; | |||
1371 | ||||
1372 | /* | |||
1373 | * Note: Everything should work even if the backlight device max | |||
1374 | * presented to the userspace is arbitrarily chosen. | |||
1375 | */ | |||
1376 | props.max_brightness = panel->backlight.max; | |||
1377 | props.brightness = scale_hw_to_user(connector, | |||
1378 | panel->backlight.level, | |||
1379 | props.max_brightness); | |||
1380 | ||||
1381 | if (panel->backlight.enabled) | |||
1382 | props.power = FB_BLANK_UNBLANK0; | |||
1383 | else | |||
1384 | props.power = FB_BLANK_POWERDOWN4; | |||
1385 | ||||
1386 | /* | |||
1387 | * Note: using the same name independent of the connector prevents | |||
1388 | * registration of multiple backlight devices in the driver. | |||
1389 | */ | |||
1390 | panel->backlight.device = | |||
1391 | backlight_device_register("intel_backlight", | |||
1392 | connector->base.kdev, | |||
1393 | connector, | |||
1394 | &intel_backlight_device_ops, &props); | |||
1395 | ||||
1396 | if (IS_ERR(panel->backlight.device)) { | |||
1397 | drm_err(&i915->drm, "Failed to register backlight: %ld\n",printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Failed to register backlight: %ld\n" , ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , PTR_ERR (panel->backlight.device)) | |||
1398 | PTR_ERR(panel->backlight.device))printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Failed to register backlight: %ld\n" , ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , PTR_ERR (panel->backlight.device)); | |||
1399 | panel->backlight.device = NULL((void *)0); | |||
1400 | return -ENODEV19; | |||
1401 | } | |||
1402 | ||||
1403 | drm_dbg_kms(&i915->drm,drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "Connector %s backlight sysfs interface registered\n" , connector->base.name) | |||
1404 | "Connector %s backlight sysfs interface registered\n",drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "Connector %s backlight sysfs interface registered\n" , connector->base.name) | |||
1405 | connector->base.name)drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "Connector %s backlight sysfs interface registered\n" , connector->base.name); | |||
1406 | ||||
1407 | return 0; | |||
1408 | } | |||
1409 | ||||
1410 | void intel_backlight_device_unregister(struct intel_connector *connector) | |||
1411 | { | |||
1412 | struct intel_panel *panel = &connector->panel; | |||
1413 | ||||
1414 | if (panel->backlight.device) { | |||
1415 | backlight_device_unregister(panel->backlight.device); | |||
1416 | panel->backlight.device = NULL((void *)0); | |||
1417 | } | |||
1418 | } | |||
1419 | #endif /* CONFIG_BACKLIGHT_CLASS_DEVICE */ | |||
1420 | ||||
1421 | /* | |||
1422 | * CNP: PWM clock frequency is 19.2 MHz or 24 MHz. | |||
1423 | * PWM increment = 1 | |||
1424 | */ | |||
1425 | static u32 cnp_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) | |||
1426 | { | |||
1427 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
1428 | ||||
1429 | return DIV_ROUND_CLOSEST(KHz(RUNTIME_INFO(dev_priv)->rawclk_freq),((((1000 * ((&(dev_priv)->__runtime)->rawclk_freq)) ) + ((pwm_freq_hz) / 2)) / (pwm_freq_hz)) | |||
1430 | pwm_freq_hz)((((1000 * ((&(dev_priv)->__runtime)->rawclk_freq)) ) + ((pwm_freq_hz) / 2)) / (pwm_freq_hz)); | |||
1431 | } | |||
1432 | ||||
1433 | /* | |||
1434 | * BXT: PWM clock frequency = 19.2 MHz. | |||
1435 | */ | |||
1436 | static u32 bxt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) | |||
1437 | { | |||
1438 | return DIV_ROUND_CLOSEST(KHz(19200), pwm_freq_hz)((((1000 * (19200))) + ((pwm_freq_hz) / 2)) / (pwm_freq_hz)); | |||
1439 | } | |||
1440 | ||||
1441 | /* | |||
1442 | * SPT: This value represents the period of the PWM stream in clock periods | |||
1443 | * multiplied by 16 (default increment) or 128 (alternate increment selected in | |||
1444 | * SCHICKEN_1 bit 0). PWM clock is 24 MHz. | |||
1445 | */ | |||
1446 | static u32 spt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) | |||
1447 | { | |||
1448 | struct intel_panel *panel = &connector->panel; | |||
1449 | u32 mul; | |||
1450 | ||||
1451 | if (panel->backlight.alternate_pwm_increment) | |||
1452 | mul = 128; | |||
1453 | else | |||
1454 | mul = 16; | |||
1455 | ||||
1456 | return DIV_ROUND_CLOSEST(MHz(24), pwm_freq_hz * mul)((((1000 * (1000 * (24)))) + ((pwm_freq_hz * mul) / 2)) / (pwm_freq_hz * mul)); | |||
1457 | } | |||
1458 | ||||
1459 | /* | |||
1460 | * LPT: This value represents the period of the PWM stream in clock periods | |||
1461 | * multiplied by 128 (default increment) or 16 (alternate increment, selected in | |||
1462 | * LPT SOUTH_CHICKEN2 register bit 5). | |||
1463 | */ | |||
1464 | static u32 lpt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) | |||
1465 | { | |||
1466 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
1467 | struct intel_panel *panel = &connector->panel; | |||
1468 | u32 mul, clock; | |||
1469 | ||||
1470 | if (panel->backlight.alternate_pwm_increment) | |||
1471 | mul = 16; | |||
1472 | else | |||
1473 | mul = 128; | |||
1474 | ||||
1475 | if (HAS_PCH_LPT_H(dev_priv)(((dev_priv)->pch_id) == 0x8c00 || ((dev_priv)->pch_id) == 0x8c80)) | |||
1476 | clock = MHz(135)(1000 * (1000 * (135))); /* LPT:H */ | |||
1477 | else | |||
1478 | clock = MHz(24)(1000 * (1000 * (24))); /* LPT:LP */ | |||
1479 | ||||
1480 | return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * mul)(((clock) + ((pwm_freq_hz * mul) / 2)) / (pwm_freq_hz * mul)); | |||
1481 | } | |||
1482 | ||||
1483 | /* | |||
1484 | * ILK/SNB/IVB: This value represents the period of the PWM stream in PCH | |||
1485 | * display raw clocks multiplied by 128. | |||
1486 | */ | |||
1487 | static u32 pch_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) | |||
1488 | { | |||
1489 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
1490 | ||||
1491 | return DIV_ROUND_CLOSEST(KHz(RUNTIME_INFO(dev_priv)->rawclk_freq),((((1000 * ((&(dev_priv)->__runtime)->rawclk_freq)) ) + ((pwm_freq_hz * 128) / 2)) / (pwm_freq_hz * 128)) | |||
1492 | pwm_freq_hz * 128)((((1000 * ((&(dev_priv)->__runtime)->rawclk_freq)) ) + ((pwm_freq_hz * 128) / 2)) / (pwm_freq_hz * 128)); | |||
1493 | } | |||
1494 | ||||
1495 | /* | |||
1496 | * Gen2: This field determines the number of time base events (display core | |||
1497 | * clock frequency/32) in total for a complete cycle of modulated backlight | |||
1498 | * control. | |||
1499 | * | |||
1500 | * Gen3: A time base event equals the display core clock ([DevPNV] HRAW clock) | |||
1501 | * divided by 32. | |||
1502 | */ | |||
1503 | static u32 i9xx_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) | |||
1504 | { | |||
1505 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
1506 | int clock; | |||
1507 | ||||
1508 | if (IS_PINEVIEW(dev_priv)IS_PLATFORM(dev_priv, INTEL_PINEVIEW)) | |||
1509 | clock = KHz(RUNTIME_INFO(dev_priv)->rawclk_freq)(1000 * ((&(dev_priv)->__runtime)->rawclk_freq)); | |||
1510 | else | |||
1511 | clock = KHz(dev_priv->cdclk.hw.cdclk)(1000 * (dev_priv->cdclk.hw.cdclk)); | |||
1512 | ||||
1513 | return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * 32)(((clock) + ((pwm_freq_hz * 32) / 2)) / (pwm_freq_hz * 32)); | |||
1514 | } | |||
1515 | ||||
1516 | /* | |||
1517 | * Gen4: This value represents the period of the PWM stream in display core | |||
1518 | * clocks ([DevCTG] HRAW clocks) multiplied by 128. | |||
1519 | * | |||
1520 | */ | |||
1521 | static u32 i965_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) | |||
1522 | { | |||
1523 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
1524 | int clock; | |||
1525 | ||||
1526 | if (IS_G4X(dev_priv)(IS_PLATFORM(dev_priv, INTEL_G45) || IS_PLATFORM(dev_priv, INTEL_GM45 ))) | |||
1527 | clock = KHz(RUNTIME_INFO(dev_priv)->rawclk_freq)(1000 * ((&(dev_priv)->__runtime)->rawclk_freq)); | |||
1528 | else | |||
1529 | clock = KHz(dev_priv->cdclk.hw.cdclk)(1000 * (dev_priv->cdclk.hw.cdclk)); | |||
1530 | ||||
1531 | return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * 128)(((clock) + ((pwm_freq_hz * 128) / 2)) / (pwm_freq_hz * 128)); | |||
1532 | } | |||
1533 | ||||
1534 | /* | |||
1535 | * VLV: This value represents the period of the PWM stream in display core | |||
1536 | * clocks ([DevCTG] 200MHz HRAW clocks) multiplied by 128 or 25MHz S0IX clocks | |||
1537 | * multiplied by 16. CHV uses a 19.2MHz S0IX clock. | |||
1538 | */ | |||
1539 | static u32 vlv_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) | |||
1540 | { | |||
1541 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
1542 | int mul, clock; | |||
1543 | ||||
1544 | if ((intel_de_read(dev_priv, CBR1_VLV((const i915_reg_t){ .reg = (0x180000 + 0x70400) })) & CBR_PWM_CLOCK_MUX_SELECT(1 << 30)) == 0) { | |||
1545 | if (IS_CHERRYVIEW(dev_priv)IS_PLATFORM(dev_priv, INTEL_CHERRYVIEW)) | |||
1546 | clock = KHz(19200)(1000 * (19200)); | |||
1547 | else | |||
1548 | clock = MHz(25)(1000 * (1000 * (25))); | |||
1549 | mul = 16; | |||
1550 | } else { | |||
1551 | clock = KHz(RUNTIME_INFO(dev_priv)->rawclk_freq)(1000 * ((&(dev_priv)->__runtime)->rawclk_freq)); | |||
1552 | mul = 128; | |||
1553 | } | |||
1554 | ||||
1555 | return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * mul)(((clock) + ((pwm_freq_hz * mul) / 2)) / (pwm_freq_hz * mul)); | |||
1556 | } | |||
1557 | ||||
1558 | static u16 get_vbt_pwm_freq(struct drm_i915_privateinteldrm_softc *dev_priv) | |||
1559 | { | |||
1560 | u16 pwm_freq_hz = dev_priv->vbt.backlight.pwm_freq_hz; | |||
1561 | ||||
1562 | if (pwm_freq_hz) { | |||
1563 | drm_dbg_kms(&dev_priv->drm,drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "VBT defined backlight frequency %u Hz\n" , pwm_freq_hz) | |||
1564 | "VBT defined backlight frequency %u Hz\n",drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "VBT defined backlight frequency %u Hz\n" , pwm_freq_hz) | |||
1565 | pwm_freq_hz)drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "VBT defined backlight frequency %u Hz\n" , pwm_freq_hz); | |||
1566 | } else { | |||
1567 | pwm_freq_hz = 200; | |||
1568 | drm_dbg_kms(&dev_priv->drm,drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "default backlight frequency %u Hz\n" , pwm_freq_hz) | |||
1569 | "default backlight frequency %u Hz\n",drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "default backlight frequency %u Hz\n" , pwm_freq_hz) | |||
1570 | pwm_freq_hz)drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "default backlight frequency %u Hz\n" , pwm_freq_hz); | |||
1571 | } | |||
1572 | ||||
1573 | return pwm_freq_hz; | |||
1574 | } | |||
1575 | ||||
1576 | static u32 get_backlight_max_vbt(struct intel_connector *connector) | |||
1577 | { | |||
1578 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
1579 | struct intel_panel *panel = &connector->panel; | |||
1580 | u16 pwm_freq_hz = get_vbt_pwm_freq(dev_priv); | |||
1581 | u32 pwm; | |||
1582 | ||||
1583 | if (!panel->backlight.hz_to_pwm) { | |||
1584 | drm_dbg_kms(&dev_priv->drm,drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "backlight frequency conversion not supported\n" ) | |||
1585 | "backlight frequency conversion not supported\n")drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "backlight frequency conversion not supported\n" ); | |||
1586 | return 0; | |||
1587 | } | |||
1588 | ||||
1589 | pwm = panel->backlight.hz_to_pwm(connector, pwm_freq_hz); | |||
1590 | if (!pwm) { | |||
1591 | drm_dbg_kms(&dev_priv->drm,drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "backlight frequency conversion failed\n" ) | |||
1592 | "backlight frequency conversion failed\n")drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "backlight frequency conversion failed\n" ); | |||
1593 | return 0; | |||
1594 | } | |||
1595 | ||||
1596 | return pwm; | |||
1597 | } | |||
1598 | ||||
1599 | /* | |||
1600 | * Note: The setup hooks can't assume pipe is set! | |||
1601 | */ | |||
1602 | static u32 get_backlight_min_vbt(struct intel_connector *connector) | |||
1603 | { | |||
1604 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
1605 | struct intel_panel *panel = &connector->panel; | |||
1606 | int min; | |||
1607 | ||||
1608 | drm_WARN_ON(&dev_priv->drm, panel->backlight.max == 0)({ int __ret = !!((panel->backlight.max == 0)); if (__ret) printf("%s %s: " "%s", dev_driver_string(((&dev_priv-> drm))->dev), "", "drm_WARN_ON(" "panel->backlight.max == 0" ")"); __builtin_expect(!!(__ret), 0); }); | |||
1609 | ||||
1610 | /* | |||
1611 | * XXX: If the vbt value is 255, it makes min equal to max, which leads | |||
1612 | * to problems. There are such machines out there. Either our | |||
1613 | * interpretation is wrong or the vbt has bogus data. Or both. Safeguard | |||
1614 | * against this by letting the minimum be at most (arbitrarily chosen) | |||
1615 | * 25% of the max. | |||
1616 | */ | |||
1617 | min = clamp_t(int, dev_priv->vbt.backlight.min_brightness, 0, 64)({ int __min_a = (({ int __max_a = (dev_priv->vbt.backlight .min_brightness); int __max_b = (0); __max_a > __max_b ? __max_a : __max_b; })); int __min_b = (64); __min_a < __min_b ? __min_a : __min_b; }); | |||
1618 | if (min != dev_priv->vbt.backlight.min_brightness) { | |||
1619 | drm_dbg_kms(&dev_priv->drm,drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "clamping VBT min backlight %d/255 to %d/255\n" , dev_priv->vbt.backlight.min_brightness, min) | |||
1620 | "clamping VBT min backlight %d/255 to %d/255\n",drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "clamping VBT min backlight %d/255 to %d/255\n" , dev_priv->vbt.backlight.min_brightness, min) | |||
1621 | dev_priv->vbt.backlight.min_brightness, min)drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "clamping VBT min backlight %d/255 to %d/255\n" , dev_priv->vbt.backlight.min_brightness, min); | |||
1622 | } | |||
1623 | ||||
1624 | /* vbt value is a coefficient in range [0..255] */ | |||
1625 | return scale(min, 0, 255, 0, panel->backlight.max); | |||
1626 | } | |||
1627 | ||||
1628 | static int lpt_setup_backlight(struct intel_connector *connector, enum pipe unused) | |||
1629 | { | |||
1630 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
1631 | struct intel_panel *panel = &connector->panel; | |||
1632 | u32 cpu_ctl2, pch_ctl1, pch_ctl2, val; | |||
1633 | bool_Bool alt, cpu_mode; | |||
1634 | ||||
1635 | if (HAS_PCH_LPT(dev_priv)(((dev_priv)->pch_type) == PCH_LPT)) | |||
1636 | alt = intel_de_read(dev_priv, SOUTH_CHICKEN2((const i915_reg_t){ .reg = (0xc2004) })) & LPT_PWM_GRANULARITY(1 << 5); | |||
1637 | else | |||
1638 | alt = intel_de_read(dev_priv, SOUTH_CHICKEN1((const i915_reg_t){ .reg = (0xc2000) })) & SPT_PWM_GRANULARITY(1 << 0); | |||
1639 | panel->backlight.alternate_pwm_increment = alt; | |||
1640 | ||||
1641 | pch_ctl1 = intel_de_read(dev_priv, BLC_PWM_PCH_CTL1((const i915_reg_t){ .reg = (0xc8250) })); | |||
1642 | panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY(1 << 29); | |||
1643 | ||||
1644 | pch_ctl2 = intel_de_read(dev_priv, BLC_PWM_PCH_CTL2((const i915_reg_t){ .reg = (0xc8254) })); | |||
1645 | panel->backlight.max = pch_ctl2 >> 16; | |||
1646 | ||||
1647 | cpu_ctl2 = intel_de_read(dev_priv, BLC_PWM_CPU_CTL2((const i915_reg_t){ .reg = (0x48250) })); | |||
1648 | ||||
1649 | if (!panel->backlight.max) | |||
1650 | panel->backlight.max = get_backlight_max_vbt(connector); | |||
1651 | ||||
1652 | if (!panel->backlight.max) | |||
1653 | return -ENODEV19; | |||
1654 | ||||
1655 | panel->backlight.min = get_backlight_min_vbt(connector); | |||
1656 | ||||
1657 | panel->backlight.enabled = pch_ctl1 & BLM_PCH_PWM_ENABLE(1 << 31); | |||
1658 | ||||
1659 | cpu_mode = panel->backlight.enabled && HAS_PCH_LPT(dev_priv)(((dev_priv)->pch_type) == PCH_LPT) && | |||
1660 | !(pch_ctl1 & BLM_PCH_OVERRIDE_ENABLE(1 << 30)) && | |||
1661 | (cpu_ctl2 & BLM_PWM_ENABLE(1 << 31)); | |||
1662 | if (cpu_mode) | |||
1663 | val = pch_get_backlight(connector); | |||
1664 | else | |||
1665 | val = lpt_get_backlight(connector); | |||
1666 | ||||
1667 | if (cpu_mode) { | |||
1668 | drm_dbg_kms(&dev_priv->drm,drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "CPU backlight register was enabled, switching to PCH override\n" ) | |||
1669 | "CPU backlight register was enabled, switching to PCH override\n")drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "CPU backlight register was enabled, switching to PCH override\n" ); | |||
1670 | ||||
1671 | /* Write converted CPU PWM value to PCH override register */ | |||
1672 | lpt_set_backlight(connector->base.state, val); | |||
1673 | intel_de_write(dev_priv, BLC_PWM_PCH_CTL1((const i915_reg_t){ .reg = (0xc8250) }), | |||
1674 | pch_ctl1 | BLM_PCH_OVERRIDE_ENABLE(1 << 30)); | |||
1675 | ||||
1676 | intel_de_write(dev_priv, BLC_PWM_CPU_CTL2((const i915_reg_t){ .reg = (0x48250) }), | |||
1677 | cpu_ctl2 & ~BLM_PWM_ENABLE(1 << 31)); | |||
1678 | } | |||
1679 | ||||
1680 | val = intel_panel_compute_brightness(connector, val); | |||
1681 | panel->backlight.level = clamp(val, panel->backlight.min,({ __typeof(val) __min_a = (({ __typeof(val) __max_a = (val); __typeof(val) __max_b = (panel->backlight.min); __max_a > __max_b ? __max_a : __max_b; })); __typeof(val) __min_b = (panel ->backlight.max); __min_a < __min_b ? __min_a : __min_b ; }) | |||
1682 | panel->backlight.max)({ __typeof(val) __min_a = (({ __typeof(val) __max_a = (val); __typeof(val) __max_b = (panel->backlight.min); __max_a > __max_b ? __max_a : __max_b; })); __typeof(val) __min_b = (panel ->backlight.max); __min_a < __min_b ? __min_a : __min_b ; }); | |||
1683 | ||||
1684 | return 0; | |||
1685 | } | |||
1686 | ||||
1687 | static int pch_setup_backlight(struct intel_connector *connector, enum pipe unused) | |||
1688 | { | |||
1689 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
1690 | struct intel_panel *panel = &connector->panel; | |||
1691 | u32 cpu_ctl2, pch_ctl1, pch_ctl2, val; | |||
1692 | ||||
1693 | pch_ctl1 = intel_de_read(dev_priv, BLC_PWM_PCH_CTL1((const i915_reg_t){ .reg = (0xc8250) })); | |||
1694 | panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY(1 << 29); | |||
1695 | ||||
1696 | pch_ctl2 = intel_de_read(dev_priv, BLC_PWM_PCH_CTL2((const i915_reg_t){ .reg = (0xc8254) })); | |||
1697 | panel->backlight.max = pch_ctl2 >> 16; | |||
1698 | ||||
1699 | if (!panel->backlight.max) | |||
1700 | panel->backlight.max = get_backlight_max_vbt(connector); | |||
1701 | ||||
1702 | if (!panel->backlight.max) | |||
1703 | return -ENODEV19; | |||
1704 | ||||
1705 | panel->backlight.min = get_backlight_min_vbt(connector); | |||
1706 | ||||
1707 | val = pch_get_backlight(connector); | |||
1708 | val = intel_panel_compute_brightness(connector, val); | |||
1709 | panel->backlight.level = clamp(val, panel->backlight.min,({ __typeof(val) __min_a = (({ __typeof(val) __max_a = (val); __typeof(val) __max_b = (panel->backlight.min); __max_a > __max_b ? __max_a : __max_b; })); __typeof(val) __min_b = (panel ->backlight.max); __min_a < __min_b ? __min_a : __min_b ; }) | |||
1710 | panel->backlight.max)({ __typeof(val) __min_a = (({ __typeof(val) __max_a = (val); __typeof(val) __max_b = (panel->backlight.min); __max_a > __max_b ? __max_a : __max_b; })); __typeof(val) __min_b = (panel ->backlight.max); __min_a < __min_b ? __min_a : __min_b ; }); | |||
1711 | ||||
1712 | cpu_ctl2 = intel_de_read(dev_priv, BLC_PWM_CPU_CTL2((const i915_reg_t){ .reg = (0x48250) })); | |||
1713 | panel->backlight.enabled = (cpu_ctl2 & BLM_PWM_ENABLE(1 << 31)) && | |||
1714 | (pch_ctl1 & BLM_PCH_PWM_ENABLE(1 << 31)); | |||
1715 | ||||
1716 | return 0; | |||
1717 | } | |||
1718 | ||||
1719 | static int i9xx_setup_backlight(struct intel_connector *connector, enum pipe unused) | |||
1720 | { | |||
1721 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
1722 | struct intel_panel *panel = &connector->panel; | |||
1723 | u32 ctl, val; | |||
1724 | ||||
1725 | ctl = intel_de_read(dev_priv, BLC_PWM_CTL((const i915_reg_t){ .reg = (((&(dev_priv)->__info)-> display_mmio_offset) + 0x61254) })); | |||
1726 | ||||
1727 | if (IS_GEN(dev_priv, 2)(0 + (&(dev_priv)->__info)->gen == (2)) || IS_I915GM(dev_priv)IS_PLATFORM(dev_priv, INTEL_I915GM) || IS_I945GM(dev_priv)IS_PLATFORM(dev_priv, INTEL_I945GM)) | |||
1728 | panel->backlight.combination_mode = ctl & BLM_LEGACY_MODE(1 << 16); | |||
1729 | ||||
1730 | if (IS_PINEVIEW(dev_priv)IS_PLATFORM(dev_priv, INTEL_PINEVIEW)) | |||
1731 | panel->backlight.active_low_pwm = ctl & BLM_POLARITY_PNV(1 << 0); | |||
1732 | ||||
1733 | panel->backlight.max = ctl >> 17; | |||
1734 | ||||
1735 | if (!panel->backlight.max) { | |||
1736 | panel->backlight.max = get_backlight_max_vbt(connector); | |||
1737 | panel->backlight.max >>= 1; | |||
1738 | } | |||
1739 | ||||
1740 | if (!panel->backlight.max) | |||
1741 | return -ENODEV19; | |||
1742 | ||||
1743 | if (panel->backlight.combination_mode) | |||
1744 | panel->backlight.max *= 0xff; | |||
1745 | ||||
1746 | panel->backlight.min = get_backlight_min_vbt(connector); | |||
1747 | ||||
1748 | val = i9xx_get_backlight(connector); | |||
1749 | val = intel_panel_compute_brightness(connector, val); | |||
1750 | panel->backlight.level = clamp(val, panel->backlight.min,({ __typeof(val) __min_a = (({ __typeof(val) __max_a = (val); __typeof(val) __max_b = (panel->backlight.min); __max_a > __max_b ? __max_a : __max_b; })); __typeof(val) __min_b = (panel ->backlight.max); __min_a < __min_b ? __min_a : __min_b ; }) | |||
1751 | panel->backlight.max)({ __typeof(val) __min_a = (({ __typeof(val) __max_a = (val); __typeof(val) __max_b = (panel->backlight.min); __max_a > __max_b ? __max_a : __max_b; })); __typeof(val) __min_b = (panel ->backlight.max); __min_a < __min_b ? __min_a : __min_b ; }); | |||
1752 | ||||
1753 | panel->backlight.enabled = val != 0; | |||
1754 | ||||
1755 | return 0; | |||
1756 | } | |||
1757 | ||||
1758 | static int i965_setup_backlight(struct intel_connector *connector, enum pipe unused) | |||
1759 | { | |||
1760 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
1761 | struct intel_panel *panel = &connector->panel; | |||
1762 | u32 ctl, ctl2, val; | |||
1763 | ||||
1764 | ctl2 = intel_de_read(dev_priv, BLC_PWM_CTL2((const i915_reg_t){ .reg = (((&(dev_priv)->__info)-> display_mmio_offset) + 0x61250) })); | |||
1765 | panel->backlight.combination_mode = ctl2 & BLM_COMBINATION_MODE(1 << 30); | |||
1766 | panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965(1 << 28); | |||
1767 | ||||
1768 | ctl = intel_de_read(dev_priv, BLC_PWM_CTL((const i915_reg_t){ .reg = (((&(dev_priv)->__info)-> display_mmio_offset) + 0x61254) })); | |||
1769 | panel->backlight.max = ctl >> 16; | |||
1770 | ||||
1771 | if (!panel->backlight.max) | |||
1772 | panel->backlight.max = get_backlight_max_vbt(connector); | |||
1773 | ||||
1774 | if (!panel->backlight.max) | |||
1775 | return -ENODEV19; | |||
1776 | ||||
1777 | if (panel->backlight.combination_mode) | |||
1778 | panel->backlight.max *= 0xff; | |||
1779 | ||||
1780 | panel->backlight.min = get_backlight_min_vbt(connector); | |||
1781 | ||||
1782 | val = i9xx_get_backlight(connector); | |||
1783 | val = intel_panel_compute_brightness(connector, val); | |||
1784 | panel->backlight.level = clamp(val, panel->backlight.min,({ __typeof(val) __min_a = (({ __typeof(val) __max_a = (val); __typeof(val) __max_b = (panel->backlight.min); __max_a > __max_b ? __max_a : __max_b; })); __typeof(val) __min_b = (panel ->backlight.max); __min_a < __min_b ? __min_a : __min_b ; }) | |||
1785 | panel->backlight.max)({ __typeof(val) __min_a = (({ __typeof(val) __max_a = (val); __typeof(val) __max_b = (panel->backlight.min); __max_a > __max_b ? __max_a : __max_b; })); __typeof(val) __min_b = (panel ->backlight.max); __min_a < __min_b ? __min_a : __min_b ; }); | |||
1786 | ||||
1787 | panel->backlight.enabled = ctl2 & BLM_PWM_ENABLE(1 << 31); | |||
1788 | ||||
1789 | return 0; | |||
1790 | } | |||
1791 | ||||
1792 | static int vlv_setup_backlight(struct intel_connector *connector, enum pipe pipe) | |||
1793 | { | |||
1794 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
1795 | struct intel_panel *panel = &connector->panel; | |||
1796 | u32 ctl, ctl2, val; | |||
1797 | ||||
1798 | if (drm_WARN_ON(&dev_priv->drm, pipe != PIPE_A && pipe != PIPE_B)({ int __ret = !!((pipe != PIPE_A && pipe != PIPE_B)) ; if (__ret) printf("%s %s: " "%s", dev_driver_string(((& dev_priv->drm))->dev), "", "drm_WARN_ON(" "pipe != PIPE_A && pipe != PIPE_B" ")"); __builtin_expect(!!(__ret), 0); })) | |||
1799 | return -ENODEV19; | |||
1800 | ||||
1801 | ctl2 = intel_de_read(dev_priv, VLV_BLC_PWM_CTL2(pipe)((const i915_reg_t){ .reg = ((((((&(dev_priv)->__info) ->display_mmio_offset) + 0x61250)) + (pipe) * (((((&(dev_priv )->__info)->display_mmio_offset) + 0x61350)) - ((((& (dev_priv)->__info)->display_mmio_offset) + 0x61250)))) ) })); | |||
1802 | panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965(1 << 28); | |||
1803 | ||||
1804 | ctl = intel_de_read(dev_priv, VLV_BLC_PWM_CTL(pipe)((const i915_reg_t){ .reg = ((((((&(dev_priv)->__info) ->display_mmio_offset) + 0x61254)) + (pipe) * (((((&(dev_priv )->__info)->display_mmio_offset) + 0x61354)) - ((((& (dev_priv)->__info)->display_mmio_offset) + 0x61254)))) ) })); | |||
1805 | panel->backlight.max = ctl >> 16; | |||
1806 | ||||
1807 | if (!panel->backlight.max) | |||
1808 | panel->backlight.max = get_backlight_max_vbt(connector); | |||
1809 | ||||
1810 | if (!panel->backlight.max) | |||
1811 | return -ENODEV19; | |||
1812 | ||||
1813 | panel->backlight.min = get_backlight_min_vbt(connector); | |||
1814 | ||||
1815 | val = _vlv_get_backlight(dev_priv, pipe); | |||
1816 | val = intel_panel_compute_brightness(connector, val); | |||
1817 | panel->backlight.level = clamp(val, panel->backlight.min,({ __typeof(val) __min_a = (({ __typeof(val) __max_a = (val); __typeof(val) __max_b = (panel->backlight.min); __max_a > __max_b ? __max_a : __max_b; })); __typeof(val) __min_b = (panel ->backlight.max); __min_a < __min_b ? __min_a : __min_b ; }) | |||
1818 | panel->backlight.max)({ __typeof(val) __min_a = (({ __typeof(val) __max_a = (val); __typeof(val) __max_b = (panel->backlight.min); __max_a > __max_b ? __max_a : __max_b; })); __typeof(val) __min_b = (panel ->backlight.max); __min_a < __min_b ? __min_a : __min_b ; }); | |||
1819 | ||||
1820 | panel->backlight.enabled = ctl2 & BLM_PWM_ENABLE(1 << 31); | |||
1821 | ||||
1822 | return 0; | |||
1823 | } | |||
1824 | ||||
1825 | static int | |||
1826 | bxt_setup_backlight(struct intel_connector *connector, enum pipe unused) | |||
1827 | { | |||
1828 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
1829 | struct intel_panel *panel = &connector->panel; | |||
1830 | u32 pwm_ctl, val; | |||
1831 | ||||
1832 | panel->backlight.controller = dev_priv->vbt.backlight.controller; | |||
1833 | ||||
1834 | pwm_ctl = intel_de_read(dev_priv, | |||
1835 | BXT_BLC_PWM_CTL(panel->backlight.controller)((const i915_reg_t){ .reg = (((0xC8250) + (panel->backlight .controller) * ((0xC8350) - (0xC8250)))) })); | |||
1836 | ||||
1837 | /* Controller 1 uses the utility pin. */ | |||
1838 | if (panel->backlight.controller == 1) { | |||
1839 | val = intel_de_read(dev_priv, UTIL_PIN_CTL((const i915_reg_t){ .reg = (0x48400) })); | |||
1840 | panel->backlight.util_pin_active_low = | |||
1841 | val & UTIL_PIN_POLARITY(1 << 22); | |||
1842 | } | |||
1843 | ||||
1844 | panel->backlight.active_low_pwm = pwm_ctl & BXT_BLC_PWM_POLARITY(1 << 29); | |||
1845 | panel->backlight.max = | |||
1846 | intel_de_read(dev_priv, | |||
1847 | BXT_BLC_PWM_FREQ(panel->backlight.controller)((const i915_reg_t){ .reg = (((0xC8254) + (panel->backlight .controller) * ((0xC8354) - (0xC8254)))) })); | |||
1848 | ||||
1849 | if (!panel->backlight.max) | |||
1850 | panel->backlight.max = get_backlight_max_vbt(connector); | |||
1851 | ||||
1852 | if (!panel->backlight.max) | |||
1853 | return -ENODEV19; | |||
1854 | ||||
1855 | panel->backlight.min = get_backlight_min_vbt(connector); | |||
1856 | ||||
1857 | val = bxt_get_backlight(connector); | |||
1858 | val = intel_panel_compute_brightness(connector, val); | |||
1859 | panel->backlight.level = clamp(val, panel->backlight.min,({ __typeof(val) __min_a = (({ __typeof(val) __max_a = (val); __typeof(val) __max_b = (panel->backlight.min); __max_a > __max_b ? __max_a : __max_b; })); __typeof(val) __min_b = (panel ->backlight.max); __min_a < __min_b ? __min_a : __min_b ; }) | |||
1860 | panel->backlight.max)({ __typeof(val) __min_a = (({ __typeof(val) __max_a = (val); __typeof(val) __max_b = (panel->backlight.min); __max_a > __max_b ? __max_a : __max_b; })); __typeof(val) __min_b = (panel ->backlight.max); __min_a < __min_b ? __min_a : __min_b ; }); | |||
1861 | ||||
1862 | panel->backlight.enabled = pwm_ctl & BXT_BLC_PWM_ENABLE(1 << 31); | |||
1863 | ||||
1864 | return 0; | |||
1865 | } | |||
1866 | ||||
1867 | static int | |||
1868 | cnp_setup_backlight(struct intel_connector *connector, enum pipe unused) | |||
1869 | { | |||
1870 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
1871 | struct intel_panel *panel = &connector->panel; | |||
1872 | u32 pwm_ctl, val; | |||
1873 | ||||
1874 | /* | |||
1875 | * CNP has the BXT implementation of backlight, but with only one | |||
1876 | * controller. TODO: ICP has multiple controllers but we only use | |||
1877 | * controller 0 for now. | |||
1878 | */ | |||
1879 | panel->backlight.controller = 0; | |||
1880 | ||||
1881 | pwm_ctl = intel_de_read(dev_priv, | |||
1882 | BXT_BLC_PWM_CTL(panel->backlight.controller)((const i915_reg_t){ .reg = (((0xC8250) + (panel->backlight .controller) * ((0xC8350) - (0xC8250)))) })); | |||
1883 | ||||
1884 | panel->backlight.active_low_pwm = pwm_ctl & BXT_BLC_PWM_POLARITY(1 << 29); | |||
1885 | panel->backlight.max = | |||
1886 | intel_de_read(dev_priv, | |||
1887 | BXT_BLC_PWM_FREQ(panel->backlight.controller)((const i915_reg_t){ .reg = (((0xC8254) + (panel->backlight .controller) * ((0xC8354) - (0xC8254)))) })); | |||
1888 | ||||
1889 | if (!panel->backlight.max) | |||
1890 | panel->backlight.max = get_backlight_max_vbt(connector); | |||
1891 | ||||
1892 | if (!panel->backlight.max) | |||
1893 | return -ENODEV19; | |||
1894 | ||||
1895 | panel->backlight.min = get_backlight_min_vbt(connector); | |||
1896 | ||||
1897 | val = bxt_get_backlight(connector); | |||
1898 | val = intel_panel_compute_brightness(connector, val); | |||
1899 | panel->backlight.level = clamp(val, panel->backlight.min,({ __typeof(val) __min_a = (({ __typeof(val) __max_a = (val); __typeof(val) __max_b = (panel->backlight.min); __max_a > __max_b ? __max_a : __max_b; })); __typeof(val) __min_b = (panel ->backlight.max); __min_a < __min_b ? __min_a : __min_b ; }) | |||
1900 | panel->backlight.max)({ __typeof(val) __min_a = (({ __typeof(val) __max_a = (val); __typeof(val) __max_b = (panel->backlight.min); __max_a > __max_b ? __max_a : __max_b; })); __typeof(val) __min_b = (panel ->backlight.max); __min_a < __min_b ? __min_a : __min_b ; }); | |||
1901 | ||||
1902 | panel->backlight.enabled = pwm_ctl & BXT_BLC_PWM_ENABLE(1 << 31); | |||
1903 | ||||
1904 | return 0; | |||
1905 | } | |||
1906 | ||||
1907 | static int pwm_setup_backlight(struct intel_connector *connector, | |||
1908 | enum pipe pipe) | |||
1909 | { | |||
1910 | struct drm_device *dev = connector->base.dev; | |||
1911 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(dev); | |||
1912 | struct intel_panel *panel = &connector->panel; | |||
1913 | const char *desc; | |||
1914 | u32 level; | |||
1915 | ||||
1916 | /* Get the right PWM chip for DSI backlight according to VBT */ | |||
1917 | if (dev_priv->vbt.dsi.config->pwm_blc == PPS_BLC_PMIC0) { | |||
1918 | panel->backlight.pwm = pwm_get(dev->dev, "pwm_pmic_backlight"); | |||
1919 | desc = "PMIC"; | |||
1920 | } else { | |||
1921 | panel->backlight.pwm = pwm_get(dev->dev, "pwm_soc_backlight"); | |||
1922 | desc = "SoC"; | |||
1923 | } | |||
1924 | ||||
1925 | if (IS_ERR(panel->backlight.pwm)) { | |||
1926 | drm_err(&dev_priv->drm, "Failed to get the %s PWM chip\n",printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Failed to get the %s PWM chip\n" , ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , desc) | |||
1927 | desc)printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Failed to get the %s PWM chip\n" , ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , desc); | |||
1928 | panel->backlight.pwm = NULL((void *)0); | |||
1929 | return -ENODEV19; | |||
1930 | } | |||
1931 | ||||
1932 | panel->backlight.max = 100; /* 100% */ | |||
1933 | panel->backlight.min = get_backlight_min_vbt(connector); | |||
1934 | ||||
1935 | #ifdef notyet | |||
1936 | if (pwm_is_enabled(panel->backlight.pwm)) { | |||
1937 | /* PWM is already enabled, use existing settings */ | |||
1938 | pwm_get_state(panel->backlight.pwm, &panel->backlight.pwm_state); | |||
1939 | ||||
1940 | level = pwm_get_relative_duty_cycle(&panel->backlight.pwm_state, | |||
1941 | 100); | |||
1942 | level = intel_panel_compute_brightness(connector, level); | |||
1943 | panel->backlight.level = clamp(level, panel->backlight.min,({ __typeof(level) __min_a = (({ __typeof(level) __max_a = (level ); __typeof(level) __max_b = (panel->backlight.min); __max_a > __max_b ? __max_a : __max_b; })); __typeof(level) __min_b = (panel->backlight.max); __min_a < __min_b ? __min_a : __min_b; }) | |||
1944 | panel->backlight.max)({ __typeof(level) __min_a = (({ __typeof(level) __max_a = (level ); __typeof(level) __max_b = (panel->backlight.min); __max_a > __max_b ? __max_a : __max_b; })); __typeof(level) __min_b = (panel->backlight.max); __min_a < __min_b ? __min_a : __min_b; }); | |||
1945 | panel->backlight.enabled = true1; | |||
1946 | ||||
1947 | drm_dbg_kms(&dev_priv->drm, "PWM already enabled at freq %ld, VBT freq %d, level %d\n",drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "PWM already enabled at freq %ld, VBT freq %d, level %d\n" , 1000000000L / (unsigned long)panel->backlight.pwm_state. period, get_vbt_pwm_freq(dev_priv), level) | |||
1948 | NSEC_PER_SEC / (unsigned long)panel->backlight.pwm_state.period,drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "PWM already enabled at freq %ld, VBT freq %d, level %d\n" , 1000000000L / (unsigned long)panel->backlight.pwm_state. period, get_vbt_pwm_freq(dev_priv), level) | |||
1949 | get_vbt_pwm_freq(dev_priv), level)drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "PWM already enabled at freq %ld, VBT freq %d, level %d\n" , 1000000000L / (unsigned long)panel->backlight.pwm_state. period, get_vbt_pwm_freq(dev_priv), level); | |||
1950 | } else { | |||
1951 | /* Set period from VBT frequency, leave other settings at 0. */ | |||
1952 | panel->backlight.pwm_state.period = | |||
1953 | NSEC_PER_SEC1000000000L / get_vbt_pwm_freq(dev_priv); | |||
1954 | } | |||
1955 | #else | |||
1956 | STUB()do { printf("%s: stub\n", __func__); } while(0); | |||
1957 | #endif | |||
1958 | ||||
1959 | drm_info(&dev_priv->drm, "Using %s PWM for LCD backlight control\n",do { } while(0) | |||
1960 | desc)do { } while(0); | |||
1961 | return 0; | |||
1962 | } | |||
1963 | ||||
1964 | void intel_panel_update_backlight(struct intel_atomic_state *state, | |||
1965 | struct intel_encoder *encoder, | |||
1966 | const struct intel_crtc_state *crtc_state, | |||
1967 | const struct drm_connector_state *conn_state) | |||
1968 | { | |||
1969 | struct intel_connector *connector = to_intel_connector(conn_state->connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (conn_state->connector); (struct intel_connector * )( (char *)__mptr - __builtin_offsetof(struct intel_connector , base) );}); | |||
1970 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
1971 | struct intel_panel *panel = &connector->panel; | |||
1972 | ||||
1973 | if (!panel->backlight.present) | |||
1974 | return; | |||
1975 | ||||
1976 | mutex_lock(&dev_priv->backlight_lock)rw_enter_write(&dev_priv->backlight_lock); | |||
1977 | if (!panel->backlight.enabled) | |||
1978 | __intel_panel_enable_backlight(crtc_state, conn_state); | |||
1979 | ||||
1980 | mutex_unlock(&dev_priv->backlight_lock)rw_exit_write(&dev_priv->backlight_lock); | |||
1981 | } | |||
1982 | ||||
1983 | int intel_panel_setup_backlight(struct drm_connector *connector, enum pipe pipe) | |||
1984 | { | |||
1985 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->dev); | |||
1986 | struct intel_connector *intel_connector = to_intel_connector(connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (connector); (struct intel_connector *)( (char *)__mptr - __builtin_offsetof(struct intel_connector, base) );}); | |||
1987 | struct intel_panel *panel = &intel_connector->panel; | |||
1988 | int ret; | |||
1989 | ||||
1990 | if (!dev_priv->vbt.backlight.present) { | |||
1991 | if (dev_priv->quirks & QUIRK_BACKLIGHT_PRESENT(1<<3)) { | |||
1992 | drm_dbg_kms(&dev_priv->drm,drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "no backlight present per VBT, but present per quirk\n" ) | |||
1993 | "no backlight present per VBT, but present per quirk\n")drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "no backlight present per VBT, but present per quirk\n" ); | |||
1994 | } else { | |||
1995 | drm_dbg_kms(&dev_priv->drm,drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "no backlight present per VBT\n" ) | |||
1996 | "no backlight present per VBT\n")drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "no backlight present per VBT\n" ); | |||
1997 | return 0; | |||
1998 | } | |||
1999 | } | |||
2000 | ||||
2001 | /* ensure intel_panel has been initialized first */ | |||
2002 | if (drm_WARN_ON(&dev_priv->drm, !panel->backlight.setup)({ int __ret = !!((!panel->backlight.setup)); if (__ret) printf ("%s %s: " "%s", dev_driver_string(((&dev_priv->drm))-> dev), "", "drm_WARN_ON(" "!panel->backlight.setup" ")"); __builtin_expect (!!(__ret), 0); })) | |||
2003 | return -ENODEV19; | |||
2004 | ||||
2005 | /* set level and max in panel struct */ | |||
2006 | mutex_lock(&dev_priv->backlight_lock)rw_enter_write(&dev_priv->backlight_lock); | |||
2007 | ret = panel->backlight.setup(intel_connector, pipe); | |||
2008 | mutex_unlock(&dev_priv->backlight_lock)rw_exit_write(&dev_priv->backlight_lock); | |||
2009 | ||||
2010 | if (ret) { | |||
2011 | drm_dbg_kms(&dev_priv->drm,drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "failed to setup backlight for connector %s\n" , connector->name) | |||
2012 | "failed to setup backlight for connector %s\n",drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "failed to setup backlight for connector %s\n" , connector->name) | |||
2013 | connector->name)drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "failed to setup backlight for connector %s\n" , connector->name); | |||
2014 | return ret; | |||
2015 | } | |||
2016 | ||||
2017 | panel->backlight.present = true1; | |||
2018 | ||||
2019 | drm_dbg_kms(&dev_priv->drm,drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "Connector %s backlight initialized, %s, brightness %u/%u\n" , connector->name, enableddisabled(panel->backlight.enabled ), panel->backlight.level, panel->backlight.max) | |||
2020 | "Connector %s backlight initialized, %s, brightness %u/%u\n",drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "Connector %s backlight initialized, %s, brightness %u/%u\n" , connector->name, enableddisabled(panel->backlight.enabled ), panel->backlight.level, panel->backlight.max) | |||
2021 | connector->name,drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "Connector %s backlight initialized, %s, brightness %u/%u\n" , connector->name, enableddisabled(panel->backlight.enabled ), panel->backlight.level, panel->backlight.max) | |||
2022 | enableddisabled(panel->backlight.enabled),drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "Connector %s backlight initialized, %s, brightness %u/%u\n" , connector->name, enableddisabled(panel->backlight.enabled ), panel->backlight.level, panel->backlight.max) | |||
2023 | panel->backlight.level, panel->backlight.max)drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "Connector %s backlight initialized, %s, brightness %u/%u\n" , connector->name, enableddisabled(panel->backlight.enabled ), panel->backlight.level, panel->backlight.max); | |||
2024 | ||||
2025 | return 0; | |||
2026 | } | |||
2027 | ||||
2028 | static void intel_panel_destroy_backlight(struct intel_panel *panel) | |||
2029 | { | |||
2030 | /* dispose of the pwm */ | |||
2031 | if (panel->backlight.pwm) | |||
2032 | pwm_put(panel->backlight.pwm); | |||
2033 | ||||
2034 | panel->backlight.present = false0; | |||
2035 | } | |||
2036 | ||||
2037 | /* Set up chip specific backlight functions */ | |||
2038 | static void | |||
2039 | intel_panel_init_backlight_funcs(struct intel_panel *panel) | |||
2040 | { | |||
2041 | struct intel_connector *connector = | |||
2042 | container_of(panel, struct intel_connector, panel)({ const __typeof( ((struct intel_connector *)0)->panel ) * __mptr = (panel); (struct intel_connector *)( (char *)__mptr - __builtin_offsetof(struct intel_connector, panel) );}); | |||
2043 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); | |||
2044 | ||||
2045 | if (connector->base.connector_type == DRM_MODE_CONNECTOR_eDP14 && | |||
2046 | intel_dp_aux_init_backlight_funcs(connector) == 0) | |||
2047 | return; | |||
2048 | ||||
2049 | if (connector->base.connector_type == DRM_MODE_CONNECTOR_DSI16 && | |||
2050 | intel_dsi_dcs_init_backlight_funcs(connector) == 0) | |||
2051 | return; | |||
2052 | ||||
2053 | if (IS_GEN9_LP(dev_priv)((0 + (&(dev_priv)->__info)->gen == (9)) && ((&(dev_priv)->__info)->is_lp))) { | |||
2054 | panel->backlight.setup = bxt_setup_backlight; | |||
2055 | panel->backlight.enable = bxt_enable_backlight; | |||
2056 | panel->backlight.disable = bxt_disable_backlight; | |||
2057 | panel->backlight.set = bxt_set_backlight; | |||
2058 | panel->backlight.get = bxt_get_backlight; | |||
2059 | panel->backlight.hz_to_pwm = bxt_hz_to_pwm; | |||
2060 | } else if (INTEL_PCH_TYPE(dev_priv)((dev_priv)->pch_type) >= PCH_CNP) { | |||
2061 | panel->backlight.setup = cnp_setup_backlight; | |||
2062 | panel->backlight.enable = cnp_enable_backlight; | |||
2063 | panel->backlight.disable = cnp_disable_backlight; | |||
2064 | panel->backlight.set = bxt_set_backlight; | |||
2065 | panel->backlight.get = bxt_get_backlight; | |||
2066 | panel->backlight.hz_to_pwm = cnp_hz_to_pwm; | |||
2067 | } else if (INTEL_PCH_TYPE(dev_priv)((dev_priv)->pch_type) >= PCH_LPT) { | |||
2068 | panel->backlight.setup = lpt_setup_backlight; | |||
2069 | panel->backlight.enable = lpt_enable_backlight; | |||
2070 | panel->backlight.disable = lpt_disable_backlight; | |||
2071 | panel->backlight.set = lpt_set_backlight; | |||
2072 | panel->backlight.get = lpt_get_backlight; | |||
2073 | if (HAS_PCH_LPT(dev_priv)(((dev_priv)->pch_type) == PCH_LPT)) | |||
2074 | panel->backlight.hz_to_pwm = lpt_hz_to_pwm; | |||
2075 | else | |||
2076 | panel->backlight.hz_to_pwm = spt_hz_to_pwm; | |||
2077 | } else if (HAS_PCH_SPLIT(dev_priv)(((dev_priv)->pch_type) != PCH_NONE)) { | |||
2078 | panel->backlight.setup = pch_setup_backlight; | |||
2079 | panel->backlight.enable = pch_enable_backlight; | |||
2080 | panel->backlight.disable = pch_disable_backlight; | |||
2081 | panel->backlight.set = pch_set_backlight; | |||
2082 | panel->backlight.get = pch_get_backlight; | |||
2083 | panel->backlight.hz_to_pwm = pch_hz_to_pwm; | |||
2084 | } else if (IS_VALLEYVIEW(dev_priv)IS_PLATFORM(dev_priv, INTEL_VALLEYVIEW) || IS_CHERRYVIEW(dev_priv)IS_PLATFORM(dev_priv, INTEL_CHERRYVIEW)) { | |||
2085 | if (connector->base.connector_type == DRM_MODE_CONNECTOR_DSI16) { | |||
2086 | panel->backlight.setup = pwm_setup_backlight; | |||
2087 | panel->backlight.enable = pwm_enable_backlight; | |||
2088 | panel->backlight.disable = pwm_disable_backlight; | |||
2089 | panel->backlight.set = pwm_set_backlight; | |||
2090 | panel->backlight.get = pwm_get_backlight; | |||
2091 | } else { | |||
2092 | panel->backlight.setup = vlv_setup_backlight; | |||
2093 | panel->backlight.enable = vlv_enable_backlight; | |||
2094 | panel->backlight.disable = vlv_disable_backlight; | |||
2095 | panel->backlight.set = vlv_set_backlight; | |||
2096 | panel->backlight.get = vlv_get_backlight; | |||
2097 | panel->backlight.hz_to_pwm = vlv_hz_to_pwm; | |||
2098 | } | |||
2099 | } else if (IS_GEN(dev_priv, 4)(0 + (&(dev_priv)->__info)->gen == (4))) { | |||
2100 | panel->backlight.setup = i965_setup_backlight; | |||
2101 | panel->backlight.enable = i965_enable_backlight; | |||
2102 | panel->backlight.disable = i965_disable_backlight; | |||
2103 | panel->backlight.set = i9xx_set_backlight; | |||
2104 | panel->backlight.get = i9xx_get_backlight; | |||
2105 | panel->backlight.hz_to_pwm = i965_hz_to_pwm; | |||
2106 | } else { | |||
2107 | panel->backlight.setup = i9xx_setup_backlight; | |||
2108 | panel->backlight.enable = i9xx_enable_backlight; | |||
2109 | panel->backlight.disable = i9xx_disable_backlight; | |||
2110 | panel->backlight.set = i9xx_set_backlight; | |||
2111 | panel->backlight.get = i9xx_get_backlight; | |||
2112 | panel->backlight.hz_to_pwm = i9xx_hz_to_pwm; | |||
2113 | } | |||
2114 | } | |||
2115 | ||||
2116 | enum drm_connector_status | |||
2117 | intel_panel_detect(struct drm_connector *connector, bool_Bool force) | |||
2118 | { | |||
2119 | struct drm_i915_privateinteldrm_softc *i915 = to_i915(connector->dev); | |||
2120 | ||||
2121 | if (!INTEL_DISPLAY_ENABLED(i915)(({ int __ret = !!((!((&(i915)->__info)->pipe_mask != 0))); if (__ret) printf("%s %s: " "%s", dev_driver_string((( &(i915)->drm))->dev), "", "drm_WARN_ON(" "!((&(i915)->__info)->pipe_mask != 0)" ")"); __builtin_expect(!!(__ret), 0); }), !(i915)->params .disable_display)) | |||
2122 | return connector_status_disconnected; | |||
2123 | ||||
2124 | return connector_status_connected; | |||
2125 | } | |||
2126 | ||||
2127 | int intel_panel_init(struct intel_panel *panel, | |||
2128 | struct drm_display_mode *fixed_mode, | |||
2129 | struct drm_display_mode *downclock_mode) | |||
2130 | { | |||
2131 | intel_panel_init_backlight_funcs(panel); | |||
2132 | ||||
2133 | panel->fixed_mode = fixed_mode; | |||
2134 | panel->downclock_mode = downclock_mode; | |||
2135 | ||||
2136 | return 0; | |||
2137 | } | |||
2138 | ||||
2139 | void intel_panel_fini(struct intel_panel *panel) | |||
2140 | { | |||
2141 | struct intel_connector *intel_connector = | |||
2142 | container_of(panel, struct intel_connector, panel)({ const __typeof( ((struct intel_connector *)0)->panel ) * __mptr = (panel); (struct intel_connector *)( (char *)__mptr - __builtin_offsetof(struct intel_connector, panel) );}); | |||
2143 | ||||
2144 | intel_panel_destroy_backlight(panel); | |||
2145 | ||||
2146 | if (panel->fixed_mode) | |||
2147 | drm_mode_destroy(intel_connector->base.dev, panel->fixed_mode); | |||
2148 | ||||
2149 | if (panel->downclock_mode) | |||
2150 | drm_mode_destroy(intel_connector->base.dev, | |||
2151 | panel->downclock_mode); | |||
2152 | } |