]> rtime.felk.cvut.cz Git - hercules2020/nv-tegra/linux-4.4.git/blob - drivers/media/platform/tegra/vi/vi.c
drivers: media: camera: Add sync op support
[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         void *priv;
110 };
111
112 struct tegra_vi_mfi_ctx {
113         u8 num_channels;
114         struct workqueue_struct *mfi_workqueue;
115         struct tegra_mfi_chan __rcu *mfi_chans;
116 };
117
118 static void vi_mfi_worker(struct work_struct *vi_work)
119 {
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();
123
124         mutex_lock(&vi_isr_lock);
125         tegra_vi_mfi_work(vi, mfi_chan->channel);
126         mutex_unlock(&vi_isr_lock);
127 }
128
129 int tegra_vi_mfi_event_notify(struct tegra_vi_mfi_ctx *mfi_ctx, u8 channel)
130 {
131         struct tegra_mfi_chan *chan;
132
133         if (!mfi_ctx) {
134                 pr_err("Invalid mfi_ctx\n");
135                 return -EINVAL;
136         }
137
138         if (channel > mfi_ctx->num_channels-1) {
139                 pr_err("Invalid mfi channel\n");
140                 return -EINVAL;
141         }
142
143         rcu_read_lock();
144         chan = rcu_dereference(mfi_ctx->mfi_chans);
145         queue_work(mfi_ctx->mfi_workqueue, &chan[channel].mfi_cb_work);
146         rcu_read_unlock();
147
148         return 0;
149 }
150 EXPORT_SYMBOL(tegra_vi_mfi_event_notify);
151
152 bool tegra_vi_has_mfi_callback(void)
153 {
154         bool ret;
155
156         mutex_lock(&vi_isr_lock);
157         ret = mfi_callback ? true : false;
158         mutex_unlock(&vi_isr_lock);
159
160         return ret;
161 }
162 EXPORT_SYMBOL(tegra_vi_has_mfi_callback);
163
164 int tegra_vi_init_mfi(struct tegra_vi_mfi_ctx **pmfi_ctx, u8 num_channels)
165 {
166         u8 i;
167         struct tegra_mfi_chan *chan;
168         struct tegra_vi_mfi_ctx *mfi_ctx;
169
170         if (!pmfi_ctx) {
171                 pr_err("mfi_ctx is invalid\n");
172                 return -EINVAL;
173         }
174
175         mfi_ctx = kzalloc(sizeof(*mfi_ctx), GFP_KERNEL);
176         if (unlikely(mfi_ctx == NULL))
177                 return -ENOMEM;
178
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);
185                 return -ENOMEM;
186         }
187
188         chan = kcalloc(num_channels, sizeof(*chan), GFP_KERNEL);
189         if (unlikely(chan == NULL)) {
190                 tegra_vi_deinit_mfi(&mfi_ctx);
191                 return -ENOMEM;
192         }
193
194         mfi_ctx->num_channels = num_channels;
195
196         /* Init mfi callback work */
197         for (i = 0; i < num_channels; i++) {
198                 INIT_WORK(&chan[i].mfi_cb_work, vi_mfi_worker);
199                 chan[i].channel = i;
200         }
201
202         rcu_assign_pointer(mfi_ctx->mfi_chans, chan);
203
204         *pmfi_ctx = mfi_ctx;
205
206         return 0;
207 }
208 EXPORT_SYMBOL(tegra_vi_init_mfi);
209
210 void tegra_vi_deinit_mfi(struct tegra_vi_mfi_ctx **pmfi_ctx)
211 {
212         struct tegra_vi_mfi_ctx *mfi_ctx;
213
214         if (!pmfi_ctx || !*pmfi_ctx)
215                 return;
216
217         mfi_ctx = *pmfi_ctx;
218
219         flush_workqueue(mfi_ctx->mfi_workqueue);
220         destroy_workqueue(mfi_ctx->mfi_workqueue);
221
222         kfree_rcu(mfi_ctx->mfi_chans, rcu);
223
224         kfree(mfi_ctx);
225         mfi_ctx = NULL;
226 }
227 EXPORT_SYMBOL(tegra_vi_deinit_mfi);
228
229 #if defined(CONFIG_TEGRA_ISOMGR)
230 static int vi_isomgr_unregister(struct vi *tegra_vi)
231 {
232         tegra_isomgr_unregister(tegra_vi->isomgr_handle);
233         tegra_vi->isomgr_handle = NULL;
234
235         return 0;
236 }
237 #endif
238
239 static int vi_out_show(struct seq_file *s, void *unused)
240 {
241         struct vi *vi = s->private;
242
243         seq_printf(s, "vi overflow: %u\n",
244                 atomic_read(&(vi->vi_out.overflow)));
245
246         return 0;
247 }
248
249 static int vi_out_open(struct inode *inode, struct file *file)
250 {
251         return single_open(file, vi_out_show, inode->i_private);
252 }
253
254 static const struct file_operations vi_out_fops = {
255         .open           = vi_out_open,
256         .read           = seq_read,
257         .llseek         = seq_lseek,
258         .release        = single_release,
259 };
260
261 static void vi_remove_debugfs(struct vi *vi)
262 {
263         debugfs_remove_recursive(vi->debugdir);
264         vi->debugdir = NULL;
265 }
266
267 static void vi_create_debugfs(struct vi *vi)
268 {
269         struct dentry *ret;
270         char tegra_vi_name[20];
271         char debugfs_file_name[20];
272
273
274         snprintf(tegra_vi_name, sizeof(tegra_vi_name), "%s", TEGRA_VI_NAME);
275
276         vi->debugdir = debugfs_create_dir(tegra_vi_name, NULL);
277         if (!vi->debugdir) {
278                 dev_err(&vi->ndev->dev,
279                         "%s: failed to create %s directory",
280                         __func__, tegra_vi_name);
281                 goto create_debugfs_fail;
282         }
283
284         snprintf(debugfs_file_name, sizeof(debugfs_file_name), "%s", "vi_out");
285
286         ret = debugfs_create_file(debugfs_file_name, S_IRUGO,
287                         vi->debugdir, vi, &vi_out_fops);
288         if (!ret) {
289                 dev_err(&vi->ndev->dev,
290                 "%s: failed to create %s", __func__, debugfs_file_name);
291                 goto create_debugfs_fail;
292         }
293
294         return;
295
296 create_debugfs_fail:
297         dev_err(&vi->ndev->dev, "%s: could not create debugfs", __func__);
298         vi_remove_debugfs(vi);
299 }
300
301 static int nvhost_vi_slcg_handler(struct notifier_block *nb,
302                 unsigned long action, void *data)
303 {
304         struct clk *clk;
305         int ret = 0;
306
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;
311
312         if (tegra_vi->mc_vi.pg_mode)
313                 return NOTIFY_OK;
314
315         clk = clk_get(NULL, "pll_d");
316         if (IS_ERR(clk))
317                 return -EINVAL;
318
319         /* Make CSI sourced from PLL_D */
320         ret = tegra_clk_cfg_ex(clk, TEGRA_CLK_PLLD_CSI_OUT_ENB, 1);
321         if (ret) {
322                 dev_err(&pdata->pdev->dev,
323                 "%s: failed to select CSI source pll_d: %d\n",
324                 __func__, ret);
325                 return ret;
326         }
327
328         /* Enable PLL_D */
329         ret = clk_prepare_enable(clk);
330         if (ret) {
331                 dev_err(&pdata->pdev->dev, "Can't enable pll_d: %d\n", ret);
332                 return ret;
333         }
334
335         udelay(1);
336
337         /* Disable PLL_D */
338         clk_disable_unprepare(clk);
339
340         /* Restore CSI source */
341         ret = tegra_clk_cfg_ex(clk, TEGRA_CLK_MIPI_CSI_OUT_ENB, 1);
342         if (ret) {
343                 dev_err(&pdata->pdev->dev,
344                 "%s: failed to restore csi source: %d\n",
345                 __func__, ret);
346                 return ret;
347         }
348
349         clk_put(clk);
350
351         return NOTIFY_OK;
352 }
353
354 static int vi_probe(struct platform_device *dev)
355 {
356         int err = 0;
357         struct nvhost_device_data *pdata = NULL;
358         struct tegra_t210_vi_data *data = NULL;
359         u8 num_channels;
360
361         if (dev->dev.of_node) {
362                 const struct of_device_id *match;
363
364                 match = of_match_device(tegra_vi_of_match, &dev->dev);
365                 if (match) {
366                         data = (struct tegra_t210_vi_data *)match->data;
367                         pdata = data->info;
368                         dev->dev.platform_data = pdata;
369                 }
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.
372                  */
373                 dev->id = dev->dev.id;
374         } else
375                 pdata = (struct nvhost_device_data *)dev->dev.platform_data;
376
377         WARN_ON(!pdata);
378         if (!pdata) {
379                 dev_info(&dev->dev, "no platform data\n");
380                 return -ENODATA;
381         }
382
383         err = nvhost_check_bondout(pdata->bond_out_id);
384         if (err) {
385                 dev_warn(&dev->dev, "No VI unit present. err:%d", err);
386                 return err;
387         }
388
389         pdata->pdev = dev;
390         mutex_init(&pdata->lock);
391         platform_set_drvdata(dev, pdata);
392
393         dev_info(&dev->dev, "%s: ++\n", __func__);
394
395         tegra_vi = devm_kzalloc(&dev->dev, sizeof(struct vi), GFP_KERNEL);
396         if (!tegra_vi)
397                 return -ENOMEM;
398
399         tegra_vi->ndev = dev;
400         tegra_vi->dev = &dev->dev;
401         err = nvhost_client_device_get_resources(dev);
402         if (err)
403                 goto vi_probe_fail;
404
405         num_channels = 6;
406
407         err = tegra_vi_init_mfi(&tegra_vi->mfi_ctx, num_channels);
408         if (err)
409                 goto vi_probe_fail;
410
411         if (!pdata->aperture[0]) {
412                 dev_err(&dev->dev, "%s: failed to map register base\n",
413                                 __func__);
414                 return -ENXIO;
415         }
416
417         /* call vi_intr_init and stats_work */
418         INIT_WORK(&tegra_vi->stats_work, vi_stats_worker);
419
420         err = vi_intr_init(tegra_vi);
421         if (err)
422                 goto vi_mfi_init_fail;
423
424         vi_create_debugfs(tegra_vi);
425
426         i2c_ctrl = pdata->private_data;
427         pdata->private_data = tegra_vi;
428         mutex_init(&tegra_vi->update_la_lock);
429
430         /* Create I2C Devices according to settings from board file */
431         if (i2c_ctrl && i2c_ctrl->new_devices)
432                 i2c_ctrl->new_devices(dev);
433
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);
437                 if (err == -ENODEV)
438                         dev_info(&tegra_vi->ndev->dev,
439                                 "%s: no regulator device\n", __func__);
440                 else
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;
446         }
447
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",
452                                 __func__);
453                 goto vi_regulator_put;
454         }
455 #endif
456
457         if (pdata->slcg_notifier_enable &&
458                         (pdata->powergate_id != -1)) {
459                 pdata->toggle_slcg_notifier.notifier_call =
460                 &nvhost_vi_slcg_handler;
461
462                 slcg_register_notifier(pdata->powergate_id,
463                         &pdata->toggle_slcg_notifier);
464         }
465
466         nvhost_module_init(dev);
467
468         err = nvhost_client_device_init(dev);
469         if (err)
470                 goto camera_unregister;
471
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);
478         if (err)
479                 goto vi_mc_init_error;
480
481         err = tegra_vi_media_controller_init(&tegra_vi->mc_vi, dev);
482         if (err)
483                 goto vi_mc_init_error;
484
485         return 0;
486
487 vi_mc_init_error:
488         nvhost_client_device_release(dev);
489 camera_unregister:
490 #ifdef CONFIG_TEGRA_CAMERA
491         tegra_camera_unregister(tegra_vi->camera);
492 vi_regulator_put:
493 #endif
494
495         regulator_put(tegra_vi->reg);
496         tegra_vi->reg = NULL;
497
498 camera_i2c_unregister:
499         if (i2c_ctrl && i2c_ctrl->remove_devices)
500                 i2c_ctrl->remove_devices(dev);
501         pdata->private_data = i2c_ctrl;
502 vi_mfi_init_fail:
503         tegra_vi_deinit_mfi(&tegra_vi->mfi_ctx);
504 vi_probe_fail:
505         dev_err(&dev->dev, "%s: failed\n", __func__);
506         return err;
507 }
508
509 static int __exit vi_remove(struct platform_device *dev)
510 {
511 #ifdef CONFIG_TEGRA_CAMERA
512         int err = 0;
513 #endif
514         struct nvhost_device_data *pdata = platform_get_drvdata(dev);
515         struct vi *tegra_vi = (struct vi *)pdata->private_data;
516
517 #ifdef CONFIG_PM
518         if (atomic_read(&dev->dev.power.usage_count) > 0)
519                 return -EBUSY;
520 #endif
521
522         dev_info(&dev->dev, "%s: ++\n", __func__);
523
524 #if defined(CONFIG_TEGRA_ISOMGR)
525         if (tegra_vi->isomgr_handle)
526                 vi_isomgr_unregister(tegra_vi);
527 #endif
528
529         tegra_vi_deinit_mfi(&tegra_vi->mfi_ctx);
530
531         vi_remove_debugfs(tegra_vi);
532
533         tegra_vi_media_controller_cleanup(&tegra_vi->mc_vi);
534
535         nvhost_client_device_release(dev);
536
537         if (pdata->slcg_notifier_enable &&
538             (pdata->powergate_id != -1))
539                 slcg_unregister_notifier(pdata->powergate_id,
540                                          &pdata->toggle_slcg_notifier);
541
542         vi_intr_free(tegra_vi);
543
544         pdata->aperture[0] = NULL;
545 #ifdef CONFIG_TEGRA_CAMERA
546         err = tegra_camera_unregister(tegra_vi->camera);
547         if (err)
548                 return err;
549 #endif
550
551 #ifdef CONFIG_PM_GENERIC_DOMAINS
552         tegra_pd_remove_device(&dev->dev);
553 #endif
554
555         regulator_put(tegra_vi->reg);
556         tegra_vi->reg = NULL;
557
558         /* Remove I2C Devices according to settings from board file */
559         if (i2c_ctrl && i2c_ctrl->remove_devices)
560                 i2c_ctrl->remove_devices(dev);
561
562         pdata->private_data = i2c_ctrl;
563
564         return 0;
565 }
566
567 static struct platform_driver vi_driver = {
568         .probe = vi_probe,
569         .remove = __exit_p(vi_remove),
570         .driver = {
571                 .owner = THIS_MODULE,
572                 .name = "vi",
573 #ifdef CONFIG_PM
574                 .pm = &nvhost_module_pm_ops,
575 #endif
576 #ifdef CONFIG_OF
577                 .of_match_table = tegra_vi_of_match,
578 #endif
579         }
580 };
581
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},
585         {},
586 };
587
588 static int __init vi_init(void)
589 {
590         int ret;
591
592         ret = nvhost_domain_init(tegra_vi_domain_match);
593         if (ret)
594                 return ret;
595
596         return platform_driver_register(&vi_driver);
597 }
598
599 static void __exit vi_exit(void)
600 {
601         platform_driver_unregister(&vi_driver);
602 }
603
604 late_initcall(vi_init);
605 module_exit(vi_exit);
606 MODULE_LICENSE("GPL v2");