tristate "generic camera device support"
depends on I2C && PLATFORM_TEGRA
select REGMAP_I2C
+ select VIDEOBUF2_DMA_CONTIG
---help---
This is a driver for generic camera devices
for use with the tegra isp.
config VIDEO_TEGRA_VI
depends on TEGRA_GRHOST
depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && OF
- select VIDEOBUF2_DMA_CONTIG
tristate "Tegra video input host1x client driver"
default y
help
#
obj-y += cam_dev/
obj-y += vi/
+obj-y += csi/
+obj-$(CONFIG_VIDEO_CAMERA) += camera/
ccflags-y += -Idrivers/video/tegra/camera
ccflags-y += -Idrivers/video/tegra/host
ccflags-y += -Idrivers/video/tegra/host/isp
--- /dev/null
+GCOV_PROFILE := y
+ccflags-y += -Idrivers/video/tegra/host
+ccflags-y += -Idrivers/video/tegra/camera
+ccflags-y += -Werror
+
+obj-y += camera_common.o mc_common.o core.o channel.o graph.o
/*
* camera_common.c - utilities for tegra camera driver
*
- * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
struct device_node *node = client->dev.of_node;
struct device_node *ep = NULL;
struct device_node *next;
- struct device_node *remote = NULL;
int bus_width = 0;
- const char *name = NULL;
- const char name_pre[4] = "csi\0";
- int size = ARRAY_SIZE(name_pre);
int err = 0;
+ int port = 0;
/* Parse all the remote entities and put them into the list */
next = of_graph_get_next_endpoint(node, ep);
}
s_data->numlanes = bus_width;
- dev_dbg(&client->dev, "%s: num of lanes %d\n",
- __func__, s_data->numlanes);
-
- remote = of_graph_get_remote_port_parent(ep);
- if (!remote)
- return -ENODATA;
-
- dev_dbg(&client->dev, "%s: name %s\n", __func__, remote->name);
-
- name = strstr(remote->name, name_pre);
- if (!name || name[size-1] < 'a' || name[size-1] > 'f') {
- dev_err(&client->dev, "%s: invalid name %s, expect %s[a-f]\n",
- __func__, remote->name, name_pre);
- return -EINVAL;
+ err = of_property_read_u32(ep, "csi-port", &port);
+ if (err) {
+ dev_err(&client->dev,
+ "Failed to find CSI port\n");
+ return err;
}
+ s_data->csi_port = port;
- s_data->csi_port = (int)(name[size-1] - 'a');
+ dev_dbg(&client->dev, "%s: csi port %d num of lanes %d\n",
+ __func__, s_data->csi_port, s_data->numlanes);
return 0;
}
return -EFAULT;
set_attr:
- dev_info(&client->dev,
+ dev_dbg(&client->dev,
"new address = %x, data = %x\n", address, data);
err |= call_s_ops(s_data, write_reg, address, data);
read:
err |= call_s_ops(s_data, read_reg, address, &readback);
- dev_info(&client->dev,
+ dev_dbg(&client->dev,
"wrote to address 0x%x with value 0x%x\n",
address, readback);
/*
* NVIDIA Tegra Video Input Device
*
- * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved.
*
* Author: Bryan Wu <pengw@nvidia.com>
*
#include <mach/clk.h>
#include <mach/io_dpd.h>
-#include "vi.h"
-#include "vi_common.h"
+#include "mc_common.h"
void tegra_channel_fmts_bitmap_init(struct tegra_channel *chan,
struct tegra_vi_graph_entity *entity)
.mmap = vb2_fop_mmap,
};
-static int tegra_channel_init(struct vi *vi, unsigned int port)
+static int tegra_channel_init(struct tegra_mc_vi *vi, unsigned int port)
{
int ret;
struct tegra_channel *chan = &vi->chans[port];
- int num_sd = MAX_SUBDEVICES - 1;
chan->vi = vi;
chan->port = port;
chan->align = 64;
- while (num_sd < 0)
- chan->subdev[num_sd] = NULL;
chan->num_subdevs = 0;
/* Init video format */
static int tegra_channel_cleanup(struct tegra_channel *chan)
{
- int num_sd = MAX_SUBDEVICES - 1;
-
- while (num_sd < 0)
- chan->subdev[num_sd] = NULL;
video_unregister_device(&chan->video);
v4l2_ctrl_handler_free(&chan->ctrl_handler);
return 0;
}
-int tegra_vi_channels_init(struct vi *vi)
+int tegra_vi_channels_init(struct tegra_mc_vi *vi)
{
unsigned int i;
int ret;
- for (i = 0; i < ARRAY_SIZE(vi->chans); i++) {
+ for (i = 0; i < vi->num_channels; i++) {
ret = tegra_channel_init(vi, i);
if (ret < 0) {
dev_err(vi->dev, "channel %d init failed\n", i);
return 0;
}
-int tegra_vi_channels_cleanup(struct vi *vi)
+int tegra_vi_channels_cleanup(struct tegra_mc_vi *vi)
{
unsigned int i;
int ret;
- for (i = 0; i < ARRAY_SIZE(vi->chans); i++) {
+ for (i = 0; i < vi->num_channels; i++) {
ret = tegra_channel_cleanup(&vi->chans[i]);
if (ret < 0) {
dev_err(vi->dev, "channel %d cleanup failed\n", i);
}
return 0;
}
-
/*
* NVIDIA Tegra Video Input Device Driver Core Helpers
*
- * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved.
*
* Author: Bryan Wu <pengw@nvidia.com>
*
/*
* NVIDIA Tegra Video Input Device Driver Core Helpers
*
- * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved.
*
* Author: Bryan Wu <pengw@nvidia.com>
*
#include <media/v4l2-of.h>
#include <media/tegra_v4l2_camera.h>
-#include "vi.h"
-#include "vi_common.h"
+#include "mc_common.h"
/* -----------------------------------------------------------------------------
*/
static struct tegra_vi_graph_entity *
-tegra_vi_graph_find_entity(struct vi *vi,
+tegra_vi_graph_find_entity(struct tegra_mc_vi *vi,
const struct device_node *node)
{
struct tegra_vi_graph_entity *entity;
return NULL;
}
-static int tegra_vi_graph_build_one(struct vi *vi,
+static int tegra_vi_graph_build_one(struct tegra_mc_vi *vi,
struct tegra_vi_graph_entity *entity)
{
u32 link_flags = MEDIA_LNK_FL_ENABLED;
return ret;
}
-static int tegra_vi_graph_build_links(struct vi *vi)
+static int tegra_vi_graph_build_links(struct tegra_mc_vi *vi)
{
u32 link_flags = MEDIA_LNK_FL_ENABLED;
struct device_node *node = vi->dev->of_node;
continue;
}
- if (link.local_port >= MAX_CHAN_NUM) {
+ if (link.local_port >= vi->num_channels) {
dev_err(vi->dev, "wrong channel number for port %u\n",
link.local_port);
v4l2_of_put_link(&link);
static int tegra_vi_graph_notify_complete(struct v4l2_async_notifier *notifier)
{
- struct vi *vi =
- container_of(notifier, struct vi, notifier);
+ struct tegra_mc_vi *vi =
+ container_of(notifier, struct tegra_mc_vi, notifier);
struct tegra_vi_graph_entity *entity;
int ret;
struct v4l2_subdev *subdev,
struct v4l2_async_subdev *asd)
{
- struct vi *vi = container_of(notifier, struct vi, notifier);
+ struct tegra_mc_vi *vi =
+ container_of(notifier, struct tegra_mc_vi, notifier);
struct tegra_vi_graph_entity *entity;
/* Locate the entity corresponding to the bound subdev and store the
return -EINVAL;
}
-void tegra_vi_graph_cleanup(struct vi *vi)
+void tegra_vi_graph_cleanup(struct tegra_mc_vi *vi)
{
struct tegra_vi_graph_entity *entityp;
struct tegra_vi_graph_entity *entity;
}
-static int tegra_vi_graph_parse_one(struct vi *vi,
+static int tegra_vi_graph_parse_one(struct tegra_mc_vi *vi,
struct device_node *node)
{
struct device_node *ep = NULL;
return ret;
}
-int tegra_vi_graph_init(struct vi *vi)
+int tegra_vi_graph_init(struct tegra_mc_vi *vi)
{
struct tegra_vi_graph_entity *entity;
struct v4l2_async_subdev **subdevs = NULL;
goto done;
}
- /*
- * VI has at least MAX_CHAN_NUM / 2 subdevices for CSI blocks.
- * If just found CSI subdevices connecting to VI, VI has no sensors
- * described in DT but has to use test pattern generator mode.
- * Otherwise VI has sensors connecting.
- */
- vi->has_sensors = (vi->num_subdevs > MAX_CHAN_NUM / 2);
- if (!vi->has_sensors)
- dev_dbg(vi->dev, "has no sensors connected!\n");
-
/* Register the subdevices notifier. */
num_subdevs = vi->num_subdevs;
subdevs = devm_kzalloc(vi->dev, sizeof(*subdevs) * num_subdevs,
goto done;
}
+ /*
+ * Add code to check for sensors and
+ * set TPG mode for VI if no sensors found
+ * logic varies for different platforms
+ */
i = 0;
list_for_each_entry(entity, &vi->entities, list)
subdevs[i++] = &entity->asd;
/*
* Tegra Video Input device common APIs
*
- * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved.
*
* Author: Bryan Wu <pengw@nvidia.com>
*
#include <linux/init.h>
#include <linux/export.h>
#include <linux/module.h>
-#include "vi.h"
-#include "vi_common.h"
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+
+#include <media/tegra_v4l2_camera.h>
+
+#include "dev.h"
+#include "mc_common.h"
+
+#define TPG_CHANNELS 6
/* -----------------------------------------------------------------------------
* Media Controller and V4L2
static int vi_s_ctrl(struct v4l2_ctrl *ctrl)
{
- struct vi *vi = container_of(ctrl->handler, struct vi,
+ struct tegra_mc_vi *vi = container_of(ctrl->handler, struct tegra_mc_vi,
ctrl_handler);
switch (ctrl->id) {
case V4L2_CID_TEST_PATTERN:
.s_ctrl = vi_s_ctrl,
};
-void tegra_vi_v4l2_cleanup(struct vi *vi)
+void tegra_vi_v4l2_cleanup(struct tegra_mc_vi *vi)
{
v4l2_ctrl_handler_free(&vi->ctrl_handler);
v4l2_device_unregister(&vi->v4l2_dev);
media_device_unregister(&vi->media_dev);
}
-int tegra_vi_v4l2_init(struct vi *vi)
+int tegra_vi_v4l2_init(struct tegra_mc_vi *vi)
{
int ret;
media_device_unregister(&vi->media_dev);
return ret;
}
+
+static int vi_parse_dt(struct tegra_mc_vi *vi, struct platform_device *dev)
+{
+ int err = 0;
+ int num_channels = 0;
+ struct device_node *node = dev->dev.of_node;
+
+ err = of_property_read_u32(node, "num-channels", &num_channels);
+ if (err) {
+ dev_err(&dev->dev,
+ "Failed to find num of channels, set TPG mode\n");
+ num_channels = TPG_CHANNELS;
+ vi->pg_mode = TEGRA_VI_PG_PATCH;
+ }
+
+ vi->num_channels = num_channels;
+ vi->chans = devm_kzalloc(&dev->dev,
+ (sizeof(struct tegra_channel) * num_channels),
+ GFP_KERNEL);
+ if (!vi->chans)
+ return -ENOMEM;
+
+ return 0;
+}
+
+int tegra_vi_media_controller_init(struct tegra_mc_vi *mc_vi,
+ struct platform_device *pdev)
+{
+ int err = 0;
+
+ err = vi_parse_dt(mc_vi, pdev);
+ if (err)
+ goto mc_init_fail;
+
+ mc_vi->ndev = pdev;
+ mc_vi->dev = &pdev->dev;
+ INIT_LIST_HEAD(&mc_vi->entities);
+
+ err = tegra_vi_v4l2_init(mc_vi);
+ if (err < 0)
+ goto mc_init_fail;
+
+ /* Init Tegra VI channels */
+ err = tegra_vi_channels_init(mc_vi);
+ if (err < 0)
+ goto channels_error;
+
+ /* Setup media links between VI and external sensor subdev. */
+ err = tegra_vi_graph_init(mc_vi);
+ if (err < 0)
+ goto graph_error;
+
+ return 0;
+
+graph_error:
+ tegra_vi_channels_cleanup(mc_vi);
+channels_error:
+ tegra_vi_v4l2_cleanup(mc_vi);
+mc_init_fail:
+ dev_err(&pdev->dev, "%s: failed\n", __func__);
+ return err;
+}
+EXPORT_SYMBOL(tegra_vi_media_controller_init);
+
+void tegra_vi_media_controller_cleanup(struct tegra_mc_vi *mc_vi)
+{
+ tegra_vi_graph_cleanup(mc_vi);
+ tegra_vi_channels_cleanup(mc_vi);
+ tegra_vi_v4l2_cleanup(mc_vi);
+}
+EXPORT_SYMBOL(tegra_vi_media_controller_cleanup);
--- /dev/null
+/*
+ * drivers/media/platform/tegra/camera/mc_common.h
+ *
+ * Tegra Media controller common APIs
+ *
+ * Copyright (c) 2012-2016, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __MC_COMMON_H__
+#define __MC_COMMON_H__
+
+#include <media/media-device.h>
+#include <media/media-entity.h>
+#include <media/v4l2-async.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-dev.h>
+#include <media/videobuf2-core.h>
+
+#include "core.h"
+
+#define MAX_FORMAT_NUM 64
+#define MAX_SUBDEVICES 4
+
+/**
+ * struct tegra_channel_buffer - video channel buffer
+ * @buf: vb2 buffer base object
+ * @queue: buffer list entry in the channel queued buffers list
+ * @chan: channel that uses the buffer
+ * @addr: Tegra IOVA buffer address for VI output
+ */
+struct tegra_channel_buffer {
+ struct vb2_buffer buf;
+ struct list_head queue;
+ struct tegra_channel *chan;
+
+ dma_addr_t addr;
+};
+
+#define to_tegra_channel_buffer(vb) \
+ container_of(vb, struct tegra_channel_buffer, buf)
+
+/**
+ * struct tegra_vi_graph_entity - Entity in the video graph
+ * @list: list entry in a graph entities list
+ * @node: the entity's DT node
+ * @entity: media entity, from the corresponding V4L2 subdev
+ * @asd: subdev asynchronous registration information
+ * @subdev: V4L2 subdev
+ */
+struct tegra_vi_graph_entity {
+ struct list_head list;
+ struct device_node *node;
+ struct media_entity *entity;
+
+ struct v4l2_async_subdev asd;
+ struct v4l2_subdev *subdev;
+};
+
+/**
+ * struct tegra_channel - Tegra video channel
+ * @list: list entry in a composite device dmas list
+ * @video: V4L2 video device associated with the video channel
+ * @video_lock:
+ * @pad: media pad for the video device entity
+ * @pipe: pipeline belonging to the channel
+ *
+ * @vi: composite device DT node port number for the channel
+ *
+ * @kthread_capture: kernel thread task structure of this video channel
+ * @wait: wait queue structure for kernel thread
+ *
+ * @format: active V4L2 pixel format
+ * @fmtinfo: format information corresponding to the active @format
+ *
+ * @queue: vb2 buffers queue
+ * @alloc_ctx: allocation context for the vb2 @queue
+ * @sequence: V4L2 buffers sequence number
+ *
+ * @capture: list of queued buffers for capture
+ * @queued_lock: protects the buf_queued list
+ *
+ * @csi: CSI register bases
+ * @align: channel buffer alignment, default is 64
+ * @port: CSI port of this video channel
+ * @io_id: Tegra IO rail ID of this video channel
+ *
+ * @fmts_bitmap: a bitmap for formats supported
+ * @bypass: bypass flag for VI bypass mode
+ */
+struct tegra_channel {
+ struct list_head list;
+ struct video_device video;
+ struct media_pad pad;
+ struct media_pipeline pipe;
+
+ struct tegra_mc_vi *vi;
+ struct v4l2_subdev *subdev[MAX_SUBDEVICES];
+
+ struct v4l2_ctrl_handler ctrl_handler;
+ struct v4l2_pix_format format;
+ const struct tegra_video_format *fmtinfo;
+
+ struct vb2_queue queue;
+ void *alloc_ctx;
+
+ void __iomem *csi;
+ unsigned int align;
+ unsigned int port;
+ unsigned int io_id;
+ unsigned int num_subdevs;
+
+ DECLARE_BITMAP(fmts_bitmap, MAX_FORMAT_NUM);
+ bool bypass;
+};
+
+#define to_tegra_channel(vdev) \
+ container_of(vdev, struct tegra_channel, video)
+
+enum tegra_vi_pg_mode {
+ TEGRA_VI_PG_DISABLED = 0,
+ TEGRA_VI_PG_DIRECT,
+ TEGRA_VI_PG_PATCH,
+};
+
+/**
+ * struct tegra_mc_vi - NVIDIA Tegra Media controller structure
+ * @v4l2_dev: V4L2 device
+ * @media_dev: media device
+ * @dev: device struct
+ * @tegra_camera: tegra camera structure
+ * @nvhost_device_data: NvHost VI device information
+ *
+ * @notifier: V4L2 asynchronous subdevs notifier
+ * @entities: entities in the graph as a list of tegra_vi_graph_entity
+ * @num_subdevs: number of subdevs in the pipeline
+ *
+ * @channels: list of channels at the pipeline output and input
+ *
+ * @ctrl_handler: V4L2 control handler
+ * @pattern: test pattern generator V4L2 control
+ * @pg_mode: test pattern generator mode (disabled/direct/patch)
+ * @tpg_fmts_bitmap: a bitmap for formats in test pattern generator mode
+ *
+ * @has_sensors: a flag to indicate whether is a real sensor connecting
+ */
+struct tegra_mc_vi {
+ struct platform_device *ndev;
+ struct v4l2_device v4l2_dev;
+ struct media_device media_dev;
+ struct device *dev;
+ struct nvhost_device_data *ndata;
+
+ struct v4l2_async_notifier notifier;
+ struct list_head entities;
+ unsigned int num_channels;
+ unsigned int num_subdevs;
+
+ struct tegra_channel *chans;
+
+ struct v4l2_ctrl_handler ctrl_handler;
+ struct v4l2_ctrl *pattern;
+ enum tegra_vi_pg_mode pg_mode;
+ DECLARE_BITMAP(tpg_fmts_bitmap, MAX_FORMAT_NUM);
+
+ bool has_sensors;
+};
+
+void tegra_vi_v4l2_cleanup(struct tegra_mc_vi *vi);
+int tegra_vi_v4l2_init(struct tegra_mc_vi *vi);
+int tegra_vi_graph_init(struct tegra_mc_vi *vi);
+void tegra_vi_graph_cleanup(struct tegra_mc_vi *vi);
+int tegra_vi_channels_init(struct tegra_mc_vi *vi);
+int tegra_vi_channels_cleanup(struct tegra_mc_vi *vi);
+void tegra_channel_fmts_bitmap_init(struct tegra_channel *chan,
+ struct tegra_vi_graph_entity *entity);
+int tegra_vi_media_controller_init(struct tegra_mc_vi *mc_vi,
+ struct platform_device *pdev);
+void tegra_vi_media_controller_cleanup(struct tegra_mc_vi *mc_vi);
+#endif
--- /dev/null
+GCOV_PROFILE := y
+ccflags-y += -Idrivers/video/tegra/host
+ccflags-y += -Idrivers/video/tegra/camera
+ccflags-y += -Idrivers/media/platform/tegra/
+ccflags-y += -Werror
+
+obj-y += csi.o
/*
* NVIDIA Tegra CSI Device
*
- * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved.
*
* Author: Bryan Wu <pengw@nvidia.com>
*
#include <media/v4l2-async.h>
#include <media/v4l2-ctrls.h>
-#include "vi.h"
-
-/* Each CSI has 2 ports, CSI_A and CSI_B */
-#define TEGRA_CSI_PORTS_NUM 2
-
-/* Each port has one source pad and one sink pad */
-#define TEGRA_CSI_PADS_NUM 4
-
-enum tegra_csi_port_num {
- PORT_A = 0,
- PORT_B = 1,
-};
-
-struct tegra_csi_port {
- void __iomem *pixel_parser;
- void __iomem *cil;
- void __iomem *tpg;
-
- /* One pair of sink/source pad has one format */
- struct v4l2_mbus_framefmt format;
- const struct tegra_video_format *core_format;
- unsigned int lanes;
-
- enum tegra_csi_port_num num;
-};
-
-struct tegra_csi_device {
- struct v4l2_subdev subdev;
- struct device *dev;
- void __iomem *iomem;
- struct clk *clk;
-
- struct tegra_csi_port ports[TEGRA_CSI_PORTS_NUM];
- struct media_pad pads[TEGRA_CSI_PADS_NUM];
-};
-
-static inline struct tegra_csi_device *to_csi(struct v4l2_subdev *subdev)
-{
- return container_of(subdev, struct tegra_csi_device, subdev);
-}
+#include "vi/vi.h"
+#include "csi.h"
/* -----------------------------------------------------------------------------
* V4L2 Subdevice Video Operations
struct v4l2_subdev_fh *cfg,
unsigned int pad, u32 which)
{
- enum tegra_csi_port_num port_num = pad < 2 ? PORT_A : PORT_B;
+ enum tegra_csi_port_num port_num = (pad >> 1);
switch (which) {
case V4L2_SUBDEV_FORMAT_TRY:
{
struct tegra_csi_device *csi = to_csi(subdev);
struct v4l2_mbus_framefmt *__format;
- enum tegra_csi_port_num port_num = fmt->pad < 2 ? PORT_A : PORT_B;
+ enum tegra_csi_port_num port_num = (fmt->pad >> 1);
__format = __tegra_csi_get_pad_format(csi, cfg,
fmt->pad, fmt->which);
* Platform Device Driver
*/
-static int tegra_csi_parse_of(struct tegra_csi_device *csi)
+static int tegra_csi_parse_of(struct tegra_csi_device *csi,
+ struct platform_device *pdev)
{
struct device_node *node = csi->dev->of_node;
struct device_node *ports;
unsigned int lanes, pad_num, port_num;
int ret;
+ ret = of_property_read_u32(node, "num-ports", &port_num);
+ if (ret < 0)
+ return ret;
+
+ csi->ports = devm_kzalloc(&pdev->dev,
+ (port_num * sizeof(struct tegra_csi_port)), GFP_KERNEL);
+ if (!csi->ports)
+ return -ENOMEM;
+ csi->num_ports = port_num;
+
+ csi->pads = devm_kzalloc(&pdev->dev,
+ (port_num * 2 * sizeof(struct media_pad)), GFP_KERNEL);
+ if (!csi->pads)
+ return -ENOMEM;
+
ports = of_get_child_by_name(node, "ports");
if (ports == NULL)
ports = node;
ret = of_property_read_u32(port, "reg", &pad_num);
if (ret < 0)
continue;
- port_num = pad_num < 2 ? PORT_A : PORT_B;
+ port_num = (pad_num >> 1);
csi->ports[port_num].num = port_num;
for_each_child_of_node(port, ep) {
return 0;
}
-static int tegra_csi_probe(struct platform_device *pdev)
+int tegra_csi_media_controller_init(struct tegra_csi_device *csi,
+ struct platform_device *pdev)
{
struct v4l2_subdev *subdev;
- struct tegra_csi_device *csi;
int ret, i;
- csi = devm_kzalloc(&pdev->dev, sizeof(*csi), GFP_KERNEL);
- if (!csi)
- return -ENOMEM;
-
csi->dev = &pdev->dev;
- ret = tegra_csi_parse_of(csi);
+ ret = tegra_csi_parse_of(csi, pdev);
if (ret < 0)
return ret;
subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
subdev->entity.ops = &tegra_csi_media_ops;
- for (i = 0; i < TEGRA_CSI_PORTS_NUM; i++) {
+ for (i = 0; i < csi->num_ports; i++) {
/* Initialize the default format */
csi->ports[i].format.code = TEGRA_VF_DEF;
csi->ports[i].format.field = V4L2_FIELD_NONE;
}
/* Initialize media entity */
- ret = media_entity_init(&subdev->entity, ARRAY_SIZE(csi->pads),
+ ret = media_entity_init(&subdev->entity, csi->num_ports * 2,
csi->pads, 0);
if (ret < 0)
return ret;
- platform_set_drvdata(pdev, csi);
-
ret = v4l2_async_register_subdev(subdev);
if (ret < 0) {
dev_err(&pdev->dev, "failed to register subdev\n");
return ret;
}
-static int tegra_csi_remove(struct platform_device *pdev)
+int tegra_csi_media_controller_remove(struct tegra_csi_device *csi)
{
- struct tegra_csi_device *csi = platform_get_drvdata(pdev);
struct v4l2_subdev *subdev = &csi->subdev;
v4l2_async_unregister_subdev(subdev);
media_entity_cleanup(&subdev->entity);
return 0;
}
-
-static const struct of_device_id tegra_csi_of_id_table[] = {
- { .compatible = "nvidia,tegra210-csi" },
- { }
-};
-MODULE_DEVICE_TABLE(of, tegra_csi_of_id_table);
-
-static struct platform_driver tegra_csi_driver = {
- .driver = {
- .name = "tegra-csi",
- .of_match_table = tegra_csi_of_id_table,
- },
- .probe = tegra_csi_probe,
- .remove = tegra_csi_remove,
-};
-module_platform_driver(tegra_csi_driver);
-
-MODULE_AUTHOR("Bryan Wu <pengw@nvidia.com>");
-MODULE_DESCRIPTION("NVIDIA Tegra CSI Device Driver");
-MODULE_LICENSE("GPL v2");
--- /dev/null
+/*
+ * NVIDIA Tegra CSI Device Header
+ *
+ * Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved.
+ *
+ * Author: Bryan Wu <pengw@nvidia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __CSI_H_
+#define __CSI_H_
+
+#include <media/media-entity.h>
+#include <media/v4l2-async.h>
+#include <media/v4l2-ctrls.h>
+
+#include "vi/vi.h"
+
+enum tegra_csi_port_num {
+ PORT_A = 0,
+ PORT_B = 1,
+ PORT_C = 2,
+ PORT_D = 3,
+ PORT_E = 4,
+ PORT_F = 5,
+};
+
+struct tegra_csi_port {
+ void __iomem *pixel_parser;
+ void __iomem *cil;
+ void __iomem *tpg;
+
+ /* One pair of sink/source pad has one format */
+ struct v4l2_mbus_framefmt format;
+ const struct tegra_video_format *core_format;
+ unsigned int lanes;
+
+ enum tegra_csi_port_num num;
+};
+
+struct tegra_csi_device {
+ struct v4l2_subdev subdev;
+ struct device *dev;
+ void __iomem *iomem;
+ struct clk *clk;
+
+ struct tegra_csi_port *ports;
+ struct media_pad *pads;
+
+ int num_ports;
+};
+
+static inline struct tegra_csi_device *to_csi(struct v4l2_subdev *subdev)
+{
+ return container_of(subdev, struct tegra_csi_device, subdev);
+}
+
+int tegra_csi_media_controller_init(struct tegra_csi_device *csi,
+ struct platform_device *pdev);
+int tegra_csi_media_controller_remove(struct tegra_csi_device *csi);
+#endif
GCOV_PROFILE := y
ccflags-y += -Idrivers/video/tegra/host
ccflags-y += -Idrivers/video/tegra/camera
+ccflags-y += -Idrivers/media/platform/tegra/camera
ccflags-y += -Werror
ifeq ($(CONFIG_ARCH_TEGRA_18x_SOC),y)
obj-y += vi_irq.o
obj-y += tegra_vi.o
endif
-obj-y += camera_common.o
-nvhost-vi-objs += vi.o vi_common.o core.o channel.o graph.o
-nvhost-csi-objs += csi.o
+nvhost-vi-objs += vi.o
obj-$(CONFIG_VIDEO_TEGRA_VI) += nvhost-vi.o
-obj-$(CONFIG_VIDEO_TEGRA_VI) += nvhost-csi.o
*
* Tegra Graphics Host VI
*
- * Copyright (c) 2012-2015, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2012-2016, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
#include "t210/t210.h"
#include "vi.h"
#include "vi_irq.h"
-#include "vi_common.h"
#include "camera_priv_defs.h"
#ifdef CONFIG_ARCH_TEGRA_18x_SOC
return -ENOMEM;
}
+ tegra_vi->ndev = dev;
+ tegra_vi->dev = &dev->dev;
err = nvhost_client_device_get_resources(dev);
if (err)
goto vi_probe_fail;
- tegra_vi->ndev = dev;
- tegra_vi->dev = &dev->dev;
- INIT_LIST_HEAD(&tegra_vi->entities);
-
/* create workqueue for mfi callback */
tegra_vi->vi_workqueue = alloc_workqueue("vi_workqueue",
WQ_HIGHPRI | WQ_UNBOUND, 1);
* as sub-domain of MC domain */
err = nvhost_module_add_domain(&pdata->pd, dev);
#endif
-
err = nvhost_client_device_init(dev);
if (err)
goto camera_unregister;
- err = tegra_vi_v4l2_init(tegra_vi);
- if (err < 0)
- goto vi_init_error;
-
- /* Init Tegra VI channels */
- err = tegra_vi_channels_init(tegra_vi);
- if (err < 0)
- goto channels_error;
-
- /* Setup media links between VI and external sensor subdev. */
- err = tegra_vi_graph_init(tegra_vi);
- if (err < 0)
- goto graph_error;
+ err = tegra_vi_media_controller_init(&tegra_vi->mc_vi, dev);
+ if (err)
+ goto vi_mc_init_error;
return 0;
-graph_error:
- tegra_vi_channels_cleanup(tegra_vi);
-channels_error:
- tegra_vi_v4l2_cleanup(tegra_vi);
-vi_init_error:
+vi_mc_init_error:
nvhost_client_device_release(dev);
camera_unregister:
#ifdef CONFIG_TEGRA_CAMERA
vi_remove_debugfs(tegra_vi);
+ tegra_vi_media_controller_cleanup(&tegra_vi->mc_vi);
+
nvhost_client_device_release(dev);
if (pdata->slcg_notifier_enable &&
pdata->private_data = i2c_ctrl;
- tegra_vi_graph_cleanup(tegra_vi);
- tegra_vi_channels_cleanup(tegra_vi);
- tegra_vi_v4l2_cleanup(tegra_vi);
-
return 0;
}
*
* Tegra Graphics Host VI
*
- * Copyright (c) 2012-2015, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2012-2016, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
#include <linux/platform/tegra/isomgr.h>
-#include <media/media-device.h>
-#include <media/media-entity.h>
-#include <media/v4l2-async.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-dev.h>
-#include <media/videobuf2-core.h>
-
-#include "core.h"
-
+#include "../camera/mc_common.h"
#include "camera_priv_defs.h"
#include "chip_support.h"
-#define MAX_CHAN_NUM 8
-#define MAX_FORMAT_NUM 64
-#define MAX_SUBDEVICES 4
-
#define VI_CFG_INTERRUPT_MASK_0 0x8c
#define VI_CFG_INTERRUPT_STATUS_0 0x98
atomic_t overflow;
};
-/**
- * struct tegra_channel_buffer - video channel buffer
- * @buf: vb2 buffer base object
- * @queue: buffer list entry in the channel queued buffers list
- * @chan: channel that uses the buffer
- * @addr: Tegra IOVA buffer address for VI output
- */
-struct tegra_channel_buffer {
- struct vb2_buffer buf;
- struct list_head queue;
- struct tegra_channel *chan;
-
- dma_addr_t addr;
-};
-
-#define to_tegra_channel_buffer(vb) \
- container_of(vb, struct tegra_channel_buffer, buf)
-
-/**
- * struct tegra_vi_graph_entity - Entity in the video graph
- * @list: list entry in a graph entities list
- * @node: the entity's DT node
- * @entity: media entity, from the corresponding V4L2 subdev
- * @asd: subdev asynchronous registration information
- * @subdev: V4L2 subdev
- */
-struct tegra_vi_graph_entity {
- struct list_head list;
- struct device_node *node;
- struct media_entity *entity;
-
- struct v4l2_async_subdev asd;
- struct v4l2_subdev *subdev;
-};
-
-/**
- * struct tegra_channel - Tegra video channel
- * @list: list entry in a composite device dmas list
- * @video: V4L2 video device associated with the video channel
- * @video_lock:
- * @pad: media pad for the video device entity
- * @pipe: pipeline belonging to the channel
- *
- * @vi: composite device DT node port number for the channel
- *
- * @kthread_capture: kernel thread task structure of this video channel
- * @wait: wait queue structure for kernel thread
- *
- * @format: active V4L2 pixel format
- * @fmtinfo: format information corresponding to the active @format
- *
- * @queue: vb2 buffers queue
- * @alloc_ctx: allocation context for the vb2 @queue
- * @sequence: V4L2 buffers sequence number
- *
- * @capture: list of queued buffers for capture
- * @queued_lock: protects the buf_queued list
- *
- * @csi: CSI register bases
- * @align: channel buffer alignment, default is 64
- * @port: CSI port of this video channel
- * @io_id: Tegra IO rail ID of this video channel
- *
- * @fmts_bitmap: a bitmap for formats supported
- * @bypass: bypass flag for VI bypass mode
- */
-struct tegra_channel {
- struct list_head list;
- struct video_device video;
- struct media_pad pad;
- struct media_pipeline pipe;
-
- struct vi *vi;
- struct v4l2_subdev *subdev[MAX_SUBDEVICES];
-
- struct v4l2_ctrl_handler ctrl_handler;
- struct v4l2_pix_format format;
- const struct tegra_video_format *fmtinfo;
-
- struct vb2_queue queue;
- void *alloc_ctx;
-
- void __iomem *csi;
- unsigned int align;
- unsigned int port;
- unsigned int io_id;
- unsigned int num_subdevs;
-
- DECLARE_BITMAP(fmts_bitmap, MAX_FORMAT_NUM);
- bool bypass;
-};
-
-#define to_tegra_channel(vdev) \
- container_of(vdev, struct tegra_channel, video)
-
-enum tegra_vi_pg_mode {
- TEGRA_VI_PG_DISABLED = 0,
- TEGRA_VI_PG_DIRECT,
- TEGRA_VI_PG_PATCH,
-};
-
-/**
- * struct tegra_vi - NVIDIA Tegra Video Input device structure
- * @v4l2_dev: V4L2 device
- * @media_dev: media device
- * @dev: device struct
- * @tegra_camera: tegra camera structure
- * @nvhost_device_data: NvHost VI device information
- *
- * @notifier: V4L2 asynchronous subdevs notifier
- * @entities: entities in the graph as a list of tegra_vi_graph_entity
- * @num_subdevs: number of subdevs in the pipeline
- *
- * @channels: list of channels at the pipeline output and input
- *
- * @ctrl_handler: V4L2 control handler
- * @pattern: test pattern generator V4L2 control
- * @pg_mode: test pattern generator mode (disabled/direct/patch)
- * @tpg_fmts_bitmap: a bitmap for formats in test pattern generator mode
- *
- * @has_sensors: a flag to indicate whether is a real sensor connecting
- */
struct vi {
struct tegra_camera *camera;
struct platform_device *ndev;
- struct v4l2_device v4l2_dev;
- struct media_device media_dev;
struct device *dev;
struct nvhost_device_data *ndata;
-
- struct v4l2_async_notifier notifier;
- struct list_head entities;
- unsigned int num_subdevs;
-
- struct tegra_channel chans[MAX_CHAN_NUM];
-
- struct v4l2_ctrl_handler ctrl_handler;
- struct v4l2_ctrl *pattern;
- enum tegra_vi_pg_mode pg_mode;
- DECLARE_BITMAP(tpg_fmts_bitmap, MAX_FORMAT_NUM);
+ struct tegra_mc_vi mc_vi;
struct regulator *reg;
struct dentry *debugdir;
int vi_irq;
uint vi_bw;
uint max_bw;
- bool has_sensors;
bool master_deinitialized;
};
+++ /dev/null
-/*
- * Tegra Video Input device common APIs
- *
- * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved.
- *
- * Author: Bryan Wu <pengw@nvidia.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __VI_COMMON_H_
-#define __VI_COMMON_H_
-
-void tegra_vi_v4l2_cleanup(struct vi *vi);
-int tegra_vi_v4l2_init(struct vi *vi);
-
-int tegra_vi_graph_init(struct vi *vi);
-void tegra_vi_graph_cleanup(struct vi *vi);
-int tegra_vi_channels_init(struct vi *vi);
-int tegra_vi_channels_cleanup(struct vi *vi);
-void tegra_channel_fmts_bitmap_init(struct tegra_channel *chan,
- struct tegra_vi_graph_entity *entity);
-
-#endif