diff -Naur old/m5602_s5k83a.c new/m5602_s5k83a.c
--- old/m5602_s5k83a.c	2008-09-07 18:15:13.000000000 +0200
+++ new/m5602_s5k83a.c	2008-09-07 21:40:12.000000000 +0200
@@ -75,7 +75,11 @@
 	m5602_write_bridge(cam, M5602_XB_I2C_DEV_ADDR,
 			   cam->sensor->i2c_slave_id);
 	m5602_write_bridge(cam, M5602_XB_I2C_REG_ADDR, address);
-	m5602_write_bridge(cam, M5602_XB_I2C_CTRL, 0x1a);
+    m5602_write_bridge(cam, M5602_XB_I2C_CTRL, 0x18 + len);
+
+    do {
+        err = m5602_read_bridge(cam, M5602_XB_I2C_STATUS, i2c_data);
+    } while ((*i2c_data & I2C_BUSY) && !err);    
 
 	for (i = 0; i < len; i++) {
 		err = m5602_read_bridge(cam, M5602_XB_I2C_DATA, &(i2c_data[i]));
@@ -173,13 +177,51 @@
 
 static int s5k83a_get_ctrl(struct m5602_camera *cam, struct v4l2_control *ctrl)
 {
-	return 0;
+	int err = 0;
+    
+	switch (ctrl->id) {
+		case V4L2_CID_BRIGHTNESS:
+			ctrl->value = s5k83a_get_brightness(cam);
+			PDEBUG(DBG_V4L2, "get brightness (0x%x)", ctrl->value );
+			break;
+		case V4L2_CID_WHITENESS:
+			ctrl->value = s5k83a_get_whiteness(cam);
+			PDEBUG(DBG_V4L2, "get whiteness (0x%x)", ctrl->value );
+			break;
+		case V4L2_CID_GAIN:
+			ctrl->value = s5k83a_get_gain(cam);
+			PDEBUG(DBG_V4L2, "get gain (0x%x)", ctrl->value );
+			break;
+		default:
+			PDEBUG(DBG_V4L2, "selected ioctl (0x%x) is not supported", ctrl->id);
+			err = -EINVAL;
+	}
+	return (err < 0) ? err : 0;
 }
 
 static int s5k83a_set_ctrl(struct m5602_camera *cam,
 			   const struct v4l2_control *ctrl)
 {
-	return 0;
+	int err = 0;
+    
+	switch (ctrl->id) {
+		case V4L2_CID_BRIGHTNESS:
+			err = s5k83a_set_brightness(cam, ctrl->value);
+			PDEBUG(DBG_V4L2, "set brightness to 0x%x", ctrl->value);
+			break;
+		case V4L2_CID_WHITENESS:
+			err = s5k83a_set_whiteness(cam, ctrl->value);
+			PDEBUG(DBG_V4L2, "set whiteness to 0x%x", ctrl->value);
+			break;
+		case V4L2_CID_GAIN:
+			err = s5k83a_set_gain(cam, ctrl->value);
+			PDEBUG(DBG_V4L2, "set gain to 0x%x", ctrl->value);
+			break;
+		default:
+			PDEBUG(DBG_V4L2, "selected ioctl (0x%x) is not supported", ctrl->id);    
+			err = -EINVAL;
+	}
+	return (err < 0) ? err : 0;
 }
 
 static void s5k83a_dump_registers(struct m5602_camera *cam)
@@ -221,3 +263,89 @@
 	info("Read/write register probing complete");
 	s5k83a_write_sensor(cam, S5K83A_PAGE_MAP, &old_page, 1);
 }
