V4L/DVB (5163): Add checks for CAP_SYS_ADMIN to VIDIOC_DBG_G_REGISTER
[pandora-kernel.git] / drivers / media / video / saa7115.c
index f28398d..7177721 100644 (file)
@@ -71,6 +71,7 @@ I2C_CLIENT_INSMOD;
 struct saa711x_state {
        v4l2_std_id std;
        int input;
+       int output;
        int enable;
        int radio;
        int bright;
@@ -851,7 +852,7 @@ static int saa711x_set_size(struct i2c_client *client, int width, int height)
 
        /* On 60Hz, it is using a higher Vertical Output Size */
        if (!is_50hz)
-               res+=(VRES_60HZ-480)>>1;
+               res += (VRES_60HZ - 480) >> 1;
 
                /* height */
        saa711x_write(client, R_CE_B_VERT_OUTPUT_WINDOW_LENGTH,
@@ -907,7 +908,7 @@ static int saa711x_set_size(struct i2c_client *client, int width, int height)
 
        /* Activates task "B" */
        saa711x_write(client, R_80_GLOBAL_CNTL_1,
-                               saa711x_read(client,R_80_GLOBAL_CNTL_1)|0x20);
+                               saa711x_read(client,R_80_GLOBAL_CNTL_1) | 0x20);
 
        return 0;
 }
@@ -932,11 +933,11 @@ static void saa711x_set_v4lstd(struct i2c_client *client, v4l2_std_id std)
        if (std & V4L2_STD_525_60) {
                v4l_dbg(1, debug, client, "decoder set standard 60 Hz\n");
                saa711x_writeregs(client, saa7115_cfg_60hz_video);
-               saa711x_set_size(client,720,480);
+               saa711x_set_size(client, 720, 480);
        } else {
                v4l_dbg(1, debug, client, "decoder set standard 50 Hz\n");
                saa711x_writeregs(client, saa7115_cfg_50hz_video);
-               saa711x_set_size(client,720,576);
+               saa711x_set_size(client, 720, 576);
        }
 
        /* Register 0E - Bits D6-D4 on NO-AUTO mode
@@ -1301,7 +1302,7 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar
                struct v4l2_routing *route = arg;
 
                route->input = state->input;
-               route->output = 0;
+               route->output = state->output;
                break;
        }
 
@@ -1309,7 +1310,7 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar
        {
                struct v4l2_routing *route = arg;
 
-               v4l_dbg(1, debug, client, "decoder set input %d\n", route->input);
+               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 &&
                    (route->input == SAA7115_COMPOSITE4 ||
@@ -1318,10 +1319,12 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar
                }
                if (route->input > SAA7115_SVIDEO3)
                        return -EINVAL;
-               if (state->input == route->input)
+               if (route->output > SAA7115_IPORT_ON)
+                       return -EINVAL;
+               if (state->input == route->input && state->output == route->output)
                        break;
-               v4l_dbg(1, debug, client, "now setting %s input\n",
-                       (route->input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite");
+               v4l_dbg(1, debug, client, "now setting %s input %s output\n",
+                       (route->input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite", (route->output == SAA7115_IPORT_ON) ? "iport on" : "iport off");
                state->input = route->input;
 
                /* select mode */
@@ -1333,6 +1336,14 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar
                saa711x_write(client, R_09_LUMA_CNTL,
                              (saa711x_read(client, R_09_LUMA_CNTL) & 0x7f) |
                               (state->input >= SAA7115_SVIDEO0 ? 0x80 : 0x0));
+
+               state->output = route->output;
+               if (state->ident == V4L2_IDENT_SAA7114 ||
+                       state->ident == V4L2_IDENT_SAA7115) {
+                       saa711x_write(client, R_83_X_PORT_I_O_ENA_AND_OUT_CLK,
+                             (saa711x_read(client, R_83_X_PORT_I_O_ENA_AND_OUT_CLK) & 0xfe) |
+                              (state->output & 0x01));
+               }
                break;
        }
 
@@ -1406,17 +1417,8 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar
        }
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-       case VIDIOC_INT_G_REGISTER:
-       {
-               struct v4l2_register *reg = arg;
-
-               if (reg->i2c_id != I2C_DRIVERID_SAA711X)
-                       return -EINVAL;
-               reg->val = saa711x_read(client, reg->reg & 0xff);
-               break;
-       }
-
-       case VIDIOC_INT_S_REGISTER:
+       case VIDIOC_DBG_G_REGISTER:
+       case VIDIOC_DBG_S_REGISTER:
        {
                struct v4l2_register *reg = arg;
 
@@ -1424,7 +1426,10 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar
                        return -EINVAL;
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
-               saa711x_write(client, reg->reg & 0xff, reg->val & 0xff);
+               if (cmd == VIDIOC_DBG_G_REGISTER)
+                       reg->val = saa711x_read(client, reg->reg & 0xff);
+               else
+                       saa711x_write(client, reg->reg & 0xff, reg->val & 0xff);
                break;
        }
 #endif
@@ -1464,13 +1469,13 @@ static int saa711x_attach(struct i2c_adapter *adapter, int address, int kind)
        client->driver = &i2c_driver_saa711x;
        snprintf(client->name, sizeof(client->name) - 1, "saa7115");
 
-       for (i=0;i<0x0f;i++) {
+       for (i = 0; i < 0x0f; i++) {
                saa711x_write(client, 0, i);
-               name[i] = (saa711x_read(client, 0) &0x0f) +'0';
-               if (name[i]>'9')
-                       name[i]+='a'-'9'-1;
+               name[i] = (saa711x_read(client, 0) & 0x0f) + '0';
+               if (name[i] > '9')
+                       name[i] += 'a' - '9' - 1;
        }
-       name[i]='\0';
+       name[i] = '\0';
 
        saa711x_write(client, 0, 5);
        chip_id = saa711x_read(client, 0) & 0x0f;
@@ -1492,6 +1497,7 @@ static int saa711x_attach(struct i2c_adapter *adapter, int address, int kind)
                return -ENOMEM;
        }
        state->input = -1;
+       state->output = SAA7115_IPORT_ON;
        state->enable = 1;
        state->radio = 0;
        state->bright = 128;
@@ -1550,7 +1556,7 @@ static int saa711x_attach(struct i2c_adapter *adapter, int address, int kind)
 
 static int saa711x_probe(struct i2c_adapter *adapter)
 {
-       if (adapter->class & I2C_CLASS_TV_ANALOG)
+       if (adapter->class & I2C_CLASS_TV_ANALOG || adapter->class & I2C_CLASS_TV_DIGITAL)
                return i2c_probe(adapter, &addr_data, &saa711x_attach);
        return 0;
 }