Rev 4560 | Rev 5097 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4560 | Rev 5060 | ||
---|---|---|---|
Line 31... | Line 31... | ||
31 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
31 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
Line 32... | Line 32... | ||
32 | 32 | ||
33 | #include |
33 | #include |
Line 34... | Line -... | ||
34 | #include "intel_drv.h" |
- | |
35 | - | ||
36 | #define PCI_LBPC 0xf4 /* legacy/combination backlight modes */ |
34 | #include "intel_drv.h" |
37 | 35 | ||
38 | void |
36 | void |
39 | intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode, |
37 | intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode, |
40 | struct drm_display_mode *adjusted_mode) |
38 | struct drm_display_mode *adjusted_mode) |
Line 41... | Line 39... | ||
41 | { |
39 | { |
42 | drm_mode_copy(adjusted_mode, fixed_mode); |
40 | drm_mode_copy(adjusted_mode, fixed_mode); |
Line -... | Line 41... | ||
- | 41 | ||
- | 42 | drm_mode_set_crtcinfo(adjusted_mode, 0); |
|
- | 43 | } |
|
- | 44 | ||
- | 45 | /** |
|
- | 46 | * intel_find_panel_downclock - find the reduced downclock for LVDS in EDID |
|
- | 47 | * @dev: drm device |
|
- | 48 | * @fixed_mode : panel native mode |
|
- | 49 | * @connector: LVDS/eDP connector |
|
- | 50 | * |
|
- | 51 | * Return downclock_avail |
|
- | 52 | * Find the reduced downclock for LVDS/eDP in EDID. |
|
- | 53 | */ |
|
- | 54 | struct drm_display_mode * |
|
- | 55 | intel_find_panel_downclock(struct drm_device *dev, |
|
- | 56 | struct drm_display_mode *fixed_mode, |
|
- | 57 | struct drm_connector *connector) |
|
- | 58 | { |
|
- | 59 | struct drm_display_mode *scan, *tmp_mode; |
|
- | 60 | int temp_downclock; |
|
- | 61 | ||
- | 62 | temp_downclock = fixed_mode->clock; |
|
- | 63 | tmp_mode = NULL; |
|
- | 64 | ||
- | 65 | list_for_each_entry(scan, &connector->probed_modes, head) { |
|
- | 66 | /* |
|
- | 67 | * If one mode has the same resolution with the fixed_panel |
|
- | 68 | * mode while they have the different refresh rate, it means |
|
- | 69 | * that the reduced downclock is found. In such |
|
- | 70 | * case we can set the different FPx0/1 to dynamically select |
|
- | 71 | * between low and high frequency. |
|
- | 72 | */ |
|
- | 73 | if (scan->hdisplay == fixed_mode->hdisplay && |
|
- | 74 | scan->hsync_start == fixed_mode->hsync_start && |
|
- | 75 | scan->hsync_end == fixed_mode->hsync_end && |
|
- | 76 | scan->htotal == fixed_mode->htotal && |
|
- | 77 | scan->vdisplay == fixed_mode->vdisplay && |
|
- | 78 | scan->vsync_start == fixed_mode->vsync_start && |
|
- | 79 | scan->vsync_end == fixed_mode->vsync_end && |
|
- | 80 | scan->vtotal == fixed_mode->vtotal) { |
|
- | 81 | if (scan->clock < temp_downclock) { |
|
- | 82 | /* |
|
- | 83 | * The downclock is already found. But we |
|
- | 84 | * expect to find the lower downclock. |
|
- | 85 | */ |
|
- | 86 | temp_downclock = scan->clock; |
|
- | 87 | tmp_mode = scan; |
|
- | 88 | } |
|
- | 89 | } |
|
- | 90 | } |
|
- | 91 | ||
- | 92 | if (temp_downclock < fixed_mode->clock) |
|
- | 93 | return drm_mode_duplicate(dev, tmp_mode); |
|
43 | 94 | else |
|
44 | drm_mode_set_crtcinfo(adjusted_mode, 0); |
95 | return NULL; |
45 | } |
96 | } |
46 | 97 | ||
47 | /* adjusted_mode has been preset to be the panel's fixed mode */ |
98 | /* adjusted_mode has been preset to be the panel's fixed mode */ |
Line 323... | Line 374... | ||
323 | pipe_config->gmch_pfit.control = pfit_control; |
374 | pipe_config->gmch_pfit.control = pfit_control; |
324 | pipe_config->gmch_pfit.pgm_ratios = pfit_pgm_ratios; |
375 | pipe_config->gmch_pfit.pgm_ratios = pfit_pgm_ratios; |
325 | pipe_config->gmch_pfit.lvds_border_bits = border; |
376 | pipe_config->gmch_pfit.lvds_border_bits = border; |
326 | } |
377 | } |
Line -... | Line 378... | ||
- | 378 | ||
- | 379 | enum drm_connector_status |
|
- | 380 | intel_panel_detect(struct drm_device *dev) |
|
- | 381 | { |
|
- | 382 | struct drm_i915_private *dev_priv = dev->dev_private; |
|
- | 383 | ||
- | 384 | /* Assume that the BIOS does not lie through the OpRegion... */ |
|
- | 385 | if (!i915.panel_ignore_lid && dev_priv->opregion.lid_state) { |
|
- | 386 | return ioread32(dev_priv->opregion.lid_state) & 0x1 ? |
|
- | 387 | connector_status_connected : |
|
- | 388 | connector_status_disconnected; |
|
- | 389 | } |
|
327 | 390 | ||
- | 391 | switch (i915.panel_ignore_lid) { |
|
- | 392 | case -2: |
|
- | 393 | return connector_status_connected; |
|
- | 394 | case -1: |
|
- | 395 | return connector_status_disconnected; |
|
- | 396 | default: |
|
- | 397 | return connector_status_unknown; |
|
- | 398 | } |
|
- | 399 | } |
|
- | 400 | ||
328 | static int i915_panel_invert_brightness; |
401 | /** |
- | 402 | * scale - scale values from one range to another |
|
329 | MODULE_PARM_DESC(invert_brightness, "Invert backlight brightness " |
403 | * |
- | 404 | * @source_val: value in range [@source_min..@source_max] |
|
330 | "(-1 force normal, 0 machine defaults, 1 force inversion), please " |
405 | * |
- | 406 | * Return @source_val in range [@source_min..@source_max] scaled to range |
|
- | 407 | * [@target_min..@target_max]. |
|
- | 408 | */ |
|
- | 409 | static uint32_t scale(uint32_t source_val, |
|
- | 410 | uint32_t source_min, uint32_t source_max, |
|
- | 411 | uint32_t target_min, uint32_t target_max) |
|
- | 412 | { |
|
- | 413 | uint64_t target_val; |
|
- | 414 | ||
- | 415 | WARN_ON(source_min > source_max); |
|
- | 416 | WARN_ON(target_min > target_max); |
|
- | 417 | ||
- | 418 | /* defensive */ |
|
- | 419 | source_val = clamp(source_val, source_min, source_max); |
|
- | 420 | ||
- | 421 | /* avoid overflows */ |
|
- | 422 | target_val = (uint64_t)(source_val - source_min) * |
|
- | 423 | (target_max - target_min); |
|
- | 424 | do_div(target_val, source_max - source_min); |
|
- | 425 | target_val += target_min; |
|
- | 426 | ||
- | 427 | return target_val; |
|
- | 428 | } |
|
- | 429 | ||
- | 430 | /* Scale user_level in range [0..user_max] to [hw_min..hw_max]. */ |
|
- | 431 | static inline u32 scale_user_to_hw(struct intel_connector *connector, |
|
- | 432 | u32 user_level, u32 user_max) |
|
- | 433 | { |
|
- | 434 | struct intel_panel *panel = &connector->panel; |
|
- | 435 | ||
- | 436 | return scale(user_level, 0, user_max, |
|
- | 437 | panel->backlight.min, panel->backlight.max); |
|
- | 438 | } |
|
- | 439 | ||
- | 440 | /* Scale user_level in range [0..user_max] to [0..hw_max], clamping the result |
|
- | 441 | * to [hw_min..hw_max]. */ |
|
- | 442 | static inline u32 clamp_user_to_hw(struct intel_connector *connector, |
|
- | 443 | u32 user_level, u32 user_max) |
|
- | 444 | { |
|
- | 445 | struct intel_panel *panel = &connector->panel; |
|
- | 446 | u32 hw_level; |
|
331 | "report PCI device ID, subsystem vendor and subsystem device ID " |
447 | |
- | 448 | hw_level = scale(user_level, 0, user_max, 0, panel->backlight.max); |
|
- | 449 | hw_level = clamp(hw_level, panel->backlight.min, panel->backlight.max); |
|
- | 450 | ||
- | 451 | return hw_level; |
|
- | 452 | } |
|
332 | "to dri-devel@lists.freedesktop.org, if your machine needs it. " |
453 | |
- | 454 | /* Scale hw_level in range [hw_min..hw_max] to [0..user_max]. */ |
|
- | 455 | static inline u32 scale_hw_to_user(struct intel_connector *connector, |
|
- | 456 | u32 hw_level, u32 user_max) |
|
- | 457 | { |
|
- | 458 | struct intel_panel *panel = &connector->panel; |
|
333 | "It will then be included in an upcoming module version."); |
459 | |
- | 460 | return scale(hw_level, panel->backlight.min, panel->backlight.max, |
|
- | 461 | 0, user_max); |
|
- | 462 | } |
|
334 | module_param_named(invert_brightness, i915_panel_invert_brightness, int, 0600); |
463 | |
335 | static u32 intel_panel_compute_brightness(struct intel_connector *connector, |
464 | static u32 intel_panel_compute_brightness(struct intel_connector *connector, |
336 | u32 val) |
465 | u32 val) |
337 | { |
466 | { |
338 | struct drm_device *dev = connector->base.dev; |
467 | struct drm_device *dev = connector->base.dev; |
339 | struct drm_i915_private *dev_priv = dev->dev_private; |
468 | struct drm_i915_private *dev_priv = dev->dev_private; |
Line 340... | Line 469... | ||
340 | struct intel_panel *panel = &connector->panel; |
469 | struct intel_panel *panel = &connector->panel; |
Line 341... | Line 470... | ||
341 | 470 | ||
342 | WARN_ON(panel->backlight.max == 0); |
471 | WARN_ON(panel->backlight.max == 0); |
Line 343... | Line 472... | ||
343 | 472 | ||
344 | if (i915_panel_invert_brightness < 0) |
473 | if (i915.invert_brightness < 0) |
345 | return val; |
474 | return val; |
346 | 475 | ||
Line 347... | Line 476... | ||
347 | if (i915_panel_invert_brightness > 0 || |
476 | if (i915.invert_brightness > 0 || |
Line 489... | Line 618... | ||
489 | 618 | ||
490 | level = intel_panel_compute_brightness(connector, level); |
619 | level = intel_panel_compute_brightness(connector, level); |
491 | dev_priv->display.set_backlight(connector, level); |
620 | dev_priv->display.set_backlight(connector, level); |
Line 492... | Line 621... | ||
492 | } |
621 | } |
493 | 622 | ||
494 | /* set backlight brightness to level in range [0..max] */ |
623 | /* set backlight brightness to level in range [0..max], scaling wrt hw min */ |
495 | void intel_panel_set_backlight(struct intel_connector *connector, u32 level, |
624 | static void intel_panel_set_backlight(struct intel_connector *connector, |
496 | u32 max) |
625 | u32 user_level, u32 user_max) |
497 | { |
626 | { |
498 | struct drm_device *dev = connector->base.dev; |
627 | struct drm_device *dev = connector->base.dev; |
499 | struct drm_i915_private *dev_priv = dev->dev_private; |
628 | struct drm_i915_private *dev_priv = dev->dev_private; |
500 | struct intel_panel *panel = &connector->panel; |
629 | struct intel_panel *panel = &connector->panel; |
501 | enum pipe pipe = intel_get_pipe_from_connector(connector); |
630 | enum pipe pipe = intel_get_pipe_from_connector(connector); |
Line 502... | Line 631... | ||
502 | u32 freq; |
631 | u32 hw_level; |
503 | unsigned long flags; |
632 | unsigned long flags; |
Line 504... | Line 633... | ||
504 | 633 | ||
Line 505... | Line 634... | ||
505 | if (!panel->backlight.present || pipe == INVALID_PIPE) |
634 | if (!panel->backlight.present || pipe == INVALID_PIPE) |
Line 506... | Line 635... | ||
506 | return; |
635 | return; |
- | 636 | ||
- | 637 | spin_lock_irqsave(&dev_priv->backlight_lock, flags); |
|
507 | 638 | ||
- | 639 | WARN_ON(panel->backlight.max == 0); |
|
- | 640 | ||
- | 641 | hw_level = scale_user_to_hw(connector, user_level, user_max); |
|
- | 642 | panel->backlight.level = hw_level; |
|
- | 643 | ||
- | 644 | if (panel->backlight.enabled) |
|
508 | spin_lock_irqsave(&dev_priv->backlight_lock, flags); |
645 | intel_panel_actually_set_backlight(connector, hw_level); |
- | 646 | ||
- | 647 | spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); |
|
509 | 648 | } |
|
- | 649 | ||
- | 650 | /* set backlight brightness to level in range [0..max], assuming hw min is |
|
- | 651 | * respected. |
|
- | 652 | */ |
|
- | 653 | void intel_panel_set_backlight_acpi(struct intel_connector *connector, |
|
- | 654 | u32 user_level, u32 user_max) |
|
- | 655 | { |
|
- | 656 | struct drm_device *dev = connector->base.dev; |
|
- | 657 | struct drm_i915_private *dev_priv = dev->dev_private; |
|
510 | WARN_ON(panel->backlight.max == 0); |
658 | struct intel_panel *panel = &connector->panel; |
- | 659 | enum pipe pipe = intel_get_pipe_from_connector(connector); |
|
- | 660 | u32 hw_level; |
|
- | 661 | unsigned long flags; |
|
- | 662 | ||
- | 663 | if (!panel->backlight.present || pipe == INVALID_PIPE) |
|
- | 664 | return; |
|
511 | 665 | ||
Line 512... | Line -... | ||
512 | /* scale to hardware max, but be careful to not overflow */ |
- | |
513 | freq = panel->backlight.max; |
- | |
514 | if (freq < max) |
- | |
Line 515... | Line 666... | ||
515 | level = level * freq / max; |
666 | spin_lock_irqsave(&dev_priv->backlight_lock, flags); |
516 | else |
667 | |
Line 517... | Line 668... | ||
517 | level = freq / max * level; |
668 | WARN_ON(panel->backlight.max == 0); |
518 | 669 | ||
Line 519... | Line 670... | ||
519 | panel->backlight.level = level; |
670 | hw_level = clamp_user_to_hw(connector, user_level, user_max); |
Line 696... | Line 847... | ||
696 | freq = panel->backlight.max; |
847 | freq = panel->backlight.max; |
697 | if (panel->backlight.combination_mode) |
848 | if (panel->backlight.combination_mode) |
698 | freq /= 0xff; |
849 | freq /= 0xff; |
Line 699... | Line 850... | ||
699 | 850 | ||
700 | ctl = freq << 17; |
851 | ctl = freq << 17; |
701 | if (IS_GEN2(dev) && panel->backlight.combination_mode) |
852 | if (panel->backlight.combination_mode) |
702 | ctl |= BLM_LEGACY_MODE; |
853 | ctl |= BLM_LEGACY_MODE; |
703 | if (IS_PINEVIEW(dev) && panel->backlight.active_low_pwm) |
854 | if (IS_PINEVIEW(dev) && panel->backlight.active_low_pwm) |
Line 704... | Line 855... | ||
704 | ctl |= BLM_POLARITY_PNV; |
855 | ctl |= BLM_POLARITY_PNV; |
Line 730... | Line 881... | ||
730 | freq /= 0xff; |
881 | freq /= 0xff; |
Line 731... | Line 882... | ||
731 | 882 | ||
732 | ctl = freq << 16; |
883 | ctl = freq << 16; |
Line 733... | Line -... | ||
733 | I915_WRITE(BLC_PWM_CTL, ctl); |
- | |
734 | - | ||
735 | /* XXX: combine this into above write? */ |
- | |
736 | intel_panel_actually_set_backlight(connector, panel->backlight.level); |
884 | I915_WRITE(BLC_PWM_CTL, ctl); |
737 | 885 | ||
738 | ctl2 = BLM_PIPE(pipe); |
886 | ctl2 = BLM_PIPE(pipe); |
739 | if (panel->backlight.combination_mode) |
887 | if (panel->backlight.combination_mode) |
740 | ctl2 |= BLM_COMBINATION_MODE; |
888 | ctl2 |= BLM_COMBINATION_MODE; |
741 | if (panel->backlight.active_low_pwm) |
889 | if (panel->backlight.active_low_pwm) |
742 | ctl2 |= BLM_POLARITY_I965; |
890 | ctl2 |= BLM_POLARITY_I965; |
743 | I915_WRITE(BLC_PWM_CTL2, ctl2); |
891 | I915_WRITE(BLC_PWM_CTL2, ctl2); |
- | 892 | POSTING_READ(BLC_PWM_CTL2); |
|
- | 893 | I915_WRITE(BLC_PWM_CTL2, ctl2 | BLM_PWM_ENABLE); |
|
744 | POSTING_READ(BLC_PWM_CTL2); |
894 | |
Line 745... | Line 895... | ||
745 | I915_WRITE(BLC_PWM_CTL2, ctl2 | BLM_PWM_ENABLE); |
895 | intel_panel_actually_set_backlight(connector, panel->backlight.level); |
746 | } |
896 | } |
747 | 897 | ||
Line 791... | Line 941... | ||
791 | 941 | ||
Line 792... | Line 942... | ||
792 | WARN_ON(panel->backlight.max == 0); |
942 | WARN_ON(panel->backlight.max == 0); |
793 | 943 | ||
794 | if (panel->backlight.level == 0) { |
- | |
795 | panel->backlight.level = panel->backlight.max; |
- | |
796 | // if (panel->backlight.device) |
- | |
797 | // panel->backlight.device->props.brightness = |
944 | if (panel->backlight.level == 0) { |
Line 798... | Line 945... | ||
798 | // panel->backlight.level; |
945 | panel->backlight.level = panel->backlight.max; |
799 | } |
946 | } |
Line 800... | Line 947... | ||
800 | 947 | ||
801 | dev_priv->display.enable_backlight(connector); |
948 | dev_priv->display.enable_backlight(connector); |
Line 802... | Line -... | ||
802 | panel->backlight.enabled = true; |
- | |
803 | - | ||
804 | spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); |
- | |
805 | } |
- | |
806 | - | ||
807 | enum drm_connector_status |
- | |
808 | intel_panel_detect(struct drm_device *dev) |
- | |
809 | { |
- | |
810 | struct drm_i915_private *dev_priv = dev->dev_private; |
- | |
811 | - | ||
812 | /* Assume that the BIOS does not lie through the OpRegion... */ |
- | |
813 | if (!i915_panel_ignore_lid && dev_priv->opregion.lid_state) { |
- | |
814 | return ioread32(dev_priv->opregion.lid_state) & 0x1 ? |
- | |
815 | connector_status_connected : |
- | |
816 | connector_status_disconnected; |
- | |
817 | } |
- | |
818 | - | ||
819 | switch (i915_panel_ignore_lid) { |
- | |
820 | case -2: |
- | |
821 | return connector_status_connected; |
- | |
822 | case -1: |
- | |
823 | return connector_status_disconnected; |
- | |
824 | default: |
949 | panel->backlight.enabled = true; |
825 | return connector_status_unknown; |
950 | |
826 | } |
951 | spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); |
827 | } |
952 | } |
828 | 953 | ||
Line 829... | Line 954... | ||
829 | #if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE) |
954 | #if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE) |
830 | static int intel_backlight_device_update_status(struct backlight_device *bd) |
955 | static int intel_backlight_device_update_status(struct backlight_device *bd) |
831 | { |
956 | { |
832 | struct intel_connector *connector = bl_get_data(bd); |
957 | struct intel_connector *connector = bl_get_data(bd); |
833 | struct drm_device *dev = connector->base.dev; |
958 | struct drm_device *dev = connector->base.dev; |
834 | 959 | ||
835 | mutex_lock(&dev->mode_config.mutex); |
960 | drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); |
836 | DRM_DEBUG_KMS("updating intel_backlight, brightness=%d/%d\n", |
961 | DRM_DEBUG_KMS("updating intel_backlight, brightness=%d/%d\n", |
Line 837... | Line 962... | ||
837 | bd->props.brightness, bd->props.max_brightness); |
962 | bd->props.brightness, bd->props.max_brightness); |
838 | intel_panel_set_backlight(connector, bd->props.brightness, |
963 | intel_panel_set_backlight(connector, bd->props.brightness, |
839 | bd->props.max_brightness); |
964 | bd->props.max_brightness); |
840 | mutex_unlock(&dev->mode_config.mutex); |
965 | drm_modeset_unlock(&dev->mode_config.connection_mutex); |
841 | return 0; |
966 | return 0; |
- | 967 | } |
|
842 | } |
968 | |
Line 843... | Line 969... | ||
843 | 969 | static int intel_backlight_device_get_brightness(struct backlight_device *bd) |
|
844 | static int intel_backlight_device_get_brightness(struct backlight_device *bd) |
970 | { |
- | 971 | struct intel_connector *connector = bl_get_data(bd); |
|
845 | { |
972 | struct drm_device *dev = connector->base.dev; |
- | 973 | struct drm_i915_private *dev_priv = dev->dev_private; |
|
- | 974 | u32 hw_level; |
|
846 | struct intel_connector *connector = bl_get_data(bd); |
975 | int ret; |
847 | struct drm_device *dev = connector->base.dev; |
976 | |
Line 848... | Line 977... | ||
848 | struct drm_i915_private *dev_priv = dev->dev_private; |
977 | intel_runtime_pm_get(dev_priv); |
849 | int ret; |
978 | drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); |
Line 868... | Line 997... | ||
868 | struct backlight_properties props; |
997 | struct backlight_properties props; |
Line 869... | Line 998... | ||
869 | 998 | ||
870 | if (WARN_ON(panel->backlight.device)) |
999 | if (WARN_ON(panel->backlight.device)) |
Line 871... | Line 1000... | ||
871 | return -ENODEV; |
1000 | return -ENODEV; |
Line 872... | Line 1001... | ||
872 | 1001 | ||
873 | BUG_ON(panel->backlight.max == 0); |
1002 | WARN_ON(panel->backlight.max == 0); |
- | 1003 | ||
- | 1004 | memset(&props, 0, sizeof(props)); |
|
874 | 1005 | props.type = BACKLIGHT_RAW; |
|
- | 1006 | ||
- | 1007 | /* |
|
875 | memset(&props, 0, sizeof(props)); |
1008 | * Note: Everything should work even if the backlight device max |
- | 1009 | * presented to the userspace is arbitrarily chosen. |
|
- | 1010 | */ |
|
- | 1011 | props.max_brightness = panel->backlight.max; |
|
Line 876... | Line 1012... | ||
876 | props.type = BACKLIGHT_RAW; |
1012 | props.brightness = scale_hw_to_user(connector, |
877 | props.brightness = panel->backlight.level; |
1013 | panel->backlight.level, |
878 | props.max_brightness = panel->backlight.max; |
1014 | props.max_brightness); |
879 | 1015 | ||
Line 919... | Line 1055... | ||
919 | * Note: The setup hooks can't assume pipe is set! |
1055 | * Note: The setup hooks can't assume pipe is set! |
920 | * |
1056 | * |
921 | * XXX: Query mode clock or hardware clock and program PWM modulation frequency |
1057 | * XXX: Query mode clock or hardware clock and program PWM modulation frequency |
922 | * appropriately when it's 0. Use VBT and/or sane defaults. |
1058 | * appropriately when it's 0. Use VBT and/or sane defaults. |
923 | */ |
1059 | */ |
- | 1060 | static u32 get_backlight_min_vbt(struct intel_connector *connector) |
|
- | 1061 | { |
|
- | 1062 | struct drm_device *dev = connector->base.dev; |
|
- | 1063 | struct drm_i915_private *dev_priv = dev->dev_private; |
|
- | 1064 | struct intel_panel *panel = &connector->panel; |
|
- | 1065 | ||
- | 1066 | WARN_ON(panel->backlight.max == 0); |
|
- | 1067 | ||
- | 1068 | /* vbt value is a coefficient in range [0..255] */ |
|
- | 1069 | return scale(dev_priv->vbt.backlight.min_brightness, 0, 255, |
|
- | 1070 | 0, panel->backlight.max); |
|
- | 1071 | } |
|
- | 1072 | ||
924 | static int bdw_setup_backlight(struct intel_connector *connector) |
1073 | static int bdw_setup_backlight(struct intel_connector *connector) |
925 | { |
1074 | { |
926 | struct drm_device *dev = connector->base.dev; |
1075 | struct drm_device *dev = connector->base.dev; |
927 | struct drm_i915_private *dev_priv = dev->dev_private; |
1076 | struct drm_i915_private *dev_priv = dev->dev_private; |
928 | struct intel_panel *panel = &connector->panel; |
1077 | struct intel_panel *panel = &connector->panel; |
Line 934... | Line 1083... | ||
934 | pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2); |
1083 | pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2); |
935 | panel->backlight.max = pch_ctl2 >> 16; |
1084 | panel->backlight.max = pch_ctl2 >> 16; |
936 | if (!panel->backlight.max) |
1085 | if (!panel->backlight.max) |
937 | return -ENODEV; |
1086 | return -ENODEV; |
Line -... | Line 1087... | ||
- | 1087 | ||
- | 1088 | panel->backlight.min = get_backlight_min_vbt(connector); |
|
938 | 1089 | ||
939 | val = bdw_get_backlight(connector); |
1090 | val = bdw_get_backlight(connector); |
Line 940... | Line 1091... | ||
940 | panel->backlight.level = intel_panel_compute_brightness(connector, val); |
1091 | panel->backlight.level = intel_panel_compute_brightness(connector, val); |
941 | 1092 | ||
Line 958... | Line 1109... | ||
958 | pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2); |
1109 | pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2); |
959 | panel->backlight.max = pch_ctl2 >> 16; |
1110 | panel->backlight.max = pch_ctl2 >> 16; |
960 | if (!panel->backlight.max) |
1111 | if (!panel->backlight.max) |
961 | return -ENODEV; |
1112 | return -ENODEV; |
Line -... | Line 1113... | ||
- | 1113 | ||
- | 1114 | panel->backlight.min = get_backlight_min_vbt(connector); |
|
962 | 1115 | ||
963 | val = pch_get_backlight(connector); |
1116 | val = pch_get_backlight(connector); |
Line 964... | Line 1117... | ||
964 | panel->backlight.level = intel_panel_compute_brightness(connector, val); |
1117 | panel->backlight.level = intel_panel_compute_brightness(connector, val); |
965 | 1118 | ||
Line 977... | Line 1130... | ||
977 | struct intel_panel *panel = &connector->panel; |
1130 | struct intel_panel *panel = &connector->panel; |
978 | u32 ctl, val; |
1131 | u32 ctl, val; |
Line 979... | Line 1132... | ||
979 | 1132 | ||
Line 980... | Line 1133... | ||
980 | ctl = I915_READ(BLC_PWM_CTL); |
1133 | ctl = I915_READ(BLC_PWM_CTL); |
981 | 1134 | ||
Line 982... | Line 1135... | ||
982 | if (IS_GEN2(dev)) |
1135 | if (IS_GEN2(dev) || IS_I915GM(dev) || IS_I945GM(dev)) |
983 | panel->backlight.combination_mode = ctl & BLM_LEGACY_MODE; |
1136 | panel->backlight.combination_mode = ctl & BLM_LEGACY_MODE; |
Line 990... | Line 1143... | ||
990 | panel->backlight.max *= 0xff; |
1143 | panel->backlight.max *= 0xff; |
Line 991... | Line 1144... | ||
991 | 1144 | ||
992 | if (!panel->backlight.max) |
1145 | if (!panel->backlight.max) |
Line -... | Line 1146... | ||
- | 1146 | return -ENODEV; |
|
- | 1147 | ||
993 | return -ENODEV; |
1148 | panel->backlight.min = get_backlight_min_vbt(connector); |
994 | 1149 | ||
Line 995... | Line 1150... | ||
995 | val = i9xx_get_backlight(connector); |
1150 | val = i9xx_get_backlight(connector); |
Line 1017... | Line 1172... | ||
1017 | panel->backlight.max *= 0xff; |
1172 | panel->backlight.max *= 0xff; |
Line 1018... | Line 1173... | ||
1018 | 1173 | ||
1019 | if (!panel->backlight.max) |
1174 | if (!panel->backlight.max) |
Line -... | Line 1175... | ||
- | 1175 | return -ENODEV; |
|
- | 1176 | ||
1020 | return -ENODEV; |
1177 | panel->backlight.min = get_backlight_min_vbt(connector); |
1021 | 1178 | ||
Line 1022... | Line 1179... | ||
1022 | val = i9xx_get_backlight(connector); |
1179 | val = i9xx_get_backlight(connector); |
1023 | panel->backlight.level = intel_panel_compute_brightness(connector, val); |
1180 | panel->backlight.level = intel_panel_compute_brightness(connector, val); |
Line 1054... | Line 1211... | ||
1054 | ctl = I915_READ(VLV_BLC_PWM_CTL(PIPE_A)); |
1211 | ctl = I915_READ(VLV_BLC_PWM_CTL(PIPE_A)); |
1055 | panel->backlight.max = ctl >> 16; |
1212 | panel->backlight.max = ctl >> 16; |
1056 | if (!panel->backlight.max) |
1213 | if (!panel->backlight.max) |
1057 | return -ENODEV; |
1214 | return -ENODEV; |
Line -... | Line 1215... | ||
- | 1215 | ||
- | 1216 | panel->backlight.min = get_backlight_min_vbt(connector); |
|
1058 | 1217 | ||
1059 | val = _vlv_get_backlight(dev, PIPE_A); |
1218 | val = _vlv_get_backlight(dev, PIPE_A); |
Line 1060... | Line 1219... | ||
1060 | panel->backlight.level = intel_panel_compute_brightness(connector, val); |
1219 | panel->backlight.level = intel_panel_compute_brightness(connector, val); |
1061 | 1220 | ||
Line 1072... | Line 1231... | ||
1072 | struct intel_connector *intel_connector = to_intel_connector(connector); |
1231 | struct intel_connector *intel_connector = to_intel_connector(connector); |
1073 | struct intel_panel *panel = &intel_connector->panel; |
1232 | struct intel_panel *panel = &intel_connector->panel; |
1074 | unsigned long flags; |
1233 | unsigned long flags; |
1075 | int ret; |
1234 | int ret; |
Line -... | Line 1235... | ||
- | 1235 | ||
- | 1236 | if (!dev_priv->vbt.backlight.present) { |
|
- | 1237 | if (dev_priv->quirks & QUIRK_BACKLIGHT_PRESENT) { |
|
- | 1238 | DRM_DEBUG_KMS("no backlight present per VBT, but present per quirk\n"); |
|
- | 1239 | } else { |
|
- | 1240 | DRM_DEBUG_KMS("no backlight present per VBT\n"); |
|
- | 1241 | return 0; |
|
- | 1242 | } |
|
- | 1243 | } |
|
1076 | 1244 | ||
1077 | /* set level and max in panel struct */ |
1245 | /* set level and max in panel struct */ |
1078 | spin_lock_irqsave(&dev_priv->backlight_lock, flags); |
1246 | spin_lock_irqsave(&dev_priv->backlight_lock, flags); |
1079 | ret = dev_priv->display.setup_backlight(intel_connector); |
1247 | ret = dev_priv->display.setup_backlight(intel_connector); |
Line 1080... | Line 1248... | ||
1080 | spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); |
1248 | spin_unlock_irqrestore(&dev_priv->backlight_lock, flags); |
1081 | 1249 | ||
1082 | if (ret) { |
1250 | if (ret) { |
1083 | DRM_DEBUG_KMS("failed to setup backlight for connector %s\n", |
1251 | DRM_DEBUG_KMS("failed to setup backlight for connector %s\n", |
1084 | drm_get_connector_name(connector)); |
1252 | connector->name); |
Line 1085... | Line 1253... | ||
1085 | return ret; |
1253 | return ret; |
Line 1105... | Line 1273... | ||
1105 | 1273 | ||
1106 | panel->backlight.present = false; |
1274 | panel->backlight.present = false; |
1107 | intel_backlight_device_unregister(intel_connector); |
1275 | intel_backlight_device_unregister(intel_connector); |
Line 1108... | Line -... | ||
1108 | } |
- | |
1109 | - | ||
1110 | /** |
- | |
1111 | * intel_find_panel_downclock - find the reduced downclock for LVDS in EDID |
- | |
1112 | * @dev: drm device |
- | |
1113 | * @fixed_mode : panel native mode |
- | |
1114 | * @connector: LVDS/eDP connector |
- | |
1115 | * |
- | |
1116 | * Return downclock_avail |
- | |
1117 | * Find the reduced downclock for LVDS/eDP in EDID. |
- | |
1118 | */ |
- | |
1119 | struct drm_display_mode * |
- | |
1120 | intel_find_panel_downclock(struct drm_device *dev, |
- | |
1121 | struct drm_display_mode *fixed_mode, |
- | |
1122 | struct drm_connector *connector) |
- | |
1123 | { |
- | |
1124 | struct drm_display_mode *scan, *tmp_mode; |
- | |
1125 | int temp_downclock; |
- | |
1126 | - | ||
1127 | temp_downclock = fixed_mode->clock; |
- | |
1128 | tmp_mode = NULL; |
- | |
1129 | - | ||
1130 | list_for_each_entry(scan, &connector->probed_modes, head) { |
- | |
1131 | /* |
- | |
1132 | * If one mode has the same resolution with the fixed_panel |
- | |
1133 | * mode while they have the different refresh rate, it means |
- | |
1134 | * that the reduced downclock is found. In such |
- | |
1135 | * case we can set the different FPx0/1 to dynamically select |
- | |
1136 | * between low and high frequency. |
- | |
1137 | */ |
- | |
1138 | if (scan->hdisplay == fixed_mode->hdisplay && |
- | |
1139 | scan->hsync_start == fixed_mode->hsync_start && |
- | |
1140 | scan->hsync_end == fixed_mode->hsync_end && |
- | |
1141 | scan->htotal == fixed_mode->htotal && |
- | |
1142 | scan->vdisplay == fixed_mode->vdisplay && |
- | |
1143 | scan->vsync_start == fixed_mode->vsync_start && |
- | |
1144 | scan->vsync_end == fixed_mode->vsync_end && |
- | |
1145 | scan->vtotal == fixed_mode->vtotal) { |
- | |
1146 | if (scan->clock < temp_downclock) { |
- | |
1147 | /* |
- | |
1148 | * The downclock is already found. But we |
- | |
1149 | * expect to find the lower downclock. |
- | |
1150 | */ |
- | |
1151 | temp_downclock = scan->clock; |
- | |
1152 | tmp_mode = scan; |
- | |
1153 | } |
- | |
1154 | } |
- | |
1155 | } |
- | |
1156 | - | ||
1157 | if (temp_downclock < fixed_mode->clock) |
- | |
1158 | return drm_mode_duplicate(dev, tmp_mode); |
- | |
1159 | else |
- | |
1160 | return NULL; |
- | |
1161 | } |
1276 | } |
1162 | 1277 | ||
1163 | /* Set up chip specific backlight functions */ |
1278 | /* Set up chip specific backlight functions */ |
1164 | void intel_panel_init_backlight_funcs(struct drm_device *dev) |
1279 | void intel_panel_init_backlight_funcs(struct drm_device *dev) |
Line 1197... | Line 1312... | ||
1197 | dev_priv->display.get_backlight = i9xx_get_backlight; |
1312 | dev_priv->display.get_backlight = i9xx_get_backlight; |
1198 | } |
1313 | } |
1199 | } |
1314 | } |
Line 1200... | Line 1315... | ||
1200 | 1315 | ||
1201 | int intel_panel_init(struct intel_panel *panel, |
1316 | int intel_panel_init(struct intel_panel *panel, |
- | 1317 | struct drm_display_mode *fixed_mode, |
|
1202 | struct drm_display_mode *fixed_mode) |
1318 | struct drm_display_mode *downclock_mode) |
1203 | { |
1319 | { |
- | 1320 | panel->fixed_mode = fixed_mode; |
|
Line 1204... | Line 1321... | ||
1204 | panel->fixed_mode = fixed_mode; |
1321 | panel->downclock_mode = downclock_mode; |
1205 | 1322 | ||
Line 1206... | Line 1323... | ||
1206 | return 0; |
1323 | return 0; |