]> nv-tegra.nvidia Code Review - linux-3.10.git/blob - drivers/video/tegra/host/vi/tegra_vi.c
platform: tegra: mc: Centralize header files
[linux-3.10.git] / drivers / video / tegra / host / vi / tegra_vi.c
1 /*
2  * Copyright (c) 2013-2015, NVIDIA CORPORATION. All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms and conditions of the GNU General Public License,
6  * version 2, as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope it will be useful, but WITHOUT
9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
11  * more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15  */
16
17 #include <linux/fs.h>
18 #include <linux/file.h>
19 #include <linux/delay.h>
20 #include <linux/module.h>
21 #include <linux/nvhost.h>
22 #include <linux/nvhost_vi_ioctl.h>
23 #include <linux/platform_device.h>
24 #include <linux/regulator/consumer.h>
25
26 #include <asm/uaccess.h>
27
28 #include <mach/clk.h>
29 #include <linux/platform/tegra/latency_allowance.h>
30
31 #include "bus_client.h"
32 #include "nvhost_acm.h"
33 #include "chip_support.h"
34 #include "host1x/host1x.h"
35 #include "vi.h"
36 #include "vi_irq.h"
37
38 static DEFINE_MUTEX(la_lock);
39
40 #define T12_VI_CFG_CG_CTRL      0xb8
41 #define T12_CG_2ND_LEVEL_EN     1
42 #define T12_VI_CSI_0_SW_RESET   0x100
43 #define T12_CSI_CSI_SW_SENSOR_A_RESET 0x858
44 #define T12_CSI_CSICIL_SW_SENSOR_A_RESET 0x94c
45 #define T12_VI_CSI_0_CSI_IMAGE_DT 0x120
46
47 #define T12_VI_CSI_1_SW_RESET   0x200
48 #define T12_CSI_CSI_SW_SENSOR_B_RESET 0x88c
49 #define T12_CSI_CSICIL_SW_SENSOR_B_RESET 0x980
50 #define T12_VI_CSI_1_CSI_IMAGE_DT 0x220
51
52 #define T21_CSI_CILA_PAD_CONFIG0 0x92c
53 #define T21_CSI1_CILA_PAD_CONFIG0 0x112c
54 #define T21_CSI2_CILA_PAD_CONFIG0 0x192c
55
56 #define VI_MAX_BPP 2
57
58 int nvhost_vi_finalize_poweron(struct platform_device *dev)
59 {
60         int ret = 0;
61         struct vi *tegra_vi;
62
63         tegra_vi = (struct vi *)nvhost_get_private_data(dev);
64
65         if (tegra_vi && tegra_vi->reg) {
66                 ret = regulator_enable(tegra_vi->reg);
67                 if (ret) {
68                         dev_err(&dev->dev,
69                                         "%s: enable csi regulator failed.\n",
70                                         __func__);
71                         goto fail;
72                 }
73         }
74
75 #ifdef CONFIG_ARCH_TEGRA_12x_SOC
76         /* Only do this for vi.0 not for slave device vi.1 */
77         if (dev->id == 0)
78                 host1x_writel(dev, T12_VI_CFG_CG_CTRL, T12_CG_2ND_LEVEL_EN);
79 #endif
80
81 #ifdef CONFIG_ARCH_TEGRA_21x_SOC
82         {
83                 void __iomem *reset_reg[3];
84                 struct nvhost_device_data *pdata = dev->dev.platform_data;
85
86                 reset_reg[0] = pdata->aperture[0] +
87                                T21_CSI_CILA_PAD_CONFIG0;
88                 reset_reg[1] = pdata->aperture[0] +
89                                T21_CSI1_CILA_PAD_CONFIG0;
90                 reset_reg[2] = pdata->aperture[0] +
91                                T21_CSI2_CILA_PAD_CONFIG0;
92
93                 writel(readl(reset_reg[0]) & 0xfffcffff, reset_reg[0]);
94                 writel(readl(reset_reg[1]) & 0xfffcffff, reset_reg[1]);
95                 writel(readl(reset_reg[2]) & 0xfffcffff, reset_reg[2]);
96         }
97 #endif
98
99 fail:
100         return ret;
101 }
102
103 int nvhost_vi_prepare_poweroff(struct platform_device *dev)
104 {
105         int ret = 0;
106         struct vi *tegra_vi;
107         tegra_vi = (struct vi *)nvhost_get_private_data(dev);
108
109         if (tegra_vi && tegra_vi->reg) {
110                 ret = regulator_disable(tegra_vi->reg);
111                 if (ret) {
112                         dev_err(&dev->dev,
113                                 "%s: disable csi regulator failed.\n",
114                                 __func__);
115                         goto fail;
116                 }
117         }
118 fail:
119         return ret;
120 }
121
122 #if defined(CONFIG_TEGRA_ISOMGR)
123 static int vi_isomgr_register(struct vi *tegra_vi)
124 {
125         int iso_client_id = TEGRA_ISO_CLIENT_VI_0;
126         struct clk *vi_clk;
127         unsigned long max_bw = 0;
128         struct nvhost_device_data *pdata =
129                                 platform_get_drvdata(tegra_vi->ndev);
130
131         dev_dbg(&tegra_vi->ndev->dev, "%s++\n", __func__);
132
133         if (WARN_ONCE(pdata == NULL, "pdata not found, %s failed\n", __func__))
134                 return -ENODEV;
135
136         if (tegra_vi->ndev->id)
137                 iso_client_id = TEGRA_ISO_CLIENT_VI_1;
138
139         /* Get max VI BW */
140         vi_clk = pdata->clk[0];
141         max_bw = (clk_round_rate(vi_clk, UINT_MAX) / 1000) * VI_MAX_BPP;
142
143         /* Register with max possible BW in VI usecases.*/
144         tegra_vi->isomgr_handle = tegra_isomgr_register(iso_client_id,
145                                         max_bw,
146                                         NULL,   /* tegra_isomgr_renegotiate */
147                                         NULL);  /* *priv */
148
149         if (!tegra_vi->isomgr_handle) {
150                 dev_err(&tegra_vi->ndev->dev, "%s: unable to register isomgr\n",
151                                         __func__);
152                 return -ENOMEM;
153         }
154
155         return 0;
156 }
157
158 static int vi_set_isomgr_request(struct vi *tegra_vi, uint vi_bw, uint lt)
159 {
160         int ret = 0;
161
162         dev_dbg(&tegra_vi->ndev->dev,
163                 "%s++ bw=%u, lt=%u\n", __func__, vi_bw, lt);
164
165         /* return value of tegra_isomgr_reserve is dvfs latency in usec */
166         ret = tegra_isomgr_reserve(tegra_vi->isomgr_handle,
167                                 vi_bw,  /* KB/sec */
168                                 lt);    /* usec */
169         if (!ret) {
170                 dev_err(&tegra_vi->ndev->dev,
171                 "%s: failed to reserve %u KBps\n", __func__, vi_bw);
172                 return -ENOMEM;
173         }
174
175         /* return value of tegra_isomgr_realize is dvfs latency in usec */
176         ret = tegra_isomgr_realize(tegra_vi->isomgr_handle);
177         if (ret)
178                 dev_dbg(&tegra_vi->ndev->dev,
179                 "%s: tegra_vi isomgr latency is %d usec",
180                 __func__, ret);
181         else {
182                 dev_err(&tegra_vi->ndev->dev,
183                 "%s: failed to realize %u KBps\n", __func__, vi_bw);
184                         return -ENOMEM;
185         }
186         return 0;
187 }
188
189 static int vi_isomgr_release(struct vi *tegra_vi)
190 {
191         int ret = 0;
192         dev_dbg(&tegra_vi->ndev->dev, "%s++\n", __func__);
193
194         /* deallocate isomgr bw */
195         ret = vi_set_isomgr_request(tegra_vi, 0, 0);
196         if (ret) {
197                 dev_err(&tegra_vi->ndev->dev,
198                 "%s: failed to deallocate memory in isomgr\n",
199                 __func__);
200                 return -ENOMEM;
201         }
202
203         return 0;
204 }
205 #endif
206
207 static int vi_set_la(struct vi *tegra_vi1, uint vi_bw)
208 {
209         struct nvhost_device_data *pdata_vi1, *pdata_vi2;
210         struct vi *tegra_vi2;
211         struct clk *clk_vi;
212         int ret = 0;
213         uint total_vi_bw;
214
215         pdata_vi1 =
216                 (struct nvhost_device_data *)tegra_vi1->ndev->dev.platform_data;
217
218         if (!pdata_vi1)
219                 return -ENODEV;
220
221         /* Copy device data for other vi device */
222         mutex_lock(&la_lock);
223
224         tegra_vi1->vi_bw = vi_bw / 1000;
225         total_vi_bw = tegra_vi1->vi_bw;
226         if (pdata_vi1->master)
227                 pdata_vi2 = (struct nvhost_device_data *)
228                         pdata_vi1->master->dev.platform_data;
229         else
230                 pdata_vi2 = (struct nvhost_device_data *)
231                         pdata_vi1->slave->dev.platform_data;
232
233         if (!pdata_vi2) {
234                 mutex_unlock(&la_lock);
235                 return -ENODEV;
236         }
237
238         tegra_vi2 = (struct vi *)pdata_vi2->private_data;
239
240         if (!tegra_vi2) {
241                 mutex_unlock(&la_lock);
242                 return -ENODATA;
243         }
244
245         clk_vi = clk_get(&tegra_vi2->ndev->dev, "emc");
246         if (tegra_is_clk_enabled(clk_vi))
247                 total_vi_bw += tegra_vi2->vi_bw;
248
249         mutex_unlock(&la_lock);
250
251 #ifdef CONFIG_TEGRA_MC
252         ret = tegra_set_camera_ptsa(TEGRA_LA_VI_W, total_vi_bw, 1);
253
254         if (!ret) {
255                 ret = tegra_set_latency_allowance(TEGRA_LA_VI_W,
256                         total_vi_bw);
257
258                 if (ret)
259                         pr_err("%s: set latency failed: %d\n",
260                                 __func__, ret);
261         } else {
262                 pr_err("%s: set ptsa failed: %d\n", __func__, ret);
263         }
264 #endif
265
266         return ret;
267 }
268
269 static long vi_ioctl(struct file *file,
270                 unsigned int cmd, unsigned long arg)
271 {
272         struct vi *tegra_vi = file->private_data;
273
274         if (_IOC_TYPE(cmd) != NVHOST_VI_IOCTL_MAGIC)
275                 return -EFAULT;
276
277         switch (cmd) {
278         case NVHOST_VI_IOCTL_ENABLE_TPG: {
279                 uint enable;
280                 int ret;
281                 struct clk *clk;
282
283                 if (copy_from_user(&enable,
284                         (const void __user *)arg, sizeof(uint))) {
285                         dev_err(&tegra_vi->ndev->dev,
286                                 "%s: Failed to copy arg from user\n", __func__);
287                         return -EFAULT;
288                 }
289
290                 clk = clk_get(&tegra_vi->ndev->dev, "pll_d");
291                 if (IS_ERR(clk))
292                         return -EINVAL;
293
294                 if (enable)
295                         ret = tegra_clk_cfg_ex(clk,
296                                 TEGRA_CLK_PLLD_CSI_OUT_ENB, 1);
297                 else
298                         ret = tegra_clk_cfg_ex(clk,
299                                 TEGRA_CLK_MIPI_CSI_OUT_ENB, 1);
300                 clk_put(clk);
301
302                 return ret;
303         }
304         case NVHOST_VI_IOCTL_SET_EMC_INFO: {
305                 uint vi_bw;
306                 int ret;
307                 if (copy_from_user(&vi_bw,
308                         (const void __user *)arg, sizeof(uint))) {
309                         dev_err(&tegra_vi->ndev->dev,
310                                 "%s: Failed to copy arg from user\n", __func__);
311                         return -EFAULT;
312                 }
313
314                 ret = vi_set_la(tegra_vi, vi_bw);
315                 if (ret) {
316                         dev_err(&tegra_vi->ndev->dev,
317                         "%s: failed to set la for vi_bw %u MBps\n",
318                         __func__, vi_bw/1000);
319                         return -ENOMEM;
320                 }
321
322 #if defined(CONFIG_TEGRA_ISOMGR)
323                 /*
324                  * Register VI as isomgr client.
325                  */
326                 if (!tegra_vi->isomgr_handle) {
327                         ret = vi_isomgr_register(tegra_vi);
328                         if (ret) {
329                                 dev_err(&tegra_vi->ndev->dev,
330                                 "%s: failed to register VI as isomgr client\n",
331                                 __func__);
332                                 return -ENOMEM;
333                         }
334                 }
335
336                 /*
337                  * Set VI ISO BW requirements.
338                  * There is no way to figure out what latency
339                  * can be tolerated in VI without reading VI
340                  * registers for now. 3 usec is minimum time
341                  * to switch PLL source. Let's put 4 usec as
342                  * latency for now.
343                  */
344                 ret = vi_set_isomgr_request(tegra_vi, vi_bw, 4);
345                 if (ret) {
346                         dev_err(&tegra_vi->ndev->dev,
347                         "%s: failed to reserve %u KBps\n",
348                         __func__, vi_bw);
349                         return -ENOMEM;
350                 }
351 #endif
352                 return ret;
353         }
354         case NVHOST_VI_IOCTL_SET_VI_CLK: {
355                 long vi_clk_rate = 0;
356
357                 if (copy_from_user(&vi_clk_rate,
358                         (const void __user *)arg, sizeof(long))) {
359                         dev_err(&tegra_vi->ndev->dev,
360                                 "%s: Failed to copy arg from user\n", __func__);
361                         return -EFAULT;
362                 }
363
364                 return nvhost_module_set_rate(tegra_vi->ndev,
365                                 tegra_vi, vi_clk_rate, 0, NVHOST_CLOCK);
366         }
367         default:
368                 dev_err(&tegra_vi->ndev->dev,
369                         "%s: Unknown vi ioctl.\n", __func__);
370                 return -EINVAL;
371         }
372         return 0;
373 }
374
375 static int vi_open(struct inode *inode, struct file *file)
376 {
377         struct nvhost_device_data *pdata;
378         struct vi *vi;
379         int err = 0;
380
381         pdata = container_of(inode->i_cdev,
382                 struct nvhost_device_data, ctrl_cdev);
383         if (WARN_ONCE(pdata == NULL, "pdata not found, %s failed\n", __func__))
384                 return -ENODEV;
385
386         vi = (struct vi *)pdata->private_data;
387         if (WARN_ONCE(vi == NULL, "vi not found, %s failed\n", __func__))
388                 return -ENODEV;
389
390         file->private_data = vi;
391
392         err = vi_enable_irq(vi);
393         if (err)
394                 dev_err(&vi->ndev->dev, "%s: vi_enable_irq failed\n", __func__);
395
396         /* add vi client to acm */
397         if (nvhost_module_add_client(vi->ndev, vi)) {
398                 dev_err(&vi->ndev->dev,
399                         "%s: failed add vi client\n",
400                         __func__);
401                 return -ENOMEM;
402         }
403
404         return err;
405 }
406
407 static int vi_release(struct inode *inode, struct file *file)
408 {
409         int ret = 0;
410         struct vi *tegra_vi = file->private_data;
411
412         ret = vi_disable_irq(tegra_vi);
413         if (ret) {
414                 dev_err(&tegra_vi->ndev->dev,
415                         "%s: vi_disable_irq failed\n",
416                         __func__);
417                 return ret;
418         }
419
420 #if defined(CONFIG_TEGRA_ISOMGR)
421         /* nullify isomgr request */
422         if (tegra_vi->isomgr_handle) {
423                 ret = vi_isomgr_release(tegra_vi);
424                 if (ret) {
425                         dev_err(&tegra_vi->ndev->dev,
426                         "%s: failed to deallocate memory in isomgr\n",
427                         __func__);
428                         return -ENOMEM;
429                 }
430         }
431 #endif
432
433         /* remove vi client from acm */
434         nvhost_module_remove_client(tegra_vi->ndev, tegra_vi);
435
436         return ret;
437 }
438
439 const struct file_operations tegra_vi_ctrl_ops = {
440         .owner = THIS_MODULE,
441         .open = vi_open,
442         .unlocked_ioctl = vi_ioctl,
443 #ifdef CONFIG_COMPAT
444         .compat_ioctl = vi_ioctl,
445 #endif
446         .release = vi_release,
447 };
448
449 /* Reset sensor data if respective clk is ON */
450 void nvhost_vi_reset_all(struct platform_device *pdev)
451 {
452         void __iomem *reset_reg[4];
453         int err;
454         bool enabled = false;
455         struct nvhost_device_data *pdata = pdev->dev.platform_data;
456         struct clk *clk;
457
458         err = nvhost_clk_get(pdev, "cilab", &clk);
459         if (!err && tegra_is_clk_enabled(clk)) {
460                 reset_reg[0] = pdata->aperture[0] +
461                         T12_VI_CSI_0_SW_RESET;
462                 reset_reg[1] = pdata->aperture[0] +
463                         T12_CSI_CSI_SW_SENSOR_A_RESET;
464                 reset_reg[2] = pdata->aperture[0] +
465                         T12_CSI_CSICIL_SW_SENSOR_A_RESET;
466                 reset_reg[3] = pdata->aperture[0] +
467                         T12_VI_CSI_0_CSI_IMAGE_DT;
468
469                 writel(0, reset_reg[3]);
470                 writel(0x1, reset_reg[2]);
471                 writel(0x1, reset_reg[1]);
472                 writel(0x1f, reset_reg[0]);
473
474                 udelay(10);
475
476                 writel(0, reset_reg[2]);
477                 writel(0, reset_reg[1]);
478         }
479
480         err = nvhost_clk_get(pdev, "cilcd", &clk);
481         if (!err && tegra_is_clk_enabled(clk))
482                 enabled = true;
483
484         err = nvhost_clk_get(pdev, "cile", &clk);
485         if (!err && tegra_is_clk_enabled(clk))
486                 enabled = true;
487
488         if (enabled) {
489                 reset_reg[0] = pdata->aperture[0] +
490                         T12_VI_CSI_1_SW_RESET;
491                 reset_reg[1] = pdata->aperture[0] +
492                         T12_CSI_CSI_SW_SENSOR_B_RESET;
493                 reset_reg[2] = pdata->aperture[0] +
494                         T12_CSI_CSICIL_SW_SENSOR_B_RESET;
495                 reset_reg[3] = pdata->aperture[0] +
496                         T12_VI_CSI_1_CSI_IMAGE_DT;
497
498                 writel(0, reset_reg[3]);
499                 writel(0x1, reset_reg[2]);
500                 writel(0x1, reset_reg[1]);
501                 writel(0x1f, reset_reg[0]);
502
503                 udelay(10);
504
505                 writel(0, reset_reg[2]);
506                 writel(0, reset_reg[1]);
507         }
508 }
509
510 void nvhost_vi_reset(struct platform_device *pdev)
511 {
512         void __iomem *reset_reg[4];
513         int i;
514         struct nvhost_device_data *pdata = pdev->dev.platform_data;
515
516         if (pdev->id == 0) {
517                 reset_reg[0] = pdata->aperture[0] +
518                                T12_VI_CSI_0_SW_RESET;
519                 reset_reg[1] = pdata->aperture[0] +
520                                T12_CSI_CSI_SW_SENSOR_A_RESET;
521                 reset_reg[2] = pdata->aperture[0] +
522                                T12_CSI_CSICIL_SW_SENSOR_A_RESET;
523                 reset_reg[3] = pdata->aperture[0] +
524                                T12_VI_CSI_0_CSI_IMAGE_DT;
525         } else {
526                 pdata = pdata->master->dev.platform_data;
527                 reset_reg[0] = pdata->aperture[0] +
528                                T12_VI_CSI_1_SW_RESET;
529                 reset_reg[1] = pdata->aperture[0] +
530                                T12_CSI_CSI_SW_SENSOR_B_RESET;
531                 reset_reg[2] = pdata->aperture[0] +
532                                T12_CSI_CSICIL_SW_SENSOR_B_RESET;
533                 reset_reg[3] = pdata->aperture[0] +
534                                T12_VI_CSI_1_CSI_IMAGE_DT;
535         }
536
537         writel(0, reset_reg[3]);
538         writel(0x1, reset_reg[2]);
539         writel(0x1, reset_reg[1]);
540         writel(0x1f, reset_reg[0]);
541
542         udelay(10);
543
544         for (i = 2; i > 0; i--)
545                 writel(0, reset_reg[i]);
546 }