diff options
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/i915/i915_debugfs.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_suspend.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 119 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_lvds.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_opregion.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_panel.c | 72 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/atombios_dp.c | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/evergreen.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_connectors.c | 29 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_device.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_encoders.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_mode.h | 1 |
16 files changed, 213 insertions, 60 deletions
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index a8ab6263e0d7..3c395a59da35 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -499,7 +499,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data) seq_printf(m, "Interrupts received: %d\n", atomic_read(&dev_priv->irq_received)); for (i = 0; i < I915_NUM_RINGS; i++) { - if (IS_GEN6(dev)) { + if (IS_GEN6(dev) || IS_GEN7(dev)) { seq_printf(m, "Graphics Interrupt mask (%s): %08x\n", dev_priv->ring[i].name, I915_READ_IMR(&dev_priv->ring[i])); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index feb4f164fd1b..7916bd97d5c1 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -36,6 +36,7 @@ #include <linux/io-mapping.h> #include <linux/i2c.h> #include <drm/intel-gtt.h> +#include <linux/backlight.h> /* General customization: */ @@ -690,6 +691,7 @@ typedef struct drm_i915_private { int child_dev_num; struct child_device_config *child_dev; struct drm_connector *int_lvds_connector; + struct drm_connector *int_edp_connector; bool mchbar_need_disable; @@ -723,6 +725,8 @@ typedef struct drm_i915_private { /* list of fbdev register on this device */ struct intel_fbdev *fbdev; + struct backlight_device *backlight; + struct drm_property *broadcast_rgb_property; struct drm_property *force_audio_property; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 02f96fd0d52d..9cbb0cd8f46a 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2058,8 +2058,10 @@ void intel_irq_init(struct drm_device *dev) dev->driver->get_vblank_counter = gm45_get_vblank_counter; } - - dev->driver->get_vblank_timestamp = i915_get_vblank_timestamp; + if (drm_core_check_feature(dev, DRIVER_MODESET)) + dev->driver->get_vblank_timestamp = i915_get_vblank_timestamp; + else + dev->driver->get_vblank_timestamp = NULL; dev->driver->get_scanout_position = i915_get_crtc_scanoutpos; if (IS_IVYBRIDGE(dev)) { diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index 87677d60d0df..f10742359ec9 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -871,7 +871,8 @@ int i915_restore_state(struct drm_device *dev) } mutex_unlock(&dev->struct_mutex); - intel_init_clock_gating(dev); + if (drm_core_check_feature(dev, DRIVER_MODESET)) + intel_init_clock_gating(dev); if (IS_IRONLAKE_M(dev)) { ironlake_enable_drps(dev); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index f6f18c72068f..ee1d701317f7 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5097,6 +5097,81 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, return ret; } +static void ironlake_update_pch_refclk(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_mode_config *mode_config = &dev->mode_config; + struct drm_crtc *crtc; + struct intel_encoder *encoder; + struct intel_encoder *has_edp_encoder = NULL; + u32 temp; + bool has_lvds = false; + + /* We need to take the global config into account */ + list_for_each_entry(crtc, &mode_config->crtc_list, head) { + if (!crtc->enabled) + continue; + + list_for_each_entry(encoder, &mode_config->encoder_list, + base.head) { + if (encoder->base.crtc != crtc) + continue; + + switch (encoder->type) { + case INTEL_OUTPUT_LVDS: + has_lvds = true; + case INTEL_OUTPUT_EDP: + has_edp_encoder = encoder; + break; + } + } + } + + /* Ironlake: try to setup display ref clock before DPLL + * enabling. This is only under driver's control after + * PCH B stepping, previous chipset stepping should be + * ignoring this setting. + */ + temp = I915_READ(PCH_DREF_CONTROL); + /* Always enable nonspread source */ + temp &= ~DREF_NONSPREAD_SOURCE_MASK; + temp |= DREF_NONSPREAD_SOURCE_ENABLE; + temp &= ~DREF_SSC_SOURCE_MASK; + temp |= DREF_SSC_SOURCE_ENABLE; + I915_WRITE(PCH_DREF_CONTROL, temp); + + POSTING_READ(PCH_DREF_CONTROL); + udelay(200); + + if (has_edp_encoder) { + if (intel_panel_use_ssc(dev_priv)) { + temp |= DREF_SSC1_ENABLE; + I915_WRITE(PCH_DREF_CONTROL, temp); + + POSTING_READ(PCH_DREF_CONTROL); + udelay(200); + } + temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK; + + /* Enable CPU source on CPU attached eDP */ + if (!intel_encoder_is_pch_edp(&has_edp_encoder->base)) { + if (intel_panel_use_ssc(dev_priv)) + temp |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD; + else + temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD; + } else { + /* Enable SSC on PCH eDP if needed */ + if (intel_panel_use_ssc(dev_priv)) { + DRM_ERROR("enabling SSC on PCH\n"); + temp |= DREF_SUPERSPREAD_SOURCE_ENABLE; + } + } + I915_WRITE(PCH_DREF_CONTROL, temp); + POSTING_READ(PCH_DREF_CONTROL); + udelay(200); + } +} + static int ironlake_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode, @@ -5292,49 +5367,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, ironlake_compute_m_n(intel_crtc->bpp, lane, target_clock, link_bw, &m_n); - /* Ironlake: try to setup display ref clock before DPLL - * enabling. This is only under driver's control after - * PCH B stepping, previous chipset stepping should be - * ignoring this setting. - */ - temp = I915_READ(PCH_DREF_CONTROL); - /* Always enable nonspread source */ - temp &= ~DREF_NONSPREAD_SOURCE_MASK; - temp |= DREF_NONSPREAD_SOURCE_ENABLE; - temp &= ~DREF_SSC_SOURCE_MASK; - temp |= DREF_SSC_SOURCE_ENABLE; - I915_WRITE(PCH_DREF_CONTROL, temp); - - POSTING_READ(PCH_DREF_CONTROL); - udelay(200); - - if (has_edp_encoder) { - if (intel_panel_use_ssc(dev_priv)) { - temp |= DREF_SSC1_ENABLE; - I915_WRITE(PCH_DREF_CONTROL, temp); - - POSTING_READ(PCH_DREF_CONTROL); - udelay(200); - } - temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK; - - /* Enable CPU source on CPU attached eDP */ - if (!intel_encoder_is_pch_edp(&has_edp_encoder->base)) { - if (intel_panel_use_ssc(dev_priv)) - temp |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD; - else - temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD; - } else { - /* Enable SSC on PCH eDP if needed */ - if (intel_panel_use_ssc(dev_priv)) { - DRM_ERROR("enabling SSC on PCH\n"); - temp |= DREF_SUPERSPREAD_SOURCE_ENABLE; - } - } - I915_WRITE(PCH_DREF_CONTROL, temp); - POSTING_READ(PCH_DREF_CONTROL); - udelay(200); - } + ironlake_update_pch_refclk(dev); fp = clock.n << 16 | clock.m1 << 8 | clock.m2; if (has_reduced_clock) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 0feae908bb37..44fef5e1c490 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1841,6 +1841,11 @@ done: static void intel_dp_destroy (struct drm_connector *connector) { + struct drm_device *dev = connector->dev; + + if (intel_dpd_is_edp(dev)) + intel_panel_destroy_backlight(dev); + drm_sysfs_connector_remove(connector); drm_connector_cleanup(connector); kfree(connector); @@ -2072,6 +2077,8 @@ intel_dp_init(struct drm_device *dev, int output_reg) DRM_MODE_TYPE_PREFERRED; } } + dev_priv->int_edp_connector = connector; + intel_panel_setup_backlight(dev); } intel_dp_add_properties(intel_dp, connector); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 7b330e76a435..0b2ee9d39980 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -297,9 +297,10 @@ extern void intel_pch_panel_fitting(struct drm_device *dev, extern u32 intel_panel_get_max_backlight(struct drm_device *dev); extern u32 intel_panel_get_backlight(struct drm_device *dev); extern void intel_panel_set_backlight(struct drm_device *dev, u32 level); -extern void intel_panel_setup_backlight(struct drm_device *dev); +extern int intel_panel_setup_backlight(struct drm_device *dev); extern void intel_panel_enable_backlight(struct drm_device *dev); extern void intel_panel_disable_backlight(struct drm_device *dev); +extern void intel_panel_destroy_backlight(struct drm_device *dev); extern enum drm_connector_status intel_panel_detect(struct drm_device *dev); extern void intel_crtc_load_lut(struct drm_crtc *crtc); diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 8b521a289b29..31da77f5c051 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -552,6 +552,8 @@ static void intel_lvds_destroy(struct drm_connector *connector) struct drm_device *dev = connector->dev; struct drm_i915_private *dev_priv = dev->dev_private; + intel_panel_destroy_backlight(dev); + if (dev_priv->lid_notifier.notifier_call) acpi_lid_notifier_unregister(&dev_priv->lid_notifier); drm_sysfs_connector_remove(connector); @@ -1032,6 +1034,9 @@ out: /* keep the LVDS connector */ dev_priv->int_lvds_connector = connector; drm_sysfs_connector_add(connector); + + intel_panel_setup_backlight(dev); + return true; failed: diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c index b7c5ddb564d1..b8e8158bb16e 100644 --- a/drivers/gpu/drm/i915/intel_opregion.c +++ b/drivers/gpu/drm/i915/intel_opregion.c @@ -227,7 +227,6 @@ void intel_opregion_asle_intr(struct drm_device *dev) asle->aslc = asle_stat; } -/* Only present on Ironlake+ */ void intel_opregion_gse_intr(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 05f500cd9c24..a9e0c7bcd317 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -277,7 +277,7 @@ void intel_panel_enable_backlight(struct drm_device *dev) dev_priv->backlight_enabled = true; } -void intel_panel_setup_backlight(struct drm_device *dev) +static void intel_panel_init_backlight(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -309,3 +309,73 @@ intel_panel_detect(struct drm_device *dev) return connector_status_unknown; } + +#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE +static int intel_panel_update_status(struct backlight_device *bd) +{ + struct drm_device *dev = bl_get_data(bd); + intel_panel_set_backlight(dev, bd->props.brightness); + return 0; +} + +static int intel_panel_get_brightness(struct backlight_device *bd) +{ + struct drm_device *dev = bl_get_data(bd); + return intel_panel_get_backlight(dev); +} + +static const struct backlight_ops intel_panel_bl_ops = { + .update_status = intel_panel_update_status, + .get_brightness = intel_panel_get_brightness, +}; + +int intel_panel_setup_backlight(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct backlight_properties props; + struct drm_connector *connector; + + intel_panel_init_backlight(dev); + + if (dev_priv->int_lvds_connector) + connector = dev_priv->int_lvds_connector; + else if (dev_priv->int_edp_connector) + connector = dev_priv->int_edp_connector; + else + return -ENODEV; + + props.type = BACKLIGHT_RAW; + props.max_brightness = intel_panel_get_max_backlight(dev); + dev_priv->backlight = + backlight_device_register("intel_backlight", + &connector->kdev, dev, + &intel_panel_bl_ops, &props); + + if (IS_ERR(dev_priv->backlight)) { + DRM_ERROR("Failed to register backlight: %ld\n", + PTR_ERR(dev_priv->backlight)); + dev_priv->backlight = NULL; + return -ENODEV; + } + dev_priv->backlight->props.brightness = intel_panel_get_backlight(dev); + return 0; +} + +void intel_panel_destroy_backlight(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + if (dev_priv->backlight) + backlight_device_unregister(dev_priv->backlight); +} +#else +int intel_panel_setup_backlight(struct drm_device *dev) +{ + intel_panel_init_backlight(dev); + return 0; +} + +void intel_panel_destroy_backlight(struct drm_device *dev) +{ + return; +} +#endif diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index 645b84b3d203..7ad43c6b1db7 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c @@ -613,6 +613,18 @@ static bool radeon_dp_get_link_status(struct radeon_connector *radeon_connector, return true; } +bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector) +{ + u8 link_status[DP_LINK_STATUS_SIZE]; + struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; + + if (!radeon_dp_get_link_status(radeon_connector, link_status)) + return false; + if (dp_channel_eq_ok(link_status, dig->dp_lane_count)) + return false; + return true; +} + struct radeon_dp_link_train_info { struct radeon_device *rdev; struct drm_encoder *encoder; diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 14dce9f22172..fb5fa0898868 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -743,7 +743,7 @@ static void evergreen_program_watermarks(struct radeon_device *rdev, !evergreen_average_bandwidth_vs_available_bandwidth(&wm) || !evergreen_check_latency_hiding(&wm) || (rdev->disp_priority == 2)) { - DRM_INFO("force priority to high\n"); + DRM_DEBUG_KMS("force priority to high\n"); priority_a_cnt |= PRIORITY_ALWAYS_ON; priority_b_cnt |= PRIORITY_ALWAYS_ON; } diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 6d6b5f16bc09..7f65940f918f 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -60,18 +60,20 @@ void radeon_connector_hotplug(struct drm_connector *connector) radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); - /* powering up/down the eDP panel generates hpd events which - * can interfere with modesetting. - */ - if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) + /* if the connector is already off, don't turn it back on */ + if (connector->dpms != DRM_MODE_DPMS_ON) return; - /* pre-r600 did not always have the hpd pins mapped accurately to connectors */ - if (rdev->family >= CHIP_R600) { - if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) + /* just deal with DP (not eDP) here. */ + if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) { + int saved_dpms = connector->dpms; + + if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd) && + radeon_dp_needs_link_train(radeon_connector)) drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); else drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); + connector->dpms = saved_dpms; } } @@ -474,11 +476,19 @@ static void radeon_fixup_lvds_native_mode(struct drm_encoder *encoder, { struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct drm_display_mode *native_mode = &radeon_encoder->native_mode; + struct drm_display_mode *t, *mode; + + /* If the EDID preferred mode doesn't match the native mode, use it */ + list_for_each_entry_safe(mode, t, &connector->probed_modes, head) { + if (mode->type & DRM_MODE_TYPE_PREFERRED) { + if (mode->hdisplay != native_mode->hdisplay || + mode->vdisplay != native_mode->vdisplay) + memcpy(native_mode, mode, sizeof(*mode)); + } + } /* Try to get native mode details from EDID if necessary */ if (!native_mode->clock) { - struct drm_display_mode *t, *mode; - list_for_each_entry_safe(mode, t, &connector->probed_modes, head) { if (mode->hdisplay == native_mode->hdisplay && mode->vdisplay == native_mode->vdisplay) { @@ -489,6 +499,7 @@ static void radeon_fixup_lvds_native_mode(struct drm_encoder *encoder, } } } + if (!native_mode->clock) { DRM_DEBUG_KMS("No LVDS native mode details, disabling RMX\n"); radeon_encoder->rmx_type = RMX_OFF; diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 440e6ecccc40..a3b011b49465 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -32,6 +32,7 @@ #include <drm/radeon_drm.h> #include <linux/vgaarb.h> #include <linux/vga_switcheroo.h> +#include <linux/efi.h> #include "radeon_reg.h" #include "radeon.h" #include "atom.h" @@ -348,6 +349,9 @@ bool radeon_card_posted(struct radeon_device *rdev) { uint32_t reg; + if (efi_enabled && rdev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE) + return false; + /* first check CRTCs */ if (ASIC_IS_DCE41(rdev)) { reg = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) | diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index b293487e5aa3..319d85d7e759 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -2323,6 +2323,9 @@ radeon_add_atom_encoder(struct drm_device *dev, default: encoder->possible_crtcs = 0x3; break; + case 4: + encoder->possible_crtcs = 0xf; + break; case 6: encoder->possible_crtcs = 0x3f; break; diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index d09031c03e26..68820f5f6303 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -479,6 +479,7 @@ extern void radeon_dp_set_link_config(struct drm_connector *connector, struct drm_display_mode *mode); extern void radeon_dp_link_train(struct drm_encoder *encoder, struct drm_connector *connector); +extern bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector); extern u8 radeon_dp_getsinktype(struct radeon_connector *radeon_connector); extern bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector); extern void atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mode); |