Merge tag 'drm-intel-next-2014-11-07-fixups' of git://anongit.freedesktop.org/drm-intel into drm-next
- skl watermarks code (Damien, Vandana, Pradeep) - reworked audio codec /eld handling code (Jani) - rework the mmio_flip code to use the vblank evade logic and wait for rendering using the standard wait_seqno interface (Ander) - skl forcewake support (Zhe Wang) - refactor the chv interrupt code to use functions shared with vlv (Ville) - prep work for different global gtt views (Tvrtko Ursulin) - precompute the display PLL config before touching hw state (Ander) - completely reworked panel power sequencer code for chv/vlv (Ville) - pre work to split the plane update code into a prepare and commit phase (Gustavo Padovan) - golden context for skl (Armin Reese) - as usual tons of fixes and improvements all over * tag 'drm-intel-next-2014-11-07-fixups' of git://anongit.freedesktop.org/drm-intel: (135 commits) drm/i915: Use correct pipe config to update pll dividers. V2 drm/i915: Plug memory leak in intel_shared_dpll_start_config() drm/i915: Update DRIVER_DATE to 20141107 drm/i915: Add gen to the gpu hang ecode drm/i915: Cache HPLL frequency on VLV/CHV Revert "drm/i915/vlv: Remove check for Old Ack during forcewake" drm/i915: Make mmio flip wait for seqno in the work function drm/i915: Make __wait_seqno non-static and rename to __i915_wait_seqno drm/i915: Move the .global_resources() hook call into modeset_update_crtc_power_domains() drm/i915/audio: add DOC comment describing HDA over HDMI/DP drm/i915: make pipe/port based audio valid accessors easier to use drm/i915/audio: add audio codec enable debug log for g4x drm/i915/audio: add audio codec disable on g4x drm/i915: enable audio codec after port drm/i915/audio: add vlv/chv/gen5-7 audio codec disable sequence drm/i915/audio: rewrite vlv/chv and gen 5-7 audio codec enable sequence drm/i915/skl: Enable Gen9 RC6 drm/i915/skl: Gen9 Forcewake drm/i915/skl: Log the order in which we flush the pipes in the WM code drm/i915/skl: Flush the WM configuration ...
This commit is contained in:
		
				commit
				
					
						fd172d0c47
					
				
			
		
					 35 changed files with 5167 additions and 1661 deletions
				
			
		|  | @ -3887,6 +3887,11 @@ int num_ioctls;</synopsis> | |||
| 	  probing, so those sections fully apply. | ||||
|         </para> | ||||
|       </sect2> | ||||
|       <sect2> | ||||
| 	<title>High Definition Audio</title> | ||||
| !Pdrivers/gpu/drm/i915/intel_audio.c High Definition Audio over HDMI and Display Port | ||||
| !Idrivers/gpu/drm/i915/intel_audio.c | ||||
|       </sect2> | ||||
|       <sect2> | ||||
|         <title>DPIO</title> | ||||
| !Pdrivers/gpu/drm/i915/i915_reg.h DPIO | ||||
|  |  | |||
|  | @ -155,6 +155,11 @@ int drm_plane_helper_check_update(struct drm_plane *plane, | |||
| 		return -ERANGE; | ||||
| 	} | ||||
| 
 | ||||
| 	if (!fb) { | ||||
| 		*visible = false; | ||||
| 		return 0; | ||||
| 	} | ||||
| 
 | ||||
| 	*visible = drm_rect_clip_scaled(src, dest, clip, hscale, vscale); | ||||
| 	if (!*visible) | ||||
| 		/*
 | ||||
|  |  | |||
|  | @ -40,10 +40,12 @@ i915-y += i915_cmd_parser.o \ | |||
| # autogenerated null render state
 | ||||
| i915-y += intel_renderstate_gen6.o \
 | ||||
| 	  intel_renderstate_gen7.o \
 | ||||
| 	  intel_renderstate_gen8.o | ||||
| 	  intel_renderstate_gen8.o \
 | ||||
| 	  intel_renderstate_gen9.o | ||||
| 
 | ||||
| # modesetting core code
 | ||||
| i915-y += intel_bios.o \
 | ||||
| i915-y += intel_audio.o \
 | ||||
| 	  intel_bios.o \
 | ||||
| 	  intel_display.o \
 | ||||
| 	  intel_fifo_underrun.o \
 | ||||
| 	  intel_frontbuffer.o \
 | ||||
|  |  | |||
|  | @ -138,6 +138,11 @@ static const struct drm_i915_cmd_descriptor common_cmds[] = { | |||
| 			.mask = MI_GLOBAL_GTT, | ||||
| 			.expected = 0, | ||||
| 	      }},						       ), | ||||
| 	/*
 | ||||
| 	 * MI_BATCH_BUFFER_START requires some special handling. It's not | ||||
| 	 * really a 'skip' action but it doesn't seem like it's worth adding | ||||
| 	 * a new action. See i915_parse_cmds(). | ||||
| 	 */ | ||||
| 	CMD(  MI_BATCH_BUFFER_START,            SMI,   !F,  0xFF,   S  ), | ||||
| }; | ||||
| 
 | ||||
|  | @ -955,7 +960,8 @@ static bool check_cmd(const struct intel_engine_cs *ring, | |||
|  * Parses the specified batch buffer looking for privilege violations as | ||||
|  * described in the overview. | ||||
|  * | ||||
|  * Return: non-zero if the parser finds violations or otherwise fails | ||||
|  * Return: non-zero if the parser finds violations or otherwise fails; -EACCES | ||||
|  * if the batch appears legal but should use hardware parsing | ||||
|  */ | ||||
| int i915_parse_cmds(struct intel_engine_cs *ring, | ||||
| 		    struct drm_i915_gem_object *batch_obj, | ||||
|  | @ -1002,6 +1008,16 @@ int i915_parse_cmds(struct intel_engine_cs *ring, | |||
| 			break; | ||||
| 		} | ||||
| 
 | ||||
| 		/*
 | ||||
| 		 * If the batch buffer contains a chained batch, return an | ||||
| 		 * error that tells the caller to abort and dispatch the | ||||
| 		 * workload as a non-secure batch. | ||||
| 		 */ | ||||
| 		if (desc->cmd.value == MI_BATCH_BUFFER_START) { | ||||
| 			ret = -EACCES; | ||||
| 			break; | ||||
| 		} | ||||
| 
 | ||||
| 		if (desc->flags & CMD_DESC_FIXED) | ||||
| 			length = desc->length.fixed; | ||||
| 		else | ||||
|  |  | |||
|  | @ -116,7 +116,7 @@ static const char *get_tiling_flag(struct drm_i915_gem_object *obj) | |||
| 
 | ||||
| static inline const char *get_global_flag(struct drm_i915_gem_object *obj) | ||||
| { | ||||
| 	return obj->has_global_gtt_mapping ? "g" : " "; | ||||
| 	return i915_gem_obj_to_ggtt(obj) ? "g" : " "; | ||||
| } | ||||
| 
 | ||||
| static void | ||||
|  | @ -2630,14 +2630,15 @@ static int i915_shared_dplls_info(struct seq_file *m, void *unused) | |||
| 		struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i]; | ||||
| 
 | ||||
| 		seq_printf(m, "DPLL%i: %s, id: %i\n", i, pll->name, pll->id); | ||||
| 		seq_printf(m, " refcount: %i, active: %i, on: %s\n", pll->refcount, | ||||
| 			   pll->active, yesno(pll->on)); | ||||
| 		seq_printf(m, " crtc_mask: 0x%08x, active: %d, on: %s\n", | ||||
| 			   pll->config.crtc_mask, pll->active, yesno(pll->on)); | ||||
| 		seq_printf(m, " tracked hardware state:\n"); | ||||
| 		seq_printf(m, " dpll:    0x%08x\n", pll->hw_state.dpll); | ||||
| 		seq_printf(m, " dpll_md: 0x%08x\n", pll->hw_state.dpll_md); | ||||
| 		seq_printf(m, " fp0:     0x%08x\n", pll->hw_state.fp0); | ||||
| 		seq_printf(m, " fp1:     0x%08x\n", pll->hw_state.fp1); | ||||
| 		seq_printf(m, " wrpll:   0x%08x\n", pll->hw_state.wrpll); | ||||
| 		seq_printf(m, " dpll:    0x%08x\n", pll->config.hw_state.dpll); | ||||
| 		seq_printf(m, " dpll_md: 0x%08x\n", | ||||
| 			   pll->config.hw_state.dpll_md); | ||||
| 		seq_printf(m, " fp0:     0x%08x\n", pll->config.hw_state.fp0); | ||||
| 		seq_printf(m, " fp1:     0x%08x\n", pll->config.hw_state.fp1); | ||||
| 		seq_printf(m, " wrpll:   0x%08x\n", pll->config.hw_state.wrpll); | ||||
| 	} | ||||
| 	drm_modeset_unlock_all(dev); | ||||
| 
 | ||||
