From ee930fffee469d076998274a2ca55e13dc1efb67 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Fri, 10 May 2024 08:50:54 +0000
Subject: [PATCH] enable tun/tap/iptables

---
 u-boot/drivers/video/drm/rockchip-inno-hdmi-phy.c |  426 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 421 insertions(+), 5 deletions(-)

diff --git a/u-boot/drivers/video/drm/rockchip-inno-hdmi-phy.c b/u-boot/drivers/video/drm/rockchip-inno-hdmi-phy.c
index 71c710f..1f60e1f 100644
--- a/u-boot/drivers/video/drm/rockchip-inno-hdmi-phy.c
+++ b/u-boot/drivers/video/drm/rockchip-inno-hdmi-phy.c
@@ -3,6 +3,7 @@
  * (C) Copyright 2008-2016 Fuzhou Rockchip Electronics Co., Ltd
  */
 
+#include <clk-uclass.h>
 #include <config.h>
 #include <common.h>
 #include <errno.h>
@@ -11,7 +12,9 @@
 #include <fdtdec.h>
 #include <fdt_support.h>
 #include <asm/unaligned.h>
+#include <asm/arch/clock.h>
 #include <dm/device.h>
+#include <dm/lists.h>
 #include <dm/read.h>
 #include <asm/io.h>
 #include <linux/list.h>
@@ -20,6 +23,7 @@
 
 #include "rockchip_display.h"
 #include "rockchip_crtc.h"
+#include "rockchip_connector.h"
 #include "rockchip_phy.h"
 
 #define INNO_HDMI_PHY_TIMEOUT_LOOP_COUNT	1000
@@ -145,7 +149,8 @@
 
 enum inno_hdmi_phy_type {
 	INNO_HDMI_PHY_RK3228,
-	INNO_HDMI_PHY_RK3328
+	INNO_HDMI_PHY_RK3328,
+	INNO_HDMI_PHY_RK3528
 };
 
 struct inno_hdmi_phy_drv_data;
@@ -214,6 +219,14 @@
 	const void *data;
 };
 
+struct clk_inno_hdmi {
+	struct udevice *dev;
+	ulong rate;
+};
+
+/* global variables are used to pass reource from phy drivers to clk driver */
+static struct inno_hdmi_phy *g_inno;
+
 static const struct pre_pll_config pre_pll_cfg_table[] = {
 	{ 27000000,  27000000, 1,  90, 3, 2, 2, 10, 3, 3, 4, 0, 0},
 	{ 27000000,  33750000, 1,  90, 1, 3, 3, 10, 3, 3, 4, 0, 0},
@@ -249,9 +262,13 @@
 	{33750000,  1, 10, 2, 4},
 	{74250000,  1, 40, 8, 1},
 	{74250000, 18, 80, 8, 2},
+	{74250000,  1, 20, 4, 8},
 	{148500000, 2, 40, 4, 3},
+	{148500000, 1, 10, 2, 8},
 	{297000000, 4, 40, 2, 3},
+	{297000000, 2, 20, 2, 8},
 	{594000000, 8, 40, 1, 3},
+	{594000000, 4, 20, 1, 8},
 	{     ~0UL, 0,  0, 0, 0}
 };
 
