From 9774bbe31a0741ad71929156f59afdb2aba4eae5 Mon Sep 17 00:00:00 2001 From: Terje Bergstrom Date: Tue, 22 May 2012 15:23:13 +0300 Subject: video: tegra: host: Register devices in SoC files Move the device structures to the driver source code files. Register all nvhost_device's in one loop which is called from board file. host1x driver code is moved to live under host1x, too. This causes a need to add host to include path of tegradc and nvavp. Bug 982965 Change-Id: If99cf9d1ef6bc24663ee8294c19370429ed04ca7 Signed-off-by: Terje Bergstrom Reviewed-on: http://git-master/r/104076 Reviewed-by: Simone Willett Tested-by: Simone Willett --- arch/arm/mach-tegra/board-aruba-panel.c | 3 +- arch/arm/mach-tegra/board-cardhu-panel.c | 3 +- arch/arm/mach-tegra/board-enterprise-panel.c | 3 +- arch/arm/mach-tegra/board-harmony-panel.c | 3 +- arch/arm/mach-tegra/board-kai-panel.c | 3 +- arch/arm/mach-tegra/board-p1852-panel.c | 3 +- arch/arm/mach-tegra/board-ventana-panel.c | 3 +- arch/arm/mach-tegra/board-whistler-panel.c | 3 +- arch/arm/mach-tegra/devices.h | 1 - arch/arm/mach-tegra/p852/board-p852-panel.c | 3 +- arch/arm/mach-tegra/tegra2_host1x_devices.h | 26 ++ arch/arm/mach-tegra/tegra3_host1x_devices.h | 26 ++ drivers/video/tegra/Makefile | 1 + drivers/video/tegra/host/bus.c | 17 + drivers/video/tegra/host/chip_support.h | 1 - drivers/video/tegra/host/dev.c | 546 +---------------------- drivers/video/tegra/host/dev.h | 45 +- drivers/video/tegra/host/gr2d/gr2d.c | 12 - drivers/video/tegra/host/gr3d/gr3d.c | 22 +- drivers/video/tegra/host/gr3d/gr3d_t20.c | 2 +- drivers/video/tegra/host/host1x/Makefile | 1 + drivers/video/tegra/host/host1x/host1x.c | 563 ++++++++++++++++++++++++ drivers/video/tegra/host/host1x/host1x.h | 63 +++ drivers/video/tegra/host/host1x/host1x_syncpt.c | 2 +- drivers/video/tegra/host/host1x/host1x_syncpt.h | 7 - drivers/video/tegra/host/isp/isp.c | 25 -- drivers/video/tegra/host/mpe/mpe.c | 26 -- drivers/video/tegra/host/t20/t20.c | 112 +++-- drivers/video/tegra/host/t30/t30.c | 123 ++++-- drivers/video/tegra/host/vi/vi.c | 25 -- include/linux/nvhost.h | 3 + 31 files changed, 879 insertions(+), 797 deletions(-) create mode 100644 arch/arm/mach-tegra/tegra2_host1x_devices.h create mode 100644 arch/arm/mach-tegra/tegra3_host1x_devices.h create mode 100644 drivers/video/tegra/host/host1x/host1x.c create mode 100644 drivers/video/tegra/host/host1x/host1x.h diff --git a/arch/arm/mach-tegra/board-aruba-panel.c b/arch/arm/mach-tegra/board-aruba-panel.c index 0e24a4375c99..01ade01a0eb6 100644 --- a/arch/arm/mach-tegra/board-aruba-panel.c +++ b/arch/arm/mach-tegra/board-aruba-panel.c @@ -35,6 +35,7 @@ #include "board.h" #include "devices.h" #include "gpio-names.h" +#include "tegra2_host1x_devices.h" #define aruba_lvds_shutdown TEGRA_GPIO_PB2 #define aruba_bl_enb TEGRA_GPIO_PW1 @@ -228,7 +229,7 @@ int __init aruba_panel_init(void) #endif #ifdef CONFIG_TEGRA_GRHOST - err = nvhost_device_register(&tegra_grhost_device); + err = tegra2_register_host1x_devices(); if (err) return err; #endif diff --git a/arch/arm/mach-tegra/board-cardhu-panel.c b/arch/arm/mach-tegra/board-cardhu-panel.c index 4a5f8548f0dd..2a9e5201061a 100644 --- a/arch/arm/mach-tegra/board-cardhu-panel.c +++ b/arch/arm/mach-tegra/board-cardhu-panel.c @@ -41,6 +41,7 @@ #include "board-cardhu.h" #include "devices.h" #include "gpio-names.h" +#include "tegra3_host1x_devices.h" #define DC_CTRL_MODE TEGRA_DC_OUT_ONE_SHOT_MODE @@ -1385,7 +1386,7 @@ skip_lvds: #endif #ifdef CONFIG_TEGRA_GRHOST - err = nvhost_device_register(&tegra_grhost_device); + err = tegra3_register_host1x_devices(); if (err) return err; #endif diff --git a/arch/arm/mach-tegra/board-enterprise-panel.c b/arch/arm/mach-tegra/board-enterprise-panel.c index 8876c8ebf88e..7043916921d0 100644 --- a/arch/arm/mach-tegra/board-enterprise-panel.c +++ b/arch/arm/mach-tegra/board-enterprise-panel.c @@ -39,6 +39,7 @@ #include "board-enterprise.h" #include "devices.h" #include "gpio-names.h" +#include "tegra3_host1x_devices.h" #define DC_CTRL_MODE TEGRA_DC_OUT_ONE_SHOT_MODE @@ -885,7 +886,7 @@ int __init enterprise_panel_init(void) #endif #ifdef CONFIG_TEGRA_GRHOST - err = nvhost_device_register(&tegra_grhost_device); + err = tegra3_register_host1x_devices(); if (err) return err; #endif diff --git a/arch/arm/mach-tegra/board-harmony-panel.c b/arch/arm/mach-tegra/board-harmony-panel.c index 9c3d296dd8d3..d4cd3f461b66 100644 --- a/arch/arm/mach-tegra/board-harmony-panel.c +++ b/arch/arm/mach-tegra/board-harmony-panel.c @@ -33,6 +33,7 @@ #include "devices.h" #include "gpio-names.h" #include "board.h" +#include "tegra2_host1x_devices.h" #define harmony_bl_enb TEGRA_GPIO_PB5 #define harmony_lvds_shutdown TEGRA_GPIO_PB2 @@ -356,7 +357,7 @@ int __init harmony_panel_init(void) #endif #ifdef CONFIG_TEGRA_GRHOST - err = nvhost_device_register(&tegra_grhost_device); + err = tegra2_register_host1x_devices(); if (err) return err; #endif diff --git a/arch/arm/mach-tegra/board-kai-panel.c b/arch/arm/mach-tegra/board-kai-panel.c index 45333840ffb7..e6ac6dd82846 100644 --- a/arch/arm/mach-tegra/board-kai-panel.c +++ b/arch/arm/mach-tegra/board-kai-panel.c @@ -37,6 +37,7 @@ #include "board-kai.h" #include "devices.h" #include "gpio-names.h" +#include "tegra3_host1x_devices.h" /* kai default display board pins */ #define kai_lvds_avdd_en TEGRA_GPIO_PH6 @@ -681,7 +682,7 @@ int __init kai_panel_init(void) #endif #ifdef CONFIG_TEGRA_GRHOST - err = nvhost_device_register(&tegra_grhost_device); + err = tegra3_register_host1x_devices(); if (err) return err; #endif diff --git a/arch/arm/mach-tegra/board-p1852-panel.c b/arch/arm/mach-tegra/board-p1852-panel.c index c104b913518e..4e86476cdd2c 100644 --- a/arch/arm/mach-tegra/board-p1852-panel.c +++ b/arch/arm/mach-tegra/board-p1852-panel.c @@ -28,6 +28,7 @@ #include "board.h" #include "devices.h" +#include "tegra3_host1x_devices.h" static int p1852_panel_enable(void) { @@ -185,7 +186,7 @@ int __init p1852_panel_init(void) res->end = tegra_fb_start + tegra_fb_size - 1; #ifdef CONFIG_TEGRA_GRHOST - err = nvhost_device_register(&tegra_grhost_device); + err = tegra3_register_host1x_devices(); if (err) return err; #endif diff --git a/arch/arm/mach-tegra/board-ventana-panel.c b/arch/arm/mach-tegra/board-ventana-panel.c index 437969261b22..a9e7a67f2bb1 100644 --- a/arch/arm/mach-tegra/board-ventana-panel.c +++ b/arch/arm/mach-tegra/board-ventana-panel.c @@ -36,6 +36,7 @@ #include "devices.h" #include "gpio-names.h" #include "board.h" +#include "tegra2_host1x_devices.h" #define ventana_bl_enb TEGRA_GPIO_PD4 #define ventana_lvds_shutdown TEGRA_GPIO_PB2 @@ -411,7 +412,7 @@ int __init ventana_panel_init(void) #endif #ifdef CONFIG_TEGRA_GRHOST - err = nvhost_device_register(&tegra_grhost_device); + err = tegra2_register_host1x_devices(); if (err) return err; #endif diff --git a/arch/arm/mach-tegra/board-whistler-panel.c b/arch/arm/mach-tegra/board-whistler-panel.c index d171cf008a77..3510f9468394 100644 --- a/arch/arm/mach-tegra/board-whistler-panel.c +++ b/arch/arm/mach-tegra/board-whistler-panel.c @@ -38,6 +38,7 @@ #include "devices.h" #include "gpio-names.h" #include "board.h" +#include "tegra2_host1x_devices.h" #define whistler_hdmi_hpd TEGRA_GPIO_PN7 @@ -361,7 +362,7 @@ int __init whistler_panel_init(void) #endif #ifdef CONFIG_TEGRA_GRHOST - err = nvhost_device_register(&tegra_grhost_device); + err = tegra2_register_host1x_devices(); if (err) return err; #endif diff --git a/arch/arm/mach-tegra/devices.h b/arch/arm/mach-tegra/devices.h index 3d0734d1c688..1ee723534476 100644 --- a/arch/arm/mach-tegra/devices.h +++ b/arch/arm/mach-tegra/devices.h @@ -109,7 +109,6 @@ extern struct platform_device tegra_uartc_device; extern struct platform_device tegra_uartd_device; extern struct platform_device tegra_uarte_device; extern struct platform_device tegra_avp_device; -extern struct nvhost_device tegra_grhost_device; extern struct nvhost_device nvavp_device; extern struct platform_device tegra_aes_device; #if !defined(CONFIG_ARCH_TEGRA_2x_SOC) diff --git a/arch/arm/mach-tegra/p852/board-p852-panel.c b/arch/arm/mach-tegra/p852/board-p852-panel.c index bcf9f4af76cf..8ed62f039dc8 100644 --- a/arch/arm/mach-tegra/p852/board-p852-panel.c +++ b/arch/arm/mach-tegra/p852/board-p852-panel.c @@ -32,6 +32,7 @@ #include #include "board-p852.h" +#include "../tegra2_host1x_devices.h" #define CARVEOUT_IRAM {\ .name = "iram",\ @@ -175,7 +176,7 @@ int __init p852_panel_init(void) return err; #ifdef CONFIG_TEGRA_GRHOST - err = nvhost_device_register(&tegra_grhost_device); + err = tegra2_register_host1x_devices(); if (err) return err; #endif diff --git a/arch/arm/mach-tegra/tegra2_host1x_devices.h b/arch/arm/mach-tegra/tegra2_host1x_devices.h new file mode 100644 index 000000000000..974154a414dd --- /dev/null +++ b/arch/arm/mach-tegra/tegra2_host1x_devices.h @@ -0,0 +1,26 @@ +/* + * drivers/video/tegra/host/tegra2_host1x_devices.h + * + * Tegra2 Graphics Host Devices + * + * 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 . + */ + +#ifndef TEGRA2_HOST1X_DEVICES_H +#define TEGRA2_HOST1X_DEVICES_H + +int tegra2_register_host1x_devices(void); + +#endif diff --git a/arch/arm/mach-tegra/tegra3_host1x_devices.h b/arch/arm/mach-tegra/tegra3_host1x_devices.h new file mode 100644 index 000000000000..38a5eabf037f --- /dev/null +++ b/arch/arm/mach-tegra/tegra3_host1x_devices.h @@ -0,0 +1,26 @@ +/* + * drivers/video/tegra/host/tegra3_host1x_devices.h + * + * Tegra3 Graphics Host Devices + * + * 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 . + */ + +#ifndef TEGRA3_HOST1X_DEVICES_H +#define TEGRA3_HOST1X_DEVICES_H + +int tegra3_register_host1x_devices(void); + +#endif diff --git a/drivers/video/tegra/Makefile b/drivers/video/tegra/Makefile index 2299a3c5eaa3..104b161cc3db 100644 --- a/drivers/video/tegra/Makefile +++ b/drivers/video/tegra/Makefile @@ -1,4 +1,5 @@ GCOV_PROFILE := y +EXTRA_CFLAGS += -Idrivers/video/tegra/host obj-$(CONFIG_TEGRA_GRHOST) += host/ obj-$(CONFIG_TEGRA_DC) += dc/ obj-$(CONFIG_FB_TEGRA) += fb.o diff --git a/drivers/video/tegra/host/bus.c b/drivers/video/tegra/host/bus.c index e59dc4153b14..3b769f41170d 100644 --- a/drivers/video/tegra/host/bus.c +++ b/drivers/video/tegra/host/bus.c @@ -149,6 +149,23 @@ void nvhost_driver_unregister(struct nvhost_driver *drv) } EXPORT_SYMBOL_GPL(nvhost_driver_unregister); +int nvhost_add_devices(struct nvhost_device **devs, int num) +{ + int i, ret = 0; + + for (i = 0; i < num; i++) { + ret = nvhost_device_register(devs[i]); + if (ret) { + while (--i >= 0) + nvhost_device_unregister(devs[i]); + break; + } + } + + return ret; +} +EXPORT_SYMBOL_GPL(nvhost_add_devices); + int nvhost_device_register(struct nvhost_device *dev) { int i, ret = 0; diff --git a/drivers/video/tegra/host/chip_support.h b/drivers/video/tegra/host/chip_support.h index 33fd92eb31c8..6d378183e6e5 100644 --- a/drivers/video/tegra/host/chip_support.h +++ b/drivers/video/tegra/host/chip_support.h @@ -128,7 +128,6 @@ struct nvhost_chip_support { } intr; struct { - struct nvhost_device *(*get_nvhost_device)(char *name); struct nvhost_channel *(*alloc_nvhost_channel)(int chid); void (*free_nvhost_channel)(struct nvhost_channel *ch); } nvhost_dev; diff --git a/drivers/video/tegra/host/dev.c b/drivers/video/tegra/host/dev.c index 5c1e39da72cf..b3afc6e4d1e4 100644 --- a/drivers/video/tegra/host/dev.c +++ b/drivers/video/tegra/host/dev.c @@ -18,561 +18,19 @@ * along with this program. If not, see . */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "dev.h" #define CREATE_TRACE_POINTS #include -#include - #include -#include #include -#include -#include - -#include "debug.h" -#include "t20/t20.h" -#include "t30/t30.h" -#include "bus_client.h" -#include "nvhost_acm.h" -#include "nvhost_channel.h" -#include "nvhost_job.h" -#include "nvhost_memmgr.h" -#include "chip_support.h" - -#define DRIVER_NAME "host1x" static unsigned int register_sets; -struct nvhost_ctrl_userctx { - struct nvhost_master *dev; - u32 *mod_locks; -}; - -static int nvhost_ctrlrelease(struct inode *inode, struct file *filp) -{ - struct nvhost_ctrl_userctx *priv = filp->private_data; - int i; - - trace_nvhost_ctrlrelease(priv->dev->dev->name); - - filp->private_data = NULL; - if (priv->mod_locks[0]) - nvhost_module_idle(priv->dev->dev); - for (i = 1; i < priv->dev->syncpt.nb_mlocks; i++) - if (priv->mod_locks[i]) - nvhost_mutex_unlock(&priv->dev->syncpt, i); - kfree(priv->mod_locks); - kfree(priv); - return 0; -} - -static int nvhost_ctrlopen(struct inode *inode, struct file *filp) -{ - struct nvhost_master *host = - container_of(inode->i_cdev, struct nvhost_master, cdev); - struct nvhost_ctrl_userctx *priv; - u32 *mod_locks; - - trace_nvhost_ctrlopen(host->dev->name); - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - mod_locks = kzalloc(sizeof(u32) * host->syncpt.nb_mlocks, GFP_KERNEL); - - if (!(priv && mod_locks)) { - kfree(priv); - kfree(mod_locks); - return -ENOMEM; - } - - priv->dev = host; - priv->mod_locks = mod_locks; - filp->private_data = priv; - return 0; -} - -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) - return -EINVAL; - args->value = nvhost_syncpt_read(&ctx->dev->syncpt, args->id); - trace_nvhost_ioctl_ctrl_syncpt_read(args->id, args->value); - return 0; -} - -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) - return -EINVAL; - trace_nvhost_ioctl_ctrl_syncpt_incr(args->id); - nvhost_syncpt_incr(&ctx->dev->syncpt, args->id); - return 0; -} - -static int nvhost_ioctl_ctrl_syncpt_waitex(struct nvhost_ctrl_userctx *ctx, - struct nvhost_ctrl_syncpt_waitex_args *args) -{ - u32 timeout; - int err; - if (args->id >= ctx->dev->syncpt.nb_pts) - return -EINVAL; - if (args->timeout == NVHOST_NO_TIMEOUT) - timeout = MAX_SCHEDULE_TIMEOUT; - else - timeout = (u32)msecs_to_jiffies(args->timeout); - - err = nvhost_syncpt_wait_timeout(&ctx->dev->syncpt, args->id, - args->thresh, timeout, &args->value); - trace_nvhost_ioctl_ctrl_syncpt_wait(args->id, args->thresh, - args->timeout, args->value, err); - - return err; -} - -static int nvhost_ioctl_ctrl_module_mutex(struct nvhost_ctrl_userctx *ctx, - struct nvhost_ctrl_module_mutex_args *args) -{ - int err = 0; - if (args->id >= ctx->dev->syncpt.nb_mlocks || - args->lock > 1) - return -EINVAL; - - trace_nvhost_ioctl_ctrl_module_mutex(args->lock, args->id); - if (args->lock && !ctx->mod_locks[args->id]) { - if (args->id == 0) - nvhost_module_busy(ctx->dev->dev); - else - err = nvhost_mutex_try_lock(&ctx->dev->syncpt, - args->id); - if (!err) - ctx->mod_locks[args->id] = 1; - } else if (!args->lock && ctx->mod_locks[args->id]) { - if (args->id == 0) - nvhost_module_idle(ctx->dev->dev); - else - nvhost_mutex_unlock(&ctx->dev->syncpt, args->id); - ctx->mod_locks[args->id] = 0; - } - return err; -} - -static int match_by_moduleid(struct device *dev, void *data) -{ - struct nvhost_device *ndev = to_nvhost_device(dev); - u32 id = (u32)data; - - return id == ndev->moduleid; -} - -static struct nvhost_device *get_ndev_by_moduleid(struct nvhost_master *host, - u32 id) -{ - struct device *dev = bus_find_device(&nvhost_bus_inst->nvhost_bus_type, NULL, (void *)id, - match_by_moduleid); - - return dev ? to_nvhost_device(dev) : NULL; -} - -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; - u32 *offsets = args->offsets; - u32 *values = args->values; - u32 vals[64]; - struct nvhost_device *ndev; - - trace_nvhost_ioctl_ctrl_module_regrdwr(args->id, - args->num_offsets, args->write); - /* Check that there is something to read and that block size is - * u32 aligned */ - if (num_offsets == 0 || args->block_size & 3) - return -EINVAL; - - ndev = get_ndev_by_moduleid(ctx->dev, args->id); - if (!ndev) - return -EINVAL; - - while (num_offsets--) { - int err; - int remaining = args->block_size >> 2; - u32 offs; - if (get_user(offs, offsets)) - return -EFAULT; - offsets++; - while (remaining) { - int batch = min(remaining, 64); - if (args->write) { - if (copy_from_user(vals, values, - batch*sizeof(u32))) - return -EFAULT; - err = nvhost_write_module_regs(ndev, - offs, batch, vals); - if (err) - return err; - } else { - err = nvhost_read_module_regs(ndev, - offs, batch, vals); - if (err) - return err; - if (copy_to_user(values, vals, - batch*sizeof(u32))) - return -EFAULT; - } - remaining -= batch; - offs += batch*sizeof(u32); - values += batch; - } - } - - return 0; -} - -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; - return 0; -} - -static long nvhost_ctrlctl(struct file *filp, - unsigned int cmd, unsigned long arg) -{ - struct nvhost_ctrl_userctx *priv = filp->private_data; - u8 buf[NVHOST_IOCTL_CTRL_MAX_ARG_SIZE]; - int err = 0; - - if ((_IOC_TYPE(cmd) != NVHOST_IOCTL_MAGIC) || - (_IOC_NR(cmd) == 0) || - (_IOC_NR(cmd) > NVHOST_IOCTL_CTRL_LAST) || - (_IOC_SIZE(cmd) > NVHOST_IOCTL_CTRL_MAX_ARG_SIZE)) - return -EFAULT; - - if (_IOC_DIR(cmd) & _IOC_WRITE) { - if (copy_from_user(buf, (void __user *)arg, _IOC_SIZE(cmd))) - return -EFAULT; - } - - switch (cmd) { - case NVHOST_IOCTL_CTRL_SYNCPT_READ: - err = nvhost_ioctl_ctrl_syncpt_read(priv, (void *)buf); - break; - case NVHOST_IOCTL_CTRL_SYNCPT_INCR: - err = nvhost_ioctl_ctrl_syncpt_incr(priv, (void *)buf); - break; - case NVHOST_IOCTL_CTRL_SYNCPT_WAIT: - err = nvhost_ioctl_ctrl_syncpt_waitex(priv, (void *)buf); - break; - case NVHOST_IOCTL_CTRL_MODULE_MUTEX: - err = nvhost_ioctl_ctrl_module_mutex(priv, (void *)buf); - break; - case NVHOST_IOCTL_CTRL_MODULE_REGRDWR: - err = nvhost_ioctl_ctrl_module_regrdwr(priv, (void *)buf); - break; - case NVHOST_IOCTL_CTRL_SYNCPT_WAITEX: - err = nvhost_ioctl_ctrl_syncpt_waitex(priv, (void *)buf); - break; - case NVHOST_IOCTL_CTRL_GET_VERSION: - err = nvhost_ioctl_ctrl_get_version(priv, (void *)buf); - 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_ctrlops = { - .owner = THIS_MODULE, - .release = nvhost_ctrlrelease, - .open = nvhost_ctrlopen, - .unlocked_ioctl = nvhost_ctrlctl -}; - -static void power_on_host(struct nvhost_device *dev) -{ - struct nvhost_master *host = nvhost_get_drvdata(dev); - nvhost_syncpt_reset(&host->syncpt); - nvhost_intr_start(&host->intr, clk_get_rate(dev->clk[0])); -} - -static int power_off_host(struct nvhost_device *dev) -{ - struct nvhost_master *host = nvhost_get_drvdata(dev); - nvhost_syncpt_save(&host->syncpt); - nvhost_intr_stop(&host->intr); - return 0; -} - -static int __devinit nvhost_user_init(struct nvhost_master *host) +void nvhost_set_register_sets(unsigned int r) { - int err, devno; - - host->nvhost_class = class_create(THIS_MODULE, IFACE_NAME); - if (IS_ERR(host->nvhost_class)) { - err = PTR_ERR(host->nvhost_class); - dev_err(&host->dev->dev, "failed to create class\n"); - goto fail; - } - - err = alloc_chrdev_region(&devno, 0, 1, IFACE_NAME); - if (err < 0) { - dev_err(&host->dev->dev, "failed to reserve chrdev region\n"); - goto fail; - } - - cdev_init(&host->cdev, &nvhost_ctrlops); - host->cdev.owner = THIS_MODULE; - err = cdev_add(&host->cdev, devno, 1); - if (err < 0) - goto fail; - host->ctrl = device_create(host->nvhost_class, NULL, devno, NULL, - IFACE_NAME "-ctrl"); - if (IS_ERR(host->ctrl)) { - err = PTR_ERR(host->ctrl); - dev_err(&host->dev->dev, "failed to create ctrl device\n"); - goto fail; - } - - return 0; -fail: - return err; + register_sets = r; } -struct nvhost_device *nvhost_get_device(char *name) -{ - BUG_ON(!host_device_op().get_nvhost_device); - return host_device_op().get_nvhost_device(name); -} - -struct nvhost_channel *nvhost_alloc_channel(int index) -{ - BUG_ON(!host_device_op().alloc_nvhost_channel); - return host_device_op().alloc_nvhost_channel(index); -} - -void nvhost_free_channel(struct nvhost_channel *ch) -{ - BUG_ON(!host_device_op().free_nvhost_channel); - host_device_op().free_nvhost_channel(ch); -} - -static void nvhost_free_resources(struct nvhost_master *host) -{ - kfree(host->intr.syncpt); - host->intr.syncpt = 0; -} - -static int __devinit nvhost_alloc_resources(struct nvhost_master *host) -{ - int err; - - err = nvhost_init_chip_support(host); - if (err) - return err; - - host->intr.syncpt = kzalloc(sizeof(struct nvhost_intr_syncpt) * - host->syncpt.nb_pts, GFP_KERNEL); - - if (!host->intr.syncpt) { - /* frees happen in the support removal phase */ - return -ENOMEM; - } - - return 0; -} - -static struct resource nvhost_resources[] = { - { - .start = TEGRA_HOST1X_BASE, - .end = TEGRA_HOST1X_BASE + TEGRA_HOST1X_SIZE - 1, - .flags = IORESOURCE_MEM, - }, - { - .start = INT_SYNCPT_THRESH_BASE, - .end = INT_SYNCPT_THRESH_BASE + INT_SYNCPT_THRESH_NR - 1, - .flags = IORESOURCE_IRQ, - }, - { - .start = INT_HOST1X_MPCORE_GENERAL, - .end = INT_HOST1X_MPCORE_GENERAL, - .flags = IORESOURCE_IRQ, - }, -}; - -struct nvhost_device tegra_grhost_device = { - .name = DRIVER_NAME, - .id = -1, - .resource = nvhost_resources, - .num_resources = ARRAY_SIZE(nvhost_resources), - .clocks = {{"host1x", UINT_MAX}, {} }, - NVHOST_MODULE_NO_POWERGATE_IDS, -}; - -static int __devinit nvhost_probe(struct nvhost_device *dev, - struct nvhost_device_id *id_table) -{ - struct nvhost_master *host; - struct resource *regs, *intr0, *intr1; - int i, err; - - regs = nvhost_get_resource(dev, IORESOURCE_MEM, 0); - intr0 = nvhost_get_resource(dev, IORESOURCE_IRQ, 0); - intr1 = nvhost_get_resource(dev, IORESOURCE_IRQ, 1); - - if (!regs || !intr0 || !intr1) { - dev_err(&dev->dev, "missing required platform resources\n"); - return -ENXIO; - } - - host = kzalloc(sizeof(*host), GFP_KERNEL); - if (!host) - return -ENOMEM; - - host->reg_mem = request_mem_region(regs->start, - resource_size(regs), dev->name); - if (!host->reg_mem) { - dev_err(&dev->dev, "failed to get host register memory\n"); - err = -ENXIO; - goto fail; - } - - host->aperture = ioremap(regs->start, resource_size(regs)); - if (!host->aperture) { - dev_err(&dev->dev, "failed to remap host registers\n"); - err = -ENXIO; - goto fail; - } - - err = nvhost_alloc_resources(host); - if (err) { - dev_err(&dev->dev, "failed to init chip support\n"); - goto fail; - } - - host->memmgr = mem_op().alloc_mgr(); - if (!host->memmgr) { - dev_err(&dev->dev, "unable to create nvmap client\n"); - err = -EIO; - goto fail; - } - - /* Register host1x device as bus master */ - host->dev = dev; - - /* Give pointer to host1x via driver */ - nvhost_set_drvdata(dev, host); - - nvhost_bus_add_host(host); - - err = nvhost_syncpt_init(&tegra_grhost_device, &host->syncpt); - if (err) - goto fail; - - err = nvhost_intr_init(&host->intr, intr1->start, intr0->start); - if (err) - goto fail; - - err = nvhost_user_init(host); - if (err) - goto fail; - - err = nvhost_module_init(&tegra_grhost_device); - if (err) - goto fail; - - for (i = 0; i < host->dev->num_clks; i++) - clk_enable(host->dev->clk[i]); - nvhost_syncpt_reset(&host->syncpt); - for (i = 0; i < host->dev->num_clks; i++) - clk_disable(host->dev->clk[0]); - - nvhost_debug_init(host); - - dev_info(&dev->dev, "initialized\n"); - return 0; - -fail: - nvhost_free_resources(host); - if (host->memmgr) - mem_op().put_mgr(host->memmgr); - kfree(host); - return err; -} - -static int __exit nvhost_remove(struct nvhost_device *dev) -{ - struct nvhost_master *host = nvhost_get_drvdata(dev); - nvhost_intr_deinit(&host->intr); - nvhost_syncpt_deinit(&host->syncpt); - nvhost_free_resources(host); - return 0; -} - -static int nvhost_suspend(struct nvhost_device *dev, pm_message_t state) -{ - struct nvhost_master *host = nvhost_get_drvdata(dev); - int ret = 0; - - ret = nvhost_module_suspend(host->dev); - dev_info(&dev->dev, "suspend status: %d\n", ret); - - return ret; -} - -static int nvhost_resume(struct nvhost_device *dev) -{ - dev_info(&dev->dev, "resuming\n"); - return 0; -} - -static struct nvhost_driver nvhost_driver = { - .probe = nvhost_probe, - .remove = __exit_p(nvhost_remove), - .suspend = nvhost_suspend, - .resume = nvhost_resume, - .driver = { - .owner = THIS_MODULE, - .name = DRIVER_NAME - }, - .finalize_poweron = power_on_host, - .prepare_poweroff = power_off_host, -}; - -static int __init nvhost_mod_init(void) -{ - register_sets = tegra_gpu_register_sets(); - return nvhost_driver_register(&nvhost_driver); -} - -static void __exit nvhost_mod_exit(void) -{ - nvhost_driver_unregister(&nvhost_driver); -} - -/* host1x master device needs nvmap to be instantiated first. - * nvmap is instantiated via fs_initcall. - * Hence instantiate host1x master device using rootfs_initcall - * which is one level after fs_initcall. */ -rootfs_initcall(nvhost_mod_init); -module_exit(nvhost_mod_exit); - module_param_call(register_sets, NULL, param_get_uint, ®ister_sets, 0444); MODULE_PARM_DESC(register_sets, "Number of register sets"); diff --git a/drivers/video/tegra/host/dev.h b/drivers/video/tegra/host/dev.h index 332c99924b27..ce32ce498d4c 100644 --- a/drivers/video/tegra/host/dev.h +++ b/drivers/video/tegra/host/dev.h @@ -1,9 +1,7 @@ /* * drivers/video/tegra/host/dev.h * - * Tegra Graphics Host Driver Entrypoint - * - * Copyright (c) 2010-2012, NVIDIA Corporation. + * 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, @@ -18,43 +16,10 @@ * along with this program. If not, see . */ -#ifndef __NVHOST_DEV_H -#define __NVHOST_DEV_H - -#include -#include "nvhost_syncpt.h" -#include "nvhost_intr.h" - -#define TRACE_MAX_LENGTH 128U -#define IFACE_NAME "nvhost" - -struct nvhost_hwctx; -struct nvhost_channel; -struct mem_mgr; - -struct nvhost_master { - void __iomem *aperture; - void __iomem *sync_aperture; - struct resource *reg_mem; - struct class *nvhost_class; - struct cdev cdev; - struct device *ctrl; - struct nvhost_syncpt syncpt; - struct mem_mgr *memmgr; - struct nvhost_intr intr; - struct nvhost_device *dev; - atomic_t clientid; -}; - -extern struct nvhost_master *nvhost; - -void nvhost_debug_init(struct nvhost_master *master); -void nvhost_debug_dump(struct nvhost_master *master); - -struct nvhost_device *nvhost_get_device(char *name); -struct nvhost_channel *nvhost_alloc_channel(int index); -void nvhost_free_channel(struct nvhost_channel *ch); +#ifndef NVHOST_DEV_H +#define NVHOST_DEV_H -extern pid_t nvhost_debug_null_kickoff_pid; +#include "host1x/host1x.h" +void nvhost_set_register_sets(unsigned int r); #endif diff --git a/drivers/video/tegra/host/gr2d/gr2d.c b/drivers/video/tegra/host/gr2d/gr2d.c index c91a3aa23714..1bbfcdd8b587 100644 --- a/drivers/video/tegra/host/gr2d/gr2d.c +++ b/drivers/video/tegra/host/gr2d/gr2d.c @@ -44,8 +44,6 @@ static int gr2d_resume(struct nvhost_device *dev) return 0; } -struct nvhost_device *gr2d_device; - static struct nvhost_driver gr2d_driver = { .probe = gr2d_probe, .remove = __exit_p(gr2d_remove), @@ -61,16 +59,6 @@ static struct nvhost_driver gr2d_driver = { 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); } diff --git a/drivers/video/tegra/host/gr3d/gr3d.c b/drivers/video/tegra/host/gr3d/gr3d.c index 3208ba452bff..d586e26f104d 100644 --- a/drivers/video/tegra/host/gr3d/gr3d.c +++ b/drivers/video/tegra/host/gr3d/gr3d.c @@ -19,6 +19,7 @@ */ #include +#include #include "t20/t20.h" #include "host1x/host1x_channel.h" @@ -35,12 +36,6 @@ #include "nvhost_memmgr.h" #include "chip_support.h" -#include - -#ifndef TEGRA_POWERGATE_3D1 -#define TEGRA_POWERGATE_3D1 -1 -#endif - void nvhost_3dctx_restore_begin(struct host1x_hwctx_handler *p, u32 *ptr) { /* set class to host */ @@ -224,6 +219,7 @@ static int __devinit gr3d_probe(struct nvhost_device *dev, * found in clock tree */ dev->name = "gr3d"; + nvhost_set_register_sets(tegra_gpu_register_sets()); return nvhost_client_device_init(dev); } @@ -244,8 +240,6 @@ static int gr3d_resume(struct nvhost_device *dev) return 0; } -struct nvhost_device *gr3d_device; - static struct nvhost_driver gr3d_driver = { .probe = gr3d_probe, .remove = __exit_p(gr3d_remove), @@ -262,18 +256,6 @@ static struct nvhost_driver gr3d_driver = { 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) { - pr_err("Could not register 3D device\n"); - return err; - } - return nvhost_driver_register(&gr3d_driver); } diff --git a/drivers/video/tegra/host/gr3d/gr3d_t20.c b/drivers/video/tegra/host/gr3d/gr3d_t20.c index baa27051c794..272c955d7e7f 100644 --- a/drivers/video/tegra/host/gr3d/gr3d_t20.c +++ b/drivers/video/tegra/host/gr3d/gr3d_t20.c @@ -20,7 +20,7 @@ #include "nvhost_hwctx.h" #include "nvhost_channel.h" -#include "dev.h" +#include "host1x/host1x.h" #include "host1x/host1x_channel.h" #include "host1x/host1x_hardware.h" #include "host1x/host1x_syncpt.h" diff --git a/drivers/video/tegra/host/host1x/Makefile b/drivers/video/tegra/host/host1x/Makefile index c3214ffe147b..55fcb375709a 100644 --- a/drivers/video/tegra/host/host1x/Makefile +++ b/drivers/video/tegra/host/host1x/Makefile @@ -3,6 +3,7 @@ GCOV_PROFILE := y EXTRA_CFLAGS += -Idrivers/video/tegra/host nvhost-host1x-objs = \ + host1x.o \ host1x_syncpt.o \ host1x_channel.o \ host1x_intr.o \ diff --git a/drivers/video/tegra/host/host1x/host1x.c b/drivers/video/tegra/host/host1x/host1x.c new file mode 100644 index 000000000000..d203bc73a67d --- /dev/null +++ b/drivers/video/tegra/host/host1x/host1x.c @@ -0,0 +1,563 @@ +/* + * drivers/video/tegra/host/dev.c + * + * Tegra Graphics Host Driver Entrypoint + * + * Copyright (c) 2010-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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dev.h" +#include "bus.h" +#include + +#include + +#include +#include +#include +#include + +#include "debug.h" +#include "t20/t20.h" +#include "t30/t30.h" +#include "bus_client.h" +#include "nvhost_acm.h" +#include "nvhost_channel.h" +#include "nvhost_job.h" + +#define DRIVER_NAME "host1x" + +static struct resource tegra_host1x01_resources[] = { + { + .start = TEGRA_HOST1X_BASE, + .end = TEGRA_HOST1X_BASE + TEGRA_HOST1X_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = INT_SYNCPT_THRESH_BASE, + .end = INT_SYNCPT_THRESH_BASE + INT_SYNCPT_THRESH_NR - 1, + .flags = IORESOURCE_IRQ, + }, + { + .start = INT_HOST1X_MPCORE_GENERAL, + .end = INT_HOST1X_MPCORE_GENERAL, + .flags = IORESOURCE_IRQ, + }, +}; + +struct nvhost_device tegra_host1x01_device = { + .name = "host1x", + .id = -1, + .resource = tegra_host1x01_resources, + .num_resources = ARRAY_SIZE(tegra_host1x01_resources), + .clocks = {{"host1x", UINT_MAX}, {} }, + NVHOST_MODULE_NO_POWERGATE_IDS, +}; + +struct nvhost_ctrl_userctx { + struct nvhost_master *dev; + u32 *mod_locks; +}; + +static int nvhost_ctrlrelease(struct inode *inode, struct file *filp) +{ + struct nvhost_ctrl_userctx *priv = filp->private_data; + int i; + + trace_nvhost_ctrlrelease(priv->dev->dev->name); + + filp->private_data = NULL; + if (priv->mod_locks[0]) + nvhost_module_idle(priv->dev->dev); + for (i = 1; i < priv->dev->syncpt.nb_mlocks; i++) + if (priv->mod_locks[i]) + nvhost_mutex_unlock(&priv->dev->syncpt, i); + kfree(priv->mod_locks); + kfree(priv); + return 0; +} + +static int nvhost_ctrlopen(struct inode *inode, struct file *filp) +{ + struct nvhost_master *host = + container_of(inode->i_cdev, struct nvhost_master, cdev); + struct nvhost_ctrl_userctx *priv; + u32 *mod_locks; + + trace_nvhost_ctrlopen(host->dev->name); + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + mod_locks = kzalloc(sizeof(u32) * host->syncpt.nb_mlocks, GFP_KERNEL); + + if (!(priv && mod_locks)) { + kfree(priv); + kfree(mod_locks); + return -ENOMEM; + } + + priv->dev = host; + priv->mod_locks = mod_locks; + filp->private_data = priv; + return 0; +} + +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) + return -EINVAL; + args->value = nvhost_syncpt_read(&ctx->dev->syncpt, args->id); + trace_nvhost_ioctl_ctrl_syncpt_read(args->id, args->value); + return 0; +} + +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) + return -EINVAL; + trace_nvhost_ioctl_ctrl_syncpt_incr(args->id); + nvhost_syncpt_incr(&ctx->dev->syncpt, args->id); + return 0; +} + +static int nvhost_ioctl_ctrl_syncpt_waitex(struct nvhost_ctrl_userctx *ctx, + struct nvhost_ctrl_syncpt_waitex_args *args) +{ + u32 timeout; + int err; + if (args->id >= ctx->dev->syncpt.nb_pts) + return -EINVAL; + if (args->timeout == NVHOST_NO_TIMEOUT) + timeout = MAX_SCHEDULE_TIMEOUT; + else + timeout = (u32)msecs_to_jiffies(args->timeout); + + err = nvhost_syncpt_wait_timeout(&ctx->dev->syncpt, args->id, + args->thresh, timeout, &args->value); + trace_nvhost_ioctl_ctrl_syncpt_wait(args->id, args->thresh, + args->timeout, args->value, err); + + return err; +} + +static int nvhost_ioctl_ctrl_module_mutex(struct nvhost_ctrl_userctx *ctx, + struct nvhost_ctrl_module_mutex_args *args) +{ + int err = 0; + if (args->id >= ctx->dev->syncpt.nb_mlocks || + args->lock > 1) + return -EINVAL; + + trace_nvhost_ioctl_ctrl_module_mutex(args->lock, args->id); + if (args->lock && !ctx->mod_locks[args->id]) { + if (args->id == 0) + nvhost_module_busy(ctx->dev->dev); + else + err = nvhost_mutex_try_lock(&ctx->dev->syncpt, + args->id); + if (!err) + ctx->mod_locks[args->id] = 1; + } else if (!args->lock && ctx->mod_locks[args->id]) { + if (args->id == 0) + nvhost_module_idle(ctx->dev->dev); + else + nvhost_mutex_unlock(&ctx->dev->syncpt, args->id); + ctx->mod_locks[args->id] = 0; + } + return err; +} + +static int match_by_moduleid(struct device *dev, void *data) +{ + struct nvhost_device *ndev = to_nvhost_device(dev); + u32 id = (u32)data; + + return id == ndev->moduleid; +} + +static struct nvhost_device *get_ndev_by_moduleid(struct nvhost_master *host, + u32 id) +{ + struct device *dev = bus_find_device(&nvhost_bus_inst->nvhost_bus_type, + NULL, (void *)id, match_by_moduleid); + + return dev ? to_nvhost_device(dev) : NULL; +} + +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; + u32 *offsets = args->offsets; + u32 *values = args->values; + u32 vals[64]; + struct nvhost_device *ndev; + + trace_nvhost_ioctl_ctrl_module_regrdwr(args->id, + args->num_offsets, args->write); + /* Check that there is something to read and that block size is + * u32 aligned */ + if (num_offsets == 0 || args->block_size & 3) + return -EINVAL; + + ndev = get_ndev_by_moduleid(ctx->dev, args->id); + if (!ndev) + return -EINVAL; + + while (num_offsets--) { + int err; + int remaining = args->block_size >> 2; + u32 offs; + if (get_user(offs, offsets)) + return -EFAULT; + offsets++; + while (remaining) { + int batch = min(remaining, 64); + if (args->write) { + if (copy_from_user(vals, values, + batch*sizeof(u32))) + return -EFAULT; + err = nvhost_write_module_regs(ndev, + offs, batch, vals); + if (err) + return err; + } else { + err = nvhost_read_module_regs(ndev, + offs, batch, vals); + if (err) + return err; + if (copy_to_user(values, vals, + batch*sizeof(u32))) + return -EFAULT; + } + remaining -= batch; + offs += batch*sizeof(u32); + values += batch; + } + } + + return 0; +} + +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; + return 0; +} + +static long nvhost_ctrlctl(struct file *filp, + unsigned int cmd, unsigned long arg) +{ + struct nvhost_ctrl_userctx *priv = filp->private_data; + u8 buf[NVHOST_IOCTL_CTRL_MAX_ARG_SIZE]; + int err = 0; + + if ((_IOC_TYPE(cmd) != NVHOST_IOCTL_MAGIC) || + (_IOC_NR(cmd) == 0) || + (_IOC_NR(cmd) > NVHOST_IOCTL_CTRL_LAST) || + (_IOC_SIZE(cmd) > NVHOST_IOCTL_CTRL_MAX_ARG_SIZE)) + return -EFAULT; + + if (_IOC_DIR(cmd) & _IOC_WRITE) { + if (copy_from_user(buf, (void __user *)arg, _IOC_SIZE(cmd))) + return -EFAULT; + } + + switch (cmd) { + case NVHOST_IOCTL_CTRL_SYNCPT_READ: + err = nvhost_ioctl_ctrl_syncpt_read(priv, (void *)buf); + break; + case NVHOST_IOCTL_CTRL_SYNCPT_INCR: + err = nvhost_ioctl_ctrl_syncpt_incr(priv, (void *)buf); + break; + case NVHOST_IOCTL_CTRL_SYNCPT_WAIT: + err = nvhost_ioctl_ctrl_syncpt_waitex(priv, (void *)buf); + break; + case NVHOST_IOCTL_CTRL_MODULE_MUTEX: + err = nvhost_ioctl_ctrl_module_mutex(priv, (void *)buf); + break; + case NVHOST_IOCTL_CTRL_MODULE_REGRDWR: + err = nvhost_ioctl_ctrl_module_regrdwr(priv, (void *)buf); + break; + case NVHOST_IOCTL_CTRL_SYNCPT_WAITEX: + err = nvhost_ioctl_ctrl_syncpt_waitex(priv, (void *)buf); + break; + case NVHOST_IOCTL_CTRL_GET_VERSION: + err = nvhost_ioctl_ctrl_get_version(priv, (void *)buf); + 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_ctrlops = { + .owner = THIS_MODULE, + .release = nvhost_ctrlrelease, + .open = nvhost_ctrlopen, + .unlocked_ioctl = nvhost_ctrlctl +}; + +static void power_on_host(struct nvhost_device *dev) +{ + struct nvhost_master *host = nvhost_get_drvdata(dev); + nvhost_syncpt_reset(&host->syncpt); + nvhost_intr_start(&host->intr, clk_get_rate(dev->clk[0])); +} + +static int power_off_host(struct nvhost_device *dev) +{ + struct nvhost_master *host = nvhost_get_drvdata(dev); + nvhost_syncpt_save(&host->syncpt); + nvhost_intr_stop(&host->intr); + return 0; +} + +static int __devinit nvhost_user_init(struct nvhost_master *host) +{ + int err, devno; + + host->nvhost_class = class_create(THIS_MODULE, IFACE_NAME); + if (IS_ERR(host->nvhost_class)) { + err = PTR_ERR(host->nvhost_class); + dev_err(&host->dev->dev, "failed to create class\n"); + goto fail; + } + + err = alloc_chrdev_region(&devno, 0, 1, IFACE_NAME); + if (err < 0) { + dev_err(&host->dev->dev, "failed to reserve chrdev region\n"); + goto fail; + } + + cdev_init(&host->cdev, &nvhost_ctrlops); + host->cdev.owner = THIS_MODULE; + err = cdev_add(&host->cdev, devno, 1); + if (err < 0) + goto fail; + host->ctrl = device_create(host->nvhost_class, NULL, devno, NULL, + IFACE_NAME "-ctrl"); + if (IS_ERR(host->ctrl)) { + err = PTR_ERR(host->ctrl); + dev_err(&host->dev->dev, "failed to create ctrl device\n"); + goto fail; + } + + return 0; +fail: + return err; +} + +struct nvhost_channel *nvhost_alloc_channel(int index) +{ + BUG_ON(!host_device_op().alloc_nvhost_channel); + return host_device_op().alloc_nvhost_channel(index); +} + +void nvhost_free_channel(struct nvhost_channel *ch) +{ + BUG_ON(!host_device_op().free_nvhost_channel); + host_device_op().free_nvhost_channel(ch); +} + +static void nvhost_free_resources(struct nvhost_master *host) +{ + kfree(host->intr.syncpt); + host->intr.syncpt = 0; +} + +static int __devinit nvhost_alloc_resources(struct nvhost_master *host) +{ + int err; + + err = nvhost_init_chip_support(host); + if (err) + return err; + + host->intr.syncpt = kzalloc(sizeof(struct nvhost_intr_syncpt) * + host->syncpt.nb_pts, GFP_KERNEL); + + if (!host->intr.syncpt) { + /* frees happen in the support removal phase */ + return -ENOMEM; + } + + return 0; +} + +static int __devinit nvhost_probe(struct nvhost_device *dev, + struct nvhost_device_id *id_table) +{ + struct nvhost_master *host; + struct resource *regs, *intr0, *intr1; + int i, err; + + regs = nvhost_get_resource(dev, IORESOURCE_MEM, 0); + intr0 = nvhost_get_resource(dev, IORESOURCE_IRQ, 0); + intr1 = nvhost_get_resource(dev, IORESOURCE_IRQ, 1); + + if (!regs || !intr0 || !intr1) { + dev_err(&dev->dev, "missing required platform resources\n"); + return -ENXIO; + } + + host = kzalloc(sizeof(*host), GFP_KERNEL); + if (!host) + return -ENOMEM; + + host->reg_mem = request_mem_region(regs->start, + resource_size(regs), dev->name); + if (!host->reg_mem) { + dev_err(&dev->dev, "failed to get host register memory\n"); + err = -ENXIO; + goto fail; + } + + host->aperture = ioremap(regs->start, resource_size(regs)); + if (!host->aperture) { + dev_err(&dev->dev, "failed to remap host registers\n"); + err = -ENXIO; + goto fail; + } + + err = nvhost_alloc_resources(host); + if (err) { + dev_err(&dev->dev, "failed to init chip support\n"); + goto fail; + } + + host->memmgr = mem_op().alloc_mgr(); + if (!host->memmgr) { + dev_err(&dev->dev, "unable to create nvmap client\n"); + err = -EIO; + goto fail; + } + + /* Register host1x device as bus master */ + host->dev = dev; + + /* Give pointer to host1x via driver */ + nvhost_set_drvdata(dev, host); + + nvhost_bus_add_host(host); + + err = nvhost_syncpt_init(dev, &host->syncpt); + if (err) + goto fail; + + err = nvhost_intr_init(&host->intr, intr1->start, intr0->start); + if (err) + goto fail; + + err = nvhost_user_init(host); + if (err) + goto fail; + + err = nvhost_module_init(dev); + if (err) + goto fail; + + for (i = 0; i < host->dev->num_clks; i++) + clk_enable(host->dev->clk[i]); + nvhost_syncpt_reset(&host->syncpt); + for (i = 0; i < host->dev->num_clks; i++) + clk_disable(host->dev->clk[0]); + + nvhost_debug_init(host); + + dev_info(&dev->dev, "initialized\n"); + return 0; + +fail: + nvhost_free_resources(host); + if (host->memmgr) + mem_op().put_mgr(host->memmgr); + kfree(host); + return err; +} + +static int __exit nvhost_remove(struct nvhost_device *dev) +{ + struct nvhost_master *host = nvhost_get_drvdata(dev); + nvhost_intr_deinit(&host->intr); + nvhost_syncpt_deinit(&host->syncpt); + nvhost_free_resources(host); + return 0; +} + +static int nvhost_suspend(struct nvhost_device *dev, pm_message_t state) +{ + struct nvhost_master *host = nvhost_get_drvdata(dev); + int ret = 0; + + ret = nvhost_module_suspend(host->dev); + dev_info(&dev->dev, "suspend status: %d\n", ret); + + return ret; +} + +static int nvhost_resume(struct nvhost_device *dev) +{ + dev_info(&dev->dev, "resuming\n"); + return 0; +} + +static struct nvhost_driver nvhost_driver = { + .probe = nvhost_probe, + .remove = __exit_p(nvhost_remove), + .suspend = nvhost_suspend, + .resume = nvhost_resume, + .driver = { + .owner = THIS_MODULE, + .name = DRIVER_NAME + }, + .finalize_poweron = power_on_host, + .prepare_poweroff = power_off_host, +}; + +static int __init nvhost_mod_init(void) +{ + return nvhost_driver_register(&nvhost_driver); +} + +static void __exit nvhost_mod_exit(void) +{ + nvhost_driver_unregister(&nvhost_driver); +} + +/* host1x master device needs nvmap to be instantiated first. + * nvmap is instantiated via fs_initcall. + * Hence instantiate host1x master device using rootfs_initcall + * which is one level after fs_initcall. */ +rootfs_initcall(nvhost_mod_init); +module_exit(nvhost_mod_exit); + diff --git a/drivers/video/tegra/host/host1x/host1x.h b/drivers/video/tegra/host/host1x/host1x.h new file mode 100644 index 000000000000..295d3ff4c7f4 --- /dev/null +++ b/drivers/video/tegra/host/host1x/host1x.h @@ -0,0 +1,63 @@ +/* + * drivers/video/tegra/host/host1x/host1x.h + * + * Tegra Graphics Host Driver Entrypoint + * + * Copyright (c) 2010-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 . + */ + +#ifndef __NVHOST_DEV_H +#define __NVHOST_DEV_H + +#include +#include "nvhost_syncpt.h" +#include "nvhost_intr.h" + +#define TRACE_MAX_LENGTH 128U +#define IFACE_NAME "nvhost" + +struct nvhost_hwctx; +struct nvhost_channel; +struct mem_mgr; + +struct nvhost_master { + void __iomem *aperture; + void __iomem *sync_aperture; + struct resource *reg_mem; + struct class *nvhost_class; + struct cdev cdev; + struct device *ctrl; + struct nvhost_syncpt syncpt; + struct mem_mgr *memmgr; + struct nvhost_intr intr; + struct nvhost_device *dev; + atomic_t clientid; +}; + +extern struct nvhost_master *nvhost; + +void nvhost_debug_init(struct nvhost_master *master); +void nvhost_debug_dump(struct nvhost_master *master); + +struct nvhost_channel *nvhost_alloc_channel(int index); +void nvhost_free_channel(struct nvhost_channel *ch); + +extern pid_t nvhost_debug_null_kickoff_pid; + +struct nvhost_device; + +extern struct nvhost_device tegra_host1x01_device; + +#endif diff --git a/drivers/video/tegra/host/host1x/host1x_syncpt.c b/drivers/video/tegra/host/host1x/host1x_syncpt.c index 4cc8e9e212fa..e67d2209c6ef 100644 --- a/drivers/video/tegra/host/host1x/host1x_syncpt.c +++ b/drivers/video/tegra/host/host1x/host1x_syncpt.c @@ -23,7 +23,7 @@ #include #include "nvhost_syncpt.h" #include "nvhost_acm.h" -#include "dev.h" +#include "host1x.h" #include "host1x_syncpt.h" #include "host1x_hardware.h" #include "chip_support.h" diff --git a/drivers/video/tegra/host/host1x/host1x_syncpt.h b/drivers/video/tegra/host/host1x/host1x_syncpt.h index 1e94a2b846eb..f624a755da9c 100644 --- a/drivers/video/tegra/host/host1x/host1x_syncpt.h +++ b/drivers/video/tegra/host/host1x/host1x_syncpt.h @@ -45,12 +45,6 @@ #define NVSYNCPT_MPE_WR_SAFE (29) #define NVSYNCPT_DSI (31) - -/*#define NVSYNCPT_2D_CHANNEL2_0 (20) */ -/*#define NVSYNCPT_2D_CHANNEL2_1 (21) */ -/*#define NVSYNCPT_2D_TINYBLT_WAR (30)*/ -/*#define NVSYNCPT_2D_TINYBLT_RESTORE_CLASS_ID (30)*/ - /* sync points that are wholly managed by the client */ #define NVSYNCPTS_CLIENT_MANAGED ( \ BIT(NVSYNCPT_DISP0_A) | BIT(NVSYNCPT_DISP1_A) | \ @@ -64,7 +58,6 @@ BIT(NVSYNCPT_MPE_EBM_EOF) | BIT(NVSYNCPT_MPE_WR_SAFE) | \ BIT(NVSYNCPT_2D_1) | BIT(NVSYNCPT_AVP_0)) - #define NVWAITBASE_2D_0 (1) #define NVWAITBASE_2D_1 (2) #define NVWAITBASE_3D (3) diff --git a/drivers/video/tegra/host/isp/isp.c b/drivers/video/tegra/host/isp/isp.c index ae9d7eb09365..0a581f89e78d 100644 --- a/drivers/video/tegra/host/isp/isp.c +++ b/drivers/video/tegra/host/isp/isp.c @@ -18,10 +18,6 @@ * along with this program. If not, see . */ -#include - -#include - #include "dev.h" #include "bus_client.h" @@ -54,15 +50,6 @@ static int isp_resume(struct nvhost_device *dev) return 0; } -static struct resource isp_resources = { - .name = "regs", - .start = TEGRA_ISP_BASE, - .end = TEGRA_ISP_BASE + TEGRA_ISP_SIZE - 1, - .flags = IORESOURCE_MEM, -}; - -struct nvhost_device *isp_device; - static struct nvhost_driver isp_driver = { .probe = isp_probe, .remove = __exit_p(isp_remove), @@ -78,18 +65,6 @@ static struct nvhost_driver isp_driver = { static int __init isp_init(void) { - int err; - - isp_device = nvhost_get_device("isp"); - if (!isp_device) - return -ENXIO; - - isp_device->resource = &isp_resources; - isp_device->num_resources = 1; - err = nvhost_device_register(isp_device); - if (err) - return err; - return nvhost_driver_register(&isp_driver); } diff --git a/drivers/video/tegra/host/mpe/mpe.c b/drivers/video/tegra/host/mpe/mpe.c index 7468d4b9d753..cee0714bf079 100644 --- a/drivers/video/tegra/host/mpe/mpe.c +++ b/drivers/video/tegra/host/mpe/mpe.c @@ -30,10 +30,6 @@ #include "nvhost_memmgr.h" #include -#include - -#include -#include #include "bus_client.h" @@ -656,15 +652,6 @@ static int mpe_resume(struct nvhost_device *dev) return 0; } -static struct resource mpe_resources = { - .name = "regs", - .start = TEGRA_MPE_BASE, - .end = TEGRA_MPE_BASE + TEGRA_MPE_SIZE - 1, - .flags = IORESOURCE_MEM, -}; - -struct nvhost_device *mpe_device; - static struct nvhost_driver mpe_driver = { .probe = mpe_probe, .remove = __exit_p(mpe_remove), @@ -681,19 +668,6 @@ static struct nvhost_driver mpe_driver = { static int __init mpe_init(void) { - int err; - - mpe_device = nvhost_get_device("mpe"); - if (!mpe_device) - return -ENXIO; - - /* use ARRAY_SIZE macro if resources are more than 1 */ - mpe_device->resource = &mpe_resources; - mpe_device->num_resources = 1; - err = nvhost_device_register(mpe_device); - if (err) - return err; - return nvhost_driver_register(&mpe_driver); } diff --git a/drivers/video/tegra/host/t20/t20.c b/drivers/video/tegra/host/t20/t20.c index 50648bc98990..9c6e87a98f13 100644 --- a/drivers/video/tegra/host/t20/t20.c +++ b/drivers/video/tegra/host/t20/t20.c @@ -21,13 +21,14 @@ #include #include #include -#include "dev.h" +#include #include "t20.h" #include "host1x/host1x_syncpt.h" #include "host1x/host1x_hardware.h" #include "gr3d/gr3d.h" #include "gr3d/gr3d_t20.h" #include "mpe/mpe.h" +#include "host1x/host1x.h" #include "nvhost_hwctx.h" #include "nvhost_channel.h" #include "host1x/host1x_channel.h" @@ -50,13 +51,11 @@ static int t20_num_alloc_channels = 0; -struct nvhost_device t20_devices[] = { -{ - /* channel 0 */ +static struct nvhost_device tegra_display01_device = { .name = "display", .id = -1, .index = 0, - .syncpts = BIT(NVSYNCPT_DISP0_A) | BIT(NVSYNCPT_DISP1_A) | + .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), @@ -64,9 +63,9 @@ struct nvhost_device t20_devices[] = { NVHOST_MODULE_NO_POWERGATE_IDS, NVHOST_DEFAULT_CLOCKGATE_DELAY, .moduleid = NVHOST_MODULE_NONE, -}, -{ - /* channel 1 */ +}; + +static struct nvhost_device tegra_gr3d01_device = { .name = "gr3d01", .id = -1, .index = 1, @@ -74,13 +73,13 @@ struct nvhost_device t20_devices[] = { .waitbases = BIT(NVWAITBASE_3D), .modulemutexes = BIT(NVMODMUTEX_3D), .class = NV_GRAPHICS_3D_CLASS_ID, - .clocks = {{"gr3d", UINT_MAX}, {"emc", UINT_MAX}, {} }, + .clocks = {{"gr3d", UINT_MAX}, {"emc", UINT_MAX}, {} }, .powergate_ids = {TEGRA_POWERGATE_3D, -1}, NVHOST_DEFAULT_CLOCKGATE_DELAY, .moduleid = NVHOST_MODULE_NONE, -}, -{ - /* channel 2 */ +}; + +static struct nvhost_device tegra_gr2d01_device = { .name = "gr2d", .id = -1, .index = 2, @@ -88,26 +87,48 @@ struct nvhost_device t20_devices[] = { .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}, + .clocks = { {"gr2d", UINT_MAX}, {"epp", UINT_MAX}, {"emc", UINT_MAX} }, NVHOST_MODULE_NO_POWERGATE_IDS, .clockgate_delay = 0, .moduleid = NVHOST_MODULE_NONE, -}, -{ - /* channel 3 */ +}; + +static struct resource isp_resources_t20[] = { + { + .name = "regs", + .start = TEGRA_ISP_BASE, + .end = TEGRA_ISP_BASE + TEGRA_ISP_SIZE - 1, + .flags = IORESOURCE_MEM, + } +}; + +static struct nvhost_device tegra_isp01_device = { .name = "isp", .id = -1, + .resource = isp_resources_t20, + .num_resources = ARRAY_SIZE(isp_resources_t20), .index = 3, .syncpts = 0, NVHOST_MODULE_NO_POWERGATE_IDS, NVHOST_DEFAULT_CLOCKGATE_DELAY, .moduleid = NVHOST_MODULE_ISP, -}, -{ - /* channel 4 */ +}; + +static struct resource vi_resources[] = { + { + .name = "regs", + .start = TEGRA_VI_BASE, + .end = TEGRA_VI_BASE + TEGRA_VI_SIZE - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct nvhost_device tegra_vi01_device = { .name = "vi", + .resource = vi_resources, + .num_resources = ARRAY_SIZE(vi_resources), .id = -1, .index = 4, .syncpts = BIT(NVSYNCPT_CSI_VI_0) | BIT(NVSYNCPT_CSI_VI_1) | @@ -119,11 +140,22 @@ struct nvhost_device t20_devices[] = { NVHOST_MODULE_NO_POWERGATE_IDS, NVHOST_DEFAULT_CLOCKGATE_DELAY, .moduleid = NVHOST_MODULE_VI, -}, -{ - /* channel 5 */ +}; + +static struct resource tegra_mpe01_resources[] = { + { + .name = "regs", + .start = TEGRA_MPE_BASE, + .end = TEGRA_MPE_BASE + TEGRA_MPE_SIZE - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct nvhost_device tegra_mpe01_device = { .name = "mpe01", .id = -1, + .resource = tegra_mpe01_resources, + .num_resources = ARRAY_SIZE(tegra_mpe01_resources), .index = 5, .syncpts = BIT(NVSYNCPT_MPE) | BIT(NVSYNCPT_MPE_EBM_EOF) | BIT(NVSYNCPT_MPE_WR_SAFE), @@ -136,9 +168,9 @@ struct nvhost_device t20_devices[] = { .powergate_ids = {TEGRA_POWERGATE_MPE, -1}, NVHOST_DEFAULT_CLOCKGATE_DELAY, .moduleid = NVHOST_MODULE_MPE, -}, -{ - /* channel 6 */ +}; + +static struct nvhost_device tegra_dsi01_device = { .name = "dsi", .id = -1, .index = 6, @@ -147,8 +179,23 @@ struct nvhost_device t20_devices[] = { NVHOST_MODULE_NO_POWERGATE_IDS, NVHOST_DEFAULT_CLOCKGATE_DELAY, .moduleid = NVHOST_MODULE_NONE, -} }; +}; +static struct nvhost_device *t20_devices[] = { + &tegra_host1x01_device, + &tegra_display01_device, + &tegra_gr3d01_device, + &tegra_gr2d01_device, + &tegra_isp01_device, + &tegra_vi01_device, + &tegra_mpe01_device, + &tegra_dsi01_device, +}; + +int tegra2_register_host1x_devices(void) +{ + return nvhost_add_devices(t20_devices, ARRAY_SIZE(t20_devices)); +} static inline void __iomem *t20_channel_aperture(void __iomem *p, int ndx) { @@ -209,18 +256,6 @@ static struct nvhost_channel *t20_alloc_nvhost_channel(int chindex) T20_NVHOST_NUMCHANNELS, &t20_num_alloc_channels); } -struct nvhost_device *t20_get_nvhost_device(char *name) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(t20_devices); i++) { - if (strncmp(t20_devices[i].name, name, strlen(name)) == 0) - return &t20_devices[i]; - } - - return NULL; -} - int nvhost_init_t20_support(struct nvhost_master *host, struct nvhost_chip_support *op) { @@ -244,7 +279,6 @@ int nvhost_init_t20_support(struct nvhost_master *host, return err; err = nvhost_memmgr_init(op); - op->nvhost_dev.get_nvhost_device = t20_get_nvhost_device; op->nvhost_dev.alloc_nvhost_channel = t20_alloc_nvhost_channel; op->nvhost_dev.free_nvhost_channel = t20_free_nvhost_channel; diff --git a/drivers/video/tegra/host/t30/t30.c b/drivers/video/tegra/host/t30/t30.c index e6687fd2153b..acd5d928b1a1 100644 --- a/drivers/video/tegra/host/t30/t30.c +++ b/drivers/video/tegra/host/t30/t30.c @@ -22,13 +22,13 @@ #include #include #include -#include "dev.h" #include "t20/t20.h" #include "t30.h" #include "gr3d/gr3d.h" #include "gr3d/gr3d_t30.h" #include "gr3d/scale3d.h" #include "mpe/mpe.h" +#include "host1x/host1x.h" #include "host1x/host1x_hardware.h" #include "host1x/host1x_syncpt.h" #include "chip_support.h" @@ -47,19 +47,15 @@ #define NVMODMUTEX_VI (8) #define NVMODMUTEX_DSI (9) -#define NVHOST_CHANNEL_BASE 0 - #define T30_NVHOST_NUMCHANNELS (NV_HOST1X_CHANNELS - 1) static int t30_num_alloc_channels = 0; -struct nvhost_device t30_devices[] = { -{ - /* channel 0 */ +static struct nvhost_device tegra_display01_device = { .name = "display", .id = -1, .index = 0, - .syncpts = BIT(NVSYNCPT_DISP0_A) | BIT(NVSYNCPT_DISP1_A) | + .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), @@ -67,13 +63,13 @@ struct nvhost_device t30_devices[] = { NVHOST_MODULE_NO_POWERGATE_IDS, NVHOST_DEFAULT_CLOCKGATE_DELAY, .moduleid = NVHOST_MODULE_NONE, -}, -{ - /* channel 1 */ +}; + +static struct nvhost_device tegra_gr3d02_device = { .name = "gr3d02", .id = -1, .index = 1, - .syncpts = BIT(NVSYNCPT_3D), + .syncpts = BIT(NVSYNCPT_3D), .waitbases = BIT(NVWAITBASE_3D), .modulemutexes = BIT(NVMODMUTEX_3D), .class = NV_GRAPHICS_3D_CLASS_ID, @@ -87,9 +83,9 @@ struct nvhost_device t30_devices[] = { .powerup_reset = true, .powergate_delay = 250, .moduleid = NVHOST_MODULE_NONE, -}, -{ - /* channel 2 */ +}; + +static struct nvhost_device tegra_gr2d02_device = { .name = "gr2d", .id = -1, .index = 2, @@ -97,29 +93,51 @@ struct nvhost_device t30_devices[] = { .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} }, + .clocks = { {"gr2d", UINT_MAX}, + {"epp", 0}, + {"emc", 300000000} }, NVHOST_MODULE_NO_POWERGATE_IDS, .clockgate_delay = 0, .moduleid = NVHOST_MODULE_NONE, -}, -{ - /* channel 3 */ +}; + +static struct resource isp_resources_t20[] = { + { + .name = "regs", + .start = TEGRA_ISP_BASE, + .end = TEGRA_ISP_BASE + TEGRA_ISP_SIZE - 1, + .flags = IORESOURCE_MEM, + } +}; + +static struct nvhost_device tegra_isp01_device = { .name = "isp", .id = -1, + .resource = isp_resources_t20, + .num_resources = ARRAY_SIZE(isp_resources_t20), .index = 3, .syncpts = 0, NVHOST_MODULE_NO_POWERGATE_IDS, NVHOST_DEFAULT_CLOCKGATE_DELAY, .moduleid = NVHOST_MODULE_ISP, -}, -{ - /* channel 4 */ +}; + +static struct resource vi_resources[] = { + { + .name = "regs", + .start = TEGRA_VI_BASE, + .end = TEGRA_VI_BASE + TEGRA_VI_SIZE - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct nvhost_device tegra_vi01_device = { .name = "vi", + .resource = vi_resources, + .num_resources = ARRAY_SIZE(vi_resources), .id = -1, .index = 4, - .syncpts = BIT(NVSYNCPT_CSI_VI_0) | BIT(NVSYNCPT_CSI_VI_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), @@ -128,11 +146,22 @@ struct nvhost_device t30_devices[] = { NVHOST_MODULE_NO_POWERGATE_IDS, NVHOST_DEFAULT_CLOCKGATE_DELAY, .moduleid = NVHOST_MODULE_VI, -}, -{ - /* channel 5 */ +}; + +static struct resource tegra_mpe01_resources[] = { + { + .name = "regs", + .start = TEGRA_MPE_BASE, + .end = TEGRA_MPE_BASE + TEGRA_MPE_SIZE - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct nvhost_device tegra_mpe02_device = { .name = "mpe02", .id = -1, + .resource = tegra_mpe01_resources, + .num_resources = ARRAY_SIZE(tegra_mpe01_resources), .index = 5, .syncpts = BIT(NVSYNCPT_MPE) | BIT(NVSYNCPT_MPE_EBM_EOF) | BIT(NVSYNCPT_MPE_WR_SAFE), @@ -140,16 +169,16 @@ struct nvhost_device t30_devices[] = { .class = NV_VIDEO_ENCODE_MPEG_CLASS_ID, .waitbasesync = true, .keepalive = true, - .clocks = { {"mpe", UINT_MAX}, + .clocks = { {"mpe", UINT_MAX}, {"emc", UINT_MAX} }, .powergate_ids = {TEGRA_POWERGATE_MPE, -1}, NVHOST_DEFAULT_CLOCKGATE_DELAY, .can_powergate = true, .powergate_delay = 100, .moduleid = NVHOST_MODULE_MPE, -}, -{ - /* channel 6 */ +}; + +static struct nvhost_device tegra_dsi01_device = { .name = "dsi", .id = -1, .index = 6, @@ -158,7 +187,23 @@ struct nvhost_device t30_devices[] = { NVHOST_MODULE_NO_POWERGATE_IDS, NVHOST_DEFAULT_CLOCKGATE_DELAY, .moduleid = NVHOST_MODULE_NONE, -} }; +}; + +static struct nvhost_device *t30_devices[] = { + &tegra_host1x01_device, + &tegra_display01_device, + &tegra_gr3d02_device, + &tegra_gr2d02_device, + &tegra_isp01_device, + &tegra_vi01_device, + &tegra_mpe02_device, + &tegra_dsi01_device, +}; + +int tegra3_register_host1x_devices(void) +{ + return nvhost_add_devices(t30_devices, ARRAY_SIZE(t30_devices)); +} static inline int t30_nvhost_hwctx_handler_init(struct nvhost_channel *ch) { @@ -181,7 +226,6 @@ static inline int t30_nvhost_hwctx_handler_init(struct nvhost_channel *ch) static inline void __iomem *t30_channel_aperture(void __iomem *p, int ndx) { - ndx += NVHOST_CHANNEL_BASE; p += NV_HOST1X_CHANNEL0_BASE; p += ndx * NV_HOST1X_CHANNEL_MAP_SIZE_BYTES; return p; @@ -227,18 +271,6 @@ static struct nvhost_channel *t30_alloc_nvhost_channel(int chindex) T30_NVHOST_NUMCHANNELS, &t30_num_alloc_channels); } -struct nvhost_device *t30_get_nvhost_device(char *name) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(t30_devices); i++) { - if (strncmp(t30_devices[i].name, name, strlen(name)) == 0) - return &t30_devices[i]; - } - - return NULL; -} - int nvhost_init_t30_support(struct nvhost_master *host, struct nvhost_chip_support *op) { @@ -264,7 +296,6 @@ int nvhost_init_t30_support(struct nvhost_master *host, if (err) return err; - op->nvhost_dev.get_nvhost_device = t30_get_nvhost_device; op->nvhost_dev.alloc_nvhost_channel = t30_alloc_nvhost_channel; op->nvhost_dev.free_nvhost_channel = t30_free_nvhost_channel; diff --git a/drivers/video/tegra/host/vi/vi.c b/drivers/video/tegra/host/vi/vi.c index 3cfc7e32cbc1..3985ee029efa 100644 --- a/drivers/video/tegra/host/vi/vi.c +++ b/drivers/video/tegra/host/vi/vi.c @@ -18,10 +18,6 @@ * along with this program. If not, see . */ -#include - -#include - #include "dev.h" #include "bus_client.h" @@ -54,15 +50,6 @@ static int vi_resume(struct nvhost_device *dev) return 0; } -static struct resource vi_resources = { - .name = "regs", - .start = TEGRA_VI_BASE, - .end = TEGRA_VI_BASE + TEGRA_VI_SIZE - 1, - .flags = IORESOURCE_MEM, -}; - -struct nvhost_device *vi_device; - static struct nvhost_driver vi_driver = { .probe = vi_probe, .remove = __exit_p(vi_remove), @@ -78,18 +65,6 @@ static struct nvhost_driver vi_driver = { static int __init vi_init(void) { - int err; - - vi_device = nvhost_get_device("vi"); - if (!vi_device) - return -ENXIO; - - vi_device->resource = &vi_resources; - vi_device->num_resources = 1; - err = nvhost_device_register(vi_device); - if (err) - return err; - return nvhost_driver_register(&vi_driver); } diff --git a/include/linux/nvhost.h b/include/linux/nvhost.h index 82bb884dfbbd..1293cec7cd75 100644 --- a/include/linux/nvhost.h +++ b/include/linux/nvhost.h @@ -94,6 +94,9 @@ struct nvhost_device { struct nvhost_channel *channel; /* Channel assigned for the module */ }; +/* Register devices to nvhost bus */ +extern int nvhost_add_devices(struct nvhost_device **, int num); + /* Register device to nvhost bus */ extern int nvhost_device_register(struct nvhost_device *); -- cgit v1.2.3