diff options
Diffstat (limited to 'drivers/media/video')
43 files changed, 2131 insertions, 453 deletions
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 94f440535c64..061e147f6f26 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig | |||
@@ -866,9 +866,13 @@ config USB_W9968CF | |||
866 | module will be called w9968cf. | 866 | module will be called w9968cf. |
867 | 867 | ||
868 | config USB_OV511 | 868 | config USB_OV511 |
869 | tristate "USB OV511 Camera support" | 869 | tristate "USB OV511 Camera support (DEPRECATED)" |
870 | depends on VIDEO_V4L1 | 870 | depends on VIDEO_V4L1 |
871 | ---help--- | 871 | ---help--- |
872 | This driver is DEPRECATED please use the gspca ov519 module | ||
873 | instead. Note that for the ov511 / ov518 support of the gspca module | ||
874 | you need atleast version 0.6.0 of libv4l. | ||
875 | |||
872 | Say Y here if you want to connect this type of camera to your | 876 | Say Y here if you want to connect this type of camera to your |
873 | computer's USB port. See <file:Documentation/video4linux/ov511.txt> | 877 | computer's USB port. See <file:Documentation/video4linux/ov511.txt> |
874 | for more information and for a list of supported cameras. | 878 | for more information and for a list of supported cameras. |
diff --git a/drivers/media/video/cx18/cx18-controls.c b/drivers/media/video/cx18/cx18-controls.c index 8e35c3aed544..5136df198338 100644 --- a/drivers/media/video/cx18/cx18-controls.c +++ b/drivers/media/video/cx18/cx18-controls.c | |||
@@ -61,6 +61,8 @@ int cx18_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *qctrl) | |||
61 | 61 | ||
62 | switch (qctrl->id) { | 62 | switch (qctrl->id) { |
63 | /* Standard V4L2 controls */ | 63 | /* Standard V4L2 controls */ |
64 | case V4L2_CID_USER_CLASS: | ||
65 | return v4l2_ctrl_query_fill(qctrl, 0, 0, 0, 0); | ||
64 | case V4L2_CID_BRIGHTNESS: | 66 | case V4L2_CID_BRIGHTNESS: |
65 | case V4L2_CID_HUE: | 67 | case V4L2_CID_HUE: |
66 | case V4L2_CID_SATURATION: | 68 | case V4L2_CID_SATURATION: |
diff --git a/drivers/media/video/cx231xx/cx231xx-avcore.c b/drivers/media/video/cx231xx/cx231xx-avcore.c index 6a9464079b4c..28f48f41f218 100644 --- a/drivers/media/video/cx231xx/cx231xx-avcore.c +++ b/drivers/media/video/cx231xx/cx231xx-avcore.c | |||
@@ -1052,22 +1052,13 @@ int cx231xx_set_audio_decoder_input(struct cx231xx *dev, | |||
1052 | /* Set resolution of the video */ | 1052 | /* Set resolution of the video */ |
1053 | int cx231xx_resolution_set(struct cx231xx *dev) | 1053 | int cx231xx_resolution_set(struct cx231xx *dev) |
1054 | { | 1054 | { |
1055 | int width, height; | ||
1056 | u32 hscale, vscale; | ||
1057 | int status = 0; | ||
1058 | |||
1059 | width = dev->width; | ||
1060 | height = dev->height; | ||
1061 | |||
1062 | get_scale(dev, width, height, &hscale, &vscale); | ||
1063 | |||
1064 | /* set horzontal scale */ | 1055 | /* set horzontal scale */ |
1065 | status = vid_blk_write_word(dev, HSCALE_CTRL, hscale); | 1056 | int status = vid_blk_write_word(dev, HSCALE_CTRL, dev->hscale); |
1057 | if (status) | ||
1058 | return status; | ||
1066 | 1059 | ||
1067 | /* set vertical scale */ | 1060 | /* set vertical scale */ |
1068 | status = vid_blk_write_word(dev, VSCALE_CTRL, vscale); | 1061 | return vid_blk_write_word(dev, VSCALE_CTRL, dev->vscale); |
1069 | |||
1070 | return status; | ||
1071 | } | 1062 | } |
1072 | 1063 | ||
1073 | /****************************************************************************** | 1064 | /****************************************************************************** |
@@ -2055,7 +2046,7 @@ int cx231xx_initialize_stream_xfer(struct cx231xx *dev, u32 media_type) | |||
2055 | 2046 | ||
2056 | int cx231xx_capture_start(struct cx231xx *dev, int start, u8 media_type) | 2047 | int cx231xx_capture_start(struct cx231xx *dev, int start, u8 media_type) |
2057 | { | 2048 | { |
2058 | int rc; | 2049 | int rc = -1; |
2059 | u32 ep_mask = -1; | 2050 | u32 ep_mask = -1; |
2060 | struct pcb_config *pcb_config; | 2051 | struct pcb_config *pcb_config; |
2061 | 2052 | ||
diff --git a/drivers/media/video/cx231xx/cx231xx-video.c b/drivers/media/video/cx231xx/cx231xx-video.c index a23ae73fe634..609bae6098d3 100644 --- a/drivers/media/video/cx231xx/cx231xx-video.c +++ b/drivers/media/video/cx231xx/cx231xx-video.c | |||
@@ -893,9 +893,9 @@ static int check_dev(struct cx231xx *dev) | |||
893 | return 0; | 893 | return 0; |
894 | } | 894 | } |
895 | 895 | ||
896 | void get_scale(struct cx231xx *dev, | 896 | static void get_scale(struct cx231xx *dev, |
897 | unsigned int width, unsigned int height, | 897 | unsigned int width, unsigned int height, |
898 | unsigned int *hscale, unsigned int *vscale) | 898 | unsigned int *hscale, unsigned int *vscale) |
899 | { | 899 | { |
900 | unsigned int maxw = norm_maxw(dev); | 900 | unsigned int maxw = norm_maxw(dev); |
901 | unsigned int maxh = norm_maxh(dev); | 901 | unsigned int maxh = norm_maxh(dev); |
@@ -907,10 +907,6 @@ void get_scale(struct cx231xx *dev, | |||
907 | *vscale = (((unsigned long)maxh) << 12) / height - 4096L; | 907 | *vscale = (((unsigned long)maxh) << 12) / height - 4096L; |
908 | if (*vscale >= 0x4000) | 908 | if (*vscale >= 0x4000) |
909 | *vscale = 0x3fff; | 909 | *vscale = 0x3fff; |
910 | |||
911 | dev->hscale = *hscale; | ||
912 | dev->vscale = *vscale; | ||
913 | |||
914 | } | 910 | } |
915 | 911 | ||
916 | /* ------------------------------------------------------------------ | 912 | /* ------------------------------------------------------------------ |
@@ -955,8 +951,8 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
955 | { | 951 | { |
956 | struct cx231xx_fh *fh = priv; | 952 | struct cx231xx_fh *fh = priv; |
957 | struct cx231xx *dev = fh->dev; | 953 | struct cx231xx *dev = fh->dev; |
958 | int width = f->fmt.pix.width; | 954 | unsigned int width = f->fmt.pix.width; |
959 | int height = f->fmt.pix.height; | 955 | unsigned int height = f->fmt.pix.height; |
960 | unsigned int maxw = norm_maxw(dev); | 956 | unsigned int maxw = norm_maxw(dev); |
961 | unsigned int maxh = norm_maxh(dev); | 957 | unsigned int maxh = norm_maxh(dev); |
962 | unsigned int hscale, vscale; | 958 | unsigned int hscale, vscale; |
@@ -971,17 +967,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
971 | 967 | ||
972 | /* width must even because of the YUYV format | 968 | /* width must even because of the YUYV format |
973 | height must be even because of interlacing */ | 969 | height must be even because of interlacing */ |
974 | height &= 0xfffe; | 970 | v4l_bound_align_image(&width, 48, maxw, 1, &height, 32, maxh, 1, 0); |
975 | width &= 0xfffe; | ||
976 | |||
977 | if (unlikely(height < 32)) | ||
978 | height = 32; | ||
979 | if (unlikely(height > maxh)) | ||
980 | height = maxh; | ||
981 | if (unlikely(width < 48)) | ||
982 | width = 48; | ||
983 | if (unlikely(width > maxw)) | ||
984 | width = maxw; | ||
985 | 971 | ||
986 | get_scale(dev, width, height, &hscale, &vscale); | 972 | get_scale(dev, width, height, &hscale, &vscale); |
987 | 973 | ||
diff --git a/drivers/media/video/cx231xx/cx231xx.h b/drivers/media/video/cx231xx/cx231xx.h index e38eb2d425f7..a0f823ac6b8d 100644 --- a/drivers/media/video/cx231xx/cx231xx.h +++ b/drivers/media/video/cx231xx/cx231xx.h | |||
@@ -722,9 +722,6 @@ int cx231xx_set_video_input_mux(struct cx231xx *dev, u8 input); | |||
722 | int cx231xx_set_decoder_video_input(struct cx231xx *dev, u8 pin_type, u8 input); | 722 | int cx231xx_set_decoder_video_input(struct cx231xx *dev, u8 pin_type, u8 input); |
723 | int cx231xx_do_mode_ctrl_overrides(struct cx231xx *dev); | 723 | int cx231xx_do_mode_ctrl_overrides(struct cx231xx *dev); |
724 | int cx231xx_set_audio_input(struct cx231xx *dev, u8 input); | 724 | int cx231xx_set_audio_input(struct cx231xx *dev, u8 input); |
725 | void get_scale(struct cx231xx *dev, | ||
726 | unsigned int width, unsigned int height, | ||
727 | unsigned int *hscale, unsigned int *vscale); | ||
728 | 725 | ||
729 | /* Provided by cx231xx-video.c */ | 726 | /* Provided by cx231xx-video.c */ |
730 | int cx231xx_register_extension(struct cx231xx_ops *dev); | 727 | int cx231xx_register_extension(struct cx231xx_ops *dev); |
diff --git a/drivers/media/video/cx2341x.c b/drivers/media/video/cx2341x.c index 8ded52946334..4c8e95853fa3 100644 --- a/drivers/media/video/cx2341x.c +++ b/drivers/media/video/cx2341x.c | |||
@@ -500,6 +500,8 @@ int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params, | |||
500 | int err; | 500 | int err; |
501 | 501 | ||
502 | switch (qctrl->id) { | 502 | switch (qctrl->id) { |
503 | case V4L2_CID_MPEG_CLASS: | ||
504 | return v4l2_ctrl_query_fill(qctrl, 0, 0, 0, 0); | ||
503 | case V4L2_CID_MPEG_STREAM_TYPE: | 505 | case V4L2_CID_MPEG_STREAM_TYPE: |
504 | return v4l2_ctrl_query_fill(qctrl, | 506 | return v4l2_ctrl_query_fill(qctrl, |
505 | V4L2_MPEG_STREAM_TYPE_MPEG2_PS, | 507 | V4L2_MPEG_STREAM_TYPE_MPEG2_PS, |
diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index e236df23370e..48a975134ac5 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #include "dibx000_common.h" | 45 | #include "dibx000_common.h" |
46 | #include "zl10353.h" | 46 | #include "zl10353.h" |
47 | #include "stv0900.h" | 47 | #include "stv0900.h" |
48 | #include "stv0900_reg.h" | ||
48 | #include "stv6110.h" | 49 | #include "stv6110.h" |
49 | #include "lnbh24.h" | 50 | #include "lnbh24.h" |
50 | #include "cx24116.h" | 51 | #include "cx24116.h" |
@@ -242,12 +243,22 @@ static struct tda18271_std_map hauppauge_tda18271_std_map = { | |||
242 | .if_lvl = 6, .rfagc_top = 0x37 }, | 243 | .if_lvl = 6, .rfagc_top = 0x37 }, |
243 | }; | 244 | }; |
244 | 245 | ||
246 | static struct tda18271_std_map hauppauge_hvr1200_tda18271_std_map = { | ||
247 | .dvbt_6 = { .if_freq = 3300, .agc_mode = 3, .std = 4, | ||
248 | .if_lvl = 1, .rfagc_top = 0x37, }, | ||
249 | .dvbt_7 = { .if_freq = 3800, .agc_mode = 3, .std = 5, | ||
250 | .if_lvl = 1, .rfagc_top = 0x37, }, | ||
251 | .dvbt_8 = { .if_freq = 4300, .agc_mode = 3, .std = 6, | ||
252 | .if_lvl = 1, .rfagc_top = 0x37, }, | ||
253 | }; | ||
254 | |||
245 | static struct tda18271_config hauppauge_tda18271_config = { | 255 | static struct tda18271_config hauppauge_tda18271_config = { |
246 | .std_map = &hauppauge_tda18271_std_map, | 256 | .std_map = &hauppauge_tda18271_std_map, |
247 | .gate = TDA18271_GATE_ANALOG, | 257 | .gate = TDA18271_GATE_ANALOG, |
248 | }; | 258 | }; |
249 | 259 | ||
250 | static struct tda18271_config hauppauge_hvr1200_tuner_config = { | 260 | static struct tda18271_config hauppauge_hvr1200_tuner_config = { |
261 | .std_map = &hauppauge_hvr1200_tda18271_std_map, | ||
251 | .gate = TDA18271_GATE_ANALOG, | 262 | .gate = TDA18271_GATE_ANALOG, |
252 | }; | 263 | }; |
253 | 264 | ||
@@ -370,13 +381,25 @@ static struct zl10353_config dvico_fusionhdtv_xc3028 = { | |||
370 | .disable_i2c_gate_ctrl = 1, | 381 | .disable_i2c_gate_ctrl = 1, |
371 | }; | 382 | }; |
372 | 383 | ||
384 | static struct stv0900_reg stv0900_ts_regs[] = { | ||
385 | { R0900_TSGENERAL, 0x00 }, | ||
386 | { R0900_P1_TSSPEED, 0x40 }, | ||
387 | { R0900_P2_TSSPEED, 0x40 }, | ||
388 | { R0900_P1_TSCFGM, 0xc0 }, | ||
389 | { R0900_P2_TSCFGM, 0xc0 }, | ||
390 | { R0900_P1_TSCFGH, 0xe0 }, | ||
391 | { R0900_P2_TSCFGH, 0xe0 }, | ||
392 | { R0900_P1_TSCFGL, 0x20 }, | ||
393 | { R0900_P2_TSCFGL, 0x20 }, | ||
394 | { 0xffff, 0xff }, /* terminate */ | ||
395 | }; | ||
396 | |||
373 | static struct stv0900_config netup_stv0900_config = { | 397 | static struct stv0900_config netup_stv0900_config = { |
374 | .demod_address = 0x68, | 398 | .demod_address = 0x68, |
375 | .xtal = 27000000, | 399 | .xtal = 27000000, |
376 | .clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */ | 400 | .clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */ |
377 | .diseqc_mode = 2,/* 2/3 PWM */ | 401 | .diseqc_mode = 2,/* 2/3 PWM */ |
378 | .path1_mode = 2,/*Serial continues clock */ | 402 | .ts_config_regs = stv0900_ts_regs, |
379 | .path2_mode = 2,/*Serial continues clock */ | ||
380 | .tun1_maddress = 0,/* 0x60 */ | 403 | .tun1_maddress = 0,/* 0x60 */ |
381 | .tun2_maddress = 3,/* 0x63 */ | 404 | .tun2_maddress = 3,/* 0x63 */ |
382 | .tun1_adc = 1,/* 1 Vpp */ | 405 | .tun1_adc = 1,/* 1 Vpp */ |
@@ -736,7 +759,8 @@ static int dvb_register(struct cx23885_tsport *port) | |||
736 | if (!dvb_attach(lnbh24_attach, | 759 | if (!dvb_attach(lnbh24_attach, |
737 | fe0->dvb.frontend, | 760 | fe0->dvb.frontend, |
738 | &i2c_bus->i2c_adap, | 761 | &i2c_bus->i2c_adap, |
739 | LNBH24_PCL, 0, 0x09)) | 762 | LNBH24_PCL, |
763 | LNBH24_TTX, 0x09)) | ||
740 | printk(KERN_ERR | 764 | printk(KERN_ERR |
741 | "No LNBH24 found!\n"); | 765 | "No LNBH24 found!\n"); |
742 | 766 | ||
@@ -756,7 +780,8 @@ static int dvb_register(struct cx23885_tsport *port) | |||
756 | if (!dvb_attach(lnbh24_attach, | 780 | if (!dvb_attach(lnbh24_attach, |
757 | fe0->dvb.frontend, | 781 | fe0->dvb.frontend, |
758 | &i2c_bus->i2c_adap, | 782 | &i2c_bus->i2c_adap, |
759 | LNBH24_PCL, 0, 0x0a)) | 783 | LNBH24_PCL, |
784 | LNBH24_TTX, 0x0a)) | ||
760 | printk(KERN_ERR | 785 | printk(KERN_ERR |
761 | "No LNBH24 found!\n"); | 786 | "No LNBH24 found!\n"); |
762 | 787 | ||
diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c index 66bbd2e71105..70836af3ab48 100644 --- a/drivers/media/video/cx23885/cx23885-video.c +++ b/drivers/media/video/cx23885/cx23885-video.c | |||
@@ -963,15 +963,8 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
963 | } | 963 | } |
964 | 964 | ||
965 | f->fmt.pix.field = field; | 965 | f->fmt.pix.field = field; |
966 | if (f->fmt.pix.height < 32) | 966 | v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2, |
967 | f->fmt.pix.height = 32; | 967 | &f->fmt.pix.height, 32, maxh, 0, 0); |
968 | if (f->fmt.pix.height > maxh) | ||
969 | f->fmt.pix.height = maxh; | ||
970 | if (f->fmt.pix.width < 48) | ||
971 | f->fmt.pix.width = 48; | ||
972 | if (f->fmt.pix.width > maxw) | ||
973 | f->fmt.pix.width = maxw; | ||
974 | f->fmt.pix.width &= ~0x03; | ||
975 | f->fmt.pix.bytesperline = | 968 | f->fmt.pix.bytesperline = |
976 | (f->fmt.pix.width * fmt->depth) >> 3; | 969 | (f->fmt.pix.width * fmt->depth) >> 3; |
977 | f->fmt.pix.sizeimage = | 970 | f->fmt.pix.sizeimage = |
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 94b7a52629d0..a5cc1c1fc2d6 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c | |||
@@ -1524,33 +1524,45 @@ static const struct cx88_board cx88_boards[] = { | |||
1524 | }, | 1524 | }, |
1525 | .mpeg = CX88_MPEG_DVB, | 1525 | .mpeg = CX88_MPEG_DVB, |
1526 | }, | 1526 | }, |
1527 | /* Terry Wu <terrywu2009@gmail.com> */ | ||
1528 | /* TV Audio : set GPIO 2, 18, 19 value to 0, 1, 0 */ | ||
1529 | /* FM Audio : set GPIO 2, 18, 19 value to 0, 0, 0 */ | ||
1530 | /* Line-in Audio : set GPIO 2, 18, 19 value to 0, 1, 1 */ | ||
1531 | /* Mute Audio : set GPIO 2 value to 1 */ | ||
1527 | [CX88_BOARD_WINFAST_TV2000_XP_GLOBAL] = { | 1532 | [CX88_BOARD_WINFAST_TV2000_XP_GLOBAL] = { |
1528 | .name = "Winfast TV2000 XP Global", | 1533 | .name = "Leadtek TV2000 XP Global", |
1529 | .tuner_type = TUNER_XC2028, | 1534 | .tuner_type = TUNER_XC2028, |
1530 | .tuner_addr = 0x61, | 1535 | .tuner_addr = 0x61, |
1536 | .radio_type = TUNER_XC2028, | ||
1537 | .radio_addr = 0x61, | ||
1531 | .input = { { | 1538 | .input = { { |
1532 | .type = CX88_VMUX_TELEVISION, | 1539 | .type = CX88_VMUX_TELEVISION, |
1533 | .vmux = 0, | 1540 | .vmux = 0, |
1534 | .gpio0 = 0x0400, /* pin 2:mute = 0 (off?) */ | 1541 | .gpio0 = 0x0400, /* pin 2 = 0 */ |
1535 | .gpio1 = 0x0000, | 1542 | .gpio1 = 0x0000, |
1536 | .gpio2 = 0x0800, /* pin 19:audio = 0 (tv) */ | 1543 | .gpio2 = 0x0C04, /* pin 18 = 1, pin 19 = 0 */ |
1537 | 1544 | .gpio3 = 0x0000, | |
1538 | }, { | 1545 | }, { |
1539 | .type = CX88_VMUX_COMPOSITE1, | 1546 | .type = CX88_VMUX_COMPOSITE1, |
1540 | .vmux = 1, | 1547 | .vmux = 1, |
1541 | .gpio0 = 0x0400, /* probably? or 0x0404 to turn mute on */ | 1548 | .gpio0 = 0x0400, /* pin 2 = 0 */ |
1542 | .gpio1 = 0x0000, | 1549 | .gpio1 = 0x0000, |
1543 | .gpio2 = 0x0808, /* pin 19:audio = 1 (line) */ | 1550 | .gpio2 = 0x0C0C, /* pin 18 = 1, pin 19 = 1 */ |
1544 | 1551 | .gpio3 = 0x0000, | |
1545 | }, { | 1552 | }, { |
1546 | .type = CX88_VMUX_SVIDEO, | 1553 | .type = CX88_VMUX_SVIDEO, |
1547 | .vmux = 2, | 1554 | .vmux = 2, |
1555 | .gpio0 = 0x0400, /* pin 2 = 0 */ | ||
1556 | .gpio1 = 0x0000, | ||
1557 | .gpio2 = 0x0C0C, /* pin 18 = 1, pin 19 = 1 */ | ||
1558 | .gpio3 = 0x0000, | ||
1548 | } }, | 1559 | } }, |
1549 | .radio = { | 1560 | .radio = { |
1550 | .type = CX88_RADIO, | 1561 | .type = CX88_RADIO, |
1551 | .gpio0 = 0x004ff, | 1562 | .gpio0 = 0x0400, /* pin 2 = 0 */ |
1552 | .gpio1 = 0x010ff, | 1563 | .gpio1 = 0x0000, |
1553 | .gpio2 = 0x0ff, | 1564 | .gpio2 = 0x0C00, /* pin 18 = 0, pin 19 = 0 */ |
1565 | .gpio3 = 0x0000, | ||
1554 | }, | 1566 | }, |
1555 | }, | 1567 | }, |
1556 | [CX88_BOARD_POWERCOLOR_REAL_ANGEL] = { | 1568 | [CX88_BOARD_POWERCOLOR_REAL_ANGEL] = { |
@@ -2438,6 +2450,41 @@ static const struct cx88_subid cx88_subids[] = { | |||
2438 | .subvendor = 0x107d, | 2450 | .subvendor = 0x107d, |
2439 | .subdevice = 0x6654, | 2451 | .subdevice = 0x6654, |
2440 | .card = CX88_BOARD_WINFAST_DTV1800H, | 2452 | .card = CX88_BOARD_WINFAST_DTV1800H, |
2453 | }, { | ||
2454 | /* PVR2000 PAL Model [107d:6630] */ | ||
2455 | .subvendor = 0x107d, | ||
2456 | .subdevice = 0x6630, | ||
2457 | .card = CX88_BOARD_LEADTEK_PVR2000, | ||
2458 | }, { | ||
2459 | /* PVR2000 PAL Model [107d:6638] */ | ||
2460 | .subvendor = 0x107d, | ||
2461 | .subdevice = 0x6638, | ||
2462 | .card = CX88_BOARD_LEADTEK_PVR2000, | ||
2463 | }, { | ||
2464 | /* PVR2000 NTSC Model [107d:6631] */ | ||
2465 | .subvendor = 0x107d, | ||
2466 | .subdevice = 0x6631, | ||
2467 | .card = CX88_BOARD_LEADTEK_PVR2000, | ||
2468 | }, { | ||
2469 | /* PVR2000 NTSC Model [107d:6637] */ | ||
2470 | .subvendor = 0x107d, | ||
2471 | .subdevice = 0x6637, | ||
2472 | .card = CX88_BOARD_LEADTEK_PVR2000, | ||
2473 | }, { | ||
2474 | /* PVR2000 NTSC Model [107d:663d] */ | ||
2475 | .subvendor = 0x107d, | ||
2476 | .subdevice = 0x663d, | ||
2477 | .card = CX88_BOARD_LEADTEK_PVR2000, | ||
2478 | }, { | ||
2479 | /* DV2000 NTSC Model [107d:6621] */ | ||
2480 | .subvendor = 0x107d, | ||
2481 | .subdevice = 0x6621, | ||
2482 | .card = CX88_BOARD_WINFAST_DV2000, | ||
2483 | }, { | ||
2484 | /* TV2000 XP Global [107d:6618] */ | ||
2485 | .subvendor = 0x107d, | ||
2486 | .subdevice = 0x6618, | ||
2487 | .card = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL, | ||
2441 | }, | 2488 | }, |
2442 | }; | 2489 | }; |
2443 | 2490 | ||
@@ -2446,12 +2493,6 @@ static const struct cx88_subid cx88_subids[] = { | |||
2446 | 2493 | ||
2447 | static void leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data) | 2494 | static void leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data) |
2448 | { | 2495 | { |
2449 | /* This is just for the "Winfast 2000XP Expert" board ATM; I don't have data on | ||
2450 | * any others. | ||
2451 | * | ||
2452 | * Byte 0 is 1 on the NTSC board. | ||
2453 | */ | ||
2454 | |||
2455 | if (eeprom_data[4] != 0x7d || | 2496 | if (eeprom_data[4] != 0x7d || |
2456 | eeprom_data[5] != 0x10 || | 2497 | eeprom_data[5] != 0x10 || |
2457 | eeprom_data[7] != 0x66) { | 2498 | eeprom_data[7] != 0x66) { |
@@ -2459,8 +2500,19 @@ static void leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data) | |||
2459 | return; | 2500 | return; |
2460 | } | 2501 | } |
2461 | 2502 | ||
2462 | core->board.tuner_type = (eeprom_data[6] == 0x13) ? | 2503 | /* Terry Wu <terrywu2009@gmail.com> */ |
2463 | TUNER_PHILIPS_FM1236_MK3 : TUNER_PHILIPS_FM1216ME_MK3; | 2504 | switch (eeprom_data[6]) { |
2505 | case 0x13: /* SSID 6613 for TV2000 XP Expert NTSC Model */ | ||
2506 | case 0x21: /* SSID 6621 for DV2000 NTSC Model */ | ||
2507 | case 0x31: /* SSID 6631 for PVR2000 NTSC Model */ | ||
2508 | case 0x37: /* SSID 6637 for PVR2000 NTSC Model */ | ||
2509 | case 0x3d: /* SSID 6637 for PVR2000 NTSC Model */ | ||
2510 | core->board.tuner_type = TUNER_PHILIPS_FM1236_MK3; | ||
2511 | break; | ||
2512 | default: | ||
2513 | core->board.tuner_type = TUNER_PHILIPS_FM1216ME_MK3; | ||
2514 | break; | ||
2515 | } | ||
2464 | 2516 | ||
2465 | info_printk(core, "Leadtek Winfast 2000XP Expert config: " | 2517 | info_printk(core, "Leadtek Winfast 2000XP Expert config: " |
2466 | "tuner=%d, eeprom[0]=0x%02x\n", | 2518 | "tuner=%d, eeprom[0]=0x%02x\n", |
@@ -2713,7 +2765,6 @@ static int cx88_xc2028_tuner_callback(struct cx88_core *core, | |||
2713 | { | 2765 | { |
2714 | /* Board-specific callbacks */ | 2766 | /* Board-specific callbacks */ |
2715 | switch (core->boardnr) { | 2767 | switch (core->boardnr) { |
2716 | case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: | ||
2717 | case CX88_BOARD_POWERCOLOR_REAL_ANGEL: | 2768 | case CX88_BOARD_POWERCOLOR_REAL_ANGEL: |
2718 | case CX88_BOARD_GENIATECH_X8000_MT: | 2769 | case CX88_BOARD_GENIATECH_X8000_MT: |
2719 | case CX88_BOARD_KWORLD_ATSC_120: | 2770 | case CX88_BOARD_KWORLD_ATSC_120: |
@@ -2725,6 +2776,7 @@ static int cx88_xc2028_tuner_callback(struct cx88_core *core, | |||
2725 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: | 2776 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: |
2726 | case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: | 2777 | case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: |
2727 | return cx88_dvico_xc2028_callback(core, command, arg); | 2778 | return cx88_dvico_xc2028_callback(core, command, arg); |
2779 | case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: | ||
2728 | case CX88_BOARD_WINFAST_DTV1800H: | 2780 | case CX88_BOARD_WINFAST_DTV1800H: |
2729 | return cx88_xc3028_winfast1800h_callback(core, command, arg); | 2781 | return cx88_xc3028_winfast1800h_callback(core, command, arg); |
2730 | } | 2782 | } |
@@ -2914,6 +2966,7 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core) | |||
2914 | udelay(1000); | 2966 | udelay(1000); |
2915 | break; | 2967 | break; |
2916 | 2968 | ||
2969 | case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: | ||
2917 | case CX88_BOARD_WINFAST_DTV1800H: | 2970 | case CX88_BOARD_WINFAST_DTV1800H: |
2918 | /* GPIO 12 (xc3028 tuner reset) */ | 2971 | /* GPIO 12 (xc3028 tuner reset) */ |
2919 | cx_set(MO_GP1_IO, 0x1010); | 2972 | cx_set(MO_GP1_IO, 0x1010); |
@@ -2950,6 +3003,7 @@ void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl) | |||
2950 | case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: | 3003 | case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: |
2951 | ctl->demod = XC3028_FE_OREN538; | 3004 | ctl->demod = XC3028_FE_OREN538; |
2952 | break; | 3005 | break; |
3006 | case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: | ||
2953 | case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME: | 3007 | case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME: |
2954 | case CX88_BOARD_PROLINK_PV_8000GT: | 3008 | case CX88_BOARD_PROLINK_PV_8000GT: |
2955 | /* | 3009 | /* |
@@ -2993,6 +3047,8 @@ static void cx88_card_setup(struct cx88_core *core) | |||
2993 | if (0 == core->i2c_rc) | 3047 | if (0 == core->i2c_rc) |
2994 | gdi_eeprom(core, eeprom); | 3048 | gdi_eeprom(core, eeprom); |
2995 | break; | 3049 | break; |
3050 | case CX88_BOARD_LEADTEK_PVR2000: | ||
3051 | case CX88_BOARD_WINFAST_DV2000: | ||
2996 | case CX88_BOARD_WINFAST2000XP_EXPERT: | 3052 | case CX88_BOARD_WINFAST2000XP_EXPERT: |
2997 | if (0 == core->i2c_rc) | 3053 | if (0 == core->i2c_rc) |
2998 | leadtek_eeprom(core, eeprom); | 3054 | leadtek_eeprom(core, eeprom); |
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 0ccac702bea4..b12770848c00 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c | |||
@@ -1111,15 +1111,8 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
1111 | } | 1111 | } |
1112 | 1112 | ||
1113 | f->fmt.pix.field = field; | 1113 | f->fmt.pix.field = field; |
1114 | if (f->fmt.pix.height < 32) | 1114 | v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2, |
1115 | f->fmt.pix.height = 32; | 1115 | &f->fmt.pix.height, 32, maxh, 0, 0); |
1116 | if (f->fmt.pix.height > maxh) | ||
1117 | f->fmt.pix.height = maxh; | ||
1118 | if (f->fmt.pix.width < 48) | ||
1119 | f->fmt.pix.width = 48; | ||
1120 | if (f->fmt.pix.width > maxw) | ||
1121 | f->fmt.pix.width = maxw; | ||
1122 | f->fmt.pix.width &= ~0x03; | ||
1123 | f->fmt.pix.bytesperline = | 1116 | f->fmt.pix.bytesperline = |
1124 | (f->fmt.pix.width * fmt->depth) >> 3; | 1117 | (f->fmt.pix.width * fmt->depth) >> 3; |
1125 | f->fmt.pix.sizeimage = | 1118 | f->fmt.pix.sizeimage = |
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 00cc791a9e44..c43fdb9bc888 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c | |||
@@ -139,6 +139,24 @@ static struct em28xx_reg_seq kworld_330u_digital[] = { | |||
139 | { -1, -1, -1, -1}, | 139 | { -1, -1, -1, -1}, |
140 | }; | 140 | }; |
141 | 141 | ||
142 | /* Evga inDtube | ||
143 | GPIO0 - Enable digital power (s5h1409) - low to enable | ||
144 | GPIO1 - Enable analog power (tvp5150/emp202) - low to enable | ||
145 | GPIO4 - xc3028 reset | ||
146 | GOP3 - s5h1409 reset | ||
147 | */ | ||
148 | static struct em28xx_reg_seq evga_indtube_analog[] = { | ||
149 | {EM28XX_R08_GPIO, 0x79, 0xff, 60}, | ||
150 | { -1, -1, -1, -1}, | ||
151 | }; | ||
152 | |||
153 | static struct em28xx_reg_seq evga_indtube_digital[] = { | ||
154 | {EM28XX_R08_GPIO, 0x7a, 0xff, 1}, | ||
155 | {EM2880_R04_GPO, 0x04, 0xff, 10}, | ||
156 | {EM2880_R04_GPO, 0x0c, 0xff, 1}, | ||
157 | { -1, -1, -1, -1}, | ||
158 | }; | ||
159 | |||
142 | /* Callback for the most boards */ | 160 | /* Callback for the most boards */ |
143 | static struct em28xx_reg_seq default_tuner_gpio[] = { | 161 | static struct em28xx_reg_seq default_tuner_gpio[] = { |
144 | {EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10}, | 162 | {EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10}, |
@@ -1449,6 +1467,33 @@ struct em28xx_board em28xx_boards[] = { | |||
1449 | .gpio = terratec_av350_unmute_gpio, | 1467 | .gpio = terratec_av350_unmute_gpio, |
1450 | } }, | 1468 | } }, |
1451 | }, | 1469 | }, |
1470 | [EM2882_BOARD_EVGA_INDTUBE] = { | ||
1471 | .name = "Evga inDtube", | ||
1472 | .tuner_type = TUNER_XC2028, | ||
1473 | .tuner_gpio = default_tuner_gpio, | ||
1474 | .decoder = EM28XX_TVP5150, | ||
1475 | .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, /* NEC IR */ | ||
1476 | .mts_firmware = 1, | ||
1477 | .has_dvb = 1, | ||
1478 | .dvb_gpio = evga_indtube_digital, | ||
1479 | .ir_codes = ir_codes_evga_indtube, | ||
1480 | .input = { { | ||
1481 | .type = EM28XX_VMUX_TELEVISION, | ||
1482 | .vmux = TVP5150_COMPOSITE0, | ||
1483 | .amux = EM28XX_AMUX_VIDEO, | ||
1484 | .gpio = evga_indtube_analog, | ||
1485 | }, { | ||
1486 | .type = EM28XX_VMUX_COMPOSITE1, | ||
1487 | .vmux = TVP5150_COMPOSITE1, | ||
1488 | .amux = EM28XX_AMUX_LINE_IN, | ||
1489 | .gpio = evga_indtube_analog, | ||
1490 | }, { | ||
1491 | .type = EM28XX_VMUX_SVIDEO, | ||
1492 | .vmux = TVP5150_SVIDEO, | ||
1493 | .amux = EM28XX_AMUX_LINE_IN, | ||
1494 | .gpio = evga_indtube_analog, | ||
1495 | } }, | ||
1496 | }, | ||
1452 | }; | 1497 | }; |
1453 | const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards); | 1498 | const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards); |
1454 | 1499 | ||
@@ -1571,6 +1616,7 @@ static struct em28xx_hash_table em28xx_eeprom_hash[] = { | |||
1571 | {0x72cc5a8b, EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2, TUNER_YMEC_TVF_5533MF}, | 1616 | {0x72cc5a8b, EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2, TUNER_YMEC_TVF_5533MF}, |
1572 | {0x966a0441, EM2880_BOARD_KWORLD_DVB_310U, TUNER_XC2028}, | 1617 | {0x966a0441, EM2880_BOARD_KWORLD_DVB_310U, TUNER_XC2028}, |
1573 | {0x9567eb1a, EM2880_BOARD_EMPIRE_DUAL_TV, TUNER_XC2028}, | 1618 | {0x9567eb1a, EM2880_BOARD_EMPIRE_DUAL_TV, TUNER_XC2028}, |
1619 | {0xcee44a99, EM2882_BOARD_EVGA_INDTUBE, TUNER_XC2028}, | ||
1574 | }; | 1620 | }; |
1575 | 1621 | ||
1576 | /* I2C devicelist hash table for devices with generic USB IDs */ | 1622 | /* I2C devicelist hash table for devices with generic USB IDs */ |
@@ -1834,6 +1880,10 @@ static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl) | |||
1834 | ctl->demod = XC3028_FE_CHINA; | 1880 | ctl->demod = XC3028_FE_CHINA; |
1835 | ctl->fname = XC2028_DEFAULT_FIRMWARE; | 1881 | ctl->fname = XC2028_DEFAULT_FIRMWARE; |
1836 | break; | 1882 | break; |
1883 | case EM2882_BOARD_EVGA_INDTUBE: | ||
1884 | ctl->demod = XC3028_FE_CHINA; | ||
1885 | ctl->fname = XC3028L_DEFAULT_FIRMWARE; | ||
1886 | break; | ||
1837 | default: | 1887 | default: |
1838 | ctl->demod = XC3028_FE_OREN538; | 1888 | ctl->demod = XC3028_FE_OREN538; |
1839 | } | 1889 | } |
@@ -2101,6 +2151,12 @@ void em28xx_card_setup(struct em28xx *dev) | |||
2101 | case EM2880_BOARD_MSI_DIGIVOX_AD: | 2151 | case EM2880_BOARD_MSI_DIGIVOX_AD: |
2102 | if (!em28xx_hint_board(dev)) | 2152 | if (!em28xx_hint_board(dev)) |
2103 | em28xx_set_model(dev); | 2153 | em28xx_set_model(dev); |
2154 | |||
2155 | /* In cases where we had to use a board hint, the call to | ||
2156 | em28xx_set_mode() in em28xx_pre_card_setup() was a no-op, | ||
2157 | so make the call now so the analog GPIOs are set properly | ||
2158 | before probing the i2c bus. */ | ||
2159 | em28xx_set_mode(dev, EM28XX_ANALOG_MODE); | ||
2104 | break; | 2160 | break; |
2105 | } | 2161 | } |
2106 | 2162 | ||
diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index 563dd2b1c8e9..e7b47c8da8f3 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c | |||
@@ -445,6 +445,7 @@ static int dvb_init(struct em28xx *dev) | |||
445 | } | 445 | } |
446 | break; | 446 | break; |
447 | case EM2883_BOARD_KWORLD_HYBRID_330U: | 447 | case EM2883_BOARD_KWORLD_HYBRID_330U: |
448 | case EM2882_BOARD_EVGA_INDTUBE: | ||
448 | dvb->frontend = dvb_attach(s5h1409_attach, | 449 | dvb->frontend = dvb_attach(s5h1409_attach, |
449 | &em28xx_s5h1409_with_xc3028, | 450 | &em28xx_s5h1409_with_xc3028, |
450 | &dev->i2c_adap); | 451 | &dev->i2c_adap); |
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 882796e84dbc..8fe1beecfffa 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c | |||
@@ -687,8 +687,8 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
687 | { | 687 | { |
688 | struct em28xx_fh *fh = priv; | 688 | struct em28xx_fh *fh = priv; |
689 | struct em28xx *dev = fh->dev; | 689 | struct em28xx *dev = fh->dev; |
690 | int width = f->fmt.pix.width; | 690 | unsigned int width = f->fmt.pix.width; |
691 | int height = f->fmt.pix.height; | 691 | unsigned int height = f->fmt.pix.height; |
692 | unsigned int maxw = norm_maxw(dev); | 692 | unsigned int maxw = norm_maxw(dev); |
693 | unsigned int maxh = norm_maxh(dev); | 693 | unsigned int maxh = norm_maxh(dev); |
694 | unsigned int hscale, vscale; | 694 | unsigned int hscale, vscale; |
@@ -701,34 +701,20 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
701 | return -EINVAL; | 701 | return -EINVAL; |
702 | } | 702 | } |
703 | 703 | ||
704 | /* width must even because of the YUYV format | ||
705 | height must be even because of interlacing */ | ||
706 | height &= 0xfffe; | ||
707 | width &= 0xfffe; | ||
708 | |||
709 | if (unlikely(height < 32)) | ||
710 | height = 32; | ||
711 | if (unlikely(height > maxh)) | ||
712 | height = maxh; | ||
713 | if (unlikely(width < 48)) | ||
714 | width = 48; | ||
715 | if (unlikely(width > maxw)) | ||
716 | width = maxw; | ||
717 | |||
718 | if (dev->board.is_em2800) { | 704 | if (dev->board.is_em2800) { |
719 | /* the em2800 can only scale down to 50% */ | 705 | /* the em2800 can only scale down to 50% */ |
720 | if (height % (maxh / 2)) | 706 | height = height > (3 * maxh / 4) ? maxh : maxh / 2; |
721 | height = maxh; | 707 | width = width > (3 * maxw / 4) ? maxw : maxw / 2; |
722 | if (width % (maxw / 2)) | 708 | /* According to empiatech support the MaxPacketSize is too small |
723 | width = maxw; | 709 | * to support framesizes larger than 640x480 @ 30 fps or 640x576 |
724 | /* according to empiatech support */ | 710 | * @ 25 fps. As this would cut of a part of the image we prefer |
725 | /* the MaxPacketSize is to small to support */ | 711 | * 360x576 or 360x480 for now */ |
726 | /* framesizes larger than 640x480 @ 30 fps */ | ||
727 | /* or 640x576 @ 25 fps. As this would cut */ | ||
728 | /* of a part of the image we prefer */ | ||
729 | /* 360x576 or 360x480 for now */ | ||
730 | if (width == maxw && height == maxh) | 712 | if (width == maxw && height == maxh) |
731 | width /= 2; | 713 | width /= 2; |
714 | } else { | ||
715 | /* width must even because of the YUYV format | ||
716 | height must be even because of interlacing */ | ||
717 | v4l_bound_align_image(&width, 48, maxw, 1, &height, 32, maxh, 1, 0); | ||
732 | } | 718 | } |
733 | 719 | ||
734 | get_scale(dev, width, height, &hscale, &vscale); | 720 | get_scale(dev, width, height, &hscale, &vscale); |
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 8bf81be1da61..813ce45c2f99 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h | |||
@@ -106,6 +106,7 @@ | |||
106 | #define EM2860_BOARD_TERRATEC_GRABBY 67 | 106 | #define EM2860_BOARD_TERRATEC_GRABBY 67 |
107 | #define EM2860_BOARD_TERRATEC_AV350 68 | 107 | #define EM2860_BOARD_TERRATEC_AV350 68 |
108 | #define EM2882_BOARD_KWORLD_ATSC_315U 69 | 108 | #define EM2882_BOARD_KWORLD_ATSC_315U 69 |
109 | #define EM2882_BOARD_EVGA_INDTUBE 70 | ||
109 | 110 | ||
110 | /* Limits minimum and default number of buffers */ | 111 | /* Limits minimum and default number of buffers */ |
111 | #define EM28XX_MIN_BUF 4 | 112 | #define EM28XX_MIN_BUF 4 |
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index f7e0355ad644..1e89600986c8 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c | |||
@@ -1042,13 +1042,11 @@ static int vidioc_queryctrl(struct file *file, void *priv, | |||
1042 | for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) { | 1042 | for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) { |
1043 | if (gspca_dev->ctrl_dis & (1 << i)) | 1043 | if (gspca_dev->ctrl_dis & (1 << i)) |
1044 | continue; | 1044 | continue; |
1045 | if (ctrls->qctrl.id < id) | 1045 | if (gspca_dev->sd_desc->ctrls[i].qctrl.id < id) |
1046 | continue; | 1046 | continue; |
1047 | if (ctrls != NULL) { | 1047 | if (ctrls && gspca_dev->sd_desc->ctrls[i].qctrl.id |
1048 | if (gspca_dev->sd_desc->ctrls[i].qctrl.id | ||
1049 | > ctrls->qctrl.id) | 1048 | > ctrls->qctrl.id) |
1050 | continue; | 1049 | continue; |
1051 | } | ||
1052 | ctrls = &gspca_dev->sd_desc->ctrls[i]; | 1050 | ctrls = &gspca_dev->sd_desc->ctrls[i]; |
1053 | } | 1051 | } |
1054 | } else { | 1052 | } else { |
diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index 188866ac6cef..2f6e135d94bc 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c | |||
@@ -50,12 +50,18 @@ static int i2c_detect_tries = 10; | |||
50 | struct sd { | 50 | struct sd { |
51 | struct gspca_dev gspca_dev; /* !! must be the first item */ | 51 | struct gspca_dev gspca_dev; /* !! must be the first item */ |
52 | 52 | ||
53 | __u8 packet_nr; | ||
54 | |||
53 | char bridge; | 55 | char bridge; |
54 | #define BRIDGE_OV511 0 | 56 | #define BRIDGE_OV511 0 |
55 | #define BRIDGE_OV511PLUS 1 | 57 | #define BRIDGE_OV511PLUS 1 |
56 | #define BRIDGE_OV518 2 | 58 | #define BRIDGE_OV518 2 |
57 | #define BRIDGE_OV518PLUS 3 | 59 | #define BRIDGE_OV518PLUS 3 |
58 | #define BRIDGE_OV519 4 | 60 | #define BRIDGE_OV519 4 |
61 | #define BRIDGE_MASK 7 | ||
62 | |||
63 | char invert_led; | ||
64 | #define BRIDGE_INVERT_LED 8 | ||
59 | 65 | ||
60 | /* Determined by sensor type */ | 66 | /* Determined by sensor type */ |
61 | __u8 sif; | 67 | __u8 sif; |
@@ -65,22 +71,25 @@ struct sd { | |||
65 | __u8 colors; | 71 | __u8 colors; |
66 | __u8 hflip; | 72 | __u8 hflip; |
67 | __u8 vflip; | 73 | __u8 vflip; |
74 | __u8 autobrightness; | ||
75 | __u8 freq; | ||
68 | 76 | ||
69 | __u8 stopped; /* Streaming is temporarily paused */ | 77 | __u8 stopped; /* Streaming is temporarily paused */ |
70 | 78 | ||
71 | __u8 frame_rate; /* current Framerate (OV519 only) */ | 79 | __u8 frame_rate; /* current Framerate */ |
72 | __u8 clockdiv; /* clockdiv override for OV519 only */ | 80 | __u8 clockdiv; /* clockdiv override */ |
73 | 81 | ||
74 | char sensor; /* Type of image sensor chip (SEN_*) */ | 82 | char sensor; /* Type of image sensor chip (SEN_*) */ |
75 | #define SEN_UNKNOWN 0 | 83 | #define SEN_UNKNOWN 0 |
76 | #define SEN_OV6620 1 | 84 | #define SEN_OV6620 1 |
77 | #define SEN_OV6630 2 | 85 | #define SEN_OV6630 2 |
78 | #define SEN_OV7610 3 | 86 | #define SEN_OV66308AF 3 |
79 | #define SEN_OV7620 4 | 87 | #define SEN_OV7610 4 |
80 | #define SEN_OV7640 5 | 88 | #define SEN_OV7620 5 |
81 | #define SEN_OV7670 6 | 89 | #define SEN_OV7640 6 |
82 | #define SEN_OV76BE 7 | 90 | #define SEN_OV7670 7 |
83 | #define SEN_OV8610 8 | 91 | #define SEN_OV76BE 8 |
92 | #define SEN_OV8610 9 | ||
84 | }; | 93 | }; |
85 | 94 | ||
86 | /* V4L2 controls supported by the driver */ | 95 | /* V4L2 controls supported by the driver */ |
@@ -94,11 +103,17 @@ static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val); | |||
94 | static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val); | 103 | static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val); |
95 | static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); | 104 | static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); |
96 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val); | 105 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val); |
106 | static int sd_setautobrightness(struct gspca_dev *gspca_dev, __s32 val); | ||
107 | static int sd_getautobrightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
108 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); | ||
109 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); | ||
97 | static void setbrightness(struct gspca_dev *gspca_dev); | 110 | static void setbrightness(struct gspca_dev *gspca_dev); |
98 | static void setcontrast(struct gspca_dev *gspca_dev); | 111 | static void setcontrast(struct gspca_dev *gspca_dev); |
99 | static void setcolors(struct gspca_dev *gspca_dev); | 112 | static void setcolors(struct gspca_dev *gspca_dev); |
113 | static void setautobrightness(struct sd *sd); | ||
114 | static void setfreq(struct sd *sd); | ||
100 | 115 | ||
101 | static struct ctrl sd_ctrls[] = { | 116 | static const struct ctrl sd_ctrls[] = { |
102 | { | 117 | { |
103 | { | 118 | { |
104 | .id = V4L2_CID_BRIGHTNESS, | 119 | .id = V4L2_CID_BRIGHTNESS, |
@@ -141,7 +156,7 @@ static struct ctrl sd_ctrls[] = { | |||
141 | .set = sd_setcolors, | 156 | .set = sd_setcolors, |
142 | .get = sd_getcolors, | 157 | .get = sd_getcolors, |
143 | }, | 158 | }, |
144 | /* next controls work with ov7670 only */ | 159 | /* The flip controls work with ov7670 only */ |
145 | #define HFLIP_IDX 3 | 160 | #define HFLIP_IDX 3 |
146 | { | 161 | { |
147 | { | 162 | { |
@@ -172,6 +187,51 @@ static struct ctrl sd_ctrls[] = { | |||
172 | .set = sd_setvflip, | 187 | .set = sd_setvflip, |
173 | .get = sd_getvflip, | 188 | .get = sd_getvflip, |
174 | }, | 189 | }, |
190 | #define AUTOBRIGHT_IDX 5 | ||
191 | { | ||
192 | { | ||
193 | .id = V4L2_CID_AUTOBRIGHTNESS, | ||
194 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
195 | .name = "Auto Brightness", | ||
196 | .minimum = 0, | ||
197 | .maximum = 1, | ||
198 | .step = 1, | ||
199 | #define AUTOBRIGHT_DEF 1 | ||
200 | .default_value = AUTOBRIGHT_DEF, | ||
201 | }, | ||
202 | .set = sd_setautobrightness, | ||
203 | .get = sd_getautobrightness, | ||
204 | }, | ||
205 | #define FREQ_IDX 6 | ||
206 | { | ||
207 | { | ||
208 | .id = V4L2_CID_POWER_LINE_FREQUENCY, | ||
209 | .type = V4L2_CTRL_TYPE_MENU, | ||
210 | .name = "Light frequency filter", | ||
211 | .minimum = 0, | ||
212 | .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */ | ||
213 | .step = 1, | ||
214 | #define FREQ_DEF 0 | ||
215 | .default_value = FREQ_DEF, | ||
216 | }, | ||
217 | .set = sd_setfreq, | ||
218 | .get = sd_getfreq, | ||
219 | }, | ||
220 | #define OV7670_FREQ_IDX 7 | ||
221 | { | ||
222 | { | ||
223 | .id = V4L2_CID_POWER_LINE_FREQUENCY, | ||
224 | .type = V4L2_CTRL_TYPE_MENU, | ||
225 | .name = "Light frequency filter", | ||
226 | .minimum = 0, | ||
227 | .maximum = 3, /* 0: 0, 1: 50Hz, 2:60Hz 3: Auto Hz */ | ||
228 | .step = 1, | ||
229 | #define OV7670_FREQ_DEF 3 | ||
230 | .default_value = OV7670_FREQ_DEF, | ||
231 | }, | ||
232 | .set = sd_setfreq, | ||
233 | .get = sd_getfreq, | ||
234 | }, | ||
175 | }; | 235 | }; |
176 | 236 | ||
177 | static const struct v4l2_pix_format ov519_vga_mode[] = { | 237 | static const struct v4l2_pix_format ov519_vga_mode[] = { |
@@ -187,11 +247,21 @@ static const struct v4l2_pix_format ov519_vga_mode[] = { | |||
187 | .priv = 0}, | 247 | .priv = 0}, |
188 | }; | 248 | }; |
189 | static const struct v4l2_pix_format ov519_sif_mode[] = { | 249 | static const struct v4l2_pix_format ov519_sif_mode[] = { |
250 | {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | ||
251 | .bytesperline = 160, | ||
252 | .sizeimage = 160 * 120 * 3 / 8 + 590, | ||
253 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
254 | .priv = 3}, | ||
190 | {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | 255 | {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, |
191 | .bytesperline = 176, | 256 | .bytesperline = 176, |
192 | .sizeimage = 176 * 144 * 3 / 8 + 590, | 257 | .sizeimage = 176 * 144 * 3 / 8 + 590, |
193 | .colorspace = V4L2_COLORSPACE_JPEG, | 258 | .colorspace = V4L2_COLORSPACE_JPEG, |
194 | .priv = 1}, | 259 | .priv = 1}, |
260 | {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | ||
261 | .bytesperline = 320, | ||
262 | .sizeimage = 320 * 240 * 3 / 8 + 590, | ||
263 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
264 | .priv = 2}, | ||
195 | {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | 265 | {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, |
196 | .bytesperline = 352, | 266 | .bytesperline = 352, |
197 | .sizeimage = 352 * 288 * 3 / 8 + 590, | 267 | .sizeimage = 352 * 288 * 3 / 8 + 590, |
@@ -199,42 +269,118 @@ static const struct v4l2_pix_format ov519_sif_mode[] = { | |||
199 | .priv = 0}, | 269 | .priv = 0}, |
200 | }; | 270 | }; |
201 | 271 | ||
272 | /* Note some of the sizeimage values for the ov511 / ov518 may seem | ||
273 | larger then necessary, however they need to be this big as the ov511 / | ||
274 | ov518 always fills the entire isoc frame, using 0 padding bytes when | ||
275 | it doesn't have any data. So with low framerates the amount of data | ||
276 | transfered can become quite large (libv4l will remove all the 0 padding | ||
277 | in userspace). */ | ||
202 | static const struct v4l2_pix_format ov518_vga_mode[] = { | 278 | static const struct v4l2_pix_format ov518_vga_mode[] = { |
203 | {320, 240, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, | 279 | {320, 240, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, |
204 | .bytesperline = 320, | 280 | .bytesperline = 320, |
205 | .sizeimage = 320 * 240 * 3 / 8 + 590, | 281 | .sizeimage = 320 * 240 * 3, |
206 | .colorspace = V4L2_COLORSPACE_JPEG, | 282 | .colorspace = V4L2_COLORSPACE_JPEG, |
207 | .priv = 1}, | 283 | .priv = 1}, |
208 | {640, 480, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, | 284 | {640, 480, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, |
209 | .bytesperline = 640, | 285 | .bytesperline = 640, |
210 | .sizeimage = 640 * 480 * 3 / 8 + 590, | 286 | .sizeimage = 640 * 480 * 2, |
211 | .colorspace = V4L2_COLORSPACE_JPEG, | 287 | .colorspace = V4L2_COLORSPACE_JPEG, |
212 | .priv = 0}, | 288 | .priv = 0}, |
213 | }; | 289 | }; |
214 | static const struct v4l2_pix_format ov518_sif_mode[] = { | 290 | static const struct v4l2_pix_format ov518_sif_mode[] = { |
291 | {160, 120, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, | ||
292 | .bytesperline = 160, | ||
293 | .sizeimage = 70000, | ||
294 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
295 | .priv = 3}, | ||
215 | {176, 144, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, | 296 | {176, 144, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, |
216 | .bytesperline = 176, | 297 | .bytesperline = 176, |
217 | .sizeimage = 40000, | 298 | .sizeimage = 70000, |
218 | .colorspace = V4L2_COLORSPACE_JPEG, | 299 | .colorspace = V4L2_COLORSPACE_JPEG, |
219 | .priv = 1}, | 300 | .priv = 1}, |
301 | {320, 240, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, | ||
302 | .bytesperline = 320, | ||
303 | .sizeimage = 320 * 240 * 3, | ||
304 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
305 | .priv = 2}, | ||
220 | {352, 288, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, | 306 | {352, 288, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE, |
221 | .bytesperline = 352, | 307 | .bytesperline = 352, |
222 | .sizeimage = 352 * 288 * 3 / 8 + 590, | 308 | .sizeimage = 352 * 288 * 3, |
223 | .colorspace = V4L2_COLORSPACE_JPEG, | 309 | .colorspace = V4L2_COLORSPACE_JPEG, |
224 | .priv = 0}, | 310 | .priv = 0}, |
225 | }; | 311 | }; |
226 | 312 | ||
313 | static const struct v4l2_pix_format ov511_vga_mode[] = { | ||
314 | {320, 240, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE, | ||
315 | .bytesperline = 320, | ||
316 | .sizeimage = 320 * 240 * 3, | ||
317 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
318 | .priv = 1}, | ||
319 | {640, 480, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE, | ||
320 | .bytesperline = 640, | ||
321 | .sizeimage = 640 * 480 * 2, | ||
322 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
323 | .priv = 0}, | ||
324 | }; | ||
325 | static const struct v4l2_pix_format ov511_sif_mode[] = { | ||
326 | {160, 120, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE, | ||
327 | .bytesperline = 160, | ||
328 | .sizeimage = 70000, | ||
329 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
330 | .priv = 3}, | ||
331 | {176, 144, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE, | ||
332 | .bytesperline = 176, | ||
333 | .sizeimage = 70000, | ||
334 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
335 | .priv = 1}, | ||
336 | {320, 240, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE, | ||
337 | .bytesperline = 320, | ||
338 | .sizeimage = 320 * 240 * 3, | ||
339 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
340 | .priv = 2}, | ||
341 | {352, 288, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE, | ||
342 | .bytesperline = 352, | ||
343 | .sizeimage = 352 * 288 * 3, | ||
344 | .colorspace = V4L2_COLORSPACE_JPEG, | ||
345 | .priv = 0}, | ||
346 | }; | ||
227 | 347 | ||
228 | /* Registers common to OV511 / OV518 */ | 348 | /* Registers common to OV511 / OV518 */ |
349 | #define R51x_FIFO_PSIZE 0x30 /* 2 bytes wide w/ OV518(+) */ | ||
229 | #define R51x_SYS_RESET 0x50 | 350 | #define R51x_SYS_RESET 0x50 |
351 | /* Reset type flags */ | ||
352 | #define OV511_RESET_OMNICE 0x08 | ||
230 | #define R51x_SYS_INIT 0x53 | 353 | #define R51x_SYS_INIT 0x53 |
231 | #define R51x_SYS_SNAP 0x52 | 354 | #define R51x_SYS_SNAP 0x52 |
232 | #define R51x_SYS_CUST_ID 0x5F | 355 | #define R51x_SYS_CUST_ID 0x5F |
233 | #define R51x_COMP_LUT_BEGIN 0x80 | 356 | #define R51x_COMP_LUT_BEGIN 0x80 |
234 | 357 | ||
235 | /* OV511 Camera interface register numbers */ | 358 | /* OV511 Camera interface register numbers */ |
359 | #define R511_CAM_DELAY 0x10 | ||
360 | #define R511_CAM_EDGE 0x11 | ||
361 | #define R511_CAM_PXCNT 0x12 | ||
362 | #define R511_CAM_LNCNT 0x13 | ||
363 | #define R511_CAM_PXDIV 0x14 | ||
364 | #define R511_CAM_LNDIV 0x15 | ||
365 | #define R511_CAM_UV_EN 0x16 | ||
366 | #define R511_CAM_LINE_MODE 0x17 | ||
367 | #define R511_CAM_OPTS 0x18 | ||
368 | |||
369 | #define R511_SNAP_FRAME 0x19 | ||
370 | #define R511_SNAP_PXCNT 0x1A | ||
371 | #define R511_SNAP_LNCNT 0x1B | ||
372 | #define R511_SNAP_PXDIV 0x1C | ||
373 | #define R511_SNAP_LNDIV 0x1D | ||
374 | #define R511_SNAP_UV_EN 0x1E | ||
375 | #define R511_SNAP_UV_EN 0x1E | ||
376 | #define R511_SNAP_OPTS 0x1F | ||
377 | |||
378 | #define R511_DRAM_FLOW_CTL 0x20 | ||
379 | #define R511_FIFO_OPTS 0x31 | ||
380 | #define R511_I2C_CTL 0x40 | ||
236 | #define R511_SYS_LED_CTL 0x55 /* OV511+ only */ | 381 | #define R511_SYS_LED_CTL 0x55 /* OV511+ only */ |
237 | #define OV511_RESET_NOREGS 0x3F /* All but OV511 & regs */ | 382 | #define R511_COMP_EN 0x78 |
383 | #define R511_COMP_LUT_EN 0x79 | ||
238 | 384 | ||
239 | /* OV518 Camera interface register numbers */ | 385 | /* OV518 Camera interface register numbers */ |
240 | #define R518_GPIO_OUT 0x56 /* OV518(+) only */ | 386 | #define R518_GPIO_OUT 0x56 /* OV518(+) only */ |
@@ -383,7 +529,7 @@ static const struct ov_i2c_regvals norm_6x20[] = { | |||
383 | { 0x28, 0x05 }, | 529 | { 0x28, 0x05 }, |
384 | { 0x2a, 0x04 }, /* Disable framerate adjust */ | 530 | { 0x2a, 0x04 }, /* Disable framerate adjust */ |
385 | /* { 0x2b, 0xac }, * Framerate; Set 2a[7] first */ | 531 | /* { 0x2b, 0xac }, * Framerate; Set 2a[7] first */ |
386 | { 0x2d, 0x99 }, | 532 | { 0x2d, 0x85 }, |
387 | { 0x33, 0xa0 }, /* Color Processing Parameter */ | 533 | { 0x33, 0xa0 }, /* Color Processing Parameter */ |
388 | { 0x34, 0xd2 }, /* Max A/D range */ | 534 | { 0x34, 0xd2 }, /* Max A/D range */ |
389 | { 0x38, 0x8b }, | 535 | { 0x38, 0x8b }, |
@@ -416,7 +562,7 @@ static const struct ov_i2c_regvals norm_6x30[] = { | |||
416 | { 0x07, 0x2d }, /* Sharpness */ | 562 | { 0x07, 0x2d }, /* Sharpness */ |
417 | { 0x0c, 0x20 }, | 563 | { 0x0c, 0x20 }, |
418 | { 0x0d, 0x20 }, | 564 | { 0x0d, 0x20 }, |
419 | { 0x0e, 0x20 }, | 565 | { 0x0e, 0xa0 }, /* Was 0x20, bit7 enables a 2x gain which we need */ |
420 | { 0x0f, 0x05 }, | 566 | { 0x0f, 0x05 }, |
421 | { 0x10, 0x9a }, | 567 | { 0x10, 0x9a }, |
422 | { 0x11, 0x00 }, /* Pixel clock = fastest */ | 568 | { 0x11, 0x00 }, /* Pixel clock = fastest */ |
@@ -558,7 +704,7 @@ static const struct ov_i2c_regvals norm_7620[] = { | |||
558 | { 0x23, 0x00 }, | 704 | { 0x23, 0x00 }, |
559 | { 0x26, 0xa2 }, | 705 | { 0x26, 0xa2 }, |
560 | { 0x27, 0xea }, | 706 | { 0x27, 0xea }, |
561 | { 0x28, 0x20 }, | 707 | { 0x28, 0x22 }, /* Was 0x20, bit1 enables a 2x gain which we need */ |
562 | { 0x29, 0x00 }, | 708 | { 0x29, 0x00 }, |
563 | { 0x2a, 0x10 }, | 709 | { 0x2a, 0x10 }, |
564 | { 0x2b, 0x00 }, | 710 | { 0x2b, 0x00 }, |
@@ -999,13 +1145,128 @@ static int ov518_reg_w32(struct sd *sd, __u16 index, u32 value, int n) | |||
999 | return ret; | 1145 | return ret; |
1000 | } | 1146 | } |
1001 | 1147 | ||
1148 | static int ov511_i2c_w(struct sd *sd, __u8 reg, __u8 value) | ||
1149 | { | ||
1150 | int rc, retries; | ||
1151 | |||
1152 | PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg); | ||
1153 | |||
1154 | /* Three byte write cycle */ | ||
1155 | for (retries = 6; ; ) { | ||
1156 | /* Select camera register */ | ||
1157 | rc = reg_w(sd, R51x_I2C_SADDR_3, reg); | ||
1158 | if (rc < 0) | ||
1159 | return rc; | ||
1160 | |||
1161 | /* Write "value" to I2C data port of OV511 */ | ||
1162 | rc = reg_w(sd, R51x_I2C_DATA, value); | ||
1163 | if (rc < 0) | ||
1164 | return rc; | ||
1165 | |||
1166 | /* Initiate 3-byte write cycle */ | ||
1167 | rc = reg_w(sd, R511_I2C_CTL, 0x01); | ||
1168 | if (rc < 0) | ||
1169 | return rc; | ||
1170 | |||
1171 | do | ||
1172 | rc = reg_r(sd, R511_I2C_CTL); | ||
1173 | while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */ | ||
1174 | |||
1175 | if (rc < 0) | ||
1176 | return rc; | ||
1177 | |||
1178 | if ((rc & 2) == 0) /* Ack? */ | ||
1179 | break; | ||
1180 | if (--retries < 0) { | ||
1181 | PDEBUG(D_USBO, "i2c write retries exhausted"); | ||
1182 | return -1; | ||
1183 | } | ||
1184 | } | ||
1185 | |||
1186 | return 0; | ||
1187 | } | ||
1188 | |||
1189 | static int ov511_i2c_r(struct sd *sd, __u8 reg) | ||
1190 | { | ||
1191 | int rc, value, retries; | ||
1192 | |||
1193 | /* Two byte write cycle */ | ||
1194 | for (retries = 6; ; ) { | ||
1195 | /* Select camera register */ | ||
1196 | rc = reg_w(sd, R51x_I2C_SADDR_2, reg); | ||
1197 | if (rc < 0) | ||
1198 | return rc; | ||
1199 | |||
1200 | /* Initiate 2-byte write cycle */ | ||
1201 | rc = reg_w(sd, R511_I2C_CTL, 0x03); | ||
1202 | if (rc < 0) | ||
1203 | return rc; | ||
1204 | |||
1205 | do | ||
1206 | rc = reg_r(sd, R511_I2C_CTL); | ||
1207 | while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */ | ||
1208 | |||
1209 | if (rc < 0) | ||
1210 | return rc; | ||
1211 | |||
1212 | if ((rc & 2) == 0) /* Ack? */ | ||
1213 | break; | ||
1214 | |||
1215 | /* I2C abort */ | ||
1216 | reg_w(sd, R511_I2C_CTL, 0x10); | ||
1217 | |||
1218 | if (--retries < 0) { | ||
1219 | PDEBUG(D_USBI, "i2c write retries exhausted"); | ||
1220 | return -1; | ||
1221 | } | ||
1222 | } | ||
1223 | |||
1224 | /* Two byte read cycle */ | ||
1225 | for (retries = 6; ; ) { | ||
1226 | /* Initiate 2-byte read cycle */ | ||
1227 | rc = reg_w(sd, R511_I2C_CTL, 0x05); | ||
1228 | if (rc < 0) | ||
1229 | return rc; | ||
1230 | |||
1231 | do | ||
1232 | rc = reg_r(sd, R511_I2C_CTL); | ||
1233 | while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */ | ||
1234 | |||
1235 | if (rc < 0) | ||
1236 | return rc; | ||
1237 | |||
1238 | if ((rc & 2) == 0) /* Ack? */ | ||
1239 | break; | ||
1240 | |||
1241 | /* I2C abort */ | ||
1242 | rc = reg_w(sd, R511_I2C_CTL, 0x10); | ||
1243 | if (rc < 0) | ||
1244 | return rc; | ||
1245 | |||
1246 | if (--retries < 0) { | ||
1247 | PDEBUG(D_USBI, "i2c read retries exhausted"); | ||
1248 | return -1; | ||
1249 | } | ||
1250 | } | ||
1251 | |||
1252 | value = reg_r(sd, R51x_I2C_DATA); | ||
1253 | |||
1254 | PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value); | ||
1255 | |||
1256 | /* This is needed to make i2c_w() work */ | ||
1257 | rc = reg_w(sd, R511_I2C_CTL, 0x05); | ||
1258 | if (rc < 0) | ||
1259 | return rc; | ||
1260 | |||
1261 | return value; | ||
1262 | } | ||
1002 | 1263 | ||
1003 | /* | 1264 | /* |
1004 | * The OV518 I2C I/O procedure is different, hence, this function. | 1265 | * The OV518 I2C I/O procedure is different, hence, this function. |
1005 | * This is normally only called from i2c_w(). Note that this function | 1266 | * This is normally only called from i2c_w(). Note that this function |
1006 | * always succeeds regardless of whether the sensor is present and working. | 1267 | * always succeeds regardless of whether the sensor is present and working. |
1007 | */ | 1268 | */ |
1008 | static int i2c_w(struct sd *sd, | 1269 | static int ov518_i2c_w(struct sd *sd, |
1009 | __u8 reg, | 1270 | __u8 reg, |
1010 | __u8 value) | 1271 | __u8 value) |
1011 | { | 1272 | { |
@@ -1040,7 +1301,7 @@ static int i2c_w(struct sd *sd, | |||
1040 | * This is normally only called from i2c_r(). Note that this function | 1301 | * This is normally only called from i2c_r(). Note that this function |
1041 | * always succeeds regardless of whether the sensor is present and working. | 1302 | * always succeeds regardless of whether the sensor is present and working. |
1042 | */ | 1303 | */ |
1043 | static int i2c_r(struct sd *sd, __u8 reg) | 1304 | static int ov518_i2c_r(struct sd *sd, __u8 reg) |
1044 | { | 1305 | { |
1045 | int rc, value; | 1306 | int rc, value; |
1046 | 1307 | ||
@@ -1063,6 +1324,34 @@ static int i2c_r(struct sd *sd, __u8 reg) | |||
1063 | return value; | 1324 | return value; |
1064 | } | 1325 | } |
1065 | 1326 | ||
1327 | static int i2c_w(struct sd *sd, __u8 reg, __u8 value) | ||
1328 | { | ||
1329 | switch (sd->bridge) { | ||
1330 | case BRIDGE_OV511: | ||
1331 | case BRIDGE_OV511PLUS: | ||
1332 | return ov511_i2c_w(sd, reg, value); | ||
1333 | case BRIDGE_OV518: | ||
1334 | case BRIDGE_OV518PLUS: | ||
1335 | case BRIDGE_OV519: | ||
1336 | return ov518_i2c_w(sd, reg, value); | ||
1337 | } | ||
1338 | return -1; /* Should never happen */ | ||
1339 | } | ||
1340 | |||
1341 | static int i2c_r(struct sd *sd, __u8 reg) | ||
1342 | { | ||
1343 | switch (sd->bridge) { | ||
1344 | case BRIDGE_OV511: | ||
1345 | case BRIDGE_OV511PLUS: | ||
1346 | return ov511_i2c_r(sd, reg); | ||
1347 | case BRIDGE_OV518: | ||
1348 | case BRIDGE_OV518PLUS: | ||
1349 | case BRIDGE_OV519: | ||
1350 | return ov518_i2c_r(sd, reg); | ||
1351 | } | ||
1352 | return -1; /* Should never happen */ | ||
1353 | } | ||
1354 | |||
1066 | /* Writes bits at positions specified by mask to an I2C reg. Bits that are in | 1355 | /* Writes bits at positions specified by mask to an I2C reg. Bits that are in |
1067 | * the same position as 1's in "mask" are cleared and set to "value". Bits | 1356 | * the same position as 1's in "mask" are cleared and set to "value". Bits |
1068 | * that are in the same position as 0's in "mask" are preserved, regardless | 1357 | * that are in the same position as 0's in "mask" are preserved, regardless |
@@ -1242,7 +1531,6 @@ static int ov8xx0_configure(struct sd *sd) | |||
1242 | } | 1531 | } |
1243 | 1532 | ||
1244 | /* Set sensor-specific vars */ | 1533 | /* Set sensor-specific vars */ |
1245 | /* sd->sif = 0; already done */ | ||
1246 | return 0; | 1534 | return 0; |
1247 | } | 1535 | } |
1248 | 1536 | ||
@@ -1279,15 +1567,13 @@ static int ov7xx0_configure(struct sd *sd) | |||
1279 | } | 1567 | } |
1280 | } else if ((rc & 3) == 1) { | 1568 | } else if ((rc & 3) == 1) { |
1281 | /* I don't know what's different about the 76BE yet. */ | 1569 | /* I don't know what's different about the 76BE yet. */ |
1282 | if (i2c_r(sd, 0x15) & 1) | 1570 | if (i2c_r(sd, 0x15) & 1) { |
1283 | PDEBUG(D_PROBE, "Sensor is an OV7620AE"); | 1571 | PDEBUG(D_PROBE, "Sensor is an OV7620AE"); |
1284 | else | 1572 | sd->sensor = SEN_OV7620; |
1573 | } else { | ||
1285 | PDEBUG(D_PROBE, "Sensor is an OV76BE"); | 1574 | PDEBUG(D_PROBE, "Sensor is an OV76BE"); |
1286 | 1575 | sd->sensor = SEN_OV76BE; | |
1287 | /* OV511+ will return all zero isoc data unless we | 1576 | } |
1288 | * configure the sensor as a 7620. Someone needs to | ||
1289 | * find the exact reg. setting that causes this. */ | ||
1290 | sd->sensor = SEN_OV76BE; | ||
1291 | } else if ((rc & 3) == 0) { | 1577 | } else if ((rc & 3) == 0) { |
1292 | /* try to read product id registers */ | 1578 | /* try to read product id registers */ |
1293 | high = i2c_r(sd, 0x0a); | 1579 | high = i2c_r(sd, 0x0a); |
@@ -1333,7 +1619,6 @@ static int ov7xx0_configure(struct sd *sd) | |||
1333 | } | 1619 | } |
1334 | 1620 | ||
1335 | /* Set sensor-specific vars */ | 1621 | /* Set sensor-specific vars */ |
1336 | /* sd->sif = 0; already done */ | ||
1337 | return 0; | 1622 | return 0; |
1338 | } | 1623 | } |
1339 | 1624 | ||
@@ -1362,13 +1647,14 @@ static int ov6xx0_configure(struct sd *sd) | |||
1362 | break; | 1647 | break; |
1363 | case 0x01: | 1648 | case 0x01: |
1364 | sd->sensor = SEN_OV6620; | 1649 | sd->sensor = SEN_OV6620; |
1650 | PDEBUG(D_PROBE, "Sensor is an OV6620"); | ||
1365 | break; | 1651 | break; |
1366 | case 0x02: | 1652 | case 0x02: |
1367 | sd->sensor = SEN_OV6630; | 1653 | sd->sensor = SEN_OV6630; |
1368 | PDEBUG(D_PROBE, "Sensor is an OV66308AE"); | 1654 | PDEBUG(D_PROBE, "Sensor is an OV66308AE"); |
1369 | break; | 1655 | break; |
1370 | case 0x03: | 1656 | case 0x03: |
1371 | sd->sensor = SEN_OV6630; | 1657 | sd->sensor = SEN_OV66308AF; |
1372 | PDEBUG(D_PROBE, "Sensor is an OV66308AF"); | 1658 | PDEBUG(D_PROBE, "Sensor is an OV66308AF"); |
1373 | break; | 1659 | break; |
1374 | case 0x90: | 1660 | case 0x90: |
@@ -1391,6 +1677,9 @@ static int ov6xx0_configure(struct sd *sd) | |||
1391 | /* Turns on or off the LED. Only has an effect with OV511+/OV518(+)/OV519 */ | 1677 | /* Turns on or off the LED. Only has an effect with OV511+/OV518(+)/OV519 */ |
1392 | static void ov51x_led_control(struct sd *sd, int on) | 1678 | static void ov51x_led_control(struct sd *sd, int on) |
1393 | { | 1679 | { |
1680 | if (sd->invert_led) | ||
1681 | on = !on; | ||
1682 | |||
1394 | switch (sd->bridge) { | 1683 | switch (sd->bridge) { |
1395 | /* OV511 has no LED control */ | 1684 | /* OV511 has no LED control */ |
1396 | case BRIDGE_OV511PLUS: | 1685 | case BRIDGE_OV511PLUS: |
@@ -1406,9 +1695,31 @@ static void ov51x_led_control(struct sd *sd, int on) | |||
1406 | } | 1695 | } |
1407 | } | 1696 | } |
1408 | 1697 | ||
1409 | /* OV518 quantization tables are 8x4 (instead of 8x8) */ | 1698 | static int ov51x_upload_quan_tables(struct sd *sd) |
1410 | static int ov518_upload_quan_tables(struct sd *sd) | ||
1411 | { | 1699 | { |
1700 | const unsigned char yQuanTable511[] = { | ||
1701 | 0, 1, 1, 2, 2, 3, 3, 4, | ||
1702 | 1, 1, 1, 2, 2, 3, 4, 4, | ||
1703 | 1, 1, 2, 2, 3, 4, 4, 4, | ||
1704 | 2, 2, 2, 3, 4, 4, 4, 4, | ||
1705 | 2, 2, 3, 4, 4, 5, 5, 5, | ||
1706 | 3, 3, 4, 4, 5, 5, 5, 5, | ||
1707 | 3, 4, 4, 4, 5, 5, 5, 5, | ||
1708 | 4, 4, 4, 4, 5, 5, 5, 5 | ||
1709 | }; | ||
1710 | |||
1711 | const unsigned char uvQuanTable511[] = { | ||
1712 | 0, 2, 2, 3, 4, 4, 4, 4, | ||
1713 | 2, 2, 2, 4, 4, 4, 4, 4, | ||
1714 | 2, 2, 3, 4, 4, 4, 4, 4, | ||
1715 | 3, 4, 4, 4, 4, 4, 4, 4, | ||
1716 | 4, 4, 4, 4, 4, 4, 4, 4, | ||
1717 | 4, 4, 4, 4, 4, 4, 4, 4, | ||
1718 | 4, 4, 4, 4, 4, 4, 4, 4, | ||
1719 | 4, 4, 4, 4, 4, 4, 4, 4 | ||
1720 | }; | ||
1721 | |||
1722 | /* OV518 quantization tables are 8x4 (instead of 8x8) */ | ||
1412 | const unsigned char yQuanTable518[] = { | 1723 | const unsigned char yQuanTable518[] = { |
1413 | 5, 4, 5, 6, 6, 7, 7, 7, | 1724 | 5, 4, 5, 6, 6, 7, 7, 7, |
1414 | 5, 5, 5, 5, 6, 7, 7, 7, | 1725 | 5, 5, 5, 5, 6, 7, 7, 7, |
@@ -1423,14 +1734,23 @@ static int ov518_upload_quan_tables(struct sd *sd) | |||
1423 | 7, 7, 7, 7, 7, 7, 8, 8 | 1734 | 7, 7, 7, 7, 7, 7, 8, 8 |
1424 | }; | 1735 | }; |
1425 | 1736 | ||
1426 | const unsigned char *pYTable = yQuanTable518; | 1737 | const unsigned char *pYTable, *pUVTable; |
1427 | const unsigned char *pUVTable = uvQuanTable518; | ||
1428 | unsigned char val0, val1; | 1738 | unsigned char val0, val1; |
1429 | int i, rc, reg = R51x_COMP_LUT_BEGIN; | 1739 | int i, size, rc, reg = R51x_COMP_LUT_BEGIN; |
1430 | 1740 | ||
1431 | PDEBUG(D_PROBE, "Uploading quantization tables"); | 1741 | PDEBUG(D_PROBE, "Uploading quantization tables"); |
1432 | 1742 | ||
1433 | for (i = 0; i < 16; i++) { | 1743 | if (sd->bridge == BRIDGE_OV511 || sd->bridge == BRIDGE_OV511PLUS) { |
1744 | pYTable = yQuanTable511; | ||
1745 | pUVTable = uvQuanTable511; | ||
1746 | size = 32; | ||
1747 | } else { | ||
1748 | pYTable = yQuanTable518; | ||
1749 | pUVTable = uvQuanTable518; | ||
1750 | size = 16; | ||
1751 | } | ||
1752 | |||
1753 | for (i = 0; i < size; i++) { | ||
1434 | val0 = *pYTable++; | 1754 | val0 = *pYTable++; |
1435 | val1 = *pYTable++; | 1755 | val1 = *pYTable++; |
1436 | val0 &= 0x0f; | 1756 | val0 &= 0x0f; |
@@ -1445,7 +1765,7 @@ static int ov518_upload_quan_tables(struct sd *sd) | |||
1445 | val0 &= 0x0f; | 1765 | val0 &= 0x0f; |
1446 | val1 &= 0x0f; | 1766 | val1 &= 0x0f; |
1447 | val0 |= val1 << 4; | 1767 | val0 |= val1 << 4; |
1448 | rc = reg_w(sd, reg + 16, val0); | 1768 | rc = reg_w(sd, reg + size, val0); |
1449 | if (rc < 0) | 1769 | if (rc < 0) |
1450 | return rc; | 1770 | return rc; |
1451 | 1771 | ||
@@ -1455,6 +1775,87 @@ static int ov518_upload_quan_tables(struct sd *sd) | |||
1455 | return 0; | 1775 | return 0; |
1456 | } | 1776 | } |
1457 | 1777 | ||
1778 | /* This initializes the OV511/OV511+ and the sensor */ | ||
1779 | static int ov511_configure(struct gspca_dev *gspca_dev) | ||
1780 | { | ||
1781 | struct sd *sd = (struct sd *) gspca_dev; | ||
1782 | int rc; | ||
1783 | |||
1784 | /* For 511 and 511+ */ | ||
1785 | const struct ov_regvals init_511[] = { | ||
1786 | { R51x_SYS_RESET, 0x7f }, | ||
1787 | { R51x_SYS_INIT, 0x01 }, | ||
1788 | { R51x_SYS_RESET, 0x7f }, | ||
1789 | { R51x_SYS_INIT, 0x01 }, | ||
1790 | { R51x_SYS_RESET, 0x3f }, | ||
1791 | { R51x_SYS_INIT, 0x01 }, | ||
1792 | { R51x_SYS_RESET, 0x3d }, | ||
1793 | }; | ||
1794 | |||
1795 | const struct ov_regvals norm_511[] = { | ||
1796 | { R511_DRAM_FLOW_CTL, 0x01 }, | ||
1797 | { R51x_SYS_SNAP, 0x00 }, | ||
1798 | { R51x_SYS_SNAP, 0x02 }, | ||
1799 | { R51x_SYS_SNAP, 0x00 }, | ||
1800 | { R511_FIFO_OPTS, 0x1f }, | ||
1801 | { R511_COMP_EN, 0x00 }, | ||
1802 | { R511_COMP_LUT_EN, 0x03 }, | ||
1803 | }; | ||
1804 | |||
1805 | const struct ov_regvals norm_511_p[] = { | ||
1806 | { R511_DRAM_FLOW_CTL, 0xff }, | ||
1807 | { R51x_SYS_SNAP, 0x00 }, | ||
1808 | { R51x_SYS_SNAP, 0x02 }, | ||
1809 | { R51x_SYS_SNAP, 0x00 }, | ||
1810 | { R511_FIFO_OPTS, 0xff }, | ||
1811 | { R511_COMP_EN, 0x00 }, | ||
1812 | { R511_COMP_LUT_EN, 0x03 }, | ||
1813 | }; | ||
1814 | |||
1815 | const struct ov_regvals compress_511[] = { | ||
1816 | { 0x70, 0x1f }, | ||
1817 | { 0x71, 0x05 }, | ||
1818 | { 0x72, 0x06 }, | ||
1819 | { 0x73, 0x06 }, | ||
1820 | { 0x74, 0x14 }, | ||
1821 | { 0x75, 0x03 }, | ||
1822 | { 0x76, 0x04 }, | ||
1823 | { 0x77, 0x04 }, | ||
1824 | }; | ||
1825 | |||
1826 | PDEBUG(D_PROBE, "Device custom id %x", reg_r(sd, R51x_SYS_CUST_ID)); | ||
1827 | |||
1828 | rc = write_regvals(sd, init_511, ARRAY_SIZE(init_511)); | ||
1829 | if (rc < 0) | ||
1830 | return rc; | ||
1831 | |||
1832 | switch (sd->bridge) { | ||
1833 | case BRIDGE_OV511: | ||
1834 | rc = write_regvals(sd, norm_511, ARRAY_SIZE(norm_511)); | ||
1835 | if (rc < 0) | ||
1836 | return rc; | ||
1837 | break; | ||
1838 | case BRIDGE_OV511PLUS: | ||
1839 | rc = write_regvals(sd, norm_511_p, ARRAY_SIZE(norm_511_p)); | ||
1840 | if (rc < 0) | ||
1841 | return rc; | ||
1842 | break; | ||
1843 | } | ||
1844 | |||
1845 | /* Init compression */ | ||
1846 | rc = write_regvals(sd, compress_511, ARRAY_SIZE(compress_511)); | ||
1847 | if (rc < 0) | ||
1848 | return rc; | ||
1849 | |||
1850 | rc = ov51x_upload_quan_tables(sd); | ||
1851 | if (rc < 0) { | ||
1852 | PDEBUG(D_ERR, "Error uploading quantization tables"); | ||
1853 | return rc; | ||
1854 | } | ||
1855 | |||
1856 | return 0; | ||
1857 | } | ||
1858 | |||
1458 | /* This initializes the OV518/OV518+ and the sensor */ | 1859 | /* This initializes the OV518/OV518+ and the sensor */ |
1459 | static int ov518_configure(struct gspca_dev *gspca_dev) | 1860 | static int ov518_configure(struct gspca_dev *gspca_dev) |
1460 | { | 1861 | { |
@@ -1462,7 +1863,7 @@ static int ov518_configure(struct gspca_dev *gspca_dev) | |||
1462 | int rc; | 1863 | int rc; |
1463 | 1864 | ||
1464 | /* For 518 and 518+ */ | 1865 | /* For 518 and 518+ */ |
1465 | static struct ov_regvals init_518[] = { | 1866 | const struct ov_regvals init_518[] = { |
1466 | { R51x_SYS_RESET, 0x40 }, | 1867 | { R51x_SYS_RESET, 0x40 }, |
1467 | { R51x_SYS_INIT, 0xe1 }, | 1868 | { R51x_SYS_INIT, 0xe1 }, |
1468 | { R51x_SYS_RESET, 0x3e }, | 1869 | { R51x_SYS_RESET, 0x3e }, |
@@ -1473,7 +1874,7 @@ static int ov518_configure(struct gspca_dev *gspca_dev) | |||
1473 | { 0x5d, 0x03 }, | 1874 | { 0x5d, 0x03 }, |
1474 | }; | 1875 | }; |
1475 | 1876 | ||
1476 | static struct ov_regvals norm_518[] = { | 1877 | const struct ov_regvals norm_518[] = { |
1477 | { R51x_SYS_SNAP, 0x02 }, /* Reset */ | 1878 | { R51x_SYS_SNAP, 0x02 }, /* Reset */ |
1478 | { R51x_SYS_SNAP, 0x01 }, /* Enable */ | 1879 | { R51x_SYS_SNAP, 0x01 }, /* Enable */ |
1479 | { 0x31, 0x0f }, | 1880 | { 0x31, 0x0f }, |
@@ -1486,7 +1887,7 @@ static int ov518_configure(struct gspca_dev *gspca_dev) | |||
1486 | { 0x2f, 0x80 }, | 1887 | { 0x2f, 0x80 }, |
1487 | }; | 1888 | }; |
1488 | 1889 | ||
1489 | static struct ov_regvals norm_518_p[] = { | 1890 | const struct ov_regvals norm_518_p[] = { |
1490 | { R51x_SYS_SNAP, 0x02 }, /* Reset */ | 1891 | { R51x_SYS_SNAP, 0x02 }, /* Reset */ |
1491 | { R51x_SYS_SNAP, 0x01 }, /* Enable */ | 1892 | { R51x_SYS_SNAP, 0x01 }, /* Enable */ |
1492 | { 0x31, 0x0f }, | 1893 | { 0x31, 0x0f }, |
@@ -1531,7 +1932,7 @@ static int ov518_configure(struct gspca_dev *gspca_dev) | |||
1531 | break; | 1932 | break; |
1532 | } | 1933 | } |
1533 | 1934 | ||
1534 | rc = ov518_upload_quan_tables(sd); | 1935 | rc = ov51x_upload_quan_tables(sd); |
1535 | if (rc < 0) { | 1936 | if (rc < 0) { |
1536 | PDEBUG(D_ERR, "Error uploading quantization tables"); | 1937 | PDEBUG(D_ERR, "Error uploading quantization tables"); |
1537 | return rc; | 1938 | return rc; |
@@ -1573,9 +1974,14 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
1573 | struct cam *cam; | 1974 | struct cam *cam; |
1574 | int ret = 0; | 1975 | int ret = 0; |
1575 | 1976 | ||
1576 | sd->bridge = id->driver_info; | 1977 | sd->bridge = id->driver_info & BRIDGE_MASK; |
1978 | sd->invert_led = id->driver_info & BRIDGE_INVERT_LED; | ||
1577 | 1979 | ||
1578 | switch (sd->bridge) { | 1980 | switch (sd->bridge) { |
1981 | case BRIDGE_OV511: | ||
1982 | case BRIDGE_OV511PLUS: | ||
1983 | ret = ov511_configure(gspca_dev); | ||
1984 | break; | ||
1579 | case BRIDGE_OV518: | 1985 | case BRIDGE_OV518: |
1580 | case BRIDGE_OV518PLUS: | 1986 | case BRIDGE_OV518PLUS: |
1581 | ret = ov518_configure(gspca_dev); | 1987 | ret = ov518_configure(gspca_dev); |
@@ -1634,6 +2040,16 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
1634 | 2040 | ||
1635 | cam = &gspca_dev->cam; | 2041 | cam = &gspca_dev->cam; |
1636 | switch (sd->bridge) { | 2042 | switch (sd->bridge) { |
2043 | case BRIDGE_OV511: | ||
2044 | case BRIDGE_OV511PLUS: | ||
2045 | if (!sd->sif) { | ||
2046 | cam->cam_mode = ov511_vga_mode; | ||
2047 | cam->nmodes = ARRAY_SIZE(ov511_vga_mode); | ||
2048 | } else { | ||
2049 | cam->cam_mode = ov511_sif_mode; | ||
2050 | cam->nmodes = ARRAY_SIZE(ov511_sif_mode); | ||
2051 | } | ||
2052 | break; | ||
1637 | case BRIDGE_OV518: | 2053 | case BRIDGE_OV518: |
1638 | case BRIDGE_OV518PLUS: | 2054 | case BRIDGE_OV518PLUS: |
1639 | if (!sd->sif) { | 2055 | if (!sd->sif) { |
@@ -1655,13 +2071,28 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
1655 | break; | 2071 | break; |
1656 | } | 2072 | } |
1657 | sd->brightness = BRIGHTNESS_DEF; | 2073 | sd->brightness = BRIGHTNESS_DEF; |
1658 | sd->contrast = CONTRAST_DEF; | 2074 | if (sd->sensor == SEN_OV6630 || sd->sensor == SEN_OV66308AF) |
2075 | sd->contrast = 200; /* The default is too low for the ov6630 */ | ||
2076 | else | ||
2077 | sd->contrast = CONTRAST_DEF; | ||
1659 | sd->colors = COLOR_DEF; | 2078 | sd->colors = COLOR_DEF; |
1660 | sd->hflip = HFLIP_DEF; | 2079 | sd->hflip = HFLIP_DEF; |
1661 | sd->vflip = VFLIP_DEF; | 2080 | sd->vflip = VFLIP_DEF; |
1662 | if (sd->sensor != SEN_OV7670) | 2081 | sd->autobrightness = AUTOBRIGHT_DEF; |
1663 | gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | 2082 | if (sd->sensor == SEN_OV7670) { |
1664 | | (1 << VFLIP_IDX); | 2083 | sd->freq = OV7670_FREQ_DEF; |
2084 | gspca_dev->ctrl_dis = 1 << FREQ_IDX; | ||
2085 | } else { | ||
2086 | sd->freq = FREQ_DEF; | ||
2087 | gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | | ||
2088 | (1 << OV7670_FREQ_IDX); | ||
2089 | } | ||
2090 | if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7670) | ||
2091 | gspca_dev->ctrl_dis |= 1 << AUTOBRIGHT_IDX; | ||
2092 | /* OV8610 Frequency filter control should work but needs testing */ | ||
2093 | if (sd->sensor == SEN_OV8610) | ||
2094 | gspca_dev->ctrl_dis |= 1 << FREQ_IDX; | ||
2095 | |||
1665 | return 0; | 2096 | return 0; |
1666 | error: | 2097 | error: |
1667 | PDEBUG(D_ERR, "OV519 Config failed"); | 2098 | PDEBUG(D_ERR, "OV519 Config failed"); |
@@ -1680,6 +2111,7 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
1680 | return -EIO; | 2111 | return -EIO; |
1681 | break; | 2112 | break; |
1682 | case SEN_OV6630: | 2113 | case SEN_OV6630: |
2114 | case SEN_OV66308AF: | ||
1683 | if (write_i2c_regvals(sd, norm_6x30, ARRAY_SIZE(norm_6x30))) | 2115 | if (write_i2c_regvals(sd, norm_6x30, ARRAY_SIZE(norm_6x30))) |
1684 | return -EIO; | 2116 | return -EIO; |
1685 | break; | 2117 | break; |
@@ -1688,6 +2120,8 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
1688 | /* case SEN_OV76BE: */ | 2120 | /* case SEN_OV76BE: */ |
1689 | if (write_i2c_regvals(sd, norm_7610, ARRAY_SIZE(norm_7610))) | 2121 | if (write_i2c_regvals(sd, norm_7610, ARRAY_SIZE(norm_7610))) |
1690 | return -EIO; | 2122 | return -EIO; |
2123 | if (i2c_w_mask(sd, 0x0e, 0x00, 0x40)) | ||
2124 | return -EIO; | ||
1691 | break; | 2125 | break; |
1692 | case SEN_OV7620: | 2126 | case SEN_OV7620: |
1693 | if (write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620))) | 2127 | if (write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620))) |
@@ -1709,6 +2143,126 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
1709 | return 0; | 2143 | return 0; |
1710 | } | 2144 | } |
1711 | 2145 | ||
2146 | /* Set up the OV511/OV511+ with the given image parameters. | ||
2147 | * | ||
2148 | * Do not put any sensor-specific code in here (including I2C I/O functions) | ||
2149 | */ | ||
2150 | static int ov511_mode_init_regs(struct sd *sd) | ||
2151 | { | ||
2152 | int hsegs, vsegs, packet_size, fps, needed; | ||
2153 | int interlaced = 0; | ||
2154 | struct usb_host_interface *alt; | ||
2155 | struct usb_interface *intf; | ||
2156 | |||
2157 | intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface); | ||
2158 | alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt); | ||
2159 | if (!alt) { | ||
2160 | PDEBUG(D_ERR, "Couldn't get altsetting"); | ||
2161 | return -EIO; | ||
2162 | } | ||
2163 | |||
2164 | packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); | ||
2165 | reg_w(sd, R51x_FIFO_PSIZE, packet_size >> 5); | ||
2166 | |||
2167 | reg_w(sd, R511_CAM_UV_EN, 0x01); | ||
2168 | reg_w(sd, R511_SNAP_UV_EN, 0x01); | ||
2169 | reg_w(sd, R511_SNAP_OPTS, 0x03); | ||
2170 | |||
2171 | /* Here I'm assuming that snapshot size == image size. | ||
2172 | * I hope that's always true. --claudio | ||
2173 | */ | ||
2174 | hsegs = (sd->gspca_dev.width >> 3) - 1; | ||
2175 | vsegs = (sd->gspca_dev.height >> 3) - 1; | ||
2176 | |||
2177 | reg_w(sd, R511_CAM_PXCNT, hsegs); | ||
2178 | reg_w(sd, R511_CAM_LNCNT, vsegs); | ||
2179 | reg_w(sd, R511_CAM_PXDIV, 0x00); | ||
2180 | reg_w(sd, R511_CAM_LNDIV, 0x00); | ||
2181 | |||
2182 | /* YUV420, low pass filter on */ | ||
2183 | reg_w(sd, R511_CAM_OPTS, 0x03); | ||
2184 | |||
2185 | /* Snapshot additions */ | ||
2186 | reg_w(sd, R511_SNAP_PXCNT, hsegs); | ||
2187 | reg_w(sd, R511_SNAP_LNCNT, vsegs); | ||
2188 | reg_w(sd, R511_SNAP_PXDIV, 0x00); | ||
2189 | reg_w(sd, R511_SNAP_LNDIV, 0x00); | ||
2190 | |||
2191 | /******** Set the framerate ********/ | ||
2192 | if (frame_rate > 0) | ||
2193 | sd->frame_rate = frame_rate; | ||
2194 | |||
2195 | switch (sd->sensor) { | ||
2196 | case SEN_OV6620: | ||
2197 | /* No framerate control, doesn't like higher rates yet */ | ||
2198 | sd->clockdiv = 3; | ||
2199 | break; | ||
2200 | |||
2201 | /* Note once the FIXME's in mode_init_ov_sensor_regs() are fixed | ||
2202 | for more sensors we need to do this for them too */ | ||
2203 | case SEN_OV7620: | ||
2204 | case SEN_OV7640: | ||
2205 | case SEN_OV76BE: | ||
2206 | if (sd->gspca_dev.width == 320) | ||
2207 | interlaced = 1; | ||
2208 | /* Fall through */ | ||
2209 | case SEN_OV6630: | ||
2210 | case SEN_OV7610: | ||
2211 | case SEN_OV7670: | ||
2212 | switch (sd->frame_rate) { | ||
2213 | case 30: | ||
2214 | case 25: | ||
2215 | /* Not enough bandwidth to do 640x480 @ 30 fps */ | ||
2216 | if (sd->gspca_dev.width != 640) { | ||
2217 | sd->clockdiv = 0; | ||
2218 | break; | ||
2219 | } | ||
2220 | /* Fall through for 640x480 case */ | ||
2221 | default: | ||
2222 | /* case 20: */ | ||
2223 | /* case 15: */ | ||
2224 | sd->clockdiv = 1; | ||
2225 | break; | ||
2226 | case 10: | ||
2227 | sd->clockdiv = 2; | ||
2228 | break; | ||
2229 | case 5: | ||
2230 | sd->clockdiv = 5; | ||
2231 | break; | ||
2232 | } | ||
2233 | if (interlaced) { | ||
2234 | sd->clockdiv = (sd->clockdiv + 1) * 2 - 1; | ||
2235 | /* Higher then 10 does not work */ | ||
2236 | if (sd->clockdiv > 10) | ||
2237 | sd->clockdiv = 10; | ||
2238 | } | ||
2239 | break; | ||
2240 | |||
2241 | case SEN_OV8610: | ||
2242 | /* No framerate control ?? */ | ||
2243 | sd->clockdiv = 0; | ||
2244 | break; | ||
2245 | } | ||
2246 | |||
2247 | /* Check if we have enough bandwidth to disable compression */ | ||
2248 | fps = (interlaced ? 60 : 30) / (sd->clockdiv + 1) + 1; | ||
2249 | needed = fps * sd->gspca_dev.width * sd->gspca_dev.height * 3 / 2; | ||
2250 | /* 1400 is a conservative estimate of the max nr of isoc packets/sec */ | ||
2251 | if (needed > 1400 * packet_size) { | ||
2252 | /* Enable Y and UV quantization and compression */ | ||
2253 | reg_w(sd, R511_COMP_EN, 0x07); | ||
2254 | reg_w(sd, R511_COMP_LUT_EN, 0x03); | ||
2255 | } else { | ||
2256 | reg_w(sd, R511_COMP_EN, 0x06); | ||
2257 | reg_w(sd, R511_COMP_LUT_EN, 0x00); | ||
2258 | } | ||
2259 | |||
2260 | reg_w(sd, R51x_SYS_RESET, OV511_RESET_OMNICE); | ||
2261 | reg_w(sd, R51x_SYS_RESET, 0); | ||
2262 | |||
2263 | return 0; | ||
2264 | } | ||
2265 | |||
1712 | /* Sets up the OV518/OV518+ with the given image parameters | 2266 | /* Sets up the OV518/OV518+ with the given image parameters |
1713 | * | 2267 | * |
1714 | * OV518 needs a completely different approach, until we can figure out what | 2268 | * OV518 needs a completely different approach, until we can figure out what |
@@ -1718,7 +2272,19 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
1718 | */ | 2272 | */ |
1719 | static int ov518_mode_init_regs(struct sd *sd) | 2273 | static int ov518_mode_init_regs(struct sd *sd) |
1720 | { | 2274 | { |
1721 | int hsegs, vsegs; | 2275 | int hsegs, vsegs, packet_size; |
2276 | struct usb_host_interface *alt; | ||
2277 | struct usb_interface *intf; | ||
2278 | |||
2279 | intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface); | ||
2280 | alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt); | ||
2281 | if (!alt) { | ||
2282 | PDEBUG(D_ERR, "Couldn't get altsetting"); | ||
2283 | return -EIO; | ||
2284 | } | ||
2285 | |||
2286 | packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); | ||
2287 | ov518_reg_w32(sd, R51x_FIFO_PSIZE, packet_size & ~7, 2); | ||
1722 | 2288 | ||
1723 | /******** Set the mode ********/ | 2289 | /******** Set the mode ********/ |
1724 | 2290 | ||
@@ -1755,20 +2321,30 @@ static int ov518_mode_init_regs(struct sd *sd) | |||
1755 | /* Windows driver does this here; who knows why */ | 2321 | /* Windows driver does this here; who knows why */ |
1756 | reg_w(sd, 0x2f, 0x80); | 2322 | reg_w(sd, 0x2f, 0x80); |
1757 | 2323 | ||
1758 | /******** Set the framerate (to 30 FPS) ********/ | 2324 | /******** Set the framerate ********/ |
1759 | if (sd->bridge == BRIDGE_OV518PLUS) | 2325 | sd->clockdiv = 1; |
1760 | sd->clockdiv = 1; | ||
1761 | else | ||
1762 | sd->clockdiv = 0; | ||
1763 | 2326 | ||
1764 | /* Mode independent, but framerate dependent, regs */ | 2327 | /* Mode independent, but framerate dependent, regs */ |
1765 | reg_w(sd, 0x51, 0x04); /* Clock divider; lower==faster */ | 2328 | /* 0x51: Clock divider; Only works on some cams which use 2 crystals */ |
2329 | reg_w(sd, 0x51, 0x04); | ||
1766 | reg_w(sd, 0x22, 0x18); | 2330 | reg_w(sd, 0x22, 0x18); |
1767 | reg_w(sd, 0x23, 0xff); | 2331 | reg_w(sd, 0x23, 0xff); |
1768 | 2332 | ||
1769 | if (sd->bridge == BRIDGE_OV518PLUS) | 2333 | if (sd->bridge == BRIDGE_OV518PLUS) { |
1770 | reg_w(sd, 0x21, 0x19); | 2334 | switch (sd->sensor) { |
1771 | else | 2335 | case SEN_OV7620: |
2336 | if (sd->gspca_dev.width == 320) { | ||
2337 | reg_w(sd, 0x20, 0x00); | ||
2338 | reg_w(sd, 0x21, 0x19); | ||
2339 | } else { | ||
2340 | reg_w(sd, 0x20, 0x60); | ||
2341 | reg_w(sd, 0x21, 0x1f); | ||
2342 | } | ||
2343 | break; | ||
2344 | default: | ||
2345 | reg_w(sd, 0x21, 0x19); | ||
2346 | } | ||
2347 | } else | ||
1772 | reg_w(sd, 0x71, 0x17); /* Compression-related? */ | 2348 | reg_w(sd, 0x71, 0x17); /* Compression-related? */ |
1773 | 2349 | ||
1774 | /* FIXME: Sensor-specific */ | 2350 | /* FIXME: Sensor-specific */ |
@@ -1879,7 +2455,11 @@ static int ov519_mode_init_regs(struct sd *sd) | |||
1879 | 2455 | ||
1880 | reg_w(sd, OV519_R10_H_SIZE, sd->gspca_dev.width >> 4); | 2456 | reg_w(sd, OV519_R10_H_SIZE, sd->gspca_dev.width >> 4); |
1881 | reg_w(sd, OV519_R11_V_SIZE, sd->gspca_dev.height >> 3); | 2457 | reg_w(sd, OV519_R11_V_SIZE, sd->gspca_dev.height >> 3); |
1882 | reg_w(sd, OV519_R12_X_OFFSETL, 0x00); | 2458 | if (sd->sensor == SEN_OV7670 && |
2459 | sd->gspca_dev.cam.cam_mode[sd->gspca_dev.curr_mode].priv) | ||
2460 | reg_w(sd, OV519_R12_X_OFFSETL, 0x04); | ||
2461 | else | ||
2462 | reg_w(sd, OV519_R12_X_OFFSETL, 0x00); | ||
1883 | reg_w(sd, OV519_R13_X_OFFSETH, 0x00); | 2463 | reg_w(sd, OV519_R13_X_OFFSETH, 0x00); |
1884 | reg_w(sd, OV519_R14_Y_OFFSETL, 0x00); | 2464 | reg_w(sd, OV519_R14_Y_OFFSETL, 0x00); |
1885 | reg_w(sd, OV519_R15_Y_OFFSETH, 0x00); | 2465 | reg_w(sd, OV519_R15_Y_OFFSETH, 0x00); |
@@ -1971,7 +2551,7 @@ static int mode_init_ov_sensor_regs(struct sd *sd) | |||
1971 | int qvga; | 2551 | int qvga; |
1972 | 2552 | ||
1973 | gspca_dev = &sd->gspca_dev; | 2553 | gspca_dev = &sd->gspca_dev; |
1974 | qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; | 2554 | qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 1; |
1975 | 2555 | ||
1976 | /******** Mode (VGA/QVGA) and sensor specific regs ********/ | 2556 | /******** Mode (VGA/QVGA) and sensor specific regs ********/ |
1977 | switch (sd->sensor) { | 2557 | switch (sd->sensor) { |
@@ -1983,21 +2563,16 @@ static int mode_init_ov_sensor_regs(struct sd *sd) | |||
1983 | i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); | 2563 | i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); |
1984 | break; | 2564 | break; |
1985 | case SEN_OV7620: | 2565 | case SEN_OV7620: |
1986 | /* i2c_w(sd, 0x2b, 0x00); */ | 2566 | case SEN_OV76BE: |
1987 | i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); | 2567 | i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); |
1988 | i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20); | 2568 | i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20); |
1989 | i2c_w(sd, 0x24, qvga ? 0x20 : 0x3a); | 2569 | i2c_w(sd, 0x24, qvga ? 0x20 : 0x3a); |
1990 | i2c_w(sd, 0x25, qvga ? 0x30 : 0x60); | 2570 | i2c_w(sd, 0x25, qvga ? 0x30 : 0x60); |
1991 | i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40); | 2571 | i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40); |
1992 | i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0); | 2572 | i2c_w_mask(sd, 0x67, qvga ? 0xb0 : 0x90, 0xf0); |
1993 | i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20); | 2573 | i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20); |
1994 | break; | 2574 | break; |
1995 | case SEN_OV76BE: | ||
1996 | /* i2c_w(sd, 0x2b, 0x00); */ | ||
1997 | i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); | ||
1998 | break; | ||
1999 | case SEN_OV7640: | 2575 | case SEN_OV7640: |
2000 | /* i2c_w(sd, 0x2b, 0x00); */ | ||
2001 | i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); | 2576 | i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); |
2002 | i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20); | 2577 | i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20); |
2003 | /* i2c_w(sd, 0x24, qvga ? 0x20 : 0x3a); */ | 2578 | /* i2c_w(sd, 0x24, qvga ? 0x20 : 0x3a); */ |
@@ -2016,6 +2591,7 @@ static int mode_init_ov_sensor_regs(struct sd *sd) | |||
2016 | break; | 2591 | break; |
2017 | case SEN_OV6620: | 2592 | case SEN_OV6620: |
2018 | case SEN_OV6630: | 2593 | case SEN_OV6630: |
2594 | case SEN_OV66308AF: | ||
2019 | i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); | 2595 | i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); |
2020 | break; | 2596 | break; |
2021 | default: | 2597 | default: |
@@ -2023,10 +2599,6 @@ static int mode_init_ov_sensor_regs(struct sd *sd) | |||
2023 | } | 2599 | } |
2024 | 2600 | ||
2025 | /******** Palette-specific regs ********/ | 2601 | /******** Palette-specific regs ********/ |
2026 | if (sd->sensor == SEN_OV7610 || sd->sensor == SEN_OV76BE) { | ||
2027 | /* not valid on the OV6620/OV7620/6630? */ | ||
2028 | i2c_w_mask(sd, 0x0e, 0x00, 0x40); | ||
2029 | } | ||
2030 | 2602 | ||
2031 | /* The OV518 needs special treatment. Although both the OV518 | 2603 | /* The OV518 needs special treatment. Although both the OV518 |
2032 | * and the OV6630 support a 16-bit video bus, only the 8 bit Y | 2604 | * and the OV6630 support a 16-bit video bus, only the 8 bit Y |
@@ -2036,25 +2608,12 @@ static int mode_init_ov_sensor_regs(struct sd *sd) | |||
2036 | 2608 | ||
2037 | /* OV7640 is 8-bit only */ | 2609 | /* OV7640 is 8-bit only */ |
2038 | 2610 | ||
2039 | if (sd->sensor != SEN_OV6630 && sd->sensor != SEN_OV7640) | 2611 | if (sd->sensor != SEN_OV6630 && sd->sensor != SEN_OV66308AF && |
2612 | sd->sensor != SEN_OV7640) | ||
2040 | i2c_w_mask(sd, 0x13, 0x00, 0x20); | 2613 | i2c_w_mask(sd, 0x13, 0x00, 0x20); |
2041 | 2614 | ||
2042 | /******** Clock programming ********/ | 2615 | /******** Clock programming ********/ |
2043 | /* The OV6620 needs special handling. This prevents the | 2616 | i2c_w(sd, 0x11, sd->clockdiv); |
2044 | * severe banding that normally occurs */ | ||
2045 | if (sd->sensor == SEN_OV6620) { | ||
2046 | |||
2047 | /* Clock down */ | ||
2048 | i2c_w(sd, 0x2a, 0x04); | ||
2049 | i2c_w(sd, 0x11, sd->clockdiv); | ||
2050 | i2c_w(sd, 0x2a, 0x84); | ||
2051 | /* This next setting is critical. It seems to improve | ||
2052 | * the gain or the contrast. The "reserved" bits seem | ||
2053 | * to have some effect in this case. */ | ||
2054 | i2c_w(sd, 0x2d, 0x85); | ||
2055 | } else { | ||
2056 | i2c_w(sd, 0x11, sd->clockdiv); | ||
2057 | } | ||
2058 | 2617 | ||
2059 | /******** Special Features ********/ | 2618 | /******** Special Features ********/ |
2060 | /* no evidence this is possible with OV7670, either */ | 2619 | /* no evidence this is possible with OV7670, either */ |
@@ -2098,13 +2657,14 @@ static void sethvflip(struct sd *sd) | |||
2098 | static int set_ov_sensor_window(struct sd *sd) | 2657 | static int set_ov_sensor_window(struct sd *sd) |
2099 | { | 2658 | { |
2100 | struct gspca_dev *gspca_dev; | 2659 | struct gspca_dev *gspca_dev; |
2101 | int qvga; | 2660 | int qvga, crop; |
2102 | int hwsbase, hwebase, vwsbase, vwebase, hwscale, vwscale; | 2661 | int hwsbase, hwebase, vwsbase, vwebase, hwscale, vwscale; |
2103 | int ret, hstart, hstop, vstop, vstart; | 2662 | int ret, hstart, hstop, vstop, vstart; |
2104 | __u8 v; | 2663 | __u8 v; |
2105 | 2664 | ||
2106 | gspca_dev = &sd->gspca_dev; | 2665 | gspca_dev = &sd->gspca_dev; |
2107 | qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; | 2666 | qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 1; |
2667 | crop = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 2; | ||
2108 | 2668 | ||
2109 | /* The different sensor ICs handle setting up of window differently. | 2669 | /* The different sensor ICs handle setting up of window differently. |
2110 | * IF YOU SET IT WRONG, YOU WILL GET ALL ZERO ISOC DATA FROM OV51x!! */ | 2670 | * IF YOU SET IT WRONG, YOU WILL GET ALL ZERO ISOC DATA FROM OV51x!! */ |
@@ -2123,14 +2683,19 @@ static int set_ov_sensor_window(struct sd *sd) | |||
2123 | break; | 2683 | break; |
2124 | case SEN_OV6620: | 2684 | case SEN_OV6620: |
2125 | case SEN_OV6630: | 2685 | case SEN_OV6630: |
2686 | case SEN_OV66308AF: | ||
2126 | hwsbase = 0x38; | 2687 | hwsbase = 0x38; |
2127 | hwebase = 0x3a; | 2688 | hwebase = 0x3a; |
2128 | vwsbase = 0x05; | 2689 | vwsbase = 0x05; |
2129 | vwebase = 0x06; | 2690 | vwebase = 0x06; |
2130 | if (qvga) { | 2691 | if (sd->sensor == SEN_OV66308AF && qvga) |
2131 | /* HDG: this fixes U and V getting swapped */ | 2692 | /* HDG: this fixes U and V getting swapped */ |
2132 | hwsbase--; | 2693 | hwsbase++; |
2133 | vwsbase--; | 2694 | if (crop) { |
2695 | hwsbase += 8; | ||
2696 | hwebase += 8; | ||
2697 | vwsbase += 11; | ||
2698 | vwebase += 11; | ||
2134 | } | 2699 | } |
2135 | break; | 2700 | break; |
2136 | case SEN_OV7620: | 2701 | case SEN_OV7620: |
@@ -2155,6 +2720,7 @@ static int set_ov_sensor_window(struct sd *sd) | |||
2155 | switch (sd->sensor) { | 2720 | switch (sd->sensor) { |
2156 | case SEN_OV6620: | 2721 | case SEN_OV6620: |
2157 | case SEN_OV6630: | 2722 | case SEN_OV6630: |
2723 | case SEN_OV66308AF: | ||
2158 | if (qvga) { /* QCIF */ | 2724 | if (qvga) { /* QCIF */ |
2159 | hwscale = 0; | 2725 | hwscale = 0; |
2160 | vwscale = 0; | 2726 | vwscale = 0; |
@@ -2207,7 +2773,7 @@ static int set_ov_sensor_window(struct sd *sd) | |||
2207 | if (qvga) { /* QVGA from ov7670.c by | 2773 | if (qvga) { /* QVGA from ov7670.c by |
2208 | * Jonathan Corbet */ | 2774 | * Jonathan Corbet */ |
2209 | hstart = 164; | 2775 | hstart = 164; |
2210 | hstop = 20; | 2776 | hstop = 28; |
2211 | vstart = 14; | 2777 | vstart = 14; |
2212 | vstop = 494; | 2778 | vstop = 494; |
2213 | } else { /* VGA */ | 2779 | } else { /* VGA */ |
@@ -2233,7 +2799,6 @@ static int set_ov_sensor_window(struct sd *sd) | |||
2233 | msleep(10); /* need to sleep between read and write to | 2799 | msleep(10); /* need to sleep between read and write to |
2234 | * same reg! */ | 2800 | * same reg! */ |
2235 | i2c_w(sd, OV7670_REG_VREF, v); | 2801 | i2c_w(sd, OV7670_REG_VREF, v); |
2236 | sethvflip(sd); | ||
2237 | } else { | 2802 | } else { |
2238 | i2c_w(sd, 0x17, hwsbase); | 2803 | i2c_w(sd, 0x17, hwsbase); |
2239 | i2c_w(sd, 0x18, hwebase + (sd->gspca_dev.width >> hwscale)); | 2804 | i2c_w(sd, 0x18, hwebase + (sd->gspca_dev.width >> hwscale)); |
@@ -2250,6 +2815,10 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
2250 | int ret = 0; | 2815 | int ret = 0; |
2251 | 2816 | ||
2252 | switch (sd->bridge) { | 2817 | switch (sd->bridge) { |
2818 | case BRIDGE_OV511: | ||
2819 | case BRIDGE_OV511PLUS: | ||
2820 | ret = ov511_mode_init_regs(sd); | ||
2821 | break; | ||
2253 | case BRIDGE_OV518: | 2822 | case BRIDGE_OV518: |
2254 | case BRIDGE_OV518PLUS: | 2823 | case BRIDGE_OV518PLUS: |
2255 | ret = ov518_mode_init_regs(sd); | 2824 | ret = ov518_mode_init_regs(sd); |
@@ -2268,6 +2837,9 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
2268 | setcontrast(gspca_dev); | 2837 | setcontrast(gspca_dev); |
2269 | setbrightness(gspca_dev); | 2838 | setbrightness(gspca_dev); |
2270 | setcolors(gspca_dev); | 2839 | setcolors(gspca_dev); |
2840 | sethvflip(sd); | ||
2841 | setautobrightness(sd); | ||
2842 | setfreq(sd); | ||
2271 | 2843 | ||
2272 | ret = ov51x_restart(sd); | 2844 | ret = ov51x_restart(sd); |
2273 | if (ret < 0) | 2845 | if (ret < 0) |
@@ -2287,23 +2859,88 @@ static void sd_stopN(struct gspca_dev *gspca_dev) | |||
2287 | ov51x_led_control(sd, 0); | 2859 | ov51x_led_control(sd, 0); |
2288 | } | 2860 | } |
2289 | 2861 | ||
2290 | static void ov518_pkt_scan(struct gspca_dev *gspca_dev, | 2862 | static void ov511_pkt_scan(struct gspca_dev *gspca_dev, |
2291 | struct gspca_frame *frame, /* target */ | 2863 | struct gspca_frame *frame, /* target */ |
2292 | __u8 *data, /* isoc packet */ | 2864 | __u8 *in, /* isoc packet */ |
2293 | int len) /* iso packet length */ | 2865 | int len) /* iso packet length */ |
2294 | { | 2866 | { |
2295 | PDEBUG(D_STREAM, "ov518_pkt_scan: %d bytes", len); | 2867 | struct sd *sd = (struct sd *) gspca_dev; |
2296 | 2868 | ||
2297 | if (len & 7) { | 2869 | /* SOF/EOF packets have 1st to 8th bytes zeroed and the 9th |
2298 | len--; | 2870 | * byte non-zero. The EOF packet has image width/height in the |
2299 | PDEBUG(D_STREAM, "packet number: %d\n", (int)data[len]); | 2871 | * 10th and 11th bytes. The 9th byte is given as follows: |
2872 | * | ||
2873 | * bit 7: EOF | ||
2874 | * 6: compression enabled | ||
2875 | * 5: 422/420/400 modes | ||
2876 | * 4: 422/420/400 modes | ||
2877 | * 3: 1 | ||
2878 | * 2: snapshot button on | ||
2879 | * 1: snapshot frame | ||
2880 | * 0: even/odd field | ||
2881 | */ | ||
2882 | if (!(in[0] | in[1] | in[2] | in[3] | in[4] | in[5] | in[6] | in[7]) && | ||
2883 | (in[8] & 0x08)) { | ||
2884 | if (in[8] & 0x80) { | ||
2885 | /* Frame end */ | ||
2886 | if ((in[9] + 1) * 8 != gspca_dev->width || | ||
2887 | (in[10] + 1) * 8 != gspca_dev->height) { | ||
2888 | PDEBUG(D_ERR, "Invalid frame size, got: %dx%d," | ||
2889 | " requested: %dx%d\n", | ||
2890 | (in[9] + 1) * 8, (in[10] + 1) * 8, | ||
2891 | gspca_dev->width, gspca_dev->height); | ||
2892 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
2893 | return; | ||
2894 | } | ||
2895 | /* Add 11 byte footer to frame, might be usefull */ | ||
2896 | gspca_frame_add(gspca_dev, LAST_PACKET, frame, in, 11); | ||
2897 | return; | ||
2898 | } else { | ||
2899 | /* Frame start */ | ||
2900 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, in, 0); | ||
2901 | sd->packet_nr = 0; | ||
2902 | } | ||
2300 | } | 2903 | } |
2301 | 2904 | ||
2905 | /* Ignore the packet number */ | ||
2906 | len--; | ||
2907 | |||
2908 | /* intermediate packet */ | ||
2909 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, in, len); | ||
2910 | } | ||
2911 | |||
2912 | static void ov518_pkt_scan(struct gspca_dev *gspca_dev, | ||
2913 | struct gspca_frame *frame, /* target */ | ||
2914 | __u8 *data, /* isoc packet */ | ||
2915 | int len) /* iso packet length */ | ||
2916 | { | ||
2917 | struct sd *sd = (struct sd *) gspca_dev; | ||
2918 | |||
2302 | /* A false positive here is likely, until OVT gives me | 2919 | /* A false positive here is likely, until OVT gives me |
2303 | * the definitive SOF/EOF format */ | 2920 | * the definitive SOF/EOF format */ |
2304 | if ((!(data[0] | data[1] | data[2] | data[3] | data[5])) && data[6]) { | 2921 | if ((!(data[0] | data[1] | data[2] | data[3] | data[5])) && data[6]) { |
2305 | gspca_frame_add(gspca_dev, LAST_PACKET, frame, data, 0); | 2922 | gspca_frame_add(gspca_dev, LAST_PACKET, frame, data, 0); |
2306 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, 0); | 2923 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, 0); |
2924 | sd->packet_nr = 0; | ||
2925 | } | ||
2926 | |||
2927 | if (gspca_dev->last_packet_type == DISCARD_PACKET) | ||
2928 | return; | ||
2929 | |||
2930 | /* Does this device use packet numbers ? */ | ||
2931 | if (len & 7) { | ||
2932 | len--; | ||
2933 | if (sd->packet_nr == data[len]) | ||
2934 | sd->packet_nr++; | ||
2935 | /* The last few packets of the frame (which are all 0's | ||
2936 | except that they may contain part of the footer), are | ||
2937 | numbered 0 */ | ||
2938 | else if (sd->packet_nr == 0 || data[len]) { | ||
2939 | PDEBUG(D_ERR, "Invalid packet nr: %d (expect: %d)", | ||
2940 | (int)data[len], (int)sd->packet_nr); | ||
2941 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
2942 | return; | ||
2943 | } | ||
2307 | } | 2944 | } |
2308 | 2945 | ||
2309 | /* intermediate packet */ | 2946 | /* intermediate packet */ |
@@ -2364,6 +3001,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
2364 | switch (sd->bridge) { | 3001 | switch (sd->bridge) { |
2365 | case BRIDGE_OV511: | 3002 | case BRIDGE_OV511: |
2366 | case BRIDGE_OV511PLUS: | 3003 | case BRIDGE_OV511PLUS: |
3004 | ov511_pkt_scan(gspca_dev, frame, data, len); | ||
2367 | break; | 3005 | break; |
2368 | case BRIDGE_OV518: | 3006 | case BRIDGE_OV518: |
2369 | case BRIDGE_OV518PLUS: | 3007 | case BRIDGE_OV518PLUS: |
@@ -2389,13 +3027,13 @@ static void setbrightness(struct gspca_dev *gspca_dev) | |||
2389 | case SEN_OV76BE: | 3027 | case SEN_OV76BE: |
2390 | case SEN_OV6620: | 3028 | case SEN_OV6620: |
2391 | case SEN_OV6630: | 3029 | case SEN_OV6630: |
3030 | case SEN_OV66308AF: | ||
2392 | case SEN_OV7640: | 3031 | case SEN_OV7640: |
2393 | i2c_w(sd, OV7610_REG_BRT, val); | 3032 | i2c_w(sd, OV7610_REG_BRT, val); |
2394 | break; | 3033 | break; |
2395 | case SEN_OV7620: | 3034 | case SEN_OV7620: |
2396 | /* 7620 doesn't like manual changes when in auto mode */ | 3035 | /* 7620 doesn't like manual changes when in auto mode */ |
2397 | /*fixme | 3036 | if (!sd->autobrightness) |
2398 | * if (!sd->auto_brt) */ | ||
2399 | i2c_w(sd, OV7610_REG_BRT, val); | 3037 | i2c_w(sd, OV7610_REG_BRT, val); |
2400 | break; | 3038 | break; |
2401 | case SEN_OV7670: | 3039 | case SEN_OV7670: |
@@ -2418,6 +3056,7 @@ static void setcontrast(struct gspca_dev *gspca_dev) | |||
2418 | i2c_w(sd, OV7610_REG_CNT, val); | 3056 | i2c_w(sd, OV7610_REG_CNT, val); |
2419 | break; | 3057 | break; |
2420 | case SEN_OV6630: | 3058 | case SEN_OV6630: |
3059 | case SEN_OV66308AF: | ||
2421 | i2c_w_mask(sd, OV7610_REG_CNT, val >> 4, 0x0f); | 3060 | i2c_w_mask(sd, OV7610_REG_CNT, val >> 4, 0x0f); |
2422 | break; | 3061 | break; |
2423 | case SEN_OV8610: { | 3062 | case SEN_OV8610: { |
@@ -2462,6 +3101,7 @@ static void setcolors(struct gspca_dev *gspca_dev) | |||
2462 | case SEN_OV76BE: | 3101 | case SEN_OV76BE: |
2463 | case SEN_OV6620: | 3102 | case SEN_OV6620: |
2464 | case SEN_OV6630: | 3103 | case SEN_OV6630: |
3104 | case SEN_OV66308AF: | ||
2465 | i2c_w(sd, OV7610_REG_SAT, val); | 3105 | i2c_w(sd, OV7610_REG_SAT, val); |
2466 | break; | 3106 | break; |
2467 | case SEN_OV7620: | 3107 | case SEN_OV7620: |
@@ -2482,6 +3122,72 @@ static void setcolors(struct gspca_dev *gspca_dev) | |||
2482 | } | 3122 | } |
2483 | } | 3123 | } |
2484 | 3124 | ||
3125 | static void setautobrightness(struct sd *sd) | ||
3126 | { | ||
3127 | if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7670) | ||
3128 | return; | ||
3129 | |||
3130 | i2c_w_mask(sd, 0x2d, sd->autobrightness ? 0x10 : 0x00, 0x10); | ||
3131 | } | ||
3132 | |||
3133 | static void setfreq(struct sd *sd) | ||
3134 | { | ||
3135 | if (sd->sensor == SEN_OV7670) { | ||
3136 | switch (sd->freq) { | ||
3137 | case 0: /* Banding filter disabled */ | ||
3138 | i2c_w_mask(sd, OV7670_REG_COM8, 0, OV7670_COM8_BFILT); | ||
3139 | break; | ||
3140 | case 1: /* 50 hz */ | ||
3141 | i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_BFILT, | ||
3142 | OV7670_COM8_BFILT); | ||
3143 | i2c_w_mask(sd, OV7670_REG_COM11, 0x08, 0x18); | ||
3144 | break; | ||
3145 | case 2: /* 60 hz */ | ||
3146 | i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_BFILT, | ||
3147 | OV7670_COM8_BFILT); | ||
3148 | i2c_w_mask(sd, OV7670_REG_COM11, 0x00, 0x18); | ||
3149 | break; | ||
3150 | case 3: /* Auto hz */ | ||
3151 | i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_BFILT, | ||
3152 | OV7670_COM8_BFILT); | ||
3153 | i2c_w_mask(sd, OV7670_REG_COM11, OV7670_COM11_HZAUTO, | ||
3154 | 0x18); | ||
3155 | break; | ||
3156 | } | ||
3157 | } else { | ||
3158 | switch (sd->freq) { | ||
3159 | case 0: /* Banding filter disabled */ | ||
3160 | i2c_w_mask(sd, 0x2d, 0x00, 0x04); | ||
3161 | i2c_w_mask(sd, 0x2a, 0x00, 0x80); | ||
3162 | break; | ||
3163 | case 1: /* 50 hz (filter on and framerate adj) */ | ||
3164 | i2c_w_mask(sd, 0x2d, 0x04, 0x04); | ||
3165 | i2c_w_mask(sd, 0x2a, 0x80, 0x80); | ||
3166 | /* 20 fps -> 16.667 fps */ | ||
3167 | if (sd->sensor == SEN_OV6620 || | ||
3168 | sd->sensor == SEN_OV6630 || | ||
3169 | sd->sensor == SEN_OV66308AF) | ||
3170 | i2c_w(sd, 0x2b, 0x5e); | ||
3171 | else | ||
3172 | i2c_w(sd, 0x2b, 0xac); | ||
3173 | break; | ||
3174 | case 2: /* 60 hz (filter on, ...) */ | ||
3175 | i2c_w_mask(sd, 0x2d, 0x04, 0x04); | ||
3176 | if (sd->sensor == SEN_OV6620 || | ||
3177 | sd->sensor == SEN_OV6630 || | ||
3178 | sd->sensor == SEN_OV66308AF) { | ||
3179 | /* 20 fps -> 15 fps */ | ||
3180 | i2c_w_mask(sd, 0x2a, 0x80, 0x80); | ||
3181 | i2c_w(sd, 0x2b, 0xa8); | ||
3182 | } else { | ||
3183 | /* no framerate adj. */ | ||
3184 | i2c_w_mask(sd, 0x2a, 0x00, 0x80); | ||
3185 | } | ||
3186 | break; | ||
3187 | } | ||
3188 | } | ||
3189 | } | ||
3190 | |||
2485 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | 3191 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) |
2486 | { | 3192 | { |
2487 | struct sd *sd = (struct sd *) gspca_dev; | 3193 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -2572,6 +3278,71 @@ static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val) | |||
2572 | return 0; | 3278 | return 0; |
2573 | } | 3279 | } |
2574 | 3280 | ||
3281 | static int sd_setautobrightness(struct gspca_dev *gspca_dev, __s32 val) | ||
3282 | { | ||
3283 | struct sd *sd = (struct sd *) gspca_dev; | ||
3284 | |||
3285 | sd->autobrightness = val; | ||
3286 | if (gspca_dev->streaming) | ||
3287 | setautobrightness(sd); | ||
3288 | return 0; | ||
3289 | } | ||
3290 | |||
3291 | static int sd_getautobrightness(struct gspca_dev *gspca_dev, __s32 *val) | ||
3292 | { | ||
3293 | struct sd *sd = (struct sd *) gspca_dev; | ||
3294 | |||
3295 | *val = sd->autobrightness; | ||
3296 | return 0; | ||
3297 | } | ||
3298 | |||
3299 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val) | ||
3300 | { | ||
3301 | struct sd *sd = (struct sd *) gspca_dev; | ||
3302 | |||
3303 | sd->freq = val; | ||
3304 | if (gspca_dev->streaming) | ||
3305 | setfreq(sd); | ||
3306 | return 0; | ||
3307 | } | ||
3308 | |||
3309 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val) | ||
3310 | { | ||
3311 | struct sd *sd = (struct sd *) gspca_dev; | ||
3312 | |||
3313 | *val = sd->freq; | ||
3314 | return 0; | ||
3315 | } | ||
3316 | |||
3317 | static int sd_querymenu(struct gspca_dev *gspca_dev, | ||
3318 | struct v4l2_querymenu *menu) | ||
3319 | { | ||
3320 | struct sd *sd = (struct sd *) gspca_dev; | ||
3321 | |||
3322 | switch (menu->id) { | ||
3323 | case V4L2_CID_POWER_LINE_FREQUENCY: | ||
3324 | switch (menu->index) { | ||
3325 | case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */ | ||
3326 | strcpy((char *) menu->name, "NoFliker"); | ||
3327 | return 0; | ||
3328 | case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */ | ||
3329 | strcpy((char *) menu->name, "50 Hz"); | ||
3330 | return 0; | ||
3331 | case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */ | ||
3332 | strcpy((char *) menu->name, "60 Hz"); | ||
3333 | return 0; | ||
3334 | case 3: | ||
3335 | if (sd->sensor != SEN_OV7670) | ||
3336 | return -EINVAL; | ||
3337 | |||
3338 | strcpy((char *) menu->name, "Automatic"); | ||
3339 | return 0; | ||
3340 | } | ||
3341 | break; | ||
3342 | } | ||
3343 | return -EINVAL; | ||
3344 | } | ||
3345 | |||
2575 | /* sub-driver description */ | 3346 | /* sub-driver description */ |
2576 | static const struct sd_desc sd_desc = { | 3347 | static const struct sd_desc sd_desc = { |
2577 | .name = MODULE_NAME, | 3348 | .name = MODULE_NAME, |
@@ -2582,6 +3353,7 @@ static const struct sd_desc sd_desc = { | |||
2582 | .start = sd_start, | 3353 | .start = sd_start, |
2583 | .stopN = sd_stopN, | 3354 | .stopN = sd_stopN, |
2584 | .pkt_scan = sd_pkt_scan, | 3355 | .pkt_scan = sd_pkt_scan, |
3356 | .querymenu = sd_querymenu, | ||
2585 | }; | 3357 | }; |
2586 | 3358 | ||
2587 | /* -- module initialisation -- */ | 3359 | /* -- module initialisation -- */ |
@@ -2590,17 +3362,22 @@ static const __devinitdata struct usb_device_id device_table[] = { | |||
2590 | {USB_DEVICE(0x041e, 0x405f), .driver_info = BRIDGE_OV519 }, | 3362 | {USB_DEVICE(0x041e, 0x405f), .driver_info = BRIDGE_OV519 }, |
2591 | {USB_DEVICE(0x041e, 0x4060), .driver_info = BRIDGE_OV519 }, | 3363 | {USB_DEVICE(0x041e, 0x4060), .driver_info = BRIDGE_OV519 }, |
2592 | {USB_DEVICE(0x041e, 0x4061), .driver_info = BRIDGE_OV519 }, | 3364 | {USB_DEVICE(0x041e, 0x4061), .driver_info = BRIDGE_OV519 }, |
2593 | {USB_DEVICE(0x041e, 0x4064), .driver_info = BRIDGE_OV519 }, | 3365 | {USB_DEVICE(0x041e, 0x4064), |
2594 | {USB_DEVICE(0x041e, 0x4068), .driver_info = BRIDGE_OV519 }, | 3366 | .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, |
3367 | {USB_DEVICE(0x041e, 0x4068), | ||
3368 | .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED }, | ||
2595 | {USB_DEVICE(0x045e, 0x028c), .driver_info = BRIDGE_OV519 }, | 3369 | {USB_DEVICE(0x045e, 0x028c), .driver_info = BRIDGE_OV519 }, |
2596 | {USB_DEVICE(0x054c, 0x0154), .driver_info = BRIDGE_OV519 }, | 3370 | {USB_DEVICE(0x054c, 0x0154), .driver_info = BRIDGE_OV519 }, |
2597 | {USB_DEVICE(0x054c, 0x0155), .driver_info = BRIDGE_OV519 }, | 3371 | {USB_DEVICE(0x054c, 0x0155), .driver_info = BRIDGE_OV519 }, |
3372 | {USB_DEVICE(0x05a9, 0x0511), .driver_info = BRIDGE_OV511 }, | ||
2598 | {USB_DEVICE(0x05a9, 0x0518), .driver_info = BRIDGE_OV518 }, | 3373 | {USB_DEVICE(0x05a9, 0x0518), .driver_info = BRIDGE_OV518 }, |
2599 | {USB_DEVICE(0x05a9, 0x0519), .driver_info = BRIDGE_OV519 }, | 3374 | {USB_DEVICE(0x05a9, 0x0519), .driver_info = BRIDGE_OV519 }, |
2600 | {USB_DEVICE(0x05a9, 0x0530), .driver_info = BRIDGE_OV519 }, | 3375 | {USB_DEVICE(0x05a9, 0x0530), .driver_info = BRIDGE_OV519 }, |
2601 | {USB_DEVICE(0x05a9, 0x4519), .driver_info = BRIDGE_OV519 }, | 3376 | {USB_DEVICE(0x05a9, 0x4519), .driver_info = BRIDGE_OV519 }, |
2602 | {USB_DEVICE(0x05a9, 0x8519), .driver_info = BRIDGE_OV519 }, | 3377 | {USB_DEVICE(0x05a9, 0x8519), .driver_info = BRIDGE_OV519 }, |
3378 | {USB_DEVICE(0x05a9, 0xa511), .driver_info = BRIDGE_OV511PLUS }, | ||
2603 | {USB_DEVICE(0x05a9, 0xa518), .driver_info = BRIDGE_OV518PLUS }, | 3379 | {USB_DEVICE(0x05a9, 0xa518), .driver_info = BRIDGE_OV518PLUS }, |
3380 | {USB_DEVICE(0x0813, 0x0002), .driver_info = BRIDGE_OV511PLUS }, | ||
2604 | {} | 3381 | {} |
2605 | }; | 3382 | }; |
2606 | 3383 | ||
diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index dc6a6f11354a..0d02f41fa7d0 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c | |||
@@ -46,6 +46,7 @@ struct sd { | |||
46 | u8 gamma; | 46 | u8 gamma; |
47 | u8 vflip; /* ov7630/ov7648 only */ | 47 | u8 vflip; /* ov7630/ov7648 only */ |
48 | u8 infrared; /* mt9v111 only */ | 48 | u8 infrared; /* mt9v111 only */ |
49 | u8 freq; /* ov76xx only */ | ||
49 | u8 quality; /* image quality */ | 50 | u8 quality; /* image quality */ |
50 | #define QUALITY_MIN 60 | 51 | #define QUALITY_MIN 60 |
51 | #define QUALITY_MAX 95 | 52 | #define QUALITY_MAX 95 |
@@ -96,8 +97,11 @@ static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); | |||
96 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val); | 97 | static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val); |
97 | static int sd_setinfrared(struct gspca_dev *gspca_dev, __s32 val); | 98 | static int sd_setinfrared(struct gspca_dev *gspca_dev, __s32 val); |
98 | static int sd_getinfrared(struct gspca_dev *gspca_dev, __s32 *val); | 99 | static int sd_getinfrared(struct gspca_dev *gspca_dev, __s32 *val); |
100 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); | ||
101 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); | ||
99 | 102 | ||
100 | static struct ctrl sd_ctrls[] = { | 103 | static struct ctrl sd_ctrls[] = { |
104 | #define BRIGHTNESS_IDX 0 | ||
101 | { | 105 | { |
102 | { | 106 | { |
103 | .id = V4L2_CID_BRIGHTNESS, | 107 | .id = V4L2_CID_BRIGHTNESS, |
@@ -113,6 +117,7 @@ static struct ctrl sd_ctrls[] = { | |||
113 | .set = sd_setbrightness, | 117 | .set = sd_setbrightness, |
114 | .get = sd_getbrightness, | 118 | .get = sd_getbrightness, |
115 | }, | 119 | }, |
120 | #define CONTRAST_IDX 1 | ||
116 | { | 121 | { |
117 | { | 122 | { |
118 | .id = V4L2_CID_CONTRAST, | 123 | .id = V4L2_CID_CONTRAST, |
@@ -128,20 +133,22 @@ static struct ctrl sd_ctrls[] = { | |||
128 | .set = sd_setcontrast, | 133 | .set = sd_setcontrast, |
129 | .get = sd_getcontrast, | 134 | .get = sd_getcontrast, |
130 | }, | 135 | }, |
136 | #define COLOR_IDX 2 | ||
131 | { | 137 | { |
132 | { | 138 | { |
133 | .id = V4L2_CID_SATURATION, | 139 | .id = V4L2_CID_SATURATION, |
134 | .type = V4L2_CTRL_TYPE_INTEGER, | 140 | .type = V4L2_CTRL_TYPE_INTEGER, |
135 | .name = "Color", | 141 | .name = "Saturation", |
136 | .minimum = 0, | 142 | .minimum = 0, |
137 | .maximum = 40, | 143 | .maximum = 40, |
138 | .step = 1, | 144 | .step = 1, |
139 | #define COLOR_DEF 32 | 145 | #define COLOR_DEF 25 |
140 | .default_value = COLOR_DEF, | 146 | .default_value = COLOR_DEF, |
141 | }, | 147 | }, |
142 | .set = sd_setcolors, | 148 | .set = sd_setcolors, |
143 | .get = sd_getcolors, | 149 | .get = sd_getcolors, |
144 | }, | 150 | }, |
151 | #define BLUE_BALANCE_IDX 3 | ||
145 | { | 152 | { |
146 | { | 153 | { |
147 | .id = V4L2_CID_BLUE_BALANCE, | 154 | .id = V4L2_CID_BLUE_BALANCE, |
@@ -156,6 +163,7 @@ static struct ctrl sd_ctrls[] = { | |||
156 | .set = sd_setblue_balance, | 163 | .set = sd_setblue_balance, |
157 | .get = sd_getblue_balance, | 164 | .get = sd_getblue_balance, |
158 | }, | 165 | }, |
166 | #define RED_BALANCE_IDX 4 | ||
159 | { | 167 | { |
160 | { | 168 | { |
161 | .id = V4L2_CID_RED_BALANCE, | 169 | .id = V4L2_CID_RED_BALANCE, |
@@ -170,6 +178,7 @@ static struct ctrl sd_ctrls[] = { | |||
170 | .set = sd_setred_balance, | 178 | .set = sd_setred_balance, |
171 | .get = sd_getred_balance, | 179 | .get = sd_getred_balance, |
172 | }, | 180 | }, |
181 | #define GAMMA_IDX 5 | ||
173 | { | 182 | { |
174 | { | 183 | { |
175 | .id = V4L2_CID_GAMMA, | 184 | .id = V4L2_CID_GAMMA, |
@@ -184,7 +193,7 @@ static struct ctrl sd_ctrls[] = { | |||
184 | .set = sd_setgamma, | 193 | .set = sd_setgamma, |
185 | .get = sd_getgamma, | 194 | .get = sd_getgamma, |
186 | }, | 195 | }, |
187 | #define AUTOGAIN_IDX 5 | 196 | #define AUTOGAIN_IDX 6 |
188 | { | 197 | { |
189 | { | 198 | { |
190 | .id = V4L2_CID_AUTOGAIN, | 199 | .id = V4L2_CID_AUTOGAIN, |
@@ -200,7 +209,7 @@ static struct ctrl sd_ctrls[] = { | |||
200 | .get = sd_getautogain, | 209 | .get = sd_getautogain, |
201 | }, | 210 | }, |
202 | /* ov7630/ov7648 only */ | 211 | /* ov7630/ov7648 only */ |
203 | #define VFLIP_IDX 6 | 212 | #define VFLIP_IDX 7 |
204 | { | 213 | { |
205 | { | 214 | { |
206 | .id = V4L2_CID_VFLIP, | 215 | .id = V4L2_CID_VFLIP, |
@@ -209,14 +218,14 @@ static struct ctrl sd_ctrls[] = { | |||
209 | .minimum = 0, | 218 | .minimum = 0, |
210 | .maximum = 1, | 219 | .maximum = 1, |
211 | .step = 1, | 220 | .step = 1, |
212 | #define VFLIP_DEF 0 /* vflip def = 1 for ov7630 */ | 221 | #define VFLIP_DEF 0 |
213 | .default_value = VFLIP_DEF, | 222 | .default_value = VFLIP_DEF, |
214 | }, | 223 | }, |
215 | .set = sd_setvflip, | 224 | .set = sd_setvflip, |
216 | .get = sd_getvflip, | 225 | .get = sd_getvflip, |
217 | }, | 226 | }, |
218 | /* mt9v111 only */ | 227 | /* mt9v111 only */ |
219 | #define INFRARED_IDX 7 | 228 | #define INFRARED_IDX 8 |
220 | { | 229 | { |
221 | { | 230 | { |
222 | .id = V4L2_CID_INFRARED, | 231 | .id = V4L2_CID_INFRARED, |
@@ -231,28 +240,44 @@ static struct ctrl sd_ctrls[] = { | |||
231 | .set = sd_setinfrared, | 240 | .set = sd_setinfrared, |
232 | .get = sd_getinfrared, | 241 | .get = sd_getinfrared, |
233 | }, | 242 | }, |
243 | /* ov7630/ov7648/ov7660 only */ | ||
244 | #define FREQ_IDX 9 | ||
245 | { | ||
246 | { | ||
247 | .id = V4L2_CID_POWER_LINE_FREQUENCY, | ||
248 | .type = V4L2_CTRL_TYPE_MENU, | ||
249 | .name = "Light frequency filter", | ||
250 | .minimum = 0, | ||
251 | .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */ | ||
252 | .step = 1, | ||
253 | #define FREQ_DEF 2 | ||
254 | .default_value = FREQ_DEF, | ||
255 | }, | ||
256 | .set = sd_setfreq, | ||
257 | .get = sd_getfreq, | ||
258 | }, | ||
234 | }; | 259 | }; |
235 | 260 | ||
236 | /* table of the disabled controls */ | 261 | /* table of the disabled controls */ |
237 | static __u32 ctrl_dis[] = { | 262 | static __u32 ctrl_dis[] = { |
238 | (1 << INFRARED_IDX) | (1 << VFLIP_IDX), | 263 | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX), |
239 | /* SENSOR_HV7131R 0 */ | 264 | /* SENSOR_HV7131R 0 */ |
240 | (1 << INFRARED_IDX) | (1 << VFLIP_IDX), | 265 | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX), |
241 | /* SENSOR_MI0360 1 */ | 266 | /* SENSOR_MI0360 1 */ |
242 | (1 << INFRARED_IDX) | (1 << VFLIP_IDX), | 267 | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX), |
243 | /* SENSOR_MO4000 2 */ | 268 | /* SENSOR_MO4000 2 */ |
244 | (1 << VFLIP_IDX), | 269 | (1 << VFLIP_IDX) | (1 << FREQ_IDX), |
245 | /* SENSOR_MT9V111 3 */ | 270 | /* SENSOR_MT9V111 3 */ |
246 | (1 << INFRARED_IDX) | (1 << VFLIP_IDX), | 271 | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | (1 << FREQ_IDX), |
247 | /* SENSOR_OM6802 4 */ | 272 | /* SENSOR_OM6802 4 */ |
248 | (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX), | 273 | (1 << INFRARED_IDX), |
249 | /* SENSOR_OV7630 5 */ | 274 | /* SENSOR_OV7630 5 */ |
250 | (1 << INFRARED_IDX), | 275 | (1 << INFRARED_IDX), |
251 | /* SENSOR_OV7648 6 */ | 276 | /* SENSOR_OV7648 6 */ |
252 | (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX), | 277 | (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX), |
253 | /* SENSOR_OV7660 7 */ | 278 | /* SENSOR_OV7660 7 */ |
254 | (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX), | 279 | (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX) | |
255 | /* SENSOR_SP80708 8 */ | 280 | (1 << FREQ_IDX), /* SENSOR_SP80708 8 */ |
256 | }; | 281 | }; |
257 | 282 | ||
258 | static const struct v4l2_pix_format vga_mode[] = { | 283 | static const struct v4l2_pix_format vga_mode[] = { |
@@ -268,7 +293,8 @@ static const struct v4l2_pix_format vga_mode[] = { | |||
268 | .priv = 1}, | 293 | .priv = 1}, |
269 | {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | 294 | {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, |
270 | .bytesperline = 640, | 295 | .bytesperline = 640, |
271 | .sizeimage = 640 * 480 * 3 / 8 + 590, | 296 | /* Note 3 / 8 is not large enough, not even 5 / 8 is ?! */ |
297 | .sizeimage = 640 * 480 * 3 / 4 + 590, | ||
272 | .colorspace = V4L2_COLORSPACE_JPEG, | 298 | .colorspace = V4L2_COLORSPACE_JPEG, |
273 | .priv = 0}, | 299 | .priv = 0}, |
274 | }; | 300 | }; |
@@ -604,7 +630,9 @@ static const u8 ov7630_sensor_init[][8] = { | |||
604 | /* win: i2c_r from 00 to 80 */ | 630 | /* win: i2c_r from 00 to 80 */ |
605 | {0xd1, 0x21, 0x03, 0x80, 0x10, 0x20, 0x80, 0x10}, | 631 | {0xd1, 0x21, 0x03, 0x80, 0x10, 0x20, 0x80, 0x10}, |
606 | {0xb1, 0x21, 0x0c, 0x20, 0x20, 0x00, 0x00, 0x10}, | 632 | {0xb1, 0x21, 0x0c, 0x20, 0x20, 0x00, 0x00, 0x10}, |
607 | {0xd1, 0x21, 0x11, 0x00, 0x48, 0xc0, 0x00, 0x10}, | 633 | /* HDG: 0x11 was 0x00 change to 0x01 for better exposure (15 fps instead of 30) |
634 | 0x13 was 0xc0 change to 0xc3 for auto gain and exposure */ | ||
635 | {0xd1, 0x21, 0x11, 0x01, 0x48, 0xc3, 0x00, 0x10}, | ||
608 | {0xb1, 0x21, 0x15, 0x80, 0x03, 0x00, 0x00, 0x10}, | 636 | {0xb1, 0x21, 0x15, 0x80, 0x03, 0x00, 0x00, 0x10}, |
609 | {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10}, | 637 | {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10}, |
610 | {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10}, | 638 | {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10}, |
@@ -638,9 +666,8 @@ static const u8 ov7630_sensor_init[][8] = { | |||
638 | {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, | 666 | {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, |
639 | {0xb1, 0x21, 0x01, 0x80, 0x80, 0x00, 0x00, 0x10}, | 667 | {0xb1, 0x21, 0x01, 0x80, 0x80, 0x00, 0x00, 0x10}, |
640 | /* */ | 668 | /* */ |
641 | {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10}, | 669 | /* {0xa1, 0x21, 0x2a, 0x88, 0x00, 0x00, 0x00, 0x10}, * set by setfreq */ |
642 | {0xa1, 0x21, 0x2a, 0x88, 0x00, 0x00, 0x00, 0x10}, | 670 | /* {0xa1, 0x21, 0x2b, 0x34, 0x00, 0x00, 0x00, 0x10}, * set by setfreq */ |
643 | {0xa1, 0x21, 0x2b, 0x34, 0x00, 0x00, 0x00, 0x10}, | ||
644 | /* */ | 671 | /* */ |
645 | {0xa1, 0x21, 0x10, 0x83, 0x00, 0x00, 0x00, 0x10}, | 672 | {0xa1, 0x21, 0x10, 0x83, 0x00, 0x00, 0x00, 0x10}, |
646 | /* {0xb1, 0x21, 0x01, 0x88, 0x70, 0x00, 0x00, 0x10}, */ | 673 | /* {0xb1, 0x21, 0x01, 0x88, 0x70, 0x00, 0x00, 0x10}, */ |
@@ -673,7 +700,7 @@ static const u8 ov7648_sensor_init[][8] = { | |||
673 | {0xd1, 0x21, 0x21, 0x86, 0x00, 0xde, 0xa0, 0x10}, | 700 | {0xd1, 0x21, 0x21, 0x86, 0x00, 0xde, 0xa0, 0x10}, |
674 | /* {0xd1, 0x21, 0x25, 0x80, 0x32, 0xfe, 0xa0, 0x10}, jfm done */ | 701 | /* {0xd1, 0x21, 0x25, 0x80, 0x32, 0xfe, 0xa0, 0x10}, jfm done */ |
675 | /* {0xd1, 0x21, 0x29, 0x00, 0x91, 0x00, 0x88, 0x10}, jfm done */ | 702 | /* {0xd1, 0x21, 0x29, 0x00, 0x91, 0x00, 0x88, 0x10}, jfm done */ |
676 | {0xb1, 0x21, 0x2d, 0x85, 0x00, 0x00, 0x00, 0x10}, | 703 | /* {0xb1, 0x21, 0x2d, 0x85, 0x00, 0x00, 0x00, 0x10}, set by setfreq */ |
677 | /*...*/ | 704 | /*...*/ |
678 | /* {0xa1, 0x21, 0x12, 0x08, 0x00, 0x00, 0x00, 0x10}, jfm done */ | 705 | /* {0xa1, 0x21, 0x12, 0x08, 0x00, 0x00, 0x00, 0x10}, jfm done */ |
679 | /* {0xa1, 0x21, 0x75, 0x06, 0x00, 0x00, 0x00, 0x10}, * COMN | 706 | /* {0xa1, 0x21, 0x75, 0x06, 0x00, 0x00, 0x00, 0x10}, * COMN |
@@ -1294,11 +1321,9 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
1294 | sd->gamma = GAMMA_DEF; | 1321 | sd->gamma = GAMMA_DEF; |
1295 | sd->autogain = AUTOGAIN_DEF; | 1322 | sd->autogain = AUTOGAIN_DEF; |
1296 | sd->ag_cnt = -1; | 1323 | sd->ag_cnt = -1; |
1297 | if (sd->sensor != SENSOR_OV7630) | 1324 | sd->vflip = VFLIP_DEF; |
1298 | sd->vflip = 0; | ||
1299 | else | ||
1300 | sd->vflip = 1; | ||
1301 | sd->infrared = INFRARED_DEF; | 1325 | sd->infrared = INFRARED_DEF; |
1326 | sd->freq = FREQ_DEF; | ||
1302 | sd->quality = QUALITY_DEF; | 1327 | sd->quality = QUALITY_DEF; |
1303 | sd->jpegqual = 80; | 1328 | sd->jpegqual = 80; |
1304 | 1329 | ||
@@ -1569,7 +1594,7 @@ static void setautogain(struct gspca_dev *gspca_dev) | |||
1569 | else | 1594 | else |
1570 | comb = 0xa0; | 1595 | comb = 0xa0; |
1571 | if (sd->autogain) | 1596 | if (sd->autogain) |
1572 | comb |= 0x02; | 1597 | comb |= 0x03; |
1573 | i2c_w1(&sd->gspca_dev, 0x13, comb); | 1598 | i2c_w1(&sd->gspca_dev, 0x13, comb); |
1574 | return; | 1599 | return; |
1575 | } | 1600 | } |
@@ -1585,12 +1610,15 @@ static void setvflip(struct sd *sd) | |||
1585 | { | 1610 | { |
1586 | u8 comn; | 1611 | u8 comn; |
1587 | 1612 | ||
1588 | if (sd->sensor == SENSOR_OV7630) | 1613 | if (sd->sensor == SENSOR_OV7630) { |
1589 | comn = 0x02; | 1614 | comn = 0x02; |
1590 | else | 1615 | if (!sd->vflip) |
1616 | comn |= 0x80; | ||
1617 | } else { | ||
1591 | comn = 0x06; | 1618 | comn = 0x06; |
1592 | if (sd->vflip) | 1619 | if (sd->vflip) |
1593 | comn |= 0x80; | 1620 | comn |= 0x80; |
1621 | } | ||
1594 | i2c_w1(&sd->gspca_dev, 0x75, comn); | 1622 | i2c_w1(&sd->gspca_dev, 0x75, comn); |
1595 | } | 1623 | } |
1596 | 1624 | ||
@@ -1602,6 +1630,58 @@ static void setinfrared(struct sd *sd) | |||
1602 | sd->infrared ? 0x66 : 0x64); | 1630 | sd->infrared ? 0x66 : 0x64); |
1603 | } | 1631 | } |
1604 | 1632 | ||
1633 | static void setfreq(struct gspca_dev *gspca_dev) | ||
1634 | { | ||
1635 | struct sd *sd = (struct sd *) gspca_dev; | ||
1636 | |||
1637 | if (sd->sensor == SENSOR_OV7660) { | ||
1638 | switch (sd->freq) { | ||
1639 | case 0: /* Banding filter disabled */ | ||
1640 | i2c_w1(gspca_dev, 0x13, 0xdf); | ||
1641 | break; | ||
1642 | case 1: /* 50 hz */ | ||
1643 | i2c_w1(gspca_dev, 0x13, 0xff); | ||
1644 | i2c_w1(gspca_dev, 0x3b, 0x0a); | ||
1645 | break; | ||
1646 | case 2: /* 60 hz */ | ||
1647 | i2c_w1(gspca_dev, 0x13, 0xff); | ||
1648 | i2c_w1(gspca_dev, 0x3b, 0x02); | ||
1649 | break; | ||
1650 | } | ||
1651 | } else { | ||
1652 | u8 reg2a = 0, reg2b = 0, reg2d = 0; | ||
1653 | |||
1654 | /* Get reg2a / reg2d base values */ | ||
1655 | switch (sd->sensor) { | ||
1656 | case SENSOR_OV7630: | ||
1657 | reg2a = 0x08; | ||
1658 | reg2d = 0x01; | ||
1659 | break; | ||
1660 | case SENSOR_OV7648: | ||
1661 | reg2a = 0x11; | ||
1662 | reg2d = 0x81; | ||
1663 | break; | ||
1664 | } | ||
1665 | |||
1666 | switch (sd->freq) { | ||
1667 | case 0: /* Banding filter disabled */ | ||
1668 | break; | ||
1669 | case 1: /* 50 hz (filter on and framerate adj) */ | ||
1670 | reg2a |= 0x80; | ||
1671 | reg2b = 0xac; | ||
1672 | reg2d |= 0x04; | ||
1673 | break; | ||
1674 | case 2: /* 60 hz (filter on, no framerate adj) */ | ||
1675 | reg2a |= 0x80; | ||
1676 | reg2d |= 0x04; | ||
1677 | break; | ||
1678 | } | ||
1679 | i2c_w1(gspca_dev, 0x2a, reg2a); | ||
1680 | i2c_w1(gspca_dev, 0x2b, reg2b); | ||
1681 | i2c_w1(gspca_dev, 0x2d, reg2d); | ||
1682 | } | ||
1683 | } | ||
1684 | |||
1605 | static void setjpegqual(struct gspca_dev *gspca_dev) | 1685 | static void setjpegqual(struct gspca_dev *gspca_dev) |
1606 | { | 1686 | { |
1607 | struct sd *sd = (struct sd *) gspca_dev; | 1687 | struct sd *sd = (struct sd *) gspca_dev; |
@@ -1828,6 +1908,7 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1828 | setbrightness(gspca_dev); | 1908 | setbrightness(gspca_dev); |
1829 | setcontrast(gspca_dev); | 1909 | setcontrast(gspca_dev); |
1830 | setautogain(gspca_dev); | 1910 | setautogain(gspca_dev); |
1911 | setfreq(gspca_dev); | ||
1831 | return 0; | 1912 | return 0; |
1832 | } | 1913 | } |
1833 | 1914 | ||
@@ -2131,6 +2212,24 @@ static int sd_getinfrared(struct gspca_dev *gspca_dev, __s32 *val) | |||
2131 | return 0; | 2212 | return 0; |
2132 | } | 2213 | } |
2133 | 2214 | ||
2215 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val) | ||
2216 | { | ||
2217 | struct sd *sd = (struct sd *) gspca_dev; | ||
2218 | |||
2219 | sd->freq = val; | ||
2220 | if (gspca_dev->streaming) | ||
2221 | setfreq(gspca_dev); | ||
2222 | return 0; | ||
2223 | } | ||
2224 | |||
2225 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val) | ||
2226 | { | ||
2227 | struct sd *sd = (struct sd *) gspca_dev; | ||
2228 | |||
2229 | *val = sd->freq; | ||
2230 | return 0; | ||
2231 | } | ||
2232 | |||
2134 | static int sd_set_jcomp(struct gspca_dev *gspca_dev, | 2233 | static int sd_set_jcomp(struct gspca_dev *gspca_dev, |
2135 | struct v4l2_jpegcompression *jcomp) | 2234 | struct v4l2_jpegcompression *jcomp) |
2136 | { | 2235 | { |
@@ -2159,6 +2258,27 @@ static int sd_get_jcomp(struct gspca_dev *gspca_dev, | |||
2159 | return 0; | 2258 | return 0; |
2160 | } | 2259 | } |
2161 | 2260 | ||
2261 | static int sd_querymenu(struct gspca_dev *gspca_dev, | ||
2262 | struct v4l2_querymenu *menu) | ||
2263 | { | ||
2264 | switch (menu->id) { | ||
2265 | case V4L2_CID_POWER_LINE_FREQUENCY: | ||
2266 | switch (menu->index) { | ||
2267 | case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */ | ||
2268 | strcpy((char *) menu->name, "NoFliker"); | ||
2269 | return 0; | ||
2270 | case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */ | ||
2271 | strcpy((char *) menu->name, "50 Hz"); | ||
2272 | return 0; | ||
2273 | case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */ | ||
2274 | strcpy((char *) menu->name, "60 Hz"); | ||
2275 | return 0; | ||
2276 | } | ||
2277 | break; | ||
2278 | } | ||
2279 | return -EINVAL; | ||
2280 | } | ||
2281 | |||
2162 | /* sub-driver description */ | 2282 | /* sub-driver description */ |
2163 | static const struct sd_desc sd_desc = { | 2283 | static const struct sd_desc sd_desc = { |
2164 | .name = MODULE_NAME, | 2284 | .name = MODULE_NAME, |
@@ -2173,6 +2293,7 @@ static const struct sd_desc sd_desc = { | |||
2173 | .dq_callback = do_autogain, | 2293 | .dq_callback = do_autogain, |
2174 | .get_jcomp = sd_get_jcomp, | 2294 | .get_jcomp = sd_get_jcomp, |
2175 | .set_jcomp = sd_set_jcomp, | 2295 | .set_jcomp = sd_set_jcomp, |
2296 | .querymenu = sd_querymenu, | ||
2176 | }; | 2297 | }; |
2177 | 2298 | ||
2178 | /* -- module initialisation -- */ | 2299 | /* -- module initialisation -- */ |
@@ -2233,7 +2354,7 @@ static const __devinitdata struct usb_device_id device_table[] = { | |||
2233 | {USB_DEVICE(0x0c45, 0x613b), BSI(SN9C120, OV7660, 0x21)}, | 2354 | {USB_DEVICE(0x0c45, 0x613b), BSI(SN9C120, OV7660, 0x21)}, |
2234 | #endif | 2355 | #endif |
2235 | {USB_DEVICE(0x0c45, 0x613c), BSI(SN9C120, HV7131R, 0x11)}, | 2356 | {USB_DEVICE(0x0c45, 0x613c), BSI(SN9C120, HV7131R, 0x11)}, |
2236 | /* {USB_DEVICE(0x0c45, 0x613e), BSI(SN9C120, OV7630, 0x??)}, */ | 2357 | {USB_DEVICE(0x0c45, 0x613e), BSI(SN9C120, OV7630, 0x21)}, |
2237 | {USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, SP80708, 0x18)}, | 2358 | {USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, SP80708, 0x18)}, |
2238 | {} | 2359 | {} |
2239 | }; | 2360 | }; |
diff --git a/drivers/media/video/gspca/stv06xx/Makefile b/drivers/media/video/gspca/stv06xx/Makefile index feeaa94ab588..2f3c3a606ce4 100644 --- a/drivers/media/video/gspca/stv06xx/Makefile +++ b/drivers/media/video/gspca/stv06xx/Makefile | |||
@@ -3,7 +3,8 @@ obj-$(CONFIG_USB_STV06XX) += gspca_stv06xx.o | |||
3 | gspca_stv06xx-objs := stv06xx.o \ | 3 | gspca_stv06xx-objs := stv06xx.o \ |
4 | stv06xx_vv6410.o \ | 4 | stv06xx_vv6410.o \ |
5 | stv06xx_hdcs.o \ | 5 | stv06xx_hdcs.o \ |
6 | stv06xx_pb0100.o | 6 | stv06xx_pb0100.o \ |
7 | stv06xx_st6422.o | ||
7 | 8 | ||
8 | EXTRA_CFLAGS += -Idrivers/media/video/gspca | 9 | EXTRA_CFLAGS += -Idrivers/media/video/gspca |
9 | 10 | ||
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.c b/drivers/media/video/gspca/stv06xx/stv06xx.c index e573c3406324..0da8e0de0456 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx.c +++ b/drivers/media/video/gspca/stv06xx/stv06xx.c | |||
@@ -92,11 +92,10 @@ static int stv06xx_write_sensor_finish(struct sd *sd) | |||
92 | { | 92 | { |
93 | int err = 0; | 93 | int err = 0; |
94 | 94 | ||
95 | if (IS_850(sd)) { | 95 | if (sd->bridge == BRIDGE_STV610) { |
96 | struct usb_device *udev = sd->gspca_dev.dev; | 96 | struct usb_device *udev = sd->gspca_dev.dev; |
97 | __u8 *buf = sd->gspca_dev.usb_buf; | 97 | __u8 *buf = sd->gspca_dev.usb_buf; |
98 | 98 | ||
99 | /* Quickam Web needs an extra packet */ | ||
100 | buf[0] = 0; | 99 | buf[0] = 0; |
101 | err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | 100 | err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), |
102 | 0x04, 0x40, 0x1704, 0, buf, 1, | 101 | 0x04, 0x40, 0x1704, 0, buf, 1, |
@@ -253,7 +252,7 @@ static int stv06xx_init(struct gspca_dev *gspca_dev) | |||
253 | 252 | ||
254 | err = sd->sensor->init(sd); | 253 | err = sd->sensor->init(sd); |
255 | 254 | ||
256 | if (dump_sensor) | 255 | if (dump_sensor && sd->sensor->dump) |
257 | sd->sensor->dump(sd); | 256 | sd->sensor->dump(sd); |
258 | 257 | ||
259 | return (err < 0) ? err : 0; | 258 | return (err < 0) ? err : 0; |
@@ -318,6 +317,8 @@ static void stv06xx_pkt_scan(struct gspca_dev *gspca_dev, | |||
318 | __u8 *data, /* isoc packet */ | 317 | __u8 *data, /* isoc packet */ |
319 | int len) /* iso packet length */ | 318 | int len) /* iso packet length */ |
320 | { | 319 | { |
320 | struct sd *sd = (struct sd *) gspca_dev; | ||
321 | |||
321 | PDEBUG(D_PACK, "Packet of length %d arrived", len); | 322 | PDEBUG(D_PACK, "Packet of length %d arrived", len); |
322 | 323 | ||
323 | /* A packet may contain several frames | 324 | /* A packet may contain several frames |
@@ -343,14 +344,29 @@ static void stv06xx_pkt_scan(struct gspca_dev *gspca_dev, | |||
343 | if (len < chunk_len) { | 344 | if (len < chunk_len) { |
344 | PDEBUG(D_ERR, "URB packet length is smaller" | 345 | PDEBUG(D_ERR, "URB packet length is smaller" |
345 | " than the specified chunk length"); | 346 | " than the specified chunk length"); |
347 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
346 | return; | 348 | return; |
347 | } | 349 | } |
348 | 350 | ||
351 | /* First byte seem to be 02=data 2nd byte is unknown??? */ | ||
352 | if (sd->bridge == BRIDGE_ST6422 && (id & 0xFF00) == 0x0200) | ||
353 | goto frame_data; | ||
354 | |||
349 | switch (id) { | 355 | switch (id) { |
350 | case 0x0200: | 356 | case 0x0200: |
351 | case 0x4200: | 357 | case 0x4200: |
358 | frame_data: | ||
352 | PDEBUG(D_PACK, "Frame data packet detected"); | 359 | PDEBUG(D_PACK, "Frame data packet detected"); |
353 | 360 | ||
361 | if (sd->to_skip) { | ||
362 | int skip = (sd->to_skip < chunk_len) ? | ||
363 | sd->to_skip : chunk_len; | ||
364 | data += skip; | ||
365 | len -= skip; | ||
366 | chunk_len -= skip; | ||
367 | sd->to_skip -= skip; | ||
368 | } | ||
369 | |||
354 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, | 370 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, |
355 | data, chunk_len); | 371 | data, chunk_len); |
356 | break; | 372 | break; |
@@ -365,6 +381,9 @@ static void stv06xx_pkt_scan(struct gspca_dev *gspca_dev, | |||
365 | gspca_frame_add(gspca_dev, FIRST_PACKET, | 381 | gspca_frame_add(gspca_dev, FIRST_PACKET, |
366 | frame, data, 0); | 382 | frame, data, 0); |
367 | 383 | ||
384 | if (sd->bridge == BRIDGE_ST6422) | ||
385 | sd->to_skip = gspca_dev->width * 4; | ||
386 | |||
368 | if (chunk_len) | 387 | if (chunk_len) |
369 | PDEBUG(D_ERR, "Chunk length is " | 388 | PDEBUG(D_ERR, "Chunk length is " |
370 | "non-zero on a SOF"); | 389 | "non-zero on a SOF"); |
@@ -395,8 +414,12 @@ static void stv06xx_pkt_scan(struct gspca_dev *gspca_dev, | |||
395 | /* Unknown chunk with 2 bytes of data, | 414 | /* Unknown chunk with 2 bytes of data, |
396 | occurs 2-3 times per USB interrupt */ | 415 | occurs 2-3 times per USB interrupt */ |
397 | break; | 416 | break; |
417 | case 0x42ff: | ||
418 | PDEBUG(D_PACK, "Chunk 0x42ff detected"); | ||
419 | /* Special chunk seen sometimes on the ST6422 */ | ||
420 | break; | ||
398 | default: | 421 | default: |
399 | PDEBUG(D_PACK, "Unknown chunk %d detected", id); | 422 | PDEBUG(D_PACK, "Unknown chunk 0x%04x detected", id); |
400 | /* Unknown chunk */ | 423 | /* Unknown chunk */ |
401 | } | 424 | } |
402 | data += chunk_len; | 425 | data += chunk_len; |
@@ -428,11 +451,16 @@ static int stv06xx_config(struct gspca_dev *gspca_dev, | |||
428 | 451 | ||
429 | cam = &gspca_dev->cam; | 452 | cam = &gspca_dev->cam; |
430 | sd->desc = sd_desc; | 453 | sd->desc = sd_desc; |
454 | sd->bridge = id->driver_info; | ||
431 | gspca_dev->sd_desc = &sd->desc; | 455 | gspca_dev->sd_desc = &sd->desc; |
432 | 456 | ||
433 | if (dump_bridge) | 457 | if (dump_bridge) |
434 | stv06xx_dump_bridge(sd); | 458 | stv06xx_dump_bridge(sd); |
435 | 459 | ||
460 | sd->sensor = &stv06xx_sensor_st6422; | ||
461 | if (!sd->sensor->probe(sd)) | ||
462 | return 0; | ||
463 | |||
436 | sd->sensor = &stv06xx_sensor_vv6410; | 464 | sd->sensor = &stv06xx_sensor_vv6410; |
437 | if (!sd->sensor->probe(sd)) | 465 | if (!sd->sensor->probe(sd)) |
438 | return 0; | 466 | return 0; |
@@ -457,9 +485,20 @@ static int stv06xx_config(struct gspca_dev *gspca_dev, | |||
457 | 485 | ||
458 | /* -- module initialisation -- */ | 486 | /* -- module initialisation -- */ |
459 | static const __devinitdata struct usb_device_id device_table[] = { | 487 | static const __devinitdata struct usb_device_id device_table[] = { |
460 | {USB_DEVICE(0x046d, 0x0840)}, /* QuickCam Express */ | 488 | /* QuickCam Express */ |
461 | {USB_DEVICE(0x046d, 0x0850)}, /* LEGO cam / QuickCam Web */ | 489 | {USB_DEVICE(0x046d, 0x0840), .driver_info = BRIDGE_STV600 }, |
462 | {USB_DEVICE(0x046d, 0x0870)}, /* Dexxa WebCam USB */ | 490 | /* LEGO cam / QuickCam Web */ |
491 | {USB_DEVICE(0x046d, 0x0850), .driver_info = BRIDGE_STV610 }, | ||
492 | /* Dexxa WebCam USB */ | ||
493 | {USB_DEVICE(0x046d, 0x0870), .driver_info = BRIDGE_STV602 }, | ||
494 | /* QuickCam Messenger */ | ||
495 | {USB_DEVICE(0x046D, 0x08F0), .driver_info = BRIDGE_ST6422 }, | ||
496 | /* QuickCam Communicate */ | ||
497 | {USB_DEVICE(0x046D, 0x08F5), .driver_info = BRIDGE_ST6422 }, | ||
498 | /* QuickCam Messenger (new) */ | ||
499 | {USB_DEVICE(0x046D, 0x08F6), .driver_info = BRIDGE_ST6422 }, | ||
500 | /* QuickCam Messenger (new) */ | ||
501 | {USB_DEVICE(0x046D, 0x08DA), .driver_info = BRIDGE_ST6422 }, | ||
463 | {} | 502 | {} |
464 | }; | 503 | }; |
465 | MODULE_DEVICE_TABLE(usb, device_table); | 504 | MODULE_DEVICE_TABLE(usb, device_table); |
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.h b/drivers/media/video/gspca/stv06xx/stv06xx.h index 1207e7d17f14..9df7137fe67e 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx.h +++ b/drivers/media/video/gspca/stv06xx/stv06xx.h | |||
@@ -93,6 +93,17 @@ struct sd { | |||
93 | 93 | ||
94 | /* Sensor private data */ | 94 | /* Sensor private data */ |
95 | void *sensor_priv; | 95 | void *sensor_priv; |
96 | |||
97 | /* The first 4 lines produced by the stv6422 are no good, this keeps | ||
98 | track of how many bytes we still need to skip during a frame */ | ||
99 | int to_skip; | ||
100 | |||
101 | /* Bridge / Camera type */ | ||
102 | u8 bridge; | ||
103 | #define BRIDGE_STV600 0 | ||
104 | #define BRIDGE_STV602 1 | ||
105 | #define BRIDGE_STV610 2 | ||
106 | #define BRIDGE_ST6422 3 /* With integrated sensor */ | ||
96 | }; | 107 | }; |
97 | 108 | ||
98 | int stv06xx_write_bridge(struct sd *sd, u16 address, u16 i2c_data); | 109 | int stv06xx_write_bridge(struct sd *sd, u16 address, u16 i2c_data); |
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c index b16903814203..3039ec208f3a 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c +++ b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c | |||
@@ -434,7 +434,7 @@ static int hdcs_probe_1x00(struct sd *sd) | |||
434 | hdcs->exp.er = 100; | 434 | hdcs->exp.er = 100; |
435 | 435 | ||
436 | /* | 436 | /* |
437 | * Frame rate on HDCS-1000 0x46D:0x840 depends on PSMP: | 437 | * Frame rate on HDCS-1000 with STV600 depends on PSMP: |
438 | * 4 = doesn't work at all | 438 | * 4 = doesn't work at all |
439 | * 5 = 7.8 fps, | 439 | * 5 = 7.8 fps, |
440 | * 6 = 6.9 fps, | 440 | * 6 = 6.9 fps, |
@@ -443,7 +443,7 @@ static int hdcs_probe_1x00(struct sd *sd) | |||
443 | * 15 = 4.4 fps, | 443 | * 15 = 4.4 fps, |
444 | * 31 = 2.8 fps | 444 | * 31 = 2.8 fps |
445 | * | 445 | * |
446 | * Frame rate on HDCS-1000 0x46D:0x870 depends on PSMP: | 446 | * Frame rate on HDCS-1000 with STV602 depends on PSMP: |
447 | * 15 = doesn't work at all | 447 | * 15 = doesn't work at all |
448 | * 18 = doesn't work at all | 448 | * 18 = doesn't work at all |
449 | * 19 = 7.3 fps | 449 | * 19 = 7.3 fps |
@@ -453,7 +453,7 @@ static int hdcs_probe_1x00(struct sd *sd) | |||
453 | * 24 = 6.3 fps | 453 | * 24 = 6.3 fps |
454 | * 30 = 5.4 fps | 454 | * 30 = 5.4 fps |
455 | */ | 455 | */ |
456 | hdcs->psmp = IS_870(sd) ? 20 : 5; | 456 | hdcs->psmp = (sd->bridge == BRIDGE_STV602) ? 20 : 5; |
457 | 457 | ||
458 | sd->sensor_priv = hdcs; | 458 | sd->sensor_priv = hdcs; |
459 | 459 | ||
@@ -530,7 +530,7 @@ static int hdcs_init(struct sd *sd) | |||
530 | int i, err = 0; | 530 | int i, err = 0; |
531 | 531 | ||
532 | /* Set the STV0602AA in STV0600 emulation mode */ | 532 | /* Set the STV0602AA in STV0600 emulation mode */ |
533 | if (IS_870(sd)) | 533 | if (sd->bridge == BRIDGE_STV602) |
534 | stv06xx_write_bridge(sd, STV_STV0600_EMULATION, 1); | 534 | stv06xx_write_bridge(sd, STV_STV0600_EMULATION, 1); |
535 | 535 | ||
536 | /* Execute the bridge init */ | 536 | /* Execute the bridge init */ |
@@ -558,7 +558,7 @@ static int hdcs_init(struct sd *sd) | |||
558 | return err; | 558 | return err; |
559 | 559 | ||
560 | /* Set PGA sample duration | 560 | /* Set PGA sample duration |
561 | (was 0x7E for IS_870, but caused slow framerate with HDCS-1020) */ | 561 | (was 0x7E for the STV602, but caused slow framerate with HDCS-1020) */ |
562 | if (IS_1020(sd)) | 562 | if (IS_1020(sd)) |
563 | err = stv06xx_write_sensor(sd, HDCS_TCTRL, | 563 | err = stv06xx_write_sensor(sd, HDCS_TCTRL, |
564 | (HDCS_ADC_START_SIG_DUR << 6) | hdcs->psmp); | 564 | (HDCS_ADC_START_SIG_DUR << 6) | hdcs->psmp); |
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h b/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h index e88c42f7d2f8..934b9cebc1ab 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h +++ b/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h | |||
@@ -32,14 +32,13 @@ | |||
32 | 32 | ||
33 | #include "stv06xx.h" | 33 | #include "stv06xx.h" |
34 | 34 | ||
35 | #define IS_850(sd) ((sd)->gspca_dev.dev->descriptor.idProduct == 0x850) | ||
36 | #define IS_870(sd) ((sd)->gspca_dev.dev->descriptor.idProduct == 0x870) | ||
37 | #define IS_1020(sd) ((sd)->sensor == &stv06xx_sensor_hdcs1020) | 35 | #define IS_1020(sd) ((sd)->sensor == &stv06xx_sensor_hdcs1020) |
38 | 36 | ||
39 | extern const struct stv06xx_sensor stv06xx_sensor_vv6410; | 37 | extern const struct stv06xx_sensor stv06xx_sensor_vv6410; |
40 | extern const struct stv06xx_sensor stv06xx_sensor_hdcs1x00; | 38 | extern const struct stv06xx_sensor stv06xx_sensor_hdcs1x00; |
41 | extern const struct stv06xx_sensor stv06xx_sensor_hdcs1020; | 39 | extern const struct stv06xx_sensor stv06xx_sensor_hdcs1020; |
42 | extern const struct stv06xx_sensor stv06xx_sensor_pb0100; | 40 | extern const struct stv06xx_sensor stv06xx_sensor_pb0100; |
41 | extern const struct stv06xx_sensor stv06xx_sensor_st6422; | ||
43 | 42 | ||
44 | struct stv06xx_sensor { | 43 | struct stv06xx_sensor { |
45 | /* Defines the name of a sensor */ | 44 | /* Defines the name of a sensor */ |
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c new file mode 100644 index 000000000000..87cb5b9ddfa7 --- /dev/null +++ b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c | |||
@@ -0,0 +1,453 @@ | |||
1 | /* | ||
2 | * Support for the sensor part which is integrated (I think) into the | ||
3 | * st6422 stv06xx alike bridge, as its integrated there are no i2c writes | ||
4 | * but instead direct bridge writes. | ||
5 | * | ||
6 | * Copyright (c) 2009 Hans de Goede <hdegoede@redhat.com> | ||
7 | * | ||
8 | * Strongly based on qc-usb-messenger, which is: | ||
9 | * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher | ||
10 | * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland | ||
11 | * Copyright (c) 2002, 2003 Tuukka Toivonen | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
26 | * | ||
27 | */ | ||
28 | |||
29 | #include "stv06xx_st6422.h" | ||
30 | |||
31 | static struct v4l2_pix_format st6422_mode[] = { | ||
32 | /* Note we actually get 124 lines of data, of which we skip the 4st | ||
33 | 4 as they are garbage */ | ||
34 | { | ||
35 | 162, | ||
36 | 120, | ||
37 | V4L2_PIX_FMT_SGRBG8, | ||
38 | V4L2_FIELD_NONE, | ||
39 | .sizeimage = 162 * 120, | ||
40 | .bytesperline = 162, | ||
41 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
42 | .priv = 1 | ||
43 | }, | ||
44 | /* Note we actually get 248 lines of data, of which we skip the 4st | ||
45 | 4 as they are garbage, and we tell the app it only gets the | ||
46 | first 240 of the 244 lines it actually gets, so that it ignores | ||
47 | the last 4. */ | ||
48 | { | ||
49 | 324, | ||
50 | 240, | ||
51 | V4L2_PIX_FMT_SGRBG8, | ||
52 | V4L2_FIELD_NONE, | ||
53 | .sizeimage = 324 * 244, | ||
54 | .bytesperline = 324, | ||
55 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
56 | .priv = 0 | ||
57 | }, | ||
58 | }; | ||
59 | |||
60 | static const struct ctrl st6422_ctrl[] = { | ||
61 | #define BRIGHTNESS_IDX 0 | ||
62 | { | ||
63 | { | ||
64 | .id = V4L2_CID_BRIGHTNESS, | ||
65 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
66 | .name = "Brightness", | ||
67 | .minimum = 0, | ||
68 | .maximum = 31, | ||
69 | .step = 1, | ||
70 | .default_value = 3 | ||
71 | }, | ||
72 | .set = st6422_set_brightness, | ||
73 | .get = st6422_get_brightness | ||
74 | }, | ||
75 | #define CONTRAST_IDX 1 | ||
76 | { | ||
77 | { | ||
78 | .id = V4L2_CID_CONTRAST, | ||
79 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
80 | .name = "Contrast", | ||
81 | .minimum = 0, | ||
82 | .maximum = 15, | ||
83 | .step = 1, | ||
84 | .default_value = 11 | ||
85 | }, | ||
86 | .set = st6422_set_contrast, | ||
87 | .get = st6422_get_contrast | ||
88 | }, | ||
89 | #define GAIN_IDX 2 | ||
90 | { | ||
91 | { | ||
92 | .id = V4L2_CID_GAIN, | ||
93 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
94 | .name = "Gain", | ||
95 | .minimum = 0, | ||
96 | .maximum = 255, | ||
97 | .step = 1, | ||
98 | .default_value = 64 | ||
99 | }, | ||
100 | .set = st6422_set_gain, | ||
101 | .get = st6422_get_gain | ||
102 | }, | ||
103 | #define EXPOSURE_IDX 3 | ||
104 | { | ||
105 | { | ||
106 | .id = V4L2_CID_EXPOSURE, | ||
107 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
108 | .name = "Exposure", | ||
109 | .minimum = 0, | ||
110 | .maximum = 1023, | ||
111 | .step = 1, | ||
112 | .default_value = 256 | ||
113 | }, | ||
114 | .set = st6422_set_exposure, | ||
115 | .get = st6422_get_exposure | ||
116 | }, | ||
117 | }; | ||
118 | |||
119 | static int st6422_probe(struct sd *sd) | ||
120 | { | ||
121 | int i; | ||
122 | s32 *sensor_settings; | ||
123 | |||
124 | if (sd->bridge != BRIDGE_ST6422) | ||
125 | return -ENODEV; | ||
126 | |||
127 | info("st6422 sensor detected"); | ||
128 | |||
129 | sensor_settings = kmalloc(ARRAY_SIZE(st6422_ctrl) * sizeof(s32), | ||
130 | GFP_KERNEL); | ||
131 | if (!sensor_settings) | ||
132 | return -ENOMEM; | ||
133 | |||
134 | sd->gspca_dev.cam.cam_mode = st6422_mode; | ||
135 | sd->gspca_dev.cam.nmodes = ARRAY_SIZE(st6422_mode); | ||
136 | sd->desc.ctrls = st6422_ctrl; | ||
137 | sd->desc.nctrls = ARRAY_SIZE(st6422_ctrl); | ||
138 | sd->sensor_priv = sensor_settings; | ||
139 | |||
140 | for (i = 0; i < sd->desc.nctrls; i++) | ||
141 | sensor_settings[i] = st6422_ctrl[i].qctrl.default_value; | ||
142 | |||
143 | return 0; | ||
144 | } | ||
145 | |||
146 | static int st6422_init(struct sd *sd) | ||
147 | { | ||
148 | int err = 0, i; | ||
149 | |||
150 | const u16 st6422_bridge_init[][2] = { | ||
151 | { STV_ISO_ENABLE, 0x00 }, /* disable capture */ | ||
152 | { 0x1436, 0x00 }, | ||
153 | { 0x1432, 0x03 }, /* 0x00-0x1F brightness */ | ||
154 | { 0x143a, 0xF9 }, /* 0x00-0x0F contrast */ | ||
155 | { 0x0509, 0x38 }, /* R */ | ||
156 | { 0x050a, 0x38 }, /* G */ | ||
157 | { 0x050b, 0x38 }, /* B */ | ||
158 | { 0x050c, 0x2A }, | ||
159 | { 0x050d, 0x01 }, | ||
160 | |||
161 | |||
162 | { 0x1431, 0x00 }, /* 0x00-0x07 ??? */ | ||
163 | { 0x1433, 0x34 }, /* 160x120, 0x00-0x01 night filter */ | ||
164 | { 0x1438, 0x18 }, /* 640x480 */ | ||
165 | /* 18 bayes */ | ||
166 | /* 10 compressed? */ | ||
167 | |||
168 | { 0x1439, 0x00 }, | ||
169 | /* antiflimmer?? 0xa2 ger perfekt bild mot monitor */ | ||
170 | |||
171 | { 0x143b, 0x05 }, | ||
172 | { 0x143c, 0x00 }, /* 0x00-0x01 - ??? */ | ||
173 | |||
174 | |||
175 | /* shutter time 0x0000-0x03FF */ | ||
176 | /* low value give good picures on moving objects (but requires much light) */ | ||
177 | /* high value gives good picures in darkness (but tends to be overexposed) */ | ||
178 | { 0x143e, 0x01 }, | ||
179 | { 0x143d, 0x00 }, | ||
180 | |||
181 | { 0x1442, 0xe2 }, | ||
182 | /* write: 1x1x xxxx */ | ||
183 | /* read: 1x1x xxxx */ | ||
184 | /* bit 5 == button pressed and hold if 0 */ | ||
185 | /* write 0xe2,0xea */ | ||
186 | |||
187 | /* 0x144a */ | ||
188 | /* 0x00 init */ | ||
189 | /* bit 7 == button has been pressed, but not handled */ | ||
190 | |||
191 | /* interrupt */ | ||
192 | /* if(urb->iso_frame_desc[i].status == 0x80) { */ | ||
193 | /* if(urb->iso_frame_desc[i].status == 0x88) { */ | ||
194 | |||
195 | { 0x1500, 0xd0 }, | ||
196 | { 0x1500, 0xd0 }, | ||
197 | { 0x1500, 0x50 }, /* 0x00 - 0xFF 0x80 == compr ? */ | ||
198 | |||
199 | { 0x1501, 0xaf }, | ||
200 | /* high val-> ljus area blir morkare. */ | ||
201 | /* low val -> ljus area blir ljusare. */ | ||
202 | { 0x1502, 0xc2 }, | ||
203 | /* high val-> ljus area blir morkare. */ | ||
204 | /* low val -> ljus area blir ljusare. */ | ||
205 | { 0x1503, 0x45 }, | ||
206 | /* high val-> ljus area blir morkare. */ | ||
207 | /* low val -> ljus area blir ljusare. */ | ||
208 | |||
209 | { 0x1505, 0x02 }, | ||
210 | /* 2 : 324x248 80352 bytes */ | ||
211 | /* 7 : 248x162 40176 bytes */ | ||
212 | /* c+f: 162*124 20088 bytes */ | ||
213 | |||
214 | { 0x150e, 0x8e }, | ||
215 | { 0x150f, 0x37 }, | ||
216 | { 0x15c0, 0x00 }, | ||
217 | { 0x15c1, 1023 }, /* 160x120, ISOC_PACKET_SIZE */ | ||
218 | { 0x15c3, 0x08 }, /* 0x04/0x14 ... test pictures ??? */ | ||
219 | |||
220 | |||
221 | { 0x143f, 0x01 }, /* commit settings */ | ||
222 | |||
223 | }; | ||
224 | |||
225 | for (i = 0; i < ARRAY_SIZE(st6422_bridge_init) && !err; i++) { | ||
226 | err = stv06xx_write_bridge(sd, st6422_bridge_init[i][0], | ||
227 | st6422_bridge_init[i][1]); | ||
228 | } | ||
229 | |||
230 | return err; | ||
231 | } | ||
232 | |||
233 | static void st6422_disconnect(struct sd *sd) | ||
234 | { | ||
235 | sd->sensor = NULL; | ||
236 | kfree(sd->sensor_priv); | ||
237 | } | ||
238 | |||
239 | static int st6422_start(struct sd *sd) | ||
240 | { | ||
241 | int err, packet_size; | ||
242 | struct cam *cam = &sd->gspca_dev.cam; | ||
243 | s32 *sensor_settings = sd->sensor_priv; | ||
244 | struct usb_host_interface *alt; | ||
245 | struct usb_interface *intf; | ||
246 | |||
247 | intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface); | ||
248 | alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt); | ||
249 | if (!alt) { | ||
250 | PDEBUG(D_ERR, "Couldn't get altsetting"); | ||
251 | return -EIO; | ||
252 | } | ||
253 | |||
254 | packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); | ||
255 | err = stv06xx_write_bridge(sd, 0x15c1, packet_size); | ||
256 | if (err < 0) | ||
257 | return err; | ||
258 | |||
259 | if (cam->cam_mode[sd->gspca_dev.curr_mode].priv) | ||
260 | err = stv06xx_write_bridge(sd, 0x1505, 0x0f); | ||
261 | else | ||
262 | err = stv06xx_write_bridge(sd, 0x1505, 0x02); | ||
263 | if (err < 0) | ||
264 | return err; | ||
265 | |||
266 | err = st6422_set_brightness(&sd->gspca_dev, | ||
267 | sensor_settings[BRIGHTNESS_IDX]); | ||
268 | if (err < 0) | ||
269 | return err; | ||
270 | |||
271 | err = st6422_set_contrast(&sd->gspca_dev, | ||
272 | sensor_settings[CONTRAST_IDX]); | ||
273 | if (err < 0) | ||
274 | return err; | ||
275 | |||
276 | err = st6422_set_exposure(&sd->gspca_dev, | ||
277 | sensor_settings[EXPOSURE_IDX]); | ||
278 | if (err < 0) | ||
279 | return err; | ||
280 | |||
281 | err = st6422_set_gain(&sd->gspca_dev, | ||
282 | sensor_settings[GAIN_IDX]); | ||
283 | if (err < 0) | ||
284 | return err; | ||
285 | |||
286 | PDEBUG(D_STREAM, "Starting stream"); | ||
287 | |||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | static int st6422_stop(struct sd *sd) | ||
292 | { | ||
293 | PDEBUG(D_STREAM, "Halting stream"); | ||
294 | |||
295 | return 0; | ||
296 | } | ||
297 | |||
298 | static int st6422_get_brightness(struct gspca_dev *gspca_dev, __s32 *val) | ||
299 | { | ||
300 | struct sd *sd = (struct sd *) gspca_dev; | ||
301 | s32 *sensor_settings = sd->sensor_priv; | ||
302 | |||
303 | *val = sensor_settings[BRIGHTNESS_IDX]; | ||
304 | |||
305 | PDEBUG(D_V4L2, "Read brightness %d", *val); | ||
306 | |||
307 | return 0; | ||
308 | } | ||
309 | |||
310 | static int st6422_set_brightness(struct gspca_dev *gspca_dev, __s32 val) | ||
311 | { | ||
312 | int err; | ||
313 | struct sd *sd = (struct sd *) gspca_dev; | ||
314 | s32 *sensor_settings = sd->sensor_priv; | ||
315 | |||
316 | sensor_settings[BRIGHTNESS_IDX] = val; | ||
317 | |||
318 | if (!gspca_dev->streaming) | ||
319 | return 0; | ||
320 | |||
321 | /* val goes from 0 -> 31 */ | ||
322 | PDEBUG(D_V4L2, "Set brightness to %d", val); | ||
323 | err = stv06xx_write_bridge(sd, 0x1432, val); | ||
324 | if (err < 0) | ||
325 | return err; | ||
326 | |||
327 | /* commit settings */ | ||
328 | err = stv06xx_write_bridge(sd, 0x143f, 0x01); | ||
329 | return (err < 0) ? err : 0; | ||
330 | } | ||
331 | |||
332 | static int st6422_get_contrast(struct gspca_dev *gspca_dev, __s32 *val) | ||
333 | { | ||
334 | struct sd *sd = (struct sd *) gspca_dev; | ||
335 | s32 *sensor_settings = sd->sensor_priv; | ||
336 | |||
337 | *val = sensor_settings[CONTRAST_IDX]; | ||
338 | |||
339 | PDEBUG(D_V4L2, "Read contrast %d", *val); | ||
340 | |||
341 | return 0; | ||
342 | } | ||
343 | |||
344 | static int st6422_set_contrast(struct gspca_dev *gspca_dev, __s32 val) | ||
345 | { | ||
346 | int err; | ||
347 | struct sd *sd = (struct sd *) gspca_dev; | ||
348 | s32 *sensor_settings = sd->sensor_priv; | ||
349 | |||
350 | sensor_settings[CONTRAST_IDX] = val; | ||
351 | |||
352 | if (!gspca_dev->streaming) | ||
353 | return 0; | ||
354 | |||
355 | /* Val goes from 0 -> 15 */ | ||
356 | PDEBUG(D_V4L2, "Set contrast to %d\n", val); | ||
357 | err = stv06xx_write_bridge(sd, 0x143a, 0xf0 | val); | ||
358 | if (err < 0) | ||
359 | return err; | ||
360 | |||
361 | /* commit settings */ | ||
362 | err = stv06xx_write_bridge(sd, 0x143f, 0x01); | ||
363 | return (err < 0) ? err : 0; | ||
364 | } | ||
365 | |||
366 | static int st6422_get_gain(struct gspca_dev *gspca_dev, __s32 *val) | ||
367 | { | ||
368 | struct sd *sd = (struct sd *) gspca_dev; | ||
369 | s32 *sensor_settings = sd->sensor_priv; | ||
370 | |||
371 | *val = sensor_settings[GAIN_IDX]; | ||
372 | |||
373 | PDEBUG(D_V4L2, "Read gain %d", *val); | ||
374 | |||
375 | return 0; | ||
376 | } | ||
377 | |||
378 | static int st6422_set_gain(struct gspca_dev *gspca_dev, __s32 val) | ||
379 | { | ||
380 | int err; | ||
381 | struct sd *sd = (struct sd *) gspca_dev; | ||
382 | s32 *sensor_settings = sd->sensor_priv; | ||
383 | |||
384 | sensor_settings[GAIN_IDX] = val; | ||
385 | |||
386 | if (!gspca_dev->streaming) | ||
387 | return 0; | ||
388 | |||
389 | PDEBUG(D_V4L2, "Set gain to %d", val); | ||
390 | |||
391 | /* Set red, green, blue, gain */ | ||
392 | err = stv06xx_write_bridge(sd, 0x0509, val); | ||
393 | if (err < 0) | ||
394 | return err; | ||
395 | |||
396 | err = stv06xx_write_bridge(sd, 0x050a, val); | ||
397 | if (err < 0) | ||
398 | return err; | ||
399 | |||
400 | err = stv06xx_write_bridge(sd, 0x050b, val); | ||
401 | if (err < 0) | ||
402 | return err; | ||
403 | |||
404 | /* 2 mystery writes */ | ||
405 | err = stv06xx_write_bridge(sd, 0x050c, 0x2a); | ||
406 | if (err < 0) | ||
407 | return err; | ||
408 | |||
409 | err = stv06xx_write_bridge(sd, 0x050d, 0x01); | ||
410 | if (err < 0) | ||
411 | return err; | ||
412 | |||
413 | /* commit settings */ | ||
414 | err = stv06xx_write_bridge(sd, 0x143f, 0x01); | ||
415 | return (err < 0) ? err : 0; | ||
416 | } | ||
417 | |||
418 | static int st6422_get_exposure(struct gspca_dev *gspca_dev, __s32 *val) | ||
419 | { | ||
420 | struct sd *sd = (struct sd *) gspca_dev; | ||
421 | s32 *sensor_settings = sd->sensor_priv; | ||
422 | |||
423 | *val = sensor_settings[EXPOSURE_IDX]; | ||
424 | |||
425 | PDEBUG(D_V4L2, "Read exposure %d", *val); | ||
426 | |||
427 | return 0; | ||
428 | } | ||
429 | |||
430 | static int st6422_set_exposure(struct gspca_dev *gspca_dev, __s32 val) | ||
431 | { | ||
432 | int err; | ||
433 | struct sd *sd = (struct sd *) gspca_dev; | ||
434 | s32 *sensor_settings = sd->sensor_priv; | ||
435 | |||
436 | sensor_settings[EXPOSURE_IDX] = val; | ||
437 | |||
438 | if (!gspca_dev->streaming) | ||
439 | return 0; | ||
440 | |||
441 | PDEBUG(D_V4L2, "Set exposure to %d\n", val); | ||
442 | err = stv06xx_write_bridge(sd, 0x143d, val & 0xff); | ||
443 | if (err < 0) | ||
444 | return err; | ||
445 | |||
446 | err = stv06xx_write_bridge(sd, 0x143e, val >> 8); | ||
447 | if (err < 0) | ||
448 | return err; | ||
449 | |||
450 | /* commit settings */ | ||
451 | err = stv06xx_write_bridge(sd, 0x143f, 0x01); | ||
452 | return (err < 0) ? err : 0; | ||
453 | } | ||
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h new file mode 100644 index 000000000000..b2d45fe50522 --- /dev/null +++ b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h | |||
@@ -0,0 +1,59 @@ | |||
1 | /* | ||
2 | * Support for the sensor part which is integrated (I think) into the | ||
3 | * st6422 stv06xx alike bridge, as its integrated there are no i2c writes | ||
4 | * but instead direct bridge writes. | ||
5 | * | ||
6 | * Copyright (c) 2009 Hans de Goede <hdegoede@redhat.com> | ||
7 | * | ||
8 | * Strongly based on qc-usb-messenger, which is: | ||
9 | * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher | ||
10 | * Mark Cave-Ayland, Carlo E Prelz, Dick Streefland | ||
11 | * Copyright (c) 2002, 2003 Tuukka Toivonen | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
26 | * | ||
27 | */ | ||
28 | |||
29 | #ifndef STV06XX_ST6422_H_ | ||
30 | #define STV06XX_ST6422_H_ | ||
31 | |||
32 | #include "stv06xx_sensor.h" | ||
33 | |||
34 | static int st6422_probe(struct sd *sd); | ||
35 | static int st6422_start(struct sd *sd); | ||
36 | static int st6422_init(struct sd *sd); | ||
37 | static int st6422_stop(struct sd *sd); | ||
38 | static void st6422_disconnect(struct sd *sd); | ||
39 | |||
40 | /* V4L2 controls supported by the driver */ | ||
41 | static int st6422_get_brightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
42 | static int st6422_set_brightness(struct gspca_dev *gspca_dev, __s32 val); | ||
43 | static int st6422_get_contrast(struct gspca_dev *gspca_dev, __s32 *val); | ||
44 | static int st6422_set_contrast(struct gspca_dev *gspca_dev, __s32 val); | ||
45 | static int st6422_get_gain(struct gspca_dev *gspca_dev, __s32 *val); | ||
46 | static int st6422_set_gain(struct gspca_dev *gspca_dev, __s32 val); | ||
47 | static int st6422_get_exposure(struct gspca_dev *gspca_dev, __s32 *val); | ||
48 | static int st6422_set_exposure(struct gspca_dev *gspca_dev, __s32 val); | ||
49 | |||
50 | const struct stv06xx_sensor stv06xx_sensor_st6422 = { | ||
51 | .name = "ST6422", | ||
52 | .init = st6422_init, | ||
53 | .probe = st6422_probe, | ||
54 | .start = st6422_start, | ||
55 | .stop = st6422_stop, | ||
56 | .disconnect = st6422_disconnect, | ||
57 | }; | ||
58 | |||
59 | #endif | ||
diff --git a/drivers/media/video/ivtv/ivtv-controls.c b/drivers/media/video/ivtv/ivtv-controls.c index 84995bcf4a75..a3b77ed3f089 100644 --- a/drivers/media/video/ivtv/ivtv-controls.c +++ b/drivers/media/video/ivtv/ivtv-controls.c | |||
@@ -60,6 +60,8 @@ int ivtv_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *qctrl) | |||
60 | 60 | ||
61 | switch (qctrl->id) { | 61 | switch (qctrl->id) { |
62 | /* Standard V4L2 controls */ | 62 | /* Standard V4L2 controls */ |
63 | case V4L2_CID_USER_CLASS: | ||
64 | return v4l2_ctrl_query_fill(qctrl, 0, 0, 0, 0); | ||
63 | case V4L2_CID_BRIGHTNESS: | 65 | case V4L2_CID_BRIGHTNESS: |
64 | case V4L2_CID_HUE: | 66 | case V4L2_CID_HUE: |
65 | case V4L2_CID_SATURATION: | 67 | case V4L2_CID_SATURATION: |
diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c index 459c04cbf69d..4d794b42d6cd 100644 --- a/drivers/media/video/mt9m001.c +++ b/drivers/media/video/mt9m001.c | |||
@@ -280,15 +280,9 @@ static int mt9m001_try_fmt(struct soc_camera_device *icd, | |||
280 | { | 280 | { |
281 | struct v4l2_pix_format *pix = &f->fmt.pix; | 281 | struct v4l2_pix_format *pix = &f->fmt.pix; |
282 | 282 | ||
283 | if (pix->height < 32 + icd->y_skip_top) | 283 | v4l_bound_align_image(&pix->width, 48, 1280, 1, |
284 | pix->height = 32 + icd->y_skip_top; | 284 | &pix->height, 32 + icd->y_skip_top, |
285 | if (pix->height > 1024 + icd->y_skip_top) | 285 | 1024 + icd->y_skip_top, 0, 0); |
286 | pix->height = 1024 + icd->y_skip_top; | ||
287 | if (pix->width < 48) | ||
288 | pix->width = 48; | ||
289 | if (pix->width > 1280) | ||
290 | pix->width = 1280; | ||
291 | pix->width &= ~0x01; /* has to be even, unsure why was ~3 */ | ||
292 | 286 | ||
293 | return 0; | 287 | return 0; |
294 | } | 288 | } |
diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c index f72aeb7c4deb..4207fb342670 100644 --- a/drivers/media/video/mt9t031.c +++ b/drivers/media/video/mt9t031.c | |||
@@ -385,17 +385,9 @@ static int mt9t031_try_fmt(struct soc_camera_device *icd, | |||
385 | { | 385 | { |
386 | struct v4l2_pix_format *pix = &f->fmt.pix; | 386 | struct v4l2_pix_format *pix = &f->fmt.pix; |
387 | 387 | ||
388 | if (pix->height < MT9T031_MIN_HEIGHT) | 388 | v4l_bound_align_image( |
389 | pix->height = MT9T031_MIN_HEIGHT; | 389 | &pix->width, MT9T031_MIN_WIDTH, MT9T031_MAX_WIDTH, 1, |
390 | if (pix->height > MT9T031_MAX_HEIGHT) | 390 | &pix->height, MT9T031_MIN_HEIGHT, MT9T031_MAX_HEIGHT, 1, 0); |
391 | pix->height = MT9T031_MAX_HEIGHT; | ||
392 | if (pix->width < MT9T031_MIN_WIDTH) | ||
393 | pix->width = MT9T031_MIN_WIDTH; | ||
394 | if (pix->width > MT9T031_MAX_WIDTH) | ||
395 | pix->width = MT9T031_MAX_WIDTH; | ||
396 | |||
397 | pix->width &= ~0x01; /* has to be even */ | ||
398 | pix->height &= ~0x01; /* has to be even */ | ||
399 | 391 | ||
400 | return 0; | 392 | return 0; |
401 | } | 393 | } |
diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index be20d312b1dc..dbdcc86ae50d 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c | |||
@@ -364,15 +364,9 @@ static int mt9v022_try_fmt(struct soc_camera_device *icd, | |||
364 | { | 364 | { |
365 | struct v4l2_pix_format *pix = &f->fmt.pix; | 365 | struct v4l2_pix_format *pix = &f->fmt.pix; |
366 | 366 | ||
367 | if (pix->height < 32 + icd->y_skip_top) | 367 | v4l_bound_align_image(&pix->width, 48, 752, 2 /* ? */, |
368 | pix->height = 32 + icd->y_skip_top; | 368 | &pix->height, 32 + icd->y_skip_top, |
369 | if (pix->height > 480 + icd->y_skip_top) | 369 | 480 + icd->y_skip_top, 0, 0); |
370 | pix->height = 480 + icd->y_skip_top; | ||
371 | if (pix->width < 48) | ||
372 | pix->width = 48; | ||
373 | if (pix->width > 752) | ||
374 | pix->width = 752; | ||
375 | pix->width &= ~0x03; /* ? */ | ||
376 | 370 | ||
377 | return 0; | 371 | return 0; |
378 | } | 372 | } |
diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c index 08cfd3e4ae8a..0bc2cf573c76 100644 --- a/drivers/media/video/ov511.c +++ b/drivers/media/video/ov511.c | |||
@@ -211,8 +211,6 @@ static const int i2c_detect_tries = 5; | |||
211 | static struct usb_device_id device_table [] = { | 211 | static struct usb_device_id device_table [] = { |
212 | { USB_DEVICE(VEND_OMNIVISION, PROD_OV511) }, | 212 | { USB_DEVICE(VEND_OMNIVISION, PROD_OV511) }, |
213 | { USB_DEVICE(VEND_OMNIVISION, PROD_OV511PLUS) }, | 213 | { USB_DEVICE(VEND_OMNIVISION, PROD_OV511PLUS) }, |
214 | { USB_DEVICE(VEND_OMNIVISION, PROD_OV518) }, | ||
215 | { USB_DEVICE(VEND_OMNIVISION, PROD_OV518PLUS) }, | ||
216 | { USB_DEVICE(VEND_MATTEL, PROD_ME2CAM) }, | 214 | { USB_DEVICE(VEND_MATTEL, PROD_ME2CAM) }, |
217 | { } /* Terminating entry */ | 215 | { } /* Terminating entry */ |
218 | }; | 216 | }; |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-audio.c b/drivers/media/video/pvrusb2/pvrusb2-audio.c index 10ef1a2c13ea..416933ca607d 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-audio.c +++ b/drivers/media/video/pvrusb2/pvrusb2-audio.c | |||
@@ -48,11 +48,13 @@ static const int routing_scheme0[] = { | |||
48 | MSP_DSP_IN_SCART), | 48 | MSP_DSP_IN_SCART), |
49 | }; | 49 | }; |
50 | 50 | ||
51 | static const struct routing_scheme routing_schemes[] = { | 51 | static const struct routing_scheme routing_def0 = { |
52 | [PVR2_ROUTING_SCHEME_HAUPPAUGE] = { | 52 | .def = routing_scheme0, |
53 | .def = routing_scheme0, | 53 | .cnt = ARRAY_SIZE(routing_scheme0), |
54 | .cnt = ARRAY_SIZE(routing_scheme0), | 54 | }; |
55 | }, | 55 | |
56 | static const struct routing_scheme *routing_schemes[] = { | ||
57 | [PVR2_ROUTING_SCHEME_HAUPPAUGE] = &routing_def0, | ||
56 | }; | 58 | }; |
57 | 59 | ||
58 | void pvr2_msp3400_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) | 60 | void pvr2_msp3400_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) |
@@ -65,7 +67,7 @@ void pvr2_msp3400_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) | |||
65 | pvr2_trace(PVR2_TRACE_CHIPS, "subdev msp3400 v4l2 set_stereo"); | 67 | pvr2_trace(PVR2_TRACE_CHIPS, "subdev msp3400 v4l2 set_stereo"); |
66 | 68 | ||
67 | if ((sid < ARRAY_SIZE(routing_schemes)) && | 69 | if ((sid < ARRAY_SIZE(routing_schemes)) && |
68 | ((sp = routing_schemes + sid) != NULL) && | 70 | ((sp = routing_schemes[sid]) != NULL) && |
69 | (hdw->input_val >= 0) && | 71 | (hdw->input_val >= 0) && |
70 | (hdw->input_val < sp->cnt)) { | 72 | (hdw->input_val < sp->cnt)) { |
71 | input = sp->def[hdw->input_val]; | 73 | input = sp->def[hdw->input_val]; |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c b/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c index 9023adf3fdcc..68980e19409f 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c +++ b/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c | |||
@@ -49,11 +49,13 @@ static const int routing_scheme1[] = { | |||
49 | [PVR2_CVAL_INPUT_SVIDEO] = 0, | 49 | [PVR2_CVAL_INPUT_SVIDEO] = 0, |
50 | }; | 50 | }; |
51 | 51 | ||
52 | static const struct routing_scheme routing_schemes[] = { | 52 | static const struct routing_scheme routing_def1 = { |
53 | [PVR2_ROUTING_SCHEME_ONAIR] = { | 53 | .def = routing_scheme1, |
54 | .def = routing_scheme1, | 54 | .cnt = ARRAY_SIZE(routing_scheme1), |
55 | .cnt = ARRAY_SIZE(routing_scheme1), | 55 | }; |
56 | }, | 56 | |
57 | static const struct routing_scheme *routing_schemes[] = { | ||
58 | [PVR2_ROUTING_SCHEME_ONAIR] = &routing_def1, | ||
57 | }; | 59 | }; |
58 | 60 | ||
59 | 61 | ||
@@ -65,12 +67,11 @@ void pvr2_cs53l32a_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) | |||
65 | u32 input; | 67 | u32 input; |
66 | pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_input(%d)", | 68 | pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_input(%d)", |
67 | hdw->input_val); | 69 | hdw->input_val); |
68 | if ((sid < ARRAY_SIZE(routing_schemes)) && | 70 | sp = (sid < ARRAY_SIZE(routing_schemes)) ? |
69 | ((sp = routing_schemes + sid) != NULL) && | 71 | routing_schemes[sid] : NULL; |
70 | (hdw->input_val >= 0) && | 72 | if ((sp == NULL) || |
71 | (hdw->input_val < sp->cnt)) { | 73 | (hdw->input_val < 0) || |
72 | input = sp->def[hdw->input_val]; | 74 | (hdw->input_val >= sp->cnt)) { |
73 | } else { | ||
74 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, | 75 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, |
75 | "*** WARNING *** subdev v4l2 set_input:" | 76 | "*** WARNING *** subdev v4l2 set_input:" |
76 | " Invalid routing scheme (%u)" | 77 | " Invalid routing scheme (%u)" |
@@ -78,6 +79,7 @@ void pvr2_cs53l32a_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) | |||
78 | sid, hdw->input_val); | 79 | sid, hdw->input_val); |
79 | return; | 80 | return; |
80 | } | 81 | } |
82 | input = sp->def[hdw->input_val]; | ||
81 | sd->ops->audio->s_routing(sd, input, 0, 0); | 83 | sd->ops->audio->s_routing(sd, input, 0, 0); |
82 | } | 84 | } |
83 | } | 85 | } |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c index 05e52358ae49..82c135835753 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c +++ b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c | |||
@@ -68,6 +68,11 @@ static const struct routing_scheme_item routing_scheme0[] = { | |||
68 | }, | 68 | }, |
69 | }; | 69 | }; |
70 | 70 | ||
71 | static const struct routing_scheme routing_def0 = { | ||
72 | .def = routing_scheme0, | ||
73 | .cnt = ARRAY_SIZE(routing_scheme0), | ||
74 | }; | ||
75 | |||
71 | /* Specific to gotview device */ | 76 | /* Specific to gotview device */ |
72 | static const struct routing_scheme_item routing_schemegv[] = { | 77 | static const struct routing_scheme_item routing_schemegv[] = { |
73 | [PVR2_CVAL_INPUT_TV] = { | 78 | [PVR2_CVAL_INPUT_TV] = { |
@@ -90,15 +95,14 @@ static const struct routing_scheme_item routing_schemegv[] = { | |||
90 | }, | 95 | }, |
91 | }; | 96 | }; |
92 | 97 | ||
93 | static const struct routing_scheme routing_schemes[] = { | 98 | static const struct routing_scheme routing_defgv = { |
94 | [PVR2_ROUTING_SCHEME_HAUPPAUGE] = { | 99 | .def = routing_schemegv, |
95 | .def = routing_scheme0, | 100 | .cnt = ARRAY_SIZE(routing_schemegv), |
96 | .cnt = ARRAY_SIZE(routing_scheme0), | 101 | }; |
97 | }, | 102 | |
98 | [PVR2_ROUTING_SCHEME_GOTVIEW] = { | 103 | static const struct routing_scheme *routing_schemes[] = { |
99 | .def = routing_schemegv, | 104 | [PVR2_ROUTING_SCHEME_HAUPPAUGE] = &routing_def0, |
100 | .cnt = ARRAY_SIZE(routing_schemegv), | 105 | [PVR2_ROUTING_SCHEME_GOTVIEW] = &routing_defgv, |
101 | }, | ||
102 | }; | 106 | }; |
103 | 107 | ||
104 | void pvr2_cx25840_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) | 108 | void pvr2_cx25840_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) |
@@ -110,13 +114,11 @@ void pvr2_cx25840_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) | |||
110 | const struct routing_scheme *sp; | 114 | const struct routing_scheme *sp; |
111 | unsigned int sid = hdw->hdw_desc->signal_routing_scheme; | 115 | unsigned int sid = hdw->hdw_desc->signal_routing_scheme; |
112 | 116 | ||
113 | if ((sid < ARRAY_SIZE(routing_schemes)) && | 117 | sp = (sid < ARRAY_SIZE(routing_schemes)) ? |
114 | ((sp = routing_schemes + sid) != NULL) && | 118 | routing_schemes[sid] : NULL; |
115 | (hdw->input_val >= 0) && | 119 | if ((sp == NULL) || |
116 | (hdw->input_val < sp->cnt)) { | 120 | (hdw->input_val < 0) || |
117 | vid_input = sp->def[hdw->input_val].vid; | 121 | (hdw->input_val >= sp->cnt)) { |
118 | aud_input = sp->def[hdw->input_val].aud; | ||
119 | } else { | ||
120 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, | 122 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, |
121 | "*** WARNING *** subdev cx2584x set_input:" | 123 | "*** WARNING *** subdev cx2584x set_input:" |
122 | " Invalid routing scheme (%u)" | 124 | " Invalid routing scheme (%u)" |
@@ -124,7 +126,8 @@ void pvr2_cx25840_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) | |||
124 | sid, hdw->input_val); | 126 | sid, hdw->input_val); |
125 | return; | 127 | return; |
126 | } | 128 | } |
127 | 129 | vid_input = sp->def[hdw->input_val].vid; | |
130 | aud_input = sp->def[hdw->input_val].aud; | ||
128 | pvr2_trace(PVR2_TRACE_CHIPS, | 131 | pvr2_trace(PVR2_TRACE_CHIPS, |
129 | "subdev cx2584x set_input vid=0x%x aud=0x%x", | 132 | "subdev cx2584x set_input vid=0x%x aud=0x%x", |
130 | vid_input, aud_input); | 133 | vid_input, aud_input); |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 0c745b142fb7..cbc388729d77 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c | |||
@@ -85,8 +85,8 @@ MODULE_PARM_DESC(video_std,"specify initial video standard"); | |||
85 | module_param_array(tolerance, int, NULL, 0444); | 85 | module_param_array(tolerance, int, NULL, 0444); |
86 | MODULE_PARM_DESC(tolerance,"specify stream error tolerance"); | 86 | MODULE_PARM_DESC(tolerance,"specify stream error tolerance"); |
87 | 87 | ||
88 | /* US Broadcast channel 7 (175.25 MHz) */ | 88 | /* US Broadcast channel 3 (61.25 MHz), to help with testing */ |
89 | static int default_tv_freq = 175250000L; | 89 | static int default_tv_freq = 61250000L; |
90 | /* 104.3 MHz, a usable FM station for my area */ | 90 | /* 104.3 MHz, a usable FM station for my area */ |
91 | static int default_radio_freq = 104300000L; | 91 | static int default_radio_freq = 104300000L; |
92 | 92 | ||
@@ -1987,6 +1987,34 @@ static unsigned int pvr2_copy_i2c_addr_list( | |||
1987 | } | 1987 | } |
1988 | 1988 | ||
1989 | 1989 | ||
1990 | static void pvr2_hdw_cx25840_vbi_hack(struct pvr2_hdw *hdw) | ||
1991 | { | ||
1992 | /* | ||
1993 | Mike Isely <isely@pobox.com> 19-Nov-2006 - This bit of nuttiness | ||
1994 | for cx25840 causes that module to correctly set up its video | ||
1995 | scaling. This is really a problem in the cx25840 module itself, | ||
1996 | but we work around it here. The problem has not been seen in | ||
1997 | ivtv because there VBI is supported and set up. We don't do VBI | ||
1998 | here (at least not yet) and thus we never attempted to even set | ||
1999 | it up. | ||
2000 | */ | ||
2001 | struct v4l2_format fmt; | ||
2002 | if (hdw->decoder_client_id != PVR2_CLIENT_ID_CX25840) { | ||
2003 | /* We're not using a cx25840 so don't enable the hack */ | ||
2004 | return; | ||
2005 | } | ||
2006 | |||
2007 | pvr2_trace(PVR2_TRACE_INIT, | ||
2008 | "Module ID %u:" | ||
2009 | " Executing cx25840 VBI hack", | ||
2010 | hdw->decoder_client_id); | ||
2011 | memset(&fmt, 0, sizeof(fmt)); | ||
2012 | fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; | ||
2013 | v4l2_device_call_all(&hdw->v4l2_dev, hdw->decoder_client_id, | ||
2014 | video, s_fmt, &fmt); | ||
2015 | } | ||
2016 | |||
2017 | |||
1990 | static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, | 2018 | static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, |
1991 | const struct pvr2_device_client_desc *cd) | 2019 | const struct pvr2_device_client_desc *cd) |
1992 | { | 2020 | { |
@@ -2078,30 +2106,6 @@ static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw, | |||
2078 | /* client-specific setup... */ | 2106 | /* client-specific setup... */ |
2079 | switch (mid) { | 2107 | switch (mid) { |
2080 | case PVR2_CLIENT_ID_CX25840: | 2108 | case PVR2_CLIENT_ID_CX25840: |
2081 | hdw->decoder_client_id = mid; | ||
2082 | { | ||
2083 | /* | ||
2084 | Mike Isely <isely@pobox.com> 19-Nov-2006 - This | ||
2085 | bit of nuttiness for cx25840 causes that module | ||
2086 | to correctly set up its video scaling. This is | ||
2087 | really a problem in the cx25840 module itself, | ||
2088 | but we work around it here. The problem has not | ||
2089 | been seen in ivtv because there VBI is supported | ||
2090 | and set up. We don't do VBI here (at least not | ||
2091 | yet) and thus we never attempted to even set it | ||
2092 | up. | ||
2093 | */ | ||
2094 | struct v4l2_format fmt; | ||
2095 | pvr2_trace(PVR2_TRACE_INIT, | ||
2096 | "Module ID %u:" | ||
2097 | " Executing cx25840 VBI hack", | ||
2098 | mid); | ||
2099 | memset(&fmt, 0, sizeof(fmt)); | ||
2100 | fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; | ||
2101 | v4l2_device_call_all(&hdw->v4l2_dev, mid, | ||
2102 | video, s_fmt, &fmt); | ||
2103 | } | ||
2104 | break; | ||
2105 | case PVR2_CLIENT_ID_SAA7115: | 2109 | case PVR2_CLIENT_ID_SAA7115: |
2106 | hdw->decoder_client_id = mid; | 2110 | hdw->decoder_client_id = mid; |
2107 | break; | 2111 | break; |
@@ -2202,6 +2206,8 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) | |||
2202 | cptr->info->set_value(cptr,~0,cptr->info->default_value); | 2206 | cptr->info->set_value(cptr,~0,cptr->info->default_value); |
2203 | } | 2207 | } |
2204 | 2208 | ||
2209 | pvr2_hdw_cx25840_vbi_hack(hdw); | ||
2210 | |||
2205 | /* Set up special default values for the television and radio | 2211 | /* Set up special default values for the television and radio |
2206 | frequencies here. It's not really important what these defaults | 2212 | frequencies here. It's not really important what these defaults |
2207 | are, but I set them to something usable in the Chicago area just | 2213 | are, but I set them to something usable in the Chicago area just |
@@ -2954,6 +2960,7 @@ static void pvr2_subdev_update(struct pvr2_hdw *hdw) | |||
2954 | vs = hdw->std_mask_cur; | 2960 | vs = hdw->std_mask_cur; |
2955 | v4l2_device_call_all(&hdw->v4l2_dev, 0, | 2961 | v4l2_device_call_all(&hdw->v4l2_dev, 0, |
2956 | core, s_std, vs); | 2962 | core, s_std, vs); |
2963 | pvr2_hdw_cx25840_vbi_hack(hdw); | ||
2957 | } | 2964 | } |
2958 | hdw->tuner_signal_stale = !0; | 2965 | hdw->tuner_signal_stale = !0; |
2959 | hdw->cropcap_stale = !0; | 2966 | hdw->cropcap_stale = !0; |
@@ -4076,6 +4083,7 @@ int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *hdw) | |||
4076 | if (hdw->decoder_client_id) { | 4083 | if (hdw->decoder_client_id) { |
4077 | v4l2_device_call_all(&hdw->v4l2_dev, hdw->decoder_client_id, | 4084 | v4l2_device_call_all(&hdw->v4l2_dev, hdw->decoder_client_id, |
4078 | core, reset, 0); | 4085 | core, reset, 0); |
4086 | pvr2_hdw_cx25840_vbi_hack(hdw); | ||
4079 | return 0; | 4087 | return 0; |
4080 | } | 4088 | } |
4081 | pvr2_trace(PVR2_TRACE_INIT, | 4089 | pvr2_trace(PVR2_TRACE_INIT, |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c index d2fe7c8f2c3a..4c96cf48c796 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c +++ b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c | |||
@@ -54,6 +54,11 @@ static const int routing_scheme0[] = { | |||
54 | [PVR2_CVAL_INPUT_SVIDEO] = SAA7115_SVIDEO2, | 54 | [PVR2_CVAL_INPUT_SVIDEO] = SAA7115_SVIDEO2, |
55 | }; | 55 | }; |
56 | 56 | ||
57 | static const struct routing_scheme routing_def0 = { | ||
58 | .def = routing_scheme0, | ||
59 | .cnt = ARRAY_SIZE(routing_scheme0), | ||
60 | }; | ||
61 | |||
57 | static const int routing_scheme1[] = { | 62 | static const int routing_scheme1[] = { |
58 | [PVR2_CVAL_INPUT_TV] = SAA7115_COMPOSITE4, | 63 | [PVR2_CVAL_INPUT_TV] = SAA7115_COMPOSITE4, |
59 | [PVR2_CVAL_INPUT_RADIO] = SAA7115_COMPOSITE5, | 64 | [PVR2_CVAL_INPUT_RADIO] = SAA7115_COMPOSITE5, |
@@ -61,15 +66,14 @@ static const int routing_scheme1[] = { | |||
61 | [PVR2_CVAL_INPUT_SVIDEO] = SAA7115_SVIDEO2, /* or SVIDEO0, it seems */ | 66 | [PVR2_CVAL_INPUT_SVIDEO] = SAA7115_SVIDEO2, /* or SVIDEO0, it seems */ |
62 | }; | 67 | }; |
63 | 68 | ||
64 | static const struct routing_scheme routing_schemes[] = { | 69 | static const struct routing_scheme routing_def1 = { |
65 | [PVR2_ROUTING_SCHEME_HAUPPAUGE] = { | 70 | .def = routing_scheme1, |
66 | .def = routing_scheme0, | 71 | .cnt = ARRAY_SIZE(routing_scheme1), |
67 | .cnt = ARRAY_SIZE(routing_scheme0), | 72 | }; |
68 | }, | 73 | |
69 | [PVR2_ROUTING_SCHEME_ONAIR] = { | 74 | static const struct routing_scheme *routing_schemes[] = { |
70 | .def = routing_scheme1, | 75 | [PVR2_ROUTING_SCHEME_HAUPPAUGE] = &routing_def0, |
71 | .cnt = ARRAY_SIZE(routing_scheme1), | 76 | [PVR2_ROUTING_SCHEME_ONAIR] = &routing_def1, |
72 | }, | ||
73 | }; | 77 | }; |
74 | 78 | ||
75 | void pvr2_saa7115_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) | 79 | void pvr2_saa7115_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) |
@@ -81,12 +85,12 @@ void pvr2_saa7115_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) | |||
81 | 85 | ||
82 | pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_input(%d)", | 86 | pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_input(%d)", |
83 | hdw->input_val); | 87 | hdw->input_val); |
84 | if ((sid < ARRAY_SIZE(routing_schemes)) && | 88 | |
85 | ((sp = routing_schemes + sid) != NULL) && | 89 | sp = (sid < ARRAY_SIZE(routing_schemes)) ? |
86 | (hdw->input_val >= 0) && | 90 | routing_schemes[sid] : NULL; |
87 | (hdw->input_val < sp->cnt)) { | 91 | if ((sp == NULL) || |
88 | input = sp->def[hdw->input_val]; | 92 | (hdw->input_val < 0) || |
89 | } else { | 93 | (hdw->input_val >= sp->cnt)) { |
90 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, | 94 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, |
91 | "*** WARNING *** subdev v4l2 set_input:" | 95 | "*** WARNING *** subdev v4l2 set_input:" |
92 | " Invalid routing scheme (%u)" | 96 | " Invalid routing scheme (%u)" |
@@ -94,6 +98,7 @@ void pvr2_saa7115_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd) | |||
94 | sid, hdw->input_val); | 98 | sid, hdw->input_val); |
95 | return; | 99 | return; |
96 | } | 100 | } |
101 | input = sp->def[hdw->input_val]; | ||
97 | sd->ops->video->s_routing(sd, input, 0, 0); | 102 | sd->ops->video->s_routing(sd, input, 0, 0); |
98 | } | 103 | } |
99 | } | 104 | } |
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index f60de40fd21f..46e0d8ad880f 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c | |||
@@ -163,13 +163,6 @@ | |||
163 | CICR0_EOFM | CICR0_FOM) | 163 | CICR0_EOFM | CICR0_FOM) |
164 | 164 | ||
165 | /* | 165 | /* |
166 | * YUV422P picture size should be a multiple of 16, so the heuristic aligns | ||
167 | * height, width on 4 byte boundaries to reach the 16 multiple for the size. | ||
168 | */ | ||
169 | #define YUV422P_X_Y_ALIGN 4 | ||
170 | #define YUV422P_SIZE_ALIGN YUV422P_X_Y_ALIGN * YUV422P_X_Y_ALIGN | ||
171 | |||
172 | /* | ||
173 | * Structures | 166 | * Structures |
174 | */ | 167 | */ |
175 | enum pxa_camera_active_dma { | 168 | enum pxa_camera_active_dma { |
@@ -1398,28 +1391,15 @@ static int pxa_camera_try_fmt(struct soc_camera_device *icd, | |||
1398 | return -EINVAL; | 1391 | return -EINVAL; |
1399 | } | 1392 | } |
1400 | 1393 | ||
1401 | /* limit to pxa hardware capabilities */ | ||
1402 | if (pix->height < 32) | ||
1403 | pix->height = 32; | ||
1404 | if (pix->height > 2048) | ||
1405 | pix->height = 2048; | ||
1406 | if (pix->width < 48) | ||
1407 | pix->width = 48; | ||
1408 | if (pix->width > 2048) | ||
1409 | pix->width = 2048; | ||
1410 | pix->width &= ~0x01; | ||
1411 | |||
1412 | /* | 1394 | /* |
1413 | * YUV422P planar format requires images size to be a 16 bytes | 1395 | * Limit to pxa hardware capabilities. YUV422P planar format requires |
1414 | * multiple. If not, zeros will be inserted between Y and U planes, and | 1396 | * images size to be a multiple of 16 bytes. If not, zeros will be |
1415 | * U and V planes, and YUV422P standard would be violated. | 1397 | * inserted between Y and U planes, and U and V planes, which violates |
1398 | * the YUV422P standard. | ||
1416 | */ | 1399 | */ |
1417 | if (xlate->host_fmt->fourcc == V4L2_PIX_FMT_YUV422P) { | 1400 | v4l_bound_align_image(&pix->width, 48, 2048, 1, |
1418 | if (!IS_ALIGNED(pix->width * pix->height, YUV422P_SIZE_ALIGN)) | 1401 | &pix->height, 32, 2048, 0, |
1419 | pix->height = ALIGN(pix->height, YUV422P_X_Y_ALIGN); | 1402 | xlate->host_fmt->fourcc == V4L2_PIX_FMT_YUV422P ? 4 : 0); |
1420 | if (!IS_ALIGNED(pix->width * pix->height, YUV422P_SIZE_ALIGN)) | ||
1421 | pix->width = ALIGN(pix->width, YUV422P_X_Y_ALIGN); | ||
1422 | } | ||
1423 | 1403 | ||
1424 | pix->bytesperline = pix->width * | 1404 | pix->bytesperline = pix->width * |
1425 | DIV_ROUND_UP(xlate->host_fmt->depth, 8); | 1405 | DIV_ROUND_UP(xlate->host_fmt->depth, 8); |
diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index e305c1674cee..ba87128542e0 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c | |||
@@ -1640,15 +1640,8 @@ static int saa7134_try_fmt_vid_cap(struct file *file, void *priv, | |||
1640 | } | 1640 | } |
1641 | 1641 | ||
1642 | f->fmt.pix.field = field; | 1642 | f->fmt.pix.field = field; |
1643 | if (f->fmt.pix.width < 48) | 1643 | v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2, |
1644 | f->fmt.pix.width = 48; | 1644 | &f->fmt.pix.height, 32, maxh, 0, 0); |
1645 | if (f->fmt.pix.height < 32) | ||
1646 | f->fmt.pix.height = 32; | ||
1647 | if (f->fmt.pix.width > maxw) | ||
1648 | f->fmt.pix.width = maxw; | ||
1649 | if (f->fmt.pix.height > maxh) | ||
1650 | f->fmt.pix.height = maxh; | ||
1651 | f->fmt.pix.width &= ~0x03; | ||
1652 | f->fmt.pix.bytesperline = | 1645 | f->fmt.pix.bytesperline = |
1653 | (f->fmt.pix.width * fmt->depth) >> 3; | 1646 | (f->fmt.pix.width * fmt->depth) >> 3; |
1654 | f->fmt.pix.sizeimage = | 1647 | f->fmt.pix.sizeimage = |
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index d369e8409ab8..0db88a53d92c 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c | |||
@@ -689,16 +689,8 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, | |||
689 | 689 | ||
690 | /* FIXME: calculate using depth and bus width */ | 690 | /* FIXME: calculate using depth and bus width */ |
691 | 691 | ||
692 | if (f->fmt.pix.height < 4) | 692 | v4l_bound_align_image(&f->fmt.pix.width, 2, 2560, 1, |
693 | f->fmt.pix.height = 4; | 693 | &f->fmt.pix.height, 4, 1920, 2, 0); |
694 | if (f->fmt.pix.height > 1920) | ||
695 | f->fmt.pix.height = 1920; | ||
696 | if (f->fmt.pix.width < 2) | ||
697 | f->fmt.pix.width = 2; | ||
698 | if (f->fmt.pix.width > 2560) | ||
699 | f->fmt.pix.width = 2560; | ||
700 | f->fmt.pix.width &= ~0x01; | ||
701 | f->fmt.pix.height &= ~0x03; | ||
702 | 694 | ||
703 | f->fmt.pix.bytesperline = f->fmt.pix.width * | 695 | f->fmt.pix.bytesperline = f->fmt.pix.width * |
704 | DIV_ROUND_UP(xlate->host_fmt->depth, 8); | 696 | DIV_ROUND_UP(xlate->host_fmt->depth, 8); |
diff --git a/drivers/media/video/tcm825x.c b/drivers/media/video/tcm825x.c index b30c49248217..b90e9da3167d 100644 --- a/drivers/media/video/tcm825x.c +++ b/drivers/media/video/tcm825x.c | |||
@@ -878,7 +878,7 @@ static int tcm825x_probe(struct i2c_client *client, | |||
878 | return rval; | 878 | return rval; |
879 | } | 879 | } |
880 | 880 | ||
881 | static int __exit tcm825x_remove(struct i2c_client *client) | 881 | static int tcm825x_remove(struct i2c_client *client) |
882 | { | 882 | { |
883 | struct tcm825x_sensor *sensor = i2c_get_clientdata(client); | 883 | struct tcm825x_sensor *sensor = i2c_get_clientdata(client); |
884 | 884 | ||
@@ -902,7 +902,7 @@ static struct i2c_driver tcm825x_i2c_driver = { | |||
902 | .name = TCM825X_NAME, | 902 | .name = TCM825X_NAME, |
903 | }, | 903 | }, |
904 | .probe = tcm825x_probe, | 904 | .probe = tcm825x_probe, |
905 | .remove = __exit_p(tcm825x_remove), | 905 | .remove = tcm825x_remove, |
906 | .id_table = tcm825x_id, | 906 | .id_table = tcm825x_id, |
907 | }; | 907 | }; |
908 | 908 | ||
diff --git a/drivers/media/video/usbvideo/Kconfig b/drivers/media/video/usbvideo/Kconfig index e4cb99c1f94b..adb1c044ad7d 100644 --- a/drivers/media/video/usbvideo/Kconfig +++ b/drivers/media/video/usbvideo/Kconfig | |||
@@ -38,10 +38,13 @@ config USB_KONICAWC | |||
38 | module will be called konicawc. | 38 | module will be called konicawc. |
39 | 39 | ||
40 | config USB_QUICKCAM_MESSENGER | 40 | config USB_QUICKCAM_MESSENGER |
41 | tristate "USB Logitech Quickcam Messenger" | 41 | tristate "USB Logitech Quickcam Messenger (DEPRECATED)" |
42 | depends on VIDEO_V4L1 | 42 | depends on VIDEO_V4L1 |
43 | select VIDEO_USBVIDEO | 43 | select VIDEO_USBVIDEO |
44 | ---help--- | 44 | ---help--- |
45 | This driver is DEPRECATED please use the gspca stv06xx module | ||
46 | instead. | ||
47 | |||
45 | Say Y or M here to enable support for the USB Logitech Quickcam | 48 | Say Y or M here to enable support for the USB Logitech Quickcam |
46 | Messenger webcam. | 49 | Messenger webcam. |
47 | 50 | ||
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index f96475626da7..b91d66a767d7 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c | |||
@@ -802,6 +802,17 @@ struct v4l2_subdev *v4l2_i2c_new_subdev(struct v4l2_device *v4l2_dev, | |||
802 | /* Decrease the module use count to match the first try_module_get. */ | 802 | /* Decrease the module use count to match the first try_module_get. */ |
803 | module_put(client->driver->driver.owner); | 803 | module_put(client->driver->driver.owner); |
804 | 804 | ||
805 | if (sd) { | ||
806 | /* We return errors from v4l2_subdev_call only if we have the | ||
807 | callback as the .s_config is not mandatory */ | ||
808 | int err = v4l2_subdev_call(sd, core, s_config, 0, NULL); | ||
809 | |||
810 | if (err && err != -ENOIOCTLCMD) { | ||
811 | v4l2_device_unregister_subdev(sd); | ||
812 | sd = NULL; | ||
813 | } | ||
814 | } | ||
815 | |||
805 | error: | 816 | error: |
806 | /* If we have a client but no subdev, then something went wrong and | 817 | /* If we have a client but no subdev, then something went wrong and |
807 | we must unregister the client. */ | 818 | we must unregister the client. */ |
@@ -852,6 +863,17 @@ struct v4l2_subdev *v4l2_i2c_new_probed_subdev(struct v4l2_device *v4l2_dev, | |||
852 | /* Decrease the module use count to match the first try_module_get. */ | 863 | /* Decrease the module use count to match the first try_module_get. */ |
853 | module_put(client->driver->driver.owner); | 864 | module_put(client->driver->driver.owner); |
854 | 865 | ||
866 | if (sd) { | ||
867 | /* We return errors from v4l2_subdev_call only if we have the | ||
868 | callback as the .s_config is not mandatory */ | ||
869 | int err = v4l2_subdev_call(sd, core, s_config, 0, NULL); | ||
870 | |||
871 | if (err && err != -ENOIOCTLCMD) { | ||
872 | v4l2_device_unregister_subdev(sd); | ||
873 | sd = NULL; | ||
874 | } | ||
875 | } | ||
876 | |||
855 | error: | 877 | error: |
856 | /* If we have a client but no subdev, then something went wrong and | 878 | /* If we have a client but no subdev, then something went wrong and |
857 | we must unregister the client. */ | 879 | we must unregister the client. */ |
@@ -872,6 +894,89 @@ struct v4l2_subdev *v4l2_i2c_new_probed_subdev_addr(struct v4l2_device *v4l2_dev | |||
872 | } | 894 | } |
873 | EXPORT_SYMBOL_GPL(v4l2_i2c_new_probed_subdev_addr); | 895 | EXPORT_SYMBOL_GPL(v4l2_i2c_new_probed_subdev_addr); |
874 | 896 | ||
897 | /* Load an i2c sub-device. */ | ||
898 | struct v4l2_subdev *v4l2_i2c_new_subdev_board(struct v4l2_device *v4l2_dev, | ||
899 | struct i2c_adapter *adapter, const char *module_name, | ||
900 | struct i2c_board_info *info, const unsigned short *probe_addrs) | ||
901 | { | ||
902 | struct v4l2_subdev *sd = NULL; | ||
903 | struct i2c_client *client; | ||
904 | |||
905 | BUG_ON(!v4l2_dev); | ||
906 | |||
907 | if (module_name) | ||
908 | request_module(module_name); | ||
909 | |||
910 | /* Create the i2c client */ | ||
911 | if (info->addr == 0 && probe_addrs) | ||
912 | client = i2c_new_probed_device(adapter, info, probe_addrs); | ||
913 | else | ||
914 | client = i2c_new_device(adapter, info); | ||
915 | |||
916 | /* Note: by loading the module first we are certain that c->driver | ||
917 | will be set if the driver was found. If the module was not loaded | ||
918 | first, then the i2c core tries to delay-load the module for us, | ||
919 | and then c->driver is still NULL until the module is finally | ||
920 | loaded. This delay-load mechanism doesn't work if other drivers | ||
921 | want to use the i2c device, so explicitly loading the module | ||
922 | is the best alternative. */ | ||
923 | if (client == NULL || client->driver == NULL) | ||
924 | goto error; | ||
925 | |||
926 | /* Lock the module so we can safely get the v4l2_subdev pointer */ | ||
927 | if (!try_module_get(client->driver->driver.owner)) | ||
928 | goto error; | ||
929 | sd = i2c_get_clientdata(client); | ||
930 | |||
931 | /* Register with the v4l2_device which increases the module's | ||
932 | use count as well. */ | ||
933 | if (v4l2_device_register_subdev(v4l2_dev, sd)) | ||
934 | sd = NULL; | ||
935 | /* Decrease the module use count to match the first try_module_get. */ | ||
936 | module_put(client->driver->driver.owner); | ||
937 | |||
938 | if (sd) { | ||
939 | /* We return errors from v4l2_subdev_call only if we have the | ||
940 | callback as the .s_config is not mandatory */ | ||
941 | int err = v4l2_subdev_call(sd, core, s_config, | ||
942 | info->irq, info->platform_data); | ||
943 | |||
944 | if (err && err != -ENOIOCTLCMD) { | ||
945 | v4l2_device_unregister_subdev(sd); | ||
946 | sd = NULL; | ||
947 | } | ||
948 | } | ||
949 | |||
950 | error: | ||
951 | /* If we have a client but no subdev, then something went wrong and | ||
952 | we must unregister the client. */ | ||
953 | if (client && sd == NULL) | ||
954 | i2c_unregister_device(client); | ||
955 | return sd; | ||
956 | } | ||
957 | EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev_board); | ||
958 | |||
959 | struct v4l2_subdev *v4l2_i2c_new_subdev_cfg(struct v4l2_device *v4l2_dev, | ||
960 | struct i2c_adapter *adapter, | ||
961 | const char *module_name, const char *client_type, | ||
962 | int irq, void *platform_data, | ||
963 | u8 addr, const unsigned short *probe_addrs) | ||
964 | { | ||
965 | struct i2c_board_info info; | ||
966 | |||
967 | /* Setup the i2c board info with the device type and | ||
968 | the device address. */ | ||
969 | memset(&info, 0, sizeof(info)); | ||
970 | strlcpy(info.type, client_type, sizeof(info.type)); | ||
971 | info.addr = addr; | ||
972 | info.irq = irq; | ||
973 | info.platform_data = platform_data; | ||
974 | |||
975 | return v4l2_i2c_new_subdev_board(v4l2_dev, adapter, module_name, | ||
976 | &info, probe_addrs); | ||
977 | } | ||
978 | EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev_cfg); | ||
979 | |||
875 | /* Return i2c client address of v4l2_subdev. */ | 980 | /* Return i2c client address of v4l2_subdev. */ |
876 | unsigned short v4l2_i2c_subdev_addr(struct v4l2_subdev *sd) | 981 | unsigned short v4l2_i2c_subdev_addr(struct v4l2_subdev *sd) |
877 | { | 982 | { |
@@ -916,4 +1021,78 @@ const unsigned short *v4l2_i2c_tuner_addrs(enum v4l2_i2c_tuner_type type) | |||
916 | } | 1021 | } |
917 | EXPORT_SYMBOL_GPL(v4l2_i2c_tuner_addrs); | 1022 | EXPORT_SYMBOL_GPL(v4l2_i2c_tuner_addrs); |
918 | 1023 | ||
919 | #endif | 1024 | #endif /* defined(CONFIG_I2C) */ |
1025 | |||
1026 | /* Clamp x to be between min and max, aligned to a multiple of 2^align. min | ||
1027 | * and max don't have to be aligned, but there must be at least one valid | ||
1028 | * value. E.g., min=17,max=31,align=4 is not allowed as there are no multiples | ||
1029 | * of 16 between 17 and 31. */ | ||
1030 | static unsigned int clamp_align(unsigned int x, unsigned int min, | ||
1031 | unsigned int max, unsigned int align) | ||
1032 | { | ||
1033 | /* Bits that must be zero to be aligned */ | ||
1034 | unsigned int mask = ~((1 << align) - 1); | ||
1035 | |||
1036 | /* Round to nearest aligned value */ | ||
1037 | if (align) | ||
1038 | x = (x + (1 << (align - 1))) & mask; | ||
1039 | |||
1040 | /* Clamp to aligned value of min and max */ | ||
1041 | if (x < min) | ||
1042 | x = (min + ~mask) & mask; | ||
1043 | else if (x > max) | ||
1044 | x = max & mask; | ||
1045 | |||
1046 | return x; | ||
1047 | } | ||
1048 | |||
1049 | /* Bound an image to have a width between wmin and wmax, and height between | ||
1050 | * hmin and hmax, inclusive. Additionally, the width will be a multiple of | ||
1051 | * 2^walign, the height will be a multiple of 2^halign, and the overall size | ||
1052 | * (width*height) will be a multiple of 2^salign. The image may be shrunk | ||
1053 | * or enlarged to fit the alignment constraints. | ||
1054 | * | ||
1055 | * The width or height maximum must not be smaller than the corresponding | ||
1056 | * minimum. The alignments must not be so high there are no possible image | ||
1057 | * sizes within the allowed bounds. wmin and hmin must be at least 1 | ||
1058 | * (don't use 0). If you don't care about a certain alignment, specify 0, | ||
1059 | * as 2^0 is 1 and one byte alignment is equivalent to no alignment. If | ||
1060 | * you only want to adjust downward, specify a maximum that's the same as | ||
1061 | * the initial value. | ||
1062 | */ | ||
1063 | void v4l_bound_align_image(u32 *w, unsigned int wmin, unsigned int wmax, | ||
1064 | unsigned int walign, | ||
1065 | u32 *h, unsigned int hmin, unsigned int hmax, | ||
1066 | unsigned int halign, unsigned int salign) | ||
1067 | { | ||
1068 | *w = clamp_align(*w, wmin, wmax, walign); | ||
1069 | *h = clamp_align(*h, hmin, hmax, halign); | ||
1070 | |||
1071 | /* Usually we don't need to align the size and are done now. */ | ||
1072 | if (!salign) | ||
1073 | return; | ||
1074 | |||
1075 | /* How much alignment do we have? */ | ||
1076 | walign = __ffs(*w); | ||
1077 | halign = __ffs(*h); | ||
1078 | /* Enough to satisfy the image alignment? */ | ||
1079 | if (walign + halign < salign) { | ||
1080 | /* Max walign where there is still a valid width */ | ||
1081 | unsigned int wmaxa = __fls(wmax ^ (wmin - 1)); | ||
1082 | /* Max halign where there is still a valid height */ | ||
1083 | unsigned int hmaxa = __fls(hmax ^ (hmin - 1)); | ||
1084 | |||
1085 | /* up the smaller alignment until we have enough */ | ||
1086 | do { | ||
1087 | if (halign >= hmaxa || | ||
1088 | (walign <= halign && walign < wmaxa)) { | ||
1089 | *w = clamp_align(*w, wmin, wmax, walign + 1); | ||
1090 | walign = __ffs(*w); | ||
1091 | } else { | ||
1092 | *h = clamp_align(*h, hmin, hmax, halign + 1); | ||
1093 | halign = __ffs(*h); | ||
1094 | } | ||
1095 | } while (halign + walign < salign); | ||
1096 | } | ||
1097 | } | ||
1098 | EXPORT_SYMBOL_GPL(v4l_bound_align_image); | ||
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index fbfefae7886f..cd7266858462 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c | |||
@@ -883,15 +883,8 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
883 | maxh = norm_maxh(); | 883 | maxh = norm_maxh(); |
884 | 884 | ||
885 | f->fmt.pix.field = field; | 885 | f->fmt.pix.field = field; |
886 | if (f->fmt.pix.height < 32) | 886 | v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2, |
887 | f->fmt.pix.height = 32; | 887 | &f->fmt.pix.height, 32, maxh, 0, 0); |
888 | if (f->fmt.pix.height > maxh) | ||
889 | f->fmt.pix.height = maxh; | ||
890 | if (f->fmt.pix.width < 48) | ||
891 | f->fmt.pix.width = 48; | ||
892 | if (f->fmt.pix.width > maxw) | ||
893 | f->fmt.pix.width = maxw; | ||
894 | f->fmt.pix.width &= ~0x03; | ||
895 | f->fmt.pix.bytesperline = | 888 | f->fmt.pix.bytesperline = |
896 | (f->fmt.pix.width * fmt->depth) >> 3; | 889 | (f->fmt.pix.width * fmt->depth) >> 3; |
897 | f->fmt.pix.sizeimage = | 890 | f->fmt.pix.sizeimage = |
diff --git a/drivers/media/video/w9968cf.c b/drivers/media/video/w9968cf.c index f59b2bd07e89..6c3f23e31b5c 100644 --- a/drivers/media/video/w9968cf.c +++ b/drivers/media/video/w9968cf.c | |||
@@ -460,7 +460,7 @@ static int w9968cf_set_picture(struct w9968cf_device*, struct video_picture); | |||
460 | static int w9968cf_set_window(struct w9968cf_device*, struct video_window); | 460 | static int w9968cf_set_window(struct w9968cf_device*, struct video_window); |
461 | static int w9968cf_postprocess_frame(struct w9968cf_device*, | 461 | static int w9968cf_postprocess_frame(struct w9968cf_device*, |
462 | struct w9968cf_frame_t*); | 462 | struct w9968cf_frame_t*); |
463 | static int w9968cf_adjust_window_size(struct w9968cf_device*, u16* w, u16* h); | 463 | static int w9968cf_adjust_window_size(struct w9968cf_device*, u32 *w, u32 *h); |
464 | static void w9968cf_init_framelist(struct w9968cf_device*); | 464 | static void w9968cf_init_framelist(struct w9968cf_device*); |
465 | static void w9968cf_push_frame(struct w9968cf_device*, u8 f_num); | 465 | static void w9968cf_push_frame(struct w9968cf_device*, u8 f_num); |
466 | static void w9968cf_pop_frame(struct w9968cf_device*,struct w9968cf_frame_t**); | 466 | static void w9968cf_pop_frame(struct w9968cf_device*,struct w9968cf_frame_t**); |
@@ -1763,8 +1763,7 @@ w9968cf_set_window(struct w9968cf_device* cam, struct video_window win) | |||
1763 | #define UNSC(x) ((x) >> 10) | 1763 | #define UNSC(x) ((x) >> 10) |
1764 | 1764 | ||
1765 | /* Make sure we are using a supported resolution */ | 1765 | /* Make sure we are using a supported resolution */ |
1766 | if ((err = w9968cf_adjust_window_size(cam, (u16*)&win.width, | 1766 | if ((err = w9968cf_adjust_window_size(cam, &win.width, &win.height))) |
1767 | (u16*)&win.height))) | ||
1768 | goto error; | 1767 | goto error; |
1769 | 1768 | ||
1770 | /* Scaling factors */ | 1769 | /* Scaling factors */ |
@@ -1914,12 +1913,9 @@ error: | |||
1914 | Return 0 on success, -1 otherwise. | 1913 | Return 0 on success, -1 otherwise. |
1915 | --------------------------------------------------------------------------*/ | 1914 | --------------------------------------------------------------------------*/ |
1916 | static int | 1915 | static int |
1917 | w9968cf_adjust_window_size(struct w9968cf_device* cam, u16* width, u16* height) | 1916 | w9968cf_adjust_window_size(struct w9968cf_device *cam, u32 *width, u32 *height) |
1918 | { | 1917 | { |
1919 | u16 maxw, maxh; | 1918 | unsigned int maxw, maxh, align; |
1920 | |||
1921 | if ((*width < cam->minwidth) || (*height < cam->minheight)) | ||
1922 | return -ERANGE; | ||
1923 | 1919 | ||
1924 | maxw = cam->upscaling && !(cam->vpp_flag & VPP_DECOMPRESSION) && | 1920 | maxw = cam->upscaling && !(cam->vpp_flag & VPP_DECOMPRESSION) && |
1925 | w9968cf_vpp ? max((u16)W9968CF_MAX_WIDTH, cam->maxwidth) | 1921 | w9968cf_vpp ? max((u16)W9968CF_MAX_WIDTH, cam->maxwidth) |
@@ -1927,16 +1923,10 @@ w9968cf_adjust_window_size(struct w9968cf_device* cam, u16* width, u16* height) | |||
1927 | maxh = cam->upscaling && !(cam->vpp_flag & VPP_DECOMPRESSION) && | 1923 | maxh = cam->upscaling && !(cam->vpp_flag & VPP_DECOMPRESSION) && |
1928 | w9968cf_vpp ? max((u16)W9968CF_MAX_HEIGHT, cam->maxheight) | 1924 | w9968cf_vpp ? max((u16)W9968CF_MAX_HEIGHT, cam->maxheight) |
1929 | : cam->maxheight; | 1925 | : cam->maxheight; |
1926 | align = (cam->vpp_flag & VPP_DECOMPRESSION) ? 4 : 0; | ||
1930 | 1927 | ||
1931 | if (*width > maxw) | 1928 | v4l_bound_align_image(width, cam->minwidth, maxw, align, |
1932 | *width = maxw; | 1929 | height, cam->minheight, maxh, align, 0); |
1933 | if (*height > maxh) | ||
1934 | *height = maxh; | ||
1935 | |||
1936 | if (cam->vpp_flag & VPP_DECOMPRESSION) { | ||
1937 | *width &= ~15L; /* multiple of 16 */ | ||
1938 | *height &= ~15L; | ||
1939 | } | ||
1940 | 1930 | ||
1941 | PDBGG("Window size adjusted w=%u, h=%u ", *width, *height) | 1931 | PDBGG("Window size adjusted w=%u, h=%u ", *width, *height) |
1942 | 1932 | ||
@@ -3043,8 +3033,8 @@ static long w9968cf_v4l_ioctl(struct file *filp, | |||
3043 | if (win.clipcount != 0 || win.flags != 0) | 3033 | if (win.clipcount != 0 || win.flags != 0) |
3044 | return -EINVAL; | 3034 | return -EINVAL; |
3045 | 3035 | ||
3046 | if ((err = w9968cf_adjust_window_size(cam, (u16*)&win.width, | 3036 | if ((err = w9968cf_adjust_window_size(cam, &win.width, |
3047 | (u16*)&win.height))) { | 3037 | &win.height))) { |
3048 | DBG(4, "Resolution not supported (%ux%u). " | 3038 | DBG(4, "Resolution not supported (%ux%u). " |
3049 | "VIDIOCSWIN failed", win.width, win.height) | 3039 | "VIDIOCSWIN failed", win.width, win.height) |
3050 | return err; | 3040 | return err; |
@@ -3116,6 +3106,7 @@ static long w9968cf_v4l_ioctl(struct file *filp, | |||
3116 | { | 3106 | { |
3117 | struct video_mmap mmap; | 3107 | struct video_mmap mmap; |
3118 | struct w9968cf_frame_t* fr; | 3108 | struct w9968cf_frame_t* fr; |
3109 | u32 w, h; | ||
3119 | int err = 0; | 3110 | int err = 0; |
3120 | 3111 | ||
3121 | if (copy_from_user(&mmap, arg, sizeof(mmap))) | 3112 | if (copy_from_user(&mmap, arg, sizeof(mmap))) |
@@ -3164,8 +3155,10 @@ static long w9968cf_v4l_ioctl(struct file *filp, | |||
3164 | } | 3155 | } |
3165 | } | 3156 | } |
3166 | 3157 | ||
3167 | if ((err = w9968cf_adjust_window_size(cam, (u16*)&mmap.width, | 3158 | w = mmap.width; h = mmap.height; |
3168 | (u16*)&mmap.height))) { | 3159 | err = w9968cf_adjust_window_size(cam, &w, &h); |
3160 | mmap.width = w; mmap.height = h; | ||
3161 | if (err) { | ||
3169 | DBG(4, "Resolution not supported (%dx%d). " | 3162 | DBG(4, "Resolution not supported (%dx%d). " |
3170 | "VIDIOCMCAPTURE failed", | 3163 | "VIDIOCMCAPTURE failed", |
3171 | mmap.width, mmap.height) | 3164 | mmap.width, mmap.height) |
diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index 643cccaa1aab..3d7df32a3d87 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c | |||
@@ -2088,16 +2088,10 @@ static int zoran_try_fmt_vid_cap(struct file *file, void *__fh, | |||
2088 | return -EINVAL; | 2088 | return -EINVAL; |
2089 | } | 2089 | } |
2090 | 2090 | ||
2091 | bpp = (zoran_formats[i].depth + 7) / 8; | 2091 | bpp = DIV_ROUND_UP(zoran_formats[i].depth, 8); |
2092 | fmt->fmt.pix.width &= ~((bpp == 2) ? 1 : 3); | 2092 | v4l_bound_align_image( |
2093 | if (fmt->fmt.pix.width > BUZ_MAX_WIDTH) | 2093 | &fmt->fmt.pix.width, BUZ_MIN_WIDTH, BUZ_MAX_WIDTH, bpp == 2 ? 1 : 2, |
2094 | fmt->fmt.pix.width = BUZ_MAX_WIDTH; | 2094 | &fmt->fmt.pix.height, BUZ_MIN_HEIGHT, BUZ_MAX_HEIGHT, 0, 0); |
2095 | if (fmt->fmt.pix.width < BUZ_MIN_WIDTH) | ||
2096 | fmt->fmt.pix.width = BUZ_MIN_WIDTH; | ||
2097 | if (fmt->fmt.pix.height > BUZ_MAX_HEIGHT) | ||
2098 | fmt->fmt.pix.height = BUZ_MAX_HEIGHT; | ||
2099 | if (fmt->fmt.pix.height < BUZ_MIN_HEIGHT) | ||
2100 | fmt->fmt.pix.height = BUZ_MIN_HEIGHT; | ||
2101 | mutex_unlock(&zr->resource_lock); | 2095 | mutex_unlock(&zr->resource_lock); |
2102 | 2096 | ||
2103 | return 0; | 2097 | return 0; |