V4L/DVB (5163): Add checks for CAP_SYS_ADMIN to VIDIOC_DBG_G_REGISTER
[pandora-kernel.git] / drivers / media / video / tvp5150.c
index dab4973..886b5df 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/delay.h>
 #include <linux/video_decoder.h>
 #include <media/v4l2-common.h>
+#include <media/tvp5150.h>
 
 #include "tvp5150_reg.h"
 
@@ -89,7 +90,7 @@ struct tvp5150 {
        struct i2c_client *client;
 
        v4l2_std_id norm;       /* Current set standard */
-       int input;
+       struct v4l2_routing route;
        int enable;
        int bright;
        int contrast;
@@ -283,33 +284,35 @@ static void dump_reg(struct i2c_client *c)
 /****************************************************************************
                        Basic functions
  ****************************************************************************/
-enum tvp5150_input {
-       TVP5150_ANALOG_CH0 = 0,
-       TVP5150_SVIDEO = 1,
-       TVP5150_ANALOG_CH1 = 2,
-       TVP5150_BLACK_SCREEN = 8
-};
 
-static inline void tvp5150_selmux(struct i2c_client *c,
-                                 enum tvp5150_input input)
+static inline void tvp5150_selmux(struct i2c_client *c)
 {
        int opmode=0;
-
        struct tvp5150 *decoder = i2c_get_clientdata(c);
+       int input = 0;
 
-       if (!decoder->enable)
-               input |= TVP5150_BLACK_SCREEN;
+       if ((decoder->route.output & TVP5150_BLACK_SCREEN) || !decoder->enable)
+               input = 8;
 
-       switch (input) {
-       case TVP5150_ANALOG_CH0:
-       case TVP5150_ANALOG_CH1:
+       switch (decoder->route.input) {
+       case TVP5150_COMPOSITE1:
+               input |= 2;
+               /* fall through */
+       case TVP5150_COMPOSITE0:
                opmode=0x30;            /* TV Mode */
                break;
+       case TVP5150_SVIDEO:
        default:
+               input |= 1;
                opmode=0;               /* Auto Mode */
                break;
        }
 
+       tvp5150_dbg( 1, "Selecting video route: route input=%i, output=%i "
+                       "=> tvp5150 input=%i, opmode=%i\n",
+                       decoder->route.input,decoder->route.output,
+                       input, opmode );
+
        tvp5150_write(c, TVP5150_OP_MODE_CTL, opmode);
        tvp5150_write(c, TVP5150_VD_IN_SRC_SEL_1, input);
 };
@@ -790,7 +793,7 @@ static inline void tvp5150_reset(struct i2c_client *c)
        tvp5150_vdp_init(c, vbi_ram_default);
 
        /* Selects decoder input */
-       tvp5150_selmux(c, decoder->input);
+       tvp5150_selmux(c);
 
        /* Initializes TVP5150 to stream enabled values */
        tvp5150_write_inittab(c, tvp5150_init_enable);
@@ -860,6 +863,21 @@ static int tvp5150_command(struct i2c_client *c,
        case VIDIOC_INT_RESET:
                tvp5150_reset(c);
                break;
+       case VIDIOC_INT_G_VIDEO_ROUTING:
+       {
+               struct v4l2_routing *route = arg;
+
+               *route = decoder->route;
+               break;
+       }
+       case VIDIOC_INT_S_VIDEO_ROUTING:
+       {
+               struct v4l2_routing *route = arg;
+
+               decoder->route = *route;
+               tvp5150_selmux(c);
+               break;
+       }
        case VIDIOC_S_STD:
                if (decoder->norm == *(v4l2_std_id *)arg)
                        break;
@@ -932,17 +950,8 @@ static int tvp5150_command(struct i2c_client *c,
        }
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-       case VIDIOC_INT_G_REGISTER:
-       {
-               struct v4l2_register *reg = arg;
-
-               if (reg->i2c_id != I2C_DRIVERID_TVP5150)
-                       return -EINVAL;
-               reg->val = tvp5150_read(c, reg->reg & 0xff);
-               break;
-       }
-
-       case VIDIOC_INT_S_REGISTER:
+       case VIDIOC_DBG_G_REGISTER:
+       case VIDIOC_DBG_S_REGISTER:
        {
                struct v4l2_register *reg = arg;
 
@@ -950,7 +959,10 @@ static int tvp5150_command(struct i2c_client *c,
                        return -EINVAL;
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
-               tvp5150_write(c, reg->reg & 0xff, reg->val & 0xff);
+               if (cmd == VIDIOC_DBG_G_REGISTER)
+                       reg->val = tvp5150_read(c, reg->reg & 0xff);
+               else
+                       tvp5150_write(c, reg->reg & 0xff, reg->val & 0xff);
                break;
        }
 #endif
@@ -1063,7 +1075,7 @@ static int tvp5150_detect_client(struct i2c_adapter *adapter,
        rv = i2c_attach_client(c);
 
        core->norm = V4L2_STD_ALL;      /* Default is autodetect */
-       core->input = 2;
+       core->route.input = TVP5150_COMPOSITE1;
        core->enable = 1;
        core->bright = 32768;
        core->contrast = 32768;