Rev 4560 | Rev 5097 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4560 | Rev 5060 | ||
---|---|---|---|
1 | /* |
1 | /* |
2 | * Copyright © 2006-2010 Intel Corporation |
2 | * Copyright © 2006-2010 Intel Corporation |
3 | * Copyright (c) 2006 Dave Airlie |
3 | * Copyright (c) 2006 Dave Airlie |
4 | * |
4 | * |
5 | * Permission is hereby granted, free of charge, to any person obtaining a |
5 | * Permission is hereby granted, free of charge, to any person obtaining a |
6 | * copy of this software and associated documentation files (the "Software"), |
6 | * copy of this software and associated documentation files (the "Software"), |
7 | * to deal in the Software without restriction, including without limitation |
7 | * to deal in the Software without restriction, including without limitation |
8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
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 |
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: |
10 | * Software is furnished to do so, subject to the following conditions: |
11 | * |
11 | * |
12 | * The above copyright notice and this permission notice (including the next |
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 |
13 | * paragraph) shall be included in all copies or substantial portions of the |
14 | * Software. |
14 | * Software. |
15 | * |
15 | * |
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
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, |
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
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 |
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 |
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 |
21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
22 | * DEALINGS IN THE SOFTWARE. |
22 | * DEALINGS IN THE SOFTWARE. |
23 | * |
23 | * |
24 | * Authors: |
24 | * Authors: |
25 | * Eric Anholt |
25 | * Eric Anholt |
26 | * Dave Airlie |
26 | * Dave Airlie |
27 | * Jesse Barnes |
27 | * Jesse Barnes |
28 | * Chris Wilson |
28 | * Chris Wilson |
29 | */ |
29 | */ |
30 | 30 | ||
31 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
31 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
32 | 32 | ||
33 | #include |
33 | #include |
34 | #include "intel_drv.h" |
34 | #include "intel_drv.h" |
35 | - | ||
36 | #define PCI_LBPC 0xf4 /* legacy/combination backlight modes */ |
- | |
37 | 35 | ||
38 | void |
36 | void |
39 | intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode, |
37 | intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode, |
40 | struct drm_display_mode *adjusted_mode) |
38 | struct drm_display_mode *adjusted_mode) |
41 | { |
39 | { |
42 | drm_mode_copy(adjusted_mode, fixed_mode); |
40 | drm_mode_copy(adjusted_mode, fixed_mode); |
43 | 41 | ||
44 | drm_mode_set_crtcinfo(adjusted_mode, 0); |
42 | drm_mode_set_crtcinfo(adjusted_mode, 0); |
45 | } |
43 | } |
- | 44 | ||
- | 45 | /** |
|
- | 46 | * intel_find_panel_downclock - find the reduced downclock for LVDS in EDID |
|
- | 47 | * @dev: drm device |
|
- | 48 | * @fixed_mode : panel native mode |
|
- | 49 | * @connector: LVDS/eDP connector |
|
- | 50 | * |
|
- | 51 | * Return downclock_avail |
|
- | 52 | * Find the reduced downclock for LVDS/eDP in EDID. |
|
- | 53 | */ |
|
- | 54 | struct drm_display_mode * |
|
- | 55 | intel_find_panel_downclock(struct drm_device *dev, |
|
- | 56 | struct drm_display_mode *fixed_mode, |
|
- | 57 | struct drm_connector *connector) |
|
- | 58 | { |
|
- | 59 | struct drm_display_mode *scan, *tmp_mode; |
|
- | 60 | int temp_downclock; |
|
- | 61 | ||
- | 62 | temp_downclock = fixed_mode->clock; |
|
- | 63 | tmp_mode = NULL; |
|
- | 64 | ||
- | 65 | list_for_each_entry(scan, &connector->probed_modes, head) { |
|
- | 66 | /* |
|
- | 67 | * If one mode has the same resolution with the fixed_panel |
|
- | 68 | * mode while they have the different refresh rate, it means |
|
- | 69 | * that the reduced downclock is found. In such |
|
- | 70 | * case we can set the different FPx0/1 to dynamically select |
|
- | 71 | * between low and high frequency. |
|
- | 72 | */ |
|
- | 73 | if (scan->hdisplay == fixed_mode->hdisplay && |
|
- | 74 | scan->hsync_start == fixed_mode->hsync_start && |
|
- | 75 | scan->hsync_end == fixed_mode->hsync_end && |
|
- | 76 | scan->htotal == fixed_mode->htotal && |
|
- | 77 | scan->vdisplay == fixed_mode->vdisplay && |
|
- | 78 | scan->vsync_start == fixed_mode->vsync_start && |
|
- | 79 | scan->vsync_end == fixed_mode->vsync_end && |
|
- | 80 | scan->vtotal == fixed_mode->vtotal) { |
|
- | 81 | if (scan->clock < temp_downclock) { |
|
- | 82 | /* |
|
- | 83 | * The downclock is already found. But we |
|
- | 84 | * expect to find the lower downclock. |
|
- | 85 | */ |
|
- | 86 | temp_downclock = scan->clock; |
|
- | 87 | tmp_mode = scan; |
|
- | 88 | } |
|
- | 89 | } |
|
- | 90 | } |
|
- | 91 | ||
- | 92 | if (temp_downclock < fixed_mode->clock) |
|
- | 93 | return drm_mode_duplicate(dev, tmp_mode); |
|
- | 94 | else |
|
- | 95 | return NULL; |
|
- | 96 | } |
|
46 | 97 | ||
47 | /* adjusted_mode has been preset to be the panel's fixed mode */ |
98 | /* adjusted_mode has been preset to be the panel's fixed mode */ |
48 | void |
99 | void |
49 | intel_pch_panel_fitting(struct intel_crtc *intel_crtc, |
100 | intel_pch_panel_fitting(struct intel_crtc *intel_crtc, |
50 | struct intel_crtc_config *pipe_config, |
101 | struct intel_crtc_config *pipe_config, |
51 | int fitting_mode) |
102 | int fitting_mode) |
52 | { |
103 | { |
53 | struct drm_display_mode *adjusted_mode; |
104 | struct drm_display_mode *adjusted_mode; |
54 | int x, y, width, height; |
105 | int x, y, width, height; |
55 | 106 | ||
56 | adjusted_mode = &pipe_config->adjusted_mode; |
107 | adjusted_mode = &pipe_config->adjusted_mode; |
57 | 108 | ||
58 | x = y = width = height = 0; |
109 | x = y = width = height = 0; |
59 | 110 | ||
60 | /* Native modes don't need fitting */ |
111 | /* Native modes don't need fitting */ |
61 | if (adjusted_mode->hdisplay == pipe_config->pipe_src_w && |
112 | if (adjusted_mode->hdisplay == pipe_config->pipe_src_w && |
62 | adjusted_mode->vdisplay == pipe_config->pipe_src_h) |
113 | adjusted_mode->vdisplay == pipe_config->pipe_src_h) |
63 | goto done; |
114 | goto done; |
64 | 115 | ||
65 | switch (fitting_mode) { |
116 | switch (fitting_mode) { |
66 | case DRM_MODE_SCALE_CENTER: |
117 | case DRM_MODE_SCALE_CENTER: |
67 | width = pipe_config->pipe_src_w; |
118 | width = pipe_config->pipe_src_w; |
68 | height = pipe_config->pipe_src_h; |
119 | height = pipe_config->pipe_src_h; |
69 | x = (adjusted_mode->hdisplay - width + 1)/2; |
120 | x = (adjusted_mode->hdisplay - width + 1)/2; |
70 | y = (adjusted_mode->vdisplay - height + 1)/2; |
121 | y = (adjusted_mode->vdisplay - height + 1)/2; |
71 | break; |
122 | break; |
72 | 123 | ||
73 | case DRM_MODE_SCALE_ASPECT: |
124 | case DRM_MODE_SCALE_ASPECT: |
74 | /* Scale but preserve the aspect ratio */ |
125 | /* Scale but preserve the aspect ratio */ |
75 | { |
126 | { |
76 | u32 scaled_width = adjusted_mode->hdisplay |
127 | u32 scaled_width = adjusted_mode->hdisplay |
77 | * pipe_config->pipe_src_h; |
128 | * pipe_config->pipe_src_h; |
78 | u32 scaled_height = pipe_config->pipe_src_w |
129 | u32 scaled_height = pipe_config->pipe_src_w |
79 | * adjusted_mode->vdisplay; |
130 | * adjusted_mode->vdisplay; |
80 | if (scaled_width > scaled_height) { /* pillar */ |
131 | if (scaled_width > scaled_height) { /* pillar */ |
81 | width = scaled_height / pipe_config->pipe_src_h; |
132 | width = scaled_height / pipe_config->pipe_src_h; |
82 | if (width & 1) |
133 | if (width & 1) |
83 | width++; |
134 | width++; |
84 | x = (adjusted_mode->hdisplay - width + 1) / 2; |
135 | x = (adjusted_mode->hdisplay - width + 1) / 2; |
85 | y = 0; |
136 | y = 0; |
86 | height = adjusted_mode->vdisplay; |
137 | height = adjusted_mode->vdisplay; |
87 | } else if (scaled_width < scaled_height) { /* letter */ |
138 | } else if (scaled_width < scaled_height) { /* letter */ |
88 | height = scaled_width / pipe_config->pipe_src_w; |
139 | height = scaled_width / pipe_config->pipe_src_w; |
89 | if (height & 1) |
140 | if (height & 1) |
90 | height++; |
141 | height++; |
91 | y = (adjusted_mode->vdisplay - height + 1) / 2; |
142 | y = (adjusted_mode->vdisplay - height + 1) / 2; |
92 | x = 0; |
143 | x = 0; |
93 | width = adjusted_mode->hdisplay; |
144 | width = adjusted_mode->hdisplay; |
94 | } else { |
145 | } else { |
95 | x = y = 0; |
146 | x = y = 0; |
96 | width = adjusted_mode->hdisplay; |
147 | width = adjusted_mode->hdisplay; |
97 | height = adjusted_mode->vdisplay; |
148 | height = adjusted_mode->vdisplay; |
98 | } |
149 | } |
99 | } |
150 | } |
100 | break; |
151 | break; |
101 | 152 | ||
102 | case DRM_MODE_SCALE_FULLSCREEN: |
153 | case DRM_MODE_SCALE_FULLSCREEN: |
103 | x = y = 0; |
154 | x = y = 0; |
104 | width = adjusted_mode->hdisplay; |
155 | width = adjusted_mode->hdisplay; |
105 | height = adjusted_mode->vdisplay; |
156 | height = adjusted_mode->vdisplay; |
106 | break; |
157 | break; |
107 | 158 | ||
108 | default: |
159 | default: |
109 | WARN(1, "bad panel fit mode: %d\n", fitting_mode); |
160 | WARN(1, "bad panel fit mode: %d\n", fitting_mode); |
110 | return; |
161 | return; |
111 | } |
162 | } |
112 | 163 | ||
113 | done: |
164 | done: |
114 | pipe_config->pch_pfit.pos = (x << 16) | y; |
165 | pipe_config->pch_pfit.pos = (x << 16) | y; |
115 | pipe_config->pch_pfit.size = (width << 16) | height; |
166 | pipe_config->pch_pfit.size = (width << 16) | height; |
116 | pipe_config->pch_pfit.enabled = pipe_config->pch_pfit.size != 0; |
167 | pipe_config->pch_pfit.enabled = pipe_config->pch_pfit.size != 0; |
117 | } |
168 | } |
118 | 169 | ||
119 | static void |
170 | static void |
120 | centre_horizontally(struct drm_display_mode *mode, |
171 | centre_horizontally(struct drm_display_mode *mode, |
121 | int width) |
172 | int width) |
122 | { |
173 | { |
123 | u32 border, sync_pos, blank_width, sync_width; |
174 | u32 border, sync_pos, blank_width, sync_width; |
124 | 175 | ||
125 | /* keep the hsync and hblank widths constant */ |
176 | /* keep the hsync and hblank widths constant */ |
126 | sync_width = mode->crtc_hsync_end - mode->crtc_hsync_start; |
177 | sync_width = mode->crtc_hsync_end - mode->crtc_hsync_start; |
127 | blank_width = mode->crtc_hblank_end - mode->crtc_hblank_start; |
178 | blank_width = mode->crtc_hblank_end - mode->crtc_hblank_start; |
128 | sync_pos = (blank_width - sync_width + 1) / 2; |
179 | sync_pos = (blank_width - sync_width + 1) / 2; |
129 | 180 | ||
130 | border = (mode->hdisplay - width + 1) / 2; |
181 | border = (mode->hdisplay - width + 1) / 2; |
131 | border += border & 1; /* make the border even */ |
182 | border += border & 1; /* make the border even */ |
132 | 183 | ||
133 | mode->crtc_hdisplay = width; |
184 | mode->crtc_hdisplay = width; |
134 | mode->crtc_hblank_start = width + border; |
185 | mode->crtc_hblank_start = width + border; |
135 | mode->crtc_hblank_end = mode->crtc_hblank_start + blank_width; |
186 | mode->crtc_hblank_end = mode->crtc_hblank_start + blank_width; |
136 | 187 | ||
137 | mode->crtc_hsync_start = mode->crtc_hblank_start + sync_pos; |
188 | mode->crtc_hsync_start = mode->crtc_hblank_start + sync_pos; |
138 | mode->crtc_hsync_end = mode->crtc_hsync_start + sync_width; |
189 | mode->crtc_hsync_end = mode->crtc_hsync_start + sync_width; |
139 | } |
190 | } |
140 | 191 | ||
141 | static void |
192 | static void |
142 | centre_vertically(struct drm_display_mode *mode, |
193 | centre_vertically(struct drm_display_mode *mode, |
143 | int height) |
194 | int height) |
144 | { |
195 | { |
145 | u32 border, sync_pos, blank_width, sync_width; |
196 | u32 border, sync_pos, blank_width, sync_width; |
146 | 197 | ||
147 | /* keep the vsync and vblank widths constant */ |
198 | /* keep the vsync and vblank widths constant */ |
148 | sync_width = mode->crtc_vsync_end - mode->crtc_vsync_start; |
199 | sync_width = mode->crtc_vsync_end - mode->crtc_vsync_start; |
149 | blank_width = mode->crtc_vblank_end - mode->crtc_vblank_start; |
200 | blank_width = mode->crtc_vblank_end - mode->crtc_vblank_start; |
150 | sync_pos = (blank_width - sync_width + 1) / 2; |
201 | sync_pos = (blank_width - sync_width + 1) / 2; |
151 | 202 | ||
152 | border = (mode->vdisplay - height + 1) / 2; |
203 | border = (mode->vdisplay - height + 1) / 2; |
153 | 204 | ||
154 | mode->crtc_vdisplay = height; |
205 | mode->crtc_vdisplay = height; |
155 | mode->crtc_vblank_start = height + border; |
206 | mode->crtc_vblank_start = height + border; |
156 | mode->crtc_vblank_end = mode->crtc_vblank_start + blank_width; |
207 | mode->crtc_vblank_end = mode->crtc_vblank_start + blank_width; |
157 | 208 | ||
158 | mode->crtc_vsync_start = mode->crtc_vblank_start + sync_pos; |
209 | mode->crtc_vsync_start = mode->crtc_vblank_start + sync_pos; |
159 | mode->crtc_vsync_end = mode->crtc_vsync_start + sync_width; |
210 | mode->crtc_vsync_end = mode->crtc_vsync_start + sync_width; |
160 | } |
211 | } |
161 | 212 | ||
162 | static inline u32 panel_fitter_scaling(u32 source, u32 target) |
213 | static inline u32 panel_fitter_scaling(u32 source, u32 target) |
163 | { |
214 | { |
164 | /* |
215 | /* |
165 | * Floating point operation is not supported. So the FACTOR |
216 | * Floating point operation is not supported. So the FACTOR |
166 | * is defined, which can avoid the floating point computation |
217 | * is defined, which can avoid the floating point computation |
167 | * when calculating the panel ratio. |
218 | * when calculating the panel ratio. |
168 | */ |
219 | */ |
169 | #define ACCURACY 12 |
220 | #define ACCURACY 12 |
170 | #define FACTOR (1 << ACCURACY) |
221 | #define FACTOR (1 << ACCURACY) |
171 | u32 ratio = source * FACTOR / target; |
222 | u32 ratio = source * FACTOR / target; |
172 | return (FACTOR * ratio + FACTOR/2) / FACTOR; |
223 | return (FACTOR * ratio + FACTOR/2) / FACTOR; |
173 | } |
224 | } |
174 | 225 | ||
175 | static void i965_scale_aspect(struct intel_crtc_config *pipe_config, |
226 | static void i965_scale_aspect(struct intel_crtc_config *pipe_config, |
176 | u32 *pfit_control) |
227 | u32 *pfit_control) |
177 | { |
228 | { |
178 | struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode; |
229 | struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode; |
179 | u32 scaled_width = adjusted_mode->hdisplay * |
230 | u32 scaled_width = adjusted_mode->hdisplay * |
180 | pipe_config->pipe_src_h; |
231 | pipe_config->pipe_src_h; |
181 | u32 scaled_height = pipe_config->pipe_src_w * |
232 | u32 scaled_height = pipe_config->pipe_src_w * |
182 | adjusted_mode->vdisplay; |
233 | adjusted_mode->vdisplay; |
183 | 234 | ||
184 | /* 965+ is easy, it does everything in hw */ |
235 | /* 965+ is easy, it does everything in hw */ |
185 | if (scaled_width > scaled_height) |
236 | if (scaled_width > scaled_height) |
186 | *pfit_control |= PFIT_ENABLE | |
237 | *pfit_control |= PFIT_ENABLE | |
187 | PFIT_SCALING_PILLAR; |
238 | PFIT_SCALING_PILLAR; |
188 | else if (scaled_width < scaled_height) |
239 | else if (scaled_width < scaled_height) |
189 | *pfit_control |= PFIT_ENABLE | |
240 | *pfit_control |= PFIT_ENABLE | |
190 | PFIT_SCALING_LETTER; |
241 | PFIT_SCALING_LETTER; |
191 | else if (adjusted_mode->hdisplay != pipe_config->pipe_src_w) |
242 | else if (adjusted_mode->hdisplay != pipe_config->pipe_src_w) |
192 | *pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO; |
243 | *pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO; |
193 | } |
244 | } |
194 | 245 | ||
195 | static void i9xx_scale_aspect(struct intel_crtc_config *pipe_config, |
246 | static void i9xx_scale_aspect(struct intel_crtc_config *pipe_config, |
196 | u32 *pfit_control, u32 *pfit_pgm_ratios, |
247 | u32 *pfit_control, u32 *pfit_pgm_ratios, |
197 | u32 *border) |
248 | u32 *border) |
198 | { |
249 | { |
199 | struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode; |
250 | struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode; |
200 | u32 scaled_width = adjusted_mode->hdisplay * |
251 | u32 scaled_width = adjusted_mode->hdisplay * |
201 | pipe_config->pipe_src_h; |
252 | pipe_config->pipe_src_h; |
202 | u32 scaled_height = pipe_config->pipe_src_w * |
253 | u32 scaled_height = pipe_config->pipe_src_w * |
203 | adjusted_mode->vdisplay; |
254 | adjusted_mode->vdisplay; |
204 | u32 bits; |
255 | u32 bits; |
205 | 256 | ||
206 | /* |
257 | /* |
207 | * For earlier chips we have to calculate the scaling |
258 | * For earlier chips we have to calculate the scaling |
208 | * ratio by hand and program it into the |
259 | * ratio by hand and program it into the |
209 | * PFIT_PGM_RATIO register |
260 | * PFIT_PGM_RATIO register |
210 | */ |
261 | */ |
211 | if (scaled_width > scaled_height) { /* pillar */ |
262 | if (scaled_width > scaled_height) { /* pillar */ |
212 | centre_horizontally(adjusted_mode, |
263 | centre_horizontally(adjusted_mode, |
213 | scaled_height / |
264 | scaled_height / |
214 | pipe_config->pipe_src_h); |
265 | pipe_config->pipe_src_h); |
215 | 266 | ||
216 | *border = LVDS_BORDER_ENABLE; |
267 | *border = LVDS_BORDER_ENABLE; |
217 | if (pipe_config->pipe_src_h != adjusted_mode->vdisplay) { |
268 | if (pipe_config->pipe_src_h != adjusted_mode->vdisplay) { |
218 | bits = panel_fitter_scaling(pipe_config->pipe_src_h, |
269 | bits = panel_fitter_scaling(pipe_config->pipe_src_h, |
219 | adjusted_mode->vdisplay); |
270 | adjusted_mode->vdisplay); |
220 | 271 | ||
221 | *pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT | |
272 | *pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT | |
222 | bits << PFIT_VERT_SCALE_SHIFT); |
273 | bits << PFIT_VERT_SCALE_SHIFT); |
223 | *pfit_control |= (PFIT_ENABLE | |
274 | *pfit_control |= (PFIT_ENABLE | |
224 | VERT_INTERP_BILINEAR | |
275 | VERT_INTERP_BILINEAR | |
225 | HORIZ_INTERP_BILINEAR); |
276 | HORIZ_INTERP_BILINEAR); |
226 | } |
277 | } |
227 | } else if (scaled_width < scaled_height) { /* letter */ |
278 | } else if (scaled_width < scaled_height) { /* letter */ |
228 | centre_vertically(adjusted_mode, |
279 | centre_vertically(adjusted_mode, |
229 | scaled_width / |
280 | scaled_width / |
230 | pipe_config->pipe_src_w); |
281 | pipe_config->pipe_src_w); |
231 | 282 | ||
232 | *border = LVDS_BORDER_ENABLE; |
283 | *border = LVDS_BORDER_ENABLE; |
233 | if (pipe_config->pipe_src_w != adjusted_mode->hdisplay) { |
284 | if (pipe_config->pipe_src_w != adjusted_mode->hdisplay) { |
234 | bits = panel_fitter_scaling(pipe_config->pipe_src_w, |
285 | bits = panel_fitter_scaling(pipe_config->pipe_src_w, |
235 | adjusted_mode->hdisplay); |
286 | adjusted_mode->hdisplay); |
236 | 287 | ||
237 | *pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT | |
288 | *pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT | |
238 | bits << PFIT_VERT_SCALE_SHIFT); |
289 | bits << PFIT_VERT_SCALE_SHIFT); |
239 | *pfit_control |= (PFIT_ENABLE | |
290 | *pfit_control |= (PFIT_ENABLE | |
240 | VERT_INTERP_BILINEAR | |
291 | VERT_INTERP_BILINEAR | |
241 | HORIZ_INTERP_BILINEAR); |
292 | HORIZ_INTERP_BILINEAR); |
242 | } |
293 | } |
243 | } else { |
294 | } else { |
244 | /* Aspects match, Let hw scale both directions */ |
295 | /* Aspects match, Let hw scale both directions */ |
245 | *pfit_control |= (PFIT_ENABLE | |
296 | *pfit_control |= (PFIT_ENABLE | |
246 | VERT_AUTO_SCALE | HORIZ_AUTO_SCALE | |
297 | VERT_AUTO_SCALE | HORIZ_AUTO_SCALE | |
247 | VERT_INTERP_BILINEAR | |
298 | VERT_INTERP_BILINEAR | |
248 | HORIZ_INTERP_BILINEAR); |
299 | HORIZ_INTERP_BILINEAR); |
249 | } |
300 | } |
250 | } |
301 | } |
251 | 302 | ||
252 | void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc, |
303 | void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc, |
253 | struct intel_crtc_config *pipe_config, |
304 | struct intel_crtc_config *pipe_config, |
254 | int fitting_mode) |
305 | int fitting_mode) |
255 | { |
306 | { |
256 | struct drm_device *dev = intel_crtc->base.dev; |
307 | struct drm_device *dev = intel_crtc->base.dev; |
257 | u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0; |
308 | u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0; |
258 | struct drm_display_mode *adjusted_mode; |
309 | struct drm_display_mode *adjusted_mode; |
259 | 310 | ||
260 | adjusted_mode = &pipe_config->adjusted_mode; |
311 | adjusted_mode = &pipe_config->adjusted_mode; |
261 | 312 | ||
262 | /* Native modes don't need fitting */ |
313 | /* Native modes don't need fitting */ |
263 | if (adjusted_mode->hdisplay == pipe_config->pipe_src_w && |
314 | if (adjusted_mode->hdisplay == pipe_config->pipe_src_w && |
264 | adjusted_mode->vdisplay == pipe_config->pipe_src_h) |
315 | adjusted_mode->vdisplay == pipe_config->pipe_src_h) |
265 | goto out; |
316 | goto out; |
266 | 317 | ||
267 | switch (fitting_mode) { |
318 | switch (fitting_mode) { |
268 | case DRM_MODE_SCALE_CENTER: |
319 | case DRM_MODE_SCALE_CENTER: |
269 | /* |
320 | /* |
270 | * For centered modes, we have to calculate border widths & |
321 | * For centered modes, we have to calculate border widths & |
271 | * heights and modify the values programmed into the CRTC. |
322 | * heights and modify the values programmed into the CRTC. |
272 | */ |
323 | */ |
273 | centre_horizontally(adjusted_mode, pipe_config->pipe_src_w); |
324 | centre_horizontally(adjusted_mode, pipe_config->pipe_src_w); |
274 | centre_vertically(adjusted_mode, pipe_config->pipe_src_h); |
325 | centre_vertically(adjusted_mode, pipe_config->pipe_src_h); |
275 | border = LVDS_BORDER_ENABLE; |
326 | border = LVDS_BORDER_ENABLE; |
276 | break; |
327 | break; |
277 | case DRM_MODE_SCALE_ASPECT: |
328 | case DRM_MODE_SCALE_ASPECT: |
278 | /* Scale but preserve the aspect ratio */ |
329 | /* Scale but preserve the aspect ratio */ |
279 | if (INTEL_INFO(dev)->gen >= 4) |
330 | if (INTEL_INFO(dev)->gen >= 4) |
280 | i965_scale_aspect(pipe_config, &pfit_control); |
331 | i965_scale_aspect(pipe_config, &pfit_control); |
281 | else |
332 | else |
282 | i9xx_scale_aspect(pipe_config, &pfit_control, |
333 | i9xx_scale_aspect(pipe_config, &pfit_control, |
283 | &pfit_pgm_ratios, &border); |
334 | &pfit_pgm_ratios, &border); |
284 | break; |
335 | break; |
285 | case DRM_MODE_SCALE_FULLSCREEN: |
336 | case DRM_MODE_SCALE_FULLSCREEN: |
286 | /* |
337 | /* |
287 | * Full scaling, even if it changes the aspect ratio. |
338 | * Full scaling, even if it changes the aspect ratio. |
288 | * Fortunately this is all done for us in hw. |
339 | * Fortunately this is all done for us in hw. |
289 | */ |
340 | */ |
290 | if (pipe_config->pipe_src_h != adjusted_mode->vdisplay || |
341 | if (pipe_config->pipe_src_h != adjusted_mode->vdisplay || |
291 | pipe_config->pipe_src_w != adjusted_mode->hdisplay) { |
342 | pipe_config->pipe_src_w != adjusted_mode->hdisplay) { |
292 | pfit_control |= PFIT_ENABLE; |
343 | pfit_control |= PFIT_ENABLE; |
293 | if (INTEL_INFO(dev)->gen >= 4) |
344 | if (INTEL_INFO(dev)->gen >= 4) |
294 | pfit_control |= PFIT_SCALING_AUTO; |
345 | pfit_control |= PFIT_SCALING_AUTO; |
295 | else |
346 | else |
296 | pfit_control |= (VERT_AUTO_SCALE | |
347 | pfit_control |= (VERT_AUTO_SCALE | |
297 | VERT_INTERP_BILINEAR | |
348 | VERT_INTERP_BILINEAR | |
298 | HORIZ_AUTO_SCALE | |
349 | HORIZ_AUTO_SCALE | |
299 | HORIZ_INTERP_BILINEAR); |
350 | HORIZ_INTERP_BILINEAR); |
300 | } |
351 | } |
301 | break; |
352 | break; |
302 | default: |
353 | default: |
303 | WARN(1, "bad panel fit mode: %d\n", fitting_mode); |
354 | WARN(1, "bad panel fit mode: %d\n", fitting_mode); |
304 | return; |
355 | return; |
305 | } |
356 | } |
306 | 357 | ||
307 | /* 965+ wants fuzzy fitting */ |
358 | /* 965+ wants fuzzy fitting */ |
308 | /* FIXME: handle multiple panels by failing gracefully */ |
359 | /* FIXME: handle multiple panels by failing gracefully */ |
309 | if (INTEL_INFO(dev)->gen >= 4) |
360 | if (INTEL_INFO(dev)->gen >= 4) |
310 | pfit_control |= ((intel_crtc->pipe << PFIT_PIPE_SHIFT) | |
361 | pfit_control |= ((intel_crtc->pipe << PFIT_PIPE_SHIFT) | |
311 | PFIT_FILTER_FUZZY); |
362 | PFIT_FILTER_FUZZY); |
312 | 363 | ||
313 | out: |
364 | out: |
314 | if ((pfit_control & PFIT_ENABLE) == 0) { |
365 | if ((pfit_control & PFIT_ENABLE) == 0) { |
315 | pfit_control = 0; |
366 | pfit_control = 0; |
316 | pfit_pgm_ratios = 0; |
367 | pfit_pgm_ratios = 0; |
317 | } |
368 | } |
318 | 369 | ||
319 | /* Make sure pre-965 set dither correctly for 18bpp panels. */ |
370 | /* Make sure pre-965 set dither correctly for 18bpp panels. */ |
320 | if (INTEL_INFO(dev)->gen < 4 && pipe_config->pipe_bpp == 18) |
371 | if (INTEL_INFO(dev)->gen < 4 && pipe_config->pipe_bpp == 18) |
321 | pfit_control |= PANEL_8TO6_DITHER_ENABLE; |
372 | pfit_control |= PANEL_8TO6_DITHER_ENABLE; |
322 | 373 | ||
323 | pipe_config->gmch_pfit.control = pfit_control; |
374 | pipe_config->gmch_pfit.control = pfit_control; |
324 | pipe_config->gmch_pfit.pgm_ratios = pfit_pgm_ratios; |
375 | pipe_config->gmch_pfit.pgm_ratios = pfit_pgm_ratios; |
325 | pipe_config->gmch_pfit.lvds_border_bits = border; |
376 | pipe_config->gmch_pfit.lvds_border_bits = border; |
326 | } |
377 | } |
- | 378 | ||
- | 379 | enum drm_connector_status |
|
- | 380 | intel_panel_detect(struct drm_device *dev) |
|
- | 381 | { |
|
- | 382 | struct drm_i915_private *dev_priv = dev->dev_private; |
|
- | 383 | ||
- | 384 | /* Assume that the BIOS does not lie through the OpRegion... */ |
|
- | 385 | if (!i915.panel_ignore_lid && dev_priv->opregion.lid_state) { |
|
- | 386 | return ioread32(dev_priv->opregion.lid_state) & 0x1 ? |
|
- | 387 | connector_status_connected : |
|
- | 388 | connector_status_disconnected; |
|
- | 389 | } |
|
327 | 390 | ||
- | 391 | switch (i915.panel_ignore_lid) { |
|
- | 392 | case -2: |
|
- | 393 | return connector_status_connected; |
|
- | 394 | case -1: |
|
- | 395 | return connector_status_disconnected; |
|
- | 396 | default: |
|
- | 397 | return connector_status_unknown; |
|
- | 398 | } |
|
- | 399 | } |
|
- | 400 | ||
328 | static int i915_panel_invert_brightness; |
401 | /** |
- | 402 | * scale - scale values from one range to another |
|
329 | MODULE_PARM_DESC(invert_brightness, "Invert backlight brightness " |
403 | * |
- | 404 | * @source_val: value in range [@source_min..@source_max] |
|
330 | "(-1 force normal, 0 machine defaults, 1 force inversion), please " |
405 | * |
- | 406 | * Return @source_val in range [@source_min..@source_max] scaled to range |
|
- | 407 | * [@target_min..@target_max]. |
|
- | 408 | */ |
|
- | 409 | static uint32_t scale(uint32_t source_val, |
|
- | 410 | uint32_t source_min, uint32_t source_max, |
|
- | 411 | uint32_t target_min, uint32_t target_max) |
|
- | 412 | { |
|
- | 413 | uint64_t target_val; |
|
- | 414 | ||
- | 415 | WARN_ON(source_min > source_max); |
|
- | 416 | WARN_ON(target_min > target_max); |
|
- | 417 | ||
- | 418 | /* defensive */ |
|
- | 419 | source_val = clamp(source_val, source_min, source_max); |
|
- | 420 | ||
- | 421 | /* avoid overflows */ |
|
- | 422 | target_val = (uint64_t)(source_val - source_min) * |
|
- | 423 | (target_max - target_min); |
|
- | 424 | do_div(target_val, source_max - source_min); |
|
- | 425 | target_val += target_min; |
|
- | 426 | ||
- | 427 | return target_val; |
|
- | 428 | } |
|
- | 429 | ||
- | 430 | /* Scale user_level in range [0..user_max] to [hw_min..hw_max]. */ |
|
- | 431 | static inline u32 scale_user_to_hw(struct intel_connector *connector, |
|
- | 432 | u32 user_level, u32 user_max) |
|
- | 433 | { |
|
- | 434 | struct intel_panel *panel = &connector->panel; |
|
- | 435 | ||
- | 436 | return scale(user_level, 0, user_max, |
|
- | 437 | panel->backlight.min, panel->backlight.max); |
|
- | 438 | } |
|
- | 439 | ||
- | 440 | /* Scale user_level in range [0..user_max] to [0..hw_max], clamping the result |
|
- | 441 | * to [hw_min..hw_max]. */ |
|
- | 442 | static inline u32 clamp_user_to_hw(struct intel_connector *connector, |
|
- | 443 | u32 user_level, u32 user_max) |
|
- | 444 | { |
|
- | 445 | struct intel_panel *panel = &connector->panel; |
|
- | 446 | u32 hw_level; |
|
331 | "report PCI device ID, subsystem vendor and subsystem device ID " |
447 | |
- | 448 | hw_level = scale(user_level, 0, user_max, 0, panel->backlight.max); |
|
- | 449 | hw_level = clamp(hw_level, panel->backlight.min, panel->backlight.max); |
|
- | 450 | ||
- | 451 | return hw_level; |
|
- | 452 | } |
|
332 | "to dri-devel@lists.freedesktop.org, if your machine needs it. " |
453 | |
- | 454 | /* Scale hw_level in range [hw_min..hw_max] to [0..user_max]. */ |
|
- | 455 | static inline u32 scale_hw_to_user(struct intel_connector *connector, |
|
- | 456 | u32 hw_level, u32 user_max) |
|
- | 457 | { |
|
- | 458 | struct intel_panel *panel = &connector->panel; |
|
333 | "It will then be included in an upcoming module version."); |
459 | |
- | 460 | return scale(hw_level, panel->backlight.min, panel->backlight.max, |
|
- | 461 | 0, user_max); |
|
- | 462 | } |
|
334 | module_param_named(invert_brightness, i915_panel_invert_brightness, int, 0600); |
463 | |
335 | static u32 intel_panel_compute_brightness(struct intel_connector *connector, |
464 | static u32 intel_panel_compute_brightness(struct intel_connector *connector, |
336 | u32 val) |
465 | u32 val) |
337 | { |
466 | { |
338 | struct drm_device *dev = connector->base.dev; |
467 | struct drm_device *dev = connector->base.dev; |
339 | struct drm_i915_private *dev_priv = dev->dev_private; |
468 | struct drm_i915_private *dev_priv = dev->dev_private; |
340 | struct intel_panel *panel = &connector->panel; |
469 | struct intel_panel *panel = &connector->panel; |
341 | 470 | ||
342 | WARN_ON(panel->backlight.max == 0); |
471 | WARN_ON(panel->backlight.max == 0); |
343 | 472 | ||
344 | if (i915_panel_invert_brightness < 0) |
473 | if (i915.invert_brightness < 0) |
345 | return val; |
474 | return val; |
346 | 475 | ||
347 | if (i915_panel_invert_brightness > 0 || |
476 | if (i915.invert_brightness > 0 || |
348 | dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) { |
477 | dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) { |
349 | return panel->backlight.max - val; |
478 | return panel->backlight.max - val; |
350 | } |
479 | } |
351 | 480 | ||
352 | return val; |
481 | return val; |
353 | } |
482 | } |
354 | 483 | ||
355 | static u32 bdw_get_backlight(struct intel_connector *connector) |
484 | static u32 bdw_get_backlight(struct intel_connector *connector) |
356 | { |
485 | { |
357 | struct drm_device *dev = connector->base.dev; |
486 | struct drm_device *dev = connector->base.dev; |
358 | struct drm_i915_private *dev_priv = dev->dev_private; |
487 | struct drm_i915_private *dev_priv = dev->dev_private; |
359 | 488 | ||
360 | return I915_READ(BLC_PWM_PCH_CTL2) & BACKLIGHT_DUTY_CYCLE_MASK; |
489 | return I915_READ(BLC_PWM_PCH_CTL2) & BACKLIGHT_DUTY_CYCLE_MASK; |
361 | } |
490 | } |
362 | 491 | ||
363 | static u32 pch_get_backlight(struct intel_connector *connector) |
492 | static u32 pch_get_backlight(struct intel_connector *connector) |
364 | { |
493 | { |
365 | struct drm_device *dev = connector->base.dev; |
494 | struct drm_device *dev = connector->base.dev; |
366 | struct drm_i915_private *dev_priv = dev->dev_private; |
495 | struct drm_i915_private *dev_priv = dev->dev_private; |
367 | 496 | ||
368 | return I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; |
497 | return I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; |
369 | } |
498 | } |
370 | 499 | ||
371 | static u32 i9xx_get_backlight(struct intel_connector *connector) |
500 | static u32 i9xx_get_backlight(struct intel_connector *connector) |
372 | { |
501 | { |
373 | struct drm_device *dev = connector->base.dev; |
502 | struct drm_device *dev = connector->base.dev; |
374 | struct drm_i915_private *dev_priv = dev->dev_private; |
503 | struct drm_i915_private *dev_priv = dev->dev_private; |
375 | struct intel_panel *panel = &connector->panel; |
504 | struct intel_panel *panel = &connector->panel; |
376 | u32 val; |
505 | u32 val; |
377 | 506 | ||
378 | val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; |
507 | val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; |
379 | if (INTEL_INFO(dev)->gen < 4) |
508 | if (INTEL_INFO(dev)->gen < 4) |
380 | val >>= 1; |
509 | val >>= 1; |
381 | 510 | ||
382 | if (panel->backlight.combination_mode) { |
511 | if (panel->backlight.combination_mode) { |
383 | u8 lbpc; |
512 | u8 lbpc; |
384 | 513 | ||
385 | pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc); |
514 | pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc); |
386 | val *= lbpc; |
515 | val *= lbpc; |
387 | } |
516 | } |
388 | 517 | ||
389 | return val; |
518 | return val; |
390 | } |
519 | } |
391 | 520 | ||
392 | static u32 _vlv_get_backlight(struct drm_device *dev, enum pipe pipe) |
521 | static u32 _vlv_get_backlight(struct drm_device *dev, enum pipe pipe) |
393 | { |
522 | { |
394 | struct drm_i915_private *dev_priv = dev->dev_private; |
523 | struct drm_i915_private *dev_priv = dev->dev_private; |
395 | 524 | ||
396 | return I915_READ(VLV_BLC_PWM_CTL(pipe)) & BACKLIGHT_DUTY_CYCLE_MASK; |
525 | return I915_READ(VLV_BLC_PWM_CTL(pipe)) & BACKLIGHT_DUTY_CYCLE_MASK; |
397 | } |
526 | } |
398 | 527 | ||
399 | static u32 vlv_get_backlight(struct intel_connector *connector) |
528 | static u32 vlv_get_backlight(struct intel_connector *connector) |
400 | { |
529 | { |
401 | struct drm_device *dev = connector->base.dev; |
530 | struct drm_device *dev = connector->base.dev; |
402 | enum pipe pipe = intel_get_pipe_from_connector(connector); |
531 | enum pipe pipe = intel_get_pipe_from_connector(connector); |
403 | 532 | ||
404 | return _vlv_get_backlight(dev, pipe); |
533 | return _vlv_get_backlight(dev, pipe); |
405 | } |
534 | } |
406 | 535 | ||
407 | static u32 intel_panel_get_backlight(struct intel_connector *connector) |
536 | static u32 intel_panel_get_backlight(struct intel_connector *connector) |
408 | { |
537 | { |
409 | struct drm_device *dev = connector->base.dev; |
538 | struct drm_device *dev = connector->base.dev; |
410 | struct drm_i915_private *dev_priv = dev->dev_private; |
539 | struct drm_i915_private *dev_priv = dev->dev_private; |
411 | u32 val; |
540 | u32 val; |
412 | unsigned long flags; |
541 | unsigned long flags; |
413 | 542 | ||
414 | spin_lock_irqsave(&dev_priv->backlight_lock, flags); |
543 | spin_lock_irqsave(&dev_priv->backlight_lock, flags); |
415 | 544 | ||
416 | val = dev_priv->display.get_backlight(connector); |
545 | val = dev_priv->display.get_backlight(connector); |
417 | val = intel_panel_compute_brightness(connector, val); |
546 | val = intel_panel_compute_brightness(connector, val); |
418 | 547 | ||
419 | spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); |
548 | spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); |
420 | 549 | ||
421 | DRM_DEBUG_DRIVER("get backlight PWM = %d\n", val); |
550 | DRM_DEBUG_DRIVER("get backlight PWM = %d\n", val); |
422 | return val; |
551 | return val; |
423 | } |
552 | } |
424 | 553 | ||
425 | static void bdw_set_backlight(struct intel_connector *connector, u32 level) |
554 | static void bdw_set_backlight(struct intel_connector *connector, u32 level) |
426 | { |
555 | { |
427 | struct drm_device *dev = connector->base.dev; |
556 | struct drm_device *dev = connector->base.dev; |
428 | struct drm_i915_private *dev_priv = dev->dev_private; |
557 | struct drm_i915_private *dev_priv = dev->dev_private; |
429 | u32 val = I915_READ(BLC_PWM_PCH_CTL2) & ~BACKLIGHT_DUTY_CYCLE_MASK; |
558 | u32 val = I915_READ(BLC_PWM_PCH_CTL2) & ~BACKLIGHT_DUTY_CYCLE_MASK; |
430 | I915_WRITE(BLC_PWM_PCH_CTL2, val | level); |
559 | I915_WRITE(BLC_PWM_PCH_CTL2, val | level); |
431 | } |
560 | } |
432 | 561 | ||
433 | static void pch_set_backlight(struct intel_connector *connector, u32 level) |
562 | static void pch_set_backlight(struct intel_connector *connector, u32 level) |
434 | { |
563 | { |
435 | struct drm_device *dev = connector->base.dev; |
564 | struct drm_device *dev = connector->base.dev; |
436 | struct drm_i915_private *dev_priv = dev->dev_private; |
565 | struct drm_i915_private *dev_priv = dev->dev_private; |
437 | u32 tmp; |
566 | u32 tmp; |
438 | 567 | ||
439 | tmp = I915_READ(BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK; |
568 | tmp = I915_READ(BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK; |
440 | I915_WRITE(BLC_PWM_CPU_CTL, tmp | level); |
569 | I915_WRITE(BLC_PWM_CPU_CTL, tmp | level); |
441 | } |
570 | } |
442 | 571 | ||
443 | static void i9xx_set_backlight(struct intel_connector *connector, u32 level) |
572 | static void i9xx_set_backlight(struct intel_connector *connector, u32 level) |
444 | { |
573 | { |
445 | struct drm_device *dev = connector->base.dev; |
574 | struct drm_device *dev = connector->base.dev; |
446 | struct drm_i915_private *dev_priv = dev->dev_private; |
575 | struct drm_i915_private *dev_priv = dev->dev_private; |
447 | struct intel_panel *panel = &connector->panel; |
576 | struct intel_panel *panel = &connector->panel; |
448 | u32 tmp, mask; |
577 | u32 tmp, mask; |
449 | 578 | ||
450 | WARN_ON(panel->backlight.max == 0); |
579 | WARN_ON(panel->backlight.max == 0); |
451 | 580 | ||
452 | if (panel->backlight.combination_mode) { |
581 | if (panel->backlight.combination_mode) { |
453 | u8 lbpc; |
582 | u8 lbpc; |
454 | 583 | ||
455 | lbpc = level * 0xfe / panel->backlight.max + 1; |
584 | lbpc = level * 0xfe / panel->backlight.max + 1; |
456 | level /= lbpc; |
585 | level /= lbpc; |
457 | pci_write_config_byte(dev->pdev, PCI_LBPC, lbpc); |
586 | pci_write_config_byte(dev->pdev, PCI_LBPC, lbpc); |
458 | } |
587 | } |
459 | 588 | ||
460 | if (IS_GEN4(dev)) { |
589 | if (IS_GEN4(dev)) { |
461 | mask = BACKLIGHT_DUTY_CYCLE_MASK; |
590 | mask = BACKLIGHT_DUTY_CYCLE_MASK; |
462 | } else { |
591 | } else { |
463 | level <<= 1; |
592 | level <<= 1; |
464 | mask = BACKLIGHT_DUTY_CYCLE_MASK_PNV; |
593 | mask = BACKLIGHT_DUTY_CYCLE_MASK_PNV; |
465 | } |
594 | } |
466 | 595 | ||
467 | tmp = I915_READ(BLC_PWM_CTL) & ~mask; |
596 | tmp = I915_READ(BLC_PWM_CTL) & ~mask; |
468 | I915_WRITE(BLC_PWM_CTL, tmp | level); |
597 | I915_WRITE(BLC_PWM_CTL, tmp | level); |
469 | } |
598 | } |
470 | 599 | ||
471 | static void vlv_set_backlight(struct intel_connector *connector, u32 level) |
600 | static void vlv_set_backlight(struct intel_connector *connector, u32 level) |
472 | { |
601 | { |
473 | struct drm_device *dev = connector->base.dev; |
602 | struct drm_device *dev = connector->base.dev; |
474 | struct drm_i915_private *dev_priv = dev->dev_private; |
603 | struct drm_i915_private *dev_priv = dev->dev_private; |
475 | enum pipe pipe = intel_get_pipe_from_connector(connector); |
604 | enum pipe pipe = intel_get_pipe_from_connector(connector); |
476 | u32 tmp; |
605 | u32 tmp; |
477 | 606 | ||
478 | tmp = I915_READ(VLV_BLC_PWM_CTL(pipe)) & ~BACKLIGHT_DUTY_CYCLE_MASK; |
607 | tmp = I915_READ(VLV_BLC_PWM_CTL(pipe)) & ~BACKLIGHT_DUTY_CYCLE_MASK; |
479 | I915_WRITE(VLV_BLC_PWM_CTL(pipe), tmp | level); |
608 | I915_WRITE(VLV_BLC_PWM_CTL(pipe), tmp | level); |
480 | } |
609 | } |
481 | 610 | ||
482 | static void |
611 | static void |
483 | intel_panel_actually_set_backlight(struct intel_connector *connector, u32 level) |
612 | intel_panel_actually_set_backlight(struct intel_connector *connector, u32 level) |
484 | { |
613 | { |
485 | struct drm_device *dev = connector->base.dev; |
614 | struct drm_device *dev = connector->base.dev; |
486 | struct drm_i915_private *dev_priv = dev->dev_private; |
615 | struct drm_i915_private *dev_priv = dev->dev_private; |
487 | 616 | ||
488 | DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level); |
617 | DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level); |
489 | 618 | ||
490 | level = intel_panel_compute_brightness(connector, level); |
619 | level = intel_panel_compute_brightness(connector, level); |
491 | dev_priv->display.set_backlight(connector, level); |
620 | dev_priv->display.set_backlight(connector, level); |
492 | } |
621 | } |
493 | 622 | ||
494 | /* set backlight brightness to level in range [0..max] */ |
623 | /* set backlight brightness to level in range [0..max], scaling wrt hw min */ |
495 | void intel_panel_set_backlight(struct intel_connector *connector, u32 level, |
624 | static void intel_panel_set_backlight(struct intel_connector *connector, |
496 | u32 max) |
625 | u32 user_level, u32 user_max) |
497 | { |
626 | { |
498 | struct drm_device *dev = connector->base.dev; |
627 | struct drm_device *dev = connector->base.dev; |
499 | struct drm_i915_private *dev_priv = dev->dev_private; |
628 | struct drm_i915_private *dev_priv = dev->dev_private; |
500 | struct intel_panel *panel = &connector->panel; |
629 | struct intel_panel *panel = &connector->panel; |
501 | enum pipe pipe = intel_get_pipe_from_connector(connector); |
630 | enum pipe pipe = intel_get_pipe_from_connector(connector); |
502 | u32 freq; |
631 | u32 hw_level; |
503 | unsigned long flags; |
632 | unsigned long flags; |
504 | 633 | ||
505 | if (!panel->backlight.present || pipe == INVALID_PIPE) |
634 | if (!panel->backlight.present || pipe == INVALID_PIPE) |
506 | return; |
635 | return; |
507 | 636 | ||
508 | spin_lock_irqsave(&dev_priv->backlight_lock, flags); |
637 | spin_lock_irqsave(&dev_priv->backlight_lock, flags); |
509 | 638 | ||
510 | WARN_ON(panel->backlight.max == 0); |
639 | WARN_ON(panel->backlight.max == 0); |
511 | 640 | ||
- | 641 | hw_level = scale_user_to_hw(connector, user_level, user_max); |
|
- | 642 | panel->backlight.level = hw_level; |
|
512 | /* scale to hardware max, but be careful to not overflow */ |
643 | |
- | 644 | if (panel->backlight.enabled) |
|
- | 645 | intel_panel_actually_set_backlight(connector, hw_level); |
|
- | 646 | ||
- | 647 | spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); |
|
- | 648 | } |
|
- | 649 | ||
513 | freq = panel->backlight.max; |
650 | /* set backlight brightness to level in range [0..max], assuming hw min is |
- | 651 | * respected. |
|
- | 652 | */ |
|
514 | if (freq < max) |
653 | void intel_panel_set_backlight_acpi(struct intel_connector *connector, |
- | 654 | u32 user_level, u32 user_max) |
|
- | 655 | { |
|
- | 656 | struct drm_device *dev = connector->base.dev; |
|
- | 657 | struct drm_i915_private *dev_priv = dev->dev_private; |
|
- | 658 | struct intel_panel *panel = &connector->panel; |
|
- | 659 | enum pipe pipe = intel_get_pipe_from_connector(connector); |
|
- | 660 | u32 hw_level; |
|
- | 661 | unsigned long flags; |
|
- | 662 | ||
515 | level = level * freq / max; |
663 | if (!panel->backlight.present || pipe == INVALID_PIPE) |
- | 664 | return; |
|
- | 665 | ||
- | 666 | spin_lock_irqsave(&dev_priv->backlight_lock, flags); |
|
- | 667 | ||
- | 668 | WARN_ON(panel->backlight.max == 0); |
|
- | 669 | ||
516 | else |
670 | hw_level = clamp_user_to_hw(connector, user_level, user_max); |
517 | level = freq / max * level; |
- | |
518 | - | ||
519 | panel->backlight.level = level; |
- | |
520 | // if (panel->backlight.device) |
671 | panel->backlight.level = hw_level; |
521 | // panel->backlight.device->props.brightness = level; |
672 | |
522 | 673 | ||
523 | if (panel->backlight.enabled) |
674 | if (panel->backlight.enabled) |
524 | intel_panel_actually_set_backlight(connector, level); |
675 | intel_panel_actually_set_backlight(connector, hw_level); |
525 | 676 | ||
526 | spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); |
677 | spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); |
527 | } |
678 | } |
528 | 679 | ||
529 | static void pch_disable_backlight(struct intel_connector *connector) |
680 | static void pch_disable_backlight(struct intel_connector *connector) |
530 | { |
681 | { |
531 | struct drm_device *dev = connector->base.dev; |
682 | struct drm_device *dev = connector->base.dev; |
532 | struct drm_i915_private *dev_priv = dev->dev_private; |
683 | struct drm_i915_private *dev_priv = dev->dev_private; |
533 | u32 tmp; |
684 | u32 tmp; |
534 | 685 | ||
535 | intel_panel_actually_set_backlight(connector, 0); |
686 | intel_panel_actually_set_backlight(connector, 0); |
536 | 687 | ||
537 | tmp = I915_READ(BLC_PWM_CPU_CTL2); |
688 | tmp = I915_READ(BLC_PWM_CPU_CTL2); |
538 | I915_WRITE(BLC_PWM_CPU_CTL2, tmp & ~BLM_PWM_ENABLE); |
689 | I915_WRITE(BLC_PWM_CPU_CTL2, tmp & ~BLM_PWM_ENABLE); |
539 | 690 | ||
540 | tmp = I915_READ(BLC_PWM_PCH_CTL1); |
691 | tmp = I915_READ(BLC_PWM_PCH_CTL1); |
541 | I915_WRITE(BLC_PWM_PCH_CTL1, tmp & ~BLM_PCH_PWM_ENABLE); |
692 | I915_WRITE(BLC_PWM_PCH_CTL1, tmp & ~BLM_PCH_PWM_ENABLE); |
542 | } |
693 | } |
543 | 694 | ||
544 | static void i9xx_disable_backlight(struct intel_connector *connector) |
695 | static void i9xx_disable_backlight(struct intel_connector *connector) |
545 | { |
696 | { |
546 | intel_panel_actually_set_backlight(connector, 0); |
697 | intel_panel_actually_set_backlight(connector, 0); |
547 | } |
698 | } |
548 | 699 | ||
549 | static void i965_disable_backlight(struct intel_connector *connector) |
700 | static void i965_disable_backlight(struct intel_connector *connector) |
550 | { |
701 | { |
551 | struct drm_device *dev = connector->base.dev; |
702 | struct drm_device *dev = connector->base.dev; |
552 | struct drm_i915_private *dev_priv = dev->dev_private; |
703 | struct drm_i915_private *dev_priv = dev->dev_private; |
553 | u32 tmp; |
704 | u32 tmp; |
554 | 705 | ||
555 | intel_panel_actually_set_backlight(connector, 0); |
706 | intel_panel_actually_set_backlight(connector, 0); |
556 | 707 | ||
557 | tmp = I915_READ(BLC_PWM_CTL2); |
708 | tmp = I915_READ(BLC_PWM_CTL2); |
558 | I915_WRITE(BLC_PWM_CTL2, tmp & ~BLM_PWM_ENABLE); |
709 | I915_WRITE(BLC_PWM_CTL2, tmp & ~BLM_PWM_ENABLE); |
559 | } |
710 | } |
560 | 711 | ||
561 | static void vlv_disable_backlight(struct intel_connector *connector) |
712 | static void vlv_disable_backlight(struct intel_connector *connector) |
562 | { |
713 | { |
563 | struct drm_device *dev = connector->base.dev; |
714 | struct drm_device *dev = connector->base.dev; |
564 | struct drm_i915_private *dev_priv = dev->dev_private; |
715 | struct drm_i915_private *dev_priv = dev->dev_private; |
565 | enum pipe pipe = intel_get_pipe_from_connector(connector); |
716 | enum pipe pipe = intel_get_pipe_from_connector(connector); |
566 | u32 tmp; |
717 | u32 tmp; |
567 | 718 | ||
568 | intel_panel_actually_set_backlight(connector, 0); |
719 | intel_panel_actually_set_backlight(connector, 0); |
569 | 720 | ||
570 | tmp = I915_READ(VLV_BLC_PWM_CTL2(pipe)); |
721 | tmp = I915_READ(VLV_BLC_PWM_CTL2(pipe)); |
571 | I915_WRITE(VLV_BLC_PWM_CTL2(pipe), tmp & ~BLM_PWM_ENABLE); |
722 | I915_WRITE(VLV_BLC_PWM_CTL2(pipe), tmp & ~BLM_PWM_ENABLE); |
572 | } |
723 | } |
573 | 724 | ||
574 | void intel_panel_disable_backlight(struct intel_connector *connector) |
725 | void intel_panel_disable_backlight(struct intel_connector *connector) |
575 | { |
726 | { |
576 | struct drm_device *dev = connector->base.dev; |
727 | struct drm_device *dev = connector->base.dev; |
577 | struct drm_i915_private *dev_priv = dev->dev_private; |
728 | struct drm_i915_private *dev_priv = dev->dev_private; |
578 | struct intel_panel *panel = &connector->panel; |
729 | struct intel_panel *panel = &connector->panel; |
579 | enum pipe pipe = intel_get_pipe_from_connector(connector); |
730 | enum pipe pipe = intel_get_pipe_from_connector(connector); |
580 | unsigned long flags; |
731 | unsigned long flags; |
581 | 732 | ||
582 | if (!panel->backlight.present || pipe == INVALID_PIPE) |
733 | if (!panel->backlight.present || pipe == INVALID_PIPE) |
583 | return; |
734 | return; |
584 | 735 | ||
585 | /* |
736 | /* |
586 | * Do not disable backlight on the vgaswitcheroo path. When switching |
737 | * Do not disable backlight on the vgaswitcheroo path. When switching |
587 | * away from i915, the other client may depend on i915 to handle the |
738 | * away from i915, the other client may depend on i915 to handle the |
588 | * backlight. This will leave the backlight on unnecessarily when |
739 | * backlight. This will leave the backlight on unnecessarily when |
589 | * another client is not activated. |
740 | * another client is not activated. |
590 | */ |
741 | */ |
591 | if (dev->switch_power_state == DRM_SWITCH_POWER_CHANGING) { |
742 | if (dev->switch_power_state == DRM_SWITCH_POWER_CHANGING) { |
592 | DRM_DEBUG_DRIVER("Skipping backlight disable on vga switch\n"); |
743 | DRM_DEBUG_DRIVER("Skipping backlight disable on vga switch\n"); |
593 | return; |
744 | return; |
594 | } |
745 | } |
595 | 746 | ||
596 | spin_lock_irqsave(&dev_priv->backlight_lock, flags); |
747 | spin_lock_irqsave(&dev_priv->backlight_lock, flags); |
597 | 748 | ||
598 | panel->backlight.enabled = false; |
749 | panel->backlight.enabled = false; |
599 | dev_priv->display.disable_backlight(connector); |
750 | dev_priv->display.disable_backlight(connector); |
600 | 751 | ||
601 | spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); |
752 | spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); |
602 | } |
753 | } |
603 | 754 | ||
604 | static void bdw_enable_backlight(struct intel_connector *connector) |
755 | static void bdw_enable_backlight(struct intel_connector *connector) |
605 | { |
756 | { |
606 | struct drm_device *dev = connector->base.dev; |
757 | struct drm_device *dev = connector->base.dev; |
607 | struct drm_i915_private *dev_priv = dev->dev_private; |
758 | struct drm_i915_private *dev_priv = dev->dev_private; |
608 | struct intel_panel *panel = &connector->panel; |
759 | struct intel_panel *panel = &connector->panel; |
609 | u32 pch_ctl1, pch_ctl2; |
760 | u32 pch_ctl1, pch_ctl2; |
610 | 761 | ||
611 | pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1); |
762 | pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1); |
612 | if (pch_ctl1 & BLM_PCH_PWM_ENABLE) { |
763 | if (pch_ctl1 & BLM_PCH_PWM_ENABLE) { |
613 | DRM_DEBUG_KMS("pch backlight already enabled\n"); |
764 | DRM_DEBUG_KMS("pch backlight already enabled\n"); |
614 | pch_ctl1 &= ~BLM_PCH_PWM_ENABLE; |
765 | pch_ctl1 &= ~BLM_PCH_PWM_ENABLE; |
615 | I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1); |
766 | I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1); |
616 | } |
767 | } |
617 | 768 | ||
618 | pch_ctl2 = panel->backlight.max << 16; |
769 | pch_ctl2 = panel->backlight.max << 16; |
619 | I915_WRITE(BLC_PWM_PCH_CTL2, pch_ctl2); |
770 | I915_WRITE(BLC_PWM_PCH_CTL2, pch_ctl2); |
620 | 771 | ||
621 | pch_ctl1 = 0; |
772 | pch_ctl1 = 0; |
622 | if (panel->backlight.active_low_pwm) |
773 | if (panel->backlight.active_low_pwm) |
623 | pch_ctl1 |= BLM_PCH_POLARITY; |
774 | pch_ctl1 |= BLM_PCH_POLARITY; |
624 | 775 | ||
625 | /* BDW always uses the pch pwm controls. */ |
776 | /* BDW always uses the pch pwm controls. */ |
626 | pch_ctl1 |= BLM_PCH_OVERRIDE_ENABLE; |
777 | pch_ctl1 |= BLM_PCH_OVERRIDE_ENABLE; |
627 | 778 | ||
628 | I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1); |
779 | I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1); |
629 | POSTING_READ(BLC_PWM_PCH_CTL1); |
780 | POSTING_READ(BLC_PWM_PCH_CTL1); |
630 | I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE); |
781 | I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE); |
631 | 782 | ||
632 | /* This won't stick until the above enable. */ |
783 | /* This won't stick until the above enable. */ |
633 | intel_panel_actually_set_backlight(connector, panel->backlight.level); |
784 | intel_panel_actually_set_backlight(connector, panel->backlight.level); |
634 | } |
785 | } |
635 | 786 | ||
636 | static void pch_enable_backlight(struct intel_connector *connector) |
787 | static void pch_enable_backlight(struct intel_connector *connector) |
637 | { |
788 | { |
638 | struct drm_device *dev = connector->base.dev; |
789 | struct drm_device *dev = connector->base.dev; |
639 | struct drm_i915_private *dev_priv = dev->dev_private; |
790 | struct drm_i915_private *dev_priv = dev->dev_private; |
640 | struct intel_panel *panel = &connector->panel; |
791 | struct intel_panel *panel = &connector->panel; |
641 | enum pipe pipe = intel_get_pipe_from_connector(connector); |
792 | enum pipe pipe = intel_get_pipe_from_connector(connector); |
642 | enum transcoder cpu_transcoder = |
793 | enum transcoder cpu_transcoder = |
643 | intel_pipe_to_cpu_transcoder(dev_priv, pipe); |
794 | intel_pipe_to_cpu_transcoder(dev_priv, pipe); |
644 | u32 cpu_ctl2, pch_ctl1, pch_ctl2; |
795 | u32 cpu_ctl2, pch_ctl1, pch_ctl2; |
645 | 796 | ||
646 | cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2); |
797 | cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2); |
647 | if (cpu_ctl2 & BLM_PWM_ENABLE) { |
798 | if (cpu_ctl2 & BLM_PWM_ENABLE) { |
648 | WARN(1, "cpu backlight already enabled\n"); |
799 | WARN(1, "cpu backlight already enabled\n"); |
649 | cpu_ctl2 &= ~BLM_PWM_ENABLE; |
800 | cpu_ctl2 &= ~BLM_PWM_ENABLE; |
650 | I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2); |
801 | I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2); |
651 | } |
802 | } |
652 | 803 | ||
653 | pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1); |
804 | pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1); |
654 | if (pch_ctl1 & BLM_PCH_PWM_ENABLE) { |
805 | if (pch_ctl1 & BLM_PCH_PWM_ENABLE) { |
655 | DRM_DEBUG_KMS("pch backlight already enabled\n"); |
806 | DRM_DEBUG_KMS("pch backlight already enabled\n"); |
656 | pch_ctl1 &= ~BLM_PCH_PWM_ENABLE; |
807 | pch_ctl1 &= ~BLM_PCH_PWM_ENABLE; |
657 | I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1); |
808 | I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1); |
658 | } |
809 | } |
659 | 810 | ||
660 | if (cpu_transcoder == TRANSCODER_EDP) |
811 | if (cpu_transcoder == TRANSCODER_EDP) |
661 | cpu_ctl2 = BLM_TRANSCODER_EDP; |
812 | cpu_ctl2 = BLM_TRANSCODER_EDP; |
662 | else |
813 | else |
663 | cpu_ctl2 = BLM_PIPE(cpu_transcoder); |
814 | cpu_ctl2 = BLM_PIPE(cpu_transcoder); |
664 | I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2); |
815 | I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2); |
665 | POSTING_READ(BLC_PWM_CPU_CTL2); |
816 | POSTING_READ(BLC_PWM_CPU_CTL2); |
666 | I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2 | BLM_PWM_ENABLE); |
817 | I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2 | BLM_PWM_ENABLE); |
667 | 818 | ||
668 | /* This won't stick until the above enable. */ |
819 | /* This won't stick until the above enable. */ |
669 | intel_panel_actually_set_backlight(connector, panel->backlight.level); |
820 | intel_panel_actually_set_backlight(connector, panel->backlight.level); |
670 | 821 | ||
671 | pch_ctl2 = panel->backlight.max << 16; |
822 | pch_ctl2 = panel->backlight.max << 16; |
672 | I915_WRITE(BLC_PWM_PCH_CTL2, pch_ctl2); |
823 | I915_WRITE(BLC_PWM_PCH_CTL2, pch_ctl2); |
673 | 824 | ||
674 | pch_ctl1 = 0; |
825 | pch_ctl1 = 0; |
675 | if (panel->backlight.active_low_pwm) |
826 | if (panel->backlight.active_low_pwm) |
676 | pch_ctl1 |= BLM_PCH_POLARITY; |
827 | pch_ctl1 |= BLM_PCH_POLARITY; |
677 | 828 | ||
678 | I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1); |
829 | I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1); |
679 | POSTING_READ(BLC_PWM_PCH_CTL1); |
830 | POSTING_READ(BLC_PWM_PCH_CTL1); |
680 | I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE); |
831 | I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE); |
681 | } |
832 | } |
682 | 833 | ||
683 | static void i9xx_enable_backlight(struct intel_connector *connector) |
834 | static void i9xx_enable_backlight(struct intel_connector *connector) |
684 | { |
835 | { |
685 | struct drm_device *dev = connector->base.dev; |
836 | struct drm_device *dev = connector->base.dev; |
686 | struct drm_i915_private *dev_priv = dev->dev_private; |
837 | struct drm_i915_private *dev_priv = dev->dev_private; |
687 | struct intel_panel *panel = &connector->panel; |
838 | struct intel_panel *panel = &connector->panel; |
688 | u32 ctl, freq; |
839 | u32 ctl, freq; |
689 | 840 | ||
690 | ctl = I915_READ(BLC_PWM_CTL); |
841 | ctl = I915_READ(BLC_PWM_CTL); |
691 | if (ctl & BACKLIGHT_DUTY_CYCLE_MASK_PNV) { |
842 | if (ctl & BACKLIGHT_DUTY_CYCLE_MASK_PNV) { |
692 | WARN(1, "backlight already enabled\n"); |
843 | WARN(1, "backlight already enabled\n"); |
693 | I915_WRITE(BLC_PWM_CTL, 0); |
844 | I915_WRITE(BLC_PWM_CTL, 0); |
694 | } |
845 | } |
695 | 846 | ||
696 | freq = panel->backlight.max; |
847 | freq = panel->backlight.max; |
697 | if (panel->backlight.combination_mode) |
848 | if (panel->backlight.combination_mode) |
698 | freq /= 0xff; |
849 | freq /= 0xff; |
699 | 850 | ||
700 | ctl = freq << 17; |
851 | ctl = freq << 17; |
701 | if (IS_GEN2(dev) && panel->backlight.combination_mode) |
852 | if (panel->backlight.combination_mode) |
702 | ctl |= BLM_LEGACY_MODE; |
853 | ctl |= BLM_LEGACY_MODE; |
703 | if (IS_PINEVIEW(dev) && panel->backlight.active_low_pwm) |
854 | if (IS_PINEVIEW(dev) && panel->backlight.active_low_pwm) |
704 | ctl |= BLM_POLARITY_PNV; |
855 | ctl |= BLM_POLARITY_PNV; |
705 | 856 | ||
706 | I915_WRITE(BLC_PWM_CTL, ctl); |
857 | I915_WRITE(BLC_PWM_CTL, ctl); |
707 | POSTING_READ(BLC_PWM_CTL); |
858 | POSTING_READ(BLC_PWM_CTL); |
708 | 859 | ||
709 | /* XXX: combine this into above write? */ |
860 | /* XXX: combine this into above write? */ |
710 | intel_panel_actually_set_backlight(connector, panel->backlight.level); |
861 | intel_panel_actually_set_backlight(connector, panel->backlight.level); |
711 | } |
862 | } |
712 | 863 | ||
713 | static void i965_enable_backlight(struct intel_connector *connector) |
864 | static void i965_enable_backlight(struct intel_connector *connector) |
714 | { |
865 | { |
715 | struct drm_device *dev = connector->base.dev; |
866 | struct drm_device *dev = connector->base.dev; |
716 | struct drm_i915_private *dev_priv = dev->dev_private; |
867 | struct drm_i915_private *dev_priv = dev->dev_private; |
717 | struct intel_panel *panel = &connector->panel; |
868 | struct intel_panel *panel = &connector->panel; |
718 | enum pipe pipe = intel_get_pipe_from_connector(connector); |
869 | enum pipe pipe = intel_get_pipe_from_connector(connector); |
719 | u32 ctl, ctl2, freq; |
870 | u32 ctl, ctl2, freq; |
720 | 871 | ||
721 | ctl2 = I915_READ(BLC_PWM_CTL2); |
872 | ctl2 = I915_READ(BLC_PWM_CTL2); |
722 | if (ctl2 & BLM_PWM_ENABLE) { |
873 | if (ctl2 & BLM_PWM_ENABLE) { |
723 | WARN(1, "backlight already enabled\n"); |
874 | WARN(1, "backlight already enabled\n"); |
724 | ctl2 &= ~BLM_PWM_ENABLE; |
875 | ctl2 &= ~BLM_PWM_ENABLE; |
725 | I915_WRITE(BLC_PWM_CTL2, ctl2); |
876 | I915_WRITE(BLC_PWM_CTL2, ctl2); |
726 | } |
877 | } |
727 | 878 | ||
728 | freq = panel->backlight.max; |
879 | freq = panel->backlight.max; |
729 | if (panel->backlight.combination_mode) |
880 | if (panel->backlight.combination_mode) |
730 | freq /= 0xff; |
881 | freq /= 0xff; |
731 | 882 | ||
732 | ctl = freq << 16; |
883 | ctl = freq << 16; |
733 | I915_WRITE(BLC_PWM_CTL, ctl); |
884 | I915_WRITE(BLC_PWM_CTL, ctl); |
734 | - | ||
735 | /* XXX: combine this into above write? */ |
- | |
736 | intel_panel_actually_set_backlight(connector, panel->backlight.level); |
- | |
737 | 885 | ||
738 | ctl2 = BLM_PIPE(pipe); |
886 | ctl2 = BLM_PIPE(pipe); |
739 | if (panel->backlight.combination_mode) |
887 | if (panel->backlight.combination_mode) |
740 | ctl2 |= BLM_COMBINATION_MODE; |
888 | ctl2 |= BLM_COMBINATION_MODE; |
741 | if (panel->backlight.active_low_pwm) |
889 | if (panel->backlight.active_low_pwm) |
742 | ctl2 |= BLM_POLARITY_I965; |
890 | ctl2 |= BLM_POLARITY_I965; |
743 | I915_WRITE(BLC_PWM_CTL2, ctl2); |
891 | I915_WRITE(BLC_PWM_CTL2, ctl2); |
744 | POSTING_READ(BLC_PWM_CTL2); |
892 | POSTING_READ(BLC_PWM_CTL2); |
745 | I915_WRITE(BLC_PWM_CTL2, ctl2 | BLM_PWM_ENABLE); |
893 | I915_WRITE(BLC_PWM_CTL2, ctl2 | BLM_PWM_ENABLE); |
- | 894 | ||
- | 895 | intel_panel_actually_set_backlight(connector, panel->backlight.level); |
|
746 | } |
896 | } |
747 | 897 | ||
748 | static void vlv_enable_backlight(struct intel_connector *connector) |
898 | static void vlv_enable_backlight(struct intel_connector *connector) |
749 | { |
899 | { |
750 | struct drm_device *dev = connector->base.dev; |
900 | struct drm_device *dev = connector->base.dev; |
751 | struct drm_i915_private *dev_priv = dev->dev_private; |
901 | struct drm_i915_private *dev_priv = dev->dev_private; |
752 | struct intel_panel *panel = &connector->panel; |
902 | struct intel_panel *panel = &connector->panel; |
753 | enum pipe pipe = intel_get_pipe_from_connector(connector); |
903 | enum pipe pipe = intel_get_pipe_from_connector(connector); |
754 | u32 ctl, ctl2; |
904 | u32 ctl, ctl2; |
755 | 905 | ||
756 | ctl2 = I915_READ(VLV_BLC_PWM_CTL2(pipe)); |
906 | ctl2 = I915_READ(VLV_BLC_PWM_CTL2(pipe)); |
757 | if (ctl2 & BLM_PWM_ENABLE) { |
907 | if (ctl2 & BLM_PWM_ENABLE) { |
758 | WARN(1, "backlight already enabled\n"); |
908 | WARN(1, "backlight already enabled\n"); |
759 | ctl2 &= ~BLM_PWM_ENABLE; |
909 | ctl2 &= ~BLM_PWM_ENABLE; |
760 | I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2); |
910 | I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2); |
761 | } |
911 | } |
762 | 912 | ||
763 | ctl = panel->backlight.max << 16; |
913 | ctl = panel->backlight.max << 16; |
764 | I915_WRITE(VLV_BLC_PWM_CTL(pipe), ctl); |
914 | I915_WRITE(VLV_BLC_PWM_CTL(pipe), ctl); |
765 | 915 | ||
766 | /* XXX: combine this into above write? */ |
916 | /* XXX: combine this into above write? */ |
767 | intel_panel_actually_set_backlight(connector, panel->backlight.level); |
917 | intel_panel_actually_set_backlight(connector, panel->backlight.level); |
768 | 918 | ||
769 | ctl2 = 0; |
919 | ctl2 = 0; |
770 | if (panel->backlight.active_low_pwm) |
920 | if (panel->backlight.active_low_pwm) |
771 | ctl2 |= BLM_POLARITY_I965; |
921 | ctl2 |= BLM_POLARITY_I965; |
772 | I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2); |
922 | I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2); |
773 | POSTING_READ(VLV_BLC_PWM_CTL2(pipe)); |
923 | POSTING_READ(VLV_BLC_PWM_CTL2(pipe)); |
774 | I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2 | BLM_PWM_ENABLE); |
924 | I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2 | BLM_PWM_ENABLE); |
775 | } |
925 | } |
776 | 926 | ||
777 | void intel_panel_enable_backlight(struct intel_connector *connector) |
927 | void intel_panel_enable_backlight(struct intel_connector *connector) |
778 | { |
928 | { |
779 | struct drm_device *dev = connector->base.dev; |
929 | struct drm_device *dev = connector->base.dev; |
780 | struct drm_i915_private *dev_priv = dev->dev_private; |
930 | struct drm_i915_private *dev_priv = dev->dev_private; |
781 | struct intel_panel *panel = &connector->panel; |
931 | struct intel_panel *panel = &connector->panel; |
782 | enum pipe pipe = intel_get_pipe_from_connector(connector); |
932 | enum pipe pipe = intel_get_pipe_from_connector(connector); |
783 | unsigned long flags; |
933 | unsigned long flags; |
784 | 934 | ||
785 | if (!panel->backlight.present || pipe == INVALID_PIPE) |
935 | if (!panel->backlight.present || pipe == INVALID_PIPE) |
786 | return; |
936 | return; |
787 | 937 | ||
788 | DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe)); |
938 | DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe)); |
789 | 939 | ||
790 | spin_lock_irqsave(&dev_priv->backlight_lock, flags); |
940 | spin_lock_irqsave(&dev_priv->backlight_lock, flags); |
791 | 941 | ||
792 | WARN_ON(panel->backlight.max == 0); |
942 | WARN_ON(panel->backlight.max == 0); |
793 | 943 | ||
794 | if (panel->backlight.level == 0) { |
944 | if (panel->backlight.level == 0) { |
795 | panel->backlight.level = panel->backlight.max; |
945 | panel->backlight.level = panel->backlight.max; |
796 | // if (panel->backlight.device) |
- | |
797 | // panel->backlight.device->props.brightness = |
- | |
798 | // panel->backlight.level; |
- | |
799 | } |
946 | } |
800 | 947 | ||
801 | dev_priv->display.enable_backlight(connector); |
948 | dev_priv->display.enable_backlight(connector); |
802 | panel->backlight.enabled = true; |
949 | panel->backlight.enabled = true; |
803 | 950 | ||
804 | spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); |
951 | spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); |
805 | } |
952 | } |
806 | - | ||
807 | enum drm_connector_status |
- | |
808 | intel_panel_detect(struct drm_device *dev) |
- | |
809 | { |
- | |
810 | struct drm_i915_private *dev_priv = dev->dev_private; |
- | |
811 | - | ||
812 | /* Assume that the BIOS does not lie through the OpRegion... */ |
- | |
813 | if (!i915_panel_ignore_lid && dev_priv->opregion.lid_state) { |
- | |
814 | return ioread32(dev_priv->opregion.lid_state) & 0x1 ? |
- | |
815 | connector_status_connected : |
- | |
816 | connector_status_disconnected; |
- | |
817 | } |
- | |
818 | - | ||
819 | switch (i915_panel_ignore_lid) { |
- | |
820 | case -2: |
- | |
821 | return connector_status_connected; |
- | |
822 | case -1: |
- | |
823 | return connector_status_disconnected; |
- | |
824 | default: |
- | |
825 | return connector_status_unknown; |
- | |
826 | } |
- | |
827 | } |
- | |
828 | 953 | ||
829 | #if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE) |
954 | #if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE) |
830 | static int intel_backlight_device_update_status(struct backlight_device *bd) |
955 | static int intel_backlight_device_update_status(struct backlight_device *bd) |
831 | { |
956 | { |
832 | struct intel_connector *connector = bl_get_data(bd); |
957 | struct intel_connector *connector = bl_get_data(bd); |
833 | struct drm_device *dev = connector->base.dev; |
958 | struct drm_device *dev = connector->base.dev; |
834 | 959 | ||
835 | mutex_lock(&dev->mode_config.mutex); |
960 | drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); |
836 | DRM_DEBUG_KMS("updating intel_backlight, brightness=%d/%d\n", |
961 | DRM_DEBUG_KMS("updating intel_backlight, brightness=%d/%d\n", |
837 | bd->props.brightness, bd->props.max_brightness); |
962 | bd->props.brightness, bd->props.max_brightness); |
838 | intel_panel_set_backlight(connector, bd->props.brightness, |
963 | intel_panel_set_backlight(connector, bd->props.brightness, |
839 | bd->props.max_brightness); |
964 | bd->props.max_brightness); |
840 | mutex_unlock(&dev->mode_config.mutex); |
965 | drm_modeset_unlock(&dev->mode_config.connection_mutex); |
841 | return 0; |
966 | return 0; |
842 | } |
967 | } |
843 | 968 | ||
844 | static int intel_backlight_device_get_brightness(struct backlight_device *bd) |
969 | static int intel_backlight_device_get_brightness(struct backlight_device *bd) |
845 | { |
970 | { |
846 | struct intel_connector *connector = bl_get_data(bd); |
971 | struct intel_connector *connector = bl_get_data(bd); |
847 | struct drm_device *dev = connector->base.dev; |
972 | struct drm_device *dev = connector->base.dev; |
848 | struct drm_i915_private *dev_priv = dev->dev_private; |
973 | struct drm_i915_private *dev_priv = dev->dev_private; |
- | 974 | u32 hw_level; |
|
849 | int ret; |
975 | int ret; |
850 | 976 | ||
851 | intel_runtime_pm_get(dev_priv); |
977 | intel_runtime_pm_get(dev_priv); |
852 | mutex_lock(&dev->mode_config.mutex); |
978 | drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); |
- | 979 | ||
853 | ret = intel_panel_get_backlight(connector); |
980 | hw_level = intel_panel_get_backlight(connector); |
- | 981 | ret = scale_hw_to_user(connector, hw_level, bd->props.max_brightness); |
|
- | 982 | ||
854 | mutex_unlock(&dev->mode_config.mutex); |
983 | drm_modeset_unlock(&dev->mode_config.connection_mutex); |
855 | intel_runtime_pm_put(dev_priv); |
984 | intel_runtime_pm_put(dev_priv); |
856 | 985 | ||
857 | return ret; |
986 | return ret; |
858 | } |
987 | } |
859 | 988 | ||
860 | static const struct backlight_ops intel_backlight_device_ops = { |
989 | static const struct backlight_ops intel_backlight_device_ops = { |
861 | .update_status = intel_backlight_device_update_status, |
990 | .update_status = intel_backlight_device_update_status, |
862 | .get_brightness = intel_backlight_device_get_brightness, |
991 | .get_brightness = intel_backlight_device_get_brightness, |
863 | }; |
992 | }; |
864 | 993 | ||
865 | static int intel_backlight_device_register(struct intel_connector *connector) |
994 | static int intel_backlight_device_register(struct intel_connector *connector) |
866 | { |
995 | { |
867 | struct intel_panel *panel = &connector->panel; |
996 | struct intel_panel *panel = &connector->panel; |
868 | struct backlight_properties props; |
997 | struct backlight_properties props; |
869 | 998 | ||
870 | if (WARN_ON(panel->backlight.device)) |
999 | if (WARN_ON(panel->backlight.device)) |
871 | return -ENODEV; |
1000 | return -ENODEV; |
872 | 1001 | ||
873 | BUG_ON(panel->backlight.max == 0); |
1002 | WARN_ON(panel->backlight.max == 0); |
874 | 1003 | ||
875 | memset(&props, 0, sizeof(props)); |
1004 | memset(&props, 0, sizeof(props)); |
876 | props.type = BACKLIGHT_RAW; |
1005 | props.type = BACKLIGHT_RAW; |
- | 1006 | ||
- | 1007 | /* |
|
877 | props.brightness = panel->backlight.level; |
1008 | * Note: Everything should work even if the backlight device max |
- | 1009 | * presented to the userspace is arbitrarily chosen. |
|
- | 1010 | */ |
|
878 | props.max_brightness = panel->backlight.max; |
1011 | props.max_brightness = panel->backlight.max; |
- | 1012 | props.brightness = scale_hw_to_user(connector, |
|
- | 1013 | panel->backlight.level, |
|
- | 1014 | props.max_brightness); |
|
879 | 1015 | ||
880 | /* |
1016 | /* |
881 | * Note: using the same name independent of the connector prevents |
1017 | * Note: using the same name independent of the connector prevents |
882 | * registration of multiple backlight devices in the driver. |
1018 | * registration of multiple backlight devices in the driver. |
883 | */ |
1019 | */ |
884 | panel->backlight.device = |
1020 | panel->backlight.device = |
885 | backlight_device_register("intel_backlight", |
1021 | backlight_device_register("intel_backlight", |
886 | connector->base.kdev, |
1022 | connector->base.kdev, |
887 | connector, |
1023 | connector, |
888 | &intel_backlight_device_ops, &props); |
1024 | &intel_backlight_device_ops, &props); |
889 | 1025 | ||
890 | if (IS_ERR(panel->backlight.device)) { |
1026 | if (IS_ERR(panel->backlight.device)) { |
891 | DRM_ERROR("Failed to register backlight: %ld\n", |
1027 | DRM_ERROR("Failed to register backlight: %ld\n", |
892 | PTR_ERR(panel->backlight.device)); |
1028 | PTR_ERR(panel->backlight.device)); |
893 | panel->backlight.device = NULL; |
1029 | panel->backlight.device = NULL; |
894 | return -ENODEV; |
1030 | return -ENODEV; |
895 | } |
1031 | } |
896 | return 0; |
1032 | return 0; |
897 | } |
1033 | } |
898 | 1034 | ||
899 | static void intel_backlight_device_unregister(struct intel_connector *connector) |
1035 | static void intel_backlight_device_unregister(struct intel_connector *connector) |
900 | { |
1036 | { |
901 | struct intel_panel *panel = &connector->panel; |
1037 | struct intel_panel *panel = &connector->panel; |
902 | 1038 | ||
903 | if (panel->backlight.device) { |
1039 | if (panel->backlight.device) { |
904 | backlight_device_unregister(panel->backlight.device); |
1040 | backlight_device_unregister(panel->backlight.device); |
905 | panel->backlight.device = NULL; |
1041 | panel->backlight.device = NULL; |
906 | } |
1042 | } |
907 | } |
1043 | } |
908 | #else /* CONFIG_BACKLIGHT_CLASS_DEVICE */ |
1044 | #else /* CONFIG_BACKLIGHT_CLASS_DEVICE */ |
909 | static int intel_backlight_device_register(struct intel_connector *connector) |
1045 | static int intel_backlight_device_register(struct intel_connector *connector) |
910 | { |
1046 | { |
911 | return 0; |
1047 | return 0; |
912 | } |
1048 | } |
913 | static void intel_backlight_device_unregister(struct intel_connector *connector) |
1049 | static void intel_backlight_device_unregister(struct intel_connector *connector) |
914 | { |
1050 | { |
915 | } |
1051 | } |
916 | #endif /* CONFIG_BACKLIGHT_CLASS_DEVICE */ |
1052 | #endif /* CONFIG_BACKLIGHT_CLASS_DEVICE */ |
917 | 1053 | ||
918 | /* |
1054 | /* |
919 | * Note: The setup hooks can't assume pipe is set! |
1055 | * Note: The setup hooks can't assume pipe is set! |
920 | * |
1056 | * |
921 | * XXX: Query mode clock or hardware clock and program PWM modulation frequency |
1057 | * XXX: Query mode clock or hardware clock and program PWM modulation frequency |
922 | * appropriately when it's 0. Use VBT and/or sane defaults. |
1058 | * appropriately when it's 0. Use VBT and/or sane defaults. |
923 | */ |
1059 | */ |
- | 1060 | static u32 get_backlight_min_vbt(struct intel_connector *connector) |
|
- | 1061 | { |
|
- | 1062 | struct drm_device *dev = connector->base.dev; |
|
- | 1063 | struct drm_i915_private *dev_priv = dev->dev_private; |
|
- | 1064 | struct intel_panel *panel = &connector->panel; |
|
- | 1065 | ||
- | 1066 | WARN_ON(panel->backlight.max == 0); |
|
- | 1067 | ||
- | 1068 | /* vbt value is a coefficient in range [0..255] */ |
|
- | 1069 | return scale(dev_priv->vbt.backlight.min_brightness, 0, 255, |
|
- | 1070 | 0, panel->backlight.max); |
|
- | 1071 | } |
|
- | 1072 | ||
924 | static int bdw_setup_backlight(struct intel_connector *connector) |
1073 | static int bdw_setup_backlight(struct intel_connector *connector) |
925 | { |
1074 | { |
926 | struct drm_device *dev = connector->base.dev; |
1075 | struct drm_device *dev = connector->base.dev; |
927 | struct drm_i915_private *dev_priv = dev->dev_private; |
1076 | struct drm_i915_private *dev_priv = dev->dev_private; |
928 | struct intel_panel *panel = &connector->panel; |
1077 | struct intel_panel *panel = &connector->panel; |
929 | u32 pch_ctl1, pch_ctl2, val; |
1078 | u32 pch_ctl1, pch_ctl2, val; |
930 | 1079 | ||
931 | pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1); |
1080 | pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1); |
932 | panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY; |
1081 | panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY; |
933 | 1082 | ||
934 | pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2); |
1083 | pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2); |
935 | panel->backlight.max = pch_ctl2 >> 16; |
1084 | panel->backlight.max = pch_ctl2 >> 16; |
936 | if (!panel->backlight.max) |
1085 | if (!panel->backlight.max) |
937 | return -ENODEV; |
1086 | return -ENODEV; |
- | 1087 | ||
- | 1088 | panel->backlight.min = get_backlight_min_vbt(connector); |
|
938 | 1089 | ||
939 | val = bdw_get_backlight(connector); |
1090 | val = bdw_get_backlight(connector); |
940 | panel->backlight.level = intel_panel_compute_brightness(connector, val); |
1091 | panel->backlight.level = intel_panel_compute_brightness(connector, val); |
941 | 1092 | ||
942 | panel->backlight.enabled = (pch_ctl1 & BLM_PCH_PWM_ENABLE) && |
1093 | panel->backlight.enabled = (pch_ctl1 & BLM_PCH_PWM_ENABLE) && |
943 | panel->backlight.level != 0; |
1094 | panel->backlight.level != 0; |
944 | 1095 | ||
945 | return 0; |
1096 | return 0; |
946 | } |
1097 | } |
947 | 1098 | ||
948 | static int pch_setup_backlight(struct intel_connector *connector) |
1099 | static int pch_setup_backlight(struct intel_connector *connector) |
949 | { |
1100 | { |
950 | struct drm_device *dev = connector->base.dev; |
1101 | struct drm_device *dev = connector->base.dev; |
951 | struct drm_i915_private *dev_priv = dev->dev_private; |
1102 | struct drm_i915_private *dev_priv = dev->dev_private; |
952 | struct intel_panel *panel = &connector->panel; |
1103 | struct intel_panel *panel = &connector->panel; |
953 | u32 cpu_ctl2, pch_ctl1, pch_ctl2, val; |
1104 | u32 cpu_ctl2, pch_ctl1, pch_ctl2, val; |
954 | 1105 | ||
955 | pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1); |
1106 | pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1); |
956 | panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY; |
1107 | panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY; |
957 | 1108 | ||
958 | pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2); |
1109 | pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2); |
959 | panel->backlight.max = pch_ctl2 >> 16; |
1110 | panel->backlight.max = pch_ctl2 >> 16; |
960 | if (!panel->backlight.max) |
1111 | if (!panel->backlight.max) |
961 | return -ENODEV; |
1112 | return -ENODEV; |
- | 1113 | ||
- | 1114 | panel->backlight.min = get_backlight_min_vbt(connector); |
|
962 | 1115 | ||
963 | val = pch_get_backlight(connector); |
1116 | val = pch_get_backlight(connector); |
964 | panel->backlight.level = intel_panel_compute_brightness(connector, val); |
1117 | panel->backlight.level = intel_panel_compute_brightness(connector, val); |
965 | 1118 | ||
966 | cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2); |
1119 | cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2); |
967 | panel->backlight.enabled = (cpu_ctl2 & BLM_PWM_ENABLE) && |
1120 | panel->backlight.enabled = (cpu_ctl2 & BLM_PWM_ENABLE) && |
968 | (pch_ctl1 & BLM_PCH_PWM_ENABLE) && panel->backlight.level != 0; |
1121 | (pch_ctl1 & BLM_PCH_PWM_ENABLE) && panel->backlight.level != 0; |
969 | 1122 | ||
970 | return 0; |
1123 | return 0; |
971 | } |
1124 | } |
972 | 1125 | ||
973 | static int i9xx_setup_backlight(struct intel_connector *connector) |
1126 | static int i9xx_setup_backlight(struct intel_connector *connector) |
974 | { |
1127 | { |
975 | struct drm_device *dev = connector->base.dev; |
1128 | struct drm_device *dev = connector->base.dev; |
976 | struct drm_i915_private *dev_priv = dev->dev_private; |
1129 | struct drm_i915_private *dev_priv = dev->dev_private; |
977 | struct intel_panel *panel = &connector->panel; |
1130 | struct intel_panel *panel = &connector->panel; |
978 | u32 ctl, val; |
1131 | u32 ctl, val; |
979 | 1132 | ||
980 | ctl = I915_READ(BLC_PWM_CTL); |
1133 | ctl = I915_READ(BLC_PWM_CTL); |
981 | 1134 | ||
982 | if (IS_GEN2(dev)) |
1135 | if (IS_GEN2(dev) || IS_I915GM(dev) || IS_I945GM(dev)) |
983 | panel->backlight.combination_mode = ctl & BLM_LEGACY_MODE; |
1136 | panel->backlight.combination_mode = ctl & BLM_LEGACY_MODE; |
984 | 1137 | ||
985 | if (IS_PINEVIEW(dev)) |
1138 | if (IS_PINEVIEW(dev)) |
986 | panel->backlight.active_low_pwm = ctl & BLM_POLARITY_PNV; |
1139 | panel->backlight.active_low_pwm = ctl & BLM_POLARITY_PNV; |
987 | 1140 | ||
988 | panel->backlight.max = ctl >> 17; |
1141 | panel->backlight.max = ctl >> 17; |
989 | if (panel->backlight.combination_mode) |
1142 | if (panel->backlight.combination_mode) |
990 | panel->backlight.max *= 0xff; |
1143 | panel->backlight.max *= 0xff; |
991 | 1144 | ||
992 | if (!panel->backlight.max) |
1145 | if (!panel->backlight.max) |
993 | return -ENODEV; |
1146 | return -ENODEV; |
- | 1147 | ||
- | 1148 | panel->backlight.min = get_backlight_min_vbt(connector); |
|
994 | 1149 | ||
995 | val = i9xx_get_backlight(connector); |
1150 | val = i9xx_get_backlight(connector); |
996 | panel->backlight.level = intel_panel_compute_brightness(connector, val); |
1151 | panel->backlight.level = intel_panel_compute_brightness(connector, val); |
997 | 1152 | ||
998 | panel->backlight.enabled = panel->backlight.level != 0; |
1153 | panel->backlight.enabled = panel->backlight.level != 0; |
999 | 1154 | ||
1000 | return 0; |
1155 | return 0; |
1001 | } |
1156 | } |
1002 | 1157 | ||
1003 | static int i965_setup_backlight(struct intel_connector *connector) |
1158 | static int i965_setup_backlight(struct intel_connector *connector) |
1004 | { |
1159 | { |
1005 | struct drm_device *dev = connector->base.dev; |
1160 | struct drm_device *dev = connector->base.dev; |
1006 | struct drm_i915_private *dev_priv = dev->dev_private; |
1161 | struct drm_i915_private *dev_priv = dev->dev_private; |
1007 | struct intel_panel *panel = &connector->panel; |
1162 | struct intel_panel *panel = &connector->panel; |
1008 | u32 ctl, ctl2, val; |
1163 | u32 ctl, ctl2, val; |
1009 | 1164 | ||
1010 | ctl2 = I915_READ(BLC_PWM_CTL2); |
1165 | ctl2 = I915_READ(BLC_PWM_CTL2); |
1011 | panel->backlight.combination_mode = ctl2 & BLM_COMBINATION_MODE; |
1166 | panel->backlight.combination_mode = ctl2 & BLM_COMBINATION_MODE; |
1012 | panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965; |
1167 | panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965; |
1013 | 1168 | ||
1014 | ctl = I915_READ(BLC_PWM_CTL); |
1169 | ctl = I915_READ(BLC_PWM_CTL); |
1015 | panel->backlight.max = ctl >> 16; |
1170 | panel->backlight.max = ctl >> 16; |
1016 | if (panel->backlight.combination_mode) |
1171 | if (panel->backlight.combination_mode) |
1017 | panel->backlight.max *= 0xff; |
1172 | panel->backlight.max *= 0xff; |
1018 | 1173 | ||
1019 | if (!panel->backlight.max) |
1174 | if (!panel->backlight.max) |
1020 | return -ENODEV; |
1175 | return -ENODEV; |
- | 1176 | ||
- | 1177 | panel->backlight.min = get_backlight_min_vbt(connector); |
|
1021 | 1178 | ||
1022 | val = i9xx_get_backlight(connector); |
1179 | val = i9xx_get_backlight(connector); |
1023 | panel->backlight.level = intel_panel_compute_brightness(connector, val); |
1180 | panel->backlight.level = intel_panel_compute_brightness(connector, val); |
1024 | 1181 | ||
1025 | panel->backlight.enabled = (ctl2 & BLM_PWM_ENABLE) && |
1182 | panel->backlight.enabled = (ctl2 & BLM_PWM_ENABLE) && |
1026 | panel->backlight.level != 0; |
1183 | panel->backlight.level != 0; |
1027 | 1184 | ||
1028 | return 0; |
1185 | return 0; |
1029 | } |
1186 | } |
1030 | 1187 | ||
1031 | static int vlv_setup_backlight(struct intel_connector *connector) |
1188 | static int vlv_setup_backlight(struct intel_connector *connector) |
1032 | { |
1189 | { |
1033 | struct drm_device *dev = connector->base.dev; |
1190 | struct drm_device *dev = connector->base.dev; |
1034 | struct drm_i915_private *dev_priv = dev->dev_private; |
1191 | struct drm_i915_private *dev_priv = dev->dev_private; |
1035 | struct intel_panel *panel = &connector->panel; |
1192 | struct intel_panel *panel = &connector->panel; |
1036 | enum pipe pipe; |
1193 | enum pipe pipe; |
1037 | u32 ctl, ctl2, val; |
1194 | u32 ctl, ctl2, val; |
1038 | 1195 | ||
1039 | for_each_pipe(pipe) { |
1196 | for_each_pipe(pipe) { |
1040 | u32 cur_val = I915_READ(VLV_BLC_PWM_CTL(pipe)); |
1197 | u32 cur_val = I915_READ(VLV_BLC_PWM_CTL(pipe)); |
1041 | 1198 | ||
1042 | /* Skip if the modulation freq is already set */ |
1199 | /* Skip if the modulation freq is already set */ |
1043 | if (cur_val & ~BACKLIGHT_DUTY_CYCLE_MASK) |
1200 | if (cur_val & ~BACKLIGHT_DUTY_CYCLE_MASK) |
1044 | continue; |
1201 | continue; |
1045 | 1202 | ||
1046 | cur_val &= BACKLIGHT_DUTY_CYCLE_MASK; |
1203 | cur_val &= BACKLIGHT_DUTY_CYCLE_MASK; |
1047 | I915_WRITE(VLV_BLC_PWM_CTL(pipe), (0xf42 << 16) | |
1204 | I915_WRITE(VLV_BLC_PWM_CTL(pipe), (0xf42 << 16) | |
1048 | cur_val); |
1205 | cur_val); |
1049 | } |
1206 | } |
1050 | 1207 | ||
1051 | ctl2 = I915_READ(VLV_BLC_PWM_CTL2(PIPE_A)); |
1208 | ctl2 = I915_READ(VLV_BLC_PWM_CTL2(PIPE_A)); |
1052 | panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965; |
1209 | panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965; |
1053 | 1210 | ||
1054 | ctl = I915_READ(VLV_BLC_PWM_CTL(PIPE_A)); |
1211 | ctl = I915_READ(VLV_BLC_PWM_CTL(PIPE_A)); |
1055 | panel->backlight.max = ctl >> 16; |
1212 | panel->backlight.max = ctl >> 16; |
1056 | if (!panel->backlight.max) |
1213 | if (!panel->backlight.max) |
1057 | return -ENODEV; |
1214 | return -ENODEV; |
- | 1215 | ||
- | 1216 | panel->backlight.min = get_backlight_min_vbt(connector); |
|
1058 | 1217 | ||
1059 | val = _vlv_get_backlight(dev, PIPE_A); |
1218 | val = _vlv_get_backlight(dev, PIPE_A); |
1060 | panel->backlight.level = intel_panel_compute_brightness(connector, val); |
1219 | panel->backlight.level = intel_panel_compute_brightness(connector, val); |
1061 | 1220 | ||
1062 | panel->backlight.enabled = (ctl2 & BLM_PWM_ENABLE) && |
1221 | panel->backlight.enabled = (ctl2 & BLM_PWM_ENABLE) && |
1063 | panel->backlight.level != 0; |
1222 | panel->backlight.level != 0; |
1064 | 1223 | ||
1065 | return 0; |
1224 | return 0; |
1066 | } |
1225 | } |
1067 | 1226 | ||
1068 | int intel_panel_setup_backlight(struct drm_connector *connector) |
1227 | int intel_panel_setup_backlight(struct drm_connector *connector) |
1069 | { |
1228 | { |
1070 | struct drm_device *dev = connector->dev; |
1229 | struct drm_device *dev = connector->dev; |
1071 | struct drm_i915_private *dev_priv = dev->dev_private; |
1230 | struct drm_i915_private *dev_priv = dev->dev_private; |
1072 | struct intel_connector *intel_connector = to_intel_connector(connector); |
1231 | struct intel_connector *intel_connector = to_intel_connector(connector); |
1073 | struct intel_panel *panel = &intel_connector->panel; |
1232 | struct intel_panel *panel = &intel_connector->panel; |
1074 | unsigned long flags; |
1233 | unsigned long flags; |
1075 | int ret; |
1234 | int ret; |
- | 1235 | ||
- | 1236 | if (!dev_priv->vbt.backlight.present) { |
|
- | 1237 | if (dev_priv->quirks & QUIRK_BACKLIGHT_PRESENT) { |
|
- | 1238 | DRM_DEBUG_KMS("no backlight present per VBT, but present per quirk\n"); |
|
- | 1239 | } else { |
|
- | 1240 | DRM_DEBUG_KMS("no backlight present per VBT\n"); |
|
- | 1241 | return 0; |
|
- | 1242 | } |
|
- | 1243 | } |
|
1076 | 1244 | ||
1077 | /* set level and max in panel struct */ |
1245 | /* set level and max in panel struct */ |
1078 | spin_lock_irqsave(&dev_priv->backlight_lock, flags); |
1246 | spin_lock_irqsave(&dev_priv->backlight_lock, flags); |
1079 | ret = dev_priv->display.setup_backlight(intel_connector); |
1247 | ret = dev_priv->display.setup_backlight(intel_connector); |
1080 | spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); |
1248 | spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); |
1081 | 1249 | ||
1082 | if (ret) { |
1250 | if (ret) { |
1083 | DRM_DEBUG_KMS("failed to setup backlight for connector %s\n", |
1251 | DRM_DEBUG_KMS("failed to setup backlight for connector %s\n", |
1084 | drm_get_connector_name(connector)); |
1252 | connector->name); |
1085 | return ret; |
1253 | return ret; |
1086 | } |
1254 | } |
1087 | 1255 | ||
1088 | intel_backlight_device_register(intel_connector); |
1256 | intel_backlight_device_register(intel_connector); |
1089 | 1257 | ||
1090 | panel->backlight.present = true; |
1258 | panel->backlight.present = true; |
1091 | 1259 | ||
1092 | DRM_DEBUG_KMS("backlight initialized, %s, brightness %u/%u, " |
1260 | DRM_DEBUG_KMS("backlight initialized, %s, brightness %u/%u, " |
1093 | "sysfs interface %sregistered\n", |
1261 | "sysfs interface %sregistered\n", |
1094 | panel->backlight.enabled ? "enabled" : "disabled", |
1262 | panel->backlight.enabled ? "enabled" : "disabled", |
1095 | panel->backlight.level, panel->backlight.max, |
1263 | panel->backlight.level, panel->backlight.max, |
1096 | panel->backlight.device ? "" : "not "); |
1264 | panel->backlight.device ? "" : "not "); |
1097 | 1265 | ||
1098 | return 0; |
1266 | return 0; |
1099 | } |
1267 | } |
1100 | 1268 | ||
1101 | void intel_panel_destroy_backlight(struct drm_connector *connector) |
1269 | void intel_panel_destroy_backlight(struct drm_connector *connector) |
1102 | { |
1270 | { |
1103 | struct intel_connector *intel_connector = to_intel_connector(connector); |
1271 | struct intel_connector *intel_connector = to_intel_connector(connector); |
1104 | struct intel_panel *panel = &intel_connector->panel; |
1272 | struct intel_panel *panel = &intel_connector->panel; |
1105 | 1273 | ||
1106 | panel->backlight.present = false; |
1274 | panel->backlight.present = false; |
1107 | intel_backlight_device_unregister(intel_connector); |
1275 | intel_backlight_device_unregister(intel_connector); |
1108 | } |
1276 | } |
1109 | - | ||
1110 | /** |
- | |
1111 | * intel_find_panel_downclock - find the reduced downclock for LVDS in EDID |
- | |
1112 | * @dev: drm device |
- | |
1113 | * @fixed_mode : panel native mode |
- | |
1114 | * @connector: LVDS/eDP connector |
- | |
1115 | * |
- | |
1116 | * Return downclock_avail |
- | |
1117 | * Find the reduced downclock for LVDS/eDP in EDID. |
- | |
1118 | */ |
- | |
1119 | struct drm_display_mode * |
- | |
1120 | intel_find_panel_downclock(struct drm_device *dev, |
- | |
1121 | struct drm_display_mode *fixed_mode, |
- | |
1122 | struct drm_connector *connector) |
- | |
1123 | { |
- | |
1124 | struct drm_display_mode *scan, *tmp_mode; |
- | |
1125 | int temp_downclock; |
- | |
1126 | - | ||
1127 | temp_downclock = fixed_mode->clock; |
- | |
1128 | tmp_mode = NULL; |
- | |
1129 | - | ||
1130 | list_for_each_entry(scan, &connector->probed_modes, head) { |
- | |
1131 | /* |
- | |
1132 | * If one mode has the same resolution with the fixed_panel |
- | |
1133 | * mode while they have the different refresh rate, it means |
- | |
1134 | * that the reduced downclock is found. In such |
- | |
1135 | * case we can set the different FPx0/1 to dynamically select |
- | |
1136 | * between low and high frequency. |
- | |
1137 | */ |
- | |
1138 | if (scan->hdisplay == fixed_mode->hdisplay && |
- | |
1139 | scan->hsync_start == fixed_mode->hsync_start && |
- | |
1140 | scan->hsync_end == fixed_mode->hsync_end && |
- | |
1141 | scan->htotal == fixed_mode->htotal && |
- | |
1142 | scan->vdisplay == fixed_mode->vdisplay && |
- | |
1143 | scan->vsync_start == fixed_mode->vsync_start && |
- | |
1144 | scan->vsync_end == fixed_mode->vsync_end && |
- | |
1145 | scan->vtotal == fixed_mode->vtotal) { |
- | |
1146 | if (scan->clock < temp_downclock) { |
- | |
1147 | /* |
- | |
1148 | * The downclock is already found. But we |
- | |
1149 | * expect to find the lower downclock. |
- | |
1150 | */ |
- | |
1151 | temp_downclock = scan->clock; |
- | |
1152 | tmp_mode = scan; |
- | |
1153 | } |
- | |
1154 | } |
- | |
1155 | } |
- | |
1156 | - | ||
1157 | if (temp_downclock < fixed_mode->clock) |
- | |
1158 | return drm_mode_duplicate(dev, tmp_mode); |
- | |
1159 | else |
- | |
1160 | return NULL; |
- | |
1161 | } |
- | |
1162 | 1277 | ||
1163 | /* Set up chip specific backlight functions */ |
1278 | /* Set up chip specific backlight functions */ |
1164 | void intel_panel_init_backlight_funcs(struct drm_device *dev) |
1279 | void intel_panel_init_backlight_funcs(struct drm_device *dev) |
1165 | { |
1280 | { |
1166 | struct drm_i915_private *dev_priv = dev->dev_private; |
1281 | struct drm_i915_private *dev_priv = dev->dev_private; |
1167 | 1282 | ||
1168 | if (IS_BROADWELL(dev)) { |
1283 | if (IS_BROADWELL(dev)) { |
1169 | dev_priv->display.setup_backlight = bdw_setup_backlight; |
1284 | dev_priv->display.setup_backlight = bdw_setup_backlight; |
1170 | dev_priv->display.enable_backlight = bdw_enable_backlight; |
1285 | dev_priv->display.enable_backlight = bdw_enable_backlight; |
1171 | dev_priv->display.disable_backlight = pch_disable_backlight; |
1286 | dev_priv->display.disable_backlight = pch_disable_backlight; |
1172 | dev_priv->display.set_backlight = bdw_set_backlight; |
1287 | dev_priv->display.set_backlight = bdw_set_backlight; |
1173 | dev_priv->display.get_backlight = bdw_get_backlight; |
1288 | dev_priv->display.get_backlight = bdw_get_backlight; |
1174 | } else if (HAS_PCH_SPLIT(dev)) { |
1289 | } else if (HAS_PCH_SPLIT(dev)) { |
1175 | dev_priv->display.setup_backlight = pch_setup_backlight; |
1290 | dev_priv->display.setup_backlight = pch_setup_backlight; |
1176 | dev_priv->display.enable_backlight = pch_enable_backlight; |
1291 | dev_priv->display.enable_backlight = pch_enable_backlight; |
1177 | dev_priv->display.disable_backlight = pch_disable_backlight; |
1292 | dev_priv->display.disable_backlight = pch_disable_backlight; |
1178 | dev_priv->display.set_backlight = pch_set_backlight; |
1293 | dev_priv->display.set_backlight = pch_set_backlight; |
1179 | dev_priv->display.get_backlight = pch_get_backlight; |
1294 | dev_priv->display.get_backlight = pch_get_backlight; |
1180 | } else if (IS_VALLEYVIEW(dev)) { |
1295 | } else if (IS_VALLEYVIEW(dev)) { |
1181 | dev_priv->display.setup_backlight = vlv_setup_backlight; |
1296 | dev_priv->display.setup_backlight = vlv_setup_backlight; |
1182 | dev_priv->display.enable_backlight = vlv_enable_backlight; |
1297 | dev_priv->display.enable_backlight = vlv_enable_backlight; |
1183 | dev_priv->display.disable_backlight = vlv_disable_backlight; |
1298 | dev_priv->display.disable_backlight = vlv_disable_backlight; |
1184 | dev_priv->display.set_backlight = vlv_set_backlight; |
1299 | dev_priv->display.set_backlight = vlv_set_backlight; |
1185 | dev_priv->display.get_backlight = vlv_get_backlight; |
1300 | dev_priv->display.get_backlight = vlv_get_backlight; |
1186 | } else if (IS_GEN4(dev)) { |
1301 | } else if (IS_GEN4(dev)) { |
1187 | dev_priv->display.setup_backlight = i965_setup_backlight; |
1302 | dev_priv->display.setup_backlight = i965_setup_backlight; |
1188 | dev_priv->display.enable_backlight = i965_enable_backlight; |
1303 | dev_priv->display.enable_backlight = i965_enable_backlight; |
1189 | dev_priv->display.disable_backlight = i965_disable_backlight; |
1304 | dev_priv->display.disable_backlight = i965_disable_backlight; |
1190 | dev_priv->display.set_backlight = i9xx_set_backlight; |
1305 | dev_priv->display.set_backlight = i9xx_set_backlight; |
1191 | dev_priv->display.get_backlight = i9xx_get_backlight; |
1306 | dev_priv->display.get_backlight = i9xx_get_backlight; |
1192 | } else { |
1307 | } else { |
1193 | dev_priv->display.setup_backlight = i9xx_setup_backlight; |
1308 | dev_priv->display.setup_backlight = i9xx_setup_backlight; |
1194 | dev_priv->display.enable_backlight = i9xx_enable_backlight; |
1309 | dev_priv->display.enable_backlight = i9xx_enable_backlight; |
1195 | dev_priv->display.disable_backlight = i9xx_disable_backlight; |
1310 | dev_priv->display.disable_backlight = i9xx_disable_backlight; |
1196 | dev_priv->display.set_backlight = i9xx_set_backlight; |
1311 | dev_priv->display.set_backlight = i9xx_set_backlight; |
1197 | dev_priv->display.get_backlight = i9xx_get_backlight; |
1312 | dev_priv->display.get_backlight = i9xx_get_backlight; |
1198 | } |
1313 | } |
1199 | } |
1314 | } |
1200 | 1315 | ||
1201 | int intel_panel_init(struct intel_panel *panel, |
1316 | int intel_panel_init(struct intel_panel *panel, |
1202 | struct drm_display_mode *fixed_mode) |
1317 | struct drm_display_mode *fixed_mode, |
- | 1318 | struct drm_display_mode *downclock_mode) |
|
1203 | { |
1319 | { |
1204 | panel->fixed_mode = fixed_mode; |
1320 | panel->fixed_mode = fixed_mode; |
- | 1321 | panel->downclock_mode = downclock_mode; |
|
1205 | 1322 | ||
1206 | return 0; |
1323 | return 0; |
1207 | } |
1324 | } |
1208 | 1325 | ||
1209 | void intel_panel_fini(struct intel_panel *panel) |
1326 | void intel_panel_fini(struct intel_panel *panel) |
1210 | { |
1327 | { |
1211 | struct intel_connector *intel_connector = |
1328 | struct intel_connector *intel_connector = |
1212 | container_of(panel, struct intel_connector, panel); |
1329 | container_of(panel, struct intel_connector, panel); |
1213 | 1330 | ||
1214 | if (panel->fixed_mode) |
1331 | if (panel->fixed_mode) |
1215 | drm_mode_destroy(intel_connector->base.dev, panel->fixed_mode); |
1332 | drm_mode_destroy(intel_connector->base.dev, panel->fixed_mode); |
1216 | 1333 | ||
1217 | if (panel->downclock_mode) |
1334 | if (panel->downclock_mode) |
1218 | drm_mode_destroy(intel_connector->base.dev, |
1335 | drm_mode_destroy(intel_connector->base.dev, |
1219 | panel->downclock_mode); |
1336 | panel->downclock_mode); |
1220 | }>>><>><>><>><>><>><>>=><=>>>>><>><>><>>><>><>>><>><>><>> |
1337 | }><>><>><>><>><>><>=><=>>>>><>><>><>>><>><>>><>><>><>>>> |