Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c15d8a64 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* '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
parents 49021355 e08fb4f6
Loading
Loading
Loading
Loading
+72 −4
Original line number Original line Diff line number Diff line
@@ -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)
+3 −3
Original line number Original line Diff line number Diff line
@@ -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);


+10 −4
Original line number Original line Diff line number Diff line
@@ -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);

		if (dev->vblank_inmodeset[crtc] & 0x2)
			drm_vblank_put(dev, crtc);
			drm_vblank_put(dev, crtc);

		dev->vblank_inmodeset[crtc] = 0;
	}
	}
}
}
EXPORT_SYMBOL(drm_vblank_post_modeset);
EXPORT_SYMBOL(drm_vblank_post_modeset);
+1 −1
Original line number Original line Diff line number Diff line
@@ -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;
+1 −1
Original line number Original line Diff line number Diff line
@@ -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;
Loading