// SPDX-License-Identifier: GPL-2.0
/*
 * OmniVision OX02F10 image sensor driver
 *
 * The module register sequence and its nominal 1080p30 RAW10 mode are
 * retained from the board driver. Changes to the CSI-2 configuration or
 * timing require a matching register sequence from the module vendor.
 */
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h>
#include <media/v4l2-subdev.h>

#define OX02F10_REG_MODE_SELECT		0x0100
#define OX02F10_MODE_STANDBY		0x00
#define OX02F10_MODE_STREAMING		0x01
#define OX02F10_REG_SOFTWARE_RESET	0x0103
#define OX02F10_REG_CHIP_ID		0x300a
/* Register 0x300a contains 0x58; register 0x300b contains 0x03. */
#define OX02F10_CHIP_ID			0x5803
#define OX02F10_WIDTH			1920
#define OX02F10_HEIGHT			1080
#define OX02F10_FPS			30
#define OX02F10_BITS_PER_PIXEL		10
#define OX02F10_XCLK_FREQ		24000000
#define OX02F10_NUM_DATA_LANES		4
#define OX02F10_LINK_FREQ			480000000LL
#define OX02F10_MEDIA_BUS_CODE		MEDIA_BUS_FMT_SRGGB10_1X10

#define OX02F10_REG_EXPOSURE		0x3501
#define OX02F10_REG_ANALOG_GAIN		0x3506
#define OX02F10_VTS_DEFAULT		0x0250
#define OX02F10_EXPOSURE_MIN		1
#define OX02F10_EXPOSURE_DEFAULT		0x0187
#define OX02F10_EXPOSURE_MARGIN		8

/* Raw gain register encoding retained from the board driver. */
#define OX02F10_ANALOG_GAIN_MIN		0x00
#define OX02F10_ANALOG_GAIN_MAX		0xff
#define OX02F10_ANALOG_GAIN_DEFAULT	0x30

static const s64 ox02f10_link_freq_menu[] = {
	OX02F10_LINK_FREQ,
};

static const struct regmap_config ox02f10_regmap_config = {
	.reg_bits = 16,
	.val_bits = 8,
};

