summaryrefslogtreecommitdiffstats
path: root/drivers/media/platform/s5p-tv/mixer_video.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/platform/s5p-tv/mixer_video.c')
-rw-r--r--drivers/media/platform/s5p-tv/mixer_video.c80
1 files changed, 80 insertions, 0 deletions
diff --git a/drivers/media/platform/s5p-tv/mixer_video.c b/drivers/media/platform/s5p-tv/mixer_video.c
index 82142a2d6d93..24fb38177c82 100644
--- a/drivers/media/platform/s5p-tv/mixer_video.c
+++ b/drivers/media/platform/s5p-tv/mixer_video.c
@@ -559,6 +559,79 @@ static int mxr_g_dv_preset(struct file *file, void *fh,
return ret ? -EINVAL : 0;
}
+static int mxr_enum_dv_timings(struct file *file, void *fh,
+ struct v4l2_enum_dv_timings *timings)
+{
+ struct mxr_layer *layer = video_drvdata(file);
+ struct mxr_device *mdev = layer->mdev;
+ int ret;
+
+ /* lock protects from changing sd_out */
+ mutex_lock(&mdev->mutex);
+ ret = v4l2_subdev_call(to_outsd(mdev), video, enum_dv_timings, timings);
+ mutex_unlock(&mdev->mutex);
+
+ return ret ? -EINVAL : 0;
+}
+
+static int mxr_s_dv_timings(struct file *file, void *fh,
+ struct v4l2_dv_timings *timings)
+{
+ struct mxr_layer *layer = video_drvdata(file);
+ struct mxr_device *mdev = layer->mdev;
+ int ret;
+
+ /* lock protects from changing sd_out */
+ mutex_lock(&mdev->mutex);
+
+ /* timings change cannot be done while there is an entity
+ * dependant on output configuration
+ */
+ if (mdev->n_output > 0) {
+ mutex_unlock(&mdev->mutex);
+ return -EBUSY;
+ }
+
+ ret = v4l2_subdev_call(to_outsd(mdev), video, s_dv_timings, timings);
+
+ mutex_unlock(&mdev->mutex);
+
+ mxr_layer_update_output(layer);
+
+ /* any failure should return EINVAL according to V4L2 doc */
+ return ret ? -EINVAL : 0;
+}
+
+static int mxr_g_dv_timings(struct file *file, void *fh,
+ struct v4l2_dv_timings *timings)
+{
+ struct mxr_layer *layer = video_drvdata(file);
+ struct mxr_device *mdev = layer->mdev;
+ int ret;
+
+ /* lock protects from changing sd_out */
+ mutex_lock(&mdev->mutex);
+ ret = v4l2_subdev_call(to_outsd(mdev), video, g_dv_timings, timings);
+ mutex_unlock(&mdev->mutex);
+
+ return ret ? -EINVAL : 0;
+}
+
+static int mxr_dv_timings_cap(struct file *file, void *fh,
+ struct v4l2_dv_timings_cap *cap)
+{
+ struct mxr_layer *layer = video_drvdata(file);
+ struct mxr_device *mdev = layer->mdev;
+ int ret;
+
+ /* lock protects from changing sd_out */
+ mutex_lock(&mdev->mutex);
+ ret = v4l2_subdev_call(to_outsd(mdev), video, dv_timings_cap, cap);
+ mutex_unlock(&mdev->mutex);
+
+ return ret ? -EINVAL : 0;
+}
+
static int mxr_s_std(struct file *file, void *fh, v4l2_std_id *norm)
{
struct mxr_layer *layer = video_drvdata(file);
@@ -618,6 +691,8 @@ static int mxr_enum_output(struct file *file, void *fh, struct v4l2_output *a)
a->capabilities = 0;
if (sd->ops->video && sd->ops->video->s_dv_preset)
a->capabilities |= V4L2_OUT_CAP_PRESETS;
+ if (sd->ops->video && sd->ops->video->s_dv_timings)
+ a->capabilities |= V4L2_OUT_CAP_DV_TIMINGS;
if (sd->ops->video && sd->ops->video->s_std_output)
a->capabilities |= V4L2_OUT_CAP_STD;
a->type = V4L2_OUTPUT_TYPE_ANALOG;
@@ -742,6 +817,11 @@ static const struct v4l2_ioctl_ops mxr_ioctl_ops = {
.vidioc_enum_dv_presets = mxr_enum_dv_presets,
.vidioc_s_dv_preset = mxr_s_dv_preset,
.vidioc_g_dv_preset = mxr_g_dv_preset,
+ /* DV Timings functions */
+ .vidioc_enum_dv_timings = mxr_enum_dv_timings,
+ .vidioc_s_dv_timings = mxr_s_dv_timings,
+ .vidioc_g_dv_timings = mxr_g_dv_timings,
+ .vidioc_dv_timings_cap = mxr_dv_timings_cap,
/* analog TV standard functions */
.vidioc_s_std = mxr_s_std,
.vidioc_g_std = mxr_g_std,
OpenPOWER on IntegriCloud