diff options
Diffstat (limited to 'drivers/media/video')
39 files changed, 1524 insertions, 660 deletions
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index f31a19890b1..85888a8a93c 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -300,7 +300,7 @@ config VIDEO_OVCAMCHIP camera drivers. To compile this driver as a module, choose M here: the - module will be called ovcamchip + module will be called ovcamchip. config VIDEO_M32R_AR tristate "AR devices" @@ -316,6 +316,13 @@ config VIDEO_M32R_AR_M64278 Say Y here to use the Renesas M64278E-800 camera module, which supports VGA(640x480 pixcels) size of images. +# +# Encoder / Decoder module configuration +# + +menu "Encoders and Decoders" + depends on VIDEO_DEV + config VIDEO_MSP3400 tristate "Micronas MSP34xx audio decoders" depends on VIDEO_DEV && I2C @@ -323,7 +330,7 @@ config VIDEO_MSP3400 Support for the Micronas MSP34xx series of audio decoders. To compile this driver as a module, choose M here: the - module will be called msp3400 + module will be called msp3400. config VIDEO_CS53L32A tristate "Cirrus Logic CS53L32A audio ADC" @@ -333,17 +340,27 @@ config VIDEO_CS53L32A stereo A/D converter. To compile this driver as a module, choose M here: the - module will be called cs53l32a + module will be called cs53l32a. config VIDEO_WM8775 - tristate "Wolfson Microelectronics WM8775 audio ADC" + tristate "Wolfson Microelectronics WM8775 audio ADC with input mixer" depends on VIDEO_DEV && I2C && EXPERIMENTAL ---help--- - Support for the Wolfson Microelectronics WM8775 - high performance stereo A/D Converter. + Support for the Wolfson Microelectronics WM8775 high + performance stereo A/D Converter with a 4 channel input mixer. To compile this driver as a module, choose M here: the - module will be called wm8775 + module will be called wm8775. + +config VIDEO_WM8739 + tristate "Wolfson Microelectronics WM8739 stereo audio ADC" + depends on VIDEO_DEV && I2C && EXPERIMENTAL + ---help--- + Support for the Wolfson Microelectronics WM8739 + stereo A/D Converter. + + To compile this driver as a module, choose M here: the + module will be called wm8739. source "drivers/media/video/cx25840/Kconfig" @@ -354,7 +371,7 @@ config VIDEO_SAA711X Support for the Philips SAA7113/4/5 video decoders. To compile this driver as a module, choose M here: the - module will be called saa7115 + module will be called saa7115. config VIDEO_SAA7127 tristate "Philips SAA7127/9 digital video encoders" @@ -363,7 +380,32 @@ config VIDEO_SAA7127 Support for the Philips SAA7127/9 digital video encoders. To compile this driver as a module, choose M here: the - module will be called saa7127 + module will be called saa7127. + +config VIDEO_UPD64031A + tristate "NEC Electronics uPD64031A Ghost Reduction" + depends on VIDEO_DEV && I2C && EXPERIMENTAL + ---help--- + Support for the NEC Electronics uPD64031A Ghost Reduction + video chip. It is most often found in NTSC TV cards made for + Japan and is used to reduce the 'ghosting' effect that can + be present in analog TV broadcasts. + + To compile this driver as a module, choose M here: the + module will be called upd64031a. + +config VIDEO_UPD64083 + tristate "NEC Electronics uPD64083 3-Dimensional Y/C separation" + depends on VIDEO_DEV && I2C && EXPERIMENTAL + ---help--- + Support for the NEC Electronics uPD64083 3-Dimensional Y/C + separation video chip. It is used to improve the quality of + the colors of a composite signal. + + To compile this driver as a module, choose M here: the + module will be called upd64083. + +endmenu # encoder / decoder chips # # USB Multimedia device configuration @@ -374,20 +416,6 @@ menu "V4L USB devices" source "drivers/media/video/em28xx/Kconfig" -config USB_VICAM - tristate "USB 3com HomeConnect (aka vicam) support (EXPERIMENTAL)" - depends on USB && VIDEO_DEV && EXPERIMENTAL - ---help--- - Say Y here if you have 3com homeconnect camera (vicam). - - This driver uses the Video For Linux API. You must say Y or M to - "Video For Linux" (under Multimedia Devices) to use this driver. - Information on this API and pointers to "v4l" programs may be found - at <file:Documentation/video4linux/API.html>. - - To compile this driver as a module, choose M here: the - module will be called vicam. - config USB_DSBR tristate "D-Link USB FM radio support (EXPERIMENTAL)" depends on USB && VIDEO_DEV && EXPERIMENTAL @@ -397,79 +425,20 @@ config USB_DSBR you must connect the line out connector to a sound card or a set of speakers. - This driver uses the Video For Linux API. You must enable - (Y or M in config) Video For Linux (under Character Devices) - to use this driver. Information on this API and pointers to - "v4l" programs may be found at - <file:Documentation/video4linux/API.html>. - To compile this driver as a module, choose M here: the module will be called dsbr100. -config USB_ET61X251 - tristate "USB ET61X[12]51 PC Camera Controller support" - depends on USB && VIDEO_DEV - ---help--- - Say Y here if you want support for cameras based on Etoms ET61X151 - or ET61X251 PC Camera Controllers. - - See <file:Documentation/usb/et61x251.txt> for more informations. - - This driver uses the Video For Linux API. You must say Y or M to - "Video For Linux" to use this driver. - - To compile this driver as a module, choose M here: the - module will be called et61x251. +source "drivers/media/video/usbvideo/Kconfig" -config USB_IBMCAM - tristate "USB IBM (Xirlink) C-it Camera support" - depends on USB && VIDEO_DEV - ---help--- - Say Y here if you want to connect a IBM "C-It" camera, also known as - "Xirlink PC Camera" to your computer's USB port. For more - information, read <file:Documentation/usb/ibmcam.txt>. - - This driver uses the Video For Linux API. You must enable - (Y or M in config) Video For Linux (under Character Devices) - to use this driver. Information on this API and pointers to - "v4l" programs may be found at - <file:Documentation/video4linux/API.html>. - - To compile this driver as a module, choose M here: the - module will be called ibmcam. - - This camera has several configuration options which - can be specified when you load the module. Read - <file:Documentation/usb/ibmcam.txt> to learn more. - -config USB_KONICAWC - tristate "USB Konica Webcam support" - depends on USB && VIDEO_DEV - ---help--- - Say Y here if you want support for webcams based on a Konica - chipset. This is known to work with the Intel YC76 webcam. - - This driver uses the Video For Linux API. You must enable - (Y or M in config) Video For Linux (under Character Devices) - to use this driver. Information on this API and pointers to - "v4l" programs may be found at - <file:Documentation/video4linux/API.html>. - - To compile this driver as a module, choose M here: the - module will be called konicawc. +source "drivers/media/video/et61x251/Kconfig" config USB_OV511 tristate "USB OV511 Camera support" depends on USB && VIDEO_DEV ---help--- Say Y here if you want to connect this type of camera to your - computer's USB port. See <file:Documentation/usb/ov511.txt> for more - information and for a list of supported cameras. - - This driver uses the Video For Linux API. You must say Y or M to - "Video For Linux" (under Character Devices) to use this driver. - Information on this API and pointers to "v4l" programs may be found - at <file:Documentation/video4linux/API.html>. + computer's USB port. See <file:Documentation/video4linux/ov511.txt> + for more information and for a list of supported cameras. To compile this driver as a module, choose M here: the module will be called ov511. @@ -479,31 +448,13 @@ config USB_SE401 depends on USB && VIDEO_DEV ---help--- Say Y here if you want to connect this type of camera to your - computer's USB port. See <file:Documentation/usb/se401.txt> for more - information and for a list of supported cameras. - - This driver uses the Video For Linux API. You must say Y or M to - "Video For Linux" (under Multimedia Devices) to use this driver. - Information on this API and pointers to "v4l" programs may be found - at <file:Documentation/video4linux/API.html>. + computer's USB port. See <file:Documentation/video4linux/se401.txt> + for more information and for a list of supported cameras. To compile this driver as a module, choose M here: the module will be called se401. -config USB_SN9C102 - tristate "USB SN9C10x PC Camera Controller support" - depends on USB && VIDEO_DEV - ---help--- - Say Y here if you want support for cameras based on SONiX SN9C101, - SN9C102 or SN9C103 PC Camera Controllers. - - See <file:Documentation/usb/sn9c102.txt> for more informations. - - This driver uses the Video For Linux API. You must say Y or M to - "Video For Linux" to use this driver. - - To compile this driver as a module, choose M here: the - module will be called sn9c102. +source "drivers/media/video/sn9c102/Kconfig" config USB_STV680 tristate "USB STV680 (Pencam) Camera support" @@ -511,20 +462,16 @@ config USB_STV680 ---help--- Say Y here if you want to connect this type of camera to your computer's USB port. This includes the Pencam line of cameras. - See <file:Documentation/usb/stv680.txt> for more information and for - a list of supported cameras. - - This driver uses the Video For Linux API. You must say Y or M to - "Video For Linux" (under Multimedia Devices) to use this driver. - Information on this API and pointers to "v4l" programs may be found - at <file:Documentation/video4linux/API.html>. + See <file:Documentation/video4linux/stv680.txt> for more information + and for a list of supported cameras. To compile this driver as a module, choose M here: the module will be called stv680. config USB_W9968CF tristate "USB W996[87]CF JPEG Dual Mode Camera support" - depends on USB && VIDEO_DEV && I2C && VIDEO_OVCAMCHIP + depends on USB && VIDEO_DEV && I2C + select VIDEO_OVCAMCHIP ---help--- Say Y here if you want support for cameras based on OV681 or Winbond W9967CF/W9968CF JPEG USB Dual Mode Camera Chips. @@ -534,64 +481,14 @@ config USB_W9968CF resolutions and framerates, but cannot be included in the official Linux kernel for performance purposes. - See <file:Documentation/usb/w9968cf.txt> for more informations. - - This driver uses the Video For Linux and the I2C APIs. It needs the - OmniVision Camera Chip support as well. You must say Y or M to - "Video For Linux", "I2C Support" and "OmniVision Camera Chip - support" to use this driver. + See <file:Documentation/video4linux/w9968cf.txt> for more info. To compile this driver as a module, choose M here: the module will be called w9968cf. -config USB_ZC0301 - tristate "USB ZC0301 Image Processor and Control Chip support" - depends on USB && VIDEO_DEV - ---help--- - Say Y here if you want support for cameras based on the ZC0301 - Image Processor and Control Chip. - - See <file:Documentation/usb/zc0301.txt> for more informations. - - This driver uses the Video For Linux API. You must say Y or M to - "Video For Linux" to use this driver. - - To compile this driver as a module, choose M here: the - module will be called zc0301. - -config USB_PWC - tristate "USB Philips Cameras" - depends on USB && VIDEO_DEV - ---help--- - Say Y or M here if you want to use one of these Philips & OEM - webcams: - * Philips PCA645, PCA646 - * Philips PCVC675, PCVC680, PCVC690 - * Philips PCVC720/40, PCVC730, PCVC740, PCVC750 - * Askey VC010 - * Logitech QuickCam Pro 3000, 4000, 'Zoom', 'Notebook Pro' - and 'Orbit'/'Sphere' - * Samsung MPC-C10, MPC-C30 - * Creative Webcam 5, Pro Ex - * SOTEC Afina Eye - * Visionite VCS-UC300, VCS-UM100 - - The PCA635, PCVC665 and PCVC720/20 are not supported by this driver - and never will be, but the 665 and 720/20 are supported by other - drivers. - - See <file:Documentation/usb/philips.txt> for more information and - installation instructions. - - The built-in microphone is enabled by selecting USB Audio support. - - This driver uses the Video For Linux API. You must say Y or M to - "Video For Linux" (under Character Devices) to use this driver. - Information on this API and pointers to "v4l" programs may be found - at <file:Documentation/video4linux/API.html>. +source "drivers/media/video/zc0301/Kconfig" - To compile this driver as a module, choose M here: the - module will be called pwc. +source "drivers/media/video/pwc/Kconfig" endmenu # V4L USB devices diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 1c0e72e5a59..4092a5e37ff 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -45,6 +45,7 @@ obj-$(CONFIG_VIDEO_EM28XX) += tvp5150.o obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o obj-$(CONFIG_VIDEO_WM8775) += wm8775.o +obj-$(CONFIG_VIDEO_WM8739) += wm8739.o obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip/ obj-$(CONFIG_VIDEO_CPIA2) += cpia2/ obj-$(CONFIG_VIDEO_MXB) += saa7111.o tda9840.o tea6415c.o tea6420.o mxb.o @@ -64,9 +65,8 @@ obj-$(CONFIG_VIDEO_M32R_AR_M64278) += arv.o obj-$(CONFIG_VIDEO_CX25840) += cx25840/ obj-$(CONFIG_VIDEO_SAA711X) += saa7115.o obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o - -et61x251-objs := et61x251_core.o et61x251_tas5130d1b.o -zc0301-objs := zc0301_core.o zc0301_pas202bcb.o +obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o +obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o obj-$(CONFIG_USB_DABUSB) += dabusb.o obj-$(CONFIG_USB_DSBR) += dsbr100.o diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 74def9c2395..423e954948b 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c @@ -973,12 +973,12 @@ audio_mux(struct bttv *btv, int input, int mute) For now this is sufficient. */ switch (input) { case TVAUDIO_INPUT_RADIO: - route.input = MSP_INPUT(MSP_IN_SCART_2, MSP_IN_TUNER_1, - MSP_DSP_OUT_SCART, MSP_DSP_OUT_SCART); + route.input = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1, + MSP_DSP_IN_SCART, MSP_DSP_IN_SCART); break; case TVAUDIO_INPUT_EXTERN: - route.input = MSP_INPUT(MSP_IN_SCART_1, MSP_IN_TUNER_1, - MSP_DSP_OUT_SCART, MSP_DSP_OUT_SCART); + route.input = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1, + MSP_DSP_IN_SCART, MSP_DSP_IN_SCART); break; case TVAUDIO_INPUT_INTERN: /* Yes, this is the same input as for RADIO. I doubt @@ -986,8 +986,8 @@ audio_mux(struct bttv *btv, int input, int mute) input is the BTTV_BOARD_AVERMEDIA98. I wonder how that was tested. My guess is that the whole INTERN input does not work. */ - route.input = MSP_INPUT(MSP_IN_SCART_2, MSP_IN_TUNER_1, - MSP_DSP_OUT_SCART, MSP_DSP_OUT_SCART); + route.input = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1, + MSP_DSP_IN_SCART, MSP_DSP_IN_SCART); break; case TVAUDIO_INPUT_TUNER: default: @@ -1023,14 +1023,11 @@ audio_input(struct bttv *btv, int input) static void i2c_vidiocschan(struct bttv *btv) { - struct video_channel c; + v4l2_std_id std = bttv_tvnorms[btv->tvnorm].v4l2_id; - memset(&c,0,sizeof(c)); - c.norm = btv->tvnorm; - c.channel = btv->input; - bttv_call_i2c_clients(btv,VIDIOCSCHAN,&c); + bttv_call_i2c_clients(btv, VIDIOC_S_STD, &std); if (btv->c.type == BTTV_BOARD_VOODOOTV_FM) - bttv_tda9880_setnorm(btv,c.norm); + bttv_tda9880_setnorm(btv,btv->tvnorm); } static int @@ -1184,11 +1181,27 @@ static int get_control(struct bttv *btv, struct v4l2_control *c) break; if (i == BTTV_CTLS) return -EINVAL; - if (i >= 4 && i <= 8) { + if (btv->audio_hook && i >= 4 && i <= 8) { memset(&va,0,sizeof(va)); - bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va); - if (btv->audio_hook) - btv->audio_hook(btv,&va,0); + btv->audio_hook(btv,&va,0); + switch (c->id) { + case V4L2_CID_AUDIO_MUTE: + c->value = (VIDEO_AUDIO_MUTE & va.flags) ? 1 : 0; + break; + case V4L2_CID_AUDIO_VOLUME: + c->value = va.volume; + break; + case V4L2_CID_AUDIO_BALANCE: + c->value = va.balance; + break; + case V4L2_CID_AUDIO_BASS: + c->value = va.bass; + break; + case V4L2_CID_AUDIO_TREBLE: + c->value = va.treble; + break; + } + return 0; } switch (c->id) { case V4L2_CID_BRIGHTNESS: @@ -1205,19 +1218,11 @@ static int get_control(struct bttv *btv, struct v4l2_control *c) break; case V4L2_CID_AUDIO_MUTE: - c->value = (VIDEO_AUDIO_MUTE & va.flags) ? 1 : 0; - break; case V4L2_CID_AUDIO_VOLUME: - c->value = va.volume; - break; case V4L2_CID_AUDIO_BALANCE: - c->value = va.balance; - break; case V4L2_CID_AUDIO_BASS: - c->value = va.bass; - break; case V4L2_CID_AUDIO_TREBLE: - c->value = va.treble; + bttv_call_i2c_clients(btv,VIDIOC_G_CTRL,c); break; case V4L2_CID_PRIVATE_CHROMA_AGC: @@ -1269,11 +1274,35 @@ static int set_control(struct bttv *btv, struct v4l2_control *c) break; if (i == BTTV_CTLS) return -EINVAL; - if (i >= 4 && i <= 8) { + if (btv->audio_hook && i >= 4 && i <= 8) { memset(&va,0,sizeof(va)); - bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va); - if (btv->audio_hook) - btv->audio_hook(btv,&va,0); + btv->audio_hook(btv,&va,0); + switch (c->id) { + case V4L2_CID_AUDIO_MUTE: + if (c->value) { + va.flags |= VIDEO_AUDIO_MUTE; + audio_mute(btv, 1); + } else { + va.flags &= ~VIDEO_AUDIO_MUTE; + audio_mute(btv, 0); + } + break; + + case V4L2_CID_AUDIO_VOLUME: + va.volume = c->value; + break; + case V4L2_CID_AUDIO_BALANCE: + va.balance = c->value; + break; + case V4L2_CID_AUDIO_BASS: + va.bass = c->value; + break; + case V4L2_CID_AUDIO_TREBLE: + va.treble = c->value; + break; + } + btv->audio_hook(btv,&va,1); + return 0; } switch (c->id) { case V4L2_CID_BRIGHTNESS: @@ -1289,26 +1318,13 @@ static int set_control(struct bttv *btv, struct v4l2_control *c) bt848_sat(btv,c->value); break; case V4L2_CID_AUDIO_MUTE: - if (c->value) { - va.flags |= VIDEO_AUDIO_MUTE; - audio_mute(btv, 1); - } else { - va.flags &= ~VIDEO_AUDIO_MUTE; - audio_mute(btv, 0); - } - break; - + audio_mute(btv, c->value); + /* fall through */ case V4L2_CID_AUDIO_VOLUME: - va.volume = c->value; - break; case V4L2_CID_AUDIO_BALANCE: - va.balance = c->value; - break; case V4L2_CID_AUDIO_BASS: - va.bass = c->value; - break; case V4L2_CID_AUDIO_TREBLE: - va.treble = c->value; + bttv_call_i2c_clients(btv,VIDIOC_S_CTRL,c); break; case V4L2_CID_PRIVATE_CHROMA_AGC: @@ -1364,11 +1380,6 @@ static int set_control(struct bttv *btv, struct v4l2_control *c) default: return -EINVAL; } - if (i >= 4 && i <= 8) { - bttv_call_i2c_clients(btv, VIDIOCSAUDIO, &va); - if (btv->audio_hook) - btv->audio_hook(btv,&va,1); - } return 0; } @@ -1591,12 +1602,16 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) } case VIDIOCSFREQ: { - unsigned long *freq = arg; + struct v4l2_frequency freq; + + memset(&freq, 0, sizeof(freq)); + freq.frequency = *(unsigned long *)arg; mutex_lock(&btv->lock); - btv->freq=*freq; - bttv_call_i2c_clients(btv,VIDIOCSFREQ,freq); + freq.type = btv->radio_user ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; + btv->freq = *(unsigned long *)arg; + bttv_call_i2c_clients(btv,VIDIOC_S_FREQUENCY,&freq); if (btv->has_matchbox && btv->radio_user) - tea5757_set_freq(btv,*freq); + tea5757_set_freq(btv,*(unsigned long *)arg); mutex_unlock(&btv->lock); return 0; } @@ -1827,33 +1842,26 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) return -EINVAL; mutex_lock(&btv->lock); memset(t,0,sizeof(*t)); + t->rxsubchans = V4L2_TUNER_SUB_MONO; + bttv_call_i2c_clients(btv, VIDIOC_G_TUNER, t); strcpy(t->name, "Television"); - t->type = V4L2_TUNER_ANALOG_TV; t->capability = V4L2_TUNER_CAP_NORM; - t->rxsubchans = V4L2_TUNER_SUB_MONO; + t->type = V4L2_TUNER_ANALOG_TV; if (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC) t->signal = 0xffff; - { - struct video_tuner tuner; - - memset(&tuner, 0, sizeof (tuner)); - tuner.rangehigh = 0xffffffffUL; - bttv_call_i2c_clients(btv, VIDIOCGTUNER, &tuner); - t->rangelow = tuner.rangelow; - t->rangehigh = tuner.rangehigh; - } - { + + if (btv->audio_hook) { /* Hmmm ... */ struct video_audio va; memset(&va, 0, sizeof(struct video_audio)); - bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va); - if (btv->audio_hook) - btv->audio_hook(btv,&va,0); + btv->audio_hook(btv,&va,0); + t->audmode = V4L2_TUNER_MODE_MONO; + t->rxsubchans = V4L2_TUNER_SUB_MONO; if(va.mode & VIDEO_SOUND_STEREO) { - t->audmode = V4L2_TUNER_MODE_STEREO; - t->rxsubchans |= V4L2_TUNER_SUB_STEREO; + t->audmode = V4L2_TUNER_MODE_STEREO; + t->rxsubchans = V4L2_TUNER_SUB_STEREO; } - if(va.mode & VIDEO_SOUND_LANG1) { + if(va.mode & VIDEO_SOUND_LANG2) { t->audmode = V4L2_TUNER_MODE_LANG1; t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; @@ -1872,10 +1880,10 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) if (0 != t->index) return -EINVAL; mutex_lock(&btv->lock); - { + bttv_call_i2c_clients(btv, VIDIOC_S_TUNER, t); + if (btv->audio_hook) { struct video_audio va; memset(&va, 0, sizeof(struct video_audio)); - bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va); if (t->audmode == V4L2_TUNER_MODE_MONO) va.mode = VIDEO_SOUND_MONO; else if (t->audmode == V4L2_TUNER_MODE_STEREO || @@ -1885,9 +1893,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) va.mode = VIDEO_SOUND_LANG1; else if (t->audmode == V4L2_TUNER_MODE_LANG2) va.mode = VIDEO_SOUND_LANG2; - bttv_call_i2c_clients(btv, VIDIOCSAUDIO, &va); - if (btv->audio_hook) - btv->audio_hook(btv,&va,1); + btv->audio_hook(btv,&va,1); } mutex_unlock(&btv->lock); return 0; @@ -1912,7 +1918,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) return -EINVAL; mutex_lock(&btv->lock); btv->freq = f->frequency; - bttv_call_i2c_clients(btv,VIDIOCSFREQ,&btv->freq); + bttv_call_i2c_clients(btv,VIDIOC_S_FREQUENCY,f); if (btv->has_matchbox && btv->radio_user) tea5757_set_freq(btv,btv->freq); mutex_unlock(&btv->lock); @@ -1920,7 +1926,9 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) } case VIDIOC_LOG_STATUS: { + printk(KERN_INFO "bttv%d: ================= START STATUS CARD #%d =================\n", btv->c.nr, btv->c.nr); bttv_call_i2c_clients(btv, VIDIOC_LOG_STATUS, NULL); + printk(KERN_INFO "bttv%d: ================== END STATUS CARD #%d ==================\n", btv->c.nr, btv->c.nr); return 0; } @@ -2870,12 +2878,10 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, return 0; } *c = bttv_ctls[i]; - if (i >= 4 && i <= 8) { + if (btv->audio_hook && i >= 4 && i <= 8) { struct video_audio va; memset(&va,0,sizeof(va)); - bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va); - if (btv->audio_hook) - btv->audio_hook(btv,&va,0); + btv->audio_hook(btv,&va,0); switch (bttv_ctls[i].id) { case V4L2_CID_AUDIO_VOLUME: if (!(va.flags & VIDEO_AUDIO_VOLUME)) diff --git a/drivers/media/video/bt8xx/bttv-vbi.c b/drivers/media/video/bt8xx/bttv-vbi.c index e20ff238e40..8c9f0f7cf46 100644 --- a/drivers/media/video/bt8xx/bttv-vbi.c +++ b/drivers/media/video/bt8xx/bttv-vbi.c @@ -184,7 +184,7 @@ void bttv_vbi_try_fmt(struct bttv_fh *fh, struct v4l2_format *f) - tvnorm->vbistart[0]; count1 = (s64) f->fmt.vbi.start[1] + f->fmt.vbi.count[1] - tvnorm->vbistart[1]; - count = clamp (max (count0, count1), 1LL, (s64) VBI_MAXLINES); + count = clamp (max (count0, count1), (s64) 1, (s64) VBI_MAXLINES); f->fmt.vbi.start[0] = tvnorm->vbistart[0]; f->fmt.vbi.start[1] = tvnorm->vbistart[1]; diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c index 2227c5640c1..85d84e89d8f 100644 --- a/drivers/media/video/cpia.c +++ b/drivers/media/video/cpia.c @@ -64,14 +64,13 @@ MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("video"); #endif -static unsigned short colorspace_conv = 0; +static unsigned short colorspace_conv; module_param(colorspace_conv, ushort, 0444); MODULE_PARM_DESC(colorspace_conv, - "\n<n> Colorspace conversion:" - "\n0 = disable" - "\n1 = enable" - "\nDefault value is 0" - "\n"); + " Colorspace conversion:" + "\n 0 = disable, 1 = enable" + "\n Default value is 0" + ); #define ABOUT "V4L-Driver for Vision CPiA based cameras" @@ -4042,7 +4041,7 @@ static int __init cpia_init(void) "allowed, it is disabled by default now. Users should fix the " "applications in case they don't work without conversion " "reenabled by setting the 'colorspace_conv' module " - "parameter to 1"); + "parameter to 1\n"); #ifdef CONFIG_PROC_FS proc_cpia_create(); diff --git a/drivers/media/video/cpia2/cpia2.h b/drivers/media/video/cpia2/cpia2.h index 8394283993f..1764991b0ac 100644 --- a/drivers/media/video/cpia2/cpia2.h +++ b/drivers/media/video/cpia2/cpia2.h @@ -456,7 +456,7 @@ int cpia2_init_camera(struct camera_data *cam); int cpia2_allocate_buffers(struct camera_data *cam); void cpia2_free_buffers(struct camera_data *cam); long cpia2_read(struct camera_data *cam, - char *buf, unsigned long count, int noblock); + char __user *buf, unsigned long count, int noblock); unsigned int cpia2_poll(struct camera_data *cam, struct file *filp, poll_table *wait); int cpia2_remap_buffer(struct camera_data *cam, struct vm_area_struct *vma); diff --git a/drivers/media/video/cx25840/cx25840-audio.c b/drivers/media/video/cx25840/cx25840-audio.c index a4540e858f2..9a4b813152e 100644 --- a/drivers/media/video/cx25840/cx25840-audio.c +++ b/drivers/media/video/cx25840/cx25840-audio.c @@ -19,8 +19,9 @@ #include <linux/videodev2.h> #include <linux/i2c.h> #include <media/v4l2-common.h> +#include <media/cx25840.h> -#include "cx25840.h" +#include "cx25840-core.h" static int set_audclk_freq(struct i2c_client *client, u32 freq) { diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index a65b3cc4bf0..a961bb2ab0f 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -32,8 +32,9 @@ #include <linux/videodev2.h> #include <linux/i2c.h> #include <media/v4l2-common.h> +#include <media/cx25840.h> -#include "cx25840.h" +#include "cx25840-core.h" MODULE_DESCRIPTION("Conexant CX25840 audio/video decoder driver"); MODULE_AUTHOR("Ulf Eklund, Chris Kennedy, Hans Verkuil, Tyler Trafford"); @@ -668,6 +669,7 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, { struct cx25840_state *state = i2c_get_clientdata(client); struct v4l2_tuner *vt = arg; + struct v4l2_routing *route = arg; switch (cmd) { #ifdef CONFIG_VIDEO_ADV_DEBUG @@ -749,19 +751,21 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, state->radio = 1; break; - case VIDIOC_G_INPUT: - *(int *)arg = state->vid_input; + case VIDIOC_INT_G_VIDEO_ROUTING: + route->input = state->vid_input; + route->output = 0; break; - case VIDIOC_S_INPUT: - return set_input(client, *(enum cx25840_video_input *)arg, state->aud_input); + case VIDIOC_INT_S_VIDEO_ROUTING: + return set_input(client, route->input, state->aud_input); - case VIDIOC_S_AUDIO: - { - struct v4l2_audio *input = arg; + case VIDIOC_INT_G_AUDIO_ROUTING: + route->input = state->aud_input; + route->output = 0; + break; - return set_input(client, state->vid_input, input->index); - } + case VIDIOC_INT_S_AUDIO_ROUTING: + return set_input(client, state->vid_input, route->input); case VIDIOC_S_FREQUENCY: input_change(client); diff --git a/drivers/media/video/cx25840/cx25840.h b/drivers/media/video/cx25840/cx25840-core.h index dd70664d1dd..1736929fc20 100644 --- a/drivers/media/video/cx25840/cx25840.h +++ b/drivers/media/video/cx25840/cx25840-core.h @@ -1,4 +1,4 @@ -/* cx25840 API header +/* cx25840 internal API header * * Copyright (C) 2003-2004 Chris Kennedy * @@ -17,8 +17,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef _CX25840_H_ -#define _CX25840_H_ +#ifndef _CX25840_CORE_H_ +#define _CX25840_CORE_H_ #include <linux/videodev2.h> @@ -32,46 +32,6 @@ providing this information. */ #define CX25840_CID_ENABLE_PVR150_WORKAROUND (V4L2_CID_PRIVATE_BASE+0) -enum cx25840_video_input { - /* Composite video inputs In1-In8 */ - CX25840_COMPOSITE1 = 1, - CX25840_COMPOSITE2, - CX25840_COMPOSITE3, - CX25840_COMPOSITE4, - CX25840_COMPOSITE5, - CX25840_COMPOSITE6, - CX25840_COMPOSITE7, - CX25840_COMPOSITE8, - - /* S-Video inputs consist of one luma input (In1-In4) ORed with one - chroma input (In5-In8) */ - CX25840_SVIDEO_LUMA1 = 0x10, - CX25840_SVIDEO_LUMA2 = 0x20, - CX25840_SVIDEO_LUMA3 = 0x30, - CX25840_SVIDEO_LUMA4 = 0x40, - CX25840_SVIDEO_CHROMA4 = 0x400, - CX25840_SVIDEO_CHROMA5 = 0x500, - CX25840_SVIDEO_CHROMA6 = 0x600, - CX25840_SVIDEO_CHROMA7 = 0x700, - CX25840_SVIDEO_CHROMA8 = 0x800, - - /* S-Video aliases for common luma/chroma combinations */ - CX25840_SVIDEO1 = 0x510, - CX25840_SVIDEO2 = 0x620, - CX25840_SVIDEO3 = 0x730, - CX25840_SVIDEO4 = 0x840, -}; - -enum cx25840_audio_input { - /* Audio inputs: serial or In4-In8 */ - CX25840_AUDIO_SERIAL, - CX25840_AUDIO4 = 4, - CX25840_AUDIO5, - CX25840_AUDIO6, - CX25840_AUDIO7, - CX25840_AUDIO8, -}; - struct cx25840_state { int pvr150_workaround; int radio; diff --git a/drivers/media/video/cx25840/cx25840-firmware.c b/drivers/media/video/cx25840/cx25840-firmware.c index e1a7823d82c..f59ced181c5 100644 --- a/drivers/media/video/cx25840/cx25840-firmware.c +++ b/drivers/media/video/cx25840/cx25840-firmware.c @@ -20,11 +20,22 @@ #include <linux/i2c-algo-bit.h> #include <linux/firmware.h> #include <media/v4l2-common.h> +#include <media/cx25840.h> -#include "cx25840.h" +#include "cx25840-core.h" #define FWFILE "v4l-cx25840.fw" -#define FWSEND 1024 + +/* + * Mike Isely <isely@pobox.com> - The FWSEND parameter controls the + * size of the firmware chunks sent down the I2C bus to the chip. + * Previously this had been set to 1024 but unfortunately some I2C + * implementations can't transfer data in such big gulps. + * Specifically, the pvrusb2 driver has a hard limit of around 60 + * bytes, due to the encapsulation there of I2C traffic into USB + * messages. So we have to significantly reduce this parameter. + */ +#define FWSEND 48 #define FWDEV(x) &((x)->adapter->dev) diff --git a/drivers/media/video/cx25840/cx25840-vbi.c b/drivers/media/video/cx25840/cx25840-vbi.c index e96fd1f1d6d..57feca288d2 100644 --- a/drivers/media/video/cx25840/cx25840-vbi.c +++ b/drivers/media/video/cx25840/cx25840-vbi.c @@ -19,8 +19,9 @@ #include <linux/videodev2.h> #include <linux/i2c.h> #include <media/v4l2-common.h> +#include <media/cx25840.h> -#include "cx25840.h" +#include "cx25840-core.h" static int odd_parity(u8 c) { @@ -151,7 +152,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) case VIDIOC_G_FMT: { static u16 lcr2vbi[] = { - 0, V4L2_SLICED_TELETEXT_PAL_B, 0, /* 1 */ + 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */ 0, V4L2_SLICED_WSS_625, 0, /* 4 */ V4L2_SLICED_CAPTION_525, /* 6 */ 0, 0, V4L2_SLICED_VPS, 0, 0, /* 9 */ @@ -231,7 +232,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) for (i = 7; i <= 23; i++) { for (x = 0; x <= 1; x++) { switch (svbi->service_lines[1-x][i]) { - case V4L2_SLICED_TELETEXT_PAL_B: + case V4L2_SLICED_TELETEXT_B: lcr[i] |= 1 << (4 * x); break; case V4L2_SLICED_WSS_625: @@ -282,7 +283,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) switch (id2) { case 1: - id2 = V4L2_SLICED_TELETEXT_PAL_B; + id2 = V4L2_SLICED_TELETEXT_B; break; case 4: id2 = V4L2_SLICED_WSS_625; diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index ff0f72340d6..630273992a4 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig @@ -1,3 +1,7 @@ +config VIDEO_CX88_VP3054 + tristate + depends on VIDEO_CX88_DVB && DVB_MT352 + config VIDEO_CX88 tristate "Conexant 2388x (bt878 successor) support" depends on VIDEO_DEV && PCI && I2C @@ -25,7 +29,7 @@ config VIDEO_CX88_ALSA It only works with boards with function 01 enabled. To check if your board supports, use lspci -n. - If supported, you should see 1471:8801 or 1471:8811 + If supported, you should see 14f1:8801 or 14f1:8811 PCI device. To compile this driver as a module, choose M here: the @@ -73,10 +77,11 @@ config VIDEO_CX88_DVB_MT352 This adds DVB-T support for cards based on the Connexant 2388x chip and the MT352 demodulator. -config VIDEO_CX88_VP3054 - tristate "VP-3054 Secondary I2C Bus Support" - default m - depends on DVB_MT352 +config VIDEO_CX88_DVB_VP3054 + bool "VP-3054 Secondary I2C Bus Support" + default y + depends on VIDEO_CX88_DVB_MT352 + select VIDEO_CX88_VP3054 ---help--- This adds DVB-T support for cards based on the Connexant 2388x chip and the MT352 demodulator, diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index f62fd706b45..3ba3439db58 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -151,8 +151,8 @@ struct em28xx_board em28xx_boards[] = { },{ .type = EM28XX_VMUX_SVIDEO, .vmux = 2, - .amux = MSP_INPUT(MSP_IN_SCART_1, MSP_IN_TUNER_1, - MSP_DSP_OUT_SCART, MSP_DSP_OUT_SCART), + .amux = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1, + MSP_DSP_IN_SCART, MSP_DSP_IN_SCART), }}, }, [EM2820_BOARD_MSI_VOX_USB_2] = { diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index dfba33d0fa6..ddc92cbb527 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -222,7 +222,7 @@ static void video_mux(struct em28xx *dev, int index) if (dev->i2s_speed) em28xx_i2c_call_clients(dev, VIDIOC_INT_I2S_CLOCK_FREQ, &dev->i2s_speed); route.input = dev->ctl_ainput; - route.output = MSP_OUTPUT(MSP_OUT_SCART1_DA); + route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1); /* Note: this is msp3400 specific */ em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, &route); ainput = EM28XX_AUDIO_SRC_TUNER; @@ -1141,26 +1141,16 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp, case VIDIOC_G_TUNER: { struct v4l2_tuner *t = arg; - int status = 0; if (0 != t->index) return -EINVAL; memset(t, 0, sizeof(*t)); strcpy(t->name, "Tuner"); - t->type = V4L2_TUNER_ANALOG_TV; - t->capability = V4L2_TUNER_CAP_NORM; - t->rangehigh = 0xffffffffUL; /* FIXME: set correct range */ -/* t->signal = 0xffff;*/ -/* em28xx_i2c_call_clients(dev,VIDIOC_G_TUNER,t);*/ - /* No way to get signal strength? */ mutex_lock(&dev->lock); - em28xx_i2c_call_clients(dev, DECODER_GET_STATUS, - &status); + /* let clients fill in the remainder of this struct */ + em28xx_i2c_call_clients(dev, cmd, t); mutex_unlock(&dev->lock); - t->signal = - (status & DECODER_STATUS_GOOD) != 0 ? 0xffff : 0; - em28xx_videodbg("VIDIO_G_TUNER: signal=%x, afc=%x\n", t->signal, t->afc); return 0; @@ -1168,26 +1158,13 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp, case VIDIOC_S_TUNER: { struct v4l2_tuner *t = arg; - int status = 0; if (0 != t->index) return -EINVAL; - memset(t, 0, sizeof(*t)); - strcpy(t->name, "Tuner"); - t->type = V4L2_TUNER_ANALOG_TV; - t->capability = V4L2_TUNER_CAP_NORM; - t->rangehigh = 0xffffffffUL; /* FIXME: set correct range */ -/* t->signal = 0xffff; */ - /* No way to get signal strength? */ mutex_lock(&dev->lock); - em28xx_i2c_call_clients(dev, DECODER_GET_STATUS, - &status); + /* let clients handle this */ + em28xx_i2c_call_clients(dev, cmd, t); mutex_unlock(&dev->lock); - t->signal = - (status & DECODER_STATUS_GOOD) != 0 ? 0xffff : 0; - - em28xx_videodbg("VIDIO_S_TUNER: signal=%x, afc=%x\n", - t->signal, t->afc); return 0; } case VIDIOC_G_FREQUENCY: diff --git a/drivers/media/video/et61x251/Kconfig b/drivers/media/video/et61x251/Kconfig new file mode 100644 index 00000000000..6c43a90c656 --- /dev/null +++ b/drivers/media/video/et61x251/Kconfig @@ -0,0 +1,14 @@ +config USB_ET61X251 + tristate "USB ET61X[12]51 PC Camera Controller support" + depends on USB && VIDEO_DEV + ---help--- + Say Y here if you want support for cameras based on Etoms ET61X151 + or ET61X251 PC Camera Controllers. + + See <file:Documentation/video4linux/et61x251.txt> for more info. + + This driver uses the Video For Linux API. You must say Y or M to + "Video For Linux" to use this driver. + + To compile this driver as a module, choose M here: the + module will be called et61x251. diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index 95bacf43541..7e66d83fe0c 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -411,6 +411,9 @@ static int ir_probe(struct i2c_adapter *adap) case I2C_HW_B_BT848: probe = probe_bttv; break; + case I2C_HW_B_CX2341X: + probe = probe_bttv; + break; case I2C_HW_SAA7134: probe = probe_saa7134; break; diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c index c40e8ba9a2e..b806999d6e0 100644 --- a/drivers/media/video/msp3400-driver.c +++ b/drivers/media/video/msp3400-driver.c @@ -279,20 +279,8 @@ void msp_set_scart(struct i2c_client *client, int in, int out) msp_write_dsp(client, 0x13, state->acb); /* Sets I2S speed 0 = 1.024 Mbps, 1 = 2.048 Mbps */ - msp_write_dem(client, 0x40, state->i2s_mode); -} - -void msp_set_mute(struct i2c_client *client) -{ - struct msp_state *state = i2c_get_clientdata(client); - - v4l_dbg(1, msp_debug, client, "mute audio\n"); - msp_write_dsp(client, 0x0000, 0); - msp_write_dsp(client, 0x0007, 1); - if (state->has_scart2_out_volume) - msp_write_dsp(client, 0x0040, 1); - if (state->has_headphones) - msp_write_dsp(client, 0x0006, 0); + if (state->has_i2s_conf) + msp_write_dem(client, 0x40, state->i2s_mode); } void msp_set_audio(struct i2c_client *client) @@ -300,17 +288,19 @@ void msp_set_audio(struct i2c_client *client) struct msp_state *state = i2c_get_clientdata(client); int bal = 0, bass, treble, loudness; int val = 0; + int reallymuted = state->muted | state->scan_in_progress; - if (!state->muted) + if (!reallymuted) val = (state->volume * 0x7f / 65535) << 8; - v4l_dbg(1, msp_debug, client, "mute=%s volume=%d\n", - state->muted ? "on" : "off", state->volume); + v4l_dbg(1, msp_debug, client, "mute=%s scanning=%s volume=%d\n", + state->muted ? "on" : "off", state->scan_in_progress ? "yes" : "no", + state->volume); msp_write_dsp(client, 0x0000, val); - msp_write_dsp(client, 0x0007, state->muted ? 0x1 : (val | 0x1)); + msp_write_dsp(client, 0x0007, reallymuted ? 0x1 : (val | 0x1)); if (state->has_scart2_out_volume) - msp_write_dsp(client, 0x0040, state->muted ? 0x1 : (val | 0x1)); + msp_write_dsp(client, 0x0040, reallymuted ? 0x1 : (val | 0x1)); if (state->has_headphones) msp_write_dsp(client, 0x0006, val); if (!state->has_sound_processing) @@ -346,7 +336,6 @@ static void msp_wake_thread(struct i2c_client *client) if (NULL == state->kthread) return; - msp_set_mute(client); state->watch_stereo = 0; state->restart = 1; wake_up_interruptible(&state->wq); @@ -374,19 +363,15 @@ int msp_sleep(struct msp_state *state, int timeout) /* ------------------------------------------------------------------------ */ -static int msp_mode_v4l2_to_v4l1(int rxsubchans) +static int msp_mode_v4l2_to_v4l1(int rxsubchans, int audmode) { - int mode = 0; - - if (rxsubchans & V4L2_TUNER_SUB_STEREO) - mode |= VIDEO_SOUND_STEREO; - if (rxsubchans & V4L2_TUNER_SUB_LANG2) - mode |= VIDEO_SOUND_LANG2 | VIDEO_SOUND_STEREO; - if (rxsubchans & V4L2_TUNER_SUB_LANG1) - mode |= VIDEO_SOUND_LANG1 | VIDEO_SOUND_STEREO; - if (mode == 0) - mode |= VIDEO_SOUND_MONO; - return mode; + if (rxsubchans == V4L2_TUNER_SUB_MONO) + return VIDEO_SOUND_MONO; + if (rxsubchans == V4L2_TUNER_SUB_STEREO) + return VIDEO_SOUND_STEREO; + if (audmode == V4L2_TUNER_MODE_LANG2) + return VIDEO_SOUND_LANG2; + return VIDEO_SOUND_LANG1; } static int msp_mode_v4l1_to_v4l2(int mode) @@ -605,7 +590,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) break; if (state->opmode == OPMODE_AUTOSELECT) msp_detect_stereo(client); - va->mode = msp_mode_v4l2_to_v4l1(state->rxsubchans); + va->mode = msp_mode_v4l2_to_v4l1(state->rxsubchans, state->audmode); break; } @@ -620,7 +605,8 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) state->treble = va->treble; msp_set_audio(client); - if (va->mode != 0 && state->radio == 0) { + if (va->mode != 0 && state->radio == 0 && + state->audmode != msp_mode_v4l1_to_v4l2(va->mode)) { state->audmode = msp_mode_v4l1_to_v4l2(va->mode); msp_set_audmode(client); } @@ -687,21 +673,23 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) int sc_in = rt->input & 0x7; int sc1_out = rt->output & 0xf; int sc2_out = (rt->output >> 4) & 0xf; - u16 val; + u16 val, reg; + if (state->routing.input == rt->input && + state->routing.output == rt->output) + break; state->routing = *rt; - if (state->opmode == OPMODE_AUTOSELECT) { - val = msp_read_dem(client, 0x30) & ~0x100; - msp_write_dem(client, 0x30, val | (tuner ? 0x100 : 0)); - } else { - val = msp_read_dem(client, 0xbb) & ~0x100; - msp_write_dem(client, 0xbb, val | (tuner ? 0x100 : 0)); - } msp_set_scart(client, sc_in, 0); msp_set_scart(client, sc1_out, 1); msp_set_scart(client, sc2_out, 2); msp_set_audmode(client); - msp_wake_thread(client); + reg = (state->opmode == OPMODE_AUTOSELECT) ? 0x30 : 0xbb; + val = msp_read_dem(client, reg); + if (tuner != ((val >> 8) & 1)) { + msp_write_dem(client, reg, (val & ~0x100) | (tuner << 8)); + /* wake thread when a new tuner input is chosen */ + msp_wake_thread(client); + } break; } @@ -715,7 +703,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) msp_detect_stereo(client); vt->audmode = state->audmode; vt->rxsubchans = state->rxsubchans; - vt->capability = V4L2_TUNER_CAP_STEREO | + vt->capability |= V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2; break; } @@ -726,6 +714,8 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) if (state->radio) /* TODO: add mono/stereo support for radio */ break; + if (state->audmode == vt->audmode) + break; state->audmode = vt->audmode; /* only set audmode */ msp_set_audmode(client); @@ -887,7 +877,7 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind) memset(state, 0, sizeof(*state)); state->v4l2_std = V4L2_STD_NTSC; - state->audmode = V4L2_TUNER_MODE_LANG1; + state->audmode = V4L2_TUNER_MODE_STEREO; state->volume = 58880; /* 0db gain */ state->balance = 32768; /* 0db gain */ state->bass = 32768; @@ -931,13 +921,16 @@ static int msp_attach(struct i2c_adapter *adapter, int address, int kind) state->has_radio = msp_revision >= 'G'; /* Has headphones output: not for stripped down products */ state->has_headphones = msp_prod_lo < 5; + /* Has scart2 input: not in stripped down products of the '3' family */ + state->has_scart2 = msp_family >= 4 || msp_prod_lo < 7; + /* Has scart3 input: not in stripped down products of the '3' family */ + state->has_scart3 = msp_family >= 4 || msp_prod_lo < 5; /* Has scart4 input: not in pre D revisions, not in stripped D revs */ state->has_scart4 = msp_family >= 4 || (msp_revision >= 'D' && msp_prod_lo < 5); - /* Has scart2 and scart3 inputs and scart2 output: not in stripped - down products of the '3' family */ - state->has_scart23_in_scart2_out = msp_family >= 4 || msp_prod_lo < 5; + /* Has scart2 output: not in stripped down products of the '3' family */ + state->has_scart2_out = msp_family >= 4 || msp_prod_lo < 5; /* Has scart2 a volume control? Not in pre-D revisions. */ - state->has_scart2_out_volume = msp_revision > 'C' && state->has_scart23_in_scart2_out; + state->has_scart2_out_volume = msp_revision > 'C' && state->has_scart2_out; /* Has a configurable i2s out? */ state->has_i2s_conf = msp_revision >= 'G' && msp_prod_lo < 7; /* Has subwoofer output: not in pre-D revs and not in stripped down products */ diff --git a/drivers/media/video/msp3400-driver.h b/drivers/media/video/msp3400-driver.h index 1940748bb63..4e451049013 100644 --- a/drivers/media/video/msp3400-driver.h +++ b/drivers/media/video/msp3400-driver.h @@ -54,8 +54,10 @@ struct msp_state { u8 has_radio; u8 has_headphones; u8 has_ntsc_jp_d_k3; + u8 has_scart2; + u8 has_scart3; u8 has_scart4; - u8 has_scart23_in_scart2_out; + u8 has_scart2_out; u8 has_scart2_out_volume; u8 has_i2s_conf; u8 has_subwoofer; @@ -83,6 +85,7 @@ struct msp_state { int volume, muted; int balance, loudness; int bass, treble; + int scan_in_progress; /* thread */ struct task_struct *kthread; @@ -98,7 +101,6 @@ int msp_read_dem(struct i2c_client *client, int addr); int msp_read_dsp(struct i2c_client *client, int addr); int msp_reset(struct i2c_client *client); void msp_set_scart(struct i2c_client *client, int in, int out); -void msp_set_mute(struct i2c_client *client); void msp_set_audio(struct i2c_client *client); int msp_sleep(struct msp_state *state, int timeout); diff --git a/drivers/media/video/msp3400-kthreads.c b/drivers/media/video/msp3400-kthreads.c index c3984ea9ca0..633a1021378 100644 --- a/drivers/media/video/msp3400-kthreads.c +++ b/drivers/media/video/msp3400-kthreads.c @@ -170,7 +170,7 @@ static void msp_set_source(struct i2c_client *client, u16 src) msp_write_dsp(client, 0x000a, src); msp_write_dsp(client, 0x000b, src); msp_write_dsp(client, 0x000c, src); - if (state->has_scart23_in_scart2_out) + if (state->has_scart2_out) msp_write_dsp(client, 0x0041, src); } @@ -228,6 +228,7 @@ static void msp3400c_set_audmode(struct i2c_client *client) char *modestr = (state->audmode >= 0 && state->audmode < 5) ? strmode[state->audmode] : "unknown"; int src = 0; /* channel source: FM/AM, nicam or SCART */ + int audmode = state->audmode; if (state->opmode == OPMODE_AUTOSELECT) { /* this method would break everything, let's make sure @@ -239,11 +240,29 @@ static void msp3400c_set_audmode(struct i2c_client *client) return; } + /* Note: for the C and D revs no NTSC stereo + SAP is possible as + the hardware does not support SAP. So the rxsubchans combination + of STEREO | LANG2 does not occur. */ + + /* switch to mono if only mono is available */ + if (state->rxsubchans == V4L2_TUNER_SUB_MONO) + audmode = V4L2_TUNER_MODE_MONO; + /* if bilingual */ + else if (state->rxsubchans & V4L2_TUNER_SUB_LANG2) { + /* and mono or stereo, then fallback to lang1 */ + if (audmode == V4L2_TUNER_MODE_MONO || + audmode == V4L2_TUNER_MODE_STEREO) + audmode = V4L2_TUNER_MODE_LANG1; + } + /* if stereo, and audmode is not mono, then switch to stereo */ + else if (audmode != V4L2_TUNER_MODE_MONO) + audmode = V4L2_TUNER_MODE_STEREO; + /* switch demodulator */ switch (state->mode) { case MSP_MODE_FM_TERRA: v4l_dbg(1, msp_debug, client, "FM set_audmode: %s\n", modestr); - switch (state->audmode) { + switch (audmode) { case V4L2_TUNER_MODE_STEREO: msp_write_dsp(client, 0x000e, 0x3001); break; @@ -257,7 +276,7 @@ static void msp3400c_set_audmode(struct i2c_client *client) break; case MSP_MODE_FM_SAT: v4l_dbg(1, msp_debug, client, "SAT set_audmode: %s\n", modestr); - switch (state->audmode) { + switch (audmode) { case V4L2_TUNER_MODE_MONO: msp3400c_set_carrier(client, MSP_CARRIER(6.5), MSP_CARRIER(6.5)); break; @@ -296,7 +315,8 @@ static void msp3400c_set_audmode(struct i2c_client *client) } /* switch audio */ - switch (state->audmode) { + v4l_dbg(1, msp_debug, client, "set audmode %d\n", audmode); + switch (audmode) { case V4L2_TUNER_MODE_STEREO: case V4L2_TUNER_MODE_LANG1_LANG2: src |= 0x0020; @@ -314,10 +334,6 @@ static void msp3400c_set_audmode(struct i2c_client *client) src = 0x0030; break; case V4L2_TUNER_MODE_LANG1: - /* switch to stereo for stereo transmission, otherwise - keep first language */ - if (state->rxsubchans & V4L2_TUNER_SUB_STEREO) - src |= 0x0020; break; case V4L2_TUNER_MODE_LANG2: src |= 0x0010; @@ -367,7 +383,7 @@ static int msp3400c_detect_stereo(struct i2c_client *client) if (val > 32767) val -= 65536; v4l_dbg(2, msp_debug, client, "stereo detect register: %d\n", val); - if (val > 4096) { + if (val > 8192) { rxsubchans = V4L2_TUNER_SUB_STEREO; } else if (val < -4096) { rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; @@ -464,19 +480,22 @@ int msp3400c_thread(void *data) if (state->radio || MSP_MODE_EXTERN == state->mode) { /* no carrier scan, just unmute */ v4l_dbg(1, msp_debug, client, "thread: no carrier scan\n"); + state->scan_in_progress = 0; msp_set_audio(client); continue; } - /* mute */ - msp_set_mute(client); + /* mute audio */ + state->scan_in_progress = 1; + msp_set_audio(client); + msp3400c_set_mode(client, MSP_MODE_AM_DETECT); val1 = val2 = 0; max1 = max2 = -1; state->watch_stereo = 0; state->nicam_on = 0; - /* some time for the tuner to sync */ + /* wait for tuner to settle down after a channel change */ if (msp_sleep(state, 200)) goto restart; @@ -552,7 +571,6 @@ int msp3400c_thread(void *data) /* B/G NICAM */ state->second = msp3400c_carrier_detect_55[max2].cdo; msp3400c_set_mode(client, MSP_MODE_FM_NICAM1); - msp3400c_set_carrier(client, state->second, state->main); state->nicam_on = 1; state->watch_stereo = 1; } else { @@ -563,7 +581,6 @@ int msp3400c_thread(void *data) /* PAL I NICAM */ state->second = MSP_CARRIER(6.552); msp3400c_set_mode(client, MSP_MODE_FM_NICAM2); - msp3400c_set_carrier(client, state->second, state->main); state->nicam_on = 1; state->watch_stereo = 1; break; @@ -577,13 +594,11 @@ int msp3400c_thread(void *data) /* L NICAM or AM-mono */ state->second = msp3400c_carrier_detect_65[max2].cdo; msp3400c_set_mode(client, MSP_MODE_AM_NICAM); - msp3400c_set_carrier(client, state->second, state->main); state->watch_stereo = 1; } else if (max2 == 0 && state->has_nicam) { /* D/K NICAM */ state->second = msp3400c_carrier_detect_65[max2].cdo; msp3400c_set_mode(client, MSP_MODE_FM_NICAM1); - msp3400c_set_carrier(client, state->second, state->main); state->nicam_on = 1; state->watch_stereo = 1; } else { @@ -595,25 +610,25 @@ int msp3400c_thread(void *data) no_second: state->second = msp3400c_carrier_detect_main[max1].cdo; msp3400c_set_mode(client, MSP_MODE_FM_TERRA); - msp3400c_set_carrier(client, state->second, state->main); - state->rxsubchans = V4L2_TUNER_SUB_MONO; break; } + msp3400c_set_carrier(client, state->second, state->main); /* unmute */ - msp_set_audio(client); + state->scan_in_progress = 0; msp3400c_set_audmode(client); + msp_set_audio(client); if (msp_debug) msp3400c_print_mode(client); /* monitor tv audio mode, the first time don't wait so long to get a quick stereo/bilingual result */ - if (msp_sleep(state, 1000)) - goto restart; + count = 3; while (state->watch_stereo) { - if (msp_sleep(state, 5000)) + if (msp_sleep(state, count ? 1000 : 5000)) goto restart; + if (count) count--; watch_stereo(client); } } @@ -626,7 +641,7 @@ int msp3410d_thread(void *data) { struct i2c_client *client = data; struct msp_state *state = i2c_get_clientdata(client); - int val, i, std; + int val, i, std, count; v4l_dbg(1, msp_debug, client, "msp3410 daemon started\n"); @@ -644,16 +659,14 @@ int msp3410d_thread(void *data) if (state->mode == MSP_MODE_EXTERN) { /* no carrier scan needed, just unmute */ v4l_dbg(1, msp_debug, client, "thread: no carrier scan\n"); + state->scan_in_progress = 0; msp_set_audio(client); continue; } - /* put into sane state (and mute) */ - msp_reset(client); - - /* some time for the tuner to sync */ - if (msp_sleep(state,200)) - goto restart; + /* mute audio */ + state->scan_in_progress = 1; + msp_set_audio(client); /* start autodetect. Note: autodetect is not supported for NTSC-M and radio, hence we force the standard in those cases. */ @@ -664,6 +677,10 @@ int msp3410d_thread(void *data) state->watch_stereo = 0; state->nicam_on = 0; + /* wait for tuner to settle down after a channel change */ + if (msp_sleep(state, 200)) + goto restart; + if (msp_debug) v4l_dbg(2, msp_debug, client, "setting standard: %s (0x%04x)\n", msp_standard_std_name(std), std); @@ -693,6 +710,7 @@ int msp3410d_thread(void *data) state->main = msp_stdlist[i].main; state->second = msp_stdlist[i].second; state->std = val; + state->rxsubchans = V4L2_TUNER_SUB_MONO; if (msp_amsound && !state->radio && (state->v4l2_std & V4L2_STD_SECAM) && (val != 0x0009)) { @@ -714,20 +732,17 @@ int msp3410d_thread(void *data) else state->mode = MSP_MODE_FM_NICAM1; /* just turn on stereo */ - state->rxsubchans = V4L2_TUNER_SUB_STEREO; state->nicam_on = 1; state->watch_stereo = 1; break; case 0x0009: state->mode = MSP_MODE_AM_NICAM; - state->rxsubchans = V4L2_TUNER_SUB_MONO; state->nicam_on = 1; state->watch_stereo = 1; break; case 0x0020: /* BTSC */ /* The pre-'G' models only have BTSC-mono */ state->mode = MSP_MODE_BTSC; - state->rxsubchans = V4L2_TUNER_SUB_MONO; break; case 0x0040: /* FM radio */ state->mode = MSP_MODE_FM_RADIO; @@ -737,15 +752,12 @@ int msp3410d_thread(void *data) msp3400c_set_mode(client, MSP_MODE_FM_RADIO); msp3400c_set_carrier(client, MSP_CARRIER(10.7), MSP_CARRIER(10.7)); - /* scart routing (this doesn't belong here I think) */ - msp_set_scart(client,SCART_IN2,0); break; case 0x0002: case 0x0003: case 0x0004: case 0x0005: state->mode = MSP_MODE_FM_TERRA; - state->rxsubchans = V4L2_TUNER_SUB_MONO; state->watch_stereo = 1; break; } @@ -759,20 +771,19 @@ int msp3410d_thread(void *data) if (state->has_i2s_conf) msp_write_dem(client, 0x40, state->i2s_mode); - /* unmute, restore misc registers */ - msp_set_audio(client); - - msp_write_dsp(client, 0x13, state->acb); + /* unmute */ msp3400c_set_audmode(client); + state->scan_in_progress = 0; + msp_set_audio(client); /* monitor tv audio mode, the first time don't wait so long to get a quick stereo/bilingual result */ - if (msp_sleep(state, 1000)) - goto restart; + count = 3; while (state->watch_stereo) { - watch_stereo(client); - if (msp_sleep(state, 5000)) + if (msp_sleep(state, count ? 1000 : 5000)) goto restart; + if (count) count--; + watch_stereo(client); } } v4l_dbg(1, msp_debug, client, "thread: exit\n"); @@ -829,27 +840,27 @@ static void msp34xxg_set_source(struct i2c_client *client, u16 reg, int in) source = 0; /* mono only */ matrix = 0x30; break; - case V4L2_TUNER_MODE_LANG1: - source = 3; /* stereo or A */ - matrix = 0x00; - break; case V4L2_TUNER_MODE_LANG2: source = 4; /* stereo or B */ matrix = 0x10; break; - case V4L2_TUNER_MODE_STEREO: case V4L2_TUNER_MODE_LANG1_LANG2: - default: source = 1; /* stereo or A|B */ matrix = 0x20; break; + case V4L2_TUNER_MODE_STEREO: + case V4L2_TUNER_MODE_LANG1: + default: + source = 3; /* stereo or A */ + matrix = 0x00; + break; } - if (in == MSP_DSP_OUT_TUNER) + if (in == MSP_DSP_IN_TUNER) source = (source << 8) | 0x20; /* the msp34x2g puts the MAIN_AVC, MAIN and AUX sources in 12, 13, 14 instead of 11, 12, 13. So we add one for that msp version. */ - else if (in >= MSP_DSP_OUT_MAIN_AVC && state->has_dolby_pro_logic) + else if (in >= MSP_DSP_IN_MAIN_AVC && state->has_dolby_pro_logic) source = ((in + 1) << 8) | matrix; else source = (in << 8) | matrix; @@ -869,7 +880,7 @@ static void msp34xxg_set_sources(struct i2c_client *client) msp34xxg_set_source(client, 0x000c, (in >> 4) & 0xf); msp34xxg_set_source(client, 0x0009, (in >> 8) & 0xf); msp34xxg_set_source(client, 0x000a, (in >> 12) & 0xf); - if (state->has_scart23_in_scart2_out) + if (state->has_scart2_out) msp34xxg_set_source(client, 0x0041, (in >> 16) & 0xf); msp34xxg_set_source(client, 0x000b, (in >> 20) & 0xf); } @@ -887,10 +898,6 @@ static void msp34xxg_reset(struct i2c_client *client) msp_reset(client); - /* make sure that input/output is muted (paranoid mode) */ - /* ACB, mute DSP input, mute SCART 1 */ - msp_write_dsp(client, 0x13, 0x0f20); - if (state->has_i2s_conf) msp_write_dem(client, 0x40, state->i2s_mode); @@ -1028,7 +1035,7 @@ static void msp34xxg_set_audmode(struct i2c_client *client) if (state->std == 0x20) { if ((state->rxsubchans & V4L2_TUNER_SUB_SAP) && - (state->audmode == V4L2_TUNER_MODE_STEREO || + (state->audmode == V4L2_TUNER_MODE_LANG1_LANG2 || state->audmode == V4L2_TUNER_MODE_LANG2)) { msp_write_dem(client, 0x20, 0x21); } else { diff --git a/drivers/media/video/pwc/Kconfig b/drivers/media/video/pwc/Kconfig new file mode 100644 index 00000000000..86376556f10 --- /dev/null +++ b/drivers/media/video/pwc/Kconfig @@ -0,0 +1,28 @@ +config USB_PWC + tristate "USB Philips Cameras" + depends on USB && VIDEO_DEV + ---help--- + Say Y or M here if you want to use one of these Philips & OEM + webcams: + * Philips PCA645, PCA646 + * Philips PCVC675, PCVC680, PCVC690 + * Philips PCVC720/40, PCVC730, PCVC740, PCVC750 + * Askey VC010 + * Logitech QuickCam Pro 3000, 4000, 'Zoom', 'Notebook Pro' + and 'Orbit'/'Sphere' + * Samsung MPC-C10, MPC-C30 + * Creative Webcam 5, Pro Ex + * SOTEC Afina Eye + * Visionite VCS-UC300, VCS-UM100 + + The PCA635, PCVC665 and PCVC720/20 are not supported by this driver + and never will be, but the 665 and 720/20 are supported by other + drivers. + + See <file:Documentation/usb/philips.txt> for more information and + installation instructions. + + The built-in microphone is enabled by selecting USB Audio support. + + To compile this driver as a module, choose M here: the + module will be called pwc. diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index b0501528260..dceebc0b125 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -40,6 +40,7 @@ #include <linux/i2c.h> #include <linux/videodev2.h> #include <media/v4l2-common.h> +#include <media/saa7115.h> #include <asm/div64.h> MODULE_DESCRIPTION("Philips SAA7113/SAA7114/SAA7115 video decoder driver"); @@ -53,7 +54,7 @@ module_param(debug, bool, 0644); MODULE_PARM_DESC(debug, "Debug level (0-1)"); static unsigned short normal_i2c[] = { - 0x4a >>1, 0x48 >>1, /* SAA7113 */ + 0x4a >> 1, 0x48 >> 1, /* SAA7113 */ 0x42 >> 1, 0x40 >> 1, /* SAA7114 and SAA7115 */ I2C_CLIENT_END }; @@ -722,16 +723,16 @@ static void saa7115_set_v4lstd(struct i2c_client *client, v4l2_std_id std) 100 reserved NTSC-Japan (3.58MHz) */ if (state->ident == V4L2_IDENT_SAA7113) { - u8 reg = saa7115_read(client, 0x0e) & 0x8f; + u8 reg = saa7115_read(client, 0x0e) & 0x8f; if (std == V4L2_STD_PAL_M) { - reg|=0x30; + reg |= 0x30; } else if (std == V4L2_STD_PAL_N) { - reg|=0x20; + reg |= 0x20; } else if (std == V4L2_STD_PAL_60) { - reg|=0x10; + reg |= 0x10; } else if (std == V4L2_STD_NTSC_M_JP) { - reg|=0x40; + reg |= 0x40; } saa7115_write(client, 0x0e, reg); } @@ -811,7 +812,7 @@ static void saa7115_set_lcr(struct i2c_client *client, struct v4l2_sliced_vbi_fo u8 lcr[24]; int i, x; - /* saa7113/71144 doesn't yet support VBI */ + /* saa7113/7114 doesn't yet support VBI */ if (state->ident != V4L2_IDENT_SAA7115) return; @@ -851,7 +852,7 @@ static void saa7115_set_lcr(struct i2c_client *client, struct v4l2_sliced_vbi_fo case 0: lcr[i] |= 0xf << (4 * x); break; - case V4L2_SLICED_TELETEXT_PAL_B: + case V4L2_SLICED_TELETEXT_B: lcr[i] |= 1 << (4 * x); break; case V4L2_SLICED_CAPTION_525: @@ -880,7 +881,7 @@ static void saa7115_set_lcr(struct i2c_client *client, struct v4l2_sliced_vbi_fo static int saa7115_get_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt) { static u16 lcr2vbi[] = { - 0, V4L2_SLICED_TELETEXT_PAL_B, 0, /* 1 */ + 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */ 0, V4L2_SLICED_CAPTION_525, /* 4 */ V4L2_SLICED_WSS_625, 0, /* 5 */ V4L2_SLICED_VPS, 0, 0, 0, 0, /* 7 */ @@ -1045,7 +1046,7 @@ static void saa7115_decode_vbi_line(struct i2c_client *client, /* decode payloads */ switch (id2) { case 1: - vbi->type = V4L2_SLICED_TELETEXT_PAL_B; + vbi->type = V4L2_SLICED_TELETEXT_B; break; case 4: if (!saa7115_odd_parity(p[0]) || !saa7115_odd_parity(p[1])) @@ -1180,6 +1181,46 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar state->radio = 1; break; + case VIDIOC_INT_G_VIDEO_ROUTING: + { + struct v4l2_routing *route = arg; + + route->input = state->input; + route->output = 0; + break; + } + + case VIDIOC_INT_S_VIDEO_ROUTING: + { + struct v4l2_routing *route = arg; + + v4l_dbg(1, debug, client, "decoder set input %d\n", route->input); + /* saa7113 does not have these inputs */ + if (state->ident == V4L2_IDENT_SAA7113 && + (route->input == SAA7115_COMPOSITE4 || + route->input == SAA7115_COMPOSITE5)) { + return -EINVAL; + } + if (route->input > SAA7115_SVIDEO3) + return -EINVAL; + if (state->input == route->input) + break; + v4l_dbg(1, debug, client, "now setting %s input\n", + (route->input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite"); + state->input = route->input; + + /* select mode */ + saa7115_write(client, 0x02, + (saa7115_read(client, 0x02) & 0xf0) | + state->input); + + /* bypass chrominance trap for S-Video modes */ + saa7115_write(client, 0x09, + (saa7115_read(client, 0x09) & 0x7f) | + (state->input >= SAA7115_SVIDEO0 ? 0x80 : 0x0)); + break; + } + case VIDIOC_G_INPUT: *(int *)arg = state->input; break; @@ -1321,7 +1362,7 @@ static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind) saa7115_write(client, 0, 5); chip_id = saa7115_read(client, 0) & 0x0f; - if (chip_id <3 && chip_id > 5) { + if (chip_id < 3 && chip_id > 5) { v4l_dbg(1, debug, client, "saa7115 not found\n"); kfree(client); return 0; @@ -1360,7 +1401,7 @@ static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind) v4l_dbg(1, debug, client, "writing init values\n"); /* init to 60hz/48khz */ - if (state->ident==V4L2_IDENT_SAA7113) + if (state->ident == V4L2_IDENT_SAA7113) saa7115_writeregs(client, saa7113_init_auto_input); else saa7115_writeregs(client, saa7115_init_auto_input); diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c index 992c71774f3..133f9e5252f 100644 --- a/drivers/media/video/saa7127.c +++ b/drivers/media/video/saa7127.c @@ -54,6 +54,7 @@ #include <linux/i2c.h> #include <linux/videodev2.h> #include <media/v4l2-common.h> +#include <media/saa7127.h> static int debug = 0; static int test_image = 0; @@ -222,22 +223,6 @@ static struct i2c_reg_value saa7127_init_config_50hz[] = { { 0, 0 } }; -/* Enumeration for the Supported input types */ -enum saa7127_input_type { - SAA7127_INPUT_TYPE_NORMAL, - SAA7127_INPUT_TYPE_TEST_IMAGE -}; - -/* Enumeration for the Supported Output signal types */ -enum saa7127_output_type { - SAA7127_OUTPUT_TYPE_BOTH, - SAA7127_OUTPUT_TYPE_COMPOSITE, - SAA7127_OUTPUT_TYPE_SVIDEO, - SAA7127_OUTPUT_TYPE_RGB, - SAA7127_OUTPUT_TYPE_YUV_C, - SAA7127_OUTPUT_TYPE_YUV_V -}; - /* ********************************************************************** * @@ -561,7 +546,7 @@ static int saa7127_command(struct i2c_client *client, { struct saa7127_state *state = i2c_get_clientdata(client); struct v4l2_format *fmt = arg; - int *iarg = arg; + struct v4l2_routing *route = arg; switch (cmd) { case VIDIOC_S_STD: @@ -573,15 +558,23 @@ static int saa7127_command(struct i2c_client *client, *(v4l2_std_id *)arg = state->std; break; - case VIDIOC_S_INPUT: - if (state->input_type == *iarg) - break; - return saa7127_set_input_type(client, *iarg); + case VIDIOC_INT_G_VIDEO_ROUTING: + route->input = state->input_type; + route->output = state->output_type; + break; - case VIDIOC_S_OUTPUT: - if (state->output_type == *iarg) - break; - return saa7127_set_output_type(client, *iarg); + case VIDIOC_INT_S_VIDEO_ROUTING: + { + int rc = 0; + + if (state->input_type != route->input) { + rc = saa7127_set_input_type(client, route->input); + } + if (rc == 0 && state->output_type != route->output) { + rc = saa7127_set_output_type(client, route->output); + } + return rc; + } case VIDIOC_STREAMON: case VIDIOC_STREAMOFF: diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig index 86671a43e76..e1c1805df1f 100644 --- a/drivers/media/video/saa7134/Kconfig +++ b/drivers/media/video/saa7134/Kconfig @@ -39,6 +39,7 @@ config VIDEO_SAA7134_DVB tristate "DVB/ATSC Support for saa7134 based TV cards" depends on VIDEO_SAA7134 && DVB_CORE select VIDEO_BUF_DVB + select FW_LOADER ---help--- This adds support for DVB cards based on the Philips saa7134 chip. diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index fdd7f48f3b7..e666a4465ca 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -208,7 +208,7 @@ struct saa7134_board saa7134_boards[] = { [SAA7134_BOARD_FLYTVPLATINUM_FM] = { /* LifeView FlyTV Platinum FM (LR214WF) */ /* "Peter Missel <peter.missel@onlinehome.de> */ - .name = "LifeView FlyTV Platinum FM", + .name = "LifeView FlyTV Platinum FM / Gold", .audio_clock = 0x00200000, .tuner_type = TUNER_PHILIPS_TDA8290, .radio_type = UNSET, @@ -2660,7 +2660,7 @@ struct saa7134_board saa7134_boards[] = { .mpeg = SAA7134_MPEG_DVB, .inputs = {{ .name = name_comp1, - .vmux = 0, + .vmux = 1, .amux = LINE1, },{ .name = name_svideo, @@ -2671,7 +2671,7 @@ struct saa7134_board saa7134_boards[] = { [SAA7134_BOARD_FLYDVBT_LR301] = { /* LifeView FlyDVB-T */ /* Giampiero Giancipoli <gianci@libero.it> */ - .name = "LifeView FlyDVB-T", + .name = "LifeView FlyDVB-T / Genius VideoWonder DVB-T", .audio_clock = 0x00200000, .tuner_type = TUNER_ABSENT, .radio_type = UNSET, @@ -2808,6 +2808,40 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, + [SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS] = { + .name = "LifeView FlyDVB-T Hybrid Cardbus", + .audio_clock = 0x00200000, + .tuner_type = TUNER_PHILIPS_TDA8290, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .mpeg = SAA7134_MPEG_DVB, + .gpiomask = 0x00600000, /* Bit 21 0=Radio, Bit 22 0=TV */ + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .gpio = 0x200000, /* GPIO21=High for TV input */ + .tv = 1, + },{ + .name = name_svideo, /* S-Video signal on S-Video input */ + .vmux = 8, + .amux = LINE2, + },{ + .name = name_comp1, /* Composite signal on S-Video input */ + .vmux = 0, + .amux = LINE2, + },{ + .name = name_comp2, /* Composite input */ + .vmux = 3, + .amux = LINE2, + }}, + .radio = { + .name = name_radio, + .amux = TV, + .gpio = 0x000000, /* GPIO21=Low for FM radio antenna */ + }, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -3333,6 +3367,30 @@ struct pci_device_id saa7134_pci_tbl[] = { .subdevice = 0x0005, .driver_data = SAA7134_BOARD_MD7134_BRIDGE_2, },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7134, + .subvendor = 0x1489, + .subdevice = 0x0301, + .driver_data = SAA7134_BOARD_FLYDVBT_LR301, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x5168, /* Animation Technologies (LifeView) */ + .subdevice = 0x0304, + .driver_data = SAA7134_BOARD_FLYTVPLATINUM_FM, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x5168, + .subdevice = 0x3306, + .driver_data = SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x5168, + .subdevice = 0x3502, /* whats the difference to 0x3306 ?*/ + .driver_data = SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS, + },{ /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, @@ -3462,6 +3520,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) saa_writeb(SAA7134_GPIO_GPSTATUS3, 0x06); break; case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331: + case SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS: saa_writeb(SAA7134_GPIO_GPMODE3, 0x08); saa_writeb(SAA7134_GPIO_GPSTATUS3, 0x00); break; @@ -3633,6 +3692,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) } break; case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331: + case SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS: /* make the tda10046 find its eeprom */ { u8 data[] = { 0x3c, 0x33, 0x62}; diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 86cfdb8514c..222a36c3891 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -1064,6 +1064,10 @@ static int dvb_init(struct saa7134_dev *dev) dev->dvb.frontend = tda10046_attach(&tevion_dvbt220rf_config, &dev->i2c_adap); break; + case SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS: + dev->dvb.frontend = tda10046_attach(&ads_tech_duo_config, + &dev->i2c_adap); + break; #endif #ifdef HAVE_NXT200X case SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180: diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 31ba293854c..353af3a8b76 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -220,6 +220,7 @@ struct saa7134_format { #define SAA7134_BOARD_AVERMEDIA_A169_B 91 #define SAA7134_BOARD_AVERMEDIA_A169_B1 92 #define SAA7134_BOARD_MD7134_BRIDGE_2 93 +#define SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS 94 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 diff --git a/drivers/media/video/sn9c102/Kconfig b/drivers/media/video/sn9c102/Kconfig new file mode 100644 index 00000000000..55f2bc11964 --- /dev/null +++ b/drivers/media/video/sn9c102/Kconfig @@ -0,0 +1,11 @@ +config USB_SN9C102 + tristate "USB SN9C10x PC Camera Controller support" + depends on USB && VIDEO_DEV + ---help--- + Say Y here if you want support for cameras based on SONiX SN9C101, + SN9C102 or SN9C103 PC Camera Controllers. + + See <file:Documentation/video4linux/sn9c102.txt> for more info. + + To compile this driver as a module, choose M here: the + module will be called sn9c102. diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index df195c90536..1013b4de89a 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -401,7 +401,7 @@ static void tuner_status(struct i2c_client *client) } tuner_info("Tuner mode: %s\n", p); tuner_info("Frequency: %lu.%02lu MHz\n", freq, freq_fraction); - tuner_info("Standard: 0x%08llx\n", t->std); + tuner_info("Standard: 0x%08lx\n", (unsigned long)t->std); if (t->mode != V4L2_TUNER_RADIO) return; if (t->has_signal) { @@ -558,10 +558,10 @@ static inline int set_mode(struct i2c_client *client, struct tuner *t, int mode, static inline int check_v4l2(struct tuner *t) { - if (t->using_v4l2) { - tuner_dbg ("ignore v4l1 call\n"); - return EINVAL; - } + /* bttv still uses both v4l1 and v4l2 calls to the tuner (v4l2 for + TV, v4l1 for radio), until that is fixed this code is disabled. + Otherwise the radio (v4l1) wouldn't tune after using the TV (v4l2) + first. */ return 0; } @@ -744,6 +744,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) switch_v4l2(); tuner->type = t->mode; + if (t->mode == V4L2_TUNER_ANALOG_TV) + tuner->capability |= V4L2_TUNER_CAP_NORM; if (t->mode != V4L2_TUNER_RADIO) { tuner->rangelow = tv_range[0] * 16; tuner->rangehigh = tv_range[1] * 16; diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 356bff455ad..c2b75610754 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -1706,21 +1706,6 @@ static int chip_command(struct i2c_client *client, break; } - case VIDIOC_S_AUDIO: - { - struct v4l2_audio *sarg = arg; - - if (!(desc->flags & CHIP_HAS_INPUTSEL) || sarg->index >= 4) - return -EINVAL; - /* There are four inputs: tuner, radio, extern and intern. */ - chip->input = sarg->index; - if (chip->muted) - break; - chip_write_masked(chip, desc->inputreg, - desc->inputmap[chip->input], desc->inputmask); - break; - } - case VIDIOC_S_TUNER: { struct v4l2_tuner *vt = arg; diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index e0d2ff83fc9..431c3e2f6c4 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c @@ -757,9 +757,9 @@ tveeprom_detect_client(struct i2c_adapter *adapter, static int tveeprom_attach_adapter (struct i2c_adapter *adapter) { - if (adapter->id != I2C_HW_B_BT848) - return 0; - return i2c_probe(adapter, &addr_data, tveeprom_detect_client); + if (adapter->class & I2C_CLASS_TV_ANALOG) + return i2c_probe(adapter, &addr_data, tveeprom_detect_client); + return 0; } static int diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index 69d0fe159f4..dab4973bcf8 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c @@ -53,7 +53,7 @@ static struct v4l2_queryctrl tvp5150_qctrl[] = { .minimum = 0, .maximum = 255, .step = 1, - .default_value = 0, + .default_value = 128, .flags = 0, }, { .id = V4L2_CID_CONTRAST, @@ -62,7 +62,7 @@ static struct v4l2_queryctrl tvp5150_qctrl[] = { .minimum = 0, .maximum = 255, .step = 0x1, - .default_value = 0x10, + .default_value = 128, .flags = 0, }, { .id = V4L2_CID_SATURATION, @@ -71,7 +71,7 @@ static struct v4l2_queryctrl tvp5150_qctrl[] = { .minimum = 0, .maximum = 255, .step = 0x1, - .default_value = 0x10, + .default_value = 128, .flags = 0, }, { .id = V4L2_CID_HUE, @@ -80,7 +80,7 @@ static struct v4l2_queryctrl tvp5150_qctrl[] = { .minimum = -128, .maximum = 127, .step = 0x1, - .default_value = 0x10, + .default_value = 0, .flags = 0, } }; @@ -500,16 +500,21 @@ struct i2c_vbi_ram_value { static struct i2c_vbi_ram_value vbi_ram_default[] = { + /* FIXME: Current api doesn't handle all VBI types, those not + yet supported are placed under #if 0 */ +#if 0 {0x010, /* Teletext, SECAM, WST System A */ {V4L2_SLICED_TELETEXT_SECAM,6,23,1}, { 0xaa, 0xaa, 0xff, 0xff, 0xe7, 0x2e, 0x20, 0x26, 0xe6, 0xb4, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00 } }, +#endif {0x030, /* Teletext, PAL, WST System B */ - {V4L2_SLICED_TELETEXT_PAL_B,6,22,1}, + {V4L2_SLICED_TELETEXT_B,6,22,1}, { 0xaa, 0xaa, 0xff, 0xff, 0x27, 0x2e, 0x20, 0x2b, 0xa6, 0x72, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00 } }, +#if 0 {0x050, /* Teletext, PAL, WST System C */ {V4L2_SLICED_TELETEXT_PAL_C,6,22,1}, { 0xaa, 0xaa, 0xff, 0xff, 0xe7, 0x2e, 0x20, 0x22, @@ -535,6 +540,7 @@ static struct i2c_vbi_ram_value vbi_ram_default[] = { 0xaa, 0x2a, 0xff, 0x3f, 0x04, 0x51, 0x6e, 0x02, 0xa6, 0x7b, 0x09, 0x00, 0x00, 0x00, 0x27, 0x00 } }, +#endif {0x0f0, /* Closed Caption, NTSC */ {V4L2_SLICED_CAPTION_525,21,21,1}, { 0xaa, 0x2a, 0xff, 0x3f, 0x04, 0x51, 0x6e, 0x02, @@ -545,6 +551,7 @@ static struct i2c_vbi_ram_value vbi_ram_default[] = { 0x5b, 0x55, 0xc5, 0xff, 0x00, 0x71, 0x6e, 0x42, 0xa6, 0xcd, 0x0f, 0x00, 0x00, 0x00, 0x3a, 0x00 } }, +#if 0 {0x130, /* Wide Screen Signal, NTSC C */ {V4L2_SLICED_WSS_525,20,20,1}, { 0x38, 0x00, 0x3f, 0x00, 0x00, 0x71, 0x6e, 0x43, @@ -560,6 +567,7 @@ static struct i2c_vbi_ram_value vbi_ram_default[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x6d, 0x49, 0x69, 0x94, 0x08, 0x00, 0x00, 0x00, 0x4c, 0x00 } }, +#endif {0x190, /* Video Program System (VPS), PAL */ {V4L2_SLICED_VPS,16,16,0}, { 0xaa, 0xaa, 0xff, 0xff, 0xba, 0xce, 0x2b, 0x0d, @@ -850,7 +858,6 @@ static int tvp5150_command(struct i2c_client *c, case 0: case VIDIOC_INT_RESET: - case DECODER_INIT: tvp5150_reset(c); break; case VIDIOC_S_STD: @@ -949,99 +956,15 @@ static int tvp5150_command(struct i2c_client *c, #endif case VIDIOC_LOG_STATUS: - case DECODER_DUMP: dump_reg(c); break; - case DECODER_GET_CAPABILITIES: + case VIDIOC_G_TUNER: { - struct video_decoder_capability *cap = arg; - - cap->flags = VIDEO_DECODER_PAL | - VIDEO_DECODER_NTSC | - VIDEO_DECODER_SECAM | - VIDEO_DECODER_AUTO | VIDEO_DECODER_CCIR; - cap->inputs = 3; - cap->outputs = 1; - break; - } - case DECODER_GET_STATUS: - { - int *iarg = arg; - int status; - int res=0; - status = tvp5150_read(c, 0x88); - if(status&0x08){ - res |= DECODER_STATUS_COLOR; - } - if(status&0x04 && status&0x02){ - res |= DECODER_STATUS_GOOD; - } - *iarg=res; - break; - } - - case DECODER_SET_GPIO: - break; - - case DECODER_SET_VBI_BYPASS: - break; - - case DECODER_SET_NORM: - { - int *iarg = arg; - - switch (*iarg) { - - case VIDEO_MODE_NTSC: - break; - - case VIDEO_MODE_PAL: - break; - - case VIDEO_MODE_SECAM: - break; - - case VIDEO_MODE_AUTO: - break; - - default: - return -EINVAL; - - } - decoder->norm = *iarg; - break; - } - case DECODER_SET_INPUT: - { - int *iarg = arg; - if (*iarg < 0 || *iarg > 3) { - return -EINVAL; - } - - decoder->input = *iarg; - tvp5150_selmux(c, decoder->input); - - break; - } - case DECODER_SET_OUTPUT: - { - int *iarg = arg; - - /* not much choice of outputs */ - if (*iarg != 0) { - return -EINVAL; - } - break; - } - case DECODER_ENABLE_OUTPUT: - { - int *iarg = arg; - - decoder->enable = (*iarg != 0); - - tvp5150_selmux(c, decoder->input); + struct v4l2_tuner *vt = arg; + int status = tvp5150_read(c, 0x88); + vt->signal = ((status & 0x04) && (status & 0x02)) ? 0xffff : 0x0; break; } case VIDIOC_QUERYCTRL: @@ -1087,35 +1010,6 @@ static int tvp5150_command(struct i2c_client *c, return -EINVAL; } - case DECODER_SET_PICTURE: - { - struct video_picture *pic = arg; - if (decoder->bright != pic->brightness) { - /* We want 0 to 255 we get 0-65535 */ - decoder->bright = pic->brightness; - tvp5150_write(c, TVP5150_BRIGHT_CTL, - decoder->bright >> 8); - } - if (decoder->contrast != pic->contrast) { - /* We want 0 to 255 we get 0-65535 */ - decoder->contrast = pic->contrast; - tvp5150_write(c, TVP5150_CONTRAST_CTL, - decoder->contrast >> 8); - } - if (decoder->sat != pic->colour) { - /* We want 0 to 255 we get 0-65535 */ - decoder->sat = pic->colour; - tvp5150_write(c, TVP5150_SATURATION_CTL, - decoder->contrast >> 8); - } - if (decoder->hue != pic->hue) { - /* We want -128 to 127 we get 0-65535 */ - decoder->hue = pic->hue; - tvp5150_write(c, TVP5150_HUE_CTL, - (decoder->hue - 32768) >> 8); - } - break; - } default: return -EINVAL; } diff --git a/drivers/media/video/upd64031a.c b/drivers/media/video/upd64031a.c new file mode 100644 index 00000000000..fc52201d607 --- /dev/null +++ b/drivers/media/video/upd64031a.c @@ -0,0 +1,286 @@ +/* + * upd64031A - NEC Electronics Ghost Reduction for NTSC in Japan + * + * 2003 by T.Adachi <tadachi@tadachi-net.com> + * 2003 by Takeru KOMORIYA <komoriya@paken.org> + * 2006 by Hans Verkuil <hverkuil@xs4all.nl> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include <linux/version.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/i2c.h> +#include <linux/videodev2.h> +#include <media/v4l2-common.h> +#include <media/upd64031a.h> + +// --------------------- read registers functions define ----------------------- + +/* bit masks */ +#define GR_MODE_MASK 0xc0 +#define DIRECT_3DYCS_CONNECT_MASK 0xc0 +#define SYNC_CIRCUIT_MASK 0xa0 + +// ----------------------------------------------------------------------------- + +MODULE_DESCRIPTION("uPD64031A driver"); +MODULE_AUTHOR("T. Adachi, Takeru KOMORIYA, Hans Verkuil"); +MODULE_LICENSE("GPL"); + +static int debug = 0; +module_param(debug, int, 0644); + +MODULE_PARM_DESC(debug, "Debug level (0-1)"); + +static unsigned short normal_i2c[] = { 0x24 >> 1, 0x26 >> 1, I2C_CLIENT_END }; + + +I2C_CLIENT_INSMOD; + +enum { + R00 = 0, R01, R02, R03, R04, + R05, R06, R07, R08, R09, + R0A, R0B, R0C, R0D, R0E, R0F, + /* unused registers + R10, R11, R12, R13, R14, + R15, R16, R17, + */ + TOT_REGS +}; + +struct upd64031a_state { + u8 regs[TOT_REGS]; + u8 gr_mode; + u8 direct_3dycs_connect; + u8 ext_comp_sync; + u8 ext_vert_sync; +}; + +static u8 upd64031a_init[] = { + 0x00, 0xb8, 0x48, 0xd2, 0xe6, + 0x03, 0x10, 0x0b, 0xaf, 0x7f, + 0x00, 0x00, 0x1d, 0x5e, 0x00, + 0xd0 +}; + +/* ------------------------------------------------------------------------ */ + +static u8 upd64031a_read(struct i2c_client *client, u8 reg) +{ + u8 buf[2]; + + if (reg >= sizeof(buf)) + return 0xff; + i2c_master_recv(client, buf, 2); + return buf[reg]; +} + +/* ------------------------------------------------------------------------ */ + +static void upd64031a_write(struct i2c_client *client, u8 reg, u8 val) +{ + u8 buf[2]; + + buf[0] = reg; + buf[1] = val; + v4l_dbg(1, debug, client, "writing reg addr: %02X val: %02X\n", reg, val); + if (i2c_master_send(client, buf, 2) != 2) + v4l_err(client, "I/O error write 0x%02x/0x%02x\n", reg, val); +} + +/* ------------------------------------------------------------------------ */ + +/* The input changed due to new input or channel changed */ +static void upd64031a_change(struct i2c_client *client) +{ + struct upd64031a_state *state = i2c_get_clientdata(client); + u8 reg = state->regs[R00]; + + v4l_dbg(1, debug, client, "changed input or channel\n"); + upd64031a_write(client, R00, reg | 0x10); + upd64031a_write(client, R00, reg & ~0x10); +} + +/* ------------------------------------------------------------------------ */ + +static int upd64031a_command(struct i2c_client *client, unsigned int cmd, void *arg) +{ + struct upd64031a_state *state = i2c_get_clientdata(client); + struct v4l2_routing *route = arg; + + switch (cmd) { + case VIDIOC_S_FREQUENCY: + upd64031a_change(client); + break; + + case VIDIOC_INT_G_VIDEO_ROUTING: + route->input = (state->gr_mode >> 6) | + (state->direct_3dycs_connect >> 4) | + (state->ext_comp_sync >> 1) | + (state->ext_vert_sync >> 2); + route->output = 0; + break; + + case VIDIOC_INT_S_VIDEO_ROUTING: + { + u8 r00, r05, r08; + + state->gr_mode = (route->input & 3) << 6; + state->direct_3dycs_connect = (route->input & 0xc) << 4; + state->ext_comp_sync = (route->input & UPD64031A_COMPOSITE_EXTERNAL) << 1; + state->ext_vert_sync = (route->input & UPD64031A_VERTICAL_EXTERNAL) << 2; + r00 = (state->regs[R00] & ~GR_MODE_MASK) | state->gr_mode; + r05 = (state->regs[R00] & ~SYNC_CIRCUIT_MASK) | + state->ext_comp_sync | state->ext_vert_sync; + r08 = (state->regs[R08] & ~DIRECT_3DYCS_CONNECT_MASK) | + state->direct_3dycs_connect; + upd64031a_write(client, R00, r00); + upd64031a_write(client, R05, r05); + upd64031a_write(client, R08, r08); + upd64031a_change(client); + break; + } + + case VIDIOC_LOG_STATUS: + v4l_info(client, "Status: SA00=0x%02x SA01=0x%02x\n", + upd64031a_read(client, 0), upd64031a_read(client, 1)); + break; + +#ifdef CONFIG_VIDEO_ADV_DEBUG + case VIDIOC_INT_G_REGISTER: + { + struct v4l2_register *reg = arg; + + if (reg->i2c_id != I2C_DRIVERID_UPD64031A) + return -EINVAL; + reg->val = upd64031a_read(client, reg->reg & 0xff); + break; + } + + case VIDIOC_INT_S_REGISTER: + { + struct v4l2_register *reg = arg; + u8 addr = reg->reg & 0xff; + u8 val = reg->val & 0xff; + + if (reg->i2c_id != I2C_DRIVERID_UPD64031A) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + upd64031a_write(client, addr, val); + break; + } +#endif + + default: + break; + } + return 0; +} + +/* ------------------------------------------------------------------------ */ + +/* i2c implementation */ + +static struct i2c_driver i2c_driver; + +static int upd64031a_attach(struct i2c_adapter *adapter, int address, int kind) +{ + struct i2c_client *client; + struct upd64031a_state *state; + int i; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return 0; + + client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); + if (client == NULL) { + return -ENOMEM; + } + + client->addr = address; + client->adapter = adapter; + client->driver = &i2c_driver; + snprintf(client->name, sizeof(client->name) - 1, "uPD64031A"); + + v4l_info(client, "chip found @ 0x%x (%s)\n", address << 1, adapter->name); + + state = kmalloc(sizeof(struct upd64031a_state), GFP_KERNEL); + if (state == NULL) { + kfree(client); + return -ENOMEM; + } + i2c_set_clientdata(client, state); + memcpy(state->regs, upd64031a_init, sizeof(state->regs)); + state->gr_mode = UPD64031A_GR_ON << 6; + state->direct_3dycs_connect = UPD64031A_3DYCS_COMPOSITE << 4; + state->ext_comp_sync = state->ext_vert_sync = 0; + for (i = 0; i < TOT_REGS; i++) { + upd64031a_write(client, i, state->regs[i]); + } + + i2c_attach_client(client); + + return 0; +} + +static int upd64031a_probe(struct i2c_adapter *adapter) +{ + if (adapter->class & I2C_CLASS_TV_ANALOG) + return i2c_probe(adapter, &addr_data, upd64031a_attach); + return 0; +} + +static int upd64031a_detach(struct i2c_client *client) +{ + int err; + + err = i2c_detach_client(client); + if (err) + return err; + + kfree(client); + return 0; +} + +/* ----------------------------------------------------------------------- */ + +/* i2c implementation */ +static struct i2c_driver i2c_driver = { + .driver = { + .name = "upd64031a", + }, + .id = I2C_DRIVERID_UPD64031A, + .attach_adapter = upd64031a_probe, + .detach_client = upd64031a_detach, + .command = upd64031a_command, +}; + + +static int __init upd64031a_init_module(void) +{ + return i2c_add_driver(&i2c_driver); +} + +static void __exit upd64031a_exit_module(void) +{ + i2c_del_driver(&i2c_driver); +} + +module_init(upd64031a_init_module); +module_exit(upd64031a_exit_module); diff --git a/drivers/media/video/upd64083.c b/drivers/media/video/upd64083.c new file mode 100644 index 00000000000..c3a7ffe5c26 --- /dev/null +++ b/drivers/media/video/upd64083.c @@ -0,0 +1,262 @@ +/* + * upd6408x - NEC Electronics 3-Dimensional Y/C separation driver + * + * 2003 by T.Adachi (tadachi@tadachi-net.com) + * 2003 by Takeru KOMORIYA <komoriya@paken.org> + * 2006 by Hans Verkuil <hverkuil@xs4all.nl> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include <linux/version.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/i2c.h> +#include <linux/videodev2.h> +#include <media/v4l2-common.h> +#include <media/upd64083.h> + +MODULE_DESCRIPTION("uPD64083 driver"); +MODULE_AUTHOR("T. Adachi, Takeru KOMORIYA, Hans Verkuil"); +MODULE_LICENSE("GPL"); + +static int debug = 0; +module_param(debug, bool, 0644); + +MODULE_PARM_DESC(debug, "Debug level (0-1)"); + +static unsigned short normal_i2c[] = { 0xb8 >> 1, 0xba >> 1, I2C_CLIENT_END }; + + +I2C_CLIENT_INSMOD; + +enum { + R00 = 0, R01, R02, R03, R04, + R05, R06, R07, R08, R09, + R0A, R0B, R0C, R0D, R0E, R0F, + R10, R11, R12, R13, R14, + R15, R16, + TOT_REGS +}; + +struct upd64083_state { + u8 mode; + u8 ext_y_adc; + u8 regs[TOT_REGS]; +}; + +/* Initial values when used in combination with the + NEC upd64031a ghost reduction chip. */ +static u8 upd64083_init[] = { + 0x1f, 0x01, 0xa0, 0x2d, 0x29, /* we use EXCSS=0 */ + 0x36, 0xdd, 0x05, 0x56, 0x48, + 0x00, 0x3a, 0xa0, 0x05, 0x08, + 0x44, 0x60, 0x08, 0x52, 0xf8, + 0x53, 0x60, 0x10 +}; + +/* ------------------------------------------------------------------------ */ + +static void upd64083_log_status(struct i2c_client *client) +{ + u8 buf[7]; + + i2c_master_recv(client, buf, 7); + v4l_info(client, "Status: SA00=%02x SA01=%02x SA02=%02x SA03=%02x " + "SA04=%02x SA05=%02x SA06=%02x\n", + buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); +} + +/* ------------------------------------------------------------------------ */ + +static void upd64083_write(struct i2c_client *client, u8 reg, u8 val) +{ + u8 buf[2]; + + buf[0] = reg; + buf[1] = val; + v4l_dbg(1, debug, client, "writing reg addr: %02x val: %02x\n", reg, val); + if (i2c_master_send(client, buf, 2) != 2) + v4l_err(client, "I/O error write 0x%02x/0x%02x\n", reg, val); +} + +/* ------------------------------------------------------------------------ */ + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static u8 upd64083_read(struct i2c_client *client, u8 reg) +{ + u8 buf[7]; + + if (reg >= sizeof(buf)) + return 0xff; + i2c_master_recv(client, buf, sizeof(buf)); + return buf[reg]; +} +#endif + +/* ------------------------------------------------------------------------ */ + +static int upd64083_command(struct i2c_client *client, unsigned int cmd, void *arg) +{ + struct upd64083_state *state = i2c_get_clientdata(client); + struct v4l2_routing *route = arg; + + switch (cmd) { + case VIDIOC_INT_G_VIDEO_ROUTING: + route->input = (state->mode >> 6) | (state->ext_y_adc >> 3); + route->output = 0; + break; + + case VIDIOC_INT_S_VIDEO_ROUTING: + { + u8 r00, r02; + + if (route->input > 7 || (route->input & 6) == 6) + return -EINVAL; + state->mode = (route->input & 3) << 6; + state->ext_y_adc = (route->input & UPD64083_EXT_Y_ADC) << 3; + r00 = (state->regs[R00] & ~(3 << 6)) | state->mode; + r02 = (state->regs[R02] & ~(1 << 5)) | state->ext_y_adc; + upd64083_write(client, R00, r00); + upd64083_write(client, R02, r02); + break; + } + + case VIDIOC_LOG_STATUS: + upd64083_log_status(client); + break; + +#ifdef CONFIG_VIDEO_ADV_DEBUG + case VIDIOC_INT_G_REGISTER: + { + struct v4l2_register *reg = arg; + + if (reg->i2c_id != I2C_DRIVERID_UPD64083) + return -EINVAL; + reg->val = upd64083_read(client, reg->reg & 0xff); + break; + } + + case VIDIOC_INT_S_REGISTER: + { + struct v4l2_register *reg = arg; + u8 addr = reg->reg & 0xff; + u8 val = reg->val & 0xff; + + if (reg->i2c_id != I2C_DRIVERID_UPD64083) + return -EINVAL; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + upd64083_write(client, addr, val); + break; + } +#endif + default: + break; + } + + return 0; +} + +/* ------------------------------------------------------------------------ */ + +/* i2c implementation */ + +static struct i2c_driver i2c_driver; + +static int upd64083_attach(struct i2c_adapter *adapter, int address, int kind) +{ + struct i2c_client *client; + struct upd64083_state *state; + int i; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return 0; + + client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); + if (client == NULL) { + return -ENOMEM; + } + + client->addr = address; + client->adapter = adapter; + client->driver = &i2c_driver; + snprintf(client->name, sizeof(client->name) - 1, "uPD64083"); + + v4l_info(client, "chip found @ 0x%x (%s)\n", address << 1, adapter->name); + + state = kmalloc(sizeof(struct upd64083_state), GFP_KERNEL); + if (state == NULL) { + kfree(client); + return -ENOMEM; + } + i2c_set_clientdata(client, state); + /* Initially assume that a ghost reduction chip is present */ + state->mode = 0; /* YCS mode */ + state->ext_y_adc = (1 << 5); + memcpy(state->regs, upd64083_init, TOT_REGS); + for (i = 0; i < TOT_REGS; i++) { + upd64083_write(client, i, state->regs[i]); + } + i2c_attach_client(client); + + return 0; +} + +static int upd64083_probe(struct i2c_adapter *adapter) +{ + if (adapter->class & I2C_CLASS_TV_ANALOG) + return i2c_probe(adapter, &addr_data, upd64083_attach); + return 0; +} + +static int upd64083_detach(struct i2c_client *client) +{ + int err; + + err = i2c_detach_client(client); + if (err) + return err; + + kfree(client); + return 0; +} + +/* ----------------------------------------------------------------------- */ + +/* i2c implementation */ +static struct i2c_driver i2c_driver = { + .driver = { + .name = "upd64083", + }, + .id = I2C_DRIVERID_UPD64083, + .attach_adapter = upd64083_probe, + .detach_client = upd64083_detach, + .command = upd64083_command, +}; + + +static int __init upd64083_init_module(void) +{ + return i2c_add_driver(&i2c_driver); +} + +static void __exit upd64083_exit_module(void) +{ + i2c_del_driver(&i2c_driver); +} + +module_init(upd64083_init_module); +module_exit(upd64083_exit_module); diff --git a/drivers/media/video/usbvideo/Kconfig b/drivers/media/video/usbvideo/Kconfig new file mode 100644 index 00000000000..08a5d20bb2c --- /dev/null +++ b/drivers/media/video/usbvideo/Kconfig @@ -0,0 +1,38 @@ +config VIDEO_USBVIDEO + tristate + +config USB_VICAM + tristate "USB 3com HomeConnect (aka vicam) support (EXPERIMENTAL)" + depends on USB && VIDEO_DEV && EXPERIMENTAL + select VIDEO_USBVIDEO + ---help--- + Say Y here if you have 3com homeconnect camera (vicam). + + To compile this driver as a module, choose M here: the + module will be called vicam. + +config USB_IBMCAM + tristate "USB IBM (Xirlink) C-it Camera support" + depends on USB && VIDEO_DEV + select VIDEO_USBVIDEO + ---help--- + Say Y here if you want to connect a IBM "C-It" camera, also known as + "Xirlink PC Camera" to your computer's USB port. + + To compile this driver as a module, choose M here: the + module will be called ibmcam. + + This camera has several configuration options which + can be specified when you load the module. Read + <file:Documentation/video4linux/ibmcam.txt> to learn more. + +config USB_KONICAWC + tristate "USB Konica Webcam support" + depends on USB && VIDEO_DEV + select VIDEO_USBVIDEO + ---help--- + Say Y here if you want support for webcams based on a Konica + chipset. This is known to work with the Intel YC76 webcam. + + To compile this driver as a module, choose M here: the + module will be called konicawc. diff --git a/drivers/media/video/usbvideo/Makefile b/drivers/media/video/usbvideo/Makefile index ed410a5ee8c..bb52eb8dc2f 100644 --- a/drivers/media/video/usbvideo/Makefile +++ b/drivers/media/video/usbvideo/Makefile @@ -1,4 +1,4 @@ -obj-$(CONFIG_USB_IBMCAM) += ibmcam.o usbvideo.o ultracam.o -obj-$(CONFIG_USB_KONICAWC) += konicawc.o usbvideo.o -obj-$(CONFIG_USB_VICAM) += vicam.o usbvideo.o - +obj-$(CONFIG_VIDEO_USBVIDEO) += usbvideo.o +obj-$(CONFIG_USB_IBMCAM) += ibmcam.o ultracam.o +obj-$(CONFIG_USB_KONICAWC) += konicawc.o +obj-$(CONFIG_USB_VICAM) += vicam.o diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index 11a97f30b87..d330fa985bc 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -317,6 +317,7 @@ static const char *v4l2_int_ioctls[] = { [_IOC_NR(TUNER_SET_STANDBY)] = "TUNER_SET_STANDBY", [_IOC_NR(TDA9887_SET_CONFIG)] = "TDA9887_SET_CONFIG", + [_IOC_NR(VIDIOC_INT_S_TUNER_MODE)] = "VIDIOC_INT_S_TUNER_MODE", [_IOC_NR(VIDIOC_INT_S_REGISTER)] = "VIDIOC_INT_S_REGISTER", [_IOC_NR(VIDIOC_INT_G_REGISTER)] = "VIDIOC_INT_G_REGISTER", [_IOC_NR(VIDIOC_INT_RESET)] = "VIDIOC_INT_RESET", @@ -325,7 +326,12 @@ static const char *v4l2_int_ioctls[] = { [_IOC_NR(VIDIOC_INT_S_VBI_DATA)] = "VIDIOC_INT_S_VBI_DATA", [_IOC_NR(VIDIOC_INT_G_VBI_DATA)] = "VIDIOC_INT_G_VBI_DATA", [_IOC_NR(VIDIOC_INT_G_CHIP_IDENT)] = "VIDIOC_INT_G_CHIP_IDENT", - [_IOC_NR(VIDIOC_INT_I2S_CLOCK_FREQ)] = "VIDIOC_INT_I2S_CLOCK_FREQ" + [_IOC_NR(VIDIOC_INT_I2S_CLOCK_FREQ)] = "VIDIOC_INT_I2S_CLOCK_FREQ", + [_IOC_NR(VIDIOC_INT_S_STANDBY)] = "VIDIOC_INT_S_STANDBY", + [_IOC_NR(VIDIOC_INT_S_AUDIO_ROUTING)] = "VIDIOC_INT_S_AUDIO_ROUTING", + [_IOC_NR(VIDIOC_INT_G_AUDIO_ROUTING)] = "VIDIOC_INT_G_AUDIO_ROUTING", + [_IOC_NR(VIDIOC_INT_S_VIDEO_ROUTING)] = "VIDIOC_INT_S_VIDEO_ROUTING", + [_IOC_NR(VIDIOC_INT_G_VIDEO_ROUTING)] = "VIDIOC_INT_G_VIDEO_ROUTING" }; #define V4L2_INT_IOCTLS ARRAY_SIZE(v4l2_int_ioctls) diff --git a/drivers/media/video/video-buf.c b/drivers/media/video/video-buf.c index d2ca0f08d0d..acc5ea93668 100644 --- a/drivers/media/video/video-buf.c +++ b/drivers/media/video/video-buf.c @@ -399,19 +399,25 @@ void videobuf_queue_pci(struct videobuf_queue* q) int videobuf_pci_dma_map(struct pci_dev *pci,struct videobuf_dmabuf *dma) { struct videobuf_queue q; + struct videobuf_queue_ops qops; q.dev=pci; - q.ops->vb_map_sg=(vb_map_sg_t *)pci_unmap_sg; + qops.vb_map_sg=(vb_map_sg_t *)pci_map_sg; + qops.vb_unmap_sg=(vb_map_sg_t *)pci_unmap_sg; + q.ops = &qops; - return (videobuf_dma_unmap(&q,dma)); + return (videobuf_dma_map(&q,dma)); } int videobuf_pci_dma_unmap(struct pci_dev *pci,struct videobuf_dmabuf *dma) { struct videobuf_queue q; + struct videobuf_queue_ops qops; q.dev=pci; - q.ops->vb_map_sg=(vb_map_sg_t *)pci_unmap_sg; + qops.vb_map_sg=(vb_map_sg_t *)pci_map_sg; + qops.vb_unmap_sg=(vb_map_sg_t *)pci_unmap_sg; + q.ops = &qops; return (videobuf_dma_unmap(&q,dma)); } @@ -923,7 +929,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, /* need to capture a new frame */ retval = -ENOMEM; q->read_buf = videobuf_alloc(q->msize); - dprintk(1,"video alloc=0x%08x\n",(unsigned int) q->read_buf); + dprintk(1,"video alloc=0x%p\n", q->read_buf); if (NULL == q->read_buf) goto done; q->read_buf->memory = V4L2_MEMORY_USERPTR; diff --git a/drivers/media/video/wm8739.c b/drivers/media/video/wm8739.c new file mode 100644 index 00000000000..a9b59c35cd6 --- /dev/null +++ b/drivers/media/video/wm8739.c @@ -0,0 +1,355 @@ +/* + * wm8739 + * + * Copyright (C) 2005 T. Adachi <tadachi@tadachi-net.com> + * + * Copyright (C) 2005 Hans Verkuil <hverkuil@xs4all.nl> + * - Cleanup + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/types.h> +#include <linux/ioctl.h> +#include <asm/uaccess.h> +#include <linux/i2c.h> +#include <linux/i2c-id.h> +#include <linux/videodev.h> +#include <media/v4l2-common.h> + +MODULE_DESCRIPTION("wm8739 driver"); +MODULE_AUTHOR("T. Adachi, Hans Verkuil"); +MODULE_LICENSE("GPL"); + +static int debug = 0; +static unsigned short normal_i2c[] = { 0x34 >> 1, 0x36 >> 1, I2C_CLIENT_END }; + +module_param(debug, int, 0644); + +MODULE_PARM_DESC(debug, "Debug level (0-1)"); + + +I2C_CLIENT_INSMOD; + +/* ------------------------------------------------------------------------ */ + +enum { + R0 = 0, R1, + R5 = 5, R6, R7, R8, R9, R15 = 15, + TOT_REGS +}; + +struct wm8739_state { + u32 clock_freq; + u8 muted; + u16 volume; + u16 balance; + u8 vol_l; /* +12dB to -34.5dB 1.5dB step (5bit) def:0dB */ + u8 vol_r; /* +12dB to -34.5dB 1.5dB step (5bit) def:0dB */ +}; + +/* ------------------------------------------------------------------------ */ + +static int wm8739_write(struct i2c_client *client, int reg, u16 val) +{ + int i; + + if (reg < 0 || reg >= TOT_REGS) { + v4l_err(client, "Invalid register R%d\n", reg); + return -1; + } + + v4l_dbg(1, debug, client, "write: %02x %02x\n", reg, val); + + for (i = 0; i < 3; i++) { + if (i2c_smbus_write_byte_data(client, (reg << 1) | + (val >> 8), val & 0xff) == 0) { + return 0; + } + } + v4l_err(client, "I2C: cannot write %03x to register R%d\n", val, reg); + return -1; +} + +/* write regs to set audio volume etc */ +static void wm8739_set_audio(struct i2c_client *client) +{ + struct wm8739_state *state = i2c_get_clientdata(client); + u16 mute = state->muted ? 0x80 : 0; + + /* Volume setting: bits 0-4, 0x1f = 12 dB, 0x00 = -34.5 dB + * Default setting: 0x17 = 0 dB + */ + wm8739_write(client, R0, (state->vol_l & 0x1f) | mute); + wm8739_write(client, R1, (state->vol_r & 0x1f) | mute); +} + +static int wm8739_get_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) +{ + struct wm8739_state *state = i2c_get_clientdata(client); + + switch (ctrl->id) { + case V4L2_CID_AUDIO_MUTE: + ctrl->value = state->muted; + break; + + case V4L2_CID_AUDIO_VOLUME: + ctrl->value = state->volume; + break; + + case V4L2_CID_AUDIO_BALANCE: + ctrl->value = state->balance; + break; + + default: + return -EINVAL; + } + return 0; +} + +static int wm8739_set_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) +{ + struct wm8739_state *state = i2c_get_clientdata(client); + unsigned int work_l, work_r; + + switch (ctrl->id) { + case V4L2_CID_AUDIO_MUTE: + state->muted = ctrl->value; + break; + + case V4L2_CID_AUDIO_VOLUME: + state->volume = ctrl->value; + break; + + case V4L2_CID_AUDIO_BALANCE: + state->balance = ctrl->value; + break; + + default: + return -EINVAL; + } + + /* normalize ( 65535 to 0 -> 31 to 0 (12dB to -34.5dB) ) */ + work_l = (min(65536 - state->balance, 32768) * state->volume) / 32768; + work_r = (min(state->balance, (u16)32768) * state->volume) / 32768; + + state->vol_l = (long)work_l * 31 / 65535; + state->vol_r = (long)work_r * 31 / 65535; + + /* set audio volume etc. */ + wm8739_set_audio(client); + return 0; +} + +/* ------------------------------------------------------------------------ */ + +static struct v4l2_queryctrl wm8739_qctrl[] = { + { + .id = V4L2_CID_AUDIO_VOLUME, + .name = "Volume", + .minimum = 0, + .maximum = 65535, + .step = 65535/100, + .default_value = 58880, + .flags = 0, + .type = V4L2_CTRL_TYPE_INTEGER, + },{ + .id = V4L2_CID_AUDIO_MUTE, + .name = "Mute", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 1, + .flags = 0, + .type = V4L2_CTRL_TYPE_BOOLEAN, + },{ + .id = V4L2_CID_AUDIO_BALANCE, + .name = "Balance", + .minimum = 0, + .maximum = 65535, + .step = 65535/100, + .default_value = 32768, + .flags = 0, + .type = V4L2_CTRL_TYPE_INTEGER, + } +}; + +/* ------------------------------------------------------------------------ */ + +static int wm8739_command(struct i2c_client *client, unsigned int cmd, void *arg) +{ + struct wm8739_state *state = i2c_get_clientdata(client); + + switch (cmd) { + case VIDIOC_INT_AUDIO_CLOCK_FREQ: + { + u32 audiofreq = *(u32 *)arg; + + state->clock_freq = audiofreq; + wm8739_write(client, R9, 0x000); /* de-activate */ + switch (audiofreq) { + case 44100: + wm8739_write(client, R8, 0x020); /* 256fps, fs=44.1k */ + break; + case 48000: + wm8739_write(client, R8, 0x000); /* 256fps, fs=48k */ + break; + case 32000: + wm8739_write(client, R8, 0x018); /* 256fps, fs=32k */ + break; + default: + break; + } + wm8739_write(client, R9, 0x001); /* activate */ + break; + } + + case VIDIOC_G_CTRL: + return wm8739_get_ctrl(client, arg); + + case VIDIOC_S_CTRL: + return wm8739_set_ctrl(client, arg); + + case VIDIOC_QUERYCTRL: + { + struct v4l2_queryctrl *qc = arg; + int i; + + for (i = 0; i < ARRAY_SIZE(wm8739_qctrl); i++) + if (qc->id && qc->id == wm8739_qctrl[i].id) { + memcpy(qc, &wm8739_qctrl[i], sizeof(*qc)); + return 0; + } + return -EINVAL; + } + + case VIDIOC_LOG_STATUS: + v4l_info(client, "Frequency: %u Hz\n", state->clock_freq); + v4l_info(client, "Volume L: %02x%s\n", state->vol_l & 0x1f, + state->muted ? " (muted)" : ""); + v4l_info(client, "Volume R: %02x%s\n", state->vol_r & 0x1f, + state->muted ? " (muted)" : ""); + break; + + default: + return -EINVAL; + } + + return 0; +} + +/* ------------------------------------------------------------------------ */ + +/* i2c implementation */ + +static struct i2c_driver i2c_driver; + +static int wm8739_attach(struct i2c_adapter *adapter, int address, int kind) +{ + struct i2c_client *client; + struct wm8739_state *state; + + /* Check if the adapter supports the needed features */ + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return 0; + + client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); + if (client == NULL) + return -ENOMEM; + + client->addr = address; + client->adapter = adapter; + client->driver = &i2c_driver; + snprintf(client->name, sizeof(client->name) - 1, "wm8739"); + + v4l_info(client, "chip found @ 0x%x (%s)\n", address << 1, adapter->name); + + state = kmalloc(sizeof(struct wm8739_state), GFP_KERNEL); + if (state == NULL) { + kfree(client); + return -ENOMEM; + } + state->vol_l = 0x17; /* 0dB */ + state->vol_r = 0x17; /* 0dB */ + state->muted = 0; + state->balance = 32768; + /* normalize (12dB(31) to -34.5dB(0) [0dB(23)] -> 65535 to 0) */ + state->volume = ((long)state->vol_l + 1) * 65535 / 31; + state->clock_freq = 48000; + i2c_set_clientdata(client, state); + + /* initialize wm8739 */ + wm8739_write(client, R15, 0x00); /* reset */ + wm8739_write(client, R5, 0x000); /* filter setting, high path, offet clear */ + wm8739_write(client, R6, 0x000); /* ADC, OSC, Power Off mode Disable */ + wm8739_write(client, R7, 0x049); /* Digital Audio interface format */ + /* Enable Master mode */ + /* 24 bit, MSB first/left justified */ + wm8739_write(client, R8, 0x000); /* sampling control */ + /* normal, 256fs, 48KHz sampling rate */ + wm8739_write(client, R9, 0x001); /* activate */ + wm8739_set_audio(client); /* set volume/mute */ + + i2c_attach_client(client); + + return 0; +} + +static int wm8739_probe(struct i2c_adapter *adapter) +{ + if (adapter->class & I2C_CLASS_TV_ANALOG) + return i2c_probe(adapter, &addr_data, wm8739_attach); + return 0; +} + +static int wm8739_detach(struct i2c_client *client) +{ + int err; + + err = i2c_detach_client(client); + if (err) + return err; + + kfree(client); + return 0; +} + +/* ----------------------------------------------------------------------- */ + +/* i2c implementation */ +static struct i2c_driver i2c_driver = { + .driver = { + .name = "wm8739", + }, + .id = I2C_DRIVERID_WM8739, + .attach_adapter = wm8739_probe, + .detach_client = wm8739_detach, + .command = wm8739_command, +}; + + +static int __init wm8739_init_module(void) +{ + return i2c_add_driver(&i2c_driver); +} + +static void __exit wm8739_cleanup_module(void) +{ + i2c_del_driver(&i2c_driver); +} + +module_init(wm8739_init_module); +module_exit(wm8739_cleanup_module); diff --git a/drivers/media/video/zc0301/Kconfig b/drivers/media/video/zc0301/Kconfig new file mode 100644 index 00000000000..c3bf886b80c --- /dev/null +++ b/drivers/media/video/zc0301/Kconfig @@ -0,0 +1,11 @@ +config USB_ZC0301 + tristate "USB ZC0301 Image Processor and Control Chip support" + depends on USB && VIDEO_DEV + ---help--- + Say Y here if you want support for cameras based on the ZC0301 + Image Processor and Control Chip. + + See <file:Documentation/video4linux/zc0301.txt> for more info. + + To compile this driver as a module, choose M here: the + module will be called zc0301. |