diff options
Diffstat (limited to 'drivers/media/video/cx88/cx88-video.c')
-rw-r--r-- | drivers/media/video/cx88/cx88-video.c | 67 |
1 files changed, 42 insertions, 25 deletions
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index ef4d56ea0027..3904b73f52ee 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c | |||
@@ -426,24 +426,7 @@ int cx88_video_mux(struct cx88_core *core, unsigned int input) | |||
426 | 426 | ||
427 | /* if there are audioroutes defined, we have an external | 427 | /* if there are audioroutes defined, we have an external |
428 | ADC to deal with audio */ | 428 | ADC to deal with audio */ |
429 | |||
430 | if (INPUT(input).audioroute) { | 429 | if (INPUT(input).audioroute) { |
431 | |||
432 | /* cx2388's C-ADC is connected to the tuner only. | ||
433 | When used with S-Video, that ADC is busy dealing with | ||
434 | chroma, so an external must be used for baseband audio */ | ||
435 | |||
436 | if (INPUT(input).type != CX88_VMUX_TELEVISION && | ||
437 | INPUT(input).type != CX88_RADIO) { | ||
438 | /* "ADC mode" */ | ||
439 | cx_write(AUD_I2SCNTL, 0x1); | ||
440 | cx_set(AUD_CTL, EN_I2SIN_ENABLE); | ||
441 | } else { | ||
442 | /* Normal mode */ | ||
443 | cx_write(AUD_I2SCNTL, 0x0); | ||
444 | cx_clear(AUD_CTL, EN_I2SIN_ENABLE); | ||
445 | } | ||
446 | |||
447 | /* The wm8775 module has the "2" route hardwired into | 430 | /* The wm8775 module has the "2" route hardwired into |
448 | the initialization. Some boards may use different | 431 | the initialization. Some boards may use different |
449 | routes for different inputs. HVR-1300 surely does */ | 432 | routes for different inputs. HVR-1300 surely does */ |
@@ -454,9 +437,19 @@ int cx88_video_mux(struct cx88_core *core, unsigned int input) | |||
454 | route.input = INPUT(input).audioroute; | 437 | route.input = INPUT(input).audioroute; |
455 | cx88_call_i2c_clients(core, | 438 | cx88_call_i2c_clients(core, |
456 | VIDIOC_INT_S_AUDIO_ROUTING, &route); | 439 | VIDIOC_INT_S_AUDIO_ROUTING, &route); |
457 | |||
458 | } | 440 | } |
459 | 441 | /* cx2388's C-ADC is connected to the tuner only. | |
442 | When used with S-Video, that ADC is busy dealing with | ||
443 | chroma, so an external must be used for baseband audio */ | ||
444 | if (INPUT(input).type != CX88_VMUX_TELEVISION ) { | ||
445 | /* "I2S ADC mode" */ | ||
446 | core->tvaudio = WW_I2SADC; | ||
447 | cx88_set_tvaudio(core); | ||
448 | } else { | ||
449 | /* Normal mode */ | ||
450 | cx_write(AUD_I2SCNTL, 0x0); | ||
451 | cx_clear(AUD_CTL, EN_I2SIN_ENABLE); | ||
452 | } | ||
460 | } | 453 | } |
461 | 454 | ||
462 | return 0; | 455 | return 0; |
@@ -773,6 +766,7 @@ static int video_open(struct inode *inode, struct file *file) | |||
773 | enum v4l2_buf_type type = 0; | 766 | enum v4l2_buf_type type = 0; |
774 | int radio = 0; | 767 | int radio = 0; |
775 | 768 | ||
769 | lock_kernel(); | ||
776 | list_for_each_entry(h, &cx8800_devlist, devlist) { | 770 | list_for_each_entry(h, &cx8800_devlist, devlist) { |
777 | if (h->video_dev->minor == minor) { | 771 | if (h->video_dev->minor == minor) { |
778 | dev = h; | 772 | dev = h; |
@@ -788,8 +782,10 @@ static int video_open(struct inode *inode, struct file *file) | |||
788 | dev = h; | 782 | dev = h; |
789 | } | 783 | } |
790 | } | 784 | } |
791 | if (NULL == dev) | 785 | if (NULL == dev) { |
786 | unlock_kernel(); | ||
792 | return -ENODEV; | 787 | return -ENODEV; |
788 | } | ||
793 | 789 | ||
794 | core = dev->core; | 790 | core = dev->core; |
795 | 791 | ||
@@ -798,8 +794,10 @@ static int video_open(struct inode *inode, struct file *file) | |||
798 | 794 | ||
799 | /* allocate + initialize per filehandle data */ | 795 | /* allocate + initialize per filehandle data */ |
800 | fh = kzalloc(sizeof(*fh),GFP_KERNEL); | 796 | fh = kzalloc(sizeof(*fh),GFP_KERNEL); |
801 | if (NULL == fh) | 797 | if (NULL == fh) { |
798 | unlock_kernel(); | ||
802 | return -ENOMEM; | 799 | return -ENOMEM; |
800 | } | ||
803 | file->private_data = fh; | 801 | file->private_data = fh; |
804 | fh->dev = dev; | 802 | fh->dev = dev; |
805 | fh->radio = radio; | 803 | fh->radio = radio; |
@@ -827,11 +825,29 @@ static int video_open(struct inode *inode, struct file *file) | |||
827 | cx_write(MO_GP0_IO, core->board.radio.gpio0); | 825 | cx_write(MO_GP0_IO, core->board.radio.gpio0); |
828 | cx_write(MO_GP1_IO, core->board.radio.gpio1); | 826 | cx_write(MO_GP1_IO, core->board.radio.gpio1); |
829 | cx_write(MO_GP2_IO, core->board.radio.gpio2); | 827 | cx_write(MO_GP2_IO, core->board.radio.gpio2); |
830 | core->tvaudio = WW_FM; | 828 | if (core->board.radio.audioroute) { |
831 | cx88_set_tvaudio(core); | 829 | if(core->board.audio_chip && |
832 | cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1); | 830 | core->board.audio_chip == V4L2_IDENT_WM8775) { |
831 | struct v4l2_routing route; | ||
832 | |||
833 | route.input = core->board.radio.audioroute; | ||
834 | cx88_call_i2c_clients(core, | ||
835 | VIDIOC_INT_S_AUDIO_ROUTING, &route); | ||
836 | } | ||
837 | /* "I2S ADC mode" */ | ||
838 | core->tvaudio = WW_I2SADC; | ||
839 | cx88_set_tvaudio(core); | ||
840 | } else { | ||
841 | /* FM Mode */ | ||
842 | core->tvaudio = WW_FM; | ||
843 | cx88_set_tvaudio(core); | ||
844 | cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1); | ||
845 | } | ||
833 | cx88_call_i2c_clients(core,AUDC_SET_RADIO,NULL); | 846 | cx88_call_i2c_clients(core,AUDC_SET_RADIO,NULL); |
834 | } | 847 | } |
848 | unlock_kernel(); | ||
849 | |||
850 | atomic_inc(&core->users); | ||
835 | 851 | ||
836 | return 0; | 852 | return 0; |
837 | } | 853 | } |
@@ -920,7 +936,8 @@ static int video_release(struct inode *inode, struct file *file) | |||
920 | file->private_data = NULL; | 936 | file->private_data = NULL; |
921 | kfree(fh); | 937 | kfree(fh); |
922 | 938 | ||
923 | cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); | 939 | if(atomic_dec_and_test(&dev->core->users)) |
940 | cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); | ||
924 | 941 | ||
925 | return 0; | 942 | return 0; |
926 | } | 943 | } |