|  | @ -2678,6 +2679,42 @@ static int i915_wa_registers(struct seq_file *m, void *unused) | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int i915_ddb_info(struct seq_file *m, void *unused) | ||||
| { | ||||
| 	struct drm_info_node *node = m->private; | ||||
| 	struct drm_device *dev = node->minor->dev; | ||||
| 	struct drm_i915_private *dev_priv = dev->dev_private; | ||||
| 	struct skl_ddb_allocation *ddb; | ||||
| 	struct skl_ddb_entry *entry; | ||||
| 	enum pipe pipe; | ||||
| 	int plane; | ||||
| 
 | ||||
| 	drm_modeset_lock_all(dev); | ||||
| 
 | ||||
| 	ddb = &dev_priv->wm.skl_hw.ddb; | ||||
| 
 | ||||
| 	seq_printf(m, "%-15s%8s%8s%8s\n", "", "Start", "End", "Size"); | ||||
| 
 | ||||
| 	for_each_pipe(dev_priv, pipe) { | ||||
| 		seq_printf(m, "Pipe %c\n", pipe_name(pipe)); | ||||
| 
 | ||||
| 		for_each_plane(pipe, plane) { | ||||
| 			entry = &ddb->plane[pipe][plane]; | ||||
| 			seq_printf(m, "  Plane%-8d%8u%8u%8u\n", plane + 1, | ||||
| 				   entry->start, entry->end, | ||||
| 				   skl_ddb_entry_size(entry)); | ||||
| 		} | ||||
| 
 | ||||
| 		entry = &ddb->cursor[pipe]; | ||||
| 		seq_printf(m, "  %-13s%8u%8u%8u\n", "Cursor", entry->start, | ||||
| 			   entry->end, skl_ddb_entry_size(entry)); | ||||
| 	} | ||||
| 
 | ||||
| 	drm_modeset_unlock_all(dev); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| struct pipe_crc_info { | ||||
| 	const char *name; | ||||
| 	struct drm_device *dev; | ||||
|  | @ -2971,6 +3008,8 @@ static int i9xx_pipe_crc_auto_source(struct drm_device *dev, enum pipe pipe, | |||
| 				break; | ||||
| 			} | ||||
| 			break; | ||||
| 		default: | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 	drm_modeset_unlock_all(dev); | ||||
|  | @ -3520,7 +3559,7 @@ static const struct file_operations i915_display_crc_ctl_fops = { | |||
| 	.write = display_crc_ctl_write | ||||
| }; | ||||
| 
 | ||||
| static void wm_latency_show(struct seq_file *m, const uint16_t wm[5]) | ||||
| static void wm_latency_show(struct seq_file *m, const uint16_t wm[8]) | ||||
| { | ||||
| 	struct drm_device *dev = m->private; | ||||
| 	int num_levels = ilk_wm_max_level(dev) + 1; | ||||
|  | @ -3531,13 +3570,17 @@ static void wm_latency_show(struct seq_file *m, const uint16_t wm[5]) | |||
| 	for (level = 0; level < num_levels; level++) { | ||||
| 		unsigned int latency = wm[level]; | ||||
| 
 | ||||
| 		/* WM1+ latency values in 0.5us units */ | ||||
| 		if (level > 0) | ||||
| 		/*
 | ||||
| 		 * - WM1+ latency values in 0.5us units | ||||
| 		 * - latencies are in us on gen9 | ||||
| 		 */ | ||||
| 		if (INTEL_INFO(dev)->gen >= 9) | ||||
| 			latency *= 10; | ||||
| 		else if (level > 0) | ||||
| 			latency *= 5; | ||||
| 
 | ||||
| 		seq_printf(m, "WM%d %u (%u.%u usec)\n", | ||||
| 			   level, wm[level], | ||||
| 			   latency / 10, latency % 10); | ||||
| 			   level, wm[level], latency / 10, latency % 10); | ||||
| 	} | ||||
| 
 | ||||
| 	drm_modeset_unlock_all(dev); | ||||
|  | @ -3546,8 +3589,15 @@ static void wm_latency_show(struct seq_file *m, const uint16_t wm[5]) | |||
| static int pri_wm_latency_show(struct seq_file *m, void *data) | ||||
| { | ||||
| 	struct drm_device *dev = m->private; | ||||
| 	struct drm_i915_private *dev_priv = dev->dev_private; | ||||
| 	const uint16_t *latencies; | ||||
| 
 | ||||
| 	wm_latency_show(m, to_i915(dev)->wm.pri_latency); | ||||
| 	if (INTEL_INFO(dev)->gen >= 9) | ||||
| 		latencies = dev_priv->wm.skl_latency; | ||||
| 	else | ||||
| 		latencies = to_i915(dev)->wm.pri_latency; | ||||
| 
 | ||||
| 	wm_latency_show(m, latencies); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
|  | @ -3555,8 +3605,15 @@ static int pri_wm_latency_show(struct seq_file *m, void *data) | |||
| static int spr_wm_latency_show(struct seq_file *m, void *data) | ||||
| { | ||||
| 	struct drm_device *dev = m->private; | ||||
| 	struct drm_i915_private *dev_priv = dev->dev_private; | ||||
| 	const uint16_t *latencies; | ||||
| 
 | ||||
| 	wm_latency_show(m, to_i915(dev)->wm.spr_latency); | ||||
| 	if (INTEL_INFO(dev)->gen >= 9) | ||||
| 		latencies = dev_priv->wm.skl_latency; | ||||
| 	else | ||||
| 		latencies = to_i915(dev)->wm.spr_latency; | ||||
| 
 | ||||
| 	wm_latency_show(m, latencies); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
|  | @ -3564,8 +3621,15 @@ static int spr_wm_latency_show(struct seq_file *m, void *data) | |||
| static int cur_wm_latency_show(struct seq_file *m, void *data) | ||||
| { | ||||
| 	struct drm_device *dev = m->private; | ||||
| 	struct drm_i915_private *dev_priv = dev->dev_private; | ||||
| 	const uint16_t *latencies; | ||||
| 
 | ||||
| 	wm_latency_show(m, to_i915(dev)->wm.cur_latency); | ||||
| 	if (INTEL_INFO(dev)->gen >= 9) | ||||
| 		latencies = dev_priv->wm.skl_latency; | ||||
| 	else | ||||
| 		latencies = to_i915(dev)->wm.cur_latency; | ||||
| 
 | ||||
| 	wm_latency_show(m, latencies); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
|  | @ -3601,11 +3665,11 @@ static int cur_wm_latency_open(struct inode *inode, struct file *file) | |||
| } | ||||
| 
 | ||||
| static ssize_t wm_latency_write(struct file *file, const char __user *ubuf, | ||||
| 				size_t len, loff_t *offp, uint16_t wm[5]) | ||||
| 				size_t len, loff_t *offp, uint16_t wm[8]) | ||||
| { | ||||
| 	struct seq_file *m = file->private_data; | ||||
| 	struct drm_device *dev = m->private; | ||||
| 	uint16_t new[5] = { 0 }; | ||||
| 	uint16_t new[8] = { 0 }; | ||||
| 	int num_levels = ilk_wm_max_level(dev) + 1; | ||||
| 	int level; | ||||
| 	int ret; | ||||
|  | @ -3619,7 +3683,9 @@ static ssize_t wm_latency_write(struct file *file, const char __user *ubuf, | |||
| 
 | ||||
| 	tmp[len] = '\0'; | ||||
| 
 | ||||
| 	ret = sscanf(tmp, "%hu %hu %hu %hu %hu", &new[0], &new[1], &new[2], &new[3], &new[4]); | ||||
| 	ret = sscanf(tmp, "%hu %hu %hu %hu %hu %hu %hu %hu", | ||||
| 		     &new[0], &new[1], &new[2], &new[3], | ||||
| 		     &new[4], &new[5], &new[6], &new[7]); | ||||
| 	if (ret != num_levels) | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
|  | @ -3639,8 +3705,15 @@ static ssize_t pri_wm_latency_write(struct file *file, const char __user *ubuf, | |||
| { | ||||
| 	struct seq_file *m = file->private_data; | ||||
| 	struct drm_device *dev = m->private; | ||||
| 	struct drm_i915_private *dev_priv = dev->dev_private; | ||||
| 	uint16_t *latencies; | ||||
| 
 | ||||
| 	return wm_latency_write(file, ubuf, len, offp, to_i915(dev)->wm.pri_latency); | ||||
| 	if (INTEL_INFO(dev)->gen >= 9) | ||||
| 		latencies = dev_priv->wm.skl_latency; | ||||
| 	else | ||||
| 		latencies = to_i915(dev)->wm.pri_latency; | ||||
| 
 | ||||
| 	return wm_latency_write(file, ubuf, len, offp, latencies); | ||||
| } | ||||
| 
 | ||||
| static ssize_t spr_wm_latency_write(struct file *file, const char __user *ubuf, | ||||
|  | @ -3648,8 +3721,15 @@ static ssize_t spr_wm_latency_write(struct file *file, const char __user *ubuf, | |||
| { | ||||
| 	struct seq_file *m = file->private_data; | ||||
| 	struct drm_device *dev = m->private; | ||||
| 	struct drm_i915_private *dev_priv = dev->dev_private; | ||||
| 	uint16_t *latencies; | ||||
| 
 | ||||
| 	return wm_latency_write(file, ubuf, len, offp, to_i915(dev)->wm.spr_latency); | ||||
| 	if (INTEL_INFO(dev)->gen >= 9) | ||||
| 		latencies = dev_priv->wm.skl_latency; | ||||
| 	else | ||||
| 		latencies = to_i915(dev)->wm.spr_latency; | ||||
| 
 | ||||
| 	return wm_latency_write(file, ubuf, len, offp, latencies); | ||||
| } | ||||
| 
 | ||||
| static ssize_t cur_wm_latency_write(struct file *file, const char __user *ubuf, | ||||
|  | @ -3657,8 +3737,15 @@ static ssize_t cur_wm_latency_write(struct file *file, const char __user *ubuf, | |||
| { | ||||
| 	struct seq_file *m = file->private_data; | ||||
| 	struct drm_device *dev = m->private; | ||||
| 	struct drm_i915_private *dev_priv = dev->dev_private; | ||||
| 	uint16_t *latencies; | ||||
| 
 | ||||
| 	return wm_latency_write(file, ubuf, len, offp, to_i915(dev)->wm.cur_latency); | ||||
| 	if (INTEL_INFO(dev)->gen >= 9) | ||||
| 		latencies = dev_priv->wm.skl_latency; | ||||
| 	else | ||||
| 		latencies = to_i915(dev)->wm.cur_latency; | ||||
| 
 | ||||
| 	return wm_latency_write(file, ubuf, len, offp, latencies); | ||||
| } | ||||
| 
 | ||||
| static const struct file_operations i915_pri_wm_latency_fops = { | ||||
|  | @ -4201,6 +4288,7 @@ static const struct drm_info_list i915_debugfs_list[] = { | |||
| 	{"i915_shared_dplls_info", i915_shared_dplls_info, 0}, | ||||
| 	{"i915_dp_mst_info", i915_dp_mst_info, 0}, | ||||
| 	{"i915_wa_registers", i915_wa_registers, 0}, | ||||
| 	{"i915_ddb_info", i915_ddb_info, 0}, | ||||
| }; | ||||
| #define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list) | ||||
| 
 | ||||
|  |  | |||
|  | @ -551,7 +551,7 @@ static void intel_suspend_encoders(struct drm_i915_private *dev_priv) | |||
| } | ||||
| 
 | ||||
| static int intel_suspend_complete(struct drm_i915_private *dev_priv); | ||||
| static int intel_resume_prepare(struct drm_i915_private *dev_priv, | ||||
| static int vlv_resume_prepare(struct drm_i915_private *dev_priv, | ||||
| 			      bool rpm_resume); | ||||
| 
 | ||||
| static int i915_drm_suspend(struct drm_device *dev) | ||||
|  | @ -744,7 +744,7 @@ static int i915_drm_resume(struct drm_device *dev) | |||
| static int i915_drm_resume_early(struct drm_device *dev) | ||||
| { | ||||
| 	struct drm_i915_private *dev_priv = dev->dev_private; | ||||
| 	int ret; | ||||
| 	int ret = 0; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * We have a resume ordering issue with the snd-hda driver also | ||||
|  | @ -760,11 +760,16 @@ static int i915_drm_resume_early(struct drm_device *dev) | |||
| 
 | ||||
| 	pci_set_master(dev->pdev); | ||||
| 
 | ||||
| 	ret = intel_resume_prepare(dev_priv, false); | ||||
| 	if (IS_VALLEYVIEW(dev_priv)) | ||||
| 		ret = vlv_resume_prepare(dev_priv, false); | ||||
| 	if (ret) | ||||
| 		DRM_ERROR("Resume prepare failed: %d,Continuing resume\n", ret); | ||||
| 
 | ||||
| 	intel_uncore_early_sanitize(dev, true); | ||||
| 
 | ||||
| 	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) | ||||
| 		hsw_disable_pc8(dev_priv); | ||||
| 
 | ||||
| 	intel_uncore_sanitize(dev); | ||||
| 	intel_power_domains_init_hw(dev_priv); | ||||
| 
 | ||||
|  | @ -986,25 +991,6 @@ static int hsw_suspend_complete(struct drm_i915_private *dev_priv) | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int snb_resume_prepare(struct drm_i915_private *dev_priv, | ||||
| 				bool rpm_resume) | ||||
| { | ||||
| 	struct drm_device *dev = dev_priv->dev; | ||||
| 
 | ||||
| 	if (rpm_resume) | ||||
| 		intel_init_pch_refclk(dev); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int hsw_resume_prepare(struct drm_i915_private *dev_priv, | ||||
| 				bool rpm_resume) | ||||
| { | ||||
| 	hsw_disable_pc8(dev_priv); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Save all Gunit registers that may be lost after a D3 and a subsequent | ||||
|  * S0i[R123] transition. The list of registers needing a save/restore is | ||||
|  | @ -1409,13 +1395,9 @@ static int intel_runtime_suspend(struct device *device) | |||
| 	i915_gem_release_all_mmaps(dev_priv); | ||||
| 	mutex_unlock(&dev->struct_mutex); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * rps.work can't be rearmed here, since we get here only after making | ||||
| 	 * sure the GPU is idle and the RPS freq is set to the minimum. See | ||||
| 	 * intel_mark_idle(). | ||||
| 	 */ | ||||
| 	cancel_work_sync(&dev_priv->rps.work); | ||||
| 	flush_delayed_work(&dev_priv->rps.delayed_resume_work); | ||||
| 	intel_runtime_pm_disable_interrupts(dev_priv); | ||||
| 	intel_suspend_gt_powersave(dev); | ||||
| 
 | ||||
| 	ret = intel_suspend_complete(dev_priv); | ||||
| 	if (ret) { | ||||
|  | @ -1462,7 +1444,7 @@ static int intel_runtime_resume(struct device *device) | |||
| 	struct pci_dev *pdev = to_pci_dev(device); | ||||
| 	struct drm_device *dev = pci_get_drvdata(pdev); | ||||
| 	struct drm_i915_private *dev_priv = dev->dev_private; | ||||
| 	int ret; | ||||
| 	int ret = 0; | ||||
| 
 | ||||
| 	if (WARN_ON_ONCE(!HAS_RUNTIME_PM(dev))) | ||||
| 		return -ENODEV; | ||||
|  | @ -1472,7 +1454,13 @@ static int intel_runtime_resume(struct device *device) | |||
| 	intel_opregion_notify_adapter(dev, PCI_D0); | ||||
| 	dev_priv->pm.suspended = false; | ||||
| 
 | ||||
| 	ret = intel_resume_prepare(dev_priv, true); | ||||
| 	if (IS_GEN6(dev_priv)) | ||||
| 		intel_init_pch_refclk(dev); | ||||
| 	else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) | ||||
| 		hsw_disable_pc8(dev_priv); | ||||
| 	else if (IS_VALLEYVIEW(dev_priv)) | ||||
| 		ret = vlv_resume_prepare(dev_priv, true); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * No point of rolling back things in case of an error, as the best | ||||
| 	 * we can do is to hope that things will still work (and disable RPM). | ||||
|  | @ -1481,7 +1469,7 @@ static int intel_runtime_resume(struct device *device) | |||
| 	gen6_update_ring_freq(dev); | ||||
| 
 | ||||
| 	intel_runtime_pm_enable_interrupts(dev_priv); | ||||
| 	intel_reset_gt_powersave(dev); | ||||
| 	intel_enable_gt_powersave(dev); | ||||
| 
 | ||||
| 	if (ret) | ||||
| 		DRM_ERROR("Runtime resume failed, disabling it (%d)\n", ret); | ||||
|  | @ -1510,29 +1498,6 @@ static int intel_suspend_complete(struct drm_i915_private *dev_priv) | |||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * This function implements common functionality of runtime and system | ||||
|  * resume sequence. Variable rpm_resume used for implementing different | ||||
|  * code paths. | ||||
|  */ | ||||
| static int intel_resume_prepare(struct drm_i915_private *dev_priv, | ||||
| 				bool rpm_resume) | ||||
| { | ||||
| 	struct drm_device *dev = dev_priv->dev; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	if (IS_GEN6(dev)) | ||||
| 		ret = snb_resume_prepare(dev_priv, rpm_resume); | ||||
| 	else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) | ||||
| 		ret = hsw_resume_prepare(dev_priv, rpm_resume); | ||||
| 	else if (IS_VALLEYVIEW(dev)) | ||||
| 		ret = vlv_resume_prepare(dev_priv, rpm_resume); | ||||
| 	else | ||||
| 		ret = 0; | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| static const struct dev_pm_ops i915_pm_ops = { | ||||
| 	/*
 | ||||
| 	 * S0ix (via system suspend) and S3 event handlers [PMSG_SUSPEND, | ||||
|  |  | |||
|  | @ -55,7 +55,10 @@ | |||
| 
 | ||||
| #define DRIVER_NAME		"i915" | ||||
| #define DRIVER_DESC		"Intel Graphics" | ||||
| #define DRIVER_DATE		"20141024" | ||||
| #define DRIVER_DATE		"20141107" | ||||
| 
 | ||||
| #undef WARN_ON | ||||
| #define WARN_ON(x)		WARN(x, "WARN_ON(" #x ")") | ||||
| 
 | ||||
| enum pipe { | ||||
| 	INVALID_PIPE = -1, | ||||
|  | @ -226,14 +229,20 @@ struct intel_dpll_hw_state { | |||
| 	uint32_t wrpll; | ||||
| }; | ||||
| 
 | ||||
| struct intel_shared_dpll_config { | ||||
| 	unsigned crtc_mask; /* mask of CRTCs sharing this PLL */ | ||||
| 	struct intel_dpll_hw_state hw_state; | ||||
| }; | ||||
| 
 | ||||
| struct intel_shared_dpll { | ||||
| 	int refcount; /* count of number of CRTCs sharing this PLL */ | ||||
| 	struct intel_shared_dpll_config config; | ||||
| 	struct intel_shared_dpll_config *new_config; | ||||
| 
 | ||||
| 	int active; /* count of number of active CRTCs (i.e. DPMS on) */ | ||||
| 	bool on; /* is the PLL actually active? Disabled during modeset */ | ||||
| 	const char *name; | ||||
| 	/* should match the index in the dev_priv->shared_dplls array */ | ||||
| 	enum intel_dpll_id id; | ||||
| 	struct intel_dpll_hw_state hw_state; | ||||
| 	/* The mode_set hook is optional and should be used together with the
 | ||||
| 	 * intel_prepare_shared_dpll function. */ | ||||
| 	void (*mode_set)(struct drm_i915_private *dev_priv, | ||||
|  | @ -275,7 +284,6 @@ void intel_link_compute_m_n(int bpp, int nlanes, | |||
| #define DRIVER_PATCHLEVEL	0 | ||||
| 
 | ||||
| #define WATCH_LISTS	0 | ||||
| #define WATCH_GTT	0 | ||||
| 
 | ||||
| struct opregion_header; | ||||
| struct opregion_acpi; | ||||
|  | @ -434,6 +442,7 @@ struct drm_i915_error_state { | |||
| }; | ||||
| 
 | ||||
| struct intel_connector; | ||||
| struct intel_encoder; | ||||
| struct intel_crtc_config; | ||||
| struct intel_plane_config; | ||||
| struct intel_crtc; | ||||
|  | @ -476,15 +485,14 @@ struct drm_i915_display_funcs { | |||
| 				struct intel_crtc_config *); | ||||
| 	void (*get_plane_config)(struct intel_crtc *, | ||||
| 				 struct intel_plane_config *); | ||||
| 	int (*crtc_mode_set)(struct intel_crtc *crtc, | ||||
| 			     int x, int y, | ||||
| 			     struct drm_framebuffer *old_fb); | ||||
| 	int (*crtc_compute_clock)(struct intel_crtc *crtc); | ||||
| 	void (*crtc_enable)(struct drm_crtc *crtc); | ||||
| 	void (*crtc_disable)(struct drm_crtc *crtc); | ||||
| 	void (*off)(struct drm_crtc *crtc); | ||||
| 	void (*write_eld)(struct drm_connector *connector, | ||||
| 			  struct drm_crtc *crtc, | ||||
| 	void (*audio_codec_enable)(struct drm_connector *connector, | ||||
| 				   struct intel_encoder *encoder, | ||||
| 				   struct drm_display_mode *mode); | ||||
| 	void (*audio_codec_disable)(struct intel_encoder *encoder); | ||||
| 	void (*fdi_link_train)(struct drm_crtc *crtc); | ||||
| 	void (*init_clock_gating)(struct drm_device *dev); | ||||
| 	int (*queue_flip)(struct drm_device *dev, struct drm_crtc *crtc, | ||||
|  | @ -541,6 +549,7 @@ struct intel_uncore { | |||
| 
 | ||||
| 	unsigned fw_rendercount; | ||||
| 	unsigned fw_mediacount; | ||||
| 	unsigned fw_blittercount; | ||||
| 
 | ||||
| 	struct timer_list force_wake_timer; | ||||
| }; | ||||
|  | @ -1379,6 +1388,49 @@ struct ilk_wm_values { | |||
| 	enum intel_ddb_partitioning partitioning; | ||||
| }; | ||||
| 
 | ||||
| struct skl_ddb_entry { | ||||
| 	uint16_t start, end;	/* in number of blocks, 'end' is exclusive */ | ||||
| }; | ||||
| 
 | ||||
| static inline uint16_t skl_ddb_entry_size(const struct skl_ddb_entry *entry) | ||||
| { | ||||
| 	return entry->end - entry->start; | ||||
| } | ||||
| 
 | ||||
| static inline bool skl_ddb_entry_equal(const struct skl_ddb_entry *e1, | ||||
| 				       const struct skl_ddb_entry *e2) | ||||
| { | ||||
| 	if (e1->start == e2->start && e1->end == e2->end) | ||||
| 		return true; | ||||
| 
 | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| struct skl_ddb_allocation { | ||||
| 	struct skl_ddb_entry pipe[I915_MAX_PIPES]; | ||||
| 	struct skl_ddb_entry plane[I915_MAX_PIPES][I915_MAX_PLANES]; | ||||
| 	struct skl_ddb_entry cursor[I915_MAX_PIPES]; | ||||
| }; | ||||
| 
 | ||||
| struct skl_wm_values { | ||||
| 	bool dirty[I915_MAX_PIPES]; | ||||
| 	struct skl_ddb_allocation ddb; | ||||
| 	uint32_t wm_linetime[I915_MAX_PIPES]; | ||||
| 	uint32_t plane[I915_MAX_PIPES][I915_MAX_PLANES][8]; | ||||
| 	uint32_t cursor[I915_MAX_PIPES][8]; | ||||
| 	uint32_t plane_trans[I915_MAX_PIPES][I915_MAX_PLANES]; | ||||
| 	uint32_t cursor_trans[I915_MAX_PIPES]; | ||||
| }; | ||||
| 
 | ||||
| struct skl_wm_level { | ||||
| 	bool plane_en[I915_MAX_PLANES]; | ||||
| 	bool cursor_en; | ||||
| 	uint16_t plane_res_b[I915_MAX_PLANES]; | ||||
| 	uint8_t plane_res_l[I915_MAX_PLANES]; | ||||
| 	uint16_t cursor_res_b; | ||||
| 	uint8_t cursor_res_l; | ||||
| }; | ||||
| 
 | ||||
| /*
 | ||||
|  * This struct helps tracking the state needed for runtime PM, which puts the | ||||
|  * device in PCI D3 state. Notice that when this happens, nothing on the | ||||
|  | @ -1561,6 +1613,7 @@ struct drm_i915_private { | |||
| 
 | ||||
| 	unsigned int fsb_freq, mem_freq, is_ddr3; | ||||
| 	unsigned int vlv_cdclk_freq; | ||||
| 	unsigned int hpll_freq; | ||||
| 
 | ||||
| 	/**
 | ||||
| 	 * wq - Driver workqueue for GEM. | ||||
|  | @ -1670,9 +1723,25 @@ struct drm_i915_private { | |||
| 		uint16_t spr_latency[5]; | ||||
| 		/* cursor */ | ||||
| 		uint16_t cur_latency[5]; | ||||
| 		/*
 | ||||
| 		 * Raw watermark memory latency values | ||||
| 		 * for SKL for all 8 levels | ||||
| 		 * in 1us units. | ||||
| 		 */ | ||||
| 		uint16_t skl_latency[8]; | ||||
| 
 | ||||
| 		/*
 | ||||
| 		 * The skl_wm_values structure is a bit too big for stack | ||||
| 		 * allocation, so we keep the staging struct where we store | ||||
| 		 * intermediate results here instead. | ||||
| 		 */ | ||||
| 		struct skl_wm_values skl_results; | ||||
| 
 | ||||
| 		/* current hardware state */ | ||||
| 		union { | ||||
| 			struct ilk_wm_values hw; | ||||
| 			struct skl_wm_values skl_hw; | ||||
| 		}; | ||||
| 	} wm; | ||||
| 
 | ||||
| 	struct i915_runtime_pm pm; | ||||
|  | @ -1856,8 +1925,6 @@ struct drm_i915_gem_object { | |||
| 	unsigned long gt_ro:1; | ||||
| 	unsigned int cache_level:3; | ||||
| 
 | ||||
| 	unsigned int has_aliasing_ppgtt_mapping:1; | ||||
| 	unsigned int has_global_gtt_mapping:1; | ||||
| 	unsigned int has_dma_mapping:1; | ||||
| 
 | ||||
| 	unsigned int frontbuffer_bits:INTEL_FRONTBUFFER_BITS; | ||||
|  | @ -2292,8 +2359,6 @@ __printf(3, 4) | |||
| void i915_handle_error(struct drm_device *dev, bool wedged, | ||||
| 		       const char *fmt, ...); | ||||
| 
 | ||||
| void gen6_set_pm_mask(struct drm_i915_private *dev_priv, u32 pm_iir, | ||||
| 							int new_delay); | ||||
| extern void intel_irq_init(struct drm_i915_private *dev_priv); | ||||
| extern void intel_hpd_init(struct drm_i915_private *dev_priv); | ||||
| int intel_irq_install(struct drm_i915_private *dev_priv); | ||||
|  | @ -2531,6 +2596,11 @@ int __i915_add_request(struct intel_engine_cs *ring, | |||
| 		       u32 *seqno); | ||||
| #define i915_add_request(ring, seqno) \ | ||||
| 	__i915_add_request(ring, NULL, NULL, seqno) | ||||
| int __i915_wait_seqno(struct intel_engine_cs *ring, u32 seqno, | ||||
| 			unsigned reset_counter, | ||||
| 			bool interruptible, | ||||
| 			s64 *timeout, | ||||
| 			struct drm_i915_file_private *file_priv); | ||||
| int __must_check i915_wait_seqno(struct intel_engine_cs *ring, | ||||
| 				 uint32_t seqno); | ||||
| int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); | ||||
|  | @ -2800,7 +2870,6 @@ static inline bool intel_gmbus_is_forced_bit(struct i2c_adapter *adapter) | |||
| extern void intel_i2c_reset(struct drm_device *dev); | ||||
| 
 | ||||
| /* intel_opregion.c */ | ||||
| struct intel_encoder; | ||||
| #ifdef CONFIG_ACPI | ||||
| extern int intel_opregion_setup(struct drm_device *dev); | ||||
| extern void intel_opregion_init(struct drm_device *dev); | ||||
|  | @ -2917,7 +2986,9 @@ int vlv_freq_opcode(struct drm_i915_private *dev_priv, int val); | |||
| 
 | ||||
| #define FORCEWAKE_RENDER	(1 << 0) | ||||
| #define FORCEWAKE_MEDIA		(1 << 1) | ||||
| #define FORCEWAKE_ALL		(FORCEWAKE_RENDER | FORCEWAKE_MEDIA) | ||||
| #define FORCEWAKE_BLITTER	(1 << 2) | ||||
| #define FORCEWAKE_ALL		(FORCEWAKE_RENDER | FORCEWAKE_MEDIA | \ | ||||
| 					FORCEWAKE_BLITTER) | ||||
| 
 | ||||
| 
 | ||||
| #define I915_READ8(reg)		dev_priv->uncore.funcs.mmio_readb(dev_priv, (reg), true) | ||||
|  |  | |||
|  | @ -1134,7 +1134,7 @@ static bool can_wait_boost(struct drm_i915_file_private *file_priv) | |||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * __wait_seqno - wait until execution of seqno has finished | ||||
|  * __i915_wait_seqno - wait until execution of seqno has finished | ||||
|  * @ring: the ring expected to report seqno | ||||
|  * @seqno: duh! | ||||
|  * @reset_counter: reset sequence associated with the given seqno | ||||
|  | @ -1151,7 +1151,7 @@ static bool can_wait_boost(struct drm_i915_file_private *file_priv) | |||
|  * Returns 0 if the seqno was found within the alloted time. Else returns the | ||||
|  * errno with remaining time filled in timeout argument. | ||||
|  */ | ||||
| static int __wait_seqno(struct intel_engine_cs *ring, u32 seqno, | ||||
| int __i915_wait_seqno(struct intel_engine_cs *ring, u32 seqno, | ||||
| 			unsigned reset_counter, | ||||
| 			bool interruptible, | ||||
| 			s64 *timeout, | ||||
|  | @ -1262,6 +1262,7 @@ i915_wait_seqno(struct intel_engine_cs *ring, uint32_t seqno) | |||
| 	struct drm_device *dev = ring->dev; | ||||
| 	struct drm_i915_private *dev_priv = dev->dev_private; | ||||
| 	bool interruptible = dev_priv->mm.interruptible; | ||||
| 	unsigned reset_counter; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	BUG_ON(!mutex_is_locked(&dev->struct_mutex)); | ||||
|  | @ -1275,14 +1276,13 @@ i915_wait_seqno(struct intel_engine_cs *ring, uint32_t seqno) | |||
| 	if (ret) | ||||
| 		return ret; | ||||
| 
 | ||||
| 	return __wait_seqno(ring, seqno, | ||||
| 			    atomic_read(&dev_priv->gpu_error.reset_counter), | ||||
| 			    interruptible, NULL, NULL); | ||||
| 	reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter); | ||||
| 	return __i915_wait_seqno(ring, seqno, reset_counter, interruptible, | ||||
| 				 NULL, NULL); | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| i915_gem_object_wait_rendering__tail(struct drm_i915_gem_object *obj, | ||||
| 				     struct intel_engine_cs *ring) | ||||
| i915_gem_object_wait_rendering__tail(struct drm_i915_gem_object *obj) | ||||
| { | ||||
| 	if (!obj->active) | ||||
| 		return 0; | ||||
|  | @ -1319,7 +1319,7 @@ i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj, | |||
| 	if (ret) | ||||
| 		return ret; | ||||
| 
 | ||||
| 	return i915_gem_object_wait_rendering__tail(obj, ring); | ||||
| 	return i915_gem_object_wait_rendering__tail(obj); | ||||
| } | ||||
| 
 | ||||
| /* A nonblocking variant of the above wait. This is a highly dangerous routine
 | ||||
|  | @ -1354,12 +1354,13 @@ i915_gem_object_wait_rendering__nonblocking(struct drm_i915_gem_object *obj, | |||
| 
 | ||||
| 	reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter); | ||||
| 	mutex_unlock(&dev->struct_mutex); | ||||
| 	ret = __wait_seqno(ring, seqno, reset_counter, true, NULL, file_priv); | ||||
| 	ret = __i915_wait_seqno(ring, seqno, reset_counter, true, NULL, | ||||
| 				file_priv); | ||||
| 	mutex_lock(&dev->struct_mutex); | ||||
| 	if (ret) | ||||
| 		return ret; | ||||
| 
 | ||||
| 	return i915_gem_object_wait_rendering__tail(obj, ring); | ||||
| 	return i915_gem_object_wait_rendering__tail(obj); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  | @ -2848,8 +2849,8 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file) | |||
| 	reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter); | ||||
| 	mutex_unlock(&dev->struct_mutex); | ||||
| 
 | ||||
| 	return __wait_seqno(ring, seqno, reset_counter, true, &args->timeout_ns, | ||||
| 			    file->driver_priv); | ||||
| 	return __i915_wait_seqno(ring, seqno, reset_counter, true, | ||||
| 				 &args->timeout_ns, file->driver_priv); | ||||
| 
 | ||||
| out: | ||||
| 	drm_gem_object_unreference(&obj->base); | ||||
|  | @ -3477,23 +3478,9 @@ search_free: | |||
| 	list_move_tail(&obj->global_list, &dev_priv->mm.bound_list); | ||||
| 	list_add_tail(&vma->mm_list, &vm->inactive_list); | ||||
| 
 | ||||
| 	if (i915_is_ggtt(vm)) { | ||||
| 		bool mappable, fenceable; | ||||
| 
 | ||||
| 		fenceable = (vma->node.size == fence_size && | ||||
| 			     (vma->node.start & (fence_alignment - 1)) == 0); | ||||
| 
 | ||||
| 		mappable = (vma->node.start + obj->base.size <= | ||||
| 			    dev_priv->gtt.mappable_end); | ||||
| 
 | ||||
| 		obj->map_and_fenceable = mappable && fenceable; | ||||
| 	} | ||||
| 
 | ||||
| 	WARN_ON(flags & PIN_MAPPABLE && !obj->map_and_fenceable); | ||||
| 
 | ||||
| 	trace_i915_vma_bind(vma, flags); | ||||
| 	vma->bind_vma(vma, obj->cache_level, | ||||
| 		      flags & (PIN_MAPPABLE | PIN_GLOBAL) ? GLOBAL_BIND : 0); | ||||
| 		      flags & PIN_GLOBAL ? GLOBAL_BIND : 0); | ||||
| 
 | ||||
| 	return vma; | ||||
| 
 | ||||
|  | @ -3701,7 +3688,7 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj, | |||
| 		list_for_each_entry(vma, &obj->vma_list, vma_link) | ||||
| 			if (drm_mm_node_allocated(&vma->node)) | ||||
| 				vma->bind_vma(vma, cache_level, | ||||
| 					      obj->has_global_gtt_mapping ? GLOBAL_BIND : 0); | ||||
| 						vma->bound & GLOBAL_BIND); | ||||
| 	} | ||||
| 
 | ||||
| 	list_for_each_entry(vma, &obj->vma_list, vma_link) | ||||
|  | @ -4028,7 +4015,7 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file) | |||
| 	if (seqno == 0) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	ret = __wait_seqno(ring, seqno, reset_counter, true, NULL, NULL); | ||||
| 	ret = __i915_wait_seqno(ring, seqno, reset_counter, true, NULL, NULL); | ||||
| 	if (ret == 0) | ||||
| 		queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, 0); | ||||
| 
 | ||||
|  | @ -4062,6 +4049,7 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj, | |||
| { | ||||
| 	struct drm_i915_private *dev_priv = obj->base.dev->dev_private; | ||||
| 	struct i915_vma *vma; | ||||
| 	unsigned bound; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	if (WARN_ON(vm == &dev_priv->mm.aliasing_ppgtt->base)) | ||||
|  | @ -4070,6 +4058,9 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj, | |||
| 	if (WARN_ON(flags & (PIN_GLOBAL | PIN_MAPPABLE) && !i915_is_ggtt(vm))) | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	if (WARN_ON((flags & (PIN_MAPPABLE | PIN_GLOBAL)) == PIN_MAPPABLE)) | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	vma = i915_gem_obj_to_vma(obj, vm); | ||||
| 	if (vma) { | ||||
| 		if (WARN_ON(vma->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT)) | ||||
|  | @ -4091,15 +4082,39 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj, | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	bound = vma ? vma->bound : 0; | ||||
| 	if (vma == NULL || !drm_mm_node_allocated(&vma->node)) { | ||||
| 		vma = i915_gem_object_bind_to_vm(obj, vm, alignment, flags); | ||||
| 		if (IS_ERR(vma)) | ||||
| 			return PTR_ERR(vma); | ||||
| 	} | ||||
| 
 | ||||
| 	if (flags & PIN_GLOBAL && !obj->has_global_gtt_mapping) | ||||
| 	if (flags & PIN_GLOBAL && !(vma->bound & GLOBAL_BIND)) | ||||
| 		vma->bind_vma(vma, obj->cache_level, GLOBAL_BIND); | ||||
| 
 | ||||
| 	if ((bound ^ vma->bound) & GLOBAL_BIND) { | ||||
| 		bool mappable, fenceable; | ||||
| 		u32 fence_size, fence_alignment; | ||||
| 
 | ||||
| 		fence_size = i915_gem_get_gtt_size(obj->base.dev, | ||||
| 						   obj->base.size, | ||||
| 						   obj->tiling_mode); | ||||
| 		fence_alignment = i915_gem_get_gtt_alignment(obj->base.dev, | ||||
| 							     obj->base.size, | ||||
| 							     obj->tiling_mode, | ||||
| 							     true); | ||||
| 
 | ||||
| 		fenceable = (vma->node.size == fence_size && | ||||
| 			     (vma->node.start & (fence_alignment - 1)) == 0); | ||||
| 
 | ||||
| 		mappable = (vma->node.start + obj->base.size <= | ||||
| 			    dev_priv->gtt.mappable_end); | ||||
| 
 | ||||
| 		obj->map_and_fenceable = mappable && fenceable; | ||||
| 	} | ||||
| 
 | ||||
| 	WARN_ON(flags & PIN_MAPPABLE && !obj->map_and_fenceable); | ||||
| 
 | ||||
| 	vma->pin_count++; | ||||
| 	if (flags & PIN_MAPPABLE) | ||||
| 		obj->pin_mappable |= true; | ||||
|  |  | |||
|  | @ -522,6 +522,7 @@ static int do_switch(struct intel_engine_cs *ring, | |||
| 	struct intel_context *from = ring->last_context; | ||||
| 	u32 hw_flags = 0; | ||||
| 	bool uninitialized = false; | ||||
| 	struct i915_vma *vma; | ||||
| 	int ret, i; | ||||
| 
 | ||||
| 	if (from != NULL && ring == &dev_priv->ring[RCS]) { | ||||
|  | @ -571,11 +572,10 @@ static int do_switch(struct intel_engine_cs *ring, | |||
| 	if (ret) | ||||
| 		goto unpin_out; | ||||
| 
 | ||||
| 	if (!to->legacy_hw_ctx.rcs_state->has_global_gtt_mapping) { | ||||
| 		struct i915_vma *vma = i915_gem_obj_to_vma(to->legacy_hw_ctx.rcs_state, | ||||
| 							   &dev_priv->gtt.base); | ||||
| 		vma->bind_vma(vma, to->legacy_hw_ctx.rcs_state->cache_level, GLOBAL_BIND); | ||||
| 	} | ||||
| 	vma = i915_gem_obj_to_ggtt(to->legacy_hw_ctx.rcs_state); | ||||
| 	if (!(vma->bound & GLOBAL_BIND)) | ||||
| 		vma->bind_vma(vma, to->legacy_hw_ctx.rcs_state->cache_level, | ||||
| 				GLOBAL_BIND); | ||||
| 
 | ||||
| 	if (!to->legacy_hw_ctx.initialized || i915_gem_context_is_default(to)) | ||||
| 		hw_flags |= MI_RESTORE_INHIBIT; | ||||
|  |  | |||
|  | @ -357,12 +357,9 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, | |||
| 	 * through the ppgtt for non_secure batchbuffers. */ | ||||
| 	if (unlikely(IS_GEN6(dev) && | ||||
| 	    reloc->write_domain == I915_GEM_DOMAIN_INSTRUCTION && | ||||
| 	    !target_i915_obj->has_global_gtt_mapping)) { | ||||
| 		struct i915_vma *vma = | ||||
| 			list_first_entry(&target_i915_obj->vma_list, | ||||
| 					 typeof(*vma), vma_link); | ||||
| 		vma->bind_vma(vma, target_i915_obj->cache_level, GLOBAL_BIND); | ||||
| 	} | ||||
| 	    !(target_vma->bound & GLOBAL_BIND))) | ||||
| 		target_vma->bind_vma(target_vma, target_i915_obj->cache_level, | ||||
| 				GLOBAL_BIND); | ||||
| 
 | ||||
| 	/* Validate that the target is in a valid r/w GPU domain */ | ||||
| 	if (unlikely(reloc->write_domain & (reloc->write_domain - 1))) { | ||||
|  | @ -531,7 +528,7 @@ i915_gem_execbuffer_reserve_vma(struct i915_vma *vma, | |||
| 
 | ||||
| 	flags = 0; | ||||
| 	if (entry->flags & __EXEC_OBJECT_NEEDS_MAP) | ||||
| 		flags |= PIN_MAPPABLE; | ||||
| 		flags |= PIN_GLOBAL | PIN_MAPPABLE; | ||||
| 	if (entry->flags & EXEC_OBJECT_NEEDS_GTT) | ||||
| 		flags |= PIN_GLOBAL; | ||||
| 	if (entry->flags & __EXEC_OBJECT_NEEDS_BIAS) | ||||
|  | @ -1368,9 +1365,10 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
| 				      batch_obj, | ||||
| 				      args->batch_start_offset, | ||||
| 				      file->is_master); | ||||
| 		if (ret) | ||||
| 		if (ret) { | ||||
| 			if (ret != -EACCES) | ||||
| 				goto err; | ||||
| 
 | ||||
| 		} else { | ||||
| 			/*
 | ||||
| 			 * XXX: Actually do this when enabling batch copy... | ||||
| 			 * | ||||
|  | @ -1380,6 +1378,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
| 			 * want that set when the command parser is enabled. | ||||
| 			 */ | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/* snb/ivb/vlv conflate the "batch in ppgtt" bit with the "non-secure
 | ||||
| 	 * batch" bit. Hence we need to pin secure batches into the global gtt. | ||||
|  |  | |||
|  | @ -1266,7 +1266,7 @@ void i915_check_and_clear_faults(struct drm_device *dev) | |||
| 		fault_reg = I915_READ(RING_FAULT_REG(ring)); | ||||
| 		if (fault_reg & RING_FAULT_VALID) { | ||||
| 			DRM_DEBUG_DRIVER("Unexpected fault\n" | ||||
| 					 "\tAddr: 0x%08lx\\n" | ||||
| 					 "\tAddr: 0x%08lx\n" | ||||
| 					 "\tAddress space: %s\n" | ||||
| 					 "\tSource ID: %d\n" | ||||
| 					 "\tType: %d\n", | ||||
|  | @ -1336,7 +1336,7 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev) | |||
| 		 * Unfortunately above, we've just wiped out the mappings | ||||
| 		 * without telling our object about it. So we need to fake it. | ||||
| 		 */ | ||||
| 		obj->has_global_gtt_mapping = 0; | ||||
| 		vma->bound &= ~GLOBAL_BIND; | ||||
| 		vma->bind_vma(vma, obj->cache_level, GLOBAL_BIND); | ||||
| 	} | ||||
| 
 | ||||
|  | @ -1533,7 +1533,7 @@ static void i915_ggtt_bind_vma(struct i915_vma *vma, | |||
| 
 | ||||
| 	BUG_ON(!i915_is_ggtt(vma->vm)); | ||||
| 	intel_gtt_insert_sg_entries(vma->obj->pages, entry, flags); | ||||
| 	vma->obj->has_global_gtt_mapping = 1; | ||||
| 	vma->bound = GLOBAL_BIND; | ||||
| } | ||||
| 
 | ||||
| static void i915_ggtt_clear_range(struct i915_address_space *vm, | ||||
|  | @ -1552,7 +1552,7 @@ static void i915_ggtt_unbind_vma(struct i915_vma *vma) | |||
| 	const unsigned int size = vma->obj->base.size >> PAGE_SHIFT; | ||||
| 
 | ||||
| 	BUG_ON(!i915_is_ggtt(vma->vm)); | ||||
| 	vma->obj->has_global_gtt_mapping = 0; | ||||
| 	vma->bound = 0; | ||||
| 	intel_gtt_clear_range(first, size); | ||||
| } | ||||
| 
 | ||||
|  | @ -1580,24 +1580,24 @@ static void ggtt_bind_vma(struct i915_vma *vma, | |||
| 	 * flags. At all other times, the GPU will use the aliasing PPGTT. | ||||
| 	 */ | ||||
| 	if (!dev_priv->mm.aliasing_ppgtt || flags & GLOBAL_BIND) { | ||||
| 		if (!obj->has_global_gtt_mapping || | ||||
| 		if (!(vma->bound & GLOBAL_BIND) || | ||||
| 		    (cache_level != obj->cache_level)) { | ||||
| 			vma->vm->insert_entries(vma->vm, obj->pages, | ||||
| 						vma->node.start, | ||||
| 						cache_level, flags); | ||||
| 			obj->has_global_gtt_mapping = 1; | ||||
| 			vma->bound |= GLOBAL_BIND; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (dev_priv->mm.aliasing_ppgtt && | ||||
| 	    (!obj->has_aliasing_ppgtt_mapping || | ||||
| 	    (!(vma->bound & LOCAL_BIND) || | ||||
| 	     (cache_level != obj->cache_level))) { | ||||
| 		struct i915_hw_ppgtt *appgtt = dev_priv->mm.aliasing_ppgtt; | ||||
| 		appgtt->base.insert_entries(&appgtt->base, | ||||
| 					    vma->obj->pages, | ||||
| 					    vma->node.start, | ||||
| 					    cache_level, flags); | ||||
| 		vma->obj->has_aliasing_ppgtt_mapping = 1; | ||||
| 		vma->bound |= LOCAL_BIND; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -1607,21 +1607,21 @@ static void ggtt_unbind_vma(struct i915_vma *vma) | |||
| 	struct drm_i915_private *dev_priv = dev->dev_private; | ||||
| 	struct drm_i915_gem_object *obj = vma->obj; | ||||
| 
 | ||||
| 	if (obj->has_global_gtt_mapping) { | ||||
| 	if (vma->bound & GLOBAL_BIND) { | ||||
| 		vma->vm->clear_range(vma->vm, | ||||
| 				     vma->node.start, | ||||
| 				     obj->base.size, | ||||
| 				     true); | ||||
| 		obj->has_global_gtt_mapping = 0; | ||||
| 		vma->bound &= ~GLOBAL_BIND; | ||||
| 	} | ||||
| 
 | ||||
| 	if (obj->has_aliasing_ppgtt_mapping) { | ||||
| 	if (vma->bound & LOCAL_BIND) { | ||||
| 		struct i915_hw_ppgtt *appgtt = dev_priv->mm.aliasing_ppgtt; | ||||
| 		appgtt->base.clear_range(&appgtt->base, | ||||
| 					 vma->node.start, | ||||
| 					 obj->base.size, | ||||
| 					 true); | ||||
| 		obj->has_aliasing_ppgtt_mapping = 0; | ||||
| 		vma->bound &= ~LOCAL_BIND; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -1699,7 +1699,7 @@ int i915_gem_setup_global_gtt(struct drm_device *dev, | |||
| 			DRM_DEBUG_KMS("Reservation failed: %i\n", ret); | ||||
| 			return ret; | ||||
| 		} | ||||
| 		obj->has_global_gtt_mapping = 1; | ||||
| 		vma->bound |= GLOBAL_BIND; | ||||
| 	} | ||||
| 
 | ||||
| 	dev_priv->gtt.base.start = start; | ||||
|  |  | |||
|  | @ -123,6 +123,12 @@ struct i915_vma { | |||
| 	struct drm_i915_gem_object *obj; | ||||
| 	struct i915_address_space *vm; | ||||
| 
 | ||||
| 	/** Flags and address space this VMA is bound to */ | ||||
| #define GLOBAL_BIND	(1<<0) | ||||
| #define LOCAL_BIND	(1<<1) | ||||
| #define PTE_READ_ONLY	(1<<2) | ||||
| 	unsigned int bound : 4; | ||||
| 
 | ||||
| 	/** This object's place on the active/inactive lists */ | ||||
| 	struct list_head mm_list; | ||||
| 
 | ||||
|  | @ -155,8 +161,6 @@ struct i915_vma { | |||
| 	 * setting the valid PTE entries to a reserved scratch page. */ | ||||
| 	void (*unbind_vma)(struct i915_vma *vma); | ||||
| 	/* Map an object into an address space with the given cache flags. */ | ||||
| #define GLOBAL_BIND (1<<0) | ||||
| #define PTE_READ_ONLY (1<<1) | ||||
| 	void (*bind_vma)(struct i915_vma *vma, | ||||
| 			 enum i915_cache_level cache_level, | ||||
| 			 u32 flags); | ||||
|  |  | |||
|  | @ -38,6 +38,8 @@ render_state_get_rodata(struct drm_device *dev, const int gen) | |||
| 		return &gen7_null_state; | ||||
| 	case 8: | ||||
| 		return &gen8_null_state; | ||||
| 	case 9: | ||||
| 		return &gen9_null_state; | ||||
| 	} | ||||
| 
 | ||||
| 	return NULL; | ||||
|  |  | |||
|  | @ -533,7 +533,7 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev, | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	obj->has_global_gtt_mapping = 1; | ||||
| 	vma->bound |= GLOBAL_BIND; | ||||
| 
 | ||||
| 	list_add_tail(&obj->global_list, &dev_priv->mm.bound_list); | ||||
| 	list_add_tail(&vma->mm_list, &ggtt->inactive_list); | ||||
|  |  | |||
|  | @ -458,6 +458,7 @@ i915_gem_get_tiling(struct drm_device *dev, void *data, | |||
| 	} | ||||
| 
 | ||||
| 	/* Hide bit 17 from the user -- see comment in i915_gem_set_tiling */ | ||||
| 	args->phys_swizzle_mode = args->swizzle_mode; | ||||
| 	if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_17) | ||||
| 		args->swizzle_mode = I915_BIT_6_SWIZZLE_9; | ||||
| 	if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_10_17) | ||||
|  |  | |||
|  | @ -565,6 +565,7 @@ i915_error_object_create(struct drm_i915_private *dev_priv, | |||
| 			 struct i915_address_space *vm) | ||||
| { | ||||
| 	struct drm_i915_error_object *dst; | ||||
| 	struct i915_vma *vma = NULL; | ||||
| 	int num_pages; | ||||
| 	bool use_ggtt; | ||||
| 	int i = 0; | ||||
|  | @ -585,16 +586,17 @@ i915_error_object_create(struct drm_i915_private *dev_priv, | |||
| 		dst->gtt_offset = -1; | ||||
| 
 | ||||
| 	reloc_offset = dst->gtt_offset; | ||||
| 	if (i915_is_ggtt(vm)) | ||||
| 		vma = i915_gem_obj_to_ggtt(src); | ||||
| 	use_ggtt = (src->cache_level == I915_CACHE_NONE && | ||||
| 		    i915_is_ggtt(vm) && | ||||
| 		    src->has_global_gtt_mapping && | ||||
| 		   vma && (vma->bound & GLOBAL_BIND) && | ||||
| 		   reloc_offset + num_pages * PAGE_SIZE <= dev_priv->gtt.mappable_end); | ||||
| 
 | ||||
| 	/* Cannot access stolen address directly, try to use the aperture */ | ||||
| 	if (src->stolen) { | ||||
| 		use_ggtt = true; | ||||
| 
 | ||||
| 		if (!src->has_global_gtt_mapping) | ||||
| 		if (!(vma && vma->bound & GLOBAL_BIND)) | ||||
| 			goto unwind; | ||||
| 
 | ||||
| 		reloc_offset = i915_gem_obj_ggtt_offset(src); | ||||
|  | @ -1240,7 +1242,8 @@ static void i915_error_capture_msg(struct drm_device *dev, | |||
| 	ecode = i915_error_generate_code(dev_priv, error, &ring_id); | ||||
| 
 | ||||
| 	len = scnprintf(error->error_msg, sizeof(error->error_msg), | ||||
| 			"GPU HANG: ecode %d:0x%08x", ring_id, ecode); | ||||
| 			"GPU HANG: ecode %d:%d:0x%08x", | ||||
| 			INTEL_INFO(dev)->gen, ring_id, ecode); | ||||
| 
 | ||||
| 	if (ring_id != -1 && error->ring[ring_id].pid != -1) | ||||
| 		len += scnprintf(error->error_msg + len, | ||||
|  |  | |||
|  | @ -126,16 +126,16 @@ static const u32 hpd_status_i915[] = { /* i915 and valleyview are the same */ | |||
| 
 | ||||
| #define GEN8_IRQ_INIT_NDX(type, which, imr_val, ier_val) do { \ | ||||
| 	GEN5_ASSERT_IIR_IS_ZERO(GEN8_##type##_IIR(which)); \ | ||||
| 	I915_WRITE(GEN8_##type##_IMR(which), (imr_val)); \ | ||||
| 	I915_WRITE(GEN8_##type##_IER(which), (ier_val)); \ | ||||
| 	POSTING_READ(GEN8_##type##_IER(which)); \ | ||||
| 	I915_WRITE(GEN8_##type##_IMR(which), (imr_val)); \ | ||||
| 	POSTING_READ(GEN8_##type##_IMR(which)); \ | ||||
| } while (0) | ||||
| 
 | ||||
| #define GEN5_IRQ_INIT(type, imr_val, ier_val) do { \ | ||||
| 	GEN5_ASSERT_IIR_IS_ZERO(type##IIR); \ | ||||
| 	I915_WRITE(type##IMR, (imr_val)); \ | ||||
| 	I915_WRITE(type##IER, (ier_val)); \ | ||||
| 	POSTING_READ(type##IER); \ | ||||
| 	I915_WRITE(type##IMR, (imr_val)); \ | ||||
| 	POSTING_READ(type##IMR); \ | ||||
| } while (0) | ||||
| 
 | ||||
| /* For display hotplug interrupt */ | ||||
|  | @ -979,9 +979,6 @@ static void notify_ring(struct drm_device *dev, | |||
| 
 | ||||
| 	trace_i915_gem_request_complete(ring); | ||||
| 
 | ||||
| 	if (drm_core_check_feature(dev, DRIVER_MODESET)) | ||||
| 		intel_notify_mmio_flip(ring); | ||||
| 
 | ||||
| 	wake_up_all(&ring->irq_queue); | ||||
| 	i915_queue_hangcheck(dev); | ||||
| } | ||||
|  | @ -3105,10 +3102,22 @@ static void ironlake_irq_reset(struct drm_device *dev) | |||
| 	ibx_irq_reset(dev); | ||||
| } | ||||
| 
 | ||||
| static void vlv_display_irq_reset(struct drm_i915_private *dev_priv) | ||||
| { | ||||
| 	enum pipe pipe; | ||||
| 
 | ||||
| 	I915_WRITE(PORT_HOTPLUG_EN, 0); | ||||
| 	I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); | ||||
| 
 | ||||
| 	for_each_pipe(dev_priv, pipe) | ||||
| 		I915_WRITE(PIPESTAT(pipe), 0xffff); | ||||
| 
 | ||||
| 	GEN5_IRQ_RESET(VLV_); | ||||
| } | ||||
| 
 | ||||
| static void valleyview_irq_preinstall(struct drm_device *dev) | ||||
| { | ||||
| 	struct drm_i915_private *dev_priv = dev->dev_private; | ||||
| 	int pipe; | ||||
| 
 | ||||
| 	/* VLV magic */ | ||||
| 	I915_WRITE(VLV_IMR, 0); | ||||
|  | @ -3116,22 +3125,11 @@ static void valleyview_irq_preinstall(struct drm_device *dev) | |||
| 	I915_WRITE(RING_IMR(GEN6_BSD_RING_BASE), 0); | ||||
| 	I915_WRITE(RING_IMR(BLT_RING_BASE), 0); | ||||
| 
 | ||||
| 	/* and GT */ | ||||
| 	I915_WRITE(GTIIR, I915_READ(GTIIR)); | ||||
| 	I915_WRITE(GTIIR, I915_READ(GTIIR)); | ||||
| 
 | ||||
| 	gen5_gt_irq_reset(dev); | ||||
| 
 | ||||
| 	I915_WRITE(DPINVGTT, 0xff); | ||||
| 	I915_WRITE(DPINVGTT, DPINVGTT_STATUS_MASK); | ||||
| 
 | ||||
| 	I915_WRITE(PORT_HOTPLUG_EN, 0); | ||||
| 	I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); | ||||
| 	for_each_pipe(dev_priv, pipe) | ||||
| 		I915_WRITE(PIPESTAT(pipe), 0xffff); | ||||
| 	I915_WRITE(VLV_IIR, 0xffffffff); | ||||
| 	I915_WRITE(VLV_IMR, 0xffffffff); | ||||
| 	I915_WRITE(VLV_IER, 0x0); | ||||
| 	POSTING_READ(VLV_IER); | ||||
| 	vlv_display_irq_reset(dev_priv); | ||||
| } | ||||
| 
 | ||||
| static void gen8_gt_irq_reset(struct drm_i915_private *dev_priv) | ||||
|  | @ -3179,7 +3177,6 @@ void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv) | |||
| static void cherryview_irq_preinstall(struct drm_device *dev) | ||||
| { | ||||
| 	struct drm_i915_private *dev_priv = dev->dev_private; | ||||
| 	int pipe; | ||||
| 
 | ||||
| 	I915_WRITE(GEN8_MASTER_IRQ, 0); | ||||
| 	POSTING_READ(GEN8_MASTER_IRQ); | ||||
|  | @ -3188,20 +3185,9 @@ static void cherryview_irq_preinstall(struct drm_device *dev) | |||
| 
 | ||||
| 	GEN5_IRQ_RESET(GEN8_PCU_); | ||||
| 
 | ||||
| 	POSTING_READ(GEN8_PCU_IIR); | ||||
| 
 | ||||
| 	I915_WRITE(DPINVGTT, DPINVGTT_STATUS_MASK_CHV); | ||||
| 
 | ||||
| 	I915_WRITE(PORT_HOTPLUG_EN, 0); | ||||
| 	I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); | ||||
| 
 | ||||
| 	for_each_pipe(dev_priv, pipe) | ||||
| 		I915_WRITE(PIPESTAT(pipe), 0xffff); | ||||
| 
 | ||||
| 	I915_WRITE(VLV_IMR, 0xffffffff); | ||||
| 	I915_WRITE(VLV_IER, 0x0); | ||||
| 	I915_WRITE(VLV_IIR, 0xffffffff); | ||||
| 	POSTING_READ(VLV_IIR); | ||||
| 	vlv_display_irq_reset(dev_priv); | ||||
| } | ||||
| 
 | ||||
| static void ibx_hpd_irq_setup(struct drm_device *dev) | ||||
|  | @ -3342,45 +3328,51 @@ static void valleyview_display_irqs_install(struct drm_i915_private *dev_priv) | |||
| { | ||||
| 	u32 pipestat_mask; | ||||
| 	u32 iir_mask; | ||||
| 	enum pipe pipe; | ||||
| 
 | ||||
| 	pipestat_mask = PIPESTAT_INT_STATUS_MASK | | ||||
| 			PIPE_FIFO_UNDERRUN_STATUS; | ||||
| 
 | ||||
| 	I915_WRITE(PIPESTAT(PIPE_A), pipestat_mask); | ||||
| 	I915_WRITE(PIPESTAT(PIPE_B), pipestat_mask); | ||||
| 	for_each_pipe(dev_priv, pipe) | ||||
| 		I915_WRITE(PIPESTAT(pipe), pipestat_mask); | ||||
| 	POSTING_READ(PIPESTAT(PIPE_A)); | ||||
| 
 | ||||
| 	pipestat_mask = PLANE_FLIP_DONE_INT_STATUS_VLV | | ||||
| 			PIPE_CRC_DONE_INTERRUPT_STATUS; | ||||
| 
 | ||||
| 	i915_enable_pipestat(dev_priv, PIPE_A, pipestat_mask | | ||||
| 					       PIPE_GMBUS_INTERRUPT_STATUS); | ||||
| 	i915_enable_pipestat(dev_priv, PIPE_B, pipestat_mask); | ||||
| 	i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS); | ||||
| 	for_each_pipe(dev_priv, pipe) | ||||
| 		      i915_enable_pipestat(dev_priv, pipe, pipestat_mask); | ||||
| 
 | ||||
| 	iir_mask = I915_DISPLAY_PORT_INTERRUPT | | ||||
| 		   I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | | ||||
| 		   I915_DISPLAY_PIPE_B_EVENT_INTERRUPT; | ||||
| 	if (IS_CHERRYVIEW(dev_priv)) | ||||
| 		iir_mask |= I915_DISPLAY_PIPE_C_EVENT_INTERRUPT; | ||||
| 	dev_priv->irq_mask &= ~iir_mask; | ||||
| 
 | ||||
| 	I915_WRITE(VLV_IIR, iir_mask); | ||||
| 	I915_WRITE(VLV_IIR, iir_mask); | ||||
| 	I915_WRITE(VLV_IMR, dev_priv->irq_mask); | ||||
| 	I915_WRITE(VLV_IER, ~dev_priv->irq_mask); | ||||
| 	POSTING_READ(VLV_IER); | ||||
| 	I915_WRITE(VLV_IMR, dev_priv->irq_mask); | ||||
| 	POSTING_READ(VLV_IMR); | ||||
| } | ||||
| 
 | ||||
| static void valleyview_display_irqs_uninstall(struct drm_i915_private *dev_priv) | ||||
| { | ||||
| 	u32 pipestat_mask; | ||||
| 	u32 iir_mask; | ||||
| 	enum pipe pipe; | ||||
| 
 | ||||
| 	iir_mask = I915_DISPLAY_PORT_INTERRUPT | | ||||
| 		   I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | | ||||
| 		   I915_DISPLAY_PIPE_B_EVENT_INTERRUPT; | ||||
| 	if (IS_CHERRYVIEW(dev_priv)) | ||||
| 		iir_mask |= I915_DISPLAY_PIPE_C_EVENT_INTERRUPT; | ||||
| 
 | ||||
| 	dev_priv->irq_mask |= iir_mask; | ||||
| 	I915_WRITE(VLV_IER, ~dev_priv->irq_mask); | ||||
| 	I915_WRITE(VLV_IMR, dev_priv->irq_mask); | ||||
| 	I915_WRITE(VLV_IER, ~dev_priv->irq_mask); | ||||
| 	I915_WRITE(VLV_IIR, iir_mask); | ||||
| 	I915_WRITE(VLV_IIR, iir_mask); | ||||
| 	POSTING_READ(VLV_IIR); | ||||
|  | @ -3388,14 +3380,15 @@ static void valleyview_display_irqs_uninstall(struct drm_i915_private *dev_priv) | |||
| 	pipestat_mask = PLANE_FLIP_DONE_INT_STATUS_VLV | | ||||
| 			PIPE_CRC_DONE_INTERRUPT_STATUS; | ||||
| 
 | ||||
| 	i915_disable_pipestat(dev_priv, PIPE_A, pipestat_mask | | ||||
| 					        PIPE_GMBUS_INTERRUPT_STATUS); | ||||
| 	i915_disable_pipestat(dev_priv, PIPE_B, pipestat_mask); | ||||
| 	i915_disable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS); | ||||
| 	for_each_pipe(dev_priv, pipe) | ||||
| 		i915_disable_pipestat(dev_priv, pipe, pipestat_mask); | ||||
| 
 | ||||
| 	pipestat_mask = PIPESTAT_INT_STATUS_MASK | | ||||
| 			PIPE_FIFO_UNDERRUN_STATUS; | ||||
| 	I915_WRITE(PIPESTAT(PIPE_A), pipestat_mask); | ||||
| 	I915_WRITE(PIPESTAT(PIPE_B), pipestat_mask); | ||||
| 
 | ||||
| 	for_each_pipe(dev_priv, pipe) | ||||
| 		I915_WRITE(PIPESTAT(pipe), pipestat_mask); | ||||
| 	POSTING_READ(PIPESTAT(PIPE_A)); | ||||
| } | ||||
| 
 | ||||
|  | @ -3425,19 +3418,18 @@ void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv) | |||
| 		valleyview_display_irqs_uninstall(dev_priv); | ||||
| } | ||||
| 
 | ||||
| static int valleyview_irq_postinstall(struct drm_device *dev) | ||||
| static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv) | ||||
| { | ||||
| 	struct drm_i915_private *dev_priv = dev->dev_private; | ||||
| 
 | ||||
| 	dev_priv->irq_mask = ~0; | ||||
| 
 | ||||
| 	I915_WRITE(PORT_HOTPLUG_EN, 0); | ||||
| 	POSTING_READ(PORT_HOTPLUG_EN); | ||||
| 
 | ||||
| 	I915_WRITE(VLV_IMR, dev_priv->irq_mask); | ||||
| 	I915_WRITE(VLV_IER, ~dev_priv->irq_mask); | ||||
| 	I915_WRITE(VLV_IIR, 0xffffffff); | ||||
| 	POSTING_READ(VLV_IER); | ||||
| 	I915_WRITE(VLV_IIR, 0xffffffff); | ||||
| 	I915_WRITE(VLV_IER, ~dev_priv->irq_mask); | ||||
| 	I915_WRITE(VLV_IMR, dev_priv->irq_mask); | ||||
| 	POSTING_READ(VLV_IMR); | ||||
| 
 | ||||
| 	/* Interrupt setup is already guaranteed to be single-threaded, this is
 | ||||
| 	 * just to make the assert_spin_locked check happy. */ | ||||
|  | @ -3445,9 +3437,13 @@ static int valleyview_irq_postinstall(struct drm_device *dev) | |||
| 	if (dev_priv->display_irqs_enabled) | ||||
| 		valleyview_display_irqs_install(dev_priv); | ||||
| 	spin_unlock_irq(&dev_priv->irq_lock); | ||||
| } | ||||
| 
 | ||||
| 	I915_WRITE(VLV_IIR, 0xffffffff); | ||||
| 	I915_WRITE(VLV_IIR, 0xffffffff); | ||||
| static int valleyview_irq_postinstall(struct drm_device *dev) | ||||
| { | ||||
| 	struct drm_i915_private *dev_priv = dev->dev_private; | ||||
| 
 | ||||
| 	vlv_display_irq_postinstall(dev_priv); | ||||
| 
 | ||||
| 	gen5_gt_irq_postinstall(dev); | ||||
| 
 | ||||
|  | @ -3561,8 +3557,10 @@ static int cherryview_irq_postinstall(struct drm_device *dev) | |||
| 	spin_unlock_irq(&dev_priv->irq_lock); | ||||
| 
 | ||||
| 	I915_WRITE(VLV_IIR, 0xffffffff); | ||||
| 	I915_WRITE(VLV_IMR, dev_priv->irq_mask); | ||||
| 	I915_WRITE(VLV_IIR, 0xffffffff); | ||||
| 	I915_WRITE(VLV_IER, enable_mask); | ||||
| 	I915_WRITE(VLV_IMR, dev_priv->irq_mask); | ||||
| 	POSTING_READ(VLV_IMR); | ||||
| 
 | ||||
| 	gen8_gt_irq_postinstall(dev_priv); | ||||
| 
 | ||||
|  | @ -3585,19 +3583,15 @@ static void gen8_irq_uninstall(struct drm_device *dev) | |||
| static void valleyview_irq_uninstall(struct drm_device *dev) | ||||
| { | ||||
| 	struct drm_i915_private *dev_priv = dev->dev_private; | ||||
| 	int pipe; | ||||
| 
 | ||||
| 	if (!dev_priv) | ||||
| 		return; | ||||
| 
 | ||||
| 	I915_WRITE(VLV_MASTER_IER, 0); | ||||
| 
 | ||||
| 	for_each_pipe(dev_priv, pipe) | ||||
| 		I915_WRITE(PIPESTAT(pipe), 0xffff); | ||||
| 	gen5_gt_irq_reset(dev); | ||||
| 
 | ||||
| 	I915_WRITE(HWSTAM, 0xffffffff); | ||||
| 	I915_WRITE(PORT_HOTPLUG_EN, 0); | ||||
| 	I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); | ||||
| 
 | ||||
| 	/* Interrupt setup is already guaranteed to be single-threaded, this is
 | ||||
| 	 * just to make the assert_spin_locked check happy. */ | ||||
|  | @ -3606,12 +3600,9 @@ static void valleyview_irq_uninstall(struct drm_device *dev) | |||
| 		valleyview_display_irqs_uninstall(dev_priv); | ||||
| 	spin_unlock_irq(&dev_priv->irq_lock); | ||||
| 
 | ||||
| 	dev_priv->irq_mask = 0; | ||||
| 	vlv_display_irq_reset(dev_priv); | ||||
| 
 | ||||
| 	I915_WRITE(VLV_IIR, 0xffffffff); | ||||
| 	I915_WRITE(VLV_IMR, 0xffffffff); | ||||
| 	I915_WRITE(VLV_IER, 0x0); | ||||
| 	POSTING_READ(VLV_IER); | ||||
| 	dev_priv->irq_mask = 0; | ||||
| } | ||||
| 
 | ||||
| static void cherryview_irq_uninstall(struct drm_device *dev) | ||||
|  | @ -3625,33 +3616,9 @@ static void cherryview_irq_uninstall(struct drm_device *dev) | |||
| 	I915_WRITE(GEN8_MASTER_IRQ, 0); | ||||
| 	POSTING_READ(GEN8_MASTER_IRQ); | ||||
| 
 | ||||
| #define GEN8_IRQ_FINI_NDX(type, which)				\ | ||||
| do {								\ | ||||
| 	I915_WRITE(GEN8_##type##_IMR(which), 0xffffffff);	\ | ||||
| 	I915_WRITE(GEN8_##type##_IER(which), 0);		\ | ||||
| 	I915_WRITE(GEN8_##type##_IIR(which), 0xffffffff);	\ | ||||
| 	POSTING_READ(GEN8_##type##_IIR(which));			\ | ||||
| 	I915_WRITE(GEN8_##type##_IIR(which), 0xffffffff);	\ | ||||
| } while (0) | ||||
| 	gen8_gt_irq_reset(dev_priv); | ||||
| 
 | ||||
| #define GEN8_IRQ_FINI(type)				\ | ||||
| do {							\ | ||||
| 	I915_WRITE(GEN8_##type##_IMR, 0xffffffff);	\ | ||||
| 	I915_WRITE(GEN8_##type##_IER, 0);		\ | ||||
| 	I915_WRITE(GEN8_##type##_IIR, 0xffffffff);	\ | ||||
| 	POSTING_READ(GEN8_##type##_IIR);		\ | ||||
| 	I915_WRITE(GEN8_##type##_IIR, 0xffffffff);	\ | ||||
| } while (0) | ||||
| 
 | ||||
| 	GEN8_IRQ_FINI_NDX(GT, 0); | ||||
| 	GEN8_IRQ_FINI_NDX(GT, 1); | ||||
| 	GEN8_IRQ_FINI_NDX(GT, 2); | ||||
| 	GEN8_IRQ_FINI_NDX(GT, 3); | ||||
| 
 | ||||
| 	GEN8_IRQ_FINI(PCU); | ||||
| 
 | ||||
| #undef GEN8_IRQ_FINI | ||||
| #undef GEN8_IRQ_FINI_NDX | ||||
| 	GEN5_IRQ_RESET(GEN8_PCU_); | ||||
| 
 | ||||
| 	I915_WRITE(PORT_HOTPLUG_EN, 0); | ||||
| 	I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); | ||||
|  | @ -3659,10 +3626,7 @@ do {							\ | |||
| 	for_each_pipe(dev_priv, pipe) | ||||
| 		I915_WRITE(PIPESTAT(pipe), 0xffff); | ||||
| 
 | ||||
| 	I915_WRITE(VLV_IMR, 0xffffffff); | ||||
| 	I915_WRITE(VLV_IER, 0x0); | ||||
| 	I915_WRITE(VLV_IIR, 0xffffffff); | ||||
| 	POSTING_READ(VLV_IIR); | ||||
| 	GEN5_IRQ_RESET(VLV_); | ||||
| } | ||||
| 
 | ||||
| static void ironlake_irq_uninstall(struct drm_device *dev) | ||||
|  |  | |||
|  | @ -4102,6 +4102,41 @@ enum punit_power_well { | |||
| #define I965_CURSOR_MAX_WM	32 | ||||
| #define I965_CURSOR_DFT_WM	8 | ||||
| 
 | ||||
| /* Watermark register definitions for SKL */ | ||||
| #define CUR_WM_A_0		0x70140 | ||||
| #define CUR_WM_B_0		0x71140 | ||||
| #define PLANE_WM_1_A_0		0x70240 | ||||
| #define PLANE_WM_1_B_0		0x71240 | ||||
| #define PLANE_WM_2_A_0		0x70340 | ||||
| #define PLANE_WM_2_B_0		0x71340 | ||||
| #define PLANE_WM_TRANS_1_A_0	0x70268 | ||||
| #define PLANE_WM_TRANS_1_B_0	0x71268 | ||||
| #define PLANE_WM_TRANS_2_A_0	0x70368 | ||||
| #define PLANE_WM_TRANS_2_B_0	0x71368 | ||||
| #define CUR_WM_TRANS_A_0	0x70168 | ||||
| #define CUR_WM_TRANS_B_0	0x71168 | ||||
| #define   PLANE_WM_EN		(1 << 31) | ||||
| #define   PLANE_WM_LINES_SHIFT	14 | ||||
| #define   PLANE_WM_LINES_MASK	0x1f | ||||
| #define   PLANE_WM_BLOCKS_MASK	0x3ff | ||||
| 
 | ||||
| #define CUR_WM_0(pipe) _PIPE(pipe, CUR_WM_A_0, CUR_WM_B_0) | ||||
| #define CUR_WM(pipe, level) (CUR_WM_0(pipe) + ((4) * (level))) | ||||
| #define CUR_WM_TRANS(pipe) _PIPE(pipe, CUR_WM_TRANS_A_0, CUR_WM_TRANS_B_0) | ||||
| 
 | ||||
| #define _PLANE_WM_1(pipe) _PIPE(pipe, PLANE_WM_1_A_0, PLANE_WM_1_B_0) | ||||
| #define _PLANE_WM_2(pipe) _PIPE(pipe, PLANE_WM_2_A_0, PLANE_WM_2_B_0) | ||||
| #define _PLANE_WM_BASE(pipe, plane)	\ | ||||
| 			_PLANE(plane, _PLANE_WM_1(pipe), _PLANE_WM_2(pipe)) | ||||
| #define PLANE_WM(pipe, plane, level)	\ | ||||
| 			(_PLANE_WM_BASE(pipe, plane) + ((4) * (level))) | ||||
| #define _PLANE_WM_TRANS_1(pipe)	\ | ||||
| 			_PIPE(pipe, PLANE_WM_TRANS_1_A_0, PLANE_WM_TRANS_1_B_0) | ||||
| #define _PLANE_WM_TRANS_2(pipe)	\ | ||||
| 			_PIPE(pipe, PLANE_WM_TRANS_2_A_0, PLANE_WM_TRANS_2_B_0) | ||||
| #define PLANE_WM_TRANS(pipe, plane)	\ | ||||
| 		_PLANE(plane, _PLANE_WM_TRANS_1(pipe), _PLANE_WM_TRANS_2(pipe)) | ||||
| 
 | ||||
| /* define the Watermark register on Ironlake */ | ||||
| #define WM0_PIPEA_ILK		0x45100 | ||||
| #define  WM0_PIPE_PLANE_MASK	(0xffff<<16) | ||||
|  | @ -4272,9 +4307,11 @@ enum punit_power_well { | |||
| #define   DISPPLANE_NO_LINE_DOUBLE		0 | ||||
| #define   DISPPLANE_STEREO_POLARITY_FIRST	0 | ||||
| #define   DISPPLANE_STEREO_POLARITY_SECOND	(1<<18) | ||||
| #define   DISPPLANE_ALPHA_PREMULTIPLY		(1<<16) /* CHV pipe B */ | ||||
| #define   DISPPLANE_ROTATE_180			(1<<15) | ||||
| #define   DISPPLANE_TRICKLE_FEED_DISABLE	(1<<14) /* Ironlake */ | ||||
| #define   DISPPLANE_TILED			(1<<10) | ||||
| #define   DISPPLANE_MIRROR			(1<<8) /* CHV pipe B */ | ||||
| #define _DSPAADDR				0x70184 | ||||
| #define _DSPASTRIDE				0x70188 | ||||
| #define _DSPAPOS				0x7018C /* reserved */ | ||||
|  | @ -4295,6 +4332,24 @@ enum punit_power_well { | |||
| #define DSPOFFSET(plane) _PIPE2(plane, _DSPAOFFSET) | ||||
| #define DSPSURFLIVE(plane) _PIPE2(plane, _DSPASURFLIVE) | ||||
| 
 | ||||
| /* CHV pipe B blender and primary plane */ | ||||
| #define _CHV_BLEND_A		0x60a00 | ||||
| #define   CHV_BLEND_LEGACY		(0<<30) | ||||
| #define   CHV_BLEND_ANDROID		(1<<30) | ||||
| #define   CHV_BLEND_MPO			(2<<30) | ||||
| #define   CHV_BLEND_MASK		(3<<30) | ||||
| #define _CHV_CANVAS_A		0x60a04 | ||||
| #define _PRIMPOS_A		0x60a08 | ||||
| #define _PRIMSIZE_A		0x60a0c | ||||
| #define _PRIMCNSTALPHA_A	0x60a10 | ||||
| #define   PRIM_CONST_ALPHA_ENABLE	(1<<31) | ||||
| 
 | ||||
| #define CHV_BLEND(pipe) _TRANSCODER2(pipe, _CHV_BLEND_A) | ||||
| #define CHV_CANVAS(pipe) _TRANSCODER2(pipe, _CHV_CANVAS_A) | ||||
| #define PRIMPOS(plane) _TRANSCODER2(plane, _PRIMPOS_A) | ||||
| #define PRIMSIZE(plane) _TRANSCODER2(plane, _PRIMSIZE_A) | ||||
| #define PRIMCNSTALPHA(plane) _TRANSCODER2(plane, _PRIMCNSTALPHA_A) | ||||
| 
 | ||||
| /* Display/Sprite base address macros */ | ||||
| #define DISP_BASEADDR_MASK	(0xfffff000) | ||||
| #define I915_LO_DISPBASE(val)	(val & ~DISP_BASEADDR_MASK) | ||||
|  | @ -4496,6 +4551,7 @@ enum punit_power_well { | |||
| #define   SP_FORMAT_RGBA1010102		(9<<26) | ||||
| #define   SP_FORMAT_RGBX8888		(0xe<<26) | ||||
| #define   SP_FORMAT_RGBA8888		(0xf<<26) | ||||
| #define   SP_ALPHA_PREMULTIPLY		(1<<23) /* CHV pipe B */ | ||||
| #define   SP_SOURCE_KEY			(1<<22) | ||||
| #define   SP_YUV_BYTE_ORDER_MASK	(3<<16) | ||||
| #define   SP_YUV_ORDER_YUYV		(0<<16) | ||||
|  | @ -4504,6 +4560,7 @@ enum punit_power_well { | |||
| #define   SP_YUV_ORDER_VYUY		(3<<16) | ||||
| #define   SP_ROTATE_180			(1<<15) | ||||
| #define   SP_TILED			(1<<10) | ||||
| #define   SP_MIRROR			(1<<8) /* CHV pipe B */ | ||||
| #define _SPALINOFF		(VLV_DISPLAY_BASE + 0x72184) | ||||
| #define _SPASTRIDE		(VLV_DISPLAY_BASE + 0x72188) | ||||
| #define _SPAPOS			(VLV_DISPLAY_BASE + 0x7218c) | ||||
|  | @ -4514,6 +4571,7 @@ enum punit_power_well { | |||
| #define _SPAKEYMAXVAL		(VLV_DISPLAY_BASE + 0x721a0) | ||||
| #define _SPATILEOFF		(VLV_DISPLAY_BASE + 0x721a4) | ||||
| #define _SPACONSTALPHA		(VLV_DISPLAY_BASE + 0x721a8) | ||||
| #define   SP_CONST_ALPHA_ENABLE		(1<<31) | ||||
| #define _SPAGAMC		(VLV_DISPLAY_BASE + 0x721f4) | ||||
| 
 | ||||
| #define _SPBCNTR		(VLV_DISPLAY_BASE + 0x72280) | ||||
|  | @ -4542,6 +4600,39 @@ enum punit_power_well { | |||
| #define SPCONSTALPHA(pipe, plane) _PIPE(pipe * 2 + plane, _SPACONSTALPHA, _SPBCONSTALPHA) | ||||
| #define SPGAMC(pipe, plane) _PIPE(pipe * 2 + plane, _SPAGAMC, _SPBGAMC) | ||||
| 
 | ||||
| /*
 | ||||
|  * CHV pipe B sprite CSC | ||||
|  * | ||||
|  * |cr|   |c0 c1 c2|   |cr + cr_ioff|   |cr_ooff| | ||||
|  * |yg| = |c3 c4 c5| x |yg + yg_ioff| + |yg_ooff| | ||||
|  * |cb|   |c6 c7 c8|   |cb + cr_ioff|   |cb_ooff| | ||||
|  */ | ||||
| #define SPCSCYGOFF(sprite)	(VLV_DISPLAY_BASE + 0x6d900 + (sprite) * 0x1000) | ||||
| #define SPCSCCBOFF(sprite)	(VLV_DISPLAY_BASE + 0x6d904 + (sprite) * 0x1000) | ||||
| #define SPCSCCROFF(sprite)	(VLV_DISPLAY_BASE + 0x6d908 + (sprite) * 0x1000) | ||||
| #define  SPCSC_OOFF(x)		(((x) & 0x7ff) << 16) /* s11 */ | ||||
| #define  SPCSC_IOFF(x)		(((x) & 0x7ff) << 0) /* s11 */ | ||||
| 
 | ||||
| #define SPCSCC01(sprite)	(VLV_DISPLAY_BASE + 0x6d90c + (sprite) * 0x1000) | ||||
| #define SPCSCC23(sprite)	(VLV_DISPLAY_BASE + 0x6d910 + (sprite) * 0x1000) | ||||
| #define SPCSCC45(sprite)	(VLV_DISPLAY_BASE + 0x6d914 + (sprite) * 0x1000) | ||||
| #define SPCSCC67(sprite)	(VLV_DISPLAY_BASE + 0x6d918 + (sprite) * 0x1000) | ||||
| #define SPCSCC8(sprite)		(VLV_DISPLAY_BASE + 0x6d91c + (sprite) * 0x1000) | ||||
| #define  SPCSC_C1(x)		(((x) & 0x7fff) << 16) /* s3.12 */ | ||||
| #define  SPCSC_C0(x)		(((x) & 0x7fff) << 0) /* s3.12 */ | ||||
| 
 | ||||
| #define SPCSCYGICLAMP(sprite)	(VLV_DISPLAY_BASE + 0x6d920 + (sprite) * 0x1000) | ||||
| #define SPCSCCBICLAMP(sprite)	(VLV_DISPLAY_BASE + 0x6d924 + (sprite) * 0x1000) | ||||
| #define SPCSCCRICLAMP(sprite)	(VLV_DISPLAY_BASE + 0x6d928 + (sprite) * 0x1000) | ||||
| #define  SPCSC_IMAX(x)		(((x) & 0x7ff) << 16) /* s11 */ | ||||
| #define  SPCSC_IMIN(x)		(((x) & 0x7ff) << 0) /* s11 */ | ||||
| 
 | ||||
| #define SPCSCYGOCLAMP(sprite)	(VLV_DISPLAY_BASE + 0x6d92c + (sprite) * 0x1000) | ||||
| #define SPCSCCBOCLAMP(sprite)	(VLV_DISPLAY_BASE + 0x6d930 + (sprite) * 0x1000) | ||||
| #define SPCSCCROCLAMP(sprite)	(VLV_DISPLAY_BASE + 0x6d934 + (sprite) * 0x1000) | ||||
| #define  SPCSC_OMAX(x)		((x) << 16) /* u10 */ | ||||
| #define  SPCSC_OMIN(x)		((x) << 0) /* u10 */ | ||||
| 
 | ||||
| /* Skylake plane registers */ | ||||
| 
 | ||||
| #define _PLANE_CTL_1_A				0x70180 | ||||
|  | @ -4605,6 +4696,8 @@ enum punit_power_well { | |||
| #define _PLANE_KEYMSK_2_A			0x70298 | ||||
| #define _PLANE_KEYMAX_1_A			0x701a0 | ||||
| #define _PLANE_KEYMAX_2_A			0x702a0 | ||||
| #define _PLANE_BUF_CFG_1_A			0x7027c | ||||
| #define _PLANE_BUF_CFG_2_A			0x7037c | ||||
| 
 | ||||
| #define _PLANE_CTL_1_B				0x71180 | ||||
| #define _PLANE_CTL_2_B				0x71280 | ||||
|  | @ -4682,6 +4775,20 @@ enum punit_power_well { | |||
| #define PLANE_KEYMAX(pipe, plane)	\ | ||||
| 	_PLANE(plane, _PLANE_KEYMAX_1(pipe), _PLANE_KEYMAX_2(pipe)) | ||||
| 
 | ||||
| #define _PLANE_BUF_CFG_1_B			0x7127c | ||||
| #define _PLANE_BUF_CFG_2_B			0x7137c | ||||
| #define _PLANE_BUF_CFG_1(pipe)	\ | ||||
| 	_PIPE(pipe, _PLANE_BUF_CFG_1_A, _PLANE_BUF_CFG_1_B) | ||||
| #define _PLANE_BUF_CFG_2(pipe)	\ | ||||
| 	_PIPE(pipe, _PLANE_BUF_CFG_2_A, _PLANE_BUF_CFG_2_B) | ||||
| #define PLANE_BUF_CFG(pipe, plane)	\ | ||||
| 	_PLANE(plane, _PLANE_BUF_CFG_1(pipe), _PLANE_BUF_CFG_2(pipe)) | ||||
| 
 | ||||
| /* SKL new cursor registers */ | ||||
| #define _CUR_BUF_CFG_A				0x7017c | ||||
| #define _CUR_BUF_CFG_B				0x7117c | ||||
| #define CUR_BUF_CFG(pipe)	_PIPE(pipe, _CUR_BUF_CFG_A, _CUR_BUF_CFG_B) | ||||
| 
 | ||||
| /* VBIOS regs */ | ||||
| #define VGACNTRL		0x71400 | ||||
| # define VGA_DISP_DISABLE			(1 << 31) | ||||
|  | @ -5726,6 +5833,12 @@ enum punit_power_well { | |||
| #define   VLV_GTLC_PW_MEDIA_STATUS_MASK		(1 << 5) | ||||
| #define   VLV_GTLC_PW_RENDER_STATUS_MASK	(1 << 7) | ||||
| #define  FORCEWAKE_MT				0xa188 /* multi-threaded */ | ||||
| #define  FORCEWAKE_MEDIA_GEN9			0xa270 | ||||
| #define  FORCEWAKE_RENDER_GEN9			0xa278 | ||||
| #define  FORCEWAKE_BLITTER_GEN9			0xa188 | ||||
| #define  FORCEWAKE_ACK_MEDIA_GEN9		0x0D88 | ||||
| #define  FORCEWAKE_ACK_RENDER_GEN9		0x0D84 | ||||
| #define  FORCEWAKE_ACK_BLITTER_GEN9		0x130044 | ||||
| #define   FORCEWAKE_KERNEL			0x1 | ||||
| #define   FORCEWAKE_USER			0x2 | ||||
| #define  FORCEWAKE_MT_ACK			0x130040 | ||||
|  | @ -5901,6 +6014,13 @@ enum punit_power_well { | |||
| #define   GEN6_PCODE_FREQ_IA_RATIO_SHIFT	8 | ||||
| #define   GEN6_PCODE_FREQ_RING_RATIO_SHIFT	16 | ||||
| 
 | ||||
| #define GEN9_PCODE_DATA1			0x13812C | ||||
| #define   GEN9_PCODE_READ_MEM_LATENCY		0x6 | ||||
| #define   GEN9_MEM_LATENCY_LEVEL_MASK		0xFF | ||||
| #define   GEN9_MEM_LATENCY_LEVEL_1_5_SHIFT	8 | ||||
| #define   GEN9_MEM_LATENCY_LEVEL_2_6_SHIFT	16 | ||||
| #define   GEN9_MEM_LATENCY_LEVEL_3_7_SHIFT	24 | ||||
| 
 | ||||
| #define GEN6_GT_CORE_STATUS		0x138060 | ||||
| #define   GEN6_CORE_CPD_STATE_MASK	(7<<4) | ||||
| #define   GEN6_RCn_MASK			7 | ||||
|  | @ -5955,6 +6075,7 @@ enum punit_power_well { | |||
| #define   GEN8_CENTROID_PIXEL_OPT_DIS	(1<<8) | ||||
| #define   GEN8_SAMPLER_POWER_BYPASS_DIS	(1<<1) | ||||
| 
 | ||||
| /* Audio */ | ||||
| #define G4X_AUD_VID_DID			(dev_priv->info.display_mmio_offset + 0x62020) | ||||
| #define   INTEL_AUDIO_DEVCL		0x808629FB | ||||
| #define   INTEL_AUDIO_DEVBLC		0x80862801 | ||||
|  | @ -5963,49 +6084,49 @@ enum punit_power_well { | |||
| #define G4X_AUD_CNTL_ST			0x620B4 | ||||
| #define   G4X_ELDV_DEVCL_DEVBLC		(1 << 13) | ||||
| #define   G4X_ELDV_DEVCTG		(1 << 14) | ||||
| #define G4X_ELD_ADDR			(0xf << 5) | ||||
| #define   G4X_ELD_ADDR_MASK		(0xf << 5) | ||||
| #define   G4X_ELD_ACK			(1 << 4) | ||||
| #define G4X_HDMIW_HDMIEDID		0x6210C | ||||
| 
 | ||||
| #define IBX_HDMIW_HDMIEDID_A		0xE2050 | ||||
| #define IBX_HDMIW_HDMIEDID_B		0xE2150 | ||||
| #define _IBX_HDMIW_HDMIEDID_A		0xE2050 | ||||
| #define _IBX_HDMIW_HDMIEDID_B		0xE2150 | ||||
| #define IBX_HDMIW_HDMIEDID(pipe) _PIPE(pipe, \ | ||||
| 					IBX_HDMIW_HDMIEDID_A, \ | ||||
| 					IBX_HDMIW_HDMIEDID_B) | ||||
| #define IBX_AUD_CNTL_ST_A		0xE20B4 | ||||
| #define IBX_AUD_CNTL_ST_B		0xE21B4 | ||||
| 					_IBX_HDMIW_HDMIEDID_A, \ | ||||
| 					_IBX_HDMIW_HDMIEDID_B) | ||||
| #define _IBX_AUD_CNTL_ST_A		0xE20B4 | ||||
| #define _IBX_AUD_CNTL_ST_B		0xE21B4 | ||||
| #define IBX_AUD_CNTL_ST(pipe) _PIPE(pipe, \ | ||||
| 					IBX_AUD_CNTL_ST_A, \ | ||||
| 					IBX_AUD_CNTL_ST_B) | ||||
| #define IBX_ELD_BUFFER_SIZE		(0x1f << 10) | ||||
| #define IBX_ELD_ADDRESS			(0x1f << 5) | ||||
| 					_IBX_AUD_CNTL_ST_A, \ | ||||
| 					_IBX_AUD_CNTL_ST_B) | ||||
| #define   IBX_ELD_BUFFER_SIZE_MASK	(0x1f << 10) | ||||
| #define   IBX_ELD_ADDRESS_MASK		(0x1f << 5) | ||||
| #define   IBX_ELD_ACK			(1 << 4) | ||||
| #define IBX_AUD_CNTL_ST2		0xE20C0 | ||||
| #define IBX_ELD_VALIDB			(1 << 0) | ||||
| #define IBX_CP_READYB			(1 << 1) | ||||
| #define   IBX_CP_READY(port)		((1 << 1) << (((port) - 1) * 4)) | ||||
| #define   IBX_ELD_VALID(port)		((1 << 0) << (((port) - 1) * 4)) | ||||
| 
 | ||||
| #define CPT_HDMIW_HDMIEDID_A		0xE5050 | ||||
| #define CPT_HDMIW_HDMIEDID_B		0xE5150 | ||||
| #define _CPT_HDMIW_HDMIEDID_A		0xE5050 | ||||
| #define _CPT_HDMIW_HDMIEDID_B		0xE5150 | ||||
| #define CPT_HDMIW_HDMIEDID(pipe) _PIPE(pipe, \ | ||||
| 					CPT_HDMIW_HDMIEDID_A, \ | ||||
| 					CPT_HDMIW_HDMIEDID_B) | ||||
| #define CPT_AUD_CNTL_ST_A		0xE50B4 | ||||
| #define CPT_AUD_CNTL_ST_B		0xE51B4 | ||||
| 					_CPT_HDMIW_HDMIEDID_A, \ | ||||
| 					_CPT_HDMIW_HDMIEDID_B) | ||||
| #define _CPT_AUD_CNTL_ST_A		0xE50B4 | ||||
| #define _CPT_AUD_CNTL_ST_B		0xE51B4 | ||||
| #define CPT_AUD_CNTL_ST(pipe) _PIPE(pipe, \ | ||||
| 					CPT_AUD_CNTL_ST_A, \ | ||||
| 					CPT_AUD_CNTL_ST_B) | ||||
| 					_CPT_AUD_CNTL_ST_A, \ | ||||
| 					_CPT_AUD_CNTL_ST_B) | ||||
| #define CPT_AUD_CNTRL_ST2		0xE50C0 | ||||
| 
 | ||||
| #define VLV_HDMIW_HDMIEDID_A		(VLV_DISPLAY_BASE + 0x62050) | ||||
| #define VLV_HDMIW_HDMIEDID_B		(VLV_DISPLAY_BASE + 0x62150) | ||||
| #define _VLV_HDMIW_HDMIEDID_A		(VLV_DISPLAY_BASE + 0x62050) | ||||
| #define _VLV_HDMIW_HDMIEDID_B		(VLV_DISPLAY_BASE + 0x62150) | ||||
| #define VLV_HDMIW_HDMIEDID(pipe) _PIPE(pipe, \ | ||||
| 					VLV_HDMIW_HDMIEDID_A, \ | ||||
| 					VLV_HDMIW_HDMIEDID_B) | ||||
| #define VLV_AUD_CNTL_ST_A		(VLV_DISPLAY_BASE + 0x620B4) | ||||
| #define VLV_AUD_CNTL_ST_B		(VLV_DISPLAY_BASE + 0x621B4) | ||||
| 					_VLV_HDMIW_HDMIEDID_A, \ | ||||
| 					_VLV_HDMIW_HDMIEDID_B) | ||||
| #define _VLV_AUD_CNTL_ST_A		(VLV_DISPLAY_BASE + 0x620B4) | ||||
| #define _VLV_AUD_CNTL_ST_B		(VLV_DISPLAY_BASE + 0x621B4) | ||||
| #define VLV_AUD_CNTL_ST(pipe) _PIPE(pipe, \ | ||||
| 					VLV_AUD_CNTL_ST_A, \ | ||||
| 					VLV_AUD_CNTL_ST_B) | ||||
| 					_VLV_AUD_CNTL_ST_A, \ | ||||
| 					_VLV_AUD_CNTL_ST_B) | ||||
| #define VLV_AUD_CNTL_ST2		(VLV_DISPLAY_BASE + 0x620C0) | ||||
| 
 | ||||
| /* These are the 4 32-bit write offset registers for each stream
 | ||||
|  | @ -6014,28 +6135,28 @@ enum punit_power_well { | |||
|  */ | ||||
| #define GEN7_SO_WRITE_OFFSET(n)		(0x5280 + (n) * 4) | ||||
| 
 | ||||
| #define IBX_AUD_CONFIG_A			0xe2000 | ||||
| #define IBX_AUD_CONFIG_B			0xe2100 | ||||
| #define _IBX_AUD_CONFIG_A		0xe2000 | ||||
| #define _IBX_AUD_CONFIG_B		0xe2100 | ||||
| #define IBX_AUD_CFG(pipe) _PIPE(pipe, \ | ||||
| 					IBX_AUD_CONFIG_A, \ | ||||
| 					IBX_AUD_CONFIG_B) | ||||
| #define CPT_AUD_CONFIG_A			0xe5000 | ||||
| #define CPT_AUD_CONFIG_B			0xe5100 | ||||
| 					_IBX_AUD_CONFIG_A, \ | ||||
| 					_IBX_AUD_CONFIG_B) | ||||
| #define _CPT_AUD_CONFIG_A		0xe5000 | ||||
| #define _CPT_AUD_CONFIG_B		0xe5100 | ||||
| #define CPT_AUD_CFG(pipe) _PIPE(pipe, \ | ||||
| 					CPT_AUD_CONFIG_A, \ | ||||
| 					CPT_AUD_CONFIG_B) | ||||
| #define VLV_AUD_CONFIG_A		(VLV_DISPLAY_BASE + 0x62000) | ||||
| #define VLV_AUD_CONFIG_B		(VLV_DISPLAY_BASE + 0x62100) | ||||
| 					_CPT_AUD_CONFIG_A, \ | ||||
| 					_CPT_AUD_CONFIG_B) | ||||
| #define _VLV_AUD_CONFIG_A		(VLV_DISPLAY_BASE + 0x62000) | ||||
| #define _VLV_AUD_CONFIG_B		(VLV_DISPLAY_BASE + 0x62100) | ||||
| #define VLV_AUD_CFG(pipe) _PIPE(pipe, \ | ||||
| 					VLV_AUD_CONFIG_A, \ | ||||
| 					VLV_AUD_CONFIG_B) | ||||
| 					_VLV_AUD_CONFIG_A, \ | ||||
| 					_VLV_AUD_CONFIG_B) | ||||
| 
 | ||||
| #define   AUD_CONFIG_N_VALUE_INDEX		(1 << 29) | ||||
| #define   AUD_CONFIG_N_PROG_ENABLE		(1 << 28) | ||||
| #define   AUD_CONFIG_UPPER_N_SHIFT		20 | ||||
| #define   AUD_CONFIG_UPPER_N_VALUE		(0xff << 20) | ||||
| #define   AUD_CONFIG_UPPER_N_MASK		(0xff << 20) | ||||
| #define   AUD_CONFIG_LOWER_N_SHIFT		4 | ||||
| #define   AUD_CONFIG_LOWER_N_VALUE		(0xfff << 4) | ||||
| #define   AUD_CONFIG_LOWER_N_MASK		(0xfff << 4) | ||||
| #define   AUD_CONFIG_PIXEL_CLOCK_HDMI_SHIFT	16 | ||||
| #define   AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK	(0xf << 16) | ||||
| #define   AUD_CONFIG_PIXEL_CLOCK_HDMI_25175	(0 << 16) | ||||
|  | @ -6051,52 +6172,44 @@ enum punit_power_well { | |||
| #define   AUD_CONFIG_DISABLE_NCTS		(1 << 3) | ||||
| 
 | ||||
| /* HSW Audio */ | ||||
| #define   HSW_AUD_CONFIG_A		0x65000 /* Audio Configuration Transcoder A */ | ||||
| #define   HSW_AUD_CONFIG_B		0x65100 /* Audio Configuration Transcoder B */ | ||||
| #define _HSW_AUD_CONFIG_A		0x65000 | ||||
| #define _HSW_AUD_CONFIG_B		0x65100 | ||||
| #define HSW_AUD_CFG(pipe) _PIPE(pipe, \ | ||||
| 					HSW_AUD_CONFIG_A, \ | ||||
| 					HSW_AUD_CONFIG_B) | ||||
| 					_HSW_AUD_CONFIG_A, \ | ||||
| 					_HSW_AUD_CONFIG_B) | ||||
| 
 | ||||
| #define   HSW_AUD_MISC_CTRL_A		0x65010 /* Audio Misc Control Convert 1 */ | ||||
| #define   HSW_AUD_MISC_CTRL_B		0x65110 /* Audio Misc Control Convert 2 */ | ||||
| #define _HSW_AUD_MISC_CTRL_A		0x65010 | ||||
| #define _HSW_AUD_MISC_CTRL_B		0x65110 | ||||
| #define HSW_AUD_MISC_CTRL(pipe) _PIPE(pipe, \ | ||||
| 					HSW_AUD_MISC_CTRL_A, \ | ||||
| 					HSW_AUD_MISC_CTRL_B) | ||||
| 					_HSW_AUD_MISC_CTRL_A, \ | ||||
| 					_HSW_AUD_MISC_CTRL_B) | ||||
| 
 | ||||
| #define   HSW_AUD_DIP_ELD_CTRL_ST_A	0x650b4 /* Audio DIP and ELD Control State Transcoder A */ | ||||
| #define   HSW_AUD_DIP_ELD_CTRL_ST_B	0x651b4 /* Audio DIP and ELD Control State Transcoder B */ | ||||
| #define _HSW_AUD_DIP_ELD_CTRL_ST_A	0x650b4 | ||||
| #define _HSW_AUD_DIP_ELD_CTRL_ST_B	0x651b4 | ||||
| #define HSW_AUD_DIP_ELD_CTRL(pipe) _PIPE(pipe, \ | ||||
| 					HSW_AUD_DIP_ELD_CTRL_ST_A, \ | ||||
| 					HSW_AUD_DIP_ELD_CTRL_ST_B) | ||||
| 					_HSW_AUD_DIP_ELD_CTRL_ST_A, \ | ||||
| 					_HSW_AUD_DIP_ELD_CTRL_ST_B) | ||||
| 
 | ||||
| /* Audio Digital Converter */ | ||||
| #define   HSW_AUD_DIG_CNVT_1		0x65080 /* Audio Converter 1 */ | ||||
| #define   HSW_AUD_DIG_CNVT_2		0x65180 /* Audio Converter 1 */ | ||||
| #define _HSW_AUD_DIG_CNVT_1		0x65080 | ||||
| #define _HSW_AUD_DIG_CNVT_2		0x65180 | ||||
| #define AUD_DIG_CNVT(pipe) _PIPE(pipe, \ | ||||
| 					HSW_AUD_DIG_CNVT_1, \ | ||||
| 					HSW_AUD_DIG_CNVT_2) | ||||
| 					_HSW_AUD_DIG_CNVT_1, \ | ||||
| 					_HSW_AUD_DIG_CNVT_2) | ||||
| #define DIP_PORT_SEL_MASK		0x3 | ||||
| 
 | ||||
| #define   HSW_AUD_EDID_DATA_A		0x65050 | ||||
| #define   HSW_AUD_EDID_DATA_B		0x65150 | ||||
| #define _HSW_AUD_EDID_DATA_A		0x65050 | ||||
| #define _HSW_AUD_EDID_DATA_B		0x65150 | ||||
| #define HSW_AUD_EDID_DATA(pipe) _PIPE(pipe, \ | ||||
| 					HSW_AUD_EDID_DATA_A, \ | ||||
| 					HSW_AUD_EDID_DATA_B) | ||||
| 					_HSW_AUD_EDID_DATA_A, \ | ||||
| 					_HSW_AUD_EDID_DATA_B) | ||||
| 
 | ||||
| #define   HSW_AUD_PIPE_CONV_CFG		0x6507c /* Audio pipe and converter configs */ | ||||
| #define   HSW_AUD_PIN_ELD_CP_VLD	0x650c0 /* Audio ELD and CP Ready Status */ | ||||
| #define   AUDIO_INACTIVE_C		(1<<11) | ||||
| #define   AUDIO_INACTIVE_B		(1<<7) | ||||
| #define   AUDIO_INACTIVE_A		(1<<3) | ||||
| #define   AUDIO_OUTPUT_ENABLE_A		(1<<2) | ||||
| #define   AUDIO_OUTPUT_ENABLE_B		(1<<6) | ||||
| #define   AUDIO_OUTPUT_ENABLE_C		(1<<10) | ||||
| #define   AUDIO_ELD_VALID_A		(1<<0) | ||||
| #define   AUDIO_ELD_VALID_B		(1<<4) | ||||
| #define   AUDIO_ELD_VALID_C		(1<<8) | ||||
| #define   AUDIO_CP_READY_A		(1<<1) | ||||
| #define   AUDIO_CP_READY_B		(1<<5) | ||||
| #define   AUDIO_CP_READY_C		(1<<9) | ||||
| #define HSW_AUD_PIPE_CONV_CFG		0x6507c | ||||
| #define HSW_AUD_PIN_ELD_CP_VLD		0x650c0 | ||||
| #define   AUDIO_INACTIVE(trans)		((1 << 3) << ((trans) * 4)) | ||||
| #define   AUDIO_OUTPUT_ENABLE(trans)	((1 << 2) << ((trans) * 4)) | ||||
| #define   AUDIO_CP_READY(trans)		((1 << 1) << ((trans) * 4)) | ||||
| #define   AUDIO_ELD_VALID(trans)	((1 << 0) << ((trans) * 4)) | ||||
| 
 | ||||
| /* HSW Power Wells */ | ||||
| #define HSW_PWR_WELL_BIOS			0x45400 /* CTL1 */ | ||||
|  |  | |||
							
								
								
									
										462
									
								
								drivers/gpu/drm/i915/intel_audio.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										462
									
								
								drivers/gpu/drm/i915/intel_audio.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,462 @@ | |||
| /*
 | ||||
|  * Copyright © 2014 Intel Corporation | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a | ||||
|  * copy of this software and associated documentation files (the "Software"), | ||||
|  * to deal in the Software without restriction, including without limitation | ||||
|  * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||||
|  * and/or sell copies of the Software, and to permit persons to whom the | ||||
|  * Software is furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice (including the next | ||||
|  * paragraph) shall be included in all copies or substantial portions of the | ||||
|  * Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL | ||||
|  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||||
|  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||||
|  * DEALINGS IN THE SOFTWARE. | ||||
|  */ | ||||
| 
 | ||||
| #include <linux/kernel.h> | ||||
| 
 | ||||
| #include <drm/drmP.h> | ||||
| #include <drm/drm_edid.h> | ||||
| #include "intel_drv.h" | ||||
| #include "i915_drv.h" | ||||
| 
 | ||||
| /**
 | ||||
|  * DOC: High Definition Audio over HDMI and Display Port | ||||
|  * | ||||
|  * The graphics and audio drivers together support High Definition Audio over | ||||
|  * HDMI and Display Port. The audio programming sequences are divided into audio | ||||
|  * codec and controller enable and disable sequences. The graphics driver | ||||
|  * handles the audio codec sequences, while the audio driver handles the audio | ||||
|  * controller sequences. | ||||
|  * | ||||
|  * The disable sequences must be performed before disabling the transcoder or | ||||
|  * port. The enable sequences may only be performed after enabling the | ||||
|  * transcoder and port, and after completed link training. | ||||
|  * | ||||
|  * The codec and controller sequences could be done either parallel or serial, | ||||
|  * but generally the ELDV/PD change in the codec sequence indicates to the audio | ||||
|  * driver that the controller sequence should start. Indeed, most of the | ||||
|  * co-operation between the graphics and audio drivers is handled via audio | ||||
|  * related registers. (The notable exception is the power management, not | ||||
|  * covered here.) | ||||
|  */ | ||||
| 
 | ||||
| static const struct { | ||||
| 	int clock; | ||||
| 	u32 config; | ||||
| } hdmi_audio_clock[] = { | ||||
| 	{ DIV_ROUND_UP(25200 * 1000, 1001), AUD_CONFIG_PIXEL_CLOCK_HDMI_25175 }, | ||||
| 	{ 25200, AUD_CONFIG_PIXEL_CLOCK_HDMI_25200 }, /* default per bspec */ | ||||
| 	{ 27000, AUD_CONFIG_PIXEL_CLOCK_HDMI_27000 }, | ||||
| 	{ 27000 * 1001 / 1000, AUD_CONFIG_PIXEL_CLOCK_HDMI_27027 }, | ||||
| 	{ 54000, AUD_CONFIG_PIXEL_CLOCK_HDMI_54000 }, | ||||
| 	{ 54000 * 1001 / 1000, AUD_CONFIG_PIXEL_CLOCK_HDMI_54054 }, | ||||
| 	{ DIV_ROUND_UP(74250 * 1000, 1001), AUD_CONFIG_PIXEL_CLOCK_HDMI_74176 }, | ||||
| 	{ 74250, AUD_CONFIG_PIXEL_CLOCK_HDMI_74250 }, | ||||
| 	{ DIV_ROUND_UP(148500 * 1000, 1001), AUD_CONFIG_PIXEL_CLOCK_HDMI_148352 }, | ||||
| 	{ 148500, AUD_CONFIG_PIXEL_CLOCK_HDMI_148500 }, | ||||
| }; | ||||
| 
 | ||||
| /* get AUD_CONFIG_PIXEL_CLOCK_HDMI_* value for mode */ | ||||
| static u32 audio_config_hdmi_pixel_clock(struct drm_display_mode *mode) | ||||
| { | ||||
| 	int i; | ||||
| 
 | ||||
| 	for (i = 0; i < ARRAY_SIZE(hdmi_audio_clock); i++) { | ||||
| 		if (mode->clock == hdmi_audio_clock[i].clock) | ||||
| 			break; | ||||
| 	} | ||||
| 
 | ||||
| 	if (i == ARRAY_SIZE(hdmi_audio_clock)) { | ||||
| 		DRM_DEBUG_KMS("HDMI audio pixel clock setting for %d not found, falling back to defaults\n", mode->clock); | ||||
| 		i = 1; | ||||
| 	} | ||||
| 
 | ||||
| 	DRM_DEBUG_KMS("Configuring HDMI audio for pixel clock %d (0x%08x)\n", | ||||
| 		      hdmi_audio_clock[i].clock, | ||||
| 		      hdmi_audio_clock[i].config); | ||||
| 
 | ||||
| 	return hdmi_audio_clock[i].config; | ||||
| } | ||||
| 
 | ||||
| static bool intel_eld_uptodate(struct drm_connector *connector, | ||||
| 			       int reg_eldv, uint32_t bits_eldv, | ||||
| 			       int reg_elda, uint32_t bits_elda, | ||||
| 			       int reg_edid) | ||||
| { | ||||
| 	struct drm_i915_private *dev_priv = connector->dev->dev_private; | ||||
| 	uint8_t *eld = connector->eld; | ||||
| 	uint32_t tmp; | ||||
| 	int i; | ||||
| 
 | ||||
| 	tmp = I915_READ(reg_eldv); | ||||
| 	tmp &= bits_eldv; | ||||
| 
 | ||||
| 	if (!tmp) | ||||
| 		return false; | ||||
| 
 | ||||
| 	tmp = I915_READ(reg_elda); | ||||
| 	tmp &= ~bits_elda; | ||||
| 	I915_WRITE(reg_elda, tmp); | ||||
| 
 | ||||
| 	for (i = 0; i < eld[2]; i++) | ||||
| 		if (I915_READ(reg_edid) != *((uint32_t *)eld + i)) | ||||
| 			return false; | ||||
| 
 | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| static void g4x_audio_codec_disable(struct intel_encoder *encoder) | ||||
| { | ||||
| 	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; | ||||
| 	uint32_t eldv, tmp; | ||||
| 
 | ||||
| 	DRM_DEBUG_KMS("Disable audio codec\n"); | ||||
| 
 | ||||
| 	tmp = I915_READ(G4X_AUD_VID_DID); | ||||
| 	if (tmp == INTEL_AUDIO_DEVBLC || tmp == INTEL_AUDIO_DEVCL) | ||||
| 		eldv = G4X_ELDV_DEVCL_DEVBLC; | ||||
| 	else | ||||
| 		eldv = G4X_ELDV_DEVCTG; | ||||
| 
 | ||||
| 	/* Invalidate ELD */ | ||||
| 	tmp = I915_READ(G4X_AUD_CNTL_ST); | ||||
| 	tmp &= ~eldv; | ||||
| 	I915_WRITE(G4X_AUD_CNTL_ST, tmp); | ||||
| } | ||||
| 
 | ||||
| static void g4x_audio_codec_enable(struct drm_connector *connector, | ||||
| 				   struct intel_encoder *encoder, | ||||
| 				   struct drm_display_mode *mode) | ||||
| { | ||||
| 	struct drm_i915_private *dev_priv = connector->dev->dev_private; | ||||
| 	uint8_t *eld = connector->eld; | ||||
| 	uint32_t eldv; | ||||
| 	uint32_t tmp; | ||||
| 	int len, i; | ||||
| 
 | ||||
| 	DRM_DEBUG_KMS("Enable audio codec, %u bytes ELD\n", eld[2]); | ||||
| 
 | ||||
| 	tmp = I915_READ(G4X_AUD_VID_DID); | ||||
| 	if (tmp == INTEL_AUDIO_DEVBLC || tmp == INTEL_AUDIO_DEVCL) | ||||
| 		eldv = G4X_ELDV_DEVCL_DEVBLC; | ||||
| 	else | ||||
| 		eldv = G4X_ELDV_DEVCTG; | ||||
| 
 | ||||
| 	if (intel_eld_uptodate(connector, | ||||
| 			       G4X_AUD_CNTL_ST, eldv, | ||||
| 			       G4X_AUD_CNTL_ST, G4X_ELD_ADDR_MASK, | ||||
| 			       G4X_HDMIW_HDMIEDID)) | ||||
| 		return; | ||||
| 
 | ||||
| 	tmp = I915_READ(G4X_AUD_CNTL_ST); | ||||
| 	tmp &= ~(eldv | G4X_ELD_ADDR_MASK); | ||||
| 	len = (tmp >> 9) & 0x1f;		/* ELD buffer size */ | ||||
| 	I915_WRITE(G4X_AUD_CNTL_ST, tmp); | ||||
| 
 | ||||
| 	len = min_t(int, eld[2], len); | ||||
| 	DRM_DEBUG_DRIVER("ELD size %d\n", len); | ||||
| 	for (i = 0; i < len; i++) | ||||
| 		I915_WRITE(G4X_HDMIW_HDMIEDID, *((uint32_t *)eld + i)); | ||||
| 
 | ||||
| 	tmp = I915_READ(G4X_AUD_CNTL_ST); | ||||
| 	tmp |= eldv; | ||||
| 	I915_WRITE(G4X_AUD_CNTL_ST, tmp); | ||||
| } | ||||
| 
 | ||||
| static void hsw_audio_codec_disable(struct intel_encoder *encoder) | ||||
| { | ||||
| 	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; | ||||
| 	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); | ||||
| 	enum pipe pipe = intel_crtc->pipe; | ||||
| 	uint32_t tmp; | ||||
| 
 | ||||
| 	DRM_DEBUG_KMS("Disable audio codec on pipe %c\n", pipe_name(pipe)); | ||||
| 
 | ||||
| 	/* Disable timestamps */ | ||||
| 	tmp = I915_READ(HSW_AUD_CFG(pipe)); | ||||
| 	tmp &= ~AUD_CONFIG_N_VALUE_INDEX; | ||||
| 	tmp |= AUD_CONFIG_N_PROG_ENABLE; | ||||
| 	tmp &= ~AUD_CONFIG_UPPER_N_MASK; | ||||
| 	tmp &= ~AUD_CONFIG_LOWER_N_MASK; | ||||
| 	if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DISPLAYPORT)) | ||||
| 		tmp |= AUD_CONFIG_N_VALUE_INDEX; | ||||
| 	I915_WRITE(HSW_AUD_CFG(pipe), tmp); | ||||
| 
 | ||||
| 	/* Invalidate ELD */ | ||||
| 	tmp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD); | ||||
| 	tmp &= ~AUDIO_ELD_VALID(pipe); | ||||
| 	I915_WRITE(HSW_AUD_PIN_ELD_CP_VLD, tmp); | ||||
| } | ||||
| 
 | ||||
| static void hsw_audio_codec_enable(struct drm_connector *connector, | ||||
| 				   struct intel_encoder *encoder, | ||||
| 				   struct drm_display_mode *mode) | ||||
| { | ||||
| 	struct drm_i915_private *dev_priv = connector->dev->dev_private; | ||||
| 	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); | ||||
| 	enum pipe pipe = intel_crtc->pipe; | ||||
| 	const uint8_t *eld = connector->eld; | ||||
| 	uint32_t tmp; | ||||
| 	int len, i; | ||||
| 
 | ||||
| 	DRM_DEBUG_KMS("Enable audio codec on pipe %c, %u bytes ELD\n", | ||||
| 		      pipe_name(pipe), eld[2]); | ||||
| 
 | ||||
| 	/* Enable audio presence detect, invalidate ELD */ | ||||
| 	tmp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD); | ||||
| 	tmp |= AUDIO_OUTPUT_ENABLE(pipe); | ||||
| 	tmp &= ~AUDIO_ELD_VALID(pipe); | ||||
| 	I915_WRITE(HSW_AUD_PIN_ELD_CP_VLD, tmp); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * FIXME: We're supposed to wait for vblank here, but we have vblanks | ||||
| 	 * disabled during the mode set. The proper fix would be to push the | ||||
| 	 * rest of the setup into a vblank work item, queued here, but the | ||||
| 	 * infrastructure is not there yet. | ||||
| 	 */ | ||||
| 
 | ||||
| 	/* Reset ELD write address */ | ||||
| 	tmp = I915_READ(HSW_AUD_DIP_ELD_CTRL(pipe)); | ||||
| 	tmp &= ~IBX_ELD_ADDRESS_MASK; | ||||
| 	I915_WRITE(HSW_AUD_DIP_ELD_CTRL(pipe), tmp); | ||||
| 
 | ||||
| 	/* Up to 84 bytes of hw ELD buffer */ | ||||
| 	len = min_t(int, eld[2], 21); | ||||
| 	for (i = 0; i < len; i++) | ||||
| 		I915_WRITE(HSW_AUD_EDID_DATA(pipe), *((uint32_t *)eld + i)); | ||||
| 
 | ||||
| 	/* ELD valid */ | ||||
| 	tmp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD); | ||||
| 	tmp |= AUDIO_ELD_VALID(pipe); | ||||
| 	I915_WRITE(HSW_AUD_PIN_ELD_CP_VLD, tmp); | ||||
| 
 | ||||
| 	/* Enable timestamps */ | ||||
| 	tmp = I915_READ(HSW_AUD_CFG(pipe)); | ||||
| 	tmp &= ~AUD_CONFIG_N_VALUE_INDEX; | ||||
| 	tmp &= ~AUD_CONFIG_N_PROG_ENABLE; | ||||
| 	tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK; | ||||
| 	if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DISPLAYPORT)) | ||||
| 		tmp |= AUD_CONFIG_N_VALUE_INDEX; | ||||
| 	else | ||||
| 		tmp |= audio_config_hdmi_pixel_clock(mode); | ||||
| 	I915_WRITE(HSW_AUD_CFG(pipe), tmp); | ||||
| } | ||||
| 
 | ||||
| static void ilk_audio_codec_disable(struct intel_encoder *encoder) | ||||
| { | ||||
| 	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; | ||||
| 	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); | ||||
| 	struct intel_digital_port *intel_dig_port = | ||||
| 		enc_to_dig_port(&encoder->base); | ||||
| 	enum port port = intel_dig_port->port; | ||||
| 	enum pipe pipe = intel_crtc->pipe; | ||||
| 	uint32_t tmp, eldv; | ||||
| 	int aud_config; | ||||
| 	int aud_cntrl_st2; | ||||
| 
 | ||||
| 	DRM_DEBUG_KMS("Disable audio codec on port %c, pipe %c\n", | ||||
| 		      port_name(port), pipe_name(pipe)); | ||||
| 
 | ||||
| 	if (HAS_PCH_IBX(dev_priv->dev)) { | ||||
| 		aud_config = IBX_AUD_CFG(pipe); | ||||
| 		aud_cntrl_st2 = IBX_AUD_CNTL_ST2; | ||||
| 	} else if (IS_VALLEYVIEW(dev_priv)) { | ||||
| 		aud_config = VLV_AUD_CFG(pipe); | ||||
| 		aud_cntrl_st2 = VLV_AUD_CNTL_ST2; | ||||
| 	} else { | ||||
| 		aud_config = CPT_AUD_CFG(pipe); | ||||
| 		aud_cntrl_st2 = CPT_AUD_CNTRL_ST2; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Disable timestamps */ | ||||
| 	tmp = I915_READ(aud_config); | ||||
| 	tmp &= ~AUD_CONFIG_N_VALUE_INDEX; | ||||
| 	tmp |= AUD_CONFIG_N_PROG_ENABLE; | ||||
| 	tmp &= ~AUD_CONFIG_UPPER_N_MASK; | ||||
| 	tmp &= ~AUD_CONFIG_LOWER_N_MASK; | ||||
| 	if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DISPLAYPORT)) | ||||
| 		tmp |= AUD_CONFIG_N_VALUE_INDEX; | ||||
| 	I915_WRITE(aud_config, tmp); | ||||
| 
 | ||||
| 	if (WARN_ON(!port)) { | ||||
| 		eldv = IBX_ELD_VALID(PORT_B) | IBX_ELD_VALID(PORT_C) | | ||||
| 			IBX_ELD_VALID(PORT_D); | ||||
| 	} else { | ||||
| 		eldv = IBX_ELD_VALID(port); | ||||
| 	} | ||||
| 
 | ||||
| 	/* Invalidate ELD */ | ||||
| 	tmp = I915_READ(aud_cntrl_st2); | ||||
| 	tmp &= ~eldv; | ||||
| 	I915_WRITE(aud_cntrl_st2, tmp); | ||||
| } | ||||
| 
 | ||||
| static void ilk_audio_codec_enable(struct drm_connector *connector, | ||||
| 				   struct intel_encoder *encoder, | ||||
| 				   struct drm_display_mode *mode) | ||||
| { | ||||
| 	struct drm_i915_private *dev_priv = connector->dev->dev_private; | ||||
| 	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); | ||||
| 	struct intel_digital_port *intel_dig_port = | ||||
| 		enc_to_dig_port(&encoder->base); | ||||
| 	enum port port = intel_dig_port->port; | ||||
| 	enum pipe pipe = intel_crtc->pipe; | ||||
| 	uint8_t *eld = connector->eld; | ||||
| 	uint32_t eldv; | ||||
| 	uint32_t tmp; | ||||
| 	int len, i; | ||||
| 	int hdmiw_hdmiedid; | ||||
| 	int aud_config; | ||||
| 	int aud_cntl_st; | ||||
| 	int aud_cntrl_st2; | ||||
| 
 | ||||
| 	DRM_DEBUG_KMS("Enable audio codec on port %c, pipe %c, %u bytes ELD\n", | ||||
| 		      port_name(port), pipe_name(pipe), eld[2]); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * FIXME: We're supposed to wait for vblank here, but we have vblanks | ||||
| 	 * disabled during the mode set. The proper fix would be to push the | ||||
| 	 * rest of the setup into a vblank work item, queued here, but the | ||||
| 	 * infrastructure is not there yet. | ||||
| 	 */ | ||||
| 
 | ||||
| 	if (HAS_PCH_IBX(connector->dev)) { | ||||
| 		hdmiw_hdmiedid = IBX_HDMIW_HDMIEDID(pipe); | ||||
| 		aud_config = IBX_AUD_CFG(pipe); | ||||
| 		aud_cntl_st = IBX_AUD_CNTL_ST(pipe); | ||||
| 		aud_cntrl_st2 = IBX_AUD_CNTL_ST2; | ||||
| 	} else if (IS_VALLEYVIEW(connector->dev)) { | ||||
| 		hdmiw_hdmiedid = VLV_HDMIW_HDMIEDID(pipe); | ||||
| 		aud_config = VLV_AUD_CFG(pipe); | ||||
| 		aud_cntl_st = VLV_AUD_CNTL_ST(pipe); | ||||
| 		aud_cntrl_st2 = VLV_AUD_CNTL_ST2; | ||||
| 	} else { | ||||
| 		hdmiw_hdmiedid = CPT_HDMIW_HDMIEDID(pipe); | ||||
| 		aud_config = CPT_AUD_CFG(pipe); | ||||
| 		aud_cntl_st = CPT_AUD_CNTL_ST(pipe); | ||||
| 		aud_cntrl_st2 = CPT_AUD_CNTRL_ST2; | ||||
| 	} | ||||
| 
 | ||||
| 	if (WARN_ON(!port)) { | ||||
| 		eldv = IBX_ELD_VALID(PORT_B) | IBX_ELD_VALID(PORT_C) | | ||||
| 			IBX_ELD_VALID(PORT_D); | ||||
| 	} else { | ||||
| 		eldv = IBX_ELD_VALID(port); | ||||
| 	} | ||||
| 
 | ||||
| 	/* Invalidate ELD */ | ||||
| 	tmp = I915_READ(aud_cntrl_st2); | ||||
| 	tmp &= ~eldv; | ||||
| 	I915_WRITE(aud_cntrl_st2, tmp); | ||||
| 
 | ||||
| 	/* Reset ELD write address */ | ||||
| 	tmp = I915_READ(aud_cntl_st); | ||||
| 	tmp &= ~IBX_ELD_ADDRESS_MASK; | ||||
| 	I915_WRITE(aud_cntl_st, tmp); | ||||
| 
 | ||||
| 	/* Up to 84 bytes of hw ELD buffer */ | ||||
| 	len = min_t(int, eld[2], 21); | ||||
| 	for (i = 0; i < len; i++) | ||||
| 		I915_WRITE(hdmiw_hdmiedid, *((uint32_t *)eld + i)); | ||||
| 
 | ||||
| 	/* ELD valid */ | ||||
| 	tmp = I915_READ(aud_cntrl_st2); | ||||
| 	tmp |= eldv; | ||||
| 	I915_WRITE(aud_cntrl_st2, tmp); | ||||
| 
 | ||||
| 	/* Enable timestamps */ | ||||
| 	tmp = I915_READ(aud_config); | ||||
| 	tmp &= ~AUD_CONFIG_N_VALUE_INDEX; | ||||
| 	tmp &= ~AUD_CONFIG_N_PROG_ENABLE; | ||||
| 	tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK; | ||||
| 	if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DISPLAYPORT)) | ||||
| 		tmp |= AUD_CONFIG_N_VALUE_INDEX; | ||||
| 	else | ||||
| 		tmp |= audio_config_hdmi_pixel_clock(mode); | ||||
| 	I915_WRITE(aud_config, tmp); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * intel_audio_codec_enable - Enable the audio codec for HD audio | ||||
|  * @intel_encoder: encoder on which to enable audio | ||||
|  * | ||||
|  * The enable sequences may only be performed after enabling the transcoder and | ||||
|  * port, and after completed link training. | ||||
|  */ | ||||
| void intel_audio_codec_enable(struct intel_encoder *intel_encoder) | ||||
| { | ||||
| 	struct drm_encoder *encoder = &intel_encoder->base; | ||||
| 	struct intel_crtc *crtc = to_intel_crtc(encoder->crtc); | ||||
| 	struct drm_display_mode *mode = &crtc->config.adjusted_mode; | ||||
| 	struct drm_connector *connector; | ||||
| 	struct drm_device *dev = encoder->dev; | ||||
| 	struct drm_i915_private *dev_priv = dev->dev_private; | ||||
| 
 | ||||
| 	connector = drm_select_eld(encoder, mode); | ||||
| 	if (!connector) | ||||
| 		return; | ||||
| 
 | ||||
| 	DRM_DEBUG_DRIVER("ELD on [CONNECTOR:%d:%s], [ENCODER:%d:%s]\n", | ||||
| 			 connector->base.id, | ||||
| 			 connector->name, | ||||
| 			 connector->encoder->base.id, | ||||
| 			 connector->encoder->name); | ||||
| 
 | ||||
| 	/* ELD Conn_Type */ | ||||
| 	connector->eld[5] &= ~(3 << 2); | ||||
| 	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) | ||||
| 		connector->eld[5] |= (1 << 2); | ||||
| 
 | ||||
| 	connector->eld[6] = drm_av_sync_delay(connector, mode) / 2; | ||||
| 
 | ||||
| 	if (dev_priv->display.audio_codec_enable) | ||||
| 		dev_priv->display.audio_codec_enable(connector, intel_encoder, mode); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * intel_audio_codec_disable - Disable the audio codec for HD audio | ||||
|  * @encoder: encoder on which to disable audio | ||||
|  * | ||||
|  * The disable sequences must be performed before disabling the transcoder or | ||||
|  * port. | ||||
|  */ | ||||
| void intel_audio_codec_disable(struct intel_encoder *encoder) | ||||
| { | ||||
| 	struct drm_device *dev = encoder->base.dev; | ||||
| 	struct drm_i915_private *dev_priv = dev->dev_private; | ||||
| 
 | ||||
| 	if (dev_priv->display.audio_codec_disable) | ||||
| 		dev_priv->display.audio_codec_disable(encoder); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * intel_init_audio - Set up chip specific audio functions | ||||
|  * @dev: drm device | ||||
|  */ | ||||
| void intel_init_audio(struct drm_device *dev) | ||||
| { | ||||
| 	struct drm_i915_private *dev_priv = dev->dev_private; | ||||
| 
 | ||||
| 	if (IS_G4X(dev)) { | ||||
| 		dev_priv->display.audio_codec_enable = g4x_audio_codec_enable; | ||||
| 		dev_priv->display.audio_codec_disable = g4x_audio_codec_disable; | ||||
| 	} else if (IS_VALLEYVIEW(dev)) { | ||||
| 		dev_priv->display.audio_codec_enable = ilk_audio_codec_enable; | ||||
| 		dev_priv->display.audio_codec_disable = ilk_audio_codec_disable; | ||||
| 	} else if (IS_HASWELL(dev) || INTEL_INFO(dev)->gen >= 8) { | ||||
| 		dev_priv->display.audio_codec_enable = hsw_audio_codec_enable; | ||||
| 		dev_priv->display.audio_codec_disable = hsw_audio_codec_disable; | ||||
| 	} else if (HAS_PCH_SPLIT(dev)) { | ||||
| 		dev_priv->display.audio_codec_enable = ilk_audio_codec_enable; | ||||
| 		dev_priv->display.audio_codec_disable = ilk_audio_codec_disable; | ||||
| 	} | ||||
| } | ||||
|  | @ -459,6 +459,27 @@ intel_ddi_get_crtc_encoder(struct drm_crtc *crtc) | |||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| static struct intel_encoder * | ||||
| intel_ddi_get_crtc_new_encoder(struct intel_crtc *crtc) | ||||
| { | ||||
| 	struct drm_device *dev = crtc->base.dev; | ||||
| 	struct intel_encoder *intel_encoder, *ret = NULL; | ||||
| 	int num_encoders = 0; | ||||
| 
 | ||||
| 	for_each_intel_encoder(dev, intel_encoder) { | ||||
| 		if (intel_encoder->new_crtc == crtc) { | ||||
| 			ret = intel_encoder; | ||||
| 			num_encoders++; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	WARN(num_encoders != 1, "%d encoders on crtc for pipe %c\n", num_encoders, | ||||
| 	     pipe_name(crtc->pipe)); | ||||
| 
 | ||||
| 	BUG_ON(ret == NULL); | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| #define LC_FREQ 2700 | ||||
| #define LC_FREQ_2K U64_C(LC_FREQ * 2000) | ||||
| 
 | ||||
|  | @ -792,7 +813,7 @@ hsw_ddi_pll_select(struct intel_crtc *intel_crtc, | |||
| 		      WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) | | ||||
| 		      WRPLL_DIVIDER_POST(p); | ||||
| 
 | ||||
| 		intel_crtc->config.dpll_hw_state.wrpll = val; | ||||
| 		intel_crtc->new_config->dpll_hw_state.wrpll = val; | ||||
| 
 | ||||
| 		pll = intel_get_shared_dpll(intel_crtc); | ||||
| 		if (pll == NULL) { | ||||
|  | @ -801,7 +822,7 @@ hsw_ddi_pll_select(struct intel_crtc *intel_crtc, | |||
| 			return false; | ||||
| 		} | ||||
| 
 | ||||
| 		intel_crtc->config.ddi_pll_sel = PORT_CLK_SEL_WRPLL(pll->id); | ||||
| 		intel_crtc->new_config->ddi_pll_sel = PORT_CLK_SEL_WRPLL(pll->id); | ||||
| 	} | ||||
| 
 | ||||
| 	return true; | ||||
|  | @ -817,11 +838,9 @@ hsw_ddi_pll_select(struct intel_crtc *intel_crtc, | |||
|  */ | ||||
| bool intel_ddi_pll_select(struct intel_crtc *intel_crtc) | ||||
| { | ||||
| 	struct drm_crtc *crtc = &intel_crtc->base; | ||||
| 	struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc); | ||||
| 	int clock = intel_crtc->config.port_clock; | ||||
| 
 | ||||
| 	intel_put_shared_dpll(intel_crtc); | ||||
| 	struct intel_encoder *intel_encoder = | ||||
| 		intel_ddi_get_crtc_new_encoder(intel_crtc); | ||||
| 	int clock = intel_crtc->new_config->port_clock; | ||||
| 
 | ||||
| 	return hsw_ddi_pll_select(intel_crtc, intel_encoder, clock); | ||||
| } | ||||
|  | @ -1120,15 +1139,6 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder) | |||
| 	enum port port = intel_ddi_get_encoder_port(intel_encoder); | ||||
| 	int type = intel_encoder->type; | ||||
| 
 | ||||
| 	if (crtc->config.has_audio) { | ||||
| 		DRM_DEBUG_DRIVER("Audio on pipe %c on DDI\n", | ||||
| 				 pipe_name(crtc->pipe)); | ||||
| 
 | ||||
| 		/* write eld */ | ||||
| 		DRM_DEBUG_DRIVER("DDI audio: write eld information\n"); | ||||
| 		intel_write_eld(encoder, &crtc->config.adjusted_mode); | ||||
| 	} | ||||
| 
 | ||||
| 	if (type == INTEL_OUTPUT_EDP) { | ||||
| 		struct intel_dp *intel_dp = enc_to_intel_dp(encoder); | ||||
| 		intel_edp_panel_on(intel_dp); | ||||
|  | @ -1195,12 +1205,10 @@ static void intel_enable_ddi(struct intel_encoder *intel_encoder) | |||
| 	struct drm_encoder *encoder = &intel_encoder->base; | ||||
| 	struct drm_crtc *crtc = encoder->crtc; | ||||
| 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||||
| 	int pipe = intel_crtc->pipe; | ||||
| 	struct drm_device *dev = encoder->dev; | ||||
| 	struct drm_i915_private *dev_priv = dev->dev_private; | ||||
| 	enum port port = intel_ddi_get_encoder_port(intel_encoder); | ||||
| 	int type = intel_encoder->type; | ||||
| 	uint32_t tmp; | ||||
| 
 | ||||
| 	if (type == INTEL_OUTPUT_HDMI) { | ||||
| 		struct intel_digital_port *intel_dig_port = | ||||
|  | @ -1225,9 +1233,7 @@ static void intel_enable_ddi(struct intel_encoder *intel_encoder) | |||
| 
 | ||||
| 	if (intel_crtc->config.has_audio) { | ||||
| 		intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO); | ||||
| 		tmp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD); | ||||
| 		tmp |= ((AUDIO_OUTPUT_ENABLE_A | AUDIO_ELD_VALID_A) << (pipe * 4)); | ||||
| 		I915_WRITE(HSW_AUD_PIN_ELD_CP_VLD, tmp); | ||||
| 		intel_audio_codec_enable(intel_encoder); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -1236,19 +1242,12 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder) | |||
| 	struct drm_encoder *encoder = &intel_encoder->base; | ||||
| 	struct drm_crtc *crtc = encoder->crtc; | ||||
| 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||||
| 	int pipe = intel_crtc->pipe; | ||||
| 	int type = intel_encoder->type; | ||||
| 	struct drm_device *dev = encoder->dev; | ||||
| 	struct drm_i915_private *dev_priv = dev->dev_private; | ||||
| 	uint32_t tmp; | ||||
| 
 | ||||
| 	/* We can't touch HSW_AUD_PIN_ELD_CP_VLD uncionditionally because this
 | ||||
| 	 * register is part of the power well on Haswell. */ | ||||
| 	if (intel_crtc->config.has_audio) { | ||||
| 		tmp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD); | ||||
| 		tmp &= ~((AUDIO_OUTPUT_ENABLE_A | AUDIO_ELD_VALID_A) << | ||||
| 			 (pipe * 4)); | ||||
| 		I915_WRITE(HSW_AUD_PIN_ELD_CP_VLD, tmp); | ||||
| 		intel_audio_codec_disable(intel_encoder); | ||||
| 		intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO); | ||||
| 	} | ||||
| 
 | ||||
|  | @ -1311,7 +1310,7 @@ int intel_ddi_get_cdclk_freq(struct drm_i915_private *dev_priv) | |||
| static void hsw_ddi_pll_enable(struct drm_i915_private *dev_priv, | ||||
| 			       struct intel_shared_dpll *pll) | ||||
| { | ||||
| 	I915_WRITE(WRPLL_CTL(pll->id), pll->hw_state.wrpll); | ||||
| 	I915_WRITE(WRPLL_CTL(pll->id), pll->config.hw_state.wrpll); | ||||
| 	POSTING_READ(WRPLL_CTL(pll->id)); | ||||
| 	udelay(20); | ||||
| } | ||||
|  | @ -1524,7 +1523,7 @@ void intel_ddi_get_config(struct intel_encoder *encoder, | |||
| 
 | ||||
| 	if (intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_AUDIO)) { | ||||
| 		temp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD); | ||||
| 		if (temp & (AUDIO_OUTPUT_ENABLE_A << (intel_crtc->pipe * 4))) | ||||
| 		if (temp & AUDIO_OUTPUT_ENABLE(intel_crtc->pipe)) | ||||
| 			pipe_config->has_audio = true; | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -113,6 +113,9 @@ static struct intel_dp *intel_attached_dp(struct drm_connector *connector) | |||
| static void intel_dp_link_down(struct intel_dp *intel_dp); | ||||
| static bool edp_panel_vdd_on(struct intel_dp *intel_dp); | ||||
| static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync); | ||||
| static void vlv_init_panel_power_sequencer(struct intel_dp *intel_dp); | ||||
| static void vlv_steal_power_sequencer(struct drm_device *dev, | ||||
| 				      enum pipe pipe); | ||||
| 
 | ||||
| int | ||||
| intel_dp_max_link_bw(struct intel_dp *intel_dp) | ||||
|  | @ -283,12 +286,10 @@ intel_hrawclk(struct drm_device *dev) | |||
| 
 | ||||
| static void | ||||
| intel_dp_init_panel_power_sequencer(struct drm_device *dev, | ||||
| 				    struct intel_dp *intel_dp, | ||||
| 				    struct edp_power_seq *out); | ||||
| 				    struct intel_dp *intel_dp); | ||||
| static void | ||||
| intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, | ||||
| 					      struct intel_dp *intel_dp, | ||||
| 					      struct edp_power_seq *out); | ||||
| 					      struct intel_dp *intel_dp); | ||||
| 
 | ||||
| static void pps_lock(struct intel_dp *intel_dp) | ||||
| { | ||||
|  | @ -322,6 +323,66 @@ static void pps_unlock(struct intel_dp *intel_dp) | |||
| 	intel_display_power_put(dev_priv, power_domain); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| vlv_power_sequencer_kick(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 pipe pipe = intel_dp->pps_pipe; | ||||
| 	bool pll_enabled; | ||||
| 	uint32_t DP; | ||||
| 
 | ||||
| 	if (WARN(I915_READ(intel_dp->output_reg) & DP_PORT_EN, | ||||
| 		 "skipping pipe %c power seqeuncer kick due to port %c being active\n", | ||||
| 		 pipe_name(pipe), port_name(intel_dig_port->port))) | ||||
| 		return; | ||||
| 
 | ||||
| 	DRM_DEBUG_KMS("kicking pipe %c power sequencer for port %c\n", | ||||
| 		      pipe_name(pipe), port_name(intel_dig_port->port)); | ||||
| 
 | ||||
| 	/* Preserve the BIOS-computed detected bit. This is
 | ||||
| 	 * supposed to be read-only. | ||||
| 	 */ | ||||
| 	DP = I915_READ(intel_dp->output_reg) & DP_DETECTED; | ||||
| 	DP |= DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0; | ||||
| 	DP |= DP_PORT_WIDTH(1); | ||||
| 	DP |= DP_LINK_TRAIN_PAT_1; | ||||
| 
 | ||||
| 	if (IS_CHERRYVIEW(dev)) | ||||
| 		DP |= DP_PIPE_SELECT_CHV(pipe); | ||||
| 	else if (pipe == PIPE_B) | ||||
| 		DP |= DP_PIPEB_SELECT; | ||||
| 
 | ||||
| 	pll_enabled = I915_READ(DPLL(pipe)) & DPLL_VCO_ENABLE; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * The DPLL for the pipe must be enabled for this to work. | ||||
| 	 * So enable temporarily it if it's not already enabled. | ||||
| 	 */ | ||||
| 	if (!pll_enabled) | ||||
| 		vlv_force_pll_on(dev, pipe, IS_CHERRYVIEW(dev) ? | ||||
| 				 &chv_dpll[0].dpll : &vlv_dpll[0].dpll); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Similar magic as in intel_dp_enable_port(). | ||||
| 	 * We _must_ do this port enable + disable trick | ||||
| 	 * to make this power seqeuencer lock onto the port. | ||||
| 	 * Otherwise even VDD force bit won't work. | ||||
| 	 */ | ||||
| 	I915_WRITE(intel_dp->output_reg, DP); | ||||
| 	POSTING_READ(intel_dp->output_reg); | ||||
| 
 | ||||
| 	I915_WRITE(intel_dp->output_reg, DP | DP_PORT_EN); | ||||
| 	POSTING_READ(intel_dp->output_reg); | ||||
| 
 | ||||
| 	I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN); | ||||
| 	POSTING_READ(intel_dp->output_reg); | ||||
| 
 | ||||
| 	if (!pll_enabled) | ||||
| 		vlv_force_pll_off(dev, pipe); | ||||
| } | ||||
| 
 | ||||
| static enum pipe | ||||
| vlv_power_sequencer_pipe(struct intel_dp *intel_dp) | ||||
| { | ||||
|  | @ -330,10 +391,13 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp) | |||
| 	struct drm_i915_private *dev_priv = dev->dev_private; | ||||
| 	struct intel_encoder *encoder; | ||||
| 	unsigned int pipes = (1 << PIPE_A) | (1 << PIPE_B); | ||||
| 	struct edp_power_seq power_seq; | ||||
| 	enum pipe pipe; | ||||
| 
 | ||||
| 	lockdep_assert_held(&dev_priv->pps_mutex); | ||||
| 
 | ||||
| 	/* We should never land here with regular DP ports */ | ||||
| 	WARN_ON(!is_edp(intel_dp)); | ||||
| 
 | ||||
| 	if (intel_dp->pps_pipe != INVALID_PIPE) | ||||
| 		return intel_dp->pps_pipe; | ||||
| 
 | ||||
|  | @ -359,18 +423,26 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp) | |||
| 	 * are two power sequencers and up to two eDP ports. | ||||
| 	 */ | ||||
| 	if (WARN_ON(pipes == 0)) | ||||
| 		return PIPE_A; | ||||
| 		pipe = PIPE_A; | ||||
| 	else | ||||
| 		pipe = ffs(pipes) - 1; | ||||
| 
 | ||||
| 	intel_dp->pps_pipe = ffs(pipes) - 1; | ||||
| 	vlv_steal_power_sequencer(dev, pipe); | ||||
| 	intel_dp->pps_pipe = pipe; | ||||
| 
 | ||||
| 	DRM_DEBUG_KMS("picked pipe %c power sequencer for port %c\n", | ||||
| 		      pipe_name(intel_dp->pps_pipe), | ||||
| 		      port_name(intel_dig_port->port)); | ||||
| 
 | ||||
| 	/* init power sequencer on this pipe and port */ | ||||
| 	intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq); | ||||
| 	intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, | ||||
| 						      &power_seq); | ||||
| 	intel_dp_init_panel_power_sequencer(dev, intel_dp); | ||||
| 	intel_dp_init_panel_power_sequencer_registers(dev, intel_dp); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Even vdd force doesn't work until we've made | ||||
| 	 * the power sequencer lock in on the port. | ||||
| 	 */ | ||||
| 	vlv_power_sequencer_kick(intel_dp); | ||||
| 
 | ||||
| 	return intel_dp->pps_pipe; | ||||
| } | ||||
|  | @ -425,7 +497,6 @@ vlv_initial_power_sequencer_setup(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; | ||||
| 	struct edp_power_seq power_seq; | ||||
| 	enum port port = intel_dig_port->port; | ||||
| 
 | ||||
| 	lockdep_assert_held(&dev_priv->pps_mutex); | ||||
|  | @ -453,9 +524,8 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp) | |||
| 	DRM_DEBUG_KMS("initial power sequencer for port %c: pipe %c\n", | ||||
| 		      port_name(port), pipe_name(intel_dp->pps_pipe)); | ||||
| 
 | ||||
| 	intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq); | ||||
| 	intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, | ||||
| 						      &power_seq); | ||||
| 	intel_dp_init_panel_power_sequencer(dev, intel_dp); | ||||
| 	intel_dp_init_panel_power_sequencer_registers(dev, intel_dp); | ||||
| } | ||||
| 
 | ||||
| void vlv_power_sequencer_reset(struct drm_i915_private *dev_priv) | ||||
|  | @ -550,6 +620,10 @@ static bool edp_have_panel_power(struct intel_dp *intel_dp) | |||
| 
 | ||||
| 	lockdep_assert_held(&dev_priv->pps_mutex); | ||||
| 
 | ||||
| 	if (IS_VALLEYVIEW(dev) && | ||||
| 	    intel_dp->pps_pipe == INVALID_PIPE) | ||||
| 		return false; | ||||
| 
 | ||||
| 	return (I915_READ(_pp_stat_reg(intel_dp)) & PP_ON) != 0; | ||||
| } | ||||
| 
 | ||||
|  | @ -560,6 +634,10 @@ static bool edp_have_panel_vdd(struct intel_dp *intel_dp) | |||
| 
 | ||||
| 	lockdep_assert_held(&dev_priv->pps_mutex); | ||||
| 
 | ||||
| 	if (IS_VALLEYVIEW(dev) && | ||||
| 	    intel_dp->pps_pipe == INVALID_PIPE) | ||||
| 		return false; | ||||
| 
 | ||||
| 	return I915_READ(_pp_ctrl_reg(intel_dp)) & EDP_FORCE_VDD; | ||||
| } | ||||
| 
 | ||||
