diff options
Diffstat (limited to 'drivers/media/common')
27 files changed, 1175 insertions, 235 deletions
diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c index 982f000a57ff..9af2140b57a4 100644 --- a/drivers/media/common/saa7146_core.c +++ b/drivers/media/common/saa7146_core.c | |||
@@ -378,12 +378,7 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent | |||
378 | dev->pci = pci; | 378 | dev->pci = pci; |
379 | 379 | ||
380 | /* get chip-revision; this is needed to enable bug-fixes */ | 380 | /* get chip-revision; this is needed to enable bug-fixes */ |
381 | err = pci_read_config_dword(pci, PCI_CLASS_REVISION, &dev->revision); | 381 | dev->revision = pci->revision; |
382 | if (err < 0) { | ||
383 | ERR(("pci_read_config_dword() failed.\n")); | ||
384 | goto err_disable; | ||
385 | } | ||
386 | dev->revision &= 0xf; | ||
387 | 382 | ||
388 | /* remap the memory from virtual to physical address */ | 383 | /* remap the memory from virtual to physical address */ |
389 | 384 | ||
@@ -452,7 +447,7 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent | |||
452 | INFO(("found saa7146 @ mem %p (revision %d, irq %d) (0x%04x,0x%04x).\n", dev->mem, dev->revision, pci->irq, pci->subsystem_vendor, pci->subsystem_device)); | 447 | INFO(("found saa7146 @ mem %p (revision %d, irq %d) (0x%04x,0x%04x).\n", dev->mem, dev->revision, pci->irq, pci->subsystem_vendor, pci->subsystem_device)); |
453 | dev->ext = ext; | 448 | dev->ext = ext; |
454 | 449 | ||
455 | mutex_init(&dev->lock); | 450 | mutex_init(&dev->v4l2_lock); |
456 | spin_lock_init(&dev->int_slock); | 451 | spin_lock_init(&dev->int_slock); |
457 | spin_lock_init(&dev->slock); | 452 | spin_lock_init(&dev->slock); |
458 | 453 | ||
diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c index 4da2a54cb8bd..1bd3dd762c6b 100644 --- a/drivers/media/common/saa7146_fops.c +++ b/drivers/media/common/saa7146_fops.c | |||
@@ -15,18 +15,15 @@ int saa7146_res_get(struct saa7146_fh *fh, unsigned int bit) | |||
15 | } | 15 | } |
16 | 16 | ||
17 | /* is it free? */ | 17 | /* is it free? */ |
18 | mutex_lock(&dev->lock); | ||
19 | if (vv->resources & bit) { | 18 | if (vv->resources & bit) { |
20 | DEB_D(("locked! vv->resources:0x%02x, we want:0x%02x\n",vv->resources,bit)); | 19 | DEB_D(("locked! vv->resources:0x%02x, we want:0x%02x\n",vv->resources,bit)); |
21 | /* no, someone else uses it */ | 20 | /* no, someone else uses it */ |
22 | mutex_unlock(&dev->lock); | ||
23 | return 0; | 21 | return 0; |
24 | } | 22 | } |
25 | /* it's free, grab it */ | 23 | /* it's free, grab it */ |
26 | fh->resources |= bit; | 24 | fh->resources |= bit; |
27 | vv->resources |= bit; | 25 | vv->resources |= bit; |
28 | DEB_D(("res: get 0x%02x, cur:0x%02x\n",bit,vv->resources)); | 26 | DEB_D(("res: get 0x%02x, cur:0x%02x\n",bit,vv->resources)); |
29 | mutex_unlock(&dev->lock); | ||
30 | return 1; | 27 | return 1; |
31 | } | 28 | } |
32 | 29 | ||
@@ -37,11 +34,9 @@ void saa7146_res_free(struct saa7146_fh *fh, unsigned int bits) | |||
37 | 34 | ||
38 | BUG_ON((fh->resources & bits) != bits); | 35 | BUG_ON((fh->resources & bits) != bits); |
39 | 36 | ||
40 | mutex_lock(&dev->lock); | ||
41 | fh->resources &= ~bits; | 37 | fh->resources &= ~bits; |
42 | vv->resources &= ~bits; | 38 | vv->resources &= ~bits; |
43 | DEB_D(("res: put 0x%02x, cur:0x%02x\n",bits,vv->resources)); | 39 | DEB_D(("res: put 0x%02x, cur:0x%02x\n",bits,vv->resources)); |
44 | mutex_unlock(&dev->lock); | ||
45 | } | 40 | } |
46 | 41 | ||
47 | 42 | ||
@@ -56,7 +51,7 @@ void saa7146_dma_free(struct saa7146_dev *dev,struct videobuf_queue *q, | |||
56 | 51 | ||
57 | BUG_ON(in_interrupt()); | 52 | BUG_ON(in_interrupt()); |
58 | 53 | ||
59 | videobuf_waiton(&buf->vb,0,0); | 54 | videobuf_waiton(q, &buf->vb, 0, 0); |
60 | videobuf_dma_unmap(q->dev, dma); | 55 | videobuf_dma_unmap(q->dev, dma); |
61 | videobuf_dma_free(dma); | 56 | videobuf_dma_free(dma); |
62 | buf->vb.state = VIDEOBUF_NEEDS_INIT; | 57 | buf->vb.state = VIDEOBUF_NEEDS_INIT; |
@@ -396,7 +391,7 @@ static const struct v4l2_file_operations video_fops = | |||
396 | .write = fops_write, | 391 | .write = fops_write, |
397 | .poll = fops_poll, | 392 | .poll = fops_poll, |
398 | .mmap = fops_mmap, | 393 | .mmap = fops_mmap, |
399 | .ioctl = video_ioctl2, | 394 | .unlocked_ioctl = video_ioctl2, |
400 | }; | 395 | }; |
401 | 396 | ||
402 | static void vv_callback(struct saa7146_dev *dev, unsigned long status) | 397 | static void vv_callback(struct saa7146_dev *dev, unsigned long status) |
@@ -505,6 +500,7 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev, | |||
505 | vfd->fops = &video_fops; | 500 | vfd->fops = &video_fops; |
506 | vfd->ioctl_ops = &dev->ext_vv_data->ops; | 501 | vfd->ioctl_ops = &dev->ext_vv_data->ops; |
507 | vfd->release = video_device_release; | 502 | vfd->release = video_device_release; |
503 | vfd->lock = &dev->v4l2_lock; | ||
508 | vfd->tvnorms = 0; | 504 | vfd->tvnorms = 0; |
509 | for (i = 0; i < dev->ext_vv_data->num_stds; i++) | 505 | for (i = 0; i < dev->ext_vv_data->num_stds; i++) |
510 | vfd->tvnorms |= dev->ext_vv_data->stds[i].id; | 506 | vfd->tvnorms |= dev->ext_vv_data->stds[i].id; |
diff --git a/drivers/media/common/saa7146_hlp.c b/drivers/media/common/saa7146_hlp.c index 05bde9ccb770..1d1d8d200755 100644 --- a/drivers/media/common/saa7146_hlp.c +++ b/drivers/media/common/saa7146_hlp.c | |||
@@ -558,7 +558,7 @@ static void saa7146_set_window(struct saa7146_dev *dev, int width, int height, e | |||
558 | static void saa7146_set_position(struct saa7146_dev *dev, int w_x, int w_y, int w_height, enum v4l2_field field, u32 pixelformat) | 558 | static void saa7146_set_position(struct saa7146_dev *dev, int w_x, int w_y, int w_height, enum v4l2_field field, u32 pixelformat) |
559 | { | 559 | { |
560 | struct saa7146_vv *vv = dev->vv_data; | 560 | struct saa7146_vv *vv = dev->vv_data; |
561 | struct saa7146_format *sfmt = format_by_fourcc(dev, pixelformat); | 561 | struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev, pixelformat); |
562 | 562 | ||
563 | int b_depth = vv->ov_fmt->depth; | 563 | int b_depth = vv->ov_fmt->depth; |
564 | int b_bpl = vv->ov_fb.fmt.bytesperline; | 564 | int b_bpl = vv->ov_fb.fmt.bytesperline; |
@@ -702,7 +702,7 @@ static int calculate_video_dma_grab_packed(struct saa7146_dev* dev, struct saa71 | |||
702 | struct saa7146_vv *vv = dev->vv_data; | 702 | struct saa7146_vv *vv = dev->vv_data; |
703 | struct saa7146_video_dma vdma1; | 703 | struct saa7146_video_dma vdma1; |
704 | 704 | ||
705 | struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat); | 705 | struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat); |
706 | 706 | ||
707 | int width = buf->fmt->width; | 707 | int width = buf->fmt->width; |
708 | int height = buf->fmt->height; | 708 | int height = buf->fmt->height; |
@@ -827,7 +827,7 @@ static int calculate_video_dma_grab_planar(struct saa7146_dev* dev, struct saa71 | |||
827 | struct saa7146_video_dma vdma2; | 827 | struct saa7146_video_dma vdma2; |
828 | struct saa7146_video_dma vdma3; | 828 | struct saa7146_video_dma vdma3; |
829 | 829 | ||
830 | struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat); | 830 | struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat); |
831 | 831 | ||
832 | int width = buf->fmt->width; | 832 | int width = buf->fmt->width; |
833 | int height = buf->fmt->height; | 833 | int height = buf->fmt->height; |
@@ -994,7 +994,7 @@ static void program_capture_engine(struct saa7146_dev *dev, int planar) | |||
994 | 994 | ||
995 | void saa7146_set_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struct saa7146_buf *next) | 995 | void saa7146_set_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struct saa7146_buf *next) |
996 | { | 996 | { |
997 | struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat); | 997 | struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat); |
998 | struct saa7146_vv *vv = dev->vv_data; | 998 | struct saa7146_vv *vv = dev->vv_data; |
999 | u32 vdma1_prot_addr; | 999 | u32 vdma1_prot_addr; |
1000 | 1000 | ||
diff --git a/drivers/media/common/saa7146_i2c.c b/drivers/media/common/saa7146_i2c.c index 48cb154c7a46..b2ba9dc0dd6d 100644 --- a/drivers/media/common/saa7146_i2c.c +++ b/drivers/media/common/saa7146_i2c.c | |||
@@ -161,7 +161,7 @@ static int saa7146_i2c_reset(struct saa7146_dev *dev) | |||
161 | msleep(SAA7146_I2C_DELAY); | 161 | msleep(SAA7146_I2C_DELAY); |
162 | } | 162 | } |
163 | 163 | ||
164 | /* if any error is still present, a fatal error has occured ... */ | 164 | /* if any error is still present, a fatal error has occurred ... */ |
165 | status = saa7146_i2c_status(dev); | 165 | status = saa7146_i2c_status(dev); |
166 | if ( dev->i2c_bitrate != status ) { | 166 | if ( dev->i2c_bitrate != status ) { |
167 | DEB_I2C(("fatal error. status:0x%08x\n",status)); | 167 | DEB_I2C(("fatal error. status:0x%08x\n",status)); |
@@ -326,9 +326,9 @@ static int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *m | |||
326 | if ( 0 != err) { | 326 | if ( 0 != err) { |
327 | /* this one is unsatisfying: some i2c slaves on some | 327 | /* this one is unsatisfying: some i2c slaves on some |
328 | dvb cards don't acknowledge correctly, so the saa7146 | 328 | dvb cards don't acknowledge correctly, so the saa7146 |
329 | thinks that an address error occured. in that case, the | 329 | thinks that an address error occurred. in that case, the |
330 | transaction should be retrying, even if an address error | 330 | transaction should be retrying, even if an address error |
331 | occured. analog saa7146 based cards extensively rely on | 331 | occurred. analog saa7146 based cards extensively rely on |
332 | i2c address probing, however, and address errors indicate that a | 332 | i2c address probing, however, and address errors indicate that a |
333 | device is really *not* there. retrying in that case | 333 | device is really *not* there. retrying in that case |
334 | increases the time the device needs to probe greatly, so | 334 | increases the time the device needs to probe greatly, so |
@@ -365,7 +365,7 @@ static int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *m | |||
365 | DEB_I2C(("transmission successful. (msg:%d).\n",err)); | 365 | DEB_I2C(("transmission successful. (msg:%d).\n",err)); |
366 | out: | 366 | out: |
367 | /* another bug in revision 0: the i2c-registers get uploaded randomly by other | 367 | /* another bug in revision 0: the i2c-registers get uploaded randomly by other |
368 | uploads, so we better clear them out before continueing */ | 368 | uploads, so we better clear them out before continuing */ |
369 | if( 0 == dev->revision ) { | 369 | if( 0 == dev->revision ) { |
370 | __le32 zero = 0; | 370 | __le32 zero = 0; |
371 | saa7146_i2c_reset(dev); | 371 | saa7146_i2c_reset(dev); |
@@ -391,7 +391,6 @@ static int saa7146_i2c_xfer(struct i2c_adapter* adapter, struct i2c_msg *msg, in | |||
391 | 391 | ||
392 | /*****************************************************************************/ | 392 | /*****************************************************************************/ |
393 | /* i2c-adapter helper functions */ | 393 | /* i2c-adapter helper functions */ |
394 | #include <linux/i2c-id.h> | ||
395 | 394 | ||
396 | /* exported algorithm data */ | 395 | /* exported algorithm data */ |
397 | static struct i2c_algorithm saa7146_algo = { | 396 | static struct i2c_algorithm saa7146_algo = { |
@@ -414,7 +413,6 @@ int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c | |||
414 | i2c_adapter->dev.parent = &dev->pci->dev; | 413 | i2c_adapter->dev.parent = &dev->pci->dev; |
415 | i2c_adapter->algo = &saa7146_algo; | 414 | i2c_adapter->algo = &saa7146_algo; |
416 | i2c_adapter->algo_data = NULL; | 415 | i2c_adapter->algo_data = NULL; |
417 | i2c_adapter->id = I2C_HW_SAA7146; | ||
418 | i2c_adapter->timeout = SAA7146_I2C_TIMEOUT; | 416 | i2c_adapter->timeout = SAA7146_I2C_TIMEOUT; |
419 | i2c_adapter->retries = SAA7146_I2C_RETRIES; | 417 | i2c_adapter->retries = SAA7146_I2C_RETRIES; |
420 | } | 418 | } |
diff --git a/drivers/media/common/saa7146_vbi.c b/drivers/media/common/saa7146_vbi.c index 8224c301d050..afe85801d6ca 100644 --- a/drivers/media/common/saa7146_vbi.c +++ b/drivers/media/common/saa7146_vbi.c | |||
@@ -412,7 +412,7 @@ static int vbi_open(struct saa7146_dev *dev, struct file *file) | |||
412 | V4L2_BUF_TYPE_VBI_CAPTURE, | 412 | V4L2_BUF_TYPE_VBI_CAPTURE, |
413 | V4L2_FIELD_SEQ_TB, // FIXME: does this really work? | 413 | V4L2_FIELD_SEQ_TB, // FIXME: does this really work? |
414 | sizeof(struct saa7146_buf), | 414 | sizeof(struct saa7146_buf), |
415 | file); | 415 | file, &dev->v4l2_lock); |
416 | 416 | ||
417 | init_timer(&fh->vbi_read_timeout); | 417 | init_timer(&fh->vbi_read_timeout); |
418 | fh->vbi_read_timeout.function = vbi_read_timeout; | 418 | fh->vbi_read_timeout.function = vbi_read_timeout; |
diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c index a212a91a30f0..9aafa4e969a8 100644 --- a/drivers/media/common/saa7146_video.c +++ b/drivers/media/common/saa7146_video.c | |||
@@ -84,7 +84,7 @@ static struct saa7146_format formats[] = { | |||
84 | 84 | ||
85 | static int NUM_FORMATS = sizeof(formats)/sizeof(struct saa7146_format); | 85 | static int NUM_FORMATS = sizeof(formats)/sizeof(struct saa7146_format); |
86 | 86 | ||
87 | struct saa7146_format* format_by_fourcc(struct saa7146_dev *dev, int fourcc) | 87 | struct saa7146_format* saa7146_format_by_fourcc(struct saa7146_dev *dev, int fourcc) |
88 | { | 88 | { |
89 | int i, j = NUM_FORMATS; | 89 | int i, j = NUM_FORMATS; |
90 | 90 | ||
@@ -266,7 +266,7 @@ static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *bu | |||
266 | struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); | 266 | struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); |
267 | struct scatterlist *list = dma->sglist; | 267 | struct scatterlist *list = dma->sglist; |
268 | int length = dma->sglen; | 268 | int length = dma->sglen; |
269 | struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat); | 269 | struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat); |
270 | 270 | ||
271 | DEB_EE(("dev:%p, buf:%p, sg_len:%d\n",dev,buf,length)); | 271 | DEB_EE(("dev:%p, buf:%p, sg_len:%d\n",dev,buf,length)); |
272 | 272 | ||
@@ -408,7 +408,7 @@ static int video_begin(struct saa7146_fh *fh) | |||
408 | } | 408 | } |
409 | } | 409 | } |
410 | 410 | ||
411 | fmt = format_by_fourcc(dev,fh->video_fmt.pixelformat); | 411 | fmt = saa7146_format_by_fourcc(dev,fh->video_fmt.pixelformat); |
412 | /* we need to have a valid format set here */ | 412 | /* we need to have a valid format set here */ |
413 | BUG_ON(NULL == fmt); | 413 | BUG_ON(NULL == fmt); |
414 | 414 | ||
@@ -460,7 +460,7 @@ static int video_end(struct saa7146_fh *fh, struct file *file) | |||
460 | return -EBUSY; | 460 | return -EBUSY; |
461 | } | 461 | } |
462 | 462 | ||
463 | fmt = format_by_fourcc(dev,fh->video_fmt.pixelformat); | 463 | fmt = saa7146_format_by_fourcc(dev,fh->video_fmt.pixelformat); |
464 | /* we need to have a valid format set here */ | 464 | /* we need to have a valid format set here */ |
465 | BUG_ON(NULL == fmt); | 465 | BUG_ON(NULL == fmt); |
466 | 466 | ||
@@ -536,7 +536,7 @@ static int vidioc_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *f | |||
536 | return -EPERM; | 536 | return -EPERM; |
537 | 537 | ||
538 | /* check args */ | 538 | /* check args */ |
539 | fmt = format_by_fourcc(dev, fb->fmt.pixelformat); | 539 | fmt = saa7146_format_by_fourcc(dev, fb->fmt.pixelformat); |
540 | if (NULL == fmt) | 540 | if (NULL == fmt) |
541 | return -EINVAL; | 541 | return -EINVAL; |
542 | 542 | ||
@@ -553,8 +553,6 @@ static int vidioc_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *f | |||
553 | } | 553 | } |
554 | } | 554 | } |
555 | 555 | ||
556 | mutex_lock(&dev->lock); | ||
557 | |||
558 | /* ok, accept it */ | 556 | /* ok, accept it */ |
559 | vv->ov_fb = *fb; | 557 | vv->ov_fb = *fb; |
560 | vv->ov_fmt = fmt; | 558 | vv->ov_fmt = fmt; |
@@ -563,8 +561,6 @@ static int vidioc_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *f | |||
563 | vv->ov_fb.fmt.bytesperline = vv->ov_fb.fmt.width * fmt->depth / 8; | 561 | vv->ov_fb.fmt.bytesperline = vv->ov_fb.fmt.width * fmt->depth / 8; |
564 | DEB_D(("setting bytesperline to %d\n", vv->ov_fb.fmt.bytesperline)); | 562 | DEB_D(("setting bytesperline to %d\n", vv->ov_fb.fmt.bytesperline)); |
565 | } | 563 | } |
566 | |||
567 | mutex_unlock(&dev->lock); | ||
568 | return 0; | 564 | return 0; |
569 | } | 565 | } |
570 | 566 | ||
@@ -649,8 +645,6 @@ static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *c) | |||
649 | return -EINVAL; | 645 | return -EINVAL; |
650 | } | 646 | } |
651 | 647 | ||
652 | mutex_lock(&dev->lock); | ||
653 | |||
654 | switch (ctrl->type) { | 648 | switch (ctrl->type) { |
655 | case V4L2_CTRL_TYPE_BOOLEAN: | 649 | case V4L2_CTRL_TYPE_BOOLEAN: |
656 | case V4L2_CTRL_TYPE_MENU: | 650 | case V4L2_CTRL_TYPE_MENU: |
@@ -693,7 +687,6 @@ static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *c) | |||
693 | /* fixme: we can support changing VFLIP and HFLIP here... */ | 687 | /* fixme: we can support changing VFLIP and HFLIP here... */ |
694 | if (IS_CAPTURE_ACTIVE(fh) != 0) { | 688 | if (IS_CAPTURE_ACTIVE(fh) != 0) { |
695 | DEB_D(("V4L2_CID_HFLIP while active capture.\n")); | 689 | DEB_D(("V4L2_CID_HFLIP while active capture.\n")); |
696 | mutex_unlock(&dev->lock); | ||
697 | return -EBUSY; | 690 | return -EBUSY; |
698 | } | 691 | } |
699 | vv->hflip = c->value; | 692 | vv->hflip = c->value; |
@@ -701,16 +694,13 @@ static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *c) | |||
701 | case V4L2_CID_VFLIP: | 694 | case V4L2_CID_VFLIP: |
702 | if (IS_CAPTURE_ACTIVE(fh) != 0) { | 695 | if (IS_CAPTURE_ACTIVE(fh) != 0) { |
703 | DEB_D(("V4L2_CID_VFLIP while active capture.\n")); | 696 | DEB_D(("V4L2_CID_VFLIP while active capture.\n")); |
704 | mutex_unlock(&dev->lock); | ||
705 | return -EBUSY; | 697 | return -EBUSY; |
706 | } | 698 | } |
707 | vv->vflip = c->value; | 699 | vv->vflip = c->value; |
708 | break; | 700 | break; |
709 | default: | 701 | default: |
710 | mutex_unlock(&dev->lock); | ||
711 | return -EINVAL; | 702 | return -EINVAL; |
712 | } | 703 | } |
713 | mutex_unlock(&dev->lock); | ||
714 | 704 | ||
715 | if (IS_OVERLAY_ACTIVE(fh) != 0) { | 705 | if (IS_OVERLAY_ACTIVE(fh) != 0) { |
716 | saa7146_stop_preview(fh); | 706 | saa7146_stop_preview(fh); |
@@ -760,7 +750,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_forma | |||
760 | 750 | ||
761 | DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh)); | 751 | DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh)); |
762 | 752 | ||
763 | fmt = format_by_fourcc(dev, f->fmt.pix.pixelformat); | 753 | fmt = saa7146_format_by_fourcc(dev, f->fmt.pix.pixelformat); |
764 | if (NULL == fmt) | 754 | if (NULL == fmt) |
765 | return -EINVAL; | 755 | return -EINVAL; |
766 | 756 | ||
@@ -902,22 +892,18 @@ static int vidioc_s_fmt_vid_overlay(struct file *file, void *__fh, struct v4l2_f | |||
902 | err = vidioc_try_fmt_vid_overlay(file, fh, f); | 892 | err = vidioc_try_fmt_vid_overlay(file, fh, f); |
903 | if (0 != err) | 893 | if (0 != err) |
904 | return err; | 894 | return err; |
905 | mutex_lock(&dev->lock); | ||
906 | fh->ov.win = f->fmt.win; | 895 | fh->ov.win = f->fmt.win; |
907 | fh->ov.nclips = f->fmt.win.clipcount; | 896 | fh->ov.nclips = f->fmt.win.clipcount; |
908 | if (fh->ov.nclips > 16) | 897 | if (fh->ov.nclips > 16) |
909 | fh->ov.nclips = 16; | 898 | fh->ov.nclips = 16; |
910 | if (copy_from_user(fh->ov.clips, f->fmt.win.clips, | 899 | if (copy_from_user(fh->ov.clips, f->fmt.win.clips, |
911 | sizeof(struct v4l2_clip) * fh->ov.nclips)) { | 900 | sizeof(struct v4l2_clip) * fh->ov.nclips)) { |
912 | mutex_unlock(&dev->lock); | ||
913 | return -EFAULT; | 901 | return -EFAULT; |
914 | } | 902 | } |
915 | 903 | ||
916 | /* fh->ov.fh is used to indicate that we have valid overlay informations, too */ | 904 | /* fh->ov.fh is used to indicate that we have valid overlay informations, too */ |
917 | fh->ov.fh = fh; | 905 | fh->ov.fh = fh; |
918 | 906 | ||
919 | mutex_unlock(&dev->lock); | ||
920 | |||
921 | /* check if our current overlay is active */ | 907 | /* check if our current overlay is active */ |
922 | if (IS_OVERLAY_ACTIVE(fh) != 0) { | 908 | if (IS_OVERLAY_ACTIVE(fh) != 0) { |
923 | saa7146_stop_preview(fh); | 909 | saa7146_stop_preview(fh); |
@@ -976,8 +962,6 @@ static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id *id) | |||
976 | } | 962 | } |
977 | } | 963 | } |
978 | 964 | ||
979 | mutex_lock(&dev->lock); | ||
980 | |||
981 | for (i = 0; i < dev->ext_vv_data->num_stds; i++) | 965 | for (i = 0; i < dev->ext_vv_data->num_stds; i++) |
982 | if (*id & dev->ext_vv_data->stds[i].id) | 966 | if (*id & dev->ext_vv_data->stds[i].id) |
983 | break; | 967 | break; |
@@ -988,8 +972,6 @@ static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id *id) | |||
988 | found = 1; | 972 | found = 1; |
989 | } | 973 | } |
990 | 974 | ||
991 | mutex_unlock(&dev->lock); | ||
992 | |||
993 | if (vv->ov_suspend != NULL) { | 975 | if (vv->ov_suspend != NULL) { |
994 | saa7146_start_preview(vv->ov_suspend); | 976 | saa7146_start_preview(vv->ov_suspend); |
995 | vv->ov_suspend = NULL; | 977 | vv->ov_suspend = NULL; |
@@ -1129,35 +1111,6 @@ static int vidioc_g_chip_ident(struct file *file, void *__fh, | |||
1129 | core, g_chip_ident, chip); | 1111 | core, g_chip_ident, chip); |
1130 | } | 1112 | } |
1131 | 1113 | ||
1132 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
1133 | static int vidiocgmbuf(struct file *file, void *__fh, struct video_mbuf *mbuf) | ||
1134 | { | ||
1135 | struct saa7146_fh *fh = __fh; | ||
1136 | struct videobuf_queue *q = &fh->video_q; | ||
1137 | int err, i; | ||
1138 | |||
1139 | /* fixme: number of capture buffers and sizes for v4l apps */ | ||
1140 | int gbuffers = 2; | ||
1141 | int gbufsize = 768 * 576 * 4; | ||
1142 | |||
1143 | DEB_D(("VIDIOCGMBUF \n")); | ||
1144 | |||
1145 | q = &fh->video_q; | ||
1146 | err = videobuf_mmap_setup(q, gbuffers, gbufsize, | ||
1147 | V4L2_MEMORY_MMAP); | ||
1148 | if (err < 0) | ||
1149 | return err; | ||
1150 | |||
1151 | gbuffers = err; | ||
1152 | memset(mbuf, 0, sizeof(*mbuf)); | ||
1153 | mbuf->frames = gbuffers; | ||
1154 | mbuf->size = gbuffers * gbufsize; | ||
1155 | for (i = 0; i < gbuffers; i++) | ||
1156 | mbuf->offsets[i] = i * gbufsize; | ||
1157 | return 0; | ||
1158 | } | ||
1159 | #endif | ||
1160 | |||
1161 | const struct v4l2_ioctl_ops saa7146_video_ioctl_ops = { | 1114 | const struct v4l2_ioctl_ops saa7146_video_ioctl_ops = { |
1162 | .vidioc_querycap = vidioc_querycap, | 1115 | .vidioc_querycap = vidioc_querycap, |
1163 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | 1116 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, |
@@ -1186,9 +1139,6 @@ const struct v4l2_ioctl_ops saa7146_video_ioctl_ops = { | |||
1186 | .vidioc_streamon = vidioc_streamon, | 1139 | .vidioc_streamon = vidioc_streamon, |
1187 | .vidioc_streamoff = vidioc_streamoff, | 1140 | .vidioc_streamoff = vidioc_streamoff, |
1188 | .vidioc_g_parm = vidioc_g_parm, | 1141 | .vidioc_g_parm = vidioc_g_parm, |
1189 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
1190 | .vidiocgmbuf = vidiocgmbuf, | ||
1191 | #endif | ||
1192 | }; | 1142 | }; |
1193 | 1143 | ||
1194 | /*********************************************************************************/ | 1144 | /*********************************************************************************/ |
@@ -1264,7 +1214,7 @@ static int buffer_prepare(struct videobuf_queue *q, | |||
1264 | buf->fmt = &fh->video_fmt; | 1214 | buf->fmt = &fh->video_fmt; |
1265 | buf->vb.field = fh->video_fmt.field; | 1215 | buf->vb.field = fh->video_fmt.field; |
1266 | 1216 | ||
1267 | sfmt = format_by_fourcc(dev,buf->fmt->pixelformat); | 1217 | sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat); |
1268 | 1218 | ||
1269 | release_all_pagetables(dev, buf); | 1219 | release_all_pagetables(dev, buf); |
1270 | if( 0 != IS_PLANAR(sfmt->trans)) { | 1220 | if( 0 != IS_PLANAR(sfmt->trans)) { |
@@ -1378,7 +1328,7 @@ static int video_open(struct saa7146_dev *dev, struct file *file) | |||
1378 | fh->video_fmt.pixelformat = V4L2_PIX_FMT_BGR24; | 1328 | fh->video_fmt.pixelformat = V4L2_PIX_FMT_BGR24; |
1379 | fh->video_fmt.bytesperline = 0; | 1329 | fh->video_fmt.bytesperline = 0; |
1380 | fh->video_fmt.field = V4L2_FIELD_ANY; | 1330 | fh->video_fmt.field = V4L2_FIELD_ANY; |
1381 | sfmt = format_by_fourcc(dev,fh->video_fmt.pixelformat); | 1331 | sfmt = saa7146_format_by_fourcc(dev,fh->video_fmt.pixelformat); |
1382 | fh->video_fmt.sizeimage = (fh->video_fmt.width * fh->video_fmt.height * sfmt->depth)/8; | 1332 | fh->video_fmt.sizeimage = (fh->video_fmt.width * fh->video_fmt.height * sfmt->depth)/8; |
1383 | 1333 | ||
1384 | videobuf_queue_sg_init(&fh->video_q, &video_qops, | 1334 | videobuf_queue_sg_init(&fh->video_q, &video_qops, |
@@ -1386,7 +1336,7 @@ static int video_open(struct saa7146_dev *dev, struct file *file) | |||
1386 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | 1336 | V4L2_BUF_TYPE_VIDEO_CAPTURE, |
1387 | V4L2_FIELD_INTERLACED, | 1337 | V4L2_FIELD_INTERLACED, |
1388 | sizeof(struct saa7146_buf), | 1338 | sizeof(struct saa7146_buf), |
1389 | file); | 1339 | file, &dev->v4l2_lock); |
1390 | 1340 | ||
1391 | return 0; | 1341 | return 0; |
1392 | } | 1342 | } |
diff --git a/drivers/media/common/tuners/Kconfig b/drivers/media/common/tuners/Kconfig index b3ed5daaacf2..22d3ca36370e 100644 --- a/drivers/media/common/tuners/Kconfig +++ b/drivers/media/common/tuners/Kconfig | |||
@@ -31,10 +31,10 @@ config MEDIA_TUNER | |||
31 | select MEDIA_TUNER_TDA9887 if !MEDIA_TUNER_CUSTOMISE | 31 | select MEDIA_TUNER_TDA9887 if !MEDIA_TUNER_CUSTOMISE |
32 | select MEDIA_TUNER_MC44S803 if !MEDIA_TUNER_CUSTOMISE | 32 | select MEDIA_TUNER_MC44S803 if !MEDIA_TUNER_CUSTOMISE |
33 | 33 | ||
34 | menuconfig MEDIA_TUNER_CUSTOMISE | 34 | config MEDIA_TUNER_CUSTOMISE |
35 | bool "Customize analog and hybrid tuner modules to build" | 35 | bool "Customize analog and hybrid tuner modules to build" |
36 | depends on MEDIA_TUNER | 36 | depends on MEDIA_TUNER |
37 | default y if EMBEDDED | 37 | default y if EXPERT |
38 | help | 38 | help |
39 | This allows the user to deselect tuner drivers unnecessary | 39 | This allows the user to deselect tuner drivers unnecessary |
40 | for their hardware from the build. Use this option with care | 40 | for their hardware from the build. Use this option with care |
@@ -44,7 +44,8 @@ menuconfig MEDIA_TUNER_CUSTOMISE | |||
44 | 44 | ||
45 | If unsure say N. | 45 | If unsure say N. |
46 | 46 | ||
47 | if MEDIA_TUNER_CUSTOMISE | 47 | menu "Customize TV tuners" |
48 | visible if MEDIA_TUNER_CUSTOMISE | ||
48 | 49 | ||
49 | config MEDIA_TUNER_SIMPLE | 50 | config MEDIA_TUNER_SIMPLE |
50 | tristate "Simple tuner support" | 51 | tristate "Simple tuner support" |
@@ -179,4 +180,18 @@ config MEDIA_TUNER_MAX2165 | |||
179 | help | 180 | help |
180 | A driver for the silicon tuner MAX2165 from Maxim. | 181 | A driver for the silicon tuner MAX2165 from Maxim. |
181 | 182 | ||
182 | endif # MEDIA_TUNER_CUSTOMISE | 183 | config MEDIA_TUNER_TDA18218 |
184 | tristate "NXP TDA18218 silicon tuner" | ||
185 | depends on VIDEO_MEDIA && I2C | ||
186 | default m if MEDIA_TUNER_CUSTOMISE | ||
187 | help | ||
188 | NXP TDA18218 silicon tuner driver. | ||
189 | |||
190 | config MEDIA_TUNER_TDA18212 | ||
191 | tristate "NXP TDA18212 silicon tuner" | ||
192 | depends on VIDEO_MEDIA && I2C | ||
193 | default m if MEDIA_TUNER_CUSTOMISE | ||
194 | help | ||
195 | NXP TDA18212 silicon tuner driver. | ||
196 | |||
197 | endmenu | ||
diff --git a/drivers/media/common/tuners/Makefile b/drivers/media/common/tuners/Makefile index a5438523f30d..2cb4f5327843 100644 --- a/drivers/media/common/tuners/Makefile +++ b/drivers/media/common/tuners/Makefile | |||
@@ -24,6 +24,8 @@ obj-$(CONFIG_MEDIA_TUNER_MXL5005S) += mxl5005s.o | |||
24 | obj-$(CONFIG_MEDIA_TUNER_MXL5007T) += mxl5007t.o | 24 | obj-$(CONFIG_MEDIA_TUNER_MXL5007T) += mxl5007t.o |
25 | obj-$(CONFIG_MEDIA_TUNER_MC44S803) += mc44s803.o | 25 | obj-$(CONFIG_MEDIA_TUNER_MC44S803) += mc44s803.o |
26 | obj-$(CONFIG_MEDIA_TUNER_MAX2165) += max2165.o | 26 | obj-$(CONFIG_MEDIA_TUNER_MAX2165) += max2165.o |
27 | obj-$(CONFIG_MEDIA_TUNER_TDA18218) += tda18218.o | ||
28 | obj-$(CONFIG_MEDIA_TUNER_TDA18212) += tda18212.o | ||
27 | 29 | ||
28 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core | 30 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core |
29 | EXTRA_CFLAGS += -Idrivers/media/dvb/frontends | 31 | EXTRA_CFLAGS += -Idrivers/media/dvb/frontends |
diff --git a/drivers/media/common/tuners/max2165.c b/drivers/media/common/tuners/max2165.c index 937e4b00d7ee..9883617b7862 100644 --- a/drivers/media/common/tuners/max2165.c +++ b/drivers/media/common/tuners/max2165.c | |||
@@ -52,13 +52,12 @@ static int max2165_write_reg(struct max2165_priv *priv, u8 reg, u8 data) | |||
52 | msg.addr = priv->config->i2c_address; | 52 | msg.addr = priv->config->i2c_address; |
53 | 53 | ||
54 | if (debug >= 2) | 54 | if (debug >= 2) |
55 | printk(KERN_DEBUG "%s: reg=0x%02X, data=0x%02X\n", | 55 | dprintk("%s: reg=0x%02X, data=0x%02X\n", __func__, reg, data); |
56 | __func__, reg, data); | ||
57 | 56 | ||
58 | ret = i2c_transfer(priv->i2c, &msg, 1); | 57 | ret = i2c_transfer(priv->i2c, &msg, 1); |
59 | 58 | ||
60 | if (ret != 1) | 59 | if (ret != 1) |
61 | dprintk(KERN_DEBUG "%s: error reg=0x%x, data=0x%x, ret=%i\n", | 60 | dprintk("%s: error reg=0x%x, data=0x%x, ret=%i\n", |
62 | __func__, reg, data, ret); | 61 | __func__, reg, data, ret); |
63 | 62 | ||
64 | return (ret != 1) ? -EIO : 0; | 63 | return (ret != 1) ? -EIO : 0; |
@@ -78,14 +77,13 @@ static int max2165_read_reg(struct max2165_priv *priv, u8 reg, u8 *p_data) | |||
78 | 77 | ||
79 | ret = i2c_transfer(priv->i2c, msg, 2); | 78 | ret = i2c_transfer(priv->i2c, msg, 2); |
80 | if (ret != 2) { | 79 | if (ret != 2) { |
81 | dprintk(KERN_DEBUG "%s: error reg=0x%x, ret=%i\n", | 80 | dprintk("%s: error reg=0x%x, ret=%i\n", __func__, reg, ret); |
82 | __func__, reg, ret); | ||
83 | return -EIO; | 81 | return -EIO; |
84 | } | 82 | } |
85 | 83 | ||
86 | *p_data = b1[0]; | 84 | *p_data = b1[0]; |
87 | if (debug >= 2) | 85 | if (debug >= 2) |
88 | printk(KERN_DEBUG "%s: reg=0x%02X, data=0x%02X\n", | 86 | dprintk("%s: reg=0x%02X, data=0x%02X\n", |
89 | __func__, reg, b1[0]); | 87 | __func__, reg, b1[0]); |
90 | return 0; | 88 | return 0; |
91 | } | 89 | } |
diff --git a/drivers/media/common/tuners/mxl5005s.c b/drivers/media/common/tuners/mxl5005s.c index 605e28b73263..56fe75c94deb 100644 --- a/drivers/media/common/tuners/mxl5005s.c +++ b/drivers/media/common/tuners/mxl5005s.c | |||
@@ -106,7 +106,7 @@ enum { | |||
106 | /* MXL5005 Tuner Register Struct */ | 106 | /* MXL5005 Tuner Register Struct */ |
107 | struct TunerReg { | 107 | struct TunerReg { |
108 | u16 Reg_Num; /* Tuner Register Address */ | 108 | u16 Reg_Num; /* Tuner Register Address */ |
109 | u16 Reg_Val; /* Current sw programmed value waiting to be writen */ | 109 | u16 Reg_Val; /* Current sw programmed value waiting to be written */ |
110 | }; | 110 | }; |
111 | 111 | ||
112 | enum { | 112 | enum { |
@@ -4024,6 +4024,8 @@ static int mxl5005s_set_params(struct dvb_frontend *fe, | |||
4024 | case BANDWIDTH_8_MHZ: | 4024 | case BANDWIDTH_8_MHZ: |
4025 | req_bw = MXL5005S_BANDWIDTH_8MHZ; | 4025 | req_bw = MXL5005S_BANDWIDTH_8MHZ; |
4026 | break; | 4026 | break; |
4027 | default: | ||
4028 | return -EINVAL; | ||
4027 | } | 4029 | } |
4028 | } | 4030 | } |
4029 | 4031 | ||
diff --git a/drivers/media/common/tuners/tda18212.c b/drivers/media/common/tuners/tda18212.c new file mode 100644 index 000000000000..1f1db20d46b1 --- /dev/null +++ b/drivers/media/common/tuners/tda18212.c | |||
@@ -0,0 +1,265 @@ | |||
1 | /* | ||
2 | * NXP TDA18212HN silicon tuner driver | ||
3 | * | ||
4 | * Copyright (C) 2011 Antti Palosaari <crope@iki.fi> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along | ||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
19 | */ | ||
20 | |||
21 | #include "tda18212_priv.h" | ||
22 | |||
23 | static int debug; | ||
24 | module_param(debug, int, 0644); | ||
25 | MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); | ||
26 | |||
27 | /* write multiple registers */ | ||
28 | static int tda18212_wr_regs(struct tda18212_priv *priv, u8 reg, u8 *val, | ||
29 | int len) | ||
30 | { | ||
31 | int ret; | ||
32 | u8 buf[len+1]; | ||
33 | struct i2c_msg msg[1] = { | ||
34 | { | ||
35 | .addr = priv->cfg->i2c_address, | ||
36 | .flags = 0, | ||
37 | .len = sizeof(buf), | ||
38 | .buf = buf, | ||
39 | } | ||
40 | }; | ||
41 | |||
42 | buf[0] = reg; | ||
43 | memcpy(&buf[1], val, len); | ||
44 | |||
45 | ret = i2c_transfer(priv->i2c, msg, 1); | ||
46 | if (ret == 1) { | ||
47 | ret = 0; | ||
48 | } else { | ||
49 | warn("i2c wr failed ret:%d reg:%02x len:%d", ret, reg, len); | ||
50 | ret = -EREMOTEIO; | ||
51 | } | ||
52 | return ret; | ||
53 | } | ||
54 | |||
55 | /* read multiple registers */ | ||
56 | static int tda18212_rd_regs(struct tda18212_priv *priv, u8 reg, u8 *val, | ||
57 | int len) | ||
58 | { | ||
59 | int ret; | ||
60 | u8 buf[len]; | ||
61 | struct i2c_msg msg[2] = { | ||
62 | { | ||
63 | .addr = priv->cfg->i2c_address, | ||
64 | .flags = 0, | ||
65 | .len = 1, | ||
66 | .buf = ®, | ||
67 | }, { | ||
68 | .addr = priv->cfg->i2c_address, | ||
69 | .flags = I2C_M_RD, | ||
70 | .len = sizeof(buf), | ||
71 | .buf = buf, | ||
72 | } | ||
73 | }; | ||
74 | |||
75 | ret = i2c_transfer(priv->i2c, msg, 2); | ||
76 | if (ret == 2) { | ||
77 | memcpy(val, buf, len); | ||
78 | ret = 0; | ||
79 | } else { | ||
80 | warn("i2c rd failed ret:%d reg:%02x len:%d", ret, reg, len); | ||
81 | ret = -EREMOTEIO; | ||
82 | } | ||
83 | |||
84 | return ret; | ||
85 | } | ||
86 | |||
87 | /* write single register */ | ||
88 | static int tda18212_wr_reg(struct tda18212_priv *priv, u8 reg, u8 val) | ||
89 | { | ||
90 | return tda18212_wr_regs(priv, reg, &val, 1); | ||
91 | } | ||
92 | |||
93 | /* read single register */ | ||
94 | static int tda18212_rd_reg(struct tda18212_priv *priv, u8 reg, u8 *val) | ||
95 | { | ||
96 | return tda18212_rd_regs(priv, reg, val, 1); | ||
97 | } | ||
98 | |||
99 | #if 0 /* keep, useful when developing driver */ | ||
100 | static void tda18212_dump_regs(struct tda18212_priv *priv) | ||
101 | { | ||
102 | int i; | ||
103 | u8 buf[256]; | ||
104 | |||
105 | #define TDA18212_RD_LEN 32 | ||
106 | for (i = 0; i < sizeof(buf); i += TDA18212_RD_LEN) | ||
107 | tda18212_rd_regs(priv, i, &buf[i], TDA18212_RD_LEN); | ||
108 | |||
109 | print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 32, 1, buf, | ||
110 | sizeof(buf), true); | ||
111 | |||
112 | return; | ||
113 | } | ||
114 | #endif | ||
115 | |||
116 | static int tda18212_set_params(struct dvb_frontend *fe, | ||
117 | struct dvb_frontend_parameters *p) | ||
118 | { | ||
119 | struct tda18212_priv *priv = fe->tuner_priv; | ||
120 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
121 | int ret, i; | ||
122 | u32 if_khz; | ||
123 | u8 buf[9]; | ||
124 | static const u8 bw_params[][3] = { | ||
125 | /* 0f 13 23 */ | ||
126 | { 0xb3, 0x20, 0x03 }, /* DVB-T 6 MHz */ | ||
127 | { 0xb3, 0x31, 0x01 }, /* DVB-T 7 MHz */ | ||
128 | { 0xb3, 0x22, 0x01 }, /* DVB-T 8 MHz */ | ||
129 | { 0x92, 0x53, 0x03 }, /* DVB-C */ | ||
130 | }; | ||
131 | |||
132 | dbg("%s: delsys=%d RF=%d BW=%d", __func__, | ||
133 | c->delivery_system, c->frequency, c->bandwidth_hz); | ||
134 | |||
135 | if (fe->ops.i2c_gate_ctrl) | ||
136 | fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */ | ||
137 | |||
138 | switch (c->delivery_system) { | ||
139 | case SYS_DVBT: | ||
140 | switch (c->bandwidth_hz) { | ||
141 | case 6000000: | ||
142 | if_khz = priv->cfg->if_dvbt_6; | ||
143 | i = 0; | ||
144 | break; | ||
145 | case 7000000: | ||
146 | if_khz = priv->cfg->if_dvbt_7; | ||
147 | i = 1; | ||
148 | break; | ||
149 | case 8000000: | ||
150 | if_khz = priv->cfg->if_dvbt_8; | ||
151 | i = 2; | ||
152 | break; | ||
153 | default: | ||
154 | ret = -EINVAL; | ||
155 | goto error; | ||
156 | } | ||
157 | break; | ||
158 | case SYS_DVBC_ANNEX_AC: | ||
159 | if_khz = priv->cfg->if_dvbc; | ||
160 | i = 3; | ||
161 | break; | ||
162 | default: | ||
163 | ret = -EINVAL; | ||
164 | goto error; | ||
165 | } | ||
166 | |||
167 | ret = tda18212_wr_reg(priv, 0x23, bw_params[i][2]); | ||
168 | if (ret) | ||
169 | goto error; | ||
170 | |||
171 | ret = tda18212_wr_reg(priv, 0x06, 0x00); | ||
172 | if (ret) | ||
173 | goto error; | ||
174 | |||
175 | ret = tda18212_wr_reg(priv, 0x0f, bw_params[i][0]); | ||
176 | if (ret) | ||
177 | goto error; | ||
178 | |||
179 | buf[0] = 0x02; | ||
180 | buf[1] = bw_params[i][1]; | ||
181 | buf[2] = 0x03; /* default value */ | ||
182 | buf[3] = if_khz / 50; | ||
183 | buf[4] = ((c->frequency / 1000) >> 16) & 0xff; | ||
184 | buf[5] = ((c->frequency / 1000) >> 8) & 0xff; | ||
185 | buf[6] = ((c->frequency / 1000) >> 0) & 0xff; | ||
186 | buf[7] = 0xc1; | ||
187 | buf[8] = 0x01; | ||
188 | ret = tda18212_wr_regs(priv, 0x12, buf, sizeof(buf)); | ||
189 | if (ret) | ||
190 | goto error; | ||
191 | |||
192 | exit: | ||
193 | if (fe->ops.i2c_gate_ctrl) | ||
194 | fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */ | ||
195 | |||
196 | return ret; | ||
197 | |||
198 | error: | ||
199 | dbg("%s: failed:%d", __func__, ret); | ||
200 | goto exit; | ||
201 | } | ||
202 | |||
203 | static int tda18212_release(struct dvb_frontend *fe) | ||
204 | { | ||
205 | kfree(fe->tuner_priv); | ||
206 | fe->tuner_priv = NULL; | ||
207 | return 0; | ||
208 | } | ||
209 | |||
210 | static const struct dvb_tuner_ops tda18212_tuner_ops = { | ||
211 | .info = { | ||
212 | .name = "NXP TDA18212", | ||
213 | |||
214 | .frequency_min = 48000000, | ||
215 | .frequency_max = 864000000, | ||
216 | .frequency_step = 1000, | ||
217 | }, | ||
218 | |||
219 | .release = tda18212_release, | ||
220 | |||
221 | .set_params = tda18212_set_params, | ||
222 | }; | ||
223 | |||
224 | struct dvb_frontend *tda18212_attach(struct dvb_frontend *fe, | ||
225 | struct i2c_adapter *i2c, struct tda18212_config *cfg) | ||
226 | { | ||
227 | struct tda18212_priv *priv = NULL; | ||
228 | int ret; | ||
229 | u8 val; | ||
230 | |||
231 | priv = kzalloc(sizeof(struct tda18212_priv), GFP_KERNEL); | ||
232 | if (priv == NULL) | ||
233 | return NULL; | ||
234 | |||
235 | priv->cfg = cfg; | ||
236 | priv->i2c = i2c; | ||
237 | fe->tuner_priv = priv; | ||
238 | |||
239 | if (fe->ops.i2c_gate_ctrl) | ||
240 | fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */ | ||
241 | |||
242 | /* check if the tuner is there */ | ||
243 | ret = tda18212_rd_reg(priv, 0x00, &val); | ||
244 | |||
245 | if (fe->ops.i2c_gate_ctrl) | ||
246 | fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */ | ||
247 | |||
248 | dbg("%s: ret:%d chip ID:%02x", __func__, ret, val); | ||
249 | if (ret || val != 0xc7) { | ||
250 | kfree(priv); | ||
251 | return NULL; | ||
252 | } | ||
253 | |||
254 | info("NXP TDA18212HN successfully identified."); | ||
255 | |||
256 | memcpy(&fe->ops.tuner_ops, &tda18212_tuner_ops, | ||
257 | sizeof(struct dvb_tuner_ops)); | ||
258 | |||
259 | return fe; | ||
260 | } | ||
261 | EXPORT_SYMBOL(tda18212_attach); | ||
262 | |||
263 | MODULE_DESCRIPTION("NXP TDA18212HN silicon tuner driver"); | ||
264 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | ||
265 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/common/tuners/tda18212.h b/drivers/media/common/tuners/tda18212.h new file mode 100644 index 000000000000..83b497f59e1b --- /dev/null +++ b/drivers/media/common/tuners/tda18212.h | |||
@@ -0,0 +1,48 @@ | |||
1 | /* | ||
2 | * NXP TDA18212HN silicon tuner driver | ||
3 | * | ||
4 | * Copyright (C) 2011 Antti Palosaari <crope@iki.fi> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along | ||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef TDA18212_H | ||
22 | #define TDA18212_H | ||
23 | |||
24 | #include "dvb_frontend.h" | ||
25 | |||
26 | struct tda18212_config { | ||
27 | u8 i2c_address; | ||
28 | |||
29 | u16 if_dvbt_6; | ||
30 | u16 if_dvbt_7; | ||
31 | u16 if_dvbt_8; | ||
32 | u16 if_dvbc; | ||
33 | }; | ||
34 | |||
35 | #if defined(CONFIG_MEDIA_TUNER_TDA18212) || \ | ||
36 | (defined(CONFIG_MEDIA_TUNER_TDA18212_MODULE) && defined(MODULE)) | ||
37 | extern struct dvb_frontend *tda18212_attach(struct dvb_frontend *fe, | ||
38 | struct i2c_adapter *i2c, struct tda18212_config *cfg); | ||
39 | #else | ||
40 | static inline struct dvb_frontend *tda18212_attach(struct dvb_frontend *fe, | ||
41 | struct i2c_adapter *i2c, struct tda18212_config *cfg) | ||
42 | { | ||
43 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
44 | return NULL; | ||
45 | } | ||
46 | #endif | ||
47 | |||
48 | #endif | ||
diff --git a/drivers/media/common/tuners/tda18212_priv.h b/drivers/media/common/tuners/tda18212_priv.h new file mode 100644 index 000000000000..9adff9356b73 --- /dev/null +++ b/drivers/media/common/tuners/tda18212_priv.h | |||
@@ -0,0 +1,44 @@ | |||
1 | /* | ||
2 | * NXP TDA18212HN silicon tuner driver | ||
3 | * | ||
4 | * Copyright (C) 2011 Antti Palosaari <crope@iki.fi> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along | ||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef TDA18212_PRIV_H | ||
22 | #define TDA18212_PRIV_H | ||
23 | |||
24 | #include "tda18212.h" | ||
25 | |||
26 | #define LOG_PREFIX "tda18212" | ||
27 | |||
28 | #undef dbg | ||
29 | #define dbg(f, arg...) \ | ||
30 | if (debug) \ | ||
31 | printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) | ||
32 | #undef err | ||
33 | #define err(f, arg...) printk(KERN_ERR LOG_PREFIX": " f "\n" , ## arg) | ||
34 | #undef info | ||
35 | #define info(f, arg...) printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) | ||
36 | #undef warn | ||
37 | #define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg) | ||
38 | |||
39 | struct tda18212_priv { | ||
40 | struct tda18212_config *cfg; | ||
41 | struct i2c_adapter *i2c; | ||
42 | }; | ||
43 | |||
44 | #endif | ||
diff --git a/drivers/media/common/tuners/tda18218.c b/drivers/media/common/tuners/tda18218.c new file mode 100644 index 000000000000..aacfe2387e28 --- /dev/null +++ b/drivers/media/common/tuners/tda18218.c | |||
@@ -0,0 +1,334 @@ | |||
1 | /* | ||
2 | * NXP TDA18218HN silicon tuner driver | ||
3 | * | ||
4 | * Copyright (C) 2010 Antti Palosaari <crope@iki.fi> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include "tda18218.h" | ||
22 | #include "tda18218_priv.h" | ||
23 | |||
24 | static int debug; | ||
25 | module_param(debug, int, 0644); | ||
26 | MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); | ||
27 | |||
28 | /* write multiple registers */ | ||
29 | static int tda18218_wr_regs(struct tda18218_priv *priv, u8 reg, u8 *val, u8 len) | ||
30 | { | ||
31 | int ret = 0; | ||
32 | u8 buf[1+len], quotient, remainder, i, msg_len, msg_len_max; | ||
33 | struct i2c_msg msg[1] = { | ||
34 | { | ||
35 | .addr = priv->cfg->i2c_address, | ||
36 | .flags = 0, | ||
37 | .buf = buf, | ||
38 | } | ||
39 | }; | ||
40 | |||
41 | msg_len_max = priv->cfg->i2c_wr_max - 1; | ||
42 | quotient = len / msg_len_max; | ||
43 | remainder = len % msg_len_max; | ||
44 | msg_len = msg_len_max; | ||
45 | for (i = 0; (i <= quotient && remainder); i++) { | ||
46 | if (i == quotient) /* set len of the last msg */ | ||
47 | msg_len = remainder; | ||
48 | |||
49 | msg[0].len = msg_len + 1; | ||
50 | buf[0] = reg + i * msg_len_max; | ||
51 | memcpy(&buf[1], &val[i * msg_len_max], msg_len); | ||
52 | |||
53 | ret = i2c_transfer(priv->i2c, msg, 1); | ||
54 | if (ret != 1) | ||
55 | break; | ||
56 | } | ||
57 | |||
58 | if (ret == 1) { | ||
59 | ret = 0; | ||
60 | } else { | ||
61 | warn("i2c wr failed ret:%d reg:%02x len:%d", ret, reg, len); | ||
62 | ret = -EREMOTEIO; | ||
63 | } | ||
64 | |||
65 | return ret; | ||
66 | } | ||
67 | |||
68 | /* read multiple registers */ | ||
69 | static int tda18218_rd_regs(struct tda18218_priv *priv, u8 reg, u8 *val, u8 len) | ||
70 | { | ||
71 | int ret; | ||
72 | u8 buf[reg+len]; /* we must start read always from reg 0x00 */ | ||
73 | struct i2c_msg msg[2] = { | ||
74 | { | ||
75 | .addr = priv->cfg->i2c_address, | ||
76 | .flags = 0, | ||
77 | .len = 1, | ||
78 | .buf = "\x00", | ||
79 | }, { | ||
80 | .addr = priv->cfg->i2c_address, | ||
81 | .flags = I2C_M_RD, | ||
82 | .len = sizeof(buf), | ||
83 | .buf = buf, | ||
84 | } | ||
85 | }; | ||
86 | |||
87 | ret = i2c_transfer(priv->i2c, msg, 2); | ||
88 | if (ret == 2) { | ||
89 | memcpy(val, &buf[reg], len); | ||
90 | ret = 0; | ||
91 | } else { | ||
92 | warn("i2c rd failed ret:%d reg:%02x len:%d", ret, reg, len); | ||
93 | ret = -EREMOTEIO; | ||
94 | } | ||
95 | |||
96 | return ret; | ||
97 | } | ||
98 | |||
99 | /* write single register */ | ||
100 | static int tda18218_wr_reg(struct tda18218_priv *priv, u8 reg, u8 val) | ||
101 | { | ||
102 | return tda18218_wr_regs(priv, reg, &val, 1); | ||
103 | } | ||
104 | |||
105 | /* read single register */ | ||
106 | |||
107 | static int tda18218_rd_reg(struct tda18218_priv *priv, u8 reg, u8 *val) | ||
108 | { | ||
109 | return tda18218_rd_regs(priv, reg, val, 1); | ||
110 | } | ||
111 | |||
112 | static int tda18218_set_params(struct dvb_frontend *fe, | ||
113 | struct dvb_frontend_parameters *params) | ||
114 | { | ||
115 | struct tda18218_priv *priv = fe->tuner_priv; | ||
116 | int ret; | ||
117 | u8 buf[3], i, BP_Filter, LP_Fc; | ||
118 | u32 LO_Frac; | ||
119 | /* TODO: find out correct AGC algorithm */ | ||
120 | u8 agc[][2] = { | ||
121 | { R20_AGC11, 0x60 }, | ||
122 | { R23_AGC21, 0x02 }, | ||
123 | { R20_AGC11, 0xa0 }, | ||
124 | { R23_AGC21, 0x09 }, | ||
125 | { R20_AGC11, 0xe0 }, | ||
126 | { R23_AGC21, 0x0c }, | ||
127 | { R20_AGC11, 0x40 }, | ||
128 | { R23_AGC21, 0x01 }, | ||
129 | { R20_AGC11, 0x80 }, | ||
130 | { R23_AGC21, 0x08 }, | ||
131 | { R20_AGC11, 0xc0 }, | ||
132 | { R23_AGC21, 0x0b }, | ||
133 | { R24_AGC22, 0x1c }, | ||
134 | { R24_AGC22, 0x0c }, | ||
135 | }; | ||
136 | |||
137 | if (fe->ops.i2c_gate_ctrl) | ||
138 | fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */ | ||
139 | |||
140 | /* low-pass filter cut-off frequency */ | ||
141 | switch (params->u.ofdm.bandwidth) { | ||
142 | case BANDWIDTH_6_MHZ: | ||
143 | LP_Fc = 0; | ||
144 | LO_Frac = params->frequency + 4000000; | ||
145 | break; | ||
146 | case BANDWIDTH_7_MHZ: | ||
147 | LP_Fc = 1; | ||
148 | LO_Frac = params->frequency + 3500000; | ||
149 | break; | ||
150 | case BANDWIDTH_8_MHZ: | ||
151 | default: | ||
152 | LP_Fc = 2; | ||
153 | LO_Frac = params->frequency + 4000000; | ||
154 | break; | ||
155 | } | ||
156 | |||
157 | /* band-pass filter */ | ||
158 | if (LO_Frac < 188000000) | ||
159 | BP_Filter = 3; | ||
160 | else if (LO_Frac < 253000000) | ||
161 | BP_Filter = 4; | ||
162 | else if (LO_Frac < 343000000) | ||
163 | BP_Filter = 5; | ||
164 | else | ||
165 | BP_Filter = 6; | ||
166 | |||
167 | buf[0] = (priv->regs[R1A_IF1] & ~7) | BP_Filter; /* BP_Filter */ | ||
168 | buf[1] = (priv->regs[R1B_IF2] & ~3) | LP_Fc; /* LP_Fc */ | ||
169 | buf[2] = priv->regs[R1C_AGC2B]; | ||
170 | ret = tda18218_wr_regs(priv, R1A_IF1, buf, 3); | ||
171 | if (ret) | ||
172 | goto error; | ||
173 | |||
174 | buf[0] = (LO_Frac / 1000) >> 12; /* LO_Frac_0 */ | ||
175 | buf[1] = (LO_Frac / 1000) >> 4; /* LO_Frac_1 */ | ||
176 | buf[2] = (LO_Frac / 1000) << 4 | | ||
177 | (priv->regs[R0C_MD5] & 0x0f); /* LO_Frac_2 */ | ||
178 | ret = tda18218_wr_regs(priv, R0A_MD3, buf, 3); | ||
179 | if (ret) | ||
180 | goto error; | ||
181 | |||
182 | buf[0] = priv->regs[R0F_MD8] | (1 << 6); /* Freq_prog_Start */ | ||
183 | ret = tda18218_wr_regs(priv, R0F_MD8, buf, 1); | ||
184 | if (ret) | ||
185 | goto error; | ||
186 | |||
187 | buf[0] = priv->regs[R0F_MD8] & ~(1 << 6); /* Freq_prog_Start */ | ||
188 | ret = tda18218_wr_regs(priv, R0F_MD8, buf, 1); | ||
189 | if (ret) | ||
190 | goto error; | ||
191 | |||
192 | /* trigger AGC */ | ||
193 | for (i = 0; i < ARRAY_SIZE(agc); i++) { | ||
194 | ret = tda18218_wr_reg(priv, agc[i][0], agc[i][1]); | ||
195 | if (ret) | ||
196 | goto error; | ||
197 | } | ||
198 | |||
199 | error: | ||
200 | if (fe->ops.i2c_gate_ctrl) | ||
201 | fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */ | ||
202 | |||
203 | if (ret) | ||
204 | dbg("%s: failed ret:%d", __func__, ret); | ||
205 | |||
206 | return ret; | ||
207 | } | ||
208 | |||
209 | static int tda18218_sleep(struct dvb_frontend *fe) | ||
210 | { | ||
211 | struct tda18218_priv *priv = fe->tuner_priv; | ||
212 | int ret; | ||
213 | |||
214 | if (fe->ops.i2c_gate_ctrl) | ||
215 | fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */ | ||
216 | |||
217 | /* standby */ | ||
218 | ret = tda18218_wr_reg(priv, R17_PD1, priv->regs[R17_PD1] | (1 << 0)); | ||
219 | |||
220 | if (fe->ops.i2c_gate_ctrl) | ||
221 | fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */ | ||
222 | |||
223 | if (ret) | ||
224 | dbg("%s: failed ret:%d", __func__, ret); | ||
225 | |||
226 | return ret; | ||
227 | } | ||
228 | |||
229 | static int tda18218_init(struct dvb_frontend *fe) | ||
230 | { | ||
231 | struct tda18218_priv *priv = fe->tuner_priv; | ||
232 | int ret; | ||
233 | |||
234 | /* TODO: calibrations */ | ||
235 | |||
236 | if (fe->ops.i2c_gate_ctrl) | ||
237 | fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */ | ||
238 | |||
239 | ret = tda18218_wr_regs(priv, R00_ID, priv->regs, TDA18218_NUM_REGS); | ||
240 | |||
241 | if (fe->ops.i2c_gate_ctrl) | ||
242 | fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */ | ||
243 | |||
244 | if (ret) | ||
245 | dbg("%s: failed ret:%d", __func__, ret); | ||
246 | |||
247 | return ret; | ||
248 | } | ||
249 | |||
250 | static int tda18218_release(struct dvb_frontend *fe) | ||
251 | { | ||
252 | kfree(fe->tuner_priv); | ||
253 | fe->tuner_priv = NULL; | ||
254 | return 0; | ||
255 | } | ||
256 | |||
257 | static const struct dvb_tuner_ops tda18218_tuner_ops = { | ||
258 | .info = { | ||
259 | .name = "NXP TDA18218", | ||
260 | |||
261 | .frequency_min = 174000000, | ||
262 | .frequency_max = 864000000, | ||
263 | .frequency_step = 1000, | ||
264 | }, | ||
265 | |||
266 | .release = tda18218_release, | ||
267 | .init = tda18218_init, | ||
268 | .sleep = tda18218_sleep, | ||
269 | |||
270 | .set_params = tda18218_set_params, | ||
271 | }; | ||
272 | |||
273 | struct dvb_frontend *tda18218_attach(struct dvb_frontend *fe, | ||
274 | struct i2c_adapter *i2c, struct tda18218_config *cfg) | ||
275 | { | ||
276 | struct tda18218_priv *priv = NULL; | ||
277 | u8 val; | ||
278 | int ret; | ||
279 | /* chip default registers values */ | ||
280 | static u8 def_regs[] = { | ||
281 | 0xc0, 0x88, 0x00, 0x8e, 0x03, 0x00, 0x00, 0xd0, 0x00, 0x40, | ||
282 | 0x00, 0x00, 0x07, 0xff, 0x84, 0x09, 0x00, 0x13, 0x00, 0x00, | ||
283 | 0x01, 0x84, 0x09, 0xf0, 0x19, 0x0a, 0x8e, 0x69, 0x98, 0x01, | ||
284 | 0x00, 0x58, 0x10, 0x40, 0x8c, 0x00, 0x0c, 0x48, 0x85, 0xc9, | ||
285 | 0xa7, 0x00, 0x00, 0x00, 0x30, 0x81, 0x80, 0x00, 0x39, 0x00, | ||
286 | 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xf6 | ||
287 | }; | ||
288 | |||
289 | priv = kzalloc(sizeof(struct tda18218_priv), GFP_KERNEL); | ||
290 | if (priv == NULL) | ||
291 | return NULL; | ||
292 | |||
293 | priv->cfg = cfg; | ||
294 | priv->i2c = i2c; | ||
295 | fe->tuner_priv = priv; | ||
296 | |||
297 | if (fe->ops.i2c_gate_ctrl) | ||
298 | fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */ | ||
299 | |||
300 | /* check if the tuner is there */ | ||
301 | ret = tda18218_rd_reg(priv, R00_ID, &val); | ||
302 | dbg("%s: ret:%d chip ID:%02x", __func__, ret, val); | ||
303 | if (ret || val != def_regs[R00_ID]) { | ||
304 | kfree(priv); | ||
305 | return NULL; | ||
306 | } | ||
307 | |||
308 | info("NXP TDA18218HN successfully identified."); | ||
309 | |||
310 | memcpy(&fe->ops.tuner_ops, &tda18218_tuner_ops, | ||
311 | sizeof(struct dvb_tuner_ops)); | ||
312 | memcpy(priv->regs, def_regs, sizeof(def_regs)); | ||
313 | |||
314 | /* loop-through enabled chip default register values */ | ||
315 | if (priv->cfg->loop_through) { | ||
316 | priv->regs[R17_PD1] = 0xb0; | ||
317 | priv->regs[R18_PD2] = 0x59; | ||
318 | } | ||
319 | |||
320 | /* standby */ | ||
321 | ret = tda18218_wr_reg(priv, R17_PD1, priv->regs[R17_PD1] | (1 << 0)); | ||
322 | if (ret) | ||
323 | dbg("%s: failed ret:%d", __func__, ret); | ||
324 | |||
325 | if (fe->ops.i2c_gate_ctrl) | ||
326 | fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */ | ||
327 | |||
328 | return fe; | ||
329 | } | ||
330 | EXPORT_SYMBOL(tda18218_attach); | ||
331 | |||
332 | MODULE_DESCRIPTION("NXP TDA18218HN silicon tuner driver"); | ||
333 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | ||
334 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/common/tuners/tda18218.h b/drivers/media/common/tuners/tda18218.h new file mode 100644 index 000000000000..b4180d180029 --- /dev/null +++ b/drivers/media/common/tuners/tda18218.h | |||
@@ -0,0 +1,45 @@ | |||
1 | /* | ||
2 | * NXP TDA18218HN silicon tuner driver | ||
3 | * | ||
4 | * Copyright (C) 2010 Antti Palosaari <crope@iki.fi> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef TDA18218_H | ||
22 | #define TDA18218_H | ||
23 | |||
24 | #include "dvb_frontend.h" | ||
25 | |||
26 | struct tda18218_config { | ||
27 | u8 i2c_address; | ||
28 | u8 i2c_wr_max; | ||
29 | u8 loop_through:1; | ||
30 | }; | ||
31 | |||
32 | #if defined(CONFIG_MEDIA_TUNER_TDA18218) || \ | ||
33 | (defined(CONFIG_MEDIA_TUNER_TDA18218_MODULE) && defined(MODULE)) | ||
34 | extern struct dvb_frontend *tda18218_attach(struct dvb_frontend *fe, | ||
35 | struct i2c_adapter *i2c, struct tda18218_config *cfg); | ||
36 | #else | ||
37 | static inline struct dvb_frontend *tda18218_attach(struct dvb_frontend *fe, | ||
38 | struct i2c_adapter *i2c, struct tda18218_config *cfg) | ||
39 | { | ||
40 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
41 | return NULL; | ||
42 | } | ||
43 | #endif | ||
44 | |||
45 | #endif | ||
diff --git a/drivers/media/common/tuners/tda18218_priv.h b/drivers/media/common/tuners/tda18218_priv.h new file mode 100644 index 000000000000..904e5365c78c --- /dev/null +++ b/drivers/media/common/tuners/tda18218_priv.h | |||
@@ -0,0 +1,106 @@ | |||
1 | /* | ||
2 | * NXP TDA18218HN silicon tuner driver | ||
3 | * | ||
4 | * Copyright (C) 2010 Antti Palosaari <crope@iki.fi> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef TDA18218_PRIV_H | ||
22 | #define TDA18218_PRIV_H | ||
23 | |||
24 | #define LOG_PREFIX "tda18218" | ||
25 | |||
26 | #undef dbg | ||
27 | #define dbg(f, arg...) \ | ||
28 | if (debug) \ | ||
29 | printk(KERN_DEBUG LOG_PREFIX": " f "\n" , ## arg) | ||
30 | #undef err | ||
31 | #define err(f, arg...) printk(KERN_ERR LOG_PREFIX": " f "\n" , ## arg) | ||
32 | #undef info | ||
33 | #define info(f, arg...) printk(KERN_INFO LOG_PREFIX": " f "\n" , ## arg) | ||
34 | #undef warn | ||
35 | #define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg) | ||
36 | |||
37 | #define R00_ID 0x00 /* ID byte */ | ||
38 | #define R01_R1 0x01 /* Read byte 1 */ | ||
39 | #define R02_R2 0x02 /* Read byte 2 */ | ||
40 | #define R03_R3 0x03 /* Read byte 3 */ | ||
41 | #define R04_R4 0x04 /* Read byte 4 */ | ||
42 | #define R05_R5 0x05 /* Read byte 5 */ | ||
43 | #define R06_R6 0x06 /* Read byte 6 */ | ||
44 | #define R07_MD1 0x07 /* Main divider byte 1 */ | ||
45 | #define R08_PSM1 0x08 /* PSM byte 1 */ | ||
46 | #define R09_MD2 0x09 /* Main divider byte 2 */ | ||
47 | #define R0A_MD3 0x0a /* Main divider byte 1 */ | ||
48 | #define R0B_MD4 0x0b /* Main divider byte 4 */ | ||
49 | #define R0C_MD5 0x0c /* Main divider byte 5 */ | ||
50 | #define R0D_MD6 0x0d /* Main divider byte 6 */ | ||
51 | #define R0E_MD7 0x0e /* Main divider byte 7 */ | ||
52 | #define R0F_MD8 0x0f /* Main divider byte 8 */ | ||
53 | #define R10_CD1 0x10 /* Call divider byte 1 */ | ||
54 | #define R11_CD2 0x11 /* Call divider byte 2 */ | ||
55 | #define R12_CD3 0x12 /* Call divider byte 3 */ | ||
56 | #define R13_CD4 0x13 /* Call divider byte 4 */ | ||
57 | #define R14_CD5 0x14 /* Call divider byte 5 */ | ||
58 | #define R15_CD6 0x15 /* Call divider byte 6 */ | ||
59 | #define R16_CD7 0x16 /* Call divider byte 7 */ | ||
60 | #define R17_PD1 0x17 /* Power-down byte 1 */ | ||
61 | #define R18_PD2 0x18 /* Power-down byte 2 */ | ||
62 | #define R19_XTOUT 0x19 /* XTOUT byte */ | ||
63 | #define R1A_IF1 0x1a /* IF byte 1 */ | ||
64 | #define R1B_IF2 0x1b /* IF byte 2 */ | ||
65 | #define R1C_AGC2B 0x1c /* AGC2b byte */ | ||
66 | #define R1D_PSM2 0x1d /* PSM byte 2 */ | ||
67 | #define R1E_PSM3 0x1e /* PSM byte 3 */ | ||
68 | #define R1F_PSM4 0x1f /* PSM byte 4 */ | ||
69 | #define R20_AGC11 0x20 /* AGC1 byte 1 */ | ||
70 | #define R21_AGC12 0x21 /* AGC1 byte 2 */ | ||
71 | #define R22_AGC13 0x22 /* AGC1 byte 3 */ | ||
72 | #define R23_AGC21 0x23 /* AGC2 byte 1 */ | ||
73 | #define R24_AGC22 0x24 /* AGC2 byte 2 */ | ||
74 | #define R25_AAGC 0x25 /* Analog AGC byte */ | ||
75 | #define R26_RC 0x26 /* RC byte */ | ||
76 | #define R27_RSSI 0x27 /* RSSI byte */ | ||
77 | #define R28_IRCAL1 0x28 /* IR CAL byte 1 */ | ||
78 | #define R29_IRCAL2 0x29 /* IR CAL byte 2 */ | ||
79 | #define R2A_IRCAL3 0x2a /* IR CAL byte 3 */ | ||
80 | #define R2B_IRCAL4 0x2b /* IR CAL byte 4 */ | ||
81 | #define R2C_RFCAL1 0x2c /* RF CAL byte 1 */ | ||
82 | #define R2D_RFCAL2 0x2d /* RF CAL byte 2 */ | ||
83 | #define R2E_RFCAL3 0x2e /* RF CAL byte 3 */ | ||
84 | #define R2F_RFCAL4 0x2f /* RF CAL byte 4 */ | ||
85 | #define R30_RFCAL5 0x30 /* RF CAL byte 5 */ | ||
86 | #define R31_RFCAL6 0x31 /* RF CAL byte 6 */ | ||
87 | #define R32_RFCAL7 0x32 /* RF CAL byte 7 */ | ||
88 | #define R33_RFCAL8 0x33 /* RF CAL byte 8 */ | ||
89 | #define R34_RFCAL9 0x34 /* RF CAL byte 9 */ | ||
90 | #define R35_RFCAL10 0x35 /* RF CAL byte 10 */ | ||
91 | #define R36_RFCALRAM1 0x36 /* RF CAL RAM byte 1 */ | ||
92 | #define R37_RFCALRAM2 0x37 /* RF CAL RAM byte 2 */ | ||
93 | #define R38_MARGIN 0x38 /* Margin byte */ | ||
94 | #define R39_FMAX1 0x39 /* Fmax byte 1 */ | ||
95 | #define R3A_FMAX2 0x3a /* Fmax byte 2 */ | ||
96 | |||
97 | #define TDA18218_NUM_REGS 59 | ||
98 | |||
99 | struct tda18218_priv { | ||
100 | struct tda18218_config *cfg; | ||
101 | struct i2c_adapter *i2c; | ||
102 | |||
103 | u8 regs[TDA18218_NUM_REGS]; | ||
104 | }; | ||
105 | |||
106 | #endif | ||
diff --git a/drivers/media/common/tuners/tda18271-common.c b/drivers/media/common/tuners/tda18271-common.c index e1f678281a58..aae40e52af5b 100644 --- a/drivers/media/common/tuners/tda18271-common.c +++ b/drivers/media/common/tuners/tda18271-common.c | |||
@@ -193,25 +193,51 @@ int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len) | |||
193 | unsigned char *regs = priv->tda18271_regs; | 193 | unsigned char *regs = priv->tda18271_regs; |
194 | unsigned char buf[TDA18271_NUM_REGS + 1]; | 194 | unsigned char buf[TDA18271_NUM_REGS + 1]; |
195 | struct i2c_msg msg = { .addr = priv->i2c_props.addr, .flags = 0, | 195 | struct i2c_msg msg = { .addr = priv->i2c_props.addr, .flags = 0, |
196 | .buf = buf, .len = len + 1 }; | 196 | .buf = buf }; |
197 | int i, ret; | 197 | int i, ret = 1, max; |
198 | 198 | ||
199 | BUG_ON((len == 0) || (idx + len > sizeof(buf))); | 199 | BUG_ON((len == 0) || (idx + len > sizeof(buf))); |
200 | 200 | ||
201 | buf[0] = idx; | 201 | |
202 | for (i = 1; i <= len; i++) | 202 | switch (priv->small_i2c) { |
203 | buf[i] = regs[idx - 1 + i]; | 203 | case TDA18271_03_BYTE_CHUNK_INIT: |
204 | max = 3; | ||
205 | break; | ||
206 | case TDA18271_08_BYTE_CHUNK_INIT: | ||
207 | max = 8; | ||
208 | break; | ||
209 | case TDA18271_16_BYTE_CHUNK_INIT: | ||
210 | max = 16; | ||
211 | break; | ||
212 | case TDA18271_39_BYTE_CHUNK_INIT: | ||
213 | default: | ||
214 | max = 39; | ||
215 | } | ||
204 | 216 | ||
205 | tda18271_i2c_gate_ctrl(fe, 1); | 217 | tda18271_i2c_gate_ctrl(fe, 1); |
218 | while (len) { | ||
219 | if (max > len) | ||
220 | max = len; | ||
221 | |||
222 | buf[0] = idx; | ||
223 | for (i = 1; i <= max; i++) | ||
224 | buf[i] = regs[idx - 1 + i]; | ||
206 | 225 | ||
207 | /* write registers */ | 226 | msg.len = max + 1; |
208 | ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); | ||
209 | 227 | ||
228 | /* write registers */ | ||
229 | ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); | ||
230 | if (ret != 1) | ||
231 | break; | ||
232 | |||
233 | idx += max; | ||
234 | len -= max; | ||
235 | } | ||
210 | tda18271_i2c_gate_ctrl(fe, 0); | 236 | tda18271_i2c_gate_ctrl(fe, 0); |
211 | 237 | ||
212 | if (ret != 1) | 238 | if (ret != 1) |
213 | tda_err("ERROR: idx = 0x%x, len = %d, " | 239 | tda_err("ERROR: idx = 0x%x, len = %d, " |
214 | "i2c_transfer returned: %d\n", idx, len, ret); | 240 | "i2c_transfer returned: %d\n", idx, max, ret); |
215 | 241 | ||
216 | return (ret == 1 ? 0 : ret); | 242 | return (ret == 1 ? 0 : ret); |
217 | } | 243 | } |
@@ -326,24 +352,7 @@ int tda18271_init_regs(struct dvb_frontend *fe) | |||
326 | regs[R_EB22] = 0x48; | 352 | regs[R_EB22] = 0x48; |
327 | regs[R_EB23] = 0xb0; | 353 | regs[R_EB23] = 0xb0; |
328 | 354 | ||
329 | switch (priv->small_i2c) { | 355 | tda18271_write_regs(fe, 0x00, TDA18271_NUM_REGS); |
330 | case TDA18271_08_BYTE_CHUNK_INIT: | ||
331 | tda18271_write_regs(fe, 0x00, 0x08); | ||
332 | tda18271_write_regs(fe, 0x08, 0x08); | ||
333 | tda18271_write_regs(fe, 0x10, 0x08); | ||
334 | tda18271_write_regs(fe, 0x18, 0x08); | ||
335 | tda18271_write_regs(fe, 0x20, 0x07); | ||
336 | break; | ||
337 | case TDA18271_16_BYTE_CHUNK_INIT: | ||
338 | tda18271_write_regs(fe, 0x00, 0x10); | ||
339 | tda18271_write_regs(fe, 0x10, 0x10); | ||
340 | tda18271_write_regs(fe, 0x20, 0x07); | ||
341 | break; | ||
342 | case TDA18271_39_BYTE_CHUNK_INIT: | ||
343 | default: | ||
344 | tda18271_write_regs(fe, 0x00, TDA18271_NUM_REGS); | ||
345 | break; | ||
346 | } | ||
347 | 356 | ||
348 | /* setup agc1 gain */ | 357 | /* setup agc1 gain */ |
349 | regs[R_EB17] = 0x00; | 358 | regs[R_EB17] = 0x00; |
@@ -524,16 +533,7 @@ int tda18271_calc_main_pll(struct dvb_frontend *fe, u32 freq) | |||
524 | if (tda_fail(ret)) | 533 | if (tda_fail(ret)) |
525 | goto fail; | 534 | goto fail; |
526 | 535 | ||
527 | regs[R_MPD] = (0x77 & pd); | 536 | regs[R_MPD] = (0x7f & pd); |
528 | |||
529 | switch (priv->mode) { | ||
530 | case TDA18271_ANALOG: | ||
531 | regs[R_MPD] &= ~0x08; | ||
532 | break; | ||
533 | case TDA18271_DIGITAL: | ||
534 | regs[R_MPD] |= 0x08; | ||
535 | break; | ||
536 | } | ||
537 | 537 | ||
538 | div = ((d * (freq / 1000)) << 7) / 125; | 538 | div = ((d * (freq / 1000)) << 7) / 125; |
539 | 539 | ||
diff --git a/drivers/media/common/tuners/tda18271-fe.c b/drivers/media/common/tuners/tda18271-fe.c index 7955e49a3440..57022e88e338 100644 --- a/drivers/media/common/tuners/tda18271-fe.c +++ b/drivers/media/common/tuners/tda18271-fe.c | |||
@@ -579,8 +579,8 @@ static int tda18271_rf_tracking_filters_init(struct dvb_frontend *fe, u32 freq) | |||
579 | #define RF3 2 | 579 | #define RF3 2 |
580 | u32 rf_default[3]; | 580 | u32 rf_default[3]; |
581 | u32 rf_freq[3]; | 581 | u32 rf_freq[3]; |
582 | u8 prog_cal[3]; | 582 | s32 prog_cal[3]; |
583 | u8 prog_tab[3]; | 583 | s32 prog_tab[3]; |
584 | 584 | ||
585 | i = tda18271_lookup_rf_band(fe, &freq, NULL); | 585 | i = tda18271_lookup_rf_band(fe, &freq, NULL); |
586 | 586 | ||
@@ -602,32 +602,33 @@ static int tda18271_rf_tracking_filters_init(struct dvb_frontend *fe, u32 freq) | |||
602 | return bcal; | 602 | return bcal; |
603 | 603 | ||
604 | tda18271_calc_rf_cal(fe, &rf_freq[rf]); | 604 | tda18271_calc_rf_cal(fe, &rf_freq[rf]); |
605 | prog_tab[rf] = regs[R_EB14]; | 605 | prog_tab[rf] = (s32)regs[R_EB14]; |
606 | 606 | ||
607 | if (1 == bcal) | 607 | if (1 == bcal) |
608 | prog_cal[rf] = tda18271_calibrate_rf(fe, rf_freq[rf]); | 608 | prog_cal[rf] = |
609 | (s32)tda18271_calibrate_rf(fe, rf_freq[rf]); | ||
609 | else | 610 | else |
610 | prog_cal[rf] = prog_tab[rf]; | 611 | prog_cal[rf] = prog_tab[rf]; |
611 | 612 | ||
612 | switch (rf) { | 613 | switch (rf) { |
613 | case RF1: | 614 | case RF1: |
614 | map[i].rf_a1 = 0; | 615 | map[i].rf_a1 = 0; |
615 | map[i].rf_b1 = (s32)(prog_cal[RF1] - prog_tab[RF1]); | 616 | map[i].rf_b1 = (prog_cal[RF1] - prog_tab[RF1]); |
616 | map[i].rf1 = rf_freq[RF1] / 1000; | 617 | map[i].rf1 = rf_freq[RF1] / 1000; |
617 | break; | 618 | break; |
618 | case RF2: | 619 | case RF2: |
619 | dividend = (s32)(prog_cal[RF2] - prog_tab[RF2]) - | 620 | dividend = (prog_cal[RF2] - prog_tab[RF2] - |
620 | (s32)(prog_cal[RF1] + prog_tab[RF1]); | 621 | prog_cal[RF1] + prog_tab[RF1]); |
621 | divisor = (s32)(rf_freq[RF2] - rf_freq[RF1]) / 1000; | 622 | divisor = (s32)(rf_freq[RF2] - rf_freq[RF1]) / 1000; |
622 | map[i].rf_a1 = (dividend / divisor); | 623 | map[i].rf_a1 = (dividend / divisor); |
623 | map[i].rf2 = rf_freq[RF2] / 1000; | 624 | map[i].rf2 = rf_freq[RF2] / 1000; |
624 | break; | 625 | break; |
625 | case RF3: | 626 | case RF3: |
626 | dividend = (s32)(prog_cal[RF3] - prog_tab[RF3]) - | 627 | dividend = (prog_cal[RF3] - prog_tab[RF3] - |
627 | (s32)(prog_cal[RF2] + prog_tab[RF2]); | 628 | prog_cal[RF2] + prog_tab[RF2]); |
628 | divisor = (s32)(rf_freq[RF3] - rf_freq[RF2]) / 1000; | 629 | divisor = (s32)(rf_freq[RF3] - rf_freq[RF2]) / 1000; |
629 | map[i].rf_a2 = (dividend / divisor); | 630 | map[i].rf_a2 = (dividend / divisor); |
630 | map[i].rf_b2 = (s32)(prog_cal[RF2] - prog_tab[RF2]); | 631 | map[i].rf_b2 = (prog_cal[RF2] - prog_tab[RF2]); |
631 | map[i].rf3 = rf_freq[RF3] / 1000; | 632 | map[i].rf3 = rf_freq[RF3] / 1000; |
632 | break; | 633 | break; |
633 | default: | 634 | default: |
@@ -975,6 +976,10 @@ static int tda18271_set_params(struct dvb_frontend *fe, | |||
975 | tda_warn("bandwidth not set!\n"); | 976 | tda_warn("bandwidth not set!\n"); |
976 | return -EINVAL; | 977 | return -EINVAL; |
977 | } | 978 | } |
979 | } else if (fe->ops.info.type == FE_QAM) { | ||
980 | /* DVB-C */ | ||
981 | map = &std_map->qam_8; | ||
982 | bw = 8000000; | ||
978 | } else { | 983 | } else { |
979 | tda_warn("modulation type not supported!\n"); | 984 | tda_warn("modulation type not supported!\n"); |
980 | return -EINVAL; | 985 | return -EINVAL; |
@@ -1156,7 +1161,6 @@ static int tda18271_get_id(struct dvb_frontend *fe) | |||
1156 | struct tda18271_priv *priv = fe->tuner_priv; | 1161 | struct tda18271_priv *priv = fe->tuner_priv; |
1157 | unsigned char *regs = priv->tda18271_regs; | 1162 | unsigned char *regs = priv->tda18271_regs; |
1158 | char *name; | 1163 | char *name; |
1159 | int ret = 0; | ||
1160 | 1164 | ||
1161 | mutex_lock(&priv->lock); | 1165 | mutex_lock(&priv->lock); |
1162 | tda18271_read_regs(fe); | 1166 | tda18271_read_regs(fe); |
@@ -1172,17 +1176,16 @@ static int tda18271_get_id(struct dvb_frontend *fe) | |||
1172 | priv->id = TDA18271HDC2; | 1176 | priv->id = TDA18271HDC2; |
1173 | break; | 1177 | break; |
1174 | default: | 1178 | default: |
1175 | name = "Unknown device"; | 1179 | tda_info("Unknown device (%i) detected @ %d-%04x, device not supported.\n", |
1176 | ret = -EINVAL; | 1180 | regs[R_ID], i2c_adapter_id(priv->i2c_props.adap), |
1177 | break; | 1181 | priv->i2c_props.addr); |
1182 | return -EINVAL; | ||
1178 | } | 1183 | } |
1179 | 1184 | ||
1180 | tda_info("%s detected @ %d-%04x%s\n", name, | 1185 | tda_info("%s detected @ %d-%04x\n", name, |
1181 | i2c_adapter_id(priv->i2c_props.adap), | 1186 | i2c_adapter_id(priv->i2c_props.adap), priv->i2c_props.addr); |
1182 | priv->i2c_props.addr, | ||
1183 | (0 == ret) ? "" : ", device not supported."); | ||
1184 | 1187 | ||
1185 | return ret; | 1188 | return 0; |
1186 | } | 1189 | } |
1187 | 1190 | ||
1188 | static int tda18271_setup_configuration(struct dvb_frontend *fe, | 1191 | static int tda18271_setup_configuration(struct dvb_frontend *fe, |
diff --git a/drivers/media/common/tuners/tda18271-maps.c b/drivers/media/common/tuners/tda18271-maps.c index e7f84c705da8..3d5b6ab7e332 100644 --- a/drivers/media/common/tuners/tda18271-maps.c +++ b/drivers/media/common/tuners/tda18271-maps.c | |||
@@ -229,8 +229,7 @@ static struct tda18271_map tda18271c2_km[] = { | |||
229 | static struct tda18271_map tda18271_rf_band[] = { | 229 | static struct tda18271_map tda18271_rf_band[] = { |
230 | { .rfmax = 47900, .val = 0x00 }, | 230 | { .rfmax = 47900, .val = 0x00 }, |
231 | { .rfmax = 61100, .val = 0x01 }, | 231 | { .rfmax = 61100, .val = 0x01 }, |
232 | /* { .rfmax = 152600, .val = 0x02 }, */ | 232 | { .rfmax = 152600, .val = 0x02 }, |
233 | { .rfmax = 121200, .val = 0x02 }, | ||
234 | { .rfmax = 164700, .val = 0x03 }, | 233 | { .rfmax = 164700, .val = 0x03 }, |
235 | { .rfmax = 203500, .val = 0x04 }, | 234 | { .rfmax = 203500, .val = 0x04 }, |
236 | { .rfmax = 457800, .val = 0x05 }, | 235 | { .rfmax = 457800, .val = 0x05 }, |
@@ -448,7 +447,7 @@ static struct tda18271_map tda18271c2_rf_cal[] = { | |||
448 | { .rfmax = 150000, .val = 0xb0 }, | 447 | { .rfmax = 150000, .val = 0xb0 }, |
449 | { .rfmax = 151000, .val = 0xb1 }, | 448 | { .rfmax = 151000, .val = 0xb1 }, |
450 | { .rfmax = 152000, .val = 0xb7 }, | 449 | { .rfmax = 152000, .val = 0xb7 }, |
451 | { .rfmax = 153000, .val = 0xbd }, | 450 | { .rfmax = 152600, .val = 0xbd }, |
452 | { .rfmax = 154000, .val = 0x20 }, | 451 | { .rfmax = 154000, .val = 0x20 }, |
453 | { .rfmax = 155000, .val = 0x22 }, | 452 | { .rfmax = 155000, .val = 0x22 }, |
454 | { .rfmax = 156000, .val = 0x24 }, | 453 | { .rfmax = 156000, .val = 0x24 }, |
@@ -459,7 +458,7 @@ static struct tda18271_map tda18271c2_rf_cal[] = { | |||
459 | { .rfmax = 161000, .val = 0x2d }, | 458 | { .rfmax = 161000, .val = 0x2d }, |
460 | { .rfmax = 163000, .val = 0x2e }, | 459 | { .rfmax = 163000, .val = 0x2e }, |
461 | { .rfmax = 164000, .val = 0x2f }, | 460 | { .rfmax = 164000, .val = 0x2f }, |
462 | { .rfmax = 165000, .val = 0x30 }, | 461 | { .rfmax = 164700, .val = 0x30 }, |
463 | { .rfmax = 166000, .val = 0x11 }, | 462 | { .rfmax = 166000, .val = 0x11 }, |
464 | { .rfmax = 167000, .val = 0x12 }, | 463 | { .rfmax = 167000, .val = 0x12 }, |
465 | { .rfmax = 168000, .val = 0x13 }, | 464 | { .rfmax = 168000, .val = 0x13 }, |
@@ -510,7 +509,8 @@ static struct tda18271_map tda18271c2_rf_cal[] = { | |||
510 | { .rfmax = 236000, .val = 0x1b }, | 509 | { .rfmax = 236000, .val = 0x1b }, |
511 | { .rfmax = 237000, .val = 0x1c }, | 510 | { .rfmax = 237000, .val = 0x1c }, |
512 | { .rfmax = 240000, .val = 0x1d }, | 511 | { .rfmax = 240000, .val = 0x1d }, |
513 | { .rfmax = 242000, .val = 0x1f }, | 512 | { .rfmax = 242000, .val = 0x1e }, |
513 | { .rfmax = 244000, .val = 0x1f }, | ||
514 | { .rfmax = 247000, .val = 0x20 }, | 514 | { .rfmax = 247000, .val = 0x20 }, |
515 | { .rfmax = 249000, .val = 0x21 }, | 515 | { .rfmax = 249000, .val = 0x21 }, |
516 | { .rfmax = 252000, .val = 0x22 }, | 516 | { .rfmax = 252000, .val = 0x22 }, |
@@ -624,7 +624,7 @@ static struct tda18271_map tda18271c2_rf_cal[] = { | |||
624 | { .rfmax = 453000, .val = 0x93 }, | 624 | { .rfmax = 453000, .val = 0x93 }, |
625 | { .rfmax = 454000, .val = 0x94 }, | 625 | { .rfmax = 454000, .val = 0x94 }, |
626 | { .rfmax = 456000, .val = 0x96 }, | 626 | { .rfmax = 456000, .val = 0x96 }, |
627 | { .rfmax = 457000, .val = 0x98 }, | 627 | { .rfmax = 457800, .val = 0x98 }, |
628 | { .rfmax = 461000, .val = 0x11 }, | 628 | { .rfmax = 461000, .val = 0x11 }, |
629 | { .rfmax = 468000, .val = 0x12 }, | 629 | { .rfmax = 468000, .val = 0x12 }, |
630 | { .rfmax = 472000, .val = 0x13 }, | 630 | { .rfmax = 472000, .val = 0x13 }, |
diff --git a/drivers/media/common/tuners/tda18271.h b/drivers/media/common/tuners/tda18271.h index d7fcc36dc6e6..50cfa8cebb93 100644 --- a/drivers/media/common/tuners/tda18271.h +++ b/drivers/media/common/tuners/tda18271.h | |||
@@ -80,8 +80,9 @@ enum tda18271_output_options { | |||
80 | 80 | ||
81 | enum tda18271_small_i2c { | 81 | enum tda18271_small_i2c { |
82 | TDA18271_39_BYTE_CHUNK_INIT = 0, | 82 | TDA18271_39_BYTE_CHUNK_INIT = 0, |
83 | TDA18271_16_BYTE_CHUNK_INIT = 1, | 83 | TDA18271_16_BYTE_CHUNK_INIT = 16, |
84 | TDA18271_08_BYTE_CHUNK_INIT = 2, | 84 | TDA18271_08_BYTE_CHUNK_INIT = 8, |
85 | TDA18271_03_BYTE_CHUNK_INIT = 3, | ||
85 | }; | 86 | }; |
86 | 87 | ||
87 | struct tda18271_config { | 88 | struct tda18271_config { |
@@ -97,7 +98,7 @@ struct tda18271_config { | |||
97 | /* output options that can be disabled */ | 98 | /* output options that can be disabled */ |
98 | enum tda18271_output_options output_opt; | 99 | enum tda18271_output_options output_opt; |
99 | 100 | ||
100 | /* some i2c providers cant write all 39 registers at once */ | 101 | /* some i2c providers can't write all 39 registers at once */ |
101 | enum tda18271_small_i2c small_i2c; | 102 | enum tda18271_small_i2c small_i2c; |
102 | 103 | ||
103 | /* force rf tracking filter calibration on startup */ | 104 | /* force rf tracking filter calibration on startup */ |
diff --git a/drivers/media/common/tuners/tda8290.c b/drivers/media/common/tuners/tda8290.c index c9062ceddc71..8c4852114eeb 100644 --- a/drivers/media/common/tuners/tda8290.c +++ b/drivers/media/common/tuners/tda8290.c | |||
@@ -95,8 +95,7 @@ static int tda8295_i2c_bridge(struct dvb_frontend *fe, int close) | |||
95 | msleep(20); | 95 | msleep(20); |
96 | } else { | 96 | } else { |
97 | msg = disable; | 97 | msg = disable; |
98 | tuner_i2c_xfer_send(&priv->i2c_props, msg, 1); | 98 | tuner_i2c_xfer_send_recv(&priv->i2c_props, msg, 1, &msg[1], 1); |
99 | tuner_i2c_xfer_recv(&priv->i2c_props, &msg[1], 1); | ||
100 | 99 | ||
101 | buf[2] = msg[1]; | 100 | buf[2] = msg[1]; |
102 | buf[2] &= ~0x04; | 101 | buf[2] &= ~0x04; |
@@ -233,19 +232,22 @@ static void tda8290_set_params(struct dvb_frontend *fe, | |||
233 | tuner_i2c_xfer_send(&priv->i2c_props, pll_bw_nom, 2); | 232 | tuner_i2c_xfer_send(&priv->i2c_props, pll_bw_nom, 2); |
234 | } | 233 | } |
235 | 234 | ||
235 | |||
236 | tda8290_i2c_bridge(fe, 1); | 236 | tda8290_i2c_bridge(fe, 1); |
237 | 237 | ||
238 | if (fe->ops.tuner_ops.set_analog_params) | 238 | if (fe->ops.tuner_ops.set_analog_params) |
239 | fe->ops.tuner_ops.set_analog_params(fe, params); | 239 | fe->ops.tuner_ops.set_analog_params(fe, params); |
240 | 240 | ||
241 | for (i = 0; i < 3; i++) { | 241 | for (i = 0; i < 3; i++) { |
242 | tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1); | 242 | tuner_i2c_xfer_send_recv(&priv->i2c_props, |
243 | tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1); | 243 | &addr_pll_stat, 1, &pll_stat, 1); |
244 | if (pll_stat & 0x80) { | 244 | if (pll_stat & 0x80) { |
245 | tuner_i2c_xfer_send(&priv->i2c_props, &addr_adc_sat, 1); | 245 | tuner_i2c_xfer_send_recv(&priv->i2c_props, |
246 | tuner_i2c_xfer_recv(&priv->i2c_props, &adc_sat, 1); | 246 | &addr_adc_sat, 1, |
247 | tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1); | 247 | &adc_sat, 1); |
248 | tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1); | 248 | tuner_i2c_xfer_send_recv(&priv->i2c_props, |
249 | &addr_agc_stat, 1, | ||
250 | &agc_stat, 1); | ||
249 | tuner_dbg("tda8290 is locked, AGC: %d\n", agc_stat); | 251 | tuner_dbg("tda8290 is locked, AGC: %d\n", agc_stat); |
250 | break; | 252 | break; |
251 | } else { | 253 | } else { |
@@ -259,20 +261,22 @@ static void tda8290_set_params(struct dvb_frontend *fe, | |||
259 | agc_stat, adc_sat, pll_stat & 0x80); | 261 | agc_stat, adc_sat, pll_stat & 0x80); |
260 | tuner_i2c_xfer_send(&priv->i2c_props, gainset_2, 2); | 262 | tuner_i2c_xfer_send(&priv->i2c_props, gainset_2, 2); |
261 | msleep(100); | 263 | msleep(100); |
262 | tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1); | 264 | tuner_i2c_xfer_send_recv(&priv->i2c_props, |
263 | tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1); | 265 | &addr_agc_stat, 1, &agc_stat, 1); |
264 | tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1); | 266 | tuner_i2c_xfer_send_recv(&priv->i2c_props, |
265 | tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1); | 267 | &addr_pll_stat, 1, &pll_stat, 1); |
266 | if ((agc_stat > 115) || !(pll_stat & 0x80)) { | 268 | if ((agc_stat > 115) || !(pll_stat & 0x80)) { |
267 | tuner_dbg("adjust gain, step 2. Agc: %d, lock: %d\n", | 269 | tuner_dbg("adjust gain, step 2. Agc: %d, lock: %d\n", |
268 | agc_stat, pll_stat & 0x80); | 270 | agc_stat, pll_stat & 0x80); |
269 | if (priv->cfg.agcf) | 271 | if (priv->cfg.agcf) |
270 | priv->cfg.agcf(fe); | 272 | priv->cfg.agcf(fe); |
271 | msleep(100); | 273 | msleep(100); |
272 | tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1); | 274 | tuner_i2c_xfer_send_recv(&priv->i2c_props, |
273 | tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1); | 275 | &addr_agc_stat, 1, |
274 | tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1); | 276 | &agc_stat, 1); |
275 | tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1); | 277 | tuner_i2c_xfer_send_recv(&priv->i2c_props, |
278 | &addr_pll_stat, 1, | ||
279 | &pll_stat, 1); | ||
276 | if((agc_stat > 115) || !(pll_stat & 0x80)) { | 280 | if((agc_stat > 115) || !(pll_stat & 0x80)) { |
277 | tuner_dbg("adjust gain, step 3. Agc: %d\n", agc_stat); | 281 | tuner_dbg("adjust gain, step 3. Agc: %d\n", agc_stat); |
278 | tuner_i2c_xfer_send(&priv->i2c_props, adc_head_12, 2); | 282 | tuner_i2c_xfer_send(&priv->i2c_props, adc_head_12, 2); |
@@ -284,10 +288,12 @@ static void tda8290_set_params(struct dvb_frontend *fe, | |||
284 | 288 | ||
285 | /* l/ l' deadlock? */ | 289 | /* l/ l' deadlock? */ |
286 | if(priv->tda8290_easy_mode & 0x60) { | 290 | if(priv->tda8290_easy_mode & 0x60) { |
287 | tuner_i2c_xfer_send(&priv->i2c_props, &addr_adc_sat, 1); | 291 | tuner_i2c_xfer_send_recv(&priv->i2c_props, |
288 | tuner_i2c_xfer_recv(&priv->i2c_props, &adc_sat, 1); | 292 | &addr_adc_sat, 1, |
289 | tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1); | 293 | &adc_sat, 1); |
290 | tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1); | 294 | tuner_i2c_xfer_send_recv(&priv->i2c_props, |
295 | &addr_pll_stat, 1, | ||
296 | &pll_stat, 1); | ||
291 | if ((adc_sat > 20) || !(pll_stat & 0x80)) { | 297 | if ((adc_sat > 20) || !(pll_stat & 0x80)) { |
292 | tuner_dbg("trying to resolve SECAM L deadlock\n"); | 298 | tuner_dbg("trying to resolve SECAM L deadlock\n"); |
293 | tuner_i2c_xfer_send(&priv->i2c_props, agc_rst_on, 2); | 299 | tuner_i2c_xfer_send(&priv->i2c_props, agc_rst_on, 2); |
@@ -307,8 +313,7 @@ static void tda8295_power(struct dvb_frontend *fe, int enable) | |||
307 | struct tda8290_priv *priv = fe->analog_demod_priv; | 313 | struct tda8290_priv *priv = fe->analog_demod_priv; |
308 | unsigned char buf[] = { 0x30, 0x00 }; /* clb_stdbt */ | 314 | unsigned char buf[] = { 0x30, 0x00 }; /* clb_stdbt */ |
309 | 315 | ||
310 | tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1); | 316 | tuner_i2c_xfer_send_recv(&priv->i2c_props, &buf[0], 1, &buf[1], 1); |
311 | tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1); | ||
312 | 317 | ||
313 | if (enable) | 318 | if (enable) |
314 | buf[1] = 0x01; | 319 | buf[1] = 0x01; |
@@ -323,8 +328,7 @@ static void tda8295_set_easy_mode(struct dvb_frontend *fe, int enable) | |||
323 | struct tda8290_priv *priv = fe->analog_demod_priv; | 328 | struct tda8290_priv *priv = fe->analog_demod_priv; |
324 | unsigned char buf[] = { 0x01, 0x00 }; | 329 | unsigned char buf[] = { 0x01, 0x00 }; |
325 | 330 | ||
326 | tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1); | 331 | tuner_i2c_xfer_send_recv(&priv->i2c_props, &buf[0], 1, &buf[1], 1); |
327 | tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1); | ||
328 | 332 | ||
329 | if (enable) | 333 | if (enable) |
330 | buf[1] = 0x01; /* rising edge sets regs 0x02 - 0x23 */ | 334 | buf[1] = 0x01; /* rising edge sets regs 0x02 - 0x23 */ |
@@ -353,8 +357,7 @@ static void tda8295_agc1_out(struct dvb_frontend *fe, int enable) | |||
353 | struct tda8290_priv *priv = fe->analog_demod_priv; | 357 | struct tda8290_priv *priv = fe->analog_demod_priv; |
354 | unsigned char buf[] = { 0x02, 0x00 }; /* DIV_FUNC */ | 358 | unsigned char buf[] = { 0x02, 0x00 }; /* DIV_FUNC */ |
355 | 359 | ||
356 | tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1); | 360 | tuner_i2c_xfer_send_recv(&priv->i2c_props, &buf[0], 1, &buf[1], 1); |
357 | tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1); | ||
358 | 361 | ||
359 | if (enable) | 362 | if (enable) |
360 | buf[1] &= ~0x40; | 363 | buf[1] &= ~0x40; |
@@ -370,10 +373,10 @@ static void tda8295_agc2_out(struct dvb_frontend *fe, int enable) | |||
370 | unsigned char set_gpio_cf[] = { 0x44, 0x00 }; | 373 | unsigned char set_gpio_cf[] = { 0x44, 0x00 }; |
371 | unsigned char set_gpio_val[] = { 0x46, 0x00 }; | 374 | unsigned char set_gpio_val[] = { 0x46, 0x00 }; |
372 | 375 | ||
373 | tuner_i2c_xfer_send(&priv->i2c_props, &set_gpio_cf[0], 1); | 376 | tuner_i2c_xfer_send_recv(&priv->i2c_props, |
374 | tuner_i2c_xfer_recv(&priv->i2c_props, &set_gpio_cf[1], 1); | 377 | &set_gpio_cf[0], 1, &set_gpio_cf[1], 1); |
375 | tuner_i2c_xfer_send(&priv->i2c_props, &set_gpio_val[0], 1); | 378 | tuner_i2c_xfer_send_recv(&priv->i2c_props, |
376 | tuner_i2c_xfer_recv(&priv->i2c_props, &set_gpio_val[1], 1); | 379 | &set_gpio_val[0], 1, &set_gpio_val[1], 1); |
377 | 380 | ||
378 | set_gpio_cf[1] &= 0xf0; /* clear GPIO_0 bits 3-0 */ | 381 | set_gpio_cf[1] &= 0xf0; /* clear GPIO_0 bits 3-0 */ |
379 | 382 | ||
@@ -392,8 +395,7 @@ static int tda8295_has_signal(struct dvb_frontend *fe) | |||
392 | unsigned char hvpll_stat = 0x26; | 395 | unsigned char hvpll_stat = 0x26; |
393 | unsigned char ret; | 396 | unsigned char ret; |
394 | 397 | ||
395 | tuner_i2c_xfer_send(&priv->i2c_props, &hvpll_stat, 1); | 398 | tuner_i2c_xfer_send_recv(&priv->i2c_props, &hvpll_stat, 1, &ret, 1); |
396 | tuner_i2c_xfer_recv(&priv->i2c_props, &ret, 1); | ||
397 | return (ret & 0x01) ? 65535 : 0; | 399 | return (ret & 0x01) ? 65535 : 0; |
398 | } | 400 | } |
399 | 401 | ||
@@ -413,8 +415,8 @@ static void tda8295_set_params(struct dvb_frontend *fe, | |||
413 | tda8295_power(fe, 1); | 415 | tda8295_power(fe, 1); |
414 | tda8295_agc1_out(fe, 1); | 416 | tda8295_agc1_out(fe, 1); |
415 | 417 | ||
416 | tuner_i2c_xfer_send(&priv->i2c_props, &blanking_mode[0], 1); | 418 | tuner_i2c_xfer_send_recv(&priv->i2c_props, |
417 | tuner_i2c_xfer_recv(&priv->i2c_props, &blanking_mode[1], 1); | 419 | &blanking_mode[0], 1, &blanking_mode[1], 1); |
418 | 420 | ||
419 | tda8295_set_video_std(fe); | 421 | tda8295_set_video_std(fe); |
420 | 422 | ||
@@ -447,8 +449,8 @@ static int tda8290_has_signal(struct dvb_frontend *fe) | |||
447 | unsigned char i2c_get_afc[1] = { 0x1B }; | 449 | unsigned char i2c_get_afc[1] = { 0x1B }; |
448 | unsigned char afc = 0; | 450 | unsigned char afc = 0; |
449 | 451 | ||
450 | tuner_i2c_xfer_send(&priv->i2c_props, i2c_get_afc, ARRAY_SIZE(i2c_get_afc)); | 452 | tuner_i2c_xfer_send_recv(&priv->i2c_props, |
451 | tuner_i2c_xfer_recv(&priv->i2c_props, &afc, 1); | 453 | i2c_get_afc, ARRAY_SIZE(i2c_get_afc), &afc, 1); |
452 | return (afc & 0x80)? 65535:0; | 454 | return (afc & 0x80)? 65535:0; |
453 | } | 455 | } |
454 | 456 | ||
@@ -654,20 +656,26 @@ static int tda829x_find_tuner(struct dvb_frontend *fe) | |||
654 | static int tda8290_probe(struct tuner_i2c_props *i2c_props) | 656 | static int tda8290_probe(struct tuner_i2c_props *i2c_props) |
655 | { | 657 | { |
656 | #define TDA8290_ID 0x89 | 658 | #define TDA8290_ID 0x89 |
657 | unsigned char tda8290_id[] = { 0x1f, 0x00 }; | 659 | u8 reg = 0x1f, id; |
660 | struct i2c_msg msg_read[] = { | ||
661 | { .addr = i2c_props->addr, .flags = 0, .len = 1, .buf = ® }, | ||
662 | { .addr = i2c_props->addr, .flags = I2C_M_RD, .len = 1, .buf = &id }, | ||
663 | }; | ||
658 | 664 | ||
659 | /* detect tda8290 */ | 665 | /* detect tda8290 */ |
660 | tuner_i2c_xfer_send(i2c_props, &tda8290_id[0], 1); | 666 | if (i2c_transfer(i2c_props->adap, msg_read, 2) != 2) { |
661 | tuner_i2c_xfer_recv(i2c_props, &tda8290_id[1], 1); | 667 | printk(KERN_WARNING "%s: couldn't read register 0x%02x\n", |
668 | __func__, reg); | ||
669 | return -ENODEV; | ||
670 | } | ||
662 | 671 | ||
663 | if (tda8290_id[1] == TDA8290_ID) { | 672 | if (id == TDA8290_ID) { |
664 | if (debug) | 673 | if (debug) |
665 | printk(KERN_DEBUG "%s: tda8290 detected @ %d-%04x\n", | 674 | printk(KERN_DEBUG "%s: tda8290 detected @ %d-%04x\n", |
666 | __func__, i2c_adapter_id(i2c_props->adap), | 675 | __func__, i2c_adapter_id(i2c_props->adap), |
667 | i2c_props->addr); | 676 | i2c_props->addr); |
668 | return 0; | 677 | return 0; |
669 | } | 678 | } |
670 | |||
671 | return -ENODEV; | 679 | return -ENODEV; |
672 | } | 680 | } |
673 | 681 | ||
@@ -675,16 +683,23 @@ static int tda8295_probe(struct tuner_i2c_props *i2c_props) | |||
675 | { | 683 | { |
676 | #define TDA8295_ID 0x8a | 684 | #define TDA8295_ID 0x8a |
677 | #define TDA8295C2_ID 0x8b | 685 | #define TDA8295C2_ID 0x8b |
678 | unsigned char tda8295_id[] = { 0x2f, 0x00 }; | 686 | u8 reg = 0x2f, id; |
687 | struct i2c_msg msg_read[] = { | ||
688 | { .addr = i2c_props->addr, .flags = 0, .len = 1, .buf = ® }, | ||
689 | { .addr = i2c_props->addr, .flags = I2C_M_RD, .len = 1, .buf = &id }, | ||
690 | }; | ||
679 | 691 | ||
680 | /* detect tda8295 */ | 692 | /* detect tda8295 */ |
681 | tuner_i2c_xfer_send(i2c_props, &tda8295_id[0], 1); | 693 | if (i2c_transfer(i2c_props->adap, msg_read, 2) != 2) { |
682 | tuner_i2c_xfer_recv(i2c_props, &tda8295_id[1], 1); | 694 | printk(KERN_WARNING "%s: couldn't read register 0x%02x\n", |
695 | __func__, reg); | ||
696 | return -ENODEV; | ||
697 | } | ||
683 | 698 | ||
684 | if ((tda8295_id[1] & 0xfe) == TDA8295_ID) { | 699 | if ((id & 0xfe) == TDA8295_ID) { |
685 | if (debug) | 700 | if (debug) |
686 | printk(KERN_DEBUG "%s: %s detected @ %d-%04x\n", | 701 | printk(KERN_DEBUG "%s: %s detected @ %d-%04x\n", |
687 | __func__, (tda8295_id[1] == TDA8295_ID) ? | 702 | __func__, (id == TDA8295_ID) ? |
688 | "tda8295c1" : "tda8295c2", | 703 | "tda8295c1" : "tda8295c2", |
689 | i2c_adapter_id(i2c_props->adap), | 704 | i2c_adapter_id(i2c_props->adap), |
690 | i2c_props->addr); | 705 | i2c_props->addr); |
@@ -740,9 +755,11 @@ struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe, | |||
740 | sizeof(struct analog_demod_ops)); | 755 | sizeof(struct analog_demod_ops)); |
741 | } | 756 | } |
742 | 757 | ||
743 | if ((!(cfg) || (TDA829X_PROBE_TUNER == cfg->probe_tuner)) && | 758 | if (!(cfg) || (TDA829X_PROBE_TUNER == cfg->probe_tuner)) { |
744 | (tda829x_find_tuner(fe) < 0)) | 759 | tda8295_power(fe, 1); |
745 | goto fail; | 760 | if (tda829x_find_tuner(fe) < 0) |
761 | goto fail; | ||
762 | } | ||
746 | 763 | ||
747 | switch (priv->ver) { | 764 | switch (priv->ver) { |
748 | case TDA8290: | 765 | case TDA8290: |
@@ -786,6 +803,8 @@ struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe, | |||
786 | return fe; | 803 | return fe; |
787 | 804 | ||
788 | fail: | 805 | fail: |
806 | memset(&fe->ops.analog_ops, 0, sizeof(struct analog_demod_ops)); | ||
807 | |||
789 | tda829x_release(fe); | 808 | tda829x_release(fe); |
790 | return NULL; | 809 | return NULL; |
791 | } | 810 | } |
@@ -809,8 +828,8 @@ int tda829x_probe(struct i2c_adapter *i2c_adap, u8 i2c_addr) | |||
809 | int i; | 828 | int i; |
810 | 829 | ||
811 | /* rule out tda9887, which would return the same byte repeatedly */ | 830 | /* rule out tda9887, which would return the same byte repeatedly */ |
812 | tuner_i2c_xfer_send(&i2c_props, soft_reset, 1); | 831 | tuner_i2c_xfer_send_recv(&i2c_props, |
813 | tuner_i2c_xfer_recv(&i2c_props, buf, PROBE_BUFFER_SIZE); | 832 | soft_reset, 1, buf, PROBE_BUFFER_SIZE); |
814 | for (i = 1; i < PROBE_BUFFER_SIZE; i++) { | 833 | for (i = 1; i < PROBE_BUFFER_SIZE; i++) { |
815 | if (buf[i] != buf[0]) | 834 | if (buf[i] != buf[0]) |
816 | break; | 835 | break; |
@@ -827,13 +846,12 @@ int tda829x_probe(struct i2c_adapter *i2c_adap, u8 i2c_addr) | |||
827 | /* fall back to old probing method */ | 846 | /* fall back to old probing method */ |
828 | tuner_i2c_xfer_send(&i2c_props, easy_mode_b, 2); | 847 | tuner_i2c_xfer_send(&i2c_props, easy_mode_b, 2); |
829 | tuner_i2c_xfer_send(&i2c_props, soft_reset, 2); | 848 | tuner_i2c_xfer_send(&i2c_props, soft_reset, 2); |
830 | tuner_i2c_xfer_send(&i2c_props, &addr_dto_lsb, 1); | 849 | tuner_i2c_xfer_send_recv(&i2c_props, &addr_dto_lsb, 1, &data, 1); |
831 | tuner_i2c_xfer_recv(&i2c_props, &data, 1); | ||
832 | if (data == 0) { | 850 | if (data == 0) { |
833 | tuner_i2c_xfer_send(&i2c_props, easy_mode_g, 2); | 851 | tuner_i2c_xfer_send(&i2c_props, easy_mode_g, 2); |
834 | tuner_i2c_xfer_send(&i2c_props, soft_reset, 2); | 852 | tuner_i2c_xfer_send(&i2c_props, soft_reset, 2); |
835 | tuner_i2c_xfer_send(&i2c_props, &addr_dto_lsb, 1); | 853 | tuner_i2c_xfer_send_recv(&i2c_props, |
836 | tuner_i2c_xfer_recv(&i2c_props, &data, 1); | 854 | &addr_dto_lsb, 1, &data, 1); |
837 | if (data == 0x7b) { | 855 | if (data == 0x7b) { |
838 | return 0; | 856 | return 0; |
839 | } | 857 | } |
diff --git a/drivers/media/common/tuners/tda9887.c b/drivers/media/common/tuners/tda9887.c index bf14bd79e2fc..cdb645d57438 100644 --- a/drivers/media/common/tuners/tda9887.c +++ b/drivers/media/common/tuners/tda9887.c | |||
@@ -36,6 +36,8 @@ struct tda9887_priv { | |||
36 | unsigned int mode; | 36 | unsigned int mode; |
37 | unsigned int audmode; | 37 | unsigned int audmode; |
38 | v4l2_std_id std; | 38 | v4l2_std_id std; |
39 | |||
40 | bool standby; | ||
39 | }; | 41 | }; |
40 | 42 | ||
41 | /* ---------------------------------------------------------------------- */ | 43 | /* ---------------------------------------------------------------------- */ |
@@ -568,7 +570,7 @@ static void tda9887_configure(struct dvb_frontend *fe) | |||
568 | tda9887_do_config(fe); | 570 | tda9887_do_config(fe); |
569 | tda9887_set_insmod(fe); | 571 | tda9887_set_insmod(fe); |
570 | 572 | ||
571 | if (priv->mode == T_STANDBY) | 573 | if (priv->standby) |
572 | priv->data[1] |= cForcedMuteAudioON; | 574 | priv->data[1] |= cForcedMuteAudioON; |
573 | 575 | ||
574 | tuner_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n", | 576 | tuner_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n", |
@@ -616,7 +618,7 @@ static void tda9887_standby(struct dvb_frontend *fe) | |||
616 | { | 618 | { |
617 | struct tda9887_priv *priv = fe->analog_demod_priv; | 619 | struct tda9887_priv *priv = fe->analog_demod_priv; |
618 | 620 | ||
619 | priv->mode = T_STANDBY; | 621 | priv->standby = true; |
620 | 622 | ||
621 | tda9887_configure(fe); | 623 | tda9887_configure(fe); |
622 | } | 624 | } |
@@ -626,6 +628,7 @@ static void tda9887_set_params(struct dvb_frontend *fe, | |||
626 | { | 628 | { |
627 | struct tda9887_priv *priv = fe->analog_demod_priv; | 629 | struct tda9887_priv *priv = fe->analog_demod_priv; |
628 | 630 | ||
631 | priv->standby = false; | ||
629 | priv->mode = params->mode; | 632 | priv->mode = params->mode; |
630 | priv->audmode = params->audmode; | 633 | priv->audmode = params->audmode; |
631 | priv->std = params->std; | 634 | priv->std = params->std; |
@@ -686,7 +689,7 @@ struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe, | |||
686 | return NULL; | 689 | return NULL; |
687 | case 1: | 690 | case 1: |
688 | fe->analog_demod_priv = priv; | 691 | fe->analog_demod_priv = priv; |
689 | priv->mode = T_STANDBY; | 692 | priv->standby = true; |
690 | tuner_info("tda988[5/6/7] found\n"); | 693 | tuner_info("tda988[5/6/7] found\n"); |
691 | break; | 694 | break; |
692 | default: | 695 | default: |
diff --git a/drivers/media/common/tuners/tea5761.c b/drivers/media/common/tuners/tea5761.c index 925399dffbed..bf78cb9fc52c 100644 --- a/drivers/media/common/tuners/tea5761.c +++ b/drivers/media/common/tuners/tea5761.c | |||
@@ -23,6 +23,7 @@ struct tea5761_priv { | |||
23 | struct tuner_i2c_props i2c_props; | 23 | struct tuner_i2c_props i2c_props; |
24 | 24 | ||
25 | u32 frequency; | 25 | u32 frequency; |
26 | bool standby; | ||
26 | }; | 27 | }; |
27 | 28 | ||
28 | /*****************************************************************************/ | 29 | /*****************************************************************************/ |
@@ -135,18 +136,19 @@ static void tea5761_status_dump(unsigned char *buffer) | |||
135 | } | 136 | } |
136 | 137 | ||
137 | /* Freq should be specifyed at 62.5 Hz */ | 138 | /* Freq should be specifyed at 62.5 Hz */ |
138 | static int set_radio_freq(struct dvb_frontend *fe, | 139 | static int __set_radio_freq(struct dvb_frontend *fe, |
139 | struct analog_parameters *params) | 140 | unsigned int freq, |
141 | bool mono) | ||
140 | { | 142 | { |
141 | struct tea5761_priv *priv = fe->tuner_priv; | 143 | struct tea5761_priv *priv = fe->tuner_priv; |
142 | unsigned int frq = params->frequency; | 144 | unsigned int frq = freq; |
143 | unsigned char buffer[7] = {0, 0, 0, 0, 0, 0, 0 }; | 145 | unsigned char buffer[7] = {0, 0, 0, 0, 0, 0, 0 }; |
144 | unsigned div; | 146 | unsigned div; |
145 | int rc; | 147 | int rc; |
146 | 148 | ||
147 | tuner_dbg("radio freq counter %d\n", frq); | 149 | tuner_dbg("radio freq counter %d\n", frq); |
148 | 150 | ||
149 | if (params->mode == T_STANDBY) { | 151 | if (priv->standby) { |
150 | tuner_dbg("TEA5761 set to standby mode\n"); | 152 | tuner_dbg("TEA5761 set to standby mode\n"); |
151 | buffer[5] |= TEA5761_TNCTRL_MU; | 153 | buffer[5] |= TEA5761_TNCTRL_MU; |
152 | } else { | 154 | } else { |
@@ -154,7 +156,7 @@ static int set_radio_freq(struct dvb_frontend *fe, | |||
154 | } | 156 | } |
155 | 157 | ||
156 | 158 | ||
157 | if (params->audmode == V4L2_TUNER_MODE_MONO) { | 159 | if (mono) { |
158 | tuner_dbg("TEA5761 set to mono\n"); | 160 | tuner_dbg("TEA5761 set to mono\n"); |
159 | buffer[5] |= TEA5761_TNCTRL_MST; | 161 | buffer[5] |= TEA5761_TNCTRL_MST; |
160 | } else { | 162 | } else { |
@@ -176,6 +178,26 @@ static int set_radio_freq(struct dvb_frontend *fe, | |||
176 | return 0; | 178 | return 0; |
177 | } | 179 | } |
178 | 180 | ||
181 | static int set_radio_freq(struct dvb_frontend *fe, | ||
182 | struct analog_parameters *params) | ||
183 | { | ||
184 | struct tea5761_priv *priv = fe->analog_demod_priv; | ||
185 | |||
186 | priv->standby = false; | ||
187 | |||
188 | return __set_radio_freq(fe, params->frequency, | ||
189 | params->audmode == V4L2_TUNER_MODE_MONO); | ||
190 | } | ||
191 | |||
192 | static int set_radio_sleep(struct dvb_frontend *fe) | ||
193 | { | ||
194 | struct tea5761_priv *priv = fe->analog_demod_priv; | ||
195 | |||
196 | priv->standby = true; | ||
197 | |||
198 | return __set_radio_freq(fe, priv->frequency, false); | ||
199 | } | ||
200 | |||
179 | static int tea5761_read_status(struct dvb_frontend *fe, char *buffer) | 201 | static int tea5761_read_status(struct dvb_frontend *fe, char *buffer) |
180 | { | 202 | { |
181 | struct tea5761_priv *priv = fe->tuner_priv; | 203 | struct tea5761_priv *priv = fe->tuner_priv; |
@@ -284,6 +306,7 @@ static struct dvb_tuner_ops tea5761_tuner_ops = { | |||
284 | .name = "tea5761", // Philips TEA5761HN FM Radio | 306 | .name = "tea5761", // Philips TEA5761HN FM Radio |
285 | }, | 307 | }, |
286 | .set_analog_params = set_radio_freq, | 308 | .set_analog_params = set_radio_freq, |
309 | .sleep = set_radio_sleep, | ||
287 | .release = tea5761_release, | 310 | .release = tea5761_release, |
288 | .get_frequency = tea5761_get_frequency, | 311 | .get_frequency = tea5761_get_frequency, |
289 | .get_status = tea5761_get_status, | 312 | .get_status = tea5761_get_status, |
diff --git a/drivers/media/common/tuners/tuner-types.c b/drivers/media/common/tuners/tuner-types.c index 58a513bcd747..afba6dc5e080 100644 --- a/drivers/media/common/tuners/tuner-types.c +++ b/drivers/media/common/tuners/tuner-types.c | |||
@@ -971,6 +971,22 @@ static struct tuner_params tuner_tena_9533_di_params[] = { | |||
971 | }, | 971 | }, |
972 | }; | 972 | }; |
973 | 973 | ||
974 | /* ------------ TUNER_TENA_TNF_5337 - Tena tnf5337MFD STD M/N ------------ */ | ||
975 | |||
976 | static struct tuner_range tuner_tena_tnf_5337_ntsc_ranges[] = { | ||
977 | { 16 * 166.25 /*MHz*/, 0x86, 0x01, }, | ||
978 | { 16 * 466.25 /*MHz*/, 0x86, 0x02, }, | ||
979 | { 16 * 999.99 , 0x86, 0x08, }, | ||
980 | }; | ||
981 | |||
982 | static struct tuner_params tuner_tena_tnf_5337_params[] = { | ||
983 | { | ||
984 | .type = TUNER_PARAM_TYPE_NTSC, | ||
985 | .ranges = tuner_tena_tnf_5337_ntsc_ranges, | ||
986 | .count = ARRAY_SIZE(tuner_tena_tnf_5337_ntsc_ranges), | ||
987 | }, | ||
988 | }; | ||
989 | |||
974 | /* ------------ TUNER_PHILIPS_FMD1216ME(X)_MK3 - Philips PAL ------------ */ | 990 | /* ------------ TUNER_PHILIPS_FMD1216ME(X)_MK3 - Philips PAL ------------ */ |
975 | 991 | ||
976 | static struct tuner_range tuner_philips_fmd1216me_mk3_pal_ranges[] = { | 992 | static struct tuner_range tuner_philips_fmd1216me_mk3_pal_ranges[] = { |
@@ -1842,6 +1858,11 @@ struct tunertype tuners[] = { | |||
1842 | .params = tuner_philips_fq1236_mk5_params, | 1858 | .params = tuner_philips_fq1236_mk5_params, |
1843 | .count = ARRAY_SIZE(tuner_philips_fq1236_mk5_params), | 1859 | .count = ARRAY_SIZE(tuner_philips_fq1236_mk5_params), |
1844 | }, | 1860 | }, |
1861 | [TUNER_TENA_TNF_5337] = { /* Tena 5337 MFD */ | ||
1862 | .name = "Tena TNF5337 MFD", | ||
1863 | .params = tuner_tena_tnf_5337_params, | ||
1864 | .count = ARRAY_SIZE(tuner_tena_tnf_5337_params), | ||
1865 | }, | ||
1845 | }; | 1866 | }; |
1846 | EXPORT_SYMBOL(tuners); | 1867 | EXPORT_SYMBOL(tuners); |
1847 | 1868 | ||
diff --git a/drivers/media/common/tuners/tuner-xc2028.c b/drivers/media/common/tuners/tuner-xc2028.c index b6ce528e1889..16fba6b59616 100644 --- a/drivers/media/common/tuners/tuner-xc2028.c +++ b/drivers/media/common/tuners/tuner-xc2028.c | |||
@@ -685,7 +685,7 @@ static int check_firmware(struct dvb_frontend *fe, unsigned int type, | |||
685 | { | 685 | { |
686 | struct xc2028_data *priv = fe->tuner_priv; | 686 | struct xc2028_data *priv = fe->tuner_priv; |
687 | struct firmware_properties new_fw; | 687 | struct firmware_properties new_fw; |
688 | int rc = 0, is_retry = 0; | 688 | int rc = 0, retry_count = 0; |
689 | u16 version, hwmodel; | 689 | u16 version, hwmodel; |
690 | v4l2_std_id std0; | 690 | v4l2_std_id std0; |
691 | 691 | ||
@@ -855,9 +855,9 @@ read_not_reliable: | |||
855 | 855 | ||
856 | fail: | 856 | fail: |
857 | memset(&priv->cur_fw, 0, sizeof(priv->cur_fw)); | 857 | memset(&priv->cur_fw, 0, sizeof(priv->cur_fw)); |
858 | if (!is_retry) { | 858 | if (retry_count < 8) { |
859 | msleep(50); | 859 | msleep(50); |
860 | is_retry = 1; | 860 | retry_count++; |
861 | tuner_dbg("Retrying firmware load\n"); | 861 | tuner_dbg("Retrying firmware load\n"); |
862 | goto retry; | 862 | goto retry; |
863 | } | 863 | } |
@@ -907,7 +907,7 @@ ret: | |||
907 | #define DIV 15625 | 907 | #define DIV 15625 |
908 | 908 | ||
909 | static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */, | 909 | static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */, |
910 | enum tuner_mode new_mode, | 910 | enum v4l2_tuner_type new_type, |
911 | unsigned int type, | 911 | unsigned int type, |
912 | v4l2_std_id std, | 912 | v4l2_std_id std, |
913 | u16 int_freq) | 913 | u16 int_freq) |
@@ -933,7 +933,7 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */, | |||
933 | * that xc2028 will be in a safe state. | 933 | * that xc2028 will be in a safe state. |
934 | * Maybe this might also be needed for DTV. | 934 | * Maybe this might also be needed for DTV. |
935 | */ | 935 | */ |
936 | if (new_mode == T_ANALOG_TV) { | 936 | if (new_type == V4L2_TUNER_ANALOG_TV) { |
937 | rc = send_seq(priv, {0x00, 0x00}); | 937 | rc = send_seq(priv, {0x00, 0x00}); |
938 | 938 | ||
939 | /* Analog modes require offset = 0 */ | 939 | /* Analog modes require offset = 0 */ |
@@ -1054,7 +1054,7 @@ static int xc2028_set_analog_freq(struct dvb_frontend *fe, | |||
1054 | if (priv->ctrl.input1) | 1054 | if (priv->ctrl.input1) |
1055 | type |= INPUT1; | 1055 | type |= INPUT1; |
1056 | return generic_set_freq(fe, (625l * p->frequency) / 10, | 1056 | return generic_set_freq(fe, (625l * p->frequency) / 10, |
1057 | T_RADIO, type, 0, 0); | 1057 | V4L2_TUNER_RADIO, type, 0, 0); |
1058 | } | 1058 | } |
1059 | 1059 | ||
1060 | /* if std is not defined, choose one */ | 1060 | /* if std is not defined, choose one */ |
@@ -1069,7 +1069,7 @@ static int xc2028_set_analog_freq(struct dvb_frontend *fe, | |||
1069 | p->std |= parse_audio_std_option(); | 1069 | p->std |= parse_audio_std_option(); |
1070 | 1070 | ||
1071 | return generic_set_freq(fe, 62500l * p->frequency, | 1071 | return generic_set_freq(fe, 62500l * p->frequency, |
1072 | T_ANALOG_TV, type, p->std, 0); | 1072 | V4L2_TUNER_ANALOG_TV, type, p->std, 0); |
1073 | } | 1073 | } |
1074 | 1074 | ||
1075 | static int xc2028_set_params(struct dvb_frontend *fe, | 1075 | static int xc2028_set_params(struct dvb_frontend *fe, |
@@ -1174,7 +1174,7 @@ static int xc2028_set_params(struct dvb_frontend *fe, | |||
1174 | } | 1174 | } |
1175 | 1175 | ||
1176 | return generic_set_freq(fe, p->frequency, | 1176 | return generic_set_freq(fe, p->frequency, |
1177 | T_DIGITAL_TV, type, 0, demod); | 1177 | V4L2_TUNER_DIGITAL_TV, type, 0, demod); |
1178 | } | 1178 | } |
1179 | 1179 | ||
1180 | static int xc2028_sleep(struct dvb_frontend *fe) | 1180 | static int xc2028_sleep(struct dvb_frontend *fe) |
diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/common/tuners/xc5000.c index d2b2c12a5561..aa1b2e844d32 100644 --- a/drivers/media/common/tuners/xc5000.c +++ b/drivers/media/common/tuners/xc5000.c | |||
@@ -65,7 +65,7 @@ struct xc5000_priv { | |||
65 | }; | 65 | }; |
66 | 66 | ||
67 | /* Misc Defines */ | 67 | /* Misc Defines */ |
68 | #define MAX_TV_STANDARD 23 | 68 | #define MAX_TV_STANDARD 24 |
69 | #define XC_MAX_I2C_WRITE_LENGTH 64 | 69 | #define XC_MAX_I2C_WRITE_LENGTH 64 |
70 | 70 | ||
71 | /* Signal Types */ | 71 | /* Signal Types */ |
@@ -92,6 +92,8 @@ struct xc5000_priv { | |||
92 | #define XREG_IF_OUT 0x05 | 92 | #define XREG_IF_OUT 0x05 |
93 | #define XREG_SEEK_MODE 0x07 | 93 | #define XREG_SEEK_MODE 0x07 |
94 | #define XREG_POWER_DOWN 0x0A /* Obsolete */ | 94 | #define XREG_POWER_DOWN 0x0A /* Obsolete */ |
95 | /* Set the output amplitude - SIF for analog, DTVP/DTVN for digital */ | ||
96 | #define XREG_OUTPUT_AMP 0x0B | ||
95 | #define XREG_SIGNALSOURCE 0x0D /* 0=Air, 1=Cable */ | 97 | #define XREG_SIGNALSOURCE 0x0D /* 0=Air, 1=Cable */ |
96 | #define XREG_SMOOTHEDCVBS 0x0E | 98 | #define XREG_SMOOTHEDCVBS 0x0E |
97 | #define XREG_XTALFREQ 0x0F | 99 | #define XREG_XTALFREQ 0x0F |
@@ -173,6 +175,7 @@ struct XC_TV_STANDARD { | |||
173 | #define DTV7 20 | 175 | #define DTV7 20 |
174 | #define FM_Radio_INPUT2 21 | 176 | #define FM_Radio_INPUT2 21 |
175 | #define FM_Radio_INPUT1 22 | 177 | #define FM_Radio_INPUT1 22 |
178 | #define FM_Radio_INPUT1_MONO 23 | ||
176 | 179 | ||
177 | static struct XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = { | 180 | static struct XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = { |
178 | {"M/N-NTSC/PAL-BTSC", 0x0400, 0x8020}, | 181 | {"M/N-NTSC/PAL-BTSC", 0x0400, 0x8020}, |
@@ -197,7 +200,8 @@ static struct XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = { | |||
197 | {"DTV7/8", 0x00C0, 0x801B}, | 200 | {"DTV7/8", 0x00C0, 0x801B}, |
198 | {"DTV7", 0x00C0, 0x8007}, | 201 | {"DTV7", 0x00C0, 0x8007}, |
199 | {"FM Radio-INPUT2", 0x9802, 0x9002}, | 202 | {"FM Radio-INPUT2", 0x9802, 0x9002}, |
200 | {"FM Radio-INPUT1", 0x0208, 0x9002} | 203 | {"FM Radio-INPUT1", 0x0208, 0x9002}, |
204 | {"FM Radio-INPUT1_MONO", 0x0278, 0x9002} | ||
201 | }; | 205 | }; |
202 | 206 | ||
203 | static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe); | 207 | static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe); |
@@ -624,6 +628,15 @@ static void xc_debug_dump(struct xc5000_priv *priv) | |||
624 | dprintk(1, "*** Quality (0:<8dB, 7:>56dB) = %d\n", quality); | 628 | dprintk(1, "*** Quality (0:<8dB, 7:>56dB) = %d\n", quality); |
625 | } | 629 | } |
626 | 630 | ||
631 | /* | ||
632 | * As defined on EN 300 429, the DVB-C roll-off factor is 0.15. | ||
633 | * So, the amount of the needed bandwith is given by: | ||
634 | * Bw = Symbol_rate * (1 + 0.15) | ||
635 | * As such, the maximum symbol rate supported by 6 MHz is given by: | ||
636 | * max_symbol_rate = 6 MHz / 1.15 = 5217391 Bauds | ||
637 | */ | ||
638 | #define MAX_SYMBOL_RATE_6MHz 5217391 | ||
639 | |||
627 | static int xc5000_set_params(struct dvb_frontend *fe, | 640 | static int xc5000_set_params(struct dvb_frontend *fe, |
628 | struct dvb_frontend_parameters *params) | 641 | struct dvb_frontend_parameters *params) |
629 | { | 642 | { |
@@ -683,6 +696,35 @@ static int xc5000_set_params(struct dvb_frontend *fe, | |||
683 | return -EINVAL; | 696 | return -EINVAL; |
684 | } | 697 | } |
685 | priv->rf_mode = XC_RF_MODE_AIR; | 698 | priv->rf_mode = XC_RF_MODE_AIR; |
699 | } else if (fe->ops.info.type == FE_QAM) { | ||
700 | switch (params->u.qam.modulation) { | ||
701 | case QAM_256: | ||
702 | case QAM_AUTO: | ||
703 | case QAM_16: | ||
704 | case QAM_32: | ||
705 | case QAM_64: | ||
706 | case QAM_128: | ||
707 | dprintk(1, "%s() QAM modulation\n", __func__); | ||
708 | priv->rf_mode = XC_RF_MODE_CABLE; | ||
709 | /* | ||
710 | * Using a 8MHz bandwidth sometimes fail | ||
711 | * with 6MHz-spaced channels, due to inter-carrier | ||
712 | * interference. So, use DTV6 firmware | ||
713 | */ | ||
714 | if (params->u.qam.symbol_rate <= MAX_SYMBOL_RATE_6MHz) { | ||
715 | priv->bandwidth = BANDWIDTH_6_MHZ; | ||
716 | priv->video_standard = DTV6; | ||
717 | priv->freq_hz = params->frequency - 1750000; | ||
718 | } else { | ||
719 | priv->bandwidth = BANDWIDTH_8_MHZ; | ||
720 | priv->video_standard = DTV7_8; | ||
721 | priv->freq_hz = params->frequency - 2750000; | ||
722 | } | ||
723 | break; | ||
724 | default: | ||
725 | dprintk(1, "%s() Unsupported QAM type\n", __func__); | ||
726 | return -EINVAL; | ||
727 | } | ||
686 | } else { | 728 | } else { |
687 | printk(KERN_ERR "xc5000 modulation type not supported!\n"); | 729 | printk(KERN_ERR "xc5000 modulation type not supported!\n"); |
688 | return -EINVAL; | 730 | return -EINVAL; |
@@ -714,6 +756,8 @@ static int xc5000_set_params(struct dvb_frontend *fe, | |||
714 | return -EIO; | 756 | return -EIO; |
715 | } | 757 | } |
716 | 758 | ||
759 | xc_write_reg(priv, XREG_OUTPUT_AMP, 0x8a); | ||
760 | |||
717 | xc_tune_channel(priv, priv->freq_hz, XC_TUNE_DIGITAL); | 761 | xc_tune_channel(priv, priv->freq_hz, XC_TUNE_DIGITAL); |
718 | 762 | ||
719 | if (debug) | 763 | if (debug) |
@@ -818,6 +862,8 @@ tune_channel: | |||
818 | return -EREMOTEIO; | 862 | return -EREMOTEIO; |
819 | } | 863 | } |
820 | 864 | ||
865 | xc_write_reg(priv, XREG_OUTPUT_AMP, 0x09); | ||
866 | |||
821 | xc_tune_channel(priv, priv->freq_hz, XC_TUNE_ANALOG); | 867 | xc_tune_channel(priv, priv->freq_hz, XC_TUNE_ANALOG); |
822 | 868 | ||
823 | if (debug) | 869 | if (debug) |
@@ -845,6 +891,8 @@ static int xc5000_set_radio_freq(struct dvb_frontend *fe, | |||
845 | radio_input = FM_Radio_INPUT1; | 891 | radio_input = FM_Radio_INPUT1; |
846 | else if (priv->radio_input == XC5000_RADIO_FM2) | 892 | else if (priv->radio_input == XC5000_RADIO_FM2) |
847 | radio_input = FM_Radio_INPUT2; | 893 | radio_input = FM_Radio_INPUT2; |
894 | else if (priv->radio_input == XC5000_RADIO_FM1_MONO) | ||
895 | radio_input = FM_Radio_INPUT1_MONO; | ||
848 | else { | 896 | else { |
849 | dprintk(1, "%s() unknown radio input %d\n", __func__, | 897 | dprintk(1, "%s() unknown radio input %d\n", __func__, |
850 | priv->radio_input); | 898 | priv->radio_input); |
@@ -871,6 +919,12 @@ static int xc5000_set_radio_freq(struct dvb_frontend *fe, | |||
871 | return -EREMOTEIO; | 919 | return -EREMOTEIO; |
872 | } | 920 | } |
873 | 921 | ||
922 | if ((priv->radio_input == XC5000_RADIO_FM1) || | ||
923 | (priv->radio_input == XC5000_RADIO_FM2)) | ||
924 | xc_write_reg(priv, XREG_OUTPUT_AMP, 0x09); | ||
925 | else if (priv->radio_input == XC5000_RADIO_FM1_MONO) | ||
926 | xc_write_reg(priv, XREG_OUTPUT_AMP, 0x06); | ||
927 | |||
874 | xc_tune_channel(priv, priv->freq_hz, XC_TUNE_ANALOG); | 928 | xc_tune_channel(priv, priv->freq_hz, XC_TUNE_ANALOG); |
875 | 929 | ||
876 | return 0; | 930 | return 0; |
@@ -1021,6 +1075,23 @@ static int xc5000_release(struct dvb_frontend *fe) | |||
1021 | return 0; | 1075 | return 0; |
1022 | } | 1076 | } |
1023 | 1077 | ||
1078 | static int xc5000_set_config(struct dvb_frontend *fe, void *priv_cfg) | ||
1079 | { | ||
1080 | struct xc5000_priv *priv = fe->tuner_priv; | ||
1081 | struct xc5000_config *p = priv_cfg; | ||
1082 | |||
1083 | dprintk(1, "%s()\n", __func__); | ||
1084 | |||
1085 | if (p->if_khz) | ||
1086 | priv->if_khz = p->if_khz; | ||
1087 | |||
1088 | if (p->radio_input) | ||
1089 | priv->radio_input = p->radio_input; | ||
1090 | |||
1091 | return 0; | ||
1092 | } | ||
1093 | |||
1094 | |||
1024 | static const struct dvb_tuner_ops xc5000_tuner_ops = { | 1095 | static const struct dvb_tuner_ops xc5000_tuner_ops = { |
1025 | .info = { | 1096 | .info = { |
1026 | .name = "Xceive XC5000", | 1097 | .name = "Xceive XC5000", |
@@ -1033,6 +1104,7 @@ static const struct dvb_tuner_ops xc5000_tuner_ops = { | |||
1033 | .init = xc5000_init, | 1104 | .init = xc5000_init, |
1034 | .sleep = xc5000_sleep, | 1105 | .sleep = xc5000_sleep, |
1035 | 1106 | ||
1107 | .set_config = xc5000_set_config, | ||
1036 | .set_params = xc5000_set_params, | 1108 | .set_params = xc5000_set_params, |
1037 | .set_analog_params = xc5000_set_analog_params, | 1109 | .set_analog_params = xc5000_set_analog_params, |
1038 | .get_frequency = xc5000_get_frequency, | 1110 | .get_frequency = xc5000_get_frequency, |
@@ -1042,7 +1114,7 @@ static const struct dvb_tuner_ops xc5000_tuner_ops = { | |||
1042 | 1114 | ||
1043 | struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe, | 1115 | struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe, |
1044 | struct i2c_adapter *i2c, | 1116 | struct i2c_adapter *i2c, |
1045 | struct xc5000_config *cfg) | 1117 | const struct xc5000_config *cfg) |
1046 | { | 1118 | { |
1047 | struct xc5000_priv *priv = NULL; | 1119 | struct xc5000_priv *priv = NULL; |
1048 | int instance; | 1120 | int instance; |
diff --git a/drivers/media/common/tuners/xc5000.h b/drivers/media/common/tuners/xc5000.h index e6d7236c9ea1..e2957451b532 100644 --- a/drivers/media/common/tuners/xc5000.h +++ b/drivers/media/common/tuners/xc5000.h | |||
@@ -40,6 +40,7 @@ struct xc5000_config { | |||
40 | #define XC5000_RADIO_NOT_CONFIGURED 0 | 40 | #define XC5000_RADIO_NOT_CONFIGURED 0 |
41 | #define XC5000_RADIO_FM1 1 | 41 | #define XC5000_RADIO_FM1 1 |
42 | #define XC5000_RADIO_FM2 2 | 42 | #define XC5000_RADIO_FM2 2 |
43 | #define XC5000_RADIO_FM1_MONO 3 | ||
43 | 44 | ||
44 | /* For each bridge framework, when it attaches either analog or digital, | 45 | /* For each bridge framework, when it attaches either analog or digital, |
45 | * it has to store a reference back to its _core equivalent structure, | 46 | * it has to store a reference back to its _core equivalent structure, |
@@ -53,11 +54,11 @@ struct xc5000_config { | |||
53 | (defined(CONFIG_MEDIA_TUNER_XC5000_MODULE) && defined(MODULE)) | 54 | (defined(CONFIG_MEDIA_TUNER_XC5000_MODULE) && defined(MODULE)) |
54 | extern struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe, | 55 | extern struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe, |
55 | struct i2c_adapter *i2c, | 56 | struct i2c_adapter *i2c, |
56 | struct xc5000_config *cfg); | 57 | const struct xc5000_config *cfg); |
57 | #else | 58 | #else |
58 | static inline struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe, | 59 | static inline struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe, |
59 | struct i2c_adapter *i2c, | 60 | struct i2c_adapter *i2c, |
60 | struct xc5000_config *cfg) | 61 | const struct xc5000_config *cfg) |
61 | { | 62 | { |
62 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | 63 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); |
63 | return NULL; | 64 | return NULL; |