summaryrefslogtreecommitdiff
path: root/isp/subdev.c
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2011-07-30 14:33:37 +0200
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2011-07-30 14:33:37 +0200
commitfebcb53ca85d911619456c09c4be49fd73c4964b (patch)
tree12ae3a93d117b56da6e1213882f5cc6de3977adb /isp/subdev.c
omap3-isp-live: Initial commit
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Diffstat (limited to 'isp/subdev.c')
-rw-r--r--isp/subdev.c287
1 files changed, 287 insertions, 0 deletions
diff --git a/isp/subdev.c b/isp/subdev.c
new file mode 100644
index 0000000..b4894a2
--- /dev/null
+++ b/isp/subdev.c
@@ -0,0 +1,287 @@
+/*
+ * OMAP3 ISP library - V4L2 sub-devices
+ *
+ * Copyright (C) 2010-2011 Ideas on board SPRL
+ *
+ * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that 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 Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <linux/v4l2-subdev.h>
+
+#include "media.h"
+#include "subdev.h"
+#include "tools.h"
+
+static struct {
+ const char *name;
+ enum v4l2_mbus_pixelcode code;
+} mbus_formats[] = {
+ { "YUYV", V4L2_MBUS_FMT_YUYV8_1X16 },
+ { "UYVY", V4L2_MBUS_FMT_UYVY8_1X16 },
+ { "SGRBG10", V4L2_MBUS_FMT_SGRBG10_1X10 },
+ { "SGRBG10_DPCM8", V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8 },
+};
+
+static const char *pixelcode_to_string(enum v4l2_mbus_pixelcode code)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(mbus_formats); ++i) {
+ if (mbus_formats[i].code == code)
+ return mbus_formats[i].name;
+ }
+
+ return "unknown";
+}
+
+int v4l2_subdev_open(struct media_entity *entity)
+{
+ if (entity->fd != -1)
+ return 0;
+
+ entity->fd = open(entity->devname, O_RDWR);
+ if (entity->fd == -1) {
+ printf("%s: Failed to open subdev device node %s\n", __func__,
+ entity->devname);
+ return -errno;
+ }
+
+ return 0;
+}
+
+void v4l2_subdev_close(struct media_entity *entity)
+{
+ close(entity->fd);
+}
+
+int v4l2_subdev_get_format(struct media_entity *entity,
+ struct v4l2_mbus_framefmt *format, unsigned int pad,
+ enum v4l2_subdev_format_whence which)
+{
+ struct v4l2_subdev_format fmt;
+ int ret;
+
+ ret = v4l2_subdev_open(entity);
+ if (ret < 0)
+ return ret;
+
+ memset(&fmt, 0, sizeof(fmt));
+ fmt.pad = pad;
+ fmt.which = which;
+
+ ret = ioctl(entity->fd, VIDIOC_SUBDEV_G_FMT, &fmt);
+ if (ret < 0)
+ return -errno;
+
+ *format = fmt.format;
+ return 0;
+}
+
+int v4l2_subdev_set_format(struct media_entity *entity,
+ struct v4l2_mbus_framefmt *format, unsigned int pad,
+ enum v4l2_subdev_format_whence which)
+{
+ struct v4l2_subdev_format fmt;
+ int ret;
+
+ ret = v4l2_subdev_open(entity);
+ if (ret < 0)
+ return ret;
+
+ memset(&fmt, 0, sizeof(fmt));
+ fmt.pad = pad;
+ fmt.which = which;
+ fmt.format = *format;
+
+ ret = ioctl(entity->fd, VIDIOC_SUBDEV_S_FMT, &fmt);
+ if (ret < 0)
+ return -errno;
+
+ *format = fmt.format;
+ return 0;
+}
+
+int v4l2_subdev_get_crop(struct media_entity *entity, struct v4l2_rect *rect,
+ unsigned int pad, enum v4l2_subdev_format_whence which)
+{
+ struct v4l2_subdev_crop crop;
+ int ret;
+
+ ret = v4l2_subdev_open(entity);
+ if (ret < 0)
+ return ret;
+
+ memset(&crop, 0, sizeof(crop));
+ crop.pad = pad;
+ crop.which = which;
+
+ ret = ioctl(entity->fd, VIDIOC_SUBDEV_G_CROP, &crop);
+ if (ret < 0)
+ return -errno;
+
+ *rect = crop.rect;
+ return 0;
+}
+
+int v4l2_subdev_set_crop(struct media_entity *entity, struct v4l2_rect *rect,
+ unsigned int pad, enum v4l2_subdev_format_whence which)
+{
+ struct v4l2_subdev_crop crop;
+ int ret;
+
+ ret = v4l2_subdev_open(entity);
+ if (ret < 0)
+ return ret;
+
+ memset(&crop, 0, sizeof(crop));
+ crop.pad = pad;
+ crop.which = which;
+ crop.rect = *rect;
+
+ ret = ioctl(entity->fd, VIDIOC_SUBDEV_S_CROP, &crop);
+ if (ret < 0)
+ return -errno;
+
+ *rect = crop.rect;
+ return 0;
+}
+
+int v4l2_subdev_set_frame_interval(struct media_entity *entity,
+ struct v4l2_fract *interval)
+{
+ struct v4l2_subdev_frame_interval ival;
+ int ret;
+
+ ret = v4l2_subdev_open(entity);
+ if (ret < 0)
+ return ret;
+
+ memset(&ival, 0, sizeof(ival));
+ ival.interval = *interval;
+
+ ret = ioctl(entity->fd, VIDIOC_SUBDEV_S_FRAME_INTERVAL, &ival);
+ if (ret < 0)
+ return -errno;
+
+ *interval = ival.interval;
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Controls
+ */
+
+int v4l2_subdev_get_control(struct media_entity *entity, unsigned int id,
+ int32_t *value)
+{
+ struct v4l2_control ctrl;
+ int ret;
+
+ ret = v4l2_subdev_open(entity);
+ if (ret < 0)
+ return ret;
+
+ ctrl.id = id;
+
+ ret = ioctl(entity->fd, VIDIOC_G_CTRL, &ctrl);
+ if (ret < 0) {
+ printf("unable to get control: %s (%d).\n",
+ strerror(errno), errno);
+ return -errno;
+ }
+
+ *value = ctrl.value;
+ return 0;
+}
+
+int v4l2_subdev_set_control(struct media_entity *entity, unsigned int id,
+ int32_t *value)
+{
+ struct v4l2_control ctrl;
+ int ret;
+
+ ret = v4l2_subdev_open(entity);
+ if (ret < 0)
+ return ret;
+
+ ctrl.id = id;
+ ctrl.value = *value;
+
+ ret = ioctl(entity->fd, VIDIOC_S_CTRL, &ctrl);
+ if (ret < 0) {
+ printf("unable to set control: %s (%d).\n",
+ strerror(errno), errno);
+ return -errno;
+ }
+
+ *value = ctrl.value;
+ return 0;
+}
+
+int v4l2_subdev_get_controls(struct media_entity *entity, unsigned int count,
+ struct v4l2_ext_control *ctrls)
+{
+ struct v4l2_ext_controls controls;
+ int ret;
+
+ ret = v4l2_subdev_open(entity);
+ if (ret < 0)
+ return ret;
+
+ memset(&controls, 0, sizeof controls);
+ controls.count = count;
+ controls.controls = ctrls;
+
+ ret = ioctl(entity->fd, VIDIOC_G_EXT_CTRLS, &controls);
+ if (ret < 0)
+ printf("unable to get multiple controls: %s (%d).\n",
+ strerror(errno), errno);
+
+ return ret;
+}
+
+int v4l2_subdev_set_controls(struct media_entity *entity, unsigned int count,
+ struct v4l2_ext_control *ctrls)
+{
+ struct v4l2_ext_controls controls;
+ int ret;
+
+ ret = v4l2_subdev_open(entity);
+ if (ret < 0)
+ return ret;
+
+ memset(&controls, 0, sizeof controls);
+ controls.count = count;
+ controls.controls = ctrls;
+
+ ret = ioctl(entity->fd, VIDIOC_S_EXT_CTRLS, &controls);
+ if (ret < 0)
+ printf("unable to set multiple controls: %s (%d).\n",
+ strerror(errno), errno);
+
+ return ret;
+}