From 2b34e9d1beb546afd7586845775f2d1272a08a4a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Frank=20Sch=C3=A4fer?= Date: Sun, 23 Sep 2012 10:29:43 -0300 Subject: [PATCH] [media] gspca_pac7302: use registers 0x01 and 0x03 for red and blue balance controls MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Currently used registers 0xc5 and 0xc7 provide only a very coarse adjustment possibility within a very small value range (0-3). With registers 0x01 and 0x03, a fine grained adjustment with 255 steps is possible. This is also what the Windows driver does. Signed-off-by: Frank Schäfer Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/gspca/pac7302.c | 51 ++++++++++++++++++++++++++++++--------- 1 file changed, 40 insertions(+), 11 deletions(-) diff --git a/drivers/media/usb/gspca/pac7302.c b/drivers/media/usb/gspca/pac7302.c index 4894ac1..4f5869a 100644 --- a/drivers/media/usb/gspca/pac7302.c +++ b/drivers/media/usb/gspca/pac7302.c @@ -77,12 +77,12 @@ * * Page | Register | Function * -----+------------+--------------------------------------------------- + * 0 | 0x01 | setredbalance() + * 0 | 0x03 | setbluebalance() * 0 | 0x0f..0x20 | setcolors() * 0 | 0xa2..0xab | setbrightcont() * 0 | 0xb6 | setsharpness() - * 0 | 0xc5 | setredbalance() * 0 | 0xc6 | setwhitebalance() - * 0 | 0xc7 | setbluebalance() * 0 | 0xdc | setbrightcont(), setcolors() * 3 | 0x02 | setexposure() * 3 | 0x10, 0x12 | setgain() @@ -98,10 +98,13 @@ /* Include pac common sof detection functions */ #include "pac_common.h" -#define PAC7302_GAIN_DEFAULT 15 -#define PAC7302_GAIN_KNEE 42 -#define PAC7302_EXPOSURE_DEFAULT 66 /* 33 ms / 30 fps */ -#define PAC7302_EXPOSURE_KNEE 133 /* 66 ms / 15 fps */ +#define PAC7302_RGB_BALANCE_MIN 0 +#define PAC7302_RGB_BALANCE_MAX 200 +#define PAC7302_RGB_BALANCE_DEFAULT 100 +#define PAC7302_GAIN_DEFAULT 15 +#define PAC7302_GAIN_KNEE 42 +#define PAC7302_EXPOSURE_DEFAULT 66 /* 33 ms / 30 fps */ +#define PAC7302_EXPOSURE_KNEE 133 /* 66 ms / 15 fps */ MODULE_AUTHOR("Jean-Francois Moine , " "Thomas Kaiser thomas@kaiser-linux.li"); @@ -438,12 +441,31 @@ static void setwhitebalance(struct gspca_dev *gspca_dev) reg_w(gspca_dev, 0xdc, 0x01); } +static u8 rgbbalance_ctrl_to_reg_value(s32 rgb_ctrl_val) +{ + const unsigned int k = 1000; /* precision factor */ + unsigned int norm; + + /* Normed value [0...k] */ + norm = k * (rgb_ctrl_val - PAC7302_RGB_BALANCE_MIN) + / (PAC7302_RGB_BALANCE_MAX - PAC7302_RGB_BALANCE_MIN); + /* Qudratic apporach improves control at small (register) values: */ + return 64 * norm * norm / (k*k) + 32 * norm / k + 32; + /* Y = 64*X*X + 32*X + 32 + * => register values 0x20-0x80; Windows driver uses these limits */ + + /* NOTE: for full value range (0x00-0xff) use + * Y = 254*X*X + X + * => 254 * norm * norm / (k*k) + 1 * norm / k */ +} + static void setredbalance(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ - reg_w(gspca_dev, 0xc5, sd->red_balance->val); + reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ + reg_w(gspca_dev, 0x01, + rgbbalance_ctrl_to_reg_value(sd->red_balance->val)); reg_w(gspca_dev, 0xdc, 0x01); } @@ -453,7 +475,8 @@ static void setbluebalance(struct gspca_dev *gspca_dev) struct sd *sd = (struct sd *) gspca_dev; reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ - reg_w(gspca_dev, 0xc7, sd->blue_balance->val); + reg_w(gspca_dev, 0x03, + rgbbalance_ctrl_to_reg_value(sd->blue_balance->val)); reg_w(gspca_dev, 0xdc, 0x01); } @@ -642,9 +665,15 @@ static int sd_init_controls(struct gspca_dev *gspca_dev) V4L2_CID_WHITE_BALANCE_TEMPERATURE, 0, 255, 1, 55); sd->red_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_RED_BALANCE, 0, 3, 1, 1); + V4L2_CID_RED_BALANCE, + PAC7302_RGB_BALANCE_MIN, + PAC7302_RGB_BALANCE_MAX, + 1, PAC7302_RGB_BALANCE_DEFAULT); sd->blue_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, - V4L2_CID_BLUE_BALANCE, 0, 3, 1, 1); + V4L2_CID_BLUE_BALANCE, + PAC7302_RGB_BALANCE_MIN, + PAC7302_RGB_BALANCE_MAX, + 1, PAC7302_RGB_BALANCE_DEFAULT); gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_AUTOGAIN, 0, 1, 1, 1); -- 2.7.4