diff options
| -rw-r--r-- | drivers/gpu/drm/drm_crtc.c | 5 | ||||
| -rw-r--r-- | drivers/gpu/drm/drm_crtc_helper.c | 27 | ||||
| -rw-r--r-- | drivers/gpu/drm/drm_drv.c | 20 | ||||
| -rw-r--r-- | drivers/gpu/drm/drm_encoder_slave.c | 6 | ||||
| -rw-r--r-- | drivers/gpu/drm/drm_mm.c | 34 | ||||
| -rw-r--r-- | drivers/gpu/drm/drm_modes.c | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 8 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_gem_gtt.c | 15 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_ddi.c | 5 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 77 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_fb.c | 16 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_pm.c | 44 | ||||
| -rw-r--r-- | drivers/gpu/drm/mgag200/mgag200_mode.c | 90 | ||||
| -rw-r--r-- | include/drm/drmP.h | 3 | ||||
| -rw-r--r-- | include/drm/drm_fb_helper.h | 15 | 
17 files changed, 213 insertions, 156 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 3a8f7e6db29..e7e92429d10 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -78,6 +78,10 @@ void drm_warn_on_modeset_not_all_locked(struct drm_device *dev)  {  	struct drm_crtc *crtc; +	/* Locking is currently fubar in the panic handler. */ +	if (oops_in_progress) +		return; +  	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)  		WARN_ON(!mutex_is_locked(&crtc->mutex)); @@ -246,6 +250,7 @@ char *drm_get_connector_status_name(enum drm_connector_status status)  	else  		return "unknown";  } +EXPORT_SYMBOL(drm_get_connector_status_name);  /**   * drm_mode_object_get - allocate a new modeset identifier diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index e974f9309b7..ed1334e27c3 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -121,6 +121,7 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,  		connector->helper_private;  	int count = 0;  	int mode_flags = 0; +	bool verbose_prune = true;  	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id,  			drm_get_connector_name(connector)); @@ -149,6 +150,7 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,  		DRM_DEBUG_KMS("[CONNECTOR:%d:%s] disconnected\n",  			connector->base.id, drm_get_connector_name(connector));  		drm_mode_connector_update_edid_property(connector, NULL); +		verbose_prune = false;  		goto prune;  	} @@ -182,7 +184,7 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,  	}  prune: -	drm_mode_prune_invalid(dev, &connector->modes, true); +	drm_mode_prune_invalid(dev, &connector->modes, verbose_prune);  	if (list_empty(&connector->modes))  		return 0; @@ -1005,12 +1007,20 @@ static void output_poll_execute(struct work_struct *work)  			continue;  		connector->status = connector->funcs->detect(connector, false); -		DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %d to %d\n", -			      connector->base.id, -			      drm_get_connector_name(connector), -			      old_status, connector->status); -		if (old_status != connector->status) +		if (old_status != connector->status) { +			const char *old, *new; + +			old = drm_get_connector_status_name(old_status); +			new = drm_get_connector_status_name(connector->status); + +			DRM_DEBUG_KMS("[CONNECTOR:%d:%s] " +				      "status updated from %s to %s\n", +				      connector->base.id, +				      drm_get_connector_name(connector), +				      old, new); +  			changed = true; +		}  	}  	mutex_unlock(&dev->mode_config.mutex); @@ -1083,10 +1093,11 @@ void drm_helper_hpd_irq_event(struct drm_device *dev)  		old_status = connector->status;  		connector->status = connector->funcs->detect(connector, false); -		DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %d to %d\n", +		DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n",  			      connector->base.id,  			      drm_get_connector_name(connector), -			      old_status, connector->status); +			      drm_get_connector_status_name(old_status), +			      drm_get_connector_status_name(connector->status));  		if (old_status != connector->status)  			changed = true;  	} diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 8d4f29075af..9cc247f5550 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -57,7 +57,7 @@ static int drm_version(struct drm_device *dev, void *data,  		       struct drm_file *file_priv);  #define DRM_IOCTL_DEF(ioctl, _func, _flags) \ -	[DRM_IOCTL_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, .cmd_drv = 0} +	[DRM_IOCTL_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, .cmd_drv = 0, .name = #ioctl}  /** Ioctl table */  static const struct drm_ioctl_desc drm_ioctls[] = { @@ -375,7 +375,7 @@ long drm_ioctl(struct file *filp,  {  	struct drm_file *file_priv = filp->private_data;  	struct drm_device *dev; -	const struct drm_ioctl_desc *ioctl; +	const struct drm_ioctl_desc *ioctl = NULL;  	drm_ioctl_t *func;  	unsigned int nr = DRM_IOCTL_NR(cmd);  	int retcode = -EINVAL; @@ -392,11 +392,6 @@ long drm_ioctl(struct file *filp,  	atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]);  	++file_priv->ioctl_count; -	DRM_DEBUG("pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%lx, auth=%d\n", -		  task_pid_nr(current), cmd, nr, -		  (long)old_encode_dev(file_priv->minor->device), -		  file_priv->authenticated); -  	if ((nr >= DRM_CORE_IOCTL_COUNT) &&  	    ((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END)))  		goto err_i1; @@ -417,6 +412,11 @@ long drm_ioctl(struct file *filp,  	} else  		goto err_i1; +	DRM_DEBUG("pid=%d, dev=0x%lx, auth=%d, %s\n", +		  task_pid_nr(current), +		  (long)old_encode_dev(file_priv->minor->device), +		  file_priv->authenticated, ioctl->name); +  	/* Do not trust userspace, use our own definition */  	func = ioctl->func;  	/* is there a local override? */ @@ -471,6 +471,12 @@ long drm_ioctl(struct file *filp,  	}        err_i1: +	if (!ioctl) +		DRM_DEBUG("invalid iotcl: pid=%d, dev=0x%lx, auth=%d, cmd=0x%02x, nr=0x%02x\n", +			  task_pid_nr(current), +			  (long)old_encode_dev(file_priv->minor->device), +			  file_priv->authenticated, cmd, nr); +  	if (kdata != stack_kdata)  		kfree(kdata);  	atomic_dec(&dev->ioctl_count); diff --git a/drivers/gpu/drm/drm_encoder_slave.c b/drivers/gpu/drm/drm_encoder_slave.c index 48c52f7df4e..0cfb60f5476 100644 --- a/drivers/gpu/drm/drm_encoder_slave.c +++ b/drivers/gpu/drm/drm_encoder_slave.c @@ -54,16 +54,12 @@ int drm_i2c_encoder_init(struct drm_device *dev,  			 struct i2c_adapter *adap,  			 const struct i2c_board_info *info)  { -	char modalias[sizeof(I2C_MODULE_PREFIX) -		      + I2C_NAME_SIZE];  	struct module *module = NULL;  	struct i2c_client *client;  	struct drm_i2c_encoder_driver *encoder_drv;  	int err = 0; -	snprintf(modalias, sizeof(modalias), -		 "%s%s", I2C_MODULE_PREFIX, info->type); -	request_module(modalias); +	request_module("%s%s", I2C_MODULE_PREFIX, info->type);  	client = i2c_new_device(adap, info);  	if (!client) { diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index db1e2d6f90d..07cf99cc886 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -755,33 +755,35 @@ void drm_mm_debug_table(struct drm_mm *mm, const char *prefix)  EXPORT_SYMBOL(drm_mm_debug_table);  #if defined(CONFIG_DEBUG_FS) -int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm) +static unsigned long drm_mm_dump_hole(struct seq_file *m, struct drm_mm_node *entry)  { -	struct drm_mm_node *entry; -	unsigned long total_used = 0, total_free = 0, total = 0;  	unsigned long hole_start, hole_end, hole_size; -	hole_start = drm_mm_hole_node_start(&mm->head_node); -	hole_end = drm_mm_hole_node_end(&mm->head_node); -	hole_size = hole_end - hole_start; -	if (hole_size) +	if (entry->hole_follows) { +		hole_start = drm_mm_hole_node_start(entry); +		hole_end = drm_mm_hole_node_end(entry); +		hole_size = hole_end - hole_start;  		seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: free\n",  				hole_start, hole_end, hole_size); -	total_free += hole_size; +		return hole_size; +	} + +	return 0; +} + +int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm) +{ +	struct drm_mm_node *entry; +	unsigned long total_used = 0, total_free = 0, total = 0; + +	total_free += drm_mm_dump_hole(m, &mm->head_node);  	drm_mm_for_each_node(entry, mm) {  		seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: used\n",  				entry->start, entry->start + entry->size,  				entry->size);  		total_used += entry->size; -		if (entry->hole_follows) { -			hole_start = drm_mm_hole_node_start(entry); -			hole_end = drm_mm_hole_node_end(entry); -			hole_size = hole_end - hole_start; -			seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: free\n", -					hole_start, hole_end, hole_size); -			total_free += hole_size; -		} +		total_free += drm_mm_dump_hole(m, entry);  	}  	total = total_free + total_used; diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index faa79df0264..a371ff865a8 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -1143,6 +1143,7 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,  				was_digit = false;  			} else  				goto done; +			break;  		case '0' ... '9':  			was_digit = true;  			break; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 6be940effef..6165535d15f 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1045,6 +1045,8 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,  	if (timeout) {  		struct timespec sleep_time = timespec_sub(now, before);  		*timeout = timespec_sub(*timeout, sleep_time); +		if (!timespec_valid(timeout)) /* i.e. negative time remains */ +			set_normalized_timespec(timeout, 0, 0);  	}  	switch (end) { @@ -1053,8 +1055,6 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,  	case -ERESTARTSYS: /* Signal */  		return (int)end;  	case 0: /* Timeout */ -		if (timeout) -			set_normalized_timespec(timeout, 0, 0);  		return -ETIME;  	default: /* Completed */  		WARN_ON(end < 0); /* We're not aware of other errors */ @@ -2377,10 +2377,8 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file)  	mutex_unlock(&dev->struct_mutex);  	ret = __wait_seqno(ring, seqno, reset_counter, true, timeout); -	if (timeout) { -		WARN_ON(!timespec_valid(timeout)); +	if (timeout)  		args->timeout_ns = timespec_to_ns(timeout); -	}  	return ret;  out: diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index dca614de71b..bdb0d7717bc 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -709,15 +709,6 @@ static inline size_t gen6_get_stolen_size(u16 snb_gmch_ctl)  	return snb_gmch_ctl << 25; /* 32 MB units */  } -static inline size_t gen7_get_stolen_size(u16 snb_gmch_ctl) -{ -	static const int stolen_decoder[] = { -		0, 0, 0, 0, 0, 32, 48, 64, 128, 256, 96, 160, 224, 352}; -	snb_gmch_ctl >>= IVB_GMCH_GMS_SHIFT; -	snb_gmch_ctl &= IVB_GMCH_GMS_MASK; -	return stolen_decoder[snb_gmch_ctl] << 20; -} -  static int gen6_gmch_probe(struct drm_device *dev,  			   size_t *gtt_total,  			   size_t *stolen, @@ -747,11 +738,7 @@ static int gen6_gmch_probe(struct drm_device *dev,  	pci_read_config_word(dev->pdev, SNB_GMCH_CTRL, &snb_gmch_ctl);  	gtt_size = gen6_get_total_gtt_size(snb_gmch_ctl); -	if (IS_GEN7(dev) && !IS_VALLEYVIEW(dev)) -		*stolen = gen7_get_stolen_size(snb_gmch_ctl); -	else -		*stolen = gen6_get_stolen_size(snb_gmch_ctl); - +	*stolen = gen6_get_stolen_size(snb_gmch_ctl);  	*gtt_total = (gtt_size / sizeof(gen6_gtt_pte_t)) << PAGE_SHIFT;  	/* For Modern GENs the PTEs and register space are split in the BAR */ diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 83f9c26e1ad..2d6b62e42da 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -46,8 +46,6 @@  #define    SNB_GMCH_GGMS_MASK	0x3  #define    SNB_GMCH_GMS_SHIFT   3 /* Graphics Mode Select */  #define    SNB_GMCH_GMS_MASK    0x1f -#define    IVB_GMCH_GMS_SHIFT   4 -#define    IVB_GMCH_GMS_MASK    0xf  /* PCI config space */ diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 26a0a570f92..fb961bb8190 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1265,6 +1265,8 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)  		intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);  		intel_dp_start_link_train(intel_dp);  		intel_dp_complete_link_train(intel_dp); +		if (port != PORT_A) +			intel_dp_stop_link_train(intel_dp);  	}  } @@ -1326,6 +1328,9 @@ static void intel_enable_ddi(struct intel_encoder *intel_encoder)  	} else if (type == INTEL_OUTPUT_EDP) {  		struct intel_dp *intel_dp = enc_to_intel_dp(encoder); +		if (port == PORT_A) +			intel_dp_stop_link_train(intel_dp); +  		ironlake_edp_backlight_on(intel_dp);  	} diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index fb2fbc1e08b..3d704b706a8 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -702,6 +702,9 @@ intel_dp_compute_config(struct intel_encoder *encoder,  	/* Walk through all bpp values. Luckily they're all nicely spaced with 2  	 * bpc in between. */  	bpp = min_t(int, 8*3, pipe_config->pipe_bpp); +	if (is_edp(intel_dp) && dev_priv->edp.bpp) +		bpp = min_t(int, bpp, dev_priv->edp.bpp); +  	for (; bpp >= 6*3; bpp -= 2*3) {  		mode_rate = intel_dp_link_required(target_clock, bpp); @@ -739,6 +742,7 @@ found:  	intel_dp->link_bw = bws[clock];  	intel_dp->lane_count = lane_count;  	adjusted_mode->clock = drm_dp_bw_code_to_link_rate(intel_dp->link_bw); +	pipe_config->pipe_bpp = bpp;  	pipe_config->pixel_target_clock = target_clock;  	DRM_DEBUG_KMS("DP link bw %02x lane count %d clock %d bpp %d\n", @@ -751,20 +755,6 @@ found:  			       target_clock, adjusted_mode->clock,  			       &pipe_config->dp_m_n); -	/* -	 * XXX: We have a strange regression where using the vbt edp bpp value -	 * for the link bw computation results in black screens, the panel only -	 * works when we do the computation at the usual 24bpp (but still -	 * requires us to use 18bpp). Until that's fully debugged, stay -	 * bug-for-bug compatible with the old code. -	 */ -	if (is_edp(intel_dp) && dev_priv->edp.bpp) { -		DRM_DEBUG_KMS("clamping display bpc (was %d) to eDP (%d)\n", -			      bpp, dev_priv->edp.bpp); -		bpp = min_t(int, bpp, dev_priv->edp.bpp); -	} -	pipe_config->pipe_bpp = bpp; -  	return true;  } @@ -1389,6 +1379,7 @@ static void intel_enable_dp(struct intel_encoder *encoder)  	ironlake_edp_panel_on(intel_dp);  	ironlake_edp_panel_vdd_off(intel_dp, true);  	intel_dp_complete_link_train(intel_dp); +	intel_dp_stop_link_train(intel_dp);  	ironlake_edp_backlight_on(intel_dp);  } @@ -1711,10 +1702,9 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,  	struct drm_i915_private *dev_priv = dev->dev_private;  	enum port port = intel_dig_port->port;  	int ret; -	uint32_t temp;  	if (HAS_DDI(dev)) { -		temp = I915_READ(DP_TP_CTL(port)); +		uint32_t temp = I915_READ(DP_TP_CTL(port));  		if (dp_train_pat & DP_LINK_SCRAMBLING_DISABLE)  			temp |= DP_TP_CTL_SCRAMBLE_DISABLE; @@ -1724,18 +1714,6 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,  		temp &= ~DP_TP_CTL_LINK_TRAIN_MASK;  		switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {  		case DP_TRAINING_PATTERN_DISABLE: - -			if (port != PORT_A) { -				temp |= DP_TP_CTL_LINK_TRAIN_IDLE; -				I915_WRITE(DP_TP_CTL(port), temp); - -				if (wait_for((I915_READ(DP_TP_STATUS(port)) & -					      DP_TP_STATUS_IDLE_DONE), 1)) -					DRM_ERROR("Timed out waiting for DP idle patterns\n"); - -				temp &= ~DP_TP_CTL_LINK_TRAIN_MASK; -			} -  			temp |= DP_TP_CTL_LINK_TRAIN_NORMAL;  			break; @@ -1811,6 +1789,37 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,  	return true;  } +static void intel_dp_set_idle_link_train(struct intel_dp *intel_dp) +{ +	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); +	struct drm_device *dev = intel_dig_port->base.base.dev; +	struct drm_i915_private *dev_priv = dev->dev_private; +	enum port port = intel_dig_port->port; +	uint32_t val; + +	if (!HAS_DDI(dev)) +		return; + +	val = I915_READ(DP_TP_CTL(port)); +	val &= ~DP_TP_CTL_LINK_TRAIN_MASK; +	val |= DP_TP_CTL_LINK_TRAIN_IDLE; +	I915_WRITE(DP_TP_CTL(port), val); + +	/* +	 * On PORT_A we can have only eDP in SST mode. There the only reason +	 * we need to set idle transmission mode is to work around a HW issue +	 * where we enable the pipe while not in idle link-training mode. +	 * In this case there is requirement to wait for a minimum number of +	 * idle patterns to be sent. +	 */ +	if (port == PORT_A) +		return; + +	if (wait_for((I915_READ(DP_TP_STATUS(port)) & DP_TP_STATUS_IDLE_DONE), +		     1)) +		DRM_ERROR("Timed out waiting for DP idle patterns\n"); +} +  /* Enable corresponding port and start training pattern 1 */  void  intel_dp_start_link_train(struct intel_dp *intel_dp) @@ -1953,10 +1962,19 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)  		++tries;  	} +	intel_dp_set_idle_link_train(intel_dp); + +	intel_dp->DP = DP; +  	if (channel_eq)  		DRM_DEBUG_KMS("Channel EQ done. DP Training successful\n"); -	intel_dp_set_link_train(intel_dp, DP, DP_TRAINING_PATTERN_DISABLE); +} + +void intel_dp_stop_link_train(struct intel_dp *intel_dp) +{ +	intel_dp_set_link_train(intel_dp, intel_dp->DP, +				DP_TRAINING_PATTERN_DISABLE);  }  static void @@ -2164,6 +2182,7 @@ intel_dp_check_link_status(struct intel_dp *intel_dp)  			      drm_get_encoder_name(&intel_encoder->base));  		intel_dp_start_link_train(intel_dp);  		intel_dp_complete_link_train(intel_dp); +		intel_dp_stop_link_train(intel_dp);  	}  } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index b5b6d19e6dd..624a9e6b8d7 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -499,6 +499,7 @@ extern void intel_dp_init_connector(struct intel_digital_port *intel_dig_port,  extern void intel_dp_init_link_config(struct intel_dp *intel_dp);  extern void intel_dp_start_link_train(struct intel_dp *intel_dp);  extern void intel_dp_complete_link_train(struct intel_dp *intel_dp); +extern void intel_dp_stop_link_train(struct intel_dp *intel_dp);  extern void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode);  extern void intel_dp_encoder_destroy(struct drm_encoder *encoder);  extern void intel_dp_check_link_status(struct intel_dp *intel_dp); diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c index 0e19e575a1b..6b7c3ca2c03 100644 --- a/drivers/gpu/drm/i915/intel_fb.c +++ b/drivers/gpu/drm/i915/intel_fb.c @@ -262,10 +262,22 @@ void intel_fbdev_fini(struct drm_device *dev)  void intel_fbdev_set_suspend(struct drm_device *dev, int state)  {  	drm_i915_private_t *dev_priv = dev->dev_private; -	if (!dev_priv->fbdev) +	struct intel_fbdev *ifbdev = dev_priv->fbdev; +	struct fb_info *info; + +	if (!ifbdev)  		return; -	fb_set_suspend(dev_priv->fbdev->helper.fbdev, state); +	info = ifbdev->helper.fbdev; + +	/* On resume from hibernation: If the object is shmemfs backed, it has +	 * been restored from swap. If the object is stolen however, it will be +	 * full of whatever garbage was left in there. +	 */ +	if (!state && ifbdev->ifb.obj->stolen) +		memset_io(info->screen_base, 0, info->screen_size); + +	fb_set_suspend(info, state);  }  MODULE_LICENSE("GPL and additional rights"); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index de3b0dc5658..aa01128ff19 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -1301,17 +1301,17 @@ static void valleyview_update_wm(struct drm_device *dev)  	vlv_update_drain_latency(dev); -	if (g4x_compute_wm0(dev, 0, +	if (g4x_compute_wm0(dev, PIPE_A,  			    &valleyview_wm_info, latency_ns,  			    &valleyview_cursor_wm_info, latency_ns,  			    &planea_wm, &cursora_wm)) -		enabled |= 1; +		enabled |= 1 << PIPE_A; -	if (g4x_compute_wm0(dev, 1, +	if (g4x_compute_wm0(dev, PIPE_B,  			    &valleyview_wm_info, latency_ns,  			    &valleyview_cursor_wm_info, latency_ns,  			    &planeb_wm, &cursorb_wm)) -		enabled |= 2; +		enabled |= 1 << PIPE_B;  	if (single_plane_enabled(enabled) &&  	    g4x_compute_srwm(dev, ffs(enabled) - 1, @@ -1357,17 +1357,17 @@ static void g4x_update_wm(struct drm_device *dev)  	int plane_sr, cursor_sr;  	unsigned int enabled = 0; -	if (g4x_compute_wm0(dev, 0, +	if (g4x_compute_wm0(dev, PIPE_A,  			    &g4x_wm_info, latency_ns,  			    &g4x_cursor_wm_info, latency_ns,  			    &planea_wm, &cursora_wm)) -		enabled |= 1; +		enabled |= 1 << PIPE_A; -	if (g4x_compute_wm0(dev, 1, +	if (g4x_compute_wm0(dev, PIPE_B,  			    &g4x_wm_info, latency_ns,  			    &g4x_cursor_wm_info, latency_ns,  			    &planeb_wm, &cursorb_wm)) -		enabled |= 2; +		enabled |= 1 << PIPE_B;  	if (single_plane_enabled(enabled) &&  	    g4x_compute_srwm(dev, ffs(enabled) - 1, @@ -1716,7 +1716,7 @@ static void ironlake_update_wm(struct drm_device *dev)  	unsigned int enabled;  	enabled = 0; -	if (g4x_compute_wm0(dev, 0, +	if (g4x_compute_wm0(dev, PIPE_A,  			    &ironlake_display_wm_info,  			    ILK_LP0_PLANE_LATENCY,  			    &ironlake_cursor_wm_info, @@ -1727,10 +1727,10 @@ static void ironlake_update_wm(struct drm_device *dev)  		DRM_DEBUG_KMS("FIFO watermarks For pipe A -"  			      " plane %d, " "cursor: %d\n",  			      plane_wm, cursor_wm); -		enabled |= 1; +		enabled |= 1 << PIPE_A;  	} -	if (g4x_compute_wm0(dev, 1, +	if (g4x_compute_wm0(dev, PIPE_B,  			    &ironlake_display_wm_info,  			    ILK_LP0_PLANE_LATENCY,  			    &ironlake_cursor_wm_info, @@ -1741,7 +1741,7 @@ static void ironlake_update_wm(struct drm_device *dev)  		DRM_DEBUG_KMS("FIFO watermarks For pipe B -"  			      " plane %d, cursor: %d\n",  			      plane_wm, cursor_wm); -		enabled |= 2; +		enabled |= 1 << PIPE_B;  	}  	/* @@ -1801,7 +1801,7 @@ static void sandybridge_update_wm(struct drm_device *dev)  	unsigned int enabled;  	enabled = 0; -	if (g4x_compute_wm0(dev, 0, +	if (g4x_compute_wm0(dev, PIPE_A,  			    &sandybridge_display_wm_info, latency,  			    &sandybridge_cursor_wm_info, latency,  			    &plane_wm, &cursor_wm)) { @@ -1812,10 +1812,10 @@ static void sandybridge_update_wm(struct drm_device *dev)  		DRM_DEBUG_KMS("FIFO watermarks For pipe A -"  			      " plane %d, " "cursor: %d\n",  			      plane_wm, cursor_wm); -		enabled |= 1; +		enabled |= 1 << PIPE_A;  	} -	if (g4x_compute_wm0(dev, 1, +	if (g4x_compute_wm0(dev, PIPE_B,  			    &sandybridge_display_wm_info, latency,  			    &sandybridge_cursor_wm_info, latency,  			    &plane_wm, &cursor_wm)) { @@ -1826,7 +1826,7 @@ static void sandybridge_update_wm(struct drm_device *dev)  		DRM_DEBUG_KMS("FIFO watermarks For pipe B -"  			      " plane %d, cursor: %d\n",  			      plane_wm, cursor_wm); -		enabled |= 2; +		enabled |= 1 << PIPE_B;  	}  	/* @@ -1904,7 +1904,7 @@ static void ivybridge_update_wm(struct drm_device *dev)  	unsigned int enabled;  	enabled = 0; -	if (g4x_compute_wm0(dev, 0, +	if (g4x_compute_wm0(dev, PIPE_A,  			    &sandybridge_display_wm_info, latency,  			    &sandybridge_cursor_wm_info, latency,  			    &plane_wm, &cursor_wm)) { @@ -1915,10 +1915,10 @@ static void ivybridge_update_wm(struct drm_device *dev)  		DRM_DEBUG_KMS("FIFO watermarks For pipe A -"  			      " plane %d, " "cursor: %d\n",  			      plane_wm, cursor_wm); -		enabled |= 1; +		enabled |= 1 << PIPE_A;  	} -	if (g4x_compute_wm0(dev, 1, +	if (g4x_compute_wm0(dev, PIPE_B,  			    &sandybridge_display_wm_info, latency,  			    &sandybridge_cursor_wm_info, latency,  			    &plane_wm, &cursor_wm)) { @@ -1929,10 +1929,10 @@ static void ivybridge_update_wm(struct drm_device *dev)  		DRM_DEBUG_KMS("FIFO watermarks For pipe B -"  			      " plane %d, cursor: %d\n",  			      plane_wm, cursor_wm); -		enabled |= 2; +		enabled |= 1 << PIPE_B;  	} -	if (g4x_compute_wm0(dev, 2, +	if (g4x_compute_wm0(dev, PIPE_C,  			    &sandybridge_display_wm_info, latency,  			    &sandybridge_cursor_wm_info, latency,  			    &plane_wm, &cursor_wm)) { @@ -1943,7 +1943,7 @@ static void ivybridge_update_wm(struct drm_device *dev)  		DRM_DEBUG_KMS("FIFO watermarks For pipe C -"  			      " plane %d, cursor: %d\n",  			      plane_wm, cursor_wm); -		enabled |= 3; +		enabled |= 1 << PIPE_C;  	}  	/* diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index f9889658329..77b8a45fb10 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -46,29 +46,26 @@ static void mga_crtc_load_lut(struct drm_crtc *crtc)  static inline void mga_wait_vsync(struct mga_device *mdev)  { -	unsigned int count = 0; +	unsigned long timeout = jiffies + HZ/10;  	unsigned int status = 0;  	do {  		status = RREG32(MGAREG_Status); -		count++; -	} while ((status & 0x08) && (count < 250000)); -	count = 0; +	} while ((status & 0x08) && time_before(jiffies, timeout)); +	timeout = jiffies + HZ/10;  	status = 0;  	do {  		status = RREG32(MGAREG_Status); -		count++; -	} while (!(status & 0x08) && (count < 250000)); +	} while (!(status & 0x08) && time_before(jiffies, timeout));  }  static inline void mga_wait_busy(struct mga_device *mdev)  { -	unsigned int count = 0; +	unsigned long timeout = jiffies + HZ;  	unsigned int status = 0;  	do {  		status = RREG8(MGAREG_Status + 2); -		count++; -	} while ((status & 0x01) && (count < 500000)); +	} while ((status & 0x01) && time_before(jiffies, timeout));  }  /* @@ -189,12 +186,12 @@ static int mga_g200wb_set_plls(struct mga_device *mdev, long clock)  		WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);  		tmp = RREG8(DAC_DATA);  		tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; -		WREG_DAC(MGA1064_PIX_CLK_CTL_CLK_DIS, tmp); +		WREG8(DAC_DATA, tmp);  		WREG8(DAC_INDEX, MGA1064_REMHEADCTL);  		tmp = RREG8(DAC_DATA);  		tmp |= MGA1064_REMHEADCTL_CLKDIS; -		WREG_DAC(MGA1064_REMHEADCTL, tmp); +		WREG8(DAC_DATA, tmp);  		/* select PLL Set C */  		tmp = RREG8(MGAREG_MEM_MISC_READ); @@ -204,7 +201,7 @@ static int mga_g200wb_set_plls(struct mga_device *mdev, long clock)  		WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);  		tmp = RREG8(DAC_DATA);  		tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN | 0x80; -		WREG_DAC(MGA1064_PIX_CLK_CTL, tmp); +		WREG8(DAC_DATA, tmp);  		udelay(500); @@ -212,7 +209,7 @@ static int mga_g200wb_set_plls(struct mga_device *mdev, long clock)  		WREG8(DAC_INDEX, MGA1064_VREF_CTL);  		tmp = RREG8(DAC_DATA);  		tmp &= ~0x04; -		WREG_DAC(MGA1064_VREF_CTL, tmp); +		WREG8(DAC_DATA, tmp);  		udelay(50); @@ -236,13 +233,13 @@ static int mga_g200wb_set_plls(struct mga_device *mdev, long clock)  		tmp = RREG8(DAC_DATA);  		tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;  		tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL; -		WREG_DAC(MGA1064_PIX_CLK_CTL, tmp); +		WREG8(DAC_DATA, tmp);  		WREG8(DAC_INDEX, MGA1064_REMHEADCTL);  		tmp = RREG8(DAC_DATA);  		tmp &= ~MGA1064_REMHEADCTL_CLKSL_MSK;  		tmp |= MGA1064_REMHEADCTL_CLKSL_PLL; -		WREG_DAC(MGA1064_REMHEADCTL, tmp); +		WREG8(DAC_DATA, tmp);  		/* reset dotclock rate bit */  		WREG8(MGAREG_SEQ_INDEX, 1); @@ -253,7 +250,7 @@ static int mga_g200wb_set_plls(struct mga_device *mdev, long clock)  		WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);  		tmp = RREG8(DAC_DATA);  		tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; -		WREG_DAC(MGA1064_PIX_CLK_CTL, tmp); +		WREG8(DAC_DATA, tmp);  		vcount = RREG8(MGAREG_VCOUNT); @@ -318,7 +315,7 @@ static int mga_g200ev_set_plls(struct mga_device *mdev, long clock)  	WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);  	tmp = RREG8(DAC_DATA);  	tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; -	WREG_DAC(MGA1064_PIX_CLK_CTL_CLK_DIS, tmp); +	WREG8(DAC_DATA, tmp);  	tmp = RREG8(MGAREG_MEM_MISC_READ);  	tmp |= 0x3 << 2; @@ -326,12 +323,12 @@ static int mga_g200ev_set_plls(struct mga_device *mdev, long clock)  	WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT);  	tmp = RREG8(DAC_DATA); -	WREG_DAC(MGA1064_PIX_PLL_STAT, tmp & ~0x40); +	WREG8(DAC_DATA, tmp & ~0x40);  	WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);  	tmp = RREG8(DAC_DATA);  	tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; -	WREG_DAC(MGA1064_PIX_CLK_CTL, tmp); +	WREG8(DAC_DATA, tmp);  	WREG_DAC(MGA1064_EV_PIX_PLLC_M, m);  	WREG_DAC(MGA1064_EV_PIX_PLLC_N, n); @@ -342,7 +339,7 @@ static int mga_g200ev_set_plls(struct mga_device *mdev, long clock)  	WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);  	tmp = RREG8(DAC_DATA);  	tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; -	WREG_DAC(MGA1064_PIX_CLK_CTL, tmp); +	WREG8(DAC_DATA, tmp);  	udelay(500); @@ -350,11 +347,11 @@ static int mga_g200ev_set_plls(struct mga_device *mdev, long clock)  	tmp = RREG8(DAC_DATA);  	tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;  	tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL; -	WREG_DAC(MGA1064_PIX_CLK_CTL, tmp); +	WREG8(DAC_DATA, tmp);  	WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT);  	tmp = RREG8(DAC_DATA); -	WREG_DAC(MGA1064_PIX_PLL_STAT, tmp | 0x40); +	WREG8(DAC_DATA, tmp | 0x40);  	tmp = RREG8(MGAREG_MEM_MISC_READ);  	tmp |= (0x3 << 2); @@ -363,7 +360,7 @@ static int mga_g200ev_set_plls(struct mga_device *mdev, long clock)  	WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);  	tmp = RREG8(DAC_DATA);  	tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; -	WREG_DAC(MGA1064_PIX_CLK_CTL, tmp); +	WREG8(DAC_DATA, tmp);  	return 0;  } @@ -416,7 +413,7 @@ static int mga_g200eh_set_plls(struct mga_device *mdev, long clock)  		WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);  		tmp = RREG8(DAC_DATA);  		tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; -		WREG_DAC(MGA1064_PIX_CLK_CTL_CLK_DIS, tmp); +		WREG8(DAC_DATA, tmp);  		tmp = RREG8(MGAREG_MEM_MISC_READ);  		tmp |= 0x3 << 2; @@ -425,7 +422,7 @@ static int mga_g200eh_set_plls(struct mga_device *mdev, long clock)  		WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);  		tmp = RREG8(DAC_DATA);  		tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; -		WREG_DAC(MGA1064_PIX_CLK_CTL, tmp); +		WREG8(DAC_DATA, tmp);  		udelay(500); @@ -439,13 +436,13 @@ static int mga_g200eh_set_plls(struct mga_device *mdev, long clock)  		tmp = RREG8(DAC_DATA);  		tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;  		tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL; -		WREG_DAC(MGA1064_PIX_CLK_CTL, tmp); +		WREG8(DAC_DATA, tmp);  		WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);  		tmp = RREG8(DAC_DATA);  		tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;  		tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; -		WREG_DAC(MGA1064_PIX_CLK_CTL, tmp); +		WREG8(DAC_DATA, tmp);  		vcount = RREG8(MGAREG_VCOUNT); @@ -515,12 +512,12 @@ static int mga_g200er_set_plls(struct mga_device *mdev, long clock)  	WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);  	tmp = RREG8(DAC_DATA);  	tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; -	WREG_DAC(MGA1064_PIX_CLK_CTL_CLK_DIS, tmp); +	WREG8(DAC_DATA, tmp);  	WREG8(DAC_INDEX, MGA1064_REMHEADCTL);  	tmp = RREG8(DAC_DATA);  	tmp |= MGA1064_REMHEADCTL_CLKDIS; -	WREG_DAC(MGA1064_REMHEADCTL, tmp); +	WREG8(DAC_DATA, tmp);  	tmp = RREG8(MGAREG_MEM_MISC_READ);  	tmp |= (0x3<<2) | 0xc0; @@ -530,7 +527,7 @@ static int mga_g200er_set_plls(struct mga_device *mdev, long clock)  	tmp = RREG8(DAC_DATA);  	tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;  	tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; -	WREG_DAC(MGA1064_PIX_CLK_CTL, tmp); +	WREG8(DAC_DATA, tmp);  	udelay(500); @@ -657,12 +654,26 @@ static void mga_g200wb_commit(struct drm_crtc *crtc)  	WREG_DAC(MGA1064_GEN_IO_DATA, tmp);  } - +/* +   This is how the framebuffer base address is stored in g200 cards: +   * Assume @offset is the gpu_addr variable of the framebuffer object +   * Then addr is the number of _pixels_ (not bytes) from the start of +     VRAM to the first pixel we want to display. (divided by 2 for 32bit +     framebuffers) +   * addr is stored in the CRTCEXT0, CRTCC and CRTCD registers +   addr<20> -> CRTCEXT0<6> +   addr<19-16> -> CRTCEXT0<3-0> +   addr<15-8> -> CRTCC<7-0> +   addr<7-0> -> CRTCD<7-0> +   CRTCEXT0 has to be programmed last to trigger an update and make the +   new addr variable take effect. + */  void mga_set_start_address(struct drm_crtc *crtc, unsigned offset)  {  	struct mga_device *mdev = crtc->dev->dev_private;  	u32 addr;  	int count; +	u8 crtcext0;  	while (RREG8(0x1fda) & 0x08);  	while (!(RREG8(0x1fda) & 0x08)); @@ -670,10 +681,17 @@ void mga_set_start_address(struct drm_crtc *crtc, unsigned offset)  	count = RREG8(MGAREG_VCOUNT) + 2;  	while (RREG8(MGAREG_VCOUNT) < count); -	addr = offset >> 2; +	WREG8(MGAREG_CRTCEXT_INDEX, 0); +	crtcext0 = RREG8(MGAREG_CRTCEXT_DATA); +	crtcext0 &= 0xB0; +	addr = offset / 8; +	/* Can't store addresses any higher than that... +	   but we also don't have more than 16MB of memory, so it should be fine. */ +	WARN_ON(addr > 0x1fffff); +	crtcext0 |= (!!(addr & (1<<20)))<<6;  	WREG_CRT(0x0d, (u8)(addr & 0xff));  	WREG_CRT(0x0c, (u8)(addr >> 8) & 0xff); -	WREG_CRT(0xaf, (u8)(addr >> 16) & 0xf); +	WREG_ECRT(0x0, ((u8)(addr >> 16) & 0xf) | crtcext0);  } @@ -829,11 +847,7 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc,  	for (i = 0; i < sizeof(dacvalue); i++) { -		if ((i <= 0x03) || -		    (i == 0x07) || -		    (i == 0x0b) || -		    (i == 0x0f) || -		    ((i >= 0x13) && (i <= 0x17)) || +		if ((i <= 0x17) ||  		    (i == 0x1b) ||  		    (i == 0x1c) ||  		    ((i >= 0x1f) && (i <= 0x29)) || diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 61196592152..63d17ee9eb4 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -316,6 +316,7 @@ struct drm_ioctl_desc {  	int flags;  	drm_ioctl_t *func;  	unsigned int cmd_drv; +	const char *name;  };  /** @@ -324,7 +325,7 @@ struct drm_ioctl_desc {   */  #define DRM_IOCTL_DEF_DRV(ioctl, _func, _flags)			\ -	[DRM_IOCTL_NR(DRM_##ioctl)] = {.cmd = DRM_##ioctl, .func = _func, .flags = _flags, .cmd_drv = DRM_IOCTL_##ioctl} +	[DRM_IOCTL_NR(DRM_##ioctl)] = {.cmd = DRM_##ioctl, .func = _func, .flags = _flags, .cmd_drv = DRM_IOCTL_##ioctl, .name = #ioctl}  struct drm_magic_entry {  	struct list_head head; diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index 8230b46fdd7..471f276ce8f 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -50,13 +50,14 @@ struct drm_fb_helper_surface_size {  /**   * struct drm_fb_helper_funcs - driver callbacks for the fbdev emulation library - * @gamma_set: - Set the given gamma lut register on the given crtc. - * @gamma_get: - Read the given gamma lut register on the given crtc, used to - * 		 save the current lut when force-restoring the fbdev for e.g. - * 		 kdbg. - * @fb_probe: - Driver callback to allocate and initialize the fbdev info - * 		structure. Futhermore it also needs to allocate the drm - * 		framebuffer used to back the fbdev. + * @gamma_set: Set the given gamma lut register on the given crtc. + * @gamma_get: Read the given gamma lut register on the given crtc, used to + *             save the current lut when force-restoring the fbdev for e.g. + *             kdbg. + * @fb_probe: Driver callback to allocate and initialize the fbdev info + *            structure. Futhermore it also needs to allocate the drm + *            framebuffer used to back the fbdev. + * @initial_config: Setup an initial fbdev display configuration   *   * Driver callbacks used by the fbdev emulation helper library.   */  |