@@ -292,6 +309,30 @@
 		594000000, {
 			0x10, 0x1a, 0x1a, 0x1a, 0x07, 0x15, 0x08, 0x08, 0x08,
 			0x00, 0xac, 0xcc, 0xcc, 0xcc,
+		},
+	}, {
+		~0UL, {
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00,
+		},
+	}
+};
+
+static const struct phy_config rk3528_phy_cfg[] = {
+	/* tmdsclk bias-clk bias-data voltage-clk voltage-data pre-emphasis-data */
+	{	165000000, {
+			0x03, 0x04, 0x0c, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00,
+		},
+	}, {
+		340000000, {
+			0x03, 0x04, 0x0c, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00,
+		},
+	}, {
+		594000000, {
+			0x02, 0x08, 0x0d, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00,
 		},
 	}, {
 		~0UL, {
@@ -398,7 +439,11 @@
 
 static int inno_hdmi_phy_power_on(struct rockchip_phy *phy)
 {
+#ifdef CONFIG_SPL_BUILD
+	struct inno_hdmi_phy *inno = (struct inno_hdmi_phy *)phy->data;
+#else
 	struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
+#endif
 	const struct post_pll_config *cfg = post_pll_cfg_table;
 	const struct phy_config *phy_cfg = inno->plat_data->phy_cfg_table;
 	u32 tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, inno->pixclock);
@@ -420,6 +465,8 @@
 	else if (inno->plat_data->dev_type == INNO_HDMI_PHY_RK3228 &&
 		 tmdsclock <= 33750000)
 		chipversion = 4;
+	else if (inno->plat_data->dev_type == INNO_HDMI_PHY_RK3528)
+		chipversion = 8;
 
 	printf("tmdsclock = %d; chipversion = %d\n", tmdsclock, chipversion);
 
@@ -444,7 +491,11 @@
 
 static int inno_hdmi_phy_power_off(struct rockchip_phy *phy)
 {
+#ifdef CONFIG_SPL_BUILD
+	struct inno_hdmi_phy *inno = (struct inno_hdmi_phy *)phy->data;
+#else
 	struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
+#endif
 
 	if (inno->plat_data->ops->power_off)
 		inno->plat_data->ops->power_off(inno);
@@ -858,6 +909,229 @@
 	return rate;
 }
 
+static int
+inno_hdmi_phy_rk3528_power_on(struct inno_hdmi_phy *inno,
+			      const struct post_pll_config *cfg,
+			      const struct phy_config *phy_cfg)
+{
+	u32 val;
+	u64 temp;
+	u32 tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, inno->pixclock);
+
+	/* Power off post PLL */
+	inno_update_bits(inno, 0xaa, 1, 0);
+
+	val = cfg->prediv;
+	inno_write(inno, 0xab, val);
+
+	if (cfg->postdiv == 1) {
+		inno_write(inno, 0xad, 0x8);
+		inno_write(inno, 0xaa, 2);
+	} else {
+		val = (cfg->postdiv / 2) - 1;
+		inno_write(inno, 0xad, val);
+		inno_write(inno, 0xaa, 0x0e);
+	}
+
+	val = cfg->fbdiv & 0xff;
+	inno_write(inno, 0xac, val);
+	val = (cfg->fbdiv >> 8) & BIT(0);
+	inno_update_bits(inno, 0xad, BIT(4), val);
+
+	/* current bias clk/data 2 */
+	val = phy_cfg->regs[0] << 4 | phy_cfg->regs[1];
+	inno_write(inno, 0xbf, val);
+
+	/* current bias data 1/0 */
+	val = phy_cfg->regs[1] << 4 | phy_cfg->regs[1];
+	inno_write(inno, 0xc0, val);
+
+	/* output voltage */
+	inno_write(inno, 0xb5, phy_cfg->regs[2]);
+	inno_write(inno, 0xb6, phy_cfg->regs[3]);
+	inno_write(inno, 0xb7, phy_cfg->regs[3]);
+	inno_write(inno, 0xb8, phy_cfg->regs[3]);
+
+	/* pre-emphasis */
+	inno_write(inno, 0xbb, phy_cfg->regs[4]);
+	inno_write(inno, 0xbc, phy_cfg->regs[4]);
+	inno_write(inno, 0xbd, phy_cfg->regs[4]);
+
+	/* enable LDO */
+	inno_write(inno, 0xb4, 0x7);
+
+	/* enable serializer */
+	inno_write(inno, 0xbe, 0x70);
+
+	inno_write(inno, 0xb2, 0x0f);
+
+	for (val = 0; val < 5; val++) {
+		if (inno_read(inno, 0xaf) & 1)
+			break;
+		udelay(1000);
+	}
+	if (!(inno_read(inno, 0xaf) & 1)) {
+		dev_err(inno->dev, "HDMI PHY Post PLL unlock\n");
+		return -ETIMEDOUT;
+	}
+
+	/* set termination resistance */
+	if (phy_cfg->tmdsclock > 340000000) {
+		inno_write(inno, 0xc7, 0x76);
+		inno_write(inno, 0xc5, 0x83);
+		inno_write(inno, 0xc8, 0x00);
+		inno_write(inno, 0xc9, 0x2f);
+		inno_write(inno, 0xca, 0x2f);
+		inno_write(inno, 0xcb, 0x2f);
+	} else {
+		inno_write(inno, 0xc7, 0x76);
+		inno_write(inno, 0xc5, 0x83);
+		inno_write(inno, 0xc8, 0x00);
+		inno_write(inno, 0xc9, 0x0f);
+		inno_write(inno, 0xca, 0x0f);
+		inno_write(inno, 0xcb, 0x0f);
+	}
+
+
+	/* set TMDS sync detection counter length */
+	temp = 47520000000UL / tmdsclock;
+	inno_write(inno, 0xd8, (temp >> 8) & 0xff);
+	inno_write(inno, 0xd9, temp & 0xff);
+
+	if (phy_cfg->tmdsclock > 340000000)
+		mdelay(100);
+	/* set pdata_en to 0/1 */
+	inno_update_bits(inno, 0x02, 1, 0);
+	inno_update_bits(inno, 0x02, 1, 1);
+
+	/* Enable PHY IRQ */
+	inno_write(inno, 0x05, 0x22);
+	inno_write(inno, 0x07, 0x22);
+	inno_write(inno, 0xcc, 0x0f);
+
+	return 0;
+}
+
+static void inno_hdmi_phy_rk3528_power_off(struct inno_hdmi_phy *inno)
+{
+	/* Power off driver */
+	inno_write(inno, 0xb2, 0);
+	/* Power off band gap */
+	inno_update_bits(inno, 0xb0, 4, 0);
+	/* Power off post pll */
+	inno_update_bits(inno, 0xaa, 1, 1);
+
+	/* Disable PHY IRQ */
+	inno_write(inno, 0x05, 0);
+	inno_write(inno, 0x07, 0);
+}
+
+static void inno_hdmi_phy_rk3528_init(struct inno_hdmi_phy *inno)
+{
+	/*
+	 * Use phy internal register control
+	 * rxsense/poweron/pllpd/pdataen signal.
+	 */
+	inno_write(inno, 0x02, 0x81);
+}
+
+static int
+inno_hdmi_phy_rk3528_pre_pll_update(struct inno_hdmi_phy *inno,
+				    const struct pre_pll_config *cfg)
+{
+	u32 val;
+
+	inno_update_bits(inno, 0xb0, 4, 4);
+	inno_write(inno, 0xcc, 0x0f);
+
+	/* Power on PLL */
+	inno_update_bits(inno, 0xa0, 1, 0);
+	/* Configure pre-pll */
+	inno_update_bits(inno, 0xa0, 2, (cfg->vco_div_5_en & 1) << 1);
+	inno_write(inno, 0xa1, cfg->prediv);
+	if (cfg->fracdiv)
+		val = ((cfg->fbdiv >> 8) & 0x0f) | 0xc0;
+	else
+		val = ((cfg->fbdiv >> 8) & 0x0f) | 0xf0;
+	inno_write(inno, 0xa2, val);
+	inno_write(inno, 0xa3, cfg->fbdiv & 0xff);
+	val = (cfg->pclk_div_a & 0x1f) |
+	      ((cfg->pclk_div_b & 3) << 5);
+	inno_write(inno, 0xa5, val);
+	val = (cfg->pclk_div_d & 0x1f) |
+	      ((cfg->pclk_div_c & 3) << 5);
+	inno_write(inno, 0xa6, val);
+	val = ((cfg->tmds_div_a & 3) << 4) |
+	      ((cfg->tmds_div_b & 3) << 2) |
+	      (cfg->tmds_div_c & 3);
+	inno_write(inno, 0xa4, val);
+
+	if (cfg->fracdiv) {
+		val = cfg->fracdiv & 0xff;
+		inno_write(inno, 0xd3, val);
+		val = (cfg->fracdiv >> 8) & 0xff;
+		inno_write(inno, 0xd2, val);
+		val = (cfg->fracdiv >> 16) & 0xff;
+		inno_write(inno, 0xd1, val);
+	} else {
+		inno_write(inno, 0xd3, 0);
+		inno_write(inno, 0xd2, 0);
+		inno_write(inno, 0xd1, 0);
+	}
+
+	/* Wait for PLL lock */
+	for (val = 0; val < 5; val++) {
+		if (inno_read(inno, 0xa9) & 1)
+			break;
+		udelay(1000);
+	}
+	if (val == 5) {
+		dev_err(inno->dev, "Pre-PLL unlock\n");
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+static unsigned long
+inno_hdmi_rk3528_phy_pll_recalc_rate(struct inno_hdmi_phy *inno,
+				     unsigned long parent_rate)
+{
+	unsigned long frac;
+	u8 nd, no_a, no_b, no_d;
+	u16 nf;
+	u64 vco = parent_rate;
+
+	nd = inno_read(inno, 0xa1) & 0x3f;
+	nf = ((inno_read(inno, 0xa2) & 0x0f) << 8) | inno_read(inno, 0xa3);
+	vco *= nf;
+	if ((inno_read(inno, 0xa2) & 0x30) == 0) {
+		frac = inno_read(inno, 0xd3) |
+		       (inno_read(inno, 0xd2) << 8) |
+		       (inno_read(inno, 0xd1) << 16);
+		vco += DIV_ROUND_CLOSEST(parent_rate * frac, (1 << 24));
+	}
+	if (inno_read(inno, 0xa0) & 2) {
+		do_div(vco, nd * 5);
+	} else {
+		no_a = inno_read(inno, 0xa5) & 0x1f;
+		no_b = ((inno_read(inno, 0xa5) >> 5) & 7) + 2;
+		no_d = inno_read(inno, 0xa6) & 0x1f;
+		if (no_a == 1)
+			do_div(vco, nd * no_b * no_d * 2);
+		else
+			do_div(vco, nd * no_a * no_d * 2);
+	}
+
+	frac = vco;
+	inno->pixclock = DIV_ROUND_CLOSEST(frac, 1000) * 1000;
+
+	dev_dbg(inno->dev, "%s rate %lu\n", __func__, inno->pixclock);
+
+	return frac;
+}
+
+#ifndef CONFIG_SPL_BUILD
 #define PHY_TAB_LEN 60
 
 static
@@ -889,6 +1163,7 @@
 
 	return 0;
 }
+#endif
 
 static const struct inno_hdmi_phy_ops rk3228_hdmi_phy_ops = {
 	.init = inno_hdmi_phy_rk3228_init,
@@ -905,6 +1180,14 @@
 	.recalc_rate = inno_hdmi_3328_phy_pll_recalc_rate,
 };
 
+static const struct inno_hdmi_phy_ops rk3528_hdmi_phy_ops = {
+	.init = inno_hdmi_phy_rk3528_init,
+	.power_on = inno_hdmi_phy_rk3528_power_on,
+	.power_off = inno_hdmi_phy_rk3528_power_off,
+	.pre_pll_update = inno_hdmi_phy_rk3528_pre_pll_update,
+	.recalc_rate = inno_hdmi_rk3528_phy_pll_recalc_rate,
+};
+
 static const struct inno_hdmi_phy_drv_data rk3228_hdmi_phy_drv_data = {
 	.dev_type = INNO_HDMI_PHY_RK3228,
 	.ops = &rk3228_hdmi_phy_ops,
@@ -917,6 +1200,12 @@
 	.phy_cfg_table = rk3328_phy_cfg,
 };
 
+static const struct inno_hdmi_phy_drv_data rk3528_hdmi_phy_drv_data = {
+	.dev_type = INNO_HDMI_PHY_RK3528,
+	.ops = &rk3528_hdmi_phy_ops,
+	.phy_cfg_table = rk3528_phy_cfg,
+};
+
 static const struct rockchip_inno_data inno_hdmi_phy_of_match[] = {
 	{ .compatible = "rockchip,rk3228-hdmi-phy",
 	  .data = &rk3228_hdmi_phy_drv_data
@@ -924,26 +1213,41 @@
 	{ .compatible = "rockchip,rk3328-hdmi-phy",
 	  .data = &rk3328_hdmi_phy_drv_data
 	},
+	{ .compatible = "rockchip,rk3528-hdmi-phy",
+	  .data = &rk3528_hdmi_phy_drv_data
+	},
 	{}
 };
 
 static int inno_hdmi_phy_init(struct rockchip_phy *phy)
 {
+#ifdef CONFIG_SPL_BUILD
+	struct inno_hdmi_phy *inno = (struct inno_hdmi_phy *)phy->data;
+#else
 	struct udevice *dev = phy->dev;
 	struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
-	int i, val, phy_table_size, ret;
-	const char *name;
+	int val, phy_table_size, ret;
 	u32 *phy_config;
+#endif
+	int i;
+	const char *name;
 
-	inno->node = dev->node;
-
+#ifdef CONFIG_SPL_BUILD
+	inno->regs = (void *)RK3528_HDMIPHY_BASE;
+#else
 	inno->regs = dev_read_addr_ptr(dev);
+	inno->node = dev->node;
+#endif
 	if (!inno->regs) {
 		printf("%s: failed to get phy address\n", __func__);
 		return -ENOMEM;
 	}
 
+#ifdef CONFIG_SPL_BUILD
+	name = "rockchip,rk3528-hdmi-phy";
+#else
 	name = dev_read_string(dev, "compatible");
+#endif
 	for (i = 0; i < ARRAY_SIZE(inno_hdmi_phy_of_match); i++) {
 		if (!strcmp(name, inno_hdmi_phy_of_match[i].compatible)) {
 			inno->plat_data = inno_hdmi_phy_of_match[i].data;
@@ -951,6 +1255,7 @@
 		}
 	}
 
+#ifndef CONFIG_SPL_BUILD
 	dev_read_prop(dev, "rockchip,phy-table", &val);
 
 	if (val >= 0) {
@@ -986,6 +1291,7 @@
 	} else {
 		printf("use default hdmi phy table\n");
 	}
+#endif
 
 	if (i >= ARRAY_SIZE(inno_hdmi_phy_of_match))
 		return 0;
@@ -1002,8 +1308,16 @@
 static unsigned long inno_hdmi_phy_set_pll(struct rockchip_phy *phy,
 					   unsigned long rate)
 {
+#ifdef CONFIG_SPL_BUILD
+	struct inno_hdmi_phy *inno = (struct inno_hdmi_phy *)phy->data;
+#else
 	struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
+#endif
 
+#ifdef CONFIG_SPL_BUILD
+	if (!inno)
+		inno = g_inno;
+#endif
 	inno_hdmi_phy_clk_prepare(inno);
 	inno_hdmi_phy_clk_is_prepared(inno);
 	inno_hdmi_phy_clk_set_rate(inno, rate);
@@ -1013,7 +1327,11 @@
 static int
 inno_hdmi_phy_set_bus_width(struct rockchip_phy *phy, u32 bus_width)
 {
+#ifdef CONFIG_SPL_BUILD
+	struct inno_hdmi_phy *inno = (struct inno_hdmi_phy *)phy->data;
+#else
 	struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
+#endif
 
 	inno->bus_width = bus_width;
 
@@ -1023,7 +1341,11 @@
 static long
 inno_hdmi_phy_clk_round_rate(struct rockchip_phy *phy, unsigned long rate)
 {
+#ifdef CONFIG_SPL_BUILD
+	struct inno_hdmi_phy *inno = (struct inno_hdmi_phy *)phy->data;
+#else
 	struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
+#endif
 	int i;
 	const struct pre_pll_config *cfg = pre_pll_cfg_table;
 	u32 tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, rate);
@@ -1082,9 +1404,26 @@
 	 .compatible = "rockchip,rk3228-hdmi-phy",
 	 .data = (ulong)&inno_hdmi_phy_driver_data,
 	},
+	{
+	 .compatible = "rockchip,rk3528-hdmi-phy",
+	 .data = (ulong)&inno_hdmi_phy_driver_data,
+	},
 	{}
 };
 
+#ifdef CONFIG_SPL_BUILD
+int inno_spl_hdmi_phy_probe(struct display_state *state)
+{
+	struct inno_hdmi_phy *inno = malloc(sizeof(struct inno_hdmi_phy));
+
+	memset(inno, 0, sizeof(*inno));
+	g_inno = inno;
+
+	state->conn_state.connector->phy = &inno_hdmi_phy_driver_data;
+	state->conn_state.connector->phy->data = (void *)inno;
+	return 0;
+}
+#else
 static int inno_hdmi_phy_probe(struct udevice *dev)
 {
 	struct inno_hdmi_phy *inno = dev_get_priv(dev);
@@ -1094,6 +1433,32 @@
 	inno->dev = dev;
 	phy->dev = dev;
 
+	g_inno = inno;
+	dev->driver_data = (ulong)&inno_hdmi_phy_driver_data;
+	phy = &inno_hdmi_phy_driver_data;
+
+	return 0;
+}
+#endif
+
+static int rockchip_inno_phy_hdmi_bind(struct udevice *parent)
+{
+	struct udevice *child;
+	ofnode subnode;
+	int ret;
+
+	subnode = ofnode_find_subnode(parent->node, "clk-port");
+	if (!ofnode_valid(subnode)) {
+		printf("%s: no subnode for %s\n", __func__, parent->name);
+		return -ENXIO;
+	}
+
+	ret = device_bind_driver_to_node(parent, "clk_inno_hdmi", "inno_hdmi_pll_clk", subnode, &child);
+	if (ret) {
+		printf("%s: clk-port cannot bind its driver\n", __func__);
+		return ret;
+	}
+
 	return 0;
 }
 
@@ -1101,6 +1466,57 @@
 	.name = "inno_hdmi_phy",
 	.id = UCLASS_PHY,
 	.of_match = inno_hdmi_phy_ids,
+#ifndef CONFIG_SPL_BUILD
 	.probe = inno_hdmi_phy_probe,
+#endif
+	.bind = rockchip_inno_phy_hdmi_bind,
 	.priv_auto_alloc_size = sizeof(struct inno_hdmi_phy),
 };
+
+
+static ulong inno_hdmi_clk_get_rate(struct clk *clk)
+{
+	struct clk_inno_hdmi *priv = dev_get_priv(clk->dev);
+
+	return priv->rate;
+}
+
+static ulong inno_hdmi_clk_set_rate(struct clk *clk, ulong rate)
+{
+	struct clk_inno_hdmi *priv = dev_get_priv(clk->dev);
+	int ret;
+
+	inno_hdmi_phy_clk_prepare(g_inno);
+	inno_hdmi_phy_clk_is_prepared(g_inno);
+	ret = inno_hdmi_phy_clk_set_rate(g_inno, rate);
+	if (ret < 0) {
+		printf("inno hdmi set rate failed ret:%d\n", ret);
+		return ret;
+	}
+
+	priv->rate = g_inno->pixclock;
+
+	return priv->rate;
+}
+
+static const struct clk_ops inno_hdmi_clk_ops = {
+	.get_rate	= inno_hdmi_clk_get_rate,
+	.set_rate	= inno_hdmi_clk_set_rate,
+};
+
+static int inno_hdmi_clk_probe(struct udevice *dev)
+{
+	return 0;
+}
+
+/*
+ * In order for other display interfaces to use hdmiphy as source
+ * for dclk, hdmiphy must register a virtual clock driver
+ */
+U_BOOT_DRIVER(clk_inno_hdmi) = {
+	.name		= "clk_inno_hdmi",
+	.id		= UCLASS_CLK,
+	.priv_auto_alloc_size = sizeof(struct clk_inno_hdmi),
+	.ops		= &inno_hdmi_clk_ops,
+	.probe		= inno_hdmi_clk_probe,
+};

--
Gitblit v1.6.2