static const struct reg_sequence ox02f10_1920x1080_regs[] = {
	{ 0x0107, 0x01 }, { 0x4d5a, 0x1c }, { 0x4d09, 0xff }, { 0x4d09, 0xdf },
	{ 0x3208, 0x04 }, { 0x4620, 0x04 }, { 0x3208, 0x14 }, { 0x3208, 0x05 },
	{ 0x4620, 0x04 }, { 0x3208, 0x15 }, { 0x3208, 0x02 }, { 0x3507, 0x00 },
	{ 0x3208, 0x12 }, { 0x3208, 0xa2 }, { 0x0301, 0xc8 }, { 0x0303, 0x03 },
	{ 0x0304, 0x01 }, { 0x0305, 0x90 }, { 0x0306, 0x04 }, { 0x0307, 0x03 },
	{ 0x0309, 0x02 }, { 0x0316, 0x00 }, { 0x0317, 0x00 }, { 0x0318, 0x00 },
	{ 0x0323, 0x05 }, { 0x0324, 0x01 }, { 0x0325, 0x20 }, { 0x0362, 0x8e },
	{ 0x0400, 0xe0 }, { 0x0401, 0x7e }, { 0x0403, 0xde }, { 0x0404, 0x34 },
	{ 0x0405, 0x3e }, { 0x0406, 0x5c }, { 0x0407, 0x08 }, { 0x0408, 0xe0 },
	{ 0x0409, 0x4e }, { 0x040a, 0xde }, { 0x040b, 0x34 }, { 0x040c, 0xb3 },
	{ 0x040d, 0x72 }, { 0x040e, 0x08 }, { 0x2803, 0xfe }, { 0x280b, 0x00 },
	{ 0x280c, 0x79 }, { 0x3001, 0x03 }, { 0x3002, 0xf8 }, { 0x3005, 0x80 },
	{ 0x3007, 0x01 }, { 0x3008, 0x80 }, { 0x3012, 0x41 }, { 0x3020, 0x05 },
	{ 0x3700, 0x28 }, { 0x3701, 0x15 }, { 0x3702, 0x19 }, { 0x3703, 0x23 },
	{ 0x3704, 0x0a }, { 0x3705, 0x00 }, { 0x3706, 0x3e }, { 0x3707, 0x0d },
	{ 0x3708, 0x50 }, { 0x3709, 0x5a }, { 0x370a, 0x00 }, { 0x370b, 0x96 },
	{ 0x3711, 0x11 }, { 0x3712, 0x13 }, { 0x3717, 0x02 }, { 0x3718, 0x73 },
	{ 0x372c, 0x40 }, { 0x3733, 0x01 }, { 0x3738, 0x36 }, { 0x3739, 0x36 },
	{ 0x373a, 0x25 }, { 0x373b, 0x25 }, { 0x373f, 0x21 }, { 0x3740, 0x21 },
	{ 0x3741, 0x21 }, { 0x3742, 0x21 }, { 0x3747, 0x28 }, { 0x3748, 0x28 },
	{ 0x3749, 0x19 }, { 0x3755, 0x1a }, { 0x3756, 0x0a }, { 0x3757, 0x1c },
	{ 0x3765, 0x19 }, { 0x3766, 0x05 }, { 0x3767, 0x05 }, { 0x3768, 0x13 },
	{ 0x376c, 0x07 }, { 0x3778, 0x20 }, { 0x377c, 0xc8 }, { 0x3781, 0x02 },
	{ 0x3783, 0x02 }, { 0x379c, 0x58 }, { 0x379e, 0x00 }, { 0x379f, 0x00 },
	{ 0x37a0, 0x00 }, { 0x37bc, 0x22 }, { 0x37c0, 0x01 }, { 0x37c4, 0x3e },
	{ 0x37c5, 0x3e }, { 0x37c6, 0x2a }, { 0x37c7, 0x28 }, { 0x37c8, 0x02 },
	{ 0x37c9, 0x12 }, { 0x37cb, 0x29 }, { 0x37cd, 0x29 }, { 0x37d2, 0x00 },
	{ 0x37d3, 0x73 }, { 0x37d6, 0x00 }, { 0x37d7, 0x6b }, { 0x37dc, 0x00 },
	{ 0x37df, 0x54 }, { 0x37e2, 0x00 }, { 0x37e3, 0x00 }, { 0x37f8, 0x00 },
	{ 0x37f9, 0x01 }, { 0x37fa, 0x00 }, { 0x37fb, 0x19 }, { 0x3c03, 0x01 },
	{ 0x3c04, 0x01 }, { 0x3c06, 0x21 }, { 0x3c08, 0x01 }, { 0x3c09, 0x01 },
	{ 0x3c0a, 0x01 }, { 0x3c0b, 0x21 }, { 0x3c13, 0x21 }, { 0x3c14, 0x82 },
	{ 0x3c16, 0x13 }, { 0x3c21, 0x00 }, { 0x3c22, 0xf3 }, { 0x3c37, 0x12 },
	{ 0x3c38, 0x31 }, { 0x3c3c, 0x00 }, { 0x3c3d, 0x03 }, { 0x3c44, 0x16 },
	{ 0x3c5c, 0x8a }, { 0x3c5f, 0x03 }, { 0x3c61, 0x80 }, { 0x3c6f, 0x2b },
	{ 0x3c70, 0x5f }, { 0x3c71, 0x2c }, { 0x3c72, 0x2c }, { 0x3c73, 0x2c },
	{ 0x3c76, 0x12 }, { 0x3182, 0x12 }, { 0x320e, 0x00 }, { 0x320f, 0x00 },
	{ 0x3211, 0x61 }, { 0x3215, 0xcd }, { 0x3219, 0x08 }, { 0x3506, 0x30 },
	{ 0x350a, 0x01 }, { 0x350b, 0x00 }, { 0x350c, 0x00 }, { 0x3586, 0x60 },
	{ 0x358a, 0x01 }, { 0x358b, 0x00 }, { 0x358c, 0x00 }, { 0x3541, 0x00 },
	{ 0x3542, 0x04 }, { 0x3546, 0x20 }, { 0x3548, 0x04 }, { 0x3549, 0x40 },
	{ 0x354a, 0x01 }, { 0x354b, 0x00 }, { 0x354c, 0x00 }, { 0x35c1, 0x00 },
	{ 0x35c2, 0x02 }, { 0x35c6, 0xa0 }, { 0x3600, 0x8f }, { 0x3605, 0x16 },
	{ 0x3609, 0xf0 }, { 0x360a, 0x01 }, { 0x360e, 0x1d }, { 0x360f, 0x10 },
	{ 0x3610, 0x70 }, { 0x3611, 0x3a }, { 0x3612, 0x28 }, { 0x361a, 0x29 },
	{ 0x361b, 0x6c }, { 0x361c, 0x0b }, { 0x361d, 0x00 }, { 0x361e, 0xfc },
	{ 0x362a, 0x00 }, { 0x364d, 0x0f }, { 0x364e, 0x18 }, { 0x364f, 0x12 },
	{ 0x3653, 0x1c }, { 0x3654, 0x00 }, { 0x3655, 0x1f }, { 0x3656, 0x1f },
	{ 0x3657, 0x0c }, { 0x3658, 0x0a }, { 0x3659, 0x14 }, { 0x365a, 0x18 },
	{ 0x365b, 0x14 }, { 0x365c, 0x10 }, { 0x365e, 0x12 }, { 0x3674, 0x08 },
	{ 0x3677, 0x3a }, { 0x3678, 0x3a }, { 0x3679, 0x19 }, { 0x3802, 0x00 },
	{ 0x3803, 0x68 }, { 0x3806, 0x04 }, { 0x3807, 0xa7 }, { 0x3808, 0x07 },
	{ 0x3809, 0x80 }, { 0x380a, 0x04 }, { 0x380b, 0x38 }, { 0x380c, 0x09 },
	{ 0x380d, 0xf8 }, { 0x380e, 0x02 }, { 0x380f, 0x50 }, { 0x3810, 0x00 },
	{ 0x3811, 0x08 }, { 0x3812, 0x00 }, { 0x3813, 0x04 }, { 0x3816, 0x01 },
	{ 0x3817, 0x01 }, { 0x381c, 0x18 }, { 0x381e, 0x01 }, { 0x381f, 0x01 },
	{ 0x3820, 0x20 }, { 0x3821, 0x19 }, { 0x3832, 0x00 }, { 0x3834, 0x00 },
	{ 0x384c, 0x04 }, { 0x384d, 0xc8 }, { 0x3850, 0x00 }, { 0x3851, 0x42 },
	{ 0x3852, 0x00 }, { 0x3853, 0x40 }, { 0x3858, 0x04 }, { 0x388c, 0x05 },
	{ 0x388d, 0x0e }, { 0x3b40, 0x05 }, { 0x3b41, 0x40 }, { 0x3b42, 0x00 },
	{ 0x3b43, 0x90 }, { 0x3b44, 0x02 }, { 0x3b45, 0x00 }, { 0x3b46, 0x02 },
	{ 0x3b47, 0x00 }, { 0x3b48, 0x19 }, { 0x3b49, 0x12 }, { 0x3b4a, 0x16 },
	{ 0x3b4b, 0x2e }, { 0x3b4c, 0x03 }, { 0x3b4d, 0x00 }, { 0x3b86, 0x00 },
	{ 0x3b87, 0x34 }, { 0x3b88, 0x00 }, { 0x3b89, 0x08 }, { 0x3b8a, 0x05 },
	{ 0x3b8b, 0x00 }, { 0x3b8c, 0x07 }, { 0x3b8d, 0x80 }, { 0x3b8e, 0x00 },
	{ 0x3b8f, 0x00 }, { 0x3b92, 0x05 }, { 0x3b93, 0x00 }, { 0x3b94, 0x07 },
	{ 0x3b95, 0x80 }, { 0x3b9e, 0x09 }, { 0x3d85, 0x05 }, { 0x3d8a, 0x03 },
	{ 0x3d8b, 0xff }, { 0x3d99, 0x00 }, { 0x3d9a, 0x9f }, { 0x3d9b, 0x00 },
	{ 0x3d9c, 0xa0 }, { 0x3da4, 0x00 }, { 0x3da7, 0x50 }, { 0x420e, 0x6b },
	{ 0x420f, 0x6e }, { 0x4210, 0x06 }, { 0x4211, 0xc1 }, { 0x421e, 0x02 },
	{ 0x421f, 0x45 }, { 0x4220, 0xe1 }, { 0x4221, 0x01 }, { 0x4301, 0xff },
	{ 0x4307, 0x03 }, { 0x4308, 0x13 }, { 0x430a, 0x13 }, { 0x430d, 0x93 },
	{ 0x430f, 0x57 }, { 0x4310, 0x95 }, { 0x4311, 0x16 }, { 0x4316, 0x00 },
	{ 0x4317, 0x38 }, { 0x4319, 0x03 }, { 0x431a, 0x00 }, { 0x431b, 0x00 },
	{ 0x431d, 0x2a }, { 0x431e, 0x11 }, { 0x431f, 0x20 }, { 0x4320, 0x19 },
	{ 0x4323, 0x80 }, { 0x4324, 0x00 }, { 0x4503, 0x4e }, { 0x4505, 0x00 },
	{ 0x4509, 0x00 }, { 0x450a, 0x00 }, { 0x4580, 0xf8 }, { 0x4583, 0x07 },
	{ 0x4584, 0x6a }, { 0x4585, 0x08 }, { 0x4586, 0x05 }, { 0x4587, 0x04 },
	{ 0x4588, 0x73 }, { 0x4589, 0x05 }, { 0x458a, 0x1f }, { 0x458b, 0x02 },
	{ 0x458c, 0xdc }, { 0x458d, 0x03 }, { 0x458e, 0x02 }, { 0x4597, 0x07 },
	{ 0x4598, 0x40 }, { 0x4599, 0x0e }, { 0x459a, 0x0e }, { 0x459b, 0xf5 },
	{ 0x459c, 0xf1 }, { 0x4602, 0x00 }, { 0x4603, 0x13 }, { 0x4604, 0x00 },
	{ 0x4609, 0x0a }, { 0x460a, 0x30 }, { 0x4610, 0x00 }, { 0x4611, 0x40 },
	{ 0x4612, 0x01 }, { 0x4613, 0x00 }, { 0x4614, 0x00 }, { 0x4615, 0x40 },
	{ 0x4616, 0x01 }, { 0x4617, 0x00 }, { 0x4800, 0x04 }, { 0x480a, 0x22 },
	{ 0x4813, 0xe4 }, { 0x4814, 0x2a }, { 0x4837, 0x20 }, { 0x484b, 0x47 },
	{ 0x484f, 0x00 }, { 0x4887, 0x51 }, { 0x4d00, 0x4a }, { 0x4d01, 0x18 },
	{ 0x4d05, 0xff }, { 0x4d06, 0x88 }, { 0x4d08, 0x63 }, { 0x4d09, 0xdf },
	{ 0x4d15, 0x7d }, { 0x4d1a, 0x20 }, { 0x4d30, 0x0a }, { 0x4d31, 0x00 },
	{ 0x4d34, 0x7d }, { 0x4d3c, 0x7d }, { 0x4f00, 0x7f }, { 0x4f01, 0xff },
	{ 0x4f02, 0xff }, { 0x4f03, 0x20 }, { 0x4f04, 0xe0 }, { 0x6a00, 0x00 },
	{ 0x6a01, 0x20 }, { 0x6a02, 0x00 }, { 0x6a03, 0x20 }, { 0x6a04, 0x02 },
	{ 0x6a05, 0x80 }, { 0x6a06, 0x01 }, { 0x6a07, 0xe0 }, { 0x6a08, 0xcf },
	{ 0x6a09, 0x01 }, { 0x6a0a, 0x40 }, { 0x6a20, 0x00 }, { 0x6a21, 0x02 },
	{ 0x6a22, 0x00 }, { 0x6a23, 0x00 }, { 0x6a24, 0x00 }, { 0x6a25, 0x00 },
	{ 0x6a26, 0x00 }, { 0x6a27, 0x00 }, { 0x6a28, 0x00 }, { 0x5000, 0x8f },
	{ 0x5001, 0x75 }, { 0x5002, 0x7f }, { 0x5003, 0x7a }, { 0x5004, 0x3e },
	{ 0x5005, 0x1e }, { 0x5006, 0x1e }, { 0x5007, 0x1e }, { 0x5008, 0x00 },
	{ 0x500c, 0x00 }, { 0x502c, 0x00 }, { 0x502e, 0x00 }, { 0x502f, 0x00 },
	{ 0x504b, 0x00 }, { 0x5053, 0x00 }, { 0x505b, 0x00 }, { 0x5063, 0x00 },
	{ 0x5070, 0x00 }, { 0x5074, 0x04 }, { 0x507a, 0x04 }, { 0x507b, 0x09 },
	{ 0x5500, 0x02 }, { 0x5700, 0x02 }, { 0x5900, 0x02 }, { 0x6007, 0x04 },
	{ 0x6008, 0x05 }, { 0x6009, 0x02 }, { 0x600b, 0x08 }, { 0x600c, 0x07 },
	{ 0x600d, 0x88 }, { 0x6016, 0x00 }, { 0x6027, 0x04 }, { 0x6028, 0x05 },
	{ 0x6029, 0x02 }, { 0x602b, 0x08 }, { 0x602c, 0x07 }, { 0x602d, 0x88 },
	{ 0x6047, 0x04 }, { 0x6048, 0x05 }, { 0x6049, 0x02 }, { 0x604b, 0x08 },
	{ 0x604c, 0x07 }, { 0x604d, 0x88 }, { 0x6067, 0x04 }, { 0x6068, 0x05 },
	{ 0x6069, 0x02 }, { 0x606b, 0x08 }, { 0x606c, 0x07 }, { 0x606d, 0x88 },
	{ 0x6087, 0x04 }, { 0x6088, 0x05 }, { 0x6089, 0x02 }, { 0x608b, 0x08 },
	{ 0x608c, 0x07 }, { 0x608d, 0x88 }, { 0x5e00, 0x00 }, { 0x5e01, 0x09 },
	{ 0x5e02, 0x09 }, { 0x5e03, 0x0a }, { 0x5e04, 0x0a }, { 0x5e05, 0x0a },
	{ 0x5e06, 0x0b }, { 0x5e07, 0x0b }, { 0x5e08, 0x0c }, { 0x5e09, 0x0c },
	{ 0x5e0a, 0x0d }, { 0x5e0b, 0x0d }, { 0x5e0c, 0x0e }, { 0x5e0d, 0x0e },
	{ 0x5e0e, 0x0f }, { 0x5e0f, 0x0f }, { 0x5e10, 0x10 }, { 0x5e11, 0x10 },
	{ 0x5e12, 0x11 }, { 0x5e13, 0x11 }, { 0x5e14, 0x12 }, { 0x5e15, 0x12 },
	{ 0x5e16, 0x12 }, { 0x5e17, 0x12 }, { 0x5e18, 0x13 }, { 0x5e19, 0x13 },
	{ 0x5e1a, 0x13 }, { 0x5e1b, 0x14 }, { 0x5e1c, 0x14 }, { 0x5e1d, 0x14 },
	{ 0x5e1e, 0x15 }, { 0x5e1f, 0x15 }, { 0x5e20, 0x15 }, { 0x5e21, 0x16 },
	{ 0x5e22, 0x00 }, { 0x5e23, 0x02 }, { 0x5e26, 0x00 }, { 0x5e27, 0xff },
	{ 0x5e29, 0x01 }, { 0x5e2a, 0x00 }, { 0x5e2c, 0x01 }, { 0x5e2d, 0x00 },
	{ 0x5e2f, 0x01 }, { 0x5e30, 0x00 }, { 0x5e32, 0x00 }, { 0x5e33, 0x80 },
	{ 0x5e34, 0x00 }, { 0x5e35, 0x00 }, { 0x5e36, 0x80 }, { 0x5e37, 0x00 },
	{ 0x5e38, 0x00 }, { 0x5e39, 0x80 }, { 0x5e3a, 0x00 }, { 0x5e3b, 0x00 },
	{ 0x5e3c, 0x80 }, { 0x5e3d, 0x00 }, { 0x5e3e, 0x00 }, { 0x5e3f, 0x80 },
	{ 0x5e40, 0x00 }, { 0x5e41, 0x00 }, { 0x5e42, 0x80 }, { 0x5e43, 0x00 },
	{ 0x5e44, 0x00 }, { 0x5e45, 0x80 }, { 0x5e46, 0x00 }, { 0x5e47, 0x00 },
	{ 0x5e48, 0x80 }, { 0x5e49, 0x00 }, { 0x5e4a, 0x00 }, { 0x5e4b, 0x80 },
	{ 0x5e4c, 0x00 }, { 0x5e4d, 0x00 }, { 0x5e4e, 0x80 }, { 0x5e50, 0x00 },
	{ 0x5e51, 0x80 }, { 0x5e53, 0x00 }, { 0x5e54, 0x80 }, { 0x5e56, 0x00 },
	{ 0x5e57, 0x40 }, { 0x5e59, 0x00 }, { 0x5e5a, 0x40 }, { 0x5e5c, 0x00 },
	{ 0x5e5d, 0x40 }, { 0x5e5f, 0x00 }, { 0x5e60, 0x40 }, { 0x5e62, 0x00 },
	{ 0x5e63, 0x40 }, { 0x5e65, 0x00 }, { 0x5e66, 0x40 }, { 0x5e68, 0x00 },
	{ 0x5e69, 0x40 }, { 0x5e6b, 0x00 }, { 0x5e6c, 0x40 }, { 0x5e6e, 0x00 },
	{ 0x5e6f, 0x40 }, { 0x5e71, 0x00 }, { 0x5e72, 0x40 }, { 0x5e74, 0x00 },
	{ 0x5e75, 0x40 }, { 0x5e77, 0x00 }, { 0x5e78, 0x40 }, { 0x5e7a, 0x00 },
	{ 0x5e7b, 0x40 }, { 0x5e7d, 0x00 }, { 0x5e7e, 0x40 }, { 0x5e80, 0x00 },
	{ 0x5e81, 0x40 }, { 0x5e83, 0x00 }, { 0x5e84, 0x40 }, { 0x5f00, 0x02 },
	{ 0x5f01, 0x08 }, { 0x5f02, 0x09 }, { 0x5f03, 0x0a }, { 0x5f04, 0x0b },
	{ 0x5f05, 0x0c }, { 0x5f06, 0x0c }, { 0x5f07, 0x0c }, { 0x5f08, 0x0c },
	{ 0x5f09, 0x0c }, { 0x5f0a, 0x0d }, { 0x5f0b, 0x0d }, { 0x5f0c, 0x0d },
	{ 0x5f0d, 0x0d }, { 0x5f0e, 0x0d }, { 0x5f0f, 0x0e }, { 0x5f10, 0x0e },
	{ 0x5f11, 0x0e }, { 0x5f12, 0x0e }, { 0x5f13, 0x0f }, { 0x5f14, 0x0f },
	{ 0x5f15, 0x10 }, { 0x5f16, 0x11 }, { 0x5f17, 0x11 }, { 0x5f18, 0x12 },
	{ 0x5f19, 0x12 }, { 0x5f1a, 0x13 }, { 0x5f1b, 0x13 }, { 0x5f1c, 0x14 },
	{ 0x5f1d, 0x14 }, { 0x5f1e, 0x16 }, { 0x5f1f, 0x16 }, { 0x5f20, 0x16 },
	{ 0x5f21, 0x08 }, { 0x5f22, 0x00 }, { 0x5f23, 0x01 }, { 0x5f26, 0x02 },
	{ 0x5f27, 0x00 }, { 0x5f29, 0x02 }, { 0x5f2a, 0x00 }, { 0x5f2c, 0x02 },
	{ 0x5f2d, 0x00 }, { 0x5f2f, 0x02 }, { 0x5f30, 0x00 }, { 0x5f32, 0x02 },
	{ 0x5f33, 0x00 }, { 0x5f34, 0x00 }, { 0x5f35, 0x02 }, { 0x5f36, 0x00 },
	{ 0x5f37, 0x00 }, { 0x5f38, 0x02 }, { 0x5f39, 0x00 }, { 0x5f3a, 0x00 },
	{ 0x5f3b, 0x02 }, { 0x5f3c, 0x00 }, { 0x5f3d, 0x00 }, { 0x5f3e, 0x02 },
	{ 0x5f3f, 0x00 }, { 0x5f40, 0x00 }, { 0x5f41, 0x02 }, { 0x5f42, 0x00 },
	{ 0x5f43, 0x00 }, { 0x5f44, 0x02 }, { 0x5f45, 0x00 }, { 0x5f46, 0x00 },
	{ 0x5f47, 0x04 }, { 0x5f48, 0x00 }, { 0x5f49, 0x00 }, { 0x5f4a, 0x04 },
	{ 0x5f4b, 0x00 }, { 0x5f4c, 0x00 }, { 0x5f4d, 0x04 }, { 0x5f4e, 0x00 },
	{ 0x5f50, 0x04 }, { 0x5f51, 0x00 }, { 0x5f53, 0x04 }, { 0x5f54, 0x00 },
	{ 0x5f56, 0x04 }, { 0x5f57, 0x00 }, { 0x5f59, 0x04 }, { 0x5f5a, 0x00 },
	{ 0x5f5c, 0x04 }, { 0x5f5d, 0x00 }, { 0x5f5f, 0x08 }, { 0x5f60, 0x00 },
	{ 0x5f62, 0x08 }, { 0x5f63, 0x00 }, { 0x5f65, 0x08 }, { 0x5f66, 0x00 },
	{ 0x5f68, 0x08 }, { 0x5f69, 0x00 }, { 0x5f6b, 0x08 }, { 0x5f6c, 0x00 },
	{ 0x5f6e, 0x10 }, { 0x5f6f, 0x00 }, { 0x5f71, 0x10 }, { 0x5f72, 0x00 },
	{ 0x5f74, 0x10 }, { 0x5f75, 0x00 }, { 0x5f77, 0x10 }, { 0x5f78, 0x00 },
	{ 0x5f7a, 0x20 }, { 0x5f7b, 0x00 }, { 0x5f7d, 0x20 }, { 0x5f7e, 0x00 },
	{ 0x5f80, 0x20 }, { 0x5f81, 0x00 }, { 0x5f83, 0x00 }, { 0x5f84, 0xff },
	{ 0x5240, 0x0f }, { 0x5243, 0x00 }, { 0x5244, 0x00 }, { 0x5245, 0x00 },
	{ 0x5246, 0x00 }, { 0x5247, 0x00 }, { 0x5248, 0x00 }, { 0x5249, 0x00 },
	{ 0x5440, 0x0f }, { 0x5443, 0x00 }, { 0x5445, 0x00 }, { 0x5447, 0x00 },
	{ 0x5448, 0x00 }, { 0x5449, 0x00 }, { 0x5640, 0x0f }, { 0x5642, 0x00 },
	{ 0x5643, 0x00 }, { 0x5644, 0x00 }, { 0x5645, 0x00 }, { 0x5646, 0x00 },
	{ 0x5647, 0x00 }, { 0x5649, 0x00 }, { 0x5840, 0x0f }, { 0x5842, 0x00 },
	{ 0x5843, 0x00 }, { 0x5845, 0x00 }, { 0x5846, 0x00 }, { 0x5847, 0x00 },
	{ 0x5848, 0x00 }, { 0x5849, 0x00 }, { 0x4001, 0x2b }, { 0x4008, 0x02 },
	{ 0x4009, 0x03 }, { 0x4018, 0x12 }, { 0x4022, 0x40 }, { 0x4023, 0x20 },
	{ 0x4026, 0x00 }, { 0x4027, 0x40 }, { 0x4028, 0x00 }, { 0x4029, 0x40 },
	{ 0x402a, 0x00 }, { 0x402b, 0x40 }, { 0x402c, 0x00 }, { 0x402d, 0x40 },
	{ 0x405e, 0x00 }, { 0x405f, 0x00 }, { 0x4060, 0x00 }, { 0x4061, 0x00 },
	{ 0x4062, 0x00 }, { 0x4063, 0x00 }, { 0x4064, 0x00 }, { 0x4065, 0x00 },
	{ 0x4066, 0x00 }, { 0x4067, 0x00 }, { 0x4068, 0x00 }, { 0x4069, 0x00 },
	{ 0x406a, 0x00 }, { 0x406b, 0x00 }, { 0x406c, 0x00 }, { 0x406d, 0x00 },
	{ 0x406e, 0x00 }, { 0x406f, 0x00 }, { 0x4070, 0x00 }, { 0x4071, 0x00 },
	{ 0x4072, 0x00 }, { 0x4073, 0x00 }, { 0x4074, 0x00 }, { 0x4075, 0x00 },
	{ 0x4076, 0x00 }, { 0x4077, 0x00 }, { 0x4078, 0x00 }, { 0x4079, 0x00 },
	{ 0x407a, 0x00 }, { 0x407b, 0x00 }, { 0x407c, 0x00 }, { 0x407d, 0x00 },
	{ 0x407e, 0xcc }, { 0x407f, 0x18 }, { 0x4080, 0xff }, { 0x4081, 0xff },
	{ 0x4082, 0x01 }, { 0x4083, 0x53 }, { 0x4084, 0x01 }, { 0x4085, 0x2b },
	{ 0x4086, 0x00 }, { 0x4087, 0xb3 }, { 0x4640, 0x40 }, { 0x4641, 0x11 },
	{ 0x4642, 0x0e }, { 0x4643, 0xee }, { 0x4646, 0x0f }, { 0x4648, 0x00 },
	{ 0x4649, 0x03 }, { 0x4d09, 0xff }, { 0x4d09, 0xdf }, { 0x5019, 0x00 },
	{ 0x501a, 0xff }, { 0x501b, 0xff }, { 0x501d, 0x00 }, { 0x501e, 0x23 },
	{ 0x501f, 0x8e }, { 0x5021, 0x00 }, { 0x5022, 0x00 }, { 0x5023, 0x50 },
	{ 0x5025, 0x00 }, { 0x5026, 0x23 }, { 0x5027, 0x8e }, { 0x5003, 0x7a },
	{ 0x5b80, 0x08 }, { 0x5c00, 0x08 }, { 0x5c80, 0x00 }, { 0x5bbe, 0x12 },
	{ 0x5c3e, 0x12 }, { 0x5cbe, 0x12 }, { 0x5b8a, 0x80 }, { 0x5b8b, 0x80 },
	{ 0x5b8c, 0x80 }, { 0x5b8d, 0x80 }, { 0x5b8e, 0x80 }, { 0x5b8f, 0x40 },
	{ 0x5b90, 0x80 }, { 0x5b91, 0x80 }, { 0x5b92, 0x80 }, { 0x5b93, 0x60 },
	{ 0x5b94, 0x00 }, { 0x5b95, 0x00 }, { 0x5b96, 0x40 }, { 0x5b97, 0x80 },
	{ 0x5b98, 0x10 }, { 0x5b99, 0x00 }, { 0x5b9a, 0x00 }, { 0x5b9b, 0x00 },
	{ 0x5b9c, 0x00 }, { 0x5b9d, 0x00 }, { 0x5b9e, 0x00 }, { 0x5b9f, 0x00 },
	{ 0x5ba0, 0x00 }, { 0x5ba1, 0x00 }, { 0x5ba2, 0x00 }, { 0x5ba3, 0x00 },
	{ 0x5ba4, 0x00 }, { 0x5ba5, 0x00 }, { 0x5ba6, 0x00 }, { 0x5ba7, 0x00 },
	{ 0x5ba8, 0x00 }, { 0x5ba9, 0xc0 }, { 0x5baa, 0x01 }, { 0x5bab, 0x40 },
	{ 0x5bac, 0x02 }, { 0x5bad, 0x40 }, { 0x5bae, 0x00 }, { 0x5baf, 0x50 },
	{ 0x5bb0, 0x00 }, { 0x5bb1, 0x60 }, { 0x5bb2, 0x00 }, { 0x5bb3, 0xc0 },
	{ 0x5c0a, 0x80 }, { 0x5c0b, 0x80 }, { 0x5c0c, 0x80 }, { 0x5c0d, 0x80 },
	{ 0x5c0e, 0x60 }, { 0x5c0f, 0x80 }, { 0x5c10, 0x80 }, { 0x5c11, 0x80 },
	{ 0x5c12, 0x60 }, { 0x5c13, 0x20 }, { 0x5c14, 0x80 }, { 0x5c15, 0x80 },
	{ 0x5c16, 0x80 }, { 0x5c17, 0x20 }, { 0x5c18, 0x00 }, { 0x5c19, 0x80 },
	{ 0x5c1a, 0x40 }, { 0x5c1b, 0x20 }, { 0x5c1c, 0x00 }, { 0x5c1d, 0x00 },
	{ 0x5c1e, 0x80 }, { 0x5c1f, 0x00 }, { 0x5c20, 0x00 }, { 0x5c21, 0x00 },
	{ 0x5c22, 0x00 }, { 0x5c23, 0x00 }, { 0x5c24, 0x00 }, { 0x5c25, 0x00 },
	{ 0x5c26, 0x00 }, { 0x5c27, 0x00 }, { 0x5c28, 0x02 }, { 0x5c29, 0x00 },
	{ 0x5c2a, 0x02 }, { 0x5c2b, 0x76 }, { 0x5c2c, 0x03 }, { 0x5c2d, 0x08 },
	{ 0x5c2e, 0x00 }, { 0x5c2f, 0x80 }, { 0x5c30, 0x01 }, { 0x5c31, 0x00 },
	{ 0x5c32, 0x02 }, { 0x5c33, 0x00 }, { 0x5c8a, 0x80 }, { 0x5c8b, 0x80 },
	{ 0x5c8c, 0x80 }, { 0x5c8d, 0x80 }, { 0x5c8e, 0x80 }, { 0x5c8f, 0x80 },
	{ 0x5c90, 0x80 }, { 0x5c91, 0x80 }, { 0x5c92, 0x80 }, { 0x5c93, 0x60 },
	{ 0x5c94, 0x80 }, { 0x5c95, 0x80 }, { 0x5c96, 0x80 }, { 0x5c97, 0x60 },
	{ 0x5c98, 0x40 }, { 0x5c99, 0x80 }, { 0x5c9a, 0x80 }, { 0x5c9b, 0x80 },
	{ 0x5c9c, 0x40 }, { 0x5c9d, 0x20 }, { 0x5c9e, 0x80 }, { 0x5c9f, 0x80 },
	{ 0x5ca0, 0x80 }, { 0x5ca1, 0x20 }, { 0x5ca2, 0x00 }, { 0x5ca3, 0x80 },
	{ 0x5ca4, 0x80 }, { 0x5ca5, 0x80 }, { 0x5ca6, 0x00 }, { 0x5ca7, 0x00 },
	{ 0x5ca8, 0x01 }, { 0x5ca9, 0x00 }, { 0x5caa, 0x02 }, { 0x5cab, 0x00 },
	{ 0x5cac, 0x03 }, { 0x5cad, 0x08 }, { 0x5cae, 0x01 }, { 0x5caf, 0x00 },
	{ 0x5cb0, 0x02 }, { 0x5cb1, 0x00 }, { 0x5cb2, 0x03 }, { 0x5cb3, 0x08 },
	{ 0x5be7, 0x80 }, { 0x5bc9, 0x80 }, { 0x5bca, 0x80 }, { 0x5bcb, 0x80 },
	{ 0x5bcc, 0x80 }, { 0x5bcd, 0x80 }, { 0x5bce, 0x80 }, { 0x5bcf, 0x80 },
	{ 0x5bd0, 0x80 }, { 0x5bd1, 0x80 }, { 0x5bd2, 0x20 }, { 0x5bd3, 0x80 },
	{ 0x5bd4, 0x40 }, { 0x5bd5, 0x20 }, { 0x5bd6, 0x00 }, { 0x5bd7, 0x00 },
	{ 0x5bd8, 0x00 }, { 0x5bd9, 0x00 }, { 0x5bda, 0x00 }, { 0x5bdb, 0x00 },
	{ 0x5bdc, 0x00 }, { 0x5bdd, 0x00 }, { 0x5bde, 0x00 }, { 0x5bdf, 0x00 },
	{ 0x5be0, 0x00 }, { 0x5be1, 0x00 }, { 0x5be2, 0x00 }, { 0x5be3, 0x00 },
	{ 0x5be4, 0x00 }, { 0x5be5, 0x00 }, { 0x5be6, 0x00 }, { 0x5c49, 0x80 },
	{ 0x5c4a, 0x80 }, { 0x5c4b, 0x80 }, { 0x5c4c, 0x80 }, { 0x5c4d, 0x40 },
	{ 0x5c4e, 0x80 }, { 0x5c4f, 0x80 }, { 0x5c50, 0x80 }, { 0x5c51, 0x60 },
	{ 0x5c52, 0x20 }, { 0x5c53, 0x80 }, { 0x5c54, 0x80 }, { 0x5c55, 0x80 },
	{ 0x5c56, 0x20 }, { 0x5c57, 0x00 }, { 0x5c58, 0x80 }, { 0x5c59, 0x40 },
	{ 0x5c5a, 0x20 }, { 0x5c5b, 0x00 }, { 0x5c5c, 0x00 }, { 0x5c5d, 0x80 },
	{ 0x5c5e, 0x00 }, { 0x5c5f, 0x00 }, { 0x5c60, 0x00 }, { 0x5c61, 0x00 },
	{ 0x5c62, 0x00 }, { 0x5c63, 0x00 }, { 0x5c64, 0x00 }, { 0x5c65, 0x00 },
	{ 0x5c66, 0x00 }, { 0x5cc9, 0x80 }, { 0x5cca, 0x80 }, { 0x5ccb, 0x80 },
	{ 0x5ccc, 0x80 }, { 0x5ccd, 0x80 }, { 0x5cce, 0x80 }, { 0x5ccf, 0x80 },
	{ 0x5cd0, 0x80 }, { 0x5cd1, 0x80 }, { 0x5cd2, 0x60 }, { 0x5cd3, 0x80 },
	{ 0x5cd4, 0x80 }, { 0x5cd5, 0x80 }, { 0x5cd6, 0x60 }, { 0x5cd7, 0x40 },
	{ 0x5cd8, 0x80 }, { 0x5cd9, 0x80 }, { 0x5cda, 0x80 }, { 0x5cdb, 0x40 },
	{ 0x5cdc, 0x20 }, { 0x5cdd, 0x80 }, { 0x5cde, 0x80 }, { 0x5cdf, 0x80 },
	{ 0x5ce0, 0x20 }, { 0x5ce1, 0x00 }, { 0x5ce2, 0x80 }, { 0x5ce3, 0x80 },
	{ 0x5ce4, 0x80 }, { 0x5ce5, 0x00 }, { 0x5ce6, 0x00 }, { 0x5b84, 0x02 },
	{ 0x5b85, 0xcc }, { 0x5bb4, 0x05 }, { 0x5bb5, 0xc6 }, { 0x5c04, 0x02 },
	{ 0x5c05, 0xcc }, { 0x5c34, 0x05 }, { 0x5c35, 0x33 }, { 0x5c84, 0x02 },
	{ 0x5c85, 0xcc }, { 0x5cb4, 0x05 }, { 0x5cb5, 0x33 }, { 0x5bbf, 0x00 },
	{ 0x5bc0, 0x04 }, { 0x5bc1, 0x06 }, { 0x5bc2, 0xff }, { 0x5bc3, 0x00 },
	{ 0x5bc4, 0x04 }, { 0x5bc5, 0x02 }, { 0x5bc6, 0xb8 }, { 0x5c3f, 0x00 },
	{ 0x5c40, 0x04 }, { 0x5c41, 0x07 }, { 0x5c42, 0xff }, { 0x5c43, 0x00 },
	{ 0x5c44, 0x04 }, { 0x5c45, 0x03 }, { 0x5c46, 0xb8 }, { 0x5cbf, 0x00 },
	{ 0x5cc0, 0x20 }, { 0x5cc1, 0x07 }, { 0x5cc2, 0xff }, { 0x5cc3, 0x00 },
	{ 0x5cc4, 0x20 }, { 0x5cc5, 0x03 }, { 0x5cc6, 0x00 }, { 0x5b86, 0x05 },
	{ 0x5c06, 0x05 }, { 0x5c86, 0x05 }, { 0x5bb8, 0x01 }, { 0x5bb9, 0x01 },
	{ 0x5c38, 0x01 }, { 0x5c39, 0x01 }, { 0x5cb8, 0x01 }, { 0x5cb9, 0x01 },
	{ 0x5bc7, 0x00 }, { 0x5bc8, 0x80 }, { 0x5c47, 0x00 }, { 0x5c48, 0x80 },
	{ 0x5cc7, 0x00 }, { 0x5cc8, 0x80 }, { 0x5bba, 0x01 }, { 0x5bbb, 0x00 },
	{ 0x5c3a, 0x01 }, { 0x5c3b, 0x00 }, { 0x5cba, 0x01 }, { 0x5cbb, 0x00 },
	{ 0x5d74, 0x01 }, { 0x5d75, 0x00 }, { 0x5d1f, 0x81 }, { 0x5d11, 0x00 },
	{ 0x5d12, 0x10 }, { 0x5d13, 0x10 }, { 0x5d15, 0x05 }, { 0x5d16, 0x05 },
	{ 0x5d17, 0x05 }, { 0x5d08, 0x03 }, { 0x5d09, 0x6b }, { 0x5d0a, 0x03 },
	{ 0x5d0b, 0x6b }, { 0x5d18, 0x03 }, { 0x5d19, 0x6b }, { 0x5b40, 0x01 },
	{ 0x5b41, 0x00 }, { 0x5b42, 0x00 }, { 0x5b43, 0x00 }, { 0x5b44, 0x00 },
	{ 0x5b45, 0x00 }, { 0x5b46, 0x00 }, { 0x5b47, 0x00 }, { 0x5b48, 0x01 },
	{ 0x5b49, 0x00 }, { 0x5b4a, 0x00 }, { 0x5b4b, 0x00 }, { 0x5b4c, 0x00 },
	{ 0x5b4d, 0x00 }, { 0x5b4e, 0x00 }, { 0x5b4f, 0x00 }, { 0x5b50, 0x01 },
	{ 0x5b51, 0x00 }, { 0x5b52, 0x01 }, { 0x5b53, 0x00 }, { 0x5b54, 0x00 },
	{ 0x5b55, 0x00 }, { 0x5b56, 0x00 }, { 0x5b57, 0x00 }, { 0x5b58, 0x00 },
	{ 0x5b59, 0x00 }, { 0x5b5a, 0x01 }, { 0x5b5b, 0x00 }, { 0x5b5c, 0x00 },
	{ 0x5b5d, 0x00 }, { 0x5b5e, 0x00 }, { 0x5b5f, 0x00 }, { 0x5b60, 0x00 },
	{ 0x5b61, 0x00 }, { 0x5b62, 0x01 }, { 0x5b63, 0x00 }, { 0x5b64, 0x01 },
	{ 0x5b65, 0x00 }, { 0x5b66, 0x00 }, { 0x5b67, 0x00 }, { 0x5b68, 0x00 },
	{ 0x5b69, 0x00 }, { 0x5b6a, 0x00 }, { 0x5b6b, 0x00 }, { 0x5b6c, 0x01 },
	{ 0x5b6d, 0x00 }, { 0x5b6e, 0x00 }, { 0x5b6f, 0x00 }, { 0x5b70, 0x00 },
	{ 0x5b71, 0x00 }, { 0x5b72, 0x00 }, { 0x5b73, 0x00 }, { 0x5b74, 0x01 },
	{ 0x5b75, 0x00 }, { 0x5b78, 0x00 }, { 0x5b79, 0x4c }, { 0x5b7a, 0x00 },
	{ 0x5b7b, 0xb9 }, { 0x5b7c, 0x01 }, { 0x5b7d, 0x38 }, { 0x5b7e, 0x01 },
	{ 0x5280, 0x04 }, { 0x5281, 0x00 }, { 0x5282, 0x04 }, { 0x5283, 0x00 },
	{ 0x5284, 0x04 }, { 0x5285, 0x00 }, { 0x5286, 0x04 }, { 0x5287, 0x00 },
	{ 0x5480, 0x04 }, { 0x5481, 0x00 }, { 0x5482, 0x04 }, { 0x5483, 0x00 },
	{ 0x5484, 0x04 }, { 0x5485, 0x00 }, { 0x5486, 0x04 }, { 0x5487, 0x00 },
	{ 0x5680, 0x04 }, { 0x5681, 0x00 }, { 0x5682, 0x04 }, { 0x5683, 0x00 },
	{ 0x5684, 0x04 }, { 0x5685, 0x00 }, { 0x5686, 0x04 }, { 0x5687, 0x00 },
	{ 0x5880, 0x04 }, { 0x5881, 0x00 }, { 0x5882, 0x04 }, { 0x5883, 0x00 },
	{ 0x5884, 0x04 }, { 0x5885, 0x00 }, { 0x5886, 0x04 }, { 0x5887, 0x00 },
	{ 0x52c6, 0x00 }, { 0x52c7, 0x12 }, { 0x52c8, 0x04 }, { 0x52c9, 0x02 },
	{ 0x52ca, 0x01 }, { 0x52cb, 0x01 }, { 0x52cc, 0x04 }, { 0x52cd, 0x02 },
	{ 0x52ce, 0x01 }, { 0x52cf, 0x01 }, { 0x52d0, 0x03 }, { 0x52d1, 0x08 },
	{ 0x52d2, 0x0c }, { 0x54c6, 0x00 }, { 0x54c7, 0x12 }, { 0x54c8, 0x04 },
	{ 0x54c9, 0x02 }, { 0x54ca, 0x01 }, { 0x54cb, 0x01 }, { 0x54cc, 0x04 },
	{ 0x54cd, 0x02 }, { 0x54ce, 0x01 }, { 0x54cf, 0x01 }, { 0x54d0, 0x03 },
	{ 0x54d1, 0x08 }, { 0x54d2, 0x0c }, { 0x56c6, 0x00 }, { 0x56c7, 0x12 },
	{ 0x56c8, 0x04 }, { 0x56c9, 0x02 }, { 0x56ca, 0x01 }, { 0x56cb, 0x01 },
	{ 0x56cc, 0x04 }, { 0x56cd, 0x02 }, { 0x56ce, 0x01 }, { 0x56cf, 0x01 },
	{ 0x56d0, 0x03 }, { 0x56d1, 0x08 }, { 0x56d2, 0x0c }, { 0x58c6, 0x00 },
	{ 0x58c7, 0x12 }, { 0x58c8, 0x04 }, { 0x58c9, 0x02 }, { 0x58ca, 0x01 },
	{ 0x58cb, 0x01 }, { 0x58cc, 0x04 }, { 0x58cd, 0x02 }, { 0x58ce, 0x01 },
	{ 0x58cf, 0x01 }, { 0x58d0, 0x03 }, { 0x58d1, 0x08 }, { 0x58d2, 0x0c },
	{ 0x5004, 0x1e }, { 0x610a, 0x07 }, { 0x610b, 0x80 }, { 0x610c, 0x05 },
	{ 0x610d, 0x00 }, { 0x6102, 0x3f }, { 0x6120, 0x75 }, { 0x6121, 0x75 },
	{ 0x6122, 0x75 }, { 0x6123, 0x75 }, { 0x6124, 0x75 }, { 0x6125, 0x75 },
	{ 0x6126, 0x75 }, { 0x6127, 0x75 }, { 0x6128, 0x75 }, { 0x6129, 0x75 },
	{ 0x612a, 0x75 }, { 0x612b, 0x75 }, { 0x612c, 0x75 }, { 0x612d, 0x75 },
	{ 0x612e, 0x75 }, { 0x612f, 0x75 }, { 0x6130, 0x75 }, { 0x6131, 0x75 },
	{ 0x6132, 0x75 }, { 0x6133, 0x75 }, { 0x6134, 0x75 }, { 0x6135, 0x75 },
	{ 0x6136, 0x75 }, { 0x6137, 0x75 }, { 0x6138, 0x75 }, { 0x6139, 0x75 },
	{ 0x613a, 0x75 }, { 0x613b, 0x75 }, { 0x613c, 0x75 }, { 0x613d, 0x75 },
	{ 0x613e, 0x75 }, { 0x613f, 0x75 }, { 0x6140, 0x75 }, { 0x6141, 0x75 },
	{ 0x6142, 0x75 }, { 0x6143, 0x75 }, { 0x6144, 0x75 }, { 0x6145, 0x75 },
	{ 0x6146, 0x75 }, { 0x6147, 0x75 }, { 0x6148, 0x75 }, { 0x6149, 0x75 },
	{ 0x614a, 0x75 }, { 0x614b, 0x75 }, { 0x614c, 0x75 }, { 0x614d, 0x75 },
	{ 0x614e, 0x75 }, { 0x614f, 0x75 }, { 0x6150, 0x75 }, { 0x6151, 0x75 },
	{ 0x6152, 0x75 }, { 0x6153, 0x75 }, { 0x6154, 0x75 }, { 0x6155, 0x75 },
	{ 0x6156, 0x75 }, { 0x6157, 0x75 }, { 0x6158, 0x75 }, { 0x6159, 0x75 },
	{ 0x615a, 0x75 }, { 0x615b, 0x75 }, { 0x615c, 0x75 }, { 0x615d, 0x75 },
	{ 0x615e, 0x75 }, { 0x615f, 0x75 }, { 0x6160, 0x75 }, { 0x6161, 0x75 },
	{ 0x6162, 0x75 }, { 0x6163, 0x75 }, { 0x6164, 0x75 }, { 0x6165, 0x75 },
	{ 0x6166, 0x75 }, { 0x6167, 0x75 }, { 0x6168, 0x75 }, { 0x6169, 0x75 },
	{ 0x616a, 0x75 }, { 0x616b, 0x75 }, { 0x616c, 0x75 }, { 0x616d, 0x75 },
	{ 0x616e, 0x75 }, { 0x616f, 0x75 }, { 0x6170, 0x75 }, { 0x6171, 0x75 },
	{ 0x6172, 0x75 }, { 0x6173, 0x75 }, { 0x6174, 0x75 }, { 0x6175, 0x75 },
	{ 0x6176, 0x75 }, { 0x6177, 0x75 }, { 0x6178, 0x75 }, { 0x6179, 0x75 },
	{ 0x617a, 0x75 }, { 0x617b, 0x75 }, { 0x617c, 0x75 }, { 0x617d, 0x75 },
	{ 0x617e, 0x75 }, { 0x617f, 0x75 }, { 0x6180, 0x75 }, { 0x6181, 0x75 },
	{ 0x6182, 0x75 }, { 0x6183, 0x75 }, { 0x6184, 0x75 }, { 0x6185, 0x75 },
	{ 0x6186, 0x75 }, { 0x6187, 0x75 }, { 0x6188, 0x75 }, { 0x6189, 0x75 },
	{ 0x618a, 0x75 }, { 0x618b, 0x75 }, { 0x618c, 0x75 }, { 0x618d, 0x75 },
	{ 0x618e, 0x75 }, { 0x618f, 0x75 }, { 0x6190, 0x75 }, { 0x6191, 0x75 },
	{ 0x6192, 0x75 }, { 0x6193, 0x75 }, { 0x6194, 0x75 }, { 0x6195, 0x75 },
	{ 0x6196, 0x75 }, { 0x6197, 0x75 }, { 0x6198, 0x75 }, { 0x6199, 0x75 },
	{ 0x619a, 0x75 }, { 0x619b, 0x75 }, { 0x619c, 0x75 }, { 0x619d, 0x75 },
	{ 0x619e, 0x75 }, { 0x619f, 0x75 }, { 0x61a0, 0x75 }, { 0x61a1, 0x75 },
	{ 0x61a2, 0x75 }, { 0x61a3, 0x75 }, { 0x61a4, 0x75 }, { 0x61a5, 0x75 },
	{ 0x61a6, 0x75 }, { 0x61a7, 0x75 }, { 0x61a8, 0x75 }, { 0x61a9, 0x75 },
	{ 0x61aa, 0x75 }, { 0x61ab, 0x75 }, { 0x61ac, 0x75 }, { 0x61ad, 0x75 },
	{ 0x61ae, 0x75 }, { 0x61af, 0x75 }, { 0x5d62, 0x07 }, { 0x5d40, 0x02 },
	{ 0x5d41, 0x01 }, { 0x5d63, 0x08 }, { 0x5d64, 0x01 }, { 0x5d65, 0xff },
	{ 0x5d56, 0x00 }, { 0x5d57, 0x20 }, { 0x5d58, 0x00 }, { 0x5d59, 0x20 },
	{ 0x5d5a, 0x00 }, { 0x5d5b, 0x0c }, { 0x5d5c, 0x02 }, { 0x5d5d, 0x40 },
	{ 0x5d5e, 0x02 }, { 0x5d5f, 0x40 }, { 0x5d60, 0x03 }, { 0x5d61, 0x40 },
	{ 0x5d4a, 0x02 }, { 0x5d4b, 0x40 }, { 0x5d4c, 0x02 }, { 0x5d4d, 0x40 },
	{ 0x5d4e, 0x02 }, { 0x5d4f, 0x40 }, { 0x5d50, 0x18 }, { 0x5d51, 0x80 },
	{ 0x5d52, 0x18 }, { 0x5d53, 0x80 }, { 0x5d54, 0x18 }, { 0x5d55, 0x80 },
	{ 0x5d46, 0x20 }, { 0x5d47, 0x00 }, { 0x5d48, 0x22 }, { 0x5d49, 0x00 },
	{ 0x5d42, 0x20 }, { 0x5d43, 0x00 }, { 0x5d44, 0x22 }, { 0x5d45, 0x00 },
	{ 0x4221, 0x03 }, { 0x3501, 0x01 }, { 0x3502, 0x87 }, { 0x3541, 0x01 },
	{ 0x3542, 0x87 }, { 0x35c1, 0x00 }, { 0x35c2, 0x00 }, { 0x420e, 0x66 },
	{ 0x420f, 0x5d }, { 0x4210, 0xa8 }, { 0x4211, 0x55 }, { 0x507a, 0x5f },
	{ 0x507b, 0x46 }, { 0x4f00, 0x00 }, { 0x4f01, 0x01 }, { 0x4f02, 0x80 },
	{ 0x4f03, 0x2c }, { 0x4f04, 0xf8 }, { 0x5e00, 0x00 }, { 0x5e01, 0x00 },
	{ 0x5e02, 0x09 }, { 0x5e03, 0x09 }, { 0x5e04, 0x0a }, { 0x5e05, 0x0a },
	{ 0x5e06, 0x0a }, { 0x5e07, 0x0b }, { 0x5e08, 0x0b }, { 0x5e09, 0x0d },
	{ 0x5e0a, 0x0d }, { 0x5e0b, 0x0d }, { 0x5e0c, 0x0e }, { 0x5e0d, 0x0e },
	{ 0x5e0e, 0x0f }, { 0x5e0f, 0x0f }, { 0x5e10, 0x10 }, { 0x5e11, 0x10 },
	{ 0x5e12, 0x11 }, { 0x5e13, 0x11 }, { 0x5e14, 0x12 }, { 0x5e15, 0x12 },
	{ 0x5e16, 0x12 }, { 0x5e17, 0x12 }, { 0x5e18, 0x13 }, { 0x5e19, 0x13 },
	{ 0x5e1a, 0x13 }, { 0x5e1b, 0x14 }, { 0x5e1c, 0x14 }, { 0x5e1d, 0x14 },
	{ 0x5e1e, 0x15 }, { 0x5e1f, 0x15 }, { 0x5e20, 0x15 }, { 0x5e21, 0x16 },
	{ 0x5e22, 0x00 }, { 0x5e23, 0x00 }, { 0x5e24, 0x00 }, { 0x5e25, 0x00 },
	{ 0x5e26, 0x01 }, { 0x5e27, 0xff }, { 0x5e28, 0x00 }, { 0x5e29, 0x00 },
	{ 0x5e2a, 0x80 }, { 0x5e2b, 0x00 }, { 0x5e2c, 0x00 }, { 0x5e2d, 0x40 },
	{ 0x5e2e, 0x00 }, { 0x5e2f, 0x00 }, { 0x5e30, 0x40 }, { 0x5e31, 0x00 },
	{ 0x5e32, 0x00 }, { 0x5e33, 0x40 }, { 0x5e34, 0x00 }, { 0x5e35, 0x00 },
	{ 0x5e36, 0x40 }, { 0x5e37, 0x00 }, { 0x5e38, 0x00 }, { 0x5e39, 0x40 },
	{ 0x5e3a, 0x00 }, { 0x5e3b, 0x00 }, { 0x5e3c, 0x40 }, { 0x5e3d, 0x00 },
	{ 0x5e3e, 0x00 }, { 0x5e3f, 0x80 }, { 0x5e40, 0x00 }, { 0x5e41, 0x00 },
	{ 0x5e42, 0x80 }, { 0x5e43, 0x00 }, { 0x5e44, 0x00 }, { 0x5e45, 0x80 },
	{ 0x5e46, 0x00 }, { 0x5e47, 0x00 }, { 0x5e48, 0x80 }, { 0x5e49, 0x00 },
	{ 0x5e4a, 0x00 }, { 0x5e4b, 0x80 }, { 0x5e4c, 0x00 }, { 0x5e4d, 0x00 },
	{ 0x5e4e, 0x80 }, { 0x5e4f, 0x00 }, { 0x5e50, 0x00 }, { 0x5e51, 0x80 },
	{ 0x5e52, 0x00 }, { 0x5e53, 0x00 }, { 0x5e54, 0x80 }, { 0x5e55, 0x00 },
	{ 0x5e56, 0x00 }, { 0x5e57, 0x80 }, { 0x5e58, 0x00 }, { 0x5e59, 0x00 },
	{ 0x5e5a, 0x80 }, { 0x5e5b, 0x00 }, { 0x5e5c, 0x00 }, { 0x5e5d, 0x80 },
	{ 0x5e5e, 0x00 }, { 0x5e5f, 0x00 }, { 0x5e60, 0x80 }, { 0x5e61, 0x00 },
	{ 0x5e62, 0x00 }, { 0x5e63, 0x80 }, { 0x5e64, 0x00 }, { 0x5e65, 0x00 },
	{ 0x5e66, 0x80 }, { 0x5e67, 0x00 }, { 0x5e68, 0x00 }, { 0x5e69, 0x80 },
	{ 0x5e6a, 0x00 }, { 0x5e6b, 0x00 }, { 0x5e6c, 0x80 }, { 0x5e6d, 0x00 },
	{ 0x5e6e, 0x00 }, { 0x5e6f, 0x80 }, { 0x5e70, 0x00 }, { 0x5e71, 0x00 },
	{ 0x5e72, 0x80 }, { 0x5e73, 0x00 }, { 0x5e74, 0x00 }, { 0x5e75, 0x80 },
	{ 0x5e76, 0x00 }, { 0x5e77, 0x00 }, { 0x5e78, 0x80 }, { 0x5e79, 0x00 },
	{ 0x5e7a, 0x00 }, { 0x5e7b, 0x80 }, { 0x5e7c, 0x00 }, { 0x5e7d, 0x00 },
	{ 0x5e7e, 0x80 }, { 0x5e7f, 0x00 }, { 0x5e80, 0x00 }, { 0x5e81, 0x80 },
	{ 0x5e82, 0x00 }, { 0x5e83, 0x00 }, { 0x5e84, 0x80 }, { 0x5b7e, 0x01 },
	{ 0x5b7f, 0x02 }, { 0x5b78, 0x00 }, { 0x5b79, 0x62 }, { 0x5b7a, 0x00 },
	{ 0x5b7b, 0xc4 }, { 0x5b7c, 0x01 }, { 0x5b7d, 0x76 }, { 0x5b40, 0x00 },
	{ 0x5b41, 0xfb }, { 0x5b42, 0x00 }, { 0x5b43, 0x05 }, { 0x5b44, 0x00 },
	{ 0x5b45, 0x00 }, { 0x5b46, 0x00 }, { 0x5b47, 0x01 }, { 0x5b48, 0x01 },
	{ 0x5b49, 0x06 }, { 0x5b4a, 0x0f }, { 0x5b4b, 0xf9 }, { 0x5b4c, 0x0f },
	{ 0x5b4d, 0xf5 }, { 0x5b4e, 0x00 }, { 0x5b4f, 0x0b }, { 0x5b50, 0x01 },
	{ 0x5b51, 0x00 }, { 0x5b52, 0x01 }, { 0x5b53, 0x1f }, { 0x5b54, 0x0f },
	{ 0x5b55, 0xed }, { 0x5b56, 0x0f }, { 0x5b57, 0xf4 }, { 0x5b58, 0x00 },
	{ 0x5b59, 0x07 }, { 0x5b5a, 0x01 }, { 0x5b5b, 0x04 }, { 0x5b5c, 0x0f },
	{ 0x5b5d, 0xf5 }, { 0x5b5e, 0x0f }, { 0x5b5f, 0xec }, { 0x5b60, 0x0f },
	{ 0x5b61, 0xed }, { 0x5b62, 0x01 }, { 0x5b63, 0x27 }, { 0x5b64, 0x01 },
	{ 0x5b65, 0x71 }, { 0x5b66, 0x0f }, { 0x5b67, 0xe6 }, { 0x5b68, 0x0f },
	{ 0x5b69, 0xa9 }, { 0x5b6a, 0x0f }, { 0x5b6b, 0xfe }, { 0x5b6c, 0x01 },
	{ 0x5b6d, 0x0a }, { 0x5b6e, 0x0f }, { 0x5b6f, 0xf8 }, { 0x5b70, 0x00 },
	{ 0x5b71, 0x00 }, { 0x5b72, 0x00 }, { 0x5b73, 0x04 }, { 0x5b74, 0x00 },
	{ 0x5b75, 0xfc }, { 0x500d, 0x03 },
};