+
+
+static int s5k83a_get_brightness(struct m5602_camera *cam)
+{
+	int err = 0;
+	u8 data[2] = {0, 0};
+
+	err = s5k83a_read_sensor(cam, 0x1b, data, 2);
+	data[1] = data[1] << 1;
+
+	return (err < 0) ? S5K83A_DEFAULT_BRIGHTNESS : data[1];
+}
+
+static int s5k83a_set_brightness(struct m5602_camera *cam, u8 value)
+{
+	int err = 0;
+	u8 data[2];
+
+	data[0] = 0x00;
+	data[1] = 0x20;
+	err = s5k83a_write_sensor(cam, 0x14, data, 2);
+	if (err < 0)
+		return err;
+
+	data[0] = 0x01;
+	data[1] = 0x00;
+	err = s5k83a_write_sensor(cam, 0x0d, data, 2);
+	if (err < 0)
+		return err;
+
+	data[0] = value >> 3; // brightness, high 5 bits
+	data[1] = value >> 1; // brightness, high 7 bits 
+	err = s5k83a_write_sensor(cam, 0x1b, data, 2);
+
+	return (err < 0) ? err : 0;
+}
+
+static int s5k83a_get_whiteness(struct m5602_camera *cam)
+{
+	int err = 0;
+	u8 data[1] = {0};
+
+	err = s5k83a_read_sensor(cam, 0x0a, data, 1);
+
+	return (err < 0) ? S5K83A_DEFAULT_WHITENESS : data[0];
+}
+
+
+static int s5k83a_set_whiteness(struct m5602_camera *cam, u8 value)
+{
+	int err = 0;
+	u8 data[1];
+
+	data[0] = value;
+	err = s5k83a_write_sensor(cam, 0x0a, data, 1);
+
+	return (err < 0) ? err : 0;
+}
+
+static int s5k83a_get_gain(struct m5602_camera *cam)
+{
+	int err = 0;
+	u8 data[2] = {0, 0};
+
+	err = s5k83a_read_sensor(cam, 0x18, data, 2);
+
+	data[1] = data[1] & 0x3f;
+	if (data[1] > S5K83A_MAXIMUM_GAIN)
+		data[1] = S5K83A_MAXIMUM_GAIN;
+
+	return (err < 0) ? S5K83A_DEFAULT_GAIN : data[1];
+}
+
+static int s5k83a_set_gain(struct m5602_camera *cam, u8 value)
+{
+	int err = 0;
+	u8 data[2];
+
+	data[0] = 0;
+	data[1] = value;
+	err = s5k83a_write_sensor(cam, 0x18, data, 2);
+
+	return (err < 0) ? err : 0;
+}
+
+
diff -Naur old/m5602_s5k83a.h new/m5602_s5k83a.h
--- old/m5602_s5k83a.h	2008-09-06 21:46:59.000000000 +0200
+++ new/m5602_s5k83a.h	2008-09-07 21:38:42.000000000 +0200
@@ -23,6 +23,11 @@
 
 #define S5K83A_PAGE_MAP			0xec
 
+#define S5K83A_DEFAULT_BRIGHTNESS 0x71
+#define S5K83A_DEFAULT_WHITENESS 0x7e
+#define S5K83A_DEFAULT_GAIN 0
+#define S5K83A_MAXIMUM_GAIN 0x3c
+
 /*****************************************************************************/
 
 static int s5k83a_get_ctrl(struct m5602_camera *cam,
@@ -39,7 +44,14 @@
 		       u8 *i2c_data, const u8 len);
 static int s5k83a_write_sensor(struct m5602_camera *cam, const u8 address,
 			u8 *i2c_data, const u8 len);
