summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMayuresh Kulkarni <mkulkarni@nvidia.com>2012-05-16 13:56:28 +0530
committerRohan Somvanshi <rsomvanshi@nvidia.com>2012-05-23 02:18:46 -0700
commit5c9ca407ae6056150948b6c3fc5a166af2a3036f (patch)
tree70a717dbe306f8737ddb69c0c8946dd149bb87ba
parentcf6d5a8c90cba0b7b4e57aaccff01f0e47e2d878 (diff)
video: tegra: host: move function pointers to nvhost_driver
- currently, function pointers are inside nvhost_device - these functions abstract the device specific implementation of a functionality per SoC - move them to nvhost_driver so that nvhost_device can be instantiated from arch code using board files/device trees - add support to use single driver for multiple devices using concept of id_table. this will be useful in supporting multiple SoC devices binding single driver - also add some notes about how device name is expected Bug 871237 Change-Id: I4c75d7121d26c3bdc50f058e0d144d89ca0edbd9 Signed-off-by: Mayuresh Kulkarni <mkulkarni@nvidia.com> Reviewed-on: http://git-master/r/100985 Reviewed-by: Rohan Somvanshi <rsomvanshi@nvidia.com> Tested-by: Rohan Somvanshi <rsomvanshi@nvidia.com>
-rw-r--r--drivers/media/video/tegra/nvavp/nvavp_dev.c3
-rw-r--r--drivers/video/tegra/dc/dc.c3
-rw-r--r--drivers/video/tegra/host/bus.c39
-rw-r--r--drivers/video/tegra/host/dev.c9
-rw-r--r--drivers/video/tegra/host/dsi/dsi.c3
-rw-r--r--drivers/video/tegra/host/gr2d/gr2d.c3
-rw-r--r--drivers/video/tegra/host/gr3d/gr3d.c82
-rw-r--r--drivers/video/tegra/host/host1x/host1x_channel.c10
-rw-r--r--drivers/video/tegra/host/isp/isp.c3
-rw-r--r--drivers/video/tegra/host/mpe/mpe.c53
-rw-r--r--drivers/video/tegra/host/nvhost_acm.c33
-rw-r--r--drivers/video/tegra/host/nvhost_channel.c6
-rw-r--r--drivers/video/tegra/host/t20/t20.c15
-rw-r--r--drivers/video/tegra/host/t30/t30.c20
-rw-r--r--drivers/video/tegra/host/vi/vi.c3
-rw-r--r--include/linux/nvhost.h61
16 files changed, 257 insertions, 89 deletions
diff --git a/drivers/media/video/tegra/nvavp/nvavp_dev.c b/drivers/media/video/tegra/nvavp/nvavp_dev.c
index 05537be2f522..6e0c3ed9f31b 100644
--- a/drivers/media/video/tegra/nvavp/nvavp_dev.c
+++ b/drivers/media/video/tegra/nvavp/nvavp_dev.c
@@ -1172,7 +1172,8 @@ static const struct file_operations tegra_nvavp_fops = {
.unlocked_ioctl = tegra_nvavp_ioctl,
};
-static int tegra_nvavp_probe(struct nvhost_device *ndev)
+static int tegra_nvavp_probe(struct nvhost_device *ndev,
+ struct nvhost_device_id *id_table)
{
struct nvavp_info *nvavp;
int irq;
diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c
index 7fe9819a335d..fb171549f78d 100644
--- a/drivers/video/tegra/dc/dc.c
+++ b/drivers/video/tegra/dc/dc.c
@@ -2904,7 +2904,8 @@ static ssize_t switch_modeset_print_mode(struct switch_dev *sdev, char *buf)
}
#endif
-static int tegra_dc_probe(struct nvhost_device *ndev)
+static int tegra_dc_probe(struct nvhost_device *ndev,
+ struct nvhost_device_id *id_table)
{
struct tegra_dc *dc;
struct clk *clk;
diff --git a/drivers/video/tegra/host/bus.c b/drivers/video/tegra/host/bus.c
index 12cb7181702d..e59dc4153b14 100644
--- a/drivers/video/tegra/host/bus.c
+++ b/drivers/video/tegra/host/bus.c
@@ -75,12 +75,42 @@ int nvhost_get_irq_byname(struct nvhost_device *dev, const char *name)
}
EXPORT_SYMBOL_GPL(nvhost_get_irq_byname);
+static struct nvhost_device_id *nvhost_bus_match_id(struct nvhost_device *dev,
+ struct nvhost_device_id *id_table)
+{
+ while (id_table->name[0]) {
+ if (strcmp(dev->name, id_table->name) == 0)
+ return id_table;
+ id_table++;
+ }
+ return NULL;
+}
+
+static int nvhost_bus_match(struct device *_dev, struct device_driver *drv)
+{
+ struct nvhost_device *dev = to_nvhost_device(_dev);
+ struct nvhost_driver *ndrv = to_nvhost_driver(drv);
+
+ /* check if driver support multiple devices through id_table */
+ if (ndrv->id_table)
+ return nvhost_bus_match_id(dev, ndrv->id_table) != NULL;
+ else /* driver does not support id_table */
+ return !strncmp(dev->name, drv->name, strlen(drv->name));
+}
+
static int nvhost_drv_probe(struct device *_dev)
{
struct nvhost_driver *drv = to_nvhost_driver(_dev->driver);
struct nvhost_device *dev = to_nvhost_device(_dev);
- return drv->probe(dev);
+ if (drv && drv->probe) {
+ if (drv->id_table)
+ return drv->probe(dev, nvhost_bus_match_id(dev, drv->id_table));
+ else
+ return drv->probe(dev, NULL);
+ }
+ else
+ return -ENODEV;
}
static int nvhost_drv_remove(struct device *_dev)
@@ -197,13 +227,6 @@ void nvhost_device_unregister(struct nvhost_device *dev)
}
EXPORT_SYMBOL_GPL(nvhost_device_unregister);
-static int nvhost_bus_match(struct device *_dev, struct device_driver *drv)
-{
- struct nvhost_device *dev = to_nvhost_device(_dev);
-
- return !strncmp(dev->name, drv->name, strlen(drv->name));
-}
-
#ifdef CONFIG_PM_SLEEP
static int nvhost_legacy_suspend(struct device *dev, pm_message_t mesg)
diff --git a/drivers/video/tegra/host/dev.c b/drivers/video/tegra/host/dev.c
index 77d335f0751e..ca73528fbeeb 100644
--- a/drivers/video/tegra/host/dev.c
+++ b/drivers/video/tegra/host/dev.c
@@ -416,13 +416,12 @@ struct nvhost_device tegra_grhost_device = {
.id = -1,
.resource = nvhost_resources,
.num_resources = ARRAY_SIZE(nvhost_resources),
- .finalize_poweron = power_on_host,
- .prepare_poweroff = power_off_host,
.clocks = {{"host1x", UINT_MAX}, {} },
NVHOST_MODULE_NO_POWERGATE_IDS,
};
-static int __devinit nvhost_probe(struct nvhost_device *dev)
+static int __devinit nvhost_probe(struct nvhost_device *dev,
+ struct nvhost_device_id *id_table)
{
struct nvhost_master *host;
struct resource *regs, *intr0, *intr1;
@@ -546,7 +545,9 @@ static struct nvhost_driver nvhost_driver = {
.driver = {
.owner = THIS_MODULE,
.name = DRIVER_NAME
- }
+ },
+ .finalize_poweron = power_on_host,
+ .prepare_poweroff = power_off_host,
};
static int __init nvhost_mod_init(void)
diff --git a/drivers/video/tegra/host/dsi/dsi.c b/drivers/video/tegra/host/dsi/dsi.c
index 0e49f591574d..87da8a6f1b8a 100644
--- a/drivers/video/tegra/host/dsi/dsi.c
+++ b/drivers/video/tegra/host/dsi/dsi.c
@@ -21,7 +21,8 @@
#include "dev.h"
#include "bus_client.h"
-static int dsi_probe(struct nvhost_device *dev)
+static int dsi_probe(struct nvhost_device *dev,
+ struct nvhost_device_id *id_table)
{
return nvhost_client_device_init(dev);
}
diff --git a/drivers/video/tegra/host/gr2d/gr2d.c b/drivers/video/tegra/host/gr2d/gr2d.c
index f88eb72e0a40..c91a3aa23714 100644
--- a/drivers/video/tegra/host/gr2d/gr2d.c
+++ b/drivers/video/tegra/host/gr2d/gr2d.c
@@ -21,7 +21,8 @@
#include "dev.h"
#include "bus_client.h"
-static int __devinit gr2d_probe(struct nvhost_device *dev)
+static int __devinit gr2d_probe(struct nvhost_device *dev,
+ struct nvhost_device_id *id_table)
{
return nvhost_client_device_init(dev);
}
diff --git a/drivers/video/tegra/host/gr3d/gr3d.c b/drivers/video/tegra/host/gr3d/gr3d.c
index 517cc8383966..b621a47bf650 100644
--- a/drivers/video/tegra/host/gr3d/gr3d.c
+++ b/drivers/video/tegra/host/gr3d/gr3d.c
@@ -28,9 +28,14 @@
#include "nvhost_hwctx.h"
#include "dev.h"
#include "gr3d.h"
+#include "gr3d_t20.h"
+#include "gr3d_t30.h"
+#include "scale3d.h"
#include "bus_client.h"
#include "nvhost_channel.h"
+#include <mach/hardware.h>
+
#ifndef TEGRA_POWERGATE_3D1
#define TEGRA_POWERGATE_3D1 -1
#endif
@@ -69,7 +74,6 @@ void nvhost_3dctx_restore_end(struct host1x_hwctx_handler *p, u32 *ptr)
}
/*** ctx3d ***/
-
struct host1x_hwctx *nvhost_3dctx_alloc_common(struct host1x_hwctx_handler *p,
struct nvhost_channel *ch, bool map_restore)
{
@@ -151,8 +155,75 @@ 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)
+enum gr3d_ip_ver {
+ gr3d_01,
+ gr3d_02,
+};
+
+struct gr3d_desc {
+ void (*finalize_poweron)(struct nvhost_device *dev);
+ void (*busy)(struct nvhost_device *);
+ void (*idle)(struct nvhost_device *);
+ void (*suspend_ndev)(struct nvhost_device *);
+ void (*init)(struct nvhost_device *dev);
+ void (*deinit)(struct nvhost_device *dev);
+ int (*prepare_poweroff)(struct nvhost_device *dev);
+ struct nvhost_hwctx_handler *(*alloc_hwctx_handler)(u32 syncpt,
+ u32 waitbase, struct nvhost_channel *ch);
+};
+
+static const struct gr3d_desc gr3d[] = {
+ [gr3d_01] = {
+ .finalize_poweron = NULL,
+ .busy = NULL,
+ .idle = NULL,
+ .suspend_ndev = NULL,
+ .init = NULL,
+ .deinit = NULL,
+ .prepare_poweroff = nvhost_gr3d_prepare_power_off,
+ .alloc_hwctx_handler = nvhost_gr3d_t20_ctxhandler_init,
+ },
+ [gr3d_02] = {
+ .finalize_poweron = NULL,
+ .busy = nvhost_scale3d_notify_busy,
+ .idle = nvhost_scale3d_notify_idle,
+ .suspend_ndev = nvhost_scale3d_suspend,
+ .init = nvhost_scale3d_init,
+ .deinit = nvhost_scale3d_deinit,
+ .prepare_poweroff = nvhost_gr3d_prepare_power_off,
+ .alloc_hwctx_handler = nvhost_gr3d_t30_ctxhandler_init,
+ },
+};
+
+static struct nvhost_device_id gr3d_id[] = {
+ { "gr3d01", gr3d_01 },
+ { "gr3d02", gr3d_02 },
+ { },
+};
+
+MODULE_DEVICE_TABLE(nvhost, gr3d_id);
+
+static int __devinit gr3d_probe(struct nvhost_device *dev,
+ struct nvhost_device_id *id_table)
{
+ int index = 0;
+ struct nvhost_driver *drv = to_nvhost_driver(dev->dev.driver);
+
+ index = id_table->driver_data;
+
+ drv->finalize_poweron = gr3d[index].finalize_poweron;
+ drv->busy = gr3d[index].busy;
+ drv->idle = gr3d[index].idle;
+ drv->suspend_ndev = gr3d[index].suspend_ndev;
+ drv->init = gr3d[index].init;
+ drv->deinit = gr3d[index].deinit;
+ drv->prepare_poweroff = gr3d[index].prepare_poweroff;
+ drv->alloc_hwctx_handler = gr3d[index].alloc_hwctx_handler;
+
+ /* reset device name so that consistent device name can be
+ * found in clock tree */
+ dev->name = "gr3d";
+
return nvhost_client_device_init(dev);
}
@@ -185,7 +256,8 @@ static struct nvhost_driver gr3d_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "gr3d",
- }
+ },
+ .id_table = gr3d_id,
};
static int __init gr3d_init(void)
@@ -197,8 +269,10 @@ static int __init gr3d_init(void)
return -ENXIO;
err = nvhost_device_register(gr3d_device);
- if (err)
+ if (err) {
+ pr_err("Could not register 3D device\n");
return err;
+ }
return nvhost_driver_register(&gr3d_driver);
}
diff --git a/drivers/video/tegra/host/host1x/host1x_channel.c b/drivers/video/tegra/host/host1x/host1x_channel.c
index 3ebf956b4399..8c4a7a5c74ad 100644
--- a/drivers/video/tegra/host/host1x/host1x_channel.c
+++ b/drivers/video/tegra/host/host1x/host1x_channel.c
@@ -203,6 +203,7 @@ int host1x_channel_submit(struct nvhost_job *job)
u32 syncval;
int err;
void *completed_waiter = NULL, *ctxsave_waiter = NULL;
+ struct nvhost_driver *drv = to_nvhost_driver(ch->dev->dev.driver);
/* Bail out on timed out contexts */
if (job->hwctx && job->hwctx->has_timedout)
@@ -210,8 +211,8 @@ int host1x_channel_submit(struct nvhost_job *job)
/* Turn on the client module and host1x */
nvhost_module_busy(ch->dev);
- if (ch->dev->busy)
- ch->dev->busy(ch->dev);
+ if (drv->busy)
+ drv->busy(ch->dev);
/* before error checks, return current max */
prev_max = job->syncpt_end =
@@ -549,6 +550,7 @@ int host1x_save_context(struct nvhost_device *dev, u32 syncpt_id)
void *ref;
void *ctx_waiter = NULL, *wakeup_waiter = NULL;
struct nvhost_job *job;
+ struct nvhost_driver *drv = to_nvhost_driver(dev->dev.driver);
ctx_waiter = nvhost_intr_alloc_waiter();
wakeup_waiter = nvhost_intr_alloc_waiter();
@@ -557,8 +559,8 @@ int host1x_save_context(struct nvhost_device *dev, u32 syncpt_id)
goto done;
}
- if (dev->busy)
- dev->busy(dev);
+ if (drv->busy)
+ drv->busy(dev);
mutex_lock(&ch->submitlock);
hwctx_to_save = ch->cur_ctx;
diff --git a/drivers/video/tegra/host/isp/isp.c b/drivers/video/tegra/host/isp/isp.c
index 9044d40b8574..ae9d7eb09365 100644
--- a/drivers/video/tegra/host/isp/isp.c
+++ b/drivers/video/tegra/host/isp/isp.c
@@ -25,7 +25,8 @@
#include "dev.h"
#include "bus_client.h"
-static int __devinit isp_probe(struct nvhost_device *dev)
+static int __devinit isp_probe(struct nvhost_device *dev,
+ struct nvhost_device_id *id_table)
{
int err = 0;
diff --git a/drivers/video/tegra/host/mpe/mpe.c b/drivers/video/tegra/host/mpe/mpe.c
index f155183613cd..d8c9da7e9a76 100644
--- a/drivers/video/tegra/host/mpe/mpe.c
+++ b/drivers/video/tegra/host/mpe/mpe.c
@@ -31,6 +31,7 @@
#include <linux/resource.h>
#include <mach/iomap.h>
+#include <mach/hardware.h>
#include "bus_client.h"
@@ -533,9 +534,8 @@ static void ctxmpe_save_service(struct nvhost_hwctx *nctx)
h->syncpt);
}
-struct nvhost_hwctx_handler *nvhost_mpe_ctxhandler_init(
- u32 syncpt, u32 waitbase,
- struct nvhost_channel *ch)
+struct nvhost_hwctx_handler *nvhost_mpe_ctxhandler_init(u32 syncpt,
+ u32 waitbase, struct nvhost_channel *ch)
{
struct nvmap_client *nvmap;
u32 *save_ptr;
@@ -585,9 +585,51 @@ 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)
+enum mpe_ip_ver {
+ mpe_01,
+ mpe_02,
+};
+
+struct mpe_desc {
+ int (*prepare_poweroff)(struct nvhost_device *dev);
+ struct nvhost_hwctx_handler *(*alloc_hwctx_handler)(u32 syncpt,
+ u32 waitbase, struct nvhost_channel *ch);
+};
+
+static const struct mpe_desc mpe[] = {
+ [mpe_01] = {
+ .prepare_poweroff = nvhost_mpe_prepare_power_off,
+ .alloc_hwctx_handler = nvhost_mpe_ctxhandler_init,
+ },
+ [mpe_02] = {
+ .prepare_poweroff = nvhost_mpe_prepare_power_off,
+ .alloc_hwctx_handler = nvhost_mpe_ctxhandler_init,
+ },
+};
+
+static struct nvhost_device_id mpe_id[] = {
+ { "mpe01", mpe_01 },
+ { "mpe02", mpe_02 },
+ { },
+};
+
+MODULE_DEVICE_TABLE(nvhost, mpe_id);
+
+static int __devinit mpe_probe(struct nvhost_device *dev,
+ struct nvhost_device_id *id_table)
{
int err = 0;
+ int index = 0;
+ struct nvhost_driver *drv = to_nvhost_driver(dev->dev.driver);
+
+ index = id_table->driver_data;
+
+ drv->prepare_poweroff = mpe[index].prepare_poweroff;
+ drv->alloc_hwctx_handler = mpe[index].alloc_hwctx_handler;
+
+ /* reset device name so that consistent device name can be
+ * found in clock tree */
+ dev->name = "mpe";
err = nvhost_client_device_get_resources(dev);
if (err)
@@ -632,7 +674,8 @@ static struct nvhost_driver mpe_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "mpe",
- }
+ },
+ .id_table = mpe_id,
};
static int __init mpe_init(void)
diff --git a/drivers/video/tegra/host/nvhost_acm.c b/drivers/video/tegra/host/nvhost_acm.c
index 015b7c4dbf66..6d96bd023d81 100644
--- a/drivers/video/tegra/host/nvhost_acm.c
+++ b/drivers/video/tegra/host/nvhost_acm.c
@@ -120,9 +120,12 @@ static void to_state_clockgated_locked(struct nvhost_device *dev)
static void to_state_running_locked(struct nvhost_device *dev)
{
+ struct nvhost_driver *drv = to_nvhost_driver(dev->dev.driver);
int prev_state = dev->powerstate;
+
if (dev->powerstate == NVHOST_POWER_STATE_POWERGATED)
to_state_clockgated_locked(dev);
+
if (dev->powerstate == NVHOST_POWER_STATE_CLOCKGATED) {
int i;
@@ -135,8 +138,8 @@ static void to_state_running_locked(struct nvhost_device *dev)
}
if (prev_state == NVHOST_POWER_STATE_POWERGATED
- && dev->finalize_poweron)
- dev->finalize_poweron(dev);
+ && drv->finalize_poweron)
+ drv->finalize_poweron(dev);
}
dev->powerstate = NVHOST_POWER_STATE_RUNNING;
}
@@ -148,12 +151,13 @@ static void to_state_running_locked(struct nvhost_device *dev)
static int to_state_powergated_locked(struct nvhost_device *dev)
{
int err = 0;
+ struct nvhost_driver *drv = to_nvhost_driver(dev->dev.driver);
- if (dev->prepare_poweroff
+ if (drv->prepare_poweroff
&& dev->powerstate != NVHOST_POWER_STATE_POWERGATED) {
/* Clock needs to be on in prepare_poweroff */
to_state_running_locked(dev);
- err = dev->prepare_poweroff(dev);
+ err = drv->prepare_poweroff(dev);
if (err)
return err;
}
@@ -185,8 +189,10 @@ static void schedule_clockgating_locked(struct nvhost_device *dev)
void nvhost_module_busy(struct nvhost_device *dev)
{
- if (dev->busy)
- dev->busy(dev);
+ struct nvhost_driver *drv = to_nvhost_driver(dev->dev.driver);
+
+ if (drv->busy)
+ drv->busy(dev);
mutex_lock(&dev->lock);
cancel_delayed_work(&dev->powerstate_down);
@@ -226,6 +232,7 @@ static void powerstate_down_handler(struct work_struct *work)
void nvhost_module_idle_mult(struct nvhost_device *dev, int refs)
{
+ struct nvhost_driver *drv = to_nvhost_driver(dev->dev.driver);
bool kick = false;
mutex_lock(&dev->lock);
@@ -240,8 +247,8 @@ void nvhost_module_idle_mult(struct nvhost_device *dev, int refs)
if (kick) {
wake_up(&dev->idle_wq);
- if (dev->idle)
- dev->idle(dev);
+ if (drv->idle)
+ drv->idle(dev);
}
}
@@ -403,6 +410,7 @@ static int is_module_idle(struct nvhost_device *dev)
int nvhost_module_suspend(struct nvhost_device *dev)
{
int ret;
+ struct nvhost_driver *drv = to_nvhost_driver(dev->dev.driver);
ret = wait_event_timeout(dev->idle_wq, is_module_idle(dev),
ACM_SUSPEND_WAIT_FOR_IDLE_TIMEOUT);
@@ -417,8 +425,8 @@ int nvhost_module_suspend(struct nvhost_device *dev)
to_state_powergated_locked(dev);
mutex_unlock(&dev->lock);
- if (dev->suspend)
- dev->suspend(dev);
+ if (drv->suspend_ndev)
+ drv->suspend_ndev(dev);
return 0;
}
@@ -426,9 +434,10 @@ int nvhost_module_suspend(struct nvhost_device *dev)
void nvhost_module_deinit(struct nvhost_device *dev)
{
int i;
+ struct nvhost_driver *drv = to_nvhost_driver(dev->dev.driver);
- if (dev->deinit)
- dev->deinit(dev);
+ if (drv->deinit)
+ drv->deinit(dev);
nvhost_module_suspend(dev);
for (i = 0; i < dev->num_clks; i++)
diff --git a/drivers/video/tegra/host/nvhost_channel.c b/drivers/video/tegra/host/nvhost_channel.c
index 8b79479bdc1a..ef8886fe4652 100644
--- a/drivers/video/tegra/host/nvhost_channel.c
+++ b/drivers/video/tegra/host/nvhost_channel.c
@@ -64,10 +64,12 @@ int nvhost_channel_submit(struct nvhost_job *job)
struct nvhost_channel *nvhost_getchannel(struct nvhost_channel *ch)
{
int err = 0;
+ struct nvhost_driver *drv = to_nvhost_driver(ch->dev->dev.driver);
+
mutex_lock(&ch->reflock);
if (ch->refcount == 0) {
- if (ch->dev->init)
- ch->dev->init(ch->dev);
+ if (drv->init)
+ drv->init(ch->dev);
err = nvhost_cdma_init(&ch->cdma);
} else if (ch->dev->exclusive) {
err = -EBUSY;
diff --git a/drivers/video/tegra/host/t20/t20.c b/drivers/video/tegra/host/t20/t20.c
index 673a81cd4966..f6713d866f19 100644
--- a/drivers/video/tegra/host/t20/t20.c
+++ b/drivers/video/tegra/host/t20/t20.c
@@ -64,15 +64,13 @@ struct nvhost_device t20_devices[] = {
},
{
/* channel 1 */
- .name = "gr3d",
+ .name = "gr3d01",
.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},
NVHOST_DEFAULT_CLOCKGATE_DELAY,
@@ -121,7 +119,7 @@ struct nvhost_device t20_devices[] = {
},
{
/* channel 5 */
- .name = "mpe",
+ .name = "mpe01",
.id = -1,
.index = 5,
.syncpts = BIT(NVSYNCPT_MPE) | BIT(NVSYNCPT_MPE_EBM_EOF) |
@@ -130,8 +128,6 @@ struct nvhost_device t20_devices[] = {
.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},
@@ -165,9 +161,10 @@ static inline int t20_nvhost_hwctx_handler_init(struct nvhost_channel *ch)
unsigned long waitbases = ch->dev->waitbases;
u32 syncpt = find_first_bit(&syncpts, BITS_PER_LONG);
u32 waitbase = find_first_bit(&waitbases, BITS_PER_LONG);
+ struct nvhost_driver *drv = to_nvhost_driver(ch->dev->dev.driver);
- if (ch->dev->alloc_hwctx_handler) {
- ch->ctxhandler = ch->dev->alloc_hwctx_handler(syncpt,
+ if (drv->alloc_hwctx_handler) {
+ ch->ctxhandler = drv->alloc_hwctx_handler(syncpt,
waitbase, ch);
if (!ch->ctxhandler)
err = -ENOMEM;
@@ -214,7 +211,7 @@ struct nvhost_device *t20_get_nvhost_device(char *name)
int i;
for (i = 0; i < ARRAY_SIZE(t20_devices); i++) {
- if (strcmp(t20_devices[i].name, name) == 0)
+ if (strncmp(t20_devices[i].name, name, strlen(name)) == 0)
return &t20_devices[i];
}
diff --git a/drivers/video/tegra/host/t30/t30.c b/drivers/video/tegra/host/t30/t30.c
index d4113a898882..257ba0849277 100644
--- a/drivers/video/tegra/host/t30/t30.c
+++ b/drivers/video/tegra/host/t30/t30.c
@@ -68,20 +68,13 @@ struct nvhost_device t30_devices[] = {
},
{
/* channel 1 */
- .name = "gr3d",
+ .name = "gr3d02",
.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,
- .alloc_hwctx_handler = nvhost_gr3d_t30_ctxhandler_init,
.clocks = { {"gr3d", UINT_MAX},
{"gr3d2", UINT_MAX},
{"emc", UINT_MAX} },
@@ -136,7 +129,7 @@ struct nvhost_device t30_devices[] = {
},
{
/* channel 5 */
- .name = "mpe",
+ .name = "mpe02",
.id = -1,
.index = 5,
.syncpts = BIT(NVSYNCPT_MPE) | BIT(NVSYNCPT_MPE_EBM_EOF) |
@@ -145,8 +138,6 @@ struct nvhost_device t30_devices[] = {
.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},
@@ -174,9 +165,10 @@ static inline int t30_nvhost_hwctx_handler_init(struct nvhost_channel *ch)
unsigned long waitbases = ch->dev->waitbases;
u32 syncpt = find_first_bit(&syncpts, BITS_PER_LONG);
u32 waitbase = find_first_bit(&waitbases, BITS_PER_LONG);
+ struct nvhost_driver *drv = to_nvhost_driver(ch->dev->dev.driver);
- if (ch->dev->alloc_hwctx_handler) {
- ch->ctxhandler = ch->dev->alloc_hwctx_handler(syncpt,
+ if (drv->alloc_hwctx_handler) {
+ ch->ctxhandler = drv->alloc_hwctx_handler(syncpt,
waitbase, ch);
if (!ch->ctxhandler)
err = -ENOMEM;
@@ -238,7 +230,7 @@ struct nvhost_device *t30_get_nvhost_device(char *name)
int i;
for (i = 0; i < ARRAY_SIZE(t30_devices); i++) {
- if (strcmp(t30_devices[i].name, name) == 0)
+ if (strncmp(t30_devices[i].name, name, strlen(name)) == 0)
return &t30_devices[i];
}
diff --git a/drivers/video/tegra/host/vi/vi.c b/drivers/video/tegra/host/vi/vi.c
index a6f902a1ac7b..3cfc7e32cbc1 100644
--- a/drivers/video/tegra/host/vi/vi.c
+++ b/drivers/video/tegra/host/vi/vi.c
@@ -25,7 +25,8 @@
#include "dev.h"
#include "bus_client.h"
-static int __devinit vi_probe(struct nvhost_device *dev)
+static int __devinit vi_probe(struct nvhost_device *dev,
+ struct nvhost_device_id *id_table)
{
int err = 0;
diff --git a/include/linux/nvhost.h b/include/linux/nvhost.h
index faa183d40d6d..82bb884dfbbd 100644
--- a/include/linux/nvhost.h
+++ b/include/linux/nvhost.h
@@ -32,6 +32,12 @@ struct nvhost_master;
#define NVHOST_MODULE_MAX_POWERGATE_IDS 2
#define NVHOST_MODULE_NO_POWERGATE_IDS .powergate_ids = {-1, -1}
#define NVHOST_DEFAULT_CLOCKGATE_DELAY .clockgate_delay = 25
+#define NVHOST_NAME_SIZE 24
+
+struct nvhost_device_id {
+ char name[NVHOST_NAME_SIZE];
+ unsigned long driver_data;
+};
struct nvhost_clock {
char *name;
@@ -46,7 +52,11 @@ enum nvhost_device_powerstate_t {
};
struct nvhost_device {
- const char *name; /* Device name */
+ /* device name: its format is of type -
+ * <name><ip-version>.<instance>
+ * e.g.: gr3d01 = gr3d ip version 01 used in tegra2
+ * no instance number means hardware supports single instance */
+ const char *name;
struct device dev; /* Linux device struct */
int id; /* Separates clients of same hw */
int index; /* Hardware channel number */
@@ -82,24 +92,6 @@ struct nvhost_device {
struct list_head client_list; /* List of clients and rate requests */
struct nvhost_channel *channel; /* Channel assigned for the module */
-
- /* Allocates a context handler for the device */
- struct nvhost_hwctx_handler *(*alloc_hwctx_handler)(u32 syncpt,
- u32 waitbase, struct nvhost_channel *ch);
- /* Preparing for power off. Used for context save. */
- int (*prepare_poweroff)(struct nvhost_device *dev);
- /* Finalize power on. Can be used for context restore. */
- void (*finalize_poweron)(struct nvhost_device *dev);
- /* Device is busy. */
- void (*busy)(struct nvhost_device *);
- /* Device is idle. */
- void (*idle)(struct nvhost_device *);
- /* Device is going to be suspended */
- void (*suspend)(struct nvhost_device *);
- /* Device is initialized */
- void (*init)(struct nvhost_device *dev);
- /* Device is de-initialized. */
- void (*deinit)(struct nvhost_device *dev);
};
/* Register device to nvhost bus */
@@ -111,12 +103,39 @@ extern void nvhost_device_unregister(struct nvhost_device *);
extern struct bus_type nvhost_bus_type;
struct nvhost_driver {
- int (*probe)(struct nvhost_device *);
+ int (*probe)(struct nvhost_device *, struct nvhost_device_id *);
int (*remove)(struct nvhost_device *);
void (*shutdown)(struct nvhost_device *);
int (*suspend)(struct nvhost_device *, pm_message_t state);
int (*resume)(struct nvhost_device *);
struct device_driver driver;
+
+ struct nvhost_device_id *id_table;
+
+ /* Finalize power on. Can be used for context restore. */
+ void (*finalize_poweron)(struct nvhost_device *dev);
+
+ /* Device is busy. */
+ void (*busy)(struct nvhost_device *);
+
+ /* Device is idle. */
+ void (*idle)(struct nvhost_device *);
+
+ /* Device is going to be suspended */
+ void (*suspend_ndev)(struct nvhost_device *);
+
+ /* Device is initialized */
+ void (*init)(struct nvhost_device *dev);
+
+ /* Device is de-initialized. */
+ void (*deinit)(struct nvhost_device *dev);
+
+ /* Preparing for power off. Used for context save. */
+ int (*prepare_poweroff)(struct nvhost_device *dev);
+
+ /* Allocates a context handler for the device */
+ struct nvhost_hwctx_handler *(*alloc_hwctx_handler)(u32 syncpt,
+ u32 waitbase, struct nvhost_channel *ch);
};
extern int nvhost_driver_register(struct nvhost_driver *);
@@ -128,7 +147,7 @@ extern struct resource *nvhost_get_resource_byname(struct nvhost_device *,
unsigned int, const char *);
extern int nvhost_get_irq_byname(struct nvhost_device *, const char *);
-#define to_nvhost_device(x) container_of((x), struct nvhost_device, dev)
+#define to_nvhost_device(x) container_of((x), struct nvhost_device, dev)
#define to_nvhost_driver(drv) (container_of((drv), struct nvhost_driver, \
driver))