2 * Tegra Video Input device common APIs
4 * Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved.
6 * Author: Bryan Wu <pengw@nvidia.com>
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.
13 #include <linux/init.h>
14 #include <linux/export.h>
15 #include <linux/module.h>
17 #include <linux/of_device.h>
18 #include <linux/of_platform.h>
20 #include <media/tegra_v4l2_camera.h>
21 #include <media/camera_common.h>
24 #include "mc_common.h"
26 #include "registers.h"
28 #define TPG_CHANNELS 6
29 #define INVALID_PORT 100
31 /* In TPG mode, VI only support 2 formats */
32 static void vi_tpg_fmts_bitmap_init(struct tegra_mc_vi *vi)
36 bitmap_zero(vi->tpg_fmts_bitmap, MAX_FORMAT_NUM);
38 index = tegra_core_get_idx_by_code(MEDIA_BUS_FMT_SRGGB10_1X10);
39 bitmap_set(vi->tpg_fmts_bitmap, index, 1);
41 index = tegra_core_get_idx_by_code(MEDIA_BUS_FMT_RGB888_1X32_PADHI);
42 bitmap_set(vi->tpg_fmts_bitmap, index, 1);
45 int tegra_vi_power_on(struct tegra_channel *chan)
48 struct tegra_mc_vi *vi = chan->vi;
50 ret = nvhost_module_busy_ext(vi->ndev);
52 dev_err(vi->dev, "%s:nvhost module is busy\n", __func__);
57 ret = regulator_enable(vi->reg);
59 dev_err(vi->dev, "%s: enable csi regulator failed.\n",
61 goto error_regulator_fail;
65 tegra_channel_write(chan, TEGRA_VI_CFG_CG_CTRL, 1);
68 ret = tegra_unpowergate_partition(TEGRA_POWERGATE_VENC);
70 dev_err(vi->dev, "failed to unpower gate VI\n");
71 goto error_unpowergate;
75 clk_prepare_enable(vi->clk);
76 ret = clk_set_rate(vi->clk, 408000000);
78 dev_err(vi->dev, "failed to set vi clock to 408MHz!\n");
79 goto error_clk_set_rate;
85 tegra_powergate_partition(TEGRA_POWERGATE_VENC);
87 regulator_disable(vi->reg);
89 nvhost_module_idle_ext(vi->ndev);
94 void tegra_vi_power_off(struct tegra_mc_vi *vi)
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);
102 /* -----------------------------------------------------------------------------
103 * Media Controller and V4L2
106 static const char *const vi_pattern_strings[] = {
108 "Black/White Direct Mode",
112 static void set_vi_mode(struct tegra_mc_vi *vi)
115 struct tegra_channel *chan = NULL;
117 for (i = 0; i < vi->num_channels; i++) {
118 chan = &vi->chans[i];
123 static void set_v4l2_ctrl(struct v4l2_ctrl *ctrl, int value)
125 v4l2_ctrl_unlock(ctrl);
126 v4l2_ctrl_s_ctrl(ctrl, value);
127 v4l2_ctrl_lock(ctrl);
130 static int vi_s_ctrl(struct v4l2_ctrl *ctrl)
132 struct tegra_mc_vi *vi = container_of(ctrl->handler, struct tegra_mc_vi,
134 struct tegra_channel *chan = NULL;
137 case V4L2_CID_TEST_PATTERN:
138 /* set all channels to vi mode before TPG is set */
139 /* set bypass port to invalid port */
141 set_v4l2_ctrl(vi->bypass, INVALID_PORT);
142 dev_info(&vi->ndev->dev, "Turning on TPG mode\n");
144 vi->pg_mode = ctrl->val;
145 vi->csi->pg_mode = vi->pg_mode;
147 case V4L2_CID_VI_SET_BYPASS_PORT:
148 if (ctrl->val < vi->num_channels) {
149 chan = &vi->chans[ctrl->val];
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;
158 /* set all channels to vi mode for invalid port */
166 static const struct v4l2_ctrl_ops vi_ctrl_ops = {
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
175 static const struct v4l2_ctrl_config bypass_ctrl = {
177 .id = V4L2_CID_VI_SET_BYPASS_PORT,
178 .name = "Bypass port",
179 .type = V4L2_CTRL_TYPE_INTEGER,
180 .flags = V4L2_CTRL_FLAG_SLIDER,
187 void tegra_vi_v4l2_cleanup(struct tegra_mc_vi *vi)
189 v4l2_ctrl_handler_free(&vi->ctrl_handler);
190 v4l2_device_unregister(&vi->v4l2_dev);
191 media_device_unregister(&vi->media_dev);
194 int tegra_vi_v4l2_init(struct tegra_mc_vi *vi)
199 vi_tpg_fmts_bitmap_init(vi);
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;
206 ret = media_device_register(&vi->media_dev);
208 dev_err(vi->dev, "media device registration failed (%d)\n",
213 vi->v4l2_dev.mdev = &vi->media_dev;
214 ret = v4l2_device_register(vi->dev, &vi->v4l2_dev);
216 dev_err(vi->dev, "V4L2 device registration failed (%d)\n",
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);
227 vi->bypass = v4l2_ctrl_new_custom(&vi->ctrl_handler,
229 if (vi->ctrl_handler.error) {
230 dev_err(vi->dev, "failed to add controls\n");
231 ret = vi->ctrl_handler.error;
234 vi->v4l2_dev.ctrl_handler = &vi->ctrl_handler;
236 ret = v4l2_ctrl_handler_setup(&vi->ctrl_handler);
238 dev_err(vi->dev, "failed to set controls\n");
245 v4l2_ctrl_handler_free(&vi->ctrl_handler);
246 v4l2_device_unregister(&vi->v4l2_dev);
248 media_device_unregister(&vi->media_dev);
252 static int vi_get_clks(struct tegra_mc_vi *vi, struct platform_device *pdev)
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);
265 static int vi_parse_dt(struct tegra_mc_vi *vi, struct platform_device *dev)
268 int num_channels = 0;
269 struct device_node *node = dev->dev.of_node;
271 err = of_property_read_u32(node, "num-channels", &num_channels);
274 "Failed to find num of channels, set TPG mode\n");
275 num_channels = TPG_CHANNELS;
276 vi->pg_mode = TEGRA_VI_PG_PATCH;
279 vi->num_channels = num_channels;
280 vi->chans = devm_kzalloc(&dev->dev,
281 (sizeof(struct tegra_channel) * num_channels),
289 static void set_vi_register_base(struct tegra_mc_vi *mc_vi,
290 void __iomem *regbase)
292 mc_vi->iomem = regbase;
295 int tegra_vi_media_controller_init(struct tegra_mc_vi *mc_vi,
296 struct platform_device *pdev)
299 struct nvhost_device_data *pdata = pdev->dev.platform_data;
301 set_vi_register_base(mc_vi, pdata->aperture[0]);
303 err = vi_get_clks(mc_vi, pdev);
307 err = vi_parse_dt(mc_vi, pdev);
312 mc_vi->dev = &pdev->dev;
313 INIT_LIST_HEAD(&mc_vi->entities);
315 err = tegra_vi_v4l2_init(mc_vi);
319 /* Init Tegra VI channels */
320 err = tegra_vi_channels_init(mc_vi);
324 /* Setup media links between VI and external sensor subdev. */
325 err = tegra_vi_graph_init(mc_vi);
332 tegra_vi_channels_cleanup(mc_vi);
334 tegra_vi_v4l2_cleanup(mc_vi);
336 dev_err(&pdev->dev, "%s: failed\n", __func__);
339 EXPORT_SYMBOL(tegra_vi_media_controller_init);
341 void tegra_vi_media_controller_cleanup(struct tegra_mc_vi *mc_vi)
343 tegra_vi_graph_cleanup(mc_vi);
344 tegra_vi_channels_cleanup(mc_vi);
345 tegra_vi_v4l2_cleanup(mc_vi);
347 EXPORT_SYMBOL(tegra_vi_media_controller_cleanup);