aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/gspca/mr97310a.c
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2009-10-29 06:42:30 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-12-05 15:41:04 -0500
commit065b6f7a34ec5628e0b1243bfc4214cb5f53d429 (patch)
treeb0a20403c01e4811b49ccbc20b9630d768f7a44d /drivers/media/video/gspca/mr97310a.c
parentf14a2972e40dbfbe7077ec7ab21cc2729f7e7d6d (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/gspca/mr97310a.c')
-rw-r--r--drivers/media/video/gspca/mr97310a.c57
1 files changed, 51 insertions, 6 deletions
diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c
index f282f800070..63050f0ebfa 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
58MODULE_AUTHOR("Kyle Guinn <elyk03@gmail.com>," 62MODULE_AUTHOR("Kyle Guinn <elyk03@gmail.com>,"
59 "Theodore Kilgore <kilgota@auburn.edu>"); 63 "Theodore Kilgore <kilgota@auburn.edu>");
60MODULE_DESCRIPTION("GSPCA/Mars-Semi MR97310A USB Camera Driver"); 64MODULE_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
81struct sensor_w_data { 86struct sensor_w_data {
@@ -92,6 +97,8 @@ static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
92static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); 97static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
93static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); 98static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
94static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); 99static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
100static int sd_setmin_clockdiv(struct gspca_dev *gspca_dev, __s32 val);
101static int sd_getmin_clockdiv(struct gspca_dev *gspca_dev, __s32 *val);
95static void setbrightness(struct gspca_dev *gspca_dev); 102static void setbrightness(struct gspca_dev *gspca_dev);
96static void setexposure(struct gspca_dev *gspca_dev); 103static void setexposure(struct gspca_dev *gspca_dev);
97static void setgain(struct gspca_dev *gspca_dev); 104static 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
165static const struct v4l2_pix_format vga_mode[] = { 187static 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
979static 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
989static 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