13625 lines
464 KiB
Diff
13625 lines
464 KiB
Diff
Start from 2.6.33.y, then pull in 2.6.34, then anholt's for-linus, then
|
|
anholt's drm-intel-next minus a bogus TV detection patch and the AGP/GTT
|
|
splitup.
|
|
|
|
commit 61b8a24d45b1c2ccab371b98f077425d0d73ab7e
|
|
Author: Chris Wilson <chris@chris-wilson.co.uk>
|
|
Date: Thu Jan 7 10:39:13 2010 +0000
|
|
|
|
drm/i915: Replace open-coded eviction in i915_gem_idle()
|
|
|
|
With the introduction of the hang-check, we can safely expect that
|
|
i915_wait_request() will always return even when the GPU hangs, and so
|
|
do not need to open code the wait in order to manually check for the
|
|
hang. Also we do not need to always evict all buffers, so only flush
|
|
the GPU (and wait for it to idle) for KMS, but continue to evict for UMS.
|
|
|
|
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 4b508552539d0a31eb5c62d1bf4847e1fd338eb8
|
|
Author: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Date: Thu Dec 17 14:48:43 2009 +0800
|
|
|
|
drm/i915: Keep MCHBAR always enabled
|
|
|
|
As we need more and more controls within MCHBAR for memory config and
|
|
power management, this trys to keep MCHBAR enabled from driver load and
|
|
only tear down in driver unload.
|
|
|
|
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 4dd298cb92eccc685aace852cab33d36085cffcc
|
|
Author: Eric Anholt <eric@anholt.net>
|
|
Date: Tue Jan 26 09:43:10 2010 -0800
|
|
|
|
drm/i915: Don't reserve compatibility fence regs in KMS mode.
|
|
|
|
The fence start is for compatibility with UMS X Servers before fence
|
|
management. KMS X Servers only started doing tiling after fence
|
|
management appeared.
|
|
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit dd4031f49bbce4b4ed4ad6f0ecf3e7da8bd240aa
|
|
Author: Li Peng <peng.li@linux.intel.com>
|
|
Date: Wed Jan 27 19:01:11 2010 +0800
|
|
|
|
drm/i915: enable memory self refresh on 9xx
|
|
|
|
Enabling memory self refresh (SR) on 9xx needs to set additional
|
|
register bits. On 945, we need bit 31 of FW_BLC_SELF to enable the
|
|
write to self refresh bit and bit 16 to enable the write of self
|
|
refresh watermark. On 915, bit 12 of INSTPM is used to enable SR.
|
|
|
|
SR will take effect when CPU enters C3+ state and its entry/exit
|
|
should be automatically controlled by H/W, driver only needs to set
|
|
SR enable bits in wm update. But this isn't safe in my test on 945
|
|
because GPU is hung. So this patch explicitly enables SR when GPU
|
|
is idle, and disables SR when it is busy. In my test on a netbook of
|
|
945GSE chipset, it saves about 0.8W idle power.
|
|
|
|
Signed-off-by: Li Peng <peng.li@intel.com>
|
|
[anholt: rebased against 33c5fd121eabbccc9103daf6cda36941eb3c349f
|
|
by adding disable of INSTPM SR bit on 915GM for two pipe setup]
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit b71e8e4881b7b8d9d0f622ace6db4d0587198b47
|
|
Author: Jesse Barnes <jbarnes@virtuousgeek.org>
|
|
Date: Fri Jan 29 11:27:07 2010 -0800
|
|
|
|
drm/i915: add dynamic performance control support for Ironlake
|
|
|
|
Ironlake (and 965GM, which this patch doesn't support) supports a
|
|
hardware performance and power management feature that allows it to
|
|
adjust to changes in GPU load over time with software help. The goal
|
|
if this is to maximize performance/power for a given workload.
|
|
|
|
This patch enables that feature, which is also a requirement for
|
|
supporting Intelligent Power Sharing, a feature which allows for
|
|
dynamic budgeting of power between the CPU and GPU in Arrandale
|
|
platforms.
|
|
|
|
Tested-by: ykzhao <yakui.zhao@intel.com>
|
|
[anholt: Resolved against the irq handler loop removal]
|
|
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit bb617ddfd5cfbbd2b657550528a8b9d9827c0c5d
|
|
Author: Matthew Garrett <mjg59@srcf.ucam.org>
|
|
Date: Tue Feb 2 18:30:47 2010 +0000
|
|
|
|
drm/i915: Deobfuscate the render p-state obfuscation
|
|
|
|
The ironlake render p-state support includes some rather odd variable
|
|
names. Clean them up in order to improve the readability of the code.
|
|
|
|
Signed-off-by: Matthew Garrett <mjg@redhat.com>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 5b497c826bdd1e2834fa5cf34a1a513f99bde04a
|
|
Author: Li Peng <peng.li@linux.intel.com>
|
|
Date: Wed Feb 10 01:54:24 2010 +0800
|
|
|
|
drm/i915: Fix OGLC performance regression on 945
|
|
|
|
He Shuang reported an OGLC performance regression introduced in the patch
|
|
"enable memory self refresh on 9xx", In that patch, SR on 945 is disabled
|
|
everytime when calling intel_mark_busy(), while too much of such operation
|
|
will impact performance. Actually disable SR is necessary only when GPU and
|
|
Crtc changing from idle to busy. This patch make such optimization.
|
|
|
|
It fixes upstream bug
|
|
http://bugs.freedesktop.org/show_bug.cgi?id=26422
|
|
|
|
Signed-off-by: Li Peng <peng.li@intel.com>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 8b31f2d2d4c38dd98bc8e1b363984a769b4bcc70
|
|
Author: Jesse Barnes <jbarnes@virtuousgeek.org>
|
|
Date: Thu Feb 4 14:17:47 2010 -0800
|
|
|
|
drm/i915: fix drps disable so unload & re-load works
|
|
|
|
At unload time, we need to disable DRPS, but we need to do it correctly
|
|
or the GPU will hang and we won't be able to load the module again. So
|
|
set the SFCAVM bit so we can properly restore the DRPS config at unload.
|
|
|
|
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 380119c14abe900e7907ba919cd31935c4bd9b26
|
|
Author: Jesse Barnes <jbarnes@virtuousgeek.org>
|
|
Date: Fri Feb 5 12:42:41 2010 -0800
|
|
|
|
drm/i915: provide FBC status in debugfs
|
|
|
|
Tools like powertop want to check the current FBC status and report it
|
|
to the user. So add a debugfs file indicating whether FBC is enabled,
|
|
and if not, why.
|
|
|
|
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 1a96157856ccbdad57e0b2c0fdda90533a035d5b
|
|
Author: Jesse Barnes <jbarnes@virtuousgeek.org>
|
|
Date: Fri Feb 5 12:47:35 2010 -0800
|
|
|
|
drm/i915: provide self-refresh status in debugfs
|
|
|
|
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit cda4b3ba8d82079de2929f637380a6067f446e08
|
|
Author: Daniel Vetter <daniel.vetter@ffwll.ch>
|
|
Date: Thu Feb 11 14:14:42 2010 +0100
|
|
|
|
drm/i915: overlay: nuke readback to flush wc caches
|
|
|
|
I retested this and whatever this papered over, the problem doesn't seem
|
|
to exist anymore.
|
|
|
|
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
|
|
Reviewed-by: Eric Anholt <eric@anholt.net>
|
|
[anholt: fixed up compile warning]
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 80bd60eafb329be40d6e83a4f0e2f2f2b28b900c
|
|
Author: Daniel Vetter <daniel.vetter@ffwll.ch>
|
|
Date: Thu Feb 11 14:14:43 2010 +0100
|
|
|
|
drm/i915: overlay: drop superflous gpu flushes
|
|
|
|
Cache-coherency is maintained by gem. Drop these leftover MI_FLUSH
|
|
commands from the userspace code.
|
|
|
|
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
|
|
Acked-by: Chris Wilson <chris@chris-wilson.co.uk>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit dd4120e04e07feec4275807656a650448b9fd2ae
|
|
Author: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Date: Wed Feb 10 10:39:33 2010 +0800
|
|
|
|
agp/intel: official names for Pineview and Ironlake
|
|
|
|
Print official names for Pineview and Ironlake, which is Intel
|
|
GMA3150 and Intel HD graphics.
|
|
|
|
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 4c0c82c9109dff54cc80493e7b3d39d0ce97b4f0
|
|
Author: Daniel Vetter <daniel.vetter@ffwll.ch>
|
|
Date: Mon Feb 1 13:59:16 2010 +0100
|
|
|
|
drm/i915: move a gtt flush to the correct place
|
|
|
|
No functional change, because gtt flushing is a no-op. Still, try
|
|
to keep the bookkeeping accurate. The if is still slightly wrong
|
|
for with execbuf2 even i915-class hw doesn't always need a fence
|
|
reg for gpu access. But that's for somewhen lateron.
|
|
|
|
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 37da128862c402c8e0f70d42e5f9113dd20ee6e8
|
|
Author: Daniel Vetter <daniel.vetter@ffwll.ch>
|
|
Date: Mon Feb 1 13:59:17 2010 +0100
|
|
|
|
drm/i915: blow away userspace mappings before fence change
|
|
|
|
This aligns it with the other user of i915_gem_clear_fence_reg,
|
|
which blows away the mapping before changing the fence reg.
|
|
|
|
Only affects userspace if it races against itself when changing
|
|
tiling parameters, i.e. behaviour is undefined, anyway.
|
|
|
|
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
|
|
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 4f0dd6f6fd13ef49a298e1f7d300b3d4f9ca8f16
|
|
Author: Owain Ainsworth <zerooa@googlemail.com>
|
|
Date: Thu Feb 18 15:33:00 2010 +0000
|
|
|
|
drm/i915: reduce some of the duplication of tiling checking
|
|
|
|
i915_gem_object_fenceable was mostly just a repeat of the
|
|
i915_gem_object_fence_offset_ok, but also checking the size (which was
|
|
checkecd when we allowed that BO to be tiled in the first place). So
|
|
instead, export the latter function and use it in place.
|
|
|
|
Signed-Off-By: Owain G. Ainsworth <oga@openbsd.org>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit e627564787847102753d565bd49a47a9fbd2b2ee
|
|
Author: Chris Wilson <chris@chris-wilson.co.uk>
|
|
Date: Thu Feb 18 10:24:56 2010 +0000
|
|
|
|
drm/i915: Record batch buffer following GPU error
|
|
|
|
In order to improve our diagnostic capabilities following a GPU hang
|
|
and subsequent reset, we need to record the batch buffer that triggered
|
|
the error. We assume that the current batch buffer, plus a few details
|
|
about what else is on the active list, will be sufficient -- at the very
|
|
least an improvement over nothing.
|
|
|
|
The extra information is stored in /debug/dri/.../i915_error_state
|
|
following an error, and may be decoded using
|
|
intel_gpu_tools/tools/intel_error_decode.
|
|
|
|
v2: Avoid excessive work under spinlocks.
|
|
v3: Include ringbuffer for later analysis.
|
|
v4: Use kunmap correctly and record more buffer state.
|
|
v5: Search ringbuffer for current batch buffer
|
|
v6: Use a work fn for the impossible IRQ error case.
|
|
v7: Avoid non-atomic paths whilst in IRQ context.
|
|
|
|
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 132c106ae1af6c5184fca797366efe24a6a5b3ce
|
|
Author: Eric Anholt <eric@anholt.net>
|
|
Date: Thu Oct 22 16:10:52 2009 -0700
|
|
|
|
agp/intel: Add support for Sandybridge.
|
|
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 404fe3988cc0529bee1a7cb6e9e31096ac003e68
|
|
Author: Eric Anholt <eric@anholt.net>
|
|
Date: Thu Oct 22 16:11:14 2009 -0700
|
|
|
|
drm/i915: Add initial bits for VGA modesetting bringup on Sandybridge.
|
|
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 80e3829ff4b255ab7f05c4baa0a6af3fafd4885c
|
|
Author: Eric Anholt <eric@anholt.net>
|
|
Date: Mon Oct 26 16:44:17 2009 -0700
|
|
|
|
drm/i915: Set up fence registers on sandybridge.
|
|
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit fdda47cece044474e38fc234ee86b0ad889b7e25
|
|
Author: Eric Anholt <eric@anholt.net>
|
|
Date: Mon Nov 2 12:08:22 2009 -0800
|
|
|
|
drm/i915: Fix sandybridge status page setup.
|
|
|
|
The register's moved to the same location as the one for the BCS, it seems.
|
|
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 68904b08da632ce82b551bb1c91111343ba6f715
|
|
Author: Eric Anholt <eric@anholt.net>
|
|
Date: Mon Nov 2 15:33:05 2009 -0800
|
|
|
|
agp/intel: Use a non-reserved value for the cache field of the PTEs.
|
|
|
|
I don't know if this is what we'll want to be using long term, we'll see.
|
|
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit c6372005734d735fa05442971656a83ba9bc2fe1
|
|
Author: Eric Anholt <eric@anholt.net>
|
|
Date: Thu Nov 5 15:30:35 2009 -0800
|
|
|
|
drm/i915: Disable the surface tile swizzling on Sandybridge.
|
|
|
|
I can't explain this, except that it makes my display correct.
|
|
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit e4dc1f5a66bd5e737fe32f8c17c4eef9ed48e2a3
|
|
Author: Eric Anholt <eric@anholt.net>
|
|
Date: Mon Nov 9 14:57:34 2009 -0800
|
|
|
|
drm/i915: Correct locking in the modesetting failure path, fixing a BUG_ON.
|
|
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 439c85dab263af43eddbf229dfdad7b5763dfc27
|
|
Author: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Date: Wed Nov 11 01:25:25 2009 +0800
|
|
|
|
drm/i915, agp/intel: Fix stolen memory size on Sandybridge
|
|
|
|
New memory control config reg at 0x50 should be used for stolen
|
|
memory size detection on Sandybridge.
|
|
|
|
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit fa358e1c80893bf82f1d3d924dbfe10a5a7909c1
|
|
Author: Eric Anholt <eric@anholt.net>
|
|
Date: Thu Jan 7 16:21:46 2010 -0800
|
|
|
|
agp/intel: Add a new Sandybridge HB/IG PCI ID combo.
|
|
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 3fece8822281b539cc61f86fd8e8b42afed9113c
|
|
Author: Eric Anholt <eric@anholt.net>
|
|
Date: Thu Jan 7 15:08:18 2010 -0800
|
|
|
|
drm/i915: Add a new mobile Sandybridge PCI ID.
|
|
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 0cc29ff88697d208b7244d28bdb508b84b4a6acc
|
|
Author: Eric Anholt <eric@anholt.net>
|
|
Date: Fri Jan 8 14:25:16 2010 -0800
|
|
|
|
drm/i915: Disable the hangcheck reset on Sandybridge until we add support.
|
|
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit d37679f2b2661a4a05f260bc6677d8f012ad1d3a
|
|
Author: Eric Anholt <eric@anholt.net>
|
|
Date: Thu Jan 28 16:13:29 2010 -0800
|
|
|
|
drm/i915: Correct the Sandybridge chipset info structs.
|
|
|
|
Disables CXSR until it's done, and sets the mobile bit on mobile.
|
|
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit cc45bac0967148d193bad87edbf20268d474346a
|
|
Author: Eric Anholt <eric@anholt.net>
|
|
Date: Thu Jan 28 16:45:52 2010 -0800
|
|
|
|
drm/i915: More s/IS_IRONLAKE/HAS_PCH_SPLIT for Sandybridge.
|
|
|
|
I think this is pretty much correct. Not really tested.
|
|
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 1035cda8796172825f191fc5a53690a60ae79694
|
|
Author: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Date: Tue Feb 23 14:05:24 2010 +0800
|
|
|
|
drm/i915: Add dependency on the intel agp module
|
|
|
|
See http://bugzilla.kernel.org/show_bug.cgi?id=15021
|
|
|
|
Make sure that the appropriate AGP module is loaded and probed before
|
|
trying to set up the DRM. The DRM already depends on the AGP core,
|
|
but in this case we know the specific AGP driver we need too, and can
|
|
help users avoid the trap of loading the AGP driver after the DRM
|
|
driver.
|
|
|
|
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 749a3068de80d499a4632c20599e18372b150612
|
|
Author: Daniel Vetter <daniel.vetter@ffwll.ch>
|
|
Date: Fri Feb 19 11:51:56 2010 +0100
|
|
|
|
drm/i915: reuse i915_gem_object_put_fence_reg for fence stealing code
|
|
|
|
This has a few functional changes against the old code:
|
|
|
|
* a few more unnecessary loads and stores to the drm_i915_fence_reg
|
|
objects. Also an unnecessary store to the hw fence register.
|
|
|
|
* zaps any userspace mappings before doing other flushes. Only changes
|
|
anything when userspace does racy stuff against itself.
|
|
|
|
* also flush GTT domain. This is a noop, but still try to keep the
|
|
bookkeeping correct.
|
|
|
|
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 8b0f935bf4b29f75849e59a0b51f671bd009b6cb
|
|
Author: Daniel Vetter <daniel.vetter@ffwll.ch>
|
|
Date: Fri Feb 19 11:51:57 2010 +0100
|
|
|
|
drm/i915: fixup active list locking in object_unbind
|
|
|
|
All other accesses take this spinlock, so do this here, too.
|
|
|
|
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 4778b6c5ada71ebe9850005d0321a3a1969cef9c
|
|
Author: Daniel Vetter <daniel.vetter@ffwll.ch>
|
|
Date: Fri Feb 19 11:51:58 2010 +0100
|
|
|
|
drm/i915: extract fence stealing code
|
|
|
|
The spaghetti logic in there tripped up my brain's code parser for a
|
|
few secs. Prevent this from happening again by extracting the fence
|
|
stealing code into a seperate functions. IMHO this slightly clears up
|
|
the code flow.
|
|
|
|
v2: Beautified according to ickle's comments.
|
|
v3: ickle forgot to flush his comment queue ... Now there's also a
|
|
we-are-paranoid BUG_ON in there.
|
|
v4: I've forgotten to switch on my brain when doing v3. Now the BUG_ON
|
|
actually checks something useful.
|
|
v5: Clean up a stale comment as noted by Eric Anholt.
|
|
|
|
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
|
|
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 34c761de7a382135d815ea7cb5a979b33d520484
|
|
Author: Daniel Vetter <daniel.vetter@ffwll.ch>
|
|
Date: Fri Feb 19 11:51:59 2010 +0100
|
|
|
|
drm/i915: ensure lru ordering of fence_list
|
|
|
|
The fence_list should be lru ordered for otherwise we might try
|
|
to steal a fence reg from an active object even though there are
|
|
fences from inactive objects available. lru ordering was obeyed
|
|
for gpu access everywhere save when moving dirty objects from
|
|
flushing_list to active_list.
|
|
|
|
Fixing this cause the code to indent way to much, so I've extracted
|
|
the flushing_list processing logic into its on function.
|
|
|
|
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
|
|
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit f85c68a7feb2bb9d59be8d3faee04d0c4a888ef2
|
|
Author: Daniel Vetter <daniel.vetter@ffwll.ch>
|
|
Date: Fri Feb 19 11:52:00 2010 +0100
|
|
|
|
drm/i915: reuse i915_gpu_idle helper
|
|
|
|
We have it, so use it. This required moving the function to avoid
|
|
a forward declaration.
|
|
|
|
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 2cbc022b1813cf865a79d051dec0c43f19987168
|
|
Author: Daniel Vetter <daniel.vetter@ffwll.ch>
|
|
Date: Fri Feb 19 11:52:01 2010 +0100
|
|
|
|
drm/i915: clean-up i915_gem_flush_gpu_write_domain
|
|
|
|
Now that we have an exact gpu write domain tracking, we don't need
|
|
to move objects to the active list ourself. i915_add_request will
|
|
take care of that under all circumstances.
|
|
|
|
Idea stolen from a patch by Chris Wilson <chris@chris-wilson.co.uk>.
|
|
|
|
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
|
|
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit bee2714db60a22a3e50bedb130bfeb4601eaeaa6
|
|
Author: Daniel Vetter <daniel.vetter@ffwll.ch>
|
|
Date: Fri Feb 19 11:52:02 2010 +0100
|
|
|
|
drm/i915: check for multiple write domains in pin_and_relocate
|
|
|
|
The assumption that an object has only ever one write domain is deeply
|
|
threaded into gem (it's even encoded the the singular of the variable
|
|
name). Don't let userspace screw us over.
|
|
|
|
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 0a0ab3f65aa8f24d12aada76f46db902b9936762
|
|
Author: Jesse Barnes <jbarnes@virtuousgeek.org>
|
|
Date: Thu Feb 11 12:41:05 2010 -0800
|
|
|
|
drm/i915: enable/disable LVDS port at DPMS time
|
|
|
|
It would be good to disable the LVDS port when we shut down the panel
|
|
to save power. We haven't done so until now because we had trouble
|
|
getting the right LVDS parameters from the BIOS. I think we're past
|
|
that now, so enabling and disabling the port should be safe, though it
|
|
would probably be made cleaner with some additional changes to the
|
|
display code, where we also bang on the LVDS reg to set the pairing
|
|
correctly etc.
|
|
|
|
Seems to save a bit of power (up to 300mW in my basic wattsup
|
|
meter testing).
|
|
|
|
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 9dab2f83450d574e05d03058dd2c0ce544a47fcd
|
|
Author: Eric Anholt <eric@anholt.net>
|
|
Date: Fri Feb 26 13:32:11 2010 -0800
|
|
|
|
drm/i915: Don't bother with the BKL for GEM ioctls.
|
|
|
|
We probably don't need it for most of the other driver ioctls as well,
|
|
but we explicitly did locking when doing the GEM pieces. On CPU-bound
|
|
graphics tasks, the BKL was showing up as 1-2% of CPU time.
|
|
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit eaa175e1942fa941c1047159721f838b3dc56263
|
|
Author: Owain G. Ainsworth <zerooa@googlemail.com>
|
|
Date: Wed Mar 3 05:34:29 2010 +0000
|
|
|
|
drm/i915: remove an unnecessary wait_request()
|
|
|
|
The continue just after this call with loop around and wait for the
|
|
request just added just fine. This leads to slightly more compact code.
|
|
|
|
Signed-Off-by: Owain G. Ainsworth <oga@openbsd.org>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 4ab0ede782d4e161ee75e076344d244847892857
|
|
Author: Priit Laes <plaes@plaes.org>
|
|
Date: Tue Mar 2 11:37:00 2010 +0200
|
|
|
|
drm/i915: Rename FBC_C3_IDLE to FBC_CTL_C3_IDLE to match other registers
|
|
|
|
Signed-off-by: Priit Laes <plaes@plaes.org>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit e213ec072ae610dad353481c654b46904b01f830
|
|
Author: Eric Anholt <eric@anholt.net>
|
|
Date: Mon Mar 8 23:41:55 2010 -0800
|
|
|
|
drm/i915: Enable VS timer dispatch.
|
|
|
|
This could resolve HW deadlocks where a unit downstream of the VS is
|
|
waiting for more input, the VS has one vertex queued up but not
|
|
dispatched because it hopes to get one more vertex for 2x4 dispatch,
|
|
and software isn't handing more vertices down because it's waiting for
|
|
rendering to complete. The B-Spec says you should always have this
|
|
bit set.
|
|
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit ae87627922f7f0f0b16c8b24e120f1d4c5574ed5
|
|
Author: Joe Perches <joe@perches.com>
|
|
Date: Thu Mar 11 14:01:38 2010 -0800
|
|
|
|
drivers/gpu/drm/i915/intel_bios.c: fix continuation line formats
|
|
|
|
String constants that are continued on subsequent lines with \ will cause
|
|
spurious whitespace in the resulting output.
|
|
|
|
Signed-off-by: Joe Perches <joe@perches.com>
|
|
Cc: Dave Airlie <airlied@linux.ie>
|
|
Cc: Eric Anholt <eric@anholt.net>
|
|
Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
|
|
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
|
|
[anholt: whacked it to wrap to 80 columns instead]
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit a977b689d5e9163fe9dec0f3c33c4fb76982964e
|
|
Author: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Date: Tue Mar 9 23:37:07 2010 +0800
|
|
|
|
drm/i915: Fix check with IS_GEN6
|
|
|
|
IS_GEN6 missed to include SandyBridge mobile chip, which failed in
|
|
i915_probe_agp() for memory config detection. Fix it with a device
|
|
info flag.
|
|
|
|
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit bced22270e7a871b27cf6df978fbbda1afe010c2
|
|
Author: Dan Carpenter <error27@gmail.com>
|
|
Date: Sat Mar 6 14:05:39 2010 +0300
|
|
|
|
drm/i915: fix small leak on overlay error path
|
|
|
|
We should free "params" before returning.
|
|
|
|
Signed-off-by: Dan Carpenter <error27@gmail.com>
|
|
Reviewed-by: Daniel Vetter <daniel@ffwll.ch>
|
|
Cc: stable@kernel.org (for .33)
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 9f3dd99fc14b1344a34132011d189e44ca94faab
|
|
Author: Eric Anholt <eric@anholt.net>
|
|
Date: Thu Mar 18 11:24:06 2010 -0700
|
|
|
|
agp/intel: Respect the GTT size on Sandybridge for scratch page setup.
|
|
|
|
This is similar to 14bc490bbdf1b194ad1f5f3d2a0a27edfdf78986 which
|
|
respected it for how much of the GTT we would actually use. Now we
|
|
won't clear beyond allocated memory when filling the GTT with scratch
|
|
page addresses.
|
|
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit aa46089ff1f59213cfd0cee248485830b60e2ba6
|
|
Author: Eric Anholt <eric@anholt.net>
|
|
Date: Thu Mar 18 12:19:37 2010 -0700
|
|
|
|
agp/intel: Don't do the chipset flush on Sandybridge.
|
|
|
|
This CPU should be coherent with graphics in this direction, though
|
|
flushing graphics caches are still required. Fixes a system reset on
|
|
module load on Sandybridge with 4G+ memory.
|
|
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 57cf4aac610bac23c5469d6e65d56004be4ebfab
|
|
Author: Eric Anholt <eric@anholt.net>
|
|
Date: Thu Mar 18 13:21:14 2010 -0700
|
|
|
|
drm/i915: Set up the documented clock gating on Sandybridge and Ironlake.
|
|
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 3b0f299bd7b2ecc2ed71f539aff433eb74a59526
|
|
Author: Daniel Vetter <daniel.vetter@ffwll.ch>
|
|
Date: Thu Mar 18 09:22:12 2010 +0100
|
|
|
|
drm/intel: fix up set_tiling for untiled->tiled transition
|
|
|
|
Bug introduced in
|
|
|
|
commit 10ae9bd25acf394c8fa2f9d795dfa9cec4d19ed6
|
|
Author: Daniel Vetter <daniel.vetter@ffwll.ch>
|
|
Date: Mon Feb 1 13:59:17 2010 +0100
|
|
|
|
drm/i915: blow away userspace mappings before fence change
|
|
|
|
The problem is that when there's no fence reg assigned and the object
|
|
is mapped at a fenceable offset in the gtt, the userspace mappings won't
|
|
be torn down. Which happens on untiled->tiled transition quite often
|
|
on 4th gen and later because there fencing does not have any special
|
|
alignment constraints (as opposed to 2nd and 3rd gen on which I've tested
|
|
the original commit).
|
|
|
|
Bugzilla: http://bugs.freedesktop.org/show_bug.cgi?id=26993
|
|
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
|
|
Tested-by: Eric Anholt <eric@anholt.net> (fixes OpenArena)
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit a84f55fc0dfb2d5d5a71b2662cb6a438955865d8
|
|
Author: Eric Anholt <eric@anholt.net>
|
|
Date: Wed Mar 17 13:48:06 2010 -0700
|
|
|
|
drm/i915: Stop trying to use ACPI lid status to determine LVDS connection.
|
|
|
|
I've been getting more and more quirk reports about this. It seems
|
|
clear at this point that other OSes are not using this for determining
|
|
whether the integrated panel should be turned on, and it is not
|
|
reliable for doing so. Better to light up an unintended panel than to
|
|
not light up the only usable output on the system.
|
|
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>
|
|
|
|
commit e08daaf2d1c43bf6321fd16ac07a784afcfc3a93
|
|
Author: Robert Hooker <sarvatt@ubuntu.com>
|
|
Date: Fri Mar 19 15:13:27 2010 -0400
|
|
|
|
drm/i915: Disable FBC on 915GM and 945GM.
|
|
|
|
It is causing hangs after a suspend/resume cycle with the default
|
|
powersave=1 module option on these chipsets since 2.6.32-rc.
|
|
|
|
BugLink: http://bugs.launchpad.net/bugs/492392
|
|
Signed-off-by: Robert Hooker <sarvatt@ubuntu.com>
|
|
Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit c438e43c09f6c2afe32571a4096e27dbd221a616
|
|
Author: Daniel Vetter <daniel.vetter@ffwll.ch>
|
|
Date: Mon Mar 8 13:35:02 2010 +0100
|
|
|
|
drm/i915: introduce to_intel_bo helper
|
|
|
|
This is a purely cosmetic change to make changes in this area easier.
|
|
And hey, it's not only clearer and typechecked, but actually shorter,
|
|
too!
|
|
|
|
[anholt: To clarify, this is a change to let us later make
|
|
drm_i915_gem_object subclass drm_gem_object, instead of having
|
|
drm_gem_object have a pointer to i915's private data]
|
|
|
|
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
|
|
Acked-by: Dave Airlie <airlied@gmail.com>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 6a891482640b165ac350b83d8f0446f6b09a1a3d
|
|
Author: Daniel Vetter <daniel.vetter@ffwll.ch>
|
|
Date: Fri Mar 19 21:46:23 2010 +0100
|
|
|
|
agp/intel: intel_845_driver is an agp driver!
|
|
|
|
... not a GTT driver. So the additional chipset flush introduced in
|
|
|
|
commit 2162e6a2b0cd5acbb9bd8a3c94e1c1269b078295
|
|
Author: Dave Airlie <airlied@redhat.com>
|
|
Date: Wed Nov 21 16:36:31 2007 +1000
|
|
|
|
agp/intel: Add chipset flushing support for i8xx chipsets.
|
|
|
|
to fix a GTT problem makes absolutely no sense. If this would really be needed
|
|
for AGP chipsets, too, we should add it to all i8xx agp drivers, not just one.
|
|
|
|
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit d6a705b18cf0635af7c7b033e46051d9ed62df64
|
|
Author: Eric Anholt <eric@anholt.net>
|
|
Date: Thu Mar 25 11:11:14 2010 -0700
|
|
|
|
drm/i915: Rename intel_output to intel_encoder.
|
|
|
|
The intel_output naming is inherited from the UMS code, which had a
|
|
structure of screen -> CRTC -> output. The DRM code has an additional
|
|
notion of encoder/connector, so the structure is screen -> CRTC ->
|
|
encoder -> connector. This is a useful structure for SDVO encoders
|
|
which can support multiple connectors (each of which requires
|
|
different programming in the one encoder and could be connected to
|
|
different CRTCs), or for DVI-I, where multiple encoders feed into the
|
|
connector for whether it's used for digital or analog. Most of our
|
|
code is encoder-related, so transition it to talking about encoders
|
|
before we start trying to distinguish connectors.
|
|
|
|
This patch is produced by sed s/intel_output/intel_encoder/ over the
|
|
driver.
|
|
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 9feb424d3e107e74e2ed9dfbce6c34a20d3eff0d
|
|
Author: Eric Anholt <eric@anholt.net>
|
|
Date: Thu Mar 25 11:48:48 2010 -0700
|
|
|
|
drm/i915: Rename many remaining uses of "output" to encoder or connector.
|
|
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit fdb1359d8e086da1139424be81dba17596b59c06
|
|
Author: Stefan Bader <stefan.bader@canonical.com>
|
|
Date: Mon Mar 29 17:53:12 2010 +0200
|
|
|
|
drm/i915: Add no_lvds entry for the Clientron U800
|
|
|
|
BugLink: http://bugs.launchpad.net/ubuntu/bugs/544671
|
|
|
|
This system claims to have a LVDS but has not.
|
|
|
|
Signed-off-by: Stephane Graber <stgraber@ubuntu.com>
|
|
Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
|
|
CC: stable@kernel.org
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit cdff9756ece2333713af35eedefffc58721a0eab
|
|
Author: Zhao Yakui <yakui.zhao@intel.com>
|
|
Date: Wed Apr 7 17:11:22 2010 +0800
|
|
|
|
drm/i915: Ignore LVDS EDID when it is unavailabe or invalid
|
|
|
|
This trys to shut up complains about invalid LVDS EDID during
|
|
mode probe, but uses fixed panel mode directly for panels with
|
|
broken EDID.
|
|
|
|
https://bugs.freedesktop.org/show_bug.cgi?id=23099
|
|
https://bugs.freedesktop.org/show_bug.cgi?id=26395
|
|
|
|
Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
|
|
Tested-by: Sitsofe Wheeler <sitsofe@yahoo.com>
|
|
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 827b98413e1ca8c3657fe83b39671c87503702b8
|
|
Author: Adam Jackson <ajax@redhat.com>
|
|
Date: Fri Apr 16 18:20:57 2010 -0400
|
|
|
|
drm/i915: Attempt to fix watermark setup on 85x (v2)
|
|
|
|
IS_MOBILE() catches 85x, so we'd always try to use the 9xx FIFO sizing;
|
|
since there's an explicit 85x version, this seems wrong.
|
|
|
|
v2: Handle 830m correctly too.
|
|
|
|
Signed-off-by: Adam Jackson <ajax@redhat.com>
|
|
Reviewed-by: Eric Anholt <eric@anholt.net>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 5c9713caf3a211c7af399036dbc70defa4df09a4
|
|
Author: Adam Jackson <ajax@redhat.com>
|
|
Date: Thu Apr 15 14:03:30 2010 -0400
|
|
|
|
drm/i915: Fix 82854 PCI ID, and treat it like other 85X
|
|
|
|
pci.ids and the datasheet both say it's 358e, not 35e8.
|
|
|
|
Signed-off-by: Adam Jackson <ajax@redhat.com>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 6a399e79b2e61ca95a8b88a6f49e1382aea23f75
|
|
Author: Zhang Rui <rui.zhang@intel.com>
|
|
Date: Mon Mar 29 15:12:16 2010 +0800
|
|
|
|
drm/i915: set DIDL using the ACPI video output device _ADR method return.
|
|
|
|
we used to set the DIDL in the output device detected order.
|
|
But some BIOSes requires it to be initialized in the ACPI device order.
|
|
e.g. the value of the first field in DIDL stands for the first
|
|
ACPI video output device in ACPI namespace.
|
|
|
|
Now we initialize the DIDL using the device id, i.e. _ADR return value,
|
|
of each ACPI video device, if it is not 0.
|
|
https://bugzilla.kernel.org/show_bug.cgi?id=15054
|
|
|
|
Signed-off-by: Zhang Rui <rui.zhang@intel.com>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit fabde8feddccbfc88c48e3e1c3e97d58094988c8
|
|
Author: Daniel Vetter <daniel.vetter@ffwll.ch>
|
|
Date: Sat Apr 17 15:12:03 2010 +0200
|
|
|
|
drm/i915: fix tiling limits for i915 class hw v2
|
|
|
|
Current code is definitely crap: Largest pitch allowed spills into
|
|
the TILING_Y bit of the fence registers ... :(
|
|
|
|
I've rewritten the limits check under the assumption that 3rd gen hw
|
|
has a 3d pitch limit of 8kb (like 2nd gen). This is supported by an
|
|
otherwise totally misleading XXX comment.
|
|
|
|
This bug mostly resulted in tiling-corrupted pixmaps because the kernel
|
|
allowed too wide buffers to be tiled. Bug brought to the light by the
|
|
xf86-video-intel 2.11 release because that unconditionally enabled
|
|
tiling for pixmaps, relying on the kernel to check things. Tiling for
|
|
the framebuffer was not affected because the ddx does some additional
|
|
checks there ensure the buffer is within hw-limits.
|
|
|
|
v2: Instead of computing the value that would be written into the
|
|
hw fence registers and then checking the limits simply check whether
|
|
the stride is above the 8kb limit. To better document the hw, add
|
|
some WARN_ONs in i915_write_fence_reg like I've done for the i830
|
|
case (using the right limits).
|
|
|
|
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
|
|
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=27449
|
|
Tested-by: Alexander Lam <lambchop468@gmail.com>
|
|
Cc: stable@kernel.org
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit d69abbbe43a7697ed7c12a7c57008023e92cffd2
|
|
Author: Li Zefan <lizf@cn.fujitsu.com>
|
|
Date: Thu Mar 11 16:41:45 2010 +0800
|
|
|
|
drm/i915: Convert some trace events to DEFINE_TRACE
|
|
|
|
Use DECLARE_EVENT_CLASS to remove duplicate code:
|
|
|
|
text data bss dec hex filename
|
|
14655 2732 15 17402 43fa i915_trace_points.o.orig
|
|
11625 2732 10 14367 381f i915_trace_points.o
|
|
|
|
8 events are converted:
|
|
|
|
i915_gem_object: i915_gem_object_{unbind, destroy}
|
|
i915_gem_request: i915_gem_request_{complete, retire, wait_begin, wait_end}
|
|
i915_ring: i915_ring_{wait_begin, wait_end}
|
|
|
|
No functional change.
|
|
|
|
Signed-off-by: Li Zefan <lizf@cn.fujitsu.com>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 2f99e2fb0673252dc3559ed69ff3ec96fb579166
|
|
Author: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Date: Tue Mar 30 14:39:26 2010 +0800
|
|
|
|
drm/i915: use encoder_list for hotplug callback
|
|
|
|
Instead of walking through drm connector_list uses encoder_list
|
|
for calling hotplug functions which is consistent with intel display
|
|
hotplug reporting.
|
|
|
|
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit fefa3dcedc5f630f653bfd6b39ff172a0e5e171e
|
|
Author: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Date: Tue Mar 30 14:39:27 2010 +0800
|
|
|
|
drm/i915: more conversion from connector_list walk to encoder_list
|
|
|
|
What we really want is encoder info instead of connector, so change
|
|
some more list walk in pipeline setup functions from connector_list
|
|
to encoder_list.
|
|
|
|
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 49c4aec093be9e3a9fa046211a11b88949cf6792
|
|
Author: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Date: Tue Mar 30 14:39:28 2010 +0800
|
|
|
|
drm/i915: Add new 'intel_connector' structure
|
|
|
|
This adds new structure of intel_connector to present drm's
|
|
connector object, which is used to convert from origin single
|
|
output into encoder/connector model.
|
|
|
|
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 2100929e476cc423d08478432b04ac887e7b6b3b
|
|
Author: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Date: Tue Mar 30 14:39:29 2010 +0800
|
|
|
|
drm/i915: Add new helper to return current attached encoder for connector
|
|
|
|
For introducing splitted encoder/connector structure, this helper will return
|
|
connector's attached encoder when needed.
|
|
|
|
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 0059113e16782b363c65dcf6f3041b37783ba190
|
|
Author: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Date: Tue Mar 30 14:39:30 2010 +0800
|
|
|
|
drm/i915: passing drm connector param for load detection
|
|
|
|
In load detection, connector's encoder assignment must be kept
|
|
consistent for proper mode setting, and this makes connector as
|
|
explicit parameter for load detect function to not require single
|
|
data structure to hold both encoder and connector reference, ease
|
|
the transition for splitted encoder/connector model.
|
|
|
|
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 17b2b7b441b69c8ddaff50332e2c55a004c791cb
|
|
Author: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Date: Tue Mar 30 14:39:31 2010 +0800
|
|
|
|
drm/i915: change intel_ddc_get_modes() function parameters
|
|
|
|
This one replaces original param for intel_ddc_get_modes() with
|
|
DRM connector and i2c bus adapter instead. With explicit params,
|
|
we won't require that a single driver structure must hold connector
|
|
and DDC bus reference, which ease the conversion to splitted encoder/
|
|
connector model.
|
|
|
|
It also clears up for some cases that we would steal other DDC bus
|
|
for mode probe, like VGA analog DDC probe for DVI-I. Also it fixed
|
|
a bug in old DVI-I probe handling, that failed to restore origin
|
|
analog GPIO port.
|
|
|
|
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 020bcd645be8b7a0837b7a0593430f26ad121844
|
|
Author: Eric Anholt <eric@anholt.net>
|
|
Date: Fri Apr 2 15:24:27 2010 -0700
|
|
|
|
drm/i915: Remove dead KMS encoder save/restore code.
|
|
|
|
This was brought over from UMS, and used for a while until we decided
|
|
that drm_helper_resume_force_mode was easier and more reliable, since
|
|
it didn't require duplicating all the code deleted here. We just
|
|
forgot to delete all that junk for a while.
|
|
|
|
commit a51895bee213fc506644305d65f8a7e9bc0a42d7
|
|
Author: Adam Jackson <ajax@redhat.com>
|
|
Date: Wed Mar 31 11:41:51 2010 -0400
|
|
|
|
drm/i915: Allow LVDS on pipe A on gen4+
|
|
|
|
The gen4 docs say it works, so why not. Tested on Ironlake.
|
|
|
|
Signed-off-by: Adam Jackson <ajax@redhat.com>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit f8c7768b50a68991f118aaa9c27039a9f1dfaa16
|
|
Author: Eric Anholt <eric@anholt.net>
|
|
Date: Fri Apr 9 14:18:55 2010 -0700
|
|
|
|
drm/i915: Clear the LVDS pipe B select bit when moving the LVDS to pipe A.
|
|
|
|
Based on a patch by Zhao Yakui.
|
|
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 4b75c3a050bccdd35f4298514571c024bf51c33e
|
|
Author: Zhao Yakui <yakui.zhao@intel.com>
|
|
Date: Wed Apr 7 17:11:21 2010 +0800
|
|
|
|
drm/i915: Fix legacy BLC event for pipe A
|
|
|
|
OpRegion event on 965G requires legacy BLC event enabled in pipe stat. As LVDS
|
|
could be on either pipe now, we should enable BLC event on both pipe. If fail to
|
|
do so, we couldn't handle the brightness request triggered from graphics
|
|
opregion.
|
|
|
|
Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
|
|
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 1d3d609b68107aad7076244742ddb3bcdcd282eb
|
|
Author: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Date: Wed Apr 7 16:15:52 2010 +0800
|
|
|
|
drm/i915: Sandybridge has no integrated TV
|
|
|
|
Integrated TV is deprecated in new chips from Ironlake.
|
|
|
|
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit c4418d1fcf08d0ffde92c96f235ac6a23864d709
|
|
Author: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Date: Wed Apr 7 16:15:53 2010 +0800
|
|
|
|
drm/i915: Probe for PCH chipset type
|
|
|
|
PCH is the new name for south bridge from Ironlake/Sandybridge,
|
|
which contains most of the display outputs except eDP. This one
|
|
adds a probe function to detect current PCH type, and method to
|
|
detect Cougarpoint PCH.
|
|
|
|
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 528bcb3d7676df9cb29b11b73fcb53be10f8240e
|
|
Author: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Date: Wed Apr 7 16:15:54 2010 +0800
|
|
|
|
drm/i915: Support for Cougarpoint PCH display pipeline
|
|
|
|
Cougarpoint is the new PCH for Sandybridge CPU. This one resolves the
|
|
chipset change for display pipeline compared to previous Ibexpeak PCH.
|
|
|
|
Sandybridge/Cougarpoint has different FDI training parameters, so this also
|
|
makes seperate FDI training functions for IBX and CPT. Other change includes
|
|
new transcoder DPLL select function to set which DPLL for transcoder to pick
|
|
up.
|
|
|
|
And with another new transcoder C introduced in Cougarpoint, each connector
|
|
has new transcoder select bits. This one adds that change to light up VGA.
|
|
|
|
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit c19eb88cd3867b0e5850c322ffeeb2b0f95a61fa
|
|
Author: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Date: Wed Apr 7 16:15:55 2010 +0800
|
|
|
|
drm/i915: Fix CRT force detect on Cougarpoint
|
|
|
|
To make CRT force detect reliable on Cougarpoint, we need to
|
|
disable DAC before force detect, and restore back when trigger
|
|
is completed.
|
|
|
|
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit bbe5385748d3514f2ec821af6b0cd1e8b8126788
|
|
Author: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Date: Wed Apr 7 16:15:56 2010 +0800
|
|
|
|
drm/i915: enable LVDS on Cougarpoint
|
|
|
|
Fix the transcoder select bit for LVDS on CPT.
|
|
|
|
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 9397e6409c31333c24f2120bc1242e57409b17b1
|
|
Author: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Date: Wed Apr 7 16:15:57 2010 +0800
|
|
|
|
drm/i915: enable HDMI on Cougarpoint
|
|
|
|
Fix transcoder select bit for HDMI on CPT.
|
|
|
|
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit b0280fea16c1993823e96ea60732471a673930a9
|
|
Author: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Date: Thu Apr 8 09:43:27 2010 +0800
|
|
|
|
drm/i915: enable DP/eDP for Sandybridge/Cougarpoint
|
|
|
|
DP on Cougarpoint has new training pattern definitions, and
|
|
new transcoder DP control register is used to determine the mapping
|
|
for transcoder and DP digital output. And eDP for Sandybridge has
|
|
new voltage and pre-emphasis level definitions.
|
|
|
|
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 34400e21a2ec1862a6aea1d415e16a8973d08009
|
|
Author: Adam Jackson <ajax@redhat.com>
|
|
Date: Mon Apr 5 17:58:00 2010 -0400
|
|
|
|
drm/i915: Un-magic a DPCD register write
|
|
|
|
Signed-off-by: Adam Jackson <ajax@redhat.com>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit d529f2bd3e73af3f58dacc142c8df96b2d8ac3de
|
|
Author: Adam Jackson <ajax@redhat.com>
|
|
Date: Mon Apr 5 17:57:59 2010 -0400
|
|
|
|
drm/i915: Set sync polarity correctly on DisplayPort
|
|
|
|
Probably only matters for format-converting dongles, but might as well
|
|
get it right all the time.
|
|
|
|
Signed-off-by: Adam Jackson <ajax@redhat.com>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit a0cf638b48c4c19531c02b546dc0a65947512588
|
|
Author: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Date: Mon Mar 29 15:53:23 2010 +0800
|
|
|
|
drm/i915: convert VGA driver to new encoder/connector structure
|
|
|
|
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 19dc930333364cee93468b49f96d93411b2dab93
|
|
Author: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Date: Mon Mar 29 16:40:50 2010 +0800
|
|
|
|
drm/i915: convert LVDS driver to new encoder/connector structure
|
|
|
|
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit fdb747792398be0bc2574b1e5bb0375a6e1ba709
|
|
Author: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Date: Mon Mar 29 15:57:42 2010 +0800
|
|
|
|
drm/i915: convert HDMI driver to new encoder/connector structure
|
|
|
|
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 76641985c72921092cb831dd09bc634c2fd89f71
|
|
Author: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Date: Mon Mar 29 16:13:57 2010 +0800
|
|
|
|
drm/i915: convert DP/eDP driver to new encoder/connector structure
|
|
|
|
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit ce8122f57adb42e80d2c62a6dd2df5660331c769
|
|
Author: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Date: Mon Mar 29 16:17:31 2010 +0800
|
|
|
|
drm/i915: convert DVO driver to new encoder/connector structure
|
|
|
|
Also remove old UMS copied code for get_crtc.
|
|
|
|
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 6cc8f013f8ebd91eea0667853ed765e1a6532649
|
|
Author: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Date: Mon Mar 29 21:22:55 2010 +0800
|
|
|
|
drm/i915: convert SDVO driver to new encoder/connector structure
|
|
|
|
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
|
|
commit f870c2dc4e9ca7609d9a0948cafb80b5af84158c
|
|
Author: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Date: Mon Mar 29 16:38:44 2010 +0800
|
|
|
|
drm/i915: convert TV driver to new encoder/connector structure
|
|
|
|
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
|
|
commit 1be1fd9444588e710ba251400249deda17e6801b
|
|
Author: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Date: Mon Mar 29 16:44:15 2010 +0800
|
|
|
|
drm/i915: remove connector object in old output structure
|
|
|
|
As all display drivers have been converted, remove the left reference
|
|
for connector object in old structure.
|
|
|
|
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
|
|
commit f9949e3847426bd72beb6be9361a0bed32992ac5
|
|
Author: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Date: Mon Mar 29 16:54:31 2010 +0800
|
|
|
|
drm/i915: remove unused intel_pipe_get_connector()
|
|
|
|
Added by original eDP support patch, not used any more.
|
|
|
|
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
|
|
commit 50b923cf1150fdf88312fb8616114e3fb5e57e57
|
|
Author: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Date: Tue Mar 30 14:06:33 2010 +0800
|
|
|
|
drm/i915: implement multifunction SDVO device support
|
|
|
|
With new intel_encoder/intel_connector structure change, each supported
|
|
connector type on SDVO device will be created as a new 'intel_connector',
|
|
and all attached to one 'intel_encoder' for its SDVO port.
|
|
|
|
The SDVO encoder will handle SDVO protocol stuff, and each connector does
|
|
its own part of work now, like detection is only to check if current active
|
|
output is itself, etc.
|
|
|
|
Update since last submit:
|
|
- Fixed SDVO TV property creation failure by incorrect set target output call
|
|
|
|
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
|
|
commit be7b7e1da367289b0998343af837dad531da7fd6
|
|
Author: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Date: Mon Mar 29 23:16:13 2010 +0800
|
|
|
|
Revert "drm/i915: Use a dmi quirk to skip a broken SDVO TV output."
|
|
|
|
This reverts commit 6070a4a928f8c92b9fae7d6717ebbb05f425d6b2.
|
|
|
|
The quirk for this SDVO device on IBM specific board is just a hack
|
|
in old code which showed the broken multifunction SDVO support in
|
|
the driver. Multifunction SDVO patch provided the right fix for it.
|
|
|
|
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
|
|
commit fa4cee3074fea74b556864ce25983b79598ba743
|
|
Author: Luca Tettamanti <kronos.it@gmail.com>
|
|
Date: Thu Apr 8 21:41:59 2010 +0200
|
|
|
|
drm/i915: do not read uninitialized ->dev_private
|
|
|
|
->dev_private at that point is NULL and is initialied only a few lines
|
|
later.
|
|
|
|
Signed-off-by: Luca Tettamanti <kronos.it@gmail.com>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 52eacfb9897f9a36cc93b587c57b922b8507d900
|
|
Author: Zhao Yakui <yakui.zhao@intel.com>
|
|
Date: Tue Mar 30 15:11:33 2010 +0800
|
|
|
|
drm/i915: Add support of SDVO on Ibexpeak PCH
|
|
|
|
SDVO on Ibexpeak PCH with Ironlake is multiplexed with
|
|
HDMIB port, and only has SDVOB port.
|
|
|
|
Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
|
|
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
|
|
commit 9df31d77abdd69427324bd0b4cd7f52eecb4a95a
|
|
Author: Zhao Yakui <yakui.zhao@intel.com>
|
|
Date: Tue Mar 30 15:15:02 2010 +0800
|
|
|
|
drm/i915: Fix the incorrect argument for SDVO SET_TV_format command
|
|
|
|
Otherwise it will cause that S-video output becomes black/white when
|
|
switching to other TV format.
|
|
|
|
http://bugs.freedesktop.org/show_bug.cgi?id=23916
|
|
|
|
Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
|
|
Tested-by: Arnold <arnold.erbsloeh@web.de>
|
|
Tested-by: Bazin <bazin.cz@gmail.com>
|
|
Tested-by: Nigel <nigel_tuck@eircom.net>
|
|
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
|
|
commit 064e7eadac1c51ce7a675da8b750defd6e82cb4b
|
|
Author: Zhao Yakui <yakui.zhao@intel.com>
|
|
Date: Fri Mar 19 17:05:10 2010 +0800
|
|
|
|
drm/i915: Only save/restore FBC on the platform that supports FBC
|
|
|
|
Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
|
|
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
|
|
commit 8860a05210d493379a9857e10b051f54097d6078
|
|
Author: Zhao Yakui <yakui.zhao@intel.com>
|
|
Date: Mon Mar 22 22:45:36 2010 +0800
|
|
|
|
drm/i915: Move Pineview CxSR and watermark code into update_wm hook.
|
|
|
|
Previously, after setting up the Pineview CxSR state, i9xx_update_wm would
|
|
get called and overwrite our state.
|
|
|
|
BTW: We will disable the self-refresh and never enable it any more if we
|
|
can't find the appropriate the latency on pineview plaftorm. In such case
|
|
the update_wm callback will be NULL.
|
|
|
|
The bitmask macro is also defined to access the corresponding fifo
|
|
watermark register.
|
|
|
|
Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
|
|
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
|
|
commit 8ab60b6bda618cf0ad0cc628bd174a9b9338dd64
|
|
Author: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Date: Thu Apr 1 13:07:53 2010 +0800
|
|
|
|
drm/i915: Add the support of memory self-refresh on Ironlake
|
|
|
|
Update the self-refresh watermark for display plane/cursor and enable
|
|
the memory self-refresh on Ironlake. The watermark is also updated for
|
|
the active display plane.
|
|
|
|
More than 1W idle power is saved on one Ironlake laptop after enabling
|
|
memory self-refresh.
|
|
|
|
Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
|
|
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
|
|
commit 55d812048fff0c36c2aed8165dcbd5578adb5807
|
|
Author: Adam Jackson <ajax@redhat.com>
|
|
Date: Mon Apr 12 11:38:44 2010 -0400
|
|
|
|
drm/i915/pch: Use minimal number of FDI lanes (v2)
|
|
|
|
This should be a small power savings. Tested on Lenovo T410 (Ironlake), LVDS
|
|
VGA and DisplayPort, up to 1920x1200R.
|
|
|
|
v2: Add Sandybridge support, fix obvious math error.
|
|
|
|
Acked-by: Zhenyu Wang <zhenyuw@linux.intel.com>
|
|
Signed-off-by: Adam Jackson <ajax@redhat.com>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
commit 12f713e6d7a31fb9cad311bbceae592ce1bb77a0
|
|
Author: Karsten Wiese <fzuuzf@googlemail.com>
|
|
Date: Sat Mar 27 22:48:33 2010 +0100
|
|
|
|
drm/i915: Don't touch PORT_HOTPLUG_EN in intel_dp_detect()
|
|
|
|
PORT_HOTPLUG_EN has allready been setup in i915_driver_irq_postinstall(),
|
|
when intel_dp_detect() runs.
|
|
|
|
Delete the DP[BCD]_HOTPLUG_INT_EN defines, they are not referenced anymore.
|
|
|
|
I found this while searching for a fix for
|
|
https://bugzilla.redhat.com/show_bug.cgi?id=528312
|
|
|
|
Signed-off-by: Karsten Wiese <fzu@wemgehoertderstaat.de>
|
|
Signed-off-by: Eric Anholt <eric@anholt.net>
|
|
|
|
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
|
|
index 3999a5f..64f8397 100644
|
|
--- a/drivers/char/agp/intel-agp.c
|
|
+++ b/drivers/char/agp/intel-agp.c
|
|
@@ -10,6 +10,9 @@
|
|
#include <linux/agp_backend.h>
|
|
#include "agp.h"
|
|
|
|
+int intel_agp_enabled;
|
|
+EXPORT_SYMBOL(intel_agp_enabled);
|
|
+
|
|
/*
|
|
* If we have Intel graphics, we're not going to have anything other than
|
|
* an Intel IOMMU. So make the correct use of the PCI DMA API contingent
|
|
@@ -64,6 +67,10 @@
|
|
#define PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB 0x0062
|
|
#define PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB 0x006a
|
|
#define PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG 0x0046
|
|
+#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB 0x0100
|
|
+#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_IG 0x0102
|
|
+#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB 0x0104
|
|
+#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_IG 0x0106
|
|
|
|
/* cover 915 and 945 variants */
|
|
#define IS_I915 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_E7221_HB || \
|
|
@@ -89,6 +96,9 @@
|
|
#define IS_PINEVIEW (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB || \
|
|
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_HB)
|
|
|
|
+#define IS_SNB (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB || \
|
|
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB)
|
|
+
|
|
#define IS_G4X (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_EAGLELAKE_HB || \
|
|
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q45_HB || \
|
|
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G45_HB || \
|
|
@@ -98,7 +108,8 @@
|
|
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB || \
|
|
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB || \
|
|
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB || \
|
|
- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB)
|
|
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB || \
|
|
+ IS_SNB)
|
|
|
|
extern int agp_memory_reserved;
|
|
|
|
@@ -147,6 +158,29 @@ extern int agp_memory_reserved;
|
|
#define INTEL_I7505_AGPCTRL 0x70
|
|
#define INTEL_I7505_MCHCFG 0x50
|
|
|
|
+#define SNB_GMCH_CTRL 0x50
|
|
+#define SNB_GMCH_GMS_STOLEN_MASK 0xF8
|
|
+#define SNB_GMCH_GMS_STOLEN_32M (1 << 3)
|
|
+#define SNB_GMCH_GMS_STOLEN_64M (2 << 3)
|
|
+#define SNB_GMCH_GMS_STOLEN_96M (3 << 3)
|
|
+#define SNB_GMCH_GMS_STOLEN_128M (4 << 3)
|
|
+#define SNB_GMCH_GMS_STOLEN_160M (5 << 3)
|
|
+#define SNB_GMCH_GMS_STOLEN_192M (6 << 3)
|
|
+#define SNB_GMCH_GMS_STOLEN_224M (7 << 3)
|
|
+#define SNB_GMCH_GMS_STOLEN_256M (8 << 3)
|
|
+#define SNB_GMCH_GMS_STOLEN_288M (9 << 3)
|
|
+#define SNB_GMCH_GMS_STOLEN_320M (0xa << 3)
|
|
+#define SNB_GMCH_GMS_STOLEN_352M (0xb << 3)
|
|
+#define SNB_GMCH_GMS_STOLEN_384M (0xc << 3)
|
|
+#define SNB_GMCH_GMS_STOLEN_416M (0xd << 3)
|
|
+#define SNB_GMCH_GMS_STOLEN_448M (0xe << 3)
|
|
+#define SNB_GMCH_GMS_STOLEN_480M (0xf << 3)
|
|
+#define SNB_GMCH_GMS_STOLEN_512M (0x10 << 3)
|
|
+#define SNB_GTT_SIZE_0M (0 << 8)
|
|
+#define SNB_GTT_SIZE_1M (1 << 8)
|
|
+#define SNB_GTT_SIZE_2M (2 << 8)
|
|
+#define SNB_GTT_SIZE_MASK (3 << 8)
|
|
+
|
|
static const struct aper_size_info_fixed intel_i810_sizes[] =
|
|
{
|
|
{64, 16384, 4},
|
|
@@ -293,6 +327,13 @@ static void intel_agp_insert_sg_entries(struct agp_memory *mem,
|
|
off_t pg_start, int mask_type)
|
|
{
|
|
int i, j;
|
|
+ u32 cache_bits = 0;
|
|
+
|
|
+ if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB ||
|
|
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB)
|
|
+ {
|
|
+ cache_bits = I830_PTE_SYSTEM_CACHED;
|
|
+ }
|
|
|
|
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
|
|
writel(agp_bridge->driver->mask_memory(agp_bridge,
|
|
@@ -613,7 +654,7 @@ static struct aper_size_info_fixed intel_i830_sizes[] =
|
|
static void intel_i830_init_gtt_entries(void)
|
|
{
|
|
u16 gmch_ctrl;
|
|
- int gtt_entries;
|
|
+ int gtt_entries = 0;
|
|
u8 rdct;
|
|
int local = 0;
|
|
static const int ddt[4] = { 0, 16, 32, 64 };
|
|
@@ -705,6 +746,63 @@ static void intel_i830_init_gtt_entries(void)
|
|
gtt_entries = 0;
|
|
break;
|
|
}
|
|
+ } else if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB ||
|
|
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB) {
|
|
+ /*
|
|
+ * SandyBridge has new memory control reg at 0x50.w
|
|
+ */
|
|
+ u16 snb_gmch_ctl;
|
|
+ pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl);
|
|
+ switch (snb_gmch_ctl & SNB_GMCH_GMS_STOLEN_MASK) {
|
|
+ case SNB_GMCH_GMS_STOLEN_32M:
|
|
+ gtt_entries = MB(32) - KB(size);
|
|
+ break;
|
|
+ case SNB_GMCH_GMS_STOLEN_64M:
|
|
+ gtt_entries = MB(64) - KB(size);
|
|
+ break;
|
|
+ case SNB_GMCH_GMS_STOLEN_96M:
|
|
+ gtt_entries = MB(96) - KB(size);
|
|
+ break;
|
|
+ case SNB_GMCH_GMS_STOLEN_128M:
|
|
+ gtt_entries = MB(128) - KB(size);
|
|
+ break;
|
|
+ case SNB_GMCH_GMS_STOLEN_160M:
|
|
+ gtt_entries = MB(160) - KB(size);
|
|
+ break;
|
|
+ case SNB_GMCH_GMS_STOLEN_192M:
|
|
+ gtt_entries = MB(192) - KB(size);
|
|
+ break;
|
|
+ case SNB_GMCH_GMS_STOLEN_224M:
|
|
+ gtt_entries = MB(224) - KB(size);
|
|
+ break;
|
|
+ case SNB_GMCH_GMS_STOLEN_256M:
|
|
+ gtt_entries = MB(256) - KB(size);
|
|
+ break;
|
|
+ case SNB_GMCH_GMS_STOLEN_288M:
|
|
+ gtt_entries = MB(288) - KB(size);
|
|
+ break;
|
|
+ case SNB_GMCH_GMS_STOLEN_320M:
|
|
+ gtt_entries = MB(320) - KB(size);
|
|
+ break;
|
|
+ case SNB_GMCH_GMS_STOLEN_352M:
|
|
+ gtt_entries = MB(352) - KB(size);
|
|
+ break;
|
|
+ case SNB_GMCH_GMS_STOLEN_384M:
|
|
+ gtt_entries = MB(384) - KB(size);
|
|
+ break;
|
|
+ case SNB_GMCH_GMS_STOLEN_416M:
|
|
+ gtt_entries = MB(416) - KB(size);
|
|
+ break;
|
|
+ case SNB_GMCH_GMS_STOLEN_448M:
|
|
+ gtt_entries = MB(448) - KB(size);
|
|
+ break;
|
|
+ case SNB_GMCH_GMS_STOLEN_480M:
|
|
+ gtt_entries = MB(480) - KB(size);
|
|
+ break;
|
|
+ case SNB_GMCH_GMS_STOLEN_512M:
|
|
+ gtt_entries = MB(512) - KB(size);
|
|
+ break;
|
|
+ }
|
|
} else {
|
|
switch (gmch_ctrl & I855_GMCH_GMS_MASK) {
|
|
case I855_GMCH_GMS_STOLEN_1M:
|
|
@@ -1115,6 +1213,9 @@ static void intel_i9xx_setup_flush(void)
|
|
if (intel_private.ifp_resource.start)
|
|
return;
|
|
|
|
+ if (IS_SNB)
|
|
+ return;
|
|
+
|
|
/* setup a resource for this object */
|
|
intel_private.ifp_resource.name = "Intel Flush Page";
|
|
intel_private.ifp_resource.flags = IORESOURCE_MEM;
|
|
@@ -1353,6 +1454,8 @@ static unsigned long intel_i965_mask_memory(struct agp_bridge_data *bridge,
|
|
|
|
static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size)
|
|
{
|
|
+ u16 snb_gmch_ctl;
|
|
+
|
|
switch (agp_bridge->dev->device) {
|
|
case PCI_DEVICE_ID_INTEL_GM45_HB:
|
|
case PCI_DEVICE_ID_INTEL_EAGLELAKE_HB:
|
|
@@ -1366,6 +1469,25 @@ static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size)
|
|
case PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB:
|
|
*gtt_offset = *gtt_size = MB(2);
|
|
break;
|
|
+ case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB:
|
|
+ case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB:
|
|
+ *gtt_offset = MB(2);
|
|
+
|
|
+ pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl);
|
|
+ switch (snb_gmch_ctl & SNB_GTT_SIZE_MASK) {
|
|
+ default:
|
|
+ case SNB_GTT_SIZE_0M:
|
|
+ printk(KERN_ERR "Bad GTT size mask: 0x%04x.\n", snb_gmch_ctl);
|
|
+ *gtt_size = MB(0);
|
|
+ break;
|
|
+ case SNB_GTT_SIZE_1M:
|
|
+ *gtt_size = MB(1);
|
|
+ break;
|
|
+ case SNB_GTT_SIZE_2M:
|
|
+ *gtt_size = MB(2);
|
|
+ break;
|
|
+ }
|
|
+ break;
|
|
default:
|
|
*gtt_offset = *gtt_size = KB(512);
|
|
}
|
|
@@ -1701,8 +1823,6 @@ static int intel_845_configure(void)
|
|
pci_write_config_byte(agp_bridge->dev, INTEL_I845_AGPM, temp2 | (1 << 1));
|
|
/* clear any possible error conditions */
|
|
pci_write_config_word(agp_bridge->dev, INTEL_I845_ERRSTS, 0x001c);
|
|
-
|
|
- intel_i830_setup_flush();
|
|
return 0;
|
|
}
|
|
|
|
@@ -2072,7 +2192,6 @@ static const struct agp_bridge_driver intel_845_driver = {
|
|
.agp_destroy_page = agp_generic_destroy_page,
|
|
.agp_destroy_pages = agp_generic_destroy_pages,
|
|
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
|
|
- .chipset_flush = intel_i830_chipset_flush,
|
|
};
|
|
|
|
static const struct agp_bridge_driver intel_850_driver = {
|
|
@@ -2345,9 +2464,9 @@ static const struct intel_driver_description {
|
|
NULL, &intel_g33_driver },
|
|
{ PCI_DEVICE_ID_INTEL_Q33_HB, PCI_DEVICE_ID_INTEL_Q33_IG, 0, "Q33",
|
|
NULL, &intel_g33_driver },
|
|
- { PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB, PCI_DEVICE_ID_INTEL_PINEVIEW_M_IG, 0, "Pineview",
|
|
+ { PCI_DEVICE_ID_INTEL_PINEVIEW_M_HB, PCI_DEVICE_ID_INTEL_PINEVIEW_M_IG, 0, "GMA3150",
|
|
NULL, &intel_g33_driver },
|
|
- { PCI_DEVICE_ID_INTEL_PINEVIEW_HB, PCI_DEVICE_ID_INTEL_PINEVIEW_IG, 0, "Pineview",
|
|
+ { PCI_DEVICE_ID_INTEL_PINEVIEW_HB, PCI_DEVICE_ID_INTEL_PINEVIEW_IG, 0, "GMA3150",
|
|
NULL, &intel_g33_driver },
|
|
{ PCI_DEVICE_ID_INTEL_GM45_HB, PCI_DEVICE_ID_INTEL_GM45_IG, 0,
|
|
"GM45", NULL, &intel_i965_driver },
|
|
@@ -2362,13 +2481,17 @@ static const struct intel_driver_description {
|
|
{ PCI_DEVICE_ID_INTEL_G41_HB, PCI_DEVICE_ID_INTEL_G41_IG, 0,
|
|
"G41", NULL, &intel_i965_driver },
|
|
{ PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG, 0,
|
|
- "Ironlake/D", NULL, &intel_i965_driver },
|
|
+ "HD Graphics", NULL, &intel_i965_driver },
|
|
{ PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, 0,
|
|
- "Ironlake/M", NULL, &intel_i965_driver },
|
|
+ "HD Graphics", NULL, &intel_i965_driver },
|
|
{ PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, 0,
|
|
- "Ironlake/MA", NULL, &intel_i965_driver },
|
|
+ "HD Graphics", NULL, &intel_i965_driver },
|
|
{ PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, 0,
|
|
- "Ironlake/MC2", NULL, &intel_i965_driver },
|
|
+ "HD Graphics", NULL, &intel_i965_driver },
|
|
+ { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_IG, 0,
|
|
+ "Sandybridge", NULL, &intel_i965_driver },
|
|
+ { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_IG, 0,
|
|
+ "Sandybridge", NULL, &intel_i965_driver },
|
|
{ 0, 0, 0, NULL, NULL, NULL }
|
|
};
|
|
|
|
@@ -2378,7 +2501,7 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
|
|
struct agp_bridge_data *bridge;
|
|
u8 cap_ptr = 0;
|
|
struct resource *r;
|
|
- int i;
|
|
+ int i, err;
|
|
|
|
cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
|
|
|
|
@@ -2470,7 +2593,10 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
|
|
}
|
|
|
|
pci_set_drvdata(pdev, bridge);
|
|
- return agp_add_bridge(bridge);
|
|
+ err = agp_add_bridge(bridge);
|
|
+ if (!err)
|
|
+ intel_agp_enabled = 1;
|
|
+ return err;
|
|
}
|
|
|
|
static void __devexit agp_intel_remove(struct pci_dev *pdev)
|
|
@@ -2575,6 +2701,8 @@ static struct pci_device_id agp_intel_pci_table[] = {
|
|
ID(PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB),
|
|
ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB),
|
|
ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB),
|
|
+ ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB),
|
|
+ ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB),
|
|
{ }
|
|
};
|
|
|
|
diff --git a/drivers/gpu/drm/i915/dvo.h b/drivers/gpu/drm/i915/dvo.h
|
|
--- a/drivers/gpu/drm/i915/dvo.h
|
|
+++ b/drivers/gpu/drm/i915/dvo.h
|
|
@@ -70,16 +70,6 @@ struct intel_dvo_dev_ops {
|
|
void (*dpms)(struct intel_dvo_device *dvo, int mode);
|
|
|
|
/*
|
|
- * Saves the output's state for restoration on VT switch.
|
|
- */
|
|
- void (*save)(struct intel_dvo_device *dvo);
|
|
-
|
|
- /*
|
|
- * Restore's the output's state at VT switch.
|
|
- */
|
|
- void (*restore)(struct intel_dvo_device *dvo);
|
|
-
|
|
- /*
|
|
* Callback for testing a video mode for a given output.
|
|
*
|
|
* This function should only check for cases where a mode can't
|
|
diff --git a/drivers/gpu/drm/i915/dvo_ch7017.c b/drivers/gpu/drm/i915/dvo_ch7017.c
|
|
--- a/drivers/gpu/drm/i915/dvo_ch7017.c
|
|
+++ b/drivers/gpu/drm/i915/dvo_ch7017.c
|
|
@@ -159,16 +159,7 @@
|
|
#define CH7017_BANG_LIMIT_CONTROL 0x7f
|
|
|
|
struct ch7017_priv {
|
|
- uint8_t save_hapi;
|
|
- uint8_t save_vali;
|
|
- uint8_t save_valo;
|
|
- uint8_t save_ailo;
|
|
- uint8_t save_lvds_pll_vco;
|
|
- uint8_t save_feedback_div;
|
|
- uint8_t save_lvds_control_2;
|
|
- uint8_t save_outputs_enable;
|
|
- uint8_t save_lvds_power_down;
|
|
- uint8_t save_power_management;
|
|
+ uint8_t dummy;
|
|
};
|
|
|
|
static void ch7017_dump_regs(struct intel_dvo_device *dvo);
|
|
@@ -401,39 +392,6 @@ do { \
|
|
DUMP(CH7017_LVDS_POWER_DOWN);
|
|
}
|
|
|
|
-static void ch7017_save(struct intel_dvo_device *dvo)
|
|
-{
|
|
- struct ch7017_priv *priv = dvo->dev_priv;
|
|
-
|
|
- ch7017_read(dvo, CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT, &priv->save_hapi);
|
|
- ch7017_read(dvo, CH7017_VERTICAL_ACTIVE_LINE_OUTPUT, &priv->save_valo);
|
|
- ch7017_read(dvo, CH7017_ACTIVE_INPUT_LINE_OUTPUT, &priv->save_ailo);
|
|
- ch7017_read(dvo, CH7017_LVDS_PLL_VCO_CONTROL, &priv->save_lvds_pll_vco);
|
|
- ch7017_read(dvo, CH7017_LVDS_PLL_FEEDBACK_DIV, &priv->save_feedback_div);
|
|
- ch7017_read(dvo, CH7017_LVDS_CONTROL_2, &priv->save_lvds_control_2);
|
|
- ch7017_read(dvo, CH7017_OUTPUTS_ENABLE, &priv->save_outputs_enable);
|
|
- ch7017_read(dvo, CH7017_LVDS_POWER_DOWN, &priv->save_lvds_power_down);
|
|
- ch7017_read(dvo, CH7017_POWER_MANAGEMENT, &priv->save_power_management);
|
|
-}
|
|
-
|
|
-static void ch7017_restore(struct intel_dvo_device *dvo)
|
|
-{
|
|
- struct ch7017_priv *priv = dvo->dev_priv;
|
|
-
|
|
- /* Power down before changing mode */
|
|
- ch7017_dpms(dvo, DRM_MODE_DPMS_OFF);
|
|
-
|
|
- ch7017_write(dvo, CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT, priv->save_hapi);
|
|
- ch7017_write(dvo, CH7017_VERTICAL_ACTIVE_LINE_OUTPUT, priv->save_valo);
|
|
- ch7017_write(dvo, CH7017_ACTIVE_INPUT_LINE_OUTPUT, priv->save_ailo);
|
|
- ch7017_write(dvo, CH7017_LVDS_PLL_VCO_CONTROL, priv->save_lvds_pll_vco);
|
|
- ch7017_write(dvo, CH7017_LVDS_PLL_FEEDBACK_DIV, priv->save_feedback_div);
|
|
- ch7017_write(dvo, CH7017_LVDS_CONTROL_2, priv->save_lvds_control_2);
|
|
- ch7017_write(dvo, CH7017_OUTPUTS_ENABLE, priv->save_outputs_enable);
|
|
- ch7017_write(dvo, CH7017_LVDS_POWER_DOWN, priv->save_lvds_power_down);
|
|
- ch7017_write(dvo, CH7017_POWER_MANAGEMENT, priv->save_power_management);
|
|
-}
|
|
-
|
|
static void ch7017_destroy(struct intel_dvo_device *dvo)
|
|
{
|
|
struct ch7017_priv *priv = dvo->dev_priv;
|
|
@@ -451,7 +409,5 @@ struct intel_dvo_dev_ops ch7017_ops = {
|
|
.mode_set = ch7017_mode_set,
|
|
.dpms = ch7017_dpms,
|
|
.dump_regs = ch7017_dump_regs,
|
|
- .save = ch7017_save,
|
|
- .restore = ch7017_restore,
|
|
.destroy = ch7017_destroy,
|
|
};
|
|
diff --git a/drivers/gpu/drm/i915/dvo_ch7xxx.c b/drivers/gpu/drm/i915/dvo_ch7xxx.c
|
|
--- a/drivers/gpu/drm/i915/dvo_ch7xxx.c
|
|
+++ b/drivers/gpu/drm/i915/dvo_ch7xxx.c
|
|
@@ -92,21 +92,10 @@ static struct ch7xxx_id_struct {
|
|
{ CH7301_VID, "CH7301" },
|
|
};
|
|
|
|
-struct ch7xxx_reg_state {
|
|
- uint8_t regs[CH7xxx_NUM_REGS];
|
|
-};
|
|
-
|
|
struct ch7xxx_priv {
|
|
bool quiet;
|
|
-
|
|
- struct ch7xxx_reg_state save_reg;
|
|
- struct ch7xxx_reg_state mode_reg;
|
|
- uint8_t save_TCTL, save_TPCP, save_TPD, save_TPVT;
|
|
- uint8_t save_TLPF, save_TCT, save_PM, save_IDF;
|
|
};
|
|
|
|
-static void ch7xxx_save(struct intel_dvo_device *dvo);
|
|
-
|
|
static char *ch7xxx_get_id(uint8_t vid)
|
|
{
|
|
int i;
|
|
@@ -312,42 +301,17 @@ static void ch7xxx_dpms(struct intel_dvo_device *dvo, int mode)
|
|
|
|
static void ch7xxx_dump_regs(struct intel_dvo_device *dvo)
|
|
{
|
|
- struct ch7xxx_priv *ch7xxx = dvo->dev_priv;
|
|
int i;
|
|
|
|
for (i = 0; i < CH7xxx_NUM_REGS; i++) {
|
|
+ uint8_t val;
|
|
if ((i % 8) == 0 )
|
|
DRM_LOG_KMS("\n %02X: ", i);
|
|
- DRM_LOG_KMS("%02X ", ch7xxx->mode_reg.regs[i]);
|
|
+ ch7xxx_readb(dvo, i, &val);
|
|
+ DRM_LOG_KMS("%02X ", val);
|
|
}
|
|
}
|
|
|
|
-static void ch7xxx_save(struct intel_dvo_device *dvo)
|
|
-{
|
|
- struct ch7xxx_priv *ch7xxx= dvo->dev_priv;
|
|
-
|
|
- ch7xxx_readb(dvo, CH7xxx_TCTL, &ch7xxx->save_TCTL);
|
|
- ch7xxx_readb(dvo, CH7xxx_TPCP, &ch7xxx->save_TPCP);
|
|
- ch7xxx_readb(dvo, CH7xxx_TPD, &ch7xxx->save_TPD);
|
|
- ch7xxx_readb(dvo, CH7xxx_TPVT, &ch7xxx->save_TPVT);
|
|
- ch7xxx_readb(dvo, CH7xxx_TLPF, &ch7xxx->save_TLPF);
|
|
- ch7xxx_readb(dvo, CH7xxx_PM, &ch7xxx->save_PM);
|
|
- ch7xxx_readb(dvo, CH7xxx_IDF, &ch7xxx->save_IDF);
|
|
-}
|
|
-
|
|
-static void ch7xxx_restore(struct intel_dvo_device *dvo)
|
|
-{
|
|
- struct ch7xxx_priv *ch7xxx = dvo->dev_priv;
|
|
-
|
|
- ch7xxx_writeb(dvo, CH7xxx_TCTL, ch7xxx->save_TCTL);
|
|
- ch7xxx_writeb(dvo, CH7xxx_TPCP, ch7xxx->save_TPCP);
|
|
- ch7xxx_writeb(dvo, CH7xxx_TPD, ch7xxx->save_TPD);
|
|
- ch7xxx_writeb(dvo, CH7xxx_TPVT, ch7xxx->save_TPVT);
|
|
- ch7xxx_writeb(dvo, CH7xxx_TLPF, ch7xxx->save_TLPF);
|
|
- ch7xxx_writeb(dvo, CH7xxx_IDF, ch7xxx->save_IDF);
|
|
- ch7xxx_writeb(dvo, CH7xxx_PM, ch7xxx->save_PM);
|
|
-}
|
|
-
|
|
static void ch7xxx_destroy(struct intel_dvo_device *dvo)
|
|
{
|
|
struct ch7xxx_priv *ch7xxx = dvo->dev_priv;
|
|
@@ -365,7 +329,5 @@ struct intel_dvo_dev_ops ch7xxx_ops = {
|
|
.mode_set = ch7xxx_mode_set,
|
|
.dpms = ch7xxx_dpms,
|
|
.dump_regs = ch7xxx_dump_regs,
|
|
- .save = ch7xxx_save,
|
|
- .restore = ch7xxx_restore,
|
|
.destroy = ch7xxx_destroy,
|
|
};
|
|
diff --git a/drivers/gpu/drm/i915/dvo_ivch.c b/drivers/gpu/drm/i915/dvo_ivch.c
|
|
--- a/drivers/gpu/drm/i915/dvo_ivch.c
|
|
+++ b/drivers/gpu/drm/i915/dvo_ivch.c
|
|
@@ -153,9 +153,6 @@ struct ivch_priv {
|
|
bool quiet;
|
|
|
|
uint16_t width, height;
|
|
-
|
|
- uint16_t save_VR01;
|
|
- uint16_t save_VR40;
|
|
};
|
|
|
|
|
|
@@ -405,22 +402,6 @@ static void ivch_dump_regs(struct intel_dvo_device *dvo)
|
|
DRM_LOG_KMS("VR8F: 0x%04x\n", val);
|
|
}
|
|
|
|
-static void ivch_save(struct intel_dvo_device *dvo)
|
|
-{
|
|
- struct ivch_priv *priv = dvo->dev_priv;
|
|
-
|
|
- ivch_read(dvo, VR01, &priv->save_VR01);
|
|
- ivch_read(dvo, VR40, &priv->save_VR40);
|
|
-}
|
|
-
|
|
-static void ivch_restore(struct intel_dvo_device *dvo)
|
|
-{
|
|
- struct ivch_priv *priv = dvo->dev_priv;
|
|
-
|
|
- ivch_write(dvo, VR01, priv->save_VR01);
|
|
- ivch_write(dvo, VR40, priv->save_VR40);
|
|
-}
|
|
-
|
|
static void ivch_destroy(struct intel_dvo_device *dvo)
|
|
{
|
|
struct ivch_priv *priv = dvo->dev_priv;
|
|
@@ -434,8 +415,6 @@ static void ivch_destroy(struct intel_dvo_device *dvo)
|
|
struct intel_dvo_dev_ops ivch_ops= {
|
|
.init = ivch_init,
|
|
.dpms = ivch_dpms,
|
|
- .save = ivch_save,
|
|
- .restore = ivch_restore,
|
|
.mode_valid = ivch_mode_valid,
|
|
.mode_set = ivch_mode_set,
|
|
.detect = ivch_detect,
|
|
diff --git a/drivers/gpu/drm/i915/dvo_sil164.c b/drivers/gpu/drm/i915/dvo_sil164.c
|
|
--- a/drivers/gpu/drm/i915/dvo_sil164.c
|
|
+++ b/drivers/gpu/drm/i915/dvo_sil164.c
|
|
@@ -58,17 +58,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
#define SIL164_REGC 0x0c
|
|
|
|
-struct sil164_save_rec {
|
|
- uint8_t reg8;
|
|
- uint8_t reg9;
|
|
- uint8_t regc;
|
|
-};
|
|
-
|
|
struct sil164_priv {
|
|
//I2CDevRec d;
|
|
bool quiet;
|
|
- struct sil164_save_rec save_regs;
|
|
- struct sil164_save_rec mode_regs;
|
|
};
|
|
|
|
#define SILPTR(d) ((SIL164Ptr)(d->DriverPrivate.ptr))
|
|
@@ -252,34 +244,6 @@ static void sil164_dump_regs(struct intel_dvo_device *dvo)
|
|
DRM_LOG_KMS("SIL164_REGC: 0x%02x\n", val);
|
|
}
|
|
|
|
-static void sil164_save(struct intel_dvo_device *dvo)
|
|
-{
|
|
- struct sil164_priv *sil= dvo->dev_priv;
|
|
-
|
|
- if (!sil164_readb(dvo, SIL164_REG8, &sil->save_regs.reg8))
|
|
- return;
|
|
-
|
|
- if (!sil164_readb(dvo, SIL164_REG9, &sil->save_regs.reg9))
|
|
- return;
|
|
-
|
|
- if (!sil164_readb(dvo, SIL164_REGC, &sil->save_regs.regc))
|
|
- return;
|
|
-
|
|
- return;
|
|
-}
|
|
-
|
|
-static void sil164_restore(struct intel_dvo_device *dvo)
|
|
-{
|
|
- struct sil164_priv *sil = dvo->dev_priv;
|
|
-
|
|
- /* Restore it powered down initially */
|
|
- sil164_writeb(dvo, SIL164_REG8, sil->save_regs.reg8 & ~0x1);
|
|
-
|
|
- sil164_writeb(dvo, SIL164_REG9, sil->save_regs.reg9);
|
|
- sil164_writeb(dvo, SIL164_REGC, sil->save_regs.regc);
|
|
- sil164_writeb(dvo, SIL164_REG8, sil->save_regs.reg8);
|
|
-}
|
|
-
|
|
static void sil164_destroy(struct intel_dvo_device *dvo)
|
|
{
|
|
struct sil164_priv *sil = dvo->dev_priv;
|
|
@@ -297,7 +261,5 @@ struct intel_dvo_dev_ops sil164_ops = {
|
|
.mode_set = sil164_mode_set,
|
|
.dpms = sil164_dpms,
|
|
.dump_regs = sil164_dump_regs,
|
|
- .save = sil164_save,
|
|
- .restore = sil164_restore,
|
|
.destroy = sil164_destroy,
|
|
};
|
|
diff --git a/drivers/gpu/drm/i915/dvo_tfp410.c b/drivers/gpu/drm/i915/dvo_tfp410.c
|
|
--- a/drivers/gpu/drm/i915/dvo_tfp410.c
|
|
+++ b/drivers/gpu/drm/i915/dvo_tfp410.c
|
|
@@ -86,16 +86,8 @@
|
|
#define TFP410_V_RES_LO 0x3C
|
|
#define TFP410_V_RES_HI 0x3D
|
|
|
|
-struct tfp410_save_rec {
|
|
- uint8_t ctl1;
|
|
- uint8_t ctl2;
|
|
-};
|
|
-
|
|
struct tfp410_priv {
|
|
bool quiet;
|
|
-
|
|
- struct tfp410_save_rec saved_reg;
|
|
- struct tfp410_save_rec mode_reg;
|
|
};
|
|
|
|
static bool tfp410_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
|
|
@@ -293,28 +285,6 @@ static void tfp410_dump_regs(struct intel_dvo_device *dvo)
|
|
DRM_LOG_KMS("TFP410_V_RES: 0x%02X%02X\n", val2, val);
|
|
}
|
|
|
|
-static void tfp410_save(struct intel_dvo_device *dvo)
|
|
-{
|
|
- struct tfp410_priv *tfp = dvo->dev_priv;
|
|
-
|
|
- if (!tfp410_readb(dvo, TFP410_CTL_1, &tfp->saved_reg.ctl1))
|
|
- return;
|
|
-
|
|
- if (!tfp410_readb(dvo, TFP410_CTL_2, &tfp->saved_reg.ctl2))
|
|
- return;
|
|
-}
|
|
-
|
|
-static void tfp410_restore(struct intel_dvo_device *dvo)
|
|
-{
|
|
- struct tfp410_priv *tfp = dvo->dev_priv;
|
|
-
|
|
- /* Restore it powered down initially */
|
|
- tfp410_writeb(dvo, TFP410_CTL_1, tfp->saved_reg.ctl1 & ~0x1);
|
|
-
|
|
- tfp410_writeb(dvo, TFP410_CTL_2, tfp->saved_reg.ctl2);
|
|
- tfp410_writeb(dvo, TFP410_CTL_1, tfp->saved_reg.ctl1);
|
|
-}
|
|
-
|
|
static void tfp410_destroy(struct intel_dvo_device *dvo)
|
|
{
|
|
struct tfp410_priv *tfp = dvo->dev_priv;
|
|
@@ -332,7 +302,5 @@ struct intel_dvo_dev_ops tfp410_ops = {
|
|
.mode_set = tfp410_mode_set,
|
|
.dpms = tfp410_dpms,
|
|
.dump_regs = tfp410_dump_regs,
|
|
- .save = tfp410_save,
|
|
- .restore = tfp410_restore,
|
|
.destroy = tfp410_destroy,
|
|
};
|
|
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
|
|
--- a/drivers/gpu/drm/i915/i915_debugfs.c
|
|
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
|
|
@@ -162,7 +162,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
|
|
struct drm_device *dev = node->minor->dev;
|
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
|
|
|
- if (!IS_IRONLAKE(dev)) {
|
|
+ if (!HAS_PCH_SPLIT(dev)) {
|
|
seq_printf(m, "Interrupt enable: %08x\n",
|
|
I915_READ(IER));
|
|
seq_printf(m, "Interrupt identity: %08x\n",
|
|
@@ -225,7 +225,7 @@ static int i915_gem_fence_regs_info(struct seq_file *m, void *data)
|
|
} else {
|
|
struct drm_i915_gem_object *obj_priv;
|
|
|
|
- obj_priv = obj->driver_private;
|
|
+ obj_priv = to_intel_bo(obj);
|
|
seq_printf(m, "Fenced object[%2d] = %p: %s "
|
|
"%08x %08zx %08x %s %08x %08x %d",
|
|
i, obj, get_pin_flag(obj_priv),
|
|
@@ -350,6 +350,36 @@ static int i915_ringbuffer_info(struct seq_file *m, void *data)
|
|
return 0;
|
|
}
|
|
|
|
+static const char *pin_flag(int pinned)
|
|
+{
|
|
+ if (pinned > 0)
|
|
+ return " P";
|
|
+ else if (pinned < 0)
|
|
+ return " p";
|
|
+ else
|
|
+ return "";
|
|
+}
|
|
+
|
|
+static const char *tiling_flag(int tiling)
|
|
+{
|
|
+ switch (tiling) {
|
|
+ default:
|
|
+ case I915_TILING_NONE: return "";
|
|
+ case I915_TILING_X: return " X";
|
|
+ case I915_TILING_Y: return " Y";
|
|
+ }
|
|
+}
|
|
+
|
|
+static const char *dirty_flag(int dirty)
|
|
+{
|
|
+ return dirty ? " dirty" : "";
|
|
+}
|
|
+
|
|
+static const char *purgeable_flag(int purgeable)
|
|
+{
|
|
+ return purgeable ? " purgeable" : "";
|
|
+}
|
|
+
|
|
static int i915_error_state(struct seq_file *m, void *unused)
|
|
{
|
|
struct drm_info_node *node = (struct drm_info_node *) m->private;
|
|
@@ -357,6 +387,7 @@ static int i915_error_state(struct seq_file *m, void *unused)
|
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
|
struct drm_i915_error_state *error;
|
|
unsigned long flags;
|
|
+ int i, page, offset, elt;
|
|
|
|
spin_lock_irqsave(&dev_priv->error_lock, flags);
|
|
if (!dev_priv->first_error) {
|
|
@@ -368,6 +399,7 @@ static int i915_error_state(struct seq_file *m, void *unused)
|
|
|
|
seq_printf(m, "Time: %ld s %ld us\n", error->time.tv_sec,
|
|
error->time.tv_usec);
|
|
+ seq_printf(m, "PCI ID: 0x%04x\n", dev->pci_device);
|
|
seq_printf(m, "EIR: 0x%08x\n", error->eir);
|
|
seq_printf(m, " PGTBL_ER: 0x%08x\n", error->pgtbl_er);
|
|
seq_printf(m, " INSTPM: 0x%08x\n", error->instpm);
|
|
@@ -379,6 +411,59 @@ static int i915_error_state(struct seq_file *m, void *unused)
|
|
seq_printf(m, " INSTPS: 0x%08x\n", error->instps);
|
|
seq_printf(m, " INSTDONE1: 0x%08x\n", error->instdone1);
|
|
}
|
|
+ seq_printf(m, "seqno: 0x%08x\n", error->seqno);
|
|
+
|
|
+ if (error->active_bo_count) {
|
|
+ seq_printf(m, "Buffers [%d]:\n", error->active_bo_count);
|
|
+
|
|
+ for (i = 0; i < error->active_bo_count; i++) {
|
|
+ seq_printf(m, " %08x %8zd %08x %08x %08x%s%s%s%s",
|
|
+ error->active_bo[i].gtt_offset,
|
|
+ error->active_bo[i].size,
|
|
+ error->active_bo[i].read_domains,
|
|
+ error->active_bo[i].write_domain,
|
|
+ error->active_bo[i].seqno,
|
|
+ pin_flag(error->active_bo[i].pinned),
|
|
+ tiling_flag(error->active_bo[i].tiling),
|
|
+ dirty_flag(error->active_bo[i].dirty),
|
|
+ purgeable_flag(error->active_bo[i].purgeable));
|
|
+
|
|
+ if (error->active_bo[i].name)
|
|
+ seq_printf(m, " (name: %d)", error->active_bo[i].name);
|
|
+ if (error->active_bo[i].fence_reg != I915_FENCE_REG_NONE)
|
|
+ seq_printf(m, " (fence: %d)", error->active_bo[i].fence_reg);
|
|
+
|
|
+ seq_printf(m, "\n");
|
|
+ }
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(error->batchbuffer); i++) {
|
|
+ if (error->batchbuffer[i]) {
|
|
+ struct drm_i915_error_object *obj = error->batchbuffer[i];
|
|
+
|
|
+ seq_printf(m, "--- gtt_offset = 0x%08x\n", obj->gtt_offset);
|
|
+ offset = 0;
|
|
+ for (page = 0; page < obj->page_count; page++) {
|
|
+ for (elt = 0; elt < PAGE_SIZE/4; elt++) {
|
|
+ seq_printf(m, "%08x : %08x\n", offset, obj->pages[page][elt]);
|
|
+ offset += 4;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (error->ringbuffer) {
|
|
+ struct drm_i915_error_object *obj = error->ringbuffer;
|
|
+
|
|
+ seq_printf(m, "--- ringbuffer = 0x%08x\n", obj->gtt_offset);
|
|
+ offset = 0;
|
|
+ for (page = 0; page < obj->page_count; page++) {
|
|
+ for (elt = 0; elt < PAGE_SIZE/4; elt++) {
|
|
+ seq_printf(m, "%08x : %08x\n", offset, obj->pages[page][elt]);
|
|
+ offset += 4;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
|
|
out:
|
|
spin_unlock_irqrestore(&dev_priv->error_lock, flags);
|
|
@@ -386,6 +471,165 @@ out:
|
|
return 0;
|
|
}
|
|
|
|
+static int i915_rstdby_delays(struct seq_file *m, void *unused)
|
|
+{
|
|
+ struct drm_info_node *node = (struct drm_info_node *) m->private;
|
|
+ struct drm_device *dev = node->minor->dev;
|
|
+ drm_i915_private_t *dev_priv = dev->dev_private;
|
|
+ u16 crstanddelay = I915_READ16(CRSTANDVID);
|
|
+
|
|
+ seq_printf(m, "w/ctx: %d, w/o ctx: %d\n", (crstanddelay >> 8) & 0x3f, (crstanddelay & 0x3f));
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int i915_cur_delayinfo(struct seq_file *m, void *unused)
|
|
+{
|
|
+ struct drm_info_node *node = (struct drm_info_node *) m->private;
|
|
+ struct drm_device *dev = node->minor->dev;
|
|
+ drm_i915_private_t *dev_priv = dev->dev_private;
|
|
+ u16 rgvswctl = I915_READ16(MEMSWCTL);
|
|
+
|
|
+ seq_printf(m, "Last command: 0x%01x\n", (rgvswctl >> 13) & 0x3);
|
|
+ seq_printf(m, "Command status: %d\n", (rgvswctl >> 12) & 1);
|
|
+ seq_printf(m, "P%d DELAY 0x%02x\n", (rgvswctl >> 8) & 0xf,
|
|
+ rgvswctl & 0x3f);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int i915_delayfreq_table(struct seq_file *m, void *unused)
|
|
+{
|
|
+ struct drm_info_node *node = (struct drm_info_node *) m->private;
|
|
+ struct drm_device *dev = node->minor->dev;
|
|
+ drm_i915_private_t *dev_priv = dev->dev_private;
|
|
+ u32 delayfreq;
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < 16; i++) {
|
|
+ delayfreq = I915_READ(PXVFREQ_BASE + i * 4);
|
|
+ seq_printf(m, "P%02dVIDFREQ: 0x%08x\n", i, delayfreq);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static inline int MAP_TO_MV(int map)
|
|
+{
|
|
+ return 1250 - (map * 25);
|
|
+}
|
|
+
|
|
+static int i915_inttoext_table(struct seq_file *m, void *unused)
|
|
+{
|
|
+ struct drm_info_node *node = (struct drm_info_node *) m->private;
|
|
+ struct drm_device *dev = node->minor->dev;
|
|
+ drm_i915_private_t *dev_priv = dev->dev_private;
|
|
+ u32 inttoext;
|
|
+ int i;
|
|
+
|
|
+ for (i = 1; i <= 32; i++) {
|
|
+ inttoext = I915_READ(INTTOEXT_BASE_ILK + i * 4);
|
|
+ seq_printf(m, "INTTOEXT%02d: 0x%08x\n", i, inttoext);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int i915_drpc_info(struct seq_file *m, void *unused)
|
|
+{
|
|
+ struct drm_info_node *node = (struct drm_info_node *) m->private;
|
|
+ struct drm_device *dev = node->minor->dev;
|
|
+ drm_i915_private_t *dev_priv = dev->dev_private;
|
|
+ u32 rgvmodectl = I915_READ(MEMMODECTL);
|
|
+
|
|
+ seq_printf(m, "HD boost: %s\n", (rgvmodectl & MEMMODE_BOOST_EN) ?
|
|
+ "yes" : "no");
|
|
+ seq_printf(m, "Boost freq: %d\n",
|
|
+ (rgvmodectl & MEMMODE_BOOST_FREQ_MASK) >>
|
|
+ MEMMODE_BOOST_FREQ_SHIFT);
|
|
+ seq_printf(m, "HW control enabled: %s\n",
|
|
+ rgvmodectl & MEMMODE_HWIDLE_EN ? "yes" : "no");
|
|
+ seq_printf(m, "SW control enabled: %s\n",
|
|
+ rgvmodectl & MEMMODE_SWMODE_EN ? "yes" : "no");
|
|
+ seq_printf(m, "Gated voltage change: %s\n",
|
|
+ rgvmodectl & MEMMODE_RCLK_GATE ? "yes" : "no");
|
|
+ seq_printf(m, "Starting frequency: P%d\n",
|
|
+ (rgvmodectl & MEMMODE_FSTART_MASK) >> MEMMODE_FSTART_SHIFT);
|
|
+ seq_printf(m, "Max frequency: P%d\n",
|
|
+ (rgvmodectl & MEMMODE_FMAX_MASK) >> MEMMODE_FMAX_SHIFT);
|
|
+ seq_printf(m, "Min frequency: P%d\n", (rgvmodectl & MEMMODE_FMIN_MASK));
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int i915_fbc_status(struct seq_file *m, void *unused)
|
|
+{
|
|
+ struct drm_info_node *node = (struct drm_info_node *) m->private;
|
|
+ struct drm_device *dev = node->minor->dev;
|
|
+ struct drm_crtc *crtc;
|
|
+ drm_i915_private_t *dev_priv = dev->dev_private;
|
|
+ bool fbc_enabled = false;
|
|
+
|
|
+ if (!dev_priv->display.fbc_enabled) {
|
|
+ seq_printf(m, "FBC unsupported on this chipset\n");
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
|
+ if (!crtc->enabled)
|
|
+ continue;
|
|
+ if (dev_priv->display.fbc_enabled(crtc))
|
|
+ fbc_enabled = true;
|
|
+ }
|
|
+
|
|
+ if (fbc_enabled) {
|
|
+ seq_printf(m, "FBC enabled\n");
|
|
+ } else {
|
|
+ seq_printf(m, "FBC disabled: ");
|
|
+ switch (dev_priv->no_fbc_reason) {
|
|
+ case FBC_STOLEN_TOO_SMALL:
|
|
+ seq_printf(m, "not enough stolen memory");
|
|
+ break;
|
|
+ case FBC_UNSUPPORTED_MODE:
|
|
+ seq_printf(m, "mode not supported");
|
|
+ break;
|
|
+ case FBC_MODE_TOO_LARGE:
|
|
+ seq_printf(m, "mode too large");
|
|
+ break;
|
|
+ case FBC_BAD_PLANE:
|
|
+ seq_printf(m, "FBC unsupported on plane");
|
|
+ break;
|
|
+ case FBC_NOT_TILED:
|
|
+ seq_printf(m, "scanout buffer not tiled");
|
|
+ break;
|
|
+ default:
|
|
+ seq_printf(m, "unknown reason");
|
|
+ }
|
|
+ seq_printf(m, "\n");
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int i915_sr_status(struct seq_file *m, void *unused)
|
|
+{
|
|
+ struct drm_info_node *node = (struct drm_info_node *) m->private;
|
|
+ struct drm_device *dev = node->minor->dev;
|
|
+ drm_i915_private_t *dev_priv = dev->dev_private;
|
|
+ bool sr_enabled = false;
|
|
+
|
|
+ if (IS_I965G(dev) || IS_I945G(dev) || IS_I945GM(dev))
|
|
+ sr_enabled = I915_READ(FW_BLC_SELF) & FW_BLC_SELF_EN;
|
|
+ else if (IS_I915GM(dev))
|
|
+ sr_enabled = I915_READ(INSTPM) & INSTPM_SELF_EN;
|
|
+ else if (IS_PINEVIEW(dev))
|
|
+ sr_enabled = I915_READ(DSPFW3) & PINEVIEW_SELF_REFRESH_EN;
|
|
+
|
|
+ seq_printf(m, "self-refresh: %s\n", sr_enabled ? "enabled" :
|
|
+ "disabled");
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static int
|
|
i915_wedged_open(struct inode *inode,
|
|
struct file *filp)
|
|
@@ -503,6 +747,13 @@ static struct drm_info_list i915_debugfs_list[] = {
|
|
{"i915_ringbuffer_info", i915_ringbuffer_info, 0},
|
|
{"i915_batchbuffers", i915_batchbuffer_info, 0},
|
|
{"i915_error_state", i915_error_state, 0},
|
|
+ {"i915_rstdby_delays", i915_rstdby_delays, 0},
|
|
+ {"i915_cur_delayinfo", i915_cur_delayinfo, 0},
|
|
+ {"i915_delayfreq_table", i915_delayfreq_table, 0},
|
|
+ {"i915_inttoext_table", i915_inttoext_table, 0},
|
|
+ {"i915_drpc_info", i915_drpc_info, 0},
|
|
+ {"i915_fbc_status", i915_fbc_status, 0},
|
|
+ {"i915_sr_status", i915_sr_status, 0},
|
|
};
|
|
#define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list)
|
|
|
|
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
|
|
--- a/drivers/gpu/drm/i915/i915_dma.c
|
|
+++ b/drivers/gpu/drm/i915/i915_dma.c
|
|
@@ -35,6 +35,8 @@
|
|
#include "i915_drv.h"
|
|
#include "i915_trace.h"
|
|
#include <linux/vgaarb.h>
|
|
+#include <linux/acpi.h>
|
|
+#include <linux/pnp.h>
|
|
|
|
/* Really want an OS-independent resettable timer. Would like to have
|
|
* this loop run for (eg) 3 sec, but have the timer reset every time
|
|
@@ -933,6 +935,120 @@ static int i915_get_bridge_dev(struct drm_device *dev)
|
|
return 0;
|
|
}
|
|
|
|
+#define MCHBAR_I915 0x44
|
|
+#define MCHBAR_I965 0x48
|
|
+#define MCHBAR_SIZE (4*4096)
|
|
+
|
|
+#define DEVEN_REG 0x54
|
|
+#define DEVEN_MCHBAR_EN (1 << 28)
|
|
+
|
|
+/* Allocate space for the MCH regs if needed, return nonzero on error */
|
|
+static int
|
|
+intel_alloc_mchbar_resource(struct drm_device *dev)
|
|
+{
|
|
+ drm_i915_private_t *dev_priv = dev->dev_private;
|
|
+ int reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
|
|
+ u32 temp_lo, temp_hi = 0;
|
|
+ u64 mchbar_addr;
|
|
+ int ret = 0;
|
|
+
|
|
+ if (IS_I965G(dev))
|
|
+ pci_read_config_dword(dev_priv->bridge_dev, reg + 4, &temp_hi);
|
|
+ pci_read_config_dword(dev_priv->bridge_dev, reg, &temp_lo);
|
|
+ mchbar_addr = ((u64)temp_hi << 32) | temp_lo;
|
|
+
|
|
+ /* If ACPI doesn't have it, assume we need to allocate it ourselves */
|
|
+#ifdef CONFIG_PNP
|
|
+ if (mchbar_addr &&
|
|
+ pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) {
|
|
+ ret = 0;
|
|
+ goto out;
|
|
+ }
|
|
+#endif
|
|
+
|
|
+ /* Get some space for it */
|
|
+ ret = pci_bus_alloc_resource(dev_priv->bridge_dev->bus, &dev_priv->mch_res,
|
|
+ MCHBAR_SIZE, MCHBAR_SIZE,
|
|
+ PCIBIOS_MIN_MEM,
|
|
+ 0, pcibios_align_resource,
|
|
+ dev_priv->bridge_dev);
|
|
+ if (ret) {
|
|
+ DRM_DEBUG_DRIVER("failed bus alloc: %d\n", ret);
|
|
+ dev_priv->mch_res.start = 0;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if (IS_I965G(dev))
|
|
+ pci_write_config_dword(dev_priv->bridge_dev, reg + 4,
|
|
+ upper_32_bits(dev_priv->mch_res.start));
|
|
+
|
|
+ pci_write_config_dword(dev_priv->bridge_dev, reg,
|
|
+ lower_32_bits(dev_priv->mch_res.start));
|
|
+out:
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/* Setup MCHBAR if possible, return true if we should disable it again */
|
|
+static void
|
|
+intel_setup_mchbar(struct drm_device *dev)
|
|
+{
|
|
+ drm_i915_private_t *dev_priv = dev->dev_private;
|
|
+ int mchbar_reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
|
|
+ u32 temp;
|
|
+ bool enabled;
|
|
+
|
|
+ dev_priv->mchbar_need_disable = false;
|
|
+
|
|
+ if (IS_I915G(dev) || IS_I915GM(dev)) {
|
|
+ pci_read_config_dword(dev_priv->bridge_dev, DEVEN_REG, &temp);
|
|
+ enabled = !!(temp & DEVEN_MCHBAR_EN);
|
|
+ } else {
|
|
+ pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
|
|
+ enabled = temp & 1;
|
|
+ }
|
|
+
|
|
+ /* If it's already enabled, don't have to do anything */
|
|
+ if (enabled)
|
|
+ return;
|
|
+
|
|
+ if (intel_alloc_mchbar_resource(dev))
|
|
+ return;
|
|
+
|
|
+ dev_priv->mchbar_need_disable = true;
|
|
+
|
|
+ /* Space is allocated or reserved, so enable it. */
|
|
+ if (IS_I915G(dev) || IS_I915GM(dev)) {
|
|
+ pci_write_config_dword(dev_priv->bridge_dev, DEVEN_REG,
|
|
+ temp | DEVEN_MCHBAR_EN);
|
|
+ } else {
|
|
+ pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
|
|
+ pci_write_config_dword(dev_priv->bridge_dev, mchbar_reg, temp | 1);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void
|
|
+intel_teardown_mchbar(struct drm_device *dev)
|
|
+{
|
|
+ drm_i915_private_t *dev_priv = dev->dev_private;
|
|
+ int mchbar_reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
|
|
+ u32 temp;
|
|
+
|
|
+ if (dev_priv->mchbar_need_disable) {
|
|
+ if (IS_I915G(dev) || IS_I915GM(dev)) {
|
|
+ pci_read_config_dword(dev_priv->bridge_dev, DEVEN_REG, &temp);
|
|
+ temp &= ~DEVEN_MCHBAR_EN;
|
|
+ pci_write_config_dword(dev_priv->bridge_dev, DEVEN_REG, temp);
|
|
+ } else {
|
|
+ pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
|
|
+ temp &= ~1;
|
|
+ pci_write_config_dword(dev_priv->bridge_dev, mchbar_reg, temp);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (dev_priv->mch_res.start)
|
|
+ release_resource(&dev_priv->mch_res);
|
|
+}
|
|
+
|
|
/**
|
|
* i915_probe_agp - get AGP bootup configuration
|
|
* @pdev: PCI device
|
|
@@ -978,59 +1094,123 @@ static int i915_probe_agp(struct drm_device *dev, uint32_t *aperture_size,
|
|
* Some of the preallocated space is taken by the GTT
|
|
* and popup. GTT is 1K per MB of aperture size, and popup is 4K.
|
|
*/
|
|
- if (IS_G4X(dev) || IS_PINEVIEW(dev) || IS_IRONLAKE(dev))
|
|
+ if (IS_G4X(dev) || IS_PINEVIEW(dev) || IS_IRONLAKE(dev) || IS_GEN6(dev))
|
|
overhead = 4096;
|
|
else
|
|
overhead = (*aperture_size / 1024) + 4096;
|
|
|
|
- switch (tmp & INTEL_GMCH_GMS_MASK) {
|
|
- case INTEL_855_GMCH_GMS_DISABLED:
|
|
- DRM_ERROR("video memory is disabled\n");
|
|
- return -1;
|
|
- case INTEL_855_GMCH_GMS_STOLEN_1M:
|
|
- stolen = 1 * 1024 * 1024;
|
|
- break;
|
|
- case INTEL_855_GMCH_GMS_STOLEN_4M:
|
|
- stolen = 4 * 1024 * 1024;
|
|
- break;
|
|
- case INTEL_855_GMCH_GMS_STOLEN_8M:
|
|
- stolen = 8 * 1024 * 1024;
|
|
- break;
|
|
- case INTEL_855_GMCH_GMS_STOLEN_16M:
|
|
- stolen = 16 * 1024 * 1024;
|
|
- break;
|
|
- case INTEL_855_GMCH_GMS_STOLEN_32M:
|
|
- stolen = 32 * 1024 * 1024;
|
|
- break;
|
|
- case INTEL_915G_GMCH_GMS_STOLEN_48M:
|
|
- stolen = 48 * 1024 * 1024;
|
|
- break;
|
|
- case INTEL_915G_GMCH_GMS_STOLEN_64M:
|
|
- stolen = 64 * 1024 * 1024;
|
|
- break;
|
|
- case INTEL_GMCH_GMS_STOLEN_128M:
|
|
- stolen = 128 * 1024 * 1024;
|
|
- break;
|
|
- case INTEL_GMCH_GMS_STOLEN_256M:
|
|
- stolen = 256 * 1024 * 1024;
|
|
- break;
|
|
- case INTEL_GMCH_GMS_STOLEN_96M:
|
|
- stolen = 96 * 1024 * 1024;
|
|
- break;
|
|
- case INTEL_GMCH_GMS_STOLEN_160M:
|
|
- stolen = 160 * 1024 * 1024;
|
|
- break;
|
|
- case INTEL_GMCH_GMS_STOLEN_224M:
|
|
- stolen = 224 * 1024 * 1024;
|
|
- break;
|
|
- case INTEL_GMCH_GMS_STOLEN_352M:
|
|
- stolen = 352 * 1024 * 1024;
|
|
- break;
|
|
- default:
|
|
- DRM_ERROR("unexpected GMCH_GMS value: 0x%02x\n",
|
|
- tmp & INTEL_GMCH_GMS_MASK);
|
|
- return -1;
|
|
+ if (IS_GEN6(dev)) {
|
|
+ /* SNB has memory control reg at 0x50.w */
|
|
+ pci_read_config_word(dev->pdev, SNB_GMCH_CTRL, &tmp);
|
|
+
|
|
+ switch (tmp & SNB_GMCH_GMS_STOLEN_MASK) {
|
|
+ case INTEL_855_GMCH_GMS_DISABLED:
|
|
+ DRM_ERROR("video memory is disabled\n");
|
|
+ return -1;
|
|
+ case SNB_GMCH_GMS_STOLEN_32M:
|
|
+ stolen = 32 * 1024 * 1024;
|
|
+ break;
|
|
+ case SNB_GMCH_GMS_STOLEN_64M:
|
|
+ stolen = 64 * 1024 * 1024;
|
|
+ break;
|
|
+ case SNB_GMCH_GMS_STOLEN_96M:
|
|
+ stolen = 96 * 1024 * 1024;
|
|
+ break;
|
|
+ case SNB_GMCH_GMS_STOLEN_128M:
|
|
+ stolen = 128 * 1024 * 1024;
|
|
+ break;
|
|
+ case SNB_GMCH_GMS_STOLEN_160M:
|
|
+ stolen = 160 * 1024 * 1024;
|
|
+ break;
|
|
+ case SNB_GMCH_GMS_STOLEN_192M:
|
|
+ stolen = 192 * 1024 * 1024;
|
|
+ break;
|
|
+ case SNB_GMCH_GMS_STOLEN_224M:
|
|
+ stolen = 224 * 1024 * 1024;
|
|
+ break;
|
|
+ case SNB_GMCH_GMS_STOLEN_256M:
|
|
+ stolen = 256 * 1024 * 1024;
|
|
+ break;
|
|
+ case SNB_GMCH_GMS_STOLEN_288M:
|
|
+ stolen = 288 * 1024 * 1024;
|
|
+ break;
|
|
+ case SNB_GMCH_GMS_STOLEN_320M:
|
|
+ stolen = 320 * 1024 * 1024;
|
|
+ break;
|
|
+ case SNB_GMCH_GMS_STOLEN_352M:
|
|
+ stolen = 352 * 1024 * 1024;
|
|
+ break;
|
|
+ case SNB_GMCH_GMS_STOLEN_384M:
|
|
+ stolen = 384 * 1024 * 1024;
|
|
+ break;
|
|
+ case SNB_GMCH_GMS_STOLEN_416M:
|
|
+ stolen = 416 * 1024 * 1024;
|
|
+ break;
|
|
+ case SNB_GMCH_GMS_STOLEN_448M:
|
|
+ stolen = 448 * 1024 * 1024;
|
|
+ break;
|
|
+ case SNB_GMCH_GMS_STOLEN_480M:
|
|
+ stolen = 480 * 1024 * 1024;
|
|
+ break;
|
|
+ case SNB_GMCH_GMS_STOLEN_512M:
|
|
+ stolen = 512 * 1024 * 1024;
|
|
+ break;
|
|
+ default:
|
|
+ DRM_ERROR("unexpected GMCH_GMS value: 0x%02x\n",
|
|
+ tmp & SNB_GMCH_GMS_STOLEN_MASK);
|
|
+ return -1;
|
|
+ }
|
|
+ } else {
|
|
+ switch (tmp & INTEL_GMCH_GMS_MASK) {
|
|
+ case INTEL_855_GMCH_GMS_DISABLED:
|
|
+ DRM_ERROR("video memory is disabled\n");
|
|
+ return -1;
|
|
+ case INTEL_855_GMCH_GMS_STOLEN_1M:
|
|
+ stolen = 1 * 1024 * 1024;
|
|
+ break;
|
|
+ case INTEL_855_GMCH_GMS_STOLEN_4M:
|
|
+ stolen = 4 * 1024 * 1024;
|
|
+ break;
|
|
+ case INTEL_855_GMCH_GMS_STOLEN_8M:
|
|
+ stolen = 8 * 1024 * 1024;
|
|
+ break;
|
|
+ case INTEL_855_GMCH_GMS_STOLEN_16M:
|
|
+ stolen = 16 * 1024 * 1024;
|
|
+ break;
|
|
+ case INTEL_855_GMCH_GMS_STOLEN_32M:
|
|
+ stolen = 32 * 1024 * 1024;
|
|
+ break;
|
|
+ case INTEL_915G_GMCH_GMS_STOLEN_48M:
|
|
+ stolen = 48 * 1024 * 1024;
|
|
+ break;
|
|
+ case INTEL_915G_GMCH_GMS_STOLEN_64M:
|
|
+ stolen = 64 * 1024 * 1024;
|
|
+ break;
|
|
+ case INTEL_GMCH_GMS_STOLEN_128M:
|
|
+ stolen = 128 * 1024 * 1024;
|
|
+ break;
|
|
+ case INTEL_GMCH_GMS_STOLEN_256M:
|
|
+ stolen = 256 * 1024 * 1024;
|
|
+ break;
|
|
+ case INTEL_GMCH_GMS_STOLEN_96M:
|
|
+ stolen = 96 * 1024 * 1024;
|
|
+ break;
|
|
+ case INTEL_GMCH_GMS_STOLEN_160M:
|
|
+ stolen = 160 * 1024 * 1024;
|
|
+ break;
|
|
+ case INTEL_GMCH_GMS_STOLEN_224M:
|
|
+ stolen = 224 * 1024 * 1024;
|
|
+ break;
|
|
+ case INTEL_GMCH_GMS_STOLEN_352M:
|
|
+ stolen = 352 * 1024 * 1024;
|
|
+ break;
|
|
+ default:
|
|
+ DRM_ERROR("unexpected GMCH_GMS value: 0x%02x\n",
|
|
+ tmp & INTEL_GMCH_GMS_MASK);
|
|
+ return -1;
|
|
+ }
|
|
}
|
|
+
|
|
*preallocated_size = stolen - overhead;
|
|
*start = overhead;
|
|
|
|
@@ -1064,7 +1244,7 @@ static unsigned long i915_gtt_to_phys(struct drm_device *dev,
|
|
int gtt_offset, gtt_size;
|
|
|
|
if (IS_I965G(dev)) {
|
|
- if (IS_G4X(dev) || IS_IRONLAKE(dev)) {
|
|
+ if (IS_G4X(dev) || IS_IRONLAKE(dev) || IS_GEN6(dev)) {
|
|
gtt_offset = 2*1024*1024;
|
|
gtt_size = 2*1024*1024;
|
|
} else {
|
|
@@ -1133,6 +1313,7 @@ static void i915_setup_compression(struct drm_device *dev, int size)
|
|
/* Leave 1M for line length buffer & misc. */
|
|
compressed_fb = drm_mm_search_free(&dev_priv->vram, size, 4096, 0);
|
|
if (!compressed_fb) {
|
|
+ dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL;
|
|
i915_warn_stolen(dev);
|
|
return;
|
|
}
|
|
@@ -1140,6 +1321,7 @@ static void i915_setup_compression(struct drm_device *dev, int size)
|
|
compressed_fb = drm_mm_get_block(compressed_fb, size, 4096);
|
|
if (!compressed_fb) {
|
|
i915_warn_stolen(dev);
|
|
+ dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL;
|
|
return;
|
|
}
|
|
|
|
@@ -1281,7 +1463,9 @@ static int i915_load_modeset_init(struct drm_device *dev,
|
|
return 0;
|
|
|
|
destroy_ringbuffer:
|
|
+ mutex_lock(&dev->struct_mutex);
|
|
i915_gem_cleanup_ringbuffer(dev);
|
|
+ mutex_unlock(&dev->struct_mutex);
|
|
out:
|
|
return ret;
|
|
}
|
|
@@ -1361,7 +1545,7 @@ static void i915_get_mem_freq(struct drm_device *dev)
|
|
*/
|
|
int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
|
{
|
|
- struct drm_i915_private *dev_priv = dev->dev_private;
|
|
+ struct drm_i915_private *dev_priv;
|
|
resource_size_t base, size;
|
|
int ret = 0, mmio_bar;
|
|
uint32_t agp_size, prealloc_size, prealloc_start;
|
|
@@ -1445,11 +1629,14 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
|
|
|
dev->driver->get_vblank_counter = i915_get_vblank_counter;
|
|
dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
|
|
- if (IS_G4X(dev) || IS_IRONLAKE(dev)) {
|
|
+ if (IS_G4X(dev) || IS_IRONLAKE(dev) || IS_GEN6(dev)) {
|
|
dev->max_vblank_count = 0xffffffff; /* full 32 bit counter */
|
|
dev->driver->get_vblank_counter = gm45_get_vblank_counter;
|
|
}
|
|
|
|
+ /* Try to make sure MCHBAR is enabled before poking at it */
|
|
+ intel_setup_mchbar(dev);
|
|
+
|
|
i915_gem_load(dev);
|
|
|
|
/* Init HWS */
|
|
@@ -1490,6 +1677,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
|
/* Start out suspended */
|
|
dev_priv->mm.suspended = 1;
|
|
|
|
+ intel_detect_pch(dev);
|
|
+
|
|
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
|
ret = i915_load_modeset_init(dev, prealloc_start,
|
|
prealloc_size, agp_size);
|
|
@@ -1523,6 +1712,8 @@ int i915_driver_unload(struct drm_device *dev)
|
|
{
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
+ i915_destroy_error_state(dev);
|
|
+
|
|
destroy_workqueue(dev_priv->wq);
|
|
del_timer_sync(&dev_priv->hangcheck_timer);
|
|
|
|
@@ -1569,6 +1760,8 @@ int i915_driver_unload(struct drm_device *dev)
|
|
intel_cleanup_overlay(dev);
|
|
}
|
|
|
|
+ intel_teardown_mchbar(dev);
|
|
+
|
|
pci_dev_put(dev_priv->bridge_dev);
|
|
kfree(dev->dev_private);
|
|
|
|
@@ -1655,29 +1848,29 @@ struct drm_ioctl_desc i915_ioctls[] = {
|
|
DRM_IOCTL_DEF(DRM_I915_GET_VBLANK_PIPE, i915_vblank_pipe_get, DRM_AUTH ),
|
|
DRM_IOCTL_DEF(DRM_I915_VBLANK_SWAP, i915_vblank_swap, DRM_AUTH),
|
|
DRM_IOCTL_DEF(DRM_I915_HWS_ADDR, i915_set_status_page, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
|
- DRM_IOCTL_DEF(DRM_I915_GEM_INIT, i915_gem_init_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
|
- DRM_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH),
|
|
- DRM_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER2, i915_gem_execbuffer2, DRM_AUTH),
|
|
- DRM_IOCTL_DEF(DRM_I915_GEM_PIN, i915_gem_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
|
|
- DRM_IOCTL_DEF(DRM_I915_GEM_UNPIN, i915_gem_unpin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
|
|
- DRM_IOCTL_DEF(DRM_I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH),
|
|
- DRM_IOCTL_DEF(DRM_I915_GEM_THROTTLE, i915_gem_throttle_ioctl, DRM_AUTH),
|
|
- DRM_IOCTL_DEF(DRM_I915_GEM_ENTERVT, i915_gem_entervt_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
|
- DRM_IOCTL_DEF(DRM_I915_GEM_LEAVEVT, i915_gem_leavevt_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
|
- DRM_IOCTL_DEF(DRM_I915_GEM_CREATE, i915_gem_create_ioctl, 0),
|
|
- DRM_IOCTL_DEF(DRM_I915_GEM_PREAD, i915_gem_pread_ioctl, 0),
|
|
- DRM_IOCTL_DEF(DRM_I915_GEM_PWRITE, i915_gem_pwrite_ioctl, 0),
|
|
- DRM_IOCTL_DEF(DRM_I915_GEM_MMAP, i915_gem_mmap_ioctl, 0),
|
|
- DRM_IOCTL_DEF(DRM_I915_GEM_MMAP_GTT, i915_gem_mmap_gtt_ioctl, 0),
|
|
- DRM_IOCTL_DEF(DRM_I915_GEM_SET_DOMAIN, i915_gem_set_domain_ioctl, 0),
|
|
- DRM_IOCTL_DEF(DRM_I915_GEM_SW_FINISH, i915_gem_sw_finish_ioctl, 0),
|
|
- DRM_IOCTL_DEF(DRM_I915_GEM_SET_TILING, i915_gem_set_tiling, 0),
|
|
- DRM_IOCTL_DEF(DRM_I915_GEM_GET_TILING, i915_gem_get_tiling, 0),
|
|
- DRM_IOCTL_DEF(DRM_I915_GEM_GET_APERTURE, i915_gem_get_aperture_ioctl, 0),
|
|
- DRM_IOCTL_DEF(DRM_I915_GET_PIPE_FROM_CRTC_ID, intel_get_pipe_from_crtc_id, 0),
|
|
- DRM_IOCTL_DEF(DRM_I915_GEM_MADVISE, i915_gem_madvise_ioctl, 0),
|
|
- DRM_IOCTL_DEF(DRM_I915_OVERLAY_PUT_IMAGE, intel_overlay_put_image, DRM_MASTER|DRM_CONTROL_ALLOW),
|
|
- DRM_IOCTL_DEF(DRM_I915_OVERLAY_ATTRS, intel_overlay_attrs, DRM_MASTER|DRM_CONTROL_ALLOW),
|
|
+ DRM_IOCTL_DEF(DRM_I915_GEM_INIT, i915_gem_init_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
|
|
+ DRM_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH|DRM_UNLOCKED),
|
|
+ DRM_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER2, i915_gem_execbuffer2, DRM_AUTH|DRM_UNLOCKED),
|
|
+ DRM_IOCTL_DEF(DRM_I915_GEM_PIN, i915_gem_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY|DRM_UNLOCKED),
|
|
+ DRM_IOCTL_DEF(DRM_I915_GEM_UNPIN, i915_gem_unpin_ioctl, DRM_AUTH|DRM_ROOT_ONLY|DRM_UNLOCKED),
|
|
+ DRM_IOCTL_DEF(DRM_I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH|DRM_UNLOCKED),
|
|
+ DRM_IOCTL_DEF(DRM_I915_GEM_THROTTLE, i915_gem_throttle_ioctl, DRM_AUTH|DRM_UNLOCKED),
|
|
+ DRM_IOCTL_DEF(DRM_I915_GEM_ENTERVT, i915_gem_entervt_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
|
|
+ DRM_IOCTL_DEF(DRM_I915_GEM_LEAVEVT, i915_gem_leavevt_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
|
|
+ DRM_IOCTL_DEF(DRM_I915_GEM_CREATE, i915_gem_create_ioctl, DRM_UNLOCKED),
|
|
+ DRM_IOCTL_DEF(DRM_I915_GEM_PREAD, i915_gem_pread_ioctl, DRM_UNLOCKED),
|
|
+ DRM_IOCTL_DEF(DRM_I915_GEM_PWRITE, i915_gem_pwrite_ioctl, DRM_UNLOCKED),
|
|
+ DRM_IOCTL_DEF(DRM_I915_GEM_MMAP, i915_gem_mmap_ioctl, DRM_UNLOCKED),
|
|
+ DRM_IOCTL_DEF(DRM_I915_GEM_MMAP_GTT, i915_gem_mmap_gtt_ioctl, DRM_UNLOCKED),
|
|
+ DRM_IOCTL_DEF(DRM_I915_GEM_SET_DOMAIN, i915_gem_set_domain_ioctl, DRM_UNLOCKED),
|
|
+ DRM_IOCTL_DEF(DRM_I915_GEM_SW_FINISH, i915_gem_sw_finish_ioctl, DRM_UNLOCKED),
|
|
+ DRM_IOCTL_DEF(DRM_I915_GEM_SET_TILING, i915_gem_set_tiling, DRM_UNLOCKED),
|
|
+ DRM_IOCTL_DEF(DRM_I915_GEM_GET_TILING, i915_gem_get_tiling, DRM_UNLOCKED),
|
|
+ DRM_IOCTL_DEF(DRM_I915_GEM_GET_APERTURE, i915_gem_get_aperture_ioctl, DRM_UNLOCKED),
|
|
+ DRM_IOCTL_DEF(DRM_I915_GET_PIPE_FROM_CRTC_ID, intel_get_pipe_from_crtc_id, DRM_UNLOCKED),
|
|
+ DRM_IOCTL_DEF(DRM_I915_GEM_MADVISE, i915_gem_madvise_ioctl, DRM_UNLOCKED),
|
|
+ DRM_IOCTL_DEF(DRM_I915_OVERLAY_PUT_IMAGE, intel_overlay_put_image, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
|
|
+ DRM_IOCTL_DEF(DRM_I915_OVERLAY_ATTRS, intel_overlay_attrs, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
|
|
};
|
|
|
|
int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
|
|
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
|
|
--- a/drivers/gpu/drm/i915/i915_drv.c
|
|
+++ b/drivers/gpu/drm/i915/i915_drv.c
|
|
@@ -49,6 +49,7 @@ unsigned int i915_lvds_downclock = 0;
|
|
module_param_named(lvds_downclock, i915_lvds_downclock, int, 0400);
|
|
|
|
static struct drm_driver driver;
|
|
+extern int intel_agp_enabled;
|
|
|
|
#define INTEL_VGA_DEVICE(id, info) { \
|
|
.class = PCI_CLASS_DISPLAY_VGA << 8, \
|
|
@@ -68,7 +69,8 @@ const static struct intel_device_info intel_845g_info = {
|
|
};
|
|
|
|
const static struct intel_device_info intel_i85x_info = {
|
|
- .is_i8xx = 1, .is_mobile = 1, .cursor_needs_physical = 1,
|
|
+ .is_i8xx = 1, .is_i85x = 1, .is_mobile = 1,
|
|
+ .cursor_needs_physical = 1,
|
|
};
|
|
|
|
const static struct intel_device_info intel_i865g_info = {
|
|
@@ -79,14 +81,14 @@ const static struct intel_device_info intel_i915g_info = {
|
|
.is_i915g = 1, .is_i9xx = 1, .cursor_needs_physical = 1,
|
|
};
|
|
const static struct intel_device_info intel_i915gm_info = {
|
|
- .is_i9xx = 1, .is_mobile = 1, .has_fbc = 1,
|
|
+ .is_i9xx = 1, .is_mobile = 1,
|
|
.cursor_needs_physical = 1,
|
|
};
|
|
const static struct intel_device_info intel_i945g_info = {
|
|
.is_i9xx = 1, .has_hotplug = 1, .cursor_needs_physical = 1,
|
|
};
|
|
const static struct intel_device_info intel_i945gm_info = {
|
|
- .is_i945gm = 1, .is_i9xx = 1, .is_mobile = 1, .has_fbc = 1,
|
|
+ .is_i945gm = 1, .is_i9xx = 1, .is_mobile = 1,
|
|
.has_hotplug = 1, .cursor_needs_physical = 1,
|
|
};
|
|
|
|
@@ -136,11 +138,21 @@ const static struct intel_device_info intel_ironlake_m_info = {
|
|
.has_hotplug = 1,
|
|
};
|
|
|
|
+const static struct intel_device_info intel_sandybridge_d_info = {
|
|
+ .is_i965g = 1, .is_i9xx = 1, .need_gfx_hws = 1,
|
|
+ .has_hotplug = 1, .is_gen6 = 1,
|
|
+};
|
|
+
|
|
+const static struct intel_device_info intel_sandybridge_m_info = {
|
|
+ .is_i965g = 1, .is_mobile = 1, .is_i9xx = 1, .need_gfx_hws = 1,
|
|
+ .has_hotplug = 1, .is_gen6 = 1,
|
|
+};
|
|
+
|
|
const static struct pci_device_id pciidlist[] = {
|
|
INTEL_VGA_DEVICE(0x3577, &intel_i830_info),
|
|
INTEL_VGA_DEVICE(0x2562, &intel_845g_info),
|
|
INTEL_VGA_DEVICE(0x3582, &intel_i85x_info),
|
|
- INTEL_VGA_DEVICE(0x35e8, &intel_i85x_info),
|
|
+ INTEL_VGA_DEVICE(0x358e, &intel_i85x_info),
|
|
INTEL_VGA_DEVICE(0x2572, &intel_i865g_info),
|
|
INTEL_VGA_DEVICE(0x2582, &intel_i915g_info),
|
|
INTEL_VGA_DEVICE(0x258a, &intel_i915g_info),
|
|
@@ -167,6 +179,8 @@ const static struct pci_device_id pciidlist[] = {
|
|
INTEL_VGA_DEVICE(0xa011, &intel_pineview_info),
|
|
INTEL_VGA_DEVICE(0x0042, &intel_ironlake_d_info),
|
|
INTEL_VGA_DEVICE(0x0046, &intel_ironlake_m_info),
|
|
+ INTEL_VGA_DEVICE(0x0102, &intel_sandybridge_d_info),
|
|
+ INTEL_VGA_DEVICE(0x0106, &intel_sandybridge_m_info),
|
|
{0, 0, 0}
|
|
};
|
|
|
|
@@ -174,6 +188,35 @@ const static struct pci_device_id pciidlist[] = {
|
|
MODULE_DEVICE_TABLE(pci, pciidlist);
|
|
#endif
|
|
|
|
+#define INTEL_PCH_DEVICE_ID_MASK 0xff00
|
|
+#define INTEL_PCH_CPT_DEVICE_ID_TYPE 0x1c00
|
|
+
|
|
+void intel_detect_pch (struct drm_device *dev)
|
|
+{
|
|
+ struct drm_i915_private *dev_priv = dev->dev_private;
|
|
+ struct pci_dev *pch;
|
|
+
|
|
+ /*
|
|
+ * The reason to probe ISA bridge instead of Dev31:Fun0 is to
|
|
+ * make graphics device passthrough work easy for VMM, that only
|
|
+ * need to expose ISA bridge to let driver know the real hardware
|
|
+ * underneath. This is a requirement from virtualization team.
|
|
+ */
|
|
+ pch = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL);
|
|
+ if (pch) {
|
|
+ if (pch->vendor == PCI_VENDOR_ID_INTEL) {
|
|
+ int id;
|
|
+ id = pch->device & INTEL_PCH_DEVICE_ID_MASK;
|
|
+
|
|
+ if (id == INTEL_PCH_CPT_DEVICE_ID_TYPE) {
|
|
+ dev_priv->pch_type = PCH_CPT;
|
|
+ DRM_DEBUG_KMS("Found CougarPoint PCH\n");
|
|
+ }
|
|
+ }
|
|
+ pci_dev_put(pch);
|
|
+ }
|
|
+}
|
|
+
|
|
static int i915_drm_freeze(struct drm_device *dev)
|
|
{
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
@@ -348,7 +391,7 @@ int i965_reset(struct drm_device *dev, u8 flags)
|
|
!dev_priv->mm.suspended) {
|
|
drm_i915_ring_buffer_t *ring = &dev_priv->ring;
|
|
struct drm_gem_object *obj = ring->ring_obj;
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
dev_priv->mm.suspended = 0;
|
|
|
|
/* Stop the ring if it's running. */
|
|
@@ -546,6 +589,11 @@ static struct drm_driver driver = {
|
|
|
|
static int __init i915_init(void)
|
|
{
|
|
+ if (!intel_agp_enabled) {
|
|
+ DRM_ERROR("drm/i915 can't work without intel_agp module!\n");
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
driver.num_ioctls = i915_max_ioctl;
|
|
|
|
i915_gem_shrinker_init();
|
|
@@ -571,6 +619,11 @@ static int __init i915_init(void)
|
|
driver.driver_features &= ~DRIVER_MODESET;
|
|
#endif
|
|
|
|
+ if (!(driver.driver_features & DRIVER_MODESET)) {
|
|
+ driver.suspend = i915_suspend;
|
|
+ driver.resume = i915_resume;
|
|
+ }
|
|
+
|
|
return drm_init(&driver);
|
|
}
|
|
|
|
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
|
|
--- a/drivers/gpu/drm/i915/i915_drv.h
|
|
+++ b/drivers/gpu/drm/i915/i915_drv.h
|
|
@@ -150,7 +150,27 @@ struct drm_i915_error_state {
|
|
u32 instps;
|
|
u32 instdone1;
|
|
u32 seqno;
|
|
+ u64 bbaddr;
|
|
struct timeval time;
|
|
+ struct drm_i915_error_object {
|
|
+ int page_count;
|
|
+ u32 gtt_offset;
|
|
+ u32 *pages[0];
|
|
+ } *ringbuffer, *batchbuffer[2];
|
|
+ struct drm_i915_error_buffer {
|
|
+ size_t size;
|
|
+ u32 name;
|
|
+ u32 seqno;
|
|
+ u32 gtt_offset;
|
|
+ u32 read_domains;
|
|
+ u32 write_domain;
|
|
+ u32 fence_reg;
|
|
+ s32 pinned:2;
|
|
+ u32 tiling:2;
|
|
+ u32 dirty:1;
|
|
+ u32 purgeable:1;
|
|
+ } *active_bo;
|
|
+ u32 active_bo_count;
|
|
};
|
|
|
|
struct drm_i915_display_funcs {
|
|
@@ -175,6 +195,7 @@ struct intel_overlay;
|
|
struct intel_device_info {
|
|
u8 is_mobile : 1;
|
|
u8 is_i8xx : 1;
|
|
+ u8 is_i85x : 1;
|
|
u8 is_i915g : 1;
|
|
u8 is_i9xx : 1;
|
|
u8 is_i945gm : 1;
|
|
@@ -185,6 +206,7 @@ struct intel_device_info {
|
|
u8 is_g4x : 1;
|
|
u8 is_pineview : 1;
|
|
u8 is_ironlake : 1;
|
|
+ u8 is_gen6 : 1;
|
|
u8 has_fbc : 1;
|
|
u8 has_rc6 : 1;
|
|
u8 has_pipe_cxsr : 1;
|
|
@@ -192,6 +214,19 @@ struct intel_device_info {
|
|
u8 cursor_needs_physical : 1;
|
|
};
|
|
|
|
+enum no_fbc_reason {
|
|
+ FBC_STOLEN_TOO_SMALL, /* not enough space to hold compressed buffers */
|
|
+ FBC_UNSUPPORTED_MODE, /* interlace or doublescanned mode */
|
|
+ FBC_MODE_TOO_LARGE, /* mode too large for compression */
|
|
+ FBC_BAD_PLANE, /* fbc not supported on plane */
|
|
+ FBC_NOT_TILED, /* buffer not tiled */
|
|
+};
|
|
+
|
|
+enum intel_pch {
|
|
+ PCH_IBX, /* Ibexpeak PCH */
|
|
+ PCH_CPT, /* Cougarpoint PCH */
|
|
+};
|
|
+
|
|
typedef struct drm_i915_private {
|
|
struct drm_device *dev;
|
|
|
|
@@ -302,6 +337,9 @@ typedef struct drm_i915_private {
|
|
/* Display functions */
|
|
struct drm_i915_display_funcs display;
|
|
|
|
+ /* PCH chipset type */
|
|
+ enum intel_pch pch_type;
|
|
+
|
|
/* Register state */
|
|
bool modeset_on_lid;
|
|
u8 saveLBB;
|
|
@@ -452,6 +490,7 @@ typedef struct drm_i915_private {
|
|
u32 savePIPEB_DATA_N1;
|
|
u32 savePIPEB_LINK_M1;
|
|
u32 savePIPEB_LINK_N1;
|
|
+ u32 saveMCHBAR_RENDER_STANDBY;
|
|
|
|
struct {
|
|
struct drm_mm gtt_space;
|
|
@@ -581,6 +620,8 @@ typedef struct drm_i915_private {
|
|
/* Reclocking support */
|
|
bool render_reclock_avail;
|
|
bool lvds_downclock_avail;
|
|
+ /* indicate whether the LVDS EDID is OK */
|
|
+ bool lvds_edid_good;
|
|
/* indicates the reduced downclock for LVDS*/
|
|
int lvds_downclock;
|
|
struct work_struct idle_work;
|
|
@@ -590,6 +631,14 @@ typedef struct drm_i915_private {
|
|
int child_dev_num;
|
|
struct child_device_config *child_dev;
|
|
struct drm_connector *int_lvds_connector;
|
|
+
|
|
+ bool mchbar_need_disable;
|
|
+
|
|
+ u8 cur_delay;
|
|
+ u8 min_delay;
|
|
+ u8 max_delay;
|
|
+
|
|
+ enum no_fbc_reason no_fbc_reason;
|
|
} drm_i915_private_t;
|
|
|
|
/** driver private structure attached to each drm_gem_object */
|
|
@@ -693,6 +742,8 @@ struct drm_i915_gem_object {
|
|
atomic_t pending_flip;
|
|
};
|
|
|
|
+#define to_intel_bo(x) ((struct drm_i915_gem_object *) (x)->driver_private)
|
|
+
|
|
/**
|
|
* Request queue structure.
|
|
*
|
|
@@ -761,6 +812,7 @@ extern int i965_reset(struct drm_device *dev, u8 flags);
|
|
|
|
/* i915_irq.c */
|
|
void i915_hangcheck_elapsed(unsigned long data);
|
|
+void i915_destroy_error_state(struct drm_device *dev);
|
|
extern int i915_irq_emit(struct drm_device *dev, void *data,
|
|
struct drm_file *file_priv);
|
|
extern int i915_irq_wait(struct drm_device *dev, void *data,
|
|
@@ -897,7 +949,8 @@ void i915_gem_object_do_bit_17_swizzle(struct drm_gem_object *obj);
|
|
void i915_gem_object_save_bit_17_swizzle(struct drm_gem_object *obj);
|
|
bool i915_tiling_ok(struct drm_device *dev, int stride, int size,
|
|
int tiling_mode);
|
|
-bool i915_obj_fenceable(struct drm_device *dev, struct drm_gem_object *obj);
|
|
+bool i915_gem_object_fence_offset_ok(struct drm_gem_object *obj,
|
|
+ int tiling_mode);
|
|
|
|
/* i915_gem_debug.c */
|
|
void i915_gem_dump_object(struct drm_gem_object *obj, int len,
|
|
@@ -946,6 +999,9 @@ extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state);
|
|
extern void i8xx_disable_fbc(struct drm_device *dev);
|
|
extern void g4x_disable_fbc(struct drm_device *dev);
|
|
|
|
+extern void intel_detect_pch (struct drm_device *dev);
|
|
+extern int intel_trans_dp_port_sel (struct drm_crtc *crtc);
|
|
+
|
|
/**
|
|
* Lock test for when it's just for synchronization of ring access.
|
|
*
|
|
@@ -1024,9 +1080,9 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
|
|
|
|
#define IS_I830(dev) ((dev)->pci_device == 0x3577)
|
|
#define IS_845G(dev) ((dev)->pci_device == 0x2562)
|
|
-#define IS_I85X(dev) ((dev)->pci_device == 0x3582)
|
|
+#define IS_I85X(dev) (INTEL_INFO(dev)->is_i85x)
|
|
#define IS_I865G(dev) ((dev)->pci_device == 0x2572)
|
|
-#define IS_I8XX(dev) (INTEL_INFO(dev)->is_i8xx)
|
|
+#define IS_GEN2(dev) (INTEL_INFO(dev)->is_i8xx)
|
|
#define IS_I915G(dev) (INTEL_INFO(dev)->is_i915g)
|
|
#define IS_I915GM(dev) ((dev)->pci_device == 0x2592)
|
|
#define IS_I945G(dev) ((dev)->pci_device == 0x2772)
|
|
@@ -1043,8 +1099,28 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
|
|
#define IS_IRONLAKE_M(dev) ((dev)->pci_device == 0x0046)
|
|
#define IS_IRONLAKE(dev) (INTEL_INFO(dev)->is_ironlake)
|
|
#define IS_I9XX(dev) (INTEL_INFO(dev)->is_i9xx)
|
|
+#define IS_GEN6(dev) (INTEL_INFO(dev)->is_gen6)
|
|
#define IS_MOBILE(dev) (INTEL_INFO(dev)->is_mobile)
|
|
|
|
+#define IS_GEN3(dev) (IS_I915G(dev) || \
|
|
+ IS_I915GM(dev) || \
|
|
+ IS_I945G(dev) || \
|
|
+ IS_I945GM(dev) || \
|
|
+ IS_G33(dev) || \
|
|
+ IS_PINEVIEW(dev))
|
|
+#define IS_GEN4(dev) ((dev)->pci_device == 0x2972 || \
|
|
+ (dev)->pci_device == 0x2982 || \
|
|
+ (dev)->pci_device == 0x2992 || \
|
|
+ (dev)->pci_device == 0x29A2 || \
|
|
+ (dev)->pci_device == 0x2A02 || \
|
|
+ (dev)->pci_device == 0x2A12 || \
|
|
+ (dev)->pci_device == 0x2E02 || \
|
|
+ (dev)->pci_device == 0x2E12 || \
|
|
+ (dev)->pci_device == 0x2E22 || \
|
|
+ (dev)->pci_device == 0x2E32 || \
|
|
+ (dev)->pci_device == 0x2A42 || \
|
|
+ (dev)->pci_device == 0x2E42)
|
|
+
|
|
#define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws)
|
|
|
|
/* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte
|
|
@@ -1057,7 +1133,8 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
|
|
#define SUPPORTS_INTEGRATED_DP(dev) (IS_G4X(dev) || IS_IRONLAKE(dev))
|
|
#define SUPPORTS_EDP(dev) (IS_IRONLAKE_M(dev))
|
|
#define SUPPORTS_TV(dev) (IS_I9XX(dev) && IS_MOBILE(dev) && \
|
|
- !IS_IRONLAKE(dev) && !IS_PINEVIEW(dev))
|
|
+ !IS_IRONLAKE(dev) && !IS_PINEVIEW(dev) && \
|
|
+ !IS_GEN6(dev))
|
|
#define I915_HAS_HOTPLUG(dev) (INTEL_INFO(dev)->has_hotplug)
|
|
/* dsparb controlled by hw only */
|
|
#define DSPARB_HWCONTROL(dev) (IS_G4X(dev) || IS_IRONLAKE(dev))
|
|
@@ -1067,6 +1144,12 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
|
|
#define I915_HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc)
|
|
#define I915_HAS_RC6(dev) (INTEL_INFO(dev)->has_rc6)
|
|
|
|
+#define HAS_PCH_SPLIT(dev) (IS_IRONLAKE(dev) || \
|
|
+ IS_GEN6(dev))
|
|
+
|
|
+#define INTEL_PCH_TYPE(dev) (((struct drm_i915_private *)(dev)->dev_private)->pch_type)
|
|
+#define HAS_PCH_CPT(dev) (INTEL_PCH_TYPE(dev) == PCH_CPT)
|
|
+
|
|
#define PRIMARY_RINGBUFFER_SIZE (128*1024)
|
|
|
|
#endif
|
|
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
|
|
--- a/drivers/gpu/drm/i915/i915_gem.c
|
|
+++ b/drivers/gpu/drm/i915/i915_gem.c
|
|
@@ -162,7 +162,7 @@ fast_shmem_read(struct page **pages,
|
|
static int i915_gem_object_needs_bit17_swizzle(struct drm_gem_object *obj)
|
|
{
|
|
drm_i915_private_t *dev_priv = obj->dev->dev_private;
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
|
|
return dev_priv->mm.bit_6_swizzle_x == I915_BIT_6_SWIZZLE_9_10_17 &&
|
|
obj_priv->tiling_mode != I915_TILING_NONE;
|
|
@@ -263,7 +263,7 @@ i915_gem_shmem_pread_fast(struct drm_device *dev, struct drm_gem_object *obj,
|
|
struct drm_i915_gem_pread *args,
|
|
struct drm_file *file_priv)
|
|
{
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
ssize_t remain;
|
|
loff_t offset, page_base;
|
|
char __user *user_data;
|
|
@@ -284,7 +284,7 @@ i915_gem_shmem_pread_fast(struct drm_device *dev, struct drm_gem_object *obj,
|
|
if (ret != 0)
|
|
goto fail_put_pages;
|
|
|
|
- obj_priv = obj->driver_private;
|
|
+ obj_priv = to_intel_bo(obj);
|
|
offset = args->offset;
|
|
|
|
while (remain > 0) {
|
|
@@ -353,7 +353,7 @@ i915_gem_shmem_pread_slow(struct drm_device *dev, struct drm_gem_object *obj,
|
|
struct drm_i915_gem_pread *args,
|
|
struct drm_file *file_priv)
|
|
{
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
struct mm_struct *mm = current->mm;
|
|
struct page **user_pages;
|
|
ssize_t remain;
|
|
@@ -402,7 +402,7 @@ i915_gem_shmem_pread_slow(struct drm_device *dev, struct drm_gem_object *obj,
|
|
if (ret != 0)
|
|
goto fail_put_pages;
|
|
|
|
- obj_priv = obj->driver_private;
|
|
+ obj_priv = to_intel_bo(obj);
|
|
offset = args->offset;
|
|
|
|
while (remain > 0) {
|
|
@@ -478,7 +478,7 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data,
|
|
obj = drm_gem_object_lookup(dev, file_priv, args->handle);
|
|
if (obj == NULL)
|
|
return -EBADF;
|
|
- obj_priv = obj->driver_private;
|
|
+ obj_priv = to_intel_bo(obj);
|
|
|
|
/* Bounds check source.
|
|
*
|
|
@@ -580,7 +580,7 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev, struct drm_gem_object *obj,
|
|
struct drm_i915_gem_pwrite *args,
|
|
struct drm_file *file_priv)
|
|
{
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
|
ssize_t remain;
|
|
loff_t offset, page_base;
|
|
@@ -604,7 +604,7 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev, struct drm_gem_object *obj,
|
|
if (ret)
|
|
goto fail;
|
|
|
|
- obj_priv = obj->driver_private;
|
|
+ obj_priv = to_intel_bo(obj);
|
|
offset = obj_priv->gtt_offset + args->offset;
|
|
|
|
while (remain > 0) {
|
|
@@ -654,7 +654,7 @@ i915_gem_gtt_pwrite_slow(struct drm_device *dev, struct drm_gem_object *obj,
|
|
struct drm_i915_gem_pwrite *args,
|
|
struct drm_file *file_priv)
|
|
{
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
|
ssize_t remain;
|
|
loff_t gtt_page_base, offset;
|
|
@@ -698,7 +698,7 @@ i915_gem_gtt_pwrite_slow(struct drm_device *dev, struct drm_gem_object *obj,
|
|
if (ret)
|
|
goto out_unpin_object;
|
|
|
|
- obj_priv = obj->driver_private;
|
|
+ obj_priv = to_intel_bo(obj);
|
|
offset = obj_priv->gtt_offset + args->offset;
|
|
|
|
while (remain > 0) {
|
|
@@ -760,7 +760,7 @@ i915_gem_shmem_pwrite_fast(struct drm_device *dev, struct drm_gem_object *obj,
|
|
struct drm_i915_gem_pwrite *args,
|
|
struct drm_file *file_priv)
|
|
{
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
ssize_t remain;
|
|
loff_t offset, page_base;
|
|
char __user *user_data;
|
|
@@ -780,7 +780,7 @@ i915_gem_shmem_pwrite_fast(struct drm_device *dev, struct drm_gem_object *obj,
|
|
if (ret != 0)
|
|
goto fail_put_pages;
|
|
|
|
- obj_priv = obj->driver_private;
|
|
+ obj_priv = to_intel_bo(obj);
|
|
offset = args->offset;
|
|
obj_priv->dirty = 1;
|
|
|
|
@@ -828,7 +828,7 @@ i915_gem_shmem_pwrite_slow(struct drm_device *dev, struct drm_gem_object *obj,
|
|
struct drm_i915_gem_pwrite *args,
|
|
struct drm_file *file_priv)
|
|
{
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
struct mm_struct *mm = current->mm;
|
|
struct page **user_pages;
|
|
ssize_t remain;
|
|
@@ -876,7 +876,7 @@ i915_gem_shmem_pwrite_slow(struct drm_device *dev, struct drm_gem_object *obj,
|
|
if (ret != 0)
|
|
goto fail_put_pages;
|
|
|
|
- obj_priv = obj->driver_private;
|
|
+ obj_priv = to_intel_bo(obj);
|
|
offset = args->offset;
|
|
obj_priv->dirty = 1;
|
|
|
|
@@ -951,7 +951,7 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
|
|
obj = drm_gem_object_lookup(dev, file_priv, args->handle);
|
|
if (obj == NULL)
|
|
return -EBADF;
|
|
- obj_priv = obj->driver_private;
|
|
+ obj_priv = to_intel_bo(obj);
|
|
|
|
/* Bounds check destination.
|
|
*
|
|
@@ -1033,7 +1033,7 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
|
|
obj = drm_gem_object_lookup(dev, file_priv, args->handle);
|
|
if (obj == NULL)
|
|
return -EBADF;
|
|
- obj_priv = obj->driver_private;
|
|
+ obj_priv = to_intel_bo(obj);
|
|
|
|
mutex_lock(&dev->struct_mutex);
|
|
|
|
@@ -1095,7 +1095,7 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,
|
|
DRM_INFO("%s: sw_finish %d (%p %zd)\n",
|
|
__func__, args->handle, obj, obj->size);
|
|
#endif
|
|
- obj_priv = obj->driver_private;
|
|
+ obj_priv = to_intel_bo(obj);
|
|
|
|
/* Pinned buffers may be scanout, so flush the cache */
|
|
if (obj_priv->pin_count)
|
|
@@ -1166,7 +1166,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
|
|
struct drm_gem_object *obj = vma->vm_private_data;
|
|
struct drm_device *dev = obj->dev;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
pgoff_t page_offset;
|
|
unsigned long pfn;
|
|
int ret = 0;
|
|
@@ -1233,7 +1233,7 @@ i915_gem_create_mmap_offset(struct drm_gem_object *obj)
|
|
{
|
|
struct drm_device *dev = obj->dev;
|
|
struct drm_gem_mm *mm = dev->mm_private;
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
struct drm_map_list *list;
|
|
struct drm_local_map *map;
|
|
int ret = 0;
|
|
@@ -1304,7 +1304,7 @@ void
|
|
i915_gem_release_mmap(struct drm_gem_object *obj)
|
|
{
|
|
struct drm_device *dev = obj->dev;
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
|
|
if (dev->dev_mapping)
|
|
unmap_mapping_range(dev->dev_mapping,
|
|
@@ -1315,7 +1315,7 @@ static void
|
|
i915_gem_free_mmap_offset(struct drm_gem_object *obj)
|
|
{
|
|
struct drm_device *dev = obj->dev;
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
struct drm_gem_mm *mm = dev->mm_private;
|
|
struct drm_map_list *list;
|
|
|
|
@@ -1346,7 +1346,7 @@ static uint32_t
|
|
i915_gem_get_gtt_alignment(struct drm_gem_object *obj)
|
|
{
|
|
struct drm_device *dev = obj->dev;
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
int start, i;
|
|
|
|
/*
|
|
@@ -1405,7 +1405,7 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data,
|
|
|
|
mutex_lock(&dev->struct_mutex);
|
|
|
|
- obj_priv = obj->driver_private;
|
|
+ obj_priv = to_intel_bo(obj);
|
|
|
|
if (obj_priv->madv != I915_MADV_WILLNEED) {
|
|
DRM_ERROR("Attempting to mmap a purgeable buffer\n");
|
|
@@ -1449,7 +1449,7 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data,
|
|
void
|
|
i915_gem_object_put_pages(struct drm_gem_object *obj)
|
|
{
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
int page_count = obj->size / PAGE_SIZE;
|
|
int i;
|
|
|
|
@@ -1485,7 +1485,7 @@ i915_gem_object_move_to_active(struct drm_gem_object *obj, uint32_t seqno)
|
|
{
|
|
struct drm_device *dev = obj->dev;
|
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
|
|
/* Add a reference if we're newly entering the active list. */
|
|
if (!obj_priv->active) {
|
|
@@ -1505,7 +1505,7 @@ i915_gem_object_move_to_flushing(struct drm_gem_object *obj)
|
|
{
|
|
struct drm_device *dev = obj->dev;
|
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
|
|
BUG_ON(!obj_priv->active);
|
|
list_move_tail(&obj_priv->list, &dev_priv->mm.flushing_list);
|
|
@@ -1516,7 +1516,7 @@ i915_gem_object_move_to_flushing(struct drm_gem_object *obj)
|
|
static void
|
|
i915_gem_object_truncate(struct drm_gem_object *obj)
|
|
{
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
struct inode *inode;
|
|
|
|
inode = obj->filp->f_path.dentry->d_inode;
|
|
@@ -1537,7 +1537,7 @@ i915_gem_object_move_to_inactive(struct drm_gem_object *obj)
|
|
{
|
|
struct drm_device *dev = obj->dev;
|
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
|
|
i915_verify_inactive(dev, __FILE__, __LINE__);
|
|
if (obj_priv->pin_count != 0)
|
|
@@ -1555,6 +1555,38 @@ i915_gem_object_move_to_inactive(struct drm_gem_object *obj)
|
|
i915_verify_inactive(dev, __FILE__, __LINE__);
|
|
}
|
|
|
|
+static void
|
|
+i915_gem_process_flushing_list(struct drm_device *dev,
|
|
+ uint32_t flush_domains, uint32_t seqno)
|
|
+{
|
|
+ drm_i915_private_t *dev_priv = dev->dev_private;
|
|
+ struct drm_i915_gem_object *obj_priv, *next;
|
|
+
|
|
+ list_for_each_entry_safe(obj_priv, next,
|
|
+ &dev_priv->mm.gpu_write_list,
|
|
+ gpu_write_list) {
|
|
+ struct drm_gem_object *obj = obj_priv->obj;
|
|
+
|
|
+ if ((obj->write_domain & flush_domains) ==
|
|
+ obj->write_domain) {
|
|
+ uint32_t old_write_domain = obj->write_domain;
|
|
+
|
|
+ obj->write_domain = 0;
|
|
+ list_del_init(&obj_priv->gpu_write_list);
|
|
+ i915_gem_object_move_to_active(obj, seqno);
|
|
+
|
|
+ /* update the fence lru list */
|
|
+ if (obj_priv->fence_reg != I915_FENCE_REG_NONE)
|
|
+ list_move_tail(&obj_priv->fence_list,
|
|
+ &dev_priv->mm.fence_list);
|
|
+
|
|
+ trace_i915_gem_object_change_domain(obj,
|
|
+ obj->read_domains,
|
|
+ old_write_domain);
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
/**
|
|
* Creates a new sequence number, emitting a write of it to the status page
|
|
* plus an interrupt, which will trigger i915_user_interrupt_handler.
|
|
@@ -1613,29 +1645,8 @@ i915_add_request(struct drm_device *dev, struct drm_file *file_priv,
|
|
/* Associate any objects on the flushing list matching the write
|
|
* domain we're flushing with our flush.
|
|
*/
|
|
- if (flush_domains != 0) {
|
|
- struct drm_i915_gem_object *obj_priv, *next;
|
|
-
|
|
- list_for_each_entry_safe(obj_priv, next,
|
|
- &dev_priv->mm.gpu_write_list,
|
|
- gpu_write_list) {
|
|
- struct drm_gem_object *obj = obj_priv->obj;
|
|
-
|
|
- if ((obj->write_domain & flush_domains) ==
|
|
- obj->write_domain) {
|
|
- uint32_t old_write_domain = obj->write_domain;
|
|
-
|
|
- obj->write_domain = 0;
|
|
- list_del_init(&obj_priv->gpu_write_list);
|
|
- i915_gem_object_move_to_active(obj, seqno);
|
|
-
|
|
- trace_i915_gem_object_change_domain(obj,
|
|
- obj->read_domains,
|
|
- old_write_domain);
|
|
- }
|
|
- }
|
|
-
|
|
- }
|
|
+ if (flush_domains != 0)
|
|
+ i915_gem_process_flushing_list(dev, flush_domains, seqno);
|
|
|
|
if (!dev_priv->mm.suspended) {
|
|
mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD);
|
|
@@ -1815,7 +1826,7 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptible)
|
|
return -EIO;
|
|
|
|
if (!i915_seqno_passed(i915_get_gem_seqno(dev), seqno)) {
|
|
- if (IS_IRONLAKE(dev))
|
|
+ if (HAS_PCH_SPLIT(dev))
|
|
ier = I915_READ(DEIER) | I915_READ(GTIER);
|
|
else
|
|
ier = I915_READ(IER);
|
|
@@ -1953,7 +1964,7 @@ static int
|
|
i915_gem_object_wait_rendering(struct drm_gem_object *obj)
|
|
{
|
|
struct drm_device *dev = obj->dev;
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
int ret;
|
|
|
|
/* This function only exists to support waiting for existing rendering,
|
|
@@ -1984,7 +1995,8 @@ int
|
|
i915_gem_object_unbind(struct drm_gem_object *obj)
|
|
{
|
|
struct drm_device *dev = obj->dev;
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ drm_i915_private_t *dev_priv = dev->dev_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
int ret = 0;
|
|
|
|
#if WATCH_BUF
|
|
@@ -2039,8 +2051,10 @@ i915_gem_object_unbind(struct drm_gem_object *obj)
|
|
}
|
|
|
|
/* Remove ourselves from the LRU list if present. */
|
|
+ spin_lock(&dev_priv->mm.active_list_lock);
|
|
if (!list_empty(&obj_priv->list))
|
|
list_del_init(&obj_priv->list);
|
|
+ spin_unlock(&dev_priv->mm.active_list_lock);
|
|
|
|
if (i915_gem_object_is_purgeable(obj_priv))
|
|
i915_gem_object_truncate(obj);
|
|
@@ -2078,11 +2092,34 @@ i915_gem_find_inactive_object(struct drm_device *dev, int min_size)
|
|
}
|
|
|
|
static int
|
|
+i915_gpu_idle(struct drm_device *dev)
|
|
+{
|
|
+ drm_i915_private_t *dev_priv = dev->dev_private;
|
|
+ bool lists_empty;
|
|
+ uint32_t seqno;
|
|
+
|
|
+ spin_lock(&dev_priv->mm.active_list_lock);
|
|
+ lists_empty = list_empty(&dev_priv->mm.flushing_list) &&
|
|
+ list_empty(&dev_priv->mm.active_list);
|
|
+ spin_unlock(&dev_priv->mm.active_list_lock);
|
|
+
|
|
+ if (lists_empty)
|
|
+ return 0;
|
|
+
|
|
+ /* Flush everything onto the inactive list. */
|
|
+ i915_gem_flush(dev, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
|
|
+ seqno = i915_add_request(dev, NULL, I915_GEM_GPU_DOMAINS);
|
|
+ if (seqno == 0)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ return i915_wait_request(dev, seqno);
|
|
+}
|
|
+
|
|
+static int
|
|
i915_gem_evict_everything(struct drm_device *dev)
|
|
{
|
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
|
int ret;
|
|
- uint32_t seqno;
|
|
bool lists_empty;
|
|
|
|
spin_lock(&dev_priv->mm.active_list_lock);
|
|
@@ -2095,12 +2132,7 @@ i915_gem_evict_everything(struct drm_device *dev)
|
|
return -ENOSPC;
|
|
|
|
/* Flush everything (on to the inactive lists) and evict */
|
|
- i915_gem_flush(dev, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
|
|
- seqno = i915_add_request(dev, NULL, I915_GEM_GPU_DOMAINS);
|
|
- if (seqno == 0)
|
|
- return -ENOMEM;
|
|
-
|
|
- ret = i915_wait_request(dev, seqno);
|
|
+ ret = i915_gpu_idle(dev);
|
|
if (ret)
|
|
return ret;
|
|
|
|
@@ -2140,7 +2172,7 @@ i915_gem_evict_something(struct drm_device *dev, int min_size)
|
|
#if WATCH_LRU
|
|
DRM_INFO("%s: evicting %p\n", __func__, obj);
|
|
#endif
|
|
- obj_priv = obj->driver_private;
|
|
+ obj_priv = to_intel_bo(obj);
|
|
BUG_ON(obj_priv->pin_count != 0);
|
|
BUG_ON(obj_priv->active);
|
|
|
|
@@ -2192,11 +2224,6 @@ i915_gem_evict_something(struct drm_device *dev, int min_size)
|
|
seqno = i915_add_request(dev, NULL, obj->write_domain);
|
|
if (seqno == 0)
|
|
return -ENOMEM;
|
|
-
|
|
- ret = i915_wait_request(dev, seqno);
|
|
- if (ret)
|
|
- return ret;
|
|
-
|
|
continue;
|
|
}
|
|
}
|
|
@@ -2216,7 +2243,7 @@ int
|
|
i915_gem_object_get_pages(struct drm_gem_object *obj,
|
|
gfp_t gfpmask)
|
|
{
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
int page_count, i;
|
|
struct address_space *mapping;
|
|
struct inode *inode;
|
|
@@ -2264,12 +2291,34 @@ err_pages:
|
|
return PTR_ERR(page);
|
|
}
|
|
|
|
+static void sandybridge_write_fence_reg(struct drm_i915_fence_reg *reg)
|
|
+{
|
|
+ struct drm_gem_object *obj = reg->obj;
|
|
+ struct drm_device *dev = obj->dev;
|
|
+ drm_i915_private_t *dev_priv = dev->dev_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
+ int regnum = obj_priv->fence_reg;
|
|
+ uint64_t val;
|
|
+
|
|
+ val = (uint64_t)((obj_priv->gtt_offset + obj->size - 4096) &
|
|
+ 0xfffff000) << 32;
|
|
+ val |= obj_priv->gtt_offset & 0xfffff000;
|
|
+ val |= (uint64_t)((obj_priv->stride / 128) - 1) <<
|
|
+ SANDYBRIDGE_FENCE_PITCH_SHIFT;
|
|
+
|
|
+ if (obj_priv->tiling_mode == I915_TILING_Y)
|
|
+ val |= 1 << I965_FENCE_TILING_Y_SHIFT;
|
|
+ val |= I965_FENCE_REG_VALID;
|
|
+
|
|
+ I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + (regnum * 8), val);
|
|
+}
|
|
+
|
|
static void i965_write_fence_reg(struct drm_i915_fence_reg *reg)
|
|
{
|
|
struct drm_gem_object *obj = reg->obj;
|
|
struct drm_device *dev = obj->dev;
|
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
int regnum = obj_priv->fence_reg;
|
|
uint64_t val;
|
|
|
|
@@ -2289,7 +2338,7 @@ static void i915_write_fence_reg(struct drm_i915_fence_reg *reg)
|
|
struct drm_gem_object *obj = reg->obj;
|
|
struct drm_device *dev = obj->dev;
|
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
int regnum = obj_priv->fence_reg;
|
|
int tile_width;
|
|
uint32_t fence_reg, val;
|
|
@@ -2312,6 +2361,12 @@ static void i915_write_fence_reg(struct drm_i915_fence_reg *reg)
|
|
pitch_val = obj_priv->stride / tile_width;
|
|
pitch_val = ffs(pitch_val) - 1;
|
|
|
|
+ if (obj_priv->tiling_mode == I915_TILING_Y &&
|
|
+ HAS_128_BYTE_Y_TILING(dev))
|
|
+ WARN_ON(pitch_val > I830_FENCE_MAX_PITCH_VAL);
|
|
+ else
|
|
+ WARN_ON(pitch_val > I915_FENCE_MAX_PITCH_VAL);
|
|
+
|
|
val = obj_priv->gtt_offset;
|
|
if (obj_priv->tiling_mode == I915_TILING_Y)
|
|
val |= 1 << I830_FENCE_TILING_Y_SHIFT;
|
|
@@ -2331,7 +2386,7 @@ static void i830_write_fence_reg(struct drm_i915_fence_reg *reg)
|
|
struct drm_gem_object *obj = reg->obj;
|
|
struct drm_device *dev = obj->dev;
|
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
int regnum = obj_priv->fence_reg;
|
|
uint32_t val;
|
|
uint32_t pitch_val;
|
|
@@ -2360,6 +2415,58 @@ static void i830_write_fence_reg(struct drm_i915_fence_reg *reg)
|
|
I915_WRITE(FENCE_REG_830_0 + (regnum * 4), val);
|
|
}
|
|
|
|
+static int i915_find_fence_reg(struct drm_device *dev)
|
|
+{
|
|
+ struct drm_i915_fence_reg *reg = NULL;
|
|
+ struct drm_i915_gem_object *obj_priv = NULL;
|
|
+ struct drm_i915_private *dev_priv = dev->dev_private;
|
|
+ struct drm_gem_object *obj = NULL;
|
|
+ int i, avail, ret;
|
|
+
|
|
+ /* First try to find a free reg */
|
|
+ avail = 0;
|
|
+ for (i = dev_priv->fence_reg_start; i < dev_priv->num_fence_regs; i++) {
|
|
+ reg = &dev_priv->fence_regs[i];
|
|
+ if (!reg->obj)
|
|
+ return i;
|
|
+
|
|
+ obj_priv = to_intel_bo(reg->obj);
|
|
+ if (!obj_priv->pin_count)
|
|
+ avail++;
|
|
+ }
|
|
+
|
|
+ if (avail == 0)
|
|
+ return -ENOSPC;
|
|
+
|
|
+ /* None available, try to steal one or wait for a user to finish */
|
|
+ i = I915_FENCE_REG_NONE;
|
|
+ list_for_each_entry(obj_priv, &dev_priv->mm.fence_list,
|
|
+ fence_list) {
|
|
+ obj = obj_priv->obj;
|
|
+
|
|
+ if (obj_priv->pin_count)
|
|
+ continue;
|
|
+
|
|
+ /* found one! */
|
|
+ i = obj_priv->fence_reg;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ BUG_ON(i == I915_FENCE_REG_NONE);
|
|
+
|
|
+ /* We only have a reference on obj from the active list. put_fence_reg
|
|
+ * might drop that one, causing a use-after-free in it. So hold a
|
|
+ * private reference to obj like the other callers of put_fence_reg
|
|
+ * (set_tiling ioctl) do. */
|
|
+ drm_gem_object_reference(obj);
|
|
+ ret = i915_gem_object_put_fence_reg(obj);
|
|
+ drm_gem_object_unreference(obj);
|
|
+ if (ret != 0)
|
|
+ return ret;
|
|
+
|
|
+ return i;
|
|
+}
|
|
+
|
|
/**
|
|
* i915_gem_object_get_fence_reg - set up a fence reg for an object
|
|
* @obj: object to map through a fence reg
|
|
@@ -2378,10 +2485,9 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj)
|
|
{
|
|
struct drm_device *dev = obj->dev;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
struct drm_i915_fence_reg *reg = NULL;
|
|
- struct drm_i915_gem_object *old_obj_priv = NULL;
|
|
- int i, ret, avail;
|
|
+ int ret;
|
|
|
|
/* Just update our place in the LRU if our fence is getting used. */
|
|
if (obj_priv->fence_reg != I915_FENCE_REG_NONE) {
|
|
@@ -2409,86 +2515,27 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj)
|
|
break;
|
|
}
|
|
|
|
- /* First try to find a free reg */
|
|
- avail = 0;
|
|
- for (i = dev_priv->fence_reg_start; i < dev_priv->num_fence_regs; i++) {
|
|
- reg = &dev_priv->fence_regs[i];
|
|
- if (!reg->obj)
|
|
- break;
|
|
-
|
|
- old_obj_priv = reg->obj->driver_private;
|
|
- if (!old_obj_priv->pin_count)
|
|
- avail++;
|
|
- }
|
|
-
|
|
- /* None available, try to steal one or wait for a user to finish */
|
|
- if (i == dev_priv->num_fence_regs) {
|
|
- struct drm_gem_object *old_obj = NULL;
|
|
-
|
|
- if (avail == 0)
|
|
- return -ENOSPC;
|
|
-
|
|
- list_for_each_entry(old_obj_priv, &dev_priv->mm.fence_list,
|
|
- fence_list) {
|
|
- old_obj = old_obj_priv->obj;
|
|
-
|
|
- if (old_obj_priv->pin_count)
|
|
- continue;
|
|
-
|
|
- /* Take a reference, as otherwise the wait_rendering
|
|
- * below may cause the object to get freed out from
|
|
- * under us.
|
|
- */
|
|
- drm_gem_object_reference(old_obj);
|
|
-
|
|
- /* i915 uses fences for GPU access to tiled buffers */
|
|
- if (IS_I965G(dev) || !old_obj_priv->active)
|
|
- break;
|
|
-
|
|
- /* This brings the object to the head of the LRU if it
|
|
- * had been written to. The only way this should
|
|
- * result in us waiting longer than the expected
|
|
- * optimal amount of time is if there was a
|
|
- * fence-using buffer later that was read-only.
|
|
- */
|
|
- i915_gem_object_flush_gpu_write_domain(old_obj);
|
|
- ret = i915_gem_object_wait_rendering(old_obj);
|
|
- if (ret != 0) {
|
|
- drm_gem_object_unreference(old_obj);
|
|
- return ret;
|
|
- }
|
|
-
|
|
- break;
|
|
- }
|
|
-
|
|
- /*
|
|
- * Zap this virtual mapping so we can set up a fence again
|
|
- * for this object next time we need it.
|
|
- */
|
|
- i915_gem_release_mmap(old_obj);
|
|
-
|
|
- i = old_obj_priv->fence_reg;
|
|
- reg = &dev_priv->fence_regs[i];
|
|
-
|
|
- old_obj_priv->fence_reg = I915_FENCE_REG_NONE;
|
|
- list_del_init(&old_obj_priv->fence_list);
|
|
-
|
|
- drm_gem_object_unreference(old_obj);
|
|
- }
|
|
+ ret = i915_find_fence_reg(dev);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
|
|
- obj_priv->fence_reg = i;
|
|
+ obj_priv->fence_reg = ret;
|
|
+ reg = &dev_priv->fence_regs[obj_priv->fence_reg];
|
|
list_add_tail(&obj_priv->fence_list, &dev_priv->mm.fence_list);
|
|
|
|
reg->obj = obj;
|
|
|
|
- if (IS_I965G(dev))
|
|
+ if (IS_GEN6(dev))
|
|
+ sandybridge_write_fence_reg(reg);
|
|
+ else if (IS_I965G(dev))
|
|
i965_write_fence_reg(reg);
|
|
else if (IS_I9XX(dev))
|
|
i915_write_fence_reg(reg);
|
|
else
|
|
i830_write_fence_reg(reg);
|
|
|
|
- trace_i915_gem_object_get_fence(obj, i, obj_priv->tiling_mode);
|
|
+ trace_i915_gem_object_get_fence(obj, obj_priv->fence_reg,
|
|
+ obj_priv->tiling_mode);
|
|
|
|
return 0;
|
|
}
|
|
@@ -2505,11 +2552,14 @@ i915_gem_clear_fence_reg(struct drm_gem_object *obj)
|
|
{
|
|
struct drm_device *dev = obj->dev;
|
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
|
|
- if (IS_I965G(dev))
|
|
+ if (IS_GEN6(dev)) {
|
|
+ I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 +
|
|
+ (obj_priv->fence_reg * 8), 0);
|
|
+ } else if (IS_I965G(dev)) {
|
|
I915_WRITE64(FENCE_REG_965_0 + (obj_priv->fence_reg * 8), 0);
|
|
- else {
|
|
+ } else {
|
|
uint32_t fence_reg;
|
|
|
|
if (obj_priv->fence_reg < 8)
|
|
@@ -2538,11 +2588,17 @@ int
|
|
i915_gem_object_put_fence_reg(struct drm_gem_object *obj)
|
|
{
|
|
struct drm_device *dev = obj->dev;
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
|
|
if (obj_priv->fence_reg == I915_FENCE_REG_NONE)
|
|
return 0;
|
|
|
|
+ /* If we've changed tiling, GTT-mappings of the object
|
|
+ * need to re-fault to ensure that the correct fence register
|
|
+ * setup is in place.
|
|
+ */
|
|
+ i915_gem_release_mmap(obj);
|
|
+
|
|
/* On the i915, GPU access to tiled buffers is via a fence,
|
|
* therefore we must wait for any outstanding access to complete
|
|
* before clearing the fence.
|
|
@@ -2551,12 +2607,12 @@ i915_gem_object_put_fence_reg(struct drm_gem_object *obj)
|
|
int ret;
|
|
|
|
i915_gem_object_flush_gpu_write_domain(obj);
|
|
- i915_gem_object_flush_gtt_write_domain(obj);
|
|
ret = i915_gem_object_wait_rendering(obj);
|
|
if (ret != 0)
|
|
return ret;
|
|
}
|
|
|
|
+ i915_gem_object_flush_gtt_write_domain(obj);
|
|
i915_gem_clear_fence_reg (obj);
|
|
|
|
return 0;
|
|
@@ -2570,7 +2626,7 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment)
|
|
{
|
|
struct drm_device *dev = obj->dev;
|
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
struct drm_mm_node *free_space;
|
|
gfp_t gfpmask = __GFP_NORETRY | __GFP_NOWARN;
|
|
int ret;
|
|
@@ -2677,7 +2733,7 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment)
|
|
void
|
|
i915_gem_clflush_object(struct drm_gem_object *obj)
|
|
{
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
|
|
/* If we don't have a page list set up, then we're not pinned
|
|
* to GPU, and we can ignore the cache flush because it'll happen
|
|
@@ -2696,7 +2752,6 @@ static void
|
|
i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj)
|
|
{
|
|
struct drm_device *dev = obj->dev;
|
|
- uint32_t seqno;
|
|
uint32_t old_write_domain;
|
|
|
|
if ((obj->write_domain & I915_GEM_GPU_DOMAINS) == 0)
|
|
@@ -2705,9 +2760,8 @@ i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj)
|
|
/* Queue the GPU write cache flushing we need. */
|
|
old_write_domain = obj->write_domain;
|
|
i915_gem_flush(dev, 0, obj->write_domain);
|
|
- seqno = i915_add_request(dev, NULL, obj->write_domain);
|
|
+ (void) i915_add_request(dev, NULL, obj->write_domain);
|
|
BUG_ON(obj->write_domain);
|
|
- i915_gem_object_move_to_active(obj, seqno);
|
|
|
|
trace_i915_gem_object_change_domain(obj,
|
|
obj->read_domains,
|
|
@@ -2780,7 +2834,7 @@ i915_gem_object_flush_write_domain(struct drm_gem_object *obj)
|
|
int
|
|
i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write)
|
|
{
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
uint32_t old_write_domain, old_read_domains;
|
|
int ret;
|
|
|
|
@@ -2830,7 +2884,7 @@ int
|
|
i915_gem_object_set_to_display_plane(struct drm_gem_object *obj)
|
|
{
|
|
struct drm_device *dev = obj->dev;
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
uint32_t old_write_domain, old_read_domains;
|
|
int ret;
|
|
|
|
@@ -3043,7 +3097,7 @@ static void
|
|
i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj)
|
|
{
|
|
struct drm_device *dev = obj->dev;
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
uint32_t invalidate_domains = 0;
|
|
uint32_t flush_domains = 0;
|
|
uint32_t old_read_domains;
|
|
@@ -3128,7 +3182,7 @@ i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj)
|
|
static void
|
|
i915_gem_object_set_to_full_cpu_read_domain(struct drm_gem_object *obj)
|
|
{
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
|
|
if (!obj_priv->page_cpu_valid)
|
|
return;
|
|
@@ -3168,7 +3222,7 @@ static int
|
|
i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj,
|
|
uint64_t offset, uint64_t size)
|
|
{
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
uint32_t old_read_domains;
|
|
int i, ret;
|
|
|
|
@@ -3237,7 +3291,7 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
|
|
{
|
|
struct drm_device *dev = obj->dev;
|
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
int i, ret;
|
|
void __iomem *reloc_page;
|
|
bool need_fence;
|
|
@@ -3246,7 +3300,8 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
|
|
obj_priv->tiling_mode != I915_TILING_NONE;
|
|
|
|
/* Check fence reg constraints and rebind if necessary */
|
|
- if (need_fence && !i915_obj_fenceable(dev, obj))
|
|
+ if (need_fence && !i915_gem_object_fence_offset_ok(obj,
|
|
+ obj_priv->tiling_mode))
|
|
i915_gem_object_unbind(obj);
|
|
|
|
/* Choose the GTT offset for our buffer and put it there. */
|
|
@@ -3287,7 +3342,7 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
|
|
i915_gem_object_unpin(obj);
|
|
return -EBADF;
|
|
}
|
|
- target_obj_priv = target_obj->driver_private;
|
|
+ target_obj_priv = to_intel_bo(target_obj);
|
|
|
|
#if WATCH_RELOC
|
|
DRM_INFO("%s: obj %p offset %08x target %d "
|
|
@@ -3316,6 +3371,16 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
|
|
}
|
|
|
|
/* Validate that the target is in a valid r/w GPU domain */
|
|
+ if (reloc->write_domain & (reloc->write_domain - 1)) {
|
|
+ DRM_ERROR("reloc with multiple write domains: "
|
|
+ "obj %p target %d offset %d "
|
|
+ "read %08x write %08x",
|
|
+ obj, reloc->target_handle,
|
|
+ (int) reloc->offset,
|
|
+ reloc->read_domains,
|
|
+ reloc->write_domain);
|
|
+ return -EINVAL;
|
|
+ }
|
|
if (reloc->write_domain & I915_GEM_DOMAIN_CPU ||
|
|
reloc->read_domains & I915_GEM_DOMAIN_CPU) {
|
|
DRM_ERROR("reloc with read/write CPU domains: "
|
|
@@ -3629,7 +3694,7 @@ i915_gem_wait_for_pending_flip(struct drm_device *dev,
|
|
prepare_to_wait(&dev_priv->pending_flip_queue,
|
|
&wait, TASK_INTERRUPTIBLE);
|
|
for (i = 0; i < count; i++) {
|
|
- obj_priv = object_list[i]->driver_private;
|
|
+ obj_priv = to_intel_bo(object_list[i]);
|
|
if (atomic_read(&obj_priv->pending_flip) > 0)
|
|
break;
|
|
}
|
|
@@ -3738,7 +3803,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
|
|
goto err;
|
|
}
|
|
|
|
- obj_priv = object_list[i]->driver_private;
|
|
+ obj_priv = to_intel_bo(object_list[i]);
|
|
if (obj_priv->in_execbuffer) {
|
|
DRM_ERROR("Object %p appears more than once in object list\n",
|
|
object_list[i]);
|
|
@@ -3864,7 +3929,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
|
|
|
|
for (i = 0; i < args->buffer_count; i++) {
|
|
struct drm_gem_object *obj = object_list[i];
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
uint32_t old_write_domain = obj->write_domain;
|
|
|
|
obj->write_domain = obj->pending_write_domain;
|
|
@@ -3939,7 +4004,7 @@ err:
|
|
|
|
for (i = 0; i < args->buffer_count; i++) {
|
|
if (object_list[i]) {
|
|
- obj_priv = object_list[i]->driver_private;
|
|
+ obj_priv = to_intel_bo(object_list[i]);
|
|
obj_priv->in_execbuffer = false;
|
|
}
|
|
drm_gem_object_unreference(object_list[i]);
|
|
@@ -4117,7 +4182,7 @@ int
|
|
i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment)
|
|
{
|
|
struct drm_device *dev = obj->dev;
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
int ret;
|
|
|
|
i915_verify_inactive(dev, __FILE__, __LINE__);
|
|
@@ -4150,7 +4215,7 @@ i915_gem_object_unpin(struct drm_gem_object *obj)
|
|
{
|
|
struct drm_device *dev = obj->dev;
|
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
|
|
i915_verify_inactive(dev, __FILE__, __LINE__);
|
|
obj_priv->pin_count--;
|
|
@@ -4190,7 +4255,7 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data,
|
|
mutex_unlock(&dev->struct_mutex);
|
|
return -EBADF;
|
|
}
|
|
- obj_priv = obj->driver_private;
|
|
+ obj_priv = to_intel_bo(obj);
|
|
|
|
if (obj_priv->madv != I915_MADV_WILLNEED) {
|
|
DRM_ERROR("Attempting to pin a purgeable buffer\n");
|
|
@@ -4247,7 +4312,7 @@ i915_gem_unpin_ioctl(struct drm_device *dev, void *data,
|
|
return -EBADF;
|
|
}
|
|
|
|
- obj_priv = obj->driver_private;
|
|
+ obj_priv = to_intel_bo(obj);
|
|
if (obj_priv->pin_filp != file_priv) {
|
|
DRM_ERROR("Not pinned by caller in i915_gem_pin_ioctl(): %d\n",
|
|
args->handle);
|
|
@@ -4289,7 +4354,7 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
|
|
*/
|
|
i915_gem_retire_requests(dev);
|
|
|
|
- obj_priv = obj->driver_private;
|
|
+ obj_priv = to_intel_bo(obj);
|
|
/* Don't count being on the flushing list against the object being
|
|
* done. Otherwise, a buffer left on the flushing list but not getting
|
|
* flushed (because nobody's flushing that domain) won't ever return
|
|
@@ -4335,7 +4400,7 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data,
|
|
}
|
|
|
|
mutex_lock(&dev->struct_mutex);
|
|
- obj_priv = obj->driver_private;
|
|
+ obj_priv = to_intel_bo(obj);
|
|
|
|
if (obj_priv->pin_count) {
|
|
drm_gem_object_unreference(obj);
|
|
@@ -4396,7 +4461,7 @@ int i915_gem_init_object(struct drm_gem_object *obj)
|
|
void i915_gem_free_object(struct drm_gem_object *obj)
|
|
{
|
|
struct drm_device *dev = obj->dev;
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
|
|
trace_i915_gem_object_destroy(obj);
|
|
|
|
@@ -4444,8 +4509,7 @@ int
|
|
i915_gem_idle(struct drm_device *dev)
|
|
{
|
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
|
- uint32_t seqno, cur_seqno, last_seqno;
|
|
- int stuck, ret;
|
|
+ int ret;
|
|
|
|
mutex_lock(&dev->struct_mutex);
|
|
|
|
@@ -4454,115 +4518,36 @@ i915_gem_idle(struct drm_device *dev)
|
|
return 0;
|
|
}
|
|
|
|
- /* Hack! Don't let anybody do execbuf while we don't control the chip.
|
|
- * We need to replace this with a semaphore, or something.
|
|
- */
|
|
- dev_priv->mm.suspended = 1;
|
|
- del_timer(&dev_priv->hangcheck_timer);
|
|
-
|
|
- /* Cancel the retire work handler, wait for it to finish if running
|
|
- */
|
|
- mutex_unlock(&dev->struct_mutex);
|
|
- cancel_delayed_work_sync(&dev_priv->mm.retire_work);
|
|
- mutex_lock(&dev->struct_mutex);
|
|
-
|
|
- i915_kernel_lost_context(dev);
|
|
-
|
|
- /* Flush the GPU along with all non-CPU write domains
|
|
- */
|
|
- i915_gem_flush(dev, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
|
|
- seqno = i915_add_request(dev, NULL, I915_GEM_GPU_DOMAINS);
|
|
-
|
|
- if (seqno == 0) {
|
|
+ ret = i915_gpu_idle(dev);
|
|
+ if (ret) {
|
|
mutex_unlock(&dev->struct_mutex);
|
|
- return -ENOMEM;
|
|
+ return ret;
|
|
}
|
|
|
|
- dev_priv->mm.waiting_gem_seqno = seqno;
|
|
- last_seqno = 0;
|
|
- stuck = 0;
|
|
- for (;;) {
|
|
- cur_seqno = i915_get_gem_seqno(dev);
|
|
- if (i915_seqno_passed(cur_seqno, seqno))
|
|
- break;
|
|
- if (last_seqno == cur_seqno) {
|
|
- if (stuck++ > 100) {
|
|
- DRM_ERROR("hardware wedged\n");
|
|
- atomic_set(&dev_priv->mm.wedged, 1);
|
|
- DRM_WAKEUP(&dev_priv->irq_queue);
|
|
- break;
|
|
- }
|
|
+ /* Under UMS, be paranoid and evict. */
|
|
+ if (!drm_core_check_feature(dev, DRIVER_MODESET)) {
|
|
+ ret = i915_gem_evict_from_inactive_list(dev);
|
|
+ if (ret) {
|
|
+ mutex_unlock(&dev->struct_mutex);
|
|
+ return ret;
|
|
}
|
|
- msleep(10);
|
|
- last_seqno = cur_seqno;
|
|
}
|
|
- dev_priv->mm.waiting_gem_seqno = 0;
|
|
-
|
|
- i915_gem_retire_requests(dev);
|
|
|
|
- spin_lock(&dev_priv->mm.active_list_lock);
|
|
- if (!atomic_read(&dev_priv->mm.wedged)) {
|
|
- /* Active and flushing should now be empty as we've
|
|
- * waited for a sequence higher than any pending execbuffer
|
|
- */
|
|
- WARN_ON(!list_empty(&dev_priv->mm.active_list));
|
|
- WARN_ON(!list_empty(&dev_priv->mm.flushing_list));
|
|
- /* Request should now be empty as we've also waited
|
|
- * for the last request in the list
|
|
- */
|
|
- WARN_ON(!list_empty(&dev_priv->mm.request_list));
|
|
- }
|
|
-
|
|
- /* Empty the active and flushing lists to inactive. If there's
|
|
- * anything left at this point, it means that we're wedged and
|
|
- * nothing good's going to happen by leaving them there. So strip
|
|
- * the GPU domains and just stuff them onto inactive.
|
|
+ /* Hack! Don't let anybody do execbuf while we don't control the chip.
|
|
+ * We need to replace this with a semaphore, or something.
|
|
+ * And not confound mm.suspended!
|
|
*/
|
|
- while (!list_empty(&dev_priv->mm.active_list)) {
|
|
- struct drm_gem_object *obj;
|
|
- uint32_t old_write_domain;
|
|
-
|
|
- obj = list_first_entry(&dev_priv->mm.active_list,
|
|
- struct drm_i915_gem_object,
|
|
- list)->obj;
|
|
- old_write_domain = obj->write_domain;
|
|
- obj->write_domain &= ~I915_GEM_GPU_DOMAINS;
|
|
- i915_gem_object_move_to_inactive(obj);
|
|
-
|
|
- trace_i915_gem_object_change_domain(obj,
|
|
- obj->read_domains,
|
|
- old_write_domain);
|
|
- }
|
|
- spin_unlock(&dev_priv->mm.active_list_lock);
|
|
-
|
|
- while (!list_empty(&dev_priv->mm.flushing_list)) {
|
|
- struct drm_gem_object *obj;
|
|
- uint32_t old_write_domain;
|
|
-
|
|
- obj = list_first_entry(&dev_priv->mm.flushing_list,
|
|
- struct drm_i915_gem_object,
|
|
- list)->obj;
|
|
- old_write_domain = obj->write_domain;
|
|
- obj->write_domain &= ~I915_GEM_GPU_DOMAINS;
|
|
- i915_gem_object_move_to_inactive(obj);
|
|
-
|
|
- trace_i915_gem_object_change_domain(obj,
|
|
- obj->read_domains,
|
|
- old_write_domain);
|
|
- }
|
|
-
|
|
-
|
|
- /* Move all inactive buffers out of the GTT. */
|
|
- ret = i915_gem_evict_from_inactive_list(dev);
|
|
- WARN_ON(!list_empty(&dev_priv->mm.inactive_list));
|
|
- if (ret) {
|
|
- mutex_unlock(&dev->struct_mutex);
|
|
- return ret;
|
|
- }
|
|
+ dev_priv->mm.suspended = 1;
|
|
+ del_timer(&dev_priv->hangcheck_timer);
|
|
|
|
+ i915_kernel_lost_context(dev);
|
|
i915_gem_cleanup_ringbuffer(dev);
|
|
+
|
|
mutex_unlock(&dev->struct_mutex);
|
|
|
|
+ /* Cancel the retire work handler, which should be idle now. */
|
|
+ cancel_delayed_work_sync(&dev_priv->mm.retire_work);
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
@@ -4585,7 +4570,7 @@ i915_gem_init_hws(struct drm_device *dev)
|
|
DRM_ERROR("Failed to allocate status page\n");
|
|
return -ENOMEM;
|
|
}
|
|
- obj_priv = obj->driver_private;
|
|
+ obj_priv = to_intel_bo(obj);
|
|
obj_priv->agp_type = AGP_USER_CACHED_MEMORY;
|
|
|
|
ret = i915_gem_object_pin(obj, 4096);
|
|
@@ -4606,8 +4591,13 @@ i915_gem_init_hws(struct drm_device *dev)
|
|
}
|
|
dev_priv->hws_obj = obj;
|
|
memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
|
|
- I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
|
|
- I915_READ(HWS_PGA); /* posting read */
|
|
+ if (IS_GEN6(dev)) {
|
|
+ I915_WRITE(HWS_PGA_GEN6, dev_priv->status_gfx_addr);
|
|
+ I915_READ(HWS_PGA_GEN6); /* posting read */
|
|
+ } else {
|
|
+ I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr);
|
|
+ I915_READ(HWS_PGA); /* posting read */
|
|
+ }
|
|
DRM_DEBUG_DRIVER("hws offset: 0x%08x\n", dev_priv->status_gfx_addr);
|
|
|
|
return 0;
|
|
@@ -4624,7 +4614,7 @@ i915_gem_cleanup_hws(struct drm_device *dev)
|
|
return;
|
|
|
|
obj = dev_priv->hws_obj;
|
|
- obj_priv = obj->driver_private;
|
|
+ obj_priv = to_intel_bo(obj);
|
|
|
|
kunmap(obj_priv->pages[0]);
|
|
i915_gem_object_unpin(obj);
|
|
@@ -4658,7 +4648,7 @@ i915_gem_init_ringbuffer(struct drm_device *dev)
|
|
i915_gem_cleanup_hws(dev);
|
|
return -ENOMEM;
|
|
}
|
|
- obj_priv = obj->driver_private;
|
|
+ obj_priv = to_intel_bo(obj);
|
|
|
|
ret = i915_gem_object_pin(obj, 4096);
|
|
if (ret != 0) {
|
|
@@ -4744,6 +4734,11 @@ i915_gem_init_ringbuffer(struct drm_device *dev)
|
|
ring->space += ring->Size;
|
|
}
|
|
|
|
+ if (IS_I9XX(dev) && !IS_GEN3(dev)) {
|
|
+ I915_WRITE(MI_MODE,
|
|
+ (VS_TIMER_DISPATCH) << 16 | VS_TIMER_DISPATCH);
|
|
+ }
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
@@ -4849,7 +4844,8 @@ i915_gem_load(struct drm_device *dev)
|
|
spin_unlock(&shrink_list_lock);
|
|
|
|
/* Old X drivers will take 0-2 for front, back, depth buffers */
|
|
- dev_priv->fence_reg_start = 3;
|
|
+ if (!drm_core_check_feature(dev, DRIVER_MODESET))
|
|
+ dev_priv->fence_reg_start = 3;
|
|
|
|
if (IS_I965G(dev) || IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
|
|
dev_priv->num_fence_regs = 16;
|
|
@@ -4945,7 +4941,7 @@ void i915_gem_detach_phys_object(struct drm_device *dev,
|
|
int ret;
|
|
int page_count;
|
|
|
|
- obj_priv = obj->driver_private;
|
|
+ obj_priv = to_intel_bo(obj);
|
|
if (!obj_priv->phys_obj)
|
|
return;
|
|
|
|
@@ -4984,7 +4980,7 @@ i915_gem_attach_phys_object(struct drm_device *dev,
|
|
if (id > I915_MAX_PHYS_OBJECT)
|
|
return -EINVAL;
|
|
|
|
- obj_priv = obj->driver_private;
|
|
+ obj_priv = to_intel_bo(obj);
|
|
|
|
if (obj_priv->phys_obj) {
|
|
if (obj_priv->phys_obj->id == id)
|
|
@@ -5035,7 +5031,7 @@ i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
|
|
struct drm_i915_gem_pwrite *args,
|
|
struct drm_file *file_priv)
|
|
{
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
void *obj_addr;
|
|
int ret;
|
|
char __user *user_data;
|
|
diff --git a/drivers/gpu/drm/i915/i915_gem_debug.c b/drivers/gpu/drm/i915/i915_gem_debug.c
|
|
--- a/drivers/gpu/drm/i915/i915_gem_debug.c
|
|
+++ b/drivers/gpu/drm/i915/i915_gem_debug.c
|
|
@@ -72,7 +72,7 @@ void
|
|
i915_gem_dump_object(struct drm_gem_object *obj, int len,
|
|
const char *where, uint32_t mark)
|
|
{
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
int page;
|
|
|
|
DRM_INFO("%s: object at offset %08x\n", where, obj_priv->gtt_offset);
|
|
@@ -137,7 +137,7 @@ void
|
|
i915_gem_object_check_coherency(struct drm_gem_object *obj, int handle)
|
|
{
|
|
struct drm_device *dev = obj->dev;
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
int page;
|
|
uint32_t *gtt_mapping;
|
|
uint32_t *backing_map = NULL;
|
|
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c
|
|
--- a/drivers/gpu/drm/i915/i915_gem_tiling.c
|
|
+++ b/drivers/gpu/drm/i915/i915_gem_tiling.c
|
|
@@ -25,8 +25,6 @@
|
|
*
|
|
*/
|
|
|
|
-#include <linux/acpi.h>
|
|
-#include <linux/pnp.h>
|
|
#include "linux/string.h"
|
|
#include "linux/bitops.h"
|
|
#include "drmP.h"
|
|
@@ -83,120 +81,6 @@
|
|
* to match what the GPU expects.
|
|
*/
|
|
|
|
-#define MCHBAR_I915 0x44
|
|
-#define MCHBAR_I965 0x48
|
|
-#define MCHBAR_SIZE (4*4096)
|
|
-
|
|
-#define DEVEN_REG 0x54
|
|
-#define DEVEN_MCHBAR_EN (1 << 28)
|
|
-
|
|
-/* Allocate space for the MCH regs if needed, return nonzero on error */
|
|
-static int
|
|
-intel_alloc_mchbar_resource(struct drm_device *dev)
|
|
-{
|
|
- drm_i915_private_t *dev_priv = dev->dev_private;
|
|
- int reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
|
|
- u32 temp_lo, temp_hi = 0;
|
|
- u64 mchbar_addr;
|
|
- int ret = 0;
|
|
-
|
|
- if (IS_I965G(dev))
|
|
- pci_read_config_dword(dev_priv->bridge_dev, reg + 4, &temp_hi);
|
|
- pci_read_config_dword(dev_priv->bridge_dev, reg, &temp_lo);
|
|
- mchbar_addr = ((u64)temp_hi << 32) | temp_lo;
|
|
-
|
|
- /* If ACPI doesn't have it, assume we need to allocate it ourselves */
|
|
-#ifdef CONFIG_PNP
|
|
- if (mchbar_addr &&
|
|
- pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) {
|
|
- ret = 0;
|
|
- goto out;
|
|
- }
|
|
-#endif
|
|
-
|
|
- /* Get some space for it */
|
|
- ret = pci_bus_alloc_resource(dev_priv->bridge_dev->bus, &dev_priv->mch_res,
|
|
- MCHBAR_SIZE, MCHBAR_SIZE,
|
|
- PCIBIOS_MIN_MEM,
|
|
- 0, pcibios_align_resource,
|
|
- dev_priv->bridge_dev);
|
|
- if (ret) {
|
|
- DRM_DEBUG_DRIVER("failed bus alloc: %d\n", ret);
|
|
- dev_priv->mch_res.start = 0;
|
|
- goto out;
|
|
- }
|
|
-
|
|
- if (IS_I965G(dev))
|
|
- pci_write_config_dword(dev_priv->bridge_dev, reg + 4,
|
|
- upper_32_bits(dev_priv->mch_res.start));
|
|
-
|
|
- pci_write_config_dword(dev_priv->bridge_dev, reg,
|
|
- lower_32_bits(dev_priv->mch_res.start));
|
|
-out:
|
|
- return ret;
|
|
-}
|
|
-
|
|
-/* Setup MCHBAR if possible, return true if we should disable it again */
|
|
-static bool
|
|
-intel_setup_mchbar(struct drm_device *dev)
|
|
-{
|
|
- drm_i915_private_t *dev_priv = dev->dev_private;
|
|
- int mchbar_reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
|
|
- u32 temp;
|
|
- bool need_disable = false, enabled;
|
|
-
|
|
- if (IS_I915G(dev) || IS_I915GM(dev)) {
|
|
- pci_read_config_dword(dev_priv->bridge_dev, DEVEN_REG, &temp);
|
|
- enabled = !!(temp & DEVEN_MCHBAR_EN);
|
|
- } else {
|
|
- pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
|
|
- enabled = temp & 1;
|
|
- }
|
|
-
|
|
- /* If it's already enabled, don't have to do anything */
|
|
- if (enabled)
|
|
- goto out;
|
|
-
|
|
- if (intel_alloc_mchbar_resource(dev))
|
|
- goto out;
|
|
-
|
|
- need_disable = true;
|
|
-
|
|
- /* Space is allocated or reserved, so enable it. */
|
|
- if (IS_I915G(dev) || IS_I915GM(dev)) {
|
|
- pci_write_config_dword(dev_priv->bridge_dev, DEVEN_REG,
|
|
- temp | DEVEN_MCHBAR_EN);
|
|
- } else {
|
|
- pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
|
|
- pci_write_config_dword(dev_priv->bridge_dev, mchbar_reg, temp | 1);
|
|
- }
|
|
-out:
|
|
- return need_disable;
|
|
-}
|
|
-
|
|
-static void
|
|
-intel_teardown_mchbar(struct drm_device *dev, bool disable)
|
|
-{
|
|
- drm_i915_private_t *dev_priv = dev->dev_private;
|
|
- int mchbar_reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915;
|
|
- u32 temp;
|
|
-
|
|
- if (disable) {
|
|
- if (IS_I915G(dev) || IS_I915GM(dev)) {
|
|
- pci_read_config_dword(dev_priv->bridge_dev, DEVEN_REG, &temp);
|
|
- temp &= ~DEVEN_MCHBAR_EN;
|
|
- pci_write_config_dword(dev_priv->bridge_dev, DEVEN_REG, temp);
|
|
- } else {
|
|
- pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
|
|
- temp &= ~1;
|
|
- pci_write_config_dword(dev_priv->bridge_dev, mchbar_reg, temp);
|
|
- }
|
|
- }
|
|
-
|
|
- if (dev_priv->mch_res.start)
|
|
- release_resource(&dev_priv->mch_res);
|
|
-}
|
|
-
|
|
/**
|
|
* Detects bit 6 swizzling of address lookup between IGD access and CPU
|
|
* access through main memory.
|
|
@@ -207,9 +91,8 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
|
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
|
uint32_t swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
|
|
uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
|
|
- bool need_disable;
|
|
|
|
- if (IS_IRONLAKE(dev)) {
|
|
+ if (IS_IRONLAKE(dev) || IS_GEN6(dev)) {
|
|
/* On Ironlake whatever DRAM config, GPU always do
|
|
* same swizzling setup.
|
|
*/
|
|
@@ -224,9 +107,6 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
|
|
} else if (IS_MOBILE(dev)) {
|
|
uint32_t dcc;
|
|
|
|
- /* Try to make sure MCHBAR is enabled before poking at it */
|
|
- need_disable = intel_setup_mchbar(dev);
|
|
-
|
|
/* On mobile 9xx chipsets, channel interleave by the CPU is
|
|
* determined by DCC. For single-channel, neither the CPU
|
|
* nor the GPU do swizzling. For dual channel interleaved,
|
|
@@ -266,8 +146,6 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
|
|
swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
|
|
swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
|
|
}
|
|
-
|
|
- intel_teardown_mchbar(dev, need_disable);
|
|
} else {
|
|
/* The 965, G33, and newer, have a very flexible memory
|
|
* configuration. It will enable dual-channel mode
|
|
@@ -302,39 +180,6 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
|
|
dev_priv->mm.bit_6_swizzle_y = swizzle_y;
|
|
}
|
|
|
|
-
|
|
-/**
|
|
- * Returns whether an object is currently fenceable. If not, it may need
|
|
- * to be unbound and have its pitch adjusted.
|
|
- */
|
|
-bool
|
|
-i915_obj_fenceable(struct drm_device *dev, struct drm_gem_object *obj)
|
|
-{
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
-
|
|
- if (IS_I965G(dev)) {
|
|
- /* The 965 can have fences at any page boundary. */
|
|
- if (obj->size & 4095)
|
|
- return false;
|
|
- return true;
|
|
- } else if (IS_I9XX(dev)) {
|
|
- if (obj_priv->gtt_offset & ~I915_FENCE_START_MASK)
|
|
- return false;
|
|
- } else {
|
|
- if (obj_priv->gtt_offset & ~I830_FENCE_START_MASK)
|
|
- return false;
|
|
- }
|
|
-
|
|
- /* Power of two sized... */
|
|
- if (obj->size & (obj->size - 1))
|
|
- return false;
|
|
-
|
|
- /* Objects must be size aligned as well */
|
|
- if (obj_priv->gtt_offset & (obj->size - 1))
|
|
- return false;
|
|
- return true;
|
|
-}
|
|
-
|
|
/* Check pitch constriants for all chips & tiling formats */
|
|
bool
|
|
i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
|
|
@@ -357,21 +202,17 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
|
|
* reg, so dont bother to check the size */
|
|
if (stride / 128 > I965_FENCE_MAX_PITCH_VAL)
|
|
return false;
|
|
- } else if (IS_I9XX(dev)) {
|
|
- uint32_t pitch_val = ffs(stride / tile_width) - 1;
|
|
-
|
|
- /* XXX: For Y tiling, FENCE_MAX_PITCH_VAL is actually 6 (8KB)
|
|
- * instead of 4 (2KB) on 945s.
|
|
- */
|
|
- if (pitch_val > I915_FENCE_MAX_PITCH_VAL ||
|
|
- size > (I830_FENCE_MAX_SIZE_VAL << 20))
|
|
+ } else if (IS_GEN3(dev) || IS_GEN2(dev)) {
|
|
+ if (stride > 8192)
|
|
return false;
|
|
- } else {
|
|
- uint32_t pitch_val = ffs(stride / tile_width) - 1;
|
|
|
|
- if (pitch_val > I830_FENCE_MAX_PITCH_VAL ||
|
|
- size > (I830_FENCE_MAX_SIZE_VAL << 19))
|
|
- return false;
|
|
+ if (IS_GEN3(dev)) {
|
|
+ if (size > I830_FENCE_MAX_SIZE_VAL << 20)
|
|
+ return false;
|
|
+ } else {
|
|
+ if (size > I830_FENCE_MAX_SIZE_VAL << 19)
|
|
+ return false;
|
|
+ }
|
|
}
|
|
|
|
/* 965+ just needs multiples of tile width */
|
|
@@ -391,11 +232,11 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
|
|
return true;
|
|
}
|
|
|
|
-static bool
|
|
+bool
|
|
i915_gem_object_fence_offset_ok(struct drm_gem_object *obj, int tiling_mode)
|
|
{
|
|
struct drm_device *dev = obj->dev;
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
|
|
if (obj_priv->gtt_space == NULL)
|
|
return true;
|
|
@@ -435,7 +276,7 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
|
|
obj = drm_gem_object_lookup(dev, file_priv, args->handle);
|
|
if (obj == NULL)
|
|
return -EINVAL;
|
|
- obj_priv = obj->driver_private;
|
|
+ obj_priv = to_intel_bo(obj);
|
|
|
|
if (!i915_tiling_ok(dev, args->stride, obj->size, args->tiling_mode)) {
|
|
drm_gem_object_unreference_unlocked(obj);
|
|
@@ -480,9 +321,12 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
|
|
* need to ensure that any fence register is cleared.
|
|
*/
|
|
if (!i915_gem_object_fence_offset_ok(obj, args->tiling_mode))
|
|
- ret = i915_gem_object_unbind(obj);
|
|
+ ret = i915_gem_object_unbind(obj);
|
|
+ else if (obj_priv->fence_reg != I915_FENCE_REG_NONE)
|
|
+ ret = i915_gem_object_put_fence_reg(obj);
|
|
else
|
|
- ret = i915_gem_object_put_fence_reg(obj);
|
|
+ i915_gem_release_mmap(obj);
|
|
+
|
|
if (ret != 0) {
|
|
WARN(ret != -ERESTARTSYS,
|
|
"failed to reset object for tiling switch");
|
|
@@ -491,12 +335,6 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
|
|
goto err;
|
|
}
|
|
|
|
- /* If we've changed tiling, GTT-mappings of the object
|
|
- * need to re-fault to ensure that the correct fence register
|
|
- * setup is in place.
|
|
- */
|
|
- i915_gem_release_mmap(obj);
|
|
-
|
|
obj_priv->tiling_mode = args->tiling_mode;
|
|
obj_priv->stride = args->stride;
|
|
}
|
|
@@ -522,7 +360,7 @@ i915_gem_get_tiling(struct drm_device *dev, void *data,
|
|
obj = drm_gem_object_lookup(dev, file_priv, args->handle);
|
|
if (obj == NULL)
|
|
return -EINVAL;
|
|
- obj_priv = obj->driver_private;
|
|
+ obj_priv = to_intel_bo(obj);
|
|
|
|
mutex_lock(&dev->struct_mutex);
|
|
|
|
@@ -585,7 +423,7 @@ i915_gem_object_do_bit_17_swizzle(struct drm_gem_object *obj)
|
|
{
|
|
struct drm_device *dev = obj->dev;
|
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
int page_count = obj->size >> PAGE_SHIFT;
|
|
int i;
|
|
|
|
@@ -614,7 +452,7 @@ i915_gem_object_save_bit_17_swizzle(struct drm_gem_object *obj)
|
|
{
|
|
struct drm_device *dev = obj->dev;
|
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
int page_count = obj->size >> PAGE_SHIFT;
|
|
int i;
|
|
|
|
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
|
|
--- a/drivers/gpu/drm/i915/i915_irq.c
|
|
+++ b/drivers/gpu/drm/i915/i915_irq.c
|
|
@@ -166,11 +166,15 @@ void intel_enable_asle (struct drm_device *dev)
|
|
{
|
|
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
|
|
|
- if (IS_IRONLAKE(dev))
|
|
+ if (HAS_PCH_SPLIT(dev))
|
|
ironlake_enable_display_irq(dev_priv, DE_GSE);
|
|
- else
|
|
+ else {
|
|
i915_enable_pipestat(dev_priv, 1,
|
|
I915_LEGACY_BLC_EVENT_ENABLE);
|
|
+ if (IS_I965G(dev))
|
|
+ i915_enable_pipestat(dev_priv, 0,
|
|
+ I915_LEGACY_BLC_EVENT_ENABLE);
|
|
+ }
|
|
}
|
|
|
|
/**
|
|
@@ -255,20 +259,71 @@ static void i915_hotplug_work_func(struct work_struct *work)
|
|
hotplug_work);
|
|
struct drm_device *dev = dev_priv->dev;
|
|
struct drm_mode_config *mode_config = &dev->mode_config;
|
|
- struct drm_connector *connector;
|
|
+ struct drm_encoder *encoder;
|
|
|
|
- if (mode_config->num_connector) {
|
|
- list_for_each_entry(connector, &mode_config->connector_list, head) {
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
+ if (mode_config->num_encoder) {
|
|
+ list_for_each_entry(encoder, &mode_config->encoder_list, head) {
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
|
|
- if (intel_output->hot_plug)
|
|
- (*intel_output->hot_plug) (intel_output);
|
|
+ if (intel_encoder->hot_plug)
|
|
+ (*intel_encoder->hot_plug) (intel_encoder);
|
|
}
|
|
}
|
|
/* Just fire off a uevent and let userspace tell us what to do */
|
|
drm_sysfs_hotplug_event(dev);
|
|
}
|
|
|
|
+static void i915_handle_rps_change(struct drm_device *dev)
|
|
+{
|
|
+ drm_i915_private_t *dev_priv = dev->dev_private;
|
|
+ u32 busy_up, busy_down, max_avg, min_avg;
|
|
+ u16 rgvswctl;
|
|
+ u8 new_delay = dev_priv->cur_delay;
|
|
+
|
|
+ I915_WRITE(MEMINTRSTS, I915_READ(MEMINTRSTS) & ~MEMINT_EVAL_CHG);
|
|
+ busy_up = I915_READ(RCPREVBSYTUPAVG);
|
|
+ busy_down = I915_READ(RCPREVBSYTDNAVG);
|
|
+ max_avg = I915_READ(RCBMAXAVG);
|
|
+ min_avg = I915_READ(RCBMINAVG);
|
|
+
|
|
+ /* Handle RCS change request from hw */
|
|
+ if (busy_up > max_avg) {
|
|
+ if (dev_priv->cur_delay != dev_priv->max_delay)
|
|
+ new_delay = dev_priv->cur_delay - 1;
|
|
+ if (new_delay < dev_priv->max_delay)
|
|
+ new_delay = dev_priv->max_delay;
|
|
+ } else if (busy_down < min_avg) {
|
|
+ if (dev_priv->cur_delay != dev_priv->min_delay)
|
|
+ new_delay = dev_priv->cur_delay + 1;
|
|
+ if (new_delay > dev_priv->min_delay)
|
|
+ new_delay = dev_priv->min_delay;
|
|
+ }
|
|
+
|
|
+ DRM_DEBUG("rps change requested: %d -> %d\n",
|
|
+ dev_priv->cur_delay, new_delay);
|
|
+
|
|
+ rgvswctl = I915_READ(MEMSWCTL);
|
|
+ if (rgvswctl & MEMCTL_CMD_STS) {
|
|
+ DRM_ERROR("gpu busy, RCS change rejected\n");
|
|
+ return; /* still busy with another command */
|
|
+ }
|
|
+
|
|
+ /* Program the new state */
|
|
+ rgvswctl = (MEMCTL_CMD_CHFREQ << MEMCTL_CMD_SHIFT) |
|
|
+ (new_delay << MEMCTL_FREQ_SHIFT) | MEMCTL_SFCAVM;
|
|
+ I915_WRITE(MEMSWCTL, rgvswctl);
|
|
+ POSTING_READ(MEMSWCTL);
|
|
+
|
|
+ rgvswctl |= MEMCTL_CMD_STS;
|
|
+ I915_WRITE(MEMSWCTL, rgvswctl);
|
|
+
|
|
+ dev_priv->cur_delay = new_delay;
|
|
+
|
|
+ DRM_DEBUG("rps changed\n");
|
|
+
|
|
+ return;
|
|
+}
|
|
+
|
|
irqreturn_t ironlake_irq_handler(struct drm_device *dev)
|
|
{
|
|
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
|
@@ -331,6 +386,11 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev)
|
|
queue_work(dev_priv->wq, &dev_priv->hotplug_work);
|
|
}
|
|
|
|
+ if (de_iir & DE_PCU_EVENT) {
|
|
+ I915_WRITE(MEMINTRSTS, I915_READ(MEMINTRSTS));
|
|
+ i915_handle_rps_change(dev);
|
|
+ }
|
|
+
|
|
/* should clear PCH hotplug event before clear CPU irq */
|
|
I915_WRITE(SDEIIR, pch_iir);
|
|
I915_WRITE(GTIIR, gt_iir);
|
|
@@ -376,6 +436,121 @@ static void i915_error_work_func(struct work_struct *work)
|
|
}
|
|
}
|
|
|
|
+static struct drm_i915_error_object *
|
|
+i915_error_object_create(struct drm_device *dev,
|
|
+ struct drm_gem_object *src)
|
|
+{
|
|
+ struct drm_i915_error_object *dst;
|
|
+ struct drm_i915_gem_object *src_priv;
|
|
+ int page, page_count;
|
|
+
|
|
+ if (src == NULL)
|
|
+ return NULL;
|
|
+
|
|
+ src_priv = to_intel_bo(src);
|
|
+ if (src_priv->pages == NULL)
|
|
+ return NULL;
|
|
+
|
|
+ page_count = src->size / PAGE_SIZE;
|
|
+
|
|
+ dst = kmalloc(sizeof(*dst) + page_count * sizeof (u32 *), GFP_ATOMIC);
|
|
+ if (dst == NULL)
|
|
+ return NULL;
|
|
+
|
|
+ for (page = 0; page < page_count; page++) {
|
|
+ void *s, *d = kmalloc(PAGE_SIZE, GFP_ATOMIC);
|
|
+ if (d == NULL)
|
|
+ goto unwind;
|
|
+ s = kmap_atomic(src_priv->pages[page], KM_USER0);
|
|
+ memcpy(d, s, PAGE_SIZE);
|
|
+ kunmap_atomic(s, KM_USER0);
|
|
+ dst->pages[page] = d;
|
|
+ }
|
|
+ dst->page_count = page_count;
|
|
+ dst->gtt_offset = src_priv->gtt_offset;
|
|
+
|
|
+ return dst;
|
|
+
|
|
+unwind:
|
|
+ while (page--)
|
|
+ kfree(dst->pages[page]);
|
|
+ kfree(dst);
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+static void
|
|
+i915_error_object_free(struct drm_i915_error_object *obj)
|
|
+{
|
|
+ int page;
|
|
+
|
|
+ if (obj == NULL)
|
|
+ return;
|
|
+
|
|
+ for (page = 0; page < obj->page_count; page++)
|
|
+ kfree(obj->pages[page]);
|
|
+
|
|
+ kfree(obj);
|
|
+}
|
|
+
|
|
+static void
|
|
+i915_error_state_free(struct drm_device *dev,
|
|
+ struct drm_i915_error_state *error)
|
|
+{
|
|
+ i915_error_object_free(error->batchbuffer[0]);
|
|
+ i915_error_object_free(error->batchbuffer[1]);
|
|
+ i915_error_object_free(error->ringbuffer);
|
|
+ kfree(error->active_bo);
|
|
+ kfree(error);
|
|
+}
|
|
+
|
|
+static u32
|
|
+i915_get_bbaddr(struct drm_device *dev, u32 *ring)
|
|
+{
|
|
+ u32 cmd;
|
|
+
|
|
+ if (IS_I830(dev) || IS_845G(dev))
|
|
+ cmd = MI_BATCH_BUFFER;
|
|
+ else if (IS_I965G(dev))
|
|
+ cmd = (MI_BATCH_BUFFER_START | (2 << 6) |
|
|
+ MI_BATCH_NON_SECURE_I965);
|
|
+ else
|
|
+ cmd = (MI_BATCH_BUFFER_START | (2 << 6));
|
|
+
|
|
+ return ring[0] == cmd ? ring[1] : 0;
|
|
+}
|
|
+
|
|
+static u32
|
|
+i915_ringbuffer_last_batch(struct drm_device *dev)
|
|
+{
|
|
+ struct drm_i915_private *dev_priv = dev->dev_private;
|
|
+ u32 head, bbaddr;
|
|
+ u32 *ring;
|
|
+
|
|
+ /* Locate the current position in the ringbuffer and walk back
|
|
+ * to find the most recently dispatched batch buffer.
|
|
+ */
|
|
+ bbaddr = 0;
|
|
+ head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
|
|
+ ring = (u32 *)(dev_priv->ring.virtual_start + head);
|
|
+
|
|
+ while (--ring >= (u32 *)dev_priv->ring.virtual_start) {
|
|
+ bbaddr = i915_get_bbaddr(dev, ring);
|
|
+ if (bbaddr)
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (bbaddr == 0) {
|
|
+ ring = (u32 *)(dev_priv->ring.virtual_start + dev_priv->ring.Size);
|
|
+ while (--ring >= (u32 *)dev_priv->ring.virtual_start) {
|
|
+ bbaddr = i915_get_bbaddr(dev, ring);
|
|
+ if (bbaddr)
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return bbaddr;
|
|
+}
|
|
+
|
|
/**
|
|
* i915_capture_error_state - capture an error record for later analysis
|
|
* @dev: drm device
|
|
@@ -388,19 +563,26 @@ static void i915_error_work_func(struct work_struct *work)
|
|
static void i915_capture_error_state(struct drm_device *dev)
|
|
{
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
+ struct drm_i915_gem_object *obj_priv;
|
|
struct drm_i915_error_state *error;
|
|
+ struct drm_gem_object *batchbuffer[2];
|
|
unsigned long flags;
|
|
+ u32 bbaddr;
|
|
+ int count;
|
|
|
|
spin_lock_irqsave(&dev_priv->error_lock, flags);
|
|
- if (dev_priv->first_error)
|
|
- goto out;
|
|
+ error = dev_priv->first_error;
|
|
+ spin_unlock_irqrestore(&dev_priv->error_lock, flags);
|
|
+ if (error)
|
|
+ return;
|
|
|
|
error = kmalloc(sizeof(*error), GFP_ATOMIC);
|
|
if (!error) {
|
|
- DRM_DEBUG_DRIVER("out ot memory, not capturing error state\n");
|
|
- goto out;
|
|
+ DRM_DEBUG_DRIVER("out of memory, not capturing error state\n");
|
|
+ return;
|
|
}
|
|
|
|
+ error->seqno = i915_get_gem_seqno(dev);
|
|
error->eir = I915_READ(EIR);
|
|
error->pgtbl_er = I915_READ(PGTBL_ER);
|
|
error->pipeastat = I915_READ(PIPEASTAT);
|
|
@@ -411,6 +593,7 @@ static void i915_capture_error_state(struct drm_device *dev)
|
|
error->ipehr = I915_READ(IPEHR);
|
|
error->instdone = I915_READ(INSTDONE);
|
|
error->acthd = I915_READ(ACTHD);
|
|
+ error->bbaddr = 0;
|
|
} else {
|
|
error->ipeir = I915_READ(IPEIR_I965);
|
|
error->ipehr = I915_READ(IPEHR_I965);
|
|
@@ -418,14 +601,101 @@ static void i915_capture_error_state(struct drm_device *dev)
|
|
error->instps = I915_READ(INSTPS);
|
|
error->instdone1 = I915_READ(INSTDONE1);
|
|
error->acthd = I915_READ(ACTHD_I965);
|
|
+ error->bbaddr = I915_READ64(BB_ADDR);
|
|
}
|
|
|
|
- do_gettimeofday(&error->time);
|
|
+ bbaddr = i915_ringbuffer_last_batch(dev);
|
|
|
|
- dev_priv->first_error = error;
|
|
+ /* Grab the current batchbuffer, most likely to have crashed. */
|
|
+ batchbuffer[0] = NULL;
|
|
+ batchbuffer[1] = NULL;
|
|
+ count = 0;
|
|
+ list_for_each_entry(obj_priv, &dev_priv->mm.active_list, list) {
|
|
+ struct drm_gem_object *obj = obj_priv->obj;
|
|
|
|
-out:
|
|
+ if (batchbuffer[0] == NULL &&
|
|
+ bbaddr >= obj_priv->gtt_offset &&
|
|
+ bbaddr < obj_priv->gtt_offset + obj->size)
|
|
+ batchbuffer[0] = obj;
|
|
+
|
|
+ if (batchbuffer[1] == NULL &&
|
|
+ error->acthd >= obj_priv->gtt_offset &&
|
|
+ error->acthd < obj_priv->gtt_offset + obj->size &&
|
|
+ batchbuffer[0] != obj)
|
|
+ batchbuffer[1] = obj;
|
|
+
|
|
+ count++;
|
|
+ }
|
|
+
|
|
+ /* We need to copy these to an anonymous buffer as the simplest
|
|
+ * method to avoid being overwritten by userpace.
|
|
+ */
|
|
+ error->batchbuffer[0] = i915_error_object_create(dev, batchbuffer[0]);
|
|
+ error->batchbuffer[1] = i915_error_object_create(dev, batchbuffer[1]);
|
|
+
|
|
+ /* Record the ringbuffer */
|
|
+ error->ringbuffer = i915_error_object_create(dev, dev_priv->ring.ring_obj);
|
|
+
|
|
+ /* Record buffers on the active list. */
|
|
+ error->active_bo = NULL;
|
|
+ error->active_bo_count = 0;
|
|
+
|
|
+ if (count)
|
|
+ error->active_bo = kmalloc(sizeof(*error->active_bo)*count,
|
|
+ GFP_ATOMIC);
|
|
+
|
|
+ if (error->active_bo) {
|
|
+ int i = 0;
|
|
+ list_for_each_entry(obj_priv, &dev_priv->mm.active_list, list) {
|
|
+ struct drm_gem_object *obj = obj_priv->obj;
|
|
+
|
|
+ error->active_bo[i].size = obj->size;
|
|
+ error->active_bo[i].name = obj->name;
|
|
+ error->active_bo[i].seqno = obj_priv->last_rendering_seqno;
|
|
+ error->active_bo[i].gtt_offset = obj_priv->gtt_offset;
|
|
+ error->active_bo[i].read_domains = obj->read_domains;
|
|
+ error->active_bo[i].write_domain = obj->write_domain;
|
|
+ error->active_bo[i].fence_reg = obj_priv->fence_reg;
|
|
+ error->active_bo[i].pinned = 0;
|
|
+ if (obj_priv->pin_count > 0)
|
|
+ error->active_bo[i].pinned = 1;
|
|
+ if (obj_priv->user_pin_count > 0)
|
|
+ error->active_bo[i].pinned = -1;
|
|
+ error->active_bo[i].tiling = obj_priv->tiling_mode;
|
|
+ error->active_bo[i].dirty = obj_priv->dirty;
|
|
+ error->active_bo[i].purgeable = obj_priv->madv != I915_MADV_WILLNEED;
|
|
+
|
|
+ if (++i == count)
|
|
+ break;
|
|
+ }
|
|
+ error->active_bo_count = i;
|
|
+ }
|
|
+
|
|
+ do_gettimeofday(&error->time);
|
|
+
|
|
+ spin_lock_irqsave(&dev_priv->error_lock, flags);
|
|
+ if (dev_priv->first_error == NULL) {
|
|
+ dev_priv->first_error = error;
|
|
+ error = NULL;
|
|
+ }
|
|
spin_unlock_irqrestore(&dev_priv->error_lock, flags);
|
|
+
|
|
+ if (error)
|
|
+ i915_error_state_free(dev, error);
|
|
+}
|
|
+
|
|
+void i915_destroy_error_state(struct drm_device *dev)
|
|
+{
|
|
+ struct drm_i915_private *dev_priv = dev->dev_private;
|
|
+ struct drm_i915_error_state *error;
|
|
+
|
|
+ spin_lock(&dev_priv->error_lock);
|
|
+ error = dev_priv->first_error;
|
|
+ dev_priv->first_error = NULL;
|
|
+ spin_unlock(&dev_priv->error_lock);
|
|
+
|
|
+ if (error)
|
|
+ i915_error_state_free(dev, error);
|
|
}
|
|
|
|
/**
|
|
@@ -576,7 +846,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
|
|
|
|
atomic_inc(&dev_priv->irq_received);
|
|
|
|
- if (IS_IRONLAKE(dev))
|
|
+ if (HAS_PCH_SPLIT(dev))
|
|
return ironlake_irq_handler(dev);
|
|
|
|
iir = I915_READ(IIR);
|
|
@@ -679,7 +949,8 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
|
|
intel_finish_page_flip(dev, 1);
|
|
}
|
|
|
|
- if ((pipeb_stats & I915_LEGACY_BLC_EVENT_STATUS) ||
|
|
+ if ((pipea_stats & I915_LEGACY_BLC_EVENT_STATUS) ||
|
|
+ (pipeb_stats & I915_LEGACY_BLC_EVENT_STATUS) ||
|
|
(iir & I915_ASLE_INTERRUPT))
|
|
opregion_asle_intr(dev);
|
|
|
|
@@ -737,7 +1008,7 @@ void i915_user_irq_get(struct drm_device *dev)
|
|
|
|
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
|
|
if (dev->irq_enabled && (++dev_priv->user_irq_refcount == 1)) {
|
|
- if (IS_IRONLAKE(dev))
|
|
+ if (HAS_PCH_SPLIT(dev))
|
|
ironlake_enable_graphics_irq(dev_priv, GT_USER_INTERRUPT);
|
|
else
|
|
i915_enable_irq(dev_priv, I915_USER_INTERRUPT);
|
|
@@ -753,7 +1024,7 @@ void i915_user_irq_put(struct drm_device *dev)
|
|
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
|
|
BUG_ON(dev->irq_enabled && dev_priv->user_irq_refcount <= 0);
|
|
if (dev->irq_enabled && (--dev_priv->user_irq_refcount == 0)) {
|
|
- if (IS_IRONLAKE(dev))
|
|
+ if (HAS_PCH_SPLIT(dev))
|
|
ironlake_disable_graphics_irq(dev_priv, GT_USER_INTERRUPT);
|
|
else
|
|
i915_disable_irq(dev_priv, I915_USER_INTERRUPT);
|
|
@@ -861,7 +1132,7 @@ int i915_enable_vblank(struct drm_device *dev, int pipe)
|
|
return -EINVAL;
|
|
|
|
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
|
|
- if (IS_IRONLAKE(dev))
|
|
+ if (HAS_PCH_SPLIT(dev))
|
|
ironlake_enable_display_irq(dev_priv, (pipe == 0) ?
|
|
DE_PIPEA_VBLANK: DE_PIPEB_VBLANK);
|
|
else if (IS_I965G(dev))
|
|
@@ -883,7 +1154,7 @@ void i915_disable_vblank(struct drm_device *dev, int pipe)
|
|
unsigned long irqflags;
|
|
|
|
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
|
|
- if (IS_IRONLAKE(dev))
|
|
+ if (HAS_PCH_SPLIT(dev))
|
|
ironlake_disable_display_irq(dev_priv, (pipe == 0) ?
|
|
DE_PIPEA_VBLANK: DE_PIPEB_VBLANK);
|
|
else
|
|
@@ -897,7 +1168,7 @@ void i915_enable_interrupt (struct drm_device *dev)
|
|
{
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
- if (!IS_IRONLAKE(dev))
|
|
+ if (!HAS_PCH_SPLIT(dev))
|
|
opregion_enable_asle(dev);
|
|
dev_priv->irq_enabled = 1;
|
|
}
|
|
@@ -973,7 +1244,11 @@ void i915_hangcheck_elapsed(unsigned long data)
|
|
struct drm_device *dev = (struct drm_device *)data;
|
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
|
uint32_t acthd;
|
|
-
|
|
+
|
|
+ /* No reset support on this chip yet. */
|
|
+ if (IS_GEN6(dev))
|
|
+ return;
|
|
+
|
|
if (!IS_I965G(dev))
|
|
acthd = I915_READ(ACTHD);
|
|
else
|
|
@@ -1064,6 +1339,13 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
|
|
I915_WRITE(SDEIER, dev_priv->pch_irq_enable_reg);
|
|
(void) I915_READ(SDEIER);
|
|
|
|
+ if (IS_IRONLAKE_M(dev)) {
|
|
+ /* Clear & enable PCU event interrupts */
|
|
+ I915_WRITE(DEIIR, DE_PCU_EVENT);
|
|
+ I915_WRITE(DEIER, I915_READ(DEIER) | DE_PCU_EVENT);
|
|
+ ironlake_enable_display_irq(dev_priv, DE_PCU_EVENT);
|
|
+ }
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
@@ -1076,7 +1358,7 @@ void i915_driver_irq_preinstall(struct drm_device * dev)
|
|
INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func);
|
|
INIT_WORK(&dev_priv->error_work, i915_error_work_func);
|
|
|
|
- if (IS_IRONLAKE(dev)) {
|
|
+ if (HAS_PCH_SPLIT(dev)) {
|
|
ironlake_irq_preinstall(dev);
|
|
return;
|
|
}
|
|
@@ -1108,7 +1390,7 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
|
|
|
|
dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
|
|
|
|
- if (IS_IRONLAKE(dev))
|
|
+ if (HAS_PCH_SPLIT(dev))
|
|
return ironlake_irq_postinstall(dev);
|
|
|
|
/* Unmask the interrupts that we always want on. */
|
|
@@ -1196,7 +1478,7 @@ void i915_driver_irq_uninstall(struct drm_device * dev)
|
|
|
|
dev_priv->vblank_pipe = 0;
|
|
|
|
- if (IS_IRONLAKE(dev)) {
|
|
+ if (HAS_PCH_SPLIT(dev)) {
|
|
ironlake_irq_uninstall(dev);
|
|
return;
|
|
}
|
|
diff --git a/drivers/gpu/drm/i915/i915_opregion.c b/drivers/gpu/drm/i915/i915_opregion.c
|
|
--- a/drivers/gpu/drm/i915/i915_opregion.c
|
|
+++ b/drivers/gpu/drm/i915/i915_opregion.c
|
|
@@ -382,8 +382,57 @@ static void intel_didl_outputs(struct drm_device *dev)
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
struct intel_opregion *opregion = &dev_priv->opregion;
|
|
struct drm_connector *connector;
|
|
+ acpi_handle handle;
|
|
+ struct acpi_device *acpi_dev, *acpi_cdev, *acpi_video_bus = NULL;
|
|
+ unsigned long long device_id;
|
|
+ acpi_status status;
|
|
int i = 0;
|
|
|
|
+ handle = DEVICE_ACPI_HANDLE(&dev->pdev->dev);
|
|
+ if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &acpi_dev)))
|
|
+ return;
|
|
+
|
|
+ if (acpi_is_video_device(acpi_dev))
|
|
+ acpi_video_bus = acpi_dev;
|
|
+ else {
|
|
+ list_for_each_entry(acpi_cdev, &acpi_dev->children, node) {
|
|
+ if (acpi_is_video_device(acpi_cdev)) {
|
|
+ acpi_video_bus = acpi_cdev;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (!acpi_video_bus) {
|
|
+ printk(KERN_WARNING "No ACPI video bus found\n");
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ list_for_each_entry(acpi_cdev, &acpi_video_bus->children, node) {
|
|
+ if (i >= 8) {
|
|
+ dev_printk (KERN_ERR, &dev->pdev->dev,
|
|
+ "More than 8 outputs detected\n");
|
|
+ return;
|
|
+ }
|
|
+ status =
|
|
+ acpi_evaluate_integer(acpi_cdev->handle, "_ADR",
|
|
+ NULL, &device_id);
|
|
+ if (ACPI_SUCCESS(status)) {
|
|
+ if (!device_id)
|
|
+ goto blind_set;
|
|
+ opregion->acpi->didl[i] = (u32)(device_id & 0x0f0f);
|
|
+ i++;
|
|
+ }
|
|
+ }
|
|
+
|
|
+end:
|
|
+ /* If fewer than 8 outputs, the list must be null terminated */
|
|
+ if (i < 8)
|
|
+ opregion->acpi->didl[i] = 0;
|
|
+ return;
|
|
+
|
|
+blind_set:
|
|
+ i = 0;
|
|
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
|
int output_type = ACPI_OTHER_OUTPUT;
|
|
if (i >= 8) {
|
|
@@ -416,10 +465,7 @@ static void intel_didl_outputs(struct drm_device *dev)
|
|
opregion->acpi->didl[i] |= (1<<31) | output_type | i;
|
|
i++;
|
|
}
|
|
-
|
|
- /* If fewer than 8 outputs, the list must be null terminated */
|
|
- if (i < 8)
|
|
- opregion->acpi->didl[i] = 0;
|
|
+ goto end;
|
|
}
|
|
|
|
int intel_opregion_init(struct drm_device *dev, int resume)
|
|
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
|
|
--- a/drivers/gpu/drm/i915/i915_reg.h
|
|
+++ b/drivers/gpu/drm/i915/i915_reg.h
|
|
@@ -53,6 +53,25 @@
|
|
#define INTEL_GMCH_GMS_STOLEN_224M (0xc << 4)
|
|
#define INTEL_GMCH_GMS_STOLEN_352M (0xd << 4)
|
|
|
|
+#define SNB_GMCH_CTRL 0x50
|
|
+#define SNB_GMCH_GMS_STOLEN_MASK 0xF8
|
|
+#define SNB_GMCH_GMS_STOLEN_32M (1 << 3)
|
|
+#define SNB_GMCH_GMS_STOLEN_64M (2 << 3)
|
|
+#define SNB_GMCH_GMS_STOLEN_96M (3 << 3)
|
|
+#define SNB_GMCH_GMS_STOLEN_128M (4 << 3)
|
|
+#define SNB_GMCH_GMS_STOLEN_160M (5 << 3)
|
|
+#define SNB_GMCH_GMS_STOLEN_192M (6 << 3)
|
|
+#define SNB_GMCH_GMS_STOLEN_224M (7 << 3)
|
|
+#define SNB_GMCH_GMS_STOLEN_256M (8 << 3)
|
|
+#define SNB_GMCH_GMS_STOLEN_288M (9 << 3)
|
|
+#define SNB_GMCH_GMS_STOLEN_320M (0xa << 3)
|
|
+#define SNB_GMCH_GMS_STOLEN_352M (0xb << 3)
|
|
+#define SNB_GMCH_GMS_STOLEN_384M (0xc << 3)
|
|
+#define SNB_GMCH_GMS_STOLEN_416M (0xd << 3)
|
|
+#define SNB_GMCH_GMS_STOLEN_448M (0xe << 3)
|
|
+#define SNB_GMCH_GMS_STOLEN_480M (0xf << 3)
|
|
+#define SNB_GMCH_GMS_STOLEN_512M (0x10 << 3)
|
|
+
|
|
/* PCI config space */
|
|
|
|
#define HPLLCC 0xc0 /* 855 only */
|
|
@@ -61,6 +80,7 @@
|
|
#define GC_CLOCK_100_200 (1 << 0)
|
|
#define GC_CLOCK_100_133 (2 << 0)
|
|
#define GC_CLOCK_166_250 (3 << 0)
|
|
+#define GCFGC2 0xda
|
|
#define GCFGC 0xf0 /* 915+ only */
|
|
#define GC_LOW_FREQUENCY_ENABLE (1 << 7)
|
|
#define GC_DISPLAY_CLOCK_190_200_MHZ (0 << 4)
|
|
@@ -221,7 +241,7 @@
|
|
#define I830_FENCE_SIZE_BITS(size) ((ffs((size) >> 19) - 1) << 8)
|
|
#define I830_FENCE_PITCH_SHIFT 4
|
|
#define I830_FENCE_REG_VALID (1<<0)
|
|
-#define I915_FENCE_MAX_PITCH_VAL 0x10
|
|
+#define I915_FENCE_MAX_PITCH_VAL 4
|
|
#define I830_FENCE_MAX_PITCH_VAL 6
|
|
#define I830_FENCE_MAX_SIZE_VAL (1<<8)
|
|
|
|
@@ -234,6 +254,9 @@
|
|
#define I965_FENCE_REG_VALID (1<<0)
|
|
#define I965_FENCE_MAX_PITCH_VAL 0x0400
|
|
|
|
+#define FENCE_REG_SANDYBRIDGE_0 0x100000
|
|
+#define SANDYBRIDGE_FENCE_PITCH_SHIFT 32
|
|
+
|
|
/*
|
|
* Instruction and interrupt control regs
|
|
*/
|
|
@@ -265,6 +288,7 @@
|
|
#define INSTDONE1 0x0207c /* 965+ only */
|
|
#define ACTHD_I965 0x02074
|
|
#define HWS_PGA 0x02080
|
|
+#define HWS_PGA_GEN6 0x04080
|
|
#define HWS_ADDRESS_MASK 0xfffff000
|
|
#define HWS_START_ADDRESS_SHIFT 4
|
|
#define PWRCTXA 0x2088 /* 965GM+ only */
|
|
@@ -274,6 +298,10 @@
|
|
#define INSTDONE 0x02090
|
|
#define NOPID 0x02094
|
|
#define HWSTAM 0x02098
|
|
+
|
|
+#define MI_MODE 0x0209c
|
|
+# define VS_TIMER_DISPATCH (1 << 6)
|
|
+
|
|
#define SCPD0 0x0209c /* 915+ only */
|
|
#define IER 0x020a0
|
|
#define IIR 0x020a4
|
|
@@ -282,7 +310,7 @@
|
|
#define I915_PIPE_CONTROL_NOTIFY_INTERRUPT (1<<18)
|
|
#define I915_DISPLAY_PORT_INTERRUPT (1<<17)
|
|
#define I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT (1<<15)
|
|
-#define I915_GMCH_THERMAL_SENSOR_EVENT_INTERRUPT (1<<14)
|
|
+#define I915_GMCH_THERMAL_SENSOR_EVENT_INTERRUPT (1<<14) /* p-state */
|
|
#define I915_HWB_OOM_INTERRUPT (1<<13)
|
|
#define I915_SYNC_STATUS_INTERRUPT (1<<12)
|
|
#define I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT (1<<11)
|
|
@@ -306,11 +334,14 @@
|
|
#define I915_ERROR_MEMORY_REFRESH (1<<1)
|
|
#define I915_ERROR_INSTRUCTION (1<<0)
|
|
#define INSTPM 0x020c0
|
|
+#define INSTPM_SELF_EN (1<<12) /* 915GM only */
|
|
#define ACTHD 0x020c8
|
|
#define FW_BLC 0x020d8
|
|
#define FW_BLC2 0x020dc
|
|
#define FW_BLC_SELF 0x020e0 /* 915+ only */
|
|
-#define FW_BLC_SELF_EN (1<<15)
|
|
+#define FW_BLC_SELF_EN_MASK (1<<31)
|
|
+#define FW_BLC_SELF_FIFO_MASK (1<<16) /* 945 only */
|
|
+#define FW_BLC_SELF_EN (1<<15) /* 945 only */
|
|
#define MM_BURST_LENGTH 0x00700000
|
|
#define MM_FIFO_WATERMARK 0x0001F000
|
|
#define LM_BURST_LENGTH 0x00000700
|
|
@@ -324,6 +355,7 @@
|
|
#define CM0_COLOR_EVICT_DISABLE (1<<3)
|
|
#define CM0_DEPTH_WRITE_DISABLE (1<<1)
|
|
#define CM0_RC_OP_FLUSH_DISABLE (1<<0)
|
|
+#define BB_ADDR 0x02140 /* 8 bytes */
|
|
#define GFX_FLSH_CNTL 0x02170 /* 915+ only */
|
|
|
|
|
|
@@ -338,7 +370,7 @@
|
|
#define FBC_CTL_PERIODIC (1<<30)
|
|
#define FBC_CTL_INTERVAL_SHIFT (16)
|
|
#define FBC_CTL_UNCOMPRESSIBLE (1<<14)
|
|
-#define FBC_C3_IDLE (1<<13)
|
|
+#define FBC_CTL_C3_IDLE (1<<13)
|
|
#define FBC_CTL_STRIDE_SHIFT (5)
|
|
#define FBC_CTL_FENCENO (1<<0)
|
|
#define FBC_COMMAND 0x0320c
|
|
@@ -784,10 +816,144 @@
|
|
#define CLKCFG_MEM_800 (3 << 4)
|
|
#define CLKCFG_MEM_MASK (7 << 4)
|
|
|
|
-/** GM965 GM45 render standby register */
|
|
-#define MCHBAR_RENDER_STANDBY 0x111B8
|
|
+#define CRSTANDVID 0x11100
|
|
+#define PXVFREQ_BASE 0x11110 /* P[0-15]VIDFREQ (0x1114c) (Ironlake) */
|
|
+#define PXVFREQ_PX_MASK 0x7f000000
|
|
+#define PXVFREQ_PX_SHIFT 24
|
|
+#define VIDFREQ_BASE 0x11110
|
|
+#define VIDFREQ1 0x11110 /* VIDFREQ1-4 (0x1111c) (Cantiga) */
|
|
+#define VIDFREQ2 0x11114
|
|
+#define VIDFREQ3 0x11118
|
|
+#define VIDFREQ4 0x1111c
|
|
+#define VIDFREQ_P0_MASK 0x1f000000
|
|
+#define VIDFREQ_P0_SHIFT 24
|
|
+#define VIDFREQ_P0_CSCLK_MASK 0x00f00000
|
|
+#define VIDFREQ_P0_CSCLK_SHIFT 20
|
|
+#define VIDFREQ_P0_CRCLK_MASK 0x000f0000
|
|
+#define VIDFREQ_P0_CRCLK_SHIFT 16
|
|
+#define VIDFREQ_P1_MASK 0x00001f00
|
|
+#define VIDFREQ_P1_SHIFT 8
|
|
+#define VIDFREQ_P1_CSCLK_MASK 0x000000f0
|
|
+#define VIDFREQ_P1_CSCLK_SHIFT 4
|
|
+#define VIDFREQ_P1_CRCLK_MASK 0x0000000f
|
|
+#define INTTOEXT_BASE_ILK 0x11300
|
|
+#define INTTOEXT_BASE 0x11120 /* INTTOEXT1-8 (0x1113c) */
|
|
+#define INTTOEXT_MAP3_SHIFT 24
|
|
+#define INTTOEXT_MAP3_MASK (0x1f << INTTOEXT_MAP3_SHIFT)
|
|
+#define INTTOEXT_MAP2_SHIFT 16
|
|
+#define INTTOEXT_MAP2_MASK (0x1f << INTTOEXT_MAP2_SHIFT)
|
|
+#define INTTOEXT_MAP1_SHIFT 8
|
|
+#define INTTOEXT_MAP1_MASK (0x1f << INTTOEXT_MAP1_SHIFT)
|
|
+#define INTTOEXT_MAP0_SHIFT 0
|
|
+#define INTTOEXT_MAP0_MASK (0x1f << INTTOEXT_MAP0_SHIFT)
|
|
+#define MEMSWCTL 0x11170 /* Ironlake only */
|
|
+#define MEMCTL_CMD_MASK 0xe000
|
|
+#define MEMCTL_CMD_SHIFT 13
|
|
+#define MEMCTL_CMD_RCLK_OFF 0
|
|
+#define MEMCTL_CMD_RCLK_ON 1
|
|
+#define MEMCTL_CMD_CHFREQ 2
|
|
+#define MEMCTL_CMD_CHVID 3
|
|
+#define MEMCTL_CMD_VMMOFF 4
|
|
+#define MEMCTL_CMD_VMMON 5
|
|
+#define MEMCTL_CMD_STS (1<<12) /* write 1 triggers command, clears
|
|
+ when command complete */
|
|
+#define MEMCTL_FREQ_MASK 0x0f00 /* jitter, from 0-15 */
|
|
+#define MEMCTL_FREQ_SHIFT 8
|
|
+#define MEMCTL_SFCAVM (1<<7)
|
|
+#define MEMCTL_TGT_VID_MASK 0x007f
|
|
+#define MEMIHYST 0x1117c
|
|
+#define MEMINTREN 0x11180 /* 16 bits */
|
|
+#define MEMINT_RSEXIT_EN (1<<8)
|
|
+#define MEMINT_CX_SUPR_EN (1<<7)
|
|
+#define MEMINT_CONT_BUSY_EN (1<<6)
|
|
+#define MEMINT_AVG_BUSY_EN (1<<5)
|
|
+#define MEMINT_EVAL_CHG_EN (1<<4)
|
|
+#define MEMINT_MON_IDLE_EN (1<<3)
|
|
+#define MEMINT_UP_EVAL_EN (1<<2)
|
|
+#define MEMINT_DOWN_EVAL_EN (1<<1)
|
|
+#define MEMINT_SW_CMD_EN (1<<0)
|
|
+#define MEMINTRSTR 0x11182 /* 16 bits */
|
|
+#define MEM_RSEXIT_MASK 0xc000
|
|
+#define MEM_RSEXIT_SHIFT 14
|
|
+#define MEM_CONT_BUSY_MASK 0x3000
|
|
+#define MEM_CONT_BUSY_SHIFT 12
|
|
+#define MEM_AVG_BUSY_MASK 0x0c00
|
|
+#define MEM_AVG_BUSY_SHIFT 10
|
|
+#define MEM_EVAL_CHG_MASK 0x0300
|
|
+#define MEM_EVAL_BUSY_SHIFT 8
|
|
+#define MEM_MON_IDLE_MASK 0x00c0
|
|
+#define MEM_MON_IDLE_SHIFT 6
|
|
+#define MEM_UP_EVAL_MASK 0x0030
|
|
+#define MEM_UP_EVAL_SHIFT 4
|
|
+#define MEM_DOWN_EVAL_MASK 0x000c
|
|
+#define MEM_DOWN_EVAL_SHIFT 2
|
|
+#define MEM_SW_CMD_MASK 0x0003
|
|
+#define MEM_INT_STEER_GFX 0
|
|
+#define MEM_INT_STEER_CMR 1
|
|
+#define MEM_INT_STEER_SMI 2
|
|
+#define MEM_INT_STEER_SCI 3
|
|
+#define MEMINTRSTS 0x11184
|
|
+#define MEMINT_RSEXIT (1<<7)
|
|
+#define MEMINT_CONT_BUSY (1<<6)
|
|
+#define MEMINT_AVG_BUSY (1<<5)
|
|
+#define MEMINT_EVAL_CHG (1<<4)
|
|
+#define MEMINT_MON_IDLE (1<<3)
|
|
+#define MEMINT_UP_EVAL (1<<2)
|
|
+#define MEMINT_DOWN_EVAL (1<<1)
|
|
+#define MEMINT_SW_CMD (1<<0)
|
|
+#define MEMMODECTL 0x11190
|
|
+#define MEMMODE_BOOST_EN (1<<31)
|
|
+#define MEMMODE_BOOST_FREQ_MASK 0x0f000000 /* jitter for boost, 0-15 */
|
|
+#define MEMMODE_BOOST_FREQ_SHIFT 24
|
|
+#define MEMMODE_IDLE_MODE_MASK 0x00030000
|
|
+#define MEMMODE_IDLE_MODE_SHIFT 16
|
|
+#define MEMMODE_IDLE_MODE_EVAL 0
|
|
+#define MEMMODE_IDLE_MODE_CONT 1
|
|
+#define MEMMODE_HWIDLE_EN (1<<15)
|
|
+#define MEMMODE_SWMODE_EN (1<<14)
|
|
+#define MEMMODE_RCLK_GATE (1<<13)
|
|
+#define MEMMODE_HW_UPDATE (1<<12)
|
|
+#define MEMMODE_FSTART_MASK 0x00000f00 /* starting jitter, 0-15 */
|
|
+#define MEMMODE_FSTART_SHIFT 8
|
|
+#define MEMMODE_FMAX_MASK 0x000000f0 /* max jitter, 0-15 */
|
|
+#define MEMMODE_FMAX_SHIFT 4
|
|
+#define MEMMODE_FMIN_MASK 0x0000000f /* min jitter, 0-15 */
|
|
+#define RCBMAXAVG 0x1119c
|
|
+#define MEMSWCTL2 0x1119e /* Cantiga only */
|
|
+#define SWMEMCMD_RENDER_OFF (0 << 13)
|
|
+#define SWMEMCMD_RENDER_ON (1 << 13)
|
|
+#define SWMEMCMD_SWFREQ (2 << 13)
|
|
+#define SWMEMCMD_TARVID (3 << 13)
|
|
+#define SWMEMCMD_VRM_OFF (4 << 13)
|
|
+#define SWMEMCMD_VRM_ON (5 << 13)
|
|
+#define CMDSTS (1<<12)
|
|
+#define SFCAVM (1<<11)
|
|
+#define SWFREQ_MASK 0x0380 /* P0-7 */
|
|
+#define SWFREQ_SHIFT 7
|
|
+#define TARVID_MASK 0x001f
|
|
+#define MEMSTAT_CTG 0x111a0
|
|
+#define RCBMINAVG 0x111a0
|
|
+#define RCUPEI 0x111b0
|
|
+#define RCDNEI 0x111b4
|
|
+#define MCHBAR_RENDER_STANDBY 0x111b8
|
|
#define RCX_SW_EXIT (1<<23)
|
|
#define RSX_STATUS_MASK 0x00700000
|
|
+#define VIDCTL 0x111c0
|
|
+#define VIDSTS 0x111c8
|
|
+#define VIDSTART 0x111cc /* 8 bits */
|
|
+#define MEMSTAT_ILK 0x111f8
|
|
+#define MEMSTAT_VID_MASK 0x7f00
|
|
+#define MEMSTAT_VID_SHIFT 8
|
|
+#define MEMSTAT_PSTATE_MASK 0x00f8
|
|
+#define MEMSTAT_PSTATE_SHIFT 3
|
|
+#define MEMSTAT_MON_ACTV (1<<2)
|
|
+#define MEMSTAT_SRC_CTL_MASK 0x0003
|
|
+#define MEMSTAT_SRC_CTL_CORE 0
|
|
+#define MEMSTAT_SRC_CTL_TRB 1
|
|
+#define MEMSTAT_SRC_CTL_THM 2
|
|
+#define MEMSTAT_SRC_CTL_STDBY 3
|
|
+#define RCPREVBSYTUPAVG 0x113b8
|
|
+#define RCPREVBSYTDNAVG 0x113bc
|
|
#define PEG_BAND_GAP_DATA 0x14d68
|
|
|
|
/*
|
|
@@ -1588,6 +1754,14 @@
|
|
#define DP_LINK_TRAIN_MASK (3 << 28)
|
|
#define DP_LINK_TRAIN_SHIFT 28
|
|
|
|
+/* CPT Link training mode */
|
|
+#define DP_LINK_TRAIN_PAT_1_CPT (0 << 8)
|
|
+#define DP_LINK_TRAIN_PAT_2_CPT (1 << 8)
|
|
+#define DP_LINK_TRAIN_PAT_IDLE_CPT (2 << 8)
|
|
+#define DP_LINK_TRAIN_OFF_CPT (3 << 8)
|
|
+#define DP_LINK_TRAIN_MASK_CPT (7 << 8)
|
|
+#define DP_LINK_TRAIN_SHIFT_CPT 8
|
|
+
|
|
/* Signal voltages. These are mostly controlled by the other end */
|
|
#define DP_VOLTAGE_0_4 (0 << 25)
|
|
#define DP_VOLTAGE_0_6 (1 << 25)
|
|
@@ -1812,15 +1986,24 @@
|
|
|
|
#define DSPFW1 0x70034
|
|
#define DSPFW_SR_SHIFT 23
|
|
+#define DSPFW_SR_MASK (0x1ff<<23)
|
|
#define DSPFW_CURSORB_SHIFT 16
|
|
+#define DSPFW_CURSORB_MASK (0x3f<<16)
|
|
#define DSPFW_PLANEB_SHIFT 8
|
|
+#define DSPFW_PLANEB_MASK (0x7f<<8)
|
|
+#define DSPFW_PLANEA_MASK (0x7f)
|
|
#define DSPFW2 0x70038
|
|
#define DSPFW_CURSORA_MASK 0x00003f00
|
|
#define DSPFW_CURSORA_SHIFT 8
|
|
+#define DSPFW_PLANEC_MASK (0x7f)
|
|
#define DSPFW3 0x7003c
|
|
#define DSPFW_HPLL_SR_EN (1<<31)
|
|
#define DSPFW_CURSOR_SR_SHIFT 24
|
|
#define PINEVIEW_SELF_REFRESH_EN (1<<30)
|
|
+#define DSPFW_CURSOR_SR_MASK (0x3f<<24)
|
|
+#define DSPFW_HPLL_CURSOR_SHIFT 16
|
|
+#define DSPFW_HPLL_CURSOR_MASK (0x3f<<16)
|
|
+#define DSPFW_HPLL_SR_MASK (0x1ff)
|
|
|
|
/* FIFO watermark sizes etc */
|
|
#define G4X_FIFO_LINE_SIZE 64
|
|
@@ -1847,6 +2030,43 @@
|
|
#define PINEVIEW_CURSOR_DFT_WM 0
|
|
#define PINEVIEW_CURSOR_GUARD_WM 5
|
|
|
|
+
|
|
+/* define the Watermark register on Ironlake */
|
|
+#define WM0_PIPEA_ILK 0x45100
|
|
+#define WM0_PIPE_PLANE_MASK (0x7f<<16)
|
|
+#define WM0_PIPE_PLANE_SHIFT 16
|
|
+#define WM0_PIPE_SPRITE_MASK (0x3f<<8)
|
|
+#define WM0_PIPE_SPRITE_SHIFT 8
|
|
+#define WM0_PIPE_CURSOR_MASK (0x1f)
|
|
+
|
|
+#define WM0_PIPEB_ILK 0x45104
|
|
+#define WM1_LP_ILK 0x45108
|
|
+#define WM1_LP_SR_EN (1<<31)
|
|
+#define WM1_LP_LATENCY_SHIFT 24
|
|
+#define WM1_LP_LATENCY_MASK (0x7f<<24)
|
|
+#define WM1_LP_SR_MASK (0x1ff<<8)
|
|
+#define WM1_LP_SR_SHIFT 8
|
|
+#define WM1_LP_CURSOR_MASK (0x3f)
|
|
+
|
|
+/* Memory latency timer register */
|
|
+#define MLTR_ILK 0x11222
|
|
+/* the unit of memory self-refresh latency time is 0.5us */
|
|
+#define ILK_SRLT_MASK 0x3f
|
|
+
|
|
+/* define the fifo size on Ironlake */
|
|
+#define ILK_DISPLAY_FIFO 128
|
|
+#define ILK_DISPLAY_MAXWM 64
|
|
+#define ILK_DISPLAY_DFTWM 8
|
|
+
|
|
+#define ILK_DISPLAY_SR_FIFO 512
|
|
+#define ILK_DISPLAY_MAX_SRWM 0x1ff
|
|
+#define ILK_DISPLAY_DFT_SRWM 0x3f
|
|
+#define ILK_CURSOR_SR_FIFO 64
|
|
+#define ILK_CURSOR_MAX_SRWM 0x3f
|
|
+#define ILK_CURSOR_DFT_SRWM 8
|
|
+
|
|
+#define ILK_FIFO_LINE_SIZE 64
|
|
+
|
|
/*
|
|
* The two pipe frame counter registers are not synchronized, so
|
|
* reading a stable value is somewhat tricky. The following code
|
|
@@ -2010,6 +2230,14 @@
|
|
#define DISPLAY_PORT_PLL_BIOS_1 0x46010
|
|
#define DISPLAY_PORT_PLL_BIOS_2 0x46014
|
|
|
|
+#define PCH_DSPCLK_GATE_D 0x42020
|
|
+# define DPFDUNIT_CLOCK_GATE_DISABLE (1 << 7)
|
|
+# define DPARBUNIT_CLOCK_GATE_DISABLE (1 << 5)
|
|
+
|
|
+#define PCH_3DCGDIS0 0x46020
|
|
+# define MARIUNIT_CLOCK_GATE_DISABLE (1 << 18)
|
|
+# define SVSMUNIT_CLOCK_GATE_DISABLE (1 << 1)
|
|
+
|
|
#define FDI_PLL_FREQ_CTL 0x46030
|
|
#define FDI_PLL_FREQ_CHANGE_REQUEST (1<<24)
|
|
#define FDI_PLL_FREQ_LOCK_LIMIT_MASK 0xfff00
|
|
@@ -2119,8 +2347,15 @@
|
|
#define GTIIR 0x44018
|
|
#define GTIER 0x4401c
|
|
|
|
+#define ILK_DISPLAY_CHICKEN2 0x42004
|
|
+#define ILK_DPARB_GATE (1<<22)
|
|
+#define ILK_VSDPFD_FULL (1<<21)
|
|
+#define ILK_DSPCLK_GATE 0x42020
|
|
+#define ILK_DPARB_CLK_GATE (1<<5)
|
|
+
|
|
#define DISP_ARB_CTL 0x45000
|
|
#define DISP_TILE_SURFACE_SWIZZLING (1<<13)
|
|
+#define DISP_FBC_WM_DIS (1<<15)
|
|
|
|
/* PCH */
|
|
|
|
@@ -2131,6 +2366,11 @@
|
|
#define SDE_PORTB_HOTPLUG (1 << 8)
|
|
#define SDE_SDVOB_HOTPLUG (1 << 6)
|
|
#define SDE_HOTPLUG_MASK (0xf << 8)
|
|
+/* CPT */
|
|
+#define SDE_CRT_HOTPLUG_CPT (1 << 19)
|
|
+#define SDE_PORTD_HOTPLUG_CPT (1 << 23)
|
|
+#define SDE_PORTC_HOTPLUG_CPT (1 << 22)
|
|
+#define SDE_PORTB_HOTPLUG_CPT (1 << 21)
|
|
|
|
#define SDEISR 0xc4000
|
|
#define SDEIMR 0xc4004
|
|
@@ -2222,6 +2462,17 @@
|
|
#define PCH_SSC4_PARMS 0xc6210
|
|
#define PCH_SSC4_AUX_PARMS 0xc6214
|
|
|
|
+#define PCH_DPLL_SEL 0xc7000
|
|
+#define TRANSA_DPLL_ENABLE (1<<3)
|
|
+#define TRANSA_DPLLB_SEL (1<<0)
|
|
+#define TRANSA_DPLLA_SEL 0
|
|
+#define TRANSB_DPLL_ENABLE (1<<7)
|
|
+#define TRANSB_DPLLB_SEL (1<<4)
|
|
+#define TRANSB_DPLLA_SEL (0)
|
|
+#define TRANSC_DPLL_ENABLE (1<<11)
|
|
+#define TRANSC_DPLLB_SEL (1<<8)
|
|
+#define TRANSC_DPLLA_SEL (0)
|
|
+
|
|
/* transcoder */
|
|
|
|
#define TRANS_HTOTAL_A 0xe0000
|
|
@@ -2308,6 +2559,19 @@
|
|
#define FDI_LINK_TRAIN_PRE_EMPHASIS_1_5X (1<<22)
|
|
#define FDI_LINK_TRAIN_PRE_EMPHASIS_2X (2<<22)
|
|
#define FDI_LINK_TRAIN_PRE_EMPHASIS_3X (3<<22)
|
|
+/* ILK always use 400mV 0dB for voltage swing and pre-emphasis level.
|
|
+ SNB has different settings. */
|
|
+/* SNB A-stepping */
|
|
+#define FDI_LINK_TRAIN_400MV_0DB_SNB_A (0x38<<22)
|
|
+#define FDI_LINK_TRAIN_400MV_6DB_SNB_A (0x02<<22)
|
|
+#define FDI_LINK_TRAIN_600MV_3_5DB_SNB_A (0x01<<22)
|
|
+#define FDI_LINK_TRAIN_800MV_0DB_SNB_A (0x0<<22)
|
|
+/* SNB B-stepping */
|
|
+#define FDI_LINK_TRAIN_400MV_0DB_SNB_B (0x0<<22)
|
|
+#define FDI_LINK_TRAIN_400MV_6DB_SNB_B (0x3a<<22)
|
|
+#define FDI_LINK_TRAIN_600MV_3_5DB_SNB_B (0x39<<22)
|
|
+#define FDI_LINK_TRAIN_800MV_0DB_SNB_B (0x38<<22)
|
|
+#define FDI_LINK_TRAIN_VOL_EMP_MASK (0x3f<<22)
|
|
#define FDI_DP_PORT_WIDTH_X1 (0<<19)
|
|
#define FDI_DP_PORT_WIDTH_X2 (1<<19)
|
|
#define FDI_DP_PORT_WIDTH_X3 (2<<19)
|
|
@@ -2340,6 +2604,13 @@
|
|
#define FDI_RX_ENHANCE_FRAME_ENABLE (1<<6)
|
|
#define FDI_SEL_RAWCLK (0<<4)
|
|
#define FDI_SEL_PCDCLK (1<<4)
|
|
+/* CPT */
|
|
+#define FDI_AUTO_TRAINING (1<<10)
|
|
+#define FDI_LINK_TRAIN_PATTERN_1_CPT (0<<8)
|
|
+#define FDI_LINK_TRAIN_PATTERN_2_CPT (1<<8)
|
|
+#define FDI_LINK_TRAIN_PATTERN_IDLE_CPT (2<<8)
|
|
+#define FDI_LINK_TRAIN_NORMAL_CPT (3<<8)
|
|
+#define FDI_LINK_TRAIN_PATTERN_MASK_CPT (3<<8)
|
|
|
|
#define FDI_RXA_MISC 0xf0010
|
|
#define FDI_RXB_MISC 0xf1010
|
|
@@ -2411,6 +2682,9 @@
|
|
#define HSYNC_ACTIVE_HIGH (1 << 3)
|
|
#define PORT_DETECTED (1 << 2)
|
|
|
|
+/* PCH SDVOB multiplex with HDMIB */
|
|
+#define PCH_SDVOB HDMIB
|
|
+
|
|
#define HDMIC 0xe1150
|
|
#define HDMID 0xe1160
|
|
|
|
@@ -2468,4 +2742,42 @@
|
|
#define PCH_DPD_AUX_CH_DATA4 0xe4320
|
|
#define PCH_DPD_AUX_CH_DATA5 0xe4324
|
|
|
|
+/* CPT */
|
|
+#define PORT_TRANS_A_SEL_CPT 0
|
|
+#define PORT_TRANS_B_SEL_CPT (1<<29)
|
|
+#define PORT_TRANS_C_SEL_CPT (2<<29)
|
|
+#define PORT_TRANS_SEL_MASK (3<<29)
|
|
+
|
|
+#define TRANS_DP_CTL_A 0xe0300
|
|
+#define TRANS_DP_CTL_B 0xe1300
|
|
+#define TRANS_DP_CTL_C 0xe2300
|
|
+#define TRANS_DP_OUTPUT_ENABLE (1<<31)
|
|
+#define TRANS_DP_PORT_SEL_B (0<<29)
|
|
+#define TRANS_DP_PORT_SEL_C (1<<29)
|
|
+#define TRANS_DP_PORT_SEL_D (2<<29)
|
|
+#define TRANS_DP_PORT_SEL_MASK (3<<29)
|
|
+#define TRANS_DP_AUDIO_ONLY (1<<26)
|
|
+#define TRANS_DP_ENH_FRAMING (1<<18)
|
|
+#define TRANS_DP_8BPC (0<<9)
|
|
+#define TRANS_DP_10BPC (1<<9)
|
|
+#define TRANS_DP_6BPC (2<<9)
|
|
+#define TRANS_DP_12BPC (3<<9)
|
|
+#define TRANS_DP_VSYNC_ACTIVE_HIGH (1<<4)
|
|
+#define TRANS_DP_VSYNC_ACTIVE_LOW 0
|
|
+#define TRANS_DP_HSYNC_ACTIVE_HIGH (1<<3)
|
|
+#define TRANS_DP_HSYNC_ACTIVE_LOW 0
|
|
+
|
|
+/* SNB eDP training params */
|
|
+/* SNB A-stepping */
|
|
+#define EDP_LINK_TRAIN_400MV_0DB_SNB_A (0x38<<22)
|
|
+#define EDP_LINK_TRAIN_400MV_6DB_SNB_A (0x02<<22)
|
|
+#define EDP_LINK_TRAIN_600MV_3_5DB_SNB_A (0x01<<22)
|
|
+#define EDP_LINK_TRAIN_800MV_0DB_SNB_A (0x0<<22)
|
|
+/* SNB B-stepping */
|
|
+#define EDP_LINK_TRAIN_400MV_0DB_SNB_B (0x0<<22)
|
|
+#define EDP_LINK_TRAIN_400MV_6DB_SNB_B (0x3a<<22)
|
|
+#define EDP_LINK_TRAIN_600MV_3_5DB_SNB_B (0x39<<22)
|
|
+#define EDP_LINK_TRAIN_800MV_0DB_SNB_B (0x38<<22)
|
|
+#define EDP_LINK_TRAIN_VOL_EMP_MASK_SNB (0x3f<<22)
|
|
+
|
|
#endif /* _I915_REG_H_ */
|
|
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c
|
|
--- a/drivers/gpu/drm/i915/i915_suspend.c
|
|
+++ b/drivers/gpu/drm/i915/i915_suspend.c
|
|
@@ -600,14 +600,16 @@ void i915_save_display(struct drm_device *dev)
|
|
}
|
|
/* FIXME: save TV & SDVO state */
|
|
|
|
- /* FBC state */
|
|
- if (IS_GM45(dev)) {
|
|
- dev_priv->saveDPFC_CB_BASE = I915_READ(DPFC_CB_BASE);
|
|
- } else {
|
|
- dev_priv->saveFBC_CFB_BASE = I915_READ(FBC_CFB_BASE);
|
|
- dev_priv->saveFBC_LL_BASE = I915_READ(FBC_LL_BASE);
|
|
- dev_priv->saveFBC_CONTROL2 = I915_READ(FBC_CONTROL2);
|
|
- dev_priv->saveFBC_CONTROL = I915_READ(FBC_CONTROL);
|
|
+ /* Only save FBC state on the platform that supports FBC */
|
|
+ if (I915_HAS_FBC(dev)) {
|
|
+ if (IS_GM45(dev)) {
|
|
+ dev_priv->saveDPFC_CB_BASE = I915_READ(DPFC_CB_BASE);
|
|
+ } else {
|
|
+ dev_priv->saveFBC_CFB_BASE = I915_READ(FBC_CFB_BASE);
|
|
+ dev_priv->saveFBC_LL_BASE = I915_READ(FBC_LL_BASE);
|
|
+ dev_priv->saveFBC_CONTROL2 = I915_READ(FBC_CONTROL2);
|
|
+ dev_priv->saveFBC_CONTROL = I915_READ(FBC_CONTROL);
|
|
+ }
|
|
}
|
|
|
|
/* VGA state */
|
|
@@ -682,6 +684,8 @@ void i915_restore_display(struct drm_device *dev)
|
|
I915_WRITE(PCH_PP_OFF_DELAYS, dev_priv->savePP_OFF_DELAYS);
|
|
I915_WRITE(PCH_PP_DIVISOR, dev_priv->savePP_DIVISOR);
|
|
I915_WRITE(PCH_PP_CONTROL, dev_priv->savePP_CONTROL);
|
|
+ I915_WRITE(MCHBAR_RENDER_STANDBY,
|
|
+ dev_priv->saveMCHBAR_RENDER_STANDBY);
|
|
} else {
|
|
I915_WRITE(PFIT_PGM_RATIOS, dev_priv->savePFIT_PGM_RATIOS);
|
|
I915_WRITE(BLC_PWM_CTL, dev_priv->saveBLC_PWM_CTL);
|
|
@@ -700,18 +704,19 @@ void i915_restore_display(struct drm_device *dev)
|
|
}
|
|
/* FIXME: restore TV & SDVO state */
|
|
|
|
- /* FBC info */
|
|
- if (IS_GM45(dev)) {
|
|
- g4x_disable_fbc(dev);
|
|
- I915_WRITE(DPFC_CB_BASE, dev_priv->saveDPFC_CB_BASE);
|
|
- } else {
|
|
- i8xx_disable_fbc(dev);
|
|
- I915_WRITE(FBC_CFB_BASE, dev_priv->saveFBC_CFB_BASE);
|
|
- I915_WRITE(FBC_LL_BASE, dev_priv->saveFBC_LL_BASE);
|
|
- I915_WRITE(FBC_CONTROL2, dev_priv->saveFBC_CONTROL2);
|
|
- I915_WRITE(FBC_CONTROL, dev_priv->saveFBC_CONTROL);
|
|
+ /* only restore FBC info on the platform that supports FBC*/
|
|
+ if (I915_HAS_FBC(dev)) {
|
|
+ if (IS_GM45(dev)) {
|
|
+ g4x_disable_fbc(dev);
|
|
+ I915_WRITE(DPFC_CB_BASE, dev_priv->saveDPFC_CB_BASE);
|
|
+ } else {
|
|
+ i8xx_disable_fbc(dev);
|
|
+ I915_WRITE(FBC_CFB_BASE, dev_priv->saveFBC_CFB_BASE);
|
|
+ I915_WRITE(FBC_LL_BASE, dev_priv->saveFBC_LL_BASE);
|
|
+ I915_WRITE(FBC_CONTROL2, dev_priv->saveFBC_CONTROL2);
|
|
+ I915_WRITE(FBC_CONTROL, dev_priv->saveFBC_CONTROL);
|
|
+ }
|
|
}
|
|
-
|
|
/* VGA state */
|
|
if (IS_IRONLAKE(dev))
|
|
I915_WRITE(CPU_VGACNTRL, dev_priv->saveVGACNTRL);
|
|
@@ -745,11 +750,16 @@ int i915_save_state(struct drm_device *dev)
|
|
dev_priv->saveGTIMR = I915_READ(GTIMR);
|
|
dev_priv->saveFDI_RXA_IMR = I915_READ(FDI_RXA_IMR);
|
|
dev_priv->saveFDI_RXB_IMR = I915_READ(FDI_RXB_IMR);
|
|
+ dev_priv->saveMCHBAR_RENDER_STANDBY =
|
|
+ I915_READ(MCHBAR_RENDER_STANDBY);
|
|
} else {
|
|
dev_priv->saveIER = I915_READ(IER);
|
|
dev_priv->saveIMR = I915_READ(IMR);
|
|
}
|
|
|
|
+ if (IS_IRONLAKE_M(dev))
|
|
+ ironlake_disable_drps(dev);
|
|
+
|
|
/* Cache mode state */
|
|
dev_priv->saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0);
|
|
|
|
@@ -820,6 +830,9 @@ int i915_restore_state(struct drm_device *dev)
|
|
/* Clock gating state */
|
|
intel_init_clock_gating(dev);
|
|
|
|
+ if (IS_IRONLAKE_M(dev))
|
|
+ ironlake_enable_drps(dev);
|
|
+
|
|
/* Cache mode state */
|
|
I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000);
|
|
|
|
diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h
|
|
--- a/drivers/gpu/drm/i915/i915_trace.h
|
|
+++ b/drivers/gpu/drm/i915/i915_trace.h
|
|
@@ -115,7 +115,7 @@ TRACE_EVENT(i915_gem_object_get_fence,
|
|
__entry->obj, __entry->fence, __entry->tiling_mode)
|
|
);
|
|
|
|
-TRACE_EVENT(i915_gem_object_unbind,
|
|
+DECLARE_EVENT_CLASS(i915_gem_object,
|
|
|
|
TP_PROTO(struct drm_gem_object *obj),
|
|
|
|
@@ -132,21 +132,18 @@ TRACE_EVENT(i915_gem_object_unbind,
|
|
TP_printk("obj=%p", __entry->obj)
|
|
);
|
|
|
|
-TRACE_EVENT(i915_gem_object_destroy,
|
|
+DEFINE_EVENT(i915_gem_object, i915_gem_object_unbind,
|
|
|
|
TP_PROTO(struct drm_gem_object *obj),
|
|
|
|
- TP_ARGS(obj),
|
|
+ TP_ARGS(obj)
|
|
+);
|
|
|
|
- TP_STRUCT__entry(
|
|
- __field(struct drm_gem_object *, obj)
|
|
- ),
|
|
+DEFINE_EVENT(i915_gem_object, i915_gem_object_destroy,
|
|
|
|
- TP_fast_assign(
|
|
- __entry->obj = obj;
|
|
- ),
|
|
+ TP_PROTO(struct drm_gem_object *obj),
|
|
|
|
- TP_printk("obj=%p", __entry->obj)
|
|
+ TP_ARGS(obj)
|
|
);
|
|
|
|
/* batch tracing */
|
|
@@ -197,8 +194,7 @@ TRACE_EVENT(i915_gem_request_flush,
|
|
__entry->flush_domains, __entry->invalidate_domains)
|
|
);
|
|
|
|
-
|
|
-TRACE_EVENT(i915_gem_request_complete,
|
|
+DECLARE_EVENT_CLASS(i915_gem_request,
|
|
|
|
TP_PROTO(struct drm_device *dev, u32 seqno),
|
|
|
|
@@ -217,64 +213,35 @@ TRACE_EVENT(i915_gem_request_complete,
|
|
TP_printk("dev=%u, seqno=%u", __entry->dev, __entry->seqno)
|
|
);
|
|
|
|
-TRACE_EVENT(i915_gem_request_retire,
|
|
+DEFINE_EVENT(i915_gem_request, i915_gem_request_complete,
|
|
|
|
TP_PROTO(struct drm_device *dev, u32 seqno),
|
|
|
|
- TP_ARGS(dev, seqno),
|
|
-
|
|
- TP_STRUCT__entry(
|
|
- __field(u32, dev)
|
|
- __field(u32, seqno)
|
|
- ),
|
|
-
|
|
- TP_fast_assign(
|
|
- __entry->dev = dev->primary->index;
|
|
- __entry->seqno = seqno;
|
|
- ),
|
|
-
|
|
- TP_printk("dev=%u, seqno=%u", __entry->dev, __entry->seqno)
|
|
+ TP_ARGS(dev, seqno)
|
|
);
|
|
|
|
-TRACE_EVENT(i915_gem_request_wait_begin,
|
|
+DEFINE_EVENT(i915_gem_request, i915_gem_request_retire,
|
|
|
|
TP_PROTO(struct drm_device *dev, u32 seqno),
|
|
|
|
- TP_ARGS(dev, seqno),
|
|
-
|
|
- TP_STRUCT__entry(
|
|
- __field(u32, dev)
|
|
- __field(u32, seqno)
|
|
- ),
|
|
-
|
|
- TP_fast_assign(
|
|
- __entry->dev = dev->primary->index;
|
|
- __entry->seqno = seqno;
|
|
- ),
|
|
-
|
|
- TP_printk("dev=%u, seqno=%u", __entry->dev, __entry->seqno)
|
|
+ TP_ARGS(dev, seqno)
|
|
);
|
|
|
|
-TRACE_EVENT(i915_gem_request_wait_end,
|
|
+DEFINE_EVENT(i915_gem_request, i915_gem_request_wait_begin,
|
|
|
|
TP_PROTO(struct drm_device *dev, u32 seqno),
|
|
|
|
- TP_ARGS(dev, seqno),
|
|
+ TP_ARGS(dev, seqno)
|
|
+);
|
|
|
|
- TP_STRUCT__entry(
|
|
- __field(u32, dev)
|
|
- __field(u32, seqno)
|
|
- ),
|
|
+DEFINE_EVENT(i915_gem_request, i915_gem_request_wait_end,
|
|
|
|
- TP_fast_assign(
|
|
- __entry->dev = dev->primary->index;
|
|
- __entry->seqno = seqno;
|
|
- ),
|
|
+ TP_PROTO(struct drm_device *dev, u32 seqno),
|
|
|
|
- TP_printk("dev=%u, seqno=%u", __entry->dev, __entry->seqno)
|
|
+ TP_ARGS(dev, seqno)
|
|
);
|
|
|
|
-TRACE_EVENT(i915_ring_wait_begin,
|
|
+DECLARE_EVENT_CLASS(i915_ring,
|
|
|
|
TP_PROTO(struct drm_device *dev),
|
|
|
|
@@ -291,21 +258,18 @@ TRACE_EVENT(i915_ring_wait_begin,
|
|
TP_printk("dev=%u", __entry->dev)
|
|
);
|
|
|
|
-TRACE_EVENT(i915_ring_wait_end,
|
|
+DEFINE_EVENT(i915_ring, i915_ring_wait_begin,
|
|
|
|
TP_PROTO(struct drm_device *dev),
|
|
|
|
- TP_ARGS(dev),
|
|
+ TP_ARGS(dev)
|
|
+);
|
|
|
|
- TP_STRUCT__entry(
|
|
- __field(u32, dev)
|
|
- ),
|
|
+DEFINE_EVENT(i915_ring, i915_ring_wait_end,
|
|
|
|
- TP_fast_assign(
|
|
- __entry->dev = dev->primary->index;
|
|
- ),
|
|
+ TP_PROTO(struct drm_device *dev),
|
|
|
|
- TP_printk("dev=%u", __entry->dev)
|
|
+ TP_ARGS(dev)
|
|
);
|
|
|
|
#endif /* _I915_TRACE_H_ */
|
|
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
|
|
--- a/drivers/gpu/drm/i915/intel_bios.c
|
|
+++ b/drivers/gpu/drm/i915/intel_bios.c
|
|
@@ -247,6 +247,7 @@ static void
|
|
parse_general_features(struct drm_i915_private *dev_priv,
|
|
struct bdb_header *bdb)
|
|
{
|
|
+ struct drm_device *dev = dev_priv->dev;
|
|
struct bdb_general_features *general;
|
|
|
|
/* Set sensible defaults in case we can't find the general block */
|
|
@@ -263,7 +264,7 @@ parse_general_features(struct drm_i915_private *dev_priv,
|
|
if (IS_I85X(dev_priv->dev))
|
|
dev_priv->lvds_ssc_freq =
|
|
general->ssc_freq ? 66 : 48;
|
|
- else if (IS_IRONLAKE(dev_priv->dev))
|
|
+ else if (IS_IRONLAKE(dev_priv->dev) || IS_GEN6(dev))
|
|
dev_priv->lvds_ssc_freq =
|
|
general->ssc_freq ? 100 : 120;
|
|
else
|
|
@@ -416,8 +417,9 @@ parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
|
|
edp = find_section(bdb, BDB_EDP);
|
|
if (!edp) {
|
|
if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->edp_support) {
|
|
- DRM_DEBUG_KMS("No eDP BDB found but eDP panel supported,\
|
|
- assume 18bpp panel color depth.\n");
|
|
+ DRM_DEBUG_KMS("No eDP BDB found but eDP panel "
|
|
+ "supported, assume 18bpp panel color "
|
|
+ "depth.\n");
|
|
dev_priv->edp_bpp = 18;
|
|
}
|
|
return;
|
|
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
|
|
--- a/drivers/gpu/drm/i915/intel_crt.c
|
|
+++ b/drivers/gpu/drm/i915/intel_crt.c
|
|
@@ -39,7 +39,7 @@ static void intel_crt_dpms(struct drm_encoder *encoder, int mode)
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
u32 temp, reg;
|
|
|
|
- if (IS_IRONLAKE(dev))
|
|
+ if (HAS_PCH_SPLIT(dev))
|
|
reg = PCH_ADPA;
|
|
else
|
|
reg = ADPA;
|
|
@@ -113,7 +113,7 @@ static void intel_crt_mode_set(struct drm_encoder *encoder,
|
|
else
|
|
dpll_md_reg = DPLL_B_MD;
|
|
|
|
- if (IS_IRONLAKE(dev))
|
|
+ if (HAS_PCH_SPLIT(dev))
|
|
adpa_reg = PCH_ADPA;
|
|
else
|
|
adpa_reg = ADPA;
|
|
@@ -122,7 +122,7 @@ static void intel_crt_mode_set(struct drm_encoder *encoder,
|
|
* Disable separate mode multiplier used when cloning SDVO to CRT
|
|
* XXX this needs to be adjusted when we really are cloning
|
|
*/
|
|
- if (IS_I965G(dev) && !IS_IRONLAKE(dev)) {
|
|
+ if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev)) {
|
|
dpll_md = I915_READ(dpll_md_reg);
|
|
I915_WRITE(dpll_md_reg,
|
|
dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK);
|
|
@@ -135,12 +135,18 @@ static void intel_crt_mode_set(struct drm_encoder *encoder,
|
|
adpa |= ADPA_VSYNC_ACTIVE_HIGH;
|
|
|
|
if (intel_crtc->pipe == 0) {
|
|
- adpa |= ADPA_PIPE_A_SELECT;
|
|
- if (!IS_IRONLAKE(dev))
|
|
+ if (HAS_PCH_CPT(dev))
|
|
+ adpa |= PORT_TRANS_A_SEL_CPT;
|
|
+ else
|
|
+ adpa |= ADPA_PIPE_A_SELECT;
|
|
+ if (!HAS_PCH_SPLIT(dev))
|
|
I915_WRITE(BCLRPAT_A, 0);
|
|
} else {
|
|
- adpa |= ADPA_PIPE_B_SELECT;
|
|
- if (!IS_IRONLAKE(dev))
|
|
+ if (HAS_PCH_CPT(dev))
|
|
+ adpa |= PORT_TRANS_B_SEL_CPT;
|
|
+ else
|
|
+ adpa |= ADPA_PIPE_B_SELECT;
|
|
+ if (!HAS_PCH_SPLIT(dev))
|
|
I915_WRITE(BCLRPAT_B, 0);
|
|
}
|
|
|
|
@@ -151,15 +157,21 @@ static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector)
|
|
{
|
|
struct drm_device *dev = connector->dev;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
- u32 adpa;
|
|
+ u32 adpa, temp;
|
|
bool ret;
|
|
|
|
- adpa = I915_READ(PCH_ADPA);
|
|
+ temp = adpa = I915_READ(PCH_ADPA);
|
|
|
|
- adpa &= ~ADPA_CRT_HOTPLUG_MASK;
|
|
- /* disable HPD first */
|
|
- I915_WRITE(PCH_ADPA, adpa);
|
|
- (void)I915_READ(PCH_ADPA);
|
|
+ if (HAS_PCH_CPT(dev)) {
|
|
+ /* Disable DAC before force detect */
|
|
+ I915_WRITE(PCH_ADPA, adpa & ~ADPA_DAC_ENABLE);
|
|
+ (void)I915_READ(PCH_ADPA);
|
|
+ } else {
|
|
+ adpa &= ~ADPA_CRT_HOTPLUG_MASK;
|
|
+ /* disable HPD first */
|
|
+ I915_WRITE(PCH_ADPA, adpa);
|
|
+ (void)I915_READ(PCH_ADPA);
|
|
+ }
|
|
|
|
adpa |= (ADPA_CRT_HOTPLUG_PERIOD_128 |
|
|
ADPA_CRT_HOTPLUG_WARMUP_10MS |
|
|
@@ -175,6 +187,11 @@ static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector)
|
|
while ((I915_READ(PCH_ADPA) & ADPA_CRT_HOTPLUG_FORCE_TRIGGER) != 0)
|
|
;
|
|
|
|
+ if (HAS_PCH_CPT(dev)) {
|
|
+ I915_WRITE(PCH_ADPA, temp);
|
|
+ (void)I915_READ(PCH_ADPA);
|
|
+ }
|
|
+
|
|
/* Check the status to see if both blue and green are on now */
|
|
adpa = I915_READ(PCH_ADPA);
|
|
adpa &= ADPA_CRT_HOTPLUG_MONITOR_MASK;
|
|
@@ -202,7 +219,7 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
|
|
u32 hotplug_en;
|
|
int i, tries = 0;
|
|
|
|
- if (IS_IRONLAKE(dev))
|
|
+ if (HAS_PCH_SPLIT(dev))
|
|
return intel_ironlake_crt_detect_hotplug(connector);
|
|
|
|
/*
|
|
@@ -244,21 +261,21 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
|
|
return false;
|
|
}
|
|
|
|
-static bool intel_crt_detect_ddc(struct drm_connector *connector)
|
|
+static bool intel_crt_detect_ddc(struct drm_encoder *encoder)
|
|
{
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
|
|
/* CRT should always be at 0, but check anyway */
|
|
- if (intel_output->type != INTEL_OUTPUT_ANALOG)
|
|
+ if (intel_encoder->type != INTEL_OUTPUT_ANALOG)
|
|
return false;
|
|
|
|
- return intel_ddc_probe(intel_output);
|
|
+ return intel_ddc_probe(intel_encoder);
|
|
}
|
|
|
|
static enum drm_connector_status
|
|
-intel_crt_load_detect(struct drm_crtc *crtc, struct intel_output *intel_output)
|
|
+intel_crt_load_detect(struct drm_crtc *crtc, struct intel_encoder *intel_encoder)
|
|
{
|
|
- struct drm_encoder *encoder = &intel_output->enc;
|
|
+ struct drm_encoder *encoder = &intel_encoder->enc;
|
|
struct drm_device *dev = encoder->dev;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
@@ -386,8 +403,8 @@ intel_crt_load_detect(struct drm_crtc *crtc, struct intel_output *intel_output)
|
|
static enum drm_connector_status intel_crt_detect(struct drm_connector *connector)
|
|
{
|
|
struct drm_device *dev = connector->dev;
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
- struct drm_encoder *encoder = &intel_output->enc;
|
|
+ struct drm_encoder *encoder = intel_attached_encoder(connector);
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
struct drm_crtc *crtc;
|
|
int dpms_mode;
|
|
enum drm_connector_status status;
|
|
@@ -399,18 +416,19 @@ static enum drm_connector_status intel_crt_detect(struct drm_connector *connecto
|
|
return connector_status_disconnected;
|
|
}
|
|
|
|
- if (intel_crt_detect_ddc(connector))
|
|
+ if (intel_crt_detect_ddc(encoder))
|
|
return connector_status_connected;
|
|
|
|
/* for pre-945g platforms use load detect */
|
|
if (encoder->crtc && encoder->crtc->enabled) {
|
|
- status = intel_crt_load_detect(encoder->crtc, intel_output);
|
|
+ status = intel_crt_load_detect(encoder->crtc, intel_encoder);
|
|
} else {
|
|
- crtc = intel_get_load_detect_pipe(intel_output,
|
|
+ crtc = intel_get_load_detect_pipe(intel_encoder, connector,
|
|
NULL, &dpms_mode);
|
|
if (crtc) {
|
|
- status = intel_crt_load_detect(crtc, intel_output);
|
|
- intel_release_load_detect_pipe(intel_output, dpms_mode);
|
|
+ status = intel_crt_load_detect(crtc, intel_encoder);
|
|
+ intel_release_load_detect_pipe(intel_encoder,
|
|
+ connector, dpms_mode);
|
|
} else
|
|
status = connector_status_unknown;
|
|
}
|
|
@@ -420,9 +438,6 @@ static enum drm_connector_status intel_crt_detect(struct drm_connector *connecto
|
|
|
|
static void intel_crt_destroy(struct drm_connector *connector)
|
|
{
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
-
|
|
- intel_i2c_destroy(intel_output->ddc_bus);
|
|
drm_sysfs_connector_remove(connector);
|
|
drm_connector_cleanup(connector);
|
|
kfree(connector);
|
|
@@ -431,29 +446,27 @@ static void intel_crt_destroy(struct drm_connector *connector)
|
|
static int intel_crt_get_modes(struct drm_connector *connector)
|
|
{
|
|
int ret;
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
- struct i2c_adapter *ddcbus;
|
|
+ struct drm_encoder *encoder = intel_attached_encoder(connector);
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ struct i2c_adapter *ddc_bus;
|
|
struct drm_device *dev = connector->dev;
|
|
|
|
|
|
- ret = intel_ddc_get_modes(intel_output);
|
|
+ ret = intel_ddc_get_modes(connector, intel_encoder->ddc_bus);
|
|
if (ret || !IS_G4X(dev))
|
|
goto end;
|
|
|
|
- ddcbus = intel_output->ddc_bus;
|
|
/* Try to probe digital port for output in DVI-I -> VGA mode. */
|
|
- intel_output->ddc_bus =
|
|
- intel_i2c_create(connector->dev, GPIOD, "CRTDDC_D");
|
|
+ ddc_bus = intel_i2c_create(connector->dev, GPIOD, "CRTDDC_D");
|
|
|
|
- if (!intel_output->ddc_bus) {
|
|
- intel_output->ddc_bus = ddcbus;
|
|
+ if (!ddc_bus) {
|
|
dev_printk(KERN_ERR, &connector->dev->pdev->dev,
|
|
"DDC bus registration failed for CRTDDC_D.\n");
|
|
goto end;
|
|
}
|
|
/* Try to get modes by GPIOD port */
|
|
- ret = intel_ddc_get_modes(intel_output);
|
|
- intel_i2c_destroy(ddcbus);
|
|
+ ret = intel_ddc_get_modes(connector, ddc_bus);
|
|
+ intel_i2c_destroy(ddc_bus);
|
|
|
|
end:
|
|
return ret;
|
|
@@ -490,12 +503,16 @@ static const struct drm_connector_funcs intel_crt_connector_funcs = {
|
|
static const struct drm_connector_helper_funcs intel_crt_connector_helper_funcs = {
|
|
.mode_valid = intel_crt_mode_valid,
|
|
.get_modes = intel_crt_get_modes,
|
|
- .best_encoder = intel_best_encoder,
|
|
+ .best_encoder = intel_attached_encoder,
|
|
};
|
|
|
|
static void intel_crt_enc_destroy(struct drm_encoder *encoder)
|
|
{
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+
|
|
+ intel_i2c_destroy(intel_encoder->ddc_bus);
|
|
drm_encoder_cleanup(encoder);
|
|
+ kfree(intel_encoder);
|
|
}
|
|
|
|
static const struct drm_encoder_funcs intel_crt_enc_funcs = {
|
|
@@ -505,26 +522,33 @@ static const struct drm_encoder_funcs intel_crt_enc_funcs = {
|
|
void intel_crt_init(struct drm_device *dev)
|
|
{
|
|
struct drm_connector *connector;
|
|
- struct intel_output *intel_output;
|
|
+ struct intel_encoder *intel_encoder;
|
|
+ struct intel_connector *intel_connector;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
u32 i2c_reg;
|
|
|
|
- intel_output = kzalloc(sizeof(struct intel_output), GFP_KERNEL);
|
|
- if (!intel_output)
|
|
+ intel_encoder = kzalloc(sizeof(struct intel_encoder), GFP_KERNEL);
|
|
+ if (!intel_encoder)
|
|
return;
|
|
|
|
- connector = &intel_output->base;
|
|
- drm_connector_init(dev, &intel_output->base,
|
|
+ intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
|
|
+ if (!intel_connector) {
|
|
+ kfree(intel_encoder);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ connector = &intel_connector->base;
|
|
+ drm_connector_init(dev, &intel_connector->base,
|
|
&intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA);
|
|
|
|
- drm_encoder_init(dev, &intel_output->enc, &intel_crt_enc_funcs,
|
|
+ drm_encoder_init(dev, &intel_encoder->enc, &intel_crt_enc_funcs,
|
|
DRM_MODE_ENCODER_DAC);
|
|
|
|
- drm_mode_connector_attach_encoder(&intel_output->base,
|
|
- &intel_output->enc);
|
|
+ drm_mode_connector_attach_encoder(&intel_connector->base,
|
|
+ &intel_encoder->enc);
|
|
|
|
/* Set up the DDC bus. */
|
|
- if (IS_IRONLAKE(dev))
|
|
+ if (HAS_PCH_SPLIT(dev))
|
|
i2c_reg = PCH_GPIOA;
|
|
else {
|
|
i2c_reg = GPIOA;
|
|
@@ -532,22 +556,22 @@ void intel_crt_init(struct drm_device *dev)
|
|
if (dev_priv->crt_ddc_bus != 0)
|
|
i2c_reg = dev_priv->crt_ddc_bus;
|
|
}
|
|
- intel_output->ddc_bus = intel_i2c_create(dev, i2c_reg, "CRTDDC_A");
|
|
- if (!intel_output->ddc_bus) {
|
|
+ intel_encoder->ddc_bus = intel_i2c_create(dev, i2c_reg, "CRTDDC_A");
|
|
+ if (!intel_encoder->ddc_bus) {
|
|
dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration "
|
|
"failed.\n");
|
|
return;
|
|
}
|
|
|
|
- intel_output->type = INTEL_OUTPUT_ANALOG;
|
|
- intel_output->clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
|
|
+ intel_encoder->type = INTEL_OUTPUT_ANALOG;
|
|
+ intel_encoder->clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
|
|
(1 << INTEL_ANALOG_CLONE_BIT) |
|
|
(1 << INTEL_SDVO_LVDS_CLONE_BIT);
|
|
- intel_output->crtc_mask = (1 << 0) | (1 << 1);
|
|
+ intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
|
|
connector->interlace_allowed = 0;
|
|
connector->doublescan_allowed = 0;
|
|
|
|
- drm_encoder_helper_add(&intel_output->enc, &intel_crt_helper_funcs);
|
|
+ drm_encoder_helper_add(&intel_encoder->enc, &intel_crt_helper_funcs);
|
|
drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);
|
|
|
|
drm_sysfs_connector_add(connector);
|
|
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
|
|
--- a/drivers/gpu/drm/i915/intel_display.c
|
|
+++ b/drivers/gpu/drm/i915/intel_display.c
|
|
@@ -232,7 +232,7 @@ struct intel_limit {
|
|
#define G4X_P2_DISPLAY_PORT_FAST 10
|
|
#define G4X_P2_DISPLAY_PORT_LIMIT 0
|
|
|
|
-/* Ironlake */
|
|
+/* Ironlake / Sandybridge */
|
|
/* as we calculate clock using (register_value + 2) for
|
|
N/M1/M2, so here the range value for them is (actual_value-2).
|
|
*/
|
|
@@ -690,7 +690,7 @@ static const intel_limit_t *intel_limit(struct drm_crtc *crtc)
|
|
struct drm_device *dev = crtc->dev;
|
|
const intel_limit_t *limit;
|
|
|
|
- if (IS_IRONLAKE(dev))
|
|
+ if (HAS_PCH_SPLIT(dev))
|
|
limit = intel_ironlake_limit(crtc);
|
|
else if (IS_G4X(dev)) {
|
|
limit = intel_g4x_limit(crtc);
|
|
@@ -741,36 +741,18 @@ bool intel_pipe_has_type (struct drm_crtc *crtc, int type)
|
|
{
|
|
struct drm_device *dev = crtc->dev;
|
|
struct drm_mode_config *mode_config = &dev->mode_config;
|
|
- struct drm_connector *l_entry;
|
|
+ struct drm_encoder *l_entry;
|
|
|
|
- list_for_each_entry(l_entry, &mode_config->connector_list, head) {
|
|
- if (l_entry->encoder &&
|
|
- l_entry->encoder->crtc == crtc) {
|
|
- struct intel_output *intel_output = to_intel_output(l_entry);
|
|
- if (intel_output->type == type)
|
|
+ list_for_each_entry(l_entry, &mode_config->encoder_list, head) {
|
|
+ if (l_entry && l_entry->crtc == crtc) {
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(l_entry);
|
|
+ if (intel_encoder->type == type)
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
-struct drm_connector *
|
|
-intel_pipe_get_output (struct drm_crtc *crtc)
|
|
-{
|
|
- struct drm_device *dev = crtc->dev;
|
|
- struct drm_mode_config *mode_config = &dev->mode_config;
|
|
- struct drm_connector *l_entry, *ret = NULL;
|
|
-
|
|
- list_for_each_entry(l_entry, &mode_config->connector_list, head) {
|
|
- if (l_entry->encoder &&
|
|
- l_entry->encoder->crtc == crtc) {
|
|
- ret = l_entry;
|
|
- break;
|
|
- }
|
|
- }
|
|
- return ret;
|
|
-}
|
|
-
|
|
#define INTELPllInvalid(s) do { /* DRM_DEBUG(s); */ return false; } while (0)
|
|
/**
|
|
* Returns whether the given set of divisors are valid for a given refclk with
|
|
@@ -886,7 +868,7 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
|
|
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
|
|
int lvds_reg;
|
|
|
|
- if (IS_IRONLAKE(dev))
|
|
+ if (HAS_PCH_SPLIT(dev))
|
|
lvds_reg = PCH_LVDS;
|
|
else
|
|
lvds_reg = LVDS;
|
|
@@ -1002,7 +984,7 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
struct drm_framebuffer *fb = crtc->fb;
|
|
struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
|
|
- struct drm_i915_gem_object *obj_priv = intel_fb->obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(intel_fb->obj);
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
int plane, i;
|
|
u32 fbc_ctl, fbc_ctl2;
|
|
@@ -1032,7 +1014,7 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
|
|
/* enable it... */
|
|
fbc_ctl = FBC_CTL_EN | FBC_CTL_PERIODIC;
|
|
if (IS_I945GM(dev))
|
|
- fbc_ctl |= FBC_C3_IDLE; /* 945 needs special SR handling */
|
|
+ fbc_ctl |= FBC_CTL_C3_IDLE; /* 945 needs special SR handling */
|
|
fbc_ctl |= (dev_priv->cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT;
|
|
fbc_ctl |= (interval & 0x2fff) << FBC_CTL_INTERVAL_SHIFT;
|
|
if (obj_priv->tiling_mode != I915_TILING_NONE)
|
|
@@ -1079,7 +1061,7 @@ static void g4x_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
struct drm_framebuffer *fb = crtc->fb;
|
|
struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
|
|
- struct drm_i915_gem_object *obj_priv = intel_fb->obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(intel_fb->obj);
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
int plane = (intel_crtc->plane == 0 ? DPFC_CTL_PLANEA :
|
|
DPFC_CTL_PLANEB);
|
|
@@ -1175,7 +1157,7 @@ static void intel_update_fbc(struct drm_crtc *crtc,
|
|
return;
|
|
|
|
intel_fb = to_intel_framebuffer(fb);
|
|
- obj_priv = intel_fb->obj->driver_private;
|
|
+ obj_priv = to_intel_bo(intel_fb->obj);
|
|
|
|
/*
|
|
* If FBC is already on, we just have to verify that we can
|
|
@@ -1188,25 +1170,30 @@ static void intel_update_fbc(struct drm_crtc *crtc,
|
|
if (intel_fb->obj->size > dev_priv->cfb_size) {
|
|
DRM_DEBUG_KMS("framebuffer too large, disabling "
|
|
"compression\n");
|
|
+ dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL;
|
|
goto out_disable;
|
|
}
|
|
if ((mode->flags & DRM_MODE_FLAG_INTERLACE) ||
|
|
(mode->flags & DRM_MODE_FLAG_DBLSCAN)) {
|
|
DRM_DEBUG_KMS("mode incompatible with compression, "
|
|
"disabling\n");
|
|
+ dev_priv->no_fbc_reason = FBC_UNSUPPORTED_MODE;
|
|
goto out_disable;
|
|
}
|
|
if ((mode->hdisplay > 2048) ||
|
|
(mode->vdisplay > 1536)) {
|
|
DRM_DEBUG_KMS("mode too large for compression, disabling\n");
|
|
+ dev_priv->no_fbc_reason = FBC_MODE_TOO_LARGE;
|
|
goto out_disable;
|
|
}
|
|
if ((IS_I915GM(dev) || IS_I945GM(dev)) && plane != 0) {
|
|
DRM_DEBUG_KMS("plane not 0, disabling compression\n");
|
|
+ dev_priv->no_fbc_reason = FBC_BAD_PLANE;
|
|
goto out_disable;
|
|
}
|
|
if (obj_priv->tiling_mode != I915_TILING_X) {
|
|
DRM_DEBUG_KMS("framebuffer not tiled, disabling compression\n");
|
|
+ dev_priv->no_fbc_reason = FBC_NOT_TILED;
|
|
goto out_disable;
|
|
}
|
|
|
|
@@ -1237,7 +1224,7 @@ out_disable:
|
|
static int
|
|
intel_pin_and_fence_fb_obj(struct drm_device *dev, struct drm_gem_object *obj)
|
|
{
|
|
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
|
+ struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
|
|
u32 alignment;
|
|
int ret;
|
|
|
|
@@ -1317,7 +1304,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
|
|
|
|
intel_fb = to_intel_framebuffer(crtc->fb);
|
|
obj = intel_fb->obj;
|
|
- obj_priv = obj->driver_private;
|
|
+ obj_priv = to_intel_bo(obj);
|
|
|
|
mutex_lock(&dev->struct_mutex);
|
|
ret = intel_pin_and_fence_fb_obj(dev, obj);
|
|
@@ -1366,7 +1353,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
|
|
dspcntr &= ~DISPPLANE_TILED;
|
|
}
|
|
|
|
- if (IS_IRONLAKE(dev))
|
|
+ if (HAS_PCH_SPLIT(dev))
|
|
/* must disable */
|
|
dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
|
|
|
|
@@ -1395,7 +1382,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
|
|
|
|
if (old_fb) {
|
|
intel_fb = to_intel_framebuffer(old_fb);
|
|
- obj_priv = intel_fb->obj->driver_private;
|
|
+ obj_priv = to_intel_bo(intel_fb->obj);
|
|
i915_gem_object_unpin(intel_fb->obj);
|
|
}
|
|
intel_increase_pllclock(crtc, true);
|
|
@@ -1427,7 +1414,7 @@ static void i915_disable_vga (struct drm_device *dev)
|
|
u8 sr1;
|
|
u32 vga_reg;
|
|
|
|
- if (IS_IRONLAKE(dev))
|
|
+ if (HAS_PCH_SPLIT(dev))
|
|
vga_reg = CPU_VGACNTRL;
|
|
else
|
|
vga_reg = VGACNTRL;
|
|
@@ -1504,6 +1491,219 @@ static void ironlake_set_pll_edp (struct drm_crtc *crtc, int clock)
|
|
udelay(500);
|
|
}
|
|
|
|
+/* The FDI link training functions for ILK/Ibexpeak. */
|
|
+static void ironlake_fdi_link_train(struct drm_crtc *crtc)
|
|
+{
|
|
+ struct drm_device *dev = crtc->dev;
|
|
+ struct drm_i915_private *dev_priv = dev->dev_private;
|
|
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
+ int pipe = intel_crtc->pipe;
|
|
+ int fdi_tx_reg = (pipe == 0) ? FDI_TXA_CTL : FDI_TXB_CTL;
|
|
+ int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL;
|
|
+ int fdi_rx_iir_reg = (pipe == 0) ? FDI_RXA_IIR : FDI_RXB_IIR;
|
|
+ int fdi_rx_imr_reg = (pipe == 0) ? FDI_RXA_IMR : FDI_RXB_IMR;
|
|
+ u32 temp, tries = 0;
|
|
+
|
|
+ /* enable CPU FDI TX and PCH FDI RX */
|
|
+ temp = I915_READ(fdi_tx_reg);
|
|
+ temp |= FDI_TX_ENABLE;
|
|
+ temp &= ~(7 << 19);
|
|
+ temp |= (intel_crtc->fdi_lanes - 1) << 19;
|
|
+ temp &= ~FDI_LINK_TRAIN_NONE;
|
|
+ temp |= FDI_LINK_TRAIN_PATTERN_1;
|
|
+ I915_WRITE(fdi_tx_reg, temp);
|
|
+ I915_READ(fdi_tx_reg);
|
|
+
|
|
+ temp = I915_READ(fdi_rx_reg);
|
|
+ temp &= ~FDI_LINK_TRAIN_NONE;
|
|
+ temp |= FDI_LINK_TRAIN_PATTERN_1;
|
|
+ I915_WRITE(fdi_rx_reg, temp | FDI_RX_ENABLE);
|
|
+ I915_READ(fdi_rx_reg);
|
|
+ udelay(150);
|
|
+
|
|
+ /* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit
|
|
+ for train result */
|
|
+ temp = I915_READ(fdi_rx_imr_reg);
|
|
+ temp &= ~FDI_RX_SYMBOL_LOCK;
|
|
+ temp &= ~FDI_RX_BIT_LOCK;
|
|
+ I915_WRITE(fdi_rx_imr_reg, temp);
|
|
+ I915_READ(fdi_rx_imr_reg);
|
|
+ udelay(150);
|
|
+
|
|
+ for (;;) {
|
|
+ temp = I915_READ(fdi_rx_iir_reg);
|
|
+ DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp);
|
|
+
|
|
+ if ((temp & FDI_RX_BIT_LOCK)) {
|
|
+ DRM_DEBUG_KMS("FDI train 1 done.\n");
|
|
+ I915_WRITE(fdi_rx_iir_reg,
|
|
+ temp | FDI_RX_BIT_LOCK);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ tries++;
|
|
+
|
|
+ if (tries > 5) {
|
|
+ DRM_DEBUG_KMS("FDI train 1 fail!\n");
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /* Train 2 */
|
|
+ temp = I915_READ(fdi_tx_reg);
|
|
+ temp &= ~FDI_LINK_TRAIN_NONE;
|
|
+ temp |= FDI_LINK_TRAIN_PATTERN_2;
|
|
+ I915_WRITE(fdi_tx_reg, temp);
|
|
+
|
|
+ temp = I915_READ(fdi_rx_reg);
|
|
+ temp &= ~FDI_LINK_TRAIN_NONE;
|
|
+ temp |= FDI_LINK_TRAIN_PATTERN_2;
|
|
+ I915_WRITE(fdi_rx_reg, temp);
|
|
+ udelay(150);
|
|
+
|
|
+ tries = 0;
|
|
+
|
|
+ for (;;) {
|
|
+ temp = I915_READ(fdi_rx_iir_reg);
|
|
+ DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp);
|
|
+
|
|
+ if (temp & FDI_RX_SYMBOL_LOCK) {
|
|
+ I915_WRITE(fdi_rx_iir_reg,
|
|
+ temp | FDI_RX_SYMBOL_LOCK);
|
|
+ DRM_DEBUG_KMS("FDI train 2 done.\n");
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ tries++;
|
|
+
|
|
+ if (tries > 5) {
|
|
+ DRM_DEBUG_KMS("FDI train 2 fail!\n");
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ DRM_DEBUG_KMS("FDI train done\n");
|
|
+}
|
|
+
|
|
+static int snb_b_fdi_train_param [] = {
|
|
+ FDI_LINK_TRAIN_400MV_0DB_SNB_B,
|
|
+ FDI_LINK_TRAIN_400MV_6DB_SNB_B,
|
|
+ FDI_LINK_TRAIN_600MV_3_5DB_SNB_B,
|
|
+ FDI_LINK_TRAIN_800MV_0DB_SNB_B,
|
|
+};
|
|
+
|
|
+/* The FDI link training functions for SNB/Cougarpoint. */
|
|
+static void gen6_fdi_link_train(struct drm_crtc *crtc)
|
|
+{
|
|
+ struct drm_device *dev = crtc->dev;
|
|
+ struct drm_i915_private *dev_priv = dev->dev_private;
|
|
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
+ int pipe = intel_crtc->pipe;
|
|
+ int fdi_tx_reg = (pipe == 0) ? FDI_TXA_CTL : FDI_TXB_CTL;
|
|
+ int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL;
|
|
+ int fdi_rx_iir_reg = (pipe == 0) ? FDI_RXA_IIR : FDI_RXB_IIR;
|
|
+ int fdi_rx_imr_reg = (pipe == 0) ? FDI_RXA_IMR : FDI_RXB_IMR;
|
|
+ u32 temp, i;
|
|
+
|
|
+ /* enable CPU FDI TX and PCH FDI RX */
|
|
+ temp = I915_READ(fdi_tx_reg);
|
|
+ temp |= FDI_TX_ENABLE;
|
|
+ temp &= ~(7 << 19);
|
|
+ temp |= (intel_crtc->fdi_lanes - 1) << 19;
|
|
+ temp &= ~FDI_LINK_TRAIN_NONE;
|
|
+ temp |= FDI_LINK_TRAIN_PATTERN_1;
|
|
+ temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
|
|
+ /* SNB-B */
|
|
+ temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B;
|
|
+ I915_WRITE(fdi_tx_reg, temp);
|
|
+ I915_READ(fdi_tx_reg);
|
|
+
|
|
+ temp = I915_READ(fdi_rx_reg);
|
|
+ if (HAS_PCH_CPT(dev)) {
|
|
+ temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
|
|
+ temp |= FDI_LINK_TRAIN_PATTERN_1_CPT;
|
|
+ } else {
|
|
+ temp &= ~FDI_LINK_TRAIN_NONE;
|
|
+ temp |= FDI_LINK_TRAIN_PATTERN_1;
|
|
+ }
|
|
+ I915_WRITE(fdi_rx_reg, temp | FDI_RX_ENABLE);
|
|
+ I915_READ(fdi_rx_reg);
|
|
+ udelay(150);
|
|
+
|
|
+ /* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit
|
|
+ for train result */
|
|
+ temp = I915_READ(fdi_rx_imr_reg);
|
|
+ temp &= ~FDI_RX_SYMBOL_LOCK;
|
|
+ temp &= ~FDI_RX_BIT_LOCK;
|
|
+ I915_WRITE(fdi_rx_imr_reg, temp);
|
|
+ I915_READ(fdi_rx_imr_reg);
|
|
+ udelay(150);
|
|
+
|
|
+ for (i = 0; i < 4; i++ ) {
|
|
+ temp = I915_READ(fdi_tx_reg);
|
|
+ temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
|
|
+ temp |= snb_b_fdi_train_param[i];
|
|
+ I915_WRITE(fdi_tx_reg, temp);
|
|
+ udelay(500);
|
|
+
|
|
+ temp = I915_READ(fdi_rx_iir_reg);
|
|
+ DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp);
|
|
+
|
|
+ if (temp & FDI_RX_BIT_LOCK) {
|
|
+ I915_WRITE(fdi_rx_iir_reg,
|
|
+ temp | FDI_RX_BIT_LOCK);
|
|
+ DRM_DEBUG_KMS("FDI train 1 done.\n");
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ if (i == 4)
|
|
+ DRM_DEBUG_KMS("FDI train 1 fail!\n");
|
|
+
|
|
+ /* Train 2 */
|
|
+ temp = I915_READ(fdi_tx_reg);
|
|
+ temp &= ~FDI_LINK_TRAIN_NONE;
|
|
+ temp |= FDI_LINK_TRAIN_PATTERN_2;
|
|
+ if (IS_GEN6(dev)) {
|
|
+ temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
|
|
+ /* SNB-B */
|
|
+ temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B;
|
|
+ }
|
|
+ I915_WRITE(fdi_tx_reg, temp);
|
|
+
|
|
+ temp = I915_READ(fdi_rx_reg);
|
|
+ if (HAS_PCH_CPT(dev)) {
|
|
+ temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
|
|
+ temp |= FDI_LINK_TRAIN_PATTERN_2_CPT;
|
|
+ } else {
|
|
+ temp &= ~FDI_LINK_TRAIN_NONE;
|
|
+ temp |= FDI_LINK_TRAIN_PATTERN_2;
|
|
+ }
|
|
+ I915_WRITE(fdi_rx_reg, temp);
|
|
+ udelay(150);
|
|
+
|
|
+ for (i = 0; i < 4; i++ ) {
|
|
+ temp = I915_READ(fdi_tx_reg);
|
|
+ temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
|
|
+ temp |= snb_b_fdi_train_param[i];
|
|
+ I915_WRITE(fdi_tx_reg, temp);
|
|
+ udelay(500);
|
|
+
|
|
+ temp = I915_READ(fdi_rx_iir_reg);
|
|
+ DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp);
|
|
+
|
|
+ if (temp & FDI_RX_SYMBOL_LOCK) {
|
|
+ I915_WRITE(fdi_rx_iir_reg,
|
|
+ temp | FDI_RX_SYMBOL_LOCK);
|
|
+ DRM_DEBUG_KMS("FDI train 2 done.\n");
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ if (i == 4)
|
|
+ DRM_DEBUG_KMS("FDI train 2 fail!\n");
|
|
+
|
|
+ DRM_DEBUG_KMS("FDI train done.\n");
|
|
+}
|
|
+
|
|
static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
|
|
{
|
|
struct drm_device *dev = crtc->dev;
|
|
@@ -1517,8 +1717,6 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
|
|
int dspbase_reg = (plane == 0) ? DSPAADDR : DSPBADDR;
|
|
int fdi_tx_reg = (pipe == 0) ? FDI_TXA_CTL : FDI_TXB_CTL;
|
|
int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL;
|
|
- int fdi_rx_iir_reg = (pipe == 0) ? FDI_RXA_IIR : FDI_RXB_IIR;
|
|
- int fdi_rx_imr_reg = (pipe == 0) ? FDI_RXA_IMR : FDI_RXB_IMR;
|
|
int transconf_reg = (pipe == 0) ? TRANSACONF : TRANSBCONF;
|
|
int pf_ctl_reg = (pipe == 0) ? PFA_CTL_1 : PFB_CTL_1;
|
|
int pf_win_size = (pipe == 0) ? PFA_WIN_SZ : PFB_WIN_SZ;
|
|
@@ -1535,8 +1733,9 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
|
|
int trans_vtot_reg = (pipe == 0) ? TRANS_VTOTAL_A : TRANS_VTOTAL_B;
|
|
int trans_vblank_reg = (pipe == 0) ? TRANS_VBLANK_A : TRANS_VBLANK_B;
|
|
int trans_vsync_reg = (pipe == 0) ? TRANS_VSYNC_A : TRANS_VSYNC_B;
|
|
+ int trans_dpll_sel = (pipe == 0) ? 0 : 1;
|
|
u32 temp;
|
|
- int tries = 5, j, n;
|
|
+ int n;
|
|
u32 pipe_bpc;
|
|
|
|
temp = I915_READ(pipeconf_reg);
|
|
@@ -1563,12 +1762,6 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
|
|
/* enable eDP PLL */
|
|
ironlake_enable_pll_edp(crtc);
|
|
} else {
|
|
- /* enable PCH DPLL */
|
|
- temp = I915_READ(pch_dpll_reg);
|
|
- if ((temp & DPLL_VCO_ENABLE) == 0) {
|
|
- I915_WRITE(pch_dpll_reg, temp | DPLL_VCO_ENABLE);
|
|
- I915_READ(pch_dpll_reg);
|
|
- }
|
|
|
|
/* enable PCH FDI RX PLL, wait warmup plus DMI latency */
|
|
temp = I915_READ(fdi_rx_reg);
|
|
@@ -1578,9 +1771,15 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
|
|
*/
|
|
temp &= ~(0x7 << 16);
|
|
temp |= (pipe_bpc << 11);
|
|
- I915_WRITE(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE |
|
|
- FDI_SEL_PCDCLK |
|
|
- FDI_DP_PORT_WIDTH_X4); /* default 4 lanes */
|
|
+ temp &= ~(7 << 19);
|
|
+ temp |= (intel_crtc->fdi_lanes - 1) << 19;
|
|
+ I915_WRITE(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE);
|
|
+ I915_READ(fdi_rx_reg);
|
|
+ udelay(200);
|
|
+
|
|
+ /* Switch from Rawclk to PCDclk */
|
|
+ temp = I915_READ(fdi_rx_reg);
|
|
+ I915_WRITE(fdi_rx_reg, temp | FDI_SEL_PCDCLK);
|
|
I915_READ(fdi_rx_reg);
|
|
udelay(200);
|
|
|
|
@@ -1623,91 +1822,32 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
|
|
}
|
|
|
|
if (!HAS_eDP) {
|
|
- /* enable CPU FDI TX and PCH FDI RX */
|
|
- temp = I915_READ(fdi_tx_reg);
|
|
- temp |= FDI_TX_ENABLE;
|
|
- temp |= FDI_DP_PORT_WIDTH_X4; /* default */
|
|
- temp &= ~FDI_LINK_TRAIN_NONE;
|
|
- temp |= FDI_LINK_TRAIN_PATTERN_1;
|
|
- I915_WRITE(fdi_tx_reg, temp);
|
|
- I915_READ(fdi_tx_reg);
|
|
-
|
|
- temp = I915_READ(fdi_rx_reg);
|
|
- temp &= ~FDI_LINK_TRAIN_NONE;
|
|
- temp |= FDI_LINK_TRAIN_PATTERN_1;
|
|
- I915_WRITE(fdi_rx_reg, temp | FDI_RX_ENABLE);
|
|
- I915_READ(fdi_rx_reg);
|
|
-
|
|
- udelay(150);
|
|
-
|
|
- /* Train FDI. */
|
|
- /* umask FDI RX Interrupt symbol_lock and bit_lock bit
|
|
- for train result */
|
|
- temp = I915_READ(fdi_rx_imr_reg);
|
|
- temp &= ~FDI_RX_SYMBOL_LOCK;
|
|
- temp &= ~FDI_RX_BIT_LOCK;
|
|
- I915_WRITE(fdi_rx_imr_reg, temp);
|
|
- I915_READ(fdi_rx_imr_reg);
|
|
- udelay(150);
|
|
+ /* For PCH output, training FDI link */
|
|
+ if (IS_GEN6(dev))
|
|
+ gen6_fdi_link_train(crtc);
|
|
+ else
|
|
+ ironlake_fdi_link_train(crtc);
|
|
|
|
- temp = I915_READ(fdi_rx_iir_reg);
|
|
- DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp);
|
|
-
|
|
- if ((temp & FDI_RX_BIT_LOCK) == 0) {
|
|
- for (j = 0; j < tries; j++) {
|
|
- temp = I915_READ(fdi_rx_iir_reg);
|
|
- DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n",
|
|
- temp);
|
|
- if (temp & FDI_RX_BIT_LOCK)
|
|
- break;
|
|
- udelay(200);
|
|
- }
|
|
- if (j != tries)
|
|
- I915_WRITE(fdi_rx_iir_reg,
|
|
- temp | FDI_RX_BIT_LOCK);
|
|
- else
|
|
- DRM_DEBUG_KMS("train 1 fail\n");
|
|
- } else {
|
|
- I915_WRITE(fdi_rx_iir_reg,
|
|
- temp | FDI_RX_BIT_LOCK);
|
|
- DRM_DEBUG_KMS("train 1 ok 2!\n");
|
|
+ /* enable PCH DPLL */
|
|
+ temp = I915_READ(pch_dpll_reg);
|
|
+ if ((temp & DPLL_VCO_ENABLE) == 0) {
|
|
+ I915_WRITE(pch_dpll_reg, temp | DPLL_VCO_ENABLE);
|
|
+ I915_READ(pch_dpll_reg);
|
|
}
|
|
- temp = I915_READ(fdi_tx_reg);
|
|
- temp &= ~FDI_LINK_TRAIN_NONE;
|
|
- temp |= FDI_LINK_TRAIN_PATTERN_2;
|
|
- I915_WRITE(fdi_tx_reg, temp);
|
|
-
|
|
- temp = I915_READ(fdi_rx_reg);
|
|
- temp &= ~FDI_LINK_TRAIN_NONE;
|
|
- temp |= FDI_LINK_TRAIN_PATTERN_2;
|
|
- I915_WRITE(fdi_rx_reg, temp);
|
|
-
|
|
- udelay(150);
|
|
+ udelay(200);
|
|
|
|
- temp = I915_READ(fdi_rx_iir_reg);
|
|
- DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp);
|
|
-
|
|
- if ((temp & FDI_RX_SYMBOL_LOCK) == 0) {
|
|
- for (j = 0; j < tries; j++) {
|
|
- temp = I915_READ(fdi_rx_iir_reg);
|
|
- DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n",
|
|
- temp);
|
|
- if (temp & FDI_RX_SYMBOL_LOCK)
|
|
- break;
|
|
- udelay(200);
|
|
- }
|
|
- if (j != tries) {
|
|
- I915_WRITE(fdi_rx_iir_reg,
|
|
- temp | FDI_RX_SYMBOL_LOCK);
|
|
- DRM_DEBUG_KMS("train 2 ok 1!\n");
|
|
- } else
|
|
- DRM_DEBUG_KMS("train 2 fail\n");
|
|
- } else {
|
|
- I915_WRITE(fdi_rx_iir_reg,
|
|
- temp | FDI_RX_SYMBOL_LOCK);
|
|
- DRM_DEBUG_KMS("train 2 ok 2!\n");
|
|
+ if (HAS_PCH_CPT(dev)) {
|
|
+ /* Be sure PCH DPLL SEL is set */
|
|
+ temp = I915_READ(PCH_DPLL_SEL);
|
|
+ if (trans_dpll_sel == 0 &&
|
|
+ (temp & TRANSA_DPLL_ENABLE) == 0)
|
|
+ temp |= (TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL);
|
|
+ else if (trans_dpll_sel == 1 &&
|
|
+ (temp & TRANSB_DPLL_ENABLE) == 0)
|
|
+ temp |= (TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL);
|
|
+ I915_WRITE(PCH_DPLL_SEL, temp);
|
|
+ I915_READ(PCH_DPLL_SEL);
|
|
}
|
|
- DRM_DEBUG_KMS("train done\n");
|
|
|
|
/* set transcoder timing */
|
|
I915_WRITE(trans_htot_reg, I915_READ(cpu_htot_reg));
|
|
@@ -1718,6 +1858,60 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
|
|
I915_WRITE(trans_vblank_reg, I915_READ(cpu_vblank_reg));
|
|
I915_WRITE(trans_vsync_reg, I915_READ(cpu_vsync_reg));
|
|
|
|
+ /* enable normal train */
|
|
+ temp = I915_READ(fdi_tx_reg);
|
|
+ temp &= ~FDI_LINK_TRAIN_NONE;
|
|
+ I915_WRITE(fdi_tx_reg, temp | FDI_LINK_TRAIN_NONE |
|
|
+ FDI_TX_ENHANCE_FRAME_ENABLE);
|
|
+ I915_READ(fdi_tx_reg);
|
|
+
|
|
+ temp = I915_READ(fdi_rx_reg);
|
|
+ if (HAS_PCH_CPT(dev)) {
|
|
+ temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
|
|
+ temp |= FDI_LINK_TRAIN_NORMAL_CPT;
|
|
+ } else {
|
|
+ temp &= ~FDI_LINK_TRAIN_NONE;
|
|
+ temp |= FDI_LINK_TRAIN_NONE;
|
|
+ }
|
|
+ I915_WRITE(fdi_rx_reg, temp | FDI_RX_ENHANCE_FRAME_ENABLE);
|
|
+ I915_READ(fdi_rx_reg);
|
|
+
|
|
+ /* wait one idle pattern time */
|
|
+ udelay(100);
|
|
+
|
|
+ /* For PCH DP, enable TRANS_DP_CTL */
|
|
+ if (HAS_PCH_CPT(dev) &&
|
|
+ intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) {
|
|
+ int trans_dp_ctl = (pipe == 0) ? TRANS_DP_CTL_A : TRANS_DP_CTL_B;
|
|
+ int reg;
|
|
+
|
|
+ reg = I915_READ(trans_dp_ctl);
|
|
+ reg &= ~TRANS_DP_PORT_SEL_MASK;
|
|
+ reg = TRANS_DP_OUTPUT_ENABLE |
|
|
+ TRANS_DP_ENH_FRAMING |
|
|
+ TRANS_DP_VSYNC_ACTIVE_HIGH |
|
|
+ TRANS_DP_HSYNC_ACTIVE_HIGH;
|
|
+
|
|
+ switch (intel_trans_dp_port_sel(crtc)) {
|
|
+ case PCH_DP_B:
|
|
+ reg |= TRANS_DP_PORT_SEL_B;
|
|
+ break;
|
|
+ case PCH_DP_C:
|
|
+ reg |= TRANS_DP_PORT_SEL_C;
|
|
+ break;
|
|
+ case PCH_DP_D:
|
|
+ reg |= TRANS_DP_PORT_SEL_D;
|
|
+ break;
|
|
+ default:
|
|
+ DRM_DEBUG_KMS("Wrong PCH DP port return. Guess port B\n");
|
|
+ reg |= TRANS_DP_PORT_SEL_B;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ I915_WRITE(trans_dp_ctl, reg);
|
|
+ POSTING_READ(trans_dp_ctl);
|
|
+ }
|
|
+
|
|
/* enable PCH transcoder */
|
|
temp = I915_READ(transconf_reg);
|
|
/*
|
|
@@ -1732,23 +1926,6 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
|
|
while ((I915_READ(transconf_reg) & TRANS_STATE_ENABLE) == 0)
|
|
;
|
|
|
|
- /* enable normal */
|
|
-
|
|
- temp = I915_READ(fdi_tx_reg);
|
|
- temp &= ~FDI_LINK_TRAIN_NONE;
|
|
- I915_WRITE(fdi_tx_reg, temp | FDI_LINK_TRAIN_NONE |
|
|
- FDI_TX_ENHANCE_FRAME_ENABLE);
|
|
- I915_READ(fdi_tx_reg);
|
|
-
|
|
- temp = I915_READ(fdi_rx_reg);
|
|
- temp &= ~FDI_LINK_TRAIN_NONE;
|
|
- I915_WRITE(fdi_rx_reg, temp | FDI_LINK_TRAIN_NONE |
|
|
- FDI_RX_ENHANCE_FRAME_ENABLE);
|
|
- I915_READ(fdi_rx_reg);
|
|
-
|
|
- /* wait one idle pattern time */
|
|
- udelay(100);
|
|
-
|
|
}
|
|
|
|
intel_crtc_load_lut(crtc);
|
|
@@ -1799,6 +1976,8 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
|
|
I915_READ(pf_ctl_reg);
|
|
}
|
|
I915_WRITE(pf_win_size, 0);
|
|
+ POSTING_READ(pf_win_size);
|
|
+
|
|
|
|
/* disable CPU FDI tx and PCH FDI rx */
|
|
temp = I915_READ(fdi_tx_reg);
|
|
@@ -1819,11 +1998,18 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
|
|
temp &= ~FDI_LINK_TRAIN_NONE;
|
|
temp |= FDI_LINK_TRAIN_PATTERN_1;
|
|
I915_WRITE(fdi_tx_reg, temp);
|
|
+ POSTING_READ(fdi_tx_reg);
|
|
|
|
temp = I915_READ(fdi_rx_reg);
|
|
- temp &= ~FDI_LINK_TRAIN_NONE;
|
|
- temp |= FDI_LINK_TRAIN_PATTERN_1;
|
|
+ if (HAS_PCH_CPT(dev)) {
|
|
+ temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
|
|
+ temp |= FDI_LINK_TRAIN_PATTERN_1_CPT;
|
|
+ } else {
|
|
+ temp &= ~FDI_LINK_TRAIN_NONE;
|
|
+ temp |= FDI_LINK_TRAIN_PATTERN_1;
|
|
+ }
|
|
I915_WRITE(fdi_rx_reg, temp);
|
|
+ POSTING_READ(fdi_rx_reg);
|
|
|
|
udelay(100);
|
|
|
|
@@ -1853,6 +2039,7 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
|
|
}
|
|
}
|
|
}
|
|
+
|
|
temp = I915_READ(transconf_reg);
|
|
/* BPC in transcoder is consistent with that in pipeconf */
|
|
temp &= ~PIPE_BPC_MASK;
|
|
@@ -1861,35 +2048,53 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
|
|
I915_READ(transconf_reg);
|
|
udelay(100);
|
|
|
|
+ if (HAS_PCH_CPT(dev)) {
|
|
+ /* disable TRANS_DP_CTL */
|
|
+ int trans_dp_ctl = (pipe == 0) ? TRANS_DP_CTL_A : TRANS_DP_CTL_B;
|
|
+ int reg;
|
|
+
|
|
+ reg = I915_READ(trans_dp_ctl);
|
|
+ reg &= ~(TRANS_DP_OUTPUT_ENABLE | TRANS_DP_PORT_SEL_MASK);
|
|
+ I915_WRITE(trans_dp_ctl, reg);
|
|
+ POSTING_READ(trans_dp_ctl);
|
|
+
|
|
+ /* disable DPLL_SEL */
|
|
+ temp = I915_READ(PCH_DPLL_SEL);
|
|
+ if (trans_dpll_sel == 0)
|
|
+ temp &= ~(TRANSA_DPLL_ENABLE | TRANSA_DPLLB_SEL);
|
|
+ else
|
|
+ temp &= ~(TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL);
|
|
+ I915_WRITE(PCH_DPLL_SEL, temp);
|
|
+ I915_READ(PCH_DPLL_SEL);
|
|
+
|
|
+ }
|
|
+
|
|
/* disable PCH DPLL */
|
|
temp = I915_READ(pch_dpll_reg);
|
|
- if ((temp & DPLL_VCO_ENABLE) != 0) {
|
|
- I915_WRITE(pch_dpll_reg, temp & ~DPLL_VCO_ENABLE);
|
|
- I915_READ(pch_dpll_reg);
|
|
- }
|
|
+ I915_WRITE(pch_dpll_reg, temp & ~DPLL_VCO_ENABLE);
|
|
+ I915_READ(pch_dpll_reg);
|
|
|
|
if (HAS_eDP) {
|
|
ironlake_disable_pll_edp(crtc);
|
|
}
|
|
|
|
+ /* Switch from PCDclk to Rawclk */
|
|
temp = I915_READ(fdi_rx_reg);
|
|
temp &= ~FDI_SEL_PCDCLK;
|
|
I915_WRITE(fdi_rx_reg, temp);
|
|
I915_READ(fdi_rx_reg);
|
|
|
|
+ /* Disable CPU FDI TX PLL */
|
|
+ temp = I915_READ(fdi_tx_reg);
|
|
+ I915_WRITE(fdi_tx_reg, temp & ~FDI_TX_PLL_ENABLE);
|
|
+ I915_READ(fdi_tx_reg);
|
|
+ udelay(100);
|
|
+
|
|
temp = I915_READ(fdi_rx_reg);
|
|
temp &= ~FDI_RX_PLL_ENABLE;
|
|
I915_WRITE(fdi_rx_reg, temp);
|
|
I915_READ(fdi_rx_reg);
|
|
|
|
- /* Disable CPU FDI TX PLL */
|
|
- temp = I915_READ(fdi_tx_reg);
|
|
- if ((temp & FDI_TX_PLL_ENABLE) != 0) {
|
|
- I915_WRITE(fdi_tx_reg, temp & ~FDI_TX_PLL_ENABLE);
|
|
- I915_READ(fdi_tx_reg);
|
|
- udelay(100);
|
|
- }
|
|
-
|
|
/* Wait for the clocks to turn off. */
|
|
udelay(100);
|
|
break;
|
|
@@ -2111,7 +2316,7 @@ static bool intel_crtc_mode_fixup(struct drm_crtc *crtc,
|
|
struct drm_display_mode *adjusted_mode)
|
|
{
|
|
struct drm_device *dev = crtc->dev;
|
|
- if (IS_IRONLAKE(dev)) {
|
|
+ if (HAS_PCH_SPLIT(dev)) {
|
|
/* FDI link clock is fixed at 2.7G */
|
|
if (mode->clock * 3 > 27000 * 4)
|
|
return MODE_CLOCK_HIGH;
|
|
@@ -2325,6 +2530,30 @@ static struct intel_watermark_params i830_wm_info = {
|
|
I830_FIFO_LINE_SIZE
|
|
};
|
|
|
|
+static struct intel_watermark_params ironlake_display_wm_info = {
|
|
+ ILK_DISPLAY_FIFO,
|
|
+ ILK_DISPLAY_MAXWM,
|
|
+ ILK_DISPLAY_DFTWM,
|
|
+ 2,
|
|
+ ILK_FIFO_LINE_SIZE
|
|
+};
|
|
+
|
|
+static struct intel_watermark_params ironlake_display_srwm_info = {
|
|
+ ILK_DISPLAY_SR_FIFO,
|
|
+ ILK_DISPLAY_MAX_SRWM,
|
|
+ ILK_DISPLAY_DFT_SRWM,
|
|
+ 2,
|
|
+ ILK_FIFO_LINE_SIZE
|
|
+};
|
|
+
|
|
+static struct intel_watermark_params ironlake_cursor_srwm_info = {
|
|
+ ILK_CURSOR_SR_FIFO,
|
|
+ ILK_CURSOR_MAX_SRWM,
|
|
+ ILK_CURSOR_DFT_SRWM,
|
|
+ 2,
|
|
+ ILK_FIFO_LINE_SIZE
|
|
+};
|
|
+
|
|
/**
|
|
* intel_calculate_wm - calculate watermark level
|
|
* @clock_in_khz: pixel clock
|
|
@@ -2443,66 +2672,6 @@ static void pineview_disable_cxsr(struct drm_device *dev)
|
|
DRM_INFO("Big FIFO is disabled\n");
|
|
}
|
|
|
|
-static void pineview_enable_cxsr(struct drm_device *dev, unsigned long clock,
|
|
- int pixel_size)
|
|
-{
|
|
- struct drm_i915_private *dev_priv = dev->dev_private;
|
|
- u32 reg;
|
|
- unsigned long wm;
|
|
- struct cxsr_latency *latency;
|
|
-
|
|
- latency = intel_get_cxsr_latency(IS_PINEVIEW_G(dev), dev_priv->fsb_freq,
|
|
- dev_priv->mem_freq);
|
|
- if (!latency) {
|
|
- DRM_DEBUG_KMS("Unknown FSB/MEM found, disable CxSR\n");
|
|
- pineview_disable_cxsr(dev);
|
|
- return;
|
|
- }
|
|
-
|
|
- /* Display SR */
|
|
- wm = intel_calculate_wm(clock, &pineview_display_wm, pixel_size,
|
|
- latency->display_sr);
|
|
- reg = I915_READ(DSPFW1);
|
|
- reg &= 0x7fffff;
|
|
- reg |= wm << 23;
|
|
- I915_WRITE(DSPFW1, reg);
|
|
- DRM_DEBUG_KMS("DSPFW1 register is %x\n", reg);
|
|
-
|
|
- /* cursor SR */
|
|
- wm = intel_calculate_wm(clock, &pineview_cursor_wm, pixel_size,
|
|
- latency->cursor_sr);
|
|
- reg = I915_READ(DSPFW3);
|
|
- reg &= ~(0x3f << 24);
|
|
- reg |= (wm & 0x3f) << 24;
|
|
- I915_WRITE(DSPFW3, reg);
|
|
-
|
|
- /* Display HPLL off SR */
|
|
- wm = intel_calculate_wm(clock, &pineview_display_hplloff_wm,
|
|
- latency->display_hpll_disable, I915_FIFO_LINE_SIZE);
|
|
- reg = I915_READ(DSPFW3);
|
|
- reg &= 0xfffffe00;
|
|
- reg |= wm & 0x1ff;
|
|
- I915_WRITE(DSPFW3, reg);
|
|
-
|
|
- /* cursor HPLL off SR */
|
|
- wm = intel_calculate_wm(clock, &pineview_cursor_hplloff_wm, pixel_size,
|
|
- latency->cursor_hpll_disable);
|
|
- reg = I915_READ(DSPFW3);
|
|
- reg &= ~(0x3f << 16);
|
|
- reg |= (wm & 0x3f) << 16;
|
|
- I915_WRITE(DSPFW3, reg);
|
|
- DRM_DEBUG_KMS("DSPFW3 register is %x\n", reg);
|
|
-
|
|
- /* activate cxsr */
|
|
- reg = I915_READ(DSPFW3);
|
|
- reg |= PINEVIEW_SELF_REFRESH_EN;
|
|
- I915_WRITE(DSPFW3, reg);
|
|
-
|
|
- DRM_INFO("Big FIFO is enabled\n");
|
|
-
|
|
- return;
|
|
-}
|
|
-
|
|
/*
|
|
* Latency for FIFO fetches is dependent on several factors:
|
|
* - memory configuration (speed, channels)
|
|
@@ -2587,6 +2756,71 @@ static int i830_get_fifo_size(struct drm_device *dev, int plane)
|
|
return size;
|
|
}
|
|
|
|
+static void pineview_update_wm(struct drm_device *dev, int planea_clock,
|
|
+ int planeb_clock, int sr_hdisplay, int pixel_size)
|
|
+{
|
|
+ struct drm_i915_private *dev_priv = dev->dev_private;
|
|
+ u32 reg;
|
|
+ unsigned long wm;
|
|
+ struct cxsr_latency *latency;
|
|
+ int sr_clock;
|
|
+
|
|
+ latency = intel_get_cxsr_latency(IS_PINEVIEW_G(dev), dev_priv->fsb_freq,
|
|
+ dev_priv->mem_freq);
|
|
+ if (!latency) {
|
|
+ DRM_DEBUG_KMS("Unknown FSB/MEM found, disable CxSR\n");
|
|
+ pineview_disable_cxsr(dev);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (!planea_clock || !planeb_clock) {
|
|
+ sr_clock = planea_clock ? planea_clock : planeb_clock;
|
|
+
|
|
+ /* Display SR */
|
|
+ wm = intel_calculate_wm(sr_clock, &pineview_display_wm,
|
|
+ pixel_size, latency->display_sr);
|
|
+ reg = I915_READ(DSPFW1);
|
|
+ reg &= ~DSPFW_SR_MASK;
|
|
+ reg |= wm << DSPFW_SR_SHIFT;
|
|
+ I915_WRITE(DSPFW1, reg);
|
|
+ DRM_DEBUG_KMS("DSPFW1 register is %x\n", reg);
|
|
+
|
|
+ /* cursor SR */
|
|
+ wm = intel_calculate_wm(sr_clock, &pineview_cursor_wm,
|
|
+ pixel_size, latency->cursor_sr);
|
|
+ reg = I915_READ(DSPFW3);
|
|
+ reg &= ~DSPFW_CURSOR_SR_MASK;
|
|
+ reg |= (wm & 0x3f) << DSPFW_CURSOR_SR_SHIFT;
|
|
+ I915_WRITE(DSPFW3, reg);
|
|
+
|
|
+ /* Display HPLL off SR */
|
|
+ wm = intel_calculate_wm(sr_clock, &pineview_display_hplloff_wm,
|
|
+ pixel_size, latency->display_hpll_disable);
|
|
+ reg = I915_READ(DSPFW3);
|
|
+ reg &= ~DSPFW_HPLL_SR_MASK;
|
|
+ reg |= wm & DSPFW_HPLL_SR_MASK;
|
|
+ I915_WRITE(DSPFW3, reg);
|
|
+
|
|
+ /* cursor HPLL off SR */
|
|
+ wm = intel_calculate_wm(sr_clock, &pineview_cursor_hplloff_wm,
|
|
+ pixel_size, latency->cursor_hpll_disable);
|
|
+ reg = I915_READ(DSPFW3);
|
|
+ reg &= ~DSPFW_HPLL_CURSOR_MASK;
|
|
+ reg |= (wm & 0x3f) << DSPFW_HPLL_CURSOR_SHIFT;
|
|
+ I915_WRITE(DSPFW3, reg);
|
|
+ DRM_DEBUG_KMS("DSPFW3 register is %x\n", reg);
|
|
+
|
|
+ /* activate cxsr */
|
|
+ reg = I915_READ(DSPFW3);
|
|
+ reg |= PINEVIEW_SELF_REFRESH_EN;
|
|
+ I915_WRITE(DSPFW3, reg);
|
|
+ DRM_DEBUG_KMS("Self-refresh is enabled\n");
|
|
+ } else {
|
|
+ pineview_disable_cxsr(dev);
|
|
+ DRM_DEBUG_KMS("Self-refresh is disabled\n");
|
|
+ }
|
|
+}
|
|
+
|
|
static void g4x_update_wm(struct drm_device *dev, int planea_clock,
|
|
int planeb_clock, int sr_hdisplay, int pixel_size)
|
|
{
|
|
@@ -2757,11 +2991,22 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock,
|
|
srwm = total_size - sr_entries;
|
|
if (srwm < 0)
|
|
srwm = 1;
|
|
- I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN | (srwm & 0x3f));
|
|
+
|
|
+ if (IS_I945G(dev) || IS_I945GM(dev))
|
|
+ I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_FIFO_MASK | (srwm & 0xff));
|
|
+ else if (IS_I915GM(dev)) {
|
|
+ /* 915M has a smaller SRWM field */
|
|
+ I915_WRITE(FW_BLC_SELF, srwm & 0x3f);
|
|
+ I915_WRITE(INSTPM, I915_READ(INSTPM) | INSTPM_SELF_EN);
|
|
+ }
|
|
} else {
|
|
/* Turn off self refresh if both pipes are enabled */
|
|
- I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF)
|
|
- & ~FW_BLC_SELF_EN);
|
|
+ if (IS_I945G(dev) || IS_I945GM(dev)) {
|
|
+ I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF)
|
|
+ & ~FW_BLC_SELF_EN);
|
|
+ } else if (IS_I915GM(dev)) {
|
|
+ I915_WRITE(INSTPM, I915_READ(INSTPM) & ~INSTPM_SELF_EN);
|
|
+ }
|
|
}
|
|
|
|
DRM_DEBUG_KMS("Setting FIFO watermarks - A: %d, B: %d, C: %d, SR %d\n",
|
|
@@ -2796,6 +3041,108 @@ static void i830_update_wm(struct drm_device *dev, int planea_clock, int unused,
|
|
I915_WRITE(FW_BLC, fwater_lo);
|
|
}
|
|
|
|
+#define ILK_LP0_PLANE_LATENCY 700
|
|
+
|
|
+static void ironlake_update_wm(struct drm_device *dev, int planea_clock,
|
|
+ int planeb_clock, int sr_hdisplay, int pixel_size)
|
|
+{
|
|
+ struct drm_i915_private *dev_priv = dev->dev_private;
|
|
+ int planea_wm, planeb_wm, cursora_wm, cursorb_wm;
|
|
+ int sr_wm, cursor_wm;
|
|
+ unsigned long line_time_us;
|
|
+ int sr_clock, entries_required;
|
|
+ u32 reg_value;
|
|
+
|
|
+ /* Calculate and update the watermark for plane A */
|
|
+ if (planea_clock) {
|
|
+ entries_required = ((planea_clock / 1000) * pixel_size *
|
|
+ ILK_LP0_PLANE_LATENCY) / 1000;
|
|
+ entries_required = DIV_ROUND_UP(entries_required,
|
|
+ ironlake_display_wm_info.cacheline_size);
|
|
+ planea_wm = entries_required +
|
|
+ ironlake_display_wm_info.guard_size;
|
|
+
|
|
+ if (planea_wm > (int)ironlake_display_wm_info.max_wm)
|
|
+ planea_wm = ironlake_display_wm_info.max_wm;
|
|
+
|
|
+ cursora_wm = 16;
|
|
+ reg_value = I915_READ(WM0_PIPEA_ILK);
|
|
+ reg_value &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
|
|
+ reg_value |= (planea_wm << WM0_PIPE_PLANE_SHIFT) |
|
|
+ (cursora_wm & WM0_PIPE_CURSOR_MASK);
|
|
+ I915_WRITE(WM0_PIPEA_ILK, reg_value);
|
|
+ DRM_DEBUG_KMS("FIFO watermarks For pipe A - plane %d, "
|
|
+ "cursor: %d\n", planea_wm, cursora_wm);
|
|
+ }
|
|
+ /* Calculate and update the watermark for plane B */
|
|
+ if (planeb_clock) {
|
|
+ entries_required = ((planeb_clock / 1000) * pixel_size *
|
|
+ ILK_LP0_PLANE_LATENCY) / 1000;
|
|
+ entries_required = DIV_ROUND_UP(entries_required,
|
|
+ ironlake_display_wm_info.cacheline_size);
|
|
+ planeb_wm = entries_required +
|
|
+ ironlake_display_wm_info.guard_size;
|
|
+
|
|
+ if (planeb_wm > (int)ironlake_display_wm_info.max_wm)
|
|
+ planeb_wm = ironlake_display_wm_info.max_wm;
|
|
+
|
|
+ cursorb_wm = 16;
|
|
+ reg_value = I915_READ(WM0_PIPEB_ILK);
|
|
+ reg_value &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
|
|
+ reg_value |= (planeb_wm << WM0_PIPE_PLANE_SHIFT) |
|
|
+ (cursorb_wm & WM0_PIPE_CURSOR_MASK);
|
|
+ I915_WRITE(WM0_PIPEB_ILK, reg_value);
|
|
+ DRM_DEBUG_KMS("FIFO watermarks For pipe B - plane %d, "
|
|
+ "cursor: %d\n", planeb_wm, cursorb_wm);
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Calculate and update the self-refresh watermark only when one
|
|
+ * display plane is used.
|
|
+ */
|
|
+ if (!planea_clock || !planeb_clock) {
|
|
+ int line_count;
|
|
+ /* Read the self-refresh latency. The unit is 0.5us */
|
|
+ int ilk_sr_latency = I915_READ(MLTR_ILK) & ILK_SRLT_MASK;
|
|
+
|
|
+ sr_clock = planea_clock ? planea_clock : planeb_clock;
|
|
+ line_time_us = ((sr_hdisplay * 1000) / sr_clock);
|
|
+
|
|
+ /* Use ns/us then divide to preserve precision */
|
|
+ line_count = ((ilk_sr_latency * 500) / line_time_us + 1000)
|
|
+ / 1000;
|
|
+
|
|
+ /* calculate the self-refresh watermark for display plane */
|
|
+ entries_required = line_count * sr_hdisplay * pixel_size;
|
|
+ entries_required = DIV_ROUND_UP(entries_required,
|
|
+ ironlake_display_srwm_info.cacheline_size);
|
|
+ sr_wm = entries_required +
|
|
+ ironlake_display_srwm_info.guard_size;
|
|
+
|
|
+ /* calculate the self-refresh watermark for display cursor */
|
|
+ entries_required = line_count * pixel_size * 64;
|
|
+ entries_required = DIV_ROUND_UP(entries_required,
|
|
+ ironlake_cursor_srwm_info.cacheline_size);
|
|
+ cursor_wm = entries_required +
|
|
+ ironlake_cursor_srwm_info.guard_size;
|
|
+
|
|
+ /* configure watermark and enable self-refresh */
|
|
+ reg_value = I915_READ(WM1_LP_ILK);
|
|
+ reg_value &= ~(WM1_LP_LATENCY_MASK | WM1_LP_SR_MASK |
|
|
+ WM1_LP_CURSOR_MASK);
|
|
+ reg_value |= WM1_LP_SR_EN |
|
|
+ (ilk_sr_latency << WM1_LP_LATENCY_SHIFT) |
|
|
+ (sr_wm << WM1_LP_SR_SHIFT) | cursor_wm;
|
|
+
|
|
+ I915_WRITE(WM1_LP_ILK, reg_value);
|
|
+ DRM_DEBUG_KMS("self-refresh watermark: display plane %d "
|
|
+ "cursor %d\n", sr_wm, cursor_wm);
|
|
+
|
|
+ } else {
|
|
+ /* Turn off self refresh if both pipes are enabled */
|
|
+ I915_WRITE(WM1_LP_ILK, I915_READ(WM1_LP_ILK) & ~WM1_LP_SR_EN);
|
|
+ }
|
|
+}
|
|
/**
|
|
* intel_update_watermarks - update FIFO watermark values based on current modes
|
|
*
|
|
@@ -2865,12 +3212,6 @@ static void intel_update_watermarks(struct drm_device *dev)
|
|
if (enabled <= 0)
|
|
return;
|
|
|
|
- /* Single plane configs can enable self refresh */
|
|
- if (enabled == 1 && IS_PINEVIEW(dev))
|
|
- pineview_enable_cxsr(dev, sr_clock, pixel_size);
|
|
- else if (IS_PINEVIEW(dev))
|
|
- pineview_disable_cxsr(dev);
|
|
-
|
|
dev_priv->display.update_wm(dev, planea_clock, planeb_clock,
|
|
sr_hdisplay, pixel_size);
|
|
}
|
|
@@ -2900,14 +3241,15 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|
int dspsize_reg = (plane == 0) ? DSPASIZE : DSPBSIZE;
|
|
int dsppos_reg = (plane == 0) ? DSPAPOS : DSPBPOS;
|
|
int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
|
|
- int refclk, num_outputs = 0;
|
|
+ int refclk, num_connectors = 0;
|
|
intel_clock_t clock, reduced_clock;
|
|
u32 dpll = 0, fp = 0, fp2 = 0, dspcntr, pipeconf;
|
|
bool ok, has_reduced_clock = false, is_sdvo = false, is_dvo = false;
|
|
bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false;
|
|
bool is_edp = false;
|
|
struct drm_mode_config *mode_config = &dev->mode_config;
|
|
- struct drm_connector *connector;
|
|
+ struct drm_encoder *encoder;
|
|
+ struct intel_encoder *intel_encoder = NULL;
|
|
const intel_limit_t *limit;
|
|
int ret;
|
|
struct fdi_m_n m_n = {0};
|
|
@@ -2918,6 +3260,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|
int pch_fp_reg = (pipe == 0) ? PCH_FPA0 : PCH_FPB0;
|
|
int pch_dpll_reg = (pipe == 0) ? PCH_DPLL_A : PCH_DPLL_B;
|
|
int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL;
|
|
+ int fdi_tx_reg = (pipe == 0) ? FDI_TXA_CTL : FDI_TXB_CTL;
|
|
+ int trans_dpll_sel = (pipe == 0) ? 0 : 1;
|
|
int lvds_reg = LVDS;
|
|
u32 temp;
|
|
int sdvo_pixel_multiply;
|
|
@@ -2925,20 +3269,21 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|
|
|
drm_vblank_pre_modeset(dev, pipe);
|
|
|
|
- list_for_each_entry(connector, &mode_config->connector_list, head) {
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
+ list_for_each_entry(encoder, &mode_config->encoder_list, head) {
|
|
|
|
- if (!connector->encoder || connector->encoder->crtc != crtc)
|
|
+ if (!encoder || encoder->crtc != crtc)
|
|
continue;
|
|
|
|
- switch (intel_output->type) {
|
|
+ intel_encoder = enc_to_intel_encoder(encoder);
|
|
+
|
|
+ switch (intel_encoder->type) {
|
|
case INTEL_OUTPUT_LVDS:
|
|
is_lvds = true;
|
|
break;
|
|
case INTEL_OUTPUT_SDVO:
|
|
case INTEL_OUTPUT_HDMI:
|
|
is_sdvo = true;
|
|
- if (intel_output->needs_tv_clock)
|
|
+ if (intel_encoder->needs_tv_clock)
|
|
is_tv = true;
|
|
break;
|
|
case INTEL_OUTPUT_DVO:
|
|
@@ -2958,16 +3303,16 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|
break;
|
|
}
|
|
|
|
- num_outputs++;
|
|
+ num_connectors++;
|
|
}
|
|
|
|
- if (is_lvds && dev_priv->lvds_use_ssc && num_outputs < 2) {
|
|
+ if (is_lvds && dev_priv->lvds_use_ssc && num_connectors < 2) {
|
|
refclk = dev_priv->lvds_ssc_freq * 1000;
|
|
DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n",
|
|
refclk / 1000);
|
|
} else if (IS_I9XX(dev)) {
|
|
refclk = 96000;
|
|
- if (IS_IRONLAKE(dev))
|
|
+ if (HAS_PCH_SPLIT(dev))
|
|
refclk = 120000; /* 120Mhz refclk */
|
|
} else {
|
|
refclk = 48000;
|
|
@@ -3025,15 +3370,13 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|
}
|
|
|
|
/* FDI link */
|
|
- if (IS_IRONLAKE(dev)) {
|
|
- int lane, link_bw, bpp;
|
|
+ if (HAS_PCH_SPLIT(dev)) {
|
|
+ int lane = 0, link_bw, bpp;
|
|
/* eDP doesn't require FDI link, so just set DP M/N
|
|
according to current link config */
|
|
if (is_edp) {
|
|
- struct drm_connector *edp;
|
|
target_clock = mode->clock;
|
|
- edp = intel_pipe_get_output(crtc);
|
|
- intel_edp_link_config(to_intel_output(edp),
|
|
+ intel_edp_link_config(intel_encoder,
|
|
&lane, &link_bw);
|
|
} else {
|
|
/* DP over FDI requires target mode clock
|
|
@@ -3042,7 +3385,6 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|
target_clock = mode->clock;
|
|
else
|
|
target_clock = adjusted_mode->clock;
|
|
- lane = 4;
|
|
link_bw = 270000;
|
|
}
|
|
|
|
@@ -3094,6 +3436,18 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|
bpp = 24;
|
|
}
|
|
|
|
+ if (!lane) {
|
|
+ /*
|
|
+ * Account for spread spectrum to avoid
|
|
+ * oversubscribing the link. Max center spread
|
|
+ * is 2.5%; use 5% for safety's sake.
|
|
+ */
|
|
+ u32 bps = target_clock * bpp * 21 / 20;
|
|
+ lane = bps / (link_bw * 8) + 1;
|
|
+ }
|
|
+
|
|
+ intel_crtc->fdi_lanes = lane;
|
|
+
|
|
ironlake_compute_m_n(bpp, lane, target_clock, link_bw, &m_n);
|
|
}
|
|
|
|
@@ -3102,7 +3456,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|
* PCH B stepping, previous chipset stepping should be
|
|
* ignoring this setting.
|
|
*/
|
|
- if (IS_IRONLAKE(dev)) {
|
|
+ if (HAS_PCH_SPLIT(dev)) {
|
|
temp = I915_READ(PCH_DREF_CONTROL);
|
|
/* Always enable nonspread source */
|
|
temp &= ~DREF_NONSPREAD_SOURCE_MASK;
|
|
@@ -3149,7 +3503,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|
reduced_clock.m2;
|
|
}
|
|
|
|
- if (!IS_IRONLAKE(dev))
|
|
+ if (!HAS_PCH_SPLIT(dev))
|
|
dpll = DPLL_VGA_MODE_DIS;
|
|
|
|
if (IS_I9XX(dev)) {
|
|
@@ -3162,7 +3516,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|
sdvo_pixel_multiply = adjusted_mode->clock / mode->clock;
|
|
if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
|
|
dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES;
|
|
- else if (IS_IRONLAKE(dev))
|
|
+ else if (HAS_PCH_SPLIT(dev))
|
|
dpll |= (sdvo_pixel_multiply - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT;
|
|
}
|
|
if (is_dp)
|
|
@@ -3174,7 +3528,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|
else {
|
|
dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
|
|
/* also FPA1 */
|
|
- if (IS_IRONLAKE(dev))
|
|
+ if (HAS_PCH_SPLIT(dev))
|
|
dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT;
|
|
if (IS_G4X(dev) && has_reduced_clock)
|
|
dpll |= (1 << (reduced_clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT;
|
|
@@ -3193,7 +3547,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|
dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
|
|
break;
|
|
}
|
|
- if (IS_I965G(dev) && !IS_IRONLAKE(dev))
|
|
+ if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev))
|
|
dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT);
|
|
} else {
|
|
if (is_lvds) {
|
|
@@ -3214,7 +3568,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|
/* XXX: just matching BIOS for now */
|
|
/* dpll |= PLL_REF_INPUT_TVCLKINBC; */
|
|
dpll |= 3;
|
|
- else if (is_lvds && dev_priv->lvds_use_ssc && num_outputs < 2)
|
|
+ else if (is_lvds && dev_priv->lvds_use_ssc && num_connectors < 2)
|
|
dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
|
|
else
|
|
dpll |= PLL_REF_INPUT_DREFCLK;
|
|
@@ -3227,7 +3581,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|
|
|
/* Ironlake's plane is forced to pipe, bit 24 is to
|
|
enable color space conversion */
|
|
- if (!IS_IRONLAKE(dev)) {
|
|
+ if (!HAS_PCH_SPLIT(dev)) {
|
|
if (pipe == 0)
|
|
dspcntr &= ~DISPPLANE_SEL_PIPE_MASK;
|
|
else
|
|
@@ -3249,14 +3603,14 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|
}
|
|
|
|
/* Disable the panel fitter if it was on our pipe */
|
|
- if (!IS_IRONLAKE(dev) && intel_panel_fitter_pipe(dev) == pipe)
|
|
+ if (!HAS_PCH_SPLIT(dev) && intel_panel_fitter_pipe(dev) == pipe)
|
|
I915_WRITE(PFIT_CONTROL, 0);
|
|
|
|
DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
|
|
drm_mode_debug_printmodeline(mode);
|
|
|
|
/* assign to Ironlake registers */
|
|
- if (IS_IRONLAKE(dev)) {
|
|
+ if (HAS_PCH_SPLIT(dev)) {
|
|
fp_reg = pch_fp_reg;
|
|
dpll_reg = pch_dpll_reg;
|
|
}
|
|
@@ -3275,6 +3629,18 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|
udelay(150);
|
|
}
|
|
|
|
+ /* enable transcoder DPLL */
|
|
+ if (HAS_PCH_CPT(dev)) {
|
|
+ temp = I915_READ(PCH_DPLL_SEL);
|
|
+ if (trans_dpll_sel == 0)
|
|
+ temp |= (TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL);
|
|
+ else
|
|
+ temp |= (TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL);
|
|
+ I915_WRITE(PCH_DPLL_SEL, temp);
|
|
+ I915_READ(PCH_DPLL_SEL);
|
|
+ udelay(150);
|
|
+ }
|
|
+
|
|
/* The LVDS pin pair needs to be on before the DPLLs are enabled.
|
|
* This is an exception to the general rule that mode_set doesn't turn
|
|
* things on.
|
|
@@ -3282,11 +3648,22 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|
if (is_lvds) {
|
|
u32 lvds;
|
|
|
|
- if (IS_IRONLAKE(dev))
|
|
+ if (HAS_PCH_SPLIT(dev))
|
|
lvds_reg = PCH_LVDS;
|
|
|
|
lvds = I915_READ(lvds_reg);
|
|
- lvds |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP | LVDS_PIPEB_SELECT;
|
|
+ lvds |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
|
|
+ if (pipe == 1) {
|
|
+ if (HAS_PCH_CPT(dev))
|
|
+ lvds |= PORT_TRANS_B_SEL_CPT;
|
|
+ else
|
|
+ lvds |= LVDS_PIPEB_SELECT;
|
|
+ } else {
|
|
+ if (HAS_PCH_CPT(dev))
|
|
+ lvds &= ~PORT_TRANS_SEL_MASK;
|
|
+ else
|
|
+ lvds &= ~LVDS_PIPEB_SELECT;
|
|
+ }
|
|
/* set the corresponsding LVDS_BORDER bit */
|
|
lvds |= dev_priv->lvds_border_bits;
|
|
/* Set the B0-B3 data pairs corresponding to whether we're going to
|
|
@@ -3304,12 +3681,12 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|
/* set the dithering flag */
|
|
if (IS_I965G(dev)) {
|
|
if (dev_priv->lvds_dither) {
|
|
- if (IS_IRONLAKE(dev))
|
|
+ if (HAS_PCH_SPLIT(dev))
|
|
pipeconf |= PIPE_ENABLE_DITHER;
|
|
else
|
|
lvds |= LVDS_ENABLE_DITHER;
|
|
} else {
|
|
- if (IS_IRONLAKE(dev))
|
|
+ if (HAS_PCH_SPLIT(dev))
|
|
pipeconf &= ~PIPE_ENABLE_DITHER;
|
|
else
|
|
lvds &= ~LVDS_ENABLE_DITHER;
|
|
@@ -3320,6 +3697,20 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|
}
|
|
if (is_dp)
|
|
intel_dp_set_m_n(crtc, mode, adjusted_mode);
|
|
+ else if (HAS_PCH_SPLIT(dev)) {
|
|
+ /* For non-DP output, clear any trans DP clock recovery setting.*/
|
|
+ if (pipe == 0) {
|
|
+ I915_WRITE(TRANSA_DATA_M1, 0);
|
|
+ I915_WRITE(TRANSA_DATA_N1, 0);
|
|
+ I915_WRITE(TRANSA_DP_LINK_M1, 0);
|
|
+ I915_WRITE(TRANSA_DP_LINK_N1, 0);
|
|
+ } else {
|
|
+ I915_WRITE(TRANSB_DATA_M1, 0);
|
|
+ I915_WRITE(TRANSB_DATA_N1, 0);
|
|
+ I915_WRITE(TRANSB_DP_LINK_M1, 0);
|
|
+ I915_WRITE(TRANSB_DP_LINK_N1, 0);
|
|
+ }
|
|
+ }
|
|
|
|
if (!is_edp) {
|
|
I915_WRITE(fp_reg, fp);
|
|
@@ -3328,7 +3719,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|
/* Wait for the clocks to stabilize. */
|
|
udelay(150);
|
|
|
|
- if (IS_I965G(dev) && !IS_IRONLAKE(dev)) {
|
|
+ if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev)) {
|
|
if (is_sdvo) {
|
|
sdvo_pixel_multiply = adjusted_mode->clock / mode->clock;
|
|
I915_WRITE(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) |
|
|
@@ -3375,14 +3766,14 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|
/* pipesrc and dspsize control the size that is scaled from, which should
|
|
* always be the user's requested size.
|
|
*/
|
|
- if (!IS_IRONLAKE(dev)) {
|
|
+ if (!HAS_PCH_SPLIT(dev)) {
|
|
I915_WRITE(dspsize_reg, ((mode->vdisplay - 1) << 16) |
|
|
(mode->hdisplay - 1));
|
|
I915_WRITE(dsppos_reg, 0);
|
|
}
|
|
I915_WRITE(pipesrc_reg, ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1));
|
|
|
|
- if (IS_IRONLAKE(dev)) {
|
|
+ if (HAS_PCH_SPLIT(dev)) {
|
|
I915_WRITE(data_m1_reg, TU_SIZE(m_n.tu) | m_n.gmch_m);
|
|
I915_WRITE(data_n1_reg, TU_SIZE(m_n.tu) | m_n.gmch_n);
|
|
I915_WRITE(link_m1_reg, m_n.link_m);
|
|
@@ -3394,6 +3785,18 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
|
|
/* enable FDI RX PLL too */
|
|
temp = I915_READ(fdi_rx_reg);
|
|
I915_WRITE(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE);
|
|
+ I915_READ(fdi_rx_reg);
|
|
+ udelay(200);
|
|
+
|
|
+ /* enable FDI TX PLL too */
|
|
+ temp = I915_READ(fdi_tx_reg);
|
|
+ I915_WRITE(fdi_tx_reg, temp | FDI_TX_PLL_ENABLE);
|
|
+ I915_READ(fdi_tx_reg);
|
|
+
|
|
+ /* enable FDI RX PCDCLK */
|
|
+ temp = I915_READ(fdi_rx_reg);
|
|
+ I915_WRITE(fdi_rx_reg, temp | FDI_SEL_PCDCLK);
|
|
+ I915_READ(fdi_rx_reg);
|
|
udelay(200);
|
|
}
|
|
}
|
|
@@ -3438,7 +3841,7 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
|
|
return;
|
|
|
|
/* use legacy palette for Ironlake */
|
|
- if (IS_IRONLAKE(dev))
|
|
+ if (HAS_PCH_SPLIT(dev))
|
|
palreg = (intel_crtc->pipe == 0) ? LGC_PALETTE_A :
|
|
LGC_PALETTE_B;
|
|
|
|
@@ -3494,7 +3897,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
|
|
if (!bo)
|
|
return -ENOENT;
|
|
|
|
- obj_priv = bo->driver_private;
|
|
+ obj_priv = to_intel_bo(bo);
|
|
|
|
if (bo->size < width * height * 4) {
|
|
DRM_ERROR("buffer is to small\n");
|
|
@@ -3638,9 +4041,9 @@ static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
|
|
* detection.
|
|
*
|
|
* It will be up to the load-detect code to adjust the pipe as appropriate for
|
|
- * its requirements. The pipe will be connected to no other outputs.
|
|
+ * its requirements. The pipe will be connected to no other encoders.
|
|
*
|
|
- * Currently this code will only succeed if there is a pipe with no outputs
|
|
+ * Currently this code will only succeed if there is a pipe with no encoders
|
|
* configured for it. In the future, it could choose to temporarily disable
|
|
* some outputs to free up a pipe for its use.
|
|
*
|
|
@@ -3653,14 +4056,15 @@ static struct drm_display_mode load_detect_mode = {
|
|
704, 832, 0, 480, 489, 491, 520, 0, DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
|
|
};
|
|
|
|
-struct drm_crtc *intel_get_load_detect_pipe(struct intel_output *intel_output,
|
|
+struct drm_crtc *intel_get_load_detect_pipe(struct intel_encoder *intel_encoder,
|
|
+ struct drm_connector *connector,
|
|
struct drm_display_mode *mode,
|
|
int *dpms_mode)
|
|
{
|
|
struct intel_crtc *intel_crtc;
|
|
struct drm_crtc *possible_crtc;
|
|
struct drm_crtc *supported_crtc =NULL;
|
|
- struct drm_encoder *encoder = &intel_output->enc;
|
|
+ struct drm_encoder *encoder = &intel_encoder->enc;
|
|
struct drm_crtc *crtc = NULL;
|
|
struct drm_device *dev = encoder->dev;
|
|
struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
|
|
@@ -3712,8 +4116,8 @@ struct drm_crtc *intel_get_load_detect_pipe(struct intel_output *intel_output,
|
|
}
|
|
|
|
encoder->crtc = crtc;
|
|
- intel_output->base.encoder = encoder;
|
|
- intel_output->load_detect_temp = true;
|
|
+ connector->encoder = encoder;
|
|
+ intel_encoder->load_detect_temp = true;
|
|
|
|
intel_crtc = to_intel_crtc(crtc);
|
|
*dpms_mode = intel_crtc->dpms_mode;
|
|
@@ -3738,23 +4142,24 @@ struct drm_crtc *intel_get_load_detect_pipe(struct intel_output *intel_output,
|
|
return crtc;
|
|
}
|
|
|
|
-void intel_release_load_detect_pipe(struct intel_output *intel_output, int dpms_mode)
|
|
+void intel_release_load_detect_pipe(struct intel_encoder *intel_encoder,
|
|
+ struct drm_connector *connector, int dpms_mode)
|
|
{
|
|
- struct drm_encoder *encoder = &intel_output->enc;
|
|
+ struct drm_encoder *encoder = &intel_encoder->enc;
|
|
struct drm_device *dev = encoder->dev;
|
|
struct drm_crtc *crtc = encoder->crtc;
|
|
struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
|
|
struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
|
|
|
|
- if (intel_output->load_detect_temp) {
|
|
+ if (intel_encoder->load_detect_temp) {
|
|
encoder->crtc = NULL;
|
|
- intel_output->base.encoder = NULL;
|
|
- intel_output->load_detect_temp = false;
|
|
+ connector->encoder = NULL;
|
|
+ intel_encoder->load_detect_temp = false;
|
|
crtc->enabled = drm_helper_crtc_in_use(crtc);
|
|
drm_helper_disable_unused_functions(dev);
|
|
}
|
|
|
|
- /* Switch crtc and output back off if necessary */
|
|
+ /* Switch crtc and encoder back off if necessary */
|
|
if (crtc->enabled && dpms_mode != DRM_MODE_DPMS_ON) {
|
|
if (encoder->crtc == crtc)
|
|
encoder_funcs->dpms(encoder, dpms_mode);
|
|
@@ -3921,7 +4326,7 @@ static void intel_increase_pllclock(struct drm_crtc *crtc, bool schedule)
|
|
int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
|
|
int dpll = I915_READ(dpll_reg);
|
|
|
|
- if (IS_IRONLAKE(dev))
|
|
+ if (HAS_PCH_SPLIT(dev))
|
|
return;
|
|
|
|
if (!dev_priv->lvds_downclock_avail)
|
|
@@ -3960,7 +4365,7 @@ static void intel_decrease_pllclock(struct drm_crtc *crtc)
|
|
int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
|
|
int dpll = I915_READ(dpll_reg);
|
|
|
|
- if (IS_IRONLAKE(dev))
|
|
+ if (HAS_PCH_SPLIT(dev))
|
|
return;
|
|
|
|
if (!dev_priv->lvds_downclock_avail)
|
|
@@ -4010,6 +4415,11 @@ static void intel_idle_update(struct work_struct *work)
|
|
|
|
mutex_lock(&dev->struct_mutex);
|
|
|
|
+ if (IS_I945G(dev) || IS_I945GM(dev)) {
|
|
+ DRM_DEBUG_DRIVER("enable memory self refresh on 945\n");
|
|
+ I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN_MASK | FW_BLC_SELF_EN);
|
|
+ }
|
|
+
|
|
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
|
/* Skip inactive CRTCs */
|
|
if (!crtc->fb)
|
|
@@ -4043,9 +4453,17 @@ void intel_mark_busy(struct drm_device *dev, struct drm_gem_object *obj)
|
|
if (!drm_core_check_feature(dev, DRIVER_MODESET))
|
|
return;
|
|
|
|
- if (!dev_priv->busy)
|
|
+ if (!dev_priv->busy) {
|
|
+ if (IS_I945G(dev) || IS_I945GM(dev)) {
|
|
+ u32 fw_blc_self;
|
|
+
|
|
+ DRM_DEBUG_DRIVER("disable memory self refresh on 945\n");
|
|
+ fw_blc_self = I915_READ(FW_BLC_SELF);
|
|
+ fw_blc_self &= ~FW_BLC_SELF_EN;
|
|
+ I915_WRITE(FW_BLC_SELF, fw_blc_self | FW_BLC_SELF_EN_MASK);
|
|
+ }
|
|
dev_priv->busy = true;
|
|
- else
|
|
+ } else
|
|
mod_timer(&dev_priv->idle_timer, jiffies +
|
|
msecs_to_jiffies(GPU_IDLE_TIMEOUT));
|
|
|
|
@@ -4057,6 +4475,14 @@ void intel_mark_busy(struct drm_device *dev, struct drm_gem_object *obj)
|
|
intel_fb = to_intel_framebuffer(crtc->fb);
|
|
if (intel_fb->obj == obj) {
|
|
if (!intel_crtc->busy) {
|
|
+ if (IS_I945G(dev) || IS_I945GM(dev)) {
|
|
+ u32 fw_blc_self;
|
|
+
|
|
+ DRM_DEBUG_DRIVER("disable memory self refresh on 945\n");
|
|
+ fw_blc_self = I915_READ(FW_BLC_SELF);
|
|
+ fw_blc_self &= ~FW_BLC_SELF_EN;
|
|
+ I915_WRITE(FW_BLC_SELF, fw_blc_self | FW_BLC_SELF_EN_MASK);
|
|
+ }
|
|
/* Non-busy -> busy, upclock */
|
|
intel_increase_pllclock(crtc, true);
|
|
intel_crtc->busy = true;
|
|
@@ -4118,7 +4544,7 @@ void intel_finish_page_flip(struct drm_device *dev, int pipe)
|
|
work = intel_crtc->unpin_work;
|
|
if (work == NULL || !work->pending) {
|
|
if (work && !work->pending) {
|
|
- obj_priv = work->pending_flip_obj->driver_private;
|
|
+ obj_priv = to_intel_bo(work->pending_flip_obj);
|
|
DRM_DEBUG_DRIVER("flip finish: %p (%d) not pending?\n",
|
|
obj_priv,
|
|
atomic_read(&obj_priv->pending_flip));
|
|
@@ -4143,7 +4569,7 @@ void intel_finish_page_flip(struct drm_device *dev, int pipe)
|
|
|
|
spin_unlock_irqrestore(&dev->event_lock, flags);
|
|
|
|
- obj_priv = work->pending_flip_obj->driver_private;
|
|
+ obj_priv = to_intel_bo(work->pending_flip_obj);
|
|
|
|
/* Initial scanout buffer will have a 0 pending flip count */
|
|
if ((atomic_read(&obj_priv->pending_flip) == 0) ||
|
|
@@ -4214,7 +4640,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
|
|
ret = intel_pin_and_fence_fb_obj(dev, obj);
|
|
if (ret != 0) {
|
|
DRM_DEBUG_DRIVER("flip queue: %p pin & fence failed\n",
|
|
- obj->driver_private);
|
|
+ to_intel_bo(obj));
|
|
kfree(work);
|
|
intel_crtc->unpin_work = NULL;
|
|
mutex_unlock(&dev->struct_mutex);
|
|
@@ -4228,7 +4654,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
|
|
crtc->fb = fb;
|
|
i915_gem_object_flush_write_domain(obj);
|
|
drm_vblank_get(dev, intel_crtc->pipe);
|
|
- obj_priv = obj->driver_private;
|
|
+ obj_priv = to_intel_bo(obj);
|
|
atomic_inc(&obj_priv->pending_flip);
|
|
work->pending_flip_obj = obj;
|
|
|
|
@@ -4354,15 +4780,15 @@ struct drm_crtc *intel_get_crtc_from_pipe(struct drm_device *dev, int pipe)
|
|
return crtc;
|
|
}
|
|
|
|
-static int intel_connector_clones(struct drm_device *dev, int type_mask)
|
|
+static int intel_encoder_clones(struct drm_device *dev, int type_mask)
|
|
{
|
|
int index_mask = 0;
|
|
- struct drm_connector *connector;
|
|
+ struct drm_encoder *encoder;
|
|
int entry = 0;
|
|
|
|
- list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
- if (type_mask & intel_output->clone_mask)
|
|
+ list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ if (type_mask & intel_encoder->clone_mask)
|
|
index_mask |= (1 << entry);
|
|
entry++;
|
|
}
|
|
@@ -4373,7 +4799,7 @@ static int intel_connector_clones(struct drm_device *dev, int type_mask)
|
|
static void intel_setup_outputs(struct drm_device *dev)
|
|
{
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
- struct drm_connector *connector;
|
|
+ struct drm_encoder *encoder;
|
|
|
|
intel_crt_init(dev);
|
|
|
|
@@ -4381,16 +4807,15 @@ static void intel_setup_outputs(struct drm_device *dev)
|
|
if (IS_MOBILE(dev) && !IS_I830(dev))
|
|
intel_lvds_init(dev);
|
|
|
|
- if (IS_IRONLAKE(dev)) {
|
|
+ if (HAS_PCH_SPLIT(dev)) {
|
|
int found;
|
|
|
|
if (IS_MOBILE(dev) && (I915_READ(DP_A) & DP_DETECTED))
|
|
intel_dp_init(dev, DP_A);
|
|
|
|
if (I915_READ(HDMIB) & PORT_DETECTED) {
|
|
- /* check SDVOB */
|
|
- /* found = intel_sdvo_init(dev, HDMIB); */
|
|
- found = 0;
|
|
+ /* PCH SDVOB multiplex with HDMIB */
|
|
+ found = intel_sdvo_init(dev, PCH_SDVOB);
|
|
if (!found)
|
|
intel_hdmi_init(dev, HDMIB);
|
|
if (!found && (I915_READ(PCH_DP_B) & DP_DETECTED))
|
|
@@ -4450,19 +4875,18 @@ static void intel_setup_outputs(struct drm_device *dev)
|
|
DRM_DEBUG_KMS("probing DP_D\n");
|
|
intel_dp_init(dev, DP_D);
|
|
}
|
|
- } else if (IS_I8XX(dev))
|
|
+ } else if (IS_GEN2(dev))
|
|
intel_dvo_init(dev);
|
|
|
|
if (SUPPORTS_TV(dev))
|
|
intel_tv_init(dev);
|
|
|
|
- list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
- struct drm_encoder *encoder = &intel_output->enc;
|
|
+ list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
|
|
- encoder->possible_crtcs = intel_output->crtc_mask;
|
|
- encoder->possible_clones = intel_connector_clones(dev,
|
|
- intel_output->clone_mask);
|
|
+ encoder->possible_crtcs = intel_encoder->crtc_mask;
|
|
+ encoder->possible_clones = intel_encoder_clones(dev,
|
|
+ intel_encoder->clone_mask);
|
|
}
|
|
}
|
|
|
|
@@ -4586,6 +5010,91 @@ err_unref:
|
|
return NULL;
|
|
}
|
|
|
|
+void ironlake_enable_drps(struct drm_device *dev)
|
|
+{
|
|
+ struct drm_i915_private *dev_priv = dev->dev_private;
|
|
+ u32 rgvmodectl = I915_READ(MEMMODECTL), rgvswctl;
|
|
+ u8 fmax, fmin, fstart, vstart;
|
|
+ int i = 0;
|
|
+
|
|
+ /* 100ms RC evaluation intervals */
|
|
+ I915_WRITE(RCUPEI, 100000);
|
|
+ I915_WRITE(RCDNEI, 100000);
|
|
+
|
|
+ /* Set max/min thresholds to 90ms and 80ms respectively */
|
|
+ I915_WRITE(RCBMAXAVG, 90000);
|
|
+ I915_WRITE(RCBMINAVG, 80000);
|
|
+
|
|
+ I915_WRITE(MEMIHYST, 1);
|
|
+
|
|
+ /* Set up min, max, and cur for interrupt handling */
|
|
+ fmax = (rgvmodectl & MEMMODE_FMAX_MASK) >> MEMMODE_FMAX_SHIFT;
|
|
+ fmin = (rgvmodectl & MEMMODE_FMIN_MASK);
|
|
+ fstart = (rgvmodectl & MEMMODE_FSTART_MASK) >>
|
|
+ MEMMODE_FSTART_SHIFT;
|
|
+ vstart = (I915_READ(PXVFREQ_BASE + (fstart * 4)) & PXVFREQ_PX_MASK) >>
|
|
+ PXVFREQ_PX_SHIFT;
|
|
+
|
|
+ dev_priv->max_delay = fstart; /* can't go to fmax w/o IPS */
|
|
+ dev_priv->min_delay = fmin;
|
|
+ dev_priv->cur_delay = fstart;
|
|
+
|
|
+ I915_WRITE(MEMINTREN, MEMINT_CX_SUPR_EN | MEMINT_EVAL_CHG_EN);
|
|
+
|
|
+ /*
|
|
+ * Interrupts will be enabled in ironlake_irq_postinstall
|
|
+ */
|
|
+
|
|
+ I915_WRITE(VIDSTART, vstart);
|
|
+ POSTING_READ(VIDSTART);
|
|
+
|
|
+ rgvmodectl |= MEMMODE_SWMODE_EN;
|
|
+ I915_WRITE(MEMMODECTL, rgvmodectl);
|
|
+
|
|
+ while (I915_READ(MEMSWCTL) & MEMCTL_CMD_STS) {
|
|
+ if (i++ > 100) {
|
|
+ DRM_ERROR("stuck trying to change perf mode\n");
|
|
+ break;
|
|
+ }
|
|
+ msleep(1);
|
|
+ }
|
|
+ msleep(1);
|
|
+
|
|
+ rgvswctl = (MEMCTL_CMD_CHFREQ << MEMCTL_CMD_SHIFT) |
|
|
+ (fstart << MEMCTL_FREQ_SHIFT) | MEMCTL_SFCAVM;
|
|
+ I915_WRITE(MEMSWCTL, rgvswctl);
|
|
+ POSTING_READ(MEMSWCTL);
|
|
+
|
|
+ rgvswctl |= MEMCTL_CMD_STS;
|
|
+ I915_WRITE(MEMSWCTL, rgvswctl);
|
|
+}
|
|
+
|
|
+void ironlake_disable_drps(struct drm_device *dev)
|
|
+{
|
|
+ struct drm_i915_private *dev_priv = dev->dev_private;
|
|
+ u32 rgvswctl;
|
|
+ u8 fstart;
|
|
+
|
|
+ /* Ack interrupts, disable EFC interrupt */
|
|
+ I915_WRITE(MEMINTREN, I915_READ(MEMINTREN) & ~MEMINT_EVAL_CHG_EN);
|
|
+ I915_WRITE(MEMINTRSTS, MEMINT_EVAL_CHG);
|
|
+ I915_WRITE(DEIER, I915_READ(DEIER) & ~DE_PCU_EVENT);
|
|
+ I915_WRITE(DEIIR, DE_PCU_EVENT);
|
|
+ I915_WRITE(DEIMR, I915_READ(DEIMR) | DE_PCU_EVENT);
|
|
+
|
|
+ /* Go back to the starting frequency */
|
|
+ fstart = (I915_READ(MEMMODECTL) & MEMMODE_FSTART_MASK) >>
|
|
+ MEMMODE_FSTART_SHIFT;
|
|
+ rgvswctl = (MEMCTL_CMD_CHFREQ << MEMCTL_CMD_SHIFT) |
|
|
+ (fstart << MEMCTL_FREQ_SHIFT) | MEMCTL_SFCAVM;
|
|
+ I915_WRITE(MEMSWCTL, rgvswctl);
|
|
+ msleep(1);
|
|
+ rgvswctl |= MEMCTL_CMD_STS;
|
|
+ I915_WRITE(MEMSWCTL, rgvswctl);
|
|
+ msleep(1);
|
|
+
|
|
+}
|
|
+
|
|
void intel_init_clock_gating(struct drm_device *dev)
|
|
{
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
@@ -4594,7 +5103,40 @@ void intel_init_clock_gating(struct drm_device *dev)
|
|
* Disable clock gating reported to work incorrectly according to the
|
|
* specs, but enable as much else as we can.
|
|
*/
|
|
- if (IS_IRONLAKE(dev)) {
|
|
+ if (HAS_PCH_SPLIT(dev)) {
|
|
+ uint32_t dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE;
|
|
+
|
|
+ if (IS_IRONLAKE(dev)) {
|
|
+ /* Required for FBC */
|
|
+ dspclk_gate |= DPFDUNIT_CLOCK_GATE_DISABLE;
|
|
+ /* Required for CxSR */
|
|
+ dspclk_gate |= DPARBUNIT_CLOCK_GATE_DISABLE;
|
|
+
|
|
+ I915_WRITE(PCH_3DCGDIS0,
|
|
+ MARIUNIT_CLOCK_GATE_DISABLE |
|
|
+ SVSMUNIT_CLOCK_GATE_DISABLE);
|
|
+ }
|
|
+
|
|
+ I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate);
|
|
+
|
|
+ /*
|
|
+ * According to the spec the following bits should be set in
|
|
+ * order to enable memory self-refresh
|
|
+ * The bit 22/21 of 0x42004
|
|
+ * The bit 5 of 0x42020
|
|
+ * The bit 15 of 0x45000
|
|
+ */
|
|
+ if (IS_IRONLAKE(dev)) {
|
|
+ I915_WRITE(ILK_DISPLAY_CHICKEN2,
|
|
+ (I915_READ(ILK_DISPLAY_CHICKEN2) |
|
|
+ ILK_DPARB_GATE | ILK_VSDPFD_FULL));
|
|
+ I915_WRITE(ILK_DSPCLK_GATE,
|
|
+ (I915_READ(ILK_DSPCLK_GATE) |
|
|
+ ILK_DPARB_CLK_GATE));
|
|
+ I915_WRITE(DISP_ARB_CTL,
|
|
+ (I915_READ(DISP_ARB_CTL) |
|
|
+ DISP_FBC_WM_DIS));
|
|
+ }
|
|
return;
|
|
} else if (IS_G4X(dev)) {
|
|
uint32_t dspclk_gate;
|
|
@@ -4642,14 +5184,14 @@ void intel_init_clock_gating(struct drm_device *dev)
|
|
struct drm_i915_gem_object *obj_priv = NULL;
|
|
|
|
if (dev_priv->pwrctx) {
|
|
- obj_priv = dev_priv->pwrctx->driver_private;
|
|
+ obj_priv = to_intel_bo(dev_priv->pwrctx);
|
|
} else {
|
|
struct drm_gem_object *pwrctx;
|
|
|
|
pwrctx = intel_alloc_power_context(dev);
|
|
if (pwrctx) {
|
|
dev_priv->pwrctx = pwrctx;
|
|
- obj_priv = pwrctx->driver_private;
|
|
+ obj_priv = to_intel_bo(pwrctx);
|
|
}
|
|
}
|
|
|
|
@@ -4667,7 +5209,7 @@ static void intel_init_display(struct drm_device *dev)
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
/* We always want a DPMS function */
|
|
- if (IS_IRONLAKE(dev))
|
|
+ if (HAS_PCH_SPLIT(dev))
|
|
dev_priv->display.dpms = ironlake_crtc_dpms;
|
|
else
|
|
dev_priv->display.dpms = i9xx_crtc_dpms;
|
|
@@ -4678,7 +5220,7 @@ static void intel_init_display(struct drm_device *dev)
|
|
dev_priv->display.fbc_enabled = g4x_fbc_enabled;
|
|
dev_priv->display.enable_fbc = g4x_enable_fbc;
|
|
dev_priv->display.disable_fbc = g4x_disable_fbc;
|
|
- } else if (IS_I965GM(dev) || IS_I945GM(dev) || IS_I915GM(dev)) {
|
|
+ } else if (IS_I965GM(dev)) {
|
|
dev_priv->display.fbc_enabled = i8xx_fbc_enabled;
|
|
dev_priv->display.enable_fbc = i8xx_enable_fbc;
|
|
dev_priv->display.disable_fbc = i8xx_disable_fbc;
|
|
@@ -4710,23 +5252,46 @@ static void intel_init_display(struct drm_device *dev)
|
|
i830_get_display_clock_speed;
|
|
|
|
/* For FIFO watermark updates */
|
|
- if (IS_IRONLAKE(dev))
|
|
- dev_priv->display.update_wm = NULL;
|
|
- else if (IS_G4X(dev))
|
|
+ if (HAS_PCH_SPLIT(dev)) {
|
|
+ if (IS_IRONLAKE(dev)) {
|
|
+ if (I915_READ(MLTR_ILK) & ILK_SRLT_MASK)
|
|
+ dev_priv->display.update_wm = ironlake_update_wm;
|
|
+ else {
|
|
+ DRM_DEBUG_KMS("Failed to get proper latency. "
|
|
+ "Disable CxSR\n");
|
|
+ dev_priv->display.update_wm = NULL;
|
|
+ }
|
|
+ } else
|
|
+ dev_priv->display.update_wm = NULL;
|
|
+ } else if (IS_PINEVIEW(dev)) {
|
|
+ if (!intel_get_cxsr_latency(IS_PINEVIEW_G(dev),
|
|
+ dev_priv->fsb_freq,
|
|
+ dev_priv->mem_freq)) {
|
|
+ DRM_INFO("failed to find known CxSR latency "
|
|
+ "(found fsb freq %d, mem freq %d), "
|
|
+ "disabling CxSR\n",
|
|
+ dev_priv->fsb_freq, dev_priv->mem_freq);
|
|
+ /* Disable CxSR and never update its watermark again */
|
|
+ pineview_disable_cxsr(dev);
|
|
+ dev_priv->display.update_wm = NULL;
|
|
+ } else
|
|
+ dev_priv->display.update_wm = pineview_update_wm;
|
|
+ } else if (IS_G4X(dev))
|
|
dev_priv->display.update_wm = g4x_update_wm;
|
|
else if (IS_I965G(dev))
|
|
dev_priv->display.update_wm = i965_update_wm;
|
|
- else if (IS_I9XX(dev) || IS_MOBILE(dev)) {
|
|
+ else if (IS_I9XX(dev)) {
|
|
dev_priv->display.update_wm = i9xx_update_wm;
|
|
dev_priv->display.get_fifo_size = i9xx_get_fifo_size;
|
|
+ } else if (IS_I85X(dev)) {
|
|
+ dev_priv->display.update_wm = i9xx_update_wm;
|
|
+ dev_priv->display.get_fifo_size = i85x_get_fifo_size;
|
|
} else {
|
|
- if (IS_I85X(dev))
|
|
- dev_priv->display.get_fifo_size = i85x_get_fifo_size;
|
|
- else if (IS_845G(dev))
|
|
+ dev_priv->display.update_wm = i830_update_wm;
|
|
+ if (IS_845G(dev))
|
|
dev_priv->display.get_fifo_size = i845_get_fifo_size;
|
|
else
|
|
dev_priv->display.get_fifo_size = i830_get_fifo_size;
|
|
- dev_priv->display.update_wm = i830_update_wm;
|
|
}
|
|
}
|
|
|
|
@@ -4769,11 +5334,6 @@ void intel_modeset_init(struct drm_device *dev)
|
|
DRM_DEBUG_KMS("%d display pipe%s available.\n",
|
|
num_pipe, num_pipe > 1 ? "s" : "");
|
|
|
|
- if (IS_I85X(dev))
|
|
- pci_read_config_word(dev->pdev, HPLLCC, &dev_priv->orig_clock);
|
|
- else if (IS_I9XX(dev) || IS_G4X(dev))
|
|
- pci_read_config_word(dev->pdev, GCFGC, &dev_priv->orig_clock);
|
|
-
|
|
for (i = 0; i < num_pipe; i++) {
|
|
intel_crtc_init(dev, i);
|
|
}
|
|
@@ -4782,18 +5342,14 @@ void intel_modeset_init(struct drm_device *dev)
|
|
|
|
intel_init_clock_gating(dev);
|
|
|
|
+ if (IS_IRONLAKE_M(dev))
|
|
+ ironlake_enable_drps(dev);
|
|
+
|
|
INIT_WORK(&dev_priv->idle_work, intel_idle_update);
|
|
setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer,
|
|
(unsigned long)dev);
|
|
|
|
intel_setup_overlay(dev);
|
|
-
|
|
- if (IS_PINEVIEW(dev) && !intel_get_cxsr_latency(IS_PINEVIEW_G(dev),
|
|
- dev_priv->fsb_freq,
|
|
- dev_priv->mem_freq))
|
|
- DRM_INFO("failed to find known CxSR latency "
|
|
- "(found fsb freq %d, mem freq %d), disabling CxSR\n",
|
|
- dev_priv->fsb_freq, dev_priv->mem_freq);
|
|
}
|
|
|
|
void intel_modeset_cleanup(struct drm_device *dev)
|
|
@@ -4822,27 +5378,45 @@ void intel_modeset_cleanup(struct drm_device *dev)
|
|
if (dev_priv->pwrctx) {
|
|
struct drm_i915_gem_object *obj_priv;
|
|
|
|
- obj_priv = dev_priv->pwrctx->driver_private;
|
|
+ obj_priv = to_intel_bo(dev_priv->pwrctx);
|
|
I915_WRITE(PWRCTXA, obj_priv->gtt_offset &~ PWRCTX_EN);
|
|
I915_READ(PWRCTXA);
|
|
i915_gem_object_unpin(dev_priv->pwrctx);
|
|
drm_gem_object_unreference(dev_priv->pwrctx);
|
|
}
|
|
|
|
+ if (IS_IRONLAKE_M(dev))
|
|
+ ironlake_disable_drps(dev);
|
|
+
|
|
mutex_unlock(&dev->struct_mutex);
|
|
|
|
drm_mode_config_cleanup(dev);
|
|
}
|
|
|
|
|
|
-/* current intel driver doesn't take advantage of encoders
|
|
- always give back the encoder for the connector
|
|
-*/
|
|
-struct drm_encoder *intel_best_encoder(struct drm_connector *connector)
|
|
+/*
|
|
+ * Return which encoder is currently attached for connector.
|
|
+ */
|
|
+struct drm_encoder *intel_attached_encoder (struct drm_connector *connector)
|
|
{
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
+ struct drm_mode_object *obj;
|
|
+ struct drm_encoder *encoder;
|
|
+ int i;
|
|
|
|
- return &intel_output->enc;
|
|
+ for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
|
|
+ if (connector->encoder_ids[i] == 0)
|
|
+ break;
|
|
+
|
|
+ obj = drm_mode_object_find(connector->dev,
|
|
+ connector->encoder_ids[i],
|
|
+ DRM_MODE_OBJECT_ENCODER);
|
|
+ if (!obj)
|
|
+ continue;
|
|
+
|
|
+ encoder = obj_to_encoder(obj);
|
|
+ return encoder;
|
|
+ }
|
|
+ return NULL;
|
|
}
|
|
|
|
/*
|
|
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
|
|
--- a/drivers/gpu/drm/i915/intel_dp.c
|
|
+++ b/drivers/gpu/drm/i915/intel_dp.c
|
|
@@ -47,30 +47,28 @@ struct intel_dp_priv {
|
|
uint32_t output_reg;
|
|
uint32_t DP;
|
|
uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE];
|
|
- uint32_t save_DP;
|
|
- uint8_t save_link_configuration[DP_LINK_CONFIGURATION_SIZE];
|
|
bool has_audio;
|
|
int dpms_mode;
|
|
uint8_t link_bw;
|
|
uint8_t lane_count;
|
|
uint8_t dpcd[4];
|
|
- struct intel_output *intel_output;
|
|
+ struct intel_encoder *intel_encoder;
|
|
struct i2c_adapter adapter;
|
|
struct i2c_algo_dp_aux_data algo;
|
|
};
|
|
|
|
static void
|
|
-intel_dp_link_train(struct intel_output *intel_output, uint32_t DP,
|
|
+intel_dp_link_train(struct intel_encoder *intel_encoder, uint32_t DP,
|
|
uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE]);
|
|
|
|
static void
|
|
-intel_dp_link_down(struct intel_output *intel_output, uint32_t DP);
|
|
+intel_dp_link_down(struct intel_encoder *intel_encoder, uint32_t DP);
|
|
|
|
void
|
|
-intel_edp_link_config (struct intel_output *intel_output,
|
|
+intel_edp_link_config (struct intel_encoder *intel_encoder,
|
|
int *lane_num, int *link_bw)
|
|
{
|
|
- struct intel_dp_priv *dp_priv = intel_output->dev_priv;
|
|
+ struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
|
|
|
|
*lane_num = dp_priv->lane_count;
|
|
if (dp_priv->link_bw == DP_LINK_BW_1_62)
|
|
@@ -80,9 +78,9 @@ intel_edp_link_config (struct intel_output *intel_output,
|
|
}
|
|
|
|
static int
|
|
-intel_dp_max_lane_count(struct intel_output *intel_output)
|
|
+intel_dp_max_lane_count(struct intel_encoder *intel_encoder)
|
|
{
|
|
- struct intel_dp_priv *dp_priv = intel_output->dev_priv;
|
|
+ struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
|
|
int max_lane_count = 4;
|
|
|
|
if (dp_priv->dpcd[0] >= 0x11) {
|
|
@@ -98,9 +96,9 @@ intel_dp_max_lane_count(struct intel_output *intel_output)
|
|
}
|
|
|
|
static int
|
|
-intel_dp_max_link_bw(struct intel_output *intel_output)
|
|
+intel_dp_max_link_bw(struct intel_encoder *intel_encoder)
|
|
{
|
|
- struct intel_dp_priv *dp_priv = intel_output->dev_priv;
|
|
+ struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
|
|
int max_link_bw = dp_priv->dpcd[1];
|
|
|
|
switch (max_link_bw) {
|
|
@@ -126,11 +124,11 @@ intel_dp_link_clock(uint8_t link_bw)
|
|
/* I think this is a fiction */
|
|
static int
|
|
intel_dp_link_required(struct drm_device *dev,
|
|
- struct intel_output *intel_output, int pixel_clock)
|
|
+ struct intel_encoder *intel_encoder, int pixel_clock)
|
|
{
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
- if (IS_eDP(intel_output))
|
|
+ if (IS_eDP(intel_encoder))
|
|
return (pixel_clock * dev_priv->edp_bpp) / 8;
|
|
else
|
|
return pixel_clock * 3;
|
|
@@ -140,11 +138,12 @@ static int
|
|
intel_dp_mode_valid(struct drm_connector *connector,
|
|
struct drm_display_mode *mode)
|
|
{
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
- int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_output));
|
|
- int max_lanes = intel_dp_max_lane_count(intel_output);
|
|
+ struct drm_encoder *encoder = intel_attached_encoder(connector);
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_encoder));
|
|
+ int max_lanes = intel_dp_max_lane_count(intel_encoder);
|
|
|
|
- if (intel_dp_link_required(connector->dev, intel_output, mode->clock)
|
|
+ if (intel_dp_link_required(connector->dev, intel_encoder, mode->clock)
|
|
> max_link_clock * max_lanes)
|
|
return MODE_CLOCK_HIGH;
|
|
|
|
@@ -208,13 +207,13 @@ intel_hrawclk(struct drm_device *dev)
|
|
}
|
|
|
|
static int
|
|
-intel_dp_aux_ch(struct intel_output *intel_output,
|
|
+intel_dp_aux_ch(struct intel_encoder *intel_encoder,
|
|
uint8_t *send, int send_bytes,
|
|
uint8_t *recv, int recv_size)
|
|
{
|
|
- struct intel_dp_priv *dp_priv = intel_output->dev_priv;
|
|
+ struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
|
|
uint32_t output_reg = dp_priv->output_reg;
|
|
- struct drm_device *dev = intel_output->base.dev;
|
|
+ struct drm_device *dev = intel_encoder->enc.dev;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
uint32_t ch_ctl = output_reg + 0x10;
|
|
uint32_t ch_data = ch_ctl + 4;
|
|
@@ -223,19 +222,27 @@ intel_dp_aux_ch(struct intel_output *intel_output,
|
|
uint32_t ctl;
|
|
uint32_t status;
|
|
uint32_t aux_clock_divider;
|
|
- int try;
|
|
+ int try, precharge;
|
|
|
|
/* The clock divider is based off the hrawclk,
|
|
* and would like to run at 2MHz. So, take the
|
|
* hrawclk value and divide by 2 and use that
|
|
*/
|
|
- if (IS_eDP(intel_output))
|
|
- aux_clock_divider = 225; /* eDP input clock at 450Mhz */
|
|
- else if (IS_IRONLAKE(dev))
|
|
+ if (IS_eDP(intel_encoder)) {
|
|
+ if (IS_GEN6(dev))
|
|
+ aux_clock_divider = 200; /* SNB eDP input clock at 400Mhz */
|
|
+ else
|
|
+ aux_clock_divider = 225; /* eDP input clock at 450Mhz */
|
|
+ } else if (HAS_PCH_SPLIT(dev))
|
|
aux_clock_divider = 62; /* IRL input clock fixed at 125Mhz */
|
|
else
|
|
aux_clock_divider = intel_hrawclk(dev) / 2;
|
|
|
|
+ if (IS_GEN6(dev))
|
|
+ precharge = 3;
|
|
+ else
|
|
+ precharge = 5;
|
|
+
|
|
/* Must try at least 3 times according to DP spec */
|
|
for (try = 0; try < 5; try++) {
|
|
/* Load the send data into the aux channel data registers */
|
|
@@ -248,7 +255,7 @@ intel_dp_aux_ch(struct intel_output *intel_output,
|
|
ctl = (DP_AUX_CH_CTL_SEND_BUSY |
|
|
DP_AUX_CH_CTL_TIME_OUT_400us |
|
|
(send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) |
|
|
- (5 << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) |
|
|
+ (precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) |
|
|
(aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT) |
|
|
DP_AUX_CH_CTL_DONE |
|
|
DP_AUX_CH_CTL_TIME_OUT_ERROR |
|
|
@@ -312,7 +319,7 @@ intel_dp_aux_ch(struct intel_output *intel_output,
|
|
|
|
/* Write data to the aux channel in native mode */
|
|
static int
|
|
-intel_dp_aux_native_write(struct intel_output *intel_output,
|
|
+intel_dp_aux_native_write(struct intel_encoder *intel_encoder,
|
|
uint16_t address, uint8_t *send, int send_bytes)
|
|
{
|
|
int ret;
|
|
@@ -329,7 +336,7 @@ intel_dp_aux_native_write(struct intel_output *intel_output,
|
|
memcpy(&msg[4], send, send_bytes);
|
|
msg_bytes = send_bytes + 4;
|
|
for (;;) {
|
|
- ret = intel_dp_aux_ch(intel_output, msg, msg_bytes, &ack, 1);
|
|
+ ret = intel_dp_aux_ch(intel_encoder, msg, msg_bytes, &ack, 1);
|
|
if (ret < 0)
|
|
return ret;
|
|
if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK)
|
|
@@ -344,15 +351,15 @@ intel_dp_aux_native_write(struct intel_output *intel_output,
|
|
|
|
/* Write a single byte to the aux channel in native mode */
|
|
static int
|
|
-intel_dp_aux_native_write_1(struct intel_output *intel_output,
|
|
+intel_dp_aux_native_write_1(struct intel_encoder *intel_encoder,
|
|
uint16_t address, uint8_t byte)
|
|
{
|
|
- return intel_dp_aux_native_write(intel_output, address, &byte, 1);
|
|
+ return intel_dp_aux_native_write(intel_encoder, address, &byte, 1);
|
|
}
|
|
|
|
/* read bytes from a native aux channel */
|
|
static int
|
|
-intel_dp_aux_native_read(struct intel_output *intel_output,
|
|
+intel_dp_aux_native_read(struct intel_encoder *intel_encoder,
|
|
uint16_t address, uint8_t *recv, int recv_bytes)
|
|
{
|
|
uint8_t msg[4];
|
|
@@ -371,7 +378,7 @@ intel_dp_aux_native_read(struct intel_output *intel_output,
|
|
reply_bytes = recv_bytes + 1;
|
|
|
|
for (;;) {
|
|
- ret = intel_dp_aux_ch(intel_output, msg, msg_bytes,
|
|
+ ret = intel_dp_aux_ch(intel_encoder, msg, msg_bytes,
|
|
reply, reply_bytes);
|
|
if (ret == 0)
|
|
return -EPROTO;
|
|
@@ -397,7 +404,7 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
|
|
struct intel_dp_priv *dp_priv = container_of(adapter,
|
|
struct intel_dp_priv,
|
|
adapter);
|
|
- struct intel_output *intel_output = dp_priv->intel_output;
|
|
+ struct intel_encoder *intel_encoder = dp_priv->intel_encoder;
|
|
uint16_t address = algo_data->address;
|
|
uint8_t msg[5];
|
|
uint8_t reply[2];
|
|
@@ -436,7 +443,7 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
|
|
}
|
|
|
|
for (;;) {
|
|
- ret = intel_dp_aux_ch(intel_output,
|
|
+ ret = intel_dp_aux_ch(intel_encoder,
|
|
msg, msg_bytes,
|
|
reply, reply_bytes);
|
|
if (ret < 0) {
|
|
@@ -464,9 +471,10 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
|
|
}
|
|
|
|
static int
|
|
-intel_dp_i2c_init(struct intel_output *intel_output, const char *name)
|
|
+intel_dp_i2c_init(struct intel_encoder *intel_encoder,
|
|
+ struct intel_connector *intel_connector, const char *name)
|
|
{
|
|
- struct intel_dp_priv *dp_priv = intel_output->dev_priv;
|
|
+ struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
|
|
|
|
DRM_DEBUG_KMS("i2c_init %s\n", name);
|
|
dp_priv->algo.running = false;
|
|
@@ -479,7 +487,7 @@ intel_dp_i2c_init(struct intel_output *intel_output, const char *name)
|
|
strncpy (dp_priv->adapter.name, name, sizeof(dp_priv->adapter.name) - 1);
|
|
dp_priv->adapter.name[sizeof(dp_priv->adapter.name) - 1] = '\0';
|
|
dp_priv->adapter.algo_data = &dp_priv->algo;
|
|
- dp_priv->adapter.dev.parent = &intel_output->base.kdev;
|
|
+ dp_priv->adapter.dev.parent = &intel_connector->base.kdev;
|
|
|
|
return i2c_dp_aux_add_bus(&dp_priv->adapter);
|
|
}
|
|
@@ -488,18 +496,18 @@ static bool
|
|
intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
|
|
struct drm_display_mode *adjusted_mode)
|
|
{
|
|
- struct intel_output *intel_output = enc_to_intel_output(encoder);
|
|
- struct intel_dp_priv *dp_priv = intel_output->dev_priv;
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
|
|
int lane_count, clock;
|
|
- int max_lane_count = intel_dp_max_lane_count(intel_output);
|
|
- int max_clock = intel_dp_max_link_bw(intel_output) == DP_LINK_BW_2_7 ? 1 : 0;
|
|
+ int max_lane_count = intel_dp_max_lane_count(intel_encoder);
|
|
+ int max_clock = intel_dp_max_link_bw(intel_encoder) == DP_LINK_BW_2_7 ? 1 : 0;
|
|
static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 };
|
|
|
|
for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) {
|
|
for (clock = 0; clock <= max_clock; clock++) {
|
|
int link_avail = intel_dp_link_clock(bws[clock]) * lane_count;
|
|
|
|
- if (intel_dp_link_required(encoder->dev, intel_output, mode->clock)
|
|
+ if (intel_dp_link_required(encoder->dev, intel_encoder, mode->clock)
|
|
<= link_avail) {
|
|
dp_priv->link_bw = bws[clock];
|
|
dp_priv->lane_count = lane_count;
|
|
@@ -554,23 +562,26 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
|
|
{
|
|
struct drm_device *dev = crtc->dev;
|
|
struct drm_mode_config *mode_config = &dev->mode_config;
|
|
- struct drm_connector *connector;
|
|
+ struct drm_encoder *encoder;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
int lane_count = 4;
|
|
struct intel_dp_m_n m_n;
|
|
|
|
/*
|
|
- * Find the lane count in the intel_output private
|
|
+ * Find the lane count in the intel_encoder private
|
|
*/
|
|
- list_for_each_entry(connector, &mode_config->connector_list, head) {
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
- struct intel_dp_priv *dp_priv = intel_output->dev_priv;
|
|
+ list_for_each_entry(encoder, &mode_config->encoder_list, head) {
|
|
+ struct intel_encoder *intel_encoder;
|
|
+ struct intel_dp_priv *dp_priv;
|
|
|
|
- if (!connector->encoder || connector->encoder->crtc != crtc)
|
|
+ if (!encoder || encoder->crtc != crtc)
|
|
continue;
|
|
|
|
- if (intel_output->type == INTEL_OUTPUT_DISPLAYPORT) {
|
|
+ intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ dp_priv = intel_encoder->dev_priv;
|
|
+
|
|
+ if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT) {
|
|
lane_count = dp_priv->lane_count;
|
|
break;
|
|
}
|
|
@@ -584,7 +595,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
|
|
intel_dp_compute_m_n(3, lane_count,
|
|
mode->clock, adjusted_mode->clock, &m_n);
|
|
|
|
- if (IS_IRONLAKE(dev)) {
|
|
+ if (HAS_PCH_SPLIT(dev)) {
|
|
if (intel_crtc->pipe == 0) {
|
|
I915_WRITE(TRANSA_DATA_M1,
|
|
((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) |
|
|
@@ -625,16 +636,24 @@ static void
|
|
intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
|
|
struct drm_display_mode *adjusted_mode)
|
|
{
|
|
- struct intel_output *intel_output = enc_to_intel_output(encoder);
|
|
- struct intel_dp_priv *dp_priv = intel_output->dev_priv;
|
|
- struct drm_crtc *crtc = intel_output->enc.crtc;
|
|
+ struct drm_device *dev = encoder->dev;
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
|
|
+ struct drm_crtc *crtc = intel_encoder->enc.crtc;
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
|
|
- dp_priv->DP = (DP_LINK_TRAIN_OFF |
|
|
- DP_VOLTAGE_0_4 |
|
|
- DP_PRE_EMPHASIS_0 |
|
|
- DP_SYNC_VS_HIGH |
|
|
- DP_SYNC_HS_HIGH);
|
|
+ dp_priv->DP = (DP_VOLTAGE_0_4 |
|
|
+ DP_PRE_EMPHASIS_0);
|
|
+
|
|
+ if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
|
|
+ dp_priv->DP |= DP_SYNC_HS_HIGH;
|
|
+ if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
|
|
+ dp_priv->DP |= DP_SYNC_VS_HIGH;
|
|
+
|
|
+ if (HAS_PCH_CPT(dev) && !IS_eDP(intel_encoder))
|
|
+ dp_priv->DP |= DP_LINK_TRAIN_OFF_CPT;
|
|
+ else
|
|
+ dp_priv->DP |= DP_LINK_TRAIN_OFF;
|
|
|
|
switch (dp_priv->lane_count) {
|
|
case 1:
|
|
@@ -663,10 +682,11 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
|
|
dp_priv->DP |= DP_ENHANCED_FRAMING;
|
|
}
|
|
|
|
- if (intel_crtc->pipe == 1)
|
|
+ /* CPT DP's pipe select is decided in TRANS_DP_CTL */
|
|
+ if (intel_crtc->pipe == 1 && !HAS_PCH_CPT(dev))
|
|
dp_priv->DP |= DP_PIPEB_SELECT;
|
|
|
|
- if (IS_eDP(intel_output)) {
|
|
+ if (IS_eDP(intel_encoder)) {
|
|
/* don't miss out required setting for eDP */
|
|
dp_priv->DP |= DP_PLL_ENABLE;
|
|
if (adjusted_mode->clock < 200000)
|
|
@@ -701,22 +721,22 @@ static void ironlake_edp_backlight_off (struct drm_device *dev)
|
|
static void
|
|
intel_dp_dpms(struct drm_encoder *encoder, int mode)
|
|
{
|
|
- struct intel_output *intel_output = enc_to_intel_output(encoder);
|
|
- struct intel_dp_priv *dp_priv = intel_output->dev_priv;
|
|
- struct drm_device *dev = intel_output->base.dev;
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
|
|
+ struct drm_device *dev = encoder->dev;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
uint32_t dp_reg = I915_READ(dp_priv->output_reg);
|
|
|
|
if (mode != DRM_MODE_DPMS_ON) {
|
|
if (dp_reg & DP_PORT_EN) {
|
|
- intel_dp_link_down(intel_output, dp_priv->DP);
|
|
- if (IS_eDP(intel_output))
|
|
+ intel_dp_link_down(intel_encoder, dp_priv->DP);
|
|
+ if (IS_eDP(intel_encoder))
|
|
ironlake_edp_backlight_off(dev);
|
|
}
|
|
} else {
|
|
if (!(dp_reg & DP_PORT_EN)) {
|
|
- intel_dp_link_train(intel_output, dp_priv->DP, dp_priv->link_configuration);
|
|
- if (IS_eDP(intel_output))
|
|
+ intel_dp_link_train(intel_encoder, dp_priv->DP, dp_priv->link_configuration);
|
|
+ if (IS_eDP(intel_encoder))
|
|
ironlake_edp_backlight_on(dev);
|
|
}
|
|
}
|
|
@@ -728,12 +748,12 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
|
|
* link status information
|
|
*/
|
|
static bool
|
|
-intel_dp_get_link_status(struct intel_output *intel_output,
|
|
+intel_dp_get_link_status(struct intel_encoder *intel_encoder,
|
|
uint8_t link_status[DP_LINK_STATUS_SIZE])
|
|
{
|
|
int ret;
|
|
|
|
- ret = intel_dp_aux_native_read(intel_output,
|
|
+ ret = intel_dp_aux_native_read(intel_encoder,
|
|
DP_LANE0_1_STATUS,
|
|
link_status, DP_LINK_STATUS_SIZE);
|
|
if (ret != DP_LINK_STATUS_SIZE)
|
|
@@ -748,20 +768,6 @@ intel_dp_link_status(uint8_t link_status[DP_LINK_STATUS_SIZE],
|
|
return link_status[r - DP_LANE0_1_STATUS];
|
|
}
|
|
|
|
-static void
|
|
-intel_dp_save(struct drm_connector *connector)
|
|
-{
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
- struct drm_device *dev = intel_output->base.dev;
|
|
- struct drm_i915_private *dev_priv = dev->dev_private;
|
|
- struct intel_dp_priv *dp_priv = intel_output->dev_priv;
|
|
-
|
|
- dp_priv->save_DP = I915_READ(dp_priv->output_reg);
|
|
- intel_dp_aux_native_read(intel_output, DP_LINK_BW_SET,
|
|
- dp_priv->save_link_configuration,
|
|
- sizeof (dp_priv->save_link_configuration));
|
|
-}
|
|
-
|
|
static uint8_t
|
|
intel_get_adjust_request_voltage(uint8_t link_status[DP_LINK_STATUS_SIZE],
|
|
int lane)
|
|
@@ -824,7 +830,7 @@ intel_dp_pre_emphasis_max(uint8_t voltage_swing)
|
|
}
|
|
|
|
static void
|
|
-intel_get_adjust_train(struct intel_output *intel_output,
|
|
+intel_get_adjust_train(struct intel_encoder *intel_encoder,
|
|
uint8_t link_status[DP_LINK_STATUS_SIZE],
|
|
int lane_count,
|
|
uint8_t train_set[4])
|
|
@@ -891,6 +897,25 @@ intel_dp_signal_levels(uint8_t train_set, int lane_count)
|
|
return signal_levels;
|
|
}
|
|
|
|
+/* Gen6's DP voltage swing and pre-emphasis control */
|
|
+static uint32_t
|
|
+intel_gen6_edp_signal_levels(uint8_t train_set)
|
|
+{
|
|
+ switch (train_set & (DP_TRAIN_VOLTAGE_SWING_MASK|DP_TRAIN_PRE_EMPHASIS_MASK)) {
|
|
+ case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_0:
|
|
+ return EDP_LINK_TRAIN_400MV_0DB_SNB_B;
|
|
+ case DP_TRAIN_VOLTAGE_SWING_400 | DP_TRAIN_PRE_EMPHASIS_6:
|
|
+ return EDP_LINK_TRAIN_400MV_6DB_SNB_B;
|
|
+ case DP_TRAIN_VOLTAGE_SWING_600 | DP_TRAIN_PRE_EMPHASIS_3_5:
|
|
+ return EDP_LINK_TRAIN_600MV_3_5DB_SNB_B;
|
|
+ case DP_TRAIN_VOLTAGE_SWING_800 | DP_TRAIN_PRE_EMPHASIS_0:
|
|
+ return EDP_LINK_TRAIN_800MV_0DB_SNB_B;
|
|
+ default:
|
|
+ DRM_DEBUG_KMS("Unsupported voltage swing/pre-emphasis level\n");
|
|
+ return EDP_LINK_TRAIN_400MV_0DB_SNB_B;
|
|
+ }
|
|
+}
|
|
+
|
|
static uint8_t
|
|
intel_get_lane_status(uint8_t link_status[DP_LINK_STATUS_SIZE],
|
|
int lane)
|
|
@@ -941,15 +966,15 @@ intel_channel_eq_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count)
|
|
}
|
|
|
|
static bool
|
|
-intel_dp_set_link_train(struct intel_output *intel_output,
|
|
+intel_dp_set_link_train(struct intel_encoder *intel_encoder,
|
|
uint32_t dp_reg_value,
|
|
uint8_t dp_train_pat,
|
|
uint8_t train_set[4],
|
|
bool first)
|
|
{
|
|
- struct drm_device *dev = intel_output->base.dev;
|
|
+ struct drm_device *dev = intel_encoder->enc.dev;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
- struct intel_dp_priv *dp_priv = intel_output->dev_priv;
|
|
+ struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
|
|
int ret;
|
|
|
|
I915_WRITE(dp_priv->output_reg, dp_reg_value);
|
|
@@ -957,11 +982,11 @@ intel_dp_set_link_train(struct intel_output *intel_output,
|
|
if (first)
|
|
intel_wait_for_vblank(dev);
|
|
|
|
- intel_dp_aux_native_write_1(intel_output,
|
|
+ intel_dp_aux_native_write_1(intel_encoder,
|
|
DP_TRAINING_PATTERN_SET,
|
|
dp_train_pat);
|
|
|
|
- ret = intel_dp_aux_native_write(intel_output,
|
|
+ ret = intel_dp_aux_native_write(intel_encoder,
|
|
DP_TRAINING_LANE0_SET, train_set, 4);
|
|
if (ret != 4)
|
|
return false;
|
|
@@ -970,12 +995,12 @@ intel_dp_set_link_train(struct intel_output *intel_output,
|
|
}
|
|
|
|
static void
|
|
-intel_dp_link_train(struct intel_output *intel_output, uint32_t DP,
|
|
+intel_dp_link_train(struct intel_encoder *intel_encoder, uint32_t DP,
|
|
uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE])
|
|
{
|
|
- struct drm_device *dev = intel_output->base.dev;
|
|
+ struct drm_device *dev = intel_encoder->enc.dev;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
- struct intel_dp_priv *dp_priv = intel_output->dev_priv;
|
|
+ struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
|
|
uint8_t train_set[4];
|
|
uint8_t link_status[DP_LINK_STATUS_SIZE];
|
|
int i;
|
|
@@ -984,30 +1009,45 @@ intel_dp_link_train(struct intel_output *intel_output, uint32_t DP,
|
|
bool channel_eq = false;
|
|
bool first = true;
|
|
int tries;
|
|
+ u32 reg;
|
|
|
|
/* Write the link configuration data */
|
|
- intel_dp_aux_native_write(intel_output, 0x100,
|
|
+ intel_dp_aux_native_write(intel_encoder, DP_LINK_BW_SET,
|
|
link_configuration, DP_LINK_CONFIGURATION_SIZE);
|
|
|
|
DP |= DP_PORT_EN;
|
|
- DP &= ~DP_LINK_TRAIN_MASK;
|
|
+ if (HAS_PCH_CPT(dev) && !IS_eDP(intel_encoder))
|
|
+ DP &= ~DP_LINK_TRAIN_MASK_CPT;
|
|
+ else
|
|
+ DP &= ~DP_LINK_TRAIN_MASK;
|
|
memset(train_set, 0, 4);
|
|
voltage = 0xff;
|
|
tries = 0;
|
|
clock_recovery = false;
|
|
for (;;) {
|
|
/* Use train_set[0] to set the voltage and pre emphasis values */
|
|
- uint32_t signal_levels = intel_dp_signal_levels(train_set[0], dp_priv->lane_count);
|
|
- DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
|
|
+ uint32_t signal_levels;
|
|
+ if (IS_GEN6(dev) && IS_eDP(intel_encoder)) {
|
|
+ signal_levels = intel_gen6_edp_signal_levels(train_set[0]);
|
|
+ DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels;
|
|
+ } else {
|
|
+ signal_levels = intel_dp_signal_levels(train_set[0], dp_priv->lane_count);
|
|
+ DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
|
|
+ }
|
|
|
|
- if (!intel_dp_set_link_train(intel_output, DP | DP_LINK_TRAIN_PAT_1,
|
|
+ if (HAS_PCH_CPT(dev) && !IS_eDP(intel_encoder))
|
|
+ reg = DP | DP_LINK_TRAIN_PAT_1_CPT;
|
|
+ else
|
|
+ reg = DP | DP_LINK_TRAIN_PAT_1;
|
|
+
|
|
+ if (!intel_dp_set_link_train(intel_encoder, reg,
|
|
DP_TRAINING_PATTERN_1, train_set, first))
|
|
break;
|
|
first = false;
|
|
/* Set training pattern 1 */
|
|
|
|
udelay(100);
|
|
- if (!intel_dp_get_link_status(intel_output, link_status))
|
|
+ if (!intel_dp_get_link_status(intel_encoder, link_status))
|
|
break;
|
|
|
|
if (intel_clock_recovery_ok(link_status, dp_priv->lane_count)) {
|
|
@@ -1032,7 +1072,7 @@ intel_dp_link_train(struct intel_output *intel_output, uint32_t DP,
|
|
voltage = train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
|
|
|
|
/* Compute new train_set as requested by target */
|
|
- intel_get_adjust_train(intel_output, link_status, dp_priv->lane_count, train_set);
|
|
+ intel_get_adjust_train(intel_encoder, link_status, dp_priv->lane_count, train_set);
|
|
}
|
|
|
|
/* channel equalization */
|
|
@@ -1040,17 +1080,29 @@ intel_dp_link_train(struct intel_output *intel_output, uint32_t DP,
|
|
channel_eq = false;
|
|
for (;;) {
|
|
/* Use train_set[0] to set the voltage and pre emphasis values */
|
|
- uint32_t signal_levels = intel_dp_signal_levels(train_set[0], dp_priv->lane_count);
|
|
- DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
|
|
+ uint32_t signal_levels;
|
|
+
|
|
+ if (IS_GEN6(dev) && IS_eDP(intel_encoder)) {
|
|
+ signal_levels = intel_gen6_edp_signal_levels(train_set[0]);
|
|
+ DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels;
|
|
+ } else {
|
|
+ signal_levels = intel_dp_signal_levels(train_set[0], dp_priv->lane_count);
|
|
+ DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
|
|
+ }
|
|
+
|
|
+ if (HAS_PCH_CPT(dev) && !IS_eDP(intel_encoder))
|
|
+ reg = DP | DP_LINK_TRAIN_PAT_2_CPT;
|
|
+ else
|
|
+ reg = DP | DP_LINK_TRAIN_PAT_2;
|
|
|
|
/* channel eq pattern */
|
|
- if (!intel_dp_set_link_train(intel_output, DP | DP_LINK_TRAIN_PAT_2,
|
|
+ if (!intel_dp_set_link_train(intel_encoder, reg,
|
|
DP_TRAINING_PATTERN_2, train_set,
|
|
false))
|
|
break;
|
|
|
|
udelay(400);
|
|
- if (!intel_dp_get_link_status(intel_output, link_status))
|
|
+ if (!intel_dp_get_link_status(intel_encoder, link_status))
|
|
break;
|
|
|
|
if (intel_channel_eq_ok(link_status, dp_priv->lane_count)) {
|
|
@@ -1063,56 +1115,55 @@ intel_dp_link_train(struct intel_output *intel_output, uint32_t DP,
|
|
break;
|
|
|
|
/* Compute new train_set as requested by target */
|
|
- intel_get_adjust_train(intel_output, link_status, dp_priv->lane_count, train_set);
|
|
+ intel_get_adjust_train(intel_encoder, link_status, dp_priv->lane_count, train_set);
|
|
++tries;
|
|
}
|
|
|
|
- I915_WRITE(dp_priv->output_reg, DP | DP_LINK_TRAIN_OFF);
|
|
+ if (HAS_PCH_CPT(dev) && !IS_eDP(intel_encoder))
|
|
+ reg = DP | DP_LINK_TRAIN_OFF_CPT;
|
|
+ else
|
|
+ reg = DP | DP_LINK_TRAIN_OFF;
|
|
+
|
|
+ I915_WRITE(dp_priv->output_reg, reg);
|
|
POSTING_READ(dp_priv->output_reg);
|
|
- intel_dp_aux_native_write_1(intel_output,
|
|
+ intel_dp_aux_native_write_1(intel_encoder,
|
|
DP_TRAINING_PATTERN_SET, DP_TRAINING_PATTERN_DISABLE);
|
|
}
|
|
|
|
static void
|
|
-intel_dp_link_down(struct intel_output *intel_output, uint32_t DP)
|
|
+intel_dp_link_down(struct intel_encoder *intel_encoder, uint32_t DP)
|
|
{
|
|
- struct drm_device *dev = intel_output->base.dev;
|
|
+ struct drm_device *dev = intel_encoder->enc.dev;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
- struct intel_dp_priv *dp_priv = intel_output->dev_priv;
|
|
+ struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
|
|
|
|
DRM_DEBUG_KMS("\n");
|
|
|
|
- if (IS_eDP(intel_output)) {
|
|
+ if (IS_eDP(intel_encoder)) {
|
|
DP &= ~DP_PLL_ENABLE;
|
|
I915_WRITE(dp_priv->output_reg, DP);
|
|
POSTING_READ(dp_priv->output_reg);
|
|
udelay(100);
|
|
}
|
|
|
|
- DP &= ~DP_LINK_TRAIN_MASK;
|
|
- I915_WRITE(dp_priv->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE);
|
|
- POSTING_READ(dp_priv->output_reg);
|
|
+ if (HAS_PCH_CPT(dev) && !IS_eDP(intel_encoder)) {
|
|
+ DP &= ~DP_LINK_TRAIN_MASK_CPT;
|
|
+ I915_WRITE(dp_priv->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE_CPT);
|
|
+ POSTING_READ(dp_priv->output_reg);
|
|
+ } else {
|
|
+ DP &= ~DP_LINK_TRAIN_MASK;
|
|
+ I915_WRITE(dp_priv->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE);
|
|
+ POSTING_READ(dp_priv->output_reg);
|
|
+ }
|
|
|
|
udelay(17000);
|
|
|
|
- if (IS_eDP(intel_output))
|
|
+ if (IS_eDP(intel_encoder))
|
|
DP |= DP_LINK_TRAIN_OFF;
|
|
I915_WRITE(dp_priv->output_reg, DP & ~DP_PORT_EN);
|
|
POSTING_READ(dp_priv->output_reg);
|
|
}
|
|
|
|
-static void
|
|
-intel_dp_restore(struct drm_connector *connector)
|
|
-{
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
- struct intel_dp_priv *dp_priv = intel_output->dev_priv;
|
|
-
|
|
- if (dp_priv->save_DP & DP_PORT_EN)
|
|
- intel_dp_link_train(intel_output, dp_priv->save_DP, dp_priv->save_link_configuration);
|
|
- else
|
|
- intel_dp_link_down(intel_output, dp_priv->save_DP);
|
|
-}
|
|
-
|
|
/*
|
|
* According to DP spec
|
|
* 5.1.2:
|
|
@@ -1123,32 +1174,33 @@ intel_dp_restore(struct drm_connector *connector)
|
|
*/
|
|
|
|
static void
|
|
-intel_dp_check_link_status(struct intel_output *intel_output)
|
|
+intel_dp_check_link_status(struct intel_encoder *intel_encoder)
|
|
{
|
|
- struct intel_dp_priv *dp_priv = intel_output->dev_priv;
|
|
+ struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
|
|
uint8_t link_status[DP_LINK_STATUS_SIZE];
|
|
|
|
- if (!intel_output->enc.crtc)
|
|
+ if (!intel_encoder->enc.crtc)
|
|
return;
|
|
|
|
- if (!intel_dp_get_link_status(intel_output, link_status)) {
|
|
- intel_dp_link_down(intel_output, dp_priv->DP);
|
|
+ if (!intel_dp_get_link_status(intel_encoder, link_status)) {
|
|
+ intel_dp_link_down(intel_encoder, dp_priv->DP);
|
|
return;
|
|
}
|
|
|
|
if (!intel_channel_eq_ok(link_status, dp_priv->lane_count))
|
|
- intel_dp_link_train(intel_output, dp_priv->DP, dp_priv->link_configuration);
|
|
+ intel_dp_link_train(intel_encoder, dp_priv->DP, dp_priv->link_configuration);
|
|
}
|
|
|
|
static enum drm_connector_status
|
|
ironlake_dp_detect(struct drm_connector *connector)
|
|
{
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
- struct intel_dp_priv *dp_priv = intel_output->dev_priv;
|
|
+ struct drm_encoder *encoder = intel_attached_encoder(connector);
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
|
|
enum drm_connector_status status;
|
|
|
|
status = connector_status_disconnected;
|
|
- if (intel_dp_aux_native_read(intel_output,
|
|
+ if (intel_dp_aux_native_read(intel_encoder,
|
|
0x000, dp_priv->dpcd,
|
|
sizeof (dp_priv->dpcd)) == sizeof (dp_priv->dpcd))
|
|
{
|
|
@@ -1167,28 +1219,19 @@ ironlake_dp_detect(struct drm_connector *connector)
|
|
static enum drm_connector_status
|
|
intel_dp_detect(struct drm_connector *connector)
|
|
{
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
- struct drm_device *dev = intel_output->base.dev;
|
|
+ struct drm_encoder *encoder = intel_attached_encoder(connector);
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ struct drm_device *dev = intel_encoder->enc.dev;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
- struct intel_dp_priv *dp_priv = intel_output->dev_priv;
|
|
+ struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
|
|
uint32_t temp, bit;
|
|
enum drm_connector_status status;
|
|
|
|
dp_priv->has_audio = false;
|
|
|
|
- if (IS_IRONLAKE(dev))
|
|
+ if (HAS_PCH_SPLIT(dev))
|
|
return ironlake_dp_detect(connector);
|
|
|
|
- temp = I915_READ(PORT_HOTPLUG_EN);
|
|
-
|
|
- I915_WRITE(PORT_HOTPLUG_EN,
|
|
- temp |
|
|
- DPB_HOTPLUG_INT_EN |
|
|
- DPC_HOTPLUG_INT_EN |
|
|
- DPD_HOTPLUG_INT_EN);
|
|
-
|
|
- POSTING_READ(PORT_HOTPLUG_EN);
|
|
-
|
|
switch (dp_priv->output_reg) {
|
|
case DP_B:
|
|
bit = DPB_HOTPLUG_INT_STATUS;
|
|
@@ -1209,7 +1252,7 @@ intel_dp_detect(struct drm_connector *connector)
|
|
return connector_status_disconnected;
|
|
|
|
status = connector_status_disconnected;
|
|
- if (intel_dp_aux_native_read(intel_output,
|
|
+ if (intel_dp_aux_native_read(intel_encoder,
|
|
0x000, dp_priv->dpcd,
|
|
sizeof (dp_priv->dpcd)) == sizeof (dp_priv->dpcd))
|
|
{
|
|
@@ -1221,20 +1264,21 @@ intel_dp_detect(struct drm_connector *connector)
|
|
|
|
static int intel_dp_get_modes(struct drm_connector *connector)
|
|
{
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
- struct drm_device *dev = intel_output->base.dev;
|
|
+ struct drm_encoder *encoder = intel_attached_encoder(connector);
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ struct drm_device *dev = intel_encoder->enc.dev;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
int ret;
|
|
|
|
/* We should parse the EDID data and find out if it has an audio sink
|
|
*/
|
|
|
|
- ret = intel_ddc_get_modes(intel_output);
|
|
+ ret = intel_ddc_get_modes(connector, intel_encoder->ddc_bus);
|
|
if (ret)
|
|
return ret;
|
|
|
|
/* if eDP has no EDID, try to use fixed panel mode from VBT */
|
|
- if (IS_eDP(intel_output)) {
|
|
+ if (IS_eDP(intel_encoder)) {
|
|
if (dev_priv->panel_fixed_mode != NULL) {
|
|
struct drm_display_mode *mode;
|
|
mode = drm_mode_duplicate(dev, dev_priv->panel_fixed_mode);
|
|
@@ -1248,13 +1292,9 @@ static int intel_dp_get_modes(struct drm_connector *connector)
|
|
static void
|
|
intel_dp_destroy (struct drm_connector *connector)
|
|
{
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
-
|
|
- if (intel_output->i2c_bus)
|
|
- intel_i2c_destroy(intel_output->i2c_bus);
|
|
drm_sysfs_connector_remove(connector);
|
|
drm_connector_cleanup(connector);
|
|
- kfree(intel_output);
|
|
+ kfree(connector);
|
|
}
|
|
|
|
static const struct drm_encoder_helper_funcs intel_dp_helper_funcs = {
|
|
@@ -1267,8 +1307,6 @@ static const struct drm_encoder_helper_funcs intel_dp_helper_funcs = {
|
|
|
|
static const struct drm_connector_funcs intel_dp_connector_funcs = {
|
|
.dpms = drm_helper_connector_dpms,
|
|
- .save = intel_dp_save,
|
|
- .restore = intel_dp_restore,
|
|
.detect = intel_dp_detect,
|
|
.fill_modes = drm_helper_probe_single_connector_modes,
|
|
.destroy = intel_dp_destroy,
|
|
@@ -1277,12 +1315,17 @@ static const struct drm_connector_funcs intel_dp_connector_funcs = {
|
|
static const struct drm_connector_helper_funcs intel_dp_connector_helper_funcs = {
|
|
.get_modes = intel_dp_get_modes,
|
|
.mode_valid = intel_dp_mode_valid,
|
|
- .best_encoder = intel_best_encoder,
|
|
+ .best_encoder = intel_attached_encoder,
|
|
};
|
|
|
|
static void intel_dp_enc_destroy(struct drm_encoder *encoder)
|
|
{
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+
|
|
+ if (intel_encoder->i2c_bus)
|
|
+ intel_i2c_destroy(intel_encoder->i2c_bus);
|
|
drm_encoder_cleanup(encoder);
|
|
+ kfree(intel_encoder);
|
|
}
|
|
|
|
static const struct drm_encoder_funcs intel_dp_enc_funcs = {
|
|
@@ -1290,12 +1333,34 @@ static const struct drm_encoder_funcs intel_dp_enc_funcs = {
|
|
};
|
|
|
|
void
|
|
-intel_dp_hot_plug(struct intel_output *intel_output)
|
|
+intel_dp_hot_plug(struct intel_encoder *intel_encoder)
|
|
{
|
|
- struct intel_dp_priv *dp_priv = intel_output->dev_priv;
|
|
+ struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
|
|
|
|
if (dp_priv->dpms_mode == DRM_MODE_DPMS_ON)
|
|
- intel_dp_check_link_status(intel_output);
|
|
+ intel_dp_check_link_status(intel_encoder);
|
|
+}
|
|
+
|
|
+/* Return which DP Port should be selected for Transcoder DP control */
|
|
+int
|
|
+intel_trans_dp_port_sel (struct drm_crtc *crtc)
|
|
+{
|
|
+ struct drm_device *dev = crtc->dev;
|
|
+ struct drm_mode_config *mode_config = &dev->mode_config;
|
|
+ struct drm_encoder *encoder;
|
|
+ struct intel_encoder *intel_encoder = NULL;
|
|
+
|
|
+ list_for_each_entry(encoder, &mode_config->encoder_list, head) {
|
|
+ if (!encoder || encoder->crtc != crtc)
|
|
+ continue;
|
|
+
|
|
+ intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT) {
|
|
+ struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
|
|
+ return dp_priv->output_reg;
|
|
+ }
|
|
+ }
|
|
+ return -1;
|
|
}
|
|
|
|
void
|
|
@@ -1303,53 +1368,60 @@ intel_dp_init(struct drm_device *dev, int output_reg)
|
|
{
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
struct drm_connector *connector;
|
|
- struct intel_output *intel_output;
|
|
+ struct intel_encoder *intel_encoder;
|
|
+ struct intel_connector *intel_connector;
|
|
struct intel_dp_priv *dp_priv;
|
|
const char *name = NULL;
|
|
|
|
- intel_output = kcalloc(sizeof(struct intel_output) +
|
|
+ intel_encoder = kcalloc(sizeof(struct intel_encoder) +
|
|
sizeof(struct intel_dp_priv), 1, GFP_KERNEL);
|
|
- if (!intel_output)
|
|
+ if (!intel_encoder)
|
|
return;
|
|
|
|
- dp_priv = (struct intel_dp_priv *)(intel_output + 1);
|
|
+ intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
|
|
+ if (!intel_connector) {
|
|
+ kfree(intel_encoder);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ dp_priv = (struct intel_dp_priv *)(intel_encoder + 1);
|
|
|
|
- connector = &intel_output->base;
|
|
+ connector = &intel_connector->base;
|
|
drm_connector_init(dev, connector, &intel_dp_connector_funcs,
|
|
DRM_MODE_CONNECTOR_DisplayPort);
|
|
drm_connector_helper_add(connector, &intel_dp_connector_helper_funcs);
|
|
|
|
if (output_reg == DP_A)
|
|
- intel_output->type = INTEL_OUTPUT_EDP;
|
|
+ intel_encoder->type = INTEL_OUTPUT_EDP;
|
|
else
|
|
- intel_output->type = INTEL_OUTPUT_DISPLAYPORT;
|
|
+ intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
|
|
|
|
if (output_reg == DP_B || output_reg == PCH_DP_B)
|
|
- intel_output->clone_mask = (1 << INTEL_DP_B_CLONE_BIT);
|
|
+ intel_encoder->clone_mask = (1 << INTEL_DP_B_CLONE_BIT);
|
|
else if (output_reg == DP_C || output_reg == PCH_DP_C)
|
|
- intel_output->clone_mask = (1 << INTEL_DP_C_CLONE_BIT);
|
|
+ intel_encoder->clone_mask = (1 << INTEL_DP_C_CLONE_BIT);
|
|
else if (output_reg == DP_D || output_reg == PCH_DP_D)
|
|
- intel_output->clone_mask = (1 << INTEL_DP_D_CLONE_BIT);
|
|
+ intel_encoder->clone_mask = (1 << INTEL_DP_D_CLONE_BIT);
|
|
|
|
- if (IS_eDP(intel_output))
|
|
- intel_output->clone_mask = (1 << INTEL_EDP_CLONE_BIT);
|
|
+ if (IS_eDP(intel_encoder))
|
|
+ intel_encoder->clone_mask = (1 << INTEL_EDP_CLONE_BIT);
|
|
|
|
- intel_output->crtc_mask = (1 << 0) | (1 << 1);
|
|
+ intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
|
|
connector->interlace_allowed = true;
|
|
connector->doublescan_allowed = 0;
|
|
|
|
- dp_priv->intel_output = intel_output;
|
|
+ dp_priv->intel_encoder = intel_encoder;
|
|
dp_priv->output_reg = output_reg;
|
|
dp_priv->has_audio = false;
|
|
dp_priv->dpms_mode = DRM_MODE_DPMS_ON;
|
|
- intel_output->dev_priv = dp_priv;
|
|
+ intel_encoder->dev_priv = dp_priv;
|
|
|
|
- drm_encoder_init(dev, &intel_output->enc, &intel_dp_enc_funcs,
|
|
+ drm_encoder_init(dev, &intel_encoder->enc, &intel_dp_enc_funcs,
|
|
DRM_MODE_ENCODER_TMDS);
|
|
- drm_encoder_helper_add(&intel_output->enc, &intel_dp_helper_funcs);
|
|
+ drm_encoder_helper_add(&intel_encoder->enc, &intel_dp_helper_funcs);
|
|
|
|
- drm_mode_connector_attach_encoder(&intel_output->base,
|
|
- &intel_output->enc);
|
|
+ drm_mode_connector_attach_encoder(&intel_connector->base,
|
|
+ &intel_encoder->enc);
|
|
drm_sysfs_connector_add(connector);
|
|
|
|
/* Set up the DDC bus. */
|
|
@@ -1377,10 +1449,10 @@ intel_dp_init(struct drm_device *dev, int output_reg)
|
|
break;
|
|
}
|
|
|
|
- intel_dp_i2c_init(intel_output, name);
|
|
+ intel_dp_i2c_init(intel_encoder, intel_connector, name);
|
|
|
|
- intel_output->ddc_bus = &dp_priv->adapter;
|
|
- intel_output->hot_plug = intel_dp_hot_plug;
|
|
+ intel_encoder->ddc_bus = &dp_priv->adapter;
|
|
+ intel_encoder->hot_plug = intel_dp_hot_plug;
|
|
|
|
if (output_reg == DP_A) {
|
|
/* initialize panel mode from VBT if available for eDP */
|
|
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
|
|
--- a/drivers/gpu/drm/i915/intel_drv.h
|
|
+++ b/drivers/gpu/drm/i915/intel_drv.h
|
|
@@ -95,9 +95,7 @@ struct intel_framebuffer {
|
|
};
|
|
|
|
|
|
-struct intel_output {
|
|
- struct drm_connector base;
|
|
-
|
|
+struct intel_encoder {
|
|
struct drm_encoder enc;
|
|
int type;
|
|
struct i2c_adapter *i2c_bus;
|
|
@@ -105,11 +103,16 @@ struct intel_output {
|
|
bool load_detect_temp;
|
|
bool needs_tv_clock;
|
|
void *dev_priv;
|
|
- void (*hot_plug)(struct intel_output *);
|
|
+ void (*hot_plug)(struct intel_encoder *);
|
|
int crtc_mask;
|
|
int clone_mask;
|
|
};
|
|
|
|
+struct intel_connector {
|
|
+ struct drm_connector base;
|
|
+ void *dev_priv;
|
|
+};
|
|
+
|
|
struct intel_crtc;
|
|
struct intel_overlay {
|
|
struct drm_device *dev;
|
|
@@ -149,18 +152,19 @@ struct intel_crtc {
|
|
bool lowfreq_avail;
|
|
struct intel_overlay *overlay;
|
|
struct intel_unpin_work *unpin_work;
|
|
+ int fdi_lanes;
|
|
};
|
|
|
|
#define to_intel_crtc(x) container_of(x, struct intel_crtc, base)
|
|
-#define to_intel_output(x) container_of(x, struct intel_output, base)
|
|
-#define enc_to_intel_output(x) container_of(x, struct intel_output, enc)
|
|
+#define to_intel_connector(x) container_of(x, struct intel_connector, base)
|
|
+#define enc_to_intel_encoder(x) container_of(x, struct intel_encoder, enc)
|
|
#define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base)
|
|
|
|
struct i2c_adapter *intel_i2c_create(struct drm_device *dev, const u32 reg,
|
|
const char *name);
|
|
void intel_i2c_destroy(struct i2c_adapter *adapter);
|
|
-int intel_ddc_get_modes(struct intel_output *intel_output);
|
|
-extern bool intel_ddc_probe(struct intel_output *intel_output);
|
|
+int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter);
|
|
+extern bool intel_ddc_probe(struct intel_encoder *intel_encoder);
|
|
void intel_i2c_quirk_set(struct drm_device *dev, bool enable);
|
|
void intel_i2c_reset_gmbus(struct drm_device *dev);
|
|
|
|
@@ -175,7 +179,7 @@ extern void intel_dp_init(struct drm_device *dev, int dp_reg);
|
|
void
|
|
intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
|
|
struct drm_display_mode *adjusted_mode);
|
|
-extern void intel_edp_link_config (struct intel_output *, int *, int *);
|
|
+extern void intel_edp_link_config (struct intel_encoder *, int *, int *);
|
|
|
|
|
|
extern int intel_panel_fitter_pipe (struct drm_device *dev);
|
|
@@ -183,7 +187,7 @@ extern void intel_crtc_load_lut(struct drm_crtc *crtc);
|
|
extern void intel_encoder_prepare (struct drm_encoder *encoder);
|
|
extern void intel_encoder_commit (struct drm_encoder *encoder);
|
|
|
|
-extern struct drm_encoder *intel_best_encoder(struct drm_connector *connector);
|
|
+extern struct drm_encoder *intel_attached_encoder(struct drm_connector *connector);
|
|
|
|
extern struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
|
|
struct drm_crtc *crtc);
|
|
@@ -191,10 +195,12 @@ int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
|
|
struct drm_file *file_priv);
|
|
extern void intel_wait_for_vblank(struct drm_device *dev);
|
|
extern struct drm_crtc *intel_get_crtc_from_pipe(struct drm_device *dev, int pipe);
|
|
-extern struct drm_crtc *intel_get_load_detect_pipe(struct intel_output *intel_output,
|
|
+extern struct drm_crtc *intel_get_load_detect_pipe(struct intel_encoder *intel_encoder,
|
|
+ struct drm_connector *connector,
|
|
struct drm_display_mode *mode,
|
|
int *dpms_mode);
|
|
-extern void intel_release_load_detect_pipe(struct intel_output *intel_output,
|
|
+extern void intel_release_load_detect_pipe(struct intel_encoder *intel_encoder,
|
|
+ struct drm_connector *connector,
|
|
int dpms_mode);
|
|
|
|
extern struct drm_connector* intel_sdvo_find(struct drm_device *dev, int sdvoB);
|
|
@@ -209,6 +215,8 @@ extern void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
|
|
extern void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
|
|
u16 *blue, int regno);
|
|
extern void intel_init_clock_gating(struct drm_device *dev);
|
|
+extern void ironlake_enable_drps(struct drm_device *dev);
|
|
+extern void ironlake_disable_drps(struct drm_device *dev);
|
|
|
|
extern int intel_framebuffer_create(struct drm_device *dev,
|
|
struct drm_mode_fb_cmd *mode_cmd,
|
|
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
|
|
--- a/drivers/gpu/drm/i915/intel_dvo.c
|
|
+++ b/drivers/gpu/drm/i915/intel_dvo.c
|
|
@@ -79,8 +79,8 @@ static struct intel_dvo_device intel_dvo_devices[] = {
|
|
static void intel_dvo_dpms(struct drm_encoder *encoder, int mode)
|
|
{
|
|
struct drm_i915_private *dev_priv = encoder->dev->dev_private;
|
|
- struct intel_output *intel_output = enc_to_intel_output(encoder);
|
|
- struct intel_dvo_device *dvo = intel_output->dev_priv;
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ struct intel_dvo_device *dvo = intel_encoder->dev_priv;
|
|
u32 dvo_reg = dvo->dvo_reg;
|
|
u32 temp = I915_READ(dvo_reg);
|
|
|
|
@@ -95,40 +95,12 @@ static void intel_dvo_dpms(struct drm_encoder *encoder, int mode)
|
|
}
|
|
}
|
|
|
|
-static void intel_dvo_save(struct drm_connector *connector)
|
|
-{
|
|
- struct drm_i915_private *dev_priv = connector->dev->dev_private;
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
- struct intel_dvo_device *dvo = intel_output->dev_priv;
|
|
-
|
|
- /* Each output should probably just save the registers it touches,
|
|
- * but for now, use more overkill.
|
|
- */
|
|
- dev_priv->saveDVOA = I915_READ(DVOA);
|
|
- dev_priv->saveDVOB = I915_READ(DVOB);
|
|
- dev_priv->saveDVOC = I915_READ(DVOC);
|
|
-
|
|
- dvo->dev_ops->save(dvo);
|
|
-}
|
|
-
|
|
-static void intel_dvo_restore(struct drm_connector *connector)
|
|
-{
|
|
- struct drm_i915_private *dev_priv = connector->dev->dev_private;
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
- struct intel_dvo_device *dvo = intel_output->dev_priv;
|
|
-
|
|
- dvo->dev_ops->restore(dvo);
|
|
-
|
|
- I915_WRITE(DVOA, dev_priv->saveDVOA);
|
|
- I915_WRITE(DVOB, dev_priv->saveDVOB);
|
|
- I915_WRITE(DVOC, dev_priv->saveDVOC);
|
|
-}
|
|
-
|
|
static int intel_dvo_mode_valid(struct drm_connector *connector,
|
|
struct drm_display_mode *mode)
|
|
{
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
- struct intel_dvo_device *dvo = intel_output->dev_priv;
|
|
+ struct drm_encoder *encoder = intel_attached_encoder(connector);
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ struct intel_dvo_device *dvo = intel_encoder->dev_priv;
|
|
|
|
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
|
|
return MODE_NO_DBLESCAN;
|
|
@@ -149,8 +121,8 @@ static bool intel_dvo_mode_fixup(struct drm_encoder *encoder,
|
|
struct drm_display_mode *mode,
|
|
struct drm_display_mode *adjusted_mode)
|
|
{
|
|
- struct intel_output *intel_output = enc_to_intel_output(encoder);
|
|
- struct intel_dvo_device *dvo = intel_output->dev_priv;
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ struct intel_dvo_device *dvo = intel_encoder->dev_priv;
|
|
|
|
/* If we have timings from the BIOS for the panel, put them in
|
|
* to the adjusted mode. The CRTC will be set up for this mode,
|
|
@@ -185,8 +157,8 @@ static void intel_dvo_mode_set(struct drm_encoder *encoder,
|
|
struct drm_device *dev = encoder->dev;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
|
|
- struct intel_output *intel_output = enc_to_intel_output(encoder);
|
|
- struct intel_dvo_device *dvo = intel_output->dev_priv;
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ struct intel_dvo_device *dvo = intel_encoder->dev_priv;
|
|
int pipe = intel_crtc->pipe;
|
|
u32 dvo_val;
|
|
u32 dvo_reg = dvo->dvo_reg, dvo_srcdim_reg;
|
|
@@ -240,23 +212,25 @@ static void intel_dvo_mode_set(struct drm_encoder *encoder,
|
|
*/
|
|
static enum drm_connector_status intel_dvo_detect(struct drm_connector *connector)
|
|
{
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
- struct intel_dvo_device *dvo = intel_output->dev_priv;
|
|
+ struct drm_encoder *encoder = intel_attached_encoder(connector);
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ struct intel_dvo_device *dvo = intel_encoder->dev_priv;
|
|
|
|
return dvo->dev_ops->detect(dvo);
|
|
}
|
|
|
|
static int intel_dvo_get_modes(struct drm_connector *connector)
|
|
{
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
- struct intel_dvo_device *dvo = intel_output->dev_priv;
|
|
+ struct drm_encoder *encoder = intel_attached_encoder(connector);
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ struct intel_dvo_device *dvo = intel_encoder->dev_priv;
|
|
|
|
/* We should probably have an i2c driver get_modes function for those
|
|
* devices which will have a fixed set of modes determined by the chip
|
|
* (TV-out, for example), but for now with just TMDS and LVDS,
|
|
* that's not the case.
|
|
*/
|
|
- intel_ddc_get_modes(intel_output);
|
|
+ intel_ddc_get_modes(connector, intel_encoder->ddc_bus);
|
|
if (!list_empty(&connector->probed_modes))
|
|
return 1;
|
|
|
|
@@ -274,39 +248,11 @@ static int intel_dvo_get_modes(struct drm_connector *connector)
|
|
|
|
static void intel_dvo_destroy (struct drm_connector *connector)
|
|
{
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
- struct intel_dvo_device *dvo = intel_output->dev_priv;
|
|
-
|
|
- if (dvo) {
|
|
- if (dvo->dev_ops->destroy)
|
|
- dvo->dev_ops->destroy(dvo);
|
|
- if (dvo->panel_fixed_mode)
|
|
- kfree(dvo->panel_fixed_mode);
|
|
- /* no need, in i830_dvoices[] now */
|
|
- //kfree(dvo);
|
|
- }
|
|
- if (intel_output->i2c_bus)
|
|
- intel_i2c_destroy(intel_output->i2c_bus);
|
|
- if (intel_output->ddc_bus)
|
|
- intel_i2c_destroy(intel_output->ddc_bus);
|
|
drm_sysfs_connector_remove(connector);
|
|
drm_connector_cleanup(connector);
|
|
- kfree(intel_output);
|
|
+ kfree(connector);
|
|
}
|
|
|
|
-#ifdef RANDR_GET_CRTC_INTERFACE
|
|
-static struct drm_crtc *intel_dvo_get_crtc(struct drm_connector *connector)
|
|
-{
|
|
- struct drm_device *dev = connector->dev;
|
|
- struct drm_i915_private *dev_priv = dev->dev_private;
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
- struct intel_dvo_device *dvo = intel_output->dev_priv;
|
|
- int pipe = !!(I915_READ(dvo->dvo_reg) & SDVO_PIPE_B_SELECT);
|
|
-
|
|
- return intel_pipe_to_crtc(pScrn, pipe);
|
|
-}
|
|
-#endif
|
|
-
|
|
static const struct drm_encoder_helper_funcs intel_dvo_helper_funcs = {
|
|
.dpms = intel_dvo_dpms,
|
|
.mode_fixup = intel_dvo_mode_fixup,
|
|
@@ -317,8 +263,6 @@ static const struct drm_encoder_helper_funcs intel_dvo_helper_funcs = {
|
|
|
|
static const struct drm_connector_funcs intel_dvo_connector_funcs = {
|
|
.dpms = drm_helper_connector_dpms,
|
|
- .save = intel_dvo_save,
|
|
- .restore = intel_dvo_restore,
|
|
.detect = intel_dvo_detect,
|
|
.destroy = intel_dvo_destroy,
|
|
.fill_modes = drm_helper_probe_single_connector_modes,
|
|
@@ -327,12 +271,26 @@ static const struct drm_connector_funcs intel_dvo_connector_funcs = {
|
|
static const struct drm_connector_helper_funcs intel_dvo_connector_helper_funcs = {
|
|
.mode_valid = intel_dvo_mode_valid,
|
|
.get_modes = intel_dvo_get_modes,
|
|
- .best_encoder = intel_best_encoder,
|
|
+ .best_encoder = intel_attached_encoder,
|
|
};
|
|
|
|
static void intel_dvo_enc_destroy(struct drm_encoder *encoder)
|
|
{
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ struct intel_dvo_device *dvo = intel_encoder->dev_priv;
|
|
+
|
|
+ if (dvo) {
|
|
+ if (dvo->dev_ops->destroy)
|
|
+ dvo->dev_ops->destroy(dvo);
|
|
+ if (dvo->panel_fixed_mode)
|
|
+ kfree(dvo->panel_fixed_mode);
|
|
+ }
|
|
+ if (intel_encoder->i2c_bus)
|
|
+ intel_i2c_destroy(intel_encoder->i2c_bus);
|
|
+ if (intel_encoder->ddc_bus)
|
|
+ intel_i2c_destroy(intel_encoder->ddc_bus);
|
|
drm_encoder_cleanup(encoder);
|
|
+ kfree(intel_encoder);
|
|
}
|
|
|
|
static const struct drm_encoder_funcs intel_dvo_enc_funcs = {
|
|
@@ -351,8 +309,9 @@ intel_dvo_get_current_mode (struct drm_connector *connector)
|
|
{
|
|
struct drm_device *dev = connector->dev;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
- struct intel_dvo_device *dvo = intel_output->dev_priv;
|
|
+ struct drm_encoder *encoder = intel_attached_encoder(connector);
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ struct intel_dvo_device *dvo = intel_encoder->dev_priv;
|
|
uint32_t dvo_reg = dvo->dvo_reg;
|
|
uint32_t dvo_val = I915_READ(dvo_reg);
|
|
struct drm_display_mode *mode = NULL;
|
|
@@ -382,24 +341,31 @@ intel_dvo_get_current_mode (struct drm_connector *connector)
|
|
|
|
void intel_dvo_init(struct drm_device *dev)
|
|
{
|
|
- struct intel_output *intel_output;
|
|
+ struct intel_encoder *intel_encoder;
|
|
+ struct intel_connector *intel_connector;
|
|
struct intel_dvo_device *dvo;
|
|
struct i2c_adapter *i2cbus = NULL;
|
|
int ret = 0;
|
|
int i;
|
|
int encoder_type = DRM_MODE_ENCODER_NONE;
|
|
- intel_output = kzalloc (sizeof(struct intel_output), GFP_KERNEL);
|
|
- if (!intel_output)
|
|
+ intel_encoder = kzalloc (sizeof(struct intel_encoder), GFP_KERNEL);
|
|
+ if (!intel_encoder)
|
|
+ return;
|
|
+
|
|
+ intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
|
|
+ if (!intel_connector) {
|
|
+ kfree(intel_encoder);
|
|
return;
|
|
+ }
|
|
|
|
/* Set up the DDC bus */
|
|
- intel_output->ddc_bus = intel_i2c_create(dev, GPIOD, "DVODDC_D");
|
|
- if (!intel_output->ddc_bus)
|
|
+ intel_encoder->ddc_bus = intel_i2c_create(dev, GPIOD, "DVODDC_D");
|
|
+ if (!intel_encoder->ddc_bus)
|
|
goto free_intel;
|
|
|
|
/* Now, try to find a controller */
|
|
for (i = 0; i < ARRAY_SIZE(intel_dvo_devices); i++) {
|
|
- struct drm_connector *connector = &intel_output->base;
|
|
+ struct drm_connector *connector = &intel_connector->base;
|
|
int gpio;
|
|
|
|
dvo = &intel_dvo_devices[i];
|
|
@@ -434,11 +400,11 @@ void intel_dvo_init(struct drm_device *dev)
|
|
if (!ret)
|
|
continue;
|
|
|
|
- intel_output->type = INTEL_OUTPUT_DVO;
|
|
- intel_output->crtc_mask = (1 << 0) | (1 << 1);
|
|
+ intel_encoder->type = INTEL_OUTPUT_DVO;
|
|
+ intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
|
|
switch (dvo->type) {
|
|
case INTEL_DVO_CHIP_TMDS:
|
|
- intel_output->clone_mask =
|
|
+ intel_encoder->clone_mask =
|
|
(1 << INTEL_DVO_TMDS_CLONE_BIT) |
|
|
(1 << INTEL_ANALOG_CLONE_BIT);
|
|
drm_connector_init(dev, connector,
|
|
@@ -447,7 +413,7 @@ void intel_dvo_init(struct drm_device *dev)
|
|
encoder_type = DRM_MODE_ENCODER_TMDS;
|
|
break;
|
|
case INTEL_DVO_CHIP_LVDS:
|
|
- intel_output->clone_mask =
|
|
+ intel_encoder->clone_mask =
|
|
(1 << INTEL_DVO_LVDS_CLONE_BIT);
|
|
drm_connector_init(dev, connector,
|
|
&intel_dvo_connector_funcs,
|
|
@@ -462,16 +428,16 @@ void intel_dvo_init(struct drm_device *dev)
|
|
connector->interlace_allowed = false;
|
|
connector->doublescan_allowed = false;
|
|
|
|
- intel_output->dev_priv = dvo;
|
|
- intel_output->i2c_bus = i2cbus;
|
|
+ intel_encoder->dev_priv = dvo;
|
|
+ intel_encoder->i2c_bus = i2cbus;
|
|
|
|
- drm_encoder_init(dev, &intel_output->enc,
|
|
+ drm_encoder_init(dev, &intel_encoder->enc,
|
|
&intel_dvo_enc_funcs, encoder_type);
|
|
- drm_encoder_helper_add(&intel_output->enc,
|
|
+ drm_encoder_helper_add(&intel_encoder->enc,
|
|
&intel_dvo_helper_funcs);
|
|
|
|
- drm_mode_connector_attach_encoder(&intel_output->base,
|
|
- &intel_output->enc);
|
|
+ drm_mode_connector_attach_encoder(&intel_connector->base,
|
|
+ &intel_encoder->enc);
|
|
if (dvo->type == INTEL_DVO_CHIP_LVDS) {
|
|
/* For our LVDS chipsets, we should hopefully be able
|
|
* to dig the fixed panel mode out of the BIOS data.
|
|
@@ -489,10 +455,11 @@ void intel_dvo_init(struct drm_device *dev)
|
|
return;
|
|
}
|
|
|
|
- intel_i2c_destroy(intel_output->ddc_bus);
|
|
+ intel_i2c_destroy(intel_encoder->ddc_bus);
|
|
/* Didn't find a chip, so tear down. */
|
|
if (i2cbus != NULL)
|
|
intel_i2c_destroy(i2cbus);
|
|
free_intel:
|
|
- kfree(intel_output);
|
|
+ kfree(intel_encoder);
|
|
+ kfree(intel_connector);
|
|
}
|
|
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c
|
|
--- a/drivers/gpu/drm/i915/intel_fb.c
|
|
+++ b/drivers/gpu/drm/i915/intel_fb.c
|
|
@@ -144,7 +144,7 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width,
|
|
ret = -ENOMEM;
|
|
goto out;
|
|
}
|
|
- obj_priv = fbo->driver_private;
|
|
+ obj_priv = to_intel_bo(fbo);
|
|
|
|
mutex_lock(&dev->struct_mutex);
|
|
|
|
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
|
|
--- a/drivers/gpu/drm/i915/intel_hdmi.c
|
|
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
|
|
@@ -38,7 +38,6 @@
|
|
|
|
struct intel_hdmi_priv {
|
|
u32 sdvox_reg;
|
|
- u32 save_SDVOX;
|
|
bool has_hdmi_sink;
|
|
};
|
|
|
|
@@ -50,8 +49,8 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder,
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
struct drm_crtc *crtc = encoder->crtc;
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
- struct intel_output *intel_output = enc_to_intel_output(encoder);
|
|
- struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv;
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ struct intel_hdmi_priv *hdmi_priv = intel_encoder->dev_priv;
|
|
u32 sdvox;
|
|
|
|
sdvox = SDVO_ENCODING_HDMI |
|
|
@@ -62,8 +61,12 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder,
|
|
if (hdmi_priv->has_hdmi_sink)
|
|
sdvox |= SDVO_AUDIO_ENABLE;
|
|
|
|
- if (intel_crtc->pipe == 1)
|
|
- sdvox |= SDVO_PIPE_B_SELECT;
|
|
+ if (intel_crtc->pipe == 1) {
|
|
+ if (HAS_PCH_CPT(dev))
|
|
+ sdvox |= PORT_TRANS_B_SEL_CPT;
|
|
+ else
|
|
+ sdvox |= SDVO_PIPE_B_SELECT;
|
|
+ }
|
|
|
|
I915_WRITE(hdmi_priv->sdvox_reg, sdvox);
|
|
POSTING_READ(hdmi_priv->sdvox_reg);
|
|
@@ -73,8 +76,8 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode)
|
|
{
|
|
struct drm_device *dev = encoder->dev;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
- struct intel_output *intel_output = enc_to_intel_output(encoder);
|
|
- struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv;
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ struct intel_hdmi_priv *hdmi_priv = intel_encoder->dev_priv;
|
|
u32 temp;
|
|
|
|
temp = I915_READ(hdmi_priv->sdvox_reg);
|
|
@@ -82,7 +85,7 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode)
|
|
/* HW workaround, need to toggle enable bit off and on for 12bpc, but
|
|
* we do this anyway which shows more stable in testing.
|
|
*/
|
|
- if (IS_IRONLAKE(dev)) {
|
|
+ if (HAS_PCH_SPLIT(dev)) {
|
|
I915_WRITE(hdmi_priv->sdvox_reg, temp & ~SDVO_ENABLE);
|
|
POSTING_READ(hdmi_priv->sdvox_reg);
|
|
}
|
|
@@ -99,33 +102,12 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode)
|
|
/* HW workaround, need to write this twice for issue that may result
|
|
* in first write getting masked.
|
|
*/
|
|
- if (IS_IRONLAKE(dev)) {
|
|
+ if (HAS_PCH_SPLIT(dev)) {
|
|
I915_WRITE(hdmi_priv->sdvox_reg, temp);
|
|
POSTING_READ(hdmi_priv->sdvox_reg);
|
|
}
|
|
}
|
|
|
|
-static void intel_hdmi_save(struct drm_connector *connector)
|
|
-{
|
|
- struct drm_device *dev = connector->dev;
|
|
- struct drm_i915_private *dev_priv = dev->dev_private;
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
- struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv;
|
|
-
|
|
- hdmi_priv->save_SDVOX = I915_READ(hdmi_priv->sdvox_reg);
|
|
-}
|
|
-
|
|
-static void intel_hdmi_restore(struct drm_connector *connector)
|
|
-{
|
|
- struct drm_device *dev = connector->dev;
|
|
- struct drm_i915_private *dev_priv = dev->dev_private;
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
- struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv;
|
|
-
|
|
- I915_WRITE(hdmi_priv->sdvox_reg, hdmi_priv->save_SDVOX);
|
|
- POSTING_READ(hdmi_priv->sdvox_reg);
|
|
-}
|
|
-
|
|
static int intel_hdmi_mode_valid(struct drm_connector *connector,
|
|
struct drm_display_mode *mode)
|
|
{
|
|
@@ -150,21 +132,22 @@ static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder,
|
|
static enum drm_connector_status
|
|
intel_hdmi_detect(struct drm_connector *connector)
|
|
{
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
- struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv;
|
|
+ struct drm_encoder *encoder = intel_attached_encoder(connector);
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ struct intel_hdmi_priv *hdmi_priv = intel_encoder->dev_priv;
|
|
struct edid *edid = NULL;
|
|
enum drm_connector_status status = connector_status_disconnected;
|
|
|
|
hdmi_priv->has_hdmi_sink = false;
|
|
- edid = drm_get_edid(&intel_output->base,
|
|
- intel_output->ddc_bus);
|
|
+ edid = drm_get_edid(connector,
|
|
+ intel_encoder->ddc_bus);
|
|
|
|
if (edid) {
|
|
if (edid->input & DRM_EDID_INPUT_DIGITAL) {
|
|
status = connector_status_connected;
|
|
hdmi_priv->has_hdmi_sink = drm_detect_hdmi_monitor(edid);
|
|
}
|
|
- intel_output->base.display_info.raw_edid = NULL;
|
|
+ connector->display_info.raw_edid = NULL;
|
|
kfree(edid);
|
|
}
|
|
|
|
@@ -173,24 +156,21 @@ intel_hdmi_detect(struct drm_connector *connector)
|
|
|
|
static int intel_hdmi_get_modes(struct drm_connector *connector)
|
|
{
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
+ struct drm_encoder *encoder = intel_attached_encoder(connector);
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
|
|
/* We should parse the EDID data and find out if it's an HDMI sink so
|
|
* we can send audio to it.
|
|
*/
|
|
|
|
- return intel_ddc_get_modes(intel_output);
|
|
+ return intel_ddc_get_modes(connector, intel_encoder->ddc_bus);
|
|
}
|
|
|
|
static void intel_hdmi_destroy(struct drm_connector *connector)
|
|
{
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
-
|
|
- if (intel_output->i2c_bus)
|
|
- intel_i2c_destroy(intel_output->i2c_bus);
|
|
drm_sysfs_connector_remove(connector);
|
|
drm_connector_cleanup(connector);
|
|
- kfree(intel_output);
|
|
+ kfree(connector);
|
|
}
|
|
|
|
static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs = {
|
|
@@ -203,8 +183,6 @@ static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs = {
|
|
|
|
static const struct drm_connector_funcs intel_hdmi_connector_funcs = {
|
|
.dpms = drm_helper_connector_dpms,
|
|
- .save = intel_hdmi_save,
|
|
- .restore = intel_hdmi_restore,
|
|
.detect = intel_hdmi_detect,
|
|
.fill_modes = drm_helper_probe_single_connector_modes,
|
|
.destroy = intel_hdmi_destroy,
|
|
@@ -213,12 +191,17 @@ static const struct drm_connector_funcs intel_hdmi_connector_funcs = {
|
|
static const struct drm_connector_helper_funcs intel_hdmi_connector_helper_funcs = {
|
|
.get_modes = intel_hdmi_get_modes,
|
|
.mode_valid = intel_hdmi_mode_valid,
|
|
- .best_encoder = intel_best_encoder,
|
|
+ .best_encoder = intel_attached_encoder,
|
|
};
|
|
|
|
static void intel_hdmi_enc_destroy(struct drm_encoder *encoder)
|
|
{
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+
|
|
+ if (intel_encoder->i2c_bus)
|
|
+ intel_i2c_destroy(intel_encoder->i2c_bus);
|
|
drm_encoder_cleanup(encoder);
|
|
+ kfree(intel_encoder);
|
|
}
|
|
|
|
static const struct drm_encoder_funcs intel_hdmi_enc_funcs = {
|
|
@@ -229,63 +212,71 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
|
|
{
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
struct drm_connector *connector;
|
|
- struct intel_output *intel_output;
|
|
+ struct intel_encoder *intel_encoder;
|
|
+ struct intel_connector *intel_connector;
|
|
struct intel_hdmi_priv *hdmi_priv;
|
|
|
|
- intel_output = kcalloc(sizeof(struct intel_output) +
|
|
+ intel_encoder = kcalloc(sizeof(struct intel_encoder) +
|
|
sizeof(struct intel_hdmi_priv), 1, GFP_KERNEL);
|
|
- if (!intel_output)
|
|
+ if (!intel_encoder)
|
|
return;
|
|
- hdmi_priv = (struct intel_hdmi_priv *)(intel_output + 1);
|
|
|
|
- connector = &intel_output->base;
|
|
+ intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
|
|
+ if (!intel_connector) {
|
|
+ kfree(intel_encoder);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ hdmi_priv = (struct intel_hdmi_priv *)(intel_encoder + 1);
|
|
+
|
|
+ connector = &intel_connector->base;
|
|
drm_connector_init(dev, connector, &intel_hdmi_connector_funcs,
|
|
DRM_MODE_CONNECTOR_HDMIA);
|
|
drm_connector_helper_add(connector, &intel_hdmi_connector_helper_funcs);
|
|
|
|
- intel_output->type = INTEL_OUTPUT_HDMI;
|
|
+ intel_encoder->type = INTEL_OUTPUT_HDMI;
|
|
|
|
connector->interlace_allowed = 0;
|
|
connector->doublescan_allowed = 0;
|
|
- intel_output->crtc_mask = (1 << 0) | (1 << 1);
|
|
+ intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
|
|
|
|
/* Set up the DDC bus. */
|
|
if (sdvox_reg == SDVOB) {
|
|
- intel_output->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT);
|
|
- intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "HDMIB");
|
|
+ intel_encoder->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT);
|
|
+ intel_encoder->ddc_bus = intel_i2c_create(dev, GPIOE, "HDMIB");
|
|
dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
|
|
} else if (sdvox_reg == SDVOC) {
|
|
- intel_output->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT);
|
|
- intel_output->ddc_bus = intel_i2c_create(dev, GPIOD, "HDMIC");
|
|
+ intel_encoder->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT);
|
|
+ intel_encoder->ddc_bus = intel_i2c_create(dev, GPIOD, "HDMIC");
|
|
dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
|
|
} else if (sdvox_reg == HDMIB) {
|
|
- intel_output->clone_mask = (1 << INTEL_HDMID_CLONE_BIT);
|
|
- intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOE,
|
|
+ intel_encoder->clone_mask = (1 << INTEL_HDMID_CLONE_BIT);
|
|
+ intel_encoder->ddc_bus = intel_i2c_create(dev, PCH_GPIOE,
|
|
"HDMIB");
|
|
dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
|
|
} else if (sdvox_reg == HDMIC) {
|
|
- intel_output->clone_mask = (1 << INTEL_HDMIE_CLONE_BIT);
|
|
- intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOD,
|
|
+ intel_encoder->clone_mask = (1 << INTEL_HDMIE_CLONE_BIT);
|
|
+ intel_encoder->ddc_bus = intel_i2c_create(dev, PCH_GPIOD,
|
|
"HDMIC");
|
|
dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
|
|
} else if (sdvox_reg == HDMID) {
|
|
- intel_output->clone_mask = (1 << INTEL_HDMIF_CLONE_BIT);
|
|
- intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOF,
|
|
+ intel_encoder->clone_mask = (1 << INTEL_HDMIF_CLONE_BIT);
|
|
+ intel_encoder->ddc_bus = intel_i2c_create(dev, PCH_GPIOF,
|
|
"HDMID");
|
|
dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS;
|
|
}
|
|
- if (!intel_output->ddc_bus)
|
|
+ if (!intel_encoder->ddc_bus)
|
|
goto err_connector;
|
|
|
|
hdmi_priv->sdvox_reg = sdvox_reg;
|
|
- intel_output->dev_priv = hdmi_priv;
|
|
+ intel_encoder->dev_priv = hdmi_priv;
|
|
|
|
- drm_encoder_init(dev, &intel_output->enc, &intel_hdmi_enc_funcs,
|
|
+ drm_encoder_init(dev, &intel_encoder->enc, &intel_hdmi_enc_funcs,
|
|
DRM_MODE_ENCODER_TMDS);
|
|
- drm_encoder_helper_add(&intel_output->enc, &intel_hdmi_helper_funcs);
|
|
+ drm_encoder_helper_add(&intel_encoder->enc, &intel_hdmi_helper_funcs);
|
|
|
|
- drm_mode_connector_attach_encoder(&intel_output->base,
|
|
- &intel_output->enc);
|
|
+ drm_mode_connector_attach_encoder(&intel_connector->base,
|
|
+ &intel_encoder->enc);
|
|
drm_sysfs_connector_add(connector);
|
|
|
|
/* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written
|
|
@@ -301,7 +292,8 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
|
|
|
|
err_connector:
|
|
drm_connector_cleanup(connector);
|
|
- kfree(intel_output);
|
|
+ kfree(intel_encoder);
|
|
+ kfree(intel_connector);
|
|
|
|
return;
|
|
}
|
|
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c
|
|
--- a/drivers/gpu/drm/i915/intel_i2c.c
|
|
+++ b/drivers/gpu/drm/i915/intel_i2c.c
|
|
@@ -128,7 +128,7 @@ intel_i2c_reset_gmbus(struct drm_device *dev)
|
|
{
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
- if (IS_IRONLAKE(dev)) {
|
|
+ if (HAS_PCH_SPLIT(dev)) {
|
|
I915_WRITE(PCH_GMBUS0, 0);
|
|
} else {
|
|
I915_WRITE(GMBUS0, 0);
|
|
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
|
|
--- a/drivers/gpu/drm/i915/intel_lvds.c
|
|
+++ b/drivers/gpu/drm/i915/intel_lvds.c
|
|
@@ -56,7 +56,7 @@ static void intel_lvds_set_backlight(struct drm_device *dev, int level)
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
u32 blc_pwm_ctl, reg;
|
|
|
|
- if (IS_IRONLAKE(dev))
|
|
+ if (HAS_PCH_SPLIT(dev))
|
|
reg = BLC_PWM_CPU_CTL;
|
|
else
|
|
reg = BLC_PWM_CTL;
|
|
@@ -74,7 +74,7 @@ static u32 intel_lvds_get_max_backlight(struct drm_device *dev)
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
u32 reg;
|
|
|
|
- if (IS_IRONLAKE(dev))
|
|
+ if (HAS_PCH_SPLIT(dev))
|
|
reg = BLC_PWM_PCH_CTL2;
|
|
else
|
|
reg = BLC_PWM_CTL;
|
|
@@ -89,17 +89,22 @@ static u32 intel_lvds_get_max_backlight(struct drm_device *dev)
|
|
static void intel_lvds_set_power(struct drm_device *dev, bool on)
|
|
{
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
- u32 pp_status, ctl_reg, status_reg;
|
|
+ u32 pp_status, ctl_reg, status_reg, lvds_reg;
|
|
|
|
- if (IS_IRONLAKE(dev)) {
|
|
+ if (HAS_PCH_SPLIT(dev)) {
|
|
ctl_reg = PCH_PP_CONTROL;
|
|
status_reg = PCH_PP_STATUS;
|
|
+ lvds_reg = PCH_LVDS;
|
|
} else {
|
|
ctl_reg = PP_CONTROL;
|
|
status_reg = PP_STATUS;
|
|
+ lvds_reg = LVDS;
|
|
}
|
|
|
|
if (on) {
|
|
+ I915_WRITE(lvds_reg, I915_READ(lvds_reg) | LVDS_PORT_EN);
|
|
+ POSTING_READ(lvds_reg);
|
|
+
|
|
I915_WRITE(ctl_reg, I915_READ(ctl_reg) |
|
|
POWER_TARGET_ON);
|
|
do {
|
|
@@ -115,6 +120,9 @@ static void intel_lvds_set_power(struct drm_device *dev, bool on)
|
|
do {
|
|
pp_status = I915_READ(status_reg);
|
|
} while (pp_status & PP_ON);
|
|
+
|
|
+ I915_WRITE(lvds_reg, I915_READ(lvds_reg) & ~LVDS_PORT_EN);
|
|
+ POSTING_READ(lvds_reg);
|
|
}
|
|
}
|
|
|
|
@@ -130,75 +138,6 @@ static void intel_lvds_dpms(struct drm_encoder *encoder, int mode)
|
|
/* XXX: We never power down the LVDS pairs. */
|
|
}
|
|
|
|
-static void intel_lvds_save(struct drm_connector *connector)
|
|
-{
|
|
- struct drm_device *dev = connector->dev;
|
|
- struct drm_i915_private *dev_priv = dev->dev_private;
|
|
- u32 pp_on_reg, pp_off_reg, pp_ctl_reg, pp_div_reg;
|
|
- u32 pwm_ctl_reg;
|
|
-
|
|
- if (IS_IRONLAKE(dev)) {
|
|
- pp_on_reg = PCH_PP_ON_DELAYS;
|
|
- pp_off_reg = PCH_PP_OFF_DELAYS;
|
|
- pp_ctl_reg = PCH_PP_CONTROL;
|
|
- pp_div_reg = PCH_PP_DIVISOR;
|
|
- pwm_ctl_reg = BLC_PWM_CPU_CTL;
|
|
- } else {
|
|
- pp_on_reg = PP_ON_DELAYS;
|
|
- pp_off_reg = PP_OFF_DELAYS;
|
|
- pp_ctl_reg = PP_CONTROL;
|
|
- pp_div_reg = PP_DIVISOR;
|
|
- pwm_ctl_reg = BLC_PWM_CTL;
|
|
- }
|
|
-
|
|
- dev_priv->savePP_ON = I915_READ(pp_on_reg);
|
|
- dev_priv->savePP_OFF = I915_READ(pp_off_reg);
|
|
- dev_priv->savePP_CONTROL = I915_READ(pp_ctl_reg);
|
|
- dev_priv->savePP_DIVISOR = I915_READ(pp_div_reg);
|
|
- dev_priv->saveBLC_PWM_CTL = I915_READ(pwm_ctl_reg);
|
|
- dev_priv->backlight_duty_cycle = (dev_priv->saveBLC_PWM_CTL &
|
|
- BACKLIGHT_DUTY_CYCLE_MASK);
|
|
-
|
|
- /*
|
|
- * If the light is off at server startup, just make it full brightness
|
|
- */
|
|
- if (dev_priv->backlight_duty_cycle == 0)
|
|
- dev_priv->backlight_duty_cycle =
|
|
- intel_lvds_get_max_backlight(dev);
|
|
-}
|
|
-
|
|
-static void intel_lvds_restore(struct drm_connector *connector)
|
|
-{
|
|
- struct drm_device *dev = connector->dev;
|
|
- struct drm_i915_private *dev_priv = dev->dev_private;
|
|
- u32 pp_on_reg, pp_off_reg, pp_ctl_reg, pp_div_reg;
|
|
- u32 pwm_ctl_reg;
|
|
-
|
|
- if (IS_IRONLAKE(dev)) {
|
|
- pp_on_reg = PCH_PP_ON_DELAYS;
|
|
- pp_off_reg = PCH_PP_OFF_DELAYS;
|
|
- pp_ctl_reg = PCH_PP_CONTROL;
|
|
- pp_div_reg = PCH_PP_DIVISOR;
|
|
- pwm_ctl_reg = BLC_PWM_CPU_CTL;
|
|
- } else {
|
|
- pp_on_reg = PP_ON_DELAYS;
|
|
- pp_off_reg = PP_OFF_DELAYS;
|
|
- pp_ctl_reg = PP_CONTROL;
|
|
- pp_div_reg = PP_DIVISOR;
|
|
- pwm_ctl_reg = BLC_PWM_CTL;
|
|
- }
|
|
-
|
|
- I915_WRITE(pwm_ctl_reg, dev_priv->saveBLC_PWM_CTL);
|
|
- I915_WRITE(pp_on_reg, dev_priv->savePP_ON);
|
|
- I915_WRITE(pp_off_reg, dev_priv->savePP_OFF);
|
|
- I915_WRITE(pp_div_reg, dev_priv->savePP_DIVISOR);
|
|
- I915_WRITE(pp_ctl_reg, dev_priv->savePP_CONTROL);
|
|
- if (dev_priv->savePP_CONTROL & POWER_TARGET_ON)
|
|
- intel_lvds_set_power(dev, true);
|
|
- else
|
|
- intel_lvds_set_power(dev, false);
|
|
-}
|
|
-
|
|
static int intel_lvds_mode_valid(struct drm_connector *connector,
|
|
struct drm_display_mode *mode)
|
|
{
|
|
@@ -230,8 +169,8 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
|
|
struct drm_encoder *tmp_encoder;
|
|
- struct intel_output *intel_output = enc_to_intel_output(encoder);
|
|
- struct intel_lvds_priv *lvds_priv = intel_output->dev_priv;
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ struct intel_lvds_priv *lvds_priv = intel_encoder->dev_priv;
|
|
u32 pfit_control = 0, pfit_pgm_ratios = 0;
|
|
int left_border = 0, right_border = 0, top_border = 0;
|
|
int bottom_border = 0;
|
|
@@ -297,7 +236,7 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
|
|
}
|
|
|
|
/* full screen scale for now */
|
|
- if (IS_IRONLAKE(dev))
|
|
+ if (HAS_PCH_SPLIT(dev))
|
|
goto out;
|
|
|
|
/* 965+ wants fuzzy fitting */
|
|
@@ -327,7 +266,7 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
|
|
* to register description and PRM.
|
|
* Change the value here to see the borders for debugging
|
|
*/
|
|
- if (!IS_IRONLAKE(dev)) {
|
|
+ if (!HAS_PCH_SPLIT(dev)) {
|
|
I915_WRITE(BCLRPAT_A, 0);
|
|
I915_WRITE(BCLRPAT_B, 0);
|
|
}
|
|
@@ -548,7 +487,7 @@ static void intel_lvds_prepare(struct drm_encoder *encoder)
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
u32 reg;
|
|
|
|
- if (IS_IRONLAKE(dev))
|
|
+ if (HAS_PCH_SPLIT(dev))
|
|
reg = BLC_PWM_CPU_CTL;
|
|
else
|
|
reg = BLC_PWM_CTL;
|
|
@@ -578,8 +517,8 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder,
|
|
{
|
|
struct drm_device *dev = encoder->dev;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
- struct intel_output *intel_output = enc_to_intel_output(encoder);
|
|
- struct intel_lvds_priv *lvds_priv = intel_output->dev_priv;
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ struct intel_lvds_priv *lvds_priv = intel_encoder->dev_priv;
|
|
|
|
/*
|
|
* The LVDS pin pair will already have been turned on in the
|
|
@@ -587,7 +526,7 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder,
|
|
* settings.
|
|
*/
|
|
|
|
- if (IS_IRONLAKE(dev))
|
|
+ if (HAS_PCH_SPLIT(dev))
|
|
return;
|
|
|
|
/*
|
|
@@ -599,53 +538,6 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder,
|
|
I915_WRITE(PFIT_CONTROL, lvds_priv->pfit_control);
|
|
}
|
|
|
|
-/* Some lid devices report incorrect lid status, assume they're connected */
|
|
-static const struct dmi_system_id bad_lid_status[] = {
|
|
- {
|
|
- .ident = "Compaq nx9020",
|
|
- .matches = {
|
|
- DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
|
|
- DMI_MATCH(DMI_BOARD_NAME, "3084"),
|
|
- },
|
|
- },
|
|
- {
|
|
- .ident = "Samsung SX20S",
|
|
- .matches = {
|
|
- DMI_MATCH(DMI_SYS_VENDOR, "Samsung Electronics"),
|
|
- DMI_MATCH(DMI_BOARD_NAME, "SX20S"),
|
|
- },
|
|
- },
|
|
- {
|
|
- .ident = "Aspire One",
|
|
- .matches = {
|
|
- DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
|
|
- DMI_MATCH(DMI_PRODUCT_NAME, "Aspire one"),
|
|
- },
|
|
- },
|
|
- {
|
|
- .ident = "Aspire 1810T",
|
|
- .matches = {
|
|
- DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
|
|
- DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1810T"),
|
|
- },
|
|
- },
|
|
- {
|
|
- .ident = "PC-81005",
|
|
- .matches = {
|
|
- DMI_MATCH(DMI_SYS_VENDOR, "MALATA"),
|
|
- DMI_MATCH(DMI_PRODUCT_NAME, "PC-81005"),
|
|
- },
|
|
- },
|
|
- {
|
|
- .ident = "Clevo M5x0N",
|
|
- .matches = {
|
|
- DMI_MATCH(DMI_SYS_VENDOR, "CLEVO Co."),
|
|
- DMI_MATCH(DMI_BOARD_NAME, "M5x0N"),
|
|
- },
|
|
- },
|
|
- { }
|
|
-};
|
|
-
|
|
/**
|
|
* Detect the LVDS connection.
|
|
*
|
|
@@ -661,12 +553,9 @@ static enum drm_connector_status intel_lvds_detect(struct drm_connector *connect
|
|
/* ACPI lid methods were generally unreliable in this generation, so
|
|
* don't even bother.
|
|
*/
|
|
- if (IS_I8XX(dev))
|
|
+ if (IS_GEN2(dev) || IS_GEN3(dev))
|
|
return connector_status_connected;
|
|
|
|
- if (!dmi_check_system(bad_lid_status) && !acpi_lid_open())
|
|
- status = connector_status_disconnected;
|
|
-
|
|
return status;
|
|
}
|
|
|
|
@@ -676,14 +565,17 @@ static enum drm_connector_status intel_lvds_detect(struct drm_connector *connect
|
|
static int intel_lvds_get_modes(struct drm_connector *connector)
|
|
{
|
|
struct drm_device *dev = connector->dev;
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
+ struct drm_encoder *encoder = intel_attached_encoder(connector);
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
int ret = 0;
|
|
|
|
- ret = intel_ddc_get_modes(intel_output);
|
|
+ if (dev_priv->lvds_edid_good) {
|
|
+ ret = intel_ddc_get_modes(connector, intel_encoder->ddc_bus);
|
|
|
|
- if (ret)
|
|
- return ret;
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ }
|
|
|
|
/* Didn't get an EDID, so
|
|
* Set wide sync ranges so we get all modes
|
|
@@ -756,11 +648,8 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
|
|
static void intel_lvds_destroy(struct drm_connector *connector)
|
|
{
|
|
struct drm_device *dev = connector->dev;
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
|
|
- if (intel_output->ddc_bus)
|
|
- intel_i2c_destroy(intel_output->ddc_bus);
|
|
if (dev_priv->lid_notifier.notifier_call)
|
|
acpi_lid_notifier_unregister(&dev_priv->lid_notifier);
|
|
drm_sysfs_connector_remove(connector);
|
|
@@ -773,13 +662,14 @@ static int intel_lvds_set_property(struct drm_connector *connector,
|
|
uint64_t value)
|
|
{
|
|
struct drm_device *dev = connector->dev;
|
|
- struct intel_output *intel_output =
|
|
- to_intel_output(connector);
|
|
|
|
if (property == dev->mode_config.scaling_mode_property &&
|
|
connector->encoder) {
|
|
struct drm_crtc *crtc = connector->encoder->crtc;
|
|
- struct intel_lvds_priv *lvds_priv = intel_output->dev_priv;
|
|
+ struct drm_encoder *encoder = connector->encoder;
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ struct intel_lvds_priv *lvds_priv = intel_encoder->dev_priv;
|
|
+
|
|
if (value == DRM_MODE_SCALE_NONE) {
|
|
DRM_DEBUG_KMS("no scaling not supported\n");
|
|
return 0;
|
|
@@ -813,13 +703,11 @@ static const struct drm_encoder_helper_funcs intel_lvds_helper_funcs = {
|
|
static const struct drm_connector_helper_funcs intel_lvds_connector_helper_funcs = {
|
|
.get_modes = intel_lvds_get_modes,
|
|
.mode_valid = intel_lvds_mode_valid,
|
|
- .best_encoder = intel_best_encoder,
|
|
+ .best_encoder = intel_attached_encoder,
|
|
};
|
|
|
|
static const struct drm_connector_funcs intel_lvds_connector_funcs = {
|
|
.dpms = drm_helper_connector_dpms,
|
|
- .save = intel_lvds_save,
|
|
- .restore = intel_lvds_restore,
|
|
.detect = intel_lvds_detect,
|
|
.fill_modes = drm_helper_probe_single_connector_modes,
|
|
.set_property = intel_lvds_set_property,
|
|
@@ -829,7 +717,12 @@ static const struct drm_connector_funcs intel_lvds_connector_funcs = {
|
|
|
|
static void intel_lvds_enc_destroy(struct drm_encoder *encoder)
|
|
{
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+
|
|
+ if (intel_encoder->ddc_bus)
|
|
+ intel_i2c_destroy(intel_encoder->ddc_bus);
|
|
drm_encoder_cleanup(encoder);
|
|
+ kfree(intel_encoder);
|
|
}
|
|
|
|
static const struct drm_encoder_funcs intel_lvds_enc_funcs = {
|
|
@@ -899,6 +792,14 @@ static const struct dmi_system_id intel_no_lvds[] = {
|
|
DMI_MATCH(DMI_PRODUCT_VERSION, "AO00001JW"),
|
|
},
|
|
},
|
|
+ {
|
|
+ .callback = intel_no_lvds_dmi_callback,
|
|
+ .ident = "Clientron U800",
|
|
+ .matches = {
|
|
+ DMI_MATCH(DMI_SYS_VENDOR, "Clientron"),
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "U800"),
|
|
+ },
|
|
+ },
|
|
|
|
{ } /* terminating entry */
|
|
};
|
|
@@ -1009,7 +910,8 @@ static int lvds_is_present_in_vbt(struct drm_device *dev)
|
|
void intel_lvds_init(struct drm_device *dev)
|
|
{
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
- struct intel_output *intel_output;
|
|
+ struct intel_encoder *intel_encoder;
|
|
+ struct intel_connector *intel_connector;
|
|
struct drm_connector *connector;
|
|
struct drm_encoder *encoder;
|
|
struct drm_display_mode *scan; /* *modes, *bios_mode; */
|
|
@@ -1027,7 +929,7 @@ void intel_lvds_init(struct drm_device *dev)
|
|
return;
|
|
}
|
|
|
|
- if (IS_IRONLAKE(dev)) {
|
|
+ if (HAS_PCH_SPLIT(dev)) {
|
|
if ((I915_READ(PCH_LVDS) & LVDS_DETECTED) == 0)
|
|
return;
|
|
if (dev_priv->edp_support) {
|
|
@@ -1037,40 +939,48 @@ void intel_lvds_init(struct drm_device *dev)
|
|
gpio = PCH_GPIOC;
|
|
}
|
|
|
|
- intel_output = kzalloc(sizeof(struct intel_output) +
|
|
+ intel_encoder = kzalloc(sizeof(struct intel_encoder) +
|
|
sizeof(struct intel_lvds_priv), GFP_KERNEL);
|
|
- if (!intel_output) {
|
|
+ if (!intel_encoder) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
|
|
+ if (!intel_connector) {
|
|
+ kfree(intel_encoder);
|
|
return;
|
|
}
|
|
|
|
- connector = &intel_output->base;
|
|
- encoder = &intel_output->enc;
|
|
- drm_connector_init(dev, &intel_output->base, &intel_lvds_connector_funcs,
|
|
+ connector = &intel_connector->base;
|
|
+ encoder = &intel_encoder->enc;
|
|
+ drm_connector_init(dev, &intel_connector->base, &intel_lvds_connector_funcs,
|
|
DRM_MODE_CONNECTOR_LVDS);
|
|
|
|
- drm_encoder_init(dev, &intel_output->enc, &intel_lvds_enc_funcs,
|
|
+ drm_encoder_init(dev, &intel_encoder->enc, &intel_lvds_enc_funcs,
|
|
DRM_MODE_ENCODER_LVDS);
|
|
|
|
- drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc);
|
|
- intel_output->type = INTEL_OUTPUT_LVDS;
|
|
+ drm_mode_connector_attach_encoder(&intel_connector->base, &intel_encoder->enc);
|
|
+ intel_encoder->type = INTEL_OUTPUT_LVDS;
|
|
|
|
- intel_output->clone_mask = (1 << INTEL_LVDS_CLONE_BIT);
|
|
- intel_output->crtc_mask = (1 << 1);
|
|
+ intel_encoder->clone_mask = (1 << INTEL_LVDS_CLONE_BIT);
|
|
+ intel_encoder->crtc_mask = (1 << 1);
|
|
+ if (IS_I965G(dev))
|
|
+ intel_encoder->crtc_mask |= (1 << 0);
|
|
drm_encoder_helper_add(encoder, &intel_lvds_helper_funcs);
|
|
drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs);
|
|
connector->display_info.subpixel_order = SubPixelHorizontalRGB;
|
|
connector->interlace_allowed = false;
|
|
connector->doublescan_allowed = false;
|
|
|
|
- lvds_priv = (struct intel_lvds_priv *)(intel_output + 1);
|
|
- intel_output->dev_priv = lvds_priv;
|
|
+ lvds_priv = (struct intel_lvds_priv *)(intel_encoder + 1);
|
|
+ intel_encoder->dev_priv = lvds_priv;
|
|
/* create the scaling mode property */
|
|
drm_mode_create_scaling_mode_property(dev);
|
|
/*
|
|
* the initial panel fitting mode will be FULL_SCREEN.
|
|
*/
|
|
|
|
- drm_connector_attach_property(&intel_output->base,
|
|
+ drm_connector_attach_property(&intel_connector->base,
|
|
dev->mode_config.scaling_mode_property,
|
|
DRM_MODE_SCALE_FULLSCREEN);
|
|
lvds_priv->fitting_mode = DRM_MODE_SCALE_FULLSCREEN;
|
|
@@ -1085,8 +995,8 @@ void intel_lvds_init(struct drm_device *dev)
|
|
*/
|
|
|
|
/* Set up the DDC bus. */
|
|
- intel_output->ddc_bus = intel_i2c_create(dev, gpio, "LVDSDDC_C");
|
|
- if (!intel_output->ddc_bus) {
|
|
+ intel_encoder->ddc_bus = intel_i2c_create(dev, gpio, "LVDSDDC_C");
|
|
+ if (!intel_encoder->ddc_bus) {
|
|
dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration "
|
|
"failed.\n");
|
|
goto failed;
|
|
@@ -1096,7 +1006,10 @@ void intel_lvds_init(struct drm_device *dev)
|
|
* Attempt to get the fixed panel mode from DDC. Assume that the
|
|
* preferred mode is the right one.
|
|
*/
|
|
- intel_ddc_get_modes(intel_output);
|
|
+ dev_priv->lvds_edid_good = true;
|
|
+
|
|
+ if (!intel_ddc_get_modes(connector, intel_encoder->ddc_bus))
|
|
+ dev_priv->lvds_edid_good = false;
|
|
|
|
list_for_each_entry(scan, &connector->probed_modes, head) {
|
|
mutex_lock(&dev->mode_config.mutex);
|
|
@@ -1130,7 +1043,7 @@ void intel_lvds_init(struct drm_device *dev)
|
|
*/
|
|
|
|
/* Ironlake: FIXME if still fail, not try pipe mode now */
|
|
- if (IS_IRONLAKE(dev))
|
|
+ if (HAS_PCH_SPLIT(dev))
|
|
goto failed;
|
|
|
|
lvds = I915_READ(LVDS);
|
|
@@ -1151,7 +1064,7 @@ void intel_lvds_init(struct drm_device *dev)
|
|
goto failed;
|
|
|
|
out:
|
|
- if (IS_IRONLAKE(dev)) {
|
|
+ if (HAS_PCH_SPLIT(dev)) {
|
|
u32 pwm;
|
|
/* make sure PWM is enabled */
|
|
pwm = I915_READ(BLC_PWM_CPU_CTL2);
|
|
@@ -1174,9 +1087,10 @@ out:
|
|
|
|
failed:
|
|
DRM_DEBUG_KMS("No LVDS modes found, disabling.\n");
|
|
- if (intel_output->ddc_bus)
|
|
- intel_i2c_destroy(intel_output->ddc_bus);
|
|
+ if (intel_encoder->ddc_bus)
|
|
+ intel_i2c_destroy(intel_encoder->ddc_bus);
|
|
drm_connector_cleanup(connector);
|
|
drm_encoder_cleanup(encoder);
|
|
- kfree(intel_output);
|
|
+ kfree(intel_encoder);
|
|
+ kfree(intel_connector);
|
|
}
|
|
diff --git a/drivers/gpu/drm/i915/intel_modes.c b/drivers/gpu/drm/i915/intel_modes.c
|
|
--- a/drivers/gpu/drm/i915/intel_modes.c
|
|
+++ b/drivers/gpu/drm/i915/intel_modes.c
|
|
@@ -33,7 +33,7 @@
|
|
* intel_ddc_probe
|
|
*
|
|
*/
|
|
-bool intel_ddc_probe(struct intel_output *intel_output)
|
|
+bool intel_ddc_probe(struct intel_encoder *intel_encoder)
|
|
{
|
|
u8 out_buf[] = { 0x0, 0x0};
|
|
u8 buf[2];
|
|
@@ -53,9 +53,9 @@ bool intel_ddc_probe(struct intel_output *intel_output)
|
|
}
|
|
};
|
|
|
|
- intel_i2c_quirk_set(intel_output->base.dev, true);
|
|
- ret = i2c_transfer(intel_output->ddc_bus, msgs, 2);
|
|
- intel_i2c_quirk_set(intel_output->base.dev, false);
|
|
+ intel_i2c_quirk_set(intel_encoder->enc.dev, true);
|
|
+ ret = i2c_transfer(intel_encoder->ddc_bus, msgs, 2);
|
|
+ intel_i2c_quirk_set(intel_encoder->enc.dev, false);
|
|
if (ret == 2)
|
|
return true;
|
|
|
|
@@ -65,22 +65,23 @@ bool intel_ddc_probe(struct intel_output *intel_output)
|
|
/**
|
|
* intel_ddc_get_modes - get modelist from monitor
|
|
* @connector: DRM connector device to use
|
|
+ * @adapter: i2c adapter
|
|
*
|
|
* Fetch the EDID information from @connector using the DDC bus.
|
|
*/
|
|
-int intel_ddc_get_modes(struct intel_output *intel_output)
|
|
+int intel_ddc_get_modes(struct drm_connector *connector,
|
|
+ struct i2c_adapter *adapter)
|
|
{
|
|
struct edid *edid;
|
|
int ret = 0;
|
|
|
|
- intel_i2c_quirk_set(intel_output->base.dev, true);
|
|
- edid = drm_get_edid(&intel_output->base, intel_output->ddc_bus);
|
|
- intel_i2c_quirk_set(intel_output->base.dev, false);
|
|
+ intel_i2c_quirk_set(connector->dev, true);
|
|
+ edid = drm_get_edid(connector, adapter);
|
|
+ intel_i2c_quirk_set(connector->dev, false);
|
|
if (edid) {
|
|
- drm_mode_connector_update_edid_property(&intel_output->base,
|
|
- edid);
|
|
- ret = drm_add_edid_modes(&intel_output->base, edid);
|
|
- intel_output->base.display_info.raw_edid = NULL;
|
|
+ drm_mode_connector_update_edid_property(connector, edid);
|
|
+ ret = drm_add_edid_modes(connector, edid);
|
|
+ connector->display_info.raw_edid = NULL;
|
|
kfree(edid);
|
|
}
|
|
|
|
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
|
|
--- a/drivers/gpu/drm/i915/intel_overlay.c
|
|
+++ b/drivers/gpu/drm/i915/intel_overlay.c
|
|
@@ -172,7 +172,7 @@ struct overlay_registers {
|
|
#define OFC_UPDATE 0x1
|
|
|
|
#define OVERLAY_NONPHYSICAL(dev) (IS_G33(dev) || IS_I965G(dev))
|
|
-#define OVERLAY_EXISTS(dev) (!IS_G4X(dev) && !IS_IRONLAKE(dev))
|
|
+#define OVERLAY_EXISTS(dev) (!IS_G4X(dev) && !IS_IRONLAKE(dev) && !IS_GEN6(dev))
|
|
|
|
|
|
static struct overlay_registers *intel_overlay_map_regs_atomic(struct intel_overlay *overlay)
|
|
@@ -199,16 +199,11 @@ static struct overlay_registers *intel_overlay_map_regs_atomic(struct intel_over
|
|
|
|
static void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay)
|
|
{
|
|
- struct drm_device *dev = overlay->dev;
|
|
- drm_i915_private_t *dev_priv = dev->dev_private;
|
|
-
|
|
if (OVERLAY_NONPHYSICAL(overlay->dev))
|
|
io_mapping_unmap_atomic(overlay->virt_addr);
|
|
|
|
overlay->virt_addr = NULL;
|
|
|
|
- I915_READ(OVADD); /* flush wc cashes */
|
|
-
|
|
return;
|
|
}
|
|
|
|
@@ -225,9 +220,7 @@ static int intel_overlay_on(struct intel_overlay *overlay)
|
|
overlay->active = 1;
|
|
overlay->hw_wedged = NEEDS_WAIT_FOR_FLIP;
|
|
|
|
- BEGIN_LP_RING(6);
|
|
- OUT_RING(MI_FLUSH);
|
|
- OUT_RING(MI_NOOP);
|
|
+ BEGIN_LP_RING(4);
|
|
OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_ON);
|
|
OUT_RING(overlay->flip_addr | OFC_UPDATE);
|
|
OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
|
|
@@ -267,9 +260,7 @@ static void intel_overlay_continue(struct intel_overlay *overlay,
|
|
if (tmp & (1 << 17))
|
|
DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp);
|
|
|
|
- BEGIN_LP_RING(4);
|
|
- OUT_RING(MI_FLUSH);
|
|
- OUT_RING(MI_NOOP);
|
|
+ BEGIN_LP_RING(2);
|
|
OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
|
|
OUT_RING(flip_addr);
|
|
ADVANCE_LP_RING();
|
|
@@ -338,9 +329,7 @@ static int intel_overlay_off(struct intel_overlay *overlay)
|
|
/* wait for overlay to go idle */
|
|
overlay->hw_wedged = SWITCH_OFF_STAGE_1;
|
|
|
|
- BEGIN_LP_RING(6);
|
|
- OUT_RING(MI_FLUSH);
|
|
- OUT_RING(MI_NOOP);
|
|
+ BEGIN_LP_RING(4);
|
|
OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
|
|
OUT_RING(flip_addr);
|
|
OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
|
|
@@ -358,9 +347,7 @@ static int intel_overlay_off(struct intel_overlay *overlay)
|
|
/* turn overlay off */
|
|
overlay->hw_wedged = SWITCH_OFF_STAGE_2;
|
|
|
|
- BEGIN_LP_RING(6);
|
|
- OUT_RING(MI_FLUSH);
|
|
- OUT_RING(MI_NOOP);
|
|
+ BEGIN_LP_RING(4);
|
|
OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
|
|
OUT_RING(flip_addr);
|
|
OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
|
|
@@ -435,9 +422,7 @@ int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay,
|
|
|
|
overlay->hw_wedged = SWITCH_OFF_STAGE_2;
|
|
|
|
- BEGIN_LP_RING(6);
|
|
- OUT_RING(MI_FLUSH);
|
|
- OUT_RING(MI_NOOP);
|
|
+ BEGIN_LP_RING(4);
|
|
OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
|
|
OUT_RING(flip_addr);
|
|
OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
|
|
@@ -739,7 +724,7 @@ int intel_overlay_do_put_image(struct intel_overlay *overlay,
|
|
int ret, tmp_width;
|
|
struct overlay_registers *regs;
|
|
bool scale_changed = false;
|
|
- struct drm_i915_gem_object *bo_priv = new_bo->driver_private;
|
|
+ struct drm_i915_gem_object *bo_priv = to_intel_bo(new_bo);
|
|
struct drm_device *dev = overlay->dev;
|
|
|
|
BUG_ON(!mutex_is_locked(&dev->struct_mutex));
|
|
@@ -824,7 +809,7 @@ int intel_overlay_do_put_image(struct intel_overlay *overlay,
|
|
intel_overlay_continue(overlay, scale_changed);
|
|
|
|
overlay->old_vid_bo = overlay->vid_bo;
|
|
- overlay->vid_bo = new_bo->driver_private;
|
|
+ overlay->vid_bo = to_intel_bo(new_bo);
|
|
|
|
return 0;
|
|
|
|
@@ -1183,8 +1168,8 @@ int intel_overlay_put_image(struct drm_device *dev, void *data,
|
|
out_unlock:
|
|
mutex_unlock(&dev->struct_mutex);
|
|
mutex_unlock(&dev->mode_config.mutex);
|
|
-out_free:
|
|
drm_gem_object_unreference_unlocked(new_bo);
|
|
+out_free:
|
|
kfree(params);
|
|
|
|
return ret;
|
|
@@ -1359,7 +1344,7 @@ void intel_setup_overlay(struct drm_device *dev)
|
|
reg_bo = drm_gem_object_alloc(dev, PAGE_SIZE);
|
|
if (!reg_bo)
|
|
goto out_free;
|
|
- overlay->reg_bo = reg_bo->driver_private;
|
|
+ overlay->reg_bo = to_intel_bo(reg_bo);
|
|
|
|
if (OVERLAY_NONPHYSICAL(dev)) {
|
|
ret = i915_gem_object_pin(reg_bo, PAGE_SIZE);
|
|
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
|
|
--- a/drivers/gpu/drm/i915/intel_sdvo.c
|
|
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
|
|
@@ -35,7 +35,18 @@
|
|
#include "i915_drm.h"
|
|
#include "i915_drv.h"
|
|
#include "intel_sdvo_regs.h"
|
|
-#include <linux/dmi.h>
|
|
+
|
|
+#define SDVO_TMDS_MASK (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1)
|
|
+#define SDVO_RGB_MASK (SDVO_OUTPUT_RGB0 | SDVO_OUTPUT_RGB1)
|
|
+#define SDVO_LVDS_MASK (SDVO_OUTPUT_LVDS0 | SDVO_OUTPUT_LVDS1)
|
|
+#define SDVO_TV_MASK (SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_SVID0)
|
|
+
|
|
+#define SDVO_OUTPUT_MASK (SDVO_TMDS_MASK | SDVO_RGB_MASK | SDVO_LVDS_MASK |\
|
|
+ SDVO_TV_MASK)
|
|
+
|
|
+#define IS_TV(c) (c->output_flag & SDVO_TV_MASK)
|
|
+#define IS_LVDS(c) (c->output_flag & SDVO_LVDS_MASK)
|
|
+
|
|
|
|
static char *tv_format_names[] = {
|
|
"NTSC_M" , "NTSC_J" , "NTSC_443",
|
|
@@ -53,7 +64,7 @@ struct intel_sdvo_priv {
|
|
u8 slave_addr;
|
|
|
|
/* Register for the SDVO device: SDVOB or SDVOC */
|
|
- int output_device;
|
|
+ int sdvo_reg;
|
|
|
|
/* Active outputs controlled by this SDVO output */
|
|
uint16_t controlled_output;
|
|
@@ -85,12 +96,6 @@ struct intel_sdvo_priv {
|
|
/* This is for current tv format name */
|
|
char *tv_format_name;
|
|
|
|
- /* This contains all current supported TV format */
|
|
- char *tv_format_supported[TV_FORMAT_NUM];
|
|
- int format_supported_num;
|
|
- struct drm_property *tv_format_property;
|
|
- struct drm_property *tv_format_name_property[TV_FORMAT_NUM];
|
|
-
|
|
/**
|
|
* This is set if we treat the device as HDMI, instead of DVI.
|
|
*/
|
|
@@ -111,29 +116,36 @@ struct intel_sdvo_priv {
|
|
*/
|
|
struct drm_display_mode *sdvo_lvds_fixed_mode;
|
|
|
|
- /**
|
|
- * Returned SDTV resolutions allowed for the current format, if the
|
|
- * device reported it.
|
|
- */
|
|
- struct intel_sdvo_sdtv_resolution_reply sdtv_resolutions;
|
|
-
|
|
/*
|
|
* supported encoding mode, used to determine whether HDMI is
|
|
* supported
|
|
*/
|
|
struct intel_sdvo_encode encode;
|
|
|
|
- /* DDC bus used by this SDVO output */
|
|
+ /* DDC bus used by this SDVO encoder */
|
|
uint8_t ddc_bus;
|
|
|
|
/* Mac mini hack -- use the same DDC as the analog connector */
|
|
struct i2c_adapter *analog_ddc_bus;
|
|
|
|
- int save_sdvo_mult;
|
|
- u16 save_active_outputs;
|
|
- struct intel_sdvo_dtd save_input_dtd_1, save_input_dtd_2;
|
|
- struct intel_sdvo_dtd save_output_dtd[16];
|
|
- u32 save_SDVOX;
|
|
+};
|
|
+
|
|
+struct intel_sdvo_connector {
|
|
+ /* Mark the type of connector */
|
|
+ uint16_t output_flag;
|
|
+
|
|
+ /* This contains all current supported TV format */
|
|
+ char *tv_format_supported[TV_FORMAT_NUM];
|
|
+ int format_supported_num;
|
|
+ struct drm_property *tv_format_property;
|
|
+ struct drm_property *tv_format_name_property[TV_FORMAT_NUM];
|
|
+
|
|
+ /**
|
|
+ * Returned SDTV resolutions allowed for the current format, if the
|
|
+ * device reported it.
|
|
+ */
|
|
+ struct intel_sdvo_sdtv_resolution_reply sdtv_resolutions;
|
|
+
|
|
/* add the property for the SDVO-TV */
|
|
struct drm_property *left_property;
|
|
struct drm_property *right_property;
|
|
@@ -161,22 +173,33 @@ struct intel_sdvo_priv {
|
|
};
|
|
|
|
static bool
|
|
-intel_sdvo_output_setup(struct intel_output *intel_output, uint16_t flags);
|
|
+intel_sdvo_output_setup(struct intel_encoder *intel_encoder,
|
|
+ uint16_t flags);
|
|
+static void
|
|
+intel_sdvo_tv_create_property(struct drm_connector *connector, int type);
|
|
+static void
|
|
+intel_sdvo_create_enhance_property(struct drm_connector *connector);
|
|
|
|
/**
|
|
* Writes the SDVOB or SDVOC with the given value, but always writes both
|
|
* SDVOB and SDVOC to work around apparent hardware issues (according to
|
|
* comments in the BIOS).
|
|
*/
|
|
-static void intel_sdvo_write_sdvox(struct intel_output *intel_output, u32 val)
|
|
+static void intel_sdvo_write_sdvox(struct intel_encoder *intel_encoder, u32 val)
|
|
{
|
|
- struct drm_device *dev = intel_output->base.dev;
|
|
+ struct drm_device *dev = intel_encoder->enc.dev;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
- struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
|
|
+ struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
|
|
u32 bval = val, cval = val;
|
|
int i;
|
|
|
|
- if (sdvo_priv->output_device == SDVOB) {
|
|
+ if (sdvo_priv->sdvo_reg == PCH_SDVOB) {
|
|
+ I915_WRITE(sdvo_priv->sdvo_reg, val);
|
|
+ I915_READ(sdvo_priv->sdvo_reg);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (sdvo_priv->sdvo_reg == SDVOB) {
|
|
cval = I915_READ(SDVOC);
|
|
} else {
|
|
bval = I915_READ(SDVOB);
|
|
@@ -195,10 +218,10 @@ static void intel_sdvo_write_sdvox(struct intel_output *intel_output, u32 val)
|
|
}
|
|
}
|
|
|
|
-static bool intel_sdvo_read_byte(struct intel_output *intel_output, u8 addr,
|
|
+static bool intel_sdvo_read_byte(struct intel_encoder *intel_encoder, u8 addr,
|
|
u8 *ch)
|
|
{
|
|
- struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
|
|
+ struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
|
|
u8 out_buf[2];
|
|
u8 buf[2];
|
|
int ret;
|
|
@@ -221,7 +244,7 @@ static bool intel_sdvo_read_byte(struct intel_output *intel_output, u8 addr,
|
|
out_buf[0] = addr;
|
|
out_buf[1] = 0;
|
|
|
|
- if ((ret = i2c_transfer(intel_output->i2c_bus, msgs, 2)) == 2)
|
|
+ if ((ret = i2c_transfer(intel_encoder->i2c_bus, msgs, 2)) == 2)
|
|
{
|
|
*ch = buf[0];
|
|
return true;
|
|
@@ -231,10 +254,10 @@ static bool intel_sdvo_read_byte(struct intel_output *intel_output, u8 addr,
|
|
return false;
|
|
}
|
|
|
|
-static bool intel_sdvo_write_byte(struct intel_output *intel_output, int addr,
|
|
+static bool intel_sdvo_write_byte(struct intel_encoder *intel_encoder, int addr,
|
|
u8 ch)
|
|
{
|
|
- struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
|
|
+ struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
|
|
u8 out_buf[2];
|
|
struct i2c_msg msgs[] = {
|
|
{
|
|
@@ -248,7 +271,7 @@ static bool intel_sdvo_write_byte(struct intel_output *intel_output, int addr,
|
|
out_buf[0] = addr;
|
|
out_buf[1] = ch;
|
|
|
|
- if (i2c_transfer(intel_output->i2c_bus, msgs, 1) == 1)
|
|
+ if (i2c_transfer(intel_encoder->i2c_bus, msgs, 1) == 1)
|
|
{
|
|
return true;
|
|
}
|
|
@@ -352,13 +375,14 @@ static const struct _sdvo_cmd_name {
|
|
SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_DATA),
|
|
};
|
|
|
|
-#define SDVO_NAME(dev_priv) ((dev_priv)->output_device == SDVOB ? "SDVOB" : "SDVOC")
|
|
-#define SDVO_PRIV(output) ((struct intel_sdvo_priv *) (output)->dev_priv)
|
|
+#define IS_SDVOB(reg) (reg == SDVOB || reg == PCH_SDVOB)
|
|
+#define SDVO_NAME(dev_priv) (IS_SDVOB((dev_priv)->sdvo_reg) ? "SDVOB" : "SDVOC")
|
|
+#define SDVO_PRIV(encoder) ((struct intel_sdvo_priv *) (encoder)->dev_priv)
|
|
|
|
-static void intel_sdvo_debug_write(struct intel_output *intel_output, u8 cmd,
|
|
+static void intel_sdvo_debug_write(struct intel_encoder *intel_encoder, u8 cmd,
|
|
void *args, int args_len)
|
|
{
|
|
- struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
|
|
+ struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
|
|
int i;
|
|
|
|
DRM_DEBUG_KMS("%s: W: %02X ",
|
|
@@ -378,19 +402,19 @@ static void intel_sdvo_debug_write(struct intel_output *intel_output, u8 cmd,
|
|
DRM_LOG_KMS("\n");
|
|
}
|
|
|
|
-static void intel_sdvo_write_cmd(struct intel_output *intel_output, u8 cmd,
|
|
+static void intel_sdvo_write_cmd(struct intel_encoder *intel_encoder, u8 cmd,
|
|
void *args, int args_len)
|
|
{
|
|
int i;
|
|
|
|
- intel_sdvo_debug_write(intel_output, cmd, args, args_len);
|
|
+ intel_sdvo_debug_write(intel_encoder, cmd, args, args_len);
|
|
|
|
for (i = 0; i < args_len; i++) {
|
|
- intel_sdvo_write_byte(intel_output, SDVO_I2C_ARG_0 - i,
|
|
+ intel_sdvo_write_byte(intel_encoder, SDVO_I2C_ARG_0 - i,
|
|
((u8*)args)[i]);
|
|
}
|
|
|
|
- intel_sdvo_write_byte(intel_output, SDVO_I2C_OPCODE, cmd);
|
|
+ intel_sdvo_write_byte(intel_encoder, SDVO_I2C_OPCODE, cmd);
|
|
}
|
|
|
|
static const char *cmd_status_names[] = {
|
|
@@ -403,11 +427,11 @@ static const char *cmd_status_names[] = {
|
|
"Scaling not supported"
|
|
};
|
|
|
|
-static void intel_sdvo_debug_response(struct intel_output *intel_output,
|
|
+static void intel_sdvo_debug_response(struct intel_encoder *intel_encoder,
|
|
void *response, int response_len,
|
|
u8 status)
|
|
{
|
|
- struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
|
|
+ struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
|
|
int i;
|
|
|
|
DRM_DEBUG_KMS("%s: R: ", SDVO_NAME(sdvo_priv));
|
|
@@ -422,7 +446,7 @@ static void intel_sdvo_debug_response(struct intel_output *intel_output,
|
|
DRM_LOG_KMS("\n");
|
|
}
|
|
|
|
-static u8 intel_sdvo_read_response(struct intel_output *intel_output,
|
|
+static u8 intel_sdvo_read_response(struct intel_encoder *intel_encoder,
|
|
void *response, int response_len)
|
|
{
|
|
int i;
|
|
@@ -432,16 +456,16 @@ static u8 intel_sdvo_read_response(struct intel_output *intel_output,
|
|
while (retry--) {
|
|
/* Read the command response */
|
|
for (i = 0; i < response_len; i++) {
|
|
- intel_sdvo_read_byte(intel_output,
|
|
+ intel_sdvo_read_byte(intel_encoder,
|
|
SDVO_I2C_RETURN_0 + i,
|
|
&((u8 *)response)[i]);
|
|
}
|
|
|
|
/* read the return status */
|
|
- intel_sdvo_read_byte(intel_output, SDVO_I2C_CMD_STATUS,
|
|
+ intel_sdvo_read_byte(intel_encoder, SDVO_I2C_CMD_STATUS,
|
|
&status);
|
|
|
|
- intel_sdvo_debug_response(intel_output, response, response_len,
|
|
+ intel_sdvo_debug_response(intel_encoder, response, response_len,
|
|
status);
|
|
if (status != SDVO_CMD_STATUS_PENDING)
|
|
return status;
|
|
@@ -469,10 +493,10 @@ static int intel_sdvo_get_pixel_multiplier(struct drm_display_mode *mode)
|
|
* another I2C transaction after issuing the DDC bus switch, it will be
|
|
* switched to the internal SDVO register.
|
|
*/
|
|
-static void intel_sdvo_set_control_bus_switch(struct intel_output *intel_output,
|
|
+static void intel_sdvo_set_control_bus_switch(struct intel_encoder *intel_encoder,
|
|
u8 target)
|
|
{
|
|
- struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
|
|
+ struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
|
|
u8 out_buf[2], cmd_buf[2], ret_value[2], ret;
|
|
struct i2c_msg msgs[] = {
|
|
{
|
|
@@ -496,10 +520,10 @@ static void intel_sdvo_set_control_bus_switch(struct intel_output *intel_output,
|
|
},
|
|
};
|
|
|
|
- intel_sdvo_debug_write(intel_output, SDVO_CMD_SET_CONTROL_BUS_SWITCH,
|
|
+ intel_sdvo_debug_write(intel_encoder, SDVO_CMD_SET_CONTROL_BUS_SWITCH,
|
|
&target, 1);
|
|
/* write the DDC switch command argument */
|
|
- intel_sdvo_write_byte(intel_output, SDVO_I2C_ARG_0, target);
|
|
+ intel_sdvo_write_byte(intel_encoder, SDVO_I2C_ARG_0, target);
|
|
|
|
out_buf[0] = SDVO_I2C_OPCODE;
|
|
out_buf[1] = SDVO_CMD_SET_CONTROL_BUS_SWITCH;
|
|
@@ -508,7 +532,7 @@ static void intel_sdvo_set_control_bus_switch(struct intel_output *intel_output,
|
|
ret_value[0] = 0;
|
|
ret_value[1] = 0;
|
|
|
|
- ret = i2c_transfer(intel_output->i2c_bus, msgs, 3);
|
|
+ ret = i2c_transfer(intel_encoder->i2c_bus, msgs, 3);
|
|
if (ret != 3) {
|
|
/* failure in I2C transfer */
|
|
DRM_DEBUG_KMS("I2c transfer returned %d\n", ret);
|
|
@@ -522,7 +546,7 @@ static void intel_sdvo_set_control_bus_switch(struct intel_output *intel_output,
|
|
return;
|
|
}
|
|
|
|
-static bool intel_sdvo_set_target_input(struct intel_output *intel_output, bool target_0, bool target_1)
|
|
+static bool intel_sdvo_set_target_input(struct intel_encoder *intel_encoder, bool target_0, bool target_1)
|
|
{
|
|
struct intel_sdvo_set_target_input_args targets = {0};
|
|
u8 status;
|
|
@@ -533,10 +557,10 @@ static bool intel_sdvo_set_target_input(struct intel_output *intel_output, bool
|
|
if (target_1)
|
|
targets.target_1 = 1;
|
|
|
|
- intel_sdvo_write_cmd(intel_output, SDVO_CMD_SET_TARGET_INPUT, &targets,
|
|
+ intel_sdvo_write_cmd(intel_encoder, SDVO_CMD_SET_TARGET_INPUT, &targets,
|
|
sizeof(targets));
|
|
|
|
- status = intel_sdvo_read_response(intel_output, NULL, 0);
|
|
+ status = intel_sdvo_read_response(intel_encoder, NULL, 0);
|
|
|
|
return (status == SDVO_CMD_STATUS_SUCCESS);
|
|
}
|
|
@@ -547,13 +571,13 @@ static bool intel_sdvo_set_target_input(struct intel_output *intel_output, bool
|
|
* This function is making an assumption about the layout of the response,
|
|
* which should be checked against the docs.
|
|
*/
|
|
-static bool intel_sdvo_get_trained_inputs(struct intel_output *intel_output, bool *input_1, bool *input_2)
|
|
+static bool intel_sdvo_get_trained_inputs(struct intel_encoder *intel_encoder, bool *input_1, bool *input_2)
|
|
{
|
|
struct intel_sdvo_get_trained_inputs_response response;
|
|
u8 status;
|
|
|
|
- intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_TRAINED_INPUTS, NULL, 0);
|
|
- status = intel_sdvo_read_response(intel_output, &response, sizeof(response));
|
|
+ intel_sdvo_write_cmd(intel_encoder, SDVO_CMD_GET_TRAINED_INPUTS, NULL, 0);
|
|
+ status = intel_sdvo_read_response(intel_encoder, &response, sizeof(response));
|
|
if (status != SDVO_CMD_STATUS_SUCCESS)
|
|
return false;
|
|
|
|
@@ -562,29 +586,18 @@ static bool intel_sdvo_get_trained_inputs(struct intel_output *intel_output, boo
|
|
return true;
|
|
}
|
|
|
|
-static bool intel_sdvo_get_active_outputs(struct intel_output *intel_output,
|
|
- u16 *outputs)
|
|
-{
|
|
- u8 status;
|
|
-
|
|
- intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_ACTIVE_OUTPUTS, NULL, 0);
|
|
- status = intel_sdvo_read_response(intel_output, outputs, sizeof(*outputs));
|
|
-
|
|
- return (status == SDVO_CMD_STATUS_SUCCESS);
|
|
-}
|
|
-
|
|
-static bool intel_sdvo_set_active_outputs(struct intel_output *intel_output,
|
|
+static bool intel_sdvo_set_active_outputs(struct intel_encoder *intel_encoder,
|
|
u16 outputs)
|
|
{
|
|
u8 status;
|
|
|
|
- intel_sdvo_write_cmd(intel_output, SDVO_CMD_SET_ACTIVE_OUTPUTS, &outputs,
|
|
+ intel_sdvo_write_cmd(intel_encoder, SDVO_CMD_SET_ACTIVE_OUTPUTS, &outputs,
|
|
sizeof(outputs));
|
|
- status = intel_sdvo_read_response(intel_output, NULL, 0);
|
|
+ status = intel_sdvo_read_response(intel_encoder, NULL, 0);
|
|
return (status == SDVO_CMD_STATUS_SUCCESS);
|
|
}
|
|
|
|
-static bool intel_sdvo_set_encoder_power_state(struct intel_output *intel_output,
|
|
+static bool intel_sdvo_set_encoder_power_state(struct intel_encoder *intel_encoder,
|
|
int mode)
|
|
{
|
|
u8 status, state = SDVO_ENCODER_STATE_ON;
|
|
@@ -604,24 +617,24 @@ static bool intel_sdvo_set_encoder_power_state(struct intel_output *intel_output
|
|
break;
|
|
}
|
|
|
|
- intel_sdvo_write_cmd(intel_output, SDVO_CMD_SET_ENCODER_POWER_STATE, &state,
|
|
+ intel_sdvo_write_cmd(intel_encoder, SDVO_CMD_SET_ENCODER_POWER_STATE, &state,
|
|
sizeof(state));
|
|
- status = intel_sdvo_read_response(intel_output, NULL, 0);
|
|
+ status = intel_sdvo_read_response(intel_encoder, NULL, 0);
|
|
|
|
return (status == SDVO_CMD_STATUS_SUCCESS);
|
|
}
|
|
|
|
-static bool intel_sdvo_get_input_pixel_clock_range(struct intel_output *intel_output,
|
|
+static bool intel_sdvo_get_input_pixel_clock_range(struct intel_encoder *intel_encoder,
|
|
int *clock_min,
|
|
int *clock_max)
|
|
{
|
|
struct intel_sdvo_pixel_clock_range clocks;
|
|
u8 status;
|
|
|
|
- intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE,
|
|
+ intel_sdvo_write_cmd(intel_encoder, SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE,
|
|
NULL, 0);
|
|
|
|
- status = intel_sdvo_read_response(intel_output, &clocks, sizeof(clocks));
|
|
+ status = intel_sdvo_read_response(intel_encoder, &clocks, sizeof(clocks));
|
|
|
|
if (status != SDVO_CMD_STATUS_SUCCESS)
|
|
return false;
|
|
@@ -633,92 +646,58 @@ static bool intel_sdvo_get_input_pixel_clock_range(struct intel_output *intel_ou
|
|
return true;
|
|
}
|
|
|
|
-static bool intel_sdvo_set_target_output(struct intel_output *intel_output,
|
|
+static bool intel_sdvo_set_target_output(struct intel_encoder *intel_encoder,
|
|
u16 outputs)
|
|
{
|
|
u8 status;
|
|
|
|
- intel_sdvo_write_cmd(intel_output, SDVO_CMD_SET_TARGET_OUTPUT, &outputs,
|
|
+ intel_sdvo_write_cmd(intel_encoder, SDVO_CMD_SET_TARGET_OUTPUT, &outputs,
|
|
sizeof(outputs));
|
|
|
|
- status = intel_sdvo_read_response(intel_output, NULL, 0);
|
|
+ status = intel_sdvo_read_response(intel_encoder, NULL, 0);
|
|
return (status == SDVO_CMD_STATUS_SUCCESS);
|
|
}
|
|
|
|
-static bool intel_sdvo_get_timing(struct intel_output *intel_output, u8 cmd,
|
|
+static bool intel_sdvo_set_timing(struct intel_encoder *intel_encoder, u8 cmd,
|
|
struct intel_sdvo_dtd *dtd)
|
|
{
|
|
u8 status;
|
|
|
|
- intel_sdvo_write_cmd(intel_output, cmd, NULL, 0);
|
|
- status = intel_sdvo_read_response(intel_output, &dtd->part1,
|
|
- sizeof(dtd->part1));
|
|
+ intel_sdvo_write_cmd(intel_encoder, cmd, &dtd->part1, sizeof(dtd->part1));
|
|
+ status = intel_sdvo_read_response(intel_encoder, NULL, 0);
|
|
if (status != SDVO_CMD_STATUS_SUCCESS)
|
|
return false;
|
|
|
|
- intel_sdvo_write_cmd(intel_output, cmd + 1, NULL, 0);
|
|
- status = intel_sdvo_read_response(intel_output, &dtd->part2,
|
|
- sizeof(dtd->part2));
|
|
+ intel_sdvo_write_cmd(intel_encoder, cmd + 1, &dtd->part2, sizeof(dtd->part2));
|
|
+ status = intel_sdvo_read_response(intel_encoder, NULL, 0);
|
|
if (status != SDVO_CMD_STATUS_SUCCESS)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
-static bool intel_sdvo_get_input_timing(struct intel_output *intel_output,
|
|
+static bool intel_sdvo_set_input_timing(struct intel_encoder *intel_encoder,
|
|
struct intel_sdvo_dtd *dtd)
|
|
{
|
|
- return intel_sdvo_get_timing(intel_output,
|
|
- SDVO_CMD_GET_INPUT_TIMINGS_PART1, dtd);
|
|
-}
|
|
-
|
|
-static bool intel_sdvo_get_output_timing(struct intel_output *intel_output,
|
|
- struct intel_sdvo_dtd *dtd)
|
|
-{
|
|
- return intel_sdvo_get_timing(intel_output,
|
|
- SDVO_CMD_GET_OUTPUT_TIMINGS_PART1, dtd);
|
|
-}
|
|
-
|
|
-static bool intel_sdvo_set_timing(struct intel_output *intel_output, u8 cmd,
|
|
- struct intel_sdvo_dtd *dtd)
|
|
-{
|
|
- u8 status;
|
|
-
|
|
- intel_sdvo_write_cmd(intel_output, cmd, &dtd->part1, sizeof(dtd->part1));
|
|
- status = intel_sdvo_read_response(intel_output, NULL, 0);
|
|
- if (status != SDVO_CMD_STATUS_SUCCESS)
|
|
- return false;
|
|
-
|
|
- intel_sdvo_write_cmd(intel_output, cmd + 1, &dtd->part2, sizeof(dtd->part2));
|
|
- status = intel_sdvo_read_response(intel_output, NULL, 0);
|
|
- if (status != SDVO_CMD_STATUS_SUCCESS)
|
|
- return false;
|
|
-
|
|
- return true;
|
|
-}
|
|
-
|
|
-static bool intel_sdvo_set_input_timing(struct intel_output *intel_output,
|
|
- struct intel_sdvo_dtd *dtd)
|
|
-{
|
|
- return intel_sdvo_set_timing(intel_output,
|
|
+ return intel_sdvo_set_timing(intel_encoder,
|
|
SDVO_CMD_SET_INPUT_TIMINGS_PART1, dtd);
|
|
}
|
|
|
|
-static bool intel_sdvo_set_output_timing(struct intel_output *intel_output,
|
|
+static bool intel_sdvo_set_output_timing(struct intel_encoder *intel_encoder,
|
|
struct intel_sdvo_dtd *dtd)
|
|
{
|
|
- return intel_sdvo_set_timing(intel_output,
|
|
+ return intel_sdvo_set_timing(intel_encoder,
|
|
SDVO_CMD_SET_OUTPUT_TIMINGS_PART1, dtd);
|
|
}
|
|
|
|
static bool
|
|
-intel_sdvo_create_preferred_input_timing(struct intel_output *output,
|
|
+intel_sdvo_create_preferred_input_timing(struct intel_encoder *intel_encoder,
|
|
uint16_t clock,
|
|
uint16_t width,
|
|
uint16_t height)
|
|
{
|
|
struct intel_sdvo_preferred_input_timing_args args;
|
|
- struct intel_sdvo_priv *sdvo_priv = output->dev_priv;
|
|
+ struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
|
|
uint8_t status;
|
|
|
|
memset(&args, 0, sizeof(args));
|
|
@@ -732,32 +711,33 @@ intel_sdvo_create_preferred_input_timing(struct intel_output *output,
|
|
sdvo_priv->sdvo_lvds_fixed_mode->vdisplay != height))
|
|
args.scaled = 1;
|
|
|
|
- intel_sdvo_write_cmd(output, SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING,
|
|
+ intel_sdvo_write_cmd(intel_encoder,
|
|
+ SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING,
|
|
&args, sizeof(args));
|
|
- status = intel_sdvo_read_response(output, NULL, 0);
|
|
+ status = intel_sdvo_read_response(intel_encoder, NULL, 0);
|
|
if (status != SDVO_CMD_STATUS_SUCCESS)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
-static bool intel_sdvo_get_preferred_input_timing(struct intel_output *output,
|
|
+static bool intel_sdvo_get_preferred_input_timing(struct intel_encoder *intel_encoder,
|
|
struct intel_sdvo_dtd *dtd)
|
|
{
|
|
bool status;
|
|
|
|
- intel_sdvo_write_cmd(output, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1,
|
|
+ intel_sdvo_write_cmd(intel_encoder, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1,
|
|
NULL, 0);
|
|
|
|
- status = intel_sdvo_read_response(output, &dtd->part1,
|
|
+ status = intel_sdvo_read_response(intel_encoder, &dtd->part1,
|
|
sizeof(dtd->part1));
|
|
if (status != SDVO_CMD_STATUS_SUCCESS)
|
|
return false;
|
|
|
|
- intel_sdvo_write_cmd(output, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2,
|
|
+ intel_sdvo_write_cmd(intel_encoder, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2,
|
|
NULL, 0);
|
|
|
|
- status = intel_sdvo_read_response(output, &dtd->part2,
|
|
+ status = intel_sdvo_read_response(intel_encoder, &dtd->part2,
|
|
sizeof(dtd->part2));
|
|
if (status != SDVO_CMD_STATUS_SUCCESS)
|
|
return false;
|
|
@@ -765,29 +745,12 @@ static bool intel_sdvo_get_preferred_input_timing(struct intel_output *output,
|
|
return false;
|
|
}
|
|
|
|
-static int intel_sdvo_get_clock_rate_mult(struct intel_output *intel_output)
|
|
-{
|
|
- u8 response, status;
|
|
-
|
|
- intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_CLOCK_RATE_MULT, NULL, 0);
|
|
- status = intel_sdvo_read_response(intel_output, &response, 1);
|
|
-
|
|
- if (status != SDVO_CMD_STATUS_SUCCESS) {
|
|
- DRM_DEBUG_KMS("Couldn't get SDVO clock rate multiplier\n");
|
|
- return SDVO_CLOCK_RATE_MULT_1X;
|
|
- } else {
|
|
- DRM_DEBUG_KMS("Current clock rate multiplier: %d\n", response);
|
|
- }
|
|
-
|
|
- return response;
|
|
-}
|
|
-
|
|
-static bool intel_sdvo_set_clock_rate_mult(struct intel_output *intel_output, u8 val)
|
|
+static bool intel_sdvo_set_clock_rate_mult(struct intel_encoder *intel_encoder, u8 val)
|
|
{
|
|
u8 status;
|
|
|
|
- intel_sdvo_write_cmd(intel_output, SDVO_CMD_SET_CLOCK_RATE_MULT, &val, 1);
|
|
- status = intel_sdvo_read_response(intel_output, NULL, 0);
|
|
+ intel_sdvo_write_cmd(intel_encoder, SDVO_CMD_SET_CLOCK_RATE_MULT, &val, 1);
|
|
+ status = intel_sdvo_read_response(intel_encoder, NULL, 0);
|
|
if (status != SDVO_CMD_STATUS_SUCCESS)
|
|
return false;
|
|
|
|
@@ -876,13 +839,13 @@ static void intel_sdvo_get_mode_from_dtd(struct drm_display_mode * mode,
|
|
mode->flags |= DRM_MODE_FLAG_PVSYNC;
|
|
}
|
|
|
|
-static bool intel_sdvo_get_supp_encode(struct intel_output *output,
|
|
+static bool intel_sdvo_get_supp_encode(struct intel_encoder *intel_encoder,
|
|
struct intel_sdvo_encode *encode)
|
|
{
|
|
uint8_t status;
|
|
|
|
- intel_sdvo_write_cmd(output, SDVO_CMD_GET_SUPP_ENCODE, NULL, 0);
|
|
- status = intel_sdvo_read_response(output, encode, sizeof(*encode));
|
|
+ intel_sdvo_write_cmd(intel_encoder, SDVO_CMD_GET_SUPP_ENCODE, NULL, 0);
|
|
+ status = intel_sdvo_read_response(intel_encoder, encode, sizeof(*encode));
|
|
if (status != SDVO_CMD_STATUS_SUCCESS) { /* non-support means DVI */
|
|
memset(encode, 0, sizeof(*encode));
|
|
return false;
|
|
@@ -891,29 +854,30 @@ static bool intel_sdvo_get_supp_encode(struct intel_output *output,
|
|
return true;
|
|
}
|
|
|
|
-static bool intel_sdvo_set_encode(struct intel_output *output, uint8_t mode)
|
|
+static bool intel_sdvo_set_encode(struct intel_encoder *intel_encoder,
|
|
+ uint8_t mode)
|
|
{
|
|
uint8_t status;
|
|
|
|
- intel_sdvo_write_cmd(output, SDVO_CMD_SET_ENCODE, &mode, 1);
|
|
- status = intel_sdvo_read_response(output, NULL, 0);
|
|
+ intel_sdvo_write_cmd(intel_encoder, SDVO_CMD_SET_ENCODE, &mode, 1);
|
|
+ status = intel_sdvo_read_response(intel_encoder, NULL, 0);
|
|
|
|
return (status == SDVO_CMD_STATUS_SUCCESS);
|
|
}
|
|
|
|
-static bool intel_sdvo_set_colorimetry(struct intel_output *output,
|
|
+static bool intel_sdvo_set_colorimetry(struct intel_encoder *intel_encoder,
|
|
uint8_t mode)
|
|
{
|
|
uint8_t status;
|
|
|
|
- intel_sdvo_write_cmd(output, SDVO_CMD_SET_COLORIMETRY, &mode, 1);
|
|
- status = intel_sdvo_read_response(output, NULL, 0);
|
|
+ intel_sdvo_write_cmd(intel_encoder, SDVO_CMD_SET_COLORIMETRY, &mode, 1);
|
|
+ status = intel_sdvo_read_response(intel_encoder, NULL, 0);
|
|
|
|
return (status == SDVO_CMD_STATUS_SUCCESS);
|
|
}
|
|
|
|
#if 0
|
|
-static void intel_sdvo_dump_hdmi_buf(struct intel_output *output)
|
|
+static void intel_sdvo_dump_hdmi_buf(struct intel_encoder *intel_encoder)
|
|
{
|
|
int i, j;
|
|
uint8_t set_buf_index[2];
|
|
@@ -922,43 +886,45 @@ static void intel_sdvo_dump_hdmi_buf(struct intel_output *output)
|
|
uint8_t buf[48];
|
|
uint8_t *pos;
|
|
|
|
- intel_sdvo_write_cmd(output, SDVO_CMD_GET_HBUF_AV_SPLIT, NULL, 0);
|
|
- intel_sdvo_read_response(output, &av_split, 1);
|
|
+ intel_sdvo_write_cmd(encoder, SDVO_CMD_GET_HBUF_AV_SPLIT, NULL, 0);
|
|
+ intel_sdvo_read_response(encoder, &av_split, 1);
|
|
|
|
for (i = 0; i <= av_split; i++) {
|
|
set_buf_index[0] = i; set_buf_index[1] = 0;
|
|
- intel_sdvo_write_cmd(output, SDVO_CMD_SET_HBUF_INDEX,
|
|
+ intel_sdvo_write_cmd(encoder, SDVO_CMD_SET_HBUF_INDEX,
|
|
set_buf_index, 2);
|
|
- intel_sdvo_write_cmd(output, SDVO_CMD_GET_HBUF_INFO, NULL, 0);
|
|
- intel_sdvo_read_response(output, &buf_size, 1);
|
|
+ intel_sdvo_write_cmd(encoder, SDVO_CMD_GET_HBUF_INFO, NULL, 0);
|
|
+ intel_sdvo_read_response(encoder, &buf_size, 1);
|
|
|
|
pos = buf;
|
|
for (j = 0; j <= buf_size; j += 8) {
|
|
- intel_sdvo_write_cmd(output, SDVO_CMD_GET_HBUF_DATA,
|
|
+ intel_sdvo_write_cmd(encoder, SDVO_CMD_GET_HBUF_DATA,
|
|
NULL, 0);
|
|
- intel_sdvo_read_response(output, pos, 8);
|
|
+ intel_sdvo_read_response(encoder, pos, 8);
|
|
pos += 8;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
-static void intel_sdvo_set_hdmi_buf(struct intel_output *output, int index,
|
|
- uint8_t *data, int8_t size, uint8_t tx_rate)
|
|
+static void intel_sdvo_set_hdmi_buf(struct intel_encoder *intel_encoder,
|
|
+ int index,
|
|
+ uint8_t *data, int8_t size, uint8_t tx_rate)
|
|
{
|
|
uint8_t set_buf_index[2];
|
|
|
|
set_buf_index[0] = index;
|
|
set_buf_index[1] = 0;
|
|
|
|
- intel_sdvo_write_cmd(output, SDVO_CMD_SET_HBUF_INDEX, set_buf_index, 2);
|
|
+ intel_sdvo_write_cmd(intel_encoder, SDVO_CMD_SET_HBUF_INDEX,
|
|
+ set_buf_index, 2);
|
|
|
|
for (; size > 0; size -= 8) {
|
|
- intel_sdvo_write_cmd(output, SDVO_CMD_SET_HBUF_DATA, data, 8);
|
|
+ intel_sdvo_write_cmd(intel_encoder, SDVO_CMD_SET_HBUF_DATA, data, 8);
|
|
data += 8;
|
|
}
|
|
|
|
- intel_sdvo_write_cmd(output, SDVO_CMD_SET_HBUF_TXRATE, &tx_rate, 1);
|
|
+ intel_sdvo_write_cmd(intel_encoder, SDVO_CMD_SET_HBUF_TXRATE, &tx_rate, 1);
|
|
}
|
|
|
|
static uint8_t intel_sdvo_calc_hbuf_csum(uint8_t *data, uint8_t size)
|
|
@@ -1033,7 +999,7 @@ struct dip_infoframe {
|
|
} __attribute__ ((packed)) u;
|
|
} __attribute__((packed));
|
|
|
|
-static void intel_sdvo_set_avi_infoframe(struct intel_output *output,
|
|
+static void intel_sdvo_set_avi_infoframe(struct intel_encoder *intel_encoder,
|
|
struct drm_display_mode * mode)
|
|
{
|
|
struct dip_infoframe avi_if = {
|
|
@@ -1044,15 +1010,16 @@ static void intel_sdvo_set_avi_infoframe(struct intel_output *output,
|
|
|
|
avi_if.checksum = intel_sdvo_calc_hbuf_csum((uint8_t *)&avi_if,
|
|
4 + avi_if.len);
|
|
- intel_sdvo_set_hdmi_buf(output, 1, (uint8_t *)&avi_if, 4 + avi_if.len,
|
|
+ intel_sdvo_set_hdmi_buf(intel_encoder, 1, (uint8_t *)&avi_if,
|
|
+ 4 + avi_if.len,
|
|
SDVO_HBUF_TX_VSYNC);
|
|
}
|
|
|
|
-static void intel_sdvo_set_tv_format(struct intel_output *output)
|
|
+static void intel_sdvo_set_tv_format(struct intel_encoder *intel_encoder)
|
|
{
|
|
|
|
struct intel_sdvo_tv_format format;
|
|
- struct intel_sdvo_priv *sdvo_priv = output->dev_priv;
|
|
+ struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
|
|
uint32_t format_map, i;
|
|
uint8_t status;
|
|
|
|
@@ -1065,10 +1032,10 @@ static void intel_sdvo_set_tv_format(struct intel_output *output)
|
|
memcpy(&format, &format_map, sizeof(format_map) > sizeof(format) ?
|
|
sizeof(format) : sizeof(format_map));
|
|
|
|
- intel_sdvo_write_cmd(output, SDVO_CMD_SET_TV_FORMAT, &format_map,
|
|
+ intel_sdvo_write_cmd(intel_encoder, SDVO_CMD_SET_TV_FORMAT, &format,
|
|
sizeof(format));
|
|
|
|
- status = intel_sdvo_read_response(output, NULL, 0);
|
|
+ status = intel_sdvo_read_response(intel_encoder, NULL, 0);
|
|
if (status != SDVO_CMD_STATUS_SUCCESS)
|
|
DRM_DEBUG_KMS("%s: Failed to set TV format\n",
|
|
SDVO_NAME(sdvo_priv));
|
|
@@ -1078,8 +1045,8 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder,
|
|
struct drm_display_mode *mode,
|
|
struct drm_display_mode *adjusted_mode)
|
|
{
|
|
- struct intel_output *output = enc_to_intel_output(encoder);
|
|
- struct intel_sdvo_priv *dev_priv = output->dev_priv;
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ struct intel_sdvo_priv *dev_priv = intel_encoder->dev_priv;
|
|
|
|
if (dev_priv->is_tv) {
|
|
struct intel_sdvo_dtd output_dtd;
|
|
@@ -1094,22 +1061,22 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder,
|
|
|
|
/* Set output timings */
|
|
intel_sdvo_get_dtd_from_mode(&output_dtd, mode);
|
|
- intel_sdvo_set_target_output(output,
|
|
- dev_priv->controlled_output);
|
|
- intel_sdvo_set_output_timing(output, &output_dtd);
|
|
+ intel_sdvo_set_target_output(intel_encoder,
|
|
+ dev_priv->attached_output);
|
|
+ intel_sdvo_set_output_timing(intel_encoder, &output_dtd);
|
|
|
|
/* Set the input timing to the screen. Assume always input 0. */
|
|
- intel_sdvo_set_target_input(output, true, false);
|
|
+ intel_sdvo_set_target_input(intel_encoder, true, false);
|
|
|
|
|
|
- success = intel_sdvo_create_preferred_input_timing(output,
|
|
+ success = intel_sdvo_create_preferred_input_timing(intel_encoder,
|
|
mode->clock / 10,
|
|
mode->hdisplay,
|
|
mode->vdisplay);
|
|
if (success) {
|
|
struct intel_sdvo_dtd input_dtd;
|
|
|
|
- intel_sdvo_get_preferred_input_timing(output,
|
|
+ intel_sdvo_get_preferred_input_timing(intel_encoder,
|
|
&input_dtd);
|
|
intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd);
|
|
dev_priv->sdvo_flags = input_dtd.part2.sdvo_flags;
|
|
@@ -1132,16 +1099,16 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder,
|
|
intel_sdvo_get_dtd_from_mode(&output_dtd,
|
|
dev_priv->sdvo_lvds_fixed_mode);
|
|
|
|
- intel_sdvo_set_target_output(output,
|
|
- dev_priv->controlled_output);
|
|
- intel_sdvo_set_output_timing(output, &output_dtd);
|
|
+ intel_sdvo_set_target_output(intel_encoder,
|
|
+ dev_priv->attached_output);
|
|
+ intel_sdvo_set_output_timing(intel_encoder, &output_dtd);
|
|
|
|
/* Set the input timing to the screen. Assume always input 0. */
|
|
- intel_sdvo_set_target_input(output, true, false);
|
|
+ intel_sdvo_set_target_input(intel_encoder, true, false);
|
|
|
|
|
|
success = intel_sdvo_create_preferred_input_timing(
|
|
- output,
|
|
+ intel_encoder,
|
|
mode->clock / 10,
|
|
mode->hdisplay,
|
|
mode->vdisplay);
|
|
@@ -1149,7 +1116,7 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder,
|
|
if (success) {
|
|
struct intel_sdvo_dtd input_dtd;
|
|
|
|
- intel_sdvo_get_preferred_input_timing(output,
|
|
+ intel_sdvo_get_preferred_input_timing(intel_encoder,
|
|
&input_dtd);
|
|
intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd);
|
|
dev_priv->sdvo_flags = input_dtd.part2.sdvo_flags;
|
|
@@ -1181,8 +1148,8 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
struct drm_crtc *crtc = encoder->crtc;
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
- struct intel_output *output = enc_to_intel_output(encoder);
|
|
- struct intel_sdvo_priv *sdvo_priv = output->dev_priv;
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
|
|
u32 sdvox = 0;
|
|
int sdvo_pixel_multiply;
|
|
struct intel_sdvo_in_out_map in_out;
|
|
@@ -1198,15 +1165,15 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
|
|
* channel on the motherboard. In a two-input device, the first input
|
|
* will be SDVOB and the second SDVOC.
|
|
*/
|
|
- in_out.in0 = sdvo_priv->controlled_output;
|
|
+ in_out.in0 = sdvo_priv->attached_output;
|
|
in_out.in1 = 0;
|
|
|
|
- intel_sdvo_write_cmd(output, SDVO_CMD_SET_IN_OUT_MAP,
|
|
+ intel_sdvo_write_cmd(intel_encoder, SDVO_CMD_SET_IN_OUT_MAP,
|
|
&in_out, sizeof(in_out));
|
|
- status = intel_sdvo_read_response(output, NULL, 0);
|
|
+ status = intel_sdvo_read_response(intel_encoder, NULL, 0);
|
|
|
|
if (sdvo_priv->is_hdmi) {
|
|
- intel_sdvo_set_avi_infoframe(output, mode);
|
|
+ intel_sdvo_set_avi_infoframe(intel_encoder, mode);
|
|
sdvox |= SDVO_AUDIO_ENABLE;
|
|
}
|
|
|
|
@@ -1223,16 +1190,16 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
|
|
*/
|
|
if (!sdvo_priv->is_tv && !sdvo_priv->is_lvds) {
|
|
/* Set the output timing to the screen */
|
|
- intel_sdvo_set_target_output(output,
|
|
- sdvo_priv->controlled_output);
|
|
- intel_sdvo_set_output_timing(output, &input_dtd);
|
|
+ intel_sdvo_set_target_output(intel_encoder,
|
|
+ sdvo_priv->attached_output);
|
|
+ intel_sdvo_set_output_timing(intel_encoder, &input_dtd);
|
|
}
|
|
|
|
/* Set the input timing to the screen. Assume always input 0. */
|
|
- intel_sdvo_set_target_input(output, true, false);
|
|
+ intel_sdvo_set_target_input(intel_encoder, true, false);
|
|
|
|
if (sdvo_priv->is_tv)
|
|
- intel_sdvo_set_tv_format(output);
|
|
+ intel_sdvo_set_tv_format(intel_encoder);
|
|
|
|
/* We would like to use intel_sdvo_create_preferred_input_timing() to
|
|
* provide the device with a timing it can support, if it supports that
|
|
@@ -1240,29 +1207,29 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
|
|
* output the preferred timing, and we don't support that currently.
|
|
*/
|
|
#if 0
|
|
- success = intel_sdvo_create_preferred_input_timing(output, clock,
|
|
+ success = intel_sdvo_create_preferred_input_timing(encoder, clock,
|
|
width, height);
|
|
if (success) {
|
|
struct intel_sdvo_dtd *input_dtd;
|
|
|
|
- intel_sdvo_get_preferred_input_timing(output, &input_dtd);
|
|
- intel_sdvo_set_input_timing(output, &input_dtd);
|
|
+ intel_sdvo_get_preferred_input_timing(encoder, &input_dtd);
|
|
+ intel_sdvo_set_input_timing(encoder, &input_dtd);
|
|
}
|
|
#else
|
|
- intel_sdvo_set_input_timing(output, &input_dtd);
|
|
+ intel_sdvo_set_input_timing(intel_encoder, &input_dtd);
|
|
#endif
|
|
|
|
switch (intel_sdvo_get_pixel_multiplier(mode)) {
|
|
case 1:
|
|
- intel_sdvo_set_clock_rate_mult(output,
|
|
+ intel_sdvo_set_clock_rate_mult(intel_encoder,
|
|
SDVO_CLOCK_RATE_MULT_1X);
|
|
break;
|
|
case 2:
|
|
- intel_sdvo_set_clock_rate_mult(output,
|
|
+ intel_sdvo_set_clock_rate_mult(intel_encoder,
|
|
SDVO_CLOCK_RATE_MULT_2X);
|
|
break;
|
|
case 4:
|
|
- intel_sdvo_set_clock_rate_mult(output,
|
|
+ intel_sdvo_set_clock_rate_mult(intel_encoder,
|
|
SDVO_CLOCK_RATE_MULT_4X);
|
|
break;
|
|
}
|
|
@@ -1273,8 +1240,8 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
|
|
SDVO_VSYNC_ACTIVE_HIGH |
|
|
SDVO_HSYNC_ACTIVE_HIGH;
|
|
} else {
|
|
- sdvox |= I915_READ(sdvo_priv->output_device);
|
|
- switch (sdvo_priv->output_device) {
|
|
+ sdvox |= I915_READ(sdvo_priv->sdvo_reg);
|
|
+ switch (sdvo_priv->sdvo_reg) {
|
|
case SDVOB:
|
|
sdvox &= SDVOB_PRESERVE_MASK;
|
|
break;
|
|
@@ -1298,26 +1265,26 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
|
|
|
|
if (sdvo_priv->sdvo_flags & SDVO_NEED_TO_STALL)
|
|
sdvox |= SDVO_STALL_SELECT;
|
|
- intel_sdvo_write_sdvox(output, sdvox);
|
|
+ intel_sdvo_write_sdvox(intel_encoder, sdvox);
|
|
}
|
|
|
|
static void intel_sdvo_dpms(struct drm_encoder *encoder, int mode)
|
|
{
|
|
struct drm_device *dev = encoder->dev;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
- struct intel_output *intel_output = enc_to_intel_output(encoder);
|
|
- struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
|
|
u32 temp;
|
|
|
|
if (mode != DRM_MODE_DPMS_ON) {
|
|
- intel_sdvo_set_active_outputs(intel_output, 0);
|
|
+ intel_sdvo_set_active_outputs(intel_encoder, 0);
|
|
if (0)
|
|
- intel_sdvo_set_encoder_power_state(intel_output, mode);
|
|
+ intel_sdvo_set_encoder_power_state(intel_encoder, mode);
|
|
|
|
if (mode == DRM_MODE_DPMS_OFF) {
|
|
- temp = I915_READ(sdvo_priv->output_device);
|
|
+ temp = I915_READ(sdvo_priv->sdvo_reg);
|
|
if ((temp & SDVO_ENABLE) != 0) {
|
|
- intel_sdvo_write_sdvox(intel_output, temp & ~SDVO_ENABLE);
|
|
+ intel_sdvo_write_sdvox(intel_encoder, temp & ~SDVO_ENABLE);
|
|
}
|
|
}
|
|
} else {
|
|
@@ -1325,13 +1292,13 @@ static void intel_sdvo_dpms(struct drm_encoder *encoder, int mode)
|
|
int i;
|
|
u8 status;
|
|
|
|
- temp = I915_READ(sdvo_priv->output_device);
|
|
+ temp = I915_READ(sdvo_priv->sdvo_reg);
|
|
if ((temp & SDVO_ENABLE) == 0)
|
|
- intel_sdvo_write_sdvox(intel_output, temp | SDVO_ENABLE);
|
|
+ intel_sdvo_write_sdvox(intel_encoder, temp | SDVO_ENABLE);
|
|
for (i = 0; i < 2; i++)
|
|
intel_wait_for_vblank(dev);
|
|
|
|
- status = intel_sdvo_get_trained_inputs(intel_output, &input1,
|
|
+ status = intel_sdvo_get_trained_inputs(intel_encoder, &input1,
|
|
&input2);
|
|
|
|
|
|
@@ -1345,109 +1312,18 @@ static void intel_sdvo_dpms(struct drm_encoder *encoder, int mode)
|
|
}
|
|
|
|
if (0)
|
|
- intel_sdvo_set_encoder_power_state(intel_output, mode);
|
|
- intel_sdvo_set_active_outputs(intel_output, sdvo_priv->controlled_output);
|
|
+ intel_sdvo_set_encoder_power_state(intel_encoder, mode);
|
|
+ intel_sdvo_set_active_outputs(intel_encoder, sdvo_priv->attached_output);
|
|
}
|
|
return;
|
|
}
|
|
|
|
-static void intel_sdvo_save(struct drm_connector *connector)
|
|
-{
|
|
- struct drm_device *dev = connector->dev;
|
|
- struct drm_i915_private *dev_priv = dev->dev_private;
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
- struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
|
|
- int o;
|
|
-
|
|
- sdvo_priv->save_sdvo_mult = intel_sdvo_get_clock_rate_mult(intel_output);
|
|
- intel_sdvo_get_active_outputs(intel_output, &sdvo_priv->save_active_outputs);
|
|
-
|
|
- if (sdvo_priv->caps.sdvo_inputs_mask & 0x1) {
|
|
- intel_sdvo_set_target_input(intel_output, true, false);
|
|
- intel_sdvo_get_input_timing(intel_output,
|
|
- &sdvo_priv->save_input_dtd_1);
|
|
- }
|
|
-
|
|
- if (sdvo_priv->caps.sdvo_inputs_mask & 0x2) {
|
|
- intel_sdvo_set_target_input(intel_output, false, true);
|
|
- intel_sdvo_get_input_timing(intel_output,
|
|
- &sdvo_priv->save_input_dtd_2);
|
|
- }
|
|
-
|
|
- for (o = SDVO_OUTPUT_FIRST; o <= SDVO_OUTPUT_LAST; o++)
|
|
- {
|
|
- u16 this_output = (1 << o);
|
|
- if (sdvo_priv->caps.output_flags & this_output)
|
|
- {
|
|
- intel_sdvo_set_target_output(intel_output, this_output);
|
|
- intel_sdvo_get_output_timing(intel_output,
|
|
- &sdvo_priv->save_output_dtd[o]);
|
|
- }
|
|
- }
|
|
- if (sdvo_priv->is_tv) {
|
|
- /* XXX: Save TV format/enhancements. */
|
|
- }
|
|
-
|
|
- sdvo_priv->save_SDVOX = I915_READ(sdvo_priv->output_device);
|
|
-}
|
|
-
|
|
-static void intel_sdvo_restore(struct drm_connector *connector)
|
|
-{
|
|
- struct drm_device *dev = connector->dev;
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
- struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
|
|
- int o;
|
|
- int i;
|
|
- bool input1, input2;
|
|
- u8 status;
|
|
-
|
|
- intel_sdvo_set_active_outputs(intel_output, 0);
|
|
-
|
|
- for (o = SDVO_OUTPUT_FIRST; o <= SDVO_OUTPUT_LAST; o++)
|
|
- {
|
|
- u16 this_output = (1 << o);
|
|
- if (sdvo_priv->caps.output_flags & this_output) {
|
|
- intel_sdvo_set_target_output(intel_output, this_output);
|
|
- intel_sdvo_set_output_timing(intel_output, &sdvo_priv->save_output_dtd[o]);
|
|
- }
|
|
- }
|
|
-
|
|
- if (sdvo_priv->caps.sdvo_inputs_mask & 0x1) {
|
|
- intel_sdvo_set_target_input(intel_output, true, false);
|
|
- intel_sdvo_set_input_timing(intel_output, &sdvo_priv->save_input_dtd_1);
|
|
- }
|
|
-
|
|
- if (sdvo_priv->caps.sdvo_inputs_mask & 0x2) {
|
|
- intel_sdvo_set_target_input(intel_output, false, true);
|
|
- intel_sdvo_set_input_timing(intel_output, &sdvo_priv->save_input_dtd_2);
|
|
- }
|
|
-
|
|
- intel_sdvo_set_clock_rate_mult(intel_output, sdvo_priv->save_sdvo_mult);
|
|
-
|
|
- if (sdvo_priv->is_tv) {
|
|
- /* XXX: Restore TV format/enhancements. */
|
|
- }
|
|
-
|
|
- intel_sdvo_write_sdvox(intel_output, sdvo_priv->save_SDVOX);
|
|
-
|
|
- if (sdvo_priv->save_SDVOX & SDVO_ENABLE)
|
|
- {
|
|
- for (i = 0; i < 2; i++)
|
|
- intel_wait_for_vblank(dev);
|
|
- status = intel_sdvo_get_trained_inputs(intel_output, &input1, &input2);
|
|
- if (status == SDVO_CMD_STATUS_SUCCESS && !input1)
|
|
- DRM_DEBUG_KMS("First %s output reported failure to "
|
|
- "sync\n", SDVO_NAME(sdvo_priv));
|
|
- }
|
|
-
|
|
- intel_sdvo_set_active_outputs(intel_output, sdvo_priv->save_active_outputs);
|
|
-}
|
|
-
|
|
static int intel_sdvo_mode_valid(struct drm_connector *connector,
|
|
struct drm_display_mode *mode)
|
|
{
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
- struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
|
|
+ struct drm_encoder *encoder = intel_attached_encoder(connector);
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
|
|
|
|
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
|
|
return MODE_NO_DBLESCAN;
|
|
@@ -1472,37 +1348,39 @@ static int intel_sdvo_mode_valid(struct drm_connector *connector,
|
|
return MODE_OK;
|
|
}
|
|
|
|
-static bool intel_sdvo_get_capabilities(struct intel_output *intel_output, struct intel_sdvo_caps *caps)
|
|
+static bool intel_sdvo_get_capabilities(struct intel_encoder *intel_encoder, struct intel_sdvo_caps *caps)
|
|
{
|
|
u8 status;
|
|
|
|
- intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_DEVICE_CAPS, NULL, 0);
|
|
- status = intel_sdvo_read_response(intel_output, caps, sizeof(*caps));
|
|
+ intel_sdvo_write_cmd(intel_encoder, SDVO_CMD_GET_DEVICE_CAPS, NULL, 0);
|
|
+ status = intel_sdvo_read_response(intel_encoder, caps, sizeof(*caps));
|
|
if (status != SDVO_CMD_STATUS_SUCCESS)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
+/* No use! */
|
|
+#if 0
|
|
struct drm_connector* intel_sdvo_find(struct drm_device *dev, int sdvoB)
|
|
{
|
|
struct drm_connector *connector = NULL;
|
|
- struct intel_output *iout = NULL;
|
|
+ struct intel_encoder *iout = NULL;
|
|
struct intel_sdvo_priv *sdvo;
|
|
|
|
/* find the sdvo connector */
|
|
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
|
- iout = to_intel_output(connector);
|
|
+ iout = to_intel_encoder(connector);
|
|
|
|
if (iout->type != INTEL_OUTPUT_SDVO)
|
|
continue;
|
|
|
|
sdvo = iout->dev_priv;
|
|
|
|
- if (sdvo->output_device == SDVOB && sdvoB)
|
|
+ if (sdvo->sdvo_reg == SDVOB && sdvoB)
|
|
return connector;
|
|
|
|
- if (sdvo->output_device == SDVOC && !sdvoB)
|
|
+ if (sdvo->sdvo_reg == SDVOC && !sdvoB)
|
|
return connector;
|
|
|
|
}
|
|
@@ -1514,16 +1392,16 @@ int intel_sdvo_supports_hotplug(struct drm_connector *connector)
|
|
{
|
|
u8 response[2];
|
|
u8 status;
|
|
- struct intel_output *intel_output;
|
|
+ struct intel_encoder *intel_encoder;
|
|
DRM_DEBUG_KMS("\n");
|
|
|
|
if (!connector)
|
|
return 0;
|
|
|
|
- intel_output = to_intel_output(connector);
|
|
+ intel_encoder = to_intel_encoder(connector);
|
|
|
|
- intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_HOT_PLUG_SUPPORT, NULL, 0);
|
|
- status = intel_sdvo_read_response(intel_output, &response, 2);
|
|
+ intel_sdvo_write_cmd(intel_encoder, SDVO_CMD_GET_HOT_PLUG_SUPPORT, NULL, 0);
|
|
+ status = intel_sdvo_read_response(intel_encoder, &response, 2);
|
|
|
|
if (response[0] !=0)
|
|
return 1;
|
|
@@ -1535,30 +1413,31 @@ void intel_sdvo_set_hotplug(struct drm_connector *connector, int on)
|
|
{
|
|
u8 response[2];
|
|
u8 status;
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
+ struct intel_encoder *intel_encoder = to_intel_encoder(connector);
|
|
|
|
- intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_ACTIVE_HOT_PLUG, NULL, 0);
|
|
- intel_sdvo_read_response(intel_output, &response, 2);
|
|
+ intel_sdvo_write_cmd(intel_encoder, SDVO_CMD_GET_ACTIVE_HOT_PLUG, NULL, 0);
|
|
+ intel_sdvo_read_response(intel_encoder, &response, 2);
|
|
|
|
if (on) {
|
|
- intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_HOT_PLUG_SUPPORT, NULL, 0);
|
|
- status = intel_sdvo_read_response(intel_output, &response, 2);
|
|
+ intel_sdvo_write_cmd(intel_encoder, SDVO_CMD_GET_HOT_PLUG_SUPPORT, NULL, 0);
|
|
+ status = intel_sdvo_read_response(intel_encoder, &response, 2);
|
|
|
|
- intel_sdvo_write_cmd(intel_output, SDVO_CMD_SET_ACTIVE_HOT_PLUG, &response, 2);
|
|
+ intel_sdvo_write_cmd(intel_encoder, SDVO_CMD_SET_ACTIVE_HOT_PLUG, &response, 2);
|
|
} else {
|
|
response[0] = 0;
|
|
response[1] = 0;
|
|
- intel_sdvo_write_cmd(intel_output, SDVO_CMD_SET_ACTIVE_HOT_PLUG, &response, 2);
|
|
+ intel_sdvo_write_cmd(intel_encoder, SDVO_CMD_SET_ACTIVE_HOT_PLUG, &response, 2);
|
|
}
|
|
|
|
- intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_ACTIVE_HOT_PLUG, NULL, 0);
|
|
- intel_sdvo_read_response(intel_output, &response, 2);
|
|
+ intel_sdvo_write_cmd(intel_encoder, SDVO_CMD_GET_ACTIVE_HOT_PLUG, NULL, 0);
|
|
+ intel_sdvo_read_response(intel_encoder, &response, 2);
|
|
}
|
|
+#endif
|
|
|
|
static bool
|
|
-intel_sdvo_multifunc_encoder(struct intel_output *intel_output)
|
|
+intel_sdvo_multifunc_encoder(struct intel_encoder *intel_encoder)
|
|
{
|
|
- struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
|
|
+ struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
|
|
int caps = 0;
|
|
|
|
if (sdvo_priv->caps.output_flags &
|
|
@@ -1592,12 +1471,17 @@ static struct drm_connector *
|
|
intel_find_analog_connector(struct drm_device *dev)
|
|
{
|
|
struct drm_connector *connector;
|
|
- struct intel_output *intel_output;
|
|
-
|
|
- list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
|
- intel_output = to_intel_output(connector);
|
|
- if (intel_output->type == INTEL_OUTPUT_ANALOG)
|
|
- return connector;
|
|
+ struct drm_encoder *encoder;
|
|
+ struct intel_encoder *intel_encoder;
|
|
+
|
|
+ list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
|
+ intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ if (intel_encoder->type == INTEL_OUTPUT_ANALOG) {
|
|
+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
|
+ if (connector && encoder == intel_attached_encoder(connector))
|
|
+ return connector;
|
|
+ }
|
|
+ }
|
|
}
|
|
return NULL;
|
|
}
|
|
@@ -1621,16 +1505,17 @@ intel_analog_is_connected(struct drm_device *dev)
|
|
enum drm_connector_status
|
|
intel_sdvo_hdmi_sink_detect(struct drm_connector *connector, u16 response)
|
|
{
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
- struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
|
|
+ struct drm_encoder *encoder = intel_attached_encoder(connector);
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
|
|
enum drm_connector_status status = connector_status_connected;
|
|
struct edid *edid = NULL;
|
|
|
|
- edid = drm_get_edid(&intel_output->base,
|
|
- intel_output->ddc_bus);
|
|
+ edid = drm_get_edid(connector,
|
|
+ intel_encoder->ddc_bus);
|
|
|
|
/* This is only applied to SDVO cards with multiple outputs */
|
|
- if (edid == NULL && intel_sdvo_multifunc_encoder(intel_output)) {
|
|
+ if (edid == NULL && intel_sdvo_multifunc_encoder(intel_encoder)) {
|
|
uint8_t saved_ddc, temp_ddc;
|
|
saved_ddc = sdvo_priv->ddc_bus;
|
|
temp_ddc = sdvo_priv->ddc_bus >> 1;
|
|
@@ -1640,8 +1525,8 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector, u16 response)
|
|
*/
|
|
while(temp_ddc > 1) {
|
|
sdvo_priv->ddc_bus = temp_ddc;
|
|
- edid = drm_get_edid(&intel_output->base,
|
|
- intel_output->ddc_bus);
|
|
+ edid = drm_get_edid(connector,
|
|
+ intel_encoder->ddc_bus);
|
|
if (edid) {
|
|
/*
|
|
* When we can get the EDID, maybe it is the
|
|
@@ -1660,8 +1545,8 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector, u16 response)
|
|
*/
|
|
if (edid == NULL &&
|
|
sdvo_priv->analog_ddc_bus &&
|
|
- !intel_analog_is_connected(intel_output->base.dev))
|
|
- edid = drm_get_edid(&intel_output->base,
|
|
+ !intel_analog_is_connected(connector->dev))
|
|
+ edid = drm_get_edid(connector,
|
|
sdvo_priv->analog_ddc_bus);
|
|
if (edid != NULL) {
|
|
/* Don't report the output as connected if it's a DVI-I
|
|
@@ -1676,7 +1561,7 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector, u16 response)
|
|
}
|
|
|
|
kfree(edid);
|
|
- intel_output->base.display_info.raw_edid = NULL;
|
|
+ connector->display_info.raw_edid = NULL;
|
|
|
|
} else if (response & (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1))
|
|
status = connector_status_disconnected;
|
|
@@ -1688,16 +1573,20 @@ static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connect
|
|
{
|
|
uint16_t response;
|
|
u8 status;
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
- struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
|
|
-
|
|
- intel_sdvo_write_cmd(intel_output,
|
|
+ struct drm_encoder *encoder = intel_attached_encoder(connector);
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ struct intel_connector *intel_connector = to_intel_connector(connector);
|
|
+ struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
|
|
+ struct intel_sdvo_connector *sdvo_connector = intel_connector->dev_priv;
|
|
+ enum drm_connector_status ret;
|
|
+
|
|
+ intel_sdvo_write_cmd(intel_encoder,
|
|
SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0);
|
|
if (sdvo_priv->is_tv) {
|
|
/* add 30ms delay when the output type is SDVO-TV */
|
|
mdelay(30);
|
|
}
|
|
- status = intel_sdvo_read_response(intel_output, &response, 2);
|
|
+ status = intel_sdvo_read_response(intel_encoder, &response, 2);
|
|
|
|
DRM_DEBUG_KMS("SDVO response %d %d\n", response & 0xff, response >> 8);
|
|
|
|
@@ -1707,24 +1596,41 @@ static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connect
|
|
if (response == 0)
|
|
return connector_status_disconnected;
|
|
|
|
- if (intel_sdvo_multifunc_encoder(intel_output) &&
|
|
- sdvo_priv->attached_output != response) {
|
|
- if (sdvo_priv->controlled_output != response &&
|
|
- intel_sdvo_output_setup(intel_output, response) != true)
|
|
- return connector_status_unknown;
|
|
- sdvo_priv->attached_output = response;
|
|
+ sdvo_priv->attached_output = response;
|
|
+
|
|
+ if ((sdvo_connector->output_flag & response) == 0)
|
|
+ ret = connector_status_disconnected;
|
|
+ else if (response & (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1))
|
|
+ ret = intel_sdvo_hdmi_sink_detect(connector, response);
|
|
+ else
|
|
+ ret = connector_status_connected;
|
|
+
|
|
+ /* May update encoder flag for like clock for SDVO TV, etc.*/
|
|
+ if (ret == connector_status_connected) {
|
|
+ sdvo_priv->is_tv = false;
|
|
+ sdvo_priv->is_lvds = false;
|
|
+ intel_encoder->needs_tv_clock = false;
|
|
+
|
|
+ if (response & SDVO_TV_MASK) {
|
|
+ sdvo_priv->is_tv = true;
|
|
+ intel_encoder->needs_tv_clock = true;
|
|
+ }
|
|
+ if (response & SDVO_LVDS_MASK)
|
|
+ sdvo_priv->is_lvds = true;
|
|
}
|
|
- return intel_sdvo_hdmi_sink_detect(connector, response);
|
|
+
|
|
+ return ret;
|
|
}
|
|
|
|
static void intel_sdvo_get_ddc_modes(struct drm_connector *connector)
|
|
{
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
- struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
|
|
+ struct drm_encoder *encoder = intel_attached_encoder(connector);
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
|
|
int num_modes;
|
|
|
|
/* set the bus switch and get the modes */
|
|
- num_modes = intel_ddc_get_modes(intel_output);
|
|
+ num_modes = intel_ddc_get_modes(connector, intel_encoder->ddc_bus);
|
|
|
|
/*
|
|
* Mac mini hack. On this device, the DVI-I connector shares one DDC
|
|
@@ -1734,17 +1640,10 @@ static void intel_sdvo_get_ddc_modes(struct drm_connector *connector)
|
|
*/
|
|
if (num_modes == 0 &&
|
|
sdvo_priv->analog_ddc_bus &&
|
|
- !intel_analog_is_connected(intel_output->base.dev)) {
|
|
- struct i2c_adapter *digital_ddc_bus;
|
|
-
|
|
+ !intel_analog_is_connected(connector->dev)) {
|
|
/* Switch to the analog ddc bus and try that
|
|
*/
|
|
- digital_ddc_bus = intel_output->ddc_bus;
|
|
- intel_output->ddc_bus = sdvo_priv->analog_ddc_bus;
|
|
-
|
|
- (void) intel_ddc_get_modes(intel_output);
|
|
-
|
|
- intel_output->ddc_bus = digital_ddc_bus;
|
|
+ (void) intel_ddc_get_modes(connector, sdvo_priv->analog_ddc_bus);
|
|
}
|
|
}
|
|
|
|
@@ -1815,8 +1714,9 @@ struct drm_display_mode sdvo_tv_modes[] = {
|
|
|
|
static void intel_sdvo_get_tv_modes(struct drm_connector *connector)
|
|
{
|
|
- struct intel_output *output = to_intel_output(connector);
|
|
- struct intel_sdvo_priv *sdvo_priv = output->dev_priv;
|
|
+ struct drm_encoder *encoder = intel_attached_encoder(connector);
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
|
|
struct intel_sdvo_sdtv_resolution_request tv_res;
|
|
uint32_t reply = 0, format_map = 0;
|
|
int i;
|
|
@@ -1836,11 +1736,11 @@ static void intel_sdvo_get_tv_modes(struct drm_connector *connector)
|
|
sizeof(format_map) ? sizeof(format_map) :
|
|
sizeof(struct intel_sdvo_sdtv_resolution_request));
|
|
|
|
- intel_sdvo_set_target_output(output, sdvo_priv->controlled_output);
|
|
+ intel_sdvo_set_target_output(intel_encoder, sdvo_priv->attached_output);
|
|
|
|
- intel_sdvo_write_cmd(output, SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT,
|
|
+ intel_sdvo_write_cmd(intel_encoder, SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT,
|
|
&tv_res, sizeof(tv_res));
|
|
- status = intel_sdvo_read_response(output, &reply, 3);
|
|
+ status = intel_sdvo_read_response(intel_encoder, &reply, 3);
|
|
if (status != SDVO_CMD_STATUS_SUCCESS)
|
|
return;
|
|
|
|
@@ -1857,9 +1757,10 @@ static void intel_sdvo_get_tv_modes(struct drm_connector *connector)
|
|
|
|
static void intel_sdvo_get_lvds_modes(struct drm_connector *connector)
|
|
{
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
+ struct drm_encoder *encoder = intel_attached_encoder(connector);
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
struct drm_i915_private *dev_priv = connector->dev->dev_private;
|
|
- struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
|
|
+ struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
|
|
struct drm_display_mode *newmode;
|
|
|
|
/*
|
|
@@ -1867,7 +1768,7 @@ static void intel_sdvo_get_lvds_modes(struct drm_connector *connector)
|
|
* Assume that the preferred modes are
|
|
* arranged in priority order.
|
|
*/
|
|
- intel_ddc_get_modes(intel_output);
|
|
+ intel_ddc_get_modes(connector, intel_encoder->ddc_bus);
|
|
if (list_empty(&connector->probed_modes) == false)
|
|
goto end;
|
|
|
|
@@ -1896,12 +1797,12 @@ end:
|
|
|
|
static int intel_sdvo_get_modes(struct drm_connector *connector)
|
|
{
|
|
- struct intel_output *output = to_intel_output(connector);
|
|
- struct intel_sdvo_priv *sdvo_priv = output->dev_priv;
|
|
+ struct intel_connector *intel_connector = to_intel_connector(connector);
|
|
+ struct intel_sdvo_connector *sdvo_connector = intel_connector->dev_priv;
|
|
|
|
- if (sdvo_priv->is_tv)
|
|
+ if (IS_TV(sdvo_connector))
|
|
intel_sdvo_get_tv_modes(connector);
|
|
- else if (sdvo_priv->is_lvds == true)
|
|
+ else if (IS_LVDS(sdvo_connector))
|
|
intel_sdvo_get_lvds_modes(connector);
|
|
else
|
|
intel_sdvo_get_ddc_modes(connector);
|
|
@@ -1914,11 +1815,11 @@ static int intel_sdvo_get_modes(struct drm_connector *connector)
|
|
static
|
|
void intel_sdvo_destroy_enhance_property(struct drm_connector *connector)
|
|
{
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
- struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
|
|
+ struct intel_connector *intel_connector = to_intel_connector(connector);
|
|
+ struct intel_sdvo_connector *sdvo_priv = intel_connector->dev_priv;
|
|
struct drm_device *dev = connector->dev;
|
|
|
|
- if (sdvo_priv->is_tv) {
|
|
+ if (IS_TV(sdvo_priv)) {
|
|
if (sdvo_priv->left_property)
|
|
drm_property_destroy(dev, sdvo_priv->left_property);
|
|
if (sdvo_priv->right_property)
|
|
@@ -1931,8 +1832,6 @@ void intel_sdvo_destroy_enhance_property(struct drm_connector *connector)
|
|
drm_property_destroy(dev, sdvo_priv->hpos_property);
|
|
if (sdvo_priv->vpos_property)
|
|
drm_property_destroy(dev, sdvo_priv->vpos_property);
|
|
- }
|
|
- if (sdvo_priv->is_tv) {
|
|
if (sdvo_priv->saturation_property)
|
|
drm_property_destroy(dev,
|
|
sdvo_priv->saturation_property);
|
|
@@ -1942,7 +1841,7 @@ void intel_sdvo_destroy_enhance_property(struct drm_connector *connector)
|
|
if (sdvo_priv->hue_property)
|
|
drm_property_destroy(dev, sdvo_priv->hue_property);
|
|
}
|
|
- if (sdvo_priv->is_tv || sdvo_priv->is_lvds) {
|
|
+ if (IS_TV(sdvo_priv) || IS_LVDS(sdvo_priv)) {
|
|
if (sdvo_priv->brightness_property)
|
|
drm_property_destroy(dev,
|
|
sdvo_priv->brightness_property);
|
|
@@ -1952,31 +1851,17 @@ void intel_sdvo_destroy_enhance_property(struct drm_connector *connector)
|
|
|
|
static void intel_sdvo_destroy(struct drm_connector *connector)
|
|
{
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
- struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
|
|
-
|
|
- if (intel_output->i2c_bus)
|
|
- intel_i2c_destroy(intel_output->i2c_bus);
|
|
- if (intel_output->ddc_bus)
|
|
- intel_i2c_destroy(intel_output->ddc_bus);
|
|
- if (sdvo_priv->analog_ddc_bus)
|
|
- intel_i2c_destroy(sdvo_priv->analog_ddc_bus);
|
|
+ struct intel_connector *intel_connector = to_intel_connector(connector);
|
|
+ struct intel_sdvo_connector *sdvo_connector = intel_connector->dev_priv;
|
|
|
|
- if (sdvo_priv->sdvo_lvds_fixed_mode != NULL)
|
|
- drm_mode_destroy(connector->dev,
|
|
- sdvo_priv->sdvo_lvds_fixed_mode);
|
|
-
|
|
- if (sdvo_priv->tv_format_property)
|
|
+ if (sdvo_connector->tv_format_property)
|
|
drm_property_destroy(connector->dev,
|
|
- sdvo_priv->tv_format_property);
|
|
-
|
|
- if (sdvo_priv->is_tv || sdvo_priv->is_lvds)
|
|
- intel_sdvo_destroy_enhance_property(connector);
|
|
+ sdvo_connector->tv_format_property);
|
|
|
|
+ intel_sdvo_destroy_enhance_property(connector);
|
|
drm_sysfs_connector_remove(connector);
|
|
drm_connector_cleanup(connector);
|
|
-
|
|
- kfree(intel_output);
|
|
+ kfree(connector);
|
|
}
|
|
|
|
static int
|
|
@@ -1984,9 +1869,11 @@ intel_sdvo_set_property(struct drm_connector *connector,
|
|
struct drm_property *property,
|
|
uint64_t val)
|
|
{
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
- struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
|
|
- struct drm_encoder *encoder = &intel_output->enc;
|
|
+ struct drm_encoder *encoder = intel_attached_encoder(connector);
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
|
|
+ struct intel_connector *intel_connector = to_intel_connector(connector);
|
|
+ struct intel_sdvo_connector *sdvo_connector = intel_connector->dev_priv;
|
|
struct drm_crtc *crtc = encoder->crtc;
|
|
int ret = 0;
|
|
bool changed = false;
|
|
@@ -1997,105 +1884,105 @@ intel_sdvo_set_property(struct drm_connector *connector,
|
|
if (ret < 0)
|
|
goto out;
|
|
|
|
- if (property == sdvo_priv->tv_format_property) {
|
|
+ if (property == sdvo_connector->tv_format_property) {
|
|
if (val >= TV_FORMAT_NUM) {
|
|
ret = -EINVAL;
|
|
goto out;
|
|
}
|
|
if (sdvo_priv->tv_format_name ==
|
|
- sdvo_priv->tv_format_supported[val])
|
|
+ sdvo_connector->tv_format_supported[val])
|
|
goto out;
|
|
|
|
- sdvo_priv->tv_format_name = sdvo_priv->tv_format_supported[val];
|
|
+ sdvo_priv->tv_format_name = sdvo_connector->tv_format_supported[val];
|
|
changed = true;
|
|
}
|
|
|
|
- if (sdvo_priv->is_tv || sdvo_priv->is_lvds) {
|
|
+ if (IS_TV(sdvo_connector) || IS_LVDS(sdvo_connector)) {
|
|
cmd = 0;
|
|
temp_value = val;
|
|
- if (sdvo_priv->left_property == property) {
|
|
+ if (sdvo_connector->left_property == property) {
|
|
drm_connector_property_set_value(connector,
|
|
- sdvo_priv->right_property, val);
|
|
- if (sdvo_priv->left_margin == temp_value)
|
|
+ sdvo_connector->right_property, val);
|
|
+ if (sdvo_connector->left_margin == temp_value)
|
|
goto out;
|
|
|
|
- sdvo_priv->left_margin = temp_value;
|
|
- sdvo_priv->right_margin = temp_value;
|
|
- temp_value = sdvo_priv->max_hscan -
|
|
- sdvo_priv->left_margin;
|
|
+ sdvo_connector->left_margin = temp_value;
|
|
+ sdvo_connector->right_margin = temp_value;
|
|
+ temp_value = sdvo_connector->max_hscan -
|
|
+ sdvo_connector->left_margin;
|
|
cmd = SDVO_CMD_SET_OVERSCAN_H;
|
|
- } else if (sdvo_priv->right_property == property) {
|
|
+ } else if (sdvo_connector->right_property == property) {
|
|
drm_connector_property_set_value(connector,
|
|
- sdvo_priv->left_property, val);
|
|
- if (sdvo_priv->right_margin == temp_value)
|
|
+ sdvo_connector->left_property, val);
|
|
+ if (sdvo_connector->right_margin == temp_value)
|
|
goto out;
|
|
|
|
- sdvo_priv->left_margin = temp_value;
|
|
- sdvo_priv->right_margin = temp_value;
|
|
- temp_value = sdvo_priv->max_hscan -
|
|
- sdvo_priv->left_margin;
|
|
+ sdvo_connector->left_margin = temp_value;
|
|
+ sdvo_connector->right_margin = temp_value;
|
|
+ temp_value = sdvo_connector->max_hscan -
|
|
+ sdvo_connector->left_margin;
|
|
cmd = SDVO_CMD_SET_OVERSCAN_H;
|
|
- } else if (sdvo_priv->top_property == property) {
|
|
+ } else if (sdvo_connector->top_property == property) {
|
|
drm_connector_property_set_value(connector,
|
|
- sdvo_priv->bottom_property, val);
|
|
- if (sdvo_priv->top_margin == temp_value)
|
|
+ sdvo_connector->bottom_property, val);
|
|
+ if (sdvo_connector->top_margin == temp_value)
|
|
goto out;
|
|
|
|
- sdvo_priv->top_margin = temp_value;
|
|
- sdvo_priv->bottom_margin = temp_value;
|
|
- temp_value = sdvo_priv->max_vscan -
|
|
- sdvo_priv->top_margin;
|
|
+ sdvo_connector->top_margin = temp_value;
|
|
+ sdvo_connector->bottom_margin = temp_value;
|
|
+ temp_value = sdvo_connector->max_vscan -
|
|
+ sdvo_connector->top_margin;
|
|
cmd = SDVO_CMD_SET_OVERSCAN_V;
|
|
- } else if (sdvo_priv->bottom_property == property) {
|
|
+ } else if (sdvo_connector->bottom_property == property) {
|
|
drm_connector_property_set_value(connector,
|
|
- sdvo_priv->top_property, val);
|
|
- if (sdvo_priv->bottom_margin == temp_value)
|
|
+ sdvo_connector->top_property, val);
|
|
+ if (sdvo_connector->bottom_margin == temp_value)
|
|
goto out;
|
|
- sdvo_priv->top_margin = temp_value;
|
|
- sdvo_priv->bottom_margin = temp_value;
|
|
- temp_value = sdvo_priv->max_vscan -
|
|
- sdvo_priv->top_margin;
|
|
+ sdvo_connector->top_margin = temp_value;
|
|
+ sdvo_connector->bottom_margin = temp_value;
|
|
+ temp_value = sdvo_connector->max_vscan -
|
|
+ sdvo_connector->top_margin;
|
|
cmd = SDVO_CMD_SET_OVERSCAN_V;
|
|
- } else if (sdvo_priv->hpos_property == property) {
|
|
- if (sdvo_priv->cur_hpos == temp_value)
|
|
+ } else if (sdvo_connector->hpos_property == property) {
|
|
+ if (sdvo_connector->cur_hpos == temp_value)
|
|
goto out;
|
|
|
|
cmd = SDVO_CMD_SET_POSITION_H;
|
|
- sdvo_priv->cur_hpos = temp_value;
|
|
- } else if (sdvo_priv->vpos_property == property) {
|
|
- if (sdvo_priv->cur_vpos == temp_value)
|
|
+ sdvo_connector->cur_hpos = temp_value;
|
|
+ } else if (sdvo_connector->vpos_property == property) {
|
|
+ if (sdvo_connector->cur_vpos == temp_value)
|
|
goto out;
|
|
|
|
cmd = SDVO_CMD_SET_POSITION_V;
|
|
- sdvo_priv->cur_vpos = temp_value;
|
|
- } else if (sdvo_priv->saturation_property == property) {
|
|
- if (sdvo_priv->cur_saturation == temp_value)
|
|
+ sdvo_connector->cur_vpos = temp_value;
|
|
+ } else if (sdvo_connector->saturation_property == property) {
|
|
+ if (sdvo_connector->cur_saturation == temp_value)
|
|
goto out;
|
|
|
|
cmd = SDVO_CMD_SET_SATURATION;
|
|
- sdvo_priv->cur_saturation = temp_value;
|
|
- } else if (sdvo_priv->contrast_property == property) {
|
|
- if (sdvo_priv->cur_contrast == temp_value)
|
|
+ sdvo_connector->cur_saturation = temp_value;
|
|
+ } else if (sdvo_connector->contrast_property == property) {
|
|
+ if (sdvo_connector->cur_contrast == temp_value)
|
|
goto out;
|
|
|
|
cmd = SDVO_CMD_SET_CONTRAST;
|
|
- sdvo_priv->cur_contrast = temp_value;
|
|
- } else if (sdvo_priv->hue_property == property) {
|
|
- if (sdvo_priv->cur_hue == temp_value)
|
|
+ sdvo_connector->cur_contrast = temp_value;
|
|
+ } else if (sdvo_connector->hue_property == property) {
|
|
+ if (sdvo_connector->cur_hue == temp_value)
|
|
goto out;
|
|
|
|
cmd = SDVO_CMD_SET_HUE;
|
|
- sdvo_priv->cur_hue = temp_value;
|
|
- } else if (sdvo_priv->brightness_property == property) {
|
|
- if (sdvo_priv->cur_brightness == temp_value)
|
|
+ sdvo_connector->cur_hue = temp_value;
|
|
+ } else if (sdvo_connector->brightness_property == property) {
|
|
+ if (sdvo_connector->cur_brightness == temp_value)
|
|
goto out;
|
|
|
|
cmd = SDVO_CMD_SET_BRIGHTNESS;
|
|
- sdvo_priv->cur_brightness = temp_value;
|
|
+ sdvo_connector->cur_brightness = temp_value;
|
|
}
|
|
if (cmd) {
|
|
- intel_sdvo_write_cmd(intel_output, cmd, &temp_value, 2);
|
|
- status = intel_sdvo_read_response(intel_output,
|
|
+ intel_sdvo_write_cmd(intel_encoder, cmd, &temp_value, 2);
|
|
+ status = intel_sdvo_read_response(intel_encoder,
|
|
NULL, 0);
|
|
if (status != SDVO_CMD_STATUS_SUCCESS) {
|
|
DRM_DEBUG_KMS("Incorrect SDVO command \n");
|
|
@@ -2121,8 +2008,6 @@ static const struct drm_encoder_helper_funcs intel_sdvo_helper_funcs = {
|
|
|
|
static const struct drm_connector_funcs intel_sdvo_connector_funcs = {
|
|
.dpms = drm_helper_connector_dpms,
|
|
- .save = intel_sdvo_save,
|
|
- .restore = intel_sdvo_restore,
|
|
.detect = intel_sdvo_detect,
|
|
.fill_modes = drm_helper_probe_single_connector_modes,
|
|
.set_property = intel_sdvo_set_property,
|
|
@@ -2132,12 +2017,27 @@ static const struct drm_connector_funcs intel_sdvo_connector_funcs = {
|
|
static const struct drm_connector_helper_funcs intel_sdvo_connector_helper_funcs = {
|
|
.get_modes = intel_sdvo_get_modes,
|
|
.mode_valid = intel_sdvo_mode_valid,
|
|
- .best_encoder = intel_best_encoder,
|
|
+ .best_encoder = intel_attached_encoder,
|
|
};
|
|
|
|
static void intel_sdvo_enc_destroy(struct drm_encoder *encoder)
|
|
{
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
|
|
+
|
|
+ if (intel_encoder->i2c_bus)
|
|
+ intel_i2c_destroy(intel_encoder->i2c_bus);
|
|
+ if (intel_encoder->ddc_bus)
|
|
+ intel_i2c_destroy(intel_encoder->ddc_bus);
|
|
+ if (sdvo_priv->analog_ddc_bus)
|
|
+ intel_i2c_destroy(sdvo_priv->analog_ddc_bus);
|
|
+
|
|
+ if (sdvo_priv->sdvo_lvds_fixed_mode != NULL)
|
|
+ drm_mode_destroy(encoder->dev,
|
|
+ sdvo_priv->sdvo_lvds_fixed_mode);
|
|
+
|
|
drm_encoder_cleanup(encoder);
|
|
+ kfree(intel_encoder);
|
|
}
|
|
|
|
static const struct drm_encoder_funcs intel_sdvo_enc_funcs = {
|
|
@@ -2190,12 +2090,15 @@ intel_sdvo_select_ddc_bus(struct intel_sdvo_priv *dev_priv)
|
|
}
|
|
|
|
static bool
|
|
-intel_sdvo_get_digital_encoding_mode(struct intel_output *output)
|
|
+intel_sdvo_get_digital_encoding_mode(struct intel_encoder *output, int device)
|
|
{
|
|
struct intel_sdvo_priv *sdvo_priv = output->dev_priv;
|
|
uint8_t status;
|
|
|
|
- intel_sdvo_set_target_output(output, sdvo_priv->controlled_output);
|
|
+ if (device == 0)
|
|
+ intel_sdvo_set_target_output(output, SDVO_OUTPUT_TMDS0);
|
|
+ else
|
|
+ intel_sdvo_set_target_output(output, SDVO_OUTPUT_TMDS1);
|
|
|
|
intel_sdvo_write_cmd(output, SDVO_CMD_GET_ENCODE, NULL, 0);
|
|
status = intel_sdvo_read_response(output, &sdvo_priv->is_hdmi, 1);
|
|
@@ -2204,42 +2107,40 @@ intel_sdvo_get_digital_encoding_mode(struct intel_output *output)
|
|
return true;
|
|
}
|
|
|
|
-static struct intel_output *
|
|
-intel_sdvo_chan_to_intel_output(struct intel_i2c_chan *chan)
|
|
+static struct intel_encoder *
|
|
+intel_sdvo_chan_to_intel_encoder(struct intel_i2c_chan *chan)
|
|
{
|
|
struct drm_device *dev = chan->drm_dev;
|
|
- struct drm_connector *connector;
|
|
- struct intel_output *intel_output = NULL;
|
|
+ struct drm_encoder *encoder;
|
|
+ struct intel_encoder *intel_encoder = NULL;
|
|
|
|
- list_for_each_entry(connector,
|
|
- &dev->mode_config.connector_list, head) {
|
|
- if (to_intel_output(connector)->ddc_bus == &chan->adapter) {
|
|
- intel_output = to_intel_output(connector);
|
|
+ list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
|
+ intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ if (intel_encoder->ddc_bus == &chan->adapter)
|
|
break;
|
|
- }
|
|
}
|
|
- return intel_output;
|
|
+ return intel_encoder;
|
|
}
|
|
|
|
static int intel_sdvo_master_xfer(struct i2c_adapter *i2c_adap,
|
|
struct i2c_msg msgs[], int num)
|
|
{
|
|
- struct intel_output *intel_output;
|
|
+ struct intel_encoder *intel_encoder;
|
|
struct intel_sdvo_priv *sdvo_priv;
|
|
struct i2c_algo_bit_data *algo_data;
|
|
const struct i2c_algorithm *algo;
|
|
|
|
algo_data = (struct i2c_algo_bit_data *)i2c_adap->algo_data;
|
|
- intel_output =
|
|
- intel_sdvo_chan_to_intel_output(
|
|
+ intel_encoder =
|
|
+ intel_sdvo_chan_to_intel_encoder(
|
|
(struct intel_i2c_chan *)(algo_data->data));
|
|
- if (intel_output == NULL)
|
|
+ if (intel_encoder == NULL)
|
|
return -EINVAL;
|
|
|
|
- sdvo_priv = intel_output->dev_priv;
|
|
- algo = intel_output->i2c_bus->algo;
|
|
+ sdvo_priv = intel_encoder->dev_priv;
|
|
+ algo = intel_encoder->i2c_bus->algo;
|
|
|
|
- intel_sdvo_set_control_bus_switch(intel_output, sdvo_priv->ddc_bus);
|
|
+ intel_sdvo_set_control_bus_switch(intel_encoder, sdvo_priv->ddc_bus);
|
|
return algo->master_xfer(i2c_adap, msgs, num);
|
|
}
|
|
|
|
@@ -2248,12 +2149,12 @@ static struct i2c_algorithm intel_sdvo_i2c_bit_algo = {
|
|
};
|
|
|
|
static u8
|
|
-intel_sdvo_get_slave_addr(struct drm_device *dev, int output_device)
|
|
+intel_sdvo_get_slave_addr(struct drm_device *dev, int sdvo_reg)
|
|
{
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
struct sdvo_device_mapping *my_mapping, *other_mapping;
|
|
|
|
- if (output_device == SDVOB) {
|
|
+ if (IS_SDVOB(sdvo_reg)) {
|
|
my_mapping = &dev_priv->sdvo_mappings[0];
|
|
other_mapping = &dev_priv->sdvo_mappings[1];
|
|
} else {
|
|
@@ -2278,120 +2179,235 @@ intel_sdvo_get_slave_addr(struct drm_device *dev, int output_device)
|
|
/* No SDVO device info is found for another DVO port,
|
|
* so use mapping assumption we had before BIOS parsing.
|
|
*/
|
|
- if (output_device == SDVOB)
|
|
+ if (IS_SDVOB(sdvo_reg))
|
|
return 0x70;
|
|
else
|
|
return 0x72;
|
|
}
|
|
|
|
-static int intel_sdvo_bad_tv_callback(const struct dmi_system_id *id)
|
|
+static bool
|
|
+intel_sdvo_connector_alloc (struct intel_connector **ret)
|
|
{
|
|
- DRM_DEBUG_KMS("Ignoring bad SDVO TV connector for %s\n", id->ident);
|
|
- return 1;
|
|
+ struct intel_connector *intel_connector;
|
|
+ struct intel_sdvo_connector *sdvo_connector;
|
|
+
|
|
+ *ret = kzalloc(sizeof(*intel_connector) +
|
|
+ sizeof(*sdvo_connector), GFP_KERNEL);
|
|
+ if (!*ret)
|
|
+ return false;
|
|
+
|
|
+ intel_connector = *ret;
|
|
+ sdvo_connector = (struct intel_sdvo_connector *)(intel_connector + 1);
|
|
+ intel_connector->dev_priv = sdvo_connector;
|
|
+
|
|
+ return true;
|
|
}
|
|
|
|
-static struct dmi_system_id intel_sdvo_bad_tv[] = {
|
|
- {
|
|
- .callback = intel_sdvo_bad_tv_callback,
|
|
- .ident = "IntelG45/ICH10R/DME1737",
|
|
- .matches = {
|
|
- DMI_MATCH(DMI_SYS_VENDOR, "IBM CORPORATION"),
|
|
- DMI_MATCH(DMI_PRODUCT_NAME, "4800784"),
|
|
- },
|
|
- },
|
|
+static void
|
|
+intel_sdvo_connector_create (struct drm_encoder *encoder,
|
|
+ struct drm_connector *connector)
|
|
+{
|
|
+ drm_connector_init(encoder->dev, connector, &intel_sdvo_connector_funcs,
|
|
+ connector->connector_type);
|
|
|
|
- { } /* terminating entry */
|
|
-};
|
|
+ drm_connector_helper_add(connector, &intel_sdvo_connector_helper_funcs);
|
|
+
|
|
+ connector->interlace_allowed = 0;
|
|
+ connector->doublescan_allowed = 0;
|
|
+ connector->display_info.subpixel_order = SubPixelHorizontalRGB;
|
|
+
|
|
+ drm_mode_connector_attach_encoder(connector, encoder);
|
|
+ drm_sysfs_connector_add(connector);
|
|
+}
|
|
+
|
|
+static bool
|
|
+intel_sdvo_dvi_init(struct intel_encoder *intel_encoder, int device)
|
|
+{
|
|
+ struct drm_encoder *encoder = &intel_encoder->enc;
|
|
+ struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
|
|
+ struct drm_connector *connector;
|
|
+ struct intel_connector *intel_connector;
|
|
+ struct intel_sdvo_connector *sdvo_connector;
|
|
+
|
|
+ if (!intel_sdvo_connector_alloc(&intel_connector))
|
|
+ return false;
|
|
+
|
|
+ sdvo_connector = intel_connector->dev_priv;
|
|
+
|
|
+ if (device == 0) {
|
|
+ sdvo_priv->controlled_output |= SDVO_OUTPUT_TMDS0;
|
|
+ sdvo_connector->output_flag = SDVO_OUTPUT_TMDS0;
|
|
+ } else if (device == 1) {
|
|
+ sdvo_priv->controlled_output |= SDVO_OUTPUT_TMDS1;
|
|
+ sdvo_connector->output_flag = SDVO_OUTPUT_TMDS1;
|
|
+ }
|
|
+
|
|
+ connector = &intel_connector->base;
|
|
+ encoder->encoder_type = DRM_MODE_ENCODER_TMDS;
|
|
+ connector->connector_type = DRM_MODE_CONNECTOR_DVID;
|
|
+
|
|
+ if (intel_sdvo_get_supp_encode(intel_encoder, &sdvo_priv->encode)
|
|
+ && intel_sdvo_get_digital_encoding_mode(intel_encoder, device)
|
|
+ && sdvo_priv->is_hdmi) {
|
|
+ /* enable hdmi encoding mode if supported */
|
|
+ intel_sdvo_set_encode(intel_encoder, SDVO_ENCODE_HDMI);
|
|
+ intel_sdvo_set_colorimetry(intel_encoder,
|
|
+ SDVO_COLORIMETRY_RGB256);
|
|
+ connector->connector_type = DRM_MODE_CONNECTOR_HDMIA;
|
|
+ }
|
|
+ intel_encoder->clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
|
|
+ (1 << INTEL_ANALOG_CLONE_BIT);
|
|
+
|
|
+ intel_sdvo_connector_create(encoder, connector);
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+static bool
|
|
+intel_sdvo_tv_init(struct intel_encoder *intel_encoder, int type)
|
|
+{
|
|
+ struct drm_encoder *encoder = &intel_encoder->enc;
|
|
+ struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
|
|
+ struct drm_connector *connector;
|
|
+ struct intel_connector *intel_connector;
|
|
+ struct intel_sdvo_connector *sdvo_connector;
|
|
+
|
|
+ if (!intel_sdvo_connector_alloc(&intel_connector))
|
|
+ return false;
|
|
+
|
|
+ connector = &intel_connector->base;
|
|
+ encoder->encoder_type = DRM_MODE_ENCODER_TVDAC;
|
|
+ connector->connector_type = DRM_MODE_CONNECTOR_SVIDEO;
|
|
+ sdvo_connector = intel_connector->dev_priv;
|
|
+
|
|
+ sdvo_priv->controlled_output |= type;
|
|
+ sdvo_connector->output_flag = type;
|
|
+
|
|
+ sdvo_priv->is_tv = true;
|
|
+ intel_encoder->needs_tv_clock = true;
|
|
+ intel_encoder->clone_mask = 1 << INTEL_SDVO_TV_CLONE_BIT;
|
|
+
|
|
+ intel_sdvo_connector_create(encoder, connector);
|
|
+
|
|
+ intel_sdvo_tv_create_property(connector, type);
|
|
+
|
|
+ intel_sdvo_create_enhance_property(connector);
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+static bool
|
|
+intel_sdvo_analog_init(struct intel_encoder *intel_encoder, int device)
|
|
+{
|
|
+ struct drm_encoder *encoder = &intel_encoder->enc;
|
|
+ struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
|
|
+ struct drm_connector *connector;
|
|
+ struct intel_connector *intel_connector;
|
|
+ struct intel_sdvo_connector *sdvo_connector;
|
|
+
|
|
+ if (!intel_sdvo_connector_alloc(&intel_connector))
|
|
+ return false;
|
|
+
|
|
+ connector = &intel_connector->base;
|
|
+ encoder->encoder_type = DRM_MODE_ENCODER_DAC;
|
|
+ connector->connector_type = DRM_MODE_CONNECTOR_VGA;
|
|
+ sdvo_connector = intel_connector->dev_priv;
|
|
+
|
|
+ if (device == 0) {
|
|
+ sdvo_priv->controlled_output |= SDVO_OUTPUT_RGB0;
|
|
+ sdvo_connector->output_flag = SDVO_OUTPUT_RGB0;
|
|
+ } else if (device == 1) {
|
|
+ sdvo_priv->controlled_output |= SDVO_OUTPUT_RGB1;
|
|
+ sdvo_connector->output_flag = SDVO_OUTPUT_RGB1;
|
|
+ }
|
|
+
|
|
+ intel_encoder->clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
|
|
+ (1 << INTEL_ANALOG_CLONE_BIT);
|
|
+
|
|
+ intel_sdvo_connector_create(encoder, connector);
|
|
+ return true;
|
|
+}
|
|
+
|
|
+static bool
|
|
+intel_sdvo_lvds_init(struct intel_encoder *intel_encoder, int device)
|
|
+{
|
|
+ struct drm_encoder *encoder = &intel_encoder->enc;
|
|
+ struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
|
|
+ struct drm_connector *connector;
|
|
+ struct intel_connector *intel_connector;
|
|
+ struct intel_sdvo_connector *sdvo_connector;
|
|
+
|
|
+ if (!intel_sdvo_connector_alloc(&intel_connector))
|
|
+ return false;
|
|
+
|
|
+ connector = &intel_connector->base;
|
|
+ encoder->encoder_type = DRM_MODE_ENCODER_LVDS;
|
|
+ connector->connector_type = DRM_MODE_CONNECTOR_LVDS;
|
|
+ sdvo_connector = intel_connector->dev_priv;
|
|
+
|
|
+ sdvo_priv->is_lvds = true;
|
|
+
|
|
+ if (device == 0) {
|
|
+ sdvo_priv->controlled_output |= SDVO_OUTPUT_LVDS0;
|
|
+ sdvo_connector->output_flag = SDVO_OUTPUT_LVDS0;
|
|
+ } else if (device == 1) {
|
|
+ sdvo_priv->controlled_output |= SDVO_OUTPUT_LVDS1;
|
|
+ sdvo_connector->output_flag = SDVO_OUTPUT_LVDS1;
|
|
+ }
|
|
+
|
|
+ intel_encoder->clone_mask = (1 << INTEL_ANALOG_CLONE_BIT) |
|
|
+ (1 << INTEL_SDVO_LVDS_CLONE_BIT);
|
|
+
|
|
+ intel_sdvo_connector_create(encoder, connector);
|
|
+ intel_sdvo_create_enhance_property(connector);
|
|
+ return true;
|
|
+}
|
|
|
|
static bool
|
|
-intel_sdvo_output_setup(struct intel_output *intel_output, uint16_t flags)
|
|
+intel_sdvo_output_setup(struct intel_encoder *intel_encoder, uint16_t flags)
|
|
{
|
|
- struct drm_connector *connector = &intel_output->base;
|
|
- struct drm_encoder *encoder = &intel_output->enc;
|
|
- struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
|
|
- bool ret = true, registered = false;
|
|
+ struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
|
|
|
|
sdvo_priv->is_tv = false;
|
|
- intel_output->needs_tv_clock = false;
|
|
+ intel_encoder->needs_tv_clock = false;
|
|
sdvo_priv->is_lvds = false;
|
|
|
|
- if (device_is_registered(&connector->kdev)) {
|
|
- drm_sysfs_connector_remove(connector);
|
|
- registered = true;
|
|
- }
|
|
+ /* SDVO requires XXX1 function may not exist unless it has XXX0 function.*/
|
|
|
|
- if (flags &
|
|
- (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1)) {
|
|
- if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS0)
|
|
- sdvo_priv->controlled_output = SDVO_OUTPUT_TMDS0;
|
|
- else
|
|
- sdvo_priv->controlled_output = SDVO_OUTPUT_TMDS1;
|
|
-
|
|
- encoder->encoder_type = DRM_MODE_ENCODER_TMDS;
|
|
- connector->connector_type = DRM_MODE_CONNECTOR_DVID;
|
|
-
|
|
- if (intel_sdvo_get_supp_encode(intel_output,
|
|
- &sdvo_priv->encode) &&
|
|
- intel_sdvo_get_digital_encoding_mode(intel_output) &&
|
|
- sdvo_priv->is_hdmi) {
|
|
- /* enable hdmi encoding mode if supported */
|
|
- intel_sdvo_set_encode(intel_output, SDVO_ENCODE_HDMI);
|
|
- intel_sdvo_set_colorimetry(intel_output,
|
|
- SDVO_COLORIMETRY_RGB256);
|
|
- connector->connector_type = DRM_MODE_CONNECTOR_HDMIA;
|
|
- intel_output->clone_mask =
|
|
- (1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
|
|
- (1 << INTEL_ANALOG_CLONE_BIT);
|
|
- }
|
|
- } else if ((flags & SDVO_OUTPUT_SVID0) &&
|
|
- !dmi_check_system(intel_sdvo_bad_tv)) {
|
|
-
|
|
- sdvo_priv->controlled_output = SDVO_OUTPUT_SVID0;
|
|
- encoder->encoder_type = DRM_MODE_ENCODER_TVDAC;
|
|
- connector->connector_type = DRM_MODE_CONNECTOR_SVIDEO;
|
|
- sdvo_priv->is_tv = true;
|
|
- intel_output->needs_tv_clock = true;
|
|
- intel_output->clone_mask = 1 << INTEL_SDVO_TV_CLONE_BIT;
|
|
- } else if (flags & SDVO_OUTPUT_RGB0) {
|
|
-
|
|
- sdvo_priv->controlled_output = SDVO_OUTPUT_RGB0;
|
|
- encoder->encoder_type = DRM_MODE_ENCODER_DAC;
|
|
- connector->connector_type = DRM_MODE_CONNECTOR_VGA;
|
|
- intel_output->clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
|
|
- (1 << INTEL_ANALOG_CLONE_BIT);
|
|
- } else if (flags & SDVO_OUTPUT_RGB1) {
|
|
-
|
|
- sdvo_priv->controlled_output = SDVO_OUTPUT_RGB1;
|
|
- encoder->encoder_type = DRM_MODE_ENCODER_DAC;
|
|
- connector->connector_type = DRM_MODE_CONNECTOR_VGA;
|
|
- intel_output->clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
|
|
- (1 << INTEL_ANALOG_CLONE_BIT);
|
|
- } else if (flags & SDVO_OUTPUT_CVBS0) {
|
|
-
|
|
- sdvo_priv->controlled_output = SDVO_OUTPUT_CVBS0;
|
|
- encoder->encoder_type = DRM_MODE_ENCODER_TVDAC;
|
|
- connector->connector_type = DRM_MODE_CONNECTOR_SVIDEO;
|
|
- sdvo_priv->is_tv = true;
|
|
- intel_output->needs_tv_clock = true;
|
|
- intel_output->clone_mask = 1 << INTEL_SDVO_TV_CLONE_BIT;
|
|
- } else if (flags & SDVO_OUTPUT_LVDS0) {
|
|
-
|
|
- sdvo_priv->controlled_output = SDVO_OUTPUT_LVDS0;
|
|
- encoder->encoder_type = DRM_MODE_ENCODER_LVDS;
|
|
- connector->connector_type = DRM_MODE_CONNECTOR_LVDS;
|
|
- sdvo_priv->is_lvds = true;
|
|
- intel_output->clone_mask = (1 << INTEL_ANALOG_CLONE_BIT) |
|
|
- (1 << INTEL_SDVO_LVDS_CLONE_BIT);
|
|
- } else if (flags & SDVO_OUTPUT_LVDS1) {
|
|
-
|
|
- sdvo_priv->controlled_output = SDVO_OUTPUT_LVDS1;
|
|
- encoder->encoder_type = DRM_MODE_ENCODER_LVDS;
|
|
- connector->connector_type = DRM_MODE_CONNECTOR_LVDS;
|
|
- sdvo_priv->is_lvds = true;
|
|
- intel_output->clone_mask = (1 << INTEL_ANALOG_CLONE_BIT) |
|
|
- (1 << INTEL_SDVO_LVDS_CLONE_BIT);
|
|
- } else {
|
|
+ if (flags & SDVO_OUTPUT_TMDS0)
|
|
+ if (!intel_sdvo_dvi_init(intel_encoder, 0))
|
|
+ return false;
|
|
+
|
|
+ if ((flags & SDVO_TMDS_MASK) == SDVO_TMDS_MASK)
|
|
+ if (!intel_sdvo_dvi_init(intel_encoder, 1))
|
|
+ return false;
|
|
+
|
|
+ /* TV has no XXX1 function block */
|
|
+ if (flags & SDVO_OUTPUT_SVID0)
|
|
+ if (!intel_sdvo_tv_init(intel_encoder, SDVO_OUTPUT_SVID0))
|
|
+ return false;
|
|
+
|
|
+ if (flags & SDVO_OUTPUT_CVBS0)
|
|
+ if (!intel_sdvo_tv_init(intel_encoder, SDVO_OUTPUT_CVBS0))
|
|
+ return false;
|
|
+
|
|
+ if (flags & SDVO_OUTPUT_RGB0)
|
|
+ if (!intel_sdvo_analog_init(intel_encoder, 0))
|
|
+ return false;
|
|
+
|
|
+ if ((flags & SDVO_RGB_MASK) == SDVO_RGB_MASK)
|
|
+ if (!intel_sdvo_analog_init(intel_encoder, 1))
|
|
+ return false;
|
|
|
|
+ if (flags & SDVO_OUTPUT_LVDS0)
|
|
+ if (!intel_sdvo_lvds_init(intel_encoder, 0))
|
|
+ return false;
|
|
+
|
|
+ if ((flags & SDVO_LVDS_MASK) == SDVO_LVDS_MASK)
|
|
+ if (!intel_sdvo_lvds_init(intel_encoder, 1))
|
|
+ return false;
|
|
+
|
|
+ if ((flags & SDVO_OUTPUT_MASK) == 0) {
|
|
unsigned char bytes[2];
|
|
|
|
sdvo_priv->controlled_output = 0;
|
|
@@ -2399,32 +2415,29 @@ intel_sdvo_output_setup(struct intel_output *intel_output, uint16_t flags)
|
|
DRM_DEBUG_KMS("%s: Unknown SDVO output type (0x%02x%02x)\n",
|
|
SDVO_NAME(sdvo_priv),
|
|
bytes[0], bytes[1]);
|
|
- ret = false;
|
|
+ return false;
|
|
}
|
|
- intel_output->crtc_mask = (1 << 0) | (1 << 1);
|
|
-
|
|
- if (ret && registered)
|
|
- ret = drm_sysfs_connector_add(connector) == 0 ? true : false;
|
|
-
|
|
-
|
|
- return ret;
|
|
+ intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
|
|
|
|
+ return true;
|
|
}
|
|
|
|
-static void intel_sdvo_tv_create_property(struct drm_connector *connector)
|
|
+static void intel_sdvo_tv_create_property(struct drm_connector *connector, int type)
|
|
{
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
- struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
|
|
+ struct drm_encoder *encoder = intel_attached_encoder(connector);
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
|
|
+ struct intel_connector *intel_connector = to_intel_connector(connector);
|
|
+ struct intel_sdvo_connector *sdvo_connector = intel_connector->dev_priv;
|
|
struct intel_sdvo_tv_format format;
|
|
uint32_t format_map, i;
|
|
uint8_t status;
|
|
|
|
- intel_sdvo_set_target_output(intel_output,
|
|
- sdvo_priv->controlled_output);
|
|
+ intel_sdvo_set_target_output(intel_encoder, type);
|
|
|
|
- intel_sdvo_write_cmd(intel_output,
|
|
+ intel_sdvo_write_cmd(intel_encoder,
|
|
SDVO_CMD_GET_SUPPORTED_TV_FORMATS, NULL, 0);
|
|
- status = intel_sdvo_read_response(intel_output,
|
|
+ status = intel_sdvo_read_response(intel_encoder,
|
|
&format, sizeof(format));
|
|
if (status != SDVO_CMD_STATUS_SUCCESS)
|
|
return;
|
|
@@ -2435,43 +2448,45 @@ static void intel_sdvo_tv_create_property(struct drm_connector *connector)
|
|
if (format_map == 0)
|
|
return;
|
|
|
|
- sdvo_priv->format_supported_num = 0;
|
|
+ sdvo_connector->format_supported_num = 0;
|
|
for (i = 0 ; i < TV_FORMAT_NUM; i++)
|
|
if (format_map & (1 << i)) {
|
|
- sdvo_priv->tv_format_supported
|
|
- [sdvo_priv->format_supported_num++] =
|
|
+ sdvo_connector->tv_format_supported
|
|
+ [sdvo_connector->format_supported_num++] =
|
|
tv_format_names[i];
|
|
}
|
|
|
|
|
|
- sdvo_priv->tv_format_property =
|
|
+ sdvo_connector->tv_format_property =
|
|
drm_property_create(
|
|
connector->dev, DRM_MODE_PROP_ENUM,
|
|
- "mode", sdvo_priv->format_supported_num);
|
|
+ "mode", sdvo_connector->format_supported_num);
|
|
|
|
- for (i = 0; i < sdvo_priv->format_supported_num; i++)
|
|
+ for (i = 0; i < sdvo_connector->format_supported_num; i++)
|
|
drm_property_add_enum(
|
|
- sdvo_priv->tv_format_property, i,
|
|
- i, sdvo_priv->tv_format_supported[i]);
|
|
+ sdvo_connector->tv_format_property, i,
|
|
+ i, sdvo_connector->tv_format_supported[i]);
|
|
|
|
- sdvo_priv->tv_format_name = sdvo_priv->tv_format_supported[0];
|
|
+ sdvo_priv->tv_format_name = sdvo_connector->tv_format_supported[0];
|
|
drm_connector_attach_property(
|
|
- connector, sdvo_priv->tv_format_property, 0);
|
|
+ connector, sdvo_connector->tv_format_property, 0);
|
|
|
|
}
|
|
|
|
static void intel_sdvo_create_enhance_property(struct drm_connector *connector)
|
|
{
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
- struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
|
|
+ struct drm_encoder *encoder = intel_attached_encoder(connector);
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ struct intel_connector *intel_connector = to_intel_connector(connector);
|
|
+ struct intel_sdvo_connector *sdvo_priv = intel_connector->dev_priv;
|
|
struct intel_sdvo_enhancements_reply sdvo_data;
|
|
struct drm_device *dev = connector->dev;
|
|
uint8_t status;
|
|
uint16_t response, data_value[2];
|
|
|
|
- intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS,
|
|
+ intel_sdvo_write_cmd(intel_encoder, SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS,
|
|
NULL, 0);
|
|
- status = intel_sdvo_read_response(intel_output, &sdvo_data,
|
|
+ status = intel_sdvo_read_response(intel_encoder, &sdvo_data,
|
|
sizeof(sdvo_data));
|
|
if (status != SDVO_CMD_STATUS_SUCCESS) {
|
|
DRM_DEBUG_KMS(" incorrect response is returned\n");
|
|
@@ -2482,23 +2497,23 @@ static void intel_sdvo_create_enhance_property(struct drm_connector *connector)
|
|
DRM_DEBUG_KMS("No enhancement is supported\n");
|
|
return;
|
|
}
|
|
- if (sdvo_priv->is_tv) {
|
|
+ if (IS_TV(sdvo_priv)) {
|
|
/* when horizontal overscan is supported, Add the left/right
|
|
* property
|
|
*/
|
|
if (sdvo_data.overscan_h) {
|
|
- intel_sdvo_write_cmd(intel_output,
|
|
+ intel_sdvo_write_cmd(intel_encoder,
|
|
SDVO_CMD_GET_MAX_OVERSCAN_H, NULL, 0);
|
|
- status = intel_sdvo_read_response(intel_output,
|
|
+ status = intel_sdvo_read_response(intel_encoder,
|
|
&data_value, 4);
|
|
if (status != SDVO_CMD_STATUS_SUCCESS) {
|
|
DRM_DEBUG_KMS("Incorrect SDVO max "
|
|
"h_overscan\n");
|
|
return;
|
|
}
|
|
- intel_sdvo_write_cmd(intel_output,
|
|
+ intel_sdvo_write_cmd(intel_encoder,
|
|
SDVO_CMD_GET_OVERSCAN_H, NULL, 0);
|
|
- status = intel_sdvo_read_response(intel_output,
|
|
+ status = intel_sdvo_read_response(intel_encoder,
|
|
&response, 2);
|
|
if (status != SDVO_CMD_STATUS_SUCCESS) {
|
|
DRM_DEBUG_KMS("Incorrect SDVO h_overscan\n");
|
|
@@ -2528,18 +2543,18 @@ static void intel_sdvo_create_enhance_property(struct drm_connector *connector)
|
|
data_value[0], data_value[1], response);
|
|
}
|
|
if (sdvo_data.overscan_v) {
|
|
- intel_sdvo_write_cmd(intel_output,
|
|
+ intel_sdvo_write_cmd(intel_encoder,
|
|
SDVO_CMD_GET_MAX_OVERSCAN_V, NULL, 0);
|
|
- status = intel_sdvo_read_response(intel_output,
|
|
+ status = intel_sdvo_read_response(intel_encoder,
|
|
&data_value, 4);
|
|
if (status != SDVO_CMD_STATUS_SUCCESS) {
|
|
DRM_DEBUG_KMS("Incorrect SDVO max "
|
|
"v_overscan\n");
|
|
return;
|
|
}
|
|
- intel_sdvo_write_cmd(intel_output,
|
|
+ intel_sdvo_write_cmd(intel_encoder,
|
|
SDVO_CMD_GET_OVERSCAN_V, NULL, 0);
|
|
- status = intel_sdvo_read_response(intel_output,
|
|
+ status = intel_sdvo_read_response(intel_encoder,
|
|
&response, 2);
|
|
if (status != SDVO_CMD_STATUS_SUCCESS) {
|
|
DRM_DEBUG_KMS("Incorrect SDVO v_overscan\n");
|
|
@@ -2569,17 +2584,17 @@ static void intel_sdvo_create_enhance_property(struct drm_connector *connector)
|
|
data_value[0], data_value[1], response);
|
|
}
|
|
if (sdvo_data.position_h) {
|
|
- intel_sdvo_write_cmd(intel_output,
|
|
+ intel_sdvo_write_cmd(intel_encoder,
|
|
SDVO_CMD_GET_MAX_POSITION_H, NULL, 0);
|
|
- status = intel_sdvo_read_response(intel_output,
|
|
+ status = intel_sdvo_read_response(intel_encoder,
|
|
&data_value, 4);
|
|
if (status != SDVO_CMD_STATUS_SUCCESS) {
|
|
DRM_DEBUG_KMS("Incorrect SDVO Max h_pos\n");
|
|
return;
|
|
}
|
|
- intel_sdvo_write_cmd(intel_output,
|
|
+ intel_sdvo_write_cmd(intel_encoder,
|
|
SDVO_CMD_GET_POSITION_H, NULL, 0);
|
|
- status = intel_sdvo_read_response(intel_output,
|
|
+ status = intel_sdvo_read_response(intel_encoder,
|
|
&response, 2);
|
|
if (status != SDVO_CMD_STATUS_SUCCESS) {
|
|
DRM_DEBUG_KMS("Incorrect SDVO get h_postion\n");
|
|
@@ -2600,17 +2615,17 @@ static void intel_sdvo_create_enhance_property(struct drm_connector *connector)
|
|
data_value[0], data_value[1], response);
|
|
}
|
|
if (sdvo_data.position_v) {
|
|
- intel_sdvo_write_cmd(intel_output,
|
|
+ intel_sdvo_write_cmd(intel_encoder,
|
|
SDVO_CMD_GET_MAX_POSITION_V, NULL, 0);
|
|
- status = intel_sdvo_read_response(intel_output,
|
|
+ status = intel_sdvo_read_response(intel_encoder,
|
|
&data_value, 4);
|
|
if (status != SDVO_CMD_STATUS_SUCCESS) {
|
|
DRM_DEBUG_KMS("Incorrect SDVO Max v_pos\n");
|
|
return;
|
|
}
|
|
- intel_sdvo_write_cmd(intel_output,
|
|
+ intel_sdvo_write_cmd(intel_encoder,
|
|
SDVO_CMD_GET_POSITION_V, NULL, 0);
|
|
- status = intel_sdvo_read_response(intel_output,
|
|
+ status = intel_sdvo_read_response(intel_encoder,
|
|
&response, 2);
|
|
if (status != SDVO_CMD_STATUS_SUCCESS) {
|
|
DRM_DEBUG_KMS("Incorrect SDVO get v_postion\n");
|
|
@@ -2630,20 +2645,18 @@ static void intel_sdvo_create_enhance_property(struct drm_connector *connector)
|
|
"default %d, current %d\n",
|
|
data_value[0], data_value[1], response);
|
|
}
|
|
- }
|
|
- if (sdvo_priv->is_tv) {
|
|
if (sdvo_data.saturation) {
|
|
- intel_sdvo_write_cmd(intel_output,
|
|
+ intel_sdvo_write_cmd(intel_encoder,
|
|
SDVO_CMD_GET_MAX_SATURATION, NULL, 0);
|
|
- status = intel_sdvo_read_response(intel_output,
|
|
+ status = intel_sdvo_read_response(intel_encoder,
|
|
&data_value, 4);
|
|
if (status != SDVO_CMD_STATUS_SUCCESS) {
|
|
DRM_DEBUG_KMS("Incorrect SDVO Max sat\n");
|
|
return;
|
|
}
|
|
- intel_sdvo_write_cmd(intel_output,
|
|
+ intel_sdvo_write_cmd(intel_encoder,
|
|
SDVO_CMD_GET_SATURATION, NULL, 0);
|
|
- status = intel_sdvo_read_response(intel_output,
|
|
+ status = intel_sdvo_read_response(intel_encoder,
|
|
&response, 2);
|
|
if (status != SDVO_CMD_STATUS_SUCCESS) {
|
|
DRM_DEBUG_KMS("Incorrect SDVO get sat\n");
|
|
@@ -2665,17 +2678,17 @@ static void intel_sdvo_create_enhance_property(struct drm_connector *connector)
|
|
data_value[0], data_value[1], response);
|
|
}
|
|
if (sdvo_data.contrast) {
|
|
- intel_sdvo_write_cmd(intel_output,
|
|
+ intel_sdvo_write_cmd(intel_encoder,
|
|
SDVO_CMD_GET_MAX_CONTRAST, NULL, 0);
|
|
- status = intel_sdvo_read_response(intel_output,
|
|
+ status = intel_sdvo_read_response(intel_encoder,
|
|
&data_value, 4);
|
|
if (status != SDVO_CMD_STATUS_SUCCESS) {
|
|
DRM_DEBUG_KMS("Incorrect SDVO Max contrast\n");
|
|
return;
|
|
}
|
|
- intel_sdvo_write_cmd(intel_output,
|
|
+ intel_sdvo_write_cmd(intel_encoder,
|
|
SDVO_CMD_GET_CONTRAST, NULL, 0);
|
|
- status = intel_sdvo_read_response(intel_output,
|
|
+ status = intel_sdvo_read_response(intel_encoder,
|
|
&response, 2);
|
|
if (status != SDVO_CMD_STATUS_SUCCESS) {
|
|
DRM_DEBUG_KMS("Incorrect SDVO get contrast\n");
|
|
@@ -2696,17 +2709,17 @@ static void intel_sdvo_create_enhance_property(struct drm_connector *connector)
|
|
data_value[0], data_value[1], response);
|
|
}
|
|
if (sdvo_data.hue) {
|
|
- intel_sdvo_write_cmd(intel_output,
|
|
+ intel_sdvo_write_cmd(intel_encoder,
|
|
SDVO_CMD_GET_MAX_HUE, NULL, 0);
|
|
- status = intel_sdvo_read_response(intel_output,
|
|
+ status = intel_sdvo_read_response(intel_encoder,
|
|
&data_value, 4);
|
|
if (status != SDVO_CMD_STATUS_SUCCESS) {
|
|
DRM_DEBUG_KMS("Incorrect SDVO Max hue\n");
|
|
return;
|
|
}
|
|
- intel_sdvo_write_cmd(intel_output,
|
|
+ intel_sdvo_write_cmd(intel_encoder,
|
|
SDVO_CMD_GET_HUE, NULL, 0);
|
|
- status = intel_sdvo_read_response(intel_output,
|
|
+ status = intel_sdvo_read_response(intel_encoder,
|
|
&response, 2);
|
|
if (status != SDVO_CMD_STATUS_SUCCESS) {
|
|
DRM_DEBUG_KMS("Incorrect SDVO get hue\n");
|
|
@@ -2727,19 +2740,19 @@ static void intel_sdvo_create_enhance_property(struct drm_connector *connector)
|
|
data_value[0], data_value[1], response);
|
|
}
|
|
}
|
|
- if (sdvo_priv->is_tv || sdvo_priv->is_lvds) {
|
|
+ if (IS_TV(sdvo_priv) || IS_LVDS(sdvo_priv)) {
|
|
if (sdvo_data.brightness) {
|
|
- intel_sdvo_write_cmd(intel_output,
|
|
+ intel_sdvo_write_cmd(intel_encoder,
|
|
SDVO_CMD_GET_MAX_BRIGHTNESS, NULL, 0);
|
|
- status = intel_sdvo_read_response(intel_output,
|
|
+ status = intel_sdvo_read_response(intel_encoder,
|
|
&data_value, 4);
|
|
if (status != SDVO_CMD_STATUS_SUCCESS) {
|
|
DRM_DEBUG_KMS("Incorrect SDVO Max bright\n");
|
|
return;
|
|
}
|
|
- intel_sdvo_write_cmd(intel_output,
|
|
+ intel_sdvo_write_cmd(intel_encoder,
|
|
SDVO_CMD_GET_BRIGHTNESS, NULL, 0);
|
|
- status = intel_sdvo_read_response(intel_output,
|
|
+ status = intel_sdvo_read_response(intel_encoder,
|
|
&response, 2);
|
|
if (status != SDVO_CMD_STATUS_SUCCESS) {
|
|
DRM_DEBUG_KMS("Incorrect SDVO get brigh\n");
|
|
@@ -2764,109 +2777,98 @@ static void intel_sdvo_create_enhance_property(struct drm_connector *connector)
|
|
return;
|
|
}
|
|
|
|
-bool intel_sdvo_init(struct drm_device *dev, int output_device)
|
|
+bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg)
|
|
{
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
- struct drm_connector *connector;
|
|
- struct intel_output *intel_output;
|
|
+ struct intel_encoder *intel_encoder;
|
|
struct intel_sdvo_priv *sdvo_priv;
|
|
-
|
|
u8 ch[0x40];
|
|
int i;
|
|
+ u32 i2c_reg, ddc_reg, analog_ddc_reg;
|
|
|
|
- intel_output = kcalloc(sizeof(struct intel_output)+sizeof(struct intel_sdvo_priv), 1, GFP_KERNEL);
|
|
- if (!intel_output) {
|
|
+ intel_encoder = kcalloc(sizeof(struct intel_encoder)+sizeof(struct intel_sdvo_priv), 1, GFP_KERNEL);
|
|
+ if (!intel_encoder) {
|
|
return false;
|
|
}
|
|
|
|
- sdvo_priv = (struct intel_sdvo_priv *)(intel_output + 1);
|
|
- sdvo_priv->output_device = output_device;
|
|
+ sdvo_priv = (struct intel_sdvo_priv *)(intel_encoder + 1);
|
|
+ sdvo_priv->sdvo_reg = sdvo_reg;
|
|
|
|
- intel_output->dev_priv = sdvo_priv;
|
|
- intel_output->type = INTEL_OUTPUT_SDVO;
|
|
+ intel_encoder->dev_priv = sdvo_priv;
|
|
+ intel_encoder->type = INTEL_OUTPUT_SDVO;
|
|
+
|
|
+ if (HAS_PCH_SPLIT(dev)) {
|
|
+ i2c_reg = PCH_GPIOE;
|
|
+ ddc_reg = PCH_GPIOE;
|
|
+ analog_ddc_reg = PCH_GPIOA;
|
|
+ } else {
|
|
+ i2c_reg = GPIOE;
|
|
+ ddc_reg = GPIOE;
|
|
+ analog_ddc_reg = GPIOA;
|
|
+ }
|
|
|
|
/* setup the DDC bus. */
|
|
- if (output_device == SDVOB)
|
|
- intel_output->i2c_bus = intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOB");
|
|
+ if (IS_SDVOB(sdvo_reg))
|
|
+ intel_encoder->i2c_bus = intel_i2c_create(dev, i2c_reg, "SDVOCTRL_E for SDVOB");
|
|
else
|
|
- intel_output->i2c_bus = intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOC");
|
|
+ intel_encoder->i2c_bus = intel_i2c_create(dev, i2c_reg, "SDVOCTRL_E for SDVOC");
|
|
|
|
- if (!intel_output->i2c_bus)
|
|
+ if (!intel_encoder->i2c_bus)
|
|
goto err_inteloutput;
|
|
|
|
- sdvo_priv->slave_addr = intel_sdvo_get_slave_addr(dev, output_device);
|
|
+ sdvo_priv->slave_addr = intel_sdvo_get_slave_addr(dev, sdvo_reg);
|
|
|
|
/* Save the bit-banging i2c functionality for use by the DDC wrapper */
|
|
- intel_sdvo_i2c_bit_algo.functionality = intel_output->i2c_bus->algo->functionality;
|
|
+ intel_sdvo_i2c_bit_algo.functionality = intel_encoder->i2c_bus->algo->functionality;
|
|
|
|
/* Read the regs to test if we can talk to the device */
|
|
for (i = 0; i < 0x40; i++) {
|
|
- if (!intel_sdvo_read_byte(intel_output, i, &ch[i])) {
|
|
+ if (!intel_sdvo_read_byte(intel_encoder, i, &ch[i])) {
|
|
DRM_DEBUG_KMS("No SDVO device found on SDVO%c\n",
|
|
- output_device == SDVOB ? 'B' : 'C');
|
|
+ IS_SDVOB(sdvo_reg) ? 'B' : 'C');
|
|
goto err_i2c;
|
|
}
|
|
}
|
|
|
|
/* setup the DDC bus. */
|
|
- if (output_device == SDVOB) {
|
|
- intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOB DDC BUS");
|
|
- sdvo_priv->analog_ddc_bus = intel_i2c_create(dev, GPIOA,
|
|
+ if (IS_SDVOB(sdvo_reg)) {
|
|
+ intel_encoder->ddc_bus = intel_i2c_create(dev, ddc_reg, "SDVOB DDC BUS");
|
|
+ sdvo_priv->analog_ddc_bus = intel_i2c_create(dev, analog_ddc_reg,
|
|
"SDVOB/VGA DDC BUS");
|
|
dev_priv->hotplug_supported_mask |= SDVOB_HOTPLUG_INT_STATUS;
|
|
} else {
|
|
- intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOC DDC BUS");
|
|
- sdvo_priv->analog_ddc_bus = intel_i2c_create(dev, GPIOA,
|
|
+ intel_encoder->ddc_bus = intel_i2c_create(dev, ddc_reg, "SDVOC DDC BUS");
|
|
+ sdvo_priv->analog_ddc_bus = intel_i2c_create(dev, analog_ddc_reg,
|
|
"SDVOC/VGA DDC BUS");
|
|
dev_priv->hotplug_supported_mask |= SDVOC_HOTPLUG_INT_STATUS;
|
|
}
|
|
|
|
- if (intel_output->ddc_bus == NULL)
|
|
+ if (intel_encoder->ddc_bus == NULL)
|
|
goto err_i2c;
|
|
|
|
/* Wrap with our custom algo which switches to DDC mode */
|
|
- intel_output->ddc_bus->algo = &intel_sdvo_i2c_bit_algo;
|
|
+ intel_encoder->ddc_bus->algo = &intel_sdvo_i2c_bit_algo;
|
|
+
|
|
+ /* encoder type will be decided later */
|
|
+ drm_encoder_init(dev, &intel_encoder->enc, &intel_sdvo_enc_funcs, 0);
|
|
+ drm_encoder_helper_add(&intel_encoder->enc, &intel_sdvo_helper_funcs);
|
|
|
|
/* In default case sdvo lvds is false */
|
|
- intel_sdvo_get_capabilities(intel_output, &sdvo_priv->caps);
|
|
+ intel_sdvo_get_capabilities(intel_encoder, &sdvo_priv->caps);
|
|
|
|
- if (intel_sdvo_output_setup(intel_output,
|
|
+ if (intel_sdvo_output_setup(intel_encoder,
|
|
sdvo_priv->caps.output_flags) != true) {
|
|
DRM_DEBUG_KMS("SDVO output failed to setup on SDVO%c\n",
|
|
- output_device == SDVOB ? 'B' : 'C');
|
|
+ IS_SDVOB(sdvo_reg) ? 'B' : 'C');
|
|
goto err_i2c;
|
|
}
|
|
|
|
-
|
|
- connector = &intel_output->base;
|
|
- drm_connector_init(dev, connector, &intel_sdvo_connector_funcs,
|
|
- connector->connector_type);
|
|
-
|
|
- drm_connector_helper_add(connector, &intel_sdvo_connector_helper_funcs);
|
|
- connector->interlace_allowed = 0;
|
|
- connector->doublescan_allowed = 0;
|
|
- connector->display_info.subpixel_order = SubPixelHorizontalRGB;
|
|
-
|
|
- drm_encoder_init(dev, &intel_output->enc,
|
|
- &intel_sdvo_enc_funcs, intel_output->enc.encoder_type);
|
|
-
|
|
- drm_encoder_helper_add(&intel_output->enc, &intel_sdvo_helper_funcs);
|
|
-
|
|
- drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc);
|
|
- if (sdvo_priv->is_tv)
|
|
- intel_sdvo_tv_create_property(connector);
|
|
-
|
|
- if (sdvo_priv->is_tv || sdvo_priv->is_lvds)
|
|
- intel_sdvo_create_enhance_property(connector);
|
|
-
|
|
- drm_sysfs_connector_add(connector);
|
|
-
|
|
intel_sdvo_select_ddc_bus(sdvo_priv);
|
|
|
|
/* Set the input timing to the screen. Assume always input 0. */
|
|
- intel_sdvo_set_target_input(intel_output, true, false);
|
|
+ intel_sdvo_set_target_input(intel_encoder, true, false);
|
|
|
|
- intel_sdvo_get_input_pixel_clock_range(intel_output,
|
|
+ intel_sdvo_get_input_pixel_clock_range(intel_encoder,
|
|
&sdvo_priv->pixel_clock_min,
|
|
&sdvo_priv->pixel_clock_max);
|
|
|
|
@@ -2893,12 +2895,12 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device)
|
|
err_i2c:
|
|
if (sdvo_priv->analog_ddc_bus != NULL)
|
|
intel_i2c_destroy(sdvo_priv->analog_ddc_bus);
|
|
- if (intel_output->ddc_bus != NULL)
|
|
- intel_i2c_destroy(intel_output->ddc_bus);
|
|
- if (intel_output->i2c_bus != NULL)
|
|
- intel_i2c_destroy(intel_output->i2c_bus);
|
|
+ if (intel_encoder->ddc_bus != NULL)
|
|
+ intel_i2c_destroy(intel_encoder->ddc_bus);
|
|
+ if (intel_encoder->i2c_bus != NULL)
|
|
+ intel_i2c_destroy(intel_encoder->i2c_bus);
|
|
err_inteloutput:
|
|
- kfree(intel_output);
|
|
+ kfree(intel_encoder);
|
|
|
|
return false;
|
|
}
|
|
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
|
|
--- a/drivers/gpu/drm/i915/intel_tv.c
|
|
+++ b/drivers/gpu/drm/i915/intel_tv.c
|
|
@@ -916,143 +916,6 @@ intel_tv_dpms(struct drm_encoder *encoder, int mode)
|
|
}
|
|
}
|
|
|
|
-static void
|
|
-intel_tv_save(struct drm_connector *connector)
|
|
-{
|
|
- struct drm_device *dev = connector->dev;
|
|
- struct drm_i915_private *dev_priv = dev->dev_private;
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
- struct intel_tv_priv *tv_priv = intel_output->dev_priv;
|
|
- int i;
|
|
-
|
|
- tv_priv->save_TV_H_CTL_1 = I915_READ(TV_H_CTL_1);
|
|
- tv_priv->save_TV_H_CTL_2 = I915_READ(TV_H_CTL_2);
|
|
- tv_priv->save_TV_H_CTL_3 = I915_READ(TV_H_CTL_3);
|
|
- tv_priv->save_TV_V_CTL_1 = I915_READ(TV_V_CTL_1);
|
|
- tv_priv->save_TV_V_CTL_2 = I915_READ(TV_V_CTL_2);
|
|
- tv_priv->save_TV_V_CTL_3 = I915_READ(TV_V_CTL_3);
|
|
- tv_priv->save_TV_V_CTL_4 = I915_READ(TV_V_CTL_4);
|
|
- tv_priv->save_TV_V_CTL_5 = I915_READ(TV_V_CTL_5);
|
|
- tv_priv->save_TV_V_CTL_6 = I915_READ(TV_V_CTL_6);
|
|
- tv_priv->save_TV_V_CTL_7 = I915_READ(TV_V_CTL_7);
|
|
- tv_priv->save_TV_SC_CTL_1 = I915_READ(TV_SC_CTL_1);
|
|
- tv_priv->save_TV_SC_CTL_2 = I915_READ(TV_SC_CTL_2);
|
|
- tv_priv->save_TV_SC_CTL_3 = I915_READ(TV_SC_CTL_3);
|
|
-
|
|
- tv_priv->save_TV_CSC_Y = I915_READ(TV_CSC_Y);
|
|
- tv_priv->save_TV_CSC_Y2 = I915_READ(TV_CSC_Y2);
|
|
- tv_priv->save_TV_CSC_U = I915_READ(TV_CSC_U);
|
|
- tv_priv->save_TV_CSC_U2 = I915_READ(TV_CSC_U2);
|
|
- tv_priv->save_TV_CSC_V = I915_READ(TV_CSC_V);
|
|
- tv_priv->save_TV_CSC_V2 = I915_READ(TV_CSC_V2);
|
|
- tv_priv->save_TV_CLR_KNOBS = I915_READ(TV_CLR_KNOBS);
|
|
- tv_priv->save_TV_CLR_LEVEL = I915_READ(TV_CLR_LEVEL);
|
|
- tv_priv->save_TV_WIN_POS = I915_READ(TV_WIN_POS);
|
|
- tv_priv->save_TV_WIN_SIZE = I915_READ(TV_WIN_SIZE);
|
|
- tv_priv->save_TV_FILTER_CTL_1 = I915_READ(TV_FILTER_CTL_1);
|
|
- tv_priv->save_TV_FILTER_CTL_2 = I915_READ(TV_FILTER_CTL_2);
|
|
- tv_priv->save_TV_FILTER_CTL_3 = I915_READ(TV_FILTER_CTL_3);
|
|
-
|
|
- for (i = 0; i < 60; i++)
|
|
- tv_priv->save_TV_H_LUMA[i] = I915_READ(TV_H_LUMA_0 + (i <<2));
|
|
- for (i = 0; i < 60; i++)
|
|
- tv_priv->save_TV_H_CHROMA[i] = I915_READ(TV_H_CHROMA_0 + (i <<2));
|
|
- for (i = 0; i < 43; i++)
|
|
- tv_priv->save_TV_V_LUMA[i] = I915_READ(TV_V_LUMA_0 + (i <<2));
|
|
- for (i = 0; i < 43; i++)
|
|
- tv_priv->save_TV_V_CHROMA[i] = I915_READ(TV_V_CHROMA_0 + (i <<2));
|
|
-
|
|
- tv_priv->save_TV_DAC = I915_READ(TV_DAC);
|
|
- tv_priv->save_TV_CTL = I915_READ(TV_CTL);
|
|
-}
|
|
-
|
|
-static void
|
|
-intel_tv_restore(struct drm_connector *connector)
|
|
-{
|
|
- struct drm_device *dev = connector->dev;
|
|
- struct drm_i915_private *dev_priv = dev->dev_private;
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
- struct intel_tv_priv *tv_priv = intel_output->dev_priv;
|
|
- struct drm_crtc *crtc = connector->encoder->crtc;
|
|
- struct intel_crtc *intel_crtc;
|
|
- int i;
|
|
-
|
|
- /* FIXME: No CRTC? */
|
|
- if (!crtc)
|
|
- return;
|
|
-
|
|
- intel_crtc = to_intel_crtc(crtc);
|
|
- I915_WRITE(TV_H_CTL_1, tv_priv->save_TV_H_CTL_1);
|
|
- I915_WRITE(TV_H_CTL_2, tv_priv->save_TV_H_CTL_2);
|
|
- I915_WRITE(TV_H_CTL_3, tv_priv->save_TV_H_CTL_3);
|
|
- I915_WRITE(TV_V_CTL_1, tv_priv->save_TV_V_CTL_1);
|
|
- I915_WRITE(TV_V_CTL_2, tv_priv->save_TV_V_CTL_2);
|
|
- I915_WRITE(TV_V_CTL_3, tv_priv->save_TV_V_CTL_3);
|
|
- I915_WRITE(TV_V_CTL_4, tv_priv->save_TV_V_CTL_4);
|
|
- I915_WRITE(TV_V_CTL_5, tv_priv->save_TV_V_CTL_5);
|
|
- I915_WRITE(TV_V_CTL_6, tv_priv->save_TV_V_CTL_6);
|
|
- I915_WRITE(TV_V_CTL_7, tv_priv->save_TV_V_CTL_7);
|
|
- I915_WRITE(TV_SC_CTL_1, tv_priv->save_TV_SC_CTL_1);
|
|
- I915_WRITE(TV_SC_CTL_2, tv_priv->save_TV_SC_CTL_2);
|
|
- I915_WRITE(TV_SC_CTL_3, tv_priv->save_TV_SC_CTL_3);
|
|
-
|
|
- I915_WRITE(TV_CSC_Y, tv_priv->save_TV_CSC_Y);
|
|
- I915_WRITE(TV_CSC_Y2, tv_priv->save_TV_CSC_Y2);
|
|
- I915_WRITE(TV_CSC_U, tv_priv->save_TV_CSC_U);
|
|
- I915_WRITE(TV_CSC_U2, tv_priv->save_TV_CSC_U2);
|
|
- I915_WRITE(TV_CSC_V, tv_priv->save_TV_CSC_V);
|
|
- I915_WRITE(TV_CSC_V2, tv_priv->save_TV_CSC_V2);
|
|
- I915_WRITE(TV_CLR_KNOBS, tv_priv->save_TV_CLR_KNOBS);
|
|
- I915_WRITE(TV_CLR_LEVEL, tv_priv->save_TV_CLR_LEVEL);
|
|
-
|
|
- {
|
|
- int pipeconf_reg = (intel_crtc->pipe == 0) ?
|
|
- PIPEACONF : PIPEBCONF;
|
|
- int dspcntr_reg = (intel_crtc->plane == 0) ?
|
|
- DSPACNTR : DSPBCNTR;
|
|
- int pipeconf = I915_READ(pipeconf_reg);
|
|
- int dspcntr = I915_READ(dspcntr_reg);
|
|
- int dspbase_reg = (intel_crtc->plane == 0) ?
|
|
- DSPAADDR : DSPBADDR;
|
|
- /* Pipe must be off here */
|
|
- I915_WRITE(dspcntr_reg, dspcntr & ~DISPLAY_PLANE_ENABLE);
|
|
- /* Flush the plane changes */
|
|
- I915_WRITE(dspbase_reg, I915_READ(dspbase_reg));
|
|
-
|
|
- if (!IS_I9XX(dev)) {
|
|
- /* Wait for vblank for the disable to take effect */
|
|
- intel_wait_for_vblank(dev);
|
|
- }
|
|
-
|
|
- I915_WRITE(pipeconf_reg, pipeconf & ~PIPEACONF_ENABLE);
|
|
- /* Wait for vblank for the disable to take effect. */
|
|
- intel_wait_for_vblank(dev);
|
|
-
|
|
- /* Filter ctl must be set before TV_WIN_SIZE */
|
|
- I915_WRITE(TV_FILTER_CTL_1, tv_priv->save_TV_FILTER_CTL_1);
|
|
- I915_WRITE(TV_FILTER_CTL_2, tv_priv->save_TV_FILTER_CTL_2);
|
|
- I915_WRITE(TV_FILTER_CTL_3, tv_priv->save_TV_FILTER_CTL_3);
|
|
- I915_WRITE(TV_WIN_POS, tv_priv->save_TV_WIN_POS);
|
|
- I915_WRITE(TV_WIN_SIZE, tv_priv->save_TV_WIN_SIZE);
|
|
- I915_WRITE(pipeconf_reg, pipeconf);
|
|
- I915_WRITE(dspcntr_reg, dspcntr);
|
|
- /* Flush the plane changes */
|
|
- I915_WRITE(dspbase_reg, I915_READ(dspbase_reg));
|
|
- }
|
|
-
|
|
- for (i = 0; i < 60; i++)
|
|
- I915_WRITE(TV_H_LUMA_0 + (i <<2), tv_priv->save_TV_H_LUMA[i]);
|
|
- for (i = 0; i < 60; i++)
|
|
- I915_WRITE(TV_H_CHROMA_0 + (i <<2), tv_priv->save_TV_H_CHROMA[i]);
|
|
- for (i = 0; i < 43; i++)
|
|
- I915_WRITE(TV_V_LUMA_0 + (i <<2), tv_priv->save_TV_V_LUMA[i]);
|
|
- for (i = 0; i < 43; i++)
|
|
- I915_WRITE(TV_V_CHROMA_0 + (i <<2), tv_priv->save_TV_V_CHROMA[i]);
|
|
-
|
|
- I915_WRITE(TV_DAC, tv_priv->save_TV_DAC);
|
|
- I915_WRITE(TV_CTL, tv_priv->save_TV_CTL);
|
|
-}
|
|
-
|
|
static const struct tv_mode *
|
|
intel_tv_mode_lookup (char *tv_format)
|
|
{
|
|
@@ -1068,9 +931,9 @@ intel_tv_mode_lookup (char *tv_format)
|
|
}
|
|
|
|
static const struct tv_mode *
|
|
-intel_tv_mode_find (struct intel_output *intel_output)
|
|
+intel_tv_mode_find (struct intel_encoder *intel_encoder)
|
|
{
|
|
- struct intel_tv_priv *tv_priv = intel_output->dev_priv;
|
|
+ struct intel_tv_priv *tv_priv = intel_encoder->dev_priv;
|
|
|
|
return intel_tv_mode_lookup(tv_priv->tv_format);
|
|
}
|
|
@@ -1078,8 +941,9 @@ intel_tv_mode_find (struct intel_output *intel_output)
|
|
static enum drm_mode_status
|
|
intel_tv_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode)
|
|
{
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
- const struct tv_mode *tv_mode = intel_tv_mode_find(intel_output);
|
|
+ struct drm_encoder *encoder = intel_attached_encoder(connector);
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ const struct tv_mode *tv_mode = intel_tv_mode_find(intel_encoder);
|
|
|
|
/* Ensure TV refresh is close to desired refresh */
|
|
if (tv_mode && abs(tv_mode->refresh - drm_mode_vrefresh(mode) * 1000)
|
|
@@ -1095,8 +959,8 @@ intel_tv_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
|
|
{
|
|
struct drm_device *dev = encoder->dev;
|
|
struct drm_mode_config *drm_config = &dev->mode_config;
|
|
- struct intel_output *intel_output = enc_to_intel_output(encoder);
|
|
- const struct tv_mode *tv_mode = intel_tv_mode_find (intel_output);
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ const struct tv_mode *tv_mode = intel_tv_mode_find (intel_encoder);
|
|
struct drm_encoder *other_encoder;
|
|
|
|
if (!tv_mode)
|
|
@@ -1121,9 +985,9 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
struct drm_crtc *crtc = encoder->crtc;
|
|
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
|
|
- struct intel_output *intel_output = enc_to_intel_output(encoder);
|
|
- struct intel_tv_priv *tv_priv = intel_output->dev_priv;
|
|
- const struct tv_mode *tv_mode = intel_tv_mode_find(intel_output);
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ struct intel_tv_priv *tv_priv = intel_encoder->dev_priv;
|
|
+ const struct tv_mode *tv_mode = intel_tv_mode_find(intel_encoder);
|
|
u32 tv_ctl;
|
|
u32 hctl1, hctl2, hctl3;
|
|
u32 vctl1, vctl2, vctl3, vctl4, vctl5, vctl6, vctl7;
|
|
@@ -1360,9 +1224,9 @@ static const struct drm_display_mode reported_modes[] = {
|
|
* \return false if TV is disconnected.
|
|
*/
|
|
static int
|
|
-intel_tv_detect_type (struct drm_crtc *crtc, struct intel_output *intel_output)
|
|
+intel_tv_detect_type (struct drm_crtc *crtc, struct intel_encoder *intel_encoder)
|
|
{
|
|
- struct drm_encoder *encoder = &intel_output->enc;
|
|
+ struct drm_encoder *encoder = &intel_encoder->enc;
|
|
struct drm_device *dev = encoder->dev;
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
unsigned long irqflags;
|
|
@@ -1441,9 +1305,10 @@ intel_tv_detect_type (struct drm_crtc *crtc, struct intel_output *intel_output)
|
|
*/
|
|
static void intel_tv_find_better_format(struct drm_connector *connector)
|
|
{
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
- struct intel_tv_priv *tv_priv = intel_output->dev_priv;
|
|
- const struct tv_mode *tv_mode = intel_tv_mode_find(intel_output);
|
|
+ struct drm_encoder *encoder = intel_attached_encoder(connector);
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ struct intel_tv_priv *tv_priv = intel_encoder->dev_priv;
|
|
+ const struct tv_mode *tv_mode = intel_tv_mode_find(intel_encoder);
|
|
int i;
|
|
|
|
if ((tv_priv->type == DRM_MODE_CONNECTOR_Component) ==
|
|
@@ -1475,9 +1340,9 @@ intel_tv_detect(struct drm_connector *connector)
|
|
{
|
|
struct drm_crtc *crtc;
|
|
struct drm_display_mode mode;
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
- struct intel_tv_priv *tv_priv = intel_output->dev_priv;
|
|
- struct drm_encoder *encoder = &intel_output->enc;
|
|
+ struct drm_encoder *encoder = intel_attached_encoder(connector);
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ struct intel_tv_priv *tv_priv = intel_encoder->dev_priv;
|
|
int dpms_mode;
|
|
int type = tv_priv->type;
|
|
|
|
@@ -1485,12 +1350,14 @@ intel_tv_detect(struct drm_connector *connector)
|
|
drm_mode_set_crtcinfo(&mode, CRTC_INTERLACE_HALVE_V);
|
|
|
|
if (encoder->crtc && encoder->crtc->enabled) {
|
|
- type = intel_tv_detect_type(encoder->crtc, intel_output);
|
|
+ type = intel_tv_detect_type(encoder->crtc, intel_encoder);
|
|
} else {
|
|
- crtc = intel_get_load_detect_pipe(intel_output, &mode, &dpms_mode);
|
|
+ crtc = intel_get_load_detect_pipe(intel_encoder, connector,
|
|
+ &mode, &dpms_mode);
|
|
if (crtc) {
|
|
- type = intel_tv_detect_type(crtc, intel_output);
|
|
- intel_release_load_detect_pipe(intel_output, dpms_mode);
|
|
+ type = intel_tv_detect_type(crtc, intel_encoder);
|
|
+ intel_release_load_detect_pipe(intel_encoder, connector,
|
|
+ dpms_mode);
|
|
} else
|
|
type = -1;
|
|
}
|
|
@@ -1525,8 +1392,9 @@ static void
|
|
intel_tv_chose_preferred_modes(struct drm_connector *connector,
|
|
struct drm_display_mode *mode_ptr)
|
|
{
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
- const struct tv_mode *tv_mode = intel_tv_mode_find(intel_output);
|
|
+ struct drm_encoder *encoder = intel_attached_encoder(connector);
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ const struct tv_mode *tv_mode = intel_tv_mode_find(intel_encoder);
|
|
|
|
if (tv_mode->nbr_end < 480 && mode_ptr->vdisplay == 480)
|
|
mode_ptr->type |= DRM_MODE_TYPE_PREFERRED;
|
|
@@ -1550,8 +1418,9 @@ static int
|
|
intel_tv_get_modes(struct drm_connector *connector)
|
|
{
|
|
struct drm_display_mode *mode_ptr;
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
- const struct tv_mode *tv_mode = intel_tv_mode_find(intel_output);
|
|
+ struct drm_encoder *encoder = intel_attached_encoder(connector);
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ const struct tv_mode *tv_mode = intel_tv_mode_find(intel_encoder);
|
|
int j, count = 0;
|
|
u64 tmp;
|
|
|
|
@@ -1604,11 +1473,9 @@ intel_tv_get_modes(struct drm_connector *connector)
|
|
static void
|
|
intel_tv_destroy (struct drm_connector *connector)
|
|
{
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
-
|
|
drm_sysfs_connector_remove(connector);
|
|
drm_connector_cleanup(connector);
|
|
- kfree(intel_output);
|
|
+ kfree(connector);
|
|
}
|
|
|
|
|
|
@@ -1617,9 +1484,9 @@ intel_tv_set_property(struct drm_connector *connector, struct drm_property *prop
|
|
uint64_t val)
|
|
{
|
|
struct drm_device *dev = connector->dev;
|
|
- struct intel_output *intel_output = to_intel_output(connector);
|
|
- struct intel_tv_priv *tv_priv = intel_output->dev_priv;
|
|
- struct drm_encoder *encoder = &intel_output->enc;
|
|
+ struct drm_encoder *encoder = intel_attached_encoder(connector);
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+ struct intel_tv_priv *tv_priv = intel_encoder->dev_priv;
|
|
struct drm_crtc *crtc = encoder->crtc;
|
|
int ret = 0;
|
|
bool changed = false;
|
|
@@ -1676,8 +1543,6 @@ static const struct drm_encoder_helper_funcs intel_tv_helper_funcs = {
|
|
|
|
static const struct drm_connector_funcs intel_tv_connector_funcs = {
|
|
.dpms = drm_helper_connector_dpms,
|
|
- .save = intel_tv_save,
|
|
- .restore = intel_tv_restore,
|
|
.detect = intel_tv_detect,
|
|
.destroy = intel_tv_destroy,
|
|
.set_property = intel_tv_set_property,
|
|
@@ -1687,12 +1552,15 @@ static const struct drm_connector_funcs intel_tv_connector_funcs = {
|
|
static const struct drm_connector_helper_funcs intel_tv_connector_helper_funcs = {
|
|
.mode_valid = intel_tv_mode_valid,
|
|
.get_modes = intel_tv_get_modes,
|
|
- .best_encoder = intel_best_encoder,
|
|
+ .best_encoder = intel_attached_encoder,
|
|
};
|
|
|
|
static void intel_tv_enc_destroy(struct drm_encoder *encoder)
|
|
{
|
|
+ struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
|
|
+
|
|
drm_encoder_cleanup(encoder);
|
|
+ kfree(intel_encoder);
|
|
}
|
|
|
|
static const struct drm_encoder_funcs intel_tv_enc_funcs = {
|
|
@@ -1740,7 +1608,8 @@ intel_tv_init(struct drm_device *dev)
|
|
{
|
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
struct drm_connector *connector;
|
|
- struct intel_output *intel_output;
|
|
+ struct intel_encoder *intel_encoder;
|
|
+ struct intel_connector *intel_connector;
|
|
struct intel_tv_priv *tv_priv;
|
|
u32 tv_dac_on, tv_dac_off, save_tv_dac;
|
|
char **tv_format_names;
|
|
@@ -1780,28 +1649,34 @@ intel_tv_init(struct drm_device *dev)
|
|
(tv_dac_off & TVDAC_STATE_CHG_EN) != 0)
|
|
return;
|
|
|
|
- intel_output = kzalloc(sizeof(struct intel_output) +
|
|
+ intel_encoder = kzalloc(sizeof(struct intel_encoder) +
|
|
sizeof(struct intel_tv_priv), GFP_KERNEL);
|
|
- if (!intel_output) {
|
|
+ if (!intel_encoder) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
|
|
+ if (!intel_connector) {
|
|
+ kfree(intel_encoder);
|
|
return;
|
|
}
|
|
|
|
- connector = &intel_output->base;
|
|
+ connector = &intel_connector->base;
|
|
|
|
drm_connector_init(dev, connector, &intel_tv_connector_funcs,
|
|
DRM_MODE_CONNECTOR_SVIDEO);
|
|
|
|
- drm_encoder_init(dev, &intel_output->enc, &intel_tv_enc_funcs,
|
|
+ drm_encoder_init(dev, &intel_encoder->enc, &intel_tv_enc_funcs,
|
|
DRM_MODE_ENCODER_TVDAC);
|
|
|
|
- drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc);
|
|
- tv_priv = (struct intel_tv_priv *)(intel_output + 1);
|
|
- intel_output->type = INTEL_OUTPUT_TVOUT;
|
|
- intel_output->crtc_mask = (1 << 0) | (1 << 1);
|
|
- intel_output->clone_mask = (1 << INTEL_TV_CLONE_BIT);
|
|
- intel_output->enc.possible_crtcs = ((1 << 0) | (1 << 1));
|
|
- intel_output->enc.possible_clones = (1 << INTEL_OUTPUT_TVOUT);
|
|
- intel_output->dev_priv = tv_priv;
|
|
+ drm_mode_connector_attach_encoder(&intel_connector->base, &intel_encoder->enc);
|
|
+ tv_priv = (struct intel_tv_priv *)(intel_encoder + 1);
|
|
+ intel_encoder->type = INTEL_OUTPUT_TVOUT;
|
|
+ intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
|
|
+ intel_encoder->clone_mask = (1 << INTEL_TV_CLONE_BIT);
|
|
+ intel_encoder->enc.possible_crtcs = ((1 << 0) | (1 << 1));
|
|
+ intel_encoder->enc.possible_clones = (1 << INTEL_OUTPUT_TVOUT);
|
|
+ intel_encoder->dev_priv = tv_priv;
|
|
tv_priv->type = DRM_MODE_CONNECTOR_Unknown;
|
|
|
|
/* BIOS margin values */
|
|
@@ -1812,7 +1687,7 @@ intel_tv_init(struct drm_device *dev)
|
|
|
|
tv_priv->tv_format = kstrdup(tv_modes[initial_mode].name, GFP_KERNEL);
|
|
|
|
- drm_encoder_helper_add(&intel_output->enc, &intel_tv_helper_funcs);
|
|
+ drm_encoder_helper_add(&intel_encoder->enc, &intel_tv_helper_funcs);
|
|
drm_connector_helper_add(connector, &intel_tv_connector_helper_funcs);
|
|
connector->interlace_allowed = false;
|
|
connector->doublescan_allowed = false;
|
|
diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h
|
|
--- a/include/drm/drm_pciids.h
|
|
+++ b/include/drm/drm_pciids.h
|
|
@@ -558,4 +558,5 @@
|
|
{0x8086, 0x35e8, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \
|
|
{0x8086, 0x0042, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \
|
|
{0x8086, 0x0046, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \
|
|
+ {0x8086, 0x0102, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \
|
|
{0, 0, 0}
|