Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2b34e9d1 authored by Frank Schäfer's avatar Frank Schäfer Committed by Mauro Carvalho Chehab
Browse files

[media] gspca_pac7302: use registers 0x01 and 0x03 for red and blue balance controls



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: default avatarFrank Schäfer <fschaefer.oss@googlemail.com>
Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 6f9b3312
Loading
Loading
Loading
Loading
+40 −11
Original line number Diff line number Diff line
@@ -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,6 +98,9 @@
/* Include pac common sof detection functions */
#include "pac_common.h"

#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 */
@@ -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, 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);