From 5973c7ee519e2a240c68b290a1836bdb25ed3701 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 15 Nov 2012 11:32:16 +0000 Subject: drm: Introduce drm_mm_create_block() To be used later by i915 to preallocate exact blocks of space from the range manager. Signed-off-by: Chris Wilson Cc: Dave Airlie Acked-by: Dave Airlie Cc: dri-devel@lists.freedesktop.org Signed-off-by: Daniel Vetter --- include/drm/drm_mm.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include') diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h index 06d7f798a08..4020f9661c3 100644 --- a/include/drm/drm_mm.h +++ b/include/drm/drm_mm.h @@ -102,6 +102,10 @@ static inline bool drm_mm_initialized(struct drm_mm *mm) /* * Basic range manager support (drm_mm.c) */ +extern struct drm_mm_node *drm_mm_create_block(struct drm_mm *mm, + unsigned long start, + unsigned long size, + bool atomic); extern struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *node, unsigned long size, unsigned alignment, -- cgit v1.2.3-18-g5258 From 9e8944ab564f2e3dde90a518cd32048c58918608 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 15 Nov 2012 11:32:17 +0000 Subject: drm: Introduce an iterator over holes in the drm_mm range manager This will be used i915 in forthcoming patches in order to measure the largest contiguous chunk of memory available for enabling chipset features. v2: Try to make the macro marginally safer and more readable by not depending upon the drm_mm_hole_node_end() being non-zero. Note that we need to open code list_for_each() in order to update the hole_start, hole_end variable on each iteration and keep the macro sane. v3: Tidy up few BUG_ONs that fell foul of adding additional tests to drm_mm_hole_node_start(). Signed-off-by: Chris Wilson Cc: Dave Airlie Acked-by: Dave Airlie Cc: dri-devel@lists.freedesktop.org Reviewed-by: Ben Widawsky Signed-off-by: Daniel Vetter --- include/drm/drm_mm.h | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'include') diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h index 4020f9661c3..cd453653f63 100644 --- a/include/drm/drm_mm.h +++ b/include/drm/drm_mm.h @@ -89,6 +89,29 @@ static inline bool drm_mm_initialized(struct drm_mm *mm) { return mm->hole_stack.next; } + +static inline unsigned long __drm_mm_hole_node_start(struct drm_mm_node *hole_node) +{ + return hole_node->start + hole_node->size; +} + +static inline unsigned long drm_mm_hole_node_start(struct drm_mm_node *hole_node) +{ + BUG_ON(!hole_node->hole_follows); + return __drm_mm_hole_node_start(hole_node); +} + +static inline unsigned long __drm_mm_hole_node_end(struct drm_mm_node *hole_node) +{ + return list_entry(hole_node->node_list.next, + struct drm_mm_node, node_list)->start; +} + +static inline unsigned long drm_mm_hole_node_end(struct drm_mm_node *hole_node) +{ + return __drm_mm_hole_node_end(hole_node); +} + #define drm_mm_for_each_node(entry, mm) list_for_each_entry(entry, \ &(mm)->head_node.node_list, \ node_list) @@ -99,6 +122,19 @@ static inline bool drm_mm_initialized(struct drm_mm *mm) entry != NULL; entry = next, \ next = entry ? list_entry(entry->node_list.next, \ struct drm_mm_node, node_list) : NULL) \ + +/* Note that we need to unroll list_for_each_entry in order to inline + * setting hole_start and hole_end on each iteration and keep the + * macro sane. + */ +#define drm_mm_for_each_hole(entry, mm, hole_start, hole_end) \ + for (entry = list_entry((mm)->hole_stack.next, struct drm_mm_node, hole_stack); \ + &entry->hole_stack != &(mm)->hole_stack ? \ + hole_start = drm_mm_hole_node_start(entry), \ + hole_end = drm_mm_hole_node_end(entry), \ + 1 : 0; \ + entry = list_entry(entry->hole_stack.next, struct drm_mm_node, hole_stack)) + /* * Basic range manager support (drm_mm.c) */ -- cgit v1.2.3-18-g5258 From 06e5598fce5ce89fe8bf081398296e5b08d993dd Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Tue, 18 Dec 2012 10:31:26 -0800 Subject: drm/i915: Move GSM mapping into dev_priv This removes an unused field from the AGP structure and moves it into the dev_priv structure (with a slightly better name). This builds upon the kill-agp series already merged. GSM is a well defined term in the bspec: GSM: Graphics Stolen Memory GTT stolen space is defined for storage of the GFX GTT entries in physical memory. IA can not access GSM directly , it can only access via GTTMMADR. GT can access GSM directly or through GTTMMADR. This is not the entire stolen space. Signed-off-by: Ben Widawsky Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- include/drm/intel-gtt.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'include') diff --git a/include/drm/intel-gtt.h b/include/drm/intel-gtt.h index 6eb76a1f11a..3e3a166a269 100644 --- a/include/drm/intel-gtt.h +++ b/include/drm/intel-gtt.h @@ -18,8 +18,6 @@ struct intel_gtt { /* Share the scratch page dma with ppgtts. */ dma_addr_t scratch_page_dma; struct page *scratch_page; - /* for ppgtt PDE access */ - u32 __iomem *gtt; /* needed for ioremap in drm/i915 */ phys_addr_t gma_bus_addr; } *intel_gtt_get(void); -- cgit v1.2.3-18-g5258 From 63d0a4195560362e2e00a3ad38fc331d34e1da9b Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 15 Jan 2013 14:56:37 +0100 Subject: drm/ttm: remove lru_lock around ttm_bo_reserve There should no longer be assumptions that reserve will always succeed with the lru lock held, so we can safely break the whole atomic reserve/lru thing. As a bonus this fixes most lockdep annotations for reservations. Signed-off-by: Maarten Lankhorst Reviewed-by: Jerome Glisse --- include/drm/ttm/ttm_bo_driver.h | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) (limited to 'include') diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index e3a43a47d78..6fff43222e2 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -790,16 +790,7 @@ extern void ttm_mem_io_unlock(struct ttm_mem_type_manager *man); * to make room for a buffer already reserved. (Buffers are reserved before * they are evicted). The following algorithm prevents such deadlocks from * occurring: - * 1) Buffers are reserved with the lru spinlock held. Upon successful - * reservation they are removed from the lru list. This stops a reserved buffer - * from being evicted. However the lru spinlock is released between the time - * a buffer is selected for eviction and the time it is reserved. - * Therefore a check is made when a buffer is reserved for eviction, that it - * is still the first buffer in the lru list, before it is removed from the - * list. @check_lru == 1 forces this check. If it fails, the function returns - * -EINVAL, and the caller should then choose a new buffer to evict and repeat - * the procedure. - * 2) Processes attempting to reserve multiple buffers other than for eviction, + * Processes attempting to reserve multiple buffers other than for eviction, * (typically execbuf), should first obtain a unique 32-bit * validation sequence number, * and call this function with @use_sequence == 1 and @sequence == the unique @@ -832,7 +823,7 @@ extern int ttm_bo_reserve(struct ttm_buffer_object *bo, /** - * ttm_bo_reserve_locked: + * ttm_bo_reserve_nolru: * * @bo: A pointer to a struct ttm_buffer_object. * @interruptible: Sleep interruptible if waiting. @@ -840,9 +831,7 @@ extern int ttm_bo_reserve(struct ttm_buffer_object *bo, * @use_sequence: If @bo is already reserved, Only sleep waiting for * it to become unreserved if @sequence < (@bo)->sequence. * - * Must be called with struct ttm_bo_global::lru_lock held, - * and will not remove reserved buffers from the lru lists. - * The function may release the LRU spinlock if it needs to sleep. + * Will not remove reserved buffers from the lru lists. * Otherwise identical to ttm_bo_reserve. * * Returns: @@ -855,7 +844,7 @@ extern int ttm_bo_reserve(struct ttm_buffer_object *bo, * -EDEADLK: Bo already reserved using @sequence. This error code will only * be returned if @use_sequence is set to true. */ -extern int ttm_bo_reserve_locked(struct ttm_buffer_object *bo, +extern int ttm_bo_reserve_nolru(struct ttm_buffer_object *bo, bool interruptible, bool no_wait, bool use_sequence, uint32_t sequence); -- cgit v1.2.3-18-g5258 From 5e45d7dfd74100d622f9cdc70bfd1f9fae1671de Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 15 Jan 2013 14:57:05 +0100 Subject: drm/ttm: add ttm_bo_reserve_slowpath Instead of dropping everything, waiting for the bo to be unreserved and trying over, a better strategy would be to do a blocking wait. This can be mapped a lot better to a mutex_lock-like call. Signed-off-by: Maarten Lankhorst Reviewed-by: Jerome Glisse --- include/drm/ttm/ttm_bo_driver.h | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'include') diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index 6fff43222e2..5af71af6bf8 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -821,6 +821,36 @@ extern int ttm_bo_reserve(struct ttm_buffer_object *bo, bool interruptible, bool no_wait, bool use_sequence, uint32_t sequence); +/** + * ttm_bo_reserve_slowpath_nolru: + * @bo: A pointer to a struct ttm_buffer_object. + * @interruptible: Sleep interruptible if waiting. + * @sequence: Set (@bo)->sequence to this value after lock + * + * This is called after ttm_bo_reserve returns -EAGAIN and we backed off + * from all our other reservations. Because there are no other reservations + * held by us, this function cannot deadlock any more. + * + * Will not remove reserved buffers from the lru lists. + * Otherwise identical to ttm_bo_reserve_slowpath. + */ +extern int ttm_bo_reserve_slowpath_nolru(struct ttm_buffer_object *bo, + bool interruptible, + uint32_t sequence); + + +/** + * ttm_bo_reserve_slowpath: + * @bo: A pointer to a struct ttm_buffer_object. + * @interruptible: Sleep interruptible if waiting. + * @sequence: Set (@bo)->sequence to this value after lock + * + * This is called after ttm_bo_reserve returns -EAGAIN and we backed off + * from all our other reservations. Because there are no other reservations + * held by us, this function cannot deadlock any more. + */ +extern int ttm_bo_reserve_slowpath(struct ttm_buffer_object *bo, + bool interruptible, uint32_t sequence); /** * ttm_bo_reserve_nolru: -- cgit v1.2.3-18-g5258 From cc4c0c4de3c775be22072ec3251f2e581b63d9a0 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 15 Jan 2013 14:57:28 +0100 Subject: drm/ttm: unexport ttm_bo_wait_unreserved All legitimate users of this function outside ttm_bo.c are gone, now it's only an implementation detail. Signed-off-by: Maarten Lankhorst Reviewed-by: Jerome Glisse --- include/drm/ttm/ttm_bo_driver.h | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'include') diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index 5af71af6bf8..0fbd046e7c9 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -898,18 +898,6 @@ extern void ttm_bo_unreserve(struct ttm_buffer_object *bo); */ extern void ttm_bo_unreserve_locked(struct ttm_buffer_object *bo); -/** - * ttm_bo_wait_unreserved - * - * @bo: A pointer to a struct ttm_buffer_object. - * - * Wait for a struct ttm_buffer_object to become unreserved. - * This is typically used in the execbuf code to relax cpu-usage when - * a potential deadlock condition backoff. - */ -extern int ttm_bo_wait_unreserved(struct ttm_buffer_object *bo, - bool interruptible); - /* * ttm_bo_util.c */ -- cgit v1.2.3-18-g5258 From ed5982e6ce5f106abcbf071f80730db344a6da42 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 17 Jan 2013 22:23:36 +0100 Subject: drm/i915: Allow userspace to hint that the relocations were known Userspace is able to hint to the kernel that its command stream and auxiliary state buffers already hold the correct presumed addresses and so the relocation process may be skipped if the kernel does not need to move any buffers in preparation for the execbuffer. Thus for the common case where the allotment of buffers is static between batches, we can avoid the overhead of individually checking the relocation entries. Note that this requires userspace to supply the domain tracking and requests for workarounds itself that would otherwise be computed based upon the relocation entries. Using copywinwin10 as an example that is dependent upon emitting a lot of relocations (2 per operation), we see improvements of: c2d/gm45: 618000.0/sec to 632000.0/sec. i3-330m: 748000.0/sec to 830000.0/sec. (measured relative to a baseline with neither optimisations applied). Signed-off-by: Chris Wilson Reviewed-by: Imre Deak [danvet: Fixup merge conflict in userspace header due to different baseline trees.] Signed-off-by: Daniel Vetter --- include/uapi/drm/i915_drm.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'include') diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h index c4d2e9c7400..2430b6ad6a8 100644 --- a/include/uapi/drm/i915_drm.h +++ b/include/uapi/drm/i915_drm.h @@ -308,6 +308,7 @@ typedef struct drm_i915_irq_wait { #define I915_PARAM_RSVD_FOR_FUTURE_USE 22 #define I915_PARAM_HAS_SECURE_BATCHES 23 #define I915_PARAM_HAS_PINNED_BATCHES 24 +#define I915_PARAM_HAS_EXEC_NO_RELOC 25 typedef struct drm_i915_getparam { int param; @@ -628,7 +629,11 @@ struct drm_i915_gem_exec_object2 { __u64 offset; #define EXEC_OBJECT_NEEDS_FENCE (1<<0) +#define EXEC_OBJECT_NEEDS_GTT (1<<1) +#define EXEC_OBJECT_WRITE (1<<2) +#define __EXEC_OBJECT_UNKNOWN_FLAGS -(EXEC_OBJECT_WRITE<<1) __u64 flags; + __u64 rsvd1; __u64 rsvd2; }; @@ -687,6 +692,15 @@ struct drm_i915_gem_execbuffer2 { */ #define I915_EXEC_IS_PINNED (1<<10) +/** Provide a hint to the kernel that the command stream and auxilliary + * state buffers already holds the correct presumed addresses and so the + * relocation process may be skipped if no buffers need to be moved in + * preparation for the execbuffer. + */ +#define I915_EXEC_NO_RELOC (1<<11) + +#define __I915_EXEC_UNKNOWN_FLAGS -(I915_EXEC_NO_RELOC<<1) + #define I915_EXEC_CONTEXT_ID_MASK (0xffffffff) #define i915_execbuffer2_set_context_id(eb2, context) \ (eb2).rsvd1 = context & I915_EXEC_CONTEXT_ID_MASK -- cgit v1.2.3-18-g5258 From eef90ccb8a4d50b219a95cc53878ebb007315b32 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 8 Jan 2013 10:53:17 +0000 Subject: drm/i915: Use the reloc.handle as an index into the execbuffer array Using copywinwin10 as an example that is dependent upon emitting a lot of relocations (2 per operation), we see improvements of: c2d/gm45: 618000.0/sec to 623000.0/sec. i3-330m: 748000.0/sec to 789000.0/sec. (measured relative to a baseline with neither optimisations applied). Signed-off-by: Chris Wilson Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- include/uapi/drm/i915_drm.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h index 2430b6ad6a8..07d59419fe6 100644 --- a/include/uapi/drm/i915_drm.h +++ b/include/uapi/drm/i915_drm.h @@ -309,6 +309,7 @@ typedef struct drm_i915_irq_wait { #define I915_PARAM_HAS_SECURE_BATCHES 23 #define I915_PARAM_HAS_PINNED_BATCHES 24 #define I915_PARAM_HAS_EXEC_NO_RELOC 25 +#define I915_PARAM_HAS_EXEC_HANDLE_LUT 26 typedef struct drm_i915_getparam { int param; @@ -699,7 +700,12 @@ struct drm_i915_gem_execbuffer2 { */ #define I915_EXEC_NO_RELOC (1<<11) -#define __I915_EXEC_UNKNOWN_FLAGS -(I915_EXEC_NO_RELOC<<1) +/** Use the reloc.handle as an index into the exec object array rather + * than as the per-file handle. + */ +#define I915_EXEC_HANDLE_LUT (1<<12) + +#define __I915_EXEC_UNKNOWN_FLAGS -(I915_EXEC_HANDLE_LUT<<1) #define I915_EXEC_CONTEXT_ID_MASK (0xffffffff) #define i915_execbuffer2_set_context_id(eb2, context) \ -- cgit v1.2.3-18-g5258 From b1edd6a6ecd436af33f210a5c75e0249466fd200 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 17 Jan 2013 16:31:30 +0200 Subject: drm/edid: Add drm_rgb_quant_range_selectable() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drm_rgb_quant_range_selectable() will report whether the monitor claims to support for RGB quantization range selection. The information can be found in the CEA Video capability block. v2: s/quantzation/quantization/ in the comment Reviewed-by: Paulo Zanoni Signed-off-by: Ville Syrjälä Acked-by: David Airlie Signed-off-by: Daniel Vetter --- include/drm/drm_crtc.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 00d78b5161c..30892dc9376 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -1033,6 +1033,7 @@ extern u8 *drm_find_cea_extension(struct edid *edid); extern u8 drm_match_cea_mode(struct drm_display_mode *to_match); extern bool drm_detect_hdmi_monitor(struct edid *edid); extern bool drm_detect_monitor_audio(struct edid *edid); +extern bool drm_rgb_quant_range_selectable(struct edid *edid); extern int drm_mode_page_flip_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); extern struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, -- cgit v1.2.3-18-g5258 From a81cc00c11ab6816fbcb7dd99a60b50e71765d25 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Fri, 18 Jan 2013 12:30:31 -0800 Subject: drm/i915: Cut out the infamous ILK w/a from AGP layer And, move it to where the rest of the logic is. There is some slight functionality changes. There was extra paranoid checks in AGP code making sure we never do idle maps on gen2 parts. That was not duplicated as the simple PCI id check should do the right thing. v2: use IS_GEN5 && IS_MOBILE check instead. For now, this is the same as IS_IRONLAKE_M but is more future proof. The workaround docs hint that more than one platform may be effected, but we've never seen such a platform in the wild. (Rodrigo, Daniel) Reviewed-by: Rodrigo Vivi (v1) Cc: Dave Airlie Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter --- include/drm/intel-gtt.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'include') diff --git a/include/drm/intel-gtt.h b/include/drm/intel-gtt.h index 3e3a166a269..1747aa095f4 100644 --- a/include/drm/intel-gtt.h +++ b/include/drm/intel-gtt.h @@ -13,8 +13,6 @@ struct intel_gtt { unsigned int gtt_mappable_entries; /* Whether i915 needs to use the dmar apis or not. */ unsigned int needs_dmar : 1; - /* Whether we idle the gpu before mapping/unmapping */ - unsigned int do_idle_maps : 1; /* Share the scratch page dma with ppgtts. */ dma_addr_t scratch_page_dma; struct page *scratch_page; -- cgit v1.2.3-18-g5258 From 9c61a32d31a55c8c6e590d83ae5645e14fde09f2 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Fri, 18 Jan 2013 12:30:32 -0800 Subject: drm/i915: Remove scratch page from shared We already had a mapping in both (minus the phys_addr in AGP). Reviewed-by: Rodrigo Vivi Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter --- include/drm/intel-gtt.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'include') diff --git a/include/drm/intel-gtt.h b/include/drm/intel-gtt.h index 1747aa095f4..c787ee4c4c0 100644 --- a/include/drm/intel-gtt.h +++ b/include/drm/intel-gtt.h @@ -13,9 +13,6 @@ struct intel_gtt { unsigned int gtt_mappable_entries; /* Whether i915 needs to use the dmar apis or not. */ unsigned int needs_dmar : 1; - /* Share the scratch page dma with ppgtts. */ - dma_addr_t scratch_page_dma; - struct page *scratch_page; /* needed for ioremap in drm/i915 */ phys_addr_t gma_bus_addr; } *intel_gtt_get(void); -- cgit v1.2.3-18-g5258 From 8d2e630899165d413ae8a2adc36846ac0b71bada Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Fri, 18 Jan 2013 12:30:33 -0800 Subject: drm/i915: Needs_dmar, not The reasoning behind our code taking two paths depending upon whether or not we may have been configured for IOMMU isn't clear to me. It should always be safe to use the pci mapping functions as they are designed to abstract the decision we were handling in i915. Aside from simpler code, removing another member for the intel_gtt struct is a nice motivation. I ran this by Chris, and he wasn't concerned about the extra kzalloc, and memory references vs. page_to_phys calculation in the case without IOMMU. v2: Update commit message v3: Remove needs_dmar addition from Zhenyu upstream This reverts (and then other stuff) commit 20652097dadd9a7fb4d652f25466299974bc78f9 Author: Zhenyu Wang Date: Thu Dec 13 23:47:47 2012 +0800 drm/i915: Fix missed needs_dmar setting Reviewed-by: Rodrigo Vivi (v2) Cc: Zhenyu Wang Signed-off-by: Ben Widawsky [danvet: Squash in follow-up fix to remove the bogus hunk which deleted the dma_mask configuration for gen6+.] Signed-off-by: Daniel Vetter --- include/drm/intel-gtt.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'include') diff --git a/include/drm/intel-gtt.h b/include/drm/intel-gtt.h index c787ee4c4c0..984105cddc5 100644 --- a/include/drm/intel-gtt.h +++ b/include/drm/intel-gtt.h @@ -11,8 +11,6 @@ struct intel_gtt { /* Part of the gtt that is mappable by the cpu, for those chips where * this is not the full gtt. */ unsigned int gtt_mappable_entries; - /* Whether i915 needs to use the dmar apis or not. */ - unsigned int needs_dmar : 1; /* needed for ioremap in drm/i915 */ phys_addr_t gma_bus_addr; } *intel_gtt_get(void); -- cgit v1.2.3-18-g5258 From e5c653777986b40e2986d2c918847fddbcba3a34 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Fri, 18 Jan 2013 12:30:34 -0800 Subject: agp/intel: Add gma_bus_addr It is no longer used in the i915 code, so isolate it from the shared struct. This was originally part of: commit 0e275518f325418d559c05327775bff894b237f7 Author: Ben Widawsky Date: Mon Jan 14 13:35:33 2013 -0800 agp/intel: decouple more of the agp-i915 sharing Reviewed-by: Rodrigo Vivi Signed-off-by: Ben Widawsky That commit had some other hunks which can't be used due to issues Daniel found in previous commits. Signed-off-by: Ben Widawsky [danvet: drop squash notice from the commit since it's imo ok to keep this one separate.] Signed-off-by: Daniel Vetter --- include/drm/intel-gtt.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'include') diff --git a/include/drm/intel-gtt.h b/include/drm/intel-gtt.h index 984105cddc5..769b6c79097 100644 --- a/include/drm/intel-gtt.h +++ b/include/drm/intel-gtt.h @@ -11,8 +11,6 @@ struct intel_gtt { /* Part of the gtt that is mappable by the cpu, for those chips where * this is not the full gtt. */ unsigned int gtt_mappable_entries; - /* needed for ioremap in drm/i915 */ - phys_addr_t gma_bus_addr; } *intel_gtt_get(void); int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev, -- cgit v1.2.3-18-g5258 From 8faf6b18a2a6bece008de1e6bb80f0c608e58483 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Sat, 1 Dec 2012 23:43:11 +0100 Subject: drm: review locking rules in drm_crtc.c - config_cleanup was confused: It claimed that callers need to hold the modeset lock, but the connector|encoder_cleanup helpers grabbed that themselves (note that crtc_cleanup did _not_ grab the modeset lock). Which resulted in all drivers _not_ hodling the lock. Since this is for single-threaded cleanup code, drop the requirement from docs and also drop the lock_grabbing from all _cleanup functions. - Kill the LOCKING section in the doctype, since clearly we're not good enough to keep them up-to-date. And misleading locking documentation is worse than useless (see e.g. the comment in the vmgfx driver about the cleanup mess). And since for most functions the very first line either grabs the lock or has a WARN_ON(!locked) the documentation doesn't really add anything. - Instead put in some effort into explaining the only two special cases a bit better: config_init and config_cleanup are both called from single-threaded setup/teardown code, so don't do any locking. It's the driver's job though to enforce this. - Where lacking, add a WARN_ON(!is_locked). Not many places though, since locking around fbdev setup/teardown is through-roughly screwed up, and so will break almost every single WARN annotation I've tried to add. - Add a drm_modeset_is_locked helper - the Grate Modset Locking Rework will use the compiler to assist in the big reorg by renaming the mode lock, so start encapsulating things. Unfortunately this ended up in the "wrong" header file since it needs the definition of struct drm_device. v2: Drop most WARNS again - we hit them all over the place, mostly in the setup and teardown sequences. And trying to fix it up leads to nice deadlocks, since the locking in the setup code is really inconsistent. Reviewed-by: Rob Clark Signed-off-by: Daniel Vetter --- include/drm/drmP.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include') diff --git a/include/drm/drmP.h b/include/drm/drmP.h index fad21c927a3..3c609abe8c8 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1276,6 +1276,11 @@ static inline int drm_device_is_unplugged(struct drm_device *dev) return ret; } +static inline bool drm_modeset_is_locked(struct drm_device *dev) +{ + return mutex_is_locked(&dev->mode_config.mutex); +} + /******************************************************************/ /** \name Internal function definitions */ /*@{*/ -- cgit v1.2.3-18-g5258 From 2d13b6796e420ed00389b7399a5d5ac7b1fed436 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 11 Dec 2012 13:47:23 +0100 Subject: drm: encapsulate crtc->set_config calls With refcounting we need to adjust framebuffer refcounts at each callsite - much easier to do if they all call the same little helper function. Reviewed-by: Rob Clark Signed-off-by: Daniel Vetter --- include/drm/drm_crtc.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 00d78b5161c..665289a68cc 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -985,6 +985,7 @@ extern int drm_mode_getcrtc(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int drm_mode_getconnector(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int drm_mode_set_config_internal(struct drm_mode_set *set); extern int drm_mode_setcrtc(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int drm_mode_getplane(struct drm_device *dev, -- cgit v1.2.3-18-g5258 From 848499032504b1defdebdcf930aa70bd01a45ac1 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Sun, 2 Dec 2012 00:28:11 +0100 Subject: drm: add drm_modeset_lock|unlock_all This is the first step towards introducing the new modeset locking scheme. The plan is to put helper functions into place at all the right places step-by-step, so that the final patch to switch on the new locking scheme doesn't need to touch every single driver. This helper here will serve as the shotgun solutions for all places where a more fine-grained locking isn't (yet) implemented. v2: Fixup kerneldoc for unlock_all. Reviewed-by: Rob Clark Signed-off-by: Daniel Vetter --- include/drm/drm_crtc.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include') diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 665289a68cc..9f0524d507f 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -842,6 +842,9 @@ struct drm_prop_enum_list { char *name; }; +extern void drm_modeset_lock_all(struct drm_device *dev); +extern void drm_modeset_unlock_all(struct drm_device *dev); + extern int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, const struct drm_crtc_funcs *funcs); -- cgit v1.2.3-18-g5258 From 29494c174dc4793ebd236aa522a2a1ed73b7180e Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Sun, 2 Dec 2012 02:18:25 +0100 Subject: drm: add per-crtc locks *drumroll* The basic idea is to protect per-crtc state which can change without touching the output configuration with separate mutexes, i.e. all the input side state to a crtc like framebuffers, cursor settings or plane configuration. Holding such a crtc lock gives a read-lock on all the other crtc state which can be changed by e.g. a modeset. All non-crtc state is still protected by the mode_config mutex. Callers that need to change modeset state of a crtc (e.g. dpms or set_mode) need to grab both the mode_config lock and nested within any crtc locks. Note that since there can only ever be one holder of the mode_config lock we can grab the subordinate crtc locks in any order (if we need to grab more than one of them). Lockdep can handle such nesting with the mutex_lock_nest_lock call correctly. With this functions that only touch connectors/encoders but not crtcs only need to take the mode_config lock. The biggest such case is the output probing, which means that we can now pageflip and move cursors while the output probe code is reading an edid. Most cases neatly fall into the three buckets: - Only touches connectors and similar output state and so only needs the mode_config lock. - Touches the global configuration and so needs all locks. - Only touches the crtc input side and so only needs the crtc lock. But a few cases that need special consideration: - Load detection which requires a crtc. The mode_config lock already prevents a modeset change, so we can use any unused crtc as we like to do load detection. The only thing to consider is that such temporary state changes don't leak out to userspace through ioctls that only take the crtc look (like a pageflip). Hence the load detect code needs to grab the crtc of any output pipes it touches (but only if it touches state used by the pageflip or cursor ioctls). - Atomic pageflip when moving planes. The first case is sane hw, where planes have a fixed association with crtcs - nothing needs to be done there. More insane^Wflexible hw needs to have plane->crtc mapping which is separately protect with a lock that nests within the crtc lock. If the plane is unused we can just assign it to the current crtc and continue. But if a plane is already in use by another crtc we can't just reassign it. Two solution present themselves: Either go back to a slow-path which takes all modeset locks, potentially incure quite a hefty delay. Or simply disallowing such changes in one atomic pageflip - in general the vblanks of two crtcs are not synced, so there's no sane way to atomically flip such plane changes accross more than one crtc. I'd heavily favour the later approach, going as far as mandating it as part of the ABI of such a new a nuclear pageflip. And if we _really_ want such semantics, we can always get them by introducing another pageflip mutex between the mode_config.mutex and the individual crtc locks. Pageflips crossing more than one crtc would then need to take that lock first, to lock out concurrent multi-crtc pageflips. - Optimized global modeset operations: We could just take the mode_config lock and then lazily lock all crtc which are affected by a modeset operation. This has the advantage that pageflip could continue unhampered on unaffected crtc. But if e.g. global resources like plls need to be reassigned and so affect unrelated crtcs we can still do that - nested locking works in any order. This patch just adds the locks and takes them in drm_modeset_lock_all, no real locking changes yet. v2: Need to initialize the new lock in crtc_init and lock it righ away, for otherwise the modeset_unlock_all below will try to unlock a not-locked mutex. Reviewed-by: Rob Clark Signed-off-by: Daniel Vetter --- include/drm/drm_crtc.h | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'include') diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 9f0524d507f..c89b1161f0b 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -390,6 +390,15 @@ struct drm_crtc { struct drm_device *dev; struct list_head head; + /** + * crtc mutex + * + * This provides a read lock for the overall crtc state (mode, dpms + * state, ...) and a write lock for everything which can be update + * without a full modeset (fb, cursor data, ...) + */ + struct mutex mutex; + struct drm_mode_object base; /* framebuffer the connector is currently bound to */ -- cgit v1.2.3-18-g5258 From 4b096ac10da0b63f09bd123b86fed8deb80646ce Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 10 Dec 2012 21:19:18 +0100 Subject: drm: revamp locking around fb creation/destruction Well, at least step 1. The goal here is that framebuffer objects can survive outside of the mode_config lock, with just a reference held as protection. The first step to get there is to introduce a special fb_lock which protects fb lookup, creation and destruction, to make them appear atomic. This new fb_lock can nest within the mode_config lock. But the idea is (once the reference counting part is completed) that we only quickly take that fb_lock to lookup a framebuffer and grab a reference, without any other locks involved. vmwgfx is the only driver which does framebuffer lookups itself, also wrap those calls to drm_mode_object_find with the new lock. Also protect the fb_list walking in i915 and omapdrm with the new lock. As a slight complication there's also the list of user-created fbs attached to the file private. The problem now is that at fclose() time we need to walk that list, eventually do a modeset call to remove the fb from active usage (and are required to be able to take the mode_config lock), but in the end we need to grab the new fb_lock to remove the fb from the list. The easiest solution is to add another mutex to protect this per-file list. Currently that new fbs_lock nests within the modeset locks and so appears redudant. But later patches will switch around this sequence so that taking the modeset locks in the fb destruction path is optional in the fastpath. Ultimately the goal is that addfb and rmfb do not require the mode_config lock, since otherwise they have the potential to introduce stalls in the pageflip sequence of a compositor (if the compositor e.g. switches to a fullscreen client or if it enables a plane). But that requires a few more steps and hoops to jump through. Note that framebuffer creation/destruction is now double-protected - once by the fb_lock and in parts by the idr_lock. The later would be unnecessariy if framebuffers would have their own idr allocator. But that's material for another patch (series). v2: Properly initialize the fb->filp_head list in _init, otherwise the newly added WARN to check whether the fb isn't on a fpriv list any more will fail for driver-private objects. v3: Fixup two error-case unlock bugs spotted by Richard Wilbur. Reviewed-by: Rob Clark Signed-off-by: Daniel Vetter --- include/drm/drmP.h | 8 ++++++++ include/drm/drm_crtc.h | 14 ++++++++++++++ 2 files changed, 22 insertions(+) (limited to 'include') diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 3c609abe8c8..e74731c1a91 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -446,7 +446,15 @@ struct drm_file { int is_master; /* this file private is a master for a minor */ struct drm_master *master; /* master this node is currently associated with N.B. not always minor->master */ + + /** + * fbs - List of framebuffers associated with this file. + * + * Protected by fbs_lock. Note that the fbs list holds a reference on + * the fb object to prevent it from untimely disappearing. + */ struct list_head fbs; + struct mutex fbs_lock; wait_queue_head_t event_wait; struct list_head event_list; diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index c89b1161f0b..c35a807d7e5 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -254,6 +254,10 @@ struct drm_framebuffer { * userspace perspective. */ struct kref refcount; + /* + * Place on the dev->mode_config.fb_list, access protected by + * dev->mode_config.fb_lock. + */ struct list_head head; struct drm_mode_object base; const struct drm_framebuffer_funcs *funcs; @@ -780,8 +784,18 @@ struct drm_mode_config { struct mutex idr_mutex; /* for IDR management */ struct idr crtc_idr; /* use this idr for all IDs, fb, crtc, connector, modes - just makes life easier */ /* this is limited to one for now */ + + + /** + * fb_lock - mutex to protect fb state + * + * Besides the global fb list his also protects the fbs list in the + * file_priv + */ + struct mutex fb_lock; int num_fb; struct list_head fb_list; + int num_connector; struct list_head connector_list; int num_encoder; -- cgit v1.2.3-18-g5258 From 786b99ed13223d8ac58a937dd348aead45eb8191 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Sun, 2 Dec 2012 21:53:40 +0100 Subject: drm: create drm_framebuffer_lookup And replace all fb lookups with it. Also add a WARN to drm_mode_object_find since that is now no longer the blessed interface to look up an fb. And add kerneldoc to both functions. This only updates all callsites, but immediately drops the acquired refence again. Hence all callers still rely on the fact that a mode fb can't disappear while they're holding the struct mutex. Subsequent patches will instate proper use of refcounts, and then rework the rmfb and unref code to no longer serialize fb destruction with the mode_config lock. We don't want that since otherwise a compositor might end up stalling for a few frames in rmfb. v2: Don't use kref_get_unless_zero - Greg KH doesn't like that kind of interface. Reviewed-by: Rob Clark Signed-off-by: Daniel Vetter --- include/drm/drm_crtc.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index c35a807d7e5..7dc1b31059d 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -958,6 +958,8 @@ extern void drm_framebuffer_set_object(struct drm_device *dev, extern int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb, const struct drm_framebuffer_funcs *funcs); +extern struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev, + uint32_t id); extern void drm_framebuffer_unreference(struct drm_framebuffer *fb); extern void drm_framebuffer_reference(struct drm_framebuffer *fb); extern void drm_framebuffer_remove(struct drm_framebuffer *fb); -- cgit v1.2.3-18-g5258 From 362063619cf67c2c2fc2eb90951b2623cbb69a7c Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 10 Dec 2012 20:42:17 +0100 Subject: drm: revamp framebuffer cleanup interfaces We have two classes of framebuffer - Created by the driver (atm only for fbdev), and the driver holds onto the last reference count until destruction. - Created by userspace and associated with a given fd. These framebuffers will be reaped when their assoiciated fb is closed. Now these two cases are set up differently, the framebuffers are on different lists and hence destruction needs to clean up different things. Also, for userspace framebuffers we remove them from any current usage, whereas for internal framebuffers it is assumed that the driver has done this already. Long story short, we need two different ways to cleanup such drivers. Three functions are involved in total: - drm_framebuffer_remove: Convenience function which removes the fb from all active usage and then drops the passed-in reference. - drm_framebuffer_unregister_private: Will remove driver-private framebuffers from relevant lists and drop the corresponding references. Should be called for driver-private framebuffers before dropping the last reference (or like for a lot of the drivers where the fbdev is embedded someplace else, before doing the cleanup manually). - drm_framebuffer_cleanup: Final cleanup for both classes of fbs, should be called by the driver's ->destroy callback once the last reference is gone. This patch just rolls out the new interfaces and updates all drivers (by adding calls to drm_framebuffer_unregister_private at all the right places)- no functional changes yet. Follow-on patches will move drm core code around and update the lifetime management for framebuffers, so that we are no longer required to keep framebuffers alive by locking mode_config.mutex. I've also updated the kerneldoc already. vmwgfx seems to again be a bit special, at least I haven't figured out how the fbdev support in that driver works. It smells like it's external though. v2: The i915 driver creates another private framebuffer in the load-detect code. Adjust its cleanup code, too. Reviewed-by: Rob Clark Signed-off-by: Daniel Vetter --- include/drm/drm_crtc.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 7dc1b31059d..66b2732f175 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -964,6 +964,7 @@ extern void drm_framebuffer_unreference(struct drm_framebuffer *fb); extern void drm_framebuffer_reference(struct drm_framebuffer *fb); extern void drm_framebuffer_remove(struct drm_framebuffer *fb); extern void drm_framebuffer_cleanup(struct drm_framebuffer *fb); +extern void drm_framebuffer_unregister_private(struct drm_framebuffer *fb); extern int drmfb_probe(struct drm_device *dev, struct drm_crtc *crtc); extern int drmfb_remove(struct drm_device *dev, struct drm_framebuffer *fb); extern void drm_crtc_probe_connector_modes(struct drm_device *dev, int maxX, int maxY); -- cgit v1.2.3-18-g5258 From 8714c0cecfc28f7ce73a520be4831f09743c4fd7 Mon Sep 17 00:00:00 2001 From: Steffen Trumtrar Date: Mon, 17 Dec 2012 14:20:17 +0100 Subject: video: add display_timing and videomode Add display_timing structure and the according helper functions. This allows the description of a display via its supported timing parameters. Also, add helper functions to convert from display timings to a generic videomode structure. The struct display_timing specifies all needed parameters to describe the signal properties of a display in one mode. This includes - ranges for signals that may have min-, max- and typical values - single integers for signals that can be on, off or are ignored - booleans for signals that are either on or off As a display may support multiple modes like this, a struct display_timings is added, that holds all given struct display_timing pointers and declares the native mode of the display. Although a display may state that a signal can be in a range, it is driven with fixed values that indicate a videomode. Therefore graphic drivers don't need all the information of struct display_timing, but would generate a videomode from the given set of supported signal timings and work with that. The video subsystems all define their own structs that describe a mode and work with that (e.g. fb_videomode or drm_display_mode). To slowly replace all those various structures and allow code reuse across those subsystems, add struct videomode as a generic description. This patch only includes the most basic fields in struct videomode. All missing fields that are needed to have a really generic video mode description can be added at a later stage. Signed-off-by: Steffen Trumtrar Reviewed-by: Thierry Reding Acked-by: Thierry Reding Tested-by: Thierry Reding Tested-by: Philipp Zabel Reviewed-by: Laurent Pinchart Acked-by: Laurent Pinchart Tested-by: Afzal Mohammed Tested-by: Rob Clark Tested-by: Leela Krishna Amudala --- include/video/display_timing.h | 124 +++++++++++++++++++++++++++++++++++++++++ include/video/videomode.h | 48 ++++++++++++++++ 2 files changed, 172 insertions(+) create mode 100644 include/video/display_timing.h create mode 100644 include/video/videomode.h (limited to 'include') diff --git a/include/video/display_timing.h b/include/video/display_timing.h new file mode 100644 index 00000000000..71e9a383a98 --- /dev/null +++ b/include/video/display_timing.h @@ -0,0 +1,124 @@ +/* + * Copyright 2012 Steffen Trumtrar + * + * description of display timings + * + * This file is released under the GPLv2 + */ + +#ifndef __LINUX_DISPLAY_TIMING_H +#define __LINUX_DISPLAY_TIMING_H + +#include +#include + +/* VESA display monitor timing parameters */ +#define VESA_DMT_HSYNC_LOW BIT(0) +#define VESA_DMT_HSYNC_HIGH BIT(1) +#define VESA_DMT_VSYNC_LOW BIT(2) +#define VESA_DMT_VSYNC_HIGH BIT(3) + +/* display specific flags */ +#define DISPLAY_FLAGS_DE_LOW BIT(0) /* data enable flag */ +#define DISPLAY_FLAGS_DE_HIGH BIT(1) +#define DISPLAY_FLAGS_PIXDATA_POSEDGE BIT(2) /* drive data on pos. edge */ +#define DISPLAY_FLAGS_PIXDATA_NEGEDGE BIT(3) /* drive data on neg. edge */ +#define DISPLAY_FLAGS_INTERLACED BIT(4) +#define DISPLAY_FLAGS_DOUBLESCAN BIT(5) + +/* + * A single signal can be specified via a range of minimal and maximal values + * with a typical value, that lies somewhere inbetween. + */ +struct timing_entry { + u32 min; + u32 typ; + u32 max; +}; + +enum timing_entry_index { + TE_MIN = 0, + TE_TYP = 1, + TE_MAX = 2, +}; + +/* + * Single "mode" entry. This describes one set of signal timings a display can + * have in one setting. This struct can later be converted to struct videomode + * (see include/video/videomode.h). As each timing_entry can be defined as a + * range, one struct display_timing may become multiple struct videomodes. + * + * Example: hsync active high, vsync active low + * + * Active Video + * Video ______________________XXXXXXXXXXXXXXXXXXXXXX_____________________ + * |<- sync ->|<- back ->|<----- active ----->|<- front ->|<- sync.. + * | | porch | | porch | + * + * HSync _|¯¯¯¯¯¯¯¯¯¯|___________________________________________|¯¯¯¯¯¯¯¯¯ + * + * VSync ¯|__________|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|_________ + */ +struct display_timing { + struct timing_entry pixelclock; + + struct timing_entry hactive; /* hor. active video */ + struct timing_entry hfront_porch; /* hor. front porch */ + struct timing_entry hback_porch; /* hor. back porch */ + struct timing_entry hsync_len; /* hor. sync len */ + + struct timing_entry vactive; /* ver. active video */ + struct timing_entry vfront_porch; /* ver. front porch */ + struct timing_entry vback_porch; /* ver. back porch */ + struct timing_entry vsync_len; /* ver. sync len */ + + unsigned int dmt_flags; /* VESA DMT flags */ + unsigned int data_flags; /* video data flags */ +}; + +/* + * This describes all timing settings a display provides. + * The native_mode is the default setting for this display. + * Drivers that can handle multiple videomodes should work with this struct and + * convert each entry to the desired end result. + */ +struct display_timings { + unsigned int num_timings; + unsigned int native_mode; + + struct display_timing **timings; +}; + +/* get value specified by index from struct timing_entry */ +static inline u32 display_timing_get_value(const struct timing_entry *te, + enum timing_entry_index index) +{ + switch (index) { + case TE_MIN: + return te->min; + break; + case TE_TYP: + return te->typ; + break; + case TE_MAX: + return te->max; + break; + default: + return te->typ; + } +} + +/* get one entry from struct display_timings */ +static inline struct display_timing *display_timings_get(const struct + display_timings *disp, + unsigned int index) +{ + if (disp->num_timings > index) + return disp->timings[index]; + else + return NULL; +} + +void display_timings_release(struct display_timings *disp); + +#endif diff --git a/include/video/videomode.h b/include/video/videomode.h new file mode 100644 index 00000000000..a42156234dd --- /dev/null +++ b/include/video/videomode.h @@ -0,0 +1,48 @@ +/* + * Copyright 2012 Steffen Trumtrar + * + * generic videomode description + * + * This file is released under the GPLv2 + */ + +#ifndef __LINUX_VIDEOMODE_H +#define __LINUX_VIDEOMODE_H + +#include +#include