video: tegra: host: move function pointers to nvhost_driver
Mayuresh Kulkarni [Wed, 16 May 2012 08:26:28 +0000 (13:26 +0530)]
- 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>

16 files changed:
drivers/media/video/tegra/nvavp/nvavp_dev.c
drivers/video/tegra/dc/dc.c
drivers/video/tegra/host/bus.c
drivers/video/tegra/host/dev.c
drivers/video/tegra/host/dsi/dsi.c
drivers/video/tegra/host/gr2d/gr2d.c
drivers/video/tegra/host/gr3d/gr3d.c
drivers/video/tegra/host/host1x/host1x_channel.c
drivers/video/tegra/host/isp/isp.c
drivers/video/tegra/host/mpe/mpe.c
drivers/video/tegra/host/nvhost_acm.c
drivers/video/tegra/host/nvhost_channel.c
drivers/video/tegra/host/t20/t20.c
drivers/video/tegra/host/t30/t30.c
drivers/video/tegra/host/vi/vi.c
include/linux/nvhost.h

index 05537be..6e0c3ed 100644 (file)
@@ -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;
index 7fe9819..fb17154 100644 (file)
@@ -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;
index 12cb718..e59dc41 100644 (file)
@@ -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)
index 77d335f..ca73528 100644 (file)
@@ -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)
index 0e49f59..87da8a6 100644 (file)
@@ -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);
 }
index f88eb72..c91a3aa 100644 (file)
@@ -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);
 }
index 517cc83..b621a47 100644 (file)
 #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);
 }
index 3ebf956..8c4a7a5 100644 (file)
@@ -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;
index 9044d40..ae9d7eb 100644 (file)
@@ -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;
 
index f155183..d8c9da7 100644 (file)
@@ -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)
index 015b7c4..6d96bd0 100644 (file)
@@ -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++)
index 8b79479..ef8886f 100644 (file)
@@ -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;
index 673a81c..f6713d8 100644 (file)
@@ -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];
        }
 
index d4113a8..257ba08 100644 (file)
@@ -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];
        }
 
index a6f902a..3cfc7e3 100644 (file)
@@ -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;
 
index faa183d..82bb884 100644 (file)
@@ -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))