struct ox02f10 {
	struct device *dev;
	struct clk *xclk;
	struct gpio_desc *pwdn_gpio;
	struct gpio_desc *reset_gpio;
	struct regmap *regmap;
	struct v4l2_subdev sd;
	struct media_pad pad;
	struct v4l2_mbus_framefmt fmt;
	struct v4l2_ctrl_handler ctrls;
	struct v4l2_ctrl *exposure;
	struct v4l2_ctrl *analogue_gain;
	struct v4l2_mbus_config_mipi_csi2 bus;
	/* Serializes controls, active format and streaming operations. */
	struct mutex mutex;
	bool streaming;
};

static int ox02f10_write_u16(struct ox02f10 *sensor,
			     unsigned int reg, u16 value)
{
	u8 data[] = { value >> 8, value & 0xff };

	return regmap_bulk_write(sensor->regmap, reg, data, sizeof(data));
}

static int ox02f10_set_exposure(struct ox02f10 *sensor, u32 exposure)
{
	return ox02f10_write_u16(sensor, OX02F10_REG_EXPOSURE, exposure);
}

static int ox02f10_set_analogue_gain(struct ox02f10 *sensor,
				     u32 gain)
{
	return regmap_write(sensor->regmap,
			    OX02F10_REG_ANALOG_GAIN,
			    gain);
}

