aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2012-09-11 06:35:30 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2013-02-05 15:30:12 -0500
commit2c2a053626cb712d6006cb10f2760a6018a65631 (patch)
tree60cd7384da0e95c26ab43d352ee4e155dbeb9f56 /drivers/media
parented986d1fee77bbbb62291a1db1c7edbb00d99515 (diff)
[media] tm6000: fix querycap and input/tuner compliance issues
- add device_caps support - fix bus_info - fix numerous tuner-related problems due to incorrect tests and setting v4l2_tuner fields to wrong values. - remove (audio) input support from the radio: it doesn't belong there. This also fixed a nasty issue where opening the radio would set dev->input to 5 for no good reason. This was never set back to a valid TV input after closing the radio device, thus leaving it at 5 which is out of bounds of the vinput card array. Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/usb/tm6000/tm6000-video.c147
1 files changed, 31 insertions, 116 deletions
diff --git a/drivers/media/usb/tm6000/tm6000-video.c b/drivers/media/usb/tm6000/tm6000-video.c
index e3c567c27918..7a653b263678 100644
--- a/drivers/media/usb/tm6000/tm6000-video.c
+++ b/drivers/media/usb/tm6000/tm6000-video.c
@@ -948,16 +948,21 @@ static int vidioc_querycap(struct file *file, void *priv,
948 struct v4l2_capability *cap) 948 struct v4l2_capability *cap)
949{ 949{
950 struct tm6000_core *dev = ((struct tm6000_fh *)priv)->dev; 950 struct tm6000_core *dev = ((struct tm6000_fh *)priv)->dev;
951 struct video_device *vdev = video_devdata(file);
951 952
952 strlcpy(cap->driver, "tm6000", sizeof(cap->driver)); 953 strlcpy(cap->driver, "tm6000", sizeof(cap->driver));
953 strlcpy(cap->card, "Trident TVMaster TM5600/6000/6010", sizeof(cap->card)); 954 strlcpy(cap->card, "Trident TVMaster TM5600/6000/6010", sizeof(cap->card));
954 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | 955 usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
955 V4L2_CAP_STREAMING |
956 V4L2_CAP_AUDIO |
957 V4L2_CAP_READWRITE;
958
959 if (dev->tuner_type != TUNER_ABSENT) 956 if (dev->tuner_type != TUNER_ABSENT)
960 cap->capabilities |= V4L2_CAP_TUNER; 957 cap->device_caps |= V4L2_CAP_TUNER;
958 if (vdev->vfl_type == VFL_TYPE_GRABBER)
959 cap->device_caps |= V4L2_CAP_VIDEO_CAPTURE |
960 V4L2_CAP_STREAMING |
961 V4L2_CAP_READWRITE;
962 else
963 cap->device_caps |= V4L2_CAP_RADIO;
964 cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS |
965 V4L2_CAP_RADIO | V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
961 966
962 return 0; 967 return 0;
963} 968}
@@ -965,7 +970,7 @@ static int vidioc_querycap(struct file *file, void *priv,
965static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, 970static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
966 struct v4l2_fmtdesc *f) 971 struct v4l2_fmtdesc *f)
967{ 972{
968 if (unlikely(f->index >= ARRAY_SIZE(format))) 973 if (f->index >= ARRAY_SIZE(format))
969 return -EINVAL; 974 return -EINVAL;
970 975
971 strlcpy(f->description, format[f->index].name, sizeof(f->description)); 976 strlcpy(f->description, format[f->index].name, sizeof(f->description));
@@ -1301,14 +1306,14 @@ static int vidioc_g_tuner(struct file *file, void *priv,
1301 struct tm6000_fh *fh = priv; 1306 struct tm6000_fh *fh = priv;
1302 struct tm6000_core *dev = fh->dev; 1307 struct tm6000_core *dev = fh->dev;
1303 1308
1304 if (unlikely(UNSET == dev->tuner_type)) 1309 if (UNSET == dev->tuner_type)
1305 return -EINVAL; 1310 return -ENOTTY;
1306 if (0 != t->index) 1311 if (0 != t->index)
1307 return -EINVAL; 1312 return -EINVAL;
1308 1313
1309 strcpy(t->name, "Television"); 1314 strcpy(t->name, "Television");
1310 t->type = V4L2_TUNER_ANALOG_TV; 1315 t->type = V4L2_TUNER_ANALOG_TV;
1311 t->capability = V4L2_TUNER_CAP_NORM; 1316 t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO;
1312 t->rangehigh = 0xffffffffUL; 1317 t->rangehigh = 0xffffffffUL;
1313 t->rxsubchans = V4L2_TUNER_SUB_STEREO; 1318 t->rxsubchans = V4L2_TUNER_SUB_STEREO;
1314 1319
@@ -1326,11 +1331,14 @@ static int vidioc_s_tuner(struct file *file, void *priv,
1326 struct tm6000_core *dev = fh->dev; 1331 struct tm6000_core *dev = fh->dev;
1327 1332
1328 if (UNSET == dev->tuner_type) 1333 if (UNSET == dev->tuner_type)
1329 return -EINVAL; 1334 return -ENOTTY;
1330 if (0 != t->index) 1335 if (0 != t->index)
1331 return -EINVAL; 1336 return -EINVAL;
1332 1337
1333 dev->amode = t->audmode; 1338 if (t->audmode > V4L2_TUNER_MODE_STEREO)
1339 dev->amode = V4L2_TUNER_MODE_STEREO;
1340 else
1341 dev->amode = t->audmode;
1334 dprintk(dev, 3, "audio mode: %x\n", t->audmode); 1342 dprintk(dev, 3, "audio mode: %x\n", t->audmode);
1335 1343
1336 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t); 1344 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
@@ -1344,10 +1352,11 @@ static int vidioc_g_frequency(struct file *file, void *priv,
1344 struct tm6000_fh *fh = priv; 1352 struct tm6000_fh *fh = priv;
1345 struct tm6000_core *dev = fh->dev; 1353 struct tm6000_core *dev = fh->dev;
1346 1354
1347 if (unlikely(UNSET == dev->tuner_type)) 1355 if (UNSET == dev->tuner_type)
1356 return -ENOTTY;
1357 if (f->tuner)
1348 return -EINVAL; 1358 return -EINVAL;
1349 1359
1350 f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
1351 f->frequency = dev->freq; 1360 f->frequency = dev->freq;
1352 1361
1353 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_frequency, f); 1362 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_frequency, f);
@@ -1361,13 +1370,9 @@ static int vidioc_s_frequency(struct file *file, void *priv,
1361 struct tm6000_fh *fh = priv; 1370 struct tm6000_fh *fh = priv;
1362 struct tm6000_core *dev = fh->dev; 1371 struct tm6000_core *dev = fh->dev;
1363 1372
1364 if (unlikely(UNSET == dev->tuner_type)) 1373 if (UNSET == dev->tuner_type)
1365 return -EINVAL; 1374 return -ENOTTY;
1366 if (unlikely(f->tuner != 0)) 1375 if (f->tuner != 0)
1367 return -EINVAL;
1368 if (0 == fh->radio && V4L2_TUNER_ANALOG_TV != f->type)
1369 return -EINVAL;
1370 if (1 == fh->radio && V4L2_TUNER_RADIO != f->type)
1371 return -EINVAL; 1376 return -EINVAL;
1372 1377
1373 dev->freq = f->frequency; 1378 dev->freq = f->frequency;
@@ -1376,27 +1381,6 @@ static int vidioc_s_frequency(struct file *file, void *priv,
1376 return 0; 1381 return 0;
1377} 1382}
1378 1383
1379static int radio_querycap(struct file *file, void *priv,
1380 struct v4l2_capability *cap)
1381{
1382 struct tm6000_fh *fh = file->private_data;
1383 struct tm6000_core *dev = fh->dev;
1384
1385 strcpy(cap->driver, "tm6000");
1386 strlcpy(cap->card, dev->name, sizeof(dev->name));
1387 sprintf(cap->bus_info, "USB%04x:%04x",
1388 le16_to_cpu(dev->udev->descriptor.idVendor),
1389 le16_to_cpu(dev->udev->descriptor.idProduct));
1390 cap->version = dev->dev_type;
1391 cap->capabilities = V4L2_CAP_TUNER |
1392 V4L2_CAP_AUDIO |
1393 V4L2_CAP_RADIO |
1394 V4L2_CAP_READWRITE |
1395 V4L2_CAP_STREAMING;
1396
1397 return 0;
1398}
1399
1400static int radio_g_tuner(struct file *file, void *priv, 1384static int radio_g_tuner(struct file *file, void *priv,
1401 struct v4l2_tuner *t) 1385 struct v4l2_tuner *t)
1402{ 1386{
@@ -1409,7 +1393,9 @@ static int radio_g_tuner(struct file *file, void *priv,
1409 memset(t, 0, sizeof(*t)); 1393 memset(t, 0, sizeof(*t));
1410 strcpy(t->name, "Radio"); 1394 strcpy(t->name, "Radio");
1411 t->type = V4L2_TUNER_RADIO; 1395 t->type = V4L2_TUNER_RADIO;
1396 t->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
1412 t->rxsubchans = V4L2_TUNER_SUB_STEREO; 1397 t->rxsubchans = V4L2_TUNER_SUB_STEREO;
1398 t->audmode = V4L2_TUNER_MODE_STEREO;
1413 1399
1414 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t); 1400 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
1415 1401
@@ -1424,78 +1410,14 @@ static int radio_s_tuner(struct file *file, void *priv,
1424 1410
1425 if (0 != t->index) 1411 if (0 != t->index)
1426 return -EINVAL; 1412 return -EINVAL;
1413 if (t->audmode > V4L2_TUNER_MODE_STEREO)
1414 t->audmode = V4L2_TUNER_MODE_STEREO;
1427 1415
1428 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t); 1416 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
1429 1417
1430 return 0; 1418 return 0;
1431} 1419}
1432 1420
1433static int radio_enum_input(struct file *file, void *priv,
1434 struct v4l2_input *i)
1435{
1436 struct tm6000_fh *fh = priv;
1437 struct tm6000_core *dev = fh->dev;
1438
1439 if (i->index != 0)
1440 return -EINVAL;
1441
1442 if (!dev->rinput.type)
1443 return -EINVAL;
1444
1445 strcpy(i->name, "Radio");
1446 i->type = V4L2_INPUT_TYPE_TUNER;
1447
1448 return 0;
1449}
1450
1451static int radio_g_input(struct file *filp, void *priv, unsigned int *i)
1452{
1453 struct tm6000_fh *fh = priv;
1454 struct tm6000_core *dev = fh->dev;
1455
1456 if (dev->input != 5)
1457 return -EINVAL;
1458
1459 *i = dev->input - 5;
1460
1461 return 0;
1462}
1463
1464static int radio_g_audio(struct file *file, void *priv,
1465 struct v4l2_audio *a)
1466{
1467 memset(a, 0, sizeof(*a));
1468 strcpy(a->name, "Radio");
1469 return 0;
1470}
1471
1472static int radio_s_audio(struct file *file, void *priv,
1473 const struct v4l2_audio *a)
1474{
1475 return 0;
1476}
1477
1478static int radio_s_input(struct file *filp, void *priv, unsigned int i)
1479{
1480 struct tm6000_fh *fh = priv;
1481 struct tm6000_core *dev = fh->dev;
1482
1483 if (i)
1484 return -EINVAL;
1485
1486 if (!dev->rinput.type)
1487 return -EINVAL;
1488
1489 dev->input = i + 5;
1490
1491 return 0;
1492}
1493
1494static int radio_s_std(struct file *file, void *fh, v4l2_std_id *norm)
1495{
1496 return 0;
1497}
1498
1499static int radio_queryctrl(struct file *file, void *priv, 1421static int radio_queryctrl(struct file *file, void *priv,
1500 struct v4l2_queryctrl *c) 1422 struct v4l2_queryctrl *c)
1501{ 1423{
@@ -1599,7 +1521,6 @@ static int __tm6000_open(struct file *file)
1599 sizeof(struct tm6000_buffer), fh, &dev->lock); 1521 sizeof(struct tm6000_buffer), fh, &dev->lock);
1600 } else { 1522 } else {
1601 dprintk(dev, V4L2_DEBUG_OPEN, "video_open: setting radio device\n"); 1523 dprintk(dev, V4L2_DEBUG_OPEN, "video_open: setting radio device\n");
1602 dev->input = 5;
1603 tm6000_set_audio_rinput(dev); 1524 tm6000_set_audio_rinput(dev);
1604 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_radio); 1525 v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_radio);
1605 tm6000_prepare_isoc(dev); 1526 tm6000_prepare_isoc(dev);
@@ -1789,16 +1710,10 @@ static const struct v4l2_file_operations radio_fops = {
1789}; 1710};
1790 1711
1791static const struct v4l2_ioctl_ops radio_ioctl_ops = { 1712static const struct v4l2_ioctl_ops radio_ioctl_ops = {
1792 .vidioc_querycap = radio_querycap, 1713 .vidioc_querycap = vidioc_querycap,
1793 .vidioc_g_tuner = radio_g_tuner, 1714 .vidioc_g_tuner = radio_g_tuner,
1794 .vidioc_enum_input = radio_enum_input,
1795 .vidioc_g_audio = radio_g_audio,
1796 .vidioc_s_tuner = radio_s_tuner, 1715 .vidioc_s_tuner = radio_s_tuner,
1797 .vidioc_s_audio = radio_s_audio,
1798 .vidioc_s_input = radio_s_input,
1799 .vidioc_s_std = radio_s_std,
1800 .vidioc_queryctrl = radio_queryctrl, 1716 .vidioc_queryctrl = radio_queryctrl,
1801 .vidioc_g_input = radio_g_input,
1802 .vidioc_g_ctrl = vidioc_g_ctrl, 1717 .vidioc_g_ctrl = vidioc_g_ctrl,
1803 .vidioc_s_ctrl = vidioc_s_ctrl, 1718 .vidioc_s_ctrl = vidioc_s_ctrl,
1804 .vidioc_g_frequency = vidioc_g_frequency, 1719 .vidioc_g_frequency = vidioc_g_frequency,