diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_opregion.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_opregion.c | 146 |
1 files changed, 131 insertions, 15 deletions
diff --git a/drivers/gpu/drm/i915/i915_opregion.c b/drivers/gpu/drm/i915/i915_opregion.c index 2d5193556d3f..8fcc75c1aa28 100644 --- a/drivers/gpu/drm/i915/i915_opregion.c +++ b/drivers/gpu/drm/i915/i915_opregion.c | |||
@@ -118,6 +118,10 @@ struct opregion_asle { | |||
118 | #define ASLE_BACKLIGHT_FAIL (2<<12) | 118 | #define ASLE_BACKLIGHT_FAIL (2<<12) |
119 | #define ASLE_PFIT_FAIL (2<<14) | 119 | #define ASLE_PFIT_FAIL (2<<14) |
120 | #define ASLE_PWM_FREQ_FAIL (2<<16) | 120 | #define ASLE_PWM_FREQ_FAIL (2<<16) |
121 | #define ASLE_ALS_ILLUM_FAILED (1<<10) | ||
122 | #define ASLE_BACKLIGHT_FAILED (1<<12) | ||
123 | #define ASLE_PFIT_FAILED (1<<14) | ||
124 | #define ASLE_PWM_FREQ_FAILED (1<<16) | ||
121 | 125 | ||
122 | /* ASLE backlight brightness to set */ | 126 | /* ASLE backlight brightness to set */ |
123 | #define ASLE_BCLP_VALID (1<<31) | 127 | #define ASLE_BCLP_VALID (1<<31) |
@@ -163,7 +167,7 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp) | |||
163 | if (IS_I965G(dev) && (blc_pwm_ctl2 & BLM_COMBINATION_MODE)) | 167 | if (IS_I965G(dev) && (blc_pwm_ctl2 & BLM_COMBINATION_MODE)) |
164 | pci_write_config_dword(dev->pdev, PCI_LBPC, bclp); | 168 | pci_write_config_dword(dev->pdev, PCI_LBPC, bclp); |
165 | else { | 169 | else { |
166 | if (IS_IGD(dev)) { | 170 | if (IS_PINEVIEW(dev)) { |
167 | blc_pwm_ctl &= ~(BACKLIGHT_DUTY_CYCLE_MASK - 1); | 171 | blc_pwm_ctl &= ~(BACKLIGHT_DUTY_CYCLE_MASK - 1); |
168 | max_backlight = (blc_pwm_ctl & BACKLIGHT_MODULATION_FREQ_MASK) >> | 172 | max_backlight = (blc_pwm_ctl & BACKLIGHT_MODULATION_FREQ_MASK) >> |
169 | BACKLIGHT_MODULATION_FREQ_SHIFT; | 173 | BACKLIGHT_MODULATION_FREQ_SHIFT; |
@@ -224,7 +228,7 @@ void opregion_asle_intr(struct drm_device *dev) | |||
224 | asle_req = asle->aslc & ASLE_REQ_MSK; | 228 | asle_req = asle->aslc & ASLE_REQ_MSK; |
225 | 229 | ||
226 | if (!asle_req) { | 230 | if (!asle_req) { |
227 | DRM_DEBUG("non asle set request??\n"); | 231 | DRM_DEBUG_DRIVER("non asle set request??\n"); |
228 | return; | 232 | return; |
229 | } | 233 | } |
230 | 234 | ||
@@ -243,6 +247,73 @@ void opregion_asle_intr(struct drm_device *dev) | |||
243 | asle->aslc = asle_stat; | 247 | asle->aslc = asle_stat; |
244 | } | 248 | } |
245 | 249 | ||
250 | static u32 asle_set_backlight_ironlake(struct drm_device *dev, u32 bclp) | ||
251 | { | ||
252 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
253 | struct opregion_asle *asle = dev_priv->opregion.asle; | ||
254 | u32 cpu_pwm_ctl, pch_pwm_ctl2; | ||
255 | u32 max_backlight, level; | ||
256 | |||
257 | if (!(bclp & ASLE_BCLP_VALID)) | ||
258 | return ASLE_BACKLIGHT_FAILED; | ||
259 | |||
260 | bclp &= ASLE_BCLP_MSK; | ||
261 | if (bclp < 0 || bclp > 255) | ||
262 | return ASLE_BACKLIGHT_FAILED; | ||
263 | |||
264 | cpu_pwm_ctl = I915_READ(BLC_PWM_CPU_CTL); | ||
265 | pch_pwm_ctl2 = I915_READ(BLC_PWM_PCH_CTL2); | ||
266 | /* get the max PWM frequency */ | ||
267 | max_backlight = (pch_pwm_ctl2 >> 16) & BACKLIGHT_DUTY_CYCLE_MASK; | ||
268 | /* calculate the expected PMW frequency */ | ||
269 | level = (bclp * max_backlight) / 255; | ||
270 | /* reserve the high 16 bits */ | ||
271 | cpu_pwm_ctl &= ~(BACKLIGHT_DUTY_CYCLE_MASK); | ||
272 | /* write the updated PWM frequency */ | ||
273 | I915_WRITE(BLC_PWM_CPU_CTL, cpu_pwm_ctl | level); | ||
274 | |||
275 | asle->cblv = (bclp*0x64)/0xff | ASLE_CBLV_VALID; | ||
276 | |||
277 | return 0; | ||
278 | } | ||
279 | |||
280 | void ironlake_opregion_gse_intr(struct drm_device *dev) | ||
281 | { | ||
282 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
283 | struct opregion_asle *asle = dev_priv->opregion.asle; | ||
284 | u32 asle_stat = 0; | ||
285 | u32 asle_req; | ||
286 | |||
287 | if (!asle) | ||
288 | return; | ||
289 | |||
290 | asle_req = asle->aslc & ASLE_REQ_MSK; | ||
291 | |||
292 | if (!asle_req) { | ||
293 | DRM_DEBUG_DRIVER("non asle set request??\n"); | ||
294 | return; | ||
295 | } | ||
296 | |||
297 | if (asle_req & ASLE_SET_ALS_ILLUM) { | ||
298 | DRM_DEBUG_DRIVER("Illum is not supported\n"); | ||
299 | asle_stat |= ASLE_ALS_ILLUM_FAILED; | ||
300 | } | ||
301 | |||
302 | if (asle_req & ASLE_SET_BACKLIGHT) | ||
303 | asle_stat |= asle_set_backlight_ironlake(dev, asle->bclp); | ||
304 | |||
305 | if (asle_req & ASLE_SET_PFIT) { | ||
306 | DRM_DEBUG_DRIVER("Pfit is not supported\n"); | ||
307 | asle_stat |= ASLE_PFIT_FAILED; | ||
308 | } | ||
309 | |||
310 | if (asle_req & ASLE_SET_PWM_FREQ) { | ||
311 | DRM_DEBUG_DRIVER("PWM freq is not supported\n"); | ||
312 | asle_stat |= ASLE_PWM_FREQ_FAILED; | ||
313 | } | ||
314 | |||
315 | asle->aslc = asle_stat; | ||
316 | } | ||
246 | #define ASLE_ALS_EN (1<<0) | 317 | #define ASLE_ALS_EN (1<<0) |
247 | #define ASLE_BLC_EN (1<<1) | 318 | #define ASLE_BLC_EN (1<<1) |
248 | #define ASLE_PFIT_EN (1<<2) | 319 | #define ASLE_PFIT_EN (1<<2) |
@@ -258,8 +329,7 @@ void opregion_enable_asle(struct drm_device *dev) | |||
258 | unsigned long irqflags; | 329 | unsigned long irqflags; |
259 | 330 | ||
260 | spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); | 331 | spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); |
261 | i915_enable_pipestat(dev_priv, 1, | 332 | intel_enable_asle(dev); |
262 | I915_LEGACY_BLC_EVENT_ENABLE); | ||
263 | spin_unlock_irqrestore(&dev_priv->user_irq_lock, | 333 | spin_unlock_irqrestore(&dev_priv->user_irq_lock, |
264 | irqflags); | 334 | irqflags); |
265 | } | 335 | } |
@@ -312,8 +382,57 @@ static void intel_didl_outputs(struct drm_device *dev) | |||
312 | struct drm_i915_private *dev_priv = dev->dev_private; | 382 | struct drm_i915_private *dev_priv = dev->dev_private; |
313 | struct intel_opregion *opregion = &dev_priv->opregion; | 383 | struct intel_opregion *opregion = &dev_priv->opregion; |
314 | struct drm_connector *connector; | 384 | struct drm_connector *connector; |
385 | acpi_handle handle; | ||
386 | struct acpi_device *acpi_dev, *acpi_cdev, *acpi_video_bus = NULL; | ||
387 | unsigned long long device_id; | ||
388 | acpi_status status; | ||
315 | int i = 0; | 389 | int i = 0; |
316 | 390 | ||
391 | handle = DEVICE_ACPI_HANDLE(&dev->pdev->dev); | ||
392 | if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &acpi_dev))) | ||
393 | return; | ||
394 | |||
395 | if (acpi_is_video_device(acpi_dev)) | ||
396 | acpi_video_bus = acpi_dev; | ||
397 | else { | ||
398 | list_for_each_entry(acpi_cdev, &acpi_dev->children, node) { | ||
399 | if (acpi_is_video_device(acpi_cdev)) { | ||
400 | acpi_video_bus = acpi_cdev; | ||
401 | break; | ||
402 | } | ||
403 | } | ||
404 | } | ||
405 | |||
406 | if (!acpi_video_bus) { | ||
407 | printk(KERN_WARNING "No ACPI video bus found\n"); | ||
408 | return; | ||
409 | } | ||
410 | |||
411 | list_for_each_entry(acpi_cdev, &acpi_video_bus->children, node) { | ||
412 | if (i >= 8) { | ||
413 | dev_printk (KERN_ERR, &dev->pdev->dev, | ||
414 | "More than 8 outputs detected\n"); | ||
415 | return; | ||
416 | } | ||
417 | status = | ||
418 | acpi_evaluate_integer(acpi_cdev->handle, "_ADR", | ||
419 | NULL, &device_id); | ||
420 | if (ACPI_SUCCESS(status)) { | ||
421 | if (!device_id) | ||
422 | goto blind_set; | ||
423 | opregion->acpi->didl[i] = (u32)(device_id & 0x0f0f); | ||
424 | i++; | ||
425 | } | ||
426 | } | ||
427 | |||
428 | end: | ||
429 | /* If fewer than 8 outputs, the list must be null terminated */ | ||
430 | if (i < 8) | ||
431 | opregion->acpi->didl[i] = 0; | ||
432 | return; | ||
433 | |||
434 | blind_set: | ||
435 | i = 0; | ||
317 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 436 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
318 | int output_type = ACPI_OTHER_OUTPUT; | 437 | int output_type = ACPI_OTHER_OUTPUT; |
319 | if (i >= 8) { | 438 | if (i >= 8) { |
@@ -346,10 +465,7 @@ static void intel_didl_outputs(struct drm_device *dev) | |||
346 | opregion->acpi->didl[i] |= (1<<31) | output_type | i; | 465 | opregion->acpi->didl[i] |= (1<<31) | output_type | i; |
347 | i++; | 466 | i++; |
348 | } | 467 | } |
349 | 468 | goto end; | |
350 | /* If fewer than 8 outputs, the list must be null terminated */ | ||
351 | if (i < 8) | ||
352 | opregion->acpi->didl[i] = 0; | ||
353 | } | 469 | } |
354 | 470 | ||
355 | int intel_opregion_init(struct drm_device *dev, int resume) | 471 | int intel_opregion_init(struct drm_device *dev, int resume) |
@@ -361,9 +477,9 @@ int intel_opregion_init(struct drm_device *dev, int resume) | |||
361 | int err = 0; | 477 | int err = 0; |
362 | 478 | ||
363 | pci_read_config_dword(dev->pdev, PCI_ASLS, &asls); | 479 | pci_read_config_dword(dev->pdev, PCI_ASLS, &asls); |
364 | DRM_DEBUG("graphic opregion physical addr: 0x%x\n", asls); | 480 | DRM_DEBUG_DRIVER("graphic opregion physical addr: 0x%x\n", asls); |
365 | if (asls == 0) { | 481 | if (asls == 0) { |
366 | DRM_DEBUG("ACPI OpRegion not supported!\n"); | 482 | DRM_DEBUG_DRIVER("ACPI OpRegion not supported!\n"); |
367 | return -ENOTSUPP; | 483 | return -ENOTSUPP; |
368 | } | 484 | } |
369 | 485 | ||
@@ -373,30 +489,30 @@ int intel_opregion_init(struct drm_device *dev, int resume) | |||
373 | 489 | ||
374 | opregion->header = base; | 490 | opregion->header = base; |
375 | if (memcmp(opregion->header->signature, OPREGION_SIGNATURE, 16)) { | 491 | if (memcmp(opregion->header->signature, OPREGION_SIGNATURE, 16)) { |
376 | DRM_DEBUG("opregion signature mismatch\n"); | 492 | DRM_DEBUG_DRIVER("opregion signature mismatch\n"); |
377 | err = -EINVAL; | 493 | err = -EINVAL; |
378 | goto err_out; | 494 | goto err_out; |
379 | } | 495 | } |
380 | 496 | ||
381 | mboxes = opregion->header->mboxes; | 497 | mboxes = opregion->header->mboxes; |
382 | if (mboxes & MBOX_ACPI) { | 498 | if (mboxes & MBOX_ACPI) { |
383 | DRM_DEBUG("Public ACPI methods supported\n"); | 499 | DRM_DEBUG_DRIVER("Public ACPI methods supported\n"); |
384 | opregion->acpi = base + OPREGION_ACPI_OFFSET; | 500 | opregion->acpi = base + OPREGION_ACPI_OFFSET; |
385 | if (drm_core_check_feature(dev, DRIVER_MODESET)) | 501 | if (drm_core_check_feature(dev, DRIVER_MODESET)) |
386 | intel_didl_outputs(dev); | 502 | intel_didl_outputs(dev); |
387 | } else { | 503 | } else { |
388 | DRM_DEBUG("Public ACPI methods not supported\n"); | 504 | DRM_DEBUG_DRIVER("Public ACPI methods not supported\n"); |
389 | err = -ENOTSUPP; | 505 | err = -ENOTSUPP; |
390 | goto err_out; | 506 | goto err_out; |
391 | } | 507 | } |
392 | opregion->enabled = 1; | 508 | opregion->enabled = 1; |
393 | 509 | ||
394 | if (mboxes & MBOX_SWSCI) { | 510 | if (mboxes & MBOX_SWSCI) { |
395 | DRM_DEBUG("SWSCI supported\n"); | 511 | DRM_DEBUG_DRIVER("SWSCI supported\n"); |
396 | opregion->swsci = base + OPREGION_SWSCI_OFFSET; | 512 | opregion->swsci = base + OPREGION_SWSCI_OFFSET; |
397 | } | 513 | } |
398 | if (mboxes & MBOX_ASLE) { | 514 | if (mboxes & MBOX_ASLE) { |
399 | DRM_DEBUG("ASLE supported\n"); | 515 | DRM_DEBUG_DRIVER("ASLE supported\n"); |
400 | opregion->asle = base + OPREGION_ASLE_OFFSET; | 516 | opregion->asle = base + OPREGION_ASLE_OFFSET; |
401 | opregion_enable_asle(dev); | 517 | opregion_enable_asle(dev); |
402 | } | 518 | } |