diff options
author | Mayuresh Kulkarni <mkulkarni@nvidia.com> | 2012-02-13 20:34:41 +0530 |
---|---|---|
committer | Rohan Somvanshi <rsomvanshi@nvidia.com> | 2012-03-21 08:44:15 -0700 |
commit | a0f946efbef9caa197ad2048d45722f65618d6c3 (patch) | |
tree | 1d92dfe33f44c8119cfe4a141812f6d3b9309926 | |
parent | 4e1ec69f7c1b5a259d7df0435647e9005f1e033c (diff) |
video: tegra: host: refactor for upstreaming
- split the nvhost clients into their own directories
- each client is a nvhost_device and nvhost_driver
- all the code related to host1x control node is centralized
at single place in dev.c
- all the code related to host1x modules nodes is centralized
at single place in bus_client.c
- update the copyright notice & year for new files
Bug 871237
Change-Id: Ief85064699e35ad02b48a7e54496928d7f085af4
Signed-off-by: Mayuresh Kulkarni <mkulkarni@nvidia.com>
Reviewed-on: http://git-master/r/83491
Reviewed-by: Rohan Somvanshi <rsomvanshi@nvidia.com>
Tested-by: Rohan Somvanshi <rsomvanshi@nvidia.com>
21 files changed, 1294 insertions, 693 deletions
diff --git a/drivers/video/tegra/host/Makefile b/drivers/video/tegra/host/Makefile index be2be9211731..0180885af4d7 100644 --- a/drivers/video/tegra/host/Makefile +++ b/drivers/video/tegra/host/Makefile @@ -6,14 +6,18 @@ nvhost-objs = \ nvhost_intr.o \ nvhost_channel.o \ nvhost_job.o \ - dev.o \ bus.o \ - bus_client.o \ - debug.o + dev.o \ + debug.o \ + bus_client.o obj-$(CONFIG_TEGRA_GRHOST) += mpe/ obj-$(CONFIG_TEGRA_GRHOST) += gr3d/ obj-$(CONFIG_TEGRA_GRHOST) += host1x/ obj-$(CONFIG_TEGRA_GRHOST) += t20/ obj-$(CONFIG_TEGRA_GRHOST) += t30/ +obj-$(CONFIG_TEGRA_GRHOST) += dsi/ +obj-$(CONFIG_TEGRA_GRHOST) += gr2d/ +obj-$(CONFIG_TEGRA_GRHOST) += isp/ +obj-$(CONFIG_TEGRA_GRHOST) += vi/ obj-$(CONFIG_TEGRA_GRHOST) += nvhost.o diff --git a/drivers/video/tegra/host/bus_client.c b/drivers/video/tegra/host/bus_client.c index 213fae59a4f0..b9164dc1b02b 100644 --- a/drivers/video/tegra/host/bus_client.c +++ b/drivers/video/tegra/host/bus_client.c @@ -18,9 +18,32 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <linux/slab.h> +#include <linux/string.h> +#include <linux/spinlock.h> +#include <linux/fs.h> +#include <linux/cdev.h> +#include <linux/uaccess.h> +#include <linux/file.h> +#include <linux/clk.h> +#include <linux/hrtimer.h> + +#include <trace/events/nvhost.h> + +#include <linux/io.h> +#include <linux/string.h> + +#include <linux/nvhost.h> +#include <linux/nvhost_ioctl.h> + +#include <mach/nvmap.h> +#include <mach/gpufuse.h> +#include <mach/hardware.h> +#include <mach/iomap.h> + +#include "debug.h" #include "bus_client.h" #include "dev.h" -#include <linux/string.h> void nvhost_read_module_regs(struct nvhost_device *ndev, u32 offset, int count, u32 *values) @@ -49,3 +72,535 @@ void nvhost_write_module_regs(struct nvhost_device *ndev, wmb(); nvhost_module_idle(ndev); } + +struct nvhost_channel_userctx { + struct nvhost_channel *ch; + struct nvhost_hwctx *hwctx; + struct nvhost_submit_hdr_ext hdr; + int num_relocshifts; + struct nvhost_job *job; + struct nvmap_client *nvmap; + u32 timeout; + u32 priority; + int clientid; +}; + +/* + * Write cmdbuf to ftrace output. Checks if cmdbuf contents should be output + * and mmaps the cmdbuf contents if required. + */ +static void trace_write_cmdbufs(struct nvhost_job *job) +{ + struct nvmap_handle_ref handle; + void *mem = NULL; + int i = 0; + + for (i = 0; i < job->num_gathers; i++) { + struct nvhost_channel_gather *gather = &job->gathers[i]; + if (nvhost_debug_trace_cmdbuf) { + handle.handle = nvmap_id_to_handle(gather->mem_id); + mem = nvmap_mmap(&handle); + if (IS_ERR_OR_NULL(mem)) + mem = NULL; + }; + + if (mem) { + u32 i; + /* + * Write in batches of 128 as there seems to be a limit + * of how much you can output to ftrace at once. + */ + for (i = 0; i < gather->words; i += TRACE_MAX_LENGTH) { + trace_nvhost_channel_write_cmdbuf_data( + job->ch->dev->name, + gather->mem_id, + min(gather->words - i, + TRACE_MAX_LENGTH), + gather->offset + i * sizeof(u32), + mem); + } + nvmap_munmap(&handle, mem); + } + } +} + +static int nvhost_channelrelease(struct inode *inode, struct file *filp) +{ + struct nvhost_channel_userctx *priv = filp->private_data; + + trace_nvhost_channel_release(priv->ch->dev->name); + + filp->private_data = NULL; + + nvhost_module_remove_client(priv->ch->dev, priv); + nvhost_putchannel(priv->ch, priv->hwctx); + + if (priv->hwctx) + priv->ch->ctxhandler->put(priv->hwctx); + + if (priv->job) + nvhost_job_put(priv->job); + + nvmap_client_put(priv->nvmap); + kfree(priv); + return 0; +} + +static int nvhost_channelopen(struct inode *inode, struct file *filp) +{ + struct nvhost_channel_userctx *priv; + struct nvhost_channel *ch; + + ch = container_of(inode->i_cdev, struct nvhost_channel, cdev); + ch = nvhost_getchannel(ch); + if (!ch) + return -ENOMEM; + trace_nvhost_channel_open(ch->dev->name); + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) { + nvhost_putchannel(ch, NULL); + return -ENOMEM; + } + filp->private_data = priv; + priv->ch = ch; + nvhost_module_add_client(ch->dev, priv); + + if (ch->ctxhandler && ch->ctxhandler->alloc) { + priv->hwctx = ch->ctxhandler->alloc(ch->ctxhandler, ch); + if (!priv->hwctx) + goto fail; + } + priv->priority = NVHOST_PRIORITY_MEDIUM; + priv->clientid = atomic_add_return(1, + &nvhost_get_host(ch->dev)->clientid); + + priv->job = nvhost_job_alloc(ch, priv->hwctx, &priv->hdr, + NULL, priv->priority, priv->clientid); + if (!priv->job) + goto fail; + + return 0; +fail: + nvhost_channelrelease(inode, filp); + return -ENOMEM; +} + +static int set_submit(struct nvhost_channel_userctx *ctx) +{ + struct device *device = &ctx->ch->dev->dev; + + /* submit should have at least 1 cmdbuf */ + if (!ctx->hdr.num_cmdbufs) + return -EIO; + + if (!ctx->nvmap) { + dev_err(device, "no nvmap context set\n"); + return -EFAULT; + } + + ctx->job = nvhost_job_realloc(ctx->job, + &ctx->hdr, + ctx->nvmap, + ctx->priority, + ctx->clientid); + if (!ctx->job) + return -ENOMEM; + ctx->job->timeout = ctx->timeout; + + if (ctx->hdr.submit_version >= NVHOST_SUBMIT_VERSION_V2) + ctx->num_relocshifts = ctx->hdr.num_relocs; + + return 0; +} + +static void reset_submit(struct nvhost_channel_userctx *ctx) +{ + ctx->hdr.num_cmdbufs = 0; + ctx->hdr.num_relocs = 0; + ctx->num_relocshifts = 0; + ctx->hdr.num_waitchks = 0; +} + +static ssize_t nvhost_channelwrite(struct file *filp, const char __user *buf, + size_t count, loff_t *offp) +{ + struct nvhost_channel_userctx *priv = filp->private_data; + size_t remaining = count; + int err = 0; + struct nvhost_job *job = priv->job; + struct nvhost_submit_hdr_ext *hdr = &priv->hdr; + const char *chname = priv->ch->dev->name; + + if (!job) + return -EIO; + + while (remaining) { + size_t consumed; + if (!hdr->num_relocs && + !priv->num_relocshifts && + !hdr->num_cmdbufs && + !hdr->num_waitchks) { + consumed = sizeof(struct nvhost_submit_hdr); + if (remaining < consumed) + break; + if (copy_from_user(hdr, buf, consumed)) { + err = -EFAULT; + break; + } + hdr->submit_version = NVHOST_SUBMIT_VERSION_V0; + err = set_submit(priv); + if (err) + break; + trace_nvhost_channel_write_submit(chname, + count, hdr->num_cmdbufs, hdr->num_relocs, + hdr->syncpt_id, hdr->syncpt_incrs); + } else if (hdr->num_cmdbufs) { + struct nvhost_cmdbuf cmdbuf; + consumed = sizeof(cmdbuf); + if (remaining < consumed) + break; + if (copy_from_user(&cmdbuf, buf, consumed)) { + err = -EFAULT; + break; + } + trace_nvhost_channel_write_cmdbuf(chname, + cmdbuf.mem, cmdbuf.words, cmdbuf.offset); + nvhost_job_add_gather(job, + cmdbuf.mem, cmdbuf.words, cmdbuf.offset); + hdr->num_cmdbufs--; + } else if (hdr->num_relocs) { + consumed = sizeof(struct nvhost_reloc); + if (remaining < consumed) + break; + if (copy_from_user(&job->pinarray[job->num_pins], + buf, consumed)) { + err = -EFAULT; + break; + } + trace_nvhost_channel_write_reloc(chname); + job->num_pins++; + hdr->num_relocs--; + } else if (hdr->num_waitchks) { + int numwaitchks = + (remaining / sizeof(struct nvhost_waitchk)); + if (!numwaitchks) + break; + numwaitchks = min_t(int, + numwaitchks, hdr->num_waitchks); + consumed = numwaitchks * sizeof(struct nvhost_waitchk); + if (copy_from_user(&job->waitchk[job->num_waitchk], + buf, consumed)) { + err = -EFAULT; + break; + } + trace_nvhost_channel_write_waitchks( + chname, numwaitchks, + hdr->waitchk_mask); + job->num_waitchk += numwaitchks; + hdr->num_waitchks -= numwaitchks; + } else if (priv->num_relocshifts) { + int next_shift = + job->num_pins - priv->num_relocshifts; + consumed = sizeof(struct nvhost_reloc_shift); + if (remaining < consumed) + break; + if (copy_from_user( + &job->pinarray[next_shift].reloc_shift, + buf, consumed)) { + err = -EFAULT; + break; + } + priv->num_relocshifts--; + } else { + err = -EFAULT; + break; + } + remaining -= consumed; + buf += consumed; + } + + if (err < 0) { + dev_err(&priv->ch->dev->dev, "channel write error\n"); + reset_submit(priv); + return err; + } + + return count - remaining; +} + +static int nvhost_ioctl_channel_flush( + struct nvhost_channel_userctx *ctx, + struct nvhost_get_param_args *args, + int null_kickoff) +{ + struct device *device = &ctx->ch->dev->dev; + int err; + + trace_nvhost_ioctl_channel_flush(ctx->ch->dev->name); + + if (!ctx->job || + ctx->hdr.num_relocs || + ctx->hdr.num_cmdbufs || + ctx->hdr.num_waitchks) { + reset_submit(ctx); + dev_err(device, "channel submit out of sync\n"); + return -EFAULT; + } + + err = nvhost_job_pin(ctx->job); + if (err) { + dev_warn(device, "nvhost_job_pin failed: %d\n", err); + return err; + } + + if (nvhost_debug_null_kickoff_pid == current->tgid) + null_kickoff = 1; + ctx->job->null_kickoff = null_kickoff; + + if ((nvhost_debug_force_timeout_pid == current->tgid) && + (nvhost_debug_force_timeout_channel == ctx->ch->chid)) { + ctx->timeout = nvhost_debug_force_timeout_val; + } + + trace_write_cmdbufs(ctx->job); + + /* context switch if needed, and submit user's gathers to the channel */ + err = nvhost_channel_submit(ctx->job); + args->value = ctx->job->syncpt_end; + if (err) + nvhost_job_unpin(ctx->job); + + return err; +} + +static int nvhost_ioctl_channel_read_3d_reg( + struct nvhost_channel_userctx *ctx, + struct nvhost_read_3d_reg_args *args) +{ + BUG_ON(!channel_op(ctx->ch).read3dreg); + return channel_op(ctx->ch).read3dreg(ctx->ch, ctx->hwctx, + args->offset, &args->value); +} + +static long nvhost_channelctl(struct file *filp, + unsigned int cmd, unsigned long arg) +{ + struct nvhost_channel_userctx *priv = filp->private_data; + u8 buf[NVHOST_IOCTL_CHANNEL_MAX_ARG_SIZE]; + int err = 0; + + if ((_IOC_TYPE(cmd) != NVHOST_IOCTL_MAGIC) || + (_IOC_NR(cmd) == 0) || + (_IOC_NR(cmd) > NVHOST_IOCTL_CHANNEL_LAST)) + return -EFAULT; + + BUG_ON(_IOC_SIZE(cmd) > NVHOST_IOCTL_CHANNEL_MAX_ARG_SIZE); + + if (_IOC_DIR(cmd) & _IOC_WRITE) { + if (copy_from_user(buf, (void __user *)arg, _IOC_SIZE(cmd))) + return -EFAULT; + } + + switch (cmd) { + case NVHOST_IOCTL_CHANNEL_FLUSH: + err = nvhost_ioctl_channel_flush(priv, (void *)buf, 0); + break; + case NVHOST_IOCTL_CHANNEL_NULL_KICKOFF: + err = nvhost_ioctl_channel_flush(priv, (void *)buf, 1); + break; + case NVHOST_IOCTL_CHANNEL_SUBMIT_EXT: + { + struct nvhost_submit_hdr_ext *hdr; + + if (priv->hdr.num_relocs || + priv->num_relocshifts || + priv->hdr.num_cmdbufs || + priv->hdr.num_waitchks) { + reset_submit(priv); + dev_err(&priv->ch->dev->dev, + "channel submit out of sync\n"); + err = -EIO; + break; + } + + hdr = (struct nvhost_submit_hdr_ext *)buf; + if (hdr->submit_version > NVHOST_SUBMIT_VERSION_MAX_SUPPORTED) { + dev_err(&priv->ch->dev->dev, + "submit version %d > max supported %d\n", + hdr->submit_version, + NVHOST_SUBMIT_VERSION_MAX_SUPPORTED); + err = -EINVAL; + break; + } + memcpy(&priv->hdr, hdr, sizeof(struct nvhost_submit_hdr_ext)); + err = set_submit(priv); + trace_nvhost_ioctl_channel_submit(priv->ch->dev->name, + priv->hdr.submit_version, + priv->hdr.num_cmdbufs, priv->hdr.num_relocs, + priv->hdr.num_waitchks, + priv->hdr.syncpt_id, priv->hdr.syncpt_incrs); + break; + } + case NVHOST_IOCTL_CHANNEL_GET_SYNCPOINTS: + /* host syncpt ID is used by the RM (and never be given out) */ + BUG_ON(priv->ch->dev->syncpts & (1 << NVSYNCPT_GRAPHICS_HOST)); + ((struct nvhost_get_param_args *)buf)->value = + priv->ch->dev->syncpts; + break; + case NVHOST_IOCTL_CHANNEL_GET_WAITBASES: + ((struct nvhost_get_param_args *)buf)->value = + priv->ch->dev->waitbases; + break; + case NVHOST_IOCTL_CHANNEL_GET_MODMUTEXES: + ((struct nvhost_get_param_args *)buf)->value = + priv->ch->dev->modulemutexes; + break; + case NVHOST_IOCTL_CHANNEL_SET_NVMAP_FD: + { + int fd = (int)((struct nvhost_set_nvmap_fd_args *)buf)->fd; + struct nvmap_client *new_client = nvmap_client_get_file(fd); + + if (IS_ERR(new_client)) { + err = PTR_ERR(new_client); + break; + } + + if (priv->nvmap) + nvmap_client_put(priv->nvmap); + + priv->nvmap = new_client; + break; + } + case NVHOST_IOCTL_CHANNEL_READ_3D_REG: + err = nvhost_ioctl_channel_read_3d_reg(priv, (void *)buf); + break; + case NVHOST_IOCTL_CHANNEL_GET_CLK_RATE: + { + unsigned long rate; + struct nvhost_clk_rate_args *arg = + (struct nvhost_clk_rate_args *)buf; + + err = nvhost_module_get_rate(priv->ch->dev, &rate, 0); + if (err == 0) + arg->rate = rate; + break; + } + case NVHOST_IOCTL_CHANNEL_SET_CLK_RATE: + { + struct nvhost_clk_rate_args *arg = + (struct nvhost_clk_rate_args *)buf; + unsigned long rate = (unsigned long)arg->rate; + + err = nvhost_module_set_rate(priv->ch->dev, priv, rate, 0); + break; + } + case NVHOST_IOCTL_CHANNEL_SET_TIMEOUT: + priv->timeout = + (u32)((struct nvhost_set_timeout_args *)buf)->timeout; + dev_dbg(&priv->ch->dev->dev, + "%s: setting buffer timeout (%d ms) for userctx 0x%p\n", + __func__, priv->timeout, priv); + break; + case NVHOST_IOCTL_CHANNEL_GET_TIMEDOUT: + ((struct nvhost_get_param_args *)buf)->value = + priv->hwctx->has_timedout; + break; + case NVHOST_IOCTL_CHANNEL_SET_PRIORITY: + priv->priority = + (u32)((struct nvhost_set_priority_args *)buf)->priority; + break; + default: + err = -ENOTTY; + break; + } + + if ((err == 0) && (_IOC_DIR(cmd) & _IOC_READ)) + err = copy_to_user((void __user *)arg, buf, _IOC_SIZE(cmd)); + + return err; +} + +static const struct file_operations nvhost_channelops = { + .owner = THIS_MODULE, + .release = nvhost_channelrelease, + .open = nvhost_channelopen, + .write = nvhost_channelwrite, + .unlocked_ioctl = nvhost_channelctl +}; + +int nvhost_client_user_init(struct nvhost_device *dev) +{ + int err, devno; + + struct nvhost_channel *ch = dev->channel; + + cdev_init(&ch->cdev, &nvhost_channelops); + ch->cdev.owner = THIS_MODULE; + + devno = MKDEV(nvhost_major, nvhost_minor + dev->index); + err = cdev_add(&ch->cdev, devno, 1); + if (err < 0) { + dev_err(&dev->dev, + "failed to add chan %i cdev\n", dev->index); + goto fail; + } + ch->node = device_create(nvhost_get_host(dev)->nvhost_class, NULL, devno, NULL, + IFACE_NAME "-%s", dev->name); + if (IS_ERR(ch->node)) { + err = PTR_ERR(ch->node); + dev_err(&dev->dev, + "failed to create %s channel device\n", dev->name); + goto fail; + } + + return 0; +fail: + return err; +} + +int nvhost_client_device_init(struct nvhost_device *dev) +{ + int err; + struct nvhost_master *nvhost_master = nvhost_get_host(dev); + struct nvhost_channel *ch = &nvhost_master->channels[dev->index]; + + /* store the pointer to this device for channel */ + ch->dev = dev; + + err = nvhost_channel_init(ch, nvhost_master, dev->index); + if (err) + goto fail; + + err = nvhost_client_user_init(dev); + if (err) + goto fail; + + err = nvhost_module_init(dev); + if (err) + goto fail; + + dev_info(&dev->dev, "initialized\n"); + + return 0; + +fail: + /* Add clean-up */ + return err; +} + +int nvhost_client_device_suspend(struct nvhost_device *dev) +{ + int ret = 0; + + dev_info(&dev->dev, "suspending\n"); + + ret = nvhost_channel_suspend(dev->channel); + if (ret) + return ret; + + ret = nvhost_module_suspend(dev, true); + dev_info(&dev->dev, "suspend status: %d\n", ret); + + return ret; +} diff --git a/drivers/video/tegra/host/bus_client.h b/drivers/video/tegra/host/bus_client.h index 45ea473c8848..4e47071fd141 100644 --- a/drivers/video/tegra/host/bus_client.h +++ b/drivers/video/tegra/host/bus_client.h @@ -1,7 +1,7 @@ /* * drivers/video/tegra/host/bus_client.h * - * Tegra Graphics Host Cpu Register Access + * Tegra Graphics Host client * * Copyright (c) 2010-2012, NVIDIA Corporation. * @@ -30,4 +30,10 @@ void nvhost_read_module_regs(struct nvhost_device *ndev, void nvhost_write_module_regs(struct nvhost_device *ndev, u32 offset, int count, const u32 *values); +int nvhost_client_user_init(struct nvhost_device *dev); + +int nvhost_client_device_init(struct nvhost_device *dev); + +int nvhost_client_device_suspend(struct nvhost_device *dev); + #endif diff --git a/drivers/video/tegra/host/chip_support.h b/drivers/video/tegra/host/chip_support.h index feae7422f28a..17e7f4b165a0 100644 --- a/drivers/video/tegra/host/chip_support.h +++ b/drivers/video/tegra/host/chip_support.h @@ -129,6 +129,11 @@ struct nvhost_chip_support { void (*free_host_general_irq)(struct nvhost_intr *); int (*request_syncpt_irq)(struct nvhost_intr_syncpt *syncpt); } intr; + + struct { + struct nvhost_device *(*get_nvhost_device)(struct nvhost_master *host, + char *name); + } nvhost_dev; }; #endif /* _NVHOST_CHIP_SUPPORT_H_ */ diff --git a/drivers/video/tegra/host/dev.c b/drivers/video/tegra/host/dev.c index 4ab0f1e0c106..8f0c0393401b 100644 --- a/drivers/video/tegra/host/dev.c +++ b/drivers/video/tegra/host/dev.c @@ -18,9 +18,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "dev.h" -#include "bus_client.h" - #include <linux/slab.h> #include <linux/string.h> #include <linux/spinlock.h> @@ -30,6 +27,8 @@ #include <linux/file.h> #include <linux/clk.h> #include <linux/hrtimer.h> + +#include "dev.h" #define CREATE_TRACE_POINTS #include <trace/events/nvhost.h> @@ -46,481 +45,20 @@ #include "nvhost_job.h" #include "t20/t20.h" #include "t30/t30.h" +#include "bus_client.h" #define DRIVER_NAME "host1x" -#define IFACE_NAME "nvhost" -#define TRACE_MAX_LENGTH 128U -static int nvhost_major = NVHOST_MAJOR; -static int nvhost_minor; -static unsigned int register_sets; +int nvhost_major; +int nvhost_minor; -struct nvhost_channel_userctx { - struct nvhost_channel *ch; - struct nvhost_hwctx *hwctx; - struct nvhost_submit_hdr_ext hdr; - int num_relocshifts; - struct nvhost_job *job; - struct nvmap_client *nvmap; - u32 timeout; - u32 priority; - int clientid; -}; +static unsigned int register_sets; struct nvhost_ctrl_userctx { struct nvhost_master *dev; u32 *mod_locks; }; -/* - * Write cmdbuf to ftrace output. Checks if cmdbuf contents should be output - * and mmaps the cmdbuf contents if required. - */ -static void trace_write_cmdbufs(struct nvhost_job *job) -{ -#if defined(CONFIG_TEGRA_NVMAP) - struct nvmap_handle_ref handle; - void *mem = NULL; - int i = 0; - - for (i = 0; i < job->num_gathers; i++) { - struct nvhost_channel_gather *gather = &job->gathers[i]; - if (nvhost_debug_trace_cmdbuf) { - handle.handle = nvmap_id_to_handle(gather->mem_id); - mem = nvmap_mmap(&handle); - if (IS_ERR_OR_NULL(mem)) - mem = NULL; - }; - - if (mem) { - u32 i; - /* - * Write in batches of 128 as there seems to be a limit - * of how much you can output to ftrace at once. - */ - for (i = 0; i < gather->words; i += TRACE_MAX_LENGTH) { - trace_nvhost_channel_write_cmdbuf_data( - job->ch->dev->name, - gather->mem_id, - min(gather->words - i, - TRACE_MAX_LENGTH), - gather->offset + i * sizeof(u32), - mem); - } - nvmap_munmap(&handle, mem); - } - } -#endif -} - -static int nvhost_channelrelease(struct inode *inode, struct file *filp) -{ - struct nvhost_channel_userctx *priv = filp->private_data; - - trace_nvhost_channel_release(priv->ch->dev->name); - - filp->private_data = NULL; - - nvhost_module_remove_client(priv->ch->dev, priv); - nvhost_putchannel(priv->ch, priv->hwctx); - - if (priv->hwctx) - priv->ch->ctxhandler->put(priv->hwctx); - - if (priv->job) - nvhost_job_put(priv->job); - - nvmap_client_put(priv->nvmap); - kfree(priv); - return 0; -} - -static int nvhost_channelopen(struct inode *inode, struct file *filp) -{ - struct nvhost_channel_userctx *priv; - struct nvhost_channel *ch; - - ch = container_of(inode->i_cdev, struct nvhost_channel, cdev); - ch = nvhost_getchannel(ch); - if (!ch) - return -ENOMEM; - trace_nvhost_channel_open(ch->dev->name); - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) { - nvhost_putchannel(ch, NULL); - return -ENOMEM; - } - filp->private_data = priv; - priv->ch = ch; - nvhost_module_add_client(ch->dev, priv); - - if (ch->ctxhandler && ch->ctxhandler->alloc) { - priv->hwctx = ch->ctxhandler->alloc(ch->ctxhandler, ch); - if (!priv->hwctx) - goto fail; - } - priv->priority = NVHOST_PRIORITY_MEDIUM; - priv->clientid = atomic_add_return(1, - &nvhost_get_host(ch->dev)->clientid); - - priv->job = nvhost_job_alloc(ch, priv->hwctx, &priv->hdr, - NULL, priv->priority, priv->clientid); - if (!priv->job) - goto fail; - - return 0; -fail: - nvhost_channelrelease(inode, filp); - return -ENOMEM; -} - -static int set_submit(struct nvhost_channel_userctx *ctx) -{ - struct device *device = &ctx->ch->dev->dev; - - /* submit should have at least 1 cmdbuf */ - if (!ctx->hdr.num_cmdbufs) - return -EIO; - - if (!ctx->nvmap) { - dev_err(device, "no nvmap context set\n"); - return -EFAULT; - } - - ctx->job = nvhost_job_realloc(ctx->job, - &ctx->hdr, - ctx->nvmap, - ctx->priority, - ctx->clientid); - if (!ctx->job) - return -ENOMEM; - ctx->job->timeout = ctx->timeout; - - if (ctx->hdr.submit_version >= NVHOST_SUBMIT_VERSION_V2) - ctx->num_relocshifts = ctx->hdr.num_relocs; - - return 0; -} - -static void reset_submit(struct nvhost_channel_userctx *ctx) -{ - ctx->hdr.num_cmdbufs = 0; - ctx->hdr.num_relocs = 0; - ctx->num_relocshifts = 0; - ctx->hdr.num_waitchks = 0; -} - -static ssize_t nvhost_channelwrite(struct file *filp, const char __user *buf, - size_t count, loff_t *offp) -{ - struct nvhost_channel_userctx *priv = filp->private_data; - size_t remaining = count; - int err = 0; - struct nvhost_job *job = priv->job; - struct nvhost_submit_hdr_ext *hdr = &priv->hdr; - const char *chname = priv->ch->dev->name; - - if (!job) - return -EIO; - - while (remaining) { - size_t consumed; - if (!hdr->num_relocs && - !priv->num_relocshifts && - !hdr->num_cmdbufs && - !hdr->num_waitchks) { - consumed = sizeof(struct nvhost_submit_hdr); - if (remaining < consumed) - break; - if (copy_from_user(hdr, buf, consumed)) { - err = -EFAULT; - break; - } - hdr->submit_version = NVHOST_SUBMIT_VERSION_V0; - err = set_submit(priv); - if (err) - break; - trace_nvhost_channel_write_submit(chname, - count, hdr->num_cmdbufs, hdr->num_relocs, - hdr->syncpt_id, hdr->syncpt_incrs); - } else if (hdr->num_cmdbufs) { - struct nvhost_cmdbuf cmdbuf; - consumed = sizeof(cmdbuf); - if (remaining < consumed) - break; - if (copy_from_user(&cmdbuf, buf, consumed)) { - err = -EFAULT; - break; - } - trace_nvhost_channel_write_cmdbuf(chname, - cmdbuf.mem, cmdbuf.words, cmdbuf.offset); - nvhost_job_add_gather(job, - cmdbuf.mem, cmdbuf.words, cmdbuf.offset); - hdr->num_cmdbufs--; - } else if (hdr->num_relocs) { - struct nvmap_pinarray_elem *elem = - &job->pinarray[job->num_pins]; - consumed = sizeof(struct nvhost_reloc); - if (remaining < consumed) - break; - if (copy_from_user(elem, buf, consumed)) { - err = -EFAULT; - break; - } - elem->patch_mem = - nvmap_convert_handle_u2k(elem->patch_mem); - elem->pin_mem = - nvmap_convert_handle_u2k(elem->pin_mem); - trace_nvhost_channel_write_reloc(chname); - job->num_pins++; - hdr->num_relocs--; - } else if (hdr->num_waitchks) { - struct nvhost_waitchk *waitchk = - &job->waitchk[job->num_waitchk]; - consumed = sizeof(struct nvhost_waitchk); - if (remaining < consumed) - break; - if (copy_from_user(waitchk, buf, consumed)) { - err = -EFAULT; - break; - } - waitchk->mem = nvmap_convert_handle_u2k(waitchk->mem); - trace_nvhost_channel_write_waitchks( - chname, 1, - hdr->waitchk_mask); - job->num_waitchk++; - hdr->num_waitchks--; - } else if (priv->num_relocshifts) { - int next_shift = - job->num_pins - priv->num_relocshifts; - consumed = sizeof(struct nvhost_reloc_shift); - if (remaining < consumed) - break; - if (copy_from_user( - &job->pinarray[next_shift].reloc_shift, - buf, consumed)) { - err = -EFAULT; - break; - } - priv->num_relocshifts--; - } else { - err = -EFAULT; - break; - } - remaining -= consumed; - buf += consumed; - } - - if (err < 0) { - dev_err(&priv->ch->dev->dev, "channel write error\n"); - reset_submit(priv); - return err; - } - - return count - remaining; -} - -static int nvhost_ioctl_channel_flush( - struct nvhost_channel_userctx *ctx, - struct nvhost_get_param_args *args, - int null_kickoff) -{ - struct device *device = &ctx->ch->dev->dev; - int err; - - trace_nvhost_ioctl_channel_flush(ctx->ch->dev->name); - - if (!ctx->job || - ctx->hdr.num_relocs || - ctx->hdr.num_cmdbufs || - ctx->hdr.num_waitchks) { - reset_submit(ctx); - dev_err(device, "channel submit out of sync\n"); - return -EFAULT; - } - - err = nvhost_job_pin(ctx->job); - if (err) { - dev_warn(device, "nvhost_job_pin failed: %d\n", err); - return err; - } - - if (nvhost_debug_null_kickoff_pid == current->tgid) - null_kickoff = 1; - ctx->job->null_kickoff = null_kickoff; - - if ((nvhost_debug_force_timeout_pid == current->tgid) && - (nvhost_debug_force_timeout_channel == ctx->ch->chid)) { - ctx->timeout = nvhost_debug_force_timeout_val; - } - - trace_write_cmdbufs(ctx->job); - - /* context switch if needed, and submit user's gathers to the channel */ - err = nvhost_channel_submit(ctx->job); - args->value = ctx->job->syncpt_end; - if (err) - nvhost_job_unpin(ctx->job); - - return err; -} - -static int nvhost_ioctl_channel_read_3d_reg( - struct nvhost_channel_userctx *ctx, - struct nvhost_read_3d_reg_args *args) -{ - BUG_ON(!channel_op(ctx->ch).read3dreg); - return channel_op(ctx->ch).read3dreg(ctx->ch, ctx->hwctx, - args->offset, &args->value); -} - -static long nvhost_channelctl(struct file *filp, - unsigned int cmd, unsigned long arg) -{ - struct nvhost_channel_userctx *priv = filp->private_data; - u8 buf[NVHOST_IOCTL_CHANNEL_MAX_ARG_SIZE]; - int err = 0; - - if ((_IOC_TYPE(cmd) != NVHOST_IOCTL_MAGIC) || - (_IOC_NR(cmd) == 0) || - (_IOC_NR(cmd) > NVHOST_IOCTL_CHANNEL_LAST)) - return -EFAULT; - - BUG_ON(_IOC_SIZE(cmd) > NVHOST_IOCTL_CHANNEL_MAX_ARG_SIZE); - - if (_IOC_DIR(cmd) & _IOC_WRITE) { - if (copy_from_user(buf, (void __user *)arg, _IOC_SIZE(cmd))) - return -EFAULT; - } - - switch (cmd) { - case NVHOST_IOCTL_CHANNEL_FLUSH: - err = nvhost_ioctl_channel_flush(priv, (void *)buf, 0); - break; - case NVHOST_IOCTL_CHANNEL_NULL_KICKOFF: - err = nvhost_ioctl_channel_flush(priv, (void *)buf, 1); - break; - case NVHOST_IOCTL_CHANNEL_SUBMIT_EXT: - { - struct nvhost_submit_hdr_ext *hdr; - - if (priv->hdr.num_relocs || - priv->num_relocshifts || - priv->hdr.num_cmdbufs || - priv->hdr.num_waitchks) { - reset_submit(priv); - dev_err(&priv->ch->dev->dev, - "channel submit out of sync\n"); - err = -EIO; - break; - } - - hdr = (struct nvhost_submit_hdr_ext *)buf; - if (hdr->submit_version > NVHOST_SUBMIT_VERSION_MAX_SUPPORTED) { - dev_err(&priv->ch->dev->dev, - "submit version %d > max supported %d\n", - hdr->submit_version, - NVHOST_SUBMIT_VERSION_MAX_SUPPORTED); - err = -EINVAL; - break; - } - memcpy(&priv->hdr, hdr, sizeof(struct nvhost_submit_hdr_ext)); - err = set_submit(priv); - trace_nvhost_ioctl_channel_submit(priv->ch->dev->name, - priv->hdr.submit_version, - priv->hdr.num_cmdbufs, priv->hdr.num_relocs, - priv->hdr.num_waitchks, - priv->hdr.syncpt_id, priv->hdr.syncpt_incrs); - break; - } - case NVHOST_IOCTL_CHANNEL_GET_SYNCPOINTS: - /* host syncpt ID is used by the RM (and never be given out) */ - BUG_ON(priv->ch->dev->syncpts & (1 << NVSYNCPT_GRAPHICS_HOST)); - ((struct nvhost_get_param_args *)buf)->value = - priv->ch->dev->syncpts; - break; - case NVHOST_IOCTL_CHANNEL_GET_WAITBASES: - ((struct nvhost_get_param_args *)buf)->value = - priv->ch->dev->waitbases; - break; - case NVHOST_IOCTL_CHANNEL_GET_MODMUTEXES: - ((struct nvhost_get_param_args *)buf)->value = - priv->ch->dev->modulemutexes; - break; - case NVHOST_IOCTL_CHANNEL_SET_NVMAP_FD: - { - int fd = (int)((struct nvhost_set_nvmap_fd_args *)buf)->fd; - struct nvmap_client *new_client = nvmap_client_get_file(fd); - - if (IS_ERR(new_client)) { - err = PTR_ERR(new_client); - break; - } - - if (priv->nvmap) - nvmap_client_put(priv->nvmap); - - priv->nvmap = new_client; - break; - } - case NVHOST_IOCTL_CHANNEL_READ_3D_REG: - err = nvhost_ioctl_channel_read_3d_reg(priv, (void *)buf); - break; - case NVHOST_IOCTL_CHANNEL_GET_CLK_RATE: - { - unsigned long rate; - struct nvhost_clk_rate_args *arg = - (struct nvhost_clk_rate_args *)buf; - - err = nvhost_module_get_rate(priv->ch->dev, &rate, 0); - if (err == 0) - arg->rate = rate; - break; - } - case NVHOST_IOCTL_CHANNEL_SET_CLK_RATE: - { - struct nvhost_clk_rate_args *arg = - (struct nvhost_clk_rate_args *)buf; - unsigned long rate = (unsigned long)arg->rate; - - err = nvhost_module_set_rate(priv->ch->dev, priv, rate, 0); - break; - } - case NVHOST_IOCTL_CHANNEL_SET_TIMEOUT: - priv->timeout = - (u32)((struct nvhost_set_timeout_args *)buf)->timeout; - dev_dbg(&priv->ch->dev->dev, - "%s: setting buffer timeout (%d ms) for userctx 0x%p\n", - __func__, priv->timeout, priv); - break; - case NVHOST_IOCTL_CHANNEL_GET_TIMEDOUT: - ((struct nvhost_get_param_args *)buf)->value = - priv->hwctx->has_timedout; - break; - case NVHOST_IOCTL_CHANNEL_SET_PRIORITY: - priv->priority = - (u32)((struct nvhost_set_priority_args *)buf)->priority; - break; - default: - err = -ENOTTY; - break; - } - - if ((err == 0) && (_IOC_DIR(cmd) & _IOC_READ)) - err = copy_to_user((void __user *)arg, buf, _IOC_SIZE(cmd)); - - return err; -} - -static const struct file_operations nvhost_channelops = { - .owner = THIS_MODULE, - .release = nvhost_channelrelease, - .open = nvhost_channelopen, - .write = nvhost_channelwrite, - .unlocked_ioctl = nvhost_channelctl -}; - static int nvhost_ctrlrelease(struct inode *inode, struct file *filp) { struct nvhost_ctrl_userctx *priv = filp->private_data; @@ -562,8 +100,7 @@ static int nvhost_ctrlopen(struct inode *inode, struct file *filp) return 0; } -static int nvhost_ioctl_ctrl_syncpt_read( - struct nvhost_ctrl_userctx *ctx, +static int nvhost_ioctl_ctrl_syncpt_read(struct nvhost_ctrl_userctx *ctx, struct nvhost_ctrl_syncpt_read_args *args) { if (args->id >= ctx->dev->syncpt.nb_pts) @@ -573,8 +110,7 @@ static int nvhost_ioctl_ctrl_syncpt_read( return 0; } -static int nvhost_ioctl_ctrl_syncpt_incr( - struct nvhost_ctrl_userctx *ctx, +static int nvhost_ioctl_ctrl_syncpt_incr(struct nvhost_ctrl_userctx *ctx, struct nvhost_ctrl_syncpt_incr_args *args) { if (args->id >= ctx->dev->syncpt.nb_pts) @@ -584,8 +120,7 @@ static int nvhost_ioctl_ctrl_syncpt_incr( return 0; } -static int nvhost_ioctl_ctrl_syncpt_waitex( - struct nvhost_ctrl_userctx *ctx, +static int nvhost_ioctl_ctrl_syncpt_waitex(struct nvhost_ctrl_userctx *ctx, struct nvhost_ctrl_syncpt_waitex_args *args) { u32 timeout; @@ -605,8 +140,7 @@ static int nvhost_ioctl_ctrl_syncpt_waitex( return err; } -static int nvhost_ioctl_ctrl_module_mutex( - struct nvhost_ctrl_userctx *ctx, +static int nvhost_ioctl_ctrl_module_mutex(struct nvhost_ctrl_userctx *ctx, struct nvhost_ctrl_module_mutex_args *args) { int err = 0; @@ -640,14 +174,20 @@ static struct nvhost_device *get_ndev_by_moduleid(struct nvhost_master *host, for (i = 0; i < host->nb_channels; i++) { struct nvhost_device *ndev = host->channels[i].dev; + + /* display and dsi do not use channel for register programming. + * so their channels do not have device instance. + * hence skip such channels from here. */ + if (ndev == NULL) + continue; + if (id == ndev->moduleid) return ndev; } return NULL; } -static int nvhost_ioctl_ctrl_module_regrdwr( - struct nvhost_ctrl_userctx *ctx, +static int nvhost_ioctl_ctrl_module_regrdwr(struct nvhost_ctrl_userctx *ctx, struct nvhost_ctrl_module_regrdwr_args *args) { u32 num_offsets = args->num_offsets; @@ -697,8 +237,7 @@ static int nvhost_ioctl_ctrl_module_regrdwr( return 0; } -static int nvhost_ioctl_ctrl_get_version( - struct nvhost_ctrl_userctx *ctx, +static int nvhost_ioctl_ctrl_get_version(struct nvhost_ctrl_userctx *ctx, struct nvhost_get_param_args *args) { args->value = NVHOST_SUBMIT_VERSION_MAX_SUPPORTED; @@ -781,7 +320,7 @@ static int power_off_host(struct nvhost_device *dev) static int __devinit nvhost_user_init(struct nvhost_master *host) { - int i, err, devno; + int err, devno; host->nvhost_class = class_create(THIS_MODULE, IFACE_NAME); if (IS_ERR(host->nvhost_class)) { @@ -798,27 +337,6 @@ static int __devinit nvhost_user_init(struct nvhost_master *host) goto fail; } - for (i = 0; i < host->nb_channels; i++) { - struct nvhost_channel *ch = &host->channels[i]; - - cdev_init(&ch->cdev, &nvhost_channelops); - ch->cdev.owner = THIS_MODULE; - - devno = MKDEV(nvhost_major, nvhost_minor + i); - err = cdev_add(&ch->cdev, devno, 1); - if (err < 0) { - dev_err(&host->dev->dev, "failed to add chan %i cdev\n", i); - goto fail; - } - ch->node = device_create(host->nvhost_class, NULL, devno, NULL, - IFACE_NAME "-%s", ch->dev->name); - if (IS_ERR(ch->node)) { - err = PTR_ERR(ch->node); - dev_err(&host->dev->dev, "failed to create chan %i device\n", i); - goto fail; - } - } - cdev_init(&host->cdev, &nvhost_ctrlops); host->cdev.owner = THIS_MODULE; devno = MKDEV(nvhost_major, nvhost_minor + host->nb_channels); @@ -838,9 +356,14 @@ fail: return err; } -static void nvhost_remove_chip_support(struct nvhost_master *host) +struct nvhost_device *nvhost_get_device(char *name) { + BUG_ON(!host_device_op(nvhost).get_nvhost_device); + return host_device_op(nvhost).get_nvhost_device(nvhost, name); +} +static void nvhost_remove_chip_support(struct nvhost_master *host) +{ kfree(host->channels); host->channels = 0; @@ -907,7 +430,7 @@ static int __devinit nvhost_init_chip_support(struct nvhost_master *host) return 0; } -static struct resource tegra_grhost_resources[] = { +static struct resource nvhost_resources[] = { { .start = TEGRA_HOST1X_BASE, .end = TEGRA_HOST1X_BASE + TEGRA_HOST1X_SIZE - 1, @@ -953,8 +476,8 @@ static struct resource tegra_grhost_resources[] = { struct nvhost_device tegra_grhost_device = { .name = DRIVER_NAME, .id = -1, - .resource = tegra_grhost_resources, - .num_resources = ARRAY_SIZE(tegra_grhost_resources), + .resource = nvhost_resources, + .num_resources = ARRAY_SIZE(nvhost_resources), .finalize_poweron = power_on_host, .prepare_poweroff = power_off_host, .clocks = {{"host1x", UINT_MAX}, {} }, @@ -1016,14 +539,6 @@ static int __devinit nvhost_probe(struct nvhost_device *dev) nvhost_bus_add_host(host); - BUG_ON(!host_channel_op(host).init); - for (i = 0; i < host->nb_channels; i++) { - struct nvhost_channel *ch = &host->channels[i]; - err = nvhost_channel_init(ch, host, i); - if (err) - goto fail; - } - err = nvhost_intr_init(&host->intr, intr1->start, intr0->start); if (err) goto fail; @@ -1036,11 +551,6 @@ static int __devinit nvhost_probe(struct nvhost_device *dev) if (err) goto fail; - for (i = 0; i < host->nb_channels; i++) { - struct nvhost_channel *ch = &host->channels[i]; - nvhost_module_init(ch->dev); - } - for (i = 0; i < host->dev->num_clks; i++) clk_enable(host->dev->clk[i]); nvhost_syncpt_reset(&host->syncpt); @@ -1071,16 +581,9 @@ static int __exit nvhost_remove(struct nvhost_device *dev) static int nvhost_suspend(struct nvhost_device *dev, pm_message_t state) { struct nvhost_master *host = nvhost_get_drvdata(dev); - int i, ret = 0; + int ret = 0; dev_info(&dev->dev, "suspending\n"); - - for (i = 0; i < host->nb_channels; i++) { - ret = nvhost_channel_suspend(&host->channels[i]); - if (ret) - return ret; - } - ret = nvhost_module_suspend(host->dev, true); dev_info(&dev->dev, "suspend status: %d\n", ret); diff --git a/drivers/video/tegra/host/dev.h b/drivers/video/tegra/host/dev.h index 3a30eff5218e..74d7e16fc272 100644 --- a/drivers/video/tegra/host/dev.h +++ b/drivers/video/tegra/host/dev.h @@ -27,7 +27,12 @@ #include "nvhost_channel.h" #include "chip_support.h" -#define NVHOST_MAJOR 0 /* dynamic */ +#define TRACE_MAX_LENGTH 128U +#define IFACE_NAME "nvhost" + +extern int nvhost_major; +extern int nvhost_minor; + struct nvhost_hwctx; struct nvhost_master { @@ -49,9 +54,15 @@ struct nvhost_master { atomic_t clientid; }; +extern struct nvhost_master *nvhost; + void nvhost_debug_init(struct nvhost_master *master); void nvhost_debug_dump(struct nvhost_master *master); +#define host_device_op(host) (host->op.nvhost_dev) + +struct nvhost_device *nvhost_get_device(char *name); + extern pid_t nvhost_debug_null_kickoff_pid; #endif diff --git a/drivers/video/tegra/host/dsi/Makefile b/drivers/video/tegra/host/dsi/Makefile new file mode 100644 index 000000000000..eb94d3ec4928 --- /dev/null +++ b/drivers/video/tegra/host/dsi/Makefile @@ -0,0 +1,7 @@ +GCOV_PROFILE := y +EXTRA_CFLAGS += -Idrivers/video/tegra/host + +nvhost-dsi-objs = \ + dsi.o + +obj-$(CONFIG_TEGRA_GRHOST) += nvhost-dsi.o diff --git a/drivers/video/tegra/host/dsi/dsi.c b/drivers/video/tegra/host/dsi/dsi.c new file mode 100644 index 000000000000..0e49f591574d --- /dev/null +++ b/drivers/video/tegra/host/dsi/dsi.c @@ -0,0 +1,82 @@ +/* + * drivers/video/tegra/host/dsi/dsi.c + * + * Tegra Graphics DSI + * + * Copyright (c) 2012, NVIDIA Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>. + */ + +#include "dev.h" +#include "bus_client.h" + +static int dsi_probe(struct nvhost_device *dev) +{ + return nvhost_client_device_init(dev); +} + +static int __exit dsi_remove(struct nvhost_device *dev) +{ + /* Add clean-up */ + return 0; +} + +static int dsi_suspend(struct nvhost_device *dev, pm_message_t state) +{ + return nvhost_client_device_suspend(dev); +} + +static int dsi_resume(struct nvhost_device *dev) +{ + dev_info(&dev->dev, "resuming\n"); + return 0; +} + +struct nvhost_device *dsi_device; + +static struct nvhost_driver dsi_driver = { + .probe = dsi_probe, + .remove = __exit_p(dsi_remove), +#ifdef CONFIG_PM + .suspend = dsi_suspend, + .resume = dsi_resume, +#endif + .driver = { + .owner = THIS_MODULE, + .name = "dsi", + } +}; + +static int __init dsi_init(void) +{ + int err; + + dsi_device = nvhost_get_device("dsi"); + if (!dsi_device) + return -ENXIO; + + err = nvhost_device_register(dsi_device); + if (err) + return err; + + return nvhost_driver_register(&dsi_driver); +} + +static void __exit dsi_exit(void) +{ + nvhost_driver_unregister(&dsi_driver); +} + +module_init(dsi_init); +module_exit(dsi_exit); diff --git a/drivers/video/tegra/host/gr2d/Makefile b/drivers/video/tegra/host/gr2d/Makefile new file mode 100644 index 000000000000..a79a2101677b --- /dev/null +++ b/drivers/video/tegra/host/gr2d/Makefile @@ -0,0 +1,7 @@ +GCOV_PROFILE := y +EXTRA_CFLAGS += -Idrivers/video/tegra/host + +nvhost-gr2d-objs = \ + gr2d.o + +obj-$(CONFIG_TEGRA_GRHOST) += nvhost-gr2d.o diff --git a/drivers/video/tegra/host/gr2d/gr2d.c b/drivers/video/tegra/host/gr2d/gr2d.c new file mode 100644 index 000000000000..f88eb72e0a40 --- /dev/null +++ b/drivers/video/tegra/host/gr2d/gr2d.c @@ -0,0 +1,82 @@ +/* + * drivers/video/tegra/host/gr2d/gr2d.c + * + * Tegra Graphics 2D + * + * Copyright (c) 2012, NVIDIA Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>. + */ + +#include "dev.h" +#include "bus_client.h" + +static int __devinit gr2d_probe(struct nvhost_device *dev) +{ + return nvhost_client_device_init(dev); +} + +static int __exit gr2d_remove(struct nvhost_device *dev) +{ + /* Add clean-up */ + return 0; +} + +static int gr2d_suspend(struct nvhost_device *dev, pm_message_t state) +{ + return nvhost_client_device_suspend(dev); +} + +static int gr2d_resume(struct nvhost_device *dev) +{ + dev_info(&dev->dev, "resuming\n"); + return 0; +} + +struct nvhost_device *gr2d_device; + +static struct nvhost_driver gr2d_driver = { + .probe = gr2d_probe, + .remove = __exit_p(gr2d_remove), +#ifdef CONFIG_PM + .suspend = gr2d_suspend, + .resume = gr2d_resume, +#endif + .driver = { + .owner = THIS_MODULE, + .name = "gr2d", + } +}; + +static int __init gr2d_init(void) +{ + int err; + + gr2d_device = nvhost_get_device("gr2d"); + if (!gr2d_device) + return -ENXIO; + + err = nvhost_device_register(gr2d_device); + if (err) + return err; + + return nvhost_driver_register(&gr2d_driver); +} + +static void __exit gr2d_exit(void) +{ + nvhost_driver_unregister(&gr2d_driver); +} + +module_init(gr2d_init); +module_exit(gr2d_exit); diff --git a/drivers/video/tegra/host/gr3d/gr3d.c b/drivers/video/tegra/host/gr3d/gr3d.c index 2dca9ef0b254..f387d54e585e 100644 --- a/drivers/video/tegra/host/gr3d/gr3d.c +++ b/drivers/video/tegra/host/gr3d/gr3d.c @@ -18,10 +18,9 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -/*** restore ***/ - #include <mach/nvmap.h> #include <linux/slab.h> + #include "t20/t20.h" #include "host1x/host1x_channel.h" #include "host1x/host1x_hardware.h" @@ -29,6 +28,11 @@ #include "nvhost_hwctx.h" #include "dev.h" #include "gr3d.h" +#include "bus_client.h" + +#ifndef TEGRA_POWERGATE_3D1 +#define TEGRA_POWERGATE_3D1 -1 +#endif void nvhost_3dctx_restore_begin(struct host1x_hwctx_handler *p, u32 *ptr) { @@ -145,3 +149,63 @@ int nvhost_gr3d_prepare_power_off(struct nvhost_device *dev) { return host1x_save_context(dev, NVSYNCPT_3D); } + +static int __devinit gr3d_probe(struct nvhost_device *dev) +{ + return nvhost_client_device_init(dev); +} + +static int __exit gr3d_remove(struct nvhost_device *dev) +{ + /* Add clean-up */ + return 0; +} + +static int gr3d_suspend(struct nvhost_device *dev, pm_message_t state) +{ + return nvhost_client_device_suspend(dev); +} + +static int gr3d_resume(struct nvhost_device *dev) +{ + dev_info(&dev->dev, "resuming\n"); + return 0; +} + +struct nvhost_device *gr3d_device; + +static struct nvhost_driver gr3d_driver = { + .probe = gr3d_probe, + .remove = __exit_p(gr3d_remove), +#ifdef CONFIG_PM + .suspend = gr3d_suspend, + .resume = gr3d_resume, +#endif + .driver = { + .owner = THIS_MODULE, + .name = "gr3d", + } +}; + +static int __init gr3d_init(void) +{ + int err; + + gr3d_device = nvhost_get_device("gr3d"); + if (!gr3d_device) + return -ENXIO; + + err = nvhost_device_register(gr3d_device); + if (err) + return err; + + return nvhost_driver_register(&gr3d_driver); +} + +static void __exit gr3d_exit(void) +{ + nvhost_driver_unregister(&gr3d_driver); +} + +module_init(gr3d_init); +module_exit(gr3d_exit); diff --git a/drivers/video/tegra/host/host1x/host1x_cdma.c b/drivers/video/tegra/host/host1x/host1x_cdma.c index 064368ad4760..cdd6026718b1 100644 --- a/drivers/video/tegra/host/host1x/host1x_cdma.c +++ b/drivers/video/tegra/host/host1x/host1x_cdma.c @@ -19,7 +19,6 @@ */ #include <linux/slab.h> -#include <linux/platform_device.h> #include "nvhost_cdma.h" #include "dev.h" diff --git a/drivers/video/tegra/host/host1x/host1x_syncpt.c b/drivers/video/tegra/host/host1x/host1x_syncpt.c index e031227b4491..14ee3c0bd663 100644 --- a/drivers/video/tegra/host/host1x/host1x_syncpt.c +++ b/drivers/video/tegra/host/host1x/host1x_syncpt.c @@ -19,7 +19,6 @@ */ #include <linux/nvhost_ioctl.h> -#include <linux/platform_device.h> #include "nvhost_syncpt.h" #include "dev.h" #include "host1x_syncpt.h" diff --git a/drivers/video/tegra/host/isp/Makefile b/drivers/video/tegra/host/isp/Makefile new file mode 100644 index 000000000000..7bcdc33c83dc --- /dev/null +++ b/drivers/video/tegra/host/isp/Makefile @@ -0,0 +1,7 @@ +GCOV_PROFILE := y +EXTRA_CFLAGS += -Idrivers/video/tegra/host + +nvhost-isp-objs = \ + isp.o + +obj-$(CONFIG_TEGRA_GRHOST) += nvhost-isp.o diff --git a/drivers/video/tegra/host/isp/isp.c b/drivers/video/tegra/host/isp/isp.c new file mode 100644 index 000000000000..f39dc644b275 --- /dev/null +++ b/drivers/video/tegra/host/isp/isp.c @@ -0,0 +1,82 @@ +/* + * drivers/video/tegra/host/isp/isp.c + * + * Tegra Graphics ISP + * + * Copyright (c) 2012, NVIDIA Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>. + */ + +#include "dev.h" +#include "bus_client.h" + +static int __devinit isp_probe(struct nvhost_device *dev) +{ + return nvhost_client_device_init(dev); +} + +static int __exit isp_remove(struct nvhost_device *dev) +{ + /* Add clean-up */ + return 0; +} + +static int isp_suspend(struct nvhost_device *dev, pm_message_t state) +{ + return nvhost_client_device_suspend(dev); +} + +static int isp_resume(struct nvhost_device *dev) +{ + dev_info(&dev->dev, "resuming\n"); + return 0; +} + +struct nvhost_device *isp_device; + +static struct nvhost_driver isp_driver = { + .probe = isp_probe, + .remove = __exit_p(isp_remove), +#ifdef CONFIG_PM + .suspend = isp_suspend, + .resume = isp_resume, +#endif + .driver = { + .owner = THIS_MODULE, + .name = "isp", + } +}; + +static int __init isp_init(void) +{ + int err; + + isp_device = nvhost_get_device("isp"); + if (!isp_device) + return -ENXIO; + + err = nvhost_device_register(isp_device); + if (err) + return err; + + return nvhost_driver_register(&isp_driver); +} + +static void __exit isp_exit(void) +{ + nvhost_driver_unregister(&isp_driver); +} + +module_init(isp_init); +module_exit(isp_exit); diff --git a/drivers/video/tegra/host/mpe/mpe.c b/drivers/video/tegra/host/mpe/mpe.c index e1fef69e0011..28002aa637a7 100644 --- a/drivers/video/tegra/host/mpe/mpe.c +++ b/drivers/video/tegra/host/mpe/mpe.c @@ -26,6 +26,7 @@ #include "host1x/host1x_hwctx.h" #include "t20/t20.h" #include <linux/slab.h> +#include "bus_client.h" enum { HWCTX_REGINFO_NORMAL = 0, @@ -575,3 +576,63 @@ int nvhost_mpe_prepare_power_off(struct nvhost_device *dev) { return host1x_save_context(dev, NVSYNCPT_MPE); } + +static int __devinit mpe_probe(struct nvhost_device *dev) +{ + return nvhost_client_device_init(dev); +} + +static int __exit mpe_remove(struct nvhost_device *dev) +{ + /* Add clean-up */ + return 0; +} + +static int mpe_suspend(struct nvhost_device *dev, pm_message_t state) +{ + return nvhost_client_device_suspend(dev); +} + +static int mpe_resume(struct nvhost_device *dev) +{ + dev_info(&dev->dev, "resuming\n"); + return 0; +} + +struct nvhost_device *mpe_device; + +static struct nvhost_driver mpe_driver = { + .probe = mpe_probe, + .remove = __exit_p(mpe_remove), +#ifdef CONFIG_PM + .suspend = mpe_suspend, + .resume = mpe_resume, +#endif + .driver = { + .owner = THIS_MODULE, + .name = "mpe", + } +}; + +static int __init mpe_init(void) +{ + int err; + + mpe_device = nvhost_get_device("mpe"); + if (!mpe_device) + return -ENXIO; + + err = nvhost_device_register(mpe_device); + if (err) + return err; + + return nvhost_driver_register(&mpe_driver); +} + +static void __exit mpe_exit(void) +{ + nvhost_driver_unregister(&mpe_driver); +} + +module_init(mpe_init); +module_exit(mpe_exit); diff --git a/drivers/video/tegra/host/t20/t20.c b/drivers/video/tegra/host/t20/t20.c index 227e2b77469e..24ddedc842e4 100644 --- a/drivers/video/tegra/host/t20/t20.c +++ b/drivers/video/tegra/host/t20/t20.c @@ -31,113 +31,122 @@ #include "mpe/mpe.h" #include "nvhost_hwctx.h" -#define NVMODMUTEX_2D_FULL (1) -#define NVMODMUTEX_2D_SIMPLE (2) -#define NVMODMUTEX_2D_SB_A (3) -#define NVMODMUTEX_2D_SB_B (4) -#define NVMODMUTEX_3D (5) -#define NVMODMUTEX_DISPLAYA (6) -#define NVMODMUTEX_DISPLAYB (7) -#define NVMODMUTEX_VI (8) -#define NVMODMUTEX_DSI (9) - -#define NVHOST_NUMCHANNELS (NV_HOST1X_CHANNELS - 1) - -struct nvhost_device devices[] = { +#define NVMODMUTEX_2D_FULL (1) +#define NVMODMUTEX_2D_SIMPLE (2) +#define NVMODMUTEX_2D_SB_A (3) +#define NVMODMUTEX_2D_SB_B (4) +#define NVMODMUTEX_3D (5) +#define NVMODMUTEX_DISPLAYA (6) +#define NVMODMUTEX_DISPLAYB (7) +#define NVMODMUTEX_VI (8) +#define NVMODMUTEX_DSI (9) + +#define NVHOST_NUMCHANNELS (NV_HOST1X_CHANNELS - 1) + +struct nvhost_device t20_devices[] = { { /* channel 0 */ - .name = "display", - .id = -1, - .syncpts = BIT(NVSYNCPT_DISP0_A) | BIT(NVSYNCPT_DISP1_A) | - BIT(NVSYNCPT_DISP0_B) | BIT(NVSYNCPT_DISP1_B) | - BIT(NVSYNCPT_DISP0_C) | BIT(NVSYNCPT_DISP1_C) | - BIT(NVSYNCPT_VBLANK0) | BIT(NVSYNCPT_VBLANK1), - .modulemutexes = BIT(NVMODMUTEX_DISPLAYA) | BIT(NVMODMUTEX_DISPLAYB), + .name = "display", + .id = -1, + .index = 0, + .syncpts = BIT(NVSYNCPT_DISP0_A) | BIT(NVSYNCPT_DISP1_A) | + BIT(NVSYNCPT_DISP0_B) | BIT(NVSYNCPT_DISP1_B) | + BIT(NVSYNCPT_DISP0_C) | BIT(NVSYNCPT_DISP1_C) | + BIT(NVSYNCPT_VBLANK0) | BIT(NVSYNCPT_VBLANK1), + .modulemutexes = BIT(NVMODMUTEX_DISPLAYA) | BIT(NVMODMUTEX_DISPLAYB), NVHOST_MODULE_NO_POWERGATE_IDS, NVHOST_DEFAULT_CLOCKGATE_DELAY, - .moduleid = NVHOST_MODULE_NONE, + .moduleid = NVHOST_MODULE_NONE, }, { /* channel 1 */ - .name = "gr3d", - .id = -1, - .syncpts = BIT(NVSYNCPT_3D), - .waitbases = BIT(NVWAITBASE_3D), - .modulemutexes = BIT(NVMODMUTEX_3D), - .class = NV_GRAPHICS_3D_CLASS_ID, + .name = "gr3d", + .id = -1, + .index = 1, + .syncpts = BIT(NVSYNCPT_3D), + .waitbases = BIT(NVWAITBASE_3D), + .modulemutexes = BIT(NVMODMUTEX_3D), + .class = NV_GRAPHICS_3D_CLASS_ID, .prepare_poweroff = nvhost_gr3d_prepare_power_off, .alloc_hwctx_handler = nvhost_gr3d_t20_ctxhandler_init, - .clocks = {{"gr3d", UINT_MAX}, {"emc", UINT_MAX}, {} }, - .powergate_ids = {TEGRA_POWERGATE_3D, -1}, + .clocks = {{"gr3d", UINT_MAX}, {"emc", UINT_MAX}, {} }, + .powergate_ids = {TEGRA_POWERGATE_3D, -1}, NVHOST_DEFAULT_CLOCKGATE_DELAY, - .moduleid = NVHOST_MODULE_NONE, + .moduleid = NVHOST_MODULE_NONE, }, { /* channel 2 */ - .name = "gr2d", - .id = -1, - .syncpts = BIT(NVSYNCPT_2D_0) | BIT(NVSYNCPT_2D_1), - .waitbases = BIT(NVWAITBASE_2D_0) | BIT(NVWAITBASE_2D_1), - .modulemutexes = BIT(NVMODMUTEX_2D_FULL) | BIT(NVMODMUTEX_2D_SIMPLE) | - BIT(NVMODMUTEX_2D_SB_A) | BIT(NVMODMUTEX_2D_SB_B), - .clocks = {{"gr2d", UINT_MAX} , - {"epp", UINT_MAX} , - {"emc", UINT_MAX} }, + .name = "gr2d", + .id = -1, + .index = 2, + .syncpts = BIT(NVSYNCPT_2D_0) | BIT(NVSYNCPT_2D_1), + .waitbases = BIT(NVWAITBASE_2D_0) | BIT(NVWAITBASE_2D_1), + .modulemutexes = BIT(NVMODMUTEX_2D_FULL) | BIT(NVMODMUTEX_2D_SIMPLE) | + BIT(NVMODMUTEX_2D_SB_A) | BIT(NVMODMUTEX_2D_SB_B), + .clocks = { {"gr2d", UINT_MAX}, + {"epp", UINT_MAX}, + {"emc", UINT_MAX} }, NVHOST_MODULE_NO_POWERGATE_IDS, .clockgate_delay = 0, - .moduleid = NVHOST_MODULE_NONE, + .moduleid = NVHOST_MODULE_NONE, }, { /* channel 3 */ - .name = "isp", - .id = -1, - .syncpts = 0, + .name = "isp", + .id = -1, + .index = 3, + .syncpts = 0, NVHOST_MODULE_NO_POWERGATE_IDS, NVHOST_DEFAULT_CLOCKGATE_DELAY, - .moduleid = NVHOST_MODULE_ISP, + .moduleid = NVHOST_MODULE_ISP, }, { /* channel 4 */ - .name = "vi", - .id = -1, - .syncpts = BIT(NVSYNCPT_CSI_VI_0) | BIT(NVSYNCPT_CSI_VI_1) | - BIT(NVSYNCPT_VI_ISP_0) | BIT(NVSYNCPT_VI_ISP_1) | - BIT(NVSYNCPT_VI_ISP_2) | BIT(NVSYNCPT_VI_ISP_3) | - BIT(NVSYNCPT_VI_ISP_4), - .modulemutexes = BIT(NVMODMUTEX_VI), - .exclusive = true, + .name = "vi", + .id = -1, + .index = 4, + .syncpts = BIT(NVSYNCPT_CSI_VI_0) | BIT(NVSYNCPT_CSI_VI_1) | + BIT(NVSYNCPT_VI_ISP_0) | BIT(NVSYNCPT_VI_ISP_1) | + BIT(NVSYNCPT_VI_ISP_2) | BIT(NVSYNCPT_VI_ISP_3) | + BIT(NVSYNCPT_VI_ISP_4), + .modulemutexes = BIT(NVMODMUTEX_VI), + .exclusive = true, NVHOST_MODULE_NO_POWERGATE_IDS, NVHOST_DEFAULT_CLOCKGATE_DELAY, - .moduleid = NVHOST_MODULE_VI, + .moduleid = NVHOST_MODULE_VI, }, { /* channel 5 */ - .name = "mpe", - .id = -1, - .syncpts = BIT(NVSYNCPT_MPE) | BIT(NVSYNCPT_MPE_EBM_EOF) | - BIT(NVSYNCPT_MPE_WR_SAFE), - .waitbases = BIT(NVWAITBASE_MPE), - .class = NV_VIDEO_ENCODE_MPEG_CLASS_ID, - .waitbasesync = true, - .keepalive = true, + .name = "mpe", + .id = -1, + .index = 5, + .syncpts = BIT(NVSYNCPT_MPE) | BIT(NVSYNCPT_MPE_EBM_EOF) | + BIT(NVSYNCPT_MPE_WR_SAFE), + .waitbases = BIT(NVWAITBASE_MPE), + .class = NV_VIDEO_ENCODE_MPEG_CLASS_ID, + .waitbasesync = true, + .keepalive = true, .prepare_poweroff = nvhost_mpe_prepare_power_off, .alloc_hwctx_handler = nvhost_mpe_ctxhandler_init, - .clocks = {{"mpe", UINT_MAX}, {"emc", UINT_MAX}, {} }, - .powergate_ids = {TEGRA_POWERGATE_MPE, -1}, + .clocks = { {"mpe", UINT_MAX}, + {"emc", UINT_MAX} }, + .powergate_ids = {TEGRA_POWERGATE_MPE, -1}, NVHOST_DEFAULT_CLOCKGATE_DELAY, - .moduleid = NVHOST_MODULE_MPE, + .moduleid = NVHOST_MODULE_MPE, }, { /* channel 6 */ - .name = "dsi", - .id = -1, - .syncpts = BIT(NVSYNCPT_DSI), - .modulemutexes = BIT(NVMODMUTEX_DSI), + .name = "dsi", + .id = -1, + .index = 6, + .syncpts = BIT(NVSYNCPT_DSI), + .modulemutexes = BIT(NVMODMUTEX_DSI), NVHOST_MODULE_NO_POWERGATE_IDS, NVHOST_DEFAULT_CLOCKGATE_DELAY, - .moduleid = NVHOST_MODULE_NONE, + .moduleid = NVHOST_MODULE_NONE, } }; + static inline void __iomem *t20_channel_aperture(void __iomem *p, int ndx) { p += NV_HOST1X_CHANNEL0_BASE; @@ -164,14 +173,12 @@ static inline int t20_nvhost_hwctx_handler_init(struct nvhost_channel *ch) } static int t20_channel_init(struct nvhost_channel *ch, - struct nvhost_master *dev, int index) + struct nvhost_master *dev, int index) { ch->chid = index; - ch->dev = &devices[index]; mutex_init(&ch->reflock); mutex_init(&ch->submitlock); - nvhost_device_register(ch->dev); ch->aperture = t20_channel_aperture(dev->aperture, index); return t20_nvhost_hwctx_handler_init(ch); @@ -188,6 +195,19 @@ int nvhost_init_t20_channel_support(struct nvhost_master *host) return 0; } +struct nvhost_device *t20_get_nvhost_device(struct nvhost_master *host, + char *name) +{ + int i; + + for (i = 0; i < host->nb_channels; i++) { + if (strcmp(t20_devices[i].name, name) == 0) + return &t20_devices[i]; + } + + return NULL; +} + int nvhost_init_t20_support(struct nvhost_master *host) { int err; @@ -208,5 +228,6 @@ int nvhost_init_t20_support(struct nvhost_master *host) err = nvhost_init_t20_intr_support(host); if (err) return err; + host->op.nvhost_dev.get_nvhost_device = t20_get_nvhost_device; return 0; } diff --git a/drivers/video/tegra/host/t30/t30.c b/drivers/video/tegra/host/t30/t30.c index d90b71739fd2..8a8b1f4d9240 100644 --- a/drivers/video/tegra/host/t30/t30.c +++ b/drivers/video/tegra/host/t30/t30.c @@ -33,129 +33,133 @@ #include "host1x/host1x_syncpt.h" #include "chip_support.h" -#define NVMODMUTEX_2D_FULL (1) -#define NVMODMUTEX_2D_SIMPLE (2) -#define NVMODMUTEX_2D_SB_A (3) -#define NVMODMUTEX_2D_SB_B (4) -#define NVMODMUTEX_3D (5) -#define NVMODMUTEX_DISPLAYA (6) -#define NVMODMUTEX_DISPLAYB (7) -#define NVMODMUTEX_VI (8) -#define NVMODMUTEX_DSI (9) - -#ifndef TEGRA_POWERGATE_3D1 -#define TEGRA_POWERGATE_3D1 -1 -#endif - -static struct nvhost_device devices[] = { +#define NVMODMUTEX_2D_FULL (1) +#define NVMODMUTEX_2D_SIMPLE (2) +#define NVMODMUTEX_2D_SB_A (3) +#define NVMODMUTEX_2D_SB_B (4) +#define NVMODMUTEX_3D (5) +#define NVMODMUTEX_DISPLAYA (6) +#define NVMODMUTEX_DISPLAYB (7) +#define NVMODMUTEX_VI (8) +#define NVMODMUTEX_DSI (9) + +#define NVHOST_CHANNEL_BASE 0 + +struct nvhost_device t30_devices[] = { { /* channel 0 */ - .name = "display", - .id = -1, - .syncpts = BIT(NVSYNCPT_DISP0_A) | BIT(NVSYNCPT_DISP1_A) | - BIT(NVSYNCPT_DISP0_B) | BIT(NVSYNCPT_DISP1_B) | - BIT(NVSYNCPT_DISP0_C) | BIT(NVSYNCPT_DISP1_C) | - BIT(NVSYNCPT_VBLANK0) | BIT(NVSYNCPT_VBLANK1), - .modulemutexes = BIT(NVMODMUTEX_DISPLAYA) | BIT(NVMODMUTEX_DISPLAYB), + .name = "display", + .id = -1, + .index = 0, + .syncpts = BIT(NVSYNCPT_DISP0_A) | BIT(NVSYNCPT_DISP1_A) | + BIT(NVSYNCPT_DISP0_B) | BIT(NVSYNCPT_DISP1_B) | + BIT(NVSYNCPT_DISP0_C) | BIT(NVSYNCPT_DISP1_C) | + BIT(NVSYNCPT_VBLANK0) | BIT(NVSYNCPT_VBLANK1), + .modulemutexes = BIT(NVMODMUTEX_DISPLAYA) | BIT(NVMODMUTEX_DISPLAYB), NVHOST_MODULE_NO_POWERGATE_IDS, NVHOST_DEFAULT_CLOCKGATE_DELAY, - .moduleid = NVHOST_MODULE_NONE, + .moduleid = NVHOST_MODULE_NONE, }, { /* channel 1 */ - .name = "gr3d", - .id = -1, - .syncpts = BIT(NVSYNCPT_3D), - .waitbases = BIT(NVWAITBASE_3D), - .modulemutexes = BIT(NVMODMUTEX_3D), - .class = NV_GRAPHICS_3D_CLASS_ID, + .name = "gr3d", + .id = -1, + .index = 1, + .syncpts = BIT(NVSYNCPT_3D), + .waitbases = BIT(NVWAITBASE_3D), + .modulemutexes = BIT(NVMODMUTEX_3D), + .class = NV_GRAPHICS_3D_CLASS_ID, .prepare_poweroff = nvhost_gr3d_prepare_power_off, - .busy = nvhost_scale3d_notify_busy, - .idle = nvhost_scale3d_notify_idle, - .init = nvhost_scale3d_init, - .deinit = nvhost_scale3d_deinit, - .suspend = nvhost_scale3d_suspend, + .busy = nvhost_scale3d_notify_busy, + .idle = nvhost_scale3d_notify_idle, + .init = nvhost_scale3d_init, + .deinit = nvhost_scale3d_deinit, + .suspend = nvhost_scale3d_suspend, .alloc_hwctx_handler = nvhost_gr3d_t30_ctxhandler_init, - .clocks = {{"gr3d", UINT_MAX}, - {"gr3d2", UINT_MAX}, - {"emc", UINT_MAX} }, - .powergate_ids = {TEGRA_POWERGATE_3D, - TEGRA_POWERGATE_3D1}, + .clocks = { {"gr3d", UINT_MAX}, + {"gr3d2", UINT_MAX}, + {"emc", UINT_MAX} }, + .powergate_ids = { TEGRA_POWERGATE_3D, + TEGRA_POWERGATE_3D1 }, NVHOST_DEFAULT_CLOCKGATE_DELAY, .can_powergate = false, .powergate_delay = 250, - .moduleid = NVHOST_MODULE_NONE, + .moduleid = NVHOST_MODULE_NONE, }, { /* channel 2 */ - .name = "gr2d", - .id = -1, - .syncpts = BIT(NVSYNCPT_2D_0) | BIT(NVSYNCPT_2D_1), - .waitbases = BIT(NVWAITBASE_2D_0) | BIT(NVWAITBASE_2D_1), - .modulemutexes = BIT(NVMODMUTEX_2D_FULL) | BIT(NVMODMUTEX_2D_SIMPLE) | - BIT(NVMODMUTEX_2D_SB_A) | BIT(NVMODMUTEX_2D_SB_B), - .clocks = {{"gr2d", 0}, - {"epp", 0}, - {"emc", 300000000} }, + .name = "gr2d", + .id = -1, + .index = 2, + .syncpts = BIT(NVSYNCPT_2D_0) | BIT(NVSYNCPT_2D_1), + .waitbases = BIT(NVWAITBASE_2D_0) | BIT(NVWAITBASE_2D_1), + .modulemutexes = BIT(NVMODMUTEX_2D_FULL) | BIT(NVMODMUTEX_2D_SIMPLE) | + BIT(NVMODMUTEX_2D_SB_A) | BIT(NVMODMUTEX_2D_SB_B), + .clocks = { {"gr2d", 0}, + {"epp", 0}, + {"emc", 300000000} }, NVHOST_MODULE_NO_POWERGATE_IDS, .clockgate_delay = 0, - .moduleid = NVHOST_MODULE_NONE, + .moduleid = NVHOST_MODULE_NONE, }, { /* channel 3 */ - .name = "isp", - .id = -1, - .syncpts = 0, + .name = "isp", + .id = -1, + .index = 3, + .syncpts = 0, NVHOST_MODULE_NO_POWERGATE_IDS, NVHOST_DEFAULT_CLOCKGATE_DELAY, - .moduleid = NVHOST_MODULE_ISP, + .moduleid = NVHOST_MODULE_ISP, }, { /* channel 4 */ - .name = "vi", - .id = -1, - .syncpts = BIT(NVSYNCPT_CSI_VI_0) | BIT(NVSYNCPT_CSI_VI_1) | - BIT(NVSYNCPT_VI_ISP_0) | BIT(NVSYNCPT_VI_ISP_1) | - BIT(NVSYNCPT_VI_ISP_2) | BIT(NVSYNCPT_VI_ISP_3) | - BIT(NVSYNCPT_VI_ISP_4), - .modulemutexes = BIT(NVMODMUTEX_VI), - .exclusive = true, + .name = "vi", + .id = -1, + .index = 4, + .syncpts = BIT(NVSYNCPT_CSI_VI_0) | BIT(NVSYNCPT_CSI_VI_1) | + BIT(NVSYNCPT_VI_ISP_0) | BIT(NVSYNCPT_VI_ISP_1) | + BIT(NVSYNCPT_VI_ISP_2) | BIT(NVSYNCPT_VI_ISP_3) | + BIT(NVSYNCPT_VI_ISP_4), + .modulemutexes = BIT(NVMODMUTEX_VI), + .exclusive = true, NVHOST_MODULE_NO_POWERGATE_IDS, NVHOST_DEFAULT_CLOCKGATE_DELAY, - .moduleid = NVHOST_MODULE_VI, + .moduleid = NVHOST_MODULE_VI, }, { /* channel 5 */ - .name = "mpe", - .id = -1, - .syncpts = BIT(NVSYNCPT_MPE) | BIT(NVSYNCPT_MPE_EBM_EOF) | - BIT(NVSYNCPT_MPE_WR_SAFE), - .waitbases = BIT(NVWAITBASE_MPE), - .class = NV_VIDEO_ENCODE_MPEG_CLASS_ID, - .waitbasesync = true, - .keepalive = true, + .name = "mpe", + .id = -1, + .index = 5, + .syncpts = BIT(NVSYNCPT_MPE) | BIT(NVSYNCPT_MPE_EBM_EOF) | + BIT(NVSYNCPT_MPE_WR_SAFE), + .waitbases = BIT(NVWAITBASE_MPE), + .class = NV_VIDEO_ENCODE_MPEG_CLASS_ID, + .waitbasesync = true, + .keepalive = true, .prepare_poweroff = nvhost_mpe_prepare_power_off, .alloc_hwctx_handler = nvhost_mpe_ctxhandler_init, - .clocks = {{"mpe", UINT_MAX}, {"emc", UINT_MAX}, {} }, - .powergate_ids = {TEGRA_POWERGATE_MPE, -1}, + .clocks = { {"mpe", UINT_MAX}, + {"emc", UINT_MAX} }, + .powergate_ids = {TEGRA_POWERGATE_MPE, -1}, NVHOST_DEFAULT_CLOCKGATE_DELAY, - .can_powergate = true, + .can_powergate = true, .powergate_delay = 100, - .moduleid = NVHOST_MODULE_MPE, + .moduleid = NVHOST_MODULE_MPE, }, { /* channel 6 */ - .name = "dsi", - .id = -1, - .syncpts = BIT(NVSYNCPT_DSI), - .modulemutexes = BIT(NVMODMUTEX_DSI), + .name = "dsi", + .id = -1, + .index = 6, + .syncpts = BIT(NVSYNCPT_DSI), + .modulemutexes = BIT(NVMODMUTEX_DSI), NVHOST_MODULE_NO_POWERGATE_IDS, NVHOST_DEFAULT_CLOCKGATE_DELAY, - .moduleid = NVHOST_MODULE_NONE, + .moduleid = NVHOST_MODULE_NONE, } }; -#define NVHOST_CHANNEL_BASE 0 - static inline int t30_nvhost_hwctx_handler_init(struct nvhost_channel *ch) { int err = 0; @@ -186,11 +190,9 @@ static int t30_channel_init(struct nvhost_channel *ch, struct nvhost_master *dev, int index) { ch->chid = index; - ch->dev = &devices[index]; mutex_init(&ch->reflock); mutex_init(&ch->submitlock); - nvhost_device_register(ch->dev); ch->aperture = t30_channel_aperture(dev->aperture, index); return t30_nvhost_hwctx_handler_init(ch); @@ -211,6 +213,19 @@ int nvhost_init_t30_debug_support(struct nvhost_master *host) return 0; } +struct nvhost_device *t30_get_nvhost_device(struct nvhost_master *host, + char *name) +{ + int i; + + for (i = 0; i < host->nb_channels; i++) { + if (strcmp(t30_devices[i].name, name) == 0) + return &t30_devices[i]; + } + + return NULL; +} + int nvhost_init_t30_support(struct nvhost_master *host) { int err; @@ -231,5 +246,6 @@ int nvhost_init_t30_support(struct nvhost_master *host) err = nvhost_init_t20_intr_support(host); if (err) return err; + host->op.nvhost_dev.get_nvhost_device = t30_get_nvhost_device; return 0; } diff --git a/drivers/video/tegra/host/vi/Makefile b/drivers/video/tegra/host/vi/Makefile new file mode 100644 index 000000000000..8c130e49814d --- /dev/null +++ b/drivers/video/tegra/host/vi/Makefile @@ -0,0 +1,7 @@ +GCOV_PROFILE := y +EXTRA_CFLAGS += -Idrivers/video/tegra/host + +nvhost-vi-objs = \ + vi.o + +obj-$(CONFIG_TEGRA_GRHOST) += nvhost-vi.o diff --git a/drivers/video/tegra/host/vi/vi.c b/drivers/video/tegra/host/vi/vi.c new file mode 100644 index 000000000000..71d517152ade --- /dev/null +++ b/drivers/video/tegra/host/vi/vi.c @@ -0,0 +1,82 @@ +/* + * drivers/video/tegra/host/vi/vi.c + * + * Tegra Graphics Host VI + * + * Copyright (c) 2012, NVIDIA Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>. + */ + +#include "dev.h" +#include "bus_client.h" + +static int __devinit vi_probe(struct nvhost_device *dev) +{ + return nvhost_client_device_init(dev); +} + +static int __exit vi_remove(struct nvhost_device *dev) +{ + /* Add clean-up */ + return 0; +} + +static int vi_suspend(struct nvhost_device *dev, pm_message_t state) +{ + return nvhost_client_device_suspend(dev); +} + +static int vi_resume(struct nvhost_device *dev) +{ + dev_info(&dev->dev, "resuming\n"); + return 0; +} + +struct nvhost_device *vi_device; + +static struct nvhost_driver vi_driver = { + .probe = vi_probe, + .remove = __exit_p(vi_remove), +#ifdef CONFIG_PM + .suspend = vi_suspend, + .resume = vi_resume, +#endif + .driver = { + .owner = THIS_MODULE, + .name = "vi", + } +}; + +static int __init vi_init(void) +{ + int err; + + vi_device = nvhost_get_device("vi"); + if (!vi_device) + return -ENXIO; + + err = nvhost_device_register(vi_device); + if (err) + return err; + + return nvhost_driver_register(&vi_driver); +} + +static void __exit vi_exit(void) +{ + nvhost_driver_unregister(&vi_driver); +} + +module_init(vi_init); +module_exit(vi_exit); diff --git a/include/linux/nvhost.h b/include/linux/nvhost.h index bc1d9d76b9a3..da5e1e6862c6 100644 --- a/include/linux/nvhost.h +++ b/include/linux/nvhost.h @@ -49,6 +49,7 @@ struct nvhost_device { const char *name; /* Device name */ struct device dev; /* Linux device struct */ int id; /* Separates clients of same hw */ + int index; /* Hardware channel number */ u32 num_resources; /* Number of resources following */ struct resource *resource; /* Resources (IOMEM in particular) */ struct resource *reg_mem; |