From 5c9ca407ae6056150948b6c3fc5a166af2a3036f Mon Sep 17 00:00:00 2001 From: Mayuresh Kulkarni Date: Wed, 16 May 2012 13:56:28 +0530 Subject: 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 Reviewed-on: http://git-master/r/100985 Reviewed-by: Rohan Somvanshi Tested-by: Rohan Somvanshi --- drivers/media/video/tegra/nvavp/nvavp_dev.c | 3 +- drivers/video/tegra/dc/dc.c | 3 +- drivers/video/tegra/host/bus.c | 39 ++++++++--- drivers/video/tegra/host/dev.c | 9 +-- drivers/video/tegra/host/dsi/dsi.c | 3 +- drivers/video/tegra/host/gr2d/gr2d.c | 3 +- drivers/video/tegra/host/gr3d/gr3d.c | 82 ++++++++++++++++++++++-- drivers/video/tegra/host/host1x/host1x_channel.c | 10 +-- drivers/video/tegra/host/isp/isp.c | 3 +- drivers/video/tegra/host/mpe/mpe.c | 53 +++++++++++++-- drivers/video/tegra/host/nvhost_acm.c | 33 ++++++---- drivers/video/tegra/host/nvhost_channel.c | 6 +- drivers/video/tegra/host/t20/t20.c | 15 ++--- drivers/video/tegra/host/t30/t30.c | 20 ++---- drivers/video/tegra/host/vi/vi.c | 3 +- include/linux/nvhost.h | 61 ++++++++++++------ 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 + #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 #include +#include #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 - + * . + * 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)) -- cgit v1.2.3