video: tegra: host: make host1x client VI driver can be a module
[linux-3.10.git] / drivers / video / tegra / host / vi / vi.c
1 /*
2  * drivers/video/tegra/host/vi/vi.c
3  *
4  * Tegra Graphics Host VI
5  *
6  * Copyright (c) 2012-2013, 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/export.h>
22 #include <linux/module.h>
23 #include <linux/resource.h>
24 #include <linux/pm_runtime.h>
25 #include <linux/of.h>
26 #include <linux/of_device.h>
27 #include <linux/of_platform.h>
28 #include <linux/nvhost_vi_ioctl.h>
29
30 #include <mach/pm_domains.h>
31 #include <mach/clk.h>
32 #include <media/tegra_v4l2_camera.h>
33
34 #include "dev.h"
35 #include "bus_client.h"
36 #include "nvhost_acm.h"
37 #include "t20/t20.h"
38 #include "t30/t30.h"
39 #include "t114/t114.h"
40 #include "t148/t148.h"
41 #include "t124/t124.h"
42 #include "vi.h"
43
44 #define MAX_DEVID_LENGTH        16
45
46 static struct of_device_id tegra_vi_of_match[] = {
47 #ifdef TEGRA_2X_OR_HIGHER_CONFIG
48         { .compatible = "nvidia,tegra20-vi",
49                 .data = (struct nvhost_device_data *)&t20_vi_info },
50 #endif
51 #ifdef TEGRA_3X_OR_HIGHER_CONFIG
52         { .compatible = "nvidia,tegra30-vi",
53                 .data = (struct nvhost_device_data *)&t30_vi_info },
54 #endif
55 #ifdef TEGRA_11X_OR_HIGHER_CONFIG
56         { .compatible = "nvidia,tegra114-vi",
57                 .data = (struct nvhost_device_data *)&t11_vi_info },
58 #endif
59 #ifdef TEGRA_14X_OR_HIGHER_CONFIG
60         { .compatible = "nvidia,tegra148-vi",
61                 .data = (struct nvhost_device_data *)&t14_vi_info },
62 #endif
63 #ifdef TEGRA_12X_OR_HIGHER_CONFIG
64         { .compatible = "nvidia,tegra124-vi",
65                 .data = (struct nvhost_device_data *)&t124_vi_info },
66 #endif
67         { },
68 };
69
70 #ifdef CONFIG_PM_GENERIC_DOMAINS
71 static int vi_unpowergate(struct generic_pm_domain *domain)
72 {
73         struct nvhost_device_data *pdata;
74
75         pdata = container_of(domain, struct nvhost_device_data, pd);
76         return nvhost_module_power_on(pdata->pdev);
77 }
78
79 static int vi_powergate(struct generic_pm_domain *domain)
80 {
81         struct nvhost_device_data *pdata;
82
83         pdata = container_of(domain, struct nvhost_device_data, pd);
84         return nvhost_module_power_off(pdata->pdev);
85 }
86 #endif
87
88 static struct i2c_camera_ctrl *i2c_ctrl;
89
90 static int vi_probe(struct platform_device *dev)
91 {
92         int err = 0;
93         struct vi *tegra_vi;
94         struct nvhost_device_data *pdata = NULL;
95
96         if (dev->dev.of_node) {
97                 const struct of_device_id *match;
98
99                 match = of_match_device(tegra_vi_of_match, &dev->dev);
100                 if (match)
101                         pdata = (struct nvhost_device_data *)match->data;
102         } else
103                 pdata = (struct nvhost_device_data *)dev->dev.platform_data;
104
105         WARN_ON(!pdata);
106         if (!pdata) {
107                 dev_info(&dev->dev, "no platform data\n");
108                 return -ENODATA;
109         }
110
111         i2c_ctrl = pdata->private_data;
112
113         dev_info(&dev->dev, "%s: ++\n", __func__);
114
115         tegra_vi = kzalloc(sizeof(struct vi), GFP_KERNEL);
116         if (!tegra_vi) {
117                 dev_err(&dev->dev, "can't allocate memory for vi\n");
118                 return -ENOMEM;
119         }
120
121         tegra_vi->ndev = dev;
122         pdata->private_data = tegra_vi;
123
124         /* Create I2C Devices according to settings from board file */
125         if (i2c_ctrl && i2c_ctrl->new_devices)
126                 i2c_ctrl->new_devices(dev);
127
128 #ifdef CONFIG_TEGRA_CAMERA
129         tegra_vi->camera = tegra_camera_register(dev);
130         if (!tegra_vi->camera) {
131                 dev_err(&dev->dev, "%s: can't register tegra_camera\n",
132                                 __func__);
133                 goto camera_i2c_unregister;
134         }
135 #endif
136
137         pdata->pdev = dev;
138         mutex_init(&pdata->lock);
139         platform_set_drvdata(dev, pdata);
140         nvhost_module_init(dev);
141
142 #ifdef CONFIG_PM_GENERIC_DOMAINS
143         pdata->pd.name = "ve";
144         pdata->pd.power_off = vi_powergate;
145         pdata->pd.power_on = vi_unpowergate;
146         pdata->pd.dev_ops.start = nvhost_module_enable_clk;
147         pdata->pd.dev_ops.stop = nvhost_module_disable_clk;
148
149         /* add module power domain and also add its domain
150          * as sub-domain of MC domain */
151         err = nvhost_module_add_domain(&pdata->pd, dev);
152
153         /* overwrite save/restore fptrs set by pm_genpd_init */
154         pdata->pd.domain.ops.suspend = nvhost_client_device_suspend;
155         pdata->pd.domain.ops.resume = nvhost_client_device_resume;
156 #endif
157
158         err = nvhost_client_device_get_resources(dev);
159         if (err)
160                 goto camera_unregister;
161
162         err = nvhost_client_device_init(dev);
163         if (err)
164                 goto camera_unregister;
165
166 #ifdef CONFIG_PM_RUNTIME
167         if (pdata->clockgate_delay) {
168                 pm_runtime_set_autosuspend_delay(&dev->dev,
169                         pdata->clockgate_delay);
170                 pm_runtime_use_autosuspend(&dev->dev);
171         }
172         pm_runtime_enable(&dev->dev);
173 #else
174         nvhost_module_enable_clk(&dev->dev);
175 #endif
176
177         return 0;
178
179 camera_unregister:
180 #ifdef CONFIG_TEGRA_CAMERA
181         tegra_camera_unregister(tegra_vi->camera);
182 #endif
183 camera_i2c_unregister:
184         if (i2c_ctrl && i2c_ctrl->remove_devices)
185                 i2c_ctrl->remove_devices(dev);
186         pdata->private_data = i2c_ctrl;
187         kfree(tegra_vi);
188         return err;
189 }
190
191 static int __exit vi_remove(struct platform_device *dev)
192 {
193 #ifdef CONFIG_TEGRA_CAMERA
194         int err = 0;
195 #endif
196         struct nvhost_device_data *pdata =
197                 (struct nvhost_device_data *)platform_get_drvdata(dev);
198         struct vi *tegra_vi = (struct vi *)pdata->private_data;
199
200         dev_info(&dev->dev, "%s: ++\n", __func__);
201
202         nvhost_client_device_release(dev);
203
204 #ifdef CONFIG_TEGRA_CAMERA
205         err = tegra_camera_unregister(tegra_vi->camera);
206         if (err)
207                 return err;
208 #endif
209
210 #ifdef CONFIG_PM_RUNTIME
211         pm_runtime_put(&dev->dev);
212         pm_runtime_disable(&dev->dev);
213 #else
214         nvhost_module_disable_clk(&dev->dev);
215 #endif
216         /* Remove I2C Devices according to settings from board file */
217         if (i2c_ctrl && i2c_ctrl->remove_devices)
218                 i2c_ctrl->remove_devices(dev);
219
220         pdata->private_data = i2c_ctrl;
221         kfree(tegra_vi);
222
223         return 0;
224 }
225
226 #ifdef CONFIG_PM
227 static int vi_suspend(struct device *dev)
228 {
229 #ifdef CONFIG_TEGRA_CAMERA
230         struct platform_device *pdev = to_platform_device(dev);
231         struct nvhost_device_data *pdata =
232                 (struct nvhost_device_data *)platform_get_drvdata(pdev);
233         struct vi *tegra_vi = (struct vi *)pdata->private_data;
234         int ret;
235 #endif
236
237         dev_info(dev, "%s: ++\n", __func__);
238
239 #ifdef CONFIG_TEGRA_CAMERA
240         ret = tegra_camera_suspend(tegra_vi->camera);
241         if (ret) {
242                 dev_info(dev, "%s: tegra_camera_suspend error=%d\n",
243                 __func__, ret);
244                 return ret;
245         }
246 #endif
247
248         return nvhost_client_device_suspend(dev);
249 }
250
251 static int vi_resume(struct device *dev)
252 {
253 #ifdef CONFIG_TEGRA_CAMERA
254         struct platform_device *pdev = to_platform_device(dev);
255         struct nvhost_device_data *pdata =
256                 (struct nvhost_device_data *)platform_get_drvdata(pdev);
257         struct vi *tegra_vi = (struct vi *)pdata->private_data;
258 #endif
259
260         dev_info(dev, "%s: ++\n", __func__);
261
262 #ifdef CONFIG_TEGRA_CAMERA
263         tegra_camera_resume(tegra_vi->camera);
264 #endif
265
266         return 0;
267 }
268
269 static const struct dev_pm_ops vi_pm_ops = {
270         .suspend = vi_suspend,
271         .resume = vi_resume,
272 #if defined(CONFIG_PM_RUNTIME) && !defined(CONFIG_PM_GENERIC_DOMAINS)
273         .runtime_suspend = nvhost_module_disable_clk,
274         .runtime_resume = nvhost_module_enable_clk,
275 #endif
276 };
277 #endif
278
279 static struct platform_driver vi_driver = {
280         .probe = vi_probe,
281         .remove = __exit_p(vi_remove),
282         .driver = {
283                 .owner = THIS_MODULE,
284                 .name = "vi",
285 #ifdef CONFIG_PM
286                 .pm = &vi_pm_ops,
287 #endif
288 #ifdef CONFIG_OF
289                 .of_match_table = tegra_vi_of_match,
290 #endif
291         }
292 };
293
294 static int __init vi_init(void)
295 {
296         return platform_driver_register(&vi_driver);
297 }
298
299 static void __exit vi_exit(void)
300 {
301         platform_driver_unregister(&vi_driver);
302 }
303
304 #ifdef TEGRA_12X_OR_HIGHER_CONFIG
305 int nvhost_vi_init(struct platform_device *dev)
306 {
307         int ret = 0;
308         struct vi *tegra_vi;
309         tegra_vi = (struct vi *)nvhost_get_private_data(dev);
310
311         tegra_vi->reg = regulator_get(&dev->dev, "avdd_dsi_csi");
312         if (IS_ERR_OR_NULL(tegra_vi->reg)) {
313                 if (tegra_vi->reg == ERR_PTR(-ENODEV)) {
314                         ret = -ENODEV;
315                         dev_info(&dev->dev,
316                                 "%s: no regulator device\n",
317                                 __func__);
318                 } else {
319                         dev_err(&dev->dev,
320                                 "%s: couldn't get regulator\n",
321                                 __func__);
322                 }
323                 tegra_vi->reg = NULL;
324         }
325         return ret;
326 }
327
328 void nvhost_vi_deinit(struct platform_device *dev)
329 {
330         struct vi *tegra_vi;
331         tegra_vi = (struct vi *)nvhost_get_private_data(dev);
332
333         if (tegra_vi->reg)
334                 regulator_put(tegra_vi->reg);
335 }
336
337 int nvhost_vi_finalize_poweron(struct platform_device *dev)
338 {
339         int ret = 0;
340         struct vi *tegra_vi;
341         tegra_vi = (struct vi *)nvhost_get_private_data(dev);
342
343         if (tegra_vi->reg) {
344                 ret = regulator_enable(tegra_vi->reg);
345                 if (ret)
346                         dev_err(&dev->dev,
347                                 "%s: enable csi regulator failed.\n",
348                                 __func__);
349         }
350         return ret;
351 }
352
353 int nvhost_vi_prepare_poweroff(struct platform_device *dev)
354 {
355         int ret = 0;
356         struct vi *tegra_vi;
357         tegra_vi = (struct vi *)nvhost_get_private_data(dev);
358
359         if (tegra_vi->reg) {
360                 ret = regulator_disable(tegra_vi->reg);
361                 if (ret)
362                         dev_err(&dev->dev,
363                                 "%s: disable csi regulator failed.\n",
364                                 __func__);
365         }
366         return ret;
367 }
368
369 long tegra_vi_ioctl(struct file *file,
370                 unsigned int cmd, unsigned long arg)
371 {
372         struct vi *tegra_vi;
373
374         if (_IOC_TYPE(cmd) != NVHOST_VI_IOCTL_MAGIC)
375                 return -EFAULT;
376
377         tegra_vi = file->private_data;
378         switch (cmd) {
379         case NVHOST_VI_IOCTL_ENABLE_TPG: {
380                 uint enable;
381                 int ret;
382                 struct clk *clk;
383
384                 if (copy_from_user(&enable,
385                         (const void __user *)arg, sizeof(uint))) {
386                         dev_err(&tegra_vi->ndev->dev,
387                                 "%s: Failed to copy arg from user\n", __func__);
388                         return -EFAULT;
389                 }
390
391                 clk = clk_get(&tegra_vi->ndev->dev, "pll_d");
392                 if (enable)
393                         ret = tegra_clk_cfg_ex(clk,
394                                 TEGRA_CLK_PLLD_CSI_OUT_ENB, 1);
395                 else
396                         ret = tegra_clk_cfg_ex(clk,
397                                 TEGRA_CLK_MIPI_CSI_OUT_ENB, 1);
398                 clk_put(clk);
399
400                 return ret;
401         }
402         default:
403                 dev_err(&tegra_vi->ndev->dev,
404                         "%s: Unknown vi ioctl.\n", __func__);
405                 return -EINVAL;
406         }
407         return 0;
408 }
409
410 static int tegra_vi_open(struct inode *inode, struct file *file)
411 {
412         struct nvhost_device_data *pdata;
413         struct vi *vi;
414
415         pdata = container_of(inode->i_cdev,
416                 struct nvhost_device_data, ctrl_cdev);
417         BUG_ON(pdata == NULL);
418
419         vi = (struct vi *)pdata->private_data;
420         BUG_ON(vi == NULL);
421
422         file->private_data = vi;
423         return 0;
424 }
425
426 static int tegra_vi_release(struct inode *inode, struct file *file)
427 {
428         return 0;
429 }
430
431 const struct file_operations tegra_vi_ctrl_ops = {
432         .owner = THIS_MODULE,
433         .open = tegra_vi_open,
434         .unlocked_ioctl = tegra_vi_ioctl,
435         .release = tegra_vi_release,
436 };
437 #endif
438
439 late_initcall(vi_init);
440 module_exit(vi_exit);
441 MODULE_LICENSE("GPL v2");