static inline struct ox02f10 *to_ox02f10(struct v4l2_subdev *sd)
{
	return container_of(sd, struct ox02f10, sd);
}

static int ox02f10_set_ctrl(struct v4l2_ctrl *ctrl)
{
	struct ox02f10 *sensor = container_of(ctrl->handler,
					    struct ox02f10, ctrls);
	int ret;

	/* Cache controls while powered off; replay them before stream-on. */
	ret = pm_runtime_get_if_in_use(sensor->dev);
	if (ret <= 0)
		return ret;

	switch (ctrl->id) {
	case V4L2_CID_EXPOSURE:
		ret = ox02f10_set_exposure(sensor, ctrl->val);
		break;
	case V4L2_CID_ANALOGUE_GAIN:
		ret = ox02f10_set_analogue_gain(sensor, ctrl->val);
		break;
	default:
		ret = -EINVAL;
	}

	pm_runtime_put(sensor->dev);
	return ret;
}

static int ox02f10_power_on(struct ox02f10 *sensor)
{
	int ret = clk_prepare_enable(sensor->xclk);
	dev_info(sensor->dev, "DEBUG: power_on entry\n");//Muni

	if (ret){
		dev_err(sensor->dev,
			"DEBUG: xclk enable failed: %d\n", ret);
		return ret;
	}
	dev_info(sensor->dev, "DEBUG: xclk enabled, rate=%lu\n",
		 clk_get_rate(sensor->xclk));
	/* GPIO descriptor values are logical: 1 asserts, 0 deasserts. */
	usleep_range(1000, 2000);
	if (sensor->pwdn_gpio)
	gpiod_set_value_cansleep(sensor->pwdn_gpio, 0);
	if (sensor->reset_gpio)
	gpiod_set_value_cansleep(sensor->reset_gpio, 0);
	/* Allow startup even on modules without a controllable reset pin. */
	msleep(30);
	dev_info(sensor->dev, "DEBUG: power_on complete\n");
	return 0;
}

