diff options
Diffstat (limited to 'drivers/gpu/drm/i915')
| -rw-r--r-- | drivers/gpu/drm/i915/dvo_ch7xxx.c | 6 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_dma.c | 3 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_drv.c | 13 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 10 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 32 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_bios.c | 11 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_crt.c | 19 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 90 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_dp.c | 18 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_lvds.c | 8 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_overlay.c | 86 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_panel.c | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_pm.c | 16 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_sdvo.c | 111 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_sdvo_regs.h | 2 | 
16 files changed, 261 insertions, 168 deletions
diff --git a/drivers/gpu/drm/i915/dvo_ch7xxx.c b/drivers/gpu/drm/i915/dvo_ch7xxx.c index 38f3a6cb8c7..3edd981e077 100644 --- a/drivers/gpu/drm/i915/dvo_ch7xxx.c +++ b/drivers/gpu/drm/i915/dvo_ch7xxx.c @@ -303,10 +303,10 @@ static bool ch7xxx_get_hw_state(struct intel_dvo_device *dvo)  	ch7xxx_readb(dvo, CH7xxx_PM, &val); -	if (val & CH7xxx_PM_FPD) -		return false; -	else +	if (val & (CH7xxx_PM_DVIL | CH7xxx_PM_DVIP))  		return true; +	else +		return false;  }  static void ch7xxx_dump_regs(struct intel_dvo_device *dvo) 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 4f2831aa5fe..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); @@ -1341,9 +1342,14 @@ int __must_check i915_gem_object_get_pages(struct drm_i915_gem_object *obj);  static inline struct page *i915_gem_object_get_page(struct drm_i915_gem_object *obj, int n)  {  	struct scatterlist *sg = obj->pages->sgl; -	while (n >= SG_MAX_SINGLE_ALLOC) { +	int nents = obj->pages->nents; +	while (nents > SG_MAX_SINGLE_ALLOC) { +		if (n < SG_MAX_SINGLE_ALLOC - 1) +			break; +  		sg = sg_chain_ptr(sg + SG_MAX_SINGLE_ALLOC - 1);  		n -= SG_MAX_SINGLE_ALLOC - 1; +		nents -= SG_MAX_SINGLE_ALLOC - 1;  	}  	return sg_page(sg+n);  } @@ -1427,7 +1433,7 @@ int __must_check i915_gpu_idle(struct drm_device *dev);  int __must_check i915_gem_idle(struct drm_device *dev);  int i915_add_request(struct intel_ring_buffer *ring,  		     struct drm_file *file, -		     struct drm_i915_gem_request *request); +		     u32 *seqno);  int __must_check i915_wait_seqno(struct intel_ring_buffer *ring,  				 uint32_t seqno);  int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 19dbdd7dd56..9b285da4449 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;  	}  } @@ -1794,7 +1796,7 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)  	 */  	mapping = obj->base.filp->f_path.dentry->d_inode->i_mapping;  	gfp = mapping_gfp_mask(mapping); -	gfp |= __GFP_NORETRY | __GFP_NOWARN; +	gfp |= __GFP_NORETRY | __GFP_NOWARN | __GFP_NO_KSWAPD;  	gfp &= ~(__GFP_IO | __GFP_WAIT);  	for_each_sg(st->sgl, sg, page_count, i) {  		page = shmem_read_mapping_page_gfp(mapping, i, gfp); @@ -1807,7 +1809,7 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)  			 * our own buffer, now let the real VM do its job and  			 * go down in flames if truly OOM.  			 */ -			gfp &= ~(__GFP_NORETRY | __GFP_NOWARN); +			gfp &= ~(__GFP_NORETRY | __GFP_NOWARN | __GFP_NO_KSWAPD);  			gfp |= __GFP_IO | __GFP_WAIT;  			i915_gem_shrink_all(dev_priv); @@ -1815,17 +1817,18 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)  			if (IS_ERR(page))  				goto err_pages; -			gfp |= __GFP_NORETRY | __GFP_NOWARN; +			gfp |= __GFP_NORETRY | __GFP_NOWARN | __GFP_NO_KSWAPD;  			gfp &= ~(__GFP_IO | __GFP_WAIT);  		}  		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: @@ -1955,11 +1958,12 @@ i915_gem_next_request_seqno(struct intel_ring_buffer *ring)  int  i915_add_request(struct intel_ring_buffer *ring,  		 struct drm_file *file, -		 struct drm_i915_gem_request *request) +		 u32 *out_seqno)  {  	drm_i915_private_t *dev_priv = ring->dev->dev_private; -	uint32_t seqno; +	struct drm_i915_gem_request *request;  	u32 request_ring_position; +	u32 seqno;  	int was_empty;  	int ret; @@ -1974,11 +1978,9 @@ i915_add_request(struct intel_ring_buffer *ring,  	if (ret)  		return ret; -	if (request == NULL) { -		request = kmalloc(sizeof(*request), GFP_KERNEL); -		if (request == NULL) -			return -ENOMEM; -	} +	request = kmalloc(sizeof(*request), GFP_KERNEL); +	if (request == NULL) +		return -ENOMEM;  	seqno = i915_gem_next_request_seqno(ring); @@ -2030,6 +2032,8 @@ i915_add_request(struct intel_ring_buffer *ring,  		}  	} +	if (out_seqno) +		*out_seqno = seqno;  	return 0;  } @@ -3959,6 +3963,9 @@ i915_gem_init_hw(struct drm_device *dev)  	if (!intel_enable_gtt())  		return -EIO; +	if (IS_HASWELL(dev) && (I915_READ(0x120010) == 1)) +		I915_WRITE(0x9008, I915_READ(0x9008) | 0xf0000); +  	i915_gem_l3_remap(dev);  	i915_gem_init_swizzling(dev); @@ -4098,7 +4105,6 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data,  	}  	BUG_ON(!list_empty(&dev_priv->mm.active_list)); -	BUG_ON(!list_empty(&dev_priv->mm.inactive_list));  	mutex_unlock(&dev->struct_mutex);  	ret = drm_irq_install(dev); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 64c1be0a9cf..a4162ddff6c 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -521,7 +521,7 @@   */  # define _3D_CHICKEN2_WM_READ_PIPELINED			(1 << 14)  #define _3D_CHICKEN3	0x02090 -#define  _3D_CHICKEN_SF_DISABLE_FASTCLIP_CULL		(1 << 5) +#define  _3D_CHICKEN3_SF_DISABLE_FASTCLIP_CULL		(1 << 5)  #define MI_MODE		0x0209c  # define VS_TIMER_DISPATCH				(1 << 6) diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 0ed6baff4b0..56846ed5ee5 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -499,12 +499,8 @@ parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb)  	edp = find_section(bdb, BDB_EDP);  	if (!edp) { -		if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->edp.support) { -			DRM_DEBUG_KMS("No eDP BDB found but eDP panel " -				      "supported, assume %dbpp panel color " -				      "depth.\n", -				      dev_priv->edp.bpp); -		} +		if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->edp.support) +			DRM_DEBUG_KMS("No eDP BDB found but eDP panel supported.\n");  		return;  	} @@ -657,9 +653,6 @@ init_vbt_defaults(struct drm_i915_private *dev_priv)  	dev_priv->lvds_use_ssc = 1;  	dev_priv->lvds_ssc_freq = intel_bios_ssc_frequency(dev, 1);  	DRM_DEBUG_KMS("Set default to SSC at %dMHz\n", dev_priv->lvds_ssc_freq); - -	/* eDP data */ -	dev_priv->edp.bpp = 18;  }  static int __init intel_no_opregion_vbt_callback(const struct dmi_system_id *id) diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 893f30164b7..6345878ae1e 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -143,7 +143,7 @@ static void intel_crt_dpms(struct drm_connector *connector, int mode)  	int old_dpms;  	/* PCH platforms and VLV only support on/off. */ -	if (INTEL_INFO(dev)->gen < 5 && mode != DRM_MODE_DPMS_ON) +	if (INTEL_INFO(dev)->gen >= 5 && mode != DRM_MODE_DPMS_ON)  		mode = DRM_MODE_DPMS_OFF;  	if (mode == connector->dpms) @@ -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 2b6ce9b2674..b426d44a2b0 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3253,6 +3253,16 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)  	if (HAS_PCH_CPT(dev))  		intel_cpt_verify_modeset(dev, intel_crtc->pipe); + +	/* +	 * There seems to be a race in PCH platform hw (at least on some +	 * outputs) where an enabled pipe still completes any pageflip right +	 * away (as if the pipe is off) instead of waiting for vblank. As soon +	 * as the first vblank happend, everything works as expected. Hence just +	 * wait for one vblank before returning to avoid strange things +	 * happening. +	 */ +	intel_wait_for_vblank(dev, intel_crtc->pipe);  }  static void ironlake_crtc_disable(struct drm_crtc *crtc) @@ -3831,6 +3841,17 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,  			}  		} +		if (intel_encoder->type == INTEL_OUTPUT_EDP) { +			/* Use VBT settings if we have an eDP panel */ +			unsigned int edp_bpc = dev_priv->edp.bpp / 3; + +			if (edp_bpc && edp_bpc < display_bpc) { +				DRM_DEBUG_KMS("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc); +				display_bpc = edp_bpc; +			} +			continue; +		} +  		/*  		 * HDMI is either 12 or 8, so if the display lets 10bpc sneak  		 * through, clamp it down.  (Note: >12bpc will be caught below.) @@ -7882,6 +7903,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 }, @@ -7892,8 +7941,7 @@ static struct intel_quirk intel_quirks[] = {  	/* ThinkPad T60 needs pipe A force quirk (bug #16494) */  	{ 0x2782, 0x17aa, 0x201a, quirk_pipea_force }, -	/* 855 & before need to leave pipe A & dpll A up */ -	{ 0x3582, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force }, +	/* 830/845 need to leave pipe A & dpll A up */  	{ 0x2562, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force },  	{ 0x3577, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force }, @@ -7922,6 +7970,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 */ @@ -8049,29 +8101,42 @@ static void intel_enable_pipe_a(struct drm_device *dev)  } +static bool +intel_check_plane_mapping(struct intel_crtc *crtc) +{ +	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; +	u32 reg, val; + +	if (dev_priv->num_pipe == 1) +		return true; + +	reg = DSPCNTR(!crtc->plane); +	val = I915_READ(reg); + +	if ((val & DISPLAY_PLANE_ENABLE) && +	    (!!(val & DISPPLANE_SEL_PIPE_MASK) == crtc->pipe)) +		return false; + +	return true; +} +  static void intel_sanitize_crtc(struct intel_crtc *crtc)  {  	struct drm_device *dev = crtc->base.dev;  	struct drm_i915_private *dev_priv = dev->dev_private; -	u32 reg, val; +	u32 reg;  	/* Clear any frame start delays used for debugging left by the BIOS */  	reg = PIPECONF(crtc->pipe);  	I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK);  	/* We need to sanitize the plane -> pipe mapping first because this will -	 * disable the crtc (and hence change the state) if it is wrong. */ -	if (!HAS_PCH_SPLIT(dev)) { +	 * disable the crtc (and hence change the state) if it is wrong. Note +	 * that gen4+ has a fixed plane -> pipe mapping.  */ +	if (INTEL_INFO(dev)->gen < 4 && !intel_check_plane_mapping(crtc)) {  		struct intel_connector *connector;  		bool plane; -		reg = DSPCNTR(crtc->plane); -		val = I915_READ(reg); - -		if ((val & DISPLAY_PLANE_ENABLE) == 0 && -		    (!!(val & DISPPLANE_SEL_PIPE_MASK) == crtc->pipe)) -			goto ok; -  		DRM_DEBUG_KMS("[CRTC:%d] wrong plane connection detected!\n",  			      crtc->base.base.id); @@ -8095,7 +8160,6 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)  		WARN_ON(crtc->active);  		crtc->base.enabled = false;  	} -ok:  	if (dev_priv->quirks & QUIRK_PIPEA_FORCE &&  	    crtc->pipe == PIPE_A && !crtc->active) { diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index d1e8ddb2d6c..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); @@ -2369,8 +2374,9 @@ static void  intel_dp_destroy(struct drm_connector *connector)  {  	struct drm_device *dev = connector->dev; +	struct intel_dp *intel_dp = intel_attached_dp(connector); -	if (intel_dpd_is_edp(dev)) +	if (is_edp(intel_dp))  		intel_panel_destroy_backlight(dev);  	drm_sysfs_connector_remove(connector); 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 ebff850a9ab..d7bc817f51a 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -209,7 +209,6 @@ static void intel_overlay_unmap_regs(struct intel_overlay *overlay,  }  static int intel_overlay_do_wait_request(struct intel_overlay *overlay, -					 struct drm_i915_gem_request *request,  					 void (*tail)(struct intel_overlay *))  {  	struct drm_device *dev = overlay->dev; @@ -218,12 +217,10 @@ static int intel_overlay_do_wait_request(struct intel_overlay *overlay,  	int ret;  	BUG_ON(overlay->last_flip_req); -	ret = i915_add_request(ring, NULL, request); -	if (ret) { -	    kfree(request); -	    return ret; -	} -	overlay->last_flip_req = request->seqno; +	ret = i915_add_request(ring, NULL, &overlay->last_flip_req); +	if (ret) +		return ret; +  	overlay->flip_tail = tail;  	ret = i915_wait_seqno(ring, overlay->last_flip_req);  	if (ret) @@ -240,7 +237,6 @@ static int intel_overlay_on(struct intel_overlay *overlay)  	struct drm_device *dev = overlay->dev;  	struct drm_i915_private *dev_priv = dev->dev_private;  	struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; -	struct drm_i915_gem_request *request;  	int ret;  	BUG_ON(overlay->active); @@ -248,17 +244,9 @@ static int intel_overlay_on(struct intel_overlay *overlay)  	WARN_ON(IS_I830(dev) && !(dev_priv->quirks & QUIRK_PIPEA_FORCE)); -	request = kzalloc(sizeof(*request), GFP_KERNEL); -	if (request == NULL) { -		ret = -ENOMEM; -		goto out; -	} -  	ret = intel_ring_begin(ring, 4); -	if (ret) { -		kfree(request); -		goto out; -	} +	if (ret) +		return ret;  	intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_ON);  	intel_ring_emit(ring, overlay->flip_addr | OFC_UPDATE); @@ -266,9 +254,7 @@ static int intel_overlay_on(struct intel_overlay *overlay)  	intel_ring_emit(ring, MI_NOOP);  	intel_ring_advance(ring); -	ret = intel_overlay_do_wait_request(overlay, request, NULL); -out: -	return ret; +	return intel_overlay_do_wait_request(overlay, NULL);  }  /* overlay needs to be enabled in OCMD reg */ @@ -278,17 +264,12 @@ static int intel_overlay_continue(struct intel_overlay *overlay,  	struct drm_device *dev = overlay->dev;  	drm_i915_private_t *dev_priv = dev->dev_private;  	struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; -	struct drm_i915_gem_request *request;  	u32 flip_addr = overlay->flip_addr;  	u32 tmp;  	int ret;  	BUG_ON(!overlay->active); -	request = kzalloc(sizeof(*request), GFP_KERNEL); -	if (request == NULL) -		return -ENOMEM; -  	if (load_polyphase_filter)  		flip_addr |= OFC_UPDATE; @@ -298,22 +279,14 @@ static int intel_overlay_continue(struct intel_overlay *overlay,  		DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp);  	ret = intel_ring_begin(ring, 2); -	if (ret) { -		kfree(request); +	if (ret)  		return ret; -	} +  	intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);  	intel_ring_emit(ring, flip_addr);  	intel_ring_advance(ring); -	ret = i915_add_request(ring, NULL, request); -	if (ret) { -		kfree(request); -		return ret; -	} - -	overlay->last_flip_req = request->seqno; -	return 0; +	return i915_add_request(ring, NULL, &overlay->last_flip_req);  }  static void intel_overlay_release_old_vid_tail(struct intel_overlay *overlay) @@ -349,15 +322,10 @@ static int intel_overlay_off(struct intel_overlay *overlay)  	struct drm_i915_private *dev_priv = dev->dev_private;  	struct intel_ring_buffer *ring = &dev_priv->ring[RCS];  	u32 flip_addr = overlay->flip_addr; -	struct drm_i915_gem_request *request;  	int ret;  	BUG_ON(!overlay->active); -	request = kzalloc(sizeof(*request), GFP_KERNEL); -	if (request == NULL) -		return -ENOMEM; -  	/* According to intel docs the overlay hw may hang (when switching  	 * off) without loading the filter coeffs. It is however unclear whether  	 * this applies to the disabling of the overlay or to the switching off @@ -365,22 +333,28 @@ static int intel_overlay_off(struct intel_overlay *overlay)  	flip_addr |= OFC_UPDATE;  	ret = intel_ring_begin(ring, 6); -	if (ret) { -		kfree(request); +	if (ret)  		return ret; -	} +  	/* wait for overlay to go idle */  	intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);  	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, request, -					     intel_overlay_off_tail); +	return intel_overlay_do_wait_request(overlay, intel_overlay_off_tail);  }  /* recover from an interruption due to a signal @@ -425,24 +399,16 @@ static int intel_overlay_release_old_vid(struct intel_overlay *overlay)  		return 0;  	if (I915_READ(ISR) & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT) { -		struct drm_i915_gem_request *request; -  		/* synchronous slowpath */ -		request = kzalloc(sizeof(*request), GFP_KERNEL); -		if (request == NULL) -			return -ENOMEM; -  		ret = intel_ring_begin(ring, 2); -		if (ret) { -			kfree(request); +		if (ret)  			return ret; -		}  		intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);  		intel_ring_emit(ring, MI_NOOP);  		intel_ring_advance(ring); -		ret = intel_overlay_do_wait_request(overlay, request, +		ret = intel_overlay_do_wait_request(overlay,  						    intel_overlay_release_old_vid_tail);  		if (ret)  			return ret; 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_pm.c b/drivers/gpu/drm/i915/intel_pm.c index b3b4b6cea8b..442968f8b20 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2373,15 +2373,9 @@ int intel_enable_rc6(const struct drm_device *dev)  	if (i915_enable_rc6 >= 0)  		return i915_enable_rc6; -	if (INTEL_INFO(dev)->gen == 5) { -#ifdef CONFIG_INTEL_IOMMU -		/* Disable rc6 on ilk if VT-d is on. */ -		if (intel_iommu_gfx_mapped) -			return false; -#endif -		DRM_DEBUG_DRIVER("Ironlake: only RC6 available\n"); -		return INTEL_RC6_ENABLE; -	} +	/* Disable RC6 on Ironlake */ +	if (INTEL_INFO(dev)->gen == 5) +		return 0;  	if (IS_HASWELL(dev)) {  		DRM_DEBUG_DRIVER("Haswell: only RC6 available\n"); @@ -3442,8 +3436,8 @@ static void gen6_init_clock_gating(struct drm_device *dev)  		   GEN6_RCCUNIT_CLOCK_GATE_DISABLE);  	/* Bspec says we need to always set all mask bits. */ -	I915_WRITE(_3D_CHICKEN, (0xFFFF << 16) | -		   _3D_CHICKEN_SF_DISABLE_FASTCLIP_CULL); +	I915_WRITE(_3D_CHICKEN3, (0xFFFF << 16) | +		   _3D_CHICKEN3_SF_DISABLE_FASTCLIP_CULL);  	/*  	 * According to the spec the following bits should be diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 0007a4d9bf6..a6ac0b41696 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)); @@ -2171,7 +2201,6 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)  		connector->connector_type = DRM_MODE_CONNECTOR_HDMIA;  		intel_sdvo->is_hdmi = true;  	} -	intel_sdvo->base.cloneable = true;  	intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);  	if (intel_sdvo->is_hdmi) @@ -2202,7 +2231,6 @@ intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, int type)  	intel_sdvo->is_tv = true;  	intel_sdvo->base.needs_tv_clock = true; -	intel_sdvo->base.cloneable = false;  	intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo); @@ -2245,8 +2273,6 @@ intel_sdvo_analog_init(struct intel_sdvo *intel_sdvo, int device)  		intel_sdvo_connector->output_flag = SDVO_OUTPUT_RGB1;  	} -	intel_sdvo->base.cloneable = true; -  	intel_sdvo_connector_init(intel_sdvo_connector,  				  intel_sdvo);  	return true; @@ -2277,11 +2303,6 @@ 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; -  	intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);  	if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector))  		goto err; @@ -2354,6 +2375,18 @@ intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, uint16_t flags)  	return true;  } +static void intel_sdvo_output_cleanup(struct intel_sdvo *intel_sdvo) +{ +	struct drm_device *dev = intel_sdvo->base.base.dev; +	struct drm_connector *connector, *tmp; + +	list_for_each_entry_safe(connector, tmp, +				 &dev->mode_config.connector_list, head) { +		if (intel_attached_encoder(connector) == &intel_sdvo->base) +			intel_sdvo_destroy(connector); +	} +} +  static bool intel_sdvo_tv_create_property(struct intel_sdvo *intel_sdvo,  					  struct intel_sdvo_connector *intel_sdvo_connector,  					  int type) @@ -2677,9 +2710,20 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)  				    intel_sdvo->caps.output_flags) != true) {  		DRM_DEBUG_KMS("SDVO output failed to setup on %s\n",  			      SDVO_NAME(intel_sdvo)); -		goto err; +		/* Output_setup can leave behind connectors! */ +		goto err_output;  	} +	/* +	 * Cloning SDVO with anything is often impossible, since the SDVO +	 * encoder can request a special input timing mode. And even if that's +	 * not the case we have evidence that cloning a plain unscaled mode with +	 * VGA doesn't really work. Furthermore the cloning flags are way too +	 * simplistic anyway to express such constraints, so just give up on +	 * cloning for SDVO encoders. +	 */ +	intel_sdvo->base.cloneable = false; +  	/* Only enable the hotplug irq if we need it, to work around noisy  	 * hotplug lines.  	 */ @@ -2690,12 +2734,12 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)  	/* Set the input timing to the screen. Assume always input 0. */  	if (!intel_sdvo_set_target_input(intel_sdvo)) -		goto err; +		goto err_output;  	if (!intel_sdvo_get_input_pixel_clock_range(intel_sdvo,  						    &intel_sdvo->pixel_clock_min,  						    &intel_sdvo->pixel_clock_max)) -		goto err; +		goto err_output;  	DRM_DEBUG_KMS("%s device VID/DID: %02X:%02X.%02X, "  			"clock range %dMHz - %dMHz, " @@ -2715,6 +2759,9 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)  			(SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N');  	return true; +err_output: +	intel_sdvo_output_cleanup(intel_sdvo); +  err:  	drm_encoder_cleanup(&intel_encoder->base);  	i2c_del_adapter(&intel_sdvo->ddc); 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  |