Browse Source

添加7116h驱动,解决6752驱动上电随机卡死问题

huangliang 2 years ago
parent
commit
a25a576de8

+ 23 - 1
linux/arch/arm/boot/dts/ark1668e_devb.dts

@@ -5,6 +5,7 @@
 
 //#define I2S_FULL_DUPLEX_CODEC_SUPPORT
 //#define DYNAMIC_TRACK_DISPLAY
+#define DECODE_ARK7116
 
 / {
 	i2c-gpio-0 {
@@ -39,6 +40,7 @@
 		i2c-gpio,delay-us = <6>;	/* clk freq = 500/delay KHz */
 		i2c-gpio,scl-output-only;
 
+#ifdef DECODE_ARK7116
 		ark7116: ark7116@B2 {
 			compatible = "arkmicro,ark7116_1668e_devb";
 			reset-gpio = <&gportf 27 0>;
@@ -51,6 +53,20 @@
 				};
 			};
 		};
+#else
+		ark7116h: ark7116h@B2 {
+			compatible = "arkmicro,ark7116h_1668e_devb";
+			reset-gpio = <&gportf 27 0>;
+			reg = <0x59>; /* i2c address(7 bits) */
+			default-channel = <0>;
+			carback-config = <1>;
+			port {
+				ark7116h_0: endpoint@0{
+					remote-endpoint = <&itu_1>;
+				};
+			};
+		};
+#endif
 	
 		rn6752: da380@4e {
 			compatible = "arkmicro,ark1668e_rn6752";
@@ -284,11 +300,17 @@
 			remote-endpoint = <&rn6752_0>;
             channel = <0>;
 		};
-
+#ifdef DECODE_ARK7116
 		itu_1: endpoint@1 {
 			remote-endpoint = <&ark7116_0>;
 			channel = <1>;
 		};
+#else
+		itu_1: endpoint@1 {
+			remote-endpoint = <&ark7116h_0>;
+			channel = <1>;
+		};
+#endif
 	};
 };
 

+ 23 - 1
linux/arch/arm/boot/dts/ark1668e_devb_emmc.dts

@@ -5,6 +5,7 @@
 
 //#define I2S_FULL_DUPLEX_CODEC_SUPPORT
 //#define DYNAMIC_TRACK_DISPLAY
+#define DECODE_ARK7116
 
 / {
 	i2c-gpio-0 {
@@ -39,6 +40,7 @@
 		i2c-gpio,delay-us = <6>;	/* clk freq = 500/delay KHz */
 		i2c-gpio,scl-output-only;
 
+#ifdef DECODE_ARK7116
 		ark7116: ark7116@B2 {
 			compatible = "arkmicro,ark7116_1668e_devb";
 			reset-gpio = <&gportf 27 0>;
@@ -51,6 +53,20 @@
 				};
 			};
 		};
+#else
+		ark7116h: ark7116h@B2 {
+			compatible = "arkmicro,ark7116h_1668e_devb";
+			reset-gpio = <&gportf 27 0>;
+			reg = <0x59>; /* i2c address(7 bits) */
+			default-channel = <0>;
+			carback-config = <1>;
+			port {
+				ark7116h_0: endpoint@0{
+					remote-endpoint = <&itu_1>;
+				};
+			};
+		};
+#endif
 	
 		rn6752: da380@4e {
 			compatible = "arkmicro,ark1668e_rn6752";
@@ -284,11 +300,17 @@
 			remote-endpoint = <&rn6752_0>;
             channel = <0>;
 		};
-
+#ifdef DECODE_ARK7116
 		itu_1: endpoint@1 {
 			remote-endpoint = <&ark7116_0>;
 			channel = <1>;
 		};
+#else
+		itu_1: endpoint@1 {
+			remote-endpoint = <&ark7116h_0>;
+			channel = <1>;
+		};
+#endif
 	};
 };
 

+ 10 - 0
linux/drivers/media/i2c/Kconfig

@@ -1078,6 +1078,16 @@ config VIDEO_ARK7116
 	  To compile this driver as a module, choose M here: the
 	  module will be called ark7116.
 
+config VIDEO_ARK7116H
+	tristate "Arkmicro ark7116h video decoder"
+	depends on VIDEO_V4L2 && I2C
+	select V4L2_FWNODE
+	---help---
+	  Support for the Arkmicro ark7116h video decoder.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ark7116h.
+
 config VIDEO_RN6752
     tristate "Arkmicro rn6752 video decoder"
     depends on VIDEO_V4L2 && I2C

+ 1 - 0
linux/drivers/media/i2c/Makefile

@@ -109,6 +109,7 @@ obj-$(CONFIG_VIDEO_TC358743)	+= tc358743.o
 obj-$(CONFIG_VIDEO_IMX258)	+= imx258.o
 obj-$(CONFIG_VIDEO_IMX274)	+= imx274.o
 obj-$(CONFIG_VIDEO_ARK7116)	+= ark7116.o
+obj-$(CONFIG_VIDEO_ARK7116H)	+= ark7116h.o
 obj-$(CONFIG_VIDEO_RN6752) += rn6752.o
 obj-$(CONFIG_VIDEO_PR2000) += pr2000/
 obj-$(CONFIG_SDR_MAX2175) += max2175.o

+ 2 - 0
linux/drivers/media/i2c/ark7116.c