|  | @ -1246,12 +1324,8 @@ static void intel_dp_prepare(struct intel_encoder *encoder) | |||
| 	intel_dp->DP |= DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0; | ||||
| 	intel_dp->DP |= DP_PORT_WIDTH(intel_dp->lane_count); | ||||
| 
 | ||||
| 	if (crtc->config.has_audio) { | ||||
| 		DRM_DEBUG_DRIVER("Enabling DP audio on pipe %c\n", | ||||
| 				 pipe_name(crtc->pipe)); | ||||
| 	if (crtc->config.has_audio) | ||||
| 		intel_dp->DP |= DP_AUDIO_OUTPUT_ENABLE; | ||||
| 		intel_write_eld(&encoder->base, adjusted_mode); | ||||
| 	} | ||||
| 
 | ||||
| 	/* Split out the IBX/CPU vs CPT settings */ | ||||
| 
 | ||||
|  | @ -1409,7 +1483,8 @@ static bool edp_panel_vdd_on(struct intel_dp *intel_dp) | |||
| 	power_domain = intel_display_port_power_domain(intel_encoder); | ||||
| 	intel_display_power_get(dev_priv, power_domain); | ||||
| 
 | ||||
| 	DRM_DEBUG_KMS("Turning eDP VDD on\n"); | ||||
| 	DRM_DEBUG_KMS("Turning eDP port %c VDD on\n", | ||||
| 		      port_name(intel_dig_port->port)); | ||||
| 
 | ||||