static void ox02f10_power_off(struct ox02f10 *sensor)
{
	if (sensor->reset_gpio)
	gpiod_set_value_cansleep(sensor->reset_gpio, 1);
	if (sensor->pwdn_gpio)
	gpiod_set_value_cansleep(sensor->pwdn_gpio, 1);
	clk_disable_unprepare(sensor->xclk);
}

static int ox02f10_identify(struct ox02f10 *sensor)
{
	u8 id_bytes[2];
	u16 id;
	int ret;

	ret = regmap_bulk_read(sensor->regmap, OX02F10_REG_CHIP_ID,
			       id_bytes, sizeof(id_bytes));
	if (ret)
		return dev_err_probe(sensor->dev, ret, "failed to read chip ID\n");
	id = (id_bytes[0] << 8) | id_bytes[1];
	if (id != OX02F10_CHIP_ID) {
		dev_err(sensor->dev, "unexpected chip ID 0x%04x\n", id);
		return -ENODEV;
	}
	dev_info(sensor->dev, "detected OX02F10, chip ID 0x%04x\n", id);
	return 0;
}

static void ox02f10_fill_format(struct v4l2_mbus_framefmt *fmt)
{
	fmt->width = OX02F10_WIDTH;
	fmt->height = OX02F10_HEIGHT;
	fmt->code = OX02F10_MEDIA_BUS_CODE;
	fmt->field = V4L2_FIELD_NONE;
	fmt->colorspace = V4L2_COLORSPACE_RAW;
	fmt->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
	fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE;
	fmt->xfer_func = V4L2_XFER_FUNC_NONE;
}

