aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_panel.c
diff options
context:
space:
mode:
authorJani Nikula <jani.nikula@intel.com>2013-04-12 08:18:37 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-04-25 08:10:10 -0400
commit8ba2d18520ce380cf572e9902d9b3b91ece6c2c0 (patch)
treeeb1ecb47ee2f713bc2980e97db7a0b566334ff90 /drivers/gpu/drm/i915/intel_panel.c
parentd65406327345e5a5e0f697a3ffe3e53bc9b5d7c6 (diff)
drm/i915: protect backlight registers and data with a spinlock
Backlight data and registers are fiddled through LVDS/eDP modeset enable/disable hooks, backlight sysfs files, asle interrupts, and register save/restore. Protect the backlight related registers and driver private fields using a spinlock. The locking in register save/restore covers a little more than is strictly necessary, including non-modeset case, for simplicity. v2: Cover register access, save/restore, i915_read_blc_pwm_ctl() and code paths leading there. Signed-off-by: Jani Nikula <jani.nikula@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_panel.c')
-rw-r--r--drivers/gpu/drm/i915/intel_panel.c30
1 files changed, 29 insertions, 1 deletions
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index 63a7c36a7603..5d3e9d7d51a7 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -138,6 +138,8 @@ static u32 i915_read_blc_pwm_ctl(struct drm_device *dev)
138 struct drm_i915_private *dev_priv = dev->dev_private; 138 struct drm_i915_private *dev_priv = dev->dev_private;
139 u32 val; 139 u32 val;
140 140
141 WARN_ON(!spin_is_locked(&dev_priv->backlight.lock));
142
141 /* Restore the CTL value if it lost, e.g. GPU reset */ 143 /* Restore the CTL value if it lost, e.g. GPU reset */
142 144
143 if (HAS_PCH_SPLIT(dev_priv->dev)) { 145 if (HAS_PCH_SPLIT(dev_priv->dev)) {
@@ -218,6 +220,9 @@ static u32 intel_panel_get_backlight(struct drm_device *dev)
218{ 220{
219 struct drm_i915_private *dev_priv = dev->dev_private; 221 struct drm_i915_private *dev_priv = dev->dev_private;
220 u32 val; 222 u32 val;
223 unsigned long flags;
224
225 spin_lock_irqsave(&dev_priv->backlight.lock, flags);
221 226
222 if (HAS_PCH_SPLIT(dev)) { 227 if (HAS_PCH_SPLIT(dev)) {
223 val = I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; 228 val = I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
@@ -235,6 +240,9 @@ static u32 intel_panel_get_backlight(struct drm_device *dev)
235 } 240 }
236 241
237 val = intel_panel_compute_brightness(dev, val); 242 val = intel_panel_compute_brightness(dev, val);
243
244 spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
245
238 DRM_DEBUG_DRIVER("get backlight PWM = %d\n", val); 246 DRM_DEBUG_DRIVER("get backlight PWM = %d\n", val);
239 return val; 247 return val;
240} 248}
@@ -282,11 +290,14 @@ void intel_panel_set_backlight(struct drm_device *dev, u32 level, u32 max)
282{ 290{
283 struct drm_i915_private *dev_priv = dev->dev_private; 291 struct drm_i915_private *dev_priv = dev->dev_private;
284 u32 freq; 292 u32 freq;
293 unsigned long flags;
294
295 spin_lock_irqsave(&dev_priv->backlight.lock, flags);
285 296
286 freq = intel_panel_get_max_backlight(dev); 297 freq = intel_panel_get_max_backlight(dev);
287 if (!freq) { 298 if (!freq) {
288 /* we are screwed, bail out */ 299 /* we are screwed, bail out */
289 return; 300 goto out;
290 } 301 }
291 302
292 /* scale to hardware */ 303 /* scale to hardware */
@@ -298,11 +309,16 @@ void intel_panel_set_backlight(struct drm_device *dev, u32 level, u32 max)
298 309
299 if (dev_priv->backlight.enabled) 310 if (dev_priv->backlight.enabled)
300 intel_panel_actually_set_backlight(dev, level); 311 intel_panel_actually_set_backlight(dev, level);
312out:
313 spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
301} 314}
302 315
303void intel_panel_disable_backlight(struct drm_device *dev) 316void intel_panel_disable_backlight(struct drm_device *dev)
304{ 317{
305 struct drm_i915_private *dev_priv = dev->dev_private; 318 struct drm_i915_private *dev_priv = dev->dev_private;
319 unsigned long flags;
320
321 spin_lock_irqsave(&dev_priv->backlight.lock, flags);
306 322
307 dev_priv->backlight.enabled = false; 323 dev_priv->backlight.enabled = false;
308 intel_panel_actually_set_backlight(dev, 0); 324 intel_panel_actually_set_backlight(dev, 0);
@@ -320,12 +336,17 @@ void intel_panel_disable_backlight(struct drm_device *dev)
320 I915_WRITE(BLC_PWM_PCH_CTL1, tmp); 336 I915_WRITE(BLC_PWM_PCH_CTL1, tmp);
321 } 337 }
322 } 338 }
339
340 spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
323} 341}
324 342
325void intel_panel_enable_backlight(struct drm_device *dev, 343void intel_panel_enable_backlight(struct drm_device *dev,
326 enum pipe pipe) 344 enum pipe pipe)
327{ 345{
328 struct drm_i915_private *dev_priv = dev->dev_private; 346 struct drm_i915_private *dev_priv = dev->dev_private;
347 unsigned long flags;
348
349 spin_lock_irqsave(&dev_priv->backlight.lock, flags);
329 350
330 if (dev_priv->backlight.level == 0) { 351 if (dev_priv->backlight.level == 0) {
331 dev_priv->backlight.level = intel_panel_get_max_backlight(dev); 352 dev_priv->backlight.level = intel_panel_get_max_backlight(dev);
@@ -375,6 +396,8 @@ set_level:
375 */ 396 */
376 dev_priv->backlight.enabled = true; 397 dev_priv->backlight.enabled = true;
377 intel_panel_actually_set_backlight(dev, dev_priv->backlight.level); 398 intel_panel_actually_set_backlight(dev, dev_priv->backlight.level);
399
400 spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
378} 401}
379 402
380static void intel_panel_init_backlight(struct drm_device *dev) 403static void intel_panel_init_backlight(struct drm_device *dev)
@@ -432,6 +455,7 @@ int intel_panel_setup_backlight(struct drm_connector *connector)
432 struct drm_device *dev = connector->dev; 455 struct drm_device *dev = connector->dev;
433 struct drm_i915_private *dev_priv = dev->dev_private; 456 struct drm_i915_private *dev_priv = dev->dev_private;
434 struct backlight_properties props; 457 struct backlight_properties props;
458 unsigned long flags;
435 459
436 intel_panel_init_backlight(dev); 460 intel_panel_init_backlight(dev);
437 461
@@ -441,7 +465,11 @@ int intel_panel_setup_backlight(struct drm_connector *connector)
441 memset(&props, 0, sizeof(props)); 465 memset(&props, 0, sizeof(props));
442 props.type = BACKLIGHT_RAW; 466 props.type = BACKLIGHT_RAW;
443 props.brightness = dev_priv->backlight.level; 467 props.brightness = dev_priv->backlight.level;
468
469 spin_lock_irqsave(&dev_priv->backlight.lock, flags);
444 props.max_brightness = intel_panel_get_max_backlight(dev); 470 props.max_brightness = intel_panel_get_max_backlight(dev);
471 spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
472
445 if (props.max_brightness == 0) { 473 if (props.max_brightness == 0) {
446 DRM_DEBUG_DRIVER("Failed to get maximum backlight value\n"); 474 DRM_DEBUG_DRIVER("Failed to get maximum backlight value\n");
447 return -ENODEV; 475 return -ENODEV;