/*
 * USB Driver for m5602 based webcams.
 *
 * Copyright (C) 2008 Erik Andrén
 * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
 * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation, version 2.
 *
 */

#ifndef M5602_H_
#define M5602_H_

#include <linux/mutex.h>

/* Driver info */
#define DRIVER_AUTHOR "ALi M5602 Linux Driver Project"
#define DRIVER_DESC "M5602 Webcam Driver"

#define DRIVER_VERSION "0.2.0"
#define DRIVER_VERSION_NUMERICAL 0x200

#define M5602_DEFAULT_FRAME_WIDTH       640
#define M5602_DEFAULT_FRAME_HEIGHT      480
#define M5602_MIN_FRAME_WIDTH	16
#define M5602_MIN_FRAME_HEIGHT	16

#define M5602_MAX_FRAMES	32

#define M5602_URBS	2
#define M5602_ISOC_PACKETS	14

#define M5602_URB_TIMEOUT	msecs_to_jiffies(2 * M5602_ISOC_PACKETS)
#define M5602_URB_MSG_TIMEOUT   5000
#define M5602_FRAME_TIMEOUT	2

#define M5602_MAX_CTRLS		(V4L2_CID_LASTP1 - V4L2_CID_BASE + 10)

#define DBG_INIT 0x1
#define DBG_PROBE 0x2
#define DBG_V4L2 0x4
#define DBG_TRACE 0x8
#define DBG_DATA 0x10
#define DBG_V4L2_CNT 0x20

