linux-imx/drivers/media/i2c/ox03c10.c
Laurentiu Palcu 91d5fa5dda LF-13725 media/i2c: ox03c10: initialize custom control values
Currently, interrogating the controls, before they're set for the first
time, will return all-zero values. To fix this, use the init() callback
in the v4l2_ctrl_type_ops structure to populate the initial control
values.

Also, when running the sensor initialization sequence, make sure we
don't cache the settings for the embedded data because they do not
contain register values. They contain ranges. Otherwise we'll end up
with wrong register values in the regmap cache.

Signed-off-by: Laurentiu Palcu <laurentiu.palcu@oss.nxp.com>
Reviewed-by: Robert Chiras <robert.chiras@nxp.com>
Reviewed-by: Mirela Rabulea <mirela.rabulea@nxp.com>
Tested-by: Celine Laurencin <celine.laurencin@nxp.com>
Reviewed-by: Celine Laurencin <celine.laurencin@nxp.com>
Acked-by: Jason Liu <jason.hui.liu@nxp.com>
2024-11-13 17:23:47 +08:00

1024 lines
47 KiB
C

// SPDX-License-Identifier: GPL-2.0+
/*
* OX03C10 camera sensor driver library. The sensor is usually paired with a serializer device.
*
* Copyright 2024 NXP
*
*/
#include <linux/i2c.h>
#include <linux/regmap.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-fwnode.h>
#include <uapi/linux/ox03c10.h>
#include "ox03c10.h"
#include "ox03c10_regs.h"
#define OX03C10_I2C_ADDR 0x36
#define OX03C10_PIXEL_RATE 90000000
#define OX03C10_PWL_LUT_SIZE 132
static const struct ox03c10_reg {
u16 addr;
u8 val;
} ox03c10_init_data[] = {
{ 0x4d5a, 0x1a }, { 0x4d09, 0xff }, { 0x4d09, 0xdf }, { 0x0301, 0xc8 }, { 0x0303, 0x01 },
{ 0x0304, 0x01 }, { 0x0305, 0x2c }, { 0x0306, 0x04 }, { 0x0307, 0x01 }, { 0x0316, 0x00 },
{ 0x0317, 0x00 }, { 0x0318, 0x00 }, { 0x0323, 0x05 }, { 0x0324, 0x01 }, { 0x0325, 0x2c },
{ 0x0400, 0xe0 }, { 0x0401, 0x80 }, { 0x0403, 0xde }, { 0x0404, 0x34 }, { 0x0405, 0x3b },
{ 0x0406, 0xde }, { 0x0407, 0x08 }, { 0x0408, 0xe0 }, { 0x0409, 0x7f }, { 0x040a, 0xde },
{ 0x040b, 0x34 }, { 0x040c, 0x47 }, { 0x040d, 0xd8 }, { 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 }, { 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, 0x04 }, { 0x3806, 0x05 }, { 0x3807, 0x0b }, { 0x3808, 0x07 }, { 0x3809, 0x80 },
{ 0x380a, 0x05 }, { 0x380b, 0x00 }, { 0x380c, 0x04 }, { 0x380d, 0x47 }, { 0x380e, 0x02 },
{ 0x380f, 0xae }, { 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, 0x02 },
{ 0x384d, 0x0d }, { 0x3850, 0x00 }, { 0x3851, 0x42 }, { 0x3852, 0x00 }, { 0x3853, 0x40 },
{ 0x3858, 0x04 }, { 0x388c, 0x02 }, { 0x388d, 0x2b }, { 0x3b40, 0x05 }, { 0x3b41, 0x40 },
{ 0x3b42, 0x00 }, { 0x3b43, 0x90 }, { 0x3b44, 0x00 }, { 0x3b45, 0x20 }, { 0x3b46, 0x00 },
{ 0x3b47, 0x20 }, { 0x3b48, 0x19 }, { 0x3b49, 0x12 }, { 0x3b4a, 0x16 }, { 0x3b4b, 0x2e },
{ 0x3b4c, 0x00 }, { 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 }, { 0x3d82, 0x73 }, { 0x3d85, 0x05 }, { 0x3d8a, 0x03 },
{ 0x3d8b, 0xff }, { 0x3d99, 0x00 }, { 0x3d9a, 0x9f }, { 0x3d9b, 0x00 }, { 0x3d9c, 0xa0 },
{ 0x3da4, 0x00 }, { 0x3da7, 0x50 }, { 0x420e, 0xff }, { 0x420f, 0xff }, { 0x4210, 0xff },
{ 0x4211, 0xff }, { 0x421e, 0x02 }, { 0x421f, 0x45 }, { 0x4220, 0xe1 }, { 0x4221, 0x05 },
{ 0x4301, 0x0f }, { 0x4307, 0x03 }, { 0x4308, 0x13 }, { 0x430a, 0x13 }, { 0x430d, 0x93 },
{ 0x430e, 0x14 }, { 0x430f, 0x17 }, { 0x4310, 0x95 }, { 0x4311, 0x16 }, { 0x4316, 0x00 },
{ 0x4317, 0x28 }, { 0x4319, 0x01 }, { 0x431a, 0x00 }, { 0x431b, 0x00 }, { 0x431d, 0x2a },
{ 0x431e, 0x11 }, { 0x431f, 0x30 }, { 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, 0xfb }, { 0x459c, 0xf3 }, { 0x4602, 0x00 }, { 0x4603, 0x13 },
{ 0x4604, 0x00 }, { 0x4609, 0x0a }, { 0x460a, 0x30 }, { 0x4610, 0x00 }, { 0x4611, 0x70 },
{ 0x4612, 0x01 }, { 0x4613, 0x00 }, { 0x4614, 0x00 }, { 0x4615, 0x70 }, { 0x4616, 0x01 },
{ 0x4617, 0x00 }, { 0x4800, 0x04 }, { 0x480a, 0x22 }, { 0x4813, 0xe4 }, { 0x4814, 0x2a },
{ 0x4837, 0x0d }, { 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, 0x3f }, { 0x4f01, 0xff }, { 0x4f02, 0xff }, { 0x4f03, 0x2c },
{ 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, 0x65 }, { 0x5002, 0x60 }, { 0x5003, 0x6a },
{ 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, 0x00 }, { 0x507b, 0x00 }, { 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, 0x02 }, { 0x5E01, 0x0F }, { 0x5E02, 0x0F }, { 0x5E03, 0x10 },
{ 0x5E04, 0x11 }, { 0x5E05, 0x12 }, { 0x5E06, 0x13 }, { 0x5E07, 0x00 }, { 0x5E08, 0x00 },
{ 0x5E09, 0x00 }, { 0x5E0A, 0x00 }, { 0x5E0B, 0x00 }, { 0x5E0C, 0x00 }, { 0x5E0D, 0x00 },
{ 0x5E0E, 0x00 }, { 0x5E0F, 0x00 }, { 0x5E10, 0x00 }, { 0x5E11, 0x00 }, { 0x5E12, 0x00 },
{ 0x5E13, 0x00 }, { 0x5E14, 0x00 }, { 0x5E15, 0x00 }, { 0x5E16, 0x00 }, { 0x5E17, 0x00 },
{ 0x5E18, 0x00 }, { 0x5E19, 0x00 }, { 0x5E1A, 0x00 }, { 0x5E1B, 0x00 }, { 0x5E1C, 0x00 },
{ 0x5E1D, 0x00 }, { 0x5E1E, 0x00 }, { 0x5E1F, 0x00 }, { 0x5E20, 0x00 }, { 0x5E21, 0x00 },
{ 0x5E22, 0x00 }, { 0x5E23, 0x7f }, { 0x5E24, 0xff }, { 0x5E25, 0x00 }, { 0x5E26, 0x40 },
{ 0x5E27, 0x00 }, { 0x5E28, 0x00 }, { 0x5E29, 0x20 }, { 0x5E2A, 0x00 }, { 0x5E2B, 0x00 },
{ 0x5E2C, 0x04 }, { 0x5E2D, 0x92 }, { 0x5E2E, 0x00 }, { 0x5E2F, 0x09 }, { 0x5E30, 0x25 },
{ 0x5E31, 0x00 }, { 0x5E32, 0x12 }, { 0x5E33, 0x49 }, { 0x5E34, 0x00 }, { 0x5E35, 0x00 },
{ 0x5E36, 0x00 }, { 0x5E37, 0x00 }, { 0x5E38, 0x00 }, { 0x5E39, 0x00 }, { 0x5E3A, 0x00 },
{ 0x5E3B, 0x00 }, { 0x5E3C, 0x00 }, { 0x5E3D, 0x00 }, { 0x5E3E, 0x00 }, { 0x5E3F, 0x00 },
{ 0x5E40, 0x00 }, { 0x5E41, 0x00 }, { 0x5E42, 0x00 }, { 0x5E43, 0x00 }, { 0x5E44, 0x00 },
{ 0x5E45, 0x00 }, { 0x5E46, 0x00 }, { 0x5E47, 0x00 }, { 0x5E48, 0x00 }, { 0x5E49, 0x00 },
{ 0x5E4A, 0x00 }, { 0x5E4B, 0x00 }, { 0x5E4C, 0x00 }, { 0x5E4D, 0x00 }, { 0x5E4E, 0x00 },
{ 0x5E4F, 0x00 }, { 0x5E50, 0x00 }, { 0x5E51, 0x00 }, { 0x5E52, 0x00 }, { 0x5E53, 0x00 },
{ 0x5E54, 0x00 }, { 0x5E55, 0x00 }, { 0x5E56, 0x00 }, { 0x5E57, 0x00 }, { 0x5E58, 0x00 },
{ 0x5E59, 0x00 }, { 0x5E5A, 0x00 }, { 0x5E5B, 0x00 }, { 0x5E5C, 0x00 }, { 0x5E5D, 0x00 },
{ 0x5E5E, 0x00 }, { 0x5E5F, 0x00 }, { 0x5E60, 0x00 }, { 0x5E61, 0x00 }, { 0x5E62, 0x00 },
{ 0x5E63, 0x00 }, { 0x5E64, 0x00 }, { 0x5E65, 0x00 }, { 0x5E66, 0x00 }, { 0x5E67, 0x00 },
{ 0x5E68, 0x00 }, { 0x5E69, 0x00 }, { 0x5E6A, 0x00 }, { 0x5E6B, 0x00 }, { 0x5E6C, 0x00 },
{ 0x5E6D, 0x00 }, { 0x5E6E, 0x00 }, { 0x5E6F, 0x00 }, { 0x5E70, 0x00 }, { 0x5E71, 0x00 },
{ 0x5E72, 0x00 }, { 0x5E73, 0x00 }, { 0x5E74, 0x00 }, { 0x5E75, 0x00 }, { 0x5E76, 0x00 },
{ 0x5E77, 0x00 }, { 0x5E78, 0x00 }, { 0x5E79, 0x00 }, { 0x5E7A, 0x00 }, { 0x5E7B, 0x00 },
{ 0x5E7C, 0x00 }, { 0x5E7D, 0x00 }, { 0x5E7E, 0x00 }, { 0x5E7F, 0x00 }, { 0x5E80, 0x00 },
{ 0x5E81, 0x00 }, { 0x5E82, 0x00 }, { 0x5E83, 0x00 }, { 0x5E84, 0x00 }, { 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 }, { 0x4f04, 0xf8 }, { 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, 0x07 }, { 0x380e, 0x02 }, { 0x380f, 0xae }, { 0x380c, 0x04 }, { 0x380d, 0x47 },
{ 0x384c, 0x02 }, { 0x384d, 0x0d }, { 0x388c, 0x02 }, { 0x388d, 0x2b }, { 0x420e, 0x66 },
{ 0x420f, 0x5d }, { 0x4210, 0xa8 }, { 0x4211, 0x55 }, { 0x507a, 0x5f }, { 0x507b, 0x46 },
{ 0x0304, 0x01 }, { 0x0305, 0x2c }, { 0x0307, 0x02 }, { 0x4837, 0x1a }, { 0x420e, 0x54 },
{ 0x420f, 0xa0 }, { 0x4210, 0xca }, { 0x4211, 0xf2 }, { 0x040e, 0x08 }, { 0x040c, 0x50 },
{ 0x040d, 0xe2 }, { 0x0408, 0x70 }, { 0x0409, 0x56 }, { 0x040a, 0x2d }, { 0x040b, 0x09 },
{ 0x0324, 0x00 }, { 0x0325, 0xf0 }, { 0x380c, 0x07 }, { 0x380d, 0xae }, { 0x384c, 0x03 },
{ 0x384d, 0xd7 }, { 0x388c, 0x03 }, { 0x388d, 0xd7 }, { 0x0400, 0x70 }, { 0x0401, 0x80 },
{ 0x0403, 0x2d }, { 0x0404, 0x09 }, { 0x0405, 0x25 }, { 0x0406, 0x80 }, { 0x0407, 0x08 },
{ 0x4603, 0x11 }, { 0x0309, 0x02 }, { 0x0320, 0x02 }, { 0x0362, 0x8a },
/* Omnivision settings */
{ 0x0307, 0x03 }, { 0x4837, 0x1a }, { 0x040e, 0x08 },
{ 0x040c, 0x47 }, { 0x040d, 0xed }, { 0x0408, 0x70 }, { 0x0409, 0x62 }, { 0x040a, 0x2d },
{ 0x040b, 0x09 }, { 0x4603, 0x11 }, { 0x0324, 0x01 }, { 0x0325, 0x36 }, { 0x0329, 0x02 },
{ 0x032a, 0x05 }, { 0x032b, 0x08 }, { 0x032c, 0x02 }, { 0x0327, 0x09 }, { 0x0326, 0x0e },
{ 0x380e, 0x02 }, { 0x380f, 0xae }, { 0x380c, 0x05 }, { 0x380d, 0xe2 }, { 0x384c, 0x02 },
{ 0x384d, 0xf1 }, { 0x388c, 0x02 }, { 0x388d, 0xf1 }, { 0x0400, 0x70 }, { 0x0401, 0x7f },
{ 0x0403, 0x2d }, { 0x0404, 0x09 }, { 0x0405, 0x2b }, { 0x0406, 0x8d }, { 0x0407, 0x08 },
/* Fsync */
{ 0x3015, 0x0A }, { 0x3009, 0x02 }, { 0x3822, 0x24 }, { 0x3823, 0x50 }, { 0x383e, 0x81 },
{ 0x3881, 0x34 }, { 0x3882, 0x02 }, { 0x3883, 0x8a }, { 0x388e, 0x01 }, { 0x388f, 0x00 },
{ 0x3892, 0x44 }, { 0x3826, 0x00 },
/* Declaring the registers to be included in the embedded data */
{ 0x3208, 0x04 }, { 0x350e, 0x02 }, { 0x3514, 0x02 }, { 0x3518, 0x03 }, { 0x354e, 0x02 },
{ 0x3554, 0x02 }, { 0x3558, 0x03 }, { 0x3594, 0x02 }, { 0x3598, 0x03 }, { 0x35ce, 0x02 },
{ 0x35d4, 0x02 }, { 0x35d8, 0x03 }, { 0x483E, 0x02 }, { 0x4D2A, 0x02 }, { 0x5280, 0x08 },
{ 0x5480, 0x08 }, { 0x5680, 0x08 }, { 0x5880, 0x0A }, { 0x3208, 0x14 },
{ 0x431c, 0x6e }, { 0x0100, 0x00 },
};
static const struct regmap_range ox03c10_volatile_ranges[] = {
{ 0x7057, 0x7059 }, { 0x705b, 0x705d }, /* OTP correction registers */
};
static const struct regmap_access_table ox03c10_volatile_access_table = {
.yes_ranges = ox03c10_volatile_ranges,
.n_yes_ranges = ARRAY_SIZE(ox03c10_volatile_ranges),
};
static const struct regmap_config ox03c10_sensor_regmap_cfg = {
.name = "ox03c10",
.reg_bits = 16,
.val_bits = 8,
.max_register = 0x705D,
.volatile_table = &ox03c10_volatile_access_table,
.cache_type = REGCACHE_RBTREE,
};
static struct ox03c10_mode ox03c10_modes[] = {
{
.width = OX03C10_PIXEL_ARRAY_WIDTH,
.height = OX03C10_PIXEL_ARRAY_HEIGHT,
.hts = 2186,
.vts = 1372,
.fps = 30
},
};
static int ox03c10_exposure_set(struct ox03c10 *sensor, struct ox03c10_exposure *exp)
{
int ret = 0;
u8 buf[2];
if (sensor->streaming)
ret |= regmap_write(sensor->rmap, OX03C10_GRP_HOLD_8, 0x00); /* set group hold 0 */
buf[0] = (exp->dcg >> 8) & 0xff;
buf[1] = exp->dcg & 0xff;
ret |= regmap_bulk_write(sensor->rmap, OX03C10_AEC_HCG_CTRL_01, buf, 2);
buf[0] = (exp->spd >> 8) & 0xff;
buf[1] = exp->spd & 0xff;
ret |= regmap_bulk_write(sensor->rmap, OX03C10_AEC_SPD_CTRL_01, buf, 2);
buf[0] = (exp->vs >> 8) & 0xff;
buf[1] = exp->vs & 0xff;
ret |= regmap_bulk_write(sensor->rmap, OX03C10_AEC_VS_CTRL_01, buf, 2);
if (sensor->streaming) {
ret |= regmap_write(sensor->rmap, OX03C10_GRP_HOLD_8, 0x10); /* end group hold 0 */
ret |= regmap_write(sensor->rmap, OX03C10_GRP_HOLD_8, 0xE0); /* quick launch */
}
return ret ? -EIO : 0;
}
static int ox03c10_analogue_gain_set(struct ox03c10 *sensor, struct ox03c10_analog_gain *gain)
{
int ret = 0;
u8 buf[2];
if (sensor->streaming)
ret |= regmap_write(sensor->rmap, OX03C10_GRP_HOLD_8, 0x01); /* set group hold 1 */
buf[0] = (gain->hcg >> 4) & 0xf;
buf[1] = (gain->hcg & 0xf) << 4;
ret |= regmap_bulk_write(sensor->rmap, OX03C10_AEC_HCG_CTRL_08, buf, 2);
buf[0] = (gain->spd >> 4) & 0xf;
buf[1] = (gain->spd & 0xf) << 4;
ret |= regmap_bulk_write(sensor->rmap, OX03C10_AEC_SPD_CTRL_08, buf, 2);
buf[0] = (gain->lcg >> 4) & 0xf;
buf[1] = (gain->lcg & 0xf) << 4;
ret |= regmap_bulk_write(sensor->rmap, OX03C10_AEC_LCG_CTRL_08, buf, 2);
buf[0] = (gain->vs >> 4) & 0xf;
buf[1] = (gain->vs & 0xf) << 4;
ret |= regmap_bulk_write(sensor->rmap, OX03C10_AEC_VS_CTRL_08, buf, 2);
if (sensor->streaming) {
ret |= regmap_write(sensor->rmap, OX03C10_GRP_HOLD_8, 0x11); /* end group hold 1 */
ret |= regmap_write(sensor->rmap, OX03C10_GRP_HOLD_8, 0xE1); /* quick launch */
}
return ret ? -EIO : 0;
}
static int ox03c10_digital_gain_set(struct ox03c10 *sensor, struct ox03c10_digital_gain *gain)
{
int ret = 0;
u8 buf[3];
if (sensor->streaming)
ret |= regmap_write(sensor->rmap, OX03C10_GRP_HOLD_8, 0x02); /* set group hold 2 */
buf[0] = (gain->hcg >> 10) & 0xf;
buf[1] = (gain->hcg >> 2) & 0xff;
buf[2] = (gain->hcg & 0x3) << 6;
ret |= regmap_bulk_write(sensor->rmap, OX03C10_AEC_HCG_CTRL_0A, buf, 3);
buf[0] = (gain->spd >> 10) & 0xf;
buf[1] = (gain->spd >> 2) & 0xff;
buf[2] = (gain->spd & 0x3) << 6;
ret |= regmap_bulk_write(sensor->rmap, OX03C10_AEC_SPD_CTRL_0A, buf, 3);
buf[0] = (gain->lcg >> 10) & 0xf;
buf[1] = (gain->lcg >> 2) & 0xff;
buf[2] = (gain->lcg & 0x3) << 6;
ret |= regmap_bulk_write(sensor->rmap, OX03C10_AEC_LCG_CTRL_0A, buf, 3);
buf[0] = (gain->vs >> 10) & 0xf;
buf[1] = (gain->vs >> 2) & 0xff;
buf[2] = (gain->vs & 0x3) << 6;
ret |= regmap_bulk_write(sensor->rmap, OX03C10_AEC_VS_CTRL_0A, buf, 3);
if (sensor->streaming) {
ret |= regmap_write(sensor->rmap, OX03C10_GRP_HOLD_8, 0x12); /* end group hold 2 */
ret |= regmap_write(sensor->rmap, OX03C10_GRP_HOLD_8, 0xE2); /* quick launch */
}
return ret ? -EIO : 0;
}
static int ox03c10_wb_gain_set(struct ox03c10 *sensor, struct ox03c10_wb_capture_gain *wb_gain)
{
int i, ret = 0;
u8 buf[8];
u16 base_addr[4] = {
OX03C10_AWB_GAIN_HCG_0,
OX03C10_AWB_GAIN_LCG_0,
OX03C10_AWB_GAIN_SPD_0,
OX03C10_AWB_GAIN_VS_0
};
if (sensor->streaming)
ret |= regmap_write(sensor->rmap, OX03C10_GRP_HOLD_8, 0x03); /* set group hold 3 */
for (i = 0; i < 4; i++, wb_gain++) {
buf[0] = (wb_gain->b >> 8) & 0xff;
buf[1] = wb_gain->b & 0xff;
buf[2] = (wb_gain->gb >> 8) & 0xff;
buf[3] = wb_gain->gb & 0xff;
buf[4] = (wb_gain->gr >> 8) & 0xff;
buf[5] = wb_gain->gr & 0xff;
buf[6] = (wb_gain->r >> 8) & 0xff;
buf[7] = wb_gain->r & 0xff;
ret |= regmap_bulk_write(sensor->rmap, base_addr[i], buf, 8);
}
if (sensor->streaming) {
ret |= regmap_write(sensor->rmap, OX03C10_GRP_HOLD_8, 0x13); /* end group hold 3 */
ret |= regmap_write(sensor->rmap, OX03C10_GRP_HOLD_8, 0xE3); /* quick launch */
}
return ret ? -EIO : 0;
}
static int ox03c10_pwl_enable(struct ox03c10 *sensor, bool en)
{
int ret;
if (sensor->streaming)
return -EBUSY;
ret = regmap_update_bits(sensor->rmap, OX03C10_FORMAT_REG_1F, BIT(5), en ? BIT(5) : 0);
ret |= regmap_update_bits(sensor->rmap, OX03C10_ISP_CTRL_02, BIT(6), en ? BIT(6) : 0);
return ret ? -EIO : 0;
}
static int ox03c10_pwl_params_set(struct ox03c10 *sensor, struct ox03c10_pwl_ctrl *pwl_ctrl)
{
if (sensor->streaming)
return -EBUSY;
return regmap_update_bits(sensor->rmap, OX03C10_FORMAT_REG_1F, 0xD8,
(pwl_ctrl->pack24bit_sel << 6) | (pwl_ctrl->pwl_mode << 3));
}
static int ox03c10_pwl_lut_set(struct ox03c10 *sensor, u8 *lut)
{
if (sensor->streaming)
return -EBUSY;
return regmap_bulk_write(sensor->rmap, OX03C10_PWL0_0_1, lut, OX03C10_PWL_LUT_SIZE);
}
static int ox03c10_hflip_enable(struct ox03c10 *sensor, bool en)
{
int ret;
if (sensor->streaming)
return -EBUSY;
ret = regmap_update_bits(sensor->rmap, OX03C10_REG_WIN_09, BIT(0), BIT(0));
ret |= regmap_update_bits(sensor->rmap, OX03C10_TIMING_CTRL_REG_20, BIT(5),
en ? 0 : BIT(5));
return ret ? -EIO : 0;
}
static int ox03c10_s_ctrl(struct v4l2_ctrl *ctrl)
{
struct ox03c10 *sensor = container_of(ctrl->handler, struct ox03c10, ctrl_handler);
switch (ctrl->id) {
case V4L2_CID_OX03C10_EXPOSURE:
return ox03c10_exposure_set(sensor, ctrl->p_new.p);
case V4L2_CID_OX03C10_ANALOGUE_GAIN:
return ox03c10_analogue_gain_set(sensor, ctrl->p_new.p);
case V4L2_CID_OX03C10_DIGITAL_GAIN:
return ox03c10_digital_gain_set(sensor, ctrl->p_new.p);
case V4L2_CID_OX03C10_WB_GAIN:
return ox03c10_wb_gain_set(sensor, ctrl->p_new.p);
case V4L2_CID_OX03C10_PWL_EN:
return ox03c10_pwl_enable(sensor, ctrl->val);
case V4L2_CID_OX03C10_PWL_CTRL:
return ox03c10_pwl_params_set(sensor, ctrl->p_new.p);
case V4L2_CID_OX03C10_PWL_KNEE_POINTS_LUT:
return ox03c10_pwl_lut_set(sensor, ctrl->p_new.p);
case V4L2_CID_HFLIP:
return ox03c10_hflip_enable(sensor, ctrl->val);
default:
return -EINVAL;
}
}
static int ox03c10_otp_correction_get(struct ox03c10 *sensor, void *ret_values)
{
struct ox03c10_otp_correction *otp = ret_values;
int ret;
u8 reg_val[3] = {0};
ret = regmap_bulk_read(sensor->rmap, 0x7057, reg_val, 3);
otp->val1 = (reg_val[0] << 16) | (reg_val[1] << 8) | reg_val[2];
ret |= regmap_bulk_read(sensor->rmap, 0x705b, reg_val, 3);
otp->val2 = (reg_val[0] << 16) | (reg_val[1] << 8) | reg_val[2];
return ret ? -EIO : 0;
}
static int ox03c10_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
{
struct ox03c10 *sensor = container_of(ctrl->handler, struct ox03c10, ctrl_handler);
switch (ctrl->id) {
case V4L2_CID_OX03C10_OTP_CORRECTION:
return ox03c10_otp_correction_get(sensor, ctrl->p_new.p);
default:
return -EINVAL;
}
}
static const struct v4l2_ctrl_ops ox03c10_ctrl_ops = {
.g_volatile_ctrl = ox03c10_g_volatile_ctrl,
.s_ctrl = ox03c10_s_ctrl,
};
static void ox03c10_ctrl_type_op_log(const struct v4l2_ctrl *ctrl)
{
/* no logging yet */
}
static struct ox03c10_exposure ox03c10_initial_exposure;
static struct ox03c10_analog_gain ox03c10_initial_analog_gain;
static struct ox03c10_digital_gain ox03c10_initial_digital_gain;
static struct ox03c10_wb_capture_gain ox03c10_initial_wb_capture_gain[4];
static struct ox03c10_pwl_ctrl ox03c10_initial_pwl_ctrl;
static u8 ox03c10_initial_pwl_knee_points_lut[OX03C10_PWL_LUT_SIZE];
static int ox03c10_get_initial_params(struct ox03c10 *sensor)
{
u16 wb_base_addr[4] = {
OX03C10_AWB_GAIN_HCG_0,
OX03C10_AWB_GAIN_LCG_0,
OX03C10_AWB_GAIN_SPD_0,
OX03C10_AWB_GAIN_VS_0,
};
int ret = 0;
u8 buf[8];
int i;
/* get initial exposure */
ret |= regmap_bulk_read(sensor->rmap, OX03C10_AEC_HCG_CTRL_01, buf, 2);
ox03c10_initial_exposure.dcg = buf[0] << 8 | buf[1];
ret |= regmap_bulk_read(sensor->rmap, OX03C10_AEC_SPD_CTRL_01, buf, 2);
ox03c10_initial_exposure.spd = buf[0] << 8 | buf[1];
ret |= regmap_bulk_read(sensor->rmap, OX03C10_AEC_VS_CTRL_01, buf, 2);
ox03c10_initial_exposure.vs = buf[0] << 8 | buf[1];
/* get initial analog gains */
ret |= regmap_bulk_read(sensor->rmap, OX03C10_AEC_HCG_CTRL_08, buf, 2);
ox03c10_initial_analog_gain.hcg = ((buf[0] & 0xf) << 4) | ((buf[1] & 0xf0) >> 4);
ret |= regmap_bulk_read(sensor->rmap, OX03C10_AEC_SPD_CTRL_08, buf, 2);
ox03c10_initial_analog_gain.spd = ((buf[0] & 0xf) << 4) | ((buf[1] & 0xf0) >> 4);
ret |= regmap_bulk_read(sensor->rmap, OX03C10_AEC_LCG_CTRL_08, buf, 2);
ox03c10_initial_analog_gain.lcg = ((buf[0] & 0xf) << 4) | ((buf[1] & 0xf0) >> 4);
ret |= regmap_bulk_read(sensor->rmap, OX03C10_AEC_VS_CTRL_08, buf, 2);
ox03c10_initial_analog_gain.vs = ((buf[0] & 0xf) << 4) | ((buf[1] & 0xf0) >> 4);
/* get initial digital gains */
ret |= regmap_bulk_read(sensor->rmap, OX03C10_AEC_HCG_CTRL_0A, buf, 3);
ox03c10_initial_digital_gain.hcg = ((buf[0] & 0xf) << 10) | (buf[1] << 2) |
((buf[2] & 0x3) >> 6);
ret |= regmap_bulk_read(sensor->rmap, OX03C10_AEC_SPD_CTRL_0A, buf, 3);
ox03c10_initial_digital_gain.spd = ((buf[0] & 0xf) << 10) | (buf[1] << 2) |
((buf[2] & 0x3) >> 6);
ret |= regmap_bulk_read(sensor->rmap, OX03C10_AEC_LCG_CTRL_0A, buf, 3);
ox03c10_initial_digital_gain.lcg = ((buf[0] & 0xf) << 10) | (buf[1] << 2) |
((buf[2] & 0x3) >> 6);
ret |= regmap_bulk_read(sensor->rmap, OX03C10_AEC_VS_CTRL_0A, buf, 3);
ox03c10_initial_digital_gain.vs = ((buf[0] & 0xf) << 10) | (buf[1] << 2) |
((buf[2] & 0x3) >> 6);
/* get initial white balance settings */
for (i = 0; i < 4; i++) {
ret |= regmap_bulk_read(sensor->rmap, wb_base_addr[i], buf, 8);
ox03c10_initial_wb_capture_gain[i].b = (buf[0] << 8) | buf[1];
ox03c10_initial_wb_capture_gain[i].gb = (buf[2] << 8) | buf[3];
ox03c10_initial_wb_capture_gain[i].gr = (buf[4] << 8) | buf[5];
ox03c10_initial_wb_capture_gain[i].r = (buf[6] << 8) | buf[7];
}
/* get initial PWL control params */
ret |= regmap_bulk_read(sensor->rmap, OX03C10_FORMAT_REG_1F, buf, 1);
ox03c10_initial_pwl_ctrl.pack24bit_sel = (buf[0] & 0xc0) >> 6;
ox03c10_initial_pwl_ctrl.pwl_mode = (buf[0] & 0x18) >> 3;
/* get initial PWL knee points LUT */
ret |= regmap_bulk_read(sensor->rmap, OX03C10_PWL0_0_1,
ox03c10_initial_pwl_knee_points_lut, OX03C10_PWL_LUT_SIZE);
return ret ? -EIO : 0;
}
static void ox03c10_v4l2_ctrl_type_op_init(const struct v4l2_ctrl *ctrl, u32 from_idx,
union v4l2_ctrl_ptr ptr)
{
u32 tot_elems = ctrl->elems;
u32 elems = tot_elems - from_idx;
if (from_idx >= elems)
return;
switch (ctrl->id) {
case V4L2_CID_OX03C10_EXPOSURE:
memcpy(ptr.p, &ox03c10_initial_exposure, sizeof(ox03c10_initial_exposure));
break;
case V4L2_CID_OX03C10_ANALOGUE_GAIN:
memcpy(ptr.p, &ox03c10_initial_analog_gain, sizeof(ox03c10_initial_analog_gain));
break;
case V4L2_CID_OX03C10_DIGITAL_GAIN:
memcpy(ptr.p, &ox03c10_initial_digital_gain, sizeof(ox03c10_initial_digital_gain));
break;
case V4L2_CID_OX03C10_WB_GAIN:
memcpy(ptr.p, &ox03c10_initial_wb_capture_gain,
sizeof(ox03c10_initial_wb_capture_gain));
break;
case V4L2_CID_OX03C10_PWL_CTRL:
memcpy(ptr.p, &ox03c10_initial_pwl_ctrl, sizeof(ox03c10_initial_pwl_ctrl));
break;
case V4L2_CID_OX03C10_PWL_KNEE_POINTS_LUT:
memcpy(ptr.p, &ox03c10_initial_pwl_knee_points_lut,
sizeof(ox03c10_initial_pwl_knee_points_lut));
break;
default:
v4l2_ctrl_type_op_init(ctrl, from_idx, ptr);
break;
}
}
static const struct v4l2_ctrl_type_ops ox03c10_ctrl_type_ops = {
.init = ox03c10_v4l2_ctrl_type_op_init,
.validate = v4l2_ctrl_type_op_validate,
.equal = v4l2_ctrl_type_op_equal,
.log = ox03c10_ctrl_type_op_log,
};
static const struct v4l2_ctrl_config ox03c10_ctrl_cfgs[] = {
{
.ops = &ox03c10_ctrl_ops,
.type_ops = &ox03c10_ctrl_type_ops,
.id = V4L2_CID_OX03C10_EXPOSURE,
.name = "Exposure for: DCG, SPD, VS",
.type = V4L2_CTRL_TYPE_U8,
.min = 0x00,
.max = 0xff,
.step = 1,
.def = 0,
.dims = { sizeof(struct ox03c10_exposure) },
},
{
.ops = &ox03c10_ctrl_ops,
.type_ops = &ox03c10_ctrl_type_ops,
.id = V4L2_CID_OX03C10_ANALOGUE_GAIN,
.name = "Analog gains for: HCG, LCG, SPD, VS",
.type = V4L2_CTRL_TYPE_U8,
.min = 0x00,
.max = 0xff,
.step = 1,
.def = 0x0,
.dims = { sizeof(struct ox03c10_analog_gain) },
},
{
.ops = &ox03c10_ctrl_ops,
.type_ops = &ox03c10_ctrl_type_ops,
.id = V4L2_CID_OX03C10_DIGITAL_GAIN,
.name = "Digital gains for: HCG, LCG, SPD, VS",
.type = V4L2_CTRL_TYPE_U8,
.min = 0x00,
.max = 0xff,
.step = 1,
.def = 0x00,
.dims = { sizeof(struct ox03c10_digital_gain) },
},
{
.ops = &ox03c10_ctrl_ops,
.type_ops = &ox03c10_ctrl_type_ops,
.id = V4L2_CID_OX03C10_WB_GAIN,
.name = "White balance gain for: HCG, LCG, SPD, VS",
.type = V4L2_CTRL_TYPE_U8,
.min = 0x00,
.max = 0xff,
.step = 1,
.def = 0x00,
.dims = { 4 * sizeof(struct ox03c10_wb_capture_gain) },
},
{
.ops = &ox03c10_ctrl_ops,
.id = V4L2_CID_OX03C10_PWL_EN,
.name = "Enable PWL compression",
.type = V4L2_CTRL_TYPE_BOOLEAN,
.min = false,
.max = true,
.step = 1,
.def = true,
},
{
.ops = &ox03c10_ctrl_ops,
.type_ops = &ox03c10_ctrl_type_ops,
.id = V4L2_CID_OX03C10_PWL_CTRL,
.name = "PWL compression control params",
.type = V4L2_CTRL_TYPE_U8,
.min = 0x00,
.max = 0xff,
.step = 1,
.def = 0,
.dims = { sizeof(struct ox03c10_pwl_ctrl) }
},
{
.ops = &ox03c10_ctrl_ops,
.type_ops = &ox03c10_ctrl_type_ops,
.id = V4L2_CID_OX03C10_PWL_KNEE_POINTS_LUT,
.name = "PWL knee points LUT",
.type = V4L2_CTRL_TYPE_U8,
.min = 0x00,
.max = 0xff,
.step = 1,
.def = 0,
.dims = { 132 }
},
{
.ops = &ox03c10_ctrl_ops,
.type_ops = &ox03c10_ctrl_type_ops,
.id = V4L2_CID_OX03C10_OTP_CORRECTION,
.name = "OTP correction values",
.type = V4L2_CTRL_TYPE_U8,
.min = 0x00,
.max = 0xff,
.step = 1,
.def = 0,
.dims = { sizeof(struct ox03c10_otp_correction) },
.flags = V4L2_CTRL_FLAG_VOLATILE | V4L2_CTRL_FLAG_READ_ONLY,
},
};
int ox03c10_v4l2_controls_init(struct ox03c10 *sensor)
{
struct device *dev = &sensor->client->dev;
struct v4l2_ctrl_handler *ctrl_handler = &sensor->ctrl_handler;
struct v4l2_fwnode_device_properties props;
int i;
u16 hblank, vblank;
int ret;
ret = v4l2_ctrl_handler_init(&sensor->ctrl_handler, ARRAY_SIZE(ox03c10_ctrl_cfgs) + 4);
if (ret < 0) {
dev_err(dev, "Cannot initialize V4L2 ctrl handler.\n");
return ret;
}
v4l2_ctrl_new_std(ctrl_handler, &ox03c10_ctrl_ops, V4L2_CID_PIXEL_RATE,
OX03C10_PIXEL_RATE, OX03C10_PIXEL_RATE, 1, OX03C10_PIXEL_RATE);
hblank = sensor->cur_mode->hts - sensor->cur_mode->width;
v4l2_ctrl_new_std(ctrl_handler, &ox03c10_ctrl_ops, V4L2_CID_HBLANK,
hblank, hblank, 1, hblank);
vblank = sensor->cur_mode->vts - sensor->cur_mode->height;
v4l2_ctrl_new_std(ctrl_handler, &ox03c10_ctrl_ops, V4L2_CID_VBLANK,
vblank, vblank, 1, vblank);
v4l2_ctrl_new_std(ctrl_handler, &ox03c10_ctrl_ops, V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 0);
v4l2_ctrl_new_std(ctrl_handler, &ox03c10_ctrl_ops, V4L2_CID_HFLIP, 0, 1, 1, 0);
ret = v4l2_fwnode_device_parse(sensor->dev, &props);
if (ret)
goto free_ctrls;
ret = v4l2_ctrl_new_fwnode_properties(ctrl_handler, &ox03c10_ctrl_ops, &props);
if (ret)
goto free_ctrls;
for (i = 0; i < ARRAY_SIZE(ox03c10_ctrl_cfgs); i++) {
sensor->ctrls[i] = v4l2_ctrl_new_custom(ctrl_handler, &ox03c10_ctrl_cfgs[i], NULL);
if (ctrl_handler->error) {
dev_err(sensor->dev, "Adding control (%d) failed: %d\n",
i, ctrl_handler->error);
ret = ctrl_handler->error;
goto free_ctrls;
}
}
return 0;
free_ctrls:
v4l2_ctrl_handler_free(ctrl_handler);
return ret;
}
EXPORT_SYMBOL(ox03c10_v4l2_controls_init);
int ox03c10_streaming_start(struct ox03c10 *sensor, bool start)
{
int ret;
if (!start) {
/*
* For stopping, we need to use group hold registers in order to be able to
* stop during vertical blanking to avoid MIPI issues.
*/
ret = regmap_write(sensor->rmap, OX03C10_GRP_HOLD_8, 0x00);
ret |= regmap_write(sensor->rmap, OX03C10_SMIA_R0100, 0);
ret |= regmap_write(sensor->rmap, OX03C10_GRP_HOLD_8, 0x10);
ret |= regmap_write(sensor->rmap, OX03C10_GRP_HOLD_8, 0xA0);
/* Wait a maximum of 1 time frame. Worst case is 33.33ms. */
msleep(34);
} else {
ret = regmap_write(sensor->rmap, OX03C10_SMIA_R0100, 1);
}
sensor->streaming = start;
return ret ? -EIO : 0;
}
EXPORT_SYMBOL(ox03c10_streaming_start);
static int ox03c10_sensor_init(struct ox03c10 *sensor)
{
const struct ox03c10_reg *reg;
int ret = 0;
int i;
/* software reset */
regmap_write(sensor->rmap, OX03C10_SMIA_R0103, 1);
regmap_write(sensor->rmap, OX03C10_SMIA_R0107, 1);
usleep_range(100, 200);
for (i = 0; i < ARRAY_SIZE(ox03c10_init_data); i++) {
reg = &ox03c10_init_data[i];
/*
* Re-enable the cache after the embedded data registers ranges have been set.
*/
if (reg->addr == OX03C10_GRP_HOLD_8 && (reg->val == 0x14 || reg->val == 0x15))
regcache_cache_bypass(sensor->rmap, false);
ret = regmap_write(sensor->rmap, reg->addr, reg->val);
if (ret < 0) {
dev_err(&sensor->client->dev, "Failed to write addr 0x%04x with 0x%02x\n",
reg->addr, reg->val);
return ret;
}
/*
* Make sure we bypass the cache when setting address ranges for embedded data.
* Otherwise, our cache will hold a range instead of the actual value...
*/
if (reg->addr == OX03C10_GRP_HOLD_8 && (reg->val == 0x04 || reg->val == 0x05))
regcache_cache_bypass(sensor->rmap, true);
}
sensor->cur_mode = &ox03c10_modes[0];
return ox03c10_get_initial_params(sensor);
}
struct ox03c10 *ox03c10_init_with_dummy_client(struct i2c_client *client,
bool use_dummy)
{
struct device *dev = &client->dev;
struct ox03c10 *sensor;
int ret;
sensor = devm_kzalloc(dev, sizeof(*sensor) +
ARRAY_SIZE(ox03c10_ctrl_cfgs) * sizeof(struct v4l2_ctrl *),
GFP_KERNEL);
if (!sensor)
return ERR_PTR(-ENOMEM);
sensor->dev = dev;
if (use_dummy) {
sensor->client =
devm_i2c_new_dummy_device(dev, client->adapter,
OX03C10_I2C_ADDR);
if (IS_ERR(sensor->client))
return ERR_PTR(-ENODEV);
} else {
sensor->client = client;
}
sensor->rmap = devm_regmap_init_i2c(sensor->client, &ox03c10_sensor_regmap_cfg);
if (IS_ERR(sensor->rmap)) {
ret = PTR_ERR(sensor->rmap);
dev_err(dev, "Failed to allocate sensor register map: %d\n", ret);
goto error;
}
ret = ox03c10_sensor_init(sensor);
if (ret)
goto error;
return sensor;
error:
return ERR_PTR(ret);
}
EXPORT_SYMBOL(ox03c10_init_with_dummy_client);
struct v4l2_ctrl_handler *ox03c10_ctrl_handler_get(struct ox03c10 *sensor)
{
return &sensor->ctrl_handler;
}
EXPORT_SYMBOL(ox03c10_ctrl_handler_get);
void ox03c10_ctrl_handler_free(struct ox03c10 *sensor)
{
v4l2_ctrl_handler_free(&sensor->ctrl_handler);
}
EXPORT_SYMBOL(ox03c10_ctrl_handler_free);
struct ox03c10_mode *ox03c10_get_mode(int index)
{
if (index >= ARRAY_SIZE(ox03c10_modes))
return ERR_PTR(-EINVAL);
return &ox03c10_modes[index];
}
EXPORT_SYMBOL(ox03c10_get_mode);
MODULE_DESCRIPTION("Omnivision OX03C10 sensor library");
MODULE_AUTHOR("Laurentiu Palcu");
MODULE_LICENSE("GPL");