diff options
Diffstat (limited to 'drivers/media/video/saa7115.c')
-rw-r--r-- | drivers/media/video/saa7115.c | 57 |
1 files changed, 33 insertions, 24 deletions
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index c2374ed7ba9f..c4f066d6668e 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c | |||
@@ -71,6 +71,7 @@ I2C_CLIENT_INSMOD; | |||
71 | struct saa711x_state { | 71 | struct saa711x_state { |
72 | v4l2_std_id std; | 72 | v4l2_std_id std; |
73 | int input; | 73 | int input; |
74 | int output; | ||
74 | int enable; | 75 | int enable; |
75 | int radio; | 76 | int radio; |
76 | int bright; | 77 | int bright; |
@@ -1301,7 +1302,7 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar | |||
1301 | struct v4l2_routing *route = arg; | 1302 | struct v4l2_routing *route = arg; |
1302 | 1303 | ||
1303 | route->input = state->input; | 1304 | route->input = state->input; |
1304 | route->output = 0; | 1305 | route->output = state->output; |
1305 | break; | 1306 | break; |
1306 | } | 1307 | } |
1307 | 1308 | ||
@@ -1309,7 +1310,7 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar | |||
1309 | { | 1310 | { |
1310 | struct v4l2_routing *route = arg; | 1311 | struct v4l2_routing *route = arg; |
1311 | 1312 | ||
1312 | v4l_dbg(1, debug, client, "decoder set input %d\n", route->input); | 1313 | v4l_dbg(1, debug, client, "decoder set input %d output %d\n", route->input, route->output); |
1313 | /* saa7113 does not have these inputs */ | 1314 | /* saa7113 does not have these inputs */ |
1314 | if (state->ident == V4L2_IDENT_SAA7113 && | 1315 | if (state->ident == V4L2_IDENT_SAA7113 && |
1315 | (route->input == SAA7115_COMPOSITE4 || | 1316 | (route->input == SAA7115_COMPOSITE4 || |
@@ -1318,10 +1319,12 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar | |||
1318 | } | 1319 | } |
1319 | if (route->input > SAA7115_SVIDEO3) | 1320 | if (route->input > SAA7115_SVIDEO3) |
1320 | return -EINVAL; | 1321 | return -EINVAL; |
1321 | if (state->input == route->input) | 1322 | if (route->output > SAA7115_IPORT_ON) |
1323 | return -EINVAL; | ||
1324 | if (state->input == route->input && state->output == route->output) | ||
1322 | break; | 1325 | break; |
1323 | v4l_dbg(1, debug, client, "now setting %s input\n", | 1326 | v4l_dbg(1, debug, client, "now setting %s input %s output\n", |
1324 | (route->input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite"); | 1327 | (route->input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite", (route->output == SAA7115_IPORT_ON) ? "iport on" : "iport off"); |
1325 | state->input = route->input; | 1328 | state->input = route->input; |
1326 | 1329 | ||
1327 | /* select mode */ | 1330 | /* select mode */ |
@@ -1333,6 +1336,14 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar | |||
1333 | saa711x_write(client, R_09_LUMA_CNTL, | 1336 | saa711x_write(client, R_09_LUMA_CNTL, |
1334 | (saa711x_read(client, R_09_LUMA_CNTL) & 0x7f) | | 1337 | (saa711x_read(client, R_09_LUMA_CNTL) & 0x7f) | |
1335 | (state->input >= SAA7115_SVIDEO0 ? 0x80 : 0x0)); | 1338 | (state->input >= SAA7115_SVIDEO0 ? 0x80 : 0x0)); |
1339 | |||
1340 | state->output = route->output; | ||
1341 | if (state->ident == V4L2_IDENT_SAA7114 || | ||
1342 | state->ident == V4L2_IDENT_SAA7115) { | ||
1343 | saa711x_write(client, R_83_X_PORT_I_O_ENA_AND_OUT_CLK, | ||
1344 | (saa711x_read(client, R_83_X_PORT_I_O_ENA_AND_OUT_CLK) & 0xfe) | | ||
1345 | (state->output & 0x01)); | ||
1346 | } | ||
1336 | break; | 1347 | break; |
1337 | } | 1348 | } |
1338 | 1349 | ||
@@ -1377,6 +1388,9 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar | |||
1377 | { | 1388 | { |
1378 | struct v4l2_sliced_vbi_data *data = arg; | 1389 | struct v4l2_sliced_vbi_data *data = arg; |
1379 | 1390 | ||
1391 | /* Note: the internal field ID is inverted for NTSC, | ||
1392 | so data->field 0 maps to the saa7115 even field, | ||
1393 | whereas for PAL it maps to the saa7115 odd field. */ | ||
1380 | switch (data->id) { | 1394 | switch (data->id) { |
1381 | case V4L2_SLICED_WSS_625: | 1395 | case V4L2_SLICED_WSS_625: |
1382 | if (saa711x_read(client, 0x6b) & 0xc0) | 1396 | if (saa711x_read(client, 0x6b) & 0xc0) |
@@ -1387,17 +1401,17 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar | |||
1387 | case V4L2_SLICED_CAPTION_525: | 1401 | case V4L2_SLICED_CAPTION_525: |
1388 | if (data->field == 0) { | 1402 | if (data->field == 0) { |
1389 | /* CC */ | 1403 | /* CC */ |
1390 | if (saa711x_read(client, 0x66) & 0xc0) | 1404 | if (saa711x_read(client, 0x66) & 0x30) |
1391 | return -EIO; | 1405 | return -EIO; |
1392 | data->data[0] = saa711x_read(client, 0x67); | 1406 | data->data[0] = saa711x_read(client, 0x69); |
1393 | data->data[1] = saa711x_read(client, 0x68); | 1407 | data->data[1] = saa711x_read(client, 0x6a); |
1394 | return 0; | 1408 | return 0; |
1395 | } | 1409 | } |
1396 | /* XDS */ | 1410 | /* XDS */ |
1397 | if (saa711x_read(client, 0x66) & 0x30) | 1411 | if (saa711x_read(client, 0x66) & 0xc0) |
1398 | return -EIO; | 1412 | return -EIO; |
1399 | data->data[0] = saa711x_read(client, 0x69); | 1413 | data->data[0] = saa711x_read(client, 0x67); |
1400 | data->data[1] = saa711x_read(client, 0x6a); | 1414 | data->data[1] = saa711x_read(client, 0x68); |
1401 | return 0; | 1415 | return 0; |
1402 | default: | 1416 | default: |
1403 | return -EINVAL; | 1417 | return -EINVAL; |
@@ -1406,17 +1420,8 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar | |||
1406 | } | 1420 | } |
1407 | 1421 | ||
1408 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 1422 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
1409 | case VIDIOC_INT_G_REGISTER: | 1423 | case VIDIOC_DBG_G_REGISTER: |
1410 | { | 1424 | case VIDIOC_DBG_S_REGISTER: |
1411 | struct v4l2_register *reg = arg; | ||
1412 | |||
1413 | if (reg->i2c_id != I2C_DRIVERID_SAA711X) | ||
1414 | return -EINVAL; | ||
1415 | reg->val = saa711x_read(client, reg->reg & 0xff); | ||
1416 | break; | ||
1417 | } | ||
1418 | |||
1419 | case VIDIOC_INT_S_REGISTER: | ||
1420 | { | 1425 | { |
1421 | struct v4l2_register *reg = arg; | 1426 | struct v4l2_register *reg = arg; |
1422 | 1427 | ||
@@ -1424,7 +1429,10 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar | |||
1424 | return -EINVAL; | 1429 | return -EINVAL; |
1425 | if (!capable(CAP_SYS_ADMIN)) | 1430 | if (!capable(CAP_SYS_ADMIN)) |
1426 | return -EPERM; | 1431 | return -EPERM; |
1427 | saa711x_write(client, reg->reg & 0xff, reg->val & 0xff); | 1432 | if (cmd == VIDIOC_DBG_G_REGISTER) |
1433 | reg->val = saa711x_read(client, reg->reg & 0xff); | ||
1434 | else | ||
1435 | saa711x_write(client, reg->reg & 0xff, reg->val & 0xff); | ||
1428 | break; | 1436 | break; |
1429 | } | 1437 | } |
1430 | #endif | 1438 | #endif |
@@ -1492,6 +1500,7 @@ static int saa711x_attach(struct i2c_adapter *adapter, int address, int kind) | |||
1492 | return -ENOMEM; | 1500 | return -ENOMEM; |
1493 | } | 1501 | } |
1494 | state->input = -1; | 1502 | state->input = -1; |
1503 | state->output = SAA7115_IPORT_ON; | ||
1495 | state->enable = 1; | 1504 | state->enable = 1; |
1496 | state->radio = 0; | 1505 | state->radio = 0; |
1497 | state->bright = 128; | 1506 | state->bright = 128; |
@@ -1550,7 +1559,7 @@ static int saa711x_attach(struct i2c_adapter *adapter, int address, int kind) | |||
1550 | 1559 | ||
1551 | static int saa711x_probe(struct i2c_adapter *adapter) | 1560 | static int saa711x_probe(struct i2c_adapter *adapter) |
1552 | { | 1561 | { |
1553 | if (adapter->class & I2C_CLASS_TV_ANALOG) | 1562 | if (adapter->class & I2C_CLASS_TV_ANALOG || adapter->class & I2C_CLASS_TV_DIGITAL) |
1554 | return i2c_probe(adapter, &addr_data, &saa711x_attach); | 1563 | return i2c_probe(adapter, &addr_data, &saa711x_attach); |
1555 | return 0; | 1564 | return 0; |
1556 | } | 1565 | } |