Linux Framebuffer Layer development
 help / color / mirror / Atom feed
* Re: [PATCH 0/4] SiI9022 HDMI encoder for AM4xxx boards
From: Arnaud Patard @ 2014-07-03 14:34 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1404394800-18138-1-git-send-email-tomi.valkeinen@ti.com>

Tomi Valkeinen <tomi.valkeinen@ti.com> writes:

> Hi,

Hi,

>
> This series adds a driver for SiI9022 HDMI encoder, which is used on AM437x GP
> and AM43x EPOS boards.
>
> The series is based on the OMAPDSS HDMI infoframe series sent earlier, as the
> SiI9022 driver uses the new infoframe support.

Is there any small possibility to not make it an omap specific driver?
There are other boards with sii9022 out there. imx5x dev boards could
receive a daughter board with this chip (both sold by Freescale) and
efikamx platform has it too. I think that some old msm platforms has it
too.
I've not compared the code of the drivers and don't know how the sii9022
works but would be annoying to have 2 or more drivers for the same piece
of HW. imho, it would be nice if it could be avoided.

Thanks,
Arnaud

^ permalink raw reply

* [PATCH] video: da8xx-fb: preserve display width when changing HSYNC
From: Ian Abbott @ 2014-07-03 13:46 UTC (permalink / raw)
  To: linux-fbdev
  Cc: Jean-Christophe Plagniol-Villard, Tomi Valkeinen, linux-kernel,
	Ian Abbott

When looking at this driver for a client, I noticed the code that
configures the HSYNC pulse clobbers the display width in the same
register.  It only preserves the MS part of the width in bit 3 and zeros
the LS part of the width in bits 9 to 4.  This doesn't matter during
initialization as the width is configured afterwards, but subsequent use
of the FBIPUT_HSYNC ioctl would clobber the width.

Preserve bits 9 to 0 of LCD_RASTER_TIMING_0_REG when configuring the
horizontal sync.

Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
---
I haven't tested this change, but it's pretty trivial.
---
 drivers/video/fbdev/da8xx-fb.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/video/fbdev/da8xx-fb.c b/drivers/video/fbdev/da8xx-fb.c
index 788f6b3..10c876c 100644
--- a/drivers/video/fbdev/da8xx-fb.c
+++ b/drivers/video/fbdev/da8xx-fb.c
@@ -419,7 +419,7 @@ static void lcd_cfg_horizontal_sync(int back_porch, int pulse_width,
 {
 	u32 reg;
 
-	reg = lcdc_read(LCD_RASTER_TIMING_0_REG) & 0xf;
+	reg = lcdc_read(LCD_RASTER_TIMING_0_REG) & 0x3ff;
 	reg |= (((back_porch-1) & 0xff) << 24)
 	    | (((front_porch-1) & 0xff) << 16)
 	    | (((pulse_width-1) & 0x3f) << 10);
-- 
2.0.0


^ permalink raw reply related

* [PATCH 4/4] arm/dts: am437x GP HDMI support
From: Tomi Valkeinen @ 2014-07-03 13:40 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1404394800-18138-1-git-send-email-tomi.valkeinen@ti.com>

AM437x GP board has both LCD and HDMI outputs. The active display is
selected with a GPIO, which affects video and audio signal routing, and
LCD backlight.

Managing the gpio dynamically has proven rather difficult, so the
approach taken here is just to have two separate .dts files for LCD/HDMI
use cases. The HDMI dts file includes the base file, which has LCD
support, and overrides and adds the necessary items.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Cc: Tony Lindgren <tony@atomide.com>
---
 arch/arm/boot/dts/Makefile               |  3 +-
 arch/arm/boot/dts/am437x-gp-evm-hdmi.dts | 70 ++++++++++++++++++++++++++++++++
 2 files changed, 72 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/boot/dts/am437x-gp-evm-hdmi.dts

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 5a1fba6d10b5..3065fb2d113b 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -302,7 +302,8 @@ dtb-$(CONFIG_ARCH_OMAP4) += omap4-duovero-parlor.dtb \
 	omap4-var-stk-om44.dtb
 dtb-$(CONFIG_SOC_AM43XX) += am43x-epos-evm.dtb \
 	am437x-gp-evm.dtb \
-	am43x-epos-evm-hdmi.dtb
+	am43x-epos-evm-hdmi.dtb \
+	am437x-gp-evm-hdmi.dtb
 dtb-$(CONFIG_SOC_OMAP5) += omap5-cm-t54.dtb \
 	omap5-sbc-t54.dtb \
 	omap5-uevm.dtb
diff --git a/arch/arm/boot/dts/am437x-gp-evm-hdmi.dts b/arch/arm/boot/dts/am437x-gp-evm-hdmi.dts
new file mode 100644
index 000000000000..9380a422227b
--- /dev/null
+++ b/arch/arm/boot/dts/am437x-gp-evm-hdmi.dts
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* AM437x GP EVM with HDMI output */
+
+#include "am437x-gp-evm.dts"
+
+/ {
+	aliases {
+		display0 = &hdmi;
+	};
+
+	hdmi: connector {
+		compatible = "hdmi-connector";
+		label = "hdmi";
+
+		type = "b";
+
+		port {
+			hdmi_connector_in: endpoint {
+				remote-endpoint = <&sii9022_out>;
+			};
+		};
+	};
+};
+
+&i2c1 {
+	sii9022@3b {
+		compatible = "sil,sii9022";
+		reg = <0x3b>;
+
+		/* XXX 'SelLCDorHDMI' Gpio, LOW to select HDMI */
+		reset-gpios = <&gpio5 8 GPIO_ACTIVE_HIGH>;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+
+				sii9022_in: endpoint {
+					remote-endpoint = <&dpi_out>;
+				};
+			};
+
+			port@1 {
+				reg = <1>;
+
+				sii9022_out: endpoint {
+					remote-endpoint = <&hdmi_connector_in>;
+				};
+			};
+		};
+	};
+};
+
+&dss {
+	port {
+		dpi_out: endpoint@0 {
+			remote-endpoint = <&sii9022_in>;
+			data-lines = <24>;
+		};
+	};
+};
-- 
1.9.1


^ permalink raw reply related

* [PATCH 3/4] arm/dts: am43x EPOS HDMI support
From: Tomi Valkeinen @ 2014-07-03 13:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1404394800-18138-1-git-send-email-tomi.valkeinen@ti.com>

AM43x EPOS board has both LCD and HDMI outputs. The active display is
selected with a GPIO, which affects video and audio signal routing, and
LCD backlight.

Managing the gpio dynamically has proven rather difficult, so the
approach taken here is just to have two separate .dts files for LCD/HDMI
use cases. The HDMI dts file includes the base file, which has LCD
support, and overrides and adds the necessary items.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Cc: Tony Lindgren <tony@atomide.com>
---
 arch/arm/boot/dts/Makefile                |  3 +-
 arch/arm/boot/dts/am43x-epos-evm-hdmi.dts | 83 +++++++++++++++++++++++++++++++
 2 files changed, 85 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/boot/dts/am43x-epos-evm-hdmi.dts

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 5986ff63b901..5a1fba6d10b5 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -301,7 +301,8 @@ dtb-$(CONFIG_ARCH_OMAP4) += omap4-duovero-parlor.dtb \
 	omap4-var-dvk-om44.dtb \
 	omap4-var-stk-om44.dtb
 dtb-$(CONFIG_SOC_AM43XX) += am43x-epos-evm.dtb \
-	am437x-gp-evm.dtb
+	am437x-gp-evm.dtb \
+	am43x-epos-evm-hdmi.dtb
 dtb-$(CONFIG_SOC_OMAP5) += omap5-cm-t54.dtb \
 	omap5-sbc-t54.dtb \
 	omap5-uevm.dtb
diff --git a/arch/arm/boot/dts/am43x-epos-evm-hdmi.dts b/arch/arm/boot/dts/am43x-epos-evm-hdmi.dts
new file mode 100644
index 000000000000..9e52b220084d
--- /dev/null
+++ b/arch/arm/boot/dts/am43x-epos-evm-hdmi.dts
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* AM43x EPOS EVM with HDMI output */
+
+#include "am43x-epos-evm.dts"
+
+/ {
+	aliases {
+		display0 = &hdmi;
+	};
+
+	hdmi: connector {
+		compatible = "hdmi-connector";
+		label = "hdmi";
+
+		type = "b";
+
+		port {
+			hdmi_connector_in: endpoint {
+				remote-endpoint = <&sii9022_out>;
+			};
+		};
+	};
+};
+
+&am43xx_pinmux {
+	sii9022_pins: sii9022_pins {
+		pinctrl-single,pins = <
+			0x48 (PIN_INPUT | MUX_MODE7)	/* gpmc_a2.gpio1_18 */
+		>;
+	};
+};
+
+&i2c2 {
+	sii9022@3b {
+		compatible = "sil,sii9022";
+		reg = <0x3b>;
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&sii9022_pins>;
+
+		reset-gpio = <&gpio2 1 GPIO_ACTIVE_LOW>;/* 65'SelLCDorHDMI' Gpio, LOW to select HDMI */
+
+		interrupt-parent = <&gpio1>;
+		interrupts = <18 IRQ_TYPE_LEVEL_LOW>;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+
+				sii9022_in: endpoint {
+					remote-endpoint = <&dpi_out>;
+				};
+			};
+
+			port@1 {
+				reg = <1>;
+
+				sii9022_out: endpoint {
+					remote-endpoint = <&hdmi_connector_in>;
+				};
+			};
+		};
+	};
+};
+
+&dss {
+	port {
+		dpi_out: endpoint@0 {
+			remote-endpoint = <&sii9022_in>;
+			data-lines = <24>;
+		};
+	};
+};
-- 
1.9.1


^ permalink raw reply related

* [PATCH 2/4] Doc/DT: Add SiI9022 binding documentation
From: Tomi Valkeinen @ 2014-07-03 13:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1404394800-18138-1-git-send-email-tomi.valkeinen@ti.com>

Add DT binding documentation for Silicon Image SiI9022 HDMI encoder.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Cc: devicetree@vger.kernel.org
---
 .../devicetree/bindings/video/sil,sii9022.txt      | 53 ++++++++++++++++++++++
 1 file changed, 53 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/video/sil,sii9022.txt

diff --git a/Documentation/devicetree/bindings/video/sil,sii9022.txt b/Documentation/devicetree/bindings/video/sil,sii9022.txt
new file mode 100644
index 000000000000..0cd926636998
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/sil,sii9022.txt
@@ -0,0 +1,53 @@
+Silicon Image SiI9022 HDMI Encoder
+=================
+
+Silicon Image SiI9022 is an HDMI encoder that encodes parallel RGB
+signal to HDMI signal. The SiI9022 is controlled with i2c command, and
+it has a single reset pin and single interrupt pin.
+
+Required properties:
+- compatible: "sil,sii9022"
+
+Optional properties:
+- reset-gpio: reset gpio
+- interrupts: interrupt line
+
+Required nodes:
+- Video port 0 for parallel video input
+- Video port 1 for HDMI output
+
+Example
+-------
+
+&i2c2 {
+	sii9022: sii9022@3b {
+		compatible = "sil,sii9022";
+		reg = <0x3b>;
+
+		reset-gpio = <&gpio2 1 GPIO_ACTIVE_LOW>;
+
+		interrupt-parent = <&gpio1>;
+		interrupts = <18 IRQ_TYPE_LEVEL_LOW>;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+
+				sii9022_in: endpoint {
+					remote-endpoint = <&dpi_out>;
+				};
+			};
+
+			port@1 {
+				reg = <1>;
+
+				sii9022_out: endpoint {
+					remote-endpoint = <&hdmi_connector_in>;
+				};
+			};
+		};
+	};
+};
-- 
1.9.1


^ permalink raw reply related

* [PATCH 1/4] OMAPDSS: add SiI9022 encoder driver
From: Tomi Valkeinen @ 2014-07-03 13:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1404394800-18138-1-git-send-email-tomi.valkeinen@ti.com>

Add an OMAPDSS encoder driver for Silicon Image SiI9022 HDMI encoder.

The driver supports only video at the moment, audio support will be
added separately.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/video/fbdev/omap2/displays-new/Kconfig     |   8 +
 drivers/video/fbdev/omap2/displays-new/Makefile    |   1 +
 .../fbdev/omap2/displays-new/encoder-sii9022.c     | 966 +++++++++++++++++++++
 .../fbdev/omap2/displays-new/encoder-sii9022.h     |  58 ++
 4 files changed, 1033 insertions(+)
 create mode 100644 drivers/video/fbdev/omap2/displays-new/encoder-sii9022.c
 create mode 100644 drivers/video/fbdev/omap2/displays-new/encoder-sii9022.h

diff --git a/drivers/video/fbdev/omap2/displays-new/Kconfig b/drivers/video/fbdev/omap2/displays-new/Kconfig
index e6cfc38160d3..f0ca306edd25 100644
--- a/drivers/video/fbdev/omap2/displays-new/Kconfig
+++ b/drivers/video/fbdev/omap2/displays-new/Kconfig
@@ -12,6 +12,14 @@ config DISPLAY_ENCODER_TPD12S015
 	  Driver for TPD12S015, which offers HDMI ESD protection and level
 	  shifting.
 
+config DISPLAY_ENCODER_SII9022
+	tristate "SiI9022 HDMI Encoder"
+	depends on I2C
+	help
+	  Driver for Silicon Image SiI9022 HDMI encoder.
+	  A brief about SiI9022 can be found here:
+	  http://www.semiconductorstore.com/pdf/newsite/siliconimage/SiI9022a_pb.pdf
+
 config DISPLAY_CONNECTOR_DVI
         tristate "DVI Connector"
 	depends on I2C
diff --git a/drivers/video/fbdev/omap2/displays-new/Makefile b/drivers/video/fbdev/omap2/displays-new/Makefile
index 0323a8a1c682..f7f034b1c2b7 100644
--- a/drivers/video/fbdev/omap2/displays-new/Makefile
+++ b/drivers/video/fbdev/omap2/displays-new/Makefile
@@ -1,5 +1,6 @@
 obj-$(CONFIG_DISPLAY_ENCODER_TFP410) += encoder-tfp410.o
 obj-$(CONFIG_DISPLAY_ENCODER_TPD12S015) += encoder-tpd12s015.o
