diff options
Diffstat (limited to 'drivers/media/video/cx23885/cx23885-video.c')
-rw-r--r-- | drivers/media/video/cx23885/cx23885-video.c | 175 |
1 files changed, 148 insertions, 27 deletions
diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c index e730b9263016..4bbf9bb97bde 100644 --- a/drivers/media/video/cx23885/cx23885-video.c +++ b/drivers/media/video/cx23885/cx23885-video.c | |||
@@ -253,9 +253,9 @@ static struct cx23885_ctrl cx23885_ctls[] = { | |||
253 | .id = V4L2_CID_AUDIO_VOLUME, | 253 | .id = V4L2_CID_AUDIO_VOLUME, |
254 | .name = "Volume", | 254 | .name = "Volume", |
255 | .minimum = 0, | 255 | .minimum = 0, |
256 | .maximum = 0x3f, | 256 | .maximum = 65535, |
257 | .step = 1, | 257 | .step = 65535 / 100, |
258 | .default_value = 0x3f, | 258 | .default_value = 65535, |
259 | .type = V4L2_CTRL_TYPE_INTEGER, | 259 | .type = V4L2_CTRL_TYPE_INTEGER, |
260 | }, | 260 | }, |
261 | .reg = PATH1_VOL_CTL, | 261 | .reg = PATH1_VOL_CTL, |
@@ -316,7 +316,7 @@ void cx23885_video_wakeup(struct cx23885_dev *dev, | |||
316 | __func__, bc); | 316 | __func__, bc); |
317 | } | 317 | } |
318 | 318 | ||
319 | static int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm) | 319 | int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm) |
320 | { | 320 | { |
321 | dprintk(1, "%s(norm = 0x%08x) name: [%s]\n", | 321 | dprintk(1, "%s(norm = 0x%08x) name: [%s]\n", |
322 | __func__, | 322 | __func__, |
@@ -344,8 +344,8 @@ static struct video_device *cx23885_vdev_init(struct cx23885_dev *dev, | |||
344 | *vfd = *template; | 344 | *vfd = *template; |
345 | vfd->v4l2_dev = &dev->v4l2_dev; | 345 | vfd->v4l2_dev = &dev->v4l2_dev; |
346 | vfd->release = video_device_release; | 346 | vfd->release = video_device_release; |
347 | snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", | 347 | snprintf(vfd->name, sizeof(vfd->name), "%s (%s)", |
348 | dev->name, type, cx23885_boards[dev->board].name); | 348 | cx23885_boards[dev->board].name, type); |
349 | video_set_drvdata(vfd, dev); | 349 | video_set_drvdata(vfd, dev); |
350 | return vfd; | 350 | return vfd; |
351 | } | 351 | } |
@@ -492,7 +492,8 @@ static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input) | |||
492 | dev->input = input; | 492 | dev->input = input; |
493 | 493 | ||
494 | if (dev->board == CX23885_BOARD_MYGICA_X8506 || | 494 | if (dev->board == CX23885_BOARD_MYGICA_X8506 || |
495 | dev->board == CX23885_BOARD_MAGICPRO_PROHDTVE2) { | 495 | dev->board == CX23885_BOARD_MAGICPRO_PROHDTVE2 || |
496 | dev->board == CX23885_BOARD_MYGICA_X8507) { | ||
496 | /* Select Analog TV */ | 497 | /* Select Analog TV */ |
497 | if (INPUT(input)->type == CX23885_VMUX_TELEVISION) | 498 | if (INPUT(input)->type == CX23885_VMUX_TELEVISION) |
498 | cx23885_gpio_clear(dev, GPIO_0); | 499 | cx23885_gpio_clear(dev, GPIO_0); |
@@ -503,7 +504,8 @@ static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input) | |||
503 | INPUT(input)->vmux, 0, 0); | 504 | INPUT(input)->vmux, 0, 0); |
504 | 505 | ||
505 | if ((dev->board == CX23885_BOARD_HAUPPAUGE_HVR1800) || | 506 | if ((dev->board == CX23885_BOARD_HAUPPAUGE_HVR1800) || |
506 | (dev->board == CX23885_BOARD_MPX885)) { | 507 | (dev->board == CX23885_BOARD_MPX885) || |
508 | (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1850)) { | ||
507 | /* Configure audio routing */ | 509 | /* Configure audio routing */ |
508 | v4l2_subdev_call(dev->sd_cx25840, audio, s_routing, | 510 | v4l2_subdev_call(dev->sd_cx25840, audio, s_routing, |
509 | INPUT(input)->amux, 0, 0); | 511 | INPUT(input)->amux, 0, 0); |
@@ -649,6 +651,7 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | |||
649 | int rc, init_buffer = 0; | 651 | int rc, init_buffer = 0; |
650 | u32 line0_offset, line1_offset; | 652 | u32 line0_offset, line1_offset; |
651 | struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb); | 653 | struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb); |
654 | int field_tff; | ||
652 | 655 | ||
653 | BUG_ON(NULL == fh->fmt); | 656 | BUG_ON(NULL == fh->fmt); |
654 | if (fh->width < 48 || fh->width > norm_maxw(dev->tvnorm) || | 657 | if (fh->width < 48 || fh->width > norm_maxw(dev->tvnorm) || |
@@ -690,15 +693,25 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | |||
690 | buf->bpl, 0, buf->vb.height); | 693 | buf->bpl, 0, buf->vb.height); |
691 | break; | 694 | break; |
692 | case V4L2_FIELD_INTERLACED: | 695 | case V4L2_FIELD_INTERLACED: |
693 | if (dev->tvnorm & V4L2_STD_NTSC) { | 696 | if (dev->tvnorm & V4L2_STD_NTSC) |
697 | /* NTSC or */ | ||
698 | field_tff = 1; | ||
699 | else | ||
700 | field_tff = 0; | ||
701 | |||
702 | if (cx23885_boards[dev->board].force_bff) | ||
703 | /* PAL / SECAM OR 888 in NTSC MODE */ | ||
704 | field_tff = 0; | ||
705 | |||
706 | if (field_tff) { | ||
694 | /* cx25840 transmits NTSC bottom field first */ | 707 | /* cx25840 transmits NTSC bottom field first */ |
695 | dprintk(1, "%s() Creating NTSC risc\n", | 708 | dprintk(1, "%s() Creating TFF/NTSC risc\n", |
696 | __func__); | 709 | __func__); |
697 | line0_offset = buf->bpl; | 710 | line0_offset = buf->bpl; |
698 | line1_offset = 0; | 711 | line1_offset = 0; |
699 | } else { | 712 | } else { |
700 | /* All other formats are top field first */ | 713 | /* All other formats are top field first */ |
701 | dprintk(1, "%s() Creating PAL/SECAM risc\n", | 714 | dprintk(1, "%s() Creating BFF/PAL/SECAM risc\n", |
702 | __func__); | 715 | __func__); |
703 | line0_offset = 0; | 716 | line0_offset = 0; |
704 | line1_offset = buf->bpl; | 717 | line1_offset = buf->bpl; |
@@ -981,6 +994,8 @@ static int video_release(struct file *file) | |||
981 | } | 994 | } |
982 | 995 | ||
983 | videobuf_mmap_free(&fh->vidq); | 996 | videobuf_mmap_free(&fh->vidq); |
997 | videobuf_mmap_free(&fh->vbiq); | ||
998 | |||
984 | file->private_data = NULL; | 999 | file->private_data = NULL; |
985 | kfree(fh); | 1000 | kfree(fh); |
986 | 1001 | ||
@@ -1002,7 +1017,7 @@ static int video_mmap(struct file *file, struct vm_area_struct *vma) | |||
1002 | /* ------------------------------------------------------------------ */ | 1017 | /* ------------------------------------------------------------------ */ |
1003 | /* VIDEO CTRL IOCTLS */ | 1018 | /* VIDEO CTRL IOCTLS */ |
1004 | 1019 | ||
1005 | static int cx23885_get_control(struct cx23885_dev *dev, | 1020 | int cx23885_get_control(struct cx23885_dev *dev, |
1006 | struct v4l2_control *ctl) | 1021 | struct v4l2_control *ctl) |
1007 | { | 1022 | { |
1008 | dprintk(1, "%s() calling cx25840(VIDIOC_G_CTRL)\n", __func__); | 1023 | dprintk(1, "%s() calling cx25840(VIDIOC_G_CTRL)\n", __func__); |
@@ -1010,7 +1025,7 @@ static int cx23885_get_control(struct cx23885_dev *dev, | |||
1010 | return 0; | 1025 | return 0; |
1011 | } | 1026 | } |
1012 | 1027 | ||
1013 | static int cx23885_set_control(struct cx23885_dev *dev, | 1028 | int cx23885_set_control(struct cx23885_dev *dev, |
1014 | struct v4l2_control *ctl) | 1029 | struct v4l2_control *ctl) |
1015 | { | 1030 | { |
1016 | dprintk(1, "%s() calling cx25840(VIDIOC_S_CTRL)\n", __func__); | 1031 | dprintk(1, "%s() calling cx25840(VIDIOC_S_CTRL)\n", __func__); |
@@ -1229,6 +1244,16 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | |||
1229 | return 0; | 1244 | return 0; |
1230 | } | 1245 | } |
1231 | 1246 | ||
1247 | static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id) | ||
1248 | { | ||
1249 | struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; | ||
1250 | dprintk(1, "%s()\n", __func__); | ||
1251 | |||
1252 | call_all(dev, core, g_std, id); | ||
1253 | |||
1254 | return 0; | ||
1255 | } | ||
1256 | |||
1232 | static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *tvnorms) | 1257 | static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *tvnorms) |
1233 | { | 1258 | { |
1234 | struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; | 1259 | struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; |
@@ -1241,7 +1266,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *tvnorms) | |||
1241 | return 0; | 1266 | return 0; |
1242 | } | 1267 | } |
1243 | 1268 | ||
1244 | static int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i) | 1269 | int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i) |
1245 | { | 1270 | { |
1246 | static const char *iname[] = { | 1271 | static const char *iname[] = { |
1247 | [CX23885_VMUX_COMPOSITE1] = "Composite1", | 1272 | [CX23885_VMUX_COMPOSITE1] = "Composite1", |
@@ -1278,6 +1303,15 @@ static int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i) | |||
1278 | if (INPUT(n)->type != CX23885_VMUX_TELEVISION) | 1303 | if (INPUT(n)->type != CX23885_VMUX_TELEVISION) |
1279 | i->audioset = 0x3; | 1304 | i->audioset = 0x3; |
1280 | 1305 | ||
1306 | if (dev->input == n) { | ||
1307 | /* enum'd input matches our configured input. | ||
1308 | * Ask the video decoder to process the call | ||
1309 | * and give it an oppertunity to update the | ||
1310 | * status field. | ||
1311 | */ | ||
1312 | call_all(dev, video, g_input_status, &i->status); | ||
1313 | } | ||
1314 | |||
1281 | return 0; | 1315 | return 0; |
1282 | } | 1316 | } |
1283 | 1317 | ||
@@ -1289,7 +1323,7 @@ static int vidioc_enum_input(struct file *file, void *priv, | |||
1289 | return cx23885_enum_input(dev, i); | 1323 | return cx23885_enum_input(dev, i); |
1290 | } | 1324 | } |
1291 | 1325 | ||
1292 | static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) | 1326 | int cx23885_get_input(struct file *file, void *priv, unsigned int *i) |
1293 | { | 1327 | { |
1294 | struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; | 1328 | struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; |
1295 | 1329 | ||
@@ -1298,7 +1332,12 @@ static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) | |||
1298 | return 0; | 1332 | return 0; |
1299 | } | 1333 | } |
1300 | 1334 | ||
1301 | static int vidioc_s_input(struct file *file, void *priv, unsigned int i) | 1335 | static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) |
1336 | { | ||
1337 | return cx23885_get_input(file, priv, i); | ||
1338 | } | ||
1339 | |||
1340 | int cx23885_set_input(struct file *file, void *priv, unsigned int i) | ||
1302 | { | 1341 | { |
1303 | struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; | 1342 | struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; |
1304 | 1343 | ||
@@ -1322,6 +1361,11 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) | |||
1322 | return 0; | 1361 | return 0; |
1323 | } | 1362 | } |
1324 | 1363 | ||
1364 | static int vidioc_s_input(struct file *file, void *priv, unsigned int i) | ||
1365 | { | ||
1366 | return cx23885_set_input(file, priv, i); | ||
1367 | } | ||
1368 | |||
1325 | static int vidioc_log_status(struct file *file, void *priv) | 1369 | static int vidioc_log_status(struct file *file, void *priv) |
1326 | { | 1370 | { |
1327 | struct cx23885_fh *fh = priv; | 1371 | struct cx23885_fh *fh = priv; |
@@ -1329,11 +1373,11 @@ static int vidioc_log_status(struct file *file, void *priv) | |||
1329 | 1373 | ||
1330 | printk(KERN_INFO | 1374 | printk(KERN_INFO |
1331 | "%s/0: ============ START LOG STATUS ============\n", | 1375 | "%s/0: ============ START LOG STATUS ============\n", |
1332 | dev->name); | 1376 | dev->name); |
1333 | call_all(dev, core, log_status); | 1377 | call_all(dev, core, log_status); |
1334 | printk(KERN_INFO | 1378 | printk(KERN_INFO |
1335 | "%s/0: ============= END LOG STATUS =============\n", | 1379 | "%s/0: ============= END LOG STATUS =============\n", |
1336 | dev->name); | 1380 | dev->name); |
1337 | return 0; | 1381 | return 0; |
1338 | } | 1382 | } |
1339 | 1383 | ||
@@ -1471,6 +1515,8 @@ static int vidioc_g_frequency(struct file *file, void *priv, | |||
1471 | 1515 | ||
1472 | static int cx23885_set_freq(struct cx23885_dev *dev, struct v4l2_frequency *f) | 1516 | static int cx23885_set_freq(struct cx23885_dev *dev, struct v4l2_frequency *f) |
1473 | { | 1517 | { |
1518 | struct v4l2_control ctrl; | ||
1519 | |||
1474 | if (unlikely(UNSET == dev->tuner_type)) | 1520 | if (unlikely(UNSET == dev->tuner_type)) |
1475 | return -EINVAL; | 1521 | return -EINVAL; |
1476 | if (unlikely(f->tuner != 0)) | 1522 | if (unlikely(f->tuner != 0)) |
@@ -1479,29 +1525,102 @@ static int cx23885_set_freq(struct cx23885_dev *dev, struct v4l2_frequency *f) | |||
1479 | mutex_lock(&dev->lock); | 1525 | mutex_lock(&dev->lock); |
1480 | dev->freq = f->frequency; | 1526 | dev->freq = f->frequency; |
1481 | 1527 | ||
1528 | /* I need to mute audio here */ | ||
1529 | ctrl.id = V4L2_CID_AUDIO_MUTE; | ||
1530 | ctrl.value = 1; | ||
1531 | cx23885_set_control(dev, &ctrl); | ||
1532 | |||
1482 | call_all(dev, tuner, s_frequency, f); | 1533 | call_all(dev, tuner, s_frequency, f); |
1483 | 1534 | ||
1484 | /* When changing channels it is required to reset TVAUDIO */ | 1535 | /* When changing channels it is required to reset TVAUDIO */ |
1485 | msleep(10); | 1536 | msleep(100); |
1537 | |||
1538 | /* I need to unmute audio here */ | ||
1539 | ctrl.value = 0; | ||
1540 | cx23885_set_control(dev, &ctrl); | ||
1486 | 1541 | ||
1487 | mutex_unlock(&dev->lock); | 1542 | mutex_unlock(&dev->lock); |
1488 | 1543 | ||
1489 | return 0; | 1544 | return 0; |
1490 | } | 1545 | } |
1491 | 1546 | ||
1492 | static int vidioc_s_frequency(struct file *file, void *priv, | 1547 | static int cx23885_set_freq_via_ops(struct cx23885_dev *dev, |
1493 | struct v4l2_frequency *f) | 1548 | struct v4l2_frequency *f) |
1549 | { | ||
1550 | struct v4l2_control ctrl; | ||
1551 | struct videobuf_dvb_frontend *vfe; | ||
1552 | struct dvb_frontend *fe; | ||
1553 | int err = 0; | ||
1554 | |||
1555 | struct analog_parameters params = { | ||
1556 | .mode = V4L2_TUNER_ANALOG_TV, | ||
1557 | .audmode = V4L2_TUNER_MODE_STEREO, | ||
1558 | .std = dev->tvnorm, | ||
1559 | .frequency = f->frequency | ||
1560 | }; | ||
1561 | |||
1562 | mutex_lock(&dev->lock); | ||
1563 | dev->freq = f->frequency; | ||
1564 | |||
1565 | /* I need to mute audio here */ | ||
1566 | ctrl.id = V4L2_CID_AUDIO_MUTE; | ||
1567 | ctrl.value = 1; | ||
1568 | cx23885_set_control(dev, &ctrl); | ||
1569 | |||
1570 | /* If HVR1850 */ | ||
1571 | dprintk(1, "%s() frequency=%d tuner=%d std=0x%llx\n", __func__, | ||
1572 | params.frequency, f->tuner, params.std); | ||
1573 | |||
1574 | vfe = videobuf_dvb_get_frontend(&dev->ts2.frontends, 1); | ||
1575 | if (!vfe) | ||
1576 | err = -EINVAL; | ||
1577 | |||
1578 | fe = vfe->dvb.frontend; | ||
1579 | |||
1580 | if (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1850) | ||
1581 | fe = &dev->ts1.analog_fe; | ||
1582 | |||
1583 | if (fe && fe->ops.tuner_ops.set_analog_params) { | ||
1584 | call_all(dev, core, s_std, dev->tvnorm); | ||
1585 | fe->ops.tuner_ops.set_analog_params(fe, ¶ms); | ||
1586 | } | ||
1587 | else | ||
1588 | printk(KERN_ERR "%s() No analog tuner, aborting\n", __func__); | ||
1589 | |||
1590 | /* When changing channels it is required to reset TVAUDIO */ | ||
1591 | msleep(100); | ||
1592 | |||
1593 | /* I need to unmute audio here */ | ||
1594 | ctrl.value = 0; | ||
1595 | cx23885_set_control(dev, &ctrl); | ||
1596 | |||
1597 | mutex_unlock(&dev->lock); | ||
1598 | |||
1599 | return 0; | ||
1600 | } | ||
1601 | |||
1602 | int cx23885_set_frequency(struct file *file, void *priv, | ||
1603 | struct v4l2_frequency *f) | ||
1494 | { | 1604 | { |
1495 | struct cx23885_fh *fh = priv; | 1605 | struct cx23885_fh *fh = priv; |
1496 | struct cx23885_dev *dev = fh->dev; | 1606 | struct cx23885_dev *dev = fh->dev; |
1607 | int ret; | ||
1497 | 1608 | ||
1498 | if (unlikely(0 == fh->radio && f->type != V4L2_TUNER_ANALOG_TV)) | 1609 | switch (dev->board) { |
1499 | return -EINVAL; | 1610 | case CX23885_BOARD_HAUPPAUGE_HVR1850: |
1500 | if (unlikely(1 == fh->radio && f->type != V4L2_TUNER_RADIO)) | 1611 | ret = cx23885_set_freq_via_ops(dev, f); |
1501 | return -EINVAL; | 1612 | break; |
1613 | default: | ||
1614 | ret = cx23885_set_freq(dev, f); | ||
1615 | } | ||
1502 | 1616 | ||
1503 | return | 1617 | return ret; |
1504 | cx23885_set_freq(dev, f); | 1618 | } |
1619 | |||
1620 | static int vidioc_s_frequency(struct file *file, void *priv, | ||
1621 | struct v4l2_frequency *f) | ||
1622 | { | ||
1623 | return cx23885_set_frequency(file, priv, f); | ||
1505 | } | 1624 | } |
1506 | 1625 | ||
1507 | /* ----------------------------------------------------------- */ | 1626 | /* ----------------------------------------------------------- */ |
@@ -1613,6 +1732,8 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { | |||
1613 | .vidioc_qbuf = vidioc_qbuf, | 1732 | .vidioc_qbuf = vidioc_qbuf, |
1614 | .vidioc_dqbuf = vidioc_dqbuf, | 1733 | .vidioc_dqbuf = vidioc_dqbuf, |
1615 | .vidioc_s_std = vidioc_s_std, | 1734 | .vidioc_s_std = vidioc_s_std, |
1735 | .vidioc_g_std = vidioc_g_std, | ||
1736 | .vidioc_querystd = vidioc_g_std, | ||
1616 | .vidioc_enum_input = vidioc_enum_input, | 1737 | .vidioc_enum_input = vidioc_enum_input, |
1617 | .vidioc_g_input = vidioc_g_input, | 1738 | .vidioc_g_input = vidioc_g_input, |
1618 | .vidioc_s_input = vidioc_s_input, | 1739 | .vidioc_s_input = vidioc_s_input, |