| 	if (!edp_have_panel_power(intel_dp)) | ||||
| 		wait_panel_power_cycle(intel_dp); | ||||
|  | @ -1428,7 +1503,8 @@ static bool edp_panel_vdd_on(struct intel_dp *intel_dp) | |||
| 	 * If the panel wasn't on, delay before accessing aux channel | ||||
| 	 */ | ||||
| 	if (!edp_have_panel_power(intel_dp)) { | ||||
| 		DRM_DEBUG_KMS("eDP was not running\n"); | ||||
| 		DRM_DEBUG_KMS("eDP port %c panel power wasn't enabled\n", | ||||
| 			      port_name(intel_dig_port->port)); | ||||
| 		msleep(intel_dp->panel_power_up_delay); | ||||
| 	} | ||||
| 
 | ||||
|  | @ -1453,7 +1529,8 @@ void intel_edp_panel_vdd_on(struct intel_dp *intel_dp) | |||
| 	vdd = edp_panel_vdd_on(intel_dp); | ||||
| 	pps_unlock(intel_dp); | ||||
| 
 | ||||
| 	WARN(!vdd, "eDP VDD already requested on\n"); | ||||
| 	WARN(!vdd, "eDP port %c VDD already requested on\n", | ||||
| 	     port_name(dp_to_dig_port(intel_dp)->port)); | ||||
| } | ||||
| 
 | ||||
