diff mbox

[U-Boot,V2,05/10] video: Add driver for Parade PS8625 dP to LVDS bridge

Message ID 1403769668-2026-6-git-send-email-ajaykumar.rs@samsung.com
State Changes Requested
Delegated to: Minkyu Kang
Headers show

Commit Message

Ajay Kumar June 26, 2014, 8:01 a.m. UTC
From: Vadim Bendebury <vbendeb@chromium.org>

The initialization table comes from the "Illustration of I2C command
for initialing PS8625" document supplied by Parade.

Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
Signed-off-by: Ajay Kumar <ajaykumar.rs@samsung.com>
Acked-by: Simon Glass <sjg@chromium.org>
Tested-by: Simon Glass <sjg@chromium.org>
---
 drivers/video/Makefile |   1 +
 drivers/video/parade.c | 220 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/fdtdec.h       |   1 +
 lib/fdtdec.c           |   1 +
 4 files changed, 223 insertions(+)
 create mode 100644 drivers/video/parade.c

Comments

Wolfgang Denk June 26, 2014, 8:48 a.m. UTC | #1
Dear Ajay Kumar,

In message <1403769668-2026-6-git-send-email-ajaykumar.rs@samsung.com> you wrote:
...
> + * Use of this source code is governed by a BSD-style license that can be
> + * found in the LICENSE file.

NAK.  We need precise licnese terms; just mentioning some "LICENSE
file" without even telling us where to find it is definitely
insufficient.

Please also make sure to use SPDX tags instead.


Best regards,

Wolfgang Denk
diff mbox

Patch

diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 945f35d..8618590 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -41,3 +41,4 @@  obj-$(CONFIG_VIDEO_SMI_LYNXEM) += smiLynxEM.o videomodes.o
 obj-$(CONFIG_VIDEO_TEGRA) += tegra.o
 obj-$(CONFIG_VIDEO_VCXK) += bus_vcxk.o
 obj-$(CONFIG_FORMIKE) += formike.o
