Rev 3746 | Rev 4293 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3746 | Rev 4104 | ||
---|---|---|---|
Line 34... | Line 34... | ||
34 | #include "intel_drv.h" |
34 | #include "intel_drv.h" |
Line 35... | Line 35... | ||
35 | 35 | ||
Line 36... | Line 36... | ||
36 | #define PCI_LBPC 0xf4 /* legacy/combination backlight modes */ |
36 | #define PCI_LBPC 0xf4 /* legacy/combination backlight modes */ |
37 | 37 | ||
38 | void |
38 | void |
39 | intel_fixed_panel_mode(struct drm_display_mode *fixed_mode, |
39 | intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode, |
40 | struct drm_display_mode *adjusted_mode) |
- | |
41 | { |
- | |
42 | adjusted_mode->hdisplay = fixed_mode->hdisplay; |
- | |
43 | adjusted_mode->hsync_start = fixed_mode->hsync_start; |
- | |
44 | adjusted_mode->hsync_end = fixed_mode->hsync_end; |
- | |
45 | adjusted_mode->htotal = fixed_mode->htotal; |
- | |
46 | - | ||
47 | adjusted_mode->vdisplay = fixed_mode->vdisplay; |
40 | struct drm_display_mode *adjusted_mode) |
48 | adjusted_mode->vsync_start = fixed_mode->vsync_start; |
- | |
Line 49... | Line 41... | ||
49 | adjusted_mode->vsync_end = fixed_mode->vsync_end; |
41 | { |
50 | adjusted_mode->vtotal = fixed_mode->vtotal; |
42 | drm_mode_copy(adjusted_mode, fixed_mode); |
Line 51... | Line 43... | ||
51 | 43 | ||
52 | adjusted_mode->clock = fixed_mode->clock; |
44 | drm_mode_set_crtcinfo(adjusted_mode, 0); |
53 | } |
45 | } |
- | 46 | ||
54 | 47 | /* adjusted_mode has been preset to be the panel's fixed mode */ |
|
55 | /* adjusted_mode has been preset to be the panel's fixed mode */ |
- | |
56 | void |
- | |
57 | intel_pch_panel_fitting(struct drm_device *dev, |
48 | void |
58 | int fitting_mode, |
49 | intel_pch_panel_fitting(struct intel_crtc *intel_crtc, |
59 | const struct drm_display_mode *mode, |
50 | struct intel_crtc_config *pipe_config, |
Line -... | Line 51... | ||
- | 51 | int fitting_mode) |
|
- | 52 | { |
|
- | 53 | struct drm_display_mode *mode, *adjusted_mode; |
|
60 | struct drm_display_mode *adjusted_mode) |
54 | int x, y, width, height; |
Line 61... | Line 55... | ||
61 | { |
55 | |
62 | struct drm_i915_private *dev_priv = dev->dev_private; |
56 | mode = &pipe_config->requested_mode; |
63 | int x, y, width, height; |
57 | adjusted_mode = &pipe_config->adjusted_mode; |
Line 102... | Line 96... | ||
102 | height = adjusted_mode->vdisplay; |
96 | height = adjusted_mode->vdisplay; |
103 | } |
97 | } |
104 | } |
98 | } |
105 | break; |
99 | break; |
Line 106... | Line -... | ||
106 | - | ||
107 | default: |
100 | |
108 | case DRM_MODE_SCALE_FULLSCREEN: |
101 | case DRM_MODE_SCALE_FULLSCREEN: |
109 | x = y = 0; |
102 | x = y = 0; |
110 | width = adjusted_mode->hdisplay; |
103 | width = adjusted_mode->hdisplay; |
111 | height = adjusted_mode->vdisplay; |
104 | height = adjusted_mode->vdisplay; |
- | 105 | break; |
|
- | 106 | ||
- | 107 | default: |
|
- | 108 | WARN(1, "bad panel fit mode: %d\n", fitting_mode); |
|
112 | break; |
109 | return; |
Line 113... | Line 110... | ||
113 | } |
110 | } |
114 | 111 | ||
115 | done: |
112 | done: |
- | 113 | pipe_config->pch_pfit.pos = (x << 16) | y; |
|
- | 114 | pipe_config->pch_pfit.size = (width << 16) | height; |
|
- | 115 | pipe_config->pch_pfit.enabled = pipe_config->pch_pfit.size != 0; |
|
- | 116 | } |
|
- | 117 | ||
- | 118 | static void |
|
- | 119 | centre_horizontally(struct drm_display_mode *mode, |
|
- | 120 | int width) |
|
- | 121 | { |
|
- | 122 | u32 border, sync_pos, blank_width, sync_width; |
|
- | 123 | ||
- | 124 | /* keep the hsync and hblank widths constant */ |
|
- | 125 | sync_width = mode->crtc_hsync_end - mode->crtc_hsync_start; |
|
- | 126 | blank_width = mode->crtc_hblank_end - mode->crtc_hblank_start; |
|
- | 127 | sync_pos = (blank_width - sync_width + 1) / 2; |
|
- | 128 | ||
- | 129 | border = (mode->hdisplay - width + 1) / 2; |
|
- | 130 | border += border & 1; /* make the border even */ |
|
- | 131 | ||
- | 132 | mode->crtc_hdisplay = width; |
|
- | 133 | mode->crtc_hblank_start = width + border; |
|
- | 134 | mode->crtc_hblank_end = mode->crtc_hblank_start + blank_width; |
|
- | 135 | ||
- | 136 | mode->crtc_hsync_start = mode->crtc_hblank_start + sync_pos; |
|
- | 137 | mode->crtc_hsync_end = mode->crtc_hsync_start + sync_width; |
|
- | 138 | } |
|
- | 139 | ||
- | 140 | static void |
|
- | 141 | centre_vertically(struct drm_display_mode *mode, |
|
- | 142 | int height) |
|
- | 143 | { |
|
- | 144 | u32 border, sync_pos, blank_width, sync_width; |
|
- | 145 | ||
- | 146 | /* keep the vsync and vblank widths constant */ |
|
- | 147 | sync_width = mode->crtc_vsync_end - mode->crtc_vsync_start; |
|
- | 148 | blank_width = mode->crtc_vblank_end - mode->crtc_vblank_start; |
|
- | 149 | sync_pos = (blank_width - sync_width + 1) / 2; |
|
- | 150 | ||
- | 151 | border = (mode->vdisplay - height + 1) / 2; |
|
- | 152 | ||
- | 153 | mode->crtc_vdisplay = height; |
|
- | 154 | mode->crtc_vblank_start = height + border; |
|
- | 155 | mode->crtc_vblank_end = mode->crtc_vblank_start + blank_width; |
|
- | 156 | ||
- | 157 | mode->crtc_vsync_start = mode->crtc_vblank_start + sync_pos; |
|
- | 158 | mode->crtc_vsync_end = mode->crtc_vsync_start + sync_width; |
|
- | 159 | } |
|
- | 160 | ||
- | 161 | static inline u32 panel_fitter_scaling(u32 source, u32 target) |
|
- | 162 | { |
|
- | 163 | /* |
|
- | 164 | * Floating point operation is not supported. So the FACTOR |
|
- | 165 | * is defined, which can avoid the floating point computation |
|
- | 166 | * when calculating the panel ratio. |
|
- | 167 | */ |
|
- | 168 | #define ACCURACY 12 |
|
- | 169 | #define FACTOR (1 << ACCURACY) |
|
- | 170 | u32 ratio = source * FACTOR / target; |
|
- | 171 | return (FACTOR * ratio + FACTOR/2) / FACTOR; |
|
- | 172 | } |
|
- | 173 | ||
- | 174 | void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc, |
|
- | 175 | struct intel_crtc_config *pipe_config, |
|
- | 176 | int fitting_mode) |
|
- | 177 | { |
|
- | 178 | struct drm_device *dev = intel_crtc->base.dev; |
|
- | 179 | u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0; |
|
- | 180 | struct drm_display_mode *mode, *adjusted_mode; |
|
- | 181 | ||
- | 182 | mode = &pipe_config->requested_mode; |
|
- | 183 | adjusted_mode = &pipe_config->adjusted_mode; |
|
- | 184 | ||
- | 185 | /* Native modes don't need fitting */ |
|
- | 186 | if (adjusted_mode->hdisplay == mode->hdisplay && |
|
- | 187 | adjusted_mode->vdisplay == mode->vdisplay) |
|
- | 188 | goto out; |
|
- | 189 | ||
- | 190 | switch (fitting_mode) { |
|
- | 191 | case DRM_MODE_SCALE_CENTER: |
|
- | 192 | /* |
|
- | 193 | * For centered modes, we have to calculate border widths & |
|
- | 194 | * heights and modify the values programmed into the CRTC. |
|
- | 195 | */ |
|
- | 196 | centre_horizontally(adjusted_mode, mode->hdisplay); |
|
- | 197 | centre_vertically(adjusted_mode, mode->vdisplay); |
|
- | 198 | border = LVDS_BORDER_ENABLE; |
|
- | 199 | break; |
|
- | 200 | case DRM_MODE_SCALE_ASPECT: |
|
- | 201 | /* Scale but preserve the aspect ratio */ |
|
- | 202 | if (INTEL_INFO(dev)->gen >= 4) { |
|
- | 203 | u32 scaled_width = adjusted_mode->hdisplay * |
|
- | 204 | mode->vdisplay; |
|
- | 205 | u32 scaled_height = mode->hdisplay * |
|
- | 206 | adjusted_mode->vdisplay; |
|
- | 207 | ||
- | 208 | /* 965+ is easy, it does everything in hw */ |
|
- | 209 | if (scaled_width > scaled_height) |
|
- | 210 | pfit_control |= PFIT_ENABLE | |
|
- | 211 | PFIT_SCALING_PILLAR; |
|
- | 212 | else if (scaled_width < scaled_height) |
|
- | 213 | pfit_control |= PFIT_ENABLE | |
|
- | 214 | PFIT_SCALING_LETTER; |
|
- | 215 | else if (adjusted_mode->hdisplay != mode->hdisplay) |
|
- | 216 | pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO; |
|
- | 217 | } else { |
|
- | 218 | u32 scaled_width = adjusted_mode->hdisplay * |
|
- | 219 | mode->vdisplay; |
|
- | 220 | u32 scaled_height = mode->hdisplay * |
|
- | 221 | adjusted_mode->vdisplay; |
|
- | 222 | /* |
|
- | 223 | * For earlier chips we have to calculate the scaling |
|
- | 224 | * ratio by hand and program it into the |
|
- | 225 | * PFIT_PGM_RATIO register |
|
- | 226 | */ |
|
- | 227 | if (scaled_width > scaled_height) { /* pillar */ |
|
- | 228 | centre_horizontally(adjusted_mode, |
|
- | 229 | scaled_height / |
|
- | 230 | mode->vdisplay); |
|
- | 231 | ||
- | 232 | border = LVDS_BORDER_ENABLE; |
|
- | 233 | if (mode->vdisplay != adjusted_mode->vdisplay) { |
|
- | 234 | u32 bits = panel_fitter_scaling(mode->vdisplay, adjusted_mode->vdisplay); |
|
- | 235 | pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT | |
|
- | 236 | bits << PFIT_VERT_SCALE_SHIFT); |
|
- | 237 | pfit_control |= (PFIT_ENABLE | |
|
- | 238 | VERT_INTERP_BILINEAR | |
|
- | 239 | HORIZ_INTERP_BILINEAR); |
|
- | 240 | } |
|
- | 241 | } else if (scaled_width < scaled_height) { /* letter */ |
|
- | 242 | centre_vertically(adjusted_mode, |
|
- | 243 | scaled_width / |
|
- | 244 | mode->hdisplay); |
|
- | 245 | ||
- | 246 | border = LVDS_BORDER_ENABLE; |
|
- | 247 | if (mode->hdisplay != adjusted_mode->hdisplay) { |
|
- | 248 | u32 bits = panel_fitter_scaling(mode->hdisplay, adjusted_mode->hdisplay); |
|
- | 249 | pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT | |
|
- | 250 | bits << PFIT_VERT_SCALE_SHIFT); |
|
- | 251 | pfit_control |= (PFIT_ENABLE | |
|
- | 252 | VERT_INTERP_BILINEAR | |
|
- | 253 | HORIZ_INTERP_BILINEAR); |
|
- | 254 | } |
|
- | 255 | } else { |
|
- | 256 | /* Aspects match, Let hw scale both directions */ |
|
- | 257 | pfit_control |= (PFIT_ENABLE | |
|
- | 258 | VERT_AUTO_SCALE | HORIZ_AUTO_SCALE | |
|
- | 259 | VERT_INTERP_BILINEAR | |
|
- | 260 | HORIZ_INTERP_BILINEAR); |
|
- | 261 | } |
|
- | 262 | } |
|
- | 263 | break; |
|
- | 264 | case DRM_MODE_SCALE_FULLSCREEN: |
|
- | 265 | /* |
|
- | 266 | * Full scaling, even if it changes the aspect ratio. |
|
- | 267 | * Fortunately this is all done for us in hw. |
|
- | 268 | */ |
|
- | 269 | if (mode->vdisplay != adjusted_mode->vdisplay || |
|
- | 270 | mode->hdisplay != adjusted_mode->hdisplay) { |
|
- | 271 | pfit_control |= PFIT_ENABLE; |
|
- | 272 | if (INTEL_INFO(dev)->gen >= 4) |
|
- | 273 | pfit_control |= PFIT_SCALING_AUTO; |
|
- | 274 | else |
|
- | 275 | pfit_control |= (VERT_AUTO_SCALE | |
|
- | 276 | VERT_INTERP_BILINEAR | |
|
- | 277 | HORIZ_AUTO_SCALE | |
|
- | 278 | HORIZ_INTERP_BILINEAR); |
|
- | 279 | } |
|
- | 280 | break; |
|
- | 281 | default: |
|
- | 282 | WARN(1, "bad panel fit mode: %d\n", fitting_mode); |
|
- | 283 | return; |
|
- | 284 | } |
|
- | 285 | ||
- | 286 | /* 965+ wants fuzzy fitting */ |
|
- | 287 | /* FIXME: handle multiple panels by failing gracefully */ |
|
- | 288 | if (INTEL_INFO(dev)->gen >= 4) |
|
- | 289 | pfit_control |= ((intel_crtc->pipe << PFIT_PIPE_SHIFT) | |
|
- | 290 | PFIT_FILTER_FUZZY); |
|
- | 291 | ||
- | 292 | out: |
|
- | 293 | if ((pfit_control & PFIT_ENABLE) == 0) { |
|
- | 294 | pfit_control = 0; |
|
- | 295 | pfit_pgm_ratios = 0; |
|
- | 296 | } |
|
- | 297 | ||
- | 298 | /* Make sure pre-965 set dither correctly for 18bpp panels. */ |
|
- | 299 | if (INTEL_INFO(dev)->gen < 4 && pipe_config->pipe_bpp == 18) |
|
- | 300 | pfit_control |= PANEL_8TO6_DITHER_ENABLE; |
|
- | 301 | ||
- | 302 | pipe_config->gmch_pfit.control = pfit_control; |
|
116 | dev_priv->pch_pf_pos = (x << 16) | y; |
303 | pipe_config->gmch_pfit.pgm_ratios = pfit_pgm_ratios; |
Line 117... | Line 304... | ||
117 | dev_priv->pch_pf_size = (width << 16) | height; |
304 | pipe_config->gmch_pfit.lvds_border_bits = border; |
118 | } |
305 | } |
119 | 306 | ||
Line 128... | Line 315... | ||
128 | return I915_READ(BLC_PWM_CTL) & BLM_LEGACY_MODE; |
315 | return I915_READ(BLC_PWM_CTL) & BLM_LEGACY_MODE; |
Line 129... | Line 316... | ||
129 | 316 | ||
130 | return 0; |
317 | return 0; |
Line -... | Line 318... | ||
- | 318 | } |
|
- | 319 | ||
- | 320 | /* XXX: query mode clock or hardware clock and program max PWM appropriately |
|
131 | } |
321 | * when it's 0. |
132 | 322 | */ |
|
133 | static u32 i915_read_blc_pwm_ctl(struct drm_device *dev) |
323 | static u32 i915_read_blc_pwm_ctl(struct drm_device *dev) |
134 | { |
324 | { |
Line -... | Line 325... | ||
- | 325 | struct drm_i915_private *dev_priv = dev->dev_private; |
|
- | 326 | u32 val; |
|
135 | struct drm_i915_private *dev_priv = dev->dev_private; |
327 | |
Line 136... | Line 328... | ||
136 | u32 val; |
328 | // WARN_ON_SMP(!spin_is_locked(&dev_priv->backlight.lock)); |
137 | 329 | ||
138 | /* Restore the CTL value if it lost, e.g. GPU reset */ |
330 | /* Restore the CTL value if it lost, e.g. GPU reset */ |
Line 162... | Line 354... | ||
162 | } |
354 | } |
Line 163... | Line 355... | ||
163 | 355 | ||
164 | return val; |
356 | return val; |
Line 165... | Line 357... | ||
165 | } |
357 | } |
166 | 358 | ||
167 | static u32 _intel_panel_get_max_backlight(struct drm_device *dev) |
359 | static u32 intel_panel_get_max_backlight(struct drm_device *dev) |
Line 168... | Line 360... | ||
168 | { |
360 | { |
Line 180... | Line 372... | ||
180 | 372 | ||
181 | if (is_backlight_combination_mode(dev)) |
373 | if (is_backlight_combination_mode(dev)) |
182 | max *= 0xff; |
374 | max *= 0xff; |
Line 183... | Line -... | ||
183 | } |
- | |
184 | - | ||
185 | return max; |
- | |
186 | } |
- | |
187 | - | ||
188 | u32 intel_panel_get_max_backlight(struct drm_device *dev) |
- | |
189 | { |
- | |
190 | u32 max; |
- | |
191 | - | ||
192 | max = _intel_panel_get_max_backlight(dev); |
- | |
193 | if (max == 0) { |
- | |
194 | /* XXX add code here to query mode clock or hardware clock |
- | |
195 | * and program max PWM appropriately. |
- | |
196 | */ |
- | |
197 | pr_warn_once("fixme: max PWM is zero\n"); |
- | |
198 | return 1; |
- | |
199 | } |
375 | } |
- | 376 | ||
200 | 377 | DRM_DEBUG_DRIVER("max backlight PWM = %d\n", max); |
|
201 | DRM_DEBUG_DRIVER("max backlight PWM = %d\n", max); |
378 | |
Line 202... | Line 379... | ||
202 | return max; |
379 | return max; |
203 | } |
380 | } |
Line 215... | Line 392... | ||
215 | 392 | ||
216 | if (i915_panel_invert_brightness < 0) |
393 | if (i915_panel_invert_brightness < 0) |
Line 217... | Line 394... | ||
217 | return val; |
394 | return val; |
218 | 395 | ||
219 | if (i915_panel_invert_brightness > 0 || |
396 | if (i915_panel_invert_brightness > 0 || |
- | 397 | dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) { |
|
- | 398 | u32 max = intel_panel_get_max_backlight(dev); |
|
- | 399 | if (max) |
|
Line 220... | Line 400... | ||
220 | dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) |
400 | return max - val; |
221 | return intel_panel_get_max_backlight(dev) - val; |
401 | } |
Line 222... | Line 402... | ||
222 | 402 | ||
223 | return val; |
403 | return val; |
224 | } |
404 | } |
225 | 405 | ||
- | 406 | static u32 intel_panel_get_backlight(struct drm_device *dev) |
|
- | 407 | { |
|
- | 408 | struct drm_i915_private *dev_priv = dev->dev_private; |
|
Line 226... | Line 409... | ||
226 | static u32 intel_panel_get_backlight(struct drm_device *dev) |
409 | u32 val; |
227 | { |
410 | unsigned long flags; |
228 | struct drm_i915_private *dev_priv = dev->dev_private; |
411 | |
229 | u32 val; |
412 | spin_lock_irqsave(&dev_priv->backlight.lock, flags); |
Line 242... | Line 425... | ||
242 | val *= lbpc; |
425 | val *= lbpc; |
243 | } |
426 | } |
244 | } |
427 | } |
Line 245... | Line 428... | ||
245 | 428 | ||
- | 429 | val = intel_panel_compute_brightness(dev, val); |
|
- | 430 | ||
- | 431 | spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); |
|
246 | val = intel_panel_compute_brightness(dev, val); |
432 | |
247 | DRM_DEBUG_DRIVER("get backlight PWM = %d\n", val); |
433 | DRM_DEBUG_DRIVER("get backlight PWM = %d\n", val); |
248 | return val; |
434 | return val; |
Line 249... | Line 435... | ||
249 | } |
435 | } |
Line 268... | Line 454... | ||
268 | 454 | ||
269 | if (is_backlight_combination_mode(dev)) { |
455 | if (is_backlight_combination_mode(dev)) { |
270 | u32 max = intel_panel_get_max_backlight(dev); |
456 | u32 max = intel_panel_get_max_backlight(dev); |
Line -... | Line 457... | ||
- | 457 | u8 lbpc; |
|
- | 458 | ||
- | 459 | /* we're screwed, but keep behaviour backwards compatible */ |
|
- | 460 | if (!max) |
|
271 | u8 lbpc; |
461 | max = 1; |
272 | 462 | ||
273 | lbpc = level * 0xfe / max + 1; |
463 | lbpc = level * 0xfe / max + 1; |
274 | level /= lbpc; |
464 | level /= lbpc; |
Line 280... | Line 470... | ||
280 | level <<= 1; |
470 | level <<= 1; |
281 | tmp &= ~BACKLIGHT_DUTY_CYCLE_MASK; |
471 | tmp &= ~BACKLIGHT_DUTY_CYCLE_MASK; |
282 | I915_WRITE(BLC_PWM_CTL, tmp | level); |
472 | I915_WRITE(BLC_PWM_CTL, tmp | level); |
283 | } |
473 | } |
Line -... | Line 474... | ||
- | 474 | ||
284 | 475 | /* set backlight brightness to level in range [0..max] */ |
|
285 | void intel_panel_set_backlight(struct drm_device *dev, u32 level) |
476 | void intel_panel_set_backlight(struct drm_device *dev, u32 level, u32 max) |
286 | { |
477 | { |
Line 287... | Line 478... | ||
287 | struct drm_i915_private *dev_priv = dev->dev_private; |
478 | struct drm_i915_private *dev_priv = dev->dev_private; |
288 | 479 | ||
Line 295... | Line 486... | ||
295 | } |
486 | } |
Line 296... | Line 487... | ||
296 | 487 | ||
297 | void intel_panel_disable_backlight(struct drm_device *dev) |
488 | void intel_panel_disable_backlight(struct drm_device *dev) |
298 | { |
489 | { |
- | 490 | struct drm_i915_private *dev_priv = dev->dev_private; |
|
- | 491 | unsigned long flags; |
|
- | 492 | ||
Line 299... | Line 493... | ||
299 | struct drm_i915_private *dev_priv = dev->dev_private; |
493 | spin_lock_irqsave(&dev_priv->backlight.lock, flags); |
300 | 494 | ||
Line 301... | Line 495... | ||
301 | dev_priv->backlight.enabled = false; |
495 | dev_priv->backlight.enabled = false; |
Line 312... | Line 506... | ||
312 | tmp = I915_READ(BLC_PWM_PCH_CTL1); |
506 | tmp = I915_READ(BLC_PWM_PCH_CTL1); |
313 | tmp &= ~BLM_PCH_PWM_ENABLE; |
507 | tmp &= ~BLM_PCH_PWM_ENABLE; |
314 | I915_WRITE(BLC_PWM_PCH_CTL1, tmp); |
508 | I915_WRITE(BLC_PWM_PCH_CTL1, tmp); |
315 | } |
509 | } |
316 | } |
510 | } |
- | 511 | ||
- | 512 | spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); |
|
317 | } |
513 | } |
Line 318... | Line 514... | ||
318 | 514 | ||
319 | void intel_panel_enable_backlight(struct drm_device *dev, |
515 | void intel_panel_enable_backlight(struct drm_device *dev, |
320 | enum pipe pipe) |
516 | enum pipe pipe) |
321 | { |
517 | { |
- | 518 | struct drm_i915_private *dev_priv = dev->dev_private; |
|
- | 519 | enum transcoder cpu_transcoder = |
|
- | 520 | intel_pipe_to_cpu_transcoder(dev_priv, pipe); |
|
- | 521 | unsigned long flags; |
|
- | 522 | ||
Line 322... | Line 523... | ||
322 | struct drm_i915_private *dev_priv = dev->dev_private; |
523 | spin_lock_irqsave(&dev_priv->backlight.lock, flags); |
323 | 524 | ||
324 | if (dev_priv->backlight.level == 0) { |
525 | if (dev_priv->backlight.level == 0) { |
325 | dev_priv->backlight.level = intel_panel_get_max_backlight(dev); |
526 | dev_priv->backlight.level = intel_panel_get_max_backlight(dev); |
Line 345... | Line 546... | ||
345 | if (INTEL_INFO(dev)->num_pipes == 3) |
546 | if (INTEL_INFO(dev)->num_pipes == 3) |
346 | tmp &= ~BLM_PIPE_SELECT_IVB; |
547 | tmp &= ~BLM_PIPE_SELECT_IVB; |
347 | else |
548 | else |
348 | tmp &= ~BLM_PIPE_SELECT; |
549 | tmp &= ~BLM_PIPE_SELECT; |
Line -... | Line 550... | ||
- | 550 | ||
- | 551 | if (cpu_transcoder == TRANSCODER_EDP) |
|
- | 552 | tmp |= BLM_TRANSCODER_EDP; |
|
349 | 553 | else |
|
350 | tmp |= BLM_PIPE(pipe); |
554 | tmp |= BLM_PIPE(cpu_transcoder); |
Line 351... | Line 555... | ||
351 | tmp &= ~BLM_PWM_ENABLE; |
555 | tmp &= ~BLM_PWM_ENABLE; |
352 | 556 | ||
353 | I915_WRITE(reg, tmp); |
557 | I915_WRITE(reg, tmp); |
Line 354... | Line 558... | ||
354 | POSTING_READ(reg); |
558 | POSTING_READ(reg); |
- | 559 | I915_WRITE(reg, tmp | BLM_PWM_ENABLE); |
|
355 | I915_WRITE(reg, tmp | BLM_PWM_ENABLE); |
560 | |
356 | 561 | if (HAS_PCH_SPLIT(dev) && |
|
357 | if (HAS_PCH_SPLIT(dev)) { |
562 | !(dev_priv->quirks & QUIRK_NO_PCH_PWM_ENABLE)) { |
358 | tmp = I915_READ(BLC_PWM_PCH_CTL1); |
563 | tmp = I915_READ(BLC_PWM_PCH_CTL1); |
359 | tmp |= BLM_PCH_PWM_ENABLE; |
564 | tmp |= BLM_PCH_PWM_ENABLE; |
Line 367... | Line 572... | ||
367 | * BLC_PWM_CPU_CTL may be cleared to zero automatically when these |
572 | * BLC_PWM_CPU_CTL may be cleared to zero automatically when these |
368 | * registers are set. |
573 | * registers are set. |
369 | */ |
574 | */ |
370 | dev_priv->backlight.enabled = true; |
575 | dev_priv->backlight.enabled = true; |
371 | intel_panel_actually_set_backlight(dev, dev_priv->backlight.level); |
576 | intel_panel_actually_set_backlight(dev, dev_priv->backlight.level); |
- | 577 | ||
- | 578 | spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); |
|
372 | } |
579 | } |
Line 373... | Line 580... | ||
373 | 580 | ||
374 | static void intel_panel_init_backlight(struct drm_device *dev) |
581 | static void intel_panel_init_backlight(struct drm_device *dev) |
375 | { |
582 | { |
Line 403... | Line 610... | ||
403 | 610 | ||
404 | #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE |
611 | #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE |
405 | static int intel_panel_update_status(struct backlight_device *bd) |
612 | static int intel_panel_update_status(struct backlight_device *bd) |
406 | { |
613 | { |
407 | struct drm_device *dev = bl_get_data(bd); |
614 | struct drm_device *dev = bl_get_data(bd); |
- | 615 | intel_panel_set_backlight(dev, bd->props.brightness, |
|
408 | intel_panel_set_backlight(dev, bd->props.brightness); |
616 | bd->props.max_brightness); |
409 | return 0; |
617 | return 0; |
Line 410... | Line 618... | ||
410 | } |
618 | } |
411 | 619 | ||
Line 423... | Line 631... | ||
423 | int intel_panel_setup_backlight(struct drm_connector *connector) |
631 | int intel_panel_setup_backlight(struct drm_connector *connector) |
424 | { |
632 | { |
425 | struct drm_device *dev = connector->dev; |
633 | struct drm_device *dev = connector->dev; |
426 | struct drm_i915_private *dev_priv = dev->dev_private; |
634 | struct drm_i915_private *dev_priv = dev->dev_private; |
427 | struct backlight_properties props; |
635 | struct backlight_properties props; |
- | 636 | unsigned long flags; |
|
Line 428... | Line 637... | ||
428 | 637 | ||
Line 429... | Line 638... | ||
429 | intel_panel_init_backlight(dev); |
638 | intel_panel_init_backlight(dev); |
430 | 639 | ||
Line 431... | Line 640... | ||
431 | if (WARN_ON(dev_priv->backlight.device)) |
640 | if (WARN_ON(dev_priv->backlight.device)) |
432 | return -ENODEV; |
641 | return -ENODEV; |
433 | 642 | ||
- | 643 | memset(&props, 0, sizeof(props)); |
|
- | 644 | props.type = BACKLIGHT_RAW; |
|
434 | memset(&props, 0, sizeof(props)); |
645 | props.brightness = dev_priv->backlight.level; |
- | 646 | ||
- | 647 | spin_lock_irqsave(&dev_priv->backlight.lock, flags); |
|
435 | props.type = BACKLIGHT_RAW; |
648 | props.max_brightness = intel_panel_get_max_backlight(dev); |
436 | props.brightness = dev_priv->backlight.level; |
649 | spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); |
437 | props.max_brightness = _intel_panel_get_max_backlight(dev); |
650 | |
438 | if (props.max_brightness == 0) { |
651 | if (props.max_brightness == 0) { |
439 | DRM_DEBUG_DRIVER("Failed to get maximum backlight value\n"); |
652 | DRM_DEBUG_DRIVER("Failed to get maximum backlight value\n"); |