2 * drivers/video/tegra/host/vi/vi.c
4 * Tegra Graphics Host VI
6 * Copyright (c) 2012-2014, NVIDIA CORPORATION. All rights reserved.
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU General Public License,
10 * version 2, as published by the Free Software Foundation.
12 * This program is distributed in the hope it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include <linux/export.h>
22 #include <linux/module.h>
23 #include <linux/resource.h>
24 #include <linux/pm_runtime.h>
26 #include <linux/of_device.h>
27 #include <linux/of_platform.h>
28 #include <linux/clk/tegra.h>
30 #include <mach/pm_domains.h>
31 #include <media/tegra_v4l2_camera.h>
34 #include "bus_client.h"
35 #include "nvhost_acm.h"
36 #include "t114/t114.h"
37 #include "t148/t148.h"
38 #include "t124/t124.h"
42 #define MAX_DEVID_LENGTH 16
43 #define TEGRA_VI_NAME "tegra_vi"
45 static struct of_device_id tegra_vi_of_match[] = {
46 #ifdef TEGRA_11X_OR_HIGHER_CONFIG
47 { .compatible = "nvidia,tegra114-vi",
48 .data = (struct nvhost_device_data *)&t11_vi_info },
50 #ifdef TEGRA_14X_OR_HIGHER_CONFIG
51 { .compatible = "nvidia,tegra148-vi",
52 .data = (struct nvhost_device_data *)&t14_vi_info },
54 #ifdef TEGRA_12X_OR_HIGHER_CONFIG
55 { .compatible = "nvidia,tegra124-vi",
56 .data = (struct nvhost_device_data *)&t124_vi_info },
61 static struct i2c_camera_ctrl *i2c_ctrl;
63 #if defined(CONFIG_TEGRA_ISOMGR)
64 static int vi_isomgr_unregister(struct vi *tegra_vi)
66 tegra_isomgr_unregister(tegra_vi->isomgr_handle);
67 tegra_vi->isomgr_handle = NULL;
73 static int vi_out_show(struct seq_file *s, void *unused)
75 struct vi *vi = s->private;
77 seq_printf(s, "vi[%d] overflow: %u\n", vi->ndev->id,
78 atomic_read(&(vi->vi_out.overflow)));
83 static int vi_out_open(struct inode *inode, struct file *file)
85 return single_open(file, vi_out_show, inode->i_private);
88 static const struct file_operations vi_out_fops = {
92 .release = single_release,
95 static void vi_remove_debugfs(struct vi *vi)
97 debugfs_remove_recursive(vi->debugdir);
101 static void vi_create_debugfs(struct vi *vi)
104 char tegra_vi_name[20];
105 char debugfs_file_name[20];
108 snprintf(tegra_vi_name, sizeof(tegra_vi_name),
109 "%s_%u", TEGRA_VI_NAME, vi->ndev->id);
111 vi->debugdir = debugfs_create_dir(tegra_vi_name, NULL);
113 dev_err(&vi->ndev->dev,
114 "%s: failed to create %s directory",
115 __func__, tegra_vi_name);
116 goto create_debugfs_fail;
119 snprintf(debugfs_file_name, sizeof(debugfs_file_name),
120 "%s_%u", "vi_out", vi->ndev->id);
122 ret = debugfs_create_file(debugfs_file_name, S_IRUGO,
123 vi->debugdir, vi, &vi_out_fops);
125 dev_err(&vi->ndev->dev,
126 "%s: failed to create %s", __func__, debugfs_file_name);
127 goto create_debugfs_fail;
133 dev_err(&vi->ndev->dev, "%s: could not create debugfs", __func__);
134 vi_remove_debugfs(vi);
137 static int vi_probe(struct platform_device *dev)
141 struct nvhost_device_data *pdata = NULL;
142 if (dev->dev.of_node) {
143 const struct of_device_id *match;
145 match = of_match_device(tegra_vi_of_match, &dev->dev);
147 pdata = (struct nvhost_device_data *)match->data;
148 dev->dev.platform_data = pdata;
151 /* DT initializes it to -1, use below WAR to set correct value.
152 * TODO: Once proper fix for dev-id goes in, remove it.
154 dev->id = dev->dev.id;
156 pdata = (struct nvhost_device_data *)dev->dev.platform_data;
160 dev_info(&dev->dev, "no platform data\n");
165 mutex_init(&pdata->lock);
166 platform_set_drvdata(dev, pdata);
168 dev_info(&dev->dev, "%s: ++\n", __func__);
170 tegra_vi = devm_kzalloc(&dev->dev, sizeof(struct vi), GFP_KERNEL);
172 dev_err(&dev->dev, "can't allocate memory for vi\n");
176 err = nvhost_client_device_get_resources(dev);
180 tegra_vi->ndev = dev;
182 /* call vi_intr_init and stats_work */
183 INIT_WORK(&tegra_vi->stats_work, vi_stats_worker);
185 err = vi_intr_init(tegra_vi);
189 vi_create_debugfs(tegra_vi);
191 i2c_ctrl = pdata->private_data;
192 pdata->private_data = tegra_vi;
194 /* Create I2C Devices according to settings from board file */
195 if (i2c_ctrl && i2c_ctrl->new_devices)
196 i2c_ctrl->new_devices(dev);
198 tegra_vi->reg = regulator_get(&tegra_vi->ndev->dev, "avdd_dsi_csi");
199 if (IS_ERR(tegra_vi->reg)) {
200 err = PTR_ERR(tegra_vi->reg);
202 dev_info(&tegra_vi->ndev->dev,
203 "%s: no regulator device\n", __func__);
205 dev_err(&tegra_vi->ndev->dev,
206 "%s: couldn't get regulator\n", __func__);
207 tegra_vi->reg = NULL;
208 goto camera_i2c_unregister;
211 #ifdef CONFIG_TEGRA_CAMERA
212 tegra_vi->camera = tegra_camera_register(dev);
213 if (!tegra_vi->camera) {
214 dev_err(&dev->dev, "%s: can't register tegra_camera\n",
216 goto vi_regulator_put;
220 nvhost_module_init(dev);
222 #ifdef CONFIG_PM_GENERIC_DOMAINS
223 pdata->pd.name = "ve";
225 /* add module power domain and also add its domain
226 * as sub-domain of MC domain */
227 err = nvhost_module_add_domain(&pdata->pd, dev);
230 err = nvhost_client_device_init(dev);
232 goto camera_unregister;
237 #ifdef CONFIG_TEGRA_CAMERA
238 tegra_camera_unregister(tegra_vi->camera);
241 regulator_put(tegra_vi->reg);
242 tegra_vi->reg = NULL;
244 camera_i2c_unregister:
245 if (i2c_ctrl && i2c_ctrl->remove_devices)
246 i2c_ctrl->remove_devices(dev);
247 pdata->private_data = i2c_ctrl;
249 dev_err(&dev->dev, "%s: failed\n", __func__);
253 static int __exit vi_remove(struct platform_device *dev)
255 #ifdef CONFIG_TEGRA_CAMERA
258 struct nvhost_device_data *pdata = platform_get_drvdata(dev);
259 struct vi *tegra_vi = (struct vi *)pdata->private_data;
261 dev_info(&dev->dev, "%s: ++\n", __func__);
263 #if defined(CONFIG_TEGRA_ISOMGR)
264 if (tegra_vi->isomgr_handle)
265 vi_isomgr_unregister(tegra_vi);
268 vi_remove_debugfs(tegra_vi);
270 vi_intr_free(tegra_vi);
272 nvhost_client_device_release(dev);
273 pdata->aperture[0] = NULL;
275 #ifdef CONFIG_TEGRA_CAMERA
276 err = tegra_camera_unregister(tegra_vi->camera);
281 #ifdef CONFIG_PM_GENERIC_DOMAINS
282 tegra_pd_remove_device(&dev->dev);
285 regulator_put(tegra_vi->reg);
286 tegra_vi->reg = NULL;
288 /* Remove I2C Devices according to settings from board file */
289 if (i2c_ctrl && i2c_ctrl->remove_devices)
290 i2c_ctrl->remove_devices(dev);
292 pdata->private_data = i2c_ctrl;
297 static struct platform_driver vi_driver = {
299 .remove = __exit_p(vi_remove),
301 .owner = THIS_MODULE,
304 .pm = &nvhost_module_pm_ops,
307 .of_match_table = tegra_vi_of_match,
312 static int __init vi_init(void)
314 return platform_driver_register(&vi_driver);
317 static void __exit vi_exit(void)
319 platform_driver_unregister(&vi_driver);
322 late_initcall(vi_init);
323 module_exit(vi_exit);
324 MODULE_LICENSE("GPL v2");