static int ox02f10_init_cfg(struct v4l2_subdev *sd,
			    struct v4l2_subdev_state *state)
{
	if (!state)
		return -EINVAL;

	ox02f10_fill_format(v4l2_subdev_get_try_format(sd, state, 0));
	return 0;
}

static int ox02f10_open(struct v4l2_subdev *sd,
			struct v4l2_subdev_fh *fh)
{
	return ox02f10_init_cfg(sd, fh->state);
}

static int ox02f10_enum_mbus_code(struct v4l2_subdev *sd,
				  struct v4l2_subdev_state *state,
				  struct v4l2_subdev_mbus_code_enum *code)
{
	if (code->pad || code->index || code->stream)
		return -EINVAL;
	code->code = OX02F10_MEDIA_BUS_CODE;
	return 0;
}

static int ox02f10_enum_frame_size(struct v4l2_subdev *sd,
				   struct v4l2_subdev_state *state,
				   struct v4l2_subdev_frame_size_enum *fse)
{
	if (fse->pad || fse->index || fse->stream ||
	    fse->code != OX02F10_MEDIA_BUS_CODE)
		return -EINVAL;
	fse->min_width = fse->max_width = OX02F10_WIDTH;
	fse->min_height = fse->max_height = OX02F10_HEIGHT;
	return 0;
}

