summaryrefslogtreecommitdiff
path: root/drivers/media/i2c/tvp514x.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-04-30 16:58:16 (GMT)
committerLinus Torvalds <torvalds@linux-foundation.org>2013-04-30 16:58:16 (GMT)
commit240c3c3424366c8109babd2a0fe80855de511b35 (patch)
tree72eb8652c8e513715efee1e254644b4b670333fd /drivers/media/i2c/tvp514x.c
parent19b344efa35dbc253e2d10403dafe6aafda73c56 (diff)
parentdf90e2258950fd631cdbf322c1ee1f22068391aa (diff)
downloadlinux-fsl-qoriq-240c3c3424366c8109babd2a0fe80855de511b35.tar.xz
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media update from Mauro Carvalho Chehab: - OF documentation and patches at core and drivers, to be used by for embedded media systems - some I2C drivers used on go7007 were rewritten/promoted from staging: sony-btf-mpx, tw2804, tw9903, tw9906, wis-ov7640, wis-uda1342 - add fimc-is driver (Exynos) - add a new radio driver: radio-si476x - add a two new tuners: r820t and tuner_it913x - split camera code on em28xx driver and add more models - the cypress firmware load is used outside dvb usb drivers. So, move it to a common directory to make easier to re-use it - siano media driver updated to work with sms2270 devices - several work done in order to promote go7007 and solo6x1x out of staging (still, there are some pending issues) - several API compliance fixes at v4l2 drivers that don't behave as expected - as usual, lots of driver fixes, improvements, cleanups and new device addition at the existing drivers. * 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (831 commits) [media] cx88: make core less verbose [media] em28xx: fix oops at em28xx_dvb_bus_ctrl() [media] s5c73m3: fix indentation of the help section in Kconfig [media] cx25821-alsa: get rid of a __must_check warning [media] cx25821-video: declare cx25821_vidioc_s_std as static [media] cx25821-video: remove maxw from cx25821_vidioc_try_fmt_vid_cap [media] r820t: Remove a warning for an unused value [media] dib0090: Fix a warning at dib0090_set_EFUSE [media] dib8000: fix a warning [media] dib8000: Fix sub-channel range [media] dib8000: store dtv_property_cache in a temp var [media] dib8000: warning fix: declare internal functions as static [media] r820t: quiet gcc warning on n_ring [media] r820t: memory leak in release() [media] r820t: precendence bug in r820t_xtal_check() [media] videodev2.h: Remove the unused old V4L1 buffer types [media] anysee: Grammar s/report the/report to/ [media] anysee: Initialize ret = 0 in anysee_frontend_attach() [media] media: videobuf2: fix the length check for mmap [media] em28xx: save isoc endpoint number for DVB only if endpoint has alt settings with xMaxPacketSize != 0 ...
Diffstat (limited to 'drivers/media/i2c/tvp514x.c')
-rw-r--r--drivers/media/i2c/tvp514x.c163
1 files changed, 154 insertions, 9 deletions
diff --git a/drivers/media/i2c/tvp514x.c b/drivers/media/i2c/tvp514x.c
index aa94ebc..ab8f3fe 100644
--- a/drivers/media/i2c/tvp514x.c
+++ b/drivers/media/i2c/tvp514x.c
@@ -12,6 +12,7 @@
* Hardik Shah <hardik.shah@ti.com>
* Manjunath Hadli <mrh@ti.com>
* Karicheri Muralidharan <m-karicheri2@ti.com>
+ * Prabhakar Lad <prabhakar.lad@ti.com>
*
* This package is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -33,6 +34,7 @@
#include <linux/delay.h>
#include <linux/videodev2.h>
#include <linux/module.h>
+#include <linux/v4l2-mediabus.h>
#include <media/v4l2-device.h>
#include <media/v4l2-common.h>
@@ -40,12 +42,10 @@
#include <media/v4l2-chip-ident.h>
#include <media/v4l2-ctrls.h>
#include <media/tvp514x.h>
+#include <media/media-entity.h>
#include "tvp514x_regs.h"
-/* Module Name */
-#define TVP514X_MODULE_NAME "tvp514x"
-
/* Private macros for TVP */
#define I2C_RETRY_COUNT (5)
#define LOCK_RETRY_COUNT (5)
@@ -91,6 +91,9 @@ static int tvp514x_s_stream(struct v4l2_subdev *sd, int enable);
* @pdata: Board specific
* @ver: Chip version
* @streaming: TVP5146/47 decoder streaming - enabled or disabled.
+ * @pix: Current pixel format
+ * @num_fmts: Number of formats
+ * @fmt_list: Format list
* @current_std: Current standard
* @num_stds: Number of standards
* @std_list: Standards list
@@ -106,12 +109,20 @@ struct tvp514x_decoder {
int ver;
int streaming;
+ struct v4l2_pix_format pix;
+ int num_fmts;
+ const struct v4l2_fmtdesc *fmt_list;
+
enum tvp514x_std current_std;
int num_stds;
const struct tvp514x_std_info *std_list;
/* Input and Output Routing parameters */
u32 input;
u32 output;
+
+ /* mc related members */
+ struct media_pad pad;
+ struct v4l2_mbus_framefmt format;
};
/* TVP514x default register values */
@@ -200,6 +211,21 @@ static struct tvp514x_reg tvp514x_reg_list_default[] = {
};
/**
+ * List of image formats supported by TVP5146/47 decoder
+ * Currently we are using 8 bit mode only, but can be
+ * extended to 10/20 bit mode.
+ */
+static const struct v4l2_fmtdesc tvp514x_fmt_list[] = {
+ {
+ .index = 0,
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ .flags = 0,
+ .description = "8-bit UYVY 4:2:2 Format",
+ .pixelformat = V4L2_PIX_FMT_UYVY,
+ },
+};
+
+/**
* Supported standards -
*
* Currently supports two standards only, need to add support for rest of the
@@ -733,7 +759,7 @@ tvp514x_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
}
/**
- * tvp514x_mbus_fmt_cap() - V4L2 decoder interface handler for try/s/g_mbus_fmt
+ * tvp514x_mbus_fmt() - V4L2 decoder interface handler for try/s/g_mbus_fmt
* @sd: pointer to standard V4L2 sub-device structure
* @f: pointer to the mediabus format structure
*
@@ -751,12 +777,11 @@ tvp514x_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f)
/* Calculate height and width based on current standard */
current_std = decoder->current_std;
- f->code = V4L2_MBUS_FMT_YUYV10_2X10;
+ f->code = V4L2_MBUS_FMT_YUYV8_2X8;
f->width = decoder->std_list[current_std].width;
f->height = decoder->std_list[current_std].height;
f->field = V4L2_FIELD_INTERLACED;
f->colorspace = V4L2_COLORSPACE_SMPTE170M;
-
v4l2_dbg(1, debug, sd, "MBUS_FMT: Width - %d, Height - %d\n",
f->width, f->height);
return 0;
@@ -892,6 +917,88 @@ static const struct v4l2_ctrl_ops tvp514x_ctrl_ops = {
.s_ctrl = tvp514x_s_ctrl,
};
+/**
+ * tvp514x_enum_mbus_code() - V4L2 decoder interface handler for enum_mbus_code
+ * @sd: pointer to standard V4L2 sub-device structure
+ * @fh: file handle
+ * @code: pointer to v4l2_subdev_mbus_code_enum structure
+ *
+ * Enumertaes mbus codes supported
+ */
+static int tvp514x_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_mbus_code_enum *code)
+{
+ u32 pad = code->pad;
+ u32 index = code->index;
+
+ memset(code, 0, sizeof(*code));
+ code->index = index;
+ code->pad = pad;
+
+ if (index != 0)
+ return -EINVAL;
+
+ code->code = V4L2_MBUS_FMT_YUYV8_2X8;
+
+ return 0;
+}
+
+/**
+ * tvp514x_get_pad_format() - V4L2 decoder interface handler for get pad format
+ * @sd: pointer to standard V4L2 sub-device structure
+ * @fh: file handle
+ * @format: pointer to v4l2_subdev_format structure
+ *
+ * Retrieves pad format which is active or tried based on requirement
+ */
+static int tvp514x_get_pad_format(struct v4l2_subdev *sd,
+ struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_format *format)
+{
+ struct tvp514x_decoder *decoder = to_decoder(sd);
+ __u32 which = format->which;
+
+ if (which == V4L2_SUBDEV_FORMAT_ACTIVE) {
+ format->format = decoder->format;
+ return 0;
+ }
+
+ format->format.code = V4L2_MBUS_FMT_YUYV8_2X8;
+ format->format.width = tvp514x_std_list[decoder->current_std].width;
+ format->format.height = tvp514x_std_list[decoder->current_std].height;
+ format->format.colorspace = V4L2_COLORSPACE_SMPTE170M;
+ format->format.field = V4L2_FIELD_INTERLACED;
+
+ return 0;
+}
+
+/**
+ * tvp514x_set_pad_format() - V4L2 decoder interface handler for set pad format
+ * @sd: pointer to standard V4L2 sub-device structure
+ * @fh: file handle
+ * @format: pointer to v4l2_subdev_format structure
+ *
+ * Set pad format for the output pad
+ */
+static int tvp514x_set_pad_format(struct v4l2_subdev *sd,
+ struct v4l2_subdev_fh *fh,
+ struct v4l2_subdev_format *fmt)
+{
+ struct tvp514x_decoder *decoder = to_decoder(sd);
+
+ if (fmt->format.field != V4L2_FIELD_INTERLACED ||
+ fmt->format.code != V4L2_MBUS_FMT_YUYV8_2X8 ||
+ fmt->format.colorspace != V4L2_COLORSPACE_SMPTE170M ||
+ fmt->format.width != tvp514x_std_list[decoder->current_std].width ||
+ fmt->format.height != tvp514x_std_list[decoder->current_std].height)
+ return -EINVAL;
+
+ decoder->format = fmt->format;
+
+ return 0;
+}
+
static const struct v4l2_subdev_core_ops tvp514x_core_ops = {
.g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
@@ -915,13 +1022,33 @@ static const struct v4l2_subdev_video_ops tvp514x_video_ops = {
.s_stream = tvp514x_s_stream,
};
+static const struct v4l2_subdev_pad_ops tvp514x_pad_ops = {
+ .enum_mbus_code = tvp514x_enum_mbus_code,
+ .get_fmt = tvp514x_get_pad_format,
+ .set_fmt = tvp514x_set_pad_format,
+};
+
static const struct v4l2_subdev_ops tvp514x_ops = {
.core = &tvp514x_core_ops,
.video = &tvp514x_video_ops,
+ .pad = &tvp514x_pad_ops,
};
static struct tvp514x_decoder tvp514x_dev = {
.streaming = 0,
+ .fmt_list = tvp514x_fmt_list,
+ .num_fmts = ARRAY_SIZE(tvp514x_fmt_list),
+ .pix = {
+ /* Default to NTSC 8-bit YUV 422 */
+ .width = NTSC_NUM_ACTIVE_PIXELS,
+ .height = NTSC_NUM_ACTIVE_LINES,
+ .pixelformat = V4L2_PIX_FMT_UYVY,
+ .field = V4L2_FIELD_INTERLACED,
+ .bytesperline = NTSC_NUM_ACTIVE_PIXELS * 2,
+ .sizeimage = NTSC_NUM_ACTIVE_PIXELS * 2 *
+ NTSC_NUM_ACTIVE_LINES,
+ .colorspace = V4L2_COLORSPACE_SMPTE170M,
+ },
.current_std = STD_NTSC_MJ,
.std_list = tvp514x_std_list,
.num_stds = ARRAY_SIZE(tvp514x_std_list),
@@ -941,6 +1068,7 @@ tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
struct tvp514x_decoder *decoder;
struct v4l2_subdev *sd;
+ int ret;
/* Check if the adapter supports the needed features */
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
@@ -981,7 +1109,21 @@ tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id)
/* Register with V4L2 layer as slave device */
sd = &decoder->sd;
v4l2_i2c_subdev_init(sd, client, &tvp514x_ops);
-
+ strlcpy(sd->name, TVP514X_MODULE_NAME, sizeof(sd->name));
+
+#if defined(CONFIG_MEDIA_CONTROLLER)
+ decoder->pad.flags = MEDIA_PAD_FL_SOURCE;
+ decoder->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+ decoder->sd.entity.flags |= MEDIA_ENT_T_V4L2_SUBDEV_DECODER;
+
+ ret = media_entity_init(&decoder->sd.entity, 1, &decoder->pad, 0);
+ if (ret < 0) {
+ v4l2_err(sd, "%s decoder driver failed to register !!\n",
+ sd->name);
+ kfree(decoder);
+ return ret;
+ }
+#endif
v4l2_ctrl_handler_init(&decoder->hdl, 5);
v4l2_ctrl_new_std(&decoder->hdl, &tvp514x_ctrl_ops,
V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
@@ -995,10 +1137,10 @@ tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id)
V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
sd->ctrl_handler = &decoder->hdl;
if (decoder->hdl.error) {
- int err = decoder->hdl.error;
+ ret = decoder->hdl.error;
v4l2_ctrl_handler_free(&decoder->hdl);
- return err;
+ return ret;
}
v4l2_ctrl_handler_setup(&decoder->hdl);
@@ -1021,6 +1163,9 @@ static int tvp514x_remove(struct i2c_client *client)
struct tvp514x_decoder *decoder = to_decoder(sd);
v4l2_device_unregister_subdev(sd);
+#if defined(CONFIG_MEDIA_CONTROLLER)
+ media_entity_cleanup(&decoder->sd.entity);
+#endif
v4l2_ctrl_handler_free(&decoder->hdl);
return 0;
}