@@ -55,7 +55,9 @@ enum {
 enum {
 	TYPE_UNDEF = -1,
 	TYPE_ARK7116 = 0,
+	TYPE_ARK7116H,
 	TYPE_RN6752,
+	TYPE_PR2000,
 };
 
 typedef struct {

+ 963 - 0
linux/drivers/media/i2c/ark7116h.c

@@ -0,0 +1,963 @@
+/*
+ * ark7116h - Arkmicro ark7116h video decoder driver
+ *
+ * Copyright (c) 2020,2021 Arkmicro, Inc.
+ * This code is placed under the terms of the GNU General Public License v2
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/gpio/consumer.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+
+//#define ARK7116H_DUMP_REGS
+
+#define ARK7116H_STATUS			0xFD26
+#define ARK7116H_INPUT_CTL		0xFDD4
+#define ARK7116H_CONTRAST_CTL	0xFE53
+#define ARK7116H_BRIGHT_CTL		0xFE54
+#define ARK7116H_HUE_CTL	    0xFE55
+#define ARK7116H_SATURATION_CTL	0xFE56
+
+#define ARK7116H_AV0		0
+#define ARK7116H_AV1		1
+#define ARK7116H_AV2		2
+
+typedef enum {
+	 DISP_16_9 = 0,
+	 DISP_4_3,
+}ConfigDisplayMode;
+
+enum {
+	TYPE_UNKNOWN = -1,
+	TYPE_CVBS = 0,
+	TYPE_720P,
+	TYPE_1080P,
+};
+
+enum {
+	TYPE_UNDEF = -1,
+	TYPE_ARK7116 = 0,
+	TYPE_ARK7116H,
+	TYPE_RN6752,
+	TYPE_PR2000,
+};
+
+typedef struct {
+	unsigned int addr;
+	unsigned char value;
+} PanlstaticPara;
+
+typedef struct {
+    unsigned int addr;
+    unsigned char value[6];
+}PanlPosDynPara;
+
+PanlstaticPara AV1_staticPara[]=
+{
+//GLOBAL
+    {0XFB01,0X01}, 
+    {0XFB02,0X40}, 
+    {0XFB03,0X16}, 
+    {0XFB04,0X00}, 
+    {0XFB05,0X00}, 
+    {0XFB06,0XC0}, 
+    {0XFB07,0X00}, 
+    {0XFB08,0X04}, 
+    {0XFB09,0X04}, 
+    {0XFB0A,0X5C}, 
+    {0XFB0B,0XFF}, 
+    {0XFB0C,0XF2}, 
+    {0XFB0D,0XAA}, 
+    {0XFB0E,0XAA}, 
+    {0XFB0F,0X2A}, 
+    {0XFB10,0X01}, 
+    {0XFB11,0X02}, 
+    {0XFB12,0X02}, 
+    {0XFB13,0X28}, 
+    {0XFB14,0X7F}, 
+    {0XFB15,0X00}, 
+    {0XFB16,0X07}, 
+    {0XFB17,0X0C}, 
+    {0XFB18,0X0C}, 
+    {0XFB19,0X00}, 
+    {0XFB1A,0X00}, 
+    {0XFB1B,0X0C}, 
+    {0XFB1C,0X0C}, 
+    {0XFB1D,0X13}, 
+    {0XFB1E,0X2B}, 
+    {0XFB1F,0X12}, 
+    {0XFB20,0X80}, 
+    {0XFB21,0X00}, 
+    {0XFB22,0X00}, 
+    {0XFB23,0X2A}, 
+    {0XFB24,0X11}, 
+    {0XFB25,0XE8}, 
+    {0XFB26,0X03}, 
+    {0XFB27,0XFF}, 
+    {0XFB28,0X0C}, 
+    {0XFB29,0X95}, 
+    {0XFB2A,0X55}, 
+    {0XFB2B,0X55}, 
+    {0XFB2C,0XC0}, 
+    {0XFB2D,0X00}, 
+    {0XFB2E,0X55}, 
+    {0XFB2F,0X55}, 
+    {0XFB30,0X55}, 
+    {0XFB31,0X55}, 
+    {0XFB32,0X55}, 
+    {0XFB33,0XCC}, 
+    {0XFB34,0X1A}, 
+    {0XFB35,0X00}, 
+    {0XFB36,0X04}, 
+    {0XFB45,0XFF}, 
+    {0XFB43,0X60}, 
+    {0XFB37,0X8C}, 
+    {0XFB38,0X10}, 
+    {0XFB3D,0X8C}, 
+    {0XFB41,0X28}, 
+    {0XFB42,0X20}, 
+    {0XFB44,0X04}, 
+    {0XFB39,0X01}, 
+    {0XFB3A,0X01}, 
+    {0XFB3B,0X00}, 
+    {0XFB3C,0X20}, 
+    {0XFB3E,0X4C}, 
+    {0XFB3F,0X20}, 
+    {0XFB40,0X20}, 
+//DECODER
+    {0XFD01,0X04}, 
+    {0XFD02,0X00}, 
+    {0XFD03,0X80}, 
+    {0XFD04,0X80}, 
+    {0XFD05,0X30}, 
+    {0XFD06,0X02}, 
+    {0XFD07,0X80}, 
+    {0XFD08,0X00}, 
+    {0XFD09,0X00}, 
+    {0XFD0A,0X2F}, 
+    {0XFD0B,0X40}, 
+    {0XFD0C,0X12}, 
+    {0XFD0D,0X03}, 
+    {0XFD0E,0X72}, 
+    {0XFD0F,0X07}, 
+    {0XFD10,0X14}, 
+    {0XFD11,0X09}, 
+    {0XFD12,0X00}, 
+    {0XFD13,0X1E}, 
+    {0XFD14,0X22}, 
+    {0XFD15,0X05}, 
+    {0XFD26,0X0E}, 
+    {0XFD27,0X00}, 
+    {0XFD28,0X00}, 
+    {0XFD2A,0X01}, 
+    {0XFD35,0XAA}, 
+    {0XFD36,0XAA}, 
+    {0XFD37,0X60}, 
+    {0XFD38,0X0F}, 
+    {0XFD39,0X08}, 
+    {0XFD48,0X07}, 
+    {0XFD54,0X40}, 
+    {0XFD55,0X8A}, 
+    {0XFD5F,0XC0}, 
+    {0XFD60,0X03}, 
+    {0XFD61,0X2D}, 
+    {0XFD62,0X41}, 
+    {0XFD63,0XC0}, 
+    {0XFD83,0X4F}, 
+    {0XFDA0,0X0E}, 
+    {0XFDAA,0X03}, 
+    {0XFDAB,0X15}, 
+    {0XFDAC,0X74}, 
+    {0XFDB1,0X02}, 
+    {0XFDB2,0X76}, 
+    {0XFDB5,0X6F}, 
+    {0XFDCA,0X4F}, 
+    {0XFDCD,0X32}, 
+    {0XFDD0,0X01}, 
+    {0XFDD1,0X19}, 
+    {0XFDD2,0X00}, 
+    {0XFDD3,0X00}, 
+    {0XFDD4,0X00}, 
+    {0XFDD5,0XB1}, 
+    {0XFDD6,0X08}, 
+    {0XFDD7,0XF7}, 
+    {0XFDD8,0XA3}, 
+    {0XFDD9,0X40}, 
+    {0XFDDA,0X29}, 
+    {0XFDDB,0X00}, 
+    {0XFDDC,0X00}, 
+    {0XFDDD,0X4C}, 
+    {0XFDDE,0X59}, 
+    {0XFDDF,0X53}, 
+    {0XFDE0,0X2E}, 
+    {0XFDE1,0X17}, 
+    {0XFDE2,0X00}, 
+    {0XFD4F,0X40}, 
+    {0XFD4F,0X40}, 
+    {0XFD50,0X42}, 
+    {0XFD31,0X20}, 
+    {0XFD52,0X70}, 
+    {0XFD4E,0X82}, 
+    {0XFD7B,0XE5}, 
+    {0XFD51,0X90}, 
+    {0XFD16,0X4E}, 
+    {0XFD98,0X0A}, 
+    {0XFD1B,0X22}, 
+    {0XFD1C,0X61}, 
+    {0XFD41,0X8A}, 
+    {0XFDCB,0X10}, 
+    {0XFD43,0X80}, 
+    {0XFD44,0X20}, 
+    {0XFD45,0X80}, 
+    {0XFD46,0X00}, 
+    {0XFD56,0X07}, 
+    {0XFD5D,0X03}, 
+    {0XFD19,0X82}, 
+    {0XFD1A,0X50}, 
+    {0XFD1D,0X70}, 
+    {0XFD8A,0X0A}, 
+    {0XFD8B,0X00}, 
+    {0XFDC8,0X00}, 
+    {0XFDC9,0X01}, 
+    {0XFDC6,0X00}, 
+    {0XFD80,0X50}, 
+    {0XFD7C,0X0A}, 
+    {0XFD7D,0XFA}, 
+    {0XFDB4,0XD2}, 
+//deinterlace
+    {0XFE00,0X10}, 
+    {0XFE01,0X00}, 
+    {0XFE02,0X42}, 
+    {0XFE03,0X0D}, 
+    {0XFE04,0X30}, 
+    {0XFE05,0X70}, 
+    {0XFE06,0X00}, 
+    {0XFE07,0X30}, 
+    {0XFE08,0X02}, 
+    {0XFE09,0X0B}, 
+    {0XFE0A,0X02}, 
+    {0XFE0B,0X00}, 
+    {0XFE0C,0X40}, 
+    {0XFE0D,0X00}, 
+    {0XFE0E,0X08}, 
+    {0XFE0F,0X00}, 
+    {0XFE10,0X00}, 
+    {0XFE11,0X00}, 
+    {0XFE12,0XA0}, 
+    {0XFE13,0XA0}, 
+    {0XFE14,0X10}, 
+    {0XFE15,0XA0}, 
+    {0XFE16,0X20}, 
+    {0XFE17,0X90}, 
+    {0XFE18,0XA0}, 
+    {0XFE19,0X60}, 
+    {0XFE1A,0X40}, 
+    {0XFE1B,0X04}, 
+    {0XFE1C,0X04}, 
+    {0XFE1D,0X00}, 
+    {0XFE1E,0X10}, 
+    {0XFE1F,0X22}, 
+    {0XFEE0,0X30}, 
+    {0XFEE1,0X00}, 
+    {0XFEE2,0X36}, 
+    {0XFE20,0XFF}, 
+    {0XFE21,0XFF}, 
+    {0XFE22,0XFF}, 
+    {0XFE23,0XFF}, 
+    {0XFE24,0XFF}, 
+    {0XFE25,0XFF}, 
+    {0XFE26,0XFF}, 
+//VP
+    {0XFE30,0X27}, 
+    {0XFE31,0X8F}, 
+    {0XFE32,0X10}, 
+    {0XFE33,0X10}, 
+    {0XFE34,0X10}, 
+    {0XFE35,0X60}, 
+    {0XFE36,0X10}, 
+    {0XFE37,0XD0}, 
+    {0XFE38,0X10}, 
+    {0XFE39,0X41}, 
+    {0XFE3A,0X20}, 
+    {0XFE3B,0X16}, 
+    {0XFE3C,0X20}, 
+    {0XFE3D,0X20}, 
+    {0XFE3E,0X20}, 
+    {0XFE3F,0X20}, 
+    {0XFE40,0X64}, 
+    {0XFE41,0X49}, 
+    {0XFE42,0XFF}, 
+    {0XFE43,0XFF}, 
+    {0XFE44,0XFF}, 
+    {0XFE45,0XFF}, 
+    {0XFE46,0XFF}, 
+    {0XFE47,0X4C}, 
+    {0XFE48,0X1A}, 
+    {0XFE49,0X15}, 
+    {0XFE4A,0X55}, 
+    {0XFE4B,0X80}, 
+    {0XFE4C,0X80}, 
+    {0XFE4D,0X00}, 
+    {0XFE4E,0X00}, 
+    {0XFE4F,0X80}, 
+    {0XFE50,0X80}, 
+    {0XFE51,0X0A}, 
+    {0XFE52,0X4F}, 
+    {0XFE53,0X80}, 
+    {0XFE54,0X7A}, 
+    {0XFE55,0X00}, 
+    {0XFE56,0X38}, 
+    {0XFE57,0X10}, 
+    {0XFE58,0X80}, 
+    {0XFE59,0X65}, 
+    {0XFE5A,0X00}, 
+    {0XFE5D,0XFF}, 
+    {0XFE5E,0XFF}, 
+    {0XFE5F,0XFF}, 
+    {0XFE60,0X3C}, 
+    {0XFE61,0XFF}, 
+    {0XFE62,0XFF}, 
+    {0XFE63,0XFF}, 
+    {0XFE64,0XFF}, 
+    {0XFE65,0XFF}, 
+    {0XFE66,0XFF}, 
+    {0XFE67,0X24}, 
+    {0XFE68,0XFF}, 
+    {0XFE69,0X20}, 
+    {0XFE6A,0X9F}, 
+    {0XFE70,0X42}, 
+    {0XFE71,0XE0}, 
+    {0XFE72,0XDE}, 
+    {0XFE73,0XE1}, 
+    {0XFE74,0XFD}, 
+    {0XFE75,0X2E}, 
+    {0XFE76,0XF0}, 
+    {0XFE77,0XDD}, 
+    {0XFE78,0XF0}, 
+    {0XFE79,0XFD}, 
+    {0XFE7A,0X33}, 
+    {0XFE7B,0X81}, 
+//vi_regfile
+    {0XFF01,0XFF}, 
+    {0XFF02,0XFF}, 
+    {0XFF03,0XFF}, 
+    {0XFF04,0XFF}, 
+    {0XFF05,0XFF}, 
+    {0XFF06,0XFF}, 
+    {0XFF07,0XFF}, 
+    {0XFF08,0XFF}, 
+    {0XFF09,0XFF}, 
+    {0XFF0A,0XFF}, 
+    {0XFF0B,0XFF}, 
+    {0XFF0C,0XFF}, 
+    {0XFF0D,0XFF}, 
+    {0XFF0E,0XFF}, 
+    {0XFF0F,0XFF}, 
+    {0XFF10,0XFF}, 
+    {0XFF11,0XFF}, 
+    {0XFF12,0XFF}, 
+    {0XFF13,0XFF}, 
+    {0XFF14,0XFF}, 
+    {0XFF15,0XFF}, 
+    {0XFF16,0XFF}, 
+    {0XFF17,0XFF}, 
+    {0XFF18,0XFF}, 
+    {0XFF19,0XFF}, 
+    {0XFF1A,0XFF}, 
+    {0XFF1B,0XFF}, 
+    {0XFF1C,0XFF}, 
+    {0XFF1D,0XFF}, 
+    {0XFF1E,0XFF}, 
+    {0XFF1F,0XFF}, 
+//scale
+    {0XFF20,0XC0}, 
+    {0XFF21,0X03}, 
+    {0XFF22,0XA0},      //B6 ok //debug scale
+    {0XFF23,0X03}, 
+    {0XFF24,0XEE}, 
+    {0XFF25,0X03}, 
+    {0XFF26,0X07}, 
+    {0XFF27,0X91}, 
+    {0XFF28,0X51}, 
+    {0XFF29,0X00}, 
+    {0XFF2A,0X03}, 
+    {0XFF2B,0X80}, 
+    {0XFF2C,0X02}, 
+    {0XFF2D,0XD0}, 
+    {0XFF2E,0X02}, 
+    {0XFF2F,0X40}, 
+    {0XFF30,0X02}, 
+    {0XFF31,0X02}, 
+    {0XFF32,0X00}, 
+    {0XFF33,0X28}, 
+    {0XFF34,0X02}, 
+    {0XFF35,0X00}, 
+    {0XFF36,0X05}, 
+    {0XFF37,0X11}, 
+    {0XFF38,0X00}, 
+    {0XFF39,0X27}, 
+    {0XFF3A,0X03}, 
+    {0XFF3B,0X00}, 
+    {0XFF3C,0X00}, 
+    {0XFF3D,0X37}, 
+    {0XFF3E,0X02}, 
+    {0XFF3F,0X00}, 
+    {0XFF40,0X00}, 
+    {0XFF41,0X00}, 
+    {0XFF42,0X00}, 
+    {0XFF43,0X00}, 
+    {0XFF44,0X96}, 
+    {0XFF45,0X00}, 
+    {0XFF46,0X00}, 
+    {0XFF47,0X00}, 
+    {0XFF48,0X00}, 
+    {0XFF49,0X19}, 
+    {0XFF4A,0X00}, 
+    {0XFF4B,0XE9}, 
+    {0XFF4C,0X02}, 
+    {0XFF4D,0X09}, 
+    {0XFF4E,0X00}, 
+    {0XFF4F,0X49}, 
+    {0XFF50,0X02}, 
+    {0XFF51,0X45}, 
+    {0XFF52,0X00}, 
+    {0XFF53,0X15}, 
+    {0XFF54,0X03}, 
+    {0XFF55,0X07}, 
+    {0XFF56,0X00}, 
+    {0XFF57,0X47}, 
+    {0XFF58,0X02}, 
+    {0XFF59,0XFF}, 
+    {0XFF5A,0X03}, 
+    {0XFF5B,0XFF}, 
+    {0XFF5C,0XFD}, 
+    {0XFF5D,0XFF}, 
+    {0XFF68,0XFF}, 
+    {0XFF69,0XFD}, 
+    {0XFF6A,0XFF}, 
+    {0XFF6B,0XFD}, 
+    {0XFF6C,0XFD}, 
+    {0XFF6D,0XFF}, 
+    {0XFF6E,0XFD}, 
+    {0XFF6F,0XFD}, 
+//GAMMA
+    {0XFF80,0XC0}, 
+    {0XFF81,0X00}, 
+    {0XFF82,0X00}, 
+    {0XFF83,0X03}, 
+    {0XFF84,0X05}, 
+    {0XFF85,0X0B}, 
+    {0XFF86,0X12}, 
+    {0XFF87,0X19}, 
+    {0XFF88,0X21}, 
+    {0XFF89,0X2A}, 
+    {0XFF8A,0X33}, 
+    {0XFF8B,0X3E}, 
+    {0XFF8C,0X48}, 
+    {0XFF8D,0X54}, 
+    {0XFF8E,0X5F}, 
+    {0XFF8F,0X6A}, 
+    {0XFF90,0X74}, 
+    {0XFF91,0X7F}, 
+    {0XFF92,0X89}, 
+    {0XFF93,0X93}, 
+    {0XFF94,0X9E}, 
+    {0XFF95,0XA9}, 
+    {0XFF96,0XB3}, 
+    {0XFF97,0XBD}, 
+    {0XFF98,0XC6}, 
+    {0XFF99,0XCE}, 
+    {0XFF9A,0XD5}, 
+    {0XFF9B,0XDC}, 
+    {0XFF9C,0XE1}, 
+    {0XFF9D,0XE7}, 
+    {0XFF9E,0XEB}, 
+    {0XFF9F,0XF0}, 
+    {0XFFA0,0XF4}, 
+    {0XFFA1,0XF8}, 
+//rgb_test_c
+    {0XFFA8,0XFB}, 
+    {0XFFA9,0X00}, 
+    {0XFFAA,0X00}, 
+    {0XFFAB,0X00}, 
+    {0XFFAC,0X00}, 
+    {0XFFAD,0X00}, 
+    {0XFFC0,0X00}, 
+    {0XFFC1,0X04}, 
+    {0XFFC2,0X4C}, 
+    {0XFFC3,0X02}, 
+    {0XFFC4,0X5A}, 
+    {0XFFC5,0X2C}, 
+    {0XFFC6,0X74}, 
+    {0XFFC7,0XDA}, 
+    {0XFFC8,0X5C}, 
+    {0XFFC9,0X10}, 
+    {0XFFCA,0X43}, 
+    {0XFFCB,0X6F}, 
+    {0XFFCC,0X60}, 
+    {0XFFCD,0X60}, 
+    {0XFFCE,0X60}, 
+    {0XFFCF,0X00}, 
+    {0XFFD0,0X7E}, 
+    {0XFFD1,0XEF}, 
+    {0XFFD2,0XFF}, 
+    {0XFFD3,0XFC}, 
+    {0XFFD4,0X4E}, 
+    {0XFFD5,0X22}, 
+    {0XFFD6,0XE9}, 
+    {0XFFD7,0X1B}, 
+    {0XFFD8,0X00}, 
+    {0XFFD9,0X00}, 
+    {0XFFDA,0X00}, 
+    {0XFFDB,0X00}, 
+    {0XFFDC,0X00}, 
+    {0XFFDD,0X00}, 
+    {0XFFE8,0X00}, 
+    {0XFFE9,0X4A}, 
+    {0XFFEA,0X04}, 
+    {0XFFEB,0X00}, 
+    {0XFFEC,0X00}, 
+    {0XFFED,0XFF}, 
+    {0XFFEE,0XFF}, 
+    {0XFFEF,0X00}, 
+};
+
+struct ark7116h {
+	struct v4l2_ctrl_handler hdl;
+	struct v4l2_subdev sd;
+	struct gpio_desc *reset_gpio;
+	u32 input;
+	u8 brightness;
+	u8 contrast;
+	u8 saturation;
+	u8 hue;
+	struct i2c_client	*client;
+	unsigned short default_addr;
+	PanlstaticPara *custom_para;
+};
+
+#define VIDIOC_GET_RESOLUTION  		_IOWR('V', BASE_VIDIOC_PRIVATE + 1, int)
+#define VIDIOC_GET_PROGRESSIVE  	_IOWR('V', BASE_VIDIOC_PRIVATE + 2, int)
+#define VIDIOC_GET_CHIPINFO  		_IOWR('V', BASE_VIDIOC_PRIVATE + 3, int)
+#define VIDIOC_GET_ITU601_ENABLE	_IOWR('V', BASE_VIDIOC_PRIVATE + 6, int)
+
+static inline struct ark7116h *to_ark7116h(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct ark7116h, sd);
+}
+
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+	return &container_of(ctrl->handler, struct ark7116h, hdl)->sd;
+}
+
+static unsigned char to_slave_addr(unsigned char addr)
+{
+	switch(addr) {
+	case 0XF9:
+	case 0XFD:
+		return 0xB4;
+    case 0XF3:
+		return 0xE6; 
+	case 0XFA:
+		return 0xBA; 	
+	case 0XFB:
+		return 0xB8;
+	case 0XFC:
+		return 0xB6;
+	case 0XFE:
+		return 0xB2;
+	case 0XFF:
+		return 0XB0;
+	case 0X00:
+		return 0xBE;
+	default:
+		return 0xBE;
+	}
+}
+
+static unsigned char amt_read_reg(struct ark7116h *decoder, unsigned int reg)
+{
+	struct v4l2_subdev *sd = &decoder->sd;
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int rc;
+
+	client->addr = to_slave_addr((reg >> 8) & 0xff) >> 1;
+	rc = i2c_smbus_read_byte_data(client, reg & 0xff);
+	client->addr = decoder->default_addr;
+	if (rc < 0) {
+		dev_err(sd->dev, "i2c i/o error: rc == %d\n", rc);
+		return rc;
+	}
+	dev_dbg(sd->dev, "ark7116h: read 0x%04x = %02x\n", reg, rc);
+
+	return rc;
+}
+
+static int amt_write_reg(struct ark7116h *decoder, unsigned int reg, unsigned char value)
+{
+	struct v4l2_subdev *sd = &decoder->sd;
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int rc;
+
+	client->addr = to_slave_addr((reg >> 8) & 0xff) >> 1;
+	rc = i2c_smbus_write_byte_data(client, reg & 0xff, value);
+	client->addr = decoder->default_addr;
+	if (rc < 0)
+		printk(KERN_ALERT "i2c i/o error: rc == %d\n", rc);
+
+#ifdef ARK7116H_DUMP_REGS
+	client->addr = to_slave_addr((reg >> 8) & 0xff) >> 1;
+	rc = i2c_smbus_read_byte_data(client, reg & 0xff);
+	client->addr = decoder->default_addr;
+    printk(KERN_ALERT "ark7116h: read 0x%04x = %02x\n", reg, rc);
+#endif
+
+	return rc;	
+}
+
+/****************************************************************************
+			I2C Client & Driver
+ ****************************************************************************/
+static int ark7116h_detect_signal(struct ark7116h *decoder)
+{
+	return (amt_read_reg(decoder, ARK7116H_STATUS) & 0x2) == 0x2;
+}
+
+static int ark7116h_select_input(struct ark7116h *decoder, u32 input)
+{
+	unsigned char val;
+
+	if (input > ARK7116H_AV2)
+		return -EINVAL;
+
+	if (input == ARK7116H_AV0)	
+		val = 0;
+	else if (input == ARK7116H_AV1)
+		val = 0x10;
+	else if (input == ARK7116H_AV2)
+		val = 0x30;
+
+	return amt_write_reg(decoder, ARK7116H_INPUT_CTL, val);
+}
+
+static int ark7116h_reset(struct ark7116h *decoder)
+{
+	gpiod_set_value_cansleep(decoder->reset_gpio, 0);
+    mdelay(1);
+    gpiod_set_value_cansleep(decoder->reset_gpio, 1);
+    mdelay(1);
+    gpiod_set_value_cansleep(decoder->reset_gpio, 0);
+    mdelay(10);
+
+	return 0;
+};
+
+static void ark7116h_config_common(struct ark7116h *decoder)
+{	
+	int i;
+	for (i = 0; i < sizeof(AV1_staticPara) / sizeof(AV1_staticPara[0]); i++)
+		amt_write_reg(decoder, AV1_staticPara[i].addr, AV1_staticPara[i].value);
+}
+
+static int _ark7116h_init(struct ark7116h *decoder)
+{
+	unsigned char val;
+    
+reinit:
+    ark7116h_reset(decoder);
+    //soft reset 7116h
+    amt_write_reg(decoder, 0xFB00, 0x5A);
+    mdelay(10);
+    amt_write_reg(decoder,0xC6, 0x40);
+    val = amt_read_reg(decoder, 0xFAC6);
+    val &= 0x80;
+    
+    if ( val != 0 ) {
+			goto reinit;
+    }
+
+	ark7116h_config_common(decoder);
+
+     //soft reset decoder
+    val = amt_read_reg(decoder,0xFDA0);
+    val |= 1;
+    amt_write_reg(decoder,0xFDA0, val);
+    mdelay(40);
+    val &= ~1;
+    amt_write_reg(decoder,0xFDA0, val);
+    mdelay(40);
+
+	ark7116h_select_input(decoder, decoder->input);
+
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+static int ark7116h_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd = to_sd(ctrl);
+    struct ark7116h *decoder = to_ark7116h(sd);
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		amt_write_reg(decoder, ARK7116H_BRIGHT_CTL, ctrl->val);
+		return 0;
+	case V4L2_CID_CONTRAST:
+		amt_write_reg(decoder, ARK7116H_CONTRAST_CTL, ctrl->val);
+		return 0;
+	case V4L2_CID_SATURATION:
+		amt_write_reg(decoder, ARK7116H_SATURATION_CTL, ctrl->val);
+		return 0;
+	case V4L2_CID_HUE:
+		amt_write_reg(decoder, ARK7116H_HUE_CTL, ctrl->val);
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static int ark7116h_g_input_status(struct v4l2_subdev *sd, u32 *status)
+{
+	struct ark7116h *decoder = to_ark7116h(sd);
+
+	if (status) {
+		*status = 0;
+		if (!ark7116h_detect_signal(decoder))
+			*status |= V4L2_IN_ST_NO_SIGNAL;
+	}
+
+	return 0;
+}
+
+static int ark7116h_s_routing(struct v4l2_subdev *sd, u32 input,
+			     u32 output, u32 config)
+{
+	struct ark7116h *decoder = to_ark7116h(sd);
+	ark7116h_select_input(decoder, input);
+	decoder->input = input;
+	return 0;
+}
+static int ark7116h_init(struct v4l2_subdev *sd, u32 val)
+{
+	struct ark7116h *decoder = to_ark7116h(sd);
+	int ret;
+	ret=_ark7116h_init(decoder);
+	if(ret){
+		printk(KERN_ALERT "_ark7116h_init error.\n");
+	}
+	return ret;
+}
+
+static long ark7116h_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
+{
+	int ret = 0;
+
+	switch (cmd) {
+	case VIDIOC_GET_RESOLUTION:
+	{
+		int* temp = (int *)arg;
+		*temp = TYPE_CVBS;
+		break;
+	}
+	case VIDIOC_GET_PROGRESSIVE:
+	{
+		int* temp = (int *)arg;
+		*temp = 1;
+		break;
+	}
+	case VIDIOC_GET_CHIPINFO:
+	{
+		int* temp = (int *)arg;
+		*temp = TYPE_ARK7116H;
+		break;
+	}
+	case VIDIOC_GET_ITU601_ENABLE:
+	{
+		int* temp = (int *)arg;
+		*temp = 1;
+		break;
+	}
+	default:
+		return -ENOIOCTLCMD;
+	}
+
+	return ret;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_ctrl_ops ark7116h_ctrl_ops = {
+	.s_ctrl = ark7116h_s_ctrl,
+};
+
+static const struct v4l2_subdev_video_ops ark7116h_video_ops = {
+	.g_input_status = ark7116h_g_input_status,
+	.s_routing = ark7116h_s_routing,
+};
+
+static const struct v4l2_subdev_core_ops ark7116h_core_ops = {
+	.init = ark7116h_init,
+	.ioctl = ark7116h_ioctl,
+};
+
+static const struct v4l2_subdev_ops ark7116h_ops = {
+	.core =  &ark7116h_core_ops,
+	.video = &ark7116h_video_ops,
+};
+
+static int ark7116h_parse_dt(struct ark7116h *decoder, struct device_node *np)
+{
+	int ret = 0;
+	int value;
+	if (of_property_read_u32(np, "default-channel", &decoder->input))
+		decoder->input = 0;
+	if(!of_property_read_u32(np, "carback-config", &value)) {
+		if(value == 1){
+			printk("Initialize in carback.\n");
+		}
+		else if(value == 0){
+			ret=_ark7116h_init(decoder);
+			if(ret){
+				printk(KERN_ALERT "_ark7116h_init error.\n");
+			}
+		}
+	}
+
+	return ret;
+}
+
+static int ark7116h_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	struct ark7116h *decoder;
+	struct v4l2_subdev *sd;
+	struct device_node *np = client->dev.of_node;
+	int res;
+
+	/* Check if the adapter supports the needed features */
+	if (!i2c_check_functionality(client->adapter,
+	     I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
+		return -EIO;
+
+	decoder = devm_kzalloc(&client->dev, sizeof(*decoder), GFP_KERNEL);
+	if (!decoder)
+		return -ENOMEM;
+	decoder->client = client;
+	decoder->default_addr = client->addr;
+	decoder->custom_para = (PanlstaticPara *)id->driver_data;
+	sd = &decoder->sd;
+	decoder->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset",
+						   GPIOD_OUT_HIGH);
+	if (IS_ERR(decoder->reset_gpio)) {
+		res = PTR_ERR(decoder->reset_gpio);
+		v4l_err(client, "request for reset pin failed: %d\n", res);
+		return res;
+	}
+
+	res = ark7116h_parse_dt(decoder, np);
+	if (res) {
+		dev_err(sd->dev, "DT parsing error: %d\n", res);
+		return res;
+	}
+
+	v4l2_i2c_subdev_init(sd, client, &ark7116h_ops);
+	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	v4l2_ctrl_handler_init(&decoder->hdl, 4);
+	v4l2_ctrl_new_std(&decoder->hdl, &ark7116h_ctrl_ops,
+			V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
+	v4l2_ctrl_new_std(&decoder->hdl, &ark7116h_ctrl_ops,
+			V4L2_CID_CONTRAST, 0, 255, 1, 128);
+	v4l2_ctrl_new_std(&decoder->hdl, &ark7116h_ctrl_ops,
+			V4L2_CID_SATURATION, 0, 255, 1, 128);
+	v4l2_ctrl_new_std(&decoder->hdl, &ark7116h_ctrl_ops,
+			V4L2_CID_HUE, -128, 127, 1, 0);
+	sd->ctrl_handler = &decoder->hdl;
+	if (decoder->hdl.error) {
+		res = decoder->hdl.error;
+		goto err;
+	}
+
+	res = v4l2_async_register_subdev(sd);
+	if (res < 0)
+		goto err;
+	
+	return 0;
+err:
+	v4l2_ctrl_handler_free(&decoder->hdl);
+	return res;
+	
+	printk("ark7116h_probe.\n");
+	
+	return 0;
+}
+
+static int ark7116h_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct ark7116h *decoder = to_ark7116h(sd);
+
+	dev_dbg(sd->dev, 
+		"ark7116h.c: removing ark7116h adapter on address 0x%x\n",
+		client->addr << 1);
+
+	v4l2_async_unregister_subdev(sd);
+	v4l2_ctrl_handler_free(&decoder->hdl);
+
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+/* the length of name must less than 20 */
+static const struct i2c_device_id ark7116h_id[] = {
+	{ "ark7116h_1668e_devb", NULL},
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ark7116h_id);
+
+#if IS_ENABLED(CONFIG_OF)
+static const struct of_device_id ark7116h_of_match[] = {
+	{ .compatible = "arkmicro,ark7116h_1668e_devb", },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, ark7116h_of_match);
+#endif
+
+static struct i2c_driver ark7116h_driver = {
+	.driver = {
+		.of_match_table = of_match_ptr(ark7116h_of_match),
+		.name	= "ark7116h",
+	},
+	.probe		= ark7116h_probe,
+	.remove		= ark7116h_remove,
+	.id_table	= ark7116h_id,
+};
+
+static int __init ark_7116h_init(void)
+{
+	return i2c_add_driver(&ark7116h_driver);
+}
+
+static void __exit ark_7116h_exit(void)
+{
+	i2c_del_driver(&ark7116h_driver);
+}
+
+device_initcall(ark_7116h_init);
+
+MODULE_AUTHOR("arkmicro");
+MODULE_DESCRIPTION("arkmicro 7116h decoder driver for v4l2");
+MODULE_LICENSE("GPL v2");

+ 4 - 1
linux/drivers/media/i2c/pr2000/pr2000.c

@@ -77,7 +77,10 @@ enum {
 };
 
 enum {
-	TYPE_UNDEF = 1,
+	TYPE_UNDEF = -1,
+	TYPE_ARK7116 = 0,
+	TYPE_ARK7116H,
+	TYPE_RN6752,
 	TYPE_PR2000,
 };
 

+ 8 - 3
linux/drivers/media/i2c/rn6752.c

@@ -67,6 +67,7 @@ static bool rn6752_dbg = false;
 #define VIDIOC_EXIT_CARBACK			_IOWR('V', BASE_VIDIOC_PRIVATE + 5, int)
 #define VIDIOC_GET_ITU601_ENABLE			_IOWR('V', BASE_VIDIOC_PRIVATE + 6, int)
 #define VIDIOC_SET_AVIN_MODE			_IOWR('V', BASE_VIDIOC_PRIVATE + 7, int)
+#define VIDIOC_ENABLE_TIME			_IOWR('V', BASE_VIDIOC_PRIVATE + 8, int)
 
 #define ARK_DVR_BRIGHTNESS_MASK		(1<<0)
 #define ARK_DVR_CONTRAST_MASK		(1<<1)
@@ -143,7 +144,9 @@ enum carback_camera_mode {
 enum {
 	TYPE_UNDEF = -1,
 	TYPE_ARK7116 = 0,
+	TYPE_ARK7116H,
 	TYPE_RN6752,
+	TYPE_PR2000,
 };
 
 const char rxchip_rn6752_cvbs_pal[] = {
@@ -2475,6 +2478,11 @@ static long rn6752_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
 		rn6752_reset(decoder);
 		break;
 	}
+    case VIDIOC_ENABLE_TIME:
+    {
+        mod_timer(&decoder->work_timer, jiffies +  msecs_to_jiffies(1));
+        break;
+    }
 	default:
 		return -ENOIOCTLCMD;
 	}
@@ -2525,7 +2533,6 @@ static int rn6752_parse_dt(struct rn6752 *decoder, struct device_node *np)
 		decoder->itu601in = 0;
 	}
 	
-	_rn6752_init(decoder);
 
 	return ret;
 }
@@ -2621,8 +2628,6 @@ static int rn6752_probe(struct i2c_client *client,
 	res = v4l2_async_register_subdev(sd);
 	if (res < 0)
 		goto err;
-
-	mod_timer(&decoder->work_timer, jiffies +  msecs_to_jiffies(1));
 	
 	return 0;
 err:

+ 13 - 2
linux/drivers/media/platform/arkmicro/ark1668e_vin.c

@@ -1203,7 +1203,10 @@ static void ark_vin_reg_init(struct dvr_dev *dvr_dev)
     vin_writel(ARK1668E_ITU656_SEP_MODE_SEL, val);
 
 	val = vin_readl(ARK1668E_ITU656_ENABLE_REG);
-    val = 0x0000200a;//0x0000600a;
+    if(g_ark1668e_vin->dvr_dev->chip_info == TYPE_ARK7116H)
+        val = 0x0000000a;//0x0000600a;
+    else
+        val = 0x0000200a;//0x0000600a;
     vin_writel(ARK1668E_ITU656_ENABLE_REG, val);
 
 	val = vin_readl(ARK1668E_ITU656_MIRR_SET);
@@ -1512,12 +1515,20 @@ static int vin_async_complete(struct v4l2_async_notifier *notifier)
 		printk(KERN_ALERT "decoder chip is rn6752\n");
 		ark_vin->dvr_dev->chip_info = TYPE_RN6752;
 		ark_vin->dvr_dev->framebuf_num = 8;
+        ret = v4l2_subdev_call(ark_vin->current_subdev->sd,core,ioctl,VIDIOC_ENABLE_TIME,0);
+        if(ret < 0){
+        printk(KERN_ALERT "%s %d: v4l2_subdev_call error \n",__FUNCTION__, __LINE__);
+        return ret;
+        }
 	}else if(chipinfo == TYPE_ARK7116){
 		printk(KERN_ALERT "decoder chip is ark7116\n");
 		ark_vin->dvr_dev->chip_info = TYPE_ARK7116;
+	}else if(chipinfo == TYPE_ARK7116H){
+		printk(KERN_ALERT "decoder chip is ark7116h\n");
+		ark_vin->dvr_dev->chip_info = TYPE_ARK7116H;
 	}else if(chipinfo == TYPE_PR2000){
 		printk(KERN_ALERT "decoder chip is pr2000\n");
-		ark_vin->dvr_dev->chip_info = TYPE_ARK7116;
+		ark_vin->dvr_dev->chip_info = TYPE_PR2000;
 	}else{
 		printk(KERN_ALERT "no find decoder chip info\n");
 	}

+ 2 - 0
linux/drivers/media/platform/arkmicro/ark1668e_vin.h

@@ -46,6 +46,7 @@
 #define VIDIOC_EXIT_CARBACK					_IOWR('V', BASE_VIDIOC_PRIVATE + 5, int)
 #define VIDIOC_GET_ITU601_ENABLE			_IOWR('V', BASE_VIDIOC_PRIVATE + 6, int)
 #define VIDIOC_SET_AVIN_MODE				_IOWR('V', BASE_VIDIOC_PRIVATE + 7, int)
+#define VIDIOC_ENABLE_TIME			        _IOWR('V', BASE_VIDIOC_PRIVATE + 8, int)
 
 #define TVOUT_LAYER			0
 #define DISPLAY_LAYER			1
@@ -103,6 +104,7 @@ enum itu656_mirror{
 enum {
 	TYPE_UNDEF = -1,
 	TYPE_ARK7116 = 0,
+	TYPE_ARK7116H,
 	TYPE_RN6752,
 	TYPE_PR2000,
 };

+ 7 - 0
linux/drivers/tty/serial/ark_mcu_serial.c

@@ -49,10 +49,14 @@ struct mcu_serial_info {
 extern int mcu_serial_send(const unsigned char *buf, int len);
 extern void mcu_serial_register_rev_handler(void (*handler)(unsigned char ch), struct work_struct *task);
 extern void mcu_serial_unregister_rev_handler(void);
+
+#ifdef CONFIG_ARK1668E_CARBACK
 extern void get_mcu_carback_data(unsigned char ch);
+#endif
 
 static struct mcu_serial_info *msinfo;
 
+#ifdef CONFIG_ARK1668E_CARBACK
 void ark_set_track_ready(void)
 {
 	msinfo->carback_ready = 1;
@@ -64,6 +68,7 @@ void ark_set_track_noready(void)
 	msinfo->carback_ready = 0;
 }
 EXPORT_SYMBOL(ark_set_track_noready);
+#endif
 
 static void mcu_serial_get_ch(unsigned char ch)
 {
@@ -73,8 +78,10 @@ static void mcu_serial_get_ch(unsigned char ch)
 	spin_lock_irqsave(&info->lock, flags);
 	//printk(KERN_ALERT "++++++ mcu_serial_get_ch rev ch = %d\n",ch);
 	info->rx_buf[info->rx_head] = ch;
+#ifdef CONFIG_ARK1668E_CARBACK
 	if(info->carback_ready)
 		get_mcu_carback_data(info->rx_buf[info->rx_head]);
+#endif
 	info->rx_head = (info->rx_head + 1) & (RX_BUF_SIZE - 1);
 	if (info->rx_head == info->rx_tail) {
 		printk("rev buf is full, lost ch.\n");