2 * drivers/video/tegra/host/vi/vi.c
4 * Tegra Graphics Host VI
6 * Copyright (c) 2012-2017, 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/init.h>
22 #include <linux/export.h>
23 #include <linux/module.h>
24 #include <linux/resource.h>
25 #include <linux/pm_runtime.h>
27 #include <linux/of_device.h>
28 #include <linux/of_platform.h>
29 #include <linux/clk/tegra.h>
30 #include <soc/tegra/chip-id.h>
31 #include <linux/tegra_pm_domains.h>
32 #include <linux/debugfs.h>
33 #include <linux/slab.h>
35 #include <media/tegra_v4l2_camera.h>
38 #include "bus_client.h"
39 #include "nvhost_acm.h"
40 #include "t210/t210.h"
42 #include "vi/vi_irq.h"
43 #include "camera/vi/vi2_fops.h"
44 #include "camera/csi/csi2_fops.h"
46 #include "tegra_camera_dev_mfi.h"
48 #define MAX_DEVID_LENGTH 16
49 #define TEGRA_VI_NAME "tegra_vi"
53 struct vi *tegra_vi_get(void)
57 EXPORT_SYMBOL(tegra_vi_get);
59 static struct tegra_t210_vi_data t21_vi_data = {
60 .info = (struct nvhost_device_data *)&t21_vi_info,
62 .csi_fops = &csi2_fops,
65 static struct of_device_id tegra_vi_of_match[] = {
66 { .compatible = "nvidia,tegra210-vi",
67 .data = (struct tegra_t210_vi_data *)&t21_vi_data },
71 static struct i2c_camera_ctrl *i2c_ctrl;
73 static void (*mfi_callback)(void *);
74 static struct mfi_cb_arg *mfi_callback_arg;
75 static DEFINE_MUTEX(vi_isr_lock);
77 int tegra_vi_register_mfi_cb(callback cb, void *cb_arg)
79 mutex_lock(&vi_isr_lock);
80 if (mfi_callback || mfi_callback_arg) {
81 pr_err("cb already registered\n");
82 mutex_unlock(&vi_isr_lock);
87 mfi_callback_arg = (struct mfi_cb_arg *)cb_arg;
88 mutex_unlock(&vi_isr_lock);
92 EXPORT_SYMBOL(tegra_vi_register_mfi_cb);
94 int tegra_vi_unregister_mfi_cb(void)
96 mutex_lock(&vi_isr_lock);
98 mfi_callback_arg = NULL;
99 mutex_unlock(&vi_isr_lock);
103 EXPORT_SYMBOL(tegra_vi_unregister_mfi_cb);
105 struct tegra_mfi_chan {
106 struct work_struct mfi_cb_work;
112 struct tegra_vi_mfi_ctx {
114 struct workqueue_struct *mfi_workqueue;
115 struct tegra_mfi_chan __rcu *mfi_chans;
118 static void vi_mfi_worker(struct work_struct *vi_work)
120 struct tegra_mfi_chan *mfi_chan =
121 container_of(vi_work, struct tegra_mfi_chan, mfi_cb_work);
122 struct tegra_mc_vi *vi = tegra_get_mc_vi();
124 mutex_lock(&vi_isr_lock);
125 tegra_vi_mfi_work(vi, mfi_chan->channel);
126 mutex_unlock(&vi_isr_lock);
129 int tegra_vi_mfi_event_notify(struct tegra_vi_mfi_ctx *mfi_ctx, u8 channel)
131 struct tegra_mfi_chan *chan;
134 pr_err("Invalid mfi_ctx\n");
138 if (channel > mfi_ctx->num_channels-1) {
139 pr_err("Invalid mfi channel\n");
144 chan = rcu_dereference(mfi_ctx->mfi_chans);
145 queue_work(mfi_ctx->mfi_workqueue, &chan[channel].mfi_cb_work);
150 EXPORT_SYMBOL(tegra_vi_mfi_event_notify);
152 bool tegra_vi_has_mfi_callback(void)
156 mutex_lock(&vi_isr_lock);
157 ret = mfi_callback ? true : false;
158 mutex_unlock(&vi_isr_lock);
162 EXPORT_SYMBOL(tegra_vi_has_mfi_callback);
164 int tegra_vi_init_mfi(struct tegra_vi_mfi_ctx **pmfi_ctx, u8 num_channels)
167 struct tegra_mfi_chan *chan;
168 struct tegra_vi_mfi_ctx *mfi_ctx;
171 pr_err("mfi_ctx is invalid\n");
175 mfi_ctx = kzalloc(sizeof(*mfi_ctx), GFP_KERNEL);
176 if (unlikely(mfi_ctx == NULL))
179 /* create workqueue for mfi callback */
180 mfi_ctx->mfi_workqueue = alloc_workqueue("mfi_workqueue",
181 WQ_HIGHPRI | WQ_UNBOUND, 1);
182 if (!mfi_ctx->mfi_workqueue) {
183 pr_err("Failed to allocated mfi_workqueue");
184 tegra_vi_deinit_mfi(&mfi_ctx);
188 chan = kcalloc(num_channels, sizeof(*chan), GFP_KERNEL);
189 if (unlikely(chan == NULL)) {
190 tegra_vi_deinit_mfi(&mfi_ctx);
194 mfi_ctx->num_channels = num_channels;
196 /* Init mfi callback work */
197 for (i = 0; i < num_channels; i++) {
198 INIT_WORK(&chan[i].mfi_cb_work, vi_mfi_worker);
202 rcu_assign_pointer(mfi_ctx->mfi_chans, chan);
208 EXPORT_SYMBOL(tegra_vi_init_mfi);
210 void tegra_vi_deinit_mfi(struct tegra_vi_mfi_ctx **pmfi_ctx)
212 struct tegra_vi_mfi_ctx *mfi_ctx;
214 if (!pmfi_ctx || !*pmfi_ctx)
219 flush_workqueue(mfi_ctx->mfi_workqueue);
220 destroy_workqueue(mfi_ctx->mfi_workqueue);
222 kfree_rcu(mfi_ctx->mfi_chans, rcu);
227 EXPORT_SYMBOL(tegra_vi_deinit_mfi);
229 #if defined(CONFIG_TEGRA_ISOMGR)
230 static int vi_isomgr_unregister(struct vi *tegra_vi)
232 tegra_isomgr_unregister(tegra_vi->isomgr_handle);
233 tegra_vi->isomgr_handle = NULL;
239 static int vi_out_show(struct seq_file *s, void *unused)
241 struct vi *vi = s->private;
243 seq_printf(s, "vi overflow: %u\n",
244 atomic_read(&(vi->vi_out.overflow)));
249 static int vi_out_open(struct inode *inode, struct file *file)
251 return single_open(file, vi_out_show, inode->i_private);
254 static const struct file_operations vi_out_fops = {
258 .release = single_release,
261 static void vi_remove_debugfs(struct vi *vi)
263 debugfs_remove_recursive(vi->debugdir);
267 static void vi_create_debugfs(struct vi *vi)
270 char tegra_vi_name[20];
271 char debugfs_file_name[20];
274 snprintf(tegra_vi_name, sizeof(tegra_vi_name), "%s", TEGRA_VI_NAME);
276 vi->debugdir = debugfs_create_dir(tegra_vi_name, NULL);
278 dev_err(&vi->ndev->dev,
279 "%s: failed to create %s directory",
280 __func__, tegra_vi_name);
281 goto create_debugfs_fail;
284 snprintf(debugfs_file_name, sizeof(debugfs_file_name), "%s", "vi_out");
286 ret = debugfs_create_file(debugfs_file_name, S_IRUGO,
287 vi->debugdir, vi, &vi_out_fops);
289 dev_err(&vi->ndev->dev,
290 "%s: failed to create %s", __func__, debugfs_file_name);
291 goto create_debugfs_fail;
297 dev_err(&vi->ndev->dev, "%s: could not create debugfs", __func__);
298 vi_remove_debugfs(vi);
301 static int nvhost_vi_slcg_handler(struct notifier_block *nb,
302 unsigned long action, void *data)
307 struct nvhost_device_data *pdata =
308 container_of(nb, struct nvhost_device_data,
309 toggle_slcg_notifier);
310 struct vi *tegra_vi = (struct vi *)pdata->private_data;
312 if (tegra_vi->mc_vi.pg_mode)
315 clk = clk_get(NULL, "pll_d");
319 /* Make CSI sourced from PLL_D */
320 ret = tegra_clk_cfg_ex(clk, TEGRA_CLK_PLLD_CSI_OUT_ENB, 1);
322 dev_err(&pdata->pdev->dev,
323 "%s: failed to select CSI source pll_d: %d\n",
329 ret = clk_prepare_enable(clk);
331 dev_err(&pdata->pdev->dev, "Can't enable pll_d: %d\n", ret);
338 clk_disable_unprepare(clk);
340 /* Restore CSI source */
341 ret = tegra_clk_cfg_ex(clk, TEGRA_CLK_MIPI_CSI_OUT_ENB, 1);
343 dev_err(&pdata->pdev->dev,
344 "%s: failed to restore csi source: %d\n",
354 static int vi_probe(struct platform_device *dev)
357 struct nvhost_device_data *pdata = NULL;
358 struct tegra_t210_vi_data *data = NULL;
361 if (dev->dev.of_node) {
362 const struct of_device_id *match;
364 match = of_match_device(tegra_vi_of_match, &dev->dev);
366 data = (struct tegra_t210_vi_data *)match->data;
368 dev->dev.platform_data = pdata;
370 /* DT initializes it to -1, use below WAR to set correct value.
371 * TODO: Once proper fix for dev-id goes in, remove it.
373 dev->id = dev->dev.id;
375 pdata = (struct nvhost_device_data *)dev->dev.platform_data;
379 dev_info(&dev->dev, "no platform data\n");
383 err = nvhost_check_bondout(pdata->bond_out_id);
385 dev_warn(&dev->dev, "No VI unit present. err:%d", err);
390 mutex_init(&pdata->lock);
391 platform_set_drvdata(dev, pdata);
393 dev_info(&dev->dev, "%s: ++\n", __func__);
395 tegra_vi = devm_kzalloc(&dev->dev, sizeof(struct vi), GFP_KERNEL);
399 tegra_vi->ndev = dev;
400 tegra_vi->dev = &dev->dev;
401 err = nvhost_client_device_get_resources(dev);
407 err = tegra_vi_init_mfi(&tegra_vi->mfi_ctx, num_channels);
411 if (!pdata->aperture[0]) {
412 dev_err(&dev->dev, "%s: failed to map register base\n",
417 /* call vi_intr_init and stats_work */
418 INIT_WORK(&tegra_vi->stats_work, vi_stats_worker);
420 err = vi_intr_init(tegra_vi);
422 goto vi_mfi_init_fail;
424 vi_create_debugfs(tegra_vi);
426 i2c_ctrl = pdata->private_data;
427 pdata->private_data = tegra_vi;
428 mutex_init(&tegra_vi->update_la_lock);
430 /* Create I2C Devices according to settings from board file */
431 if (i2c_ctrl && i2c_ctrl->new_devices)
432 i2c_ctrl->new_devices(dev);
434 tegra_vi->reg = regulator_get(&tegra_vi->ndev->dev, "avdd_dsi_csi");
435 if (IS_ERR(tegra_vi->reg)) {
436 err = PTR_ERR(tegra_vi->reg);
438 dev_info(&tegra_vi->ndev->dev,
439 "%s: no regulator device\n", __func__);
441 dev_err(&tegra_vi->ndev->dev,
442 "%s: couldn't get regulator\n", __func__);
443 tegra_vi->reg = NULL;
444 if (tegra_platform_is_silicon())
445 goto camera_i2c_unregister;
448 #ifdef CONFIG_TEGRA_CAMERA
449 tegra_vi->camera = tegra_camera_register(dev);
450 if (!tegra_vi->camera) {
451 dev_err(&dev->dev, "%s: can't register tegra_camera\n",
453 goto vi_regulator_put;
457 if (pdata->slcg_notifier_enable &&
458 (pdata->powergate_id != -1)) {
459 pdata->toggle_slcg_notifier.notifier_call =
460 &nvhost_vi_slcg_handler;
462 slcg_register_notifier(pdata->powergate_id,
463 &pdata->toggle_slcg_notifier);
466 nvhost_module_init(dev);
468 err = nvhost_client_device_init(dev);
470 goto camera_unregister;
472 tegra_vi->mc_vi.vi = tegra_vi;
473 tegra_vi->mc_vi.csi = &tegra_vi->csi;
474 tegra_vi->mc_vi.reg = tegra_vi->reg;
475 tegra_vi->mc_vi.fops = data->vi_fops;
476 tegra_vi->csi.fops = data->csi_fops;
477 err = tegra_csi_media_controller_init(&tegra_vi->csi, dev);
479 goto vi_mc_init_error;
481 err = tegra_vi_media_controller_init(&tegra_vi->mc_vi, dev);
483 goto vi_mc_init_error;
488 nvhost_client_device_release(dev);
490 #ifdef CONFIG_TEGRA_CAMERA
491 tegra_camera_unregister(tegra_vi->camera);
495 regulator_put(tegra_vi->reg);
496 tegra_vi->reg = NULL;
498 camera_i2c_unregister:
499 if (i2c_ctrl && i2c_ctrl->remove_devices)
500 i2c_ctrl->remove_devices(dev);
501 pdata->private_data = i2c_ctrl;
503 tegra_vi_deinit_mfi(&tegra_vi->mfi_ctx);
505 dev_err(&dev->dev, "%s: failed\n", __func__);
509 static int __exit vi_remove(struct platform_device *dev)
511 #ifdef CONFIG_TEGRA_CAMERA
514 struct nvhost_device_data *pdata = platform_get_drvdata(dev);
515 struct vi *tegra_vi = (struct vi *)pdata->private_data;
518 if (atomic_read(&dev->dev.power.usage_count) > 0)
522 dev_info(&dev->dev, "%s: ++\n", __func__);
524 #if defined(CONFIG_TEGRA_ISOMGR)
525 if (tegra_vi->isomgr_handle)
526 vi_isomgr_unregister(tegra_vi);
529 tegra_vi_deinit_mfi(&tegra_vi->mfi_ctx);
531 vi_remove_debugfs(tegra_vi);
533 tegra_vi_media_controller_cleanup(&tegra_vi->mc_vi);
535 nvhost_client_device_release(dev);
537 if (pdata->slcg_notifier_enable &&
538 (pdata->powergate_id != -1))
539 slcg_unregister_notifier(pdata->powergate_id,
540 &pdata->toggle_slcg_notifier);
542 vi_intr_free(tegra_vi);
544 pdata->aperture[0] = NULL;
545 #ifdef CONFIG_TEGRA_CAMERA
546 err = tegra_camera_unregister(tegra_vi->camera);
551 #ifdef CONFIG_PM_GENERIC_DOMAINS
552 tegra_pd_remove_device(&dev->dev);
555 regulator_put(tegra_vi->reg);
556 tegra_vi->reg = NULL;
558 /* Remove I2C Devices according to settings from board file */
559 if (i2c_ctrl && i2c_ctrl->remove_devices)
560 i2c_ctrl->remove_devices(dev);
562 pdata->private_data = i2c_ctrl;
567 static struct platform_driver vi_driver = {
569 .remove = __exit_p(vi_remove),
571 .owner = THIS_MODULE,
574 .pm = &nvhost_module_pm_ops,
577 .of_match_table = tegra_vi_of_match,
582 static struct of_device_id tegra_vi_domain_match[] = {
583 {.compatible = "nvidia,tegra210-ve-pd",
584 .data = (struct nvhost_device_data *)&t21_vi_info},
588 static int __init vi_init(void)
592 ret = nvhost_domain_init(tegra_vi_domain_match);
596 return platform_driver_register(&vi_driver);
599 static void __exit vi_exit(void)
601 platform_driver_unregister(&vi_driver);
604 late_initcall(vi_init);
605 module_exit(vi_exit);
606 MODULE_LICENSE("GPL v2");