#include <media/v4l2-device.h>
#include <media/v4l2-common.h>
+#include <media/v4l2-mediabus.h>
#include <media/v4l2-chip-ident.h>
#include <media/tvp514x.h>
};
static struct tvp514x_reg tvp514x_reg_list_default[0x40];
+
+static int tvp514x_s_stream(struct v4l2_subdev *sd, int enable);
/**
* struct tvp514x_decoder - TVP5146/47 decoder object
* @sd: Subdevice Slave handle
* @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
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;
- struct tvp514x_std_info *std_list;
+ const struct tvp514x_std_info *std_list;
/* Input and Output Routing parameters */
u32 input;
u32 output;
{TOK_TERM, 0, 0},
};
-/**
- * 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
* modes, like SECAM, etc...
*/
-static struct tvp514x_std_info tvp514x_std_list[] = {
+static const struct tvp514x_std_info tvp514x_std_list[] = {
/* Standard: STD_NTSC_MJ */
[STD_NTSC_MJ] = {
.width = NTSC_NUM_ACTIVE_PIXELS,
}
/**
- * tvp514x_get_current_std() : Get the current standard detected by TVP5146/47
+ * tvp514x_query_current_std() : Query the current standard detected by TVP5146/47
* @sd: ptr to v4l2_subdev struct
*
- * Get current standard detected by TVP5146/47, STD_INVALID if there is no
+ * Returns the current standard detected by TVP5146/47, STD_INVALID if there is no
* standard detected.
*/
-static enum tvp514x_std tvp514x_get_current_std(struct v4l2_subdev *sd)
+static enum tvp514x_std tvp514x_query_current_std(struct v4l2_subdev *sd)
{
u8 std, std_status;
* @std_id: standard V4L2 std_id ioctl enum
*
* Returns the current standard detected by TVP5146/47. If no active input is
- * detected, returns -EINVAL
+ * detected then *std_id is set to 0 and the function returns 0.
*/
static int tvp514x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id)
{
if (std_id == NULL)
return -EINVAL;
- /* get the current standard */
- current_std = tvp514x_get_current_std(sd);
+ *std_id = V4L2_STD_UNKNOWN;
+
+ /* query the current standard */
+ current_std = tvp514x_query_current_std(sd);
if (current_std == STD_INVALID)
- return -EINVAL;
+ return 0;
input_sel = decoder->input;
/* check whether signal is locked */
sync_lock_status = tvp514x_read_reg(sd, REG_STATUS1);
if (lock_mask != (sync_lock_status & lock_mask))
- return -EINVAL; /* No input detected */
+ return 0; /* No input detected */
- decoder->current_std = current_std;
*std_id = decoder->std_list[current_std].standard.id;
- v4l2_dbg(1, debug, sd, "Current STD: %s",
+ v4l2_dbg(1, debug, sd, "Current STD: %s\n",
decoder->std_list[current_std].standard.name);
return 0;
}
decoder->tvp514x_regs[REG_VIDEO_STD].val =
decoder->std_list[i].video_std;
- v4l2_dbg(1, debug, sd, "Standard set to: %s",
+ v4l2_dbg(1, debug, sd, "Standard set to: %s\n",
decoder->std_list[i].standard.name);
return 0;
}
int err;
enum tvp514x_input input_sel;
enum tvp514x_output output_sel;
- enum tvp514x_std current_std = STD_INVALID;
u8 sync_lock_status, lock_mask;
int try_count = LOCK_RETRY_COUNT;
/* Index out of bound */
return -EINVAL;
+ /*
+ * For the sequence streamon -> streamoff and again s_input
+ * it fails to lock the signal, since streamoff puts TVP514x
+ * into power off state which leads to failure in sub-sequent s_input.
+ *
+ * So power up the TVP514x device here, since it is important to lock
+ * the signal at this stage.
+ */
+ if (!decoder->streaming)
+ tvp514x_s_stream(sd, 1);
+
input_sel = input;
output_sel = output;
/* Allow decoder to sync up with new input */
msleep(LOCK_RETRY_DELAY);
- /* get the current standard for future reference */
- current_std = tvp514x_get_current_std(sd);
- if (current_std == STD_INVALID)
- continue;
-
sync_lock_status = tvp514x_read_reg(sd,
REG_STATUS1);
if (lock_mask == (sync_lock_status & lock_mask))
break;
}
- if ((current_std == STD_INVALID) || (try_count < 0))
+ if (try_count < 0)
return -EINVAL;
- decoder->current_std = current_std;
decoder->input = input;
decoder->output = output;
- v4l2_dbg(1, debug, sd, "Input set to: %d, std : %d",
- input_sel, current_std);
+ v4l2_dbg(1, debug, sd, "Input set to: %d\n", input_sel);
return 0;
}
return err;
}
- v4l2_dbg(1, debug, sd, "Query Control:%s: Min - %d, Max - %d, Def - %d",
+ v4l2_dbg(1, debug, sd, "Query Control:%s: Min - %d, Max - %d, Def - %d\n",
qctrl->name, qctrl->minimum, qctrl->maximum,
qctrl->default_value);
return -EINVAL;
}
- v4l2_dbg(1, debug, sd, "Get Control: ID - %d - %d",
+ v4l2_dbg(1, debug, sd, "Get Control: ID - %d - %d\n",
ctrl->id, ctrl->value);
return 0;
}
return err;
}
- v4l2_dbg(1, debug, sd, "Set Control: ID - %d - %d",
+ v4l2_dbg(1, debug, sd, "Set Control: ID - %d - %d\n",
ctrl->id, ctrl->value);
return err;
}
/**
- * tvp514x_enum_fmt_cap() - V4L2 decoder interface handler for enum_fmt
+ * tvp514x_enum_mbus_fmt() - V4L2 decoder interface handler for enum_mbus_fmt
* @sd: pointer to standard V4L2 sub-device structure
- * @fmt: standard V4L2 VIDIOC_ENUM_FMT ioctl structure
+ * @index: index of pixelcode to retrieve
+ * @code: receives the pixelcode
*
- * Implement the VIDIOC_ENUM_FMT ioctl to enumerate supported formats
+ * Enumerates supported mediabus formats
*/
static int
-tvp514x_enum_fmt_cap(struct v4l2_subdev *sd, struct v4l2_fmtdesc *fmt)
+tvp514x_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
+ enum v4l2_mbus_pixelcode *code)
{
- struct tvp514x_decoder *decoder = to_decoder(sd);
- int index;
-
- if (fmt == NULL)
+ if (index)
return -EINVAL;
- index = fmt->index;
- if ((index >= decoder->num_fmts) || (index < 0))
- /* Index out of bound */
- return -EINVAL;
-
- if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- /* only capture is supported */
- return -EINVAL;
-
- memcpy(fmt, &decoder->fmt_list[index],
- sizeof(struct v4l2_fmtdesc));
-
- v4l2_dbg(1, debug, sd, "Current FMT: index - %d (%s)",
- decoder->fmt_list[index].index,
- decoder->fmt_list[index].description);
+ *code = V4L2_MBUS_FMT_YUYV10_2X10;
return 0;
}
/**
- * tvp514x_try_fmt_cap() - V4L2 decoder interface handler for try_fmt
+ * tvp514x_mbus_fmt_cap() - V4L2 decoder interface handler for try/s/g_mbus_fmt
* @sd: pointer to standard V4L2 sub-device structure
- * @f: pointer to standard V4L2 VIDIOC_TRY_FMT ioctl structure
+ * @f: pointer to the mediabus format structure
*
- * Implement the VIDIOC_TRY_FMT ioctl for the CAPTURE buffer type. This
- * ioctl is used to negotiate the image capture size and pixel format
- * without actually making it take effect.
+ * Negotiates the image capture size and mediabus format.
*/
static int
-tvp514x_try_fmt_cap(struct v4l2_subdev *sd, struct v4l2_format *f)
+tvp514x_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f)
{
struct tvp514x_decoder *decoder = to_decoder(sd);
- int ifmt;
- struct v4l2_pix_format *pix;
enum tvp514x_std current_std;
if (f == NULL)
return -EINVAL;
- if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- /* only capture is supported */
- f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
- pix = &f->fmt.pix;
-
/* Calculate height and width based on current standard */
- current_std = tvp514x_get_current_std(sd);
- if (current_std == STD_INVALID)
- return -EINVAL;
+ current_std = decoder->current_std;
- decoder->current_std = current_std;
- pix->width = decoder->std_list[current_std].width;
- pix->height = decoder->std_list[current_std].height;
+ f->code = V4L2_MBUS_FMT_YUYV10_2X10;
+ 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;
- for (ifmt = 0; ifmt < decoder->num_fmts; ifmt++) {
- if (pix->pixelformat ==
- decoder->fmt_list[ifmt].pixelformat)
- break;
- }
- if (ifmt == decoder->num_fmts)
- /* None of the format matched, select default */
- ifmt = 0;
- pix->pixelformat = decoder->fmt_list[ifmt].pixelformat;
-
- pix->field = V4L2_FIELD_INTERLACED;
- pix->bytesperline = pix->width * 2;
- pix->sizeimage = pix->bytesperline * pix->height;
- pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
- pix->priv = 0;
-
- v4l2_dbg(1, debug, sd, "Try FMT: pixelformat - %s, bytesperline - %d"
- "Width - %d, Height - %d",
- decoder->fmt_list[ifmt].description, pix->bytesperline,
- pix->width, pix->height);
- return 0;
-}
-
-/**
- * tvp514x_s_fmt_cap() - V4L2 decoder interface handler for s_fmt
- * @sd: pointer to standard V4L2 sub-device structure
- * @f: pointer to standard V4L2 VIDIOC_S_FMT ioctl structure
- *
- * If the requested format is supported, configures the HW to use that
- * format, returns error code if format not supported or HW can't be
- * correctly configured.
- */
-static int
-tvp514x_s_fmt_cap(struct v4l2_subdev *sd, struct v4l2_format *f)
-{
- struct tvp514x_decoder *decoder = to_decoder(sd);
- struct v4l2_pix_format *pix;
- int rval;
-
- if (f == NULL)
- return -EINVAL;
-
- if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- /* only capture is supported */
- return -EINVAL;
-
- pix = &f->fmt.pix;
- rval = tvp514x_try_fmt_cap(sd, f);
- if (rval)
- return rval;
-
- decoder->pix = *pix;
-
- return rval;
-}
-
-/**
- * tvp514x_g_fmt_cap() - V4L2 decoder interface handler for tvp514x_g_fmt_cap
- * @sd: pointer to standard V4L2 sub-device structure
- * @f: pointer to standard V4L2 v4l2_format structure
- *
- * Returns the decoder's current pixel format in the v4l2_format
- * parameter.
- */
-static int
-tvp514x_g_fmt_cap(struct v4l2_subdev *sd, struct v4l2_format *f)
-{
- struct tvp514x_decoder *decoder = to_decoder(sd);
-
- if (f == NULL)
- return -EINVAL;
-
- if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- /* only capture is supported */
- return -EINVAL;
-
- f->fmt.pix = decoder->pix;
-
- v4l2_dbg(1, debug, sd, "Current FMT: bytesperline - %d"
- "Width - %d, Height - %d",
- decoder->pix.bytesperline,
- decoder->pix.width, decoder->pix.height);
+ v4l2_dbg(1, debug, sd, "MBUS_FMT: Width - %d, Height - %d\n",
+ f->width, f->height);
return 0;
}
/* only capture is supported */
return -EINVAL;
- memset(a, 0, sizeof(*a));
- a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
/* get the current standard */
- current_std = tvp514x_get_current_std(sd);
- if (current_std == STD_INVALID)
- return -EINVAL;
-
- decoder->current_std = current_std;
+ current_std = decoder->current_std;
cparm = &a->parm.capture;
cparm->capability = V4L2_CAP_TIMEPERFRAME;
timeperframe = &a->parm.capture.timeperframe;
/* get the current standard */
- current_std = tvp514x_get_current_std(sd);
- if (current_std == STD_INVALID)
- return -EINVAL;
-
- decoder->current_std = current_std;
+ current_std = decoder->current_std;
*timeperframe =
decoder->std_list[current_std].standard.frameperiod;
static const struct v4l2_subdev_video_ops tvp514x_video_ops = {
.s_routing = tvp514x_s_routing,
.querystd = tvp514x_querystd,
- .enum_fmt = tvp514x_enum_fmt_cap,
- .g_fmt = tvp514x_g_fmt_cap,
- .try_fmt = tvp514x_try_fmt_cap,
- .s_fmt = tvp514x_s_fmt_cap,
+ .enum_mbus_fmt = tvp514x_enum_mbus_fmt,
+ .g_mbus_fmt = tvp514x_mbus_fmt,
+ .try_mbus_fmt = tvp514x_mbus_fmt,
+ .s_mbus_fmt = tvp514x_mbus_fmt,
.g_parm = tvp514x_g_parm,
.s_parm = tvp514x_s_parm,
.s_stream = tvp514x_s_stream,
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),