#define PDEBUG(level, fmt, args...) \
	do { \
		if (debug & level)     \
			info("[%s:%d] " fmt, __FUNCTION__, __LINE__ , \
			## args); \
	} while (0)

/* *** helper macros *** */

/* turn a numeric literal into a hex constant
(avoids problems with leading zeroes)
8-bit constants max value 0x11111111, always fits in unsigned long
*/
#define HEX__(n) 0x##n##LU

/* 8-bit conversion function */
#define B8__(x) ((x&0x0000000FLU)?1:0) \
+((x&0x000000F0LU)?2:0) \
+((x&0x00000F00LU)?4:0) \
+((x&0x0000F000LU)?8:0) \
+((x&0x000F0000LU)?16:0) \
+((x&0x00F00000LU)?32:0) \
+((x&0x0F000000LU)?64:0) \
+((x&0xF0000000LU)?128:0)

/* for upto 8-bit binary constants */
#define B8(d) ((unsigned char)B8__(HEX__(d)))

/*****************************************************************************/

#define S5K83A_I2C_SLAVE_WRITE_ADDRESS 0x5a
#define S5K83A_I2C_SLAVE_READ_ADDRESS 0x5a

/*****************************************************************************/

#define M5602_XB_SENSOR_TYPE 0x00
#define M5602_XB_SENSOR_CTRL 0x01
#define M5602_XB_LINE_OF_FRAME_H 0x02
#define M5602_XB_LINE_OF_FRAME_L 0x03
#define M5602_XB_PIX_OF_LINE_H 0x04
#define M5602_XB_PIX_OF_LINE_L 0x05
#define M5602_XB_VSYNC_PARA 0x06
#define M5602_XB_HSYNC_PARA 0x07
#define M5602_XB_TEST_MODE_1 0x08
#define M5602_XB_TEST_MODE_2 0x09
#define M5602_XB_SIG_INI 0x0a
#define M5602_XB_DS_PARA 0x0e
#define M5602_XB_TRIG_PARA 0x0f
#define M5602_XB_CLK_PD 0x10
#define M5602_XB_MCU_CLK_CTRL 0x12
#define M5602_XB_MCU_CLK_DIV 0x13
#define M5602_XB_SEN_CLK_CTRL 0x14
#define M5602_XB_SEN_CLK_DIV 0x15
#define M5602_XB_AUD_CLK_CTRL 0x16
#define M5602_XB_AUD_CLK_DIV 0x17
#define M5602_XB_DEVCTR1 0x41
#define M5602_XB_EPSETR0 0x42
#define M5602_XB_EPAFCTR 0x47
#define M5602_XB_EPBFCTR 0x49
#define M5602_XB_EPEFCTR 0x4f
#define M5602_XB_TEST_REG 0x53
#define M5602_XB_ALT2SIZE 0x54
#define M5602_XB_ALT3SIZE 0x55
#define M5602_XB_OBSFRAME 0x56
#define M5602_XB_PWR_CTL 0x59
#define M5602_XB_ADC_CTRL 0x60
#define M5602_XB_ADC_DATA 0x61
#define M5602_XB_MISC_CTRL 0x62
#define M5602_XB_SNAPSHOT 0x63
#define M5602_XB_SCRATCH_1 0x64
#define M5602_XB_SCRATCH_2 0x65
#define M5602_XB_SCRATCH_3 0x66
#define M5602_XB_SCRATCH_4 0x67
#define M5602_XB_I2C_CTRL 0x68
#define M5602_XB_I2C_CLK_DIV 0x69
#define M5602_XB_I2C_DEV_ADDR 0x6a
#define M5602_XB_I2C_REG_ADDR 0x6b
#define M5602_XB_I2C_DATA 0x6c
#define M5602_XB_I2C_STATUS 0x6d
#define M5602_XB_GPIO_DAT_H 0x70
#define M5602_XB_GPIO_DAT_L 0x71
#define M5602_XB_GPIO_DIR_H 0x72
#define M5602_XB_GPIO_DIR_L 0x73
#define M5602_XB_GPIO_EN_H 0x74
#define M5602_XB_GPIO_EN_L 0x75
#define M5602_XB_GPIO_DAT 0x76
#define M5602_XB_GPIO_DIR 0x77
#define M5602_XB_MISC_CTL 0x70

/*****************************************************************************/

#define I2C_BUSY 0x80

/*****************************************************************************/

enum Instruction {
	BRIDGE,
	SENSOR,
	END
};

enum m5602_frame_state {
	FRAME_UNUSED,   /* Unused (no MCAPTURE) */
	FRAME_QUEUED,   /* Ready to start grabbing */
	FRAME_GRABBING, /* In the process of being grabbed into */
	FRAME_DONE,     /* Finished grabbing, but not been synced yet */
	FRAME_ERROR    /* Something bad happened while processing */
};

enum m5602_stream_state {
	STREAM_OFF,
	STREAM_INTERRUPT,
	STREAM_ON
};

enum m5602_dev_state {
	DEV_INITIALIZED = 0x1,
	DEV_DISCONNECTED = 0x2,
	DEV_MISCONFIGURED = 0x4
};

struct m5602_frame_t {
	struct list_head frame;

	unsigned char *bufmem;
	unsigned char *rawdata;

	int framenum;
	struct v4l2_buffer buf;

	enum m5602_frame_state state;
	unsigned long vma_use_count;
};

struct m5602_capture_format {
	__u32 pixelformat;
	char description[32];
} m5602_capture_format;

static DECLARE_RWSEM(m5602_disconnect);

struct m5602_camera;

struct m5602_sensor {
	const struct device *dev;
	const struct usb_device *usbdev;
	struct v4l2_rect _rect;
	struct v4l2_cropcap cropcap;
	struct v4l2_queryctrl qctrl[M5602_MAX_CTRLS];
	u8 i2c_slave_id;
	int (*get_ctrl)(struct m5602_camera *cam,
	      struct v4l2_control *ctrl);
	int (*set_ctrl)(struct m5602_camera *cam,
	      const struct v4l2_control *ctrl);
	int (*set_crop)(struct m5602_camera *cam,
	      const struct v4l2_rect *rect);
	int (*i2c_write)(struct m5602_camera *cam,
	      const unsigned char register_id, const unsigned char *data);
	int (*i2c_read)(struct m5602_camera *cam,
	      const unsigned char register_id, unsigned char *data);
	char name[32]; /* sensor name */
	char maintainer[64]; /* name of the maintainer <email> */
};

struct m5602_camera {
	char *name;
	struct m5602_sensor *sensor;
	struct v4l2_pix_format current_fmt;
	struct device dev;

	/* the v4l video device for this device */
	struct video_device *vdev;

	/* the usb device for this camera */
	struct usb_device *udev;

	/* the interface for this usb device */
	struct usb_interface *interface;

	u8 *control_buffer;

	/* Temporary buffer used for performing color recovery and scaling */
	u8 *canvas;

	/* the size of the INT receive buffer */
	size_t int_in_size;

	/* the address of the INT in endpoint */
	__u8 int_in_endpointAddr;

	struct urb *urb[M5602_URBS];

	/* the buffer to receive ISOC data */
	unsigned char *isoc_in_buffer[M5602_URBS];

	/* the size of the ISOC receive buffer */
	size_t isoc_in_size;

	/* the address of the ISOC in endpoint */
	__u8 isoc_in_endpointAddr;

	struct m5602_frame_t *frame_current, frame[M5602_MAX_FRAMES];

	u32 frame_count, nbuffers;

	/* Three linked lists, one for free frames,
	one for finished frames and one for frames awaiting post processing */
	struct list_head inqueue, postprocqueue, outqueue;

	enum v4l2_memory io;

	enum m5602_stream_state stream;

	enum m5602_dev_state state;

	u8 users;

	struct mutex dev_mutex, fileop_mutex, canvas_mutex;

	spinlock_t queue_lock;

	struct kref kref;

	wait_queue_head_t open, wait_frame, wait_stream;

	struct work_struct m5602_work;
};

static void bayer_decode_rgb(unsigned char *src,
			     unsigned char *dest,
			     const int width,
			     const int height,
			     const unsigned char depth);

static void scale_line(u8 *src,
		       u8 *dest,
		       const int source_width,
		       const int target_width,
		       const unsigned char depth);

static void scale_bresenham(u8 *src,
			    u8 *dest,
			    const int source_width,
			    const int source_height,
			    const int target_width,
			    const int target_height,
			    const unsigned char depth);

static int m5602_stream_interrupt(struct m5602_camera *cam);
static void m5602_empty_framequeues(struct m5602_camera *cam);

static int m5602_read_bridge(struct m5602_camera *cam, u8 address, u8 *i2c_data);
static int m5602_read_sensor(struct m5602_camera *cam, const u8 address, u8 *i2c_data, const u8 len);

static int m5602_write_sensor(struct m5602_camera *cam, const u8 address, u8 *i2c_data, const u8 len);
static int m5602_write_bridge(struct m5602_camera *cam, u8 address, u8 i2c_data);

static void m5602_post_proc(struct work_struct *m5602_work);
static void m5602_release_buffers(struct m5602_camera *cam);

static int m5602_start_transfer(struct m5602_camera *cam);
static int m5602_stop_transfer(struct m5602_camera *cam);

static int v4l_m5602_open(struct inode *inode, struct file *filp);
static int v4l_m5602_release(struct inode *inode, struct file *filp);

static int v4l_m5602_mmap(struct file *filp, struct vm_area_struct *vma);
static int probe_sensor(struct m5602_camera *cam);
static int v4l_m5602_ioctl(struct inode *inode,
			   struct file *file,
			   unsigned int cmd,
			   unsigned long arg);

static int v4l_m5602_do_ioctl(struct inode *inode,
			      struct file *file,
			      unsigned int ioctlnr,
			      void *arg);

int s5k83a_get_ctrl(struct m5602_camera *cam, struct v4l2_control *ctrl);
int s5k83a_set_ctrl(struct m5602_camera *cam, const struct v4l2_control *ctrl);

static void m5602_dump_bridge(struct m5602_camera *cam);
static void m5602_dump_sensor(struct m5602_camera *cam);

static struct m5602_sensor S5K83A = {
	.name = "Samsung S5K83A",

	.i2c_slave_id = 0x5a,

	.get_ctrl = s5k83a_get_ctrl,
	.set_ctrl = s5k83a_set_ctrl,

	.qctrl = {},

	.cropcap = {
		.bounds = {
			.left = 0,
			.top = 0,
			.width = M5602_DEFAULT_FRAME_WIDTH,
			.height = M5602_DEFAULT_FRAME_HEIGHT
		},

		.defrect = {
			.left = 0,
			.top = 0,
			.width = M5602_DEFAULT_FRAME_WIDTH,
			.height = M5602_DEFAULT_FRAME_HEIGHT
		}
	}
};

static const unsigned char bridge_urb_skeleton[4] =
{
	0x13, 0x00, 0x81, 0x00
};

static unsigned char sensor_urb_skeleton[24] =
{
	0x23, 0x74, 0x81, 0x06,
	0x23, 0x62, 0x81, 0x80,
	0x13, M5602_XB_I2C_DEV_ADDR, 0x81, S5K83A_I2C_SLAVE_WRITE_ADDRESS,
	0x13, M5602_XB_I2C_REG_ADDR, 0x81, 0x00,
	0x13, M5602_XB_I2C_DATA, 0x81, 0x00,
	0x13, M5602_XB_I2C_CTRL, 0x81, 0x11
};

static const unsigned char init_s5k83a[][4] =
{
    {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},    // 0x13
    {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},   // 0x12
    {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},    // 0x15
    {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},   // 0x14
    {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},       // 0x60
    {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00},    // 0x00
	{BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00},    // 0x01

	{SENSOR, 0xec, 0x04, 0x00},
	{SENSOR, 0xaf, 0x01, 0x00},
	{SENSOR, 0xec, 0x00, 0x00},
	{SENSOR, 0x7b, 0xf0, 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, 0x20, 0x00},
	{SENSOR, 0x04, 0xf0, 0x00},
	{SENSOR, 0x05, 0x0b, 0x00},
	{SENSOR, 0xec, 0x05, 0x00},

    {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},    // 0x15
    {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},   // 0x14
    {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},       // 0x60
    {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},    // 0x00
    {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},// 0x02
    {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},  // 0x04
    {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},        // 0x0a
    {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},     // 0x06
	{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},        // 0x0a
    {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},        // 0x0a
    {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},     // 0x07
	{BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
	{BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
	{BRIDGE, M5602_XB_HSYNC_PARA, 0x87, 0x00},
    {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},        // 0x0a
    {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},    // 0x15
    {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},   // 0x14

	{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, 0x14, 0x00, 0x20},
	{SENSOR, 0x0d, 0x00, 0x7d},
	{SENSOR, 0x1b, 0x0d, 0x05},

    {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},    // 0x15
    {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},   // 0x14
    {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},       // 0x60
    {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},    // 0x00
    {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},// 0x02
    {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},  // 0x04
    {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},        // 0x0a
    {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},     // 0x06
	{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},        // 0x0a
    {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},        // 0x0a
    {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},     // 0x07
	{BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
	{BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
	{BRIDGE, M5602_XB_HSYNC_PARA, 0x87, 0x00},

    {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},        // 0x0a
    {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},       // 0x77
    {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},       // 0x76
    {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00},      // 0x74
    {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00},     // 0x72
    {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},     // 0x70
    {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},      // 0x75
    {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},     // 0x73
    {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},     // 0x71
    {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00},    // 0x15
    {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00},   // 0x14
    {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},    // 0x15
    {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},   // 0x14
    {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},       // 0x60
    {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},    // 0x00
	{BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},    // 0x13
    {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},   // 0x12
    {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},    // 0x15
    {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00},   // 0x14
    {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},       // 0x77
    {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00},       // 0x76
    {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},      // 0x74
    {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00},     // 0x72
    {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},     // 0x70
    {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},      // 0x75
    {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00},    // 0x69

	{SENSOR, 0xec, 0x04, 0x00},
	{SENSOR, 0xaf, 0x01, 0x00},
	{SENSOR, 0xec, 0x05, 0x00}, // no
	{SENSOR, 0x7b, 0xff, 0x00}, // no ( ff ( init value )is very dark) || 71 and f0 better
	{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}, // some values like 0x10 give a blue-purple image
	{SENSOR, 0x04, 0xf0, 0x00},
	{SENSOR, 0x05, 0x0b, 0x00},
	{SENSOR, 0xec, 0x05, 0x00},

    {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},    // 0x15 /* I have the same image for values between 0x00 and 0x10, for higher values I have a very bad ( or I don't have) image*/
    {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},   // 0x14    under 80 don't work, highter depend on value
	//    {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},  useless
	//    {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},  seems useless ( if I remove it, it doesn't change the image but I can't change the value )
	//    {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00}, useless ( isn't it weird ? you said in the doc : "defines the number of pixels in height"? )
    {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00}, // 0x04 ... seems important
	//    {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00}, useless
    {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},      // 0x06
	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, // no
	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, // no
	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00}, // no
	{BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00}, // no 01
	{BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00}, // under 0xe0 the low of the image is black, at 0x00 half( the low ) the image is black
	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
	{BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
    {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},        // 0x0a
    {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, // no   0x07
	{BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00}, // no
	{BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00}, // no
	{BRIDGE, M5602_XB_HSYNC_PARA, 0x7f, 0x00}, // no

    {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},        // 0x0a
    {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},    // 0x15
    {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},   // 0x14

	{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, 0x14, 0x00, 0x20},
	{SENSOR, 0x0d, 0x00, 0x7d},
	{SENSOR, 0x1b, 0x0d, 0x05},
    
    
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // SENSOR TEST SEQUENCE:
    
    
    {SENSOR,0x00, B8(00000100), 0x00},   // only first byte is important
                    /* bits:
                    0   ??
                    1   0 darker, 1 brighter
                    2   0: sensor is more sensitible on light, 1 OK
                    3   ??
                    4   0 image is gray, 1 image is yellow (if bit 6 of register 0x1 is set, color is normal!? wtf?)
                    5   ??
                    6   ??
                    7   ??
                    */
    
    {SENSOR,0x01, B8(01010000), 0x00},   // only first byte is important, 0x50 si "default" value
                /* bits:
                    0   0 OK, 1 bad image
                    1   same
                    2   0 OK, 1 image is horizontaly reducted on 50% 
                    3   0 OK, 1 image is horizontaly reducted on 25% 
                    4   1 OK, 0 unstable colors
                    5   0 OK, 1 unstable image
                    6   1 gray image, 0 yellow image  (if bit 4 of register 0x0 is set, color is normal!? wtf?)
                    7   0 normal image, 1 horizontaly flipped (and purple color)
                */
     
     {SENSOR,0x02, B8(00000000), 0x00},   // only first byte is important
                /* bits:
                     0  0 OK, 1 image is moved up by 50%
                     1:7  ??
                 */
     
     {SENSOR,0x03, B8(00000001), B8(00000000)},    // both byts are important
                /* bits of first byte:
                    0   0 purple, 1 gray color
                    1:5   ??
                    6:7 00 OK, different move image up
                      
                   bits of second byte:
                    0:1   00 OK, different move image right
                    2:7   ???
                */     
     
     {SENSOR,0x4, B8(00000000), B8(00000000)},  // both byts are important
                /* bits of first byte:
                    0:1   0 OK, 1 move image right
                    2:7   ??
                      
                   bits of second byte:
                    0   ??
                    1:5   0 OK, 1 yellow image
                    6:7 0 Ok, different move image right (and yellow image)
                */     
     
     
//     {SENSOR,0x5, 0x00, 0x00},    // TEST ME
//     {SENSOR,0x6, 0xf0, 0x00},    // "vertical centralizator". TEST ME
//     {SENSOR,0x7, 0x68, 0xe8},    // DONT TOUCH. "image destructor" (in czech: kurvítko), TEST ME AGAIN
//     {SENSOR,0x8, 0x82, 0x2},     // DONT TOUCH. same as previous, TEST ME AGAIN
//     {SENSOR,0x9, 0x8, 0x88},     // DONT TOUCH. same, TEST ME AGAIN 
     
     {SENSOR,0xa, 0x80, 0x80},  // TEST ME
     {SENSOR,0xb, 0x82, 0x2},   // TEST ME     
     {SENSOR,0xc, 0xd, 0xd},    // TEST ME
     
     {SENSOR,0xd, 0x0, 0x0},    // TEST ME
     {SENSOR,0xe, 0xff, 0xff},   // "initial brightness" (0x50 is dark, 0x90 normal, 0xff too normal), TEST ME
//     {SENSOR,0xf, 0x2, 0x2},      // wtf? if use, image is dark with any values, TEST ME
     
     {SENSOR,0x10, 0xe5, 0xff}, // TEST ME 
     {SENSOR,0x11, 0x0, 0x1},  // TEST ME 
     {SENSOR,0x12, 0x20, 0x20}, // TEST ME 
     
     
     {SENSOR,0x13, 0x00, B8(11100011) },  // only second byte change things
            /* bits:
                    0:2  ???
                    3:4  00: about 15 fps, all diferent about 3ftp
                    5:7  ??
            */
     
//     {SENSOR,0x14, 0x0, 0x0},     // TEST ME
     {SENSOR,0x15, 0x20, 0x20},     // TEST ME
//     {SENSOR,0x16, 0x20, 0x20},     // DONT TOUCH. image destructor, TEST ME AGAIN
     {SENSOR,0x17, 0x40, 0x0},      // TEST ME

     {SENSOR,0x18, 0x0, 0x0},       // TEST ME
     {SENSOR,0x19, 0x0, 0x0},       // TEST ME
//     {SENSOR,0x1a, 0x18, 0x98},   // DONT TOUCH. image destructor, TEST ME AGAIN
     
     {SENSOR,0x1b, 0xd, 0x0},       // TEST ME
     {SENSOR,0x1c, 0x5, 0x7f},      // TEST ME
     {SENSOR,0x1d, 0x80, 0x0},      // TEST ME
     {SENSOR,0x1e, 0x80, 0x0},      // TEST ME
     {SENSOR,0x1f, 0x0, 0x0},       // TEST ME     
     {SENSOR,0x20, 0x6, 0x86},      // TEST ME
     {SENSOR,0x21, 0x4, 0x0},       // TEST ME
     {SENSOR,0x22, 0x7f, 0xd0},     // TEST ME
     {SENSOR,0x23, 0xd3, 0x53},     // TEST ME
     {SENSOR,0x24, 0x0, 0x0},       // TEST ME
     {SENSOR,0x25, 0x65, 0x65},     // TEST ME
     {SENSOR,0x26, 0x11, 0x0},      // TEST ME
     {SENSOR,0x27, 0x0, 0x0},       // TEST ME
     {SENSOR,0x28, 0x0, 0x0},       // TEST ME     
     {SENSOR,0x29, 0x0, 0x0},       // TEST ME
     {SENSOR,0x2a, 0x5, 0x5},       // TEST ME
     {SENSOR,0x2b, 0x1, 0x1},       // TEST ME
     {SENSOR,0x2c, 0x60, 0xe0},     // TEST ME
     {SENSOR,0x2d, 0x80, 0x0},      // TEST ME
     {SENSOR,0x2e, 0x3a, 0x3a},     // TEST ME
     {SENSOR,0x2f, 0x2, 0x0},       // TEST ME
     {SENSOR,0x30, 0x80, 0x0},      // TEST ME     
     {SENSOR,0x31, 0x80, 0x0},      // TEST ME
     {SENSOR,0x32, 0x5, 0x5},       // TEST ME
     {SENSOR,0x33, 0x1, 0x1},       // TEST ME
     {SENSOR,0x34, 0xe0, 0x0},      // TEST ME
     {SENSOR,0x35, 0x80, 0x0},      // TEST ME
     {SENSOR,0x36, 0x3a, 0x2},      // TEST ME
     {SENSOR,0x37, 0x0, 0x2},       // TEST ME
     {SENSOR,0x38, 0x0, 0x7f},      // TEST ME
     {SENSOR,0x39, 0xff, 0x0},      // TEST ME
     {SENSOR,0x3a, 0x6, 0x0},       // TEST ME
     {SENSOR,0x3b, 0x1, 0x0},       // TEST ME
     {SENSOR,0x3c, 0x60, 0xe0},     // TEST ME
     {SENSOR,0x3d, 0xff, 0x0},      // TEST ME
     {SENSOR,0x3e, 0x3a, 0x3a},     // TEST ME
     {SENSOR,0x3f, 0x2, 0x2},       // TEST ME
     {SENSOR,0x40, 0x7f, 0x80},     // TEST ME
     {SENSOR,0x41, 0x83, 0x3},      // TEST ME
     {SENSOR,0x42, 0xb, 0xb},       // TEST ME
     {SENSOR,0x43, 0x2, 0xd},       // TEST ME
     {SENSOR,0x44, 0x0, 0xd},       // TEST ME
     {SENSOR,0x45, 0x2, 0x2},       // TEST ME
     {SENSOR,0x46, 0xd, 0xd},       // TEST ME
     {SENSOR,0x47, 0x2, 0x2},       // TEST ME
     {SENSOR,0x48, 0xd, 0xd},       // TEST ME
     {SENSOR,0x49, 0x0, 0x0},       // TEST ME
     {SENSOR,0x4a, 0x5a, 0x5a},     // TEST ME
     {SENSOR,0x4b, 0x0, 0x0},       // TEST ME
     {SENSOR,0x4c, 0x10, 0x10},     // TEST ME
     {SENSOR,0x4d, 0x0, 0x0},       // TEST ME
     {SENSOR,0x4e, 0x7f, 0xff},     // TEST ME
     {SENSOR,0x4f, 0xc3, 0xc3},     // TEST ME
     {SENSOR,0x50, 0xff, 0xff},     // TEST ME
     {SENSOR,0x51, 0x0, 0xff},      // TEST ME
     {SENSOR,0x52, 0xc3, 0xc3},     // TEST ME
     {SENSOR,0x53, 0xff, 0xff},     // TEST ME
     {SENSOR,0x54, 0xff, 0xff},     // TEST ME
     {SENSOR,0x55, 0xc3, 0xc3},     // TEST ME
     {SENSOR,0x56, 0xff, 0xff},     // TEST ME
     {SENSOR,0x57, 0x60, 0x1b},     // TEST ME
     {SENSOR,0x58, 0x0, 0x1b},      // TEST ME
     {SENSOR,0x59, 0x40, 0x40},     // TEST ME
     {SENSOR,0x5a, 0x28, 0x28},     // TEST ME
     {SENSOR,0x5b, 0x8, 0x88},      // TEST ME
     {SENSOR,0x5c, 0xff, 0x14},     // TEST ME
     {SENSOR,0x5d, 0x10, 0x10},     // TEST ME
     {SENSOR,0x5e, 0x5, 0x5},       // TEST ME
     {SENSOR,0x5f, 0x0, 0x0},       // TEST ME
     {SENSOR,0x60, 0x11, 0x11},     // TEST ME
     {SENSOR,0x61, 0x60, 0xff},     // TEST ME
     {SENSOR,0x62, 0xff, 0x8},      // TEST ME
     {SENSOR,0x63, 0x0, 0x0},       // TEST ME
     {SENSOR,0x64, 0x8, 0x0},       // TEST ME
     
     {SENSOR,0x65, 0x0, 0x0},       // TEST ALL FOLLOWING REGISTERS...
     {SENSOR,0x66, 0x0, 0x0},
     {SENSOR,0x67, 0x0, 0x0},
     {SENSOR,0x68, 0x0, 0x0},       
     {SENSOR,0x69, 0x0, 0x0},
     {SENSOR,0x6a, 0x0, 0x0},
     {SENSOR,0x6b, 0x0, 0x0},
     {SENSOR,0x6c, 0x0, 0x0},
     {SENSOR,0x6d, 0x0, 0x0},
     {SENSOR,0x6e, 0x0, 0x0},
     {SENSOR,0x6f, 0x0, 0x0},
     {SENSOR,0x70, 0x0, 0x0},
     {SENSOR,0x71, 0x0, 0x0},
     {SENSOR,0x72, 0x0, 0x0},
     {SENSOR,0x73, 0x0, 0x0},
     {SENSOR,0x74, 0x0, 0x0},
     {SENSOR,0x75, 0x0, 0x0},
     {SENSOR,0x76, 0x0, 0x0},
     {SENSOR,0x77, 0x0, 0x0},
     {SENSOR,0x78, 0x0, 0x0},
     {SENSOR,0x79, 0x0, 0x0},
     {SENSOR,0x7a, 0x0, 0x0},
     {SENSOR,0x7b, 0x0, 0x0},
     {SENSOR,0x7c, 0x0, 0x0},
     {SENSOR,0x7d, 0x0, 0x0},
     {SENSOR,0x7e, 0x0, 0x0},
     {SENSOR,0x7f, 0x0, 0x0},
     {SENSOR,0x80, 0x0, 0x0},
     {SENSOR,0x81, 0x0, 0x0},
     {SENSOR,0x82, 0x0, 0x0},
     {SENSOR,0x83, 0x0, 0x0},
     {SENSOR,0x84, 0x0, 0x0},
     {SENSOR,0x85, 0x0, 0x0},
     {SENSOR,0x86, 0x0, 0x0},
     {SENSOR,0x87, 0x0, 0x0},
     {SENSOR,0x88, 0x0, 0x0},
     {SENSOR,0x89, 0x0, 0x0},
     {SENSOR,0x8a, 0x0, 0x0},
     {SENSOR,0x8b, 0x0, 0x0},
     {SENSOR,0x8c, 0x0, 0x0},
     {SENSOR,0x8d, 0x0, 0x0},
     {SENSOR,0x8e, 0x0, 0x0},
     {SENSOR,0x8f, 0x0, 0x0},
     {SENSOR,0x90, 0x0, 0x0},
     {SENSOR,0x91, 0x0, 0x0},
     {SENSOR,0x92, 0x0, 0x0},
     {SENSOR,0x93, 0x0, 0x0},
     {SENSOR,0x94, 0x0, 0x0},
     {SENSOR,0x95, 0x0, 0x0},
     {SENSOR,0x96, 0x0, 0x0},
     {SENSOR,0x97, 0x0, 0x0},
     {SENSOR,0x98, 0x0, 0x0},
     {SENSOR,0x99, 0x0, 0x0},
     {SENSOR,0x9a, 0x0, 0x0},
     {SENSOR,0x9b, 0x0, 0x0},
     {SENSOR,0x9c, 0x0, 0x0},
     {SENSOR,0x9d, 0x0, 0x0},
     {SENSOR,0x9e, 0x0, 0x0},
     {SENSOR,0x9f, 0x0, 0x0},
     {SENSOR,0xa0, 0x0, 0x0},
     {SENSOR,0xa1, 0x0, 0x0},
     {SENSOR,0xa2, 0x0, 0x0},
     {SENSOR,0xa3, 0x0, 0x0},
     {SENSOR,0xa4, 0x0, 0x0},
     {SENSOR,0xa5, 0x0, 0x0},
     {SENSOR,0xa6, 0x0, 0x0},
     {SENSOR,0xa7, 0x0, 0x0},
     {SENSOR,0xa8, 0x0, 0x0},
     {SENSOR,0xa9, 0x0, 0x0},
     {SENSOR,0xaa, 0x0, 0x0},
     {SENSOR,0xab, 0x0, 0x0},
     {SENSOR,0xac, 0x0, 0x0},
     {SENSOR,0xad, 0x0, 0x0},
     {SENSOR,0xae, 0x0, 0x0},
     {SENSOR,0xaf, 0x0, 0x0},
     {SENSOR,0xb0, 0x0, 0x0},
     {SENSOR,0xb1, 0x0, 0x0},
     {SENSOR,0xb2, 0x0, 0x0},
     {SENSOR,0xb3, 0x0, 0x0},
     {SENSOR,0xb4, 0x0, 0x0},
     {SENSOR,0xb5, 0x0, 0x0},
     {SENSOR,0xb6, 0x0, 0x0},
     {SENSOR,0xb7, 0x0, 0x0},
     {SENSOR,0xb8, 0x0, 0x0},
     {SENSOR,0xb9, 0x0, 0x0},
     {SENSOR,0xba, 0x0, 0x0},
     {SENSOR,0xbb, 0x0, 0x0},
     {SENSOR,0xbc, 0x0, 0x0},
     {SENSOR,0xbd, 0x0, 0x0},
     {SENSOR,0xbe, 0x0, 0x0},
     {SENSOR,0xbf, 0x0, 0x0},
     {SENSOR,0xc0, 0x0, 0x0},
     {SENSOR,0xc1, 0x0, 0x0},
     {SENSOR,0xc2, 0x0, 0x0},
     {SENSOR,0xc3, 0x0, 0x0},
     {SENSOR,0xc4, 0x0, 0x0},
     {SENSOR,0xc5, 0x0, 0x0},
     {SENSOR,0xc6, 0x0, 0x0},
     {SENSOR,0xc7, 0x0, 0x0},
     {SENSOR,0xc8, 0x0, 0x0},
     {SENSOR,0xc9, 0x0, 0x0},
     {SENSOR,0xca, 0x0, 0x0},
     {SENSOR,0xcb, 0x0, 0x0},
     {SENSOR,0xcc, 0x0, 0x0},
     
     {SENSOR,0xcd, 0x6, 0x6},
     {SENSOR,0xce, 0x1, 0x0},
     {SENSOR,0xcf, 0x60, 0xe0},
     {SENSOR,0xd0, 0x80, 0x0},
     {SENSOR,0xd1, 0x3a, 0x3a},
     {SENSOR,0xd2, 0x2, 0x2},
     {SENSOR,0xd3, 0x0, 0x7f},
     {SENSOR,0xd4, 0xff, 0x0},
     {SENSOR,0xd5, 0x0, 0x0},
     {SENSOR,0xd6, 0x0, 0x0},
     {SENSOR,0xd7, 0x7f, 0x70},
     {SENSOR,0xd8, 0x0, 0x0},
     {SENSOR,0xd9, 0x0, 0x0},
     {SENSOR,0xda, 0x1, 0x1},
     {SENSOR,0xdb, 0x40, 0x0},
     {SENSOR,0xdc, 0x0, 0x0},
     {SENSOR,0xdd, 0x0, 0x0},
     {SENSOR,0xde, 0x0, 0x0},
     {SENSOR,0xdf, 0x78, 0x78},
     {SENSOR,0xe0, 0x0, 0x0},
     {SENSOR,0xe1, 0x0, 0x0},
     {SENSOR,0xe2, 0x0, 0x0},
     {SENSOR,0xe3, 0x20, 0xa0},
     {SENSOR,0xe4, 0x80, 0x0},
     {SENSOR,0xe5, 0x0, 0x0},
     {SENSOR,0xe6, 0x1, 0x1},
     {SENSOR,0xe7, 0x20, 0x20},
     {SENSOR,0xe8, 0x0, 0x0},
     {SENSOR,0xe9, 0x0, 0x0},
     {SENSOR,0xea, 0x1, 0x0},
     {SENSOR,0xeb, 0x0, 0x80},
     {SENSOR,0xec, 0x85, 0x5},
     {SENSOR,0xed, 0x0, 0x0},
     {SENSOR,0xee, 0x0, 0x0},
     {SENSOR,0xef, 0x90, 0x0},     
     {SENSOR,0xf0, 0xff, 0x0},
     {SENSOR,0xf1, 0x0, 0x0},
     {SENSOR,0xf2, 0x0, 0x0},
     {SENSOR,0xf3, 0x7f, 0xc0},
     {SENSOR,0xf4, 0x0, 0x0},
     {SENSOR,0xf5, 0x0, 0x0},
     {SENSOR,0xf6, 0x0, 0x0},
     {SENSOR,0xf7, 0x60, 0x60},
     {SENSOR,0xf8, 0x0, 0x0},
     {SENSOR,0xf9, 0x0, 0x0},
     {SENSOR,0xfa, 0x0, 0x0},
     {SENSOR,0xfb, 0x0, 0x80},
     {SENSOR,0xfc, 0xff, 0x0},
     {SENSOR,0xfd, 0x0, 0x0},
     {SENSOR,0xfe, 0x0, 0x0},
     {SENSOR,0xff, 0x0, 0x0}
    
};

#endif /*M5602_H_*/
