diff options
Diffstat (limited to 'include/drm')
29 files changed, 1828 insertions, 658 deletions
diff --git a/include/drm/bridge/ptn3460.h b/include/drm/bridge/ptn3460.h new file mode 100644 index 00000000000..ff62344fec6 --- /dev/null +++ b/include/drm/bridge/ptn3460.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2013 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + */ + +#ifndef _DRM_BRIDGE_PTN3460_H_ +#define _DRM_BRIDGE_PTN3460_H_ + +struct drm_device; +struct drm_encoder; +struct i2c_client; +struct device_node; + +#if defined(CONFIG_DRM_PTN3460) || defined(CONFIG_DRM_PTN3460_MODULE) + +int ptn3460_init(struct drm_device *dev, struct drm_encoder *encoder, +		struct i2c_client *client, struct device_node *node); +#else + +static inline int ptn3460_init(struct drm_device *dev, +		struct drm_encoder *encoder, struct i2c_client *client, +		struct device_node *node) +{ +	return 0; +} + +#endif + +#endif diff --git a/include/drm/drmP.h b/include/drm/drmP.h index b46fb45f2cc..8af71a8e2c0 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -43,6 +43,7 @@  #include <asm/current.h>  #endif				/* __alpha__ */  #include <linux/kernel.h> +#include <linux/kref.h>  #include <linux/miscdevice.h>  #include <linux/fs.h>  #include <linux/init.h> @@ -56,6 +57,7 @@  #include <linux/mutex.h>  #include <linux/io.h>  #include <linux/slab.h> +#include <linux/ratelimit.h>  #if defined(__alpha__) || defined(__powerpc__)  #include <asm/pgtable.h>	/* For pte_wrprotect */  #endif @@ -86,46 +88,41 @@ struct videomode;  #include <drm/drm_hashtab.h>  #include <drm/drm_mm.h> -#define DRM_UT_CORE 		0x01 -#define DRM_UT_DRIVER		0x02 -#define DRM_UT_KMS		0x04 -#define DRM_UT_PRIME		0x08  /* - * Three debug levels are defined. - * drm_core, drm_driver, drm_kms - * drm_core level can be used in the generic drm code. For example: - * 	drm_ioctl, drm_mm, drm_memory - * The macro definition of DRM_DEBUG is used. - * 	DRM_DEBUG(fmt, args...) - * 	The debug info by using the DRM_DEBUG can be obtained by adding - * 	the boot option of "drm.debug=1". + * 4 debug categories are defined: + * + * CORE: Used in the generic drm code: drm_ioctl.c, drm_mm.c, drm_memory.c, ... + *	 This is the category used by the DRM_DEBUG() macro. + * + * DRIVER: Used in the vendor specific part of the driver: i915, radeon, ... + *	   This is the category used by the DRM_DEBUG_DRIVER() macro. + * + * KMS: used in the modesetting code. + *	This is the category used by the DRM_DEBUG_KMS() macro. + * + * PRIME: used in the prime code. + *	  This is the category used by the DRM_DEBUG_PRIME() macro.   * - * drm_driver level can be used in the specific drm driver. It is used - * to add the debug info related with the drm driver. For example: - * i915_drv, i915_dma, i915_gem, radeon_drv, - * 	The macro definition of DRM_DEBUG_DRIVER can be used. - * 	DRM_DEBUG_DRIVER(fmt, args...) - * 	The debug info by using the DRM_DEBUG_DRIVER can be obtained by - * 	adding the boot option of "drm.debug=0x02" + * Enabling verbose debug messages is done through the drm.debug parameter, + * each category being enabled by a bit.   * - * drm_kms level can be used in the KMS code related with specific drm driver. - * It is used to add the debug info related with KMS mode. For example: - * the connector/crtc , - * 	The macro definition of DRM_DEBUG_KMS can be used. - * 	DRM_DEBUG_KMS(fmt, args...) - * 	The debug info by using the DRM_DEBUG_KMS can be obtained by - * 	adding the boot option of "drm.debug=0x04" + * drm.debug=0x1 will enable CORE messages + * drm.debug=0x2 will enable DRIVER messages + * drm.debug=0x3 will enable CORE and DRIVER messages + * ... + * drm.debug=0xf will enable all messages   * - * If we add the boot option of "drm.debug=0x06", we can get the debug info by - * using the DRM_DEBUG_KMS and DRM_DEBUG_DRIVER. - * If we add the boot option of "drm.debug=0x05", we can get the debug info by - * using the DRM_DEBUG_KMS and DRM_DEBUG. + * An interesting feature is that it's possible to enable verbose logging at + * run-time by echoing the debug value in its sysfs node: + *   # echo 0xf > /sys/module/drm/parameters/debug   */ +#define DRM_UT_CORE 		0x01 +#define DRM_UT_DRIVER		0x02 +#define DRM_UT_KMS		0x04 +#define DRM_UT_PRIME		0x08 -extern __printf(4, 5) -void drm_ut_debug_printk(unsigned int request_level, -			 const char *prefix, -			 const char *function_name, +extern __printf(2, 3) +void drm_ut_debug_printk(const char *function_name,  			 const char *format, ...);  extern __printf(2, 3)  int drm_err(const char *func, const char *format, ...); @@ -136,7 +133,6 @@ int drm_err(const char *func, const char *format, ...);  /* driver capabilities and requirements mask */  #define DRIVER_USE_AGP     0x1 -#define DRIVER_REQUIRE_AGP 0x2  #define DRIVER_PCI_DMA     0x8  #define DRIVER_SG          0x10  #define DRIVER_HAVE_DMA    0x20 @@ -147,10 +143,6 @@ int drm_err(const char *func, const char *format, ...);  #define DRIVER_PRIME       0x4000  #define DRIVER_RENDER      0x8000 -#define DRIVER_BUS_PCI 0x1 -#define DRIVER_BUS_PLATFORM 0x2 -#define DRIVER_BUS_USB 0x3 -  /***********************************************************************/  /** \name Begin the DRM... */  /*@{*/ @@ -179,9 +171,28 @@ int drm_err(const char *func, const char *format, ...);  #define DRM_ERROR(fmt, ...)				\  	drm_err(__func__, fmt, ##__VA_ARGS__) +/** + * Rate limited error output.  Like DRM_ERROR() but won't flood the log. + * + * \param fmt printf() like format string. + * \param arg arguments + */ +#define DRM_ERROR_RATELIMITED(fmt, ...)				\ +({									\ +	static DEFINE_RATELIMIT_STATE(_rs,				\ +				      DEFAULT_RATELIMIT_INTERVAL,	\ +				      DEFAULT_RATELIMIT_BURST);		\ +									\ +	if (__ratelimit(&_rs))						\ +		drm_err(__func__, fmt, ##__VA_ARGS__);			\ +}) +  #define DRM_INFO(fmt, ...)				\  	printk(KERN_INFO "[" DRM_NAME "] " fmt, ##__VA_ARGS__) +#define DRM_INFO_ONCE(fmt, ...)				\ +	printk_once(KERN_INFO "[" DRM_NAME "] " fmt, ##__VA_ARGS__) +  /**   * Debug output.   * @@ -191,55 +202,30 @@ int drm_err(const char *func, const char *format, ...);  #if DRM_DEBUG_CODE  #define DRM_DEBUG(fmt, args...)						\  	do {								\ -		drm_ut_debug_printk(DRM_UT_CORE, DRM_NAME, 		\ -					__func__, fmt, ##args);		\ +		if (unlikely(drm_debug & DRM_UT_CORE))			\ +			drm_ut_debug_printk(__func__, fmt, ##args);	\  	} while (0)  #define DRM_DEBUG_DRIVER(fmt, args...)					\  	do {								\ -		drm_ut_debug_printk(DRM_UT_DRIVER, DRM_NAME,		\ -					__func__, fmt, ##args);		\ +		if (unlikely(drm_debug & DRM_UT_DRIVER))		\ +			drm_ut_debug_printk(__func__, fmt, ##args);	\  	} while (0) -#define DRM_DEBUG_KMS(fmt, args...)				\ +#define DRM_DEBUG_KMS(fmt, args...)					\  	do {								\ -		drm_ut_debug_printk(DRM_UT_KMS, DRM_NAME, 		\ -					 __func__, fmt, ##args);	\ +		if (unlikely(drm_debug & DRM_UT_KMS))			\ +			drm_ut_debug_printk(__func__, fmt, ##args);	\  	} while (0)  #define DRM_DEBUG_PRIME(fmt, args...)					\  	do {								\ -		drm_ut_debug_printk(DRM_UT_PRIME, DRM_NAME,		\ -					__func__, fmt, ##args);		\ -	} while (0) -#define DRM_LOG(fmt, args...)						\ -	do {								\ -		drm_ut_debug_printk(DRM_UT_CORE, NULL,			\ -					NULL, fmt, ##args);		\ -	} while (0) -#define DRM_LOG_KMS(fmt, args...)					\ -	do {								\ -		drm_ut_debug_printk(DRM_UT_KMS, NULL,			\ -					NULL, fmt, ##args);		\ -	} while (0) -#define DRM_LOG_MODE(fmt, args...)					\ -	do {								\ -		drm_ut_debug_printk(DRM_UT_MODE, NULL,			\ -					NULL, fmt, ##args);		\ -	} while (0) -#define DRM_LOG_DRIVER(fmt, args...)					\ -	do {								\ -		drm_ut_debug_printk(DRM_UT_DRIVER, NULL,		\ -					NULL, fmt, ##args);		\ +		if (unlikely(drm_debug & DRM_UT_PRIME))			\ +			drm_ut_debug_printk(__func__, fmt, ##args);	\  	} while (0)  #else  #define DRM_DEBUG_DRIVER(fmt, args...) do { } while (0)  #define DRM_DEBUG_KMS(fmt, args...)	do { } while (0)  #define DRM_DEBUG_PRIME(fmt, args...)	do { } while (0)  #define DRM_DEBUG(fmt, arg...)		 do { } while (0) -#define DRM_LOG(fmt, arg...)		do { } while (0) -#define DRM_LOG_KMS(fmt, args...) do { } while (0) -#define DRM_LOG_MODE(fmt, arg...) do { } while (0) -#define DRM_LOG_DRIVER(fmt, arg...) do { } while (0) -  #endif  /*@}*/ @@ -248,8 +234,6 @@ int drm_err(const char *func, const char *format, ...);  /** \name Internal types and structures */  /*@{*/ -#define DRM_ARRAY_SIZE(x) ARRAY_SIZE(x) -  #define DRM_IF_VERSION(maj, min) (maj << 16 | min)  /** @@ -412,11 +396,21 @@ struct drm_prime_file_private {  /** File private data */  struct drm_file { -	int authenticated; +	unsigned always_authenticated :1; +	unsigned authenticated :1; +	/* Whether we're master for a minor. Protected by master_mutex */ +	unsigned is_master :1; +	/* true when the client has asked us to expose stereo 3D mode flags */ +	unsigned stereo_allowed :1; +	/* +	 * true if client understands CRTC primary planes and cursor planes +	 * in the plane list +	 */ +	unsigned universal_planes:1; +  	struct pid *pid;  	kuid_t uid;  	drm_magic_t magic; -	unsigned long ioctl_count;  	struct list_head lhead;  	struct drm_minor *minor;  	unsigned long lock_count; @@ -429,10 +423,8 @@ struct drm_file {  	struct file *filp;  	void *driver_priv; -	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.  	 * @@ -507,7 +499,7 @@ struct drm_device_dma {   */  struct drm_agp_mem {  	unsigned long handle;		/**< handle */ -	DRM_AGP_MEM *memory; +	struct agp_memory *memory;  	unsigned long bound;		/**< address */  	int pages;  	struct list_head head; @@ -519,7 +511,7 @@ struct drm_agp_mem {   * \sa drm_agp_init() and drm_device::agp.   */  struct drm_agp_head { -	DRM_AGP_KERN agp_info;		/**< AGP device information */ +	struct agp_kern_info agp_info;		/**< AGP device information */  	struct list_head memory;  	unsigned long mode;		/**< AGP mode */  	struct agp_bridge_data *bridge; @@ -603,13 +595,6 @@ struct drm_ati_pcigart_info {  };  /** - * GEM specific mm private for tracking GEM objects - */ -struct drm_gem_mm { -	struct drm_vma_offset_manager vma_manager; -}; - -/**   * This structure defines the drm_mm memory object, which will be used by the   * DRM for its buffer objects.   */ @@ -667,8 +652,6 @@ struct drm_gem_object {  	uint32_t pending_read_domains;  	uint32_t pending_write_domain; -	void *driver_private; -  	/**  	 * dma_buf - dma buf associated with this GEM object  	 * @@ -700,29 +683,29 @@ struct drm_gem_object {  #include <drm/drm_crtc.h> -/* per-master structure */ +/** + * struct drm_master - drm master structure + * + * @refcount: Refcount for this master object. + * @minor: Link back to minor char device we are master for. Immutable. + * @unique: Unique identifier: e.g. busid. Protected by drm_global_mutex. + * @unique_len: Length of unique field. Protected by drm_global_mutex. + * @unique_size: Amount allocated. Protected by drm_global_mutex. + * @magiclist: Hash of used authentication tokens. Protected by struct_mutex. + * @magicfree: List of used authentication tokens. Protected by struct_mutex. + * @lock: DRI lock information. + * @driver_priv: Pointer to driver-private information. + */  struct drm_master { - -	struct kref refcount; /* refcount for this master */ - -	struct list_head head; /**< each minor contains a list of masters */ -	struct drm_minor *minor; /**< link back to minor we are a master for */ - -	char *unique;			/**< Unique identifier: e.g., busid */ -	int unique_len;			/**< Length of unique field */ -	int unique_size;		/**< amount allocated */ - -	int blocked;			/**< Blocked due to VC switch? */ - -	/** \name Authentication */ -	/*@{ */ +	struct kref refcount; +	struct drm_minor *minor; +	char *unique; +	int unique_len; +	int unique_size;  	struct drm_open_hash magiclist;  	struct list_head magicfree; -	/*@} */ - -	struct drm_lock_data lock;	/**< Information on hardware lock */ - -	void *driver_priv; /**< Private structure for driver to use */ +	struct drm_lock_data lock; +	void *driver_priv;  };  /* Size of ringbuffer for vblank timestamps. Just double-buffer @@ -741,17 +724,7 @@ struct drm_master {  #define DRM_SCANOUTPOS_ACCURATE     (1 << 2)  struct drm_bus { -	int bus_type; -	int (*get_irq)(struct drm_device *dev); -	const char *(*get_name)(struct drm_device *dev);  	int (*set_busid)(struct drm_device *dev, struct drm_master *master); -	int (*set_unique)(struct drm_device *dev, struct drm_master *master, -			  struct drm_unique *unique); -	int (*irq_by_busid)(struct drm_device *dev, struct drm_irq_busid *p); -	/* hooks that are for PCI */ -	int (*agp_init)(struct drm_device *dev); -	void (*agp_destroy)(struct drm_device *dev); -  };  /** @@ -834,12 +807,18 @@ struct drm_driver {  	/**  	 * Called by vblank timestamping code.  	 * -	 * Return the current display scanout position from a crtc. +	 * Return the current display scanout position from a crtc, and an +	 * optional accurate ktime_get timestamp of when position was measured.  	 *  	 * \param dev  DRM device.  	 * \param crtc Id of the crtc to query. +	 * \param flags Flags from the caller (DRM_CALLED_FROM_VBLIRQ or 0).  	 * \param *vpos Target location for current vertical scanout position.  	 * \param *hpos Target location for current horizontal scanout position. +	 * \param *stime Target location for timestamp taken immediately before +	 *               scanout position query. Can be NULL to skip timestamp. +	 * \param *etime Target location for timestamp taken immediately after +	 *               scanout position query. Can be NULL to skip timestamp.  	 *  	 * Returns vpos as a positive number while in active scanout area.  	 * Returns vpos as a negative number inside vblank, counting the number @@ -856,7 +835,9 @@ struct drm_driver {  	 *  	 */  	int (*get_scanout_position) (struct drm_device *dev, int crtc, -				     int *vpos, int *hpos); +				     unsigned int flags, +				     int *vpos, int *hpos, ktime_t *stime, +				     ktime_t *etime);  	/**  	 * Called by \c drm_get_last_vbltimestamp. Should return a precise @@ -895,7 +876,7 @@ struct drm_driver {  	/* these have to be filled in */ -	irqreturn_t(*irq_handler) (DRM_IRQ_ARGS); +	irqreturn_t(*irq_handler) (int irq, void *arg);  	void (*irq_preinstall) (struct drm_device *dev);  	int (*irq_postinstall) (struct drm_device *dev);  	void (*irq_uninstall) (struct drm_device *dev); @@ -922,7 +903,6 @@ struct drm_driver {  	 *  	 * Returns 0 on success.  	 */ -	int (*gem_init_object) (struct drm_gem_object *obj);  	void (*gem_free_object) (struct drm_gem_object *obj);  	int (*gem_open_object) (struct drm_gem_object *, struct drm_file *);  	void (*gem_close_object) (struct drm_gem_object *, struct drm_file *); @@ -981,41 +961,17 @@ struct drm_driver {  	const struct drm_ioctl_desc *ioctls;  	int num_ioctls;  	const struct file_operations *fops; -	union { -		struct pci_driver *pci; -		struct platform_device *platform_device; -		struct usb_driver *usb; -	} kdriver;  	struct drm_bus *bus; -	/* List of devices hanging off this driver */ -	struct list_head device_list; +	/* List of devices hanging off this driver with stealth attach. */ +	struct list_head legacy_dev_list;  }; -#define DRM_MINOR_UNASSIGNED 0 -#define DRM_MINOR_LEGACY 1 -#define DRM_MINOR_CONTROL 2 -#define DRM_MINOR_RENDER 3 - - -/** - * debugfs node list. This structure represents a debugfs file to - * be created by the drm core - */ -struct drm_debugfs_list { -	const char *name; /** file name */ -	int (*show)(struct seq_file*, void*); /** show callback */ -	u32 driver_features; /**< Required driver features for this entry */ -}; - -/** - * debugfs node structure. This structure represents a debugfs file. - */ -struct drm_debugfs_node { -	struct list_head list; -	struct drm_minor *minor; -	struct drm_debugfs_list *debugfs_ent; -	struct dentry *dent; +enum drm_minor_type { +	DRM_MINOR_LEGACY, +	DRM_MINOR_CONTROL, +	DRM_MINOR_RENDER, +	DRM_MINOR_CNT,  };  /** @@ -1045,8 +1001,7 @@ struct drm_info_node {  struct drm_minor {  	int index;			/**< Minor device number */  	int type;                       /**< Control or render */ -	dev_t device;			/**< Device number for mknod */ -	struct device kdev;		/**< Linux device */ +	struct device *kdev;		/**< Linux device */  	struct drm_device *dev;  	struct dentry *debugfs_root; @@ -1054,26 +1009,11 @@ struct drm_minor {  	struct list_head debugfs_list;  	struct mutex debugfs_lock; /* Protects debugfs_list. */ -	struct drm_master *master; /* currently active master for this node */ -	struct list_head master_list; +	/* currently active master for this node. Protected by master_mutex */ +	struct drm_master *master;  	struct drm_mode_group mode_group;  }; -/* mode specified on the command line */ -struct drm_cmdline_mode { -	bool specified; -	bool refresh_specified; -	bool bpp_specified; -	int xres, yres; -	int bpp; -	int refresh; -	bool rb; -	bool interlace; -	bool cvt; -	bool margins; -	enum drm_connector_force force; -}; -  struct drm_pending_vblank_event {  	struct drm_pending_event base; @@ -1081,49 +1021,68 @@ struct drm_pending_vblank_event {  	struct drm_event_vblank event;  }; +struct drm_vblank_crtc { +	struct drm_device *dev;		/* pointer to the drm_device */ +	wait_queue_head_t queue;	/**< VBLANK wait queue */ +	struct timeval time[DRM_VBLANKTIME_RBSIZE];	/**< timestamp of current count */ +	struct timer_list disable_timer;		/* delayed disable timer */ +	atomic_t count;			/**< number of VBLANK interrupts */ +	atomic_t refcount;		/* number of users of vblank interruptsper crtc */ +	u32 last;			/* protected by dev->vbl_lock, used */ +					/* for wraparound handling */ +	u32 last_wait;			/* Last vblank seqno waited per CRTC */ +	unsigned int inmodeset;		/* Display driver is setting mode */ +	int crtc;			/* crtc index */ +	bool enabled;			/* so we don't call enable more than +					   once per disable */ +}; +  /**   * DRM device structure. This structure represent a complete card that   * may contain multiple heads.   */  struct drm_device { -	struct list_head driver_item;	/**< list of devices per driver */ -	char *devname;			/**< For /proc/interrupts */ +	struct list_head legacy_dev_list;/**< list of devices per driver for stealth attach cleanup */  	int if_version;			/**< Highest interface version set */ +	/** \name Lifetime Management */ +	/*@{ */ +	struct kref ref;		/**< Object ref-count */ +	struct device *dev;		/**< Device structure of bus-device */ +	struct drm_driver *driver;	/**< DRM driver managing the device */ +	void *dev_private;		/**< DRM driver private data */ +	struct drm_minor *control;		/**< Control node */ +	struct drm_minor *primary;		/**< Primary node */ +	struct drm_minor *render;		/**< Render node */ +	atomic_t unplugged;			/**< Flag whether dev is dead */ +	struct inode *anon_inode;		/**< inode for private address-space */ +	char *unique;				/**< unique name of the device */ +	/*@} */ +  	/** \name Locks */  	/*@{ */ -	spinlock_t count_lock;		/**< For inuse, drm_device::open_count, drm_device::buf_use */  	struct mutex struct_mutex;	/**< For others */ +	struct mutex master_mutex;      /**< For drm_minor::master and drm_file::is_master */  	/*@} */  	/** \name Usage Counters */  	/*@{ */ -	int open_count;			/**< Outstanding files open */ -	atomic_t ioctl_count;		/**< Outstanding IOCTLs pending */ -	atomic_t vma_count;		/**< Outstanding vma areas open */ +	int open_count;			/**< Outstanding files open, protected by drm_global_mutex. */ +	spinlock_t buf_lock;		/**< For drm_device::buf_use and a few other things. */  	int buf_use;			/**< Buffers in use -- cannot alloc */  	atomic_t buf_alloc;		/**< Buffer allocation in progress */  	/*@} */ -	/** \name Performance counters */ -	/*@{ */ -	unsigned long counters; -	enum drm_stat_type types[15]; -	atomic_t counts[15]; -	/*@} */ -  	struct list_head filelist;  	/** \name Memory management */  	/*@{ */  	struct list_head maplist;	/**< Linked list of regions */ -	int map_count;			/**< Number of mappable regions */  	struct drm_open_hash map_hash;	/**< User token hash table for maps */  	/** \name Context handle management */  	/*@{ */  	struct list_head ctxlist;	/**< Linked list of context handles */ -	int ctx_count;			/**< Number of context handles */  	struct mutex ctxlist_mutex;	/**< For ctxlist */  	struct idr ctx_idr; @@ -1139,12 +1098,13 @@ struct drm_device {  	/** \name Context support */  	/*@{ */ -	int irq_enabled;		/**< True if irq handler is enabled */ +	bool irq_enabled;		/**< True if irq handler is enabled */ +	int irq; +  	__volatile__ long context_flag;	/**< Context swapping flag */  	int last_context;		/**< Last current context */  	/*@} */ -	struct work_struct work;  	/** \name VBLANK IRQ support */  	/*@{ */ @@ -1154,21 +1114,13 @@ struct drm_device {  	 * Once the modeset ioctl *has* been called though, we can safely  	 * disable them when unused.  	 */ -	int vblank_disable_allowed; +	bool vblank_disable_allowed; + +	/* array of size num_crtcs */ +	struct drm_vblank_crtc *vblank; -	wait_queue_head_t *vbl_queue;   /**< VBLANK wait queue */ -	atomic_t *_vblank_count;        /**< number of VBLANK interrupts (driver must alloc the right number of counters) */ -	struct timeval *_vblank_time;   /**< timestamp of current vblank_count (drivers must alloc right number of fields) */  	spinlock_t vblank_time_lock;    /**< Protects vblank count and time updates during vblank enable/disable */  	spinlock_t vbl_lock; -	atomic_t *vblank_refcount;      /* number of users of vblank interruptsper crtc */ -	u32 *last_vblank;               /* protected by dev->vbl_lock, used */ -					/* for wraparound handling */ -	int *vblank_enabled;            /* so we don't call enable more than -					   once per disable */ -	int *vblank_inmodeset;          /* Display driver is setting mode */ -	u32 *last_vblank_wait;		/* Last vblank seqno waited per CRTC */ -	struct timer_list vblank_disable_timer;  	u32 max_vblank_count;           /**< size of vblank counter register */ @@ -1182,10 +1134,7 @@ struct drm_device {  	struct drm_agp_head *agp;	/**< AGP data */ -	struct device *dev;             /**< Device structure */  	struct pci_dev *pdev;		/**< PCI device structure */ -	int pci_vendor;			/**< PCI vendor id */ -	int pci_device;			/**< PCI device id */  #ifdef __alpha__  	struct pci_controller *hose;  #endif @@ -1195,18 +1144,11 @@ struct drm_device {  	struct drm_sg_mem *sg;	/**< Scatter gather memory */  	unsigned int num_crtcs;                  /**< Number of CRTCs on this device */ -	void *dev_private;		/**< device private data */ -	void *mm_private; -	struct address_space *dev_mapping;  	struct drm_sigdata sigdata;	   /**< For block_all_signals */  	sigset_t sigmask; -	struct drm_driver *driver;  	struct drm_local_map *agp_buffer_map;  	unsigned int agp_buffer_token; -	struct drm_minor *control;		/**< Control node for card */ -	struct drm_minor *primary;		/**< render type primary screen head */ -	struct drm_minor *render;		/**< render node for card */          struct drm_mode_config mode_config;	/**< Current mode config */ @@ -1214,10 +1156,9 @@ struct drm_device {  	/*@{ */  	struct mutex object_name_lock;  	struct idr object_name_idr; +	struct drm_vma_offset_manager *vma_offset_manager;  	/*@} */  	int switch_power_state; - -	atomic_t unplugged; /* device has been unplugged or gone away */  };  #define DRM_SWITCH_POWER_ON 0 @@ -1231,11 +1172,6 @@ static __inline__ int drm_core_check_feature(struct drm_device *dev,  	return ((dev->driver->driver_features & feature) ? 1 : 0);  } -static inline int drm_dev_to_irq(struct drm_device *dev) -{ -	return dev->driver->bus->get_irq(dev); -} -  static inline void drm_device_set_unplugged(struct drm_device *dev)  {  	smp_wmb(); @@ -1249,14 +1185,19 @@ static inline int drm_device_is_unplugged(struct drm_device *dev)  	return ret;  } -static inline bool drm_modeset_is_locked(struct drm_device *dev) +static inline bool drm_is_render_client(const struct drm_file *file_priv) +{ +	return file_priv->minor->type == DRM_MINOR_RENDER; +} + +static inline bool drm_is_control_client(const struct drm_file *file_priv)  { -	return mutex_is_locked(&dev->mode_config.mutex); +	return file_priv->minor->type == DRM_MINOR_CONTROL;  } -static inline bool drm_is_render_client(struct drm_file *file_priv) +static inline bool drm_is_primary_client(const struct drm_file *file_priv)  { -	return file_priv->minor->type == DRM_MINOR_RENDER; +	return file_priv->minor->type == DRM_MINOR_LEGACY;  }  /******************************************************************/ @@ -1269,6 +1210,7 @@ extern long drm_ioctl(struct file *filp,  extern long drm_compat_ioctl(struct file *filp,  			     unsigned int cmd, unsigned long arg);  extern int drm_lastclose(struct drm_device *dev); +extern bool drm_ioctl_flags(unsigned int nr, unsigned int *flags);  				/* Device support (drm_fops.h) */  extern struct mutex drm_global_mutex; @@ -1288,6 +1230,7 @@ extern unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait);  				/* Memory management support (drm_memory.h) */  #include <drm/drm_memory.h> +  				/* Misc. IOCTL support (drm_ioctl.h) */  extern int drm_irq_by_busid(struct drm_device *dev, void *data,  			    struct drm_file *file_priv); @@ -1303,6 +1246,8 @@ extern int drm_getstats(struct drm_device *dev, void *data,  			struct drm_file *file_priv);  extern int drm_getcap(struct drm_device *dev, void *data,  		      struct drm_file *file_priv); +extern int drm_setclientcap(struct drm_device *dev, void *data, +			    struct drm_file *file_priv);  extern int drm_setversion(struct drm_device *dev, void *data,  			  struct drm_file *file_priv);  extern int drm_noop(struct drm_device *dev, void *data, @@ -1341,7 +1286,7 @@ extern int drm_remove_magic(struct drm_master *master, drm_magic_t magic);  /* Cache management (drm_cache.c) */  void drm_clflush_pages(struct page *pages[], unsigned long num_pages);  void drm_clflush_sg(struct sg_table *st); -void drm_clflush_virt_range(char *addr, unsigned long length); +void drm_clflush_virt_range(void *addr, unsigned long length);  				/* Locking IOCTL support (drm_lock.h) */  extern int drm_lock(struct drm_device *dev, void *data, @@ -1394,7 +1339,7 @@ extern void drm_core_reclaim_buffers(struct drm_device *dev,  				/* IRQ support (drm_irq.h) */  extern int drm_control(struct drm_device *dev, void *data,  		       struct drm_file *file_priv); -extern int drm_irq_install(struct drm_device *dev); +extern int drm_irq_install(struct drm_device *dev, int irq);  extern int drm_irq_uninstall(struct drm_device *dev);  extern int drm_vblank_init(struct drm_device *dev, int num_crtcs); @@ -1408,31 +1353,25 @@ extern void drm_send_vblank_event(struct drm_device *dev, int crtc,  extern bool drm_handle_vblank(struct drm_device *dev, int crtc);  extern int drm_vblank_get(struct drm_device *dev, int crtc);  extern void drm_vblank_put(struct drm_device *dev, int crtc); +extern int drm_crtc_vblank_get(struct drm_crtc *crtc); +extern void drm_crtc_vblank_put(struct drm_crtc *crtc);  extern void drm_vblank_off(struct drm_device *dev, int crtc); +extern void drm_vblank_on(struct drm_device *dev, int crtc); +extern void drm_crtc_vblank_off(struct drm_crtc *crtc); +extern void drm_crtc_vblank_on(struct drm_crtc *crtc);  extern void drm_vblank_cleanup(struct drm_device *dev); +  extern u32 drm_get_last_vbltimestamp(struct drm_device *dev, int crtc,  				     struct timeval *tvblank, unsigned flags);  extern int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,  						 int crtc, int *max_error,  						 struct timeval *vblank_time,  						 unsigned flags, -						 struct drm_crtc *refcrtc); -extern void drm_calc_timestamping_constants(struct drm_crtc *crtc); - -extern bool -drm_mode_parse_command_line_for_connector(const char *mode_option, -					  struct drm_connector *connector, -					  struct drm_cmdline_mode *mode); +						 const struct drm_crtc *refcrtc, +						 const struct drm_display_mode *mode); +extern void drm_calc_timestamping_constants(struct drm_crtc *crtc, +					    const struct drm_display_mode *mode); -extern struct drm_display_mode * -drm_mode_create_from_cmdline_mode(struct drm_device *dev, -				  struct drm_cmdline_mode *cmd); - -extern int drm_display_mode_from_videomode(const struct videomode *vm, -					   struct drm_display_mode *dmode); -extern int of_get_drm_display_mode(struct device_node *np, -				   struct drm_display_mode *dmode, -				   int index);  /* Modesetting support */  extern void drm_vblank_pre_modeset(struct drm_device *dev, int crtc); @@ -1454,10 +1393,10 @@ extern struct drm_master *drm_master_get(struct drm_master *master);  extern void drm_master_put(struct drm_master **master);  extern void drm_put_dev(struct drm_device *dev); -extern int drm_put_minor(struct drm_minor **minor);  extern void drm_unplug_dev(struct drm_device *dev);  extern unsigned int drm_debug;  extern unsigned int drm_rnodes; +extern unsigned int drm_universal_planes;  extern unsigned int drm_vblank_offdelay;  extern unsigned int drm_timestamp_precision; @@ -1474,11 +1413,36 @@ extern struct drm_local_map *drm_getsarea(struct drm_device *dev);  #if defined(CONFIG_DEBUG_FS)  extern int drm_debugfs_init(struct drm_minor *minor, int minor_id,  			    struct dentry *root); -extern int drm_debugfs_create_files(struct drm_info_list *files, int count, -				    struct dentry *root, struct drm_minor *minor); -extern int drm_debugfs_remove_files(struct drm_info_list *files, int count, -                                    struct drm_minor *minor); +extern int drm_debugfs_create_files(const struct drm_info_list *files, +				    int count, struct dentry *root, +				    struct drm_minor *minor); +extern int drm_debugfs_remove_files(const struct drm_info_list *files, +				    int count, struct drm_minor *minor);  extern int drm_debugfs_cleanup(struct drm_minor *minor); +#else +static inline int drm_debugfs_init(struct drm_minor *minor, int minor_id, +				   struct dentry *root) +{ +	return 0; +} + +static inline int drm_debugfs_create_files(const struct drm_info_list *files, +					   int count, struct dentry *root, +					   struct drm_minor *minor) +{ +	return 0; +} + +static inline int drm_debugfs_remove_files(const struct drm_info_list *files, +					   int count, struct drm_minor *minor) +{ +	return 0; +} + +static inline int drm_debugfs_cleanup(struct drm_minor *minor) +{ +	return 0; +}  #endif  				/* Info file support */ @@ -1540,6 +1504,9 @@ extern drm_dma_handle_t *drm_pci_alloc(struct drm_device *dev, size_t size,  				       size_t align);  extern void __drm_pci_free(struct drm_device *dev, drm_dma_handle_t * dmah);  extern void drm_pci_free(struct drm_device *dev, drm_dma_handle_t * dmah); +extern int drm_pci_set_unique(struct drm_device *dev, +			      struct drm_master *master, +			      struct drm_unique *u);  			       /* sysfs support (drm_sysfs.c) */  struct drm_sysfs_class; @@ -1556,8 +1523,6 @@ int drm_gem_init(struct drm_device *dev);  void drm_gem_destroy(struct drm_device *dev);  void drm_gem_object_release(struct drm_gem_object *obj);  void drm_gem_object_free(struct kref *kref); -struct drm_gem_object *drm_gem_object_alloc(struct drm_device *dev, -					    size_t size);  int drm_gem_object_init(struct drm_device *dev,  			struct drm_gem_object *obj, size_t size);  void drm_gem_private_object_init(struct drm_device *dev, @@ -1645,10 +1610,17 @@ static __inline__ void drm_core_dropmap(struct drm_local_map *map)  #include <drm/drm_mem_util.h> -extern int drm_fill_in_dev(struct drm_device *dev, -			   const struct pci_device_id *ent, -			   struct drm_driver *driver); -int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int type); +struct drm_device *drm_dev_alloc(struct drm_driver *driver, +				 struct device *parent); +void drm_dev_ref(struct drm_device *dev); +void drm_dev_unref(struct drm_device *dev); +int drm_dev_register(struct drm_device *dev, unsigned long flags); +void drm_dev_unregister(struct drm_device *dev); +int drm_dev_set_unique(struct drm_device *dev, const char *fmt, ...); + +struct drm_minor *drm_minor_acquire(unsigned int minor_id); +void drm_minor_release(struct drm_minor *minor); +  /*@}*/  /* PCI section */ @@ -1664,6 +1636,7 @@ static __inline__ int drm_pci_device_is_agp(struct drm_device *dev)  	return pci_find_capability(dev->pdev, PCI_CAP_ID_AGP);  } +void drm_pci_agp_destroy(struct drm_device *dev);  extern int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver);  extern void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver); @@ -1679,7 +1652,6 @@ extern int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *speed_mask);  /* platform section */  extern int drm_platform_init(struct drm_driver *driver, struct platform_device *platform_device); -extern void drm_platform_exit(struct drm_driver *driver, struct platform_device *platform_device);  /* returns true if currently okay to sleep */  static __inline__ bool drm_can_sleep(void) diff --git a/include/drm/drm_agpsupport.h b/include/drm/drm_agpsupport.h index a184eeee9c9..86a02188074 100644 --- a/include/drm/drm_agpsupport.h +++ b/include/drm/drm_agpsupport.h @@ -10,17 +10,16 @@  #if __OS_HAS_AGP -void drm_free_agp(DRM_AGP_MEM * handle, int pages); -int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start); -int drm_unbind_agp(DRM_AGP_MEM * handle); -DRM_AGP_MEM *drm_agp_bind_pages(struct drm_device *dev, +void drm_free_agp(struct agp_memory * handle, int pages); +int drm_bind_agp(struct agp_memory * handle, unsigned int start); +int drm_unbind_agp(struct agp_memory * handle); +struct agp_memory *drm_agp_bind_pages(struct drm_device *dev,  				struct page **pages,  				unsigned long num_pages,  				uint32_t gtt_offset,  				uint32_t type);  struct drm_agp_head *drm_agp_init(struct drm_device *dev); -void drm_agp_destroy(struct drm_agp_head *agp);  void drm_agp_clear(struct drm_device *dev);  int drm_agp_acquire(struct drm_device *dev);  int drm_agp_acquire_ioctl(struct drm_device *dev, void *data, @@ -46,29 +45,23 @@ int drm_agp_unbind_ioctl(struct drm_device *dev, void *data,  int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request);  int drm_agp_bind_ioctl(struct drm_device *dev, void *data,  		       struct drm_file *file_priv); - -static inline int drm_core_has_AGP(struct drm_device *dev) -{ -	return drm_core_check_feature(dev, DRIVER_USE_AGP); -} -  #else /* __OS_HAS_AGP */ -static inline void drm_free_agp(DRM_AGP_MEM * handle, int pages) +static inline void drm_free_agp(struct agp_memory * handle, int pages)  {  } -static inline int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start) +static inline int drm_bind_agp(struct agp_memory * handle, unsigned int start)  {  	return -ENODEV;  } -static inline int drm_unbind_agp(DRM_AGP_MEM * handle) +static inline int drm_unbind_agp(struct agp_memory * handle)  {  	return -ENODEV;  } -static inline DRM_AGP_MEM *drm_agp_bind_pages(struct drm_device *dev, +static inline struct agp_memory *drm_agp_bind_pages(struct drm_device *dev,  					      struct page **pages,  					      unsigned long num_pages,  					      uint32_t gtt_offset, @@ -82,10 +75,6 @@ static inline struct drm_agp_head *drm_agp_init(struct drm_device *dev)  	return NULL;  } -static inline void drm_agp_destroy(struct drm_agp_head *agp) -{ -} -  static inline void drm_agp_clear(struct drm_device *dev)  {  } @@ -183,12 +172,6 @@ static inline int drm_agp_bind_ioctl(struct drm_device *dev, void *data,  {  	return -ENODEV;  } - -static inline int drm_core_has_AGP(struct drm_device *dev) -{ -	return 0; -} -  #endif /* __OS_HAS_AGP */  #endif /* _DRM_AGPSUPPORT_H_ */ diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 24f499569a2..251b75e6bf7 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -30,9 +30,10 @@  #include <linux/types.h>  #include <linux/idr.h>  #include <linux/fb.h> +#include <linux/hdmi.h>  #include <drm/drm_mode.h> -  #include <drm/drm_fourcc.h> +#include <drm/drm_modeset_lock.h>  struct drm_device;  struct drm_mode_set; @@ -50,6 +51,7 @@ struct drm_clip_rect;  #define DRM_MODE_OBJECT_BLOB 0xbbbbbbbb  #define DRM_MODE_OBJECT_PLANE 0xeeeeeeee  #define DRM_MODE_OBJECT_BRIDGE 0xbdbdbdbd +#define DRM_MODE_OBJECT_ANY 0  struct drm_mode_object {  	uint32_t id; @@ -64,121 +66,23 @@ struct drm_object_properties {  	uint64_t values[DRM_OBJECT_MAX_PROPERTY];  }; -/* - * Note on terminology:  here, for brevity and convenience, we refer to connector - * control chips as 'CRTCs'.  They can control any type of connector, VGA, LVDS, - * DVI, etc.  And 'screen' refers to the whole of the visible display, which - * may span multiple monitors (and therefore multiple CRTC and connector - * structures). - */ +static inline int64_t U642I64(uint64_t val) +{ +	return (int64_t)*((int64_t *)&val); +} +static inline uint64_t I642U64(int64_t val) +{ +	return (uint64_t)*((uint64_t *)&val); +} -enum drm_mode_status { -    MODE_OK	= 0,	/* Mode OK */ -    MODE_HSYNC,		/* hsync out of range */ -    MODE_VSYNC,		/* vsync out of range */ -    MODE_H_ILLEGAL,	/* mode has illegal horizontal timings */ -    MODE_V_ILLEGAL,	/* mode has illegal horizontal timings */ -    MODE_BAD_WIDTH,	/* requires an unsupported linepitch */ -    MODE_NOMODE,	/* no mode with a matching name */ -    MODE_NO_INTERLACE,	/* interlaced mode not supported */ -    MODE_NO_DBLESCAN,	/* doublescan mode not supported */ -    MODE_NO_VSCAN,	/* multiscan mode not supported */ -    MODE_MEM,		/* insufficient video memory */ -    MODE_VIRTUAL_X,	/* mode width too large for specified virtual size */ -    MODE_VIRTUAL_Y,	/* mode height too large for specified virtual size */ -    MODE_MEM_VIRT,	/* insufficient video memory given virtual size */ -    MODE_NOCLOCK,	/* no fixed clock available */ -    MODE_CLOCK_HIGH,	/* clock required is too high */ -    MODE_CLOCK_LOW,	/* clock required is too low */ -    MODE_CLOCK_RANGE,	/* clock/mode isn't in a ClockRange */ -    MODE_BAD_HVALUE,	/* horizontal timing was out of range */ -    MODE_BAD_VVALUE,	/* vertical timing was out of range */ -    MODE_BAD_VSCAN,	/* VScan value out of range */ -    MODE_HSYNC_NARROW,	/* horizontal sync too narrow */ -    MODE_HSYNC_WIDE,	/* horizontal sync too wide */ -    MODE_HBLANK_NARROW,	/* horizontal blanking too narrow */ -    MODE_HBLANK_WIDE,	/* horizontal blanking too wide */ -    MODE_VSYNC_NARROW,	/* vertical sync too narrow */ -    MODE_VSYNC_WIDE,	/* vertical sync too wide */ -    MODE_VBLANK_NARROW,	/* vertical blanking too narrow */ -    MODE_VBLANK_WIDE,	/* vertical blanking too wide */ -    MODE_PANEL,         /* exceeds panel dimensions */ -    MODE_INTERLACE_WIDTH, /* width too large for interlaced mode */ -    MODE_ONE_WIDTH,     /* only one width is supported */ -    MODE_ONE_HEIGHT,    /* only one height is supported */ -    MODE_ONE_SIZE,      /* only one resolution is supported */ -    MODE_NO_REDUCED,    /* monitor doesn't accept reduced blanking */ -    MODE_UNVERIFIED = -3, /* mode needs to reverified */ -    MODE_BAD = -2,	/* unspecified reason */ -    MODE_ERROR	= -1	/* error condition */ +enum drm_connector_force { +	DRM_FORCE_UNSPECIFIED, +	DRM_FORCE_OFF, +	DRM_FORCE_ON,         /* force on analog part normally */ +	DRM_FORCE_ON_DIGITAL, /* for DVI-I use digital connector */  }; -#define DRM_MODE_TYPE_CLOCK_CRTC_C (DRM_MODE_TYPE_CLOCK_C | \ -				    DRM_MODE_TYPE_CRTC_C) - -#define DRM_MODE(nm, t, c, hd, hss, hse, ht, hsk, vd, vss, vse, vt, vs, f) \ -	.name = nm, .status = 0, .type = (t), .clock = (c), \ -	.hdisplay = (hd), .hsync_start = (hss), .hsync_end = (hse), \ -	.htotal = (ht), .hskew = (hsk), .vdisplay = (vd), \ -	.vsync_start = (vss), .vsync_end = (vse), .vtotal = (vt), \ -	.vscan = (vs), .flags = (f), \ -	.base.type = DRM_MODE_OBJECT_MODE - -#define CRTC_INTERLACE_HALVE_V 0x1 /* halve V values for interlacing */ - -struct drm_display_mode { -	/* Header */ -	struct list_head head; -	struct drm_mode_object base; - -	char name[DRM_DISPLAY_MODE_LEN]; - -	enum drm_mode_status status; -	unsigned int type; - -	/* Proposed mode values */ -	int clock;		/* in kHz */ -	int hdisplay; -	int hsync_start; -	int hsync_end; -	int htotal; -	int hskew; -	int vdisplay; -	int vsync_start; -	int vsync_end; -	int vtotal; -	int vscan; -	unsigned int flags; - -	/* Addressable image size (may be 0 for projectors, etc.) */ -	int width_mm; -	int height_mm; - -	/* Actual mode we give to hw */ -	int clock_index; -	int synth_clock; -	int crtc_hdisplay; -	int crtc_hblank_start; -	int crtc_hblank_end; -	int crtc_hsync_start; -	int crtc_hsync_end; -	int crtc_htotal; -	int crtc_hskew; -	int crtc_vdisplay; -	int crtc_vblank_start; -	int crtc_vblank_end; -	int crtc_vsync_start; -	int crtc_vsync_end; -	int crtc_vtotal; - -	/* Driver private mode info */ -	int private_size; -	int *private; -	int private_flags; - -	int vrefresh;		/* in Hz */ -	int hsync;		/* in kHz */ -}; +#include <drm/drm_modes.h>  enum drm_connector_status {  	connector_status_connected = 1, @@ -217,6 +121,9 @@ struct drm_display_info {  	enum subpixel_order subpixel_order;  	u32 color_formats; +	/* Mask of supported hdmi deep color modes */ +	u8 edid_hdmi_dc_modes; +  	u8 cea_rev;  }; @@ -297,10 +204,15 @@ struct drm_property {  	char name[DRM_PROP_NAME_LEN];  	uint32_t num_values;  	uint64_t *values; +	struct drm_device *dev;  	struct list_head enum_blob_list;  }; +void drm_modeset_lock_all(struct drm_device *dev); +void drm_modeset_unlock_all(struct drm_device *dev); +void drm_warn_on_modeset_not_all_locked(struct drm_device *dev); +  struct drm_crtc;  struct drm_connector;  struct drm_encoder; @@ -376,7 +288,10 @@ struct drm_crtc_funcs {   * drm_crtc - central CRTC control structure   * @dev: parent DRM device   * @head: list management + * @mutex: per-CRTC locking   * @base: base KMS object for ID tracking etc. + * @primary: primary plane for this CRTC + * @cursor: cursor plane for this CRTC   * @enabled: is this CRTC enabled?   * @mode: current mode timings   * @hwmode: mode timings as programmed to hw regs @@ -408,12 +323,13 @@ struct drm_crtc {  	 * state, ...) and a write lock for everything which can be update  	 * without a full modeset (fb, cursor data, ...)  	 */ -	struct mutex mutex; +	struct drm_modeset_lock mutex;  	struct drm_mode_object base; -	/* framebuffer the connector is currently bound to */ -	struct drm_framebuffer *fb; +	/* primary and cursor planes for CRTC */ +	struct drm_plane *primary; +	struct drm_plane *cursor;  	/* Temporary tracking of the old fb while a modeset is ongoing. Used  	 * by drm_mode_set_config_internal to implement correct refcounting. */ @@ -439,7 +355,7 @@ struct drm_crtc {  	uint16_t *gamma_store;  	/* Constants needed for precise vblank and swap timestamping. */ -	s64 framedur_ns, linedur_ns, pixeldur_ns; +	int framedur_ns, linedur_ns, pixeldur_ns;  	/* if you are using the helper */  	void *helper_private; @@ -504,6 +420,7 @@ struct drm_encoder_funcs {   * @dev: parent DRM device   * @head: list management   * @base: base KMS object + * @name: encoder name   * @encoder_type: one of the %DRM_MODE_ENCODER_<foo> types in drm_mode.h   * @possible_crtcs: bitmask of potential CRTC bindings   * @possible_clones: bitmask of potential sibling encoders for cloning @@ -520,6 +437,7 @@ struct drm_encoder {  	struct list_head head;  	struct drm_mode_object base; +	char *name;  	int encoder_type;  	uint32_t possible_crtcs;  	uint32_t possible_clones; @@ -530,13 +448,6 @@ struct drm_encoder {  	void *helper_private;  }; -enum drm_connector_force { -	DRM_FORCE_UNSPECIFIED, -	DRM_FORCE_OFF, -	DRM_FORCE_ON,         /* force on analog part normally */ -	DRM_FORCE_ON_DIGITAL, /* for DVI-I use digital connector */ -}; -  /* should we poll this connector for connects and disconnects */  /* hot plug detectable */  #define DRM_CONNECTOR_POLL_HPD (1 << 0) @@ -555,6 +466,7 @@ enum drm_connector_force {   * @attr: sysfs attributes   * @head: list management   * @base: base KMS object + * @name: connector name   * @connector_type: one of the %DRM_MODE_CONNECTOR_<foo> types from drm_mode.h   * @connector_type_id: index into connector type enum   * @interlace_allowed: can this connector handle interlaced modes? @@ -587,16 +499,18 @@ enum drm_connector_force {   */  struct drm_connector {  	struct drm_device *dev; -	struct device kdev; +	struct device *kdev;  	struct device_attribute *attr;  	struct list_head head;  	struct drm_mode_object base; +	char *name;  	int connector_type;  	int connector_type_id;  	bool interlace_allowed;  	bool doublescan_allowed; +	bool stereo_allowed;  	struct list_head modes; /* list of modes on this connector */  	enum drm_connector_status status; @@ -654,6 +568,12 @@ struct drm_plane_funcs {  			    struct drm_property *property, uint64_t val);  }; +enum drm_plane_type { +	DRM_PLANE_TYPE_OVERLAY, +	DRM_PLANE_TYPE_PRIMARY, +	DRM_PLANE_TYPE_CURSOR, +}; +  /**   * drm_plane - central DRM plane control structure   * @dev: DRM device this plane belongs to @@ -666,6 +586,7 @@ struct drm_plane_funcs {   * @fb: currently bound fb   * @funcs: helper functions   * @properties: property tracking for this plane + * @type: type of plane (overlay, primary, cursor)   */  struct drm_plane {  	struct drm_device *dev; @@ -683,6 +604,8 @@ struct drm_plane {  	const struct drm_plane_funcs *funcs;  	struct drm_object_properties properties; + +	enum drm_plane_type type;  };  /** @@ -824,6 +747,8 @@ struct drm_mode_group {   */  struct drm_mode_config {  	struct mutex mutex; /* protects configuration (mode lists etc.) */ +	struct drm_modeset_lock connection_mutex; /* protects connector->encoder and encoder->crtc links */ +	struct drm_modeset_acquire_ctx *acquire_ctx; /* for legacy _lock_all() / _unlock_all() */  	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 */ @@ -845,7 +770,15 @@ struct drm_mode_config {  	struct list_head bridge_list;  	int num_encoder;  	struct list_head encoder_list; -	int num_plane; + +	/* +	 * Track # of overlay planes separately from # of total planes.  By +	 * default we only advertise overlay planes to userspace; if userspace +	 * sets the "universal plane" capability bit, we'll go ahead and +	 * expose all planes. +	 */ +	int num_overlay_plane; +	int num_total_plane;  	struct list_head plane_list;  	int num_crtc; @@ -867,6 +800,7 @@ struct drm_mode_config {  	struct list_head property_blob_list;  	struct drm_property *edid_property;  	struct drm_property *dpms_property; +	struct drm_property *plane_type_property;  	/* DVI-I properties */  	struct drm_property *dvi_i_subconnector_property; @@ -896,6 +830,9 @@ struct drm_mode_config {  	/* whether async page flip is supported or not */  	bool async_page_flip; + +	/* cursor size */ +	uint32_t cursor_width, cursor_height;  };  #define obj_to_crtc(x) container_of(x, struct drm_crtc, base) @@ -912,14 +849,28 @@ 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 void drm_warn_on_modeset_not_all_locked(struct drm_device *dev); - +extern int drm_crtc_init_with_planes(struct drm_device *dev, +				     struct drm_crtc *crtc, +				     struct drm_plane *primary, +				     void *cursor, +				     const struct drm_crtc_funcs *funcs);  extern int drm_crtc_init(struct drm_device *dev,  			 struct drm_crtc *crtc,  			 const struct drm_crtc_funcs *funcs);  extern void drm_crtc_cleanup(struct drm_crtc *crtc); +extern unsigned int drm_crtc_index(struct drm_crtc *crtc); + +/** + * drm_crtc_mask - find the mask of a registered CRTC + * @crtc: CRTC to find mask for + * + * Given a registered CRTC, return the mask bit of that CRTC for an + * encoder's possible_crtcs field. + */ +static inline uint32_t drm_crtc_mask(struct drm_crtc *crtc) +{ +	return 1 << drm_crtc_index(crtc); +}  extern void drm_connector_ida_init(void);  extern void drm_connector_ida_destroy(void); @@ -941,19 +892,43 @@ extern int drm_encoder_init(struct drm_device *dev,  			    const struct drm_encoder_funcs *funcs,  			    int encoder_type); +/** + * drm_encoder_crtc_ok - can a given crtc drive a given encoder? + * @encoder: encoder to test + * @crtc: crtc to test + * + * Return false if @encoder can't be driven by @crtc, true otherwise. + */ +static inline bool drm_encoder_crtc_ok(struct drm_encoder *encoder, +				       struct drm_crtc *crtc) +{ +	return !!(encoder->possible_crtcs & drm_crtc_mask(crtc)); +} + +extern int drm_universal_plane_init(struct drm_device *dev, +				    struct drm_plane *plane, +				    unsigned long possible_crtcs, +				    const struct drm_plane_funcs *funcs, +				    const uint32_t *formats, +				    uint32_t format_count, +				    enum drm_plane_type type);  extern int drm_plane_init(struct drm_device *dev,  			  struct drm_plane *plane,  			  unsigned long possible_crtcs,  			  const struct drm_plane_funcs *funcs,  			  const uint32_t *formats, uint32_t format_count, -			  bool priv); +			  bool is_primary);  extern void drm_plane_cleanup(struct drm_plane *plane);  extern void drm_plane_force_disable(struct drm_plane *plane); +extern int drm_crtc_check_viewport(const struct drm_crtc *crtc, +				   int x, int y, +				   const struct drm_display_mode *mode, +				   const struct drm_framebuffer *fb);  extern void drm_encoder_cleanup(struct drm_encoder *encoder); -extern const char *drm_get_connector_name(const struct drm_connector *connector);  extern const char *drm_get_connector_status_name(enum drm_connector_status status); +extern const char *drm_get_subpixel_order_name(enum subpixel_order order);  extern const char *drm_get_dpms_name(int val);  extern const char *drm_get_dvi_i_subconnector_name(int val);  extern const char *drm_get_dvi_i_select_name(int val); @@ -961,40 +936,35 @@ extern const char *drm_get_tv_subconnector_name(int val);  extern const char *drm_get_tv_select_name(int val);  extern void drm_fb_release(struct drm_file *file_priv);  extern int drm_mode_group_init_legacy_group(struct drm_device *dev, struct drm_mode_group *group); +extern void drm_mode_group_destroy(struct drm_mode_group *group);  extern bool drm_probe_ddc(struct i2c_adapter *adapter);  extern struct edid *drm_get_edid(struct drm_connector *connector,  				 struct i2c_adapter *adapter); +extern struct edid *drm_edid_duplicate(const struct edid *edid);  extern int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid); -extern void drm_mode_probed_add(struct drm_connector *connector, struct drm_display_mode *mode); -extern void drm_mode_copy(struct drm_display_mode *dst, const struct drm_display_mode *src); -extern struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev, -						   const struct drm_display_mode *mode); -extern void drm_mode_debug_printmodeline(const struct drm_display_mode *mode);  extern void drm_mode_config_init(struct drm_device *dev);  extern void drm_mode_config_reset(struct drm_device *dev);  extern void drm_mode_config_cleanup(struct drm_device *dev); -extern void drm_mode_set_name(struct drm_display_mode *mode); -extern bool drm_mode_equal(const struct drm_display_mode *mode1, const struct drm_display_mode *mode2); -extern bool drm_mode_equal_no_clocks(const struct drm_display_mode *mode1, const struct drm_display_mode *mode2); -extern int drm_mode_width(const struct drm_display_mode *mode); -extern int drm_mode_height(const struct drm_display_mode *mode); - -/* for us by fb module */ -extern struct drm_display_mode *drm_mode_create(struct drm_device *dev); -extern void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode); -extern void drm_mode_validate_size(struct drm_device *dev, -				   struct list_head *mode_list, -				   int maxX, int maxY, int maxPitch); -extern void drm_mode_prune_invalid(struct drm_device *dev, -				   struct list_head *mode_list, bool verbose); -extern void drm_mode_sort(struct list_head *mode_list); -extern int drm_mode_hsync(const struct drm_display_mode *mode); -extern int drm_mode_vrefresh(const struct drm_display_mode *mode); -extern void drm_mode_set_crtcinfo(struct drm_display_mode *p, -				  int adjust_flags); -extern void drm_mode_connector_list_update(struct drm_connector *connector); +  extern int drm_mode_connector_update_edid_property(struct drm_connector *connector,  						struct edid *edid); + +static inline bool drm_property_type_is(struct drm_property *property, +		uint32_t type) +{ +	/* instanceof for props.. handles extended type vs original types: */ +	if (property->flags & DRM_MODE_PROP_EXTENDED_TYPE) +		return (property->flags & DRM_MODE_PROP_EXTENDED_TYPE) == type; +	return property->flags & type; +} + +static inline bool drm_property_type_valid(struct drm_property *property) +{ +	if (property->flags & DRM_MODE_PROP_EXTENDED_TYPE) +		return !(property->flags & DRM_MODE_PROP_LEGACY_TYPE); +	return !!(property->flags & DRM_MODE_PROP_LEGACY_TYPE); +} +  extern int drm_object_property_set_value(struct drm_mode_object *obj,  					 struct drm_property *property,  					 uint64_t val); @@ -1028,6 +998,11 @@ struct drm_property *drm_property_create_bitmask(struct drm_device *dev,  struct drm_property *drm_property_create_range(struct drm_device *dev, int flags,  					 const char *name,  					 uint64_t min, uint64_t max); +struct drm_property *drm_property_create_signed_range(struct drm_device *dev, +					 int flags, const char *name, +					 int64_t min, int64_t max); +struct drm_property *drm_property_create_object(struct drm_device *dev, +					 int flags, const char *name, uint32_t type);  extern void drm_property_destroy(struct drm_device *dev, struct drm_property *property);  extern int drm_property_add_enum(struct drm_property *property, int index,  				 uint64_t value, const char *name); @@ -1036,16 +1011,14 @@ extern int drm_mode_create_tv_properties(struct drm_device *dev, int num_formats  				     char *formats[]);  extern int drm_mode_create_scaling_mode_property(struct drm_device *dev);  extern int drm_mode_create_dirty_info_property(struct drm_device *dev); -extern const char *drm_get_encoder_name(const struct drm_encoder *encoder);  extern int drm_mode_connector_attach_encoder(struct drm_connector *connector,  					     struct drm_encoder *encoder); -extern void drm_mode_connector_detach_encoder(struct drm_connector *connector, -					   struct drm_encoder *encoder);  extern int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc,  					 int gamma_size);  extern struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,  		uint32_t id, uint32_t type); +  /* IOCTLs */  extern int drm_mode_getresources(struct drm_device *dev,  				 void *data, struct drm_file *file_priv); @@ -1091,23 +1064,16 @@ extern int drm_mode_gamma_get_ioctl(struct drm_device *dev,  extern int drm_mode_gamma_set_ioctl(struct drm_device *dev,  				    void *data, struct drm_file *file_priv);  extern u8 drm_match_cea_mode(const struct drm_display_mode *to_match); +extern enum hdmi_picture_aspect drm_get_cea_aspect_ratio(const u8 video_code);  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, -				int hdisplay, int vdisplay, int vrefresh, -				bool reduced, bool interlaced, bool margins); -extern struct drm_display_mode *drm_gtf_mode(struct drm_device *dev, -				int hdisplay, int vdisplay, int vrefresh, -				bool interlaced, int margins); -extern struct drm_display_mode *drm_gtf_mode_complex(struct drm_device *dev, -				int hdisplay, int vdisplay, int vrefresh, -				bool interlaced, int margins, int GTF_M, -				int GTF_2C, int GTF_K, int GTF_2J);  extern int drm_add_modes_noedid(struct drm_connector *connector,  				int hdisplay, int vdisplay); +extern void drm_set_preferred_mode(struct drm_connector *connector, +				   int hpref, int vpref);  extern int drm_edid_header_is_valid(const u8 *raw_edid);  extern bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid); @@ -1135,4 +1101,59 @@ extern int drm_format_horz_chroma_subsampling(uint32_t format);  extern int drm_format_vert_chroma_subsampling(uint32_t format);  extern const char *drm_get_format_name(uint32_t format); +/* Helpers */ + +static inline struct drm_plane *drm_plane_find(struct drm_device *dev, +		uint32_t id) +{ +	struct drm_mode_object *mo; +	mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_PLANE); +	return mo ? obj_to_plane(mo) : NULL; +} + +static inline struct drm_crtc *drm_crtc_find(struct drm_device *dev, +	uint32_t id) +{ +	struct drm_mode_object *mo; +	mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_CRTC); +	return mo ? obj_to_crtc(mo) : NULL; +} + +static inline struct drm_encoder *drm_encoder_find(struct drm_device *dev, +	uint32_t id) +{ +	struct drm_mode_object *mo; +	mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_ENCODER); +	return mo ? obj_to_encoder(mo) : NULL; +} + +static inline struct drm_connector *drm_connector_find(struct drm_device *dev, +		uint32_t id) +{ +	struct drm_mode_object *mo; +	mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_CONNECTOR); +	return mo ? obj_to_connector(mo) : NULL; +} + +static inline struct drm_property *drm_property_find(struct drm_device *dev, +		uint32_t id) +{ +	struct drm_mode_object *mo; +	mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_PROPERTY); +	return mo ? obj_to_property(mo) : NULL; +} + +static inline struct drm_property_blob * +drm_property_blob_find(struct drm_device *dev, uint32_t id) +{ +	struct drm_mode_object *mo; +	mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_BLOB); +	return mo ? obj_to_blob(mo) : NULL; +} + +/* Plane list iterator for legacy (overlay only) planes. */ +#define drm_for_each_legacy_plane(plane, planelist) \ +	list_for_each_entry(plane, planelist, head) \ +		if (plane->type == DRM_PLANE_TYPE_OVERLAY) +  #endif /* __DRM_CRTC_H__ */ diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h index f43d556bf40..a3d75fefd01 100644 --- a/include/drm/drm_crtc_helper.h +++ b/include/drm/drm_crtc_helper.h @@ -114,18 +114,17 @@ struct drm_encoder_helper_funcs {  /**   * drm_connector_helper_funcs - helper operations for connectors   * @get_modes: get mode list for this connector - * @mode_valid: is this mode valid on the given connector? + * @mode_valid (optional): is this mode valid on the given connector?   *   * The helper operations are called by the mid-layer CRTC helper.   */  struct drm_connector_helper_funcs {  	int (*get_modes)(struct drm_connector *connector); -	int (*mode_valid)(struct drm_connector *connector, -			  struct drm_display_mode *mode); +	enum drm_mode_status (*mode_valid)(struct drm_connector *connector, +					   struct drm_display_mode *mode);  	struct drm_encoder *(*best_encoder)(struct drm_connector *connector);  }; -extern int drm_helper_probe_single_connector_modes(struct drm_connector *connector, uint32_t maxX, uint32_t maxY);  extern void drm_helper_disable_unused_functions(struct drm_device *dev);  extern int drm_crtc_helper_set_config(struct drm_mode_set *set);  extern bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, @@ -139,8 +138,8 @@ extern void drm_helper_connector_dpms(struct drm_connector *connector, int mode)  extern void drm_helper_move_panel_connectors_to_head(struct drm_device *); -extern int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, -					  struct drm_mode_fb_cmd2 *mode_cmd); +extern void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, +					   struct drm_mode_fb_cmd2 *mode_cmd);  static inline void drm_crtc_helper_add(struct drm_crtc *crtc,  				       const struct drm_crtc_helper_funcs *funcs) @@ -160,10 +159,19 @@ static inline void drm_connector_helper_add(struct drm_connector *connector,  	connector->helper_private = (void *)funcs;  } -extern int drm_helper_resume_force_mode(struct drm_device *dev); +extern void drm_helper_resume_force_mode(struct drm_device *dev); + +/* drm_probe_helper.c */ +extern int drm_helper_probe_single_connector_modes(struct drm_connector +						   *connector, uint32_t maxX, +						   uint32_t maxY); +extern int drm_helper_probe_single_connector_modes_nomerge(struct drm_connector +							   *connector, +							   uint32_t maxX, +							   uint32_t maxY);  extern void drm_kms_helper_poll_init(struct drm_device *dev);  extern void drm_kms_helper_poll_fini(struct drm_device *dev); -extern void drm_helper_hpd_irq_event(struct drm_device *dev); +extern bool drm_helper_hpd_irq_event(struct drm_device *dev);  extern void drm_kms_helper_hotplug_event(struct drm_device *dev);  extern void drm_kms_helper_poll_disable(struct drm_device *dev); diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index ae8dbfb1207..a21568bf151 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -37,26 +37,27 @@   * eDP: Embedded DisplayPort version 1   * DPI: DisplayPort Interoperability Guideline v1.1a   * 1.2: DisplayPort 1.2 + * MST: Multistream Transport - part of DP 1.2a   *   * 1.2 formally includes both eDP and DPI definitions.   */ -#define AUX_NATIVE_WRITE	0x8 -#define AUX_NATIVE_READ		0x9 -#define AUX_I2C_WRITE		0x0 -#define AUX_I2C_READ		0x1 -#define AUX_I2C_STATUS		0x2 -#define AUX_I2C_MOT		0x4 +#define DP_AUX_I2C_WRITE		0x0 +#define DP_AUX_I2C_READ			0x1 +#define DP_AUX_I2C_STATUS		0x2 +#define DP_AUX_I2C_MOT			0x4 +#define DP_AUX_NATIVE_WRITE		0x8 +#define DP_AUX_NATIVE_READ		0x9 -#define AUX_NATIVE_REPLY_ACK	(0x0 << 4) -#define AUX_NATIVE_REPLY_NACK	(0x1 << 4) -#define AUX_NATIVE_REPLY_DEFER	(0x2 << 4) -#define AUX_NATIVE_REPLY_MASK	(0x3 << 4) +#define DP_AUX_NATIVE_REPLY_ACK		(0x0 << 0) +#define DP_AUX_NATIVE_REPLY_NACK	(0x1 << 0) +#define DP_AUX_NATIVE_REPLY_DEFER	(0x2 << 0) +#define DP_AUX_NATIVE_REPLY_MASK	(0x3 << 0) -#define AUX_I2C_REPLY_ACK	(0x0 << 6) -#define AUX_I2C_REPLY_NACK	(0x1 << 6) -#define AUX_I2C_REPLY_DEFER	(0x2 << 6) -#define AUX_I2C_REPLY_MASK	(0x3 << 6) +#define DP_AUX_I2C_REPLY_ACK		(0x0 << 2) +#define DP_AUX_I2C_REPLY_NACK		(0x1 << 2) +#define DP_AUX_I2C_REPLY_DEFER		(0x2 << 2) +#define DP_AUX_I2C_REPLY_MASK		(0x3 << 2)  /* AUX CH addresses */  /* DPCD */ @@ -77,10 +78,10 @@  #define DP_DOWNSTREAMPORT_PRESENT           0x005  # define DP_DWN_STRM_PORT_PRESENT           (1 << 0)  # define DP_DWN_STRM_PORT_TYPE_MASK         0x06 -/* 00b = DisplayPort */ -/* 01b = Analog */ -/* 10b = TMDS or HDMI */ -/* 11b = Other */ +# define DP_DWN_STRM_PORT_TYPE_DP           (0 << 1) +# define DP_DWN_STRM_PORT_TYPE_ANALOG       (1 << 1) +# define DP_DWN_STRM_PORT_TYPE_TMDS         (2 << 1) +# define DP_DWN_STRM_PORT_TYPE_OTHER        (3 << 1)  # define DP_FORMAT_CONVERSION               (1 << 3)  # define DP_DETAILED_CAP_INFO_AVAILABLE	    (1 << 4) /* DPI */ @@ -103,9 +104,14 @@  #define DP_TRAINING_AUX_RD_INTERVAL         0x00e   /* XXX 1.2? */  /* Multiple stream transport */ +#define DP_FAUX_CAP			    0x020   /* 1.2 */ +# define DP_FAUX_CAP_1			    (1 << 0) +  #define DP_MSTM_CAP			    0x021   /* 1.2 */  # define DP_MST_CAP			    (1 << 0) +#define DP_GUID				    0x030   /* 1.2 */ +  #define DP_PSR_SUPPORT                      0x070   /* XXX 1.2? */  # define DP_PSR_IS_SUPPORTED                1  #define DP_PSR_CAPS                         0x071   /* XXX 1.2? */ @@ -221,6 +227,16 @@  # define DP_PSR_CRC_VERIFICATION	    (1 << 2)  # define DP_PSR_FRAME_CAPTURE		    (1 << 3) +#define DP_ADAPTER_CTRL			    0x1a0 +# define DP_ADAPTER_CTRL_FORCE_LOAD_SENSE   (1 << 0) + +#define DP_BRANCH_DEVICE_CTRL		    0x1a1 +# define DP_BRANCH_DEVICE_IRQ_HPD	    (1 << 0) + +#define DP_PAYLOAD_ALLOCATE_SET		    0x1c0 +#define DP_PAYLOAD_ALLOCATE_START_TIME_SLOT 0x1c1 +#define DP_PAYLOAD_ALLOCATE_TIME_SLOT_COUNT 0x1c2 +  #define DP_SINK_COUNT			    0x200  /* prior to 1.2 bit 7 was reserved mbz */  # define DP_GET_SINK_COUNT(x)		    ((((x) & 0x80) >> 1) | ((x) & 0x3f)) @@ -230,6 +246,9 @@  # define DP_REMOTE_CONTROL_COMMAND_PENDING  (1 << 0)  # define DP_AUTOMATED_TEST_REQUEST	    (1 << 1)  # define DP_CP_IRQ			    (1 << 2) +# define DP_MCCS_IRQ			    (1 << 3) +# define DP_DOWN_REP_MSG_RDY		    (1 << 4) /* 1.2 MST */ +# define DP_UP_REQ_MSG_RDY		    (1 << 5) /* 1.2 MST */  # define DP_SINK_SPECIFIC_IRQ		    (1 << 6)  #define DP_LANE0_1_STATUS		    0x202 @@ -266,9 +285,10 @@  #define DP_TEST_REQUEST			    0x218  # define DP_TEST_LINK_TRAINING		    (1 << 0) -# define DP_TEST_LINK_PATTERN		    (1 << 1) +# define DP_TEST_LINK_VIDEO_PATTERN	    (1 << 1)  # define DP_TEST_LINK_EDID_READ		    (1 << 2)  # define DP_TEST_LINK_PHY_TEST_PATTERN	    (1 << 3) /* DPCD >= 1.1 */ +# define DP_TEST_LINK_FAUX_PATTERN	    (1 << 4) /* DPCD >= 1.2 */  #define DP_TEST_LINK_RATE		    0x219  # define DP_LINK_RATE_162		    (0x6) @@ -278,11 +298,30 @@  #define DP_TEST_PATTERN			    0x221 +#define DP_TEST_CRC_R_CR		    0x240 +#define DP_TEST_CRC_G_Y			    0x242 +#define DP_TEST_CRC_B_CB		    0x244 + +#define DP_TEST_SINK_MISC		    0x246 +#define DP_TEST_CRC_SUPPORTED		    (1 << 5) +  #define DP_TEST_RESPONSE		    0x260  # define DP_TEST_ACK			    (1 << 0)  # define DP_TEST_NAK			    (1 << 1)  # define DP_TEST_EDID_CHECKSUM_WRITE	    (1 << 2) +#define DP_TEST_EDID_CHECKSUM		    0x261 + +#define DP_TEST_SINK			    0x270 +#define DP_TEST_SINK_START	    (1 << 0) + +#define DP_PAYLOAD_TABLE_UPDATE_STATUS      0x2c0   /* 1.2 MST */ +# define DP_PAYLOAD_TABLE_UPDATED           (1 << 0) +# define DP_PAYLOAD_ACT_HANDLED             (1 << 1) + +#define DP_VC_PAYLOAD_ID_SLOT_1             0x2c1   /* 1.2 MST */ +/* up to ID_SLOT_63 at 0x2ff */ +  #define DP_SOURCE_OUI			    0x300  #define DP_SINK_OUI			    0x400  #define DP_BRANCH_OUI			    0x500 @@ -290,6 +329,22 @@  #define DP_SET_POWER                        0x600  # define DP_SET_POWER_D0                    0x1  # define DP_SET_POWER_D3                    0x2 +# define DP_SET_POWER_MASK                  0x3 + +#define DP_SIDEBAND_MSG_DOWN_REQ_BASE	    0x1000   /* 1.2 MST */ +#define DP_SIDEBAND_MSG_UP_REP_BASE	    0x1200   /* 1.2 MST */ +#define DP_SIDEBAND_MSG_DOWN_REP_BASE	    0x1400   /* 1.2 MST */ +#define DP_SIDEBAND_MSG_UP_REQ_BASE	    0x1600   /* 1.2 MST */ + +#define DP_SINK_COUNT_ESI		    0x2002   /* 1.2 */ +/* 0-5 sink count */ +# define DP_SINK_COUNT_CP_READY             (1 << 6) + +#define DP_DEVICE_SERVICE_IRQ_VECTOR_ESI0   0x2003   /* 1.2 */ + +#define DP_DEVICE_SERVICE_IRQ_VECTOR_ESI1   0x2004   /* 1.2 */ + +#define DP_LINK_SERVICE_IRQ_VECTOR_ESI0     0x2005   /* 1.2 */  #define DP_PSR_ERROR_STATUS                 0x2006  /* XXX 1.2? */  # define DP_PSR_LINK_CRC_ERROR              (1 << 0) @@ -307,6 +362,43 @@  # define DP_PSR_SINK_INTERNAL_ERROR         7  # define DP_PSR_SINK_STATE_MASK             0x07 +/* DP 1.2 Sideband message defines */ +/* peer device type - DP 1.2a Table 2-92 */ +#define DP_PEER_DEVICE_NONE		0x0 +#define DP_PEER_DEVICE_SOURCE_OR_SST	0x1 +#define DP_PEER_DEVICE_MST_BRANCHING	0x2 +#define DP_PEER_DEVICE_SST_SINK		0x3 +#define DP_PEER_DEVICE_DP_LEGACY_CONV	0x4 + +/* DP 1.2 MST sideband request names DP 1.2a Table 2-80 */ +#define DP_LINK_ADDRESS			0x01 +#define DP_CONNECTION_STATUS_NOTIFY	0x02 +#define DP_ENUM_PATH_RESOURCES		0x10 +#define DP_ALLOCATE_PAYLOAD		0x11 +#define DP_QUERY_PAYLOAD		0x12 +#define DP_RESOURCE_STATUS_NOTIFY	0x13 +#define DP_CLEAR_PAYLOAD_ID_TABLE	0x14 +#define DP_REMOTE_DPCD_READ		0x20 +#define DP_REMOTE_DPCD_WRITE		0x21 +#define DP_REMOTE_I2C_READ		0x22 +#define DP_REMOTE_I2C_WRITE		0x23 +#define DP_POWER_UP_PHY			0x24 +#define DP_POWER_DOWN_PHY		0x25 +#define DP_SINK_EVENT_NOTIFY		0x30 +#define DP_QUERY_STREAM_ENC_STATUS	0x38 + +/* DP 1.2 MST sideband nak reasons - table 2.84 */ +#define DP_NAK_WRITE_FAILURE		0x01 +#define DP_NAK_INVALID_READ		0x02 +#define DP_NAK_CRC_FAILURE		0x03 +#define DP_NAK_BAD_PARAM		0x04 +#define DP_NAK_DEFER			0x05 +#define DP_NAK_LINK_FAILURE		0x06 +#define DP_NAK_NO_RESOURCES		0x07 +#define DP_NAK_DPCD_FAIL		0x08 +#define DP_NAK_I2C_NAK			0x09 +#define DP_NAK_ALLOCATE_FAIL		0x0a +  #define MODE_I2C_START	1  #define MODE_I2C_WRITE	2  #define MODE_I2C_READ	4 @@ -333,20 +425,20 @@ i2c_dp_aux_add_bus(struct i2c_adapter *adapter);  #define DP_LINK_STATUS_SIZE	   6 -bool drm_dp_channel_eq_ok(u8 link_status[DP_LINK_STATUS_SIZE], +bool drm_dp_channel_eq_ok(const u8 link_status[DP_LINK_STATUS_SIZE],  			  int lane_count); -bool drm_dp_clock_recovery_ok(u8 link_status[DP_LINK_STATUS_SIZE], +bool drm_dp_clock_recovery_ok(const u8 link_status[DP_LINK_STATUS_SIZE],  			      int lane_count); -u8 drm_dp_get_adjust_request_voltage(u8 link_status[DP_LINK_STATUS_SIZE], +u8 drm_dp_get_adjust_request_voltage(const u8 link_status[DP_LINK_STATUS_SIZE],  				     int lane); -u8 drm_dp_get_adjust_request_pre_emphasis(u8 link_status[DP_LINK_STATUS_SIZE], +u8 drm_dp_get_adjust_request_pre_emphasis(const u8 link_status[DP_LINK_STATUS_SIZE],  					  int lane);  #define DP_RECEIVER_CAP_SIZE		0xf  #define EDP_PSR_RECEIVER_CAP_SIZE	2 -void drm_dp_link_train_clock_recovery_delay(u8 dpcd[DP_RECEIVER_CAP_SIZE]); -void drm_dp_link_train_channel_eq_delay(u8 dpcd[DP_RECEIVER_CAP_SIZE]); +void drm_dp_link_train_clock_recovery_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE]); +void drm_dp_link_train_channel_eq_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE]);  u8 drm_dp_link_rate_to_bw_code(int link_rate);  int drm_dp_bw_code_to_link_rate(u8 link_bw); @@ -379,15 +471,142 @@ struct edp_vsc_psr {  #define EDP_VSC_PSR_CRC_VALUES_VALID	(1<<2)  static inline int -drm_dp_max_link_rate(u8 dpcd[DP_RECEIVER_CAP_SIZE]) +drm_dp_max_link_rate(const u8 dpcd[DP_RECEIVER_CAP_SIZE])  {  	return drm_dp_bw_code_to_link_rate(dpcd[DP_MAX_LINK_RATE]);  }  static inline u8 -drm_dp_max_lane_count(u8 dpcd[DP_RECEIVER_CAP_SIZE]) +drm_dp_max_lane_count(const u8 dpcd[DP_RECEIVER_CAP_SIZE])  {  	return dpcd[DP_MAX_LANE_COUNT] & DP_MAX_LANE_COUNT_MASK;  } +static inline bool +drm_dp_enhanced_frame_cap(const u8 dpcd[DP_RECEIVER_CAP_SIZE]) +{ +	return dpcd[DP_DPCD_REV] >= 0x11 && +		(dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP); +} + +/* + * DisplayPort AUX channel + */ + +/** + * struct drm_dp_aux_msg - DisplayPort AUX channel transaction + * @address: address of the (first) register to access + * @request: contains the type of transaction (see DP_AUX_* macros) + * @reply: upon completion, contains the reply type of the transaction + * @buffer: pointer to a transmission or reception buffer + * @size: size of @buffer + */ +struct drm_dp_aux_msg { +	unsigned int address; +	u8 request; +	u8 reply; +	void *buffer; +	size_t size; +}; + +/** + * struct drm_dp_aux - DisplayPort AUX channel + * @name: user-visible name of this AUX channel and the I2C-over-AUX adapter + * @ddc: I2C adapter that can be used for I2C-over-AUX communication + * @dev: pointer to struct device that is the parent for this AUX channel + * @hw_mutex: internal mutex used for locking transfers + * @transfer: transfers a message representing a single AUX transaction + * + * The .dev field should be set to a pointer to the device that implements + * the AUX channel. + * + * The .name field may be used to specify the name of the I2C adapter. If set to + * NULL, dev_name() of .dev will be used. + * + * Drivers provide a hardware-specific implementation of how transactions + * are executed via the .transfer() function. A pointer to a drm_dp_aux_msg + * structure describing the transaction is passed into this function. Upon + * success, the implementation should return the number of payload bytes + * that were transferred, or a negative error-code on failure. Helpers + * propagate errors from the .transfer() function, with the exception of + * the -EBUSY error, which causes a transaction to be retried. On a short, + * helpers will return -EPROTO to make it simpler to check for failure. + * + * An AUX channel can also be used to transport I2C messages to a sink. A + * typical application of that is to access an EDID that's present in the + * sink device. The .transfer() function can also be used to execute such + * transactions. The drm_dp_aux_register_i2c_bus() function registers an + * I2C adapter that can be passed to drm_probe_ddc(). Upon removal, drivers + * should call drm_dp_aux_unregister_i2c_bus() to remove the I2C adapter. + * + * Note that the aux helper code assumes that the .transfer() function + * only modifies the reply field of the drm_dp_aux_msg structure.  The + * retry logic and i2c helpers assume this is the case. + */ +struct drm_dp_aux { +	const char *name; +	struct i2c_adapter ddc; +	struct device *dev; +	struct mutex hw_mutex; +	ssize_t (*transfer)(struct drm_dp_aux *aux, +			    struct drm_dp_aux_msg *msg); +}; + +ssize_t drm_dp_dpcd_read(struct drm_dp_aux *aux, unsigned int offset, +			 void *buffer, size_t size); +ssize_t drm_dp_dpcd_write(struct drm_dp_aux *aux, unsigned int offset, +			  void *buffer, size_t size); + +/** + * drm_dp_dpcd_readb() - read a single byte from the DPCD + * @aux: DisplayPort AUX channel + * @offset: address of the register to read + * @valuep: location where the value of the register will be stored + * + * Returns the number of bytes transferred (1) on success, or a negative + * error code on failure. + */ +static inline ssize_t drm_dp_dpcd_readb(struct drm_dp_aux *aux, +					unsigned int offset, u8 *valuep) +{ +	return drm_dp_dpcd_read(aux, offset, valuep, 1); +} + +/** + * drm_dp_dpcd_writeb() - write a single byte to the DPCD + * @aux: DisplayPort AUX channel + * @offset: address of the register to write + * @value: value to write to the register + * + * Returns the number of bytes transferred (1) on success, or a negative + * error code on failure. + */ +static inline ssize_t drm_dp_dpcd_writeb(struct drm_dp_aux *aux, +					 unsigned int offset, u8 value) +{ +	return drm_dp_dpcd_write(aux, offset, &value, 1); +} + +int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux, +				 u8 status[DP_LINK_STATUS_SIZE]); + +/* + * DisplayPort link + */ +#define DP_LINK_CAP_ENHANCED_FRAMING (1 << 0) + +struct drm_dp_link { +	unsigned char revision; +	unsigned int rate; +	unsigned int num_lanes; +	unsigned long capabilities; +}; + +int drm_dp_link_probe(struct drm_dp_aux *aux, struct drm_dp_link *link); +int drm_dp_link_power_up(struct drm_dp_aux *aux, struct drm_dp_link *link); +int drm_dp_link_configure(struct drm_dp_aux *aux, struct drm_dp_link *link); + +int drm_dp_aux_register(struct drm_dp_aux *aux); +void drm_dp_aux_unregister(struct drm_dp_aux *aux); +  #endif /* _DRM_DP_HELPER_H_ */ diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index a1441c5ac63..b96031d947a 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h @@ -202,6 +202,11 @@ struct detailed_timing {  #define DRM_EDID_FEATURE_PM_SUSPEND       (1 << 6)  #define DRM_EDID_FEATURE_PM_STANDBY       (1 << 7) +#define DRM_EDID_HDMI_DC_48               (1 << 6) +#define DRM_EDID_HDMI_DC_36               (1 << 5) +#define DRM_EDID_HDMI_DC_30               (1 << 4) +#define DRM_EDID_HDMI_DC_Y444             (1 << 3) +  struct edid {  	u8 header[8];  	/* Vendor & product info */ diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index 471f276ce8f..7997246d403 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -55,7 +55,7 @@ struct drm_fb_helper_surface_size {   *             save the current lut when force-restoring the fbdev for e.g.   *             kdbg.   * @fb_probe: Driver callback to allocate and initialize the fbdev info - *            structure. Futhermore it also needs to allocate the drm + *            structure. Furthermore it also needs to allocate the drm   *            framebuffer used to back the fbdev.   * @initial_config: Setup an initial fbdev display configuration   * @@ -108,7 +108,7 @@ int drm_fb_helper_set_par(struct fb_info *info);  int drm_fb_helper_check_var(struct fb_var_screeninfo *var,  			    struct fb_info *info); -bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper); +bool drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper);  void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helper,  			    uint32_t fb_width, uint32_t fb_height);  void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch, @@ -121,5 +121,11 @@ bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel);  int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper);  int drm_fb_helper_debug_enter(struct fb_info *info);  int drm_fb_helper_debug_leave(struct fb_info *info); +struct drm_display_mode * +drm_has_preferred_mode(struct drm_fb_helper_connector *fb_connector, +			int width, int height); +struct drm_display_mode * +drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn, +		      int width, int height);  #endif diff --git a/include/drm/drm_flip_work.h b/include/drm/drm_flip_work.h index 35c776ae7d3..9eed34dcd6a 100644 --- a/include/drm/drm_flip_work.h +++ b/include/drm/drm_flip_work.h @@ -57,6 +57,7 @@ typedef void (*drm_flip_func_t)(struct drm_flip_work *work, void *val);   * @count: number of committed items   * @func: callback fxn called for each committed item   * @worker: worker which calls @func + * @fifo: queue of committed items   */  struct drm_flip_work {  	const char *name; diff --git a/include/drm/drm_gem_cma_helper.h b/include/drm/drm_gem_cma_helper.h index 89b4d7db1eb..2a3cea91606 100644 --- a/include/drm/drm_gem_cma_helper.h +++ b/include/drm/drm_gem_cma_helper.h @@ -1,6 +1,8 @@  #ifndef __DRM_GEM_CMA_HELPER_H__  #define __DRM_GEM_CMA_HELPER_H__ +#include <drm/drmP.h> +  struct drm_gem_cma_object {  	struct drm_gem_object base;  	dma_addr_t paddr; diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h new file mode 100644 index 00000000000..944f33f8ba3 --- /dev/null +++ b/include/drm/drm_mipi_dsi.h @@ -0,0 +1,166 @@ +/* + * MIPI DSI Bus + * + * Copyright (C) 2012-2013, Samsung Electronics, Co., Ltd. + * Andrzej Hajda <a.hajda@samsung.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __DRM_MIPI_DSI_H__ +#define __DRM_MIPI_DSI_H__ + +#include <linux/device.h> + +struct mipi_dsi_host; +struct mipi_dsi_device; + +/* request ACK from peripheral */ +#define MIPI_DSI_MSG_REQ_ACK	BIT(0) +/* use Low Power Mode to transmit message */ +#define MIPI_DSI_MSG_USE_LPM	BIT(1) + +/** + * struct mipi_dsi_msg - read/write DSI buffer + * @channel: virtual channel id + * @type: payload data type + * @tx_len: length of @tx_buf + * @tx_buf: data to be written + * @rx_len: length of @rx_buf + * @rx_buf: data to be read, or NULL + */ +struct mipi_dsi_msg { +	u8 channel; +	u8 type; +	u16 flags; + +	size_t tx_len; +	const void *tx_buf; + +	size_t rx_len; +	void *rx_buf; +}; + +/** + * struct mipi_dsi_host_ops - DSI bus operations + * @attach: attach DSI device to DSI host + * @detach: detach DSI device from DSI host + * @transfer: send and/or receive DSI packet, return number of received bytes, + * 	      or error + */ +struct mipi_dsi_host_ops { +	int (*attach)(struct mipi_dsi_host *host, +		      struct mipi_dsi_device *dsi); +	int (*detach)(struct mipi_dsi_host *host, +		      struct mipi_dsi_device *dsi); +	ssize_t (*transfer)(struct mipi_dsi_host *host, +			    struct mipi_dsi_msg *msg); +}; + +/** + * struct mipi_dsi_host - DSI host device + * @dev: driver model device node for this DSI host + * @ops: DSI host operations + */ +struct mipi_dsi_host { +	struct device *dev; +	const struct mipi_dsi_host_ops *ops; +}; + +int mipi_dsi_host_register(struct mipi_dsi_host *host); +void mipi_dsi_host_unregister(struct mipi_dsi_host *host); + +/* DSI mode flags */ + +/* video mode */ +#define MIPI_DSI_MODE_VIDEO		BIT(0) +/* video burst mode */ +#define MIPI_DSI_MODE_VIDEO_BURST	BIT(1) +/* video pulse mode */ +#define MIPI_DSI_MODE_VIDEO_SYNC_PULSE	BIT(2) +/* enable auto vertical count mode */ +#define MIPI_DSI_MODE_VIDEO_AUTO_VERT	BIT(3) +/* enable hsync-end packets in vsync-pulse and v-porch area */ +#define MIPI_DSI_MODE_VIDEO_HSE		BIT(4) +/* disable hfront-porch area */ +#define MIPI_DSI_MODE_VIDEO_HFP		BIT(5) +/* disable hback-porch area */ +#define MIPI_DSI_MODE_VIDEO_HBP		BIT(6) +/* disable hsync-active area */ +#define MIPI_DSI_MODE_VIDEO_HSA		BIT(7) +/* flush display FIFO on vsync pulse */ +#define MIPI_DSI_MODE_VSYNC_FLUSH	BIT(8) +/* disable EoT packets in HS mode */ +#define MIPI_DSI_MODE_EOT_PACKET	BIT(9) + +enum mipi_dsi_pixel_format { +	MIPI_DSI_FMT_RGB888, +	MIPI_DSI_FMT_RGB666, +	MIPI_DSI_FMT_RGB666_PACKED, +	MIPI_DSI_FMT_RGB565, +}; + +/** + * struct mipi_dsi_device - DSI peripheral device + * @host: DSI host for this peripheral + * @dev: driver model device node for this peripheral + * @channel: virtual channel assigned to the peripheral + * @format: pixel format for video mode + * @lanes: number of active data lanes + * @mode_flags: DSI operation mode related flags + */ +struct mipi_dsi_device { +	struct mipi_dsi_host *host; +	struct device dev; + +	unsigned int channel; +	unsigned int lanes; +	enum mipi_dsi_pixel_format format; +	unsigned long mode_flags; +}; + +#define to_mipi_dsi_device(d) container_of(d, struct mipi_dsi_device, dev) + +int mipi_dsi_attach(struct mipi_dsi_device *dsi); +int mipi_dsi_detach(struct mipi_dsi_device *dsi); +int mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, unsigned int channel, +		       const void *data, size_t len); +ssize_t mipi_dsi_dcs_read(struct mipi_dsi_device *dsi, unsigned int channel, +			  u8 cmd, void *data, size_t len); + +/** + * struct mipi_dsi_driver - DSI driver + * @driver: device driver model driver + * @probe: callback for device binding + * @remove: callback for device unbinding + * @shutdown: called at shutdown time to quiesce the device + */ +struct mipi_dsi_driver { +	struct device_driver driver; +	int(*probe)(struct mipi_dsi_device *dsi); +	int(*remove)(struct mipi_dsi_device *dsi); +	void (*shutdown)(struct mipi_dsi_device *dsi); +}; + +#define to_mipi_dsi_driver(d) container_of(d, struct mipi_dsi_driver, driver) + +static inline void *mipi_dsi_get_drvdata(const struct mipi_dsi_device *dsi) +{ +	return dev_get_drvdata(&dsi->dev); +} + +static inline void mipi_dsi_set_drvdata(struct mipi_dsi_device *dsi, void *data) +{ +	dev_set_drvdata(&dsi->dev, data); +} + +int mipi_dsi_driver_register(struct mipi_dsi_driver *driver); +void mipi_dsi_driver_unregister(struct mipi_dsi_driver *driver); + +#define module_mipi_dsi_driver(__mipi_dsi_driver) \ +	module_driver(__mipi_dsi_driver, mipi_dsi_driver_register, \ +			mipi_dsi_driver_unregister) + +#endif /* __DRM_MIPI_DSI__ */ diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h index cba67865d18..a24addfdfce 100644 --- a/include/drm/drm_mm.h +++ b/include/drm/drm_mm.h @@ -47,8 +47,17 @@  enum drm_mm_search_flags {  	DRM_MM_SEARCH_DEFAULT =		0,  	DRM_MM_SEARCH_BEST =		1 << 0, +	DRM_MM_SEARCH_BELOW =		1 << 1,  }; +enum drm_mm_allocator_flags { +	DRM_MM_CREATE_DEFAULT =		0, +	DRM_MM_CREATE_TOP =		1 << 0, +}; + +#define DRM_MM_BOTTOMUP DRM_MM_SEARCH_DEFAULT, DRM_MM_CREATE_DEFAULT +#define DRM_MM_TOPDOWN DRM_MM_SEARCH_BELOW, DRM_MM_CREATE_TOP +  struct drm_mm_node {  	struct list_head node_list;  	struct list_head hole_stack; @@ -85,11 +94,31 @@ struct drm_mm {  			     unsigned long *start, unsigned long *end);  }; +/** + * drm_mm_node_allocated - checks whether a node is allocated + * @node: drm_mm_node to check + * + * Drivers should use this helpers for proper encapusulation of drm_mm + * internals. + * + * Returns: + * True if the @node is allocated. + */  static inline bool drm_mm_node_allocated(struct drm_mm_node *node)  {  	return node->allocated;  } +/** + * drm_mm_initialized - checks whether an allocator is initialized + * @mm: drm_mm to check + * + * Drivers should use this helpers for proper encapusulation of drm_mm + * internals. + * + * Returns: + * True if the @mm is initialized. + */  static inline bool drm_mm_initialized(struct drm_mm *mm)  {  	return mm->hole_stack.next; @@ -100,6 +129,17 @@ static inline unsigned long __drm_mm_hole_node_start(struct drm_mm_node *hole_no  	return hole_node->start + hole_node->size;  } +/** + * drm_mm_hole_node_start - computes the start of the hole following @node + * @hole_node: drm_mm_node which implicitly tracks the following hole + * + * This is useful for driver-sepific debug dumpers. Otherwise drivers should not + * inspect holes themselves. Drivers must check first whether a hole indeed + * follows by looking at node->hole_follows. + * + * Returns: + * Start of the subsequent hole. + */  static inline unsigned long drm_mm_hole_node_start(struct drm_mm_node *hole_node)  {  	BUG_ON(!hole_node->hole_follows); @@ -112,18 +152,52 @@ static inline unsigned long __drm_mm_hole_node_end(struct drm_mm_node *hole_node  			  struct drm_mm_node, node_list)->start;  } +/** + * drm_mm_hole_node_end - computes the end of the hole following @node + * @hole_node: drm_mm_node which implicitly tracks the following hole + * + * This is useful for driver-sepific debug dumpers. Otherwise drivers should not + * inspect holes themselves. Drivers must check first whether a hole indeed + * follows by looking at node->hole_follows. + * + * Returns: + * End of the subsequent hole. + */  static inline unsigned long drm_mm_hole_node_end(struct drm_mm_node *hole_node)  {  	return __drm_mm_hole_node_end(hole_node);  } +/** + * drm_mm_for_each_node - iterator to walk over all allocated nodes + * @entry: drm_mm_node structure to assign to in each iteration step + * @mm: drm_mm allocator to walk + * + * This iterator walks over all nodes in the range allocator. It is implemented + * with list_for_each, so not save against removal of elements. + */  #define drm_mm_for_each_node(entry, mm) list_for_each_entry(entry, \  						&(mm)->head_node.node_list, \  						node_list) -/* 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. +/** + * drm_mm_for_each_hole - iterator to walk over all holes + * @entry: drm_mm_node used internally to track progress + * @mm: drm_mm allocator to walk + * @hole_start: ulong variable to assign the hole start to on each iteration + * @hole_end: ulong variable to assign the hole end to on each iteration + * + * This iterator walks over all holes in the range allocator. It is implemented + * with list_for_each, so not save against removal of elements. @entry is used + * internally and will not reflect a real drm_mm_node for the very first hole. + * Hence users of this iterator may not access it. + * + * Implementation Note: + * We need to inline list_for_each_entry in order to be able to set hole_start + * and hole_end on each iteration while keeping the macro sane. + * + * The __drm_mm_for_each_hole version is similar, but with added support for + * going backwards.   */  #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); \ @@ -133,34 +207,79 @@ static inline unsigned long drm_mm_hole_node_end(struct drm_mm_node *hole_node)  	     1 : 0; \  	     entry = list_entry(entry->hole_stack.next, struct drm_mm_node, hole_stack)) +#define __drm_mm_for_each_hole(entry, mm, hole_start, hole_end, backwards) \ +	for (entry = list_entry((backwards) ? (mm)->hole_stack.prev : (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((backwards) ? entry->hole_stack.prev : entry->hole_stack.next, struct drm_mm_node, hole_stack)) +  /*   * Basic range manager support (drm_mm.c)   */ -extern int drm_mm_reserve_node(struct drm_mm *mm, struct drm_mm_node *node); - -extern int drm_mm_insert_node_generic(struct drm_mm *mm, -				      struct drm_mm_node *node, -				      unsigned long size, -				      unsigned alignment, -				      unsigned long color, -				      enum drm_mm_search_flags flags); +int drm_mm_reserve_node(struct drm_mm *mm, struct drm_mm_node *node); + +int drm_mm_insert_node_generic(struct drm_mm *mm, +			       struct drm_mm_node *node, +			       unsigned long size, +			       unsigned alignment, +			       unsigned long color, +			       enum drm_mm_search_flags sflags, +			       enum drm_mm_allocator_flags aflags); +/** + * drm_mm_insert_node - search for space and insert @node + * @mm: drm_mm to allocate from + * @node: preallocate node to insert + * @size: size of the allocation + * @alignment: alignment of the allocation + * @flags: flags to fine-tune the allocation + * + * This is a simplified version of drm_mm_insert_node_generic() with @color set + * to 0. + * + * The preallocated node must be cleared to 0. + * + * Returns: + * 0 on success, -ENOSPC if there's no suitable hole. + */  static inline int drm_mm_insert_node(struct drm_mm *mm,  				     struct drm_mm_node *node,  				     unsigned long size,  				     unsigned alignment,  				     enum drm_mm_search_flags flags)  { -	return drm_mm_insert_node_generic(mm, node, size, alignment, 0, flags); +	return drm_mm_insert_node_generic(mm, node, size, alignment, 0, flags, +					  DRM_MM_CREATE_DEFAULT);  } -extern int drm_mm_insert_node_in_range_generic(struct drm_mm *mm, -				       struct drm_mm_node *node, -				       unsigned long size, -				       unsigned alignment, -				       unsigned long color, -				       unsigned long start, -				       unsigned long end, -				       enum drm_mm_search_flags flags); +int drm_mm_insert_node_in_range_generic(struct drm_mm *mm, +					struct drm_mm_node *node, +					unsigned long size, +					unsigned alignment, +					unsigned long color, +					unsigned long start, +					unsigned long end, +					enum drm_mm_search_flags sflags, +					enum drm_mm_allocator_flags aflags); +/** + * drm_mm_insert_node_in_range - ranged search for space and insert @node + * @mm: drm_mm to allocate from + * @node: preallocate node to insert + * @size: size of the allocation + * @alignment: alignment of the allocation + * @start: start of the allowed range for this node + * @end: end of the allowed range for this node + * @flags: flags to fine-tune the allocation + * + * This is a simplified version of drm_mm_insert_node_in_range_generic() with + * @color set to 0. + * + * The preallocated node must be cleared to 0. + * + * Returns: + * 0 on success, -ENOSPC if there's no suitable hole. + */  static inline int drm_mm_insert_node_in_range(struct drm_mm *mm,  					      struct drm_mm_node *node,  					      unsigned long size, @@ -170,16 +289,17 @@ static inline int drm_mm_insert_node_in_range(struct drm_mm *mm,  					      enum drm_mm_search_flags flags)  {  	return drm_mm_insert_node_in_range_generic(mm, node, size, alignment, -						   0, start, end, flags); +						   0, start, end, flags, +						   DRM_MM_CREATE_DEFAULT);  } -extern void drm_mm_remove_node(struct drm_mm_node *node); -extern void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new); -extern void drm_mm_init(struct drm_mm *mm, -			unsigned long start, -			unsigned long size); -extern void drm_mm_takedown(struct drm_mm *mm); -extern int drm_mm_clean(struct drm_mm *mm); +void drm_mm_remove_node(struct drm_mm_node *node); +void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new); +void drm_mm_init(struct drm_mm *mm, +		 unsigned long start, +		 unsigned long size); +void drm_mm_takedown(struct drm_mm *mm); +bool drm_mm_clean(struct drm_mm *mm);  void drm_mm_init_scan(struct drm_mm *mm,  		      unsigned long size, @@ -191,10 +311,10 @@ void drm_mm_init_scan_with_range(struct drm_mm *mm,  				 unsigned long color,  				 unsigned long start,  				 unsigned long end); -int drm_mm_scan_add_block(struct drm_mm_node *node); -int drm_mm_scan_remove_block(struct drm_mm_node *node); +bool drm_mm_scan_add_block(struct drm_mm_node *node); +bool drm_mm_scan_remove_block(struct drm_mm_node *node); -extern void drm_mm_debug_table(struct drm_mm *mm, const char *prefix); +void drm_mm_debug_table(struct drm_mm *mm, const char *prefix);  #ifdef CONFIG_DEBUG_FS  int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm);  #endif diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h new file mode 100644 index 00000000000..91d0582f924 --- /dev/null +++ b/include/drm/drm_modes.h @@ -0,0 +1,237 @@ +/* + * Copyright © 2006 Keith Packard + * Copyright © 2007-2008 Dave Airlie + * Copyright © 2007-2008 Intel Corporation + *   Jesse Barnes <jesse.barnes@intel.com> + * Copyright © 2014 Intel Corporation + *   Daniel Vetter <daniel.vetter@ffwll.ch> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef __DRM_MODES_H__ +#define __DRM_MODES_H__ + +/* + * Note on terminology:  here, for brevity and convenience, we refer to connector + * control chips as 'CRTCs'.  They can control any type of connector, VGA, LVDS, + * DVI, etc.  And 'screen' refers to the whole of the visible display, which + * may span multiple monitors (and therefore multiple CRTC and connector + * structures). + */ + +enum drm_mode_status { +    MODE_OK	= 0,	/* Mode OK */ +    MODE_HSYNC,		/* hsync out of range */ +    MODE_VSYNC,		/* vsync out of range */ +    MODE_H_ILLEGAL,	/* mode has illegal horizontal timings */ +    MODE_V_ILLEGAL,	/* mode has illegal horizontal timings */ +    MODE_BAD_WIDTH,	/* requires an unsupported linepitch */ +    MODE_NOMODE,	/* no mode with a matching name */ +    MODE_NO_INTERLACE,	/* interlaced mode not supported */ +    MODE_NO_DBLESCAN,	/* doublescan mode not supported */ +    MODE_NO_VSCAN,	/* multiscan mode not supported */ +    MODE_MEM,		/* insufficient video memory */ +    MODE_VIRTUAL_X,	/* mode width too large for specified virtual size */ +    MODE_VIRTUAL_Y,	/* mode height too large for specified virtual size */ +    MODE_MEM_VIRT,	/* insufficient video memory given virtual size */ +    MODE_NOCLOCK,	/* no fixed clock available */ +    MODE_CLOCK_HIGH,	/* clock required is too high */ +    MODE_CLOCK_LOW,	/* clock required is too low */ +    MODE_CLOCK_RANGE,	/* clock/mode isn't in a ClockRange */ +    MODE_BAD_HVALUE,	/* horizontal timing was out of range */ +    MODE_BAD_VVALUE,	/* vertical timing was out of range */ +    MODE_BAD_VSCAN,	/* VScan value out of range */ +    MODE_HSYNC_NARROW,	/* horizontal sync too narrow */ +    MODE_HSYNC_WIDE,	/* horizontal sync too wide */ +    MODE_HBLANK_NARROW,	/* horizontal blanking too narrow */ +    MODE_HBLANK_WIDE,	/* horizontal blanking too wide */ +    MODE_VSYNC_NARROW,	/* vertical sync too narrow */ +    MODE_VSYNC_WIDE,	/* vertical sync too wide */ +    MODE_VBLANK_NARROW,	/* vertical blanking too narrow */ +    MODE_VBLANK_WIDE,	/* vertical blanking too wide */ +    MODE_PANEL,         /* exceeds panel dimensions */ +    MODE_INTERLACE_WIDTH, /* width too large for interlaced mode */ +    MODE_ONE_WIDTH,     /* only one width is supported */ +    MODE_ONE_HEIGHT,    /* only one height is supported */ +    MODE_ONE_SIZE,      /* only one resolution is supported */ +    MODE_NO_REDUCED,    /* monitor doesn't accept reduced blanking */ +    MODE_NO_STEREO,	/* stereo modes not supported */ +    MODE_UNVERIFIED = -3, /* mode needs to reverified */ +    MODE_BAD = -2,	/* unspecified reason */ +    MODE_ERROR	= -1	/* error condition */ +}; + +#define DRM_MODE_TYPE_CLOCK_CRTC_C (DRM_MODE_TYPE_CLOCK_C | \ +				    DRM_MODE_TYPE_CRTC_C) + +#define DRM_MODE(nm, t, c, hd, hss, hse, ht, hsk, vd, vss, vse, vt, vs, f) \ +	.name = nm, .status = 0, .type = (t), .clock = (c), \ +	.hdisplay = (hd), .hsync_start = (hss), .hsync_end = (hse), \ +	.htotal = (ht), .hskew = (hsk), .vdisplay = (vd), \ +	.vsync_start = (vss), .vsync_end = (vse), .vtotal = (vt), \ +	.vscan = (vs), .flags = (f), \ +	.base.type = DRM_MODE_OBJECT_MODE + +#define CRTC_INTERLACE_HALVE_V	(1 << 0) /* halve V values for interlacing */ +#define CRTC_STEREO_DOUBLE	(1 << 1) /* adjust timings for stereo modes */ + +#define DRM_MODE_FLAG_3D_MAX	DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF + +struct drm_display_mode { +	/* Header */ +	struct list_head head; +	struct drm_mode_object base; + +	char name[DRM_DISPLAY_MODE_LEN]; + +	enum drm_mode_status status; +	unsigned int type; + +	/* Proposed mode values */ +	int clock;		/* in kHz */ +	int hdisplay; +	int hsync_start; +	int hsync_end; +	int htotal; +	int hskew; +	int vdisplay; +	int vsync_start; +	int vsync_end; +	int vtotal; +	int vscan; +	unsigned int flags; + +	/* Addressable image size (may be 0 for projectors, etc.) */ +	int width_mm; +	int height_mm; + +	/* Actual mode we give to hw */ +	int crtc_clock;		/* in KHz */ +	int crtc_hdisplay; +	int crtc_hblank_start; +	int crtc_hblank_end; +	int crtc_hsync_start; +	int crtc_hsync_end; +	int crtc_htotal; +	int crtc_hskew; +	int crtc_vdisplay; +	int crtc_vblank_start; +	int crtc_vblank_end; +	int crtc_vsync_start; +	int crtc_vsync_end; +	int crtc_vtotal; + +	/* Driver private mode info */ +	int *private; +	int private_flags; + +	int vrefresh;		/* in Hz */ +	int hsync;		/* in kHz */ +	enum hdmi_picture_aspect picture_aspect_ratio; +}; + +/* mode specified on the command line */ +struct drm_cmdline_mode { +	bool specified; +	bool refresh_specified; +	bool bpp_specified; +	int xres, yres; +	int bpp; +	int refresh; +	bool rb; +	bool interlace; +	bool cvt; +	bool margins; +	enum drm_connector_force force; +}; + +/** + * drm_mode_is_stereo - check for stereo mode flags + * @mode: drm_display_mode to check + * + * Returns: + * True if the mode is one of the stereo modes (like side-by-side), false if + * not. + */ +static inline bool drm_mode_is_stereo(const struct drm_display_mode *mode) +{ +	return mode->flags & DRM_MODE_FLAG_3D_MASK; +} + +struct drm_connector; +struct drm_cmdline_mode; + +struct drm_display_mode *drm_mode_create(struct drm_device *dev); +void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode); +void drm_mode_probed_add(struct drm_connector *connector, struct drm_display_mode *mode); +void drm_mode_debug_printmodeline(const struct drm_display_mode *mode); + +struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, +				      int hdisplay, int vdisplay, int vrefresh, +				      bool reduced, bool interlaced, +				      bool margins); +struct drm_display_mode *drm_gtf_mode(struct drm_device *dev, +				      int hdisplay, int vdisplay, int vrefresh, +				      bool interlaced, int margins); +struct drm_display_mode *drm_gtf_mode_complex(struct drm_device *dev, +					      int hdisplay, int vdisplay, +					      int vrefresh, bool interlaced, +					      int margins, +					      int GTF_M, int GTF_2C, +					      int GTF_K, int GTF_2J); +void drm_display_mode_from_videomode(const struct videomode *vm, +				     struct drm_display_mode *dmode); +int of_get_drm_display_mode(struct device_node *np, +			    struct drm_display_mode *dmode, +			    int index); + +void drm_mode_set_name(struct drm_display_mode *mode); +int drm_mode_hsync(const struct drm_display_mode *mode); +int drm_mode_vrefresh(const struct drm_display_mode *mode); + +void drm_mode_set_crtcinfo(struct drm_display_mode *p, +			   int adjust_flags); +void drm_mode_copy(struct drm_display_mode *dst, +		   const struct drm_display_mode *src); +struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev, +					    const struct drm_display_mode *mode); +bool drm_mode_equal(const struct drm_display_mode *mode1, +		    const struct drm_display_mode *mode2); +bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1, +					const struct drm_display_mode *mode2); + +/* for use by the crtc helper probe functions */ +void drm_mode_validate_size(struct drm_device *dev, +			    struct list_head *mode_list, +			    int maxX, int maxY); +void drm_mode_prune_invalid(struct drm_device *dev, +			    struct list_head *mode_list, bool verbose); +void drm_mode_sort(struct list_head *mode_list); +void drm_mode_connector_list_update(struct drm_connector *connector, bool merge_type_bits); + +/* parsing cmdline modes */ +bool +drm_mode_parse_command_line_for_connector(const char *mode_option, +					  struct drm_connector *connector, +					  struct drm_cmdline_mode *mode); +struct drm_display_mode * +drm_mode_create_from_cmdline_mode(struct drm_device *dev, +				  struct drm_cmdline_mode *cmd); + +#endif /* __DRM_MODES_H__ */ diff --git a/include/drm/drm_modeset_lock.h b/include/drm/drm_modeset_lock.h new file mode 100644 index 00000000000..402aa7a6a05 --- /dev/null +++ b/include/drm/drm_modeset_lock.h @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2014 Red Hat + * Author: Rob Clark <robdclark@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef DRM_MODESET_LOCK_H_ +#define DRM_MODESET_LOCK_H_ + +#include <linux/ww_mutex.h> + +struct drm_modeset_lock; + +/** + * drm_modeset_acquire_ctx - locking context (see ww_acquire_ctx) + * @ww_ctx: base acquire ctx + * @contended: used internally for -EDEADLK handling + * @locked: list of held locks + * + * Each thread competing for a set of locks must use one acquire + * ctx.  And if any lock fxn returns -EDEADLK, it must backoff and + * retry. + */ +struct drm_modeset_acquire_ctx { + +	struct ww_acquire_ctx ww_ctx; + +	/** +	 * Contended lock: if a lock is contended you should only call +	 * drm_modeset_backoff() which drops locks and slow-locks the +	 * contended lock. +	 */ +	struct drm_modeset_lock *contended; + +	/** +	 * list of held locks (drm_modeset_lock) +	 */ +	struct list_head locked; +}; + +/** + * drm_modeset_lock - used for locking modeset resources. + * @mutex: resource locking + * @head: used to hold it's place on state->locked list when + *    part of an atomic update + * + * Used for locking CRTCs and other modeset resources. + */ +struct drm_modeset_lock { +	/** +	 * modeset lock +	 */ +	struct ww_mutex mutex; + +	/** +	 * Resources that are locked as part of an atomic update are added +	 * to a list (so we know what to unlock at the end). +	 */ +	struct list_head head; +}; + +extern struct ww_class crtc_ww_class; + +void drm_modeset_acquire_init(struct drm_modeset_acquire_ctx *ctx, +		uint32_t flags); +void drm_modeset_acquire_fini(struct drm_modeset_acquire_ctx *ctx); +void drm_modeset_drop_locks(struct drm_modeset_acquire_ctx *ctx); +void drm_modeset_backoff(struct drm_modeset_acquire_ctx *ctx); +int drm_modeset_backoff_interruptible(struct drm_modeset_acquire_ctx *ctx); + +/** + * drm_modeset_lock_init - initialize lock + * @lock: lock to init + */ +static inline void drm_modeset_lock_init(struct drm_modeset_lock *lock) +{ +	ww_mutex_init(&lock->mutex, &crtc_ww_class); +	INIT_LIST_HEAD(&lock->head); +} + +/** + * drm_modeset_lock_fini - cleanup lock + * @lock: lock to cleanup + */ +static inline void drm_modeset_lock_fini(struct drm_modeset_lock *lock) +{ +	WARN_ON(!list_empty(&lock->head)); +} + +/** + * drm_modeset_is_locked - equivalent to mutex_is_locked() + * @lock: lock to check + */ +static inline bool drm_modeset_is_locked(struct drm_modeset_lock *lock) +{ +	return ww_mutex_is_locked(&lock->mutex); +} + +int drm_modeset_lock(struct drm_modeset_lock *lock, +		struct drm_modeset_acquire_ctx *ctx); +int drm_modeset_lock_interruptible(struct drm_modeset_lock *lock, +		struct drm_modeset_acquire_ctx *ctx); +void drm_modeset_unlock(struct drm_modeset_lock *lock); + +struct drm_device; +int drm_modeset_lock_all_crtcs(struct drm_device *dev, +		struct drm_modeset_acquire_ctx *ctx); + +#endif /* DRM_MODESET_LOCK_H_ */ diff --git a/include/drm/drm_os_linux.h b/include/drm/drm_os_linux.h index 815fafc6b4a..86ab99bc0ac 100644 --- a/include/drm/drm_os_linux.h +++ b/include/drm/drm_os_linux.h @@ -21,7 +21,6 @@ static inline void writeq(u64 val, void __iomem *reg)  /** Current process ID */  #define DRM_CURRENTPID			task_pid_nr(current) -#define DRM_SUSER(p)			capable(CAP_SYS_ADMIN)  #define DRM_UDELAY(d)			udelay(d)  /** Read a byte from a MMIO region */  #define DRM_READ8(map, offset)		readb(((void __iomem *)(map)->handle) + (offset)) @@ -35,45 +34,12 @@ static inline void writeq(u64 val, void __iomem *reg)  #define DRM_WRITE16(map, offset, val)   writew(val, ((void __iomem *)(map)->handle) + (offset))  /** Write a dword into a MMIO region */  #define DRM_WRITE32(map, offset, val)	writel(val, ((void __iomem *)(map)->handle) + (offset)) -/** Read memory barrier */  /** Read a qword from a MMIO region - be careful using these unless you really understand them */  #define DRM_READ64(map, offset)		readq(((void __iomem *)(map)->handle) + (offset))  /** Write a qword into a MMIO region */  #define DRM_WRITE64(map, offset, val)	writeq(val, ((void __iomem *)(map)->handle) + (offset)) -#define DRM_READMEMORYBARRIER()		rmb() -/** Write memory barrier */ -#define DRM_WRITEMEMORYBARRIER()	wmb() -/** Read/write memory barrier */ -#define DRM_MEMORYBARRIER()		mb() - -/** IRQ handler arguments and return type and values */ -#define DRM_IRQ_ARGS		int irq, void *arg - -/** AGP types */ -#if __OS_HAS_AGP -#define DRM_AGP_MEM		struct agp_memory -#define DRM_AGP_KERN		struct agp_kern_info -#else -/* define some dummy types for non AGP supporting kernels */ -struct no_agp_kern { -	unsigned long aper_base; -	unsigned long aper_size; -}; -#define DRM_AGP_MEM             int -#define DRM_AGP_KERN            struct no_agp_kern -#endif - -/** Other copying of data to kernel space */ -#define DRM_COPY_FROM_USER(arg1, arg2, arg3)		\ -	copy_from_user(arg1, arg2, arg3) -/** Other copying of data from kernel space */ -#define DRM_COPY_TO_USER(arg1, arg2, arg3)		\ -	copy_to_user(arg1, arg2, arg3) - -#define DRM_HZ HZ -  #define DRM_WAIT_ON( ret, queue, timeout, condition )		\  do {								\  	DECLARE_WAITQUEUE(entry, current);			\ @@ -97,6 +63,3 @@ do {								\  	__set_current_state(TASK_RUNNING);			\  	remove_wait_queue(&(queue), &entry);			\  } while (0) - -#define DRM_WAKEUP( queue ) wake_up( queue ) -#define DRM_INIT_WAITQUEUE( queue ) init_waitqueue_head( queue ) diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h new file mode 100644 index 00000000000..c2ab77add67 --- /dev/null +++ b/include/drm/drm_panel.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2013, NVIDIA Corporation.  All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef __DRM_PANEL_H__ +#define __DRM_PANEL_H__ + +#include <linux/list.h> + +struct drm_connector; +struct drm_device; +struct drm_panel; + +struct drm_panel_funcs { +	int (*disable)(struct drm_panel *panel); +	int (*enable)(struct drm_panel *panel); +	int (*get_modes)(struct drm_panel *panel); +}; + +struct drm_panel { +	struct drm_device *drm; +	struct drm_connector *connector; +	struct device *dev; + +	const struct drm_panel_funcs *funcs; + +	struct list_head list; +}; + +static inline int drm_panel_disable(struct drm_panel *panel) +{ +	if (panel && panel->funcs && panel->funcs->disable) +		return panel->funcs->disable(panel); + +	return panel ? -ENOSYS : -EINVAL; +} + +static inline int drm_panel_enable(struct drm_panel *panel) +{ +	if (panel && panel->funcs && panel->funcs->enable) +		return panel->funcs->enable(panel); + +	return panel ? -ENOSYS : -EINVAL; +} + +void drm_panel_init(struct drm_panel *panel); + +int drm_panel_add(struct drm_panel *panel); +void drm_panel_remove(struct drm_panel *panel); + +int drm_panel_attach(struct drm_panel *panel, struct drm_connector *connector); +int drm_panel_detach(struct drm_panel *panel); + +#ifdef CONFIG_OF +struct drm_panel *of_drm_find_panel(struct device_node *np); +#else +static inline struct drm_panel *of_drm_find_panel(struct device_node *np) +{ +	return NULL; +} +#endif + +#endif diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h index 3d79e513c0b..6dfd64b3a60 100644 --- a/include/drm/drm_pciids.h +++ b/include/drm/drm_pciids.h @@ -261,6 +261,18 @@  	{0x1002, 0x679B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \  	{0x1002, 0x679E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \  	{0x1002, 0x679F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ +	{0x1002, 0x67A0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAWAII|RADEON_NEW_MEMMAP}, \ +	{0x1002, 0x67A1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAWAII|RADEON_NEW_MEMMAP}, \ +	{0x1002, 0x67A2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAWAII|RADEON_NEW_MEMMAP}, \ +	{0x1002, 0x67A8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAWAII|RADEON_NEW_MEMMAP}, \ +	{0x1002, 0x67A9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAWAII|RADEON_NEW_MEMMAP}, \ +	{0x1002, 0x67AA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAWAII|RADEON_NEW_MEMMAP}, \ +	{0x1002, 0x67B0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAWAII|RADEON_NEW_MEMMAP}, \ +	{0x1002, 0x67B1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAWAII|RADEON_NEW_MEMMAP}, \ +	{0x1002, 0x67B8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAWAII|RADEON_NEW_MEMMAP}, \ +	{0x1002, 0x67B9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAWAII|RADEON_NEW_MEMMAP}, \ +	{0x1002, 0x67BA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAWAII|RADEON_NEW_MEMMAP}, \ +	{0x1002, 0x67BE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAWAII|RADEON_NEW_MEMMAP}, \  	{0x1002, 0x6800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \  	{0x1002, 0x6801, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \  	{0x1002, 0x6802, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ @@ -588,7 +600,7 @@  	{0x1002, 0x9645, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO2|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \  	{0x1002, 0x9647, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\  	{0x1002, 0x9648, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\ -	{0x1002, 0x9649, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\ +	{0x1002, 0x9649, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO2|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\  	{0x1002, 0x964a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \  	{0x1002, 0x964b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \  	{0x1002, 0x964c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ @@ -625,6 +637,22 @@  	{0x1002, 0x983d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \  	{0x1002, 0x983e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \  	{0x1002, 0x983f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KABINI|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ +	{0x1002, 0x9850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ +	{0x1002, 0x9851, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ +	{0x1002, 0x9852, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ +	{0x1002, 0x9853, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ +	{0x1002, 0x9854, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ +	{0x1002, 0x9855, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ +	{0x1002, 0x9856, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ +	{0x1002, 0x9857, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ +	{0x1002, 0x9858, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ +	{0x1002, 0x9859, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ +	{0x1002, 0x985A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ +	{0x1002, 0x985B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ +	{0x1002, 0x985C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ +	{0x1002, 0x985D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ +	{0x1002, 0x985E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ +	{0x1002, 0x985F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \  	{0x1002, 0x9900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \  	{0x1002, 0x9901, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \  	{0x1002, 0x9903, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ diff --git a/include/drm/drm_plane_helper.h b/include/drm/drm_plane_helper.h new file mode 100644 index 00000000000..52e6870534b --- /dev/null +++ b/include/drm/drm_plane_helper.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2011-2013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef DRM_PLANE_HELPER_H +#define DRM_PLANE_HELPER_H + +#include <drm/drm_rect.h> + +/* + * Drivers that don't allow primary plane scaling may pass this macro in place + * of the min/max scale parameters of the update checker function. + * + * Due to src being in 16.16 fixed point and dest being in integer pixels, + * 1<<16 represents no scaling. + */ +#define DRM_PLANE_HELPER_NO_SCALING (1<<16) + +/** + * DOC: plane helpers + * + * Helper functions to assist with creation and handling of CRTC primary + * planes. + */ + +extern int drm_plane_helper_check_update(struct drm_plane *plane, +					 struct drm_crtc *crtc, +					 struct drm_framebuffer *fb, +					 struct drm_rect *src, +					 struct drm_rect *dest, +					 const struct drm_rect *clip, +					 int min_scale, +					 int max_scale, +					 bool can_position, +					 bool can_update_disabled, +					 bool *visible); +extern int drm_primary_helper_update(struct drm_plane *plane, +				     struct drm_crtc *crtc, +				     struct drm_framebuffer *fb, +				     int crtc_x, int crtc_y, +				     unsigned int crtc_w, unsigned int crtc_h, +				     uint32_t src_x, uint32_t src_y, +				     uint32_t src_w, uint32_t src_h); +extern int drm_primary_helper_disable(struct drm_plane *plane); +extern void drm_primary_helper_destroy(struct drm_plane *plane); +extern const struct drm_plane_funcs drm_primary_helper_funcs; +extern struct drm_plane *drm_primary_helper_create_plane(struct drm_device *dev, +							 const uint32_t *formats, +							 int num_formats); + + +#endif diff --git a/include/drm/drm_vma_manager.h b/include/drm/drm_vma_manager.h index c18a593d174..8cd402c73a5 100644 --- a/include/drm/drm_vma_manager.h +++ b/include/drm/drm_vma_manager.h @@ -221,8 +221,8 @@ static inline __u64 drm_vma_node_offset_addr(struct drm_vma_offset_node *node)   * @file_mapping: Address space to unmap @node from   *   * Unmap all userspace mappings for a given offset node. The mappings must be - * associated with the @file_mapping address-space. If no offset exists or - * the address-space is invalid, nothing is done. + * associated with the @file_mapping address-space. If no offset exists + * nothing is done.   *   * This call is unlocked. The caller must guarantee that drm_vma_offset_remove()   * is not called on this node concurrently. @@ -230,7 +230,7 @@ static inline __u64 drm_vma_node_offset_addr(struct drm_vma_offset_node *node)  static inline void drm_vma_node_unmap(struct drm_vma_offset_node *node,  				      struct address_space *file_mapping)  { -	if (file_mapping && drm_vma_node_has_offset(node)) +	if (drm_vma_node_has_offset(node))  		unmap_mapping_range(file_mapping,  				    drm_vma_node_offset_addr(node),  				    drm_vma_node_size(node) << PAGE_SHIFT, 1); diff --git a/include/drm/gma_drm.h b/include/drm/gma_drm.h index 884613ee00a..87ac5e6ca55 100644 --- a/include/drm/gma_drm.h +++ b/include/drm/gma_drm.h @@ -19,73 +19,7 @@   *   **************************************************************************/ -#ifndef _PSB_DRM_H_ -#define _PSB_DRM_H_ - -/* - *	Manage the LUT for an output - */ -struct drm_psb_dpst_lut_arg { -	uint8_t lut[256]; -	int output_id; -}; - -/* - *	Validate modes - */ -struct drm_psb_mode_operation_arg { -	u32 obj_id; -	u16 operation; -	struct drm_mode_modeinfo mode; -	u64 data; -}; - -/* - *	Query the stolen memory for smarter management of - *	memory by the server - */ -struct drm_psb_stolen_memory_arg { -	u32 base; -	u32 size; -}; - -struct drm_psb_get_pipe_from_crtc_id_arg { -	/** ID of CRTC being requested **/ -	u32 crtc_id; -	/** pipe of requested CRTC **/ -	u32 pipe; -}; - -struct drm_psb_gem_create { -	__u64 size; -	__u32 handle; -	__u32 flags; -#define GMA_GEM_CREATE_STOLEN		1	/* Stolen memory can be used */ -}; - -struct drm_psb_gem_mmap { -	__u32 handle; -	__u32 pad; -	/** -	 * Fake offset to use for subsequent mmap call -	 * -	 * This is a fixed-size type for 32/64 compatibility. -	 */ -	__u64 offset; -}; - -/* Controlling the kernel modesetting buffers */ - -#define DRM_GMA_GEM_CREATE	0x00		/* Create a GEM object */ -#define DRM_GMA_GEM_MMAP	0x01		/* Map GEM memory */ -#define DRM_GMA_STOLEN_MEMORY	0x02		/* Report stolen memory */ -#define DRM_GMA_2D_OP		0x03		/* Will be merged later */ -#define DRM_GMA_GAMMA		0x04		/* Set gamma table */ -#define DRM_GMA_ADB		0x05		/* Get backlight */ -#define DRM_GMA_DPST_BL		0x06		/* Set backlight */ -#define DRM_GMA_MODE_OPERATION	0x07		/* Mode validation/DC set */ -#define 	PSB_MODE_OPERATION_MODE_VALID	0x01 -#define DRM_GMA_GET_PIPE_FROM_CRTC_ID	0x08	/* CRTC to physical pipe# */ - +#ifndef _GMA_DRM_H_ +#define _GMA_DRM_H_  #endif diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h index 3abfa6ea226..595f85c392a 100644 --- a/include/drm/i915_drm.h +++ b/include/drm/i915_drm.h @@ -49,9 +49,19 @@ extern bool i915_gpu_turbo_disable(void);  #define    SNB_GMCH_GGMS_MASK	0x3  #define    SNB_GMCH_GMS_SHIFT   3 /* Graphics Mode Select */  #define    SNB_GMCH_GMS_MASK    0x1f +#define    BDW_GMCH_GGMS_SHIFT	6 +#define    BDW_GMCH_GGMS_MASK	0x3 +#define    BDW_GMCH_GMS_SHIFT   8 +#define    BDW_GMCH_GMS_MASK    0xff  #define I830_GMCH_CTRL			0x52 +#define I830_GMCH_GMS_MASK		0x70 +#define I830_GMCH_GMS_LOCAL		0x10 +#define I830_GMCH_GMS_STOLEN_512	0x20 +#define I830_GMCH_GMS_STOLEN_1024	0x30 +#define I830_GMCH_GMS_STOLEN_8192	0x40 +  #define I855_GMCH_GMS_MASK		0xF0  #define I855_GMCH_GMS_STOLEN_0M		0x0  #define I855_GMCH_GMS_STOLEN_1M		(0x1 << 4) @@ -68,4 +78,18 @@ extern bool i915_gpu_turbo_disable(void);  #define INTEL_GMCH_GMS_STOLEN_224M	(0xc << 4)  #define INTEL_GMCH_GMS_STOLEN_352M	(0xd << 4) +#define I830_DRB3		0x63 +#define I85X_DRB3		0x43 +#define I865_TOUD		0xc4 + +#define I830_ESMRAMC		0x91 +#define I845_ESMRAMC		0x9e +#define I85X_ESMRAMC		0x61 +#define    TSEG_ENABLE		(1 << 0) +#define    I830_TSEG_SIZE_512K	(0 << 1) +#define    I830_TSEG_SIZE_1M	(1 << 1) +#define    I845_TSEG_SIZE_MASK	(3 << 1) +#define    I845_TSEG_SIZE_512K	(2 << 1) +#define    I845_TSEG_SIZE_1M	(3 << 1) +  #endif				/* _I915_DRM_H_ */ diff --git a/include/drm/i915_pciids.h b/include/drm/i915_pciids.h index 8a10f5c354e..a70d4564789 100644 --- a/include/drm/i915_pciids.h +++ b/include/drm/i915_pciids.h @@ -191,8 +191,8 @@  	INTEL_VGA_DEVICE(0x0A06, info), /* ULT GT1 mobile */ \  	INTEL_VGA_DEVICE(0x0A16, info), /* ULT GT2 mobile */ \  	INTEL_VGA_DEVICE(0x0A26, info), /* ULT GT3 mobile */ \ -	INTEL_VGA_DEVICE(0x0A0E, info), /* ULT GT1 reserved */ \ -	INTEL_VGA_DEVICE(0x0A1E, info), /* ULT GT2 reserved */ \ +	INTEL_VGA_DEVICE(0x0A0E, info), /* ULX GT1 mobile */ \ +	INTEL_VGA_DEVICE(0x0A1E, info), /* ULX GT2 mobile */ \  	INTEL_VGA_DEVICE(0x0A2E, info), /* ULT GT3 reserved */ \  	INTEL_VGA_DEVICE(0x0D06, info), /* CRW GT1 mobile */ \  	INTEL_VGA_DEVICE(0x0D16, info), /* CRW GT2 mobile */ \ @@ -208,4 +208,55 @@  #define INTEL_VLV_D_IDS(info) \  	INTEL_VGA_DEVICE(0x0155, info) +#define _INTEL_BDW_M(gt, id, info) \ +	INTEL_VGA_DEVICE((((gt) - 1) << 4) | (id), info) +#define _INTEL_BDW_D(gt, id, info) \ +	INTEL_VGA_DEVICE((((gt) - 1) << 4) | (id), info) + +#define _INTEL_BDW_M_IDS(gt, info) \ +	_INTEL_BDW_M(gt, 0x1602, info), /* ULT */ \ +	_INTEL_BDW_M(gt, 0x1606, info), /* ULT */ \ +	_INTEL_BDW_M(gt, 0x160B, info), /* Iris */ \ +	_INTEL_BDW_M(gt, 0x160E, info) /* ULX */ + +#define _INTEL_BDW_D_IDS(gt, info) \ +	_INTEL_BDW_D(gt, 0x160A, info), /* Server */ \ +	_INTEL_BDW_D(gt, 0x160D, info) /* Workstation */ + +#define INTEL_BDW_GT12M_IDS(info) \ +	_INTEL_BDW_M_IDS(1, info), \ +	_INTEL_BDW_M_IDS(2, info) + +#define INTEL_BDW_GT12D_IDS(info) \ +	_INTEL_BDW_D_IDS(1, info), \ +	_INTEL_BDW_D_IDS(2, info) + +#define INTEL_BDW_GT3M_IDS(info) \ +	_INTEL_BDW_M_IDS(3, info) + +#define INTEL_BDW_GT3D_IDS(info) \ +	_INTEL_BDW_D_IDS(3, info) + +#define INTEL_BDW_RSVDM_IDS(info) \ +	_INTEL_BDW_M_IDS(4, info) + +#define INTEL_BDW_RSVDD_IDS(info) \ +	_INTEL_BDW_D_IDS(4, info) + +#define INTEL_BDW_M_IDS(info) \ +	INTEL_BDW_GT12M_IDS(info), \ +	INTEL_BDW_GT3M_IDS(info), \ +	INTEL_BDW_RSVDM_IDS(info) + +#define INTEL_BDW_D_IDS(info) \ +	INTEL_BDW_GT12D_IDS(info), \ +	INTEL_BDW_GT3D_IDS(info), \ +	INTEL_BDW_RSVDD_IDS(info) + +#define INTEL_CHV_IDS(info) \ +	INTEL_VGA_DEVICE(0x22b0, info), \ +	INTEL_VGA_DEVICE(0x22b1, info), \ +	INTEL_VGA_DEVICE(0x22b2, info), \ +	INTEL_VGA_DEVICE(0x22b3, info) +  #endif /* _I915_PCIIDS_H */ diff --git a/include/drm/i915_powerwell.h b/include/drm/i915_powerwell.h index cfdc884405b..baa6f11b183 100644 --- a/include/drm/i915_powerwell.h +++ b/include/drm/i915_powerwell.h @@ -30,7 +30,8 @@  #define _I915_POWERWELL_H_  /* For use by hda_i915 driver */ -extern void i915_request_power_well(void); -extern void i915_release_power_well(void); +extern int i915_request_power_well(void); +extern int i915_release_power_well(void); +extern int i915_get_cdclk_freq(void);  #endif				/* _I915_POWERWELL_H_ */ diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h index 751eaffbf0d..7526c5bf561 100644 --- a/include/drm/ttm/ttm_bo_api.h +++ b/include/drm/ttm/ttm_bo_api.h @@ -169,6 +169,7 @@ struct ttm_tt;   * @offset: The current GPU offset, which can have different meanings   * depending on the memory type. For SYSTEM type memory, it should be 0.   * @cur_placement: Hint of current placement. + * @wu_mutex: Wait unreserved mutex.   *   * Base class for TTM buffer object, that deals with data placement and CPU   * mappings. GPU mappings are really up to the driver, but for simpler GPUs @@ -250,6 +251,7 @@ struct ttm_buffer_object {  	struct reservation_object *resv;  	struct reservation_object ttm_resv; +	struct mutex wu_mutex;  };  /** @@ -483,13 +485,12 @@ extern int ttm_bo_init(struct ttm_bo_device *bdev,  			void (*destroy) (struct ttm_buffer_object *));  /** - * ttm_bo_synccpu_object_init + * ttm_bo_create   *   * @bdev: Pointer to a ttm_bo_device struct. - * @bo: Pointer to a ttm_buffer_object to be initialized.   * @size: Requested size of buffer object.   * @type: Requested type of buffer object. - * @flags: Initial placement flags. + * @placement: Initial placement.   * @page_alignment: Data alignment in pages.   * @interruptible: If needing to sleep while waiting for GPU resources,   * sleep interruptible. @@ -702,5 +703,5 @@ extern ssize_t ttm_bo_io(struct ttm_bo_device *bdev, struct file *filp,  			 size_t count, loff_t *f_pos, bool write);  extern void ttm_bo_swapout_all(struct ttm_bo_device *bdev); - +extern int ttm_bo_wait_unreserved(struct ttm_buffer_object *bo);  #endif diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index 8639c85d61c..a5183da3ef9 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -681,6 +681,15 @@ extern int ttm_tt_set_placement_caching(struct ttm_tt *ttm, uint32_t placement);  extern int ttm_tt_swapout(struct ttm_tt *ttm,  			  struct file *persistent_swap_storage); +/** + * ttm_tt_unpopulate - free pages from a ttm + * + * @ttm: Pointer to the ttm_tt structure + * + * Calls the driver method to free all pages from a ttm + */ +extern void ttm_tt_unpopulate(struct ttm_tt *ttm); +  /*   * ttm_bo.c   */ @@ -738,6 +747,7 @@ extern int ttm_bo_device_release(struct ttm_bo_device *bdev);   * @bdev: A pointer to a struct ttm_bo_device to initialize.   * @glob: A pointer to an initialized struct ttm_bo_global.   * @driver: A pointer to a struct ttm_bo_driver set up by the caller. + * @mapping: The address space to use for this bo.   * @file_page_offset: Offset into the device address space that is available   * for buffer data. This ensures compatibility with other users of the   * address space. @@ -749,6 +759,7 @@ extern int ttm_bo_device_release(struct ttm_bo_device *bdev);  extern int ttm_bo_device_init(struct ttm_bo_device *bdev,  			      struct ttm_bo_global *glob,  			      struct ttm_bo_driver *driver, +			      struct address_space *mapping,  			      uint64_t file_page_offset, bool need_dma32);  /** @@ -777,7 +788,7 @@ extern void ttm_bo_del_sub_from_lru(struct ttm_buffer_object *bo);  extern void ttm_bo_add_to_lru(struct ttm_buffer_object *bo);  /** - * ttm_bo_reserve_nolru: + * __ttm_bo_reserve:   *   * @bo: A pointer to a struct ttm_buffer_object.   * @interruptible: Sleep interruptible if waiting. @@ -798,10 +809,10 @@ extern void ttm_bo_add_to_lru(struct ttm_buffer_object *bo);   * -EALREADY: Bo already reserved using @ticket. This error code will only   * be returned if @use_ticket is set to true.   */ -static inline int ttm_bo_reserve_nolru(struct ttm_buffer_object *bo, -				       bool interruptible, -				       bool no_wait, bool use_ticket, -				       struct ww_acquire_ctx *ticket) +static inline int __ttm_bo_reserve(struct ttm_buffer_object *bo, +				   bool interruptible, +				   bool no_wait, bool use_ticket, +				   struct ww_acquire_ctx *ticket)  {  	int ret = 0; @@ -877,8 +888,7 @@ static inline int ttm_bo_reserve(struct ttm_buffer_object *bo,  	WARN_ON(!atomic_read(&bo->kref.refcount)); -	ret = ttm_bo_reserve_nolru(bo, interruptible, no_wait, use_ticket, -				    ticket); +	ret = __ttm_bo_reserve(bo, interruptible, no_wait, use_ticket, ticket);  	if (likely(ret == 0))  		ttm_bo_del_sub_from_lru(bo); @@ -918,20 +928,14 @@ static inline int ttm_bo_reserve_slowpath(struct ttm_buffer_object *bo,  }  /** - * ttm_bo_unreserve_ticket + * __ttm_bo_unreserve   * @bo: A pointer to a struct ttm_buffer_object. - * @ticket: ww_acquire_ctx used for reserving   * - * Unreserve a previous reservation of @bo made with @ticket. + * Unreserve a previous reservation of @bo where the buffer object is + * already on lru lists.   */ -static inline void ttm_bo_unreserve_ticket(struct ttm_buffer_object *bo, -					   struct ww_acquire_ctx *t) +static inline void __ttm_bo_unreserve(struct ttm_buffer_object *bo)  { -	if (!(bo->mem.placement & TTM_PL_FLAG_NO_EVICT)) { -		spin_lock(&bo->glob->lru_lock); -		ttm_bo_add_to_lru(bo); -		spin_unlock(&bo->glob->lru_lock); -	}  	ww_mutex_unlock(&bo->resv->lock);  } @@ -944,7 +948,25 @@ static inline void ttm_bo_unreserve_ticket(struct ttm_buffer_object *bo,   */  static inline void ttm_bo_unreserve(struct ttm_buffer_object *bo)  { -	ttm_bo_unreserve_ticket(bo, NULL); +	if (!(bo->mem.placement & TTM_PL_FLAG_NO_EVICT)) { +		spin_lock(&bo->glob->lru_lock); +		ttm_bo_add_to_lru(bo); +		spin_unlock(&bo->glob->lru_lock); +	} +	__ttm_bo_unreserve(bo); +} + +/** + * ttm_bo_unreserve_ticket + * @bo: A pointer to a struct ttm_buffer_object. + * @ticket: ww_acquire_ctx used for reserving + * + * Unreserve a previous reservation of @bo made with @ticket. + */ +static inline void ttm_bo_unreserve_ticket(struct ttm_buffer_object *bo, +					   struct ww_acquire_ctx *t) +{ +	ttm_bo_unreserve(bo);  }  /* diff --git a/include/drm/ttm/ttm_execbuf_util.h b/include/drm/ttm/ttm_execbuf_util.h index ec8a1d30651..16db7d01a33 100644 --- a/include/drm/ttm/ttm_execbuf_util.h +++ b/include/drm/ttm/ttm_execbuf_util.h @@ -70,7 +70,8 @@ extern void ttm_eu_backoff_reservation(struct ww_acquire_ctx *ticket,  /**   * function ttm_eu_reserve_buffers   * - * @ticket:  [out] ww_acquire_ctx returned by call. + * @ticket:  [out] ww_acquire_ctx filled in by call, or NULL if only + *           non-blocking reserves should be tried.   * @list:    thread private list of ttm_validate_buffer structs.   *   * Tries to reserve bos pointed to by the list entries for validation. diff --git a/include/drm/ttm/ttm_object.h b/include/drm/ttm/ttm_object.h index fc0cf064990..ed953f98f0e 100644 --- a/include/drm/ttm/ttm_object.h +++ b/include/drm/ttm/ttm_object.h @@ -41,6 +41,7 @@  #include <drm/drm_hashtab.h>  #include <linux/kref.h>  #include <linux/rcupdate.h> +#include <linux/dma-buf.h>  #include <ttm/ttm_memory.h>  /** @@ -77,6 +78,7 @@ enum ttm_object_type {  	ttm_fence_type,  	ttm_buffer_type,  	ttm_lock_type, +	ttm_prime_type,  	ttm_driver_type0 = 256,  	ttm_driver_type1,  	ttm_driver_type2, @@ -132,6 +134,30 @@ struct ttm_base_object {  				 enum ttm_ref_type ref_type);  }; + +/** + * struct ttm_prime_object - Modified base object that is prime-aware + * + * @base: struct ttm_base_object that we derive from + * @mutex: Mutex protecting the @dma_buf member. + * @size: Size of the dma_buf associated with this object + * @real_type: Type of the underlying object. Needed since we're setting + * the value of @base::object_type to ttm_prime_type + * @dma_buf: Non ref-coutned pointer to a struct dma_buf created from this + * object. + * @refcount_release: The underlying object's release method. Needed since + * we set @base::refcount_release to our own release method. + */ + +struct ttm_prime_object { +	struct ttm_base_object base; +	struct mutex mutex; +	size_t size; +	enum ttm_object_type real_type; +	struct dma_buf *dma_buf; +	void (*refcount_release) (struct ttm_base_object **); +}; +  /**   * ttm_base_object_init   * @@ -164,14 +190,26 @@ extern int ttm_base_object_init(struct ttm_object_file *tfile,   * @key: Hash key   *   * Looks up a struct ttm_base_object with the key @key. - * Also verifies that the object is visible to the application, by - * comparing the @tfile argument and checking the object shareable flag.   */  extern struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file  						      *tfile, uint32_t key);  /** + * ttm_base_object_lookup_for_ref + * + * @tdev: Pointer to a struct ttm_object_device. + * @key: Hash key + * + * Looks up a struct ttm_base_object with the key @key. + * This function should only be used when the struct tfile associated with the + * caller doesn't yet have a reference to the base object. + */ + +extern struct ttm_base_object * +ttm_base_object_lookup_for_ref(struct ttm_object_device *tdev, uint32_t key); + +/**   * ttm_base_object_unref   *   * @p_base: Pointer to a pointer referencing a struct ttm_base_object. @@ -192,6 +230,8 @@ extern void ttm_base_object_unref(struct ttm_base_object **p_base);   * @existed: Upon completion, indicates that an identical reference object   * already existed, and the refcount was upped on that object instead.   * + * Checks that the base object is shareable and adds a ref object to it. + *   * Adding a ref object to a base object is basically like referencing the   * base object, but a user-space application holds the reference. When the   * file corresponding to @tfile is closed, all its reference objects are @@ -204,6 +244,10 @@ extern void ttm_base_object_unref(struct ttm_base_object **p_base);  extern int ttm_ref_object_add(struct ttm_object_file *tfile,  			      struct ttm_base_object *base,  			      enum ttm_ref_type ref_type, bool *existed); + +extern bool ttm_ref_object_exists(struct ttm_object_file *tfile, +				  struct ttm_base_object *base); +  /**   * ttm_ref_object_base_unref   * @@ -248,14 +292,18 @@ extern void ttm_object_file_release(struct ttm_object_file **p_tfile);  /**   * ttm_object device init - initialize a struct ttm_object_device   * + * @mem_glob: struct ttm_mem_global for memory accounting.   * @hash_order: Order of hash table used to hash the base objects. + * @ops: DMA buf ops for prime objects of this device.   *   * This function is typically called on device initialization to prepare   * data structures needed for ttm base and ref objects.   */ -extern struct ttm_object_device *ttm_object_device_init -    (struct ttm_mem_global *mem_glob, unsigned int hash_order); +extern struct ttm_object_device * +ttm_object_device_init(struct ttm_mem_global *mem_glob, +		       unsigned int hash_order, +		       const struct dma_buf_ops *ops);  /**   * ttm_object_device_release - release data held by a ttm_object_device @@ -272,4 +320,31 @@ extern void ttm_object_device_release(struct ttm_object_device **p_tdev);  #define ttm_base_object_kfree(__object, __base)\  	kfree_rcu(__object, __base.rhead) + +extern int ttm_prime_object_init(struct ttm_object_file *tfile, +				 size_t size, +				 struct ttm_prime_object *prime, +				 bool shareable, +				 enum ttm_object_type type, +				 void (*refcount_release) +				 (struct ttm_base_object **), +				 void (*ref_obj_release) +				 (struct ttm_base_object *, +				  enum ttm_ref_type ref_type)); + +static inline enum ttm_object_type +ttm_base_object_type(struct ttm_base_object *base) +{ +	return (base->object_type == ttm_prime_type) ? +		container_of(base, struct ttm_prime_object, base)->real_type : +		base->object_type; +} +extern int ttm_prime_fd_to_handle(struct ttm_object_file *tfile, +				  int fd, u32 *handle); +extern int ttm_prime_handle_to_fd(struct ttm_object_file *tfile, +				  uint32_t handle, uint32_t flags, +				  int *prime_fd); + +#define ttm_prime_object_kfree(__obj, __prime)		\ +	kfree_rcu(__obj, __prime.base.rhead)  #endif diff --git a/include/drm/ttm/ttm_page_alloc.h b/include/drm/ttm/ttm_page_alloc.h index 706b962c646..49a828425fa 100644 --- a/include/drm/ttm/ttm_page_alloc.h +++ b/include/drm/ttm/ttm_page_alloc.h @@ -29,6 +29,8 @@  #include <drm/ttm/ttm_bo_driver.h>  #include <drm/ttm/ttm_memory.h> +struct device; +  /**   * Initialize pool allocator.   */ @@ -62,7 +64,7 @@ extern void ttm_pool_unpopulate(struct ttm_tt *ttm);  extern int ttm_page_alloc_debugfs(struct seq_file *m, void *data); -#ifdef CONFIG_SWIOTLB +#if defined(CONFIG_SWIOTLB) || defined(CONFIG_INTEL_IOMMU)  /**   * Initialize pool allocator.   */ @@ -94,6 +96,15 @@ static inline int ttm_dma_page_alloc_debugfs(struct seq_file *m, void *data)  {  	return 0;  } +static inline int ttm_dma_populate(struct ttm_dma_tt *ttm_dma, +				   struct device *dev) +{ +	return -ENOMEM; +} +static inline void ttm_dma_unpopulate(struct ttm_dma_tt *ttm_dma, +				      struct device *dev) +{ +}  #endif  #endif diff --git a/include/drm/ttm/ttm_placement.h b/include/drm/ttm/ttm_placement.h index c84ff153a56..8ed44f9bbdf 100644 --- a/include/drm/ttm/ttm_placement.h +++ b/include/drm/ttm/ttm_placement.h @@ -65,6 +65,8 @@   * reference the buffer.   * TTM_PL_FLAG_NO_EVICT means that the buffer may never   * be evicted to make room for other buffers. + * TTM_PL_FLAG_TOPDOWN requests to be placed from the + * top of the memory area, instead of the bottom.   */  #define TTM_PL_FLAG_CACHED      (1 << 16) @@ -72,6 +74,7 @@  #define TTM_PL_FLAG_WC          (1 << 18)  #define TTM_PL_FLAG_SHARED      (1 << 20)  #define TTM_PL_FLAG_NO_EVICT    (1 << 21) +#define TTM_PL_FLAG_TOPDOWN     (1 << 22)  #define TTM_PL_MASK_CACHING     (TTM_PL_FLAG_CACHED | \  				 TTM_PL_FLAG_UNCACHED | \  | 
