diff options
author | Ondrej Zary <linux@rainbow-software.org> | 2011-04-27 17:36:05 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-05-20 09:29:29 -0300 |
commit | 240d57bb8238d6998644c7f696c27076956ff653 (patch) | |
tree | eada3a282c50d4209ee76d7ef92f4748a1d11174 /drivers/media/video/usbvision/usbvision-core.c | |
parent | 449a0bada34e5e554ef52aca86aeaa81ed35533e (diff) |
[media] usbvision: add Nogatech USB MicroCam
Add Nogatech USB MicroCam PAL (NV3001P) and NTSC (NV3000N) support to
usbvision driver.
PAL version is tested, NTSC untested.
Data captured using usbsnoop, init_values are listed in the INF file along
with image dimensions, offsets and frame rates.
Signed-off-by: Ondrej Zary <linux@rainbow-software.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/usbvision/usbvision-core.c')
-rw-r--r-- | drivers/media/video/usbvision/usbvision-core.c | 73 |
1 files changed, 72 insertions, 1 deletions
diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c index c8feb0d6fccf..89ac46277031 100644 --- a/drivers/media/video/usbvision/usbvision-core.c +++ b/drivers/media/video/usbvision/usbvision-core.c @@ -1679,6 +1679,55 @@ int usbvision_power_off(struct usb_usbvision *usbvision) return err_code; } +/* configure webcam image sensor using the serial port */ +static int usbvision_init_webcam(struct usb_usbvision *usbvision) +{ + int rc; + int i; + static char init_values[38][3] = { + { 0x04, 0x12, 0x08 }, { 0x05, 0xff, 0xc8 }, { 0x06, 0x18, 0x07 }, { 0x07, 0x90, 0x00 }, + { 0x09, 0x00, 0x00 }, { 0x0a, 0x00, 0x00 }, { 0x0b, 0x08, 0x00 }, { 0x0d, 0xcc, 0xcc }, + { 0x0e, 0x13, 0x14 }, { 0x10, 0x9b, 0x83 }, { 0x11, 0x5a, 0x3f }, { 0x12, 0xe4, 0x73 }, + { 0x13, 0x88, 0x84 }, { 0x14, 0x89, 0x80 }, { 0x15, 0x00, 0x20 }, { 0x16, 0x00, 0x00 }, + { 0x17, 0xff, 0xa0 }, { 0x18, 0x6b, 0x20 }, { 0x19, 0x22, 0x40 }, { 0x1a, 0x10, 0x07 }, + { 0x1b, 0x00, 0x47 }, { 0x1c, 0x03, 0xe0 }, { 0x1d, 0x00, 0x00 }, { 0x1e, 0x00, 0x00 }, + { 0x1f, 0x00, 0x00 }, { 0x20, 0x00, 0x00 }, { 0x21, 0x00, 0x00 }, { 0x22, 0x00, 0x00 }, + { 0x23, 0x00, 0x00 }, { 0x24, 0x00, 0x00 }, { 0x25, 0x00, 0x00 }, { 0x26, 0x00, 0x00 }, + { 0x27, 0x00, 0x00 }, { 0x28, 0x00, 0x00 }, { 0x29, 0x00, 0x00 }, { 0x08, 0x80, 0x60 }, + { 0x0f, 0x2d, 0x24 }, { 0x0c, 0x80, 0x80 } + }; + char value[3]; + + /* the only difference between PAL and NTSC init_values */ + if (usbvision_device_data[usbvision->dev_model].video_norm == V4L2_STD_NTSC) + init_values[4][1] = 0x34; + + for (i = 0; i < sizeof(init_values) / 3; i++) { + usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_SER_MODE_SOFT); + memcpy(value, init_values[i], 3); + rc = usb_control_msg(usbvision->dev, + usb_sndctrlpipe(usbvision->dev, 1), + USBVISION_OP_CODE, + USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_ENDPOINT, 0, + (__u16) USBVISION_SER_DAT1, value, + 3, HZ); + if (rc < 0) + return rc; + usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_SER_MODE_SIO); + /* write 3 bytes to the serial port using SIO mode */ + usbvision_write_reg(usbvision, USBVISION_SER_CONT, 3 | 0x10); + usbvision_write_reg(usbvision, USBVISION_IOPIN_REG, 0); + usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_SER_MODE_SOFT); + usbvision_write_reg(usbvision, USBVISION_IOPIN_REG, USBVISION_IO_2); + usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_SER_MODE_SOFT | USBVISION_CLK_OUT); + usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_SER_MODE_SOFT | USBVISION_DAT_IO); + usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_SER_MODE_SOFT | USBVISION_CLK_OUT | USBVISION_DAT_IO); + } + + return 0; +} + /* * usbvision_set_video_format() * @@ -1797,6 +1846,13 @@ int usbvision_set_output(struct usb_usbvision *usbvision, int width, frame_drop = FRAMERATE_MAX; /* We can allow the maximum here, because dropping is controlled */ + if (usbvision_device_data[usbvision->dev_model].codec == CODEC_WEBCAM) { + if (usbvision_device_data[usbvision->dev_model].video_norm == V4L2_STD_PAL) + frame_drop = 25; + else + frame_drop = 30; + } + /* frame_drop = 7; => frame_phase = 1, 5, 9, 13, 17, 21, 25, 0, 4, 8, ... => frame_skip = 4; => frame_rate = (7 + 1) * 25 / 32 = 200 / 32 = 6.25; @@ -2046,6 +2102,12 @@ int usbvision_set_input(struct usb_usbvision *usbvision) value[7] = 0x00; /* 0x0010 -> 16 Input video v offset */ } + /* webcam is only 480 pixels wide, both PAL and NTSC version */ + if (usbvision_device_data[usbvision->dev_model].codec == CODEC_WEBCAM) { + value[0] = 0xe0; + value[1] = 0x01; /* 0x01E0 -> 480 Input video line length */ + } + if (usbvision_device_data[usbvision->dev_model].x_offset >= 0) { value[4] = usbvision_device_data[usbvision->dev_model].x_offset & 0xff; value[5] = (usbvision_device_data[usbvision->dev_model].x_offset & 0x0300) >> 8; @@ -2148,7 +2210,7 @@ static int usbvision_set_dram_settings(struct usb_usbvision *usbvision) (__u16) USBVISION_DRM_PRM1, value, 8, HZ); if (rc < 0) { - dev_err(&usbvision->dev->dev, "%sERROR=%d\n", __func__, rc); + dev_err(&usbvision->dev->dev, "%s: ERROR=%d\n", __func__, rc); return rc; } @@ -2180,8 +2242,15 @@ int usbvision_power_on(struct usb_usbvision *usbvision) usbvision_write_reg(usbvision, USBVISION_PWR_REG, USBVISION_SSPND_EN | USBVISION_RES2); + if (usbvision_device_data[usbvision->dev_model].codec == CODEC_WEBCAM) { + usbvision_write_reg(usbvision, USBVISION_VIN_REG1, + USBVISION_16_422_SYNC | USBVISION_HVALID_PO); + usbvision_write_reg(usbvision, USBVISION_VIN_REG2, + USBVISION_NOHVALID | USBVISION_KEEP_BLANK); + } usbvision_write_reg(usbvision, USBVISION_PWR_REG, USBVISION_SSPND_EN | USBVISION_PWR_VID); + mdelay(10); err_code = usbvision_write_reg(usbvision, USBVISION_PWR_REG, USBVISION_SSPND_EN | USBVISION_PWR_VID | USBVISION_RES2); if (err_code == 1) @@ -2310,6 +2379,8 @@ int usbvision_set_audio(struct usb_usbvision *usbvision, int audio_channel) int usbvision_setup(struct usb_usbvision *usbvision, int format) { + if (usbvision_device_data[usbvision->dev_model].codec == CODEC_WEBCAM) + usbvision_init_webcam(usbvision); usbvision_set_video_format(usbvision, format); usbvision_set_dram_settings(usbvision); usbvision_set_compress_params(usbvision); |