From e1e906448d2fc6f5a69e1967e00868f0cbfbb566 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Tue, 24 Sep 2013 13:59:01 +0200 Subject: gpu: host1x: Make host1x header file public In preparation to support host1x clients other than DRM, move this header into a public location. Signed-off-by: Thierry Reding --- include/linux/host1x.h | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 include/linux/host1x.h (limited to 'include') diff --git a/include/linux/host1x.h b/include/linux/host1x.h new file mode 100644 index 0000000..fe09939 --- /dev/null +++ b/include/linux/host1x.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2009-2013, NVIDIA Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __LINUX_HOST1X_H +#define __LINUX_HOST1X_H + +enum host1x_class { + HOST1X_CLASS_HOST1X = 0x1, + HOST1X_CLASS_GR2D = 0x51, + HOST1X_CLASS_GR2D_SB = 0x52, +}; + +#endif -- cgit v1.1 From 53fa7f7204c97dc0c86b99ff8365ad6a7b2ebd78 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Tue, 24 Sep 2013 15:35:40 +0200 Subject: drm/tegra: Introduce tegra_drm_client structure This structure derives from host1x_client. DRM-specific fields are moved from host1x_client to this structure, so that host1x_client can remain agnostic of DRM. Signed-off-by: Thierry Reding --- include/linux/host1x.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'include') diff --git a/include/linux/host1x.h b/include/linux/host1x.h index fe09939..d429a93 100644 --- a/include/linux/host1x.h +++ b/include/linux/host1x.h @@ -25,4 +25,24 @@ enum host1x_class { HOST1X_CLASS_GR2D_SB = 0x52, }; +struct host1x_client; + +struct host1x_client_ops { + int (*init)(struct host1x_client *client); + int (*exit)(struct host1x_client *client); +}; + +struct host1x_client { + struct list_head list; + struct device *dev; + + const struct host1x_client_ops *ops; + + enum host1x_class class; + struct host1x_channel *channel; + + struct host1x_syncpt **syncpts; + unsigned int num_syncpts; +}; + #endif -- cgit v1.1 From 35d747a81d7eb824bd0c3476cd0c564b52ad5353 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Tue, 24 Sep 2013 16:30:32 +0200 Subject: gpu: host1x: Expose syncpt and channel functionality Expose the buffer objects, syncpoint and channel functionality in the public public header so that drivers can use them. Signed-off-by: Thierry Reding --- include/linux/host1x.h | 185 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 185 insertions(+) (limited to 'include') diff --git a/include/linux/host1x.h b/include/linux/host1x.h index d429a93..7442f2a 100644 --- a/include/linux/host1x.h +++ b/include/linux/host1x.h @@ -19,6 +19,9 @@ #ifndef __LINUX_HOST1X_H #define __LINUX_HOST1X_H +#include +#include + enum host1x_class { HOST1X_CLASS_HOST1X = 0x1, HOST1X_CLASS_GR2D = 0x51, @@ -45,4 +48,186 @@ struct host1x_client { unsigned int num_syncpts; }; +/* + * host1x buffer objects + */ + +struct host1x_bo; +struct sg_table; + +struct host1x_bo_ops { + struct host1x_bo *(*get)(struct host1x_bo *bo); + void (*put)(struct host1x_bo *bo); + dma_addr_t (*pin)(struct host1x_bo *bo, struct sg_table **sgt); + void (*unpin)(struct host1x_bo *bo, struct sg_table *sgt); + void *(*mmap)(struct host1x_bo *bo); + void (*munmap)(struct host1x_bo *bo, void *addr); + void *(*kmap)(struct host1x_bo *bo, unsigned int pagenum); + void (*kunmap)(struct host1x_bo *bo, unsigned int pagenum, void *addr); +}; + +struct host1x_bo { + const struct host1x_bo_ops *ops; +}; + +static inline void host1x_bo_init(struct host1x_bo *bo, + const struct host1x_bo_ops *ops) +{ + bo->ops = ops; +} + +static inline struct host1x_bo *host1x_bo_get(struct host1x_bo *bo) +{ + return bo->ops->get(bo); +} + +static inline void host1x_bo_put(struct host1x_bo *bo) +{ + bo->ops->put(bo); +} + +static inline dma_addr_t host1x_bo_pin(struct host1x_bo *bo, + struct sg_table **sgt) +{ + return bo->ops->pin(bo, sgt); +} + +static inline void host1x_bo_unpin(struct host1x_bo *bo, struct sg_table *sgt) +{ + bo->ops->unpin(bo, sgt); +} + +static inline void *host1x_bo_mmap(struct host1x_bo *bo) +{ + return bo->ops->mmap(bo); +} + +static inline void host1x_bo_munmap(struct host1x_bo *bo, void *addr) +{ + bo->ops->munmap(bo, addr); +} + +static inline void *host1x_bo_kmap(struct host1x_bo *bo, unsigned int pagenum) +{ + return bo->ops->kmap(bo, pagenum); +} + +static inline void host1x_bo_kunmap(struct host1x_bo *bo, + unsigned int pagenum, void *addr) +{ + bo->ops->kunmap(bo, pagenum, addr); +} + +/* + * host1x syncpoints + */ + +struct host1x_syncpt; +struct host1x; + +struct host1x_syncpt *host1x_syncpt_get(struct host1x *host, u32 id); +u32 host1x_syncpt_id(struct host1x_syncpt *sp); +u32 host1x_syncpt_read_min(struct host1x_syncpt *sp); +u32 host1x_syncpt_read_max(struct host1x_syncpt *sp); +int host1x_syncpt_incr(struct host1x_syncpt *sp); +int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh, long timeout, + u32 *value); +struct host1x_syncpt *host1x_syncpt_request(struct device *dev, + bool client_managed); +void host1x_syncpt_free(struct host1x_syncpt *sp); + +/* + * host1x channel + */ + +struct host1x_channel; +struct host1x_job; + +struct host1x_channel *host1x_channel_request(struct device *dev); +void host1x_channel_free(struct host1x_channel *channel); +struct host1x_channel *host1x_channel_get(struct host1x_channel *channel); +void host1x_channel_put(struct host1x_channel *channel); +int host1x_job_submit(struct host1x_job *job); + +/* + * host1x job + */ + +struct host1x_reloc { + struct host1x_bo *cmdbuf; + u32 cmdbuf_offset; + struct host1x_bo *target; + u32 target_offset; + u32 shift; + u32 pad; +}; + +struct host1x_job { + /* When refcount goes to zero, job can be freed */ + struct kref ref; + + /* List entry */ + struct list_head list; + + /* Channel where job is submitted to */ + struct host1x_channel *channel; + + u32 client; + + /* Gathers and their memory */ + struct host1x_job_gather *gathers; + unsigned int num_gathers; + + /* Wait checks to be processed at submit time */ + struct host1x_waitchk *waitchk; + unsigned int num_waitchk; + u32 waitchk_mask; + + /* Array of handles to be pinned & unpinned */ + struct host1x_reloc *relocarray; + unsigned int num_relocs; + struct host1x_job_unpin_data *unpins; + unsigned int num_unpins; + + dma_addr_t *addr_phys; + dma_addr_t *gather_addr_phys; + dma_addr_t *reloc_addr_phys; + + /* Sync point id, number of increments and end related to the submit */ + u32 syncpt_id; + u32 syncpt_incrs; + u32 syncpt_end; + + /* Maximum time to wait for this job */ + unsigned int timeout; + + /* Index and number of slots used in the push buffer */ + unsigned int first_get; + unsigned int num_slots; + + /* Copy of gathers */ + size_t gather_copy_size; + dma_addr_t gather_copy; + u8 *gather_copy_mapped; + + /* Check if register is marked as an address reg */ + int (*is_addr_reg)(struct device *dev, u32 reg, u32 class); + + /* Request a SETCLASS to this class */ + u32 class; + + /* Add a channel wait for previous ops to complete */ + bool serialize; +}; + +struct host1x_job *host1x_job_alloc(struct host1x_channel *ch, + u32 num_cmdbufs, u32 num_relocs, + u32 num_waitchks); +void host1x_job_add_gather(struct host1x_job *job, struct host1x_bo *mem_id, + u32 words, u32 offset); +struct host1x_job *host1x_job_get(struct host1x_job *job); +void host1x_job_put(struct host1x_job *job); +int host1x_job_pin(struct host1x_job *job, struct device *dev); +void host1x_job_unpin(struct host1x_job *job); + #endif -- cgit v1.1 From 776dc38403676f499a73d32e2e7c61eb5b42f736 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 14 Oct 2013 14:43:22 +0200 Subject: drm/tegra: Move subdevice infrastructure to host1x The Tegra DRM driver currently uses some infrastructure to defer the DRM core initialization until all required devices have registered. The same infrastructure can potentially be used by any other driver that requires more than a single sub-device of the host1x module. Make the infrastructure more generic and keep only the DRM specific code in the DRM part of the driver. Eventually this will make it easy to move the DRM driver part back to the DRM subsystem. Signed-off-by: Thierry Reding --- include/drm/drmP.h | 1 + include/linux/host1x.h | 45 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 45 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 2b954ad..ffd8ad92 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -150,6 +150,7 @@ int drm_err(const char *func, const char *format, ...); #define DRIVER_BUS_PCI 0x1 #define DRIVER_BUS_PLATFORM 0x2 #define DRIVER_BUS_USB 0x3 +#define DRIVER_BUS_HOST1X 0x4 /***********************************************************************/ /** \name Begin the DRM... */ diff --git a/include/linux/host1x.h b/include/linux/host1x.h index 7442f2a..e62c61a 100644 --- a/include/linux/host1x.h +++ b/include/linux/host1x.h @@ -19,7 +19,7 @@ #ifndef __LINUX_HOST1X_H #define __LINUX_HOST1X_H -#include +#include #include enum host1x_class { @@ -37,6 +37,7 @@ struct host1x_client_ops { struct host1x_client { struct list_head list; + struct device *parent; struct device *dev; const struct host1x_client_ops *ops; @@ -230,4 +231,46 @@ void host1x_job_put(struct host1x_job *job); int host1x_job_pin(struct host1x_job *job, struct device *dev); void host1x_job_unpin(struct host1x_job *job); +/* + * subdevice probe infrastructure + */ + +struct host1x_device; + +struct host1x_driver { + const struct of_device_id *subdevs; + struct list_head list; + const char *name; + + int (*probe)(struct host1x_device *device); + int (*remove)(struct host1x_device *device); +}; + +int host1x_driver_register(struct host1x_driver *driver); +void host1x_driver_unregister(struct host1x_driver *driver); + +struct host1x_device { + struct host1x_driver *driver; + struct list_head list; + struct device dev; + + struct mutex subdevs_lock; + struct list_head subdevs; + struct list_head active; + + struct mutex clients_lock; + struct list_head clients; +}; + +static inline struct host1x_device *to_host1x_device(struct device *dev) +{ + return container_of(dev, struct host1x_device, dev); +} + +int host1x_device_init(struct host1x_device *device); +int host1x_device_exit(struct host1x_device *device); + +int host1x_client_register(struct host1x_client *client); +int host1x_client_unregister(struct host1x_client *client); + #endif -- cgit v1.1 From 5f60ed0d840d53e9d65aa54e1a5365af8ce2769e Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 28 Feb 2013 08:08:01 +0100 Subject: drm/tegra: Add 3D support Initialize and power the 3D unit on Tegra20, Tegra30 and Tegra114 and register a channel with the Tegra DRM driver so that the unit can be used from userspace. Signed-off-by: Thierry Reding Signed-off-by: Thierry Reding --- include/linux/host1x.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/linux/host1x.h b/include/linux/host1x.h index e62c61a..f5dd56f 100644 --- a/include/linux/host1x.h +++ b/include/linux/host1x.h @@ -26,6 +26,7 @@ enum host1x_class { HOST1X_CLASS_HOST1X = 0x1, HOST1X_CLASS_GR2D = 0x51, HOST1X_CLASS_GR2D_SB = 0x52, + HOST1X_CLASS_GR3D = 0x60, }; struct host1x_client; -- cgit v1.1 From 773af77fc479fd454c3f6836f86bf63996545cf4 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 4 Oct 2013 22:34:01 +0200 Subject: drm/tegra: Add support for tiled buffer objects The gr2d and gr3d engines work more efficiently on buffers with a tiled memory layout. Allow created buffers to be marked as tiled so that the display controller can scan them out properly. Signed-off-by: Thierry Reding Signed-off-by: Thierry Reding --- include/uapi/drm/tegra_drm.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/uapi/drm/tegra_drm.h b/include/uapi/drm/tegra_drm.h index 73bde4e..6b42002 100644 --- a/include/uapi/drm/tegra_drm.h +++ b/include/uapi/drm/tegra_drm.h @@ -19,6 +19,8 @@ #include +#define DRM_TEGRA_GEM_CREATE_TILED (1 << 0) + struct drm_tegra_gem_create { __u64 size; __u32 flags; -- cgit v1.1 From db7fbdfd25ee009165b6c3b80a9d1c6d8534ad94 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 7 Oct 2013 09:47:58 +0200 Subject: drm/tegra: Support bottom-up buffer objects The gr3d engine renders images bottom-up. Allow buffers that are used for 3D content to be marked as such and implement support in the display controller to present them properly. Signed-off-by: Thierry Reding Signed-off-by: Thierry Reding --- include/uapi/drm/tegra_drm.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/uapi/drm/tegra_drm.h b/include/uapi/drm/tegra_drm.h index 6b42002..0f8575f 100644 --- a/include/uapi/drm/tegra_drm.h +++ b/include/uapi/drm/tegra_drm.h @@ -19,7 +19,8 @@ #include -#define DRM_TEGRA_GEM_CREATE_TILED (1 << 0) +#define DRM_TEGRA_GEM_CREATE_TILED (1 << 0) +#define DRM_TEGRA_GEM_CREATE_BOTTOM_UP (1 << 1) struct drm_tegra_gem_create { __u64 size; -- cgit v1.1 From 8736fe81532182ba0086a371fae0708ea42a2cdf Mon Sep 17 00:00:00 2001 From: Arto Merilainen Date: Mon, 14 Oct 2013 15:21:52 +0300 Subject: gpu: host1x: Add 'flags' field to syncpt request Functions host1x_syncpt_request() and _host1x_syncpt_alloc() have been taking a separate boolean flag ('client_managed') for indicating if the syncpoint value should be tracked by the host1x driver. This patch converts the field into generic 'flags' field so that we can easily add more information while requesting a syncpoint. Clients are adapted to use the new interface accordingly. Signed-off-by: Arto Merilainen Reviewed-by: Terje Bergstrom Signed-off-by: Thierry Reding --- include/linux/host1x.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/host1x.h b/include/linux/host1x.h index f5dd56f..eb713db 100644 --- a/include/linux/host1x.h +++ b/include/linux/host1x.h @@ -124,6 +124,8 @@ static inline void host1x_bo_kunmap(struct host1x_bo *bo, * host1x syncpoints */ +#define HOST1X_SYNCPT_CLIENT_MANAGED (1 << 0) + struct host1x_syncpt; struct host1x; @@ -135,7 +137,7 @@ int host1x_syncpt_incr(struct host1x_syncpt *sp); int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh, long timeout, u32 *value); struct host1x_syncpt *host1x_syncpt_request(struct device *dev, - bool client_managed); + unsigned long flags); void host1x_syncpt_free(struct host1x_syncpt *sp); /* -- cgit v1.1 From f5a954fed9b3eb04973ede72c50c66157fa9e15b Mon Sep 17 00:00:00 2001 From: Arto Merilainen Date: Mon, 14 Oct 2013 15:21:53 +0300 Subject: gpu: host1x: Add syncpoint base support This patch adds support for hardware syncpoint bases. This creates a simple mechanism to stall the command FIFO until an operation is completed. Signed-off-by: Arto Merilainen Reviewed-by: Terje Bergstrom Signed-off-by: Thierry Reding --- include/linux/host1x.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include') diff --git a/include/linux/host1x.h b/include/linux/host1x.h index eb713db..f5b9b87 100644 --- a/include/linux/host1x.h +++ b/include/linux/host1x.h @@ -125,7 +125,9 @@ static inline void host1x_bo_kunmap(struct host1x_bo *bo, */ #define HOST1X_SYNCPT_CLIENT_MANAGED (1 << 0) +#define HOST1X_SYNCPT_HAS_BASE (1 << 1) +struct host1x_syncpt_base; struct host1x_syncpt; struct host1x; @@ -140,6 +142,9 @@ struct host1x_syncpt *host1x_syncpt_request(struct device *dev, unsigned long flags); void host1x_syncpt_free(struct host1x_syncpt *sp); +struct host1x_syncpt_base *host1x_syncpt_get_base(struct host1x_syncpt *sp); +u32 host1x_syncpt_base_id(struct host1x_syncpt_base *base); + /* * host1x channel */ -- cgit v1.1 From c54a169b528d0ac2a5d3a7bf91f8534323bda83d Mon Sep 17 00:00:00 2001 From: Arto Merilainen Date: Mon, 14 Oct 2013 15:21:54 +0300 Subject: drm/tegra: Deliver syncpoint base to user space This patch adds a separate ioctl for delivering syncpoint base number to user space. If the syncpoint does not have an associated base, the function returns -ENXIO. Signed-off-by: Arto Merilainen Reviewed-by: Terje Bergstrom Signed-off-by: Thierry Reding --- include/uapi/drm/tegra_drm.h | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/include/uapi/drm/tegra_drm.h b/include/uapi/drm/tegra_drm.h index 0f8575f..5e1ab55 100644 --- a/include/uapi/drm/tegra_drm.h +++ b/include/uapi/drm/tegra_drm.h @@ -68,6 +68,12 @@ struct drm_tegra_get_syncpt { __u32 id; }; +struct drm_tegra_get_syncpt_base { + __u64 context; + __u32 syncpt; + __u32 id; +}; + struct drm_tegra_syncpt { __u32 id; __u32 incrs; @@ -118,15 +124,16 @@ struct drm_tegra_submit { __u32 reserved[5]; /* future expansion */ }; -#define DRM_TEGRA_GEM_CREATE 0x00 -#define DRM_TEGRA_GEM_MMAP 0x01 -#define DRM_TEGRA_SYNCPT_READ 0x02 -#define DRM_TEGRA_SYNCPT_INCR 0x03 -#define DRM_TEGRA_SYNCPT_WAIT 0x04 -#define DRM_TEGRA_OPEN_CHANNEL 0x05 -#define DRM_TEGRA_CLOSE_CHANNEL 0x06 -#define DRM_TEGRA_GET_SYNCPT 0x07 -#define DRM_TEGRA_SUBMIT 0x08 +#define DRM_TEGRA_GEM_CREATE 0x00 +#define DRM_TEGRA_GEM_MMAP 0x01 +#define DRM_TEGRA_SYNCPT_READ 0x02 +#define DRM_TEGRA_SYNCPT_INCR 0x03 +#define DRM_TEGRA_SYNCPT_WAIT 0x04 +#define DRM_TEGRA_OPEN_CHANNEL 0x05 +#define DRM_TEGRA_CLOSE_CHANNEL 0x06 +#define DRM_TEGRA_GET_SYNCPT 0x07 +#define DRM_TEGRA_SUBMIT 0x08 +#define DRM_TEGRA_GET_SYNCPT_BASE 0x09 #define DRM_IOCTL_TEGRA_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_CREATE, struct drm_tegra_gem_create) #define DRM_IOCTL_TEGRA_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_MMAP, struct drm_tegra_gem_mmap) @@ -137,5 +144,6 @@ struct drm_tegra_submit { #define DRM_IOCTL_TEGRA_CLOSE_CHANNEL DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_CLOSE_CHANNEL, struct drm_tegra_open_channel) #define DRM_IOCTL_TEGRA_GET_SYNCPT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT, struct drm_tegra_get_syncpt) #define DRM_IOCTL_TEGRA_SUBMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SUBMIT, struct drm_tegra_submit) +#define DRM_IOCTL_TEGRA_GET_SYNCPT_BASE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT_BASE, struct drm_tegra_get_syncpt_base) #endif -- cgit v1.1