summaryrefslogtreecommitdiff
path: root/drivers/media/video/davinci
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/davinci')
-rw-r--r--drivers/media/video/davinci/vpif.c177
-rw-r--r--drivers/media/video/davinci/vpif.h18
-rw-r--r--drivers/media/video/davinci/vpif_capture.c451
-rw-r--r--drivers/media/video/davinci/vpif_capture.h2
-rw-r--r--drivers/media/video/davinci/vpif_display.c474
-rw-r--r--drivers/media/video/davinci/vpif_display.h2
6 files changed, 907 insertions, 217 deletions
diff --git a/drivers/media/video/davinci/vpif.c b/drivers/media/video/davinci/vpif.c
index 1f532e31cd49..9f3bfc1eb240 100644
--- a/drivers/media/video/davinci/vpif.c
+++ b/drivers/media/video/davinci/vpif.c
@@ -41,6 +41,183 @@ spinlock_t vpif_lock;
void __iomem *vpif_base;
+/**
+ * ch_params: video standard configuration parameters for vpif
+ * The table must include all presets from supported subdevices.
+ */
+const struct vpif_channel_config_params ch_params[] = {
+ /* HDTV formats */
+ {
+ .name = "480p59_94",
+ .width = 720,
+ .height = 480,
+ .frm_fmt = 1,
+ .ycmux_mode = 0,
+ .eav2sav = 138-8,
+ .sav2eav = 720,
+ .l1 = 1,
+ .l3 = 43,
+ .l5 = 523,
+ .vsize = 525,
+ .capture_format = 0,
+ .vbi_supported = 0,
+ .hd_sd = 1,
+ .dv_preset = V4L2_DV_480P59_94,
+ },
+ {
+ .name = "576p50",
+ .width = 720,
+ .height = 576,
+ .frm_fmt = 1,
+ .ycmux_mode = 0,
+ .eav2sav = 144-8,
+ .sav2eav = 720,
+ .l1 = 1,
+ .l3 = 45,
+ .l5 = 621,
+ .vsize = 625,
+ .capture_format = 0,
+ .vbi_supported = 0,
+ .hd_sd = 1,
+ .dv_preset = V4L2_DV_576P50,
+ },
+ {
+ .name = "720p50",
+ .width = 1280,
+ .height = 720,
+ .frm_fmt = 1,
+ .ycmux_mode = 0,
+ .eav2sav = 700-8,
+ .sav2eav = 1280,
+ .l1 = 1,
+ .l3 = 26,
+ .l5 = 746,
+ .vsize = 750,
+ .capture_format = 0,
+ .vbi_supported = 0,
+ .hd_sd = 1,
+ .dv_preset = V4L2_DV_720P50,
+ },
+ {
+ .name = "720p60",
+ .width = 1280,
+ .height = 720,
+ .frm_fmt = 1,
+ .ycmux_mode = 0,
+ .eav2sav = 370 - 8,
+ .sav2eav = 1280,
+ .l1 = 1,
+ .l3 = 26,
+ .l5 = 746,
+ .vsize = 750,
+ .capture_format = 0,
+ .vbi_supported = 0,
+ .hd_sd = 1,
+ .dv_preset = V4L2_DV_720P60,
+ },
+ {
+ .name = "1080I50",
+ .width = 1920,
+ .height = 1080,
+ .frm_fmt = 0,
+ .ycmux_mode = 0,
+ .eav2sav = 720 - 8,
+ .sav2eav = 1920,
+ .l1 = 1,
+ .l3 = 21,
+ .l5 = 561,
+ .l7 = 563,
+ .l9 = 584,
+ .l11 = 1124,
+ .vsize = 1125,
+ .capture_format = 0,
+ .vbi_supported = 0,
+ .hd_sd = 1,
+ .dv_preset = V4L2_DV_1080I50,
+ },
+ {
+ .name = "1080I60",
+ .width = 1920,
+ .height = 1080,
+ .frm_fmt = 0,
+ .ycmux_mode = 0,
+ .eav2sav = 280 - 8,
+ .sav2eav = 1920,
+ .l1 = 1,
+ .l3 = 21,
+ .l5 = 561,
+ .l7 = 563,
+ .l9 = 584,
+ .l11 = 1124,
+ .vsize = 1125,
+ .capture_format = 0,
+ .vbi_supported = 0,
+ .hd_sd = 1,
+ .dv_preset = V4L2_DV_1080I60,
+ },
+ {
+ .name = "1080p60",
+ .width = 1920,
+ .height = 1080,
+ .frm_fmt = 1,
+ .ycmux_mode = 0,
+ .eav2sav = 280 - 8,
+ .sav2eav = 1920,
+ .l1 = 1,
+ .l3 = 42,
+ .l5 = 1122,
+ .vsize = 1125,
+ .capture_format = 0,
+ .vbi_supported = 0,
+ .hd_sd = 1,
+ .dv_preset = V4L2_DV_1080P60,
+ },
+
+ /* SDTV formats */
+ {
+ .name = "NTSC_M",
+ .width = 720,
+ .height = 480,
+ .frm_fmt = 0,
+ .ycmux_mode = 1,
+ .eav2sav = 268,
+ .sav2eav = 1440,
+ .l1 = 1,
+ .l3 = 23,
+ .l5 = 263,
+ .l7 = 266,
+ .l9 = 286,
+ .l11 = 525,
+ .vsize = 525,
+ .capture_format = 0,
+ .vbi_supported = 1,
+ .hd_sd = 0,
+ .stdid = V4L2_STD_525_60,
+ },
+ {
+ .name = "PAL_BDGHIK",
+ .width = 720,
+ .height = 576,
+ .frm_fmt = 0,
+ .ycmux_mode = 1,
+ .eav2sav = 280,
+ .sav2eav = 1440,
+ .l1 = 1,
+ .l3 = 23,
+ .l5 = 311,
+ .l7 = 313,
+ .l9 = 336,
+ .l11 = 624,
+ .vsize = 625,
+ .capture_format = 0,
+ .vbi_supported = 1,
+ .hd_sd = 0,
+ .stdid = V4L2_STD_625_50,
+ },
+};
+
+const unsigned int vpif_ch_params_count = ARRAY_SIZE(ch_params);
+
static inline void vpif_wr_bit(u32 reg, u32 bit, u32 val)
{
if (val)
diff --git a/drivers/media/video/davinci/vpif.h b/drivers/media/video/davinci/vpif.h
index ebd5c4338ebb..10550bd93b06 100644
--- a/drivers/media/video/davinci/vpif.h
+++ b/drivers/media/video/davinci/vpif.h
@@ -577,12 +577,10 @@ struct vpif_channel_config_params {
char name[VPIF_MAX_NAME]; /* Name of the mode */
u16 width; /* Indicates width of the image */
u16 height; /* Indicates height of the image */
- u8 fps;
- u8 frm_fmt; /* Indicates whether this is interlaced
- * or progressive format */
- u8 ycmux_mode; /* Indicates whether this mode requires
- * single or two channels */
- u16 eav2sav; /* length of sav 2 eav */
+ u8 frm_fmt; /* Interlaced (0) or progressive (1) */
+ u8 ycmux_mode; /* This mode requires one (0) or two (1)
+ channels */
+ u16 eav2sav; /* length of eav 2 sav */
u16 sav2eav; /* length of sav 2 eav */
u16 l1, l3, l5, l7, l9, l11; /* Other parameter configurations */
u16 vsize; /* Vertical size of the image */
@@ -590,10 +588,14 @@ struct vpif_channel_config_params {
* is in BT or in CCD/CMOS */
u8 vbi_supported; /* Indicates whether this mode
* supports capturing vbi or not */
- u8 hd_sd;
- v4l2_std_id stdid;
+ u8 hd_sd; /* HDTV (1) or SDTV (0) format */
+ v4l2_std_id stdid; /* SDTV format */
+ u32 dv_preset; /* HDTV format */
};
+extern const unsigned int vpif_ch_params_count;
+extern const struct vpif_channel_config_params ch_params[];
+
struct vpif_video_params;
struct vpif_params;
struct vpif_vbi_params;
diff --git a/drivers/media/video/davinci/vpif_capture.c b/drivers/media/video/davinci/vpif_capture.c
index 193abab6b355..d93ad74a34c5 100644
--- a/drivers/media/video/davinci/vpif_capture.c
+++ b/drivers/media/video/davinci/vpif_capture.c
@@ -37,6 +37,7 @@
#include <linux/slab.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
+#include <media/v4l2-chip-ident.h>
#include "vpif_capture.h"
#include "vpif.h"
@@ -81,20 +82,6 @@ static struct vpif_device vpif_obj = { {NULL} };
static struct device *vpif_dev;
/**
- * ch_params: video standard configuration parameters for vpif
- */
-static const struct vpif_channel_config_params ch_params[] = {
- {
- "NTSC_M", 720, 480, 30, 0, 1, 268, 1440, 1, 23, 263, 266,
- 286, 525, 525, 0, 1, 0, V4L2_STD_525_60,
- },
- {
- "PAL_BDGHIK", 720, 576, 25, 0, 1, 280, 1440, 1, 23, 311, 313,
- 336, 624, 625, 0, 1, 0, V4L2_STD_625_50,
- },
-};
-
-/**
* vpif_uservirt_to_phys : translate user/virtual address to phy address
* @virtp: user/virtual address
*
@@ -342,7 +329,7 @@ static void vpif_schedule_next_buffer(struct common_obj *common)
* @dev_id: dev_id ptr
*
* It changes status of the captured buffer, takes next buffer from the queue
- * and sets its address in VPIF registers
+ * and sets its address in VPIF registers
*/
static irqreturn_t vpif_channel_isr(int irq, void *dev_id)
{
@@ -435,24 +422,31 @@ static int vpif_update_std_info(struct channel_obj *ch)
struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
struct vpif_params *vpifparams = &ch->vpifparams;
const struct vpif_channel_config_params *config;
- struct vpif_channel_config_params *std_info;
+ struct vpif_channel_config_params *std_info = &vpifparams->std_info;
struct video_obj *vid_ch = &ch->video;
int index;
vpif_dbg(2, debug, "vpif_update_std_info\n");
- std_info = &vpifparams->std_info;
-
- for (index = 0; index < ARRAY_SIZE(ch_params); index++) {
+ for (index = 0; index < vpif_ch_params_count; index++) {
config = &ch_params[index];
- if (config->stdid & vid_ch->stdid) {
- memcpy(std_info, config, sizeof(*config));
- break;
+ if (config->hd_sd == 0) {
+ vpif_dbg(2, debug, "SD format\n");
+ if (config->stdid & vid_ch->stdid) {
+ memcpy(std_info, config, sizeof(*config));
+ break;
+ }
+ } else {
+ vpif_dbg(2, debug, "HD format\n");
+ if (config->dv_preset == vid_ch->dv_preset) {
+ memcpy(std_info, config, sizeof(*config));
+ break;
+ }
}
}
/* standard not found */
- if (index == ARRAY_SIZE(ch_params))
+ if (index == vpif_ch_params_count)
return -EINVAL;
common->fmt.fmt.pix.width = std_info->width;
@@ -462,6 +456,7 @@ static int vpif_update_std_info(struct channel_obj *ch)
common->fmt.fmt.pix.bytesperline = std_info->width;
vpifparams->video_params.hpitch = std_info->width;
vpifparams->video_params.storage_mode = std_info->frm_fmt;
+
return 0;
}
@@ -757,7 +752,7 @@ static int vpif_open(struct file *filep)
struct video_obj *vid_ch;
struct channel_obj *ch;
struct vpif_fh *fh;
- int i, ret = 0;
+ int i;
vpif_dbg(2, debug, "vpif_open\n");
@@ -766,9 +761,6 @@ static int vpif_open(struct file *filep)
vid_ch = &ch->video;
common = &ch->common[VPIF_VIDEO_INDEX];
- if (mutex_lock_interruptible(&common->lock))
- return -ERESTARTSYS;
-
if (NULL == ch->curr_subdev_info) {
/**
* search through the sub device to see a registered
@@ -785,8 +777,7 @@ static int vpif_open(struct file *filep)
}
if (i == config->subdev_count) {
vpif_err("No sub device registered\n");
- ret = -ENOENT;
- goto exit;
+ return -ENOENT;
}
}
@@ -794,8 +785,7 @@ static int vpif_open(struct file *filep)
fh = kzalloc(sizeof(struct vpif_fh), GFP_KERNEL);
if (NULL == fh) {
vpif_err("unable to allocate memory for file handle object\n");
- ret = -ENOMEM;
- goto exit;
+ return -ENOMEM;
}
/* store pointer to fh in private_data member of filep */
@@ -815,9 +805,7 @@ static int vpif_open(struct file *filep)
/* Initialize priority of this instance to default priority */
fh->prio = V4L2_PRIORITY_UNSET;
v4l2_prio_open(&ch->prio, &fh->prio);
-exit:
- mutex_unlock(&common->lock);
- return ret;
+ return 0;
}
/**
@@ -837,9 +825,6 @@ static int vpif_release(struct file *filep)
common = &ch->common[VPIF_VIDEO_INDEX];
- if (mutex_lock_interruptible(&common->lock))
- return -ERESTARTSYS;
-
/* if this instance is doing IO */
if (fh->io_allowed[VPIF_VIDEO_INDEX]) {
/* Reset io_usrs member of channel object */
@@ -863,9 +848,6 @@ static int vpif_release(struct file *filep)
/* Decrement channel usrs counter */
ch->usrs--;
- /* unlock mutex on channel object */
- mutex_unlock(&common->lock);
-
/* Close the priority */
v4l2_prio_close(&ch->prio, fh->prio);
@@ -890,7 +872,6 @@ static int vpif_reqbufs(struct file *file, void *priv,
struct channel_obj *ch = fh->channel;
struct common_obj *common;
u8 index = 0;
- int ret = 0;
vpif_dbg(2, debug, "vpif_reqbufs\n");
@@ -913,13 +894,8 @@ static int vpif_reqbufs(struct file *file, void *priv,
common = &ch->common[index];
- if (mutex_lock_interruptible(&common->lock))
- return -ERESTARTSYS;
-
- if (0 != common->io_usrs) {
- ret = -EBUSY;
- goto reqbuf_exit;
- }
+ if (0 != common->io_usrs)
+ return -EBUSY;
/* Initialize videobuf queue as per the buffer type */
videobuf_queue_dma_contig_init(&common->buffer_queue,
@@ -928,7 +904,7 @@ static int vpif_reqbufs(struct file *file, void *priv,
reqbuf->type,
common->fmt.fmt.pix.field,
sizeof(struct videobuf_buffer), fh,
- NULL);
+ &common->lock);
/* Set io allowed member of file handle to TRUE */
fh->io_allowed[index] = 1;
@@ -939,11 +915,7 @@ static int vpif_reqbufs(struct file *file, void *priv,
INIT_LIST_HEAD(&common->dma_queue);
/* Allocate buffers */
- ret = videobuf_reqbufs(&common->buffer_queue, reqbuf);
-
-reqbuf_exit:
- mutex_unlock(&common->lock);
- return ret;
+ return videobuf_reqbufs(&common->buffer_queue, reqbuf);
}
/**
@@ -1157,11 +1129,6 @@ static int vpif_streamon(struct file *file, void *priv,
return ret;
}
- if (mutex_lock_interruptible(&common->lock)) {
- ret = -ERESTARTSYS;
- goto streamoff_exit;
- }
-
/* If buffer queue is empty, return error */
if (list_empty(&common->dma_queue)) {
vpif_dbg(1, debug, "buffer queue is empty\n");
@@ -1240,13 +1207,10 @@ static int vpif_streamon(struct file *file, void *priv,
enable_channel1(1);
}
channel_first_int[VPIF_VIDEO_INDEX][ch->channel_id] = 1;
- mutex_unlock(&common->lock);
return ret;
exit:
- mutex_unlock(&common->lock);
-streamoff_exit:
- ret = videobuf_streamoff(&common->buffer_queue);
+ videobuf_streamoff(&common->buffer_queue);
return ret;
}
@@ -1284,9 +1248,6 @@ static int vpif_streamoff(struct file *file, void *priv,
return -EINVAL;
}
- if (mutex_lock_interruptible(&common->lock))
- return -ERESTARTSYS;
-
/* disable channel */
if (VPIF_CHANNEL0_VIDEO == ch->channel_id) {
enable_channel0(0);
@@ -1304,8 +1265,6 @@ static int vpif_streamoff(struct file *file, void *priv,
if (ret && (ret != -ENOIOCTLCMD))
vpif_dbg(1, debug, "stream off failed in subdev\n");
- mutex_unlock(&common->lock);
-
return videobuf_streamoff(&common->buffer_queue);
}
@@ -1381,21 +1340,16 @@ static int vpif_querystd(struct file *file, void *priv, v4l2_std_id *std_id)
{
struct vpif_fh *fh = priv;
struct channel_obj *ch = fh->channel;
- struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
int ret = 0;
vpif_dbg(2, debug, "vpif_querystd\n");
- if (mutex_lock_interruptible(&common->lock))
- return -ERESTARTSYS;
-
/* Call querystd function of decoder device */
ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], video,
querystd, std_id);
if (ret < 0)
vpif_dbg(1, debug, "Failed to set standard for sub devices\n");
- mutex_unlock(&common->lock);
return ret;
}
@@ -1451,16 +1405,14 @@ static int vpif_s_std(struct file *file, void *priv, v4l2_std_id *std_id)
fh->initialized = 1;
/* Call encoder subdevice function to set the standard */
- if (mutex_lock_interruptible(&common->lock))
- return -ERESTARTSYS;
-
ch->video.stdid = *std_id;
+ ch->video.dv_preset = V4L2_DV_INVALID;
+ memset(&ch->video.bt_timings, 0, sizeof(ch->video.bt_timings));
/* Get the information about the standard */
if (vpif_update_std_info(ch)) {
- ret = -EINVAL;
vpif_err("Error getting the standard info\n");
- goto s_std_exit;
+ return -EINVAL;
}
/* Configure the default format information */
@@ -1471,9 +1423,6 @@ static int vpif_s_std(struct file *file, void *priv, v4l2_std_id *std_id)
s_std, *std_id);
if (ret < 0)
vpif_dbg(1, debug, "Failed to set standard for sub devices\n");
-
-s_std_exit:
- mutex_unlock(&common->lock);
return ret;
}
@@ -1567,9 +1516,6 @@ static int vpif_s_input(struct file *file, void *priv, unsigned int index)
return -EINVAL;
}
- if (mutex_lock_interruptible(&common->lock))
- return -ERESTARTSYS;
-
/* first setup input path from sub device to vpif */
if (config->setup_input_path) {
ret = config->setup_input_path(ch->channel_id,
@@ -1578,7 +1524,7 @@ static int vpif_s_input(struct file *file, void *priv, unsigned int index)
vpif_dbg(1, debug, "couldn't setup input path for the"
" sub device %s, for input index %d\n",
subdev_info->name, index);
- goto exit;
+ return ret;
}
}
@@ -1589,7 +1535,7 @@ static int vpif_s_input(struct file *file, void *priv, unsigned int index)
input, output, 0);
if (ret < 0) {
vpif_dbg(1, debug, "Failed to set input\n");
- goto exit;
+ return ret;
}
}
vid_ch->input_idx = index;
@@ -1600,9 +1546,6 @@ static int vpif_s_input(struct file *file, void *priv, unsigned int index)
/* update tvnorms from the sub device input info */
ch->video_dev->tvnorms = chan_cfg->inputs[index].input.std;
-
-exit:
- mutex_unlock(&common->lock);
return ret;
}
@@ -1671,11 +1614,7 @@ static int vpif_g_fmt_vid_cap(struct file *file, void *priv,
return -EINVAL;
/* Fill in the information about format */
- if (mutex_lock_interruptible(&common->lock))
- return -ERESTARTSYS;
-
*fmt = common->fmt;
- mutex_unlock(&common->lock);
return 0;
}
@@ -1694,7 +1633,7 @@ static int vpif_s_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_pix_format *pixfmt;
int ret = 0;
- vpif_dbg(2, debug, "VIDIOC_S_FMT\n");
+ vpif_dbg(2, debug, "%s\n", __func__);
/* If streaming is started, return error */
if (common->started) {
@@ -1723,12 +1662,7 @@ static int vpif_s_fmt_vid_cap(struct file *file, void *priv,
if (ret)
return ret;
/* store the format in the channel object */
- if (mutex_lock_interruptible(&common->lock))
- return -ERESTARTSYS;
-
common->fmt = *fmt;
- mutex_unlock(&common->lock);
-
return 0;
}
@@ -1807,6 +1741,306 @@ static int vpif_cropcap(struct file *file, void *priv,
return 0;
}
+/**
+ * vpif_enum_dv_presets() - ENUM_DV_PRESETS handler
+ * @file: file ptr
+ * @priv: file handle
+ * @preset: input preset
+ */
+static int vpif_enum_dv_presets(struct file *file, void *priv,
+ struct v4l2_dv_enum_preset *preset)
+{
+ struct vpif_fh *fh = priv;
+ struct channel_obj *ch = fh->channel;
+
+ return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index],
+ video, enum_dv_presets, preset);
+}
+
+/**
+ * vpif_query_dv_presets() - QUERY_DV_PRESET handler
+ * @file: file ptr
+ * @priv: file handle
+ * @preset: input preset
+ */
+static int vpif_query_dv_preset(struct file *file, void *priv,
+ struct v4l2_dv_preset *preset)
+{
+ struct vpif_fh *fh = priv;
+ struct channel_obj *ch = fh->channel;
+
+ return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index],
+ video, query_dv_preset, preset);
+}
+/**
+ * vpif_s_dv_presets() - S_DV_PRESETS handler
+ * @file: file ptr
+ * @priv: file handle
+ * @preset: input preset
+ */
+static int vpif_s_dv_preset(struct file *file, void *priv,
+ struct v4l2_dv_preset *preset)
+{
+ struct vpif_fh *fh = priv;
+ struct channel_obj *ch = fh->channel;
+ struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
+ int ret = 0;
+
+ if (common->started) {
+ vpif_dbg(1, debug, "streaming in progress\n");
+ return -EBUSY;
+ }
+
+ if ((VPIF_CHANNEL0_VIDEO == ch->channel_id) ||
+ (VPIF_CHANNEL1_VIDEO == ch->channel_id)) {
+ if (!fh->initialized) {
+ vpif_dbg(1, debug, "Channel Busy\n");
+ return -EBUSY;
+ }
+ }
+
+ ret = v4l2_prio_check(&ch->prio, fh->prio);
+ if (ret)
+ return ret;
+
+ fh->initialized = 1;
+
+ /* Call encoder subdevice function to set the standard */
+ if (mutex_lock_interruptible(&common->lock))
+ return -ERESTARTSYS;
+
+ ch->video.dv_preset = preset->preset;
+ ch->video.stdid = V4L2_STD_UNKNOWN;
+ memset(&ch->video.bt_timings, 0, sizeof(ch->video.bt_timings));
+
+ /* Get the information about the standard */
+ if (vpif_update_std_info(ch)) {
+ vpif_dbg(1, debug, "Error getting the standard info\n");
+ ret = -EINVAL;
+ } else {
+ /* Configure the default format information */
+ vpif_config_format(ch);
+
+ ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index],
+ video, s_dv_preset, preset);
+ }
+
+ mutex_unlock(&common->lock);
+
+ return ret;
+}
+/**
+ * vpif_g_dv_presets() - G_DV_PRESETS handler
+ * @file: file ptr
+ * @priv: file handle
+ * @preset: input preset
+ */
+static int vpif_g_dv_preset(struct file *file, void *priv,
+ struct v4l2_dv_preset *preset)
+{
+ struct vpif_fh *fh = priv;
+ struct channel_obj *ch = fh->channel;
+
+ preset->preset = ch->video.dv_preset;
+
+ return 0;
+}
+
+/**
+ * vpif_s_dv_timings() - S_DV_TIMINGS handler
+ * @file: file ptr
+ * @priv: file handle
+ * @timings: digital video timings
+ */
+static int vpif_s_dv_timings(struct file *file, void *priv,
+ struct v4l2_dv_timings *timings)
+{
+ struct vpif_fh *fh = priv;
+ struct channel_obj *ch = fh->channel;
+ struct vpif_params *vpifparams = &ch->vpifparams;
+ struct vpif_channel_config_params *std_info = &vpifparams->std_info;
+ struct video_obj *vid_ch = &ch->video;
+ struct v4l2_bt_timings *bt = &vid_ch->bt_timings;
+ int ret;
+
+ if (timings->type != V4L2_DV_BT_656_1120) {
+ vpif_dbg(2, debug, "Timing type not defined\n");
+ return -EINVAL;
+ }
+
+ /* Configure subdevice timings, if any */
+ ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index],
+ video, s_dv_timings, timings);
+ if (ret == -ENOIOCTLCMD) {
+ vpif_dbg(2, debug, "Custom DV timings not supported by "
+ "subdevice\n");
+ return -EINVAL;
+ }
+ if (ret < 0) {
+ vpif_dbg(2, debug, "Error setting custom DV timings\n");
+ return ret;
+ }
+
+ if (!(timings->bt.width && timings->bt.height &&
+ (timings->bt.hbackporch ||
+ timings->bt.hfrontporch ||
+ timings->bt.hsync) &&
+ timings->bt.vfrontporch &&
+ (timings->bt.vbackporch ||
+ timings->bt.vsync))) {
+ vpif_dbg(2, debug, "Timings for width, height, "
+ "horizontal back porch, horizontal sync, "
+ "horizontal front porch, vertical back porch, "
+ "vertical sync and vertical back porch "
+ "must be defined\n");
+ return -EINVAL;
+ }
+
+ *bt = timings->bt;
+
+ /* Configure video port timings */
+
+ std_info->eav2sav = bt->hbackporch + bt->hfrontporch +
+ bt->hsync - 8;
+ std_info->sav2eav = bt->width;
+
+ std_info->l1 = 1;
+ std_info->l3 = bt->vsync + bt->vbackporch + 1;
+
+ if (bt->interlaced) {
+ if (bt->il_vbackporch || bt->il_vfrontporch || bt->il_vsync) {
+ std_info->vsize = bt->height * 2 +
+ bt->vfrontporch + bt->vsync + bt->vbackporch +
+ bt->il_vfrontporch + bt->il_vsync +
+ bt->il_vbackporch;
+ std_info->l5 = std_info->vsize/2 -
+ (bt->vfrontporch - 1);
+ std_info->l7 = std_info->vsize/2 + 1;
+ std_info->l9 = std_info->l7 + bt->il_vsync +
+ bt->il_vbackporch + 1;
+ std_info->l11 = std_info->vsize -
+ (bt->il_vfrontporch - 1);
+ } else {
+ vpif_dbg(2, debug, "Required timing values for "
+ "interlaced BT format missing\n");
+ return -EINVAL;
+ }
+ } else {
+ std_info->vsize = bt->height + bt->vfrontporch +
+ bt->vsync + bt->vbackporch;
+ std_info->l5 = std_info->vsize - (bt->vfrontporch - 1);
+ }
+ strncpy(std_info->name, "Custom timings BT656/1120", VPIF_MAX_NAME);
+ std_info->width = bt->width;
+ std_info->height = bt->height;
+ std_info->frm_fmt = bt->interlaced ? 0 : 1;
+ std_info->ycmux_mode = 0;
+ std_info->capture_format = 0;
+ std_info->vbi_supported = 0;
+ std_info->hd_sd = 1;
+ std_info->stdid = 0;
+ std_info->dv_preset = V4L2_DV_INVALID;
+
+ vid_ch->stdid = 0;
+ vid_ch->dv_preset = V4L2_DV_INVALID;
+ return 0;
+}
+
+/**
+ * vpif_g_dv_timings() - G_DV_TIMINGS handler
+ * @file: file ptr
+ * @priv: file handle
+ * @timings: digital video timings
+ */
+static int vpif_g_dv_timings(struct file *file, void *priv,
+ struct v4l2_dv_timings *timings)
+{
+ struct vpif_fh *fh = priv;
+ struct channel_obj *ch = fh->channel;
+ struct video_obj *vid_ch = &ch->video;
+ struct v4l2_bt_timings *bt = &vid_ch->bt_timings;
+
+ timings->bt = *bt;
+
+ return 0;
+}
+
+/*
+ * vpif_g_chip_ident() - Identify the chip
+ * @file: file ptr
+ * @priv: file handle
+ * @chip: chip identity
+ *
+ * Returns zero or -EINVAL if read operations fails.
+ */
+static int vpif_g_chip_ident(struct file *file, void *priv,
+ struct v4l2_dbg_chip_ident *chip)
+{
+ chip->ident = V4L2_IDENT_NONE;
+ chip->revision = 0;
+ if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER &&
+ chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR) {
+ vpif_dbg(2, debug, "match_type is invalid.\n");
+ return -EINVAL;
+ }
+
+ return v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 0, core,
+ g_chip_ident, chip);
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+/*
+ * vpif_dbg_g_register() - Read register
+ * @file: file ptr
+ * @priv: file handle
+ * @reg: register to be read
+ *
+ * Debugging only
+ * Returns zero or -EINVAL if read operations fails.
+ */
+static int vpif_dbg_g_register(struct file *file, void *priv,
+ struct v4l2_dbg_register *reg){
+ struct vpif_fh *fh = priv;
+ struct channel_obj *ch = fh->channel;
+
+ return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], core,
+ g_register, reg);
+}
+
+/*
+ * vpif_dbg_s_register() - Write to register
+ * @file: file ptr
+ * @priv: file handle
+ * @reg: register to be modified
+ *
+ * Debugging only
+ * Returns zero or -EINVAL if write operations fails.
+ */
+static int vpif_dbg_s_register(struct file *file, void *priv,
+ struct v4l2_dbg_register *reg){
+ struct vpif_fh *fh = priv;
+ struct channel_obj *ch = fh->channel;
+
+ return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], core,
+ s_register, reg);
+}
+#endif
+
+/*
+ * vpif_log_status() - Status information
+ * @file: file ptr
+ * @priv: file handle
+ *
+ * Returns zero.
+ */
+static int vpif_log_status(struct file *filep, void *priv)
+{
+ /* status for sub devices */
+ v4l2_device_call_all(&vpif_obj.v4l2_dev, 0, core, log_status);
+
+ return 0;
+}
+
/* vpif capture ioctl operations */
static const struct v4l2_ioctl_ops vpif_ioctl_ops = {
.vidioc_querycap = vpif_querycap,
@@ -1829,6 +2063,18 @@ static const struct v4l2_ioctl_ops vpif_ioctl_ops = {
.vidioc_streamon = vpif_streamon,
.vidioc_streamoff = vpif_streamoff,
.vidioc_cropcap = vpif_cropcap,
+ .vidioc_enum_dv_presets = vpif_enum_dv_presets,
+ .vidioc_s_dv_preset = vpif_s_dv_preset,
+ .vidioc_g_dv_preset = vpif_g_dv_preset,
+ .vidioc_query_dv_preset = vpif_query_dv_preset,
+ .vidioc_s_dv_timings = vpif_s_dv_timings,
+ .vidioc_g_dv_timings = vpif_g_dv_timings,
+ .vidioc_g_chip_ident = vpif_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ .vidioc_g_register = vpif_dbg_g_register,
+ .vidioc_s_register = vpif_dbg_s_register,
+#endif
+ .vidioc_log_status = vpif_log_status,
};
/* vpif file operations */
@@ -1836,7 +2082,7 @@ static struct v4l2_file_operations vpif_fops = {
.owner = THIS_MODULE,
.open = vpif_open,
.release = vpif_release,
- .ioctl = video_ioctl2,
+ .unlocked_ioctl = video_ioctl2,
.mmap = vpif_mmap,
.poll = vpif_poll
};
@@ -1979,6 +2225,7 @@ static __init int vpif_probe(struct platform_device *pdev)
common = &(ch->common[VPIF_VIDEO_INDEX]);
spin_lock_init(&common->irqlock);
mutex_init(&common->lock);
+ ch->video_dev->lock = &common->lock;
/* Initialize prio member of channel object */
v4l2_prio_init(&ch->prio);
err = video_register_device(ch->video_dev,
@@ -2026,9 +2273,9 @@ static __init int vpif_probe(struct platform_device *pdev)
if (vpif_obj.sd[i])
vpif_obj.sd[i]->grp_id = 1 << i;
}
- v4l2_info(&vpif_obj.v4l2_dev, "DM646x VPIF Capture driver"
- " initialized\n");
+ v4l2_info(&vpif_obj.v4l2_dev,
+ "DM646x VPIF capture driver initialized\n");
return 0;
probe_subdev_out:
diff --git a/drivers/media/video/davinci/vpif_capture.h b/drivers/media/video/davinci/vpif_capture.h
index 4e12ec8cac6f..7a4196dfdce1 100644
--- a/drivers/media/video/davinci/vpif_capture.h
+++ b/drivers/media/video/davinci/vpif_capture.h
@@ -59,6 +59,8 @@ struct video_obj {
enum v4l2_field buf_field;
/* Currently selected or default standard */
v4l2_std_id stdid;
+ u32 dv_preset;
+ struct v4l2_bt_timings bt_timings;
/* This is to track the last input that is passed to application */
u32 input_idx;
};
diff --git a/drivers/media/video/davinci/vpif_display.c b/drivers/media/video/davinci/vpif_display.c
index 412c65d54fe1..cdf659abdc2a 100644
--- a/drivers/media/video/davinci/vpif_display.c
+++ b/drivers/media/video/davinci/vpif_display.c
@@ -38,6 +38,7 @@
#include <media/adv7343.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
+#include <media/v4l2-chip-ident.h>
#include <mach/dm646x.h>
@@ -84,17 +85,6 @@ static struct vpif_config_params config_params = {
static struct vpif_device vpif_obj = { {NULL} };
static struct device *vpif_dev;
-static const struct vpif_channel_config_params ch_params[] = {
- {
- "NTSC", 720, 480, 30, 0, 1, 268, 1440, 1, 23, 263, 266,
- 286, 525, 525, 0, 1, 0, V4L2_STD_525_60,
- },
- {
- "PAL", 720, 576, 25, 0, 1, 280, 1440, 1, 23, 311, 313,
- 336, 624, 625, 0, 1, 0, V4L2_STD_625_50,
- },
-};
-
/*
* vpif_uservirt_to_phys: This function is used to convert user
* space virtual address to physical address.
@@ -373,30 +363,54 @@ static irqreturn_t vpif_channel_isr(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static int vpif_get_std_info(struct channel_obj *ch)
+static int vpif_update_std_info(struct channel_obj *ch)
{
- struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
struct video_obj *vid_ch = &ch->video;
struct vpif_params *vpifparams = &ch->vpifparams;
struct vpif_channel_config_params *std_info = &vpifparams->std_info;
const struct vpif_channel_config_params *config;
- int index;
-
- std_info->stdid = vid_ch->stdid;
- if (!std_info->stdid)
- return -1;
+ int i;
- for (index = 0; index < ARRAY_SIZE(ch_params); index++) {
- config = &ch_params[index];
- if (config->stdid & std_info->stdid) {
- memcpy(std_info, config, sizeof(*config));
- break;
+ for (i = 0; i < vpif_ch_params_count; i++) {
+ config = &ch_params[i];
+ if (config->hd_sd == 0) {
+ vpif_dbg(2, debug, "SD format\n");
+ if (config->stdid & vid_ch->stdid) {
+ memcpy(std_info, config, sizeof(*config));
+ break;
+ }
+ } else {
+ vpif_dbg(2, debug, "HD format\n");
+ if (config->dv_preset == vid_ch->dv_preset) {
+ memcpy(std_info, config, sizeof(*config));
+ break;
+ }
}
}
- if (index == ARRAY_SIZE(ch_params))
- return -1;
+ if (i == vpif_ch_params_count) {
+ vpif_dbg(1, debug, "Format not found\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vpif_update_resolution(struct channel_obj *ch)
+{
+ struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
+ struct video_obj *vid_ch = &ch->video;
+ struct vpif_params *vpifparams = &ch->vpifparams;
+ struct vpif_channel_config_params *std_info = &vpifparams->std_info;
+
+ if (!vid_ch->stdid && !vid_ch->dv_preset && !vid_ch->bt_timings.height)
+ return -EINVAL;
+
+ if (vid_ch->stdid || vid_ch->dv_preset) {
+ if (vpif_update_std_info(ch))
+ return -EINVAL;
+ }
common->fmt.fmt.pix.width = std_info->width;
common->fmt.fmt.pix.height = std_info->height;
@@ -404,8 +418,8 @@ static int vpif_get_std_info(struct channel_obj *ch)
common->fmt.fmt.pix.width, common->fmt.fmt.pix.height);
/* Set height and width paramateres */
- ch->common[VPIF_VIDEO_INDEX].height = std_info->height;
- ch->common[VPIF_VIDEO_INDEX].width = std_info->width;
+ common->height = std_info->height;
+ common->width = std_info->width;
return 0;
}
@@ -516,10 +530,8 @@ static int vpif_check_format(struct channel_obj *ch,
else
sizeimage = config_params.channel_bufsize[ch->channel_id];
- if (vpif_get_std_info(ch)) {
- vpif_err("Error getting the standard info\n");
+ if (vpif_update_resolution(ch))
return -EINVAL;
- }
hpitch = pixfmt->bytesperline;
vpitch = sizeimage / (hpitch * 2);
@@ -568,7 +580,10 @@ static void vpif_config_addr(struct channel_obj *ch, int muxmode)
static int vpif_mmap(struct file *filep, struct vm_area_struct *vma)
{
struct vpif_fh *fh = filep->private_data;
- struct common_obj *common = &fh->channel->common[VPIF_VIDEO_INDEX];
+ struct channel_obj *ch = fh->channel;
+ struct common_obj *common = &(ch->common[VPIF_VIDEO_INDEX]);
+
+ vpif_dbg(2, debug, "vpif_mmap\n");
return videobuf_mmap_mapper(&common->buffer_queue, vma);
}
@@ -637,9 +652,6 @@ static int vpif_release(struct file *filep)
struct channel_obj *ch = fh->channel;
struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
- if (mutex_lock_interruptible(&common->lock))
- return -ERESTARTSYS;
-
/* if this instance is doing IO */
if (fh->io_allowed[VPIF_VIDEO_INDEX]) {
/* Reset io_usrs member of channel object */
@@ -662,8 +674,6 @@ static int vpif_release(struct file *filep)
config_params.numbuffers[ch->channel_id];
}
- mutex_unlock(&common->lock);
-
/* Decrement channel usrs counter */
atomic_dec(&ch->usrs);
/* If this file handle has initialize encoder device, reset it */
@@ -680,7 +690,12 @@ static int vpif_release(struct file *filep)
}
/* functions implementing ioctls */
-
+/**
+ * vpif_querycap() - QUERYCAP handler
+ * @file: file ptr
+ * @priv: file handle
+ * @cap: ptr to v4l2_capability structure
+ */
static int vpif_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
@@ -722,17 +737,9 @@ static int vpif_g_fmt_vid_out(struct file *file, void *priv,
if (common->fmt.type != fmt->type)
return -EINVAL;
- /* Fill in the information about format */
- if (mutex_lock_interruptible(&common->lock))
- return -ERESTARTSYS;
-
- if (vpif_get_std_info(ch)) {
- vpif_err("Error getting the standard info\n");
+ if (vpif_update_resolution(ch))
return -EINVAL;
- }
-
*fmt = common->fmt;
- mutex_unlock(&common->lock);
return 0;
}
@@ -773,12 +780,7 @@ static int vpif_s_fmt_vid_out(struct file *file, void *priv,
/* store the pix format in the channel object */
common->fmt.fmt.pix = *pixfmt;
/* store the format in the channel object */
- if (mutex_lock_interruptible(&common->lock))
- return -ERESTARTSYS;
-
common->fmt = *fmt;
- mutex_unlock(&common->lock);
-
return 0;
}
@@ -808,7 +810,6 @@ static int vpif_reqbufs(struct file *file, void *priv,
struct common_obj *common;
enum v4l2_field field;
u8 index = 0;
- int ret = 0;
/* This file handle has not initialized the channel,
It is not allowed to do settings */
@@ -826,18 +827,12 @@ static int vpif_reqbufs(struct file *file, void *priv,
index = VPIF_VIDEO_INDEX;
common = &ch->common[index];
- if (mutex_lock_interruptible(&common->lock))
- return -ERESTARTSYS;
- if (common->fmt.type != reqbuf->type) {
- ret = -EINVAL;
- goto reqbuf_exit;
- }
+ if (common->fmt.type != reqbuf->type)
+ return -EINVAL;
- if (0 != common->io_usrs) {
- ret = -EBUSY;
- goto reqbuf_exit;
- }
+ if (0 != common->io_usrs)
+ return -EBUSY;
if (reqbuf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
if (common->fmt.fmt.pix.field == V4L2_FIELD_ANY)
@@ -854,7 +849,7 @@ static int vpif_reqbufs(struct file *file, void *priv,
&common->irqlock,
reqbuf->type, field,
sizeof(struct videobuf_buffer), fh,
- NULL);
+ &common->lock);
/* Set io allowed member of file handle to TRUE */
fh->io_allowed[index] = 1;
@@ -865,11 +860,7 @@ static int vpif_reqbufs(struct file *file, void *priv,
INIT_LIST_HEAD(&common->dma_queue);
/* Allocate buffers */
- ret = videobuf_reqbufs(&common->buffer_queue, reqbuf);
-
-reqbuf_exit:
- mutex_unlock(&common->lock);
- return ret;
+ return videobuf_reqbufs(&common->buffer_queue, reqbuf);
}
static int vpif_querybuf(struct file *file, void *priv,
@@ -990,22 +981,19 @@ static int vpif_s_std(struct file *file, void *priv, v4l2_std_id *std_id)
}
/* Call encoder subdevice function to set the standard */
- if (mutex_lock_interruptible(&common->lock))
- return -ERESTARTSYS;
-
ch->video.stdid = *std_id;
+ ch->video.dv_preset = V4L2_DV_INVALID;
+ memset(&ch->video.bt_timings, 0, sizeof(ch->video.bt_timings));
+
/* Get the information about the standard */
- if (vpif_get_std_info(ch)) {
- vpif_err("Error getting the standard info\n");
+ if (vpif_update_resolution(ch))
return -EINVAL;
- }
if ((ch->vpifparams.std_info.width *
ch->vpifparams.std_info.height * 2) >
config_params.channel_bufsize[ch->channel_id]) {
vpif_err("invalid std for this size\n");
- ret = -EINVAL;
- goto s_std_exit;
+ return -EINVAL;
}
common->fmt.fmt.pix.bytesperline = common->fmt.fmt.pix.width;
@@ -1016,16 +1004,13 @@ static int vpif_s_std(struct file *file, void *priv, v4l2_std_id *std_id)
s_std_output, *std_id);
if (ret < 0) {
vpif_err("Failed to set output standard\n");
- goto s_std_exit;
+ return ret;
}
ret = v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 1, core,
s_std, *std_id);
if (ret < 0)
vpif_err("Failed to set standard for sub devices\n");
-
-s_std_exit:
- mutex_unlock(&common->lock);
return ret;
}
@@ -1090,21 +1075,17 @@ static int vpif_streamon(struct file *file, void *priv,
if (ret < 0)
return ret;
- /* Call videobuf_streamon to start streaming in videobuf */
+ /* Call videobuf_streamon to start streaming in videobuf */
ret = videobuf_streamon(&common->buffer_queue);
if (ret < 0) {
vpif_err("videobuf_streamon\n");
return ret;
}
- if (mutex_lock_interruptible(&common->lock))
- return -ERESTARTSYS;
-
/* If buffer queue is empty, return error */
if (list_empty(&common->dma_queue)) {
vpif_err("buffer queue is empty\n");
- ret = -EIO;
- goto streamon_exit;
+ return -EIO;
}
/* Get the next frame from the buffer queue */
@@ -1130,8 +1111,7 @@ static int vpif_streamon(struct file *file, void *priv,
|| (!ch->vpifparams.std_info.frm_fmt
&& (common->fmt.fmt.pix.field == V4L2_FIELD_NONE))) {
vpif_err("conflict in field format and std format\n");
- ret = -EINVAL;
- goto streamon_exit;
+ return -EINVAL;
}
/* clock settings */
@@ -1140,13 +1120,13 @@ static int vpif_streamon(struct file *file, void *priv,
ch->vpifparams.std_info.hd_sd);
if (ret < 0) {
vpif_err("can't set clock\n");
- goto streamon_exit;
+ return ret;
}
/* set the parameters and addresses */
ret = vpif_set_video_params(vpif, ch->channel_id + 2);
if (ret < 0)
- goto streamon_exit;
+ return ret;
common->started = ret;
vpif_config_addr(ch, ret);
@@ -1171,9 +1151,6 @@ static int vpif_streamon(struct file *file, void *priv,
}
channel_first_int[VPIF_VIDEO_INDEX][ch->channel_id] = 1;
}
-
-streamon_exit:
- mutex_unlock(&common->lock);
return ret;
}
@@ -1199,9 +1176,6 @@ static int vpif_streamoff(struct file *file, void *priv,
return -EINVAL;
}
- if (mutex_lock_interruptible(&common->lock))
- return -ERESTARTSYS;
-
if (buftype == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
/* disable channel */
if (VPIF_CHANNEL2_VIDEO == ch->channel_id) {
@@ -1216,8 +1190,6 @@ static int vpif_streamoff(struct file *file, void *priv,
}
common->started = 0;
- mutex_unlock(&common->lock);
-
return videobuf_streamoff(&common->buffer_queue);
}
@@ -1264,13 +1236,9 @@ static int vpif_s_output(struct file *file, void *priv, unsigned int i)
struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
int ret = 0;
- if (mutex_lock_interruptible(&common->lock))
- return -ERESTARTSYS;
-
if (common->started) {
vpif_err("Streaming in progress\n");
- ret = -EBUSY;
- goto s_output_exit;
+ return -EBUSY;
}
ret = v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 1, video,
@@ -1280,9 +1248,6 @@ static int vpif_s_output(struct file *file, void *priv, unsigned int i)
vpif_err("Failed to set output standard\n");
vid_ch->output_id = i;
-
-s_output_exit:
- mutex_unlock(&common->lock);
return ret;
}
@@ -1315,6 +1280,287 @@ static int vpif_s_priority(struct file *file, void *priv, enum v4l2_priority p)
return v4l2_prio_change(&ch->prio, &fh->prio, p);
}
+/**
+ * vpif_enum_dv_presets() - ENUM_DV_PRESETS handler
+ * @file: file ptr
+ * @priv: file handle
+ * @preset: input preset
+ */
+static int vpif_enum_dv_presets(struct file *file, void *priv,
+ struct v4l2_dv_enum_preset *preset)
+{
+ struct vpif_fh *fh = priv;
+ struct channel_obj *ch = fh->channel;
+ struct video_obj *vid_ch = &ch->video;
+
+ return v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id],
+ video, enum_dv_presets, preset);
+}
+
+/**
+ * vpif_s_dv_presets() - S_DV_PRESETS handler
+ * @file: file ptr
+ * @priv: file handle
+ * @preset: input preset
+ */
+static int vpif_s_dv_preset(struct file *file, void *priv,
+ struct v4l2_dv_preset *preset)
+{
+ struct vpif_fh *fh = priv;
+ struct channel_obj *ch = fh->channel;
+ struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
+ struct video_obj *vid_ch = &ch->video;
+ int ret = 0;
+
+ if (common->started) {
+ vpif_dbg(1, debug, "streaming in progress\n");
+ return -EBUSY;
+ }
+
+ ret = v4l2_prio_check(&ch->prio, fh->prio);
+ if (ret != 0)
+ return ret;
+
+ fh->initialized = 1;
+
+ /* Call encoder subdevice function to set the standard */
+ if (mutex_lock_interruptible(&common->lock))
+ return -ERESTARTSYS;
+
+ ch->video.dv_preset = preset->preset;
+ ch->video.stdid = V4L2_STD_UNKNOWN;
+ memset(&ch->video.bt_timings, 0, sizeof(ch->video.bt_timings));
+
+ /* Get the information about the standard */
+ if (vpif_update_resolution(ch)) {
+ ret = -EINVAL;
+ } else {
+ /* Configure the default format information */
+ vpif_config_format(ch);
+
+ ret = v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id],
+ video, s_dv_preset, preset);
+ }
+
+ mutex_unlock(&common->lock);
+
+ return ret;
+}
+/**
+ * vpif_g_dv_presets() - G_DV_PRESETS handler
+ * @file: file ptr
+ * @priv: file handle
+ * @preset: input preset
+ */
+static int vpif_g_dv_preset(struct file *file, void *priv,
+ struct v4l2_dv_preset *preset)
+{
+ struct vpif_fh *fh = priv;
+ struct channel_obj *ch = fh->channel;
+
+ preset->preset = ch->video.dv_preset;
+
+ return 0;
+}
+/**
+ * vpif_s_dv_timings() - S_DV_TIMINGS handler
+ * @file: file ptr
+ * @priv: file handle
+ * @timings: digital video timings
+ */
+static int vpif_s_dv_timings(struct file *file, void *priv,
+ struct v4l2_dv_timings *timings)
+{
+ struct vpif_fh *fh = priv;
+ struct channel_obj *ch = fh->channel;
+ struct vpif_params *vpifparams = &ch->vpifparams;
+ struct vpif_channel_config_params *std_info = &vpifparams->std_info;
+ struct video_obj *vid_ch = &ch->video;
+ struct v4l2_bt_timings *bt = &vid_ch->bt_timings;
+ int ret;
+
+ if (timings->type != V4L2_DV_BT_656_1120) {
+ vpif_dbg(2, debug, "Timing type not defined\n");
+ return -EINVAL;
+ }
+
+ /* Configure subdevice timings, if any */
+ ret = v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id],
+ video, s_dv_timings, timings);
+ if (ret == -ENOIOCTLCMD) {
+ vpif_dbg(2, debug, "Custom DV timings not supported by "
+ "subdevice\n");
+ return -EINVAL;
+ }
+ if (ret < 0) {
+ vpif_dbg(2, debug, "Error setting custom DV timings\n");
+ return ret;
+ }
+
+ if (!(timings->bt.width && timings->bt.height &&
+ (timings->bt.hbackporch ||
+ timings->bt.hfrontporch ||
+ timings->bt.hsync) &&
+ timings->bt.vfrontporch &&
+ (timings->bt.vbackporch ||
+ timings->bt.vsync))) {
+ vpif_dbg(2, debug, "Timings for width, height, "
+ "horizontal back porch, horizontal sync, "
+ "horizontal front porch, vertical back porch, "
+ "vertical sync and vertical back porch "
+ "must be defined\n");
+ return -EINVAL;
+ }
+
+ *bt = timings->bt;
+
+ /* Configure video port timings */
+
+ std_info->eav2sav = bt->hbackporch + bt->hfrontporch +
+ bt->hsync - 8;
+ std_info->sav2eav = bt->width;
+
+ std_info->l1 = 1;
+ std_info->l3 = bt->vsync + bt->vbackporch + 1;
+
+ if (bt->interlaced) {
+ if (bt->il_vbackporch || bt->il_vfrontporch || bt->il_vsync) {
+ std_info->vsize = bt->height * 2 +
+ bt->vfrontporch + bt->vsync + bt->vbackporch +
+ bt->il_vfrontporch + bt->il_vsync +
+ bt->il_vbackporch;
+ std_info->l5 = std_info->vsize/2 -
+ (bt->vfrontporch - 1);
+ std_info->l7 = std_info->vsize/2 + 1;
+ std_info->l9 = std_info->l7 + bt->il_vsync +
+ bt->il_vbackporch + 1;
+ std_info->l11 = std_info->vsize -
+ (bt->il_vfrontporch - 1);
+ } else {
+ vpif_dbg(2, debug, "Required timing values for "
+ "interlaced BT format missing\n");
+ return -EINVAL;
+ }
+ } else {
+ std_info->vsize = bt->height + bt->vfrontporch +
+ bt->vsync + bt->vbackporch;
+ std_info->l5 = std_info->vsize - (bt->vfrontporch - 1);
+ }
+ strncpy(std_info->name, "Custom timings BT656/1120",
+ VPIF_MAX_NAME);
+ std_info->width = bt->width;
+ std_info->height = bt->height;
+ std_info->frm_fmt = bt->interlaced ? 0 : 1;
+ std_info->ycmux_mode = 0;
+ std_info->capture_format = 0;
+ std_info->vbi_supported = 0;
+ std_info->hd_sd = 1;
+ std_info->stdid = 0;
+ std_info->dv_preset = V4L2_DV_INVALID;
+
+ vid_ch->stdid = 0;
+ vid_ch->dv_preset = V4L2_DV_INVALID;
+
+ return 0;
+}
+
+/**
+ * vpif_g_dv_timings() - G_DV_TIMINGS handler
+ * @file: file ptr
+ * @priv: file handle
+ * @timings: digital video timings
+ */
+static int vpif_g_dv_timings(struct file *file, void *priv,
+ struct v4l2_dv_timings *timings)
+{
+ struct vpif_fh *fh = priv;
+ struct channel_obj *ch = fh->channel;
+ struct video_obj *vid_ch = &ch->video;
+ struct v4l2_bt_timings *bt = &vid_ch->bt_timings;
+
+ timings->bt = *bt;
+
+ return 0;
+}
+
+/*
+ * vpif_g_chip_ident() - Identify the chip
+ * @file: file ptr
+ * @priv: file handle
+ * @chip: chip identity
+ *
+ * Returns zero or -EINVAL if read operations fails.
+ */
+static int vpif_g_chip_ident(struct file *file, void *priv,
+ struct v4l2_dbg_chip_ident *chip)
+{
+ chip->ident = V4L2_IDENT_NONE;
+ chip->revision = 0;
+ if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER &&
+ chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR) {
+ vpif_dbg(2, debug, "match_type is invalid.\n");
+ return -EINVAL;
+ }
+
+ return v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 0, core,
+ g_chip_ident, chip);
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+/*
+ * vpif_dbg_g_register() - Read register
+ * @file: file ptr
+ * @priv: file handle
+ * @reg: register to be read
+ *
+ * Debugging only
+ * Returns zero or -EINVAL if read operations fails.
+ */
+static int vpif_dbg_g_register(struct file *file, void *priv,
+ struct v4l2_dbg_register *reg){
+ struct vpif_fh *fh = priv;
+ struct channel_obj *ch = fh->channel;
+ struct video_obj *vid_ch = &ch->video;
+
+ return v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id], core,
+ g_register, reg);
+}
+
+/*
+ * vpif_dbg_s_register() - Write to register
+ * @file: file ptr
+ * @priv: file handle
+ * @reg: register to be modified
+ *
+ * Debugging only
+ * Returns zero or -EINVAL if write operations fails.
+ */
+static int vpif_dbg_s_register(struct file *file, void *priv,
+ struct v4l2_dbg_register *reg){
+ struct vpif_fh *fh = priv;
+ struct channel_obj *ch = fh->channel;
+ struct video_obj *vid_ch = &ch->video;
+
+ return v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id], core,
+ s_register, reg);
+}
+#endif
+
+/*
+ * vpif_log_status() - Status information
+ * @file: file ptr
+ * @priv: file handle
+ *
+ * Returns zero.
+ */
+static int vpif_log_status(struct file *filep, void *priv)
+{
+ /* status for sub devices */
+ v4l2_device_call_all(&vpif_obj.v4l2_dev, 0, core, log_status);
+
+ return 0;
+}
+
/* vpif display ioctl operations */
static const struct v4l2_ioctl_ops vpif_ioctl_ops = {
.vidioc_querycap = vpif_querycap,
@@ -1336,13 +1582,24 @@ static const struct v4l2_ioctl_ops vpif_ioctl_ops = {
.vidioc_s_output = vpif_s_output,
.vidioc_g_output = vpif_g_output,
.vidioc_cropcap = vpif_cropcap,
+ .vidioc_enum_dv_presets = vpif_enum_dv_presets,
+ .vidioc_s_dv_preset = vpif_s_dv_preset,
+ .vidioc_g_dv_preset = vpif_g_dv_preset,
+ .vidioc_s_dv_timings = vpif_s_dv_timings,
+ .vidioc_g_dv_timings = vpif_g_dv_timings,
+ .vidioc_g_chip_ident = vpif_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ .vidioc_g_register = vpif_dbg_g_register,
+ .vidioc_s_register = vpif_dbg_s_register,
+#endif
+ .vidioc_log_status = vpif_log_status,
};
static const struct v4l2_file_operations vpif_fops = {
.owner = THIS_MODULE,
.open = vpif_open,
.release = vpif_release,
- .ioctl = video_ioctl2,
+ .unlocked_ioctl = video_ioctl2,
.mmap = vpif_mmap,
.poll = vpif_poll
};
@@ -1526,6 +1783,7 @@ static __init int vpif_probe(struct platform_device *pdev)
v4l2_prio_init(&ch->prio);
ch->common[VPIF_VIDEO_INDEX].fmt.type =
V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ ch->video_dev->lock = &common->lock;
/* register video device */
vpif_dbg(1, debug, "channel=%x,channel->video_dev=%x\n",
@@ -1565,6 +1823,8 @@ static __init int vpif_probe(struct platform_device *pdev)
vpif_obj.sd[i]->grp_id = 1 << i;
}
+ v4l2_info(&vpif_obj.v4l2_dev,
+ "DM646x VPIF display driver initialized\n");
return 0;
probe_subdev_out:
diff --git a/drivers/media/video/davinci/vpif_display.h b/drivers/media/video/davinci/vpif_display.h
index a2a7cd166bbf..b53aaa883075 100644
--- a/drivers/media/video/davinci/vpif_display.h
+++ b/drivers/media/video/davinci/vpif_display.h
@@ -67,6 +67,8 @@ struct video_obj {
* most recent displayed frame only */
v4l2_std_id stdid; /* Currently selected or default
* standard */
+ u32 dv_preset;
+ struct v4l2_bt_timings bt_timings;
u32 output_id; /* Current output id */
};