| static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp) | ||||
|  | @ -1474,7 +1551,8 @@ static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp) | |||
| 	if (!edp_have_panel_vdd(intel_dp)) | ||||
| 		return; | ||||
| 
 | ||||
| 	DRM_DEBUG_KMS("Turning eDP VDD off\n"); | ||||
| 	DRM_DEBUG_KMS("Turning eDP port %c VDD off\n", | ||||
| 		      port_name(intel_dig_port->port)); | ||||
| 
 | ||||
| 	pp = ironlake_get_pp_control(intel_dp); | ||||
| 	pp &= ~EDP_FORCE_VDD; | ||||
|  | @ -1535,7 +1613,8 @@ static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync) | |||
| 	if (!is_edp(intel_dp)) | ||||
| 		return; | ||||
| 
 | ||||
| 	WARN(!intel_dp->want_panel_vdd, "eDP VDD not forced on"); | ||||
| 	WARN(!intel_dp->want_panel_vdd, "eDP port %c VDD not forced on", | ||||
| 	     port_name(dp_to_dig_port(intel_dp)->port)); | ||||
| 
 | ||||
| 	intel_dp->want_panel_vdd = false; | ||||
| 
 | ||||
|  | @ -1545,40 +1624,25 @@ static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync) | |||
| 		edp_panel_vdd_schedule_off(intel_dp); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Must be paired with intel_edp_panel_vdd_on(). | ||||
|  * Nested calls to these functions are not allowed since | ||||
|  * we drop the lock. Caller must use some higher level | ||||
|  * locking to prevent nested calls from other threads. | ||||
|  */ | ||||
| static void intel_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync) | ||||
| { | ||||
| 	if (!is_edp(intel_dp)) | ||||
| 		return; | ||||
| 
 | ||||
| 	pps_lock(intel_dp); | ||||
| 	edp_panel_vdd_off(intel_dp, sync); | ||||
| 	pps_unlock(intel_dp); | ||||
| } | ||||
| 
 | ||||
