Merge branch 'drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6
* 'drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6: drm/i915: convert DRM_ERROR to DRM_DEBUG in phys object pwrite path drm/i915: make hw page ioremap use ioremap_wc drm: edid revision 0 is valid drm: Correct unbalanced drm_vblank_put() during mode setting. drm: disable encoders before re-routing them drm: Fix ordering of bit fields in EDID structure leading huge vsync values. drm: Fix shifts of EDID vsync offset/width fields. drm/i915: handle bogus VBT panel timing drm/i915: remove PLL debugging messages
This commit is contained in:
commit
c15d8a6499
|
@ -452,6 +452,59 @@ static void drm_setup_crtcs(struct drm_device *dev)
|
||||||
kfree(modes);
|
kfree(modes);
|
||||||
kfree(enabled);
|
kfree(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* drm_encoder_crtc_ok - can a given crtc drive a given encoder?
|
||||||
|
* @encoder: encoder to test
|
||||||
|
* @crtc: crtc to test
|
||||||
|
*
|
||||||
|
* Return false if @encoder can't be driven by @crtc, true otherwise.
|
||||||
|
*/
|
||||||
|
static bool drm_encoder_crtc_ok(struct drm_encoder *encoder,
|
||||||
|
struct drm_crtc *crtc)
|
||||||
|
{
|
||||||
|
struct drm_device *dev;
|
||||||
|
struct drm_crtc *tmp;
|
||||||
|
int crtc_mask = 1;
|
||||||
|
|
||||||
|
WARN(!crtc, "checking null crtc?");
|
||||||
|
|
||||||
|
dev = crtc->dev;
|
||||||
|
|
||||||
|
list_for_each_entry(tmp, &dev->mode_config.crtc_list, head) {
|
||||||
|
if (tmp == crtc)
|
||||||
|
break;
|
||||||
|
crtc_mask <<= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (encoder->possible_crtcs & crtc_mask)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check the CRTC we're going to map each output to vs. its current
|
||||||
|
* CRTC. If they don't match, we have to disable the output and the CRTC
|
||||||
|
* since the driver will have to re-route things.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
drm_crtc_prepare_encoders(struct drm_device *dev)
|
||||||
|
{
|
||||||
|
struct drm_encoder_helper_funcs *encoder_funcs;
|
||||||
|
struct drm_encoder *encoder;
|
||||||
|
|
||||||
|
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
||||||
|
encoder_funcs = encoder->helper_private;
|
||||||
|
/* Disable unused encoders */
|
||||||
|
if (encoder->crtc == NULL)
|
||||||
|
(*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
|
||||||
|
/* Disable encoders whose CRTC is about to change */
|
||||||
|
if (encoder_funcs->get_crtc &&
|
||||||
|
encoder->crtc != (*encoder_funcs->get_crtc)(encoder))
|
||||||
|
(*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* drm_crtc_set_mode - set a mode
|
* drm_crtc_set_mode - set a mode
|
||||||
* @crtc: CRTC to program
|
* @crtc: CRTC to program
|
||||||
|
@ -547,6 +600,8 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
|
||||||
encoder_funcs->prepare(encoder);
|
encoder_funcs->prepare(encoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
drm_crtc_prepare_encoders(dev);
|
||||||
|
|
||||||
crtc_funcs->prepare(crtc);
|
crtc_funcs->prepare(crtc);
|
||||||
|
|
||||||
/* Set up the DPLL and any encoders state that needs to adjust or depend
|
/* Set up the DPLL and any encoders state that needs to adjust or depend
|
||||||
|
@ -617,7 +672,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
|
||||||
struct drm_device *dev;
|
struct drm_device *dev;
|
||||||
struct drm_crtc **save_crtcs, *new_crtc;
|
struct drm_crtc **save_crtcs, *new_crtc;
|
||||||
struct drm_encoder **save_encoders, *new_encoder;
|
struct drm_encoder **save_encoders, *new_encoder;
|
||||||
struct drm_framebuffer *old_fb;
|
struct drm_framebuffer *old_fb = NULL;
|
||||||
bool save_enabled;
|
bool save_enabled;
|
||||||
bool mode_changed = false;
|
bool mode_changed = false;
|
||||||
bool fb_changed = false;
|
bool fb_changed = false;
|
||||||
|
@ -668,9 +723,10 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
|
||||||
* and then just flip_or_move it */
|
* and then just flip_or_move it */
|
||||||
if (set->crtc->fb != set->fb) {
|
if (set->crtc->fb != set->fb) {
|
||||||
/* If we have no fb then treat it as a full mode set */
|
/* If we have no fb then treat it as a full mode set */
|
||||||
if (set->crtc->fb == NULL)
|
if (set->crtc->fb == NULL) {
|
||||||
|
DRM_DEBUG("crtc has no fb, full mode set\n");
|
||||||
mode_changed = true;
|
mode_changed = true;
|
||||||
else if ((set->fb->bits_per_pixel !=
|
} else if ((set->fb->bits_per_pixel !=
|
||||||
set->crtc->fb->bits_per_pixel) ||
|
set->crtc->fb->bits_per_pixel) ||
|
||||||
set->fb->depth != set->crtc->fb->depth)
|
set->fb->depth != set->crtc->fb->depth)
|
||||||
fb_changed = true;
|
fb_changed = true;
|
||||||
|
@ -682,7 +738,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
|
||||||
fb_changed = true;
|
fb_changed = true;
|
||||||
|
|
||||||
if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) {
|
if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) {
|
||||||
DRM_DEBUG("modes are different\n");
|
DRM_DEBUG("modes are different, full mode set\n");
|
||||||
drm_mode_debug_printmodeline(&set->crtc->mode);
|
drm_mode_debug_printmodeline(&set->crtc->mode);
|
||||||
drm_mode_debug_printmodeline(set->mode);
|
drm_mode_debug_printmodeline(set->mode);
|
||||||
mode_changed = true;
|
mode_changed = true;
|
||||||
|
@ -708,6 +764,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_encoder != connector->encoder) {
|
if (new_encoder != connector->encoder) {
|
||||||
|
DRM_DEBUG("encoder changed, full mode switch\n");
|
||||||
mode_changed = true;
|
mode_changed = true;
|
||||||
connector->encoder = new_encoder;
|
connector->encoder = new_encoder;
|
||||||
}
|
}
|
||||||
|
@ -734,10 +791,20 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
|
||||||
if (set->connectors[ro] == connector)
|
if (set->connectors[ro] == connector)
|
||||||
new_crtc = set->crtc;
|
new_crtc = set->crtc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Make sure the new CRTC will work with the encoder */
|
||||||
|
if (new_crtc &&
|
||||||
|
!drm_encoder_crtc_ok(connector->encoder, new_crtc)) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto fail_set_mode;
|
||||||
|
}
|
||||||
if (new_crtc != connector->encoder->crtc) {
|
if (new_crtc != connector->encoder->crtc) {
|
||||||
|
DRM_DEBUG("crtc changed, full mode switch\n");
|
||||||
mode_changed = true;
|
mode_changed = true;
|
||||||
connector->encoder->crtc = new_crtc;
|
connector->encoder->crtc = new_crtc;
|
||||||
}
|
}
|
||||||
|
DRM_DEBUG("setting connector %d crtc to %p\n",
|
||||||
|
connector->base.id, new_crtc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* mode_set_base is not a required function */
|
/* mode_set_base is not a required function */
|
||||||
|
@ -781,6 +848,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
|
||||||
|
|
||||||
fail_set_mode:
|
fail_set_mode:
|
||||||
set->crtc->enabled = save_enabled;
|
set->crtc->enabled = save_enabled;
|
||||||
|
set->crtc->fb = old_fb;
|
||||||
count = 0;
|
count = 0;
|
||||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||||
if (!connector->encoder)
|
if (!connector->encoder)
|
||||||
|
|
|
@ -125,7 +125,7 @@ static bool edid_is_valid(struct edid *edid)
|
||||||
DRM_ERROR("EDID has major version %d, instead of 1\n", edid->version);
|
DRM_ERROR("EDID has major version %d, instead of 1\n", edid->version);
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
if (edid->revision <= 0 || edid->revision > 3) {
|
if (edid->revision > 3) {
|
||||||
DRM_ERROR("EDID has minor version %d, which is not between 0-3\n", edid->revision);
|
DRM_ERROR("EDID has minor version %d, which is not between 0-3\n", edid->revision);
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
@ -320,10 +320,10 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
|
||||||
mode->htotal = mode->hdisplay + ((pt->hblank_hi << 8) | pt->hblank_lo);
|
mode->htotal = mode->hdisplay + ((pt->hblank_hi << 8) | pt->hblank_lo);
|
||||||
|
|
||||||
mode->vdisplay = (pt->vactive_hi << 8) | pt->vactive_lo;
|
mode->vdisplay = (pt->vactive_hi << 8) | pt->vactive_lo;
|
||||||
mode->vsync_start = mode->vdisplay + ((pt->vsync_offset_hi << 8) |
|
mode->vsync_start = mode->vdisplay + ((pt->vsync_offset_hi << 4) |
|
||||||
pt->vsync_offset_lo);
|
pt->vsync_offset_lo);
|
||||||
mode->vsync_end = mode->vsync_start +
|
mode->vsync_end = mode->vsync_start +
|
||||||
((pt->vsync_pulse_width_hi << 8) |
|
((pt->vsync_pulse_width_hi << 4) |
|
||||||
pt->vsync_pulse_width_lo);
|
pt->vsync_pulse_width_lo);
|
||||||
mode->vtotal = mode->vdisplay + ((pt->vblank_hi << 8) | pt->vblank_lo);
|
mode->vtotal = mode->vdisplay + ((pt->vblank_hi << 8) | pt->vblank_lo);
|
||||||
|
|
||||||
|
|
|
@ -435,6 +435,8 @@ EXPORT_SYMBOL(drm_vblank_get);
|
||||||
*/
|
*/
|
||||||
void drm_vblank_put(struct drm_device *dev, int crtc)
|
void drm_vblank_put(struct drm_device *dev, int crtc)
|
||||||
{
|
{
|
||||||
|
BUG_ON (atomic_read (&dev->vblank_refcount[crtc]) == 0);
|
||||||
|
|
||||||
/* Last user schedules interrupt disable */
|
/* Last user schedules interrupt disable */
|
||||||
if (atomic_dec_and_test(&dev->vblank_refcount[crtc]))
|
if (atomic_dec_and_test(&dev->vblank_refcount[crtc]))
|
||||||
mod_timer(&dev->vblank_disable_timer, jiffies + 5*DRM_HZ);
|
mod_timer(&dev->vblank_disable_timer, jiffies + 5*DRM_HZ);
|
||||||
|
@ -460,8 +462,9 @@ void drm_vblank_pre_modeset(struct drm_device *dev, int crtc)
|
||||||
* so that interrupts remain enabled in the interim.
|
* so that interrupts remain enabled in the interim.
|
||||||
*/
|
*/
|
||||||
if (!dev->vblank_inmodeset[crtc]) {
|
if (!dev->vblank_inmodeset[crtc]) {
|
||||||
dev->vblank_inmodeset[crtc] = 1;
|
dev->vblank_inmodeset[crtc] = 0x1;
|
||||||
drm_vblank_get(dev, crtc);
|
if (drm_vblank_get(dev, crtc) == 0)
|
||||||
|
dev->vblank_inmodeset[crtc] |= 0x2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_vblank_pre_modeset);
|
EXPORT_SYMBOL(drm_vblank_pre_modeset);
|
||||||
|
@ -473,9 +476,12 @@ void drm_vblank_post_modeset(struct drm_device *dev, int crtc)
|
||||||
if (dev->vblank_inmodeset[crtc]) {
|
if (dev->vblank_inmodeset[crtc]) {
|
||||||
spin_lock_irqsave(&dev->vbl_lock, irqflags);
|
spin_lock_irqsave(&dev->vbl_lock, irqflags);
|
||||||
dev->vblank_disable_allowed = 1;
|
dev->vblank_disable_allowed = 1;
|
||||||
dev->vblank_inmodeset[crtc] = 0;
|
|
||||||
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
|
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
|
||||||
drm_vblank_put(dev, crtc);
|
|
||||||
|
if (dev->vblank_inmodeset[crtc] & 0x2)
|
||||||
|
drm_vblank_put(dev, crtc);
|
||||||
|
|
||||||
|
dev->vblank_inmodeset[crtc] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_vblank_post_modeset);
|
EXPORT_SYMBOL(drm_vblank_post_modeset);
|
||||||
|
|
|
@ -811,7 +811,7 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
|
||||||
dev_priv->hws_map.flags = 0;
|
dev_priv->hws_map.flags = 0;
|
||||||
dev_priv->hws_map.mtrr = 0;
|
dev_priv->hws_map.mtrr = 0;
|
||||||
|
|
||||||
drm_core_ioremap(&dev_priv->hws_map, dev);
|
drm_core_ioremap_wc(&dev_priv->hws_map, dev);
|
||||||
if (dev_priv->hws_map.handle == NULL) {
|
if (dev_priv->hws_map.handle == NULL) {
|
||||||
i915_dma_cleanup(dev);
|
i915_dma_cleanup(dev);
|
||||||
dev_priv->status_gfx_addr = 0;
|
dev_priv->status_gfx_addr = 0;
|
||||||
|
|
|
@ -3548,7 +3548,7 @@ i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
|
||||||
user_data = (char __user *) (uintptr_t) args->data_ptr;
|
user_data = (char __user *) (uintptr_t) args->data_ptr;
|
||||||
obj_addr = obj_priv->phys_obj->handle->vaddr + args->offset;
|
obj_addr = obj_priv->phys_obj->handle->vaddr + args->offset;
|
||||||
|
|
||||||
DRM_ERROR("obj_addr %p, %lld\n", obj_addr, args->size);
|
DRM_DEBUG("obj_addr %p, %lld\n", obj_addr, args->size);
|
||||||
ret = copy_from_user(obj_addr, user_data, args->size);
|
ret = copy_from_user(obj_addr, user_data, args->size);
|
||||||
if (ret)
|
if (ret)
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
|
@ -111,6 +111,12 @@ parse_panel_data(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
|
||||||
panel_fixed_mode->clock = dvo_timing->clock * 10;
|
panel_fixed_mode->clock = dvo_timing->clock * 10;
|
||||||
panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED;
|
panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED;
|
||||||
|
|
||||||
|
/* Some VBTs have bogus h/vtotal values */
|
||||||
|
if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal)
|
||||||
|
panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1;
|
||||||
|
if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal)
|
||||||
|
panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end + 1;
|
||||||
|
|
||||||
drm_mode_set_name(panel_fixed_mode);
|
drm_mode_set_name(panel_fixed_mode);
|
||||||
|
|
||||||
dev_priv->vbt_mode = panel_fixed_mode;
|
dev_priv->vbt_mode = panel_fixed_mode;
|
||||||
|
|
|
@ -217,7 +217,7 @@ bool intel_pipe_has_type (struct drm_crtc *crtc, int type)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define INTELPllInvalid(s) do { DRM_DEBUG(s); return false; } while (0)
|
#define INTELPllInvalid(s) do { /* DRM_DEBUG(s); */ return false; } while (0)
|
||||||
/**
|
/**
|
||||||
* Returns whether the given set of divisors are valid for a given refclk with
|
* Returns whether the given set of divisors are valid for a given refclk with
|
||||||
* the given connectors.
|
* the given connectors.
|
||||||
|
|
|
@ -76,6 +76,7 @@ struct drm_encoder_helper_funcs {
|
||||||
void (*mode_set)(struct drm_encoder *encoder,
|
void (*mode_set)(struct drm_encoder *encoder,
|
||||||
struct drm_display_mode *mode,
|
struct drm_display_mode *mode,
|
||||||
struct drm_display_mode *adjusted_mode);
|
struct drm_display_mode *adjusted_mode);
|
||||||
|
struct drm_crtc *(*get_crtc)(struct drm_encoder *encoder);
|
||||||
/* detect for DAC style encoders */
|
/* detect for DAC style encoders */
|
||||||
enum drm_connector_status (*detect)(struct drm_encoder *encoder,
|
enum drm_connector_status (*detect)(struct drm_encoder *encoder,
|
||||||
struct drm_connector *connector);
|
struct drm_connector *connector);
|
||||||
|
|
|
@ -58,10 +58,10 @@ struct detailed_pixel_timing {
|
||||||
u8 hsync_pulse_width_lo;
|
u8 hsync_pulse_width_lo;
|
||||||
u8 vsync_pulse_width_lo:4;
|
u8 vsync_pulse_width_lo:4;
|
||||||
u8 vsync_offset_lo:4;
|
u8 vsync_offset_lo:4;
|
||||||
u8 hsync_pulse_width_hi:2;
|
|
||||||
u8 hsync_offset_hi:2;
|
|
||||||
u8 vsync_pulse_width_hi:2;
|
u8 vsync_pulse_width_hi:2;
|
||||||
u8 vsync_offset_hi:2;
|
u8 vsync_offset_hi:2;
|
||||||
|
u8 hsync_pulse_width_hi:2;
|
||||||
|
u8 hsync_offset_hi:2;
|
||||||
u8 width_mm_lo;
|
u8 width_mm_lo;
|
||||||
u8 height_mm_lo;
|
u8 height_mm_lo;
|
||||||
u8 height_mm_hi:4;
|
u8 height_mm_hi:4;
|
||||||
|
|
Loading…
Reference in New Issue