All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH/RFC 0/5] HDMI driver for Samsung S5PV310 platform
@ 2011-02-08  9:30 Tomasz Stanislawski
  2011-02-08  9:30 ` [PATCH 1/5] i2c-s3c2410: fix I2C dedicated for hdmiphy Tomasz Stanislawski
                   ` (5 more replies)
  0 siblings, 6 replies; 23+ messages in thread
From: Tomasz Stanislawski @ 2011-02-08  9:30 UTC (permalink / raw)
  To: linux-media, linux-samsung-soc; +Cc: m.szyprowski, t.stanislaws, kyungmin.park

==============
 Introduction
==============

The purpose of this RFC is to discuss the driver for a TV output interface
available in upcoming Samsung SoC. The HW is able to generate digital and
analog signals. Current version of the driver supports only digital output.

Internally the driver uses videobuf2 framework, and CMA memory allocator.  Not
all of them are merged by now, but I decided to post the sources to start
discussion driver's design.

======================
 Hardware description
======================

The SoC contains a few HW sub-blocks:

1. Video Processor (VP). It is used for processing of NV12 data.  An image
stored in RAM is accessed by DMA. Pixels are cropped, scaled. Additionally,
post processing operations like brightness, sharpness and contrast adjustments
could be performed. The output in YCbCr444 format is send to Mixer.

2. Mixer (MXR). The piece of hardware responsible for mixing and blending
multiple data inputs before passing it to an output device.  The MXR is capable
of handling up to three image layers. One is the output of VP.  Other two are
images in RGB format (multiple variants are supported).  The layers are scaled,
cropped and blended with background color.  The blending factor, and layers'
priority are controlled by MXR's registers. The output is passed either to HDMI
or TVOUT.

3. HDMI. The piece of HW responsible for generation of HDMI packets. It takes
pixel data from mixer and transforms it into data frames. The output is send
to HDMIPHY interface.

4. HDMIPHY. Physical interface for HDMI. Its duties are sending HDMI packets to
HDMI connector. Basically, it contains a PLL that produces source clock for
Mixer, VP and HDMI during streaming.

5. TVOUT. Generation of TV analog signal. (driver not implemented)

6. VideoDAC. Modulator for TVOUT signal. (driver not implemented)


The diagram below depicts connection between all HW pieces.
                    +-----------+
NV12 data ---dma--->|   Video   |
                    | Processor |
                    +-----------+
                          |
                          V
                    +-----------+
RGB data  ---dma--->|           |
                    |   Mixer   |
RGB data  ---dma--->|           |
                    +-----------+
                          |
                          * dmux
                         /
                  +-----*   *------+
                  |                |
                  V                V
            +-----------+    +-----------+
            |    HDMI   |    |   TVOUT   |
            +-----------+    +-----------+
                  |                |
                  V                V
            +-----------+    +-----------+
            |  HDMIPHY  |    |  VideoDAC |
            +-----------+    +-----------+
                  |                |
                  V                V
                HDMI           Composite
             connector         connector


==================
 Driver interface
==================

The posted driver implements three V4L2 nodes. Every video node implements V4L2
output buffer. One of nodes corresponds to input of Video Processor. The other
two nodes correspond to RGB inputs of Mixer. All nodes share the same output.
It is one of the Mixer's outputs: TVOUT or HDMI. Changing output in one layer
using S_OUTPUT would change outputs of all other video nodes. The same thing
happens if one try to reconfigure output i.e. by calling S_DV_PRESET. However
it not possible to change or reconfigure the output while streaming. To sum up,
all features in posted version of driver goes as follows:

1. QUERYCAP
2. S_FMT, G_FMT - single and multiplanar API
  a) node named video0 supports formats NV12, NV12, NV12T (tiled version of
NV12), NV12MT (multiplane version of NV12T).
  b) nodes named graph0 and graph1 support formats RGB565, ARGB1555, ARGB4444,
ARGB8888.
3. Buffer with USERPTR and MMAP memory.
4. Streaming and buffer control. (STREAMON, STREAMOFF, REQBUF, QBUF, DQBUF)
5. OUTPUT enumeration.
6. DV preset control (SET, GET, ENUM). Currently modes 480P59_94, 720P59_94,
1080P30, 1080P59_94 and 1080P60 work.
7. Positioning layer's window on output display using S_CROP, G_GROP, CROPCAP.
8. Positioning and cropping data in buffer using S_CROP, G_GROP, CROPCAP with
buffer type OVERLAY. *

TODOs:
- add analog TVOUT driver
- add S_OUTPUT
- add S_STD ioctl
- add control of alpha blending / chroma keying via V4L2 controls
- add controls for luminance curve and sharpness in VP
- consider exporting all output functionalities to separate video node
- consider media controller framework
- better control over debugging
- fix dependency between all TV drivers

* The need of cropping in source buffers came from problem with MFC driver for
S5P. The MFC supports only width divisible by 64. If a width of a decoded movie
is not aligned do 64 then padding pixels are filled with zeros. This is an ugly
green color in YCbCr colorspace. Filling it with zeros by a CPU is a waste of
resources since an image can be cropped in VP. Is it possible to set crops for
user data for M2M devices. V4L2 lacks such functionality of non-M2M devices.
Therefore cropping in buffer V4L2_BUF_TYPE_VIDEO_OVERLAY was used as an work
around.

=====================
 Device Architecture
=====================

Three drivers are added in this patch.

1. HDMIPHY. It is an I2C driver for HDMIPHY interface. It exports following
callback by V4L2 subdevice:
- s_power: currently stub
- s_stream: configures and starts/stops HDMIPHY
- s_dv_preset: used to choose proper frequency of clock for other TV devices

2. HDMI. The auxiliary driver used to control HDMI interface. It exports its
subdev to a subdev pool for use by other drivers. The following callbacks are
implemented:
- s_power: runs HDMI hardware, regulators and clocks.
- s_stream: runs HDMIPHY and starts generation of video frames.
- enum_dv_presets
- s_dv_preset
- g_mbus_format: returns information on data format expected by on HDMI input
  The driver supports an interrupt. It is used to detect plug/unplug events in
kernel debugs.  The API for detection of such an events in V4L2 API is to be
defined.

3. Mixer & Video Processor driver. It is called 's5p-mixer' because of
historical reasons. It was decided combine VP and MXR drivers into one because
of shared interrupt and very similar interface via V4L2 nodes. The driver is a
realization of many-to-many relation between multiple input layers and multiple
outputs. All shared resources are kept in struct mxr_device. It provides
utilities for management and synchronization of access to resources and
reference counting. The outputs are obtained from subdev pool basing on names
supplied in platform data. One layer is a single video node. Since layers
differs simple inheritance is applied. Every layer type implements set of ops.
There are different ops for Mixer layers and other for VP layer.

The videobuf2 framework was used for the management of buffers and streaming.
All other V4L2 ioctls are processed in layers common interface. The CMA was
used as memory allocator for Mixer's buffers. It could be easily exchanged with
any other allocator integrated with videobuf2 framework.

Driver is not yet integrated with power domain driver. Moreover one of mixer's
clocks has to change parent while entering streaming mode. Therefore all power
and clock management was moved to platform data until final solutions emerges.

===============
 Usage summary
===============

Follow steps below to display double-buffered animation on HDMI output.

01. Open video node named graph0.
02. S_FMT(type = OUTPUT, pixelformat = V4L2_PIX_FMT_RGB*, width, height, ...)
03. REQ_BUFS(type = OUTPUT, memory = MMAP, count = 2)
04. MMAP(type = OUTPUT, index = 0)
05. MMAP(type = OUTPUT, index = 1)
06. Fill buffer 0 with data
07. QBUF(type = OUTPUT, index = 0)
08. STREAM_ON(type = OUTPUT)
09. Fill buffer 1 with data
10. QBUF(type = OUTPUT, index = 1)
11. DQBUF(type = OUTPUT)
12. QBUF(type = OUTPUT, index = 0)
13. DQBUF(type = OUTPUT)
14. Goto 09

===============
 Patch Summary
===============

Tomasz Stanislawski (5):
  i2c-s3c2410: fix I2C dedicated for hdmiphy
  universal: i2c: add I2C controller 8 (HDMIPHY)
  v4l: add macro for 1080p59_54 preset
  s5p-tv: add driver for HDMI output on S5PC210 platform
  s5pc210: add s5p-tv to platform devices

 arch/arm/mach-s5pv310/Kconfig                   |    7 +
 arch/arm/mach-s5pv310/Makefile                  |    1 +
 arch/arm/mach-s5pv310/clock.c                   |  132 ++-
 arch/arm/mach-s5pv310/dev-tv.c                  |  450 ++++++
 arch/arm/mach-s5pv310/include/mach/irqs.h       |    8 +
 arch/arm/mach-s5pv310/include/mach/map.h        |   27 +
 arch/arm/mach-s5pv310/include/mach/regs-clock.h |   15 +
 arch/arm/plat-samsung/Kconfig                   |    5 +
 arch/arm/plat-samsung/Makefile                  |    1 +
 arch/arm/plat-samsung/dev-i2c8.c                |   68 +
 arch/arm/plat-samsung/include/plat/devs.h       |    3 +
 arch/arm/plat-samsung/include/plat/iic.h        |    1 +
 arch/arm/plat-samsung/include/plat/tv.h         |   36 +
 drivers/i2c/busses/i2c-s3c2410.c                |   36 +-
 drivers/media/video/Kconfig                     |    8 +
 drivers/media/video/Makefile                    |    1 +
 drivers/media/video/s5p-tv/Kconfig              |   42 +
 drivers/media/video/s5p-tv/Makefile             |   15 +
 drivers/media/video/s5p-tv/hdmi.h               |   74 +
 drivers/media/video/s5p-tv/hdmi_drv.c           |  795 ++++++++++
 drivers/media/video/s5p-tv/hdmiphy.h            |   37 +
 drivers/media/video/s5p-tv/hdmiphy_drv.c        |  228 +++
 drivers/media/video/s5p-tv/mixer.h              |  281 ++++
 drivers/media/video/s5p-tv/mixer_drv.c          |  362 +++++
 drivers/media/video/s5p-tv/mixer_grp_layer.c    |  181 +++
 drivers/media/video/s5p-tv/mixer_reg.c          |  532 +++++++
 drivers/media/video/s5p-tv/mixer_reg.h          |   44 +
 drivers/media/video/s5p-tv/mixer_video.c        |  834 ++++++++++
 drivers/media/video/s5p-tv/mixer_vp_layer.c     |  202 +++
 drivers/media/video/s5p-tv/regs-hdmi.h          | 1849 +++++++++++++++++++++++
 drivers/media/video/s5p-tv/regs-vmx.h           |  196 +++
 drivers/media/video/s5p-tv/regs-vp.h            |  277 ++++
 drivers/media/video/v4l2-common.c               |    1 +
 include/linux/videodev2.h                       |    1 +
 34 files changed, 6748 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm/mach-s5pv310/dev-tv.c
 create mode 100644 arch/arm/plat-samsung/dev-i2c8.c
 create mode 100644 arch/arm/plat-samsung/include/plat/tv.h
 create mode 100644 drivers/media/video/s5p-tv/Kconfig
 create mode 100644 drivers/media/video/s5p-tv/Makefile
 create mode 100644 drivers/media/video/s5p-tv/hdmi.h
 create mode 100644 drivers/media/video/s5p-tv/hdmi_drv.c
 create mode 100644 drivers/media/video/s5p-tv/hdmiphy.h
 create mode 100644 drivers/media/video/s5p-tv/hdmiphy_drv.c
 create mode 100644 drivers/media/video/s5p-tv/mixer.h
 create mode 100644 drivers/media/video/s5p-tv/mixer_drv.c
 create mode 100644 drivers/media/video/s5p-tv/mixer_grp_layer.c
 create mode 100644 drivers/media/video/s5p-tv/mixer_reg.c
 create mode 100644 drivers/media/video/s5p-tv/mixer_reg.h
 create mode 100644 drivers/media/video/s5p-tv/mixer_video.c
 create mode 100644 drivers/media/video/s5p-tv/mixer_vp_layer.c
 create mode 100644 drivers/media/video/s5p-tv/regs-hdmi.h
 create mode 100644 drivers/media/video/s5p-tv/regs-vmx.h
 create mode 100644 drivers/media/video/s5p-tv/regs-vp.h

-- 
1.7.3.5


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH 1/5] i2c-s3c2410: fix I2C dedicated for hdmiphy
  2011-02-08  9:30 [PATCH/RFC 0/5] HDMI driver for Samsung S5PV310 platform Tomasz Stanislawski
@ 2011-02-08  9:30 ` Tomasz Stanislawski
  2011-02-09  7:14   ` Kukjin Kim
  2011-02-08  9:30 ` [PATCH 2/5] universal: i2c: add I2C controller 8 (HDMIPHY) Tomasz Stanislawski
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 23+ messages in thread
From: Tomasz Stanislawski @ 2011-02-08  9:30 UTC (permalink / raw)
  To: linux-media, linux-samsung-soc; +Cc: m.szyprowski, t.stanislaws, kyungmin.park

The I2C HDMIPHY dedicated controller has different timeout
handling and reset conditions.

Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 drivers/i2c/busses/i2c-s3c2410.c |   36 +++++++++++++++++++++++++++++++++++-
 1 files changed, 35 insertions(+), 1 deletions(-)

diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index 6c00c10..99cfe2f 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -54,6 +54,7 @@ enum s3c24xx_i2c_state {
 enum s3c24xx_i2c_type {
 	TYPE_S3C2410,
 	TYPE_S3C2440,
+	TYPE_S3C2440_HDMIPHY,
 };
 
 struct s3c24xx_i2c {
@@ -96,7 +97,21 @@ static inline int s3c24xx_i2c_is2440(struct s3c24xx_i2c *i2c)
 	enum s3c24xx_i2c_type type;
 
 	type = platform_get_device_id(pdev)->driver_data;
-	return type == TYPE_S3C2440;
+	return type == TYPE_S3C2440 || type == TYPE_S3C2440_HDMIPHY;
+}
+
+/* s3c24xx_i2c_is2440_hdmiphy()
+ *
+ * return true is this is an s3c2440 dedicated for HDMIPHY interface
+*/
+
+static inline int s3c24xx_i2c_is2440_hdmiphy(struct s3c24xx_i2c *i2c)
+{
+	struct platform_device *pdev = to_platform_device(i2c->dev);
+	enum s3c24xx_i2c_type type;
+
+	type = platform_get_device_id(pdev)->driver_data;
+	return type == TYPE_S3C2440_HDMIPHY;
 }
 
 /* s3c24xx_i2c_master_complete
@@ -461,6 +476,13 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c)
 	unsigned long iicstat;
 	int timeout = 400;
 
+	/* if hang-up of HDMIPHY occured reduce timeout
+	 * The controller will work after reset, so waiting
+	 * 400 ms will cause unneccessary system hangup
+	 */
+	if (s3c24xx_i2c_is2440_hdmiphy(i2c))
+		timeout = 10;
+
 	while (timeout-- > 0) {
 		iicstat = readl(i2c->regs + S3C2410_IICSTAT);
 
@@ -470,6 +492,15 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c)
 		msleep(1);
 	}
 
+	/* hang-up of bus dedicated for HDMIPHY occured, resetting */
+	if (s3c24xx_i2c_is2440_hdmiphy(i2c)) {
+		writel(0, i2c->regs + S3C2410_IICCON);
+		writel(0, i2c->regs + S3C2410_IICSTAT);
+		writel(0, i2c->regs + S3C2410_IICDS);
+
+		return 0;
+	}
+
 	return -ETIMEDOUT;
 }
 
@@ -1009,6 +1040,9 @@ static struct platform_device_id s3c24xx_driver_ids[] = {
 	}, {
 		.name		= "s3c2440-i2c",
 		.driver_data	= TYPE_S3C2440,
+	}, {
+		.name		= "s3c2440-hdmiphy-i2c",
+		.driver_data	= TYPE_S3C2440_HDMIPHY,
 	}, { },
 };
 MODULE_DEVICE_TABLE(platform, s3c24xx_driver_ids);
-- 
1.7.3.5


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 2/5] universal: i2c: add I2C controller 8 (HDMIPHY)
  2011-02-08  9:30 [PATCH/RFC 0/5] HDMI driver for Samsung S5PV310 platform Tomasz Stanislawski
  2011-02-08  9:30 ` [PATCH 1/5] i2c-s3c2410: fix I2C dedicated for hdmiphy Tomasz Stanislawski
@ 2011-02-08  9:30 ` Tomasz Stanislawski
  2011-02-09  6:54   ` Kukjin Kim
  2011-02-08  9:30 ` [PATCH 3/5] v4l: add macro for 1080p59_54 preset Tomasz Stanislawski
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 23+ messages in thread
From: Tomasz Stanislawski @ 2011-02-08  9:30 UTC (permalink / raw)
  To: linux-media, linux-samsung-soc; +Cc: m.szyprowski, t.stanislaws, kyungmin.park

Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 arch/arm/mach-s5pv310/clock.c             |    6 +++
 arch/arm/mach-s5pv310/include/mach/irqs.h |    4 ++
 arch/arm/mach-s5pv310/include/mach/map.h  |    1 +
 arch/arm/plat-samsung/Kconfig             |    5 ++
 arch/arm/plat-samsung/Makefile            |    1 +
 arch/arm/plat-samsung/dev-i2c8.c          |   68 +++++++++++++++++++++++++++++
 arch/arm/plat-samsung/include/plat/devs.h |    1 +
 arch/arm/plat-samsung/include/plat/iic.h  |    1 +
 8 files changed, 87 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/plat-samsung/dev-i2c8.c

diff --git a/arch/arm/mach-s5pv310/clock.c b/arch/arm/mach-s5pv310/clock.c
index fc7c2f8..6161b54 100644
--- a/arch/arm/mach-s5pv310/clock.c
+++ b/arch/arm/mach-s5pv310/clock.c
@@ -589,6 +589,12 @@ static struct clk init_clocks_off[] = {
 		.parent		= &clk_aclk_100.clk,
 		.enable		= s5pv310_clk_ip_peril_ctrl,
 		.ctrlbit	= (1 << 13),
+	}, {
+		.name           = "i2c",
+		.id             = 8,
+		.parent         = &clk_aclk_100.clk,
+		.enable         = s5pv310_clk_ip_peril_ctrl,
+		.ctrlbit        = (1 << 14),
 	},
 };
 
diff --git a/arch/arm/mach-s5pv310/include/mach/irqs.h b/arch/arm/mach-s5pv310/include/mach/irqs.h
index 536b0b5..0ba778b 100644
--- a/arch/arm/mach-s5pv310/include/mach/irqs.h
+++ b/arch/arm/mach-s5pv310/include/mach/irqs.h
@@ -76,6 +76,9 @@
 #define IRQ_PDMA0		COMBINER_IRQ(21, 0)
 #define IRQ_PDMA1		COMBINER_IRQ(21, 1)
 
+#define IRQ_HDMI		COMBINER_IRQ(16, 0)
+#define IRQ_HDMI_I2C		COMBINER_IRQ(16, 1)
+
 #define IRQ_TIMER0_VIC		COMBINER_IRQ(22, 0)
 #define IRQ_TIMER1_VIC		COMBINER_IRQ(22, 1)
 #define IRQ_TIMER2_VIC		COMBINER_IRQ(22, 2)
@@ -99,6 +102,7 @@
 #define IRQ_IIC5		COMBINER_IRQ(27, 5)
 #define IRQ_IIC6		COMBINER_IRQ(27, 6)
 #define IRQ_IIC7		COMBINER_IRQ(27, 7)
+#define IRQ_IIC8		IRQ_HDMI_I2C
 
 #define IRQ_HSMMC0		COMBINER_IRQ(29, 0)
 #define IRQ_HSMMC1		COMBINER_IRQ(29, 1)
diff --git a/arch/arm/mach-s5pv310/include/mach/map.h b/arch/arm/mach-s5pv310/include/mach/map.h
index 74d4006..845b739 100644
--- a/arch/arm/mach-s5pv310/include/mach/map.h
+++ b/arch/arm/mach-s5pv310/include/mach/map.h
@@ -141,6 +141,7 @@
 #define S3C_PA_IIC5			S5PV310_PA_IIC(5)
 #define S3C_PA_IIC6			S5PV310_PA_IIC(6)
 #define S3C_PA_IIC7			S5PV310_PA_IIC(7)
+#define S3C_PA_IIC8			S5PV310_PA_IIC(8)
 #define S3C_PA_RTC			S5PV310_PA_RTC
 #define S3C_PA_WDT			S5PV310_PA_WATCHDOG
 #define S5P_PA_MIPI_CSIS0		S5PV310_PA_MIPI_CSIS0
diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
index 32be05c..dd1fd15 100644
--- a/arch/arm/plat-samsung/Kconfig
+++ b/arch/arm/plat-samsung/Kconfig
@@ -211,6 +211,11 @@ config S3C_DEV_I2C7
 	help
 	  Compile in platform device definition for I2C controller 7
 
+config S3C_DEV_I2C8
+	bool
+	help
+	  Compile in platform device definitions for I2C channel 8 (HDMIPHY)
+
 config S3C_DEV_FB
 	bool
 	help
diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile
index 29932f8..5df8db7 100644
--- a/arch/arm/plat-samsung/Makefile
+++ b/arch/arm/plat-samsung/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_S3C_DEV_I2C4)	+= dev-i2c4.o
 obj-$(CONFIG_S3C_DEV_I2C5)	+= dev-i2c5.o
 obj-$(CONFIG_S3C_DEV_I2C6)	+= dev-i2c6.o
 obj-$(CONFIG_S3C_DEV_I2C7)	+= dev-i2c7.o
+obj-$(CONFIG_S3C_DEV_I2C8)	+= dev-i2c8.o
 obj-$(CONFIG_S3C_DEV_FB)	+= dev-fb.o
 obj-y				+= dev-uart.o
 obj-$(CONFIG_S3C_DEV_USB_HOST)	+= dev-usb.o
diff --git a/arch/arm/plat-samsung/dev-i2c8.c b/arch/arm/plat-samsung/dev-i2c8.c
new file mode 100644
index 0000000..8edba7f
--- /dev/null
+++ b/arch/arm/plat-samsung/dev-i2c8.c
@@ -0,0 +1,68 @@
+/* linux/arch/arm/plat-samsung/dev-i2c7.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S3C series device definition for i2c device 8
+ *
+ * Based on plat-samsung/dev-i2c8.c
+ *
+ * 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/gfp.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+
+#include <mach/irqs.h>
+#include <mach/map.h>
+
+#include <plat/regs-iic.h>
+#include <plat/iic.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+
+static struct resource s3c_i2c_resource[] = {
+	[0] = {
+		.start = S3C_PA_IIC8,
+		.end   = S3C_PA_IIC8 + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_IIC8,
+		.end   = IRQ_IIC8,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device s3c_device_i2c8 = {
+	.name		  = "s3c2440-hdmiphy-i2c",
+	.id		  = 8,
+	.num_resources	  = ARRAY_SIZE(s3c_i2c_resource),
+	.resource	  = s3c_i2c_resource,
+};
+
+static struct s3c2410_platform_i2c default_i2c_data8 __initdata = {
+	.flags		= 0,
+	.bus_num	= 8,
+	.slave_addr	= 0x10,
+	.frequency	= 400*1000,
+	.sda_delay	= 100,
+};
+
+void __init s3c_i2c8_set_platdata(struct s3c2410_platform_i2c *pd)
+{
+	struct s3c2410_platform_i2c *npd;
+
+	if (!pd)
+		pd = &default_i2c_data8;
+
+	npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL);
+	if (!npd)
+		printk(KERN_ERR "%s: no memory for platform data\n", __func__);
+
+	s3c_device_i2c8.dev.platform_data = npd;
+}
diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h
index b4d208b..6effbb4 100644
--- a/arch/arm/plat-samsung/include/plat/devs.h
+++ b/arch/arm/plat-samsung/include/plat/devs.h
@@ -53,6 +53,7 @@ extern struct platform_device s3c_device_i2c4;
 extern struct platform_device s3c_device_i2c5;
 extern struct platform_device s3c_device_i2c6;
 extern struct platform_device s3c_device_i2c7;
+extern struct platform_device s3c_device_i2c8;
 extern struct platform_device s3c_device_rtc;
 extern struct platform_device s3c_device_adc;
 extern struct platform_device s3c_device_sdi;
diff --git a/arch/arm/plat-samsung/include/plat/iic.h b/arch/arm/plat-samsung/include/plat/iic.h
index 1543da8..dd0d728 100644
--- a/arch/arm/plat-samsung/include/plat/iic.h
+++ b/arch/arm/plat-samsung/include/plat/iic.h
@@ -60,6 +60,7 @@ extern void s3c_i2c4_set_platdata(struct s3c2410_platform_i2c *i2c);
 extern void s3c_i2c5_set_platdata(struct s3c2410_platform_i2c *i2c);
 extern void s3c_i2c6_set_platdata(struct s3c2410_platform_i2c *i2c);
 extern void s3c_i2c7_set_platdata(struct s3c2410_platform_i2c *i2c);
+extern void s3c_i2c8_set_platdata(struct s3c2410_platform_i2c *i2c);
 
 /* defined by architecture to configure gpio */
 extern void s3c_i2c0_cfg_gpio(struct platform_device *dev);
-- 
1.7.3.5


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 3/5] v4l: add macro for 1080p59_54 preset
  2011-02-08  9:30 [PATCH/RFC 0/5] HDMI driver for Samsung S5PV310 platform Tomasz Stanislawski
  2011-02-08  9:30 ` [PATCH 1/5] i2c-s3c2410: fix I2C dedicated for hdmiphy Tomasz Stanislawski
  2011-02-08  9:30 ` [PATCH 2/5] universal: i2c: add I2C controller 8 (HDMIPHY) Tomasz Stanislawski
@ 2011-02-08  9:30 ` Tomasz Stanislawski
  2011-02-08  9:30 ` [PATCH 4/5] s5p-tv: add driver for HDMI output on S5PC210 platform Tomasz Stanislawski
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 23+ messages in thread
From: Tomasz Stanislawski @ 2011-02-08  9:30 UTC (permalink / raw)
  To: linux-media, linux-samsung-soc; +Cc: m.szyprowski, t.stanislaws, kyungmin.park

The 1080p59_94 is supported in latest Samusng SoC.

Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 drivers/media/video/v4l2-common.c |    1 +
 include/linux/videodev2.h         |    1 +
 2 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
index 810eef4..96742d1 100644
--- a/drivers/media/video/v4l2-common.c
+++ b/drivers/media/video/v4l2-common.c
@@ -646,6 +646,7 @@ int v4l_fill_dv_preset_info(u32 preset, struct v4l2_dv_enum_preset *info)
 		{ 1920, 1080, "1080p@30" },	/* V4L2_DV_1080P30 */
 		{ 1920, 1080, "1080p@50" },	/* V4L2_DV_1080P50 */
 		{ 1920, 1080, "1080p@60" },	/* V4L2_DV_1080P60 */
+		{ 1920, 1080, "1080p@59.94" },	/* V4L2_DV_1080P59_94 */
 	};
 
 	if (info == NULL || preset >= ARRAY_SIZE(dv_presets))
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 5122b26..5a8f0ba 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -862,6 +862,7 @@ struct v4l2_dv_enum_preset {
 #define		V4L2_DV_1080P30		16 /* SMPTE 296M */
 #define		V4L2_DV_1080P50		17 /* BT.1120 */
 #define		V4L2_DV_1080P60		18 /* BT.1120 */
+#define		V4L2_DV_1080P59_94	19
 
 /*
  *	D V 	B T	T I M I N G S
-- 
1.7.3.5


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 4/5] s5p-tv: add driver for HDMI output on S5PC210 platform
  2011-02-08  9:30 [PATCH/RFC 0/5] HDMI driver for Samsung S5PV310 platform Tomasz Stanislawski
                   ` (2 preceding siblings ...)
  2011-02-08  9:30 ` [PATCH 3/5] v4l: add macro for 1080p59_54 preset Tomasz Stanislawski
@ 2011-02-08  9:30 ` Tomasz Stanislawski
  2011-02-08  9:30 ` [PATCH 5/5] s5pc210: add s5p-tv to platform devices Tomasz Stanislawski
  2011-02-08  9:47 ` [PATCH/RFC 0/5] HDMI driver for Samsung S5PV310 platform Hans Verkuil
  5 siblings, 0 replies; 23+ messages in thread
From: Tomasz Stanislawski @ 2011-02-08  9:30 UTC (permalink / raw)
  To: linux-media, linux-samsung-soc; +Cc: m.szyprowski, t.stanislaws, kyungmin.park

Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 arch/arm/plat-samsung/include/plat/tv.h      |   36 +
 drivers/media/video/Kconfig                  |    8 +
 drivers/media/video/Makefile                 |    1 +
 drivers/media/video/s5p-tv/Kconfig           |   42 +
 drivers/media/video/s5p-tv/Makefile          |   15 +
 drivers/media/video/s5p-tv/hdmi.h            |   74 +
 drivers/media/video/s5p-tv/hdmi_drv.c        |  795 +++++++++++
 drivers/media/video/s5p-tv/hdmiphy.h         |   37 +
 drivers/media/video/s5p-tv/hdmiphy_drv.c     |  228 ++++
 drivers/media/video/s5p-tv/mixer.h           |  281 ++++
 drivers/media/video/s5p-tv/mixer_drv.c       |  362 +++++
 drivers/media/video/s5p-tv/mixer_grp_layer.c |  181 +++
 drivers/media/video/s5p-tv/mixer_reg.c       |  532 ++++++++
 drivers/media/video/s5p-tv/mixer_reg.h       |   44 +
 drivers/media/video/s5p-tv/mixer_video.c     |  834 ++++++++++++
 drivers/media/video/s5p-tv/mixer_vp_layer.c  |  202 +++
 drivers/media/video/s5p-tv/regs-hdmi.h       | 1849 ++++++++++++++++++++++++++
 drivers/media/video/s5p-tv/regs-vmx.h        |  196 +++
 drivers/media/video/s5p-tv/regs-vp.h         |  277 ++++
 19 files changed, 5994 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/plat-samsung/include/plat/tv.h
 create mode 100644 drivers/media/video/s5p-tv/Kconfig
 create mode 100644 drivers/media/video/s5p-tv/Makefile
 create mode 100644 drivers/media/video/s5p-tv/hdmi.h
 create mode 100644 drivers/media/video/s5p-tv/hdmi_drv.c
 create mode 100644 drivers/media/video/s5p-tv/hdmiphy.h
 create mode 100644 drivers/media/video/s5p-tv/hdmiphy_drv.c
 create mode 100644 drivers/media/video/s5p-tv/mixer.h
 create mode 100644 drivers/media/video/s5p-tv/mixer_drv.c
 create mode 100644 drivers/media/video/s5p-tv/mixer_grp_layer.c
 create mode 100644 drivers/media/video/s5p-tv/mixer_reg.c
 create mode 100644 drivers/media/video/s5p-tv/mixer_reg.h
 create mode 100644 drivers/media/video/s5p-tv/mixer_video.c
 create mode 100644 drivers/media/video/s5p-tv/mixer_vp_layer.c
 create mode 100644 drivers/media/video/s5p-tv/regs-hdmi.h
 create mode 100644 drivers/media/video/s5p-tv/regs-vmx.h
 create mode 100644 drivers/media/video/s5p-tv/regs-vp.h

diff --git a/arch/arm/plat-samsung/include/plat/tv.h b/arch/arm/plat-samsung/include/plat/tv.h
new file mode 100644
index 0000000..218ad2c
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/tv.h
@@ -0,0 +1,36 @@
+/* arch/arm/plat-samsung/include/plat/tv.h
+ *
+ * S5P - TV platform data definitions
+ *
+ * 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 __PLAT_S5P_TV_H
+#define __PLAT_S5P_TV_H __FILE__
+
+#include <linux/device.h>
+
+struct mxr_platform_output {
+	char *output_name;
+	char *module_name;
+};
+
+struct mxr_platform_data {
+	struct mxr_platform_output *output;
+	int output_cnt;
+	int (*init)(struct device *dev);
+	void (*deinit)(struct device *dev);
+	int (*power_setup)(struct device *dev, int on);
+};
+
+struct hdmi_platform_data {
+	int (*init)(struct device *dev);
+	void (*deinit)(struct device *dev);
+	int (*power_setup)(struct device *dev, int on);
+	int (*stream_setup)(struct device *dev, int on);
+};
+
+#endif /* __PLAT_S5P_TV_H */
+
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index d40a8fc..0fe6673 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -1012,3 +1012,11 @@ config  VIDEO_SAMSUNG_S5P_FIMC
 	  (video postprocessor)
 
 endif # V4L_MEM2MEM_DRIVERS
+
+menuconfig VIDEO_SAMSUNG_S5P_TV
+	bool "Digital/analog TV output interfaces"
+	default y
+if VIDEO_SAMSUNG_S5P_TV
+source "drivers/media/video/s5p-tv/Kconfig"
+endif # VIDEO_SAMSUNG_S5P_TV
+
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index 251b7ca..23fd0ac 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -162,6 +162,7 @@ obj-$(CONFIG_VIDEO_SH_MOBILE_CSI2)	+= sh_mobile_csi2.o
 obj-$(CONFIG_VIDEO_SH_MOBILE_CEU)	+= sh_mobile_ceu_camera.o
 obj-$(CONFIG_VIDEO_OMAP1)		+= omap1_camera.o
 obj-$(CONFIG_VIDEO_SAMSUNG_S5P_FIMC) 	+= s5p-fimc/
+obj-$(CONFIG_VIDEO_SAMSUNG_S5P_TV) 	+= s5p-tv/
 
 obj-$(CONFIG_ARCH_DAVINCI)		+= davinci/
 
diff --git a/drivers/media/video/s5p-tv/Kconfig b/drivers/media/video/s5p-tv/Kconfig
new file mode 100644
index 0000000..ec97dd0
--- /dev/null
+++ b/drivers/media/video/s5p-tv/Kconfig
@@ -0,0 +1,42 @@
+# drivers/media/video/samsung/tvout/Kconfig
+#
+# Copyright (c) 2010 Samsung Electronics Co., Ltd.
+#	http://www.samsung.com/
+# Tomasz Stanislawski <t.stanislaws@samsung.com>
+#
+# Licensed under GPLv2
+
+comment "HDMI output drivers"
+
+config VIDEO_SAMSUNG_S5P_HDMIPHY
+	tristate "Samsung HDMIPHY Driver"
+	depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P
+	default y
+	help
+	  Say Y here if you want support for the physical HDMI
+	  interface in S5P Samsung SoC. The driver can be compiled
+	  as module. It is an I2C driver, that produce a V4L2
+	  subdev for use by other drivers.
+
+config VIDEO_SAMSUNG_S5P_HDMI
+	tristate "Samsung HDMI Driver"
+	depends on VIDEO_SAMSUNG_S5P_HDMIPHY
+	help
+	  Say Y here if you want support for the HDMI
+	  interface in S5P Samsung SoC. The driver can be compiled
+	  as module. It is an auxliary driver, that produce a V4L2
+	  subdev for use by other drivers. This driver requires
+	  hdmiphy driver to work correctly.
+
+comment "Analog TV output drivers"
+
+comment "Mixer drivers"
+
+config VIDEO_SAMSUNG_S5P_MIXER
+	tristate "Samsung Mixer and Video Processor Driver"
+	depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P
+	default y
+	select VIDEOBUF_DMA_CONTIG
+	select CMA
+	help
+	  Mixer driver for Samsung ARM based SoC.
diff --git a/drivers/media/video/s5p-tv/Makefile b/drivers/media/video/s5p-tv/Makefile
new file mode 100644
index 0000000..3643794
--- /dev/null
+++ b/drivers/media/video/s5p-tv/Makefile
@@ -0,0 +1,15 @@
+# drivers/media/video/samsung/tvout/Makefile
+#
+# Copyright (c) 2010 Samsung Electronics Co., Ltd.
+#	http://www.samsung.com/
+# Tomasz Stanislawski <t.stanislaws@samsung.com>
+#
+# Licensed under GPLv2
+
+obj-$(CONFIG_VIDEO_SAMSUNG_S5P_HDMIPHY) += s5p-hdmiphy.o
+s5p-hdmiphy-y += hdmiphy_drv.o
+obj-$(CONFIG_VIDEO_SAMSUNG_S5P_HDMI) += s5p-hdmi.o
+s5p-hdmi-y += hdmi_drv.o
+obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MIXER) += s5p-mixer.o
+s5p-mixer-y += mixer_drv.o mixer_video.o mixer_reg.o mixer_grp_layer.o mixer_vp_layer.o
+
diff --git a/drivers/media/video/s5p-tv/hdmi.h b/drivers/media/video/s5p-tv/hdmi.h
new file mode 100644
index 0000000..a2c6073
--- /dev/null
+++ b/drivers/media/video/s5p-tv/hdmi.h
@@ -0,0 +1,74 @@
+/*
+ * Samsung HDMI interface driver
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ *
+ * Tomasz Stanislawski, t.stanislaws@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 Foundiation. either version 2 of the License,
+ * or (at your option) any later version
+ */
+
+#ifndef _SAMSUNG_HDMI_H_
+#define _SAMSUNG_HDMI_H_ __FILE__
+
+#include <linux/kernel.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-mediabus.h>
+
+struct hdmi_tg_regs {
+	u8 cmd;
+	u8 h_fsz_l;
+	u8 h_fsz_h;
+	u8 hact_st_l;
+	u8 hact_st_h;
+	u8 hact_sz_l;
+	u8 hact_sz_h;
+	u8 v_fsz_l;
+	u8 v_fsz_h;
+	u8 vsync_l;
+	u8 vsync_h;
+	u8 vsync2_l;
+	u8 vsync2_h;
+	u8 vact_st_l;
+	u8 vact_st_h;
+	u8 vact_sz_l;
+	u8 vact_sz_h;
+	u8 field_chg_l;
+	u8 field_chg_h;
+	u8 vact_st2_l;
+	u8 vact_st2_h;
+	u8 vsync_top_hdmi_l;
+	u8 vsync_top_hdmi_h;
+	u8 vsync_bot_hdmi_l;
+	u8 vsync_bot_hdmi_h;
+	u8 field_top_hdmi_l;
+	u8 field_top_hdmi_h;
+	u8 field_bot_hdmi_l;
+	u8 field_bot_hdmi_h;
+};
+
+struct hdmi_core_regs {
+	u8 h_blank[2];
+	u8 v_blank[3];
+	u8 h_v_line[3];
+	u8 vsync_pol[1];
+	u8 int_pro_mode[1];
+	u8 v_blank_f[3];
+	u8 h_sync_gen[3];
+	u8 v_sync_gen1[3];
+	u8 v_sync_gen2[3];
+	u8 v_sync_gen3[3];
+};
+
+struct hdmi_preset_conf {
+	struct hdmi_core_regs core;
+	/* u8 tg[29]; */
+	struct hdmi_tg_regs tg;
+	struct v4l2_mbus_framefmt mbus_fmt;
+};
+
+#endif /* _SAMSUNG_HDMI_H_ */
+
diff --git a/drivers/media/video/s5p-tv/hdmi_drv.c b/drivers/media/video/s5p-tv/hdmi_drv.c
new file mode 100644
index 0000000..561c200
--- /dev/null
+++ b/drivers/media/video/s5p-tv/hdmi_drv.c
@@ -0,0 +1,795 @@
+/*
+ * Samsung HDMI interface driver
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ *
+ * Tomasz Stanislawski, t.stanislaws@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 Foundiation. either version 2 of the License,
+ * or (at your option) any later version
+ */
+
+#include "plat/tv.h"
+#include "hdmi.h"
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <media/v4l2-subdev.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#include <linux/bug.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-dev.h>
+#include <media/v4l2-device.h>
+
+#include "regs-hdmi.h"
+
+MODULE_AUTHOR("Tomasz Stanislawski, t.stanislaws@samsung.com");
+MODULE_DESCRIPTION("Samsung HDMI");
+MODULE_LICENSE("GPL");
+
+/* #define HDMI_DEFAULT_PRESET V4L2_DV_480P59_94 */
+/* #define HDMI_DEFAULT_PRESET V4L2_DV_720P59_94 */
+#define HDMI_DEFAULT_PRESET V4L2_DV_1080P60
+/* #define HDMI_DEFAULT_PRESET V4L2_DV_1080P59_94 */
+
+/* D R I V E R   I N I T I A L I Z A T I O N */
+
+static struct platform_driver hdmi_driver;
+
+static int __init hdmi_init(void)
+{
+	int ret;
+	static const char banner[] __initdata = KERN_INFO \
+		"Samsung HDMI output driver, "
+		"(c) 2010 Samsung Electronics\n";
+	printk(banner);
+
+	ret = platform_driver_register(&hdmi_driver);
+	if (ret)
+		printk(KERN_ERR "HDMI platform driver register failed\n");
+
+	return ret;
+}
+module_init(hdmi_init);
+
+static void __exit hdmi_exit(void)
+{
+	platform_driver_unregister(&hdmi_driver);
+}
+module_exit(hdmi_exit);
+
+struct hdmi_device {
+	/** base address of HDMI registers */
+	void __iomem *regs;
+	/** HDMI interrupt */
+	unsigned int irq;
+	/** pointer to device parent */
+	struct device *dev;
+	/** subdev generated by HDMI device */
+	struct v4l2_subdev sd;
+	/** V4L2 device structure */
+	struct v4l2_device vdev;
+	/** subdev of HDMIPHY interface */
+	struct v4l2_subdev *phy_sd;
+	/** configuration of current graphic mode */
+	const struct hdmi_preset_conf *cur_conf;
+	/** current preset */
+	u32 cur_preset;
+};
+
+/* FIXME: this parameters should be acquired from platform data */
+static struct i2c_board_info hdmiphy_info = {
+	I2C_BOARD_INFO("hdmiphy", 0x38),
+	/* .irq = IRQ_HDMI_I2C, */
+};
+static int hdmiphy_bus = 8;
+
+static irqreturn_t hdmi_irq_handler(int irq, void *dev_data);
+
+static const struct v4l2_subdev_ops hdmi_sd_ops;
+
+static const struct hdmi_preset_conf *hdmi_preset2conf(u32 preset);
+
+#define CHECK_POINT dev_err(dev, "%s:%d\n", __func__, __LINE__)
+
+static struct hdmi_device *sd_to_hdmi_dev(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct hdmi_device, sd);
+}
+
+static int __devinit hdmi_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	struct i2c_adapter *phy_adapter;
+	struct hdmi_platform_data *pdata = dev->platform_data;
+	struct v4l2_subdev *sd;
+	struct hdmi_device *hdmi_dev = NULL;
+
+	int ret;
+
+	dev_info(dev, "probe start\n");
+
+	if (pdata->init) {
+		ret = pdata->init(dev);
+		if (ret)
+			goto fail;
+	}
+
+	hdmi_dev = kzalloc(sizeof(*hdmi_dev), GFP_KERNEL);
+	if (!hdmi_dev) {
+		dev_err(dev, "not enough memory.\n");
+		ret = -ENOMEM;
+		goto fail_init;
+	}
+
+	hdmi_dev->dev = dev;
+
+	/* mapping HDMI registers */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		dev_err(dev, "get memory resource failed.\n");
+		ret = -ENXIO;
+		goto fail_hdev;
+	}
+
+	/* TODO: add request_mem_region */
+	hdmi_dev->regs = ioremap(res->start, resource_size(res));
+	if (hdmi_dev->regs == NULL) {
+		dev_err(dev, "register mapping failed.\n");
+		ret = -ENXIO;
+		goto fail_hdev;
+	}
+
+	/* acquiring HDMI interrupt */
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (res == NULL) {
+		dev_err(dev, "get interrupt resource failed.\n");
+		ret = -ENXIO;
+		goto fail_regs;
+	}
+
+	ret = request_irq(res->start, hdmi_irq_handler, 0, "hdmi", hdmi_dev);
+	if (ret) {
+		dev_err(dev, "request interrupt failed.\n");
+		goto fail_regs;
+	}
+	hdmi_dev->irq = res->start;
+
+	ret = v4l2_device_register(dev, &hdmi_dev->vdev);
+	if (ret) {
+		dev_err(dev, "could not register v4l2 device.\n");
+		goto fail_irq;
+	}
+
+	phy_adapter = i2c_get_adapter(hdmiphy_bus);
+	if (phy_adapter == NULL) {
+		dev_err(dev, "adapter request failed\n");
+		ret = -ENXIO;
+		goto fail_vdev;
+	}
+
+	hdmi_dev->phy_sd = v4l2_i2c_new_subdev_board(&hdmi_dev->vdev,
+		phy_adapter, &hdmiphy_info, NULL);
+	/* on failure or not adapter is no longer useful */
+	i2c_put_adapter(phy_adapter);
+	if (hdmi_dev->phy_sd == NULL) {
+		dev_err(dev, "missing subdev for hdmiphy\n");
+		ret = -ENODEV;
+		goto fail_vdev;
+	}
+
+	sd = &hdmi_dev->sd;
+	v4l2_subdev_init(sd, &hdmi_sd_ops);
+
+	strlcpy(sd->name, hdmi_driver.driver.name, sizeof sd->name);
+	hdmi_dev->cur_preset = HDMI_DEFAULT_PRESET;
+	/* FIXME: missing fail preset is not supported */
+	hdmi_dev->cur_conf = hdmi_preset2conf(hdmi_dev->cur_preset);
+
+	/* storing subdev for call that have only access to struct device */
+	dev_set_drvdata(dev, sd);
+
+	dev_info(dev, "probe sucessful\n");
+
+	return 0;
+
+fail_vdev:
+	v4l2_device_unregister(&hdmi_dev->vdev);
+
+fail_irq:
+	free_irq(hdmi_dev->irq, hdmi_dev);
+
+fail_regs:
+	iounmap(hdmi_dev->regs);
+
+fail_hdev:
+	kfree(hdmi_dev);
+
+fail_init:
+	if (pdata->deinit)
+		pdata->deinit(dev);
+
+fail:
+	dev_info(dev, "probe failed\n");
+	return ret;
+}
+
+static int __devexit hdmi_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct hdmi_platform_data *pdata = dev->platform_data;
+	struct v4l2_subdev *sd = dev_get_drvdata(dev);
+	struct hdmi_device *hdmi_dev = sd_to_hdmi_dev(sd);
+
+	v4l2_device_unregister(&hdmi_dev->vdev);
+	disable_irq(hdmi_dev->irq);
+	free_irq(hdmi_dev->irq, hdmi_dev);
+	iounmap(hdmi_dev->regs);
+	kfree(hdmi_dev);
+	if (pdata->deinit)
+		pdata->deinit(dev);
+	dev_info(dev, "remove sucessful\n");
+	return 0;
+}
+
+static struct platform_driver hdmi_driver __refdata = {
+	.probe = hdmi_probe,
+	.remove = __devexit_p(hdmi_remove),
+	.driver = {
+		.name = "s5p-hdmi",
+		.owner = THIS_MODULE,
+	}
+};
+
+static inline
+void hdmi_write(struct hdmi_device *hdev, u32 reg_id, u32 value)
+{
+	writel(value, hdev->regs + reg_id);
+}
+
+static inline
+void hdmi_write_mask(struct hdmi_device *hdev, u32 reg_id, u32 value, u32 mask)
+{
+	u32 old = readl(hdev->regs + reg_id);
+	value = (value & mask) | (old & ~mask);
+	writel(value, hdev->regs + reg_id);
+}
+
+static inline
+void hdmi_writeb(struct hdmi_device *hdev, u32 reg_id, u8 value)
+{
+	writeb(value, hdev->regs + reg_id);
+}
+
+static inline u32 hdmi_read(struct hdmi_device *hdev, u32 reg_id)
+{
+	return readl(hdev->regs + reg_id);
+}
+
+static irqreturn_t hdmi_irq_handler(int irq, void *dev_data)
+{
+	struct hdmi_device *hdev = dev_data;
+	u32 intc_flag;
+	(void)irq;
+	/* TODO: add V4L2 event generation */
+
+	intc_flag = hdmi_read(hdev, HDMI_INTC_FLAG);
+	/* clearing flags for HPD plug/unplug */
+	if (intc_flag & HDMI_INTC_FLAG_HPD_UNPLUG) {
+		printk(KERN_INFO "unplugged\n");
+		hdmi_write_mask(hdev, HDMI_INTC_FLAG, ~0,
+			HDMI_INTC_FLAG_HPD_UNPLUG);
+	}
+	if (intc_flag & HDMI_INTC_FLAG_HPD_PLUG) {
+		printk(KERN_INFO "plugged\n");
+		hdmi_write_mask(hdev, HDMI_INTC_FLAG, ~0,
+			HDMI_INTC_FLAG_HPD_PLUG);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int hdmi_s_dv_preset(struct v4l2_subdev *sd,
+	struct v4l2_dv_preset *preset);
+
+static int hdmi_s_power(struct v4l2_subdev *sd, int on)
+{
+	struct hdmi_device *hdmi_dev = sd_to_hdmi_dev(sd);
+	struct device *dev = hdmi_dev->dev;
+	struct hdmi_platform_data *pdata = dev->platform_data;
+
+	dev_info(dev, "%s(%d)\n", __func__, on);
+
+	if (pdata->power_setup && pdata->power_setup(dev, on) != 0) {
+		dev_err(dev, "power setup (en = %d) failed\n", on);
+		return -EIO;
+	}
+
+	/* setting default preset if none is available */
+	if (on) {
+		struct v4l2_dv_preset preset;
+		preset.preset = hdmi_dev->cur_preset;
+		return hdmi_s_dv_preset(sd, &preset);
+	}
+
+	return 0;
+}
+
+static void hdmi_conf_apply(struct hdmi_device *hdev,
+	const struct hdmi_preset_conf *conf);
+static void hdmi_dumpregs(struct hdmi_device *hdev, char *prefix);
+
+static void hdmi_reg_init(struct hdmi_device *hdev)
+{
+	/* enable HPD interrupts */
+	hdmi_write_mask(hdev, HDMI_INTC_CON, ~0, HDMI_INTC_EN_GLOBAL |
+		HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG);
+	/* choose HDMI mode */
+	hdmi_write_mask(hdev, HDMI_MODE_SEL,
+		HDMI_MODE_HDMI_EN | HDMI_MODE_DVI_DIS, HDMI_MODE_MASK);
+	/* XXX: choose bluescreen */
+	hdmi_write_mask(hdev, HDMI_CON_0, 0, HDMI_BLUE_SCR_EN);
+	/* choose bluescreen (fecal) color */
+	hdmi_writeb(hdev, HDMI_BLUE_SCREEN_0, 0x12);
+	hdmi_writeb(hdev, HDMI_BLUE_SCREEN_1, 0x34);
+	hdmi_writeb(hdev, HDMI_BLUE_SCREEN_2, 0x56);
+}
+
+static int hdmi_s_dv_preset(struct v4l2_subdev *sd,
+	struct v4l2_dv_preset *preset)
+{
+	struct hdmi_device *hdmi_dev = sd_to_hdmi_dev(sd);
+	struct device *dev = hdmi_dev->dev;
+	const struct hdmi_preset_conf *conf;
+	int tries, ret;
+	dev_info(dev, "%s(preset = %u)\n", __func__, preset->preset);
+
+	conf = hdmi_preset2conf(preset->preset);
+	if (conf == NULL) {
+		dev_err(dev, "preset (%u) not supported\n", preset->preset);
+		return -ENXIO;
+	}
+
+	/* TODO: check if mode is supported */
+
+	/* reset hdmiphy */
+	hdmi_write_mask(hdmi_dev, HDMI_PHY_RSTOUT, ~0, HDMI_PHY_SW_RSTOUT);
+	mdelay(10);
+	hdmi_write_mask(hdmi_dev, HDMI_PHY_RSTOUT,  0, HDMI_PHY_SW_RSTOUT);
+	mdelay(10);
+
+	/* configure presets */
+	ret = v4l2_subdev_call(hdmi_dev->phy_sd, video, s_dv_preset, preset);
+	if (ret) {
+		dev_err(dev, "failed to set preset (%u)\n", preset->preset);
+		return ret;
+	}
+
+	/* resetting HDMI core */
+	hdmi_write_mask(hdmi_dev, HDMI_CORE_RSTOUT,  0, HDMI_CORE_SW_RSTOUT);
+	mdelay(10);
+	hdmi_write_mask(hdmi_dev, HDMI_CORE_RSTOUT, ~0, HDMI_CORE_SW_RSTOUT);
+	mdelay(10);
+
+	hdmi_reg_init(hdmi_dev);
+
+	/* waiting for HDMIPHY's PLL to get to steady state */
+	for (tries = 100; tries; --tries) {
+		u32 val = hdmi_read(hdmi_dev, HDMI_PHY_STATUS);
+		if (val & HDMI_PHY_STATUS_READY)
+			break;
+		mdelay(1);
+	}
+	/* steady state not achieved */
+	if (tries == 0) {
+		dev_err(dev, "hdmiphy's pll could not reach steady state.\n");
+		hdmi_dumpregs(hdmi_dev, "s_preset");
+		return -EIO;
+	}
+
+	/* setting core registers */
+	hdmi_conf_apply(hdmi_dev, conf);
+	hdmi_dev->cur_conf = conf;
+	hdmi_dev->cur_preset = preset->preset;
+
+	return 0;
+}
+
+static int hdmi_enum_dv_presets(struct v4l2_subdev *sd,
+	struct v4l2_dv_enum_preset *preset);
+
+static int hdmi_g_mbus_fmt(struct v4l2_subdev *sd,
+	  struct v4l2_mbus_framefmt *fmt)
+{
+	struct hdmi_device *hdev = sd_to_hdmi_dev(sd);
+	struct device *dev = hdev->dev;
+	dev_info(dev, "%s\n", __func__);
+	if (!hdev->cur_conf)
+		return -ENXIO;
+	*fmt = hdev->cur_conf->mbus_fmt;
+	return 0;
+}
+
+static int hdmi_streamon(struct hdmi_device *hdev)
+{
+	struct device *dev = hdev->dev;
+	struct hdmi_platform_data *pdata = dev->platform_data;
+	int ret = 0;
+	dev_info(dev, "%s\n", __func__);
+
+	if (pdata->stream_setup)
+		ret = pdata->stream_setup(dev, 1);
+	if (ret) {
+		dev_err(dev, "platform stream on failed\n");
+		return ret;
+	}
+	hdmi_write_mask(hdev, HDMI_CON_0, ~0, HDMI_EN);
+	/* XXX: enable VSYNC and BT656 synchro */
+	/* dmi_write(hdev, S5P_HDMI_TG_CMD, ~0, (1 << 3) | (1 << 4)); */
+	hdmi_write_mask(hdev, HDMI_TG_CMD, ~0, HDMI_TG_EN);
+	hdmi_dumpregs(hdev, "streamon");
+	return 0;
+}
+
+static int hdmi_streamoff(struct hdmi_device *hdev)
+{
+	struct device *dev = hdev->dev;
+	struct hdmi_platform_data *pdata = dev->platform_data;
+	int ret = 0;
+	dev_info(dev, "%s\n", __func__);
+
+	hdmi_write_mask(hdev, HDMI_CON_0, 0, HDMI_EN);
+	hdmi_write_mask(hdev, HDMI_TG_CMD, 0, HDMI_TG_EN);
+	if (pdata->stream_setup)
+		ret = pdata->stream_setup(dev, 0);
+	WARN(ret, "platform stream off failed\n");
+	hdmi_dumpregs(hdev, "streamoff");
+	return 0;
+}
+
+static int hdmi_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct hdmi_device *hdev = sd_to_hdmi_dev(sd);
+	struct device *dev = hdev->dev;
+	dev_info(dev, "%s(%d)\n", __func__, enable);
+	if (enable)
+		return hdmi_streamon(hdev);
+	else
+		return hdmi_streamoff(hdev);
+	/* call stream_setup from pdata (it changes clocks) */
+	/* set bit 0 in in HDMI_CON_0 */
+	/* set bits in in HDMI_TG_CMD */
+	/* enjoy your TV */
+}
+
+static const struct v4l2_subdev_core_ops hdmi_sd_core_ops = {
+	.s_power = hdmi_s_power,
+};
+
+static const struct v4l2_subdev_video_ops hdmi_sd_video_ops = {
+	.s_dv_preset = hdmi_s_dv_preset,
+	.enum_dv_presets = hdmi_enum_dv_presets,
+	.g_mbus_fmt = hdmi_g_mbus_fmt,
+	.s_stream = hdmi_s_stream,
+};
+
+static const struct v4l2_subdev_ops hdmi_sd_ops = {
+	.core = &hdmi_sd_core_ops,
+	.video = &hdmi_sd_video_ops,
+};
+
+static void hdmi_conf_apply(struct hdmi_device *hdev,
+	const struct hdmi_preset_conf *conf)
+{
+	const struct hdmi_core_regs *core = &conf->core;
+	const struct hdmi_tg_regs *tg = &conf->tg;
+	/* setting core registers */
+	hdmi_writeb(hdev, HDMI_H_BLANK_0, core->h_blank[0]);
+	hdmi_writeb(hdev, HDMI_H_BLANK_1, core->h_blank[1]);
+	hdmi_writeb(hdev, HDMI_V_BLANK_0, core->v_blank[0]);
+	hdmi_writeb(hdev, HDMI_V_BLANK_1, core->v_blank[1]);
+	hdmi_writeb(hdev, HDMI_V_BLANK_2, core->v_blank[2]);
+	hdmi_writeb(hdev, HDMI_H_V_LINE_0, core->h_v_line[0]);
+	hdmi_writeb(hdev, HDMI_H_V_LINE_1, core->h_v_line[1]);
+	hdmi_writeb(hdev, HDMI_H_V_LINE_2, core->h_v_line[2]);
+	hdmi_writeb(hdev, HDMI_VSYNC_POL, core->vsync_pol[0]);
+	hdmi_writeb(hdev, HDMI_INT_PRO_MODE, core->int_pro_mode[0]);
+	hdmi_writeb(hdev, HDMI_V_BLANK_F_0, core->v_blank_f[0]);
+	hdmi_writeb(hdev, HDMI_V_BLANK_F_1, core->v_blank_f[1]);
+	hdmi_writeb(hdev, HDMI_V_BLANK_F_2, core->v_blank_f[2]);
+	hdmi_writeb(hdev, HDMI_H_SYNC_GEN_0, core->h_sync_gen[0]);
+	hdmi_writeb(hdev, HDMI_H_SYNC_GEN_1, core->h_sync_gen[1]);
+	hdmi_writeb(hdev, HDMI_H_SYNC_GEN_2, core->h_sync_gen[2]);
+	hdmi_writeb(hdev, HDMI_V_SYNC_GEN_1_0, core->v_sync_gen1[0]);
+	hdmi_writeb(hdev, HDMI_V_SYNC_GEN_1_1, core->v_sync_gen1[1]);
+	hdmi_writeb(hdev, HDMI_V_SYNC_GEN_1_2, core->v_sync_gen1[2]);
+	hdmi_writeb(hdev, HDMI_V_SYNC_GEN_2_0, core->v_sync_gen2[0]);
+	hdmi_writeb(hdev, HDMI_V_SYNC_GEN_2_1, core->v_sync_gen2[1]);
+	hdmi_writeb(hdev, HDMI_V_SYNC_GEN_2_2, core->v_sync_gen2[2]);
+	hdmi_writeb(hdev, HDMI_V_SYNC_GEN_3_0, core->v_sync_gen3[0]);
+	hdmi_writeb(hdev, HDMI_V_SYNC_GEN_3_1, core->v_sync_gen3[1]);
+	hdmi_writeb(hdev, HDMI_V_SYNC_GEN_3_2, core->v_sync_gen3[2]);
+	/* Timing generator registers */
+	hdmi_writeb(hdev, HDMI_TG_H_FSZ_L, tg->h_fsz_l);
+	hdmi_writeb(hdev, HDMI_TG_H_FSZ_H, tg->h_fsz_h);
+	hdmi_writeb(hdev, HDMI_TG_HACT_ST_L, tg->hact_st_l);
+	hdmi_writeb(hdev, HDMI_TG_HACT_ST_H, tg->hact_st_h);
+	hdmi_writeb(hdev, HDMI_TG_HACT_SZ_L, tg->hact_sz_l);
+	hdmi_writeb(hdev, HDMI_TG_HACT_SZ_H, tg->hact_sz_h);
+	hdmi_writeb(hdev, HDMI_TG_V_FSZ_L, tg->v_fsz_l);
+	hdmi_writeb(hdev, HDMI_TG_V_FSZ_H, tg->v_fsz_h);
+	hdmi_writeb(hdev, HDMI_TG_VSYNC_L, tg->vsync_l);
+	hdmi_writeb(hdev, HDMI_TG_VSYNC_H, tg->vsync_h);
+	hdmi_writeb(hdev, HDMI_TG_VSYNC2_L, tg->vsync2_l);
+	hdmi_writeb(hdev, HDMI_TG_VSYNC2_H, tg->vsync2_h);
+	hdmi_writeb(hdev, HDMI_TG_VACT_ST_L, tg->vact_st_l);
+	hdmi_writeb(hdev, HDMI_TG_VACT_ST_H, tg->vact_st_h);
+	hdmi_writeb(hdev, HDMI_TG_VACT_SZ_L, tg->vact_sz_l);
+	hdmi_writeb(hdev, HDMI_TG_VACT_SZ_H, tg->vact_sz_h);
+	hdmi_writeb(hdev, HDMI_TG_FIELD_CHG_L, tg->field_chg_l);
+	hdmi_writeb(hdev, HDMI_TG_FIELD_CHG_H, tg->field_chg_h);
+	hdmi_writeb(hdev, HDMI_TG_VACT_ST2_L, tg->vact_st2_l);
+	hdmi_writeb(hdev, HDMI_TG_VACT_ST2_H, tg->vact_st2_h);
+	hdmi_writeb(hdev, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi_l);
+	hdmi_writeb(hdev, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi_h);
+	hdmi_writeb(hdev, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi_l);
+	hdmi_writeb(hdev, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi_h);
+	hdmi_writeb(hdev, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi_l);
+	hdmi_writeb(hdev, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi_h);
+	hdmi_writeb(hdev, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi_l);
+	hdmi_writeb(hdev, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi_h);
+}
+
+static const struct hdmi_preset_conf hdmi_conf_480p = {
+	.core = {
+		.h_blank = {0x8a, 0x00},
+		.v_blank = {0x0d, 0x6a, 0x01},
+		.h_v_line = {0x0d, 0xa2, 0x35},
+		.vsync_pol = {0x01},
+		.int_pro_mode = {0x00},
+		.v_blank_f = {0x00, 0x00, 0x00},
+		.h_sync_gen = {0x0e, 0x30, 0x11},
+		.v_sync_gen1 = {0x0f, 0x90, 0x00},
+		/* other don't care */
+	},
+	.tg = {
+		0x00, /* cmd */
+		0x5a, 0x03, /* h_fsz */
+		0x8a, 0x00, 0xd0, 0x02, /* hact */
+		0x0d, 0x02, /* v_fsz */
+		0x01, 0x00, 0x33, 0x02, /* vsync */
+		0x2d, 0x00, 0xe0, 0x01, /* vact */
+		0x33, 0x02, /* field_chg */
+		0x49, 0x02, /* vact_st2 */
+		0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
+		0x01, 0x00, 0x33, 0x02, /* field top/bot */
+	},
+	.mbus_fmt = {
+		.width = 720,
+		.height = 480,
+		.code = V4L2_MBUS_FMT_FIXED, /* means RGB888 */
+		.field = V4L2_FIELD_NONE,
+	},
+};
+
+static const struct hdmi_preset_conf hdmi_conf_720p60 = {
+	.core = {
+		.h_blank = {0x72, 0x01},
+		.v_blank = {0xee, 0xf2, 0x00},
+		.h_v_line = {0xee, 0x22, 0x67},
+		.vsync_pol = {0x00},
+		.int_pro_mode = {0x00},
+		.v_blank_f = {0x00, 0x00, 0x00}, /* don't care */
+		.h_sync_gen = {0x6c, 0x50, 0x02},
+		.v_sync_gen1 = {0x0a, 0x50, 0x00},
+		/* other don't care */
+	},
+	.tg = {
+		0x00, /* cmd */
+		0x72, 0x06, /* h_fsz */
+		0x72, 0x01, 0x00, 0x05, /* hact */
+		0xee, 0x02, /* v_fsz */
+		0x01, 0x00, 0x33, 0x02, /* vsync */
+		0x1e, 0x00, 0xd0, 0x02, /* vact */
+		0x33, 0x02, /* field_chg */
+		0x49, 0x02, /* vact_st2 */
+		0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
+		0x01, 0x00, 0x33, 0x02, /* field top/bot */
+	},
+	.mbus_fmt = {
+		.width = 1280,
+		.height = 720,
+		.code = V4L2_MBUS_FMT_FIXED, /* means RGB888 */
+		.field = V4L2_FIELD_NONE,
+	},
+};
+
+static const struct hdmi_preset_conf hdmi_conf_1080p50 = {
+	.core = {
+		.h_blank = {0xd0, 0x02},
+		.v_blank = {0x65, 0x6c, 0x01},
+		.h_v_line = {0x65, 0x04, 0xa5},
+		.vsync_pol = {0x00},
+		.int_pro_mode = {0x00},
+		.v_blank_f = {0x00, 0x00, 0x00}, /* don't care */
+		.h_sync_gen = {0x0e, 0xea, 0x08},
+		.v_sync_gen1 = {0x09, 0x40, 0x00},
+		/* other don't care */
+	},
+	.tg = {
+		0x00, /* cmd */
+		0x98, 0x08, /* h_fsz */
+		0x18, 0x01, 0x80, 0x07, /* hact */
+		0x65, 0x04, /* v_fsz */
+		0x01, 0x00, 0x33, 0x02, /* vsync */
+		0x2d, 0x00, 0x38, 0x04, /* vact */
+		0x33, 0x02, /* field_chg */
+		0x49, 0x02, /* vact_st2 */
+		0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
+		0x01, 0x00, 0x33, 0x02, /* field top/bot */
+	},
+	.mbus_fmt = {
+		.width = 1920,
+		.height = 1080,
+		.code = V4L2_MBUS_FMT_FIXED, /* means RGB888 */
+		.field = V4L2_FIELD_NONE,
+	},
+};
+
+static const struct hdmi_preset_conf hdmi_conf_1080p60 = {
+	.core = {
+		.h_blank = {0x18, 0x01},
+		.v_blank = {0x65, 0x6c, 0x01},
+		.h_v_line = {0x65, 0x84, 0x89},
+		.vsync_pol = {0x00},
+		.int_pro_mode = {0x00},
+		.v_blank_f = {0x00, 0x00, 0x00}, /* don't care */
+		.h_sync_gen = {0x56, 0x08, 0x02},
+		.v_sync_gen1 = {0x09, 0x40, 0x00},
+		/* other don't care */
+	},
+	.tg = {
+		0x00, /* cmd */
+		0x98, 0x08, /* h_fsz */
+		0x18, 0x01, 0x80, 0x07, /* hact */
+		0x65, 0x04, /* v_fsz */
+		0x01, 0x00, 0x33, 0x02, /* vsync */
+		0x2d, 0x00, 0x38, 0x04, /* vact */
+		0x33, 0x02, /* field_chg */
+		0x48, 0x02, /* vact_st2 */
+		0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
+		0x01, 0x00, 0x33, 0x02, /* field top/bot */
+	},
+	.mbus_fmt = {
+		.width = 1920,
+		.height = 1080,
+		.code = V4L2_MBUS_FMT_FIXED, /* means RGB888 */
+		.field = V4L2_FIELD_NONE,
+	},
+};
+
+static const struct {
+	u32 preset;
+	const struct hdmi_preset_conf *conf;
+} hdmi_conf[] = {
+	{ V4L2_DV_480P59_94, &hdmi_conf_480p },
+	{ V4L2_DV_720P59_94, &hdmi_conf_720p60 },
+	{ V4L2_DV_1080P50, &hdmi_conf_1080p50 },
+	{ V4L2_DV_1080P30, &hdmi_conf_1080p60 },
+	{ V4L2_DV_1080P60, &hdmi_conf_1080p60 },
+	{ V4L2_DV_1080P59_94, &hdmi_conf_1080p60 },
+};
+
+static const struct hdmi_preset_conf *hdmi_preset2conf(u32 preset)
+{
+	int i;
+	for (i = 0; i < ARRAY_SIZE(hdmi_conf); ++i)
+		if (hdmi_conf[i].preset == preset)
+			return  hdmi_conf[i].conf;
+	return NULL;
+}
+
+static int hdmi_enum_dv_presets(struct v4l2_subdev *sd,
+	struct v4l2_dv_enum_preset *preset)
+{
+	if (preset->index >= ARRAY_SIZE(hdmi_conf))
+		return -EINVAL;
+	return v4l_fill_dv_preset_info(hdmi_conf[preset->index].preset, preset);
+}
+
+static void hdmi_dumpregs(struct hdmi_device *hdev, char *prefix)
+{
+#define DUMPREG(reg_id) \
+	printk(KERN_DEBUG "%s:" #reg_id " = %08x\n", prefix, \
+	readl(hdev->regs + reg_id))
+	printk(KERN_ERR "%s: ---- CONTROL REGISTERS ----\n", prefix);
+	DUMPREG(HDMI_INTC_FLAG);
+	DUMPREG(HDMI_INTC_CON);
+	DUMPREG(HDMI_HPD_STATUS);
+	DUMPREG(HDMI_PHY_RSTOUT);
+	DUMPREG(HDMI_PHY_VPLL);
+	DUMPREG(HDMI_PHY_CMU);
+	DUMPREG(HDMI_CORE_RSTOUT);
+
+	printk(KERN_ERR "%s: ---- CORE REGISTERS ----\n", prefix);
+	DUMPREG(HDMI_CON_0);
+	DUMPREG(HDMI_CON_1);
+	DUMPREG(HDMI_CON_2);
+	DUMPREG(HDMI_SYS_STATUS);
+	DUMPREG(HDMI_PHY_STATUS);
+	DUMPREG(HDMI_STATUS_EN);
+	DUMPREG(HDMI_HPD);
+	DUMPREG(HDMI_MODE_SEL);
+	DUMPREG(HDMI_HPD_GEN);
+	DUMPREG(HDMI_DC_CONTROL);
+	DUMPREG(HDMI_VIDEO_PATTERN_GEN);
+
+	printk(KERN_ERR "%s: ---- CORE SYNC REGISTERS ----\n", prefix);
+	DUMPREG(HDMI_H_BLANK_0);
+	DUMPREG(HDMI_H_BLANK_1);
+	DUMPREG(HDMI_V_BLANK_0);
+	DUMPREG(HDMI_V_BLANK_1);
+	DUMPREG(HDMI_V_BLANK_2);
+	DUMPREG(HDMI_H_V_LINE_0);
+	DUMPREG(HDMI_H_V_LINE_1);
+	DUMPREG(HDMI_H_V_LINE_2);
+	DUMPREG(HDMI_VSYNC_POL);
+	DUMPREG(HDMI_INT_PRO_MODE);
+	DUMPREG(HDMI_V_BLANK_F_0);
+	DUMPREG(HDMI_V_BLANK_F_1);
+	DUMPREG(HDMI_V_BLANK_F_2);
+	DUMPREG(HDMI_H_SYNC_GEN_0);
+	DUMPREG(HDMI_H_SYNC_GEN_1);
+	DUMPREG(HDMI_H_SYNC_GEN_2);
+	DUMPREG(HDMI_V_SYNC_GEN_1_0);
+	DUMPREG(HDMI_V_SYNC_GEN_1_1);
+	DUMPREG(HDMI_V_SYNC_GEN_1_2);
+	DUMPREG(HDMI_V_SYNC_GEN_2_0);
+	DUMPREG(HDMI_V_SYNC_GEN_2_1);
+	DUMPREG(HDMI_V_SYNC_GEN_2_2);
+	DUMPREG(HDMI_V_SYNC_GEN_3_0);
+	DUMPREG(HDMI_V_SYNC_GEN_3_1);
+	DUMPREG(HDMI_V_SYNC_GEN_3_2);
+
+	printk(KERN_ERR "%s: ---- TG REGISTERS ----\n", prefix);
+	DUMPREG(HDMI_TG_CMD);
+	DUMPREG(HDMI_TG_H_FSZ_L);
+	DUMPREG(HDMI_TG_H_FSZ_H);
+	DUMPREG(HDMI_TG_HACT_ST_L);
+	DUMPREG(HDMI_TG_HACT_ST_H);
+	DUMPREG(HDMI_TG_HACT_SZ_L);
+	DUMPREG(HDMI_TG_HACT_SZ_H);
+	DUMPREG(HDMI_TG_V_FSZ_L);
+	DUMPREG(HDMI_TG_V_FSZ_H);
+	DUMPREG(HDMI_TG_VSYNC_L);
+	DUMPREG(HDMI_TG_VSYNC_H);
+	DUMPREG(HDMI_TG_VSYNC2_L);
+	DUMPREG(HDMI_TG_VSYNC2_H);
+	DUMPREG(HDMI_TG_VACT_ST_L);
+	DUMPREG(HDMI_TG_VACT_ST_H);
+	DUMPREG(HDMI_TG_VACT_SZ_L);
+	DUMPREG(HDMI_TG_VACT_SZ_H);
+	DUMPREG(HDMI_TG_FIELD_CHG_L);
+	DUMPREG(HDMI_TG_FIELD_CHG_H);
+	DUMPREG(HDMI_TG_VACT_ST2_L);
+	DUMPREG(HDMI_TG_VACT_ST2_H);
+	DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_L);
+	DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_H);
+	DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_L);
+	DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_H);
+	DUMPREG(HDMI_TG_FIELD_TOP_HDMI_L);
+	DUMPREG(HDMI_TG_FIELD_TOP_HDMI_H);
+	DUMPREG(HDMI_TG_FIELD_BOT_HDMI_L);
+	DUMPREG(HDMI_TG_FIELD_BOT_HDMI_H);
+#undef DUMPREG
+}
+
diff --git a/drivers/media/video/s5p-tv/hdmiphy.h b/drivers/media/video/s5p-tv/hdmiphy.h
new file mode 100644
index 0000000..0b40766
--- /dev/null
+++ b/drivers/media/video/s5p-tv/hdmiphy.h
@@ -0,0 +1,37 @@
+#ifndef HDMIPHY_H_
+#define HDMIPHY_H_
+
+#include <media/v4l2-subdev.h>
+
+enum hdmiphy_color_depth {
+	PHY_8B = 0,
+	PHY_10B = 1,
+	PHY_12B = 2,
+	PHY_DEPTHS,
+};
+
+enum hdmiphy_pixel_freq {
+	PHY_027_000_MHZ = 0,
+	PHY_027_027_MHZ = 1,
+	PHY_074_176_MHZ = 2,
+	PHY_074_250_MHZ = 3,
+	PHY_148_352_MHZ = 4,
+	PHY_148_500_MHZ = 5,
+	PHY_PIXEL_FREQS,
+};
+
+#define HDMIPHY_REGS 32
+
+struct hdmiphy_fmt {
+	struct v4l2_mbus_framefmt mbus_fmt;
+	enum hdmiphy_pixel_freq freq;
+	enum hdmiphy_color_depth color_depth;
+};
+
+extern u8 hdmiphy_conf_27m[PHY_PIXEL_FREQS][PHY_DEPTHS][HDMIPHY_REGS];
+extern u8 hdmiphy_conf_24m[PHY_PIXEL_FREQS][PHY_DEPTHS][HDMIPHY_REGS];
+extern u32 hdmiphy_freqs[PHY_PIXEL_FREQS];
+extern struct hdmiphy_fmt hdmiphy_fmt[];
+
+#endif /* HDMIPHY_H_ */
+
diff --git a/drivers/media/video/s5p-tv/hdmiphy_drv.c b/drivers/media/video/s5p-tv/hdmiphy_drv.c
new file mode 100644
index 0000000..34de421
--- /dev/null
+++ b/drivers/media/video/s5p-tv/hdmiphy_drv.c
@@ -0,0 +1,228 @@
+/*
+ * Samsung HDMI Physical interface driver
+ *
+ * Copyright (C) 2010 Samsung Electronics Co.Ltd
+ * Author: Tomasz Stanislawski <t.stanislaws@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 "hdmiphy.h"
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/err.h>
+
+#include <media/v4l2-subdev.h>
+
+/* Module information */
+MODULE_AUTHOR("Tomasz Stanislawski <t.stanislaws@samsung.com>");
+MODULE_DESCRIPTION("Samsung HDMI Physical interface driver");
+MODULE_LICENSE("GPL");
+
+struct hdmiphy_conf {
+	u32 *preset;
+	u8 data[32];
+};
+
+static struct i2c_driver hdmiphy_driver;
+static const struct v4l2_subdev_ops hdmiphy_ops;
+static const struct hdmiphy_conf *hdmiphy_conf[];
+
+static int __init hdmiphy_init(void)
+{
+	return i2c_add_driver(&hdmiphy_driver);
+}
+module_init(hdmiphy_init);
+
+static void __exit hdmiphy_exit(void)
+{
+	i2c_del_driver(&hdmiphy_driver);
+}
+module_exit(hdmiphy_exit);
+
+static int __devinit hdmiphy_probe(struct i2c_client *client,
+	const struct i2c_device_id *id)
+{
+	static struct v4l2_subdev sd;
+	struct device *dev = &client->dev;
+	v4l2_i2c_subdev_init(&sd, client, &hdmiphy_ops);
+	dev_info(dev, "probe successful\n");
+	return 0;
+}
+
+static int __devexit hdmiphy_remove(struct i2c_client *client)
+{
+	struct device *dev = &client->dev;
+	dev_info(dev, "remove successful\n");
+	return 0;
+}
+
+static const struct i2c_device_id hdmiphy_id[] = {
+	{ "hdmiphy", 0 },
+	{ },
+};
+MODULE_DEVICE_TABLE(i2c, hdmiphy_id);
+
+static struct i2c_driver hdmiphy_driver = {
+	.driver = {
+		.name	= "s5p-hdmiphy",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= hdmiphy_probe,
+	.remove		= __devexit_p(hdmiphy_remove),
+	.id_table = hdmiphy_id,
+};
+
+static int hdmiphy_s_power(struct v4l2_subdev *sd, int on)
+{
+	return 0;
+}
+
+const struct hdmiphy_conf *hdmiphy_preset2conf(u32 preset)
+{
+	int i, j;
+	for (i = 0; hdmiphy_conf[i]; ++i)
+		for (j = 0; hdmiphy_conf[i]->preset[j]; ++j)
+			if (hdmiphy_conf[i]->preset[j] == preset)
+				return hdmiphy_conf[i];
+	return NULL;
+}
+
+static int hdmiphy_s_dv_preset(struct v4l2_subdev *sd,
+	struct v4l2_dv_preset *preset)
+{
+	const struct hdmiphy_conf *conf;
+	u8 buffer[32];
+	int ret;
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct device *dev = &client->dev;
+	int x, y;
+
+	conf = hdmiphy_preset2conf(preset->preset);
+	if (!conf) {
+		dev_err(dev, "format not supported\n");
+		return -ENXIO;
+	}
+
+	/* storing configuration to the device */
+	memcpy(buffer, conf->data, 32);
+	for (y = 0; y < 4; ++y) {
+		char txt[64], *p = txt;
+		for (x = 0; x < 8; ++x)
+			p += sprintf(p, "0x%02x, ", buffer[8 * y + x]);
+		dev_info(dev, "[%02d-%02d] = %s\n", 8 * y, 8 * y + 7, txt);
+	}
+	ret = i2c_master_send(client, buffer, 32);
+	if (ret != 32) {
+		dev_err(dev, "failed to configure HDMIPHY via I2C\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int hdmiphy_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct device *dev = &client->dev;
+	u8 buffer[2];
+	int ret;
+	/* going to/from configuration from/to operation mode */
+	buffer[0] = 0x1f;
+	if (enable)
+		buffer[1] = 0x80;
+	else
+		buffer[1] = 0x00;
+
+	ret = i2c_master_send(client, buffer, 2);
+	if (ret != 2) {
+		dev_err(dev, "stream (%d) failed\n", enable);
+		return -EIO;
+	}
+	return 0;
+}
+
+static const struct v4l2_subdev_core_ops hdmiphy_core_ops = {
+	.s_power =  hdmiphy_s_power,
+};
+
+static const struct v4l2_subdev_video_ops hdmiphy_video_ops = {
+	.s_dv_preset = hdmiphy_s_dv_preset,
+	.s_stream =  hdmiphy_s_stream,
+};
+
+static const struct v4l2_subdev_ops hdmiphy_ops = {
+	.core = &hdmiphy_core_ops,
+	.video = &hdmiphy_video_ops,
+};
+
+static const struct hdmiphy_conf hdmiphy_conf27 = {
+	.preset = (u32 []) {V4L2_DV_480P59_94, 0},
+	.data = {
+		0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40,
+		0x6B, 0x10, 0x02, 0x51, 0xDf, 0xF2, 0x54, 0x87,
+		0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
+		0x22, 0x40, 0xe3, 0x26, 0x00, 0x00, 0x00, 0x80,
+	},
+};
+
+static const struct hdmiphy_conf hdmiphy_conf74_175 = {
+	.preset = (u32 []) {V4L2_DV_1080P30, V4L2_DV_720P59_94, 0},
+	.data = {
+		0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xef, 0x5B,
+		0x6D, 0x10, 0x01, 0x51, 0xef, 0xF3, 0x54, 0xb9,
+		0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
+		0x22, 0x40, 0xa5, 0x26, 0x01, 0x00, 0x00, 0x80,
+	}
+};
+
+static const struct hdmiphy_conf hdmiphy_conf74_25 = {
+	.preset = (u32 []) {V4L2_DV_720P60, 0},
+	.data = {
+		0x01, 0x05, 0x00, 0xd8, 0x10, 0x9c, 0xf8, 0x40,
+		0x6a, 0x10, 0x01, 0x51, 0xff, 0xf1, 0x54, 0xba,
+		0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xe0,
+		0x22, 0x40, 0xa4, 0x26, 0x01, 0x00, 0x00, 0x80,
+	},
+};
+
+static const struct hdmiphy_conf hdmiphy_conf148_5 = {
+	.preset = (u32 []) {V4L2_DV_1080P50, V4L2_DV_1080P60, 0},
+	/* LSI tables */
+	.data = {
+		0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xf8, 0x40,
+		0x6A, 0x18, 0x00, 0x51, 0xff, 0xF1, 0x54, 0xba,
+		0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xE0,
+		0x22, 0x40, 0xa4, 0x26, 0x02, 0x00, 0x00, 0x80,
+	},
+};
+
+static const struct hdmiphy_conf hdmiphy_conf148_35 = {
+	.preset = (u32 []) {V4L2_DV_1080P59_94, 0},
+	/* LSI tables */
+	.data = {
+		0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xef, 0x5B,
+		0x6D, 0x18, 0x00, 0x51, 0xef, 0xF3, 0x54, 0xb9,
+		0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
+		0x22, 0x40, 0xa5, 0x26, 0x02, 0x00, 0x00, 0x80,
+	},
+};
+
+static const struct hdmiphy_conf *hdmiphy_conf[] = {
+	&hdmiphy_conf27,
+	&hdmiphy_conf74_175,
+	&hdmiphy_conf74_25,
+	&hdmiphy_conf148_5,
+	&hdmiphy_conf148_35,
+	NULL,
+};
+
diff --git a/drivers/media/video/s5p-tv/mixer.h b/drivers/media/video/s5p-tv/mixer.h
new file mode 100644
index 0000000..87ab000
--- /dev/null
+++ b/drivers/media/video/s5p-tv/mixer.h
@@ -0,0 +1,281 @@
+/*
+ * Samsung TV Mixer driver
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ *
+ * Tomasz Stanislawski, t.stanislaws@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 Foundiation. either version 2 of the License,
+ * or (at your option) any later version
+ */
+
+#ifndef _SAMSUNG_MIXER_H_
+#define _SAMSUNG_MIXER_H_
+
+#include <linux/fb.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
+#include <media/v4l2-device.h>
+#include <media/videobuf2-core.h>
+
+#include "regs-vmx.h"
+
+/** maximum number of output interfaces */
+#define MXR_OUTPUTS 2
+/** maximum number of input interfaces (layers) */
+#define MXR_MAX_LAYERS 3
+#define MXR_DRIVER_NAME "s5p-mixer"
+/** maximal number of planes for every layer */
+#define MXR_MAX_PLANES	2
+
+#define MXR_ENABLE 1
+#define MXR_DISABLE 0
+
+/** description of a macroblock for packed formats */
+struct mxr_block {
+	/** vertical number of pixels in macroblock */
+	unsigned int pxWidth:8;
+	/** horizontal number of pixels in macroblock */
+	unsigned int pxHeight:8;
+	/** size of block in bytes */
+	unsigned int bSize:16;
+};
+
+/** description of supported format */
+struct mxr_format {
+	/** format name/mnemonic */
+	char *name;
+	/** fourcc identifier */
+	u32 fourcc;
+	/** number of planes in image data */
+	int num_planes;
+	/** description of block for each plane */
+	struct mxr_block plane[MXR_MAX_PLANES];
+	/** number of subframes in image data */
+	int num_subframes;
+	/** specifies to which subframe belong given plane */
+	int plane2subframe[MXR_MAX_PLANES];
+	/** internal code, driver dependant */
+	unsigned long hwCode;
+};
+
+/** description of crop configuration for image */
+struct mxr_crop {
+	/** width of layer in pixels */
+	unsigned int full_width;
+	/** height of layer in pixels */
+	unsigned int full_height;
+	/** horizontal offset of first pixel to be displayed */
+	unsigned int x_offset;
+	/** vertical offset of first pixel to be displayed */
+	unsigned int y_offset;
+	/** width of displayed data in pixels */
+	unsigned int width;
+	/** height of displayed data in pixels */
+	unsigned int height;
+};
+
+/** description of transformation from source to destination image */
+struct mxr_geometry {
+	/** cropping for source image */
+	struct mxr_crop src;
+	/** cropping for destination image */
+	struct mxr_crop dst;
+	/** layer-dependant description of horizontal scaling */
+	unsigned int x_ratio;
+	/** layer-dependant description of vertical scaling */
+	unsigned int y_ratio;
+};
+
+/** instance of a buffer */
+struct mxr_buffer {
+	/** common v4l buffer stuff -- must be first */
+	struct vb2_buffer	vb;
+	/** node for layer's lists */
+	struct list_head	list;
+};
+
+
+/** internal states of layer */
+enum mxr_layer_state {
+	/** layers is not shown */
+	MXR_LAYER_IDLE = 0,
+	/** state between STREAMON and hardware start */
+	MXR_LAYER_STREAMING_START,
+	/** layer is shown */
+	MXR_LAYER_STREAMING,
+	/** state before STREAMOFF is finished */
+	MXR_LAYER_STREAMING_FINISH,
+};
+
+/** forward declarations */
+struct mxr_device;
+struct mxr_layer;
+
+/** callback for layers operation */
+struct mxr_layer_ops {
+	/* TODO: try to port it to subdev API */
+	/** handler for resource release function */
+	void (*release)(struct mxr_layer *);
+	/** setting buffer to HW */
+	void (*buffer_set)(struct mxr_layer *, struct mxr_buffer *);
+	/** setting format and geometry in HW */
+	void (*format_set)(struct mxr_layer *);
+	/** streaming stop/start */
+	void (*stream_set)(struct mxr_layer *, int);
+	/** adjusting geometry */
+	void (*fix_geometry)(struct mxr_layer *);
+};
+
+/** layer instance, a single window and content displayed on output */
+struct mxr_layer {
+	/** parent mixer device */
+	struct mxr_device *mdev;
+	/** layer index (unique identifier) */
+	int idx;
+	/** callbacks for layer methods */
+	struct mxr_layer_ops ops;
+	/** format array */
+	const struct mxr_format **fmt_array;
+	/** size of format array */
+	unsigned long fmt_array_size;
+
+	/** lock for protection of list and state fields */
+	spinlock_t enq_slock;
+	/** list for enqueued buffers */
+	struct list_head enq_list;
+	/** buffer currently owned by hardware in temporary registers */
+	struct mxr_buffer *update_buf;
+	/** buffer currently owned by hardware in shadow registers */
+	struct mxr_buffer *shadow_buf;
+	/** state of layer IDLE/STREAMING */
+	enum mxr_layer_state state;
+
+	/** mutex for protection of fields below */
+	struct mutex mutex;
+	/** use count */
+	int n_user;
+	/** handler for video node */
+	struct video_device vfd;
+	/** queue for output buffers */
+	struct vb2_queue vb_queue;
+	/** current image format */
+	const struct mxr_format *fmt;
+	/** current geometry of image */
+	struct mxr_geometry geo;
+};
+
+/** description of mixers output interface */
+struct mxr_output {
+	/** name of output */
+	char name[32];
+	/** output subdev */
+	struct v4l2_subdev *sd;
+};
+
+/** drivers instance */
+struct mxr_device {
+	/** interrupt index */
+	int irq;
+	/** master device */
+	struct device *dev;
+	/** state of each layer */
+	struct mxr_layer *layer[MXR_MAX_LAYERS];
+	/** state of each output */
+	struct mxr_output *output[MXR_OUTPUTS];
+
+	/* video resources */
+
+	/** V4L2 device */
+	struct v4l2_device v4l2_dev;
+	/** context of allocator */
+	void *alloc_ctx;
+
+	/** spinlock for protection of registers */
+	spinlock_t reg_slock;
+	/** pointer to Mixer registers */
+	void __iomem *mxr_regs;
+	/** pointer to Video Processor registers */
+	void __iomem *vp_regs;
+
+	/** mutex for protection of fields below */
+	struct mutex mutex;
+	/** number of power consumers */
+	int n_power;
+	/** number of entities depndant on output configuration */
+	int n_output;
+	/** number of users that do streaming */
+	int n_streamer;
+	/** index of current output */
+	int current_output;
+};
+
+/** transform device structure into mixer device */
+static inline struct mxr_device *to_mdev(struct device *dev)
+{
+	struct v4l2_device *vdev = dev_get_drvdata(dev);
+	return container_of(vdev, struct mxr_device, v4l2_dev);
+}
+
+/** get current output data, should be called under mdev's mutex */
+static inline struct mxr_output *to_output(struct mxr_device *mdev)
+{
+	return mdev->output[mdev->current_output];
+}
+
+/** get current output subdev, should be called under mdev's mutex */
+static inline struct v4l2_subdev *to_outsd(struct mxr_device *mdev)
+{
+	struct mxr_output *out = to_output(mdev);
+	return out ? out->sd : NULL;
+}
+
+/** forward declaration for mixer platform data */
+struct mxr_platform_data;
+
+/** acquiring common video resources */
+int __devinit mxr_acquire_video(struct mxr_device *mdev,
+	struct mxr_platform_data *pdata);
+
+/** releasing common video resources */
+void __devexit mxr_release_video(struct mxr_device *mdev);
+
+struct mxr_layer *mxr_graph_layer_create(struct mxr_device *mdev, int idx);
+struct mxr_layer *mxr_vp_layer_create(struct mxr_device *mdev, int idx);
+struct mxr_layer *mxr_base_layer_create(struct mxr_device *mdev,
+	int idx, char *name, struct mxr_layer_ops *ops);
+
+void mxr_base_layer_release(struct mxr_layer *layer);
+void mxr_layer_release(struct mxr_layer *layer);
+
+int mxr_base_layer_register(struct mxr_layer *layer);
+void mxr_base_layer_unregister(struct mxr_layer *layer);
+
+unsigned long mxr_get_plane_size(const struct mxr_block *blk,
+	unsigned int width, unsigned int height);
+
+/** adds new consumer for mixer's power */
+void mxr_power_get(struct mxr_device *mdev);
+/** removes consumer for mixer's power */
+void mxr_power_put(struct mxr_device *mdev);
+/** add new client for output configuration */
+void mxr_output_get(struct mxr_device *mdev);
+/** removes new client for output configuration */
+void mxr_output_put(struct mxr_device *mdev);
+/** add new client for streaming */
+void mxr_streamer_get(struct mxr_device *mdev);
+/** removes new client for streaming */
+void mxr_streamer_put(struct mxr_device *mdev);
+/** returns format of data delivared to current output */
+void mxr_get_mbus_fmt(struct mxr_device *mdev,
+	struct v4l2_mbus_framefmt *mbus_fmt);
+
+
+#define MXR_CHECK printk(KERN_ERR "%s:%d\n", __func__, __LINE__)
+
+
+#endif /* _SAMSUNG_MIXER_H_ */
+
diff --git a/drivers/media/video/s5p-tv/mixer_drv.c b/drivers/media/video/s5p-tv/mixer_drv.c
new file mode 100644
index 0000000..d3d38ea
--- /dev/null
+++ b/drivers/media/video/s5p-tv/mixer_drv.c
@@ -0,0 +1,362 @@
+/*
+ * Samsung TV Mixer driver
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ *
+ * Tomasz Stanislawski, t.stanislaws@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 Foundiation. either version 2 of the License,
+ * or (at your option) any later version
+ */
+
+#include "plat/tv.h"
+#include "mixer.h"
+#include "mixer_reg.h"
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/fb.h>
+#include <linux/delay.h>
+
+MODULE_AUTHOR("Tomasz Stanislawski, t.stanislaws@samsung.com");
+MODULE_DESCRIPTION("Samsung MIXER");
+MODULE_LICENSE("GPL");
+
+/* --------- DRIVER INITIALIZATION ---------- */
+
+static struct platform_driver mxr_driver __refdata;
+
+static int __init mxr_init(void)
+{
+	int ret;
+	static const char banner[] __initdata = KERN_INFO
+		"Samsung TV Mixer driver, (c) 2010 Samsung Electronics\n";
+	printk(banner);
+
+	ret = platform_driver_register(&mxr_driver);
+	if (ret != 0) {
+		printk(KERN_ERR "registration of MIXER driver failed\n");
+		return -ENXIO;
+	}
+
+	return 0;
+}
+module_init(mxr_init);
+
+static void __exit mxr_exit(void)
+{
+	platform_driver_unregister(&mxr_driver);
+}
+module_exit(mxr_exit);
+
+static int __devinit mxr_acquire_resources(struct mxr_device *mdev,
+	struct platform_device *pdev);
+
+static void mxr_release_resources(struct mxr_device *mdev);
+
+static int __devinit mxr_acquire_layers(struct mxr_device *mdev,
+	struct mxr_platform_data *pdata);
+
+static void mxr_release_layers(struct mxr_device *mxr_dev);
+
+static int __devinit mxr_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct mxr_platform_data *pdata = dev->platform_data;
+	struct mxr_device *mdev;
+	int ret;
+
+	dev_info(dev, "probe start\n");
+
+	if (pdata->init) {
+		ret = pdata->init(dev);
+		if (ret)
+			goto fail;
+	}
+
+	mdev = kzalloc(sizeof *mdev, GFP_KERNEL);
+	if (!mdev) {
+		dev_err(dev, "not enough memory.\n");
+		ret = -ENOMEM;
+		goto fail_init;
+	}
+
+	/* setup pointer to master device */
+	mdev->dev = dev;
+
+	mutex_init(&mdev->mutex);
+	spin_lock_init(&mdev->reg_slock);
+
+	/* acquire resources: regs, irqs */
+	ret = mxr_acquire_resources(mdev, pdev);
+	if (ret)
+		goto fail_mem;
+
+	/* configure resources for video output */
+	ret = mxr_acquire_video(mdev, pdata);
+	if (ret)
+		goto fail_resources;
+
+	/* configure layers */
+	ret = mxr_acquire_layers(mdev, pdata);
+	if (ret)
+		goto fail_video;
+
+	dev_info(dev, "probe successful\n");
+	return 0;
+
+fail_video:
+	mxr_release_video(mdev);
+
+fail_resources:
+	mxr_release_resources(mdev);
+
+fail_mem:
+	kfree(mdev);
+
+fail_init:
+	if (pdata->deinit)
+		pdata->deinit(dev);
+
+fail:
+	dev_info(dev, "probe failed\n");
+	return ret;
+}
+
+static int __devexit mxr_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct mxr_device *mdev = to_mdev(dev);
+	struct mxr_platform_data *pdata = dev->platform_data;
+
+	mxr_release_layers(mdev);
+	mxr_release_video(mdev);
+	mxr_release_resources(mdev);
+
+	kfree(mdev);
+
+	if (pdata->deinit)
+		pdata->deinit(dev);
+
+	dev_info(dev, "remove sucessful\n");
+	return 0;
+}
+
+static struct platform_driver mxr_driver __refdata = {
+	.probe = mxr_probe,
+	.remove = __devexit_p(mxr_remove),
+	.driver = {
+		.name = MXR_DRIVER_NAME,
+		.owner = THIS_MODULE,
+	}
+};
+
+static int __devinit mxr_acquire_resources(struct mxr_device *mdev,
+	struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	int ret;
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mxr");
+	if (res == NULL) {
+		dev_err(dev, "get memory resource failed.\n");
+		ret = -ENXIO;
+		goto fail;
+	}
+
+	mdev->mxr_regs = ioremap(res->start, resource_size(res));
+	if (mdev->mxr_regs == NULL) {
+		dev_err(dev, "register mapping failed.\n");
+		ret = -ENXIO;
+		goto fail;
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vp");
+	if (res == NULL) {
+		dev_err(dev, "get memory resource failed.\n");
+		ret = -ENXIO;
+		goto fail_mxr_regs;
+	}
+
+	mdev->vp_regs = ioremap(res->start, resource_size(res));
+	if (mdev->vp_regs == NULL) {
+		dev_err(dev, "register mapping failed.\n");
+		ret = -ENXIO;
+		goto fail_mxr_regs;
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq");
+	if (res == NULL) {
+		dev_err(dev, "get interrupt resource failed.\n");
+		ret = -ENXIO;
+		goto fail_vp_regs;
+	}
+
+	ret = request_irq(res->start, mxr_irq_handler, 0, "s5p-mixer", mdev);
+	if (ret) {
+		dev_err(dev, "request interrupt failed.\n");
+		goto fail_vp_regs;
+	}
+	mdev->irq = res->start;
+	dev_info(dev, "resources acquired\n");
+
+	return 0;
+
+fail_vp_regs:
+	iounmap(mdev->vp_regs);
+
+fail_mxr_regs:
+	iounmap(mdev->mxr_regs);
+
+fail:
+	return ret;
+}
+
+static void mxr_release_resources(struct mxr_device *mdev)
+{
+	free_irq(mdev->irq, mdev);
+	iounmap(mdev->vp_regs);
+	iounmap(mdev->mxr_regs);
+}
+
+static int __devinit mxr_acquire_layers(struct mxr_device *mdev,
+	struct mxr_platform_data *pdata)
+{
+	mdev->layer[0] = mxr_graph_layer_create(mdev, 0);
+	mdev->layer[1] = mxr_graph_layer_create(mdev, 1);
+	mdev->layer[2] = mxr_vp_layer_create(mdev, 0);
+
+	if (!mdev->layer[0] || !mdev->layer[1] || !mdev->layer[2]) {
+		dev_err(mdev->dev, "failed to acquire layers\n");
+		goto fail;
+	}
+
+	return 0;
+
+fail:
+	mxr_release_layers(mdev);
+	return -ENODEV;
+}
+
+static void mxr_release_layers(struct mxr_device *mdev)
+{
+	int i;
+	for (i = 0; i < ARRAY_SIZE(mdev->layer); ++i)
+		if (mdev->layer[i])
+			mxr_layer_release(mdev->layer[i]);
+}
+
+void mxr_power_get(struct mxr_device *mdev)
+{
+	struct device *dev = mdev->dev;
+	struct mxr_platform_data *pdata = dev->platform_data;
+
+	mutex_lock(&mdev->mutex);
+	++mdev->n_power;
+	dev_info(mdev->dev, "%s(%d)\n", __func__, mdev->n_power);
+	if (mdev->n_power == 1) {
+		/* power on */
+		dev_info(dev, "pdata->power_setup = %p\n", pdata->power_setup);
+		if (pdata->power_setup)
+			pdata->power_setup(dev, 1);
+		/* apply default configuration */
+		mxr_reg_reset(mdev);
+		v4l2_subdev_call(to_outsd(mdev), core, s_power, 1);
+	}
+	mutex_unlock(&mdev->mutex);
+}
+
+void mxr_power_put(struct mxr_device *mdev)
+{
+	struct device *dev = mdev->dev;
+	struct mxr_platform_data *pdata = dev->platform_data;
+
+	mutex_lock(&mdev->mutex);
+	--mdev->n_power;
+	dev_info(mdev->dev, "%s(%d)\n", __func__, mdev->n_power);
+	if (mdev->n_power == 0) {
+		/* __mxr_reg_deinit(mdev); */
+		if (pdata->power_setup)
+			pdata->power_setup(dev, 0);
+		/* power off */
+		v4l2_subdev_call(to_outsd(mdev), core, s_power, 0);
+	}
+	WARN(mdev->n_power < 0, "negative number of power users (%d)\n",
+		mdev->n_power);
+	mutex_unlock(&mdev->mutex);
+}
+
+void mxr_get_mbus_fmt(struct mxr_device *mdev,
+	struct v4l2_mbus_framefmt *mbus_fmt)
+{
+	struct v4l2_subdev *sd;
+	int ret;
+	mutex_lock(&mdev->mutex);
+	sd = to_outsd(mdev);
+	ret = v4l2_subdev_call(sd, video, g_mbus_fmt, mbus_fmt);
+	WARN(ret, "failed to get mbus_fmt for output %s\n", sd->name);
+	mutex_unlock(&mdev->mutex);
+}
+
+void mxr_streamer_get(struct mxr_device *mdev)
+{
+	mutex_lock(&mdev->mutex);
+	++mdev->n_streamer;
+	dev_info(mdev->dev, "%s(%d)\n", __func__, mdev->n_streamer);
+	if (mdev->n_streamer == 1) {
+		struct v4l2_subdev *sd = to_outsd(mdev);
+		struct v4l2_mbus_framefmt mbus_fmt;
+		int ret;
+		ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mbus_fmt);
+		WARN(ret, "failed to get mbus_fmt for output %s\n", sd->name);
+		mxr_reg_set_mbus_fmt(mdev, &mbus_fmt);
+		mxr_reg_streamon(mdev);
+		ret = v4l2_subdev_call(sd, video, s_stream, 1);
+		WARN(ret, "starting stream failed for output %s\n", sd->name);
+	}
+	mutex_unlock(&mdev->mutex);
+	mxr_reg_dump(mdev);
+	/* FIXME: what to do when streaming fails? */
+}
+
+void mxr_streamer_put(struct mxr_device *mdev)
+{
+	mutex_lock(&mdev->mutex);
+	--mdev->n_streamer;
+	dev_info(mdev->dev, "%s(%d)\n", __func__, mdev->n_streamer);
+	if (mdev->n_streamer == 0) {
+		int ret;
+		struct v4l2_subdev *sd = to_outsd(mdev);
+		mxr_reg_streamoff(mdev);
+		ret = v4l2_subdev_call(sd, video, s_stream, 0);
+		WARN(ret, "stopping stream failed for output %s\n", sd->name);
+	}
+	WARN(mdev->n_streamer < 0, "negative number of streamers (%d)\n",
+		mdev->n_streamer);
+	mutex_unlock(&mdev->mutex);
+	mxr_reg_dump(mdev);
+}
+
+void mxr_output_get(struct mxr_device *mdev)
+{
+	mutex_lock(&mdev->mutex);
+	++mdev->n_output;
+	dev_info(mdev->dev, "%s(%d)\n", __func__, mdev->n_output);
+	mutex_unlock(&mdev->mutex);
+}
+
+void mxr_output_put(struct mxr_device *mdev)
+{
+	mutex_lock(&mdev->mutex);
+	--mdev->n_output;
+	dev_info(mdev->dev, "%s(%d)\n", __func__, mdev->n_output);
+	WARN(mdev->n_output < 0, "negative number of output users (%d)\n",
+		mdev->n_output);
+	mutex_unlock(&mdev->mutex);
+}
+
diff --git a/drivers/media/video/s5p-tv/mixer_grp_layer.c b/drivers/media/video/s5p-tv/mixer_grp_layer.c
new file mode 100644
index 0000000..6d1a694
--- /dev/null
+++ b/drivers/media/video/s5p-tv/mixer_grp_layer.c
@@ -0,0 +1,181 @@
+/*
+ * Samsung TV Mixer driver
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ *
+ * Tomasz Stanislawski, t.stanislaws@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 Foundiation. either version 2 of the License,
+ * or (at your option) any later version
+ */
+
+#include "mixer.h"
+#include "mixer_reg.h"
+
+#include <media/videobuf2-cma.h>
+
+/* FORMAT DEFINITIONS */
+
+static const struct mxr_format mxr_fb_fmt_rgb565 = {
+	.name = "RGB565",
+	.fourcc = V4L2_PIX_FMT_RGB565,
+	.num_planes = 1,
+	.plane = {
+		{ .pxWidth = 1, .pxHeight = 1, .bSize = 2 },
+	},
+	.num_subframes = 1,
+	.hwCode = 4,
+};
+
+static const struct mxr_format mxr_fb_fmt_argb1555 = {
+	.name = "ARGB1555",
+	.num_planes = 1,
+	.fourcc = V4L2_PIX_FMT_RGB555,
+	.plane = {
+		{ .pxWidth = 1, .pxHeight = 1, .bSize = 2 },
+	},
+	.num_subframes = 1,
+	.hwCode = 5,
+};
+
+static const struct mxr_format mxr_fb_fmt_argb4444 = {
+	.name = "ARGB4444",
+	.num_planes = 1,
+	.fourcc = V4L2_PIX_FMT_RGB444,
+	.plane = {
+		{ .pxWidth = 1, .pxHeight = 1, .bSize = 2 },
+	},
+	.num_subframes = 1,
+	.hwCode = 6,
+};
+
+static const struct mxr_format mxr_fb_fmt_argb8888 = {
+	.name = "ARGB8888",
+	.fourcc = V4L2_PIX_FMT_BGR32,
+	.num_planes = 1,
+	.plane = {
+		{ .pxWidth = 1, .pxHeight = 1, .bSize = 4 },
+	},
+	.num_subframes = 1,
+	.hwCode = 7,
+};
+
+static const struct mxr_format *mxr_graph_format[] = {
+	&mxr_fb_fmt_rgb565,
+	&mxr_fb_fmt_argb1555,
+	&mxr_fb_fmt_argb4444,
+	&mxr_fb_fmt_argb8888,
+};
+
+/* AUXILIARY CALLBACKS */
+
+static void mxr_graph_layer_release(struct mxr_layer *layer)
+{
+	mxr_base_layer_unregister(layer);
+	mxr_base_layer_release(layer);
+}
+
+static void mxr_graph_buffer_set(struct mxr_layer *layer,
+	struct mxr_buffer *buf)
+{
+	dma_addr_t addr = 0;
+	if (buf)
+		addr = vb2_cma_plane_paddr(&buf->vb, 0);
+	mxr_reg_graph_buffer(layer->mdev, layer->idx, addr);
+}
+
+static void mxr_graph_stream_set(struct mxr_layer *layer, int en)
+{
+	mxr_reg_graph_layer_stream(layer->mdev, layer->idx, en);
+}
+
+static void mxr_graph_format_set(struct mxr_layer *layer)
+{
+	mxr_reg_graph_format(layer->mdev, layer->idx,
+		layer->fmt, &layer->geo);
+}
+
+static void mxr_graph_fix_geometry(struct mxr_layer *layer)
+{
+	struct mxr_geometry *geo = &layer->geo;
+	/* limit to boundary size */
+	geo->src.full_width = clamp_val(geo->src.full_width, 1, 32767);
+	geo->src.full_height = clamp_val(geo->src.full_height, 1, 2047);
+	geo->src.width = clamp_val(geo->src.width, 1, geo->src.full_width);
+	geo->src.width = min(geo->src.width, 2047U);
+	/* not possible to crop of Y axis */
+	geo->src.y_offset = min(geo->src.y_offset, geo->src.full_height - 1);
+	geo->src.height = geo->src.full_height - geo->src.y_offset;
+	/* limitting offset */
+	geo->src.x_offset = min(geo->src.x_offset,
+		geo->src.full_width - geo->src.width);
+
+	/* setting position in output */
+	geo->dst.width = min(geo->dst.width, geo->dst.full_width);
+	geo->dst.height = min(geo->dst.height, geo->dst.full_height);
+
+	/* Mixer supports only 1x and 2x scaling */
+	if (geo->dst.width >= 2 * geo->src.width) {
+		geo->x_ratio = 1;
+		geo->dst.width = 2 * geo->src.width;
+	} else {
+		geo->x_ratio = 0;
+		geo->dst.width = geo->src.width;
+	}
+
+	if (geo->dst.height >= 2 * geo->src.height) {
+		geo->y_ratio = 1;
+		geo->dst.height = 2 * geo->src.height;
+	} else {
+		geo->y_ratio = 0;
+		geo->dst.height = geo->src.height;
+	}
+
+	geo->dst.x_offset = min(geo->dst.x_offset,
+		geo->dst.full_width - geo->dst.width);
+	geo->dst.y_offset = min(geo->dst.y_offset,
+		geo->dst.full_height - geo->dst.height);
+}
+
+/* PUBLIC API */
+
+struct mxr_layer *mxr_graph_layer_create(struct mxr_device *mdev, int idx)
+{
+	struct mxr_layer *layer;
+	struct device *dev = mdev->dev;
+	int ret;
+	struct mxr_layer_ops ops = {
+		.release = mxr_graph_layer_release,
+		.buffer_set = mxr_graph_buffer_set,
+		.stream_set = mxr_graph_stream_set,
+		.format_set = mxr_graph_format_set,
+		.fix_geometry = mxr_graph_fix_geometry,
+	};
+	char name[32];
+
+	sprintf(name, "graph%d", idx);
+
+	layer = mxr_base_layer_create(mdev, idx, name, &ops);
+	if (layer == NULL) {
+		dev_err(dev, "failed to initialize layer(%d) base\n", idx);
+		goto fail;
+	}
+
+	layer->fmt_array = mxr_graph_format;
+	layer->fmt_array_size = ARRAY_SIZE(mxr_graph_format);
+
+	ret = mxr_base_layer_register(layer);
+	if (ret)
+		goto fail_layer;
+
+	return layer;
+
+fail_layer:
+	mxr_base_layer_release(layer);
+
+fail:
+	return NULL;
+}
+
diff --git a/drivers/media/video/s5p-tv/mixer_reg.c b/drivers/media/video/s5p-tv/mixer_reg.c
new file mode 100644
index 0000000..b96d2da
--- /dev/null
+++ b/drivers/media/video/s5p-tv/mixer_reg.c
@@ -0,0 +1,532 @@
+/*
+ * Samsung TV Mixer driver
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ *
+ * Tomasz Stanislawski, t.stanislaws@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 Foundiation. either version 2 of the License,
+ * or (at your option) any later version
+ */
+
+#include "mixer_reg.h"
+#include "regs-vmx.h"
+#include "regs-vp.h"
+
+#include <linux/delay.h>
+
+/* Register access subroutines */
+
+static inline u32 vp_read(struct mxr_device *mdev, u32 reg_id)
+{
+	return readl(mdev->vp_regs + reg_id);
+}
+
+static inline void vp_write(struct mxr_device *mdev, u32 reg_id, u32 val)
+{
+	writel(val, mdev->vp_regs + reg_id);
+}
+
+static inline void vp_write_mask(struct mxr_device *mdev, u32 reg_id,
+	u32 val, u32 mask)
+{
+	u32 old = vp_read(mdev, reg_id);
+	val = (val & mask) | (old & ~mask);
+	writel(val, mdev->vp_regs + reg_id);
+}
+
+static inline u32 mxr_read(struct mxr_device *mdev, u32 reg_id)
+{
+	return readl(mdev->mxr_regs + reg_id);
+}
+
+static inline void mxr_write(struct mxr_device *mdev, u32 reg_id, u32 val)
+{
+	writel(val, mdev->mxr_regs + reg_id);
+}
+
+static inline void mxr_write_mask(struct mxr_device *mdev, u32 reg_id,
+	u32 val, u32 mask)
+{
+	u32 old = mxr_read(mdev, reg_id);
+	val = (val & mask) | (old & ~mask);
+	writel(val, mdev->mxr_regs + reg_id);
+}
+
+void mxr_vsync_set_update(struct mxr_device *mdev, int en)
+{
+	/* block update on vsync */
+	mxr_write_mask(mdev, MXR_STATUS, en ? MXR_STATUS_SYNC_ENABLE : 0,
+		MXR_STATUS_SYNC_ENABLE);
+	vp_write(mdev, VP_SHADOW_UPDATE, en ? VP_SHADOW_UPDATE_ENABLE : 0);
+}
+
+static void __mxr_reg_vp_reset(struct mxr_device *mdev)
+{
+	int tries = 100;
+	vp_write(mdev, VP_SRESET, VP_SRESET_PROCESSING);
+	for (tries = 100; tries; --tries) {
+		/* waiting until VP_SRESET_PROCESSING is 0 */
+		if (~vp_read(mdev, VP_SRESET) & VP_SRESET_PROCESSING)
+			break;
+		mdelay(10);
+	}
+	WARN(tries == 0, "failed to reset Video Processor\n");
+}
+
+static void mxr_reg_vp_default_filter(struct mxr_device *mdev);
+
+void mxr_reg_reset(struct mxr_device *mdev)
+{
+	unsigned long flags;
+	u32 val; /* value stored to register */
+
+	spin_lock_irqsave(&mdev->reg_slock, flags);
+	mxr_vsync_set_update(mdev, MXR_DISABLE);
+
+	/* FIXME: value of dest bit should configured by s_output and pdata */
+	/* set HDMI output in RGB888 mode */
+	mxr_write(mdev, MXR_CFG, MXR_CFG_DST_HDMI | MXR_CFG_OUT_RGB888);
+
+	/* 16 beat burst in DMA */
+	mxr_write_mask(mdev, MXR_STATUS, MXR_STATUS_16_BURST,
+		MXR_STATUS_BURST_MASK);
+
+	/* setting default layer priority: layer1 > video > layer0
+	 * because typical usage scenario would be
+	 * layer0 - framebuffer
+	 * video - video overlay
+	 * layer1 - OSD
+	 */
+	val  = MXR_LAYER_CFG_GRP0_VAL(1);
+	val |= MXR_LAYER_CFG_VP_VAL(2);
+	val |= MXR_LAYER_CFG_GRP1_VAL(3);
+	mxr_write(mdev, MXR_LAYER_CFG, val);
+
+	/* use dark gray background color */
+	mxr_write(mdev, MXR_BG_COLOR0, 0x808080);
+	mxr_write(mdev, MXR_BG_COLOR1, 0x808080);
+	mxr_write(mdev, MXR_BG_COLOR2, 0x808080);
+
+	/* setting graphical layers */
+
+	val  = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */
+	val |= MXR_GRP_CFG_BLEND_PRE_MUL; /* premul mode */
+	val |= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */
+
+	/* the same configuration for both layers */
+	mxr_write(mdev, MXR_GRAPHIC_CFG(0), val);
+	mxr_write(mdev, MXR_GRAPHIC_CFG(1), val);
+
+	/* configuration of Video Processor Registers */
+	__mxr_reg_vp_reset(mdev);
+	mxr_reg_vp_default_filter(mdev);
+
+	mxr_vsync_set_update(mdev, MXR_ENABLE);
+	spin_unlock_irqrestore(&mdev->reg_slock, flags);
+}
+
+void mxr_reg_graph_format(struct mxr_device *mdev, int idx,
+	const struct mxr_format *fmt, const struct mxr_geometry *geo)
+{
+	u32 val;
+	unsigned long flags;
+
+	spin_lock_irqsave(&mdev->reg_slock, flags);
+	mxr_vsync_set_update(mdev, MXR_DISABLE);
+
+	/* setup format */
+	mxr_write_mask(mdev, MXR_GRAPHIC_CFG(idx),
+		MXR_GRP_CFG_FORMAT_VAL(fmt->hwCode), MXR_GRP_CFG_FORMAT_MASK);
+
+	/* setup geometry */
+	mxr_write(mdev, MXR_GRAPHIC_SPAN(idx), geo->src.full_width);
+	val  = MXR_GRP_WH_WIDTH(geo->src.width);
+	val |= MXR_GRP_WH_HEIGHT(geo->src.height);
+	val |= MXR_GRP_WH_H_SCALE(geo->x_ratio);
+	val |= MXR_GRP_WH_V_SCALE(geo->y_ratio);
+	mxr_write(mdev, MXR_GRAPHIC_WH(idx), val);
+
+	/* setup offsets in source image */
+	val  = MXR_GRP_SXY_SX(geo->src.x_offset);
+	val |= MXR_GRP_SXY_SY(geo->src.y_offset);
+	mxr_write(mdev, MXR_GRAPHIC_SXY(idx), val);
+
+	/* setup offsets in display image */
+	val  = MXR_GRP_DXY_DX(geo->dst.x_offset);
+	val |= MXR_GRP_DXY_DY(geo->dst.y_offset);
+	mxr_write(mdev, MXR_GRAPHIC_DXY(idx), val);
+
+	mxr_vsync_set_update(mdev, MXR_ENABLE);
+	spin_unlock_irqrestore(&mdev->reg_slock, flags);
+}
+
+void mxr_reg_vp_format(struct mxr_device *mdev,
+	const struct mxr_format *fmt, const struct mxr_geometry *geo)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&mdev->reg_slock, flags);
+	mxr_vsync_set_update(mdev, MXR_DISABLE);
+
+	vp_write_mask(mdev, VP_MODE, fmt->hwCode, VP_MODE_FMT_MASK);
+
+	/* setting size of input image */
+	vp_write(mdev, VP_IMG_SIZE_Y, VP_IMG_HSIZE(geo->src.full_width) |
+		VP_IMG_VSIZE(geo->src.full_height));
+	vp_write(mdev, VP_IMG_SIZE_C, VP_IMG_HSIZE(geo->src.full_width) |
+		VP_IMG_VSIZE(geo->src.full_height));
+
+	vp_write(mdev, VP_SRC_WIDTH, geo->src.width);
+	vp_write(mdev, VP_SRC_HEIGHT, geo->src.height);
+	vp_write(mdev, VP_SRC_H_POSITION,
+		VP_SRC_H_POSITION_VAL(geo->src.x_offset));
+	vp_write(mdev, VP_SRC_V_POSITION, geo->src.y_offset);
+
+	vp_write(mdev, VP_DST_WIDTH, geo->dst.width);
+	vp_write(mdev, VP_DST_HEIGHT, geo->dst.height);
+	vp_write(mdev, VP_DST_H_POSITION, geo->dst.x_offset);
+	vp_write(mdev, VP_DST_V_POSITION, geo->dst.y_offset);
+
+	vp_write(mdev, VP_H_RATIO, geo->x_ratio);
+	vp_write(mdev, VP_V_RATIO, geo->y_ratio);
+
+	vp_write(mdev, VP_ENDIAN_MODE, VP_ENDIAN_MODE_LITTLE);
+
+	mxr_vsync_set_update(mdev, MXR_ENABLE);
+	spin_unlock_irqrestore(&mdev->reg_slock, flags);
+
+}
+
+void mxr_reg_graph_buffer(struct mxr_device *mdev, int idx, dma_addr_t addr)
+{
+	u32 val = addr ? ~0 : 0;
+	unsigned long flags;
+	/*printk(KERN_INFO "%s(%08x)\n", __func__, addr);*/
+	spin_lock_irqsave(&mdev->reg_slock, flags);
+	mxr_vsync_set_update(mdev, MXR_DISABLE);
+
+	if (idx == 0)
+		mxr_write_mask(mdev, MXR_CFG, val, MXR_CFG_GRP0_ENABLE);
+	else
+		mxr_write_mask(mdev, MXR_CFG, val, MXR_CFG_GRP1_ENABLE);
+	mxr_write(mdev, MXR_GRAPHIC_BASE(idx), addr);
+
+	mxr_vsync_set_update(mdev, MXR_ENABLE);
+	spin_unlock_irqrestore(&mdev->reg_slock, flags);
+}
+
+void mxr_reg_vp_buffer(struct mxr_device *mdev, dma_addr_t luma_addr,
+	dma_addr_t chroma_addr)
+{
+	u32 val = luma_addr ? ~0 : 0;
+	unsigned long flags;
+	/*printk(KERN_CRIT "%s(luma=%08x, chroma=%08x)\n", __func__,
+		luma_addr, chroma_addr);*/
+	spin_lock_irqsave(&mdev->reg_slock, flags);
+	mxr_vsync_set_update(mdev, MXR_DISABLE);
+
+	mxr_write_mask(mdev, MXR_CFG, val, MXR_CFG_VP_ENABLE);
+	vp_write(mdev, VP_TOP_Y_PTR, luma_addr);
+	vp_write(mdev, VP_TOP_C_PTR, chroma_addr);
+
+	mxr_vsync_set_update(mdev, MXR_ENABLE);
+	spin_unlock_irqrestore(&mdev->reg_slock, flags);
+}
+
+static void mxr_irq_layer_handle(struct mxr_layer *layer)
+{
+	struct list_head *head = &layer->enq_list;
+	struct mxr_buffer *done;
+
+	/* skip non-existing layer */
+	if (layer == NULL)
+		return;
+
+	spin_lock(&layer->enq_slock);
+	if (layer->state == MXR_LAYER_IDLE)
+		goto done;
+
+	done = layer->shadow_buf;
+	layer->shadow_buf = layer->update_buf;
+
+	if (list_empty(head)) {
+		if (layer->state != MXR_LAYER_STREAMING)
+			layer->update_buf = NULL;
+	} else {
+		struct mxr_buffer *next;
+		next = list_first_entry(head, struct mxr_buffer, list);
+		list_del(&next->list);
+		layer->update_buf = next;
+	}
+
+	layer->ops.buffer_set(layer, layer->update_buf);
+
+	if (done && done != layer->shadow_buf)
+		vb2_buffer_done(&done->vb, VB2_BUF_STATE_DONE);
+
+done:
+	spin_unlock(&layer->enq_slock);
+}
+
+irqreturn_t mxr_irq_handler(int irq, void *dev_data)
+{
+	struct mxr_device *mdev = dev_data;
+	u32 i, val;
+	spin_lock(&mdev->reg_slock);
+	val = mxr_read(mdev, MXR_INT_STATUS);
+
+	/* clear interrupts */
+	mxr_write(mdev, MXR_INT_STATUS, val);
+
+	spin_unlock(&mdev->reg_slock);
+	/* leave on non-vsync event */
+	if (~val & MXR_INT_EN_VSYNC)
+		return IRQ_HANDLED;
+	for (i = 0; i < MXR_MAX_LAYERS; ++i)
+		mxr_irq_layer_handle(mdev->layer[i]);
+	return IRQ_HANDLED;
+}
+
+void mxr_reg_streamon(struct mxr_device *mdev)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&mdev->reg_slock, flags);
+	mxr_vsync_set_update(mdev, MXR_DISABLE);
+
+	/* start MIXER */
+	mxr_write_mask(mdev, MXR_STATUS, ~0, MXR_STATUS_REG_RUN);
+	/* start all interrupts */
+	mxr_write_mask(mdev, MXR_INT_EN, ~0, MXR_INT_EN_ALL);
+
+	mxr_vsync_set_update(mdev, MXR_ENABLE);
+	spin_unlock_irqrestore(&mdev->reg_slock, flags);
+}
+
+void mxr_reg_streamoff(struct mxr_device *mdev)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&mdev->reg_slock, flags);
+	mxr_vsync_set_update(mdev, MXR_DISABLE);
+
+	/* stop MIXER */
+	mxr_write_mask(mdev, MXR_STATUS, 0, MXR_STATUS_REG_RUN);
+	/* disable all interrupts */
+	mxr_write_mask(mdev, MXR_INT_EN, 0, MXR_INT_EN_ALL);
+
+	mxr_vsync_set_update(mdev, MXR_ENABLE);
+	spin_unlock_irqrestore(&mdev->reg_slock, flags);
+}
+
+void mxr_reg_set_mbus_fmt(struct mxr_device *mdev,
+	struct v4l2_mbus_framefmt *fmt)
+{
+	u32 val = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&mdev->reg_slock, flags);
+	mxr_vsync_set_update(mdev, MXR_DISABLE);
+
+	/* choosing between interlace and progressive mode */
+	if (fmt->field == V4L2_FIELD_INTERLACED)
+		val |= MXR_CFG_SCAN_INTERLACE;
+	else
+		val |= MXR_CFG_SCAN_PROGRASSIVE;
+
+	/* choosing between porper HD and SD mode */
+	if (fmt->height == 480)
+		val |= MXR_CFG_NTSC | MXR_CFG_SD;
+	else if (fmt->height == 576)
+		val |= MXR_CFG_PAL | MXR_CFG_SD;
+	else if (fmt->height == 720)
+		val |= MXR_CFG_HD_720 | MXR_CFG_HD;
+	else if (fmt->height == 1080)
+		val |= MXR_CFG_HD_1080 | MXR_CFG_HD;
+	else
+		WARN(1, "unrecognized mbus height %u!\n", fmt->height);
+
+	mxr_write_mask(mdev, MXR_CFG, val, MXR_CFG_SCAN_MASK);
+
+	mxr_vsync_set_update(mdev, MXR_ENABLE);
+	spin_unlock_irqrestore(&mdev->reg_slock, flags);
+}
+
+void mxr_reg_graph_layer_stream(struct mxr_device *mdev, int idx, int en)
+{
+	/* no extra actions need to be done */
+}
+
+void mxr_reg_vp_layer_stream(struct mxr_device *mdev, int en)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&mdev->reg_slock, flags);
+	mxr_vsync_set_update(mdev, MXR_DISABLE);
+
+	vp_write_mask(mdev, VP_ENABLE, en ? VP_ENABLE_ON : 0, VP_ENABLE_ON);
+
+	mxr_vsync_set_update(mdev, MXR_ENABLE);
+	spin_unlock_irqrestore(&mdev->reg_slock, flags);
+}
+
+static const u8 filter_y_horiz_tap8[] = {
+	0,	-1,	-1,	-1,	-1,	-1,	-1,	-1,
+	-1,	-1,	-1,	-1,	-1,	0,	0,	0,
+	0,	2,	4,	5,	6,	6,	6,	6,
+	6,	5,	5,	4,	3,	2,	1,	1,
+	0,	-6,	-12,	-16,	-18,	-20,	-21,	-20,
+	-20,	-18,	-16,	-13,	-10,	-8,	-5,	-2,
+	127,	126,	125,	121,	114,	107,	99,	89,
+	79,	68,	57,	46,	35,	25,	16,	8,
+};
+
+static const u8 filter_y_vert_tap4[] = {
+	0,	-3,	-6,	-8,	-8,	-8,	-8,	-7,
+	-6,	-5,	-4,	-3,	-2,	-1,	-1,	0,
+	127,	126,	124,	118,	111,	102,	92,	81,
+	70,	59,	48,	37,	27,	19,	11,	5,
+	0,	5,	11,	19,	27,	37,	48,	59,
+	70,	81,	92,	102,	111,	118,	124,	126,
+	0,	0,	-1,	-1,	-2,	-3,	-4,	-5,
+	-6,	-7,	-8,	-8,	-8,	-8,	-6,	-3,
+};
+
+static const u8 filter_cr_horiz_tap4[] = {
+	0,	-3,	-6,	-8,	-8,	-8,	-8,	-7,
+	-6,	-5,	-4,	-3,	-2,	-1,	-1,	0,
+	127,	126,	124,	118,	111,	102,	92,	81,
+	70,	59,	48,	37,	27,	19,	11,	5,
+};
+
+static inline void mxr_reg_vp_filter_set(struct mxr_device *mdev,
+	int reg_id, const u8 *data, unsigned int size)
+{
+	/* assure 4-byte align */
+	BUG_ON(size & 3);
+	printk(KERN_ERR "%08x <- ", reg_id);
+	for (; size; size -= 4, reg_id += 4, data += 4) {
+		u32 val = (data[0] << 24) |  (data[1] << 16) |
+			(data[2] << 8) | data[3];
+		vp_write(mdev, reg_id, val);
+		printk(KERN_CONT "%08x, ", val);
+	}
+	printk(KERN_CONT "\n");
+}
+
+static void mxr_reg_vp_default_filter(struct mxr_device *mdev)
+{
+	mxr_reg_vp_filter_set(mdev, VP_POLY8_Y0_LL,
+		filter_y_horiz_tap8, sizeof filter_y_horiz_tap8);
+	mxr_reg_vp_filter_set(mdev, VP_POLY4_Y0_LL,
+		filter_y_vert_tap4, sizeof filter_y_vert_tap4);
+	mxr_reg_vp_filter_set(mdev, VP_POLY4_C0_LL,
+		filter_cr_horiz_tap4, sizeof filter_cr_horiz_tap4);
+}
+
+static void mxr_reg_mxr_dump(struct mxr_device *mdev)
+{
+#define DUMPREG(reg_id) \
+do { \
+	u32 value = readl(mdev->mxr_regs + reg_id); \
+	printk(KERN_DEBUG #reg_id " = %08x\n", value); \
+} while (0)
+	DUMPREG(MXR_STATUS);
+	DUMPREG(MXR_CFG);
+	DUMPREG(MXR_INT_EN);
+	DUMPREG(MXR_INT_STATUS);
+
+	DUMPREG(MXR_LAYER_CFG);
+	DUMPREG(MXR_VIDEO_CFG);
+
+	DUMPREG(MXR_GRAPHIC0_CFG);
+	DUMPREG(MXR_GRAPHIC0_BASE);
+	DUMPREG(MXR_GRAPHIC0_SPAN);
+	DUMPREG(MXR_GRAPHIC0_WH);
+	DUMPREG(MXR_GRAPHIC0_SXY);
+	DUMPREG(MXR_GRAPHIC0_DXY);
+
+	DUMPREG(MXR_GRAPHIC1_CFG);
+	DUMPREG(MXR_GRAPHIC1_BASE);
+	DUMPREG(MXR_GRAPHIC1_SPAN);
+	DUMPREG(MXR_GRAPHIC1_WH);
+	DUMPREG(MXR_GRAPHIC1_SXY);
+	DUMPREG(MXR_GRAPHIC1_DXY);
+#undef DUMPREG
+}
+
+static void mxr_reg_vp_dump(struct mxr_device *mdev)
+{
+#define DUMPREG(reg_id) \
+do { \
+	u32 value = readl(mdev->vp_regs + reg_id); \
+	printk(KERN_DEBUG #reg_id " = %08x\n", value); \
+} while (0)
+
+	DUMPREG(VP_ENABLE);
+	DUMPREG(VP_SRESET);
+	DUMPREG(VP_SHADOW_UPDATE);
+	DUMPREG(VP_FIELD_ID);
+	DUMPREG(VP_MODE);
+	DUMPREG(VP_IMG_SIZE_Y);
+	DUMPREG(VP_IMG_SIZE_C);
+	DUMPREG(VP_PER_RATE_CTRL);
+	DUMPREG(VP_TOP_Y_PTR);
+	DUMPREG(VP_BOT_Y_PTR);
+	DUMPREG(VP_TOP_C_PTR);
+	DUMPREG(VP_BOT_C_PTR);
+	DUMPREG(VP_ENDIAN_MODE);
+	DUMPREG(VP_SRC_H_POSITION);
+	DUMPREG(VP_SRC_V_POSITION);
+	DUMPREG(VP_SRC_WIDTH);
+	DUMPREG(VP_SRC_HEIGHT);
+	DUMPREG(VP_DST_H_POSITION);
+	DUMPREG(VP_DST_V_POSITION);
+	DUMPREG(VP_DST_WIDTH);
+	DUMPREG(VP_DST_HEIGHT);
+	DUMPREG(VP_H_RATIO);
+	DUMPREG(VP_V_RATIO);
+
+	DUMPREG(VP_FIELD_ID_S);
+	DUMPREG(VP_MODE_S);
+	DUMPREG(VP_IMG_SIZE_Y_S);
+	DUMPREG(VP_IMG_SIZE_C_S);
+	DUMPREG(VP_TOP_Y_PTR_S);
+	DUMPREG(VP_BOT_Y_PTR_S);
+	DUMPREG(VP_TOP_C_PTR_S);
+	DUMPREG(VP_BOT_C_PTR_S);
+	DUMPREG(VP_ENDIAN_MODE_S);
+	DUMPREG(VP_SRC_H_POSITION_S);
+	DUMPREG(VP_SRC_V_POSITION_S);
+	DUMPREG(VP_SRC_WIDTH_S);
+	DUMPREG(VP_SRC_HEIGHT_S);
+	DUMPREG(VP_DST_H_POSITION_S);
+	DUMPREG(VP_DST_V_POSITION_S);
+	DUMPREG(VP_DST_WIDTH_S);
+	DUMPREG(VP_DST_HEIGHT_S);
+	DUMPREG(VP_H_RATIO_S);
+	DUMPREG(VP_V_RATIO_S);
+
+	DUMPREG(VP_PP_BYPASS);
+	DUMPREG(VP_PP_SATURATION);
+	DUMPREG(VP_PP_SHARPNESS);
+	DUMPREG(VP_PP_LINE_EQ0);
+	DUMPREG(VP_PP_LINE_EQ1);
+	DUMPREG(VP_PP_LINE_EQ2);
+	DUMPREG(VP_PP_LINE_EQ3);
+	DUMPREG(VP_PP_LINE_EQ4);
+	DUMPREG(VP_PP_LINE_EQ5);
+	DUMPREG(VP_PP_LINE_EQ6);
+	DUMPREG(VP_PP_LINE_EQ7);
+	DUMPREG(VP_PP_BRIGHT_OFFSET);
+	DUMPREG(VP_VERSION_INFO);
+
+#undef DUMPREG
+}
+
+void mxr_reg_dump(struct mxr_device *mdev)
+{
+	mxr_reg_mxr_dump(mdev);
+	mxr_reg_vp_dump(mdev);
+}
+
diff --git a/drivers/media/video/s5p-tv/mixer_reg.h b/drivers/media/video/s5p-tv/mixer_reg.h
new file mode 100644
index 0000000..e803c05
--- /dev/null
+++ b/drivers/media/video/s5p-tv/mixer_reg.h
@@ -0,0 +1,44 @@
+/*
+ * Samsung TV Mixer driver
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ *
+ * Tomasz Stanislawski, t.stanislaws@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 Foundiation. either version 2 of the License,
+ * or (at your option) any later version
+ */
+
+#ifndef _SAMSUNG_MIXER_REG_H_
+#define _SAMSUNG_MIXER_REG_H_	__FILE__
+
+#include "mixer.h"
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+
+void mxr_vsync_set_update(struct mxr_device *mdev, int en);
+void mxr_reg_reset(struct mxr_device *mdev);
+irqreturn_t mxr_irq_handler(int irq, void *dev_data);
+void mxr_reg_streamon(struct mxr_device *mdev);
+void mxr_reg_streamoff(struct mxr_device *mdev);
+void mxr_reg_set_mbus_fmt(struct mxr_device *mdev,
+	struct v4l2_mbus_framefmt *fmt);
+void mxr_reg_graph_layer_stream(struct mxr_device *mdev, int idx, int en);
+void mxr_reg_graph_buffer(struct mxr_device *mdev, int idx, dma_addr_t addr);
+void mxr_reg_graph_format(struct mxr_device *mdev, int idx,
+	const struct mxr_format *fmt, const struct mxr_geometry *geo);
+
+void mxr_reg_vp_layer_stream(struct mxr_device *mdev, int en);
+void mxr_reg_vp_buffer(struct mxr_device *mdev, dma_addr_t luma_addr,
+	dma_addr_t chroma_addr);
+void mxr_reg_vp_format(struct mxr_device *mdev,
+	const struct mxr_format *fmt, const struct mxr_geometry *geo);
+
+void mxr_reg_dump(struct mxr_device *mdev);
+
+#endif /* _SAMSUNG_MIXER_REG_H_ */
+
diff --git a/drivers/media/video/s5p-tv/mixer_video.c b/drivers/media/video/s5p-tv/mixer_video.c
new file mode 100644
index 0000000..e991c60
--- /dev/null
+++ b/drivers/media/video/s5p-tv/mixer_video.c
@@ -0,0 +1,834 @@
+/*
+ * Samsung TV Mixer driver
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ *
+ * Tomasz Stanislawski, t.stanislaws@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 Foundiation. either version 2 of the License,
+ * or (at your option) any later version
+ */
+
+#include "mixer.h"
+#include "plat/tv.h"
+
+#include <media/v4l2-ioctl.h>
+#include <linux/videodev2.h>
+#include <media/videobuf2-cma.h>
+#include <linux/mm.h>
+#include <linux/version.h>
+
+static int find_reg_callback(struct device *dev, void *p)
+{
+	struct v4l2_subdev **sd = p;
+
+	*sd = dev_get_drvdata(dev);
+	/* non-zero value stops iteration */
+	return 1;
+}
+
+static struct v4l2_subdev *find_and_register_subdev(char *module_name,
+	struct v4l2_device *vdev)
+{
+	struct device_driver *drv;
+	struct v4l2_subdev *sd;
+	int ret;
+
+	request_module(module_name);
+	/* TODO: add waiting until probe is finished */
+	drv = driver_find(module_name, &platform_bus_type);
+	if (WARN(!drv, "driver %s is missing\n", module_name))
+		return NULL;
+	/* driver refcnt is increased, it is safe to iterate over devices */
+	ret = driver_for_each_device(drv, NULL, &sd, find_reg_callback);
+	/* ret == 0 means that find_reg_callback was never executed */
+	WARN(ret == 0, "module %s provides no subdev!\n", module_name);
+	/* v4l2_device_register_subdev detects if sd is NULL */
+	ret = v4l2_device_register_subdev(vdev, sd);
+	put_driver(drv);
+	return ret == 0 ? sd : NULL;
+}
+
+int __devinit mxr_acquire_video(struct mxr_device *mdev,
+	struct mxr_platform_data *pdata)
+{
+	struct device *dev = mdev->dev;
+	struct v4l2_device *vdev = &mdev->v4l2_dev;
+	int i;
+	int ret = 0;
+	struct v4l2_subdev *sd;
+
+	strlcpy(vdev->name, "s5p-tv", sizeof(vdev->name));
+	/* prepare context for V4L2 device */
+	ret = v4l2_device_register(dev, vdev);
+	if (ret) {
+		dev_err(dev, "could not register v4l2 device.\n");
+		goto fail;
+	}
+
+	/* prepare alloc context */
+	mdev->alloc_ctx = vb2_cma_init(dev, NULL, 0);
+	if (IS_ERR_OR_NULL(mdev->alloc_ctx)) {
+		dev_err(dev, "could not initialize allocator's context\n");
+		ret = -ENOMEM;
+		goto fail_v4l2_dev;
+	}
+
+
+	/* registering outputs */
+	for (i = 0; i < pdata->output_cnt && i < MXR_OUTPUTS; ++i) {
+		struct mxr_platform_output *pout = &pdata->output[i];
+		struct mxr_output *out;
+		sd = find_and_register_subdev(pout->module_name, vdev);
+		if (sd == NULL) {
+			dev_err(dev, "failed to find subdev in module '%s'\n",
+				pout->module_name);
+			ret = -ENXIO;
+			goto fail_output;
+		}
+		out = kzalloc(sizeof *out, GFP_KERNEL);
+		if (out == NULL) {
+			dev_err(dev, "no memory for '%s'\n", pout->output_name);
+			ret = -ENOMEM;
+			/* registered subdevs are removed in fail_v4l2_dev */
+			goto fail_output;
+		}
+		strlcpy(out->name, pout->output_name, sizeof(out->name));
+		out->sd = sd;
+		mdev->output[i] = out;
+		dev_info(dev, "added output '%s' from module '%s'\n",
+			pout->output_name, pout->module_name);
+	}
+
+	return 0;
+
+fail_output:
+	/* kfree is NULL-safe */
+	for (i = 0; i < MXR_OUTPUTS; ++i)
+		kfree(mdev->output[i]);
+	memset(mdev->output, 0, sizeof mdev->output);
+
+	/* freeing cma context */
+	vb2_cma_cleanup(mdev->alloc_ctx);
+
+fail_v4l2_dev:
+	/* NOTE: automatically unregisteres all subdevs */
+	v4l2_device_unregister(vdev);
+
+fail:
+	return ret;
+}
+
+void __devexit mxr_release_video(struct mxr_device *mdev)
+{
+	int i;
+
+	/* kfree is NULL-safe */
+	for (i = 0; i < MXR_OUTPUTS; ++i)
+		kfree(mdev->output[i]);
+
+	vb2_cma_cleanup(mdev->alloc_ctx);
+	v4l2_device_unregister(&mdev->v4l2_dev);
+}
+
+static int mxr_querycap(struct file *file, void *priv,
+	struct v4l2_capability *cap)
+{
+	struct mxr_layer *layer = video_drvdata(file);
+	struct mxr_device *mdev = layer->mdev;
+	dev_info(mdev->dev, "%s:%d\n", __func__, __LINE__);
+
+	strlcpy(cap->driver, MXR_DRIVER_NAME, sizeof cap->driver);
+	strlcpy(cap->card, layer->vfd.name, sizeof cap->card);
+	sprintf(cap->bus_info, "%d", layer->idx);
+	cap->version = KERNEL_VERSION(0, 1, 0);
+	cap->capabilities = V4L2_CAP_STREAMING |
+		V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_MPLANE;
+
+	return 0;
+}
+
+/* Geometry handling */
+static void mxr_layer_geo_fix(struct mxr_layer *layer)
+{
+	struct mxr_device *mdev = layer->mdev;
+	struct v4l2_mbus_framefmt mbus_fmt;
+
+	/* TODO: add some dirty flag */
+	mxr_get_mbus_fmt(mdev, &mbus_fmt);
+	layer->geo.dst.full_width = mbus_fmt.width;
+	layer->geo.dst.full_height = mbus_fmt.height;
+	layer->ops.fix_geometry(layer);
+}
+
+static void mxr_layer_default_geo(struct mxr_layer *layer)
+{
+	struct mxr_device *mdev = layer->mdev;
+	struct v4l2_mbus_framefmt mbus_fmt;
+
+	memset(&layer->geo, 0, sizeof layer->geo);
+
+	mxr_get_mbus_fmt(mdev, &mbus_fmt);
+
+	layer->geo.dst.full_width = mbus_fmt.width;
+	layer->geo.dst.full_height = mbus_fmt.height;
+	layer->geo.dst.width = layer->geo.dst.full_width;
+	layer->geo.dst.height = layer->geo.dst.full_height;
+
+	layer->geo.src.full_width = mbus_fmt.width;
+	layer->geo.src.full_height = mbus_fmt.height;
+	layer->geo.src.width = layer->geo.src.full_width;
+	layer->geo.src.height = layer->geo.src.full_height;
+
+	layer->ops.fix_geometry(layer);
+}
+
+static void mxr_geometry_dump(struct device *dev, struct mxr_geometry *geo)
+{
+	dev_info(dev, "src.full_size = (%u, %u)\n",
+		geo->src.full_width, geo->src.full_height);
+	dev_info(dev, "src.size = (%u, %u)\n",
+		geo->src.width, geo->src.height);
+	dev_info(dev, "src.offset = (%u, %u)\n",
+		geo->src.x_offset, geo->src.y_offset);
+	dev_info(dev, "dst.full_size = (%u, %u)\n",
+		geo->dst.full_width, geo->dst.full_height);
+	dev_info(dev, "dst.size = (%u, %u)\n",
+		geo->dst.width, geo->dst.height);
+	dev_info(dev, "dst.offset = (%u, %u)\n",
+		geo->dst.x_offset, geo->dst.y_offset);
+	dev_info(dev, "ratio = (%u, %u)\n",
+		geo->x_ratio, geo->y_ratio);
+}
+
+
+static const struct mxr_format *find_format_by_fourcc(
+	struct mxr_layer *layer, unsigned long fourcc);
+static const struct mxr_format *find_format_by_index(
+	struct mxr_layer *layer, unsigned long index);
+
+static int mxr_enum_fmt(struct file *file, void  *priv,
+	struct v4l2_fmtdesc *f)
+{
+	struct mxr_layer *layer = video_drvdata(file);
+	struct mxr_device *mdev = layer->mdev;
+	const struct mxr_format *fmt;
+
+	dev_info(mdev->dev, "%s\n", __func__);
+	fmt = find_format_by_index(layer, f->index);
+	if (fmt == NULL)
+		return -EINVAL;
+
+	strlcpy(f->description, fmt->name, sizeof(f->description));
+	f->pixelformat = fmt->fourcc;
+
+	return 0;
+}
+
+static int mxr_s_fmt(struct file *file, void *priv,
+	struct v4l2_format *f)
+{
+	struct mxr_layer *layer = video_drvdata(file);
+	const struct mxr_format *fmt;
+	struct v4l2_pix_format_mplane *pix;
+	struct mxr_device *mdev = layer->mdev;
+	struct mxr_geometry *geo = &layer->geo;
+	int i;
+
+	dev_info(mdev->dev, "%s:%d\n", __func__, __LINE__);
+
+	pix = &f->fmt.pix_mp;
+	fmt = find_format_by_fourcc(layer, pix->pixelformat);
+	if (fmt == NULL) {
+		dev_err(mdev->dev, "not recognized fourcc: %08x\n",
+			pix->pixelformat);
+		return -EINVAL;
+	}
+	layer->fmt = fmt;
+	geo->src.full_width = pix->width;
+	geo->src.width = pix->width;
+	geo->src.full_height = pix->height;
+	geo->src.height = pix->height;
+	/* assure consistency of geometry */
+	mxr_layer_geo_fix(layer);
+
+	for (i = 0; i < fmt->num_subframes; ++i) {
+		unsigned int nPixel = fmt->plane[i].pxHeight *
+			fmt->plane[i].pxWidth;
+		pix->plane_fmt[i].bytesperline = geo->src.full_width *
+			fmt->plane[i].bSize / nPixel;
+	}
+	printk(KERN_ERR "width=%u height=%u bpp=%u span=%u\n",
+		geo->src.width, geo->src.height,
+		pix->plane_fmt[0].bytesperline, geo->src.full_width);
+	return 0;
+}
+
+static int mxr_g_fmt(struct file *file, void *priv,
+			     struct v4l2_format *f)
+{
+	struct mxr_layer *layer = video_drvdata(file);
+	struct mxr_device *mdev = layer->mdev;
+	dev_info(mdev->dev, "%s:%d\n", __func__, __LINE__);
+
+	f->fmt.pix.width	= layer->geo.src.full_width;
+	f->fmt.pix.height	= layer->geo.src.full_height;
+	f->fmt.pix.field	= V4L2_FIELD_NONE;
+	f->fmt.pix.pixelformat	= layer->fmt->fourcc;
+
+	return 0;
+}
+
+static inline struct mxr_crop *choose_crop_by_type(struct mxr_geometry *geo,
+	enum v4l2_buf_type type)
+{
+	switch (type) {
+	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+		return &geo->dst;
+	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+		return &geo->src;
+	default:
+		return NULL;
+	}
+}
+
+static int mxr_g_crop(struct file *file, void *fh, struct v4l2_crop *a)
+{
+	struct mxr_layer *layer = video_drvdata(file);
+	struct mxr_device *mdev = layer->mdev;
+	struct mxr_crop *crop;
+	dev_info(mdev->dev, "%s:%d\n", __func__, __LINE__);
+	crop = choose_crop_by_type(&layer->geo, a->type);
+	if (crop == NULL)
+		return -EINVAL;
+	mxr_layer_geo_fix(layer);
+	a->c.left = crop->x_offset;
+	a->c.top = crop->y_offset;
+	a->c.width = crop->width;
+	a->c.height = crop->height;
+	return 0;
+}
+
+static int mxr_s_crop(struct file *file, void *fh, struct v4l2_crop *a)
+{
+	struct mxr_layer *layer = video_drvdata(file);
+	struct mxr_device *mdev = layer->mdev;
+	struct mxr_crop *crop;
+	dev_info(mdev->dev, "%s:%d\n", __func__, __LINE__);
+	crop = choose_crop_by_type(&layer->geo, a->type);
+	if (crop == NULL)
+		return -EINVAL;
+	crop->x_offset = a->c.left;
+	crop->y_offset = a->c.top;
+	crop->width = a->c.width;
+	crop->height = a->c.height;
+	mxr_layer_geo_fix(layer);
+	return 0;
+}
+
+static int mxr_cropcap(struct file *file, void *fh, struct v4l2_cropcap *a)
+{
+	struct mxr_layer *layer = video_drvdata(file);
+	struct mxr_device *mdev = layer->mdev;
+	struct mxr_crop *crop;
+	dev_info(mdev->dev, "%s:%d\n", __func__, __LINE__);
+	crop = choose_crop_by_type(&layer->geo, a->type);
+	if (crop == NULL)
+		return -EINVAL;
+	mxr_layer_geo_fix(layer);
+	a->bounds.left = 0;
+	a->bounds.top = 0;
+	a->bounds.width = crop->full_width;
+	a->bounds.top = crop->full_height;
+	a->defrect = a->bounds;
+	return 0;
+}
+
+static int mxr_enum_dv_presets(struct file *file, void *fh,
+	struct v4l2_dv_enum_preset *preset)
+{
+	struct mxr_layer *layer = video_drvdata(file);
+	struct mxr_device *mdev = layer->mdev;
+	int ret;
+
+	/* lock protects from changing sd_out */
+	mutex_lock(&mdev->mutex);
+	ret = v4l2_subdev_call(to_outsd(mdev), video, enum_dv_presets, preset);
+	mutex_unlock(&mdev->mutex);
+
+	return ret ? -EINVAL : 0;
+}
+
+static int mxr_s_dv_preset(struct file *file, void *fh,
+	struct v4l2_dv_preset *preset)
+{
+	struct mxr_layer *layer = video_drvdata(file);
+	struct mxr_device *mdev = layer->mdev;
+	int ret;
+
+	/* lock protects from changing sd_out */
+	mutex_lock(&mdev->mutex);
+
+	/* preset change cannot be done while there is an entity
+	 * dependant on output configuration
+	 */
+	if (mdev->n_output == 0)
+		ret = v4l2_subdev_call(to_outsd(mdev), video, s_dv_preset,
+			preset);
+	else
+		ret = -EBUSY;
+
+	mutex_unlock(&mdev->mutex);
+
+	return ret;
+}
+
+static int mxr_g_dv_preset(struct file *file, void *fh,
+	struct v4l2_dv_preset *preset)
+{
+	struct mxr_layer *layer = video_drvdata(file);
+	struct mxr_device *mdev = layer->mdev;
+	int ret;
+
+	/* lock protects from changing sd_out */
+	mutex_lock(&mdev->mutex);
+	ret = v4l2_subdev_call(to_outsd(mdev), video, query_dv_preset, preset);
+	mutex_unlock(&mdev->mutex);
+
+	return ret;
+}
+
+static int mxr_enum_output(struct file *file, void *fh, struct v4l2_output *a)
+{
+	struct mxr_layer *layer = video_drvdata(file);
+	struct mxr_device *mdev = layer->mdev;
+	struct mxr_output *out;
+
+	if (a->index >= MXR_OUTPUTS)
+		return -EINVAL;
+	out = mdev->output[a->index];
+	if (out == NULL)
+		return -EINVAL;
+	strlcpy(a->name, out->name, sizeof(a->name));
+	/* capabilities are already configured by v4l2_ioctl */
+
+	/* FIXME: no std_id is set for analog output.
+	 * Add g_std_output to subdev api, use it to configure std field.
+	 */
+
+	return 0;
+}
+
+static int mxr_reqbufs(struct file *file, void *priv,
+			  struct v4l2_requestbuffers *p)
+{
+	struct mxr_layer *layer = video_drvdata(file);
+	struct mxr_device *mdev = layer->mdev;
+	dev_info(mdev->dev, "%s:%d\n", __func__, __LINE__);
+	return vb2_reqbufs(&layer->vb_queue, p);
+}
+
+static int mxr_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+	struct mxr_layer *layer = video_drvdata(file);
+	struct mxr_device *mdev = layer->mdev;
+	dev_info(mdev->dev, "%s:%d\n", __func__, __LINE__);
+	return vb2_querybuf(&layer->vb_queue, p);
+}
+
+static int mxr_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+	struct mxr_layer *layer = video_drvdata(file);
+	struct mxr_device *mdev = layer->mdev;
+	dev_info(mdev->dev, "%s:%d(%d)\n", __func__, __LINE__,
+		p->index);
+	return vb2_qbuf(&layer->vb_queue, p);
+}
+
+static int mxr_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+	struct mxr_layer *layer = video_drvdata(file);
+	struct mxr_device *mdev = layer->mdev;
+	dev_info(mdev->dev, "%s:%d\n", __func__, __LINE__);
+	return vb2_dqbuf(&layer->vb_queue, p, file->f_flags & O_NONBLOCK);
+}
+
+static int mxr_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+	struct mxr_layer *layer = video_drvdata(file);
+	struct mxr_device *mdev = layer->mdev;
+	dev_info(mdev->dev, "%s:%d\n", __func__, __LINE__);
+	return vb2_streamon(&layer->vb_queue, i);
+}
+
+static int mxr_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+	struct mxr_layer *layer = video_drvdata(file);
+	struct mxr_device *mdev = layer->mdev;
+	dev_info(mdev->dev, "%s:%d\n", __func__, __LINE__);
+	return vb2_streamoff(&layer->vb_queue, i);
+}
+
+static const struct v4l2_ioctl_ops mxr_ioctl_ops = {
+	.vidioc_querycap = mxr_querycap,
+	.vidioc_enum_fmt_vid_out = mxr_enum_fmt,
+	.vidioc_s_fmt_vid_out_mplane = mxr_s_fmt,
+	.vidioc_g_fmt_vid_out_mplane = mxr_g_fmt,
+	.vidioc_reqbufs = mxr_reqbufs,
+	.vidioc_querybuf = mxr_querybuf,
+	.vidioc_qbuf = mxr_qbuf,
+	.vidioc_dqbuf = mxr_dqbuf,
+	.vidioc_streamon = mxr_streamon,
+	.vidioc_streamoff = mxr_streamoff,
+
+	/* Preset functions */
+	.vidioc_enum_dv_presets = mxr_enum_dv_presets,
+	.vidioc_s_dv_preset = mxr_s_dv_preset,
+	.vidioc_g_dv_preset = mxr_g_dv_preset,
+
+	/* Output handling */
+	.vidioc_enum_output = mxr_enum_output,
+	/* Crop ioctls */
+	.vidioc_g_crop = mxr_g_crop,
+	.vidioc_s_crop = mxr_s_crop,
+	.vidioc_cropcap = mxr_cropcap,
+};
+
+static int mxr_video_open(struct file *file)
+{
+	struct mxr_layer *layer = video_drvdata(file);
+	struct mxr_device *mdev = layer->mdev;
+	struct device *dev = mdev->dev;
+	int ret = 0;
+
+	dev_info(dev, "%s:%d\n", __func__, __LINE__);
+	/* assure device probe is finished */
+	wait_for_device_probe();
+	/* lock layer->mutex is already taken by video_device */
+	if (++layer->n_user == 1) {
+		mxr_power_get(mdev);
+		/* set default format, first on the list */
+		layer->fmt = layer->fmt_array[0];
+		/* setup default geometry */
+		mxr_layer_default_geo(layer);
+		ret = vb2_queue_init(&layer->vb_queue);
+		if (ret != 0) {
+			dev_err(dev, "failed to initialize vb2 queue\n");
+			mxr_power_put(mdev);
+			--layer->n_user;
+		}
+	}
+	return ret;
+}
+
+static unsigned int
+mxr_video_poll(struct file *file, struct poll_table_struct *wait)
+{
+	struct mxr_layer *layer = video_drvdata(file);
+	struct mxr_device *mdev = layer->mdev;
+	struct device *dev = mdev->dev;
+
+	dev_info(dev, "%s:%d\n", __func__, __LINE__);
+
+	return vb2_poll(&layer->vb_queue, file, wait);
+}
+
+static int mxr_video_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct mxr_layer *layer = video_drvdata(file);
+	struct mxr_device *mdev = layer->mdev;
+	struct device *dev = mdev->dev;
+
+	dev_info(dev, "%s:%d\n", __func__, __LINE__);
+
+	return vb2_mmap(&layer->vb_queue, vma);
+}
+
+static int mxr_video_release(struct file *file)
+{
+	struct mxr_layer *layer = video_drvdata(file);
+	struct mxr_device *mdev = layer->mdev;
+	struct device *dev = mdev->dev;
+
+	dev_info(dev, "%s:%d\n", __func__, __LINE__);
+	if (--layer->n_user == 0) {
+		vb2_queue_release(&layer->vb_queue);
+		/* TODO: move power off to timer thread */
+		mxr_power_put(mdev);
+	}
+	return 0;
+}
+
+static const struct v4l2_file_operations mxr_fops = {
+	.owner = THIS_MODULE,
+	.open = mxr_video_open,
+	.poll = mxr_video_poll,
+	.mmap = mxr_video_mmap,
+	.release = mxr_video_release,
+	.unlocked_ioctl = video_ioctl2,
+};
+
+static unsigned int divup(unsigned int divident, unsigned int divisor)
+{
+	return (divident + divisor - 1) / divisor;
+}
+
+unsigned long mxr_get_plane_size(const struct mxr_block *blk,
+	unsigned int width, unsigned int height)
+{
+	unsigned int blWidth = divup(width, blk->pxWidth);
+	unsigned int blHeight = divup(height, blk->pxHeight);
+	return PAGE_ALIGN(blWidth * blHeight * blk->bSize);
+}
+
+static int queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
+	unsigned int *nplanes, unsigned long sizes[],
+	void *alloc_ctxs[])
+{
+	struct mxr_layer *layer = vb2_get_drv_priv(vq);
+	const struct mxr_format *fmt = layer->fmt;
+	int i;
+	struct mxr_device *mdev = layer->mdev;
+	dev_info(mdev->dev, "%s\n", __func__);
+	/* checking if format was configured */
+	if (fmt == NULL)
+		return -EINVAL;
+	dev_info(mdev->dev, "fmt = %s\n", fmt->name);
+
+	*nplanes = fmt->num_subframes;
+	for (i = 0; i < fmt->num_subframes; ++i) {
+		alloc_ctxs[i] = layer->mdev->alloc_ctx;
+		sizes[i] = 0;
+	}
+
+	for (i = 0; i < fmt->num_planes; ++i) {
+		int frame_idx = fmt->plane2subframe[i];
+		const struct mxr_block *blk = &fmt->plane[frame_idx];
+		sizes[frame_idx] += mxr_get_plane_size(blk,
+			layer->geo.src.full_width, layer->geo.src.full_height);
+	}
+	for (i = 0; i < fmt->num_subframes; ++i)
+		dev_info(mdev->dev, "size[%d] = %08lx\n", i, sizes[i]);
+
+	if (*nbuffers == 0)
+		*nbuffers = 1;
+
+	return 0;
+}
+
+static void buf_queue(struct vb2_buffer *vb)
+{
+	struct mxr_buffer *buffer = container_of(vb, struct mxr_buffer, vb);
+	struct mxr_layer *layer = vb2_get_drv_priv(vb->vb2_queue);
+	struct mxr_device *mdev = layer->mdev;
+	unsigned long flags;
+	int must_start = 0;
+
+	spin_lock_irqsave(&layer->enq_slock, flags);
+	if (layer->state == MXR_LAYER_STREAMING_START) {
+		layer->state = MXR_LAYER_STREAMING;
+		must_start = 1;
+	}
+	list_add_tail(&buffer->list, &layer->enq_list);
+	spin_unlock_irqrestore(&layer->enq_slock, flags);
+	if (must_start) {
+		layer->ops.stream_set(layer, MXR_ENABLE);
+		mxr_streamer_get(mdev);
+	}
+
+	dev_info(mdev->dev, "queuing buffer\n");
+}
+
+static void wait_lock(struct vb2_queue *vq)
+{
+	struct mxr_layer *layer = vb2_get_drv_priv(vq);
+	struct mxr_device *mdev = layer->mdev;
+	dev_info(mdev->dev, "%s\n", __func__);
+	mutex_lock(&layer->mutex);
+}
+
+static void wait_unlock(struct vb2_queue *vq)
+{
+	struct mxr_layer *layer = vb2_get_drv_priv(vq);
+	struct mxr_device *mdev = layer->mdev;
+	dev_info(mdev->dev, "%s\n", __func__);
+	mutex_unlock(&layer->mutex);
+}
+
+static int start_streaming(struct vb2_queue *vq)
+{
+	struct mxr_layer *layer = vb2_get_drv_priv(vq);
+	struct mxr_device *mdev = layer->mdev;
+	unsigned long flags;
+
+	dev_info(mdev->dev, "%s\n", __func__);
+	/* block any changes in output configuration */
+	mxr_output_get(mdev);
+
+	/* update layers geometry */
+	mxr_layer_geo_fix(layer);
+	mxr_geometry_dump(mdev->dev, &layer->geo);
+
+	layer->ops.format_set(layer);
+	/* enabling layer in hardware */
+	spin_lock_irqsave(&layer->enq_slock, flags);
+	layer->state = MXR_LAYER_STREAMING_START;
+	spin_unlock_irqrestore(&layer->enq_slock, flags);
+
+	return 0;
+}
+
+static int stop_streaming(struct vb2_queue *vq)
+{
+	struct mxr_layer *layer = vb2_get_drv_priv(vq);
+	struct mxr_device *mdev = layer->mdev;
+	unsigned long flags;
+
+	dev_info(mdev->dev, "%s\n", __func__);
+
+	spin_lock_irqsave(&layer->enq_slock, flags);
+
+	/* reset list */
+	layer->state = MXR_LAYER_STREAMING_FINISH;
+
+	/* set all buffer to be done */
+	/* TODO: try to use for...safe macro */
+	while (!list_empty(&layer->enq_list)) {
+		struct mxr_buffer *buf;
+		buf = list_first_entry(&layer->enq_list,
+			struct mxr_buffer, list);
+		list_del(&buf->list);
+		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+	}
+
+	spin_unlock_irqrestore(&layer->enq_slock, flags);
+
+	/* wait until all buffers are goes to done state */
+	vb2_wait_for_all_buffers(vq);
+
+	/* stopping hardware */
+	spin_lock_irqsave(&layer->enq_slock, flags);
+	layer->state = MXR_LAYER_IDLE;
+	spin_unlock_irqrestore(&layer->enq_slock, flags);
+
+	/* disabling layer in hardware */
+	layer->ops.stream_set(layer, MXR_DISABLE);
+	/* remove one streamer */
+	mxr_streamer_put(mdev);
+	/* allow changes in output configuration */
+	mxr_output_put(mdev);
+	return 0;
+}
+
+static struct vb2_ops mxr_video_qops = {
+	.queue_setup = queue_setup,
+	.buf_queue = buf_queue,
+	.wait_prepare = wait_unlock,
+	.wait_finish = wait_lock,
+	.start_streaming = start_streaming,
+	.stop_streaming = stop_streaming,
+};
+
+/* FIXME: itry to put this functions to mxr_base_layer_create */
+int mxr_base_layer_register(struct mxr_layer *layer)
+{
+	struct device *dev = layer->mdev->dev;
+	int ret;
+	ret = video_register_device(&layer->vfd, VFL_TYPE_GRABBER, -1);
+	if (ret)
+		dev_err(dev, "failed to register video device\n");
+	else
+		dev_info(dev, "registered layer %s as /dev/video%d\n",
+			layer->vfd.name, layer->vfd.num);
+	return ret;
+}
+
+void mxr_base_layer_unregister(struct mxr_layer *layer)
+{
+	video_unregister_device(&layer->vfd);
+}
+
+void mxr_layer_release(struct mxr_layer *layer)
+{
+	if (layer->ops.release)
+		layer->ops.release(layer);
+}
+
+void mxr_base_layer_release(struct mxr_layer *layer)
+{
+	kfree(layer);
+}
+
+static void mxr_vfd_release(struct video_device *vdev)
+{
+	printk(KERN_INFO "video device release\n");
+}
+
+struct mxr_layer *mxr_base_layer_create(struct mxr_device *mdev,
+	int idx, char *name, struct mxr_layer_ops *ops)
+{
+	struct device *dev = mdev->dev;
+	struct mxr_layer *layer;
+
+	layer = kzalloc(sizeof *layer, GFP_KERNEL);
+	if (layer == NULL) {
+		dev_err(dev, "not enough memory for layer.\n");
+		goto fail;
+	}
+
+	layer->mdev = mdev;
+	layer->idx = idx;
+	layer->ops = *ops;
+
+	spin_lock_init(&layer->enq_slock);
+	INIT_LIST_HEAD(&layer->enq_list);
+	mutex_init(&layer->mutex);
+
+	layer->vfd = (struct video_device) {
+		.minor = -1,
+		.release = mxr_vfd_release,
+		.fops = &mxr_fops,
+		.ioctl_ops = &mxr_ioctl_ops,
+	};
+	strlcpy(layer->vfd.name, name, sizeof(layer->vfd.name));
+
+	video_set_drvdata(&layer->vfd, layer);
+	layer->vfd.lock = &layer->mutex;
+	layer->vfd.v4l2_dev = &mdev->v4l2_dev;
+
+	layer->vb_queue = (struct vb2_queue) {
+		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.io_modes = VB2_MMAP | VB2_USERPTR,
+		.drv_priv = layer,
+		.buf_struct_size = sizeof(struct mxr_buffer),
+		.ops = &mxr_video_qops,
+		.mem_ops = &vb2_cma_memops,
+	};
+
+	return layer;
+
+fail:
+	return NULL;
+}
+
+static const struct mxr_format *find_format_by_fourcc(
+	struct mxr_layer *layer, unsigned long fourcc)
+{
+	int i;
+	for (i = 0; i < layer->fmt_array_size; ++i)
+		if (layer->fmt_array[i]->fourcc == fourcc)
+			return layer->fmt_array[i];
+	return NULL;
+}
+
+static const struct mxr_format *find_format_by_index(
+	struct mxr_layer *layer, unsigned long index)
+{
+	if (index >= layer->fmt_array_size)
+		return NULL;
+	return layer->fmt_array[index];
+}
+
diff --git a/drivers/media/video/s5p-tv/mixer_vp_layer.c b/drivers/media/video/s5p-tv/mixer_vp_layer.c
new file mode 100644
index 0000000..448c757
--- /dev/null
+++ b/drivers/media/video/s5p-tv/mixer_vp_layer.c
@@ -0,0 +1,202 @@
+/*
+ * Samsung TV Mixer driver
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ *
+ * Tomasz Stanislawski, t.stanislaws@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 Foundiation. either version 2 of the License,
+ * or (at your option) any later version
+ */
+
+#include "mixer.h"
+#include "mixer_reg.h"
+
+#include <media/videobuf2-cma.h>
+
+#include "regs-vp.h"
+
+
+/* FORMAT DEFINITIONS */
+static const struct mxr_format mxr_fmt_nv12 = {
+	.name = "NV12",
+	.fourcc = V4L2_PIX_FMT_NV12,
+	.num_planes = 2,
+	.plane = {
+		{ .pxWidth = 1, .pxHeight = 1, .bSize = 1 },
+		{ .pxWidth = 2, .pxHeight = 2, .bSize = 2 },
+	},
+	.num_subframes = 1,
+	.hwCode = VP_MODE_NV12 | VP_MODE_MEM_LINEAR,
+};
+
+static const struct mxr_format mxr_fmt_nv21 = {
+	.name = "NV21",
+	.fourcc = V4L2_PIX_FMT_NV21,
+	.num_planes = 2,
+	.plane = {
+		{ .pxWidth = 1, .pxHeight = 1, .bSize = 1 },
+		{ .pxWidth = 2, .pxHeight = 2, .bSize = 2 },
+	},
+	.num_subframes = 1,
+	.hwCode = VP_MODE_NV21 | VP_MODE_MEM_LINEAR,
+};
+
+static const struct mxr_format mxr_fmt_nv12m = {
+	.name = "NV12 (mplane)",
+	.fourcc = V4L2_PIX_FMT_NV12M,
+	.num_planes = 2,
+	.plane = {
+		{ .pxWidth = 1, .pxHeight = 1, .bSize = 1 },
+		{ .pxWidth = 2, .pxHeight = 2, .bSize = 2 },
+	},
+	.num_subframes = 2,
+	.plane2subframe = {0, 1},
+	.hwCode = VP_MODE_NV12 | VP_MODE_MEM_LINEAR,
+};
+
+static const struct mxr_format mxr_fmt_nv12mt = {
+	.name = "NV12 tiled (mplane)",
+	.fourcc = V4L2_PIX_FMT_NV12MT,
+	.num_planes = 2,
+	.plane = {
+		{ .pxWidth = 128, .pxHeight = 32, .bSize = 4096 },
+		{ .pxWidth = 128, .pxHeight = 32, .bSize = 2048 },
+	},
+	.num_subframes = 2,
+	.plane2subframe = {0, 1},
+	.hwCode = VP_MODE_NV12 | VP_MODE_MEM_TILED,
+};
+
+static const struct mxr_format *mxr_video_format[] = {
+	&mxr_fmt_nv12,
+	&mxr_fmt_nv21,
+	&mxr_fmt_nv12m,
+	&mxr_fmt_nv12mt,
+};
+
+/* AUXILIARY CALLBACKS */
+
+static void mxr_vp_layer_release(struct mxr_layer *layer)
+{
+	mxr_base_layer_unregister(layer);
+	mxr_base_layer_release(layer);
+}
+
+static void mxr_vp_buffer_set(struct mxr_layer *layer,
+	struct mxr_buffer *buf)
+{
+	dma_addr_t luma_addr, chroma_addr;
+	if (buf == NULL) {
+		mxr_reg_vp_buffer(layer->mdev, 0, 0);
+		return;
+	}
+	luma_addr = vb2_cma_plane_paddr(&buf->vb, 0);
+	if (layer->fmt->num_subframes == 2) {
+		chroma_addr = vb2_cma_plane_paddr(&buf->vb, 1);
+	} else {
+		/* FIXME: mxr_get_plane_size compute integer division,
+		 * which is slow and should not be performed in interrupt */
+		chroma_addr = luma_addr + mxr_get_plane_size(
+			&layer->fmt->plane[0], layer->geo.src.full_width,
+			layer->geo.src.full_height);
+	}
+	/*if (layer->fmt->hwCode & MXR_MODE_TILED)
+		chroma_addr += 0x40;*/
+	mxr_reg_vp_buffer(layer->mdev, luma_addr, chroma_addr);
+}
+
+static void mxr_vp_stream_set(struct mxr_layer *layer, int en)
+{
+	mxr_reg_vp_layer_stream(layer->mdev, en);
+}
+
+static void mxr_vp_format_set(struct mxr_layer *layer)
+{
+	mxr_reg_vp_format(layer->mdev, layer->fmt, &layer->geo);
+}
+
+static void mxr_vp_fix_geometry(struct mxr_layer *layer)
+{
+	struct mxr_geometry *geo = &layer->geo;
+	/* align horizontal size to 8 pixels */
+	geo->src.full_width = ALIGN(geo->src.full_width, 8);
+	/* limit to boundary size */
+	geo->src.full_width = clamp_val(geo->src.full_width, 8, 8192);
+	geo->src.full_height = clamp_val(geo->src.full_height, 1, 8192);
+	geo->src.width = clamp_val(geo->src.width, 32, geo->src.full_width);
+	geo->src.width = min(geo->src.width, 2047U);
+	geo->src.height = clamp_val(geo->src.height, 4, geo->src.full_height);
+	geo->src.height = min(geo->src.height, 2047U);
+
+	/* setting size of output window */
+	geo->dst.width = clamp_val(geo->dst.width, 8, geo->dst.full_width);
+	geo->dst.height = clamp_val(geo->dst.height, 1, geo->dst.full_height);
+
+	/* ensure that scaling is in range 1/4x to 16x */
+	if (geo->src.width >= 4 * geo->dst.width)
+		geo->src.width = 4 * geo->dst.width;
+	if (geo->dst.width >= 16 * geo->src.width)
+		geo->dst.width = 16 * geo->src.width;
+	if (geo->src.height >= 4 * geo->dst.height)
+		geo->src.height = 4 * geo->dst.height;
+	if (geo->dst.height >= 16 * geo->src.height)
+		geo->dst.height = 16 * geo->src.height;
+
+	/* setting scaling ratio */
+	geo->x_ratio = (geo->src.width << 16) / geo->dst.width;
+	geo->y_ratio = (geo->src.height << 16) / geo->dst.height;
+
+	/* adjust offsets */
+	geo->src.x_offset = min(geo->src.x_offset,
+		geo->src.full_width - geo->src.width);
+	geo->src.y_offset = min(geo->src.y_offset,
+		geo->src.full_height - geo->src.height);
+	geo->dst.x_offset = min(geo->dst.x_offset,
+		geo->dst.full_width - geo->dst.width);
+	geo->dst.y_offset = min(geo->dst.y_offset,
+		geo->dst.full_height - geo->dst.height);
+}
+
+/* PUBLIC API */
+
+struct mxr_layer *mxr_vp_layer_create(struct mxr_device *mdev, int idx)
+{
+	struct mxr_layer *layer;
+	struct device *dev = mdev->dev;
+	int ret;
+	struct mxr_layer_ops ops = {
+		.release = mxr_vp_layer_release,
+		.buffer_set = mxr_vp_buffer_set,
+		.stream_set = mxr_vp_stream_set,
+		.format_set = mxr_vp_format_set,
+		.fix_geometry = mxr_vp_fix_geometry,
+	};
+	char name[32];
+
+	sprintf(name, "video%d", idx);
+
+	layer = mxr_base_layer_create(mdev, idx, name, &ops);
+	if (layer == NULL) {
+		dev_err(dev, "failed to initialize layer(%d) base\n", idx);
+		goto fail;
+	}
+
+	layer->fmt_array = mxr_video_format;
+	layer->fmt_array_size = ARRAY_SIZE(mxr_video_format);
+
+	ret = mxr_base_layer_register(layer);
+	if (ret)
+		goto fail_layer;
+
+	return layer;
+
+fail_layer:
+	mxr_base_layer_release(layer);
+
+fail:
+	return NULL;
+}
+
diff --git a/drivers/media/video/s5p-tv/regs-hdmi.h b/drivers/media/video/s5p-tv/regs-hdmi.h
new file mode 100644
index 0000000..2b6daf6
--- /dev/null
+++ b/drivers/media/video/s5p-tv/regs-hdmi.h
@@ -0,0 +1,1849 @@
+/* linux/arch/arm/mach-s5pv310/include/mach/regs-hdmi.h
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ * http://www.samsung.com/
+ *
+ * HDMI register header file for Samsung TVOUT driver
+ *
+ * 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 __ASM_ARCH_REGS_HDMI_H
+
+/*
+ * Register part
+*/
+#define HDMI_CTRL_BASE(x)			(x)
+#define HDMI_BASE(x)				((x) + 0x00010000)
+#define HDMI_SPDIF_BASE(x)			((x) + 0x00030000)
+#define HDMI_I2S_BASE(x)			((x) + 0x00040000)
+#define HDMI_TG_BASE(x)				((x) + 0x00050000)
+#define HDMI_EFUSE_BASE(x)			((x) + 0x00060000)
+
+
+/* Interrupt Control Register */
+#define HDMI_INTC_CON			HDMI_CTRL_BASE(0x0000)
+/* Interrupt Flag Register */
+#define HDMI_INTC_FLAG			HDMI_CTRL_BASE(0x0004)
+/* HDCP KEY Status */
+#define HDMI_HDCP_KEY_LOAD			HDMI_CTRL_BASE(0x0008)
+/* HPD signal */
+#define HDMI_HPD_STATUS			HDMI_CTRL_BASE(0x000C)
+/* Audio system clock selection */
+#define HDMI_AUDIO_CLKSEL			HDMI_CTRL_BASE(0x0010)
+/* HDMI PHY Reset Out */
+#define HDMI_PHY_RSTOUT			HDMI_CTRL_BASE(0x0014)
+/* HDMI PHY VPLL Monitor */
+#define HDMI_PHY_VPLL			HDMI_CTRL_BASE(0x0018)
+/* HDMI PHY CMU Monitor */
+#define HDMI_PHY_CMU			HDMI_CTRL_BASE(0x001C)
+/* HDMI TX Core S/W reset */
+#define HDMI_CORE_RSTOUT			HDMI_CTRL_BASE(0x0020)
+
+/* HDMI System Control Register 0 0x00 */
+#define HDMI_CON_0				HDMI_BASE(0x0000)
+/* HDMI System Control Register 1 0x00 */
+#define HDMI_CON_1				HDMI_BASE(0x0004)
+/* HDMI System Control Register 2. 0x00 */
+#define HDMI_CON_2				HDMI_BASE(0x0008)
+/* HDMI System Status Register 0x00 */
+#define HDMI_SYS_STATUS			HDMI_BASE(0x0010)
+/* HDMI Phy Status */
+#define HDMI_PHY_STATUS			HDMI_BASE(0x0014)
+/* HDMI System Status Enable Register 0x00 */
+#define HDMI_STATUS_EN			HDMI_BASE(0x0020)
+/* Hot Plug Detection Control Register 0x00 */
+#define HDMI_HPD				HDMI_BASE(0x0030)
+/* HDMI/DVI Mode Selection 0x00 */
+#define HDMI_MODE_SEL			HDMI_BASE(0x0040)
+/* HDCP Encryption Enable Register 0x00 */
+#define HDMI_ENC_EN				HDMI_BASE(0x0044)
+
+/* Pixel Values for Blue Screen 0x00 */
+#define HDMI_BLUE_SCREEN_0			HDMI_BASE(0x0050)
+/* Pixel Values for Blue Screen 0x00 */
+#define HDMI_BLUE_SCREEN_1			HDMI_BASE(0x0054)
+/* Pixel Values for Blue Screen 0x00 */
+#define HDMI_BLUE_SCREEN_2			HDMI_BASE(0x0058)
+
+/* Maximum Y (or R,G,B) Pixel Value 0xEB */
+#define HDMI_YMAX				HDMI_BASE(0x0060)
+/* Minimum Y (or R,G,B) Pixel Value 0x10 */
+#define HDMI_YMIN				HDMI_BASE(0x0064)
+/* Maximum Cb/ Cr Pixel Value 0xF0 */
+#define HDMI_CMAX				HDMI_BASE(0x0068)
+/* Minimum Cb/ Cr Pixel Value 0x10 */
+#define HDMI_CMIN				HDMI_BASE(0x006C)
+
+/* Horizontal Blanking Setting 0x00 */
+#define HDMI_H_BLANK_0			HDMI_BASE(0x00A0)
+/* Horizontal Blanking Setting 0x00 */
+#define HDMI_H_BLANK_1			HDMI_BASE(0x00A4)
+/* Vertical Blanking Setting 0x00 */
+#define HDMI_V_BLANK_0			HDMI_BASE(0x00B0)
+/* Vertical Blanking Setting 0x00 */
+#define HDMI_V_BLANK_1			HDMI_BASE(0x00B4)
+/* Vertical Blanking Setting 0x00 */
+#define HDMI_V_BLANK_2			HDMI_BASE(0x00B8)
+/* Hori. Line and Ver. Line 0x00 */
+#define HDMI_H_V_LINE_0			HDMI_BASE(0x00C0)
+/* Hori. Line and Ver. Line 0x00 */
+#define HDMI_H_V_LINE_1			HDMI_BASE(0x00C4)
+/* Hori. Line and Ver. Line 0x00 */
+#define HDMI_H_V_LINE_2			HDMI_BASE(0x00C8)
+
+/* Vertical Sync Polarity Control Register 0x00 */
+#define HDMI_SYNC_MODE			HDMI_BASE(0x00E4)
+/* Vertical Sync Polarity Control Register 0x00 */
+#define HDMI_VSYNC_POL			HDMI_BASE(0x00E4)
+/* Interlace/ Progressive Control Register 0x00 */
+#define HDMI_INT_PRO_MODE			HDMI_BASE(0x00E8)
+
+/* Vertical Blanking Setting for Bottom Field 0x00 */
+#define HDMI_V_BLANK_F_0			HDMI_BASE(0x0110)
+/* Vertical Blanking Setting for Bottom Field 0x00 */
+#define HDMI_V_BLANK_F_1			HDMI_BASE(0x0114)
+/* Vertical Blanking Setting for Bottom Field 0x00 */
+#define HDMI_V_BLANK_F_2			HDMI_BASE(0x0118)
+/* Horizontal Sync Generation Setting 0x00 */
+#define HDMI_H_SYNC_GEN_0			HDMI_BASE(0x0120)
+/* Horizontal Sync Generation Setting 0x00 */
+#define HDMI_H_SYNC_GEN_1			HDMI_BASE(0x0124)
+/* Horizontal Sync Generation Setting 0x00 */
+#define HDMI_H_SYNC_GEN_2			HDMI_BASE(0x0128)
+/* Vertical Sync Generation for Top Field or Frame. 0x01 */
+#define HDMI_V_SYNC_GEN_1_0			HDMI_BASE(0x0130)
+/* Vertical Sync Generation for Top Field or Frame. 0x10 */
+#define HDMI_V_SYNC_GEN_1_1			HDMI_BASE(0x0134)
+/* Vertical Sync Generation for Top Field or Frame. 0x00 */
+#define HDMI_V_SYNC_GEN_1_2			HDMI_BASE(0x0138)
+/* Vertical Sync Generation for Bottom field ? Vertical position. 0x01 */
+#define HDMI_V_SYNC_GEN_2_0			HDMI_BASE(0x0140)
+/* Vertical Sync Generation for Bottom field ? Vertical position. 0x10 */
+#define HDMI_V_SYNC_GEN_2_1			HDMI_BASE(0x0144)
+/* Vertical Sync Generation for Bottom field ? Vertical position. 0x00 */
+#define HDMI_V_SYNC_GEN_2_2			HDMI_BASE(0x0148)
+/* Vertical Sync Generation for Bottom field ? Horizontal position. 0x01 */
+#define HDMI_V_SYNC_GEN_3_0			HDMI_BASE(0x0150)
+/* Vertical Sync Generation for Bottom field ? Horizontal position. 0x10 */
+#define HDMI_V_SYNC_GEN_3_1			HDMI_BASE(0x0154)
+/* Vertical Sync Generation for Bottom field ? Horizontal position. 0x00 */
+#define HDMI_V_SYNC_GEN_3_2			HDMI_BASE(0x0158)
+
+/* ASP Packet Control Register 0x00 */
+#define HDMI_ASP_CON			HDMI_BASE(0x0160)
+/* ASP Packet sp_flat Bit Control 0x00 */
+#define HDMI_ASP_SP_FLAT			HDMI_BASE(0x0164)
+/* ASP Audio Channel Configuration 0x04 */
+#define HDMI_ASP_CHCFG0			HDMI_BASE(0x0170)
+/* ASP Audio Channel Configuration 0x1A */
+#define HDMI_ASP_CHCFG1			HDMI_BASE(0x0174)
+/* ASP Audio Channel Configuration 0x2C */
+#define HDMI_ASP_CHCFG2			HDMI_BASE(0x0178)
+/* ASP Audio Channel Configuration 0x3E */
+#define HDMI_ASP_CHCFG3			HDMI_BASE(0x017C)
+
+/* ACR Packet Control Register 0x00 */
+#define HDMI_ACR_CON			HDMI_BASE(0x0180)
+/* Measured CTS Value 0x01 */
+#define HDMI_ACR_MCTS0			HDMI_BASE(0x0184)
+/* Measured CTS Value 0x00 */
+#define HDMI_ACR_MCTS1			HDMI_BASE(0x0188)
+/* Measured CTS Value 0x00 */
+#define HDMI_ACR_MCTS2			HDMI_BASE(0x018C)
+/* CTS Value for Fixed CTS Transmission Mode. 0xE8 */
+#define HDMI_ACR_CTS0			HDMI_BASE(0x0190)
+/* CTS Value for Fixed CTS Transmission Mode. 0x03 */
+#define HDMI_ACR_CTS1			HDMI_BASE(0x0194)
+/* CTS Value for Fixed CTS Transmission Mode. 0x00 */
+#define HDMI_ACR_CTS2			HDMI_BASE(0x0198)
+/* N Value for ACR Packet. 0xE8 */
+#define HDMI_ACR_N0				HDMI_BASE(0x01A0)
+/* N Value for ACR Packet. 0x03 */
+#define HDMI_ACR_N1				HDMI_BASE(0x01A4)
+/* N Value for ACR Packet. 0x00 */
+#define HDMI_ACR_N2				HDMI_BASE(0x01A8)
+/* Altenate LSB for Fixed CTS Transmission Mode 0x00 */
+#define HDMI_ACR_LSB2			HDMI_BASE(0x01B0)
+/* Number of ACR Packet Transmission per frame 0x1F */
+#define HDMI_ACR_TXCNT			HDMI_BASE(0x01B4)
+/* Interval for ACR Packet Transmission 0x63 */
+#define HDMI_ACR_TXINTERVAL			HDMI_BASE(0x01B8)
+/* CTS Offset for Measured CTS mode. 0x00 */
+#define HDMI_ACR_CTS_OFFSET			HDMI_BASE(0x01BC)
+
+/* ACR Packet Control register 0x00 */
+#define HDMI_GCP_CON			HDMI_BASE(0x01C0)
+/* GCP Packet Body 0x00 */
+#define HDMI_GCP_BYTE1			HDMI_BASE(0x01D0)
+/* GCP Packet Body 0x01 */
+#define HDMI_GCP_BYTE2			HDMI_BASE(0x01D4)
+/* GCP Packet Body 0x02 */
+#define HDMI_GCP_BYTE3			HDMI_BASE(0x01D8)
+
+/* ACP Packet Control register 0x00 */
+#define HDMI_ACP_CON			HDMI_BASE(0x01E0)
+/* ACP Packet Header 0x00 */
+#define HDMI_ACP_TYPE			HDMI_BASE(0x01E4)
+
+/* ACP Packet Body 0x00 */
+#define HDMI_ACP_DATA0			HDMI_BASE(0x0200)
+/* ACP Packet Body 0x00 */
+#define HDMI_ACP_DATA1			HDMI_BASE(0x0204)
+/* ACP Packet Body 0x00 */
+#define HDMI_ACP_DATA2			HDMI_BASE(0x0208)
+/* ACP Packet Body 0x00 */
+#define HDMI_ACP_DATA3			HDMI_BASE(0x020c)
+/* ACP Packet Body 0x00 */
+#define HDMI_ACP_DATA4			HDMI_BASE(0x0210)
+/* ACP Packet Body 0x00 */
+#define HDMI_ACP_DATA5			HDMI_BASE(0x0214)
+/* ACP Packet Body 0x00 */
+#define HDMI_ACP_DATA6			HDMI_BASE(0x0218)
+/* ACP Packet Body 0x00 */
+#define HDMI_ACP_DATA7			HDMI_BASE(0x021c)
+/* ACP Packet Body 0x00 */
+#define HDMI_ACP_DATA8			HDMI_BASE(0x0220)
+/* ACP Packet Body 0x00 */
+#define HDMI_ACP_DATA9			HDMI_BASE(0x0224)
+/* ACP Packet Body 0x00 */
+#define HDMI_ACP_DATA10			HDMI_BASE(0x0228)
+/* ACP Packet Body 0x00 */
+#define HDMI_ACP_DATA11			HDMI_BASE(0x022c)
+/* ACP Packet Body 0x00 */
+#define HDMI_ACP_DATA12			HDMI_BASE(0x0230)
+/* ACP Packet Body 0x00 */
+#define HDMI_ACP_DATA13			HDMI_BASE(0x0234)
+/* ACP Packet Body 0x00 */
+#define HDMI_ACP_DATA14			HDMI_BASE(0x0238)
+/* ACP Packet Body 0x00 */
+#define HDMI_ACP_DATA15			HDMI_BASE(0x023c)
+/* ACP Packet Body 0x00 */
+#define HDMI_ACP_DATA16			HDMI_BASE(0x0240)
+
+/* ACR Packet Control Register 0x00 */
+#define HDMI_ISRC_CON			HDMI_BASE(0x0250)
+/* ISCR1 Packet Header 0x00 */
+#define HDMI_ISRC1_HEADER1			HDMI_BASE(0x0264)
+
+/* ISRC1 Packet Body 0x00 */
+#define HDMI_ISRC1_DATA0			HDMI_BASE(0x0270)
+/* ISRC1 Packet Body 0x00 */
+#define HDMI_ISRC1_DATA1			HDMI_BASE(0x0274)
+/* ISRC1 Packet Body 0x00 */
+#define HDMI_ISRC1_DATA2			HDMI_BASE(0x0278)
+/* ISRC1 Packet Body 0x00 */
+#define HDMI_ISRC1_DATA3			HDMI_BASE(0x027c)
+/* ISRC1 Packet Body 0x00 */
+#define HDMI_ISRC1_DATA4			HDMI_BASE(0x0280)
+/* ISRC1 Packet Body 0x00 */
+#define HDMI_ISRC1_DATA5			HDMI_BASE(0x0284)
+/* ISRC1 Packet Body 0x00 */
+#define HDMI_ISRC1_DATA6			HDMI_BASE(0x0288)
+/* ISRC1 Packet Body 0x00 */
+#define HDMI_ISRC1_DATA7			HDMI_BASE(0x028c)
+/* ISRC1 Packet Body 0x00 */
+#define HDMI_ISRC1_DATA8			HDMI_BASE(0x0290)
+/* ISRC1 Packet Body 0x00 */
+#define HDMI_ISRC1_DATA9			HDMI_BASE(0x0294)
+/* ISRC1 Packet Body 0x00 */
+#define HDMI_ISRC1_DATA10			HDMI_BASE(0x0298)
+/* ISRC1 Packet Body 0x00 */
+#define HDMI_ISRC1_DATA11			HDMI_BASE(0x029c)
+/* ISRC1 Packet Body 0x00 */
+#define HDMI_ISRC1_DATA12			HDMI_BASE(0x02a0)
+/* ISRC1 Packet Body 0x00 */
+#define HDMI_ISRC1_DATA13			HDMI_BASE(0x02a4)
+/* ISRC1 Packet Body 0x00 */
+#define HDMI_ISRC1_DATA14			HDMI_BASE(0x02a8)
+/* ISRC1 Packet Body 0x00 */
+#define HDMI_ISRC1_DATA15			HDMI_BASE(0x02ac)
+
+/* ISRC2 Packet Body 0x00 */
+#define HDMI_ISRC2_DATA0			HDMI_BASE(0x02b0)
+/* ISRC2 Packet Body 0x00 */
+#define HDMI_ISRC2_DATA1			HDMI_BASE(0x02b4)
+/* ISRC2 Packet Body 0x00 */
+#define HDMI_ISRC2_DATA2			HDMI_BASE(0x02b8)
+/* ISRC2 Packet Body 0x00 */
+#define HDMI_ISRC2_DATA3			HDMI_BASE(0x02bc)
+/* ISRC2 Packet Body 0x00 */
+#define HDMI_ISRC2_DATA4			HDMI_BASE(0x02c0)
+/* ISRC2 Packet Body 0x00 */
+#define HDMI_ISRC2_DATA5			HDMI_BASE(0x02c4)
+/* ISRC2 Packet Body 0x00 */
+#define HDMI_ISRC2_DATA6			HDMI_BASE(0x02c8)
+/* ISRC2 Packet Body 0x00 */
+#define HDMI_ISRC2_DATA7			HDMI_BASE(0x02cc)
+/* ISRC2 Packet Body 0x00 */
+#define HDMI_ISRC2_DATA8			HDMI_BASE(0x02d0)
+/* ISRC2 Packet Body 0x00 */
+#define HDMI_ISRC2_DATA9			HDMI_BASE(0x02d4)
+/* ISRC2 Packet Body 0x00 */
+#define HDMI_ISRC2_DATA10			HDMI_BASE(0x02d8)
+/* ISRC2 Packet Body 0x00 */
+#define HDMI_ISRC2_DATA11			HDMI_BASE(0x02dc)
+/* ISRC2 Packet Body 0x00 */
+#define HDMI_ISRC2_DATA12			HDMI_BASE(0x02e0)
+/* ISRC2 Packet Body 0x00 */
+#define HDMI_ISRC2_DATA13			HDMI_BASE(0x02e4)
+/* ISRC2 Packet Body 0x00 */
+#define HDMI_ISRC2_DATA14			HDMI_BASE(0x02e8)
+/* ISRC2 Packet Body 0x00 */
+#define HDMI_ISRC2_DATA15			HDMI_BASE(0x02ec)
+
+/* AVI Packet Control Register 0x00 */
+#define HDMI_AVI_CON			HDMI_BASE(0x0300)
+/* AVI Packet Checksum 0x00 */
+#define HDMI_AVI_CHECK_SUM			HDMI_BASE(0x0310)
+
+/* AVI Packet Body 0x00 */
+#define HDMI_AVI_BYTE1			HDMI_BASE(0x0320)
+/* AVI Packet Body 0x00 */
+#define HDMI_AVI_BYTE2			HDMI_BASE(0x0324)
+/* AVI Packet Body 0x00 */
+#define HDMI_AVI_BYTE3			HDMI_BASE(0x0328)
+/* AVI Packet Body 0x00 */
+#define HDMI_AVI_BYTE4			HDMI_BASE(0x032c)
+/* AVI Packet Body 0x00 */
+#define HDMI_AVI_BYTE5			HDMI_BASE(0x0330)
+/* AVI Packet Body 0x00 */
+#define HDMI_AVI_BYTE6			HDMI_BASE(0x0334)
+/* AVI Packet Body 0x00 */
+#define HDMI_AVI_BYTE7			HDMI_BASE(0x0338)
+/* AVI Packet Body 0x00 */
+#define HDMI_AVI_BYTE8			HDMI_BASE(0x033c)
+/* AVI Packet Body 0x00 */
+#define HDMI_AVI_BYTE9			HDMI_BASE(0x0340)
+/* AVI Packet Body 0x00 */
+#define HDMI_AVI_BYTE10			HDMI_BASE(0x0344)
+/* AVI Packet Body 0x00 */
+#define HDMI_AVI_BYTE11			HDMI_BASE(0x0348)
+/* AVI Packet Body 0x00 */
+#define HDMI_AVI_BYTE12			HDMI_BASE(0x034c)
+/* AVI Packet Body 0x00  */
+#define HDMI_AVI_BYTE13			HDMI_BASE(0x0350)
+
+/* AUI Packet Control Register 0x00 */
+#define HDMI_AUI_CON			HDMI_BASE(0x0360)
+/* AUI Packet Checksum 0x00 */
+#define HDMI_AUI_CHECK_SUM			HDMI_BASE(0x0370)
+
+/* AUI Packet Body 0x00 */
+#define HDMI_AUI_BYTE1			HDMI_BASE(0x0380)
+/* AUI Packet Body 0x00 */
+#define HDMI_AUI_BYTE2			HDMI_BASE(0x0384)
+/* AUI Packet Body 0x00 */
+#define HDMI_AUI_BYTE3			HDMI_BASE(0x0388)
+/* AUI Packet Body 0x00 */
+#define HDMI_AUI_BYTE4			HDMI_BASE(0x038c)
+/* AUI Packet Body 0x00 */
+#define HDMI_AUI_BYTE5			HDMI_BASE(0x0390)
+
+/* ACR Packet Control Register 0x00 */
+#define HDMI_MPG_CON			HDMI_BASE(0x03A0)
+/* MPG Packet Checksum 0x00 */
+#define HDMI_MPG_CHECK_SUM			HDMI_BASE(0x03B0)
+
+/* MPEG Packet Body 0x00 */
+#define HDMI_MPEG_BYTE1			HDMI_BASE(0x03c0)
+/* MPEG Packet Body 0x00 */
+#define HDMI_MPEG_BYTE2			HDMI_BASE(0x03c4)
+/* MPEG Packet Body 0x00 */
+#define HDMI_MPEG_BYTE3			HDMI_BASE(0x03c8)
+/* MPEG Packet Body 0x00 */
+#define HDMI_MPEG_BYTE4			HDMI_BASE(0x03cc)
+/* MPEG Packet Body 0x00 */
+#define HDMI_MPEG_BYTE5			HDMI_BASE(0x03d0)
+
+/* SPD Packet Control Register 0x00 */
+#define HDMI_SPD_CON			HDMI_BASE(0x0400)
+/* SPD Packet Header 0x00 */
+#define HDMI_SPD_HEADER0			HDMI_BASE(0x0410)
+/* SPD Packet Header 0x00 */
+#define HDMI_SPD_HEADER1			HDMI_BASE(0x0414)
+/* SPD Packet Header 0x00 */
+#define HDMI_SPD_HEADER2			HDMI_BASE(0x0418)
+
+/* SPD Packet Body 0x00 */
+#define HDMI_SPD_DATA0			HDMI_BASE(0x0420)
+/* SPD Packet Body 0x00 */
+#define HDMI_SPD_DATA1			HDMI_BASE(0x0424)
+/* SPD Packet Body 0x00 */
+#define HDMI_SPD_DATA2			HDMI_BASE(0x0428)
+/* SPD Packet Body 0x00 */
+#define HDMI_SPD_DATA3			HDMI_BASE(0x042c)
+/* SPD Packet Body 0x00 */
+#define HDMI_SPD_DATA4			HDMI_BASE(0x0430)
+/* SPD Packet Body 0x00 */
+#define HDMI_SPD_DATA5			HDMI_BASE(0x0434)
+/* SPD Packet Body 0x00 */
+#define HDMI_SPD_DATA6			HDMI_BASE(0x0438)
+/* SPD Packet Body 0x00 */
+#define HDMI_SPD_DATA7			HDMI_BASE(0x043c)
+/* SPD Packet Body 0x00 */
+#define HDMI_SPD_DATA8			HDMI_BASE(0x0440)
+/* SPD Packet Body 0x00 */
+#define HDMI_SPD_DATA9			HDMI_BASE(0x0444)
+/* SPD Packet Body 0x00 */
+#define HDMI_SPD_DATA10			HDMI_BASE(0x0448)
+/* SPD Packet Body 0x00 */
+#define HDMI_SPD_DATA11			HDMI_BASE(0x044c)
+/* SPD Packet Body 0x00 */
+#define HDMI_SPD_DATA12			HDMI_BASE(0x0450)
+/* SPD Packet Body 0x00 */
+#define HDMI_SPD_DATA13			HDMI_BASE(0x0454)
+/* SPD Packet Body 0x00 */
+#define HDMI_SPD_DATA14			HDMI_BASE(0x0458)
+/* SPD Packet Body 0x00 */
+#define HDMI_SPD_DATA15			HDMI_BASE(0x045c)
+/* SPD Packet Body 0x00 */
+#define HDMI_SPD_DATA16			HDMI_BASE(0x0460)
+/* SPD Packet Body 0x00 */
+#define HDMI_SPD_DATA17			HDMI_BASE(0x0464)
+/* SPD Packet Body 0x00 */
+#define HDMI_SPD_DATA18			HDMI_BASE(0x0468)
+/* SPD Packet Body 0x00 */
+#define HDMI_SPD_DATA19			HDMI_BASE(0x046c)
+/* SPD Packet Body 0x00 */
+#define HDMI_SPD_DATA20			HDMI_BASE(0x0470)
+/* SPD Packet Body 0x00 */
+#define HDMI_SPD_DATA21			HDMI_BASE(0x0474)
+/* SPD Packet Body 0x00 */
+#define HDMI_SPD_DATA22			HDMI_BASE(0x0478)
+/* SPD Packet Body 0x00 */
+#define HDMI_SPD_DATA23			HDMI_BASE(0x048c)
+/* SPD Packet Body 0x00 */
+#define HDMI_SPD_DATA24			HDMI_BASE(0x0480)
+/* SPD Packet Body 0x00 */
+#define HDMI_SPD_DATA25			HDMI_BASE(0x0484)
+/* SPD Packet Body 0x00 */
+#define HDMI_SPD_DATA26			HDMI_BASE(0x0488)
+/* SPD Packet Body 0x00 */
+#define HDMI_SPD_DATA27			HDMI_BASE(0x048c)
+
+/* SHA-1 Value from Repeater 0x00 */
+#define HDMI_HDCP_RX_SHA1_0_0		HDMI_BASE(0x0600)
+/* SHA-1 Value from Repeater 0x00 */
+#define HDMI_HDCP_RX_SHA1_0_1		HDMI_BASE(0x0604)
+/* SHA-1 value from Repeater 0x00 */
+#define HDMI_HDCP_RX_SHA1_0_2		HDMI_BASE(0x0608)
+/* SHA-1 value from Repeater 0x00 */
+#define HDMI_HDCP_RX_SHA1_0_3		HDMI_BASE(0x060C)
+/* SHA-1 value from Repeater 0x00 */
+#define HDMI_HDCP_RX_SHA1_1_0		HDMI_BASE(0x0610)
+/* SHA-1 value from Repeater 0x00 */
+#define HDMI_HDCP_RX_SHA1_1_1		HDMI_BASE(0x0614)
+/* SHA-1 value from Repeater 0x00 */
+#define HDMI_HDCP_RX_SHA1_1_2		HDMI_BASE(0x0618)
+/* SHA-1 value from Repeater 0x00 */
+#define HDMI_HDCP_RX_SHA1_1_3		HDMI_BASE(0x061C)
+/* SHA-1 value from Repeater 0x00 */
+#define HDMI_HDCP_RX_SHA1_2_0		HDMI_BASE(0x0620)
+/* SHA-1 value from Repeater 0x00 */
+#define HDMI_HDCP_RX_SHA1_2_1		HDMI_BASE(0x0624)
+/* SHA-1 value from Repeater 0x00 */
+#define HDMI_HDCP_RX_SHA1_2_2		HDMI_BASE(0x0628)
+/* SHA-1 value from Repeater 0x00 */
+#define HDMI_HDCP_RX_SHA1_2_3		HDMI_BASE(0x062C)
+/* SHA-1 value from Repeater 0x00 */
+#define HDMI_HDCP_RX_SHA1_3_0		HDMI_BASE(0x0630)
+/* SHA-1 value from Repeater 0x00 */
+#define HDMI_HDCP_RX_SHA1_3_1		HDMI_BASE(0x0634)
+/* SHA-1 value from Repeater 0x00 */
+#define HDMI_HDCP_RX_SHA1_3_2		HDMI_BASE(0x0638)
+/* SHA-1 value from Repeater 0x00 */
+#define HDMI_HDCP_RX_SHA1_3_3		HDMI_BASE(0x063C)
+/* SHA-1 value from Repeater 0x00 */
+#define HDMI_HDCP_RX_SHA1_4_0		HDMI_BASE(0x0640)
+/* SHA-1 value from Repeater 0x00 */
+#define HDMI_HDCP_RX_SHA1_4_1		HDMI_BASE(0x0644)
+/* SHA-1 value from Repeater 0x00 */
+#define HDMI_HDCP_RX_SHA1_4_2		HDMI_BASE(0x0648)
+/* SHA-1 value from Repeater 0x00 */
+#define HDMI_HDCP_RX_SHA1_4_3		HDMI_BASE(0x064C)
+
+/* Receiver KSV 0 0x00 */
+#define HDMI_HDCP_RX_KSV_0_0		HDMI_BASE(0x0650)
+/* Receiver KSV 0 0x00 */
+#define HDMI_HDCP_RX_KSV_0_1		HDMI_BASE(0x0654)
+/* Receiver KSV 0 0x00 */
+#define HDMI_HDCP_RX_KSV_0_2		HDMI_BASE(0x0658)
+/* Receiver KSV 0 0x00 */
+#define HDMI_HDCP_RX_KSV_0_3		HDMI_BASE(0x065C)
+/* Receiver KSV 1 0x00 */
+#define HDMI_HDCP_RX_KSV_0_4		HDMI_BASE(0x0660)
+
+/* Receiver KSV 1 0x00 */
+#define HDMI_HDCP_KSV_LIST_CON		HDMI_BASE(0x0664)
+/* 2nd authentication status 0x00 */
+#define HDMI_HDCP_SHA_RESULT		HDMI_BASE(0x0670)
+/* HDCP Control 0x00 */
+#define HDMI_HDCP_CTRL1			HDMI_BASE(0x0680)
+/* HDCP Control 0x00 */
+#define HDMI_HDCP_CTRL2			HDMI_BASE(0x0684)
+/* HDCP Ri, Pj, V result 0x00 */
+#define HDMI_HDCP_CHECK_RESULT		HDMI_BASE(0x0690)
+
+/* Receiver BKSV 0x00 */
+#define HDMI_HDCP_BKSV_0_0			HDMI_BASE(0x06A0)
+/* Receiver BKSV 0x00 */
+#define HDMI_HDCP_BKSV_0_1			HDMI_BASE(0x06A4)
+/* Receiver BKSV 0x00 */
+#define HDMI_HDCP_BKSV_0_2			HDMI_BASE(0x06A8)
+/* Receiver BKSV 0x00 */
+#define HDMI_HDCP_BKSV_0_3			HDMI_BASE(0x06AC)
+/* Receiver BKSV 0x00 */
+#define HDMI_HDCP_BKSV_1			HDMI_BASE(0x06B0)
+
+/* Transmitter AKSV 0x00 */
+#define HDMI_HDCP_AKSV_0_0			HDMI_BASE(0x06C0)
+/* Transmitter AKSV 0x00 */
+#define HDMI_HDCP_AKSV_0_1			HDMI_BASE(0x06C4)
+/* Transmitter AKSV 0x00 */
+#define HDMI_HDCP_AKSV_0_2			HDMI_BASE(0x06C8)
+/* Transmitter AKSV 0x00 */
+#define HDMI_HDCP_AKSV_0_3			HDMI_BASE(0x06CC)
+/* Transmitter AKSV 0x00 */
+#define HDMI_HDCP_AKSV_1			HDMI_BASE(0x06D0)
+
+/* Transmitter An 0x00 */
+#define HDMI_HDCP_An_0_0			HDMI_BASE(0x06E0)
+/* Transmitter An 0x00 */
+#define HDMI_HDCP_An_0_1			HDMI_BASE(0x06E4)
+/* Transmitter An 0x00 */
+#define HDMI_HDCP_An_0_2			HDMI_BASE(0x06E8)
+/* Transmitter An 0x00 */
+#define HDMI_HDCP_An_0_3			HDMI_BASE(0x06EC)
+/* Transmitter An 0x00 */
+#define HDMI_HDCP_An_1_0			HDMI_BASE(0x06F0)
+/* Transmitter An 0x00 */
+#define HDMI_HDCP_An_1_1			HDMI_BASE(0x06F4)
+/* Transmitter An 0x00 */
+#define HDMI_HDCP_An_1_2			HDMI_BASE(0x06F8)
+/* Transmitter An 0x00 */
+#define HDMI_HDCP_An_1_3			HDMI_BASE(0x06FC)
+
+/* Receiver BCAPS 0x00 */
+#define HDMI_HDCP_BCAPS			HDMI_BASE(0x0700)
+/* Receiver BSTATUS 0x00 */
+#define HDMI_HDCP_BSTATUS_0			HDMI_BASE(0x0710)
+/* Receiver BSTATUS 0x00 */
+#define HDMI_HDCP_BSTATUS_1			HDMI_BASE(0x0714)
+/* Transmitter Ri 0x00 */
+#define HDMI_HDCP_Ri_0			HDMI_BASE(0x0740)
+/* Transmitter Ri 0x00 */
+#define HDMI_HDCP_Ri_1			HDMI_BASE(0x0744)
+
+/* HDCP I2C interrupt status */
+#define HDMI_HDCP_I2C_INT			HDMI_BASE(0x0780)
+/* HDCP An interrupt status */
+#define HDMI_HDCP_AN_INT			HDMI_BASE(0x0790)
+/* HDCP Watchdog interrupt status */
+#define HDMI_HDCP_WDT_INT			HDMI_BASE(0x07a0)
+/* HDCP RI interrupt status */
+#define HDMI_HDCP_RI_INT			HDMI_BASE(0x07b0)
+
+/* HDCP Ri Interrupt Frame number index register 0 */
+#define HDMI_HDCP_RI_COMPARE_0		HDMI_BASE(0x07d0)
+/* HDCP Ri Interrupt Frame number index register 1 */
+#define HDMI_HDCP_RI_COMPARE_1		HDMI_BASE(0x07d4)
+/* Current value of the frame count index in the hardware */
+#define HDMI_HDCP_FRAME_COUNT		HDMI_BASE(0x07e0)
+
+/* Gamut Metadata packet transmission control register */
+#define HDMI_GAMUT_CON			HDMI_BASE(0x0500)
+/* Gamut metadata packet header */
+#define HDMI_GAMUT_HEADER0			HDMI_BASE(0x0504)
+/* Gamut metadata packet header */
+#define HDMI_GAMUT_HEADER1			HDMI_BASE(0x0508)
+/* Gamut metadata packet header */
+#define HDMI_GAMUT_HEADER2			HDMI_BASE(0x050c)
+/* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA00			HDMI_BASE(0x0510)
+/* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA01			HDMI_BASE(0x0514)
+/* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA02			HDMI_BASE(0x0518)
+/* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA03			HDMI_BASE(0x051c)
+/* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA04			HDMI_BASE(0x0520)
+/* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA05			HDMI_BASE(0x0524)
+/* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA06			HDMI_BASE(0x0528)
+/* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA07			HDMI_BASE(0x052c)
+/* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA08			HDMI_BASE(0x0530)
+/* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA09			HDMI_BASE(0x0534)
+/* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA10			HDMI_BASE(0x0538)
+/* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA11			HDMI_BASE(0x053c)
+/* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA12			HDMI_BASE(0x0540)
+/* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA13			HDMI_BASE(0x0544)
+/* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA14			HDMI_BASE(0x0548)
+/* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA15			HDMI_BASE(0x054c)
+/* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA16			HDMI_BASE(0x0550)
+/* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA17			HDMI_BASE(0x0554)
+/* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA18			HDMI_BASE(0x0558)
+/* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA19			HDMI_BASE(0x055c)
+/* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA20			HDMI_BASE(0x0560)
+/* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA21			HDMI_BASE(0x0564)
+/* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA22			HDMI_BASE(0x0568)
+/* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA23			HDMI_BASE(0x056c)
+/* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA24			HDMI_BASE(0x0570)
+/* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA25			HDMI_BASE(0x0574)
+/* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA26			HDMI_BASE(0x0578)
+/* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA27			HDMI_BASE(0x057c)
+
+/* Gamut Metadata packet body data */
+#define	HDMI_DC_CONTROL			HDMI_BASE(0x05C0)
+/* Gamut Metadata packet body data */
+#define HDMI_VIDEO_PATTERN_GEN		HDMI_BASE(0x05C4)
+/* Gamut Metadata packet body data */
+#define HDMI_HPD_GEN			HDMI_BASE(0x05C8)
+
+
+/* SPDIFIN_CLK_CTRL [1:0] 0x02 */
+#define HDMI_SPDIFIN_CLK_CTRL		HDMI_SPDIF_BASE(0x0000)
+/* SPDIFIN_OP_CTRL [1:0] 0x00 */
+#define HDMI_SPDIFIN_OP_CTRL		HDMI_SPDIF_BASE(0x0004)
+/* SPDIFIN_IRQ_MASK[7:0] 0x00 */
+#define HDMI_SPDIFIN_IRQ_MASK		HDMI_SPDIF_BASE(0x0008)
+/* SPDIFIN_IRQ_STATUS [7:0] 0x00 */
+#define HDMI_SPDIFIN_IRQ_STATUS		HDMI_SPDIF_BASE(0x000C)
+/* SPDIFIN_CONFIG [7:0] 0x00 */
+#define HDMI_SPDIFIN_CONFIG_1		HDMI_SPDIF_BASE(0x0010)
+/* SPDIFIN_CONFIG [11:8] 0x00 */
+#define HDMI_SPDIFIN_CONFIG_2		HDMI_SPDIF_BASE(0x0014)
+/* SPDIFIN_USER_VALUE [7:0] 0x00 */
+#define HDMI_SPDIFIN_USER_VALUE_1		HDMI_SPDIF_BASE(0x0020)
+/* SPDIFIN_USER_VALUE [15:8] 0x00 */
+#define HDMI_SPDIFIN_USER_VALUE_2		HDMI_SPDIF_BASE(0x0024)
+/* SPDIFIN_USER_VALUE [23:16] 0x00 */
+#define HDMI_SPDIFIN_USER_VALUE_3		HDMI_SPDIF_BASE(0x0028)
+/* SPDIFIN_USER_VALUE [31:24] 0x00 */
+#define HDMI_SPDIFIN_USER_VALUE_4		HDMI_SPDIF_BASE(0x002C)
+/* SPDIFIN_CH_STATUS_0 [7:0] 0x00 */
+#define HDMI_SPDIFIN_CH_STATUS_0_1		HDMI_SPDIF_BASE(0x0030)
+/* SPDIFIN_CH_STATUS_0 [15:8] 0x00 */
+#define HDMI_SPDIFIN_CH_STATUS_0_2		HDMI_SPDIF_BASE(0x0034)
+/* SPDIFIN_CH_STATUS_0 [23:16] 0x00 */
+#define HDMI_SPDIFIN_CH_STATUS_0_3		HDMI_SPDIF_BASE(0x0038)
+/* SPDIFIN_CH_STATUS_0 [31:24] 0x00 */
+#define HDMI_SPDIFIN_CH_STATUS_0_4		HDMI_SPDIF_BASE(0x003C)
+/* SPDIFIN_CH_STATUS_1 0x00 */
+#define HDMI_SPDIFIN_CH_STATUS_1		HDMI_SPDIF_BASE(0x0040)
+/* SPDIF_FRAME_PERIOD [7:0] 0x00 */
+#define HDMI_SPDIFIN_FRAME_PERIOD_1		HDMI_SPDIF_BASE(0x0048)
+/* SPDIF_FRAME_PERIOD [15:8] 0x00 */
+#define HDMI_SPDIFIN_FRAME_PERIOD_2		HDMI_SPDIF_BASE(0x004C)
+/* SPDIFIN_Pc_INFO [7:0] 0x00 */
+#define HDMI_SPDIFIN_Pc_INFO_1		HDMI_SPDIF_BASE(0x0050)
+/* SPDIFIN_Pc_INFO [15:8] 0x00 */
+#define HDMI_SPDIFIN_Pc_INFO_2		HDMI_SPDIF_BASE(0x0054)
+/* SPDIFIN_Pd_INFO [7:0] 0x00 */
+#define HDMI_SPDIFIN_Pd_INFO_1		HDMI_SPDIF_BASE(0x0058)
+/* SPDIFIN_Pd_INFO [15:8] 0x00 */
+#define HDMI_SPDIFIN_Pd_INFO_2		HDMI_SPDIF_BASE(0x005C)
+/* SPDIFIN_DATA_BUF_0 [7:0] 0x00 */
+#define HDMI_SPDIFIN_DATA_BUF_0_1		HDMI_SPDIF_BASE(0x0060)
+/* SPDIFIN_DATA_BUF_0 [15:8] 0x00 */
+#define HDMI_SPDIFIN_DATA_BUF_0_2		HDMI_SPDIF_BASE(0x0064)
+/* SPDIFIN_DATA_BUF_0 [23:16] 0x00 */
+#define HDMI_SPDIFIN_DATA_BUF_0_3		HDMI_SPDIF_BASE(0x0068)
+/* SPDIFIN_DATA_BUF_0 [31:28] 0x00 */
+#define HDMI_SPDIFIN_USER_BUF_0		HDMI_SPDIF_BASE(0x006C)
+/* SPDIFIN_DATA_BUF_1 [7:0] 0x00 */
+#define HDMI_SPDIFIN_DATA_BUF_1_1		HDMI_SPDIF_BASE(0x0070)
+/* SPDIFIN_DATA_BUF_1 [15:8] 0x00 */
+#define HDMI_SPDIFIN_DATA_BUF_1_2		HDMI_SPDIF_BASE(0x0074)
+/* SPDIFIN_DATA_BUF_1 [23:16] 0x00 */
+#define HDMI_SPDIFIN_DATA_BUF_1_3		HDMI_SPDIF_BASE(0x0078)
+/* SPDIFIN_DATA_BUF_1 [31:28] 0x00 */
+#define HDMI_SPDIFIN_USER_BUF_1		HDMI_SPDIF_BASE(0x007C)
+
+
+/* I2S Clock Enable Register0x00  */
+#define HDMI_I2S_CLK_CON			HDMI_I2S_BASE(0x0000)
+/* I2S Control Register 10x00  */
+#define HDMI_I2S_CON_1			HDMI_I2S_BASE(0x0004)
+/* I2S Control Register 20x00  */
+#define HDMI_I2S_CON_2			HDMI_I2S_BASE(0x0008)
+/* I2S Input Pin Selection Register 0 0x77  */
+#define HDMI_I2S_PIN_SEL_0			HDMI_I2S_BASE(0x000C)
+/* I2S Input Pin Selection Register 1 0x77  */
+#define HDMI_I2S_PIN_SEL_1			HDMI_I2S_BASE(0x0010)
+/* I2S Input Pin Selection Register 2 0x77  */
+#define HDMI_I2S_PIN_SEL_2			HDMI_I2S_BASE(0x0014)
+/* I2S Input Pin Selection Register 30x07  */
+#define HDMI_I2S_PIN_SEL_3			HDMI_I2S_BASE(0x0018)
+/* I2S DSD Control Register0x02  */
+#define HDMI_I2S_DSD_CON			HDMI_I2S_BASE(0x001C)
+/* I2S In/Mux Control Register 0x60  */
+#define HDMI_I2S_MUX_CON			HDMI_I2S_BASE(0x0020)
+/* I2S Channel Status Control Register0x00  */
+#define HDMI_I2S_CH_ST_CON			HDMI_I2S_BASE(0x0024)
+/* I2S Channel Status Block 00x00  */
+#define HDMI_I2S_CH_ST_0			HDMI_I2S_BASE(0x0028)
+/* I2S Channel Status Block 10x00  */
+#define HDMI_I2S_CH_ST_1			HDMI_I2S_BASE(0x002C)
+/* I2S Channel Status Block 20x00  */
+#define HDMI_I2S_CH_ST_2			HDMI_I2S_BASE(0x0030)
+/* I2S Channel Status Block 30x00  */
+#define HDMI_I2S_CH_ST_3			HDMI_I2S_BASE(0x0034)
+/* I2S Channel Status Block 40x00  */
+#define HDMI_I2S_CH_ST_4			HDMI_I2S_BASE(0x0038)
+/* I2S Channel Status Block Shadow Register 00x00  */
+#define HDMI_I2S_CH_ST_SH_0			HDMI_I2S_BASE(0x003C)
+/* I2S Channel Status Block Shadow Register 10x00  */
+#define HDMI_I2S_CH_ST_SH_1			HDMI_I2S_BASE(0x0040)
+/* I2S Channel Status Block Shadow Register 20x00  */
+#define HDMI_I2S_CH_ST_SH_2			HDMI_I2S_BASE(0x0044)
+/* I2S Channel Status Block Shadow Register 30x00  */
+#define HDMI_I2S_CH_ST_SH_3			HDMI_I2S_BASE(0x0048)
+/* I2S Channel Status Block Shadow Register 40x00  */
+#define HDMI_I2S_CH_ST_SH_4			HDMI_I2S_BASE(0x004C)
+/* I2S Audio Sample Validity Register0x00  */
+#define HDMI_I2S_VD_DATA			HDMI_I2S_BASE(0x0050)
+/* I2S Channel Enable Register0x03  */
+#define HDMI_I2S_MUX_CH			HDMI_I2S_BASE(0x0054)
+/* I2S CUV Enable Register0x03  */
+#define HDMI_I2S_MUX_CUV			HDMI_I2S_BASE(0x0058)
+/* I2S Interrupt Request Mask Register0x03  */
+#define HDMI_I2S_IRQ_MASK			HDMI_I2S_BASE(0x005C)
+/* I2S Interrupt Request Status Register0x00  */
+#define HDMI_I2S_IRQ_STATUS			HDMI_I2S_BASE(0x0060)
+/* I2S PCM Output Data Register0x00  */
+#define HDMI_I2S_CH0_L_0			HDMI_I2S_BASE(0x0064)
+/* I2S PCM Output Data Register0x00  */
+#define HDMI_I2S_CH0_L_1			HDMI_I2S_BASE(0x0068)
+/* I2S PCM Output Data Register0x00  */
+#define HDMI_I2S_CH0_L_2			HDMI_I2S_BASE(0x006C)
+/* I2S PCM Output Data Register0x00  */
+#define HDMI_I2S_CH0_L_3			HDMI_I2S_BASE(0x0070)
+/* I2S PCM Output Data Register0x00  */
+#define HDMI_I2S_CH0_R_0			HDMI_I2S_BASE(0x0074)
+/* I2S PCM Output Data Register0x00  */
+#define HDMI_I2S_CH0_R_1			HDMI_I2S_BASE(0x0078)
+/* I2S PCM Output Data Register0x00  */
+#define HDMI_I2S_CH0_R_2			HDMI_I2S_BASE(0x007C)
+/* I2S PCM Output Data Register0x00  */
+#define HDMI_I2S_CH0_R_3			HDMI_I2S_BASE(0x0080)
+/* I2S PCM Output Data Register0x00  */
+#define HDMI_I2S_CH1_L_0			HDMI_I2S_BASE(0x0084)
+/* I2S PCM Output Data Register0x00  */
+#define HDMI_I2S_CH1_L_1			HDMI_I2S_BASE(0x0088)
+/* I2S PCM Output Data Register0x00  */
+#define HDMI_I2S_CH1_L_2			HDMI_I2S_BASE(0x008C)
+/* I2S PCM Output Data Register0x00  */
+#define HDMI_I2S_CH1_L_3			HDMI_I2S_BASE(0x0090)
+/* I2S PCM Output Data Register0x00  */
+#define HDMI_I2S_CH1_R_0			HDMI_I2S_BASE(0x0094)
+/* I2S PCM Output Data Register0x00  */
+#define HDMI_I2S_CH1_R_1			HDMI_I2S_BASE(0x0098)
+/* I2S PCM Output Data Register0x00  */
+#define HDMI_I2S_CH1_R_2			HDMI_I2S_BASE(0x009C)
+/* I2S PCM Output Data Register0x00  */
+#define HDMI_I2S_CH1_R_3			HDMI_I2S_BASE(0x00A0)
+/* I2S PCM Output Data Register0x00  */
+#define HDMI_I2S_CH2_L_0			HDMI_I2S_BASE(0x00A4)
+/* I2S PCM Output Data Register0x00  */
+#define HDMI_I2S_CH2_L_1			HDMI_I2S_BASE(0x00A8)
+/* I2S PCM Output Data Register0x00  */
+#define HDMI_I2S_CH2_L_2			HDMI_I2S_BASE(0x00AC)
+/* I2S PCM Output Data Register0x00  */
+#define HDMI_I2S_CH2_L_3			HDMI_I2S_BASE(0x00B0)
+/* I2S PCM Output Data Register0x00  */
+#define HDMI_I2S_CH2_R_0			HDMI_I2S_BASE(0x00B4)
+/* I2S PCM Output Data Register0x00  */
+#define HDMI_I2S_CH2_R_1			HDMI_I2S_BASE(0x00B8)
+/* I2S PCM Output Data Register0x00  */
+#define HDMI_I2S_CH2_R_2			HDMI_I2S_BASE(0x00BC)
+/* I2S PCM Output Data Register0x00  */
+#define HDMI_I2S_Ch2_R_3			HDMI_I2S_BASE(0x00C0)
+/* I2S PCM Output Data Register0x00  */
+#define HDMI_I2S_CH3_L_0			HDMI_I2S_BASE(0x00C4)
+/* I2S PCM Output Data Register0x00  */
+#define HDMI_I2S_CH3_L_1			HDMI_I2S_BASE(0x00C8)
+/* I2S PCM Output Data Register0x00  */
+#define HDMI_I2S_CH3_L_2			HDMI_I2S_BASE(0x00CC)
+/* I2S PCM Output Data Register0x00  */
+#define HDMI_I2S_CH3_R_0			HDMI_I2S_BASE(0x00D0)
+/* I2S PCM Output Data Register0x00  */
+#define HDMI_I2S_CH3_R_1			HDMI_I2S_BASE(0x00D4)
+/* I2S PCM Output Data Register0x00  */
+#define HDMI_I2S_CH3_R_2			HDMI_I2S_BASE(0x00D8)
+/* I2S CUV Output Data Register0x00  */
+#define HDMI_I2S_CUV_L_R			HDMI_I2S_BASE(0x00DC)
+
+
+/* Command Register 0x00 */
+#define HDMI_TG_CMD				HDMI_TG_BASE(0x0000)
+/* Horizontal Full Size 0x72 */
+#define HDMI_TG_H_FSZ_L			HDMI_TG_BASE(0x0018)
+/* Horizontal Full Size 0x06 */
+#define HDMI_TG_H_FSZ_H			HDMI_TG_BASE(0x001C)
+/* Horizontal Active Start 0x05 */
+#define HDMI_TG_HACT_ST_L			HDMI_TG_BASE(0x0020)
+/* Horizontal Active Start 0x01 */
+#define HDMI_TG_HACT_ST_H			HDMI_TG_BASE(0x0024)
+/* Horizontal Active Size 0x00 */
+#define HDMI_TG_HACT_SZ_L			HDMI_TG_BASE(0x0028)
+/* Horizontal Active Size 0x05 */
+#define HDMI_TG_HACT_SZ_H			HDMI_TG_BASE(0x002C)
+/* Vertical Full Line Size 0xEE */
+#define HDMI_TG_V_FSZ_L			HDMI_TG_BASE(0x0030)
+/* Vertical Full Line Size 0x02 */
+#define HDMI_TG_V_FSZ_H			HDMI_TG_BASE(0x0034)
+/* Vertical Sync Position 0x01 */
+#define HDMI_TG_VSYNC_L			HDMI_TG_BASE(0x0038)
+/* Vertical Sync Position 0x00 */
+#define HDMI_TG_VSYNC_H			HDMI_TG_BASE(0x003C)
+/* Vertical Sync Position for Bottom Field 0x33 */
+#define HDMI_TG_VSYNC2_L			HDMI_TG_BASE(0x0040)
+/* Vertical Sync Position for Bottom Field 0x02 */
+#define HDMI_TG_VSYNC2_H			HDMI_TG_BASE(0x0044)
+/* Vertical Sync Active Start Position 0x1a */
+#define HDMI_TG_VACT_ST_L			HDMI_TG_BASE(0x0048)
+/* Vertical Sync Active Start Position 0x00 */
+#define HDMI_TG_VACT_ST_H			HDMI_TG_BASE(0x004C)
+/* Vertical Active Size 0xd0 */
+#define HDMI_TG_VACT_SZ_L			HDMI_TG_BASE(0x0050)
+/* Vertical Active Size 0x02 */
+#define HDMI_TG_VACT_SZ_H			HDMI_TG_BASE(0x0054)
+/* Field Change Position 0x33 */
+#define HDMI_TG_FIELD_CHG_L			HDMI_TG_BASE(0x0058)
+/* Field Change Position 0x02 */
+#define HDMI_TG_FIELD_CHG_H			HDMI_TG_BASE(0x005C)
+/* Vertical Sync Active Start Position for Bottom Field 0x48 */
+#define HDMI_TG_VACT_ST2_L			HDMI_TG_BASE(0x0060)
+/* Vertical Sync Active Start Position for Bottom Field 0x02 */
+#define HDMI_TG_VACT_ST2_H			HDMI_TG_BASE(0x0064)
+
+/* HDMI Vsync Positon for Top Field 0x01 */
+#define HDMI_TG_VSYNC_TOP_HDMI_L		HDMI_TG_BASE(0x0078)
+/* HDMI Vsync Positon for Top Field 0x00 */
+#define HDMI_TG_VSYNC_TOP_HDMI_H		HDMI_TG_BASE(0x007C)
+/* HDMI Vsync Positon for Bottom Field 0x33 */
+#define HDMI_TG_VSYNC_BOT_HDMI_L		HDMI_TG_BASE(0x0080)
+/* HDMI Vsync Positon for Bottom Field 0x02 */
+#define HDMI_TG_VSYNC_BOT_HDMI_H		HDMI_TG_BASE(0x0084)
+/* HDMI Top Field Start Position 0x01 */
+#define HDMI_TG_FIELD_TOP_HDMI_L		HDMI_TG_BASE(0x0088)
+/* HDMI Top Field Start Position 0x00 */
+#define HDMI_TG_FIELD_TOP_HDMI_H		HDMI_TG_BASE(0x008C)
+/* HDMI Bottom Field Start Position 0x33 */
+#define HDMI_TG_FIELD_BOT_HDMI_L		HDMI_TG_BASE(0x0090)
+/* HDMI Bottom Field Start Position 0x02 */
+#define HDMI_TG_FIELD_BOT_HDMI_H		HDMI_TG_BASE(0x0094)
+
+#define HDMI_EFUSE_CTRL			HDMI_EFUSE_BASE(0x0000)
+#define HDMI_EFUSE_STATUS			HDMI_EFUSE_BASE(0x0004)
+#define HDMI_EFUSE_ADDR_WIDTH		HDMI_EFUSE_BASE(0x0008)
+#define HDMI_EFUSE_SIGDEV_ASSERT		HDMI_EFUSE_BASE(0x000c)
+#define HDMI_EFUSE_SIGDEV_DEASSERT		HDMI_EFUSE_BASE(0x0010)
+#define HDMI_EFUSE_PRCHG_ASSERT		HDMI_EFUSE_BASE(0x0014)
+#define HDMI_EFUSE_PRCHG_DEASSERT		HDMI_EFUSE_BASE(0x0018)
+#define HDMI_EFUSE_FSET_ASSERT		HDMI_EFUSE_BASE(0x001c)
+#define HDMI_EFUSE_FSET_DEASSERT		HDMI_EFUSE_BASE(0x0020)
+#define HDMI_EFUSE_SENSING			HDMI_EFUSE_BASE(0x0024)
+#define HDMI_EFUSE_SCK_ASSERT		HDMI_EFUSE_BASE(0x0028)
+#define HDMI_EFUSE_SCK_DEASSERT		HDMI_EFUSE_BASE(0x002c)
+#define HDMI_EFUSE_SDOUT_OFFSET		HDMI_EFUSE_BASE(0x0030)
+#define HDMI_EFUSE_READ_OFFSET		HDMI_EFUSE_BASE(0x0034)
+
+#define HDMI_AUI_SZ				5
+#define HDMI_GCP_SZ				3
+#define HDMI_SPD_SZ				28
+#define HDMI_AVI_SZ				13
+#define HDMI_MPG_SZ				5
+#define HDMI_GMU_SX				28
+#define HDMI_ISRC_SZ			16
+#define HDMI_ACP_SZ				17
+
+/*
+ * Bit definition part
+ */
+
+/* Control Register */
+
+/* INTC_CON */
+#define HDMI_INTC_ACT_HI			(1 << 7)
+#define HDMI_INTC_ACT_LOW			(0 << 7)
+#define HDMI_INTC_EN_GLOBAL			(1 << 6)
+#define HDMI_INTC_DIS_GLOBAL		(0 << 6)
+#define HDMI_INTC_EN_I2S			(1 << 5)
+#define HDMI_INTC_DIS_I2S			(0 << 5)
+#define HDMI_INTC_EN_CEC			(1 << 4)
+#define HDMI_INTC_DIS_CEC			(0 << 4)
+#define HDMI_INTC_EN_HPD_PLUG		(1 << 3)
+#define HDMI_INTC_DIS_HPD_PLUG		(0 << 3)
+#define HDMI_INTC_EN_HPD_UNPLUG		(1 << 2)
+#define HDMI_INTC_DIS_HPD_UNPLUG		(0 << 2)
+#define HDMI_INTC_EN_SPDIF			(1 << 1)
+#define HDMI_INTC_DIS_SPDIF			(0 << 1)
+#define HDMI_INTC_EN_HDCP			(1 << 0)
+#define HDMI_INTC_DIS_HDCP			(0 << 0)
+
+/* INTC_FLAG */
+#define HDMI_INTC_FLAG_I2S			(1 << 5)
+#define HDMI_INTC_FLAG_CEC			(1 << 4)
+#define HDMI_INTC_FLAG_HPD_PLUG		(1 << 3)
+#define HDMI_INTC_FLAG_HPD_UNPLUG		(1 << 2)
+#define HDMI_INTC_FLAG_SPDIF		(1 << 1)
+#define HDMI_INTC_FLAG_HDCP			(1 << 0)
+
+/* HDCP_KEY_LOAD_DONE */
+#define HDMI_HDCP_KEY_LOAD_DONE		(1 << 0)
+
+/* HPD_STATUS */
+#define HDMI_HPD_PLUGED			(1 << 0)
+
+/* AUDIO_CLKSEL */
+#define HDMI_AUDIO_SPDIF_CLK		(1 << 0)
+#define HDMI_AUDIO_PCLK			(0 << 0)
+
+/* HDMI_PHY_RSTOUT */
+#define HDMI_PHY_SW_RSTOUT			(1 << 0)
+
+/* HDMI_PHY_VPLL */
+#define HDMI_PHY_VPLL_LOCK			(1 << 7)
+#define HDMI_PHY_VPLL_CODE_MASK		(0x7 << 0)
+
+/* HDMI_PHY_CMU */
+#define HDMI_PHY_CMU_LOCK			(1 << 7)
+#define HDMI_PHY_CMU_CODE_MASK		(0x7 << 0)
+
+/* HDMI_CORE_RSTOUT */
+#define HDMI_CORE_SW_RSTOUT			(1 << 0)
+
+
+/* Core Register */
+
+/* HDMI_CON_0 */
+#define HDMI_BLUE_SCR_EN			(1 << 5)
+#define HDMI_BLUE_SCR_DIS			(0 << 5)
+#define HDMI_ENC_OPTION			(1 << 4)
+#define HDMI_ASP_EN				(1 << 2)
+#define HDMI_ASP_DIS			(0 << 2)
+#define HDMI_PWDN_ENB_NORMAL		(1 << 1)
+#define HDMI_PWDN_ENB_PD			(0 << 1)
+#define HDMI_EN				(1 << 0)
+#define HDMI_DIS				(~(1 << 0))
+
+/* HDMI_CON_1 */
+#define HDMI_PX_LMT_CTRL_BYPASS		(0 << 5)
+#define HDMI_PX_LMT_CTRL_RGB		(1 << 5)
+#define HDMI_PX_LMT_CTRL_YPBPR		(2 << 5)
+#define HDMI_PX_LMT_CTRL_RESERVED		(3 << 5)
+/*Not support in S5PV210 */
+#define HDMI_CON_PXL_REP_RATIO_MASK		(1 << 1 | 1 << 0)
+/*Not support in S5PV210 */
+#define HDMI_DOUBLE_PIXEL_REPETITION	(0x01)
+
+/* HDMI_CON_2 */
+#define HDMI_VID_PREAMBLE_EN		(0 << 5)
+#define HDMI_VID_PREAMBLE_DIS		(1 << 5)
+#define HDMI_GUARD_BAND_EN			(0 << 1)
+#define HDMI_GUARD_BAND_DIS			(1 << 1)
+
+/* STATUS */
+#define HDMI_AUTHEN_ACK_AUTH		(1 << 7)
+#define HDMI_AUTHEN_ACK_NOT			(0 << 7)
+#define HDMI_AUD_FIFO_OVF_FULL		(1 << 6)
+#define HDMI_AUD_FIFO_OVF_NOT		(0 << 6)
+#define HDMI_UPDATE_RI_INT_OCC		(1 << 4)
+#define HDMI_UPDATE_RI_INT_NOT		(0 << 4)
+#define HDMI_UPDATE_RI_INT_CLEAR		(1 << 4)
+#define HDMI_UPDATE_PJ_INT_OCC		(1 << 3)
+#define HDMI_UPDATE_PJ_INT_NOT		(0 << 3)
+#define HDMI_UPDATE_PJ_INT_CLEAR		(1 << 3)
+#define HDMI_WRITE_INT_OCC			(1 << 2)
+#define HDMI_WRITE_INT_NOT			(0 << 2)
+#define HDMI_WRITE_INT_CLEAR		(1 << 2)
+#define HDMI_WATCHDOG_INT_OCC		(1 << 1)
+#define HDMI_WATCHDOG_INT_NOT		(0 << 1)
+#define HDMI_WATCHDOG_INT_CLEAR		(1 << 1)
+#define HDMI_WTFORACTIVERX_INT_OCC		(1)
+#define HDMI_WTFORACTIVERX_INT_NOT		(0)
+#define HDMI_WTFORACTIVERX_INT_CLEAR	(1)
+
+/* PHY_STATUS */
+#define HDMI_PHY_STATUS_READY		(1)
+
+/* STATUS_EN */
+#define HDMI_AUD_FIFO_OVF_EN		(1 << 6)
+#define HDMI_AUD_FIFO_OVF_DIS		(0 << 6)
+#define HDMI_UPDATE_RI_INT_EN		(1 << 4)
+#define HDMI_UPDATE_RI_INT_DIS		(0 << 4)
+#define HDMI_UPDATE_PJ_INT_EN		(1 << 3)
+#define HDMI_UPDATE_PJ_INT_DIS		(0 << 3)
+#define HDMI_WRITE_INT_EN			(1 << 2)
+#define HDMI_WRITE_INT_DIS			(0 << 2)
+#define HDMI_WATCHDOG_INT_EN		(1 << 1)
+#define HDMI_WATCHDOG_INT_DIS		(0 << 1)
+#define HDMI_WTFORACTIVERX_INT_EN		(1)
+#define HDMI_WTFORACTIVERX_INT_DIS		(0)
+#define HDMI_INT_EN_ALL				(HDMI_UPDATE_RI_INT_EN|\
+						HDMI_UPDATE_PJ_INT_DIS|\
+						HDMI_WRITE_INT_EN|\
+						HDMI_WATCHDOG_INT_EN|\
+						HDMI_WTFORACTIVERX_INT_EN)
+#define HDMI_INT_DIS_ALL			(~0x1F)
+
+/* HPD */
+#define HDMI_SW_HPD_PLUGGED			(1 << 1)
+#define HDMI_SW_HPD_UNPLUGGED		(0 << 1)
+#define HDMI_HPD_SEL_I_HPD			(1)
+#define HDMI_HPD_SEL_SW_HPD			(0)
+
+/* MODE_SEL */
+#define HDMI_MODE_HDMI_EN			(1 << 1)
+#define HDMI_MODE_HDMI_DIS			(0 << 1)
+#define HDMI_MODE_DVI_EN			(1)
+#define HDMI_MODE_DVI_DIS			(0)
+#define HDMI_MODE_MASK				(3)
+
+/* ENC_EN */
+#define HDMI_HDCP_ENC_ENABLE		(1)
+#define HDMI_HDCP_ENC_DISABLE		(0)
+
+
+/* Video Related Register */
+
+/* BLUESCREEN_0/1/2 */
+#define HDMI_SET_BLUESCREEN_0(x)		((x) & 0xFF)
+#define HDMI_SET_BLUESCREEN_1(x)		((x) & 0xFF)
+#define HDMI_SET_BLUESCREEN_2(x)		((x) & 0xFF)
+
+/* HDMI_YMAX/YMIN/CMAX/CMIN */
+#define HDMI_SET_YMAX(x)			((x) & 0xFF)
+#define HDMI_SET_YMIN(x)			((x) & 0xFF)
+#define HDMI_SET_CMAX(x)			((x) & 0xFF)
+#define HDMI_SET_CMIN(x)			((x) & 0xFF)
+
+/* H_BLANK_0/1 */
+#define HDMI_SET_H_BLANK_0(x)		((x) & 0xFF)
+#define HDMI_SET_H_BLANK_1(x)		(((x) >> 8) & 0x3FF)
+
+/* V_BLANK_0/1/2 */
+#define HDMI_SET_V_BLANK_0(x)		((x) & 0xFF)
+#define HDMI_SET_V_BLANK_1(x)		(((x) >> 8) & 0xFF)
+#define HDMI_SET_V_BLANK_2(x)		(((x) >> 16) & 0xFF)
+
+/* H_V_LINE_0/1/2 */
+#define HDMI_SET_H_V_LINE_0(x)		((x) & 0xFF)
+#define HDMI_SET_H_V_LINE_1(x)		(((x) >> 8) & 0xFF)
+#define HDMI_SET_H_V_LINE_2(x)		(((x) >> 16) & 0xFF)
+
+/* VSYNC_POL */
+#define HDMI_V_SYNC_POL_ACT_LOW		(1)
+#define HDMI_V_SYNC_POL_ACT_HIGH		(0)
+
+/* INT_PRO_MODE */
+#define HDMI_INTERLACE_MODE			(1)
+#define HDMI_PROGRESSIVE_MODE		(0)
+
+/* V_BLANK_F_0/1/2 */
+#define HDMI_SET_V_BLANK_F_0(x)		((x) & 0xFF)
+#define HDMI_SET_V_BLANK_F_1(x)		(((x) >> 8) & 0xFF)
+#define HDMI_SET_V_BLANK_F_2(x)		(((x) >> 16) & 0xFF)
+
+
+/* H_SYNC_GEN_0/1/2 */
+#define HDMI_SET_H_SYNC_GEN_0(x)		((x) & 0xFF)
+#define HDMI_SET_H_SYNC_GEN_1(x)		(((x) >> 8) & 0xFF)
+#define HDMI_SET_H_SYNC_GEN_2(x)		(((x) >> 16) & 0xFF)
+
+
+/* V_SYNC_GEN1_0/1/2 */
+#define HDMI_SET_V_SYNC_GEN1_0(x)		((x) & 0xFF)
+#define HDMI_SET_V_SYNC_GEN1_1(x)		(((x) >> 8) & 0xFF)
+#define HDMI_SET_V_SYNC_GEN1_2(x)		(((x) >> 16) & 0xFF)
+
+/* V_SYNC_GEN2_0/1/2 */
+#define HDMI_SET_V_SYNC_GEN2_0(x)		((x) & 0xFF)
+#define HDMI_SET_V_SYNC_GEN2_1(x)		(((x) >> 8) & 0xFF)
+#define HDMI_SET_V_SYNC_GEN2_2(x)		(((x) >> 16) & 0xFF)
+
+/* V_SYNC_GEN3_0/1/2 */
+#define HDMI_SET_V_SYNC_GEN3_0(x)		((x) & 0xFF)
+#define HDMI_SET_V_SYNC_GEN3_1(x)		(((x) >> 8) & 0xFF)
+#define HDMI_SET_V_SYNC_GEN3_2(x)		(((x) >> 16) & 0xFF)
+
+
+/* Audio Related Packet Register */
+
+/* ASP_CON */
+#define HDMI_AUD_DST_DOUBLE			(1 << 7)
+#define HDMI_AUD_NO_DST_DOUBLE		(0 << 7)
+#define HDMI_AUD_TYPE_SAMPLE		(0 << 5)
+#define HDMI_AUD_TYPE_ONE_BIT		(1 << 5)
+#define HDMI_AUD_TYPE_HBR			(2 << 5)
+#define HDMI_AUD_TYPE_DST			(3 << 5)
+#define HDMI_AUD_MODE_TWO_CH		(0 << 4)
+#define HDMI_AUD_MODE_MULTI_CH		(1 << 4)
+#define HDMI_AUD_SP_AUD3_EN			(1 << 3)
+#define HDMI_AUD_SP_AUD2_EN			(1 << 2)
+#define HDMI_AUD_SP_AUD1_EN			(1 << 1)
+#define HDMI_AUD_SP_AUD0_EN			(1 << 0)
+#define HDMI_AUD_SP_ALL_DIS			(0 << 0)
+
+#define HDMI_AUD_SET_SP_PRE(x)		((x) & 0xF)
+
+/* ASP_SP_FLAT */
+#define HDMI_ASP_SP_FLAT_AUD_SAMPLE		(0)
+
+/* ASP_CHCFG0/1/2/3 */
+#define HDMI_SPK3R_SEL_I_PCM0L		(0 << 27)
+#define HDMI_SPK3R_SEL_I_PCM0R		(1 << 27)
+#define HDMI_SPK3R_SEL_I_PCM1L		(2 << 27)
+#define HDMI_SPK3R_SEL_I_PCM1R		(3 << 27)
+#define HDMI_SPK3R_SEL_I_PCM2L		(4 << 27)
+#define HDMI_SPK3R_SEL_I_PCM2R		(5 << 27)
+#define HDMI_SPK3R_SEL_I_PCM3L		(6 << 27)
+#define HDMI_SPK3R_SEL_I_PCM3R		(7 << 27)
+#define HDMI_SPK3L_SEL_I_PCM0L		(0 << 24)
+#define HDMI_SPK3L_SEL_I_PCM0R		(1 << 24)
+#define HDMI_SPK3L_SEL_I_PCM1L		(2 << 24)
+#define HDMI_SPK3L_SEL_I_PCM1R		(3 << 24)
+#define HDMI_SPK3L_SEL_I_PCM2L		(4 << 24)
+#define HDMI_SPK3L_SEL_I_PCM2R		(5 << 24)
+#define HDMI_SPK3L_SEL_I_PCM3L		(6 << 24)
+#define HDMI_SPK3L_SEL_I_PCM3R		(7 << 24)
+#define HDMI_SPK2R_SEL_I_PCM0L		(0 << 19)
+#define HDMI_SPK2R_SEL_I_PCM0R		(1 << 19)
+#define HDMI_SPK2R_SEL_I_PCM1L		(2 << 19)
+#define HDMI_SPK2R_SEL_I_PCM1R		(3 << 19)
+#define HDMI_SPK2R_SEL_I_PCM2L		(4 << 19)
+#define HDMI_SPK2R_SEL_I_PCM2R		(5 << 19)
+#define HDMI_SPK2R_SEL_I_PCM3L		(6 << 19)
+#define HDMI_SPK2R_SEL_I_PCM3R		(7 << 19)
+#define HDMI_SPK2L_SEL_I_PCM0L		(0 << 16)
+#define HDMI_SPK2L_SEL_I_PCM0R		(1 << 16)
+#define HDMI_SPK2L_SEL_I_PCM1L		(2 << 16)
+#define HDMI_SPK2L_SEL_I_PCM1R		(3 << 16)
+#define HDMI_SPK2L_SEL_I_PCM2L		(4 << 16)
+#define HDMI_SPK2L_SEL_I_PCM2R		(5 << 16)
+#define HDMI_SPK2L_SEL_I_PCM3L		(6 << 16)
+#define HDMI_SPK2L_SEL_I_PCM3R		(7 << 16)
+#define HDMI_SPK1R_SEL_I_PCM0L		(0 << 11)
+#define HDMI_SPK1R_SEL_I_PCM0R		(1 << 11)
+#define HDMI_SPK1R_SEL_I_PCM1L		(2 << 11)
+#define HDMI_SPK1R_SEL_I_PCM1R		(3 << 11)
+#define HDMI_SPK1R_SEL_I_PCM2L		(4 << 11)
+#define HDMI_SPK1R_SEL_I_PCM2R		(5 << 11)
+#define HDMI_SPK1R_SEL_I_PCM3L		(6 << 11)
+#define HDMI_SPK1R_SEL_I_PCM3R		(7 << 11)
+#define HDMI_SPK1L_SEL_I_PCM0L		(0 << 8)
+#define HDMI_SPK1L_SEL_I_PCM0R		(1 << 8)
+#define HDMI_SPK1L_SEL_I_PCM1L		(2 << 8)
+#define HDMI_SPK1L_SEL_I_PCM1R		(3 << 8)
+#define HDMI_SPK1L_SEL_I_PCM2L		(4 << 8)
+#define HDMI_SPK1L_SEL_I_PCM2R		(5 << 8)
+#define HDMI_SPK1L_SEL_I_PCM3L		(6 << 8)
+#define HDMI_SPK1L_SEL_I_PCM3R		(7 << 8)
+#define HDMI_SPK0R_SEL_I_PCM0L		(0 << 3)
+#define HDMI_SPK0R_SEL_I_PCM0R		(1 << 3)
+#define HDMI_SPK0R_SEL_I_PCM1L		(2 << 3)
+#define HDMI_SPK0R_SEL_I_PCM1R		(3 << 3)
+#define HDMI_SPK0R_SEL_I_PCM2L		(4 << 3)
+#define HDMI_SPK0R_SEL_I_PCM2R		(5 << 3)
+#define HDMI_SPK0R_SEL_I_PCM3L		(6 << 3)
+#define HDMI_SPK0R_SEL_I_PCM3R		(7 << 3)
+#define HDMI_SPK0L_SEL_I_PCM0L		(0)
+#define HDMI_SPK0L_SEL_I_PCM0R		(1)
+#define HDMI_SPK0L_SEL_I_PCM1L		(2)
+#define HDMI_SPK0L_SEL_I_PCM1R		(3)
+#define HDMI_SPK0L_SEL_I_PCM2L		(4)
+#define HDMI_SPK0L_SEL_I_PCM2R		(5)
+#define HDMI_SPK0L_SEL_I_PCM3L		(6)
+#define HDMI_SPK0L_SEL_I_PCM3R		(7)
+
+/* ACR_CON */
+#define HDMI_ALT_CTS_RATE_CTS_1		(0 << 3)
+#define HDMI_ALT_CTS_RATE_CTS_11		(1 << 3)
+#define HDMI_ALT_CTS_RATE_CTS_21		(2 << 3)
+#define HDMI_ALT_CTS_RATE_CTS_31		(3 << 3)
+#define HDMI_ACR_TX_MODE_NO_TX		(0)
+#define HDMI_ACR_TX_MODE_TX_ONCE		(1)
+#define HDMI_ACR_TX_MODE_TXCNT_VBI		(2)
+#define HDMI_ACR_TX_MODE_TX_VPC		(3)
+#define HDMI_ACR_TX_MODE_MESURE_CTS		(4)
+
+/* ACR_MCTS0/1/2 */
+#define HDMI_SET_ACR_MCTS_0(x)		((x) & 0xFF)
+#define HDMI_SET_ACR_MCTS_1(x)		(((x) >> 8) & 0xFF)
+#define HDMI_SET_ACR_MCTS_2(x)		(((x) >> 16) & 0xFF)
+
+/* ACR_CTS0/1/2 */
+#define HDMI_SET_ACR_CTS_0(x)		((x) & 0xFF)
+#define HDMI_SET_ACR_CTS_1(x)		(((x) >> 8) & 0xFF)
+#define HDMI_SET_ACR_CTS_2(x)		(((x) >> 16) & 0xFF)
+
+/* ACR_N0/1/2 */
+#define HDMI_SET_ACR_N_0(x)			((x) & 0xFF)
+#define HDMI_SET_ACR_N_1(x)			(((x) >> 8) & 0xFF)
+#define HDMI_SET_ACR_N_2(x)			(((x) >> 16) & 0xFF)
+
+
+/* ACR_LSB2 */
+#define HDMI_ACR_LSB2_MASK			(0xFF)
+
+/* ACR_TXCNT */
+#define HDMI_ACR_TXCNT_MASK			(0x1F)
+
+/* ACR_TXINTERNAL */
+#define HDMI_ACR_TX_INTERNAL_MASK		(0xFF)
+
+/* ACR_CTS_OFFSET */
+#define HDMI_ACR_CTS_OFFSET_MASK		(0xFF)
+
+/* GCP_CON */
+#define HDMI_GCP_CON_EN_1ST_VSYNC		(1 << 3)
+#define HDMI_GCP_CON_EN_2ST_VSYNC		(1 << 2)
+#define HDMI_GCP_CON_TRANS_EVERY_VSYNC	(2)
+#define HDMI_GCP_CON_NO_TRAN		(0)
+#define HDMI_GCP_CON_TRANS_ONCE		(1)
+#define HDMI_GCP_CON_TRANS_EVERY_VSYNC	(2)
+
+/* GCP_BYTE1 */
+#define HDMI_GCP_BYTE1_MASK			(0xFF)
+
+/* GCP_BYTE2 */
+#define HDMI_GCP_BYTE2_PP_MASK		(0xF << 4)
+#define HDMI_GCP_BYTE2_CD_24BPP		(1 << 2)
+/*Not support in S5PV210 */
+#define HDMI_GCP_BYTE2_CD_30BPP		(1 << 0 | 1 << 2)
+/*Not support in S5PV210 */
+#define HDMI_GCP_BYTE2_CD_36BPP		(1 << 1 | 1 << 2)
+/*Not support in S5PV210 */
+#define HDMI_GCP_BYTE2_CD_48BPP		(1 << 0 | 1 << 1 | 1 << 2)
+
+
+/* GCP_BYTE3 */
+#define HDMI_GCP_BYTE3_MASK			(0xFF)
+
+
+/* ACP Packet Register */
+
+/* ACP_CON */
+#define HDMI_ACP_FR_RATE_MASK		(0x1F << 3)
+#define HDMI_ACP_CON_NO_TRAN		(0)
+#define HDMI_ACP_CON_TRANS_ONCE		(1)
+#define HDMI_ACP_CON_TRANS_EVERY_VSYNC	(2)
+
+/* ACP_TYPE */
+#define HDMI_ACP_TYPE_MASK			(0xFF)
+
+/* ACP_DATA00~16 */
+#define HDMI_ACP_DATA_MASK			(0xFF)
+
+
+/* ISRC1/2 Packet Register */
+
+/* ISRC_CON */
+#define HDMI_ISRC_FR_RATE_MASK		(0x1F << 3)
+#define HDMI_ISRC_EN			(1 << 2)
+#define HDMI_ISRC_DIS			(0 << 2)
+
+
+/* ISRC1_HEADER1 */
+#define HDMI_ISRC1_HEADER_MASK		(0xFF)
+
+/* ISRC1_DATA 00~15 */
+#define HDMI_ISRC1_DATA_MASK		(0xFF)
+
+/* ISRC2_DATA 00~15 */
+#define HDMI_ISRC2_DATA_MASK		(0xFF)
+
+
+/* AVI InfoFrame Register */
+
+/* AVI_CON */
+
+/* AVI_CHECK_SUM */
+#define HDMI_SET_AVI_CHECK_SUM(x)		((x) & 0xFF)
+
+/* AVI_DATA01~13 */
+#define HDMI_SET_AVI_DATA(x)		((x) & 0xFF)
+#define HDMI_AVI_PIXEL_REPETITION_DOUBLE	(1<<0)
+#define HDMI_AVI_PICTURE_ASPECT_4_3		(1<<4)
+#define HDMI_AVI_PICTURE_ASPECT_16_9	(1<<5)
+
+
+/* Audio InfoFrame Register */
+
+/* AUI_CON */
+
+/* AUI_CHECK_SUM */
+#define HDMI_SET_AUI_CHECK_SUM(x)		((x) & 0xFF)
+
+/* AUI_DATA1~5 */
+#define HDMI_SET_AUI_DATA(x)		((x) & 0xFF)
+
+
+/* MPEG Source InfoFrame registers */
+
+/* MPG_CON */
+
+/* HDMI_MPG_CHECK_SUM */
+#define HDMI_SET_MPG_CHECK_SUM(x)		((x) & 0xFF)
+
+/* MPG_DATA1~5 */
+#define HDMI_SET_MPG_DATA(x)		((x) & 0xFF)
+
+
+/* Source Product Descriptor Infoframe registers */
+
+/* SPD_CON */
+
+/* SPD_HEADER0/1/2 */
+#define HDMI_SET_SPD_HEADER(x)		((x) & 0xFF)
+
+
+/* SPD_DATA0~27 */
+#define HDMI_SET_SPD_DATA(x)		((x) & 0xFF)
+
+
+/* HDCP Register */
+
+/* HDCP_SHA1_00~19 */
+#define HDMI_SET_HDCP_SHA1(x)		((x) & 0xFF)
+
+/* HDCP_KSV_LIST_0~4 */
+
+/* HDCP_KSV_LIST_CON */
+#define HDMI_HDCP_KSV_WRITE_DONE		(0x1 << 3)
+#define HDMI_HDCP_KSV_LIST_EMPTY		(0x1 << 2)
+#define HDMI_HDCP_KSV_END			(0x1 << 1)
+#define HDMI_HDCP_KSV_READ			(0x1 << 0)
+
+/* HDCP_CTRL1 */
+#define HDMI_HDCP_EN_PJ_EN			(1 << 4)
+#define HDMI_HDCP_EN_PJ_DIS			(~(1 << 4))
+#define HDMI_HDCP_SET_REPEATER_TIMEOUT	(1 << 2)
+#define HDMI_HDCP_CLEAR_REPEATER_TIMEOUT	(~(1 << 2))
+#define HDMI_HDCP_CP_DESIRED_EN		(1 << 1)
+#define HDMI_HDCP_CP_DESIRED_DIS		(~(1 << 1))
+#define HDMI_HDCP_ENABLE_1_1_FEATURE_EN	(1)
+#define HDMI_HDCP_ENABLE_1_1_FEATURE_DIS	(~(1))
+
+/* HDCP_CHECK_RESULT */
+#define HDMI_HDCP_Pi_MATCH_RESULT_Y		((0x1 << 3) | (0x1 << 2))
+#define HDMI_HDCP_Pi_MATCH_RESULT_N		((0x1 << 3) | (0x0 << 2))
+#define HDMI_HDCP_Ri_MATCH_RESULT_Y		((0x1 << 1) | (0x1 << 0))
+#define HDMI_HDCP_Ri_MATCH_RESULT_N		((0x1 << 1) | (0x0 << 0))
+#define HDMI_HDCP_CLR_ALL_RESULTS		(0)
+
+/* HDCP_BKSV0~4 */
+/* HDCP_AKSV0~4 */
+
+/* HDCP_BCAPS */
+#define HDMI_HDCP_BCAPS_REPEATER		(1 << 6)
+#define HDMI_HDCP_BCAPS_READY		(1 << 5)
+#define HDMI_HDCP_BCAPS_FAST		(1 << 4)
+#define HDMI_HDCP_BCAPS_1_1_FEATURES	(1 << 1)
+#define HDMI_HDCP_BCAPS_FAST_REAUTH		(1)
+
+/* HDCP_BSTATUS_0/1 */
+/* HDCP_Ri_0/1 */
+/* HDCP_I2C_INT */
+/* HDCP_AN_INT */
+/* HDCP_WATCHDOG_INT */
+/* HDCP_RI_INT/1 */
+/* HDCP_Ri_Compare_0 */
+/* HDCP_Ri_Compare_1 */
+/* HDCP_Frame_Count */
+
+
+/* Gamut Metadata Packet Register */
+
+/* GAMUT_CON */
+/* GAMUT_HEADER0 */
+/* GAMUT_HEADER1 */
+/* GAMUT_HEADER2 */
+/* GAMUT_METADATA0~27 */
+
+
+/* Video Mode Register */
+
+/* VIDEO_PATTERN_GEN */
+/* HPD_GEN */
+/* HDCP_Ri_Compare_0 */
+/* HDCP_Ri_Compare_0 */
+/* HDCP_Ri_Compare_0 */
+/* HDCP_Ri_Compare_0 */
+/* HDCP_Ri_Compare_0 */
+/* HDCP_Ri_Compare_0 */
+/* HDCP_Ri_Compare_0 */
+/* HDCP_Ri_Compare_0 */
+/* HDCP_Ri_Compare_0 */
+/* HDCP_Ri_Compare_0 */
+
+
+/* SPDIF Register */
+
+/* SPDIFIN_CLK_CTRL */
+#define HDMI_SPDIFIN_READY_CLK_DOWN		(1 << 1)
+#define HDMI_SPDIFIN_CLK_ON			(1)
+
+/* SPDIFIN_OP_CTRL */
+#define HDMI_SPDIFIN_SW_RESET		(0)
+#define HDMI_SPDIFIN_STATUS_CHECK_MODE	(1)
+#define HDMI_SPDIFIN_STATUS_CHK_OP_MODE	(3)
+
+/* SPDIFIN_IRQ_MASK */
+
+/* SPDIFIN_IRQ_STATUS */
+#define HDMI_SPDIFIN_IRQ_OVERFLOW_EN			(1 << 7)
+#define HDMI_SPDIFIN_IRQ_ABNORMAL_PD_EN			(1 << 6)
+#define HDMI_SPDIFIN_IRQ_SH_NOT_DETECTED_RIGHTTIME_EN	(1 << 5)
+#define HDMI_SPDIFIN_IRQ_SH_DETECTED_EN			(1 << 4)
+#define HDMI_SPDIFIN_IRQ_SH_NOT_DETECTED_EN			(1 << 3)
+#define HDMI_SPDIFIN_IRQ_WRONG_PREAMBLE_EN			(1 << 2)
+#define HDMI_SPDIFIN_IRQ_CH_STATUS_RECOVERED_EN		(1 << 1)
+#define HDMI_SPDIFIN_IRQ_WRONG_SIG_EN			(1 << 0)
+
+/* SPDIFIN_CONFIG_1 */
+#define HDMI_SPDIFIN_CFG_FILTER_3_SAMPLE			(0 << 6)
+#define HDMI_SPDIFIN_CFG_FILTER_2_SAMPLE			(1 << 6)
+#define HDMI_SPDIFIN_CFG_LINEAR_PCM_TYPE			(0 << 5)
+#define HDMI_SPDIFIN_CFG_NO_LINEAR_PCM_TYPE			(1 << 5)
+#define HDMI_SPDIFIN_CFG_PCPD_AUTO_SET			(0 << 4)
+#define HDMI_SPDIFIN_CFG_PCPD_MANUAL_SET			(1 << 4)
+#define HDMI_SPDIFIN_CFG_WORD_LENGTH_A_SET			(0 << 3)
+#define HDMI_SPDIFIN_CFG_WORD_LENGTH_M_SET			(1 << 3)
+#define HDMI_SPDIFIN_CFG_U_V_C_P_NEGLECT			(0 << 2)
+#define HDMI_SPDIFIN_CFG_U_V_C_P_REPORT			(1 << 2)
+#define HDMI_SPDIFIN_CFG_BURST_SIZE_1			(0 << 1)
+#define HDMI_SPDIFIN_CFG_BURST_SIZE_2			(1 << 1)
+#define HDMI_SPDIFIN_CFG_DATA_ALIGN_16BIT			(0 << 0)
+#define HDMI_SPDIFIN_CFG_DATA_ALIGN_32BIT			(1 << 0)
+
+/* SPDIFIN_CONFIG_2 */
+#define HDMI_SPDIFIN_CFG2_NO_CLK_DIV			(0)
+
+/* SPDIFIN_USER_VALUE_1 */
+/* SPDIFIN_USER_VALUE_2 */
+/* SPDIFIN_USER_VALUE_3 */
+/* SPDIFIN_USER_VALUE_4 */
+/* SPDIFIN_CH_STATUS_0_1 */
+/* SPDIFIN_CH_STATUS_0_2 */
+/* SPDIFIN_CH_STATUS_0_3 */
+/* SPDIFIN_CH_STATUS_0_4 */
+/* SPDIFIN_CH_STATUS_1 */
+/* SPDIFIN_FRAME_PERIOD_1 */
+/* SPDIFIN_FRAME_PERIOD_2 */
+/* SPDIFIN_PC_INFO_1 */
+/* SPDIFIN_PC_INFO_2 */
+/* SPDIFIN_PD_INFO_1 */
+/* SPDIFIN_PD_INFO_2 */
+/* SPDIFIN_DATA_BUF_0_1 */
+/* SPDIFIN_DATA_BUF_0_2 */
+/* SPDIFIN_DATA_BUF_0_3 */
+/* SPDIFIN_USER_BUF_0 */
+/* SPDIFIN_USER_BUF_1_1 */
+/* SPDIFIN_USER_BUF_1_2 */
+/* SPDIFIN_USER_BUF_1_3 */
+/* SPDIFIN_USER_BUF_1 */
+
+
+/* I2S Register */
+
+/* I2S_CLK_CON */
+#define HDMI_I2S_CLK_DIS			(0)
+#define HDMI_I2S_CLK_EN			(1)
+
+/* I2S_CON_1 */
+#define HDMI_I2S_SCLK_FALLING_EDGE		(0 << 1)
+#define HDMI_I2S_SCLK_RISING_EDGE		(1 << 1)
+#define HDMI_I2S_L_CH_LOW_POL		(0)
+#define HDMI_I2S_L_CH_HIGH_POL		(1)
+
+/* I2S_CON_2 */
+#define HDMI_I2S_MSB_FIRST_MODE		(0 << 6)
+#define HDMI_I2S_LSB_FIRST_MODE		(1 << 6)
+#define HDMI_I2S_BIT_CH_32FS		(0 << 4)
+#define HDMI_I2S_BIT_CH_48FS		(1 << 4)
+#define HDMI_I2S_BIT_CH_RESERVED		(2 << 4)
+#define HDMI_I2S_SDATA_16BIT		(1 << 2)
+#define HDMI_I2S_SDATA_20BIT		(2 << 2)
+#define HDMI_I2S_SDATA_24BIT		(3 << 2)
+#define HDMI_I2S_BASIC_FORMAT		(0)
+#define HDMI_I2S_L_JUST_FORMAT		(2)
+#define HDMI_I2S_R_JUST_FORMAT		(3)
+#define HDMI_I2S_CON_2_CLR			(~0xFF)
+#define HDMI_I2S_SET_BIT_CH(x)		(((x) & 0x7) << 4)
+#define HDMI_I2S_SET_SDATA_BIT(x)		(((x) & 0x7) << 2)
+
+/* I2S_PIN_SEL_0 */
+#define HDMI_I2S_SEL_SCLK(x)		(((x) & 0x7) << 4)
+#define HDMI_I2S_SEL_SCLK_DEFAULT_1		(0x7 << 4)
+#define HDMI_I2S_SEL_LRCK(x)		((x) & 0x7)
+#define HDMI_I2S_SEL_LRCK_DEFAULT_0		(0x7)
+
+/* I2S_PIN_SEL_1 */
+#define HDMI_I2S_SEL_SDATA1(x)		(((x) & 0x7) << 4)
+#define HDMI_I2S_SEL_SDATA1_DEFAULT_3	(0x7 << 4)
+#define HDMI_I2S_SEL_SDATA2(x)		((x) & 0x7)
+#define HDMI_I2S_SEL_SDATA2_DEFAULT_2	(0x7)
+
+/* I2S_PIN_SEL_2 */
+#define HDMI_I2S_SEL_SDATA3(x)		(((x) & 0x7) << 4)
+#define HDMI_I2S_SEL_SDATA3_DEFAULT_5	(0x7 << 4)
+#define HDMI_I2S_SEL_SDATA2(x)		((x) & 0x7)
+#define HDMI_I2S_SEL_SDATA2_DEFAULT_4	(0x7)
+
+/* I2S_PIN_SEL_3 */
+#define HDMI_I2S_SEL_DSD(x)			((x) & 0x7)
+#define HDMI_I2S_SEL_DSD_DEFAULT_6		(0x7)
+
+/* I2S_DSD_CON */
+#define HDMI_I2S_DSD_CLK_RI_EDGE		(1 << 1)
+#define HDMI_I2S_DSD_CLK_FA_EDGE		(0 << 1)
+#define HDMI_I2S_DSD_ENABLE			(1)
+#define HDMI_I2S_DSD_DISABLE		(0)
+
+/* I2S_MUX_CON */
+#define HDMI_I2S_NOISE_FILTER_ZERO		(0 << 5)
+#define HDMI_I2S_NOISE_FILTER_2_STAGE	(1 << 5)
+#define HDMI_I2S_NOISE_FILTER_3_STAGE	(2 << 5)
+#define HDMI_I2S_NOISE_FILTER_4_STAGE	(3 << 5)
+#define HDMI_I2S_NOISE_FILTER_5_STAGE	(4 << 5)
+#define HDMI_I2S_IN_DISABLE			(1 << 4)
+#define HDMI_I2S_IN_ENABLE			(0 << 4)
+#define HDMI_I2S_AUD_SPDIF			(0 << 2)
+#define HDMI_I2S_AUD_I2S			(1 << 2)
+#define HDMI_I2S_AUD_DSD			(2 << 2)
+#define HDMI_I2S_CUV_SPDIF_ENABLE		(0 << 1)
+#define HDMI_I2S_CUV_I2S_ENABLE		(1 << 1)
+#define HDMI_I2S_MUX_DISABLE		(0)
+#define HDMI_I2S_MUX_ENABLE			(1)
+#define HDMI_I2S_MUX_CON_CLR		(~0xFF)
+
+/* I2S_CH_ST_CON */
+#define HDMI_I2S_CH_STATUS_RELOAD		(1)
+#define HDMI_I2S_CH_ST_CON_CLR		(~1)
+
+/* I2S_CH_ST_0 / I2S_CH_ST_SH_0 */
+#define HDMI_I2S_CH_STATUS_MODE_0		(0 << 6)
+#define HDMI_I2S_2AUD_CH_WITHOUT_PREEMPH	(0 << 3)
+#define HDMI_I2S_2AUD_CH_WITH_PREEMPH	(1 << 3)
+#define HDMI_I2S_DEFAULT_EMPHASIS		(0 << 3)
+#define HDMI_I2S_COPYRIGHT			(0 << 2)
+#define HDMI_I2S_NO_COPYRIGHT		(1 << 2)
+#define HDMI_I2S_LINEAR_PCM			(0 << 1)
+#define HDMI_I2S_NO_LINEAR_PCM		(1 << 1)
+#define HDMI_I2S_CONSUMER_FORMAT		(0)
+#define HDMI_I2S_PROF_FORMAT		(1)
+#define HDMI_I2S_CH_ST_0_CLR		(~0xFF)
+
+/* I2S_CH_ST_1 / I2S_CH_ST_SH_1 */
+#define HDMI_I2S_CD_PLAYER			(0x00)
+#define HDMI_I2S_DAT_PLAYER			(0x03)
+#define HDMI_I2S_DCC_PLAYER			(0x43)
+#define HDMI_I2S_MINI_DISC_PLAYER		(0x49)
+
+/* I2S_CH_ST_2 / I2S_CH_ST_SH_2 */
+#define HDMI_I2S_CHANNEL_NUM_MASK		(0xF << 4)
+#define HDMI_I2S_SOURCE_NUM_MASK		(0xF)
+#define HDMI_I2S_SET_CHANNEL_NUM(x)		((x) & (0xF) << 4)
+#define HDMI_I2S_SET_SOURCE_NUM(x)		((x) & (0xF))
+
+/* I2S_CH_ST_3 / I2S_CH_ST_SH_3 */
+#define HDMI_I2S_CLK_ACCUR_LEVEL_1		(1 << 4)
+#define HDMI_I2S_CLK_ACCUR_LEVEL_2		(0 << 4)
+#define HDMI_I2S_CLK_ACCUR_LEVEL_3		(2 << 4)
+#define HDMI_I2S_SAMPLING_FREQ_44_1		(0x0)
+#define HDMI_I2S_SAMPLING_FREQ_48		(0x2)
+#define HDMI_I2S_SAMPLING_FREQ_32		(0x3)
+#define HDMI_I2S_SAMPLING_FREQ_96		(0xA)
+#define HDMI_I2S_SET_SAMPLING_FREQ(x)	((x) & (0xF))
+
+/* I2S_CH_ST_4 / I2S_CH_ST_SH_4 */
+#define HDMI_I2S_ORG_SAMPLING_FREQ_44_1	(0xF << 4)
+#define HDMI_I2S_ORG_SAMPLING_FREQ_88_2	(0x7 << 4)
+#define HDMI_I2S_ORG_SAMPLING_FREQ_22_05	(0xB << 4)
+#define HDMI_I2S_ORG_SAMPLING_FREQ_176_4	(0x3 << 4)
+#define HDMI_I2S_WORD_LENGTH_NOT_DEFINE	(0x0 << 1)
+#define HDMI_I2S_WORD_LENGTH_MAX24_20BITS	(0x1 << 1)
+#define HDMI_I2S_WORD_LENGTH_MAX24_22BITS	(0x2 << 1)
+#define HDMI_I2S_WORD_LENGTH_MAX24_23BITS	(0x4 << 1)
+#define HDMI_I2S_WORD_LENGTH_MAX24_24BITS	(0x5 << 1)
+#define HDMI_I2S_WORD_LENGTH_MAX24_21BITS	(0x6 << 1)
+#define HDMI_I2S_WORD_LENGTH_MAX20_16BITS	(0x1 << 1)
+#define HDMI_I2S_WORD_LENGTH_MAX20_18BITS	(0x2 << 1)
+#define HDMI_I2S_WORD_LENGTH_MAX20_19BITS	(0x4 << 1)
+#define HDMI_I2S_WORD_LENGTH_MAX20_20BITS	(0x5 << 1)
+#define HDMI_I2S_WORD_LENGTH_MAX20_17BITS	(0x6 << 1)
+#define HDMI_I2S_WORD_LENGTH_MAX_24BITS	(1)
+#define HDMI_I2S_WORD_LENGTH_MAX_20BITS	(0)
+
+/* I2S_VD_DATA */
+#define HDMI_I2S_VD_AUD_SAMPLE_RELIABLE	(0)
+#define HDMI_I2S_VD_AUD_SAMPLE_UNRELIABLE	(1)
+
+/* I2S_MUX_CH */
+#define HDMI_I2S_CH3_R_EN			(1 << 7)
+#define HDMI_I2S_CH3_L_EN			(1 << 6)
+#define HDMI_I2S_CH3_EN			(3 << 6)
+#define HDMI_I2S_CH2_R_EN			(1 << 5)
+#define HDMI_I2S_CH2_L_EN			(1 << 4)
+#define HDMI_I2S_CH2_EN			(3 << 4)
+#define HDMI_I2S_CH1_R_EN			(1 << 3)
+#define HDMI_I2S_CH1_L_EN			(1 << 2)
+#define HDMI_I2S_CH1_EN			(3 << 2)
+#define HDMI_I2S_CH0_R_EN			(1 << 1)
+#define HDMI_I2S_CH0_L_EN			(1)
+#define HDMI_I2S_CH0_EN			(3)
+#define HDMI_I2S_CH_ALL_EN			(0xFF)
+#define HDMI_I2S_MUX_CH_CLR			(~HDMI_I2S_CH_ALL_EN)
+
+/* I2S_MUX_CUV */
+#define HDMI_I2S_CUV_R_EN			(1 << 1)
+#define HDMI_I2S_CUV_L_EN			(1)
+#define HDMI_I2S_CUV_RL_EN			(0x03)
+
+/* I2S_IRQ_MASK */
+#define HDMI_I2S_INT2_DIS			(0 << 1)
+#define HDMI_I2S_INT2_EN			(1 << 1)
+
+/* I2S_IRQ_STATUS */
+#define HDMI_I2S_INT2_STATUS		(1 << 1)
+
+/* I2S_CH0_L_0 */
+/* I2S_CH0_L_1 */
+/* I2S_CH0_L_2 */
+/* I2S_CH0_L_3 */
+/* I2S_CH0_R_0 */
+/* I2S_CH0_R_1 */
+/* I2S_CH0_R_2 */
+/* I2S_CH0_R_3 */
+/* I2S_CH1_L_0 */
+/* I2S_CH1_L_1 */
+/* I2S_CH1_L_2 */
+/* I2S_CH1_L_3 */
+/* I2S_CH1_R_0 */
+/* I2S_CH1_R_1 */
+/* I2S_CH1_R_2 */
+/* I2S_CH1_R_3 */
+/* I2S_CH2_L_0 */
+/* I2S_CH2_L_1 */
+/* I2S_CH2_L_2 */
+/* I2S_CH2_L_3 */
+/* I2S_CH2_R_0 */
+/* I2S_CH2_R_1 */
+/* I2S_CH2_R_2 */
+/* I2S_Ch2_R_3 */
+/* I2S_CH3_L_0 */
+/* I2S_CH3_L_1 */
+/* I2S_CH3_L_2 */
+/* I2S_CH3_R_0 */
+/* I2S_CH3_R_1 */
+/* I2S_CH3_R_2 */
+
+/* I2S_CUV_L_R */
+#define HDMI_I2S_CUV_R_DATA_MASK		(0x7 << 4)
+#define HDMI_I2S_CUV_L_DATA_MASK		(0x7)
+
+
+/* Timing Generator Register */
+/* TG_CMD */
+#define HDMI_GETSYNC_TYPE_EN		(1 << 4)
+#define HDMI_GETSYNC_TYPE_DIS		(~HDMI_GETSYNC_TYPE_EN)
+#define HDMI_GETSYNC_EN			(1 << 3)
+#define HDMI_GETSYNC_DIS			(~HDMI_GETSYNC_EN)
+#define HDMI_FIELD_EN			(1 << 1)
+#define HDMI_FIELD_DIS			(~HDMI_FIELD_EN)
+#define HDMI_TG_EN				(1)
+#define HDMI_TG_DIS				(~HDMI_TG_EN)
+
+/* TG_CFG */
+/* TG_CB_SZ */
+/* TG_INDELAY_L */
+/* TG_INDELAY_H */
+/* TG_POL_CTRL */
+
+/* TG_H_FSZ_L */
+#define HDMI_SET_TG_H_FSZ_L(x)		((x) & 0xFF)
+
+/* TG_H_FSZ_H */
+#define HDMI_SET_TG_H_FSZ_H(x)		(((x) >> 8) & 0x1F)
+
+/* TG_HACT_ST_L */
+#define HDMI_SET_TG_HACT_ST_L(x)		((x) & 0xFF)
+
+/* TG_HACT_ST_H */
+#define HDMI_SET_TG_HACT_ST_H(x)		(((x) >> 8) & 0xF)
+
+/* TG_HACT_SZ_L */
+#define HDMI_SET_TG_HACT_SZ_L(x)		((x) & 0xFF)
+
+/* TG_HACT_SZ_H */
+#define HDMI_SET_TG_HACT_SZ_H(x)		(((x) >> 8) & 0xF)
+
+/* TG_V_FSZ_L */
+#define HDMI_SET_TG_V_FSZ_L(x)		((x) & 0xFF)
+
+/* TG_V_FSZ_H */
+#define HDMI_SET_TG_V_FSZ_H(x)		(((x) >> 8) & 0x7)
+
+/* TG_VSYNC_L */
+#define HDMI_SET_TG_VSYNC_L(x)		((x) & 0xFF)
+
+/* TG_VSYNC_H */
+#define HDMI_SET_TG_VSYNC_H(x)		(((x) >> 8) & 0x7)
+
+/* TG_VSYNC2_L */
+#define HDMI_SET_TG_VSYNC2_L(x)		((x) & 0xFF)
+
+/* TG_VSYNC2_H */
+#define HDMI_SET_TG_VSYNC2_H(x)		(((x) >> 8) & 0x7)
+
+/* TG_VACT_ST_L */
+#define HDMI_SET_TG_VACT_ST_L(x)		((x) & 0xFF)
+
+/* TG_VACT_ST_H */
+#define HDMI_SET_TG_VACT_ST_H(x)		(((x) >> 8) & 0x7)
+
+/* TG_VACT_SZ_L */
+#define HDMI_SET_TG_VACT_SZ_L(x)		((x) & 0xFF)
+
+/* TG_VACT_SZ_H */
+#define HDMI_SET_TG_VACT_SZ_H(x)		(((x) >> 8) & 0x7)
+
+/* TG_FIELD_CHG_L */
+#define HDMI_SET_TG_FIELD_CHG_L(x)		((x) & 0xFF)
+
+/* TG_FIELD_CHG_H */
+#define HDMI_SET_TG_FIELD_CHG_H(x)		(((x) >> 8) & 0x7)
+
+/* TG_VACT_ST2_L */
+#define HDMI_SET_TG_VACT_ST2_L(x)		((x) & 0xFF)
+
+/* TG_VACT_ST2_H */
+#define HDMI_SET_TG_VACT_ST2_H(x)		(((x) >> 8) & 0x7)
+
+/* TG_VACT_SC_ST_L */
+/* TG_VACT_SC_ST_H */
+/* TG_VACT_SC_SZ_L */
+/* TG_VACT_SC_SZ_H */
+
+/* TG_VSYNC_TOP_HDMI_L */
+#define HDMI_SET_TG_VSYNC_TOP_HDMI_L(x)	((x) & 0xFF)
+
+/* TG_VSYNC_TOP_HDMI_H */
+#define HDMI_SET_TG_VSYNC_TOP_HDMI_H(x)	(((x) >> 8) & 0x7)
+
+/* TG_VSYNC_BOT_HDMI_L */
+#define HDMI_SET_TG_VSYNC_BOT_HDMI_L(x)	((x) & 0xFF)
+
+/* TG_VSYNC_BOT_HDMI_H */
+#define HDMI_SET_TG_VSYNC_BOT_HDMI_H(x)	(((x) >> 8) & 0x7)
+
+/* TG_FIELD_TOP_HDMI_L */
+#define HDMI_SET_TG_FIELD_TOP_HDMI_L(x)	((x) & 0xFF)
+
+/* TG_FIELD_TOP_HDMI_H */
+#define HDMI_SET_TG_FIELD_TOP_HDMI_H(x)	(((x) >> 8) & 0x7)
+
+/* TG_FIELD_BOT_HDMI_L */
+#define HDMI_SET_TG_FIELD_BOT_HDMI_L(x)	((x) & 0xFF)
+
+/* TG_FIELD_BOT_HDMI_H */
+#define HDMI_SET_TG_FIELD_BOT_HDMI_H(x)	(((x) >> 8) & 0x7)
+
+/* TG_HSYNC_HDOUT_ST_L */
+/* TG_HSYNC_HDOUT_ST_H */
+/* TG_HSYNC_HDOUT_END_L */
+/* TG_HSYNC_HDOUT_END_H */
+/* TG_VSYNC_HDOUT_ST_L */
+/* TG_VSYNC_HDOUT_ST_H */
+/* TG_VSYNC_HDOUT_END_L */
+/* TG_VSYNC_HDOUT_END_H */
+/* TG_VSYNC_HDOUT_DLY_L */
+/* TG_VSYNC_HDOUT_DLY_H */
+/* TG_BT_ERR_RANGE */
+/* TG_BT_ERR_RESULT */
+/* TG_COR_THR */
+/* TG_COR_NUM */
+/* TG_BT_CON */
+/* TG_BT_H_FSZ_L */
+/* TG_BT_H_FSZ_H */
+/* TG_BT_HSYNC_ST */
+/* TG_BT_HSYNC_SZ */
+/* TG_BT_FSZ_L */
+/* TG_BT_FSZ_H */
+/* TG_BT_VACT_T_ST_L */
+/* TG_BT_VACT_T_ST_H */
+/* TG_BT_VACT_B_ST_L */
+/* TG_BT_VACT_B_ST_H */
+/* TG_BT_VACT_SZ_L */
+/* TG_BT_VACT_SZ_H */
+/* TG_BT_VSYNC_SZ */
+
+
+/* HDCP E-FUSE Control Register */
+/* HDCP_E_FUSE_CTRL */
+#define HDMI_EFUSE_CTRL_HDCP_KEY_READ	(1)
+
+/* HDCP_E_FUSE_STATUS */
+#define HDMI_EFUSE_ECC_FAIL			(1 << 2)
+#define HDMI_EFUSE_ECC_BUSY			(1 << 1)
+#define HDMI_EFUSE_ECC_DONE			(1)
+
+/* EFUSE_ADDR_WIDTH */
+/* EFUSE_SIGDEV_ASSERT */
+/* EFUSE_SIGDEV_DE-ASSERT */
+/* EFUSE_PRCHG_ASSERT */
+/* EFUSE_PRCHG_DE-ASSERT */
+/* EFUSE_FSET_ASSERT */
+/* EFUSE_FSET_DE-ASSERT */
+/* EFUSE_SENSING */
+/* EFUSE_SCK_ASSERT */
+/* EFUSE_SCK_DEASSERT */
+/* EFUSE_SDOUT_OFFSET */
+/* EFUSE_READ_OFFSET */
+
+/* HDCP_SHA_RESULT, Not support in s5pv210 */
+/* Not support in s5pv210 */
+#define HDMI_HDCP_SHA_VALID_NO_RD		(0 << 1)
+/* Not support in s5pv210 */
+#define HDMI_HDCP_SHA_VALID_RD		(1 << 1)
+/* Not support in s5pv210 */
+#define HDMI_HDCP_SHA_VALID			(1)
+/* Not support in s5pv210 */
+#define HDMI_HDCP_SHA_NO_VALID		(0)
+
+/* DC_CONTRAL */
+/*Not support in S5PV210 */
+#define HDMI_DC_CTL_12			(1 << 1)
+/*Not support in S5PV210 */
+#define HDMI_DC_CTL_8			(0)
+/*Not support in S5PV210 */
+#define HDMI_DC_CTL_10			(1)
+#endif /* __ASM_ARCH_REGS_HDMI_H */
diff --git a/drivers/media/video/s5p-tv/regs-vmx.h b/drivers/media/video/s5p-tv/regs-vmx.h
new file mode 100644
index 0000000..8f5edc1
--- /dev/null
+++ b/drivers/media/video/s5p-tv/regs-vmx.h
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2010 Samsung Electronics
+ * http://www.samsung.com/
+ *
+ * Mixer register header file for Samsung Mixer driver
+ *
+ * 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 __ASM_ARCH_REGS_VMX_H
+#define __ASM_ARCH_REGS_VMX_H
+
+/*
+ * Register part
+ */
+#define MXR_STATUS			(0x0000)
+#define MXR_CFG				(0x0004)
+#define MXR_INT_EN			(0x0008)
+#define MXR_INT_STATUS			(0x000C)
+#define MXR_LAYER_CFG			(0x0010)
+#define MXR_VIDEO_CFG			(0x0014)
+#define MXR_GRAPHIC0_CFG		(0x0020)
+#define MXR_GRAPHIC0_BASE		(0x0024)
+#define MXR_GRAPHIC0_SPAN		(0x0028)
+#define MXR_GRAPHIC0_SXY		(0x002C)
+#define MXR_GRAPHIC0_WH			(0x0030)
+#define MXR_GRAPHIC0_DXY		(0x0034)
+#define MXR_GRAPHIC0_BLANK		(0x0038)
+#define MXR_GRAPHIC1_CFG		(0x0040)
+#define MXR_GRAPHIC1_BASE		(0x0044)
+#define MXR_GRAPHIC1_SPAN		(0x0048)
+#define MXR_GRAPHIC1_SXY		(0x004C)
+#define MXR_GRAPHIC1_WH			(0x0050)
+#define MXR_GRAPHIC1_DXY		(0x0054)
+#define MXR_GRAPHIC1_BLANK		(0x0058)
+#define MXR_BG_CFG			(0x0060)
+#define MXR_BG_COLOR0			(0x0064)
+#define MXR_BG_COLOR1			(0x0068)
+#define MXR_BG_COLOR2			(0x006C)
+#define MXR_CM_COEFF_Y			(0x0080)
+#define MXR_CM_COEFF_CB			(0x0084)
+#define MXR_CM_COEFF_CR			(0x0088)
+#define MXR_VER				(0x0100)
+
+/* for parametrized access to registers */
+#define MXR_GRAPHIC_CFG(i)		(0x0020 + (i) * 0x20)
+#define MXR_GRAPHIC_BASE(i)		(0x0024 + (i) * 0x20)
+#define MXR_GRAPHIC_SPAN(i)		(0x0028 + (i) * 0x20)
+#define MXR_GRAPHIC_SXY(i)		(0x002C + (i) * 0x20)
+#define MXR_GRAPHIC_WH(i)		(0x0030 + (i) * 0x20)
+#define MXR_GRAPHIC_DXY(i)		(0x0034 + (i) * 0x20)
+#define MXR_GRAPHIC_BLANK(i)		(0x0038 + (i) * 0x20)
+
+/* Shadow registers */
+#define MXR_STATUS_S			(0x2000)
+#define MXR_CFG_S			(0x2004)
+#define MXR_LAYER_CFG_S			(0x2010)
+#define MXR_VIDEO_CFG_S			(0x2014)
+#define MXR_GRAPHIC0_CFG_S		(0x2020)
+#define MXR_GRAPHIC0_BASE_S		(0x2024)
+#define MXR_GRAPHIC0_SPAN_S		(0x2028)
+#define MXR_GRAPHIC0_SXY_S		(0x202C)
+#define MXR_GRAPHIC0_WH_S		(0x2030)
+#define MXR_GRAPHIC0_DXY_S		(0x2034)
+#define MXR_GRAPHIC0_BLANK_PIXEL_S	(0x2038)
+#define MXR_GRAPHIC1_CFG_S		(0x2040)
+#define MXR_GRAPHIC1_BASE_S		(0x2044)
+#define MXR_GRAPHIC1_SPAN_S		(0x2048)
+#define MXR_GRAPHIC1_SXY_S		(0x204C)
+#define MXR_GRAPHIC1_WH_S		(0x2050)
+#define MXR_GRAPHIC1_DXY_S		(0x2054)
+#define MXR_GRAPHIC1_BLANK_PIXEL_S	(0x2058)
+#define MXR_BG_COLOR0_S			(0x2064)
+#define MXR_BG_COLOR1_S			(0x2068)
+#define MXR_BG_COLOR2_S			(0x206C)
+
+/* for parametrized access to shadow registers */
+#define MXR_GRAPHIC_CFG_S(i)		(0x2020 + (i) * 0x20)
+#define MXR_GRAPHIC_BASE_S(i)		(0x2024 + (i) * 0x20)
+#define MXR_GRAPHIC_SPAN_S(i)		(0x2028 + (i) * 0x20)
+#define MXR_GRAPHIC_SXY_S(i)		(0x202C + (i) * 0x20)
+#define MXR_GRAPHIC_WH_S(i)		(0x2030 + (i) * 0x20)
+#define MXR_GRAPHIC_DXY_S(i)		(0x2034 + (i) * 0x20)
+#define MXR_GRAPHIC_BLANK_S(i)		(0x2038 + (i) * 0x20)
+
+/*
+ * Bit definition part
+ */
+
+#define MASK(high_bit, low_bit) \
+	(((2 << ((high_bit) - (low_bit))) - 1) << (low_bit))
+
+#define MASK_VAL(val, high_bit, low_bit) \
+	(((val) << (low_bit)) & MASK(high_bit, low_bit))
+
+/* MIXER_STATUS */
+#define MXR_STATUS_16_BURST		(1 << 7)
+#define MXR_STATUS_8_BURST		(0 << 7)
+#define MXR_STATUS_BURST_MASK		(1 << 7)
+#define MXR_STATUS_LITTLE_ENDIAN	(0 << 3)
+#define MXR_STATUS_BIG_ENDIAN		(1 << 3)
+#define MXR_STATUS_SYNC_ENABLE		(1 << 2)
+#define MXR_STATUS_OPERATING		(0 << 1)
+#define MXR_STATUS_IDLE_MODE		(1 << 1)
+#define MXR_STATUS_OPERATION_STATUS	(1 << 1)
+#define MXR_STATUS_REG_RUN		(1 << 0)
+
+/* MIXER_CFG */
+#define MXR_CFG_OUT_YUV444		(0 << 8)
+#define MXR_CFG_OUT_RGB888		(1 << 8)
+#define MXR_CFG_DST_TV			(0 << 7)
+#define MXR_CFG_DST_HDMI		(1 << 7)
+#define MXR_CFG_HD_720			(0 << 6)
+#define MXR_CFG_HD_1080			(1 << 6)
+#define MXR_CFG_GRP1_ENABLE		(1 << 5)
+#define MXR_CFG_GRP0_ENABLE		(1 << 4)
+#define MXR_CFG_VP_ENABLE		(1 << 3)
+#define MXR_CFG_SCAN_INTERLACE		(0 << 2)
+#define MXR_CFG_SCAN_PROGRASSIVE	(1 << 2)
+#define MXR_CFG_NTSC			(0 << 1)
+#define MXR_CFG_PAL			(1 << 1)
+#define MXR_CFG_SD			(0 << 0)
+#define MXR_CFG_HD			(1 << 0)
+#define MXR_CFG_SCAN_MASK		0x47
+
+/* MIXER_INT_EN */
+#define MXR_INT_EN_VSYNC		(1 << 11)
+#define MXR_INT_EN_VP			(1 << 10)
+#define MXR_INT_EN_GRP1			(1 << 9)
+#define MXR_INT_EN_GRP0			(1 << 8)
+#define MXR_INT_EN_ALL			(0x0f << 8)
+
+/* MIXER_INT_STATUS */
+#define MXR_INT_CLEAR_VSYNC		(1 << 11)
+#define MXR_INT_STATUS_VP		(1 << 10)
+#define MXR_INT_STATUS_GRP1		(1 << 9)
+#define MXR_INT_STATUS_GRP0		(1 << 8)
+#define MXR_INT_STATUS_VSYNC		(1 << 0)
+
+/* MIXER_LAYER_CFG */
+#define MXR_LAYER_CFG_GRP1_VAL(x)	MASK_VAL(x, 11, 8)
+#define MXR_LAYER_CFG_GRP1_HIDE		MASK_VAL(0, 11, 8)
+#define MXR_LAYER_CFG_GRP0_VAL(x)	MASK_VAL(x, 7, 4)
+#define MXR_LAYER_CFG_GRP0_HIDE		MASK_VAL(0, 7, 4)
+#define MXR_LAYER_CFG_VP_VAL(x)		MASK_VAL(x, 3, 0)
+#define MXR_LAYER_CFG_VP_HIDE		MASK_VAL(0, 3, 0)
+
+/* MIXER_VIDEO_CFG */
+#define MXR_VP_CFG_LIMITER_EN		(1 << 17)
+#define MXR_VP_CFG_BLEND_EN		(1 << 16)
+#define MXR_VP_CFG_ALPHA_VAL(x)		MASK_VAL(x, 7, 0)
+
+/* MIXER_GRAPHICn_CFG */
+#define MXR_GRP_CFG_COLOR_KEY_DISABLE	(1 << 21)
+#define MXR_GRP_CFG_BLEND_PRE_MUL	(1 << 20)
+#define MXR_GRP_CFG_BLEND_NORMAL	(0 << 20)
+#define MXR_GRP_CFG_WIN_BLEND		(1 << 17)
+#define MXR_GRP_CFG_PIXEL_BLEND		(1 << 16)
+#define MXR_GRP_CFG_FORMAT_VAL(x)	MASK_VAL(x, 11, 8)
+#define MXR_GRP_CFG_FORMAT_MASK		MXR_GRP_CFG_FORMAT_VAL(~0)
+#define MXR_GRP_CFG_ALPHA_VAL(x)	MASK_VAL(x, 7, 0)
+
+/* MIXER_GRAPHICn_WH */
+#define MXR_GRP_WH_H_SCALE(x)		MASK_VAL(x, 28, 28)
+#define MXR_GRP_WH_V_SCALE(x)		MASK_VAL(x, 12, 12)
+#define MXR_GRP_WH_WIDTH(x)		MASK_VAL(x, 26, 16)
+#define MXR_GRP_WH_HEIGHT(x)		MASK_VAL(x, 10, 0)
+
+/* MIXER_GRAPHICn_XY */
+#define MXR_GRP_SXY_SX(x)		MASK_VAL(x, 26, 16)
+#define MXR_GRP_SXY_SY(x)		MASK_VAL(x, 10, 0)
+
+/* MIXER_GRAPHICn_DXY */
+#define MXR_GRP_DXY_DX(x)		MASK_VAL(x, 26, 16)
+#define MXR_GRP_DXY_DY(x)		MASK_VAL(x, 10, 0)
+
+/* MIXER_BG_CFG, Not supported in S5PV210 */
+#define MXR_BG_CR_DIHER			(1 << 19)
+#define MXR_BG_CB_DIHER			(1 << 18)
+#define MXR_BG_Y_DIHER			(1 << 17)
+
+/* MIXER_BG_COLOR0/1/2 */
+#define MXR_BG_Y(x)			MASK_VAL(x, 23, 16)
+#define MXR_BG_CB(x)			MASK_VAL(x, 15, 8)
+#define MXR_BG_CR(x)			MASK_VAL(x, 7, 0)
+
+/* MIXER_CM_COEFF_{Y/CB/CR} */
+#define MXR_CM_COLOR_WIDE		(1 << 30)
+#define MXR_CM_COLOR_NARROW		(0 << 30)
+#define MXR_CM_COEF0(x)			MASK_VAL(x, 29, 20)
+#define MXR_CM_COEF1(x)			MASK_VAL(x, 19, 10)
+#define MXR_CM_COEF2(x)			MASK_VAL(x, 9, 0)
+
+#endif /* __ASM_ARCH_REGS_VMX_H */
+
diff --git a/drivers/media/video/s5p-tv/regs-vp.h b/drivers/media/video/s5p-tv/regs-vp.h
new file mode 100644
index 0000000..f06dbb6
--- /dev/null
+++ b/drivers/media/video/s5p-tv/regs-vp.h
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2010 Samsung Electronics
+ *		http://www.samsung.com/
+ *
+ * Video processor register header file for Samsung Mixer driver
+ *
+ * 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 __ARCH_ARM_REGS_VP_H
+#define __ARCH_ARM_REGS_VP_H
+
+/*
+ * Register part
+ */
+#define VP_ENABLE			(0x0000)
+#define VP_SRESET			(0x0004)
+#define VP_SHADOW_UPDATE		(0x0008)
+#define VP_FIELD_ID			(0x000C)
+#define VP_MODE				(0x0010)
+#define VP_IMG_SIZE_Y			(0x0014)
+#define VP_IMG_SIZE_C			(0x0018)
+#define VP_PER_RATE_CTRL		(0x001C)
+#define VP_TOP_Y_PTR			(0x0028)
+#define VP_BOT_Y_PTR			(0x002C)
+#define VP_TOP_C_PTR			(0x0030)
+#define VP_BOT_C_PTR			(0x0034)
+#define VP_ENDIAN_MODE			(0x03CC)
+#define VP_SRC_H_POSITION		(0x0044)
+#define VP_SRC_V_POSITION		(0x0048)
+#define VP_SRC_WIDTH			(0x004C)
+#define VP_SRC_HEIGHT			(0x0050)
+#define VP_DST_H_POSITION		(0x0054)
+#define VP_DST_V_POSITION		(0x0058)
+#define VP_DST_WIDTH			(0x005C)
+#define VP_DST_HEIGHT			(0x0060)
+#define VP_H_RATIO			(0x0064)
+#define VP_V_RATIO			(0x0068)
+#define VP_POLY8_Y0_LL			(0x006C)
+#define VP_POLY8_Y0_LH			(0x0070)
+#define VP_POLY8_Y0_HL			(0x0074)
+#define VP_POLY8_Y0_HH			(0x0078)
+#define VP_POLY8_Y1_LL			(0x007C)
+#define VP_POLY8_Y1_LH			(0x0080)
+#define VP_POLY8_Y1_HL			(0x0084)
+#define VP_POLY8_Y1_HH			(0x0088)
+#define VP_POLY8_Y2_LL			(0x008C)
+#define VP_POLY8_Y2_LH			(0x0090)
+#define VP_POLY8_Y2_HL			(0x0094)
+#define VP_POLY8_Y2_HH			(0x0098)
+#define VP_POLY8_Y3_LL			(0x009C)
+#define VP_POLY8_Y3_LH			(0x00A0)
+#define VP_POLY8_Y3_HL			(0x00A4)
+#define VP_POLY8_Y3_HH			(0x00A8)
+#define VP_POLY4_Y0_LL			(0x00EC)
+#define VP_POLY4_Y0_LH			(0x00F0)
+#define VP_POLY4_Y0_HL			(0x00F4)
+#define VP_POLY4_Y0_HH			(0x00F8)
+#define VP_POLY4_Y1_LL			(0x00FC)
+#define VP_POLY4_Y1_LH			(0x0100)
+#define VP_POLY4_Y1_HL			(0x0104)
+#define VP_POLY4_Y1_HH			(0x0108)
+#define VP_POLY4_Y2_LL			(0x010C)
+#define VP_POLY4_Y2_LH			(0x0110)
+#define VP_POLY4_Y2_HL			(0x0114)
+#define VP_POLY4_Y2_HH			(0x0118)
+#define VP_POLY4_Y3_LL			(0x011C)
+#define VP_POLY4_Y3_LH			(0x0120)
+#define VP_POLY4_Y3_HL			(0x0124)
+#define VP_POLY4_Y3_HH			(0x0128)
+#define VP_POLY4_C0_LL			(0x012C)
+#define VP_POLY4_C0_LH			(0x0130)
+#define VP_POLY4_C0_HL			(0x0134)
+#define VP_POLY4_C0_HH			(0x0138)
+#define VP_POLY4_C1_LL			(0x013C)
+#define VP_POLY4_C1_LH			(0x0140)
+#define VP_POLY4_C1_HL			(0x0144)
+#define VP_POLY4_C1_HH			(0x0148)
+#define VP_FIELD_ID_S			(0x016C)
+#define VP_MODE_S			(0x0170)
+#define VP_IMG_SIZE_Y_S			(0x0174)
+#define VP_IMG_SIZE_C_S			(0x0178)
+#define VP_TOP_Y_PTR_S			(0x0190)
+#define VP_BOT_Y_PTR_S			(0x0194)
+#define VP_TOP_C_PTR_S			(0x0198)
+#define VP_BOT_C_PTR_S			(0x019C)
+#define VP_SRC_H_POSITION_S		(0x01AC)
+#define VP_SRC_V_POSITION_S		(0x01B0)
+#define VP_SRC_WIDTH_S			(0x01B4)
+#define VP_SRC_HEIGHT_S			(0x01B8)
+#define VP_DST_H_POSITION_S		(0x01BC)
+#define VP_DST_V_POSITION_S		(0x01C0)
+#define VP_DST_WIDTH_S			(0x01C4)
+#define VP_DST_HEIGHT_S			(0x01C8)
+#define VP_H_RATIO_S			(0x01CC)
+#define VP_V_RATIO_S			(0x01D0)
+#define VP_PP_CSC_Y2Y_COEF		(0x01D4)
+#define VP_PP_CSC_CB2Y_COEF		(0x01D8)
+#define VP_PP_CSC_CR2Y_COEF		(0x01DC)
+#define VP_PP_CSC_Y2CB_COEF		(0x01E0)
+#define VP_PP_CSC_CB2CB_COEF		(0x01E4)
+#define VP_PP_CSC_CR2CB_COEF		(0x01E8)
+#define VP_PP_CSC_Y2CR_COEF		(0x01EC)
+#define VP_PP_CSC_CB2CR_COEF		(0x01F0)
+#define VP_PP_CSC_CR2CR_COEF		(0x01F4)
+#define VP_PP_BYPASS			(0x0200)
+#define VP_PP_SATURATION		(0x020C)
+#define VP_PP_SHARPNESS			(0x0210)
+#define VP_PP_LINE_EQ0			(0x0218)
+#define VP_PP_LINE_EQ1			(0x021C)
+#define VP_PP_LINE_EQ2			(0x0220)
+#define VP_PP_LINE_EQ3			(0x0224)
+#define VP_PP_LINE_EQ4			(0x0228)
+#define VP_PP_LINE_EQ5			(0x022C)
+#define VP_PP_LINE_EQ6			(0x0230)
+#define VP_PP_LINE_EQ7			(0x0234)
+#define VP_PP_BRIGHT_OFFSET		(0x0238)
+#define VP_PP_CSC_EN			(0x023C)
+#define VP_PP_BYPASS_S			(0x0258)
+#define VP_PP_SATURATION_S		(0x025C)
+#define VP_PP_SHARPNESS_S		(0x0260)
+#define VP_PP_LINE_EQ0_S		(0x0268)
+#define VP_PP_LINE_EQ1_S		(0x026C)
+#define VP_PP_LINE_EQ2_S		(0x0270)
+#define VP_PP_LINE_EQ3_S		(0x0274)
+#define VP_PP_LINE_EQ4_S		(0x0278)
+#define VP_PP_LINE_EQ5_S		(0x027C)
+#define VP_PP_LINE_EQ6_S		(0x0280)
+#define VP_PP_LINE_EQ7_S		(0x0284)
+#define VP_PP_BRIGHT_OFFSET_S		(0x0288)
+#define VP_PP_CSC_EN_S			(0x028C)
+#define VP_PP_CSC_Y2Y_COEF_S		(0x0290)
+#define VP_PP_CSC_CB2Y_COEF_S		(0x0294)
+#define VP_PP_CSC_CR2Y_COEF_S		(0x0298)
+#define VP_PP_CSC_Y2CB_COEF_S		(0x029C)
+#define VP_PP_CSC_CB2CB_COEF_S		(0x02A0)
+#define VP_PP_CSC_CR2CB_COEF_S		(0x02A4)
+#define VP_PP_CSC_Y2CR_COEF_S		(0x02A8)
+#define VP_PP_CSC_CB2CR_COEF_S		(0x02AC)
+#define VP_PP_CSC_CR2CR_COEF_S		(0x02B0)
+#define VP_ENDIAN_MODE_S		(0x03EC)
+#define VP_VERSION_INFO			(0x03FC)
+
+#define MASK(high_bit, low_bit) \
+	(((2 << ((high_bit) - (low_bit))) - 1) << (low_bit))
+
+#define MASK_VAL(val, high_bit, low_bit) \
+	(((val) << (low_bit)) & MASK(high_bit, low_bit))
+/*
+ * Bit definition part
+ */
+
+ /* VP_ENABLE */
+#define VP_ENABLE_ON_S			(1 << 2)
+#define VP_ENABLE_OPERATION_STATUS	(1 << 1)
+#define VP_ENABLE_ON			(1 << 0)
+
+/* VP_SRESET */
+#define VP_SRESET_PROCESSING		(1 << 0)
+
+/* VP_SHADOW_UPDATE */
+#define VP_SHADOW_UPDATE_ENABLE		(1 << 0)
+
+/* VP_FIELD_ID */
+#define VP_FIELD_ID_TOP			(0 << 0)
+#define VP_FIELD_ID_BOTTOM		(1 << 0)
+
+/* VP_MODE */
+#define VP_MODE_NV12			(0 << 6)
+#define VP_MODE_NV21			(1 << 6)
+#define VP_MODE_LINE_SKIP		(1 << 5)
+#define VP_MODE_MEM_LINEAR		(0 << 4)
+#define VP_MODE_MEM_TILED		(1 << 4)
+#define VP_MODE_FMT_MASK		(VP_MODE_NV21 | VP_MODE_MEM_TILED)
+#define VP_MODE_CROMA_EXP_TOP		(0 << 3)
+#define VP_MODE_CROMA_EXP_TOPBOT	(1 << 3)
+#define VP_MODE_FIELD_ID_AUTO_TOGGLING	(1 << 2)
+#define VP_MODE_2D_IPC			(1 << 1)
+
+/* VP_IMG_SIZE_Y */
+/* VP_IMG_SIZE_C */
+#define VP_IMG_HSIZE(x)			MASK_VAL(x, 29, 16)
+#define VP_IMG_VSIZE(x)			MASK_VAL(x, 13, 0)
+
+/* VP_ENDIAN_MODE */
+#define VP_ENDIAN_MODE_BIG		(0 << 0)
+#define VP_ENDIAN_MODE_LITTLE		(1 << 0)
+
+/* VP_SRC_H_POSITION */
+#define VP_SRC_H_POSITION_VAL(x)	MASK_VAL(x, 14, 4)
+
+/* VP_SRC_V_POSITION */
+#define VP_SRC_V_POSITION_VAL(x)	MASK_VAL(x, 10, 0)
+
+/* VP_SRC_WIDTH */
+/* VP_SRC_HEIGHT */
+#define VP_SRC_WIDTH_VAL(x)		MASK_VAL(x, 10, 0)
+#define VP_SRC_HEIGHT_VAL(x)		MASK_VAL(x, 10, 0)
+
+/* VP_DST_H_POSITION */
+/* VP_DST_V_POSITION */
+#define VP_DST_H_POSITION_VAL(x)	MASK_VAL(x, 10, 0)
+#define VP_DST_V_POSITION_VAL(x)	MASK_VAL(x, 10, 0)
+
+/* VP_DST_WIDTH */
+/* VP_DST_HEIGHT */
+#define VP_DST_WIDTH_VAL(x)		MASK_VAL(x, 10, 0)
+#define VP_DST_HEIGHT_VAL(x)		MASK_VAL(x, 10, 0)
+
+/* VP_H_RATIO */
+/* VP_V_RATIO */
+#define VP_H_RATIO_VAL(x)		MASK_VAL(x, 18, 0)
+#define VP_V_RATIO_VAL(x)		MASK_VAL(x, 18, 0)
+
+/* PP_CSC_Y2Y_COEF */
+#define PP_Y2Y_COEF_601_TO_709		(0x400)
+#define PP_Y2Y_COEF_709_TO_601		(0x400)
+
+/* PP_CSC_CB2Y_COEF */
+#define PP_CB2Y_COEF_601_TO_709		(0x879)
+#define PP_CB2Y_COEF_709_TO_601		(0x068)
+
+/* PP_CSC_CR2Y_COEF */
+#define PP_CR2Y_COEF_601_TO_709		(0x8D9)
+#define PP_CR2Y_COEF_709_TO_601		(0x0C9)
+
+/* PP_CSC_Y2CB_COEF */
+#define PP_Y2CB_COEF_601_TO_709		(0x0)
+#define PP_Y2CB_COEF_709_TO_601		(0x0)
+
+/* PP_CSC_CB2CB_COEF */
+#define PP_CB2CB_COEF_601_TO_709	(0x413)
+#define PP_CB2CB_COEF_709_TO_601	(0x3F6)
+
+/* PP_CSC_CR2CB_COEF */
+#define PP_CR2CB_COEF_601_TO_709	(0x875)
+#define PP_CR2CB_COEF_709_TO_601	(0x871)
+
+/* PP_CSC_Y2CR_COEF */
+#define PP_Y2CR_COEF_601_TO_709		(0x0)
+#define PP_Y2CR_COEF_709_TO_601		(0x0)
+
+/* PP_CSC_CB2CR_COEF */
+#define PP_CB2CR_COEF_601_TO_709	(0x04D)
+#define PP_CB2CR_COEF_709_TO_601	(0x84A)
+
+/* PP_CSC_CR2CR_COEF */
+#define PP_CR2CR_COEF_601_TO_709	(0x41A)
+#define PP_CR2CR_COEF_709_TO_601	(0xBEF)
+
+#define PP_CSC_COEF(x)			MASK_VAL(x, 11, 0)
+
+/* PP_BYPASS */
+#define VP_BY_PASS_ENABLE		(0)
+#define VP_BY_PASS_DISABLE		(1)
+
+/* PP_SATURATION */
+#define VP_SATURATION(x)		MASK_VAL(x, 7, 0)
+
+/* PP_SHARPNESS */
+#define VP_TH_HNOISE(x)			MASK_VAL(x, 15, 8)
+#define VP_SHARPNESS(x)			MASK_VAL(x, 1, 0)
+
+/* PP_LINE_EQ0 ~ 7 */
+#define VP_LINE_INTC(x)			MASK_VAL(x, 23, 8)
+#define VP_LINE_SLOPE(x)		MASK_VAL(x, 7, 0)
+
+/* PP_BRIGHT_OFFSET */
+#define VP_BRIGHT_OFFSET(x)		MASK_VAL(x, 8, 0)
+
+/* PP_CSC_EN */
+#define VP_SUB_Y_OFFSET_ENABLE		(1 << 1)
+#define VP_CSC_ENABLE			(1)
+
+#endif /* __ARCH_ARM_REGS_VP_H */
-- 
1.7.3.5


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 5/5] s5pc210: add s5p-tv to platform devices
  2011-02-08  9:30 [PATCH/RFC 0/5] HDMI driver for Samsung S5PV310 platform Tomasz Stanislawski
                   ` (3 preceding siblings ...)
  2011-02-08  9:30 ` [PATCH 4/5] s5p-tv: add driver for HDMI output on S5PC210 platform Tomasz Stanislawski
@ 2011-02-08  9:30 ` Tomasz Stanislawski
  2011-02-09  6:40   ` Kukjin Kim
  2011-02-08  9:47 ` [PATCH/RFC 0/5] HDMI driver for Samsung S5PV310 platform Hans Verkuil
  5 siblings, 1 reply; 23+ messages in thread
From: Tomasz Stanislawski @ 2011-02-08  9:30 UTC (permalink / raw)
  To: linux-media, linux-samsung-soc; +Cc: m.szyprowski, t.stanislaws, kyungmin.park

Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Reviewed-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 arch/arm/mach-s5pv310/Kconfig                   |    7 +
 arch/arm/mach-s5pv310/Makefile                  |    1 +
 arch/arm/mach-s5pv310/clock.c                   |  126 +++++++-
 arch/arm/mach-s5pv310/dev-tv.c                  |  450 +++++++++++++++++++++++
 arch/arm/mach-s5pv310/include/mach/irqs.h       |    4 +
 arch/arm/mach-s5pv310/include/mach/map.h        |   26 ++
 arch/arm/mach-s5pv310/include/mach/regs-clock.h |   15 +
 arch/arm/plat-samsung/include/plat/devs.h       |    2 +
 8 files changed, 630 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/mach-s5pv310/dev-tv.c

diff --git a/arch/arm/mach-s5pv310/Kconfig b/arch/arm/mach-s5pv310/Kconfig
index 09c4c21..e62103b 100644
--- a/arch/arm/mach-s5pv310/Kconfig
+++ b/arch/arm/mach-s5pv310/Kconfig
@@ -20,6 +20,11 @@ config S5PV310_DEV_PD
 	help
 	  Compile in platform device definitions for Power Domain
 
+config S5PV310_DEV_TV
+	bool
+	help
+	  Compile in platform device definition for TV interface
+
 config S5PV310_SETUP_I2C1
 	bool
 	help
@@ -102,6 +107,8 @@ config MACH_UNIVERSAL_C210
 	select S3C_DEV_HSMMC3
 	select S5PV310_SETUP_SDHCI
 	select S3C_DEV_I2C1
+	select S3C_DEV_I2C8
+	select S5PV310_DEV_TV
 	select S5PV310_SETUP_I2C1
 	help
 	  Machine support for Samsung Mobile Universal S5PC210 Reference
diff --git a/arch/arm/mach-s5pv310/Makefile b/arch/arm/mach-s5pv310/Makefile
index 036fb38..a234b80 100644
--- a/arch/arm/mach-s5pv310/Makefile
+++ b/arch/arm/mach-s5pv310/Makefile
@@ -32,6 +32,7 @@ obj-y					+= dev-audio.o
 obj-$(CONFIG_S5PV310_DEV_PD)		+= dev-pd.o
 obj-$(CONFIG_S5PV310_DEV_SYSMMU)	+= dev-sysmmu.o
 
+obj-$(CONFIG_S5PV310_DEV_TV)		+= dev-tv.o
 obj-$(CONFIG_S5PV310_SETUP_I2C1)	+= setup-i2c1.o
 obj-$(CONFIG_S5PV310_SETUP_I2C2)	+= setup-i2c2.o
 obj-$(CONFIG_S5PV310_SETUP_I2C3)	+= setup-i2c3.o
diff --git a/arch/arm/mach-s5pv310/clock.c b/arch/arm/mach-s5pv310/clock.c
index 6161b54..5bca261 100644
--- a/arch/arm/mach-s5pv310/clock.c
+++ b/arch/arm/mach-s5pv310/clock.c
@@ -81,6 +81,11 @@ static int s5pv310_clksrc_mask_peril1_ctrl(struct clk *clk, int enable)
 	return s5p_gatectrl(S5P_CLKSRC_MASK_PERIL1, clk, enable);
 }
 
+static int s5pv310_clksrc_mask_tv_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKSRC_MASK_TV, clk, enable);
+}
+
 static int s5pv310_clk_ip_cam_ctrl(struct clk *clk, int enable)
 {
 	return s5p_gatectrl(S5P_CLKGATE_IP_CAM, clk, enable);
@@ -116,6 +121,11 @@ static int s5pv310_clk_ip_perir_ctrl(struct clk *clk, int enable)
 	return s5p_gatectrl(S5P_CLKGATE_IP_PERIR, clk, enable);
 }
 
+static int s5pv310_clk_ip_tv_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKGATE_IP_TV, clk, enable);
+}
+
 /* Core list of CMU_CPU side */
 
 static struct clksrc_clk clk_mout_apll = {
@@ -432,6 +442,26 @@ static struct clk init_clocks_off[] = {
 		.enable		= s5pv310_clk_ip_lcd1_ctrl,
 		.ctrlbit	= (1 << 0),
 	}, {
+		.name           = "dac",
+		.id             = -1,
+		.enable         = s5pv310_clk_ip_tv_ctrl,
+		.ctrlbit        = (1 << 2),
+	}, {
+		.name           = "mixer",
+		.id             = -1,
+		.enable         = s5pv310_clk_ip_tv_ctrl,
+		.ctrlbit        = (1 << 1),
+	}, {
+		.name           = "vp",
+		.id             = -1,
+		.enable         = s5pv310_clk_ip_tv_ctrl,
+		.ctrlbit        = (1 << 0),
+	}, {
+		.name           = "hdmi",
+		.id             = -1,
+		.enable         = s5pv310_clk_ip_tv_ctrl,
+		.ctrlbit        = (1 << 3),
+	}, {
 		.name		= "hsmmc",
 		.id		= 0,
 		.parent		= &clk_aclk_133.clk,
@@ -697,6 +727,93 @@ static struct clksrc_sources clkset_mout_g2d = {
 	.nr_sources	= ARRAY_SIZE(clkset_mout_g2d_list),
 };
 
+/* --------------------------------------
+ *         TV subsystem CLOCKS
+ * --------------------------------------
+ */
+
+static struct clk *clkset_sclk_dac_list[] = {
+	[0] = &clk_sclk_vpll.clk,
+	[1] = &clk_sclk_hdmiphy,
+};
+
+static struct clksrc_sources clkset_sclk_dac = {
+	.sources	= clkset_sclk_dac_list,
+	.nr_sources	= ARRAY_SIZE(clkset_sclk_dac_list),
+};
+
+static struct clksrc_clk clk_sclk_dac = {
+	.clk		= {
+		.name		= "sclk_dac",
+		.id		= -1,
+		.enable		= s5pv310_clksrc_mask_tv_ctrl,
+		.ctrlbit	= (1 << 8),
+	},
+	.sources = &clkset_sclk_dac,
+	.reg_src = { .reg = S5P_CLKSRC_TV, .shift = 8, .size = 1 },
+};
+
+static struct clksrc_clk clk_sclk_pixel  = {
+	.clk		= {
+		.name		= "sclk_pixel",
+		.id		= -1,
+		.parent = &clk_sclk_vpll.clk,
+	},
+	.reg_div = { .reg = S5P_CLKDIV_TV, .shift = 0, .size = 4 },
+};
+
+static struct clk *clkset_sclk_hdmi_list[] = {
+	[0] = &clk_sclk_pixel.clk,
+	[1] = &clk_sclk_hdmiphy,
+};
+
+static struct clksrc_sources clkset_sclk_hdmi = {
+	.sources	= clkset_sclk_hdmi_list,
+	.nr_sources	= ARRAY_SIZE(clkset_sclk_hdmi_list),
+};
+
+static struct clksrc_clk clk_sclk_hdmi = {
+	.clk		= {
+		.name		= "sclk_hdmi",
+		.id		= -1,
+		.enable		= s5pv310_clksrc_mask_tv_ctrl,
+		.ctrlbit	= (1 << 0),
+	},
+	.sources = &clkset_sclk_hdmi,
+	.reg_src = { .reg = S5P_CLKSRC_TV, .shift = 0, .size = 1 },
+};
+
+static struct clk *clkset_sclk_mixer_list[] = {
+	[0] = &clk_sclk_dac.clk,
+	[1] = &clk_sclk_hdmi.clk,
+};
+
+static struct clksrc_sources clkset_sclk_mixer = {
+	.sources	= clkset_sclk_mixer_list,
+	.nr_sources	= ARRAY_SIZE(clkset_sclk_mixer_list),
+};
+
+static struct clksrc_clk clk_sclk_mixer = {
+	.clk		= {
+		.name		= "sclk_mixer",
+		.id		= -1,
+		.enable		= s5pv310_clksrc_mask_tv_ctrl,
+		.ctrlbit	= (1 << 4),
+	},
+	.sources = &clkset_sclk_mixer,
+	.reg_src = { .reg = S5P_CLKSRC_TV, .shift = 4, .size = 1 },
+};
+
+static struct clksrc_clk *sclk_tv[] = {
+	&clk_sclk_dac,
+	&clk_sclk_pixel,
+	&clk_sclk_hdmi,
+	&clk_sclk_mixer,
+	NULL,
+};
+
+/* -------------------------------------------- */
+
 static struct clksrc_clk clk_dout_mmc0 = {
 	.clk		= {
 		.name		= "dout_mmc0",
@@ -1106,7 +1223,10 @@ void __init_or_cpufreq s5pv310_setup_clocks(void)
 }
 
 static struct clk *clks[] __initdata = {
-	/* Nothing here yet */
+	&clk_sclk_hdmi27m,
+	&clk_sclk_hdmiphy,
+	&clk_sclk_usbphy0,
+	&clk_sclk_usbphy1,
 };
 
 void __init s5pv310_register_clocks(void)
@@ -1118,6 +1238,10 @@ void __init s5pv310_register_clocks(void)
 	for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
 		s3c_register_clksrc(sysclks[ptr], 1);
 
+	/* register TV clocks */
+	for (ptr = 0; sclk_tv[ptr]; ++ptr)
+		s3c_register_clksrc(sclk_tv[ptr], 1);
+
 	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
 	s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
 
diff --git a/arch/arm/mach-s5pv310/dev-tv.c b/arch/arm/mach-s5pv310/dev-tv.c
new file mode 100644
index 0000000..b652c4c
--- /dev/null
+++ b/arch/arm/mach-s5pv310/dev-tv.c
@@ -0,0 +1,450 @@
+/* linux/arch/arm/mach-s5pv310/dev-tv.c
+ *
+ * Copyright 20i10 Samsung Electronics
+ *      Tomasz Stanislawski <t.stanislaws@samsung.com>
+ *
+ * S5P series device definition for TV device
+ *
+ * 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 "plat/tv.h"
+
+#include <mach/gpio.h>
+#include <plat/gpio-cfg.h>
+#include <mach/regs-clock.h>
+#include <mach/regs-pmu.h>
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+#include <linux/fb.h>
+#include <linux/gfp.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <linux/delay.h>
+
+#include <mach/irqs.h>
+#include <mach/map.h>
+
+#include <plat/devs.h>
+#include <plat/cpu.h>
+
+/* macro for setting registeres */
+#define SETREG(name, value, mask) \
+do { \
+	u32 reg = readl(name); \
+	reg &= ~mask; \
+	reg |= value; \
+	writel(reg, name); \
+	reg = readl(name); \
+	printk(KERN_DEBUG #name " <- %08x\n", reg); \
+} while (0)
+
+/* macro for debugging registeres */
+#define DBGREG(name) \
+do { \
+	u32 reg = readl(name); \
+	printk(KERN_DEBUG #name " <- %08x\n", reg); \
+} while (0)
+
+static void dbg_plat_regs(void);
+
+/* very simpler tv-power-domain support */
+static int tv_power_cnt;
+
+static void tv_power_get(void)
+{
+	if (++tv_power_cnt == 1) {
+		int tries;
+		printk(KERN_ERR "TV power domain on - start\n");
+		dbg_plat_regs();
+		SETREG(S5P_CLKGATE_BLOCK, 0x02, 0x02); /* keep here */
+		SETREG(S5P_CMU_CLKSTOP_TV_SYS_PWR, 1, 1);
+		SETREG(S5P_CMU_RESET_TV_SYS_PWR, 1, 1);
+		SETREG(S5P_TV_SYS_PWR, 7, 7);
+		/* power domain on sequence */
+		SETREG(S5P_TV_CONFIGURATION, 7, 7);
+		for (tries = 1000; tries; mdelay(1), tries--)
+			if ((readl(S5P_TV_STATUS) & 7) == 7)
+				break;
+		WARN(tries == 0, "failed to turn TV power domain on\n");
+		printk(KERN_ERR "TV power domain on - finish\n");
+		dbg_plat_regs();
+	}
+}
+
+static void tv_power_put(void)
+{
+	if (--tv_power_cnt == 0) {
+		int tries;
+		printk(KERN_ERR "TV power domain off - start\n");
+		dbg_plat_regs();
+		SETREG(S5P_TV_CONFIGURATION, 0, 7);
+		for (tries = 1000; tries; mdelay(1), tries--)
+			if ((readl(S5P_TV_STATUS) & 7) == 0)
+				break;
+		WARN(tries == 0, "failed to turn TV power domain off\n");
+		SETREG(S5P_TV_SYS_PWR, 0, 7);
+		SETREG(S5P_CMU_RESET_TV_SYS_PWR, 0, 1);
+		SETREG(S5P_CMU_CLKSTOP_TV_SYS_PWR, 0, 1);
+		SETREG(S5P_CLKGATE_BLOCK, 0x00, 0x02); /* keep here */
+		printk(KERN_ERR "TV power domain off - finish\n");
+		dbg_plat_regs();
+	}
+}
+
+/* HDMI interface */
+static struct resource s5p_hdmi_resources[] = {
+	[0] = {
+		.start  = S5P_PA_HDMI,
+		.end    = S5P_PA_HDMI + S5P_SZ_HDMI - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = IRQ_HDMI,
+		.end    = IRQ_HDMI,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct hdmi_platform_data hdmi_pdata;
+
+struct platform_device s5p_device_hdmi = {
+	.name           = "s5p-hdmi",
+	.id             = -1,
+	.num_resources  = ARRAY_SIZE(s5p_hdmi_resources),
+	.resource       = s5p_hdmi_resources,
+	.dev.platform_data = &hdmi_pdata,
+};
+EXPORT_SYMBOL(s5p_device_hdmi);
+
+static struct hdmi_plat_resource {
+	struct clk *hdmi;
+	struct clk *sclk_hdmi;
+	struct clk *sclk_pixel;
+	struct clk *sclk_hdmiphy;
+	struct regulator *ldo4;
+} hdmi_plat_resource;
+
+static void hdmi_deinit(struct device *dev);
+
+static int hdmi_init(struct device *dev)
+{
+	struct hdmi_plat_resource *res = &hdmi_plat_resource;
+	dev_info(dev, "platform HDMI Init\n");
+	memset(res, 0, sizeof *res);
+	/* get clocks, power, and GPIOs */
+	gpio_request(S5PV310_GPX3(7), "hpd-plug");
+	gpio_request(S5PV310_GPE0(1), "hdmi-en");
+
+	/* direct HPD to HDMI chip */
+	gpio_direction_input(S5PV310_GPX3(7));
+	s3c_gpio_cfgpin(S5PV310_GPX3(7), S3C_GPIO_SFN(0x3));
+	s3c_gpio_setpull(S5PV310_GPX3(7), S3C_GPIO_PULL_NONE);
+
+	/* move this names somewhere */
+	res->hdmi = clk_get(dev, "hdmi");
+	if (IS_ERR_OR_NULL(res->hdmi)) {
+		dev_err(dev, "failed to get clock 'hdmi'\n");
+		goto fail;
+	}
+	res->sclk_hdmi = clk_get(dev, "sclk_hdmi");
+	if (IS_ERR_OR_NULL(res->sclk_hdmi)) {
+		dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
+		goto fail;
+	}
+	res->sclk_pixel = clk_get(dev, "sclk_pixel");
+	if (IS_ERR_OR_NULL(res->sclk_pixel)) {
+		dev_err(dev, "failed to get clock 'sclk_pixel'\n");
+		goto fail;
+	}
+	res->sclk_hdmiphy = clk_get(dev, "sclk_hdmiphy");
+	if (IS_ERR_OR_NULL(res->sclk_hdmiphy)) {
+		dev_err(dev, "failed to get clock 'sclk_hdmiphy'\n");
+		goto fail;
+	}
+	res->ldo4 = regulator_get(dev, "vadc_3.3v_c210");
+	if (IS_ERR_OR_NULL(res->ldo4)) {
+		dev_err(dev, "failed to get regulator 'ldo4'\n");
+		goto fail;
+	}
+
+	/* use VPP as parent clock; HDMIPHY is not working yet */
+	clk_set_parent(res->sclk_hdmi, res->sclk_pixel);
+	/* regulator_enable(res->ldo4); */
+	tv_power_get();
+
+	dbg_plat_regs();
+
+	return 0;
+fail:
+	dev_err(dev, "platform HDMI Init - failed\n");
+	hdmi_deinit(dev);
+	return -ENODEV;
+}
+
+static void hdmi_deinit(struct device *dev)
+{
+	struct hdmi_plat_resource *res = &hdmi_plat_resource;
+	dev_info(dev, "platform HDMI Deinit\n");
+	/* put clocks, power, and GPIOs */
+	if (!IS_ERR_OR_NULL(res->ldo4)) {
+		tv_power_put();
+		/* regulator_disable(res->ldo4); */
+		regulator_put(res->ldo4);
+	}
+	if (!IS_ERR_OR_NULL(res->sclk_hdmiphy))
+		clk_put(res->sclk_hdmiphy);
+	if (!IS_ERR_OR_NULL(res->sclk_pixel))
+		clk_put(res->sclk_pixel);
+	if (!IS_ERR_OR_NULL(res->sclk_hdmi))
+		clk_put(res->sclk_hdmi);
+	if (!IS_ERR_OR_NULL(res->hdmi))
+		clk_put(res->hdmi);
+	memset(res, 0, sizeof *res);
+	gpio_free(S5PV310_GPE0(1));
+	gpio_free(S5PV310_GPX3(7));
+}
+
+static int hdmi_power_setup(struct device *dev, int en)
+{
+	struct hdmi_plat_resource *res = &hdmi_plat_resource;
+	if (en) {
+		dev_info(dev, "HDMI power-on\n");
+		/* turn HDMI power on */
+		gpio_direction_output(S5PV310_GPE0(1), 1);
+		/* tv_power_get(); */
+		regulator_enable(res->ldo4);
+		/* turn clocks on */
+		clk_enable(res->hdmi);
+		clk_enable(res->sclk_hdmi);
+		/* power-on hdmi physical interface */
+		SETREG(S5P_HDMI_PHY_CONTROL, 1, 1);
+	} else {
+		dev_info(dev, "HDMI power-off\n");
+		/* power-off hdmiphy */
+		SETREG(S5P_HDMI_PHY_CONTROL, 0, 1);
+		/* turn clocks off */
+		clk_disable(res->sclk_hdmi);
+		clk_disable(res->hdmi);
+		/* turn HDMI power off */
+		regulator_disable(res->ldo4);
+		/* tv_power_put(); */
+		gpio_direction_output(S5PV310_GPE0(1), 0);
+	}
+	dbg_plat_regs();
+	return 0;
+}
+
+static int hdmi_stream_setup(struct device *dev, int en)
+{
+	struct hdmi_plat_resource *res = &hdmi_plat_resource;
+	/* NOTE: assumed HDMI power is on */
+	if (en) {
+		dev_info(dev, "HDMI: stream on\n");
+		/* hdmiphy clock is used for HDMI in streaming mode */
+		clk_disable(res->sclk_hdmi);
+		clk_set_parent(res->sclk_hdmi, res->sclk_hdmiphy);
+		clk_enable(res->sclk_hdmi);
+		/* SETREG(S5P_CLKSRC_TV, 0x00000001, 0x00000001); */
+	} else {
+		dev_info(dev, "HDMI: stream off\n");
+		/* pixel(vpll) clock is used for HDMI in config mode */
+		clk_disable(res->sclk_hdmi);
+		clk_set_parent(res->sclk_hdmi, res->sclk_pixel);
+		clk_enable(res->sclk_hdmi);
+		/* SETREG(S5P_CLKSRC_TV, 0x00000000, 0x00000001); */
+	}
+	dbg_plat_regs();
+	return 0;
+}
+
+static struct hdmi_platform_data hdmi_pdata = {
+	.init = hdmi_init,
+	.deinit = hdmi_deinit,
+	.power_setup = hdmi_power_setup,
+	.stream_setup = hdmi_stream_setup,
+};
+
+/* MIXER */
+static struct resource s5p_mixer_resources[] = {
+	[0] = {
+		.start  = S5P_PA_MIXER,
+		.end    = S5P_PA_MIXER + S5P_SZ_MIXER - 1,
+		.flags  = IORESOURCE_MEM,
+		.name	= "mxr"
+	},
+	[1] = {
+		.start  = S5P_PA_VP,
+		.end    = S5P_PA_VP + S5P_SZ_VP - 1,
+		.flags  = IORESOURCE_MEM,
+		.name	= "vp"
+	},
+	[2] = {
+		.start  = IRQ_MIXER,
+		.end    = IRQ_MIXER,
+		.flags  = IORESOURCE_IRQ,
+		.name	= "irq"
+	},
+};
+
+static struct mxr_platform_data mxr_pdata;
+
+struct platform_device s5p_device_mixer = {
+	.name           = "s5p-mixer",
+	.id             = -1,
+	.num_resources  = ARRAY_SIZE(s5p_mixer_resources),
+	.resource       = s5p_mixer_resources,
+	.dev		= {
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.dma_mask = &s5p_device_mixer.dev.coherent_dma_mask,
+		.platform_data = &mxr_pdata,
+	}
+};
+EXPORT_SYMBOL(s5p_device_mixer);
+
+static struct mxr_plat_resource {
+	struct clk *mixer;
+	struct clk *vp;
+	struct clk *sclk_mixer;
+	struct clk *sclk_hdmi;
+	struct clk *sclk_dac;
+	struct regulator *ldo4;
+} mxr_plat_resource;
+
+static void mxr_deinit(struct device *dev);
+
+static int mxr_init(struct device *dev)
+{
+	struct mxr_plat_resource *res = &mxr_plat_resource;
+	dev_info(dev, "platform Mixer Init\n");
+	res->mixer = clk_get(dev, "mixer");
+	if (IS_ERR_OR_NULL(res->mixer)) {
+		dev_err(dev, "failed to get clock 'mixer'\n");
+		goto fail;
+	}
+	res->vp = clk_get(dev, "vp");
+	if (IS_ERR_OR_NULL(res->vp)) {
+		dev_err(dev, "failed to get clock 'vp'\n");
+		goto fail;
+	}
+	res->sclk_mixer = clk_get(dev, "sclk_mixer");
+	if (IS_ERR_OR_NULL(res->sclk_mixer)) {
+		dev_err(dev, "failed to get clock 'sclk_mixer'\n");
+		goto fail;
+	}
+	res->sclk_hdmi = clk_get(dev, "sclk_hdmi");
+	if (IS_ERR_OR_NULL(res->sclk_hdmi)) {
+		dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
+		goto fail;
+	}
+	res->sclk_dac = clk_get(dev, "sclk_dac");
+	if (IS_ERR_OR_NULL(res->sclk_dac)) {
+		dev_err(dev, "failed to get clock 'sclk_dac'\n");
+		goto fail;
+	}
+	res->ldo4 = regulator_get(dev, "vadc_3.3v_c210");
+	if (IS_ERR_OR_NULL(res->ldo4)) {
+		dev_err(dev, "failed to get regulator 'ldo4'\n");
+		goto fail;
+	}
+	/* regulator_enable(res->ldo4); */
+	tv_power_get();
+
+	/* XXX: fixed connetction between MIXER and HDMI */
+	clk_set_parent(res->sclk_mixer, res->sclk_hdmi);
+	dbg_plat_regs();
+	return 0;
+fail:
+	dev_err(dev, "platform Mixer Init - failed\n");
+	mxr_deinit(dev);
+	return -ENODEV;
+}
+
+static void mxr_deinit(struct device *dev)
+{
+	struct mxr_plat_resource *res = &mxr_plat_resource;
+	dev_info(dev, "platform Mixer denit\n");
+	if (!IS_ERR_OR_NULL(res->ldo4)) {
+		tv_power_put();
+		/* regulator_disable(res->ldo4); */
+		regulator_put(res->ldo4);
+	}
+	if (!IS_ERR_OR_NULL(res->sclk_dac))
+		clk_put(res->sclk_dac);
+	if (!IS_ERR_OR_NULL(res->sclk_hdmi))
+		clk_put(res->sclk_hdmi);
+	if (!IS_ERR_OR_NULL(res->sclk_mixer))
+		clk_put(res->sclk_mixer);
+	if (!IS_ERR_OR_NULL(res->vp))
+		clk_put(res->vp);
+	if (!IS_ERR_OR_NULL(res->mixer))
+		clk_put(res->mixer);
+	memset(res, 0, sizeof *res);
+}
+
+static int mxr_power_setup(struct device *dev, int en)
+{
+	struct mxr_plat_resource *res = &mxr_plat_resource;
+	/* enable/disable clocks, power, and GPIOs */
+	if (en) {
+		dev_info(dev, "MIXER power-on\n");
+		/* turn MIXER power on */
+		/* tv_power_get(); */
+		regulator_enable(res->ldo4);
+		/* turn clocks on */
+		clk_enable(res->mixer);
+		clk_enable(res->vp);
+		clk_enable(res->sclk_mixer);
+		/* HDMI CEC (no support) */
+		/* SETREG(S5P_CLKGATE_IP_PERIR, ~0, 1 << 11); */
+		/* keep here */
+	} else {
+		dev_info(dev, "MIXER power-off\n");
+		/* turn clocks off */
+		clk_disable(res->sclk_mixer);
+		clk_disable(res->vp);
+		clk_disable(res->mixer);
+		/* turn MIXER power off */
+		regulator_disable(res->ldo4);
+		/* tv_power_put(); */
+	}
+	dbg_plat_regs();
+	return 0;
+}
+
+static struct mxr_platform_output output[] = {
+	{ .output_name = "S5P HDMI connector", .module_name = "s5p-hdmi" },
+};
+
+static struct mxr_platform_data mxr_pdata = {
+	.output = output,
+	.output_cnt = ARRAY_SIZE(output),
+	.init = mxr_init,
+	.deinit = mxr_deinit,
+	.power_setup = mxr_power_setup,
+};
+
+static void dbg_plat_regs(void)
+{
+	DBGREG(S5P_CLKSRC_TV);
+	DBGREG(S5P_CLKSRC_MASK_TV);
+	DBGREG(S5P_CLKGATE_IP_TV);
+	DBGREG(S5P_CLKGATE_IP_PERIL); /* remove (unknown?) */
+	DBGREG(S5P_CLKGATE_IP_PERIL); /* I2C HDMI (I2C8) remove */
+	DBGREG(S5P_CLKGATE_IP_PERIR); /* HDMI CEC remove (no support) */
+	DBGREG(S5P_CLKGATE_BLOCK); /* keep here */
+	DBGREG(S5P_CLKSRC_TOP0);
+	DBGREG(S5P_CLKSRC_TOP1);
+	DBGREG(S5P_HDMI_PHY_CONTROL);
+	DBGREG(S5P_CMU_CLKSTOP_TV_SYS_PWR);
+	DBGREG(S5P_CMU_RESET_TV_SYS_PWR);
+	DBGREG(S5P_TV_SYS_PWR);
+	DBGREG(S5P_TV_CONFIGURATION);
+	DBGREG(S5P_TV_STATUS);
+	DBGREG(S5P_CLKDIV_TV);
+}
diff --git a/arch/arm/mach-s5pv310/include/mach/irqs.h b/arch/arm/mach-s5pv310/include/mach/irqs.h
index 0ba778b..76cfe4d 100644
--- a/arch/arm/mach-s5pv310/include/mach/irqs.h
+++ b/arch/arm/mach-s5pv310/include/mach/irqs.h
@@ -116,6 +116,10 @@
 
 #define IRQ_MCT_L1		COMBINER_IRQ(35, 3)
 
+/* Set the default NR_IRQS */
+#define IRQ_MIXER		COMBINER_IRQ(36, 0)
+#define IRQ_TVENC		COMBINER_IRQ(36, 1)
+
 #define IRQ_EINT4		COMBINER_IRQ(37, 0)
 #define IRQ_EINT5		COMBINER_IRQ(37, 1)
 #define IRQ_EINT6		COMBINER_IRQ(37, 2)
diff --git a/arch/arm/mach-s5pv310/include/mach/map.h b/arch/arm/mach-s5pv310/include/mach/map.h
index 845b739..acc2a71 100644
--- a/arch/arm/mach-s5pv310/include/mach/map.h
+++ b/arch/arm/mach-s5pv310/include/mach/map.h
@@ -147,4 +147,30 @@
 #define S5P_PA_MIPI_CSIS0		S5PV310_PA_MIPI_CSIS0
 #define S5P_PA_MIPI_CSIS1		S5PV310_PA_MIPI_CSIS1
 
+/* CEC */
+#define S5PV210_PA_CEC		(0x100B0000)
+#define S5P_PA_CEC		S5PV210_PA_CEC
+#define S5P_SZ_CEC		SZ_4K
+
+/* TVOUT */
+#define S5PV210_PA_TVENC	(0x12C20000)
+#define S5P_PA_TVENC		S5PV210_PA_TVENC
+#define S5P_SZ_TVENC		SZ_64K
+
+#define S5PV210_PA_VP		(0x12C00000)
+#define S5P_PA_VP		S5PV210_PA_VP
+#define S5P_SZ_VP		SZ_64K
+
+#define S5PV210_PA_MIXER	(0x12C10000)
+#define S5P_PA_MIXER		S5PV210_PA_MIXER
+#define S5P_SZ_MIXER		SZ_64K
+
+#define S5PV210_PA_HDMI		(0x12D00000)
+#define S5P_PA_HDMI		S5PV210_PA_HDMI
+#define S5P_SZ_HDMI		SZ_1M
+
+#define S5PV210_I2C_HDMI_PHY	(0x138E0000)
+#define S5P_I2C_HDMI_PHY	S5PV210_I2C_HDMI_PHY
+#define S5P_I2C_HDMI_SZ_PHY	SZ_1K
+
 #endif /* __ASM_ARCH_MAP_H */
diff --git a/arch/arm/mach-s5pv310/include/mach/regs-clock.h b/arch/arm/mach-s5pv310/include/mach/regs-clock.h
index b5c4ada..b1af66c 100644
--- a/arch/arm/mach-s5pv310/include/mach/regs-clock.h
+++ b/arch/arm/mach-s5pv310/include/mach/regs-clock.h
@@ -33,6 +33,7 @@
 #define S5P_CLKSRC_TOP0			S5P_CLKREG(0x0C210)
 #define S5P_CLKSRC_TOP1			S5P_CLKREG(0x0C214)
 #define S5P_CLKSRC_CAM			S5P_CLKREG(0x0C220)
+#define S5P_CLKSRC_TV			S5P_CLKREG(0x0C224)
 #define S5P_CLKSRC_IMAGE		S5P_CLKREG(0x0C230)
 #define S5P_CLKSRC_LCD0			S5P_CLKREG(0x0C234)
 #define S5P_CLKSRC_LCD1			S5P_CLKREG(0x0C238)
@@ -42,6 +43,7 @@
 
 #define S5P_CLKDIV_TOP			S5P_CLKREG(0x0C510)
 #define S5P_CLKDIV_CAM			S5P_CLKREG(0x0C520)
+#define S5P_CLKDIV_TV			S5P_CLKREG(0x0C524)
 #define S5P_CLKDIV_IMAGE		S5P_CLKREG(0x0C530)
 #define S5P_CLKDIV_LCD0			S5P_CLKREG(0x0C534)
 #define S5P_CLKDIV_LCD1			S5P_CLKREG(0x0C538)
@@ -58,6 +60,7 @@
 
 #define S5P_CLKSRC_MASK_TOP		S5P_CLKREG(0x0C310)
 #define S5P_CLKSRC_MASK_CAM		S5P_CLKREG(0x0C320)
+#define S5P_CLKSRC_MASK_TV		S5P_CLKREG(0x0C324)
 #define S5P_CLKSRC_MASK_LCD0		S5P_CLKREG(0x0C334)
 #define S5P_CLKSRC_MASK_LCD1		S5P_CLKREG(0x0C338)
 #define S5P_CLKSRC_MASK_FSYS		S5P_CLKREG(0x0C340)
@@ -67,6 +70,7 @@
 #define S5P_CLKDIV_STAT_TOP		S5P_CLKREG(0x0C610)
 
 #define S5P_CLKGATE_IP_CAM		S5P_CLKREG(0x0C920)
+#define S5P_CLKGATE_IP_TV		S5P_CLKREG(0x0C924)
 #define S5P_CLKGATE_IP_IMAGE		S5P_CLKREG(0x0C930)
 #define S5P_CLKGATE_IP_LCD0		S5P_CLKREG(0x0C934)
 #define S5P_CLKGATE_IP_LCD1		S5P_CLKREG(0x0C938)
@@ -164,4 +168,15 @@
 
 #define S5P_EPLL_CON			S5P_EPLL_CON0
 
+/* TVOUT related */
+#define S5P_TV_CONFIGURATION		S5P_PMUREG(0x03C20)
+#define S5P_TV_STATUS			S5P_PMUREG(0x03C24)
+#define S5P_TV_SYS_PWR			S5P_PMUREG(0x1384)
+#define S5P_CMU_CLKSTOP_TV_SYS_PWR	S5P_PMUREG(0x1144)
+#define S5P_CMU_RESET_TV_SYS_PWR	S5P_PMUREG(0x1164)
+
+#define S5P_HDMI_PHY_CONTROL		S5P_PMUREG(0x0700)
+#define S5P_CLKOUT_CMU_TOP		S5P_CLKREG(0x0CA00)
+#define S5P_PMU_DEBUG			S5P_PMUREG(0x0A00)
+
 #endif /* __ASM_ARCH_REGS_CLOCK_H */
diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h
index 6effbb4..a6b78d4 100644
--- a/arch/arm/plat-samsung/include/plat/devs.h
+++ b/arch/arm/plat-samsung/include/plat/devs.h
@@ -134,6 +134,8 @@ extern struct platform_device samsung_device_keypad;
 extern struct platform_device s5p_device_fimc0;
 extern struct platform_device s5p_device_fimc1;
 extern struct platform_device s5p_device_fimc2;
+extern struct platform_device s5p_device_hdmi;
+extern struct platform_device s5p_device_mixer;
 
 extern struct platform_device s5p_device_mipi_csis0;
 extern struct platform_device s5p_device_mipi_csis1;
-- 
1.7.3.5


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [PATCH/RFC 0/5] HDMI driver for Samsung S5PV310 platform
  2011-02-08  9:30 [PATCH/RFC 0/5] HDMI driver for Samsung S5PV310 platform Tomasz Stanislawski
                   ` (4 preceding siblings ...)
  2011-02-08  9:30 ` [PATCH 5/5] s5pc210: add s5p-tv to platform devices Tomasz Stanislawski
@ 2011-02-08  9:47 ` Hans Verkuil
  2011-02-08 10:08   ` Marek Szyprowski
                     ` (2 more replies)
  5 siblings, 3 replies; 23+ messages in thread
From: Hans Verkuil @ 2011-02-08  9:47 UTC (permalink / raw)
  To: Tomasz Stanislawski
  Cc: linux-media, linux-samsung-soc, m.szyprowski, kyungmin.park

Just two quick notes. I'll try to do a full review this weekend.

On Tuesday, February 08, 2011 10:30:22 Tomasz Stanislawski wrote:
> ==============
>  Introduction
> ==============
> 
> The purpose of this RFC is to discuss the driver for a TV output interface
> available in upcoming Samsung SoC. The HW is able to generate digital and
> analog signals. Current version of the driver supports only digital output.
> 
> Internally the driver uses videobuf2 framework, and CMA memory allocator.  
Not
> all of them are merged by now, but I decided to post the sources to start
> discussion driver's design.
> 
> ======================
>  Hardware description
> ======================
> 
> The SoC contains a few HW sub-blocks:
> 
> 1. Video Processor (VP). It is used for processing of NV12 data.  An image
> stored in RAM is accessed by DMA. Pixels are cropped, scaled. Additionally,
> post processing operations like brightness, sharpness and contrast 
adjustments
> could be performed. The output in YCbCr444 format is send to Mixer.
> 
> 2. Mixer (MXR). The piece of hardware responsible for mixing and blending
> multiple data inputs before passing it to an output device.  The MXR is 
capable
> of handling up to three image layers. One is the output of VP.  Other two 
are
> images in RGB format (multiple variants are supported).  The layers are 
scaled,
> cropped and blended with background color.  The blending factor, and layers'
> priority are controlled by MXR's registers. The output is passed either to 
HDMI
> or TVOUT.
> 
> 3. HDMI. The piece of HW responsible for generation of HDMI packets. It 
takes
> pixel data from mixer and transforms it into data frames. The output is send
> to HDMIPHY interface.
> 
> 4. HDMIPHY. Physical interface for HDMI. Its duties are sending HDMI packets 
to
> HDMI connector. Basically, it contains a PLL that produces source clock for
> Mixer, VP and HDMI during streaming.
> 
> 5. TVOUT. Generation of TV analog signal. (driver not implemented)
> 
> 6. VideoDAC. Modulator for TVOUT signal. (driver not implemented)
> 
> 
> The diagram below depicts connection between all HW pieces.
>                     +-----------+
> NV12 data ---dma--->|   Video   |
>                     | Processor |
>                     +-----------+
>                           |
>                           V
>                     +-----------+
> RGB data  ---dma--->|           |
>                     |   Mixer   |
> RGB data  ---dma--->|           |
>                     +-----------+
>                           |
>                           * dmux
>                          /
>                   +-----*   *------+
>                   |                |
>                   V                V
>             +-----------+    +-----------+
>             |    HDMI   |    |   TVOUT   |
>             +-----------+    +-----------+
>                   |                |
>                   V                V
>             +-----------+    +-----------+
>             |  HDMIPHY  |    |  VideoDAC |
>             +-----------+    +-----------+
>                   |                |
>                   V                V
>                 HDMI           Composite
>              connector         connector
> 
> 
> ==================
>  Driver interface
> ==================
> 
> The posted driver implements three V4L2 nodes. Every video node implements 
V4L2
> output buffer. One of nodes corresponds to input of Video Processor. The 
other
> two nodes correspond to RGB inputs of Mixer. All nodes share the same 
output.
> It is one of the Mixer's outputs: TVOUT or HDMI. Changing output in one 
layer
> using S_OUTPUT would change outputs of all other video nodes. The same thing
> happens if one try to reconfigure output i.e. by calling S_DV_PRESET. 
However
> it not possible to change or reconfigure the output while streaming. To sum 
up,
> all features in posted version of driver goes as follows:
> 
> 1. QUERYCAP
> 2. S_FMT, G_FMT - single and multiplanar API
>   a) node named video0 supports formats NV12, NV12, NV12T (tiled version of
> NV12), NV12MT (multiplane version of NV12T).
>   b) nodes named graph0 and graph1 support formats RGB565, ARGB1555, 
ARGB4444,
> ARGB8888.

graph0? Do you perhaps mean fb0? I haven't heard about nodes names 'graph' 
before.

> 3. Buffer with USERPTR and MMAP memory.
> 4. Streaming and buffer control. (STREAMON, STREAMOFF, REQBUF, QBUF, DQBUF)
> 5. OUTPUT enumeration.
> 6. DV preset control (SET, GET, ENUM). Currently modes 480P59_94, 720P59_94,
> 1080P30, 1080P59_94 and 1080P60 work.
> 7. Positioning layer's window on output display using S_CROP, G_GROP, 
CROPCAP.
> 8. Positioning and cropping data in buffer using S_CROP, G_GROP, CROPCAP 
with
> buffer type OVERLAY. *
> 
> TODOs:
> - add analog TVOUT driver
> - add S_OUTPUT
> - add S_STD ioctl
> - add control of alpha blending / chroma keying via V4L2 controls
> - add controls for luminance curve and sharpness in VP
> - consider exporting all output functionalities to separate video node
> - consider media controller framework
> - better control over debugging
> - fix dependency between all TV drivers
> 
> * The need of cropping in source buffers came from problem with MFC driver 
for
> S5P. The MFC supports only width divisible by 64. If a width of a decoded 
movie
> is not aligned do 64 then padding pixels are filled with zeros. This is an 
ugly
> green color in YCbCr colorspace. Filling it with zeros by a CPU is a waste 
of
> resources since an image can be cropped in VP. Is it possible to set crops 
for
> user data for M2M devices. V4L2 lacks such functionality of non-M2M devices.
> Therefore cropping in buffer V4L2_BUF_TYPE_VIDEO_OVERLAY was used as an work
> around.
> 
> =====================
>  Device Architecture
> =====================
> 
> Three drivers are added in this patch.
> 
> 1. HDMIPHY. It is an I2C driver for HDMIPHY interface. It exports following
> callback by V4L2 subdevice:
> - s_power: currently stub
> - s_stream: configures and starts/stops HDMIPHY
> - s_dv_preset: used to choose proper frequency of clock for other TV devices
> 
> 2. HDMI. The auxiliary driver used to control HDMI interface. It exports its
> subdev to a subdev pool for use by other drivers. The following callbacks 
are
> implemented:
> - s_power: runs HDMI hardware, regulators and clocks.
> - s_stream: runs HDMIPHY and starts generation of video frames.
> - enum_dv_presets
> - s_dv_preset
> - g_mbus_format: returns information on data format expected by on HDMI 
input
>   The driver supports an interrupt. It is used to detect plug/unplug events 
in
> kernel debugs.  The API for detection of such an events in V4L2 API is to be
> defined.

Cisco (i.e. a few colleagues and myself) are working on this. We hope to post 
an RFC by the end of this month. We also have a proposal for CEC support in
the pipeline.

Regards,

	Hans


> 
> 3. Mixer & Video Processor driver. It is called 's5p-mixer' because of
> historical reasons. It was decided combine VP and MXR drivers into one 
because
> of shared interrupt and very similar interface via V4L2 nodes. The driver is 
a
> realization of many-to-many relation between multiple input layers and 
multiple
> outputs. All shared resources are kept in struct mxr_device. It provides
> utilities for management and synchronization of access to resources and
> reference counting. The outputs are obtained from subdev pool basing on 
names
> supplied in platform data. One layer is a single video node. Since layers
> differs simple inheritance is applied. Every layer type implements set of 
ops.
> There are different ops for Mixer layers and other for VP layer.
> 
> The videobuf2 framework was used for the management of buffers and 
streaming.
> All other V4L2 ioctls are processed in layers common interface. The CMA was
> used as memory allocator for Mixer's buffers. It could be easily exchanged 
with
> any other allocator integrated with videobuf2 framework.
> 
> Driver is not yet integrated with power domain driver. Moreover one of 
mixer's
> clocks has to change parent while entering streaming mode. Therefore all 
power
> and clock management was moved to platform data until final solutions 
emerges.
> 
> ===============
>  Usage summary
> ===============
> 
> Follow steps below to display double-buffered animation on HDMI output.
> 
> 01. Open video node named graph0.
> 02. S_FMT(type = OUTPUT, pixelformat = V4L2_PIX_FMT_RGB*, width, height, 
...)
> 03. REQ_BUFS(type = OUTPUT, memory = MMAP, count = 2)
> 04. MMAP(type = OUTPUT, index = 0)
> 05. MMAP(type = OUTPUT, index = 1)
> 06. Fill buffer 0 with data
> 07. QBUF(type = OUTPUT, index = 0)
> 08. STREAM_ON(type = OUTPUT)
> 09. Fill buffer 1 with data
> 10. QBUF(type = OUTPUT, index = 1)
> 11. DQBUF(type = OUTPUT)
> 12. QBUF(type = OUTPUT, index = 0)
> 13. DQBUF(type = OUTPUT)
> 14. Goto 09
> 
> ===============
>  Patch Summary
> ===============
> 
> Tomasz Stanislawski (5):
>   i2c-s3c2410: fix I2C dedicated for hdmiphy
>   universal: i2c: add I2C controller 8 (HDMIPHY)
>   v4l: add macro for 1080p59_54 preset
>   s5p-tv: add driver for HDMI output on S5PC210 platform
>   s5pc210: add s5p-tv to platform devices
> 
>  arch/arm/mach-s5pv310/Kconfig                   |    7 +
>  arch/arm/mach-s5pv310/Makefile                  |    1 +
>  arch/arm/mach-s5pv310/clock.c                   |  132 ++-
>  arch/arm/mach-s5pv310/dev-tv.c                  |  450 ++++++
>  arch/arm/mach-s5pv310/include/mach/irqs.h       |    8 +
>  arch/arm/mach-s5pv310/include/mach/map.h        |   27 +
>  arch/arm/mach-s5pv310/include/mach/regs-clock.h |   15 +
>  arch/arm/plat-samsung/Kconfig                   |    5 +
>  arch/arm/plat-samsung/Makefile                  |    1 +
>  arch/arm/plat-samsung/dev-i2c8.c                |   68 +
>  arch/arm/plat-samsung/include/plat/devs.h       |    3 +
>  arch/arm/plat-samsung/include/plat/iic.h        |    1 +
>  arch/arm/plat-samsung/include/plat/tv.h         |   36 +
>  drivers/i2c/busses/i2c-s3c2410.c                |   36 +-
>  drivers/media/video/Kconfig                     |    8 +
>  drivers/media/video/Makefile                    |    1 +
>  drivers/media/video/s5p-tv/Kconfig              |   42 +
>  drivers/media/video/s5p-tv/Makefile             |   15 +
>  drivers/media/video/s5p-tv/hdmi.h               |   74 +
>  drivers/media/video/s5p-tv/hdmi_drv.c           |  795 ++++++++++
>  drivers/media/video/s5p-tv/hdmiphy.h            |   37 +
>  drivers/media/video/s5p-tv/hdmiphy_drv.c        |  228 +++
>  drivers/media/video/s5p-tv/mixer.h              |  281 ++++
>  drivers/media/video/s5p-tv/mixer_drv.c          |  362 +++++
>  drivers/media/video/s5p-tv/mixer_grp_layer.c    |  181 +++
>  drivers/media/video/s5p-tv/mixer_reg.c          |  532 +++++++
>  drivers/media/video/s5p-tv/mixer_reg.h          |   44 +
>  drivers/media/video/s5p-tv/mixer_video.c        |  834 ++++++++++
>  drivers/media/video/s5p-tv/mixer_vp_layer.c     |  202 +++
>  drivers/media/video/s5p-tv/regs-hdmi.h          | 1849 
+++++++++++++++++++++++
>  drivers/media/video/s5p-tv/regs-vmx.h           |  196 +++
>  drivers/media/video/s5p-tv/regs-vp.h            |  277 ++++
>  drivers/media/video/v4l2-common.c               |    1 +
>  include/linux/videodev2.h                       |    1 +
>  34 files changed, 6748 insertions(+), 2 deletions(-)
>  create mode 100644 arch/arm/mach-s5pv310/dev-tv.c
>  create mode 100644 arch/arm/plat-samsung/dev-i2c8.c
>  create mode 100644 arch/arm/plat-samsung/include/plat/tv.h
>  create mode 100644 drivers/media/video/s5p-tv/Kconfig
>  create mode 100644 drivers/media/video/s5p-tv/Makefile
>  create mode 100644 drivers/media/video/s5p-tv/hdmi.h
>  create mode 100644 drivers/media/video/s5p-tv/hdmi_drv.c
>  create mode 100644 drivers/media/video/s5p-tv/hdmiphy.h
>  create mode 100644 drivers/media/video/s5p-tv/hdmiphy_drv.c
>  create mode 100644 drivers/media/video/s5p-tv/mixer.h
>  create mode 100644 drivers/media/video/s5p-tv/mixer_drv.c
>  create mode 100644 drivers/media/video/s5p-tv/mixer_grp_layer.c
>  create mode 100644 drivers/media/video/s5p-tv/mixer_reg.c
>  create mode 100644 drivers/media/video/s5p-tv/mixer_reg.h
>  create mode 100644 drivers/media/video/s5p-tv/mixer_video.c
>  create mode 100644 drivers/media/video/s5p-tv/mixer_vp_layer.c
>  create mode 100644 drivers/media/video/s5p-tv/regs-hdmi.h
>  create mode 100644 drivers/media/video/s5p-tv/regs-vmx.h
>  create mode 100644 drivers/media/video/s5p-tv/regs-vp.h
> 
> -- 
> 1.7.3.5
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" 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	[flat|nested] 23+ messages in thread

* RE: [PATCH/RFC 0/5] HDMI driver for Samsung S5PV310 platform
  2011-02-08  9:47 ` [PATCH/RFC 0/5] HDMI driver for Samsung S5PV310 platform Hans Verkuil
@ 2011-02-08 10:08   ` Marek Szyprowski
  2011-02-08 10:21   ` Tomasz Stanislawski
  2011-02-08 15:28   ` Alex Deucher
  2 siblings, 0 replies; 23+ messages in thread
From: Marek Szyprowski @ 2011-02-08 10:08 UTC (permalink / raw)
  To: 'Hans Verkuil', Tomasz Stanislawski
  Cc: linux-media, linux-samsung-soc, kyungmin.park, Marek Szyprowski

Hello,

On Tuesday, February 08, 2011 10:47 AM Hans Verkuil wrote:

> Just two quick notes. I'll try to do a full review this weekend.

Thanks! Please focus only on the "PATCH 4/5", which contains the driver itself.
The other patches are mostly platform prerequisites for the driver and will be
rewritten to fit better some extensions to Samsung platform API.

> On Tuesday, February 08, 2011 10:30:22 Tomasz Stanislawski wrote:
> > ==============
> >  Introduction
> > ==============
> >
> > The purpose of this RFC is to discuss the driver for a TV output interface
> > available in upcoming Samsung SoC. The HW is able to generate digital and
> > analog signals. Current version of the driver supports only digital output.
> >
> > Internally the driver uses videobuf2 framework, and CMA memory allocator.
> Not
> > all of them are merged by now, but I decided to post the sources to start
> > discussion driver's design.

> [snip]

Best regards
--
Marek Szyprowski
Samsung Poland R&D Center




^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH/RFC 0/5] HDMI driver for Samsung S5PV310 platform
  2011-02-08  9:47 ` [PATCH/RFC 0/5] HDMI driver for Samsung S5PV310 platform Hans Verkuil
  2011-02-08 10:08   ` Marek Szyprowski
@ 2011-02-08 10:21   ` Tomasz Stanislawski
  2011-02-08 15:28   ` Alex Deucher
  2 siblings, 0 replies; 23+ messages in thread
From: Tomasz Stanislawski @ 2011-02-08 10:21 UTC (permalink / raw)
  To: linux-samsung-soc; +Cc: linux-media

Hans Verkuil wrote:
> Just two quick notes. I'll try to do a full review this weekend.
> 
> On Tuesday, February 08, 2011 10:30:22 Tomasz Stanislawski wrote:
>> ==============
>>  Introduction
>> ==============
>>
>> The purpose of this RFC is to discuss the driver for a TV output interface
>> available in upcoming Samsung SoC. The HW is able to generate digital and
>> analog signals. Current version of the driver supports only digital output.
>>
>> Internally the driver uses videobuf2 framework, and CMA memory allocator.  
> Not
>> all of them are merged by now, but I decided to post the sources to start
>> discussion driver's design.
>>
>> ======================
>>  Hardware description
>> ======================
>>
>> The SoC contains a few HW sub-blocks:
>>
>> 1. Video Processor (VP). It is used for processing of NV12 data.  An image
>> stored in RAM is accessed by DMA. Pixels are cropped, scaled. Additionally,
>> post processing operations like brightness, sharpness and contrast 
> adjustments
>> could be performed. The output in YCbCr444 format is send to Mixer.
>>
>> 2. Mixer (MXR). The piece of hardware responsible for mixing and blending
>> multiple data inputs before passing it to an output device.  The MXR is 
> capable
>> of handling up to three image layers. One is the output of VP.  Other two 
> are
>> images in RGB format (multiple variants are supported).  The layers are 
> scaled,
>> cropped and blended with background color.  The blending factor, and layers'
>> priority are controlled by MXR's registers. The output is passed either to 
> HDMI
>> or TVOUT.
>>
>> 3. HDMI. The piece of HW responsible for generation of HDMI packets. It 
> takes
>> pixel data from mixer and transforms it into data frames. The output is send
>> to HDMIPHY interface.
>>
>> 4. HDMIPHY. Physical interface for HDMI. Its duties are sending HDMI packets 
> to
>> HDMI connector. Basically, it contains a PLL that produces source clock for
>> Mixer, VP and HDMI during streaming.
>>
>> 5. TVOUT. Generation of TV analog signal. (driver not implemented)
>>
>> 6. VideoDAC. Modulator for TVOUT signal. (driver not implemented)
>>
>>
>> The diagram below depicts connection between all HW pieces.
>>                     +-----------+
>> NV12 data ---dma--->|   Video   |
>>                     | Processor |
>>                     +-----------+
>>                           |
>>                           V
>>                     +-----------+
>> RGB data  ---dma--->|           |
>>                     |   Mixer   |
>> RGB data  ---dma--->|           |
>>                     +-----------+
>>                           |
>>                           * dmux
>>                          /
>>                   +-----*   *------+
>>                   |                |
>>                   V                V
>>             +-----------+    +-----------+
>>             |    HDMI   |    |   TVOUT   |
>>             +-----------+    +-----------+
>>                   |                |
>>                   V                V
>>             +-----------+    +-----------+
>>             |  HDMIPHY  |    |  VideoDAC |
>>             +-----------+    +-----------+
>>                   |                |
>>                   V                V
>>                 HDMI           Composite
>>              connector         connector
>>
>>
>> ==================
>>  Driver interface
>> ==================
>>
>> The posted driver implements three V4L2 nodes. Every video node implements 
> V4L2
>> output buffer. One of nodes corresponds to input of Video Processor. The 
> other
>> two nodes correspond to RGB inputs of Mixer. All nodes share the same 
> output.
>> It is one of the Mixer's outputs: TVOUT or HDMI. Changing output in one 
> layer
>> using S_OUTPUT would change outputs of all other video nodes. The same thing
>> happens if one try to reconfigure output i.e. by calling S_DV_PRESET. 
> However
>> it not possible to change or reconfigure the output while streaming. To sum 
> up,
>> all features in posted version of driver goes as follows:
>>
>> 1. QUERYCAP
>> 2. S_FMT, G_FMT - single and multiplanar API
>>   a) node named video0 supports formats NV12, NV12, NV12T (tiled version of
>> NV12), NV12MT (multiplane version of NV12T).
>>   b) nodes named graph0 and graph1 support formats RGB565, ARGB1555, 
> ARGB4444,
>> ARGB8888.
> 
> graph0? Do you perhaps mean fb0? I haven't heard about nodes names 'graph' 
> before.


Hello,
Of course all nodes are named using /dev/video* pattern. By "video0", 
"graph0", "graph1" I mean struct video_device.name. Internal name of a 
mixer's layer.

Regards,
Tomasz Stanislawski


> 
>> 3. Buffer with USERPTR and MMAP memory.
>> 4. Streaming and buffer control. (STREAMON, STREAMOFF, REQBUF, QBUF, DQBUF)
>> 5. OUTPUT enumeration.
>> 6. DV preset control (SET, GET, ENUM). Currently modes 480P59_94, 720P59_94,
>> 1080P30, 1080P59_94 and 1080P60 work.
>> 7. Positioning layer's window on output display using S_CROP, G_GROP, 
> CROPCAP.
>> 8. Positioning and cropping data in buffer using S_CROP, G_GROP, CROPCAP 
> with
>> buffer type OVERLAY. *
>>
>> TODOs:
>> - add analog TVOUT driver
>> - add S_OUTPUT
>> - add S_STD ioctl
>> - add control of alpha blending / chroma keying via V4L2 controls
>> - add controls for luminance curve and sharpness in VP
>> - consider exporting all output functionalities to separate video node
>> - consider media controller framework
>> - better control over debugging
>> - fix dependency between all TV drivers
>>
>> * The need of cropping in source buffers came from problem with MFC driver 
> for
>> S5P. The MFC supports only width divisible by 64. If a width of a decoded 
> movie
>> is not aligned do 64 then padding pixels are filled with zeros. This is an 
> ugly
>> green color in YCbCr colorspace. Filling it with zeros by a CPU is a waste 
> of
>> resources since an image can be cropped in VP. Is it possible to set crops 
> for
>> user data for M2M devices. V4L2 lacks such functionality of non-M2M devices.
>> Therefore cropping in buffer V4L2_BUF_TYPE_VIDEO_OVERLAY was used as an work
>> around.
>>
>> =====================
>>  Device Architecture
>> =====================
>>
>> Three drivers are added in this patch.
>>
>> 1. HDMIPHY. It is an I2C driver for HDMIPHY interface. It exports following
>> callback by V4L2 subdevice:
>> - s_power: currently stub
>> - s_stream: configures and starts/stops HDMIPHY
>> - s_dv_preset: used to choose proper frequency of clock for other TV devices
>>
>> 2. HDMI. The auxiliary driver used to control HDMI interface. It exports its
>> subdev to a subdev pool for use by other drivers. The following callbacks 
> are
>> implemented:
>> - s_power: runs HDMI hardware, regulators and clocks.
>> - s_stream: runs HDMIPHY and starts generation of video frames.
>> - enum_dv_presets
>> - s_dv_preset
>> - g_mbus_format: returns information on data format expected by on HDMI 
> input
>>   The driver supports an interrupt. It is used to detect plug/unplug events 
> in
>> kernel debugs.  The API for detection of such an events in V4L2 API is to be
>> defined.
> 
> Cisco (i.e. a few colleagues and myself) are working on this. We hope to post 
> an RFC by the end of this month. We also have a proposal for CEC support in
> the pipeline.
> 
> Regards,
> 
> 	Hans
> 
> 
>> 3. Mixer & Video Processor driver. It is called 's5p-mixer' because of
>> historical reasons. It was decided combine VP and MXR drivers into one 
> because
>> of shared interrupt and very similar interface via V4L2 nodes. The driver is 
> a
>> realization of many-to-many relation between multiple input layers and 
> multiple
>> outputs. All shared resources are kept in struct mxr_device. It provides
>> utilities for management and synchronization of access to resources and
>> reference counting. The outputs are obtained from subdev pool basing on 
> names
>> supplied in platform data. One layer is a single video node. Since layers
>> differs simple inheritance is applied. Every layer type implements set of 
> ops.
>> There are different ops for Mixer layers and other for VP layer.
>>
>> The videobuf2 framework was used for the management of buffers and 
> streaming.
>> All other V4L2 ioctls are processed in layers common interface. The CMA was
>> used as memory allocator for Mixer's buffers. It could be easily exchanged 
> with
>> any other allocator integrated with videobuf2 framework.
>>
>> Driver is not yet integrated with power domain driver. Moreover one of 
> mixer's
>> clocks has to change parent while entering streaming mode. Therefore all 
> power
>> and clock management was moved to platform data until final solutions 
> emerges.
>> ===============
>>  Usage summary
>> ===============
>>
>> Follow steps below to display double-buffered animation on HDMI output.
>>
>> 01. Open video node named graph0.
>> 02. S_FMT(type = OUTPUT, pixelformat = V4L2_PIX_FMT_RGB*, width, height, 
> ...)
>> 03. REQ_BUFS(type = OUTPUT, memory = MMAP, count = 2)
>> 04. MMAP(type = OUTPUT, index = 0)
>> 05. MMAP(type = OUTPUT, index = 1)
>> 06. Fill buffer 0 with data
>> 07. QBUF(type = OUTPUT, index = 0)
>> 08. STREAM_ON(type = OUTPUT)
>> 09. Fill buffer 1 with data
>> 10. QBUF(type = OUTPUT, index = 1)
>> 11. DQBUF(type = OUTPUT)
>> 12. QBUF(type = OUTPUT, index = 0)
>> 13. DQBUF(type = OUTPUT)
>> 14. Goto 09
>>
>> ===============
>>  Patch Summary
>> ===============
>>
>> Tomasz Stanislawski (5):
>>   i2c-s3c2410: fix I2C dedicated for hdmiphy
>>   universal: i2c: add I2C controller 8 (HDMIPHY)
>>   v4l: add macro for 1080p59_54 preset
>>   s5p-tv: add driver for HDMI output on S5PC210 platform
>>   s5pc210: add s5p-tv to platform devices
>>
>>  arch/arm/mach-s5pv310/Kconfig                   |    7 +
>>  arch/arm/mach-s5pv310/Makefile                  |    1 +
>>  arch/arm/mach-s5pv310/clock.c                   |  132 ++-
>>  arch/arm/mach-s5pv310/dev-tv.c                  |  450 ++++++
>>  arch/arm/mach-s5pv310/include/mach/irqs.h       |    8 +
>>  arch/arm/mach-s5pv310/include/mach/map.h        |   27 +
>>  arch/arm/mach-s5pv310/include/mach/regs-clock.h |   15 +
>>  arch/arm/plat-samsung/Kconfig                   |    5 +
>>  arch/arm/plat-samsung/Makefile                  |    1 +
>>  arch/arm/plat-samsung/dev-i2c8.c                |   68 +
>>  arch/arm/plat-samsung/include/plat/devs.h       |    3 +
>>  arch/arm/plat-samsung/include/plat/iic.h        |    1 +
>>  arch/arm/plat-samsung/include/plat/tv.h         |   36 +
>>  drivers/i2c/busses/i2c-s3c2410.c                |   36 +-
>>  drivers/media/video/Kconfig                     |    8 +
>>  drivers/media/video/Makefile                    |    1 +
>>  drivers/media/video/s5p-tv/Kconfig              |   42 +
>>  drivers/media/video/s5p-tv/Makefile             |   15 +
>>  drivers/media/video/s5p-tv/hdmi.h               |   74 +
>>  drivers/media/video/s5p-tv/hdmi_drv.c           |  795 ++++++++++
>>  drivers/media/video/s5p-tv/hdmiphy.h            |   37 +
>>  drivers/media/video/s5p-tv/hdmiphy_drv.c        |  228 +++
>>  drivers/media/video/s5p-tv/mixer.h              |  281 ++++
>>  drivers/media/video/s5p-tv/mixer_drv.c          |  362 +++++
>>  drivers/media/video/s5p-tv/mixer_grp_layer.c    |  181 +++
>>  drivers/media/video/s5p-tv/mixer_reg.c          |  532 +++++++
>>  drivers/media/video/s5p-tv/mixer_reg.h          |   44 +
>>  drivers/media/video/s5p-tv/mixer_video.c        |  834 ++++++++++
>>  drivers/media/video/s5p-tv/mixer_vp_layer.c     |  202 +++
>>  drivers/media/video/s5p-tv/regs-hdmi.h          | 1849 
> +++++++++++++++++++++++
>>  drivers/media/video/s5p-tv/regs-vmx.h           |  196 +++
>>  drivers/media/video/s5p-tv/regs-vp.h            |  277 ++++
>>  drivers/media/video/v4l2-common.c               |    1 +
>>  include/linux/videodev2.h                       |    1 +
>>  34 files changed, 6748 insertions(+), 2 deletions(-)
>>  create mode 100644 arch/arm/mach-s5pv310/dev-tv.c
>>  create mode 100644 arch/arm/plat-samsung/dev-i2c8.c
>>  create mode 100644 arch/arm/plat-samsung/include/plat/tv.h
>>  create mode 100644 drivers/media/video/s5p-tv/Kconfig
>>  create mode 100644 drivers/media/video/s5p-tv/Makefile
>>  create mode 100644 drivers/media/video/s5p-tv/hdmi.h
>>  create mode 100644 drivers/media/video/s5p-tv/hdmi_drv.c
>>  create mode 100644 drivers/media/video/s5p-tv/hdmiphy.h
>>  create mode 100644 drivers/media/video/s5p-tv/hdmiphy_drv.c
>>  create mode 100644 drivers/media/video/s5p-tv/mixer.h
>>  create mode 100644 drivers/media/video/s5p-tv/mixer_drv.c
>>  create mode 100644 drivers/media/video/s5p-tv/mixer_grp_layer.c
>>  create mode 100644 drivers/media/video/s5p-tv/mixer_reg.c
>>  create mode 100644 drivers/media/video/s5p-tv/mixer_reg.h
>>  create mode 100644 drivers/media/video/s5p-tv/mixer_video.c
>>  create mode 100644 drivers/media/video/s5p-tv/mixer_vp_layer.c
>>  create mode 100644 drivers/media/video/s5p-tv/regs-hdmi.h
>>  create mode 100644 drivers/media/video/s5p-tv/regs-vmx.h
>>  create mode 100644 drivers/media/video/s5p-tv/regs-vp.h
>>
>> -- 
>> 1.7.3.5
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-media" 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	[flat|nested] 23+ messages in thread

* Re: [PATCH/RFC 0/5] HDMI driver for Samsung S5PV310 platform
  2011-02-08  9:47 ` [PATCH/RFC 0/5] HDMI driver for Samsung S5PV310 platform Hans Verkuil
  2011-02-08 10:08   ` Marek Szyprowski
  2011-02-08 10:21   ` Tomasz Stanislawski
@ 2011-02-08 15:28   ` Alex Deucher
  2011-02-08 22:47     ` Andy Walls
  2011-02-09  8:59     ` Hans Verkuil
  2 siblings, 2 replies; 23+ messages in thread
From: Alex Deucher @ 2011-02-08 15:28 UTC (permalink / raw)
  To: Hans Verkuil
  Cc: Tomasz Stanislawski, linux-media, linux-samsung-soc,
	m.szyprowski, kyungmin.park

On Tue, Feb 8, 2011 at 4:47 AM, Hans Verkuil <hansverk@cisco.com> wrote:
> Just two quick notes. I'll try to do a full review this weekend.
>
> On Tuesday, February 08, 2011 10:30:22 Tomasz Stanislawski wrote:
>> ==============
>>  Introduction
>> ==============
>>
>> The purpose of this RFC is to discuss the driver for a TV output interface
>> available in upcoming Samsung SoC. The HW is able to generate digital and
>> analog signals. Current version of the driver supports only digital output.
>>
>> Internally the driver uses videobuf2 framework, and CMA memory allocator.
> Not
>> all of them are merged by now, but I decided to post the sources to start
>> discussion driver's design.
>>
>> ======================
>>  Hardware description
>> ======================
>>
>> The SoC contains a few HW sub-blocks:
>>
>> 1. Video Processor (VP). It is used for processing of NV12 data.  An image
>> stored in RAM is accessed by DMA. Pixels are cropped, scaled. Additionally,
>> post processing operations like brightness, sharpness and contrast
> adjustments
>> could be performed. The output in YCbCr444 format is send to Mixer.
>>
>> 2. Mixer (MXR). The piece of hardware responsible for mixing and blending
>> multiple data inputs before passing it to an output device.  The MXR is
> capable
>> of handling up to three image layers. One is the output of VP.  Other two
> are
>> images in RGB format (multiple variants are supported).  The layers are
> scaled,
>> cropped and blended with background color.  The blending factor, and layers'
>> priority are controlled by MXR's registers. The output is passed either to
> HDMI
>> or TVOUT.
>>
>> 3. HDMI. The piece of HW responsible for generation of HDMI packets. It
> takes
>> pixel data from mixer and transforms it into data frames. The output is send
>> to HDMIPHY interface.
>>
>> 4. HDMIPHY. Physical interface for HDMI. Its duties are sending HDMI packets
> to
>> HDMI connector. Basically, it contains a PLL that produces source clock for
>> Mixer, VP and HDMI during streaming.
>>
>> 5. TVOUT. Generation of TV analog signal. (driver not implemented)
>>
>> 6. VideoDAC. Modulator for TVOUT signal. (driver not implemented)
>>
>>
>> The diagram below depicts connection between all HW pieces.
>>                     +-----------+
>> NV12 data ---dma--->|   Video   |
>>                     | Processor |
>>                     +-----------+
>>                           |
>>                           V
>>                     +-----------+
>> RGB data  ---dma--->|           |
>>                     |   Mixer   |
>> RGB data  ---dma--->|           |
>>                     +-----------+
>>                           |
>>                           * dmux
>>                          /
>>                   +-----*   *------+
>>                   |                |
>>                   V                V
>>             +-----------+    +-----------+
>>             |    HDMI   |    |   TVOUT   |
>>             +-----------+    +-----------+
>>                   |                |
>>                   V                V
>>             +-----------+    +-----------+
>>             |  HDMIPHY  |    |  VideoDAC |
>>             +-----------+    +-----------+
>>                   |                |
>>                   V                V
>>                 HDMI           Composite
>>              connector         connector
>>
>>
>> ==================
>>  Driver interface
>> ==================
>>
>> The posted driver implements three V4L2 nodes. Every video node implements
> V4L2
>> output buffer. One of nodes corresponds to input of Video Processor. The
> other
>> two nodes correspond to RGB inputs of Mixer. All nodes share the same
> output.
>> It is one of the Mixer's outputs: TVOUT or HDMI. Changing output in one
> layer
>> using S_OUTPUT would change outputs of all other video nodes. The same thing
>> happens if one try to reconfigure output i.e. by calling S_DV_PRESET.
> However
>> it not possible to change or reconfigure the output while streaming. To sum
> up,
>> all features in posted version of driver goes as follows:
>>
>> 1. QUERYCAP
>> 2. S_FMT, G_FMT - single and multiplanar API
>>   a) node named video0 supports formats NV12, NV12, NV12T (tiled version of
>> NV12), NV12MT (multiplane version of NV12T).
>>   b) nodes named graph0 and graph1 support formats RGB565, ARGB1555,
> ARGB4444,
>> ARGB8888.
>
> graph0? Do you perhaps mean fb0? I haven't heard about nodes names 'graph'
> before.
>
>> 3. Buffer with USERPTR and MMAP memory.
>> 4. Streaming and buffer control. (STREAMON, STREAMOFF, REQBUF, QBUF, DQBUF)
>> 5. OUTPUT enumeration.
>> 6. DV preset control (SET, GET, ENUM). Currently modes 480P59_94, 720P59_94,
>> 1080P30, 1080P59_94 and 1080P60 work.
>> 7. Positioning layer's window on output display using S_CROP, G_GROP,
> CROPCAP.
>> 8. Positioning and cropping data in buffer using S_CROP, G_GROP, CROPCAP
> with
>> buffer type OVERLAY. *
>>
>> TODOs:
>> - add analog TVOUT driver
>> - add S_OUTPUT
>> - add S_STD ioctl
>> - add control of alpha blending / chroma keying via V4L2 controls
>> - add controls for luminance curve and sharpness in VP
>> - consider exporting all output functionalities to separate video node
>> - consider media controller framework
>> - better control over debugging
>> - fix dependency between all TV drivers
>>
>> * The need of cropping in source buffers came from problem with MFC driver
> for
>> S5P. The MFC supports only width divisible by 64. If a width of a decoded
> movie
>> is not aligned do 64 then padding pixels are filled with zeros. This is an
> ugly
>> green color in YCbCr colorspace. Filling it with zeros by a CPU is a waste
> of
>> resources since an image can be cropped in VP. Is it possible to set crops
> for
>> user data for M2M devices. V4L2 lacks such functionality of non-M2M devices.
>> Therefore cropping in buffer V4L2_BUF_TYPE_VIDEO_OVERLAY was used as an work
>> around.
>>
>> =====================
>>  Device Architecture
>> =====================
>>
>> Three drivers are added in this patch.
>>
>> 1. HDMIPHY. It is an I2C driver for HDMIPHY interface. It exports following
>> callback by V4L2 subdevice:
>> - s_power: currently stub
>> - s_stream: configures and starts/stops HDMIPHY
>> - s_dv_preset: used to choose proper frequency of clock for other TV devices
>>
>> 2. HDMI. The auxiliary driver used to control HDMI interface. It exports its
>> subdev to a subdev pool for use by other drivers. The following callbacks
> are
>> implemented:
>> - s_power: runs HDMI hardware, regulators and clocks.
>> - s_stream: runs HDMIPHY and starts generation of video frames.
>> - enum_dv_presets
>> - s_dv_preset
>> - g_mbus_format: returns information on data format expected by on HDMI
> input
>>   The driver supports an interrupt. It is used to detect plug/unplug events
> in
>> kernel debugs.  The API for detection of such an events in V4L2 API is to be
>> defined.
>
> Cisco (i.e. a few colleagues and myself) are working on this. We hope to post
> an RFC by the end of this month. We also have a proposal for CEC support in
> the pipeline.

Any reason to not use the drm kms APIs for modesetting, display
configuration, and hotplug support?  We already have the
infrastructure in place for complex display configurations and
generating events for hotplug interrupts.  It would seem to make more
sense to me to fix any deficiencies in the KMS APIs than to spin a new
API.  Things like CEC would be a natural fit since a lot of desktop
GPUs support hdmi audio/3d/etc. and are already using kms.

Alex

>
> Regards,
>
>        Hans
>
>
>>
>> 3. Mixer & Video Processor driver. It is called 's5p-mixer' because of
>> historical reasons. It was decided combine VP and MXR drivers into one
> because
>> of shared interrupt and very similar interface via V4L2 nodes. The driver is
> a
>> realization of many-to-many relation between multiple input layers and
> multiple
>> outputs. All shared resources are kept in struct mxr_device. It provides
>> utilities for management and synchronization of access to resources and
>> reference counting. The outputs are obtained from subdev pool basing on
> names
>> supplied in platform data. One layer is a single video node. Since layers
>> differs simple inheritance is applied. Every layer type implements set of
> ops.
>> There are different ops for Mixer layers and other for VP layer.
>>
>> The videobuf2 framework was used for the management of buffers and
> streaming.
>> All other V4L2 ioctls are processed in layers common interface. The CMA was
>> used as memory allocator for Mixer's buffers. It could be easily exchanged
> with
>> any other allocator integrated with videobuf2 framework.
>>
>> Driver is not yet integrated with power domain driver. Moreover one of
> mixer's
>> clocks has to change parent while entering streaming mode. Therefore all
> power
>> and clock management was moved to platform data until final solutions
> emerges.
>>
>> ===============
>>  Usage summary
>> ===============
>>
>> Follow steps below to display double-buffered animation on HDMI output.
>>
>> 01. Open video node named graph0.
>> 02. S_FMT(type = OUTPUT, pixelformat = V4L2_PIX_FMT_RGB*, width, height,
> ...)
>> 03. REQ_BUFS(type = OUTPUT, memory = MMAP, count = 2)
>> 04. MMAP(type = OUTPUT, index = 0)
>> 05. MMAP(type = OUTPUT, index = 1)
>> 06. Fill buffer 0 with data
>> 07. QBUF(type = OUTPUT, index = 0)
>> 08. STREAM_ON(type = OUTPUT)
>> 09. Fill buffer 1 with data
>> 10. QBUF(type = OUTPUT, index = 1)
>> 11. DQBUF(type = OUTPUT)
>> 12. QBUF(type = OUTPUT, index = 0)
>> 13. DQBUF(type = OUTPUT)
>> 14. Goto 09
>>
>> ===============
>>  Patch Summary
>> ===============
>>
>> Tomasz Stanislawski (5):
>>   i2c-s3c2410: fix I2C dedicated for hdmiphy
>>   universal: i2c: add I2C controller 8 (HDMIPHY)
>>   v4l: add macro for 1080p59_54 preset
>>   s5p-tv: add driver for HDMI output on S5PC210 platform
>>   s5pc210: add s5p-tv to platform devices
>>
>>  arch/arm/mach-s5pv310/Kconfig                   |    7 +
>>  arch/arm/mach-s5pv310/Makefile                  |    1 +
>>  arch/arm/mach-s5pv310/clock.c                   |  132 ++-
>>  arch/arm/mach-s5pv310/dev-tv.c                  |  450 ++++++
>>  arch/arm/mach-s5pv310/include/mach/irqs.h       |    8 +
>>  arch/arm/mach-s5pv310/include/mach/map.h        |   27 +
>>  arch/arm/mach-s5pv310/include/mach/regs-clock.h |   15 +
>>  arch/arm/plat-samsung/Kconfig                   |    5 +
>>  arch/arm/plat-samsung/Makefile                  |    1 +
>>  arch/arm/plat-samsung/dev-i2c8.c                |   68 +
>>  arch/arm/plat-samsung/include/plat/devs.h       |    3 +
>>  arch/arm/plat-samsung/include/plat/iic.h        |    1 +
>>  arch/arm/plat-samsung/include/plat/tv.h         |   36 +
>>  drivers/i2c/busses/i2c-s3c2410.c                |   36 +-
>>  drivers/media/video/Kconfig                     |    8 +
>>  drivers/media/video/Makefile                    |    1 +
>>  drivers/media/video/s5p-tv/Kconfig              |   42 +
>>  drivers/media/video/s5p-tv/Makefile             |   15 +
>>  drivers/media/video/s5p-tv/hdmi.h               |   74 +
>>  drivers/media/video/s5p-tv/hdmi_drv.c           |  795 ++++++++++
>>  drivers/media/video/s5p-tv/hdmiphy.h            |   37 +
>>  drivers/media/video/s5p-tv/hdmiphy_drv.c        |  228 +++
>>  drivers/media/video/s5p-tv/mixer.h              |  281 ++++
>>  drivers/media/video/s5p-tv/mixer_drv.c          |  362 +++++
>>  drivers/media/video/s5p-tv/mixer_grp_layer.c    |  181 +++
>>  drivers/media/video/s5p-tv/mixer_reg.c          |  532 +++++++
>>  drivers/media/video/s5p-tv/mixer_reg.h          |   44 +
>>  drivers/media/video/s5p-tv/mixer_video.c        |  834 ++++++++++
>>  drivers/media/video/s5p-tv/mixer_vp_layer.c     |  202 +++
>>  drivers/media/video/s5p-tv/regs-hdmi.h          | 1849
> +++++++++++++++++++++++
>>  drivers/media/video/s5p-tv/regs-vmx.h           |  196 +++
>>  drivers/media/video/s5p-tv/regs-vp.h            |  277 ++++
>>  drivers/media/video/v4l2-common.c               |    1 +
>>  include/linux/videodev2.h                       |    1 +
>>  34 files changed, 6748 insertions(+), 2 deletions(-)
>>  create mode 100644 arch/arm/mach-s5pv310/dev-tv.c
>>  create mode 100644 arch/arm/plat-samsung/dev-i2c8.c
>>  create mode 100644 arch/arm/plat-samsung/include/plat/tv.h
>>  create mode 100644 drivers/media/video/s5p-tv/Kconfig
>>  create mode 100644 drivers/media/video/s5p-tv/Makefile
>>  create mode 100644 drivers/media/video/s5p-tv/hdmi.h
>>  create mode 100644 drivers/media/video/s5p-tv/hdmi_drv.c
>>  create mode 100644 drivers/media/video/s5p-tv/hdmiphy.h
>>  create mode 100644 drivers/media/video/s5p-tv/hdmiphy_drv.c
>>  create mode 100644 drivers/media/video/s5p-tv/mixer.h
>>  create mode 100644 drivers/media/video/s5p-tv/mixer_drv.c
>>  create mode 100644 drivers/media/video/s5p-tv/mixer_grp_layer.c
>>  create mode 100644 drivers/media/video/s5p-tv/mixer_reg.c
>>  create mode 100644 drivers/media/video/s5p-tv/mixer_reg.h
>>  create mode 100644 drivers/media/video/s5p-tv/mixer_video.c
>>  create mode 100644 drivers/media/video/s5p-tv/mixer_vp_layer.c
>>  create mode 100644 drivers/media/video/s5p-tv/regs-hdmi.h
>>  create mode 100644 drivers/media/video/s5p-tv/regs-vmx.h
>>  create mode 100644 drivers/media/video/s5p-tv/regs-vp.h
>>
>> --
>> 1.7.3.5
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-media" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
>>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" 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	[flat|nested] 23+ messages in thread

* Re: [PATCH/RFC 0/5] HDMI driver for Samsung S5PV310 platform
  2011-02-08 15:28   ` Alex Deucher
@ 2011-02-08 22:47     ` Andy Walls
  2011-02-09  7:12       ` Alex Deucher
  2011-02-09  8:59     ` Hans Verkuil
  1 sibling, 1 reply; 23+ messages in thread
From: Andy Walls @ 2011-02-08 22:47 UTC (permalink / raw)
  To: Alex Deucher
  Cc: Hans Verkuil, Tomasz Stanislawski, linux-media,
	linux-samsung-soc, m.szyprowski, kyungmin.park

On Tue, 2011-02-08 at 10:28 -0500, Alex Deucher wrote:
> On Tue, Feb 8, 2011 at 4:47 AM, Hans Verkuil <hansverk@cisco.com> wrote:
> > Just two quick notes. I'll try to do a full review this weekend.
> >
> > On Tuesday, February 08, 2011 10:30:22 Tomasz Stanislawski wrote:
> >> ==============
> >>  Introduction
> >> ==============
> >>
> >> The purpose of this RFC is to discuss the driver for a TV output interface
> >> available in upcoming Samsung SoC. The HW is able to generate digital and
> >> analog signals. Current version of the driver supports only digital output.
> >>
> >> Internally the driver uses videobuf2 framework, and CMA memory allocator.
> > Not
> >> all of them are merged by now, but I decided to post the sources to start
> >> discussion driver's design.

> >
> > Cisco (i.e. a few colleagues and myself) are working on this. We hope to post
> > an RFC by the end of this month. We also have a proposal for CEC support in
> > the pipeline.
> 
> Any reason to not use the drm kms APIs for modesetting, display
> configuration, and hotplug support?  We already have the
> infrastructure in place for complex display configurations and
> generating events for hotplug interrupts.  It would seem to make more
> sense to me to fix any deficiencies in the KMS APIs than to spin a new
> API.  Things like CEC would be a natural fit since a lot of desktop
> GPUs support hdmi audio/3d/etc. and are already using kms.
> 
> Alex

I'll toss one out: lack of API documentation for driver or application
developers to use.


When I last looked at converting ivtvfb to use DRM, KMS, TTM, etc. (to
possibly get rid of reliance on the ivtv X video driver
http://dl.ivtvdriver.org/xf86-video-ivtv/ ), I found the documentation
was really sparse.

DRM had the most documentation under Documentation/DocBook/drm.tmpl, but
the userland API wasn't fleshed out.  GEM was talked about a bit in
there as well, IIRC.

TTM documentation was essentially non-existant.

I can't find any KMS documentation either.

I recall having to read much of the drm code, and having to look at the
radeon driver, just to tease out what the DRM ioctls needed to do.

Am I missing a Documentation source for the APIs?



For V4L2 and DVB on ther other hand, one can point to pretty verbose
documentation that application developers can use:

	http://linuxtv.org/downloads/v4l-dvb-apis/



Regards,
Andy



^ permalink raw reply	[flat|nested] 23+ messages in thread

* RE: [PATCH 5/5] s5pc210: add s5p-tv to platform devices
  2011-02-08  9:30 ` [PATCH 5/5] s5pc210: add s5p-tv to platform devices Tomasz Stanislawski
@ 2011-02-09  6:40   ` Kukjin Kim
  0 siblings, 0 replies; 23+ messages in thread
From: Kukjin Kim @ 2011-02-09  6:40 UTC (permalink / raw)
  To: 'Tomasz Stanislawski', linux-media, linux-samsung-soc
  Cc: m.szyprowski, kyungmin.park, hansverk, ben-linux

Tomasz Stanislawski wrote:
> 
> Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> Reviewed-by: Marek Szyprowski <m.szyprowski@samsung.com>
> ---
>  arch/arm/mach-s5pv310/Kconfig                   |    7 +
>  arch/arm/mach-s5pv310/Makefile                  |    1 +
>  arch/arm/mach-s5pv310/clock.c                   |  126 +++++++-
>  arch/arm/mach-s5pv310/dev-tv.c                  |  450
> +++++++++++++++++++++++
>  arch/arm/mach-s5pv310/include/mach/irqs.h       |    4 +
>  arch/arm/mach-s5pv310/include/mach/map.h        |   26 ++
>  arch/arm/mach-s5pv310/include/mach/regs-clock.h |   15 +
>  arch/arm/plat-samsung/include/plat/devs.h       |    2 +
>  8 files changed, 630 insertions(+), 1 deletions(-)
>  create mode 100644 arch/arm/mach-s5pv310/dev-tv.c
> 

Hi Tomasz,

Please add me on Cc, because I believe that I'm a proper person, maintainer
on this.

And Cc'ed Hans now, because I didn't subscribe linux-media.

> diff --git a/arch/arm/mach-s5pv310/Kconfig b/arch/arm/mach-s5pv310/Kconfig
> index 09c4c21..e62103b 100644
> --- a/arch/arm/mach-s5pv310/Kconfig
> +++ b/arch/arm/mach-s5pv310/Kconfig
> @@ -20,6 +20,11 @@ config S5PV310_DEV_PD
>  	help
>  	  Compile in platform device definitions for Power Domain
> 
> +config S5PV310_DEV_TV
> +	bool
> +	help
> +	  Compile in platform device definition for TV interface
> +
>  config S5PV310_SETUP_I2C1
>  	bool
>  	help
> @@ -102,6 +107,8 @@ config MACH_UNIVERSAL_C210
>  	select S3C_DEV_HSMMC3
>  	select S5PV310_SETUP_SDHCI
>  	select S3C_DEV_I2C1
> +	select S3C_DEV_I2C8

This should be added in other patch file.
Because this is for just adding tv platform device.

> +	select S5PV310_DEV_TV
>  	select S5PV310_SETUP_I2C1
>  	help
>  	  Machine support for Samsung Mobile Universal S5PC210 Reference
> diff --git a/arch/arm/mach-s5pv310/Makefile
b/arch/arm/mach-s5pv310/Makefile
> index 036fb38..a234b80 100644
> --- a/arch/arm/mach-s5pv310/Makefile
> +++ b/arch/arm/mach-s5pv310/Makefile
> @@ -32,6 +32,7 @@ obj-y					+=
dev-audio.o
>  obj-$(CONFIG_S5PV310_DEV_PD)		+= dev-pd.o
>  obj-$(CONFIG_S5PV310_DEV_SYSMMU)	+= dev-sysmmu.o
> 
> +obj-$(CONFIG_S5PV310_DEV_TV)		+= dev-tv.o
>  obj-$(CONFIG_S5PV310_SETUP_I2C1)	+= setup-i2c1.o

Maybe you want this?
...
  obj-$(CONFIG_S5PV310_DEV_SYSMMU)	+= dev-sysmmu.o
 +obj-$(CONFIG_S5PV310_DEV_TV)		+= dev-tv.o

  obj-$(CONFIG_S5PV310_SETUP_I2C1)	+= setup-i2c1.o
...

>  obj-$(CONFIG_S5PV310_SETUP_I2C2)	+= setup-i2c2.o
>  obj-$(CONFIG_S5PV310_SETUP_I2C3)	+= setup-i2c3.o
> diff --git a/arch/arm/mach-s5pv310/clock.c b/arch/arm/mach-s5pv310/clock.c
> index 6161b54..5bca261 100644
> --- a/arch/arm/mach-s5pv310/clock.c
> +++ b/arch/arm/mach-s5pv310/clock.c

Will review regarding clock part this weekend.

(snip)

> diff --git a/arch/arm/mach-s5pv310/dev-tv.c
b/arch/arm/mach-s5pv310/dev-tv.c
> new file mode 100644
> index 0000000..b652c4c
> --- /dev/null
> +++ b/arch/arm/mach-s5pv310/dev-tv.c
> @@ -0,0 +1,450 @@
> +/* linux/arch/arm/mach-s5pv310/dev-tv.c
> + *
> + * Copyright 20i10 Samsung Electronics

20i10?

> + *      Tomasz Stanislawski <t.stanislaws@samsung.com>
> + *
> + * S5P series device definition for TV device

S5P? or S5PV310?



> + *
> + * 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 "plat/tv.h"

What's this?

> +
> +#include <mach/gpio.h>

Should be <linux/gpio.h>

> +#include <plat/gpio-cfg.h>
> +#include <mach/regs-clock.h>
> +#include <mach/regs-pmu.h>
> +
> +#include <linux/kernel.h>
> +#include <linux/string.h>
> +#include <linux/platform_device.h>
> +#include <linux/fb.h>
> +#include <linux/gfp.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/clk.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/delay.h>
> +
> +#include <mach/irqs.h>
> +#include <mach/map.h>
> +
> +#include <plat/devs.h>
> +#include <plat/cpu.h>
> +

Firstly, cleanup your inclusion. If useless, please remove it. I don't
think, above all inclusion is needed.

Secondly, grouping according to similar inclusion is needed like following.

#include <linux/...>

#include <mach/...>

#include <plat/...>

> +/* macro for setting registeres */
> +#define SETREG(name, value, mask) \
> +do { \
> +	u32 reg = readl(name); \
> +	reg &= ~mask; \
> +	reg |= value; \
> +	writel(reg, name); \
> +	reg = readl(name); \
> +	printk(KERN_DEBUG #name " <- %08x\n", reg); \
> +} while (0)
> +
> +/* macro for debugging registeres */
> +#define DBGREG(name) \
> +do { \
> +	u32 reg = readl(name); \
> +	printk(KERN_DEBUG #name " <- %08x\n", reg); \
> +} while (0)
> +

Hmm...I don't think that we need this macro.

> +static void dbg_plat_regs(void);
> +
> +/* very simpler tv-power-domain support */
> +static int tv_power_cnt;
> +
> +static void tv_power_get(void)
> +{
> +	if (++tv_power_cnt == 1) {
> +		int tries;
> +		printk(KERN_ERR "TV power domain on - start\n");
> +		dbg_plat_regs();
> +		SETREG(S5P_CLKGATE_BLOCK, 0x02, 0x02); /* keep here */
> +		SETREG(S5P_CMU_CLKSTOP_TV_SYS_PWR, 1, 1);
> +		SETREG(S5P_CMU_RESET_TV_SYS_PWR, 1, 1);
> +		SETREG(S5P_TV_SYS_PWR, 7, 7);
> +		/* power domain on sequence */
> +		SETREG(S5P_TV_CONFIGURATION, 7, 7);
> +		for (tries = 1000; tries; mdelay(1), tries--)
> +			if ((readl(S5P_TV_STATUS) & 7) == 7)
> +				break;
> +		WARN(tries == 0, "failed to turn TV power domain on\n");
> +		printk(KERN_ERR "TV power domain on - finish\n");
> +		dbg_plat_regs();
> +	}
> +}
> +
Regarding power should be controlled in driver via using runtimePM.

> +static void tv_power_put(void)
> +{
> +	if (--tv_power_cnt == 0) {
> +		int tries;
> +		printk(KERN_ERR "TV power domain off - start\n");
> +		dbg_plat_regs();
> +		SETREG(S5P_TV_CONFIGURATION, 0, 7);
> +		for (tries = 1000; tries; mdelay(1), tries--)
> +			if ((readl(S5P_TV_STATUS) & 7) == 0)
> +				break;
> +		WARN(tries == 0, "failed to turn TV power domain off\n");
> +		SETREG(S5P_TV_SYS_PWR, 0, 7);
> +		SETREG(S5P_CMU_RESET_TV_SYS_PWR, 0, 1);
> +		SETREG(S5P_CMU_CLKSTOP_TV_SYS_PWR, 0, 1);
> +		SETREG(S5P_CLKGATE_BLOCK, 0x00, 0x02); /* keep here */
> +		printk(KERN_ERR "TV power domain off - finish\n");
> +		dbg_plat_regs();
> +	}
> +}
> +
Same.

> +/* HDMI interface */
> +static struct resource s5p_hdmi_resources[] = {

If this is for S5PV310, s5pv310_hdmi_resources is better to avoid
mis-reading.

> +	[0] = {
> +		.start  = S5P_PA_HDMI,
                      ^^
S5PV310_PA_XXX

> +		.end    = S5P_PA_HDMI + S5P_SZ_HDMI - 1,
                    ^^^^
> +		.flags  = IORESOURCE_MEM,
                      ^^

Please use tab between member of structure and = (mark ^^^)

> +	},
> +	[1] = {
> +		.start  = IRQ_HDMI,
> +		.end    = IRQ_HDMI,
> +		.flags  = IORESOURCE_IRQ,

Same as above.

> +	},
> +};
> +
> +static struct hdmi_platform_data hdmi_pdata;
> +
> +struct platform_device s5p_device_hdmi = {
> +	.name           = "s5p-hdmi",
> +	.id             = -1,
> +	.num_resources  = ARRAY_SIZE(s5p_hdmi_resources),
> +	.resource       = s5p_hdmi_resources,
> +	.dev.platform_data = &hdmi_pdata,
> +};
> +EXPORT_SYMBOL(s5p_device_hdmi);

Do we rellay need export symbol of this?

> +
> +static struct hdmi_plat_resource {
> +	struct clk *hdmi;
> +	struct clk *sclk_hdmi;
> +	struct clk *sclk_pixel;
> +	struct clk *sclk_hdmiphy;
> +	struct regulator *ldo4;
> +} hdmi_plat_resource;
> +
> +static void hdmi_deinit(struct device *dev);
> +
> +static int hdmi_init(struct device *dev)
> +{
> +	struct hdmi_plat_resource *res = &hdmi_plat_resource;
> +	dev_info(dev, "platform HDMI Init\n");
> +	memset(res, 0, sizeof *res);
> +	/* get clocks, power, and GPIOs */
> +	gpio_request(S5PV310_GPX3(7), "hpd-plug");
> +	gpio_request(S5PV310_GPE0(1), "hdmi-en");
> +
> +	/* direct HPD to HDMI chip */
> +	gpio_direction_input(S5PV310_GPX3(7));
> +	s3c_gpio_cfgpin(S5PV310_GPX3(7), S3C_GPIO_SFN(0x3));
> +	s3c_gpio_setpull(S5PV310_GPX3(7), S3C_GPIO_PULL_NONE);

Hmm...GPIO setup should be separated like other IP.

> +
> +	/* move this names somewhere */
> +	res->hdmi = clk_get(dev, "hdmi");

Basically, clock control should be controlled in device driver part not
here.

> +	if (IS_ERR_OR_NULL(res->hdmi)) {
> +		dev_err(dev, "failed to get clock 'hdmi'\n");
> +		goto fail;
> +	}
> +	res->sclk_hdmi = clk_get(dev, "sclk_hdmi");
> +	if (IS_ERR_OR_NULL(res->sclk_hdmi)) {
> +		dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
> +		goto fail;
> +	}
> +	res->sclk_pixel = clk_get(dev, "sclk_pixel");
> +	if (IS_ERR_OR_NULL(res->sclk_pixel)) {
> +		dev_err(dev, "failed to get clock 'sclk_pixel'\n");
> +		goto fail;
> +	}
> +	res->sclk_hdmiphy = clk_get(dev, "sclk_hdmiphy");
> +	if (IS_ERR_OR_NULL(res->sclk_hdmiphy)) {
> +		dev_err(dev, "failed to get clock 'sclk_hdmiphy'\n");
> +		goto fail;
> +	}
> +	res->ldo4 = regulator_get(dev, "vadc_3.3v_c210");

Should be controlled in machine specific part?

> +	if (IS_ERR_OR_NULL(res->ldo4)) {
> +		dev_err(dev, "failed to get regulator 'ldo4'\n");
> +		goto fail;
> +	}
> +
> +	/* use VPP as parent clock; HDMIPHY is not working yet */
> +	clk_set_parent(res->sclk_hdmi, res->sclk_pixel);
> +	/* regulator_enable(res->ldo4); */
> +	tv_power_get();
> +
> +	dbg_plat_regs();
> +
> +	return 0;
> +fail:
> +	dev_err(dev, "platform HDMI Init - failed\n");
> +	hdmi_deinit(dev);
> +	return -ENODEV;
> +}
> +
> +static void hdmi_deinit(struct device *dev)
> +{
> +	struct hdmi_plat_resource *res = &hdmi_plat_resource;
> +	dev_info(dev, "platform HDMI Deinit\n");
> +	/* put clocks, power, and GPIOs */
> +	if (!IS_ERR_OR_NULL(res->ldo4)) {
> +		tv_power_put();
> +		/* regulator_disable(res->ldo4); */
> +		regulator_put(res->ldo4);
> +	}
> +	if (!IS_ERR_OR_NULL(res->sclk_hdmiphy))
> +		clk_put(res->sclk_hdmiphy);
> +	if (!IS_ERR_OR_NULL(res->sclk_pixel))
> +		clk_put(res->sclk_pixel);
> +	if (!IS_ERR_OR_NULL(res->sclk_hdmi))
> +		clk_put(res->sclk_hdmi);
> +	if (!IS_ERR_OR_NULL(res->hdmi))
> +		clk_put(res->hdmi);
> +	memset(res, 0, sizeof *res);
> +	gpio_free(S5PV310_GPE0(1));
> +	gpio_free(S5PV310_GPX3(7));
> +}
> +
> +static int hdmi_power_setup(struct device *dev, int en)
> +{
> +	struct hdmi_plat_resource *res = &hdmi_plat_resource;
> +	if (en) {
> +		dev_info(dev, "HDMI power-on\n");
> +		/* turn HDMI power on */
> +		gpio_direction_output(S5PV310_GPE0(1), 1);
> +		/* tv_power_get(); */
> +		regulator_enable(res->ldo4);
> +		/* turn clocks on */
> +		clk_enable(res->hdmi);
> +		clk_enable(res->sclk_hdmi);
> +		/* power-on hdmi physical interface */
> +		SETREG(S5P_HDMI_PHY_CONTROL, 1, 1);
> +	} else {
> +		dev_info(dev, "HDMI power-off\n");
> +		/* power-off hdmiphy */
> +		SETREG(S5P_HDMI_PHY_CONTROL, 0, 1);
> +		/* turn clocks off */
> +		clk_disable(res->sclk_hdmi);
> +		clk_disable(res->hdmi);
> +		/* turn HDMI power off */
> +		regulator_disable(res->ldo4);
> +		/* tv_power_put(); */
> +		gpio_direction_output(S5PV310_GPE0(1), 0);
> +	}
> +	dbg_plat_regs();
> +	return 0;
> +}
> +
> +static int hdmi_stream_setup(struct device *dev, int en)
> +{
> +	struct hdmi_plat_resource *res = &hdmi_plat_resource;
> +	/* NOTE: assumed HDMI power is on */
> +	if (en) {
> +		dev_info(dev, "HDMI: stream on\n");
> +		/* hdmiphy clock is used for HDMI in streaming mode */
> +		clk_disable(res->sclk_hdmi);
> +		clk_set_parent(res->sclk_hdmi, res->sclk_hdmiphy);
> +		clk_enable(res->sclk_hdmi);
> +		/* SETREG(S5P_CLKSRC_TV, 0x00000001, 0x00000001); */
> +	} else {
> +		dev_info(dev, "HDMI: stream off\n");
> +		/* pixel(vpll) clock is used for HDMI in config mode */
> +		clk_disable(res->sclk_hdmi);
> +		clk_set_parent(res->sclk_hdmi, res->sclk_pixel);
> +		clk_enable(res->sclk_hdmi);
> +		/* SETREG(S5P_CLKSRC_TV, 0x00000000, 0x00000001); */
> +	}
> +	dbg_plat_regs();
> +	return 0;
> +}
> +
> +static struct hdmi_platform_data hdmi_pdata = {
> +	.init = hdmi_init,
> +	.deinit = hdmi_deinit,
> +	.power_setup = hdmi_power_setup,
> +	.stream_setup = hdmi_stream_setup,
> +};

Why does above things go to driver via hdmi_platform_data?

> +
> +/* MIXER */
> +static struct resource s5p_mixer_resources[] = {
> +	[0] = {
> +		.start  = S5P_PA_MIXER,
                      ^^
> +		.end    = S5P_PA_MIXER + S5P_SZ_MIXER - 1,
                    ^^^^
> +		.flags  = IORESOURCE_MEM,
                      ^^
Please use tab...

> +		.name	= "mxr"
> +	},
> +	[1] = {
> +		.start  = S5P_PA_VP,
                      ^^
> +		.end    = S5P_PA_VP + S5P_SZ_VP - 1,
                    ^^^^
> +		.flags  = IORESOURCE_MEM,
                      ^^
> +		.name	= "vp"
> +	},
> +	[2] = {
> +		.start  = IRQ_MIXER,
                      ^^
> +		.end    = IRQ_MIXER,
                    ^^^^
> +		.flags  = IORESOURCE_IRQ,
                      ^^
> +		.name	= "irq"
> +	},
> +};
> +
> +static struct mxr_platform_data mxr_pdata;
> +
> +struct platform_device s5p_device_mixer = {
> +	.name           = "s5p-mixer",
             ^^^^^^^^^^^
> +	.id             = -1,
           ^^^^^^^^^^^^^
> +	.num_resources  = ARRAY_SIZE(s5p_mixer_resources),
                      ^^
> +	.resource       = s5p_mixer_resources,
                 ^^^^^^^
> +	.dev		= {
> +		.coherent_dma_mask = DMA_BIT_MASK(32),
> +		.dma_mask = &s5p_device_mixer.dev.coherent_dma_mask,

How about following?

static u64 s5pv310_mixer_dmamask = DMA_BIT_MASK(32);
...
+		.dma_mask = &s5pv310_mixer_dmamask,
...

> +		.platform_data = &mxr_pdata,
> +	}
> +};
> +EXPORT_SYMBOL(s5p_device_mixer);

Same...no need this.

> +
> +static struct mxr_plat_resource {
> +	struct clk *mixer;
> +	struct clk *vp;
> +	struct clk *sclk_mixer;
> +	struct clk *sclk_hdmi;
> +	struct clk *sclk_dac;
> +	struct regulator *ldo4;
> +} mxr_plat_resource;
> +
> +static void mxr_deinit(struct device *dev);
> +
> +static int mxr_init(struct device *dev)
> +{
> +	struct mxr_plat_resource *res = &mxr_plat_resource;
> +	dev_info(dev, "platform Mixer Init\n");
> +	res->mixer = clk_get(dev, "mixer");
> +	if (IS_ERR_OR_NULL(res->mixer)) {
> +		dev_err(dev, "failed to get clock 'mixer'\n");
> +		goto fail;
> +	}
> +	res->vp = clk_get(dev, "vp");
> +	if (IS_ERR_OR_NULL(res->vp)) {
> +		dev_err(dev, "failed to get clock 'vp'\n");
> +		goto fail;
> +	}
> +	res->sclk_mixer = clk_get(dev, "sclk_mixer");
> +	if (IS_ERR_OR_NULL(res->sclk_mixer)) {
> +		dev_err(dev, "failed to get clock 'sclk_mixer'\n");
> +		goto fail;
> +	}
> +	res->sclk_hdmi = clk_get(dev, "sclk_hdmi");
> +	if (IS_ERR_OR_NULL(res->sclk_hdmi)) {
> +		dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
> +		goto fail;
> +	}
> +	res->sclk_dac = clk_get(dev, "sclk_dac");
> +	if (IS_ERR_OR_NULL(res->sclk_dac)) {
> +		dev_err(dev, "failed to get clock 'sclk_dac'\n");
> +		goto fail;
> +	}
> +	res->ldo4 = regulator_get(dev, "vadc_3.3v_c210");
> +	if (IS_ERR_OR_NULL(res->ldo4)) {
> +		dev_err(dev, "failed to get regulator 'ldo4'\n");
> +		goto fail;
> +	}
> +	/* regulator_enable(res->ldo4); */
> +	tv_power_get();
> +
> +	/* XXX: fixed connetction between MIXER and HDMI */
> +	clk_set_parent(res->sclk_mixer, res->sclk_hdmi);
> +	dbg_plat_regs();
> +	return 0;
> +fail:
> +	dev_err(dev, "platform Mixer Init - failed\n");
> +	mxr_deinit(dev);
> +	return -ENODEV;
> +}
> +
> +static void mxr_deinit(struct device *dev)
> +{
> +	struct mxr_plat_resource *res = &mxr_plat_resource;
> +	dev_info(dev, "platform Mixer denit\n");
> +	if (!IS_ERR_OR_NULL(res->ldo4)) {
> +		tv_power_put();
> +		/* regulator_disable(res->ldo4); */
> +		regulator_put(res->ldo4);
> +	}
> +	if (!IS_ERR_OR_NULL(res->sclk_dac))
> +		clk_put(res->sclk_dac);
> +	if (!IS_ERR_OR_NULL(res->sclk_hdmi))
> +		clk_put(res->sclk_hdmi);
> +	if (!IS_ERR_OR_NULL(res->sclk_mixer))
> +		clk_put(res->sclk_mixer);
> +	if (!IS_ERR_OR_NULL(res->vp))
> +		clk_put(res->vp);
> +	if (!IS_ERR_OR_NULL(res->mixer))
> +		clk_put(res->mixer);
> +	memset(res, 0, sizeof *res);
> +}
> +
> +static int mxr_power_setup(struct device *dev, int en)
> +{
> +	struct mxr_plat_resource *res = &mxr_plat_resource;
> +	/* enable/disable clocks, power, and GPIOs */
> +	if (en) {
> +		dev_info(dev, "MIXER power-on\n");
> +		/* turn MIXER power on */
> +		/* tv_power_get(); */
> +		regulator_enable(res->ldo4);
> +		/* turn clocks on */
> +		clk_enable(res->mixer);
> +		clk_enable(res->vp);
> +		clk_enable(res->sclk_mixer);
> +		/* HDMI CEC (no support) */
> +		/* SETREG(S5P_CLKGATE_IP_PERIR, ~0, 1 << 11); */
> +		/* keep here */
> +	} else {
> +		dev_info(dev, "MIXER power-off\n");
> +		/* turn clocks off */
> +		clk_disable(res->sclk_mixer);
> +		clk_disable(res->vp);
> +		clk_disable(res->mixer);
> +		/* turn MIXER power off */
> +		regulator_disable(res->ldo4);
> +		/* tv_power_put(); */
> +	}
> +	dbg_plat_regs();
> +	return 0;
> +}
> +
> +static struct mxr_platform_output output[] = {
> +	{ .output_name = "S5P HDMI connector", .module_name = "s5p-hdmi" },
> +};
> +
> +static struct mxr_platform_data mxr_pdata = {
> +	.output = output,
> +	.output_cnt = ARRAY_SIZE(output),
> +	.init = mxr_init,
> +	.deinit = mxr_deinit,
> +	.power_setup = mxr_power_setup,
> +};
> +
> +static void dbg_plat_regs(void)
> +{
> +	DBGREG(S5P_CLKSRC_TV);
> +	DBGREG(S5P_CLKSRC_MASK_TV);
> +	DBGREG(S5P_CLKGATE_IP_TV);
> +	DBGREG(S5P_CLKGATE_IP_PERIL); /* remove (unknown?) */
> +	DBGREG(S5P_CLKGATE_IP_PERIL); /* I2C HDMI (I2C8) remove */
> +	DBGREG(S5P_CLKGATE_IP_PERIR); /* HDMI CEC remove (no support) */
> +	DBGREG(S5P_CLKGATE_BLOCK); /* keep here */
> +	DBGREG(S5P_CLKSRC_TOP0);
> +	DBGREG(S5P_CLKSRC_TOP1);
> +	DBGREG(S5P_HDMI_PHY_CONTROL);
> +	DBGREG(S5P_CMU_CLKSTOP_TV_SYS_PWR);
> +	DBGREG(S5P_CMU_RESET_TV_SYS_PWR);
> +	DBGREG(S5P_TV_SYS_PWR);
> +	DBGREG(S5P_TV_CONFIGURATION);
> +	DBGREG(S5P_TV_STATUS);
> +	DBGREG(S5P_CLKDIV_TV);
> +}
> diff --git a/arch/arm/mach-s5pv310/include/mach/irqs.h b/arch/arm/mach-
> s5pv310/include/mach/irqs.h
> index 0ba778b..76cfe4d 100644
> --- a/arch/arm/mach-s5pv310/include/mach/irqs.h
> +++ b/arch/arm/mach-s5pv310/include/mach/irqs.h
> @@ -116,6 +116,10 @@
> 
>  #define IRQ_MCT_L1		COMBINER_IRQ(35, 3)
> 
> +/* Set the default NR_IRQS */

What's this?

> +#define IRQ_MIXER		COMBINER_IRQ(36, 0)
> +#define IRQ_TVENC		COMBINER_IRQ(36, 1)
> +
>  #define IRQ_EINT4		COMBINER_IRQ(37, 0)
>  #define IRQ_EINT5		COMBINER_IRQ(37, 1)
>  #define IRQ_EINT6		COMBINER_IRQ(37, 2)
> diff --git a/arch/arm/mach-s5pv310/include/mach/map.h b/arch/arm/mach-
> s5pv310/include/mach/map.h
> index 845b739..acc2a71 100644
> --- a/arch/arm/mach-s5pv310/include/mach/map.h
> +++ b/arch/arm/mach-s5pv310/include/mach/map.h
> @@ -147,4 +147,30 @@
>  #define S5P_PA_MIPI_CSIS0		S5PV310_PA_MIPI_CSIS0
>  #define S5P_PA_MIPI_CSIS1		S5PV310_PA_MIPI_CSIS1
> 
> +/* CEC */

No need comment.

> +#define S5PV210_PA_CEC		(0x100B0000)

1. S5PV310_PA_XXX.
2. No need brace around address.
3. Please re-work this based on my latest for-next, because did cleanup
map.h

> +#define S5P_PA_CEC		S5PV210_PA_CEC

I don't think, need S5P_PA_XXX for compatibility. Because current dev-tv.c
is for only mach-s5pv310.

> +#define S5P_SZ_CEC		SZ_4K

Just use SZ macro directly in platform device.

> +
> +/* TVOUT */
> +#define S5PV210_PA_TVENC	(0x12C20000)
> +#define S5P_PA_TVENC		S5PV210_PA_TVENC
> +#define S5P_SZ_TVENC		SZ_64K
> +
Same as above.

> +#define S5PV210_PA_VP		(0x12C00000)
> +#define S5P_PA_VP		S5PV210_PA_VP
> +#define S5P_SZ_VP		SZ_64K
> +
Same as above.

> +#define S5PV210_PA_MIXER	(0x12C10000)
> +#define S5P_PA_MIXER		S5PV210_PA_MIXER
> +#define S5P_SZ_MIXER		SZ_64K
> +
Same as above.

> +#define S5PV210_PA_HDMI		(0x12D00000)
> +#define S5P_PA_HDMI		S5PV210_PA_HDMI
> +#define S5P_SZ_HDMI		SZ_1M
> +
Same as above.

> +#define S5PV210_I2C_HDMI_PHY	(0x138E0000)
> +#define S5P_I2C_HDMI_PHY	S5PV210_I2C_HDMI_PHY
> +#define S5P_I2C_HDMI_SZ_PHY	SZ_1K
> +
Same as above.

>  #endif /* __ASM_ARCH_MAP_H */
> diff --git a/arch/arm/mach-s5pv310/include/mach/regs-clock.h
b/arch/arm/mach-
> s5pv310/include/mach/regs-clock.h
> index b5c4ada..b1af66c 100644
> --- a/arch/arm/mach-s5pv310/include/mach/regs-clock.h
> +++ b/arch/arm/mach-s5pv310/include/mach/regs-clock.h
> @@ -33,6 +33,7 @@
>  #define S5P_CLKSRC_TOP0			S5P_CLKREG(0x0C210)
>  #define S5P_CLKSRC_TOP1			S5P_CLKREG(0x0C214)
>  #define S5P_CLKSRC_CAM			S5P_CLKREG(0x0C220)
> +#define S5P_CLKSRC_TV			S5P_CLKREG(0x0C224)
>  #define S5P_CLKSRC_IMAGE		S5P_CLKREG(0x0C230)
>  #define S5P_CLKSRC_LCD0			S5P_CLKREG(0x0C234)
>  #define S5P_CLKSRC_LCD1			S5P_CLKREG(0x0C238)
> @@ -42,6 +43,7 @@
> 
>  #define S5P_CLKDIV_TOP			S5P_CLKREG(0x0C510)
>  #define S5P_CLKDIV_CAM			S5P_CLKREG(0x0C520)
> +#define S5P_CLKDIV_TV			S5P_CLKREG(0x0C524)
>  #define S5P_CLKDIV_IMAGE		S5P_CLKREG(0x0C530)
>  #define S5P_CLKDIV_LCD0			S5P_CLKREG(0x0C534)
>  #define S5P_CLKDIV_LCD1			S5P_CLKREG(0x0C538)
> @@ -58,6 +60,7 @@
> 
>  #define S5P_CLKSRC_MASK_TOP		S5P_CLKREG(0x0C310)
>  #define S5P_CLKSRC_MASK_CAM		S5P_CLKREG(0x0C320)
> +#define S5P_CLKSRC_MASK_TV		S5P_CLKREG(0x0C324)
>  #define S5P_CLKSRC_MASK_LCD0		S5P_CLKREG(0x0C334)
>  #define S5P_CLKSRC_MASK_LCD1		S5P_CLKREG(0x0C338)
>  #define S5P_CLKSRC_MASK_FSYS		S5P_CLKREG(0x0C340)
> @@ -67,6 +70,7 @@
>  #define S5P_CLKDIV_STAT_TOP		S5P_CLKREG(0x0C610)
> 
>  #define S5P_CLKGATE_IP_CAM		S5P_CLKREG(0x0C920)
> +#define S5P_CLKGATE_IP_TV		S5P_CLKREG(0x0C924)
>  #define S5P_CLKGATE_IP_IMAGE		S5P_CLKREG(0x0C930)
>  #define S5P_CLKGATE_IP_LCD0		S5P_CLKREG(0x0C934)
>  #define S5P_CLKGATE_IP_LCD1		S5P_CLKREG(0x0C938)
> @@ -164,4 +168,15 @@
> 
>  #define S5P_EPLL_CON			S5P_EPLL_CON0
> 
> +/* TVOUT related */
> +#define S5P_TV_CONFIGURATION		S5P_PMUREG(0x03C20)
> +#define S5P_TV_STATUS			S5P_PMUREG(0x03C24)
> +#define S5P_TV_SYS_PWR			S5P_PMUREG(0x1384)
> +#define S5P_CMU_CLKSTOP_TV_SYS_PWR	S5P_PMUREG(0x1144)
> +#define S5P_CMU_RESET_TV_SYS_PWR	S5P_PMUREG(0x1164)
> +
> +#define S5P_HDMI_PHY_CONTROL		S5P_PMUREG(0x0700)
> +#define S5P_CLKOUT_CMU_TOP		S5P_CLKREG(0x0CA00)
> +#define S5P_PMU_DEBUG			S5P_PMUREG(0x0A00)
> +
Hmm...Why are regarding PMU registers in here not regs-pmu.h?

>  #endif /* __ASM_ARCH_REGS_CLOCK_H */
> diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-
> samsung/include/plat/devs.h
> index 6effbb4..a6b78d4 100644
> --- a/arch/arm/plat-samsung/include/plat/devs.h
> +++ b/arch/arm/plat-samsung/include/plat/devs.h
> @@ -134,6 +134,8 @@ extern struct platform_device samsung_device_keypad;
>  extern struct platform_device s5p_device_fimc0;
>  extern struct platform_device s5p_device_fimc1;
>  extern struct platform_device s5p_device_fimc2;
> +extern struct platform_device s5p_device_hdmi;
> +extern struct platform_device s5p_device_mixer;
> 
>  extern struct platform_device s5p_device_mipi_csis0;
>  extern struct platform_device s5p_device_mipi_csis1;
> --


Thanks.

Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.


^ permalink raw reply	[flat|nested] 23+ messages in thread

* RE: [PATCH 2/5] universal: i2c: add I2C controller 8 (HDMIPHY)
  2011-02-08  9:30 ` [PATCH 2/5] universal: i2c: add I2C controller 8 (HDMIPHY) Tomasz Stanislawski
@ 2011-02-09  6:54   ` Kukjin Kim
  0 siblings, 0 replies; 23+ messages in thread
From: Kukjin Kim @ 2011-02-09  6:54 UTC (permalink / raw)
  To: 'Tomasz Stanislawski', linux-media, linux-samsung-soc
  Cc: m.szyprowski, kyungmin.park, ben-linux

Tomasz Stanislawski wrote:
> 
> Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> ---
>  arch/arm/mach-s5pv310/clock.c             |    6 +++
>  arch/arm/mach-s5pv310/include/mach/irqs.h |    4 ++
>  arch/arm/mach-s5pv310/include/mach/map.h  |    1 +
>  arch/arm/plat-samsung/Kconfig             |    5 ++
>  arch/arm/plat-samsung/Makefile            |    1 +
>  arch/arm/plat-samsung/dev-i2c8.c          |   68
> +++++++++++++++++++++++++++++
>  arch/arm/plat-samsung/include/plat/devs.h |    1 +
>  arch/arm/plat-samsung/include/plat/iic.h  |    1 +
>  8 files changed, 87 insertions(+), 0 deletions(-)
>  create mode 100644 arch/arm/plat-samsung/dev-i2c8.c
> 

Cc'ed Ben Dooks.

> diff --git a/arch/arm/mach-s5pv310/clock.c b/arch/arm/mach-s5pv310/clock.c
> index fc7c2f8..6161b54 100644
> --- a/arch/arm/mach-s5pv310/clock.c
> +++ b/arch/arm/mach-s5pv310/clock.c
> @@ -589,6 +589,12 @@ static struct clk init_clocks_off[] = {
>  		.parent		= &clk_aclk_100.clk,
>  		.enable		= s5pv310_clk_ip_peril_ctrl,
>  		.ctrlbit	= (1 << 13),
> +	}, {
> +		.name           = "i2c",
                     ^^^^^^^^^^^
> +		.id             = 8,
                   ^^^^^^^^^^^^^
> +		.parent         = &clk_aclk_100.clk,
                       ^^^^^^^^^
> +		.enable         = s5pv310_clk_ip_peril_ctrl,
                       ^^^^^^^^^
> +		.ctrlbit        = (1 << 14),
                        ^^^^^^^^
Please use tab.

>  	},
>  };
> 
> diff --git a/arch/arm/mach-s5pv310/include/mach/irqs.h b/arch/arm/mach-
> s5pv310/include/mach/irqs.h
> index 536b0b5..0ba778b 100644
> --- a/arch/arm/mach-s5pv310/include/mach/irqs.h
> +++ b/arch/arm/mach-s5pv310/include/mach/irqs.h
> @@ -76,6 +76,9 @@
>  #define IRQ_PDMA0		COMBINER_IRQ(21, 0)
>  #define IRQ_PDMA1		COMBINER_IRQ(21, 1)
> 
> +#define IRQ_HDMI		COMBINER_IRQ(16, 0)

To add IRQ_HDMI should be moved in other patch file.

> +#define IRQ_HDMI_I2C		COMBINER_IRQ(16, 1)
> +

Would be better keep the ordering by number.

>  #define IRQ_TIMER0_VIC		COMBINER_IRQ(22, 0)
>  #define IRQ_TIMER1_VIC		COMBINER_IRQ(22, 1)
>  #define IRQ_TIMER2_VIC		COMBINER_IRQ(22, 2)
> @@ -99,6 +102,7 @@
>  #define IRQ_IIC5		COMBINER_IRQ(27, 5)
>  #define IRQ_IIC6		COMBINER_IRQ(27, 6)
>  #define IRQ_IIC7		COMBINER_IRQ(27, 7)
> +#define IRQ_IIC8		IRQ_HDMI_I2C
> 
>  #define IRQ_HSMMC0		COMBINER_IRQ(29, 0)
>  #define IRQ_HSMMC1		COMBINER_IRQ(29, 1)
> diff --git a/arch/arm/mach-s5pv310/include/mach/map.h b/arch/arm/mach-
> s5pv310/include/mach/map.h
> index 74d4006..845b739 100644
> --- a/arch/arm/mach-s5pv310/include/mach/map.h
> +++ b/arch/arm/mach-s5pv310/include/mach/map.h
> @@ -141,6 +141,7 @@
>  #define S3C_PA_IIC5			S5PV310_PA_IIC(5)
>  #define S3C_PA_IIC6			S5PV310_PA_IIC(6)
>  #define S3C_PA_IIC7			S5PV310_PA_IIC(7)
> +#define S3C_PA_IIC8			S5PV310_PA_IIC(8)
>  #define S3C_PA_RTC			S5PV310_PA_RTC
>  #define S3C_PA_WDT			S5PV310_PA_WATCHDOG
>  #define S5P_PA_MIPI_CSIS0		S5PV310_PA_MIPI_CSIS0
> diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
> index 32be05c..dd1fd15 100644
> --- a/arch/arm/plat-samsung/Kconfig
> +++ b/arch/arm/plat-samsung/Kconfig
> @@ -211,6 +211,11 @@ config S3C_DEV_I2C7
>  	help
>  	  Compile in platform device definition for I2C controller 7
> 
> +config S3C_DEV_I2C8
> +	bool
> +	help
> +	  Compile in platform device definitions for I2C channel 8 (HDMIPHY)

I don't think, I2C8 is dedicated to HDMI PHY. So following is enough.

+	  Compile in platform device definitions for I2C channel 8

> +
>  config S3C_DEV_FB
>  	bool
>  	help
> diff --git a/arch/arm/plat-samsung/Makefile
b/arch/arm/plat-samsung/Makefile
> index 29932f8..5df8db7 100644
> --- a/arch/arm/plat-samsung/Makefile
> +++ b/arch/arm/plat-samsung/Makefile
> @@ -46,6 +46,7 @@ obj-$(CONFIG_S3C_DEV_I2C4)	+= dev-i2c4.o
>  obj-$(CONFIG_S3C_DEV_I2C5)	+= dev-i2c5.o
>  obj-$(CONFIG_S3C_DEV_I2C6)	+= dev-i2c6.o
>  obj-$(CONFIG_S3C_DEV_I2C7)	+= dev-i2c7.o
> +obj-$(CONFIG_S3C_DEV_I2C8)	+= dev-i2c8.o
>  obj-$(CONFIG_S3C_DEV_FB)	+= dev-fb.o
>  obj-y				+= dev-uart.o
>  obj-$(CONFIG_S3C_DEV_USB_HOST)	+= dev-usb.o
> diff --git a/arch/arm/plat-samsung/dev-i2c8.c b/arch/arm/plat-samsung/dev-
> i2c8.c
> new file mode 100644
> index 0000000..8edba7f
> --- /dev/null
> +++ b/arch/arm/plat-samsung/dev-i2c8.c
> @@ -0,0 +1,68 @@
> +/* linux/arch/arm/plat-samsung/dev-i2c7.c

+/* linux/arch/arm/plat-samsung/dev-i2c8.c

> + *
> + * Copyright (c) 2010 Samsung Electronics Co., Ltd.
> + *		http://www.samsung.com/
> + *
> + * S3C series device definition for i2c device 8
> + *
> + * Based on plat-samsung/dev-i2c8.c
> + *
> + * 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/gfp.h>
> +#include <linux/kernel.h>
> +#include <linux/string.h>
> +#include <linux/platform_device.h>
> +
> +#include <mach/irqs.h>
> +#include <mach/map.h>
> +
> +#include <plat/regs-iic.h>
> +#include <plat/iic.h>
> +#include <plat/devs.h>
> +#include <plat/cpu.h>
> +
> +static struct resource s3c_i2c_resource[] = {
> +	[0] = {
> +		.start = S3C_PA_IIC8,
                      ^
> +		.end   = S3C_PA_IIC8 + SZ_4K - 1,
                    ^^^
> +		.flags = IORESOURCE_MEM,
                      ^
> +	},
> +	[1] = {
> +		.start = IRQ_IIC8,
                      ^
> +		.end   = IRQ_IIC8,
                    ^^^
> +		.flags = IORESOURCE_IRQ,
                      ^
> +	},
> +};
> +
> +struct platform_device s3c_device_i2c8 = {
> +	.name		  = "s3c2440-hdmiphy-i2c",
                        ^^
Hmm...you used tab and white spaces between .name and =.

> +	.id		  = 8,
                        ^^
> +	.num_resources	  = ARRAY_SIZE(s3c_i2c_resource),
                        ^^
> +	.resource	  = s3c_i2c_resource,
                        ^^
> +};
> +
> +static struct s3c2410_platform_i2c default_i2c_data8 __initdata = {
> +	.flags		= 0,
> +	.bus_num	= 8,
> +	.slave_addr	= 0x10,
> +	.frequency	= 400*1000,

Why is default frequency 400*1000 not 100*1000 like others?

> +	.sda_delay	= 100,
> +};
> +
> +void __init s3c_i2c8_set_platdata(struct s3c2410_platform_i2c *pd)
> +{
> +	struct s3c2410_platform_i2c *npd;
> +
> +	if (!pd)
> +		pd = &default_i2c_data8;
> +
> +	npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL);
> +	if (!npd)
> +		printk(KERN_ERR "%s: no memory for platform data\n",
__func__);
> +
> +	s3c_device_i2c8.dev.platform_data = npd;
> +}
> diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-
> samsung/include/plat/devs.h
> index b4d208b..6effbb4 100644
> --- a/arch/arm/plat-samsung/include/plat/devs.h
> +++ b/arch/arm/plat-samsung/include/plat/devs.h
> @@ -53,6 +53,7 @@ extern struct platform_device s3c_device_i2c4;
>  extern struct platform_device s3c_device_i2c5;
>  extern struct platform_device s3c_device_i2c6;
>  extern struct platform_device s3c_device_i2c7;
> +extern struct platform_device s3c_device_i2c8;
>  extern struct platform_device s3c_device_rtc;
>  extern struct platform_device s3c_device_adc;
>  extern struct platform_device s3c_device_sdi;
> diff --git a/arch/arm/plat-samsung/include/plat/iic.h b/arch/arm/plat-
> samsung/include/plat/iic.h
> index 1543da8..dd0d728 100644
> --- a/arch/arm/plat-samsung/include/plat/iic.h
> +++ b/arch/arm/plat-samsung/include/plat/iic.h
> @@ -60,6 +60,7 @@ extern void s3c_i2c4_set_platdata(struct
> s3c2410_platform_i2c *i2c);
>  extern void s3c_i2c5_set_platdata(struct s3c2410_platform_i2c *i2c);
>  extern void s3c_i2c6_set_platdata(struct s3c2410_platform_i2c *i2c);
>  extern void s3c_i2c7_set_platdata(struct s3c2410_platform_i2c *i2c);
> +extern void s3c_i2c8_set_platdata(struct s3c2410_platform_i2c *i2c);
> 
>  /* defined by architecture to configure gpio */
>  extern void s3c_i2c0_cfg_gpio(struct platform_device *dev);
> --
> 1.7.3.5
> 

Thanks.

Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH/RFC 0/5] HDMI driver for Samsung S5PV310 platform
  2011-02-08 22:47     ` Andy Walls
@ 2011-02-09  7:12       ` Alex Deucher
  2011-02-09 19:00         ` Matt Turner
  2011-02-10  0:51         ` Andy Walls
  0 siblings, 2 replies; 23+ messages in thread
From: Alex Deucher @ 2011-02-09  7:12 UTC (permalink / raw)
  To: Andy Walls
  Cc: Hans Verkuil, Tomasz Stanislawski, linux-media,
	linux-samsung-soc, m.szyprowski, kyungmin.park,
	Maling list - DRI developers

On Tue, Feb 8, 2011 at 5:47 PM, Andy Walls <awalls@md.metrocast.net> wrote:
> On Tue, 2011-02-08 at 10:28 -0500, Alex Deucher wrote:
>> On Tue, Feb 8, 2011 at 4:47 AM, Hans Verkuil <hansverk@cisco.com> wrote:
>> > Just two quick notes. I'll try to do a full review this weekend.
>> >
>> > On Tuesday, February 08, 2011 10:30:22 Tomasz Stanislawski wrote:
>> >> ==============
>> >>  Introduction
>> >> ==============
>> >>
>> >> The purpose of this RFC is to discuss the driver for a TV output interface
>> >> available in upcoming Samsung SoC. The HW is able to generate digital and
>> >> analog signals. Current version of the driver supports only digital output.
>> >>
>> >> Internally the driver uses videobuf2 framework, and CMA memory allocator.
>> > Not
>> >> all of them are merged by now, but I decided to post the sources to start
>> >> discussion driver's design.
>
>> >
>> > Cisco (i.e. a few colleagues and myself) are working on this. We hope to post
>> > an RFC by the end of this month. We also have a proposal for CEC support in
>> > the pipeline.
>>
>> Any reason to not use the drm kms APIs for modesetting, display
>> configuration, and hotplug support?  We already have the
>> infrastructure in place for complex display configurations and
>> generating events for hotplug interrupts.  It would seem to make more
>> sense to me to fix any deficiencies in the KMS APIs than to spin a new
>> API.  Things like CEC would be a natural fit since a lot of desktop
>> GPUs support hdmi audio/3d/etc. and are already using kms.
>>
>> Alex
>
> I'll toss one out: lack of API documentation for driver or application
> developers to use.
>
>
> When I last looked at converting ivtvfb to use DRM, KMS, TTM, etc. (to
> possibly get rid of reliance on the ivtv X video driver
> http://dl.ivtvdriver.org/xf86-video-ivtv/ ), I found the documentation
> was really sparse.
>
> DRM had the most documentation under Documentation/DocBook/drm.tmpl, but
> the userland API wasn't fleshed out.  GEM was talked about a bit in
> there as well, IIRC.
>
> TTM documentation was essentially non-existant.
>
> I can't find any KMS documentation either.
>
> I recall having to read much of the drm code, and having to look at the
> radeon driver, just to tease out what the DRM ioctls needed to do.
>
> Am I missing a Documentation source for the APIs?
>

Documentation is somewhat sparse compared to some other APIs.  Mostly
inline kerneldoc comments in the core functions.  It would be nice to
improve things.   The modesetting API is very similar to the xrandr
API in the xserver.

At the moment a device specific surface manager (Xorg ddx, or some
other userspace lib) is required to use kms due to device specific
requirements with respect to memory management and alignment for
acceleration.  The kms modesetting ioctls are common across all kms
drm drivers, but the memory management ioctls are device specific.
GEM itself is an Intel-specific memory manager, although radeon uses
similar ioctls.  TTM is used internally by radeon, nouveau, and svga
for managing memory gpu accessible memory pools.  Drivers are free to
use whatever memory manager they want; an existing one shared with a
v4l or platform driver, TTM, or something new.  There is no generic
userspace kms driver/lib although Dave and others have done some work
to support that, but it's really hard to make a generic interface
flexible enough to handle all the strange acceleration requirements of
GPUs.  kms does however provide a legacy kernel fb interface.

While the documentation is not great, the modesetting API is solid and
it would be nice to get more people involved and working on it (or at
least looking at it) rather than starting something equivalent from
scratch or implementing a device specific modesetting API.  If you
have any questions about it, please ask on dri-devel (CCed).

Alex

>
>
> For V4L2 and DVB on ther other hand, one can point to pretty verbose
> documentation that application developers can use:
>
>        http://linuxtv.org/downloads/v4l-dvb-apis/
>
>
>
> Regards,
> Andy
>
>
>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* RE: [PATCH 1/5] i2c-s3c2410: fix I2C dedicated for hdmiphy
  2011-02-08  9:30 ` [PATCH 1/5] i2c-s3c2410: fix I2C dedicated for hdmiphy Tomasz Stanislawski
@ 2011-02-09  7:14   ` Kukjin Kim
  0 siblings, 0 replies; 23+ messages in thread
From: Kukjin Kim @ 2011-02-09  7:14 UTC (permalink / raw)
  To: 'Tomasz Stanislawski', linux-media, linux-samsung-soc
  Cc: m.szyprowski, kyungmin.park, ben-linux

Tomasz Stanislawski wrote:
> 
> The I2C HDMIPHY dedicated controller has different timeout
> handling and reset conditions.
> 
> Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> ---
>  drivers/i2c/busses/i2c-s3c2410.c |   36
+++++++++++++++++++++++++++++++++++-
>  1 files changed, 35 insertions(+), 1 deletions(-)
> 

Cc'ed Ben Dooks who is a maintainer of I2C and Samsung architecture also.

> diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-
> s3c2410.c
> index 6c00c10..99cfe2f 100644
> --- a/drivers/i2c/busses/i2c-s3c2410.c
> +++ b/drivers/i2c/busses/i2c-s3c2410.c
> @@ -54,6 +54,7 @@ enum s3c24xx_i2c_state {
>  enum s3c24xx_i2c_type {
>  	TYPE_S3C2410,
>  	TYPE_S3C2440,
> +	TYPE_S3C2440_HDMIPHY,
>  };
> 
>  struct s3c24xx_i2c {
> @@ -96,7 +97,21 @@ static inline int s3c24xx_i2c_is2440(struct s3c24xx_i2c
> *i2c)
>  	enum s3c24xx_i2c_type type;
> 
>  	type = platform_get_device_id(pdev)->driver_data;
> -	return type == TYPE_S3C2440;
> +	return type == TYPE_S3C2440 || type == TYPE_S3C2440_HDMIPHY;
> +}
> +
> +/* s3c24xx_i2c_is2440_hdmiphy()
> + *
> + * return true is this is an s3c2440 dedicated for HDMIPHY interface
> +*/
> +
> +static inline int s3c24xx_i2c_is2440_hdmiphy(struct s3c24xx_i2c *i2c)
> +{
> +	struct platform_device *pdev = to_platform_device(i2c->dev);
> +	enum s3c24xx_i2c_type type;
> +
> +	type = platform_get_device_id(pdev)->driver_data;
> +	return type == TYPE_S3C2440_HDMIPHY;
>  }
> 
>  /* s3c24xx_i2c_master_complete
> @@ -461,6 +476,13 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c
> *i2c)
>  	unsigned long iicstat;
>  	int timeout = 400;
> 
> +	/* if hang-up of HDMIPHY occured reduce timeout
> +	 * The controller will work after reset, so waiting
> +	 * 400 ms will cause unneccessary system hangup
> +	 */
> +	if (s3c24xx_i2c_is2440_hdmiphy(i2c))
> +		timeout = 10;
> +
>  	while (timeout-- > 0) {
>  		iicstat = readl(i2c->regs + S3C2410_IICSTAT);
> 
> @@ -470,6 +492,15 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c
> *i2c)
>  		msleep(1);
>  	}
> 
> +	/* hang-up of bus dedicated for HDMIPHY occured, resetting */
> +	if (s3c24xx_i2c_is2440_hdmiphy(i2c)) {
> +		writel(0, i2c->regs + S3C2410_IICCON);
> +		writel(0, i2c->regs + S3C2410_IICSTAT);
> +		writel(0, i2c->regs + S3C2410_IICDS);
> +
> +		return 0;
> +	}
> +
>  	return -ETIMEDOUT;
>  }
> 
> @@ -1009,6 +1040,9 @@ static struct platform_device_id
s3c24xx_driver_ids[] =
> {
>  	}, {
>  		.name		= "s3c2440-i2c",
>  		.driver_data	= TYPE_S3C2440,
> +	}, {
> +		.name		= "s3c2440-hdmiphy-i2c",
> +		.driver_data	= TYPE_S3C2440_HDMIPHY,
>  	}, { },
>  };
>  MODULE_DEVICE_TABLE(platform, s3c24xx_driver_ids);
> --


Thanks.

Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH/RFC 0/5] HDMI driver for Samsung S5PV310 platform
  2011-02-08 15:28   ` Alex Deucher
  2011-02-08 22:47     ` Andy Walls
@ 2011-02-09  8:59     ` Hans Verkuil
  2011-02-09 17:55       ` Alex Deucher
  1 sibling, 1 reply; 23+ messages in thread
From: Hans Verkuil @ 2011-02-09  8:59 UTC (permalink / raw)
  To: Alex Deucher
  Cc: Tomasz Stanislawski, linux-media, linux-samsung-soc,
	m.szyprowski, kyungmin.park

On Tuesday, February 08, 2011 16:28:32 Alex Deucher wrote:
> On Tue, Feb 8, 2011 at 4:47 AM, Hans Verkuil <hansverk@cisco.com> wrote:

<snip>

> >>   The driver supports an interrupt. It is used to detect plug/unplug 
events
> > in
> >> kernel debugs.  The API for detection of such an events in V4L2 API is to 
be
> >> defined.
> >
> > Cisco (i.e. a few colleagues and myself) are working on this. We hope to 
post
> > an RFC by the end of this month. We also have a proposal for CEC support 
in
> > the pipeline.
> 
> Any reason to not use the drm kms APIs for modesetting, display
> configuration, and hotplug support?  We already have the
> infrastructure in place for complex display configurations and
> generating events for hotplug interrupts.  It would seem to make more
> sense to me to fix any deficiencies in the KMS APIs than to spin a new
> API.  Things like CEC would be a natural fit since a lot of desktop
> GPUs support hdmi audio/3d/etc. and are already using kms.

There are various reasons for not going down that road. The most important one 
is that mixing APIs is actually a bad idea. I've done that once in the past 
and I've regretted ever since. The problem with doing that is that it is 
pretty hard on applications who have to mix two different styles of API, 
somehow know where to find the documentation for each and know that both APIs 
can in fact be used on the same device.

Now, if there was a lot of code that could be shared, then that might be 
enough reason to go that way, but in practice there is very little overlap. 
Take CEC: all the V4L API will do is to pass the CEC packets from kernel to 
userspace and vice versa. There is no parsing at all. This is typically used 
by embedded apps that want to do their own CEC processing.

An exception might be a PCI(e) card with HDMI input/output that wants to 
handle CEC internally. At that point we might look at sharing CEC parsing 
code. A similar story is true for EDID handling.

One area that might be nice to look at would be to share drivers for HDMI 
receivers and transmitters. However, the infrastructure for such drivers is 
wildly different between how it is used for GPUs versus V4L and has been for 
10 years or so. I also suspect that most GPUs have there own HDMI internal 
implementation so code sharing will probably be quite limited.

So, no, there are no plans to share anything between the two (except perhaps 
EDID and CEC parsing should that become relevant).

Oh, and let me join Andy in saying that the drm/kms/whatever API documentation 
*really* needs a lot of work.

Regards,

	Hans

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH/RFC 0/5] HDMI driver for Samsung S5PV310 platform
  2011-02-09  8:59     ` Hans Verkuil
@ 2011-02-09 17:55       ` Alex Deucher
  2011-02-09 18:45         ` Corbin Simpson
  0 siblings, 1 reply; 23+ messages in thread
From: Alex Deucher @ 2011-02-09 17:55 UTC (permalink / raw)
  To: Hans Verkuil
  Cc: Tomasz Stanislawski, linux-media, linux-samsung-soc,
	m.szyprowski, kyungmin.park, Maling list - DRI developers

On Wed, Feb 9, 2011 at 3:59 AM, Hans Verkuil <hansverk@cisco.com> wrote:
> On Tuesday, February 08, 2011 16:28:32 Alex Deucher wrote:
>> On Tue, Feb 8, 2011 at 4:47 AM, Hans Verkuil <hansverk@cisco.com> wrote:
>
> <snip>
>
>> >>   The driver supports an interrupt. It is used to detect plug/unplug
> events
>> > in
>> >> kernel debugs.  The API for detection of such an events in V4L2 API is to
> be
>> >> defined.
>> >
>> > Cisco (i.e. a few colleagues and myself) are working on this. We hope to
> post
>> > an RFC by the end of this month. We also have a proposal for CEC support
> in
>> > the pipeline.
>>
>> Any reason to not use the drm kms APIs for modesetting, display
>> configuration, and hotplug support?  We already have the
>> infrastructure in place for complex display configurations and
>> generating events for hotplug interrupts.  It would seem to make more
>> sense to me to fix any deficiencies in the KMS APIs than to spin a new
>> API.  Things like CEC would be a natural fit since a lot of desktop
>> GPUs support hdmi audio/3d/etc. and are already using kms.
>
> There are various reasons for not going down that road. The most important one
> is that mixing APIs is actually a bad idea. I've done that once in the past
> and I've regretted ever since. The problem with doing that is that it is
> pretty hard on applications who have to mix two different styles of API,
> somehow know where to find the documentation for each and know that both APIs
> can in fact be used on the same device.
>
> Now, if there was a lot of code that could be shared, then that might be
> enough reason to go that way, but in practice there is very little overlap.
> Take CEC: all the V4L API will do is to pass the CEC packets from kernel to
> userspace and vice versa. There is no parsing at all. This is typically used
> by embedded apps that want to do their own CEC processing.
>
> An exception might be a PCI(e) card with HDMI input/output that wants to
> handle CEC internally. At that point we might look at sharing CEC parsing
> code. A similar story is true for EDID handling.
>
> One area that might be nice to look at would be to share drivers for HDMI
> receivers and transmitters. However, the infrastructure for such drivers is
> wildly different between how it is used for GPUs versus V4L and has been for
> 10 years or so. I also suspect that most GPUs have there own HDMI internal
> implementation so code sharing will probably be quite limited.
>

You don't need to worry about the rest of the 3D and acceleration
stuff to use the kms modesetting API.  For video output, you have a
timing generator, an encoder that translates a bitstream into
voltages, and an connector that you plug into a monitor.  Additionally
you may want to read an edid or generate a hotplug event and use some
modeline handling helpers.  The kms api provides core modesetting code
and a set of modesetting driver callbacks for crtcs, encoders, and
connectors.  The hardware implementations will vary, but modesetting
is the same.  From drm_crtc_helper.h:

The driver provides the following callbacks for the crtc.  The crtc
loosely refers to the part of the display pipe that generates timing
and framebuffer scanout position.

struct drm_crtc_helper_funcs {
        /*
         * Control power levels on the CRTC.  If the mode passed in is
         * unsupported, the provider must use the next lowest power
level.
         */
        void (*dpms)(struct drm_crtc *crtc, int mode);
        void (*prepare)(struct drm_crtc *crtc);
        void (*commit)(struct drm_crtc *crtc);

        /* Provider can fixup or change mode timings before modeset occurs */
        bool (*mode_fixup)(struct drm_crtc *crtc,
                           struct drm_display_mode *mode,
                           struct drm_display_mode *adjusted_mode);
        /* Actually set the mode */
        int (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode,
                        struct drm_display_mode *adjusted_mode, int x, int y,
                        struct drm_framebuffer *old_fb);

        /* Move the crtc on the current fb to the given position *optional* */
        int (*mode_set_base)(struct drm_crtc *crtc, int x, int y,
                             struct drm_framebuffer *old_fb);
        int (*mode_set_base_atomic)(struct drm_crtc *crtc,
                                    struct drm_framebuffer *fb, int x, int y,
                                    enum mode_set_atomic);

        /* reload the current crtc LUT */
        void (*load_lut)(struct drm_crtc *crtc);

        /* disable crtc when not in use - more explicit than dpms off */
        void (*disable)(struct drm_crtc *crtc);
};

encoders take the bitstream from the crtc and convert it into a set of
voltages understood by the monitor, e.g., TMDS or LVDS encoders.  The
callbacks follow a similar pattern to crtcs.

struct drm_encoder_helper_funcs {
        void (*dpms)(struct drm_encoder *encoder, int mode);
        void (*save)(struct drm_encoder *encoder);
        void (*restore)(struct drm_encoder *encoder);

	bool (*mode_fixup)(struct drm_encoder *encoder,
                           struct drm_display_mode *mode,
                           struct drm_display_mode *adjusted_mode);
        void (*prepare)(struct drm_encoder *encoder);
        void (*commit)(struct drm_encoder *encoder);
	void (*mode_set)(struct drm_encoder *encoder,
                         struct drm_display_mode *mode,
                         struct drm_display_mode *adjusted_mode);
        struct drm_crtc *(*get_crtc)(struct drm_encoder *encoder);
 	/* detect for DAC style encoders */
        enum drm_connector_status (*detect)(struct drm_encoder *encoder,
                                            struct drm_connector *connector);
        /* disable encoder when not in use - more explicit than dpms off */
        void (*disable)(struct drm_encoder *encoder);
};


And finally connectors.  These are the actual physical connectors on
the board (DVI-I, HDMI-A, VGA, S-video, etc.).  Things like ddc lines
are generally tied to a connector so functions relevant to getting
modelines are associated with connectors.

struct drm_connector_helper_funcs {
        int (*get_modes)(struct drm_connector *connector);
        int (*mode_valid)(struct drm_connector *connector,
                          struct drm_display_mode *mode);
        struct drm_encoder *(*best_encoder)(struct drm_connector *connector);
};

See drm_crtc_helper.c to see how the callbacks are used.  The code can
handle crtcs that can be routed to different encoders dynamically or
crtcs that are hardcoded to specific encoders.  Additionally, it can
handle encoders that are shared between multiple connectors (e.g., a
DAC shared between VGA and S-video), or multiple encoders tied to a
single connector (e.g., DAC and TMDS encoders tied to a single DVI-I
connector).

Let's look at two scenarios where you want a system to display an
interactive RGB desktop and provide video capture and video output.
You'd need to use different sets of APIs depending on what hardware
you use:

1. SoC with an LVDS panel and HDMI output and a capture unit
2. PC with a GPU with an LVDS panel and an HDMI output and a capture unit.

As I understand it, to use the scenario 1 would use the following:

- LVDS uses some new v4l interface or a hacked up kernel fb interface
to support multiple displays
- HDMI uses some new v4l interface or a hacked up kernel fb interface
to support multiple displays
- capture unit uses V4L

Scenario 2 would use:

- LVDS uses KMS API
- HDMI uses KMS API
- capture unit uses V4L

Why not use KMS?  A modesetting API is a huge amount of work.  I
haven't seen anything in these SoC platforms that makes them so
radically different that they need their own API.  If there are any,
we'd love to hear about them so they can be addressed.

Alex

> So, no, there are no plans to share anything between the two (except perhaps
> EDID and CEC parsing should that become relevant).
>
> Oh, and let me join Andy in saying that the drm/kms/whatever API documentation
> *really* needs a lot of work.
>
> Regards,
>
>        Hans
>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH/RFC 0/5] HDMI driver for Samsung S5PV310 platform
  2011-02-09 17:55       ` Alex Deucher
@ 2011-02-09 18:45         ` Corbin Simpson
  0 siblings, 0 replies; 23+ messages in thread
From: Corbin Simpson @ 2011-02-09 18:45 UTC (permalink / raw)
  To: Alex Deucher
  Cc: Hans Verkuil, Tomasz Stanislawski, linux-samsung-soc,
	Maling list - DRI developers, kyungmin.park, linux-media,
	m.szyprowski

On Wed, Feb 9, 2011 at 9:55 AM, Alex Deucher <alexdeucher@gmail.com> wrote:
> On Wed, Feb 9, 2011 at 3:59 AM, Hans Verkuil <hansverk@cisco.com> wrote:
>> On Tuesday, February 08, 2011 16:28:32 Alex Deucher wrote:
>>> On Tue, Feb 8, 2011 at 4:47 AM, Hans Verkuil <hansverk@cisco.com> wrote:
>>
>> <snip>
>>
>>> >>   The driver supports an interrupt. It is used to detect plug/unplug
>> events
>>> > in
>>> >> kernel debugs.  The API for detection of such an events in V4L2 API is to
>> be
>>> >> defined.
>>> >
>>> > Cisco (i.e. a few colleagues and myself) are working on this. We hope to
>> post
>>> > an RFC by the end of this month. We also have a proposal for CEC support
>> in
>>> > the pipeline.
>>>
>>> Any reason to not use the drm kms APIs for modesetting, display
>>> configuration, and hotplug support?  We already have the
>>> infrastructure in place for complex display configurations and
>>> generating events for hotplug interrupts.  It would seem to make more
>>> sense to me to fix any deficiencies in the KMS APIs than to spin a new
>>> API.  Things like CEC would be a natural fit since a lot of desktop
>>> GPUs support hdmi audio/3d/etc. and are already using kms.
>>
>> There are various reasons for not going down that road. The most important one
>> is that mixing APIs is actually a bad idea. I've done that once in the past
>> and I've regretted ever since. The problem with doing that is that it is
>> pretty hard on applications who have to mix two different styles of API,
>> somehow know where to find the documentation for each and know that both APIs
>> can in fact be used on the same device.
>>
>> Now, if there was a lot of code that could be shared, then that might be
>> enough reason to go that way, but in practice there is very little overlap.
>> Take CEC: all the V4L API will do is to pass the CEC packets from kernel to
>> userspace and vice versa. There is no parsing at all. This is typically used
>> by embedded apps that want to do their own CEC processing.
>>
>> An exception might be a PCI(e) card with HDMI input/output that wants to
>> handle CEC internally. At that point we might look at sharing CEC parsing
>> code. A similar story is true for EDID handling.
>>
>> One area that might be nice to look at would be to share drivers for HDMI
>> receivers and transmitters. However, the infrastructure for such drivers is
>> wildly different between how it is used for GPUs versus V4L and has been for
>> 10 years or so. I also suspect that most GPUs have there own HDMI internal
>> implementation so code sharing will probably be quite limited.
>>
>
> You don't need to worry about the rest of the 3D and acceleration
> stuff to use the kms modesetting API.  For video output, you have a
> timing generator, an encoder that translates a bitstream into
> voltages, and an connector that you plug into a monitor.  Additionally
> you may want to read an edid or generate a hotplug event and use some
> modeline handling helpers.  The kms api provides core modesetting code
> and a set of modesetting driver callbacks for crtcs, encoders, and
> connectors.  The hardware implementations will vary, but modesetting
> is the same.  From drm_crtc_helper.h:
>
> The driver provides the following callbacks for the crtc.  The crtc
> loosely refers to the part of the display pipe that generates timing
> and framebuffer scanout position.
>
> struct drm_crtc_helper_funcs {
>        /*
>         * Control power levels on the CRTC.  If the mode passed in is
>         * unsupported, the provider must use the next lowest power
> level.
>         */
>        void (*dpms)(struct drm_crtc *crtc, int mode);
>        void (*prepare)(struct drm_crtc *crtc);
>        void (*commit)(struct drm_crtc *crtc);
>
>        /* Provider can fixup or change mode timings before modeset occurs */
>        bool (*mode_fixup)(struct drm_crtc *crtc,
>                           struct drm_display_mode *mode,
>                           struct drm_display_mode *adjusted_mode);
>        /* Actually set the mode */
>        int (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode,
>                        struct drm_display_mode *adjusted_mode, int x, int y,
>                        struct drm_framebuffer *old_fb);
>
>        /* Move the crtc on the current fb to the given position *optional* */
>        int (*mode_set_base)(struct drm_crtc *crtc, int x, int y,
>                             struct drm_framebuffer *old_fb);
>        int (*mode_set_base_atomic)(struct drm_crtc *crtc,
>                                    struct drm_framebuffer *fb, int x, int y,
>                                    enum mode_set_atomic);
>
>        /* reload the current crtc LUT */
>        void (*load_lut)(struct drm_crtc *crtc);
>
>        /* disable crtc when not in use - more explicit than dpms off */
>        void (*disable)(struct drm_crtc *crtc);
> };
>
> encoders take the bitstream from the crtc and convert it into a set of
> voltages understood by the monitor, e.g., TMDS or LVDS encoders.  The
> callbacks follow a similar pattern to crtcs.
>
> struct drm_encoder_helper_funcs {
>        void (*dpms)(struct drm_encoder *encoder, int mode);
>        void (*save)(struct drm_encoder *encoder);
>        void (*restore)(struct drm_encoder *encoder);
>
>        bool (*mode_fixup)(struct drm_encoder *encoder,
>                           struct drm_display_mode *mode,
>                           struct drm_display_mode *adjusted_mode);
>        void (*prepare)(struct drm_encoder *encoder);
>        void (*commit)(struct drm_encoder *encoder);
>        void (*mode_set)(struct drm_encoder *encoder,
>                         struct drm_display_mode *mode,
>                         struct drm_display_mode *adjusted_mode);
>        struct drm_crtc *(*get_crtc)(struct drm_encoder *encoder);
>        /* detect for DAC style encoders */
>        enum drm_connector_status (*detect)(struct drm_encoder *encoder,
>                                            struct drm_connector *connector);
>        /* disable encoder when not in use - more explicit than dpms off */
>        void (*disable)(struct drm_encoder *encoder);
> };
>
>
> And finally connectors.  These are the actual physical connectors on
> the board (DVI-I, HDMI-A, VGA, S-video, etc.).  Things like ddc lines
> are generally tied to a connector so functions relevant to getting
> modelines are associated with connectors.
>
> struct drm_connector_helper_funcs {
>        int (*get_modes)(struct drm_connector *connector);
>        int (*mode_valid)(struct drm_connector *connector,
>                          struct drm_display_mode *mode);
>        struct drm_encoder *(*best_encoder)(struct drm_connector *connector);
> };
>
> See drm_crtc_helper.c to see how the callbacks are used.  The code can
> handle crtcs that can be routed to different encoders dynamically or
> crtcs that are hardcoded to specific encoders.  Additionally, it can
> handle encoders that are shared between multiple connectors (e.g., a
> DAC shared between VGA and S-video), or multiple encoders tied to a
> single connector (e.g., DAC and TMDS encoders tied to a single DVI-I
> connector).
>
> Let's look at two scenarios where you want a system to display an
> interactive RGB desktop and provide video capture and video output.
> You'd need to use different sets of APIs depending on what hardware
> you use:
>
> 1. SoC with an LVDS panel and HDMI output and a capture unit
> 2. PC with a GPU with an LVDS panel and an HDMI output and a capture unit.
>
> As I understand it, to use the scenario 1 would use the following:
>
> - LVDS uses some new v4l interface or a hacked up kernel fb interface
> to support multiple displays
> - HDMI uses some new v4l interface or a hacked up kernel fb interface
> to support multiple displays
> - capture unit uses V4L
>
> Scenario 2 would use:
>
> - LVDS uses KMS API
> - HDMI uses KMS API
> - capture unit uses V4L
>
> Why not use KMS?  A modesetting API is a huge amount of work.  I
> haven't seen anything in these SoC platforms that makes them so
> radically different that they need their own API.  If there are any,
> we'd love to hear about them so they can be addressed.
>
> Alex
>
>> So, no, there are no plans to share anything between the two (except perhaps
>> EDID and CEC parsing should that become relevant).
>>
>> Oh, and let me join Andy in saying that the drm/kms/whatever API documentation
>> *really* needs a lot of work.

I know this is sort of a "me too" as none of my code's upstream yet,
but the barrier posed by the lack of documentation for KMS is
*massive* since the only KMS drivers are for highly complex pieces of
hardware, making them difficult to read. The entire KMS API can be
implemented in a single C file for simple hardware, just like the FB
API, but you'd never know it by looking at the existing drivers.

~ C.

-- 
When the facts change, I change my mind. What do you do, sir? ~ Keynes

Corbin Simpson
<MostAwesomeDude@gmail.com>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH/RFC 0/5] HDMI driver for Samsung S5PV310 platform
  2011-02-09  7:12       ` Alex Deucher
@ 2011-02-09 19:00         ` Matt Turner
  2011-02-09 19:43           ` Hans Verkuil
  2011-02-10  0:51         ` Andy Walls
  1 sibling, 1 reply; 23+ messages in thread
From: Matt Turner @ 2011-02-09 19:00 UTC (permalink / raw)
  To: Hans Verkuil
  Cc: Andy Walls, Tomasz Stanislawski, linux-samsung-soc,
	Maling list - DRI developers, Alex Deucher, kyungmin.park,
	linux-media, m.szyprowski

On Wed, Feb 9, 2011 at 7:12 AM, Alex Deucher <alexdeucher@gmail.com> wrote:
> On Tue, Feb 8, 2011 at 5:47 PM, Andy Walls <awalls@md.metrocast.net> wrote:
>> On Tue, 2011-02-08 at 10:28 -0500, Alex Deucher wrote:
>>> On Tue, Feb 8, 2011 at 4:47 AM, Hans Verkuil <hansverk@cisco.com> wrote:
>>> > Just two quick notes. I'll try to do a full review this weekend.
>>> >
>>> > On Tuesday, February 08, 2011 10:30:22 Tomasz Stanislawski wrote:
>>> >> ==============
>>> >>  Introduction
>>> >> ==============
>>> >>
>>> >> The purpose of this RFC is to discuss the driver for a TV output interface
>>> >> available in upcoming Samsung SoC. The HW is able to generate digital and
>>> >> analog signals. Current version of the driver supports only digital output.
>>> >>
>>> >> Internally the driver uses videobuf2 framework, and CMA memory allocator.
>>> > Not
>>> >> all of them are merged by now, but I decided to post the sources to start
>>> >> discussion driver's design.
>>
>>> >
>>> > Cisco (i.e. a few colleagues and myself) are working on this. We hope to post
>>> > an RFC by the end of this month. We also have a proposal for CEC support in
>>> > the pipeline.
>>>
>>> Any reason to not use the drm kms APIs for modesetting, display
>>> configuration, and hotplug support?  We already have the
>>> infrastructure in place for complex display configurations and
>>> generating events for hotplug interrupts.  It would seem to make more
>>> sense to me to fix any deficiencies in the KMS APIs than to spin a new
>>> API.  Things like CEC would be a natural fit since a lot of desktop
>>> GPUs support hdmi audio/3d/etc. and are already using kms.
>>>
>>> Alex
>>
>> I'll toss one out: lack of API documentation for driver or application
>> developers to use.
>>
>>
>> When I last looked at converting ivtvfb to use DRM, KMS, TTM, etc. (to
>> possibly get rid of reliance on the ivtv X video driver
>> http://dl.ivtvdriver.org/xf86-video-ivtv/ ), I found the documentation
>> was really sparse.
>>
>> DRM had the most documentation under Documentation/DocBook/drm.tmpl, but
>> the userland API wasn't fleshed out.  GEM was talked about a bit in
>> there as well, IIRC.
>>
>> TTM documentation was essentially non-existant.
>>
>> I can't find any KMS documentation either.
>>
>> I recall having to read much of the drm code, and having to look at the
>> radeon driver, just to tease out what the DRM ioctls needed to do.
>>
>> Am I missing a Documentation source for the APIs?

Yes,

My summer of code project's purpose was to create something of a
tutorial for writing a KMS driver. The code, split out into something
like 15 step-by-step patches, and accompanying documentation are
available from Google's website.

http://code.google.com/p/google-summer-of-code-2010-xorg/downloads/detail?name=Matt_Turner.tar.gz

My repository (doesn't include the documentation) is available here:
http://git.kernel.org/?p=linux/kernel/git/mattst88/glint.git;a=summary

There's a 'rebased' branch that contains API changes required for the
code to work with 2.6.37~.

I hope it's useful to you.

I can't image how the lack of documentation of an used and tested API
could be a serious reason to write you own. That makes absolutely no
sense to me, so I hope you'll decide to use KMS.

Matt

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH/RFC 0/5] HDMI driver for Samsung S5PV310 platform
  2011-02-09 19:00         ` Matt Turner
@ 2011-02-09 19:43           ` Hans Verkuil
  2011-02-09 23:59             ` Alex Deucher
  0 siblings, 1 reply; 23+ messages in thread
From: Hans Verkuil @ 2011-02-09 19:43 UTC (permalink / raw)
  To: Matt Turner
  Cc: Hans Verkuil, Andy Walls, Tomasz Stanislawski, linux-samsung-soc,
	Maling list - DRI developers, Alex Deucher, kyungmin.park,
	linux-media, m.szyprowski

On Wednesday, February 09, 2011 20:00:38 Matt Turner wrote:
> On Wed, Feb 9, 2011 at 7:12 AM, Alex Deucher <alexdeucher@gmail.com> wrote:
> > On Tue, Feb 8, 2011 at 5:47 PM, Andy Walls <awalls@md.metrocast.net> wrote:
> >> On Tue, 2011-02-08 at 10:28 -0500, Alex Deucher wrote:
> >>> On Tue, Feb 8, 2011 at 4:47 AM, Hans Verkuil <hansverk@cisco.com> wrote:
> >>> > Just two quick notes. I'll try to do a full review this weekend.
> >>> >
> >>> > On Tuesday, February 08, 2011 10:30:22 Tomasz Stanislawski wrote:
> >>> >> ==============
> >>> >>  Introduction
> >>> >> ==============
> >>> >>
> >>> >> The purpose of this RFC is to discuss the driver for a TV output interface
> >>> >> available in upcoming Samsung SoC. The HW is able to generate digital and
> >>> >> analog signals. Current version of the driver supports only digital output.
> >>> >>
> >>> >> Internally the driver uses videobuf2 framework, and CMA memory allocator.
> >>> > Not
> >>> >> all of them are merged by now, but I decided to post the sources to start
> >>> >> discussion driver's design.
> >>
> >>> >
> >>> > Cisco (i.e. a few colleagues and myself) are working on this. We hope to post
> >>> > an RFC by the end of this month. We also have a proposal for CEC support in
> >>> > the pipeline.
> >>>
> >>> Any reason to not use the drm kms APIs for modesetting, display
> >>> configuration, and hotplug support?  We already have the
> >>> infrastructure in place for complex display configurations and
> >>> generating events for hotplug interrupts.  It would seem to make more
> >>> sense to me to fix any deficiencies in the KMS APIs than to spin a new
> >>> API.  Things like CEC would be a natural fit since a lot of desktop
> >>> GPUs support hdmi audio/3d/etc. and are already using kms.
> >>>
> >>> Alex
> >>
> >> I'll toss one out: lack of API documentation for driver or application
> >> developers to use.
> >>
> >>
> >> When I last looked at converting ivtvfb to use DRM, KMS, TTM, etc. (to
> >> possibly get rid of reliance on the ivtv X video driver
> >> http://dl.ivtvdriver.org/xf86-video-ivtv/ ), I found the documentation
> >> was really sparse.
> >>
> >> DRM had the most documentation under Documentation/DocBook/drm.tmpl, but
> >> the userland API wasn't fleshed out.  GEM was talked about a bit in
> >> there as well, IIRC.
> >>
> >> TTM documentation was essentially non-existant.
> >>
> >> I can't find any KMS documentation either.
> >>
> >> I recall having to read much of the drm code, and having to look at the
> >> radeon driver, just to tease out what the DRM ioctls needed to do.
> >>
> >> Am I missing a Documentation source for the APIs?
> 
> Yes,
> 
> My summer of code project's purpose was to create something of a
> tutorial for writing a KMS driver. The code, split out into something
> like 15 step-by-step patches, and accompanying documentation are
> available from Google's website.
> 
> http://code.google.com/p/google-summer-of-code-2010-xorg/downloads/detail?name=Matt_Turner.tar.gz

Nice!

What I still don't understand is if and how this is controlled via userspace.

Is there some documentation of the userspace API somewhere?

> My repository (doesn't include the documentation) is available here:
> http://git.kernel.org/?p=linux/kernel/git/mattst88/glint.git;a=summary
> 
> There's a 'rebased' branch that contains API changes required for the
> code to work with 2.6.37~.
> 
> I hope it's useful to you.
> 
> I can't image how the lack of documentation of an used and tested API
> could be a serious reason to write you own.

That never was the main reason. It doesn't help, though.

> That makes absolutely no
> sense to me, so I hope you'll decide to use KMS.

No, we won't. A GPU driver != a V4L driver. The primary purpose of a V4L2
display driver is to output discrete frames from memory to some device. This
may be a HDMI transmitter, a SDTV transmitter, a memory-to-memory codec, an
FPGA, whatever. In other words, there is not necessarily a monitor on the other
end. We have for some time now V4L2 APIs to set up video formats. The original
ioctl was VIDIOC_G/S_STD to select PAL/NTSC/SECAM. The new ones are
VIDIOC_G/S_DV_PRESETS which set up standard formats (1080p60, 720p60, etc) and
DV_TIMINGS which can be used for custom bt.656/1120 digital video timings.

Trying to mix KMS into the V4L2 API is just a recipe for disaster. Just think
about what it would mean for DRM if DRM would use the V4L2 API for setting
video modes. That would be a disaster as well.

Regards,

	Hans

-- 
Hans Verkuil - video4linux developer - sponsored by Cisco

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH/RFC 0/5] HDMI driver for Samsung S5PV310 platform
  2011-02-09 19:43           ` Hans Verkuil
@ 2011-02-09 23:59             ` Alex Deucher
  0 siblings, 0 replies; 23+ messages in thread
From: Alex Deucher @ 2011-02-09 23:59 UTC (permalink / raw)
  To: Hans Verkuil
  Cc: Matt Turner, Hans Verkuil, Andy Walls, Tomasz Stanislawski,
	linux-samsung-soc, Maling list - DRI developers, kyungmin.park,
	linux-media, m.szyprowski

On Wed, Feb 9, 2011 at 2:43 PM, Hans Verkuil <hverkuil@xs4all.nl> wrote:
> On Wednesday, February 09, 2011 20:00:38 Matt Turner wrote:
>> On Wed, Feb 9, 2011 at 7:12 AM, Alex Deucher <alexdeucher@gmail.com> wrote:
>> > On Tue, Feb 8, 2011 at 5:47 PM, Andy Walls <awalls@md.metrocast.net> wrote:
>> >> On Tue, 2011-02-08 at 10:28 -0500, Alex Deucher wrote:
>> >>> On Tue, Feb 8, 2011 at 4:47 AM, Hans Verkuil <hansverk@cisco.com> wrote:
>> >>> > Just two quick notes. I'll try to do a full review this weekend.
>> >>> >
>> >>> > On Tuesday, February 08, 2011 10:30:22 Tomasz Stanislawski wrote:
>> >>> >> ==============
>> >>> >>  Introduction
>> >>> >> ==============
>> >>> >>
>> >>> >> The purpose of this RFC is to discuss the driver for a TV output interface
>> >>> >> available in upcoming Samsung SoC. The HW is able to generate digital and
>> >>> >> analog signals. Current version of the driver supports only digital output.
>> >>> >>
>> >>> >> Internally the driver uses videobuf2 framework, and CMA memory allocator.
>> >>> > Not
>> >>> >> all of them are merged by now, but I decided to post the sources to start
>> >>> >> discussion driver's design.
>> >>
>> >>> >
>> >>> > Cisco (i.e. a few colleagues and myself) are working on this. We hope to post
>> >>> > an RFC by the end of this month. We also have a proposal for CEC support in
>> >>> > the pipeline.
>> >>>
>> >>> Any reason to not use the drm kms APIs for modesetting, display
>> >>> configuration, and hotplug support?  We already have the
>> >>> infrastructure in place for complex display configurations and
>> >>> generating events for hotplug interrupts.  It would seem to make more
>> >>> sense to me to fix any deficiencies in the KMS APIs than to spin a new
>> >>> API.  Things like CEC would be a natural fit since a lot of desktop
>> >>> GPUs support hdmi audio/3d/etc. and are already using kms.
>> >>>
>> >>> Alex
>> >>
>> >> I'll toss one out: lack of API documentation for driver or application
>> >> developers to use.
>> >>
>> >>
>> >> When I last looked at converting ivtvfb to use DRM, KMS, TTM, etc. (to
>> >> possibly get rid of reliance on the ivtv X video driver
>> >> http://dl.ivtvdriver.org/xf86-video-ivtv/ ), I found the documentation
>> >> was really sparse.
>> >>
>> >> DRM had the most documentation under Documentation/DocBook/drm.tmpl, but
>> >> the userland API wasn't fleshed out.  GEM was talked about a bit in
>> >> there as well, IIRC.
>> >>
>> >> TTM documentation was essentially non-existant.
>> >>
>> >> I can't find any KMS documentation either.
>> >>
>> >> I recall having to read much of the drm code, and having to look at the
>> >> radeon driver, just to tease out what the DRM ioctls needed to do.
>> >>
>> >> Am I missing a Documentation source for the APIs?
>>
>> Yes,
>>
>> My summer of code project's purpose was to create something of a
>> tutorial for writing a KMS driver. The code, split out into something
>> like 15 step-by-step patches, and accompanying documentation are
>> available from Google's website.
>>
>> http://code.google.com/p/google-summer-of-code-2010-xorg/downloads/detail?name=Matt_Turner.tar.gz
>
> Nice!
>
> What I still don't understand is if and how this is controlled via userspace.
>
> Is there some documentation of the userspace API somewhere?

At the moment, it's only used by Xorg ddxes and the plymouth
bootsplash.  For details see:
http://cgit.freedesktop.org/plymouth/tree/src/plugins/renderers/drm
http://cgit.freedesktop.org/xorg/driver/xf86-video-ati/tree/src/drmmode_display.c

>
>> My repository (doesn't include the documentation) is available here:
>> http://git.kernel.org/?p=linux/kernel/git/mattst88/glint.git;a=summary
>>
>> There's a 'rebased' branch that contains API changes required for the
>> code to work with 2.6.37~.
>>
>> I hope it's useful to you.
>>
>> I can't image how the lack of documentation of an used and tested API
>> could be a serious reason to write you own.
>
> That never was the main reason. It doesn't help, though.
>
>> That makes absolutely no
>> sense to me, so I hope you'll decide to use KMS.
>
> No, we won't. A GPU driver != a V4L driver. The primary purpose of a V4L2
> display driver is to output discrete frames from memory to some device. This
> may be a HDMI transmitter, a SDTV transmitter, a memory-to-memory codec, an
> FPGA, whatever. In other words, there is not necessarily a monitor on the other
> end. We have for some time now V4L2 APIs to set up video formats. The original
> ioctl was VIDIOC_G/S_STD to select PAL/NTSC/SECAM. The new ones are
> VIDIOC_G/S_DV_PRESETS which set up standard formats (1080p60, 720p60, etc) and
> DV_TIMINGS which can be used for custom bt.656/1120 digital video timings.
>
> Trying to mix KMS into the V4L2 API is just a recipe for disaster. Just think
> about what it would mean for DRM if DRM would use the V4L2 API for setting
> video modes. That would be a disaster as well.

I still think there's room for cooperation here.  There are GPUs out
there that have a capture interface and a full gamut of display output
options in addition to a 3D engine.  Besides conventional desktop
stuff, you could use this sort of setup to capture frames, run them
through shader-based filters/transforms and render then to memory to
be scanned out by display hardware, or dma'ed to another device like
an fpga or codec like you mentioned.  On the other side, the same SoCs
that such that are used for v4l could also be used as a desktop
framebuffer.

FWIW, you may find the drm EDID and mode handling bits useful.  See
drm_modes.c and drm_edid.c.

Alex

>
> Regards,
>
>        Hans
>
> --
> Hans Verkuil - video4linux developer - sponsored by Cisco
>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH/RFC 0/5] HDMI driver for Samsung S5PV310 platform
  2011-02-09  7:12       ` Alex Deucher
  2011-02-09 19:00         ` Matt Turner
@ 2011-02-10  0:51         ` Andy Walls
  2011-02-12 18:38           ` Alex Deucher
  1 sibling, 1 reply; 23+ messages in thread
From: Andy Walls @ 2011-02-10  0:51 UTC (permalink / raw)
  To: Alex Deucher
  Cc: Hans Verkuil, Tomasz Stanislawski, linux-media,
	linux-samsung-soc, m.szyprowski, kyungmin.park,
	Maling list - DRI developers

On Wed, 2011-02-09 at 02:12 -0500, Alex Deucher wrote:
> On Tue, Feb 8, 2011 at 5:47 PM, Andy Walls <awalls@md.metrocast.net> wrote:
> > On Tue, 2011-02-08 at 10:28 -0500, Alex Deucher wrote:
> >> On Tue, Feb 8, 2011 at 4:47 AM, Hans Verkuil <hansverk@cisco.com> wrote:
> >> > Just two quick notes. I'll try to do a full review this weekend.
> >> >
> >> > On Tuesday, February 08, 2011 10:30:22 Tomasz Stanislawski wrote:
> >> >> ==============
> >> >>  Introduction
> >> >> ==============
> >> >>
> >> >> The purpose of this RFC is to discuss the driver for a TV output interface
> >> >> available in upcoming Samsung SoC. The HW is able to generate digital and
> >> >> analog signals. Current version of the driver supports only digital output.
> >> >>
> >> >> Internally the driver uses videobuf2 framework, and CMA memory allocator.
> >> > Not
> >> >> all of them are merged by now, but I decided to post the sources to start
> >> >> discussion driver's design.
> >
> >> >
> >> > Cisco (i.e. a few colleagues and myself) are working on this. We hope to post
> >> > an RFC by the end of this month. We also have a proposal for CEC support in
> >> > the pipeline.
> >>
> >> Any reason to not use the drm kms APIs for modesetting, display
> >> configuration, and hotplug support?  We already have the
> >> infrastructure in place for complex display configurations and
> >> generating events for hotplug interrupts.  It would seem to make more
> >> sense to me to fix any deficiencies in the KMS APIs than to spin a new
> >> API.  Things like CEC would be a natural fit since a lot of desktop
> >> GPUs support hdmi audio/3d/etc. and are already using kms.
> >>
> >> Alex
> >
> > I'll toss one out: lack of API documentation for driver or application
> > developers to use.
> >
> >
> > When I last looked at converting ivtvfb to use DRM, KMS, TTM, etc. (to
> > possibly get rid of reliance on the ivtv X video driver
> > http://dl.ivtvdriver.org/xf86-video-ivtv/ ), I found the documentation
> > was really sparse.
> >
> > DRM had the most documentation under Documentation/DocBook/drm.tmpl, but
> > the userland API wasn't fleshed out.  GEM was talked about a bit in
> > there as well, IIRC.
> >
> > TTM documentation was essentially non-existant.
> >
> > I can't find any KMS documentation either.
> >
> > I recall having to read much of the drm code, and having to look at the
> > radeon driver, just to tease out what the DRM ioctls needed to do.
> >
> > Am I missing a Documentation source for the APIs?
> >
> 
> Documentation is somewhat sparse compared to some other APIs.  Mostly
> inline kerneldoc comments in the core functions.  It would be nice to
> improve things.   The modesetting API is very similar to the xrandr
> API in the xserver.
> 
> At the moment a device specific surface manager (Xorg ddx, or some
> other userspace lib) is required to use kms due to device specific
> requirements with respect to memory management and alignment for
> acceleration.  The kms modesetting ioctls are common across all kms
> drm drivers, but the memory management ioctls are device specific.
> GEM itself is an Intel-specific memory manager, although radeon uses
> similar ioctls.  TTM is used internally by radeon, nouveau, and svga
> for managing memory gpu accessible memory pools.  Drivers are free to
> use whatever memory manager they want; an existing one shared with a
> v4l or platform driver, TTM, or something new.
>   There is no generic
> userspace kms driver/lib although Dave and others have done some work
> to support that, but it's really hard to make a generic interface
> flexible enough to handle all the strange acceleration requirements of
> GPUs.

All of the above unfortunately says to me that the KMS API has a fairly
tightly coupled set of userspace components, because userspace
applications need have details about the specific underlying hardware
embeeded in the application to effectively use the API.

If so, that's not really conducive to getting application developers to
write applications to the API, since applications will get tied to
specific sets of hardware.

Lack of documentation on the API for userpace application writers to use
exacerbates that issue, as there are no clearly stated guarantees on

	device node conventions
	ioctl's
		arguments and bounds on the arguments
		expected error return values
		behavior on error return and meaning of error return
		which are mandatory, which are optional
		how to perform "atomic" transactions
	Behavior of other fops:
		Are multiple opens allowed or not?
		Is llseek() meaningful?
		Is poll() meaningful?
		Does final close() deallocate all memory objects?
	sysfs nodes
		location
		expected names
		data formats
	how compliant or not any one driver is with the KMS APIcontrol
	where drivers are permitted to behave differently and where they are not
	What include files do user space applications need to include


What device nodes should be opened?
$ ls -al /dev/dri/*
crw-rw----+ 1 root video 226,  0 2011-02-09 17:27 /dev/dri/card0
crw-rw-rw-. 1 root video 226, 64 2011-02-09 17:26 /dev/dri/controlD64

What's the difference between them?
What's the renderDnn node that can show up?

Which of the below are mandatory for a KMS driver to support?
Which are optional?
Which were bad ideas and are deprecated?

#define DRM_IOCTL_MODE_GETRESOURCES     DRM_IOWR(0xA0, struct drm_mode_card_res)
#define DRM_IOCTL_MODE_GETCRTC          DRM_IOWR(0xA1, struct drm_mode_crtc)
#define DRM_IOCTL_MODE_SETCRTC          DRM_IOWR(0xA2, struct drm_mode_crtc)
#define DRM_IOCTL_MODE_CURSOR           DRM_IOWR(0xA3, struct drm_mode_cursor)
#define DRM_IOCTL_MODE_GETGAMMA         DRM_IOWR(0xA4, struct drm_mode_crtc_lut)
#define DRM_IOCTL_MODE_SETGAMMA         DRM_IOWR(0xA5, struct drm_mode_crtc_lut)
#define DRM_IOCTL_MODE_GETENCODER       DRM_IOWR(0xA6, struct drm_mode_get_encoder)
#define DRM_IOCTL_MODE_GETCONNECTOR     DRM_IOWR(0xA7, struct drm_mode_get_connector)
#define DRM_IOCTL_MODE_ATTACHMODE       DRM_IOWR(0xA8, struct drm_mode_mode_cmd)
#define DRM_IOCTL_MODE_DETACHMODE       DRM_IOWR(0xA9, struct drm_mode_mode_cmd)

#define DRM_IOCTL_MODE_GETPROPERTY      DRM_IOWR(0xAA, struct drm_mode_get_property)

	How does one iterate through multiple properties or all they all returned at once?
	The amount of data returned by drm_mode_get_property seems unbounded
		as the caller provides some pointers cast to __u64.
	How is the caller supposed to know how much space to reserve?
	Is the method consistent across all drivers?
	What is a property?  Any random (name-tag, value) pair the driver wants to provide?
	Are there any required properties consistent across all drivers?

#define DRM_IOCTL_MODE_SETPROPERTY      DRM_IOWR(0xAB, struct drm_mode_connector_set_property)
#define DRM_IOCTL_MODE_GETPROPBLOB      DRM_IOWR(0xAC, struct drm_mode_get_blob)
#define DRM_IOCTL_MODE_GETFB            DRM_IOWR(0xAD, struct drm_mode_fb_cmd)
#define DRM_IOCTL_MODE_ADDFB            DRM_IOWR(0xAE, struct drm_mode_fb_cmd)
#define DRM_IOCTL_MODE_RMFB             DRM_IOWR(0xAF, unsigned int)
#define DRM_IOCTL_MODE_PAGE_FLIP        DRM_IOWR(0xB0, struct drm_mode_crtc_page_flip)
#define DRM_IOCTL_MODE_DIRTYFB          DRM_IOWR(0xB1, struct drm_mode_fb_dirty_cmd)


If we ask application developers to "read the kernel source and figure
it out", who is really going to write any userland code to that API?  X
and Wayland developers.

What userspace application developer is going to crosswalk all the
drivers and figure out what is universally supported by all the kernel
drivers, versus what is intel, radeon, or nouveau driver specific?

What are the userspace applications currently using KMS: the Xserver,
Plymouth, and Wayland?  Any others on the horizon?



>   kms does however provide a legacy kernel fb interface.

That's another reason I had initally looked into it for replacing the
ivtv X-driver.  I figured moving ivtvfb over to the DRM/KMS FB
implementation interface could be a first easy step.


> While the documentation is not great, the modesetting API is solid and
> it would be nice to get more people involved and working on it (or at
> least looking at it)

Does solid mean it is not going to change?


>  rather than starting something equivalent from
> scratch or implementing a device specific modesetting API.

It is too difficult for me to say if it would be equivalent.

The one issue that often springs to mind is the security policy.  Video
capture and presentation devices may require different user permissions
than the Desktop, and console VTs.

If using a common API means both Console and Video devices now have to
have the same security policy; requires someone to get new, elevated
privileges; or now means joe-user can DoS the graphics memory system,
then it is not worth it just for that.

>   If you
> have any questions about it, please ask on dri-devel (CCed).

I've posed some of them both rhetorical and genuine.

Regards,
Andy


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH/RFC 0/5] HDMI driver for Samsung S5PV310 platform
  2011-02-10  0:51         ` Andy Walls
@ 2011-02-12 18:38           ` Alex Deucher
  0 siblings, 0 replies; 23+ messages in thread
From: Alex Deucher @ 2011-02-12 18:38 UTC (permalink / raw)
  To: Andy Walls
  Cc: Hans Verkuil, Tomasz Stanislawski, linux-media,
	linux-samsung-soc, m.szyprowski, kyungmin.park,
	Maling list - DRI developers

On Wed, Feb 9, 2011 at 7:51 PM, Andy Walls <awalls@md.metrocast.net> wrote:
> On Wed, 2011-02-09 at 02:12 -0500, Alex Deucher wrote:
>> On Tue, Feb 8, 2011 at 5:47 PM, Andy Walls <awalls@md.metrocast.net> wrote:
>> > On Tue, 2011-02-08 at 10:28 -0500, Alex Deucher wrote:
>> >> On Tue, Feb 8, 2011 at 4:47 AM, Hans Verkuil <hansverk@cisco.com> wrote:
>> >> > Just two quick notes. I'll try to do a full review this weekend.
>> >> >
>> >> > On Tuesday, February 08, 2011 10:30:22 Tomasz Stanislawski wrote:
>> >> >> ==============
>> >> >>  Introduction
>> >> >> ==============
>> >> >>
>> >> >> The purpose of this RFC is to discuss the driver for a TV output interface
>> >> >> available in upcoming Samsung SoC. The HW is able to generate digital and
>> >> >> analog signals. Current version of the driver supports only digital output.
>> >> >>
>> >> >> Internally the driver uses videobuf2 framework, and CMA memory allocator.
>> >> > Not
>> >> >> all of them are merged by now, but I decided to post the sources to start
>> >> >> discussion driver's design.
>> >
>> >> >
>> >> > Cisco (i.e. a few colleagues and myself) are working on this. We hope to post
>> >> > an RFC by the end of this month. We also have a proposal for CEC support in
>> >> > the pipeline.
>> >>
>> >> Any reason to not use the drm kms APIs for modesetting, display
>> >> configuration, and hotplug support?  We already have the
>> >> infrastructure in place for complex display configurations and
>> >> generating events for hotplug interrupts.  It would seem to make more
>> >> sense to me to fix any deficiencies in the KMS APIs than to spin a new
>> >> API.  Things like CEC would be a natural fit since a lot of desktop
>> >> GPUs support hdmi audio/3d/etc. and are already using kms.
>> >>
>> >> Alex
>> >
>> > I'll toss one out: lack of API documentation for driver or application
>> > developers to use.
>> >
>> >
>> > When I last looked at converting ivtvfb to use DRM, KMS, TTM, etc. (to
>> > possibly get rid of reliance on the ivtv X video driver
>> > http://dl.ivtvdriver.org/xf86-video-ivtv/ ), I found the documentation
>> > was really sparse.
>> >
>> > DRM had the most documentation under Documentation/DocBook/drm.tmpl, but
>> > the userland API wasn't fleshed out.  GEM was talked about a bit in
>> > there as well, IIRC.
>> >
>> > TTM documentation was essentially non-existant.
>> >
>> > I can't find any KMS documentation either.
>> >
>> > I recall having to read much of the drm code, and having to look at the
>> > radeon driver, just to tease out what the DRM ioctls needed to do.
>> >
>> > Am I missing a Documentation source for the APIs?
>> >
>>
>> Documentation is somewhat sparse compared to some other APIs.  Mostly
>> inline kerneldoc comments in the core functions.  It would be nice to
>> improve things.   The modesetting API is very similar to the xrandr
>> API in the xserver.
>>
>> At the moment a device specific surface manager (Xorg ddx, or some
>> other userspace lib) is required to use kms due to device specific
>> requirements with respect to memory management and alignment for
>> acceleration.  The kms modesetting ioctls are common across all kms
>> drm drivers, but the memory management ioctls are device specific.
>> GEM itself is an Intel-specific memory manager, although radeon uses
>> similar ioctls.  TTM is used internally by radeon, nouveau, and svga
>> for managing memory gpu accessible memory pools.  Drivers are free to
>> use whatever memory manager they want; an existing one shared with a
>> v4l or platform driver, TTM, or something new.
>>   There is no generic
>> userspace kms driver/lib although Dave and others have done some work
>> to support that, but it's really hard to make a generic interface
>> flexible enough to handle all the strange acceleration requirements of
>> GPUs.
>
> All of the above unfortunately says to me that the KMS API has a fairly
> tightly coupled set of userspace components, because userspace
> applications need have details about the specific underlying hardware
> embeeded in the application to effectively use the API.
>

At the moment, the only thing that uses the APIs are X-like things,
Xorg, but also, wayland and graphical boot managers like plymouth.
However, embedded devices with graphics often have similar usage
models so the APIs would work for them as well.  I'm sorry if I gave
the wrong impression, I was not implying you should use kms for video
capture, but rather it should be considered for video output type
things.  Right now just about every embedded device out there uses
some device specific hack (either a hacked up kernel fb interface or
some proprietary ioctls) to support video output and framebuffers.
The hardware is not that different from desktop hardware.

> If so, that's not really conducive to getting application developers to
> write applications to the API, since applications will get tied to
> specific sets of hardware.
>
> Lack of documentation on the API for userpace application writers to use
> exacerbates that issue, as there are no clearly stated guarantees on
>
>        device node conventions
>        ioctl's
>                arguments and bounds on the arguments
>                expected error return values
>                behavior on error return and meaning of error return
>                which are mandatory, which are optional
>                how to perform "atomic" transactions
>        Behavior of other fops:
>                Are multiple opens allowed or not?
>                Is llseek() meaningful?
>                Is poll() meaningful?
>                Does final close() deallocate all memory objects?
>        sysfs nodes
>                location
>                expected names
>                data formats
>        how compliant or not any one driver is with the KMS APIcontrol
>        where drivers are permitted to behave differently and where they are not
>        What include files do user space applications need to include

For things like 3D, the API is generally provided by large userspace
libraries that provide the actual API used by the applications.  The
API libs talk to the drm via their own device specific ioctls, there's
no real way around that.  However, your app can use the API provided
by that lib, e.g, OpenGL or X rendering.

However, modesetting is common enough across asics that it can and
does use a common API.  Once Dave's generic buffer allocation ioctls
land, you can create a general app that can allocate buffers and set
modes on multiple displays uses only the kms and generic buffer
ioctls.  If you want to do anything more advanced, you will need
device specific APIs.

It's easiest to use libdrm and include xf86drmMode.h.
http://cgit.freedesktop.org/mesa/drm/tree/

There are also device specific helper libs in the libdrm tree
(libdrm_radeon, libdrm_intel, etc.) that provide easy to use
interfaces for device specific ioctls like memory management an
acceleration.

With a combination of libdrm for modesetting and connecting to the
device and device specific libs for acceleration and memory
management, you can support just about any display-type setup you
might want.

>
>
> What device nodes should be opened?
> $ ls -al /dev/dri/*
> crw-rw----+ 1 root video 226,  0 2011-02-09 17:27 /dev/dri/card0
> crw-rw-rw-. 1 root video 226, 64 2011-02-09 17:26 /dev/dri/controlD64
>
> What's the difference between them?
> What's the renderDnn node that can show up?
>
> Which of the below are mandatory for a KMS driver to support?
> Which are optional?
> Which were bad ideas and are deprecated?
>
> #define DRM_IOCTL_MODE_GETRESOURCES     DRM_IOWR(0xA0, struct drm_mode_card_res)
> #define DRM_IOCTL_MODE_GETCRTC          DRM_IOWR(0xA1, struct drm_mode_crtc)
> #define DRM_IOCTL_MODE_SETCRTC          DRM_IOWR(0xA2, struct drm_mode_crtc)
> #define DRM_IOCTL_MODE_CURSOR           DRM_IOWR(0xA3, struct drm_mode_cursor)
> #define DRM_IOCTL_MODE_GETGAMMA         DRM_IOWR(0xA4, struct drm_mode_crtc_lut)
> #define DRM_IOCTL_MODE_SETGAMMA         DRM_IOWR(0xA5, struct drm_mode_crtc_lut)
> #define DRM_IOCTL_MODE_GETENCODER       DRM_IOWR(0xA6, struct drm_mode_get_encoder)
> #define DRM_IOCTL_MODE_GETCONNECTOR     DRM_IOWR(0xA7, struct drm_mode_get_connector)
> #define DRM_IOCTL_MODE_ATTACHMODE       DRM_IOWR(0xA8, struct drm_mode_mode_cmd)
> #define DRM_IOCTL_MODE_DETACHMODE       DRM_IOWR(0xA9, struct drm_mode_mode_cmd)
>
> #define DRM_IOCTL_MODE_GETPROPERTY      DRM_IOWR(0xAA, struct drm_mode_get_property)
>
>        How does one iterate through multiple properties or all they all returned at once?
>        The amount of data returned by drm_mode_get_property seems unbounded
>                as the caller provides some pointers cast to __u64.
>        How is the caller supposed to know how much space to reserve?
>        Is the method consistent across all drivers?
>        What is a property?  Any random (name-tag, value) pair the driver wants to provide?
>        Are there any required properties consistent across all drivers?
>
> #define DRM_IOCTL_MODE_SETPROPERTY      DRM_IOWR(0xAB, struct drm_mode_connector_set_property)
> #define DRM_IOCTL_MODE_GETPROPBLOB      DRM_IOWR(0xAC, struct drm_mode_get_blob)
> #define DRM_IOCTL_MODE_GETFB            DRM_IOWR(0xAD, struct drm_mode_fb_cmd)
> #define DRM_IOCTL_MODE_ADDFB            DRM_IOWR(0xAE, struct drm_mode_fb_cmd)
> #define DRM_IOCTL_MODE_RMFB             DRM_IOWR(0xAF, unsigned int)
> #define DRM_IOCTL_MODE_PAGE_FLIP        DRM_IOWR(0xB0, struct drm_mode_crtc_page_flip)
> #define DRM_IOCTL_MODE_DIRTYFB          DRM_IOWR(0xB1, struct drm_mode_fb_dirty_cmd)
>
>
> If we ask application developers to "read the kernel source and figure
> it out", who is really going to write any userland code to that API?  X
> and Wayland developers.
>
> What userspace application developer is going to crosswalk all the
> drivers and figure out what is universally supported by all the kernel
> drivers, versus what is intel, radeon, or nouveau driver specific?

All kms drivers should support the features handled in the modesetting
fucntions in libdrm.

>
> What are the userspace applications currently using KMS: the Xserver,
> Plymouth, and Wayland?  Any others on the horizon?
>

In theory any display server type thing could use them.

>
>
>>   kms does however provide a legacy kernel fb interface.
>
> That's another reason I had initally looked into it for replacing the
> ivtv X-driver.  I figured moving ivtvfb over to the DRM/KMS FB
> implementation interface could be a first easy step.
>
>
>> While the documentation is not great, the modesetting API is solid and
>> it would be nice to get more people involved and working on it (or at
>> least looking at it)
>
> Does solid mean it is not going to change?

It will change as developers see fit, but so far, for user interfaces,
the current API seems to work fine.

>
>
>>  rather than starting something equivalent from
>> scratch or implementing a device specific modesetting API.
>
> It is too difficult for me to say if it would be equivalent.
>
> The one issue that often springs to mind is the security policy.  Video
> capture and presentation devices may require different user permissions
> than the Desktop, and console VTs.

Sorry, I wasn't talking about video capture, but video output configuration.

>
> If using a common API means both Console and Video devices now have to
> have the same security policy; requires someone to get new, elevated
> privileges; or now means joe-user can DoS the graphics memory system,
> then it is not worth it just for that.

There are several APIs provided by the kms drm, not all of which are required:
1. legacy kernel FB (for console)
2. KMS modesetting (for complex display configuration)
3. memory management (for allocating buffers)
4. acceleration APIs (for sending drawing commands to the GPU)

For console and apps the use the old kernel fb interface, 1. is all
you need.  If you want to support complex displays dynamically, you'd
need 2. and 3.  Right now 3 is device dependant, but a new set of
generic buffer ioctls are going in in 2.6.38.  For accelerated
desktop-type configurations you'd need 2., 3., and 4.  3., and 4. are
device dependant as acceleration and buffer management for
accelerations tend to be very device specific.

>
>>   If you
>> have any questions about it, please ask on dri-devel (CCed).
>
> I've posed some of them both rhetorical and genuine.
>
> Regards,
> Andy
>
>

^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2011-02-12 18:38 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-02-08  9:30 [PATCH/RFC 0/5] HDMI driver for Samsung S5PV310 platform Tomasz Stanislawski
2011-02-08  9:30 ` [PATCH 1/5] i2c-s3c2410: fix I2C dedicated for hdmiphy Tomasz Stanislawski
2011-02-09  7:14   ` Kukjin Kim
2011-02-08  9:30 ` [PATCH 2/5] universal: i2c: add I2C controller 8 (HDMIPHY) Tomasz Stanislawski
2011-02-09  6:54   ` Kukjin Kim
2011-02-08  9:30 ` [PATCH 3/5] v4l: add macro for 1080p59_54 preset Tomasz Stanislawski
2011-02-08  9:30 ` [PATCH 4/5] s5p-tv: add driver for HDMI output on S5PC210 platform Tomasz Stanislawski
2011-02-08  9:30 ` [PATCH 5/5] s5pc210: add s5p-tv to platform devices Tomasz Stanislawski
2011-02-09  6:40   ` Kukjin Kim
2011-02-08  9:47 ` [PATCH/RFC 0/5] HDMI driver for Samsung S5PV310 platform Hans Verkuil
2011-02-08 10:08   ` Marek Szyprowski
2011-02-08 10:21   ` Tomasz Stanislawski
2011-02-08 15:28   ` Alex Deucher
2011-02-08 22:47     ` Andy Walls
2011-02-09  7:12       ` Alex Deucher
2011-02-09 19:00         ` Matt Turner
2011-02-09 19:43           ` Hans Verkuil
2011-02-09 23:59             ` Alex Deucher
2011-02-10  0:51         ` Andy Walls
2011-02-12 18:38           ` Alex Deucher
2011-02-09  8:59     ` Hans Verkuil
2011-02-09 17:55       ` Alex Deucher
2011-02-09 18:45         ` Corbin Simpson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.