| void intel_edp_panel_on(struct intel_dp *intel_dp) | ||||
| static void edp_panel_on(struct intel_dp *intel_dp) | ||||
| { | ||||
| 	struct drm_device *dev = intel_dp_to_dev(intel_dp); | ||||
| 	struct drm_i915_private *dev_priv = dev->dev_private; | ||||
| 	u32 pp; | ||||
| 	u32 pp_ctrl_reg; | ||||
| 
 | ||||
| 	lockdep_assert_held(&dev_priv->pps_mutex); | ||||
| 
 | ||||
| 	if (!is_edp(intel_dp)) | ||||
| 		return; | ||||
| 
 | ||||
| 	DRM_DEBUG_KMS("Turn eDP power on\n"); | ||||
| 	DRM_DEBUG_KMS("Turn eDP port %c panel power on\n", | ||||
| 		      port_name(dp_to_dig_port(intel_dp)->port)); | ||||
| 
 | ||||
| 	pps_lock(intel_dp); | ||||
| 
 | ||||
| 	if (edp_have_panel_power(intel_dp)) { | ||||
| 		DRM_DEBUG_KMS("eDP power already on\n"); | ||||
| 		goto out; | ||||
| 	} | ||||
| 	if (WARN(edp_have_panel_power(intel_dp), | ||||
| 		 "eDP port %c panel power already on\n", | ||||
| 		 port_name(dp_to_dig_port(intel_dp)->port))) | ||||
| 		return; | ||||
| 
 | ||||
| 	wait_panel_power_cycle(intel_dp); | ||||
| 
 | ||||
|  | @ -1606,12 +1670,20 @@ void intel_edp_panel_on(struct intel_dp *intel_dp) | |||
| 		I915_WRITE(pp_ctrl_reg, pp); | ||||
| 		POSTING_READ(pp_ctrl_reg); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  out: | ||||
| void intel_edp_panel_on(struct intel_dp *intel_dp) | ||||
| { | ||||
| 	if (!is_edp(intel_dp)) | ||||
| 		return; | ||||
| 
 | ||||
| 	pps_lock(intel_dp); | ||||
| 	edp_panel_on(intel_dp); | ||||
| 	pps_unlock(intel_dp); | ||||
| } | ||||
| 
 | ||||
| void intel_edp_panel_off(struct intel_dp *intel_dp) | ||||
| 
 | ||||
| static void edp_panel_off(struct intel_dp *intel_dp) | ||||
| { | ||||
| 	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); | ||||
| 	struct intel_encoder *intel_encoder = &intel_dig_port->base; | ||||
|  | @ -1621,14 +1693,16 @@ void intel_edp_panel_off(struct intel_dp *intel_dp) | |||
| 	u32 pp; | ||||
| 	u32 pp_ctrl_reg; | ||||
| 
 | ||||
| 	lockdep_assert_held(&dev_priv->pps_mutex); | ||||
| 
 | ||||
| 	if (!is_edp(intel_dp)) | ||||
| 		return; | ||||
| 
 | ||||
| 	DRM_DEBUG_KMS("Turn eDP power off\n"); | ||||
| 	DRM_DEBUG_KMS("Turn eDP port %c panel power off\n", | ||||
| 		      port_name(dp_to_dig_port(intel_dp)->port)); | ||||
| 
 | ||||
| 	pps_lock(intel_dp); | ||||
| 
 | ||||
| 	WARN(!intel_dp->want_panel_vdd, "Need VDD to turn off panel\n"); | ||||
| 	WARN(!intel_dp->want_panel_vdd, "Need eDP port %c VDD to turn off panel\n", | ||||
| 	     port_name(dp_to_dig_port(intel_dp)->port)); | ||||
| 
 | ||||
| 	pp = ironlake_get_pp_control(intel_dp); | ||||
| 	/* We need to switch off panel power _and_ force vdd, for otherwise some
 | ||||
|  | @ -1649,7 +1723,15 @@ void intel_edp_panel_off(struct intel_dp *intel_dp) | |||
| 	/* We got a reference when we enabled the VDD. */ | ||||
| 	power_domain = intel_display_port_power_domain(intel_encoder); | ||||
| 	intel_display_power_put(dev_priv, power_domain); | ||||
| } | ||||
| 
 | ||||
| void intel_edp_panel_off(struct intel_dp *intel_dp) | ||||
| { | ||||
| 	if (!is_edp(intel_dp)) | ||||
| 		return; | ||||
| 
 | ||||
| 	pps_lock(intel_dp); | ||||
| 	edp_panel_off(intel_dp); | ||||
| 	pps_unlock(intel_dp); | ||||
| } | ||||
| 
 | ||||
|  | @ -2368,6 +2450,10 @@ static void intel_disable_dp(struct intel_encoder *encoder) | |||
| { | ||||
| 	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); | ||||
| 	struct drm_device *dev = encoder->base.dev; | ||||
| 	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); | ||||
| 
 | ||||
| 	if (crtc->config.has_audio) | ||||
| 		intel_audio_codec_disable(encoder); | ||||
| 
 | ||||
| 	/* Make sure the panel is off before trying to change the mode. But also
 | ||||
| 	 * ensure that we have vdd while we switch off the panel. */ | ||||
|  | @ -2522,14 +2608,23 @@ static void intel_dp_enable_port(struct intel_dp *intel_dp) | |||
| 	struct drm_device *dev = intel_dp_to_dev(intel_dp); | ||||
| 	struct drm_i915_private *dev_priv = dev->dev_private; | ||||
| 
 | ||||
| 	intel_dp->DP |= DP_PORT_EN; | ||||
| 
 | ||||
| 	/* enable with pattern 1 (as per spec) */ | ||||
| 	_intel_dp_set_link_train(intel_dp, &intel_dp->DP, | ||||
| 				 DP_TRAINING_PATTERN_1); | ||||
| 
 | ||||
| 	I915_WRITE(intel_dp->output_reg, intel_dp->DP); | ||||
| 	POSTING_READ(intel_dp->output_reg); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Magic for VLV/CHV. We _must_ first set up the register | ||||
| 	 * without actually enabling the port, and then do another | ||||
| 	 * write to enable the port. Otherwise link training will | ||||
| 	 * fail when the power sequencer is freshly used for this port. | ||||
| 	 */ | ||||
| 	intel_dp->DP |= DP_PORT_EN; | ||||
| 
 | ||||
| 	I915_WRITE(intel_dp->output_reg, intel_dp->DP); | ||||
| 	POSTING_READ(intel_dp->output_reg); | ||||
| } | ||||
| 
 | ||||
| static void intel_enable_dp(struct intel_encoder *encoder) | ||||
|  | @ -2537,19 +2632,38 @@ static void intel_enable_dp(struct intel_encoder *encoder) | |||
| 	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); | ||||
| 	struct drm_device *dev = encoder->base.dev; | ||||
| 	struct drm_i915_private *dev_priv = dev->dev_private; | ||||
| 	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); | ||||
| 	uint32_t dp_reg = I915_READ(intel_dp->output_reg); | ||||
| 
 | ||||
| 	if (WARN_ON(dp_reg & DP_PORT_EN)) | ||||
| 		return; | ||||
| 
 | ||||
| 	pps_lock(intel_dp); | ||||
| 
 | ||||
| 	if (IS_VALLEYVIEW(dev)) | ||||
| 		vlv_init_panel_power_sequencer(intel_dp); | ||||
| 
 | ||||
| 	intel_dp_enable_port(intel_dp); | ||||
| 	intel_edp_panel_vdd_on(intel_dp); | ||||
| 	intel_edp_panel_on(intel_dp); | ||||
| 	intel_edp_panel_vdd_off(intel_dp, true); | ||||
| 
 | ||||
| 	edp_panel_vdd_on(intel_dp); | ||||
| 	edp_panel_on(intel_dp); | ||||
| 	edp_panel_vdd_off(intel_dp, true); | ||||
| 
 | ||||
| 	pps_unlock(intel_dp); | ||||
| 
 | ||||
| 	if (IS_VALLEYVIEW(dev)) | ||||
| 		vlv_wait_port_ready(dev_priv, dp_to_dig_port(intel_dp)); | ||||
| 
 | ||||
| 	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); | ||||
| 	intel_dp_start_link_train(intel_dp); | ||||
| 	intel_dp_complete_link_train(intel_dp); | ||||
| 	intel_dp_stop_link_train(intel_dp); | ||||
| 
 | ||||
| 	if (crtc->config.has_audio) { | ||||
| 		DRM_DEBUG_DRIVER("Enabling DP audio on pipe %c\n", | ||||
| 				 pipe_name(crtc->pipe)); | ||||
| 		intel_audio_codec_enable(encoder); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void g4x_enable_dp(struct intel_encoder *encoder) | ||||
|  | @ -2581,6 +2695,32 @@ static void g4x_pre_enable_dp(struct intel_encoder *encoder) | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void vlv_detach_power_sequencer(struct intel_dp *intel_dp) | ||||
| { | ||||
| 	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); | ||||
| 	struct drm_i915_private *dev_priv = intel_dig_port->base.base.dev->dev_private; | ||||
| 	enum pipe pipe = intel_dp->pps_pipe; | ||||
| 	int pp_on_reg = VLV_PIPE_PP_ON_DELAYS(pipe); | ||||
| 
 | ||||
| 	edp_panel_vdd_off_sync(intel_dp); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * VLV seems to get confused when multiple power seqeuencers | ||||
| 	 * have the same port selected (even if only one has power/vdd | ||||
| 	 * enabled). The failure manifests as vlv_wait_port_ready() failing | ||||
| 	 * CHV on the other hand doesn't seem to mind having the same port | ||||
| 	 * selected in multiple power seqeuencers, but let's clear the | ||||
| 	 * port select always when logically disconnecting a power sequencer | ||||
| 	 * from a port. | ||||
| 	 */ | ||||
| 	DRM_DEBUG_KMS("detaching pipe %c power sequencer from port %c\n", | ||||
| 		      pipe_name(pipe), port_name(intel_dig_port->port)); | ||||
| 	I915_WRITE(pp_on_reg, 0); | ||||
| 	POSTING_READ(pp_on_reg); | ||||
| 
 | ||||
| 	intel_dp->pps_pipe = INVALID_PIPE; | ||||
| } | ||||
| 
 | ||||
| static void vlv_steal_power_sequencer(struct drm_device *dev, | ||||
| 				      enum pipe pipe) | ||||
| { | ||||
|  | @ -2589,6 +2729,9 @@ static void vlv_steal_power_sequencer(struct drm_device *dev, | |||
| 
 | ||||
| 	lockdep_assert_held(&dev_priv->pps_mutex); | ||||
| 
 | ||||
| 	if (WARN_ON(pipe != PIPE_A && pipe != PIPE_B)) | ||||
| 		return; | ||||
| 
 | ||||
| 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, | ||||
| 			    base.head) { | ||||
| 		struct intel_dp *intel_dp; | ||||
|  | @ -2606,10 +2749,12 @@ static void vlv_steal_power_sequencer(struct drm_device *dev, | |||
| 		DRM_DEBUG_KMS("stealing pipe %c power sequencer from port %c\n", | ||||
| 			      pipe_name(pipe), port_name(port)); | ||||
| 
 | ||||
| 		/* make sure vdd is off before we steal it */ | ||||
| 		edp_panel_vdd_off_sync(intel_dp); | ||||
| 		WARN(encoder->connectors_active, | ||||
| 		     "stealing pipe %c power sequencer from active eDP port %c\n", | ||||
| 		     pipe_name(pipe), port_name(port)); | ||||
| 
 | ||||
| 		intel_dp->pps_pipe = INVALID_PIPE; | ||||
| 		/* make sure vdd is off before we steal it */ | ||||
| 		vlv_detach_power_sequencer(intel_dp); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -2620,10 +2765,12 @@ static void vlv_init_panel_power_sequencer(struct intel_dp *intel_dp) | |||
| 	struct drm_device *dev = encoder->base.dev; | ||||
| 	struct drm_i915_private *dev_priv = dev->dev_private; | ||||
| 	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); | ||||
| 	struct edp_power_seq power_seq; | ||||
| 
 | ||||
| 	lockdep_assert_held(&dev_priv->pps_mutex); | ||||
| 
 | ||||
| 	if (!is_edp(intel_dp)) | ||||
| 		return; | ||||
| 
 | ||||
| 	if (intel_dp->pps_pipe == crtc->pipe) | ||||
| 		return; | ||||
| 
 | ||||
|  | @ -2633,7 +2780,7 @@ static void vlv_init_panel_power_sequencer(struct intel_dp *intel_dp) | |||
| 	 * we still have control of it. | ||||
| 	 */ | ||||
| 	if (intel_dp->pps_pipe != INVALID_PIPE) | ||||
| 		edp_panel_vdd_off_sync(intel_dp); | ||||
| 		vlv_detach_power_sequencer(intel_dp); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * We may be stealing the power | ||||
|  | @ -2648,9 +2795,8 @@ static void vlv_init_panel_power_sequencer(struct intel_dp *intel_dp) | |||
| 		      pipe_name(intel_dp->pps_pipe), port_name(intel_dig_port->port)); | ||||
| 
 | ||||
| 	/* init power sequencer on this pipe and port */ | ||||
| 	intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq); | ||||
| 	intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, | ||||
| 						      &power_seq); | ||||
| 	intel_dp_init_panel_power_sequencer(dev, intel_dp); | ||||
| 	intel_dp_init_panel_power_sequencer_registers(dev, intel_dp); | ||||
| } | ||||
| 
 | ||||
| static void vlv_pre_enable_dp(struct intel_encoder *encoder) | ||||
|  | @ -2679,15 +2825,7 @@ static void vlv_pre_enable_dp(struct intel_encoder *encoder) | |||
| 
 | ||||
| 	mutex_unlock(&dev_priv->dpio_lock); | ||||
| 
 | ||||
| 	if (is_edp(intel_dp)) { | ||||
| 		pps_lock(intel_dp); | ||||
| 		vlv_init_panel_power_sequencer(intel_dp); | ||||
| 		pps_unlock(intel_dp); | ||||
| 	} | ||||
| 
 | ||||
| 	intel_enable_dp(encoder); | ||||
| 
 | ||||
| 	vlv_wait_port_ready(dev_priv, dport); | ||||
| } | ||||
| 
 | ||||
| static void vlv_dp_pre_pll_enable(struct intel_encoder *encoder) | ||||
|  | @ -2779,15 +2917,7 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder) | |||
| 
 | ||||
| 	mutex_unlock(&dev_priv->dpio_lock); | ||||
| 
 | ||||
| 	if (is_edp(intel_dp)) { | ||||
| 		pps_lock(intel_dp); | ||||
| 		vlv_init_panel_power_sequencer(intel_dp); | ||||
| 		pps_unlock(intel_dp); | ||||
| 	} | ||||
| 
 | ||||
| 	intel_enable_dp(encoder); | ||||
| 
 | ||||
| 	vlv_wait_port_ready(dev_priv, dport); | ||||
| } | ||||
| 
 | ||||
| static void chv_dp_pre_pll_enable(struct intel_encoder *encoder) | ||||
|  | @ -3696,7 +3826,6 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) | |||
| 
 | ||||
| 		/* Try 5 times, then try clock recovery if that fails */ | ||||
| 		if (tries > 5) { | ||||
| 			intel_dp_link_down(intel_dp); | ||||
| 			intel_dp_start_link_train(intel_dp); | ||||
| 			intel_dp_set_link_train(intel_dp, &DP, | ||||
| 						training_pattern | | ||||
|  | @ -3854,8 +3983,6 @@ intel_dp_probe_oui(struct intel_dp *intel_dp) | |||
| 	if (!(intel_dp->dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_OUI_SUPPORT)) | ||||
| 		return; | ||||
| 
 | ||||
| 	intel_edp_panel_vdd_on(intel_dp); | ||||
| 
 | ||||
| 	if (intel_dp_dpcd_read_wake(&intel_dp->aux, DP_SINK_OUI, buf, 3) == 3) | ||||
| 		DRM_DEBUG_KMS("Sink OUI: %02hx%02hx%02hx\n", | ||||
| 			      buf[0], buf[1], buf[2]); | ||||
|  | @ -3863,8 +3990,6 @@ intel_dp_probe_oui(struct intel_dp *intel_dp) | |||
| 	if (intel_dp_dpcd_read_wake(&intel_dp->aux, DP_BRANCH_OUI, buf, 3) == 3) | ||||
| 		DRM_DEBUG_KMS("Branch OUI: %02hx%02hx%02hx\n", | ||||
| 			      buf[0], buf[1], buf[2]); | ||||
| 
 | ||||
| 	intel_edp_panel_vdd_off(intel_dp, false); | ||||
| } | ||||
| 
 | ||||
| static bool | ||||
|  | @ -3878,7 +4003,6 @@ intel_dp_probe_mst(struct intel_dp *intel_dp) | |||
| 	if (intel_dp->dpcd[DP_DPCD_REV] < 0x12) | ||||
| 		return false; | ||||
| 
 | ||||
| 	intel_edp_panel_vdd_on(intel_dp); | ||||
| 	if (intel_dp_dpcd_read_wake(&intel_dp->aux, DP_MSTM_CAP, buf, 1)) { | ||||
| 		if (buf[0] & DP_MST_CAP) { | ||||
| 			DRM_DEBUG_KMS("Sink is MST capable\n"); | ||||
|  | @ -3888,7 +4012,6 @@ intel_dp_probe_mst(struct intel_dp *intel_dp) | |||
| 			intel_dp->is_mst = false; | ||||
| 		} | ||||
| 	} | ||||
| 	intel_edp_panel_vdd_off(intel_dp, false); | ||||
| 
 | ||||
| 	drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, intel_dp->is_mst); | ||||
| 	return intel_dp->is_mst; | ||||
|  | @ -4568,9 +4691,52 @@ static void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder) | |||
| 	pps_unlock(intel_dp); | ||||
| } | ||||
| 
 | ||||
| static void intel_edp_panel_vdd_sanitize(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 intel_display_power_domain power_domain; | ||||
| 
 | ||||
| 	lockdep_assert_held(&dev_priv->pps_mutex); | ||||
| 
 | ||||
| 	if (!edp_have_panel_vdd(intel_dp)) | ||||
| 		return; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * The VDD bit needs a power domain reference, so if the bit is | ||||
| 	 * already enabled when we boot or resume, grab this reference and | ||||
| 	 * schedule a vdd off, so we don't hold on to the reference | ||||
| 	 * indefinitely. | ||||
| 	 */ | ||||
| 	DRM_DEBUG_KMS("VDD left on by BIOS, adjusting state tracking\n"); | ||||
| 	power_domain = intel_display_port_power_domain(&intel_dig_port->base); | ||||
| 	intel_display_power_get(dev_priv, power_domain); | ||||
| 
 | ||||
| 	edp_panel_vdd_schedule_off(intel_dp); | ||||
| } | ||||
| 
 | ||||
| static void intel_dp_encoder_reset(struct drm_encoder *encoder) | ||||
| { | ||||
| 	intel_edp_panel_vdd_sanitize(to_intel_encoder(encoder)); | ||||
| 	struct intel_dp *intel_dp; | ||||
| 
 | ||||
| 	if (to_intel_encoder(encoder)->type != INTEL_OUTPUT_EDP) | ||||
| 		return; | ||||
| 
 | ||||
| 	intel_dp = enc_to_intel_dp(encoder); | ||||
| 
 | ||||
| 	pps_lock(intel_dp); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Read out the current power sequencer assignment, | ||||
| 	 * in case the BIOS did something with it. | ||||
| 	 */ | ||||
| 	if (IS_VALLEYVIEW(encoder->dev)) | ||||
| 		vlv_initial_power_sequencer_setup(intel_dp); | ||||
| 
 | ||||
| 	intel_edp_panel_vdd_sanitize(intel_dp); | ||||
| 
 | ||||
| 	pps_unlock(intel_dp); | ||||
| } | ||||
| 
 | ||||
| static const struct drm_connector_funcs intel_dp_connector_funcs = { | ||||
|  | @ -4757,16 +4923,20 @@ static void intel_dp_init_panel_power_timestamps(struct intel_dp *intel_dp) | |||
| 
 | ||||
| static void | ||||
| intel_dp_init_panel_power_sequencer(struct drm_device *dev, | ||||
| 				    struct intel_dp *intel_dp, | ||||
| 				    struct edp_power_seq *out) | ||||
| 				    struct intel_dp *intel_dp) | ||||
| { | ||||
| 	struct drm_i915_private *dev_priv = dev->dev_private; | ||||
| 	struct edp_power_seq cur, vbt, spec, final; | ||||
| 	struct edp_power_seq cur, vbt, spec, | ||||
| 		*final = &intel_dp->pps_delays; | ||||
| 	u32 pp_on, pp_off, pp_div, pp; | ||||
| 	int pp_ctrl_reg, pp_on_reg, pp_off_reg, pp_div_reg; | ||||
| 
 | ||||
| 	lockdep_assert_held(&dev_priv->pps_mutex); | ||||
| 
 | ||||
| 	/* already initialized? */ | ||||
| 	if (final->t11_t12 != 0) | ||||
| 		return; | ||||
| 
 | ||||
| 	if (HAS_PCH_SPLIT(dev)) { | ||||
| 		pp_ctrl_reg = PCH_PP_CONTROL; | ||||
| 		pp_on_reg = PCH_PP_ON_DELAYS; | ||||
|  | @ -4828,7 +4998,7 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev, | |||
| 
 | ||||
| 	/* Use the max of the register settings and vbt. If both are
 | ||||
| 	 * unset, fall back to the spec limits. */ | ||||
| #define assign_final(field)	final.field = (max(cur.field, vbt.field) == 0 ? \ | ||||
| #define assign_final(field)	final->field = (max(cur.field, vbt.field) == 0 ? \ | ||||
| 				       spec.field : \ | ||||
| 				       max(cur.field, vbt.field)) | ||||
| 	assign_final(t1_t3); | ||||
|  | @ -4838,7 +5008,7 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev, | |||
| 	assign_final(t11_t12); | ||||
| #undef assign_final | ||||
| 
 | ||||
| #define get_delay(field)	(DIV_ROUND_UP(final.field, 10)) | ||||
| #define get_delay(field)	(DIV_ROUND_UP(final->field, 10)) | ||||
| 	intel_dp->panel_power_up_delay = get_delay(t1_t3); | ||||
| 	intel_dp->backlight_on_delay = get_delay(t8); | ||||
| 	intel_dp->backlight_off_delay = get_delay(t9); | ||||
|  | @ -4852,21 +5022,18 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev, | |||
| 
 | ||||
| 	DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n", | ||||
| 		      intel_dp->backlight_on_delay, intel_dp->backlight_off_delay); | ||||
| 
 | ||||
| 	if (out) | ||||
| 		*out = final; | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, | ||||
| 					      struct intel_dp *intel_dp, | ||||
| 					      struct edp_power_seq *seq) | ||||
| 					      struct intel_dp *intel_dp) | ||||
| { | ||||
| 	struct drm_i915_private *dev_priv = dev->dev_private; | ||||
| 	u32 pp_on, pp_off, pp_div, port_sel = 0; | ||||
| 	int div = HAS_PCH_SPLIT(dev) ? intel_pch_rawclk(dev) : intel_hrawclk(dev); | ||||
| 	int pp_on_reg, pp_off_reg, pp_div_reg; | ||||
| 	enum port port = dp_to_dig_port(intel_dp)->port; | ||||
| 	const struct edp_power_seq *seq = &intel_dp->pps_delays; | ||||
| 
 | ||||
| 	lockdep_assert_held(&dev_priv->pps_mutex); | ||||
| 
 | ||||
|  | @ -5052,40 +5219,8 @@ intel_dp_drrs_init(struct intel_digital_port *intel_dig_port, | |||
| 	return downclock_mode; | ||||
| } | ||||
| 
 | ||||
| void intel_edp_panel_vdd_sanitize(struct intel_encoder *intel_encoder) | ||||
| { | ||||
| 	struct drm_device *dev = intel_encoder->base.dev; | ||||
| 	struct drm_i915_private *dev_priv = dev->dev_private; | ||||
| 	struct intel_dp *intel_dp; | ||||
| 	enum intel_display_power_domain power_domain; | ||||
| 
 | ||||
| 	if (intel_encoder->type != INTEL_OUTPUT_EDP) | ||||
| 		return; | ||||
| 
 | ||||
| 	intel_dp = enc_to_intel_dp(&intel_encoder->base); | ||||
| 
 | ||||
| 	pps_lock(intel_dp); | ||||
| 
 | ||||
| 	if (!edp_have_panel_vdd(intel_dp)) | ||||
| 		goto out; | ||||
| 	/*
 | ||||
| 	 * The VDD bit needs a power domain reference, so if the bit is | ||||
| 	 * already enabled when we boot or resume, grab this reference and | ||||
| 	 * schedule a vdd off, so we don't hold on to the reference | ||||
| 	 * indefinitely. | ||||
| 	 */ | ||||
| 	DRM_DEBUG_KMS("VDD left on by BIOS, adjusting state tracking\n"); | ||||
| 	power_domain = intel_display_port_power_domain(intel_encoder); | ||||
| 	intel_display_power_get(dev_priv, power_domain); | ||||
| 
 | ||||
| 	edp_panel_vdd_schedule_off(intel_dp); | ||||
|  out: | ||||
| 	pps_unlock(intel_dp); | ||||
| } | ||||
| 
 | ||||
| static bool intel_edp_init_connector(struct intel_dp *intel_dp, | ||||
| 				     struct intel_connector *intel_connector, | ||||
| 				     struct edp_power_seq *power_seq) | ||||
| 				     struct intel_connector *intel_connector) | ||||
| { | ||||
| 	struct drm_connector *connector = &intel_connector->base; | ||||
| 	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); | ||||
|  | @ -5103,12 +5238,12 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, | |||
| 	if (!is_edp(intel_dp)) | ||||
| 		return true; | ||||
| 
 | ||||