-
+            
+static int s5k83a_set_brightness(struct m5602_camera *cam, u8 value);
+static int s5k83a_get_brightness(struct m5602_camera *cam);
+static int s5k83a_set_whiteness(struct m5602_camera *cam, u8 value);
+static int s5k83a_get_whiteness(struct m5602_camera *cam);
+static int s5k83a_set_gain(struct m5602_camera *cam, u8 value);
+static int s5k83a_get_gain(struct m5602_camera *cam);
+        
 static struct m5602_sensor s5k83a = {
 	.name = "S5K83A",
 	.probe = s5k83a_probe,
@@ -50,7 +62,38 @@
 	.read_sensor = s5k83a_read_sensor,
 	.write_sensor = s5k83a_write_sensor,
 	.i2c_slave_id = 0x5a,
-	.qctrl = {},
+	.qctrl = {
+		{
+			.id = V4L2_CID_BRIGHTNESS,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "brightness",
+			.minimum = 0x00,
+			.maximum = 0xff,
+			.step = 0x01,
+			.default_value = S5K83A_DEFAULT_BRIGHTNESS,
+			.flags = V4L2_CTRL_FLAG_SLIDER
+		},
+		{
+				.id = V4L2_CID_WHITENESS,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "whiteness",
+			.minimum = 0x00,
+			.maximum = 0xff,
+			.step = 0x01,
+			.default_value = S5K83A_DEFAULT_WHITENESS,
+			.flags = V4L2_CTRL_FLAG_SLIDER
+		},
+		{
+				.id = V4L2_CID_GAIN,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "gain",
+			.minimum = 0x00,
+			.maximum = S5K83A_MAXIMUM_GAIN,
+			.step = 0x01,
+			.default_value = S5K83A_DEFAULT_GAIN,
+			.flags = V4L2_CTRL_FLAG_SLIDER
+		}
+    },
 	.cropcap = {
 		.bounds = {
 			.left = 0,
@@ -284,7 +327,106 @@
 	{SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
 	{SENSOR_LONG, 0x14, 0x00, 0x20},
 	{SENSOR_LONG, 0x0d, 0x00, 0x7d},
-	{SENSOR_LONG, 0x1b, 0x0d, 0x05}
+	{SENSOR_LONG, 0x1b, 0x0d, 0x05},
+ 
+	// following sequence is useless after clear boot
+	// but it is necessary after some resume from suspend...
+	{BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
+	{BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
+	{BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00},
+	{BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00},
+	{BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
+	{BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
+	{BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
+	{BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
+	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00},
+	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00},
+	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+	{BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
+	{BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
+	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00},
+	{BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
+	{BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00},
+	{BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
+	{BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00},
+	{BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
+	{BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
+	{BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00},
+		
+	{SENSOR, 0xec, 0x04, 0x00},
+	{SENSOR, 0xaf, 0x01, 0x00},
+	{SENSOR, 0xec, 0x00, 0x00},
+	{SENSOR, 0x7b, 0xff, 0x00},
+	{SENSOR, 0xec, 0x05, 0x00},
+	{SENSOR, 0x01, 0x50, 0x00},
+	{SENSOR, 0x12, 0x20, 0x00},
+	{SENSOR, 0x17, 0x40, 0x00},
+	{SENSOR, 0x1b, 0x0f, 0x00},
+	{SENSOR, 0x1c, 0x00, 0x00},
+	{SENSOR, 0x02, 0x70, 0x00},
+	{SENSOR, 0x03, 0x0b, 0x00},
+	{SENSOR, 0x04, 0xf0, 0x00},
+	{SENSOR, 0x05, 0x0b, 0x00},
+	{SENSOR, 0xec, 0x05, 0x00},
+		
+	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
+	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+	{BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+	{BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+	{BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
+	{BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
+	{BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
+	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+	{BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
+	{BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00},
+	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+	{BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+	{BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
+	{BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+	{BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+	{BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
+	{BRIDGE, M5602_XB_HSYNC_PARA, 0x7f, 0x00},
+	{BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+	{BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+	{BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+		
+	{SENSOR, 0xec, 0x05, 0x00},
+	{SENSOR, 0x06, 0x71, 0x00},
+	{SENSOR, 0x07, 0xe8, 0x00},
+	{SENSOR, 0x08, 0x02, 0x00},
+	{SENSOR, 0x09, 0x88, 0x00},
+	{SENSOR, 0x14, 0x00, 0x00},
+	{SENSOR, 0x15, 0x20, 0x00},
+	{SENSOR, 0x19, 0x00, 0x00},
+	{SENSOR, 0x1a, 0x98, 0x00},
+	{SENSOR, 0x0f, 0x02, 0x00},
+		
+	{SENSOR, 0x10, 0xe5, 0x00},
+	{SENSOR, 0xec, 0x05, 0x00},
+	{SENSOR_LONG, 0x14, 0x00, 0x20},
+	{SENSOR_LONG, 0x0d, 0x00, 0x7d},
+	{SENSOR_LONG, 0x1b, 0x0d, 0x05},
+		
+	{SENSOR, 0x00, 0x06, 0x00},  // normal colors (this is value after boot, but after tries can be different)
+		
+	// set default brightness
+	{SENSOR_LONG, 0x14, 0x00, 0x20},
+	{SENSOR_LONG, 0x0d, 0x01, 0x00},
+	{SENSOR_LONG, 0x1b, S5K83A_DEFAULT_BRIGHTNESS >> 3 , S5K83A_DEFAULT_BRIGHTNESS >> 1},
+		
+	// set default whiteness
+	{SENSOR, 0x0a, S5K83A_DEFAULT_WHITENESS, 0x00},
+		
+	// set default gain
+	{SENSOR_LONG, 0x18, 0x00, S5K83A_DEFAULT_GAIN}
 };
 
 #endif
