Rev 6283 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 6283 | Rev 6937 | ||
---|---|---|---|
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 |
34 | #include |
35 | #include |
35 | #include |
36 | #include "intel_drv.h" |
36 | #include "intel_drv.h" |
37 | 37 | ||
38 | #define CRC_PMIC_PWM_PERIOD_NS 21333 |
38 | #define CRC_PMIC_PWM_PERIOD_NS 21333 |
39 | 39 | ||
40 | void |
40 | void |
41 | intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode, |
41 | intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode, |
42 | struct drm_display_mode *adjusted_mode) |
42 | struct drm_display_mode *adjusted_mode) |
43 | { |
43 | { |
44 | drm_mode_copy(adjusted_mode, fixed_mode); |
44 | drm_mode_copy(adjusted_mode, fixed_mode); |
45 | 45 | ||
46 | drm_mode_set_crtcinfo(adjusted_mode, 0); |
46 | drm_mode_set_crtcinfo(adjusted_mode, 0); |
47 | } |
47 | } |
48 | 48 | ||
49 | /** |
49 | /** |
50 | * intel_find_panel_downclock - find the reduced downclock for LVDS in EDID |
50 | * intel_find_panel_downclock - find the reduced downclock for LVDS in EDID |
51 | * @dev: drm device |
51 | * @dev: drm device |
52 | * @fixed_mode : panel native mode |
52 | * @fixed_mode : panel native mode |
53 | * @connector: LVDS/eDP connector |
53 | * @connector: LVDS/eDP connector |
54 | * |
54 | * |
55 | * Return downclock_avail |
55 | * Return downclock_avail |
56 | * Find the reduced downclock for LVDS/eDP in EDID. |
56 | * Find the reduced downclock for LVDS/eDP in EDID. |
57 | */ |
57 | */ |
58 | struct drm_display_mode * |
58 | struct drm_display_mode * |
59 | intel_find_panel_downclock(struct drm_device *dev, |
59 | intel_find_panel_downclock(struct drm_device *dev, |
60 | struct drm_display_mode *fixed_mode, |
60 | struct drm_display_mode *fixed_mode, |
61 | struct drm_connector *connector) |
61 | struct drm_connector *connector) |
62 | { |
62 | { |
63 | struct drm_display_mode *scan, *tmp_mode; |
63 | struct drm_display_mode *scan, *tmp_mode; |
64 | int temp_downclock; |
64 | int temp_downclock; |
65 | 65 | ||
66 | temp_downclock = fixed_mode->clock; |
66 | temp_downclock = fixed_mode->clock; |
67 | tmp_mode = NULL; |
67 | tmp_mode = NULL; |
68 | 68 | ||
69 | list_for_each_entry(scan, &connector->probed_modes, head) { |
69 | list_for_each_entry(scan, &connector->probed_modes, head) { |
70 | /* |
70 | /* |
71 | * If one mode has the same resolution with the fixed_panel |
71 | * If one mode has the same resolution with the fixed_panel |
72 | * mode while they have the different refresh rate, it means |
72 | * mode while they have the different refresh rate, it means |
73 | * that the reduced downclock is found. In such |
73 | * that the reduced downclock is found. In such |
74 | * case we can set the different FPx0/1 to dynamically select |
74 | * case we can set the different FPx0/1 to dynamically select |
75 | * between low and high frequency. |
75 | * between low and high frequency. |
76 | */ |
76 | */ |
77 | if (scan->hdisplay == fixed_mode->hdisplay && |
77 | if (scan->hdisplay == fixed_mode->hdisplay && |
78 | scan->hsync_start == fixed_mode->hsync_start && |
78 | scan->hsync_start == fixed_mode->hsync_start && |
79 | scan->hsync_end == fixed_mode->hsync_end && |
79 | scan->hsync_end == fixed_mode->hsync_end && |
80 | scan->htotal == fixed_mode->htotal && |
80 | scan->htotal == fixed_mode->htotal && |
81 | scan->vdisplay == fixed_mode->vdisplay && |
81 | scan->vdisplay == fixed_mode->vdisplay && |
82 | scan->vsync_start == fixed_mode->vsync_start && |
82 | scan->vsync_start == fixed_mode->vsync_start && |
83 | scan->vsync_end == fixed_mode->vsync_end && |
83 | scan->vsync_end == fixed_mode->vsync_end && |
84 | scan->vtotal == fixed_mode->vtotal) { |
84 | scan->vtotal == fixed_mode->vtotal) { |
85 | if (scan->clock < temp_downclock) { |
85 | if (scan->clock < temp_downclock) { |
86 | /* |
86 | /* |
87 | * The downclock is already found. But we |
87 | * The downclock is already found. But we |
88 | * expect to find the lower downclock. |
88 | * expect to find the lower downclock. |
89 | */ |
89 | */ |
90 | temp_downclock = scan->clock; |
90 | temp_downclock = scan->clock; |
91 | tmp_mode = scan; |
91 | tmp_mode = scan; |
92 | } |
92 | } |
93 | } |
93 | } |
94 | } |
94 | } |
95 | 95 | ||
96 | if (temp_downclock < fixed_mode->clock) |
96 | if (temp_downclock < fixed_mode->clock) |
97 | return drm_mode_duplicate(dev, tmp_mode); |
97 | return drm_mode_duplicate(dev, tmp_mode); |
98 | else |
98 | else |
99 | return NULL; |
99 | return NULL; |
100 | } |
100 | } |
101 | 101 | ||
102 | /* adjusted_mode has been preset to be the panel's fixed mode */ |
102 | /* adjusted_mode has been preset to be the panel's fixed mode */ |
103 | void |
103 | void |
104 | intel_pch_panel_fitting(struct intel_crtc *intel_crtc, |
104 | intel_pch_panel_fitting(struct intel_crtc *intel_crtc, |
105 | struct intel_crtc_state *pipe_config, |
105 | struct intel_crtc_state *pipe_config, |
106 | int fitting_mode) |
106 | int fitting_mode) |
107 | { |
107 | { |
108 | const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; |
108 | const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; |
109 | int x = 0, y = 0, width = 0, height = 0; |
109 | int x = 0, y = 0, width = 0, height = 0; |
110 | 110 | ||
111 | /* Native modes don't need fitting */ |
111 | /* Native modes don't need fitting */ |
112 | if (adjusted_mode->crtc_hdisplay == pipe_config->pipe_src_w && |
112 | if (adjusted_mode->crtc_hdisplay == pipe_config->pipe_src_w && |
113 | adjusted_mode->crtc_vdisplay == pipe_config->pipe_src_h) |
113 | adjusted_mode->crtc_vdisplay == pipe_config->pipe_src_h) |
114 | goto done; |
114 | goto done; |
115 | 115 | ||
116 | switch (fitting_mode) { |
116 | switch (fitting_mode) { |
117 | case DRM_MODE_SCALE_CENTER: |
117 | case DRM_MODE_SCALE_CENTER: |
118 | width = pipe_config->pipe_src_w; |
118 | width = pipe_config->pipe_src_w; |
119 | height = pipe_config->pipe_src_h; |
119 | height = pipe_config->pipe_src_h; |
120 | x = (adjusted_mode->crtc_hdisplay - width + 1)/2; |
120 | x = (adjusted_mode->crtc_hdisplay - width + 1)/2; |
121 | y = (adjusted_mode->crtc_vdisplay - height + 1)/2; |
121 | y = (adjusted_mode->crtc_vdisplay - height + 1)/2; |
122 | break; |
122 | break; |
123 | 123 | ||
124 | case DRM_MODE_SCALE_ASPECT: |
124 | case DRM_MODE_SCALE_ASPECT: |
125 | /* Scale but preserve the aspect ratio */ |
125 | /* Scale but preserve the aspect ratio */ |
126 | { |
126 | { |
127 | u32 scaled_width = adjusted_mode->crtc_hdisplay |
127 | u32 scaled_width = adjusted_mode->crtc_hdisplay |
128 | * pipe_config->pipe_src_h; |
128 | * pipe_config->pipe_src_h; |
129 | u32 scaled_height = pipe_config->pipe_src_w |
129 | u32 scaled_height = pipe_config->pipe_src_w |
130 | * adjusted_mode->crtc_vdisplay; |
130 | * adjusted_mode->crtc_vdisplay; |
131 | if (scaled_width > scaled_height) { /* pillar */ |
131 | if (scaled_width > scaled_height) { /* pillar */ |
132 | width = scaled_height / pipe_config->pipe_src_h; |
132 | width = scaled_height / pipe_config->pipe_src_h; |
133 | if (width & 1) |
133 | if (width & 1) |
134 | width++; |
134 | width++; |
135 | x = (adjusted_mode->crtc_hdisplay - width + 1) / 2; |
135 | x = (adjusted_mode->crtc_hdisplay - width + 1) / 2; |
136 | y = 0; |
136 | y = 0; |
137 | height = adjusted_mode->crtc_vdisplay; |
137 | height = adjusted_mode->crtc_vdisplay; |
138 | } else if (scaled_width < scaled_height) { /* letter */ |
138 | } else if (scaled_width < scaled_height) { /* letter */ |
139 | height = scaled_width / pipe_config->pipe_src_w; |
139 | height = scaled_width / pipe_config->pipe_src_w; |
140 | if (height & 1) |
140 | if (height & 1) |
141 | height++; |
141 | height++; |
142 | y = (adjusted_mode->crtc_vdisplay - height + 1) / 2; |
142 | y = (adjusted_mode->crtc_vdisplay - height + 1) / 2; |
143 | x = 0; |
143 | x = 0; |
144 | width = adjusted_mode->crtc_hdisplay; |
144 | width = adjusted_mode->crtc_hdisplay; |
145 | } else { |
145 | } else { |
146 | x = y = 0; |
146 | x = y = 0; |
147 | width = adjusted_mode->crtc_hdisplay; |
147 | width = adjusted_mode->crtc_hdisplay; |
148 | height = adjusted_mode->crtc_vdisplay; |
148 | height = adjusted_mode->crtc_vdisplay; |
149 | } |
149 | } |
150 | } |
150 | } |
151 | break; |
151 | break; |
152 | 152 | ||
153 | case DRM_MODE_SCALE_FULLSCREEN: |
153 | case DRM_MODE_SCALE_FULLSCREEN: |
154 | x = y = 0; |
154 | x = y = 0; |
155 | width = adjusted_mode->crtc_hdisplay; |
155 | width = adjusted_mode->crtc_hdisplay; |
156 | height = adjusted_mode->crtc_vdisplay; |
156 | height = adjusted_mode->crtc_vdisplay; |
157 | break; |
157 | break; |
158 | 158 | ||
159 | default: |
159 | default: |
160 | WARN(1, "bad panel fit mode: %d\n", fitting_mode); |
160 | WARN(1, "bad panel fit mode: %d\n", fitting_mode); |
161 | return; |
161 | return; |
162 | } |
162 | } |
163 | 163 | ||
164 | done: |
164 | done: |
165 | pipe_config->pch_pfit.pos = (x << 16) | y; |
165 | pipe_config->pch_pfit.pos = (x << 16) | y; |
166 | pipe_config->pch_pfit.size = (width << 16) | height; |
166 | pipe_config->pch_pfit.size = (width << 16) | height; |
167 | pipe_config->pch_pfit.enabled = pipe_config->pch_pfit.size != 0; |
167 | pipe_config->pch_pfit.enabled = pipe_config->pch_pfit.size != 0; |
168 | } |
168 | } |
169 | 169 | ||
170 | static void |
170 | static void |
171 | centre_horizontally(struct drm_display_mode *adjusted_mode, |
171 | centre_horizontally(struct drm_display_mode *adjusted_mode, |
172 | int width) |
172 | int width) |
173 | { |
173 | { |
174 | u32 border, sync_pos, blank_width, sync_width; |
174 | u32 border, sync_pos, blank_width, sync_width; |
175 | 175 | ||
176 | /* keep the hsync and hblank widths constant */ |
176 | /* keep the hsync and hblank widths constant */ |
177 | sync_width = adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start; |
177 | sync_width = adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start; |
178 | blank_width = adjusted_mode->crtc_hblank_end - adjusted_mode->crtc_hblank_start; |
178 | blank_width = adjusted_mode->crtc_hblank_end - adjusted_mode->crtc_hblank_start; |
179 | sync_pos = (blank_width - sync_width + 1) / 2; |
179 | sync_pos = (blank_width - sync_width + 1) / 2; |
180 | 180 | ||
181 | border = (adjusted_mode->crtc_hdisplay - width + 1) / 2; |
181 | border = (adjusted_mode->crtc_hdisplay - width + 1) / 2; |
182 | border += border & 1; /* make the border even */ |
182 | border += border & 1; /* make the border even */ |
183 | 183 | ||
184 | adjusted_mode->crtc_hdisplay = width; |
184 | adjusted_mode->crtc_hdisplay = width; |
185 | adjusted_mode->crtc_hblank_start = width + border; |
185 | adjusted_mode->crtc_hblank_start = width + border; |
186 | adjusted_mode->crtc_hblank_end = adjusted_mode->crtc_hblank_start + blank_width; |
186 | adjusted_mode->crtc_hblank_end = adjusted_mode->crtc_hblank_start + blank_width; |
187 | 187 | ||
188 | adjusted_mode->crtc_hsync_start = adjusted_mode->crtc_hblank_start + sync_pos; |
188 | adjusted_mode->crtc_hsync_start = adjusted_mode->crtc_hblank_start + sync_pos; |
189 | adjusted_mode->crtc_hsync_end = adjusted_mode->crtc_hsync_start + sync_width; |
189 | adjusted_mode->crtc_hsync_end = adjusted_mode->crtc_hsync_start + sync_width; |
190 | } |
190 | } |
191 | 191 | ||
192 | static void |
192 | static void |
193 | centre_vertically(struct drm_display_mode *adjusted_mode, |
193 | centre_vertically(struct drm_display_mode *adjusted_mode, |
194 | int height) |
194 | int height) |
195 | { |
195 | { |
196 | u32 border, sync_pos, blank_width, sync_width; |
196 | u32 border, sync_pos, blank_width, sync_width; |
197 | 197 | ||
198 | /* keep the vsync and vblank widths constant */ |
198 | /* keep the vsync and vblank widths constant */ |
199 | sync_width = adjusted_mode->crtc_vsync_end - adjusted_mode->crtc_vsync_start; |
199 | sync_width = adjusted_mode->crtc_vsync_end - adjusted_mode->crtc_vsync_start; |
200 | blank_width = adjusted_mode->crtc_vblank_end - adjusted_mode->crtc_vblank_start; |
200 | blank_width = adjusted_mode->crtc_vblank_end - adjusted_mode->crtc_vblank_start; |
201 | sync_pos = (blank_width - sync_width + 1) / 2; |
201 | sync_pos = (blank_width - sync_width + 1) / 2; |
202 | 202 | ||
203 | border = (adjusted_mode->crtc_vdisplay - height + 1) / 2; |
203 | border = (adjusted_mode->crtc_vdisplay - height + 1) / 2; |
204 | 204 | ||
205 | adjusted_mode->crtc_vdisplay = height; |
205 | adjusted_mode->crtc_vdisplay = height; |
206 | adjusted_mode->crtc_vblank_start = height + border; |
206 | adjusted_mode->crtc_vblank_start = height + border; |
207 | adjusted_mode->crtc_vblank_end = adjusted_mode->crtc_vblank_start + blank_width; |
207 | adjusted_mode->crtc_vblank_end = adjusted_mode->crtc_vblank_start + blank_width; |
208 | 208 | ||
209 | adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vblank_start + sync_pos; |
209 | adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vblank_start + sync_pos; |
210 | adjusted_mode->crtc_vsync_end = adjusted_mode->crtc_vsync_start + sync_width; |
210 | adjusted_mode->crtc_vsync_end = adjusted_mode->crtc_vsync_start + sync_width; |
211 | } |
211 | } |
212 | 212 | ||
213 | static inline u32 panel_fitter_scaling(u32 source, u32 target) |
213 | static inline u32 panel_fitter_scaling(u32 source, u32 target) |
214 | { |
214 | { |
215 | /* |
215 | /* |
216 | * Floating point operation is not supported. So the FACTOR |
216 | * Floating point operation is not supported. So the FACTOR |
217 | * is defined, which can avoid the floating point computation |
217 | * is defined, which can avoid the floating point computation |
218 | * when calculating the panel ratio. |
218 | * when calculating the panel ratio. |
219 | */ |
219 | */ |
220 | #define ACCURACY 12 |
220 | #define ACCURACY 12 |
221 | #define FACTOR (1 << ACCURACY) |
221 | #define FACTOR (1 << ACCURACY) |
222 | u32 ratio = source * FACTOR / target; |
222 | u32 ratio = source * FACTOR / target; |
223 | return (FACTOR * ratio + FACTOR/2) / FACTOR; |
223 | return (FACTOR * ratio + FACTOR/2) / FACTOR; |
224 | } |
224 | } |
225 | 225 | ||
226 | static void i965_scale_aspect(struct intel_crtc_state *pipe_config, |
226 | static void i965_scale_aspect(struct intel_crtc_state *pipe_config, |
227 | u32 *pfit_control) |
227 | u32 *pfit_control) |
228 | { |
228 | { |
229 | const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; |
229 | const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; |
230 | u32 scaled_width = adjusted_mode->crtc_hdisplay * |
230 | u32 scaled_width = adjusted_mode->crtc_hdisplay * |
231 | pipe_config->pipe_src_h; |
231 | pipe_config->pipe_src_h; |
232 | u32 scaled_height = pipe_config->pipe_src_w * |
232 | u32 scaled_height = pipe_config->pipe_src_w * |
233 | adjusted_mode->crtc_vdisplay; |
233 | adjusted_mode->crtc_vdisplay; |
234 | 234 | ||
235 | /* 965+ is easy, it does everything in hw */ |
235 | /* 965+ is easy, it does everything in hw */ |
236 | if (scaled_width > scaled_height) |
236 | if (scaled_width > scaled_height) |
237 | *pfit_control |= PFIT_ENABLE | |
237 | *pfit_control |= PFIT_ENABLE | |
238 | PFIT_SCALING_PILLAR; |
238 | PFIT_SCALING_PILLAR; |
239 | else if (scaled_width < scaled_height) |
239 | else if (scaled_width < scaled_height) |
240 | *pfit_control |= PFIT_ENABLE | |
240 | *pfit_control |= PFIT_ENABLE | |
241 | PFIT_SCALING_LETTER; |
241 | PFIT_SCALING_LETTER; |
242 | else if (adjusted_mode->crtc_hdisplay != pipe_config->pipe_src_w) |
242 | else if (adjusted_mode->crtc_hdisplay != pipe_config->pipe_src_w) |
243 | *pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO; |
243 | *pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO; |
244 | } |
244 | } |
245 | 245 | ||
246 | static void i9xx_scale_aspect(struct intel_crtc_state *pipe_config, |
246 | static void i9xx_scale_aspect(struct intel_crtc_state *pipe_config, |
247 | u32 *pfit_control, u32 *pfit_pgm_ratios, |
247 | u32 *pfit_control, u32 *pfit_pgm_ratios, |
248 | u32 *border) |
248 | u32 *border) |
249 | { |
249 | { |
250 | struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; |
250 | struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; |
251 | u32 scaled_width = adjusted_mode->crtc_hdisplay * |
251 | u32 scaled_width = adjusted_mode->crtc_hdisplay * |
252 | pipe_config->pipe_src_h; |
252 | pipe_config->pipe_src_h; |
253 | u32 scaled_height = pipe_config->pipe_src_w * |
253 | u32 scaled_height = pipe_config->pipe_src_w * |
254 | adjusted_mode->crtc_vdisplay; |
254 | adjusted_mode->crtc_vdisplay; |
255 | u32 bits; |
255 | u32 bits; |
256 | 256 | ||
257 | /* |
257 | /* |
258 | * For earlier chips we have to calculate the scaling |
258 | * For earlier chips we have to calculate the scaling |
259 | * ratio by hand and program it into the |
259 | * ratio by hand and program it into the |
260 | * PFIT_PGM_RATIO register |
260 | * PFIT_PGM_RATIO register |
261 | */ |
261 | */ |
262 | if (scaled_width > scaled_height) { /* pillar */ |
262 | if (scaled_width > scaled_height) { /* pillar */ |
263 | centre_horizontally(adjusted_mode, |
263 | centre_horizontally(adjusted_mode, |
264 | scaled_height / |
264 | scaled_height / |
265 | pipe_config->pipe_src_h); |
265 | pipe_config->pipe_src_h); |
266 | 266 | ||
267 | *border = LVDS_BORDER_ENABLE; |
267 | *border = LVDS_BORDER_ENABLE; |
268 | if (pipe_config->pipe_src_h != adjusted_mode->crtc_vdisplay) { |
268 | if (pipe_config->pipe_src_h != adjusted_mode->crtc_vdisplay) { |
269 | bits = panel_fitter_scaling(pipe_config->pipe_src_h, |
269 | bits = panel_fitter_scaling(pipe_config->pipe_src_h, |
270 | adjusted_mode->crtc_vdisplay); |
270 | adjusted_mode->crtc_vdisplay); |
271 | 271 | ||
272 | *pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT | |
272 | *pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT | |
273 | bits << PFIT_VERT_SCALE_SHIFT); |
273 | bits << PFIT_VERT_SCALE_SHIFT); |
274 | *pfit_control |= (PFIT_ENABLE | |
274 | *pfit_control |= (PFIT_ENABLE | |
275 | VERT_INTERP_BILINEAR | |
275 | VERT_INTERP_BILINEAR | |
276 | HORIZ_INTERP_BILINEAR); |
276 | HORIZ_INTERP_BILINEAR); |
277 | } |
277 | } |
278 | } else if (scaled_width < scaled_height) { /* letter */ |
278 | } else if (scaled_width < scaled_height) { /* letter */ |
279 | centre_vertically(adjusted_mode, |
279 | centre_vertically(adjusted_mode, |
280 | scaled_width / |
280 | scaled_width / |
281 | pipe_config->pipe_src_w); |
281 | pipe_config->pipe_src_w); |
282 | 282 | ||
283 | *border = LVDS_BORDER_ENABLE; |
283 | *border = LVDS_BORDER_ENABLE; |
284 | if (pipe_config->pipe_src_w != adjusted_mode->crtc_hdisplay) { |
284 | if (pipe_config->pipe_src_w != adjusted_mode->crtc_hdisplay) { |
285 | bits = panel_fitter_scaling(pipe_config->pipe_src_w, |
285 | bits = panel_fitter_scaling(pipe_config->pipe_src_w, |
286 | adjusted_mode->crtc_hdisplay); |
286 | adjusted_mode->crtc_hdisplay); |
287 | 287 | ||
288 | *pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT | |
288 | *pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT | |
289 | bits << PFIT_VERT_SCALE_SHIFT); |
289 | bits << PFIT_VERT_SCALE_SHIFT); |
290 | *pfit_control |= (PFIT_ENABLE | |
290 | *pfit_control |= (PFIT_ENABLE | |
291 | VERT_INTERP_BILINEAR | |
291 | VERT_INTERP_BILINEAR | |
292 | HORIZ_INTERP_BILINEAR); |
292 | HORIZ_INTERP_BILINEAR); |
293 | } |
293 | } |
294 | } else { |
294 | } else { |
295 | /* Aspects match, Let hw scale both directions */ |
295 | /* Aspects match, Let hw scale both directions */ |
296 | *pfit_control |= (PFIT_ENABLE | |
296 | *pfit_control |= (PFIT_ENABLE | |
297 | VERT_AUTO_SCALE | HORIZ_AUTO_SCALE | |
297 | VERT_AUTO_SCALE | HORIZ_AUTO_SCALE | |
298 | VERT_INTERP_BILINEAR | |
298 | VERT_INTERP_BILINEAR | |
299 | HORIZ_INTERP_BILINEAR); |
299 | HORIZ_INTERP_BILINEAR); |
300 | } |
300 | } |
301 | } |
301 | } |
302 | 302 | ||
303 | void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc, |
303 | void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc, |
304 | struct intel_crtc_state *pipe_config, |
304 | struct intel_crtc_state *pipe_config, |
305 | int fitting_mode) |
305 | int fitting_mode) |
306 | { |
306 | { |
307 | struct drm_device *dev = intel_crtc->base.dev; |
307 | struct drm_device *dev = intel_crtc->base.dev; |
308 | u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0; |
308 | u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0; |
309 | struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; |
309 | struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; |
310 | 310 | ||
311 | /* Native modes don't need fitting */ |
311 | /* Native modes don't need fitting */ |
312 | if (adjusted_mode->crtc_hdisplay == pipe_config->pipe_src_w && |
312 | if (adjusted_mode->crtc_hdisplay == pipe_config->pipe_src_w && |
313 | adjusted_mode->crtc_vdisplay == pipe_config->pipe_src_h) |
313 | adjusted_mode->crtc_vdisplay == pipe_config->pipe_src_h) |
314 | goto out; |
314 | goto out; |
315 | 315 | ||
316 | switch (fitting_mode) { |
316 | switch (fitting_mode) { |
317 | case DRM_MODE_SCALE_CENTER: |
317 | case DRM_MODE_SCALE_CENTER: |
318 | /* |
318 | /* |
319 | * For centered modes, we have to calculate border widths & |
319 | * For centered modes, we have to calculate border widths & |
320 | * heights and modify the values programmed into the CRTC. |
320 | * heights and modify the values programmed into the CRTC. |
321 | */ |
321 | */ |
322 | centre_horizontally(adjusted_mode, pipe_config->pipe_src_w); |
322 | centre_horizontally(adjusted_mode, pipe_config->pipe_src_w); |
323 | centre_vertically(adjusted_mode, pipe_config->pipe_src_h); |
323 | centre_vertically(adjusted_mode, pipe_config->pipe_src_h); |
324 | border = LVDS_BORDER_ENABLE; |
324 | border = LVDS_BORDER_ENABLE; |
325 | break; |
325 | break; |
326 | case DRM_MODE_SCALE_ASPECT: |
326 | case DRM_MODE_SCALE_ASPECT: |
327 | /* Scale but preserve the aspect ratio */ |
327 | /* Scale but preserve the aspect ratio */ |
328 | if (INTEL_INFO(dev)->gen >= 4) |
328 | if (INTEL_INFO(dev)->gen >= 4) |
329 | i965_scale_aspect(pipe_config, &pfit_control); |
329 | i965_scale_aspect(pipe_config, &pfit_control); |
330 | else |
330 | else |
331 | i9xx_scale_aspect(pipe_config, &pfit_control, |
331 | i9xx_scale_aspect(pipe_config, &pfit_control, |
332 | &pfit_pgm_ratios, &border); |
332 | &pfit_pgm_ratios, &border); |
333 | break; |
333 | break; |
334 | case DRM_MODE_SCALE_FULLSCREEN: |
334 | case DRM_MODE_SCALE_FULLSCREEN: |
335 | /* |
335 | /* |
336 | * Full scaling, even if it changes the aspect ratio. |
336 | * Full scaling, even if it changes the aspect ratio. |
337 | * Fortunately this is all done for us in hw. |
337 | * Fortunately this is all done for us in hw. |
338 | */ |
338 | */ |
339 | if (pipe_config->pipe_src_h != adjusted_mode->crtc_vdisplay || |
339 | if (pipe_config->pipe_src_h != adjusted_mode->crtc_vdisplay || |
340 | pipe_config->pipe_src_w != adjusted_mode->crtc_hdisplay) { |
340 | pipe_config->pipe_src_w != adjusted_mode->crtc_hdisplay) { |
341 | pfit_control |= PFIT_ENABLE; |
341 | pfit_control |= PFIT_ENABLE; |
342 | if (INTEL_INFO(dev)->gen >= 4) |
342 | if (INTEL_INFO(dev)->gen >= 4) |
343 | pfit_control |= PFIT_SCALING_AUTO; |
343 | pfit_control |= PFIT_SCALING_AUTO; |
344 | else |
344 | else |
345 | pfit_control |= (VERT_AUTO_SCALE | |
345 | pfit_control |= (VERT_AUTO_SCALE | |
346 | VERT_INTERP_BILINEAR | |
346 | VERT_INTERP_BILINEAR | |
347 | HORIZ_AUTO_SCALE | |
347 | HORIZ_AUTO_SCALE | |
348 | HORIZ_INTERP_BILINEAR); |
348 | HORIZ_INTERP_BILINEAR); |
349 | } |
349 | } |
350 | break; |
350 | break; |
351 | default: |
351 | default: |
352 | WARN(1, "bad panel fit mode: %d\n", fitting_mode); |
352 | WARN(1, "bad panel fit mode: %d\n", fitting_mode); |
353 | return; |
353 | return; |
354 | } |
354 | } |
355 | 355 | ||
356 | /* 965+ wants fuzzy fitting */ |
356 | /* 965+ wants fuzzy fitting */ |
357 | /* FIXME: handle multiple panels by failing gracefully */ |
357 | /* FIXME: handle multiple panels by failing gracefully */ |
358 | if (INTEL_INFO(dev)->gen >= 4) |
358 | if (INTEL_INFO(dev)->gen >= 4) |
359 | pfit_control |= ((intel_crtc->pipe << PFIT_PIPE_SHIFT) | |
359 | pfit_control |= ((intel_crtc->pipe << PFIT_PIPE_SHIFT) | |
360 | PFIT_FILTER_FUZZY); |
360 | PFIT_FILTER_FUZZY); |
361 | 361 | ||
362 | out: |
362 | out: |
363 | if ((pfit_control & PFIT_ENABLE) == 0) { |
363 | if ((pfit_control & PFIT_ENABLE) == 0) { |
364 | pfit_control = 0; |
364 | pfit_control = 0; |
365 | pfit_pgm_ratios = 0; |
365 | pfit_pgm_ratios = 0; |
366 | } |
366 | } |
367 | 367 | ||
368 | /* Make sure pre-965 set dither correctly for 18bpp panels. */ |
368 | /* Make sure pre-965 set dither correctly for 18bpp panels. */ |
369 | if (INTEL_INFO(dev)->gen < 4 && pipe_config->pipe_bpp == 18) |
369 | if (INTEL_INFO(dev)->gen < 4 && pipe_config->pipe_bpp == 18) |
370 | pfit_control |= PANEL_8TO6_DITHER_ENABLE; |
370 | pfit_control |= PANEL_8TO6_DITHER_ENABLE; |
371 | 371 | ||
372 | pipe_config->gmch_pfit.control = pfit_control; |
372 | pipe_config->gmch_pfit.control = pfit_control; |
373 | pipe_config->gmch_pfit.pgm_ratios = pfit_pgm_ratios; |
373 | pipe_config->gmch_pfit.pgm_ratios = pfit_pgm_ratios; |
374 | pipe_config->gmch_pfit.lvds_border_bits = border; |
374 | pipe_config->gmch_pfit.lvds_border_bits = border; |
375 | } |
375 | } |
376 | 376 | ||
377 | enum drm_connector_status |
377 | enum drm_connector_status |
378 | intel_panel_detect(struct drm_device *dev) |
378 | intel_panel_detect(struct drm_device *dev) |
379 | { |
379 | { |
380 | struct drm_i915_private *dev_priv = dev->dev_private; |
380 | struct drm_i915_private *dev_priv = dev->dev_private; |
381 | 381 | ||
382 | /* Assume that the BIOS does not lie through the OpRegion... */ |
382 | /* Assume that the BIOS does not lie through the OpRegion... */ |
383 | if (!i915.panel_ignore_lid && dev_priv->opregion.lid_state) { |
383 | if (!i915.panel_ignore_lid && dev_priv->opregion.lid_state) { |
384 | return *dev_priv->opregion.lid_state & 0x1 ? |
384 | return *dev_priv->opregion.lid_state & 0x1 ? |
385 | connector_status_connected : |
385 | connector_status_connected : |
386 | connector_status_disconnected; |
386 | connector_status_disconnected; |
387 | } |
387 | } |
388 | 388 | ||
389 | switch (i915.panel_ignore_lid) { |
389 | switch (i915.panel_ignore_lid) { |
390 | case -2: |
390 | case -2: |
391 | return connector_status_connected; |
391 | return connector_status_connected; |
392 | case -1: |
392 | case -1: |
393 | return connector_status_disconnected; |
393 | return connector_status_disconnected; |
394 | default: |
394 | default: |
395 | return connector_status_unknown; |
395 | return connector_status_unknown; |
396 | } |
396 | } |
397 | } |
397 | } |
398 | 398 | ||
399 | /** |
399 | /** |
400 | * scale - scale values from one range to another |
400 | * scale - scale values from one range to another |
401 | * |
401 | * |
402 | * @source_val: value in range [@source_min..@source_max] |
402 | * @source_val: value in range [@source_min..@source_max] |
403 | * |
403 | * |
404 | * Return @source_val in range [@source_min..@source_max] scaled to range |
404 | * Return @source_val in range [@source_min..@source_max] scaled to range |
405 | * [@target_min..@target_max]. |
405 | * [@target_min..@target_max]. |
406 | */ |
406 | */ |
407 | static uint32_t scale(uint32_t source_val, |
407 | static uint32_t scale(uint32_t source_val, |
408 | uint32_t source_min, uint32_t source_max, |
408 | uint32_t source_min, uint32_t source_max, |
409 | uint32_t target_min, uint32_t target_max) |
409 | uint32_t target_min, uint32_t target_max) |
410 | { |
410 | { |
411 | uint64_t target_val; |
411 | uint64_t target_val; |
412 | 412 | ||
413 | WARN_ON(source_min > source_max); |
413 | WARN_ON(source_min > source_max); |
414 | WARN_ON(target_min > target_max); |
414 | WARN_ON(target_min > target_max); |
415 | 415 | ||
416 | /* defensive */ |
416 | /* defensive */ |
417 | source_val = clamp(source_val, source_min, source_max); |
417 | source_val = clamp(source_val, source_min, source_max); |
418 | 418 | ||
419 | /* avoid overflows */ |
419 | /* avoid overflows */ |
420 | target_val = DIV_ROUND_CLOSEST_ULL((uint64_t)(source_val - source_min) * |
420 | target_val = DIV_ROUND_CLOSEST_ULL((uint64_t)(source_val - source_min) * |
421 | (target_max - target_min), source_max - source_min); |
421 | (target_max - target_min), source_max - source_min); |
422 | target_val += target_min; |
422 | target_val += target_min; |
423 | 423 | ||
424 | return target_val; |
424 | return target_val; |
425 | } |
425 | } |
426 | 426 | ||
427 | /* Scale user_level in range [0..user_max] to [hw_min..hw_max]. */ |
427 | /* Scale user_level in range [0..user_max] to [hw_min..hw_max]. */ |
428 | static inline u32 scale_user_to_hw(struct intel_connector *connector, |
428 | static inline u32 scale_user_to_hw(struct intel_connector *connector, |
429 | u32 user_level, u32 user_max) |
429 | u32 user_level, u32 user_max) |
430 | { |
430 | { |
431 | struct intel_panel *panel = &connector->panel; |
431 | struct intel_panel *panel = &connector->panel; |
432 | 432 | ||
433 | return scale(user_level, 0, user_max, |
433 | return scale(user_level, 0, user_max, |
434 | panel->backlight.min, panel->backlight.max); |
434 | panel->backlight.min, panel->backlight.max); |
435 | } |
435 | } |
436 | 436 | ||
437 | /* Scale user_level in range [0..user_max] to [0..hw_max], clamping the result |
437 | /* Scale user_level in range [0..user_max] to [0..hw_max], clamping the result |
438 | * to [hw_min..hw_max]. */ |
438 | * to [hw_min..hw_max]. */ |
439 | static inline u32 clamp_user_to_hw(struct intel_connector *connector, |
439 | static inline u32 clamp_user_to_hw(struct intel_connector *connector, |
440 | u32 user_level, u32 user_max) |
440 | u32 user_level, u32 user_max) |
441 | { |
441 | { |
442 | struct intel_panel *panel = &connector->panel; |
442 | struct intel_panel *panel = &connector->panel; |
443 | u32 hw_level; |
443 | u32 hw_level; |
444 | 444 | ||
445 | hw_level = scale(user_level, 0, user_max, 0, panel->backlight.max); |
445 | hw_level = scale(user_level, 0, user_max, 0, panel->backlight.max); |
446 | hw_level = clamp(hw_level, panel->backlight.min, panel->backlight.max); |
446 | hw_level = clamp(hw_level, panel->backlight.min, panel->backlight.max); |
447 | 447 | ||
448 | return hw_level; |
448 | return hw_level; |
449 | } |
449 | } |
450 | 450 | ||
451 | /* Scale hw_level in range [hw_min..hw_max] to [0..user_max]. */ |
451 | /* Scale hw_level in range [hw_min..hw_max] to [0..user_max]. */ |
452 | static inline u32 scale_hw_to_user(struct intel_connector *connector, |
452 | static inline u32 scale_hw_to_user(struct intel_connector *connector, |
453 | u32 hw_level, u32 user_max) |
453 | u32 hw_level, u32 user_max) |
454 | { |
454 | { |
455 | struct intel_panel *panel = &connector->panel; |
455 | struct intel_panel *panel = &connector->panel; |
456 | 456 | ||
457 | return scale(hw_level, panel->backlight.min, panel->backlight.max, |
457 | return scale(hw_level, panel->backlight.min, panel->backlight.max, |
458 | 0, user_max); |
458 | 0, user_max); |
459 | } |
459 | } |
460 | 460 | ||
461 | static u32 intel_panel_compute_brightness(struct intel_connector *connector, |
461 | static u32 intel_panel_compute_brightness(struct intel_connector *connector, |
462 | u32 val) |
462 | u32 val) |
463 | { |
463 | { |
464 | struct drm_device *dev = connector->base.dev; |
- | |
465 | struct drm_i915_private *dev_priv = dev->dev_private; |
464 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
466 | struct intel_panel *panel = &connector->panel; |
465 | struct intel_panel *panel = &connector->panel; |
467 | 466 | ||
468 | WARN_ON(panel->backlight.max == 0); |
467 | WARN_ON(panel->backlight.max == 0); |
469 | 468 | ||
470 | if (i915.invert_brightness < 0) |
469 | if (i915.invert_brightness < 0) |
471 | return val; |
470 | return val; |
472 | 471 | ||
473 | if (i915.invert_brightness > 0 || |
472 | if (i915.invert_brightness > 0 || |
474 | dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) { |
473 | dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) { |
475 | return panel->backlight.max - val; |
474 | return panel->backlight.max - val; |
476 | } |
475 | } |
477 | 476 | ||
478 | return val; |
477 | return val; |
479 | } |
478 | } |
480 | 479 | ||
481 | static u32 lpt_get_backlight(struct intel_connector *connector) |
480 | static u32 lpt_get_backlight(struct intel_connector *connector) |
482 | { |
481 | { |
483 | struct drm_device *dev = connector->base.dev; |
- | |
484 | struct drm_i915_private *dev_priv = dev->dev_private; |
482 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
485 | 483 | ||
486 | return I915_READ(BLC_PWM_PCH_CTL2) & BACKLIGHT_DUTY_CYCLE_MASK; |
484 | return I915_READ(BLC_PWM_PCH_CTL2) & BACKLIGHT_DUTY_CYCLE_MASK; |
487 | } |
485 | } |
488 | 486 | ||
489 | static u32 pch_get_backlight(struct intel_connector *connector) |
487 | static u32 pch_get_backlight(struct intel_connector *connector) |
490 | { |
488 | { |
491 | struct drm_device *dev = connector->base.dev; |
- | |
492 | struct drm_i915_private *dev_priv = dev->dev_private; |
489 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
493 | 490 | ||
494 | return I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; |
491 | return I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; |
495 | } |
492 | } |
496 | 493 | ||
497 | static u32 i9xx_get_backlight(struct intel_connector *connector) |
494 | static u32 i9xx_get_backlight(struct intel_connector *connector) |
498 | { |
495 | { |
499 | struct drm_device *dev = connector->base.dev; |
- | |
500 | struct drm_i915_private *dev_priv = dev->dev_private; |
496 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
501 | struct intel_panel *panel = &connector->panel; |
497 | struct intel_panel *panel = &connector->panel; |
502 | u32 val; |
498 | u32 val; |
503 | 499 | ||
504 | val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; |
500 | val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; |
505 | if (INTEL_INFO(dev)->gen < 4) |
501 | if (INTEL_INFO(dev_priv)->gen < 4) |
506 | val >>= 1; |
502 | val >>= 1; |
507 | 503 | ||
508 | if (panel->backlight.combination_mode) { |
504 | if (panel->backlight.combination_mode) { |
509 | u8 lbpc; |
505 | u8 lbpc; |
510 | 506 | ||
511 | pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc); |
507 | pci_read_config_byte(dev_priv->dev->pdev, PCI_LBPC, &lbpc); |
512 | val *= lbpc; |
508 | val *= lbpc; |
513 | } |
509 | } |
514 | 510 | ||
515 | return val; |
511 | return val; |
516 | } |
512 | } |
517 | 513 | ||
518 | static u32 _vlv_get_backlight(struct drm_device *dev, enum pipe pipe) |
514 | static u32 _vlv_get_backlight(struct drm_i915_private *dev_priv, enum pipe pipe) |
519 | { |
- | |
520 | struct drm_i915_private *dev_priv = dev->dev_private; |
- | |
521 | 515 | { |
|
522 | if (WARN_ON(pipe != PIPE_A && pipe != PIPE_B)) |
516 | if (WARN_ON(pipe != PIPE_A && pipe != PIPE_B)) |
523 | return 0; |
517 | return 0; |
524 | 518 | ||
525 | return I915_READ(VLV_BLC_PWM_CTL(pipe)) & BACKLIGHT_DUTY_CYCLE_MASK; |
519 | return I915_READ(VLV_BLC_PWM_CTL(pipe)) & BACKLIGHT_DUTY_CYCLE_MASK; |
526 | } |
520 | } |
527 | 521 | ||
528 | static u32 vlv_get_backlight(struct intel_connector *connector) |
522 | static u32 vlv_get_backlight(struct intel_connector *connector) |
529 | { |
523 | { |
530 | struct drm_device *dev = connector->base.dev; |
524 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
531 | enum pipe pipe = intel_get_pipe_from_connector(connector); |
525 | enum pipe pipe = intel_get_pipe_from_connector(connector); |
532 | 526 | ||
533 | return _vlv_get_backlight(dev, pipe); |
527 | return _vlv_get_backlight(dev_priv, pipe); |
534 | } |
528 | } |
535 | 529 | ||
536 | static u32 bxt_get_backlight(struct intel_connector *connector) |
530 | static u32 bxt_get_backlight(struct intel_connector *connector) |
537 | { |
531 | { |
538 | struct drm_device *dev = connector->base.dev; |
532 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
539 | struct intel_panel *panel = &connector->panel; |
533 | struct intel_panel *panel = &connector->panel; |
540 | struct drm_i915_private *dev_priv = dev->dev_private; |
- | |
541 | 534 | ||
542 | return I915_READ(BXT_BLC_PWM_DUTY(panel->backlight.controller)); |
535 | return I915_READ(BXT_BLC_PWM_DUTY(panel->backlight.controller)); |
543 | } |
536 | } |
544 | 537 | ||
545 | static u32 pwm_get_backlight(struct intel_connector *connector) |
538 | static u32 pwm_get_backlight(struct intel_connector *connector) |
546 | { |
539 | { |
547 | struct intel_panel *panel = &connector->panel; |
540 | struct intel_panel *panel = &connector->panel; |
548 | int duty_ns; |
541 | int duty_ns; |
549 | 542 | ||
550 | duty_ns = pwm_get_duty_cycle(panel->backlight.pwm); |
543 | duty_ns = pwm_get_duty_cycle(panel->backlight.pwm); |
551 | return DIV_ROUND_UP(duty_ns * 100, CRC_PMIC_PWM_PERIOD_NS); |
544 | return DIV_ROUND_UP(duty_ns * 100, CRC_PMIC_PWM_PERIOD_NS); |
552 | } |
545 | } |
553 | 546 | ||
554 | static u32 intel_panel_get_backlight(struct intel_connector *connector) |
547 | static u32 intel_panel_get_backlight(struct intel_connector *connector) |
555 | { |
548 | { |
556 | struct drm_device *dev = connector->base.dev; |
- | |
557 | struct drm_i915_private *dev_priv = dev->dev_private; |
549 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
558 | struct intel_panel *panel = &connector->panel; |
550 | struct intel_panel *panel = &connector->panel; |
559 | u32 val = 0; |
551 | u32 val = 0; |
560 | 552 | ||
561 | mutex_lock(&dev_priv->backlight_lock); |
553 | mutex_lock(&dev_priv->backlight_lock); |
562 | 554 | ||
563 | if (panel->backlight.enabled) { |
555 | if (panel->backlight.enabled) { |
564 | val = panel->backlight.get(connector); |
556 | val = panel->backlight.get(connector); |
565 | val = intel_panel_compute_brightness(connector, val); |
557 | val = intel_panel_compute_brightness(connector, val); |
566 | } |
558 | } |
567 | 559 | ||
568 | mutex_unlock(&dev_priv->backlight_lock); |
560 | mutex_unlock(&dev_priv->backlight_lock); |
569 | 561 | ||
570 | DRM_DEBUG_DRIVER("get backlight PWM = %d\n", val); |
562 | DRM_DEBUG_DRIVER("get backlight PWM = %d\n", val); |
571 | return val; |
563 | return val; |
572 | } |
564 | } |
573 | 565 | ||
574 | static void lpt_set_backlight(struct intel_connector *connector, u32 level) |
566 | static void lpt_set_backlight(struct intel_connector *connector, u32 level) |
575 | { |
567 | { |
576 | struct drm_device *dev = connector->base.dev; |
- | |
577 | struct drm_i915_private *dev_priv = dev->dev_private; |
568 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
578 | u32 val = I915_READ(BLC_PWM_PCH_CTL2) & ~BACKLIGHT_DUTY_CYCLE_MASK; |
569 | u32 val = I915_READ(BLC_PWM_PCH_CTL2) & ~BACKLIGHT_DUTY_CYCLE_MASK; |
579 | I915_WRITE(BLC_PWM_PCH_CTL2, val | level); |
570 | I915_WRITE(BLC_PWM_PCH_CTL2, val | level); |
580 | } |
571 | } |
581 | 572 | ||
582 | static void pch_set_backlight(struct intel_connector *connector, u32 level) |
573 | static void pch_set_backlight(struct intel_connector *connector, u32 level) |
583 | { |
574 | { |
584 | struct drm_device *dev = connector->base.dev; |
- | |
585 | struct drm_i915_private *dev_priv = dev->dev_private; |
575 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
586 | u32 tmp; |
576 | u32 tmp; |
587 | 577 | ||
588 | tmp = I915_READ(BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK; |
578 | tmp = I915_READ(BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK; |
589 | I915_WRITE(BLC_PWM_CPU_CTL, tmp | level); |
579 | I915_WRITE(BLC_PWM_CPU_CTL, tmp | level); |
590 | } |
580 | } |
591 | 581 | ||
592 | static void i9xx_set_backlight(struct intel_connector *connector, u32 level) |
582 | static void i9xx_set_backlight(struct intel_connector *connector, u32 level) |
593 | { |
583 | { |
594 | struct drm_device *dev = connector->base.dev; |
- | |
595 | struct drm_i915_private *dev_priv = dev->dev_private; |
584 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
596 | struct intel_panel *panel = &connector->panel; |
585 | struct intel_panel *panel = &connector->panel; |
597 | u32 tmp, mask; |
586 | u32 tmp, mask; |
598 | 587 | ||
599 | WARN_ON(panel->backlight.max == 0); |
588 | WARN_ON(panel->backlight.max == 0); |
600 | 589 | ||
601 | if (panel->backlight.combination_mode) { |
590 | if (panel->backlight.combination_mode) { |
602 | u8 lbpc; |
591 | u8 lbpc; |
603 | 592 | ||
604 | lbpc = level * 0xfe / panel->backlight.max + 1; |
593 | lbpc = level * 0xfe / panel->backlight.max + 1; |
605 | level /= lbpc; |
594 | level /= lbpc; |
606 | pci_write_config_byte(dev->pdev, PCI_LBPC, lbpc); |
595 | pci_write_config_byte(dev_priv->dev->pdev, PCI_LBPC, lbpc); |
607 | } |
596 | } |
608 | 597 | ||
609 | if (IS_GEN4(dev)) { |
598 | if (IS_GEN4(dev_priv)) { |
610 | mask = BACKLIGHT_DUTY_CYCLE_MASK; |
599 | mask = BACKLIGHT_DUTY_CYCLE_MASK; |
611 | } else { |
600 | } else { |
612 | level <<= 1; |
601 | level <<= 1; |
613 | mask = BACKLIGHT_DUTY_CYCLE_MASK_PNV; |
602 | mask = BACKLIGHT_DUTY_CYCLE_MASK_PNV; |
614 | } |
603 | } |
615 | 604 | ||
616 | tmp = I915_READ(BLC_PWM_CTL) & ~mask; |
605 | tmp = I915_READ(BLC_PWM_CTL) & ~mask; |
617 | I915_WRITE(BLC_PWM_CTL, tmp | level); |
606 | I915_WRITE(BLC_PWM_CTL, tmp | level); |
618 | } |
607 | } |
619 | 608 | ||
620 | static void vlv_set_backlight(struct intel_connector *connector, u32 level) |
609 | static void vlv_set_backlight(struct intel_connector *connector, u32 level) |
621 | { |
610 | { |
622 | struct drm_device *dev = connector->base.dev; |
- | |
623 | struct drm_i915_private *dev_priv = dev->dev_private; |
611 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
624 | enum pipe pipe = intel_get_pipe_from_connector(connector); |
612 | enum pipe pipe = intel_get_pipe_from_connector(connector); |
625 | u32 tmp; |
613 | u32 tmp; |
626 | 614 | ||
627 | if (WARN_ON(pipe != PIPE_A && pipe != PIPE_B)) |
615 | if (WARN_ON(pipe != PIPE_A && pipe != PIPE_B)) |
628 | return; |
616 | return; |
629 | 617 | ||
630 | tmp = I915_READ(VLV_BLC_PWM_CTL(pipe)) & ~BACKLIGHT_DUTY_CYCLE_MASK; |
618 | tmp = I915_READ(VLV_BLC_PWM_CTL(pipe)) & ~BACKLIGHT_DUTY_CYCLE_MASK; |
631 | I915_WRITE(VLV_BLC_PWM_CTL(pipe), tmp | level); |
619 | I915_WRITE(VLV_BLC_PWM_CTL(pipe), tmp | level); |
632 | } |
620 | } |
633 | 621 | ||
634 | static void bxt_set_backlight(struct intel_connector *connector, u32 level) |
622 | static void bxt_set_backlight(struct intel_connector *connector, u32 level) |
635 | { |
623 | { |
636 | struct drm_device *dev = connector->base.dev; |
- | |
637 | struct drm_i915_private *dev_priv = dev->dev_private; |
624 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
638 | struct intel_panel *panel = &connector->panel; |
625 | struct intel_panel *panel = &connector->panel; |
639 | 626 | ||
640 | I915_WRITE(BXT_BLC_PWM_DUTY(panel->backlight.controller), level); |
627 | I915_WRITE(BXT_BLC_PWM_DUTY(panel->backlight.controller), level); |
641 | } |
628 | } |
642 | 629 | ||
643 | static void pwm_set_backlight(struct intel_connector *connector, u32 level) |
630 | static void pwm_set_backlight(struct intel_connector *connector, u32 level) |
644 | { |
631 | { |
645 | struct intel_panel *panel = &connector->panel; |
632 | struct intel_panel *panel = &connector->panel; |
646 | int duty_ns = DIV_ROUND_UP(level * CRC_PMIC_PWM_PERIOD_NS, 100); |
633 | int duty_ns = DIV_ROUND_UP(level * CRC_PMIC_PWM_PERIOD_NS, 100); |
647 | 634 | ||
648 | pwm_config(panel->backlight.pwm, duty_ns, CRC_PMIC_PWM_PERIOD_NS); |
635 | pwm_config(panel->backlight.pwm, duty_ns, CRC_PMIC_PWM_PERIOD_NS); |
649 | } |
636 | } |
650 | 637 | ||
651 | static void |
638 | static void |
652 | intel_panel_actually_set_backlight(struct intel_connector *connector, u32 level) |
639 | intel_panel_actually_set_backlight(struct intel_connector *connector, u32 level) |
653 | { |
640 | { |
654 | struct intel_panel *panel = &connector->panel; |
641 | struct intel_panel *panel = &connector->panel; |
655 | 642 | ||
656 | DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level); |
643 | DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level); |
657 | 644 | ||
658 | level = intel_panel_compute_brightness(connector, level); |
645 | level = intel_panel_compute_brightness(connector, level); |
659 | panel->backlight.set(connector, level); |
646 | panel->backlight.set(connector, level); |
660 | } |
647 | } |
661 | 648 | ||
662 | /* set backlight brightness to level in range [0..max], scaling wrt hw min */ |
649 | /* set backlight brightness to level in range [0..max], scaling wrt hw min */ |
663 | static void intel_panel_set_backlight(struct intel_connector *connector, |
650 | static void intel_panel_set_backlight(struct intel_connector *connector, |
664 | u32 user_level, u32 user_max) |
651 | u32 user_level, u32 user_max) |
665 | { |
652 | { |
666 | struct drm_device *dev = connector->base.dev; |
- | |
667 | struct drm_i915_private *dev_priv = dev->dev_private; |
653 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
668 | struct intel_panel *panel = &connector->panel; |
654 | struct intel_panel *panel = &connector->panel; |
669 | u32 hw_level; |
655 | u32 hw_level; |
670 | 656 | ||
671 | if (!panel->backlight.present) |
657 | if (!panel->backlight.present) |
672 | return; |
658 | return; |
673 | 659 | ||
674 | mutex_lock(&dev_priv->backlight_lock); |
660 | mutex_lock(&dev_priv->backlight_lock); |
675 | 661 | ||
676 | WARN_ON(panel->backlight.max == 0); |
662 | WARN_ON(panel->backlight.max == 0); |
677 | 663 | ||
678 | hw_level = scale_user_to_hw(connector, user_level, user_max); |
664 | hw_level = scale_user_to_hw(connector, user_level, user_max); |
679 | panel->backlight.level = hw_level; |
665 | panel->backlight.level = hw_level; |
680 | 666 | ||
681 | if (panel->backlight.enabled) |
667 | if (panel->backlight.enabled) |
682 | intel_panel_actually_set_backlight(connector, hw_level); |
668 | intel_panel_actually_set_backlight(connector, hw_level); |
683 | 669 | ||
684 | mutex_unlock(&dev_priv->backlight_lock); |
670 | mutex_unlock(&dev_priv->backlight_lock); |
685 | } |
671 | } |
686 | 672 | ||
687 | /* set backlight brightness to level in range [0..max], assuming hw min is |
673 | /* set backlight brightness to level in range [0..max], assuming hw min is |
688 | * respected. |
674 | * respected. |
689 | */ |
675 | */ |
690 | void intel_panel_set_backlight_acpi(struct intel_connector *connector, |
676 | void intel_panel_set_backlight_acpi(struct intel_connector *connector, |
691 | u32 user_level, u32 user_max) |
677 | u32 user_level, u32 user_max) |
692 | { |
678 | { |
693 | struct drm_device *dev = connector->base.dev; |
- | |
694 | struct drm_i915_private *dev_priv = dev->dev_private; |
679 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
695 | struct intel_panel *panel = &connector->panel; |
680 | struct intel_panel *panel = &connector->panel; |
696 | enum pipe pipe = intel_get_pipe_from_connector(connector); |
681 | enum pipe pipe = intel_get_pipe_from_connector(connector); |
697 | u32 hw_level; |
682 | u32 hw_level; |
698 | 683 | ||
699 | /* |
684 | /* |
700 | * INVALID_PIPE may occur during driver init because |
685 | * INVALID_PIPE may occur during driver init because |
701 | * connection_mutex isn't held across the entire backlight |
686 | * connection_mutex isn't held across the entire backlight |
702 | * setup + modeset readout, and the BIOS can issue the |
687 | * setup + modeset readout, and the BIOS can issue the |
703 | * requests at any time. |
688 | * requests at any time. |
704 | */ |
689 | */ |
705 | if (!panel->backlight.present || pipe == INVALID_PIPE) |
690 | if (!panel->backlight.present || pipe == INVALID_PIPE) |
706 | return; |
691 | return; |
707 | 692 | ||
708 | mutex_lock(&dev_priv->backlight_lock); |
693 | mutex_lock(&dev_priv->backlight_lock); |
709 | 694 | ||
710 | WARN_ON(panel->backlight.max == 0); |
695 | WARN_ON(panel->backlight.max == 0); |
711 | 696 | ||
712 | hw_level = clamp_user_to_hw(connector, user_level, user_max); |
697 | hw_level = clamp_user_to_hw(connector, user_level, user_max); |
713 | panel->backlight.level = hw_level; |
698 | panel->backlight.level = hw_level; |
714 | 699 | ||
715 | 700 | ||
716 | if (panel->backlight.enabled) |
701 | if (panel->backlight.enabled) |
717 | intel_panel_actually_set_backlight(connector, hw_level); |
702 | intel_panel_actually_set_backlight(connector, hw_level); |
718 | 703 | ||
719 | mutex_unlock(&dev_priv->backlight_lock); |
704 | mutex_unlock(&dev_priv->backlight_lock); |
720 | } |
705 | } |
721 | 706 | ||
722 | static void lpt_disable_backlight(struct intel_connector *connector) |
707 | static void lpt_disable_backlight(struct intel_connector *connector) |
723 | { |
708 | { |
724 | struct drm_device *dev = connector->base.dev; |
- | |
725 | struct drm_i915_private *dev_priv = dev->dev_private; |
709 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
726 | u32 tmp; |
710 | u32 tmp; |
727 | 711 | ||
728 | intel_panel_actually_set_backlight(connector, 0); |
712 | intel_panel_actually_set_backlight(connector, 0); |
729 | 713 | ||
730 | /* |
714 | /* |
731 | * Although we don't support or enable CPU PWM with LPT/SPT based |
715 | * Although we don't support or enable CPU PWM with LPT/SPT based |
732 | * systems, it may have been enabled prior to loading the |
716 | * systems, it may have been enabled prior to loading the |
733 | * driver. Disable to avoid warnings on LCPLL disable. |
717 | * driver. Disable to avoid warnings on LCPLL disable. |
734 | * |
718 | * |
735 | * This needs rework if we need to add support for CPU PWM on PCH split |
719 | * This needs rework if we need to add support for CPU PWM on PCH split |
736 | * platforms. |
720 | * platforms. |
737 | */ |
721 | */ |
738 | tmp = I915_READ(BLC_PWM_CPU_CTL2); |
722 | tmp = I915_READ(BLC_PWM_CPU_CTL2); |
739 | if (tmp & BLM_PWM_ENABLE) { |
723 | if (tmp & BLM_PWM_ENABLE) { |
740 | DRM_DEBUG_KMS("cpu backlight was enabled, disabling\n"); |
724 | DRM_DEBUG_KMS("cpu backlight was enabled, disabling\n"); |
741 | I915_WRITE(BLC_PWM_CPU_CTL2, tmp & ~BLM_PWM_ENABLE); |
725 | I915_WRITE(BLC_PWM_CPU_CTL2, tmp & ~BLM_PWM_ENABLE); |
742 | } |
726 | } |
743 | 727 | ||
744 | tmp = I915_READ(BLC_PWM_PCH_CTL1); |
728 | tmp = I915_READ(BLC_PWM_PCH_CTL1); |
745 | I915_WRITE(BLC_PWM_PCH_CTL1, tmp & ~BLM_PCH_PWM_ENABLE); |
729 | I915_WRITE(BLC_PWM_PCH_CTL1, tmp & ~BLM_PCH_PWM_ENABLE); |
746 | } |
730 | } |
747 | 731 | ||
748 | static void pch_disable_backlight(struct intel_connector *connector) |
732 | static void pch_disable_backlight(struct intel_connector *connector) |
749 | { |
733 | { |
750 | struct drm_device *dev = connector->base.dev; |
- | |
751 | struct drm_i915_private *dev_priv = dev->dev_private; |
734 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
752 | u32 tmp; |
735 | u32 tmp; |
753 | 736 | ||
754 | intel_panel_actually_set_backlight(connector, 0); |
737 | intel_panel_actually_set_backlight(connector, 0); |
755 | 738 | ||
756 | tmp = I915_READ(BLC_PWM_CPU_CTL2); |
739 | tmp = I915_READ(BLC_PWM_CPU_CTL2); |
757 | I915_WRITE(BLC_PWM_CPU_CTL2, tmp & ~BLM_PWM_ENABLE); |
740 | I915_WRITE(BLC_PWM_CPU_CTL2, tmp & ~BLM_PWM_ENABLE); |
758 | 741 | ||
759 | tmp = I915_READ(BLC_PWM_PCH_CTL1); |
742 | tmp = I915_READ(BLC_PWM_PCH_CTL1); |
760 | I915_WRITE(BLC_PWM_PCH_CTL1, tmp & ~BLM_PCH_PWM_ENABLE); |
743 | I915_WRITE(BLC_PWM_PCH_CTL1, tmp & ~BLM_PCH_PWM_ENABLE); |
761 | } |
744 | } |
762 | 745 | ||
763 | static void i9xx_disable_backlight(struct intel_connector *connector) |
746 | static void i9xx_disable_backlight(struct intel_connector *connector) |
764 | { |
747 | { |
765 | intel_panel_actually_set_backlight(connector, 0); |
748 | intel_panel_actually_set_backlight(connector, 0); |
766 | } |
749 | } |
767 | 750 | ||
768 | static void i965_disable_backlight(struct intel_connector *connector) |
751 | static void i965_disable_backlight(struct intel_connector *connector) |
769 | { |
752 | { |
770 | struct drm_device *dev = connector->base.dev; |
- | |
771 | struct drm_i915_private *dev_priv = dev->dev_private; |
753 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
772 | u32 tmp; |
754 | u32 tmp; |
773 | 755 | ||
774 | intel_panel_actually_set_backlight(connector, 0); |
756 | intel_panel_actually_set_backlight(connector, 0); |
775 | 757 | ||
776 | tmp = I915_READ(BLC_PWM_CTL2); |
758 | tmp = I915_READ(BLC_PWM_CTL2); |
777 | I915_WRITE(BLC_PWM_CTL2, tmp & ~BLM_PWM_ENABLE); |
759 | I915_WRITE(BLC_PWM_CTL2, tmp & ~BLM_PWM_ENABLE); |
778 | } |
760 | } |
779 | 761 | ||
780 | static void vlv_disable_backlight(struct intel_connector *connector) |
762 | static void vlv_disable_backlight(struct intel_connector *connector) |
781 | { |
763 | { |
782 | struct drm_device *dev = connector->base.dev; |
- | |
783 | struct drm_i915_private *dev_priv = dev->dev_private; |
764 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
784 | enum pipe pipe = intel_get_pipe_from_connector(connector); |
765 | enum pipe pipe = intel_get_pipe_from_connector(connector); |
785 | u32 tmp; |
766 | u32 tmp; |
786 | 767 | ||
787 | if (WARN_ON(pipe != PIPE_A && pipe != PIPE_B)) |
768 | if (WARN_ON(pipe != PIPE_A && pipe != PIPE_B)) |
788 | return; |
769 | return; |
789 | 770 | ||
790 | intel_panel_actually_set_backlight(connector, 0); |
771 | intel_panel_actually_set_backlight(connector, 0); |
791 | 772 | ||
792 | tmp = I915_READ(VLV_BLC_PWM_CTL2(pipe)); |
773 | tmp = I915_READ(VLV_BLC_PWM_CTL2(pipe)); |
793 | I915_WRITE(VLV_BLC_PWM_CTL2(pipe), tmp & ~BLM_PWM_ENABLE); |
774 | I915_WRITE(VLV_BLC_PWM_CTL2(pipe), tmp & ~BLM_PWM_ENABLE); |
794 | } |
775 | } |
795 | 776 | ||
796 | static void bxt_disable_backlight(struct intel_connector *connector) |
777 | static void bxt_disable_backlight(struct intel_connector *connector) |
797 | { |
778 | { |
798 | struct drm_device *dev = connector->base.dev; |
- | |
799 | struct drm_i915_private *dev_priv = dev->dev_private; |
779 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
800 | struct intel_panel *panel = &connector->panel; |
780 | struct intel_panel *panel = &connector->panel; |
801 | u32 tmp, val; |
781 | u32 tmp, val; |
802 | 782 | ||
803 | intel_panel_actually_set_backlight(connector, 0); |
783 | intel_panel_actually_set_backlight(connector, 0); |
804 | 784 | ||
805 | tmp = I915_READ(BXT_BLC_PWM_CTL(panel->backlight.controller)); |
785 | tmp = I915_READ(BXT_BLC_PWM_CTL(panel->backlight.controller)); |
806 | I915_WRITE(BXT_BLC_PWM_CTL(panel->backlight.controller), |
786 | I915_WRITE(BXT_BLC_PWM_CTL(panel->backlight.controller), |
807 | tmp & ~BXT_BLC_PWM_ENABLE); |
787 | tmp & ~BXT_BLC_PWM_ENABLE); |
808 | 788 | ||
809 | if (panel->backlight.controller == 1) { |
789 | if (panel->backlight.controller == 1) { |
810 | val = I915_READ(UTIL_PIN_CTL); |
790 | val = I915_READ(UTIL_PIN_CTL); |
811 | val &= ~UTIL_PIN_ENABLE; |
791 | val &= ~UTIL_PIN_ENABLE; |
812 | I915_WRITE(UTIL_PIN_CTL, val); |
792 | I915_WRITE(UTIL_PIN_CTL, val); |
813 | } |
793 | } |
814 | } |
794 | } |
815 | 795 | ||
816 | static void pwm_disable_backlight(struct intel_connector *connector) |
796 | static void pwm_disable_backlight(struct intel_connector *connector) |
817 | { |
797 | { |
818 | struct intel_panel *panel = &connector->panel; |
798 | struct intel_panel *panel = &connector->panel; |
819 | 799 | ||
820 | /* Disable the backlight */ |
800 | /* Disable the backlight */ |
821 | pwm_config(panel->backlight.pwm, 0, CRC_PMIC_PWM_PERIOD_NS); |
801 | pwm_config(panel->backlight.pwm, 0, CRC_PMIC_PWM_PERIOD_NS); |
822 | usleep_range(2000, 3000); |
802 | usleep_range(2000, 3000); |
823 | pwm_disable(panel->backlight.pwm); |
803 | pwm_disable(panel->backlight.pwm); |
824 | } |
804 | } |
825 | 805 | ||
826 | void intel_panel_disable_backlight(struct intel_connector *connector) |
806 | void intel_panel_disable_backlight(struct intel_connector *connector) |
827 | { |
807 | { |
828 | struct drm_device *dev = connector->base.dev; |
- | |
829 | struct drm_i915_private *dev_priv = dev->dev_private; |
808 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
830 | struct intel_panel *panel = &connector->panel; |
809 | struct intel_panel *panel = &connector->panel; |
831 | 810 | ||
832 | if (!panel->backlight.present) |
811 | if (!panel->backlight.present) |
833 | return; |
812 | return; |
834 | 813 | ||
835 | /* |
814 | /* |
836 | * Do not disable backlight on the vga_switcheroo path. When switching |
815 | * Do not disable backlight on the vga_switcheroo path. When switching |
837 | * away from i915, the other client may depend on i915 to handle the |
816 | * away from i915, the other client may depend on i915 to handle the |
838 | * backlight. This will leave the backlight on unnecessarily when |
817 | * backlight. This will leave the backlight on unnecessarily when |
839 | * another client is not activated. |
818 | * another client is not activated. |
840 | */ |
819 | */ |
841 | if (dev->switch_power_state == DRM_SWITCH_POWER_CHANGING) { |
820 | if (dev_priv->dev->switch_power_state == DRM_SWITCH_POWER_CHANGING) { |
842 | DRM_DEBUG_DRIVER("Skipping backlight disable on vga switch\n"); |
821 | DRM_DEBUG_DRIVER("Skipping backlight disable on vga switch\n"); |
843 | return; |
822 | return; |
844 | } |
823 | } |
845 | 824 | ||
846 | mutex_lock(&dev_priv->backlight_lock); |
825 | mutex_lock(&dev_priv->backlight_lock); |
847 | 826 | ||
848 | panel->backlight.enabled = false; |
827 | panel->backlight.enabled = false; |
849 | panel->backlight.disable(connector); |
828 | panel->backlight.disable(connector); |
850 | 829 | ||
851 | mutex_unlock(&dev_priv->backlight_lock); |
830 | mutex_unlock(&dev_priv->backlight_lock); |
852 | } |
831 | } |
853 | 832 | ||
854 | static void lpt_enable_backlight(struct intel_connector *connector) |
833 | static void lpt_enable_backlight(struct intel_connector *connector) |
855 | { |
834 | { |
856 | struct drm_device *dev = connector->base.dev; |
- | |
857 | struct drm_i915_private *dev_priv = dev->dev_private; |
835 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
858 | struct intel_panel *panel = &connector->panel; |
836 | struct intel_panel *panel = &connector->panel; |
859 | u32 pch_ctl1, pch_ctl2; |
837 | u32 pch_ctl1, pch_ctl2; |
860 | 838 | ||
861 | pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1); |
839 | pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1); |
862 | if (pch_ctl1 & BLM_PCH_PWM_ENABLE) { |
840 | if (pch_ctl1 & BLM_PCH_PWM_ENABLE) { |
863 | DRM_DEBUG_KMS("pch backlight already enabled\n"); |
841 | DRM_DEBUG_KMS("pch backlight already enabled\n"); |
864 | pch_ctl1 &= ~BLM_PCH_PWM_ENABLE; |
842 | pch_ctl1 &= ~BLM_PCH_PWM_ENABLE; |
865 | I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1); |
843 | I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1); |
866 | } |
844 | } |
867 | 845 | ||
868 | pch_ctl2 = panel->backlight.max << 16; |
846 | pch_ctl2 = panel->backlight.max << 16; |
869 | I915_WRITE(BLC_PWM_PCH_CTL2, pch_ctl2); |
847 | I915_WRITE(BLC_PWM_PCH_CTL2, pch_ctl2); |
870 | 848 | ||
871 | pch_ctl1 = 0; |
849 | pch_ctl1 = 0; |
872 | if (panel->backlight.active_low_pwm) |
850 | if (panel->backlight.active_low_pwm) |
873 | pch_ctl1 |= BLM_PCH_POLARITY; |
851 | pch_ctl1 |= BLM_PCH_POLARITY; |
874 | 852 | ||
875 | /* After LPT, override is the default. */ |
853 | /* After LPT, override is the default. */ |
876 | if (HAS_PCH_LPT(dev_priv)) |
854 | if (HAS_PCH_LPT(dev_priv)) |
877 | pch_ctl1 |= BLM_PCH_OVERRIDE_ENABLE; |
855 | pch_ctl1 |= BLM_PCH_OVERRIDE_ENABLE; |
878 | 856 | ||
879 | I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1); |
857 | I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1); |
880 | POSTING_READ(BLC_PWM_PCH_CTL1); |
858 | POSTING_READ(BLC_PWM_PCH_CTL1); |
881 | I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE); |
859 | I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE); |
882 | 860 | ||
883 | /* This won't stick until the above enable. */ |
861 | /* This won't stick until the above enable. */ |
884 | intel_panel_actually_set_backlight(connector, panel->backlight.level); |
862 | intel_panel_actually_set_backlight(connector, panel->backlight.level); |
885 | } |
863 | } |
886 | 864 | ||
887 | static void pch_enable_backlight(struct intel_connector *connector) |
865 | static void pch_enable_backlight(struct intel_connector *connector) |
888 | { |
866 | { |
889 | struct drm_device *dev = connector->base.dev; |
- | |
890 | struct drm_i915_private *dev_priv = dev->dev_private; |
867 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
891 | struct intel_panel *panel = &connector->panel; |
868 | struct intel_panel *panel = &connector->panel; |
892 | enum pipe pipe = intel_get_pipe_from_connector(connector); |
869 | enum pipe pipe = intel_get_pipe_from_connector(connector); |
893 | enum transcoder cpu_transcoder = |
870 | enum transcoder cpu_transcoder = |
894 | intel_pipe_to_cpu_transcoder(dev_priv, pipe); |
871 | intel_pipe_to_cpu_transcoder(dev_priv, pipe); |
895 | u32 cpu_ctl2, pch_ctl1, pch_ctl2; |
872 | u32 cpu_ctl2, pch_ctl1, pch_ctl2; |
896 | 873 | ||
897 | cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2); |
874 | cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2); |
898 | if (cpu_ctl2 & BLM_PWM_ENABLE) { |
875 | if (cpu_ctl2 & BLM_PWM_ENABLE) { |
899 | DRM_DEBUG_KMS("cpu backlight already enabled\n"); |
876 | DRM_DEBUG_KMS("cpu backlight already enabled\n"); |
900 | cpu_ctl2 &= ~BLM_PWM_ENABLE; |
877 | cpu_ctl2 &= ~BLM_PWM_ENABLE; |
901 | I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2); |
878 | I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2); |
902 | } |
879 | } |
903 | 880 | ||
904 | pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1); |
881 | pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1); |
905 | if (pch_ctl1 & BLM_PCH_PWM_ENABLE) { |
882 | if (pch_ctl1 & BLM_PCH_PWM_ENABLE) { |
906 | DRM_DEBUG_KMS("pch backlight already enabled\n"); |
883 | DRM_DEBUG_KMS("pch backlight already enabled\n"); |
907 | pch_ctl1 &= ~BLM_PCH_PWM_ENABLE; |
884 | pch_ctl1 &= ~BLM_PCH_PWM_ENABLE; |
908 | I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1); |
885 | I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1); |
909 | } |
886 | } |
910 | 887 | ||
911 | if (cpu_transcoder == TRANSCODER_EDP) |
888 | if (cpu_transcoder == TRANSCODER_EDP) |
912 | cpu_ctl2 = BLM_TRANSCODER_EDP; |
889 | cpu_ctl2 = BLM_TRANSCODER_EDP; |
913 | else |
890 | else |
914 | cpu_ctl2 = BLM_PIPE(cpu_transcoder); |
891 | cpu_ctl2 = BLM_PIPE(cpu_transcoder); |
915 | I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2); |
892 | I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2); |
916 | POSTING_READ(BLC_PWM_CPU_CTL2); |
893 | POSTING_READ(BLC_PWM_CPU_CTL2); |
917 | I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2 | BLM_PWM_ENABLE); |
894 | I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2 | BLM_PWM_ENABLE); |
918 | 895 | ||
919 | /* This won't stick until the above enable. */ |
896 | /* This won't stick until the above enable. */ |
920 | intel_panel_actually_set_backlight(connector, panel->backlight.level); |
897 | intel_panel_actually_set_backlight(connector, panel->backlight.level); |
921 | 898 | ||
922 | pch_ctl2 = panel->backlight.max << 16; |
899 | pch_ctl2 = panel->backlight.max << 16; |
923 | I915_WRITE(BLC_PWM_PCH_CTL2, pch_ctl2); |
900 | I915_WRITE(BLC_PWM_PCH_CTL2, pch_ctl2); |
924 | 901 | ||
925 | pch_ctl1 = 0; |
902 | pch_ctl1 = 0; |
926 | if (panel->backlight.active_low_pwm) |
903 | if (panel->backlight.active_low_pwm) |
927 | pch_ctl1 |= BLM_PCH_POLARITY; |
904 | pch_ctl1 |= BLM_PCH_POLARITY; |
928 | 905 | ||
929 | I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1); |
906 | I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1); |
930 | POSTING_READ(BLC_PWM_PCH_CTL1); |
907 | POSTING_READ(BLC_PWM_PCH_CTL1); |
931 | I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE); |
908 | I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE); |
932 | } |
909 | } |
933 | 910 | ||
934 | static void i9xx_enable_backlight(struct intel_connector *connector) |
911 | static void i9xx_enable_backlight(struct intel_connector *connector) |
935 | { |
912 | { |
936 | struct drm_device *dev = connector->base.dev; |
- | |
937 | struct drm_i915_private *dev_priv = dev->dev_private; |
913 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
938 | struct intel_panel *panel = &connector->panel; |
914 | struct intel_panel *panel = &connector->panel; |
939 | u32 ctl, freq; |
915 | u32 ctl, freq; |
940 | 916 | ||
941 | ctl = I915_READ(BLC_PWM_CTL); |
917 | ctl = I915_READ(BLC_PWM_CTL); |
942 | if (ctl & BACKLIGHT_DUTY_CYCLE_MASK_PNV) { |
918 | if (ctl & BACKLIGHT_DUTY_CYCLE_MASK_PNV) { |
943 | DRM_DEBUG_KMS("backlight already enabled\n"); |
919 | DRM_DEBUG_KMS("backlight already enabled\n"); |
944 | I915_WRITE(BLC_PWM_CTL, 0); |
920 | I915_WRITE(BLC_PWM_CTL, 0); |
945 | } |
921 | } |
946 | 922 | ||
947 | freq = panel->backlight.max; |
923 | freq = panel->backlight.max; |
948 | if (panel->backlight.combination_mode) |
924 | if (panel->backlight.combination_mode) |
949 | freq /= 0xff; |
925 | freq /= 0xff; |
950 | 926 | ||
951 | ctl = freq << 17; |
927 | ctl = freq << 17; |
952 | if (panel->backlight.combination_mode) |
928 | if (panel->backlight.combination_mode) |
953 | ctl |= BLM_LEGACY_MODE; |
929 | ctl |= BLM_LEGACY_MODE; |
954 | if (IS_PINEVIEW(dev) && panel->backlight.active_low_pwm) |
930 | if (IS_PINEVIEW(dev_priv) && panel->backlight.active_low_pwm) |
955 | ctl |= BLM_POLARITY_PNV; |
931 | ctl |= BLM_POLARITY_PNV; |
956 | 932 | ||
957 | I915_WRITE(BLC_PWM_CTL, ctl); |
933 | I915_WRITE(BLC_PWM_CTL, ctl); |
958 | POSTING_READ(BLC_PWM_CTL); |
934 | POSTING_READ(BLC_PWM_CTL); |
959 | 935 | ||
960 | /* XXX: combine this into above write? */ |
936 | /* XXX: combine this into above write? */ |
961 | intel_panel_actually_set_backlight(connector, panel->backlight.level); |
937 | intel_panel_actually_set_backlight(connector, panel->backlight.level); |
962 | 938 | ||
963 | /* |
939 | /* |
964 | * Needed to enable backlight on some 855gm models. BLC_HIST_CTL is |
940 | * Needed to enable backlight on some 855gm models. BLC_HIST_CTL is |
965 | * 855gm only, but checking for gen2 is safe, as 855gm is the only gen2 |
941 | * 855gm only, but checking for gen2 is safe, as 855gm is the only gen2 |
966 | * that has backlight. |
942 | * that has backlight. |
967 | */ |
943 | */ |
968 | if (IS_GEN2(dev)) |
944 | if (IS_GEN2(dev_priv)) |
969 | I915_WRITE(BLC_HIST_CTL, BLM_HISTOGRAM_ENABLE); |
945 | I915_WRITE(BLC_HIST_CTL, BLM_HISTOGRAM_ENABLE); |
970 | } |
946 | } |
971 | 947 | ||
972 | static void i965_enable_backlight(struct intel_connector *connector) |
948 | static void i965_enable_backlight(struct intel_connector *connector) |
973 | { |
949 | { |
974 | struct drm_device *dev = connector->base.dev; |
- | |
975 | struct drm_i915_private *dev_priv = dev->dev_private; |
950 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
976 | struct intel_panel *panel = &connector->panel; |
951 | struct intel_panel *panel = &connector->panel; |
977 | enum pipe pipe = intel_get_pipe_from_connector(connector); |
952 | enum pipe pipe = intel_get_pipe_from_connector(connector); |
978 | u32 ctl, ctl2, freq; |
953 | u32 ctl, ctl2, freq; |
979 | 954 | ||
980 | ctl2 = I915_READ(BLC_PWM_CTL2); |
955 | ctl2 = I915_READ(BLC_PWM_CTL2); |
981 | if (ctl2 & BLM_PWM_ENABLE) { |
956 | if (ctl2 & BLM_PWM_ENABLE) { |
982 | DRM_DEBUG_KMS("backlight already enabled\n"); |
957 | DRM_DEBUG_KMS("backlight already enabled\n"); |
983 | ctl2 &= ~BLM_PWM_ENABLE; |
958 | ctl2 &= ~BLM_PWM_ENABLE; |
984 | I915_WRITE(BLC_PWM_CTL2, ctl2); |
959 | I915_WRITE(BLC_PWM_CTL2, ctl2); |
985 | } |
960 | } |
986 | 961 | ||
987 | freq = panel->backlight.max; |
962 | freq = panel->backlight.max; |
988 | if (panel->backlight.combination_mode) |
963 | if (panel->backlight.combination_mode) |
989 | freq /= 0xff; |
964 | freq /= 0xff; |
990 | 965 | ||
991 | ctl = freq << 16; |
966 | ctl = freq << 16; |
992 | I915_WRITE(BLC_PWM_CTL, ctl); |
967 | I915_WRITE(BLC_PWM_CTL, ctl); |
993 | 968 | ||
994 | ctl2 = BLM_PIPE(pipe); |
969 | ctl2 = BLM_PIPE(pipe); |
995 | if (panel->backlight.combination_mode) |
970 | if (panel->backlight.combination_mode) |
996 | ctl2 |= BLM_COMBINATION_MODE; |
971 | ctl2 |= BLM_COMBINATION_MODE; |
997 | if (panel->backlight.active_low_pwm) |
972 | if (panel->backlight.active_low_pwm) |
998 | ctl2 |= BLM_POLARITY_I965; |
973 | ctl2 |= BLM_POLARITY_I965; |
999 | I915_WRITE(BLC_PWM_CTL2, ctl2); |
974 | I915_WRITE(BLC_PWM_CTL2, ctl2); |
1000 | POSTING_READ(BLC_PWM_CTL2); |
975 | POSTING_READ(BLC_PWM_CTL2); |
1001 | I915_WRITE(BLC_PWM_CTL2, ctl2 | BLM_PWM_ENABLE); |
976 | I915_WRITE(BLC_PWM_CTL2, ctl2 | BLM_PWM_ENABLE); |
1002 | 977 | ||
1003 | intel_panel_actually_set_backlight(connector, panel->backlight.level); |
978 | intel_panel_actually_set_backlight(connector, panel->backlight.level); |
1004 | } |
979 | } |
1005 | 980 | ||
1006 | static void vlv_enable_backlight(struct intel_connector *connector) |
981 | static void vlv_enable_backlight(struct intel_connector *connector) |
1007 | { |
982 | { |
1008 | struct drm_device *dev = connector->base.dev; |
- | |
1009 | struct drm_i915_private *dev_priv = dev->dev_private; |
983 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
1010 | struct intel_panel *panel = &connector->panel; |
984 | struct intel_panel *panel = &connector->panel; |
1011 | enum pipe pipe = intel_get_pipe_from_connector(connector); |
985 | enum pipe pipe = intel_get_pipe_from_connector(connector); |
1012 | u32 ctl, ctl2; |
986 | u32 ctl, ctl2; |
1013 | 987 | ||
1014 | if (WARN_ON(pipe != PIPE_A && pipe != PIPE_B)) |
988 | if (WARN_ON(pipe != PIPE_A && pipe != PIPE_B)) |
1015 | return; |
989 | return; |
1016 | 990 | ||
1017 | ctl2 = I915_READ(VLV_BLC_PWM_CTL2(pipe)); |
991 | ctl2 = I915_READ(VLV_BLC_PWM_CTL2(pipe)); |
1018 | if (ctl2 & BLM_PWM_ENABLE) { |
992 | if (ctl2 & BLM_PWM_ENABLE) { |
1019 | DRM_DEBUG_KMS("backlight already enabled\n"); |
993 | DRM_DEBUG_KMS("backlight already enabled\n"); |
1020 | ctl2 &= ~BLM_PWM_ENABLE; |
994 | ctl2 &= ~BLM_PWM_ENABLE; |
1021 | I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2); |
995 | I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2); |
1022 | } |
996 | } |
1023 | 997 | ||
1024 | ctl = panel->backlight.max << 16; |
998 | ctl = panel->backlight.max << 16; |
1025 | I915_WRITE(VLV_BLC_PWM_CTL(pipe), ctl); |
999 | I915_WRITE(VLV_BLC_PWM_CTL(pipe), ctl); |
1026 | 1000 | ||
1027 | /* XXX: combine this into above write? */ |
1001 | /* XXX: combine this into above write? */ |
1028 | intel_panel_actually_set_backlight(connector, panel->backlight.level); |
1002 | intel_panel_actually_set_backlight(connector, panel->backlight.level); |
1029 | 1003 | ||
1030 | ctl2 = 0; |
1004 | ctl2 = 0; |
1031 | if (panel->backlight.active_low_pwm) |
1005 | if (panel->backlight.active_low_pwm) |
1032 | ctl2 |= BLM_POLARITY_I965; |
1006 | ctl2 |= BLM_POLARITY_I965; |
1033 | I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2); |
1007 | I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2); |
1034 | POSTING_READ(VLV_BLC_PWM_CTL2(pipe)); |
1008 | POSTING_READ(VLV_BLC_PWM_CTL2(pipe)); |
1035 | I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2 | BLM_PWM_ENABLE); |
1009 | I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2 | BLM_PWM_ENABLE); |
1036 | } |
1010 | } |
1037 | 1011 | ||
1038 | static void bxt_enable_backlight(struct intel_connector *connector) |
1012 | static void bxt_enable_backlight(struct intel_connector *connector) |
1039 | { |
1013 | { |
1040 | struct drm_device *dev = connector->base.dev; |
- | |
1041 | struct drm_i915_private *dev_priv = dev->dev_private; |
1014 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
1042 | struct intel_panel *panel = &connector->panel; |
1015 | struct intel_panel *panel = &connector->panel; |
1043 | enum pipe pipe = intel_get_pipe_from_connector(connector); |
1016 | enum pipe pipe = intel_get_pipe_from_connector(connector); |
1044 | u32 pwm_ctl, val; |
1017 | u32 pwm_ctl, val; |
1045 | 1018 | ||
1046 | /* To use 2nd set of backlight registers, utility pin has to be |
1019 | /* To use 2nd set of backlight registers, utility pin has to be |
1047 | * enabled with PWM mode. |
1020 | * enabled with PWM mode. |
1048 | * The field should only be changed when the utility pin is disabled |
1021 | * The field should only be changed when the utility pin is disabled |
1049 | */ |
1022 | */ |
1050 | if (panel->backlight.controller == 1) { |
1023 | if (panel->backlight.controller == 1) { |
1051 | val = I915_READ(UTIL_PIN_CTL); |
1024 | val = I915_READ(UTIL_PIN_CTL); |
1052 | if (val & UTIL_PIN_ENABLE) { |
1025 | if (val & UTIL_PIN_ENABLE) { |
1053 | DRM_DEBUG_KMS("util pin already enabled\n"); |
1026 | DRM_DEBUG_KMS("util pin already enabled\n"); |
1054 | val &= ~UTIL_PIN_ENABLE; |
1027 | val &= ~UTIL_PIN_ENABLE; |
1055 | I915_WRITE(UTIL_PIN_CTL, val); |
1028 | I915_WRITE(UTIL_PIN_CTL, val); |
1056 | } |
1029 | } |
1057 | 1030 | ||
1058 | val = 0; |
1031 | val = 0; |
1059 | if (panel->backlight.util_pin_active_low) |
1032 | if (panel->backlight.util_pin_active_low) |
1060 | val |= UTIL_PIN_POLARITY; |
1033 | val |= UTIL_PIN_POLARITY; |
1061 | I915_WRITE(UTIL_PIN_CTL, val | UTIL_PIN_PIPE(pipe) | |
1034 | I915_WRITE(UTIL_PIN_CTL, val | UTIL_PIN_PIPE(pipe) | |
1062 | UTIL_PIN_MODE_PWM | UTIL_PIN_ENABLE); |
1035 | UTIL_PIN_MODE_PWM | UTIL_PIN_ENABLE); |
1063 | } |
1036 | } |
1064 | 1037 | ||
1065 | pwm_ctl = I915_READ(BXT_BLC_PWM_CTL(panel->backlight.controller)); |
1038 | pwm_ctl = I915_READ(BXT_BLC_PWM_CTL(panel->backlight.controller)); |
1066 | if (pwm_ctl & BXT_BLC_PWM_ENABLE) { |
1039 | if (pwm_ctl & BXT_BLC_PWM_ENABLE) { |
1067 | DRM_DEBUG_KMS("backlight already enabled\n"); |
1040 | DRM_DEBUG_KMS("backlight already enabled\n"); |
1068 | pwm_ctl &= ~BXT_BLC_PWM_ENABLE; |
1041 | pwm_ctl &= ~BXT_BLC_PWM_ENABLE; |
1069 | I915_WRITE(BXT_BLC_PWM_CTL(panel->backlight.controller), |
1042 | I915_WRITE(BXT_BLC_PWM_CTL(panel->backlight.controller), |
1070 | pwm_ctl); |
1043 | pwm_ctl); |
1071 | } |
1044 | } |
1072 | 1045 | ||
1073 | I915_WRITE(BXT_BLC_PWM_FREQ(panel->backlight.controller), |
1046 | I915_WRITE(BXT_BLC_PWM_FREQ(panel->backlight.controller), |
1074 | panel->backlight.max); |
1047 | panel->backlight.max); |
1075 | 1048 | ||
1076 | intel_panel_actually_set_backlight(connector, panel->backlight.level); |
1049 | intel_panel_actually_set_backlight(connector, panel->backlight.level); |
1077 | 1050 | ||
1078 | pwm_ctl = 0; |
1051 | pwm_ctl = 0; |
1079 | if (panel->backlight.active_low_pwm) |
1052 | if (panel->backlight.active_low_pwm) |
1080 | pwm_ctl |= BXT_BLC_PWM_POLARITY; |
1053 | pwm_ctl |= BXT_BLC_PWM_POLARITY; |
1081 | 1054 | ||
1082 | I915_WRITE(BXT_BLC_PWM_CTL(panel->backlight.controller), pwm_ctl); |
1055 | I915_WRITE(BXT_BLC_PWM_CTL(panel->backlight.controller), pwm_ctl); |
1083 | POSTING_READ(BXT_BLC_PWM_CTL(panel->backlight.controller)); |
1056 | POSTING_READ(BXT_BLC_PWM_CTL(panel->backlight.controller)); |
1084 | I915_WRITE(BXT_BLC_PWM_CTL(panel->backlight.controller), |
1057 | I915_WRITE(BXT_BLC_PWM_CTL(panel->backlight.controller), |
1085 | pwm_ctl | BXT_BLC_PWM_ENABLE); |
1058 | pwm_ctl | BXT_BLC_PWM_ENABLE); |
1086 | } |
1059 | } |
1087 | 1060 | ||
1088 | static void pwm_enable_backlight(struct intel_connector *connector) |
1061 | static void pwm_enable_backlight(struct intel_connector *connector) |
1089 | { |
1062 | { |
1090 | struct intel_panel *panel = &connector->panel; |
1063 | struct intel_panel *panel = &connector->panel; |
1091 | 1064 | ||
1092 | pwm_enable(panel->backlight.pwm); |
1065 | pwm_enable(panel->backlight.pwm); |
1093 | intel_panel_actually_set_backlight(connector, panel->backlight.level); |
1066 | intel_panel_actually_set_backlight(connector, panel->backlight.level); |
1094 | } |
1067 | } |
1095 | 1068 | ||
1096 | void intel_panel_enable_backlight(struct intel_connector *connector) |
1069 | void intel_panel_enable_backlight(struct intel_connector *connector) |
1097 | { |
1070 | { |
1098 | struct drm_device *dev = connector->base.dev; |
- | |
1099 | struct drm_i915_private *dev_priv = dev->dev_private; |
1071 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
1100 | struct intel_panel *panel = &connector->panel; |
1072 | struct intel_panel *panel = &connector->panel; |
1101 | enum pipe pipe = intel_get_pipe_from_connector(connector); |
1073 | enum pipe pipe = intel_get_pipe_from_connector(connector); |
1102 | 1074 | ||
1103 | if (!panel->backlight.present) |
1075 | if (!panel->backlight.present) |
1104 | return; |
1076 | return; |
1105 | 1077 | ||
1106 | DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe)); |
1078 | DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe)); |
1107 | 1079 | ||
1108 | mutex_lock(&dev_priv->backlight_lock); |
1080 | mutex_lock(&dev_priv->backlight_lock); |
1109 | 1081 | ||
1110 | WARN_ON(panel->backlight.max == 0); |
1082 | WARN_ON(panel->backlight.max == 0); |
1111 | 1083 | ||
1112 | if (panel->backlight.level <= panel->backlight.min) { |
1084 | if (panel->backlight.level <= panel->backlight.min) { |
1113 | panel->backlight.level = panel->backlight.max; |
1085 | panel->backlight.level = panel->backlight.max; |
1114 | } |
1086 | } |
1115 | 1087 | ||
1116 | panel->backlight.enable(connector); |
1088 | panel->backlight.enable(connector); |
1117 | panel->backlight.enabled = true; |
1089 | panel->backlight.enabled = true; |
1118 | 1090 | ||
1119 | mutex_unlock(&dev_priv->backlight_lock); |
1091 | mutex_unlock(&dev_priv->backlight_lock); |
1120 | } |
1092 | } |
1121 | 1093 | ||
1122 | #if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE) |
1094 | #if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE) |
1123 | static int intel_backlight_device_update_status(struct backlight_device *bd) |
1095 | static int intel_backlight_device_update_status(struct backlight_device *bd) |
1124 | { |
1096 | { |
1125 | struct intel_connector *connector = bl_get_data(bd); |
1097 | struct intel_connector *connector = bl_get_data(bd); |
1126 | struct intel_panel *panel = &connector->panel; |
1098 | struct intel_panel *panel = &connector->panel; |
1127 | struct drm_device *dev = connector->base.dev; |
1099 | struct drm_device *dev = connector->base.dev; |
1128 | 1100 | ||
1129 | drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); |
1101 | drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); |
1130 | DRM_DEBUG_KMS("updating intel_backlight, brightness=%d/%d\n", |
1102 | DRM_DEBUG_KMS("updating intel_backlight, brightness=%d/%d\n", |
1131 | bd->props.brightness, bd->props.max_brightness); |
1103 | bd->props.brightness, bd->props.max_brightness); |
1132 | intel_panel_set_backlight(connector, bd->props.brightness, |
1104 | intel_panel_set_backlight(connector, bd->props.brightness, |
1133 | bd->props.max_brightness); |
1105 | bd->props.max_brightness); |
1134 | 1106 | ||
1135 | /* |
1107 | /* |
1136 | * Allow flipping bl_power as a sub-state of enabled. Sadly the |
1108 | * Allow flipping bl_power as a sub-state of enabled. Sadly the |
1137 | * backlight class device does not make it easy to to differentiate |
1109 | * backlight class device does not make it easy to to differentiate |
1138 | * between callbacks for brightness and bl_power, so our backlight_power |
1110 | * between callbacks for brightness and bl_power, so our backlight_power |
1139 | * callback needs to take this into account. |
1111 | * callback needs to take this into account. |
1140 | */ |
1112 | */ |
1141 | if (panel->backlight.enabled) { |
1113 | if (panel->backlight.enabled) { |
1142 | if (panel->backlight.power) { |
1114 | if (panel->backlight.power) { |
1143 | bool enable = bd->props.power == FB_BLANK_UNBLANK && |
1115 | bool enable = bd->props.power == FB_BLANK_UNBLANK && |
1144 | bd->props.brightness != 0; |
1116 | bd->props.brightness != 0; |
1145 | panel->backlight.power(connector, enable); |
1117 | panel->backlight.power(connector, enable); |
1146 | } |
1118 | } |
1147 | } else { |
1119 | } else { |
1148 | bd->props.power = FB_BLANK_POWERDOWN; |
1120 | bd->props.power = FB_BLANK_POWERDOWN; |
1149 | } |
1121 | } |
1150 | 1122 | ||
1151 | drm_modeset_unlock(&dev->mode_config.connection_mutex); |
1123 | drm_modeset_unlock(&dev->mode_config.connection_mutex); |
1152 | return 0; |
1124 | return 0; |
1153 | } |
1125 | } |
1154 | 1126 | ||
1155 | static int intel_backlight_device_get_brightness(struct backlight_device *bd) |
1127 | static int intel_backlight_device_get_brightness(struct backlight_device *bd) |
1156 | { |
1128 | { |
1157 | struct intel_connector *connector = bl_get_data(bd); |
1129 | struct intel_connector *connector = bl_get_data(bd); |
1158 | struct drm_device *dev = connector->base.dev; |
1130 | struct drm_device *dev = connector->base.dev; |
1159 | struct drm_i915_private *dev_priv = dev->dev_private; |
1131 | struct drm_i915_private *dev_priv = dev->dev_private; |
1160 | u32 hw_level; |
1132 | u32 hw_level; |
1161 | int ret; |
1133 | int ret; |
1162 | 1134 | ||
1163 | intel_runtime_pm_get(dev_priv); |
1135 | intel_runtime_pm_get(dev_priv); |
1164 | drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); |
1136 | drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); |
1165 | 1137 | ||
1166 | hw_level = intel_panel_get_backlight(connector); |
1138 | hw_level = intel_panel_get_backlight(connector); |
1167 | ret = scale_hw_to_user(connector, hw_level, bd->props.max_brightness); |
1139 | ret = scale_hw_to_user(connector, hw_level, bd->props.max_brightness); |
1168 | 1140 | ||
1169 | drm_modeset_unlock(&dev->mode_config.connection_mutex); |
1141 | drm_modeset_unlock(&dev->mode_config.connection_mutex); |
1170 | intel_runtime_pm_put(dev_priv); |
1142 | intel_runtime_pm_put(dev_priv); |
1171 | 1143 | ||
1172 | return ret; |
1144 | return ret; |
1173 | } |
1145 | } |
1174 | 1146 | ||
1175 | static const struct backlight_ops intel_backlight_device_ops = { |
1147 | static const struct backlight_ops intel_backlight_device_ops = { |
1176 | .update_status = intel_backlight_device_update_status, |
1148 | .update_status = intel_backlight_device_update_status, |
1177 | .get_brightness = intel_backlight_device_get_brightness, |
1149 | .get_brightness = intel_backlight_device_get_brightness, |
1178 | }; |
1150 | }; |
1179 | 1151 | ||
1180 | static int intel_backlight_device_register(struct intel_connector *connector) |
1152 | static int intel_backlight_device_register(struct intel_connector *connector) |
1181 | { |
1153 | { |
1182 | struct intel_panel *panel = &connector->panel; |
1154 | struct intel_panel *panel = &connector->panel; |
1183 | struct backlight_properties props; |
1155 | struct backlight_properties props; |
1184 | 1156 | ||
1185 | if (WARN_ON(panel->backlight.device)) |
1157 | if (WARN_ON(panel->backlight.device)) |
1186 | return -ENODEV; |
1158 | return -ENODEV; |
1187 | 1159 | ||
1188 | if (!panel->backlight.present) |
1160 | if (!panel->backlight.present) |
1189 | return 0; |
1161 | return 0; |
1190 | 1162 | ||
1191 | WARN_ON(panel->backlight.max == 0); |
1163 | WARN_ON(panel->backlight.max == 0); |
1192 | 1164 | ||
1193 | memset(&props, 0, sizeof(props)); |
1165 | memset(&props, 0, sizeof(props)); |
1194 | props.type = BACKLIGHT_RAW; |
1166 | props.type = BACKLIGHT_RAW; |
1195 | 1167 | ||
1196 | /* |
1168 | /* |
1197 | * Note: Everything should work even if the backlight device max |
1169 | * Note: Everything should work even if the backlight device max |
1198 | * presented to the userspace is arbitrarily chosen. |
1170 | * presented to the userspace is arbitrarily chosen. |
1199 | */ |
1171 | */ |
1200 | props.max_brightness = panel->backlight.max; |
1172 | props.max_brightness = panel->backlight.max; |
1201 | props.brightness = scale_hw_to_user(connector, |
1173 | props.brightness = scale_hw_to_user(connector, |
1202 | panel->backlight.level, |
1174 | panel->backlight.level, |
1203 | props.max_brightness); |
1175 | props.max_brightness); |
1204 | 1176 | ||
1205 | if (panel->backlight.enabled) |
1177 | if (panel->backlight.enabled) |
1206 | props.power = FB_BLANK_UNBLANK; |
1178 | props.power = FB_BLANK_UNBLANK; |
1207 | else |
1179 | else |
1208 | props.power = FB_BLANK_POWERDOWN; |
1180 | props.power = FB_BLANK_POWERDOWN; |
1209 | 1181 | ||
1210 | /* |
1182 | /* |
1211 | * Note: using the same name independent of the connector prevents |
1183 | * Note: using the same name independent of the connector prevents |
1212 | * registration of multiple backlight devices in the driver. |
1184 | * registration of multiple backlight devices in the driver. |
1213 | */ |
1185 | */ |
1214 | panel->backlight.device = |
1186 | panel->backlight.device = |
1215 | backlight_device_register("intel_backlight", |
1187 | backlight_device_register("intel_backlight", |
1216 | connector->base.kdev, |
1188 | connector->base.kdev, |
1217 | connector, |
1189 | connector, |
1218 | &intel_backlight_device_ops, &props); |
1190 | &intel_backlight_device_ops, &props); |
1219 | 1191 | ||
1220 | if (IS_ERR(panel->backlight.device)) { |
1192 | if (IS_ERR(panel->backlight.device)) { |
1221 | DRM_ERROR("Failed to register backlight: %ld\n", |
1193 | DRM_ERROR("Failed to register backlight: %ld\n", |
1222 | PTR_ERR(panel->backlight.device)); |
1194 | PTR_ERR(panel->backlight.device)); |
1223 | panel->backlight.device = NULL; |
1195 | panel->backlight.device = NULL; |
1224 | return -ENODEV; |
1196 | return -ENODEV; |
1225 | } |
1197 | } |
1226 | 1198 | ||
1227 | DRM_DEBUG_KMS("Connector %s backlight sysfs interface registered\n", |
1199 | DRM_DEBUG_KMS("Connector %s backlight sysfs interface registered\n", |
1228 | connector->base.name); |
1200 | connector->base.name); |
1229 | 1201 | ||
1230 | return 0; |
1202 | return 0; |
1231 | } |
1203 | } |
1232 | 1204 | ||
1233 | static void intel_backlight_device_unregister(struct intel_connector *connector) |
1205 | static void intel_backlight_device_unregister(struct intel_connector *connector) |
1234 | { |
1206 | { |
1235 | struct intel_panel *panel = &connector->panel; |
1207 | struct intel_panel *panel = &connector->panel; |
1236 | 1208 | ||
1237 | if (panel->backlight.device) { |
1209 | if (panel->backlight.device) { |
1238 | backlight_device_unregister(panel->backlight.device); |
1210 | backlight_device_unregister(panel->backlight.device); |
1239 | panel->backlight.device = NULL; |
1211 | panel->backlight.device = NULL; |
1240 | } |
1212 | } |
1241 | } |
1213 | } |
1242 | #else /* CONFIG_BACKLIGHT_CLASS_DEVICE */ |
1214 | #else /* CONFIG_BACKLIGHT_CLASS_DEVICE */ |
1243 | static int intel_backlight_device_register(struct intel_connector *connector) |
1215 | static int intel_backlight_device_register(struct intel_connector *connector) |
1244 | { |
1216 | { |
1245 | return 0; |
1217 | return 0; |
1246 | } |
1218 | } |
1247 | static void intel_backlight_device_unregister(struct intel_connector *connector) |
1219 | static void intel_backlight_device_unregister(struct intel_connector *connector) |
1248 | { |
1220 | { |
1249 | } |
1221 | } |
1250 | #endif /* CONFIG_BACKLIGHT_CLASS_DEVICE */ |
1222 | #endif /* CONFIG_BACKLIGHT_CLASS_DEVICE */ |
1251 | 1223 | ||
1252 | /* |
1224 | /* |
- | 1225 | * BXT: PWM clock frequency = 19.2 MHz. |
|
- | 1226 | */ |
|
- | 1227 | static u32 bxt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) |
|
- | 1228 | { |
|
- | 1229 | return KHz(19200) / pwm_freq_hz; |
|
- | 1230 | } |
|
- | 1231 | ||
- | 1232 | /* |
|
1253 | * SPT: This value represents the period of the PWM stream in clock periods |
1233 | * SPT: This value represents the period of the PWM stream in clock periods |
1254 | * multiplied by 16 (default increment) or 128 (alternate increment selected in |
1234 | * multiplied by 16 (default increment) or 128 (alternate increment selected in |
1255 | * SCHICKEN_1 bit 0). PWM clock is 24 MHz. |
1235 | * SCHICKEN_1 bit 0). PWM clock is 24 MHz. |
1256 | */ |
1236 | */ |
1257 | static u32 spt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) |
1237 | static u32 spt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) |
1258 | { |
1238 | { |
1259 | struct drm_device *dev = connector->base.dev; |
- | |
1260 | struct drm_i915_private *dev_priv = dev->dev_private; |
1239 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
1261 | u32 mul, clock; |
1240 | u32 mul, clock; |
1262 | 1241 | ||
1263 | if (I915_READ(SOUTH_CHICKEN1) & SPT_PWM_GRANULARITY) |
1242 | if (I915_READ(SOUTH_CHICKEN1) & SPT_PWM_GRANULARITY) |
1264 | mul = 128; |
1243 | mul = 128; |
1265 | else |
1244 | else |
1266 | mul = 16; |
1245 | mul = 16; |
1267 | 1246 | ||
1268 | clock = MHz(24); |
1247 | clock = MHz(24); |
1269 | 1248 | ||
1270 | return clock / (pwm_freq_hz * mul); |
1249 | return clock / (pwm_freq_hz * mul); |
1271 | } |
1250 | } |
1272 | 1251 | ||
1273 | /* |
1252 | /* |
1274 | * LPT: This value represents the period of the PWM stream in clock periods |
1253 | * LPT: This value represents the period of the PWM stream in clock periods |
1275 | * multiplied by 128 (default increment) or 16 (alternate increment, selected in |
1254 | * multiplied by 128 (default increment) or 16 (alternate increment, selected in |
1276 | * LPT SOUTH_CHICKEN2 register bit 5). |
1255 | * LPT SOUTH_CHICKEN2 register bit 5). |
1277 | */ |
1256 | */ |
1278 | static u32 lpt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) |
1257 | static u32 lpt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) |
1279 | { |
1258 | { |
1280 | struct drm_device *dev = connector->base.dev; |
- | |
1281 | struct drm_i915_private *dev_priv = dev->dev_private; |
1259 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
1282 | u32 mul, clock; |
1260 | u32 mul, clock; |
1283 | 1261 | ||
1284 | if (I915_READ(SOUTH_CHICKEN2) & LPT_PWM_GRANULARITY) |
1262 | if (I915_READ(SOUTH_CHICKEN2) & LPT_PWM_GRANULARITY) |
1285 | mul = 16; |
1263 | mul = 16; |
1286 | else |
1264 | else |
1287 | mul = 128; |
1265 | mul = 128; |
1288 | 1266 | ||
1289 | if (dev_priv->pch_id == INTEL_PCH_LPT_DEVICE_ID_TYPE) |
1267 | if (HAS_PCH_LPT_H(dev_priv)) |
1290 | clock = MHz(135); /* LPT:H */ |
1268 | clock = MHz(135); /* LPT:H */ |
1291 | else |
1269 | else |
1292 | clock = MHz(24); /* LPT:LP */ |
1270 | clock = MHz(24); /* LPT:LP */ |
1293 | 1271 | ||
1294 | return clock / (pwm_freq_hz * mul); |
1272 | return clock / (pwm_freq_hz * mul); |
1295 | } |
1273 | } |
1296 | 1274 | ||
1297 | /* |
1275 | /* |
1298 | * ILK/SNB/IVB: This value represents the period of the PWM stream in PCH |
1276 | * ILK/SNB/IVB: This value represents the period of the PWM stream in PCH |
1299 | * display raw clocks multiplied by 128. |
1277 | * display raw clocks multiplied by 128. |
1300 | */ |
1278 | */ |
1301 | static u32 pch_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) |
1279 | static u32 pch_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) |
1302 | { |
1280 | { |
1303 | struct drm_device *dev = connector->base.dev; |
1281 | struct drm_device *dev = connector->base.dev; |
1304 | int clock = MHz(intel_pch_rawclk(dev)); |
1282 | int clock = MHz(intel_pch_rawclk(dev)); |
1305 | 1283 | ||
1306 | return clock / (pwm_freq_hz * 128); |
1284 | return clock / (pwm_freq_hz * 128); |
1307 | } |
1285 | } |
1308 | 1286 | ||
1309 | /* |
1287 | /* |
1310 | * Gen2: This field determines the number of time base events (display core |
1288 | * Gen2: This field determines the number of time base events (display core |
1311 | * clock frequency/32) in total for a complete cycle of modulated backlight |
1289 | * clock frequency/32) in total for a complete cycle of modulated backlight |
1312 | * control. |
1290 | * control. |
1313 | * |
1291 | * |
1314 | * Gen3: A time base event equals the display core clock ([DevPNV] HRAW clock) |
1292 | * Gen3: A time base event equals the display core clock ([DevPNV] HRAW clock) |
1315 | * divided by 32. |
1293 | * divided by 32. |
1316 | */ |
1294 | */ |
1317 | static u32 i9xx_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) |
1295 | static u32 i9xx_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) |
1318 | { |
1296 | { |
1319 | struct drm_device *dev = connector->base.dev; |
1297 | struct drm_device *dev = connector->base.dev; |
1320 | struct drm_i915_private *dev_priv = dev->dev_private; |
1298 | struct drm_i915_private *dev_priv = dev->dev_private; |
1321 | int clock; |
1299 | int clock; |
1322 | 1300 | ||
1323 | if (IS_PINEVIEW(dev)) |
1301 | if (IS_PINEVIEW(dev)) |
1324 | clock = intel_hrawclk(dev); |
1302 | clock = MHz(intel_hrawclk(dev)); |
1325 | else |
1303 | else |
1326 | clock = 1000 * dev_priv->display.get_display_clock_speed(dev); |
1304 | clock = 1000 * dev_priv->cdclk_freq; |
1327 | 1305 | ||
1328 | return clock / (pwm_freq_hz * 32); |
1306 | return clock / (pwm_freq_hz * 32); |
1329 | } |
1307 | } |
1330 | 1308 | ||
1331 | /* |
1309 | /* |
1332 | * Gen4: This value represents the period of the PWM stream in display core |
1310 | * Gen4: This value represents the period of the PWM stream in display core |
1333 | * clocks multiplied by 128. |
1311 | * clocks ([DevCTG] HRAW clocks) multiplied by 128. |
- | 1312 | * |
|
1334 | */ |
1313 | */ |
1335 | static u32 i965_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) |
1314 | static u32 i965_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) |
1336 | { |
1315 | { |
1337 | struct drm_device *dev = connector->base.dev; |
1316 | struct drm_device *dev = connector->base.dev; |
1338 | struct drm_i915_private *dev_priv = dev->dev_private; |
1317 | struct drm_i915_private *dev_priv = dev->dev_private; |
- | 1318 | int clock; |
|
- | 1319 | ||
- | 1320 | if (IS_G4X(dev_priv)) |
|
- | 1321 | clock = MHz(intel_hrawclk(dev)); |
|
- | 1322 | else |
|
1339 | int clock = 1000 * dev_priv->display.get_display_clock_speed(dev); |
1323 | clock = 1000 * dev_priv->cdclk_freq; |
1340 | 1324 | ||
1341 | return clock / (pwm_freq_hz * 128); |
1325 | return clock / (pwm_freq_hz * 128); |
1342 | } |
1326 | } |
1343 | 1327 | ||
1344 | /* |
1328 | /* |
1345 | * VLV: This value represents the period of the PWM stream in display core |
1329 | * VLV: This value represents the period of the PWM stream in display core |
1346 | * clocks ([DevCTG] 200MHz HRAW clocks) multiplied by 128 or 25MHz S0IX clocks |
1330 | * clocks ([DevCTG] 200MHz HRAW clocks) multiplied by 128 or 25MHz S0IX clocks |
1347 | * multiplied by 16. CHV uses a 19.2MHz S0IX clock. |
1331 | * multiplied by 16. CHV uses a 19.2MHz S0IX clock. |
1348 | */ |
1332 | */ |
1349 | static u32 vlv_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) |
1333 | static u32 vlv_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) |
1350 | { |
1334 | { |
1351 | struct drm_device *dev = connector->base.dev; |
1335 | struct drm_device *dev = connector->base.dev; |
1352 | struct drm_i915_private *dev_priv = dev->dev_private; |
1336 | struct drm_i915_private *dev_priv = dev->dev_private; |
1353 | int clock; |
1337 | int clock; |
1354 | 1338 | ||
1355 | if ((I915_READ(CBR1_VLV) & CBR_PWM_CLOCK_MUX_SELECT) == 0) { |
1339 | if ((I915_READ(CBR1_VLV) & CBR_PWM_CLOCK_MUX_SELECT) == 0) { |
1356 | if (IS_CHERRYVIEW(dev)) |
1340 | if (IS_CHERRYVIEW(dev)) |
1357 | return KHz(19200) / (pwm_freq_hz * 16); |
1341 | return KHz(19200) / (pwm_freq_hz * 16); |
1358 | else |
1342 | else |
1359 | return MHz(25) / (pwm_freq_hz * 16); |
1343 | return MHz(25) / (pwm_freq_hz * 16); |
1360 | } else { |
1344 | } else { |
1361 | clock = intel_hrawclk(dev); |
1345 | clock = intel_hrawclk(dev); |
1362 | return MHz(clock) / (pwm_freq_hz * 128); |
1346 | return MHz(clock) / (pwm_freq_hz * 128); |
1363 | } |
1347 | } |
1364 | } |
1348 | } |
1365 | 1349 | ||
1366 | static u32 get_backlight_max_vbt(struct intel_connector *connector) |
1350 | static u32 get_backlight_max_vbt(struct intel_connector *connector) |
1367 | { |
1351 | { |
1368 | struct drm_device *dev = connector->base.dev; |
- | |
1369 | struct drm_i915_private *dev_priv = dev->dev_private; |
1352 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
1370 | struct intel_panel *panel = &connector->panel; |
1353 | struct intel_panel *panel = &connector->panel; |
1371 | u16 pwm_freq_hz = dev_priv->vbt.backlight.pwm_freq_hz; |
1354 | u16 pwm_freq_hz = dev_priv->vbt.backlight.pwm_freq_hz; |
1372 | u32 pwm; |
1355 | u32 pwm; |
1373 | 1356 | ||
1374 | if (!pwm_freq_hz) { |
1357 | if (!panel->backlight.hz_to_pwm) { |
1375 | DRM_DEBUG_KMS("backlight frequency not specified in VBT\n"); |
1358 | DRM_DEBUG_KMS("backlight frequency conversion not supported\n"); |
1376 | return 0; |
1359 | return 0; |
1377 | } |
1360 | } |
1378 | 1361 | ||
1379 | if (!panel->backlight.hz_to_pwm) { |
1362 | if (pwm_freq_hz) { |
- | 1363 | DRM_DEBUG_KMS("VBT defined backlight frequency %u Hz\n", |
|
1380 | DRM_DEBUG_KMS("backlight frequency setting from VBT currently not supported on this platform\n"); |
1364 | pwm_freq_hz); |
- | 1365 | } else { |
|
- | 1366 | pwm_freq_hz = 200; |
|
- | 1367 | DRM_DEBUG_KMS("default backlight frequency %u Hz\n", |
|
1381 | return 0; |
1368 | pwm_freq_hz); |
1382 | } |
1369 | } |
1383 | 1370 | ||
1384 | pwm = panel->backlight.hz_to_pwm(connector, pwm_freq_hz); |
1371 | pwm = panel->backlight.hz_to_pwm(connector, pwm_freq_hz); |
1385 | if (!pwm) { |
1372 | if (!pwm) { |
1386 | DRM_DEBUG_KMS("backlight frequency conversion failed\n"); |
1373 | DRM_DEBUG_KMS("backlight frequency conversion failed\n"); |
1387 | return 0; |
1374 | return 0; |
1388 | } |
1375 | } |
1389 | - | ||
1390 | DRM_DEBUG_KMS("backlight frequency %u Hz from VBT\n", pwm_freq_hz); |
- | |
1391 | 1376 | ||
1392 | return pwm; |
1377 | return pwm; |
1393 | } |
1378 | } |
1394 | 1379 | ||
1395 | /* |
1380 | /* |
1396 | * Note: The setup hooks can't assume pipe is set! |
1381 | * Note: The setup hooks can't assume pipe is set! |
1397 | */ |
1382 | */ |
1398 | static u32 get_backlight_min_vbt(struct intel_connector *connector) |
1383 | static u32 get_backlight_min_vbt(struct intel_connector *connector) |
1399 | { |
1384 | { |
1400 | struct drm_device *dev = connector->base.dev; |
- | |
1401 | struct drm_i915_private *dev_priv = dev->dev_private; |
1385 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
1402 | struct intel_panel *panel = &connector->panel; |
1386 | struct intel_panel *panel = &connector->panel; |
1403 | int min; |
1387 | int min; |
1404 | 1388 | ||
1405 | WARN_ON(panel->backlight.max == 0); |
1389 | WARN_ON(panel->backlight.max == 0); |
1406 | 1390 | ||
1407 | /* |
1391 | /* |
1408 | * XXX: If the vbt value is 255, it makes min equal to max, which leads |
1392 | * XXX: If the vbt value is 255, it makes min equal to max, which leads |
1409 | * to problems. There are such machines out there. Either our |
1393 | * to problems. There are such machines out there. Either our |
1410 | * interpretation is wrong or the vbt has bogus data. Or both. Safeguard |
1394 | * interpretation is wrong or the vbt has bogus data. Or both. Safeguard |
1411 | * against this by letting the minimum be at most (arbitrarily chosen) |
1395 | * against this by letting the minimum be at most (arbitrarily chosen) |
1412 | * 25% of the max. |
1396 | * 25% of the max. |
1413 | */ |
1397 | */ |
1414 | min = clamp_t(int, dev_priv->vbt.backlight.min_brightness, 0, 64); |
1398 | min = clamp_t(int, dev_priv->vbt.backlight.min_brightness, 0, 64); |
1415 | if (min != dev_priv->vbt.backlight.min_brightness) { |
1399 | if (min != dev_priv->vbt.backlight.min_brightness) { |
1416 | DRM_DEBUG_KMS("clamping VBT min backlight %d/255 to %d/255\n", |
1400 | DRM_DEBUG_KMS("clamping VBT min backlight %d/255 to %d/255\n", |
1417 | dev_priv->vbt.backlight.min_brightness, min); |
1401 | dev_priv->vbt.backlight.min_brightness, min); |
1418 | } |
1402 | } |
1419 | 1403 | ||
1420 | /* vbt value is a coefficient in range [0..255] */ |
1404 | /* vbt value is a coefficient in range [0..255] */ |
1421 | return scale(min, 0, 255, 0, panel->backlight.max); |
1405 | return scale(min, 0, 255, 0, panel->backlight.max); |
1422 | } |
1406 | } |
1423 | 1407 | ||
1424 | static int lpt_setup_backlight(struct intel_connector *connector, enum pipe unused) |
1408 | static int lpt_setup_backlight(struct intel_connector *connector, enum pipe unused) |
1425 | { |
1409 | { |
1426 | struct drm_device *dev = connector->base.dev; |
- | |
1427 | struct drm_i915_private *dev_priv = dev->dev_private; |
1410 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
1428 | struct intel_panel *panel = &connector->panel; |
1411 | struct intel_panel *panel = &connector->panel; |
1429 | u32 pch_ctl1, pch_ctl2, val; |
1412 | u32 pch_ctl1, pch_ctl2, val; |
1430 | 1413 | ||
1431 | pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1); |
1414 | pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1); |
1432 | panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY; |
1415 | panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY; |
1433 | 1416 | ||
1434 | pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2); |
1417 | pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2); |
1435 | panel->backlight.max = pch_ctl2 >> 16; |
1418 | panel->backlight.max = pch_ctl2 >> 16; |
1436 | 1419 | ||
1437 | if (!panel->backlight.max) |
1420 | if (!panel->backlight.max) |
1438 | panel->backlight.max = get_backlight_max_vbt(connector); |
1421 | panel->backlight.max = get_backlight_max_vbt(connector); |
1439 | 1422 | ||
1440 | if (!panel->backlight.max) |
1423 | if (!panel->backlight.max) |
1441 | return -ENODEV; |
1424 | return -ENODEV; |
1442 | 1425 | ||
1443 | panel->backlight.min = get_backlight_min_vbt(connector); |
1426 | panel->backlight.min = get_backlight_min_vbt(connector); |
1444 | 1427 | ||
1445 | val = lpt_get_backlight(connector); |
1428 | val = lpt_get_backlight(connector); |
1446 | panel->backlight.level = intel_panel_compute_brightness(connector, val); |
1429 | panel->backlight.level = intel_panel_compute_brightness(connector, val); |
1447 | 1430 | ||
1448 | panel->backlight.enabled = (pch_ctl1 & BLM_PCH_PWM_ENABLE) && |
1431 | panel->backlight.enabled = (pch_ctl1 & BLM_PCH_PWM_ENABLE) && |
1449 | panel->backlight.level != 0; |
1432 | panel->backlight.level != 0; |
1450 | 1433 | ||
1451 | return 0; |
1434 | return 0; |
1452 | } |
1435 | } |
1453 | 1436 | ||
1454 | static int pch_setup_backlight(struct intel_connector *connector, enum pipe unused) |
1437 | static int pch_setup_backlight(struct intel_connector *connector, enum pipe unused) |
1455 | { |
1438 | { |
1456 | struct drm_device *dev = connector->base.dev; |
- | |
1457 | struct drm_i915_private *dev_priv = dev->dev_private; |
1439 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
1458 | struct intel_panel *panel = &connector->panel; |
1440 | struct intel_panel *panel = &connector->panel; |
1459 | u32 cpu_ctl2, pch_ctl1, pch_ctl2, val; |
1441 | u32 cpu_ctl2, pch_ctl1, pch_ctl2, val; |
1460 | 1442 | ||
1461 | pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1); |
1443 | pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1); |
1462 | panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY; |
1444 | panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY; |
1463 | 1445 | ||
1464 | pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2); |
1446 | pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2); |
1465 | panel->backlight.max = pch_ctl2 >> 16; |
1447 | panel->backlight.max = pch_ctl2 >> 16; |
1466 | 1448 | ||
1467 | if (!panel->backlight.max) |
1449 | if (!panel->backlight.max) |
1468 | panel->backlight.max = get_backlight_max_vbt(connector); |
1450 | panel->backlight.max = get_backlight_max_vbt(connector); |
1469 | 1451 | ||
1470 | if (!panel->backlight.max) |
1452 | if (!panel->backlight.max) |
1471 | return -ENODEV; |
1453 | return -ENODEV; |
1472 | 1454 | ||
1473 | panel->backlight.min = get_backlight_min_vbt(connector); |
1455 | panel->backlight.min = get_backlight_min_vbt(connector); |
1474 | 1456 | ||
1475 | val = pch_get_backlight(connector); |
1457 | val = pch_get_backlight(connector); |
1476 | panel->backlight.level = intel_panel_compute_brightness(connector, val); |
1458 | panel->backlight.level = intel_panel_compute_brightness(connector, val); |
1477 | 1459 | ||
1478 | cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2); |
1460 | cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2); |
1479 | panel->backlight.enabled = (cpu_ctl2 & BLM_PWM_ENABLE) && |
1461 | panel->backlight.enabled = (cpu_ctl2 & BLM_PWM_ENABLE) && |
1480 | (pch_ctl1 & BLM_PCH_PWM_ENABLE) && panel->backlight.level != 0; |
1462 | (pch_ctl1 & BLM_PCH_PWM_ENABLE) && panel->backlight.level != 0; |
1481 | 1463 | ||
1482 | return 0; |
1464 | return 0; |
1483 | } |
1465 | } |
1484 | 1466 | ||
1485 | static int i9xx_setup_backlight(struct intel_connector *connector, enum pipe unused) |
1467 | static int i9xx_setup_backlight(struct intel_connector *connector, enum pipe unused) |
1486 | { |
1468 | { |
1487 | struct drm_device *dev = connector->base.dev; |
- | |
1488 | struct drm_i915_private *dev_priv = dev->dev_private; |
1469 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
1489 | struct intel_panel *panel = &connector->panel; |
1470 | struct intel_panel *panel = &connector->panel; |
1490 | u32 ctl, val; |
1471 | u32 ctl, val; |
1491 | 1472 | ||
1492 | ctl = I915_READ(BLC_PWM_CTL); |
1473 | ctl = I915_READ(BLC_PWM_CTL); |
1493 | 1474 | ||
1494 | if (IS_GEN2(dev) || IS_I915GM(dev) || IS_I945GM(dev)) |
1475 | if (IS_GEN2(dev_priv) || IS_I915GM(dev_priv) || IS_I945GM(dev_priv)) |
1495 | panel->backlight.combination_mode = ctl & BLM_LEGACY_MODE; |
1476 | panel->backlight.combination_mode = ctl & BLM_LEGACY_MODE; |
1496 | 1477 | ||
1497 | if (IS_PINEVIEW(dev)) |
1478 | if (IS_PINEVIEW(dev_priv)) |
1498 | panel->backlight.active_low_pwm = ctl & BLM_POLARITY_PNV; |
1479 | panel->backlight.active_low_pwm = ctl & BLM_POLARITY_PNV; |
1499 | 1480 | ||
1500 | panel->backlight.max = ctl >> 17; |
1481 | panel->backlight.max = ctl >> 17; |
1501 | 1482 | ||
1502 | if (!panel->backlight.max) { |
1483 | if (!panel->backlight.max) { |
1503 | panel->backlight.max = get_backlight_max_vbt(connector); |
1484 | panel->backlight.max = get_backlight_max_vbt(connector); |
1504 | panel->backlight.max >>= 1; |
1485 | panel->backlight.max >>= 1; |
1505 | } |
1486 | } |
1506 | 1487 | ||
1507 | if (!panel->backlight.max) |
1488 | if (!panel->backlight.max) |
1508 | return -ENODEV; |
1489 | return -ENODEV; |
1509 | 1490 | ||
1510 | if (panel->backlight.combination_mode) |
1491 | if (panel->backlight.combination_mode) |
1511 | panel->backlight.max *= 0xff; |
1492 | panel->backlight.max *= 0xff; |
1512 | 1493 | ||
1513 | panel->backlight.min = get_backlight_min_vbt(connector); |
1494 | panel->backlight.min = get_backlight_min_vbt(connector); |
1514 | 1495 | ||
1515 | val = i9xx_get_backlight(connector); |
1496 | val = i9xx_get_backlight(connector); |
1516 | panel->backlight.level = intel_panel_compute_brightness(connector, val); |
1497 | panel->backlight.level = intel_panel_compute_brightness(connector, val); |
1517 | 1498 | ||
1518 | panel->backlight.enabled = panel->backlight.level != 0; |
1499 | panel->backlight.enabled = panel->backlight.level != 0; |
1519 | 1500 | ||
1520 | return 0; |
1501 | return 0; |
1521 | } |
1502 | } |
1522 | 1503 | ||
1523 | static int i965_setup_backlight(struct intel_connector *connector, enum pipe unused) |
1504 | static int i965_setup_backlight(struct intel_connector *connector, enum pipe unused) |
1524 | { |
1505 | { |
1525 | struct drm_device *dev = connector->base.dev; |
- | |
1526 | struct drm_i915_private *dev_priv = dev->dev_private; |
1506 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
1527 | struct intel_panel *panel = &connector->panel; |
1507 | struct intel_panel *panel = &connector->panel; |
1528 | u32 ctl, ctl2, val; |
1508 | u32 ctl, ctl2, val; |
1529 | 1509 | ||
1530 | ctl2 = I915_READ(BLC_PWM_CTL2); |
1510 | ctl2 = I915_READ(BLC_PWM_CTL2); |
1531 | panel->backlight.combination_mode = ctl2 & BLM_COMBINATION_MODE; |
1511 | panel->backlight.combination_mode = ctl2 & BLM_COMBINATION_MODE; |
1532 | panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965; |
1512 | panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965; |
1533 | 1513 | ||
1534 | ctl = I915_READ(BLC_PWM_CTL); |
1514 | ctl = I915_READ(BLC_PWM_CTL); |
1535 | panel->backlight.max = ctl >> 16; |
1515 | panel->backlight.max = ctl >> 16; |
1536 | 1516 | ||
1537 | if (!panel->backlight.max) |
1517 | if (!panel->backlight.max) |
1538 | panel->backlight.max = get_backlight_max_vbt(connector); |
1518 | panel->backlight.max = get_backlight_max_vbt(connector); |
1539 | 1519 | ||
1540 | if (!panel->backlight.max) |
1520 | if (!panel->backlight.max) |
1541 | return -ENODEV; |
1521 | return -ENODEV; |
1542 | 1522 | ||
1543 | if (panel->backlight.combination_mode) |
1523 | if (panel->backlight.combination_mode) |
1544 | panel->backlight.max *= 0xff; |
1524 | panel->backlight.max *= 0xff; |
1545 | 1525 | ||
1546 | panel->backlight.min = get_backlight_min_vbt(connector); |
1526 | panel->backlight.min = get_backlight_min_vbt(connector); |
1547 | 1527 | ||
1548 | val = i9xx_get_backlight(connector); |
1528 | val = i9xx_get_backlight(connector); |
1549 | panel->backlight.level = intel_panel_compute_brightness(connector, val); |
1529 | panel->backlight.level = intel_panel_compute_brightness(connector, val); |
1550 | 1530 | ||
1551 | panel->backlight.enabled = (ctl2 & BLM_PWM_ENABLE) && |
1531 | panel->backlight.enabled = (ctl2 & BLM_PWM_ENABLE) && |
1552 | panel->backlight.level != 0; |
1532 | panel->backlight.level != 0; |
1553 | 1533 | ||
1554 | return 0; |
1534 | return 0; |
1555 | } |
1535 | } |
1556 | 1536 | ||
1557 | static int vlv_setup_backlight(struct intel_connector *connector, enum pipe pipe) |
1537 | static int vlv_setup_backlight(struct intel_connector *connector, enum pipe pipe) |
1558 | { |
1538 | { |
1559 | struct drm_device *dev = connector->base.dev; |
- | |
1560 | struct drm_i915_private *dev_priv = dev->dev_private; |
1539 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
1561 | struct intel_panel *panel = &connector->panel; |
1540 | struct intel_panel *panel = &connector->panel; |
1562 | u32 ctl, ctl2, val; |
1541 | u32 ctl, ctl2, val; |
1563 | 1542 | ||
1564 | if (WARN_ON(pipe != PIPE_A && pipe != PIPE_B)) |
1543 | if (WARN_ON(pipe != PIPE_A && pipe != PIPE_B)) |
1565 | return -ENODEV; |
1544 | return -ENODEV; |
1566 | 1545 | ||
1567 | ctl2 = I915_READ(VLV_BLC_PWM_CTL2(pipe)); |
1546 | ctl2 = I915_READ(VLV_BLC_PWM_CTL2(pipe)); |
1568 | panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965; |
1547 | panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965; |
1569 | 1548 | ||
1570 | ctl = I915_READ(VLV_BLC_PWM_CTL(pipe)); |
1549 | ctl = I915_READ(VLV_BLC_PWM_CTL(pipe)); |
1571 | panel->backlight.max = ctl >> 16; |
1550 | panel->backlight.max = ctl >> 16; |
1572 | 1551 | ||
1573 | if (!panel->backlight.max) |
1552 | if (!panel->backlight.max) |
1574 | panel->backlight.max = get_backlight_max_vbt(connector); |
1553 | panel->backlight.max = get_backlight_max_vbt(connector); |
1575 | 1554 | ||
1576 | if (!panel->backlight.max) |
1555 | if (!panel->backlight.max) |
1577 | return -ENODEV; |
1556 | return -ENODEV; |
1578 | 1557 | ||
1579 | panel->backlight.min = get_backlight_min_vbt(connector); |
1558 | panel->backlight.min = get_backlight_min_vbt(connector); |
1580 | 1559 | ||
1581 | val = _vlv_get_backlight(dev, pipe); |
1560 | val = _vlv_get_backlight(dev_priv, pipe); |
1582 | panel->backlight.level = intel_panel_compute_brightness(connector, val); |
1561 | panel->backlight.level = intel_panel_compute_brightness(connector, val); |
1583 | 1562 | ||
1584 | panel->backlight.enabled = (ctl2 & BLM_PWM_ENABLE) && |
1563 | panel->backlight.enabled = (ctl2 & BLM_PWM_ENABLE) && |
1585 | panel->backlight.level != 0; |
1564 | panel->backlight.level != 0; |
1586 | 1565 | ||
1587 | return 0; |
1566 | return 0; |
1588 | } |
1567 | } |
1589 | 1568 | ||
1590 | static int |
1569 | static int |
1591 | bxt_setup_backlight(struct intel_connector *connector, enum pipe unused) |
1570 | bxt_setup_backlight(struct intel_connector *connector, enum pipe unused) |
1592 | { |
1571 | { |
1593 | struct drm_device *dev = connector->base.dev; |
- | |
1594 | struct drm_i915_private *dev_priv = dev->dev_private; |
1572 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
1595 | struct intel_panel *panel = &connector->panel; |
1573 | struct intel_panel *panel = &connector->panel; |
1596 | u32 pwm_ctl, val; |
1574 | u32 pwm_ctl, val; |
1597 | 1575 | ||
1598 | /* |
1576 | /* |
1599 | * For BXT hard coding the Backlight controller to 0. |
1577 | * For BXT hard coding the Backlight controller to 0. |
1600 | * TODO : Read the controller value from VBT and generalize |
1578 | * TODO : Read the controller value from VBT and generalize |
1601 | */ |
1579 | */ |
1602 | panel->backlight.controller = 0; |
1580 | panel->backlight.controller = 0; |
1603 | 1581 | ||
1604 | pwm_ctl = I915_READ(BXT_BLC_PWM_CTL(panel->backlight.controller)); |
1582 | pwm_ctl = I915_READ(BXT_BLC_PWM_CTL(panel->backlight.controller)); |
1605 | 1583 | ||
1606 | /* Keeping the check if controller 1 is to be programmed. |
1584 | /* Keeping the check if controller 1 is to be programmed. |
1607 | * This will come into affect once the VBT parsing |
1585 | * This will come into affect once the VBT parsing |
1608 | * is fixed for controller selection, and controller 1 is used |
1586 | * is fixed for controller selection, and controller 1 is used |
1609 | * for a prticular display configuration. |
1587 | * for a prticular display configuration. |
1610 | */ |
1588 | */ |
1611 | if (panel->backlight.controller == 1) { |
1589 | if (panel->backlight.controller == 1) { |
1612 | val = I915_READ(UTIL_PIN_CTL); |
1590 | val = I915_READ(UTIL_PIN_CTL); |
1613 | panel->backlight.util_pin_active_low = |
1591 | panel->backlight.util_pin_active_low = |
1614 | val & UTIL_PIN_POLARITY; |
1592 | val & UTIL_PIN_POLARITY; |
1615 | } |
1593 | } |
1616 | 1594 | ||
1617 | panel->backlight.active_low_pwm = pwm_ctl & BXT_BLC_PWM_POLARITY; |
1595 | panel->backlight.active_low_pwm = pwm_ctl & BXT_BLC_PWM_POLARITY; |
1618 | panel->backlight.max = |
1596 | panel->backlight.max = |
1619 | I915_READ(BXT_BLC_PWM_FREQ(panel->backlight.controller)); |
1597 | I915_READ(BXT_BLC_PWM_FREQ(panel->backlight.controller)); |
1620 | 1598 | ||
1621 | if (!panel->backlight.max) |
1599 | if (!panel->backlight.max) |
1622 | panel->backlight.max = get_backlight_max_vbt(connector); |
1600 | panel->backlight.max = get_backlight_max_vbt(connector); |
1623 | 1601 | ||
1624 | if (!panel->backlight.max) |
1602 | if (!panel->backlight.max) |
1625 | return -ENODEV; |
1603 | return -ENODEV; |
1626 | 1604 | ||
1627 | val = bxt_get_backlight(connector); |
1605 | val = bxt_get_backlight(connector); |
1628 | panel->backlight.level = intel_panel_compute_brightness(connector, val); |
1606 | panel->backlight.level = intel_panel_compute_brightness(connector, val); |
1629 | 1607 | ||
1630 | panel->backlight.enabled = (pwm_ctl & BXT_BLC_PWM_ENABLE) && |
1608 | panel->backlight.enabled = (pwm_ctl & BXT_BLC_PWM_ENABLE) && |
1631 | panel->backlight.level != 0; |
1609 | panel->backlight.level != 0; |
1632 | 1610 | ||
1633 | return 0; |
1611 | return 0; |
1634 | } |
1612 | } |
1635 | 1613 | ||
1636 | static int pwm_setup_backlight(struct intel_connector *connector, |
1614 | static int pwm_setup_backlight(struct intel_connector *connector, |
1637 | enum pipe pipe) |
1615 | enum pipe pipe) |
1638 | { |
1616 | { |
1639 | struct drm_device *dev = connector->base.dev; |
1617 | struct drm_device *dev = connector->base.dev; |
1640 | struct intel_panel *panel = &connector->panel; |
1618 | struct intel_panel *panel = &connector->panel; |
1641 | int retval; |
1619 | int retval; |
1642 | 1620 | ||
1643 | /* Get the PWM chip for backlight control */ |
1621 | /* Get the PWM chip for backlight control */ |
1644 | panel->backlight.pwm = pwm_get(dev->dev, "pwm_backlight"); |
1622 | panel->backlight.pwm = pwm_get(dev->dev, "pwm_backlight"); |
1645 | if (IS_ERR(panel->backlight.pwm)) { |
1623 | if (IS_ERR(panel->backlight.pwm)) { |
1646 | DRM_ERROR("Failed to own the pwm chip\n"); |
1624 | DRM_ERROR("Failed to own the pwm chip\n"); |
1647 | panel->backlight.pwm = NULL; |
1625 | panel->backlight.pwm = NULL; |
1648 | return -ENODEV; |
1626 | return -ENODEV; |
1649 | } |
1627 | } |
1650 | 1628 | ||
1651 | retval = pwm_config(panel->backlight.pwm, CRC_PMIC_PWM_PERIOD_NS, |
1629 | retval = pwm_config(panel->backlight.pwm, CRC_PMIC_PWM_PERIOD_NS, |
1652 | CRC_PMIC_PWM_PERIOD_NS); |
1630 | CRC_PMIC_PWM_PERIOD_NS); |
1653 | if (retval < 0) { |
1631 | if (retval < 0) { |
1654 | DRM_ERROR("Failed to configure the pwm chip\n"); |
1632 | DRM_ERROR("Failed to configure the pwm chip\n"); |
1655 | pwm_put(panel->backlight.pwm); |
1633 | pwm_put(panel->backlight.pwm); |
1656 | panel->backlight.pwm = NULL; |
1634 | panel->backlight.pwm = NULL; |
1657 | return retval; |
1635 | return retval; |
1658 | } |
1636 | } |
1659 | 1637 | ||
1660 | panel->backlight.min = 0; /* 0% */ |
1638 | panel->backlight.min = 0; /* 0% */ |
1661 | panel->backlight.max = 100; /* 100% */ |
1639 | panel->backlight.max = 100; /* 100% */ |
1662 | panel->backlight.level = DIV_ROUND_UP( |
1640 | panel->backlight.level = DIV_ROUND_UP( |
1663 | pwm_get_duty_cycle(panel->backlight.pwm) * 100, |
1641 | pwm_get_duty_cycle(panel->backlight.pwm) * 100, |
1664 | CRC_PMIC_PWM_PERIOD_NS); |
1642 | CRC_PMIC_PWM_PERIOD_NS); |
1665 | panel->backlight.enabled = panel->backlight.level != 0; |
1643 | panel->backlight.enabled = panel->backlight.level != 0; |
1666 | 1644 | ||
1667 | return 0; |
1645 | return 0; |
1668 | } |
1646 | } |
1669 | 1647 | ||
1670 | int intel_panel_setup_backlight(struct drm_connector *connector, enum pipe pipe) |
1648 | int intel_panel_setup_backlight(struct drm_connector *connector, enum pipe pipe) |
1671 | { |
1649 | { |
1672 | struct drm_device *dev = connector->dev; |
- | |
1673 | struct drm_i915_private *dev_priv = dev->dev_private; |
1650 | struct drm_i915_private *dev_priv = to_i915(connector->dev); |
1674 | struct intel_connector *intel_connector = to_intel_connector(connector); |
1651 | struct intel_connector *intel_connector = to_intel_connector(connector); |
1675 | struct intel_panel *panel = &intel_connector->panel; |
1652 | struct intel_panel *panel = &intel_connector->panel; |
1676 | int ret; |
1653 | int ret; |
1677 | 1654 | ||
1678 | if (!dev_priv->vbt.backlight.present) { |
1655 | if (!dev_priv->vbt.backlight.present) { |
1679 | if (dev_priv->quirks & QUIRK_BACKLIGHT_PRESENT) { |
1656 | if (dev_priv->quirks & QUIRK_BACKLIGHT_PRESENT) { |
1680 | DRM_DEBUG_KMS("no backlight present per VBT, but present per quirk\n"); |
1657 | DRM_DEBUG_KMS("no backlight present per VBT, but present per quirk\n"); |
1681 | } else { |
1658 | } else { |
1682 | DRM_DEBUG_KMS("no backlight present per VBT\n"); |
1659 | DRM_DEBUG_KMS("no backlight present per VBT\n"); |
1683 | return 0; |
1660 | return 0; |
1684 | } |
1661 | } |
1685 | } |
1662 | } |
1686 | 1663 | ||
1687 | /* ensure intel_panel has been initialized first */ |
1664 | /* ensure intel_panel has been initialized first */ |
1688 | if (WARN_ON(!panel->backlight.setup)) |
1665 | if (WARN_ON(!panel->backlight.setup)) |
1689 | return -ENODEV; |
1666 | return -ENODEV; |
1690 | 1667 | ||
1691 | /* set level and max in panel struct */ |
1668 | /* set level and max in panel struct */ |
1692 | mutex_lock(&dev_priv->backlight_lock); |
1669 | mutex_lock(&dev_priv->backlight_lock); |
1693 | ret = panel->backlight.setup(intel_connector, pipe); |
1670 | ret = panel->backlight.setup(intel_connector, pipe); |
1694 | mutex_unlock(&dev_priv->backlight_lock); |
1671 | mutex_unlock(&dev_priv->backlight_lock); |
1695 | 1672 | ||
1696 | if (ret) { |
1673 | if (ret) { |
1697 | DRM_DEBUG_KMS("failed to setup backlight for connector %s\n", |
1674 | DRM_DEBUG_KMS("failed to setup backlight for connector %s\n", |
1698 | connector->name); |
1675 | connector->name); |
1699 | return ret; |
1676 | return ret; |
1700 | } |
1677 | } |
1701 | 1678 | ||
1702 | panel->backlight.present = true; |
1679 | panel->backlight.present = true; |
1703 | 1680 | ||
1704 | DRM_DEBUG_KMS("Connector %s backlight initialized, %s, brightness %u/%u\n", |
1681 | DRM_DEBUG_KMS("Connector %s backlight initialized, %s, brightness %u/%u\n", |
1705 | connector->name, |
1682 | connector->name, |
1706 | panel->backlight.enabled ? "enabled" : "disabled", |
1683 | panel->backlight.enabled ? "enabled" : "disabled", |
1707 | panel->backlight.level, panel->backlight.max); |
1684 | panel->backlight.level, panel->backlight.max); |
1708 | 1685 | ||
1709 | return 0; |
1686 | return 0; |
1710 | } |
1687 | } |
1711 | 1688 | ||
1712 | void intel_panel_destroy_backlight(struct drm_connector *connector) |
1689 | void intel_panel_destroy_backlight(struct drm_connector *connector) |
1713 | { |
1690 | { |
1714 | struct intel_connector *intel_connector = to_intel_connector(connector); |
1691 | struct intel_connector *intel_connector = to_intel_connector(connector); |
1715 | struct intel_panel *panel = &intel_connector->panel; |
1692 | struct intel_panel *panel = &intel_connector->panel; |
1716 | 1693 | ||
1717 | /* dispose of the pwm */ |
1694 | /* dispose of the pwm */ |
1718 | if (panel->backlight.pwm) |
1695 | if (panel->backlight.pwm) |
1719 | pwm_put(panel->backlight.pwm); |
1696 | pwm_put(panel->backlight.pwm); |
1720 | 1697 | ||
1721 | panel->backlight.present = false; |
1698 | panel->backlight.present = false; |
1722 | } |
1699 | } |
1723 | 1700 | ||
1724 | /* Set up chip specific backlight functions */ |
1701 | /* Set up chip specific backlight functions */ |
1725 | static void |
1702 | static void |
1726 | intel_panel_init_backlight_funcs(struct intel_panel *panel) |
1703 | intel_panel_init_backlight_funcs(struct intel_panel *panel) |
1727 | { |
1704 | { |
1728 | struct intel_connector *intel_connector = |
1705 | struct intel_connector *connector = |
1729 | container_of(panel, struct intel_connector, panel); |
1706 | container_of(panel, struct intel_connector, panel); |
1730 | struct drm_device *dev = intel_connector->base.dev; |
- | |
1731 | struct drm_i915_private *dev_priv = dev->dev_private; |
1707 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
1732 | 1708 | ||
1733 | if (IS_BROXTON(dev)) { |
1709 | if (IS_BROXTON(dev_priv)) { |
1734 | panel->backlight.setup = bxt_setup_backlight; |
1710 | panel->backlight.setup = bxt_setup_backlight; |
1735 | panel->backlight.enable = bxt_enable_backlight; |
1711 | panel->backlight.enable = bxt_enable_backlight; |
1736 | panel->backlight.disable = bxt_disable_backlight; |
1712 | panel->backlight.disable = bxt_disable_backlight; |
1737 | panel->backlight.set = bxt_set_backlight; |
1713 | panel->backlight.set = bxt_set_backlight; |
1738 | panel->backlight.get = bxt_get_backlight; |
1714 | panel->backlight.get = bxt_get_backlight; |
- | 1715 | panel->backlight.hz_to_pwm = bxt_hz_to_pwm; |
|
1739 | } else if (HAS_PCH_LPT(dev) || HAS_PCH_SPT(dev)) { |
1716 | } else if (HAS_PCH_LPT(dev_priv) || HAS_PCH_SPT(dev_priv)) { |
1740 | panel->backlight.setup = lpt_setup_backlight; |
1717 | panel->backlight.setup = lpt_setup_backlight; |
1741 | panel->backlight.enable = lpt_enable_backlight; |
1718 | panel->backlight.enable = lpt_enable_backlight; |
1742 | panel->backlight.disable = lpt_disable_backlight; |
1719 | panel->backlight.disable = lpt_disable_backlight; |
1743 | panel->backlight.set = lpt_set_backlight; |
1720 | panel->backlight.set = lpt_set_backlight; |
1744 | panel->backlight.get = lpt_get_backlight; |
1721 | panel->backlight.get = lpt_get_backlight; |
1745 | if (HAS_PCH_LPT(dev)) |
1722 | if (HAS_PCH_LPT(dev_priv)) |
1746 | panel->backlight.hz_to_pwm = lpt_hz_to_pwm; |
1723 | panel->backlight.hz_to_pwm = lpt_hz_to_pwm; |
1747 | else |
1724 | else |
1748 | panel->backlight.hz_to_pwm = spt_hz_to_pwm; |
1725 | panel->backlight.hz_to_pwm = spt_hz_to_pwm; |
1749 | } else if (HAS_PCH_SPLIT(dev)) { |
1726 | } else if (HAS_PCH_SPLIT(dev_priv)) { |
1750 | panel->backlight.setup = pch_setup_backlight; |
1727 | panel->backlight.setup = pch_setup_backlight; |
1751 | panel->backlight.enable = pch_enable_backlight; |
1728 | panel->backlight.enable = pch_enable_backlight; |
1752 | panel->backlight.disable = pch_disable_backlight; |
1729 | panel->backlight.disable = pch_disable_backlight; |
1753 | panel->backlight.set = pch_set_backlight; |
1730 | panel->backlight.set = pch_set_backlight; |
1754 | panel->backlight.get = pch_get_backlight; |
1731 | panel->backlight.get = pch_get_backlight; |
1755 | panel->backlight.hz_to_pwm = pch_hz_to_pwm; |
1732 | panel->backlight.hz_to_pwm = pch_hz_to_pwm; |
1756 | } else if (IS_VALLEYVIEW(dev)) { |
1733 | } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { |
1757 | if (dev_priv->vbt.has_mipi) { |
1734 | if (dev_priv->vbt.has_mipi) { |
1758 | panel->backlight.setup = pwm_setup_backlight; |
1735 | panel->backlight.setup = pwm_setup_backlight; |
1759 | panel->backlight.enable = pwm_enable_backlight; |
1736 | panel->backlight.enable = pwm_enable_backlight; |
1760 | panel->backlight.disable = pwm_disable_backlight; |
1737 | panel->backlight.disable = pwm_disable_backlight; |
1761 | panel->backlight.set = pwm_set_backlight; |
1738 | panel->backlight.set = pwm_set_backlight; |
1762 | panel->backlight.get = pwm_get_backlight; |
1739 | panel->backlight.get = pwm_get_backlight; |
1763 | } else { |
1740 | } else { |
1764 | panel->backlight.setup = vlv_setup_backlight; |
1741 | panel->backlight.setup = vlv_setup_backlight; |
1765 | panel->backlight.enable = vlv_enable_backlight; |
1742 | panel->backlight.enable = vlv_enable_backlight; |
1766 | panel->backlight.disable = vlv_disable_backlight; |
1743 | panel->backlight.disable = vlv_disable_backlight; |
1767 | panel->backlight.set = vlv_set_backlight; |
1744 | panel->backlight.set = vlv_set_backlight; |
1768 | panel->backlight.get = vlv_get_backlight; |
1745 | panel->backlight.get = vlv_get_backlight; |
1769 | panel->backlight.hz_to_pwm = vlv_hz_to_pwm; |
1746 | panel->backlight.hz_to_pwm = vlv_hz_to_pwm; |
1770 | } |
1747 | } |
1771 | } else if (IS_GEN4(dev)) { |
1748 | } else if (IS_GEN4(dev_priv)) { |
1772 | panel->backlight.setup = i965_setup_backlight; |
1749 | panel->backlight.setup = i965_setup_backlight; |
1773 | panel->backlight.enable = i965_enable_backlight; |
1750 | panel->backlight.enable = i965_enable_backlight; |
1774 | panel->backlight.disable = i965_disable_backlight; |
1751 | panel->backlight.disable = i965_disable_backlight; |
1775 | panel->backlight.set = i9xx_set_backlight; |
1752 | panel->backlight.set = i9xx_set_backlight; |
1776 | panel->backlight.get = i9xx_get_backlight; |
1753 | panel->backlight.get = i9xx_get_backlight; |
1777 | panel->backlight.hz_to_pwm = i965_hz_to_pwm; |
1754 | panel->backlight.hz_to_pwm = i965_hz_to_pwm; |
1778 | } else { |
1755 | } else { |
1779 | panel->backlight.setup = i9xx_setup_backlight; |
1756 | panel->backlight.setup = i9xx_setup_backlight; |
1780 | panel->backlight.enable = i9xx_enable_backlight; |
1757 | panel->backlight.enable = i9xx_enable_backlight; |
1781 | panel->backlight.disable = i9xx_disable_backlight; |
1758 | panel->backlight.disable = i9xx_disable_backlight; |
1782 | panel->backlight.set = i9xx_set_backlight; |
1759 | panel->backlight.set = i9xx_set_backlight; |
1783 | panel->backlight.get = i9xx_get_backlight; |
1760 | panel->backlight.get = i9xx_get_backlight; |
1784 | panel->backlight.hz_to_pwm = i9xx_hz_to_pwm; |
1761 | panel->backlight.hz_to_pwm = i9xx_hz_to_pwm; |
1785 | } |
1762 | } |
1786 | } |
1763 | } |
1787 | 1764 | ||
1788 | int intel_panel_init(struct intel_panel *panel, |
1765 | int intel_panel_init(struct intel_panel *panel, |
1789 | struct drm_display_mode *fixed_mode, |
1766 | struct drm_display_mode *fixed_mode, |
1790 | struct drm_display_mode *downclock_mode) |
1767 | struct drm_display_mode *downclock_mode) |
1791 | { |
1768 | { |
1792 | intel_panel_init_backlight_funcs(panel); |
1769 | intel_panel_init_backlight_funcs(panel); |
1793 | 1770 | ||
1794 | panel->fixed_mode = fixed_mode; |
1771 | panel->fixed_mode = fixed_mode; |
1795 | panel->downclock_mode = downclock_mode; |
1772 | panel->downclock_mode = downclock_mode; |
1796 | 1773 | ||
1797 | return 0; |
1774 | return 0; |
1798 | } |
1775 | } |
1799 | 1776 | ||
1800 | void intel_panel_fini(struct intel_panel *panel) |
1777 | void intel_panel_fini(struct intel_panel *panel) |
1801 | { |
1778 | { |
1802 | struct intel_connector *intel_connector = |
1779 | struct intel_connector *intel_connector = |
1803 | container_of(panel, struct intel_connector, panel); |
1780 | container_of(panel, struct intel_connector, panel); |
1804 | 1781 | ||
1805 | if (panel->fixed_mode) |
1782 | if (panel->fixed_mode) |
1806 | drm_mode_destroy(intel_connector->base.dev, panel->fixed_mode); |
1783 | drm_mode_destroy(intel_connector->base.dev, panel->fixed_mode); |
1807 | 1784 | ||
1808 | if (panel->downclock_mode) |
1785 | if (panel->downclock_mode) |
1809 | drm_mode_destroy(intel_connector->base.dev, |
1786 | drm_mode_destroy(intel_connector->base.dev, |
1810 | panel->downclock_mode); |
1787 | panel->downclock_mode); |
1811 | } |
1788 | } |
1812 | 1789 | ||
1813 | void intel_backlight_register(struct drm_device *dev) |
1790 | void intel_backlight_register(struct drm_device *dev) |
1814 | { |
1791 | { |
1815 | struct intel_connector *connector; |
1792 | struct intel_connector *connector; |
1816 | 1793 | ||
1817 | list_for_each_entry(connector, &dev->mode_config.connector_list, base.head) |
1794 | for_each_intel_connector(dev, connector) |
1818 | intel_backlight_device_register(connector); |
1795 | intel_backlight_device_register(connector); |
1819 | } |
1796 | } |
1820 | 1797 | ||
1821 | void intel_backlight_unregister(struct drm_device *dev) |
1798 | void intel_backlight_unregister(struct drm_device *dev) |
1822 | { |
1799 | { |
1823 | struct intel_connector *connector; |
1800 | struct intel_connector *connector; |
1824 | 1801 | ||
1825 | list_for_each_entry(connector, &dev->mode_config.connector_list, base.head) |
1802 | for_each_intel_connector(dev, connector) |
1826 | intel_backlight_device_unregister(connector); |
1803 | intel_backlight_device_unregister(connector); |
1827 | }>=>><>><>><>><>><>=><=>>>>><>><>><>>><>><>>><>><>><>>>> |
1804 | }>=>><>><>><>><>><>=><=>>>>><>><>><>>><>><>>><>><>><>>>> |