]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/blob - drivers/media/platform/tegra/camera/mc_common.c
drivers: media: platform: tegra: VI mode
[sojka/nv-tegra/linux-3.10.git] / drivers / media / platform / tegra / camera / mc_common.c
1 /*
2  * Tegra Video Input device common APIs
3  *
4  * Copyright (c) 2015-2016, NVIDIA CORPORATION.  All rights reserved.
5  *
6  * Author: Bryan Wu <pengw@nvidia.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  */
12
13 #include <linux/init.h>
14 #include <linux/export.h>
15 #include <linux/module.h>
16 #include <linux/of.h>
17 #include <linux/of_device.h>
18 #include <linux/of_platform.h>
19
20 #include <media/tegra_v4l2_camera.h>
21 #include <media/camera_common.h>
22
23 #include "dev.h"
24 #include "mc_common.h"
25 #include "vi.h"
26 #include "registers.h"
27
28 #define TPG_CHANNELS 6
29 #define INVALID_PORT 100
30
31 /* In TPG mode, VI only support 2 formats */
32 static void vi_tpg_fmts_bitmap_init(struct tegra_mc_vi *vi)
33 {
34         int index;
35
36         bitmap_zero(vi->tpg_fmts_bitmap, MAX_FORMAT_NUM);
37
38         index = tegra_core_get_idx_by_code(MEDIA_BUS_FMT_SRGGB10_1X10);
39         bitmap_set(vi->tpg_fmts_bitmap, index, 1);
40
41         index = tegra_core_get_idx_by_code(MEDIA_BUS_FMT_RGB888_1X32_PADHI);
42         bitmap_set(vi->tpg_fmts_bitmap, index, 1);
43 }
44
45 int tegra_vi_power_on(struct tegra_channel *chan)
46 {
47         int ret;
48         struct tegra_mc_vi *vi = chan->vi;
49
50         ret = nvhost_module_busy_ext(vi->ndev);
51         if (ret) {
52                 dev_err(vi->dev, "%s:nvhost module is busy\n", __func__);
53                 return ret;
54         }
55
56         if (vi->reg) {
57                 ret = regulator_enable(vi->reg);
58                 if (ret) {
59                         dev_err(vi->dev, "%s: enable csi regulator failed.\n",
60                                         __func__);
61                         goto error_regulator_fail;
62                 }
63         }
64
65         tegra_channel_write(chan, TEGRA_VI_CFG_CG_CTRL, 1);
66
67         /* unpowergate VE */
68         ret = tegra_unpowergate_partition(TEGRA_POWERGATE_VENC);
69         if (ret) {
70                 dev_err(vi->dev, "failed to unpower gate VI\n");
71                 goto error_unpowergate;
72         }
73
74         /* clock settings */
75         clk_prepare_enable(vi->clk);
76         ret = clk_set_rate(vi->clk, 408000000);
77         if (ret) {
78                 dev_err(vi->dev, "failed to set vi clock to 408MHz!\n");
79                 goto error_clk_set_rate;
80         }
81
82         return 0;
83
84 error_clk_set_rate:
85         tegra_powergate_partition(TEGRA_POWERGATE_VENC);
86 error_unpowergate:
87         regulator_disable(vi->reg);
88 error_regulator_fail:
89         nvhost_module_idle_ext(vi->ndev);
90
91         return ret;
92 }
93
94 void tegra_vi_power_off(struct tegra_mc_vi *vi)
95 {
96         clk_disable_unprepare(vi->clk);
97         tegra_powergate_partition(TEGRA_POWERGATE_VENC);
98         regulator_disable(vi->reg);
99         nvhost_module_idle_ext(vi->ndev);
100 }
101
102 /* -----------------------------------------------------------------------------
103  * Media Controller and V4L2
104  */
105
106 static const char *const vi_pattern_strings[] = {
107         "Disabled",
108         "Black/White Direct Mode",
109         "Color Patch Mode",
110 };
111
112 static void set_vi_mode(struct tegra_mc_vi *vi)
113 {
114         int i;
115         struct tegra_channel *chan = NULL;
116
117         for (i = 0; i < vi->num_channels; i++) {
118                 chan = &vi->chans[i];
119                 chan->bypass = 0;
120         }
121 }
122
123 static void set_v4l2_ctrl(struct v4l2_ctrl *ctrl, int value)
124 {
125         v4l2_ctrl_unlock(ctrl);
126         v4l2_ctrl_s_ctrl(ctrl, value);
127         v4l2_ctrl_lock(ctrl);
128 }
129
130 static int vi_s_ctrl(struct v4l2_ctrl *ctrl)
131 {
132         struct tegra_mc_vi *vi = container_of(ctrl->handler, struct tegra_mc_vi,
133                                            ctrl_handler);
134         struct tegra_channel *chan = NULL;
135
136         switch (ctrl->id) {
137         case V4L2_CID_TEST_PATTERN:
138                 /* set all channels to vi mode before TPG is set */
139                 /* set bypass port to invalid port */
140                 if (ctrl->val) {
141                         set_v4l2_ctrl(vi->bypass, INVALID_PORT);
142                         dev_info(&vi->ndev->dev, "Turning on TPG mode\n");
143                 }
144                 vi->pg_mode = ctrl->val;
145                 vi->csi->pg_mode = vi->pg_mode;
146                 break;
147         case V4L2_CID_VI_SET_BYPASS_PORT:
148                 if (ctrl->val < vi->num_channels) {
149                         chan = &vi->chans[ctrl->val];
150                         chan->bypass = 1;
151                         if (vi->pg_mode) {
152                                 dev_info(&vi->ndev->dev,
153                                         "Turning off TPG mode\n");
154                                 set_v4l2_ctrl(vi->pattern, 0);
155                                 vi->pg_mode = vi->csi->pg_mode = 0;
156                         }
157                 } else
158                         /* set all channels to vi mode for invalid port */
159                         set_vi_mode(vi);
160                 break;
161         }
162
163         return 0;
164 }
165
166 static const struct v4l2_ctrl_ops vi_ctrl_ops = {
167         .s_ctrl = vi_s_ctrl,
168 };
169
170 /**
171  * Default value is invalid port, max 99 channels are available
172  * By default all the channels will be in VI mode
173  * Idea is to enable the user space to set bypass flag per channel
174  */
175 static const struct v4l2_ctrl_config bypass_ctrl = {
176         .ops = &vi_ctrl_ops,
177         .id = V4L2_CID_VI_SET_BYPASS_PORT,
178         .name = "Bypass port",
179         .type = V4L2_CTRL_TYPE_INTEGER,
180         .flags = V4L2_CTRL_FLAG_SLIDER,
181         .def = INVALID_PORT,
182         .min = 0,
183         .max = INVALID_PORT,
184         .step = 1,
185 };
186
187 void tegra_vi_v4l2_cleanup(struct tegra_mc_vi *vi)
188 {
189         v4l2_ctrl_handler_free(&vi->ctrl_handler);
190         v4l2_device_unregister(&vi->v4l2_dev);
191         media_device_unregister(&vi->media_dev);
192 }
193
194 int tegra_vi_v4l2_init(struct tegra_mc_vi *vi)
195 {
196         int ret;
197
198         vi->pg_mode = 0;
199         vi_tpg_fmts_bitmap_init(vi);
200
201         vi->media_dev.dev = vi->dev;
202         strlcpy(vi->media_dev.model, "NVIDIA Tegra Video Input Device",
203                 sizeof(vi->media_dev.model));
204         vi->media_dev.hw_revision = 3;
205
206         ret = media_device_register(&vi->media_dev);
207         if (ret < 0) {
208                 dev_err(vi->dev, "media device registration failed (%d)\n",
209                         ret);
210                 return ret;
211         }
212
213         vi->v4l2_dev.mdev = &vi->media_dev;
214         ret = v4l2_device_register(vi->dev, &vi->v4l2_dev);
215         if (ret < 0) {
216                 dev_err(vi->dev, "V4L2 device registration failed (%d)\n",
217                         ret);
218                 goto register_error;
219         }
220
221         v4l2_ctrl_handler_init(&vi->ctrl_handler, 2);
222         vi->pattern = v4l2_ctrl_new_std_menu_items(&vi->ctrl_handler,
223                                         &vi_ctrl_ops, V4L2_CID_TEST_PATTERN,
224                                         ARRAY_SIZE(vi_pattern_strings) - 1,
225                                         0, 0, vi_pattern_strings);
226
227         vi->bypass = v4l2_ctrl_new_custom(&vi->ctrl_handler,
228                                         &bypass_ctrl, NULL);
229         if (vi->ctrl_handler.error) {
230                 dev_err(vi->dev, "failed to add controls\n");
231                 ret = vi->ctrl_handler.error;
232                 goto ctrl_error;
233         }
234         vi->v4l2_dev.ctrl_handler = &vi->ctrl_handler;
235
236         ret = v4l2_ctrl_handler_setup(&vi->ctrl_handler);
237         if (ret < 0) {
238                 dev_err(vi->dev, "failed to set controls\n");
239                 goto ctrl_error;
240         }
241         return 0;
242
243
244 ctrl_error:
245         v4l2_ctrl_handler_free(&vi->ctrl_handler);
246         v4l2_device_unregister(&vi->v4l2_dev);
247 register_error:
248         media_device_unregister(&vi->media_dev);
249         return ret;
250 }
251
252 static int vi_get_clks(struct tegra_mc_vi *vi, struct platform_device *pdev)
253 {
254         int ret = 0;
255
256         vi->clk = devm_clk_get(&pdev->dev, "vi");
257         if (IS_ERR(vi->clk)) {
258                 dev_err(&pdev->dev, "Failed to get vi clock\n");
259                 return PTR_ERR(vi->clk);
260         }
261
262         return ret;
263 }
264
265 static int vi_parse_dt(struct tegra_mc_vi *vi, struct platform_device *dev)
266 {
267         int err = 0;
268         int num_channels = 0;
269         struct device_node *node = dev->dev.of_node;
270
271         err = of_property_read_u32(node, "num-channels", &num_channels);
272         if (err) {
273                 dev_err(&dev->dev,
274                         "Failed to find num of channels, set TPG mode\n");
275                 num_channels = TPG_CHANNELS;
276                 vi->pg_mode = TEGRA_VI_PG_PATCH;
277         }
278
279         vi->num_channels = num_channels;
280         vi->chans = devm_kzalloc(&dev->dev,
281                         (sizeof(struct tegra_channel) * num_channels),
282                         GFP_KERNEL);
283         if (!vi->chans)
284                 return -ENOMEM;
285
286         return 0;
287 }
288
289 static void set_vi_register_base(struct tegra_mc_vi *mc_vi,
290                         void __iomem *regbase)
291 {
292         mc_vi->iomem = regbase;
293 }
294
295 int tegra_vi_media_controller_init(struct tegra_mc_vi *mc_vi,
296                         struct platform_device *pdev)
297 {
298         int err = 0;
299         struct nvhost_device_data *pdata = pdev->dev.platform_data;
300
301         set_vi_register_base(mc_vi, pdata->aperture[0]);
302
303         err = vi_get_clks(mc_vi, pdev);
304         if (err)
305                 return err;
306
307         err = vi_parse_dt(mc_vi, pdev);
308         if (err)
309                 goto mc_init_fail;
310
311         mc_vi->ndev = pdev;
312         mc_vi->dev = &pdev->dev;
313         INIT_LIST_HEAD(&mc_vi->entities);
314
315         err = tegra_vi_v4l2_init(mc_vi);
316         if (err < 0)
317                 goto mc_init_fail;
318
319         /* Init Tegra VI channels */
320         err = tegra_vi_channels_init(mc_vi);
321         if (err < 0)
322                 goto channels_error;
323
324         /* Setup media links between VI and external sensor subdev. */
325         err = tegra_vi_graph_init(mc_vi);
326         if (err < 0)
327                 goto graph_error;
328
329         return 0;
330
331 graph_error:
332         tegra_vi_channels_cleanup(mc_vi);
333 channels_error:
334         tegra_vi_v4l2_cleanup(mc_vi);
335 mc_init_fail:
336         dev_err(&pdev->dev, "%s: failed\n", __func__);
337         return err;
338 }
339 EXPORT_SYMBOL(tegra_vi_media_controller_init);
340
341 void tegra_vi_media_controller_cleanup(struct tegra_mc_vi *mc_vi)
342 {
343         tegra_vi_graph_cleanup(mc_vi);
344         tegra_vi_channels_cleanup(mc_vi);
345         tegra_vi_v4l2_cleanup(mc_vi);
346 }
347 EXPORT_SYMBOL(tegra_vi_media_controller_cleanup);