V4L/DVB (8940): saa7115: fix saa7111(a) support

The saa7111 support in saa7115.c was missing some features and did not
properly take some of the differences into account. With this patch
saa7115 can be used in the mxb driver instead of saa7111.c.

Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c
index ad733ca..4ed7d65 100644
--- a/drivers/media/video/saa7115.c
+++ b/drivers/media/video/saa7115.c
@@ -1309,10 +1309,13 @@
 	case VIDIOC_INT_S_VIDEO_ROUTING:
 	{
 		struct v4l2_routing *route = arg;
+		u32 input = route->input;
+		u8 mask = (state->ident == V4L2_IDENT_SAA7111) ? 0xf8 : 0xf0;
 
 		v4l_dbg(1, debug, client, "decoder set input %d output %d\n", route->input, route->output);
-		/* saa7113 does not have these inputs */
-		if (state->ident == V4L2_IDENT_SAA7113 &&
+		/* saa7111/3 does not have these inputs */
+		if ((state->ident == V4L2_IDENT_SAA7113 ||
+		     state->ident == V4L2_IDENT_SAA7111) &&
 		    (route->input == SAA7115_COMPOSITE4 ||
 		     route->input == SAA7115_COMPOSITE5)) {
 			return -EINVAL;
@@ -1327,10 +1330,23 @@
 			(route->input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite", (route->output == SAA7115_IPORT_ON) ? "iport on" : "iport off");
 		state->input = route->input;
 
+		/* saa7111 has slightly different input numbering */
+		if (state->ident == V4L2_IDENT_SAA7111) {
+			if (input >= SAA7115_COMPOSITE4)
+				input -= 2;
+			/* saa7111 specific */
+			saa711x_write(client, R_10_CHROMA_CNTL_2,
+					(saa711x_read(client, R_10_CHROMA_CNTL_2) & 0x3f) |
+					((route->output & 0xc0) ^ 0x40));
+			saa711x_write(client, R_13_RT_X_PORT_OUT_CNTL,
+					(saa711x_read(client, R_13_RT_X_PORT_OUT_CNTL) & 0xf0) |
+					((route->output & 2) ? 0x0a : 0));
+		}
+
 		/* select mode */
 		saa711x_write(client, R_02_INPUT_CNTL_1,
-			      (saa711x_read(client, R_02_INPUT_CNTL_1) & 0xf0) |
-			       state->input);
+			      (saa711x_read(client, R_02_INPUT_CNTL_1) & mask) |
+			       input);
 
 		/* bypass chrominance trap for S-Video modes */
 		saa711x_write(client, R_09_LUMA_CNTL,
@@ -1384,6 +1400,13 @@
 		saa711x_writeregs(client, saa7115_cfg_reset_scaler);
 		break;
 
+	case VIDIOC_INT_S_GPIO:
+		if (state->ident != V4L2_IDENT_SAA7111)
+			return -EINVAL;
+		saa711x_write(client, 0x11, (saa711x_read(client, 0x11) & 0x7f) |
+			(*(u32 *)arg ? 0x80 : 0));
+		break;
+
 	case VIDIOC_INT_G_VBI_DATA:
 	{
 		struct v4l2_sliced_vbi_data *data = arg;
@@ -1539,7 +1562,8 @@
 		state->crystal_freq = SAA7115_FREQ_32_11_MHZ;
 		saa711x_writeregs(client, saa7115_init_auto_input);
 	}
-	saa711x_writeregs(client, saa7115_init_misc);
+	if (state->ident != V4L2_IDENT_SAA7111)
+		saa711x_writeregs(client, saa7115_init_misc);
 	saa711x_set_v4lstd(client, V4L2_STD_NTSC);
 
 	v4l_dbg(1, debug, client, "status: (1E) 0x%02x, (1F) 0x%02x\n",
diff --git a/include/media/saa7115.h b/include/media/saa7115.h
index f677dfb..bab2127 100644
--- a/include/media/saa7115.h
+++ b/include/media/saa7115.h
@@ -1,5 +1,5 @@
 /*
-    saa7115.h - definition for saa7113/4/5 inputs and frequency flags
+    saa7115.h - definition for saa7111/3/4/5 inputs and frequency flags
 
     Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl)
 
@@ -21,13 +21,13 @@
 #ifndef _SAA7115_H_
 #define _SAA7115_H_
 
-/* SAA7113/4/5 HW inputs */
+/* SAA7111/3/4/5 HW inputs */
 #define SAA7115_COMPOSITE0 0
 #define SAA7115_COMPOSITE1 1
 #define SAA7115_COMPOSITE2 2
 #define SAA7115_COMPOSITE3 3
-#define SAA7115_COMPOSITE4 4 /* not available for the saa7113 */
-#define SAA7115_COMPOSITE5 5 /* not available for the saa7113 */
+#define SAA7115_COMPOSITE4 4 /* not available for the saa7111/3 */
+#define SAA7115_COMPOSITE5 5 /* not available for the saa7111/3 */
 #define SAA7115_SVIDEO0    6
 #define SAA7115_SVIDEO1    7
 #define SAA7115_SVIDEO2    8
@@ -42,8 +42,15 @@
 #define SAA7115_FREQ_FL_CGCDIV (1 << 1)	   /* SA 3A[6], CGCDIV, SAA7115 only */
 #define SAA7115_FREQ_FL_APLL   (1 << 2)	   /* SA 3A[3], APLL, SAA7114/5 only */
 
-#define SAA7115_IPORT_ON    1
-#define SAA7115_IPORT_OFF   0
+#define SAA7115_IPORT_ON    	1
+#define SAA7115_IPORT_OFF   	0
+
+/* SAA7111 specific output flags */
+#define SAA7111_VBI_BYPASS 	2
+#define SAA7111_FMT_YUV422      0x00
+#define SAA7111_FMT_RGB 	0x40
+#define SAA7111_FMT_CCIR 	0x80
+#define SAA7111_FMT_YUV411 	0xc0
 
 #endif
 
diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h
index 0c195cc..2f8719a 100644
--- a/include/media/v4l2-common.h
+++ b/include/media/v4l2-common.h
@@ -225,18 +225,22 @@
    An extra flags field allows device specific configuration regarding
    clock frequency dividers, etc. If not used, then set flags to 0.
    If the frequency is not supported, then -EINVAL is returned. */
-#define VIDIOC_INT_S_CRYSTAL_FREQ 	_IOW ('d', 113, struct v4l2_crystal_freq)
+#define VIDIOC_INT_S_CRYSTAL_FREQ 	_IOW('d', 113, struct v4l2_crystal_freq)
 
 /* Initialize the sensor registors to some sort of reasonable
    default values. */
-#define VIDIOC_INT_INIT			_IOW ('d', 114, u32)
+#define VIDIOC_INT_INIT			_IOW('d', 114, u32)
 
 /* Set v4l2_std_id for video OUTPUT devices. This is ignored by
    video input devices. */
-#define VIDIOC_INT_S_STD_OUTPUT		_IOW  ('d', 115, v4l2_std_id)
+#define VIDIOC_INT_S_STD_OUTPUT		_IOW('d', 115, v4l2_std_id)
 
 /* Get v4l2_std_id for video OUTPUT devices. This is ignored by
    video input devices. */
-#define VIDIOC_INT_G_STD_OUTPUT		_IOW  ('d', 116, v4l2_std_id)
+#define VIDIOC_INT_G_STD_OUTPUT		_IOW('d', 116, v4l2_std_id)
+
+/* Set GPIO pins. Very simple right now, might need to be extended with
+   a v4l2_gpio struct if a direction is also needed. */
+#define VIDIOC_INT_S_GPIO		_IOW('d', 117, u32)
 
 #endif /* V4L2_COMMON_H_ */