diff options
author | Hans de Goede <hdegoede@redhat.com> | 2009-10-29 06:42:30 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-12-05 15:41:04 -0500 |
commit | 065b6f7a34ec5628e0b1243bfc4214cb5f53d429 (patch) | |
tree | b0a20403c01e4811b49ccbc20b9630d768f7a44d /drivers/media/video | |
parent | f14a2972e40dbfbe7077ec7ab21cc2729f7e7d6d (diff) |
V4L/DVB (13242): gspca_mr97310a: Add minimum clock divider control
When "shooting" certain (quite rare) scenes, the mr97310's compression is not
effective and it cannot keep up with the data stream. This patch adds a
minimum clock divider control, which influences the maximum framerate,
libv4l will automatically increase this minimum clockdiv control when it
detect the cam cannot keep up.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video')
-rw-r--r-- | drivers/media/video/gspca/mr97310a.c | 57 |
1 files changed, 51 insertions, 6 deletions
diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c index f282f8000701..63050f0ebfad 100644 --- a/drivers/media/video/gspca/mr97310a.c +++ b/drivers/media/video/gspca/mr97310a.c | |||
@@ -55,6 +55,10 @@ | |||
55 | #define MR97310A_GAIN_MAX 31 | 55 | #define MR97310A_GAIN_MAX 31 |
56 | #define MR97310A_GAIN_DEFAULT 25 | 56 | #define MR97310A_GAIN_DEFAULT 25 |
57 | 57 | ||
58 | #define MR97310A_MIN_CLOCKDIV_MIN 3 | ||
59 | #define MR97310A_MIN_CLOCKDIV_MAX 8 | ||
60 | #define MR97310A_MIN_CLOCKDIV_DEFAULT 3 | ||
61 | |||
58 | MODULE_AUTHOR("Kyle Guinn <elyk03@gmail.com>," | 62 | MODULE_AUTHOR("Kyle Guinn <elyk03@gmail.com>," |
59 | "Theodore Kilgore <kilgota@auburn.edu>"); | 63 | "Theodore Kilgore <kilgota@auburn.edu>"); |
60 | MODULE_DESCRIPTION("GSPCA/Mars-Semi MR97310A USB Camera Driver"); | 64 | MODULE_DESCRIPTION("GSPCA/Mars-Semi MR97310A USB Camera Driver"); |
@@ -76,6 +80,7 @@ struct sd { | |||
76 | int brightness; | 80 | int brightness; |
77 | u16 exposure; | 81 | u16 exposure; |
78 | u8 gain; | 82 | u8 gain; |
83 | u8 min_clockdiv; | ||
79 | }; | 84 | }; |
80 | 85 | ||
81 | struct sensor_w_data { | 86 | struct sensor_w_data { |
@@ -92,6 +97,8 @@ static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); | |||
92 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); | 97 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); |
93 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); | 98 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); |
94 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); | 99 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); |
100 | static int sd_setmin_clockdiv(struct gspca_dev *gspca_dev, __s32 val); | ||
101 | static int sd_getmin_clockdiv(struct gspca_dev *gspca_dev, __s32 *val); | ||
95 | static void setbrightness(struct gspca_dev *gspca_dev); | 102 | static void setbrightness(struct gspca_dev *gspca_dev); |
96 | static void setexposure(struct gspca_dev *gspca_dev); | 103 | static void setexposure(struct gspca_dev *gspca_dev); |
97 | static void setgain(struct gspca_dev *gspca_dev); | 104 | static void setgain(struct gspca_dev *gspca_dev); |
@@ -160,6 +167,21 @@ static struct ctrl sd_ctrls[] = { | |||
160 | .set = sd_setgain, | 167 | .set = sd_setgain, |
161 | .get = sd_getgain, | 168 | .get = sd_getgain, |
162 | }, | 169 | }, |
170 | { | ||
171 | #define MIN_CLOCKDIV_IDX 4 | ||
172 | { | ||
173 | .id = V4L2_CID_PRIVATE_BASE, | ||
174 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
175 | .name = "Minimum Clock Divider", | ||
176 | .minimum = MR97310A_MIN_CLOCKDIV_MIN, | ||
177 | .maximum = MR97310A_MIN_CLOCKDIV_MAX, | ||
178 | .step = 1, | ||
179 | .default_value = MR97310A_MIN_CLOCKDIV_DEFAULT, | ||
180 | .flags = 0, | ||
181 | }, | ||
182 | .set = sd_setmin_clockdiv, | ||
183 | .get = sd_getmin_clockdiv, | ||
184 | }, | ||
163 | }; | 185 | }; |
164 | 186 | ||
165 | static const struct v4l2_pix_format vga_mode[] = { | 187 | static const struct v4l2_pix_format vga_mode[] = { |
@@ -544,14 +566,16 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
544 | gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) | | 566 | gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) | |
545 | (1 << ARGUS_QC_BRIGHTNESS_IDX); | 567 | (1 << ARGUS_QC_BRIGHTNESS_IDX); |
546 | else | 568 | else |
547 | gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX); | 569 | gspca_dev->ctrl_dis = (1 << ARGUS_QC_BRIGHTNESS_IDX) | |
570 | (1 << MIN_CLOCKDIV_IDX); | ||
548 | } else { | 571 | } else { |
549 | /* All controls need to be disabled if VGA sensor_type is 0 */ | 572 | /* All controls need to be disabled if VGA sensor_type is 0 */ |
550 | if (sd->sensor_type == 0) | 573 | if (sd->sensor_type == 0) |
551 | gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) | | 574 | gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX) | |
552 | (1 << ARGUS_QC_BRIGHTNESS_IDX) | | 575 | (1 << ARGUS_QC_BRIGHTNESS_IDX) | |
553 | (1 << EXPOSURE_IDX) | | 576 | (1 << EXPOSURE_IDX) | |
554 | (1 << GAIN_IDX); | 577 | (1 << GAIN_IDX) | |
578 | (1 << MIN_CLOCKDIV_IDX); | ||
555 | else if (sd->do_lcd_stop) | 579 | else if (sd->do_lcd_stop) |
556 | /* Argus QuickClix has different brightness limits */ | 580 | /* Argus QuickClix has different brightness limits */ |
557 | gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX); | 581 | gspca_dev->ctrl_dis = (1 << NORM_BRIGHTNESS_IDX); |
@@ -562,6 +586,7 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
562 | sd->brightness = MR97310A_BRIGHTNESS_DEFAULT; | 586 | sd->brightness = MR97310A_BRIGHTNESS_DEFAULT; |
563 | sd->exposure = MR97310A_EXPOSURE_DEFAULT; | 587 | sd->exposure = MR97310A_EXPOSURE_DEFAULT; |
564 | sd->gain = MR97310A_GAIN_DEFAULT; | 588 | sd->gain = MR97310A_GAIN_DEFAULT; |
589 | sd->min_clockdiv = MR97310A_MIN_CLOCKDIV_DEFAULT; | ||
565 | 590 | ||
566 | return 0; | 591 | return 0; |
567 | } | 592 | } |
@@ -837,6 +862,7 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
837 | { | 862 | { |
838 | struct sd *sd = (struct sd *) gspca_dev; | 863 | struct sd *sd = (struct sd *) gspca_dev; |
839 | int exposure; | 864 | int exposure; |
865 | u8 buf[2]; | ||
840 | 866 | ||
841 | if (gspca_dev->ctrl_dis & (1 << EXPOSURE_IDX)) | 867 | if (gspca_dev->ctrl_dis & (1 << EXPOSURE_IDX)) |
842 | return; | 868 | return; |
@@ -858,8 +884,8 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
858 | u8 clockdiv = (60 * sd->exposure + 7999) / 8000; | 884 | u8 clockdiv = (60 * sd->exposure + 7999) / 8000; |
859 | 885 | ||
860 | /* Limit framerate to not exceed usb bandwidth */ | 886 | /* Limit framerate to not exceed usb bandwidth */ |
861 | if (clockdiv < 3 && gspca_dev->width >= 320) | 887 | if (clockdiv < sd->min_clockdiv && gspca_dev->width >= 320) |
862 | clockdiv = 3; | 888 | clockdiv = sd->min_clockdiv; |
863 | else if (clockdiv < 2) | 889 | else if (clockdiv < 2) |
864 | clockdiv = 2; | 890 | clockdiv = 2; |
865 | 891 | ||
@@ -875,9 +901,10 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
875 | /* exposure register value is reversed! */ | 901 | /* exposure register value is reversed! */ |
876 | exposure = 511 - exposure; | 902 | exposure = 511 - exposure; |
877 | 903 | ||
904 | buf[0] = exposure & 0xff; | ||
905 | buf[1] = exposure >> 8; | ||
906 | sensor_write_reg(gspca_dev, 0x0e, 0, buf, 2); | ||
878 | sensor_write1(gspca_dev, 0x02, clockdiv); | 907 | sensor_write1(gspca_dev, 0x02, clockdiv); |
879 | sensor_write1(gspca_dev, 0x0e, exposure & 0xff); | ||
880 | sensor_write1(gspca_dev, 0x0f, exposure >> 8); | ||
881 | } | 908 | } |
882 | } | 909 | } |
883 | 910 | ||
@@ -949,6 +976,24 @@ static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) | |||
949 | return 0; | 976 | return 0; |
950 | } | 977 | } |
951 | 978 | ||
979 | static int sd_setmin_clockdiv(struct gspca_dev *gspca_dev, __s32 val) | ||
980 | { | ||
981 | struct sd *sd = (struct sd *) gspca_dev; | ||
982 | |||
983 | sd->min_clockdiv = val; | ||
984 | if (gspca_dev->streaming) | ||
985 | setexposure(gspca_dev); | ||
986 | return 0; | ||
987 | } | ||
988 | |||
989 | static int sd_getmin_clockdiv(struct gspca_dev *gspca_dev, __s32 *val) | ||
990 | { | ||
991 | struct sd *sd = (struct sd *) gspca_dev; | ||
992 | |||
993 | *val = sd->min_clockdiv; | ||
994 | return 0; | ||
995 | } | ||
996 | |||
952 | /* Include pac common sof detection functions */ | 997 | /* Include pac common sof detection functions */ |
953 | #include "pac_common.h" | 998 | #include "pac_common.h" |
954 | 999 | ||