mirror of
https://github.com/torvalds/linux.git
synced 2024-11-25 13:41:51 +00:00
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(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
|
||||
* @crtc: CRTC to program
|
||||
@ -547,6 +600,8 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
|
||||
encoder_funcs->prepare(encoder);
|
||||
}
|
||||
|
||||
drm_crtc_prepare_encoders(dev);
|
||||
|
||||
crtc_funcs->prepare(crtc);
|
||||
|
||||
/* 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_crtc **save_crtcs, *new_crtc;
|
||||
struct drm_encoder **save_encoders, *new_encoder;
|
||||
struct drm_framebuffer *old_fb;
|
||||
struct drm_framebuffer *old_fb = NULL;
|
||||
bool save_enabled;
|
||||
bool mode_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 */
|
||||
if (set->crtc->fb != set->fb) {
|
||||
/* 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;
|
||||
else if ((set->fb->bits_per_pixel !=
|
||||
} else if ((set->fb->bits_per_pixel !=
|
||||
set->crtc->fb->bits_per_pixel) ||
|
||||
set->fb->depth != set->crtc->fb->depth)
|
||||
fb_changed = true;
|
||||
@ -682,7 +738,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
|
||||
fb_changed = true;
|
||||
|
||||
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->mode);
|
||||
mode_changed = true;
|
||||
@ -708,6 +764,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
|
||||
}
|
||||
|
||||
if (new_encoder != connector->encoder) {
|
||||
DRM_DEBUG("encoder changed, full mode switch\n");
|
||||
mode_changed = true;
|
||||
connector->encoder = new_encoder;
|
||||
}
|
||||
@ -734,10 +791,20 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
|
||||
if (set->connectors[ro] == connector)
|
||||
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) {
|
||||
DRM_DEBUG("crtc changed, full mode switch\n");
|
||||
mode_changed = true;
|
||||
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 */
|
||||
@ -781,6 +848,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
|
||||
|
||||
fail_set_mode:
|
||||
set->crtc->enabled = save_enabled;
|
||||
set->crtc->fb = old_fb;
|
||||
count = 0;
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
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);
|
||||
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);
|
||||
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->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);
|
||||
mode->vsync_end = mode->vsync_start +
|
||||
((pt->vsync_pulse_width_hi << 8) |
|
||||
((pt->vsync_pulse_width_hi << 4) |
|
||||
pt->vsync_pulse_width_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)
|
||||
{
|
||||
BUG_ON (atomic_read (&dev->vblank_refcount[crtc]) == 0);
|
||||
|
||||
/* Last user schedules interrupt disable */
|
||||
if (atomic_dec_and_test(&dev->vblank_refcount[crtc]))
|
||||
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.
|
||||
*/
|
||||
if (!dev->vblank_inmodeset[crtc]) {
|
||||
dev->vblank_inmodeset[crtc] = 1;
|
||||
drm_vblank_get(dev, crtc);
|
||||
dev->vblank_inmodeset[crtc] = 0x1;
|
||||
if (drm_vblank_get(dev, crtc) == 0)
|
||||
dev->vblank_inmodeset[crtc] |= 0x2;
|
||||
}
|
||||
}
|
||||
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]) {
|
||||
spin_lock_irqsave(&dev->vbl_lock, irqflags);
|
||||
dev->vblank_disable_allowed = 1;
|
||||
dev->vblank_inmodeset[crtc] = 0;
|
||||
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);
|
||||
|
@ -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.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) {
|
||||
i915_dma_cleanup(dev);
|
||||
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;
|
||||
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);
|
||||
if (ret)
|
||||
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->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);
|
||||
|
||||
dev_priv->vbt_mode = panel_fixed_mode;
|
||||
|
@ -217,7 +217,7 @@ bool intel_pipe_has_type (struct drm_crtc *crtc, int type)
|
||||
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
|
||||
* the given connectors.
|
||||
|
@ -76,6 +76,7 @@ struct drm_encoder_helper_funcs {
|
||||
void (*mode_set)(struct drm_encoder *encoder,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode);
|
||||
struct drm_crtc *(*get_crtc)(struct drm_encoder *encoder);
|
||||
/* detect for DAC style encoders */
|
||||
enum drm_connector_status (*detect)(struct drm_encoder *encoder,
|
||||
struct drm_connector *connector);
|
||||
|
@ -58,10 +58,10 @@ struct detailed_pixel_timing {
|
||||
u8 hsync_pulse_width_lo;
|
||||
u8 vsync_pulse_width_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_offset_hi:2;
|
||||
u8 hsync_pulse_width_hi:2;
|
||||
u8 hsync_offset_hi:2;
|
||||
u8 width_mm_lo;
|
||||
u8 height_mm_lo;
|
||||
u8 height_mm_hi:4;
|
||||
|
Loading…
Reference in New Issue
Block a user