static int ox02f10_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
				  struct v4l2_mbus_frame_desc *fd)
{
	if (pad)
		return -EINVAL;

	memset(fd, 0, sizeof(*fd));
	fd->type = V4L2_MBUS_FRAME_DESC_TYPE_CSI2;
	fd->num_entries = 1;
	fd->entry[0].stream = 0;
	fd->entry[0].flags = V4L2_MBUS_FRAME_DESC_FL_LEN_MAX;
	fd->entry[0].length = OX02F10_WIDTH * OX02F10_HEIGHT *
			      OX02F10_BITS_PER_PIXEL / 8;
	fd->entry[0].pixelcode = OX02F10_MEDIA_BUS_CODE;
	fd->entry[0].bus.csi2.vc = 0;
	fd->entry[0].bus.csi2.dt = 0x2b; /* RAW10 */

	return 0;
}

static int ox02f10_set_fmt(struct v4l2_subdev *sd,
			   struct v4l2_subdev_state *state,
			   struct v4l2_subdev_format *fmt)
{
	struct ox02f10 *sensor = to_ox02f10(sd);
	int ret = 0;

	if (fmt->pad || fmt->stream ||
	    (fmt->which != V4L2_SUBDEV_FORMAT_TRY &&
	     fmt->which != V4L2_SUBDEV_FORMAT_ACTIVE) ||
	    (fmt->which == V4L2_SUBDEV_FORMAT_TRY && !state))
		return -EINVAL;

	mutex_lock(&sensor->mutex);
	if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE && sensor->streaming) {
		ret = -EBUSY;
		goto unlock;
	}
	ox02f10_fill_format(&fmt->format);
	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
		*v4l2_subdev_get_try_format(sd, state, 0) = fmt->format;
	else
		sensor->fmt = fmt->format;
unlock:
	mutex_unlock(&sensor->mutex);
	return ret;
}

static int ox02f10_get_fmt(struct v4l2_subdev *sd,
			   struct v4l2_subdev_state *state,
			   struct v4l2_subdev_format *fmt)
{
	struct ox02f10 *sensor = to_ox02f10(sd);

	if (fmt->pad || fmt->stream ||
	    (fmt->which != V4L2_SUBDEV_FORMAT_TRY &&
	     fmt->which != V4L2_SUBDEV_FORMAT_ACTIVE) ||
	    (fmt->which == V4L2_SUBDEV_FORMAT_TRY && !state))
		return -EINVAL;

	mutex_lock(&sensor->mutex);
	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
		fmt->format = *v4l2_subdev_get_try_format(sd, state, 0);
	else
		fmt->format = sensor->fmt;
	mutex_unlock(&sensor->mutex);
	return 0;
}

static int ox02f10_get_selection(struct v4l2_subdev *sd,
				 struct v4l2_subdev_state *state,
				 struct v4l2_subdev_selection *sel)
{
	if (sel->pad || sel->stream ||
	    (sel->which != V4L2_SUBDEV_FORMAT_TRY &&
	     sel->which != V4L2_SUBDEV_FORMAT_ACTIVE))
		return -EINVAL;

	/* Only the fixed output window is described by the board mode. */
	switch (sel->target) {
	case V4L2_SEL_TGT_CROP:
	case V4L2_SEL_TGT_CROP_DEFAULT:
	case V4L2_SEL_TGT_CROP_BOUNDS:
		sel->r = (struct v4l2_rect) {
			.width = OX02F10_WIDTH,
			.height = OX02F10_HEIGHT,
		};
		return 0;
	default:
		return -EINVAL;
	}
}

static int ox02f10_get_frame_interval(struct v4l2_subdev *sd,
				      struct v4l2_subdev_frame_interval *fi)
{
	if (fi->pad || fi->stream)
		return -EINVAL;
	fi->interval.numerator = 1;
	fi->interval.denominator = OX02F10_FPS;
	return 0;
}

static int ox02f10_enum_frame_interval(struct v4l2_subdev *sd,
				      struct v4l2_subdev_state *state,
				      struct v4l2_subdev_frame_interval_enum *fie)
{
	if (fie->pad || fie->stream || fie->index ||
	    fie->code != OX02F10_MEDIA_BUS_CODE ||
	    fie->width != OX02F10_WIDTH || fie->height != OX02F10_HEIGHT)
		return -EINVAL;

	fie->interval.numerator = 1;
	fie->interval.denominator = OX02F10_FPS;
	return 0;
}

static int ox02f10_get_mbus_config(struct v4l2_subdev *sd, unsigned int pad,
				   struct v4l2_mbus_config *config)
{
	struct ox02f10 *sensor = to_ox02f10(sd);

	if (pad)
		return -EINVAL;

	config->type = V4L2_MBUS_CSI2_DPHY;
	config->bus.mipi_csi2 = sensor->bus;
	return 0;
}

static int ox02f10_start_streaming(struct ox02f10 *sensor)
{
	int ret;
	 unsigned int val;//Muni
dev_info(sensor->dev,
		 "DEBUG: start_streaming entered\n");//Muni
	ret = regmap_write(sensor->regmap, OX02F10_REG_SOFTWARE_RESET, 1);
	if (ret){
		dev_err(sensor->dev,
			"DEBUG: software reset failed: %d\n", ret);//Muni
		return ret;
	}
	dev_info(sensor->dev,
		 "DEBUG: software reset OK\n");//Muni
	usleep_range(5000, 10000);
	dev_info(sensor->dev,
		 "DEBUG: writing mode register table\n");//Muni
	ret = regmap_multi_reg_write(sensor->regmap, ox02f10_1920x1080_regs,
				     ARRAY_SIZE(ox02f10_1920x1080_regs));
	if (ret) {
		dev_err(sensor->dev, "failed to write mode registers: %d\n", ret);
		return ret;
	}
	dev_info(sensor->dev,
		 "DEBUG: mode register table OK\n");//Muni
	/* sensor->mutex already protects the control handler. */
	ret = __v4l2_ctrl_handler_setup(&sensor->ctrls);
	if (ret){
		dev_err(sensor->dev,
			"DEBUG: control setup failed: %d\n", ret);//Muni
		return ret;
	}
	dev_info(sensor->dev,
		 "DEBUG: controls OK\n");//Muni
	ret = regmap_write(sensor->regmap, OX02F10_REG_MODE_SELECT,
			   OX02F10_MODE_STREAMING);
	if (!ret) {
		usleep_range(10000, 20000);
		dev_info(sensor->dev,
			 "DEBUG: MODE_SELECT=STREAMING OK\n");//Muni
		/* Muni code start */
		/* -------- Register readback starts here -------- */

		if (!regmap_read(sensor->regmap, 0x0100, &val))
			dev_info(sensor->dev,
				 "DEBUG: REG 0100 = 0x%02x\n", val);

		if (!regmap_read(sensor->regmap, 0x3808, &val))
			dev_info(sensor->dev,
				 "DEBUG: REG 3808 = 0x%02x\n", val);

		if (!regmap_read(sensor->regmap, 0x3809, &val))
			dev_info(sensor->dev,
				 "DEBUG: REG 3809 = 0x%02x\n", val);

		if (!regmap_read(sensor->regmap, 0x380a, &val))
			dev_info(sensor->dev,
				 "DEBUG: REG 380A = 0x%02x\n", val);

		if (!regmap_read(sensor->regmap, 0x380b, &val))
			dev_info(sensor->dev,
				 "DEBUG: REG 380B = 0x%02x\n", val);

		if (!regmap_read(sensor->regmap, 0x380c, &val))
			dev_info(sensor->dev,
				 "DEBUG: REG 380C = 0x%02x\n", val);

		if (!regmap_read(sensor->regmap, 0x380d, &val))
			dev_info(sensor->dev,
				 "DEBUG: REG 380D = 0x%02x\n", val);

		if (!regmap_read(sensor->regmap, 0x380e, &val))
			dev_info(sensor->dev,
				 "DEBUG: REG 380E = 0x%02x\n", val);

		if (!regmap_read(sensor->regmap, 0x380f, &val))
			dev_info(sensor->dev,
				 "DEBUG: REG 380F = 0x%02x\n", val);

		if (!regmap_read(sensor->regmap, 0x4800, &val))
			dev_info(sensor->dev,
				 "DEBUG: REG 4800 = 0x%02x\n", val);

		if (!regmap_read(sensor->regmap, 0x4837, &val))
			dev_info(sensor->dev,
				 "DEBUG: REG 4837 = 0x%02x\n", val);

		/* -------- Register readback ends here -------- */
		//Muni code ends
	}
	return ret;
}

static int ox02f10_stop_streaming(struct ox02f10 *sensor)
{
	int ret = regmap_write(sensor->regmap, OX02F10_REG_MODE_SELECT,
			       OX02F10_MODE_STANDBY);

	if (!ret)
		usleep_range(10000, 20000);
	return ret;
}

static int ox02f10_set_stream(struct v4l2_subdev *sd, int enable)
{
	struct ox02f10 *sensor = to_ox02f10(sd);
	int ret = 0;
dev_info(sensor->dev,
	 "DEBUG: set_stream enable=%d\n", enable);//Muni
	enable = !!enable;
	mutex_lock(&sensor->mutex);
	if (sensor->streaming == enable)
		goto unlock;
	if (enable) {
		ret = pm_runtime_resume_and_get(sensor->dev);
		if (ret < 0)
			goto unlock;
		ret = ox02f10_start_streaming(sensor);
		if (ret) {
			/* Stream-on may have reached the sensor despite an I2C error. */
			ox02f10_stop_streaming(sensor);
			pm_runtime_put_sync(sensor->dev);
			goto unlock;
		}
	} else {
		ret = ox02f10_stop_streaming(sensor);
		/* Release power even if the standby write failed. */
		pm_runtime_put_sync(sensor->dev);
		sensor->streaming = false;
		goto unlock;
	}
	sensor->streaming = enable;
unlock:
	mutex_unlock(&sensor->mutex);
	if (ret)
		dev_err(sensor->dev, "failed to %s streaming: %d\n",
			enable ? "start" : "stop", ret);
	return ret;
}

