From 9370bb92b2d16684ee45cf24e879c93c509162da Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Thu, 19 Dec 2024 01:47:39 +0000 Subject: [PATCH] add wifi6 8852be driver --- kernel/drivers/media/i2c/nvp6188.c | 1680 +++++++++++++++++++++++++++++++++++------------------------ 1 files changed, 1,006 insertions(+), 674 deletions(-) diff --git a/kernel/drivers/media/i2c/nvp6188.c b/kernel/drivers/media/i2c/nvp6188.c index dc32e88..36cf018 100644 --- a/kernel/drivers/media/i2c/nvp6188.c +++ b/kernel/drivers/media/i2c/nvp6188.c @@ -10,9 +10,11 @@ * 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.0X02.0x00 version. - * 1,support auto detect format when plugging - * 2,support quick stream when reset vicap + * 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 @@ -36,15 +38,14 @@ #include <linux/rk-preisp.h> #include <linux/sched.h> #include <linux/kthread.h> - #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> #include <sound/soc.h> #include <sound/tlv.h> - #include <linux/platform_device.h> #include <linux/input.h> +#include "nvp6188.h" #define DRIVER_VERSION KERNEL_VERSION(0, 0x02, 0x0) @@ -80,21 +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 - -enum nvp6188_max_pad { - PAD0, - PAD1, - PAD2, - PAD3, - PAD_MAX, -}; +#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, @@ -102,10 +97,12 @@ 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 */ @@ -133,6 +130,7 @@ u32 hdr_mode; u32 vc[PAD_MAX]; u32 channel_reso[PAD_MAX]; + u32 unkown_reso_count[PAD_MAX]; }; struct nvp6188_audio { @@ -146,11 +144,9 @@ 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; @@ -159,23 +155,20 @@ 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) @@ -192,489 +185,619 @@ 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 DEVICE_ATTR(hotplug_status, 0644, show_hotplug_status, NULL); +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 }, - { 0x04, 0x6c }, - { 0x01, 0xe4 }, - { 0x00, 0x7d }, - { 0x01, 0xe0 }, - { 0x02, 0xa0 }, - { 0x20, 0x1e }, - { 0x20, 0x1f }, - { 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, 0x00 }, //close mipi - { 0x40, 0x01 }, - { 0x40, 0x00 }, - { 0xff, 0x01 }, - { 0x97, 0x00 }, - { 0x97, 0x0f }, - - { 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 __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[] = { @@ -808,51 +931,29 @@ 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); - } - - 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_hotplug(struct nvp6188 *nvp6188) @@ -924,8 +1025,8 @@ __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); @@ -981,6 +1082,21 @@ 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) @@ -1003,12 +1119,25 @@ return 0; } -static int nvp6188_g_mbus_config(struct v4l2_subdev *sd, +static int nvp6188_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad_id, struct v4l2_mbus_config *cfg) { - cfg->type = V4L2_MBUS_CSI2; + 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) +{ + struct nvp6188 *nvp6188 = to_nvp6188(sd); + const struct nvp6188_mode *mode = &nvp6188->cur_mode; + + mutex_lock(&nvp6188->mutex); + fi->interval = mode->max_fps; + mutex_unlock(&nvp6188->mutex); return 0; } @@ -1028,8 +1157,8 @@ { int ch = 0; static u32 last_channel_reso[PAD_MAX] = {NVP_RESO_UNKOWN}; - memset(inf, 0, sizeof(*inf)); + for (ch = 0; ch < PAD_MAX; ch++) { //Maintain last resolution modify by cairufan if (nvp6188->cur_mode.channel_reso[ch] != NVP_RESO_UNKOWN) @@ -1071,6 +1200,16 @@ 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_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; @@ -1107,18 +1246,8 @@ struct i2c_client *client = nvp6188->client; dev_info(&client->dev, "%s: on: %d\n", __func__, on); - - mutex_lock(&nvp6188->mutex); - - 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); - } - - mutex_unlock(&nvp6188->mutex); + if (!on) + usleep_range(40 * 1000, 50 * 1000); } static long nvp6188_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) @@ -1292,6 +1421,7 @@ */ 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; @@ -1299,27 +1429,29 @@ dev_info(&client->dev, "%s: ch %d ntpal %d", __func__, ch, ntpal); nvp6188_write_reg(client, 0xff, 0x00); - 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_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); + 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, ch+0x8e, 0x00); - nvp6188_write_reg(client, 0xa0+ch, 0x05); + 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, 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); @@ -1353,16 +1485,18 @@ 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 &= (~(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 @@ -1377,9 +1511,9 @@ 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); - + 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); @@ -1398,17 +1532,16 @@ 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); @@ -1437,19 +1570,19 @@ 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 @@ -1465,10 +1598,10 @@ 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, 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); @@ -1480,16 +1613,15 @@ 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); @@ -1499,38 +1631,38 @@ 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 @@ -1545,10 +1677,11 @@ 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); + 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); @@ -1560,16 +1693,15 @@ 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); @@ -1598,18 +1730,115 @@ 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); +} + +//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) +{ + 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) @@ -1617,14 +1846,15 @@ unsigned char val_13x70 = 0, val_13x71 = 0; struct i2c_client *client = nvp6188->client; - 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); - + 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); @@ -1638,6 +1868,9 @@ 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; @@ -1650,8 +1883,11 @@ 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, 1); + nv6188_set_chn_1080p(nvp6188, ch, 0); dev_err(&client->dev, "channel %d not detect\n", ch); nvp6188_write_reg(client, 0xFF, 0x13); @@ -1659,71 +1895,96 @@ 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; + 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; + dev_dbg(&client->dev, "channel %d det 960h nstc", ch); + reso = NVP_RESO_960H_NSTC; break; case NVP_RESO_960H_PAL_VALUE: - dev_dbg(&client->dev, "channel %d det 960h pal", ch); - reso = NVP_RESO_960H_PAL; + dev_dbg(&client->dev, "channel %d det 960h pal", ch); + reso = NVP_RESO_960H_PAL; break; case NVP_RESO_720P_NSTC_VALUE: - dev_dbg(&client->dev, "channel %d det 720p nstc", ch); - reso = NVP_RESO_720P_NSTC; + dev_dbg(&client->dev, "channel %d det 720p nstc", ch); + reso = NVP_RESO_720P_NSTC; break; case NVP_RESO_720P_PAL_VALUE: - dev_dbg(&client->dev, "channel %d det 720p pal", ch); - reso = NVP_RESO_720P_PAL; + dev_dbg(&client->dev, "channel %d det 720p pal", ch); + reso = NVP_RESO_720P_PAL; break; case NVP_RESO_1080P_NSTC_VALUE: - dev_dbg(&client->dev, "channel %d det 1080p nstc", ch); - reso = NVP_RESO_1080P_NSTC; + dev_dbg(&client->dev, "channel %d det 1080p nstc", ch); + reso = NVP_RESO_1080P_NSTC; break; case NVP_RESO_1080P_PAL_VALUE: - dev_dbg(&client->dev, "channel %d det 1080p pal", ch); - reso = NVP_RESO_1080P_PAL; + 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; + 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; + 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: - dev_dbg(&client->dev, "channel %d not detect\n", ch); - reso = NVP_RESO_UNKOWN; + 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)) { + 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); - return; + 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); + ch, nvp6188->cur_mode.channel_reso[ch], reso); nvp6188_manual_mode(nvp6188, ch, reso); nvp6188->cur_mode.channel_reso[ch] = reso; } @@ -1745,21 +2006,22 @@ struct nvp6188 *nvp6188 = (struct nvp6188 *) data; struct i2c_client *client = nvp6188->client; 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) { 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); nvp6188->last_detect_status = nvp6188->detect_status; input_event(nvp6188->input_dev, EV_MSC, MSC_RAW, nvp6188->detect_status); input_sync(nvp6188->input_dev); @@ -1770,7 +2032,7 @@ } 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); @@ -1785,6 +2047,7 @@ 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); @@ -1800,19 +2063,21 @@ if (nvp6188->detect_thread) kthread_stop(nvp6188->detect_thread); nvp6188->detect_thread = NULL; + return 0; } -static int nvp6188_reg_check(struct nvp6188 *nvp6188) +static int __maybe_unused nvp6188_reg_check(struct nvp6188 *nvp6188) { unsigned char val_20x52 = 0, val_20x53 = 0; - unsigned char val_20x52_bak = 0, val_20x53_bak = 0; - int check_value1, check_value2, check_cnt = 10; + int check_value1 = 0, check_value2 = 0, check_cnt = 10; struct i2c_client *client = nvp6188->client; - dev_dbg(&client->dev, "[%s::%d]\n", __func__, __LINE__); 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); @@ -1820,25 +2085,48 @@ 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_bak); - nvp6188_read_reg(client, 0x53, &val_20x53_bak); - check_value2 = (val_20x52_bak << 8) | val_20x53_bak; - if (check_value1 == check_value2) { - dev_info(&client->dev, "attention!!! check cnt = %d\n", check_cnt); + 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); + check_value1, check_value2, check_cnt); break; } } - return check_cnt; } -static int __nvp6188_start_stream(struct nvp6188 *nvp6188) + +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; @@ -1855,20 +2143,28 @@ ret = nvp6188_write_array(nvp6188->client, nvp6188->cur_mode.global_reg_list, array_size); if (ret) { - dev_err(&client->dev, "%s: global_reg_list failed", __func__); - return ret; - } - - ret = nvp6188_write_array(nvp6188->client, - auto_detect_regs, ARRAY_SIZE(auto_detect_regs)); - if (ret) { - dev_err(&client->dev, "%s: auto_detect_regs failed", __func__); + dev_err(&client->dev, "__nvp6188_start_stream global_reg_list faild"); return ret; } nvp6188_init_default_fmt(nvp6188, NVP_RESO_UNKOWN); - usleep_range(500*1000, 1000*1000); + nvp6188_auto_det_set(nvp6188); + usleep_range(150*1000, 150*1000); nvp6188_auto_detect_fmt(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); @@ -1878,11 +2174,14 @@ 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; } @@ -1891,7 +2190,7 @@ struct nvp6188 *nvp6188 = to_nvp6188(sd); struct i2c_client *client = nvp6188->client; - dev_err(&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); @@ -1925,8 +2224,6 @@ /* If the power state is not modified - no work to do. */ if (nvp6188->power_on == !!on) goto exit; - - dev_err(&client->dev, "%s: on %d\n", __func__, on); if (on) { ret = pm_runtime_get_sync(&client->dev); @@ -1985,7 +2282,7 @@ 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); @@ -2059,9 +2356,9 @@ goto err_free_handler; } - 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); - dev_info(&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; @@ -2073,7 +2370,7 @@ return ret; } -static int nvp6188_runtime_resume(struct device *dev) +static int __maybe_unused nvp6188_runtime_resume(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); struct v4l2_subdev *sd = i2c_get_clientdata(client); @@ -2082,7 +2379,7 @@ return __nvp6188_power_on(nvp6188); } -static int nvp6188_runtime_suspend(struct device *dev) +static int __maybe_unused nvp6188_runtime_suspend(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); struct v4l2_subdev *sd = i2c_get_clientdata(client); @@ -2125,14 +2422,16 @@ static const struct v4l2_subdev_video_ops nvp6188_video_ops = { .s_stream = nvp6188_stream, - .g_mbus_config = nvp6188_g_mbus_config, + .g_frame_interval = nvp6188_g_frame_interval, }; static const struct v4l2_subdev_pad_ops nvp6188_subdev_pad_ops = { .enum_mbus_code = nvp6188_enum_mbus_code, .enum_frame_size = nvp6188_enum_frame_sizes, + .enum_frame_interval = nvp6188_enum_frame_interval, .get_fmt = nvp6188_get_fmt, .set_fmt = nvp6188_set_fmt, + .get_mbus_config = nvp6188_g_mbus_config, }; static const struct v4l2_subdev_core_ops nvp6188_core_ops = { @@ -2161,12 +2460,15 @@ 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; } @@ -2178,12 +2480,15 @@ 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; } @@ -2204,7 +2509,9 @@ 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); @@ -2219,7 +2526,8 @@ val_pb &= (~0x80); break; default: - return -EINVAL; + ret = -EINVAL; + goto unlock; } /* interface format */ @@ -2237,7 +2545,8 @@ val_pb |= 0x03; break; default: - return -EINVAL; + ret = -EINVAL; + goto unlock; } /* clock inversion */ @@ -2251,13 +2560,17 @@ 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, @@ -2268,7 +2581,9 @@ 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) { @@ -2282,7 +2597,8 @@ val &= (~0x04); break; default: - return -EINVAL; + ret = -EINVAL; + goto unlock; } switch (params_rate(params)) { @@ -2296,7 +2612,8 @@ /* TODO */ break; default: - return -EINVAL; + ret = -EINVAL; + goto unlock; } if (nvp6188->audio_out) { @@ -2313,7 +2630,8 @@ default: dev_err(&client->dev, "Invalid audio_out mclk_fs: %d\n", nvp6188->audio_out->mclk_fs); - return -EINVAL; + ret = -EINVAL; + goto unlock; } } @@ -2329,7 +2647,8 @@ val &= (~0x04); break; default: - return -EINVAL; + ret = -EINVAL; + goto unlock; } switch (params_rate(params)) { @@ -2343,7 +2662,8 @@ /* TODO */ break; default: - return -EINVAL; + ret = -EINVAL; + goto unlock; } if (nvp6188->audio_in) { @@ -2360,7 +2680,8 @@ 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); @@ -2376,12 +2697,16 @@ 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) @@ -2440,7 +2765,9 @@ 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); } @@ -2826,6 +3153,8 @@ pm_runtime_enable(dev); pm_runtime_idle(dev); + nvp6188_video_init(nvp6188); + return 0; err_clean_entity: @@ -2862,7 +3191,7 @@ 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) }; @@ -2883,7 +3212,7 @@ 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, @@ -2891,17 +3220,20 @@ .id_table = nvp6188_match_id, }; -static int __init sensor_mod_init(void) +int nvp6188_sensor_mod_init(void) { return i2c_add_driver(&nvp6188_i2c_driver); } + +#ifndef CONFIG_VIDEO_REVERSE_IMAGE +device_initcall_sync(nvp6188_sensor_mod_init); +#endif static void __exit sensor_mod_exit(void) { i2c_del_driver(&nvp6188_i2c_driver); } -device_initcall_sync(sensor_mod_init); module_exit(sensor_mod_exit); MODULE_AUTHOR("Vicent Chi <vicent.chi@rock-chips.com>"); -- Gitblit v1.6.2