From 984cbfd81a334f6e7f73b46373c1c26bcb94b82c Mon Sep 17 00:00:00 2001 From: Jason Song Date: Tue, 25 Apr 2023 01:58:34 +0000 Subject: [PATCH] media: i2c: nvp6188 update to version v0.2.0 1. update init registers setting 2. nvp6188 do not stream after writing registers setting 3. support detect fmt change when hotplug ahd camera 4. support 1600x1300 ahd camera input Change-Id: I26d51e5eede8d956065bcb9d94359c7d815c9f44 Signed-off-by: Jason Song --- drivers/media/i2c/nvp6188.c | 1934 ++++++++++++++++++++++------------- 1 file changed, 1205 insertions(+), 729 deletions(-) diff --git a/drivers/media/i2c/nvp6188.c b/drivers/media/i2c/nvp6188.c index 6bd0316101c1..36cf018b34f2 100644 --- a/drivers/media/i2c/nvp6188.c +++ b/drivers/media/i2c/nvp6188.c @@ -10,9 +10,14 @@ * 2. add get virtual channel hotplug status ioctl * 3. add virtual channel hotplug status event report to vicap * 4. fixup variables are reused when multiple devices use the same driver - * V0.0X01.0X02 add quick stream support + * V0.0X02.0X00 version. + * 1. update init registers setting + * 2. nvp6188 do not stream after writing registers setting + * 3. support detect fmt change when hotplug ahd camera + * 4. support 1600x1300 ahd camera input */ +//#define DEBUG #include #include #include @@ -33,18 +38,16 @@ #include #include #include - #include #include #include #include #include - #include #include #include "nvp6188.h" -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x2) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x02, 0x0) #ifndef V4L2_CID_DIGITAL_GAIN #define V4L2_CID_DIGITAL_GAIN V4L2_CID_GAIN @@ -78,13 +81,15 @@ #endif #define NVP_RESO_960H_NSTC_VALUE 0x00 -#define NVP_RESO_960H_PAL_VALUE 0x10 +#define NVP_RESO_960H_PAL_VALUE 0x10 #define NVP_RESO_720P_NSTC_VALUE 0x20 -#define NVP_RESO_720P_PAL_VALUE 0x21 +#define NVP_RESO_720P_PAL_VALUE 0x21 #define NVP_RESO_1080P_NSTC_VALUE 0x30 #define NVP_RESO_1080P_PAL_VALUE 0x31 #define NVP_RESO_960P_NSTC_VALUE 0xa0 -#define NVP_RESO_960P_PAL_VALUE 0xa1 +#define NVP_RESO_960P_PAL_VALUE 0xa1 +#define NVP_RESO_1300P_NSTC_VALUE 0x3A +#define NVP_RESO_1300P_PAL_VALUE 0x3B enum nvp6188_support_reso { NVP_RESO_UNKOWN = 0, @@ -92,10 +97,12 @@ enum nvp6188_support_reso { NVP_RESO_720P_PAL, NVP_RESO_960P_PAL, NVP_RESO_1080P_PAL, + NVP_RESO_1300P_PAL, NVP_RESO_960H_NSTC, NVP_RESO_720P_NSTC, NVP_RESO_960P_NSTC, NVP_RESO_1080P_NSTC, + NVP_RESO_1300P_NSTC, }; /* Audio output port formats */ @@ -123,6 +130,7 @@ struct nvp6188_mode { u32 hdr_mode; u32 vc[PAD_MAX]; u32 channel_reso[PAD_MAX]; + u32 unkown_reso_count[PAD_MAX]; }; struct nvp6188_audio { @@ -136,11 +144,9 @@ struct nvp6188 { struct gpio_desc *reset_gpio; struct gpio_desc *power_gpio; struct gpio_desc *vi_gpio; - struct pinctrl *pinctrl; struct pinctrl_state *pins_default; struct pinctrl_state *pins_sleep; - struct v4l2_subdev subdev; struct media_pad pad; struct v4l2_ctrl_handler ctrl_handler; @@ -149,520 +155,649 @@ struct nvp6188 { struct mutex mutex; bool power_on; struct nvp6188_mode cur_mode; - u32 module_index; u32 cfg_num; const char *module_facing; const char *module_name; const char *len_name; - struct nvp6188_audio *audio_in; struct nvp6188_audio *audio_out; - int streaming; - struct task_struct *detect_thread; struct input_dev* input_dev; unsigned char detect_status; unsigned char last_detect_status; u8 is_reset; + bool disable_dump_register; }; #define to_nvp6188(sd) container_of(sd, struct nvp6188, subdev) static int nvp6188_audio_init(struct nvp6188 *nvp6188); +static int __nvp6188_start_stream(struct nvp6188 *nvp6188); +static int __nvp6188_stop_stream(struct nvp6188 *nvp6188); // detect_status: bit 0~3 means channels plugin status : 1 no exist 0: exist static ssize_t show_hotplug_status(struct device *dev, struct device_attribute *attr, - char *buf) //cat命令时,将会调用该函数 + char *buf) { struct i2c_client *client = to_i2c_client(dev); struct v4l2_subdev *sd = i2c_get_clientdata(client); struct nvp6188 *nvp6188 = to_nvp6188(sd); + return sprintf(buf, "%d\n", nvp6188->detect_status); } +static ssize_t nvp6188_debug_func(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct nvp6188 *nvp6188 = to_nvp6188(sd); + + nvp6188->disable_dump_register = (nvp6188->disable_dump_register) ? false : true; + return sprintf(buf, "switch disable_dump_register(%d)\n", nvp6188->disable_dump_register); +} + static DEVICE_ATTR(hotplug_status, S_IRUSR, show_hotplug_status, NULL); +static DEVICE_ATTR(nvp6188_debug, S_IRUSR, nvp6188_debug_func, NULL); static struct attribute *dev_attrs[] = { &dev_attr_hotplug_status.attr, + &dev_attr_nvp6188_debug.attr, NULL, }; + static struct attribute_group dev_attr_grp = { .attrs = dev_attrs, }; static __maybe_unused const struct regval common_setting_756M_regs[] = { - { 0xff, 0x00 }, - { 0x80, 0x0f }, - { 0x00, 0x10 }, - { 0x01, 0x10 }, - { 0x02, 0x10 }, - { 0x03, 0x10 }, - { 0x22, 0x0b }, - { 0x23, 0x41 }, - { 0x26, 0x0b }, - { 0x27, 0x41 }, - { 0x2a, 0x0b }, - { 0x2b, 0x41 }, - { 0x2e, 0x0b }, - { 0x2f, 0x41 }, + {0xff, 0x00}, + {0x80, 0x0f}, + {0x00, 0x10}, + {0x01, 0x10}, + {0x02, 0x10}, + {0x03, 0x10}, + {0x22, 0x0b}, + {0x23, 0x41}, + {0x26, 0x0b}, + {0x27, 0x41}, + {0x2a, 0x0b}, + {0x2b, 0x41}, + {0x2e, 0x0b}, + {0x2f, 0x41}, - { 0xff, 0x01 }, - { 0x98, 0x30 }, - { 0xed, 0x00 }, + {0xff, 0x01}, + {0x98, 0x30}, + {0xed, 0x00}, - { 0xff, 0x05+0 }, - { 0x00, 0xd0 }, - { 0x01, 0x22 }, - { 0x47, 0xee }, - { 0x50, 0xc6 }, - { 0x57, 0x00 }, - { 0x58, 0x77 }, - { 0x5b, 0x41 }, - { 0x5c, 0x78 }, - { 0xB8, 0xB8 }, + {0xff, 0x05 + 0}, + {0x00, 0xd0}, + {0x01, 0x22}, + {0x47, 0xee}, + {0x50, 0xc6}, + {0x57, 0x00}, + {0x58, 0x77}, + {0x5b, 0x41}, + {0x5c, 0x78}, + {0xB8, 0xB8}, - { 0xff, 0x05+1 }, - { 0x00, 0xd0 }, - { 0x01, 0x22 }, - { 0x47, 0xee }, - { 0x50, 0xc6 }, - { 0x57, 0x00 }, - { 0x58, 0x77 }, - { 0x5b, 0x41 }, - { 0x5c, 0x78 }, - { 0xB8, 0xB8 }, + {0xff, 0x05 + 1}, + {0x00, 0xd0}, + {0x01, 0x22}, + {0x47, 0xee}, + {0x50, 0xc6}, + {0x57, 0x00}, + {0x58, 0x77}, + {0x5b, 0x41}, + {0x5c, 0x78}, + {0xB8, 0xB8}, - { 0xff, 0x05+2 }, - { 0x00, 0xd0 }, - { 0x01, 0x22 }, - { 0x47, 0xee }, - { 0x50, 0xc6 }, - { 0x57, 0x00 }, - { 0x58, 0x77 }, - { 0x5b, 0x41 }, - { 0x5c, 0x78 }, - { 0xB8, 0xB8 }, + {0xff, 0x05 + 2}, + {0x00, 0xd0}, + {0x01, 0x22}, + {0x47, 0xee}, + {0x50, 0xc6}, + {0x57, 0x00}, + {0x58, 0x77}, + {0x5b, 0x41}, + {0x5c, 0x78}, + {0xB8, 0xB8}, - { 0xff, 0x05+3 }, - { 0x00, 0xd0 }, - { 0x01, 0x22 }, - { 0x47, 0xee }, - { 0x50, 0xc6 }, - { 0x57, 0x00 }, - { 0x58, 0x77 }, - { 0x5b, 0x41 }, - { 0x5c, 0x78 }, - { 0xB8, 0xB8 }, + {0xff, 0x05 + 3}, + {0x00, 0xd0}, + {0x01, 0x22}, + {0x47, 0xee}, + {0x50, 0xc6}, + {0x57, 0x00}, + {0x58, 0x77}, + {0x5b, 0x41}, + {0x5c, 0x78}, + {0xB8, 0xB8}, - { 0xff, 0x09 }, - { 0x50, 0x30 }, - { 0x51, 0x6f }, - { 0x52, 0x67 }, - { 0x53, 0x48 }, - { 0x54, 0x30 }, - { 0x55, 0x6f }, - { 0x56, 0x67 }, - { 0x57, 0x48 }, - { 0x58, 0x30 }, - { 0x59, 0x6f }, - { 0x5a, 0x67 }, - { 0x5b, 0x48 }, - { 0x5c, 0x30 }, - { 0x5d, 0x6f }, - { 0x5e, 0x67 }, - { 0x5f, 0x48 }, + {0xff, 0x09}, + {0x50, 0x30}, + {0x51, 0x6f}, + {0x52, 0x67}, + {0x53, 0x48}, + {0x54, 0x30}, + {0x55, 0x6f}, + {0x56, 0x67}, + {0x57, 0x48}, + {0x58, 0x30}, + {0x59, 0x6f}, + {0x5a, 0x67}, + {0x5b, 0x48}, + {0x5c, 0x30}, + {0x5d, 0x6f}, + {0x5e, 0x67}, + {0x5f, 0x48}, - { 0xff, 0x0a }, - { 0x25, 0x10 }, - { 0x27, 0x1e }, - { 0x30, 0xac }, - { 0x31, 0x78 }, - { 0x32, 0x17 }, - { 0x33, 0xc1 }, - { 0x34, 0x40 }, - { 0x35, 0x00 }, - { 0x36, 0xc3 }, - { 0x37, 0x0a }, - { 0x38, 0x00 }, - { 0x39, 0x02 }, - { 0x3a, 0x00 }, - { 0x3b, 0xb2 }, - { 0xa5, 0x10 }, - { 0xa7, 0x1e }, - { 0xb0, 0xac }, - { 0xb1, 0x78 }, - { 0xb2, 0x17 }, - { 0xb3, 0xc1 }, - { 0xb4, 0x40 }, - { 0xb5, 0x00 }, - { 0xb6, 0xc3 }, - { 0xb7, 0x0a }, - { 0xb8, 0x00 }, - { 0xb9, 0x02 }, - { 0xba, 0x00 }, - { 0xbb, 0xb2 }, - { 0xff, 0x0b }, - { 0x25, 0x10 }, - { 0x27, 0x1e }, - { 0x30, 0xac }, - { 0x31, 0x78 }, - { 0x32, 0x17 }, - { 0x33, 0xc1 }, - { 0x34, 0x40 }, - { 0x35, 0x00 }, - { 0x36, 0xc3 }, - { 0x37, 0x0a }, - { 0x38, 0x00 }, - { 0x39, 0x02 }, - { 0x3a, 0x00 }, - { 0x3b, 0xb2 }, - { 0xa5, 0x10 }, - { 0xa7, 0x1e }, - { 0xb0, 0xac }, - { 0xb1, 0x78 }, - { 0xb2, 0x17 }, - { 0xb3, 0xc1 }, - { 0xb4, 0x40 }, - { 0xb5, 0x00 }, - { 0xb6, 0xc3 }, - { 0xb7, 0x0a }, - { 0xb8, 0x00 }, - { 0xb9, 0x02 }, - { 0xba, 0x00 }, - { 0xbb, 0xb2 }, + {0xff, 0x0a}, + {0x25, 0x10}, + {0x27, 0x1e}, + {0x30, 0xac}, + {0x31, 0x78}, + {0x32, 0x17}, + {0x33, 0xc1}, + {0x34, 0x40}, + {0x35, 0x00}, + {0x36, 0xc3}, + {0x37, 0x0a}, + {0x38, 0x00}, + {0x39, 0x02}, + {0x3a, 0x00}, + {0x3b, 0xb2}, + {0xa5, 0x10}, + {0xa7, 0x1e}, + {0xb0, 0xac}, + {0xb1, 0x78}, + {0xb2, 0x17}, + {0xb3, 0xc1}, + {0xb4, 0x40}, + {0xb5, 0x00}, + {0xb6, 0xc3}, + {0xb7, 0x0a}, + {0xb8, 0x00}, + {0xb9, 0x02}, + {0xba, 0x00}, + {0xbb, 0xb2}, + {0xff, 0x0b}, + {0x25, 0x10}, + {0x27, 0x1e}, + {0x30, 0xac}, + {0x31, 0x78}, + {0x32, 0x17}, + {0x33, 0xc1}, + {0x34, 0x40}, + {0x35, 0x00}, + {0x36, 0xc3}, + {0x37, 0x0a}, + {0x38, 0x00}, + {0x39, 0x02}, + {0x3a, 0x00}, + {0x3b, 0xb2}, + {0xa5, 0x10}, + {0xa7, 0x1e}, + {0xb0, 0xac}, + {0xb1, 0x78}, + {0xb2, 0x17}, + {0xb3, 0xc1}, + {0xb4, 0x40}, + {0xb5, 0x00}, + {0xb6, 0xc3}, + {0xb7, 0x0a}, + {0xb8, 0x00}, + {0xb9, 0x02}, + {0xba, 0x00}, + {0xbb, 0xb2}, - { 0xff, 0x13 }, - { 0x05, 0xa0 }, - { 0x31, 0xff }, - { 0x07, 0x47 }, - { 0x12, 0x04 }, - { 0x1e, 0x1f }, - { 0x1f, 0x27 }, - { 0x2e, 0x10 }, - { 0x2f, 0xc8 }, - { 0x31, 0xff }, - { 0x32, 0x00 }, - { 0x33, 0x00 }, - { 0x72, 0x05 }, - { 0x7a, 0xf0 }, - { 0xff, _MAR_BANK_ }, - { 0x10, 0xff }, - { 0x11, 0xff }, + {0xff, 0x13}, + {0x05, 0xa0}, + {0x31, 0xff}, + {0x07, 0x47}, + {0x12, 0x04}, + {0x1e, 0x1f}, + {0x1f, 0x27}, + {0x2e, 0x10}, + {0x2f, 0xc8}, + {0x31, 0xff}, + {0x32, 0x00}, + {0x33, 0x00}, + {0x72, 0x05}, + {0x7a, 0xf0}, + {0xff, _MAR_BANK_}, + {0x10, 0xff}, + {0x11, 0xff}, - { 0x30, 0x0f }, - { 0x32, 0x92 }, - { 0x34, 0xcd }, - { 0x36, 0x04 }, - { 0x38, 0x58 }, + {0x30, 0x0f}, + {0x32, 0x92}, + {0x34, 0xcd}, + {0x36, 0x04}, + {0x38, 0x58}, - { 0x3c, 0x01 }, - { 0x3d, 0x11 }, - { 0x3e, 0x11 }, - { 0x45, 0x60 }, - { 0x46, 0x49 }, + {0x3c, 0x01}, + {0x3d, 0x11}, + {0x3e, 0x11}, + {0x45, 0x60}, + {0x46, 0x49}, - { 0xff, _MTX_BANK_ }, - { 0xe9, 0x03 }, - { 0x03, 0x02 }, - { 0x01, 0xe0 }, - { 0x00, 0x7d }, - { 0x01, 0xe0 }, - { 0x02, 0xa0 }, - { 0x20, 0x1e }, - { 0x20, 0x1f }, + {0xff, _MTX_BANK_}, + {0xe9, 0x03}, + {0x03, 0x02}, + {0x01, 0xe0}, + {0x00, 0x7d}, + {0x01, 0xe0}, + {0x02, 0xa0}, + {0x20, 0x1e}, + {0x20, 0x1f}, - { 0x04, 0x38 }, - { 0x45, 0xc4 }, - { 0x46, 0x01 }, - { 0x47, 0x1b }, - { 0x48, 0x08 }, - { 0x65, 0xc4 }, - { 0x66, 0x01 }, - { 0x67, 0x1b }, - { 0x68, 0x08 }, - { 0x85, 0xc4 }, - { 0x86, 0x01 }, - { 0x87, 0x1b }, - { 0x88, 0x08 }, - { 0xa5, 0xc4 }, - { 0xa6, 0x01 }, - { 0xa7, 0x1b }, - { 0xa8, 0x08 }, - { 0xc5, 0xc4 }, - { 0xc6, 0x01 }, - { 0xc7, 0x1b }, - { 0xc8, 0x08 }, - { 0xeb, 0x8d }, + {0x04, 0x38}, + {0x45, 0xc4}, + {0x46, 0x01}, + {0x47, 0x1b}, + {0x48, 0x08}, + {0x65, 0xc4}, + {0x66, 0x01}, + {0x67, 0x1b}, + {0x68, 0x08}, + {0x85, 0xc4}, + {0x86, 0x01}, + {0x87, 0x1b}, + {0x88, 0x08}, + {0xa5, 0xc4}, + {0xa6, 0x01}, + {0xa7, 0x1b}, + {0xa8, 0x08}, + {0xc5, 0xc4}, + {0xc6, 0x01}, + {0xc7, 0x1b}, + {0xc8, 0x08}, + {0xeb, 0x8d}, - { 0xff, _MAR_BANK_ }, - { 0x00, 0xff }, - { 0x40, 0x01 }, - { 0x40, 0x00 }, - { 0xff, 0x01 }, - { 0x97, 0x00 }, - { 0x97, 0x0f }, + {0xff, _MAR_BANK_}, + {0x00, 0xff}, + {0x40, 0x01}, + {0x40, 0x00}, + {0xff, 0x01}, + {0x97, 0x00}, + {0x97, 0x0f}, - { 0xff, 0x00 }, //test pattern - { 0x78, 0xba }, - { 0x79, 0xac }, - { 0xff, 0x05 }, - { 0x2c, 0x08 }, - { 0x6a, 0x80 }, - { 0xff, 0x06 }, - { 0x2c, 0x08 }, - { 0x6a, 0x80 }, - { 0xff, 0x07 }, - { 0x2c, 0x08 }, - { 0x6a, 0x80 }, - { 0xff, 0x08 }, - { 0x2c, 0x08 }, - { 0x6a, 0x80 }, + {0xff, 0x00}, //test pattern + {0x78, 0xba}, + {0x79, 0xac}, + {0xff, 0x05}, + {0x2c, 0x08}, + {0x6a, 0x80}, + {0xff, 0x06}, + {0x2c, 0x08}, + {0x6a, 0x80}, + {0xff, 0x07}, + {0x2c, 0x08}, + {0x6a, 0x80}, + {0xff, 0x08}, + {0x2c, 0x08}, + {0x6a, 0x80}, }; static __maybe_unused const struct regval common_setting_1458M_regs[] = { - { 0xff, 0x00 }, - { 0x80, 0x0f }, - { 0x00, 0x10 }, - { 0x01, 0x10 }, - { 0x02, 0x10 }, - { 0x03, 0x10 }, - { 0x22, 0x0b }, - { 0x23, 0x41 }, - { 0x26, 0x0b }, - { 0x27, 0x41 }, - { 0x2a, 0x0b }, - { 0x2b, 0x41 }, - { 0x2e, 0x0b }, - { 0x2f, 0x41 }, + {0xff, 0x01}, + {0x80, 0x40}, + {0x98, 0x30}, + {0x7a, 0x00}, + {0xff, _MTX_BANK_}, + {0xe9, 0x03}, + {0x03, 0x02}, + {0x04, 0x6c}, + {0x08, 0x4f}, + {0x01, 0xe4}, + {0x00, 0x7d}, + {0x01, 0xe0}, + {0x20, 0x1e}, + {0x20, 0x1f}, + {0xeb, 0x8d}, + {0x45, 0xcd}, + {0x46, 0x42}, + {0x47, 0x36}, + {0x48, 0x0f}, + {0x65, 0xcd}, + {0x66, 0x42}, + {0x67, 0x0e}, + {0x68, 0x0f}, + {0x85, 0xcd}, + {0x86, 0x42}, + {0x87, 0x0e}, + {0x88, 0x0f}, + {0xa5, 0xcd}, + {0xa6, 0x42}, + {0xa7, 0x0e}, + {0xa8, 0x0f}, + {0xc5, 0xcd}, + {0xc6, 0x42}, + {0xc7, 0x0e}, + {0xc8, 0x0f}, - { 0xff, 0x01 }, - { 0x98, 0x30 }, - { 0xed, 0x00 }, + {0xff, 0x05 + 0}, + {0x01, 0x62}, + {0x05, 0x04}, + {0x08, 0x55}, + {0x1b, 0x08}, + {0x25, 0xdc}, + {0x28, 0x80}, + {0x2f, 0x00}, + {0x30, 0xe0}, + {0x31, 0x43}, + {0x32, 0xa2}, + {0x57, 0x00}, + {0x58, 0x77}, + {0x5b, 0x41}, + {0x5c, 0x78}, + {0x5f, 0x00}, + {0x7b, 0x11}, + {0x7c, 0x01}, + {0x7d, 0x80}, + {0x80, 0x00}, + {0x90, 0x01}, + {0xa9, 0x00}, + {0xb5, 0x00}, + {0xb9, 0x72}, + {0xd1, 0x00}, + {0xd5, 0x80}, - { 0xff, 0x05+0 }, - { 0x00, 0xd0 }, - { 0x01, 0x22 }, - { 0x47, 0xee }, - { 0x50, 0xc6 }, - { 0x57, 0x00 }, - { 0x58, 0x77 }, - { 0x5b, 0x41 }, - { 0x5c, 0x78 }, - { 0xB8, 0xB8 }, + {0xff, 0x05 + 1}, + {0x01, 0x62}, + {0x05, 0x04}, + {0x08, 0x55}, + {0x1b, 0x08}, + {0x25, 0xdc}, + {0x28, 0x80}, + {0x2f, 0x00}, + {0x30, 0xe0}, + {0x31, 0x43}, + {0x32, 0xa2}, + {0x57, 0x00}, + {0x58, 0x77}, + {0x5b, 0x41}, + {0x5c, 0x78}, + {0x5f, 0x00}, + {0x7b, 0x11}, + {0x7c, 0x01}, + {0x7d, 0x80}, + {0x80, 0x00}, + {0x90, 0x01}, + {0xa9, 0x00}, + {0xb5, 0x00}, + {0xb9, 0x72}, + {0xd1, 0x00}, + {0xd5, 0x80}, - { 0xff, 0x05+1 }, - { 0x00, 0xd0 }, - { 0x01, 0x22 }, - { 0x47, 0xee }, - { 0x50, 0xc6 }, - { 0x57, 0x00 }, - { 0x58, 0x77 }, - { 0x5b, 0x41 }, - { 0x5c, 0x78 }, - { 0xB8, 0xB8 }, + {0xff, 0x05 + 2}, + {0x01, 0x62}, + {0x05, 0x04}, + {0x08, 0x55}, + {0x1b, 0x08}, + {0x25, 0xdc}, + {0x28, 0x80}, + {0x2f, 0x00}, + {0x30, 0xe0}, + {0x31, 0x43}, + {0x32, 0xa2}, + {0x57, 0x00}, + {0x58, 0x77}, + {0x5b, 0x41}, + {0x5c, 0x78}, + {0x5f, 0x00}, + {0x7b, 0x11}, + {0x7c, 0x01}, + {0x7d, 0x80}, + {0x80, 0x00}, + {0x90, 0x01}, + {0xa9, 0x00}, + {0xb5, 0x00}, + {0xb9, 0x72}, + {0xd1, 0x00}, + {0xd5, 0x80}, - { 0xff, 0x05+2 }, - { 0x00, 0xd0 }, - { 0x01, 0x22 }, - { 0x47, 0xee }, - { 0x50, 0xc6 }, - { 0x57, 0x00 }, - { 0x58, 0x77 }, - { 0x5b, 0x41 }, - { 0x5c, 0x78 }, - { 0xB8, 0xB8 }, + {0xff, 0x05 + 3}, + {0x01, 0x62}, + {0x05, 0x04}, + {0x08, 0x55}, + {0x1b, 0x08}, + {0x25, 0xdc}, + {0x28, 0x80}, + {0x2f, 0x00}, + {0x30, 0xe0}, + {0x31, 0x43}, + {0x32, 0xa2}, + {0x57, 0x00}, + {0x58, 0x77}, + {0x5b, 0x41}, + {0x5c, 0x78}, + {0x5f, 0x00}, + {0x7b, 0x11}, + {0x7c, 0x01}, + {0x7d, 0x80}, + {0x80, 0x00}, + {0x90, 0x01}, + {0xa9, 0x00}, + {0xb5, 0x00}, + {0xb9, 0x72}, + {0xd1, 0x00}, + {0xd5, 0x80}, - { 0xff, 0x05+3 }, - { 0x00, 0xd0 }, - { 0x01, 0x22 }, - { 0x47, 0xee }, - { 0x50, 0xc6 }, - { 0x57, 0x00 }, - { 0x58, 0x77 }, - { 0x5b, 0x41 }, - { 0x5c, 0x78 }, - { 0xB8, 0xB8 }, + {0xff, 0x09}, + {0x50, 0x30}, + {0x51, 0x6f}, + {0x52, 0x67}, + {0x53, 0x48}, + {0x54, 0x30}, + {0x55, 0x6f}, + {0x56, 0x67}, + {0x57, 0x48}, + {0x58, 0x30}, + {0x59, 0x6f}, + {0x5a, 0x67}, + {0x5b, 0x48}, + {0x5c, 0x30}, + {0x5d, 0x6f}, + {0x5e, 0x67}, + {0x5f, 0x48}, + {0x96, 0x03}, + {0xb6, 0x03}, + {0xd6, 0x03}, + {0xf6, 0x03}, - { 0xff, 0x09 }, - { 0x50, 0x30 }, - { 0x51, 0x6f }, - { 0x52, 0x67 }, - { 0x53, 0x48 }, - { 0x54, 0x30 }, - { 0x55, 0x6f }, - { 0x56, 0x67 }, - { 0x57, 0x48 }, - { 0x58, 0x30 }, - { 0x59, 0x6f }, - { 0x5a, 0x67 }, - { 0x5b, 0x48 }, - { 0x5c, 0x30 }, - { 0x5d, 0x6f }, - { 0x5e, 0x67 }, - { 0x5f, 0x48 }, + {0xff, 0x0a}, + {0x25, 0x10}, + {0x27, 0x1e}, + {0x30, 0xac}, + {0x31, 0x78}, + {0x32, 0x17}, + {0x33, 0xc1}, + {0x34, 0x40}, + {0x35, 0x00}, + {0x36, 0xc3}, + {0x37, 0x0a}, + {0x38, 0x00}, + {0x39, 0x02}, + {0x3a, 0x00}, + {0x3b, 0xb2}, + {0xa5, 0x10}, + {0xa7, 0x1e}, + {0xb0, 0xac}, + {0xb1, 0x78}, + {0xb2, 0x17}, + {0xb3, 0xc1}, + {0xb4, 0x40}, + {0xb5, 0x00}, + {0xb6, 0xc3}, + {0xb7, 0x0a}, + {0xb8, 0x00}, + {0xb9, 0x02}, + {0xba, 0x00}, + {0xbb, 0xb2}, + {0xff, 0x0b}, + {0x25, 0x10}, + {0x27, 0x1e}, + {0x30, 0xac}, + {0x31, 0x78}, + {0x32, 0x17}, + {0x33, 0xc1}, + {0x34, 0x40}, + {0x35, 0x00}, + {0x36, 0xc3}, + {0x37, 0x0a}, + {0x38, 0x00}, + {0x39, 0x02}, + {0x3a, 0x00}, + {0x3b, 0xb2}, + {0xa5, 0x10}, + {0xa7, 0x1e}, + {0xb0, 0xac}, + {0xb1, 0x78}, + {0xb2, 0x17}, + {0xb3, 0xc1}, + {0xb4, 0x40}, + {0xb5, 0x00}, + {0xb6, 0xc3}, + {0xb7, 0x0a}, + {0xb8, 0x00}, + {0xb9, 0x02}, + {0xba, 0x00}, + {0xbb, 0xb2}, - { 0xff, 0x0a }, - { 0x25, 0x10 }, - { 0x27, 0x1e }, - { 0x30, 0xac }, - { 0x31, 0x78 }, - { 0x32, 0x17 }, - { 0x33, 0xc1 }, - { 0x34, 0x40 }, - { 0x35, 0x00 }, - { 0x36, 0xc3 }, - { 0x37, 0x0a }, - { 0x38, 0x00 }, - { 0x39, 0x02 }, - { 0x3a, 0x00 }, - { 0x3b, 0xb2 }, - { 0xa5, 0x10 }, - { 0xa7, 0x1e }, - { 0xb0, 0xac }, - { 0xb1, 0x78 }, - { 0xb2, 0x17 }, - { 0xb3, 0xc1 }, - { 0xb4, 0x40 }, - { 0xb5, 0x00 }, - { 0xb6, 0xc3 }, - { 0xb7, 0x0a }, - { 0xb8, 0x00 }, - { 0xb9, 0x02 }, - { 0xba, 0x00 }, - { 0xbb, 0xb2 }, - { 0xff, 0x0b }, - { 0x25, 0x10 }, - { 0x27, 0x1e }, - { 0x30, 0xac }, - { 0x31, 0x78 }, - { 0x32, 0x17 }, - { 0x33, 0xc1 }, - { 0x34, 0x40 }, - { 0x35, 0x00 }, - { 0x36, 0xc3 }, - { 0x37, 0x0a }, - { 0x38, 0x00 }, - { 0x39, 0x02 }, - { 0x3a, 0x00 }, - { 0x3b, 0xb2 }, - { 0xa5, 0x10 }, - { 0xa7, 0x1e }, - { 0xb0, 0xac }, - { 0xb1, 0x78 }, - { 0xb2, 0x17 }, - { 0xb3, 0xc1 }, - { 0xb4, 0x40 }, - { 0xb5, 0x00 }, - { 0xb6, 0xc3 }, - { 0xb7, 0x0a }, - { 0xb8, 0x00 }, - { 0xb9, 0x02 }, - { 0xba, 0x00 }, - { 0xbb, 0xb2 }, + {0xff, 0x00}, + {0x00, 0x10}, + {0x01, 0x10}, + {0x02, 0x10}, + {0x03, 0x10}, + {0x22, 0x0b}, + {0x23, 0x41}, + {0x26, 0x0b}, + {0x27, 0x41}, + {0x2a, 0x0b}, + {0x2b, 0x41}, + {0x2e, 0x0b}, + {0x2f, 0x41}, - { 0xff, 0x13 }, - { 0x05, 0xa0 }, - { 0x31, 0xff }, - { 0x07, 0x47 }, - { 0x12, 0x04 }, - { 0x1e, 0x1f }, - { 0x1f, 0x27 }, - { 0x2e, 0x10 }, - { 0x2f, 0xc8 }, - { 0x31, 0xff }, - { 0x32, 0x00 }, - { 0x33, 0x00 }, - { 0x72, 0x05 }, - { 0x7a, 0xf0 }, - { 0xff, _MAR_BANK_ }, - { 0x10, 0xff }, - { 0x11, 0xff }, + {0xff, 0x13}, + {0x05, 0xa0}, + {0x07, 0x47}, + {0x12, 0x04}, + {0x1e, 0x1f}, + {0x1f, 0x27}, + {0x2e, 0x10}, + {0x2f, 0xc8}, + {0x30, 0x00}, + {0x31, 0xff}, + {0x32, 0x00}, + {0x33, 0x00}, + {0x3a, 0xff}, + {0x3b, 0xff}, + {0x3c, 0xff}, + {0x3d, 0xff}, + {0x3e, 0xff}, + {0x3f, 0x0f}, + {0x70, 0x00}, + {0x72, 0x05}, + {0x7A, 0xf0}, + {0x74, 0x00}, + {0x76, 0x00}, + {0x78, 0x00}, + {0x75, 0xff}, + {0x77, 0xff}, + {0x79, 0xff}, + {0x01, 0x0c}, + {0x73, 0x23}, + {0xff, _MAR_BANK_}, + {0x40, 0x01}, + {0x10, 0xff}, + {0x11, 0xff}, + {0x46, 0x49}, + {0x45, 0x60}, + {0x30, 0x0f}, + {0x32, 0xff}, + {0x34, 0xcd}, + {0x36, 0x04}, + {0x38, 0xff}, + {0x07, 0x00}, + {0x2a, 0x0a}, + {0x3d, 0x11}, + {0x3e, 0x11}, + {0x3c, 0x01}, + {0x1a, 0x92}, + {0x1b, 0x00}, + {0x1c, 0x00}, + {0x05, 0x00}, + {0x06, 0x00}, + {0x0d, 0x01}, + {0x00, 0x00},//mipi not enabled first + {0x40, 0x00}, - { 0x30, 0x0f }, - { 0x32, 0xff }, - { 0x34, 0xcd }, - { 0x36, 0x04 }, - { 0x38, 0xff }, - { 0x3c, 0x01 }, - { 0x3d, 0x11 }, - { 0x3e, 0x11 }, - { 0x45, 0x60 }, - { 0x46, 0x49 }, + {0xff, 0x01}, + //{ 0x82, 0x12 }, + {0x80, 0x61}, + {0x80, 0x60}, + {0xa0, 0x20}, + {0xa1, 0x20}, + {0xa2, 0x20}, + {0xa3, 0x20}, + {0xed, 0x00}, - { 0xff, _MTX_BANK_ }, - { 0xe9, 0x03 }, - { 0x03, 0x02 }, - { 0x01, 0xe4 }, - { 0x00, 0x7d }, - { 0x01, 0xe0 }, - { 0x02, 0xa0 }, - { 0x20, 0x1e }, - { 0x20, 0x1f }, - { 0x04, 0x6c }, - { 0x45, 0xcd }, - { 0x46, 0x42 }, - { 0x47, 0x36 }, - { 0x48, 0x0f }, - { 0x65, 0xcd }, - { 0x66, 0x42 }, - { 0x67, 0x0e }, - { 0x68, 0x0f }, - { 0x85, 0xcd }, - { 0x86, 0x42 }, - { 0x87, 0x0e }, - { 0x88, 0x0f }, - { 0xa5, 0xcd }, - { 0xa6, 0x42 }, - { 0xa7, 0x0e }, - { 0xa8, 0x0f }, - { 0xc5, 0xcd }, - { 0xc6, 0x42 }, - { 0xc7, 0x0e }, - { 0xc8, 0x0f }, - { 0xeb, 0x8d }, + {0xff, 0x00}, + {0x80, 0x0f}, + {0x81, 0x02}, + {0x82, 0x02}, + {0x83, 0x02}, + {0x84, 0x02}, + {0x64, 0x01}, + {0x65, 0x01}, + {0x66, 0x01}, + {0x67, 0x01}, + {0x5c, 0x80}, + {0x5d, 0x80}, + {0x5e, 0x80}, + {0x5f, 0x80}, + {0xff, 0x01}, + {0x84, 0x02}, + {0x85, 0x02}, + {0x86, 0x02}, + {0x87, 0x02}, + {0x8c, 0x40}, + {0x8d, 0x40}, + {0x8e, 0x40}, + {0x8f, 0x40}, + {0xff, 0x20}, + {0x01, 0x00}, + {0x12, 0xc0}, + {0x13, 0x03}, + {0x14, 0xc0}, + {0x15, 0x03}, + {0x16, 0xc0}, + {0x17, 0x03}, + {0x18, 0xc0}, + {0x19, 0x03}, + {0xff, 0x01}, + {0x97, 0xf0}, + {0x97, 0x0f}, - { 0xff, _MAR_BANK_ }, - { 0x00, 0xff }, - { 0x40, 0x01 }, - { 0x40, 0x00 }, - { 0xff, 0x01 }, - { 0x97, 0x00 }, - { 0x97, 0x0f }, - - { 0xff, 0x00 }, //test pattern - { 0x78, 0xba }, - { 0x79, 0xac }, - { 0xff, 0x05 }, - { 0x2c, 0x08 }, - { 0x6a, 0x80 }, - { 0xff, 0x06 }, - { 0x2c, 0x08 }, - { 0x6a, 0x80 }, - { 0xff, 0x07 }, - { 0x2c, 0x08 }, - { 0x6a, 0x80 }, - { 0xff, 0x08 }, - { 0x2c, 0x08 }, - { 0x6a, 0x80 }, -}; - -static __maybe_unused const struct regval auto_detect_regs[] = { - { 0xFF, 0x13 }, - { 0x30, 0x7f }, - { 0x70, 0xf0 }, - - { 0xFF, 0x00 }, - { 0x00, 0x18 }, - { 0x01, 0x18 }, - { 0x02, 0x18 }, - { 0x03, 0x18 }, - - { 0x00, 0x10 }, - { 0x01, 0x10 }, - { 0x02, 0x10 }, - { 0x03, 0x10 }, + {0xff, 0x00}, //test pattern + {0x78, 0x88}, + {0x79, 0x88}, + {0xff, 0x05}, + {0x2c, 0x08}, + {0x6a, 0x00}, + {0xff, 0x06}, + {0x2c, 0x08}, + {0x6a, 0x00}, + {0xff, 0x07}, + {0x2c, 0x08}, + {0x6a, 0x00}, + {0xff, 0x08}, + {0x2c, 0x08}, + {0x6a, 0x00}, }; static struct nvp6188_mode supported_modes[] = { @@ -796,123 +931,38 @@ static int nvp6188_read_reg(struct i2c_client *client, u8 reg, u8 *val) return ret; } +static int nv6188_read_htotal(struct nvp6188 *nvp6188, unsigned char ch) +{ + int ch_htotal = 0; + unsigned char val_5xf2 = 0, val_5xf3 = 0; + struct i2c_client *client = nvp6188->client; + + nvp6188_write_reg(client, 0xff, 0x05 + ch); + nvp6188_read_reg(client, 0xf2, &val_5xf2); + nvp6188_read_reg(client, 0xf3, &val_5xf3); + ch_htotal = ((val_5xf3 << 8) | val_5xf2); + + return ch_htotal; +} + static unsigned char nv6188_read_vfc(struct nvp6188 *nvp6188, unsigned char ch) { unsigned char ch_vfc = 0xff; struct i2c_client *client = nvp6188->client; + nvp6188_write_reg(client, 0xff, 0x05 + ch); nvp6188_read_reg(client, 0xf0, &ch_vfc); + return ch_vfc; } -static __maybe_unused int nvp6188_read_all_vfc(struct nvp6188 *nvp6188, - u8 *ch_vfc) -{ - int ret = 0; - int check_cnt = 0, ch = 0; - struct i2c_client *client = nvp6188->client; - - ret = nvp6188_write_array(client, - auto_detect_regs, ARRAY_SIZE(auto_detect_regs)); - if (ret) { - dev_err(&client->dev, "write auto_detect_regs faild %d", ret); - } - - ret = -1; - while ((check_cnt++) < 50) { - for (ch = 0; ch < 4; ch++) { - ch_vfc[ch] = nv6188_read_vfc(nvp6188, ch); - } - if (ch_vfc[0] != 0xff || ch_vfc[1] != 0xff || - ch_vfc[2] != 0xff || ch_vfc[3] != 0xff) { - ret = 0; - if (ch == 3) { - dev_dbg(&client->dev, "try check cnt %d",check_cnt); - break; - } - } else { - usleep_range(20 * 1000, 40 * 1000); - } - } - - if (ret) { - dev_err(&client->dev, "read vfc faild %d", ret); - } else { - dev_dbg(&client->dev, "read vfc 0x%2x 0x%2x 0x%2x 0x%2x", - ch_vfc[0], ch_vfc[1], ch_vfc[2], ch_vfc[3]); - } - return ret; -} - -static __maybe_unused int nvp6188_auto_detect_fmt(struct nvp6188 *nvp6188) -{ - int ret = 0; - int ch = 0; - unsigned char ch_vfc[4] = { 0xff, 0xff, 0xff, 0xff }; - unsigned char val_13x70 = 0, val_13x71 = 0; - struct i2c_client *client = nvp6188->client; - - if (nvp6188_read_all_vfc(nvp6188, ch_vfc)) - return -1; - - for (ch = 0; ch < 4; ch++) { - nvp6188_write_reg(client, 0xFF, 0x13); - nvp6188_read_reg(client, 0x70, &val_13x70); - val_13x70 |= (0x01 << ch); - nvp6188_write_reg(client, 0x70, val_13x70); - nvp6188_read_reg(client, 0x71, &val_13x71); - val_13x71 |= (0x01 << ch); - nvp6188_write_reg(client, 0x71, val_13x71); - switch(ch_vfc[ch]) { - case NVP_RESO_960H_NSTC_VALUE: - dev_dbg(&client->dev, "channel %d det 960h nstc", ch); - nvp6188->cur_mode.channel_reso[ch] = NVP_RESO_960H_NSTC; - break; - case NVP_RESO_960H_PAL_VALUE: - dev_dbg(&client->dev, "channel %d det 960h pal", ch); - nvp6188->cur_mode.channel_reso[ch] = NVP_RESO_960H_PAL; - break; - case NVP_RESO_720P_NSTC_VALUE: - dev_dbg(&client->dev, "channel %d det 720p nstc", ch); - nvp6188->cur_mode.channel_reso[ch] = NVP_RESO_720P_NSTC; - break; - case NVP_RESO_720P_PAL_VALUE: - dev_dbg(&client->dev, "channel %d det 720p pal", ch); - nvp6188->cur_mode.channel_reso[ch] = NVP_RESO_720P_PAL; - break; - case NVP_RESO_1080P_NSTC_VALUE: - dev_dbg(&client->dev, "channel %d det 1080p nstc", ch); - nvp6188->cur_mode.channel_reso[ch] = NVP_RESO_1080P_NSTC; - break; - case NVP_RESO_1080P_PAL_VALUE: - dev_dbg(&client->dev, "channel %d det 1080p pal", ch); - nvp6188->cur_mode.channel_reso[ch] = NVP_RESO_1080P_PAL; - break; - case NVP_RESO_960P_NSTC_VALUE: - dev_dbg(&client->dev, "channel %d det 960p nstc", ch); - nvp6188->cur_mode.channel_reso[ch] = NVP_RESO_960P_NSTC; - break; - case NVP_RESO_960P_PAL_VALUE: - dev_dbg(&client->dev, "channel %d det 960p pal", ch); - nvp6188->cur_mode.channel_reso[ch] = NVP_RESO_960P_PAL; - break; - default: - dev_err(&client->dev, "channel %d not detect, def 1080p pal\n", ch); - nvp6188->cur_mode.channel_reso[ch] = NVP_RESO_1080P_PAL; - break; - } - } - - return ret; -} - static __maybe_unused int nvp6188_auto_detect_hotplug(struct nvp6188 *nvp6188) { int ret = 0; struct i2c_client *client = nvp6188->client; nvp6188_write_reg(client, 0xff, 0x00); nvp6188_read_reg(client, 0xa8, &nvp6188->detect_status); - nvp6188->detect_status = ~nvp6188->detect_status; + //nvp6188->detect_status = ~nvp6188->detect_status; return ret; } @@ -975,8 +1025,8 @@ static int nvp6188_set_fmt(struct v4l2_subdev *sd, __v4l2_ctrl_s_ctrl(nvp6188->link_freq, mode->mipi_freq_idx); pixel_rate = (u32)link_freq_items[mode->mipi_freq_idx] / mode->bpp * 2 * NVP6188_LANES; __v4l2_ctrl_s_ctrl_int64(nvp6188->pixel_rate, pixel_rate); - dev_err(&nvp6188->client->dev, "mipi_freq_idx %d\n", mode->mipi_freq_idx); - dev_err(&nvp6188->client->dev, "pixel_rate %lld\n", pixel_rate); + dev_info(&nvp6188->client->dev, "mipi_freq_idx %d\n", mode->mipi_freq_idx); + dev_info(&nvp6188->client->dev, "pixel_rate %lld\n", pixel_rate); } mutex_unlock(&nvp6188->mutex); @@ -1005,7 +1055,7 @@ static int nvp6188_get_fmt(struct v4l2_subdev *sd, fmt->format.height = mode->height; fmt->format.code = mode->bus_fmt; fmt->format.field = V4L2_FIELD_NONE; - if (fmt->pad < PAD_MAX && fmt->pad >= PAD0) + if (fmt->pad < PAD_MAX && fmt->pad > PAD0) fmt->reserved[0] = mode->vc[fmt->pad]; else fmt->reserved[0] = mode->vc[PAD0]; @@ -1032,6 +1082,21 @@ static int nvp6188_enum_mbus_code(struct v4l2_subdev *sd, return 0; } +static int nvp6188_enum_frame_interval(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_interval_enum *fie) +{ + if (fie->index >= ARRAY_SIZE(supported_modes)) + return -EINVAL; + + fie->code = supported_modes[fie->index].bus_fmt; + fie->width = supported_modes[fie->index].width; + fie->height = supported_modes[fie->index].height; + fie->interval = supported_modes[fie->index].max_fps; + + return 0; +} + static int nvp6188_enum_frame_sizes(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_frame_size_enum *fse) @@ -1054,6 +1119,16 @@ static int nvp6188_enum_frame_sizes(struct v4l2_subdev *sd, return 0; } +static int nvp6188_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad_id, + struct v4l2_mbus_config *cfg) +{ + cfg->type = V4L2_MBUS_CSI2_DPHY; + cfg->flags = V4L2_MBUS_CSI2_4_LANE | + V4L2_MBUS_CSI2_CHANNELS; + + return 0; +} + static int nvp6188_g_frame_interval(struct v4l2_subdev *sd, struct v4l2_subdev_frame_interval *fi) { @@ -1067,94 +1142,79 @@ static int nvp6188_g_frame_interval(struct v4l2_subdev *sd, return 0; } -static int nvp6188_enum_frame_interval(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_frame_interval_enum *fie) -{ - if (fie->index >= ARRAY_SIZE(supported_modes)) - return -EINVAL; - - fie->code = supported_modes[fie->index].bus_fmt; - fie->width = supported_modes[fie->index].width; - fie->height = supported_modes[fie->index].height; - fie->interval = supported_modes[fie->index].max_fps; - - return 0; -} - -static int nvp6188_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad_id, - struct v4l2_mbus_config *cfg) -{ - cfg->type = V4L2_MBUS_CSI2_DPHY; - cfg->flags = V4L2_MBUS_CSI2_4_LANE | - V4L2_MBUS_CSI2_CHANNELS; - - return 0; -} - static void nvp6188_get_module_inf(struct nvp6188 *nvp6188, struct rkmodule_inf *inf) { memset(inf, 0, sizeof(*inf)); - strlcpy(inf->base.sensor, NVP6188_NAME, sizeof(inf->base.sensor)); - strlcpy(inf->base.module, nvp6188->module_name, + strscpy(inf->base.sensor, NVP6188_NAME, sizeof(inf->base.sensor)); + strscpy(inf->base.module, nvp6188->module_name, sizeof(inf->base.module)); - strlcpy(inf->base.lens, nvp6188->len_name, sizeof(inf->base.lens)); + strscpy(inf->base.lens, nvp6188->len_name, sizeof(inf->base.lens)); } static void nvp6188_get_vc_fmt_inf(struct nvp6188 *nvp6188, struct rkmodule_vc_fmt_info *inf) { int ch = 0; - unsigned char ch_vfc[4] = { 0xff, 0xff, 0xff, 0xff }; + static u32 last_channel_reso[PAD_MAX] = {NVP_RESO_UNKOWN}; memset(inf, 0, sizeof(*inf)); - nvp6188_read_all_vfc(nvp6188, ch_vfc); - dev_dbg(&nvp6188->client->dev, "nvp6188_get_vc_fmt_inf 0x%2x 0x%2x 0x%2x 0x%2x", - ch_vfc[0], ch_vfc[1], ch_vfc[2], ch_vfc[3]); + for (ch = 0; ch < PAD_MAX; ch++) { + //Maintain last resolution modify by cairufan + if (nvp6188->cur_mode.channel_reso[ch] != NVP_RESO_UNKOWN) + last_channel_reso[ch] = nvp6188->cur_mode.channel_reso[ch]; - for (ch = 0; ch < 4; ch++) { - switch(ch_vfc[ch]) { - case NVP_RESO_960H_NSTC_VALUE: + switch (last_channel_reso[ch]) { + case NVP_RESO_960H_NSTC: inf->width[ch] = 960; inf->height[ch] = 576; inf->fps[ch] = 30; break; - case NVP_RESO_960H_PAL_VALUE: + case NVP_RESO_960H_PAL: inf->width[ch] = 960; inf->height[ch] = 576; inf->fps[ch] = 25; break; - case NVP_RESO_960P_PAL_VALUE: + case NVP_RESO_960P_PAL: inf->width[ch] = 1280; inf->height[ch] = 960; inf->fps[ch] = 25; break; - case NVP_RESO_960P_NSTC_VALUE: + case NVP_RESO_960P_NSTC: inf->width[ch] = 1280; inf->height[ch] = 960; inf->fps[ch] = 30; break; - case NVP_RESO_720P_PAL_VALUE: + case NVP_RESO_720P_PAL: inf->width[ch] = 1280; inf->height[ch] = 720; inf->fps[ch] = 25; break; - case NVP_RESO_720P_NSTC_VALUE: + case NVP_RESO_720P_NSTC: inf->width[ch] = 1280; inf->height[ch] = 720; inf->fps[ch] = 30; break; - case NVP_RESO_1080P_NSTC_VALUE: + case NVP_RESO_1080P_PAL: inf->width[ch] = 1920; inf->height[ch] = 1080; + inf->fps[ch] = 25; + break; + case NVP_RESO_1300P_NSTC: + inf->width[ch] = 1600; + inf->height[ch] = 1300; inf->fps[ch] = 30; break; - case NVP_RESO_1080P_PAL_VALUE: + case NVP_RESO_1300P_PAL: + inf->width[ch] = 1600; + inf->height[ch] = 1300; + inf->fps[ch] = 25; + break; + case NVP_RESO_1080P_NSTC: default: inf->width[ch] = 1920; inf->height[ch] = 1080; - inf->fps[ch] = 25; + inf->fps[ch] = 30; break; } } @@ -1164,7 +1224,7 @@ static void nvp6188_get_vc_hotplug_inf(struct nvp6188 *nvp6188, struct rkmodule_vc_hotplug_info *inf) { memset(inf, 0, sizeof(*inf)); - nvp6188_auto_detect_hotplug(nvp6188); + //nvp6188_auto_detect_hotplug(nvp6188); inf->detect_status = nvp6188->detect_status; } @@ -1186,14 +1246,8 @@ static void nvp6188_set_streaming(struct nvp6188 *nvp6188, int on) struct i2c_client *client = nvp6188->client; dev_info(&client->dev, "%s: on: %d\n", __func__, on); - - if (on) { - nvp6188_write_reg(client, 0xff, 0x20); - nvp6188_write_reg(client, 0xff, 0xff); - } else { - nvp6188_write_reg(client, 0xff, 0x20); - nvp6188_write_reg(client, 0xff, 0x00); - } + if (!on) + usleep_range(40 * 1000, 50 * 1000); } static long nvp6188_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) @@ -1225,7 +1279,6 @@ static long nvp6188_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) stream = *((u32 *)arg); nvp6188_set_streaming(nvp6188, !!stream); break; - default: ret = -ENOTTY; break; @@ -1360,19 +1413,107 @@ static long nvp6188_compat_ioctl32(struct v4l2_subdev *sd, } #endif +/* + * 1280x960p + * dev:0x60 / 0x62 / 0x64 / 0x66 + * ch : 0 ~ 3 + * ntpal: 1:25p, 0:30p + */ +static __maybe_unused void nv6188_set_chn_960p(struct nvp6188 *nvp6188, u8 ch, + u8 ntpal) + +{ + unsigned char val_0x54 = 0, val_20x01 = 0; + struct i2c_client *client = nvp6188->client; + + dev_info(&client->dev, "%s: ch %d ntpal %d", __func__, ch, ntpal); + + nvp6188_write_reg(client, 0xff, 0x00); + nvp6188_write_reg(client, 0x00 + ch, 0x10); + nvp6188_write_reg(client, 0x08 + ch, 0x00); + nvp6188_write_reg(client, 0x18 + ch, 0x0f); + nvp6188_write_reg(client, 0x30 + ch, 0x12); + nvp6188_write_reg(client, 0x34 + ch, 0x00); + nvp6188_read_reg(client, 0x54, &val_0x54); + val_0x54 &= ~(0x10 << ch); + nvp6188_write_reg(client, 0x54, val_0x54); + nvp6188_write_reg(client, 0x58 + ch, ntpal ? 0x40 : 0x48); + nvp6188_write_reg(client, 0x5c + ch, ntpal ? 0x80 : 0x80); + nvp6188_write_reg(client, 0x64 + ch, ntpal ? 0x28 : 0x28); + nvp6188_write_reg(client, 0x81 + ch, ntpal ? 0x07 : 0x06); + nvp6188_write_reg(client, 0x85 + ch, 0x0b); + nvp6188_write_reg(client, 0x89 + ch, 0x00); + nvp6188_write_reg(client, 0x8e + ch, 0x00); + nvp6188_write_reg(client, 0xa0 + ch, 0x05); + nvp6188_write_reg(client, 0xff, 0x01); + nvp6188_write_reg(client, 0x84 + ch, 0x02); + nvp6188_write_reg(client, 0x88 + ch, 0x00); + nvp6188_write_reg(client, 0x8c + ch, 0x40); + nvp6188_write_reg(client, 0xa0 + ch, 0x20); + nvp6188_write_reg(client, 0xff, 0x05 + ch); + nvp6188_write_reg(client, 0x00, 0xd0); + nvp6188_write_reg(client, 0x01, 0x22); + nvp6188_write_reg(client, 0x05, 0x04); + nvp6188_write_reg(client, 0x08, 0x55); + nvp6188_write_reg(client, 0x25, 0xdc); + nvp6188_write_reg(client, 0x28, 0x80); + nvp6188_write_reg(client, 0x2f, 0x00); + nvp6188_write_reg(client, 0x30, 0xe0); + nvp6188_write_reg(client, 0x31, 0x43); + nvp6188_write_reg(client, 0x32, 0xa2); + nvp6188_write_reg(client, 0x47, 0xee); + nvp6188_write_reg(client, 0x50, 0xc6); + nvp6188_write_reg(client, 0x57, 0x00); + nvp6188_write_reg(client, 0x58, 0x77); + nvp6188_write_reg(client, 0x5b, 0x41); + nvp6188_write_reg(client, 0x5c, 0x78); + nvp6188_write_reg(client, 0x5f, 0x00); + nvp6188_write_reg(client, 0x62, 0x00); + nvp6188_write_reg(client, 0x6C, 0x00); + nvp6188_write_reg(client, 0x6d, 0x00); + nvp6188_write_reg(client, 0x6e, 0x00); + nvp6188_write_reg(client, 0x6f, 0x00); + nvp6188_write_reg(client, 0x7b, 0x11); + nvp6188_write_reg(client, 0x7c, 0x01); + nvp6188_write_reg(client, 0x7d, 0x80); + nvp6188_write_reg(client, 0x80, 0x00); + nvp6188_write_reg(client, 0x90, 0x01); + nvp6188_write_reg(client, 0xa9, 0x00); + nvp6188_write_reg(client, 0xb5, 0x40); + nvp6188_write_reg(client, 0xb8, 0x39); + nvp6188_write_reg(client, 0xb9, 0x72); + nvp6188_write_reg(client, 0xd1, 0x00); + nvp6188_write_reg(client, 0xd5, 0x80); + nvp6188_write_reg(client, 0xff, 0x09); + nvp6188_write_reg(client, 0x96 + (ch * 0x20), 0x00); + nvp6188_write_reg(client, 0x98 + (ch * 0x20), 0x00); + nvp6188_write_reg(client, 0x9e + (ch * 0x20), 0x00); + nvp6188_write_reg(client, 0xff, 0x11); + nvp6188_write_reg(client, 0x00 + (ch * 0x20), 0x00); + nvp6188_write_reg(client, 0xff, _MAR_BANK_); + nvp6188_read_reg(client, 0x01, &val_20x01); + val_20x01 &= (~(0x03 << (ch * 2))); + //val_20x01 |=(0x01<<(ch*2)); + nvp6188_write_reg(client, 0x01, val_20x01); + nvp6188_write_reg(client, 0x12 + (ch * 2), 0x80); + nvp6188_write_reg(client, 0x13 + (ch * 2), 0x02); +} + //each channel setting /* -960x480i -ch : 0 ~ 3 -ntpal: 1:25p, 0:30p -*/ + * 960x480i + * ch : 0 ~ 3 + * ntpal: 1:25p, 0:30p + */ static __maybe_unused void nv6188_set_chn_960h(struct nvp6188 *nvp6188, u8 ch, u8 ntpal) { unsigned char val_0x54 = 0, val_20x01 = 0; struct i2c_client *client = nvp6188->client; - dev_err(&client->dev, "nv6188_set_chn_960h ch %d ntpal %d", ch, ntpal); + + dev_err(&client->dev, "%s: ch %d ntpal %d", __func__, ch, ntpal); nvp6188_write_reg(client, 0xff, 0x00); + nvp6188_write_reg(client, 0x00 + ch, 0x10); nvp6188_write_reg(client, 0x08 + ch, ntpal ? 0xdd : 0xa0); nvp6188_write_reg(client, 0x18 + ch, 0x08); nvp6188_write_reg(client, 0x22 + ch * 4, 0x0b); @@ -1391,17 +1532,16 @@ static __maybe_unused void nv6188_set_chn_960h(struct nvp6188 *nvp6188, u8 ch, nvp6188_write_reg(client, 0x81 + ch, ntpal ? 0xf0 : 0xe0); nvp6188_write_reg(client, 0x85 + ch, 0x00); nvp6188_write_reg(client, 0x89 + ch, 0x00); - nvp6188_write_reg(client, ch + 0x8e, 0x00); + nvp6188_write_reg(client, 0x8e + ch, 0x00); nvp6188_write_reg(client, 0xa0 + ch, 0x05); - nvp6188_write_reg(client, 0xff, 0x01); nvp6188_write_reg(client, 0x84 + ch, 0x02); nvp6188_write_reg(client, 0x88 + ch, 0x00); nvp6188_write_reg(client, 0x8c + ch, 0x40); nvp6188_write_reg(client, 0xa0 + ch, 0x20); nvp6188_write_reg(client, 0xed, 0x00); - nvp6188_write_reg(client, 0xff, 0x05 + ch); + nvp6188_write_reg(client, 0x00, 0xd0); nvp6188_write_reg(client, 0x01, 0x22); nvp6188_write_reg(client, 0x05, 0x00); nvp6188_write_reg(client, 0x08, 0x55); @@ -1430,36 +1570,38 @@ static __maybe_unused void nv6188_set_chn_960h(struct nvp6188 *nvp6188, u8 ch, nvp6188_write_reg(client, 0xb9, 0x72); nvp6188_write_reg(client, 0xd1, 0x00); nvp6188_write_reg(client, 0xd5, 0x80); - nvp6188_write_reg(client, 0xff, 0x09); - nvp6188_write_reg(client, 0x96 + ch * 0x20, 0x10); - nvp6188_write_reg(client, 0x98 + ch * 0x20, ntpal ? 0xc0 : 0xe0); - nvp6188_write_reg(client, ch * 0x20 + 0x9e, 0x00); - + nvp6188_write_reg(client, 0x96 + (ch * 0x20), 0x10); + nvp6188_write_reg(client, 0x98 + (ch * 0x20), ntpal ? 0xc0 : 0xe0); + nvp6188_write_reg(client, 0x9e + (ch * 0x20), 0x00); + nvp6188_write_reg(client, 0xff, 0x11); + nvp6188_write_reg(client, 0x00 + (ch * 0x20), 0x00); nvp6188_write_reg(client, 0xff, _MAR_BANK_); nvp6188_read_reg(client, 0x01, &val_20x01); val_20x01 &= (~(0x03 << (ch * 2))); val_20x01 |= (0x02 << (ch * 2)); nvp6188_write_reg(client, 0x01, val_20x01); - nvp6188_write_reg(client, 0x12 + ch * 2, 0xe0); - nvp6188_write_reg(client, 0x13 + ch * 2, 0x01); + nvp6188_write_reg(client, 0x12 + (ch * 2), 0xe0); + nvp6188_write_reg(client, 0x13 + (ch * 2), 0x01); } //each channel setting /* -1280x720p -ch : 0 ~ 3 -ntpal: 1:25p, 0:30p -*/ + * 1280x720p + * ch : 0 ~ 3 + * ntpal: 1:25p, 0:30p + */ static __maybe_unused void nv6188_set_chn_720p(struct nvp6188 *nvp6188, u8 ch, u8 ntpal) { unsigned char val_0x54 = 0, val_20x01 = 0; struct i2c_client *client = nvp6188->client; - dev_err(&client->dev, "nv6188_set_chn_720p ch %d ntpal %d", ch, ntpal); + + dev_info(&client->dev, "%s: ch %d ntpal %d", __func__, ch, ntpal); nvp6188_write_reg(client, 0xff, 0x00); + nvp6188_write_reg(client, 0x00 + ch, 0x00); nvp6188_write_reg(client, 0x08 + ch, 0x00); - nvp6188_write_reg(client, 0x18 + ch, 0x3f); + nvp6188_write_reg(client, 0x18 + ch, 0x10); nvp6188_write_reg(client, 0x30 + ch, 0x12); nvp6188_write_reg(client, 0x34 + ch, 0x00); nvp6188_read_reg(client, 0x54, &val_0x54); @@ -1471,16 +1613,15 @@ static __maybe_unused void nv6188_set_chn_720p(struct nvp6188 *nvp6188, u8 ch, nvp6188_write_reg(client, 0x81 + ch, ntpal ? 0x0d : 0x0c); nvp6188_write_reg(client, 0x85 + ch, 0x00); nvp6188_write_reg(client, 0x89 + ch, 0x00); - nvp6188_write_reg(client, ch + 0x8e, 0x00); + nvp6188_write_reg(client, 0x8e + ch, 0x00); nvp6188_write_reg(client, 0xa0 + ch, 0x05); - nvp6188_write_reg(client, 0xff, 0x01); nvp6188_write_reg(client, 0x84 + ch, 0x02); nvp6188_write_reg(client, 0x88 + ch, 0x00); nvp6188_write_reg(client, 0x8c + ch, 0x40); nvp6188_write_reg(client, 0xa0 + ch, 0x20); - nvp6188_write_reg(client, 0xff, 0x05 + ch); + nvp6188_write_reg(client, 0x00, 0xf0); nvp6188_write_reg(client, 0x01, 0x22); nvp6188_write_reg(client, 0x05, 0x04); nvp6188_write_reg(client, 0x08, 0x55); @@ -1490,55 +1631,57 @@ static __maybe_unused void nv6188_set_chn_720p(struct nvp6188 *nvp6188, u8 ch, nvp6188_write_reg(client, 0x30, 0xe0); nvp6188_write_reg(client, 0x31, 0x43); nvp6188_write_reg(client, 0x32, 0xa2); - nvp6188_write_reg(client, 0x47, 0xee); - nvp6188_write_reg(client, 0x50, 0xc6); + nvp6188_write_reg(client, 0x47, 0x04); + nvp6188_write_reg(client, 0x50, 0x84); nvp6188_write_reg(client, 0x57, 0x00); nvp6188_write_reg(client, 0x58, 0x77); nvp6188_write_reg(client, 0x5b, 0x41); - nvp6188_write_reg(client, 0x5c, 0x7C); + nvp6188_write_reg(client, 0x5c, 0x78); nvp6188_write_reg(client, 0x5f, 0x00); - nvp6188_write_reg(client, 0x62, 0x20); + nvp6188_write_reg(client, 0x62, 0x00); nvp6188_write_reg(client, 0x7b, 0x11); nvp6188_write_reg(client, 0x7c, 0x01); nvp6188_write_reg(client, 0x7d, 0x80); nvp6188_write_reg(client, 0x80, 0x00); nvp6188_write_reg(client, 0x90, 0x01); nvp6188_write_reg(client, 0xa9, 0x00); - nvp6188_write_reg(client, 0xb5, 0x40); - nvp6188_write_reg(client, 0xb8, 0x39); + nvp6188_write_reg(client, 0xb5, 0x00); + nvp6188_write_reg(client, 0xb8, 0xb9); nvp6188_write_reg(client, 0xb9, 0x72); nvp6188_write_reg(client, 0xd1, 0x00); nvp6188_write_reg(client, 0xd5, 0x80); - nvp6188_write_reg(client, 0xff, 0x09); - nvp6188_write_reg(client, 0x96 + ch * 0x20, 0x00); - nvp6188_write_reg(client, 0x98 + ch * 0x20, 0x00); - nvp6188_write_reg(client, ch * 0x20 + 0x9e, 0x00); - + nvp6188_write_reg(client, 0x96 + (ch * 0x20), 0x00); + nvp6188_write_reg(client, 0x98 + (ch * 0x20), 0x00); + nvp6188_write_reg(client, 0x9e + (ch * 0x20), 0x00); + nvp6188_write_reg(client, 0xff, 0x11); + nvp6188_write_reg(client, 0x00 + (ch * 0x20), 0x00); nvp6188_write_reg(client, 0xff, _MAR_BANK_); nvp6188_read_reg(client, 0x01, &val_20x01); val_20x01 &= (~(0x03 << (ch * 2))); val_20x01 |= (0x01 << (ch * 2)); nvp6188_write_reg(client, 0x01, val_20x01); - nvp6188_write_reg(client, 0x12 + ch * 2, 0x80); - nvp6188_write_reg(client, 0x13 + ch * 2, 0x02); + nvp6188_write_reg(client, 0x12 + (ch * 2), 0x80); + nvp6188_write_reg(client, 0x13 + (ch * 2), 0x02); } //each channel setting /* -1920x1080p -ch : 0 ~ 3 -ntpal: 1:25p, 0:30p -*/ + * 1920x1080p + * ch : 0 ~ 3 + * ntpal: 1:25p, 0:30p + */ static __maybe_unused void nv6188_set_chn_1080p(struct nvp6188 *nvp6188, u8 ch, u8 ntpal) { unsigned char val_0x54 = 0, val_20x01 = 0; struct i2c_client *client = nvp6188->client; - dev_err(&client->dev, "nv6188_set_chn_1080p ch %d ntpal %d", ch, ntpal); + + dev_info(&client->dev, "%s ch %d ntpal %d", __func__, ch, ntpal); nvp6188_write_reg(client, 0xff, 0x00); + nvp6188_write_reg(client, 0x00 + ch, 0x10); nvp6188_write_reg(client, 0x08 + ch, 0x00); - nvp6188_write_reg(client, 0x18 + ch, 0x3f); + nvp6188_write_reg(client, 0x18 + ch, 0x10); nvp6188_write_reg(client, 0x30 + ch, 0x12); nvp6188_write_reg(client, 0x34 + ch, 0x00); nvp6188_read_reg(client, 0x54, &val_0x54); @@ -1550,16 +1693,15 @@ static __maybe_unused void nv6188_set_chn_1080p(struct nvp6188 *nvp6188, u8 ch, nvp6188_write_reg(client, 0x81 + ch, ntpal ? 0x03 : 0x02); nvp6188_write_reg(client, 0x85 + ch, 0x00); nvp6188_write_reg(client, 0x89 + ch, 0x10); - nvp6188_write_reg(client, ch + 0x8e, 0x00); + nvp6188_write_reg(client, 0x8e + ch, 0x00); nvp6188_write_reg(client, 0xa0 + ch, 0x05); - nvp6188_write_reg(client, 0xff, 0x01); nvp6188_write_reg(client, 0x84 + ch, 0x02); nvp6188_write_reg(client, 0x88 + ch, 0x00); nvp6188_write_reg(client, 0x8c + ch, 0x40); nvp6188_write_reg(client, 0xa0 + ch, 0x20); - nvp6188_write_reg(client, 0xff, 0x05 + ch); + nvp6188_write_reg(client, 0x00, 0xd0); nvp6188_write_reg(client, 0x01, 0x22); nvp6188_write_reg(client, 0x05, 0x04); nvp6188_write_reg(client, 0x08, 0x55); @@ -1588,48 +1730,274 @@ static __maybe_unused void nv6188_set_chn_1080p(struct nvp6188 *nvp6188, u8 ch, nvp6188_write_reg(client, 0xb9, 0x72); nvp6188_write_reg(client, 0xd1, 0x00); nvp6188_write_reg(client, 0xd5, 0x80); - nvp6188_write_reg(client, 0xff, 0x09); - nvp6188_write_reg(client, 0x96 + ch * 0x20, 0x00); - nvp6188_write_reg(client, 0x98 + ch * 0x20, 0x00); - nvp6188_write_reg(client, ch * 0x20 + 0x9e, 0x00); - + nvp6188_write_reg(client, 0x96 + (ch * 0x20), 0x00); + nvp6188_write_reg(client, 0x98 + (ch * 0x20), 0x00); + nvp6188_write_reg(client, 0x9e + (ch * 0x20), 0x00); + nvp6188_write_reg(client, 0xff, 0x11); + nvp6188_write_reg(client, 0x00 + (ch * 0x20), 0x00); nvp6188_write_reg(client, 0xff, _MAR_BANK_); nvp6188_read_reg(client, 0x01, &val_20x01); val_20x01 &= (~(0x03 << (ch * 2))); nvp6188_write_reg(client, 0x01, val_20x01); - nvp6188_write_reg(client, 0x12 + ch * 2, 0xc0); - nvp6188_write_reg(client, 0x13 + ch * 2, 0x03); + nvp6188_write_reg(client, 0x12 + (ch * 2), 0xc0); + nvp6188_write_reg(client, 0x13 + (ch * 2), 0x03); } -static __maybe_unused void nvp6188_manual_mode(struct nvp6188 *nvp6188) +//each channel setting +/* + * 1600x1300p + * dev:0x60 / 0x62 / 0x64 / 0x66 + * ch : 0 ~ 3 + * ntpal: 1:25p, 0:30p + * detection: 5xf3<<8 | 5xf2 = 0x0708(30p) =0x0870(25p) + */ +static void nv6188_set_chn_1300p(struct nvp6188 *nvp6188, unsigned char ch, unsigned char ntpal) { - int i, reso; - for (i = 3; i >= 0; i--) { - reso = nvp6188->cur_mode.channel_reso[i]; - switch (reso) { - case NVP_RESO_960H_PAL: - nv6188_set_chn_960h(nvp6188, i, 1); + unsigned char val_0x54 = 0, val_20x01 = 0; + struct i2c_client *client = nvp6188->client; + + dev_info(&client->dev, "%s ch %d ntpal %d", __func__, ch, ntpal); + + nvp6188_write_reg(client, 0xff, 0x00); + nvp6188_write_reg(client, 0x00 + ch, 0x10); + nvp6188_write_reg(client, 0x08 + ch, 0x00); + nvp6188_write_reg(client, 0x18 + ch, 0x10); + nvp6188_write_reg(client, 0x30 + ch, 0x12); + nvp6188_write_reg(client, 0x34 + ch, 0x00); + nvp6188_read_reg(client, 0x54, &val_0x54); + val_0x54 &= ~(0x10 << ch); + nvp6188_write_reg(client, 0x54, val_0x54); + nvp6188_write_reg(client, 0x58 + ch, ntpal ? 0x80 : 0x80); + nvp6188_write_reg(client, 0x5c + ch, ntpal ? 0x80 : 0x80); + nvp6188_write_reg(client, 0x64 + ch, ntpal ? 0x00 : 0x01); + nvp6188_write_reg(client, 0x81 + ch, ntpal ? 0x03 : 0x02); + nvp6188_write_reg(client, 0x85 + ch, 0x00); + nvp6188_write_reg(client, 0x89 + ch, 0x10); + nvp6188_write_reg(client, 0x8e + ch, 0x00); + nvp6188_write_reg(client, 0xa0 + ch, 0x05); + nvp6188_write_reg(client, 0xff, 0x01); + nvp6188_write_reg(client, 0x84 + ch, 0x02); + nvp6188_write_reg(client, 0x88 + ch, 0x00); + nvp6188_write_reg(client, 0x8c + ch, 0x40); + nvp6188_write_reg(client, 0xa0 + ch, 0x20); + nvp6188_write_reg(client, 0xff, 0x05 + ch); + nvp6188_write_reg(client, 0x00, 0xd0); + nvp6188_write_reg(client, 0x01, 0x22); + nvp6188_write_reg(client, 0x05, 0x04); + nvp6188_write_reg(client, 0x08, 0x55); + nvp6188_write_reg(client, 0x25, 0xdc); + nvp6188_write_reg(client, 0x28, 0x80); + nvp6188_write_reg(client, 0x2f, 0x00); + nvp6188_write_reg(client, 0x30, 0xe0); + nvp6188_write_reg(client, 0x31, 0x41); + nvp6188_write_reg(client, 0x32, 0xa2); + nvp6188_write_reg(client, 0x47, 0xee); + nvp6188_write_reg(client, 0x50, 0xc6); + nvp6188_write_reg(client, 0x57, 0x00); + nvp6188_write_reg(client, 0x58, 0x77); + nvp6188_write_reg(client, 0x5b, 0x41); + nvp6188_write_reg(client, 0x5c, 0x78); + nvp6188_write_reg(client, 0x5f, 0x00); + nvp6188_write_reg(client, 0x62, 0x00); + nvp6188_write_reg(client, 0x6C, 0x00); + nvp6188_write_reg(client, 0x6d, 0x00); + nvp6188_write_reg(client, 0x6e, 0x00); + nvp6188_write_reg(client, 0x6f, 0x00); + nvp6188_write_reg(client, 0x7b, 0x11); + nvp6188_write_reg(client, 0x7c, 0x01); + nvp6188_write_reg(client, 0x7d, 0x80); + nvp6188_write_reg(client, 0x80, 0x00); + nvp6188_write_reg(client, 0x90, 0x01); + nvp6188_write_reg(client, 0xa9, 0x00); + nvp6188_write_reg(client, 0xb5, 0x00); + nvp6188_write_reg(client, 0xb8, 0xb9); + nvp6188_write_reg(client, 0xb9, 0x72); + nvp6188_write_reg(client, 0xd1, 0x00); + nvp6188_write_reg(client, 0xd5, 0x80); + nvp6188_write_reg(client, 0xff, 0x09); + nvp6188_write_reg(client, 0x96 + (ch * 0x20), 0x00); + nvp6188_write_reg(client, 0x98 + (ch * 0x20), 0x00); + nvp6188_write_reg(client, 0x9e + (ch * 0x20), 0x00); + nvp6188_write_reg(client, 0xff, 0x11); //additional settings for 1300p + nvp6188_write_reg(client, 0x01 + (ch * 0x20), ntpal ? 0x01 : 0x00); + nvp6188_write_reg(client, 0x02 + (ch * 0x20), ntpal ? 0xb2 : 0x50); + nvp6188_write_reg(client, 0x03 + (ch * 0x20), 0x06); + nvp6188_write_reg(client, 0x04 + (ch * 0x20), 0x40); + nvp6188_write_reg(client, 0x05 + (ch * 0x20), ntpal ? 0x08 : 0x07); + nvp6188_write_reg(client, 0x06 + (ch * 0x20), ntpal ? 0x70 : 0x08); + nvp6188_write_reg(client, 0x07 + (ch * 0x20), 0x00); + nvp6188_write_reg(client, 0x08 + (ch * 0x20), 0x00); + nvp6188_write_reg(client, 0x0a + (ch * 0x20), 0x05); + nvp6188_write_reg(client, 0x0b + (ch * 0x20), 0x14); + nvp6188_write_reg(client, 0x0c + (ch * 0x20), 0x05); + nvp6188_write_reg(client, 0x0d + (ch * 0x20), 0x5f); + nvp6188_write_reg(client, 0x00 + (ch * 0x20), 0x03); + nvp6188_write_reg(client, 0xff, 0x20); + nvp6188_read_reg(client, 0x01, &val_20x01); + val_20x01 &= (~(0x03 << (ch * 2))); + nvp6188_write_reg(client, 0x01, val_20x01); + nvp6188_write_reg(client, 0x12 + (ch * 2), 0x20); + nvp6188_write_reg(client, 0x13 + (ch * 2), 0x03); +} + +static __maybe_unused void nvp6188_manual_mode(struct nvp6188 *nvp6188, u8 ch, u32 fmt) +{ + unsigned char val_13x70 = 0, val_13x71 = 0; + struct i2c_client *client = nvp6188->client; + + if (fmt != NVP_RESO_UNKOWN) { + nvp6188_write_reg(client, 0xFF, 0x13); + nvp6188_read_reg(client, 0x70, &val_13x70); + val_13x70 |= (0x01 << ch); + nvp6188_write_reg(client, 0x70, val_13x70); + nvp6188_read_reg(client, 0x71, &val_13x71); + val_13x71 |= (0x01 << ch); + nvp6188_write_reg(client, 0x71, val_13x71); + } + switch (fmt) { + case NVP_RESO_960H_PAL: + nv6188_set_chn_960h(nvp6188, ch, 1); + break; + case NVP_RESO_960P_PAL: + nv6188_set_chn_960p(nvp6188, ch, 1); + break; + case NVP_RESO_720P_PAL: + nv6188_set_chn_720p(nvp6188, ch, 1); + break; + case NVP_RESO_1080P_PAL: + nv6188_set_chn_1080p(nvp6188, ch, 1); + break; + case NVP_RESO_1300P_PAL: + nv6188_set_chn_1300p(nvp6188, ch, 1); + break; + case NVP_RESO_960H_NSTC: + nv6188_set_chn_960h(nvp6188, ch, 0); + break; + case NVP_RESO_960P_NSTC: + nv6188_set_chn_960p(nvp6188, ch, 0); + break; + case NVP_RESO_720P_NSTC: + nv6188_set_chn_720p(nvp6188, ch, 0); + break; + case NVP_RESO_1080P_NSTC: + nv6188_set_chn_1080p(nvp6188, ch, 0); + break; + case NVP_RESO_1300P_NSTC: + nv6188_set_chn_1300p(nvp6188, ch, 0); + break; + default: + nv6188_set_chn_1080p(nvp6188, ch, 0); + + dev_err(&client->dev, "channel %d not detect\n", ch); + nvp6188_write_reg(client, 0xFF, 0x13); + nvp6188_read_reg(client, 0x70, &val_13x70); + val_13x70 &= ~(0x01 << ch); + nvp6188_write_reg(client, 0x70, val_13x70); + nvp6188_write_reg(client, 0xFF, 0x05 + ch); + nvp6188_write_reg(client, 0x58, 0x77); + nvp6188_write_reg(client, 0xb8, 0xb8); + break; + } + + // clear unknown count status + nvp6188->cur_mode.unkown_reso_count[ch] = 0; +} + +static __maybe_unused void nvp6188_auto_detect_fmt(struct nvp6188 *nvp6188) +{ + u8 ch = 0; + u32 reso = 0; + unsigned char ch_vfc = 0xff, val_13x70 = 0xf0; + int ch_htotal = 0; + struct i2c_client *client = nvp6188->client; + + for (ch = 0; ch < PAD_MAX; ch++) { + ch_vfc = nv6188_read_vfc(nvp6188, ch); + if (ch_vfc == 0xFF) { + ch_htotal = nv6188_read_htotal(nvp6188, ch); + if (ch_htotal == 0x0708) + ch_vfc = NVP_RESO_1300P_NSTC_VALUE; + else if (ch_htotal == 0x0870) + ch_vfc = NVP_RESO_1300P_PAL_VALUE; + } + switch (ch_vfc) { + case NVP_RESO_960H_NSTC_VALUE: + dev_dbg(&client->dev, "channel %d det 960h nstc", ch); + reso = NVP_RESO_960H_NSTC; break; - case NVP_RESO_720P_PAL: - nv6188_set_chn_720p(nvp6188, i, 1); + case NVP_RESO_960H_PAL_VALUE: + dev_dbg(&client->dev, "channel %d det 960h pal", ch); + reso = NVP_RESO_960H_PAL; break; - case NVP_RESO_1080P_PAL: - nv6188_set_chn_1080p(nvp6188, i, 1); + case NVP_RESO_720P_NSTC_VALUE: + dev_dbg(&client->dev, "channel %d det 720p nstc", ch); + reso = NVP_RESO_720P_NSTC; break; - case NVP_RESO_960H_NSTC: - nv6188_set_chn_960h(nvp6188, i, 0); + case NVP_RESO_720P_PAL_VALUE: + dev_dbg(&client->dev, "channel %d det 720p pal", ch); + reso = NVP_RESO_720P_PAL; break; - case NVP_RESO_720P_NSTC: - nv6188_set_chn_720p(nvp6188, i, 0); + case NVP_RESO_1080P_NSTC_VALUE: + dev_dbg(&client->dev, "channel %d det 1080p nstc", ch); + reso = NVP_RESO_1080P_NSTC; break; - case NVP_RESO_1080P_NSTC: - nv6188_set_chn_1080p(nvp6188, i, 0); + case NVP_RESO_1080P_PAL_VALUE: + dev_dbg(&client->dev, "channel %d det 1080p pal", ch); + reso = NVP_RESO_1080P_PAL; + break; + case NVP_RESO_960P_NSTC_VALUE: + dev_dbg(&client->dev, "channel %d det 960p nstc", ch); + reso = NVP_RESO_960P_NSTC; + break; + case NVP_RESO_960P_PAL_VALUE: + dev_dbg(&client->dev, "channel %d det 960p pal", ch); + reso = NVP_RESO_960P_PAL; + break; + case NVP_RESO_1300P_NSTC_VALUE: + dev_dbg(&client->dev, "channel %d det 1300p nstc", ch); + reso = NVP_RESO_1300P_NSTC; + break; + case NVP_RESO_1300P_PAL_VALUE: + dev_dbg(&client->dev, "channel %d det 1300p pal", ch); + reso = NVP_RESO_1300P_PAL; break; default: - nv6188_set_chn_1080p(nvp6188, i, 1); + dev_dbg(&client->dev, "channel %d not detect\n", ch); + reso = NVP_RESO_UNKOWN; break; } + + if (reso != nvp6188->cur_mode.channel_reso[ch]) { + if (nvp6188->cur_mode.channel_reso[ch] != NVP_RESO_UNKOWN && + reso == NVP_RESO_UNKOWN && + (nvp6188->detect_status & (0x01 << ch)) == 0) { + dev_info(&client->dev, "channel(%d) fmt(%d) -> invalid(0x%x)", + ch, nvp6188->cur_mode.channel_reso[ch], ch_vfc); + if (nvp6188->cur_mode.unkown_reso_count[ch] < 5) { + nvp6188_write_reg(client, 0xFF, 0x13); + nvp6188_read_reg(client, 0x70, &val_13x70); + val_13x70 &= ~(0x01 << ch); + nvp6188_write_reg(client, 0x70, val_13x70); + nvp6188->cur_mode.unkown_reso_count[ch]++; + continue; + } + } + dev_info(&client->dev, "channel(%d) fmt(%d) -> cur(%d)", + ch, nvp6188->cur_mode.channel_reso[ch], reso); + nvp6188_manual_mode(nvp6188, ch, reso); + nvp6188->cur_mode.channel_reso[ch] = reso; + } + } +} + +static __maybe_unused void nvp6188_init_default_fmt(struct nvp6188 *nvp6188, u32 fmt) +{ + u8 ch = 0; + + for (ch = 0; ch < PAD_MAX; ch++) { + nvp6188_manual_mode(nvp6188, ch, fmt); + nvp6188->cur_mode.channel_reso[ch] = fmt; } } @@ -1637,30 +2005,23 @@ static int detect_thread_function(void *data) { struct nvp6188 *nvp6188 = (struct nvp6188 *) data; struct i2c_client *client = nvp6188->client; - unsigned char bits = 0, ch, val_13x70 = 0, val_13x71 = 0; int need_reset_wait = -1; + nvp6188->disable_dump_register = true; if (nvp6188->power_on) { nvp6188_auto_detect_hotplug(nvp6188); nvp6188->last_detect_status = nvp6188->detect_status; nvp6188->is_reset = 0; } while (!kthread_should_stop()) { - if (nvp6188->power_on) { + if (nvp6188->disable_dump_register && nvp6188->power_on) { + mutex_lock(&nvp6188->mutex); nvp6188_auto_detect_hotplug(nvp6188); + nvp6188_auto_detect_fmt(nvp6188); + + mutex_unlock(&nvp6188->mutex); if (nvp6188->last_detect_status != nvp6188->detect_status) { - bits = nvp6188->last_detect_status ^ nvp6188->detect_status; - for (ch = 0; ch < 4; ch++) { - if (bits & (1 << ch)) { - dev_err(&client->dev, "nvp6188 detect ch %d change\n", ch); - nvp6188_write_reg(client, 0xFF, 0x13); - nvp6188_read_reg(client, 0x70, &val_13x70); - val_13x70 |= (0x01 << ch); - nvp6188_write_reg(client, 0x70, val_13x70); - nvp6188_read_reg(client, 0x71, &val_13x71); - val_13x71 |= (0x01 << ch); - nvp6188_write_reg(client, 0x71, val_13x71); - } - } + dev_info(&client->dev, "last_detect_status(0x%x) -> detect_status(0x%x)", + nvp6188->last_detect_status, nvp6188->detect_status); nvp6188->last_detect_status = nvp6188->detect_status; input_event(nvp6188->input_dev, EV_MSC, MSC_RAW, nvp6188->detect_status); input_sync(nvp6188->input_dev); @@ -1671,7 +2032,7 @@ static int detect_thread_function(void *data) } else if (need_reset_wait == 0) { need_reset_wait = -1; nvp6188->is_reset = 1; - dev_err(&client->dev, "trigger reset time up\n"); + dev_info(&client->dev, "trigger reset time up\n"); } } set_current_state(TASK_INTERRUPTIBLE); @@ -1686,6 +2047,7 @@ static int __maybe_unused detect_thread_start(struct nvp6188 *nvp6188) struct i2c_client *client = nvp6188->client; nvp6188->detect_thread = kthread_create(detect_thread_function, nvp6188, "nvp6188_kthread"); + if (IS_ERR(nvp6188->detect_thread)) { dev_err(&client->dev, "kthread_create nvp6188_kthread failed\n"); ret = PTR_ERR(nvp6188->detect_thread); @@ -1701,10 +2063,70 @@ static int __maybe_unused detect_thread_stop(struct nvp6188 *nvp6188) if (nvp6188->detect_thread) kthread_stop(nvp6188->detect_thread); nvp6188->detect_thread = NULL; + return 0; } -static int __nvp6188_start_stream(struct nvp6188 *nvp6188) +static int __maybe_unused nvp6188_reg_check(struct nvp6188 *nvp6188) +{ + unsigned char val_20x52 = 0, val_20x53 = 0; + int check_value1 = 0, check_value2 = 0, check_cnt = 10; + struct i2c_client *client = nvp6188->client; + + nvp6188_write_reg(client, 0xff, 0x20); + nvp6188_write_reg(client, 0x00, 0xff); // open mipi + usleep_range(100 * 1000, 100 * 1000); + //nvp6188_write_reg(client, 0x40, 0x01); + //nvp6188_write_reg(client, 0x40, 0x00); + while (check_cnt--) { + nvp6188_write_reg(client, 0xff, 0x20); + nvp6188_read_reg(client, 0x52, &val_20x52); + nvp6188_read_reg(client, 0x53, &val_20x53); + check_value1 = (val_20x52 << 8) | val_20x53; + usleep_range(80 * 1000, 100 * 1000); + nvp6188_write_reg(client, 0xff, 0x20); + nvp6188_read_reg(client, 0x52, &val_20x52); + nvp6188_read_reg(client, 0x53, &val_20x53); + check_value2 = (val_20x52 << 8) | val_20x53; + if (check_value2 <= 2 || check_value1 == check_value2) { + dev_err(&client->dev, "attention!!! check cnt = %d\n", check_cnt); + nvp6188_write_reg(client, 0xff, 0x01); + nvp6188_write_reg(client, 0x97, 0xf0); + usleep_range(40 * 1000, 50 * 1000); + nvp6188_write_reg(client, 0x97, 0x0f); + } else { + dev_err(&client->dev, "check_value1=%x, check_value2=%x,check cnt = %d\n", + check_value1, check_value2, check_cnt); + break; + } + } + return check_cnt; +} + +static int nvp6188_auto_det_set(struct nvp6188 *nvp6188) +{ + struct i2c_client *client = nvp6188->client; + + dev_info(&client->dev, "[%s::%d]\n", __func__, __LINE__); + + nvp6188_write_reg(client, 0xff, 0x13); + nvp6188_write_reg(client, 0x30, 0x7f); + nvp6188_write_reg(client, 0x70, 0xf0); + nvp6188_write_reg(client, 0xff, 0x00); + nvp6188_write_reg(client, 0x00, 0x18); + nvp6188_write_reg(client, 0x01, 0x18); + nvp6188_write_reg(client, 0x02, 0x18); + nvp6188_write_reg(client, 0x03, 0x18); + usleep_range(30 * 1000, 40 * 1000); + nvp6188_write_reg(client, 0x00, 0x10); + nvp6188_write_reg(client, 0x01, 0x10); + nvp6188_write_reg(client, 0x02, 0x10); + nvp6188_write_reg(client, 0x03, 0x10); + + return 0; +} + +static int nvp6188_video_init(struct nvp6188 *nvp6188) { int ret; int array_size = 0; @@ -1725,9 +2147,26 @@ static int __nvp6188_start_stream(struct nvp6188 *nvp6188) return ret; } + nvp6188_init_default_fmt(nvp6188, NVP_RESO_UNKOWN); + nvp6188_auto_det_set(nvp6188); + usleep_range(150*1000, 150*1000); nvp6188_auto_detect_fmt(nvp6188); - nvp6188_manual_mode(nvp6188); + + return 0; +} + +static int __nvp6188_start_stream(struct nvp6188 *nvp6188) +{ + struct i2c_client *client = nvp6188->client; + + if (nvp6188->detect_thread) { + nvp6188_write_reg(client, 0xff, 0x20); + nvp6188_write_reg(client, 0x00, 0xff); + return 0; + } + nvp6188_audio_init(nvp6188); + nvp6188_reg_check(nvp6188); detect_thread_start(nvp6188); return 0; } @@ -1735,11 +2174,14 @@ static int __nvp6188_start_stream(struct nvp6188 *nvp6188) static int __nvp6188_stop_stream(struct nvp6188 *nvp6188) { struct i2c_client *client = nvp6188->client; + nvp6188_write_reg(client, 0xff, 0x20); nvp6188_write_reg(client, 0x00, 0x00); nvp6188_write_reg(client, 0x40, 0x01); nvp6188_write_reg(client, 0x40, 0x00); - detect_thread_stop(nvp6188); + //detect_thread_stop(nvp6188); + usleep_range(100 * 1000, 150 * 1000); + return 0; } @@ -1748,7 +2190,7 @@ static int nvp6188_stream(struct v4l2_subdev *sd, int on) struct nvp6188 *nvp6188 = to_nvp6188(sd); struct i2c_client *client = nvp6188->client; - dev_dbg(&client->dev, "s_stream: %d. %dx%d\n", on, + dev_info(&client->dev, "s_stream: %d. %dx%d\n", on, nvp6188->cur_mode.width, nvp6188->cur_mode.height); @@ -1783,8 +2225,6 @@ static int nvp6188_power(struct v4l2_subdev *sd, int on) if (nvp6188->power_on == !!on) goto exit; - dev_dbg(&client->dev, "%s: on %d\n", __func__, on); - if (on) { ret = pm_runtime_get_sync(&client->dev); if (ret < 0) { @@ -1808,8 +2248,6 @@ static int __nvp6188_power_on(struct nvp6188 *nvp6188) int ret; struct device *dev = &nvp6188->client->dev; - dev_dbg(dev, "%s\n", __func__); - if (!IS_ERR_OR_NULL(nvp6188->pins_default)) { ret = pinctrl_select_state(nvp6188->pinctrl, nvp6188->pins_default); @@ -1839,10 +2277,15 @@ static int __nvp6188_power_on(struct nvp6188 *nvp6188) } if (!IS_ERR(nvp6188->reset_gpio)) { + gpiod_set_value_cansleep(nvp6188->reset_gpio, 1); + usleep_range(10 * 1000, 20 * 1000); gpiod_set_value_cansleep(nvp6188->reset_gpio, 0); usleep_range(10 * 1000, 20 * 1000); gpiod_set_value_cansleep(nvp6188->reset_gpio, 1); - usleep_range(10 * 1000, 20 * 1000); + usleep_range(100 * 1000, 110 * 1000); + + //Resolve audio register reset caused by reset_gpio + nvp6188_audio_init(nvp6188); } usleep_range(10 * 1000, 20 * 1000); @@ -1864,8 +2307,6 @@ static void __nvp6188_power_off(struct nvp6188 *nvp6188) int ret; struct device *dev = &nvp6188->client->dev; - dev_dbg(dev, "%s\n", __func__); - if (!IS_ERR(nvp6188->reset_gpio)) gpiod_set_value_cansleep(nvp6188->reset_gpio, 1); clk_disable_unprepare(nvp6188->xvclk); @@ -1915,9 +2356,9 @@ static int nvp6188_initialize_controls(struct nvp6188 *nvp6188) goto err_free_handler; } - dev_err(&nvp6188->client->dev, "mipi_freq_idx %d\n", mode->mipi_freq_idx); - dev_err(&nvp6188->client->dev, "pixel_rate %lld\n", pixel_rate); - dev_err(&nvp6188->client->dev, "link_freq %lld\n", link_freq_items[mode->mipi_freq_idx]); + dev_dbg(&nvp6188->client->dev, "mipi_freq_idx %d\n", mode->mipi_freq_idx); + dev_dbg(&nvp6188->client->dev, "pixel_rate %lld\n", pixel_rate); + dev_dbg(&nvp6188->client->dev, "link_freq %lld\n", link_freq_items[mode->mipi_freq_idx]); nvp6188->subdev.ctrl_handler = handler; @@ -2019,12 +2460,15 @@ static unsigned int nvp6188_codec_read(struct snd_soc_component *component, int ret; u8 val; + mutex_lock(&nvp6188->mutex); ret = nvp6188_read_reg(client, reg, &val); if (ret < 0) { dev_err(&client->dev, "%s failed: (%d)\n", __func__, ret); + mutex_unlock(&nvp6188->mutex); return ret; } + mutex_unlock(&nvp6188->mutex); return val; } @@ -2036,12 +2480,15 @@ static int nvp6188_codec_write(struct snd_soc_component *component, struct i2c_client *client = nvp6188->client; int ret; + mutex_lock(&nvp6188->mutex); ret = nvp6188_write_reg(client, reg, val); if (ret < 0) { dev_err(&client->dev, "%s failed: (%d)\n", __func__, ret); + mutex_unlock(&nvp6188->mutex); return ret; } + mutex_unlock(&nvp6188->mutex); return 0; } @@ -2062,7 +2509,9 @@ static int nvp6188_pcm_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) struct nvp6188 *nvp6188 = to_nvp6188(sd); struct i2c_client *client = nvp6188->client; u8 val_rm = 0, val_pb = 0; + int ret = 0; + mutex_lock(&nvp6188->mutex); nvp6188_write_reg(client, 0xff, 0x01); /* Switch to bank1 for audio */ nvp6188_read_reg(client, 0x07, &val_rm); nvp6188_read_reg(client, 0x13, &val_pb); @@ -2077,7 +2526,8 @@ static int nvp6188_pcm_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) val_pb &= (~0x80); break; default: - return -EINVAL; + ret = -EINVAL; + goto unlock; } /* interface format */ @@ -2095,7 +2545,8 @@ static int nvp6188_pcm_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) val_pb |= 0x03; break; default: - return -EINVAL; + ret = -EINVAL; + goto unlock; } /* clock inversion */ @@ -2109,13 +2560,17 @@ static int nvp6188_pcm_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) val_pb |= 0x40; break; default: - return -EINVAL; + ret = -EINVAL; + goto unlock; } nvp6188_write_reg(client, 0x07, val_rm); nvp6188_write_reg(client, 0x13, val_pb); - return 0; +unlock: + mutex_unlock(&nvp6188->mutex); + + return ret; } static int nvp6188_pcm_hw_params(struct snd_pcm_substream *substream, @@ -2126,7 +2581,9 @@ static int nvp6188_pcm_hw_params(struct snd_pcm_substream *substream, struct nvp6188 *nvp6188 = to_nvp6188(sd); struct i2c_client *client = nvp6188->client; u8 val = 0; + int ret = 0; + mutex_lock(&nvp6188->mutex); nvp6188_write_reg(client, 0xff, 0x01); /* Switch to bank1 for audio */ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { @@ -2140,7 +2597,8 @@ static int nvp6188_pcm_hw_params(struct snd_pcm_substream *substream, val &= (~0x04); break; default: - return -EINVAL; + ret = -EINVAL; + goto unlock; } switch (params_rate(params)) { @@ -2154,7 +2612,8 @@ static int nvp6188_pcm_hw_params(struct snd_pcm_substream *substream, /* TODO */ break; default: - return -EINVAL; + ret = -EINVAL; + goto unlock; } if (nvp6188->audio_out) { @@ -2171,7 +2630,8 @@ static int nvp6188_pcm_hw_params(struct snd_pcm_substream *substream, default: dev_err(&client->dev, "Invalid audio_out mclk_fs: %d\n", nvp6188->audio_out->mclk_fs); - return -EINVAL; + ret = -EINVAL; + goto unlock; } } @@ -2187,7 +2647,8 @@ static int nvp6188_pcm_hw_params(struct snd_pcm_substream *substream, val &= (~0x04); break; default: - return -EINVAL; + ret = -EINVAL; + goto unlock; } switch (params_rate(params)) { @@ -2201,7 +2662,8 @@ static int nvp6188_pcm_hw_params(struct snd_pcm_substream *substream, /* TODO */ break; default: - return -EINVAL; + ret = -EINVAL; + goto unlock; } if (nvp6188->audio_in) { @@ -2218,7 +2680,8 @@ static int nvp6188_pcm_hw_params(struct snd_pcm_substream *substream, default: dev_err(&client->dev, "Invalid audio_in mclk_fs: %d\n", nvp6188->audio_in->mclk_fs); - return -EINVAL; + ret = -EINVAL; + goto unlock; } } nvp6188_write_reg(client, 0x07, val); @@ -2234,12 +2697,16 @@ static int nvp6188_pcm_hw_params(struct snd_pcm_substream *substream, default: dev_err(&client->dev, "Not supported channels: %d\n", params_channels(params)); - return -EINVAL; + ret = -EINVAL; + goto unlock; } nvp6188_write_reg(client, 0x08, val); } - return 0; +unlock: + mutex_unlock(&nvp6188->mutex); + + return ret; } static int nvp6188_pcm_mute(struct snd_soc_dai *dai, int mute, int stream) @@ -2298,7 +2765,9 @@ static int nvp6188_codec_tlv_get(struct snd_kcontrol *kcontrol, struct nvp6188 *nvp6188 = to_nvp6188(sd); struct i2c_client *client = nvp6188->client; + mutex_lock(&nvp6188->mutex); nvp6188_write_reg(client, 0xff, 0x01); /* Switch to bank1 for audio */ + mutex_unlock(&nvp6188->mutex); return snd_soc_get_volsw(kcontrol, ucontrol); } @@ -2441,6 +2910,11 @@ static int nvp6188_audio_init(struct nvp6188 *nvp6188) msleep(30); nvp6188_write_reg(client, 0x38, 0x08); + //SLAVE MODE I2S MODE Inverted Clock + nvp6188_write_reg(client, 0xff, 0x01); + nvp6188_write_reg(client, 0x07, 0x08); + nvp6188_write_reg(client, 0x13, 0x08); + return 0; } @@ -2679,6 +3153,8 @@ static int nvp6188_probe(struct i2c_client *client, pm_runtime_enable(dev); pm_runtime_idle(dev); + nvp6188_video_init(nvp6188); + return 0; err_clean_entity: @@ -2715,7 +3191,7 @@ static int nvp6188_remove(struct i2c_client *client) return 0; } -static const struct dev_pm_ops nvp6188_pm_ops = { +static const struct dev_pm_ops __maybe_unused nvp6188_pm_ops = { SET_RUNTIME_PM_OPS(nvp6188_runtime_suspend, nvp6188_runtime_resume, NULL) }; @@ -2736,7 +3212,7 @@ static const struct i2c_device_id nvp6188_match_id[] = { static struct i2c_driver nvp6188_i2c_driver = { .driver = { .name = NVP6188_NAME, - .pm = &nvp6188_pm_ops, + //.pm = &nvp6188_pm_ops, .of_match_table = of_match_ptr(nvp6188_of_match), }, .probe = &nvp6188_probe,