]> rtime.felk.cvut.cz Git - hercules2020/nv-tegra/linux-4.4.git/blob - drivers/media/platform/tegra/vi/vi.c
da86ee4725679e6c0fda26f706e97d3a177145b1
[hercules2020/nv-tegra/linux-4.4.git] / drivers / media / platform / tegra / vi / vi.c
1 /*
2  * drivers/video/tegra/host/vi/vi.c
3  *
4  * Tegra Graphics Host VI
5  *
6  * Copyright (c) 2012-2017, NVIDIA CORPORATION. All rights reserved.
7  *
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.
11  *
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
15  * more details.
16  *
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/>.
19  */
20
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>
26 #include <linux/of.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>
34
35 #include <media/tegra_v4l2_camera.h>
36
37 #include "dev.h"
38 #include "bus_client.h"
39 #include "nvhost_acm.h"
40 #include "t210/t210.h"
41 #include "vi/vi.h"
42 #include "vi/vi_irq.h"
43 #include "camera/vi/vi2_fops.h"
44 #include "camera/csi/csi2_fops.h"
45
46 #include "tegra_camera_dev_mfi.h"
47
48 #define MAX_DEVID_LENGTH        16
49 #define TEGRA_VI_NAME           "tegra_vi"
50
51 struct vi *tegra_vi;
52
53 struct vi *tegra_vi_get(void)
54 {
55         return tegra_vi;
56 }
57 EXPORT_SYMBOL(tegra_vi_get);
58
59 static struct tegra_t210_vi_data t21_vi_data = {
60         .info = (struct nvhost_device_data *)&t21_vi_info,
61         .vi_fops = &vi2_fops,
62         .csi_fops = &csi2_fops,
63 };
64
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 },
68         { },
69 };
70
71 static struct i2c_camera_ctrl *i2c_ctrl;
72
73 static void (*mfi_callback)(void *);
74 static struct mfi_cb_arg *mfi_callback_arg;
75 static DEFINE_MUTEX(vi_isr_lock);
76
77 int tegra_vi_register_mfi_cb(callback cb, void *cb_arg)
78 {
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);
83                 return -1;
84         }
85
86         mfi_callback = cb;
87         mfi_callback_arg = (struct  mfi_cb_arg *)cb_arg;
88         mutex_unlock(&vi_isr_lock);
89
90         return 0;
91 }
92 EXPORT_SYMBOL(tegra_vi_register_mfi_cb);
93
94 int tegra_vi_unregister_mfi_cb(void)
95 {
96         mutex_lock(&vi_isr_lock);
97         mfi_callback = NULL;
98         mfi_callback_arg = NULL;
99         mutex_unlock(&vi_isr_lock);
100
101         return 0;
102 }
103 EXPORT_SYMBOL(tegra_vi_unregister_mfi_cb);
104
105 struct tegra_mfi_chan {
106         struct work_struct mfi_cb_work;
107         struct rcu_head rcu;
108         u8 channel;
109 };
110
111 struct tegra_vi_mfi_ctx {
112         u8 num_channels;
113         struct workqueue_struct *mfi_workqueue;
114         struct tegra_mfi_chan __rcu *mfi_chans;
115 };
116
117 static void vi_mfi_worker(struct work_struct *vi_work)
118 {
119         struct tegra_mfi_chan *mfi_chan =
120                 container_of(vi_work, struct tegra_mfi_chan, mfi_cb_work);
121
122         mutex_lock(&vi_isr_lock);
123         if (mfi_callback == NULL) {
124                 pr_debug("NULL callback\n");
125                 mutex_unlock(&vi_isr_lock);
126                 return;
127         }
128         if (mfi_callback_arg)
129                 mfi_callback_arg->vi_chan = mfi_chan->channel;
130         mfi_callback(mfi_callback_arg);
131         mutex_unlock(&vi_isr_lock);
132 }
133
134 int tegra_vi_mfi_event_notify(struct tegra_vi_mfi_ctx *mfi_ctx, u8 channel)
135 {
136         struct tegra_mfi_chan *chan;
137
138         if (!mfi_ctx) {
139                 pr_err("Invalid mfi_ctx\n");
140                 return -EINVAL;
141         }
142
143         if (channel > mfi_ctx->num_channels-1) {
144                 pr_err("Invalid mfi channel\n");
145                 return -EINVAL;
146         }
147
148         rcu_read_lock();
149         chan = rcu_dereference(mfi_ctx->mfi_chans);
150         queue_work(mfi_ctx->mfi_workqueue, &chan[channel].mfi_cb_work);
151         rcu_read_unlock();
152
153         return 0;
154 }
155 EXPORT_SYMBOL(tegra_vi_mfi_event_notify);
156
157 bool tegra_vi_has_mfi_callback(void)
158 {
159         bool ret;
160
161         mutex_lock(&vi_isr_lock);
162         ret = mfi_callback ? true : false;
163         mutex_unlock(&vi_isr_lock);
164
165         return ret;
166 }
167 EXPORT_SYMBOL(tegra_vi_has_mfi_callback);
168
169 int tegra_vi_init_mfi(struct tegra_vi_mfi_ctx **pmfi_ctx, u8 num_channels)
170 {
171         u8 i;
172         struct tegra_mfi_chan *chan;
173         struct tegra_vi_mfi_ctx *mfi_ctx;
174
175         if (!pmfi_ctx) {
176                 pr_err("mfi_ctx is invalid\n");
177                 return -EINVAL;
178         }
179
180         mfi_ctx = kzalloc(sizeof(*mfi_ctx), GFP_KERNEL);
181         if (unlikely(mfi_ctx == NULL))
182                 return -ENOMEM;
183
184         /* create workqueue for mfi callback */
185         mfi_ctx->mfi_workqueue = alloc_workqueue("mfi_workqueue",
186                                         WQ_HIGHPRI | WQ_UNBOUND, 1);
187         if (!mfi_ctx->mfi_workqueue) {
188                 pr_err("Failed to allocated mfi_workqueue");
189                 tegra_vi_deinit_mfi(&mfi_ctx);
190                 return -ENOMEM;
191         }
192
193         chan = kcalloc(num_channels, sizeof(*chan), GFP_KERNEL);
194         if (unlikely(chan == NULL)) {
195                 tegra_vi_deinit_mfi(&mfi_ctx);
196                 return -ENOMEM;
197         }
198
199         mfi_ctx->num_channels = num_channels;
200
201         /* Init mfi callback work */
202         for (i = 0; i < num_channels; i++) {
203                 INIT_WORK(&chan[i].mfi_cb_work, vi_mfi_worker);
204                 chan[i].channel = i;
205         }
206
207         rcu_assign_pointer(mfi_ctx->mfi_chans, chan);
208
209         *pmfi_ctx = mfi_ctx;
210
211         return 0;
212 }
213 EXPORT_SYMBOL(tegra_vi_init_mfi);
214
215 void tegra_vi_deinit_mfi(struct tegra_vi_mfi_ctx **pmfi_ctx)
216 {
217         struct tegra_vi_mfi_ctx *mfi_ctx;
218
219         if (!pmfi_ctx || !*pmfi_ctx)
220                 return;
221
222         mfi_ctx = *pmfi_ctx;
223
224         flush_workqueue(mfi_ctx->mfi_workqueue);
225         destroy_workqueue(mfi_ctx->mfi_workqueue);
226
227         kfree_rcu(mfi_ctx->mfi_chans, rcu);
228
229         kfree(mfi_ctx);
230         mfi_ctx = NULL;
231 }
232 EXPORT_SYMBOL(tegra_vi_deinit_mfi);
233
234 #if defined(CONFIG_TEGRA_ISOMGR)
235 static int vi_isomgr_unregister(struct vi *tegra_vi)
236 {
237         tegra_isomgr_unregister(tegra_vi->isomgr_handle);
238         tegra_vi->isomgr_handle = NULL;
239
240         return 0;
241 }
242 #endif
243
244 static int vi_out_show(struct seq_file *s, void *unused)
245 {
246         struct vi *vi = s->private;
247
248         seq_printf(s, "vi overflow: %u\n",
249                 atomic_read(&(vi->vi_out.overflow)));
250
251         return 0;
252 }
253
254 static int vi_out_open(struct inode *inode, struct file *file)
255 {
256         return single_open(file, vi_out_show, inode->i_private);
257 }
258
259 static const struct file_operations vi_out_fops = {
260         .open           = vi_out_open,
261         .read           = seq_read,
262         .llseek         = seq_lseek,
263         .release        = single_release,
264 };
265
266 static void vi_remove_debugfs(struct vi *vi)
267 {
268         debugfs_remove_recursive(vi->debugdir);
269         vi->debugdir = NULL;
270 }
271
272 static void vi_create_debugfs(struct vi *vi)
273 {
274         struct dentry *ret;
275         char tegra_vi_name[20];
276         char debugfs_file_name[20];
277
278
279         snprintf(tegra_vi_name, sizeof(tegra_vi_name), "%s", TEGRA_VI_NAME);
280
281         vi->debugdir = debugfs_create_dir(tegra_vi_name, NULL);
282         if (!vi->debugdir) {
283                 dev_err(&vi->ndev->dev,
284                         "%s: failed to create %s directory",
285                         __func__, tegra_vi_name);
286                 goto create_debugfs_fail;
287         }
288
289         snprintf(debugfs_file_name, sizeof(debugfs_file_name), "%s", "vi_out");
290
291         ret = debugfs_create_file(debugfs_file_name, S_IRUGO,
292                         vi->debugdir, vi, &vi_out_fops);
293         if (!ret) {
294                 dev_err(&vi->ndev->dev,
295                 "%s: failed to create %s", __func__, debugfs_file_name);
296                 goto create_debugfs_fail;
297         }
298
299         return;
300
301 create_debugfs_fail:
302         dev_err(&vi->ndev->dev, "%s: could not create debugfs", __func__);
303         vi_remove_debugfs(vi);
304 }
305
306 static int nvhost_vi_slcg_handler(struct notifier_block *nb,
307                 unsigned long action, void *data)
308 {
309         struct clk *clk;
310         int ret = 0;
311
312         struct nvhost_device_data *pdata =
313                 container_of(nb, struct nvhost_device_data,
314                         toggle_slcg_notifier);
315         struct vi *tegra_vi = (struct vi *)pdata->private_data;
316
317         if (tegra_vi->mc_vi.pg_mode)
318                 return NOTIFY_OK;
319
320         clk = clk_get(NULL, "pll_d");
321         if (IS_ERR(clk))
322                 return -EINVAL;
323
324         /* Make CSI sourced from PLL_D */
325         ret = tegra_clk_cfg_ex(clk, TEGRA_CLK_PLLD_CSI_OUT_ENB, 1);
326         if (ret) {
327                 dev_err(&pdata->pdev->dev,
328                 "%s: failed to select CSI source pll_d: %d\n",
329                 __func__, ret);
330                 return ret;
331         }
332
333         /* Enable PLL_D */
334         ret = clk_prepare_enable(clk);
335         if (ret) {
336                 dev_err(&pdata->pdev->dev, "Can't enable pll_d: %d\n", ret);
337                 return ret;
338         }
339
340         udelay(1);
341
342         /* Disable PLL_D */
343         clk_disable_unprepare(clk);
344
345         /* Restore CSI source */
346         ret = tegra_clk_cfg_ex(clk, TEGRA_CLK_MIPI_CSI_OUT_ENB, 1);
347         if (ret) {
348                 dev_err(&pdata->pdev->dev,
349                 "%s: failed to restore csi source: %d\n",
350                 __func__, ret);
351                 return ret;
352         }
353
354         clk_put(clk);
355
356         return NOTIFY_OK;
357 }
358
359 static int vi_probe(struct platform_device *dev)
360 {
361         int err = 0;
362         struct nvhost_device_data *pdata = NULL;
363         struct tegra_t210_vi_data *data = NULL;
364         u8 num_channels;
365
366         if (dev->dev.of_node) {
367                 const struct of_device_id *match;
368
369                 match = of_match_device(tegra_vi_of_match, &dev->dev);
370                 if (match) {
371                         data = (struct tegra_t210_vi_data *)match->data;
372                         pdata = data->info;
373                         dev->dev.platform_data = pdata;
374                 }
375                 /* DT initializes it to -1, use below WAR to set correct value.
376                  * TODO: Once proper fix for dev-id goes in, remove it.
377                  */
378                 dev->id = dev->dev.id;
379         } else
380                 pdata = (struct nvhost_device_data *)dev->dev.platform_data;
381
382         WARN_ON(!pdata);
383         if (!pdata) {
384                 dev_info(&dev->dev, "no platform data\n");
385                 return -ENODATA;
386         }
387
388         err = nvhost_check_bondout(pdata->bond_out_id);
389         if (err) {
390                 dev_warn(&dev->dev, "No VI unit present. err:%d", err);
391                 return err;
392         }
393
394         pdata->pdev = dev;
395         mutex_init(&pdata->lock);
396         platform_set_drvdata(dev, pdata);
397
398         dev_info(&dev->dev, "%s: ++\n", __func__);
399
400         tegra_vi = devm_kzalloc(&dev->dev, sizeof(struct vi), GFP_KERNEL);
401         if (!tegra_vi)
402                 return -ENOMEM;
403
404         tegra_vi->ndev = dev;
405         tegra_vi->dev = &dev->dev;
406         err = nvhost_client_device_get_resources(dev);
407         if (err)
408                 goto vi_probe_fail;
409
410         num_channels = 6;
411
412         err = tegra_vi_init_mfi(&tegra_vi->mfi_ctx, num_channels);
413         if (err)
414                 goto vi_probe_fail;
415
416         if (!pdata->aperture[0]) {
417                 dev_err(&dev->dev, "%s: failed to map register base\n",
418                                 __func__);
419                 return -ENXIO;
420         }
421
422         /* call vi_intr_init and stats_work */
423         INIT_WORK(&tegra_vi->stats_work, vi_stats_worker);
424
425         err = vi_intr_init(tegra_vi);
426         if (err)
427                 goto vi_mfi_init_fail;
428
429         vi_create_debugfs(tegra_vi);
430
431         i2c_ctrl = pdata->private_data;
432         pdata->private_data = tegra_vi;
433         mutex_init(&tegra_vi->update_la_lock);
434
435         /* Create I2C Devices according to settings from board file */
436         if (i2c_ctrl && i2c_ctrl->new_devices)
437                 i2c_ctrl->new_devices(dev);
438
439         tegra_vi->reg = regulator_get(&tegra_vi->ndev->dev, "avdd_dsi_csi");
440         if (IS_ERR(tegra_vi->reg)) {
441                 err = PTR_ERR(tegra_vi->reg);
442                 if (err == -ENODEV)
443                         dev_info(&tegra_vi->ndev->dev,
444                                 "%s: no regulator device\n", __func__);
445                 else
446                         dev_err(&tegra_vi->ndev->dev,
447                                 "%s: couldn't get regulator\n", __func__);
448                 tegra_vi->reg = NULL;
449                 if (tegra_platform_is_silicon())
450                         goto camera_i2c_unregister;
451         }
452
453 #ifdef CONFIG_TEGRA_CAMERA
454         tegra_vi->camera = tegra_camera_register(dev);
455         if (!tegra_vi->camera) {
456                 dev_err(&dev->dev, "%s: can't register tegra_camera\n",
457                                 __func__);
458                 goto vi_regulator_put;
459         }
460 #endif
461
462         if (pdata->slcg_notifier_enable &&
463                         (pdata->powergate_id != -1)) {
464                 pdata->toggle_slcg_notifier.notifier_call =
465                 &nvhost_vi_slcg_handler;
466
467                 slcg_register_notifier(pdata->powergate_id,
468                         &pdata->toggle_slcg_notifier);
469         }
470
471         nvhost_module_init(dev);
472
473         err = nvhost_client_device_init(dev);
474         if (err)
475                 goto camera_unregister;
476
477         tegra_vi->mc_vi.vi = tegra_vi;
478         tegra_vi->mc_vi.csi = &tegra_vi->csi;
479         tegra_vi->mc_vi.reg = tegra_vi->reg;
480         tegra_vi->mc_vi.fops = data->vi_fops;
481         tegra_vi->csi.fops = data->csi_fops;
482         err = tegra_csi_media_controller_init(&tegra_vi->csi, dev);
483         if (err)
484                 goto vi_mc_init_error;
485
486         err = tegra_vi_media_controller_init(&tegra_vi->mc_vi, dev);
487         if (err)
488                 goto vi_mc_init_error;
489
490         return 0;
491
492 vi_mc_init_error:
493         nvhost_client_device_release(dev);
494 camera_unregister:
495 #ifdef CONFIG_TEGRA_CAMERA
496         tegra_camera_unregister(tegra_vi->camera);
497 vi_regulator_put:
498 #endif
499
500         regulator_put(tegra_vi->reg);
501         tegra_vi->reg = NULL;
502
503 camera_i2c_unregister:
504         if (i2c_ctrl && i2c_ctrl->remove_devices)
505                 i2c_ctrl->remove_devices(dev);
506         pdata->private_data = i2c_ctrl;
507 vi_mfi_init_fail:
508         tegra_vi_deinit_mfi(&tegra_vi->mfi_ctx);
509 vi_probe_fail:
510         dev_err(&dev->dev, "%s: failed\n", __func__);
511         return err;
512 }
513
514 static int __exit vi_remove(struct platform_device *dev)
515 {
516 #ifdef CONFIG_TEGRA_CAMERA
517         int err = 0;
518 #endif
519         struct nvhost_device_data *pdata = platform_get_drvdata(dev);
520         struct vi *tegra_vi = (struct vi *)pdata->private_data;
521
522 #ifdef CONFIG_PM
523         if (atomic_read(&dev->dev.power.usage_count) > 0)
524                 return -EBUSY;
525 #endif
526
527         dev_info(&dev->dev, "%s: ++\n", __func__);
528
529 #if defined(CONFIG_TEGRA_ISOMGR)
530         if (tegra_vi->isomgr_handle)
531                 vi_isomgr_unregister(tegra_vi);
532 #endif
533
534         tegra_vi_deinit_mfi(&tegra_vi->mfi_ctx);
535
536         vi_remove_debugfs(tegra_vi);
537
538         tegra_vi_media_controller_cleanup(&tegra_vi->mc_vi);
539
540         nvhost_client_device_release(dev);
541
542         if (pdata->slcg_notifier_enable &&
543             (pdata->powergate_id != -1))
544                 slcg_unregister_notifier(pdata->powergate_id,
545                                          &pdata->toggle_slcg_notifier);
546
547         vi_intr_free(tegra_vi);
548
549         pdata->aperture[0] = NULL;
550 #ifdef CONFIG_TEGRA_CAMERA
551         err = tegra_camera_unregister(tegra_vi->camera);
552         if (err)
553                 return err;
554 #endif
555
556 #ifdef CONFIG_PM_GENERIC_DOMAINS
557         tegra_pd_remove_device(&dev->dev);
558 #endif
559
560         regulator_put(tegra_vi->reg);
561         tegra_vi->reg = NULL;
562
563         /* Remove I2C Devices according to settings from board file */
564         if (i2c_ctrl && i2c_ctrl->remove_devices)
565                 i2c_ctrl->remove_devices(dev);
566
567         pdata->private_data = i2c_ctrl;
568
569         return 0;
570 }
571
572 static struct platform_driver vi_driver = {
573         .probe = vi_probe,
574         .remove = __exit_p(vi_remove),
575         .driver = {
576                 .owner = THIS_MODULE,
577                 .name = "vi",
578 #ifdef CONFIG_PM
579                 .pm = &nvhost_module_pm_ops,
580 #endif
581 #ifdef CONFIG_OF
582                 .of_match_table = tegra_vi_of_match,
583 #endif
584         }
585 };
586
587 static struct of_device_id tegra_vi_domain_match[] = {
588         {.compatible = "nvidia,tegra210-ve-pd",
589          .data = (struct nvhost_device_data *)&t21_vi_info},
590         {},
591 };
592
593 static int __init vi_init(void)
594 {
595         int ret;
596
597         ret = nvhost_domain_init(tegra_vi_domain_match);
598         if (ret)
599                 return ret;
600
601         return platform_driver_register(&vi_driver);
602 }
603
604 static void __exit vi_exit(void)
605 {
606         platform_driver_unregister(&vi_driver);
607 }
608
609 late_initcall(vi_init);
610 module_exit(vi_exit);
611 MODULE_LICENSE("GPL v2");