+obj-$(CONFIG_VIDEO_PARADE) += parade.o
diff --git a/drivers/video/parade.c b/drivers/video/parade.c
new file mode 100644
index 0000000..36e5d80
--- /dev/null
+++ b/drivers/video/parade.c
@@ -0,0 +1,220 @@ 
+/*
+ * Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/*
+ * This file is a driver for Parade dP<->LVDS bridges. The original submission
+ * is for the ps8625 chip.
+ */
+#include <config.h>
+#include <common.h>
+#include <i2c.h>
+#include <fdtdec.h>
+
+/*
+ * Initialization of the chip is a process of writing certaing values into
+ * certain registers over i2c bus. The chip in fact responds to a range of
+ * addresses on the i2c bus, so for each written value three parameters are
+ * required: i2c address, register address and the actual value.
+ *
+ * The base address is derived from the device tree, only address offset is
+ * stored in the table below.
+ */
+/**
+ * struct reg_data() - data for a parade register write
+ *
+ * @addr_off        offset from the i2c base address for parade
+ * @reg_addr        register address to write
+ * @value           value to be written
+ */
+struct reg_data {
+	uint8_t addr_off;
+	uint8_t reg;
+	uint8_t value;
+} _packed;
+
+#define END_OF_TABLE 0xff /* Ficticious offset */
+
+static const struct reg_data parade_values[] = {
+	{0x02, 0xa1, 0x01},  /* HPD low */
+	 /*
+	  * SW setting
+	  * [1:0] SW output 1.2V voltage is lower to 96%
+	  */
+	{0x04, 0x14, 0x01},
+	 /*
+	  * RCO SS setting
+	  * [5:4] = b01 0.5%, b10 1%, b11 1.5%
+	  */
+	{0x04, 0xe3, 0x20},
+	{0x04, 0xe2, 0x80}, /* [7] RCO SS enable */
+	 /*
+	  *  RPHY Setting
+	  * [3:2] CDR tune wait cycle before
+	  * measure for fine tune b00: 1us,
+	  * 01: 0.5us, 10:2us, 11:4us.
+	  */
+	{0x04, 0x8a, 0x0c},
+	{0x04, 0x89, 0x08}, /* [3] RFD always on */
+	 /*
+	  * CTN lock in/out:
+	  * 20000ppm/80000ppm. Lock out 2
+	  * times.
+	  */
+	{0x04, 0x71, 0x2d},
+	 /*
+	  * 2.7G CDR settings
+	  * NOF=40LSB for HBR CDR setting
+	  */
+	{0x04, 0x7d, 0x07},
+	{0x04, 0x7b, 0x00},  /* [1:0] Fmin=+4bands */
+	{0x04, 0x7a, 0xfd},  /* [7:5] DCO_FTRNG=+-40% */
+	 /*
+	  * 1.62G CDR settings
+	  * [5:2]NOF=64LSB [1:0]DCO scale is 2/5
+	  */
+	{0x04, 0xc0, 0x12},
+	{0x04, 0xc1, 0x92},  /* Gitune=-37% */
+	{0x04, 0xc2, 0x1c},  /* Fbstep=100% */
+	{0x04, 0x32, 0x80},  /* [7] LOS signal disable */
+	 /*
+	  * RPIO Setting
+	  * [7:4] LVDS driver bias current :
+	  * 75% (250mV swing)
+	  */
+	{0x04, 0x00, 0xb0},
+	 /*
+	  * [7:6] Right-bar GPIO output strength is 8mA
+	  */
+	{0x04, 0x15, 0x40},
+	 /* EQ Training State Machine Setting */
+	{0x04, 0x54, 0x10},  /* RCO calibration start */
+	 /* [4:0] MAX_LANE_COUNT set to one lane */
+	{0x01, 0x02, 0x81},
+	 /* [4:0] LANE_COUNT_SET set to one lane */
+	{0x01, 0x21, 0x81},
+	{0x00, 0x52, 0x20},
+	{0x00, 0xf1, 0x03},  /* HPD CP toggle enable */
+	{0x00, 0x62, 0x41},
+	 /* Counter number, add 1ms counter delay */
+	{0x00, 0xf6, 0x01},
+	 /*
+	  * [6]PWM function control by
+	  * DPCD0040f[7], default is PWM
+	  * block always works.
+	  */
+	{0x00, 0x77, 0x06},
+	 /*
+	  * 04h Adjust VTotal tolerance to
+	  * fix the 30Hz no display issue
+	  */
+	{0x00, 0x4c, 0x04},
+	 /* DPCD00400='h00, Parade OUI = 'h001cf8 */
+	{0x01, 0xc0, 0x00},
+	{0x01, 0xc1, 0x1c},  /* DPCD00401='h1c */
+	{0x01, 0xc2, 0xf8},  /* DPCD00402='hf8 */
+	 /*
+	  * DPCD403~408 = ASCII code
+	  * D2SLV5='h4432534c5635
+	  */
+	{0x01, 0xc3, 0x44},
+	{0x01, 0xc4, 0x32},  /* DPCD404 */
+	{0x01, 0xc5, 0x53},  /* DPCD405 */
+	{0x01, 0xc6, 0x4c},  /* DPCD406 */
+	{0x01, 0xc7, 0x56},  /* DPCD407 */
+	{0x01, 0xc8, 0x35},  /* DPCD408 */
+	 /*
+	  * DPCD40A, Initial Code major  revision
+	  * '01'
+	  */
+	{0x01, 0xca, 0x01},
+	 /* DPCD40B, Initial Code minor revision '05' */
+	{0x01, 0xcb, 0x05},
+	 /* DPCD720, Select internal PWM */
+	{0x01, 0xa5, 0xa0},
+	 /*
+	  * FFh for 100% PWM of brightness, 0h for 0%
+	  * brightness
+	  */
+	{0x01, 0xa7, 0xff},
+	 /*
+	  * Set LVDS output as 6bit-VESA mapping,
+	  * single LVDS channel
+	  */
+	{0x01, 0xcc, 0x13},
+	 /* Enable SSC set by register */
+	{0x02, 0xb1, 0x20},
+	 /*
+	  * Set SSC enabled and +/-1% central
+	  * spreading
+	  */
+	{0x04, 0x10, 0x16},
+	 /* MPU Clock source: LC => RCO */
+	{0x04, 0x59, 0x60},
+	{0x04, 0x54, 0x14},  /* LC -> RCO */
+	{0x02, 0xa1, 0x91},  /* HPD high */
+	{END_OF_TABLE}
+};
+
+/**
+ * Write values table into the Parade eDP bridge
+ *
+ * @return      0 on success, non-0 on failure
+ */
+
+static int parade_write_regs(int base_addr, const struct reg_data *table)
+{
+	int ret = 0;
+
+	while (!ret && (table->addr_off != END_OF_TABLE)) {
+		ret = i2c_write(base_addr + table->addr_off,
+				table->reg, 1,
+				(uint8_t *)&table->value,
+				sizeof(table->value));
+		table++;
+	}
+	return ret;
+}
+
+int parade_init(const void *blob)
+{
+	int bus, old_bus;
+	int parent;
+	int node;
+	int addr;
+	int ret;
+
+	node = fdtdec_next_compatible(blob, 0, COMPAT_PARADE_PS8625);
+	if (node < 0)
+		return 0;
+
+	parent = fdt_parent_offset(blob, node);
+	if (parent < 0) {
+		debug("%s: Could not find parent i2c node\n", __func__);
+		return -1;
+	}
+	addr = fdtdec_get_int(blob, node, "reg", -1);
+	if (addr < 0) {
+		debug("%s: Could not find i2c address\n", __func__);
+		return -1;
+	}
+
+	bus = i2c_get_bus_num_fdt(parent);
+	old_bus = i2c_get_bus_num();
+
+	debug("%s: Using i2c bus %d\n", __func__, bus);
+
+	/*
+	 * TODO(sjg@chromium.org): Hmmm we seem to need some sort of delay
+	 * here.
+	 */
+	mdelay(40);
+	i2c_set_bus_num(bus);
+	ret = parade_write_regs(addr, parade_values);
+
+	i2c_set_bus_num(old_bus);
+
+	return ret;
+}
diff --git a/include/fdtdec.h b/include/fdtdec.h
index a583d68..d4284bb 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -95,6 +95,7 @@  enum fdt_compat_id {
 	COMPAT_TI_TPS65090,		/* Texas Instrument TPS65090 */
 	COMPAT_NXP_PTN3460,		/* NXP PTN3460 DP/LVDS bridge */
 	COMPAT_SAMSUNG_EXYNOS_SYSMMU,	/* Exynos sysmmu */
+	COMPAT_PARADE_PS8625,		/* Parade PS8622 EDP->LVDS bridge */
 
 	COMPAT_COUNT,
 };
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 1ccfb39..c7c4854 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -69,6 +69,7 @@  static const char * const compat_names[COMPAT_COUNT] = {
 	COMPAT(TI_TPS65090, "ti,tps65090"),
 	COMPAT(COMPAT_NXP_PTN3460, "nxp,ptn3460"),
 	COMPAT(SAMSUNG_EXYNOS_SYSMMU, "samsung,sysmmu-v3.3"),
+	COMPAT(PARADE_PS8625, "parade,ps8625"),
 };
 
 const char *fdtdec_get_compatible(enum fdt_compat_id id)