diff options
author | Ondrej Zary <linux@rainbow-software.org> | 2011-04-27 16:36:05 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-05-20 08:29:29 -0400 |
commit | 240d57bb8238d6998644c7f696c27076956ff653 (patch) | |
tree | eada3a282c50d4209ee76d7ef92f4748a1d11174 /drivers | |
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')
-rw-r--r-- | drivers/media/video/usbvision/usbvision-cards.c | 33 | ||||
-rw-r--r-- | drivers/media/video/usbvision/usbvision-cards.h | 2 | ||||
-rw-r--r-- | drivers/media/video/usbvision/usbvision-core.c | 73 | ||||
-rw-r--r-- | drivers/media/video/usbvision/usbvision-i2c.c | 2 | ||||
-rw-r--r-- | drivers/media/video/usbvision/usbvision-video.c | 3 | ||||
-rw-r--r-- | drivers/media/video/usbvision/usbvision.h | 6 |
6 files changed, 114 insertions, 5 deletions
diff --git a/drivers/media/video/usbvision/usbvision-cards.c b/drivers/media/video/usbvision/usbvision-cards.c index 68b998bd203f..8f5266157f15 100644 --- a/drivers/media/video/usbvision/usbvision-cards.c +++ b/drivers/media/video/usbvision/usbvision-cards.c | |||
@@ -1025,6 +1025,34 @@ struct usbvision_device_data_st usbvision_device_data[] = { | |||
1025 | .y_offset = -1, | 1025 | .y_offset = -1, |
1026 | .model_string = "Hauppauge WinTv-USB", | 1026 | .model_string = "Hauppauge WinTv-USB", |
1027 | }, | 1027 | }, |
1028 | [MICROCAM_NTSC] = { | ||
1029 | .interface = -1, | ||
1030 | .codec = CODEC_WEBCAM, | ||
1031 | .video_channels = 1, | ||
1032 | .video_norm = V4L2_STD_NTSC, | ||
1033 | .audio_channels = 0, | ||
1034 | .radio = 0, | ||
1035 | .vbi = 0, | ||
1036 | .tuner = 0, | ||
1037 | .tuner_type = 0, | ||
1038 | .x_offset = 71, | ||
1039 | .y_offset = 15, | ||
1040 | .model_string = "Nogatech USB MicroCam NTSC (NV3000N)", | ||
1041 | }, | ||
1042 | [MICROCAM_PAL] = { | ||
1043 | .interface = -1, | ||
1044 | .codec = CODEC_WEBCAM, | ||
1045 | .video_channels = 1, | ||
1046 | .video_norm = V4L2_STD_PAL, | ||
1047 | .audio_channels = 0, | ||
1048 | .radio = 0, | ||
1049 | .vbi = 0, | ||
1050 | .tuner = 0, | ||
1051 | .tuner_type = 0, | ||
1052 | .x_offset = 71, | ||
1053 | .y_offset = 18, | ||
1054 | .model_string = "Nogatech USB MicroCam PAL (NV3001P)", | ||
1055 | }, | ||
1028 | }; | 1056 | }; |
1029 | const int usbvision_device_data_size = ARRAY_SIZE(usbvision_device_data); | 1057 | const int usbvision_device_data_size = ARRAY_SIZE(usbvision_device_data); |
1030 | 1058 | ||
@@ -1042,6 +1070,8 @@ struct usb_device_id usbvision_table[] = { | |||
1042 | { USB_DEVICE(0x0573, 0x2d00), .driver_info = HPG_WINTV_LIVE_PAL_BG }, | 1070 | { USB_DEVICE(0x0573, 0x2d00), .driver_info = HPG_WINTV_LIVE_PAL_BG }, |
1043 | { USB_DEVICE(0x0573, 0x2d01), .driver_info = HPG_WINTV_LIVE_PRO_NTSC_MN }, | 1071 | { USB_DEVICE(0x0573, 0x2d01), .driver_info = HPG_WINTV_LIVE_PRO_NTSC_MN }, |
1044 | { USB_DEVICE(0x0573, 0x2101), .driver_info = ZORAN_PMD_NOGATECH }, | 1072 | { USB_DEVICE(0x0573, 0x2101), .driver_info = ZORAN_PMD_NOGATECH }, |
1073 | { USB_DEVICE(0x0573, 0x3000), .driver_info = MICROCAM_NTSC }, | ||
1074 | { USB_DEVICE(0x0573, 0x3001), .driver_info = MICROCAM_PAL }, | ||
1045 | { USB_DEVICE(0x0573, 0x4100), .driver_info = NOGATECH_USB_TV_NTSC_FM }, | 1075 | { USB_DEVICE(0x0573, 0x4100), .driver_info = NOGATECH_USB_TV_NTSC_FM }, |
1046 | { USB_DEVICE(0x0573, 0x4110), .driver_info = PNY_USB_TV_NTSC_FM }, | 1076 | { USB_DEVICE(0x0573, 0x4110), .driver_info = PNY_USB_TV_NTSC_FM }, |
1047 | { USB_DEVICE(0x0573, 0x4450), .driver_info = PV_PLAYTV_USB_PRO_PAL_FM }, | 1077 | { USB_DEVICE(0x0573, 0x4450), .driver_info = PV_PLAYTV_USB_PRO_PAL_FM }, |
@@ -1088,8 +1118,7 @@ struct usb_device_id usbvision_table[] = { | |||
1088 | { USB_DEVICE(0x2304, 0x0110), .driver_info = PINNA_PCTV_USB_PAL_FM }, | 1118 | { USB_DEVICE(0x2304, 0x0110), .driver_info = PINNA_PCTV_USB_PAL_FM }, |
1089 | { USB_DEVICE(0x2304, 0x0111), .driver_info = MIRO_PCTV_USB }, | 1119 | { USB_DEVICE(0x2304, 0x0111), .driver_info = MIRO_PCTV_USB }, |
1090 | { USB_DEVICE(0x2304, 0x0112), .driver_info = PINNA_PCTV_USB_NTSC_FM }, | 1120 | { USB_DEVICE(0x2304, 0x0112), .driver_info = PINNA_PCTV_USB_NTSC_FM }, |
1091 | { USB_DEVICE(0x2304, 0x0113), | 1121 | { USB_DEVICE(0x2304, 0x0113), .driver_info = PINNA_PCTV_USB_NTSC_FM_V3 }, |
1092 | .driver_info = PINNA_PCTV_USB_NTSC_FM_V3 }, | ||
1093 | { USB_DEVICE(0x2304, 0x0210), .driver_info = PINNA_PCTV_USB_PAL_FM_V2 }, | 1122 | { USB_DEVICE(0x2304, 0x0210), .driver_info = PINNA_PCTV_USB_PAL_FM_V2 }, |
1094 | { USB_DEVICE(0x2304, 0x0212), .driver_info = PINNA_PCTV_USB_NTSC_FM_V2 }, | 1123 | { USB_DEVICE(0x2304, 0x0212), .driver_info = PINNA_PCTV_USB_NTSC_FM_V2 }, |
1095 | { USB_DEVICE(0x2304, 0x0214), .driver_info = PINNA_PCTV_USB_PAL_FM_V3 }, | 1124 | { USB_DEVICE(0x2304, 0x0214), .driver_info = PINNA_PCTV_USB_PAL_FM_V3 }, |
diff --git a/drivers/media/video/usbvision/usbvision-cards.h b/drivers/media/video/usbvision/usbvision-cards.h index 9c6ad22960d8..a51cc1185cce 100644 --- a/drivers/media/video/usbvision/usbvision-cards.h +++ b/drivers/media/video/usbvision/usbvision-cards.h | |||
@@ -63,5 +63,7 @@ | |||
63 | #define PINNA_PCTV_BUNGEE_PAL_FM 62 | 63 | #define PINNA_PCTV_BUNGEE_PAL_FM 62 |
64 | #define HPG_WINTV 63 | 64 | #define HPG_WINTV 63 |
65 | #define PINNA_PCTV_USB_NTSC_FM_V3 64 | 65 | #define PINNA_PCTV_USB_NTSC_FM_V3 64 |
66 | #define MICROCAM_NTSC 65 | ||
67 | #define MICROCAM_PAL 66 | ||
66 | 68 | ||
67 | extern const int usbvision_device_data_size; | 69 | extern const int usbvision_device_data_size; |
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) | |||
1679 | return err_code; | 1679 | return err_code; |
1680 | } | 1680 | } |
1681 | 1681 | ||
1682 | /* configure webcam image sensor using the serial port */ | ||
1683 | static int usbvision_init_webcam(struct usb_usbvision *usbvision) | ||
1684 | { | ||
1685 | int rc; | ||
1686 | int i; | ||
1687 | static char init_values[38][3] = { | ||
1688 | { 0x04, 0x12, 0x08 }, { 0x05, 0xff, 0xc8 }, { 0x06, 0x18, 0x07 }, { 0x07, 0x90, 0x00 }, | ||
1689 | { 0x09, 0x00, 0x00 }, { 0x0a, 0x00, 0x00 }, { 0x0b, 0x08, 0x00 }, { 0x0d, 0xcc, 0xcc }, | ||
1690 | { 0x0e, 0x13, 0x14 }, { 0x10, 0x9b, 0x83 }, { 0x11, 0x5a, 0x3f }, { 0x12, 0xe4, 0x73 }, | ||
1691 | { 0x13, 0x88, 0x84 }, { 0x14, 0x89, 0x80 }, { 0x15, 0x00, 0x20 }, { 0x16, 0x00, 0x00 }, | ||
1692 | { 0x17, 0xff, 0xa0 }, { 0x18, 0x6b, 0x20 }, { 0x19, 0x22, 0x40 }, { 0x1a, 0x10, 0x07 }, | ||
1693 | { 0x1b, 0x00, 0x47 }, { 0x1c, 0x03, 0xe0 }, { 0x1d, 0x00, 0x00 }, { 0x1e, 0x00, 0x00 }, | ||
1694 | { 0x1f, 0x00, 0x00 }, { 0x20, 0x00, 0x00 }, { 0x21, 0x00, 0x00 }, { 0x22, 0x00, 0x00 }, | ||
1695 | { 0x23, 0x00, 0x00 }, { 0x24, 0x00, 0x00 }, { 0x25, 0x00, 0x00 }, { 0x26, 0x00, 0x00 }, | ||
1696 | { 0x27, 0x00, 0x00 }, { 0x28, 0x00, 0x00 }, { 0x29, 0x00, 0x00 }, { 0x08, 0x80, 0x60 }, | ||
1697 | { 0x0f, 0x2d, 0x24 }, { 0x0c, 0x80, 0x80 } | ||
1698 | }; | ||
1699 | char value[3]; | ||
1700 | |||
1701 | /* the only difference between PAL and NTSC init_values */ | ||
1702 | if (usbvision_device_data[usbvision->dev_model].video_norm == V4L2_STD_NTSC) | ||
1703 | init_values[4][1] = 0x34; | ||
1704 | |||
1705 | for (i = 0; i < sizeof(init_values) / 3; i++) { | ||
1706 | usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_SER_MODE_SOFT); | ||
1707 | memcpy(value, init_values[i], 3); | ||
1708 | rc = usb_control_msg(usbvision->dev, | ||
1709 | usb_sndctrlpipe(usbvision->dev, 1), | ||
1710 | USBVISION_OP_CODE, | ||
1711 | USB_DIR_OUT | USB_TYPE_VENDOR | | ||
1712 | USB_RECIP_ENDPOINT, 0, | ||
1713 | (__u16) USBVISION_SER_DAT1, value, | ||
1714 | 3, HZ); | ||
1715 | if (rc < 0) | ||
1716 | return rc; | ||
1717 | usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_SER_MODE_SIO); | ||
1718 | /* write 3 bytes to the serial port using SIO mode */ | ||
1719 | usbvision_write_reg(usbvision, USBVISION_SER_CONT, 3 | 0x10); | ||
1720 | usbvision_write_reg(usbvision, USBVISION_IOPIN_REG, 0); | ||
1721 | usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_SER_MODE_SOFT); | ||
1722 | usbvision_write_reg(usbvision, USBVISION_IOPIN_REG, USBVISION_IO_2); | ||
1723 | usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_SER_MODE_SOFT | USBVISION_CLK_OUT); | ||
1724 | usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_SER_MODE_SOFT | USBVISION_DAT_IO); | ||
1725 | usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_SER_MODE_SOFT | USBVISION_CLK_OUT | USBVISION_DAT_IO); | ||
1726 | } | ||
1727 | |||
1728 | return 0; | ||
1729 | } | ||
1730 | |||
1682 | /* | 1731 | /* |
1683 | * usbvision_set_video_format() | 1732 | * usbvision_set_video_format() |
1684 | * | 1733 | * |
@@ -1797,6 +1846,13 @@ int usbvision_set_output(struct usb_usbvision *usbvision, int width, | |||
1797 | 1846 | ||
1798 | frame_drop = FRAMERATE_MAX; /* We can allow the maximum here, because dropping is controlled */ | 1847 | frame_drop = FRAMERATE_MAX; /* We can allow the maximum here, because dropping is controlled */ |
1799 | 1848 | ||
1849 | if (usbvision_device_data[usbvision->dev_model].codec == CODEC_WEBCAM) { | ||
1850 | if (usbvision_device_data[usbvision->dev_model].video_norm == V4L2_STD_PAL) | ||
1851 | frame_drop = 25; | ||
1852 | else | ||
1853 | frame_drop = 30; | ||
1854 | } | ||
1855 | |||
1800 | /* frame_drop = 7; => frame_phase = 1, 5, 9, 13, 17, 21, 25, 0, 4, 8, ... | 1856 | /* frame_drop = 7; => frame_phase = 1, 5, 9, 13, 17, 21, 25, 0, 4, 8, ... |
1801 | => frame_skip = 4; | 1857 | => frame_skip = 4; |
1802 | => frame_rate = (7 + 1) * 25 / 32 = 200 / 32 = 6.25; | 1858 | => frame_rate = (7 + 1) * 25 / 32 = 200 / 32 = 6.25; |
@@ -2046,6 +2102,12 @@ int usbvision_set_input(struct usb_usbvision *usbvision) | |||
2046 | value[7] = 0x00; /* 0x0010 -> 16 Input video v offset */ | 2102 | value[7] = 0x00; /* 0x0010 -> 16 Input video v offset */ |
2047 | } | 2103 | } |
2048 | 2104 | ||
2105 | /* webcam is only 480 pixels wide, both PAL and NTSC version */ | ||
2106 | if (usbvision_device_data[usbvision->dev_model].codec == CODEC_WEBCAM) { | ||
2107 | value[0] = 0xe0; | ||
2108 | value[1] = 0x01; /* 0x01E0 -> 480 Input video line length */ | ||
2109 | } | ||
2110 | |||
2049 | if (usbvision_device_data[usbvision->dev_model].x_offset >= 0) { | 2111 | if (usbvision_device_data[usbvision->dev_model].x_offset >= 0) { |
2050 | value[4] = usbvision_device_data[usbvision->dev_model].x_offset & 0xff; | 2112 | value[4] = usbvision_device_data[usbvision->dev_model].x_offset & 0xff; |
2051 | value[5] = (usbvision_device_data[usbvision->dev_model].x_offset & 0x0300) >> 8; | 2113 | 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) | |||
2148 | (__u16) USBVISION_DRM_PRM1, value, 8, HZ); | 2210 | (__u16) USBVISION_DRM_PRM1, value, 8, HZ); |
2149 | 2211 | ||
2150 | if (rc < 0) { | 2212 | if (rc < 0) { |
2151 | dev_err(&usbvision->dev->dev, "%sERROR=%d\n", __func__, rc); | 2213 | dev_err(&usbvision->dev->dev, "%s: ERROR=%d\n", __func__, rc); |
2152 | return rc; | 2214 | return rc; |
2153 | } | 2215 | } |
2154 | 2216 | ||
@@ -2180,8 +2242,15 @@ int usbvision_power_on(struct usb_usbvision *usbvision) | |||
2180 | usbvision_write_reg(usbvision, USBVISION_PWR_REG, | 2242 | usbvision_write_reg(usbvision, USBVISION_PWR_REG, |
2181 | USBVISION_SSPND_EN | USBVISION_RES2); | 2243 | USBVISION_SSPND_EN | USBVISION_RES2); |
2182 | 2244 | ||
2245 | if (usbvision_device_data[usbvision->dev_model].codec == CODEC_WEBCAM) { | ||
2246 | usbvision_write_reg(usbvision, USBVISION_VIN_REG1, | ||
2247 | USBVISION_16_422_SYNC | USBVISION_HVALID_PO); | ||
2248 | usbvision_write_reg(usbvision, USBVISION_VIN_REG2, | ||
2249 | USBVISION_NOHVALID | USBVISION_KEEP_BLANK); | ||
2250 | } | ||
2183 | usbvision_write_reg(usbvision, USBVISION_PWR_REG, | 2251 | usbvision_write_reg(usbvision, USBVISION_PWR_REG, |
2184 | USBVISION_SSPND_EN | USBVISION_PWR_VID); | 2252 | USBVISION_SSPND_EN | USBVISION_PWR_VID); |
2253 | mdelay(10); | ||
2185 | err_code = usbvision_write_reg(usbvision, USBVISION_PWR_REG, | 2254 | err_code = usbvision_write_reg(usbvision, USBVISION_PWR_REG, |
2186 | USBVISION_SSPND_EN | USBVISION_PWR_VID | USBVISION_RES2); | 2255 | USBVISION_SSPND_EN | USBVISION_PWR_VID | USBVISION_RES2); |
2187 | if (err_code == 1) | 2256 | if (err_code == 1) |
@@ -2310,6 +2379,8 @@ int usbvision_set_audio(struct usb_usbvision *usbvision, int audio_channel) | |||
2310 | 2379 | ||
2311 | int usbvision_setup(struct usb_usbvision *usbvision, int format) | 2380 | int usbvision_setup(struct usb_usbvision *usbvision, int format) |
2312 | { | 2381 | { |
2382 | if (usbvision_device_data[usbvision->dev_model].codec == CODEC_WEBCAM) | ||
2383 | usbvision_init_webcam(usbvision); | ||
2313 | usbvision_set_video_format(usbvision, format); | 2384 | usbvision_set_video_format(usbvision, format); |
2314 | usbvision_set_dram_settings(usbvision); | 2385 | usbvision_set_dram_settings(usbvision); |
2315 | usbvision_set_compress_params(usbvision); | 2386 | usbvision_set_compress_params(usbvision); |
diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c index 05b1344181cd..d7f97513b289 100644 --- a/drivers/media/video/usbvision/usbvision-i2c.c +++ b/drivers/media/video/usbvision/usbvision-i2c.c | |||
@@ -222,7 +222,7 @@ int usbvision_i2c_register(struct usb_usbvision *usbvision) | |||
222 | i2c_set_adapdata(&usbvision->i2c_adap, &usbvision->v4l2_dev); | 222 | i2c_set_adapdata(&usbvision->i2c_adap, &usbvision->v4l2_dev); |
223 | 223 | ||
224 | if (usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_IIC_LRNACK) < 0) { | 224 | if (usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_IIC_LRNACK) < 0) { |
225 | printk(KERN_ERR "usbvision_register: can't write reg\n"); | 225 | printk(KERN_ERR "usbvision_i2c_register: can't write reg\n"); |
226 | return -EBUSY; | 226 | return -EBUSY; |
227 | } | 227 | } |
228 | 228 | ||
diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index 6083137f0bf8..711cd997e21c 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c | |||
@@ -1470,7 +1470,8 @@ static void usbvision_configure_video(struct usb_usbvision *usbvision) | |||
1470 | 1470 | ||
1471 | /* This should be here to make i2c clients to be able to register */ | 1471 | /* This should be here to make i2c clients to be able to register */ |
1472 | /* first switch off audio */ | 1472 | /* first switch off audio */ |
1473 | usbvision_audio_off(usbvision); | 1473 | if (usbvision_device_data[model].audio_channels > 0) |
1474 | usbvision_audio_off(usbvision); | ||
1474 | if (!power_on_at_open) { | 1475 | if (!power_on_at_open) { |
1475 | /* and then power up the noisy tuner */ | 1476 | /* and then power up the noisy tuner */ |
1476 | usbvision_power_on(usbvision); | 1477 | usbvision_power_on(usbvision); |
diff --git a/drivers/media/video/usbvision/usbvision.h b/drivers/media/video/usbvision/usbvision.h index 8074787fd1ac..43cf61fe4943 100644 --- a/drivers/media/video/usbvision/usbvision.h +++ b/drivers/media/video/usbvision/usbvision.h | |||
@@ -59,6 +59,11 @@ | |||
59 | #define USBVISION_AUDIO_RADIO 2 | 59 | #define USBVISION_AUDIO_RADIO 2 |
60 | #define USBVISION_AUDIO_MUTE 3 | 60 | #define USBVISION_AUDIO_MUTE 3 |
61 | #define USBVISION_SER_MODE 0x07 | 61 | #define USBVISION_SER_MODE 0x07 |
62 | #define USBVISION_CLK_OUT (1 << 0) | ||
63 | #define USBVISION_DAT_IO (1 << 1) | ||
64 | #define USBVISION_SENS_OUT (1 << 2) | ||
65 | #define USBVISION_SER_MODE_SOFT (0 << 4) | ||
66 | #define USBVISION_SER_MODE_SIO (1 << 4) | ||
62 | #define USBVISION_SER_ADRS 0x08 | 67 | #define USBVISION_SER_ADRS 0x08 |
63 | #define USBVISION_SER_CONT 0x09 | 68 | #define USBVISION_SER_CONT 0x09 |
64 | #define USBVISION_SER_DAT1 0x0A | 69 | #define USBVISION_SER_DAT1 0x0A |
@@ -328,6 +333,7 @@ struct usbvision_frame { | |||
328 | 333 | ||
329 | #define CODEC_SAA7113 7113 | 334 | #define CODEC_SAA7113 7113 |
330 | #define CODEC_SAA7111 7111 | 335 | #define CODEC_SAA7111 7111 |
336 | #define CODEC_WEBCAM 3000 | ||
331 | #define BRIDGE_NT1003 1003 | 337 | #define BRIDGE_NT1003 1003 |
332 | #define BRIDGE_NT1004 1004 | 338 | #define BRIDGE_NT1004 1004 |
333 | #define BRIDGE_NT1005 1005 | 339 | #define BRIDGE_NT1005 1005 |