| 	intel_edp_panel_vdd_sanitize(intel_encoder); | ||||
| 	pps_lock(intel_dp); | ||||
| 	intel_edp_panel_vdd_sanitize(intel_dp); | ||||
| 	pps_unlock(intel_dp); | ||||
| 
 | ||||
| 	/* Cache DPCD and EDID for edp. */ | ||||
| 	intel_edp_panel_vdd_on(intel_dp); | ||||
| 	has_dpcd = intel_dp_get_dpcd(intel_dp); | ||||
| 	intel_edp_panel_vdd_off(intel_dp, false); | ||||
| 
 | ||||
| 	if (has_dpcd) { | ||||
| 		if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11) | ||||
|  | @ -5123,7 +5258,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, | |||
| 
 | ||||
| 	/* We now know it's not a ghost, init power sequence regs. */ | ||||
| 	pps_lock(intel_dp); | ||||
| 	intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, power_seq); | ||||
| 	intel_dp_init_panel_power_sequencer_registers(dev, intel_dp); | ||||
| 	pps_unlock(intel_dp); | ||||
| 
 | ||||
| 	mutex_lock(&dev->mode_config.mutex); | ||||
|  | @ -5184,7 +5319,6 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, | |||
| 	struct drm_device *dev = intel_encoder->base.dev; | ||||
| 	struct drm_i915_private *dev_priv = dev->dev_private; | ||||
| 	enum port port = intel_dig_port->port; | ||||
| 	struct edp_power_seq power_seq = { 0 }; | ||||
| 	int type; | ||||
| 
 | ||||
| 	intel_dp->pps_pipe = INVALID_PIPE; | ||||
|  | @ -5223,6 +5357,11 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, | |||
| 	if (type == DRM_MODE_CONNECTOR_eDP) | ||||
| 		intel_encoder->type = INTEL_OUTPUT_EDP; | ||||
| 
 | ||||
| 	/* eDP only on port B and/or C on vlv/chv */ | ||||
| 	if (WARN_ON(IS_VALLEYVIEW(dev) && is_edp(intel_dp) && | ||||
| 		    port != PORT_B && port != PORT_C)) | ||||
| 		return false; | ||||
| 
 | ||||
| 	DRM_DEBUG_KMS("Adding %s connector on port %c\n", | ||||
| 			type == DRM_MODE_CONNECTOR_eDP ? "eDP" : "DP", | ||||
| 			port_name(port)); | ||||
|  | @ -5265,13 +5404,11 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, | |||
| 
 | ||||
| 	if (is_edp(intel_dp)) { | ||||
| 		pps_lock(intel_dp); | ||||
| 		if (IS_VALLEYVIEW(dev)) { | ||||
| 			vlv_initial_power_sequencer_setup(intel_dp); | ||||
| 		} else { | ||||
| 		intel_dp_init_panel_power_timestamps(intel_dp); | ||||
| 			intel_dp_init_panel_power_sequencer(dev, intel_dp, | ||||
| 							    &power_seq); | ||||
| 		} | ||||
| 		if (IS_VALLEYVIEW(dev)) | ||||
| 			vlv_initial_power_sequencer_setup(intel_dp); | ||||
| 		else | ||||
| 			intel_dp_init_panel_power_sequencer(dev, intel_dp); | ||||
| 		pps_unlock(intel_dp); | ||||
| 	} | ||||
| 
 | ||||