static const struct v4l2_subdev_core_ops ox02f10_core_ops = {
	.subscribe_event = v4l2_ctrl_subdev_subscribe_event,
	.unsubscribe_event = v4l2_event_subdev_unsubscribe,
};

static const struct v4l2_subdev_video_ops ox02f10_video_ops = {
	.g_frame_interval = ox02f10_get_frame_interval,
	//.s_frame_interval = ox02f10_get_frame_interval,
	.s_stream = ox02f10_set_stream,
};

static const struct v4l2_subdev_pad_ops ox02f10_pad_ops = {
	.init_cfg = ox02f10_init_cfg,
	.get_fmt = ox02f10_get_fmt,
	.set_fmt = ox02f10_set_fmt,
	.get_selection = ox02f10_get_selection,
	.enum_mbus_code = ox02f10_enum_mbus_code,
	.enum_frame_size = ox02f10_enum_frame_size,
	.enum_frame_interval = ox02f10_enum_frame_interval,
	.get_frame_desc = ox02f10_get_frame_desc,
	.get_mbus_config = ox02f10_get_mbus_config,
};

static const struct v4l2_subdev_internal_ops ox02f10_internal_ops = {
	.open = ox02f10_open,
};

static const struct v4l2_subdev_ops ox02f10_subdev_ops = {
	.core = &ox02f10_core_ops,
	.video = &ox02f10_video_ops,
	.pad = &ox02f10_pad_ops,
};

static int ox02f10_runtime_resume(struct device *dev)
{
	dev_info(dev, "DEBUG: runtime_resume called\n");//Muni
	return ox02f10_power_on(to_ox02f10(dev_get_drvdata(dev)));
}

static int ox02f10_runtime_suspend(struct device *dev)
{
	ox02f10_power_off(to_ox02f10(dev_get_drvdata(dev)));
	return 0;
}

static int ox02f10_parse_endpoint(struct ox02f10 *sensor)
{
	struct v4l2_fwnode_endpoint ep = {
		.bus_type = V4L2_MBUS_CSI2_DPHY,
	};
	struct fwnode_handle *endpoint;
	unsigned int i;
	int ret;

	endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(sensor->dev), NULL);
	if (!endpoint)
		return dev_err_probe(sensor->dev, -EINVAL,
				     "missing CSI-2 endpoint\n");
	ret = v4l2_fwnode_endpoint_alloc_parse(endpoint, &ep);
	fwnode_handle_put(endpoint);
	if (ret) {
		dev_err_probe(sensor->dev, ret, "failed to parse CSI-2 endpoint\n");
		goto free_ep;
	}
	if (ep.bus.mipi_csi2.num_data_lanes != OX02F10_NUM_DATA_LANES ||
	    ep.bus.mipi_csi2.clock_lane != 0 ||
	    ep.bus.mipi_csi2.flags & V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK) {
		ret = dev_err_probe(sensor->dev, -EINVAL,
				    "mode requires four lanes and continuous clock on lane 0\n");
		goto free_ep;
	}
	for (i = 0; i < OX02F10_NUM_DATA_LANES; i++) {
		if (ep.bus.mipi_csi2.data_lanes[i] != i + 1) {
			ret = dev_err_probe(sensor->dev, -EINVAL,
					    "mode requires data-lanes = <1 2 3 4>\n");
			goto free_ep;
		}
	}
	for (i = 0; i <= OX02F10_NUM_DATA_LANES; i++) {
		if (ep.bus.mipi_csi2.lane_polarities[i]) {
			ret = dev_err_probe(sensor->dev, -EINVAL,
					    "lane polarity inversion is not supported\n");
			goto free_ep;
		}
	}
	for (i = 0; i < ep.nr_of_link_frequencies; i++)
		if (ep.link_frequencies[i] == OX02F10_LINK_FREQ)
			break;
	if (i == ep.nr_of_link_frequencies) {
		ret = dev_err_probe(sensor->dev, -EINVAL,
				    "endpoint must support a %lld Hz link frequency\n",
				    OX02F10_LINK_FREQ);
		goto free_ep;
	}
	sensor->bus = ep.bus.mipi_csi2;
	ret = 0;
free_ep:
	v4l2_fwnode_endpoint_free(&ep);
	return ret;
}

static const struct v4l2_ctrl_ops ox02f10_ctrl_ops = {
	.s_ctrl = ox02f10_set_ctrl,
};

static int ox02f10_init_controls(struct ox02f10 *sensor)
{
	struct v4l2_ctrl *ctrl;
	s64 pixel_rate;
	int ret;

	ret = v4l2_ctrl_handler_init(&sensor->ctrls, 4);
	if (ret)
		return ret;
	sensor->ctrls.lock = &sensor->mutex;
	ctrl = v4l2_ctrl_new_int_menu(&sensor->ctrls, NULL,
				      V4L2_CID_LINK_FREQ, 0, 0,
				      ox02f10_link_freq_menu);
	if (ctrl)
		ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
	pixel_rate = OX02F10_LINK_FREQ * 2 * OX02F10_NUM_DATA_LANES /
		     OX02F10_BITS_PER_PIXEL;
	ctrl = v4l2_ctrl_new_std(&sensor->ctrls, NULL, V4L2_CID_PIXEL_RATE,
				 pixel_rate, pixel_rate, 1, pixel_rate);
	if (ctrl)
		ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;

	sensor->exposure = v4l2_ctrl_new_std(&sensor->ctrls, &ox02f10_ctrl_ops,
					    V4L2_CID_EXPOSURE, OX02F10_EXPOSURE_MIN,
					    OX02F10_VTS_DEFAULT - OX02F10_EXPOSURE_MARGIN,
					    1, OX02F10_EXPOSURE_DEFAULT);
	sensor->analogue_gain = v4l2_ctrl_new_std(&sensor->ctrls, &ox02f10_ctrl_ops,
						 V4L2_CID_ANALOGUE_GAIN,
						 OX02F10_ANALOG_GAIN_MIN,
						 OX02F10_ANALOG_GAIN_MAX, 1,
						 OX02F10_ANALOG_GAIN_DEFAULT);
	/*
	 * The table's VTS is smaller than the output height. Its timing units
	 * need vendor confirmation before exposing HBLANK/VBLANK controls.
	 * Keep the existing fixed-mode exposure limits in register units.
	 */
	if (sensor->ctrls.error) {
		ret = sensor->ctrls.error;
		v4l2_ctrl_handler_free(&sensor->ctrls);
		return ret;
	}
	sensor->sd.ctrl_handler = &sensor->ctrls;
	return 0;
}

static int ox02f10_probe(struct i2c_client *client)
{
	struct device *dev = &client->dev;
	struct ox02f10 *sensor;
	int ret;

	sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL);
	if (!sensor)
		return -ENOMEM;
	sensor->dev = dev;
	mutex_init(&sensor->mutex);
	sensor->regmap = devm_regmap_init_i2c(client, &ox02f10_regmap_config);
	if (IS_ERR(sensor->regmap)) {
		ret = PTR_ERR(sensor->regmap);
		goto destroy_mutex;
	}
	sensor->xclk = devm_clk_get(dev, "inck");
	if (IS_ERR(sensor->xclk)) {
		ret = dev_err_probe(dev, PTR_ERR(sensor->xclk),
				    "failed to get input clock\n");
		goto destroy_mutex;
	}
	if (clk_get_rate(sensor->xclk) != OX02F10_XCLK_FREQ) {
		dev_err(dev, "input clock must be %u Hz\n", OX02F10_XCLK_FREQ);
		ret = -EINVAL;
		goto destroy_mutex;
	}
	sensor->pwdn_gpio =
		devm_gpiod_get_optional(dev, "pwdn", GPIOD_OUT_HIGH);
	if (IS_ERR(sensor->pwdn_gpio)) {
		ret = dev_err_probe(dev, PTR_ERR(sensor->pwdn_gpio),
				    "failed to get power-down GPIO\n");
		goto destroy_mutex;
	}
	sensor->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
	if (IS_ERR(sensor->reset_gpio)) {
		ret = dev_err_probe(dev, PTR_ERR(sensor->reset_gpio),
				    "failed to get reset GPIO\n");
		goto destroy_mutex;
	}
	ret = ox02f10_parse_endpoint(sensor);
	if (ret)
		goto destroy_mutex;
	v4l2_i2c_subdev_init(&sensor->sd, client, &ox02f10_subdev_ops);
	sensor->sd.internal_ops = &ox02f10_internal_ops;
	ox02f10_fill_format(&sensor->fmt);
	sensor->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
			    V4L2_SUBDEV_FL_HAS_EVENTS;
	sensor->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
	sensor->pad.flags = MEDIA_PAD_FL_SOURCE;
	ret = media_entity_pads_init(&sensor->sd.entity, 1, &sensor->pad);
	if (ret)
		goto destroy_mutex;
	ret = ox02f10_init_controls(sensor);
	if (ret)
		goto cleanup_entity;
	ret = ox02f10_power_on(sensor);
	if (ret)
		goto free_ctrls;
	ret = ox02f10_identify(sensor);
	ox02f10_power_off(sensor);
	if (ret)
		goto free_ctrls;
	pm_runtime_set_suspended(dev);
	pm_runtime_enable(dev);
	ret = v4l2_async_register_subdev_sensor(&sensor->sd);
	if (ret)
		goto disable_pm;
	return 0;

disable_pm:
	pm_runtime_disable(dev);
free_ctrls:
	v4l2_ctrl_handler_free(&sensor->ctrls);
cleanup_entity:
	media_entity_cleanup(&sensor->sd.entity);
destroy_mutex:
	mutex_destroy(&sensor->mutex);
	return ret;
}

static void ox02f10_remove(struct i2c_client *client)
{
	struct v4l2_subdev *sd = i2c_get_clientdata(client);
	struct ox02f10 *sensor = to_ox02f10(sd);

	v4l2_async_unregister_subdev(sd);
	if (sensor->streaming)
		ox02f10_set_stream(sd, 0);
	v4l2_ctrl_handler_free(&sensor->ctrls);
	media_entity_cleanup(&sd->entity);
	pm_runtime_disable(sensor->dev);
	if (!pm_runtime_status_suspended(sensor->dev))
		ox02f10_power_off(sensor);
	pm_runtime_set_suspended(sensor->dev);
	mutex_destroy(&sensor->mutex);
}

static const struct dev_pm_ops ox02f10_pm_ops = {
	SET_RUNTIME_PM_OPS(ox02f10_runtime_suspend,
			   ox02f10_runtime_resume, NULL)
};

static const struct of_device_id ox02f10_of_match[] = {
	{ .compatible = "ovti,ox02f10" },
	{ }
};
MODULE_DEVICE_TABLE(of, ox02f10_of_match);

static struct i2c_driver ox02f10_i2c_driver = {
	.driver = {
		.name = "ox02f10",
		.of_match_table = ox02f10_of_match,
		.pm = &ox02f10_pm_ops,
	},
	.probe_new = ox02f10_probe,
	.remove = ox02f10_remove,
};
module_i2c_driver(ox02f10_i2c_driver);

MODULE_DESCRIPTION("OmniVision OX02F10 image sensor driver");
MODULE_LICENSE("GPL");