+obj-$(CONFIG_DISPLAY_ENCODER_SII9022) += encoder-sii9022.o
 obj-$(CONFIG_DISPLAY_CONNECTOR_DVI) += connector-dvi.o
 obj-$(CONFIG_DISPLAY_CONNECTOR_HDMI) += connector-hdmi.o
 obj-$(CONFIG_DISPLAY_CONNECTOR_ANALOG_TV) += connector-analog-tv.o
diff --git a/drivers/video/fbdev/omap2/displays-new/encoder-sii9022.c b/drivers/video/fbdev/omap2/displays-new/encoder-sii9022.c
new file mode 100644
index 000000000000..955beae57e71
--- /dev/null
+++ b/drivers/video/fbdev/omap2/displays-new/encoder-sii9022.c
@@ -0,0 +1,966 @@
+/*
+ * Silicon Image SiI9022 Encoder Driver
+ *
+ * Copyright (C) 2014 Texas Instruments
+ * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/of_gpio.h>
+#include <linux/workqueue.h>
+#include <linux/of_irq.h>
+#include <linux/hdmi.h>
+
+#include <video/omapdss.h>
+#include <video/omap-panel-data.h>
+
+#include <drm/drm_edid.h>
+
+#include "encoder-sii9022.h"
+
+static const struct regmap_config sii9022_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+};
+
+struct panel_drv_data {
+	struct omap_dss_device dssdev;
+	struct omap_dss_device *in;
+	struct i2c_client *i2c_client;
+	struct gpio_desc *reset_gpio;
+	struct regmap *regmap;
+	struct omap_video_timings timings;
+	struct delayed_work work;
+	struct mutex lock;
+
+	int irq;
+	bool use_polling;
+
+	bool htplg_state;
+	bool rxsense_state;
+
+	bool hdmi_mode;
+	struct hdmi_avi_infoframe frame;
+};
+
+#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
+
+static int sii9022_set_power_state(struct panel_drv_data *ddata,
+	enum sii9022_power_state state)
+{
+	unsigned pwr;
+	unsigned cold;
+	int r;
+
+	switch (state) {
+	case SII9022_POWER_STATE_D0:
+		pwr = 0;
+		cold = 0;
+		break;
+	case SII9022_POWER_STATE_D2:
+		pwr = 2;
+		cold = 0;
+		break;
+	case SII9022_POWER_STATE_D3_HOT:
+		pwr = 3;
+		cold = 0;
+		break;
+	case SII9022_POWER_STATE_D3_COLD:
+		pwr = 3;
+		cold = 1;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	r = regmap_update_bits(ddata->regmap, SII9022_POWER_STATE_CTRL_REG,
+		1 << 2, cold << 2);
+	if (r) {
+		dev_err(&ddata->i2c_client->dev, "failed to set hot/cold bit\n");
+		return r;
+	}
+
+	r = regmap_update_bits(ddata->regmap, SII9022_POWER_STATE_CTRL_REG,
+		0x3, pwr);
+	if (r) {
+		dev_err(&ddata->i2c_client->dev,
+			"failed to set power state to %d\n", pwr);
+		return r;
+	}
+
+	return 0;
+}
+
+static int sii9022_ddc_read(struct i2c_adapter *adapter,
+		unsigned char *buf, u16 count, u8 offset)
+{
+	int r, retries;
+
+	for (retries = 3; retries > 0; retries--) {
+		struct i2c_msg msgs[] = {
+			{
+				.addr   = HDMI_I2C_MONITOR_ADDRESS,
+				.flags  = 0,
+				.len    = 1,
+				.buf    = &offset,
+			}, {
+				.addr   = HDMI_I2C_MONITOR_ADDRESS,
+				.flags  = I2C_M_RD,
+				.len    = count,
+				.buf    = buf,
+			}
+		};
+
+		r = i2c_transfer(adapter, msgs, 2);
+		if (r = 2)
+			return 0;
+
+		if (r != -EAGAIN)
+			break;
+	}
+
+	return r < 0 ? r : -EIO;
+}
+
+static int sii9022_request_ddc_access(struct panel_drv_data *ddata,
+	unsigned *ctrl_reg)
+{
+	struct device *dev = &ddata->i2c_client->dev;
+	unsigned int val;
+	int r;
+	unsigned retries;
+
+	*ctrl_reg = 0;
+
+	/* Read TPI system control register*/
+	r = regmap_read(ddata->regmap, SII9022_SYS_CTRL_DATA_REG, &val);
+	if (r) {
+		dev_err(dev, "error reading DDC BUS REQUEST\n");
+		return r;
+	}
+
+	/* set SII9022_SYS_CTRL_DDC_BUS_REQUEST to request the DDC bus */
+	val |= SII9022_SYS_CTRL_DDC_BUS_REQUEST;
+
+	r = regmap_write(ddata->regmap, SII9022_SYS_CTRL_DATA_REG, val);
+	if (r) {
+		dev_err(dev, "error writing DDC BUS REQUEST\n");
+		return r;
+	}
+
+	/*  Poll for bus DDC Bus control to be granted */
+	retries = 0;
+	do {
+		r = regmap_read(ddata->regmap, SII9022_SYS_CTRL_DATA_REG, &val);
+		if (retries++ > 100)
+			return r;
+
+	} while ((val & SII9022_SYS_CTRL_DDC_BUS_GRANTED) = 0);
+
+	/*  Close the switch to the DDC */
+	val |= SII9022_SYS_CTRL_DDC_BUS_REQUEST |
+		SII9022_SYS_CTRL_DDC_BUS_GRANTED;
+	r = regmap_write(ddata->regmap, SII9022_SYS_CTRL_DATA_REG, val);
+	if (r) {
+		dev_err(dev, "error closing switch to DDC BUS REQUEST\n");
+		return r;
+	}
+
+	*ctrl_reg = val;
+
+	return 0;
+}
+
+static int sii9022_release_ddc_access(struct panel_drv_data *ddata,
+	unsigned ctrl_reg)
+{
+	struct device *dev = &ddata->i2c_client->dev;
+	unsigned int val;
+	int r;
+	unsigned retries;
+
+	val = ctrl_reg;
+	val &= ~(SII9022_SYS_CTRL_DDC_BUS_REQUEST |
+		SII9022_SYS_CTRL_DDC_BUS_GRANTED);
+
+	/* retry write until we can read the register, and the bits are 0 */
+	for (retries = 5; retries > 0; --retries) {
+		unsigned v;
+
+		/* ignore error, as the chip won't ACK this. */
+		regmap_write(ddata->regmap, SII9022_SYS_CTRL_DATA_REG, val);
+
+		r = regmap_read(ddata->regmap, SII9022_SYS_CTRL_DATA_REG, &v);
+		if (r)
+			continue;
+
+		if (v = val)
+			break;
+	}
+
+	if (retries = 0) {
+		dev_err(dev, "error releasing DDC Bus Access\n");
+		return r;
+	}
+
+	return 0;
+}
+
+static int sii9022_write_avi_infoframe(struct panel_drv_data *ddata)
+{
+	struct regmap *regmap = ddata->regmap;
+	u8 data[HDMI_INFOFRAME_SIZE(AVI)];
+	int r;
+
+	r = hdmi_avi_infoframe_pack(&ddata->frame, data, sizeof(data));
+	if (r < 0)
+		return r;
+
+	print_hex_dump_debug("AVI: ", DUMP_PREFIX_NONE, 16, 1, data,
+		HDMI_INFOFRAME_SIZE(AVI), false);
+
+	/* SiI9022 wants the checksum + the avi infoframe */
+	r = regmap_bulk_write(regmap, SII9022_AVI_INFOFRAME_BASE_REG,
+		&data[3], 1 + HDMI_AVI_INFOFRAME_SIZE);
+
+	return r;
+}
+
+static int sii9022_clear_avi_infoframe(struct panel_drv_data *ddata)
+{
+	struct regmap *regmap = ddata->regmap;
+	u8 data[1 + HDMI_AVI_INFOFRAME_SIZE] = { 0 };
+	int r;
+
+	r = regmap_bulk_write(regmap, SII9022_AVI_INFOFRAME_BASE_REG,
+		data, 1 + HDMI_AVI_INFOFRAME_SIZE);
+
+	return r;
+}
+
+static int sii9022_probe_chip_version(struct panel_drv_data *ddata)
+{
+	struct device *dev = &ddata->i2c_client->dev;
+	int r = 0;
+	unsigned id, rev, tpi_id;
+
+	r = regmap_read(ddata->regmap, SII9022_DEVICE_ID_REG, &id);
+	if (r) {
+		dev_err(dev, "failed to read device ID\n");
+		return r;
+	}
+
+	if (id != SII9022_ID_902xA) {
+		dev_err(dev, "unsupported device ID: 0x%x\n", id);
+		return -ENODEV;
+	}
+
+	r = regmap_read(ddata->regmap, SII9022_DEVICE_REV_ID_REG, &rev);
+	if (r) {
+		dev_err(dev, "failed to read device revision\n");
+		return r;
+	}
+
+	r = regmap_read(ddata->regmap, SII9022_DEVICE_TPI_ID_REG, &tpi_id);
+	if (r) {
+		dev_err(dev, "failed to read TPI ID\n");
+		return r;
+	}
+
+	dev_info(dev, "SiI902xA HDMI device %x, rev %x, tpi %x\n",
+		id, rev, tpi_id);
+
+	return r;
+}
+
+static int sii9022_enable_tpi(struct panel_drv_data *ddata)
+{
+	struct device *dev = &ddata->i2c_client->dev;
+	int r;
+
+	r = regmap_write(ddata->regmap, SII9022_TPI_RQB_REG, 0);
+	if (r) {
+		dev_err(dev, "failed to enable TPI commands\n");
+		return r;
+	}
+
+	return 0;
+}
+
+static int sii9022_enable_tmds(struct panel_drv_data *ddata, bool enable)
+{
+	struct regmap *regmap = ddata->regmap;
+	struct device *dev = &ddata->i2c_client->dev;
+	int r;
+
+	r = regmap_update_bits(regmap, SII9022_SYS_CTRL_DATA_REG,
+		1 << 4, (enable ? 0 : 1) << 4);
+	if (r) {
+		dev_err(dev, "failed to %s TMDS output\n",
+			enable ? "enable" : "disable");
+		return r;
+	}
+
+	return 0;
+}
+
+static int sii9022_setup_video(struct panel_drv_data *ddata,
+	struct omap_video_timings *timings)
+{
+	struct regmap *regmap = ddata->regmap;
+	struct device *dev = &ddata->i2c_client->dev;
+	int r;
+	unsigned pck = timings->pixelclock / 10000;
+	unsigned xres = timings->x_res;
+	unsigned yres = timings->y_res;
+	unsigned vfreq = 60;
+
+	u8 vals[] = {
+		pck & 0xff,
+		(pck & 0xff00) >> 8,
+		vfreq & 0xff,
+		(vfreq & 0xff00) >> 8,
+		(xres & 0xff),
+		(xres & 0xff00) >> 8,
+		(yres & 0xff),
+		(yres & 0xff00) >> 8,
+	};
+
+	r = regmap_bulk_write(regmap, SII9022_VIDEO_DATA_BASE_REG,
+		&vals, ARRAY_SIZE(vals));
+	if (r) {
+		dev_err(dev, "failed to write video mode config\n");
+		return r;
+	}
+
+	return 0;
+}
+
+static int sii9022_hw_enable(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct regmap *regmap = ddata->regmap;
+	struct device *dev = &ddata->i2c_client->dev;
+	int r;
+
+	/* make sure we're in D2 */
+	r = sii9022_set_power_state(ddata, SII9022_POWER_STATE_D2);
+	if (r)
+		return r;
+
+	r = sii9022_setup_video(ddata, &ddata->timings);
+	if (r)
+		return r;
+
+	/* configure input video format */
+	r = regmap_write(regmap, SII9022_AVI_IN_FORMAT_REG, 0);
+	if (r) {
+		dev_err(dev, "failed to set input format\n");
+		return r;
+	}
+
+	/* configure output video format */
+	r = regmap_write(regmap, SII9022_AVI_OUT_FORMAT_REG,
+		(1 << 4)); /* CONV_BT709 */
+	if (r) {
+		dev_err(dev, "failed to set output format\n");
+		return r;
+	}
+
+	if (ddata->hdmi_mode)
+		r = sii9022_write_avi_infoframe(ddata);
+	else
+		r = sii9022_clear_avi_infoframe(ddata);
+
+	if (r) {
+		dev_err(dev, "failed to write AVI infoframe\n");
+		return r;
+	}
+
+	/* select DVI / HDMI */
+	/* note: must be done before D0 */
+	r = regmap_update_bits(regmap, SII9022_SYS_CTRL_DATA_REG,
+		1 << 0, ddata->hdmi_mode ? 1 : 0); /* 0 = DVI, 1 = HDMI */
+	if (r) {
+		dev_err(dev, "failed to set DVI/HDMI mode\n");
+		return r;
+	}
+
+	/* power up transmitter */
+	r = sii9022_set_power_state(ddata, SII9022_POWER_STATE_D0);
+	if (r)
+		return r;
+
+	/* enable TMDS */
+	r = sii9022_enable_tmds(ddata, true);
+	if (r)
+		return r;
+
+	/* configure input bus and pixel repetition */
+	/* Note: must be done after enabling TMDS */
+	r = regmap_write(regmap, SII9022_PIXEL_REPETITION_REG,
+		(1 << 5) |	/* 24BIT */
+		(1 << 6)	/* CLK_RATIO_1X */
+		);
+	if (r) {
+		dev_err(dev, "failed to write pixel repetition reg\n");
+		return r;
+	}
+
+	return 0;
+}
+
+static int sii9022_hw_disable(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	int r;
+
+	sii9022_enable_tmds(ddata, false);
+
+	r = sii9022_set_power_state(ddata, SII9022_POWER_STATE_D2);
+	if (r)
+		return r;
+
+	return 0;
+}
+
+static void sii9022_handle_hpd(struct panel_drv_data *ddata)
+{
+	struct device *dev = &ddata->i2c_client->dev;
+	unsigned int stat;
+	int r;
+	bool htplg, rxsense;
+	bool htplg_ev, rxsense_ev;
+
+	htplg_ev = rxsense_ev = false;
+
+	r = regmap_read(ddata->regmap, SII9022_IRQ_STATUS_REG, &stat);
+
+	if (stat & 0x3) {
+		if (stat & 1)
+			htplg_ev = true;
+		if (stat & 2)
+			rxsense_ev = true;
+
+		regmap_write(ddata->regmap, SII9022_IRQ_STATUS_REG, 0x3);
+	}
+
+	htplg = stat & (1 << 2);
+	rxsense = stat & (1 << 3);
+
+	if (ddata->htplg_state != htplg || htplg_ev) {
+		dev_dbg(dev, "hotplug %sconnect\n", htplg ? "" : "dis");
+		ddata->htplg_state = htplg;
+	}
+
+	if (ddata->rxsense_state != rxsense || rxsense_ev) {
+		dev_dbg(dev, "rxsense %sconnect\n", rxsense ? "" : "dis");
+		ddata->rxsense_state = rxsense;
+	}
+}
+
+static irqreturn_t dispc_irq_handler(int irq, void *arg)
+{
+	struct panel_drv_data *ddata = arg;
+
+	mutex_lock(&ddata->lock);
+
+	sii9022_handle_hpd(ddata);
+
+	mutex_unlock(&ddata->lock);
+
+	return IRQ_HANDLED;
+}
+
+static void sii9022_poll(struct work_struct *work)
+{
+	struct panel_drv_data *ddata;
+
+	ddata = container_of(work, struct panel_drv_data, work.work);
+
+	mutex_lock(&ddata->lock);
+
+	sii9022_handle_hpd(ddata);
+
+	mutex_unlock(&ddata->lock);
+
+	schedule_delayed_work(&ddata->work, msecs_to_jiffies(250));
+}
+
+static int sii9022_connect(struct omap_dss_device *dssdev,
+		struct omap_dss_device *dst)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct device *dev = &ddata->i2c_client->dev;
+	struct omap_dss_device *in = ddata->in;
+	int r;
+
+	if (omapdss_device_is_connected(dssdev))
+		return -EBUSY;
+
+	r = in->ops.dpi->connect(in, dssdev);
+	if (r)
+		return r;
+
+	mutex_lock(&ddata->lock);
+
+	r = sii9022_set_power_state(ddata, SII9022_POWER_STATE_D2);
+	if (r)
+		goto err_pwr;
+
+	ddata->htplg_state = ddata->rxsense_state = false;
+
+	sii9022_handle_hpd(ddata);
+
+	regmap_write(ddata->regmap, SII9022_IRQ_ENABLE_REG, 0x3);
+
+	if (ddata->use_polling) {
+		INIT_DELAYED_WORK(&ddata->work, sii9022_poll);
+		schedule_delayed_work(&ddata->work, msecs_to_jiffies(250));
+	} else {
+		r = devm_request_threaded_irq(dev, ddata->irq,
+			NULL, dispc_irq_handler,
+			IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+			"sii9022 int", ddata);
+		if (r) {
+			dev_err(dev, "failed to request irq\n");
+			goto err_irq;
+		}
+	}
+
+	dst->src = dssdev;
+	dssdev->dst = dst;
+
+	mutex_unlock(&ddata->lock);
+
+	return 0;
+
+err_irq:
+err_pwr:
+	mutex_unlock(&ddata->lock);
+	in->ops.dpi->disconnect(in, dssdev);
+	return r;
+}
+
+static void sii9022_disconnect(struct omap_dss_device *dssdev,
+		struct omap_dss_device *dst)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct device *dev = &ddata->i2c_client->dev;
+	struct omap_dss_device *in = ddata->in;
+
+	WARN_ON(!omapdss_device_is_connected(dssdev));
+	if (!omapdss_device_is_connected(dssdev))
+		return;
+
+	WARN_ON(dst != dssdev->dst);
+	if (dst != dssdev->dst)
+		return;
+
+	if (ddata->use_polling)
+		cancel_delayed_work_sync(&ddata->work);
+	else
+		devm_free_irq(dev, ddata->irq, ddata);
+
+	dst->src = NULL;
+	dssdev->dst = NULL;
+
+	in->ops.dpi->disconnect(in, dssdev);
+}
+
+static int sii9022_enable(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+	int r;
+
+	if (!omapdss_device_is_connected(dssdev))
+		return -ENODEV;
+
+	if (omapdss_device_is_enabled(dssdev))
+		return 0;
+
+	in->ops.dpi->set_timings(in, &ddata->timings);
+
+	r = in->ops.dpi->enable(in);
+	if (r)
+		return r;
+
+	if (ddata->reset_gpio)
+		gpiod_set_value_cansleep(ddata->reset_gpio, 0);
+
+	mutex_lock(&ddata->lock);
+
+	r = sii9022_hw_enable(dssdev);
+	if (r)
+		goto err_hw_enable;
+
+	mutex_unlock(&ddata->lock);
+
+	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+	return 0;
+
+err_hw_enable:
+	mutex_unlock(&ddata->lock);
+
+	if (ddata->reset_gpio)
+		gpiod_set_value_cansleep(ddata->reset_gpio, 1);
+
+	in->ops.dpi->disable(in);
+
+	return r;
+}
+
+static void sii9022_disable(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	if (!omapdss_device_is_enabled(dssdev))
+		return;
+
+	mutex_lock(&ddata->lock);
+
+	sii9022_hw_disable(dssdev);
+
+	mutex_unlock(&ddata->lock);
+
+	if (ddata->reset_gpio)
+		gpiod_set_value_cansleep(ddata->reset_gpio, 1);
+
+	in->ops.dpi->disable(in);
+
+	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+}
+
+static void sii9022_set_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+	struct omap_video_timings t = *timings;
+
+	/* update DPI specific timing info */
+	t.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
+	t.de_level = OMAPDSS_SIG_ACTIVE_HIGH;
+	t.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
+
+	ddata->timings = t;
+	dssdev->panel.timings = t;
+
+	in->ops.dpi->set_timings(in, &t);
+}
+
+static void sii9022_get_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	*timings = ddata->timings;
+}
+
+static int sii9022_check_timings(struct omap_dss_device *dssdev,
+		struct omap_video_timings *timings)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct omap_dss_device *in = ddata->in;
+
+	/* update DPI specific timing info */
+	timings->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
+	timings->de_level = OMAPDSS_SIG_ACTIVE_HIGH;
+	timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
+
+	return in->ops.dpi->check_timings(in, timings);
+}
+
+static int sii9022_read_edid(struct omap_dss_device *dssdev,
+		u8 *edid, int len)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct i2c_client *client = ddata->i2c_client;
+	unsigned ctrl_reg;
+	int r, l, bytes_read;
+
+	mutex_lock(&ddata->lock);
+
+	if (ddata->use_polling)
+		sii9022_handle_hpd(ddata);
+
+	if (ddata->htplg_state = false) {
+		r = -ENODEV;
+		goto err_hpd;
+	}
+
+	r = sii9022_request_ddc_access(ddata, &ctrl_reg);
+	if (r)
+		goto err_ddc_request;
+
+	l = min(len, EDID_LENGTH);
+
+	r = sii9022_ddc_read(client->adapter, edid, l, 0);
+	if (r)
+		goto err_ddc_read;
+
+	bytes_read = l;
+
+	/* if there are extensions, read second block */
+	if (len > EDID_LENGTH && edid[0x7e] > 0) {
+		l = min(EDID_LENGTH, len - EDID_LENGTH);
+
+		r = sii9022_ddc_read(client->adapter, edid + EDID_LENGTH,
+				l, EDID_LENGTH);
+		if (r)
+			goto err_ddc_read;
+
+		bytes_read += l;
+	}
+
+	r = sii9022_release_ddc_access(ddata, ctrl_reg);
+	if (r)
+		goto err_ddc_read;
+
+	print_hex_dump_debug("EDID: ", DUMP_PREFIX_NONE, 16, 1, edid,
+		bytes_read, false);
+
+	mutex_unlock(&ddata->lock);
+
+	return bytes_read;
+
+err_ddc_read:
+	sii9022_release_ddc_access(ddata, ctrl_reg);
+err_ddc_request:
+err_hpd:
+	mutex_unlock(&ddata->lock);
+
+	return r;
+}
+
+static bool sii9022_detect(struct omap_dss_device *dssdev)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	bool hpd;
+
+	mutex_lock(&ddata->lock);
+
+	if (ddata->use_polling)
+		sii9022_handle_hpd(ddata);
+
+	hpd = ddata->htplg_state;
+
+	mutex_unlock(&ddata->lock);
+
+	return hpd;
+}
+
+static int sii9022_set_infoframe(struct omap_dss_device *dssdev,
+	const struct hdmi_avi_infoframe *infoframe)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+
+	ddata->frame = *infoframe;
+
+	return 0;
+}
+
+
+static int sii9022_set_hdmi_mode(struct omap_dss_device *dssdev, bool hdmi_mode)
+{
+	struct panel_drv_data *ddata = to_panel_data(dssdev);
+
+	ddata->hdmi_mode = hdmi_mode;
+
+	return 0;
+}
+
+static bool sii9022_audio_supported(struct omap_dss_device *dssdev)
+{
+	return false;
+}
+
+static const struct omapdss_hdmi_ops sii9022_hdmi_ops = {
+	.connect		= sii9022_connect,
+	.disconnect		= sii9022_disconnect,
+
+	.enable			= sii9022_enable,
+	.disable		= sii9022_disable,
+
+	.check_timings		= sii9022_check_timings,
+	.set_timings		= sii9022_set_timings,
+	.get_timings		= sii9022_get_timings,
+
+	.read_edid		= sii9022_read_edid,
+	.detect			= sii9022_detect,
+	.set_hdmi_mode		= sii9022_set_hdmi_mode,
+	.set_infoframe		= sii9022_set_infoframe,
+
+	.audio_supported	= sii9022_audio_supported,
+};
+
+static int sii9022_probe_of(struct i2c_client *client)
+{
+	struct panel_drv_data *ddata = dev_get_drvdata(&client->dev);
+	struct device_node *node = client->dev.of_node;
+	struct omap_dss_device *in;
+	struct gpio_desc *gpio;
+
+	gpio = devm_gpiod_get(&client->dev, "reset");
+
+	if (IS_ERR(gpio)) {
+		if (PTR_ERR(gpio) != -ENOENT)
+			return PTR_ERR(gpio);
+		else
+			gpio = NULL;
+	} else {
+		gpiod_direction_output(gpio, 0);
+	}
+
+	ddata->reset_gpio = gpio;
+
+	ddata->irq = irq_of_parse_and_map(node, 0);
+	if (ddata->irq > 0)
+		ddata->use_polling = false;
+	else
+		ddata->use_polling = true;
+
+	in = omapdss_of_find_source_for_first_ep(node);
+	if (IS_ERR(in)) {
+		dev_err(&client->dev, "failed to find video source\n");
+		return PTR_ERR(in);
+	}
+
+	ddata->in = in;
+
+	return 0;
+}
+
+static int sii9022_probe(struct i2c_client *client,
+		const struct i2c_device_id *id)
+{
+	struct panel_drv_data *ddata;
+	struct omap_dss_device *dssdev;
+	struct regmap *regmap;
+	int r = 0;
+
+	regmap = devm_regmap_init_i2c(client, &sii9022_regmap_config);
+	if (IS_ERR(regmap)) {
+		r = PTR_ERR(regmap);
+		dev_err(&client->dev, "Failed to init regmap: %d\n", r);
+		return r;
+	}
+
+	ddata = devm_kzalloc(&client->dev, sizeof(*ddata), GFP_KERNEL);
+	if (ddata = NULL)
+		return -ENOMEM;
+
+	dev_set_drvdata(&client->dev, ddata);
+
+	mutex_init(&ddata->lock);
+
+	if (client->dev.of_node) {
+		r = sii9022_probe_of(client);
+		if (r)
+			return r;
+	} else {
+		return -ENODEV;
+	}
+
+	ddata->regmap = regmap;
+	ddata->i2c_client = client;
+
+	dssdev = &ddata->dssdev;
+	dssdev->dev = &client->dev;
+	dssdev->ops.hdmi = &sii9022_hdmi_ops;
+	dssdev->type = OMAP_DISPLAY_TYPE_DPI;
+	dssdev->output_type = OMAP_DISPLAY_TYPE_HDMI;
+	dssdev->owner = THIS_MODULE;
+
+	r = sii9022_enable_tpi(ddata);
+	if (r)
+		goto err_tpi;
+
+	r = sii9022_probe_chip_version(ddata);
+	if (r)
+		goto err_i2c;
+
+	r = omapdss_register_output(dssdev);
+	if (r) {
+		dev_err(&client->dev, "Failed to register output\n");
+		goto err_reg;
+	}
+
+	return 0;
+
+err_reg:
+err_i2c:
+err_tpi:
+	omap_dss_put_device(ddata->in);
+	return r;
+}
+
+static int sii9022_remove(struct i2c_client *client)
+{
+	struct panel_drv_data *ddata = dev_get_drvdata(&client->dev);
+	struct omap_dss_device *dssdev = &ddata->dssdev;
+
+	omapdss_unregister_output(dssdev);
+
+	WARN_ON(omapdss_device_is_enabled(dssdev));
+	if (omapdss_device_is_enabled(dssdev))
+		sii9022_disable(dssdev);
+
+	WARN_ON(omapdss_device_is_connected(dssdev));
+	if (omapdss_device_is_connected(dssdev))
+		sii9022_disconnect(dssdev, dssdev->dst);
+
+	omap_dss_put_device(ddata->in);
+
+	return 0;
+}
+
+static const struct i2c_device_id sii9022_id[] = {
+	{ "sii9022", 0 },
+	{ },
+};
+
+static const struct of_device_id sii9022_of_match[] = {
+	{ .compatible = "omapdss,sil,sii9022", },
+	{},
+};
+
+MODULE_DEVICE_TABLE(i2c, sii9022_id);
+
+static struct i2c_driver sii9022_driver = {
+	.driver = {
+		.name  = "sii9022",
+		.owner = THIS_MODULE,
+		.of_match_table = sii9022_of_match,
+		},
+	.probe		= sii9022_probe,
+	.remove		= sii9022_remove,
+	.id_table	= sii9022_id,
+};
+
+module_i2c_driver(sii9022_driver);
+
+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
+MODULE_DESCRIPTION("SiI9022 HDMI Encoder Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/omap2/displays-new/encoder-sii9022.h b/drivers/video/fbdev/omap2/displays-new/encoder-sii9022.h
new file mode 100644
index 000000000000..f9a340437b08
--- /dev/null
+++ b/drivers/video/fbdev/omap2/displays-new/encoder-sii9022.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2014 Texas Instruments
+ * Author : Tomi Valkeinen <tomi.valkeinen@ti.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ *
+ */
+
+#ifndef __ENCODER_SII9022_H_
+#define __ENCODER_SII9022_H_
+
+#define SII9022_ID_902xA		0xb0
+
+#define HDMI_I2C_MONITOR_ADDRESS	0x50
+
+#define SII9022_VIDEO_DATA_BASE_REG	0x00
+#define SII9022_PIXEL_CLK_LSB_REG	(SII9022_VIDEO_DATA_BASE_REG + 0x00)
+#define SII9022_PIXEL_CLK_MSB_REG	(SII9022_VIDEO_DATA_BASE_REG + 0x01)
+#define SII9022_VFREQ_LSB_REG		(SII9022_VIDEO_DATA_BASE_REG + 0x02)
+#define SII9022_VFREQ_MSB_REG		(SII9022_VIDEO_DATA_BASE_REG + 0x03)
+#define SII9022_PIXELS_LSB_REG		(SII9022_VIDEO_DATA_BASE_REG + 0x04)
+#define SII9022_PIXELS_MSB_REG		(SII9022_VIDEO_DATA_BASE_REG + 0x05)
+#define SII9022_LINES_LSB_REG		(SII9022_VIDEO_DATA_BASE_REG + 0x06)
+#define SII9022_LINES_MSB_REG		(SII9022_VIDEO_DATA_BASE_REG + 0x07)
+
+#define SII9022_PIXEL_REPETITION_REG	0x08
+
+#define SII9022_AVI_IN_FORMAT_REG	0x09
+#define SII9022_AVI_OUT_FORMAT_REG	0x0a
+#define SII9022_AVI_INFOFRAME_BASE_REG	0x0c
+
+#define SII9022_SYS_CTRL_DATA_REG	0x1a
+#define SII9022_DEVICE_ID_REG		0x1b
+#define SII9022_DEVICE_REV_ID_REG	0x1c
+#define SII9022_DEVICE_TPI_ID_REG	0x1d
+
+#define SII9022_POWER_STATE_CTRL_REG	0x1e
+
+#define SII9022_IRQ_ENABLE_REG		0x3c
+#define SII9022_IRQ_STATUS_REG		0x3d
+
+#define SII9022_TPI_RQB_REG		0xc7
+
+/* SII9022_SYS_CTRL_DATA_REG */
+#define SII9022_SYS_CTRL_DDC_BUS_GRANTED	BIT(1)
+#define SII9022_SYS_CTRL_DDC_BUS_REQUEST	BIT(2)
+
+
+enum sii9022_power_state {
+	SII9022_POWER_STATE_D0,
+	SII9022_POWER_STATE_D2,
+	SII9022_POWER_STATE_D3_HOT,
+	SII9022_POWER_STATE_D3_COLD,
+};
+
+#endif
-- 
1.9.1


^ permalink raw reply related

* [PATCH 0/4] SiI9022 HDMI encoder for AM4xxx boards
From: Tomi Valkeinen @ 2014-07-03 13:39 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

This series adds a driver for SiI9022 HDMI encoder, which is used on AM437x GP
and AM43x EPOS boards.

The series is based on the OMAPDSS HDMI infoframe series sent earlier, as the
SiI9022 driver uses the new infoframe support.

 Tomi

Tomi Valkeinen (4):
  OMAPDSS: add SiI9022 encoder driver
  Doc/DT: Add SiI9022 binding documentation
  arm/dts: am43x EPOS HDMI support
  arm/dts: am437x GP HDMI support

 .../devicetree/bindings/video/sil,sii9022.txt      |  53 ++
 arch/arm/boot/dts/Makefile                         |   4 +-
 arch/arm/boot/dts/am437x-gp-evm-hdmi.dts           |  70 ++
 arch/arm/boot/dts/am43x-epos-evm-hdmi.dts          |  83 ++
 drivers/video/fbdev/omap2/displays-new/Kconfig     |   8 +
 drivers/video/fbdev/omap2/displays-new/Makefile    |   1 +
 .../fbdev/omap2/displays-new/encoder-sii9022.c     | 966 +++++++++++++++++++++
 .../fbdev/omap2/displays-new/encoder-sii9022.h     |  58 ++
 8 files changed, 1242 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/video/sil,sii9022.txt
 create mode 100644 arch/arm/boot/dts/am437x-gp-evm-hdmi.dts
 create mode 100644 arch/arm/boot/dts/am43x-epos-evm-hdmi.dts
 create mode 100644 drivers/video/fbdev/omap2/displays-new/encoder-sii9022.c
 create mode 100644 drivers/video/fbdev/omap2/displays-new/encoder-sii9022.h

-- 
1.9.1


^ permalink raw reply

* Re: [RFC v4 2/2] backlight: device tree: add new tps611xx backlight binding
From: Mark Rutland @ 2014-07-03  9:04 UTC (permalink / raw)
  To: Daniel Jeong
  Cc: Jingoo Han, Bryan Wu, Lee Jones, Jean-Christophe Plagniol-Villard,
	Tomi Valkeinen,
	grant.likely-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org, Rob Herring,
	Randy Dunlap, Daniel Jeong,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-fbdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-doc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <1404367277-12003-3-git-send-email-gshark.jeong-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

On Thu, Jul 03, 2014 at 07:01:17AM +0100, Daniel Jeong wrote:
> This commit is about tps611xx device tree documentation.
> 
> Signed-off-by: Daniel Jeong <gshark.jeong@gmail.com>
> ---
>  .../video/backlight/tps611xx-backlight.txt         |   24 ++++++++++++++++++++
>  1 file changed, 24 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/video/backlight/tps611xx-backlight.txt
> 
> diff --git a/Documentation/devicetree/bindings/video/backlight/tps611xx-backlight.txt b/Documentation/devicetree/bindings/video/backlight/tps611xx-backlight.txt
> new file mode 100644
> index 0000000..7af8182
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/video/backlight/tps611xx-backlight.txt
> @@ -0,0 +1,24 @@
> +TPS611xx family of backlight driver based on EasyScale.
> +
> +EasyScale is a simple but flexible one pin interface to configure the current.
> +
> +Required properties:
> +- compatible: should contain at least one of
> +  "ti,tps61158_bl"
> +  "ti,tps61161_bl"
> +  "ti,tps61163_bl"
> +  "ti,tps61165_bl"

In v3 I asked you to get rid of the "_bl" suffix.

> +- rfa-enable: enable request for acknowledge.
> +  If RFA is enabled, the data byte includes the RFA bit and device will wait
> +  and check acknowledge from device.

You didn't answer my question as to why this should be in the DT.

> +- es-gpio : GPIO for easy-scale communication.(see GPIO binding[0])
> +
> +[0]: Documentation/devicetree/bindings/gpio/gpio.txt
> +
> +Example:
> +
> +	backlight {
> +		compatible = "ti,tps61163";

This now doesn't match the Documentation above.

Thanks,
Mark.

> +		rfa-enable;
> +		es-gpio = <&gpio 45 0>;
> +	};
> -- 
> 1.7.9.5
> 
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply

* [RFC v4 2/2] backlight: device tree: add new tps611xx backlight binding
From: Daniel Jeong @ 2014-07-03  6:01 UTC (permalink / raw)
  To: Jingoo Han, Bryan Wu, Lee Jones, Jean-Christophe Plagniol-Villard,
	Tomi Valkeinen, Grant Likely, Rob Herring, Randy Dunlap
  Cc: Daniel Jeong, linux-kernel, linux-fbdev, devicetree, linux-doc,
	Daniel Jeong
In-Reply-To: <1404367277-12003-1-git-send-email-gshark.jeong@gmail.com>

This commit is about tps611xx device tree documentation.

Signed-off-by: Daniel Jeong <gshark.jeong@gmail.com>
---
 .../video/backlight/tps611xx-backlight.txt         |   24 ++++++++++++++++++++
 1 file changed, 24 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/video/backlight/tps611xx-backlight.txt

diff --git a/Documentation/devicetree/bindings/video/backlight/tps611xx-backlight.txt b/Documentation/devicetree/bindings/video/backlight/tps611xx-backlight.txt
new file mode 100644
index 0000000..7af8182
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/backlight/tps611xx-backlight.txt
@@ -0,0 +1,24 @@
+TPS611xx family of backlight driver based on EasyScale.
+
+EasyScale is a simple but flexible one pin interface to configure the current.
+
+Required properties:
+- compatible: should contain at least one of
+  "ti,tps61158_bl"
+  "ti,tps61161_bl"
+  "ti,tps61163_bl"
+  "ti,tps61165_bl"
+- rfa-enable: enable request for acknowledge.
+  If RFA is enabled, the data byte includes the RFA bit and device will wait
+  and check acknowledge from device.
+- es-gpio : GPIO for easy-scale communication.(see GPIO binding[0])
+
+[0]: Documentation/devicetree/bindings/gpio/gpio.txt
+
+Example:
+
+	backlight {
+		compatible = "ti,tps61163";
+		rfa-enable;
+		es-gpio = <&gpio 45 0>;
+	};
-- 
1.7.9.5


^ permalink raw reply related

* [RFC v4 1/2] backlight: add new tps611xx backlight driver
From: Daniel Jeong @ 2014-07-03  6:01 UTC (permalink / raw)
  To: Jingoo Han, Bryan Wu, Lee Jones, Jean-Christophe Plagniol-Villard,
	Tomi Valkeinen, Grant Likely, Rob Herring, Randy Dunlap
  Cc: Daniel Jeong, linux-kernel, linux-fbdev, devicetree, linux-doc,
	Daniel Jeong
In-Reply-To: <1404367277-12003-1-git-send-email-gshark.jeong@gmail.com>

This driver is a general version for tps611xx backlgiht chips of TI.
It supports tps61158, tps61161, tps61163 and tps61165 backlight driver
based on EasyScale protocol(1-Wire Control Interface).

EasyScale
EasyScale is a simple but flexible one pin interface to configure the current.
The interface is based on a master-slave structure, where the master is
typically a microcontroller or application processor and the IC is the slave.
The advantage of EasyScale compared with other one pin interfaces is that
its bit detection is in a large extent independent from the bit transmission
rate. It can automatically detect bit rates between 1.7kBit/sec and up
to 160kBit/sec.

EasyScale on TPS61163
A command consists of 24 bits, including an 8-bit device address byte and
a 16-bit data byte. All of the 24 bits should be transmitted together each
time, and the LSB bit should be transmitted first. The device address byte
A7(MSB)~A0(LSB) is fixed to 0x8F.
The data byte includes 9 bits D8(MSB)~D0(LSB) for brightness information
and an RFA bit. The RFA bit set to "1" indicates the Request for Acknowledge
condition. The Acknowledge condition is only applied when the protocol is
received correctly.
Bit sream : D0-D8 | 0 | RFA | 00000 | A0-A7
Please refer to the links below  for more details.
http://www.ti.com/lit/ds/symlink/tps61163.pdf

EasyScale on TPS61158/61/65
A command consists of 16 bits, including an 8-bit device address byte
and a 8-bit data byte. All of the 16 bits should be transmitted together
each time, and the MSB bit should be transmitted first. The device address
byte A7(MSB)~A0(LSB) is fixed (tps61158 0x58 tps61161 and tps61165 0x72).
The data byte includes an RFA bit.
The RFA bit set to "1" indicates the Request for Acknowledge condition.
The Acknowledge condition is only applied when the protocol is received
correctly.
Bit sream : A7-A0 | RFA | 00 | D4-D0
Please refer to the links below  for more details.
http://www.ti.com/lit/ds/symlink/tps61158.pdf
http://www.ti.com.cn/cn/lit/ds/symlink/tps61161-q1.pdf
http://www.ti.com/lit/ds/symlink/tps61165.pdf

Signed-off-by: Daniel Jeong <gshark.jeong@gmail.com>
---
 drivers/video/backlight/Kconfig           |    7 +
 drivers/video/backlight/Makefile          |    1 +
 drivers/video/backlight/tps611xx_bl.c     |  479 +++++++++++++++++++++++++++++
 include/linux/platform_data/tps611xx_bl.h |   31 ++
 4 files changed, 518 insertions(+)
 create mode 100644 drivers/video/backlight/tps611xx_bl.c
 create mode 100644 include/linux/platform_data/tps611xx_bl.h

diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index 5a3eb2e..c779a85 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -418,6 +418,13 @@ config BACKLIGHT_TPS65217
 	  If you have a Texas Instruments TPS65217 say Y to enable the
 	  backlight driver.
 
+config BACKLIGHT_TPS611xx
+	tristate "TPS611xx Backlight"
+	depends on BACKLIGHT_CLASS_DEVICE && GPIOLIB
+	help
+	  This supports TI TPS61158,TPS61161, TPS61163 and TPS61165
+	  backlight driver based on EasyScale Protocol.
+
 config BACKLIGHT_AS3711
 	tristate "AS3711 Backlight"
 	depends on BACKLIGHT_CLASS_DEVICE && MFD_AS3711
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index bb82002..5c39945 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -51,5 +51,6 @@ obj-$(CONFIG_BACKLIGHT_PCF50633)	+= pcf50633-backlight.o
 obj-$(CONFIG_BACKLIGHT_PWM)		+= pwm_bl.o
 obj-$(CONFIG_BACKLIGHT_SAHARA)		+= kb3886_bl.o
 obj-$(CONFIG_BACKLIGHT_TOSA)		+= tosa_bl.o
+obj-$(CONFIG_BACKLIGHT_TPS611xx)	+= tps611xx_bl.o
 obj-$(CONFIG_BACKLIGHT_TPS65217)	+= tps65217_bl.o
 obj-$(CONFIG_BACKLIGHT_WM831X)		+= wm831x_bl.o
diff --git a/drivers/video/backlight/tps611xx_bl.c b/drivers/video/backlight/tps611xx_bl.c
new file mode 100644
index 0000000..6c485ff
--- /dev/null
+++ b/drivers/video/backlight/tps611xx_bl.c
@@ -0,0 +1,479 @@
+/*
+ * Simple driver for Texas Instruments TPS611XX Backlight driver chip
+ *        using EasyScale Interface. It supports TPS61158, TPS61161,
+ *        TPS61163 and TPS61165.
+ *
+ * Copyright (C) 2014 Texas Instruments
+ * Author: Daniel Jeong  <gshark.jeong@gmail.com>
+ *	       Ldd Mlp <ldd-mlp@list.ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/backlight.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/fb.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_data/tps611xx_bl.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#define CMD_FORWARD 0
+#define CMD_BACKWARD 1
+
+enum tps611xx_id {
+	TPS61158_ID = 0,
+	TPS61161_ID,
+	TPS61163_ID,
+	TPS61165_ID,
+};
+
+/*
+ * easyscale time spec
+ * @es_delay : es delay time(ns)
+ * @es_det   : es detection time(ns)
+ * @start    : start time of data stream(ns)
+ * @eos      : end time of data stream(ns)
+ * @reset    : ic shutdown time(ms)
+ * @logic_1_low : low time high bit(ns)
+ * @logic_0_low : low time low bit(ns)
+ * @ackn        : duation of ack condistion(ns)
+ * @ack_poll    : ack polling duration(ns)
+ */
+struct tps611xx_time {
+	unsigned int es_delay;
+	unsigned int es_det;
+	unsigned int start;
+	unsigned int eos;
+	unsigned int reset;
+	unsigned int logic_1_low;
+	unsigned int logic_0_low;
+	unsigned int ackn;
+	unsigned int ack_poll;
+};
+
+/*
+ * @seq : sequence of data transfer
+ * @size: size of data
+ * @brt_max : max brightness
+ * @brt_bmask : bit mask of dimming bits
+ * @rfa_bmask : bit mask of RFA(Request for Acknowledge condition)
+ */
+struct tps611xx_command {
+	int seq;
+	int size;
+	int brt_max;
+	int brt_bmask;
+	int rfa_bmask;
+};
+
+/*
+ * @id : product id
+ * @name : product name
+ * @addr : device address
+ * @cmd  : es command info
+ * @time : es time info
+ */
+struct tps611xx_esdata {
+	enum tps611xx_id id;
+	char *name;
+	int addr;
+	struct tps611xx_command cmd;
+	struct tps611xx_time time;
+};
+
+struct tps611xx_bl_data {
+	struct device *dev;
+	struct backlight_device *bled;
+	struct tps611xx_platform_data *pdata;
+
+	/*
+	 * @rfa_en : RFA enable (Request for Acknowledge condition)
+	 * @en_gpio: enable pin gpio no.
+	 * @esdata : easyscale data
+	 */
+	int rfa_en;
+	unsigned int en_gpio;
+	const struct tps611xx_esdata *esdata;
+};
+
+static struct tps611xx_esdata tps611xx_info[] = {
+	[TPS61158_ID] = {
+		.id = TPS61158_ID,
+		.name = "tps61158",
+		.addr = 0x5800,
+		.cmd = {
+			.seq = CMD_FORWARD,
+			.size = 16,
+			.brt_max = 31,
+			.brt_bmask = 0x1f,
+			.rfa_bmask = 0x80
+		},
+		.time = {
+			.es_delay = 100000,
+			.es_det = 450000,
+			.start = 3500,
+			.eos = 3500,
+			.reset = 4,
+			.logic_1_low = 5000,
+			.logic_0_low = 15000,
+			.ackn = 900000,
+			.ack_poll = 2000
+		},
+	},
+
+	[TPS61161_ID] = {
+		.id = TPS61161_ID,
+		.name = "tps61161",
+		.addr = 0x7200,
+		.cmd = {
+			.seq = CMD_FORWARD,
+			.size = 16,
+			.brt_max = 31,
+			.brt_bmask = 0x1f,
+			.rfa_bmask = 0x80
+		},
+		.time = {
+			.es_delay = 120000,
+			.es_det = 280000,
+			.start = 2000,
+			.eos = 2000,
+			.reset = 3,
+			.logic_1_low = 3000,
+			.logic_0_low = 7000,
+			.ackn = 512000,
+			.ack_poll = 2000
+		},
+	},
+
+	[TPS61163_ID] = {
+		.id = TPS61163_ID,
+		.name = "tps61163",
+		.addr = 0x8F0000,
+		.cmd = {
+			.seq = CMD_BACKWARD,
+			.size = 24,
+			.brt_max = 511,
+			.brt_bmask = 0x1ff,
+			.rfa_bmask = 0x400
+		},
+		.time = {
+			.es_delay = 100000,
+			.es_det = 260000,
+			.start = 2000,
+			.eos = 2000,
+			.reset = 3,
+			.logic_1_low = 3000,
+			.logic_0_low = 7000,
+			.ackn = 512000,
+			.ack_poll = 2000
+		},
+	},
+
+	[TPS61165_ID] = {
+		.id = TPS61165_ID,
+		.name = "tps61165",
+		.addr = 0x7200,
+		.cmd = {
+			.seq = CMD_FORWARD,
+			.size = 16,
+			.brt_max = 31,
+			.brt_bmask = 0x1f,
+			.rfa_bmask = 0x80
+		},
+		.time = {
+			.es_delay = 120000,
+			.es_det = 280000,
+			.start = 4000,
+			.eos = 4000,
+			.reset = 3,
+			.logic_1_low = 3000,
+			.logic_0_low = 7000,
+			.ackn = 512000,
+			.ack_poll = 2000
+		},
+	},
+};
+
+static int tps611xx_bl_update_status(struct backlight_device *bl)
+{
+	struct tps611xx_bl_data *pchip = bl_get_data(bl);
+	const struct tps611xx_esdata *esdata = pchip->esdata;
+	int data_in, t_low, t_logic, max_bmask;
+	unsigned long flags;
+
+	data_in = esdata->addr | (bl->props.brightness & esdata->cmd.brt_bmask);
+	if (pchip->rfa_en)
+		data_in |= esdata->cmd.rfa_bmask;
+
+	max_bmask = 0x1 << esdata->cmd.size;
+	t_logic = esdata->time.logic_1_low + esdata->time.logic_0_low;
+
+	local_irq_save(flags);
+	/* t_start : 2us high before data byte */
+	gpio_direction_output(pchip->en_gpio, 1);
+	ndelay(esdata->time.start);
+
+	/* forward command transfer */
+	if (esdata->cmd.seq = CMD_FORWARD) {
+		int addr_bmask = max_bmask >> 8;
+
+		for (max_bmask >>= 1; max_bmask > 0x0; max_bmask >>= 1) {
+			if (data_in & max_bmask)
+				t_low = esdata->time.logic_1_low;
+			else
+				t_low = esdata->time.logic_0_low;
+
+			gpio_direction_output(pchip->en_gpio, 0);
+			ndelay(t_low);
+			gpio_direction_output(pchip->en_gpio, 1);
+			ndelay(t_logic - t_low);
+
+			if (max_bmask = addr_bmask) {
+				gpio_direction_output(pchip->en_gpio, 0);
+				/* t_eos : low after address byte */
+				ndelay(esdata->time.eos);
+				gpio_direction_output(pchip->en_gpio, 1);
+				/* t_start : high before data byte */
+				ndelay(esdata->time.start);
+			}
+		}
+	} else {
+		/* backward command tansfer */
+		int bmask;
+
+		for (bmask = 0x01; bmask < max_bmask; bmask <<= 1) {
+			if (data_in & bmask)
+				t_low = esdata->time.logic_1_low;
+			else
+				t_low = esdata->time.logic_0_low;
+
+			gpio_direction_output(pchip->en_gpio, 0);
+			ndelay(t_low);
+			gpio_direction_output(pchip->en_gpio, 1);
+			ndelay(t_logic - t_low);
+		}
+	}
+
+	/*
+	 * t_eos : low after address byte
+	 * t_ackVal is also t_eos
+	 */
+	gpio_direction_output(pchip->en_gpio, 0);
+	ndelay(esdata->time.eos);
+
+	/* RFA management  */
+	if (pchip->rfa_en) {
+		int max_ack_time = esdata->time.ackn;
+		/* set input */
+		gpio_direction_input(pchip->en_gpio);
+		/* read acknowledge from chip */
+		while (max_ack_time > 0) {
+			if (gpio_get_value(pchip->en_gpio) = 0)
+				break;
+			max_ack_time -= esdata->time.ack_poll;
+		}
+		if (max_ack_time <= 0)
+			dev_err(pchip->dev,
+				"easyscale : no ack from %s\n", esdata->name);
+		else
+			ndelay(max_ack_time);
+	}
+	gpio_direction_output(pchip->en_gpio, 1);
+	local_irq_restore(flags);
+
+	return bl->props.brightness;
+}
+
+static const struct backlight_ops tps611xx_bl_ops = {
+	.update_status = tps611xx_bl_update_status,
+};
+
+static ssize_t tps611xx_enable_store(struct device *dev,
+				     struct device_attribute *devAttr,
+				     const char *buf, size_t size)
+{
+	struct tps611xx_bl_data *pchip = dev_get_drvdata(dev);
+	const struct tps611xx_esdata *esdata = pchip->esdata;
+	unsigned long flags;
+	unsigned int input;
+	int ret;
+
+	ret = kstrtouint(buf, 10, &input);
+	if (ret)
+		return -EINVAL;
+
+	local_irq_save(flags);
+	if (input = 0) {
+		/* chip disable */
+		gpio_direction_output(pchip->en_gpio, 0);
+		/* low more than reset ms to reset */
+		mdelay(esdata->time.reset);
+	} else {
+		/* easyscale detection window */
+		gpio_direction_output(pchip->en_gpio, 1);
+		ndelay(esdata->time.es_delay);
+		gpio_direction_output(pchip->en_gpio, 0);
+		ndelay(esdata->time.es_det);
+		gpio_direction_output(pchip->en_gpio, 1);
+	}
+	local_irq_restore(flags);
+
+	return size;
+}
+
+static DEVICE_ATTR(enable, S_IWUSR, NULL, tps611xx_enable_store);
+
+#ifdef CONFIG_OF
+static const struct of_device_id tps611xx_backlight_of_match[] = {
+	{.compatible = "ti,tps61158", .data = &tps611xx_info[TPS61158_ID]},
+	{.compatible = "ti,tps61161", .data = &tps611xx_info[TPS61161_ID]},
+	{.compatible = "ti,tps61163", .data = &tps611xx_info[TPS61163_ID]},
+	{.compatible = "ti,tps61165", .data = &tps611xx_info[TPS61165_ID]},
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, tps611xx_backlight_of_match);
+
+static int tps611xx_backlight_parse_dt(struct tps611xx_bl_data *pchip)
+{
+	struct device *dev = pchip->dev;
+	struct device_node *node = dev->of_node;
+	const struct of_device_id *of_id +	    of_match_device(tps611xx_backlight_of_match, dev);
+
+	if (!node)
+		return -ENODEV;
+
+	if (!of_id || !of_id->data) {
+		dev_err(dev, "Failed to find tps611xx chip id\n");
+		return -EFAULT;
+	}
+	pchip->esdata = of_id->data;
+	pchip->rfa_en = of_property_read_bool(node, "rfa-enable");
+	pchip->en_gpio = of_get_named_gpio(node, "es-gpio", 0);
+
+	return 0;
+}
+#else
+static int tps611xx_backlight_parse_dt(struct tps611xx_bl_data *pchip)
+{
+	return -ENODEV;
+}
+#endif
+
+static int tps611xx_backlight_probe(struct platform_device *pdev)
+{
+	struct tps611xx_bl_data *pchip;
+	struct backlight_properties props;
+	const struct tps611xx_esdata *esdata;
+	struct tps611xx_platform_data *pdata = dev_get_platdata(&pdev->dev);
+	unsigned long flags;
+	int ret;
+
+	pchip = devm_kzalloc(&pdev->dev,
+			     sizeof(struct tps611xx_bl_data), GFP_KERNEL);
+	if (pchip = NULL)
+		return -ENOMEM;
+	pchip->dev = &pdev->dev;
+
+	if (pdata = NULL) {
+		ret = tps611xx_backlight_parse_dt(pchip);
+		if (ret < 0)
+			return ret;
+	} else {
+		pchip->rfa_en = pdata->rfa_en;
+		pchip->en_gpio = pdata->en_gpio_num;
+		pchip->esdata = (const struct tps611xx_esdata *)
+		    platform_get_device_id(pdev)->driver_data;
+	}
+	esdata = pchip->esdata;
+
+	memset(&props, 0, sizeof(struct backlight_properties));
+	props.brightness = esdata->cmd.brt_max;
+	props.max_brightness = esdata->cmd.brt_max;
+	props.type = BACKLIGHT_RAW;
+	pchip->bled +	    devm_backlight_device_register(pchip->dev, TPS611XX_NAME,
+					   pchip->dev, pchip,
+					   &tps611xx_bl_ops, &props);
+	if (IS_ERR(pchip->bled))
+		return PTR_ERR(pchip->bled);
+
+	/* for enable/disable */
+	ret = device_create_file(&(pchip->bled->dev), &dev_attr_enable);
+	if (ret < 0) {
+		dev_err(pchip->dev, "failed : add sysfs entries\n");
+		return ret;
+	}
+	platform_set_drvdata(pdev, pchip);
+
+	/* EasyScale init */
+	ret = gpio_request_one(pchip->en_gpio, GPIOF_OUT_INIT_HIGH, "tps611xx");
+	if (ret) {
+		device_remove_file(&(pchip->bled->dev), &dev_attr_enable);
+		dev_err(pchip->dev, "failed : get gpio %d\n", pchip->en_gpio);
+		return ret;
+	}
+
+	/*
+	 * ES Detection Window
+	 *   - ES detect delay
+	 *   - ES detect time
+	 */
+	local_irq_save(flags);
+	gpio_direction_output(pchip->en_gpio, 1);
+	ndelay(esdata->time.es_delay);
+	gpio_direction_output(pchip->en_gpio, 0);
+	ndelay(esdata->time.es_det);
+	gpio_direction_output(pchip->en_gpio, 1);
+	local_irq_restore(flags);
+	dev_info(pchip->dev,
+		 "%s EasyScale is initialized\n", pchip->esdata->name);
+	return 0;
+}
+
+static int tps611xx_backlight_remove(struct platform_device *pdev)
+{
+	struct tps611xx_bl_data *pchip = platform_get_drvdata(pdev);
+	const struct tps611xx_esdata *esdata = pchip->esdata;
+
+	device_remove_file(&(pchip->bled->dev), &dev_attr_enable);
+	gpio_direction_output(pchip->en_gpio, 0);
+	mdelay(esdata->time.reset);
+	return 0;
+}
+
+static const struct platform_device_id tps611xx_id_table[] = {
+	{TPS61158_NAME, (unsigned long)&tps611xx_info[TPS61158_ID]},
+	{TPS61161_NAME, (unsigned long)&tps611xx_info[TPS61161_ID]},
+	{TPS61163_NAME, (unsigned long)&tps611xx_info[TPS61163_ID]},
+	{TPS61165_NAME, (unsigned long)&tps611xx_info[TPS61165_ID]},
+	{}
+};
+
+static struct platform_driver tps611xx_backlight_driver = {
+	.driver = {
+		.name = TPS611XX_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(tps611xx_backlight_of_match),
+	},
+	.probe = tps611xx_backlight_probe,
+	.remove = tps611xx_backlight_remove,
+	.id_table = tps611xx_id_table,
+};
+
+module_platform_driver(tps611xx_backlight_driver);
+
+MODULE_DESCRIPTION("EasyScale based tps611xx Backlight Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:tps611xx_bl");
diff --git a/include/linux/platform_data/tps611xx_bl.h b/include/linux/platform_data/tps611xx_bl.h
new file mode 100644
index 0000000..f16b43b
--- /dev/null
+++ b/include/linux/platform_data/tps611xx_bl.h
@@ -0,0 +1,31 @@
+/*
+ * Simple driver for Texas Instruments TPS611xx Backlight driver chip
+ * Copyright (C) 2014 Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __TPS611XX_H
+#define __TPS611XX_H
+
+#define TPS611XX_NAME "tps611xx"
+#define TPS61158_NAME "tps61158"
+#define TPS61161_NAME "tps61161"
+#define TPS61163_NAME "tps61163"
+#define TPS61165_NAME "tps61165"
+
+/*
+ * struct tps611xx platform data
+ * @rfa_en : request for acknowledge
+ * @en_gpio_num : gpio number for en_pin
+ */
+struct tps611xx_platform_data {
+
+	int rfa_en;
+	unsigned int en_gpio_num;
+};
+
+#endif /* __TPS611XX_H */
-- 
1.7.9.5


^ permalink raw reply related

* [RFC v4 0/2]  backlight: add new tps611xx backlight driver
From: Daniel Jeong @ 2014-07-03  6:01 UTC (permalink / raw)
  To: Jingoo Han, Bryan Wu, Lee Jones, Jean-Christophe Plagniol-Villard,
	Tomi Valkeinen, Grant Likely, Rob Herring, Randy Dunlap
  Cc: Daniel Jeong, linux-kernel, linux-fbdev, devicetree, linux-doc,
	Daniel Jeong

This driver is a general version for tps611xx backlgiht chips of TI.
It supports tps61158, tps61161, tps61163 and tps61165 backlight driver
based on EasyScale protocol.

Daniel Jeong (2):
  backlight
  backlight: add new tps611xx backlight device tree support

 .../video/backlight/tps611xx-backlight.txt         |   24 +
 drivers/video/backlight/Kconfig                    |    7 +
 drivers/video/backlight/Makefile                   |    1 +
 drivers/video/backlight/tps611xx_bl.c              |  479 ++++++++++++++++++++
 include/linux/platform_data/tps611xx_bl.h          |   31 ++
 5 files changed, 542 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/video/backlight/tps611xx-backlight.txt
 create mode 100644 drivers/video/backlight/tps611xx_bl.c
 create mode 100644 include/linux/platform_data/tps611xx_bl.h

-- 
1.7.9.5


^ permalink raw reply

* Re: [PATCH 15/15] drm/omap: Add infoframe & dvi/hdmi mode support
From: Tomi Valkeinen @ 2014-07-03  5:55 UTC (permalink / raw)
  To: linux-fbdev, linux-omap, dri-devel@lists.freedesktop.org,
	Dave Airlie
  Cc: Archit Taneja, Jyri Sarha, Rob Clark
In-Reply-To: <1403604240-16738-16-git-send-email-tomi.valkeinen@ti.com>

[-- Attachment #1: Type: text/plain, Size: 4241 bytes --]

On 24/06/14 13:04, Tomi Valkeinen wrote:
> Make the omapdrm driver use the new HDMI ops when possible.
> 
> omapdrm will call set_hdmi_mode (when available) to tell the encoder
> driver whether the monitor is a DVI or HDMI monitor, and if it's an HDMI
> monitor, omapdrm will call set_hdmi_infoframe to to set the AVI
> infoframe.
> 
> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
> Cc: Rob Clark <robdclark@gmail.com>
> ---
>  drivers/gpu/drm/omapdrm/omap_connector.c | 12 ++++++++++++
>  drivers/gpu/drm/omapdrm/omap_drv.h       |  1 +
>  drivers/gpu/drm/omapdrm/omap_encoder.c   | 27 +++++++++++++++++++++++++++
>  3 files changed, 40 insertions(+)

Ah, I forgot to add dri-devel list for this one.

Dave, is it ok if I queue this one via fbdev tree, as it depends on the
previous patches on this series?

 Tomi

> 
> diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c
> index 86f4ead0441d..19492cd31f10 100644
> --- a/drivers/gpu/drm/omapdrm/omap_connector.c
> +++ b/drivers/gpu/drm/omapdrm/omap_connector.c
> @@ -32,8 +32,16 @@ struct omap_connector {
>  	struct drm_connector base;
>  	struct omap_dss_device *dssdev;
>  	struct drm_encoder *encoder;
> +	bool hdmi_mode;
>  };
>  
> +bool omap_connector_get_hdmi_mode(struct drm_connector *connector)
> +{
> +	struct omap_connector *omap_connector = to_omap_connector(connector);
> +
> +	return omap_connector->hdmi_mode;
> +}
> +
>  void copy_timings_omap_to_drm(struct drm_display_mode *mode,
>  		struct omap_video_timings *timings)
>  {
> @@ -162,10 +170,14 @@ static int omap_connector_get_modes(struct drm_connector *connector)
>  			drm_mode_connector_update_edid_property(
>  					connector, edid);
>  			n = drm_add_edid_modes(connector, edid);
> +
> +			omap_connector->hdmi_mode =
> +				drm_detect_hdmi_monitor(edid);
>  		} else {
>  			drm_mode_connector_update_edid_property(
>  					connector, NULL);
>  		}
> +
>  		kfree(edid);
>  	} else {
>  		struct drm_display_mode *mode = drm_mode_create(dev);
> diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
> index 284b80fc3c54..c204c1e7ce87 100644
> --- a/drivers/gpu/drm/omapdrm/omap_drv.h
> +++ b/drivers/gpu/drm/omapdrm/omap_drv.h
> @@ -194,6 +194,7 @@ struct drm_encoder *omap_connector_attached_encoder(
>  		struct drm_connector *connector);
>  void omap_connector_flush(struct drm_connector *connector,
>  		int x, int y, int w, int h);
> +bool omap_connector_get_hdmi_mode(struct drm_connector *connector);
>  
>  void copy_timings_omap_to_drm(struct drm_display_mode *mode,
>  		struct omap_video_timings *timings);
> diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c b/drivers/gpu/drm/omapdrm/omap_encoder.c
> index 5290a88c681d..7445fb1491ae 100644
> --- a/drivers/gpu/drm/omapdrm/omap_encoder.c
> +++ b/drivers/gpu/drm/omapdrm/omap_encoder.c
> @@ -17,6 +17,8 @@
>   * this program.  If not, see <http://www.gnu.org/licenses/>.
>   */
>  
> +#include <drm/drm_edid.h>
> +
>  #include "omap_drv.h"
>  
>  #include "drm_crtc.h"
> @@ -89,6 +91,31 @@ static void omap_encoder_mode_set(struct drm_encoder *encoder,
>  				struct drm_display_mode *mode,
>  				struct drm_display_mode *adjusted_mode)
>  {
> +	struct drm_device *dev = encoder->dev;
> +	struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
> +	struct omap_dss_device *dssdev = omap_encoder->dssdev;
> +	struct drm_connector *connector;
> +	bool hdmi_mode;
> +	int r;
> +
> +	hdmi_mode = false;
> +	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
> +		if (connector->encoder == encoder) {
> +			hdmi_mode = omap_connector_get_hdmi_mode(connector);
> +			break;
> +		}
> +	}
> +
> +	if (dssdev->driver->set_hdmi_mode)
> +		dssdev->driver->set_hdmi_mode(dssdev, hdmi_mode);
> +
> +	if (hdmi_mode && dssdev->driver->set_hdmi_infoframe) {
> +		struct hdmi_avi_infoframe avi;
> +
> +		r = drm_hdmi_avi_infoframe_from_display_mode(&avi, adjusted_mode);
> +		if (r == 0)
> +			dssdev->driver->set_hdmi_infoframe(dssdev, &avi);
> +	}
>  }
>  
>  static void omap_encoder_prepare(struct drm_encoder *encoder)
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply

* Re: [PATCH] video: fbdev: matrox: matroxfb_base.c:  Fix for possible null pointer dereference
From: Mikulas Patocka @ 2014-07-02 22:18 UTC (permalink / raw)
  To: Rickard Strandqvist
  Cc: Jean-Christophe Plagniol-Villard, Tomi Valkeinen, Jingoo Han,
	Alexandru Juncu, Daniel Vetter, Joe Perches, linux-fbdev,
	linux-kernel
In-Reply-To: <1404337551-6499-1-git-send-email-rickard_strandqvist@spectrumdigital.se>



On Wed, 2 Jul 2014, Rickard Strandqvist wrote:

> Fix a possible null pointer dereference, there is otherwise a risk of a 
> possible null pointer dereference
> 
> This was found using a static code analysis program called cppcheck
> 
> Signed-off-by: Rickard Strandqvist <rickard_strandqvist@spectrumdigital.se>
> ---
>  drivers/video/fbdev/matrox/matroxfb_base.c |    4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/video/fbdev/matrox/matroxfb_base.c b/drivers/video/fbdev/matrox/matroxfb_base.c
> index 7116c53..85ef84b 100644
> --- a/drivers/video/fbdev/matrox/matroxfb_base.c
> +++ b/drivers/video/fbdev/matrox/matroxfb_base.c
> @@ -1971,9 +1971,9 @@ static void matroxfb_register_device(struct matrox_fb_info* minfo) {
>  	int i = 0;
>  	list_add(&minfo->next_fb, &matroxfb_list);
>  	for (drv = matroxfb_driver_l(matroxfb_driver_list.next);
> -	     drv != matroxfb_driver_l(&matroxfb_driver_list);
> +	     drv && drv != matroxfb_driver_l(&matroxfb_driver_list);

The "drv" check is pointless because drv can't be NULL - use the patch 
below.

>  	     drv = matroxfb_driver_l(drv->node.next)) {
> -		if (drv && drv->probe) {
> +		if (drv->probe) {
>  			void *p = drv->probe(minfo);
>  			if (p) {
>  				minfo->drivers_data[i] = p;
> -- 
> 1.7.10.4

matroxfb: delete pointless NULL-pointer check

The for loop walks a double-linked list, so drv cannot be NULL.

This patch deletes the pointless NULL-pointer check. cppcheck warned about
it.

Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>

---
 drivers/video/fbdev/matrox/matroxfb_base.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Index: linux-2.6/drivers/video/fbdev/matrox/matroxfb_base.c
=================================--- linux-2.6.orig/drivers/video/fbdev/matrox/matroxfb_base.c	2014-06-19 16:41:45.048259897 +0200
+++ linux-2.6/drivers/video/fbdev/matrox/matroxfb_base.c	2014-07-03 00:13:04.299380130 +0200
@@ -1973,7 +1973,7 @@ static void matroxfb_register_device(str
 	for (drv = matroxfb_driver_l(matroxfb_driver_list.next);
 	     drv != matroxfb_driver_l(&matroxfb_driver_list);
 	     drv = matroxfb_driver_l(drv->node.next)) {
-		if (drv && drv->probe) {
+		if (drv->probe) {
 			void *p = drv->probe(minfo);
 			if (p) {
 				minfo->drivers_data[i] = p;

^ permalink raw reply

* [PATCH] video: fbdev: sis: init301.c:  Cleaning up a potential division by zero
From: Rickard Strandqvist @ 2014-07-02 22:08 UTC (permalink / raw)
  To: Jean-Christophe Plagniol-Villard, Tomi Valkeinen
  Cc: Rickard Strandqvist, Jingoo Han, Laurent Pinchart, Rob Clark,
	linux-fbdev, linux-kernel
In-Reply-To: <1404338915-6946-1-git-send-email-rickard_strandqvist@spectrumdigital.se>

Cleaning up a potential division by zero.

Signed-off-by: Rickard Strandqvist <rickard_strandqvist@spectrumdigital.se>
---
 drivers/video/fbdev/sis/init301.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/video/fbdev/sis/init301.c b/drivers/video/fbdev/sis/init301.c
index a89e3ca..730be06 100644
--- a/drivers/video/fbdev/sis/init301.c
+++ b/drivers/video/fbdev/sis/init301.c
@@ -5351,7 +5351,7 @@ SiS_SetGroup1_LVDS(struct SiS_Private *SiS_Pr, unsigned short ModeNo, unsigned s
 {
   unsigned short modeflag, resinfo = 0;
   unsigned short push2, tempax, tempbx, tempcx, temp;
-  unsigned int   tempeax = 0, tempebx, tempecx, tempvcfact = 0;
+  unsigned int   tempeax = 0, tempebx, tempecx, tempvcfact = 1;
   bool islvds = false, issis  = false, chkdclkfirst = false;
 #ifdef CONFIG_FB_SIS_300
   unsigned short crt2crtc = 0;
-- 
1.7.10.4


^ permalink raw reply related

* [PATCH] video: fbdev: sis: init301.c:  Cleaning up a potential division by zero
From: Rickard Strandqvist @ 2014-07-02 22:08 UTC (permalink / raw)
  To: Jean-Christophe Plagniol-Villard, Tomi Valkeinen
  Cc: Rickard Strandqvist, Jingoo Han, Laurent Pinchart, Rob Clark,
	linux-fbdev, linux-kernel
In-Reply-To: <1402869130-4962-1-git-send-email-rickard_strandqvist@spectrumdigital.se>

Guess these ifdef will always be set, but still feel that 1 is a better starting value other than 0 in this case.

This was found using a static code analysis program called cppcheck

Rickard Strandqvist (1):
  video: fbdev: sis: init301.c:  Cleaning up a potential division by zero

 drivers/video/fbdev/sis/init301.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

-- 
1.7.10.4


^ permalink raw reply

* [PATCH] video: fbdev: sh_mipi_dsi.c:  Cleaning up Boolean used in bitwise operation
From: Rickard Strandqvist @ 2014-07-02 21:57 UTC (permalink / raw)
  To: Jean-Christophe Plagniol-Villard, Tomi Valkeinen
  Cc: Rickard Strandqvist, Jingoo Han, Laurent Pinchart, Rob Clark,
	linux-fbdev, linux-kernel
In-Reply-To: <1404338232-6708-1-git-send-email-rickard_strandqvist@spectrumdigital.se>

Boolean variable is used in bitwise operation.

Signed-off-by: Rickard Strandqvist <rickard_strandqvist@spectrumdigital.se>
---
 drivers/video/fbdev/sh_mipi_dsi.c |    9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/video/fbdev/sh_mipi_dsi.c b/drivers/video/fbdev/sh_mipi_dsi.c
index 8f6e8ff..39417ab 100644
--- a/drivers/video/fbdev/sh_mipi_dsi.c
+++ b/drivers/video/fbdev/sh_mipi_dsi.c
@@ -113,11 +113,18 @@ static int sh_mipi_dcs_param(int handle, u8 cmd, u8 param)
 
 static void sh_mipi_dsi_enable(struct sh_mipi *mipi, bool enable)
 {
+	unsigned int enable_value;
+
+	if (enable)
+		enable_value = 0x00000003;
+	else
+		enable_value = 0x00000002;
+
 	/*
 	 * enable LCDC data tx, transition to LPS after completion of each HS
 	 * packet
 	 */
-	iowrite32(0x00000002 | enable, mipi->linkbase + DTCTR);
+	iowrite32(enable_value, mipi->linkbase + DTCTR);
 }
 
 static void sh_mipi_shutdown(struct platform_device *pdev)
-- 
1.7.10.4


^ permalink raw reply related

* [PATCH] video: fbdev: sh_mipi_dsi.c:  Cleaning up Boolean used in bitwise operation
From: Rickard Strandqvist @ 2014-07-02 21:57 UTC (permalink / raw)
  To: Jean-Christophe Plagniol-Villard, Tomi Valkeinen
  Cc: Rickard Strandqvist, Jingoo Han, Laurent Pinchart, Rob Clark,
	linux-fbdev, linux-kernel

Boolean variable is used in bitwise operation.
I personally find that this was pretty ugly, but think a solution like this yet is more correct.

This was found using a static code analysis program called cppcheck

Rickard Strandqvist (1):
  video: fbdev: sh_mipi_dsi.c:  Cleaning up Boolean used in bitwise operation

 drivers/video/fbdev/sh_mipi_dsi.c |    9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

-- 
1.7.10.4


^ permalink raw reply

* [PATCH] video: fbdev: matrox: matroxfb_base.c:  Fix for possible null pointer dereference
From: Rickard Strandqvist @ 2014-07-02 21:45 UTC (permalink / raw)
  To: Jean-Christophe Plagniol-Villard, Tomi Valkeinen
  Cc: Rickard Strandqvist, Jingoo Han, Alexandru Juncu, Mikulas Patocka,
	Daniel Vetter, Joe Perches, linux-fbdev, linux-kernel

Fix a possible null pointer dereference, there is otherwise a risk of a possible null pointer dereference

This was found using a static code analysis program called cppcheck

Signed-off-by: Rickard Strandqvist <rickard_strandqvist@spectrumdigital.se>
---
 drivers/video/fbdev/matrox/matroxfb_base.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/video/fbdev/matrox/matroxfb_base.c b/drivers/video/fbdev/matrox/matroxfb_base.c
index 7116c53..85ef84b 100644
--- a/drivers/video/fbdev/matrox/matroxfb_base.c
+++ b/drivers/video/fbdev/matrox/matroxfb_base.c
@@ -1971,9 +1971,9 @@ static void matroxfb_register_device(struct matrox_fb_info* minfo) {
 	int i = 0;
 	list_add(&minfo->next_fb, &matroxfb_list);
 	for (drv = matroxfb_driver_l(matroxfb_driver_list.next);
-	     drv != matroxfb_driver_l(&matroxfb_driver_list);
+	     drv && drv != matroxfb_driver_l(&matroxfb_driver_list);
 	     drv = matroxfb_driver_l(drv->node.next)) {
-		if (drv && drv->probe) {
+		if (drv->probe) {
 			void *p = drv->probe(minfo);
 			if (p) {
 				minfo->drivers_data[i] = p;
-- 
1.7.10.4


^ permalink raw reply related

* [PATCH] video: fbdev: core: fbmon.c:  Fix for possible null pointer dereference
From: Rickard Strandqvist @ 2014-07-02 21:44 UTC (permalink / raw)
  To: Jean-Christophe Plagniol-Villard, Tomi Valkeinen
  Cc: Rickard Strandqvist, Jingoo Han, Daniel Vetter, Laurent Pinchart,
	Rob Clark, David Ung, linux-fbdev, linux-kernel

Fix a possible null pointer dereference, there is otherwise a risk of a possible null pointer dereference

This was found using a static code analysis program called cppcheck

Signed-off-by: Rickard Strandqvist <rickard_strandqvist@spectrumdigital.se>
---
 drivers/video/fbdev/core/fbmon.c |   11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/video/fbdev/core/fbmon.c b/drivers/video/fbdev/core/fbmon.c
index 5b0e313..9ec81ee 100644
--- a/drivers/video/fbdev/core/fbmon.c
+++ b/drivers/video/fbdev/core/fbmon.c
@@ -608,6 +608,11 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
 	int num = 0, i, first = 1;
 	int ver, rev;
 
+	if (edid = NULL || !edid_checksum(edid) ||
+		!edid_check_header(edid)) {
+		return NULL;
+	}
+
 	ver = edid[EDID_STRUCT_VERSION];
 	rev = edid[EDID_STRUCT_REVISION];
 
@@ -615,12 +620,6 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
 	if (mode = NULL)
 		return NULL;
 
-	if (edid = NULL || !edid_checksum(edid) ||
-	    !edid_check_header(edid)) {
-		kfree(mode);
-		return NULL;
-	}
-
 	*dbsize = 0;
 
 	DPRINTK("   Detailed Timings\n");
-- 
1.7.10.4


^ permalink raw reply related

* [PATCH] video: fbdev: broadsheetfb.c:  Fix a memory leak
From: Rickard Strandqvist @ 2014-07-02 21:31 UTC (permalink / raw)
  To: Jean-Christophe Plagniol-Villard, Tomi Valkeinen
  Cc: Rickard Strandqvist, Jingoo Han, Daniel Vetter, Joe Perches,
	Hanjun Guo, linux-fbdev, linux-kernel

Fix a memory leak.

This was found using a static code analysis program called cppcheck

Signed-off-by: Rickard Strandqvist <rickard_strandqvist@spectrumdigital.se>
---
 drivers/video/fbdev/broadsheetfb.c |    9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/video/fbdev/broadsheetfb.c b/drivers/video/fbdev/broadsheetfb.c
index 8556264..526e5e84 100644
--- a/drivers/video/fbdev/broadsheetfb.c
+++ b/drivers/video/fbdev/broadsheetfb.c
@@ -636,7 +636,7 @@ static int broadsheet_spiflash_rewrite_sector(struct broadsheetfb_par *par,
 		err = broadsheet_spiflash_read_range(par, start_sector_addr,
 						data_start_addr, sector_buffer);
 		if (err)
-			return err;
+			goto end_release;
 	}
 
 	/* now we copy our data into the right place in the sector buffer */
@@ -657,7 +657,7 @@ static int broadsheet_spiflash_rewrite_sector(struct broadsheetfb_par *par,
 		err = broadsheet_spiflash_read_range(par, tail_start_addr,
 			tail_len, sector_buffer + tail_start_addr);
 		if (err)
-			return err;
+			goto end_release;
 	}
 
 	/* if we got here we have the full sector that we want to rewrite. */
@@ -665,11 +665,14 @@ static int broadsheet_spiflash_rewrite_sector(struct broadsheetfb_par *par,
 	/* first erase the sector */
 	err = broadsheet_spiflash_erase_sector(par, start_sector_addr);
 	if (err)
-		return err;
+		goto end_release;
 
 	/* now write it */
 	err = broadsheet_spiflash_write_sector(par, start_sector_addr,
 					sector_buffer, sector_size);
+
+end_release:
+	kfree(sector_buffer);
 	return err;
 }
 
-- 
1.7.10.4


^ permalink raw reply related

* Re: [PATCH 5/5] drm/i915: Kick out vga console
From: Ed Tomlinson @ 2014-07-01 13:51 UTC (permalink / raw)
  To: Chris Wilson
  Cc: linux-fbdev, Dave Airlie, Daniel Vetter,
	Intel Graphics Development, LKML, DRI Development, Tomi Valkeinen,
	David Herrmann, Jean-Christophe Plagniol-Villard
In-Reply-To: <20140630065955.GD7687@nuc-i3427.alporthouse.com>

Hi Chris,

I had to rediff to get a patch that applies...  I am not hanging with this applied - it
does look like the i915 is starting is initialization later boot the new kernel.

[    2.389796] [drm] Radeon Display Connectors
[    2.389798] [drm] Connector 0:
[    2.389799] [drm]   DP-1
[    2.389799] [drm]   HPD2
[    2.389801] [drm]   DDC: 0x6530 0x6530 0x6534 0x6534 0x6538 0x6538 0x653c 0x653c
[    2.389802] [drm]   Encoders:
[    2.389803] [drm]     DFP1: INTERNAL_UNIPHY2
[    2.389804] [drm] Connector 1:
[    2.389805] [drm]   HDMI-A-1
[    2.389805] [drm]   HPD3
[    2.389806] [drm]   DDC: 0x6550 0x6550 0x6554 0x6554 0x6558 0x6558 0x655c 0x655c
[    2.389807] [drm]   Encoders:
[    2.389808] [drm]     DFP2: INTERNAL_UNIPHY2
[    2.389809] [drm] Connector 2:
[    2.389810] [drm]   DVI-D-1
[    2.389811] [drm]   HPD1
[    2.389812] [drm]   DDC: 0x6560 0x6560 0x6564 0x6564 0x6568 0x6568 0x656c 0x656c
[    2.389813] [drm]   Encoders:
[    2.389814] [drm]     DFP3: INTERNAL_UNIPHY1
[    2.389815] [drm] Connector 3:
[    2.389815] [drm]   DVI-I-1
[    2.389816] [drm]   HPD6
[    2.389817] [drm]   DDC: 0x6580 0x6580 0x6584 0x6584 0x6588 0x6588 0x658c 0x658c
[    2.389818] [drm]   Encoders:
[    2.389819] [drm]     DFP4: INTERNAL_UNIPHY
[    2.389820] [drm]     CRT1: INTERNAL_KLDSCP_DAC1
[    2.435689] raid6: avx2x2   24564 MB/s
[    2.435691] Switched to clocksource tsc
[    2.489087] usb 1-8: new low-speed USB device number 7 using xhci_hcd
[    2.492403] raid6: avx2x4   34887 MB/s
[    2.492404] raid6: using algorithm avx2x4 (34887 MB/s)
[    2.492405] raid6: using avx2x2 recovery algorithm
[    2.492789] xor: automatically using best checksumming function:
[    2.502557] Adding 5779452k swap on /dev/sdb2.  Priority:-2 extents:1 across:5779452k FS
[    2.511532] [drm] fb mappable at 0xE098E000
[    2.511536] [drm] vram apper at 0xE0000000
[    2.511538] [drm] size 9216000
[    2.511539] [drm] fb depth is 24
[    2.511541] [drm]    pitch is 7680
[    2.511590] fbcon: radeondrmfb (fb0) is primary device
[    2.516691] nct6775: Found NCT6776D/F or compatible chip at 0x2e:0x290
[    2.525778]    avx       : 41474.400 MB/sec
[    2.532408] Console: switching to colour frame buffer device 240x75
[    2.535567] radeon 0000:01:00.0: fb0: radeondrmfb frame buffer device
[    2.535567] radeon 0000:01:00.0: registered panic notifier
[    2.544968] Btrfs loaded
[    2.545276] BTRFS: device fsid 9d4254aa-6715-4fa8-986a-1af0d51768ad devid 1 transid 308068 /dev/sdc1
[    2.545739] BTRFS: device fsid 9d4254aa-6715-4fa8-986a-1af0d51768ad devid 2 transid 308068 /dev/sdb1
[    2.552946] [drm] Initialized radeon 2.39.0 20080528 for 0000:01:00.0 on minor 0
[    2.553248] [drm] Memory usable by graphics device = 2048M
[    2.553273] [drm] Replacing VGA console driver
[    2.572539] i915 0000:00:02.0: irq 46 for MSI/MSI-X
[    2.572546] [drm] Supports vblank timestamp caching Rev 2 (21.10.2013).
[    2.572565] [drm] Driver supports precise vblank timestamp query.

If you are happy with this you can give this patch my tested by.

Thanks
Ed Tomlinson

On Monday 30 June 2014 07:59:55 Chris Wilson wrote:
> On Sat, Jun 28, 2014 at 11:55:19PM -0400, Ed Tomlinson wrote:
> > On Saturday 28 June 2014 15:28:22 Ed Tomlinson wrote:
> > 
> > Resend without html krud which causes list to bounce the message.
> > 
> > > Hi
> > > 
> > > This commit ( a4de05268e674e8ed31df6348269e22d6c6a1803 ) hangs my boot with 3.16-git.  Reverting it lets the boot proceed. 
> > > 
> > > I have an i7 with a built-in i915 and an pcie r7 260x.  The R7 is the primary console.  The i915 is initialized
> > > but does not have a physical display attached.
> > > 
> > > With the patch applied the boot stops at the messages:
> > > 
> > > [drm] Memory usable by graphics device = 2048M
> > > [drm] Replacing VGA console driver
> 
> The issue looks like that we are ripping out the radeon fb_con whilst it
> is active and that upsets everyone. In which case, I think the
> compromise is:
> 
> 
> diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> index 5f44581..4915f1d 100644
> --- a/drivers/gpu/drm/i915/i915_dma.c
> +++ b/drivers/gpu/drm/i915/i915_dma.c
> @@ -1439,18 +1439,20 @@ static int i915_kick_out_vgacon(struct drm_i915_private *dev_priv)
>  #else
>  static int i915_kick_out_vgacon(struct drm_i915_private *dev_priv)
>  {
> -       int ret;
> +       int ret = 0;
>  
>         DRM_INFO("Replacing VGA console driver\n");
>  
>         console_lock();
> -       ret = do_take_over_console(&dummy_con, 0, MAX_NR_CONSOLES - 1, 1);
> -       if (ret = 0) {
> -               ret = do_unregister_con_driver(&vga_con);
> -
> -               /* Ignore "already unregistered". */
> -               if (ret = -ENODEV)
> -                       ret = 0;
> +       if (con_is_bound(&vga_con)) {
> +               ret = do_take_over_console(&dummy_con, 0, MAX_NR_CONSOLES - 1, 1);
> +               if (ret = 0) {
> +                       ret = do_unregister_con_driver(&vga_con);
> +
> +                       /* Ignore "already unregistered". */
> +                       if (ret = -ENODEV)
> +                               ret = 0;
> +               }
>         }
>         console_unlock();
> 
> -Chris
> 
> 


^ permalink raw reply

* [GIT PULL] fbdev fixes for 3.16
From: Tomi Valkeinen @ 2014-07-01 11:31 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Linux Fbdev development list, LKML

[-- Attachment #1: Type: text/plain, Size: 1281 bytes --]

Hi Linus,

The following changes since commit a497c3ba1d97fc69c1e78e7b96435ba8c2cb42ee:

  Linux 3.16-rc2 (2014-06-21 19:02:54 -1000)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux.git tags/fbdev-fixes-3.16

for you to fetch changes up to 0b479c3db63303814c1d2f8e97497db6be1caaa4:

  fb: adv7393: add missing semicolon (2014-07-01 13:18:38 +0300)

----------------------------------------------------------------
fbdev fixes for 3.16

A few minor fbdev fixes for bfin_adv7393fb, omapdss, vt8500lcdfb, atmel_lcdfb.

----------------------------------------------------------------
Emil Goode (1):
      video: vt8500lcdfb: Remove kfree call since devm_kzalloc() is used

Michael Welling (1):
      drivers:video:fbdev atmel_lcdfb.c power GPIO registration bug

Sachin Kamat (1):
      video: omapdss: Fix potential null pointer dereference

Scott Jiang (1):
      fb: adv7393: add missing semicolon

 drivers/video/fbdev/atmel_lcdfb.c                 | 2 ++
 drivers/video/fbdev/bfin_adv7393fb.c              | 2 +-
 drivers/video/fbdev/omap2/dss/omapdss-boot-init.c | 8 +++++---
 drivers/video/fbdev/vt8500lcdfb.c                 | 2 --
 4 files changed, 8 insertions(+), 6 deletions(-)


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply

* Re: [PATCH] fb: adv7393: add missing semicolon
From: Tomi Valkeinen @ 2014-07-01 10:33 UTC (permalink / raw)
  To: linux-fbdev
In-Reply-To: <1404284022-24866-1-git-send-email-scott.jiang.linux@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 1019 bytes --]

On 02/07/14 09:53, Scott Jiang wrote:
> Commit f8bd493456c3da372ae81ed8f6b903f6207b9d98 by Jingoo Han
> introduced this problem. This makes bfin_adv7393fb.c failed to compile.
> 
> Signed-off-by: Scott Jiang <scott.jiang.linux@gmail.com>
> ---
>  drivers/video/fbdev/bfin_adv7393fb.c |    2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/video/fbdev/bfin_adv7393fb.c b/drivers/video/fbdev/bfin_adv7393fb.c
> index a54f7f7..8fe41ca 100644
> --- a/drivers/video/fbdev/bfin_adv7393fb.c
> +++ b/drivers/video/fbdev/bfin_adv7393fb.c
> @@ -408,7 +408,7 @@ static int bfin_adv7393_fb_probe(struct i2c_client *client,
>  	/* Workaround "PPI Does Not Start Properly In Specific Mode" */
>  	if (ANOMALY_05000400) {
>  		ret = gpio_request_one(P_IDENT(P_PPI0_FS3), GPIOF_OUT_INIT_LOW,
> -					"PPI0_FS3")
> +					"PPI0_FS3");
>  		if (ret) {
>  			dev_err(&client->dev, "PPI0_FS3 GPIO request failed\n");
>  			ret = -EBUSY;
> 

Thanks, queued for 3.16 fixes.

 Tomi



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply

* Re: [PATCH 2/2] video: clps711x: Fix sparse warnings
From: Alexander Shiyan @ 2014-07-01 10:31 UTC (permalink / raw)
  To: linux-fbdev
In-Reply-To: <1374825597.724071106@f170.mail.ru>

VHVlLCAxIEp1bCAyMDE0IDEzOjIyOjUxICswMzAwINC+0YIgVG9taSBWYWxrZWluZW4gPHRvbWku
dmFsa2VpbmVuQHRpLmNvbT46Cj4gT24gMDEvMDcvMTQgMDk6MjMsIEFsZXhhbmRlciBTaGl5YW4g
d3JvdGU6Cj4gPiBUdWUsIDEgSnVsIDIwMTQgMDk6MTQ6MDIgKzAzMDAg0L7RgiBUb21pIFZhbGtl
aW5lbiA8dG9taS52YWxrZWluZW5AdGkuY29tPjoKPiA+PiBPbiAyOC8wNi8xNCAwOTozNCwgQWxl
eGFuZGVyIFNoaXlhbiB3cm90ZToKPiA+Pj4gVGhpcyBwYXRjaCBmaXhlcyBiZWxvdyB3YXJuaW5n
czoKPiA+Pj4gQ0hFQ0sgICBkcml2ZXJzL3ZpZGVvL2ZiZGV2L2NscHM3MTF4LWZiLmMKPiA+Pj4g
ICBkcml2ZXJzL3ZpZGVvL2ZiZGV2L2NscHM3MTF4LWZiLmM6MjQ3OjI0OiB3YXJuaW5nOiBpbmNv
cnJlY3QgdHlwZSBpbiBhcmd1bWVudCAxIChkaWZmZXJlbnQgYWRkcmVzcyBzcGFjZXMpCj4gPj4+
ICAgZHJpdmVycy92aWRlby9mYmRldi9jbHBzNzExeC1mYi5jOjI0NzoyNDogICAgZXhwZWN0ZWQg
dm9pZCBjb25zdCAqcHRyCj4gPj4+ICAgZHJpdmVycy92aWRlby9mYmRldi9jbHBzNzExeC1mYi5j
OjI0NzoyNDogICAgZ290IGNoYXIgW25vZGVyZWZdIDxhc246Mj4qc2NyZWVuX2Jhc2UKPiA+Pj4g
ICBkcml2ZXJzL3ZpZGVvL2ZiZGV2L2NscHM3MTF4LWZiLmM6MjQ4OjM1OiB3YXJuaW5nOiBpbmNv
cnJlY3QgdHlwZSBpbiBhcmd1bWVudCAxIChkaWZmZXJlbnQgYWRkcmVzcyBzcGFjZXMpCj4gPj4+
ICAgZHJpdmVycy92aWRlby9mYmRldi9jbHBzNzExeC1mYi5jOjI0ODozNTogICAgZXhwZWN0ZWQg
dm9pZCBjb25zdCAqcHRyCj4gPj4+ICAgZHJpdmVycy92aWRlby9mYmRldi9jbHBzNzExeC1mYi5j
OjI0ODozNTogICAgZ290IGNoYXIgW25vZGVyZWZdIDxhc246Mj4qc2NyZWVuX2Jhc2UKPiA+IC4u
Lgo+ID4+PiAgCWluZm8tPnNjcmVlbl9iYXNlID0gZGV2bV9pb3JlbWFwX3Jlc291cmNlKGRldiwg
cmVzKTsKPiA+Pj4gLQlpZiAoSVNfRVJSKGluZm8tPnNjcmVlbl9iYXNlKSkgewo+ID4+PiAtCQly
ZXQgPSBQVFJfRVJSKGluZm8tPnNjcmVlbl9iYXNlKTsKPiA+Pj4gKwlpZiAoSVNfRVJSKChfX2Zv
cmNlIHZvaWQgKilpbmZvLT5zY3JlZW5fYmFzZSkpIHsKPiA+Pj4gKwkJcmV0ID0gUFRSX0VSUigo
X19mb3JjZSB2b2lkICopaW5mby0+c2NyZWVuX2Jhc2UpOwo+ID4+Cj4gPj4gSSBkb24ndCBzZWUg
YW55IG90aGVyIHVzZXIgb2YgZGV2bV9pb3JlbWFwX3Jlc291cmNlKCkgaGF2aW5nIHRoYXQga2lu
ZAo+ID4+IG9mIGNhc3RzLiBXaHkgYXJlIHRoZXkgbmVlZGVkIGhlcmU/Cj4gPiAKPiA+IE5vdCBu
ZWVkZWQsIHR5cGUgY2FzdCB3YXMgZG9uZSBvbmx5IHRvIHJlbW92ZSBzcGFyc2Ugd2FybmluZ3Mu
Cj4gCj4gUmlnaHQsIGJ1dCBJIHRoaW5rIGVpdGhlciBzcGFyc2UgaXMgd3JvbmcgaGVyZSwgb3Ig
dGhlIFBUUl9FUlIvSVNfRVJSCj4gYXJlIHdyb25nLiBZb3Ugc2hvdWxkbid0IGRvIHR5cGVjYXN0
cyBsaWtlIHRoYXQgdG8gaGlkZSB0aG9zZSB3YXJuaW5ncy4KCldlbGwsIEknbGwgcmVtb3ZlIHRo
ZXNlIGNoYW5nZXMgYW5kIHNlbmQgYSBzZWNvbmQgdmVyc2lvbiBvZiB0aGUgcGF0Y2guCgotLS0K
Cg=

^ permalink raw reply

* Re: [PATCH 2/2] video: clps711x: Fix sparse warnings
From: Tomi Valkeinen @ 2014-07-01 10:22 UTC (permalink / raw)
  To: linux-fbdev
In-Reply-To: <1403937246-14506-2-git-send-email-shc_work@mail.ru>

[-- Attachment #1: Type: text/plain, Size: 1517 bytes --]

On 01/07/14 09:23, Alexander Shiyan wrote:
> Tue, 1 Jul 2014 09:14:02 +0300 от Tomi Valkeinen <tomi.valkeinen@ti.com>:
>> On 28/06/14 09:34, Alexander Shiyan wrote:
>>> This patch fixes below warnings:
>>> CHECK   drivers/video/fbdev/clps711x-fb.c
>>>   drivers/video/fbdev/clps711x-fb.c:247:24: warning: incorrect type in argument 1 (different address spaces)
>>>   drivers/video/fbdev/clps711x-fb.c:247:24:    expected void const *ptr
>>>   drivers/video/fbdev/clps711x-fb.c:247:24:    got char [noderef] <asn:2>*screen_base
>>>   drivers/video/fbdev/clps711x-fb.c:248:35: warning: incorrect type in argument 1 (different address spaces)
>>>   drivers/video/fbdev/clps711x-fb.c:248:35:    expected void const *ptr
>>>   drivers/video/fbdev/clps711x-fb.c:248:35:    got char [noderef] <asn:2>*screen_base
> ...
>>>  	info->screen_base = devm_ioremap_resource(dev, res);
>>> -	if (IS_ERR(info->screen_base)) {
>>> -		ret = PTR_ERR(info->screen_base);
>>> +	if (IS_ERR((__force void *)info->screen_base)) {
>>> +		ret = PTR_ERR((__force void *)info->screen_base);
>>
>> I don't see any other user of devm_ioremap_resource() having that kind
>> of casts. Why are they needed here?
> 
> Not needed, type cast was done only to remove sparse warnings.

Right, but I think either sparse is wrong here, or the PTR_ERR/IS_ERR
are wrong. You shouldn't do typecasts like that to hide those warnings.

The memset warning is correct, because you shouldn't use memset to
__iomem memory.

 Tomi



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox