aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/tegra/tegra_camera.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/tegra/tegra_camera.c')
-rw-r--r--drivers/media/video/tegra/tegra_camera.c612
1 files changed, 612 insertions, 0 deletions
diff --git a/drivers/media/video/tegra/tegra_camera.c b/drivers/media/video/tegra/tegra_camera.c
new file mode 100644
index 00000000000..e90b130bcd6
--- /dev/null
+++ b/drivers/media/video/tegra/tegra_camera.c
@@ -0,0 +1,612 @@
1/*
2 * drivers/media/video/tegra/tegra_camera.c
3 *
4 * Copyright (C) 2010 Google, Inc.
5 * Copyright (C) 2012 Nvidia Corp
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
18#include <linux/miscdevice.h>
19#include <linux/platform_device.h>
20#include <linux/ioctl.h>
21#include <linux/fs.h>
22#include <linux/device.h>
23#include <linux/regulator/consumer.h>
24#include <linux/clk.h>
25#include <linux/io.h>
26#include <linux/uaccess.h>
27#include <linux/delay.h>
28#include <mach/iomap.h>
29#include <mach/clk.h>
30#include <mach/powergate.h>
31
32#include <media/tegra_camera.h>
33
34/* Eventually this should handle all clock and reset calls for the isp, vi,
35 * vi_sensor, and csi modules, replacing nvrm and nvos completely for camera
36 */
37#define TEGRA_CAMERA_NAME "tegra_camera"
38
39struct tegra_camera_dev {
40 struct device *dev;
41 struct miscdevice misc_dev;
42 struct clk *isp_clk;
43 struct clk *vi_clk;
44 struct clk *vi_sensor_clk;
45 struct clk *csus_clk;
46 struct clk *csi_clk;
47 struct clk *emc_clk;
48 struct regulator *reg;
49 struct tegra_camera_clk_info info;
50 struct mutex tegra_camera_lock;
51 int power_refcnt;
52};
53
54struct tegra_camera_block {
55 int (*enable) (struct tegra_camera_dev *dev);
56 int (*disable) (struct tegra_camera_dev *dev);
57 bool is_enabled;
58};
59
60static int tegra_camera_enable_isp(struct tegra_camera_dev *dev)
61{
62 return clk_enable(dev->isp_clk);
63}
64
65static int tegra_camera_disable_isp(struct tegra_camera_dev *dev)
66{
67 clk_disable(dev->isp_clk);
68 return 0;
69}
70
71static int tegra_camera_enable_vi(struct tegra_camera_dev *dev)
72{
73 int ret = 0;
74
75 ret |= clk_enable(dev->vi_clk);
76 ret |= clk_enable(dev->vi_sensor_clk);
77 ret |= clk_enable(dev->csus_clk);
78 return ret;
79}
80
81static int tegra_camera_disable_vi(struct tegra_camera_dev *dev)
82{
83 clk_disable(dev->vi_clk);
84 clk_disable(dev->vi_sensor_clk);
85 clk_disable(dev->csus_clk);
86 return 0;
87}
88
89static int tegra_camera_enable_csi(struct tegra_camera_dev *dev)
90{
91 return clk_enable(dev->csi_clk);
92}
93
94static int tegra_camera_disable_csi(struct tegra_camera_dev *dev)
95{
96 clk_disable(dev->csi_clk);
97 return 0;
98}
99
100static int tegra_camera_enable_emc(struct tegra_camera_dev *dev)
101{
102 /* tegra_camera wasn't added as a user of emc_clk until 3x.
103 set to 150 MHz, will likely need to be increased as we support
104 sensors with higher framerates and resolutions. */
105 clk_enable(dev->emc_clk);
106#ifdef CONFIG_ARCH_TEGRA_2x_SOC
107 clk_set_rate(dev->emc_clk, 300000000);
108#else
109 clk_set_rate(dev->emc_clk, 150000000);
110#endif
111 return 0;
112}
113
114static int tegra_camera_disable_emc(struct tegra_camera_dev *dev)
115{
116 clk_disable(dev->emc_clk);
117 return 0;
118}
119
120struct tegra_camera_block tegra_camera_block[] = {
121 [TEGRA_CAMERA_MODULE_ISP] = {tegra_camera_enable_isp,
122 tegra_camera_disable_isp, false},
123 [TEGRA_CAMERA_MODULE_VI] = {tegra_camera_enable_vi,
124 tegra_camera_disable_vi, false},
125 [TEGRA_CAMERA_MODULE_CSI] = {tegra_camera_enable_csi,
126 tegra_camera_disable_csi, false},
127};
128
129#define TEGRA_CAMERA_VI_CLK_SEL_INTERNAL 0
130#define TEGRA_CAMERA_VI_CLK_SEL_EXTERNAL (1<<24)
131#define TEGRA_CAMERA_PD2VI_CLK_SEL_VI_SENSOR_CLK (1<<25)
132#define TEGRA_CAMERA_PD2VI_CLK_SEL_PD2VI_CLK 0
133
134static bool tegra_camera_enabled(struct tegra_camera_dev *dev)
135{
136 bool ret = false;
137
138 mutex_lock(&dev->tegra_camera_lock);
139 ret = tegra_camera_block[TEGRA_CAMERA_MODULE_ISP].is_enabled == true ||
140 tegra_camera_block[TEGRA_CAMERA_MODULE_VI].is_enabled == true ||
141 tegra_camera_block[TEGRA_CAMERA_MODULE_CSI].is_enabled == true;
142 mutex_unlock(&dev->tegra_camera_lock);
143 return ret;
144}
145
146static int tegra_camera_clk_set_rate(struct tegra_camera_dev *dev)
147{
148 struct clk *clk, *clk_parent;
149 struct tegra_camera_clk_info *info = &dev->info;
150 unsigned long parent_rate, parent_div_rate, parent_div_rate_pre;
151
152 if (!info) {
153 dev_err(dev->dev,
154 "%s: no clock info %d\n",
155 __func__, info->id);
156 return -EINVAL;
157 }
158
159 if (info->id != TEGRA_CAMERA_MODULE_VI) {
160 dev_err(dev->dev,
161 "%s: set rate only aplies to vi module %d\n",
162 __func__, info->id);
163 return -EINVAL;
164 }
165
166 switch (info->clk_id) {
167 case TEGRA_CAMERA_VI_CLK:
168 clk = dev->vi_clk;
169 break;
170 case TEGRA_CAMERA_VI_SENSOR_CLK:
171 clk = dev->vi_sensor_clk;
172 break;
173 default:
174 dev_err(dev->dev,
175 "%s: invalid clk id for set rate %d\n",
176 __func__, info->clk_id);
177 return -EINVAL;
178 }
179
180 clk_parent = clk_get_parent(clk);
181 parent_rate = clk_get_rate(clk_parent);
182 dev_dbg(dev->dev, "%s: clk_id=%d, parent_rate=%lu, clk_rate=%lu\n",
183 __func__, info->clk_id, parent_rate, info->rate);
184 parent_div_rate = parent_rate;
185 parent_div_rate_pre = parent_rate;
186
187 /*
188 * The requested clock rate from user space should be respected.
189 * This loop is to search the clock rate that is higher than requested
190 * clock.
191 */
192 while (parent_div_rate >= info->rate) {
193 parent_div_rate_pre = parent_div_rate;
194 parent_div_rate = clk_round_rate(clk, parent_div_rate-1);
195 }
196
197 dev_dbg(dev->dev, "%s: set_rate=%lu",
198 __func__, parent_div_rate_pre);
199
200 clk_set_rate(clk, parent_div_rate_pre);
201
202 if (info->clk_id == TEGRA_CAMERA_VI_CLK) {
203 /*
204 * bit 25: 0 = pd2vi_Clk, 1 = vi_sensor_clk
205 * bit 24: 0 = internal clock, 1 = external clock(pd2vi_clk)
206 */
207 if (info->flag == TEGRA_CAMERA_ENABLE_PD2VI_CLK)
208 tegra_clk_cfg_ex(clk, TEGRA_CLK_VI_INP_SEL, 2);
209
210#ifdef CONFIG_ARCH_TEGRA_2x_SOC
211 u32 val;
212 void __iomem *apb_misc = IO_ADDRESS(TEGRA_APB_MISC_BASE);
213 val = readl(apb_misc + 0x42c);
214 writel(val | 0x1, apb_misc + 0x42c);
215#endif
216 }
217
218 info->rate = clk_get_rate(clk);
219 dev_dbg(dev->dev, "%s: get_rate=%lu",
220 __func__, info->rate);
221 return 0;
222
223}
224static int tegra_camera_reset(struct tegra_camera_dev *dev, uint id)
225{
226 struct clk *clk;
227
228 switch (id) {
229 case TEGRA_CAMERA_MODULE_VI:
230 clk = dev->vi_clk;
231 break;
232 case TEGRA_CAMERA_MODULE_ISP:
233 clk = dev->isp_clk;
234 break;
235 case TEGRA_CAMERA_MODULE_CSI:
236 clk = dev->csi_clk;
237 break;
238 default:
239 return -EINVAL;
240 }
241 tegra_periph_reset_assert(clk);
242 udelay(10);
243 tegra_periph_reset_deassert(clk);
244
245 return 0;
246}
247
248static int tegra_camera_power_on(struct tegra_camera_dev *dev)
249{
250 int ret = 0;
251
252 if (dev->power_refcnt++ == 0) {
253 /* Enable external power */
254 if (dev->reg) {
255 ret = regulator_enable(dev->reg);
256 if (ret) {
257 dev_err(dev->dev,
258 "%s: enable csi regulator failed.\n",
259 __func__);
260 return ret;
261 }
262 }
263#ifndef CONFIG_ARCH_TEGRA_2x_SOC
264 /* Unpowergate VE */
265 ret = tegra_unpowergate_partition(TEGRA_POWERGATE_VENC);
266 if (ret)
267 dev_err(dev->dev,
268 "%s: unpowergate failed.\n",
269 __func__);
270#endif
271 }
272
273 return ret;
274}
275
276static int tegra_camera_power_off(struct tegra_camera_dev *dev)
277{
278 int ret = 0;
279
280 if (--dev->power_refcnt == 0) {
281#ifndef CONFIG_ARCH_TEGRA_2x_SOC
282 /* Powergate VE */
283 ret = tegra_powergate_partition(TEGRA_POWERGATE_VENC);
284 if (ret)
285 dev_err(dev->dev,
286 "%s: powergate failed.\n",
287 __func__);
288#endif
289 /* Disable external power */
290 if (dev->reg) {
291 ret = regulator_disable(dev->reg);
292 if (ret) {
293 dev_err(dev->dev,
294 "%s: disable csi regulator failed.\n",
295 __func__);
296 return ret;
297 }
298 }
299 }
300 return ret;
301}
302
303static long tegra_camera_ioctl(struct file *file,
304 unsigned int cmd, unsigned long arg)
305{
306 uint id;
307 struct tegra_camera_dev *dev = file->private_data;
308
309 /* first element of arg must be u32 with id of module to talk to */
310 if (copy_from_user(&id, (const void __user *)arg, sizeof(uint))) {
311 dev_err(dev->dev,
312 "%s: Failed to copy arg from user", __func__);
313 return -EFAULT;
314 }
315
316 if (id >= ARRAY_SIZE(tegra_camera_block)) {
317 dev_err(dev->dev,
318 "%s: Invalid id to tegra isp ioctl%d\n",
319 __func__, id);
320 return -EINVAL;
321 }
322
323 switch (cmd) {
324 case TEGRA_CAMERA_IOCTL_ENABLE:
325 {
326 int ret = 0;
327
328 mutex_lock(&dev->tegra_camera_lock);
329 /* Unpowergate camera blocks (vi, csi and isp)
330 before enabling clocks */
331 ret = tegra_camera_power_on(dev);
332 if (ret) {
333 dev->power_refcnt = 0;
334 mutex_unlock(&dev->tegra_camera_lock);
335 return ret;
336 }
337
338 if (!tegra_camera_block[id].is_enabled) {
339 ret = tegra_camera_block[id].enable(dev);
340 tegra_camera_block[id].is_enabled = true;
341 }
342 mutex_unlock(&dev->tegra_camera_lock);
343 return ret;
344 }
345 case TEGRA_CAMERA_IOCTL_DISABLE:
346 {
347 int ret = 0;
348
349 mutex_lock(&dev->tegra_camera_lock);
350 if (tegra_camera_block[id].is_enabled) {
351 ret = tegra_camera_block[id].disable(dev);
352 tegra_camera_block[id].is_enabled = false;
353 }
354 /* Powergate camera blocks (vi, csi and isp)
355 after disabling all the clocks */
356 if (!ret) {
357 ret = tegra_camera_power_off(dev);
358 }
359 mutex_unlock(&dev->tegra_camera_lock);
360 return ret;
361 }
362 case TEGRA_CAMERA_IOCTL_CLK_SET_RATE:
363 {
364 int ret;
365
366 if (copy_from_user(&dev->info, (const void __user *)arg,
367 sizeof(struct tegra_camera_clk_info))) {
368 dev_err(dev->dev,
369 "%s: Failed to copy arg from user\n", __func__);
370 return -EFAULT;
371 }
372 ret = tegra_camera_clk_set_rate(dev);
373 if (ret)
374 return ret;
375 if (copy_to_user((void __user *)arg, &dev->info,
376 sizeof(struct tegra_camera_clk_info))) {
377 dev_err(dev->dev,
378 "%s: Failed to copy arg to user\n", __func__);
379 return -EFAULT;
380 }
381 return 0;
382 }
383 case TEGRA_CAMERA_IOCTL_RESET:
384 return tegra_camera_reset(dev, id);
385 default:
386 dev_err(dev->dev,
387 "%s: Unknown tegra_camera ioctl.\n", __func__);
388 return -EINVAL;
389 }
390 return 0;
391}
392
393static int tegra_camera_open(struct inode *inode, struct file *file)
394{
395 struct miscdevice *miscdev = file->private_data;
396 struct tegra_camera_dev *dev = container_of(miscdev,
397 struct tegra_camera_dev,
398 misc_dev);
399 dev_info(dev->dev, "%s\n", __func__);
400 file->private_data = dev;
401
402 tegra_camera_enable_emc(dev);
403
404 return 0;
405}
406
407static int tegra_camera_release(struct inode *inode, struct file *file)
408{
409 int i, err;
410 struct tegra_camera_dev *dev = file->private_data;
411
412 dev_info(dev->dev, "%s\n", __func__);
413 for (i = 0; i < ARRAY_SIZE(tegra_camera_block); i++)
414 if (tegra_camera_block[i].is_enabled) {
415 tegra_camera_block[i].disable(dev);
416 tegra_camera_block[i].is_enabled = false;
417 }
418
419 /* If camera blocks are not powergated yet, do it now */
420 if (dev->power_refcnt > 0) {
421 mutex_lock(&dev->tegra_camera_lock);
422#ifndef CONFIG_ARCH_TEGRA_2x_SOC
423 err = tegra_powergate_partition(TEGRA_POWERGATE_VENC);
424 if (err)
425 dev_err(dev->dev, "%s: powergate failed.\n", __func__);
426#endif
427 dev->power_refcnt = 0;
428 mutex_unlock(&dev->tegra_camera_lock);
429 }
430
431 tegra_camera_disable_emc(dev);
432
433 return 0;
434}
435
436static const struct file_operations tegra_camera_fops = {
437 .owner = THIS_MODULE,
438 .open = tegra_camera_open,
439 .unlocked_ioctl = tegra_camera_ioctl,
440 .release = tegra_camera_release,
441};
442
443static int tegra_camera_clk_get(struct platform_device *pdev, const char *name,
444 struct clk **clk)
445{
446 *clk = clk_get(&pdev->dev, name);
447 if (IS_ERR_OR_NULL(*clk)) {
448 dev_err(&pdev->dev, "%s: unable to get clock for %s\n",
449 __func__, name);
450 *clk = NULL;
451 return PTR_ERR(*clk);
452 }
453 return 0;
454}
455
456static int tegra_camera_probe(struct platform_device *pdev)
457{
458 int err;
459 struct tegra_camera_dev *dev;
460
461 dev_info(&pdev->dev, "%s\n", __func__);
462 dev = devm_kzalloc(&pdev->dev, sizeof(struct tegra_camera_dev),
463 GFP_KERNEL);
464 if (!dev) {
465 err = -ENOMEM;
466 dev_err(&pdev->dev, "%s: unable to allocate memory\n",
467 __func__);
468 goto alloc_err;
469 }
470
471 mutex_init(&dev->tegra_camera_lock);
472
473 /* Powergate VE when boot */
474 mutex_lock(&dev->tegra_camera_lock);
475 dev->power_refcnt = 0;
476#ifndef CONFIG_ARCH_TEGRA_2x_SOC
477 err = tegra_powergate_partition(TEGRA_POWERGATE_VENC);
478 if (err)
479 dev_err(&pdev->dev, "%s: powergate failed.\n", __func__);
480#endif
481 mutex_unlock(&dev->tegra_camera_lock);
482
483 dev->dev = &pdev->dev;
484
485 /* Get regulator pointer */
486#ifdef CONFIG_ARCH_TEGRA_2x_SOC
487 dev->reg = regulator_get(&pdev->dev, "vcsi");
488#else
489 dev->reg = regulator_get(&pdev->dev, "avdd_dsi_csi");
490#endif
491 if (IS_ERR_OR_NULL(dev->reg)) {
492 if (dev->reg == ERR_PTR(-ENODEV)) {
493 dev->reg = NULL;
494 dev_info(&pdev->dev, "%s: no regulator device, overriding\n",
495 __func__);
496 } else {
497 dev_err(&pdev->dev, "%s: couldn't get regulator\n",
498 __func__);
499 return PTR_ERR(dev->reg);
500 }
501 }
502
503 dev->misc_dev.minor = MISC_DYNAMIC_MINOR;
504 dev->misc_dev.name = TEGRA_CAMERA_NAME;
505 dev->misc_dev.fops = &tegra_camera_fops;
506 dev->misc_dev.parent = &pdev->dev;
507
508 err = misc_register(&dev->misc_dev);
509 if (err) {
510 dev_err(&pdev->dev, "%s: Unable to register misc device!\n",
511 TEGRA_CAMERA_NAME);
512 goto misc_register_err;
513 }
514
515 err = tegra_camera_clk_get(pdev, "isp", &dev->isp_clk);
516 if (err)
517 goto misc_register_err;
518 err = tegra_camera_clk_get(pdev, "vi", &dev->vi_clk);
519 if (err)
520 goto vi_clk_get_err;
521 err = tegra_camera_clk_get(pdev, "vi_sensor", &dev->vi_sensor_clk);
522 if (err)
523 goto vi_sensor_clk_get_err;
524 err = tegra_camera_clk_get(pdev, "csus", &dev->csus_clk);
525 if (err)
526 goto csus_clk_get_err;
527 err = tegra_camera_clk_get(pdev, "csi", &dev->csi_clk);
528 if (err)
529 goto csi_clk_get_err;
530 err = tegra_camera_clk_get(pdev, "emc", &dev->emc_clk);
531 if (err)
532 goto emc_clk_get_err;
533
534 /* dev is set in order to restore in _remove */
535 platform_set_drvdata(pdev, dev);
536
537 return 0;
538
539emc_clk_get_err:
540 clk_put(dev->emc_clk);
541csi_clk_get_err:
542 clk_put(dev->csus_clk);
543csus_clk_get_err:
544 clk_put(dev->vi_sensor_clk);
545vi_sensor_clk_get_err:
546 clk_put(dev->vi_clk);
547vi_clk_get_err:
548 clk_put(dev->isp_clk);
549misc_register_err:
550 regulator_put(dev->reg);
551alloc_err:
552 return err;
553}
554
555static int tegra_camera_remove(struct platform_device *pdev)
556{
557 struct tegra_camera_dev *dev = platform_get_drvdata(pdev);
558
559 clk_put(dev->isp_clk);
560 clk_put(dev->vi_clk);
561 clk_put(dev->vi_sensor_clk);
562 clk_put(dev->csus_clk);
563 clk_put(dev->csi_clk);
564
565 misc_deregister(&dev->misc_dev);
566 regulator_put(dev->reg);
567 mutex_destroy(&dev->tegra_camera_lock);
568
569 return 0;
570}
571
572static int tegra_camera_suspend(struct platform_device *pdev, pm_message_t state)
573{
574 struct tegra_camera_dev *dev = platform_get_drvdata(pdev);
575 int ret = 0;
576
577 if (tegra_camera_enabled(dev)) {
578 ret = -EBUSY;
579 dev_err(&pdev->dev,
580 "tegra_camera cannot suspend, "
581 "application is holding on to camera. \n");
582 }
583
584 return ret;
585}
586
587static int tegra_camera_resume(struct platform_device *pdev)
588{
589 return 0;
590}
591
592static struct platform_driver tegra_camera_driver = {
593 .probe = tegra_camera_probe,
594 .remove = tegra_camera_remove,
595 .suspend = tegra_camera_suspend,
596 .resume = tegra_camera_resume,
597 .driver = { .name = TEGRA_CAMERA_NAME }
598};
599
600static int __init tegra_camera_init(void)
601{
602 return platform_driver_register(&tegra_camera_driver);
603}
604
605static void __exit tegra_camera_exit(void)
606{
607 platform_driver_unregister(&tegra_camera_driver);
608}
609
610module_init(tegra_camera_init);
611module_exit(tegra_camera_exit);
612