Merge tag 'drm-intel-fixes-2014-07-09' of git://anongit.freedesktop.org/drm-intel into drm-fixes
Fixes for regressions and black screens, cc: stable where applicapable (the last minute rebase was to sprinkle missing stable tags). A bit more than what I'd wish for, but excluding vlv and that the first 3 patches are just quirks for 1 regression it looks much better. There's still a "oops, lost dithering" issue on older platforms open. I'm working on a fix for that now but didn't want to delay this pile. * tag 'drm-intel-fixes-2014-07-09' of git://anongit.freedesktop.org/drm-intel: drm/i915/vlv: T12 eDP panel timing enforcement during reboot drm/i915: Only unbind vgacon, not other console drivers drm/i915: Don't clobber the GTT when it's within stolen memory drm/i915/vlv: Update the DSI ULPS entry/exit sequence drm/i915/vlv: DPI FIFO empty check is not needed drm/i915: Toshiba CB35 has a controllable backlight drm/i915: Acer C720 and C720P have controllable backlights drm/i915: quirk asserts controllable backlight presence, overriding VBT
This commit is contained in:
commit
2db38e06ec
@ -1464,12 +1464,13 @@ static int i915_kick_out_vgacon(struct drm_i915_private *dev_priv)
|
||||
#else
|
||||
static int i915_kick_out_vgacon(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
DRM_INFO("Replacing VGA console driver\n");
|
||||
|
||||
console_lock();
|
||||
ret = do_take_over_console(&dummy_con, 0, MAX_NR_CONSOLES - 1, 1);
|
||||
if (con_is_bound(&vga_con))
|
||||
ret = do_take_over_console(&dummy_con, 0, MAX_NR_CONSOLES - 1, 1);
|
||||
if (ret == 0) {
|
||||
ret = do_unregister_con_driver(&vga_con);
|
||||
|
||||
|
@ -656,6 +656,7 @@ enum intel_sbi_destination {
|
||||
#define QUIRK_PIPEA_FORCE (1<<0)
|
||||
#define QUIRK_LVDS_SSC_DISABLE (1<<1)
|
||||
#define QUIRK_INVERT_BRIGHTNESS (1<<2)
|
||||
#define QUIRK_BACKLIGHT_PRESENT (1<<3)
|
||||
|
||||
struct intel_fbdev;
|
||||
struct intel_fbc_work;
|
||||
|
@ -74,6 +74,50 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
|
||||
if (base == 0)
|
||||
return 0;
|
||||
|
||||
/* make sure we don't clobber the GTT if it's within stolen memory */
|
||||
if (INTEL_INFO(dev)->gen <= 4 && !IS_G33(dev) && !IS_G4X(dev)) {
|
||||
struct {
|
||||
u32 start, end;
|
||||
} stolen[2] = {
|
||||
{ .start = base, .end = base + dev_priv->gtt.stolen_size, },
|
||||
{ .start = base, .end = base + dev_priv->gtt.stolen_size, },
|
||||
};
|
||||
u64 gtt_start, gtt_end;
|
||||
|
||||
gtt_start = I915_READ(PGTBL_CTL);
|
||||
if (IS_GEN4(dev))
|
||||
gtt_start = (gtt_start & PGTBL_ADDRESS_LO_MASK) |
|
||||
(gtt_start & PGTBL_ADDRESS_HI_MASK) << 28;
|
||||
else
|
||||
gtt_start &= PGTBL_ADDRESS_LO_MASK;
|
||||
gtt_end = gtt_start + gtt_total_entries(dev_priv->gtt) * 4;
|
||||
|
||||
if (gtt_start >= stolen[0].start && gtt_start < stolen[0].end)
|
||||
stolen[0].end = gtt_start;
|
||||
if (gtt_end > stolen[1].start && gtt_end <= stolen[1].end)
|
||||
stolen[1].start = gtt_end;
|
||||
|
||||
/* pick the larger of the two chunks */
|
||||
if (stolen[0].end - stolen[0].start >
|
||||
stolen[1].end - stolen[1].start) {
|
||||
base = stolen[0].start;
|
||||
dev_priv->gtt.stolen_size = stolen[0].end - stolen[0].start;
|
||||
} else {
|
||||
base = stolen[1].start;
|
||||
dev_priv->gtt.stolen_size = stolen[1].end - stolen[1].start;
|
||||
}
|
||||
|
||||
if (stolen[0].start != stolen[1].start ||
|
||||
stolen[0].end != stolen[1].end) {
|
||||
DRM_DEBUG_KMS("GTT within stolen memory at 0x%llx-0x%llx\n",
|
||||
(unsigned long long) gtt_start,
|
||||
(unsigned long long) gtt_end - 1);
|
||||
DRM_DEBUG_KMS("Stolen memory adjusted to 0x%x-0x%x\n",
|
||||
base, base + (u32) dev_priv->gtt.stolen_size - 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Verify that nothing else uses this physical address. Stolen
|
||||
* memory should be reserved by the BIOS and hidden from the
|
||||
* kernel. So if the region is already marked as busy, something
|
||||
|
@ -942,6 +942,9 @@ enum punit_power_well {
|
||||
/*
|
||||
* Instruction and interrupt control regs
|
||||
*/
|
||||
#define PGTBL_CTL 0x02020
|
||||
#define PGTBL_ADDRESS_LO_MASK 0xfffff000 /* bits [31:12] */
|
||||
#define PGTBL_ADDRESS_HI_MASK 0x000000f0 /* bits [35:32] (gen4) */
|
||||
#define PGTBL_ER 0x02024
|
||||
#define RENDER_RING_BASE 0x02000
|
||||
#define BSD_RING_BASE 0x04000
|
||||
|
@ -11591,6 +11591,14 @@ static void quirk_invert_brightness(struct drm_device *dev)
|
||||
DRM_INFO("applying inverted panel brightness quirk\n");
|
||||
}
|
||||
|
||||
/* Some VBT's incorrectly indicate no backlight is present */
|
||||
static void quirk_backlight_present(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
dev_priv->quirks |= QUIRK_BACKLIGHT_PRESENT;
|
||||
DRM_INFO("applying backlight present quirk\n");
|
||||
}
|
||||
|
||||
struct intel_quirk {
|
||||
int device;
|
||||
int subsystem_vendor;
|
||||
@ -11659,6 +11667,12 @@ static struct intel_quirk intel_quirks[] = {
|
||||
|
||||
/* Acer Aspire 5336 */
|
||||
{ 0x2a42, 0x1025, 0x048a, quirk_invert_brightness },
|
||||
|
||||
/* Acer C720 and C720P Chromebooks (Celeron 2955U) have backlights */
|
||||
{ 0x0a06, 0x1025, 0x0a11, quirk_backlight_present },
|
||||
|
||||
/* Toshiba CB35 Chromebook (Celeron 2955U) */
|
||||
{ 0x0a06, 0x1179, 0x0a88, quirk_backlight_present },
|
||||
};
|
||||
|
||||
static void intel_init_quirks(struct drm_device *dev)
|
||||
|
@ -28,6 +28,8 @@
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
@ -336,6 +338,37 @@ static u32 _pp_stat_reg(struct intel_dp *intel_dp)
|
||||
return VLV_PIPE_PP_STATUS(vlv_power_sequencer_pipe(intel_dp));
|
||||
}
|
||||
|
||||
/* Reboot notifier handler to shutdown panel power to guarantee T12 timing
|
||||
This function only applicable when panel PM state is not to be tracked */
|
||||
static int edp_notify_handler(struct notifier_block *this, unsigned long code,
|
||||
void *unused)
|
||||
{
|
||||
struct intel_dp *intel_dp = container_of(this, typeof(* intel_dp),
|
||||
edp_notifier);
|
||||
struct drm_device *dev = intel_dp_to_dev(intel_dp);
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 pp_div;
|
||||
u32 pp_ctrl_reg, pp_div_reg;
|
||||
enum pipe pipe = vlv_power_sequencer_pipe(intel_dp);
|
||||
|
||||
if (!is_edp(intel_dp) || code != SYS_RESTART)
|
||||
return 0;
|
||||
|
||||
if (IS_VALLEYVIEW(dev)) {
|
||||
pp_ctrl_reg = VLV_PIPE_PP_CONTROL(pipe);
|
||||
pp_div_reg = VLV_PIPE_PP_DIVISOR(pipe);
|
||||
pp_div = I915_READ(pp_div_reg);
|
||||
pp_div &= PP_REFERENCE_DIVIDER_MASK;
|
||||
|
||||
/* 0x1F write to PP_DIV_REG sets max cycle delay */
|
||||
I915_WRITE(pp_div_reg, pp_div | 0x1F);
|
||||
I915_WRITE(pp_ctrl_reg, PANEL_UNLOCK_REGS | PANEL_POWER_OFF);
|
||||
msleep(intel_dp->panel_power_cycle_delay);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool edp_have_panel_power(struct intel_dp *intel_dp)
|
||||
{
|
||||
struct drm_device *dev = intel_dp_to_dev(intel_dp);
|
||||
@ -3707,6 +3740,10 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)
|
||||
drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
|
||||
edp_panel_vdd_off_sync(intel_dp);
|
||||
drm_modeset_unlock(&dev->mode_config.connection_mutex);
|
||||
if (intel_dp->edp_notifier.notifier_call) {
|
||||
unregister_reboot_notifier(&intel_dp->edp_notifier);
|
||||
intel_dp->edp_notifier.notifier_call = NULL;
|
||||
}
|
||||
}
|
||||
kfree(intel_dig_port);
|
||||
}
|
||||
@ -4184,6 +4221,11 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
|
||||
}
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
|
||||
if (IS_VALLEYVIEW(dev)) {
|
||||
intel_dp->edp_notifier.notifier_call = edp_notify_handler;
|
||||
register_reboot_notifier(&intel_dp->edp_notifier);
|
||||
}
|
||||
|
||||
intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
|
||||
intel_panel_setup_backlight(connector);
|
||||
|
||||
|
@ -538,6 +538,8 @@ struct intel_dp {
|
||||
unsigned long last_power_on;
|
||||
unsigned long last_backlight_off;
|
||||
bool psr_setup_done;
|
||||
struct notifier_block edp_notifier;
|
||||
|
||||
bool use_tps3;
|
||||
struct intel_connector *attached_connector;
|
||||
|
||||
|
@ -117,17 +117,18 @@ static void intel_dsi_device_ready(struct intel_encoder *encoder)
|
||||
/* bandgap reset is needed after everytime we do power gate */
|
||||
band_gap_reset(dev_priv);
|
||||
|
||||
I915_WRITE(MIPI_DEVICE_READY(pipe), ULPS_STATE_ENTER);
|
||||
usleep_range(2500, 3000);
|
||||
|
||||
val = I915_READ(MIPI_PORT_CTRL(pipe));
|
||||
I915_WRITE(MIPI_PORT_CTRL(pipe), val | LP_OUTPUT_HOLD);
|
||||
usleep_range(1000, 1500);
|
||||
I915_WRITE(MIPI_DEVICE_READY(pipe), DEVICE_READY | ULPS_STATE_EXIT);
|
||||
usleep_range(2000, 2500);
|
||||
|
||||
I915_WRITE(MIPI_DEVICE_READY(pipe), ULPS_STATE_EXIT);
|
||||
usleep_range(2500, 3000);
|
||||
|
||||
I915_WRITE(MIPI_DEVICE_READY(pipe), DEVICE_READY);
|
||||
usleep_range(2000, 2500);
|
||||
I915_WRITE(MIPI_DEVICE_READY(pipe), 0x00);
|
||||
usleep_range(2000, 2500);
|
||||
I915_WRITE(MIPI_DEVICE_READY(pipe), DEVICE_READY);
|
||||
usleep_range(2000, 2500);
|
||||
usleep_range(2500, 3000);
|
||||
}
|
||||
|
||||
static void intel_dsi_enable(struct intel_encoder *encoder)
|
||||
@ -271,23 +272,23 @@ static void intel_dsi_clear_device_ready(struct intel_encoder *encoder)
|
||||
|
||||
DRM_DEBUG_KMS("\n");
|
||||
|
||||
I915_WRITE(MIPI_DEVICE_READY(pipe), ULPS_STATE_ENTER);
|
||||
I915_WRITE(MIPI_DEVICE_READY(pipe), DEVICE_READY | ULPS_STATE_ENTER);
|
||||
usleep_range(2000, 2500);
|
||||
|
||||
I915_WRITE(MIPI_DEVICE_READY(pipe), ULPS_STATE_EXIT);
|
||||
I915_WRITE(MIPI_DEVICE_READY(pipe), DEVICE_READY | ULPS_STATE_EXIT);
|
||||
usleep_range(2000, 2500);
|
||||
|
||||
I915_WRITE(MIPI_DEVICE_READY(pipe), ULPS_STATE_ENTER);
|
||||
I915_WRITE(MIPI_DEVICE_READY(pipe), DEVICE_READY | ULPS_STATE_ENTER);
|
||||
usleep_range(2000, 2500);
|
||||
|
||||
val = I915_READ(MIPI_PORT_CTRL(pipe));
|
||||
I915_WRITE(MIPI_PORT_CTRL(pipe), val & ~LP_OUTPUT_HOLD);
|
||||
usleep_range(1000, 1500);
|
||||
|
||||
if (wait_for(((I915_READ(MIPI_PORT_CTRL(pipe)) & AFE_LATCHOUT)
|
||||
== 0x00000), 30))
|
||||
DRM_ERROR("DSI LP not going Low\n");
|
||||
|
||||
val = I915_READ(MIPI_PORT_CTRL(pipe));
|
||||
I915_WRITE(MIPI_PORT_CTRL(pipe), val & ~LP_OUTPUT_HOLD);
|
||||
usleep_range(1000, 1500);
|
||||
|
||||
I915_WRITE(MIPI_DEVICE_READY(pipe), 0x00);
|
||||
usleep_range(2000, 2500);
|
||||
|
||||
|
@ -404,12 +404,6 @@ int dpi_send_cmd(struct intel_dsi *intel_dsi, u32 cmd, bool hs)
|
||||
else
|
||||
cmd |= DPI_LP_MODE;
|
||||
|
||||
/* DPI virtual channel?! */
|
||||
|
||||
mask = DPI_FIFO_EMPTY;
|
||||
if (wait_for((I915_READ(MIPI_GEN_FIFO_STAT(pipe)) & mask) == mask, 50))
|
||||
DRM_ERROR("Timeout waiting for DPI FIFO empty.\n");
|
||||
|
||||
/* clear bit */
|
||||
I915_WRITE(MIPI_INTR_STAT(pipe), SPL_PKT_SENT_INTERRUPT);
|
||||
|
||||
|
@ -1118,8 +1118,12 @@ int intel_panel_setup_backlight(struct drm_connector *connector)
|
||||
int ret;
|
||||
|
||||
if (!dev_priv->vbt.backlight.present) {
|
||||
DRM_DEBUG_KMS("native backlight control not available per VBT\n");
|
||||
return 0;
|
||||
if (dev_priv->quirks & QUIRK_BACKLIGHT_PRESENT) {
|
||||
DRM_DEBUG_KMS("no backlight present per VBT, but present per quirk\n");
|
||||
} else {
|
||||
DRM_DEBUG_KMS("no backlight present per VBT\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* set level and max in panel struct */
|
||||
|
Loading…
Reference in New Issue
Block a user