Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(455)

Unified Diff: drivers/media/video/samsung/tv20/s5p_tv_v4l2.c

Issue 2036011: V4L/DVB : Add S5PV210 TV out driver support (Closed) Base URL: swsolcc@12.23.106.100:kernel-samsung.git
Patch Set: Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « drivers/media/video/samsung/tv20/s5p_tv_base.c ('k') | drivers/media/video/samsung/tv20/sdout_s5pv210.c » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: drivers/media/video/samsung/tv20/s5p_tv_v4l2.c
diff --git a/drivers/media/video/samsung/tv20/s5p_tv_v4l2.c b/drivers/media/video/samsung/tv20/s5p_tv_v4l2.c
new file mode 100644
index 0000000000000000000000000000000000000000..938dced7f6af466e9ed0f29270fc008e3ee40683
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/s5p_tv_v4l2.c
@@ -0,0 +1,1637 @@
+/* linux/drivers/media/video/samsung/tv20/s5p_tv_v4l2.c
+*
+* Copyright (c) 2010 Samsung Electronics Co., Ltd.
+* http://www.samsung.com/
+*
+* S5PV210 - Video4Linux API ftn. file for Samsung TVOut driver
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/stddef.h>
+#include <linux/string.h>
+#include <linux/version.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+
+#include <linux/io.h>
+#include <linux/uaccess.h>
+
+#include "s5p_tv.h"
+
+#ifdef CONFIG_TVOUT_DBG
+#define S5P_V4L2_DEBUG 1
+#endif
+
+#ifdef S5P_V4L2_DEBUG
+#define V4L2PRINTK(fmt, args...) \
+ printk(KERN_INFO "[V4L2_IF] %s: " fmt, __func__ , ## args)
+#else
+#define V4L2PRINTK(fmt, args...)
+#endif
+
+u8 hdcp_protocol_status;
+ /* 0 - hdcp stopped, 1 - hdcp started, 2 - hdcp reset */
+
+#define CVBS_S_VIDEO (V4L2_STD_NTSC_M|V4L2_STD_NTSC_M_JP|\
+ V4L2_STD_PAL|V4L2_STD_PAL_M|V4L2_STD_PAL_N|V4L2_STD_PAL_Nc|\
+ V4L2_STD_PAL_60|V4L2_STD_NTSC_443)
+
+struct v4l2_output s5p_tv_outputs[] = {
+ {
+ .index = 0,
+ .name = "Analog COMPOSITE",
+ .type = V4L2_OUTPUT_TYPE_COMPOSITE,
+ .audioset = 0,
+ .modulator = 0,
+ .std = CVBS_S_VIDEO,
+ }, {
+ .index = 1,
+ .name = "Analog SVIDEO",
+ .type = V4L2_OUTPUT_TYPE_SVIDEO,
+ .audioset = 0,
+ .modulator = 0,
+ .std = CVBS_S_VIDEO,
+ }, {
+ .index = 2,
+ .name = "Analog COMPONENT_YPBPR_I",
+ .type = V4L2_OUTPUT_TYPE_YPBPR_INERLACED,
+ .audioset = 0,
+ .modulator = 0,
+ .std = V4L2_STD_ALL,
+ }, {
+ .index = 3,
+ .name = "Analog COMPONENT_YPBPR_P",
+ .type = V4L2_OUTPUT_TYPE_YPBPR_PROGRESSIVE,
+ .audioset = 0,
+ .modulator = 0,
+ .std = V4L2_STD_ALL,
+ }, {
+ .index = 4,
+ .name = "Analog COMPONENT_RGB_P",
+ .type = V4L2_OUTPUT_TYPE_RGB_PROGRESSIVE,
+ .audioset = 0,
+ .modulator = 0,
+ .std = V4L2_STD_ALL,
+ }, {
+ .index = 5,
+ .name = "Digital HDMI(YCbCr)",
+ .type = V4L2_OUTPUT_TYPE_HDMI,
+ .audioset = 2,
+ .modulator = 0,
+ .std =
+ V4L2_STD_480P_60_16_9 | V4L2_STD_480P_60_16_9 |
+ V4L2_STD_720P_60 | V4L2_STD_720P_50
+ | V4L2_STD_1080P_60 | V4L2_STD_1080P_50 |
+ V4L2_STD_1080I_60 | V4L2_STD_1080I_50 |
+ V4L2_STD_480P_59 | V4L2_STD_720P_59 |
+ V4L2_STD_1080I_59 | V4L2_STD_1080P_59 |
+ V4L2_STD_1080P_30,
+ }, {
+ .index = 6,
+ .name = "Digital HDMI(RGB)",
+ .type = V4L2_OUTPUT_TYPE_HDMI_RGB,
+ .audioset = 2,
+ .modulator = 0,
+ .std = V4L2_STD_480P_60_16_9 |
+ V4L2_STD_480P_60_16_9 |
+ V4L2_STD_720P_60 | V4L2_STD_720P_50
+ | V4L2_STD_1080P_60 | V4L2_STD_1080P_50 |
+ V4L2_STD_1080I_60 | V4L2_STD_1080I_50 |
+ V4L2_STD_480P_59 | V4L2_STD_720P_59 |
+ V4L2_STD_1080I_59 | V4L2_STD_1080P_59 |
+ V4L2_STD_1080P_30,
+ }, {
+ .index = 7,
+ .name = "Digital DVI",
+ .type = V4L2_OUTPUT_TYPE_DVI,
+ .audioset = 2,
+ .modulator = 0,
+ .std =
+ V4L2_STD_480P_60_16_9 | V4L2_STD_480P_60_16_9 |
+ V4L2_STD_720P_60 | V4L2_STD_720P_50
+ | V4L2_STD_1080P_60 | V4L2_STD_1080P_50 |
+ V4L2_STD_1080I_60 | V4L2_STD_1080I_50 |
+ V4L2_STD_480P_59 | V4L2_STD_720P_59 |
+ V4L2_STD_1080I_59 | V4L2_STD_1080P_59 |
+ V4L2_STD_1080P_30,
+ }
+
+};
+
+const struct v4l2_fmtdesc s5p_tv_o_fmt_desc[] = {
+ {
+ .index = 0,
+ .type = V4L2_BUF_TYPE_VIDEO_OUTPUT,
+ .description = "YUV420, NV12 (Video Processor)",
+ .pixelformat = V4L2_PIX_FMT_NV12,
+ .flags = FORMAT_FLAGS_CrCb,
+ }
+};
+
+const struct v4l2_fmtdesc s5p_tv_o_overlay_fmt_desc[] = {
+ {
+ .index = 0,
+ .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY,
+ .description = "16bpp RGB, le - RGB[565]",
+ .pixelformat = V4L2_PIX_FMT_RGB565,
+ .flags = FORMAT_FLAGS_PACKED,
+ }, {
+ .index = 1,
+ .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY,
+ .description = "16bpp RGB, le - ARGB[1555]",
+ .pixelformat = V4L2_PIX_FMT_RGB555,
+ .flags = FORMAT_FLAGS_PACKED,
+ }, {
+ .index = 2,
+ .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY,
+ .description = "16bpp RGB, le - ARGB[4444]",
+ .pixelformat = V4L2_PIX_FMT_RGB444,
+ .flags = FORMAT_FLAGS_PACKED,
+ }, {
+ .index = 3,
+ .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY,
+ .description = "32bpp RGB, le - ARGB[8888]",
+ .pixelformat = V4L2_PIX_FMT_RGB32,
+ .flags = FORMAT_FLAGS_PACKED,
+ }
+};
+
+const struct v4l2_standard s5p_tv_standards[] = {
+ {
+ .index = 0,
+ .id = V4L2_STD_NTSC_M,
+ .name = "NTSC_M",
+ }, {
+
+ .index = 1,
+ .id = V4L2_STD_PAL_BDGHI,
+ .name = "PAL_BDGHI",
+ }, {
+ .index = 2,
+ .id = V4L2_STD_PAL_M,
+ .name = "PAL_M",
+ }, {
+ .index = 3,
+ .id = V4L2_STD_PAL_N,
+ .name = "PAL_N",
+ }, {
+ .index = 4,
+ .id = V4L2_STD_PAL_Nc,
+ .name = "PAL_Nc",
+ }, {
+ .index = 5,
+ .id = V4L2_STD_PAL_60,
+ .name = "PAL_60",
+ }, {
+ .index = 6,
+ .id = V4L2_STD_NTSC_443,
+ .name = "NTSC_443",
+ }, {
+ .index = 7,
+ .id = V4L2_STD_480P_60_16_9,
+ .name = "480P_60_16_9",
+ }, {
+ .index = 8,
+ .id = V4L2_STD_480P_60_4_3,
+ .name = "480P_60_4_3",
+ }, {
+ .index = 9,
+ .id = V4L2_STD_576P_50_16_9,
+ .name = "576P_50_16_9",
+ }, {
+ .index = 10,
+ .id = V4L2_STD_576P_50_4_3,
+ .name = "576P_50_4_3",
+ }, {
+ .index = 11,
+ .id = V4L2_STD_720P_60,
+ .name = "720P_60",
+ }, {
+ .index = 12,
+ .id = V4L2_STD_720P_50,
+ .name = "720P_50",
+ },
+ {
+ .index = 13,
+ .id = V4L2_STD_1080P_60,
+ .name = "1080P_60",
+ }, {
+ .index = 14,
+ .id = V4L2_STD_1080P_50,
+ .name = "1080P_50",
+ }, {
+ .index = 15,
+ .id = V4L2_STD_1080I_60,
+ .name = "1080I_60",
+ }, {
+ .index = 16,
+ .id = V4L2_STD_1080I_50,
+ .name = "1080I_50",
+ }, {
+ .index = 17,
+ .id = V4L2_STD_480P_59,
+ .name = "480P_59",
+ }, {
+ .index = 18,
+ .id = V4L2_STD_720P_59,
+ .name = "720P_59",
+ }, {
+ .index = 19,
+ .id = V4L2_STD_1080I_59,
+ .name = "1080I_59",
+ }, {
+ .index = 20,
+ .id = V4L2_STD_1080P_59,
+ .name = "1080I_50",
+ }, {
+ .index = 21,
+ .id = V4L2_STD_1080P_30,
+ .name = "1080I_30",
+ }
+};
+
+/* TODO: set default format for v, vo0/1 */
+
+const struct v4l2_format s5p_tv_format[] = {
+ {
+ .type = V4L2_BUF_TYPE_VIDEO_OUTPUT,
+ }, {
+ .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY,
+ }, {
+ .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY,
+ },
+};
+
+#define S5P_TVOUT_MAX_STANDARDS ARRAY_SIZE(s5p_tv_standards)
+#define S5P_TVOUT_MAX_O_TYPES ARRAY_SIZE(s5p_tv_outputs)
+#define S5P_TVOUT_MAX_O_FMT ARRAY_SIZE(s5p_tv_format)
+#define S5P_TVOUT_MAX_O_FMT_DESC ARRAY_SIZE(s5p_tv_o_fmt_desc)
+#define S5P_TVOUT_MAX_O_OVERLAY_FMT_DESC \
+ ARRAY_SIZE(s5p_tv_o_overlay_fmt_desc)
+
+
+void s5p_tv_v4l2_init_param(void)
+{
+ s5ptv_status.v4l2.output =
+ (struct v4l2_output *)&s5p_tv_outputs[0];
+ s5ptv_status.v4l2.std =
+ (struct v4l2_standard *)&s5p_tv_standards[0];
+ s5ptv_status.v4l2.fmt_v =
+ (struct v4l2_format *)&s5p_tv_o_fmt_desc[0];
+ s5ptv_status.v4l2.fmt_vo_0 =
+ (struct v4l2_format *)&s5p_tv_format[1];
+ s5ptv_status.v4l2.fmt_vo_1 =
+ (struct v4l2_format *)&s5p_tv_format[2];
+ s5ptv_status.hdmi_audio_type = HDMI_AUDIO_PCM;
+}
+
+/* VIDIOC_QUERYCAP handler */
+static int s5p_tv_v4l2_querycap(
+ struct file *file, void *fh, struct v4l2_capability *cap)
+{
+ struct s5p_tv_vo *layer = (struct s5p_tv_vo *)fh;
+ u32 index;
+
+ if (layer == NULL) {
+ index = 0;
+ strcpy(cap->driver, "S3C TV Vid drv");
+ cap->capabilities = V4L2_CAP_VIDEO_OUTPUT;
+ } else {
+ index = layer->index + 1;
+ strcpy(cap->driver, "S3C TV Grp drv");
+ cap->capabilities = V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
+ }
+
+ strlcpy(cap->card,
+ s5ptv_status.video_dev[index]->name, sizeof(cap->card));
+
+ sprintf(cap->bus_info, "ARM AHB BUS");
+ cap->version = KERNEL_VERSION(2, 6, 29);
+
+ return 0;
+}
+
+
+/* VIDIOC_ENUM_FMT handlers */
+static int s5p_tv_v4l2_enum_fmt_vid_out(
+ struct file *file, void *fh, struct v4l2_fmtdesc *f)
+{
+ int index = f->index;
+
+ V4L2PRINTK("(%d)++\n", f->index);
+
+ if (index >= S5P_TVOUT_MAX_O_FMT_DESC) {
+ V4L2PRINTK("exceeded S5P_TVOUT_MAX_O_FMT_DESC\n");
+ return -EINVAL;
+ }
+
+ memcpy(f, &s5p_tv_o_fmt_desc[index],
+ sizeof(struct v4l2_fmtdesc));
+
+ V4L2PRINTK("()--\n");
+ return 0;
+
+}
+
+static int s5p_tv_v4l2_enum_fmt_vid_out_overlay(
+ struct file *file, void *fh, struct v4l2_fmtdesc *f)
+{
+ int index = f->index;
+
+ V4L2PRINTK("(%d)++\n", f->index);
+
+ if (index >= S5P_TVOUT_MAX_O_OVERLAY_FMT_DESC) {
+ V4L2PRINTK("exceeded S5P_TVOUT_MAX_O_OVERLAY_FMT_DESC\n");
+ return -EINVAL;
+ }
+
+ memcpy(f, &s5p_tv_o_overlay_fmt_desc[index],
+ sizeof(struct v4l2_fmtdesc));
+
+ V4L2PRINTK("()--\n");
+
+ return 0;
+}
+
+
+/* VIDIOC_G_FMT handlers */
+static int s5p_tv_v4l2_g_fmt_vid_out(
+ struct file *file, void *fh, struct v4l2_format *f)
+{
+
+ struct v4l2_format *vid_out_fmt = f;
+
+ V4L2PRINTK("(0x%08x)++\n", f->type);
+
+ switch (vid_out_fmt->type) {
+
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT: {
+
+ struct v4l2_pix_format_s5p_tvout vparam;
+ memset(&vparam, 0, sizeof(struct v4l2_pix_format_s5p_tvout));
+
+ vparam.base_y =
+ (void *)s5ptv_status.vl_basic_param.top_y_address;
+ vparam.base_c =
+ (void *)s5ptv_status.vl_basic_param.top_c_address;
+ vparam.pix_fmt.pixelformat =
+ s5ptv_status.src_color; /* VPROC_SRC_COLOR_NV12 */
+ vparam.pix_fmt.width =
+ s5ptv_status.vl_basic_param.src_width;
+ vparam.pix_fmt.height =
+ s5ptv_status.vl_basic_param.src_height;
+ V4L2PRINTK(
+ "[type0x%08x]:addr_y:[0x%08x],addr_c[0x%08x],w[%d],h[%d]\n",
+ f->type,
+ s5ptv_status.vl_basic_param.top_y_address,
+ s5ptv_status.vl_basic_param.top_c_address,
+ s5ptv_status.vl_basic_param.src_width,
+ s5ptv_status.vl_basic_param.src_height);
+ memcpy(vid_out_fmt->fmt.raw_data, &vparam,
+ sizeof(struct v4l2_pix_format_s5p_tvout));
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int s5p_tv_v4l2_g_fmt_vid_out_overlay(
+ struct file *file, void *fh, struct v4l2_format *f)
+{
+
+ struct v4l2_format *vid_out_fmt = f;
+
+ V4L2PRINTK("(0x%08x)++\n", f->type);
+
+ switch (vid_out_fmt->type) {
+
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: {
+
+ struct v4l2_window_s5p_tvout vparam;
+ memset(&vparam, 0, sizeof(struct v4l2_window_s5p_tvout));
+
+ if (s5ptv_status.vl_basic_param.win_blending) {
+ vparam.flags = V4L2_FBUF_FLAG_CHROMAKEY;
+ vparam.capability = V4L2_FBUF_CAP_CHROMAKEY;
+ }
+
+ if (s5ptv_status.vl_basic_param.alpha) {
+ vparam.flags = V4L2_FBUF_FLAG_LOCAL_ALPHA;
+ vparam.capability = V4L2_FBUF_CAP_LOCAL_ALPHA;
+ }
+
+ vparam.priority =
+ s5ptv_status.vl_basic_param.priority;
+
+ vparam.win.w.left =
+ s5ptv_status.vl_basic_param.src_offset_x;
+ vparam.win.w.top =
+ s5ptv_status.vl_basic_param.src_offset_y;
+ vparam.win.w.width =
+ s5ptv_status.vl_basic_param.src_width;
+ vparam.win.w.height =
+ s5ptv_status.vl_basic_param.src_height;
+ V4L2PRINTK(
+ "[type 0x%08x] : left:[%d],top[%d],width[%d],height[%d]\n",
+ f->type,
+ s5ptv_status.vl_basic_param.src_offset_x,
+ s5ptv_status.vl_basic_param.src_offset_y,
+ s5ptv_status.vl_basic_param.src_width,
+ s5ptv_status.vl_basic_param.src_height);
+ memcpy(vid_out_fmt->fmt.raw_data,
+ &vparam, sizeof(struct v4l2_window_s5p_tvout));
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ V4L2PRINTK("()--\n");
+
+ return 0;
+}
+
+/* VIDIOC_S_FMT handlers */
+static int s5p_tv_v4l2_s_fmt_vid_out(
+ struct file *file, void *fh, struct v4l2_format *f)
+{
+
+ struct v4l2_format *vid_out_fmt = f;
+
+ V4L2PRINTK("(0x%08x)++\n", f->type);
+
+ switch (vid_out_fmt->type) {
+
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT: {
+
+ struct v4l2_pix_format_s5p_tvout vparam;
+ memcpy(&vparam, vid_out_fmt->fmt.raw_data,
+ sizeof(struct v4l2_pix_format_s5p_tvout));
+
+ s5ptv_status.vl_basic_param.src_width =
+ vparam.pix_fmt.width;
+ s5ptv_status.vl_basic_param.src_height =
+ vparam.pix_fmt.height;
+ s5ptv_status.src_color = vparam.pix_fmt.pixelformat;
+
+ s5ptv_status.vl_basic_param.top_y_address =
+ (unsigned int)vparam.base_y;
+ s5ptv_status.vl_basic_param.top_c_address =
+ (unsigned int)vparam.base_c;
+
+ /* check progressive or not */
+ if (vparam.pix_fmt.field == V4L2_FIELD_NONE) {
+
+ /* progressive */
+
+ switch (vparam.pix_fmt.pixelformat) {
+
+ case V4L2_PIX_FMT_NV12:
+ /* linear */
+ s5ptv_status.src_color =
+ VPROC_SRC_COLOR_NV12;
+ break;
+ case V4L2_PIX_FMT_NV12T:
+ /* tiled */
+ s5ptv_status.src_color =
+ VPROC_SRC_COLOR_TILE_NV12;
+ break;
+ default:
+ V4L2PRINTK("src img format not supported\n");
+ break;
+ }
+
+ s5ptv_status.field_id = VPROC_TOP_FIELD;
+
+ if (s5ptv_status.vp_layer_enable) {
+ struct s5p_video_img_address temp_addr;
+ struct s5p_img_size img_size;
+
+ temp_addr.y_address =
+ (unsigned int)vparam.base_y;
+ temp_addr.c_address =
+ (unsigned int)vparam.base_c;
+ img_size.img_width =
+ (unsigned int)vparam.pix_fmt.width;
+ img_size.img_height =
+ (unsigned int)vparam.pix_fmt.height;
+
+ tv_vlayer_set_top_address(
+ (unsigned long)&temp_addr);
+ tv_vlayer_set_img_size(
+ (unsigned long)&img_size);
+ tv_vlayer_set_src_size(
+ (unsigned long)&img_size);
+
+ }
+ } else if (vparam.pix_fmt.field == V4L2_FIELD_INTERLACED_TB) {
+
+ /* interlaced */
+
+ switch (vparam.pix_fmt.pixelformat) {
+
+ case V4L2_PIX_FMT_NV12:
+ /* linear */
+ s5ptv_status.src_color = VPROC_SRC_COLOR_NV12IW;
+ break;
+ case V4L2_PIX_FMT_NV12T:
+ /* tiled */
+ s5ptv_status.src_color =
+ VPROC_SRC_COLOR_TILE_NV12IW;
+ break;
+ default:
+ V4L2PRINTK("src img format not supported\n");
+ break;
+ }
+
+ if (vparam.pix_fmt.priv == V4L2_FIELD_BOTTOM)
+ s5ptv_status.field_id = VPROC_BOTTOM_FIELD;
+ else
+ s5ptv_status.field_id = VPROC_TOP_FIELD;
+
+ if (s5ptv_status.vp_layer_enable) {
+ struct s5p_video_img_address temp_addr;
+ struct s5p_img_size img_size;
+
+ temp_addr.y_address =
+ (unsigned int)vparam.base_y;
+ temp_addr.c_address =
+ (unsigned int)vparam.base_c;
+ img_size.img_width =
+ (unsigned int)vparam.pix_fmt.width;
+ img_size.img_height =
+ (unsigned int)vparam.pix_fmt.height;
+
+ tv_vlayer_set_top_address(
+ (unsigned long)&temp_addr);
+ tv_vlayer_set_img_size(
+ (unsigned long)&img_size);
+ tv_vlayer_set_src_size(
+ (unsigned long)&img_size);
+
+ }
+
+ } else {
+ V4L2PRINTK("this field id not supported\n");
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ V4L2PRINTK(
+ "[type 0x%08x] : addr_y:[0x%08x],addr_c[0x%08x],width[%d],height[%d]\n",
+ f->type,
+ s5ptv_status.vl_basic_param.top_y_address,
+ s5ptv_status.vl_basic_param.top_c_address,
+ s5ptv_status.vl_basic_param.src_width,
+ s5ptv_status.vl_basic_param.src_height);
+ V4L2PRINTK("()--\n");
+
+ return 0;
+}
+
+
+static int s5p_tv_v4l2_s_fmt_vid_out_overlay(
+ struct file *file, void *fh, struct v4l2_format *f)
+{
+
+ struct v4l2_format *vid_out_fmt = f;
+
+ V4L2PRINTK("(0x%08x)++\n", f->type);
+
+ switch (vid_out_fmt->type) {
+
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: {
+
+ struct v4l2_window_s5p_tvout vparam;
+ memcpy(&vparam, vid_out_fmt->fmt.raw_data,
+ sizeof(struct v4l2_window_s5p_tvout));
+
+ s5ptv_status.vl_basic_param.win_blending =
+ (vparam.flags & V4L2_FBUF_FLAG_CHROMAKEY) ? 1 : 0;
+ s5ptv_status.vl_basic_param.alpha =
+ (vparam.flags & V4L2_FBUF_FLAG_LOCAL_ALPHA) ? 1 : 0;
+ s5ptv_status.vl_basic_param.priority =
+ vparam.priority;
+ s5ptv_status.vl_basic_param.src_offset_x =
+ vparam.win.w.left;
+ s5ptv_status.vl_basic_param.src_offset_y =
+ vparam.win.w.top;
+ s5ptv_status.vl_basic_param.src_width = vparam.win.w.width;
+ s5ptv_status.vl_basic_param.src_height = vparam.win.w.height;
+ V4L2PRINTK(
+ "[type 0x%08x] : left: [%d],top [%d],width[%d],height[%d]\n",
+ f->type,
+ s5ptv_status.vl_basic_param.src_offset_x,
+ s5ptv_status.vl_basic_param.src_offset_y,
+ s5ptv_status.vl_basic_param.src_width,
+ s5ptv_status.vl_basic_param.src_height);
+
+ if (s5ptv_status.vp_layer_enable) {
+ struct s5p_img_offset img_offset;
+ struct s5p_img_size img_size;
+
+ img_offset.offset_x = vparam.win.w.left;
+ img_offset.offset_y = vparam.win.w.top;
+ img_size.img_width = vparam.win.w.width;
+ img_size.img_height = vparam.win.w.height;
+ tv_vlayer_set_blending(
+ s5ptv_status.vl_basic_param.win_blending);
+ tv_vlayer_set_alpha(
+ s5ptv_status.vl_basic_param.alpha);
+ tv_vlayer_set_priority(vparam.priority);
+ tv_vlayer_set_src_position(
+ (unsigned long)&img_offset);
+ tv_vlayer_set_src_size((unsigned long)&img_size);
+ }
+
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ V4L2PRINTK("()--\n");
+
+ return 0;
+}
+
+/* start overlay * */
+static int s5p_tv_v4l2_overlay(struct file *file, void *fh, unsigned int i)
+{
+ struct s5p_tv_vo *layer = (struct s5p_tv_vo *)fh;
+ int start = i;
+ V4L2PRINTK("(0x%08x)++\n", i);
+
+ if (start)
+ tv_grp_start(layer->index);
+ else
+ tv_grp_stop(layer->index);
+
+ return 0;
+}
+
+static int s5p_tv_v4l2_g_fbuf(
+ struct file *file, void *fh, struct v4l2_framebuffer *a)
+{
+
+ struct v4l2_framebuffer *fbuf = a;
+ struct s5p_tv_vo *layer = (struct s5p_tv_vo *)fh;
+
+ fbuf->base = (void *)s5ptv_overlay[layer->index].base_addr;
+ fbuf->fmt.pixelformat = s5ptv_overlay[layer->index].fb.fmt.pixelformat;
+
+ return 0;
+}
+
+static int s5p_tv_v4l2_s_fbuf(
+ struct file *file, void *fh, struct v4l2_framebuffer *a)
+{
+
+ struct v4l2_framebuffer *fbuf = a;
+ struct s5p_tv_vo *layer = (struct s5p_tv_vo *)fh;
+
+ s5ptv_overlay[layer->index].base_addr = (unsigned int)fbuf->base;
+
+ switch (fbuf->fmt.pixelformat) {
+
+ case V4L2_PIX_FMT_RGB565:
+ s5ptv_overlay[layer->index].fb.fmt.pixelformat =
+ VM_DIRECT_RGB565;
+ break;
+
+ case V4L2_PIX_FMT_RGB555:
+ s5ptv_overlay[layer->index].fb.fmt.pixelformat =
+ VM_DIRECT_RGB1555;
+ break;
+
+ case V4L2_PIX_FMT_RGB444:
+ s5ptv_overlay[layer->index].fb.fmt.pixelformat =
+ VM_DIRECT_RGB4444;
+ break;
+
+ case V4L2_PIX_FMT_RGB32:
+ s5ptv_overlay[layer->index].fb.fmt.pixelformat =
+ VM_DIRECT_RGB8888;
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/* Stream on/off */
+static int s5p_tv_v4l2_streamon(
+ struct file *file, void *fh, enum v4l2_buf_type i)
+{
+ struct s5p_tv_vo *layer = (struct s5p_tv_vo *)fh;
+
+ V4L2PRINTK("(0x%08x)++\n", i);
+
+ switch (i) {
+
+ /* Vlayer */
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ tv_vlayer_init_param(0);
+ tv_vlayer_start();
+ s5ptv_status.vp_layer_enable = true;
+ break;
+
+ /* GRP0/1 */
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
+ tv_grp_start(layer->index);
+ break;
+
+ default:
+ break;
+ }
+
+ V4L2PRINTK("()--\n");
+
+ return 0;
+}
+
+static int s5p_tv_v4l2_streamoff(
+ struct file *file, void *fh, enum v4l2_buf_type i)
+{
+ struct s5p_tv_vo *layer = (struct s5p_tv_vo *)fh;
+
+ V4L2PRINTK("(0x%08x)++\n", i);
+
+ switch (i) {
+
+ /* Vlayer */
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ tv_vlayer_stop();
+ break;
+
+ /* GRP0/1 */
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
+ tv_grp_stop(layer->index);
+ break;
+
+ default:
+ break;
+ }
+
+ V4L2PRINTK("()--\n");
+
+ return 0;
+}
+
+/* Standard handling ENUMSTD is handled by videodev.c */
+static int s5p_tv_v4l2_g_std(struct file *file, void *fh, v4l2_std_id *norm)
+{
+ V4L2PRINTK("()++\n");
+
+ *norm = s5ptv_status.v4l2.std->id;
+
+ V4L2PRINTK("(%d)++\n", (int)(*norm));
+
+ return 0;
+}
+
+static int s5p_tv_v4l2_s_std(struct file *file, void *fh, v4l2_std_id *norm)
+{
+ unsigned int i = 0;
+ v4l2_std_id std_id = *norm;
+
+ V4L2PRINTK("(0x%08Lx)++\n", std_id);
+
+ s5ptv_status.v4l2.std = NULL;
+
+ do {
+ if (s5p_tv_standards[i].id == std_id) {
+ s5ptv_status.v4l2.std =
+ (struct v4l2_standard *)&s5p_tv_standards[i];
+ break;
+ }
+
+ i++;
+ } while (i < S5P_TVOUT_MAX_STANDARDS);
+
+ if (i >= S5P_TVOUT_MAX_STANDARDS || s5ptv_status.v4l2.std == NULL) {
+ V4L2PRINTK(
+ "(ERR) There is no tv-out standards : index = 0x%08Lx\n",
+ std_id);
+ return -EINVAL;
+ }
+
+ switch (std_id) {
+
+ case V4L2_STD_NTSC_M:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_NTSC_M;
+ break;
+
+ case V4L2_STD_PAL_BDGHI:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_PAL_BDGHI;
+ break;
+
+ case V4L2_STD_PAL_M:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_PAL_M;
+ break;
+
+ case V4L2_STD_PAL_N:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_PAL_N;
+ break;
+
+ case V4L2_STD_PAL_Nc:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_PAL_NC;
+ break;
+
+ case V4L2_STD_PAL_60:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_PAL_60;
+ break;
+
+ case V4L2_STD_NTSC_443:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_NTSC_443;
+ break;
+
+ case V4L2_STD_480P_60_16_9:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_480P_60_16_9;
+ break;
+
+ case V4L2_STD_480P_60_4_3:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_480P_60_4_3;
+ break;
+
+ case V4L2_STD_480P_59:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_480P_59;
+ break;
+
+ case V4L2_STD_576P_50_16_9:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_576P_50_16_9;
+ break;
+
+ case V4L2_STD_576P_50_4_3:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_576P_50_4_3;
+ break;
+
+ case V4L2_STD_720P_60:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_720P_60;
+ break;
+
+ case V4L2_STD_720P_59:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_720P_59;
+ break;
+
+ case V4L2_STD_720P_50:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_720P_50;
+ break;
+
+ case V4L2_STD_1080I_60:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_1080I_60;
+ break;
+
+ case V4L2_STD_1080I_59:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_1080I_59;
+ break;
+
+ case V4L2_STD_1080I_50:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_1080I_50;
+ break;
+
+ case V4L2_STD_1080P_30:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_1080P_30;
+ break;
+
+ case V4L2_STD_1080P_60:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_1080P_60;
+ break;
+
+ case V4L2_STD_1080P_59:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_1080P_59;
+ break;
+
+ case V4L2_STD_1080P_50:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_1080P_50;
+ break;
+ default:
+ V4L2PRINTK(
+ "(ERR) not supported standard id : index = 0x%08Lx\n",
+ std_id);
+ return -EINVAL;
+ }
+
+ V4L2PRINTK("()--\n");
+
+ return 0;
+}
+
+/* Output handling */
+static int s5p_tv_v4l2_enum_output(struct file *file,
+ void *fh, struct v4l2_output *a)
+{
+ unsigned int index = a->index;
+ V4L2PRINTK("(%d)++\n", a->index);
+
+ if (index >= S5P_TVOUT_MAX_O_TYPES) {
+ V4L2PRINTK("exceeded supported output!!\n");
+ return -EINVAL;
+ }
+
+ memcpy(a, &s5p_tv_outputs[index], sizeof(struct v4l2_output));
+
+ V4L2PRINTK("()--\n");
+
+ return 0;
+}
+
+static int s5p_tv_v4l2_g_output(struct file *file, void *fh, unsigned int *i)
+{
+ V4L2PRINTK("(%d)++\n", *i);
+
+ *i = s5ptv_status.v4l2.output->index;
+
+ V4L2PRINTK("()--\n");
+ return 0;
+}
+
+static int s5p_tv_v4l2_s_output(struct file *file, void *fh, unsigned int i)
+{
+ V4L2PRINTK("(%d)++\n", i);
+
+ if (i >= S5P_TVOUT_MAX_O_TYPES)
+ return -EINVAL;
+
+ s5ptv_status.v4l2.output = &s5p_tv_outputs[i];
+
+ switch (s5ptv_status.v4l2.output->type) {
+
+ case V4L2_OUTPUT_TYPE_COMPOSITE:
+ s5ptv_status.tvout_param.out_mode = TVOUT_OUTPUT_COMPOSITE;
+ break;
+
+ case V4L2_OUTPUT_TYPE_SVIDEO:
+ s5ptv_status.tvout_param.out_mode = TVOUT_OUTPUT_SVIDEO;
+ break;
+
+ case V4L2_OUTPUT_TYPE_YPBPR_INERLACED:
+ s5ptv_status.tvout_param.out_mode =
+ TVOUT_OUTPUT_COMPONENT_YPBPR_INERLACED;
+ break;
+
+ case V4L2_OUTPUT_TYPE_YPBPR_PROGRESSIVE:
+ s5ptv_status.tvout_param.out_mode =
+ TVOUT_OUTPUT_COMPONENT_YPBPR_PROGRESSIVE;
+ break;
+
+ case V4L2_OUTPUT_TYPE_RGB_PROGRESSIVE:
+ s5ptv_status.tvout_param.out_mode = TVOUT_OUTPUT_COMPOSITE;
+ break;
+
+ case V4L2_OUTPUT_TYPE_HDMI:
+ s5ptv_status.tvout_param.out_mode = TVOUT_OUTPUT_HDMI;
+ break;
+
+ case V4L2_OUTPUT_TYPE_HDMI_RGB:
+ s5ptv_status.tvout_param.out_mode = TVOUT_OUTPUT_HDMI_RGB;
+ break;
+
+ case V4L2_OUTPUT_TYPE_DVI:
+ s5ptv_status.tvout_param.out_mode = TVOUT_OUTPUT_DVI;
+ break;
+
+ default:
+ break;
+ }
+
+ tv_if_set_disp();
+
+ V4L2PRINTK("()--\n");
+
+ return 0;
+};
+
+/* Crop ioctls */
+
+/*
+ * Video Format Name Pixel aspect ratio Description
+ * STD(4:3) Anamorphic(16:9)
+ * 640x480 4:3 Used on YouTube
+ * 720x576 576i 5:4 64:45 Used on D1/DV PAL
+ * 704x576 576p 12:11 16:11 Used on EDTV PAL
+ * 720x480 480i 8:9 32:27 Used on DV NTSC
+ * 720x486 480i 8:9 32:27 Used on D1 NTSC (ITU-R 601)
+ * 704x480 480p 10:11 40:33 Used on EDTV NTSC
+ */
+
+static int s5p_tv_v4l2_cropcap(struct file *file, void *fh,
+ struct v4l2_cropcap *a)
+{
+
+ struct v4l2_cropcap *cropcap = a;
+
+ switch (cropcap->type) {
+
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ break;
+
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
+ break;
+
+ default:
+ return -1;
+ }
+
+ switch (s5ptv_status.tvout_param.disp_mode) {
+
+ case TVOUT_NTSC_M:
+ case TVOUT_NTSC_443:
+ case TVOUT_480P_60_16_9:
+ case TVOUT_480P_60_4_3:
+ case TVOUT_480P_59:
+ cropcap->bounds.top = 0;
+ cropcap->bounds.left = 0;
+ cropcap->bounds.width = 720;
+ cropcap->bounds.height = 480;
+
+ cropcap->defrect.top = 0;
+ cropcap->defrect.left = 0;
+ cropcap->defrect.width = 720;
+ cropcap->defrect.height = 480;
+ break;
+
+ case TVOUT_PAL_M:
+ case TVOUT_PAL_BDGHI:
+ case TVOUT_PAL_N:
+ case TVOUT_PAL_NC:
+ case TVOUT_PAL_60:
+ case TVOUT_576P_50_16_9:
+ case TVOUT_576P_50_4_3:
+ cropcap->bounds.top = 0;
+ cropcap->bounds.left = 0;
+ cropcap->bounds.width = 720;
+ cropcap->bounds.height = 576;
+
+ cropcap->defrect.top = 0;
+ cropcap->defrect.left = 0;
+ cropcap->defrect.width = 720;
+ cropcap->defrect.height = 576;
+ break;
+
+ case TVOUT_720P_60:
+ case TVOUT_720P_59:
+ case TVOUT_720P_50:
+ cropcap->bounds.top = 0;
+ cropcap->bounds.left = 0;
+ cropcap->bounds.width = 1280;
+ cropcap->bounds.height = 720;
+
+ cropcap->defrect.top = 0;
+ cropcap->defrect.left = 0;
+ cropcap->defrect.width = 1280;
+ cropcap->defrect.height = 720;
+ break;
+
+ case TVOUT_1080I_60:
+ case TVOUT_1080I_59:
+ case TVOUT_1080I_50:
+ case TVOUT_1080P_60:
+ case TVOUT_1080P_59:
+ case TVOUT_1080P_50:
+ case TVOUT_1080P_30:
+ cropcap->bounds.top = 0;
+ cropcap->bounds.left = 0;
+ cropcap->bounds.width = 1920;
+ cropcap->bounds.height = 1080;
+
+ cropcap->defrect.top = 0;
+ cropcap->defrect.left = 0;
+ cropcap->defrect.width = 1920;
+ cropcap->defrect.height = 1080;
+ break;
+
+ default:
+ return -1;
+
+ }
+
+ V4L2PRINTK("[input type 0x%08x] : left: \
+ [%d], top [%d], width[%d], height[%d]\n",
+ s5ptv_status.tvout_param.disp_mode,
+ cropcap->bounds.top ,
+ cropcap->bounds.left ,
+ cropcap->bounds.width,
+ cropcap->bounds.height);
+
+ return 0;
+}
+
+static int s5p_tv_v4l2_g_crop(struct file *file, void *fh, struct v4l2_crop *a)
+{
+
+ struct v4l2_crop *crop = a;
+ struct s5p_tv_vo *layer = (struct s5p_tv_vo *)fh;
+
+ switch (crop->type) {
+
+ /* Vlayer */
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ crop->c.left = s5ptv_status.vl_basic_param.dest_offset_x;
+ crop->c.top = s5ptv_status.vl_basic_param.dest_offset_y;
+ crop->c.width = s5ptv_status.vl_basic_param.dest_width;
+ crop->c.height = s5ptv_status.vl_basic_param.dest_height;
+ break;
+
+ /* GRP0/1 */
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
+ crop->c.left = s5ptv_overlay[layer->index].dst_rect.left;
+ crop->c.top = s5ptv_overlay[layer->index].dst_rect.top;
+ crop->c.width = s5ptv_overlay[layer->index].dst_rect.width;
+ crop->c.height = s5ptv_overlay[layer->index].dst_rect.height;
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int s5p_tv_v4l2_s_crop(struct file *file, void *fh, struct v4l2_crop *a)
+{
+
+ struct v4l2_crop *crop = a;
+ struct s5p_tv_vo *layer = (struct s5p_tv_vo *)fh;
+
+ switch (crop->type) {
+
+ /* Vlayer - scaling!! */
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+
+ s5ptv_status.vl_basic_param.dest_offset_x = crop->c.left;
+ s5ptv_status.vl_basic_param.dest_offset_y = crop->c.top;
+ s5ptv_status.vl_basic_param.dest_width = crop->c.width;
+ s5ptv_status.vl_basic_param.dest_height = crop->c.height;
+
+ if (s5ptv_status.vp_layer_enable) {
+ struct s5p_img_size img_size;
+ struct s5p_img_offset img_offset;
+ img_size.img_width = crop->c.width;
+ img_size.img_height = crop->c.height;
+ img_offset.offset_x = crop->c.left;
+ img_offset.offset_y = crop->c.top;
+
+ tv_vlayer_set_dest_size((unsigned long)&img_size);
+ tv_vlayer_set_dest_position(
+ (unsigned long)&img_offset);
+ }
+ break;
+
+ /* GRP0/1 */
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
+ s5ptv_overlay[layer->index].dst_rect.left = crop->c.left;
+ s5ptv_overlay[layer->index].dst_rect.top = crop->c.top;
+ s5ptv_overlay[layer->index].dst_rect.width
+ = crop->c.width;
+ s5ptv_overlay[layer->index].dst_rect.height
+ = crop->c.height;
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/* Stream type-dependent parameter ioctls */
+static int s5p_tv_v4l2_g_parm_v(struct file *file, void *fh,
+ struct v4l2_streamparm *a)
+{
+
+ struct v4l2_streamparm *param = a;
+
+ struct v4l2_window_s5p_tvout vparam;
+
+ if (s5ptv_status.vl_basic_param.win_blending) {
+ vparam.flags = V4L2_FBUF_FLAG_GLOBAL_ALPHA;
+ vparam.capability = V4L2_FBUF_FLAG_GLOBAL_ALPHA;
+ }
+
+ vparam.win.global_alpha = s5ptv_status.vl_basic_param.alpha;
+
+ vparam.priority = s5ptv_status.vl_basic_param.priority;
+ vparam.win.w.left = s5ptv_status.vl_basic_param.src_offset_x;
+ vparam.win.w.top = s5ptv_status.vl_basic_param.src_offset_y;
+ vparam.win.w.width = s5ptv_status.vl_basic_param.src_width;
+ vparam.win.w.height = s5ptv_status.vl_basic_param.src_height;
+
+ memcpy(param->parm.raw_data, &vparam,
+ sizeof(struct v4l2_window_s5p_tvout));
+
+ return 0;
+}
+
+static int s5p_tv_v4l2_s_parm_v(struct file *file, void *fh,
+ struct v4l2_streamparm *a)
+{
+
+ struct v4l2_streamparm *param = a;
+
+ struct v4l2_window_s5p_tvout vparam;
+
+ memcpy(&vparam, param->parm.raw_data,
+ sizeof(struct v4l2_window_s5p_tvout));
+
+ s5ptv_status.vl_basic_param.win_blending =
+ (vparam.flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) ? 1 : 0;
+ s5ptv_status.vl_basic_param.alpha = vparam.win.global_alpha;
+ s5ptv_status.vl_basic_param.priority = vparam.priority;
+ s5ptv_status.vl_basic_param.src_offset_x = vparam.win.w.left;
+ s5ptv_status.vl_basic_param.src_offset_y = vparam.win.w.top;
+ s5ptv_status.vl_basic_param.src_width = vparam.win.w.width;
+ s5ptv_status.vl_basic_param.src_height = vparam.win.w.height;
+
+ V4L2PRINTK("[type 0x%08x] : left: [%d], top [%d], \
+ width[%d], height[%d]\n",
+ a->type,
+ s5ptv_status.vl_basic_param.src_offset_x,
+ s5ptv_status.vl_basic_param.src_offset_y,
+ s5ptv_status.vl_basic_param.src_width,
+ s5ptv_status.vl_basic_param.src_height);
+
+ if (s5ptv_status.vp_layer_enable) {
+ struct s5p_img_offset img_offset;
+ struct s5p_img_size img_size;
+
+ img_offset.offset_x = vparam.win.w.left;
+ img_offset.offset_y = vparam.win.w.top;
+ img_size.img_width = vparam.win.w.width;
+ img_size.img_height = vparam.win.w.height;
+ tv_vlayer_set_blending(
+ s5ptv_status.vl_basic_param.win_blending);
+ tv_vlayer_set_alpha(s5ptv_status.vl_basic_param.alpha);
+ tv_vlayer_set_priority(vparam.priority);
+ tv_vlayer_set_src_position((unsigned long)&img_offset);
+ tv_vlayer_set_src_size((unsigned long)&img_size);
+ }
+
+ return 0;
+}
+
+static int s5p_tv_v4l2_g_parm_vo(struct file *file, void *fh,
+ struct v4l2_streamparm *a)
+{
+
+ struct v4l2_streamparm *param = a;
+
+ struct v4l2_window_s5p_tvout vparam;
+ struct s5p_tv_vo *layer = (struct s5p_tv_vo *)fh;
+
+ memset(&vparam, 0, sizeof(struct v4l2_window_s5p_tvout));
+
+ V4L2PRINTK("entered\n");
+
+ if (s5ptv_overlay[layer->index].win_blending) {
+ vparam.flags = V4L2_FBUF_FLAG_GLOBAL_ALPHA;
+ vparam.capability = V4L2_FBUF_CAP_GLOBAL_ALPHA;
+ }
+
+ if (s5ptv_overlay[layer->index].blank_change) {
+ vparam.flags |= V4L2_FBUF_FLAG_CHROMAKEY;
+ vparam.capability |= V4L2_FBUF_CAP_CHROMAKEY;
+ }
+
+ if (s5ptv_overlay[layer->index].pixel_blending) {
+ vparam.flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
+ vparam.capability |= V4L2_FBUF_CAP_LOCAL_ALPHA;
+ }
+
+ if (s5ptv_overlay[layer->index].pre_mul) {
+ vparam.flags |= V4L2_FBUF_FLAG_PRE_MULTIPLY;
+ vparam.capability |= V4L2_FBUF_CAP_PRE_MULTIPLY;
+ }
+
+ vparam.priority = s5ptv_overlay[layer->index].priority;
+
+ vparam.win.chromakey =
+ s5ptv_overlay[layer->index].blank_color;
+ vparam.win.w.left = s5ptv_overlay[layer->index].dst_rect.left;
+ vparam.win.w.top = s5ptv_overlay[layer->index].dst_rect.top;
+ vparam.win.w.left = s5ptv_overlay[layer->index].win.w.left;
+ vparam.win.w.top = s5ptv_overlay[layer->index].win.w.top;
+ vparam.win.w.width = s5ptv_overlay[layer->index].win.w.width;
+ vparam.win.w.height = s5ptv_overlay[layer->index].win.w.height;
+ vparam.win.global_alpha =
+ s5ptv_overlay[layer->index].win.global_alpha;
+ vparam.win.w.width =
+ s5ptv_overlay[layer->index].fb.fmt.bytesperline;
+
+ memcpy(param->parm.raw_data, &vparam,
+ sizeof(struct v4l2_window_s5p_tvout));
+
+ return 0;
+
+}
+
+
+static int s5p_tv_v4l2_s_parm_vo(struct file *file, void *fh,
+ struct v4l2_streamparm *a)
+{
+
+ struct v4l2_streamparm *param = a;
+
+ struct v4l2_window_s5p_tvout vparam;
+
+ struct s5p_tv_vo *layer = (struct s5p_tv_vo *)fh;
+ memcpy(&vparam, param->parm.raw_data,
+ sizeof(struct v4l2_window_s5p_tvout));
+
+ s5ptv_overlay[layer->index].win_blending =
+ (vparam.flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) ? 1 : 0;
+ s5ptv_overlay[layer->index].blank_change =
+ (vparam.flags & V4L2_FBUF_FLAG_CHROMAKEY) ? 1 : 0;
+ s5ptv_overlay[layer->index].pixel_blending =
+ (vparam.flags & V4L2_FBUF_FLAG_LOCAL_ALPHA) ? 1 : 0;
+ s5ptv_overlay[layer->index].pre_mul =
+ (vparam.flags & V4L2_FBUF_FLAG_PRE_MULTIPLY) ? 1 : 0;
+ s5ptv_overlay[layer->index].priority = vparam.priority;
+ s5ptv_overlay[layer->index].blank_color =
+ vparam.win.chromakey;
+ s5ptv_overlay[layer->index].dst_rect.left = vparam.win.w.left;
+ s5ptv_overlay[layer->index].dst_rect.top = vparam.win.w.top;
+ s5ptv_overlay[layer->index].win.w.left = vparam.win.w.left;
+ s5ptv_overlay[layer->index].win.w.top = vparam.win.w.top;
+ s5ptv_overlay[layer->index].win.w.width = vparam.win.w.width;
+ s5ptv_overlay[layer->index].win.w.height = vparam.win.w.height;
+ s5ptv_overlay[layer->index].win.global_alpha =
+ vparam.win.global_alpha;
+
+ s5ptv_overlay[layer->index].fb.fmt.bytesperline = vparam.win.w.width;
+
+ return 0;
+}
+
+#define VIDIOC_HDCP_ENABLE _IOWR('V', 100, unsigned int)
+#define VIDIOC_HDCP_STATUS _IOR('V', 101, unsigned int)
+#define VIDIOC_HDCP_PROT_STATUS _IOR('V', 102, unsigned int)
+
+long s5p_tv_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ switch (cmd) {
+
+ case VIDIOC_HDCP_ENABLE:
+ s5ptv_status.hdcp_en = (unsigned int) arg;
+ V4L2PRINTK("HDCP status is %s\n",
+ s5ptv_status.hdcp_en ? "enabled" : "disabled");
+ return 0;
+
+ case VIDIOC_HDCP_STATUS: {
+
+ unsigned int *status = (unsigned int *)&arg;
+
+ *status = 1;
+
+ V4L2PRINTK("HPD status is %s\n",
+ s5ptv_status.hpd_status ? "plugged" : "unplugged");
+ return 0;
+ }
+
+ case VIDIOC_HDCP_PROT_STATUS: {
+
+ unsigned int *prot = (unsigned int *)&arg;
+
+ *prot = 1;
+
+ V4L2PRINTK("hdcp prot status is %d\n",
+ hdcp_protocol_status);
+ return 0;
+ }
+
+ case VIDIOC_ENUMSTD: {
+
+ struct v4l2_standard *p = (struct v4l2_standard *)arg;
+
+ if (p->index >= S5P_TVOUT_MAX_STANDARDS) {
+ V4L2PRINTK("exceeded S5P_TVOUT_MAX_STANDARDS\n");
+ return -EINVAL;
+ }
+
+ memcpy(p, &s5p_tv_standards[p->index],
+ sizeof(struct v4l2_standard));
+ return 0;
+ }
+
+ default:
+ break;
+ }
+
+ return video_ioctl2(file, cmd, arg);
+}
+
+long s5p_tv_vid_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct video_device *vfd = video_devdata(file);
+ const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;
+
+ switch (cmd) {
+
+ case VIDIOC_S_FMT: {
+ struct v4l2_format *f = (struct v4l2_format *)arg;
+ void *fh = file->private_data;
+ long ret = -EINVAL;
+
+ if (ops->vidioc_s_fmt_vid_out)
+ ret = ops->vidioc_s_fmt_vid_out(file, fh, f);
+ return ret;
+ }
+
+ default:
+ break;
+ }
+
+ return video_ioctl2(file, cmd, arg);
+}
+
+
+long s5p_tv_v_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct video_device *vfd = video_devdata(file);
+ const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;
+
+ switch (cmd) {
+
+ case VIDIOC_S_FMT: {
+ struct v4l2_format *f = (struct v4l2_format *)arg;
+ void *fh = file->private_data;
+ long ret = -EINVAL;
+
+ if (ops->vidioc_s_fmt_vid_out)
+ ret = ops->vidioc_s_fmt_vid_out(file, fh, f);
+ return ret;
+ }
+
+ case VIDIOC_HDCP_ENABLE:
+ s5ptv_status.hdcp_en = (unsigned int) arg;
+ V4L2PRINTK("HDCP status is %s\n",
+ s5ptv_status.hdcp_en ? "enabled" : "disabled");
+ return 0;
+
+ case VIDIOC_HDCP_STATUS: {
+
+ unsigned int *status = (unsigned int *)&arg;
+
+ *status = 1;
+
+ V4L2PRINTK("HPD status is %s\n",
+ s5ptv_status.hpd_status ? "plugged" : "unplugged");
+ return 0;
+ }
+
+ case VIDIOC_HDCP_PROT_STATUS: {
+
+ unsigned int *prot = (unsigned int *)&arg;
+
+ *prot = 1;
+
+ V4L2PRINTK("hdcp prot status is %d\n",
+ hdcp_protocol_status);
+ return 0;
+ }
+
+ case VIDIOC_ENUMSTD: {
+
+ struct v4l2_standard *p = (struct v4l2_standard *)arg;
+
+ if (p->index >= S5P_TVOUT_MAX_STANDARDS) {
+ V4L2PRINTK("exceeded S5P_TVOUT_MAX_STANDARDS\n");
+ return -EINVAL;
+ }
+
+ memcpy(p, &s5p_tv_standards[p->index],
+ sizeof(struct v4l2_standard));
+
+ return 0;
+ }
+
+ default:
+ break;
+ }
+
+ return video_ioctl2(file, cmd, arg);
+}
+
+long s5p_tv_vo_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ void *fh = file->private_data;
+
+ switch (cmd) {
+
+ case VIDIOC_ENUM_FMT: {
+
+ struct v4l2_fmtdesc *f = (struct v4l2_fmtdesc *)arg;
+ enum v4l2_buf_type type;
+ unsigned int index;
+
+ index = f->index;
+ type = f->type;
+
+ if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY) {
+ memset(f, 0, sizeof(*f));
+ f->index = index;
+ f->type = type;
+
+ return s5p_tv_v4l2_enum_fmt_vid_out_overlay(
+ file, fh, f);
+ }
+
+ break;
+ }
+
+ case VIDIOC_G_FMT: {
+
+ struct v4l2_format *f = (struct v4l2_format *)arg;
+
+ return s5p_tv_v4l2_g_fmt_vid_out_overlay(file, fh, f);
+ }
+
+ break;
+
+ default:
+ break;
+ }
+
+ /*
+ * in 2.6.28 version Mauro Carvalho Chehab added for removing inode
+ * but 2.6.29 is not applied. what is it?
+ */
+ return video_ioctl2(file, cmd, arg);
+}
+
+const struct v4l2_ioctl_ops s5p_tv_v4l2_ops = {
+ .vidioc_querycap = s5p_tv_v4l2_querycap,
+ .vidioc_g_std = s5p_tv_v4l2_g_std,
+ .vidioc_s_std = s5p_tv_v4l2_s_std,
+ .vidioc_enum_output = s5p_tv_v4l2_enum_output,
+ .vidioc_g_output = s5p_tv_v4l2_g_output,
+ .vidioc_s_output = s5p_tv_v4l2_s_output,
+};
+
+const struct v4l2_ioctl_ops s5p_tv_v4l2_vid_ops = {
+ .vidioc_querycap = s5p_tv_v4l2_querycap,
+ .vidioc_enum_fmt_vid_out = s5p_tv_v4l2_enum_fmt_vid_out,
+ .vidioc_g_fmt_vid_out = s5p_tv_v4l2_g_fmt_vid_out,
+ .vidioc_s_fmt_vid_out = s5p_tv_v4l2_s_fmt_vid_out,
+ .vidioc_streamon = s5p_tv_v4l2_streamon,
+ .vidioc_streamoff = s5p_tv_v4l2_streamoff,
+ .vidioc_cropcap = s5p_tv_v4l2_cropcap,
+ .vidioc_g_crop = s5p_tv_v4l2_g_crop,
+ .vidioc_s_crop = s5p_tv_v4l2_s_crop,
+ .vidioc_g_parm = s5p_tv_v4l2_g_parm_v,
+ .vidioc_s_parm = s5p_tv_v4l2_s_parm_v,
+};
+
+const struct v4l2_ioctl_ops s5p_tv_v4l2_v_ops = {
+ .vidioc_querycap = s5p_tv_v4l2_querycap,
+ .vidioc_enum_fmt_vid_out = s5p_tv_v4l2_enum_fmt_vid_out,
+ .vidioc_g_fmt_vid_out = s5p_tv_v4l2_g_fmt_vid_out,
+ .vidioc_s_fmt_vid_out = s5p_tv_v4l2_s_fmt_vid_out,
+ .vidioc_streamon = s5p_tv_v4l2_streamon,
+ .vidioc_streamoff = s5p_tv_v4l2_streamoff,
+ .vidioc_g_std = s5p_tv_v4l2_g_std,
+ .vidioc_s_std = s5p_tv_v4l2_s_std,
+ .vidioc_enum_output = s5p_tv_v4l2_enum_output,
+ .vidioc_g_output = s5p_tv_v4l2_g_output,
+ .vidioc_s_output = s5p_tv_v4l2_s_output,
+ .vidioc_cropcap = s5p_tv_v4l2_cropcap,
+ .vidioc_g_crop = s5p_tv_v4l2_g_crop,
+ .vidioc_s_crop = s5p_tv_v4l2_s_crop,
+ .vidioc_g_parm = s5p_tv_v4l2_g_parm_v,
+ .vidioc_s_parm = s5p_tv_v4l2_s_parm_v,
+};
+
+const struct v4l2_ioctl_ops s5p_tv_v4l2_vo_ops = {
+ .vidioc_querycap = s5p_tv_v4l2_querycap,
+ .vidioc_g_fmt_vid_out_overlay = s5p_tv_v4l2_g_fmt_vid_out_overlay,
+ .vidioc_s_fmt_vid_out_overlay = s5p_tv_v4l2_s_fmt_vid_out_overlay,
+ .vidioc_overlay = s5p_tv_v4l2_overlay,
+ .vidioc_g_fbuf = s5p_tv_v4l2_g_fbuf,
+ .vidioc_s_fbuf = s5p_tv_v4l2_s_fbuf,
+ .vidioc_streamon = s5p_tv_v4l2_streamon,
+ .vidioc_streamoff = s5p_tv_v4l2_streamoff,
+ .vidioc_cropcap = s5p_tv_v4l2_cropcap,
+ .vidioc_g_crop = s5p_tv_v4l2_g_crop,
+ .vidioc_s_crop = s5p_tv_v4l2_s_crop,
+ .vidioc_g_parm = s5p_tv_v4l2_g_parm_vo,
+ .vidioc_s_parm = s5p_tv_v4l2_s_parm_vo,
+};
+
« no previous file with comments | « drivers/media/video/samsung/tv20/s5p_tv_base.c ('k') | drivers/media/video/samsung/tv20/sdout_s5pv210.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698