提交 c027e165 编写于 作者: M Mats Randgaard 提交者: Mauro Carvalho Chehab

[media] vpif_cap/disp: Added support for DV timings

Added functions to set and get custom DV timings.
Signed-off-by: NMats Randgaard <mats.randgaard@cisco.com>
Signed-off-by: NHans Verkuil <hans.verkuil@cisco.com>
Acked-by: NVaibhav Hiremath <hvaibhav@ti.com>
Acked-by: NManjunath Hadli <manjunath.hadli@ti.com>
Signed-off-by: NMauro Carvalho Chehab <mchehab@redhat.com>
上级 40c8bcea
master alk-4.19.24 alk-4.19.30 alk-4.19.34 alk-4.19.36 alk-4.19.43 alk-4.19.48 alk-4.19.57 ck-4.19.67 ck-4.19.81 ck-4.19.91 github/fork/deepanshu1422/fix-typo-in-comment github/fork/haosdent/fix-typo linux-next v4.19.91 v4.19.90 v4.19.89 v4.19.88 v4.19.87 v4.19.86 v4.19.85 v4.19.84 v4.19.83 v4.19.82 v4.19.81 v4.19.80 v4.19.79 v4.19.78 v4.19.77 v4.19.76 v4.19.75 v4.19.74 v4.19.73 v4.19.72 v4.19.71 v4.19.70 v4.19.69 v4.19.68 v4.19.67 v4.19.66 v4.19.65 v4.19.64 v4.19.63 v4.19.62 v4.19.61 v4.19.60 v4.19.59 v4.19.58 v4.19.57 v4.19.56 v4.19.55 v4.19.54 v4.19.53 v4.19.52 v4.19.51 v4.19.50 v4.19.49 v4.19.48 v4.19.47 v4.19.46 v4.19.45 v4.19.44 v4.19.43 v4.19.42 v4.19.41 v4.19.40 v4.19.39 v4.19.38 v4.19.37 v4.19.36 v4.19.35 v4.19.34 v4.19.33 v4.19.32 v4.19.31 v4.19.30 v4.19.29 v4.19.28 v4.19.27 v4.19.26 v4.19.25 v4.19.24 v4.19.23 v4.19.22 v4.19.21 v4.19.20 v4.19.19 v4.19.18 v4.19.17 v4.19.16 v4.19.15 v4.19.14 v4.19.13 v4.19.12 v4.19.11 v4.19.10 v4.19.9 v4.19.8 v4.19.7 v4.19.6 v4.19.5 v4.19.4 v4.19.3 v4.19.2 v4.19.1 v4.19 v4.19-rc8 v4.19-rc7 v4.19-rc6 v4.19-rc5 v4.19-rc4 v4.19-rc3 v4.19-rc2 v4.19-rc1 ck-release-21 ck-release-20 ck-release-19.2 ck-release-19.1 ck-release-19 ck-release-18 ck-release-17.2 ck-release-17.1 ck-release-17 ck-release-16 ck-release-15.1 ck-release-15 ck-release-14 ck-release-13.2 ck-release-13 ck-release-12 ck-release-11 ck-release-10 ck-release-9 ck-release-7 alk-release-15 alk-release-14 alk-release-13.2 alk-release-13 alk-release-12 alk-release-11 alk-release-10 alk-release-9 alk-release-7
无相关合并请求
......@@ -1452,6 +1452,7 @@ static int vpif_s_std(struct file *file, void *priv, v4l2_std_id *std_id)
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)) {
......@@ -1874,6 +1875,7 @@ static int vpif_s_dv_preset(struct file *file, void *priv,
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)) {
......@@ -1908,6 +1910,125 @@ static int vpif_g_dv_preset(struct file *file, void *priv,
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
......@@ -2010,6 +2131,8 @@ static const struct v4l2_ioctl_ops vpif_ioctl_ops = {
.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,
......
......@@ -60,6 +60,7 @@ struct video_obj {
/* 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;
};
......
......@@ -363,21 +363,17 @@ 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;
if (!vid_ch->stdid && !vid_ch->dv_preset)
return -EINVAL;
int i;
for (index = 0; index < vpif_ch_params_count; index++) {
config = &ch_params[index];
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) {
......@@ -393,17 +389,37 @@ static int vpif_get_std_info(struct channel_obj *ch)
}
}
if (index == vpif_ch_params_count)
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;
vpif_dbg(1, debug, "Pixel details: Width = %d,Height = %d\n",
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;
}
......@@ -514,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);
......@@ -715,6 +729,7 @@ static int vpif_g_fmt_vid_out(struct file *file, void *priv,
struct vpif_fh *fh = priv;
struct channel_obj *ch = fh->channel;
struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
int ret = 0;
/* Check the validity of the buffer type */
if (common->fmt.type != fmt->type)
......@@ -724,14 +739,14 @@ static int vpif_g_fmt_vid_out(struct file *file, void *priv,
if (mutex_lock_interruptible(&common->lock))
return -ERESTARTSYS;
if (vpif_get_std_info(ch)) {
vpif_err("Error getting the standard info\n");
return -EINVAL;
}
if (vpif_update_resolution(ch))
ret = -EINVAL;
else
*fmt = common->fmt;
*fmt = common->fmt;
mutex_unlock(&common->lock);
return 0;
return ret;
}
static int vpif_s_fmt_vid_out(struct file *file, void *priv,
......@@ -992,10 +1007,13 @@ static int vpif_s_std(struct file *file, void *priv, v4l2_std_id *std_id)
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");
return -EINVAL;
if (vpif_update_resolution(ch)) {
ret = -EINVAL;
goto s_std_exit;
}
if ((ch->vpifparams.std_info.width *
......@@ -1362,11 +1380,11 @@ static int vpif_s_dv_preset(struct file *file, void *priv,
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_get_std_info(ch)) {
if (vpif_update_resolution(ch)) {
ret = -EINVAL;
vpif_dbg(1, debug, "Error getting the standard info\n");
} else {
/* Configure the default format information */
vpif_config_format(ch);
......@@ -1395,6 +1413,126 @@ static int vpif_g_dv_preset(struct file *file, void *priv,
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
......@@ -1498,6 +1636,8 @@ static const struct v4l2_ioctl_ops vpif_ioctl_ops = {
.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,
......
......@@ -68,6 +68,7 @@ struct video_obj {
v4l2_std_id stdid; /* Currently selected or default
* standard */
u32 dv_preset;
struct v4l2_bt_timings bt_timings;
u32 output_id; /* Current output id */
};
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册
新手
引导
客服 返回
顶部