summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMayuresh Kulkarni <mkulkarni@nvidia.com>2012-02-13 20:34:41 +0530
committerRohan Somvanshi <rsomvanshi@nvidia.com>2012-03-21 08:44:15 -0700
commita0f946efbef9caa197ad2048d45722f65618d6c3 (patch)
tree1d92dfe33f44c8119cfe4a141812f6d3b9309926
parent4e1ec69f7c1b5a259d7df0435647e9005f1e033c (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>
-rw-r--r--drivers/video/tegra/host/Makefile10
-rw-r--r--drivers/video/tegra/host/bus_client.c557
-rw-r--r--drivers/video/tegra/host/bus_client.h8
-rw-r--r--drivers/video/tegra/host/chip_support.h5
-rw-r--r--drivers/video/tegra/host/dev.c557
-rw-r--r--drivers/video/tegra/host/dev.h13
-rw-r--r--drivers/video/tegra/host/dsi/Makefile7
-rw-r--r--drivers/video/tegra/host/dsi/dsi.c82
-rw-r--r--drivers/video/tegra/host/gr2d/Makefile7
-rw-r--r--drivers/video/tegra/host/gr2d/gr2d.c82
-rw-r--r--drivers/video/tegra/host/gr3d/gr3d.c68
-rw-r--r--drivers/video/tegra/host/host1x/host1x_cdma.c1
-rw-r--r--drivers/video/tegra/host/host1x/host1x_syncpt.c1
-rw-r--r--drivers/video/tegra/host/isp/Makefile7
-rw-r--r--drivers/video/tegra/host/isp/isp.c82
-rw-r--r--drivers/video/tegra/host/mpe/mpe.c61
-rw-r--r--drivers/video/tegra/host/t20/t20.c165
-rw-r--r--drivers/video/tegra/host/t30/t30.c184
-rw-r--r--drivers/video/tegra/host/vi/Makefile7
-rw-r--r--drivers/video/tegra/host/vi/vi.c82
-rw-r--r--include/linux/nvhost.h1
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;