Linux Framebuffer Layer development
 help / color / mirror / Atom feed
* [PATCH 1/5] ARM: dts: vf610: Add DCU and TCON nodes
From: Alison Wang @ 2013-07-12  6:07 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1373609276-14566-1-git-send-email-b18965@freescale.com>

This patch adds DCU and TCON nodes in SoC level DTS for Freescale
Vybrid VF610. It also removes useless pin for DCU0 pinctrl.

Signed-off-by: Alison Wang <b18965@freescale.com>
---
Changes in v2: None

 arch/arm/boot/dts/vf610.dtsi | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/vf610.dtsi b/arch/arm/boot/dts/vf610.dtsi
index e1eb7da..037e8f1 100644
--- a/arch/arm/boot/dts/vf610.dtsi
+++ b/arch/arm/boot/dts/vf610.dtsi
@@ -140,6 +140,14 @@
 				clock-names = "pit";
 			};
 
+			tcon0: tcon@4003d000 {
+				compatible = "fsl,vf610-tcon";
+				reg = <0x4003d000 0x1000>;
+				clocks = <&clks VF610_CLK_TCON0>;
+				clock-names = "tcon";
+				status = "disabled";
+			};
+
 			wdog@4003e000 {
 				compatible = "fsl,vf610-wdt", "fsl,imx21-wdt";
 				reg = <0x4003e000 0x1000>;
@@ -169,7 +177,6 @@
 				dcu0 {
 					pinctrl_dcu0_1: dcu0grp_1 {
 						fsl,pins = <
-						VF610_PAD_PTB8__GPIO_30		0x42
 						VF610_PAD_PTE0__DCU0_HSYNC	0x42
 						VF610_PAD_PTE1__DCU0_VSYNC	0x42
 						VF610_PAD_PTE2__DCU0_PCLK	0x42
@@ -395,6 +402,16 @@
 				reg = <0x40050000 0x1000>;
 			};
 
+			dcu0: dcu@40058000 {
+				compatible = "fsl,vf610-dcu";
+				reg = <0x40058000 0x1200>;
+				interrupts = <0 30 0x04>;
+				clocks = <&clks VF610_CLK_DCU0>;
+				clock-names = "dcu";
+				tcon-controller = <&tcon0>;
+				status = "disabled";
+			};
+
 			i2c0: i2c@40066000 {
 				#address-cells = <1>;
 				#size-cells = <0>;
-- 
1.8.0



^ permalink raw reply related

* [PATCH v2 0/5] ARM: vf610: Add DCU framebuffer driver for Vybrid VF610 platform
From: Alison Wang @ 2013-07-12  6:07 UTC (permalink / raw)
  To: linux-arm-kernel

This series contain DCU framebuffer driver for Freescale Vybrid VF610 platform.

The Display Controller Unit (DCU) module is a system master that
fetches graphics stored in internal or external memory and displays
them on a TFT LCD panel. A wide range of panel sizes is supported
and the timing of the interface signals is highly configurable.
Graphics are read directly from memory and then blended in real-time,
which allows for dynamic content creation with minimal CPU intervention.

The features:

(1) Full RGB888 output to TFT LCD panel.
(2) For the current LCD panel, WQVGA "480x272" is tested.
(3) Blending of each pixel using up to 4 source layers dependent on size of panel.
(4) Each graphic layer can be placed with one pixel resolution in either axis.
(5) Each graphic layer support RGB565 and RGB888 direct colors without alpha channel
and BGRA8888 direct colors with an alpha channel.
(6) Each graphic layer support alpha blending with 8-bit resolution.

Changes in v2:
- Add a document for DCU framebuffer driver under Documentation/devicetree/bindings/fb/.

----------------------------------------------------------------
Alison Wang (5):
      ARM: dts: vf610: Add DCU and TCON nodes
      ARM: dts: vf610-twr: Enable DCU and TCON devices
      ARM: clk: vf610: Add DCU and TCON clock support
      fb: Add DCU framebuffer driver for Vybrid VF610 platform
      Documentation: DT: Add DCU framebuffer driver

 Documentation/devicetree/bindings/fb/fsl-dcu-fb.txt |   36 ++++
 arch/arm/boot/dts/vf610-twr.dts                     |   10 +
 arch/arm/boot/dts/vf610.dtsi                        |   19 +-
 arch/arm/mach-imx/clk-vf610.c                       |    5 +
 drivers/video/Kconfig                               |    9 +
 drivers/video/Makefile                              |    1 +
 drivers/video/fsl-dcu-fb.c                          | 1091 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 include/dt-bindings/clock/vf610-clock.h             |    3 +-
 8 files changed, 1172 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/fb/fsl-dcu-fb.txt
 create mode 100644 drivers/video/fsl-dcu-fb.c



^ permalink raw reply

* RE: [PATCH 1/1] OMAPDSS: Add sil9022 driver
From: Pulukuru, Srinivas @ 2013-07-11 16:41 UTC (permalink / raw)
  To: Jean-Christophe PLAGNIOL-VILLARD, Prakash, Sathya
  Cc: Valkeinen, Tomi, Taneja, Archit, linux-omap@vger.kernel.org,
	linux-fbdev@vger.kernel.org
In-Reply-To: <20130709134033.GD18477@ns203013.ovh.net>

THis was a demo patch done to enable basic HDMI display on OMAP3 which somehow got pushed into the regular builds on OMAP3 deliverables and has since been floating around. This is not a production code that can be upstreamed. Please abandon this patch and do not up-stream in the present form. Except basic display via HDMI, there is no other functionality in this patch.

Regards,
Srinivas Pulukuru


-----Original Message-----
From: Jean-Christophe PLAGNIOL-VILLARD [mailto:plagnioj@jcrosoft.com] 
Sent: Tuesday, July 09, 2013 8:41 AM
To: Prakash, Sathya
Cc: Valkeinen, Tomi; Taneja, Archit; linux-omap@vger.kernel.org; linux-fbdev@vger.kernel.org; Pulukuru, Srinivas
Subject: Re: [PATCH 1/1] OMAPDSS: Add sil9022 driver

HI,

	Tomi can you take a look at this one your are back

Best Regards,
J.
On 14:37 Tue 09 Jul     , Sathya Prakash M R wrote:
> From: Srinivas Pulukuru <srinivas.pulukuru@ti.com>
> 
> Add driver for SIL9022 DPI-to-HDMI chip.
> 
> Signed-off-by: Srinivas Pulukuru <srinivas.pulukuru@ti.com>
> [sathyap@ti.com: Ported the driver from 2.6.32 based internal
> kernel to v3.10 kernel]
> Signed-off-by: Sathya Prakash M R <sathyap@ti.com>
> ---
> This patch was tested using the legacy OMAP3630 based Zoom3 platform.
> There is no DT support for Zoom , hence board file changes
> made locally were used for validation purpose. 
> Further, DT support will be added for a newer SOC which uses
> the sil9022 HDMI interface chip.
> 
>  drivers/video/omap2/displays/Kconfig         |    8 +
>  drivers/video/omap2/displays/Makefile        |    1 +
>  drivers/video/omap2/displays/panel-sil9022.c | 1274 ++++++++++++++++++++++++++
>  drivers/video/omap2/displays/panel-sil9022.h |  527 +++++++++++
>  4 files changed, 1810 insertions(+)
>  create mode 100644 drivers/video/omap2/displays/panel-sil9022.c
>  create mode 100644 drivers/video/omap2/displays/panel-sil9022.h
> 
> diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig
> index c3853c9..53d8bb7 100644
> --- a/drivers/video/omap2/displays/Kconfig
> +++ b/drivers/video/omap2/displays/Kconfig
> @@ -39,6 +39,14 @@ config PANEL_NEC_NL8048HL11_01B
>  		This NEC NL8048HL11-01B panel is TFT LCD
>  		used in the Zoom2/3/3630 sdp boards.
>  
> +config PANEL_SIL9022
> +	tristate "HDMI interface"
> +        depends on OMAP2_DSS_DPI
> +	depends on I2C
> +	help
> +		Driver for SIL9022 DPI-to-HDMI chip
> +		Driver uses i2c to read EDID information.
> +
>  config PANEL_PICODLP
>  	tristate "TI PICO DLP mini-projector"
>  	depends on OMAP2_DSS_DPI && I2C
> diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile
> index 58a5176..34cfa8e 100644
> --- a/drivers/video/omap2/displays/Makefile
> +++ b/drivers/video/omap2/displays/Makefile
> @@ -3,6 +3,7 @@ obj-$(CONFIG_PANEL_TFP410) += panel-tfp410.o
>  obj-$(CONFIG_PANEL_LGPHILIPS_LB035Q02) += panel-lgphilips-lb035q02.o
>  obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
>  obj-$(CONFIG_PANEL_NEC_NL8048HL11_01B) += panel-nec-nl8048hl11-01b.o
> +obj-$(CONFIG_PANEL_SIL9022) += panel-sil9022.o
>  
>  obj-$(CONFIG_PANEL_TAAL) += panel-taal.o
>  obj-$(CONFIG_PANEL_PICODLP) +=  panel-picodlp.o
> diff --git a/drivers/video/omap2/displays/panel-sil9022.c b/drivers/video/omap2/displays/panel-sil9022.c
> new file mode 100644
> index 0000000..3b5cb17
> --- /dev/null
> +++ b/drivers/video/omap2/displays/panel-sil9022.c
> @@ -0,0 +1,1274 @@
> +/*
> + * drivers/video/omap2/panel-sil9022.c
> + *
> + * Copyright (C) 2009 Texas Instruments
> + *
> + * 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.
> + *
> + * SIL9022 hdmi driver
> + * Owner: kiran Chitriki
> + *
> + */
> +
> +/***********************************/
> +#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 <video/omapdss.h>
> +#include <video/omap-panel-data.h>
> +#include "panel-sil9022.h"
> +
> +u16 current_descriptor_addrs;
> +
> +static struct i2c_client *sil9022_client;
> +
> +static struct omap_video_timings omap_dss_hdmi_timings = {
> +	.x_res          = HDMI_XRES,
> +	.y_res          = HDMI_YRES,
> +	.pixel_clock    = HDMI_PIXCLOCK_MAX,
> +	.hfp            = 110,
> +	.hbp            = 220,
> +	.hsw            = 40,
> +	.vfp            = 5,
> +	.vbp            = 20,
> +	.vsw            = 5,
> +	.vsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
> +	.hsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
> +	.data_pclk_edge	= OMAPDSS_DRIVE_SIG_RISING_EDGE,
> +	.de_level	= OMAPDSS_SIG_ACTIVE_HIGH,
> +	.sync_pclk_edge	= OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
> +};
> +
> +static struct hdmi_reg_data  hdmi_tpi_audio_config_data[] = {
> +	/* Transmitter is brought to Full operation when value of power
> +	 * state register is 0x0 */
> +	{ HDMI_TPI_POWER_STATE_CTRL_REG, TPI_AVI_POWER_STATE_D0		 },
> +	/* TMDS output lines active. bit 3 1:TMDS inactive, 0: TMDS active */
> +	{ HDMI_SYS_CTRL_DATA_REG,  0x01					 },
> +	/*HDCP Enable - Disable */
> +	{ HDMI_TPI_HDCP_CONTROLDATA_REG, 0				 },
> +	/* I2S mode , Mute Enabled , PCM */
> +	{ HDMI_TPI_AUDIO_CONFIG_BYTE2_REG, TPI_AUDIO_INTERFACE_I2S |
> +					    TPI_AUDIO_MUTE_ENABLE |
> +					    TPI_AUDIO_CODING_PCM	 },
> +	/* I2S Input configuration register */
> +	{ HDMI_TPI_I2S_INPUT_CONFIG_REG, TPI_I2S_SCK_EDGE_RISING |
> +					TPI_I2S_MCLK_MULTIPLIER_256 |
> +					TPI_I2S_WS_POLARITY_HIGH |
> +					TPI_I2S_SD_JUSTIFY_LEFT |
> +					TPI_I2S_SD_DIRECTION_MSB_FIRST |
> +					TPI_I2S_FIRST_BIT_SHIFT_YES	 },
> +	/* I2S Enable ad Mapping Register */
> +	{ HDMI_TPI_I2S_ENABLE_MAPPING_REG, TPI_I2S_SD_CHANNEL_ENABLE |
> +					    TPI_I2S_SD_FIFO_0 |
> +					    TPI_I2S_DOWNSAMPLE_DISABLE |
> +					    TPI_I2S_LF_RT_SWAP_NO |
> +					    TPI_I2S_SD_CONFIG_SELECT_SD0 },
> +	{ HDMI_TPI_I2S_ENABLE_MAPPING_REG, TPI_I2S_SD_CHANNEL_DISABLE |
> +					    TPI_I2S_SD_FIFO_1 |
> +					    TPI_I2S_DOWNSAMPLE_DISABLE |
> +					    TPI_I2S_LF_RT_SWAP_NO |
> +					    TPI_I2S_SD_CONFIG_SELECT_SD1 },
> +	{ HDMI_TPI_I2S_ENABLE_MAPPING_REG, TPI_I2S_SD_CHANNEL_DISABLE |
> +					    TPI_I2S_SD_FIFO_2 |
> +					    TPI_I2S_DOWNSAMPLE_DISABLE |
> +					    TPI_I2S_LF_RT_SWAP_NO |
> +					    TPI_I2S_SD_CONFIG_SELECT_SD2 },
> +	{ HDMI_TPI_I2S_ENABLE_MAPPING_REG, TPI_I2S_SD_CHANNEL_DISABLE |
> +					    TPI_I2S_SD_FIFO_3 |
> +					    TPI_I2S_DOWNSAMPLE_DISABLE |
> +					    TPI_I2S_LF_RT_SWAP_NO |
> +					    TPI_I2S_SD_CONFIG_SELECT_SD3 },
> +	{ HDMI_TPI_AUDIO_CONFIG_BYTE3_REG, TPI_AUDIO_SAMPLE_SIZE_16 |
> +					     TPI_AUDIO_FREQ_44KHZ |
> +					     TPI_AUDIO_2_CHANNEL	 },
> +	/* Speaker Configuration  refer CEA Specification*/
> +	{ HDMI_TPI_AUDIO_CONFIG_BYTE4_REG, (0x0 << 0)},
> +	/* Stream Header Settings */
> +	{ HDMI_TPI_I2S_STRM_HDR_0_REG, I2S_CHAN_STATUS_MODE		 },
> +	{ HDMI_TPI_I2S_STRM_HDR_1_REG, I2S_CHAN_STATUS_CAT_CODE	},
> +	{ HDMI_TPI_I2S_STRM_HDR_2_REG, I2S_CHAN_SOURCE_CHANNEL_NUM	 },
> +	{ HDMI_TPI_I2S_STRM_HDR_3_REG, I2S_CHAN_ACCURACY_N_44_SAMPLING_FS },
> +	{ HDMI_TPI_I2S_STRM_HDR_4_REG, I2S_CHAN_ORIGIN_FS_N_SAMP_LENGTH  },
> +	/*     Infoframe data Select  */
> +	{ HDMI_CPI_MISC_IF_SELECT_REG, HDMI_INFOFRAME_TX_ENABLE |
> +					HDMI_INFOFRAME_TX_REPEAT |
> +					HDMI_AUDIO_INFOFRAME		 },
> +};
> +
> +static u8 misc_audio_info_frame_data[] = {
> +	MISC_INFOFRAME_TYPE | MISC_INFOFRAME_ALWAYS_SET,
> +	MISC_INFOFRAME_VERSION,
> +	MISC_INFOFRAME_LENGTH,
> +	0,				/* Checksum byte*/
> +	HDMI_SH_PCM | HDMI_SH_TWO_CHANNELS,
> +	HDMI_SH_44KHz | HDMI_SH_16BIT,	/* 44.1 KHz*/
> +	0x0,   /* Default 0*/
> +	HDMI_SH_SPKR_FLFR,
> +	HDMI_SH_0dB_ATUN | 0x1,		/* 0 dB  Attenuation*/
> +	0x0,
> +	0x0,
> +	0x0,
> +	0x0,
> +	0x0
> +};
> +
> +static u8 avi_info_frame_data[] = {
> +	0x00,
> +	0x00,
> +	0xA8,
> +	0x00,
> +	0x04,
> +	0x00,
> +	0x00,
> +	0x00,
> +	0x00,
> +	0x00,
> +	0x00,
> +	0x00,
> +	0x00,
> +	0x00
> +};
> +
> +void get_horz_vert_timing_info(u8 *edid)
> +{
> +	/*HORIZONTAL FRONT PORCH */
> +	omap_dss_hdmi_timings.hfp = edid[current_descriptor_addrs + 8];
> +	/*HORIZONTAL SYNC WIDTH */
> +	omap_dss_hdmi_timings.hsw = edid[current_descriptor_addrs + 9];
> +	/*HORIZONTAL BACK PORCH */
> +	omap_dss_hdmi_timings.hbp = (((edid[current_descriptor_addrs + 4]
> +					  & 0x0F) << 8) |
> +					edid[current_descriptor_addrs + 3]) -
> +		(omap_dss_hdmi_timings.hfp + omap_dss_hdmi_timings.hsw);
> +	/*VERTICAL FRONT PORCH */
> +	omap_dss_hdmi_timings.vfp = ((edid[current_descriptor_addrs + 10] &
> +				       0xF0) >> 4);
> +	/*VERTICAL SYNC WIDTH */
> +	omap_dss_hdmi_timings.vsw = (edid[current_descriptor_addrs + 10] &
> +				      0x0F);
> +	/*VERTICAL BACK PORCH */
> +	omap_dss_hdmi_timings.vbp = (((edid[current_descriptor_addrs + 7] &
> +					0x0F) << 8) |
> +				      edid[current_descriptor_addrs + 6]) -
> +		(omap_dss_hdmi_timings.vfp + omap_dss_hdmi_timings.vsw);
> +
> +	dev_dbg(&sil9022_client->dev, "<%s>\n"
> +				       "hfp			= %d\n"
> +				       "hsw			= %d\n"
> +				       "hbp			= %d\n"
> +				       "vfp			= %d\n"
> +				       "vsw			= %d\n"
> +				       "vbp			= %d\n",
> +		 __func__,
> +		 omap_dss_hdmi_timings.hfp,
> +		 omap_dss_hdmi_timings.hsw,
> +		 omap_dss_hdmi_timings.hbp,
> +		 omap_dss_hdmi_timings.vfp,
> +		 omap_dss_hdmi_timings.vsw,
> +		 omap_dss_hdmi_timings.vbp
> +		 );
> +
> +}
> +
> +void get_edid_timing_data(u8 *edid, u16 *pixel_clk, u16 *horizontal_res,
> +			  u16 *vertical_res)
> +{
> +	u8 offset, effective_addrs;
> +	u8 count;
> +	u8 i;
> +	u8 flag = false;
> +	/*check for 720P timing in block0 */
> +	for (count = 0; count < EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR; count++) {
> +		current_descriptor_addrs > +			EDID_DESCRIPTOR_BLOCK0_ADDRESS +
> +			count * EDID_TIMING_DESCRIPTOR_SIZE;
> +		*horizontal_res > +			(((edid[EDID_DESCRIPTOR_BLOCK0_ADDRESS + 4 +
> +			   count * EDID_TIMING_DESCRIPTOR_SIZE] & 0xF0) << 4) |
> +			 edid[EDID_DESCRIPTOR_BLOCK0_ADDRESS + 2 +
> +			 count * EDID_TIMING_DESCRIPTOR_SIZE]);
> +		*vertical_res > +			(((edid[EDID_DESCRIPTOR_BLOCK0_ADDRESS + 7 +
> +			   count * EDID_TIMING_DESCRIPTOR_SIZE] & 0xF0) << 4) |
> +			 edid[EDID_DESCRIPTOR_BLOCK0_ADDRESS + 5 +
> +			 count * EDID_TIMING_DESCRIPTOR_SIZE]);
> +
> +		dev_dbg(&sil9022_client->dev,
> +			"<%s> ***Block-0-Timing-descriptor[%d]***\n",
> +			__func__, count);
> +		for (i = current_descriptor_addrs;
> +		      i <
> +		      (current_descriptor_addrs+EDID_TIMING_DESCRIPTOR_SIZE);
> +		      i++)
> +			dev_dbg(&sil9022_client->dev,
> +				"%x =>		%x\n", i, edid[i]);
> +
> +			dev_dbg(&sil9022_client->dev,
> +				 "<%s>\n"
> +				 "E-EDID Buffer Index	= %d\n"
> +				 "horizontal_res	= %d\n"
> +				 "vertical_res		= %d\n",
> +				 __func__,
> +				 current_descriptor_addrs,
> +				 *horizontal_res,
> +				 *vertical_res
> +				 );
> +
> +		if (*horizontal_res = HDMI_XRES &&
> +		    *vertical_res = HDMI_YRES) {
> +			dev_info(&sil9022_client->dev,
> +				"<%s>\nFound EDID Data for %d x %dp\n",
> +				 __func__, *horizontal_res, *vertical_res);
> +			flag = true;
> +			break;
> +			}
> +	}
> +
> +	/*check for the Timing in block1 */
> +	if (flag != true) {
> +		offset = edid[EDID_DESCRIPTOR_BLOCK1_ADDRESS + 2];
> +		if (offset != 0) {
> +			effective_addrs = EDID_DESCRIPTOR_BLOCK1_ADDRESS
> +				+ offset;
> +			/*to determine the number of descriptor blocks */
> +			for (count = 0;
> +			      count < EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR;
> +			      count++) {
> +				current_descriptor_addrs = effective_addrs +
> +					count * EDID_TIMING_DESCRIPTOR_SIZE;
> +				*horizontal_res > +					(((edid[effective_addrs + 4 +
> +					   count*EDID_TIMING_DESCRIPTOR_SIZE] &
> +					   0xF0) << 4) |
> +					 edid[effective_addrs + 2 +
> +					 count * EDID_TIMING_DESCRIPTOR_SIZE]);
> +				*vertical_res > +					(((edid[effective_addrs + 7 +
> +					   count*EDID_TIMING_DESCRIPTOR_SIZE] &
> +					   0xF0) << 4) |
> +					 edid[effective_addrs + 5 +
> +					 count * EDID_TIMING_DESCRIPTOR_SIZE]);
> +
> +				dev_dbg(&sil9022_client->dev,
> +					 "<%s> Block1-Timing-descriptor[%d]\n",
> +					 __func__, count);
> +
> +				for (i = current_descriptor_addrs;
> +				      i < (current_descriptor_addrs+
> +					   EDID_TIMING_DESCRIPTOR_SIZE); i++)
> +					dev_dbg(&sil9022_client->dev,
> +						"%x =>		%x\n",
> +						   i, edid[i]);
> +
> +				dev_dbg(&sil9022_client->dev, "<%s>\n"
> +						"current_descriptor	= %d\n"
> +						"horizontal_res		= %d\n"
> +						"vertical_res		= %d\n",
> +					 __func__, current_descriptor_addrs,
> +					 *horizontal_res, *vertical_res);
> +
> +				if (*horizontal_res = HDMI_XRES &&
> +				    *vertical_res = HDMI_YRES) {
> +					dev_info(&sil9022_client->dev,
> +						 "<%s> Found EDID Data for "
> +						 "%d x %dp\n",
> +						 __func__,
> +						 *horizontal_res,
> +						 *vertical_res
> +						 );
> +					flag = true;
> +					break;
> +					}
> +			}
> +		}
> +	}
> +
> +	if (flag = true) {
> +		*pixel_clk = ((edid[current_descriptor_addrs + 1] << 8) |
> +			     edid[current_descriptor_addrs]);
> +
> +		omap_dss_hdmi_timings.x_res = *horizontal_res;
> +		omap_dss_hdmi_timings.y_res = *vertical_res;
> +		omap_dss_hdmi_timings.pixel_clock = *pixel_clk*10;
> +		dev_dbg(&sil9022_client->dev,
> +			 "EDID TIMING DATA supported by zoom2 FOUND\n"
> +			 "EDID DTD block address	= %d\n"
> +			 "pixel_clk			= %d\n"
> +			 "horizontal res		= %d\n"
> +			 "vertical res			= %d\n",
> +			 current_descriptor_addrs,
> +			 omap_dss_hdmi_timings.pixel_clock,
> +			 omap_dss_hdmi_timings.x_res,
> +			 omap_dss_hdmi_timings.y_res
> +			 );
> +
> +		get_horz_vert_timing_info(edid);
> +	} else {
> +
> +		dev_info(&sil9022_client->dev,
> +			 "<%s>\n"
> +			 "EDID TIMING DATA supported by zoom2 NOT FOUND\n"
> +			 "setting default timing values for 720p\n"
> +			 "pixel_clk		= %d\n"
> +			 "horizontal res	= %d\n"
> +			 "vertical res		= %d\n",
> +			 __func__,
> +			 omap_dss_hdmi_timings.pixel_clock,
> +			 omap_dss_hdmi_timings.x_res,
> +			 omap_dss_hdmi_timings.y_res
> +			 );
> +
> +		*pixel_clk = omap_dss_hdmi_timings.pixel_clock;
> +		*horizontal_res = omap_dss_hdmi_timings.x_res;
> +		*vertical_res = omap_dss_hdmi_timings.y_res;
> +	}
> +
> +
> +}
> +
> +
> +static int
> +sil9022_blockwrite_reg(struct i2c_client *client,
> +				  u8 reg, u16 alength, u8 *val, u16 *out_len)
> +{
> +	int err = 0, i;
> +	struct i2c_msg msg[1];
> +	u8 data[2];
> +
> +	if (!client->adapter) {
> +		dev_err(&client->dev, "<%s> ERROR: No HDMI Device\n", __func__);
> +		return -ENODEV;
> +	}
> +
> +	msg->addr = client->addr;
> +	msg->flags = I2C_M_WR;
> +	msg->len = 2;
> +	msg->buf = data;
> +
> +	/* high byte goes out first */
> +	data[0] = reg >> 8;
> +
> +	for (i = 0; i < alength - 1; i++) {
> +		data[1] = val[i];
> +		err = i2c_transfer(client->adapter, msg, 1);
> +		udelay(50);
> +		dev_dbg(&client->dev, "<%s> i2c Block write at 0x%x, "
> +				      "*val=%d flags=%d byte[%d] err=%d\n",
> +			__func__, data[0], data[1], msg->flags, i, err);
> +		if (err < 0)
> +			break;
> +	}
> +	/* set the number of bytes written*/
> +	*out_len = i;
> +
> +	if (err < 0) {
> +		dev_err(&client->dev, "<%s> ERROR:  i2c Block Write at 0x%x, "
> +				      "*val=%d flags=%d bytes written=%d "
> +				      "err=%d\n",
> +			__func__, data[0], data[1], msg->flags, i, err);
> +		return err;
> +	}
> +	return 0;
> +}
> +
> +static int
> +sil9022_blockread_reg(struct i2c_client *client,
> +		      u16 data_length, u16 alength,
> +		      u8 reg, u8 *val, u16 *out_len)
> +{
> +	int err = 0, i;
> +	struct i2c_msg msg[1];
> +	u8 data[2];
> +
> +	if (!client->adapter) {
> +		dev_err(&client->dev, "<%s> ERROR: No HDMI Device\n", __func__);
> +		return -ENODEV;
> +	}
> +
> +	msg->addr = client->addr;
> +	msg->flags = I2C_M_WR;
> +	msg->len = 1;
> +	msg->buf = data;
> +
> +	/* High byte goes out first */
> +	data[0] = reg;
> +	err = i2c_transfer(client->adapter, msg, 1);
> +	dev_dbg(&client->dev, "<%s> i2c Block Read1 at 0x%x, "
> +			       "*val=%d flags=%d err=%d\n",
> +		 __func__, data[0], data[1], msg->flags, err);
> +
> +	for (i = 0; i < alength; i++) {
> +		if (err >= 0) {
> +			mdelay(3);
> +			msg->flags = I2C_M_RD;
> +			msg->len = data_length;
> +			err = i2c_transfer(client->adapter, msg, 1);
> +		} else
> +			break;
> +		if (err >= 0) {
> +			val[i] = 0;
> +			/* High byte comes first */
> +			if (data_length = 1)
> +				val[i] = data[0];
> +			else if (data_length = 2)
> +				val[i] = data[1] + (data[0] << 8);
> +			dev_dbg(&client->dev, "<%s> i2c Block Read2 at 0x%x, "
> +					       "*val=%d flags=%d byte=%d "
> +					       "err=%d\n",
> +				 __func__, reg, val[i], msg->flags, i, err);
> +		} else
> +			break;
> +	}
> +	*out_len = i;
> +	dev_dbg(&client->dev, "<%s> i2c Block Read at 0x%x, bytes read = %d\n",
> +		__func__, client->addr, *out_len);
> +
> +	if (err < 0) {
> +		dev_err(&client->dev, "<%s> ERROR:  i2c Read at 0x%x, "
> +				      "*val=%d flags=%d bytes read=%d err=%d\n",
> +			__func__, reg, *val, msg->flags, i, err);
> +		return err;
> +	}
> +	return 0;
> +}
> +
> +
> +/* Write a value to a register in sil9022 device.
> + * @client: i2c driver client structure.
> + * @reg: Address of the register to read value from.
> + * @val: Value to be written to a specific register.
> + * Returns zero if successful, or non-zero otherwise.
> + */
> +static int
> +sil9022_write_reg(struct i2c_client *client, u8 reg, u8 val)
> +{
> +	int err = 0;
> +	struct i2c_msg msg[1];
> +	u8 data[2];
> +	int retries = 0;
> +
> +	if (!client->adapter) {
> +		dev_err(&client->dev, "<%s> ERROR: No HDMI Device\n", __func__);
> +		return -ENODEV;
> +	}
> +
> +retry:
> +	msg->addr = client->addr;
> +	msg->flags = I2C_M_WR;
> +	msg->len = 2;
> +	msg->buf = data;
> +
> +	data[0] = reg;
> +	data[1] = val;
> +
> +	err = i2c_transfer(client->adapter, msg, 1);
> +	dev_dbg(&client->dev, "<%s> i2c write at=%x "
> +			       "val=%x flags=%d err=%d\n",
> +		__func__, data[0], data[1], msg->flags, err);
> +	udelay(50);
> +
> +	if (err >= 0)
> +		return 0;
> +
> +	dev_err(&client->dev, "<%s> ERROR: i2c write at=%x "
> +			       "val=%x flags=%d err=%d\n",
> +		__func__, data[0], data[1], msg->flags, err);
> +	if (retries <= 5) {
> +		dev_info(&client->dev, "Retrying I2C... %d\n", retries);
> +		retries++;
> +		set_current_state(TASK_UNINTERRUPTIBLE);
> +		schedule_timeout(msecs_to_jiffies(20));
> +		goto retry;
> +	}
> +	return err;
> +}
> +
> +/*
> + * Read a value from a register in sil9022 device.
> + * The value is returned in 'val'.
> + * Returns zero if successful, or non-zero otherwise.
> + */
> +static int
> +sil9022_read_reg(struct i2c_client *client, u16 data_length, u8 reg, u8 *val)
> +{
> +	int err = 0;
> +	struct i2c_msg msg[1];
> +	u8 data[2];
> +
> +	if (!client->adapter) {
> +		dev_err(&client->dev, "<%s> ERROR: No HDMI Device\n", __func__);
> +		return -ENODEV;
> +	}
> +
> +	msg->addr = client->addr;
> +	msg->flags = I2C_M_WR;
> +	msg->len = 1;
> +	msg->buf = data;
> +
> +	data[0] = reg;
> +	err = i2c_transfer(client->adapter, msg, 1);
> +	dev_dbg(&client->dev, "<%s> i2c Read1 reg=%x val=%d "
> +			       "flags=%d err=%d\n",
> +		__func__, reg, data[1], msg->flags, err);
> +
> +	if (err >= 0) {
> +		mdelay(3);
> +		msg->flags = I2C_M_RD;
> +		msg->len = data_length;
> +		err = i2c_transfer(client->adapter, msg, 1);
> +	}
> +
> +	if (err >= 0) {
> +		*val = 0;
> +		if (data_length = 1)
> +			*val = data[0];
> +		else if (data_length = 2)
> +			*val = data[1] + (data[0] << 8);
> +		dev_dbg(&client->dev, "<%s> i2c Read2 at 0x%x, *val=%d "
> +				       "flags=%d err=%d\n",
> +			 __func__, reg, *val, msg->flags, err);
> +		return 0;
> +	}
> +
> +	dev_err(&client->dev, "<%s> ERROR: i2c Read at 0x%x, "
> +			      "*val=%d flags=%d err=%d\n",
> +		__func__, reg, *val, msg->flags, err);
> +	return err;
> +}
> +
> +static int
> +sil9022_read_edid(struct i2c_client *client, u16 len,
> +	       char *p_buffer, u16 *out_len)
> +{
> +	int err =  0;
> +	u8 val = 0;
> +	int retries = 0;
> +	int i = 0;
> +	int k = 0;
> +
> +	len = (len < HDMI_EDID_MAX_LENGTH) ? len : HDMI_EDID_MAX_LENGTH;
> +
> +	/* Request DDC bus access to read EDID info from HDTV */
> +	dev_info(&client->dev, "<%s> Reading HDMI EDID\n", __func__);
> +
> +	/* Bring transmitter to low-Power state */
> +	val = TPI_AVI_POWER_STATE_D2;
> +	err = sil9022_write_reg(client, HDMI_TPI_DEVICE_POWER_STATE_DATA, val);
> +	if (err < 0) {
> +		dev_err(&client->dev,
> +			"<%s> ERROR: Failed during bring power state - low.\n",
> +			 __func__);
> +		return err;
> +	}
> +
> +	/* Disable TMDS clock */
> +	val = 0x11;
> +	err = sil9022_write_reg(client, HDMI_SYS_CTRL_DATA_REG, val);
> +	if (err < 0) {
> +		dev_err(&client->dev,
> +			"<%s> ERROR: Failed during bring power state - low.\n",
> +			 __func__);
> +		return err;
> +	}
> +
> +	val = 0;
> +	/* Read TPI system control register*/
> +	err = sil9022_read_reg(client, 1, HDMI_SYS_CTRL_DATA_REG, &val);
> +	if (err < 0) {
> +		dev_err(&client->dev,
> +			"<%s> ERROR: Reading DDC BUS REQUEST\n", __func__);
> +		return err;
> +	}
> +
> +	/* The host writes 0x1A[2]=1 to request the
> +	 * DDC(Display Data Channel) bus
> +	 */
> +	val |= TPI_SYS_CTRL_DDC_BUS_REQUEST;
> +	err = sil9022_write_reg(client, HDMI_SYS_CTRL_DATA_REG, val);
> +	if (err < 0) {
> +		dev_err(&client->dev,
> +			"<%s> ERROR: Writing DDC BUS REQUEST\n", __func__);
> +		return err;
> +	}
> +
> +	 /*  Poll for bus DDC Bus control to be granted */
> +	dev_info(&client->dev, "<%s> Poll for DDC bus access\n", __func__);
> +	val = 0;
> +	do {
> +		err = sil9022_read_reg(client, 1, HDMI_SYS_CTRL_DATA_REG, &val);
> +		if (retries++ > 100)
> +			return err;
> +
> +	} while ((val & TPI_SYS_CTRL_DDC_BUS_GRANTED) = 0);
> +
> +	/*  Close the switch to the DDC */
> +	val |= TPI_SYS_CTRL_DDC_BUS_REQUEST | TPI_SYS_CTRL_DDC_BUS_GRANTED;
> +	err = sil9022_write_reg(client, HDMI_SYS_CTRL_DATA_REG, val);
> +	if (err < 0) {
> +		dev_err(&client->dev,
> +			"<%s> ERROR: Close switch to DDC BUS REQUEST\n",
> +			__func__);
> +		return err;
> +	}
> +
> +	memset(p_buffer, 0, len);
> +	/* change I2C SetSlaveAddress to HDMI_I2C_MONITOR_ADDRESS */
> +	/*  Read the EDID structure from the monitor I2C address  */
> +	client->addr = HDMI_I2C_MONITOR_ADDRESS;
> +	err = sil9022_blockread_reg(client, 1, len,
> +				    0x00, p_buffer, out_len);
> +	if (err < 0 || *out_len <= 0) {
> +		dev_err(&client->dev,
> +			"<%s> ERROR: Reading EDID from "
> +			"HDMI_I2C_MONITOR_ADDRESS\n", __func__);
> +		return err;
> +	}
> +
> +	for (i = 0; i < *out_len; i++) {
> +		if ((i / 18) < 3) {
> +			dev_dbg(&client->dev, "byte->%02x	%x\n",
> +				i, p_buffer[i]);
> +			continue;
> +		}
> +		if ((i/18 >= 3 && i/18 <= 6) && (i%18 = 0))
> +			dev_dbg(&client->dev, "\n DTD Block %d\n", k++);
> +
> +		if ((i/18 = 7) && (i%18 = 0))
> +			dev_dbg(&client->dev, "\n");
> +
> +		dev_dbg(&client->dev, "byte->%02x	%x\n", i, p_buffer[i]);
> +	}
> +
> +	/* Release DDC bus access */
> +	client->addr = SI9022_I2CSLAVEADDRESS;
> +	val &= ~(TPI_SYS_CTRL_DDC_BUS_REQUEST | TPI_SYS_CTRL_DDC_BUS_GRANTED);
> +	err = sil9022_write_reg(client, HDMI_SYS_CTRL_DATA_REG, val);
> +
> +	if (err < 0) {
> +		dev_err(&client->dev,
> +			"<%s> ERROR: Releasing DDC  Bus Access\n",
> +			__func__);
> +		return err;
> +		}
> +
> +	/*  Success */
> +	return 0;
> +}
> +
> +static int
> +sil9022_enable_audio(struct i2c_client *client)
> +{
> +	int err = 0;
> +	u8  val = 0;
> +	u8  crc = 0;
> +	u32 count = 0;
> +	int index = 0;
> +
> +	for (index = 0;
> +	      index < sizeof(hdmi_tpi_audio_config_data) /
> +	      sizeof(struct hdmi_reg_data);
> +	      index++) {
> +		err = sil9022_write_reg(
> +			client,
> +			hdmi_tpi_audio_config_data[index].reg_offset,
> +			hdmi_tpi_audio_config_data[index].value);
> +		if (err != 0) {
> +			dev_err(&client->dev,
> +				"<%s> ERROR: Writing "
> +				"tpi_audio_config_data[%d]={ %d, %d }\n",
> +				__func__, index,
> +				hdmi_tpi_audio_config_data[index].reg_offset,
> +				hdmi_tpi_audio_config_data[index].value);
> +			return err;
> +			}
> +		}
> +
> +	/* Fill the checksum byte for Infoframe data*/
> +	count = 0;
> +	while (count < MISC_INFOFRAME_SIZE_MEMORY) {
> +		crc += misc_audio_info_frame_data[count];
> +		count++;
> +	}
> +	crc = 0x100 - crc;
> +
> +	/* Fill CRC Byte*/
> +	misc_audio_info_frame_data[0x3] = crc;
> +
> +	for (count = 0; count < MISC_INFOFRAME_SIZE_MEMORY; count++) {
> +		err = sil9022_write_reg(client,
> +					(HDMI_CPI_MISC_IF_OFFSET + count),
> +					misc_audio_info_frame_data[count]);
> +		if (err < 0) {
> +			dev_err(&client->dev,
> +				"<%s> ERROR: writing audio info frame"
> +				" CRC data: %d\n", __func__, count);
> +			return err;
> +		}
> +	}
> +
> +	/* Decode Level 0 Packets */
> +	val = 0x2;
> +	sil9022_write_reg(client, 0xBC, val);
> +	if (err < 0) {
> +		dev_err(&client->dev,
> +			"<%s> ERROR: writing level 0 packets to 0xBC\n",
> +			__func__);
> +		return err;
> +	}
> +
> +	val = 0x24;
> +	err = sil9022_write_reg(client, 0xBD, val);
> +	if (err < 0) {
> +		dev_err(&client->dev,
> +			"<%s> ERROR: writing level 0 packets to 0xBD\n",
> +			__func__);
> +		return err;
> +	}
> +
> +	val = 0x2;
> +	err = sil9022_write_reg(client, 0xBE, val);
> +	if (err < 0) {
> +		dev_err(&client->dev,
> +			"<%s> ERROR: writing level 0 packets to 0xBE\n",
> +			__func__);
> +		return err;
> +	}
> +
> +	/* Disable Mute */
> +	val = TPI_AUDIO_INTERFACE_I2S |
> +		  TPI_AUDIO_MUTE_DISABLE |
> +		  TPI_AUDIO_CODING_PCM;
> +	err = sil9022_write_reg(client, HDMI_TPI_AUDIO_CONFIG_BYTE2_REG, val);
> +	if (err < 0) {
> +		dev_err(&client->dev,
> +			"<%s> ERROR: Disabling mute\n",
> +			__func__);
> +		return err;
> +	}
> +
> +	dev_info(&client->dev, "<%s> hdmi audio enabled\n",
> +		__func__);
> +	return 0;
> +
> +}
> +
> +static int
> +sil9022_disable_audio(struct i2c_client *client)
> +{
> +	u8 val = 0;
> +	int err = 0;
> +	/* Disable Audio */
> +	val = TPI_AUDIO_INTERFACE_DISABLE;
> +	err = sil9022_write_reg(client, HDMI_TPI_AUDIO_CONFIG_BYTE2_REG, val);
> +	if (err < 0)
> +		dev_err(&client->dev,
> +			"<%s> ERROR: Disisable audio interface", __func__);
> +
> +	dev_info(&client->dev, "<%s> hdmi audio disabled\n", __func__);
> +	return err;
> +}
> +
> +static int
> +sil9022_enable(struct omap_dss_device *dssdev)
> +{
> +	int		err;
> +	u8		val, vals[14];
> +	int		i;
> +	u16		out_len = 0;
> +	u8		edid[HDMI_EDID_MAX_LENGTH];
> +	u16		horizontal_res;
> +	u16		vertical_res;
> +	u16		pixel_clk;
> +
> +	memset(edid, 0, HDMI_EDID_MAX_LENGTH);
> +	memset(vals, 0, 14);
> +
> +	err = sil9022_read_edid(sil9022_client, HDMI_EDID_MAX_LENGTH,
> +			     edid, &out_len);
> +	if (err < 0 || out_len = 0) {
> +		dev_err(&sil9022_client->dev,
> +			"<%s> Unable to read EDID for monitor\n", __func__);
> +		return err;
> +	}
> +
> +	get_edid_timing_data(edid,
> +			     &pixel_clk,
> +			     &horizontal_res,
> +			     &vertical_res
> +			     );
> +
> +	/*  Fill the TPI Video Mode Data structure */
> +	vals[0] = (pixel_clk & 0xFF);                  /* Pixel clock */
> +	vals[1] = ((pixel_clk & 0xFF00) >> 8);
> +	vals[2] = VERTICAL_FREQ;                    /* Vertical freq */
> +	vals[3] = 0x00;
> +	vals[4] = (horizontal_res & 0xFF);         /* Horizontal pixels*/
> +	vals[5] = ((horizontal_res & 0xFF00) >> 8);
> +	vals[6] = (vertical_res & 0xFF);           /* Vertical pixels */
> +	vals[7] = ((vertical_res & 0xFF00) >> 8);
> +
> +	dev_info(&sil9022_client->dev, "<%s>\nHDMI Monitor E-EDID Timing Data\n"
> +				       "horizontal_res	= %d\n"
> +				       "vertical_res	= %d\n"
> +				       "pixel_clk	= %d\n"
> +				       "hfp		= %d\n"
> +				       "hsw		= %d\n"
> +				       "hbp		= %d\n"
> +				       "vfp		= %d\n"
> +				       "vsw		= %d\n"
> +				       "vbp		= %d\n",
> +		 __func__,
> +		 omap_dss_hdmi_timings.x_res,
> +		 omap_dss_hdmi_timings.y_res,
> +		 omap_dss_hdmi_timings.pixel_clock,
> +		 omap_dss_hdmi_timings.hfp,
> +		 omap_dss_hdmi_timings.hsw,
> +		 omap_dss_hdmi_timings.hbp,
> +		 omap_dss_hdmi_timings.vfp,
> +		 omap_dss_hdmi_timings.vsw,
> +		 omap_dss_hdmi_timings.vbp
> +		 );
> +
> +	dssdev->panel.timings = omap_dss_hdmi_timings;
> +	/*  Write out the TPI Video Mode Data */
> +	out_len = 0;
> +	err = sil9022_blockwrite_reg(sil9022_client,
> +				     HDMI_TPI_VIDEO_DATA_BASE_REG,
> +				     8, vals, &out_len);
> +	if (err < 0) {
> +		dev_err(&sil9022_client->dev,
> +			"<%s> ERROR: writing TPI video mode data\n", __func__);
> +		return err;
> +	}
> +
> +	/* Write out the TPI Pixel Repetition Data (24 bit wide bus,
> +	falling edge, no pixel replication) */
> +	val = TPI_AVI_PIXEL_REP_BUS_24BIT |
> +		TPI_AVI_PIXEL_REP_FALLING_EDGE |
> +		TPI_AVI_PIXEL_REP_NONE;
> +	err = sil9022_write_reg(sil9022_client,
> +				HDMI_TPI_PIXEL_REPETITION_REG,
> +				val);
> +	if (err < 0) {
> +		dev_err(&sil9022_client->dev,
> +			"<%s> ERROR: writing TPI pixel repetition data\n",
> +			__func__);
> +		return err;
> +	}
> +
> +	 /*  Write out the TPI AVI Input Format */
> +	val = TPI_AVI_INPUT_BITMODE_8BIT |
> +		TPI_AVI_INPUT_RANGE_AUTO |
> +		TPI_AVI_INPUT_COLORSPACE_RGB;
> +	err = sil9022_write_reg(sil9022_client,
> +				HDMI_TPI_AVI_IN_FORMAT_REG,
> +				val);
> +	if (err < 0) {
> +		dev_err(&sil9022_client->dev,
> +			"<%s> ERROR: writing TPI AVI Input format\n", __func__);
> +		return err;
> +	}
> +
> +	/*  Write out the TPI AVI Output Format */
> +	val = TPI_AVI_OUTPUT_CONV_BT709 |
> +		TPI_AVI_OUTPUT_RANGE_AUTO |
> +		TPI_AVI_OUTPUT_COLORSPACE_RGBHDMI;
> +	err = sil9022_write_reg(sil9022_client,
> +				HDMI_TPI_AVI_OUT_FORMAT_REG, val);
> +	if (err < 0) {
> +		dev_err(&sil9022_client->dev,
> +			"<%s> ERROR: writing TPI AVI output format\n",
> +			__func__);
> +		return err;
> +	}
> +
> +	/* Write out the TPI System Control Data to power down */
> +	val = TPI_SYS_CTRL_POWER_DOWN;
> +	err = sil9022_write_reg(sil9022_client, HDMI_SYS_CTRL_DATA_REG, val);
> +	if (err < 0) {
> +		dev_err(&sil9022_client->dev,
> +			"<%s> ERROR: writing TPI power down control data\n",
> +			__func__);
> +		return err;
> +	}
> +
> +	/* Write out the TPI AVI InfoFrame Data (all defaults) */
> +	/* Compute CRC*/
> +	val = 0x82 + 0x02 + 13;
> +
> +	for (i = 0; i < sizeof(avi_info_frame_data); i++)
> +		val += avi_info_frame_data[i];
> +
> +	avi_info_frame_data[0] = 0x100 - val;
> +
> +	out_len = 0;
> +	err = sil9022_blockwrite_reg(sil9022_client,
> +				     HDMI_TPI_AVI_DBYTE_BASE_REG,
> +				     sizeof(avi_info_frame_data),
> +				     avi_info_frame_data, &out_len);
> +	if (err < 0) {
> +		dev_err(&sil9022_client->dev,
> +			"<%s> ERROR: writing TPI AVI infoframe data\n",
> +			__func__);
> +		return err;
> +	}
> +
> +	/*  Audio Configuration  */
> +	err = sil9022_enable_audio(sil9022_client);
> +	if (err < 0) {
> +		dev_err(&sil9022_client->dev,
> +			"<%s> ERROR: Unable set audio configuration\n",
> +			__func__);
> +		return err;
> +	}
> +
> +	/*  Write out the TPI Device Power State (D0) */
> +	val = TPI_AVI_POWER_STATE_D0;
> +	err = sil9022_write_reg(sil9022_client,
> +				HDMI_TPI_POWER_STATE_CTRL_REG, val);
> +	if (err < 0) {
> +		dev_err(&sil9022_client->dev,
> +			"<%s> ERROR: Setting device power state to D0\n",
> +			__func__);
> +		return err;
> +	}
> +
> +	/* Write out the TPI System Control Data to power up and
> +	 * select output mode
> +	 */
> +	val = TPI_SYS_CTRL_POWER_ACTIVE | TPI_SYS_CTRL_OUTPUT_MODE_HDMI;
> +	err = sil9022_write_reg(sil9022_client, HDMI_SYS_CTRL_DATA_REG, val);
> +	if (err < 0) {
> +		dev_err(&sil9022_client->dev,
> +			"<%s> ERROR: Writing system control data\n", __func__);
> +		return err;
> +	}
> +
> +	/*  Read back TPI System Control Data to latch settings */
> +	msleep(20);
> +	err = sil9022_read_reg(sil9022_client, 1, HDMI_SYS_CTRL_DATA_REG, &val);
> +	if (err < 0) {
> +		dev_err(&sil9022_client->dev,
> +			"<%s> ERROR: Writing system control data\n",
> +			__func__);
> +		return err;
> +	}
> +
> +	/* HDCP Enable - Disable */
> +	val = 0;
> +	err = sil9022_write_reg(sil9022_client,
> +				HDMI_TPI_HDCP_CONTROLDATA_REG, val);
> +	if (err < 0) {
> +		dev_err(&sil9022_client->dev,
> +			"<%s> ERROR: Enable (1) / Disable (0) => HDCP: %d\n",
> +			__func__, val);
> +		return err;
> +	}
> +
> +	dev_info(&sil9022_client->dev, "<%s> hdmi enabled\n", __func__);
> +	return 0;
> +
> +}
> +
> +static int
> +sil9022_disable(void)
> +{
> +	u8 val = 0;
> +	int err = 0;
> +
> +	err = sil9022_disable_audio(sil9022_client);
> +	if (err < 0) {
> +		dev_err(&sil9022_client->dev,
> +			"<%s> ERROR: failed to disable audio\n", __func__);
> +		return err;
> +	}
> +
> +	/*  Write out the TPI System Control Data to power down  */
> +	val = TPI_SYS_CTRL_POWER_DOWN;
> +	err = sil9022_write_reg(sil9022_client, HDMI_SYS_CTRL_DATA_REG, val);
> +	if (err < 0) {
> +		dev_err(&sil9022_client->dev,
> +			"<%s> ERROR: writing control data - power down\n",
> +			__func__);
> +		return err;
> +	}
> +
> +	/*  Write out the TPI Device Power State (D2) */
> +	val = TPI_AVI_POWER_STATE_D2;
> +	err = sil9022_write_reg(sil9022_client,
> +			  HDMI_TPI_DEVICE_POWER_STATE_DATA, val);
> +	if (err < 0) {
> +		dev_err(&sil9022_client->dev,
> +			"<%s> ERROR: Setting device power state to D2\n",
> +			__func__);
> +		return err;
> +	}
> +
> +	/*  Read back TPI System Control Data to latch settings */
> +	mdelay(10);
> +	err = sil9022_read_reg(sil9022_client, 1, HDMI_SYS_CTRL_DATA_REG, &val);
> +	if (err < 0) {
> +		dev_err(&sil9022_client->dev,
> +			"<%s> ERROR:  Reading System control data "
> +			"- latch settings\n", __func__);
> +		return err;
> +	}
> +
> +	dev_info(&sil9022_client->dev, "<%s> hdmi disabled\n", __func__);
> +	return 0;
> +
> +}
> +
> +static int sil9022_set_reg_read_ctrl(struct i2c_client *client)
> +{
> +	int err = 0;
> +	u8 ver;
> +
> +	/* probe for sil9022 chip version*/
> +	err = sil9022_write_reg(client, SI9022_REG_TPI_RQB, 0x00);
> +	if (err < 0) {
> +		dev_err(&client->dev,
> +			"<%s> ERROR: Writing HDMI configuration to "
> +			"reg - SI9022_REG_TPI_RQB\n", __func__);
> +		err = -ENODEV;
> +		goto ERROR1;
> +	}
> +
> +	err = sil9022_read_reg(client, 1, SI9022_REG_CHIPID0, &ver);
> +	if (err < 0) {
> +		dev_err(&client->dev,
> +			"<%s> ERROR: Reading HDMI version Id\n", __func__);
> +		err = -ENODEV;
> +		goto ERROR1;
> +	} else if (ver != SI9022_CHIPID_902x) {
> +		dev_err(&client->dev,
> +			"<%s> Not a valid verId: 0x%x\n", __func__, ver);
> +		err = -ENODEV;
> +		goto ERROR1;
> +	} else
> +		dev_info(&client->dev,
> +			 "<%s> sil9022 HDMI Chip version = %x\n",
> +			 __func__, ver);
> +
> +	return 0;
> +ERROR1:
> +	return err;
> +}
> +
> +static inline struct sil9022_platform_data
> +*get_panel_data(const struct omap_dss_device *dssdev)
> +{
> +	return (struct sil9022_platform_data *) dssdev->data;
> +}
> +
> +
> +static int sil9022_panel_probe(struct omap_dss_device *dssdev)
> +{
> +	struct sil9022_platform_data *sidata = get_panel_data(dssdev);
> +	int r;
> +	if (!sidata)
> +		return -EINVAL;
> +
> +	dssdev->panel.timings = omap_dss_hdmi_timings;
> +
> +	if (gpio_is_valid(sidata->res_gpio)) {
> +		r = devm_gpio_request_one(&dssdev->dev, sidata->res_gpio,
> +				GPIOF_OUT_INIT_HIGH, "HDMI");
> +		if (r)
> +			return r;
> +	}
> +
> +	return 0;
> +}
> +
> +static void sil9022_panel_remove(struct omap_dss_device *dssdev)
> +{
> +	omap_dss_unregister_driver(dssdev->driver);
> +}
> +
> +
> +static int sil9022_panel_power_on(struct omap_dss_device *dssdev)
> +{
> +	int r = 0;
> +	struct sil9022_platform_data *sidata = get_panel_data(dssdev);
> +
> +	if (dssdev->state = OMAP_DSS_DISPLAY_ACTIVE)
> +		return 0;
> +
> +	if (gpio_is_valid(sidata->res_gpio))
> +		gpio_set_value_cansleep(sidata->res_gpio, 1);
> +
> +	omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
> +	omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
> +	r = omapdss_dpi_display_enable(dssdev);
> +	return r;
> +
> +}
> +
> +static void sil9022_panel_power_off(struct omap_dss_device *dssdev)
> +{
> +	struct sil9022_platform_data *sidata = get_panel_data(dssdev);
> +
> +	if (gpio_is_valid(sidata->res_gpio))
> +		gpio_set_value_cansleep(sidata->res_gpio, 0);
> +	return;
> +
> +}
> +
> +static int sil9022_panel_enable(struct omap_dss_device *dssdev)
> +{
> +	int r = 0;
> +
> +	r = sil9022_panel_power_on(dssdev);
> +	if (r)
> +			goto ERROR0;
> +	r = sil9022_set_reg_read_ctrl(sil9022_client);
> +	if (r)
> +		goto ERROR0;
> +
> +	r = sil9022_enable(dssdev);
> +	if (r)
> +		goto ERROR0;
> +	/* wait couple of vsyncs until enabling the LCD */
> +	msleep(50);
> +	return 0;
> +
> +ERROR0:
> +	return r;
> +}
> +
> +static void sil9022_panel_disable(struct omap_dss_device *dssdev)
> +{
> +	sil9022_disable();
> +	/* wait couple of vsyncs until enabling the hdmi */
> +	msleep(50);
> +	sil9022_panel_power_off(dssdev);
> +	return;
> +}
> +
> +static struct omap_dss_driver hdmi_driver = {
> +	.probe		= sil9022_panel_probe,
> +	.remove		= sil9022_panel_remove,
> +
> +	.enable		= sil9022_panel_enable,
> +	.disable		= sil9022_panel_disable,
> +
> +	.driver         = {
> +		.name   = "sil9022_panel",
> +		.owner  = THIS_MODULE,
> +	},
> +};
> +
> +static int
> +sil9022_probe(struct i2c_client *client, const struct i2c_device_id *id)
> +{
> +	int err = 0;
> +
> +	sil9022_client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
> +	if (!sil9022_client) {
> +		err = -ENOMEM;
> +		goto ERROR0;
> +	}
> +	memset(sil9022_client, 0, sizeof(struct i2c_client));
> +
> +	strncpy(sil9022_client->name, client->name, I2C_NAME_SIZE);
> +	sil9022_client->addr = client->addr;
> +	sil9022_client->adapter = client->adapter;
> +
> +	err = sil9022_set_reg_read_ctrl(client);
> +	if (err)
> +		goto ERROR1;
> +
> +	omap_dss_register_driver(&hdmi_driver);
> +	return 0;
> +
> +ERROR1:
> +	kfree(sil9022_client);
> +ERROR0:
> +	return err;
> +}
> +
> +
> +static int
> +sil9022_remove(struct i2c_client *client)
> +
> +{
> +	int err = 0;
> +
> +	if (!client->adapter) {
> +		dev_err(&sil9022_client->dev, "<%s> No HDMI Device\n",
> +			__func__);
> +		return -ENODEV;
> +	}
> +	kfree(sil9022_client);
> +
> +	return err;
> +}
> +
> +static const struct i2c_device_id sil9022_id[] = {
> +	{ SIL9022_DRV_NAME, 0 },
> +	{ },
> +};
> +
> +MODULE_DEVICE_TABLE(i2c, sil9022_id);
> +
> +static struct i2c_driver sil9022_driver = {
> +	.driver = {
> +		.name  = SIL9022_DRV_NAME,
> +		.owner = THIS_MODULE,
> +		},
> +	.probe		= sil9022_probe,
> +	.remove		= sil9022_remove,
> +	.id_table	= sil9022_id,
> +};
> +
> +static int __init
> +sil9022_init(void)
> +{
> +	int err = 0;
> +	err = i2c_add_driver(&sil9022_driver);
> +	if (err < 0) {
> +		printk(KERN_ERR "<%s> Driver registration failed\n", __func__);
> +		err = -ENODEV;
> +		goto ERROR0;
> +	}
> +
> +	if (sil9022_client = NULL) {
> +		printk(KERN_ERR "<%s> sil9022_client not allocated\n"
> +				"<%s> No HDMI Device\n", __func__, __func__);
> +		err = -ENODEV;
> +		goto ERROR0;
> +	}
> +	return 0;
> +
> +ERROR0:
> +	return err;
> +}
> +
> +static void __exit
> +sil9022_exit(void)
> +{
> +	i2c_del_driver(&sil9022_driver);
> +}
> +
> +late_initcall(sil9022_init);
> +module_exit(sil9022_exit);
> +
> +MODULE_AUTHOR("Texas Instruments");
> +MODULE_DESCRIPTION("SIL9022 HDMI Driver");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/video/omap2/displays/panel-sil9022.h b/drivers/video/omap2/displays/panel-sil9022.h
> new file mode 100644
> index 0000000..7c920c0
> --- /dev/null
> +++ b/drivers/video/omap2/displays/panel-sil9022.h
> @@ -0,0 +1,527 @@
> +/*
> + * drivers/video/omap2/displays/panel-sil9022.c
> + *
> + * Copyright (C) 2009 Texas Instruments
> + *
> + * 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.
> + *
> + * sil9022 hdmi driver
> + */
> +#ifndef _SI9022_H_
> +#define _SI9022_H_
> +
> +#define SIL9022_DRV_NAME		"sil9022"
> +
> +#define CLKOUT2_EN		(0x1 << 7)
> +#define CLKOUT2_DIV		(0x4 << 3)
> +#define CLKOUT2SOURCE		(0x2 << 0)
> +#define CM_CLKOUT_CTRL		0x48004D70
> +
> +#define HDMI_XRES			1280
> +#define HDMI_YRES			720
> +#define HDMI_PIXCLOCK_MAX		74250
> +#define VERTICAL_FREQ			0x3C
> +
> +#define I2C_M_WR			0
> +
> +#define SI9022_USERST_PIN		1
> +
> +#define SI9022_REG_PIX_CLK_LSB		0x00
> +#define SI9022_REG_PIX_CLK_MSB		0x01
> +
> +#define SI9022_REG_PIX_REPETITION	0x08
> +#define SI9022_REG_INPUT_FORMAT		0x09
> +#define SI9022_REG_OUTPUT_FORMAT	0x0A
> +#define SI9022_REG_SYNC_GEN_CTRL	0x60
> +
> +#define SI9022_REG_DE_CTRL		0x63
> +#define DE_DLY_MSB_BITPOS		0
> +#define HSYNCPOL_INVERT_BITPOS		4
> +#define VSYNCPOL_INVERT_BITPOS		5
> +#define DE_GENERATOR_EN_BITPOS		6
> +
> +#define SI9022_REG_PWR_STATE		0x1E
> +
> +#define SI9022_REG_TPI_RQB		0xC7
> +
> +#define SI9022_REG_INT_PAGE		0xBC
> +#define SI9022_REG_OFFSET		0xBD
> +#define	SI9022_REG_VALUE		0xBE
> +
> +#define SI9022_PLLMULT_BITPOS		0x05
> +
> +#define SI9022_REG_TPI_SYSCTRL		0x1A
> +#define I2DDCREQ_BITPOS			2
> +#define TMDS_ENABLE_BITPOS		4
> +#define HDMI_ENABLE_BITPOS		0
> +
> +#define SI9022_REG_CHIPID0		0x1B
> +#define SI9022_REG_CHIPID1		0x1C
> +#define SI9022_REG_CHIPID2		0x1D
> +#define SI9022_REG_HDCPVER		0x30
> +
> +#define SI9022_REG_INTSTATUS		0x3D
> +#define HOTPLUG_PENDING_BITPOS		0
> +#define RCV_SENSE_PENDING_BITPOS	1
> +#define HOTPLUG_SENSE_BITPOS		2
> +#define RX_SENSE_BITPOS			3
> +#define AUDIO_ERR_PENDING_BITPOS	4
> +
> +
> +#define SI9022_I2CSLAVEADDRESS		0x39
> +
> +#define SI9022_CHIPID_902x		0xB0
> +
> +#define SI9022_MAXRETRY			100
> +
> +#define SI9022_EDID_DETAILED_TIMING_OFFSET	0x36 /*EDID Detailed Timing */
> +						/*Info 0 begin offset*/
> +#define SI9022_EDID_PIX_CLK_OFFSET		0
> +#define SI9022_EDID_H_ACTIVE_OFFSET		2
> +#define SI9022_EDID_H_BLANKING_OFFSET		3
> +#define SI9022_EDID_V_ACTIVE_OFFSET		5
> +#define SI9022_EDID_V_BLANKING_OFFSET		6
> +#define SI9022_EDID_H_SYNC_OFFSET		8
> +#define SI9022_EDID_H_SYNC_PW_OFFSET		9
> +#define SI9022_EDID_V_SYNC_OFFSET		10
> +#define SI9022_EDID_V_SYNC_PW_OFFSET		10
> +#define SI9022_EDID_H_IMAGE_SIZE_OFFSET		12
> +#define SI9022_EDID_V_IMAGE_SIZE_OFFSET		13
> +#define SI9022_EDID_H_BORDER_OFFSET		15
> +#define SI9022_EDID_V_BORDER_OFFSET		16
> +#define SI9022_EDID_FLAGS_OFFSET		17
> +
> +#define SI9022_PLUG_DETECTED			0xF0
> +#define SI9022_UNPLUG_DETECTED			0xF1
> +
> +
> +/* ---------------------------------------------------------------------  */
> +#define EDID_TIMING_DESCRIPTOR_SIZE		0x12
> +#define EDID_DESCRIPTOR_BLOCK0_ADDRESS		0x36
> +#define EDID_DESCRIPTOR_BLOCK1_ADDRESS		0x80
> +#define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR	4
> +#define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR	4
> +
> +/* HDMI Connected States  */
> +#define HDMI_STATE_NOMONITOR	0	/* NOT CONNECTED */
> +#define HDMI_STATE_CONNECTED	1	/* CONNECTED */
> +#define HDMI_STATE_ON		2	/* CONNECTED AND POWERED ON */
> +
> +
> +/* HDMI EDID Length  */
> +#define HDMI_EDID_MAX_LENGTH	256
> +
> +/* HDMI EDID DTDs  */
> +#define HDMI_EDID_MAX_DTDS	4
> +
> +/* HDMI EDID DTD Tags  */
> +#define HDMI_EDID_DTD_TAG_MONITOR_NAME		0xFC
> +#define HDMI_EDID_DTD_TAG_MONITOR_SERIALNUM	0xFF
> +#define HDMI_EDID_DTD_TAG_MONITOR_LIMITS	0xFD
> +
> +
> +/* HDMI EDID Extension Data Block Tags  */
> +#define HDMI_EDID_EX_DATABLOCK_TAG_MASK		0xE0
> +#define HDMI_EDID_EX_DATABLOCK_LEN_MASK		0x1F
> +
> +#define HDMI_EDID_EX_DATABLOCK_AUDIO		0x20
> +#define HDMI_EDID_EX_DATABLOCK_VIDEO		0x40
> +#define HDMI_EDID_EX_DATABLOCK_VENDOR		0x60
> +#define HDMI_EDID_EX_DATABLOCK_SPEAKERS		0x80
> +
> +/* HDMI EDID Extenion Data Block Values: Video  */
> +#define HDMI_EDID_EX_VIDEO_NATIVE		0x80
> +#define HDMI_EDID_EX_VIDEO_MASK			0x7F
> +#define HDMI_EDID_EX_VIDEO_MAX			35
> +
> +#define HDMI_EDID_EX_VIDEO_640x480p_60Hz_4_3		1
> +#define HDMI_EDID_EX_VIDEO_720x480p_60Hz_4_3		2
> +#define HDMI_EDID_EX_VIDEO_720x480p_60Hz_16_9		3
> +#define HDMI_EDID_EX_VIDEO_1280x720p_60Hz_16_9		4
> +#define HDMI_EDID_EX_VIDEO_1920x1080i_60Hz_16_9		5
> +#define HDMI_EDID_EX_VIDEO_720x480i_60Hz_4_3		6
> +#define HDMI_EDID_EX_VIDEO_720x480i_60Hz_16_9		7
> +#define HDMI_EDID_EX_VIDEO_720x240p_60Hz_4_3		8
> +#define HDMI_EDID_EX_VIDEO_720x240p_60Hz_16_9		9
> +#define HDMI_EDID_EX_VIDEO_2880x480i_60Hz_4_3		10
> +#define HDMI_EDID_EX_VIDEO_2880x480i_60Hz_16_9		11
> +#define HDMI_EDID_EX_VIDEO_2880x480p_60Hz_4_3		12
> +#define HDMI_EDID_EX_VIDEO_2880x480p_60Hz_16_9		13
> +#define HDMI_EDID_EX_VIDEO_1440x480p_60Hz_4_3		14
> +#define HDMI_EDID_EX_VIDEO_1440x480p_60Hz_16_9		15
> +#define HDMI_EDID_EX_VIDEO_1920x1080p_60Hz_16_9		16
> +#define HDMI_EDID_EX_VIDEO_720x576p_50Hz_4_3		17
> +#define HDMI_EDID_EX_VIDEO_720x576p_50Hz_16_9		18
> +#define HDMI_EDID_EX_VIDEO_1280x720p_50Hz_16_9		19
> +#define HDMI_EDID_EX_VIDEO_1920x1080i_50Hz_16_9		20
> +#define HDMI_EDID_EX_VIDEO_720x576i_50Hz_4_3		21
> +#define HDMI_EDID_EX_VIDEO_720x576i_50Hz_16_9		22
> +#define HDMI_EDID_EX_VIDEO_720x288p_50Hz_4_3		23
> +#define HDMI_EDID_EX_VIDEO_720x288p_50Hz_16_9		24
> +#define HDMI_EDID_EX_VIDEO_2880x576i_50Hz_4_3		25
> +#define HDMI_EDID_EX_VIDEO_2880x576i_50Hz_16_9		26
> +#define HDMI_EDID_EX_VIDEO_2880x288p_50Hz_4_3		27
> +#define HDMI_EDID_EX_VIDEO_2880x288p_50Hz_16_9		28
> +#define HDMI_EDID_EX_VIDEO_1440x576p_50Hz_4_3		29
> +#define HDMI_EDID_EX_VIDEO_1440x576p_50Hz_16_9		30
> +#define HDMI_EDID_EX_VIDEO_1920x1080p_50Hz_16_9		31
> +#define HDMI_EDID_EX_VIDEO_1920x1080p_24Hz_16_9		32
> +#define HDMI_EDID_EX_VIDEO_1920x1080p_25Hz_16_9		33
> +#define HDMI_EDID_EX_VIDEO_1920x1080p_30Hz_16_9		34
> +
> +/*  HDMI TPI Registers  */
> +#define HDMI_TPI_VIDEO_DATA_BASE_REG	0x00
> +#define HDMI_TPI_PIXEL_CLK_LSB_REG	 (HDMI_TPI_VIDEO_DATA_BASE_REG + 0x00)
> +#define HDMI_TPI_PIXEL_CLK_MSB_REG (HDMI_TPI_VIDEO_DATA_BASE_REG + 0x01)
> +#define HDMI_TPI_VFREQ_LSB_REG	(HDMI_TPI_VIDEO_DATA_BASE_REG + 0x02)
> +#define HDMI_TPI_VFREQ_MSB_REG	(HDMI_TPI_VIDEO_DATA_BASE_REG + 0x03)
> +#define HDMI_TPI_PIXELS_LSB_REG	(HDMI_TPI_VIDEO_DATA_BASE_REG + 0x04)
> +#define HDMI_TPI_PIXELS_MSB_REG	(HDMI_TPI_VIDEO_DATA_BASE_REG + 0x05)
> +#define HDMI_TPI_LINES_LSB_REG		(HDMI_TPI_VIDEO_DATA_BASE_REG + 0x06)
> +#define HDMI_TPI_LINES_MSB_REG		(HDMI_TPI_VIDEO_DATA_BASE_REG + 0x07)
> +
> +#define HDMI_TPI_PIXEL_REPETITION_REG	0x08
> +
> +#define HDMI_TPI_AVI_INOUT_BASE_REG	0x09
> +#define HDMI_TPI_AVI_IN_FORMAT_REG	(HDMI_TPI_AVI_INOUT_BASE_REG + 0x00)
> +#define HDMI_TPI_AVI_OUT_FORMAT_REG	(HDMI_TPI_AVI_INOUT_BASE_REG + 0x01)
> +
> +#define HDMI_SYS_CTRL_DATA_REG		0x1A
> +
> +#define HDMI_TPI_SYN_GENERATOR_REG	0x60
> +
> +#define HDMI_TPI_VIDEO_SYN_POLARITY_REG	0x61
> +
> +#define HDMI_TPI_DE_BASE_REG			0x62
> +#define HDMI_TPI_DE_DLY_LSB_REG		(HDMI_TPI_DE_BASE_REG + 0x0)
> +#define HDMI_TPI_DE_DLY_MSB_REG		(HDMI_TPI_DE_BASE_REG + 0x1)
> +#define HDMI_TPI_DE_TOP_REG			(HDMI_TPI_DE_BASE_REG + 0x2)
> +#define HDMI_TPI_DE_RSVD_REG			(HDMI_TPI_DE_BASE_REG + 0x3)
> +#define HDMI_TPI_DE_CNT_LSB_REG		(HDMI_TPI_DE_BASE_REG + 0x4)
> +#define HDMI_TPI_DE_CNT_MSB_REG		(HDMI_TPI_DE_BASE_REG + 0x5)
> +#define HDMI_TPI_DE_LIN_LSB_REG		(HDMI_TPI_DE_BASE_REG + 0x6)
> +#define HDMI_TPI_DE_LIN_MSB_REG		(HDMI_TPI_DE_BASE_REG + 0x7)
> +
> +#define HDMI_TPI_HRES_LSB_REG		0x6A
> +#define HDMI_TPI_HRES_MSB_REG		0x6B
> +
> +#define HDMI_TPI_VRES_LSB_REG		0x6C
> +#define HDMI_TPI_VRES_MSB_REG		0x6D
> +
> +#define HDMI_TPI_RQB_REG		0xC7
> +#define HDMI_TPI_DEVID_REG		0x1B
> +#define HDMI_TPI_DEVREV_REG		0x1C
> +
> +#define HDMI_TPI_DEVICE_POWER_STATE_DATA	0x1E
> +#define HDMI_REQ_GRANT_BMODE_REG		0xC7
> +#define HDMI_TPI_DEVICE_ID_REG			0x1B
> +#define HDMI_TPI_REVISION_REG			0x1C
> +#define HDMI_TPI_ID_BYTE2_REG			0x1D
> +#define HDMI_TPI_POWER_STATE_CTRL_REG		0x1E
> +
> +#define HDMI_TPI_INTERRUPT_ENABLE_REG		0x3C
> +#define HDMI_TPI_INTERRUPT_STATUS_REG		0x3D
> +
> +
> +/* AVI InfoFrames can be readed byte by byte but must be write in a burst  */
> +#define HDMI_TPI_AVI_DBYTE_BASE_REG      0x0C
> +#define HDMI_TPI_AVI_DBYTE0_CHKSUM_REG   (HDMI_TPI_AVI_DBYTE_BASE_REG +  0x00)
> +#define HDMI_TPI_AVI_DBYTE1_REG          (HDMI_TPI_AVI_DBYTE_BASE_REG +  0x01)
> +#define HDMI_TPI_AVI_DBYTE2_REG          (HDMI_TPI_AVI_DBYTE_BASE_REG +  0x02)
> +#define HDMI_TPI_AVI_DBYTE3_REG          (HDMI_TPI_AVI_DBYTE_BASE_REG +  0x03)
> +#define HDMI_TPI_AVI_DBYTE4_REG          (HDMI_TPI_AVI_DBYTE_BASE_REG +  0x04)
> +#define HDMI_TPI_AVI_DBYTE5_REG          (HDMI_TPI_AVI_DBYTE_BASE_REG +  0x05)
> +#define HDMI_TPI_AVI_ETB_LSB_REG         (HDMI_TPI_AVI_DBYTE_BASE_REG +  0x06)
> +#define HDMI_TPI_AVI_ETB_MSB_REG         (HDMI_TPI_AVI_DBYTE_BASE_REG +  0x07)
> +#define HDMI_TPI_AVI_SBB_LSB_REG         (HDMI_TPI_AVI_DBYTE_BASE_REG +  0x08)
> +#define HDMI_TPI_AVI_SBB_MSB_REG         (HDMI_TPI_AVI_DBYTE_BASE_REG +  0x09)
> +#define HDMI_TPI_AVI_ELB_LSB_REG         (HDMI_TPI_AVI_DBYTE_BASE_REG +  0x0A)
> +#define HDMI_TPI_AVI_ELB_MSB_REG         (HDMI_TPI_AVI_DBYTE_BASE_REG +  0x0B)
> +#define HDMI_TPI_AVI_SRB_LSB_REG         (HDMI_TPI_AVI_DBYTE_BASE_REG +  0x0C)
> +#define HDMI_TPI_AVI_SRB_MSB_REG         (HDMI_TPI_AVI_DBYTE_BASE_REG +  0x0D)
> +
> +#define HDMI_CPI_MISC_IF_SELECT_REG         0xBF
> +#define HDMI_CPI_MISC_IF_OFFSET             0xC0
> +
> +#define MISC_INFOFRAME_SIZE_MEMORY          14
> +#define MISC_INFOFRAME_TYPE_SUBOFFSET       0
> +#define MISC_INFOFRAME_VERSION_SUBOFFSET    1
> +#define MISC_INFOFRAME_LENGTH_SUBOFFSET     2
> +#define MISC_INFOFRAME_CHECKSUM_SUBOFFSET   3
> +#define MISC_INFOFRAME_DBYTE1_SUBOFFSET     4
> +#define MISC_INFOFRAME_DBYTE2_SUBOFFSET     5
> +#define MISC_INFOFRAME_DBYTE3_SUBOFFSET     6
> +#define MISC_INFOFRAME_DBYTE4_SUBOFFSET     7
> +#define MISC_INFOFRAME_DBYTE5_SUBOFFSET     8
> +#define MISC_INFOFRAME_DBYTE6_SUBOFFSET     9
> +#define MISC_INFOFRAME_DBYTE7_SUBOFFSET     10
> +#define MISC_INFOFRAME_DBYTE8_SUBOFFSET     11
> +#define MISC_INFOFRAME_DBYTE9_SUBOFFSET     12
> +#define MISC_INFOFRAME_DBYTE10_SUBOFFSET    13
> +
> +#define HDMI_CPI_MISC_TYPE_REG		(HDMI_CPI_MISC_IF_OFFSET\
> +					+  MISC_INFOFRAME_TYPE_SUBOFFSET)
> +#define HDMI_CPI_MISC_VERSION_REG	(HDMI_CPI_MISC_IF_OFFSET\
> +					+  MISC_INFOFRAME_VERSION_SUBOFFSET)
> +#define HDMI_CPI_MISC_LENGTH_REG	(HDMI_CPI_MISC_IF_OFFSET\
> +					+  MISC_INFOFRAME_LENGTH_SUBOFFSET)
> +#define HDMI_CPI_MISC_CHECKSUM_REG	(HDMI_CPI_MISC_IF_OFFSET\
> +					+  MISC_INFOFRAME_CHECKSUM_SUBOFFSET)
> +#define HDMI_CPI_MISC_DBYTE1_REG        (HDMI_CPI_MISC_IF_OFFSET\
> +					+  MISC_INFOFRAME_DBYTE1_SUBOFFSET)
> +#define HDMI_CPI_MISC_DBYTE2_REG        (HDMI_CPI_MISC_IF_OFFSET\
> +					+  MISC_INFOFRAME_DBYTE2_SUBOFFSET)
> +#define HDMI_CPI_MISC_DBYTE3_REG        (HDMI_CPI_MISC_IF_OFFSET\
> +					+  MISC_INFOFRAME_DBYTE3_SUBOFFSET)
> +#define HDMI_CPI_MISC_DBYTE4_REG        (HDMI_CPI_MISC_IF_OFFSET\
> +					+  MISC_INFOFRAME_DBYTE4_SUBOFFSET)
> +#define HDMI_CPI_MISC_DBYTE5_REG        (HDMI_CPI_MISC_IF_OFFSET\
> +					+  MISC_INFOFRAME_DBYTE5_SUBOFFSET)
> +#define HDMI_CPI_MISC_DBYTE6_REG        (HDMI_CPI_MISC_IF_OFFSET\
> +					+  MISC_INFOFRAME_DBYTE6_SUBOFFSET)
> +#define HDMI_CPI_MISC_DBYTE7_REG        (HDMI_CPI_MISC_IF_OFFSET\
> +					+  MISC_INFOFRAME_DBYTE7_SUBOFFSET)
> +#define HDMI_CPI_MISC_DBYTE8_REG        (HDMI_CPI_MISC_IF_OFFSET\
> +					+  MISC_INFOFRAME_DBYTE8_SUBOFFSET)
> +#define HDMI_CPI_MISC_DBYTE9_REG        (HDMI_CPI_MISC_IF_OFFSET\
> +					+  MISC_INFOFRAME_DBYTE9_SUBOFFSET)
> +#define HDMI_CPI_MISC_DBYTE10_REG       (HDMI_CPI_MISC_IF_OFFSET\
> +					+  MISC_INFOFRAME_DBYTE10_SUBOFFSET)
> +
> +/* Audio  */
> +#define HDMI_TPI_I2S_ENABLE_MAPPING_REG     0x1F
> +#define HDMI_TPI_I2S_INPUT_CONFIG_REG       0x20
> +#define HDMI_TPI_I2S_STRM_HDR_BASE          0x21
> +#define HDMI_TPI_I2S_STRM_HDR_0_REG         (HDMI_TPI_I2S_STRM_HDR_BASE + 0)
> +#define HDMI_TPI_I2S_STRM_HDR_1_REG         (HDMI_TPI_I2S_STRM_HDR_BASE + 1)
> +#define HDMI_TPI_I2S_STRM_HDR_2_REG         (HDMI_TPI_I2S_STRM_HDR_BASE + 2)
> +#define HDMI_TPI_I2S_STRM_HDR_3_REG         (HDMI_TPI_I2S_STRM_HDR_BASE + 3)
> +#define HDMI_TPI_I2S_STRM_HDR_4_REG         (HDMI_TPI_I2S_STRM_HDR_BASE + 4)
> +#define HDMI_TPI_AUDIO_CONFIG_BYTE2_REG     0x26
> +#define HDMI_TPI_AUDIO_CONFIG_BYTE3_REG     0x27
> +#define HDMI_TPI_AUDIO_CONFIG_BYTE4_REG     0x28
> +
> +/* HDCP */
> +#define HDMI_TPI_HDCP_QUERYDATA_REG         0x29
> +#define HDMI_TPI_HDCP_CONTROLDATA_REG       0x2A
> +
> +/* HDMI_TPI_DEVICE_ID_REG  */
> +#define TPI_DEVICE_ID                       0xB0
> +
> +/* HDMI_TPI_REVISION_REG  */
> +#define TPI_REVISION                        0x00
> +
> +/* HDMI_TPI_ID_BYTE2_REG  */
> +#define TPI_ID_BYTE2_VALUE                  0x00
> +
> +/* HDMI_SYS_CTRL_DATA_REG  */
> +#define TPI_SYS_CTRL_POWER_DOWN             (1 << 4)
> +#define TPI_SYS_CTRL_POWER_ACTIVE           (0 << 4)
> +#define TPI_SYS_CTRL_AV_MUTE                (1 << 3)
> +#define TPI_SYS_CTRL_DDC_BUS_REQUEST        (1 << 2)
> +#define TPI_SYS_CTRL_DDC_BUS_GRANTED        (1 << 1)
> +#define TPI_SYS_CTRL_OUTPUT_MODE_HDMI       (1 << 0)
> +#define TPI_SYS_CTRL_OUTPUT_MODE_DVI        (0 << 0)
> +
> +
> +/* HDMI Monitor I2C default address  */
> +#define HDMI_I2C_MONITOR_ADDRESS            0x50
> +
> +
> +/* HDMI_TPI_INTR_ENABLE  */
> +#define TPI_INTR_ENABLE_SECURITY_EVENT      (1 << 5)
> +#define TPI_INTR_ENABLE_AUDIO_EVENT         (1 << 4)
> +#define TPI_INTR_ENABLE_CPI_EVENT           (1 << 3)
> +#define TPI_INTR_ENABLE_RECEIVER_EVENT      (1 << 1)
> +#define TPI_INTR_ENABLE_HOTPLUG_EVENT       (1 << 0)
> +
> +/* HDMI_TPI_INTR_STATUS  */
> +#define TPI_INTR_STATUS_SECURITY_EVENT      (1 << 5)
> +#define TPI_INTR_STATUS_AUDIO_EVENT         (1 << 4)
> +#define TPI_INTR_STATUS_POWERED_EVENT       (1 << 3)
> +#define TPI_INTR_STATUS_HOTPLUG_STATE       (1 << 2)
> +#define TPI_INTR_STATUS_RECEIVER_EVENT      (1 << 1)
> +#define TPI_INTR_STATUS_HOTPLUG_EVENT       (1 << 0)
> +
> +
> +/* HDMI_TPI_PIXEL_REPETITION  */
> +#define TPI_AVI_PIXEL_REP_BUS_24BIT         (1 << 5)
> +#define TPI_AVI_PIXEL_REP_BUS_12BIT         (0 << 5)
> +#define TPI_AVI_PIXEL_REP_RISING_EDGE       (1 << 4)
> +#define TPI_AVI_PIXEL_REP_FALLING_EDGE      (0 << 4)
> +#define TPI_AVI_PIXEL_REP_4X                (3 << 0)
> +#define TPI_AVI_PIXEL_REP_2X                (1 << 0)
> +#define TPI_AVI_PIXEL_REP_NONE              (0 << 0)
> +
> +/* HDMI_TPI_AVI_INPUT_FORMAT  */
> +#define TPI_AVI_INPUT_BITMODE_12BIT         (1 << 7)
> +#define TPI_AVI_INPUT_BITMODE_8BIT          (0 << 7)
> +#define TPI_AVI_INPUT_DITHER                (1 << 6)
> +#define TPI_AVI_INPUT_RANGE_LIMITED         (2 << 2)
> +#define TPI_AVI_INPUT_RANGE_FULL            (1 << 2)
> +#define TPI_AVI_INPUT_RANGE_AUTO            (0 << 2)
> +#define TPI_AVI_INPUT_COLORSPACE_BLACK      (3 << 0)
> +#define TPI_AVI_INPUT_COLORSPACE_YUV422     (2 << 0)
> +#define TPI_AVI_INPUT_COLORSPACE_YUV444     (1 << 0)
> +#define TPI_AVI_INPUT_COLORSPACE_RGB        (0 << 0)
> +
> +
> +/* HDMI_TPI_AVI_OUTPUT_FORMAT  */
> +#define TPI_AVI_OUTPUT_CONV_BT709           (1 << 4)
> +#define TPI_AVI_OUTPUT_CONV_BT601           (0 << 4)
> +#define TPI_AVI_OUTPUT_RANGE_LIMITED        (2 << 2)
> +#define TPI_AVI_OUTPUT_RANGE_FULL           (1 << 2)
> +#define TPI_AVI_OUTPUT_RANGE_AUTO           (0 << 2)
> +#define TPI_AVI_OUTPUT_COLORSPACE_RGBDVI    (3 << 0)
> +#define TPI_AVI_OUTPUT_COLORSPACE_YUV422    (2 << 0)
> +#define TPI_AVI_OUTPUT_COLORSPACE_YUV444    (1 << 0)
> +#define TPI_AVI_OUTPUT_COLORSPACE_RGBHDMI   (0 << 0)
> +
> +
> +/* HDMI_TPI_DEVICE_POWER_STATE  */
> +#define TPI_AVI_POWER_STATE_D3              (3 << 0)
> +#define TPI_AVI_POWER_STATE_D2              (2 << 0)
> +#define TPI_AVI_POWER_STATE_D0              (0 << 0)
> +
> +/* HDMI_TPI_AUDIO_CONFIG_BYTE2_REG  */
> +#define TPI_AUDIO_CODING_STREAM_HEADER      (0 << 0)
> +#define TPI_AUDIO_CODING_PCM                (1 << 0)
> +#define TPI_AUDIO_CODING_AC3                (2 << 0)
> +#define TPI_AUDIO_CODING_MPEG1              (3 << 0)
> +#define TPI_AUDIO_CODING_MP3                (4 << 0)
> +#define TPI_AUDIO_CODING_MPEG2              (5 << 0)
> +#define TPI_AUDIO_CODING_AAC                (6 << 0)
> +#define TPI_AUDIO_CODING_DTS                (7 << 0)
> +#define TPI_AUDIO_CODING_ATRAC              (8 << 0)
> +#define TPI_AUDIO_MUTE_DISABLE              (0 << 4)
> +#define TPI_AUDIO_MUTE_ENABLE               (1 << 4)
> +#define TPI_AUDIO_INTERFACE_DISABLE         (0 << 6)
> +#define TPI_AUDIO_INTERFACE_SPDIF           (1 << 6)
> +#define TPI_AUDIO_INTERFACE_I2S             (2 << 6)
> +
> +/* HDMI_TPI_AUDIO_CONFIG_BYTE3_REG  */
> +#define TPI_AUDIO_CHANNEL_STREAM            (0 << 0)
> +#define TPI_AUDIO_2_CHANNEL                 (1 << 0)
> +#define TPI_AUDIO_8_CHANNEL                 (7 << 0)
> +#define TPI_AUDIO_FREQ_STREAM               (0 << 3)
> +#define TPI_AUDIO_FREQ_32KHZ                (1 << 3)
> +#define TPI_AUDIO_FREQ_44KHZ                (2 << 3)
> +#define TPI_AUDIO_FREQ_48KHZ                (3 << 3)
> +#define TPI_AUDIO_FREQ_88KHZ                (4 << 3)
> +#define TPI_AUDIO_FREQ_96KHZ                (5 << 3)
> +#define TPI_AUDIO_FREQ_176KHZ               (6 << 3)
> +#define TPI_AUDIO_FREQ_192KHZ               (7 << 3)
> +#define TPI_AUDIO_SAMPLE_SIZE_STREAM        (0 << 6)
> +#define TPI_AUDIO_SAMPLE_SIZE_16            (1 << 6)
> +#define TPI_AUDIO_SAMPLE_SIZE_20            (2 << 6)
> +#define TPI_AUDIO_SAMPLE_SIZE_24            (3 << 6)
> +
> +/* HDMI_TPI_I2S_ENABLE_MAPPING_REG  */
> +#define TPI_I2S_SD_CONFIG_SELECT_SD0        (0 << 0)
> +#define TPI_I2S_SD_CONFIG_SELECT_SD1        (1 << 0)
> +#define TPI_I2S_SD_CONFIG_SELECT_SD2        (2 << 0)
> +#define TPI_I2S_SD_CONFIG_SELECT_SD3        (3 << 0)
> +#define TPI_I2S_LF_RT_SWAP_NO               (0 << 2)
> +#define TPI_I2S_LF_RT_SWAP_YES              (1 << 2)
> +#define TPI_I2S_DOWNSAMPLE_DISABLE          (0 << 3)
> +#define TPI_I2S_DOWNSAMPLE_ENABLE           (1 << 3)
> +#define TPI_I2S_SD_FIFO_0                   (0 << 4)
> +#define TPI_I2S_SD_FIFO_1                   (1 << 4)
> +#define TPI_I2S_SD_FIFO_2                   (2 << 4)
> +#define TPI_I2S_SD_FIFO_3                   (3 << 4)
> +#define TPI_I2S_SD_CHANNEL_DISABLE          (0 << 7)
> +#define TPI_I2S_SD_CHANNEL_ENABLE           (1 << 7)
> +
> +
> +/* HDMI_TPI_I2S_INPUT_CONFIG_REG  */
> +#define TPI_I2S_FIRST_BIT_SHIFT_YES         (0 << 0)
> +#define TPI_I2S_FIRST_BIT_SHIFT_NO          (1 << 0)
> +#define TPI_I2S_SD_DIRECTION_MSB_FIRST      (0 << 1)
> +#define TPI_I2S_SD_DIRECTION_LSB_FIRST      (1 << 1)
> +#define TPI_I2S_SD_JUSTIFY_LEFT             (0 << 2)
> +#define TPI_I2S_SD_JUSTIFY_RIGHT            (1 << 2)
> +#define TPI_I2S_WS_POLARITY_LOW             (0 << 3)
> +#define TPI_I2S_WS_POLARITY_HIGH            (1 << 3)
> +#define TPI_I2S_MCLK_MULTIPLIER_128         (0 << 4)
> +#define TPI_I2S_MCLK_MULTIPLIER_256         (1 << 4)
> +#define TPI_I2S_MCLK_MULTIPLIER_384         (2 << 4)
> +#define TPI_I2S_MCLK_MULTIPLIER_512         (3 << 4)
> +#define TPI_I2S_MCLK_MULTIPLIER_768         (4 << 4)
> +#define TPI_I2S_MCLK_MULTIPLIER_1024        (5 << 4)
> +#define TPI_I2S_MCLK_MULTIPLIER_1152        (6 << 4)
> +#define TPI_I2S_MCLK_MULTIPLIER_192         (7 << 4)
> +#define TPI_I2S_SCK_EDGE_FALLING            (0 << 7)
> +#define TPI_I2S_SCK_EDGE_RISING             (1 << 7)
> +
> +/* HDMI_TPI_I2S_STRM_HDR_REG                       */
> +/* the reference of this values is in IEC 60958-3  */
> +#define I2S_CHAN_STATUS_MODE                0x00
> +#define I2S_CHAN_STATUS_CAT_CODE            0x00
> +#define I2S_CHAN_SOURCE_CHANNEL_NUM         0x00
> +#define I2S_CHAN_ACCURACY_N_44_SAMPLING_FS  0x20
> +#define I2S_CHAN_ACCURACY_N_48_SAMPLING_FS  0x22
> +#define I2S_CHAN_ORIGIN_FS_N_SAMP_LENGTH    0xD2
> +
> +
> +/* MISCELLANOUS INFOFRAME VALUES  */
> +
> +#define HDMI_INFOFRAME_TX_ENABLE            (0x1 << 7)
> +#define HDMI_INFOFRAME_TX_REPEAT            (0x1 << 6)
> +#define HDMI_AUDIO_INFOFRAME                (0x2 << 0)
> +
> +/* Stream Header Data  */
> +#define HDMI_SH_PCM                         (0x1 << 4)
> +#define HDMI_SH_TWO_CHANNELS                (0x1 << 0)
> +#define HDMI_SH_44KHz                       (0x2 << 2)
> +#define HDMI_SH_48KHz                       (0x3 << 2)
> +#define HDMI_SH_16BIT                       (0x1 << 0)
> +#define HDMI_SH_SPKR_FLFR                   0x0
> +#define HDMI_SH_0dB_ATUN                    0x0
> +
> +/* MISC_TYPE  */
> +#define MISC_INFOFRAME_TYPE                 0x04  /* for Audio */
> +#define MISC_INFOFRAME_ALWAYS_SET           0x80
> +
> +/* MISC_VERSION  */
> +#define MISC_INFOFRAME_VERSION              0x01
> +
> +/* MISC_LENGTH  */
> +#define MISC_INFOFRAME_LENGTH               0x0A /*length for Audio infoframe*/
> +#define MISC_INFOFRAME_LENGTH_RSVD_BITS     0xE0
> +
> +/* MISC_DBYTE1                */
> +/* Type, Encoding, Trandport  */
> +#define MISC_DBYTE1_CT_CHK_HEADER_STREAM    0x00
> +
> +/* audio channel count  */
> +#define MISC_DBYTE1_CC_CHK_HEADER_STREAM    0x00
> +#define MISC_DBYTE1_CC_2_CHANNELS           0x01
> +
> +/* MISC_DBYTE2  */
> +/*Sample Size   */
> +#define MISC_DBYTE2_SS_CHK_HEADER_STREAM    0x00  /* for hdmi by default */
> +
> +/* Sampling Frequency  */
> +#define MISC_DBYTE2_SF_CHK_HEADER_STREAM    0x00  /* for hdmi by default */
> +
> +/* MISC_DBYTE3     */
> +/* Code Extention  */
> +#define MISC_DBYTE3_CTX_TAKE_DBYTE1         0x00  /* for hdmi by default */
> +
> +/* MISC_DBYTE4  */
> +#define MISC_DBYTE4                         0x00 /*for no multichannel( */
> +						 /* multichannel means more*/
> +						/* than 2 channels */
> +
> +/* MISC_DBYTE5  */
> +#define MISC_DBYTE5           0x00  /* for no multichannel(multichannel  */
> +					/* means more than 2 channels */
> +
> +struct hdmi_reg_data {
> +	u8 reg_offset;
> +	u8 value;
> +};
> +
> +#endif
> -- 
> 1.7.9.5
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-fbdev" 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

* [ANNOUNCE] second pull for fbdev this friday
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-07-11  9:52 UTC (permalink / raw)
  To: linux-fbdev

HI,

	I'm goign to send a second pull to Linus for the fbdev for 3.11

	If you have patch that I did merge (I forget or request a rebase)
	ping them a send them quick


	I plan to send the pull friday night shangahi time or max sunday

Best Regards,
J.

^ permalink raw reply

* Re: [PATCH] omapfb: In omapfb_probe return -EPROBE_DEFER when display driver is not loaded yet
From: Archit Taneja @ 2013-07-11  8:50 UTC (permalink / raw)
  To: Pali Rohár
  Cc: Tomi Valkeinen, Jean-Christophe Plagniol-Villard, linux-omap,
	linux-fbdev, linux-kernel, Pavel Machek, Aaro Koskinen,
	Tony Lindgren
In-Reply-To: <1373461739-10168-1-git-send-email-pali.rohar@gmail.com>

Hi,

On Wednesday 10 July 2013 06:38 PM, Pali Rohár wrote:
> * On RX-51 probing for acx565akm driver is later then for omapfb which cause that omapfb probe fail and framebuffer is not working
> * EPROBE_DEFER causing that kernel try to probe for omapfb later again which fixing this problem
>
> * Without this patch display on Nokia RX-51 (N900) phone not working
>
> Signed-off-by: Pali Rohár <pali.rohar@gmail.com>
> ---
>   drivers/video/omap2/omapfb/omapfb-main.c |    9 +++++++++
>   1 file changed, 9 insertions(+)
>
> diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
> index 856917b..93e7c84 100644
> --- a/drivers/video/omap2/omapfb/omapfb-main.c
> +++ b/drivers/video/omap2/omapfb/omapfb-main.c
> @@ -2419,6 +2419,15 @@ static int omapfb_probe(struct platform_device *pdev)
>   	if (omapdss_is_initialized() = false)
>   		return -EPROBE_DEFER;
>
> +	dssdev = NULL;
> +	for_each_dss_dev(dssdev) {
> +		if (!dssdev->driver) {
> +			dev_warn(&pdev->dev, "no driver for display: %s\n",
> +				dssdev->name);
> +			return -EPROBE_DEFER;

This will make omapfb probe defer till the time every panel has a 
driver. It's possible that all the panel driver modules are never 
interested by userspace. This will lead to the panels having drivers 
also not work.

I think Tomi was working on this, it was something like making omapfb 
defer only if the default display doesn't have a driver. We can wait for 
his comment.

Archit

> +		}
> +	}
> +
>   	if (pdev->num_resources != 0) {
>   		dev_err(&pdev->dev, "probed for an unknown device\n");
>   		r = -ENODEV;
>


^ permalink raw reply

* [PATCH] vga16fb: Remove unused variable
From: Luis Henriques @ 2013-07-10 22:57 UTC (permalink / raw)
  To: linux-fbdev
  Cc: Jean-Christophe Plagniol-Villard, Tomi Valkeinen, linux-kernel

Fix build warning of unused variable:

drivers/video/vga16fb.c:1268:26: warning: unused variable ‘dev’ [-Wunused-variable]

Signed-off-by: Luis Henriques<luis.henriques@canonical.com>
---
 drivers/video/vga16fb.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c
index 830ded4..2827333 100644
--- a/drivers/video/vga16fb.c
+++ b/drivers/video/vga16fb.c
@@ -1265,7 +1265,6 @@ static void vga16fb_imageblit(struct fb_info *info, const struct fb_image *image
 
 static void vga16fb_destroy(struct fb_info *info)
 {
-	struct platform_device *dev = container_of(info->device, struct platform_device, dev);
 	iounmap(info->screen_base);
 	fb_dealloc_cmap(&info->cmap);
 	/* XXX unshare VGA regions */
-- 
1.8.1.2

^ permalink raw reply related

* [PATCH 12/12] drivers/video: don't use devm_pinctrl_get_select_default() in probe
From: Wolfram Sang @ 2013-07-10 15:57 UTC (permalink / raw)
  To: linux-kernel
  Cc: Wolfram Sang, Jean-Christophe Plagniol-Villard, Tomi Valkeinen,
	linux-fbdev
In-Reply-To: <1373471889-18107-1-git-send-email-wsa@the-dreams.de>

Since commit ab78029 (drivers/pinctrl: grab default handles from device core),
we can rely on device core for setting the default pins. Compile tested only.

Acked-by: Linus Walleij <linus.walleij@linaro.org> (personally at LCE13)
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
---
 drivers/video/mxsfb.c |    8 --------
 1 file changed, 8 deletions(-)

diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c
index 3ba3771..5861ba2 100644
--- a/drivers/video/mxsfb.c
+++ b/drivers/video/mxsfb.c
@@ -46,7 +46,6 @@
 #include <linux/clk.h>
 #include <linux/dma-mapping.h>
 #include <linux/io.h>
-#include <linux/pinctrl/consumer.h>
 #include <linux/fb.h>
 #include <linux/regulator/consumer.h>
 #include <video/of_display_timing.h>
@@ -877,7 +876,6 @@ static int mxsfb_probe(struct platform_device *pdev)
 	struct mxsfb_info *host;
 	struct fb_info *fb_info;
 	struct fb_modelist *modelist;
-	struct pinctrl *pinctrl;
 	int ret;
 
 	if (of_id)
@@ -908,12 +906,6 @@ static int mxsfb_probe(struct platform_device *pdev)
 
 	host->devdata = &mxsfb_devdata[pdev->id_entry->driver_data];
 
-	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
-	if (IS_ERR(pinctrl)) {
-		ret = PTR_ERR(pinctrl);
-		goto fb_release;
-	}
-
 	host->clk = devm_clk_get(&host->pdev->dev, NULL);
 	if (IS_ERR(host->clk)) {
 		ret = PTR_ERR(host->clk);
-- 
1.7.10.4


^ permalink raw reply related

* =?UTF-8?q?=5BPATCH=5D=20omapfb=3A=20In=20omapfb=5Fprobe=20return=20-EPROBE=5FDEFER=20when=20display=
From: Pali Rohár @ 2013-07-10 13:08 UTC (permalink / raw)
  To: Tomi Valkeinen, Jean-Christophe Plagniol-Villard
  Cc: linux-omap, linux-fbdev, linux-kernel, Pavel Machek,
	Aaro Koskinen, Tony Lindgren, Pali Rohár

* On RX-51 probing for acx565akm driver is later then for omapfb which cause that omapfb probe fail and framebuffer is not working
* EPROBE_DEFER causing that kernel try to probe for omapfb later again which fixing this problem

* Without this patch display on Nokia RX-51 (N900) phone not working

Signed-off-by: Pali Rohár <pali.rohar@gmail.com>
---
 drivers/video/omap2/omapfb/omapfb-main.c |    9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index 856917b..93e7c84 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -2419,6 +2419,15 @@ static int omapfb_probe(struct platform_device *pdev)
 	if (omapdss_is_initialized() = false)
 		return -EPROBE_DEFER;
 
+	dssdev = NULL;
+	for_each_dss_dev(dssdev) {
+		if (!dssdev->driver) {
+			dev_warn(&pdev->dev, "no driver for display: %s\n",
+				dssdev->name);
+			return -EPROBE_DEFER;
+		}
+	}
+
 	if (pdev->num_resources != 0) {
 		dev_err(&pdev->dev, "probed for an unknown device\n");
 		r = -ENODEV;
-- 
1.7.10.4


^ permalink raw reply related

* [RFC PATCH v1 2/2] dma-buf: add lock callback for fcntl system call.
From: Inki Dae @ 2013-07-10 11:58 UTC (permalink / raw)
  To: dri-devel, linux-fbdev, linux-arm-kernel, linux-media
  Cc: maarten.lankhorst, daniel, robdclark, kyungmin.park, myungjoo.ham,
	yj44.cho, Inki Dae
In-Reply-To: <1373457527-28263-1-git-send-email-inki.dae@samsung.com>

This patch adds lock callback to dma buf file operations,
and this callback will be called by fcntl system call.

With this patch, fcntl system call can be used for buffer
synchronization between CPU and CPU, and CPU and DMA in user mode.

Signed-off-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 drivers/base/dma-buf.c |   34 ++++++++++++++++++++++++++++++++++
 1 files changed, 34 insertions(+), 0 deletions(-)

diff --git a/drivers/base/dma-buf.c b/drivers/base/dma-buf.c
index fe39120..cd71447 100644
--- a/drivers/base/dma-buf.c
+++ b/drivers/base/dma-buf.c
@@ -31,6 +31,7 @@
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 #include <linux/reservation.h>
+#include <linux/dmabuf-sync.h>
 
 static inline int is_dma_buf_file(struct file *);
 
@@ -82,9 +83,42 @@ static int dma_buf_mmap_internal(struct file *file, struct vm_area_struct *vma)
 	return dmabuf->ops->mmap(dmabuf, vma);
 }
 
+static int dma_buf_lock(struct file *file, int cmd, struct file_lock *fl)
+{
+	struct dma_buf *dmabuf;
+	unsigned int type;
+	bool wait = false;
+
+	if (!is_dma_buf_file(file))
+		return -EINVAL;
+
+	dmabuf = file->private_data;
+
+	if ((fl->fl_type & F_UNLCK) = F_UNLCK) {
+		dmabuf_sync_single_unlock(dmabuf);
+		return 0;
+	}
+
+	/* convert flock type to dmabuf sync type. */
+	if ((fl->fl_type & F_WRLCK) = F_WRLCK)
+		type = DMA_BUF_ACCESS_W;
+	else if ((fl->fl_type & F_RDLCK) = F_RDLCK)
+		type = DMA_BUF_ACCESS_R;
+	else
+		return -EINVAL;
+
+	if (fl->fl_flags & FL_SLEEP)
+		wait = true;
+
+	/* TODO. the locking to certain region should also be considered. */
+
+	return dmabuf_sync_single_lock(dmabuf, type, wait);
+}
+
 static const struct file_operations dma_buf_fops = {
 	.release	= dma_buf_release,
 	.mmap		= dma_buf_mmap_internal,
+	.lock		= dma_buf_lock,
 };
 
 /*
-- 
1.7.5.4


^ permalink raw reply related

* [RFC PATCH v4 1/2] dmabuf-sync: Introduce buffer synchronization framework
From: Inki Dae @ 2013-07-10 11:58 UTC (permalink / raw)
  To: dri-devel, linux-fbdev, linux-arm-kernel, linux-media
  Cc: maarten.lankhorst, daniel, robdclark, kyungmin.park, myungjoo.ham,
	yj44.cho, Inki Dae
In-Reply-To: <1373457527-28263-1-git-send-email-inki.dae@samsung.com>

This patch adds a buffer synchronization framework based on DMA BUF[1]
and reservation[2] to use dma-buf resource, and based on ww-mutexes[3]
for lock mechanism.

The purpose of this framework is to provide not only buffer access control
to CPU and DMA but also easy-to-use interfaces for device drivers and
user application. This framework can be used for all dma devices using
system memory as dma buffer, especially for most ARM based SoCs.

Changelog v4:
- Add user side interface for buffer synchronization mechanism and update
  descriptions related to the user side interface.

Changelog v3:
- remove cache operation relevant codes and update document file.

Changelog v2:
- use atomic_add_unless to avoid potential bug.
- add a macro for checking valid access type.
- code clean.

The mechanism of this framework has the following steps,
    1. Register dmabufs to a sync object - A task gets a new sync object and
    can add one or more dmabufs that the task wants to access.
    This registering should be performed when a device context or an event
    context such as a page flip event is created or before CPU accesses a shared
    buffer.

	dma_buf_sync_get(a sync object, a dmabuf);

    2. Lock a sync object - A task tries to lock all dmabufs added in its own
    sync object. Basically, the lock mechanism uses ww-mutex[1] to avoid dead
    lock issue and for race condition between CPU and CPU, CPU and DMA, and DMA
    and DMA. Taking a lock means that others cannot access all locked dmabufs
    until the task that locked the corresponding dmabufs, unlocks all the locked
    dmabufs.
    This locking should be performed before DMA or CPU accesses these dmabufs.

	dma_buf_sync_lock(a sync object);

    3. Unlock a sync object - The task unlocks all dmabufs added in its own sync
    object. The unlock means that the DMA or CPU accesses to the dmabufs have
    been completed so that others may access them.
    This unlocking should be performed after DMA or CPU has completed accesses
    to the dmabufs.

	dma_buf_sync_unlock(a sync object);

    4. Unregister one or all dmabufs from a sync object - A task unregisters
    the given dmabufs from the sync object. This means that the task dosen't
    want to lock the dmabufs.
    The unregistering should be performed after DMA or CPU has completed
    accesses to the dmabufs or when dma_buf_sync_lock() is failed.

	dma_buf_sync_put(a sync object, a dmabuf);
	dma_buf_sync_put_all(a sync object);

    The described steps may be summarized as:
	get -> lock -> CPU or DMA access to a buffer/s -> unlock -> put

This framework includes the following two features.
    1. read (shared) and write (exclusive) locks - A task is required to declare
    the access type when the task tries to register a dmabuf;
    READ, WRITE, READ DMA, or WRITE DMA.

    The below is example codes,
	struct dmabuf_sync *sync;

	sync = dmabuf_sync_init(NULL, "test sync");

	dmabuf_sync_get(sync, dmabuf, DMA_BUF_ACCESS_R);
	...

	And the below can be used as access types:
		DMA_BUF_ACCESS_R - CPU will access a buffer for read.
		DMA_BUF_ACCESS_W - CPU will access a buffer for read or write.
		DMA_BUF_ACCESS_DMA_R - DMA will access a buffer for read
		DMA_BUF_ACCESS_DMA_W - DMA will access a buffer for read or
					write.

    2. Mandatory resource releasing - a task cannot hold a lock indefinitely.
    A task may never try to unlock a buffer after taking a lock to the buffer.
    In this case, a timer handler to the corresponding sync object is called
    in five (default) seconds and then the timed-out buffer is unlocked by work
    queue handler to avoid lockups and to enforce resources of the buffer.


The below is how to use for device driver:
	1. Allocate and Initialize a sync object:
		struct dmabuf_sync *sync;

		sync = dmabuf_sync_init(NULL, "test sync");
		...

	2. Add a dmabuf to the sync object when setting up dma buffer relevant
	   registers:
		dmabuf_sync_get(sync, dmabuf, DMA_BUF_ACCESS_READ);
		...

	3. Lock all dmabufs of the sync object before DMA or CPU accesses
	   the dmabufs:
		dmabuf_sync_lock(sync);
		...

	4. Now CPU or DMA can access all dmabufs locked in step 3.

	5. Unlock all dmabufs added in a sync object after DMA or CPU access
	   to these dmabufs is completed:
		dmabuf_sync_unlock(sync);

	   And call the following functions to release all resources,
		dmabuf_sync_put_all(sync);
		dmabuf_sync_fini(sync);

	You can refer to actual example codes:
		https://git.kernel.org/cgit/linux/kernel/git/daeinki/drm-exynos.git/
		commit/?h=dmabuf-sync&id@30bdee9bab5841ad32faade528d04cc0c5fc94

		https://git.kernel.org/cgit/linux/kernel/git/daeinki/drm-exynos.git/
		commit/?h=dmabuf-sync&idla548e9ea9e865592719ef6b1cde58366af9f5c

And this framework includes fcntl system call[4] as interfaces exported
to user. As you know, user sees a buffer object as a dma-buf file descriptor.
So fcntl() call with the file descriptor means to lock some buffer region being
managed by the dma-buf object.

The below is how to use for user application:
	struct flock filelock;

	1. Lock a dma buf:
		filelock.l_type = F_WRLCK or F_RDLCK;

		/* lock entire region to the dma buf. */
		filelock.lwhence = SEEK_CUR;
		filelock.l_start = 0;
		filelock.l_len = 0;

		fcntl(dmabuf fd, F_SETLKW or F_SETLK, &filelock);
		...
		CPU access to the dma buf

	2. Unlock a dma buf:
		filelock.l_type = F_UNLCK;

		fcntl(dmabuf fd, F_SETLKW or F_SETLK, &filelock);

		close(dmabuf fd) call would also unlock the dma buf. And for more
		detail, please refer to [4]


References:
[1] http://lwn.net/Articles/470339/
[2] http://lwn.net/Articles/532616/
[3] https://patchwork.kernel.org/patch/2625361/
[4] http://linux.die.net/man/2/fcntl

Signed-off-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 Documentation/dma-buf-sync.txt |  283 +++++++++++++++++
 drivers/base/Kconfig           |    7 +
 drivers/base/Makefile          |    1 +
 drivers/base/dmabuf-sync.c     |  661 ++++++++++++++++++++++++++++++++++++++++
 include/linux/dma-buf.h        |   14 +
 include/linux/dmabuf-sync.h    |  132 ++++++++
 include/linux/reservation.h    |    9 +
 7 files changed, 1107 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/dma-buf-sync.txt
 create mode 100644 drivers/base/dmabuf-sync.c
 create mode 100644 include/linux/dmabuf-sync.h

diff --git a/Documentation/dma-buf-sync.txt b/Documentation/dma-buf-sync.txt
new file mode 100644
index 0000000..9d12d00
--- /dev/null
+++ b/Documentation/dma-buf-sync.txt
@@ -0,0 +1,283 @@
+                    DMA Buffer Synchronization Framework
+                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+                                  Inki Dae
+                      <inki dot dae at samsung dot com>
+                          <daeinki at gmail dot com>
+
+This document is a guide for device-driver writers describing the DMA buffer
+synchronization API. This document also describes how to use the API to
+use buffer synchronization mechanism between DMA and DMA, CPU and DMA, and
+CPU and CPU.
+
+The DMA Buffer synchronization API provides buffer synchronization mechanism;
+i.e., buffer access control to CPU and DMA, and easy-to-use interfaces for
+device drivers and user application. And this API can be used for all dma
+devices using system memory as dma buffer, especially for most ARM based SoCs.
+
+
+Motivation
+----------
+
+Buffer synchronization issue between DMA and DMA:
+	Sharing a buffer, a device cannot be aware of when the other device
+	will access the shared buffer: a device may access a buffer containing
+	wrong data if the device accesses the shared buffer while another
+	device is still accessing the shared buffer.
+	Therefore, a user process should have waited for the completion of DMA
+	access by another device before a device tries to access the shared
+	buffer.
+
+Buffer synchronization issue between CPU and DMA:
+	A user process should consider that when having to send a buffer, filled
+	by CPU, to a device driver for the device driver to access the buffer as
+	a input buffer while CPU and DMA are sharing the buffer.
+	This means that the user process needs to understand how the device
+	driver is worked. Hence, the conventional mechanism not only makes
+	user application complicated but also incurs performance overhead.
+
+Buffer synchronization issue between CPU and CPU:
+	In case that two processes share one buffer; shared with DMA also,
+	they may need some mechanism to allow process B to access the shared
+	buffer after the completion of CPU access by process A.
+	Therefore, process B should have waited for the completion of CPU access
+	by process A using the mechanism before trying to access the shared
+	buffer.
+
+What is the best way to solve these buffer synchronization issues?
+	We may need a common object that a device driver and a user process
+	notify the common object of when they try to access a shared buffer.
+	That way we could decide when we have to allow or not to allow for CPU
+	or DMA to access the shared buffer through the common object.
+	If so, what could become the common object? Right, that's a dma-buf[1].
+	Now we have already been using the dma-buf to share one buffer with
+	other drivers.
+
+How we can utilize multi threads for more performance?
+	DMA and CPU works individually. So CPU could perform other works while
+	DMA is performing some works, and vise versa. However, in conventional
+	way, that is not easy to do so because DMA operation is depend on CPU
+	operation, and vice versa.
+
+	conventional way:
+	User                                     Kernel
+	---------------------------------------------------------------------
+	CPU writes something to src
+	send the src to driver------------------------->
+	                                         update DMA register
+	request DMA start------------------------------>
+	                                         DMA start
+		<-----------completion signal-------
+	CPU accesses dst
+
+	And with dmabuf-sync:
+	User(thread a)          User(thread b)            Kernel
+	---------------------------------------------------------------------
+	send a src to driver---------------------------------->
+	                                                  update DMA register
+        lock the src
+	                        request DMA start(1)---------->
+	CPU acccess to src
+	unlock the src		                          lock src and dst
+							  DMA start
+		<-------------completion signal(2)-------------
+	lock dst	                                  DMA completion
+	CPU access to dst				  unlock src and dst
+	unlock DST
+
+	In above,
+	(1) Try to start DMA operation while CPU is accessing the src buffer.
+	(2) Try CPU access to dst buffer while DMA is accessing the dst buffer.
+
+	With same approach, we could reduce hand shaking overhead between
+	two processes in addition. There may be other cases that we could
+	reduce overhead as well.
+
+
+Basic concept
+-------------
+
+The mechanism of this framework has the following steps,
+    1. Register dmabufs to a sync object - A task gets a new sync object and
+    can add one or more dmabufs that the task wants to access.
+    This registering should be performed when a device context or an event
+    context such as a page flip event is created or before CPU accesses a shared
+    buffer.
+
+	dma_buf_sync_get(a sync object, a dmabuf);
+
+    2. Lock a sync object - A task tries to lock all dmabufs added in its own
+    sync object. Basically, the lock mechanism uses ww-mutexes[2] to avoid dead
+    lock issue and for race condition between CPU and CPU, CPU and DMA, and DMA
+    and DMA. Taking a lock means that others cannot access all locked dmabufs
+    until the task that locked the corresponding dmabufs, unlocks all the locked
+    dmabufs.
+    This locking should be performed before DMA or CPU accesses these dmabufs.
+
+	dma_buf_sync_lock(a sync object);
+
+    3. Unlock a sync object - The task unlocks all dmabufs added in its own sync
+    object. The unlock means that the DMA or CPU accesses to the dmabufs have
+    been completed so that others may access them.
+    This unlocking should be performed after DMA or CPU has completed accesses
+    to the dmabufs.
+
+	dma_buf_sync_unlock(a sync object);
+
+    4. Unregister one or all dmabufs from a sync object - A task unregisters
+    the given dmabufs from the sync object. This means that the task dosen't
+    want to lock the dmabufs.
+    The unregistering should be performed after DMA or CPU has completed
+    accesses to the dmabufs or when dma_buf_sync_lock() is failed.
+
+	dma_buf_sync_put(a sync object, a dmabuf);
+	dma_buf_sync_put_all(a sync object);
+
+    The described steps may be summarized as:
+	get -> lock -> CPU or DMA access to a buffer/s -> unlock -> put
+
+This framework includes the following two features.
+    1. read (shared) and write (exclusive) locks - A task is required to declare
+    the access type when the task tries to register a dmabuf;
+    READ, WRITE, READ DMA, or WRITE DMA.
+
+    The below is example codes,
+	struct dmabuf_sync *sync;
+
+	sync = dmabuf_sync_init(NULL, "test sync");
+
+	dmabuf_sync_get(sync, dmabuf, DMA_BUF_ACCESS_R);
+	...
+
+    2. Mandatory resource releasing - a task cannot hold a lock indefinitely.
+    A task may never try to unlock a buffer after taking a lock to the buffer.
+    In this case, a timer handler to the corresponding sync object is called
+    in five (default) seconds and then the timed-out buffer is unlocked by work
+    queue handler to avoid lockups and to enforce resources of the buffer.
+
+
+Access types
+------------
+
+DMA_BUF_ACCESS_R - CPU will access a buffer for read.
+DMA_BUF_ACCESS_W - CPU will access a buffer for read or write.
+DMA_BUF_ACCESS_DMA_R - DMA will access a buffer for read
+DMA_BUF_ACCESS_DMA_W - DMA will access a buffer for read or write.
+
+
+Generic user interfaces
+-----------------------
+
+The DMA-BUF Sync mechanism includes fcntl system call[3] as interfaces exported
+to user. As you know, user sees a buffer object as a dma-buf file descriptor.
+So fcntl() call with the file descriptor means to lock some buffer region being
+managed by the dma-buf object.
+
+
+API set
+-------
+
+bool is_dmabuf_sync_supported(void)
+	- Check if dmabuf sync is supported or not.
+
+struct dmabuf_sync *dmabuf_sync_init(void *priv, const char *name)
+	- Allocate and initialize a new sync object. The caller can get a new
+	sync object for buffer synchronization. priv is used to set caller's
+	private data and name is the name of sync object.
+
+void dmabuf_sync_fini(struct dmabuf_sync *sync)
+	- Release all resources to the sync object.
+
+int dmabuf_sync_get(struct dmabuf_sync *sync, void *sync_buf,
+			unsigned int type)
+	- Add a dmabuf to a sync object. The caller can group multiple dmabufs
+	by calling this function several times. Internally, this function also
+	takes a reference to a dmabuf.
+
+void dmabuf_sync_put(struct dmabuf_sync *sync, struct dma_buf *dmabuf)
+	- Remove a given dmabuf from a sync object. Internally, this function
+	also release every reference to the given dmabuf.
+
+void dmabuf_sync_put_all(struct dmabuf_sync *sync)
+	- Remove all dmabufs added in a sync object. Internally, this function
+	also release every reference to the dmabufs of the sync object.
+
+int dmabuf_sync_lock(struct dmabuf_sync *sync)
+	- Lock all dmabufs added in a sync object. The caller should call this
+	function prior to CPU or DMA access to the dmabufs so that others can
+	not access the dmabufs. Internally, this function avoids dead lock
+	issue with ww-mutexes.
+
+int dmabuf_sync_single_lock(struct dma_buf *dmabuf)
+	- Lock a dmabuf. The caller should call this
+	function prior to CPU or DMA access to the dmabuf so that others can
+	not access the dmabuf.
+
+int dmabuf_sync_unlock(struct dmabuf_sync *sync)
+	- Unlock all dmabufs added in a sync object. The caller should call
+	this function after CPU or DMA access to the dmabufs is completed so
+	that others can access the dmabufs.
+
+void dmabuf_sync_single_unlock(struct dma_buf *dmabuf)
+	- Unlock a dmabuf. The caller should call this function after CPU or
+	DMA access to the dmabuf is completed so that others can access
+	the dmabuf.
+
+
+Tutorial for device driver
+--------------------------
+
+1. Allocate and Initialize a sync object:
+	struct dmabuf_sync *sync;
+
+	sync = dmabuf_sync_init(NULL, "test sync");
+	...
+
+2. Add a dmabuf to the sync object when setting up dma buffer relevant registers:
+	dmabuf_sync_get(sync, dmabuf, DMA_BUF_ACCESS_READ);
+	...
+
+3. Lock all dmabufs of the sync object before DMA or CPU accesses the dmabufs:
+	dmabuf_sync_lock(sync);
+	...
+
+4. Now CPU or DMA can access all dmabufs locked in step 3.
+
+5. Unlock all dmabufs added in a sync object after DMA or CPU access to these
+   dmabufs is completed:
+	dmabuf_sync_unlock(sync);
+
+   And call the following functions to release all resources,
+	dmabuf_sync_put_all(sync);
+	dmabuf_sync_fini(sync);
+
+
+Tutorial for user application
+-----------------------------
+	struct flock filelock;
+
+1. Lock a dma buf:
+	filelock.l_type = F_WRLCK or F_RDLCK;
+
+	/* lock entire region to the dma buf. */
+	filelock.lwhence = SEEK_CUR;
+	filelock.l_start = 0;
+	filelock.l_len = 0;
+
+	fcntl(dmabuf fd, F_SETLKW or F_SETLK, &filelock);
+	...
+	CPU access to the dma buf
+
+2. Unlock a dma buf:
+	filelock.l_type = F_UNLCK;
+
+	fcntl(dmabuf fd, F_SETLKW or F_SETLK, &filelock);
+
+	close(dmabuf fd) call would also unlock the dma buf. And for more
+	detail, please refer to [3]
+
+
+References:
+[1] http://lwn.net/Articles/470339/
+[2] https://patchwork.kernel.org/patch/2625361/
+[3] http://linux.die.net/man/2/fcntl
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index 5ccf182..54a1d5a 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -212,6 +212,13 @@ config FENCE_TRACE
 	  lockup related problems for dma-buffers shared across multiple
 	  devices.
 
+config DMABUF_SYNC
+	bool "DMABUF Synchronization Framework"
+	depends on DMA_SHARED_BUFFER
+	help
+	  This option enables dmabuf sync framework for buffer synchronization between
+	  DMA and DMA, CPU and DMA, and CPU and CPU.
+
 config CMA
 	bool "Contiguous Memory Allocator"
 	depends on HAVE_DMA_CONTIGUOUS && HAVE_MEMBLOCK
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index 8a55cb9..599f6c90 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -11,6 +11,7 @@ obj-y			+= power/
 obj-$(CONFIG_HAS_DMA)	+= dma-mapping.o
 obj-$(CONFIG_HAVE_GENERIC_DMA_COHERENT) += dma-coherent.o
 obj-$(CONFIG_DMA_SHARED_BUFFER) += dma-buf.o fence.o reservation.o
+obj-$(CONFIG_DMABUF_SYNC) += dmabuf-sync.o
 obj-$(CONFIG_ISA)	+= isa.o
 obj-$(CONFIG_FW_LOADER)	+= firmware_class.o
 obj-$(CONFIG_NUMA)	+= node.o
diff --git a/drivers/base/dmabuf-sync.c b/drivers/base/dmabuf-sync.c
new file mode 100644
index 0000000..437a46e
--- /dev/null
+++ b/drivers/base/dmabuf-sync.c
@@ -0,0 +1,661 @@
+/*
+ * Copyright (C) 2013 Samsung Electronics Co.Ltd
+ * Authors:
+ *	Inki Dae <inki.dae@samsung.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>
+
+#include <linux/dmabuf-sync.h>
+
+#define MAX_SYNC_TIMEOUT	5 /* Second. */
+
+int dmabuf_sync_enabled = 1;
+
+MODULE_PARM_DESC(enabled, "Check if dmabuf sync is supported or not");
+module_param_named(enabled, dmabuf_sync_enabled, int, 0444);
+
+static void dmabuf_sync_timeout_worker(struct work_struct *work)
+{
+	struct dmabuf_sync *sync = container_of(work, struct dmabuf_sync, work);
+	struct dmabuf_sync_object *sobj;
+
+	mutex_lock(&sync->lock);
+
+	list_for_each_entry(sobj, &sync->syncs, head) {
+		if (WARN_ON(!sobj->robj))
+			continue;
+
+		mutex_lock(&sobj->robj->r_lock);
+
+		printk(KERN_WARNING "%s: timeout = 0x%x [type = %d, " \
+					"refcnt = %d, locked = %d]\n",
+					sync->name, (u32)sobj->dmabuf,
+					sobj->access_type,
+					atomic_read(&sobj->robj->shared_cnt),
+					sobj->robj->locked);
+
+		/* unlock only valid sync object. */
+		if (!sobj->robj->locked) {
+			mutex_unlock(&sobj->robj->r_lock);
+			continue;
+		}
+
+		if (sobj->robj->shared &&
+		    atomic_add_unless(&sobj->robj->shared_cnt, -1, 1)) {
+			mutex_unlock(&sobj->robj->r_lock);
+			continue;
+		}
+
+		mutex_unlock(&sobj->robj->r_lock);
+
+		ww_mutex_unlock(&sobj->robj->lock);
+
+		mutex_lock(&sobj->robj->r_lock);
+
+		if (sobj->access_type & DMA_BUF_ACCESS_R)
+			printk(KERN_WARNING "%s: r-unlocked = 0x%x\n",
+					sync->name, (u32)sobj->dmabuf);
+		else
+			printk(KERN_WARNING "%s: w-unlocked = 0x%x\n",
+					sync->name, (u32)sobj->dmabuf);
+
+		mutex_unlock(&sobj->robj->r_lock);
+	}
+
+	sync->status = 0;
+	mutex_unlock(&sync->lock);
+
+	dmabuf_sync_put_all(sync);
+	dmabuf_sync_fini(sync);
+}
+
+static void dmabuf_sync_lock_timeout(unsigned long arg)
+{
+	struct dmabuf_sync *sync = (struct dmabuf_sync *)arg;
+
+	schedule_work(&sync->work);
+}
+
+static int dmabuf_sync_lock_objs(struct dmabuf_sync *sync,
+					struct ww_acquire_ctx *ctx)
+{
+	struct dmabuf_sync_object *contended_sobj = NULL;
+	struct dmabuf_sync_object *res_sobj = NULL;
+	struct dmabuf_sync_object *sobj = NULL;
+	int ret;
+
+	if (ctx)
+		ww_acquire_init(ctx, &reservation_ww_class);
+
+retry:
+	list_for_each_entry(sobj, &sync->syncs, head) {
+		if (WARN_ON(!sobj->robj))
+			continue;
+
+		mutex_lock(&sobj->robj->r_lock);
+
+		/* Don't lock in case of read and read. */
+		if (sobj->robj->accessed_type & DMA_BUF_ACCESS_R &&
+		    sobj->access_type & DMA_BUF_ACCESS_R) {
+			atomic_inc(&sobj->robj->shared_cnt);
+			sobj->robj->shared = true;
+			mutex_unlock(&sobj->robj->r_lock);
+			continue;
+		}
+
+		if (sobj = res_sobj) {
+			res_sobj = NULL;
+			mutex_unlock(&sobj->robj->r_lock);
+			continue;
+		}
+
+		mutex_unlock(&sobj->robj->r_lock);
+
+		ret = ww_mutex_lock(&sobj->robj->lock, ctx);
+		if (ret < 0) {
+			contended_sobj = sobj;
+
+			if (ret = -EDEADLK)
+				printk(KERN_WARNING"%s: deadlock = 0x%x\n",
+					sync->name, (u32)sobj->dmabuf);
+			goto err;
+		}
+
+		mutex_lock(&sobj->robj->r_lock);
+		sobj->robj->locked = true;
+
+		mutex_unlock(&sobj->robj->r_lock);
+	}
+
+	if (ctx)
+		ww_acquire_done(ctx);
+
+	init_timer(&sync->timer);
+
+	sync->timer.data = (unsigned long)sync;
+	sync->timer.function = dmabuf_sync_lock_timeout;
+	sync->timer.expires = jiffies + (HZ * MAX_SYNC_TIMEOUT);
+
+	add_timer(&sync->timer);
+
+	return 0;
+
+err:
+	list_for_each_entry_continue_reverse(sobj, &sync->syncs, head) {
+		mutex_lock(&sobj->robj->r_lock);
+
+		/* Don't need to unlock in case of read and read. */
+		if (atomic_add_unless(&sobj->robj->shared_cnt, -1, 1)) {
+			mutex_unlock(&sobj->robj->r_lock);
+			continue;
+		}
+
+		ww_mutex_unlock(&sobj->robj->lock);
+		sobj->robj->locked = false;
+
+		mutex_unlock(&sobj->robj->r_lock);
+	}
+
+	if (res_sobj) {
+		mutex_lock(&res_sobj->robj->r_lock);
+
+		if (!atomic_add_unless(&res_sobj->robj->shared_cnt, -1, 1)) {
+			ww_mutex_unlock(&res_sobj->robj->lock);
+			res_sobj->robj->locked = false;
+		}
+
+		mutex_unlock(&res_sobj->robj->r_lock);
+	}
+
+	if (ret = -EDEADLK) {
+		ww_mutex_lock_slow(&contended_sobj->robj->lock, ctx);
+		res_sobj = contended_sobj;
+
+		goto retry;
+	}
+
+	if (ctx)
+		ww_acquire_fini(ctx);
+
+	return ret;
+}
+
+static void dmabuf_sync_unlock_objs(struct dmabuf_sync *sync,
+					struct ww_acquire_ctx *ctx)
+{
+	struct dmabuf_sync_object *sobj;
+
+	if (list_empty(&sync->syncs))
+		return;
+
+	mutex_lock(&sync->lock);
+
+	list_for_each_entry(sobj, &sync->syncs, head) {
+		mutex_lock(&sobj->robj->r_lock);
+
+		if (sobj->robj->shared) {
+			if (atomic_add_unless(&sobj->robj->shared_cnt, -1,
+						1)) {
+				mutex_unlock(&sobj->robj->r_lock);
+				continue;
+			}
+
+			mutex_unlock(&sobj->robj->r_lock);
+
+			ww_mutex_unlock(&sobj->robj->lock);
+
+			mutex_lock(&sobj->robj->r_lock);
+			sobj->robj->shared = false;
+			sobj->robj->locked = false;
+		} else {
+			mutex_unlock(&sobj->robj->r_lock);
+
+			ww_mutex_unlock(&sobj->robj->lock);
+
+			mutex_lock(&sobj->robj->r_lock);
+			sobj->robj->locked = false;
+		}
+
+		mutex_unlock(&sobj->robj->r_lock);
+	}
+
+	mutex_unlock(&sync->lock);
+
+	if (ctx)
+		ww_acquire_fini(ctx);
+
+	del_timer(&sync->timer);
+}
+
+/**
+ * is_dmabuf_sync_supported - Check if dmabuf sync is supported or not.
+ */
+bool is_dmabuf_sync_supported(void)
+{
+	return dmabuf_sync_enabled = 1;
+}
+EXPORT_SYMBOL(is_dmabuf_sync_supported);
+
+/**
+ * dmabuf_sync_init - Allocate and initialize a dmabuf sync.
+ *
+ * @priv: A device private data.
+ * @name: A sync object name.
+ *
+ * This function should be called when a device context or an event
+ * context such as a page flip event is created. And the created
+ * dmabuf_sync object should be set to the context.
+ * The caller can get a new sync object for buffer synchronization
+ * through this function.
+ */
+struct dmabuf_sync *dmabuf_sync_init(void *priv, const char *name)
+{
+	struct dmabuf_sync *sync;
+
+	sync = kzalloc(sizeof(*sync), GFP_KERNEL);
+	if (!sync)
+		return ERR_PTR(-ENOMEM);
+
+	strncpy(sync->name, name, ARRAY_SIZE(sync->name) - 1);
+
+	sync->priv = priv;
+	INIT_LIST_HEAD(&sync->syncs);
+	mutex_init(&sync->lock);
+	INIT_WORK(&sync->work, dmabuf_sync_timeout_worker);
+
+	return sync;
+}
+EXPORT_SYMBOL(dmabuf_sync_init);
+
+/**
+ * dmabuf_sync_fini - Release a given dmabuf sync.
+ *
+ * @sync: An object to dmabuf_sync structure.
+ *
+ * This function should be called if some operation is failed after
+ * dmabuf_sync_init call to release relevant resources, and after
+ * dmabuf_sync_unlock function is called.
+ */
+void dmabuf_sync_fini(struct dmabuf_sync *sync)
+{
+	if (WARN_ON(!sync))
+		return;
+
+	kfree(sync);
+}
+EXPORT_SYMBOL(dmabuf_sync_fini);
+
+/*
+ * dmabuf_sync_get_obj - Add a given object to syncs list.
+ *
+ * @sync: An object to dmabuf_sync structure.
+ * @dmabuf: An object to dma_buf structure.
+ * @type: A access type to a dma buf.
+ *	The DMA_BUF_ACCESS_R means that this dmabuf could be accessed by
+ *	others for read access. On the other hand, the DMA_BUF_ACCESS_W
+ *	means that this dmabuf couldn't be accessed by others but would be
+ *	accessed by caller's dma exclusively. And the DMA_BUF_ACCESS_DMA can be
+ *	combined.
+ *
+ * This function creates and initializes a new dmabuf sync object and it adds
+ * the dmabuf sync object to syncs list to track and manage all dmabufs.
+ */
+static int dmabuf_sync_get_obj(struct dmabuf_sync *sync, struct dma_buf *dmabuf,
+					unsigned int type)
+{
+	struct dmabuf_sync_object *sobj;
+
+	if (!dmabuf->resv) {
+		WARN_ON(1);
+		return -EFAULT;
+	}
+
+	if (!IS_VALID_DMA_BUF_ACCESS_TYPE(type))
+		return -EINVAL;
+
+	if ((type & DMA_BUF_ACCESS_RW) = DMA_BUF_ACCESS_RW)
+		type &= ~DMA_BUF_ACCESS_R;
+
+	sobj = kzalloc(sizeof(*sobj), GFP_KERNEL);
+	if (!sobj) {
+		WARN_ON(1);
+		return -ENOMEM;
+	}
+
+	sobj->dmabuf = dmabuf;
+	sobj->robj = dmabuf->resv;
+
+	mutex_lock(&sync->lock);
+	list_add_tail(&sobj->head, &sync->syncs);
+	mutex_unlock(&sync->lock);
+
+	get_dma_buf(dmabuf);
+
+	mutex_lock(&sobj->robj->r_lock);
+	sobj->access_type = type;
+	mutex_unlock(&sobj->robj->r_lock);
+
+	return 0;
+}
+
+/*
+ * dmabuf_sync_put_obj - Release a given sync object.
+ *
+ * @sync: An object to dmabuf_sync structure.
+ *
+ * This function should be called if some operation is failed after
+ * dmabuf_sync_get_obj call to release a given sync object.
+ */
+static void dmabuf_sync_put_obj(struct dmabuf_sync *sync,
+					struct dma_buf *dmabuf)
+{
+	struct dmabuf_sync_object *sobj;
+
+	mutex_lock(&sync->lock);
+
+	list_for_each_entry(sobj, &sync->syncs, head) {
+		if (sobj->dmabuf != dmabuf)
+			continue;
+
+		dma_buf_put(sobj->dmabuf);
+
+		list_del_init(&sobj->head);
+		kfree(sobj);
+		break;
+	}
+
+	if (list_empty(&sync->syncs))
+		sync->status = 0;
+
+	mutex_unlock(&sync->lock);
+}
+
+/*
+ * dmabuf_sync_put_objs - Release all sync objects of dmabuf_sync.
+ *
+ * @sync: An object to dmabuf_sync structure.
+ *
+ * This function should be called if some operation is failed after
+ * dmabuf_sync_get_obj call to release all sync objects.
+ */
+static void dmabuf_sync_put_objs(struct dmabuf_sync *sync)
+{
+	struct dmabuf_sync_object *sobj, *next;
+
+	mutex_lock(&sync->lock);
+
+	list_for_each_entry_safe(sobj, next, &sync->syncs, head) {
+		dma_buf_put(sobj->dmabuf);
+
+		list_del_init(&sobj->head);
+		kfree(sobj);
+	}
+
+	mutex_unlock(&sync->lock);
+
+	sync->status = 0;
+}
+
+/**
+ * dmabuf_sync_lock - lock all dmabufs added to syncs list.
+ *
+ * @sync: An object to dmabuf_sync structure.
+ *
+ * The caller should call this function prior to CPU or DMA access to
+ * the dmabufs so that others can not access the dmabufs.
+ * Internally, this function avoids dead lock issue with ww-mutex.
+ */
+int dmabuf_sync_lock(struct dmabuf_sync *sync)
+{
+	int ret;
+
+	if (!sync) {
+		WARN_ON(1);
+		return -EFAULT;
+	}
+
+	if (list_empty(&sync->syncs))
+		return -EINVAL;
+
+	if (sync->status != DMABUF_SYNC_GOT)
+		return -EINVAL;
+
+	ret = dmabuf_sync_lock_objs(sync, &sync->ctx);
+	if (ret < 0) {
+		WARN_ON(1);
+		return ret;
+	}
+
+	sync->status = DMABUF_SYNC_LOCKED;
+
+	return ret;
+}
+EXPORT_SYMBOL(dmabuf_sync_lock);
+
+/**
+ * dmabuf_sync_unlock - unlock all objects added to syncs list.
+ *
+ * @sync: An object to dmabuf_sync structure.
+ *
+ * The caller should call this function after CPU or DMA access to
+ * the dmabufs is completed so that others can access the dmabufs.
+ */
+int dmabuf_sync_unlock(struct dmabuf_sync *sync)
+{
+	if (!sync) {
+		WARN_ON(1);
+		return -EFAULT;
+	}
+
+	/* If current dmabuf sync object wasn't reserved then just return. */
+	if (sync->status != DMABUF_SYNC_LOCKED)
+		return -EAGAIN;
+
+	dmabuf_sync_unlock_objs(sync, &sync->ctx);
+
+	return 0;
+}
+EXPORT_SYMBOL(dmabuf_sync_unlock);
+
+/**
+ * dmabuf_sync_single_lock - lock a dma buf.
+ *
+ * @dmabuf: A dma buf object that tries to lock.
+ * @type: A access type to a dma buf.
+ *	The DMA_BUF_ACCESS_R means that this dmabuf could be accessed by
+ *	others for read access. On the other hand, the DMA_BUF_ACCESS_W
+ *	means that this dmabuf couldn't be accessed by others but would be
+ *	accessed by caller's dma exclusively. And the DMA_BUF_ACCESS_DMA can
+ *	be combined
+ * @wait: Indicate whether caller is blocked or not.
+ *	true means that caller will be blocked, and false means that this
+ *	function will return -EAGAIN if this caller can't take the lock
+ *	right now.
+ *
+ * The caller should call this function prior to CPU or DMA access to the dmabuf
+ * so that others cannot access the dmabuf.
+ */
+int dmabuf_sync_single_lock(struct dma_buf *dmabuf, unsigned int type,
+				bool wait)
+{
+	struct reservation_object *robj;
+
+	if (!dmabuf->resv) {
+		WARN_ON(1);
+		return -EFAULT;
+	}
+
+	if (!IS_VALID_DMA_BUF_ACCESS_TYPE(type)) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	get_dma_buf(dmabuf);
+	robj = dmabuf->resv;
+
+	mutex_lock(&robj->r_lock);
+
+	/* Don't lock in case of read and read. */
+	if (robj->accessed_type & DMA_BUF_ACCESS_R && type & DMA_BUF_ACCESS_R) {
+		atomic_inc(&robj->shared_cnt);
+		robj->shared = true;
+		mutex_unlock(&robj->r_lock);
+		return 0;
+	}
+
+	/*
+	 * In case of F_SETLK, just return -EAGAIN if this dmabuf has already
+	 * been locked.
+	 */
+	if (!wait && robj->locked) {
+		mutex_unlock(&robj->r_lock);
+		dma_buf_put(dmabuf);
+		return -EAGAIN;
+	}
+
+	mutex_unlock(&robj->r_lock);
+
+	mutex_lock(&robj->lock.base);
+
+	mutex_lock(&robj->r_lock);
+	robj->locked = true;
+	mutex_unlock(&robj->r_lock);
+
+	return 0;
+}
+EXPORT_SYMBOL(dmabuf_sync_single_lock);
+
+/**
+ * dmabuf_sync_single_unlock - unlock a dma buf.
+ *
+ * @dmabuf: A dma buf object that tries to unlock.
+ *
+ * The caller should call this function after CPU or DMA access to
+ * the dmabuf is completed so that others can access the dmabuf.
+ */
+void dmabuf_sync_single_unlock(struct dma_buf *dmabuf)
+{
+	struct reservation_object *robj;
+
+	if (!dmabuf->resv) {
+		WARN_ON(1);
+		return;
+	}
+
+	robj = dmabuf->resv;
+
+	mutex_lock(&robj->r_lock);
+
+	if (robj->shared) {
+		if (atomic_add_unless(&robj->shared_cnt, -1 , 1)) {
+			mutex_unlock(&robj->r_lock);
+			return;
+		}
+
+		robj->shared = false;
+	}
+
+	mutex_unlock(&robj->r_lock);
+
+	mutex_unlock(&robj->lock.base);
+
+	mutex_lock(&robj->r_lock);
+	robj->locked = false;
+	mutex_unlock(&robj->r_lock);
+
+	dma_buf_put(dmabuf);
+
+	return;
+}
+EXPORT_SYMBOL(dmabuf_sync_single_unlock);
+
+/**
+ * dmabuf_sync_get - initialize reservation entry and update
+ *				dmabuf sync.
+ *
+ * @sync: An object to dmabuf_sync structure.
+ * @sync_buf: A dma_buf object pointer that we want to be synchronized
+ *	with others.
+ *
+ * This function should be called after dmabuf_sync_init function is called.
+ * The caller can group multiple dmabufs by calling this function several
+ * times. Internally, this function also takes a reference to a dmabuf.
+ */
+int dmabuf_sync_get(struct dmabuf_sync *sync, void *sync_buf, unsigned int type)
+{
+	int ret;
+
+	if (!sync || !sync_buf) {
+		WARN_ON(1);
+		return -EFAULT;
+	}
+
+	ret = dmabuf_sync_get_obj(sync, sync_buf, type);
+	if (ret < 0) {
+		WARN_ON(1);
+		return ret;
+	}
+
+	sync->status = DMABUF_SYNC_GOT;
+
+	return 0;
+}
+EXPORT_SYMBOL(dmabuf_sync_get);
+
+/**
+ * dmabuf_sync_put - Release a given dmabuf.
+ *
+ * @sync: An object to dmabuf_sync structure.
+ * @dmabuf: An object to dma_buf structure.
+ *
+ * This function should be called if some operation is failed after
+ * dmabuf_sync_get function is called to release the dmabuf, or
+ * dmabuf_sync_unlock function is called.
+ */
+void dmabuf_sync_put(struct dmabuf_sync *sync, struct dma_buf *dmabuf)
+{
+	if (!sync || !dmabuf) {
+		WARN_ON(1);
+		return;
+	}
+
+	if (list_empty(&sync->syncs))
+		return;
+
+	dmabuf_sync_put_obj(sync, dmabuf);
+}
+EXPORT_SYMBOL(dmabuf_sync_put);
+
+/**
+ * dmabuf_sync_put_all - Release all sync objects
+ *
+ * @sync: An object to dmabuf_sync structure.
+ *
+ * This function should be called if some operation is failed after
+ * dmabuf_sync_get function is called to release all sync objects, or
+ * dmabuf_sync_unlock function is called.
+ */
+void dmabuf_sync_put_all(struct dmabuf_sync *sync)
+{
+	if (!sync) {
+		WARN_ON(1);
+		return;
+	}
+
+	if (list_empty(&sync->syncs))
+		return;
+
+	dmabuf_sync_put_objs(sync);
+}
+EXPORT_SYMBOL(dmabuf_sync_put_all);
diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h
index 34cfbac..ae0c87b 100644
--- a/include/linux/dma-buf.h
+++ b/include/linux/dma-buf.h
@@ -150,6 +150,20 @@ struct dma_buf_attachment {
 	void *priv;
 };
 
+#define	DMA_BUF_ACCESS_R	0x1
+#define DMA_BUF_ACCESS_W	0x2
+#define DMA_BUF_ACCESS_DMA	0x4
+#define DMA_BUF_ACCESS_RW	(DMA_BUF_ACCESS_R | DMA_BUF_ACCESS_W)
+#define DMA_BUF_ACCESS_DMA_R	(DMA_BUF_ACCESS_R | DMA_BUF_ACCESS_DMA)
+#define DMA_BUF_ACCESS_DMA_W	(DMA_BUF_ACCESS_W | DMA_BUF_ACCESS_DMA)
+#define DMA_BUF_ACCESS_DMA_RW	(DMA_BUF_ACCESS_DMA_R | DMA_BUF_ACCESS_DMA_W)
+#define IS_VALID_DMA_BUF_ACCESS_TYPE(t)	(t = DMA_BUF_ACCESS_R || \
+					 t = DMA_BUF_ACCESS_W || \
+					 t = DMA_BUF_ACCESS_DMA_R || \
+					 t = DMA_BUF_ACCESS_DMA_W || \
+					 t = DMA_BUF_ACCESS_RW || \
+					 t = DMA_BUF_ACCESS_DMA_RW)
+
 /**
  * get_dma_buf - convenience wrapper for get_file.
  * @dmabuf:	[in]	pointer to dma_buf
diff --git a/include/linux/dmabuf-sync.h b/include/linux/dmabuf-sync.h
new file mode 100644
index 0000000..d5ccfa7
--- /dev/null
+++ b/include/linux/dmabuf-sync.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2013 Samsung Electronics Co.Ltd
+ * Authors:
+ *	Inki Dae <inki.dae@samsung.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/mutex.h>
+#include <linux/sched.h>
+#include <linux/dma-buf.h>
+#include <linux/reservation.h>
+
+enum dmabuf_sync_status {
+	DMABUF_SYNC_GOT		= 1,
+	DMABUF_SYNC_LOCKED,
+};
+
+/*
+ * A structure for dmabuf_sync_object.
+ *
+ * @head: A list head to be added to syncs list.
+ * @robj: A reservation_object object.
+ * @dma_buf: A dma_buf object.
+ * @access_type: Indicate how a current task tries to access
+ *	a given buffer.
+ */
+struct dmabuf_sync_object {
+	struct list_head		head;
+	struct reservation_object	*robj;
+	struct dma_buf			*dmabuf;
+	unsigned int			access_type;
+};
+
+/*
+ * A structure for dmabuf_sync.
+ *
+ * @syncs: A list head to sync object and this is global to system.
+ * @list: A list entry used as committed list node
+ * @lock: A mutex lock to current sync object.
+ * @ctx: A current context for ww mutex.
+ * @work: A work struct to release resources at timeout.
+ * @priv: A private data.
+ * @name: A string to dmabuf sync owner.
+ * @timer: A timer list to avoid lockup and release resources.
+ * @status: Indicate current status (DMABUF_SYNC_GOT or DMABUF_SYNC_LOCKED).
+ */
+struct dmabuf_sync {
+	struct list_head	syncs;
+	struct list_head	list;
+	struct mutex		lock;
+	struct ww_acquire_ctx	ctx;
+	struct work_struct	work;
+	void			*priv;
+	char			name[64];
+	struct timer_list	timer;
+	unsigned int		status;
+};
+
+#ifdef CONFIG_DMABUF_SYNC
+extern bool is_dmabuf_sync_supported(void);
+
+extern struct dmabuf_sync *dmabuf_sync_init(void *priv, const char *name);
+
+extern void dmabuf_sync_fini(struct dmabuf_sync *sync);
+
+extern int dmabuf_sync_lock(struct dmabuf_sync *sync);
+
+extern int dmabuf_sync_unlock(struct dmabuf_sync *sync);
+
+int dmabuf_sync_single_lock(struct dma_buf *dmabuf, unsigned int type,
+				bool wait);
+
+void dmabuf_sync_single_unlock(struct dma_buf *dmabuf);
+
+extern int dmabuf_sync_get(struct dmabuf_sync *sync, void *sync_buf,
+				unsigned int type);
+
+extern void dmabuf_sync_put(struct dmabuf_sync *sync, struct dma_buf *dmabuf);
+
+extern void dmabuf_sync_put_all(struct dmabuf_sync *sync);
+
+#else
+static inline bool is_dmabuf_sync_supported(void) { return false; }
+
+static inline struct dmabuf_sync *dmabuf_sync_init(void *priv,
+					const char *names)
+{
+	return ERR_PTR(0);
+}
+
+static inline void dmabuf_sync_fini(struct dmabuf_sync *sync) { }
+
+static inline int dmabuf_sync_lock(struct dmabuf_sync *sync)
+{
+	return 0;
+}
+
+static inline int dmabuf_sync_unlock(struct dmabuf_sync *sync)
+{
+	return 0;
+}
+
+static inline int dmabuf_sync_single_lock(struct dma_buf *dmabuf,
+						unsigned int type,
+						bool wait)
+{
+	return 0;
+}
+
+static inline void dmabuf_sync_single_unlock(struct dma_buf *dmabuf)
+{
+	return;
+}
+
+static inline int dmabuf_sync_get(struct dmabuf_sync *sync,
+					void *sync_buf,
+					unsigned int type)
+{
+	return 0;
+}
+
+static inline void dmabuf_sync_put(struct dmabuf_sync *sync,
+					struct dma_buf *dmabuf) { }
+
+static inline void dmabuf_sync_put_all(struct dmabuf_sync *sync) { }
+
+#endif
diff --git a/include/linux/reservation.h b/include/linux/reservation.h
index 80050e2..51b7b96 100644
--- a/include/linux/reservation.h
+++ b/include/linux/reservation.h
@@ -50,6 +50,12 @@ struct reservation_object {
 	struct fence *fence_excl;
 	struct fence **fence_shared;
 	u32 fence_shared_count, fence_shared_max;
+
+	struct mutex		r_lock;
+	atomic_t		shared_cnt;
+	unsigned int		accessed_type;
+	unsigned int		shared;
+	unsigned int		locked;
 };
 
 static inline void
@@ -60,6 +66,9 @@ reservation_object_init(struct reservation_object *obj)
 	obj->fence_shared_count = obj->fence_shared_max = 0;
 	obj->fence_shared = NULL;
 	obj->fence_excl = NULL;
+
+	mutex_init(&obj->r_lock);
+	atomic_set(&obj->shared_cnt, 1);
 }
 
 static inline void
-- 
1.7.5.4


^ permalink raw reply related

* [RFC PATCH v4 0/2] Introduce buffer synchronization framework
From: Inki Dae @ 2013-07-10 11:58 UTC (permalink / raw)
  To: dri-devel, linux-fbdev, linux-arm-kernel, linux-media
  Cc: maarten.lankhorst, daniel, robdclark, kyungmin.park, myungjoo.ham,
	yj44.cho, Inki Dae

Hi all,

This patch set introduces a buffer synchronization framework based
on DMA BUF[1] and reservation[2] to use dma-buf resource, and based
on ww-mutexes[3] for lock mechanism.

The purpose of this framework is to provide not only buffer access
control to CPU and CPU, and CPU and DMA, and DMA and DMA but also
easy-to-use interfaces for device drivers and user application.
In addtion, this patch set suggests a way for enhancing performance.

to implement generic user mode interface, we have used fcntl system
call[4]. As you know, user application sees a buffer object as
a dma-buf file descriptor. So fcntl() call with the file descriptor
means to lock some buffer region being managed by the dma-buf object.
For more detail, you can refer to the dma-buf-sync.txt in Documentation/

Moreover, we had tried to find how we could utilize limited hardware
resources more using buffer synchronization mechanism. And finally,
we have realized that it could enhance performance using multi threads
with this buffer synchronization mechanism: DMA and CPU works individually
so CPU could perform other works while DMA is performing some works,
and vise versa.

However, in the conventional way, that is not easy to do so because DMA
operation is depend on CPU operation, and vice versa.

Conventional way:
	User                                     Kernel
	---------------------------------------------------------------------
	CPU writes something to src
	send the src to driver------------------------->
	                                         update DMA register
	request DMA start(1)--------------------------->
						 DMA start
		<---------completion signal(2)----------
	CPU accesses dst

	(1) Request DMA start after the CPU access to src buffer is completed.
	(2) Access dst buffer after DMA access to the dst buffer is completed.

On the other hand, if there is something to control buffer access between CPU
and DMA? The below shows that:

	User(thread a)          User(thread b)            Kernel
	---------------------------------------------------------------------
	send a src to driver---------------------------------->
		                                          update DMA register
        lock the src
	                        request DMA start(1)---------->
	CPU acccess to src
	unlock the src		                          lock src and dst
							  DMA start
		<-------------completion signal(2)-------------
	lock dst	                                  DMA completion
	CPU access to dst				  unlock src and dst
	unlock DST

	(1) Try to start DMA operation while CPU is accessing the src buffer.
	(2) Try CPU access to dst buffer while DMA is accessing the dst buffer.

	This means that CPU or DMA could do more works.

	In the same way, we could reduce hand shaking overhead between
	two processes when those processes need to share a shared buffer.
	There may be other cases that we could reduce overhead as well.


References:
[1] http://lwn.net/Articles/470339/
[2] http://lwn.net/Articles/532616/
[3] https://patchwork.kernel.org/patch/2625361/
[4] http://linux.die.net/man/2/fcntl

Inki Dae (2):
  dmabuf-sync: Introduce buffer synchronization framework
  dma-buf: add lock callback for fcntl system call.

 Documentation/dma-buf-sync.txt |  283 +++++++++++++++++
 drivers/base/Kconfig           |    7 +
 drivers/base/Makefile          |    1 +
 drivers/base/dma-buf.c         |   34 ++
 drivers/base/dmabuf-sync.c     |  661 ++++++++++++++++++++++++++++++++++++++++
 include/linux/dma-buf.h        |   14 +
 include/linux/dmabuf-sync.h    |  132 ++++++++
 include/linux/reservation.h    |    9 +
 8 files changed, 1141 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/dma-buf-sync.txt
 create mode 100644 drivers/base/dmabuf-sync.c
 create mode 100644 include/linux/dmabuf-sync.h

-- 
1.7.5.4


^ permalink raw reply

* Re: [PATCH v6] video: imxfb: Add DT support
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-07-09 13:41 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAOMZO5A-1gacTOSrpZ4HKfwq13mug+uNCS3m4gyFp1WT21_JeQ@mail.gmail.com>

On 09:09 Fri 05 Jul     , Fabio Estevam wrote:
> Hi Jean-Christophe,
> 
> On Tue, May 28, 2013 at 8:09 AM, Jean-Christophe PLAGNIOL-VILLARD
> <plagnioj@jcrosoft.com> wrote:
> > On 12:35 Sun 26 May     , Markus Pargmann wrote:
> >> Add devicetree support for imx framebuffer driver. It uses the generic
> >> display bindings and helper functions.
> >>
> >> Signed-off-by: Markus Pargmann <mpa@pengutronix.de>
> >> Cc: Fabio Estevam <festevam@gmail.com>
> >> Cc: Mark Rutland <mark.rutland@arm.com>
> >> Acked-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
> >
> > Applied thanks
> 
> Still don't see this patch in linux-next. Could you please check?
in the pull to Linus

Best Regards,
J.

^ permalink raw reply

* Re: [PATCH 1/1] OMAPDSS: Add sil9022 driver
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-07-09 13:40 UTC (permalink / raw)
  To: Sathya Prakash M R
  Cc: tomi.valkeinen, archit, linux-omap, linux-fbdev,
	Srinivas Pulukuru
In-Reply-To: <1373360825-25170-1-git-send-email-sathyap@ti.com>

HI,

	Tomi can you take a look at this one your are back

Best Regards,
J.
On 14:37 Tue 09 Jul     , Sathya Prakash M R wrote:
> From: Srinivas Pulukuru <srinivas.pulukuru@ti.com>
> 
> Add driver for SIL9022 DPI-to-HDMI chip.
> 
> Signed-off-by: Srinivas Pulukuru <srinivas.pulukuru@ti.com>
> [sathyap@ti.com: Ported the driver from 2.6.32 based internal
> kernel to v3.10 kernel]
> Signed-off-by: Sathya Prakash M R <sathyap@ti.com>
> ---
> This patch was tested using the legacy OMAP3630 based Zoom3 platform.
> There is no DT support for Zoom , hence board file changes
> made locally were used for validation purpose. 
> Further, DT support will be added for a newer SOC which uses
> the sil9022 HDMI interface chip.
> 
>  drivers/video/omap2/displays/Kconfig         |    8 +
>  drivers/video/omap2/displays/Makefile        |    1 +
>  drivers/video/omap2/displays/panel-sil9022.c | 1274 ++++++++++++++++++++++++++
>  drivers/video/omap2/displays/panel-sil9022.h |  527 +++++++++++
>  4 files changed, 1810 insertions(+)
>  create mode 100644 drivers/video/omap2/displays/panel-sil9022.c
>  create mode 100644 drivers/video/omap2/displays/panel-sil9022.h
> 
> diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig
> index c3853c9..53d8bb7 100644
> --- a/drivers/video/omap2/displays/Kconfig
> +++ b/drivers/video/omap2/displays/Kconfig
> @@ -39,6 +39,14 @@ config PANEL_NEC_NL8048HL11_01B
>  		This NEC NL8048HL11-01B panel is TFT LCD
>  		used in the Zoom2/3/3630 sdp boards.
>  
> +config PANEL_SIL9022
> +	tristate "HDMI interface"
> +        depends on OMAP2_DSS_DPI
> +	depends on I2C
> +	help
> +		Driver for SIL9022 DPI-to-HDMI chip
> +		Driver uses i2c to read EDID information.
> +
>  config PANEL_PICODLP
>  	tristate "TI PICO DLP mini-projector"
>  	depends on OMAP2_DSS_DPI && I2C
> diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile
> index 58a5176..34cfa8e 100644
> --- a/drivers/video/omap2/displays/Makefile
> +++ b/drivers/video/omap2/displays/Makefile
> @@ -3,6 +3,7 @@ obj-$(CONFIG_PANEL_TFP410) += panel-tfp410.o
>  obj-$(CONFIG_PANEL_LGPHILIPS_LB035Q02) += panel-lgphilips-lb035q02.o
>  obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
>  obj-$(CONFIG_PANEL_NEC_NL8048HL11_01B) += panel-nec-nl8048hl11-01b.o
> +obj-$(CONFIG_PANEL_SIL9022) += panel-sil9022.o
>  
>  obj-$(CONFIG_PANEL_TAAL) += panel-taal.o
>  obj-$(CONFIG_PANEL_PICODLP) +=  panel-picodlp.o
> diff --git a/drivers/video/omap2/displays/panel-sil9022.c b/drivers/video/omap2/displays/panel-sil9022.c
> new file mode 100644
> index 0000000..3b5cb17
> --- /dev/null
> +++ b/drivers/video/omap2/displays/panel-sil9022.c
> @@ -0,0 +1,1274 @@
> +/*
> + * drivers/video/omap2/panel-sil9022.c
> + *
> + * Copyright (C) 2009 Texas Instruments
> + *
> + * 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.
> + *
> + * SIL9022 hdmi driver
> + * Owner: kiran Chitriki
> + *
> + */
> +
> +/***********************************/
> +#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 <video/omapdss.h>
> +#include <video/omap-panel-data.h>
> +#include "panel-sil9022.h"
> +
> +u16 current_descriptor_addrs;
> +
> +static struct i2c_client *sil9022_client;
> +
> +static struct omap_video_timings omap_dss_hdmi_timings = {
> +	.x_res          = HDMI_XRES,
> +	.y_res          = HDMI_YRES,
> +	.pixel_clock    = HDMI_PIXCLOCK_MAX,
> +	.hfp            = 110,
> +	.hbp            = 220,
> +	.hsw            = 40,
> +	.vfp            = 5,
> +	.vbp            = 20,
> +	.vsw            = 5,
> +	.vsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
> +	.hsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
> +	.data_pclk_edge	= OMAPDSS_DRIVE_SIG_RISING_EDGE,
> +	.de_level	= OMAPDSS_SIG_ACTIVE_HIGH,
> +	.sync_pclk_edge	= OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
> +};
> +
> +static struct hdmi_reg_data  hdmi_tpi_audio_config_data[] = {
> +	/* Transmitter is brought to Full operation when value of power
> +	 * state register is 0x0 */
> +	{ HDMI_TPI_POWER_STATE_CTRL_REG, TPI_AVI_POWER_STATE_D0		 },
> +	/* TMDS output lines active. bit 3 1:TMDS inactive, 0: TMDS active */
> +	{ HDMI_SYS_CTRL_DATA_REG,  0x01					 },
> +	/*HDCP Enable - Disable */
> +	{ HDMI_TPI_HDCP_CONTROLDATA_REG, 0				 },
> +	/* I2S mode , Mute Enabled , PCM */
> +	{ HDMI_TPI_AUDIO_CONFIG_BYTE2_REG, TPI_AUDIO_INTERFACE_I2S |
> +					    TPI_AUDIO_MUTE_ENABLE |
> +					    TPI_AUDIO_CODING_PCM	 },
> +	/* I2S Input configuration register */
> +	{ HDMI_TPI_I2S_INPUT_CONFIG_REG, TPI_I2S_SCK_EDGE_RISING |
> +					TPI_I2S_MCLK_MULTIPLIER_256 |
> +					TPI_I2S_WS_POLARITY_HIGH |
> +					TPI_I2S_SD_JUSTIFY_LEFT |
> +					TPI_I2S_SD_DIRECTION_MSB_FIRST |
> +					TPI_I2S_FIRST_BIT_SHIFT_YES	 },
> +	/* I2S Enable ad Mapping Register */
> +	{ HDMI_TPI_I2S_ENABLE_MAPPING_REG, TPI_I2S_SD_CHANNEL_ENABLE |
> +					    TPI_I2S_SD_FIFO_0 |
> +					    TPI_I2S_DOWNSAMPLE_DISABLE |
> +					    TPI_I2S_LF_RT_SWAP_NO |
> +					    TPI_I2S_SD_CONFIG_SELECT_SD0 },
> +	{ HDMI_TPI_I2S_ENABLE_MAPPING_REG, TPI_I2S_SD_CHANNEL_DISABLE |
> +					    TPI_I2S_SD_FIFO_1 |
> +					    TPI_I2S_DOWNSAMPLE_DISABLE |
> +					    TPI_I2S_LF_RT_SWAP_NO |
> +					    TPI_I2S_SD_CONFIG_SELECT_SD1 },
> +	{ HDMI_TPI_I2S_ENABLE_MAPPING_REG, TPI_I2S_SD_CHANNEL_DISABLE |
> +					    TPI_I2S_SD_FIFO_2 |
> +					    TPI_I2S_DOWNSAMPLE_DISABLE |
> +					    TPI_I2S_LF_RT_SWAP_NO |
> +					    TPI_I2S_SD_CONFIG_SELECT_SD2 },
> +	{ HDMI_TPI_I2S_ENABLE_MAPPING_REG, TPI_I2S_SD_CHANNEL_DISABLE |
> +					    TPI_I2S_SD_FIFO_3 |
> +					    TPI_I2S_DOWNSAMPLE_DISABLE |
> +					    TPI_I2S_LF_RT_SWAP_NO |
> +					    TPI_I2S_SD_CONFIG_SELECT_SD3 },
> +	{ HDMI_TPI_AUDIO_CONFIG_BYTE3_REG, TPI_AUDIO_SAMPLE_SIZE_16 |
> +					     TPI_AUDIO_FREQ_44KHZ |
> +					     TPI_AUDIO_2_CHANNEL	 },
> +	/* Speaker Configuration  refer CEA Specification*/
> +	{ HDMI_TPI_AUDIO_CONFIG_BYTE4_REG, (0x0 << 0)},
> +	/* Stream Header Settings */
> +	{ HDMI_TPI_I2S_STRM_HDR_0_REG, I2S_CHAN_STATUS_MODE		 },
> +	{ HDMI_TPI_I2S_STRM_HDR_1_REG, I2S_CHAN_STATUS_CAT_CODE	},
> +	{ HDMI_TPI_I2S_STRM_HDR_2_REG, I2S_CHAN_SOURCE_CHANNEL_NUM	 },
> +	{ HDMI_TPI_I2S_STRM_HDR_3_REG, I2S_CHAN_ACCURACY_N_44_SAMPLING_FS },
> +	{ HDMI_TPI_I2S_STRM_HDR_4_REG, I2S_CHAN_ORIGIN_FS_N_SAMP_LENGTH  },
> +	/*     Infoframe data Select  */
> +	{ HDMI_CPI_MISC_IF_SELECT_REG, HDMI_INFOFRAME_TX_ENABLE |
> +					HDMI_INFOFRAME_TX_REPEAT |
> +					HDMI_AUDIO_INFOFRAME		 },
> +};
> +
> +static u8 misc_audio_info_frame_data[] = {
> +	MISC_INFOFRAME_TYPE | MISC_INFOFRAME_ALWAYS_SET,
> +	MISC_INFOFRAME_VERSION,
> +	MISC_INFOFRAME_LENGTH,
> +	0,				/* Checksum byte*/
> +	HDMI_SH_PCM | HDMI_SH_TWO_CHANNELS,
> +	HDMI_SH_44KHz | HDMI_SH_16BIT,	/* 44.1 KHz*/
> +	0x0,   /* Default 0*/
> +	HDMI_SH_SPKR_FLFR,
> +	HDMI_SH_0dB_ATUN | 0x1,		/* 0 dB  Attenuation*/
> +	0x0,
> +	0x0,
> +	0x0,
> +	0x0,
> +	0x0
> +};
> +
> +static u8 avi_info_frame_data[] = {
> +	0x00,
> +	0x00,
> +	0xA8,
> +	0x00,
> +	0x04,
> +	0x00,
> +	0x00,
> +	0x00,
> +	0x00,
> +	0x00,
> +	0x00,
> +	0x00,
> +	0x00,
> +	0x00
> +};
> +
> +void get_horz_vert_timing_info(u8 *edid)
> +{
> +	/*HORIZONTAL FRONT PORCH */
> +	omap_dss_hdmi_timings.hfp = edid[current_descriptor_addrs + 8];
> +	/*HORIZONTAL SYNC WIDTH */
> +	omap_dss_hdmi_timings.hsw = edid[current_descriptor_addrs + 9];
> +	/*HORIZONTAL BACK PORCH */
> +	omap_dss_hdmi_timings.hbp = (((edid[current_descriptor_addrs + 4]
> +					  & 0x0F) << 8) |
> +					edid[current_descriptor_addrs + 3]) -
> +		(omap_dss_hdmi_timings.hfp + omap_dss_hdmi_timings.hsw);
> +	/*VERTICAL FRONT PORCH */
> +	omap_dss_hdmi_timings.vfp = ((edid[current_descriptor_addrs + 10] &
> +				       0xF0) >> 4);
> +	/*VERTICAL SYNC WIDTH */
> +	omap_dss_hdmi_timings.vsw = (edid[current_descriptor_addrs + 10] &
> +				      0x0F);
> +	/*VERTICAL BACK PORCH */
> +	omap_dss_hdmi_timings.vbp = (((edid[current_descriptor_addrs + 7] &
> +					0x0F) << 8) |
> +				      edid[current_descriptor_addrs + 6]) -
> +		(omap_dss_hdmi_timings.vfp + omap_dss_hdmi_timings.vsw);
> +
> +	dev_dbg(&sil9022_client->dev, "<%s>\n"
> +				       "hfp			= %d\n"
> +				       "hsw			= %d\n"
> +				       "hbp			= %d\n"
> +				       "vfp			= %d\n"
> +				       "vsw			= %d\n"
> +				       "vbp			= %d\n",
> +		 __func__,
> +		 omap_dss_hdmi_timings.hfp,
> +		 omap_dss_hdmi_timings.hsw,
> +		 omap_dss_hdmi_timings.hbp,
> +		 omap_dss_hdmi_timings.vfp,
> +		 omap_dss_hdmi_timings.vsw,
> +		 omap_dss_hdmi_timings.vbp
> +		 );
> +
> +}
> +
> +void get_edid_timing_data(u8 *edid, u16 *pixel_clk, u16 *horizontal_res,
> +			  u16 *vertical_res)
> +{
> +	u8 offset, effective_addrs;
> +	u8 count;
> +	u8 i;
> +	u8 flag = false;
> +	/*check for 720P timing in block0 */
> +	for (count = 0; count < EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR; count++) {
> +		current_descriptor_addrs > +			EDID_DESCRIPTOR_BLOCK0_ADDRESS +
> +			count * EDID_TIMING_DESCRIPTOR_SIZE;
> +		*horizontal_res > +			(((edid[EDID_DESCRIPTOR_BLOCK0_ADDRESS + 4 +
> +			   count * EDID_TIMING_DESCRIPTOR_SIZE] & 0xF0) << 4) |
> +			 edid[EDID_DESCRIPTOR_BLOCK0_ADDRESS + 2 +
> +			 count * EDID_TIMING_DESCRIPTOR_SIZE]);
> +		*vertical_res > +			(((edid[EDID_DESCRIPTOR_BLOCK0_ADDRESS + 7 +
> +			   count * EDID_TIMING_DESCRIPTOR_SIZE] & 0xF0) << 4) |
> +			 edid[EDID_DESCRIPTOR_BLOCK0_ADDRESS + 5 +
> +			 count * EDID_TIMING_DESCRIPTOR_SIZE]);
> +
> +		dev_dbg(&sil9022_client->dev,
> +			"<%s> ***Block-0-Timing-descriptor[%d]***\n",
> +			__func__, count);
> +		for (i = current_descriptor_addrs;
> +		      i <
> +		      (current_descriptor_addrs+EDID_TIMING_DESCRIPTOR_SIZE);
> +		      i++)
> +			dev_dbg(&sil9022_client->dev,
> +				"%x =>		%x\n", i, edid[i]);
> +
> +			dev_dbg(&sil9022_client->dev,
> +				 "<%s>\n"
> +				 "E-EDID Buffer Index	= %d\n"
> +				 "horizontal_res	= %d\n"
> +				 "vertical_res		= %d\n",
> +				 __func__,
> +				 current_descriptor_addrs,
> +				 *horizontal_res,
> +				 *vertical_res
> +				 );
> +
> +		if (*horizontal_res = HDMI_XRES &&
> +		    *vertical_res = HDMI_YRES) {
> +			dev_info(&sil9022_client->dev,
> +				"<%s>\nFound EDID Data for %d x %dp\n",
> +				 __func__, *horizontal_res, *vertical_res);
> +			flag = true;
> +			break;
> +			}
> +	}
> +
> +	/*check for the Timing in block1 */
> +	if (flag != true) {
> +		offset = edid[EDID_DESCRIPTOR_BLOCK1_ADDRESS + 2];
> +		if (offset != 0) {
> +			effective_addrs = EDID_DESCRIPTOR_BLOCK1_ADDRESS
> +				+ offset;
> +			/*to determine the number of descriptor blocks */
> +			for (count = 0;
> +			      count < EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR;
> +			      count++) {
> +				current_descriptor_addrs = effective_addrs +
> +					count * EDID_TIMING_DESCRIPTOR_SIZE;
> +				*horizontal_res > +					(((edid[effective_addrs + 4 +
> +					   count*EDID_TIMING_DESCRIPTOR_SIZE] &
> +					   0xF0) << 4) |
> +					 edid[effective_addrs + 2 +
> +					 count * EDID_TIMING_DESCRIPTOR_SIZE]);
> +				*vertical_res > +					(((edid[effective_addrs + 7 +
> +					   count*EDID_TIMING_DESCRIPTOR_SIZE] &
> +					   0xF0) << 4) |
> +					 edid[effective_addrs + 5 +
> +					 count * EDID_TIMING_DESCRIPTOR_SIZE]);
> +
> +				dev_dbg(&sil9022_client->dev,
> +					 "<%s> Block1-Timing-descriptor[%d]\n",
> +					 __func__, count);
> +
> +				for (i = current_descriptor_addrs;
> +				      i < (current_descriptor_addrs+
> +					   EDID_TIMING_DESCRIPTOR_SIZE); i++)
> +					dev_dbg(&sil9022_client->dev,
> +						"%x =>		%x\n",
> +						   i, edid[i]);
> +
> +				dev_dbg(&sil9022_client->dev, "<%s>\n"
> +						"current_descriptor	= %d\n"
> +						"horizontal_res		= %d\n"
> +						"vertical_res		= %d\n",
> +					 __func__, current_descriptor_addrs,
> +					 *horizontal_res, *vertical_res);
> +
> +				if (*horizontal_res = HDMI_XRES &&
> +				    *vertical_res = HDMI_YRES) {
> +					dev_info(&sil9022_client->dev,
> +						 "<%s> Found EDID Data for "
> +						 "%d x %dp\n",
> +						 __func__,
> +						 *horizontal_res,
> +						 *vertical_res
> +						 );
> +					flag = true;
> +					break;
> +					}
> +			}
> +		}
> +	}
> +
> +	if (flag = true) {
> +		*pixel_clk = ((edid[current_descriptor_addrs + 1] << 8) |
> +			     edid[current_descriptor_addrs]);
> +
> +		omap_dss_hdmi_timings.x_res = *horizontal_res;
> +		omap_dss_hdmi_timings.y_res = *vertical_res;
> +		omap_dss_hdmi_timings.pixel_clock = *pixel_clk*10;
> +		dev_dbg(&sil9022_client->dev,
> +			 "EDID TIMING DATA supported by zoom2 FOUND\n"
> +			 "EDID DTD block address	= %d\n"
> +			 "pixel_clk			= %d\n"
> +			 "horizontal res		= %d\n"
> +			 "vertical res			= %d\n",
> +			 current_descriptor_addrs,
> +			 omap_dss_hdmi_timings.pixel_clock,
> +			 omap_dss_hdmi_timings.x_res,
> +			 omap_dss_hdmi_timings.y_res
> +			 );
> +
> +		get_horz_vert_timing_info(edid);
> +	} else {
> +
> +		dev_info(&sil9022_client->dev,
> +			 "<%s>\n"
> +			 "EDID TIMING DATA supported by zoom2 NOT FOUND\n"
> +			 "setting default timing values for 720p\n"
> +			 "pixel_clk		= %d\n"
> +			 "horizontal res	= %d\n"
> +			 "vertical res		= %d\n",
> +			 __func__,
> +			 omap_dss_hdmi_timings.pixel_clock,
> +			 omap_dss_hdmi_timings.x_res,
> +			 omap_dss_hdmi_timings.y_res
> +			 );
> +
> +		*pixel_clk = omap_dss_hdmi_timings.pixel_clock;
> +		*horizontal_res = omap_dss_hdmi_timings.x_res;
> +		*vertical_res = omap_dss_hdmi_timings.y_res;
> +	}
> +
> +
> +}
> +
> +
> +static int
> +sil9022_blockwrite_reg(struct i2c_client *client,
> +				  u8 reg, u16 alength, u8 *val, u16 *out_len)
> +{
> +	int err = 0, i;
> +	struct i2c_msg msg[1];
> +	u8 data[2];
> +
> +	if (!client->adapter) {
> +		dev_err(&client->dev, "<%s> ERROR: No HDMI Device\n", __func__);
> +		return -ENODEV;
> +	}
> +
> +	msg->addr = client->addr;
> +	msg->flags = I2C_M_WR;
> +	msg->len = 2;
> +	msg->buf = data;
> +
> +	/* high byte goes out first */
> +	data[0] = reg >> 8;
> +
> +	for (i = 0; i < alength - 1; i++) {
> +		data[1] = val[i];
> +		err = i2c_transfer(client->adapter, msg, 1);
> +		udelay(50);
> +		dev_dbg(&client->dev, "<%s> i2c Block write at 0x%x, "
> +				      "*val=%d flags=%d byte[%d] err=%d\n",
> +			__func__, data[0], data[1], msg->flags, i, err);
> +		if (err < 0)
> +			break;
> +	}
> +	/* set the number of bytes written*/
> +	*out_len = i;
> +
> +	if (err < 0) {
> +		dev_err(&client->dev, "<%s> ERROR:  i2c Block Write at 0x%x, "
> +				      "*val=%d flags=%d bytes written=%d "
> +				      "err=%d\n",
> +			__func__, data[0], data[1], msg->flags, i, err);
> +		return err;
> +	}
> +	return 0;
> +}
> +
> +static int
> +sil9022_blockread_reg(struct i2c_client *client,
> +		      u16 data_length, u16 alength,
> +		      u8 reg, u8 *val, u16 *out_len)
> +{
> +	int err = 0, i;
> +	struct i2c_msg msg[1];
> +	u8 data[2];
> +
> +	if (!client->adapter) {
> +		dev_err(&client->dev, "<%s> ERROR: No HDMI Device\n", __func__);
> +		return -ENODEV;
> +	}
> +
> +	msg->addr = client->addr;
> +	msg->flags = I2C_M_WR;
> +	msg->len = 1;
> +	msg->buf = data;
> +
> +	/* High byte goes out first */
> +	data[0] = reg;
> +	err = i2c_transfer(client->adapter, msg, 1);
> +	dev_dbg(&client->dev, "<%s> i2c Block Read1 at 0x%x, "
> +			       "*val=%d flags=%d err=%d\n",
> +		 __func__, data[0], data[1], msg->flags, err);
> +
> +	for (i = 0; i < alength; i++) {
> +		if (err >= 0) {
> +			mdelay(3);
> +			msg->flags = I2C_M_RD;
> +			msg->len = data_length;
> +			err = i2c_transfer(client->adapter, msg, 1);
> +		} else
> +			break;
> +		if (err >= 0) {
> +			val[i] = 0;
> +			/* High byte comes first */
> +			if (data_length = 1)
> +				val[i] = data[0];
> +			else if (data_length = 2)
> +				val[i] = data[1] + (data[0] << 8);
> +			dev_dbg(&client->dev, "<%s> i2c Block Read2 at 0x%x, "
> +					       "*val=%d flags=%d byte=%d "
> +					       "err=%d\n",
> +				 __func__, reg, val[i], msg->flags, i, err);
> +		} else
> +			break;
> +	}
> +	*out_len = i;
> +	dev_dbg(&client->dev, "<%s> i2c Block Read at 0x%x, bytes read = %d\n",
> +		__func__, client->addr, *out_len);
> +
> +	if (err < 0) {
> +		dev_err(&client->dev, "<%s> ERROR:  i2c Read at 0x%x, "
> +				      "*val=%d flags=%d bytes read=%d err=%d\n",
> +			__func__, reg, *val, msg->flags, i, err);
> +		return err;
> +	}
> +	return 0;
> +}
> +
> +
> +/* Write a value to a register in sil9022 device.
> + * @client: i2c driver client structure.
> + * @reg: Address of the register to read value from.
> + * @val: Value to be written to a specific register.
> + * Returns zero if successful, or non-zero otherwise.
> + */
> +static int
> +sil9022_write_reg(struct i2c_client *client, u8 reg, u8 val)
> +{
> +	int err = 0;
> +	struct i2c_msg msg[1];
> +	u8 data[2];
> +	int retries = 0;
> +
> +	if (!client->adapter) {
> +		dev_err(&client->dev, "<%s> ERROR: No HDMI Device\n", __func__);
> +		return -ENODEV;
> +	}
> +
> +retry:
> +	msg->addr = client->addr;
> +	msg->flags = I2C_M_WR;
> +	msg->len = 2;
> +	msg->buf = data;
> +
> +	data[0] = reg;
> +	data[1] = val;
> +
> +	err = i2c_transfer(client->adapter, msg, 1);
> +	dev_dbg(&client->dev, "<%s> i2c write at=%x "
> +			       "val=%x flags=%d err=%d\n",
> +		__func__, data[0], data[1], msg->flags, err);
> +	udelay(50);
> +
> +	if (err >= 0)
> +		return 0;
> +
> +	dev_err(&client->dev, "<%s> ERROR: i2c write at=%x "
> +			       "val=%x flags=%d err=%d\n",
> +		__func__, data[0], data[1], msg->flags, err);
> +	if (retries <= 5) {
> +		dev_info(&client->dev, "Retrying I2C... %d\n", retries);
> +		retries++;
> +		set_current_state(TASK_UNINTERRUPTIBLE);
> +		schedule_timeout(msecs_to_jiffies(20));
> +		goto retry;
> +	}
> +	return err;
> +}
> +
> +/*
> + * Read a value from a register in sil9022 device.
> + * The value is returned in 'val'.
> + * Returns zero if successful, or non-zero otherwise.
> + */
> +static int
> +sil9022_read_reg(struct i2c_client *client, u16 data_length, u8 reg, u8 *val)
> +{
> +	int err = 0;
> +	struct i2c_msg msg[1];
> +	u8 data[2];
> +
> +	if (!client->adapter) {
> +		dev_err(&client->dev, "<%s> ERROR: No HDMI Device\n", __func__);
> +		return -ENODEV;
> +	}
> +
> +	msg->addr = client->addr;
> +	msg->flags = I2C_M_WR;
> +	msg->len = 1;
> +	msg->buf = data;
> +
> +	data[0] = reg;
> +	err = i2c_transfer(client->adapter, msg, 1);
> +	dev_dbg(&client->dev, "<%s> i2c Read1 reg=%x val=%d "
> +			       "flags=%d err=%d\n",
> +		__func__, reg, data[1], msg->flags, err);
> +
> +	if (err >= 0) {
> +		mdelay(3);
> +		msg->flags = I2C_M_RD;
> +		msg->len = data_length;
> +		err = i2c_transfer(client->adapter, msg, 1);
> +	}
> +
> +	if (err >= 0) {
> +		*val = 0;
> +		if (data_length = 1)
> +			*val = data[0];
> +		else if (data_length = 2)
> +			*val = data[1] + (data[0] << 8);
> +		dev_dbg(&client->dev, "<%s> i2c Read2 at 0x%x, *val=%d "
> +				       "flags=%d err=%d\n",
> +			 __func__, reg, *val, msg->flags, err);
> +		return 0;
> +	}
> +
> +	dev_err(&client->dev, "<%s> ERROR: i2c Read at 0x%x, "
> +			      "*val=%d flags=%d err=%d\n",
> +		__func__, reg, *val, msg->flags, err);
> +	return err;
> +}
> +
> +static int
> +sil9022_read_edid(struct i2c_client *client, u16 len,
> +	       char *p_buffer, u16 *out_len)
> +{
> +	int err =  0;
> +	u8 val = 0;
> +	int retries = 0;
> +	int i = 0;
> +	int k = 0;
> +
> +	len = (len < HDMI_EDID_MAX_LENGTH) ? len : HDMI_EDID_MAX_LENGTH;
> +
> +	/* Request DDC bus access to read EDID info from HDTV */
> +	dev_info(&client->dev, "<%s> Reading HDMI EDID\n", __func__);
> +
> +	/* Bring transmitter to low-Power state */
> +	val = TPI_AVI_POWER_STATE_D2;
> +	err = sil9022_write_reg(client, HDMI_TPI_DEVICE_POWER_STATE_DATA, val);
> +	if (err < 0) {
> +		dev_err(&client->dev,
> +			"<%s> ERROR: Failed during bring power state - low.\n",
> +			 __func__);
> +		return err;
> +	}
> +
> +	/* Disable TMDS clock */
> +	val = 0x11;
> +	err = sil9022_write_reg(client, HDMI_SYS_CTRL_DATA_REG, val);
> +	if (err < 0) {
> +		dev_err(&client->dev,
> +			"<%s> ERROR: Failed during bring power state - low.\n",
> +			 __func__);
> +		return err;
> +	}
> +
> +	val = 0;
> +	/* Read TPI system control register*/
> +	err = sil9022_read_reg(client, 1, HDMI_SYS_CTRL_DATA_REG, &val);
> +	if (err < 0) {
> +		dev_err(&client->dev,
> +			"<%s> ERROR: Reading DDC BUS REQUEST\n", __func__);
> +		return err;
> +	}
> +
> +	/* The host writes 0x1A[2]=1 to request the
> +	 * DDC(Display Data Channel) bus
> +	 */
> +	val |= TPI_SYS_CTRL_DDC_BUS_REQUEST;
> +	err = sil9022_write_reg(client, HDMI_SYS_CTRL_DATA_REG, val);
> +	if (err < 0) {
> +		dev_err(&client->dev,
> +			"<%s> ERROR: Writing DDC BUS REQUEST\n", __func__);
> +		return err;
> +	}
> +
> +	 /*  Poll for bus DDC Bus control to be granted */
> +	dev_info(&client->dev, "<%s> Poll for DDC bus access\n", __func__);
> +	val = 0;
> +	do {
> +		err = sil9022_read_reg(client, 1, HDMI_SYS_CTRL_DATA_REG, &val);
> +		if (retries++ > 100)
> +			return err;
> +
> +	} while ((val & TPI_SYS_CTRL_DDC_BUS_GRANTED) = 0);
> +
> +	/*  Close the switch to the DDC */
> +	val |= TPI_SYS_CTRL_DDC_BUS_REQUEST | TPI_SYS_CTRL_DDC_BUS_GRANTED;
> +	err = sil9022_write_reg(client, HDMI_SYS_CTRL_DATA_REG, val);
> +	if (err < 0) {
> +		dev_err(&client->dev,
> +			"<%s> ERROR: Close switch to DDC BUS REQUEST\n",
> +			__func__);
> +		return err;
> +	}
> +
> +	memset(p_buffer, 0, len);
> +	/* change I2C SetSlaveAddress to HDMI_I2C_MONITOR_ADDRESS */
> +	/*  Read the EDID structure from the monitor I2C address  */
> +	client->addr = HDMI_I2C_MONITOR_ADDRESS;
> +	err = sil9022_blockread_reg(client, 1, len,
> +				    0x00, p_buffer, out_len);
> +	if (err < 0 || *out_len <= 0) {
> +		dev_err(&client->dev,
> +			"<%s> ERROR: Reading EDID from "
> +			"HDMI_I2C_MONITOR_ADDRESS\n", __func__);
> +		return err;
> +	}
> +
> +	for (i = 0; i < *out_len; i++) {
> +		if ((i / 18) < 3) {
> +			dev_dbg(&client->dev, "byte->%02x	%x\n",
> +				i, p_buffer[i]);
> +			continue;
> +		}
> +		if ((i/18 >= 3 && i/18 <= 6) && (i%18 = 0))
> +			dev_dbg(&client->dev, "\n DTD Block %d\n", k++);
> +
> +		if ((i/18 = 7) && (i%18 = 0))
> +			dev_dbg(&client->dev, "\n");
> +
> +		dev_dbg(&client->dev, "byte->%02x	%x\n", i, p_buffer[i]);
> +	}
> +
> +	/* Release DDC bus access */
> +	client->addr = SI9022_I2CSLAVEADDRESS;
> +	val &= ~(TPI_SYS_CTRL_DDC_BUS_REQUEST | TPI_SYS_CTRL_DDC_BUS_GRANTED);
> +	err = sil9022_write_reg(client, HDMI_SYS_CTRL_DATA_REG, val);
> +
> +	if (err < 0) {
> +		dev_err(&client->dev,
> +			"<%s> ERROR: Releasing DDC  Bus Access\n",
> +			__func__);
> +		return err;
> +		}
> +
> +	/*  Success */
> +	return 0;
> +}
> +
> +static int
> +sil9022_enable_audio(struct i2c_client *client)
> +{
> +	int err = 0;
> +	u8  val = 0;
> +	u8  crc = 0;
> +	u32 count = 0;
> +	int index = 0;
> +
> +	for (index = 0;
> +	      index < sizeof(hdmi_tpi_audio_config_data) /
> +	      sizeof(struct hdmi_reg_data);
> +	      index++) {
> +		err = sil9022_write_reg(
> +			client,
> +			hdmi_tpi_audio_config_data[index].reg_offset,
> +			hdmi_tpi_audio_config_data[index].value);
> +		if (err != 0) {
> +			dev_err(&client->dev,
> +				"<%s> ERROR: Writing "
> +				"tpi_audio_config_data[%d]={ %d, %d }\n",
> +				__func__, index,
> +				hdmi_tpi_audio_config_data[index].reg_offset,
> +				hdmi_tpi_audio_config_data[index].value);
> +			return err;
> +			}
> +		}
> +
> +	/* Fill the checksum byte for Infoframe data*/
> +	count = 0;
> +	while (count < MISC_INFOFRAME_SIZE_MEMORY) {
> +		crc += misc_audio_info_frame_data[count];
> +		count++;
> +	}
> +	crc = 0x100 - crc;
> +
> +	/* Fill CRC Byte*/
> +	misc_audio_info_frame_data[0x3] = crc;
> +
> +	for (count = 0; count < MISC_INFOFRAME_SIZE_MEMORY; count++) {
> +		err = sil9022_write_reg(client,
> +					(HDMI_CPI_MISC_IF_OFFSET + count),
> +					misc_audio_info_frame_data[count]);
> +		if (err < 0) {
> +			dev_err(&client->dev,
> +				"<%s> ERROR: writing audio info frame"
> +				" CRC data: %d\n", __func__, count);
> +			return err;
> +		}
> +	}
> +
> +	/* Decode Level 0 Packets */
> +	val = 0x2;
> +	sil9022_write_reg(client, 0xBC, val);
> +	if (err < 0) {
> +		dev_err(&client->dev,
> +			"<%s> ERROR: writing level 0 packets to 0xBC\n",
> +			__func__);
> +		return err;
> +	}
> +
> +	val = 0x24;
> +	err = sil9022_write_reg(client, 0xBD, val);
> +	if (err < 0) {
> +		dev_err(&client->dev,
> +			"<%s> ERROR: writing level 0 packets to 0xBD\n",
> +			__func__);
> +		return err;
> +	}
> +
> +	val = 0x2;
> +	err = sil9022_write_reg(client, 0xBE, val);
> +	if (err < 0) {
> +		dev_err(&client->dev,
> +			"<%s> ERROR: writing level 0 packets to 0xBE\n",
> +			__func__);
> +		return err;
> +	}
> +
> +	/* Disable Mute */
> +	val = TPI_AUDIO_INTERFACE_I2S |
> +		  TPI_AUDIO_MUTE_DISABLE |
> +		  TPI_AUDIO_CODING_PCM;
> +	err = sil9022_write_reg(client, HDMI_TPI_AUDIO_CONFIG_BYTE2_REG, val);
> +	if (err < 0) {
> +		dev_err(&client->dev,
> +			"<%s> ERROR: Disabling mute\n",
> +			__func__);
> +		return err;
> +	}
> +
> +	dev_info(&client->dev, "<%s> hdmi audio enabled\n",
> +		__func__);
> +	return 0;
> +
> +}
> +
> +static int
> +sil9022_disable_audio(struct i2c_client *client)
> +{
> +	u8 val = 0;
> +	int err = 0;
> +	/* Disable Audio */
> +	val = TPI_AUDIO_INTERFACE_DISABLE;
> +	err = sil9022_write_reg(client, HDMI_TPI_AUDIO_CONFIG_BYTE2_REG, val);
> +	if (err < 0)
> +		dev_err(&client->dev,
> +			"<%s> ERROR: Disisable audio interface", __func__);
> +
> +	dev_info(&client->dev, "<%s> hdmi audio disabled\n", __func__);
> +	return err;
> +}
> +
> +static int
> +sil9022_enable(struct omap_dss_device *dssdev)
> +{
> +	int		err;
> +	u8		val, vals[14];
> +	int		i;
> +	u16		out_len = 0;
> +	u8		edid[HDMI_EDID_MAX_LENGTH];
> +	u16		horizontal_res;
> +	u16		vertical_res;
> +	u16		pixel_clk;
> +
> +	memset(edid, 0, HDMI_EDID_MAX_LENGTH);
> +	memset(vals, 0, 14);
> +
> +	err = sil9022_read_edid(sil9022_client, HDMI_EDID_MAX_LENGTH,
> +			     edid, &out_len);
> +	if (err < 0 || out_len = 0) {
> +		dev_err(&sil9022_client->dev,
> +			"<%s> Unable to read EDID for monitor\n", __func__);
> +		return err;
> +	}
> +
> +	get_edid_timing_data(edid,
> +			     &pixel_clk,
> +			     &horizontal_res,
> +			     &vertical_res
> +			     );
> +
> +	/*  Fill the TPI Video Mode Data structure */
> +	vals[0] = (pixel_clk & 0xFF);                  /* Pixel clock */
> +	vals[1] = ((pixel_clk & 0xFF00) >> 8);
> +	vals[2] = VERTICAL_FREQ;                    /* Vertical freq */
> +	vals[3] = 0x00;
> +	vals[4] = (horizontal_res & 0xFF);         /* Horizontal pixels*/
> +	vals[5] = ((horizontal_res & 0xFF00) >> 8);
> +	vals[6] = (vertical_res & 0xFF);           /* Vertical pixels */
> +	vals[7] = ((vertical_res & 0xFF00) >> 8);
> +
> +	dev_info(&sil9022_client->dev, "<%s>\nHDMI Monitor E-EDID Timing Data\n"
> +				       "horizontal_res	= %d\n"
> +				       "vertical_res	= %d\n"
> +				       "pixel_clk	= %d\n"
> +				       "hfp		= %d\n"
> +				       "hsw		= %d\n"
> +				       "hbp		= %d\n"
> +				       "vfp		= %d\n"
> +				       "vsw		= %d\n"
> +				       "vbp		= %d\n",
> +		 __func__,
> +		 omap_dss_hdmi_timings.x_res,
> +		 omap_dss_hdmi_timings.y_res,
> +		 omap_dss_hdmi_timings.pixel_clock,
> +		 omap_dss_hdmi_timings.hfp,
> +		 omap_dss_hdmi_timings.hsw,
> +		 omap_dss_hdmi_timings.hbp,
> +		 omap_dss_hdmi_timings.vfp,
> +		 omap_dss_hdmi_timings.vsw,
> +		 omap_dss_hdmi_timings.vbp
> +		 );
> +
> +	dssdev->panel.timings = omap_dss_hdmi_timings;
> +	/*  Write out the TPI Video Mode Data */
> +	out_len = 0;
> +	err = sil9022_blockwrite_reg(sil9022_client,
> +				     HDMI_TPI_VIDEO_DATA_BASE_REG,
> +				     8, vals, &out_len);
> +	if (err < 0) {
> +		dev_err(&sil9022_client->dev,
> +			"<%s> ERROR: writing TPI video mode data\n", __func__);
> +		return err;
> +	}
> +
> +	/* Write out the TPI Pixel Repetition Data (24 bit wide bus,
> +	falling edge, no pixel replication) */
> +	val = TPI_AVI_PIXEL_REP_BUS_24BIT |
> +		TPI_AVI_PIXEL_REP_FALLING_EDGE |
> +		TPI_AVI_PIXEL_REP_NONE;
> +	err = sil9022_write_reg(sil9022_client,
> +				HDMI_TPI_PIXEL_REPETITION_REG,
> +				val);
> +	if (err < 0) {
> +		dev_err(&sil9022_client->dev,
> +			"<%s> ERROR: writing TPI pixel repetition data\n",
> +			__func__);
> +		return err;
> +	}
> +
> +	 /*  Write out the TPI AVI Input Format */
> +	val = TPI_AVI_INPUT_BITMODE_8BIT |
> +		TPI_AVI_INPUT_RANGE_AUTO |
> +		TPI_AVI_INPUT_COLORSPACE_RGB;
> +	err = sil9022_write_reg(sil9022_client,
> +				HDMI_TPI_AVI_IN_FORMAT_REG,
> +				val);
> +	if (err < 0) {
> +		dev_err(&sil9022_client->dev,
> +			"<%s> ERROR: writing TPI AVI Input format\n", __func__);
> +		return err;
> +	}
> +
> +	/*  Write out the TPI AVI Output Format */
> +	val = TPI_AVI_OUTPUT_CONV_BT709 |
> +		TPI_AVI_OUTPUT_RANGE_AUTO |
> +		TPI_AVI_OUTPUT_COLORSPACE_RGBHDMI;
> +	err = sil9022_write_reg(sil9022_client,
> +				HDMI_TPI_AVI_OUT_FORMAT_REG, val);
> +	if (err < 0) {
> +		dev_err(&sil9022_client->dev,
> +			"<%s> ERROR: writing TPI AVI output format\n",
> +			__func__);
> +		return err;
> +	}
> +
> +	/* Write out the TPI System Control Data to power down */
> +	val = TPI_SYS_CTRL_POWER_DOWN;
> +	err = sil9022_write_reg(sil9022_client, HDMI_SYS_CTRL_DATA_REG, val);
> +	if (err < 0) {
> +		dev_err(&sil9022_client->dev,
> +			"<%s> ERROR: writing TPI power down control data\n",
> +			__func__);
> +		return err;
> +	}
> +
> +	/* Write out the TPI AVI InfoFrame Data (all defaults) */
> +	/* Compute CRC*/
> +	val = 0x82 + 0x02 + 13;
> +
> +	for (i = 0; i < sizeof(avi_info_frame_data); i++)
> +		val += avi_info_frame_data[i];
> +
> +	avi_info_frame_data[0] = 0x100 - val;
> +
> +	out_len = 0;
> +	err = sil9022_blockwrite_reg(sil9022_client,
> +				     HDMI_TPI_AVI_DBYTE_BASE_REG,
> +				     sizeof(avi_info_frame_data),
> +				     avi_info_frame_data, &out_len);
> +	if (err < 0) {
> +		dev_err(&sil9022_client->dev,
> +			"<%s> ERROR: writing TPI AVI infoframe data\n",
> +			__func__);
> +		return err;
> +	}
> +
> +	/*  Audio Configuration  */
> +	err = sil9022_enable_audio(sil9022_client);
> +	if (err < 0) {
> +		dev_err(&sil9022_client->dev,
> +			"<%s> ERROR: Unable set audio configuration\n",
> +			__func__);
> +		return err;
> +	}
> +
> +	/*  Write out the TPI Device Power State (D0) */
> +	val = TPI_AVI_POWER_STATE_D0;
> +	err = sil9022_write_reg(sil9022_client,
> +				HDMI_TPI_POWER_STATE_CTRL_REG, val);
> +	if (err < 0) {
> +		dev_err(&sil9022_client->dev,
> +			"<%s> ERROR: Setting device power state to D0\n",
> +			__func__);
> +		return err;
> +	}
> +
> +	/* Write out the TPI System Control Data to power up and
> +	 * select output mode
> +	 */
> +	val = TPI_SYS_CTRL_POWER_ACTIVE | TPI_SYS_CTRL_OUTPUT_MODE_HDMI;
> +	err = sil9022_write_reg(sil9022_client, HDMI_SYS_CTRL_DATA_REG, val);
> +	if (err < 0) {
> +		dev_err(&sil9022_client->dev,
> +			"<%s> ERROR: Writing system control data\n", __func__);
> +		return err;
> +	}
> +
> +	/*  Read back TPI System Control Data to latch settings */
> +	msleep(20);
> +	err = sil9022_read_reg(sil9022_client, 1, HDMI_SYS_CTRL_DATA_REG, &val);
> +	if (err < 0) {
> +		dev_err(&sil9022_client->dev,
> +			"<%s> ERROR: Writing system control data\n",
> +			__func__);
> +		return err;
> +	}
> +
> +	/* HDCP Enable - Disable */
> +	val = 0;
> +	err = sil9022_write_reg(sil9022_client,
> +				HDMI_TPI_HDCP_CONTROLDATA_REG, val);
> +	if (err < 0) {
> +		dev_err(&sil9022_client->dev,
> +			"<%s> ERROR: Enable (1) / Disable (0) => HDCP: %d\n",
> +			__func__, val);
> +		return err;
> +	}
> +
> +	dev_info(&sil9022_client->dev, "<%s> hdmi enabled\n", __func__);
> +	return 0;
> +
> +}
> +
> +static int
> +sil9022_disable(void)
> +{
> +	u8 val = 0;
> +	int err = 0;
> +
> +	err = sil9022_disable_audio(sil9022_client);
> +	if (err < 0) {
> +		dev_err(&sil9022_client->dev,
> +			"<%s> ERROR: failed to disable audio\n", __func__);
> +		return err;
> +	}
> +
> +	/*  Write out the TPI System Control Data to power down  */
> +	val = TPI_SYS_CTRL_POWER_DOWN;
> +	err = sil9022_write_reg(sil9022_client, HDMI_SYS_CTRL_DATA_REG, val);
> +	if (err < 0) {
> +		dev_err(&sil9022_client->dev,
> +			"<%s> ERROR: writing control data - power down\n",
> +			__func__);
> +		return err;
> +	}
> +
> +	/*  Write out the TPI Device Power State (D2) */
> +	val = TPI_AVI_POWER_STATE_D2;
> +	err = sil9022_write_reg(sil9022_client,
> +			  HDMI_TPI_DEVICE_POWER_STATE_DATA, val);
> +	if (err < 0) {
> +		dev_err(&sil9022_client->dev,
> +			"<%s> ERROR: Setting device power state to D2\n",
> +			__func__);
> +		return err;
> +	}
> +
> +	/*  Read back TPI System Control Data to latch settings */
> +	mdelay(10);
> +	err = sil9022_read_reg(sil9022_client, 1, HDMI_SYS_CTRL_DATA_REG, &val);
> +	if (err < 0) {
> +		dev_err(&sil9022_client->dev,
> +			"<%s> ERROR:  Reading System control data "
> +			"- latch settings\n", __func__);
> +		return err;
> +	}
> +
> +	dev_info(&sil9022_client->dev, "<%s> hdmi disabled\n", __func__);
> +	return 0;
> +
> +}
> +
> +static int sil9022_set_reg_read_ctrl(struct i2c_client *client)
> +{
> +	int err = 0;
> +	u8 ver;
> +
> +	/* probe for sil9022 chip version*/
> +	err = sil9022_write_reg(client, SI9022_REG_TPI_RQB, 0x00);
> +	if (err < 0) {
> +		dev_err(&client->dev,
> +			"<%s> ERROR: Writing HDMI configuration to "
> +			"reg - SI9022_REG_TPI_RQB\n", __func__);
> +		err = -ENODEV;
> +		goto ERROR1;
> +	}
> +
> +	err = sil9022_read_reg(client, 1, SI9022_REG_CHIPID0, &ver);
> +	if (err < 0) {
> +		dev_err(&client->dev,
> +			"<%s> ERROR: Reading HDMI version Id\n", __func__);
> +		err = -ENODEV;
> +		goto ERROR1;
> +	} else if (ver != SI9022_CHIPID_902x) {
> +		dev_err(&client->dev,
> +			"<%s> Not a valid verId: 0x%x\n", __func__, ver);
> +		err = -ENODEV;
> +		goto ERROR1;
> +	} else
> +		dev_info(&client->dev,
> +			 "<%s> sil9022 HDMI Chip version = %x\n",
> +			 __func__, ver);
> +
> +	return 0;
> +ERROR1:
> +	return err;
> +}
> +
> +static inline struct sil9022_platform_data
> +*get_panel_data(const struct omap_dss_device *dssdev)
> +{
> +	return (struct sil9022_platform_data *) dssdev->data;
> +}
> +
> +
> +static int sil9022_panel_probe(struct omap_dss_device *dssdev)
> +{
> +	struct sil9022_platform_data *sidata = get_panel_data(dssdev);
> +	int r;
> +	if (!sidata)
> +		return -EINVAL;
> +
> +	dssdev->panel.timings = omap_dss_hdmi_timings;
> +
> +	if (gpio_is_valid(sidata->res_gpio)) {
> +		r = devm_gpio_request_one(&dssdev->dev, sidata->res_gpio,
> +				GPIOF_OUT_INIT_HIGH, "HDMI");
> +		if (r)
> +			return r;
> +	}
> +
> +	return 0;
> +}
> +
> +static void sil9022_panel_remove(struct omap_dss_device *dssdev)
> +{
> +	omap_dss_unregister_driver(dssdev->driver);
> +}
> +
> +
> +static int sil9022_panel_power_on(struct omap_dss_device *dssdev)
> +{
> +	int r = 0;
> +	struct sil9022_platform_data *sidata = get_panel_data(dssdev);
> +
> +	if (dssdev->state = OMAP_DSS_DISPLAY_ACTIVE)
> +		return 0;
> +
> +	if (gpio_is_valid(sidata->res_gpio))
> +		gpio_set_value_cansleep(sidata->res_gpio, 1);
> +
> +	omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
> +	omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
> +	r = omapdss_dpi_display_enable(dssdev);
> +	return r;
> +
> +}
> +
> +static void sil9022_panel_power_off(struct omap_dss_device *dssdev)
> +{
> +	struct sil9022_platform_data *sidata = get_panel_data(dssdev);
> +
> +	if (gpio_is_valid(sidata->res_gpio))
> +		gpio_set_value_cansleep(sidata->res_gpio, 0);
> +	return;
> +
> +}
> +
> +static int sil9022_panel_enable(struct omap_dss_device *dssdev)
> +{
> +	int r = 0;
> +
> +	r = sil9022_panel_power_on(dssdev);
> +	if (r)
> +			goto ERROR0;
> +	r = sil9022_set_reg_read_ctrl(sil9022_client);
> +	if (r)
> +		goto ERROR0;
> +
> +	r = sil9022_enable(dssdev);
> +	if (r)
> +		goto ERROR0;
> +	/* wait couple of vsyncs until enabling the LCD */
> +	msleep(50);
> +	return 0;
> +
> +ERROR0:
> +	return r;
> +}
> +
> +static void sil9022_panel_disable(struct omap_dss_device *dssdev)
> +{
> +	sil9022_disable();
> +	/* wait couple of vsyncs until enabling the hdmi */
> +	msleep(50);
> +	sil9022_panel_power_off(dssdev);
> +	return;
> +}
> +
> +static struct omap_dss_driver hdmi_driver = {
> +	.probe		= sil9022_panel_probe,
> +	.remove		= sil9022_panel_remove,
> +
> +	.enable		= sil9022_panel_enable,
> +	.disable		= sil9022_panel_disable,
> +
> +	.driver         = {
> +		.name   = "sil9022_panel",
> +		.owner  = THIS_MODULE,
> +	},
> +};
> +
> +static int
> +sil9022_probe(struct i2c_client *client, const struct i2c_device_id *id)
> +{
> +	int err = 0;
> +
> +	sil9022_client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
> +	if (!sil9022_client) {
> +		err = -ENOMEM;
> +		goto ERROR0;
> +	}
> +	memset(sil9022_client, 0, sizeof(struct i2c_client));
> +
> +	strncpy(sil9022_client->name, client->name, I2C_NAME_SIZE);
> +	sil9022_client->addr = client->addr;
> +	sil9022_client->adapter = client->adapter;
> +
> +	err = sil9022_set_reg_read_ctrl(client);
> +	if (err)
> +		goto ERROR1;
> +
> +	omap_dss_register_driver(&hdmi_driver);
> +	return 0;
> +
> +ERROR1:
> +	kfree(sil9022_client);
> +ERROR0:
> +	return err;
> +}
> +
> +
> +static int
> +sil9022_remove(struct i2c_client *client)
> +
> +{
> +	int err = 0;
> +
> +	if (!client->adapter) {
> +		dev_err(&sil9022_client->dev, "<%s> No HDMI Device\n",
> +			__func__);
> +		return -ENODEV;
> +	}
> +	kfree(sil9022_client);
> +
> +	return err;
> +}
> +
> +static const struct i2c_device_id sil9022_id[] = {
> +	{ SIL9022_DRV_NAME, 0 },
> +	{ },
> +};
> +
> +MODULE_DEVICE_TABLE(i2c, sil9022_id);
> +
> +static struct i2c_driver sil9022_driver = {
> +	.driver = {
> +		.name  = SIL9022_DRV_NAME,
> +		.owner = THIS_MODULE,
> +		},
> +	.probe		= sil9022_probe,
> +	.remove		= sil9022_remove,
> +	.id_table	= sil9022_id,
> +};
> +
> +static int __init
> +sil9022_init(void)
> +{
> +	int err = 0;
> +	err = i2c_add_driver(&sil9022_driver);
> +	if (err < 0) {
> +		printk(KERN_ERR "<%s> Driver registration failed\n", __func__);
> +		err = -ENODEV;
> +		goto ERROR0;
> +	}
> +
> +	if (sil9022_client = NULL) {
> +		printk(KERN_ERR "<%s> sil9022_client not allocated\n"
> +				"<%s> No HDMI Device\n", __func__, __func__);
> +		err = -ENODEV;
> +		goto ERROR0;
> +	}
> +	return 0;
> +
> +ERROR0:
> +	return err;
> +}
> +
> +static void __exit
> +sil9022_exit(void)
> +{
> +	i2c_del_driver(&sil9022_driver);
> +}
> +
> +late_initcall(sil9022_init);
> +module_exit(sil9022_exit);
> +
> +MODULE_AUTHOR("Texas Instruments");
> +MODULE_DESCRIPTION("SIL9022 HDMI Driver");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/video/omap2/displays/panel-sil9022.h b/drivers/video/omap2/displays/panel-sil9022.h
> new file mode 100644
> index 0000000..7c920c0
> --- /dev/null
> +++ b/drivers/video/omap2/displays/panel-sil9022.h
> @@ -0,0 +1,527 @@
> +/*
> + * drivers/video/omap2/displays/panel-sil9022.c
> + *
> + * Copyright (C) 2009 Texas Instruments
> + *
> + * 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.
> + *
> + * sil9022 hdmi driver
> + */
> +#ifndef _SI9022_H_
> +#define _SI9022_H_
> +
> +#define SIL9022_DRV_NAME		"sil9022"
> +
> +#define CLKOUT2_EN		(0x1 << 7)
> +#define CLKOUT2_DIV		(0x4 << 3)
> +#define CLKOUT2SOURCE		(0x2 << 0)
> +#define CM_CLKOUT_CTRL		0x48004D70
> +
> +#define HDMI_XRES			1280
> +#define HDMI_YRES			720
> +#define HDMI_PIXCLOCK_MAX		74250
> +#define VERTICAL_FREQ			0x3C
> +
> +#define I2C_M_WR			0
> +
> +#define SI9022_USERST_PIN		1
> +
> +#define SI9022_REG_PIX_CLK_LSB		0x00
> +#define SI9022_REG_PIX_CLK_MSB		0x01
> +
> +#define SI9022_REG_PIX_REPETITION	0x08
> +#define SI9022_REG_INPUT_FORMAT		0x09
> +#define SI9022_REG_OUTPUT_FORMAT	0x0A
> +#define SI9022_REG_SYNC_GEN_CTRL	0x60
> +
> +#define SI9022_REG_DE_CTRL		0x63
> +#define DE_DLY_MSB_BITPOS		0
> +#define HSYNCPOL_INVERT_BITPOS		4
> +#define VSYNCPOL_INVERT_BITPOS		5
> +#define DE_GENERATOR_EN_BITPOS		6
> +
> +#define SI9022_REG_PWR_STATE		0x1E
> +
> +#define SI9022_REG_TPI_RQB		0xC7
> +
> +#define SI9022_REG_INT_PAGE		0xBC
> +#define SI9022_REG_OFFSET		0xBD
> +#define	SI9022_REG_VALUE		0xBE
> +
> +#define SI9022_PLLMULT_BITPOS		0x05
> +
> +#define SI9022_REG_TPI_SYSCTRL		0x1A
> +#define I2DDCREQ_BITPOS			2
> +#define TMDS_ENABLE_BITPOS		4
> +#define HDMI_ENABLE_BITPOS		0
> +
> +#define SI9022_REG_CHIPID0		0x1B
> +#define SI9022_REG_CHIPID1		0x1C
> +#define SI9022_REG_CHIPID2		0x1D
> +#define SI9022_REG_HDCPVER		0x30
> +
> +#define SI9022_REG_INTSTATUS		0x3D
> +#define HOTPLUG_PENDING_BITPOS		0
> +#define RCV_SENSE_PENDING_BITPOS	1
> +#define HOTPLUG_SENSE_BITPOS		2
> +#define RX_SENSE_BITPOS			3
> +#define AUDIO_ERR_PENDING_BITPOS	4
> +
> +
> +#define SI9022_I2CSLAVEADDRESS		0x39
> +
> +#define SI9022_CHIPID_902x		0xB0
> +
> +#define SI9022_MAXRETRY			100
> +
> +#define SI9022_EDID_DETAILED_TIMING_OFFSET	0x36 /*EDID Detailed Timing */
> +						/*Info 0 begin offset*/
> +#define SI9022_EDID_PIX_CLK_OFFSET		0
> +#define SI9022_EDID_H_ACTIVE_OFFSET		2
> +#define SI9022_EDID_H_BLANKING_OFFSET		3
> +#define SI9022_EDID_V_ACTIVE_OFFSET		5
> +#define SI9022_EDID_V_BLANKING_OFFSET		6
> +#define SI9022_EDID_H_SYNC_OFFSET		8
> +#define SI9022_EDID_H_SYNC_PW_OFFSET		9
> +#define SI9022_EDID_V_SYNC_OFFSET		10
> +#define SI9022_EDID_V_SYNC_PW_OFFSET		10
> +#define SI9022_EDID_H_IMAGE_SIZE_OFFSET		12
> +#define SI9022_EDID_V_IMAGE_SIZE_OFFSET		13
> +#define SI9022_EDID_H_BORDER_OFFSET		15
> +#define SI9022_EDID_V_BORDER_OFFSET		16
> +#define SI9022_EDID_FLAGS_OFFSET		17
> +
> +#define SI9022_PLUG_DETECTED			0xF0
> +#define SI9022_UNPLUG_DETECTED			0xF1
> +
> +
> +/* ---------------------------------------------------------------------  */
> +#define EDID_TIMING_DESCRIPTOR_SIZE		0x12
> +#define EDID_DESCRIPTOR_BLOCK0_ADDRESS		0x36
> +#define EDID_DESCRIPTOR_BLOCK1_ADDRESS		0x80
> +#define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR	4
> +#define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR	4
> +
> +/* HDMI Connected States  */
> +#define HDMI_STATE_NOMONITOR	0	/* NOT CONNECTED */
> +#define HDMI_STATE_CONNECTED	1	/* CONNECTED */
> +#define HDMI_STATE_ON		2	/* CONNECTED AND POWERED ON */
> +
> +
> +/* HDMI EDID Length  */
> +#define HDMI_EDID_MAX_LENGTH	256
> +
> +/* HDMI EDID DTDs  */
> +#define HDMI_EDID_MAX_DTDS	4
> +
> +/* HDMI EDID DTD Tags  */
> +#define HDMI_EDID_DTD_TAG_MONITOR_NAME		0xFC
> +#define HDMI_EDID_DTD_TAG_MONITOR_SERIALNUM	0xFF
> +#define HDMI_EDID_DTD_TAG_MONITOR_LIMITS	0xFD
> +
> +
> +/* HDMI EDID Extension Data Block Tags  */
> +#define HDMI_EDID_EX_DATABLOCK_TAG_MASK		0xE0
> +#define HDMI_EDID_EX_DATABLOCK_LEN_MASK		0x1F
> +
> +#define HDMI_EDID_EX_DATABLOCK_AUDIO		0x20
> +#define HDMI_EDID_EX_DATABLOCK_VIDEO		0x40
> +#define HDMI_EDID_EX_DATABLOCK_VENDOR		0x60
> +#define HDMI_EDID_EX_DATABLOCK_SPEAKERS		0x80
> +
> +/* HDMI EDID Extenion Data Block Values: Video  */
> +#define HDMI_EDID_EX_VIDEO_NATIVE		0x80
> +#define HDMI_EDID_EX_VIDEO_MASK			0x7F
> +#define HDMI_EDID_EX_VIDEO_MAX			35
> +
> +#define HDMI_EDID_EX_VIDEO_640x480p_60Hz_4_3		1
> +#define HDMI_EDID_EX_VIDEO_720x480p_60Hz_4_3		2
> +#define HDMI_EDID_EX_VIDEO_720x480p_60Hz_16_9		3
> +#define HDMI_EDID_EX_VIDEO_1280x720p_60Hz_16_9		4
> +#define HDMI_EDID_EX_VIDEO_1920x1080i_60Hz_16_9		5
> +#define HDMI_EDID_EX_VIDEO_720x480i_60Hz_4_3		6
> +#define HDMI_EDID_EX_VIDEO_720x480i_60Hz_16_9		7
> +#define HDMI_EDID_EX_VIDEO_720x240p_60Hz_4_3		8
> +#define HDMI_EDID_EX_VIDEO_720x240p_60Hz_16_9		9
> +#define HDMI_EDID_EX_VIDEO_2880x480i_60Hz_4_3		10
> +#define HDMI_EDID_EX_VIDEO_2880x480i_60Hz_16_9		11
> +#define HDMI_EDID_EX_VIDEO_2880x480p_60Hz_4_3		12
> +#define HDMI_EDID_EX_VIDEO_2880x480p_60Hz_16_9		13
> +#define HDMI_EDID_EX_VIDEO_1440x480p_60Hz_4_3		14
> +#define HDMI_EDID_EX_VIDEO_1440x480p_60Hz_16_9		15
> +#define HDMI_EDID_EX_VIDEO_1920x1080p_60Hz_16_9		16
> +#define HDMI_EDID_EX_VIDEO_720x576p_50Hz_4_3		17
> +#define HDMI_EDID_EX_VIDEO_720x576p_50Hz_16_9		18
> +#define HDMI_EDID_EX_VIDEO_1280x720p_50Hz_16_9		19
> +#define HDMI_EDID_EX_VIDEO_1920x1080i_50Hz_16_9		20
> +#define HDMI_EDID_EX_VIDEO_720x576i_50Hz_4_3		21
> +#define HDMI_EDID_EX_VIDEO_720x576i_50Hz_16_9		22
> +#define HDMI_EDID_EX_VIDEO_720x288p_50Hz_4_3		23
> +#define HDMI_EDID_EX_VIDEO_720x288p_50Hz_16_9		24
> +#define HDMI_EDID_EX_VIDEO_2880x576i_50Hz_4_3		25
> +#define HDMI_EDID_EX_VIDEO_2880x576i_50Hz_16_9		26
> +#define HDMI_EDID_EX_VIDEO_2880x288p_50Hz_4_3		27
> +#define HDMI_EDID_EX_VIDEO_2880x288p_50Hz_16_9		28
> +#define HDMI_EDID_EX_VIDEO_1440x576p_50Hz_4_3		29
> +#define HDMI_EDID_EX_VIDEO_1440x576p_50Hz_16_9		30
> +#define HDMI_EDID_EX_VIDEO_1920x1080p_50Hz_16_9		31
> +#define HDMI_EDID_EX_VIDEO_1920x1080p_24Hz_16_9		32
> +#define HDMI_EDID_EX_VIDEO_1920x1080p_25Hz_16_9		33
> +#define HDMI_EDID_EX_VIDEO_1920x1080p_30Hz_16_9		34
> +
> +/*  HDMI TPI Registers  */
> +#define HDMI_TPI_VIDEO_DATA_BASE_REG	0x00
> +#define HDMI_TPI_PIXEL_CLK_LSB_REG	 (HDMI_TPI_VIDEO_DATA_BASE_REG + 0x00)
> +#define HDMI_TPI_PIXEL_CLK_MSB_REG (HDMI_TPI_VIDEO_DATA_BASE_REG + 0x01)
> +#define HDMI_TPI_VFREQ_LSB_REG	(HDMI_TPI_VIDEO_DATA_BASE_REG + 0x02)
> +#define HDMI_TPI_VFREQ_MSB_REG	(HDMI_TPI_VIDEO_DATA_BASE_REG + 0x03)
> +#define HDMI_TPI_PIXELS_LSB_REG	(HDMI_TPI_VIDEO_DATA_BASE_REG + 0x04)
> +#define HDMI_TPI_PIXELS_MSB_REG	(HDMI_TPI_VIDEO_DATA_BASE_REG + 0x05)
> +#define HDMI_TPI_LINES_LSB_REG		(HDMI_TPI_VIDEO_DATA_BASE_REG + 0x06)
> +#define HDMI_TPI_LINES_MSB_REG		(HDMI_TPI_VIDEO_DATA_BASE_REG + 0x07)
> +
> +#define HDMI_TPI_PIXEL_REPETITION_REG	0x08
> +
> +#define HDMI_TPI_AVI_INOUT_BASE_REG	0x09
> +#define HDMI_TPI_AVI_IN_FORMAT_REG	(HDMI_TPI_AVI_INOUT_BASE_REG + 0x00)
> +#define HDMI_TPI_AVI_OUT_FORMAT_REG	(HDMI_TPI_AVI_INOUT_BASE_REG + 0x01)
> +
> +#define HDMI_SYS_CTRL_DATA_REG		0x1A
> +
> +#define HDMI_TPI_SYN_GENERATOR_REG	0x60
> +
> +#define HDMI_TPI_VIDEO_SYN_POLARITY_REG	0x61
> +
> +#define HDMI_TPI_DE_BASE_REG			0x62
> +#define HDMI_TPI_DE_DLY_LSB_REG		(HDMI_TPI_DE_BASE_REG + 0x0)
> +#define HDMI_TPI_DE_DLY_MSB_REG		(HDMI_TPI_DE_BASE_REG + 0x1)
> +#define HDMI_TPI_DE_TOP_REG			(HDMI_TPI_DE_BASE_REG + 0x2)
> +#define HDMI_TPI_DE_RSVD_REG			(HDMI_TPI_DE_BASE_REG + 0x3)
> +#define HDMI_TPI_DE_CNT_LSB_REG		(HDMI_TPI_DE_BASE_REG + 0x4)
> +#define HDMI_TPI_DE_CNT_MSB_REG		(HDMI_TPI_DE_BASE_REG + 0x5)
> +#define HDMI_TPI_DE_LIN_LSB_REG		(HDMI_TPI_DE_BASE_REG + 0x6)
> +#define HDMI_TPI_DE_LIN_MSB_REG		(HDMI_TPI_DE_BASE_REG + 0x7)
> +
> +#define HDMI_TPI_HRES_LSB_REG		0x6A
> +#define HDMI_TPI_HRES_MSB_REG		0x6B
> +
> +#define HDMI_TPI_VRES_LSB_REG		0x6C
> +#define HDMI_TPI_VRES_MSB_REG		0x6D
> +
> +#define HDMI_TPI_RQB_REG		0xC7
> +#define HDMI_TPI_DEVID_REG		0x1B
> +#define HDMI_TPI_DEVREV_REG		0x1C
> +
> +#define HDMI_TPI_DEVICE_POWER_STATE_DATA	0x1E
> +#define HDMI_REQ_GRANT_BMODE_REG		0xC7
> +#define HDMI_TPI_DEVICE_ID_REG			0x1B
> +#define HDMI_TPI_REVISION_REG			0x1C
> +#define HDMI_TPI_ID_BYTE2_REG			0x1D
> +#define HDMI_TPI_POWER_STATE_CTRL_REG		0x1E
> +
> +#define HDMI_TPI_INTERRUPT_ENABLE_REG		0x3C
> +#define HDMI_TPI_INTERRUPT_STATUS_REG		0x3D
> +
> +
> +/* AVI InfoFrames can be readed byte by byte but must be write in a burst  */
> +#define HDMI_TPI_AVI_DBYTE_BASE_REG      0x0C
> +#define HDMI_TPI_AVI_DBYTE0_CHKSUM_REG   (HDMI_TPI_AVI_DBYTE_BASE_REG +  0x00)
> +#define HDMI_TPI_AVI_DBYTE1_REG          (HDMI_TPI_AVI_DBYTE_BASE_REG +  0x01)
> +#define HDMI_TPI_AVI_DBYTE2_REG          (HDMI_TPI_AVI_DBYTE_BASE_REG +  0x02)
> +#define HDMI_TPI_AVI_DBYTE3_REG          (HDMI_TPI_AVI_DBYTE_BASE_REG +  0x03)
> +#define HDMI_TPI_AVI_DBYTE4_REG          (HDMI_TPI_AVI_DBYTE_BASE_REG +  0x04)
> +#define HDMI_TPI_AVI_DBYTE5_REG          (HDMI_TPI_AVI_DBYTE_BASE_REG +  0x05)
> +#define HDMI_TPI_AVI_ETB_LSB_REG         (HDMI_TPI_AVI_DBYTE_BASE_REG +  0x06)
> +#define HDMI_TPI_AVI_ETB_MSB_REG         (HDMI_TPI_AVI_DBYTE_BASE_REG +  0x07)
> +#define HDMI_TPI_AVI_SBB_LSB_REG         (HDMI_TPI_AVI_DBYTE_BASE_REG +  0x08)
> +#define HDMI_TPI_AVI_SBB_MSB_REG         (HDMI_TPI_AVI_DBYTE_BASE_REG +  0x09)
> +#define HDMI_TPI_AVI_ELB_LSB_REG         (HDMI_TPI_AVI_DBYTE_BASE_REG +  0x0A)
> +#define HDMI_TPI_AVI_ELB_MSB_REG         (HDMI_TPI_AVI_DBYTE_BASE_REG +  0x0B)
> +#define HDMI_TPI_AVI_SRB_LSB_REG         (HDMI_TPI_AVI_DBYTE_BASE_REG +  0x0C)
> +#define HDMI_TPI_AVI_SRB_MSB_REG         (HDMI_TPI_AVI_DBYTE_BASE_REG +  0x0D)
> +
> +#define HDMI_CPI_MISC_IF_SELECT_REG         0xBF
> +#define HDMI_CPI_MISC_IF_OFFSET             0xC0
> +
> +#define MISC_INFOFRAME_SIZE_MEMORY          14
> +#define MISC_INFOFRAME_TYPE_SUBOFFSET       0
> +#define MISC_INFOFRAME_VERSION_SUBOFFSET    1
> +#define MISC_INFOFRAME_LENGTH_SUBOFFSET     2
> +#define MISC_INFOFRAME_CHECKSUM_SUBOFFSET   3
> +#define MISC_INFOFRAME_DBYTE1_SUBOFFSET     4
> +#define MISC_INFOFRAME_DBYTE2_SUBOFFSET     5
> +#define MISC_INFOFRAME_DBYTE3_SUBOFFSET     6
> +#define MISC_INFOFRAME_DBYTE4_SUBOFFSET     7
> +#define MISC_INFOFRAME_DBYTE5_SUBOFFSET     8
> +#define MISC_INFOFRAME_DBYTE6_SUBOFFSET     9
> +#define MISC_INFOFRAME_DBYTE7_SUBOFFSET     10
> +#define MISC_INFOFRAME_DBYTE8_SUBOFFSET     11
> +#define MISC_INFOFRAME_DBYTE9_SUBOFFSET     12
> +#define MISC_INFOFRAME_DBYTE10_SUBOFFSET    13
> +
> +#define HDMI_CPI_MISC_TYPE_REG		(HDMI_CPI_MISC_IF_OFFSET\
> +					+  MISC_INFOFRAME_TYPE_SUBOFFSET)
> +#define HDMI_CPI_MISC_VERSION_REG	(HDMI_CPI_MISC_IF_OFFSET\
> +					+  MISC_INFOFRAME_VERSION_SUBOFFSET)
> +#define HDMI_CPI_MISC_LENGTH_REG	(HDMI_CPI_MISC_IF_OFFSET\
> +					+  MISC_INFOFRAME_LENGTH_SUBOFFSET)
> +#define HDMI_CPI_MISC_CHECKSUM_REG	(HDMI_CPI_MISC_IF_OFFSET\
> +					+  MISC_INFOFRAME_CHECKSUM_SUBOFFSET)
> +#define HDMI_CPI_MISC_DBYTE1_REG        (HDMI_CPI_MISC_IF_OFFSET\
> +					+  MISC_INFOFRAME_DBYTE1_SUBOFFSET)
> +#define HDMI_CPI_MISC_DBYTE2_REG        (HDMI_CPI_MISC_IF_OFFSET\
> +					+  MISC_INFOFRAME_DBYTE2_SUBOFFSET)
> +#define HDMI_CPI_MISC_DBYTE3_REG        (HDMI_CPI_MISC_IF_OFFSET\
> +					+  MISC_INFOFRAME_DBYTE3_SUBOFFSET)
> +#define HDMI_CPI_MISC_DBYTE4_REG        (HDMI_CPI_MISC_IF_OFFSET\
> +					+  MISC_INFOFRAME_DBYTE4_SUBOFFSET)
> +#define HDMI_CPI_MISC_DBYTE5_REG        (HDMI_CPI_MISC_IF_OFFSET\
> +					+  MISC_INFOFRAME_DBYTE5_SUBOFFSET)
> +#define HDMI_CPI_MISC_DBYTE6_REG        (HDMI_CPI_MISC_IF_OFFSET\
> +					+  MISC_INFOFRAME_DBYTE6_SUBOFFSET)
> +#define HDMI_CPI_MISC_DBYTE7_REG        (HDMI_CPI_MISC_IF_OFFSET\
> +					+  MISC_INFOFRAME_DBYTE7_SUBOFFSET)
> +#define HDMI_CPI_MISC_DBYTE8_REG        (HDMI_CPI_MISC_IF_OFFSET\
> +					+  MISC_INFOFRAME_DBYTE8_SUBOFFSET)
> +#define HDMI_CPI_MISC_DBYTE9_REG        (HDMI_CPI_MISC_IF_OFFSET\
> +					+  MISC_INFOFRAME_DBYTE9_SUBOFFSET)
> +#define HDMI_CPI_MISC_DBYTE10_REG       (HDMI_CPI_MISC_IF_OFFSET\
> +					+  MISC_INFOFRAME_DBYTE10_SUBOFFSET)
> +
> +/* Audio  */
> +#define HDMI_TPI_I2S_ENABLE_MAPPING_REG     0x1F
> +#define HDMI_TPI_I2S_INPUT_CONFIG_REG       0x20
> +#define HDMI_TPI_I2S_STRM_HDR_BASE          0x21
> +#define HDMI_TPI_I2S_STRM_HDR_0_REG         (HDMI_TPI_I2S_STRM_HDR_BASE + 0)
> +#define HDMI_TPI_I2S_STRM_HDR_1_REG         (HDMI_TPI_I2S_STRM_HDR_BASE + 1)
> +#define HDMI_TPI_I2S_STRM_HDR_2_REG         (HDMI_TPI_I2S_STRM_HDR_BASE + 2)
> +#define HDMI_TPI_I2S_STRM_HDR_3_REG         (HDMI_TPI_I2S_STRM_HDR_BASE + 3)
> +#define HDMI_TPI_I2S_STRM_HDR_4_REG         (HDMI_TPI_I2S_STRM_HDR_BASE + 4)
> +#define HDMI_TPI_AUDIO_CONFIG_BYTE2_REG     0x26
> +#define HDMI_TPI_AUDIO_CONFIG_BYTE3_REG     0x27
> +#define HDMI_TPI_AUDIO_CONFIG_BYTE4_REG     0x28
> +
> +/* HDCP */
> +#define HDMI_TPI_HDCP_QUERYDATA_REG         0x29
> +#define HDMI_TPI_HDCP_CONTROLDATA_REG       0x2A
> +
> +/* HDMI_TPI_DEVICE_ID_REG  */
> +#define TPI_DEVICE_ID                       0xB0
> +
> +/* HDMI_TPI_REVISION_REG  */
> +#define TPI_REVISION                        0x00
> +
> +/* HDMI_TPI_ID_BYTE2_REG  */
> +#define TPI_ID_BYTE2_VALUE                  0x00
> +
> +/* HDMI_SYS_CTRL_DATA_REG  */
> +#define TPI_SYS_CTRL_POWER_DOWN             (1 << 4)
> +#define TPI_SYS_CTRL_POWER_ACTIVE           (0 << 4)
> +#define TPI_SYS_CTRL_AV_MUTE                (1 << 3)
> +#define TPI_SYS_CTRL_DDC_BUS_REQUEST        (1 << 2)
> +#define TPI_SYS_CTRL_DDC_BUS_GRANTED        (1 << 1)
> +#define TPI_SYS_CTRL_OUTPUT_MODE_HDMI       (1 << 0)
> +#define TPI_SYS_CTRL_OUTPUT_MODE_DVI        (0 << 0)
> +
> +
> +/* HDMI Monitor I2C default address  */
> +#define HDMI_I2C_MONITOR_ADDRESS            0x50
> +
> +
> +/* HDMI_TPI_INTR_ENABLE  */
> +#define TPI_INTR_ENABLE_SECURITY_EVENT      (1 << 5)
> +#define TPI_INTR_ENABLE_AUDIO_EVENT         (1 << 4)
> +#define TPI_INTR_ENABLE_CPI_EVENT           (1 << 3)
> +#define TPI_INTR_ENABLE_RECEIVER_EVENT      (1 << 1)
> +#define TPI_INTR_ENABLE_HOTPLUG_EVENT       (1 << 0)
> +
> +/* HDMI_TPI_INTR_STATUS  */
> +#define TPI_INTR_STATUS_SECURITY_EVENT      (1 << 5)
> +#define TPI_INTR_STATUS_AUDIO_EVENT         (1 << 4)
> +#define TPI_INTR_STATUS_POWERED_EVENT       (1 << 3)
> +#define TPI_INTR_STATUS_HOTPLUG_STATE       (1 << 2)
> +#define TPI_INTR_STATUS_RECEIVER_EVENT      (1 << 1)
> +#define TPI_INTR_STATUS_HOTPLUG_EVENT       (1 << 0)
> +
> +
> +/* HDMI_TPI_PIXEL_REPETITION  */
> +#define TPI_AVI_PIXEL_REP_BUS_24BIT         (1 << 5)
> +#define TPI_AVI_PIXEL_REP_BUS_12BIT         (0 << 5)
> +#define TPI_AVI_PIXEL_REP_RISING_EDGE       (1 << 4)
> +#define TPI_AVI_PIXEL_REP_FALLING_EDGE      (0 << 4)
> +#define TPI_AVI_PIXEL_REP_4X                (3 << 0)
> +#define TPI_AVI_PIXEL_REP_2X                (1 << 0)
> +#define TPI_AVI_PIXEL_REP_NONE              (0 << 0)
> +
> +/* HDMI_TPI_AVI_INPUT_FORMAT  */
> +#define TPI_AVI_INPUT_BITMODE_12BIT         (1 << 7)
> +#define TPI_AVI_INPUT_BITMODE_8BIT          (0 << 7)
> +#define TPI_AVI_INPUT_DITHER                (1 << 6)
> +#define TPI_AVI_INPUT_RANGE_LIMITED         (2 << 2)
> +#define TPI_AVI_INPUT_RANGE_FULL            (1 << 2)
> +#define TPI_AVI_INPUT_RANGE_AUTO            (0 << 2)
> +#define TPI_AVI_INPUT_COLORSPACE_BLACK      (3 << 0)
> +#define TPI_AVI_INPUT_COLORSPACE_YUV422     (2 << 0)
> +#define TPI_AVI_INPUT_COLORSPACE_YUV444     (1 << 0)
> +#define TPI_AVI_INPUT_COLORSPACE_RGB        (0 << 0)
> +
> +
> +/* HDMI_TPI_AVI_OUTPUT_FORMAT  */
> +#define TPI_AVI_OUTPUT_CONV_BT709           (1 << 4)
> +#define TPI_AVI_OUTPUT_CONV_BT601           (0 << 4)
> +#define TPI_AVI_OUTPUT_RANGE_LIMITED        (2 << 2)
> +#define TPI_AVI_OUTPUT_RANGE_FULL           (1 << 2)
> +#define TPI_AVI_OUTPUT_RANGE_AUTO           (0 << 2)
> +#define TPI_AVI_OUTPUT_COLORSPACE_RGBDVI    (3 << 0)
> +#define TPI_AVI_OUTPUT_COLORSPACE_YUV422    (2 << 0)
> +#define TPI_AVI_OUTPUT_COLORSPACE_YUV444    (1 << 0)
> +#define TPI_AVI_OUTPUT_COLORSPACE_RGBHDMI   (0 << 0)
> +
> +
> +/* HDMI_TPI_DEVICE_POWER_STATE  */
> +#define TPI_AVI_POWER_STATE_D3              (3 << 0)
> +#define TPI_AVI_POWER_STATE_D2              (2 << 0)
> +#define TPI_AVI_POWER_STATE_D0              (0 << 0)
> +
> +/* HDMI_TPI_AUDIO_CONFIG_BYTE2_REG  */
> +#define TPI_AUDIO_CODING_STREAM_HEADER      (0 << 0)
> +#define TPI_AUDIO_CODING_PCM                (1 << 0)
> +#define TPI_AUDIO_CODING_AC3                (2 << 0)
> +#define TPI_AUDIO_CODING_MPEG1              (3 << 0)
> +#define TPI_AUDIO_CODING_MP3                (4 << 0)
> +#define TPI_AUDIO_CODING_MPEG2              (5 << 0)
> +#define TPI_AUDIO_CODING_AAC                (6 << 0)
> +#define TPI_AUDIO_CODING_DTS                (7 << 0)
> +#define TPI_AUDIO_CODING_ATRAC              (8 << 0)
> +#define TPI_AUDIO_MUTE_DISABLE              (0 << 4)
> +#define TPI_AUDIO_MUTE_ENABLE               (1 << 4)
> +#define TPI_AUDIO_INTERFACE_DISABLE         (0 << 6)
> +#define TPI_AUDIO_INTERFACE_SPDIF           (1 << 6)
> +#define TPI_AUDIO_INTERFACE_I2S             (2 << 6)
> +
> +/* HDMI_TPI_AUDIO_CONFIG_BYTE3_REG  */
> +#define TPI_AUDIO_CHANNEL_STREAM            (0 << 0)
> +#define TPI_AUDIO_2_CHANNEL                 (1 << 0)
> +#define TPI_AUDIO_8_CHANNEL                 (7 << 0)
> +#define TPI_AUDIO_FREQ_STREAM               (0 << 3)
> +#define TPI_AUDIO_FREQ_32KHZ                (1 << 3)
> +#define TPI_AUDIO_FREQ_44KHZ                (2 << 3)
> +#define TPI_AUDIO_FREQ_48KHZ                (3 << 3)
> +#define TPI_AUDIO_FREQ_88KHZ                (4 << 3)
> +#define TPI_AUDIO_FREQ_96KHZ                (5 << 3)
> +#define TPI_AUDIO_FREQ_176KHZ               (6 << 3)
> +#define TPI_AUDIO_FREQ_192KHZ               (7 << 3)
> +#define TPI_AUDIO_SAMPLE_SIZE_STREAM        (0 << 6)
> +#define TPI_AUDIO_SAMPLE_SIZE_16            (1 << 6)
> +#define TPI_AUDIO_SAMPLE_SIZE_20            (2 << 6)
> +#define TPI_AUDIO_SAMPLE_SIZE_24            (3 << 6)
> +
> +/* HDMI_TPI_I2S_ENABLE_MAPPING_REG  */
> +#define TPI_I2S_SD_CONFIG_SELECT_SD0        (0 << 0)
> +#define TPI_I2S_SD_CONFIG_SELECT_SD1        (1 << 0)
> +#define TPI_I2S_SD_CONFIG_SELECT_SD2        (2 << 0)
> +#define TPI_I2S_SD_CONFIG_SELECT_SD3        (3 << 0)
> +#define TPI_I2S_LF_RT_SWAP_NO               (0 << 2)
> +#define TPI_I2S_LF_RT_SWAP_YES              (1 << 2)
> +#define TPI_I2S_DOWNSAMPLE_DISABLE          (0 << 3)
> +#define TPI_I2S_DOWNSAMPLE_ENABLE           (1 << 3)
> +#define TPI_I2S_SD_FIFO_0                   (0 << 4)
> +#define TPI_I2S_SD_FIFO_1                   (1 << 4)
> +#define TPI_I2S_SD_FIFO_2                   (2 << 4)
> +#define TPI_I2S_SD_FIFO_3                   (3 << 4)
> +#define TPI_I2S_SD_CHANNEL_DISABLE          (0 << 7)
> +#define TPI_I2S_SD_CHANNEL_ENABLE           (1 << 7)
> +
> +
> +/* HDMI_TPI_I2S_INPUT_CONFIG_REG  */
> +#define TPI_I2S_FIRST_BIT_SHIFT_YES         (0 << 0)
> +#define TPI_I2S_FIRST_BIT_SHIFT_NO          (1 << 0)
> +#define TPI_I2S_SD_DIRECTION_MSB_FIRST      (0 << 1)
> +#define TPI_I2S_SD_DIRECTION_LSB_FIRST      (1 << 1)
> +#define TPI_I2S_SD_JUSTIFY_LEFT             (0 << 2)
> +#define TPI_I2S_SD_JUSTIFY_RIGHT            (1 << 2)
> +#define TPI_I2S_WS_POLARITY_LOW             (0 << 3)
> +#define TPI_I2S_WS_POLARITY_HIGH            (1 << 3)
> +#define TPI_I2S_MCLK_MULTIPLIER_128         (0 << 4)
> +#define TPI_I2S_MCLK_MULTIPLIER_256         (1 << 4)
> +#define TPI_I2S_MCLK_MULTIPLIER_384         (2 << 4)
> +#define TPI_I2S_MCLK_MULTIPLIER_512         (3 << 4)
> +#define TPI_I2S_MCLK_MULTIPLIER_768         (4 << 4)
> +#define TPI_I2S_MCLK_MULTIPLIER_1024        (5 << 4)
> +#define TPI_I2S_MCLK_MULTIPLIER_1152        (6 << 4)
> +#define TPI_I2S_MCLK_MULTIPLIER_192         (7 << 4)
> +#define TPI_I2S_SCK_EDGE_FALLING            (0 << 7)
> +#define TPI_I2S_SCK_EDGE_RISING             (1 << 7)
> +
> +/* HDMI_TPI_I2S_STRM_HDR_REG                       */
> +/* the reference of this values is in IEC 60958-3  */
> +#define I2S_CHAN_STATUS_MODE                0x00
> +#define I2S_CHAN_STATUS_CAT_CODE            0x00
> +#define I2S_CHAN_SOURCE_CHANNEL_NUM         0x00
> +#define I2S_CHAN_ACCURACY_N_44_SAMPLING_FS  0x20
> +#define I2S_CHAN_ACCURACY_N_48_SAMPLING_FS  0x22
> +#define I2S_CHAN_ORIGIN_FS_N_SAMP_LENGTH    0xD2
> +
> +
> +/* MISCELLANOUS INFOFRAME VALUES  */
> +
> +#define HDMI_INFOFRAME_TX_ENABLE            (0x1 << 7)
> +#define HDMI_INFOFRAME_TX_REPEAT            (0x1 << 6)
> +#define HDMI_AUDIO_INFOFRAME                (0x2 << 0)
> +
> +/* Stream Header Data  */
> +#define HDMI_SH_PCM                         (0x1 << 4)
> +#define HDMI_SH_TWO_CHANNELS                (0x1 << 0)
> +#define HDMI_SH_44KHz                       (0x2 << 2)
> +#define HDMI_SH_48KHz                       (0x3 << 2)
> +#define HDMI_SH_16BIT                       (0x1 << 0)
> +#define HDMI_SH_SPKR_FLFR                   0x0
> +#define HDMI_SH_0dB_ATUN                    0x0
> +
> +/* MISC_TYPE  */
> +#define MISC_INFOFRAME_TYPE                 0x04  /* for Audio */
> +#define MISC_INFOFRAME_ALWAYS_SET           0x80
> +
> +/* MISC_VERSION  */
> +#define MISC_INFOFRAME_VERSION              0x01
> +
> +/* MISC_LENGTH  */
> +#define MISC_INFOFRAME_LENGTH               0x0A /*length for Audio infoframe*/
> +#define MISC_INFOFRAME_LENGTH_RSVD_BITS     0xE0
> +
> +/* MISC_DBYTE1                */
> +/* Type, Encoding, Trandport  */
> +#define MISC_DBYTE1_CT_CHK_HEADER_STREAM    0x00
> +
> +/* audio channel count  */
> +#define MISC_DBYTE1_CC_CHK_HEADER_STREAM    0x00
> +#define MISC_DBYTE1_CC_2_CHANNELS           0x01
> +
> +/* MISC_DBYTE2  */
> +/*Sample Size   */
> +#define MISC_DBYTE2_SS_CHK_HEADER_STREAM    0x00  /* for hdmi by default */
> +
> +/* Sampling Frequency  */
> +#define MISC_DBYTE2_SF_CHK_HEADER_STREAM    0x00  /* for hdmi by default */
> +
> +/* MISC_DBYTE3     */
> +/* Code Extention  */
> +#define MISC_DBYTE3_CTX_TAKE_DBYTE1         0x00  /* for hdmi by default */
> +
> +/* MISC_DBYTE4  */
> +#define MISC_DBYTE4                         0x00 /*for no multichannel( */
> +						 /* multichannel means more*/
> +						/* than 2 channels */
> +
> +/* MISC_DBYTE5  */
> +#define MISC_DBYTE5           0x00  /* for no multichannel(multichannel  */
> +					/* means more than 2 channels */
> +
> +struct hdmi_reg_data {
> +	u8 reg_offset;
> +	u8 value;
> +};
> +
> +#endif
> -- 
> 1.7.9.5
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-fbdev" 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

* Re: [V3 0/7] Enhance mmp display driver
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-07-09 13:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1372332473-6584-1-git-send-email-jtzhou@marvell.com>

HI,

	please rebase on the for-next branch as it does not apply

Best Regards,
J.
On 19:27 Thu 27 Jun     , Jett.Zhou wrote:
> Changelog:
> 1 Add more comments for the mmp_display rbswap usage 
> according to Daniel's comments;
> 2 Add fix patch for ttc_dkb on rbswap;
> 3 Add more comments on the pitch usage and definition;
> 4 Combine the modification on pitch of graphic and video layer
> in one patch.
> 
> Guoqing Li (2):
>   video: mmp: rb swap setting update for mmp display
>   video: mmp: optimize some register setting code
> 
> Jett.Zhou (1):
>   ARM: mmp: remove the legacy rbswap setting for ttc_dkb platform
> 
> Jing Xiang (4):
>   video: mmp: fix graphics/video layer enable/mask issue
>   video: mmp: fix memcpy wrong size for mmp_addr issue
>   video: mmp: calculate pitch value when fb set win
>   video: mmp: add pitch info in mmp_win structure
> 
>  arch/arm/mach-mmp/ttc_dkb.c     |    4 +-
>  drivers/video/mmp/fb/mmpfb.c    |   34 +++++++++++------
>  drivers/video/mmp/hw/mmp_ctrl.c |   79 ++++++++++++++++++++++-----------------
>  drivers/video/mmp/hw/mmp_ctrl.h |    5 ++
>  include/video/mmp_disp.h        |    6 +++
>  5 files changed, 79 insertions(+), 49 deletions(-)
> 

^ permalink raw reply

* Re: [PATCH 1/1] OMAPDSS: Add sil9022 driver
From: Yegor Yefremov @ 2013-07-09 12:31 UTC (permalink / raw)
  To: Sathya Prakash
  Cc: Sathya Prakash M R, Valkeinen, Tomi, archit, linux-omap,
	linux-fbdev, Srinivas Pulukuru
In-Reply-To: <51DBEC74.70406@ti.com>

On Tue, Jul 9, 2013 at 12:56 PM, Sathya Prakash <a0393677@ti.com> wrote:
> Hi,
>
>
> On Tuesday 09 July 2013 03:07 PM, Yegor Yefremov wrote:
>>
>> On Tue, Jul 9, 2013 at 11:07 AM, Sathya Prakash M R <sathyap@ti.com>
>> wrote:
>>>
>>> From: Srinivas Pulukuru <srinivas.pulukuru@ti.com>
>>>
>>> Add driver for SIL9022 DPI-to-HDMI chip.
>>>
>>> Signed-off-by: Srinivas Pulukuru <srinivas.pulukuru@ti.com>
>>> [sathyap@ti.com: Ported the driver from 2.6.32 based internal
>>> kernel to v3.10 kernel]
>>> Signed-off-by: Sathya Prakash M R <sathyap@ti.com>
>>> ---
>>> This patch was tested using the legacy OMAP3630 based Zoom3 platform.
>>> There is no DT support for Zoom , hence board file changes
>>> made locally were used for validation purpose.
>>> Further, DT support will be added for a newer SOC which uses
>>> the sil9022 HDMI interface chip.
>>>
>>>   drivers/video/omap2/displays/Kconfig         |    8 +
>>>   drivers/video/omap2/displays/Makefile        |    1 +
>>>   drivers/video/omap2/displays/panel-sil9022.c | 1274
>>> ++++++++++++++++++++++++++
>>>   drivers/video/omap2/displays/panel-sil9022.h |  527 +++++++++++
>>>   4 files changed, 1810 insertions(+)
>>>   create mode 100644 drivers/video/omap2/displays/panel-sil9022.c
>>>   create mode 100644 drivers/video/omap2/displays/panel-sil9022.h
>>
>> What about making this driver more general. We've tested this HDMI
>> chip on am335x and there are also Freescal based devices using this
>> chip (http://www.genesi-tech.com/products/efika and kernel repo
>> http://github.com/genesi/linux-legacy).
>
> Currently the panel driver is tied to the OMAPDSS and hence making
> this driver more generic is a difficult job.
> But the Common Display Framework (CDF) will surely help us in future
> to get drivers like this easy to port across different platforms.
> In the future, will make this driver part of CDF to help in making it more
> general.

O.K.

Yegor

^ permalink raw reply

* Re: [PATCH 1/1] OMAPDSS: Add sil9022 driver
From: Sathya Prakash @ 2013-07-09 10:56 UTC (permalink / raw)
  To: Yegor Yefremov
  Cc: Sathya Prakash M R, Valkeinen, Tomi, archit, linux-omap,
	linux-fbdev, Srinivas Pulukuru
In-Reply-To: <CAGm1_kuVLrTPS2TYw=TRWOppbY4HW0tpYUJzWqyv7MapJTL-_Q@mail.gmail.com>

Hi,

On Tuesday 09 July 2013 03:07 PM, Yegor Yefremov wrote:
> On Tue, Jul 9, 2013 at 11:07 AM, Sathya Prakash M R <sathyap@ti.com> wrote:
>> From: Srinivas Pulukuru <srinivas.pulukuru@ti.com>
>>
>> Add driver for SIL9022 DPI-to-HDMI chip.
>>
>> Signed-off-by: Srinivas Pulukuru <srinivas.pulukuru@ti.com>
>> [sathyap@ti.com: Ported the driver from 2.6.32 based internal
>> kernel to v3.10 kernel]
>> Signed-off-by: Sathya Prakash M R <sathyap@ti.com>
>> ---
>> This patch was tested using the legacy OMAP3630 based Zoom3 platform.
>> There is no DT support for Zoom , hence board file changes
>> made locally were used for validation purpose.
>> Further, DT support will be added for a newer SOC which uses
>> the sil9022 HDMI interface chip.
>>
>>   drivers/video/omap2/displays/Kconfig         |    8 +
>>   drivers/video/omap2/displays/Makefile        |    1 +
>>   drivers/video/omap2/displays/panel-sil9022.c | 1274 ++++++++++++++++++++++++++
>>   drivers/video/omap2/displays/panel-sil9022.h |  527 +++++++++++
>>   4 files changed, 1810 insertions(+)
>>   create mode 100644 drivers/video/omap2/displays/panel-sil9022.c
>>   create mode 100644 drivers/video/omap2/displays/panel-sil9022.h
> What about making this driver more general. We've tested this HDMI
> chip on am335x and there are also Freescal based devices using this
> chip (http://www.genesi-tech.com/products/efika and kernel repo
> http://github.com/genesi/linux-legacy).
Currently the panel driver is tied to the OMAPDSS and hence making
this driver more generic is a difficult job.
But the Common Display Framework (CDF) will surely help us in future
to get drivers like this easy to port across different platforms.
In the future, will make this driver part of CDF to help in making it 
more general.
Regards,
  Sathya Prakash M R
> Yegor


^ permalink raw reply

* Re: [V3 2/7] ARM: mmp: remove the legacy rbswap setting for ttc_dkb platform
From: Haojian Zhuang @ 2013-07-09 10:41 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1372332524-6772-1-git-send-email-jtzhou@marvell.com>

On Thu, Jun 27, 2013 at 7:28 PM, Jett.Zhou <jtzhou@marvell.com> wrote:
> According to new rbswap scheme of mmp_display, it support appropriate
> rbswap setting based specific pix_fmt, then we can remove the legacy
> rbswap setting for ttc_dkb platform.
>
> Signed-off-by: Jett.Zhou <jtzhou@marvell.com>
> ---
>  arch/arm/mach-mmp/ttc_dkb.c |    4 +---
>  1 files changed, 1 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm/mach-mmp/ttc_dkb.c b/arch/arm/mach-mmp/ttc_dkb.c
> index 8483906..cb08485 100644
> --- a/arch/arm/mach-mmp/ttc_dkb.c
> +++ b/arch/arm/mach-mmp/ttc_dkb.c
> @@ -191,7 +191,6 @@ static struct pxa3xx_nand_platform_data dkb_nand_info = {
>  #define SCLK_SOURCE_SELECT(x)  (x << 30) /* 0x0 ~ 0x3 */
>  /* link config */
>  #define CFG_DUMBMODE(mode)     (mode << 28) /* 0x0 ~ 0x6*/
> -#define CFG_GRA_SWAPRB(x)      (x << 0) /* 1: rbswap enabled */
>  static struct mmp_mach_path_config dkb_disp_config[] = {
>         [0] = {
>                 .name = "mmp-parallel",
> @@ -199,8 +198,7 @@ static struct mmp_mach_path_config dkb_disp_config[] = {
>                 .output_type = PATH_OUT_PARALLEL,
>                 .path_config = CFG_IOPADMODE(0x1)
>                         | SCLK_SOURCE_SELECT(0x1),
> -               .link_config = CFG_DUMBMODE(0x2)
> -                       | CFG_GRA_SWAPRB(0x1),
> +               .link_config = CFG_DUMBMODE(0x2),
>         },
>  };
>
> --
> 1.7.0.4
>

Acked-by: Haojian Zhuang <haojian.zhuang@gmail.com>

^ permalink raw reply

* Re: [PATCH 1/1] OMAPDSS: Add sil9022 driver
From: Yegor Yefremov @ 2013-07-09  9:37 UTC (permalink / raw)
  To: Sathya Prakash M R
  Cc: Valkeinen, Tomi, archit, linux-omap, linux-fbdev,
	Srinivas Pulukuru
In-Reply-To: <1373360825-25170-1-git-send-email-sathyap@ti.com>

On Tue, Jul 9, 2013 at 11:07 AM, Sathya Prakash M R <sathyap@ti.com> wrote:
> From: Srinivas Pulukuru <srinivas.pulukuru@ti.com>
>
> Add driver for SIL9022 DPI-to-HDMI chip.
>
> Signed-off-by: Srinivas Pulukuru <srinivas.pulukuru@ti.com>
> [sathyap@ti.com: Ported the driver from 2.6.32 based internal
> kernel to v3.10 kernel]
> Signed-off-by: Sathya Prakash M R <sathyap@ti.com>
> ---
> This patch was tested using the legacy OMAP3630 based Zoom3 platform.
> There is no DT support for Zoom , hence board file changes
> made locally were used for validation purpose.
> Further, DT support will be added for a newer SOC which uses
> the sil9022 HDMI interface chip.
>
>  drivers/video/omap2/displays/Kconfig         |    8 +
>  drivers/video/omap2/displays/Makefile        |    1 +
>  drivers/video/omap2/displays/panel-sil9022.c | 1274 ++++++++++++++++++++++++++
>  drivers/video/omap2/displays/panel-sil9022.h |  527 +++++++++++
>  4 files changed, 1810 insertions(+)
>  create mode 100644 drivers/video/omap2/displays/panel-sil9022.c
>  create mode 100644 drivers/video/omap2/displays/panel-sil9022.h

What about making this driver more general. We've tested this HDMI
chip on am335x and there are also Freescal based devices using this
chip (http://www.genesi-tech.com/products/efika and kernel repo
http://github.com/genesi/linux-legacy).

Yegor

^ permalink raw reply

* [PATCH 1/1] OMAPDSS: Add sil9022 driver
From: Sathya Prakash M R @ 2013-07-09  9:19 UTC (permalink / raw)
  To: tomi.valkeinen
  Cc: archit, linux-omap, linux-fbdev, Srinivas Pulukuru,
	Sathya Prakash M R

From: Srinivas Pulukuru <srinivas.pulukuru@ti.com>

Add driver for SIL9022 DPI-to-HDMI chip.

Signed-off-by: Srinivas Pulukuru <srinivas.pulukuru@ti.com>
[sathyap@ti.com: Ported the driver from 2.6.32 based internal
kernel to v3.10 kernel]
Signed-off-by: Sathya Prakash M R <sathyap@ti.com>
---
This patch was tested using the legacy OMAP3630 based Zoom3 platform.
There is no DT support for Zoom , hence board file changes
made locally were used for validation purpose. 
Further, DT support will be added for a newer SOC which uses
the sil9022 HDMI interface chip.

 drivers/video/omap2/displays/Kconfig         |    8 +
 drivers/video/omap2/displays/Makefile        |    1 +
 drivers/video/omap2/displays/panel-sil9022.c | 1274 ++++++++++++++++++++++++++
 drivers/video/omap2/displays/panel-sil9022.h |  527 +++++++++++
 4 files changed, 1810 insertions(+)
 create mode 100644 drivers/video/omap2/displays/panel-sil9022.c
 create mode 100644 drivers/video/omap2/displays/panel-sil9022.h

diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig
index c3853c9..53d8bb7 100644
--- a/drivers/video/omap2/displays/Kconfig
+++ b/drivers/video/omap2/displays/Kconfig
@@ -39,6 +39,14 @@ config PANEL_NEC_NL8048HL11_01B
 		This NEC NL8048HL11-01B panel is TFT LCD
 		used in the Zoom2/3/3630 sdp boards.
 
+config PANEL_SIL9022
+	tristate "HDMI interface"
+        depends on OMAP2_DSS_DPI
+	depends on I2C
+	help
+		Driver for SIL9022 DPI-to-HDMI chip
+		Driver uses i2c to read EDID information.
+
 config PANEL_PICODLP
 	tristate "TI PICO DLP mini-projector"
 	depends on OMAP2_DSS_DPI && I2C
diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile
index 58a5176..34cfa8e 100644
--- a/drivers/video/omap2/displays/Makefile
+++ b/drivers/video/omap2/displays/Makefile
@@ -3,6 +3,7 @@ obj-$(CONFIG_PANEL_TFP410) += panel-tfp410.o
 obj-$(CONFIG_PANEL_LGPHILIPS_LB035Q02) += panel-lgphilips-lb035q02.o
 obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
 obj-$(CONFIG_PANEL_NEC_NL8048HL11_01B) += panel-nec-nl8048hl11-01b.o
+obj-$(CONFIG_PANEL_SIL9022) += panel-sil9022.o
 
 obj-$(CONFIG_PANEL_TAAL) += panel-taal.o
 obj-$(CONFIG_PANEL_PICODLP) +=  panel-picodlp.o
diff --git a/drivers/video/omap2/displays/panel-sil9022.c b/drivers/video/omap2/displays/panel-sil9022.c
new file mode 100644
index 0000000..3b5cb17
--- /dev/null
+++ b/drivers/video/omap2/displays/panel-sil9022.c
@@ -0,0 +1,1274 @@
+/*
+ * drivers/video/omap2/panel-sil9022.c
+ *
+ * Copyright (C) 2009 Texas Instruments
+ *
+ * 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.
+ *
+ * SIL9022 hdmi driver
+ * Owner: kiran Chitriki
+ *
+ */
+
+/***********************************/
+#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 <video/omapdss.h>
+#include <video/omap-panel-data.h>
+#include "panel-sil9022.h"
+
+u16 current_descriptor_addrs;
+
+static struct i2c_client *sil9022_client;
+
+static struct omap_video_timings omap_dss_hdmi_timings = {
+	.x_res          = HDMI_XRES,
+	.y_res          = HDMI_YRES,
+	.pixel_clock    = HDMI_PIXCLOCK_MAX,
+	.hfp            = 110,
+	.hbp            = 220,
+	.hsw            = 40,
+	.vfp            = 5,
+	.vbp            = 20,
+	.vsw            = 5,
+	.vsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
+	.hsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
+	.data_pclk_edge	= OMAPDSS_DRIVE_SIG_RISING_EDGE,
+	.de_level	= OMAPDSS_SIG_ACTIVE_HIGH,
+	.sync_pclk_edge	= OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
+};
+
+static struct hdmi_reg_data  hdmi_tpi_audio_config_data[] = {
+	/* Transmitter is brought to Full operation when value of power
+	 * state register is 0x0 */
+	{ HDMI_TPI_POWER_STATE_CTRL_REG, TPI_AVI_POWER_STATE_D0		 },
+	/* TMDS output lines active. bit 3 1:TMDS inactive, 0: TMDS active */
+	{ HDMI_SYS_CTRL_DATA_REG,  0x01					 },
+	/*HDCP Enable - Disable */
+	{ HDMI_TPI_HDCP_CONTROLDATA_REG, 0				 },
+	/* I2S mode , Mute Enabled , PCM */
+	{ HDMI_TPI_AUDIO_CONFIG_BYTE2_REG, TPI_AUDIO_INTERFACE_I2S |
+					    TPI_AUDIO_MUTE_ENABLE |
+					    TPI_AUDIO_CODING_PCM	 },
+	/* I2S Input configuration register */
+	{ HDMI_TPI_I2S_INPUT_CONFIG_REG, TPI_I2S_SCK_EDGE_RISING |
+					TPI_I2S_MCLK_MULTIPLIER_256 |
+					TPI_I2S_WS_POLARITY_HIGH |
+					TPI_I2S_SD_JUSTIFY_LEFT |
+					TPI_I2S_SD_DIRECTION_MSB_FIRST |
+					TPI_I2S_FIRST_BIT_SHIFT_YES	 },
+	/* I2S Enable ad Mapping Register */
+	{ HDMI_TPI_I2S_ENABLE_MAPPING_REG, TPI_I2S_SD_CHANNEL_ENABLE |
+					    TPI_I2S_SD_FIFO_0 |
+					    TPI_I2S_DOWNSAMPLE_DISABLE |
+					    TPI_I2S_LF_RT_SWAP_NO |
+					    TPI_I2S_SD_CONFIG_SELECT_SD0 },
+	{ HDMI_TPI_I2S_ENABLE_MAPPING_REG, TPI_I2S_SD_CHANNEL_DISABLE |
+					    TPI_I2S_SD_FIFO_1 |
+					    TPI_I2S_DOWNSAMPLE_DISABLE |
+					    TPI_I2S_LF_RT_SWAP_NO |
+					    TPI_I2S_SD_CONFIG_SELECT_SD1 },
+	{ HDMI_TPI_I2S_ENABLE_MAPPING_REG, TPI_I2S_SD_CHANNEL_DISABLE |
+					    TPI_I2S_SD_FIFO_2 |
+					    TPI_I2S_DOWNSAMPLE_DISABLE |
+					    TPI_I2S_LF_RT_SWAP_NO |
+					    TPI_I2S_SD_CONFIG_SELECT_SD2 },
+	{ HDMI_TPI_I2S_ENABLE_MAPPING_REG, TPI_I2S_SD_CHANNEL_DISABLE |
+					    TPI_I2S_SD_FIFO_3 |
+					    TPI_I2S_DOWNSAMPLE_DISABLE |
+					    TPI_I2S_LF_RT_SWAP_NO |
+					    TPI_I2S_SD_CONFIG_SELECT_SD3 },
+	{ HDMI_TPI_AUDIO_CONFIG_BYTE3_REG, TPI_AUDIO_SAMPLE_SIZE_16 |
+					     TPI_AUDIO_FREQ_44KHZ |
+					     TPI_AUDIO_2_CHANNEL	 },
+	/* Speaker Configuration  refer CEA Specification*/
+	{ HDMI_TPI_AUDIO_CONFIG_BYTE4_REG, (0x0 << 0)},
+	/* Stream Header Settings */
+	{ HDMI_TPI_I2S_STRM_HDR_0_REG, I2S_CHAN_STATUS_MODE		 },
+	{ HDMI_TPI_I2S_STRM_HDR_1_REG, I2S_CHAN_STATUS_CAT_CODE	},
+	{ HDMI_TPI_I2S_STRM_HDR_2_REG, I2S_CHAN_SOURCE_CHANNEL_NUM	 },
+	{ HDMI_TPI_I2S_STRM_HDR_3_REG, I2S_CHAN_ACCURACY_N_44_SAMPLING_FS },
+	{ HDMI_TPI_I2S_STRM_HDR_4_REG, I2S_CHAN_ORIGIN_FS_N_SAMP_LENGTH  },
+	/*     Infoframe data Select  */
+	{ HDMI_CPI_MISC_IF_SELECT_REG, HDMI_INFOFRAME_TX_ENABLE |
+					HDMI_INFOFRAME_TX_REPEAT |
+					HDMI_AUDIO_INFOFRAME		 },
+};
+
+static u8 misc_audio_info_frame_data[] = {
+	MISC_INFOFRAME_TYPE | MISC_INFOFRAME_ALWAYS_SET,
+	MISC_INFOFRAME_VERSION,
+	MISC_INFOFRAME_LENGTH,
+	0,				/* Checksum byte*/
+	HDMI_SH_PCM | HDMI_SH_TWO_CHANNELS,
+	HDMI_SH_44KHz | HDMI_SH_16BIT,	/* 44.1 KHz*/
+	0x0,   /* Default 0*/
+	HDMI_SH_SPKR_FLFR,
+	HDMI_SH_0dB_ATUN | 0x1,		/* 0 dB  Attenuation*/
+	0x0,
+	0x0,
+	0x0,
+	0x0,
+	0x0
+};
+
+static u8 avi_info_frame_data[] = {
+	0x00,
+	0x00,
+	0xA8,
+	0x00,
+	0x04,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00
+};
+
+void get_horz_vert_timing_info(u8 *edid)
+{
+	/*HORIZONTAL FRONT PORCH */
+	omap_dss_hdmi_timings.hfp = edid[current_descriptor_addrs + 8];
+	/*HORIZONTAL SYNC WIDTH */
+	omap_dss_hdmi_timings.hsw = edid[current_descriptor_addrs + 9];
+	/*HORIZONTAL BACK PORCH */
+	omap_dss_hdmi_timings.hbp = (((edid[current_descriptor_addrs + 4]
+					  & 0x0F) << 8) |
+					edid[current_descriptor_addrs + 3]) -
+		(omap_dss_hdmi_timings.hfp + omap_dss_hdmi_timings.hsw);
+	/*VERTICAL FRONT PORCH */
+	omap_dss_hdmi_timings.vfp = ((edid[current_descriptor_addrs + 10] &
+				       0xF0) >> 4);
+	/*VERTICAL SYNC WIDTH */
+	omap_dss_hdmi_timings.vsw = (edid[current_descriptor_addrs + 10] &
+				      0x0F);
+	/*VERTICAL BACK PORCH */
+	omap_dss_hdmi_timings.vbp = (((edid[current_descriptor_addrs + 7] &
+					0x0F) << 8) |
+				      edid[current_descriptor_addrs + 6]) -
+		(omap_dss_hdmi_timings.vfp + omap_dss_hdmi_timings.vsw);
+
+	dev_dbg(&sil9022_client->dev, "<%s>\n"
+				       "hfp			= %d\n"
+				       "hsw			= %d\n"
+				       "hbp			= %d\n"
+				       "vfp			= %d\n"
+				       "vsw			= %d\n"
+				       "vbp			= %d\n",
+		 __func__,
+		 omap_dss_hdmi_timings.hfp,
+		 omap_dss_hdmi_timings.hsw,
+		 omap_dss_hdmi_timings.hbp,
+		 omap_dss_hdmi_timings.vfp,
+		 omap_dss_hdmi_timings.vsw,
+		 omap_dss_hdmi_timings.vbp
+		 );
+
+}
+
+void get_edid_timing_data(u8 *edid, u16 *pixel_clk, u16 *horizontal_res,
+			  u16 *vertical_res)
+{
+	u8 offset, effective_addrs;
+	u8 count;
+	u8 i;
+	u8 flag = false;
+	/*check for 720P timing in block0 */
+	for (count = 0; count < EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR; count++) {
+		current_descriptor_addrs +			EDID_DESCRIPTOR_BLOCK0_ADDRESS +
+			count * EDID_TIMING_DESCRIPTOR_SIZE;
+		*horizontal_res +			(((edid[EDID_DESCRIPTOR_BLOCK0_ADDRESS + 4 +
+			   count * EDID_TIMING_DESCRIPTOR_SIZE] & 0xF0) << 4) |
+			 edid[EDID_DESCRIPTOR_BLOCK0_ADDRESS + 2 +
+			 count * EDID_TIMING_DESCRIPTOR_SIZE]);
+		*vertical_res +			(((edid[EDID_DESCRIPTOR_BLOCK0_ADDRESS + 7 +
+			   count * EDID_TIMING_DESCRIPTOR_SIZE] & 0xF0) << 4) |
+			 edid[EDID_DESCRIPTOR_BLOCK0_ADDRESS + 5 +
+			 count * EDID_TIMING_DESCRIPTOR_SIZE]);
+
+		dev_dbg(&sil9022_client->dev,
+			"<%s> ***Block-0-Timing-descriptor[%d]***\n",
+			__func__, count);
+		for (i = current_descriptor_addrs;
+		      i <
+		      (current_descriptor_addrs+EDID_TIMING_DESCRIPTOR_SIZE);
+		      i++)
+			dev_dbg(&sil9022_client->dev,
+				"%x =>		%x\n", i, edid[i]);
+
+			dev_dbg(&sil9022_client->dev,
+				 "<%s>\n"
+				 "E-EDID Buffer Index	= %d\n"
+				 "horizontal_res	= %d\n"
+				 "vertical_res		= %d\n",
+				 __func__,
+				 current_descriptor_addrs,
+				 *horizontal_res,
+				 *vertical_res
+				 );
+
+		if (*horizontal_res = HDMI_XRES &&
+		    *vertical_res = HDMI_YRES) {
+			dev_info(&sil9022_client->dev,
+				"<%s>\nFound EDID Data for %d x %dp\n",
+				 __func__, *horizontal_res, *vertical_res);
+			flag = true;
+			break;
+			}
+	}
+
+	/*check for the Timing in block1 */
+	if (flag != true) {
+		offset = edid[EDID_DESCRIPTOR_BLOCK1_ADDRESS + 2];
+		if (offset != 0) {
+			effective_addrs = EDID_DESCRIPTOR_BLOCK1_ADDRESS
+				+ offset;
+			/*to determine the number of descriptor blocks */
+			for (count = 0;
+			      count < EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR;
+			      count++) {
+				current_descriptor_addrs = effective_addrs +
+					count * EDID_TIMING_DESCRIPTOR_SIZE;
+				*horizontal_res +					(((edid[effective_addrs + 4 +
+					   count*EDID_TIMING_DESCRIPTOR_SIZE] &
+					   0xF0) << 4) |
+					 edid[effective_addrs + 2 +
+					 count * EDID_TIMING_DESCRIPTOR_SIZE]);
+				*vertical_res +					(((edid[effective_addrs + 7 +
+					   count*EDID_TIMING_DESCRIPTOR_SIZE] &
+					   0xF0) << 4) |
+					 edid[effective_addrs + 5 +
+					 count * EDID_TIMING_DESCRIPTOR_SIZE]);
+
+				dev_dbg(&sil9022_client->dev,
+					 "<%s> Block1-Timing-descriptor[%d]\n",
+					 __func__, count);
+
+				for (i = current_descriptor_addrs;
+				      i < (current_descriptor_addrs+
+					   EDID_TIMING_DESCRIPTOR_SIZE); i++)
+					dev_dbg(&sil9022_client->dev,
+						"%x =>		%x\n",
+						   i, edid[i]);
+
+				dev_dbg(&sil9022_client->dev, "<%s>\n"
+						"current_descriptor	= %d\n"
+						"horizontal_res		= %d\n"
+						"vertical_res		= %d\n",
+					 __func__, current_descriptor_addrs,
+					 *horizontal_res, *vertical_res);
+
+				if (*horizontal_res = HDMI_XRES &&
+				    *vertical_res = HDMI_YRES) {
+					dev_info(&sil9022_client->dev,
+						 "<%s> Found EDID Data for "
+						 "%d x %dp\n",
+						 __func__,
+						 *horizontal_res,
+						 *vertical_res
+						 );
+					flag = true;
+					break;
+					}
+			}
+		}
+	}
+
+	if (flag = true) {
+		*pixel_clk = ((edid[current_descriptor_addrs + 1] << 8) |
+			     edid[current_descriptor_addrs]);
+
+		omap_dss_hdmi_timings.x_res = *horizontal_res;
+		omap_dss_hdmi_timings.y_res = *vertical_res;
+		omap_dss_hdmi_timings.pixel_clock = *pixel_clk*10;
+		dev_dbg(&sil9022_client->dev,
+			 "EDID TIMING DATA supported by zoom2 FOUND\n"
+			 "EDID DTD block address	= %d\n"
+			 "pixel_clk			= %d\n"
+			 "horizontal res		= %d\n"
+			 "vertical res			= %d\n",
+			 current_descriptor_addrs,
+			 omap_dss_hdmi_timings.pixel_clock,
+			 omap_dss_hdmi_timings.x_res,
+			 omap_dss_hdmi_timings.y_res
+			 );
+
+		get_horz_vert_timing_info(edid);
+	} else {
+
+		dev_info(&sil9022_client->dev,
+			 "<%s>\n"
+			 "EDID TIMING DATA supported by zoom2 NOT FOUND\n"
+			 "setting default timing values for 720p\n"
+			 "pixel_clk		= %d\n"
+			 "horizontal res	= %d\n"
+			 "vertical res		= %d\n",
+			 __func__,
+			 omap_dss_hdmi_timings.pixel_clock,
+			 omap_dss_hdmi_timings.x_res,
+			 omap_dss_hdmi_timings.y_res
+			 );
+
+		*pixel_clk = omap_dss_hdmi_timings.pixel_clock;
+		*horizontal_res = omap_dss_hdmi_timings.x_res;
+		*vertical_res = omap_dss_hdmi_timings.y_res;
+	}
+
+
+}
+
+
+static int
+sil9022_blockwrite_reg(struct i2c_client *client,
+				  u8 reg, u16 alength, u8 *val, u16 *out_len)
+{
+	int err = 0, i;
+	struct i2c_msg msg[1];
+	u8 data[2];
+
+	if (!client->adapter) {
+		dev_err(&client->dev, "<%s> ERROR: No HDMI Device\n", __func__);
+		return -ENODEV;
+	}
+
+	msg->addr = client->addr;
+	msg->flags = I2C_M_WR;
+	msg->len = 2;
+	msg->buf = data;
+
+	/* high byte goes out first */
+	data[0] = reg >> 8;
+
+	for (i = 0; i < alength - 1; i++) {
+		data[1] = val[i];
+		err = i2c_transfer(client->adapter, msg, 1);
+		udelay(50);
+		dev_dbg(&client->dev, "<%s> i2c Block write at 0x%x, "
+				      "*val=%d flags=%d byte[%d] err=%d\n",
+			__func__, data[0], data[1], msg->flags, i, err);
+		if (err < 0)
+			break;
+	}
+	/* set the number of bytes written*/
+	*out_len = i;
+
+	if (err < 0) {
+		dev_err(&client->dev, "<%s> ERROR:  i2c Block Write at 0x%x, "
+				      "*val=%d flags=%d bytes written=%d "
+				      "err=%d\n",
+			__func__, data[0], data[1], msg->flags, i, err);
+		return err;
+	}
+	return 0;
+}
+
+static int
+sil9022_blockread_reg(struct i2c_client *client,
+		      u16 data_length, u16 alength,
+		      u8 reg, u8 *val, u16 *out_len)
+{
+	int err = 0, i;
+	struct i2c_msg msg[1];
+	u8 data[2];
+
+	if (!client->adapter) {
+		dev_err(&client->dev, "<%s> ERROR: No HDMI Device\n", __func__);
+		return -ENODEV;
+	}
+
+	msg->addr = client->addr;
+	msg->flags = I2C_M_WR;
+	msg->len = 1;
+	msg->buf = data;
+
+	/* High byte goes out first */
+	data[0] = reg;
+	err = i2c_transfer(client->adapter, msg, 1);
+	dev_dbg(&client->dev, "<%s> i2c Block Read1 at 0x%x, "
+			       "*val=%d flags=%d err=%d\n",
+		 __func__, data[0], data[1], msg->flags, err);
+
+	for (i = 0; i < alength; i++) {
+		if (err >= 0) {
+			mdelay(3);
+			msg->flags = I2C_M_RD;
+			msg->len = data_length;
+			err = i2c_transfer(client->adapter, msg, 1);
+		} else
+			break;
+		if (err >= 0) {
+			val[i] = 0;
+			/* High byte comes first */
+			if (data_length = 1)
+				val[i] = data[0];
+			else if (data_length = 2)
+				val[i] = data[1] + (data[0] << 8);
+			dev_dbg(&client->dev, "<%s> i2c Block Read2 at 0x%x, "
+					       "*val=%d flags=%d byte=%d "
+					       "err=%d\n",
+				 __func__, reg, val[i], msg->flags, i, err);
+		} else
+			break;
+	}
+	*out_len = i;
+	dev_dbg(&client->dev, "<%s> i2c Block Read at 0x%x, bytes read = %d\n",
+		__func__, client->addr, *out_len);
+
+	if (err < 0) {
+		dev_err(&client->dev, "<%s> ERROR:  i2c Read at 0x%x, "
+				      "*val=%d flags=%d bytes read=%d err=%d\n",
+			__func__, reg, *val, msg->flags, i, err);
+		return err;
+	}
+	return 0;
+}
+
+
+/* Write a value to a register in sil9022 device.
+ * @client: i2c driver client structure.
+ * @reg: Address of the register to read value from.
+ * @val: Value to be written to a specific register.
+ * Returns zero if successful, or non-zero otherwise.
+ */
+static int
+sil9022_write_reg(struct i2c_client *client, u8 reg, u8 val)
+{
+	int err = 0;
+	struct i2c_msg msg[1];
+	u8 data[2];
+	int retries = 0;
+
+	if (!client->adapter) {
+		dev_err(&client->dev, "<%s> ERROR: No HDMI Device\n", __func__);
+		return -ENODEV;
+	}
+
+retry:
+	msg->addr = client->addr;
+	msg->flags = I2C_M_WR;
+	msg->len = 2;
+	msg->buf = data;
+
+	data[0] = reg;
+	data[1] = val;
+
+	err = i2c_transfer(client->adapter, msg, 1);
+	dev_dbg(&client->dev, "<%s> i2c write at=%x "
+			       "val=%x flags=%d err=%d\n",
+		__func__, data[0], data[1], msg->flags, err);
+	udelay(50);
+
+	if (err >= 0)
+		return 0;
+
+	dev_err(&client->dev, "<%s> ERROR: i2c write at=%x "
+			       "val=%x flags=%d err=%d\n",
+		__func__, data[0], data[1], msg->flags, err);
+	if (retries <= 5) {
+		dev_info(&client->dev, "Retrying I2C... %d\n", retries);
+		retries++;
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(msecs_to_jiffies(20));
+		goto retry;
+	}
+	return err;
+}
+
+/*
+ * Read a value from a register in sil9022 device.
+ * The value is returned in 'val'.
+ * Returns zero if successful, or non-zero otherwise.
+ */
+static int
+sil9022_read_reg(struct i2c_client *client, u16 data_length, u8 reg, u8 *val)
+{
+	int err = 0;
+	struct i2c_msg msg[1];
+	u8 data[2];
+
+	if (!client->adapter) {
+		dev_err(&client->dev, "<%s> ERROR: No HDMI Device\n", __func__);
+		return -ENODEV;
+	}
+
+	msg->addr = client->addr;
+	msg->flags = I2C_M_WR;
+	msg->len = 1;
+	msg->buf = data;
+
+	data[0] = reg;
+	err = i2c_transfer(client->adapter, msg, 1);
+	dev_dbg(&client->dev, "<%s> i2c Read1 reg=%x val=%d "
+			       "flags=%d err=%d\n",
+		__func__, reg, data[1], msg->flags, err);
+
+	if (err >= 0) {
+		mdelay(3);
+		msg->flags = I2C_M_RD;
+		msg->len = data_length;
+		err = i2c_transfer(client->adapter, msg, 1);
+	}
+
+	if (err >= 0) {
+		*val = 0;
+		if (data_length = 1)
+			*val = data[0];
+		else if (data_length = 2)
+			*val = data[1] + (data[0] << 8);
+		dev_dbg(&client->dev, "<%s> i2c Read2 at 0x%x, *val=%d "
+				       "flags=%d err=%d\n",
+			 __func__, reg, *val, msg->flags, err);
+		return 0;
+	}
+
+	dev_err(&client->dev, "<%s> ERROR: i2c Read at 0x%x, "
+			      "*val=%d flags=%d err=%d\n",
+		__func__, reg, *val, msg->flags, err);
+	return err;
+}
+
+static int
+sil9022_read_edid(struct i2c_client *client, u16 len,
+	       char *p_buffer, u16 *out_len)
+{
+	int err =  0;
+	u8 val = 0;
+	int retries = 0;
+	int i = 0;
+	int k = 0;
+
+	len = (len < HDMI_EDID_MAX_LENGTH) ? len : HDMI_EDID_MAX_LENGTH;
+
+	/* Request DDC bus access to read EDID info from HDTV */
+	dev_info(&client->dev, "<%s> Reading HDMI EDID\n", __func__);
+
+	/* Bring transmitter to low-Power state */
+	val = TPI_AVI_POWER_STATE_D2;
+	err = sil9022_write_reg(client, HDMI_TPI_DEVICE_POWER_STATE_DATA, val);
+	if (err < 0) {
+		dev_err(&client->dev,
+			"<%s> ERROR: Failed during bring power state - low.\n",
+			 __func__);
+		return err;
+	}
+
+	/* Disable TMDS clock */
+	val = 0x11;
+	err = sil9022_write_reg(client, HDMI_SYS_CTRL_DATA_REG, val);
+	if (err < 0) {
+		dev_err(&client->dev,
+			"<%s> ERROR: Failed during bring power state - low.\n",
+			 __func__);
+		return err;
+	}
+
+	val = 0;
+	/* Read TPI system control register*/
+	err = sil9022_read_reg(client, 1, HDMI_SYS_CTRL_DATA_REG, &val);
+	if (err < 0) {
+		dev_err(&client->dev,
+			"<%s> ERROR: Reading DDC BUS REQUEST\n", __func__);
+		return err;
+	}
+
+	/* The host writes 0x1A[2]=1 to request the
+	 * DDC(Display Data Channel) bus
+	 */
+	val |= TPI_SYS_CTRL_DDC_BUS_REQUEST;
+	err = sil9022_write_reg(client, HDMI_SYS_CTRL_DATA_REG, val);
+	if (err < 0) {
+		dev_err(&client->dev,
+			"<%s> ERROR: Writing DDC BUS REQUEST\n", __func__);
+		return err;
+	}
+
+	 /*  Poll for bus DDC Bus control to be granted */
+	dev_info(&client->dev, "<%s> Poll for DDC bus access\n", __func__);
+	val = 0;
+	do {
+		err = sil9022_read_reg(client, 1, HDMI_SYS_CTRL_DATA_REG, &val);
+		if (retries++ > 100)
+			return err;
+
+	} while ((val & TPI_SYS_CTRL_DDC_BUS_GRANTED) = 0);
+
+	/*  Close the switch to the DDC */
+	val |= TPI_SYS_CTRL_DDC_BUS_REQUEST | TPI_SYS_CTRL_DDC_BUS_GRANTED;
+	err = sil9022_write_reg(client, HDMI_SYS_CTRL_DATA_REG, val);
+	if (err < 0) {
+		dev_err(&client->dev,
+			"<%s> ERROR: Close switch to DDC BUS REQUEST\n",
+			__func__);
+		return err;
+	}
+
+	memset(p_buffer, 0, len);
+	/* change I2C SetSlaveAddress to HDMI_I2C_MONITOR_ADDRESS */
+	/*  Read the EDID structure from the monitor I2C address  */
+	client->addr = HDMI_I2C_MONITOR_ADDRESS;
+	err = sil9022_blockread_reg(client, 1, len,
+				    0x00, p_buffer, out_len);
+	if (err < 0 || *out_len <= 0) {
+		dev_err(&client->dev,
+			"<%s> ERROR: Reading EDID from "
+			"HDMI_I2C_MONITOR_ADDRESS\n", __func__);
+		return err;
+	}
+
+	for (i = 0; i < *out_len; i++) {
+		if ((i / 18) < 3) {
+			dev_dbg(&client->dev, "byte->%02x	%x\n",
+				i, p_buffer[i]);
+			continue;
+		}
+		if ((i/18 >= 3 && i/18 <= 6) && (i%18 = 0))
+			dev_dbg(&client->dev, "\n DTD Block %d\n", k++);
+
+		if ((i/18 = 7) && (i%18 = 0))
+			dev_dbg(&client->dev, "\n");
+
+		dev_dbg(&client->dev, "byte->%02x	%x\n", i, p_buffer[i]);
+	}
+
+	/* Release DDC bus access */
+	client->addr = SI9022_I2CSLAVEADDRESS;
+	val &= ~(TPI_SYS_CTRL_DDC_BUS_REQUEST | TPI_SYS_CTRL_DDC_BUS_GRANTED);
+	err = sil9022_write_reg(client, HDMI_SYS_CTRL_DATA_REG, val);
+
+	if (err < 0) {
+		dev_err(&client->dev,
+			"<%s> ERROR: Releasing DDC  Bus Access\n",
+			__func__);
+		return err;
+		}
+
+	/*  Success */
+	return 0;
+}
+
+static int
+sil9022_enable_audio(struct i2c_client *client)
+{
+	int err = 0;
+	u8  val = 0;
+	u8  crc = 0;
+	u32 count = 0;
+	int index = 0;
+
+	for (index = 0;
+	      index < sizeof(hdmi_tpi_audio_config_data) /
+	      sizeof(struct hdmi_reg_data);
+	      index++) {
+		err = sil9022_write_reg(
+			client,
+			hdmi_tpi_audio_config_data[index].reg_offset,
+			hdmi_tpi_audio_config_data[index].value);
+		if (err != 0) {
+			dev_err(&client->dev,
+				"<%s> ERROR: Writing "
+				"tpi_audio_config_data[%d]={ %d, %d }\n",
+				__func__, index,
+				hdmi_tpi_audio_config_data[index].reg_offset,
+				hdmi_tpi_audio_config_data[index].value);
+			return err;
+			}
+		}
+
+	/* Fill the checksum byte for Infoframe data*/
+	count = 0;
+	while (count < MISC_INFOFRAME_SIZE_MEMORY) {
+		crc += misc_audio_info_frame_data[count];
+		count++;
+	}
+	crc = 0x100 - crc;
+
+	/* Fill CRC Byte*/
+	misc_audio_info_frame_data[0x3] = crc;
+
+	for (count = 0; count < MISC_INFOFRAME_SIZE_MEMORY; count++) {
+		err = sil9022_write_reg(client,
+					(HDMI_CPI_MISC_IF_OFFSET + count),
+					misc_audio_info_frame_data[count]);
+		if (err < 0) {
+			dev_err(&client->dev,
+				"<%s> ERROR: writing audio info frame"
+				" CRC data: %d\n", __func__, count);
+			return err;
+		}
+	}
+
+	/* Decode Level 0 Packets */
+	val = 0x2;
+	sil9022_write_reg(client, 0xBC, val);
+	if (err < 0) {
+		dev_err(&client->dev,
+			"<%s> ERROR: writing level 0 packets to 0xBC\n",
+			__func__);
+		return err;
+	}
+
+	val = 0x24;
+	err = sil9022_write_reg(client, 0xBD, val);
+	if (err < 0) {
+		dev_err(&client->dev,
+			"<%s> ERROR: writing level 0 packets to 0xBD\n",
+			__func__);
+		return err;
+	}
+
+	val = 0x2;
+	err = sil9022_write_reg(client, 0xBE, val);
+	if (err < 0) {
+		dev_err(&client->dev,
+			"<%s> ERROR: writing level 0 packets to 0xBE\n",
+			__func__);
+		return err;
+	}
+
+	/* Disable Mute */
+	val = TPI_AUDIO_INTERFACE_I2S |
+		  TPI_AUDIO_MUTE_DISABLE |
+		  TPI_AUDIO_CODING_PCM;
+	err = sil9022_write_reg(client, HDMI_TPI_AUDIO_CONFIG_BYTE2_REG, val);
+	if (err < 0) {
+		dev_err(&client->dev,
+			"<%s> ERROR: Disabling mute\n",
+			__func__);
+		return err;
+	}
+
+	dev_info(&client->dev, "<%s> hdmi audio enabled\n",
+		__func__);
+	return 0;
+
+}
+
+static int
+sil9022_disable_audio(struct i2c_client *client)
+{
+	u8 val = 0;
+	int err = 0;
+	/* Disable Audio */
+	val = TPI_AUDIO_INTERFACE_DISABLE;
+	err = sil9022_write_reg(client, HDMI_TPI_AUDIO_CONFIG_BYTE2_REG, val);
+	if (err < 0)
+		dev_err(&client->dev,
+			"<%s> ERROR: Disisable audio interface", __func__);
+
+	dev_info(&client->dev, "<%s> hdmi audio disabled\n", __func__);
+	return err;
+}
+
+static int
+sil9022_enable(struct omap_dss_device *dssdev)
+{
+	int		err;
+	u8		val, vals[14];
+	int		i;
+	u16		out_len = 0;
+	u8		edid[HDMI_EDID_MAX_LENGTH];
+	u16		horizontal_res;
+	u16		vertical_res;
+	u16		pixel_clk;
+
+	memset(edid, 0, HDMI_EDID_MAX_LENGTH);
+	memset(vals, 0, 14);
+
+	err = sil9022_read_edid(sil9022_client, HDMI_EDID_MAX_LENGTH,
+			     edid, &out_len);
+	if (err < 0 || out_len = 0) {
+		dev_err(&sil9022_client->dev,
+			"<%s> Unable to read EDID for monitor\n", __func__);
+		return err;
+	}
+
+	get_edid_timing_data(edid,
+			     &pixel_clk,
+			     &horizontal_res,
+			     &vertical_res
+			     );
+
+	/*  Fill the TPI Video Mode Data structure */
+	vals[0] = (pixel_clk & 0xFF);                  /* Pixel clock */
+	vals[1] = ((pixel_clk & 0xFF00) >> 8);
+	vals[2] = VERTICAL_FREQ;                    /* Vertical freq */
+	vals[3] = 0x00;
+	vals[4] = (horizontal_res & 0xFF);         /* Horizontal pixels*/
+	vals[5] = ((horizontal_res & 0xFF00) >> 8);
+	vals[6] = (vertical_res & 0xFF);           /* Vertical pixels */
+	vals[7] = ((vertical_res & 0xFF00) >> 8);
+
+	dev_info(&sil9022_client->dev, "<%s>\nHDMI Monitor E-EDID Timing Data\n"
+				       "horizontal_res	= %d\n"
+				       "vertical_res	= %d\n"
+				       "pixel_clk	= %d\n"
+				       "hfp		= %d\n"
+				       "hsw		= %d\n"
+				       "hbp		= %d\n"
+				       "vfp		= %d\n"
+				       "vsw		= %d\n"
+				       "vbp		= %d\n",
+		 __func__,
+		 omap_dss_hdmi_timings.x_res,
+		 omap_dss_hdmi_timings.y_res,
+		 omap_dss_hdmi_timings.pixel_clock,
+		 omap_dss_hdmi_timings.hfp,
+		 omap_dss_hdmi_timings.hsw,
+		 omap_dss_hdmi_timings.hbp,
+		 omap_dss_hdmi_timings.vfp,
+		 omap_dss_hdmi_timings.vsw,
+		 omap_dss_hdmi_timings.vbp
+		 );
+
+	dssdev->panel.timings = omap_dss_hdmi_timings;
+	/*  Write out the TPI Video Mode Data */
+	out_len = 0;
+	err = sil9022_blockwrite_reg(sil9022_client,
+				     HDMI_TPI_VIDEO_DATA_BASE_REG,
+				     8, vals, &out_len);
+	if (err < 0) {
+		dev_err(&sil9022_client->dev,
+			"<%s> ERROR: writing TPI video mode data\n", __func__);
+		return err;
+	}
+
+	/* Write out the TPI Pixel Repetition Data (24 bit wide bus,
+	falling edge, no pixel replication) */
+	val = TPI_AVI_PIXEL_REP_BUS_24BIT |
+		TPI_AVI_PIXEL_REP_FALLING_EDGE |
+		TPI_AVI_PIXEL_REP_NONE;
+	err = sil9022_write_reg(sil9022_client,
+				HDMI_TPI_PIXEL_REPETITION_REG,
+				val);
+	if (err < 0) {
+		dev_err(&sil9022_client->dev,
+			"<%s> ERROR: writing TPI pixel repetition data\n",
+			__func__);
+		return err;
+	}
+
+	 /*  Write out the TPI AVI Input Format */
+	val = TPI_AVI_INPUT_BITMODE_8BIT |
+		TPI_AVI_INPUT_RANGE_AUTO |
+		TPI_AVI_INPUT_COLORSPACE_RGB;
+	err = sil9022_write_reg(sil9022_client,
+				HDMI_TPI_AVI_IN_FORMAT_REG,
+				val);
+	if (err < 0) {
+		dev_err(&sil9022_client->dev,
+			"<%s> ERROR: writing TPI AVI Input format\n", __func__);
+		return err;
+	}
+
+	/*  Write out the TPI AVI Output Format */
+	val = TPI_AVI_OUTPUT_CONV_BT709 |
+		TPI_AVI_OUTPUT_RANGE_AUTO |
+		TPI_AVI_OUTPUT_COLORSPACE_RGBHDMI;
+	err = sil9022_write_reg(sil9022_client,
+				HDMI_TPI_AVI_OUT_FORMAT_REG, val);
+	if (err < 0) {
+		dev_err(&sil9022_client->dev,
+			"<%s> ERROR: writing TPI AVI output format\n",
+			__func__);
+		return err;
+	}
+
+	/* Write out the TPI System Control Data to power down */
+	val = TPI_SYS_CTRL_POWER_DOWN;
+	err = sil9022_write_reg(sil9022_client, HDMI_SYS_CTRL_DATA_REG, val);
+	if (err < 0) {
+		dev_err(&sil9022_client->dev,
+			"<%s> ERROR: writing TPI power down control data\n",
+			__func__);
+		return err;
+	}
+
+	/* Write out the TPI AVI InfoFrame Data (all defaults) */
+	/* Compute CRC*/
+	val = 0x82 + 0x02 + 13;
+
+	for (i = 0; i < sizeof(avi_info_frame_data); i++)
+		val += avi_info_frame_data[i];
+
+	avi_info_frame_data[0] = 0x100 - val;
+
+	out_len = 0;
+	err = sil9022_blockwrite_reg(sil9022_client,
+				     HDMI_TPI_AVI_DBYTE_BASE_REG,
+				     sizeof(avi_info_frame_data),
+				     avi_info_frame_data, &out_len);
+	if (err < 0) {
+		dev_err(&sil9022_client->dev,
+			"<%s> ERROR: writing TPI AVI infoframe data\n",
+			__func__);
+		return err;
+	}
+
+	/*  Audio Configuration  */
+	err = sil9022_enable_audio(sil9022_client);
+	if (err < 0) {
+		dev_err(&sil9022_client->dev,
+			"<%s> ERROR: Unable set audio configuration\n",
+			__func__);
+		return err;
+	}
+
+	/*  Write out the TPI Device Power State (D0) */
+	val = TPI_AVI_POWER_STATE_D0;
+	err = sil9022_write_reg(sil9022_client,
+				HDMI_TPI_POWER_STATE_CTRL_REG, val);
+	if (err < 0) {
+		dev_err(&sil9022_client->dev,
+			"<%s> ERROR: Setting device power state to D0\n",
+			__func__);
+		return err;
+	}
+
+	/* Write out the TPI System Control Data to power up and
+	 * select output mode
+	 */
+	val = TPI_SYS_CTRL_POWER_ACTIVE | TPI_SYS_CTRL_OUTPUT_MODE_HDMI;
+	err = sil9022_write_reg(sil9022_client, HDMI_SYS_CTRL_DATA_REG, val);
+	if (err < 0) {
+		dev_err(&sil9022_client->dev,
+			"<%s> ERROR: Writing system control data\n", __func__);
+		return err;
+	}
+
+	/*  Read back TPI System Control Data to latch settings */
+	msleep(20);
+	err = sil9022_read_reg(sil9022_client, 1, HDMI_SYS_CTRL_DATA_REG, &val);
+	if (err < 0) {
+		dev_err(&sil9022_client->dev,
+			"<%s> ERROR: Writing system control data\n",
+			__func__);
+		return err;
+	}
+
+	/* HDCP Enable - Disable */
+	val = 0;
+	err = sil9022_write_reg(sil9022_client,
+				HDMI_TPI_HDCP_CONTROLDATA_REG, val);
+	if (err < 0) {
+		dev_err(&sil9022_client->dev,
+			"<%s> ERROR: Enable (1) / Disable (0) => HDCP: %d\n",
+			__func__, val);
+		return err;
+	}
+
+	dev_info(&sil9022_client->dev, "<%s> hdmi enabled\n", __func__);
+	return 0;
+
+}
+
+static int
+sil9022_disable(void)
+{
+	u8 val = 0;
+	int err = 0;
+
+	err = sil9022_disable_audio(sil9022_client);
+	if (err < 0) {
+		dev_err(&sil9022_client->dev,
+			"<%s> ERROR: failed to disable audio\n", __func__);
+		return err;
+	}
+
+	/*  Write out the TPI System Control Data to power down  */
+	val = TPI_SYS_CTRL_POWER_DOWN;
+	err = sil9022_write_reg(sil9022_client, HDMI_SYS_CTRL_DATA_REG, val);
+	if (err < 0) {
+		dev_err(&sil9022_client->dev,
+			"<%s> ERROR: writing control data - power down\n",
+			__func__);
+		return err;
+	}
+
+	/*  Write out the TPI Device Power State (D2) */
+	val = TPI_AVI_POWER_STATE_D2;
+	err = sil9022_write_reg(sil9022_client,
+			  HDMI_TPI_DEVICE_POWER_STATE_DATA, val);
+	if (err < 0) {
+		dev_err(&sil9022_client->dev,
+			"<%s> ERROR: Setting device power state to D2\n",
+			__func__);
+		return err;
+	}
+
+	/*  Read back TPI System Control Data to latch settings */
+	mdelay(10);
+	err = sil9022_read_reg(sil9022_client, 1, HDMI_SYS_CTRL_DATA_REG, &val);
+	if (err < 0) {
+		dev_err(&sil9022_client->dev,
+			"<%s> ERROR:  Reading System control data "
+			"- latch settings\n", __func__);
+		return err;
+	}
+
+	dev_info(&sil9022_client->dev, "<%s> hdmi disabled\n", __func__);
+	return 0;
+
+}
+
+static int sil9022_set_reg_read_ctrl(struct i2c_client *client)
+{
+	int err = 0;
+	u8 ver;
+
+	/* probe for sil9022 chip version*/
+	err = sil9022_write_reg(client, SI9022_REG_TPI_RQB, 0x00);
+	if (err < 0) {
+		dev_err(&client->dev,
+			"<%s> ERROR: Writing HDMI configuration to "
+			"reg - SI9022_REG_TPI_RQB\n", __func__);
+		err = -ENODEV;
+		goto ERROR1;
+	}
+
+	err = sil9022_read_reg(client, 1, SI9022_REG_CHIPID0, &ver);
+	if (err < 0) {
+		dev_err(&client->dev,
+			"<%s> ERROR: Reading HDMI version Id\n", __func__);
+		err = -ENODEV;
+		goto ERROR1;
+	} else if (ver != SI9022_CHIPID_902x) {
+		dev_err(&client->dev,
+			"<%s> Not a valid verId: 0x%x\n", __func__, ver);
+		err = -ENODEV;
+		goto ERROR1;
+	} else
+		dev_info(&client->dev,
+			 "<%s> sil9022 HDMI Chip version = %x\n",
+			 __func__, ver);
+
+	return 0;
+ERROR1:
+	return err;
+}
+
+static inline struct sil9022_platform_data
+*get_panel_data(const struct omap_dss_device *dssdev)
+{
+	return (struct sil9022_platform_data *) dssdev->data;
+}
+
+
+static int sil9022_panel_probe(struct omap_dss_device *dssdev)
+{
+	struct sil9022_platform_data *sidata = get_panel_data(dssdev);
+	int r;
+	if (!sidata)
+		return -EINVAL;
+
+	dssdev->panel.timings = omap_dss_hdmi_timings;
+
+	if (gpio_is_valid(sidata->res_gpio)) {
+		r = devm_gpio_request_one(&dssdev->dev, sidata->res_gpio,
+				GPIOF_OUT_INIT_HIGH, "HDMI");
+		if (r)
+			return r;
+	}
+
+	return 0;
+}
+
+static void sil9022_panel_remove(struct omap_dss_device *dssdev)
+{
+	omap_dss_unregister_driver(dssdev->driver);
+}
+
+
+static int sil9022_panel_power_on(struct omap_dss_device *dssdev)
+{
+	int r = 0;
+	struct sil9022_platform_data *sidata = get_panel_data(dssdev);
+
+	if (dssdev->state = OMAP_DSS_DISPLAY_ACTIVE)
+		return 0;
+
+	if (gpio_is_valid(sidata->res_gpio))
+		gpio_set_value_cansleep(sidata->res_gpio, 1);
+
+	omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
+	omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
+	r = omapdss_dpi_display_enable(dssdev);
+	return r;
+
+}
+
+static void sil9022_panel_power_off(struct omap_dss_device *dssdev)
+{
+	struct sil9022_platform_data *sidata = get_panel_data(dssdev);
+
+	if (gpio_is_valid(sidata->res_gpio))
+		gpio_set_value_cansleep(sidata->res_gpio, 0);
+	return;
+
+}
+
+static int sil9022_panel_enable(struct omap_dss_device *dssdev)
+{
+	int r = 0;
+
+	r = sil9022_panel_power_on(dssdev);
+	if (r)
+			goto ERROR0;
+	r = sil9022_set_reg_read_ctrl(sil9022_client);
+	if (r)
+		goto ERROR0;
+
+	r = sil9022_enable(dssdev);
+	if (r)
+		goto ERROR0;
+	/* wait couple of vsyncs until enabling the LCD */
+	msleep(50);
+	return 0;
+
+ERROR0:
+	return r;
+}
+
+static void sil9022_panel_disable(struct omap_dss_device *dssdev)
+{
+	sil9022_disable();
+	/* wait couple of vsyncs until enabling the hdmi */
+	msleep(50);
+	sil9022_panel_power_off(dssdev);
+	return;
+}
+
+static struct omap_dss_driver hdmi_driver = {
+	.probe		= sil9022_panel_probe,
+	.remove		= sil9022_panel_remove,
+
+	.enable		= sil9022_panel_enable,
+	.disable		= sil9022_panel_disable,
+
+	.driver         = {
+		.name   = "sil9022_panel",
+		.owner  = THIS_MODULE,
+	},
+};
+
+static int
+sil9022_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+	int err = 0;
+
+	sil9022_client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+	if (!sil9022_client) {
+		err = -ENOMEM;
+		goto ERROR0;
+	}
+	memset(sil9022_client, 0, sizeof(struct i2c_client));
+
+	strncpy(sil9022_client->name, client->name, I2C_NAME_SIZE);
+	sil9022_client->addr = client->addr;
+	sil9022_client->adapter = client->adapter;
+
+	err = sil9022_set_reg_read_ctrl(client);
+	if (err)
+		goto ERROR1;
+
+	omap_dss_register_driver(&hdmi_driver);
+	return 0;
+
+ERROR1:
+	kfree(sil9022_client);
+ERROR0:
+	return err;
+}
+
+
+static int
+sil9022_remove(struct i2c_client *client)
+
+{
+	int err = 0;
+
+	if (!client->adapter) {
+		dev_err(&sil9022_client->dev, "<%s> No HDMI Device\n",
+			__func__);
+		return -ENODEV;
+	}
+	kfree(sil9022_client);
+
+	return err;
+}
+
+static const struct i2c_device_id sil9022_id[] = {
+	{ SIL9022_DRV_NAME, 0 },
+	{ },
+};
+
+MODULE_DEVICE_TABLE(i2c, sil9022_id);
+
+static struct i2c_driver sil9022_driver = {
+	.driver = {
+		.name  = SIL9022_DRV_NAME,
+		.owner = THIS_MODULE,
+		},
+	.probe		= sil9022_probe,
+	.remove		= sil9022_remove,
+	.id_table	= sil9022_id,
+};
+
+static int __init
+sil9022_init(void)
+{
+	int err = 0;
+	err = i2c_add_driver(&sil9022_driver);
+	if (err < 0) {
+		printk(KERN_ERR "<%s> Driver registration failed\n", __func__);
+		err = -ENODEV;
+		goto ERROR0;
+	}
+
+	if (sil9022_client = NULL) {
+		printk(KERN_ERR "<%s> sil9022_client not allocated\n"
+				"<%s> No HDMI Device\n", __func__, __func__);
+		err = -ENODEV;
+		goto ERROR0;
+	}
+	return 0;
+
+ERROR0:
+	return err;
+}
+
+static void __exit
+sil9022_exit(void)
+{
+	i2c_del_driver(&sil9022_driver);
+}
+
+late_initcall(sil9022_init);
+module_exit(sil9022_exit);
+
+MODULE_AUTHOR("Texas Instruments");
+MODULE_DESCRIPTION("SIL9022 HDMI Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-sil9022.h b/drivers/video/omap2/displays/panel-sil9022.h
new file mode 100644
index 0000000..7c920c0
--- /dev/null
+++ b/drivers/video/omap2/displays/panel-sil9022.h
@@ -0,0 +1,527 @@
+/*
+ * drivers/video/omap2/displays/panel-sil9022.c
+ *
+ * Copyright (C) 2009 Texas Instruments
+ *
+ * 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.
+ *
+ * sil9022 hdmi driver
+ */
+#ifndef _SI9022_H_
+#define _SI9022_H_
+
+#define SIL9022_DRV_NAME		"sil9022"
+
+#define CLKOUT2_EN		(0x1 << 7)
+#define CLKOUT2_DIV		(0x4 << 3)
+#define CLKOUT2SOURCE		(0x2 << 0)
+#define CM_CLKOUT_CTRL		0x48004D70
+
+#define HDMI_XRES			1280
+#define HDMI_YRES			720
+#define HDMI_PIXCLOCK_MAX		74250
+#define VERTICAL_FREQ			0x3C
+
+#define I2C_M_WR			0
+
+#define SI9022_USERST_PIN		1
+
+#define SI9022_REG_PIX_CLK_LSB		0x00
+#define SI9022_REG_PIX_CLK_MSB		0x01
+
+#define SI9022_REG_PIX_REPETITION	0x08
+#define SI9022_REG_INPUT_FORMAT		0x09
+#define SI9022_REG_OUTPUT_FORMAT	0x0A
+#define SI9022_REG_SYNC_GEN_CTRL	0x60
+
+#define SI9022_REG_DE_CTRL		0x63
+#define DE_DLY_MSB_BITPOS		0
+#define HSYNCPOL_INVERT_BITPOS		4
+#define VSYNCPOL_INVERT_BITPOS		5
+#define DE_GENERATOR_EN_BITPOS		6
+
+#define SI9022_REG_PWR_STATE		0x1E
+
+#define SI9022_REG_TPI_RQB		0xC7
+
+#define SI9022_REG_INT_PAGE		0xBC
+#define SI9022_REG_OFFSET		0xBD
+#define	SI9022_REG_VALUE		0xBE
+
+#define SI9022_PLLMULT_BITPOS		0x05
+
+#define SI9022_REG_TPI_SYSCTRL		0x1A
+#define I2DDCREQ_BITPOS			2
+#define TMDS_ENABLE_BITPOS		4
+#define HDMI_ENABLE_BITPOS		0
+
+#define SI9022_REG_CHIPID0		0x1B
+#define SI9022_REG_CHIPID1		0x1C
+#define SI9022_REG_CHIPID2		0x1D
+#define SI9022_REG_HDCPVER		0x30
+
+#define SI9022_REG_INTSTATUS		0x3D
+#define HOTPLUG_PENDING_BITPOS		0
+#define RCV_SENSE_PENDING_BITPOS	1
+#define HOTPLUG_SENSE_BITPOS		2
+#define RX_SENSE_BITPOS			3
+#define AUDIO_ERR_PENDING_BITPOS	4
+
+
+#define SI9022_I2CSLAVEADDRESS		0x39
+
+#define SI9022_CHIPID_902x		0xB0
+
+#define SI9022_MAXRETRY			100
+
+#define SI9022_EDID_DETAILED_TIMING_OFFSET	0x36 /*EDID Detailed Timing */
+						/*Info 0 begin offset*/
+#define SI9022_EDID_PIX_CLK_OFFSET		0
+#define SI9022_EDID_H_ACTIVE_OFFSET		2
+#define SI9022_EDID_H_BLANKING_OFFSET		3
+#define SI9022_EDID_V_ACTIVE_OFFSET		5
+#define SI9022_EDID_V_BLANKING_OFFSET		6
+#define SI9022_EDID_H_SYNC_OFFSET		8
+#define SI9022_EDID_H_SYNC_PW_OFFSET		9
+#define SI9022_EDID_V_SYNC_OFFSET		10
+#define SI9022_EDID_V_SYNC_PW_OFFSET		10
+#define SI9022_EDID_H_IMAGE_SIZE_OFFSET		12
+#define SI9022_EDID_V_IMAGE_SIZE_OFFSET		13
+#define SI9022_EDID_H_BORDER_OFFSET		15
+#define SI9022_EDID_V_BORDER_OFFSET		16
+#define SI9022_EDID_FLAGS_OFFSET		17
+
+#define SI9022_PLUG_DETECTED			0xF0
+#define SI9022_UNPLUG_DETECTED			0xF1
+
+
+/* ---------------------------------------------------------------------  */
+#define EDID_TIMING_DESCRIPTOR_SIZE		0x12
+#define EDID_DESCRIPTOR_BLOCK0_ADDRESS		0x36
+#define EDID_DESCRIPTOR_BLOCK1_ADDRESS		0x80
+#define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR	4
+#define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR	4
+
+/* HDMI Connected States  */
+#define HDMI_STATE_NOMONITOR	0	/* NOT CONNECTED */
+#define HDMI_STATE_CONNECTED	1	/* CONNECTED */
+#define HDMI_STATE_ON		2	/* CONNECTED AND POWERED ON */
+
+
+/* HDMI EDID Length  */
+#define HDMI_EDID_MAX_LENGTH	256
+
+/* HDMI EDID DTDs  */
+#define HDMI_EDID_MAX_DTDS	4
+
+/* HDMI EDID DTD Tags  */
+#define HDMI_EDID_DTD_TAG_MONITOR_NAME		0xFC
+#define HDMI_EDID_DTD_TAG_MONITOR_SERIALNUM	0xFF
+#define HDMI_EDID_DTD_TAG_MONITOR_LIMITS	0xFD
+
+
+/* HDMI EDID Extension Data Block Tags  */
+#define HDMI_EDID_EX_DATABLOCK_TAG_MASK		0xE0
+#define HDMI_EDID_EX_DATABLOCK_LEN_MASK		0x1F
+
+#define HDMI_EDID_EX_DATABLOCK_AUDIO		0x20
+#define HDMI_EDID_EX_DATABLOCK_VIDEO		0x40
+#define HDMI_EDID_EX_DATABLOCK_VENDOR		0x60
+#define HDMI_EDID_EX_DATABLOCK_SPEAKERS		0x80
+
+/* HDMI EDID Extenion Data Block Values: Video  */
+#define HDMI_EDID_EX_VIDEO_NATIVE		0x80
+#define HDMI_EDID_EX_VIDEO_MASK			0x7F
+#define HDMI_EDID_EX_VIDEO_MAX			35
+
+#define HDMI_EDID_EX_VIDEO_640x480p_60Hz_4_3		1
+#define HDMI_EDID_EX_VIDEO_720x480p_60Hz_4_3		2
+#define HDMI_EDID_EX_VIDEO_720x480p_60Hz_16_9		3
+#define HDMI_EDID_EX_VIDEO_1280x720p_60Hz_16_9		4
+#define HDMI_EDID_EX_VIDEO_1920x1080i_60Hz_16_9		5
+#define HDMI_EDID_EX_VIDEO_720x480i_60Hz_4_3		6
+#define HDMI_EDID_EX_VIDEO_720x480i_60Hz_16_9		7
+#define HDMI_EDID_EX_VIDEO_720x240p_60Hz_4_3		8
+#define HDMI_EDID_EX_VIDEO_720x240p_60Hz_16_9		9
+#define HDMI_EDID_EX_VIDEO_2880x480i_60Hz_4_3		10
+#define HDMI_EDID_EX_VIDEO_2880x480i_60Hz_16_9		11
+#define HDMI_EDID_EX_VIDEO_2880x480p_60Hz_4_3		12
+#define HDMI_EDID_EX_VIDEO_2880x480p_60Hz_16_9		13
+#define HDMI_EDID_EX_VIDEO_1440x480p_60Hz_4_3		14
+#define HDMI_EDID_EX_VIDEO_1440x480p_60Hz_16_9		15
+#define HDMI_EDID_EX_VIDEO_1920x1080p_60Hz_16_9		16
+#define HDMI_EDID_EX_VIDEO_720x576p_50Hz_4_3		17
+#define HDMI_EDID_EX_VIDEO_720x576p_50Hz_16_9		18
+#define HDMI_EDID_EX_VIDEO_1280x720p_50Hz_16_9		19
+#define HDMI_EDID_EX_VIDEO_1920x1080i_50Hz_16_9		20
+#define HDMI_EDID_EX_VIDEO_720x576i_50Hz_4_3		21
+#define HDMI_EDID_EX_VIDEO_720x576i_50Hz_16_9		22
+#define HDMI_EDID_EX_VIDEO_720x288p_50Hz_4_3		23
+#define HDMI_EDID_EX_VIDEO_720x288p_50Hz_16_9		24
+#define HDMI_EDID_EX_VIDEO_2880x576i_50Hz_4_3		25
+#define HDMI_EDID_EX_VIDEO_2880x576i_50Hz_16_9		26
+#define HDMI_EDID_EX_VIDEO_2880x288p_50Hz_4_3		27
+#define HDMI_EDID_EX_VIDEO_2880x288p_50Hz_16_9		28
+#define HDMI_EDID_EX_VIDEO_1440x576p_50Hz_4_3		29
+#define HDMI_EDID_EX_VIDEO_1440x576p_50Hz_16_9		30
+#define HDMI_EDID_EX_VIDEO_1920x1080p_50Hz_16_9		31
+#define HDMI_EDID_EX_VIDEO_1920x1080p_24Hz_16_9		32
+#define HDMI_EDID_EX_VIDEO_1920x1080p_25Hz_16_9		33
+#define HDMI_EDID_EX_VIDEO_1920x1080p_30Hz_16_9		34
+
+/*  HDMI TPI Registers  */
+#define HDMI_TPI_VIDEO_DATA_BASE_REG	0x00
+#define HDMI_TPI_PIXEL_CLK_LSB_REG	 (HDMI_TPI_VIDEO_DATA_BASE_REG + 0x00)
+#define HDMI_TPI_PIXEL_CLK_MSB_REG (HDMI_TPI_VIDEO_DATA_BASE_REG + 0x01)
+#define HDMI_TPI_VFREQ_LSB_REG	(HDMI_TPI_VIDEO_DATA_BASE_REG + 0x02)
+#define HDMI_TPI_VFREQ_MSB_REG	(HDMI_TPI_VIDEO_DATA_BASE_REG + 0x03)
+#define HDMI_TPI_PIXELS_LSB_REG	(HDMI_TPI_VIDEO_DATA_BASE_REG + 0x04)
+#define HDMI_TPI_PIXELS_MSB_REG	(HDMI_TPI_VIDEO_DATA_BASE_REG + 0x05)
+#define HDMI_TPI_LINES_LSB_REG		(HDMI_TPI_VIDEO_DATA_BASE_REG + 0x06)
+#define HDMI_TPI_LINES_MSB_REG		(HDMI_TPI_VIDEO_DATA_BASE_REG + 0x07)
+
+#define HDMI_TPI_PIXEL_REPETITION_REG	0x08
+
+#define HDMI_TPI_AVI_INOUT_BASE_REG	0x09
+#define HDMI_TPI_AVI_IN_FORMAT_REG	(HDMI_TPI_AVI_INOUT_BASE_REG + 0x00)
+#define HDMI_TPI_AVI_OUT_FORMAT_REG	(HDMI_TPI_AVI_INOUT_BASE_REG + 0x01)
+
+#define HDMI_SYS_CTRL_DATA_REG		0x1A
+
+#define HDMI_TPI_SYN_GENERATOR_REG	0x60
+
+#define HDMI_TPI_VIDEO_SYN_POLARITY_REG	0x61
+
+#define HDMI_TPI_DE_BASE_REG			0x62
+#define HDMI_TPI_DE_DLY_LSB_REG		(HDMI_TPI_DE_BASE_REG + 0x0)
+#define HDMI_TPI_DE_DLY_MSB_REG		(HDMI_TPI_DE_BASE_REG + 0x1)
+#define HDMI_TPI_DE_TOP_REG			(HDMI_TPI_DE_BASE_REG + 0x2)
+#define HDMI_TPI_DE_RSVD_REG			(HDMI_TPI_DE_BASE_REG + 0x3)
+#define HDMI_TPI_DE_CNT_LSB_REG		(HDMI_TPI_DE_BASE_REG + 0x4)
+#define HDMI_TPI_DE_CNT_MSB_REG		(HDMI_TPI_DE_BASE_REG + 0x5)
+#define HDMI_TPI_DE_LIN_LSB_REG		(HDMI_TPI_DE_BASE_REG + 0x6)
+#define HDMI_TPI_DE_LIN_MSB_REG		(HDMI_TPI_DE_BASE_REG + 0x7)
+
+#define HDMI_TPI_HRES_LSB_REG		0x6A
+#define HDMI_TPI_HRES_MSB_REG		0x6B
+
+#define HDMI_TPI_VRES_LSB_REG		0x6C
+#define HDMI_TPI_VRES_MSB_REG		0x6D
+
+#define HDMI_TPI_RQB_REG		0xC7
+#define HDMI_TPI_DEVID_REG		0x1B
+#define HDMI_TPI_DEVREV_REG		0x1C
+
+#define HDMI_TPI_DEVICE_POWER_STATE_DATA	0x1E
+#define HDMI_REQ_GRANT_BMODE_REG		0xC7
+#define HDMI_TPI_DEVICE_ID_REG			0x1B
+#define HDMI_TPI_REVISION_REG			0x1C
+#define HDMI_TPI_ID_BYTE2_REG			0x1D
+#define HDMI_TPI_POWER_STATE_CTRL_REG		0x1E
+
+#define HDMI_TPI_INTERRUPT_ENABLE_REG		0x3C
+#define HDMI_TPI_INTERRUPT_STATUS_REG		0x3D
+
+
+/* AVI InfoFrames can be readed byte by byte but must be write in a burst  */
+#define HDMI_TPI_AVI_DBYTE_BASE_REG      0x0C
+#define HDMI_TPI_AVI_DBYTE0_CHKSUM_REG   (HDMI_TPI_AVI_DBYTE_BASE_REG +  0x00)
+#define HDMI_TPI_AVI_DBYTE1_REG          (HDMI_TPI_AVI_DBYTE_BASE_REG +  0x01)
+#define HDMI_TPI_AVI_DBYTE2_REG          (HDMI_TPI_AVI_DBYTE_BASE_REG +  0x02)
+#define HDMI_TPI_AVI_DBYTE3_REG          (HDMI_TPI_AVI_DBYTE_BASE_REG +  0x03)
+#define HDMI_TPI_AVI_DBYTE4_REG          (HDMI_TPI_AVI_DBYTE_BASE_REG +  0x04)
+#define HDMI_TPI_AVI_DBYTE5_REG          (HDMI_TPI_AVI_DBYTE_BASE_REG +  0x05)
+#define HDMI_TPI_AVI_ETB_LSB_REG         (HDMI_TPI_AVI_DBYTE_BASE_REG +  0x06)
+#define HDMI_TPI_AVI_ETB_MSB_REG         (HDMI_TPI_AVI_DBYTE_BASE_REG +  0x07)
+#define HDMI_TPI_AVI_SBB_LSB_REG         (HDMI_TPI_AVI_DBYTE_BASE_REG +  0x08)
+#define HDMI_TPI_AVI_SBB_MSB_REG         (HDMI_TPI_AVI_DBYTE_BASE_REG +  0x09)
+#define HDMI_TPI_AVI_ELB_LSB_REG         (HDMI_TPI_AVI_DBYTE_BASE_REG +  0x0A)
+#define HDMI_TPI_AVI_ELB_MSB_REG         (HDMI_TPI_AVI_DBYTE_BASE_REG +  0x0B)
+#define HDMI_TPI_AVI_SRB_LSB_REG         (HDMI_TPI_AVI_DBYTE_BASE_REG +  0x0C)
+#define HDMI_TPI_AVI_SRB_MSB_REG         (HDMI_TPI_AVI_DBYTE_BASE_REG +  0x0D)
+
+#define HDMI_CPI_MISC_IF_SELECT_REG         0xBF
+#define HDMI_CPI_MISC_IF_OFFSET             0xC0
+
+#define MISC_INFOFRAME_SIZE_MEMORY          14
+#define MISC_INFOFRAME_TYPE_SUBOFFSET       0
+#define MISC_INFOFRAME_VERSION_SUBOFFSET    1
+#define MISC_INFOFRAME_LENGTH_SUBOFFSET     2
+#define MISC_INFOFRAME_CHECKSUM_SUBOFFSET   3
+#define MISC_INFOFRAME_DBYTE1_SUBOFFSET     4
+#define MISC_INFOFRAME_DBYTE2_SUBOFFSET     5
+#define MISC_INFOFRAME_DBYTE3_SUBOFFSET     6
+#define MISC_INFOFRAME_DBYTE4_SUBOFFSET     7
+#define MISC_INFOFRAME_DBYTE5_SUBOFFSET     8
+#define MISC_INFOFRAME_DBYTE6_SUBOFFSET     9
+#define MISC_INFOFRAME_DBYTE7_SUBOFFSET     10
+#define MISC_INFOFRAME_DBYTE8_SUBOFFSET     11
+#define MISC_INFOFRAME_DBYTE9_SUBOFFSET     12
+#define MISC_INFOFRAME_DBYTE10_SUBOFFSET    13
+
+#define HDMI_CPI_MISC_TYPE_REG		(HDMI_CPI_MISC_IF_OFFSET\
+					+  MISC_INFOFRAME_TYPE_SUBOFFSET)
+#define HDMI_CPI_MISC_VERSION_REG	(HDMI_CPI_MISC_IF_OFFSET\
+					+  MISC_INFOFRAME_VERSION_SUBOFFSET)
+#define HDMI_CPI_MISC_LENGTH_REG	(HDMI_CPI_MISC_IF_OFFSET\
+					+  MISC_INFOFRAME_LENGTH_SUBOFFSET)
+#define HDMI_CPI_MISC_CHECKSUM_REG	(HDMI_CPI_MISC_IF_OFFSET\
+					+  MISC_INFOFRAME_CHECKSUM_SUBOFFSET)
+#define HDMI_CPI_MISC_DBYTE1_REG        (HDMI_CPI_MISC_IF_OFFSET\
+					+  MISC_INFOFRAME_DBYTE1_SUBOFFSET)
+#define HDMI_CPI_MISC_DBYTE2_REG        (HDMI_CPI_MISC_IF_OFFSET\
+					+  MISC_INFOFRAME_DBYTE2_SUBOFFSET)
+#define HDMI_CPI_MISC_DBYTE3_REG        (HDMI_CPI_MISC_IF_OFFSET\
+					+  MISC_INFOFRAME_DBYTE3_SUBOFFSET)
+#define HDMI_CPI_MISC_DBYTE4_REG        (HDMI_CPI_MISC_IF_OFFSET\
+					+  MISC_INFOFRAME_DBYTE4_SUBOFFSET)
+#define HDMI_CPI_MISC_DBYTE5_REG        (HDMI_CPI_MISC_IF_OFFSET\
+					+  MISC_INFOFRAME_DBYTE5_SUBOFFSET)
+#define HDMI_CPI_MISC_DBYTE6_REG        (HDMI_CPI_MISC_IF_OFFSET\
+					+  MISC_INFOFRAME_DBYTE6_SUBOFFSET)
+#define HDMI_CPI_MISC_DBYTE7_REG        (HDMI_CPI_MISC_IF_OFFSET\
+					+  MISC_INFOFRAME_DBYTE7_SUBOFFSET)
+#define HDMI_CPI_MISC_DBYTE8_REG        (HDMI_CPI_MISC_IF_OFFSET\
+					+  MISC_INFOFRAME_DBYTE8_SUBOFFSET)
+#define HDMI_CPI_MISC_DBYTE9_REG        (HDMI_CPI_MISC_IF_OFFSET\
+					+  MISC_INFOFRAME_DBYTE9_SUBOFFSET)
+#define HDMI_CPI_MISC_DBYTE10_REG       (HDMI_CPI_MISC_IF_OFFSET\
+					+  MISC_INFOFRAME_DBYTE10_SUBOFFSET)
+
+/* Audio  */
+#define HDMI_TPI_I2S_ENABLE_MAPPING_REG     0x1F
+#define HDMI_TPI_I2S_INPUT_CONFIG_REG       0x20
+#define HDMI_TPI_I2S_STRM_HDR_BASE          0x21
+#define HDMI_TPI_I2S_STRM_HDR_0_REG         (HDMI_TPI_I2S_STRM_HDR_BASE + 0)
+#define HDMI_TPI_I2S_STRM_HDR_1_REG         (HDMI_TPI_I2S_STRM_HDR_BASE + 1)
+#define HDMI_TPI_I2S_STRM_HDR_2_REG         (HDMI_TPI_I2S_STRM_HDR_BASE + 2)
+#define HDMI_TPI_I2S_STRM_HDR_3_REG         (HDMI_TPI_I2S_STRM_HDR_BASE + 3)
+#define HDMI_TPI_I2S_STRM_HDR_4_REG         (HDMI_TPI_I2S_STRM_HDR_BASE + 4)
+#define HDMI_TPI_AUDIO_CONFIG_BYTE2_REG     0x26
+#define HDMI_TPI_AUDIO_CONFIG_BYTE3_REG     0x27
+#define HDMI_TPI_AUDIO_CONFIG_BYTE4_REG     0x28
+
+/* HDCP */
+#define HDMI_TPI_HDCP_QUERYDATA_REG         0x29
+#define HDMI_TPI_HDCP_CONTROLDATA_REG       0x2A
+
+/* HDMI_TPI_DEVICE_ID_REG  */
+#define TPI_DEVICE_ID                       0xB0
+
+/* HDMI_TPI_REVISION_REG  */
+#define TPI_REVISION                        0x00
+
+/* HDMI_TPI_ID_BYTE2_REG  */
+#define TPI_ID_BYTE2_VALUE                  0x00
+
+/* HDMI_SYS_CTRL_DATA_REG  */
+#define TPI_SYS_CTRL_POWER_DOWN             (1 << 4)
+#define TPI_SYS_CTRL_POWER_ACTIVE           (0 << 4)
+#define TPI_SYS_CTRL_AV_MUTE                (1 << 3)
+#define TPI_SYS_CTRL_DDC_BUS_REQUEST        (1 << 2)
+#define TPI_SYS_CTRL_DDC_BUS_GRANTED        (1 << 1)
+#define TPI_SYS_CTRL_OUTPUT_MODE_HDMI       (1 << 0)
+#define TPI_SYS_CTRL_OUTPUT_MODE_DVI        (0 << 0)
+
+
+/* HDMI Monitor I2C default address  */
+#define HDMI_I2C_MONITOR_ADDRESS            0x50
+
+
+/* HDMI_TPI_INTR_ENABLE  */
+#define TPI_INTR_ENABLE_SECURITY_EVENT      (1 << 5)
+#define TPI_INTR_ENABLE_AUDIO_EVENT         (1 << 4)
+#define TPI_INTR_ENABLE_CPI_EVENT           (1 << 3)
+#define TPI_INTR_ENABLE_RECEIVER_EVENT      (1 << 1)
+#define TPI_INTR_ENABLE_HOTPLUG_EVENT       (1 << 0)
+
+/* HDMI_TPI_INTR_STATUS  */
+#define TPI_INTR_STATUS_SECURITY_EVENT      (1 << 5)
+#define TPI_INTR_STATUS_AUDIO_EVENT         (1 << 4)
+#define TPI_INTR_STATUS_POWERED_EVENT       (1 << 3)
+#define TPI_INTR_STATUS_HOTPLUG_STATE       (1 << 2)
+#define TPI_INTR_STATUS_RECEIVER_EVENT      (1 << 1)
+#define TPI_INTR_STATUS_HOTPLUG_EVENT       (1 << 0)
+
+
+/* HDMI_TPI_PIXEL_REPETITION  */
+#define TPI_AVI_PIXEL_REP_BUS_24BIT         (1 << 5)
+#define TPI_AVI_PIXEL_REP_BUS_12BIT         (0 << 5)
+#define TPI_AVI_PIXEL_REP_RISING_EDGE       (1 << 4)
+#define TPI_AVI_PIXEL_REP_FALLING_EDGE      (0 << 4)
+#define TPI_AVI_PIXEL_REP_4X                (3 << 0)
+#define TPI_AVI_PIXEL_REP_2X                (1 << 0)
+#define TPI_AVI_PIXEL_REP_NONE              (0 << 0)
+
+/* HDMI_TPI_AVI_INPUT_FORMAT  */
+#define TPI_AVI_INPUT_BITMODE_12BIT         (1 << 7)
+#define TPI_AVI_INPUT_BITMODE_8BIT          (0 << 7)
+#define TPI_AVI_INPUT_DITHER                (1 << 6)
+#define TPI_AVI_INPUT_RANGE_LIMITED         (2 << 2)
+#define TPI_AVI_INPUT_RANGE_FULL            (1 << 2)
+#define TPI_AVI_INPUT_RANGE_AUTO            (0 << 2)
+#define TPI_AVI_INPUT_COLORSPACE_BLACK      (3 << 0)
+#define TPI_AVI_INPUT_COLORSPACE_YUV422     (2 << 0)
+#define TPI_AVI_INPUT_COLORSPACE_YUV444     (1 << 0)
+#define TPI_AVI_INPUT_COLORSPACE_RGB        (0 << 0)
+
+
+/* HDMI_TPI_AVI_OUTPUT_FORMAT  */
+#define TPI_AVI_OUTPUT_CONV_BT709           (1 << 4)
+#define TPI_AVI_OUTPUT_CONV_BT601           (0 << 4)
+#define TPI_AVI_OUTPUT_RANGE_LIMITED        (2 << 2)
+#define TPI_AVI_OUTPUT_RANGE_FULL           (1 << 2)
+#define TPI_AVI_OUTPUT_RANGE_AUTO           (0 << 2)
+#define TPI_AVI_OUTPUT_COLORSPACE_RGBDVI    (3 << 0)
+#define TPI_AVI_OUTPUT_COLORSPACE_YUV422    (2 << 0)
+#define TPI_AVI_OUTPUT_COLORSPACE_YUV444    (1 << 0)
+#define TPI_AVI_OUTPUT_COLORSPACE_RGBHDMI   (0 << 0)
+
+
+/* HDMI_TPI_DEVICE_POWER_STATE  */
+#define TPI_AVI_POWER_STATE_D3              (3 << 0)
+#define TPI_AVI_POWER_STATE_D2              (2 << 0)
+#define TPI_AVI_POWER_STATE_D0              (0 << 0)
+
+/* HDMI_TPI_AUDIO_CONFIG_BYTE2_REG  */
+#define TPI_AUDIO_CODING_STREAM_HEADER      (0 << 0)
+#define TPI_AUDIO_CODING_PCM                (1 << 0)
+#define TPI_AUDIO_CODING_AC3                (2 << 0)
+#define TPI_AUDIO_CODING_MPEG1              (3 << 0)
+#define TPI_AUDIO_CODING_MP3                (4 << 0)
+#define TPI_AUDIO_CODING_MPEG2              (5 << 0)
+#define TPI_AUDIO_CODING_AAC                (6 << 0)
+#define TPI_AUDIO_CODING_DTS                (7 << 0)
+#define TPI_AUDIO_CODING_ATRAC              (8 << 0)
+#define TPI_AUDIO_MUTE_DISABLE              (0 << 4)
+#define TPI_AUDIO_MUTE_ENABLE               (1 << 4)
+#define TPI_AUDIO_INTERFACE_DISABLE         (0 << 6)
+#define TPI_AUDIO_INTERFACE_SPDIF           (1 << 6)
+#define TPI_AUDIO_INTERFACE_I2S             (2 << 6)
+
+/* HDMI_TPI_AUDIO_CONFIG_BYTE3_REG  */
+#define TPI_AUDIO_CHANNEL_STREAM            (0 << 0)
+#define TPI_AUDIO_2_CHANNEL                 (1 << 0)
+#define TPI_AUDIO_8_CHANNEL                 (7 << 0)
+#define TPI_AUDIO_FREQ_STREAM               (0 << 3)
+#define TPI_AUDIO_FREQ_32KHZ                (1 << 3)
+#define TPI_AUDIO_FREQ_44KHZ                (2 << 3)
+#define TPI_AUDIO_FREQ_48KHZ                (3 << 3)
+#define TPI_AUDIO_FREQ_88KHZ                (4 << 3)
+#define TPI_AUDIO_FREQ_96KHZ                (5 << 3)
+#define TPI_AUDIO_FREQ_176KHZ               (6 << 3)
+#define TPI_AUDIO_FREQ_192KHZ               (7 << 3)
+#define TPI_AUDIO_SAMPLE_SIZE_STREAM        (0 << 6)
+#define TPI_AUDIO_SAMPLE_SIZE_16            (1 << 6)
+#define TPI_AUDIO_SAMPLE_SIZE_20            (2 << 6)
+#define TPI_AUDIO_SAMPLE_SIZE_24            (3 << 6)
+
+/* HDMI_TPI_I2S_ENABLE_MAPPING_REG  */
+#define TPI_I2S_SD_CONFIG_SELECT_SD0        (0 << 0)
+#define TPI_I2S_SD_CONFIG_SELECT_SD1        (1 << 0)
+#define TPI_I2S_SD_CONFIG_SELECT_SD2        (2 << 0)
+#define TPI_I2S_SD_CONFIG_SELECT_SD3        (3 << 0)
+#define TPI_I2S_LF_RT_SWAP_NO               (0 << 2)
+#define TPI_I2S_LF_RT_SWAP_YES              (1 << 2)
+#define TPI_I2S_DOWNSAMPLE_DISABLE          (0 << 3)
+#define TPI_I2S_DOWNSAMPLE_ENABLE           (1 << 3)
+#define TPI_I2S_SD_FIFO_0                   (0 << 4)
+#define TPI_I2S_SD_FIFO_1                   (1 << 4)
+#define TPI_I2S_SD_FIFO_2                   (2 << 4)
+#define TPI_I2S_SD_FIFO_3                   (3 << 4)
+#define TPI_I2S_SD_CHANNEL_DISABLE          (0 << 7)
+#define TPI_I2S_SD_CHANNEL_ENABLE           (1 << 7)
+
+
+/* HDMI_TPI_I2S_INPUT_CONFIG_REG  */
+#define TPI_I2S_FIRST_BIT_SHIFT_YES         (0 << 0)
+#define TPI_I2S_FIRST_BIT_SHIFT_NO          (1 << 0)
+#define TPI_I2S_SD_DIRECTION_MSB_FIRST      (0 << 1)
+#define TPI_I2S_SD_DIRECTION_LSB_FIRST      (1 << 1)
+#define TPI_I2S_SD_JUSTIFY_LEFT             (0 << 2)
+#define TPI_I2S_SD_JUSTIFY_RIGHT            (1 << 2)
+#define TPI_I2S_WS_POLARITY_LOW             (0 << 3)
+#define TPI_I2S_WS_POLARITY_HIGH            (1 << 3)
+#define TPI_I2S_MCLK_MULTIPLIER_128         (0 << 4)
+#define TPI_I2S_MCLK_MULTIPLIER_256         (1 << 4)
+#define TPI_I2S_MCLK_MULTIPLIER_384         (2 << 4)
+#define TPI_I2S_MCLK_MULTIPLIER_512         (3 << 4)
+#define TPI_I2S_MCLK_MULTIPLIER_768         (4 << 4)
+#define TPI_I2S_MCLK_MULTIPLIER_1024        (5 << 4)
+#define TPI_I2S_MCLK_MULTIPLIER_1152        (6 << 4)
+#define TPI_I2S_MCLK_MULTIPLIER_192         (7 << 4)
+#define TPI_I2S_SCK_EDGE_FALLING            (0 << 7)
+#define TPI_I2S_SCK_EDGE_RISING             (1 << 7)
+
+/* HDMI_TPI_I2S_STRM_HDR_REG                       */
+/* the reference of this values is in IEC 60958-3  */
+#define I2S_CHAN_STATUS_MODE                0x00
+#define I2S_CHAN_STATUS_CAT_CODE            0x00
+#define I2S_CHAN_SOURCE_CHANNEL_NUM         0x00
+#define I2S_CHAN_ACCURACY_N_44_SAMPLING_FS  0x20
+#define I2S_CHAN_ACCURACY_N_48_SAMPLING_FS  0x22
+#define I2S_CHAN_ORIGIN_FS_N_SAMP_LENGTH    0xD2
+
+
+/* MISCELLANOUS INFOFRAME VALUES  */
+
+#define HDMI_INFOFRAME_TX_ENABLE            (0x1 << 7)
+#define HDMI_INFOFRAME_TX_REPEAT            (0x1 << 6)
+#define HDMI_AUDIO_INFOFRAME                (0x2 << 0)
+
+/* Stream Header Data  */
+#define HDMI_SH_PCM                         (0x1 << 4)
+#define HDMI_SH_TWO_CHANNELS                (0x1 << 0)
+#define HDMI_SH_44KHz                       (0x2 << 2)
+#define HDMI_SH_48KHz                       (0x3 << 2)
+#define HDMI_SH_16BIT                       (0x1 << 0)
+#define HDMI_SH_SPKR_FLFR                   0x0
+#define HDMI_SH_0dB_ATUN                    0x0
+
+/* MISC_TYPE  */
+#define MISC_INFOFRAME_TYPE                 0x04  /* for Audio */
+#define MISC_INFOFRAME_ALWAYS_SET           0x80
+
+/* MISC_VERSION  */
+#define MISC_INFOFRAME_VERSION              0x01
+
+/* MISC_LENGTH  */
+#define MISC_INFOFRAME_LENGTH               0x0A /*length for Audio infoframe*/
+#define MISC_INFOFRAME_LENGTH_RSVD_BITS     0xE0
+
+/* MISC_DBYTE1                */
+/* Type, Encoding, Trandport  */
+#define MISC_DBYTE1_CT_CHK_HEADER_STREAM    0x00
+
+/* audio channel count  */
+#define MISC_DBYTE1_CC_CHK_HEADER_STREAM    0x00
+#define MISC_DBYTE1_CC_2_CHANNELS           0x01
+
+/* MISC_DBYTE2  */
+/*Sample Size   */
+#define MISC_DBYTE2_SS_CHK_HEADER_STREAM    0x00  /* for hdmi by default */
+
+/* Sampling Frequency  */
+#define MISC_DBYTE2_SF_CHK_HEADER_STREAM    0x00  /* for hdmi by default */
+
+/* MISC_DBYTE3     */
+/* Code Extention  */
+#define MISC_DBYTE3_CTX_TAKE_DBYTE1         0x00  /* for hdmi by default */
+
+/* MISC_DBYTE4  */
+#define MISC_DBYTE4                         0x00 /*for no multichannel( */
+						 /* multichannel means more*/
+						/* than 2 channels */
+
+/* MISC_DBYTE5  */
+#define MISC_DBYTE5           0x00  /* for no multichannel(multichannel  */
+					/* means more than 2 channels */
+
+struct hdmi_reg_data {
+	u8 reg_offset;
+	u8 value;
+};
+
+#endif
-- 
1.7.9.5


^ permalink raw reply related

* Re: [PATCH V6 0/4] Generic PHY driver for the Exynos SoC DP PHY
From: Sylwester Nawrocki @ 2013-07-09  8:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <003d01ce7c7a$d04043d0$70c0cb70$@samsung.com>

On 07/09/2013 10:03 AM, Jingoo Han wrote:
> This patch series adds a simple driver for the Samsung Exynos SoC
> series DP transmitter PHY, using the generic PHY framework [1].
> Previously the DP PHY used an internal DT node to control the PHY
> power enable bit.
> 
> These patches was tested on Exynos5250.
> 
> This PATCH v6 follows:
>  * PATCH v5, sent on July, 8th 2013
>  * PATCH v4, sent on July, 2nd 2013
>  * PATCH v3, sent on July, 1st 2013
>  * PATCH v2, sent on June, 28th 2013
>  * PATCH v1, sent on June, 28th 2013
> 
> Changes between v5 and v6:
>   * Re-based on git://gitorious.org/linuxphy/linuxphy.git

I'm not sure if we really need to keep the documentation of the
original binding. Anyway, for the whole series, please feel free
to ad my

Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>

--
Thanks,
Sylwester


^ permalink raw reply

* [PATCH V6 4/4] video: exynos_dp: Use the generic PHY driver
From: Jingoo Han @ 2013-07-09  8:05 UTC (permalink / raw)
  To: linux-arm-kernel

Use the generic PHY API to control the DP PHY.

Signed-off-by: Jingoo Han <jg1.han@samsung.com>
Reviewed-by: Tomasz Figa <t.figa@samsung.com>
---
 .../devicetree/bindings/video/exynos_dp.txt          |   18 +++++++++---------
 drivers/video/exynos/exynos_dp_core.c                |   16 ++++++++++++----
 drivers/video/exynos/exynos_dp_core.h                |    1 +
 3 files changed, 22 insertions(+), 13 deletions(-)

diff --git a/Documentation/devicetree/bindings/video/exynos_dp.txt b/Documentation/devicetree/bindings/video/exynos_dp.txt
index c60da67..e2874ae 100644
--- a/Documentation/devicetree/bindings/video/exynos_dp.txt
+++ b/Documentation/devicetree/bindings/video/exynos_dp.txt
@@ -6,10 +6,10 @@ We use two nodes:
 	-dptx-phy node(defined inside dp-controller node)
 
 For the DP-PHY initialization, we use the dptx-phy node.
-Required properties for dptx-phy:
-	-reg:
+Required properties for dptx-phy: deprecated, use phys and phy-names
+	-reg: deprecated
 		Base address of DP PHY register.
-	-samsung,enable-mask:
+	-samsung,enable-mask: deprecated
 		The bit-mask used to enable/disable DP PHY.
 
 For the Panel initialization, we read data from dp-controller node.
@@ -21,6 +21,10 @@ Required properties for dp-controller:
 		of memory mapped region.
 	-interrupts:
 		interrupt combiner values.
+	-phys:
+		from general PHY binding: the phandle for the PHY device.
+	-phy-names:
+		from general PHY binding: Should be "dp".
 	-interrupt-parent:
 		phandle to Interrupt combiner node.
 	-samsung,color-space:
@@ -61,12 +65,8 @@ SOC specific portion:
 		reg = <0x145b0000 0x10000>;
 		interrupts = <10 3>;
 		interrupt-parent = <&combiner>;
-
-		dptx-phy {
-			reg = <0x10040720>;
-			samsung,enable-mask = <1>;
-		};
-
+		phys = <&dp_phy>;
+		phy-names = "dp";
 	};
 
 Board Specific portion:
diff --git a/drivers/video/exynos/exynos_dp_core.c b/drivers/video/exynos/exynos_dp_core.c
index 05fed7d..5e1a715 100644
--- a/drivers/video/exynos/exynos_dp_core.c
+++ b/drivers/video/exynos/exynos_dp_core.c
@@ -19,6 +19,7 @@
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/of.h>
+#include <linux/phy/phy.h>
 
 #include "exynos_dp_core.h"
 
@@ -960,8 +961,11 @@ static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
 
 	dp_phy_node = of_find_node_by_name(dp_phy_node, "dptx-phy");
 	if (!dp_phy_node) {
-		dev_err(dp->dev, "could not find dptx-phy node\n");
-		return -ENODEV;
+		dp->phy = devm_phy_get(dp->dev, "dp");
+		if (IS_ERR(dp->phy))
+			return PTR_ERR(dp->phy);
+		else
+			return 0;
 	}
 
 	if (of_property_read_u32(dp_phy_node, "reg", &phy_base)) {
@@ -992,7 +996,9 @@ err:
 
 static void exynos_dp_phy_init(struct exynos_dp_device *dp)
 {
-	if (dp->phy_addr) {
+	if (dp->phy) {
+		phy_power_on(dp->phy);
+	} else if (dp->phy_addr) {
 		u32 reg;
 
 		reg = __raw_readl(dp->phy_addr);
@@ -1003,7 +1009,9 @@ static void exynos_dp_phy_init(struct exynos_dp_device *dp)
 
 static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
 {
-	if (dp->phy_addr) {
+	if (dp->phy) {
+		phy_power_off(dp->phy);
+	} else if (dp->phy_addr) {
 		u32 reg;
 
 		reg = __raw_readl(dp->phy_addr);
diff --git a/drivers/video/exynos/exynos_dp_core.h b/drivers/video/exynos/exynos_dp_core.h
index 56cfec8..607e36d 100644
--- a/drivers/video/exynos/exynos_dp_core.h
+++ b/drivers/video/exynos/exynos_dp_core.h
@@ -151,6 +151,7 @@ struct exynos_dp_device {
 	struct video_info	*video_info;
 	struct link_train	link_train;
 	struct work_struct	hotplug_work;
+	struct phy		*phy;
 };
 
 /* exynos_dp_reg.c */
-- 
1.7.10.4



^ permalink raw reply related

* [PATCH V6 3/4] video: exynos_dp: remove non-DT support for Exynos Display Port
From: Jingoo Han @ 2013-07-09  8:05 UTC (permalink / raw)
  To: linux-arm-kernel

Exynos Display Port can be used only for Exynos SoCs. In addition,
non-DT for EXYNOS SoCs is not supported from v3.11; thus, there is
no need to support non-DT for Exynos Display Port.

The 'include/video/exynos_dp.h' file has been used for non-DT
support and the content of file include/video/exynos_dp.h is moved
to drivers/video/exynos/exynos_dp_core.h. Thus, the 'exynos_dp.h'
file is removed. Also, 'struct exynos_dp_platdata' is removed,
because it is not used any more.

Signed-off-by: Jingoo Han <jg1.han@samsung.com>
Reviewed-by: Tomasz Figa <t.figa@samsung.com>
---
 drivers/video/exynos/Kconfig          |    2 +-
 drivers/video/exynos/exynos_dp_core.c |  116 +++++++----------------------
 drivers/video/exynos/exynos_dp_core.h |  109 +++++++++++++++++++++++++++
 drivers/video/exynos/exynos_dp_reg.c  |    2 -
 include/video/exynos_dp.h             |  131 ---------------------------------
 5 files changed, 135 insertions(+), 225 deletions(-)
 delete mode 100644 include/video/exynos_dp.h

diff --git a/drivers/video/exynos/Kconfig b/drivers/video/exynos/Kconfig
index 1b035b2..fab9019 100644
--- a/drivers/video/exynos/Kconfig
+++ b/drivers/video/exynos/Kconfig
@@ -29,7 +29,7 @@ config EXYNOS_LCD_S6E8AX0
 
 config EXYNOS_DP
 	bool "EXYNOS DP driver support"
-	depends on ARCH_EXYNOS
+	depends on OF && ARCH_EXYNOS
 	default n
 	help
 	  This enables support for DP device.
diff --git a/drivers/video/exynos/exynos_dp_core.c b/drivers/video/exynos/exynos_dp_core.c
index 12bbede..05fed7d 100644
--- a/drivers/video/exynos/exynos_dp_core.c
+++ b/drivers/video/exynos/exynos_dp_core.c
@@ -20,8 +20,6 @@
 #include <linux/delay.h>
 #include <linux/of.h>
 
-#include <video/exynos_dp.h>
-
 #include "exynos_dp_core.h"
 
 static int exynos_dp_init_dp(struct exynos_dp_device *dp)
@@ -894,26 +892,17 @@ static void exynos_dp_hotplug(struct work_struct *work)
 		dev_err(dp->dev, "unable to config video\n");
 }
 
-#ifdef CONFIG_OF
-static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device *dev)
+static struct video_info *exynos_dp_dt_parse_pdata(struct device *dev)
 {
 	struct device_node *dp_node = dev->of_node;
-	struct exynos_dp_platdata *pd;
 	struct video_info *dp_video_config;
 
-	pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
-	if (!pd) {
-		dev_err(dev, "memory allocation for pdata failed\n");
-		return ERR_PTR(-ENOMEM);
-	}
 	dp_video_config = devm_kzalloc(dev,
 				sizeof(*dp_video_config), GFP_KERNEL);
-
 	if (!dp_video_config) {
 		dev_err(dev, "memory allocation for video config failed\n");
 		return ERR_PTR(-ENOMEM);
 	}
-	pd->video_info = dp_video_config;
 
 	dp_video_config->h_sync_polarity  		of_property_read_bool(dp_node, "hsync-active-high");
@@ -960,7 +949,7 @@ static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device *dev)
 		return ERR_PTR(-EINVAL);
 	}
 
-	return pd;
+	return dp_video_config;
 }
 
 static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
@@ -1003,48 +992,30 @@ err:
 
 static void exynos_dp_phy_init(struct exynos_dp_device *dp)
 {
-	u32 reg;
+	if (dp->phy_addr) {
+		u32 reg;
 
-	reg = __raw_readl(dp->phy_addr);
-	reg |= dp->enable_mask;
-	__raw_writel(reg, dp->phy_addr);
+		reg = __raw_readl(dp->phy_addr);
+		reg |= dp->enable_mask;
+		__raw_writel(reg, dp->phy_addr);
+	}
 }
 
 static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
 {
-	u32 reg;
-
-	reg = __raw_readl(dp->phy_addr);
-	reg &= ~(dp->enable_mask);
-	__raw_writel(reg, dp->phy_addr);
-}
-#else
-static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device *dev)
-{
-	return NULL;
-}
-
-static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
-{
-	return -EINVAL;
-}
-
-static void exynos_dp_phy_init(struct exynos_dp_device *dp)
-{
-	return;
-}
+	if (dp->phy_addr) {
+		u32 reg;
 
-static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
-{
-	return;
+		reg = __raw_readl(dp->phy_addr);
+		reg &= ~(dp->enable_mask);
+		__raw_writel(reg, dp->phy_addr);
+	}
 }
-#endif /* CONFIG_OF */
 
 static int exynos_dp_probe(struct platform_device *pdev)
 {
 	struct resource *res;
 	struct exynos_dp_device *dp;
-	struct exynos_dp_platdata *pdata;
 
 	int ret = 0;
 
@@ -1057,21 +1028,13 @@ static int exynos_dp_probe(struct platform_device *pdev)
 
 	dp->dev = &pdev->dev;
 
-	if (pdev->dev.of_node) {
-		pdata = exynos_dp_dt_parse_pdata(&pdev->dev);
-		if (IS_ERR(pdata))
-			return PTR_ERR(pdata);
+	dp->video_info = exynos_dp_dt_parse_pdata(&pdev->dev);
+	if (IS_ERR(dp->video_info))
+		return PTR_ERR(dp->video_info);
 
-		ret = exynos_dp_dt_parse_phydata(dp);
-		if (ret)
-			return ret;
-	} else {
-		pdata = pdev->dev.platform_data;
-		if (!pdata) {
-			dev_err(&pdev->dev, "no platform data\n");
-			return -EINVAL;
-		}
-	}
+	ret = exynos_dp_dt_parse_phydata(dp);
+	if (ret)
+		return ret;
 
 	dp->clock = devm_clk_get(&pdev->dev, "dp");
 	if (IS_ERR(dp->clock)) {
@@ -1095,15 +1058,7 @@ static int exynos_dp_probe(struct platform_device *pdev)
 
 	INIT_WORK(&dp->hotplug_work, exynos_dp_hotplug);
 
-	dp->video_info = pdata->video_info;
-
-	if (pdev->dev.of_node) {
-		if (dp->phy_addr)
-			exynos_dp_phy_init(dp);
-	} else {
-		if (pdata->phy_init)
-			pdata->phy_init();
-	}
+	exynos_dp_phy_init(dp);
 
 	exynos_dp_init_dp(dp);
 
@@ -1121,18 +1076,11 @@ static int exynos_dp_probe(struct platform_device *pdev)
 
 static int exynos_dp_remove(struct platform_device *pdev)
 {
-	struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
 	struct exynos_dp_device *dp = platform_get_drvdata(pdev);
 
 	flush_work(&dp->hotplug_work);
 
-	if (pdev->dev.of_node) {
-		if (dp->phy_addr)
-			exynos_dp_phy_exit(dp);
-	} else {
-		if (pdata->phy_exit)
-			pdata->phy_exit();
-	}
+	exynos_dp_phy_exit(dp);
 
 	clk_disable_unprepare(dp->clock);
 
@@ -1143,20 +1091,13 @@ static int exynos_dp_remove(struct platform_device *pdev)
 #ifdef CONFIG_PM_SLEEP
 static int exynos_dp_suspend(struct device *dev)
 {
-	struct exynos_dp_platdata *pdata = dev->platform_data;
 	struct exynos_dp_device *dp = dev_get_drvdata(dev);
 
 	disable_irq(dp->irq);
 
 	flush_work(&dp->hotplug_work);
 
-	if (dev->of_node) {
-		if (dp->phy_addr)
-			exynos_dp_phy_exit(dp);
-	} else {
-		if (pdata->phy_exit)
-			pdata->phy_exit();
-	}
+	exynos_dp_phy_exit(dp);
 
 	clk_disable_unprepare(dp->clock);
 
@@ -1165,16 +1106,9 @@ static int exynos_dp_suspend(struct device *dev)
 
 static int exynos_dp_resume(struct device *dev)
 {
-	struct exynos_dp_platdata *pdata = dev->platform_data;
 	struct exynos_dp_device *dp = dev_get_drvdata(dev);
 
-	if (dev->of_node) {
-		if (dp->phy_addr)
-			exynos_dp_phy_init(dp);
-	} else {
-		if (pdata->phy_init)
-			pdata->phy_init();
-	}
+	exynos_dp_phy_init(dp);
 
 	clk_prepare_enable(dp->clock);
 
@@ -1203,7 +1137,7 @@ static struct platform_driver exynos_dp_driver = {
 		.name	= "exynos-dp",
 		.owner	= THIS_MODULE,
 		.pm	= &exynos_dp_pm_ops,
-		.of_match_table = of_match_ptr(exynos_dp_match),
+		.of_match_table = exynos_dp_match,
 	},
 };
 
diff --git a/drivers/video/exynos/exynos_dp_core.h b/drivers/video/exynos/exynos_dp_core.h
index 6c567bbf..56cfec8 100644
--- a/drivers/video/exynos/exynos_dp_core.h
+++ b/drivers/video/exynos/exynos_dp_core.h
@@ -13,6 +13,99 @@
 #ifndef _EXYNOS_DP_CORE_H
 #define _EXYNOS_DP_CORE_H
 
+#define DP_TIMEOUT_LOOP_COUNT 100
+#define MAX_CR_LOOP 5
+#define MAX_EQ_LOOP 5
+
+enum link_rate_type {
+	LINK_RATE_1_62GBPS = 0x06,
+	LINK_RATE_2_70GBPS = 0x0a
+};
+
+enum link_lane_count_type {
+	LANE_COUNT1 = 1,
+	LANE_COUNT2 = 2,
+	LANE_COUNT4 = 4
+};
+
+enum link_training_state {
+	START,
+	CLOCK_RECOVERY,
+	EQUALIZER_TRAINING,
+	FINISHED,
+	FAILED
+};
+
+enum voltage_swing_level {
+	VOLTAGE_LEVEL_0,
+	VOLTAGE_LEVEL_1,
+	VOLTAGE_LEVEL_2,
+	VOLTAGE_LEVEL_3,
+};
+
+enum pre_emphasis_level {
+	PRE_EMPHASIS_LEVEL_0,
+	PRE_EMPHASIS_LEVEL_1,
+	PRE_EMPHASIS_LEVEL_2,
+	PRE_EMPHASIS_LEVEL_3,
+};
+
+enum pattern_set {
+	PRBS7,
+	D10_2,
+	TRAINING_PTN1,
+	TRAINING_PTN2,
+	DP_NONE
+};
+
+enum color_space {
+	COLOR_RGB,
+	COLOR_YCBCR422,
+	COLOR_YCBCR444
+};
+
+enum color_depth {
+	COLOR_6,
+	COLOR_8,
+	COLOR_10,
+	COLOR_12
+};
+
+enum color_coefficient {
+	COLOR_YCBCR601,
+	COLOR_YCBCR709
+};
+
+enum dynamic_range {
+	VESA,
+	CEA
+};
+
+enum pll_status {
+	PLL_UNLOCKED,
+	PLL_LOCKED
+};
+
+enum clock_recovery_m_value_type {
+	CALCULATED_M,
+	REGISTER_M
+};
+
+enum video_timing_recognition_type {
+	VIDEO_TIMING_FROM_CAPTURE,
+	VIDEO_TIMING_FROM_REGISTER
+};
+
+enum analog_power_block {
+	AUX_BLOCK,
+	CH0_BLOCK,
+	CH1_BLOCK,
+	CH2_BLOCK,
+	CH3_BLOCK,
+	ANALOG_TOTAL,
+	POWER_ALL
+};
+
 enum dp_irq_type {
 	DP_IRQ_TYPE_HP_CABLE_IN,
 	DP_IRQ_TYPE_HP_CABLE_OUT,
@@ -20,6 +113,22 @@ enum dp_irq_type {
 	DP_IRQ_TYPE_UNKNOWN,
 };
 
+struct video_info {
+	char *name;
+
+	bool h_sync_polarity;
+	bool v_sync_polarity;
+	bool interlaced;
+
+	enum color_space color_space;
+	enum dynamic_range dynamic_range;
+	enum color_coefficient ycbcr_coeff;
+	enum color_depth color_depth;
+
+	enum link_rate_type link_rate;
+	enum link_lane_count_type lane_count;
+};
+
 struct link_train {
 	int eq_loop;
 	int cr_loop[4];
diff --git a/drivers/video/exynos/exynos_dp_reg.c b/drivers/video/exynos/exynos_dp_reg.c
index 29d9d03..b70da50 100644
--- a/drivers/video/exynos/exynos_dp_reg.c
+++ b/drivers/video/exynos/exynos_dp_reg.c
@@ -14,8 +14,6 @@
 #include <linux/io.h>
 #include <linux/delay.h>
 
-#include <video/exynos_dp.h>
-
 #include "exynos_dp_core.h"
 #include "exynos_dp_reg.h"
 
diff --git a/include/video/exynos_dp.h b/include/video/exynos_dp.h
deleted file mode 100644
index bd8cabd..0000000
--- a/include/video/exynos_dp.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Samsung SoC DP device support
- *
- * Copyright (C) 2012 Samsung Electronics Co., Ltd.
- * Author: Jingoo Han <jg1.han@samsung.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.
- */
-
-#ifndef _EXYNOS_DP_H
-#define _EXYNOS_DP_H
-
-#define DP_TIMEOUT_LOOP_COUNT 100
-#define MAX_CR_LOOP 5
-#define MAX_EQ_LOOP 5
-
-enum link_rate_type {
-	LINK_RATE_1_62GBPS = 0x06,
-	LINK_RATE_2_70GBPS = 0x0a
-};
-
-enum link_lane_count_type {
-	LANE_COUNT1 = 1,
-	LANE_COUNT2 = 2,
-	LANE_COUNT4 = 4
-};
-
-enum link_training_state {
-	START,
-	CLOCK_RECOVERY,
-	EQUALIZER_TRAINING,
-	FINISHED,
-	FAILED
-};
-
-enum voltage_swing_level {
-	VOLTAGE_LEVEL_0,
-	VOLTAGE_LEVEL_1,
-	VOLTAGE_LEVEL_2,
-	VOLTAGE_LEVEL_3,
-};
-
-enum pre_emphasis_level {
-	PRE_EMPHASIS_LEVEL_0,
-	PRE_EMPHASIS_LEVEL_1,
-	PRE_EMPHASIS_LEVEL_2,
-	PRE_EMPHASIS_LEVEL_3,
-};
-
-enum pattern_set {
-	PRBS7,
-	D10_2,
-	TRAINING_PTN1,
-	TRAINING_PTN2,
-	DP_NONE
-};
-
-enum color_space {
-	COLOR_RGB,
-	COLOR_YCBCR422,
-	COLOR_YCBCR444
-};
-
-enum color_depth {
-	COLOR_6,
-	COLOR_8,
-	COLOR_10,
-	COLOR_12
-};
-
-enum color_coefficient {
-	COLOR_YCBCR601,
-	COLOR_YCBCR709
-};
-
-enum dynamic_range {
-	VESA,
-	CEA
-};
-
-enum pll_status {
-	PLL_UNLOCKED,
-	PLL_LOCKED
-};
-
-enum clock_recovery_m_value_type {
-	CALCULATED_M,
-	REGISTER_M
-};
-
-enum video_timing_recognition_type {
-	VIDEO_TIMING_FROM_CAPTURE,
-	VIDEO_TIMING_FROM_REGISTER
-};
-
-enum analog_power_block {
-	AUX_BLOCK,
-	CH0_BLOCK,
-	CH1_BLOCK,
-	CH2_BLOCK,
-	CH3_BLOCK,
-	ANALOG_TOTAL,
-	POWER_ALL
-};
-
-struct video_info {
-	char *name;
-
-	bool h_sync_polarity;
-	bool v_sync_polarity;
-	bool interlaced;
-
-	enum color_space color_space;
-	enum dynamic_range dynamic_range;
-	enum color_coefficient ycbcr_coeff;
-	enum color_depth color_depth;
-
-	enum link_rate_type link_rate;
-	enum link_lane_count_type lane_count;
-};
-
-struct exynos_dp_platdata {
-	struct video_info *video_info;
-
-	void (*phy_init)(void);
-	void (*phy_exit)(void);
-};
-
-#endif /* _EXYNOS_DP_H */
-- 
1.7.10.4



^ permalink raw reply related

* [PATCH V6 2/4] phy: Add driver for Exynos DP PHY
From: Jingoo Han @ 2013-07-09  8:04 UTC (permalink / raw)
  To: linux-arm-kernel

Add a PHY provider driver for the Samsung Exynos SoC Display Port PHY.

Signed-off-by: Jingoo Han <jg1.han@samsung.com>
Reviewed-by: Tomasz Figa <t.figa@samsung.com>
Cc: Sylwester Nawrocki <s.nawrocki@samsung.com>
Acked-by: Felipe Balbi <balbi@ti.com>
---
 .../devicetree/bindings/phy/samsung-phy.txt        |    8 ++
 drivers/phy/Kconfig                                |    6 ++
 drivers/phy/Makefile                               |    1 +
 drivers/phy/phy-exynos-dp-video.c                  |  111 ++++++++++++++++++++
 4 files changed, 126 insertions(+)
 create mode 100644 drivers/phy/phy-exynos-dp-video.c

diff --git a/Documentation/devicetree/bindings/phy/samsung-phy.txt b/Documentation/devicetree/bindings/phy/samsung-phy.txt
index 5ff208c..c0fccaa 100644
--- a/Documentation/devicetree/bindings/phy/samsung-phy.txt
+++ b/Documentation/devicetree/bindings/phy/samsung-phy.txt
@@ -12,3 +12,11 @@ the PHY specifier identifies the PHY and its meaning is as follows:
   1 - MIPI DSIM 0,
   2 - MIPI CSIS 1,
   3 - MIPI DSIM 1.
+
+Samsung EXYNOS SoC series Display Port PHY
+-------------------------------------------------
+
+Required properties:
+- compatible : should be "samsung,exynos5250-dp-video-phy";
+- reg : offset and length of the Display Port PHY register set;
+- #phy-cells : from the generic PHY bindings, must be 0;
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 6f446d0..ed0b1b8 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -19,4 +19,10 @@ config PHY_EXYNOS_MIPI_VIDEO
 	help
 	  Support for MIPI CSI-2 and MIPI DSI DPHY found on Samsung
 	  S5P and EXYNOS SoCs.
+
+config PHY_EXYNOS_DP_VIDEO
+	tristate "EXYNOS SoC series Display Port PHY driver"
+	depends on OF
+	help
+	  Support for Display Port PHY found on Samsung EXYNOS SoCs.
 endif
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 71d8841..0fd1340 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -4,3 +4,4 @@
 
 obj-$(CONFIG_GENERIC_PHY)		+= phy-core.o
 obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO)	+= phy-exynos-mipi-video.o
+obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO)	+= phy-exynos-dp-video.o
diff --git a/drivers/phy/phy-exynos-dp-video.c b/drivers/phy/phy-exynos-dp-video.c
new file mode 100644
index 0000000..3c8e247
--- /dev/null
+++ b/drivers/phy/phy-exynos-dp-video.c
@@ -0,0 +1,111 @@
+/*
+ * Samsung EXYNOS SoC series Display Port PHY driver
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ * Author: Jingoo Han <jg1.han@samsung.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/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+
+/* DPTX_PHY_CONTROL register */
+#define EXYNOS_DPTX_PHY_ENABLE		(1 << 0)
+
+struct exynos_dp_video_phy {
+	void __iomem *regs;
+};
+
+static int __set_phy_state(struct exynos_dp_video_phy *state, unsigned int on)
+{
+	u32 reg;
+
+	reg = readl(state->regs);
+	if (on)
+		reg |= EXYNOS_DPTX_PHY_ENABLE;
+	else
+		reg &= ~EXYNOS_DPTX_PHY_ENABLE;
+	writel(reg, state->regs);
+
+	return 0;
+}
+
+static int exynos_dp_video_phy_power_on(struct phy *phy)
+{
+	struct exynos_dp_video_phy *state = phy_get_drvdata(phy);
+
+	return __set_phy_state(state, 1);
+}
+
+static int exynos_dp_video_phy_power_off(struct phy *phy)
+{
+	struct exynos_dp_video_phy *state = phy_get_drvdata(phy);
+
+	return __set_phy_state(state, 0);
+}
+
+static struct phy_ops exynos_dp_video_phy_ops = {
+	.power_on	= exynos_dp_video_phy_power_on,
+	.power_off	= exynos_dp_video_phy_power_off,
+	.owner		= THIS_MODULE,
+};
+
+static int exynos_dp_video_phy_probe(struct platform_device *pdev)
+{
+	struct exynos_dp_video_phy *state;
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	struct phy_provider *phy_provider;
+	struct phy *phy;
+
+	state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
+	if (!state)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	state->regs = devm_ioremap_resource(dev, res);
+	if (IS_ERR(state->regs))
+		return PTR_ERR(state->regs);
+
+	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+	if (IS_ERR(phy_provider))
+		return PTR_ERR(phy_provider);
+
+	phy = devm_phy_create(dev, 0, &exynos_dp_video_phy_ops, NULL);
+	if (IS_ERR(phy)) {
+		dev_err(dev, "failed to create Display Port PHY\n");
+		return PTR_ERR(phy);
+	}
+	phy_set_drvdata(phy, state);
+
+	return 0;
+}
+
+static const struct of_device_id exynos_dp_video_phy_of_match[] = {
+	{ .compatible = "samsung,exynos5250-dp-video-phy" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, exynos_dp_video_phy_of_match);
+
+static struct platform_driver exynos_dp_video_phy_driver = {
+	.probe	= exynos_dp_video_phy_probe,
+	.driver = {
+		.name	= "exynos-dp-video-phy",
+		.owner	= THIS_MODULE,
+		.of_match_table	= exynos_dp_video_phy_of_match,
+	}
+};
+module_platform_driver(exynos_dp_video_phy_driver);
+
+MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
+MODULE_DESCRIPTION("Samsung EXYNOS SoC DP PHY driver");
+MODULE_LICENSE("GPL v2");
-- 
1.7.10.4



^ permalink raw reply related

* [PATCH V6 1/4] ARM: dts: Add DP PHY node to exynos5250.dtsi
From: Jingoo Han @ 2013-07-09  8:04 UTC (permalink / raw)
  To: linux-arm-kernel

Add PHY provider node for the DP PHY.

Signed-off-by: Jingoo Han <jg1.han@samsung.com>
Reviewed-by: Tomasz Figa <t.figa@samsung.com>
Acked-by: Felipe Balbi <balbi@ti.com>
---
 arch/arm/boot/dts/exynos5250.dtsi |   13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi
index fc9fb3d..c326c06 100644
--- a/arch/arm/boot/dts/exynos5250.dtsi
+++ b/arch/arm/boot/dts/exynos5250.dtsi
@@ -616,6 +616,12 @@
 		interrupts = <0 94 0>;
 	};
 
+	dp_phy: video-phy@10040720 {
+		compatible = "samsung,exynos5250-dp-video-phy";
+		reg = <0x10040720 4>;
+		#phy-cells = <0>;
+	};
+
 	dp-controller {
 		compatible = "samsung,exynos5-dp";
 		reg = <0x145b0000 0x1000>;
@@ -623,11 +629,8 @@
 		interrupt-parent = <&combiner>;
 		#address-cells = <1>;
 		#size-cells = <0>;
-
-		dptx-phy {
-			reg = <0x10040720>;
-			samsung,enable-mask = <1>;
-		};
+		phys = <&dp_phy>;
+		phy-names = "dp";
 	};
 
 	fimd {
-- 
1.7.10.4



^ permalink raw reply related

* [PATCH V6 0/4] Generic PHY driver for the Exynos SoC DP PHY
From: Jingoo Han @ 2013-07-09  8:03 UTC (permalink / raw)
  To: linux-arm-kernel

This patch series adds a simple driver for the Samsung Exynos SoC
series DP transmitter PHY, using the generic PHY framework [1].
Previously the DP PHY used an internal DT node to control the PHY
power enable bit.

These patches was tested on Exynos5250.

This PATCH v6 follows:
 * PATCH v5, sent on July, 8th 2013
 * PATCH v4, sent on July, 2nd 2013
 * PATCH v3, sent on July, 1st 2013
 * PATCH v2, sent on June, 28th 2013
 * PATCH v1, sent on June, 28th 2013

Changes between v5 and v6:
  * Re-based on git://gitorious.org/linuxphy/linuxphy.git

Changes between v4 and v5:
  * Marked original bindings as deprecated in 'exynos_dp.txt'
  * Fixed typo of commit message.
  * Added Tomasz Figa's Reviewed-by.

Changes between v3 and v4:
  * Added OF dependancy.
  * Removed redundant local variable 'void __iomem *addr'.
  * Removed unnecessary dev_set_drvdata().
  * Added a patch that remove non-DT support for Exynos
    Display Port driver.
  * Removed unnecessary 'struct exynos_dp_platdata'.
  * Kept supporting the original bindings for DT compatibility.

Changes between v2 and v3:
  * Removed redundant spinlock
  * Removed 'struct phy' from 'struct exynos_dp_video_phy'
  * Updated 'samsung-phy.txt', instead of creating
    'samsung,exynos5250-dp-video-phy.txt'.
  * Removed unnecessary additional specifier from 'phys'
    DT property.
  * Added 'phys', 'phy-names' properties to 'exynos_dp.txt' file.
  * Added Felipe Balbi's Acked-by.

Changes between v1 and v2:
  * Replaced exynos_dp_video_phy_xlate() with of_phy_simple_xlate(),
    as Kishon Vijay Abraham I guided.
  * Set the value of phy-cells as 0, because the phy_provider implements
    only one PHY.
  * Removed unnecessary header include.
  * Added '#ifdef CONFIG_OF' and of_match_ptr macro.

This series depends on the generic PHY framework [1]. These patches
refer to Sylwester Nawrocki's patches about Exynos MIPI [2].

[1] https://lkml.org/lkml/2013/6/26/259
[2] http://www.spinics.net/lists/linux-samsung-soc/msg20098.html

Jingoo Han (4):
  ARM: dts: Add DP PHY node to exynos5250.dtsi
  phy: Add driver for Exynos DP PHY
  video: exynos_dp: remove non-DT support for Exynos Display Port
  video: exynos_dp: Use the generic PHY driver

 .../devicetree/bindings/phy/samsung-phy.txt        |    8 ++
 .../devicetree/bindings/video/exynos_dp.txt        |   18 +++++++++---------
 arch/arm/boot/dts/exynos5250.dtsi                  |   13 ++++++++-----
 drivers/phy/Kconfig                                |    6 ++
 drivers/phy/Makefile                               |    1 +
 drivers/phy/phy-exynos-dp-video.c                  |  111 ++++++++++++++++++++
 drivers/video/exynos/Kconfig                       |    2 +-
 drivers/video/exynos/exynos_dp_core.c              |  132 +++++++----------------------
 drivers/video/exynos/exynos_dp_core.h              |  110 +++++++++++++++++++++++++++
 drivers/video/exynos/exynos_dp_reg.c               |    2 -
 include/video/exynos_dp.h                          |  131 ---------------------------------
 11 files changed, 291 insertions(+), 243 deletions(-) 
 create mode 100644 drivers/phy/phy-exynos-dp-video.c
 delete mode 100644 include/video/exynos_dp.h

--
1.7.10.4


^ 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