|  | @ -5285,7 +5422,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (!intel_edp_init_connector(intel_dp, intel_connector, &power_seq)) { | ||||
| 	if (!intel_edp_init_connector(intel_dp, intel_connector)) { | ||||
| 		drm_dp_aux_unregister(&intel_dp->aux); | ||||
| 		if (is_edp(intel_dp)) { | ||||
| 			cancel_delayed_work_sync(&intel_dp->panel_vdd_work); | ||||
|  |  | |||
|  | @ -94,18 +94,20 @@ | |||
| 
 | ||||
| /* these are outputs from the chip - integrated only
 | ||||
|    external chips are via DVO or SDVO output */ | ||||
| #define INTEL_OUTPUT_UNUSED 0 | ||||
| #define INTEL_OUTPUT_ANALOG 1 | ||||
| #define INTEL_OUTPUT_DVO 2 | ||||
| #define INTEL_OUTPUT_SDVO 3 | ||||
| #define INTEL_OUTPUT_LVDS 4 | ||||
| #define INTEL_OUTPUT_TVOUT 5 | ||||
| #define INTEL_OUTPUT_HDMI 6 | ||||
| #define INTEL_OUTPUT_DISPLAYPORT 7 | ||||
| #define INTEL_OUTPUT_EDP 8 | ||||
| #define INTEL_OUTPUT_DSI 9 | ||||
| #define INTEL_OUTPUT_UNKNOWN 10 | ||||
| #define INTEL_OUTPUT_DP_MST 11 | ||||
| enum intel_output_type { | ||||
| 	INTEL_OUTPUT_UNUSED = 0, | ||||
| 	INTEL_OUTPUT_ANALOG = 1, | ||||
| 	INTEL_OUTPUT_DVO = 2, | ||||
| 	INTEL_OUTPUT_SDVO = 3, | ||||
| 	INTEL_OUTPUT_LVDS = 4, | ||||
| 	INTEL_OUTPUT_TVOUT = 5, | ||||
| 	INTEL_OUTPUT_HDMI = 6, | ||||
| 	INTEL_OUTPUT_DISPLAYPORT = 7, | ||||
| 	INTEL_OUTPUT_EDP = 8, | ||||
| 	INTEL_OUTPUT_DSI = 9, | ||||
| 	INTEL_OUTPUT_UNKNOWN = 10, | ||||
| 	INTEL_OUTPUT_DP_MST = 11, | ||||
| }; | ||||
| 
 | ||||
| #define INTEL_DVO_CHIP_NONE 0 | ||||
| #define INTEL_DVO_CHIP_LVDS 1 | ||||
|  | @ -136,7 +138,7 @@ struct intel_encoder { | |||
| 	 */ | ||||
| 	struct intel_crtc *new_crtc; | ||||
| 
 | ||||
| 	int type; | ||||
| 	enum intel_output_type type; | ||||
| 	unsigned int cloneable; | ||||
| 	bool connectors_active; | ||||
| 	void (*hot_plug)(struct intel_encoder *); | ||||
|  | @ -399,7 +401,14 @@ struct intel_pipe_wm { | |||
| 
 | ||||
| struct intel_mmio_flip { | ||||
| 	u32 seqno; | ||||
| 	u32 ring_id; | ||||
| 	struct intel_engine_cs *ring; | ||||
| 	struct work_struct work; | ||||
| }; | ||||
| 
 | ||||
| struct skl_pipe_wm { | ||||
| 	struct skl_wm_level wm[8]; | ||||
| 	struct skl_wm_level trans_wm; | ||||
| 	uint32_t linetime; | ||||
| }; | ||||
| 
 | ||||
| struct intel_crtc { | ||||
|  | @ -449,6 +458,8 @@ struct intel_crtc { | |||
| 	struct { | ||||
| 		/* watermarks currently being used  */ | ||||
| 		struct intel_pipe_wm active; | ||||
| 		/* SKL wm values currently in use */ | ||||
| 		struct skl_pipe_wm skl_active; | ||||
| 	} wm; | ||||
| 
 | ||||
| 	int scanline_offset; | ||||
|  | @ -590,6 +601,7 @@ struct intel_dp { | |||
| 	 * this port. Only relevant on VLV/CHV. | ||||
| 	 */ | ||||
| 	enum pipe pps_pipe; | ||||
| 	struct edp_power_seq pps_delays; | ||||
| 
 | ||||
| 	bool use_tps3; | ||||
| 	bool can_mst; /* this port supports mst */ | ||||
|  | @ -848,6 +860,11 @@ void intel_frontbuffer_flip(struct drm_device *dev, | |||
| void intel_fb_obj_flush(struct drm_i915_gem_object *obj, bool retire); | ||||
| 
 | ||||
| 
 | ||||
| /* intel_audio.c */ | ||||
| void intel_init_audio(struct drm_device *dev); | ||||
| void intel_audio_codec_enable(struct intel_encoder *encoder); | ||||
| void intel_audio_codec_disable(struct intel_encoder *encoder); | ||||
| 
 | ||||
| /* intel_display.c */ | ||||
| const char *intel_output_name(int output); | ||||
| bool intel_has_pending_fb_unpin(struct drm_device *dev); | ||||
|  | @ -873,6 +890,7 @@ int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, | |||
| 				struct drm_file *file_priv); | ||||
| enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv, | ||||
| 					     enum pipe pipe); | ||||
| bool intel_pipe_has_type(struct intel_crtc *crtc, enum intel_output_type type); | ||||
| static inline void | ||||
| intel_wait_for_vblank(struct drm_device *dev, int pipe) | ||||
| { | ||||
|  | @ -887,8 +905,8 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector, | |||
| 				struct drm_modeset_acquire_ctx *ctx); | ||||
| void intel_release_load_detect_pipe(struct drm_connector *connector, | ||||
| 				    struct intel_load_detect_pipe *old); | ||||
| int intel_pin_and_fence_fb_obj(struct drm_device *dev, | ||||
| 			       struct drm_i915_gem_object *obj, | ||||
| int intel_pin_and_fence_fb_obj(struct drm_plane *plane, | ||||
| 			       struct drm_framebuffer *fb, | ||||
| 			       struct intel_engine_cs *pipelined); | ||||
| void intel_unpin_fb_obj(struct drm_i915_gem_object *obj); | ||||
| struct drm_framebuffer * | ||||
|  | @ -910,6 +928,10 @@ void assert_shared_dpll(struct drm_i915_private *dev_priv, | |||
| struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc); | ||||
| void intel_put_shared_dpll(struct intel_crtc *crtc); | ||||
| 
 | ||||
| void vlv_force_pll_on(struct drm_device *dev, enum pipe pipe, | ||||
| 		      const struct dpll *dpll); | ||||
| void vlv_force_pll_off(struct drm_device *dev, enum pipe pipe); | ||||
| 
 | ||||
| /* modesetting asserts */ | ||||
| void assert_panel_unlocked(struct drm_i915_private *dev_priv, | ||||
| 			   enum pipe pipe); | ||||
|  | @ -924,8 +946,6 @@ void assert_fdi_rx_pll(struct drm_i915_private *dev_priv, | |||
| void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, bool state); | ||||
| #define assert_pipe_enabled(d, p) assert_pipe(d, p, true) | ||||
| #define assert_pipe_disabled(d, p) assert_pipe(d, p, false) | ||||
| void intel_write_eld(struct drm_encoder *encoder, | ||||
| 		     struct drm_display_mode *mode); | ||||
| unsigned long intel_gen4_compute_page_offset(int *x, int *y, | ||||
| 					     unsigned int tiling_mode, | ||||
| 					     unsigned int bpp, | ||||
|  | @ -970,7 +990,6 @@ bool intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, | |||
| void intel_edp_backlight_on(struct intel_dp *intel_dp); | ||||
| void intel_edp_backlight_off(struct intel_dp *intel_dp); | ||||
| void intel_edp_panel_vdd_on(struct intel_dp *intel_dp); | ||||
| void intel_edp_panel_vdd_sanitize(struct intel_encoder *intel_encoder); | ||||
| void intel_edp_panel_on(struct intel_dp *intel_dp); | ||||
| void intel_edp_panel_off(struct intel_dp *intel_dp); | ||||
| void intel_edp_psr_enable(struct intel_dp *intel_dp); | ||||
|  | @ -982,7 +1001,6 @@ void intel_edp_psr_flush(struct drm_device *dev, | |||
| 			 unsigned frontbuffer_bits); | ||||
| void intel_edp_psr_init(struct drm_device *dev); | ||||
| 
 | ||||
| int intel_dp_handle_hpd_irq(struct intel_digital_port *digport, bool long_hpd); | ||||
| void intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connector); | ||||
| void intel_dp_mst_suspend(struct drm_device *dev); | ||||
| void intel_dp_mst_resume(struct drm_device *dev); | ||||
|  | @ -1139,6 +1157,9 @@ void gen6_update_ring_freq(struct drm_device *dev); | |||
| void gen6_rps_idle(struct drm_i915_private *dev_priv); | ||||
| void gen6_rps_boost(struct drm_i915_private *dev_priv); | ||||
| void ilk_wm_get_hw_state(struct drm_device *dev); | ||||
| void skl_wm_get_hw_state(struct drm_device *dev); | ||||
| void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv, | ||||
| 			  struct skl_ddb_allocation *ddb /* out */); | ||||
| 
 | ||||
| 
 | ||||
| /* intel_sdvo.c */ | ||||
|  | @ -1158,7 +1179,9 @@ int intel_sprite_set_colorkey(struct drm_device *dev, void *data, | |||
| 			      struct drm_file *file_priv); | ||||
| int intel_sprite_get_colorkey(struct drm_device *dev, void *data, | ||||
| 			      struct drm_file *file_priv); | ||||
| 
 | ||||
| bool intel_pipe_update_start(struct intel_crtc *crtc, | ||||
| 			     uint32_t *start_vbl_count); | ||||
| void intel_pipe_update_end(struct intel_crtc *crtc, u32 start_vbl_count); | ||||
| 
 | ||||
| /* intel_tv.c */ | ||||
| void intel_tv_init(struct drm_device *dev); | ||||
|  |  | |||
|  | @ -119,25 +119,25 @@ static int intelfb_alloc(struct drm_fb_helper *helper, | |||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Flush everything out, we'll be doing GTT only from now on */ | ||||
| 	ret = intel_pin_and_fence_fb_obj(dev, obj, NULL); | ||||
| 	if (ret) { | ||||
| 		DRM_ERROR("failed to pin obj: %d\n", ret); | ||||
| 		goto out_unref; | ||||
| 	} | ||||
| 
 | ||||
| 	fb = __intel_framebuffer_create(dev, &mode_cmd, obj); | ||||
| 	if (IS_ERR(fb)) { | ||||
| 		ret = PTR_ERR(fb); | ||||
| 		goto out_unpin; | ||||
| 		goto out_unref; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Flush everything out, we'll be doing GTT only from now on */ | ||||
| 	ret = intel_pin_and_fence_fb_obj(NULL, fb, NULL); | ||||
| 	if (ret) { | ||||
| 		DRM_ERROR("failed to pin obj: %d\n", ret); | ||||
| 		goto out_fb; | ||||
| 	} | ||||
| 
 | ||||
| 	ifbdev->fb = to_intel_framebuffer(fb); | ||||
| 
 | ||||
| 	return 0; | ||||
| 
 | ||||
| out_unpin: | ||||
| 	i915_gem_object_ggtt_unpin(obj); | ||||
| out_fb: | ||||
| 	drm_framebuffer_remove(fb); | ||||
| out_unref: | ||||
| 	drm_gem_object_unreference(&obj->base); | ||||
| out: | ||||
|  |  | |||
|  | @ -661,14 +661,6 @@ static void intel_hdmi_prepare(struct intel_encoder *encoder) | |||
| 	if (crtc->config.has_hdmi_sink) | ||||
| 		hdmi_val |= HDMI_MODE_SELECT_HDMI; | ||||
| 
 | ||||
| 	if (crtc->config.has_audio) { | ||||
| 		WARN_ON(!crtc->config.has_hdmi_sink); | ||||
| 		DRM_DEBUG_DRIVER("Enabling HDMI audio on pipe %c\n", | ||||
| 				 pipe_name(crtc->pipe)); | ||||
| 		hdmi_val |= SDVO_AUDIO_ENABLE; | ||||
| 		intel_write_eld(&encoder->base, adjusted_mode); | ||||
| 	} | ||||
| 
 | ||||
| 	if (HAS_PCH_CPT(dev)) | ||||
| 		hdmi_val |= SDVO_PIPE_SEL_CPT(crtc->pipe); | ||||
| 	else if (IS_CHERRYVIEW(dev)) | ||||
|  | @ -791,6 +783,13 @@ static void intel_enable_hdmi(struct intel_encoder *encoder) | |||
| 		I915_WRITE(intel_hdmi->hdmi_reg, temp); | ||||
| 		POSTING_READ(intel_hdmi->hdmi_reg); | ||||
| 	} | ||||
| 
 | ||||
| 	if (intel_crtc->config.has_audio) { | ||||
| 		WARN_ON(!intel_crtc->config.has_hdmi_sink); | ||||
| 		DRM_DEBUG_DRIVER("Enabling HDMI audio on pipe %c\n", | ||||
| 				 pipe_name(intel_crtc->pipe)); | ||||
| 		intel_audio_codec_enable(encoder); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void vlv_enable_hdmi(struct intel_encoder *encoder) | ||||
|  | @ -802,9 +801,13 @@ static void intel_disable_hdmi(struct intel_encoder *encoder) | |||
| 	struct drm_device *dev = encoder->base.dev; | ||||
| 	struct drm_i915_private *dev_priv = dev->dev_private; | ||||
| 	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); | ||||
| 	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); | ||||
| 	u32 temp; | ||||
| 	u32 enable_bits = SDVO_ENABLE | SDVO_AUDIO_ENABLE; | ||||
| 
 | ||||
| 	if (crtc->config.has_audio) | ||||
| 		intel_audio_codec_disable(encoder); | ||||
| 
 | ||||
| 	temp = I915_READ(intel_hdmi->hdmi_reg); | ||||
| 
 | ||||
| 	/* HW workaround for IBX, we need to move the port to transcoder A
 | ||||
|  |  | |||
|  | @ -356,7 +356,7 @@ static int execlists_ctx_write_tail(struct drm_i915_gem_object *ctx_obj, u32 tai | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int execlists_submit_context(struct intel_engine_cs *ring, | ||||
| static void execlists_submit_contexts(struct intel_engine_cs *ring, | ||||
| 				      struct intel_context *to0, u32 tail0, | ||||
| 				      struct intel_context *to1, u32 tail1) | ||||
| { | ||||
|  | @ -378,8 +378,6 @@ static int execlists_submit_context(struct intel_engine_cs *ring, | |||
| 	} | ||||
| 
 | ||||
| 	execlists_elsp_write(ring, ctx_obj0, ctx_obj1); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static void execlists_context_unqueue(struct intel_engine_cs *ring) | ||||
|  | @ -413,9 +411,9 @@ static void execlists_context_unqueue(struct intel_engine_cs *ring) | |||
| 
 | ||||
| 	WARN_ON(req1 && req1->elsp_submitted); | ||||
| 
 | ||||
| 	WARN_ON(execlists_submit_context(ring, req0->ctx, req0->tail, | ||||
| 	execlists_submit_contexts(ring, req0->ctx, req0->tail, | ||||
| 				  req1 ? req1->ctx : NULL, | ||||
| 					 req1 ? req1->tail : 0)); | ||||
| 				  req1 ? req1->tail : 0); | ||||
| 
 | ||||
| 	req0->elsp_submitted++; | ||||
| 	if (req1) | ||||
|  | @ -1214,11 +1212,13 @@ static int gen8_emit_request(struct intel_ringbuffer *ringbuf) | |||
|  */ | ||||
| void intel_logical_ring_cleanup(struct intel_engine_cs *ring) | ||||
| { | ||||
| 	struct drm_i915_private *dev_priv = ring->dev->dev_private; | ||||
| 	struct drm_i915_private *dev_priv; | ||||
| 
 | ||||
| 	if (!intel_ring_initialized(ring)) | ||||
| 		return; | ||||
| 
 | ||||
| 	dev_priv = ring->dev->dev_private; | ||||
| 
 | ||||
| 	intel_logical_ring_stop(ring); | ||||
| 	WARN_ON((I915_READ_MODE(ring) & MODE_IDLE) == 0); | ||||
| 	ring->preallocated_lazy_request = NULL; | ||||
|  | @ -1649,6 +1649,27 @@ static uint32_t get_lr_context_size(struct intel_engine_cs *ring) | |||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| static int lrc_setup_hardware_status_page(struct intel_engine_cs *ring, | ||||
| 		struct drm_i915_gem_object *default_ctx_obj) | ||||
| { | ||||
| 	struct drm_i915_private *dev_priv = ring->dev->dev_private; | ||||
| 
 | ||||
| 	/* The status page is offset 0 from the default context object
 | ||||
| 	 * in LRC mode. */ | ||||
| 	ring->status_page.gfx_addr = i915_gem_obj_ggtt_offset(default_ctx_obj); | ||||
| 	ring->status_page.page_addr = | ||||
| 			kmap(sg_page(default_ctx_obj->pages->sgl)); | ||||
| 	if (ring->status_page.page_addr == NULL) | ||||
| 		return -ENOMEM; | ||||
| 	ring->status_page.obj = default_ctx_obj; | ||||
| 
 | ||||
| 	I915_WRITE(RING_HWS_PGA(ring->mmio_base), | ||||
| 			(u32)ring->status_page.gfx_addr); | ||||
| 	POSTING_READ(RING_HWS_PGA(ring->mmio_base)); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * intel_lr_context_deferred_create() - create the LRC specific bits of a context | ||||
|  * @ctx: LR context to create. | ||||
|  | @ -1734,14 +1755,11 @@ int intel_lr_context_deferred_create(struct intel_context *ctx, | |||
| 	ctx->engine[ring->id].state = ctx_obj; | ||||
| 
 | ||||
| 	if (ctx == ring->default_context) { | ||||
| 		/* The status page is offset 0 from the default context object
 | ||||
| 		 * in LRC mode. */ | ||||
| 		ring->status_page.gfx_addr = i915_gem_obj_ggtt_offset(ctx_obj); | ||||
| 		ring->status_page.page_addr = | ||||
| 				kmap(sg_page(ctx_obj->pages->sgl)); | ||||
| 		if (ring->status_page.page_addr == NULL) | ||||
| 			return -ENOMEM; | ||||
| 		ring->status_page.obj = ctx_obj; | ||||
| 		ret = lrc_setup_hardware_status_page(ring, ctx_obj); | ||||
| 		if (ret) { | ||||
| 			DRM_ERROR("Failed to setup hardware status page\n"); | ||||
| 			goto error; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (ring->id == RCS && !ctx->rcs_initialized) { | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -29,6 +29,7 @@ | |||
| extern const struct intel_renderstate_rodata gen6_null_state; | ||||
| extern const struct intel_renderstate_rodata gen7_null_state; | ||||
| extern const struct intel_renderstate_rodata gen8_null_state; | ||||
| extern const struct intel_renderstate_rodata gen9_null_state; | ||||
| 
 | ||||
| #define RO_RENDERSTATE(_g)						\ | ||||
| 	const struct intel_renderstate_rodata gen ## _g ## _null_state = { \ | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										974
									
								
								drivers/gpu/drm/i915/intel_renderstate_gen9.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										974
									
								
								drivers/gpu/drm/i915/intel_renderstate_gen9.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,974 @@ | |||
| #include "intel_renderstate.h" | ||||
| 
 | ||||
| static const u32 gen9_null_state_relocs[] = { | ||||
| 	0x000007a8, | ||||
| 	0x000007b4, | ||||
| 	0x000007bc, | ||||
| 	0x000007cc, | ||||
| 	-1, | ||||
| }; | ||||
| 
 | ||||
| static const u32 gen9_null_state_batch[] = { | ||||
| 	0x7a000004, | ||||
| 	0x01000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x69040300, | ||||
| 	0x78140000, | ||||
| 	0x04000000, | ||||
| 	0x7820000a, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x80000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x78130002, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x02001808, | ||||
| 	0x781f0004, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x78510009, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x78100007, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00010000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x781b0007, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000800, | ||||
| 	0x00000000, | ||||
| 	0x78110008, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x781e0003, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x781d0009, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x78120002, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x78500003, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x781c0002, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x780c0000, | ||||
| 	0x00000000, | ||||
| 	0x78520003, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x78300000, | ||||
| 	0x08010040, | ||||
| 	0x78310000, | ||||
| 	0x1e000000, | ||||
| 	0x78320000, | ||||
| 	0x1e000000, | ||||
| 	0x78330000, | ||||
| 	0x1e000000, | ||||
| 	0x79190002, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x791a0002, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x791b0002, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x79120000, | ||||
| 	0x00000000, | ||||
| 	0x79130000, | ||||
| 	0x00000000, | ||||
| 	0x79140000, | ||||
| 	0x00000000, | ||||
| 	0x79150000, | ||||
| 	0x00000000, | ||||
| 	0x79160000, | ||||
| 	0x00000000, | ||||
| 	0x78150009, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x78190009, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x781a0009, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x78160009, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x78170009, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x78490001, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x784a0000, | ||||
| 	0x00000000, | ||||
| 	0x784b0000, | ||||
| 	0x00000004, | ||||
| 	0x79170101, | ||||
| 	0x00000000, | ||||
| 	0x00000080, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x79180006, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x79180006, | ||||
| 	0x20000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x79180006, | ||||
| 	0x40000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x79180006, | ||||
| 	0x60000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x61010011, | ||||
| 	0x00000001,	 /* reloc */ | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000001,	 /* reloc */ | ||||
| 	0x00000000, | ||||
| 	0x00000001,	 /* reloc */ | ||||
| 	0x00000000, | ||||
| 	0x00000001, | ||||
| 	0x00000000, | ||||
| 	0x00000001,	 /* reloc */ | ||||
| 	0x00000000, | ||||
| 	0x00001001, | ||||
| 	0x00001001, | ||||
| 	0x00000001, | ||||
| 	0x00001001, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x61020001, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x79000002, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x78050006, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x79040002, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x79040002, | ||||
| 	0x40000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x79040002, | ||||
| 	0x80000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x79040002, | ||||
| 	0xc0000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x79080001, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x790a0001, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x78060003, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x78070003, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x78040001, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x79110000, | ||||
| 	0x00000000, | ||||
| 	0x780d0000, | ||||
| 	0x00000000, | ||||
| 	0x79060000, | ||||
| 	0x00000000, | ||||
| 	0x7907001f, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x7902000f, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x790c000f, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x780a0003, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x78080083, | ||||
| 	0x00004000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x04004000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x08004000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x0c004000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x10004000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x14004000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x18004000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x1c004000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x20004000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x24004000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x28004000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x2c004000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x30004000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x34004000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x38004000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x3c004000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x40004000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x44004000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x48004000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x4c004000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x50004000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x54004000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x58004000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x5c004000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x60004000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x64004000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x68004000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x6c004000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x70004000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x74004000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x78004000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x7c004000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x80004000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x78090043, | ||||
| 	0x02000000, | ||||
| 	0x22220000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x78550003, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x680b0001, | ||||
| 	0x780e0000, | ||||
| 	0x00000e01, | ||||
| 	0x78240000, | ||||
| 	0x00000e41, | ||||
| 	0x784f0000, | ||||
| 	0x80000100, | ||||
| 	0x784d0000, | ||||
| 	0x40000000, | ||||
| 	0x782b0000, | ||||
| 	0x00000000, | ||||
| 	0x782c0000, | ||||
| 	0x00000000, | ||||
| 	0x782d0000, | ||||
| 	0x00000000, | ||||
| 	0x782e0000, | ||||
| 	0x00000000, | ||||
| 	0x782f0000, | ||||
| 	0x00000000, | ||||
| 	0x780f0000, | ||||
| 	0x00000000, | ||||
| 	0x78230000, | ||||
| 	0x00000ea0, | ||||
| 	0x78210000, | ||||
| 	0x00000ec0, | ||||
| 	0x78260000, | ||||
| 	0x00000000, | ||||
| 	0x78270000, | ||||
| 	0x00000000, | ||||
| 	0x78280000, | ||||
| 	0x00000000, | ||||
| 	0x78290000, | ||||
| 	0x00000000, | ||||
| 	0x782a0000, | ||||
| 	0x00000000, | ||||
| 	0x7b000005, | ||||
| 	0x00000004, | ||||
| 	0x00000001, | ||||
| 	0x00000000, | ||||
| 	0x00000001, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x05000000,	 /* cmds end */ | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000,	 /* state start */ | ||||
| 	0x00000000, | ||||
| 	0x3f800000, | ||||
| 	0x3f800000, | ||||
| 	0x3f800000, | ||||
| 	0x3f800000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000, | ||||
| 	0x00000000,	 /* state end */ | ||||
| }; | ||||
| 
 | ||||
| RO_RENDERSTATE(9); | ||||
|  | @ -1845,12 +1845,15 @@ error: | |||
| 
 | ||||
| void intel_cleanup_ring_buffer(struct intel_engine_cs *ring) | ||||
| { | ||||
| 	struct drm_i915_private *dev_priv = to_i915(ring->dev); | ||||
| 	struct intel_ringbuffer *ringbuf = ring->buffer; | ||||
| 	struct drm_i915_private *dev_priv; | ||||
| 	struct intel_ringbuffer *ringbuf; | ||||
| 
 | ||||
| 	if (!intel_ring_initialized(ring)) | ||||
| 		return; | ||||
| 
 | ||||
| 	dev_priv = to_i915(ring->dev); | ||||
| 	ringbuf = ring->buffer; | ||||
| 
 | ||||
| 	intel_stop_ring_buffer(ring); | ||||
| 	WARN_ON(!IS_GEN2(ring->dev) && (I915_READ_MODE(ring) & MODE_IDLE) == 0); | ||||
| 
 | ||||
|  |  | |||
|  | @ -587,6 +587,9 @@ static void chv_pipe_power_well_disable(struct drm_i915_private *dev_priv, | |||
| 		     power_well->data != PIPE_C); | ||||
| 
 | ||||
| 	chv_set_pipe_power_well(dev_priv, power_well, false); | ||||
| 
 | ||||
| 	if (power_well->data == PIPE_A) | ||||
| 		vlv_power_sequencer_reset(dev_priv); | ||||
| } | ||||
| 
 | ||||
| static void check_power_well_state(struct drm_i915_private *dev_priv, | ||||
|  | @ -938,12 +941,20 @@ static struct i915_power_well chv_power_wells[] = { | |||
| 		.data = PUNIT_POWER_WELL_DISP2D, | ||||
| 		.ops = &vlv_display_power_well_ops, | ||||
| 	}, | ||||
| #endif | ||||
| 	{ | ||||
| 		.name = "pipe-a", | ||||
| 		.domains = CHV_PIPE_A_POWER_DOMAINS, | ||||
| 		/*
 | ||||
| 		 * FIXME: pipe A power well seems to be the new disp2d well. | ||||
| 		 * At least all registers seem to be housed there. Figure | ||||
| 		 * out if this a a temporary situation in pre-production | ||||
| 		 * hardware or a permanent state of affairs. | ||||
| 		 */ | ||||
| 		.domains = CHV_PIPE_A_POWER_DOMAINS | VLV_DISPLAY_POWER_DOMAINS, | ||||
| 		.data = PIPE_A, | ||||
| 		.ops = &chv_pipe_power_well_ops, | ||||
| 	}, | ||||
| #if 0 | ||||
| 	{ | ||||
| 		.name = "pipe-b", | ||||
| 		.domains = CHV_PIPE_B_POWER_DOMAINS, | ||||
|  | @ -1137,12 +1148,9 @@ static void vlv_cmnlane_wa(struct drm_i915_private *dev_priv) | |||
| 	struct i915_power_well *disp2d = | ||||
| 		lookup_power_well(dev_priv, PUNIT_POWER_WELL_DISP2D); | ||||
| 
 | ||||
| 	/* nothing to do if common lane is already off */ | ||||
| 	if (!cmn->ops->is_enabled(dev_priv, cmn)) | ||||
| 		return; | ||||
| 
 | ||||
| 	/* If the display might be already active skip this */ | ||||
| 	if (disp2d->ops->is_enabled(dev_priv, disp2d) && | ||||
| 	if (cmn->ops->is_enabled(dev_priv, cmn) && | ||||
| 	    disp2d->ops->is_enabled(dev_priv, disp2d) && | ||||
| 	    I915_READ(DPIO_CTL) & DPIO_CMNRST) | ||||
| 		return; | ||||
| 
 | ||||
|  |  | |||
|  | @ -37,6 +37,20 @@ | |||
| #include <drm/i915_drm.h> | ||||
| #include "i915_drv.h" | ||||
| 
 | ||||
| static bool | ||||
| format_is_yuv(uint32_t format) | ||||
| { | ||||
| 	switch (format) { | ||||
| 	case DRM_FORMAT_YUYV: | ||||
| 	case DRM_FORMAT_UYVY: | ||||
| 	case DRM_FORMAT_VYUY: | ||||
| 	case DRM_FORMAT_YVYU: | ||||
| 		return true; | ||||
| 	default: | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static int usecs_to_scanlines(const struct drm_display_mode *mode, int usecs) | ||||
| { | ||||
| 	/* paranoia */ | ||||
|  | @ -46,7 +60,23 @@ static int usecs_to_scanlines(const struct drm_display_mode *mode, int usecs) | |||
| 	return DIV_ROUND_UP(usecs * mode->crtc_clock, 1000 * mode->crtc_htotal); | ||||
| } | ||||
| 
 | ||||
| static bool intel_pipe_update_start(struct intel_crtc *crtc, uint32_t *start_vbl_count) | ||||
| /**
 | ||||
|  * intel_pipe_update_start() - start update of a set of display registers | ||||
|  * @crtc: the crtc of which the registers are going to be updated | ||||
|  * @start_vbl_count: vblank counter return pointer used for error checking | ||||
|  * | ||||
|  * Mark the start of an update to pipe registers that should be updated | ||||
|  * atomically regarding vblank. If the next vblank will happens within | ||||
|  * the next 100 us, this function waits until the vblank passes. | ||||
|  * | ||||
|  * After a successful call to this function, interrupts will be disabled | ||||
|  * until a subsequent call to intel_pipe_update_end(). That is done to | ||||
|  * avoid random delays. The value written to @start_vbl_count should be | ||||
|  * supplied to intel_pipe_update_end() for error checking. | ||||
|  * | ||||
|  * Return: true if the call was successful | ||||
|  */ | ||||
| bool intel_pipe_update_start(struct intel_crtc *crtc, uint32_t *start_vbl_count) | ||||
| { | ||||
| 	struct drm_device *dev = crtc->base.dev; | ||||
| 	const struct drm_display_mode *mode = &crtc->config.adjusted_mode; | ||||
|  | @ -56,8 +86,6 @@ static bool intel_pipe_update_start(struct intel_crtc *crtc, uint32_t *start_vbl | |||
| 	wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base); | ||||
| 	DEFINE_WAIT(wait); | ||||
| 
 | ||||
| 	WARN_ON(!drm_modeset_is_locked(&crtc->base.mutex)); | ||||
| 
 | ||||
| 	vblank_start = mode->crtc_vblank_start; | ||||
| 	if (mode->flags & DRM_MODE_FLAG_INTERLACE) | ||||
| 		vblank_start = DIV_ROUND_UP(vblank_start, 2); | ||||
|  | @ -112,7 +140,16 @@ static bool intel_pipe_update_start(struct intel_crtc *crtc, uint32_t *start_vbl | |||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| static void intel_pipe_update_end(struct intel_crtc *crtc, u32 start_vbl_count) | ||||
| /**
 | ||||
|  * intel_pipe_update_end() - end update of a set of display registers | ||||
|  * @crtc: the crtc of which the registers were updated | ||||
|  * @start_vbl_count: start vblank counter (used for error checking) | ||||
|  * | ||||
|  * Mark the end of an update started with intel_pipe_update_start(). This | ||||
|  * re-enables interrupts and verifies the update was actually completed | ||||
|  * before a vblank using the value of @start_vbl_count. | ||||
|  */ | ||||
| void intel_pipe_update_end(struct intel_crtc *crtc, u32 start_vbl_count) | ||||
| { | ||||
| 	struct drm_device *dev = crtc->base.dev; | ||||
| 	enum pipe pipe = crtc->pipe; | ||||
|  | @ -319,6 +356,45 @@ skl_get_colorkey(struct drm_plane *drm_plane, | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| chv_update_csc(struct intel_plane *intel_plane, uint32_t format) | ||||
| { | ||||
| 	struct drm_i915_private *dev_priv = intel_plane->base.dev->dev_private; | ||||
| 	int plane = intel_plane->plane; | ||||
| 
 | ||||
| 	/* Seems RGB data bypasses the CSC always */ | ||||
| 	if (!format_is_yuv(format)) | ||||
| 		return; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * BT.601 limited range YCbCr -> full range RGB | ||||
| 	 * | ||||
| 	 * |r|   | 6537 4769     0|   |cr  | | ||||
| 	 * |g| = |-3330 4769 -1605| x |y-64| | ||||
| 	 * |b|   |    0 4769  8263|   |cb  | | ||||
| 	 * | ||||
| 	 * Cb and Cr apparently come in as signed already, so no | ||||
| 	 * need for any offset. For Y we need to remove the offset. | ||||
| 	 */ | ||||
| 	I915_WRITE(SPCSCYGOFF(plane), SPCSC_OOFF(0) | SPCSC_IOFF(-64)); | ||||
| 	I915_WRITE(SPCSCCBOFF(plane), SPCSC_OOFF(0) | SPCSC_IOFF(0)); | ||||
| 	I915_WRITE(SPCSCCROFF(plane), SPCSC_OOFF(0) | SPCSC_IOFF(0)); | ||||
| 
 | ||||
| 	I915_WRITE(SPCSCC01(plane), SPCSC_C1(4769) | SPCSC_C0(6537)); | ||||
| 	I915_WRITE(SPCSCC23(plane), SPCSC_C1(-3330) | SPCSC_C0(0)); | ||||
| 	I915_WRITE(SPCSCC45(plane), SPCSC_C1(-1605) | SPCSC_C0(4769)); | ||||
| 	I915_WRITE(SPCSCC67(plane), SPCSC_C1(4769) | SPCSC_C0(0)); | ||||
| 	I915_WRITE(SPCSCC8(plane), SPCSC_C0(8263)); | ||||
| 
 | ||||
| 	I915_WRITE(SPCSCYGICLAMP(plane), SPCSC_IMAX(940) | SPCSC_IMIN(64)); | ||||
| 	I915_WRITE(SPCSCCBICLAMP(plane), SPCSC_IMAX(448) | SPCSC_IMIN(-448)); | ||||
| 	I915_WRITE(SPCSCCRICLAMP(plane), SPCSC_IMAX(448) | SPCSC_IMIN(-448)); | ||||
| 
 | ||||
| 	I915_WRITE(SPCSCYGOCLAMP(plane), SPCSC_OMAX(1023) | SPCSC_OMIN(0)); | ||||
| 	I915_WRITE(SPCSCCBOCLAMP(plane), SPCSC_OMAX(1023) | SPCSC_OMIN(0)); | ||||
| 	I915_WRITE(SPCSCCROCLAMP(plane), SPCSC_OMAX(1023) | SPCSC_OMIN(0)); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc, | ||||
| 		 struct drm_framebuffer *fb, | ||||
|  | @ -430,6 +506,9 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc, | |||
| 
 | ||||
| 	intel_update_primary_plane(intel_crtc); | ||||
| 
 | ||||
| 	if (IS_CHERRYVIEW(dev) && pipe == PIPE_B) | ||||
| 		chv_update_csc(intel_plane, fb->pixel_format); | ||||
| 
 | ||||
| 	I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]); | ||||
| 	I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x); | ||||
| 
 | ||||
|  | @ -438,6 +517,8 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc, | |||
| 	else | ||||
| 		I915_WRITE(SPLINOFF(pipe, plane), linear_offset); | ||||
| 
 | ||||
| 	I915_WRITE(SPCONSTALPHA(pipe, plane), 0); | ||||
| 
 | ||||
| 	I915_WRITE(SPSIZE(pipe, plane), (crtc_h << 16) | crtc_w); | ||||
| 	I915_WRITE(SPCNTR(pipe, plane), sprctl); | ||||
| 	I915_WRITE(SPSURF(pipe, plane), i915_gem_obj_ggtt_offset(obj) + | ||||
|  | @ -1002,20 +1083,6 @@ ilk_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key) | |||
| 		key->flags = I915_SET_COLORKEY_NONE; | ||||
| } | ||||
| 
 | ||||
| static bool | ||||
| format_is_yuv(uint32_t format) | ||||
| { | ||||
| 	switch (format) { | ||||
| 	case DRM_FORMAT_YUYV: | ||||
| 	case DRM_FORMAT_UYVY: | ||||
| 	case DRM_FORMAT_VYUY: | ||||
| 	case DRM_FORMAT_YVYU: | ||||
| 		return true; | ||||
| 	default: | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static bool colorkey_enabled(struct intel_plane *intel_plane) | ||||
| { | ||||
| 	struct drm_intel_sprite_colorkey key; | ||||
|  | @ -1032,8 +1099,7 @@ intel_check_sprite_plane(struct drm_plane *plane, | |||
| 	struct intel_crtc *intel_crtc = to_intel_crtc(state->crtc); | ||||
| 	struct intel_plane *intel_plane = to_intel_plane(plane); | ||||
| 	struct drm_framebuffer *fb = state->fb; | ||||
| 	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); | ||||
| 	struct drm_i915_gem_object *obj = intel_fb->obj; | ||||
| 	struct drm_i915_gem_object *obj = intel_fb_obj(fb); | ||||
| 	int crtc_x, crtc_y; | ||||
| 	unsigned int crtc_w, crtc_h; | ||||
| 	uint32_t src_x, src_y, src_w, src_h; | ||||
|  | @ -1192,34 +1258,18 @@ intel_check_sprite_plane(struct drm_plane *plane, | |||
| } | ||||
| 
 | ||||
| static int | ||||
| intel_commit_sprite_plane(struct drm_plane *plane, | ||||
| intel_prepare_sprite_plane(struct drm_plane *plane, | ||||
| 			   struct intel_plane_state *state) | ||||
| { | ||||
| 	struct drm_device *dev = plane->dev; | ||||
| 	struct drm_crtc *crtc = state->crtc; | ||||
| 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||||
| 	struct intel_plane *intel_plane = to_intel_plane(plane); | ||||
| 	enum pipe pipe = intel_crtc->pipe; | ||||
| 	struct drm_framebuffer *fb = state->fb; | ||||
| 	struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); | ||||
| 	struct drm_i915_gem_object *obj = intel_fb->obj; | ||||
| 	struct drm_i915_gem_object *old_obj = intel_plane->obj; | ||||
| 	int crtc_x, crtc_y; | ||||
| 	unsigned int crtc_w, crtc_h; | ||||
| 	uint32_t src_x, src_y, src_w, src_h; | ||||
| 	struct drm_rect *dst = &state->dst; | ||||
| 	const struct drm_rect *clip = &state->clip; | ||||
| 	bool primary_enabled; | ||||
| 	struct drm_i915_gem_object *obj = intel_fb_obj(fb); | ||||
| 	struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->fb); | ||||
| 	int ret; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * If the sprite is completely covering the primary plane, | ||||
| 	 * we can disable the primary and save power. | ||||
| 	 */ | ||||
| 	primary_enabled = !drm_rect_equals(dst, clip) || colorkey_enabled(intel_plane); | ||||
| 	WARN_ON(!primary_enabled && !state->visible && intel_crtc->active); | ||||
| 
 | ||||
| 
 | ||||
| 	if (old_obj != obj) { | ||||
| 		mutex_lock(&dev->struct_mutex); | ||||
| 
 | ||||
|  | @ -1229,7 +1279,7 @@ intel_commit_sprite_plane(struct drm_plane *plane, | |||
| 		 * the sprite planes only require 128KiB alignment and 32 PTE | ||||
| 		 * padding. | ||||
| 		 */ | ||||
| 		ret = intel_pin_and_fence_fb_obj(dev, obj, NULL); | ||||
| 		ret = intel_pin_and_fence_fb_obj(plane, fb, NULL); | ||||
| 		if (ret == 0) | ||||
| 			i915_gem_track_fb(old_obj, obj, | ||||
| 					  INTEL_FRONTBUFFER_SPRITE(pipe)); | ||||
|  | @ -1238,6 +1288,35 @@ intel_commit_sprite_plane(struct drm_plane *plane, | |||
| 			return ret; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| intel_commit_sprite_plane(struct drm_plane *plane, | ||||
| 			  struct intel_plane_state *state) | ||||
| { | ||||
| 	struct drm_device *dev = plane->dev; | ||||
| 	struct drm_crtc *crtc = state->crtc; | ||||
| 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||||
| 	struct intel_plane *intel_plane = to_intel_plane(plane); | ||||
| 	enum pipe pipe = intel_crtc->pipe; | ||||
| 	struct drm_framebuffer *fb = state->fb; | ||||
| 	struct drm_i915_gem_object *obj = intel_fb_obj(fb); | ||||
| 	struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->fb); | ||||
| 	int crtc_x, crtc_y; | ||||
| 	unsigned int crtc_w, crtc_h; | ||||
| 	uint32_t src_x, src_y, src_w, src_h; | ||||
| 	struct drm_rect *dst = &state->dst; | ||||
| 	const struct drm_rect *clip = &state->clip; | ||||
| 	bool primary_enabled; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * If the sprite is completely covering the primary plane, | ||||
| 	 * we can disable the primary and save power. | ||||
| 	 */ | ||||
| 	primary_enabled = !drm_rect_equals(dst, clip) || colorkey_enabled(intel_plane); | ||||
| 	WARN_ON(!primary_enabled && !state->visible && intel_crtc->active); | ||||
| 
 | ||||
| 	intel_plane->crtc_x = state->orig_dst.x1; | ||||
| 	intel_plane->crtc_y = state->orig_dst.y1; | ||||
| 	intel_plane->crtc_w = drm_rect_width(&state->orig_dst); | ||||
|  | @ -1298,8 +1377,6 @@ intel_commit_sprite_plane(struct drm_plane *plane, | |||
| 		intel_unpin_fb_obj(old_obj); | ||||
| 		mutex_unlock(&dev->struct_mutex); | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
|  | @ -1339,7 +1416,12 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, | |||
| 	if (ret) | ||||
| 		return ret; | ||||
| 
 | ||||
| 	return intel_commit_sprite_plane(plane, &state); | ||||
| 	ret = intel_prepare_sprite_plane(plane, &state); | ||||
| 	if (ret) | ||||
| 		return ret; | ||||
| 
 | ||||
| 	intel_commit_sprite_plane(plane, &state); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
|  |  | |||
|  | @ -194,15 +194,13 @@ static void vlv_force_wake_reset(struct drm_i915_private *dev_priv) | |||
| static void __vlv_force_wake_get(struct drm_i915_private *dev_priv, | ||||
| 						int fw_engine) | ||||
| { | ||||
| 	/*
 | ||||
| 	 * WaRsDontPollForAckOnClearingFWBits:vlv | ||||
| 	 * Hardware clears ack bits lazily (only when all ack | ||||
| 	 * bits become 0) so don't poll for individiual ack | ||||
| 	 * bits to be clear here like on other platforms. | ||||
| 	 */ | ||||
| 
 | ||||
| 	/* Check for Render Engine */ | ||||
| 	if (FORCEWAKE_RENDER & fw_engine) { | ||||
| 		if (wait_for_atomic((__raw_i915_read32(dev_priv, | ||||
| 						FORCEWAKE_ACK_VLV) & | ||||
| 						FORCEWAKE_KERNEL) == 0, | ||||
| 					FORCEWAKE_ACK_TIMEOUT_MS)) | ||||
| 			DRM_ERROR("Timed out: Render forcewake old ack to clear.\n"); | ||||
| 
 | ||||
| 		__raw_i915_write32(dev_priv, FORCEWAKE_VLV, | ||||
| 				   _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL)); | ||||
|  | @ -216,6 +214,11 @@ static void __vlv_force_wake_get(struct drm_i915_private *dev_priv, | |||
| 
 | ||||
| 	/* Check for Media Engine */ | ||||
| 	if (FORCEWAKE_MEDIA & fw_engine) { | ||||
| 		if (wait_for_atomic((__raw_i915_read32(dev_priv, | ||||
| 						FORCEWAKE_ACK_MEDIA_VLV) & | ||||
| 						FORCEWAKE_KERNEL) == 0, | ||||
| 					FORCEWAKE_ACK_TIMEOUT_MS)) | ||||
| 			DRM_ERROR("Timed out: Media forcewake old ack to clear.\n"); | ||||
| 
 | ||||
| 		__raw_i915_write32(dev_priv, FORCEWAKE_MEDIA_VLV, | ||||
| 				   _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL)); | ||||
|  | @ -296,6 +299,154 @@ static void vlv_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine) | |||
| 	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); | ||||
| } | ||||
| 
 | ||||
| static void __gen9_gt_force_wake_mt_reset(struct drm_i915_private *dev_priv) | ||||
| { | ||||
| 	__raw_i915_write32(dev_priv, FORCEWAKE_RENDER_GEN9, | ||||
| 			_MASKED_BIT_DISABLE(0xffff)); | ||||
| 
 | ||||
| 	__raw_i915_write32(dev_priv, FORCEWAKE_MEDIA_GEN9, | ||||
| 			_MASKED_BIT_DISABLE(0xffff)); | ||||
| 
 | ||||
| 	__raw_i915_write32(dev_priv, FORCEWAKE_BLITTER_GEN9, | ||||
| 			_MASKED_BIT_DISABLE(0xffff)); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| __gen9_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine) | ||||
| { | ||||
| 	/* Check for Render Engine */ | ||||
| 	if (FORCEWAKE_RENDER & fw_engine) { | ||||
| 		if (wait_for_atomic((__raw_i915_read32(dev_priv, | ||||
| 						FORCEWAKE_ACK_RENDER_GEN9) & | ||||
| 						FORCEWAKE_KERNEL) == 0, | ||||
| 					FORCEWAKE_ACK_TIMEOUT_MS)) | ||||
| 			DRM_ERROR("Timed out: Render forcewake old ack to clear.\n"); | ||||
| 
 | ||||
| 		__raw_i915_write32(dev_priv, FORCEWAKE_RENDER_GEN9, | ||||
| 				   _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL)); | ||||
| 
 | ||||
| 		if (wait_for_atomic((__raw_i915_read32(dev_priv, | ||||
| 						FORCEWAKE_ACK_RENDER_GEN9) & | ||||
| 						FORCEWAKE_KERNEL), | ||||
| 					FORCEWAKE_ACK_TIMEOUT_MS)) | ||||
| 			DRM_ERROR("Timed out: waiting for Render to ack.\n"); | ||||
| 	} | ||||
| 
 | ||||
| 	/* Check for Media Engine */ | ||||
| 	if (FORCEWAKE_MEDIA & fw_engine) { | ||||
| 		if (wait_for_atomic((__raw_i915_read32(dev_priv, | ||||
| 						FORCEWAKE_ACK_MEDIA_GEN9) & | ||||
| 						FORCEWAKE_KERNEL) == 0, | ||||
| 					FORCEWAKE_ACK_TIMEOUT_MS)) | ||||
| 			DRM_ERROR("Timed out: Media forcewake old ack to clear.\n"); | ||||
| 
 | ||||
| 		__raw_i915_write32(dev_priv, FORCEWAKE_MEDIA_GEN9, | ||||
| 				   _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL)); | ||||
| 
 | ||||
| 		if (wait_for_atomic((__raw_i915_read32(dev_priv, | ||||
| 						FORCEWAKE_ACK_MEDIA_GEN9) & | ||||
| 						FORCEWAKE_KERNEL), | ||||
| 					FORCEWAKE_ACK_TIMEOUT_MS)) | ||||
| 			DRM_ERROR("Timed out: waiting for Media to ack.\n"); | ||||
| 	} | ||||
| 
 | ||||
| 	/* Check for Blitter Engine */ | ||||
| 	if (FORCEWAKE_BLITTER & fw_engine) { | ||||
| 		if (wait_for_atomic((__raw_i915_read32(dev_priv, | ||||
| 						FORCEWAKE_ACK_BLITTER_GEN9) & | ||||
| 						FORCEWAKE_KERNEL) == 0, | ||||
| 					FORCEWAKE_ACK_TIMEOUT_MS)) | ||||
| 			DRM_ERROR("Timed out: Blitter forcewake old ack to clear.\n"); | ||||
| 
 | ||||
| 		__raw_i915_write32(dev_priv, FORCEWAKE_BLITTER_GEN9, | ||||
| 				   _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL)); | ||||
| 
 | ||||
| 		if (wait_for_atomic((__raw_i915_read32(dev_priv, | ||||
| 						FORCEWAKE_ACK_BLITTER_GEN9) & | ||||
| 						FORCEWAKE_KERNEL), | ||||
| 					FORCEWAKE_ACK_TIMEOUT_MS)) | ||||
| 			DRM_ERROR("Timed out: waiting for Blitter to ack.\n"); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| __gen9_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine) | ||||
| { | ||||
| 	/* Check for Render Engine */ | ||||
| 	if (FORCEWAKE_RENDER & fw_engine) | ||||
| 		__raw_i915_write32(dev_priv, FORCEWAKE_RENDER_GEN9, | ||||
| 				_MASKED_BIT_DISABLE(FORCEWAKE_KERNEL)); | ||||
| 
 | ||||
| 	/* Check for Media Engine */ | ||||
| 	if (FORCEWAKE_MEDIA & fw_engine) | ||||
| 		__raw_i915_write32(dev_priv, FORCEWAKE_MEDIA_GEN9, | ||||
| 				_MASKED_BIT_DISABLE(FORCEWAKE_KERNEL)); | ||||
| 
 | ||||
| 	/* Check for Blitter Engine */ | ||||
| 	if (FORCEWAKE_BLITTER & fw_engine) | ||||
| 		__raw_i915_write32(dev_priv, FORCEWAKE_BLITTER_GEN9, | ||||
| 				_MASKED_BIT_DISABLE(FORCEWAKE_KERNEL)); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| gen9_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine) | ||||
| { | ||||
| 	unsigned long irqflags; | ||||
| 
 | ||||
| 	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); | ||||
| 
 | ||||
| 	if (FORCEWAKE_RENDER & fw_engine) { | ||||
| 		if (dev_priv->uncore.fw_rendercount++ == 0) | ||||
| 			dev_priv->uncore.funcs.force_wake_get(dev_priv, | ||||
| 							FORCEWAKE_RENDER); | ||||
| 	} | ||||
| 
 | ||||
| 	if (FORCEWAKE_MEDIA & fw_engine) { | ||||
| 		if (dev_priv->uncore.fw_mediacount++ == 0) | ||||
| 			dev_priv->uncore.funcs.force_wake_get(dev_priv, | ||||
| 							FORCEWAKE_MEDIA); | ||||
| 	} | ||||
| 
 | ||||
| 	if (FORCEWAKE_BLITTER & fw_engine) { | ||||
| 		if (dev_priv->uncore.fw_blittercount++ == 0) | ||||
| 			dev_priv->uncore.funcs.force_wake_get(dev_priv, | ||||
| 							FORCEWAKE_BLITTER); | ||||
| 	} | ||||
| 
 | ||||
| 	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| gen9_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine) | ||||
| { | ||||
| 	unsigned long irqflags; | ||||
| 
 | ||||
| 	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); | ||||
| 
 | ||||
| 	if (FORCEWAKE_RENDER & fw_engine) { | ||||
| 		WARN_ON(dev_priv->uncore.fw_rendercount == 0); | ||||
| 		if (--dev_priv->uncore.fw_rendercount == 0) | ||||
| 			dev_priv->uncore.funcs.force_wake_put(dev_priv, | ||||
| 							FORCEWAKE_RENDER); | ||||
| 	} | ||||
| 
 | ||||
| 	if (FORCEWAKE_MEDIA & fw_engine) { | ||||
| 		WARN_ON(dev_priv->uncore.fw_mediacount == 0); | ||||
| 		if (--dev_priv->uncore.fw_mediacount == 0) | ||||
| 			dev_priv->uncore.funcs.force_wake_put(dev_priv, | ||||
| 							FORCEWAKE_MEDIA); | ||||
| 	} | ||||
| 
 | ||||
| 	if (FORCEWAKE_BLITTER & fw_engine) { | ||||
| 		WARN_ON(dev_priv->uncore.fw_blittercount == 0); | ||||
| 		if (--dev_priv->uncore.fw_blittercount == 0) | ||||
| 			dev_priv->uncore.funcs.force_wake_put(dev_priv, | ||||
| 							FORCEWAKE_BLITTER); | ||||
| 	} | ||||
| 
 | ||||
| 	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); | ||||
| } | ||||
| 
 | ||||
| static void gen6_force_wake_timer(unsigned long arg) | ||||
| { | ||||
| 	struct drm_i915_private *dev_priv = (void *)arg; | ||||
|  | @ -334,6 +485,9 @@ void intel_uncore_forcewake_reset(struct drm_device *dev, bool restore) | |||
| 	if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev) || IS_BROADWELL(dev)) | ||||
| 		__gen7_gt_force_wake_mt_reset(dev_priv); | ||||
| 
 | ||||
| 	if (IS_GEN9(dev)) | ||||
| 		__gen9_gt_force_wake_mt_reset(dev_priv); | ||||
| 
 | ||||
| 	if (restore) { /* If reset with a user forcewake, try to restore */ | ||||
| 		unsigned fw = 0; | ||||
| 
 | ||||
|  | @ -343,6 +497,15 @@ void intel_uncore_forcewake_reset(struct drm_device *dev, bool restore) | |||
| 
 | ||||
| 			if (dev_priv->uncore.fw_mediacount) | ||||
| 				fw |= FORCEWAKE_MEDIA; | ||||
| 		} else if (IS_GEN9(dev)) { | ||||
| 			if (dev_priv->uncore.fw_rendercount) | ||||
| 				fw |= FORCEWAKE_RENDER; | ||||
| 
 | ||||
| 			if (dev_priv->uncore.fw_mediacount) | ||||
| 				fw |= FORCEWAKE_MEDIA; | ||||
| 
 | ||||
| 			if (dev_priv->uncore.fw_blittercount) | ||||
| 				fw |= FORCEWAKE_BLITTER; | ||||
| 		} else { | ||||
| 			if (dev_priv->uncore.forcewake_count) | ||||
| 				fw = FORCEWAKE_ALL; | ||||
|  | @ -414,6 +577,10 @@ void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine) | |||
| 
 | ||||
| 	intel_runtime_pm_get(dev_priv); | ||||
| 
 | ||||
| 	/* Redirect to Gen9 specific routine */ | ||||
| 	if (IS_GEN9(dev_priv->dev)) | ||||
| 		return gen9_force_wake_get(dev_priv, fw_engine); | ||||
| 
 | ||||
| 	/* Redirect to VLV specific routine */ | ||||
| 	if (IS_VALLEYVIEW(dev_priv->dev)) | ||||
| 		return vlv_force_wake_get(dev_priv, fw_engine); | ||||
|  | @ -435,6 +602,12 @@ void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine) | |||
| 	if (!dev_priv->uncore.funcs.force_wake_put) | ||||
| 		return; | ||||
| 
 | ||||
| 	/* Redirect to Gen9 specific routine */ | ||||
| 	if (IS_GEN9(dev_priv->dev)) { | ||||
| 		gen9_force_wake_put(dev_priv, fw_engine); | ||||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Redirect to VLV specific routine */ | ||||
| 	if (IS_VALLEYVIEW(dev_priv->dev)) { | ||||
| 		vlv_force_wake_put(dev_priv, fw_engine); | ||||
|  | @ -855,7 +1028,10 @@ void intel_uncore_init(struct drm_device *dev) | |||
| 
 | ||||
| 	__intel_uncore_early_sanitize(dev, false); | ||||
| 
 | ||||
| 	if (IS_VALLEYVIEW(dev)) { | ||||
| 	if (IS_GEN9(dev)) { | ||||
| 		dev_priv->uncore.funcs.force_wake_get = __gen9_force_wake_get; | ||||
| 		dev_priv->uncore.funcs.force_wake_put = __gen9_force_wake_put; | ||||
| 	} else if (IS_VALLEYVIEW(dev)) { | ||||
| 		dev_priv->uncore.funcs.force_wake_get = __vlv_force_wake_get; | ||||
| 		dev_priv->uncore.funcs.force_wake_put = __vlv_force_wake_put; | ||||
| 	} else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { | ||||
|  |  | |||
|  | @ -876,6 +876,12 @@ struct drm_i915_gem_get_tiling { | |||
| 	 * mmap mapping. | ||||
| 	 */ | ||||
| 	__u32 swizzle_mode; | ||||
| 
 | ||||
| 	/**
 | ||||
| 	 * Returned address bit 6 swizzling required for CPU access through | ||||
| 	 * mmap mapping whilst bound. | ||||
| 	 */ | ||||
| 	__u32 phys_swizzle_mode; | ||||
| }; | ||||
| 
 | ||||
| struct drm_i915_gem_get_aperture { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dave Airlie
				Dave Airlie