diff options
Diffstat (limited to 'drivers/gpu')
53 files changed, 623 insertions, 337 deletions
diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c index 09e11a5d921..fd9d0af4d53 100644 --- a/drivers/gpu/drm/drm_fb_cma_helper.c +++ b/drivers/gpu/drm/drm_fb_cma_helper.c @@ -206,7 +206,7 @@ static int drm_fbdev_cma_create(struct drm_fb_helper *helper,  	size_t size;  	int ret; -	DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d\n", +	DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d)\n",  			sizes->surface_width, sizes->surface_height,  			sizes->surface_bpp); @@ -220,7 +220,7 @@ static int drm_fbdev_cma_create(struct drm_fb_helper *helper,  	size = mode_cmd.pitches[0] * mode_cmd.height;  	obj = drm_gem_cma_create(dev, size); -	if (!obj) +	if (IS_ERR(obj))  		return -ENOMEM;  	fbi = framebuffer_alloc(0, dev->dev); diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c index 441ebc1bdbe..d4b20ceda3f 100644 --- a/drivers/gpu/drm/drm_info.c +++ b/drivers/gpu/drm/drm_info.c @@ -205,8 +205,6 @@ static int drm_gem_one_name_info(int id, void *ptr, void *data)  	struct drm_gem_object *obj = ptr;  	struct seq_file *m = data; -	seq_printf(m, "name %d size %zd\n", obj->name, obj->size); -  	seq_printf(m, "%6d %8zd %7d %8d\n",  		   obj->name, obj->size,  		   atomic_read(&obj->handle_count), diff --git a/drivers/gpu/drm/drm_platform.c b/drivers/gpu/drm/drm_platform.c index aaeb6f8d69c..b8a282ea875 100644 --- a/drivers/gpu/drm/drm_platform.c +++ b/drivers/gpu/drm/drm_platform.c @@ -64,7 +64,6 @@ int drm_get_platform_dev(struct platform_device *platdev,  	}  	if (drm_core_check_feature(dev, DRIVER_MODESET)) { -		dev_set_drvdata(&platdev->dev, dev);  		ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL);  		if (ret)  			goto err_g1; diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig index 59a26e577b5..fc345d4ebb0 100644 --- a/drivers/gpu/drm/exynos/Kconfig +++ b/drivers/gpu/drm/exynos/Kconfig @@ -1,6 +1,6 @@  config DRM_EXYNOS  	tristate "DRM Support for Samsung SoC EXYNOS Series" -	depends on DRM && PLAT_SAMSUNG +	depends on DRM && (PLAT_SAMSUNG || ARCH_MULTIPLATFORM)  	select DRM_KMS_HELPER  	select FB_CFB_FILLRECT  	select FB_CFB_COPYAREA diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c index 18c271862ca..0f68a287267 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_connector.c +++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c @@ -374,6 +374,7 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,  	exynos_connector->encoder_id = encoder->base.id;  	exynos_connector->manager = manager;  	exynos_connector->dpms = DRM_MODE_DPMS_OFF; +	connector->dpms = DRM_MODE_DPMS_OFF;  	connector->encoder = encoder;  	err = drm_mode_connector_attach_encoder(connector, encoder); diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c index e51503fbaf2..241ad1eeec6 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c +++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c @@ -43,12 +43,14 @@   * @manager: specific encoder has its own manager to control a hardware   *	appropriately and we can access a hardware drawing on this manager.   * @dpms: store the encoder dpms value. + * @updated: indicate whether overlay data updating is needed or not.   */  struct exynos_drm_encoder {  	struct drm_crtc			*old_crtc;  	struct drm_encoder		drm_encoder;  	struct exynos_drm_manager	*manager; -	int dpms; +	int				dpms; +	bool				updated;  };  static void exynos_drm_connector_power(struct drm_encoder *encoder, int mode) @@ -85,7 +87,9 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)  	switch (mode) {  	case DRM_MODE_DPMS_ON:  		if (manager_ops && manager_ops->apply) -			manager_ops->apply(manager->dev); +			if (!exynos_encoder->updated) +				manager_ops->apply(manager->dev); +  		exynos_drm_connector_power(encoder, mode);  		exynos_encoder->dpms = mode;  		break; @@ -94,6 +98,7 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)  	case DRM_MODE_DPMS_OFF:  		exynos_drm_connector_power(encoder, mode);  		exynos_encoder->dpms = mode; +		exynos_encoder->updated = false;  		break;  	default:  		DRM_ERROR("unspecified mode %d\n", mode); @@ -205,13 +210,22 @@ static void exynos_drm_encoder_prepare(struct drm_encoder *encoder)  static void exynos_drm_encoder_commit(struct drm_encoder *encoder)  { -	struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder); +	struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); +	struct exynos_drm_manager *manager = exynos_encoder->manager;  	struct exynos_drm_manager_ops *manager_ops = manager->ops;  	DRM_DEBUG_KMS("%s\n", __FILE__);  	if (manager_ops && manager_ops->commit)  		manager_ops->commit(manager->dev); + +	/* +	 * this will avoid one issue that overlay data is updated to +	 * real hardware two times. +	 * And this variable will be used to check if the data was +	 * already updated or not by exynos_drm_encoder_dpms function. +	 */ +	exynos_encoder->updated = true;  }  static void exynos_drm_encoder_disable(struct drm_encoder *encoder) @@ -401,19 +415,6 @@ void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data)  		manager_ops->dpms(manager->dev, mode);  	/* -	 * set current mode to new one so that data aren't updated into -	 * registers by drm_helper_connector_dpms two times. -	 * -	 * in case that drm_crtc_helper_set_mode() is called, -	 * overlay_ops->commit() and manager_ops->commit() callbacks -	 * can be called two times, first at drm_crtc_helper_set_mode() -	 * and second at drm_helper_connector_dpms(). -	 * so with this setting, when drm_helper_connector_dpms() is called -	 * encoder->funcs->dpms() will be ignored. -	 */ -	exynos_encoder->dpms = mode; - -	/*  	 * if this condition is ok then it means that the crtc is already  	 * detached from encoder and last function for detaching is properly  	 * done, so clear pipe from manager to prevent repeated call. diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 614b2e9ac46..e7fbb823fd8 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -1142,7 +1142,7 @@ static int __devinit mixer_probe(struct platform_device *pdev)  		const struct of_device_id *match;  		match = of_match_node(of_match_ptr(mixer_match_types),  							  pdev->dev.of_node); -		drv = match->data; +		drv = (struct mixer_drv_data *)match->data;  	} else {  		drv = (struct mixer_drv_data *)  			platform_get_device_id(pdev)->driver_data; diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index c9bfd83dde6..61ae104dca8 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1505,7 +1505,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)  		goto put_gmch;  	} -	i915_kick_out_firmware_fb(dev_priv); +	if (drm_core_check_feature(dev, DRIVER_MODESET)) +		i915_kick_out_firmware_fb(dev_priv);  	pci_set_master(dev->pdev); diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index aac4e5e1a5b..6770ee6084b 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -118,6 +118,13 @@ module_param_named(i915_enable_ppgtt, i915_enable_ppgtt, int, 0600);  MODULE_PARM_DESC(i915_enable_ppgtt,  		"Enable PPGTT (default: true)"); +unsigned int i915_preliminary_hw_support __read_mostly = 0; +module_param_named(preliminary_hw_support, i915_preliminary_hw_support, int, 0600); +MODULE_PARM_DESC(preliminary_hw_support, +		"Enable preliminary hardware support. " +		"Enable Haswell and ValleyView Support. " +		"(default: false)"); +  static struct drm_driver driver;  extern int intel_agp_enabled; @@ -826,6 +833,12 @@ i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  	struct intel_device_info *intel_info =  		(struct intel_device_info *) ent->driver_data; +	if (intel_info->is_haswell || intel_info->is_valleyview) +		if(!i915_preliminary_hw_support) { +			DRM_ERROR("Preliminary hardware support disabled\n"); +			return -ENODEV; +		} +  	/* Only bind to function 0 of the device. Early generations  	 * used function 1 as a placeholder for multi-head. This causes  	 * us confusion instead, especially on the systems where both diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index b84f7861e43..f511fa2f416 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1217,6 +1217,7 @@ extern int i915_enable_rc6 __read_mostly;  extern int i915_enable_fbc __read_mostly;  extern bool i915_enable_hangcheck __read_mostly;  extern int i915_enable_ppgtt __read_mostly; +extern unsigned int i915_preliminary_hw_support __read_mostly;  extern int i915_suspend(struct drm_device *dev, pm_message_t state);  extern int i915_resume(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index d33d02d13c9..107f09befe9 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1407,8 +1407,10 @@ out:  		return VM_FAULT_NOPAGE;  	case -ENOMEM:  		return VM_FAULT_OOM; +	case -ENOSPC: +		return VM_FAULT_SIGBUS;  	default: -		WARN_ON_ONCE(ret); +		WARN_ONCE(ret, "unhandled error in i915_gem_fault: %i\n", ret);  		return VM_FAULT_SIGBUS;  	}  } @@ -1822,10 +1824,11 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)  		sg_set_page(sg, page, PAGE_SIZE, 0);  	} +	obj->pages = st; +  	if (i915_gem_object_needs_bit17_swizzle(obj))  		i915_gem_object_do_bit_17_swizzle(obj); -	obj->pages = st;  	return 0;  err_pages: diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 893f30164b7..b726b478a4f 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -219,20 +219,7 @@ static void intel_crt_mode_set(struct drm_encoder *encoder,  		intel_encoder_to_crt(to_intel_encoder(encoder));  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);  	struct drm_i915_private *dev_priv = dev->dev_private; -	int dpll_md_reg; -	u32 adpa, dpll_md; - -	dpll_md_reg = DPLL_MD(intel_crtc->pipe); - -	/* -	 * Disable separate mode multiplier used when cloning SDVO to CRT -	 * XXX this needs to be adjusted when we really are cloning -	 */ -	if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) { -		dpll_md = I915_READ(dpll_md_reg); -		I915_WRITE(dpll_md_reg, -			   dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK); -	} +	u32 adpa;  	adpa = ADPA_HOTPLUG_BITS;  	if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) @@ -742,7 +729,7 @@ void intel_crt_init(struct drm_device *dev)  	crt->base.type = INTEL_OUTPUT_ANALOG;  	crt->base.cloneable = true; -	if (IS_HASWELL(dev)) +	if (IS_HASWELL(dev) || IS_I830(dev))  		crt->base.crtc_mask = (1 << 0);  	else  		crt->base.crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 682bd3729ba..461a637f1ef 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -7892,6 +7892,34 @@ struct intel_quirk {  	void (*hook)(struct drm_device *dev);  }; +/* For systems that don't have a meaningful PCI subdevice/subvendor ID */ +struct intel_dmi_quirk { +	void (*hook)(struct drm_device *dev); +	const struct dmi_system_id (*dmi_id_list)[]; +}; + +static int intel_dmi_reverse_brightness(const struct dmi_system_id *id) +{ +	DRM_INFO("Backlight polarity reversed on %s\n", id->ident); +	return 1; +} + +static const struct intel_dmi_quirk intel_dmi_quirks[] = { +	{ +		.dmi_id_list = &(const struct dmi_system_id[]) { +			{ +				.callback = intel_dmi_reverse_brightness, +				.ident = "NCR Corporation", +				.matches = {DMI_MATCH(DMI_SYS_VENDOR, "NCR Corporation"), +					    DMI_MATCH(DMI_PRODUCT_NAME, ""), +				}, +			}, +			{ }  /* terminating entry */ +		}, +		.hook = quirk_invert_brightness, +	}, +}; +  static struct intel_quirk intel_quirks[] = {  	/* HP Mini needs pipe A force quirk (LP: #322104) */  	{ 0x27ae, 0x103c, 0x361a, quirk_pipea_force }, @@ -7931,6 +7959,10 @@ static void intel_init_quirks(struct drm_device *dev)  		     q->subsystem_device == PCI_ANY_ID))  			q->hook(dev);  	} +	for (i = 0; i < ARRAY_SIZE(intel_dmi_quirks); i++) { +		if (dmi_check_system(*intel_dmi_quirks[i].dmi_id_list) != 0) +			intel_dmi_quirks[i].hook(dev); +	}  }  /* Disable the VGA plane that we never use */ diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 1b727a5c9ee..368ed8ef160 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1797,7 +1797,8 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)  			if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0)  				break;  		if (i == intel_dp->lane_count && voltage_tries == 5) { -			if (++loop_tries == 5) { +			++loop_tries; +			if (loop_tries == 5) {  				DRM_DEBUG_KMS("too many full retries, give up\n");  				break;  			} @@ -1807,11 +1808,15 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)  		}  		/* Check to see if we've tried the same voltage 5 times */ -		if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) != voltage) { -			voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; -			voltage_tries = 0; -		} else +		if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) {  			++voltage_tries; +			if (voltage_tries == 5) { +				DRM_DEBUG_KMS("too many voltage retries, give up\n"); +				break; +			} +		} else +			voltage_tries = 0; +		voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;  		/* Compute new intel_dp->train_set as requested by target */  		intel_get_adjust_train(intel_dp, link_status); diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index e3166df55da..edba93b3474 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -777,6 +777,14 @@ static const struct dmi_system_id intel_no_lvds[] = {  			DMI_MATCH(DMI_BOARD_NAME, "D525TUD"),  		},  	}, +	{ +		.callback = intel_no_lvds_dmi_callback, +		.ident = "Supermicro X7SPA-H", +		.matches = { +			DMI_MATCH(DMI_SYS_VENDOR, "Supermicro"), +			DMI_MATCH(DMI_PRODUCT_NAME, "X7SPA-H"), +		}, +	},  	{ }	/* terminating entry */  }; diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index 495625914e4..d7bc817f51a 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -341,9 +341,17 @@ static int intel_overlay_off(struct intel_overlay *overlay)  	intel_ring_emit(ring, flip_addr);  	intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);  	/* turn overlay off */ -	intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF); -	intel_ring_emit(ring, flip_addr); -	intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); +	if (IS_I830(dev)) { +		/* Workaround: Don't disable the overlay fully, since otherwise +		 * it dies on the next OVERLAY_ON cmd. */ +		intel_ring_emit(ring, MI_NOOP); +		intel_ring_emit(ring, MI_NOOP); +		intel_ring_emit(ring, MI_NOOP); +	} else { +		intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF); +		intel_ring_emit(ring, flip_addr); +		intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); +	}  	intel_ring_advance(ring);  	return intel_overlay_do_wait_request(overlay, intel_overlay_off_tail); diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index e019b236986..e2aacd32954 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -435,7 +435,7 @@ int intel_panel_setup_backlight(struct drm_device *dev)  	props.type = BACKLIGHT_RAW;  	props.max_brightness = _intel_panel_get_max_backlight(dev);  	if (props.max_brightness == 0) { -		DRM_ERROR("Failed to get maximum backlight value\n"); +		DRM_DEBUG_DRIVER("Failed to get maximum backlight value\n");  		return -ENODEV;  	}  	dev_priv->backlight = diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 0007a4d9bf6..79d308da29f 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -139,6 +139,11 @@ struct intel_sdvo {  	/* DDC bus used by this SDVO encoder */  	uint8_t ddc_bus; + +	/* +	 * the sdvo flag gets lost in round trip: dtd->adjusted_mode->dtd +	 */ +	uint8_t dtd_sdvo_flags;  };  struct intel_sdvo_connector { @@ -889,6 +894,45 @@ static void intel_sdvo_dump_hdmi_buf(struct intel_sdvo *intel_sdvo)  }  #endif +static bool intel_sdvo_write_infoframe(struct intel_sdvo *intel_sdvo, +				       unsigned if_index, uint8_t tx_rate, +				       uint8_t *data, unsigned length) +{ +	uint8_t set_buf_index[2] = { if_index, 0 }; +	uint8_t hbuf_size, tmp[8]; +	int i; + +	if (!intel_sdvo_set_value(intel_sdvo, +				  SDVO_CMD_SET_HBUF_INDEX, +				  set_buf_index, 2)) +		return false; + +	if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_HBUF_INFO, +				  &hbuf_size, 1)) +		return false; + +	/* Buffer size is 0 based, hooray! */ +	hbuf_size++; + +	DRM_DEBUG_KMS("writing sdvo hbuf: %i, hbuf_size %i, hbuf_size: %i\n", +		      if_index, length, hbuf_size); + +	for (i = 0; i < hbuf_size; i += 8) { +		memset(tmp, 0, 8); +		if (i < length) +			memcpy(tmp, data + i, min_t(unsigned, 8, length - i)); + +		if (!intel_sdvo_set_value(intel_sdvo, +					  SDVO_CMD_SET_HBUF_DATA, +					  tmp, 8)) +			return false; +	} + +	return intel_sdvo_set_value(intel_sdvo, +				    SDVO_CMD_SET_HBUF_TXRATE, +				    &tx_rate, 1); +} +  static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)  {  	struct dip_infoframe avi_if = { @@ -896,11 +940,7 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)  		.ver = DIP_VERSION_AVI,  		.len = DIP_LEN_AVI,  	}; -	uint8_t tx_rate = SDVO_HBUF_TX_VSYNC; -	uint8_t set_buf_index[2] = { 1, 0 };  	uint8_t sdvo_data[4 + sizeof(avi_if.body.avi)]; -	uint64_t *data = (uint64_t *)sdvo_data; -	unsigned i;  	intel_dip_infoframe_csum(&avi_if); @@ -910,22 +950,9 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)  	sdvo_data[3] = avi_if.checksum;  	memcpy(&sdvo_data[4], &avi_if.body, sizeof(avi_if.body.avi)); -	if (!intel_sdvo_set_value(intel_sdvo, -				  SDVO_CMD_SET_HBUF_INDEX, -				  set_buf_index, 2)) -		return false; - -	for (i = 0; i < sizeof(sdvo_data); i += 8) { -		if (!intel_sdvo_set_value(intel_sdvo, -					  SDVO_CMD_SET_HBUF_DATA, -					  data, 8)) -			return false; -		data++; -	} - -	return intel_sdvo_set_value(intel_sdvo, -				    SDVO_CMD_SET_HBUF_TXRATE, -				    &tx_rate, 1); +	return intel_sdvo_write_infoframe(intel_sdvo, SDVO_HBUF_INDEX_AVI_IF, +					  SDVO_HBUF_TX_VSYNC, +					  sdvo_data, sizeof(sdvo_data));  }  static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo) @@ -984,6 +1011,7 @@ intel_sdvo_get_preferred_input_mode(struct intel_sdvo *intel_sdvo,  		return false;  	intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd); +	intel_sdvo->dtd_sdvo_flags = input_dtd.part2.sdvo_flags;  	return true;  } @@ -1092,6 +1120,8 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,  	 * adjusted_mode.  	 */  	intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode); +	if (intel_sdvo->is_tv || intel_sdvo->is_lvds) +		input_dtd.part2.sdvo_flags = intel_sdvo->dtd_sdvo_flags;  	if (!intel_sdvo_set_input_timing(intel_sdvo, &input_dtd))  		DRM_INFO("Setting input timings on %s failed\n",  			 SDVO_NAME(intel_sdvo)); @@ -2277,10 +2307,8 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device)  		intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS1;  	} -	/* SDVO LVDS is cloneable because the SDVO encoder does the upscaling, -	 * as opposed to native LVDS, where we upscale with the panel-fitter -	 * (and hence only the native LVDS resolution could be cloned). */ -	intel_sdvo->base.cloneable = true; +	/* SDVO LVDS is not cloneable because the input mode gets adjusted by the encoder */ +	intel_sdvo->base.cloneable = false;  	intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);  	if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector)) diff --git a/drivers/gpu/drm/i915/intel_sdvo_regs.h b/drivers/gpu/drm/i915/intel_sdvo_regs.h index 9d030142ee4..770bdd6ecd9 100644 --- a/drivers/gpu/drm/i915/intel_sdvo_regs.h +++ b/drivers/gpu/drm/i915/intel_sdvo_regs.h @@ -708,6 +708,8 @@ struct intel_sdvo_enhancements_arg {  #define SDVO_CMD_SET_AUDIO_STAT		0x91  #define SDVO_CMD_GET_AUDIO_STAT		0x92  #define SDVO_CMD_SET_HBUF_INDEX		0x93 +  #define SDVO_HBUF_INDEX_ELD		0 +  #define SDVO_HBUF_INDEX_AVI_IF	1  #define SDVO_CMD_GET_HBUF_INDEX		0x94  #define SDVO_CMD_GET_HBUF_INFO		0x95  #define SDVO_CMD_SET_HBUF_AV_SPLIT	0x96 diff --git a/drivers/gpu/drm/nouveau/core/core/gpuobj.c b/drivers/gpu/drm/nouveau/core/core/gpuobj.c index 1f34549aff1..70586fde69c 100644 --- a/drivers/gpu/drm/nouveau/core/core/gpuobj.c +++ b/drivers/gpu/drm/nouveau/core/core/gpuobj.c @@ -39,6 +39,11 @@ nouveau_gpuobj_destroy(struct nouveau_gpuobj *gpuobj)  			nv_wo32(gpuobj, i, 0x00000000);  	} +	if (gpuobj->node) { +		nouveau_mm_free(&nv_gpuobj(gpuobj->parent)->heap, +				&gpuobj->node); +	} +  	if (gpuobj->heap.block_size)  		nouveau_mm_fini(&gpuobj->heap); diff --git a/drivers/gpu/drm/nouveau/core/core/mm.c b/drivers/gpu/drm/nouveau/core/core/mm.c index bfddf87926d..a6d3cd6490f 100644 --- a/drivers/gpu/drm/nouveau/core/core/mm.c +++ b/drivers/gpu/drm/nouveau/core/core/mm.c @@ -218,13 +218,16 @@ nouveau_mm_init(struct nouveau_mm *mm, u32 offset, u32 length, u32 block)  	node = kzalloc(sizeof(*node), GFP_KERNEL);  	if (!node)  		return -ENOMEM; -	node->offset = roundup(offset, mm->block_size); -	node->length = rounddown(offset + length, mm->block_size) - node->offset; + +	if (length) { +		node->offset  = roundup(offset, mm->block_size); +		node->length  = rounddown(offset + length, mm->block_size); +		node->length -= node->offset; +	}  	list_add_tail(&node->nl_entry, &mm->nodes);  	list_add_tail(&node->fl_entry, &mm->free);  	mm->heap_nodes++; -	mm->heap_size += length;  	return 0;  } @@ -236,7 +239,7 @@ nouveau_mm_fini(struct nouveau_mm *mm)  	int nodes = 0;  	list_for_each_entry(node, &mm->nodes, nl_entry) { -		if (nodes++ == mm->heap_nodes) +		if (WARN_ON(nodes++ == mm->heap_nodes))  			return -EBUSY;  	} diff --git a/drivers/gpu/drm/nouveau/core/include/core/mm.h b/drivers/gpu/drm/nouveau/core/include/core/mm.h index 9ee9bf4028c..975137ba34a 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/mm.h +++ b/drivers/gpu/drm/nouveau/core/include/core/mm.h @@ -19,7 +19,6 @@ struct nouveau_mm {  	u32 block_size;  	int heap_nodes; -	u32 heap_size;  };  int  nouveau_mm_init(struct nouveau_mm *, u32 offset, u32 length, u32 block); diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c index dcb5c2befc9..70ca7d5a1aa 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c @@ -72,7 +72,7 @@ nouveau_bios_shadow_of(struct nouveau_bios *bios)  	}  	data = of_get_property(dn, "NVDA,BMP", &size); -	if (data) { +	if (data && size) {  		bios->size = size;  		bios->data = kmalloc(bios->size, GFP_KERNEL);  		if (bios->data) @@ -104,6 +104,9 @@ nouveau_bios_shadow_pramin(struct nouveau_bios *bios)  		goto out;  	bios->size = nv_rd08(bios, 0x700002) * 512; +	if (!bios->size) +		goto out; +  	bios->data = kmalloc(bios->size, GFP_KERNEL);  	if (bios->data) {  		for (i = 0; i < bios->size; i++) @@ -155,6 +158,9 @@ nouveau_bios_shadow_prom(struct nouveau_bios *bios)  	/* read entire bios image to system memory */  	bios->size = nv_rd08(bios, 0x300002) * 512; +	if (!bios->size) +		goto out; +  	bios->data = kmalloc(bios->size, GFP_KERNEL);  	if (bios->data) {  		for (i = 0; i < bios->size; i++) @@ -186,14 +192,22 @@ nouveau_bios_shadow_acpi(struct nouveau_bios *bios)  {  	struct pci_dev *pdev = nv_device(bios)->pdev;  	int ret, cnt, i; -	u8  data[3]; -	if (!nouveau_acpi_rom_supported(pdev)) +	if (!nouveau_acpi_rom_supported(pdev)) { +		bios->data = NULL;  		return; +	}  	bios->size = 0; -	if (nouveau_acpi_get_bios_chunk(data, 0, 3) == 3) -		bios->size = data[2] * 512; +	bios->data = kmalloc(4096, GFP_KERNEL); +	if (bios->data) { +		if (nouveau_acpi_get_bios_chunk(bios->data, 0, 4096) == 4096) +			bios->size = bios->data[2] * 512; +		kfree(bios->data); +	} + +	if (!bios->size) +		return;  	bios->data = kmalloc(bios->size, GFP_KERNEL);  	for (i = 0; bios->data && i < bios->size; i += cnt) { @@ -229,12 +243,14 @@ nouveau_bios_shadow_pci(struct nouveau_bios *bios)  static int  nouveau_bios_score(struct nouveau_bios *bios, const bool writeable)  { -	if (!bios->data || bios->data[0] != 0x55 || bios->data[1] != 0xAA) { +	if (bios->size < 3 || !bios->data || bios->data[0] != 0x55 || +			bios->data[1] != 0xAA) {  		nv_info(bios, "... signature not found\n");  		return 0;  	} -	if (nvbios_checksum(bios->data, bios->data[2] * 512)) { +	if (nvbios_checksum(bios->data, +			min_t(u32, bios->data[2] * 512, bios->size))) {  		nv_info(bios, "... checksum invalid\n");  		/* if a ro image is somewhat bad, it's probably all rubbish */  		return writeable ? 2 : 1; diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/pll.c b/drivers/gpu/drm/nouveau/core/subdev/bios/pll.c index 5e5f4cddae3..f835501203e 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/pll.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/pll.c @@ -157,11 +157,10 @@ pll_map_reg(struct nouveau_bios *bios, u32 reg, u32 *type, u8 *ver, u8 *len)  	while (map->reg) {  		if (map->reg == reg && *ver >= 0x20) {  			u16 addr = (data += hdr); +			*type = map->type;  			while (cnt--) { -				if (nv_ro32(bios, data) == map->reg) { -					*type = map->type; +				if (nv_ro32(bios, data) == map->reg)  					return data; -				}  				data += *len;  			}  			return addr; @@ -200,11 +199,10 @@ pll_map_type(struct nouveau_bios *bios, u8 type, u32 *reg, u8 *ver, u8 *len)  	while (map->reg) {  		if (map->type == type && *ver >= 0x20) {  			u16 addr = (data += hdr); +			*reg = map->reg;  			while (cnt--) { -				if (nv_ro32(bios, data) == map->reg) { -					*reg = map->reg; +				if (nv_ro32(bios, data) == map->reg)  					return data; -				}  				data += *len;  			}  			return addr; diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c index 42d7539e652..5f570806143 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c @@ -219,13 +219,11 @@ nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  			     ((priv->base.ram.size & 0x000000ff) << 32);  	tags = nv_rd32(priv, 0x100320); -	if (tags) { -		ret = nouveau_mm_init(&priv->base.tags, 0, tags, 1); -		if (ret) -			return ret; +	ret = nouveau_mm_init(&priv->base.tags, 0, tags, 1); +	if (ret) +		return ret; -		nv_debug(priv, "%d compression tags\n", tags); -	} +	nv_debug(priv, "%d compression tags\n", tags);  	size = (priv->base.ram.size >> 12) - rsvd_head - rsvd_tail;  	switch (device->chipset) { @@ -237,6 +235,7 @@ nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  			return ret;  		priv->base.ram.stolen = (u64)nv_rd32(priv, 0x100e10) << 12; +		priv->base.ram.type = NV_MEM_TYPE_STOLEN;  		break;  	default:  		ret = nouveau_mm_init(&priv->base.vram, rsvd_head, size, diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c index 3d2c88310f9..dbfc2abf0cf 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c @@ -292,7 +292,7 @@ nouveau_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  		case DCB_I2C_NVIO_BIT:  			port->drive = info.drive & 0x0f;  			if (device->card_type < NV_D0) { -				if (info.drive >= ARRAY_SIZE(nv50_i2c_port)) +				if (port->drive >= ARRAY_SIZE(nv50_i2c_port))  					break;  				port->drive = nv50_i2c_port[port->drive];  				port->sense = port->drive; diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c index 0203e1e12ca..49050d991e7 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c @@ -92,7 +92,8 @@ nv41_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	struct nv04_vmmgr_priv *priv;  	int ret; -	if (!nouveau_boolopt(device->cfgopt, "NvPCIE", true)) { +	if (pci_find_capability(device->pdev, PCI_CAP_ID_AGP) || +	    !nouveau_boolopt(device->cfgopt, "NvPCIE", true)) {  		return nouveau_object_ctor(parent, engine, &nv04_vmmgr_oclass,  					   data, size, pobject);  	} diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c index 0ac18d05a14..aa8131436e3 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c @@ -163,7 +163,8 @@ nv44_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  	struct nv04_vmmgr_priv *priv;  	int ret; -	if (!nouveau_boolopt(device->cfgopt, "NvPCIE", true)) { +	if (pci_find_capability(device->pdev, PCI_CAP_ID_AGP) || +	    !nouveau_boolopt(device->cfgopt, "NvPCIE", true)) {  		return nouveau_object_ctor(parent, engine, &nv04_vmmgr_oclass,  					   data, size, pobject);  	} diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 8f98e5a8c48..86124b131f4 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -290,6 +290,7 @@ nouveau_display_create(struct drm_device *dev)  	struct nouveau_drm *drm = nouveau_drm(dev);  	struct nouveau_disp *pdisp = nouveau_disp(drm->device);  	struct nouveau_display *disp; +	u32 pclass = dev->pdev->class >> 8;  	int ret, gen;  	disp = drm->display = kzalloc(sizeof(*disp), GFP_KERNEL); @@ -360,23 +361,27 @@ nouveau_display_create(struct drm_device *dev)  	drm_kms_helper_poll_init(dev);  	drm_kms_helper_poll_disable(dev); -	if (nv_device(drm->device)->card_type < NV_50) -		ret = nv04_display_create(dev); -	else -	if (nv_device(drm->device)->card_type < NV_D0) -		ret = nv50_display_create(dev); -	else -		ret = nvd0_display_create(dev); -	if (ret) -		goto disp_create_err; - -	if (dev->mode_config.num_crtc) { -		ret = drm_vblank_init(dev, dev->mode_config.num_crtc); +	if (nouveau_modeset == 1 || +	    (nouveau_modeset < 0 && pclass == PCI_CLASS_DISPLAY_VGA)) { +		if (nv_device(drm->device)->card_type < NV_50) +			ret = nv04_display_create(dev); +		else +		if (nv_device(drm->device)->card_type < NV_D0) +			ret = nv50_display_create(dev); +		else +			ret = nvd0_display_create(dev);  		if (ret) -			goto vblank_err; +			goto disp_create_err; + +		if (dev->mode_config.num_crtc) { +			ret = drm_vblank_init(dev, dev->mode_config.num_crtc); +			if (ret) +				goto vblank_err; +		} + +		nouveau_backlight_init(dev);  	} -	nouveau_backlight_init(dev);  	return 0;  vblank_err: @@ -395,7 +400,8 @@ nouveau_display_destroy(struct drm_device *dev)  	nouveau_backlight_exit(dev);  	drm_vblank_cleanup(dev); -	disp->dtor(dev); +	if (disp->dtor) +		disp->dtor(dev);  	drm_kms_helper_poll_fini(dev);  	drm_mode_config_cleanup(dev); @@ -530,9 +536,11 @@ nouveau_page_flip_reserve(struct nouveau_bo *old_bo,  	if (ret)  		goto fail; -	ret = ttm_bo_reserve(&old_bo->bo, false, false, false, 0); -	if (ret) -		goto fail_unreserve; +	if (likely(old_bo != new_bo)) { +		ret = ttm_bo_reserve(&old_bo->bo, false, false, false, 0); +		if (ret) +			goto fail_unreserve; +	}  	return 0; @@ -551,8 +559,10 @@ nouveau_page_flip_unreserve(struct nouveau_bo *old_bo,  	nouveau_bo_fence(new_bo, fence);  	ttm_bo_unreserve(&new_bo->bo); -	nouveau_bo_fence(old_bo, fence); -	ttm_bo_unreserve(&old_bo->bo); +	if (likely(old_bo != new_bo)) { +		nouveau_bo_fence(old_bo, fence); +		ttm_bo_unreserve(&old_bo->bo); +	}  	nouveau_bo_unpin(old_bo);  } diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index ccae8c26ae2..0910125cbbc 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -63,8 +63,9 @@ MODULE_PARM_DESC(noaccel, "disable kernel/abi16 acceleration");  static int nouveau_noaccel = 0;  module_param_named(noaccel, nouveau_noaccel, int, 0400); -MODULE_PARM_DESC(modeset, "enable driver"); -static int nouveau_modeset = -1; +MODULE_PARM_DESC(modeset, "enable driver (default: auto, " +		          "0 = disabled, 1 = enabled, 2 = headless)"); +int nouveau_modeset = -1;  module_param_named(modeset, nouveau_modeset, int, 0400);  static struct drm_driver driver; @@ -363,7 +364,8 @@ nouveau_drm_unload(struct drm_device *dev)  	nouveau_pm_fini(dev); -	nouveau_display_fini(dev); +	if (dev->mode_config.num_crtc) +		nouveau_display_fini(dev);  	nouveau_display_destroy(dev);  	nouveau_irq_fini(dev); @@ -403,13 +405,15 @@ nouveau_drm_suspend(struct pci_dev *pdev, pm_message_t pm_state)  	    pm_state.event == PM_EVENT_PRETHAW)  		return 0; -	NV_INFO(drm, "suspending fbcon...\n"); -	nouveau_fbcon_set_suspend(dev, 1); +	if (dev->mode_config.num_crtc) { +		NV_INFO(drm, "suspending fbcon...\n"); +		nouveau_fbcon_set_suspend(dev, 1); -	NV_INFO(drm, "suspending display...\n"); -	ret = nouveau_display_suspend(dev); -	if (ret) -		return ret; +		NV_INFO(drm, "suspending display...\n"); +		ret = nouveau_display_suspend(dev); +		if (ret) +			return ret; +	}  	NV_INFO(drm, "evicting buffers...\n");  	ttm_bo_evict_mm(&drm->ttm.bdev, TTM_PL_VRAM); @@ -445,8 +449,10 @@ fail_client:  		nouveau_client_init(&cli->base);  	} -	NV_INFO(drm, "resuming display...\n"); -	nouveau_display_resume(dev); +	if (dev->mode_config.num_crtc) { +		NV_INFO(drm, "resuming display...\n"); +		nouveau_display_resume(dev); +	}  	return ret;  } @@ -486,8 +492,10 @@ nouveau_drm_resume(struct pci_dev *pdev)  	nouveau_irq_postinstall(dev);  	nouveau_pm_resume(dev); -	NV_INFO(drm, "resuming display...\n"); -	nouveau_display_resume(dev); +	if (dev->mode_config.num_crtc) { +		NV_INFO(drm, "resuming display...\n"); +		nouveau_display_resume(dev); +	}  	return 0;  } @@ -662,9 +670,7 @@ nouveau_drm_init(void)  #ifdef CONFIG_VGA_CONSOLE  		if (vgacon_text_force())  			nouveau_modeset = 0; -		else  #endif -			nouveau_modeset = 1;  	}  	if (!nouveau_modeset) diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.h b/drivers/gpu/drm/nouveau/nouveau_drm.h index 81947121754..a1016992708 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.h +++ b/drivers/gpu/drm/nouveau/nouveau_drm.h @@ -141,4 +141,6 @@ int nouveau_drm_resume(struct pci_dev *);  		nv_info((cli), fmt, ##args);                                   \  } while (0) +extern int nouveau_modeset; +  #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_irq.c b/drivers/gpu/drm/nouveau/nouveau_irq.c index 9ca8afdb554..1d8cb506a28 100644 --- a/drivers/gpu/drm/nouveau/nouveau_irq.c +++ b/drivers/gpu/drm/nouveau/nouveau_irq.c @@ -61,13 +61,15 @@ nouveau_irq_handler(DRM_IRQ_ARGS)  	nv_subdev(pmc)->intr(nv_subdev(pmc)); -	if (device->card_type >= NV_D0) { -		if (nv_rd32(device, 0x000100) & 0x04000000) -			nvd0_display_intr(dev); -	} else -	if (device->card_type >= NV_50) { -		if (nv_rd32(device, 0x000100) & 0x04000000) -			nv50_display_intr(dev); +	if (dev->mode_config.num_crtc) { +		if (device->card_type >= NV_D0) { +			if (nv_rd32(device, 0x000100) & 0x04000000) +				nvd0_display_intr(dev); +		} else +		if (device->card_type >= NV_50) { +			if (nv_rd32(device, 0x000100) & 0x04000000) +				nv50_display_intr(dev); +		}  	}  	return IRQ_HANDLED; diff --git a/drivers/gpu/drm/nouveau/nv04_dac.c b/drivers/gpu/drm/nouveau/nv04_dac.c index 347a3bd78d0..64f7020fb60 100644 --- a/drivers/gpu/drm/nouveau/nv04_dac.c +++ b/drivers/gpu/drm/nouveau/nv04_dac.c @@ -220,7 +220,7 @@ out:  	NVWriteVgaCrtc(dev, 0, NV_CIO_CR_MODE_INDEX, saved_cr_mode);  	if (blue == 0x18) { -		NV_INFO(drm, "Load detected on head A\n"); +		NV_DEBUG(drm, "Load detected on head A\n");  		return connector_status_connected;  	} @@ -338,8 +338,8 @@ nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)  	if (nv17_dac_sample_load(encoder) &  	    NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) { -		NV_INFO(drm, "Load detected on output %c\n", -			'@' + ffs(dcb->or)); +		NV_DEBUG(drm, "Load detected on output %c\n", +			 '@' + ffs(dcb->or));  		return connector_status_connected;  	} else {  		return connector_status_disconnected; @@ -413,9 +413,9 @@ static void nv04_dac_commit(struct drm_encoder *encoder)  	helper->dpms(encoder, DRM_MODE_DPMS_ON); -	NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n", -		drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), -		nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); +	NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n", +		 drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), +		 nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));  }  void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable) @@ -461,8 +461,8 @@ static void nv04_dac_dpms(struct drm_encoder *encoder, int mode)  		return;  	nv_encoder->last_dpms = mode; -	NV_INFO(drm, "Setting dpms mode %d on vga encoder (output %d)\n", -		     mode, nv_encoder->dcb->index); +	NV_DEBUG(drm, "Setting dpms mode %d on vga encoder (output %d)\n", +		 mode, nv_encoder->dcb->index);  	nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON);  } diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/nv04_dfp.c index da55d7642c8..184cdf80676 100644 --- a/drivers/gpu/drm/nouveau/nv04_dfp.c +++ b/drivers/gpu/drm/nouveau/nv04_dfp.c @@ -476,9 +476,9 @@ static void nv04_dfp_commit(struct drm_encoder *encoder)  	helper->dpms(encoder, DRM_MODE_DPMS_ON); -	NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n", -		drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), -		nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); +	NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n", +		 drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), +		 nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));  }  static void nv04_dfp_update_backlight(struct drm_encoder *encoder, int mode) @@ -520,8 +520,8 @@ static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode)  		return;  	nv_encoder->last_dpms = mode; -	NV_INFO(drm, "Setting dpms mode %d on lvds encoder (output %d)\n", -		     mode, nv_encoder->dcb->index); +	NV_DEBUG(drm, "Setting dpms mode %d on lvds encoder (output %d)\n", +		 mode, nv_encoder->dcb->index);  	if (was_powersaving && is_powersaving_dpms(mode))  		return; @@ -565,8 +565,8 @@ static void nv04_tmds_dpms(struct drm_encoder *encoder, int mode)  		return;  	nv_encoder->last_dpms = mode; -	NV_INFO(drm, "Setting dpms mode %d on tmds encoder (output %d)\n", -		     mode, nv_encoder->dcb->index); +	NV_DEBUG(drm, "Setting dpms mode %d on tmds encoder (output %d)\n", +		 mode, nv_encoder->dcb->index);  	nv04_dfp_update_backlight(encoder, mode);  	nv04_dfp_update_fp_control(encoder, mode); diff --git a/drivers/gpu/drm/nouveau/nv04_tv.c b/drivers/gpu/drm/nouveau/nv04_tv.c index 099fbeda6e2..62e826a139b 100644 --- a/drivers/gpu/drm/nouveau/nv04_tv.c +++ b/drivers/gpu/drm/nouveau/nv04_tv.c @@ -75,8 +75,8 @@ static void nv04_tv_dpms(struct drm_encoder *encoder, int mode)  	struct nv04_mode_state *state = &nv04_display(dev)->mode_reg;  	uint8_t crtc1A; -	NV_INFO(drm, "Setting dpms mode %d on TV encoder (output %d)\n", -		mode, nv_encoder->dcb->index); +	NV_DEBUG(drm, "Setting dpms mode %d on TV encoder (output %d)\n", +		 mode, nv_encoder->dcb->index);  	state->pllsel &= ~(PLLSEL_TV_CRTC1_MASK | PLLSEL_TV_CRTC2_MASK); @@ -167,9 +167,8 @@ static void nv04_tv_commit(struct drm_encoder *encoder)  	helper->dpms(encoder, DRM_MODE_DPMS_ON); -	NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n", -		      drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index, -		      '@' + ffs(nv_encoder->dcb->or)); +	NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n", +		 drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));  }  static void nv04_tv_destroy(struct drm_encoder *encoder) diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index 49cbb3795a1..ba498f8e47a 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -184,6 +184,7 @@ void radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder,  	struct radeon_backlight_privdata *pdata;  	struct radeon_encoder_atom_dig *dig;  	u8 backlight_level; +	char bl_name[16];  	if (!radeon_encoder->enc_priv)  		return; @@ -203,7 +204,9 @@ void radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder,  	memset(&props, 0, sizeof(props));  	props.max_brightness = RADEON_MAX_BL_LEVEL;  	props.type = BACKLIGHT_RAW; -	bd = backlight_device_register("radeon_bl", &drm_connector->kdev, +	snprintf(bl_name, sizeof(bl_name), +		 "radeon_bl%d", dev->primary->index); +	bd = backlight_device_register(bl_name, &drm_connector->kdev,  				       pdata, &radeon_atom_backlight_ops, &props);  	if (IS_ERR(bd)) {  		DRM_ERROR("Backlight registration failed\n"); diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index 573ed1bc6cf..95e6318b626 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -264,7 +264,7 @@ static int evergreen_surface_check_2d(struct radeon_cs_parser *p,  	/* macro tile width & height */  	palign = (8 * surf->bankw * track->npipes) * surf->mtilea;  	halign = (8 * surf->bankh * surf->nbanks) / surf->mtilea; -	mtileb = (palign / 8) * (halign / 8) * tileb;; +	mtileb = (palign / 8) * (halign / 8) * tileb;  	mtile_pr = surf->nbx / palign;  	mtile_ps = (mtile_pr * surf->nby) / halign;  	surf->layer_size = mtile_ps * mtileb * slice_pt; @@ -2829,6 +2829,7 @@ static bool evergreen_vm_reg_valid(u32 reg)  	case CAYMAN_SQ_EX_ALLOC_TABLE_SLOTS:  		return true;  	default: +		DRM_ERROR("Invalid register 0x%x in CS\n", reg);  		return false;  	}  } diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 8c74c729586..81e6a568c29 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -1538,26 +1538,31 @@ void cayman_vm_set_page(struct radeon_device *rdev, uint64_t pe,  {  	struct radeon_ring *ring = &rdev->ring[rdev->asic->vm.pt_ring_index];  	uint32_t r600_flags = cayman_vm_page_flags(rdev, flags); -	int i; -	radeon_ring_write(ring, PACKET3(PACKET3_ME_WRITE, 1 + count * 2)); -	radeon_ring_write(ring, pe); -	radeon_ring_write(ring, upper_32_bits(pe) & 0xff); -	for (i = 0; i < count; ++i) { -		uint64_t value = 0; -		if (flags & RADEON_VM_PAGE_SYSTEM) { -			value = radeon_vm_map_gart(rdev, addr); -			value &= 0xFFFFFFFFFFFFF000ULL; -			addr += incr; +	while (count) { +		unsigned ndw = 1 + count * 2; +		if (ndw > 0x3FFF) +			ndw = 0x3FFF; -		} else if (flags & RADEON_VM_PAGE_VALID) { -			value = addr; -			addr += incr; -		} +		radeon_ring_write(ring, PACKET3(PACKET3_ME_WRITE, ndw)); +		radeon_ring_write(ring, pe); +		radeon_ring_write(ring, upper_32_bits(pe) & 0xff); +		for (; ndw > 1; ndw -= 2, --count, pe += 8) { +			uint64_t value = 0; +			if (flags & RADEON_VM_PAGE_SYSTEM) { +				value = radeon_vm_map_gart(rdev, addr); +				value &= 0xFFFFFFFFFFFFF000ULL; +				addr += incr; + +			} else if (flags & RADEON_VM_PAGE_VALID) { +				value = addr; +				addr += incr; +			} -		value |= r600_flags; -		radeon_ring_write(ring, value); -		radeon_ring_write(ring, upper_32_bits(value)); +			value |= r600_flags; +			radeon_ring_write(ring, value); +			radeon_ring_write(ring, upper_32_bits(value)); +		}  	}  } @@ -1586,4 +1591,8 @@ void cayman_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm)  	/* bits 0-7 are the VM contexts0-7 */  	radeon_ring_write(ring, PACKET0(VM_INVALIDATE_REQUEST, 0));  	radeon_ring_write(ring, 1 << vm->id); + +	/* sync PFP to ME, otherwise we might get invalid PFP reads */ +	radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0)); +	radeon_ring_write(ring, 0x0);  } diff --git a/drivers/gpu/drm/radeon/nid.h b/drivers/gpu/drm/radeon/nid.h index 2423d1b5d38..cbef6815907 100644 --- a/drivers/gpu/drm/radeon/nid.h +++ b/drivers/gpu/drm/radeon/nid.h @@ -502,6 +502,7 @@  #define	PACKET3_MPEG_INDEX				0x3A  #define	PACKET3_WAIT_REG_MEM				0x3C  #define	PACKET3_MEM_WRITE				0x3D +#define	PACKET3_PFP_SYNC_ME				0x42  #define	PACKET3_SURFACE_SYNC				0x43  #              define PACKET3_CB0_DEST_BASE_ENA    (1 << 6)  #              define PACKET3_CB1_DEST_BASE_ENA    (1 << 7) diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c index 1aa3f910b99..15f5ded65e0 100644 --- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c +++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c @@ -87,7 +87,7 @@ static union acpi_object *radeon_atpx_call(acpi_handle handle, int function,  		atpx_arg_elements[1].integer.value = 0;  	} -	status = acpi_evaluate_object(handle, "ATPX", &atpx_arg, &buffer); +	status = acpi_evaluate_object(handle, NULL, &atpx_arg, &buffer);  	/* Fail only if calling the method fails and ATPX is supported */  	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { @@ -352,9 +352,9 @@ static int radeon_atpx_switchto(enum vga_switcheroo_client_id id)  }  /** - * radeon_atpx_switchto - switch to the requested GPU + * radeon_atpx_power_state - power down/up the requested GPU   * - * @id: GPU to switch to + * @id: GPU to power down/up   * @state: requested power state (0 = off, 1 = on)   *   * Execute the necessary ATPX function to power down/up the discrete GPU @@ -373,11 +373,11 @@ static int radeon_atpx_power_state(enum vga_switcheroo_client_id id,  }  /** - * radeon_atpx_pci_probe_handle - look up the ATRM and ATPX handles + * radeon_atpx_pci_probe_handle - look up the ATPX handle   *   * @pdev: pci device   * - * Look up the ATPX and ATRM handles (all asics). + * Look up the ATPX handles (all asics).   * Returns true if the handles are found, false if not.   */  static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev) diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 67cfc1795ec..b884c362a8c 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -941,7 +941,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)  	struct drm_mode_object *obj;  	int i;  	enum drm_connector_status ret = connector_status_disconnected; -	bool dret = false; +	bool dret = false, broken_edid = false;  	if (!force && radeon_check_hpd_status_unchanged(connector))  		return connector->status; @@ -965,6 +965,9 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)  				ret = connector_status_disconnected;  				DRM_ERROR("%s: detected RS690 floating bus bug, stopping ddc detect\n", drm_get_connector_name(connector));  				radeon_connector->ddc_bus = NULL; +			} else { +				ret = connector_status_connected; +				broken_edid = true; /* defer use_digital to later */  			}  		} else {  			radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL); @@ -1047,13 +1050,24 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)  			encoder_funcs = encoder->helper_private;  			if (encoder_funcs->detect) { -				if (ret != connector_status_connected) { -					ret = encoder_funcs->detect(encoder, connector); -					if (ret == connector_status_connected) { -						radeon_connector->use_digital = false; +				if (!broken_edid) { +					if (ret != connector_status_connected) { +						/* deal with analog monitors without DDC */ +						ret = encoder_funcs->detect(encoder, connector); +						if (ret == connector_status_connected) { +							radeon_connector->use_digital = false; +						} +						if (ret != connector_status_disconnected) +							radeon_connector->detected_by_load = true;  					} -					if (ret != connector_status_disconnected) -						radeon_connector->detected_by_load = true; +				} else { +					enum drm_connector_status lret; +					/* assume digital unless load detected otherwise */ +					radeon_connector->use_digital = true; +					lret = encoder_funcs->detect(encoder, connector); +					DRM_DEBUG_KMS("load_detect %x returned: %x\n",encoder->encoder_type,lret); +					if (lret == connector_status_connected) +						radeon_connector->use_digital = false;  				}  				break;  			} diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index bd13ca09eb6..e2f5f888c37 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -355,6 +355,8 @@ int radeon_wb_init(struct radeon_device *rdev)   */  void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64 base)  { +	uint64_t limit = (uint64_t)radeon_vram_limit << 20; +  	mc->vram_start = base;  	if (mc->mc_vram_size > (0xFFFFFFFF - base + 1)) {  		dev_warn(rdev->dev, "limiting VRAM to PCI aperture size\n"); @@ -368,8 +370,8 @@ void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64  		mc->mc_vram_size = mc->aper_size;  	}  	mc->vram_end = mc->vram_start + mc->mc_vram_size - 1; -	if (radeon_vram_limit && radeon_vram_limit < mc->real_vram_size) -		mc->real_vram_size = radeon_vram_limit; +	if (limit && limit < mc->real_vram_size) +		mc->real_vram_size = limit;  	dev_info(rdev->dev, "VRAM: %lluM 0x%016llX - 0x%016llX (%lluM used)\n",  			mc->mc_vram_size >> 20, mc->vram_start,  			mc->vram_end, mc->real_vram_size >> 20); @@ -835,6 +837,19 @@ static unsigned int radeon_vga_set_decode(void *cookie, bool state)  }  /** + * radeon_check_pot_argument - check that argument is a power of two + * + * @arg: value to check + * + * Validates that a certain argument is a power of two (all asics). + * Returns true if argument is valid. + */ +static bool radeon_check_pot_argument(int arg) +{ +	return (arg & (arg - 1)) == 0; +} + +/**   * radeon_check_arguments - validate module params   *   * @rdev: radeon_device pointer @@ -845,52 +860,25 @@ static unsigned int radeon_vga_set_decode(void *cookie, bool state)  static void radeon_check_arguments(struct radeon_device *rdev)  {  	/* vramlimit must be a power of two */ -	switch (radeon_vram_limit) { -	case 0: -	case 4: -	case 8: -	case 16: -	case 32: -	case 64: -	case 128: -	case 256: -	case 512: -	case 1024: -	case 2048: -	case 4096: -		break; -	default: +	if (!radeon_check_pot_argument(radeon_vram_limit)) {  		dev_warn(rdev->dev, "vram limit (%d) must be a power of 2\n",  				radeon_vram_limit);  		radeon_vram_limit = 0; -		break;  	} -	radeon_vram_limit = radeon_vram_limit << 20; +  	/* gtt size must be power of two and greater or equal to 32M */ -	switch (radeon_gart_size) { -	case 4: -	case 8: -	case 16: +	if (radeon_gart_size < 32) {  		dev_warn(rdev->dev, "gart size (%d) too small forcing to 512M\n",  				radeon_gart_size);  		radeon_gart_size = 512; -		break; -	case 32: -	case 64: -	case 128: -	case 256: -	case 512: -	case 1024: -	case 2048: -	case 4096: -		break; -	default: + +	} else if (!radeon_check_pot_argument(radeon_gart_size)) {  		dev_warn(rdev->dev, "gart size (%d) must be a power of 2\n",  				radeon_gart_size);  		radeon_gart_size = 512; -		break;  	} -	rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; +	rdev->mc.gtt_size = (uint64_t)radeon_gart_size << 20; +  	/* AGP mode can only be -1, 1, 2, 4, 8 */  	switch (radeon_agpmode) {  	case -1: diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index a7677dd1ce9..4debd60e5aa 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c @@ -355,14 +355,13 @@ int radeon_gart_init(struct radeon_device *rdev)  	DRM_INFO("GART: num cpu pages %u, num gpu pages %u\n",  		 rdev->gart.num_cpu_pages, rdev->gart.num_gpu_pages);  	/* Allocate pages table */ -	rdev->gart.pages = kzalloc(sizeof(void *) * rdev->gart.num_cpu_pages, -				   GFP_KERNEL); +	rdev->gart.pages = vzalloc(sizeof(void *) * rdev->gart.num_cpu_pages);  	if (rdev->gart.pages == NULL) {  		radeon_gart_fini(rdev);  		return -ENOMEM;  	} -	rdev->gart.pages_addr = kzalloc(sizeof(dma_addr_t) * -					rdev->gart.num_cpu_pages, GFP_KERNEL); +	rdev->gart.pages_addr = vzalloc(sizeof(dma_addr_t) * +					rdev->gart.num_cpu_pages);  	if (rdev->gart.pages_addr == NULL) {  		radeon_gart_fini(rdev);  		return -ENOMEM; @@ -388,8 +387,8 @@ void radeon_gart_fini(struct radeon_device *rdev)  		radeon_gart_unbind(rdev, 0, rdev->gart.num_cpu_pages);  	}  	rdev->gart.ready = false; -	kfree(rdev->gart.pages); -	kfree(rdev->gart.pages_addr); +	vfree(rdev->gart.pages); +	vfree(rdev->gart.pages_addr);  	rdev->gart.pages = NULL;  	rdev->gart.pages_addr = NULL; @@ -577,7 +576,7 @@ void radeon_vm_manager_fini(struct radeon_device *rdev)   *   * Global and local mutex must be locked!   */ -int radeon_vm_evict(struct radeon_device *rdev, struct radeon_vm *vm) +static int radeon_vm_evict(struct radeon_device *rdev, struct radeon_vm *vm)  {  	struct radeon_vm *vm_evict; @@ -1036,8 +1035,7 @@ static void radeon_vm_update_ptes(struct radeon_device *rdev,  		pte = radeon_sa_bo_gpu_addr(vm->page_tables[pt_idx]);  		pte += (addr & mask) * 8; -		if (((last_pte + 8 * count) != pte) || -		    ((count + nptes) > 1 << 11)) { +		if ((last_pte + 8 * count) != pte) {  			if (count) {  				radeon_asic_vm_set_page(rdev, last_pte, @@ -1148,17 +1146,17 @@ int radeon_vm_bo_update_pte(struct radeon_device *rdev,  	if (RADEON_VM_BLOCK_SIZE > 11)  		/* reserve space for one header for every 2k dwords */ -		ndw += (nptes >> 11) * 3; +		ndw += (nptes >> 11) * 4;  	else  		/* reserve space for one header for  		    every (1 << BLOCK_SIZE) entries */ -		ndw += (nptes >> RADEON_VM_BLOCK_SIZE) * 3; +		ndw += (nptes >> RADEON_VM_BLOCK_SIZE) * 4;  	/* reserve space for pte addresses */  	ndw += nptes * 2;  	/* reserve space for one header for every 2k dwords */ -	ndw += (npdes >> 11) * 3; +	ndw += (npdes >> 11) * 4;  	/* reserve space for pde addresses */  	ndw += npdes * 2; diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index f38fbcc4693..fe5c1f6b795 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -53,6 +53,7 @@ int radeon_gem_object_create(struct radeon_device *rdev, int size,  				struct drm_gem_object **obj)  {  	struct radeon_bo *robj; +	unsigned long max_size;  	int r;  	*obj = NULL; @@ -60,11 +61,26 @@ int radeon_gem_object_create(struct radeon_device *rdev, int size,  	if (alignment < PAGE_SIZE) {  		alignment = PAGE_SIZE;  	} + +	/* maximun bo size is the minimun btw visible vram and gtt size */ +	max_size = min(rdev->mc.visible_vram_size, rdev->mc.gtt_size); +	if (size > max_size) { +		printk(KERN_WARNING "%s:%d alloc size %dMb bigger than %ldMb limit\n", +		       __func__, __LINE__, size >> 20, max_size >> 20); +		return -ENOMEM; +	} + +retry:  	r = radeon_bo_create(rdev, size, alignment, kernel, initial_domain, NULL, &robj);  	if (r) { -		if (r != -ERESTARTSYS) +		if (r != -ERESTARTSYS) { +			if (initial_domain == RADEON_GEM_DOMAIN_VRAM) { +				initial_domain |= RADEON_GEM_DOMAIN_GTT; +				goto retry; +			}  			DRM_ERROR("Failed to allocate GEM object (%d, %d, %u, %d)\n",  				  size, initial_domain, alignment, r); +		}  		return r;  	}  	*obj = &robj->gem_base; diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index 5677a424b58..6857cb4efb7 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c @@ -295,6 +295,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)  	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);  	struct drm_device *dev = crtc->dev;  	struct radeon_device *rdev = dev->dev_private; +	uint32_t crtc_ext_cntl = 0;  	uint32_t mask;  	if (radeon_crtc->crtc_id) @@ -307,6 +308,16 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)  			RADEON_CRTC_VSYNC_DIS |  			RADEON_CRTC_HSYNC_DIS); +	/* +	 * On all dual CRTC GPUs this bit controls the CRTC of the primary DAC. +	 * Therefore it is set in the DAC DMPS function. +	 * This is different for GPU's with a single CRTC but a primary and a +	 * TV DAC: here it controls the single CRTC no matter where it is +	 * routed. Therefore we set it here. +	 */ +	if (rdev->flags & RADEON_SINGLE_CRTC) +		crtc_ext_cntl = RADEON_CRTC_CRT_ON; +	  	switch (mode) {  	case DRM_MODE_DPMS_ON:  		radeon_crtc->enabled = true; @@ -317,7 +328,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)  		else {  			WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_EN, ~(RADEON_CRTC_EN |  									 RADEON_CRTC_DISP_REQ_EN_B)); -			WREG32_P(RADEON_CRTC_EXT_CNTL, 0, ~mask); +			WREG32_P(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl, ~(mask | crtc_ext_cntl));  		}  		drm_vblank_post_modeset(dev, radeon_crtc->crtc_id);  		radeon_crtc_load_lut(crtc); @@ -331,7 +342,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)  		else {  			WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B, ~(RADEON_CRTC_EN |  										    RADEON_CRTC_DISP_REQ_EN_B)); -			WREG32_P(RADEON_CRTC_EXT_CNTL, mask, ~mask); +			WREG32_P(RADEON_CRTC_EXT_CNTL, mask, ~(mask | crtc_ext_cntl));  		}  		radeon_crtc->enabled = false;  		/* adjust pm to dpms changes AFTER disabling crtcs */ diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index a13ad9d707c..f5ba2241dac 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c @@ -370,6 +370,7 @@ void radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,  	struct backlight_properties props;  	struct radeon_backlight_privdata *pdata;  	uint8_t backlight_level; +	char bl_name[16];  	if (!radeon_encoder->enc_priv)  		return; @@ -389,7 +390,9 @@ void radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,  	memset(&props, 0, sizeof(props));  	props.max_brightness = RADEON_MAX_BL_LEVEL;  	props.type = BACKLIGHT_RAW; -	bd = backlight_device_register("radeon_bl", &drm_connector->kdev, +	snprintf(bl_name, sizeof(bl_name), +		 "radeon_bl%d", dev->primary->index); +	bd = backlight_device_register(bl_name, &drm_connector->kdev,  				       pdata, &radeon_backlight_ops, &props);  	if (IS_ERR(bd)) {  		DRM_ERROR("Backlight registration failed\n"); @@ -534,7 +537,9 @@ static void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode  		break;  	} -	WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl); +	/* handled in radeon_crtc_dpms() */ +	if (!(rdev->flags & RADEON_SINGLE_CRTC)) +		WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);  	WREG32(RADEON_DAC_CNTL, dac_cntl);  	WREG32(RADEON_DAC_MACRO_CNTL, dac_macro_cntl); @@ -659,6 +664,8 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc  	if (ASIC_IS_R300(rdev))  		tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT); +	else if (ASIC_IS_RV100(rdev)) +		tmp |= (0x1ac << RADEON_DAC_FORCE_DATA_SHIFT);  	else  		tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT); @@ -668,6 +675,7 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc  	tmp |= RADEON_DAC_RANGE_CNTL_PS2 | RADEON_DAC_CMP_EN;  	WREG32(RADEON_DAC_CNTL, tmp); +	tmp = dac_macro_cntl;  	tmp &= ~(RADEON_DAC_PDWN_R |  		 RADEON_DAC_PDWN_G |  		 RADEON_DAC_PDWN_B); @@ -1089,7 +1097,8 @@ static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode)  	} else {  		if (is_tv)  			WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl); -		else +		/* handled in radeon_crtc_dpms() */ +		else if (!(rdev->flags & RADEON_SINGLE_CRTC))  			WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);  		WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);  	} @@ -1413,13 +1422,104 @@ static bool radeon_legacy_tv_detect(struct drm_encoder *encoder,  	return found;  } +static bool radeon_legacy_ext_dac_detect(struct drm_encoder *encoder, +					 struct drm_connector *connector) +{ +	struct drm_device *dev = encoder->dev; +	struct radeon_device *rdev = dev->dev_private; +	uint32_t gpio_monid, fp2_gen_cntl, disp_output_cntl, crtc2_gen_cntl; +	uint32_t disp_lin_trans_grph_a, disp_lin_trans_grph_b, disp_lin_trans_grph_c; +	uint32_t disp_lin_trans_grph_d, disp_lin_trans_grph_e, disp_lin_trans_grph_f; +	uint32_t tmp, crtc2_h_total_disp, crtc2_v_total_disp; +	uint32_t crtc2_h_sync_strt_wid, crtc2_v_sync_strt_wid; +	bool found = false; +	int i; + +	/* save the regs we need */ +	gpio_monid = RREG32(RADEON_GPIO_MONID); +	fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL); +	disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL); +	crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); +	disp_lin_trans_grph_a = RREG32(RADEON_DISP_LIN_TRANS_GRPH_A); +	disp_lin_trans_grph_b = RREG32(RADEON_DISP_LIN_TRANS_GRPH_B); +	disp_lin_trans_grph_c = RREG32(RADEON_DISP_LIN_TRANS_GRPH_C); +	disp_lin_trans_grph_d = RREG32(RADEON_DISP_LIN_TRANS_GRPH_D); +	disp_lin_trans_grph_e = RREG32(RADEON_DISP_LIN_TRANS_GRPH_E); +	disp_lin_trans_grph_f = RREG32(RADEON_DISP_LIN_TRANS_GRPH_F); +	crtc2_h_total_disp = RREG32(RADEON_CRTC2_H_TOTAL_DISP); +	crtc2_v_total_disp = RREG32(RADEON_CRTC2_V_TOTAL_DISP); +	crtc2_h_sync_strt_wid = RREG32(RADEON_CRTC2_H_SYNC_STRT_WID); +	crtc2_v_sync_strt_wid = RREG32(RADEON_CRTC2_V_SYNC_STRT_WID); + +	tmp = RREG32(RADEON_GPIO_MONID); +	tmp &= ~RADEON_GPIO_A_0; +	WREG32(RADEON_GPIO_MONID, tmp); + +	WREG32(RADEON_FP2_GEN_CNTL, (RADEON_FP2_ON | +				     RADEON_FP2_PANEL_FORMAT | +				     R200_FP2_SOURCE_SEL_TRANS_UNIT | +				     RADEON_FP2_DVO_EN | +				     R200_FP2_DVO_RATE_SEL_SDR)); + +	WREG32(RADEON_DISP_OUTPUT_CNTL, (RADEON_DISP_DAC_SOURCE_RMX | +					 RADEON_DISP_TRANS_MATRIX_GRAPHICS)); + +	WREG32(RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_EN | +				       RADEON_CRTC2_DISP_REQ_EN_B)); + +	WREG32(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000); +	WREG32(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0); +	WREG32(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000); +	WREG32(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0); +	WREG32(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000); +	WREG32(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0); + +	WREG32(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008); +	WREG32(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800); +	WREG32(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001); +	WREG32(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080); + +	for (i = 0; i < 200; i++) { +		tmp = RREG32(RADEON_GPIO_MONID); +		if (tmp & RADEON_GPIO_Y_0) +			found = true; + +		if (found) +			break; + +		if (!drm_can_sleep()) +			mdelay(1); +		else +			msleep(1); +	} + +	/* restore the regs we used */ +	WREG32(RADEON_DISP_LIN_TRANS_GRPH_A, disp_lin_trans_grph_a); +	WREG32(RADEON_DISP_LIN_TRANS_GRPH_B, disp_lin_trans_grph_b); +	WREG32(RADEON_DISP_LIN_TRANS_GRPH_C, disp_lin_trans_grph_c); +	WREG32(RADEON_DISP_LIN_TRANS_GRPH_D, disp_lin_trans_grph_d); +	WREG32(RADEON_DISP_LIN_TRANS_GRPH_E, disp_lin_trans_grph_e); +	WREG32(RADEON_DISP_LIN_TRANS_GRPH_F, disp_lin_trans_grph_f); +	WREG32(RADEON_CRTC2_H_TOTAL_DISP, crtc2_h_total_disp); +	WREG32(RADEON_CRTC2_V_TOTAL_DISP, crtc2_v_total_disp); +	WREG32(RADEON_CRTC2_H_SYNC_STRT_WID, crtc2_h_sync_strt_wid); +	WREG32(RADEON_CRTC2_V_SYNC_STRT_WID, crtc2_v_sync_strt_wid); +	WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); +	WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); +	WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); +	WREG32(RADEON_GPIO_MONID, gpio_monid); + +	return found; +} +  static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder *encoder,  							     struct drm_connector *connector)  {  	struct drm_device *dev = encoder->dev;  	struct radeon_device *rdev = dev->dev_private; -	uint32_t crtc2_gen_cntl, tv_dac_cntl, dac_cntl2, dac_ext_cntl; -	uint32_t disp_hw_debug, disp_output_cntl, gpiopad_a, pixclks_cntl, tmp; +	uint32_t crtc2_gen_cntl = 0, tv_dac_cntl, dac_cntl2, dac_ext_cntl; +	uint32_t gpiopad_a = 0, pixclks_cntl, tmp; +	uint32_t disp_output_cntl = 0, disp_hw_debug = 0, crtc_ext_cntl = 0;  	enum drm_connector_status found = connector_status_disconnected;  	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);  	struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv; @@ -1456,12 +1556,27 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder  		return connector_status_disconnected;  	} +	/* R200 uses an external DAC for secondary DAC */ +	if (rdev->family == CHIP_R200) { +		if (radeon_legacy_ext_dac_detect(encoder, connector)) +			found = connector_status_connected; +		return found; +	} +  	/* save the regs we need */  	pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL); -	gpiopad_a = ASIC_IS_R300(rdev) ? RREG32(RADEON_GPIOPAD_A) : 0; -	disp_output_cntl = ASIC_IS_R300(rdev) ? RREG32(RADEON_DISP_OUTPUT_CNTL) : 0; -	disp_hw_debug = ASIC_IS_R300(rdev) ? 0 : RREG32(RADEON_DISP_HW_DEBUG); -	crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); + +	if (rdev->flags & RADEON_SINGLE_CRTC) { +		crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); +	} else { +		if (ASIC_IS_R300(rdev)) { +			gpiopad_a = RREG32(RADEON_GPIOPAD_A); +			disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL); +		} else { +			disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG); +		} +		crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); +	}  	tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);  	dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL);  	dac_cntl2 = RREG32(RADEON_DAC_CNTL2); @@ -1470,22 +1585,24 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder  			       | RADEON_PIX2CLK_DAC_ALWAYS_ONb);  	WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp); -	if (ASIC_IS_R300(rdev)) -		WREG32_P(RADEON_GPIOPAD_A, 1, ~1); - -	tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK; -	tmp |= RADEON_CRTC2_CRT2_ON | -		(2 << RADEON_CRTC2_PIX_WIDTH_SHIFT); - -	WREG32(RADEON_CRTC2_GEN_CNTL, tmp); - -	if (ASIC_IS_R300(rdev)) { -		tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK; -		tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2; -		WREG32(RADEON_DISP_OUTPUT_CNTL, tmp); +	if (rdev->flags & RADEON_SINGLE_CRTC) { +		tmp = crtc_ext_cntl | RADEON_CRTC_CRT_ON; +		WREG32(RADEON_CRTC_EXT_CNTL, tmp);  	} else { -		tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL; -		WREG32(RADEON_DISP_HW_DEBUG, tmp); +		tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK; +		tmp |= RADEON_CRTC2_CRT2_ON | +			(2 << RADEON_CRTC2_PIX_WIDTH_SHIFT); +		WREG32(RADEON_CRTC2_GEN_CNTL, tmp); + +		if (ASIC_IS_R300(rdev)) { +			WREG32_P(RADEON_GPIOPAD_A, 1, ~1); +			tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK; +			tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2; +			WREG32(RADEON_DISP_OUTPUT_CNTL, tmp); +		} else { +			tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL; +			WREG32(RADEON_DISP_HW_DEBUG, tmp); +		}  	}  	tmp = RADEON_TV_DAC_NBLANK | @@ -1527,14 +1644,19 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder  	WREG32(RADEON_DAC_CNTL2, dac_cntl2);  	WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl);  	WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl); -	WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); -	if (ASIC_IS_R300(rdev)) { -		WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); -		WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1); +	if (rdev->flags & RADEON_SINGLE_CRTC) { +		WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);  	} else { -		WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug); +		WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); +		if (ASIC_IS_R300(rdev)) { +			WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); +			WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1); +		} else { +			WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug); +		}  	} +  	WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);  	return found; diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 8b27dd6e314..b91118ccef8 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -105,7 +105,6 @@ int radeon_bo_create(struct radeon_device *rdev,  	struct radeon_bo *bo;  	enum ttm_bo_type type;  	unsigned long page_align = roundup(byte_align, PAGE_SIZE) >> PAGE_SHIFT; -	unsigned long max_size = 0;  	size_t acc_size;  	int r; @@ -121,18 +120,9 @@ int radeon_bo_create(struct radeon_device *rdev,  	}  	*bo_ptr = NULL; -	/* maximun bo size is the minimun btw visible vram and gtt size */ -	max_size = min(rdev->mc.visible_vram_size, rdev->mc.gtt_size); -	if ((page_align << PAGE_SHIFT) >= max_size) { -		printk(KERN_WARNING "%s:%d alloc size %ldM bigger than %ldMb limit\n", -			__func__, __LINE__, page_align  >> (20 - PAGE_SHIFT), max_size >> 20); -		return -ENOMEM; -	} -  	acc_size = ttm_bo_dma_acc_size(&rdev->mman.bdev, size,  				       sizeof(struct radeon_bo)); -retry:  	bo = kzalloc(sizeof(struct radeon_bo), GFP_KERNEL);  	if (bo == NULL)  		return -ENOMEM; @@ -154,15 +144,6 @@ retry:  			acc_size, sg, &radeon_ttm_bo_destroy);  	up_read(&rdev->pm.mclk_lock);  	if (unlikely(r != 0)) { -		if (r != -ERESTARTSYS) { -			if (domain == RADEON_GEM_DOMAIN_VRAM) { -				domain |= RADEON_GEM_DOMAIN_GTT; -				goto retry; -			} -			dev_err(rdev->dev, -				"object_init failed for (%lu, 0x%08X)\n", -				size, domain); -		}  		return r;  	}  	*bo_ptr = bo; diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index df8dd770164..b0db712060f 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -2808,26 +2808,31 @@ void si_vm_set_page(struct radeon_device *rdev, uint64_t pe,  {  	struct radeon_ring *ring = &rdev->ring[rdev->asic->vm.pt_ring_index];  	uint32_t r600_flags = cayman_vm_page_flags(rdev, flags); -	int i; -	uint64_t value; -	radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 2 + count * 2)); -	radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) | -				 WRITE_DATA_DST_SEL(1))); -	radeon_ring_write(ring, pe); -	radeon_ring_write(ring, upper_32_bits(pe)); -	for (i = 0; i < count; ++i) { -		if (flags & RADEON_VM_PAGE_SYSTEM) { -			value = radeon_vm_map_gart(rdev, addr); -			value &= 0xFFFFFFFFFFFFF000ULL; -		} else if (flags & RADEON_VM_PAGE_VALID) -			value = addr; -		else -			value = 0; -		addr += incr; -		value |= r600_flags; -		radeon_ring_write(ring, value); -		radeon_ring_write(ring, upper_32_bits(value)); +	while (count) { +		unsigned ndw = 2 + count * 2; +		if (ndw > 0x3FFE) +			ndw = 0x3FFE; + +		radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, ndw)); +		radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) | +					 WRITE_DATA_DST_SEL(1))); +		radeon_ring_write(ring, pe); +		radeon_ring_write(ring, upper_32_bits(pe)); +		for (; ndw > 2; ndw -= 2, --count, pe += 8) { +			uint64_t value; +			if (flags & RADEON_VM_PAGE_SYSTEM) { +				value = radeon_vm_map_gart(rdev, addr); +				value &= 0xFFFFFFFFFFFFF000ULL; +			} else if (flags & RADEON_VM_PAGE_VALID) +				value = addr; +			else +				value = 0; +			addr += incr; +			value |= r600_flags; +			radeon_ring_write(ring, value); +			radeon_ring_write(ring, upper_32_bits(value)); +		}  	}  } @@ -2868,6 +2873,10 @@ void si_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm)  	radeon_ring_write(ring, VM_INVALIDATE_REQUEST >> 2);  	radeon_ring_write(ring, 0);  	radeon_ring_write(ring, 1 << vm->id); + +	/* sync PFP to ME, otherwise we might get invalid PFP reads */ +	radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0)); +	radeon_ring_write(ring, 0x0);  }  /* diff --git a/drivers/gpu/drm/shmobile/shmob_drm_drv.c b/drivers/gpu/drm/shmobile/shmob_drm_drv.c index c71d493fd0c..1c350fc4e44 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_drv.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_drv.c @@ -201,6 +201,8 @@ static int shmob_drm_load(struct drm_device *dev, unsigned long flags)  		goto done;  	} +	platform_set_drvdata(pdev, sdev); +  done:  	if (ret)  		shmob_drm_unload(dev); @@ -299,11 +301,9 @@ static struct drm_driver shmob_drm_driver = {  #if CONFIG_PM_SLEEP  static int shmob_drm_pm_suspend(struct device *dev)  { -	struct platform_device *pdev = to_platform_device(dev); -	struct drm_device *ddev = platform_get_drvdata(pdev); -	struct shmob_drm_device *sdev = ddev->dev_private; +	struct shmob_drm_device *sdev = dev_get_drvdata(dev); -	drm_kms_helper_poll_disable(ddev); +	drm_kms_helper_poll_disable(sdev->ddev);  	shmob_drm_crtc_suspend(&sdev->crtc);  	return 0; @@ -311,9 +311,7 @@ static int shmob_drm_pm_suspend(struct device *dev)  static int shmob_drm_pm_resume(struct device *dev)  { -	struct platform_device *pdev = to_platform_device(dev); -	struct drm_device *ddev = platform_get_drvdata(pdev); -	struct shmob_drm_device *sdev = ddev->dev_private; +	struct shmob_drm_device *sdev = dev_get_drvdata(dev);  	mutex_lock(&sdev->ddev->mode_config.mutex);  	shmob_drm_crtc_resume(&sdev->crtc); diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 402ab69f9f9..bf6e4b5a73b 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -580,6 +580,7 @@ retry:  	if (unlikely(ret != 0))  		return ret; +retry_reserve:  	spin_lock(&glob->lru_lock);  	if (unlikely(list_empty(&bo->ddestroy))) { @@ -587,14 +588,20 @@ retry:  		return 0;  	} -	ret = ttm_bo_reserve_locked(bo, interruptible, -				    no_wait_reserve, false, 0); +	ret = ttm_bo_reserve_locked(bo, false, true, false, 0); -	if (unlikely(ret != 0)) { +	if (unlikely(ret == -EBUSY)) {  		spin_unlock(&glob->lru_lock); -		return ret; +		if (likely(!no_wait_reserve)) +			ret = ttm_bo_wait_unreserved(bo, interruptible); +		if (unlikely(ret != 0)) +			return ret; + +		goto retry_reserve;  	} +	BUG_ON(ret != 0); +  	/**  	 * We can re-check for sync object without taking  	 * the bo::lock since setting the sync object requires @@ -811,17 +818,14 @@ retry:  					  no_wait_reserve, no_wait_gpu);  		kref_put(&bo->list_kref, ttm_bo_release_list); -		if (likely(ret == 0 || ret == -ERESTARTSYS)) -			return ret; - -		goto retry; +		return ret;  	} -	ret = ttm_bo_reserve_locked(bo, false, no_wait_reserve, false, 0); +	ret = ttm_bo_reserve_locked(bo, false, true, false, 0);  	if (unlikely(ret == -EBUSY)) {  		spin_unlock(&glob->lru_lock); -		if (likely(!no_wait_gpu)) +		if (likely(!no_wait_reserve))  			ret = ttm_bo_wait_unreserved(bo, interruptible);  		kref_put(&bo->list_kref, ttm_bo_release_list); diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h index fccd361f7b5..87aa5f5d3c8 100644 --- a/drivers/gpu/drm/udl/udl_drv.h +++ b/drivers/gpu/drm/udl/udl_drv.h @@ -104,7 +104,7 @@ udl_fb_user_fb_create(struct drm_device *dev,  int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr,  		     const char *front, char **urb_buf_ptr, -		     u32 byte_offset, u32 byte_width, +		     u32 byte_offset, u32 device_byte_offset, u32 byte_width,  		     int *ident_ptr, int *sent_ptr);  int udl_dumb_create(struct drm_file *file_priv, diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c index 69a2b16f42a..d4ab3beaada 100644 --- a/drivers/gpu/drm/udl/udl_fb.c +++ b/drivers/gpu/drm/udl/udl_fb.c @@ -114,9 +114,10 @@ static void udlfb_dpy_deferred_io(struct fb_info *info,  	list_for_each_entry(cur, &fbdefio->pagelist, lru) {  		if (udl_render_hline(dev, (ufbdev->ufb.base.bits_per_pixel / 8), -				  &urb, (char *) info->fix.smem_start, -				  &cmd, cur->index << PAGE_SHIFT, -				  PAGE_SIZE, &bytes_identical, &bytes_sent)) +				     &urb, (char *) info->fix.smem_start, +				     &cmd, cur->index << PAGE_SHIFT, +				     cur->index << PAGE_SHIFT, +				     PAGE_SIZE, &bytes_identical, &bytes_sent))  			goto error;  		bytes_rendered += PAGE_SIZE;  	} @@ -187,10 +188,11 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y,  	for (i = y; i < y + height ; i++) {  		const int line_offset = fb->base.pitches[0] * i;  		const int byte_offset = line_offset + (x * bpp); - +		const int dev_byte_offset = (fb->base.width * bpp * i) + (x * bpp);  		if (udl_render_hline(dev, bpp, &urb,  				     (char *) fb->obj->vmapping, -				     &cmd, byte_offset, width * bpp, +				     &cmd, byte_offset, dev_byte_offset, +				     width * bpp,  				     &bytes_identical, &bytes_sent))  			goto error;  	} diff --git a/drivers/gpu/drm/udl/udl_transfer.c b/drivers/gpu/drm/udl/udl_transfer.c index dc095526ffb..142fee5f983 100644 --- a/drivers/gpu/drm/udl/udl_transfer.c +++ b/drivers/gpu/drm/udl/udl_transfer.c @@ -213,11 +213,12 @@ static void udl_compress_hline16(   */  int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr,  		     const char *front, char **urb_buf_ptr, -		     u32 byte_offset, u32 byte_width, +		     u32 byte_offset, u32 device_byte_offset, +		     u32 byte_width,  		     int *ident_ptr, int *sent_ptr)  {  	const u8 *line_start, *line_end, *next_pixel; -	u32 base16 = 0 + (byte_offset / bpp) * 2; +	u32 base16 = 0 + (device_byte_offset / bpp) * 2;  	struct urb *urb = *urb_ptr;  	u8 *cmd = *urb_buf_ptr;  	u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length;  |