summaryrefslogtreecommitdiff
path: root/recipes/linux/linux-2.6.24/smartq5/mer
diff options
context:
space:
mode:
Diffstat (limited to 'recipes/linux/linux-2.6.24/smartq5/mer')
-rw-r--r--recipes/linux/linux-2.6.24/smartq5/mer/0001-Mer-keymappings-change.patch66
-rw-r--r--recipes/linux/linux-2.6.24/smartq5/mer/0002-no-DM9000.patch25
-rw-r--r--recipes/linux/linux-2.6.24/smartq5/mer/0003-Mer-WPA-fix.patch27
-rw-r--r--recipes/linux/linux-2.6.24/smartq5/mer/0004-Mer-hardwire-USB-OTG-gadget-type.patch25
-rw-r--r--recipes/linux/linux-2.6.24/smartq5/mer/0005-backlight-parameter-and-fixes.patch67
-rw-r--r--recipes/linux/linux-2.6.24/smartq5/mer/0006-tv-encoder.patch2624
-rw-r--r--recipes/linux/linux-2.6.24/smartq5/mer/0007-make-tv-encoder-scaler-compile.patch5208
-rw-r--r--recipes/linux/linux-2.6.24/smartq5/mer/0008-build-TV-by-default.patch136
-rw-r--r--recipes/linux/linux-2.6.24/smartq5/mer/0009-Apply-cpufreq-patch-from-gqwang.patch113
-rw-r--r--recipes/linux/linux-2.6.24/smartq5/mer/0010-Better-compatibility-with-some-memory-chips.patch77
-rw-r--r--recipes/linux/linux-2.6.24/smartq5/mer/0011-Only-reserve-memory-for-TV-if-CONFIG_VIDEO_SAMSUNG_T.patch32
-rw-r--r--recipes/linux/linux-2.6.24/smartq5/mer/0012-Disable-TV-out-to-save-RAM.patch100
12 files changed, 8500 insertions, 0 deletions
diff --git a/recipes/linux/linux-2.6.24/smartq5/mer/0001-Mer-keymappings-change.patch b/recipes/linux/linux-2.6.24/smartq5/mer/0001-Mer-keymappings-change.patch
new file mode 100644
index 0000000000..a95ff35c04
--- /dev/null
+++ b/recipes/linux/linux-2.6.24/smartq5/mer/0001-Mer-keymappings-change.patch
@@ -0,0 +1,66 @@
+From 8dd9e60b445d8e002fdf3b4da5199a54ac87c422 Mon Sep 17 00:00:00 2001
+From: Carsten V. Munk <carsten.munk@gmail.com>
+Date: Thu, 6 Aug 2009 09:24:12 +0000
+Subject: [PATCH 01/13] Mer: keymappings change
+
+---
+ arch/arm/mach-s3c6410/mach-smdk6410.c | 12 ++++++------
+ 1 files changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/arch/arm/mach-s3c6410/mach-smdk6410.c b/arch/arm/mach-s3c6410/mach-smdk6410.c
+index 74dadd1..bdcfc59 100644
+--- a/arch/arm/mach-s3c6410/mach-smdk6410.c
++++ b/arch/arm/mach-s3c6410/mach-smdk6410.c
+@@ -299,21 +299,21 @@ static struct gpio_keys_button hhmid_buttons[] = {
+ #if defined (CONFIG_LCD_4)
+ {
+ .gpio = S3C_GPN2, //32*16 + 2
+- .code = KEY_PAGEDOWN,
++ .code = 196,
+ .desc = "Button 0",
+ .active_low = 1,
+ .debounce_interval = 5,
+ },
+ {
+ .gpio = S3C_GPN12,
+- .code = KEY_PAGEUP,
++ .code = 197,
+ .desc = "Button 3",
+ .active_low = 1,
+ .debounce_interval = 5,
+ },
+ {
+ .gpio = S3C_GPN15,
+- .code = KEY_LEFTALT,
++ .code = 195,
+ .desc = "Button 4",
+ .active_low = 1,
+ .debounce_interval = 5,
+@@ -321,21 +321,21 @@ static struct gpio_keys_button hhmid_buttons[] = {
+ #else
+ {
+ .gpio = S3C_GPN4,
+- .code = KEY_PAGEUP,
++ .code = KEY_F7,
+ .desc = "Button 0",
+ .active_low = 1,
+ .debounce_interval = 5,
+ },
+ {
+ .gpio = S3C_GPN3,
+- .code = KEY_PAGEDOWN,
++ .code = KEY_F8,
+ .desc = "Button 1",
+ .active_low = 1,
+ .debounce_interval = 5,
+ },
+ {
+ .gpio = S3C_GPN2, //32*16 + 2
+- .code = KEY_LEFTALT,
++ .code = KEY_F6,
+ .desc = "Button 2",
+ .active_low = 1,
+ .debounce_interval = 5,
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-2.6.24/smartq5/mer/0002-no-DM9000.patch b/recipes/linux/linux-2.6.24/smartq5/mer/0002-no-DM9000.patch
new file mode 100644
index 0000000000..c08915dce6
--- /dev/null
+++ b/recipes/linux/linux-2.6.24/smartq5/mer/0002-no-DM9000.patch
@@ -0,0 +1,25 @@
+From 34c76c67a3f790ff87a0111eee31ffb967b1ae78 Mon Sep 17 00:00:00 2001
+From: Carsten V. Munk <carsten.munk@gmail.com>
+Date: Thu, 6 Aug 2009 09:26:30 +0000
+Subject: [PATCH 02/13] no DM9000
+
+---
+ arch/arm/mach-s3c6410/mach-smdk6410.c | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/arch/arm/mach-s3c6410/mach-smdk6410.c b/arch/arm/mach-s3c6410/mach-smdk6410.c
+index 74dadd1..6e3c2ec 100644
+--- a/arch/arm/mach-s3c6410/mach-smdk6410.c
++++ b/arch/arm/mach-s3c6410/mach-smdk6410.c
+@@ -434,7 +434,7 @@ static struct platform_device *smdk6410_devices[] __initdata = {
+ &s3c_device_g3d,
+ &s3c_device_rotator,
+ #if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
+- &s3c_device_dm9000,
++// &s3c_device_dm9000,
+ #endif
+ };
+
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-2.6.24/smartq5/mer/0003-Mer-WPA-fix.patch b/recipes/linux/linux-2.6.24/smartq5/mer/0003-Mer-WPA-fix.patch
new file mode 100644
index 0000000000..4d7228d1b7
--- /dev/null
+++ b/recipes/linux/linux-2.6.24/smartq5/mer/0003-Mer-WPA-fix.patch
@@ -0,0 +1,27 @@
+From 5884edb0b88bd1cad2c39ad7e88786c0fd1fbd09 Mon Sep 17 00:00:00 2001
+From: Carsten V. Munk <carsten.munk@gmail.com>
+Date: Thu, 6 Aug 2009 09:28:34 +0000
+Subject: [PATCH 03/13] Mer: WPA fix
+
+---
+ drivers/net/wireless/marvell8686/wlan_wext.c | 4 +++-
+ 1 files changed, 3 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/net/wireless/marvell8686/wlan_wext.c b/drivers/net/wireless/marvell8686/wlan_wext.c
+index 85ee593..adef3ab 100644
+--- a/drivers/net/wireless/marvell8686/wlan_wext.c
++++ b/drivers/net/wireless/marvell8686/wlan_wext.c
+@@ -2567,7 +2567,9 @@ wlan_get_range(struct net_device *dev, struct iw_request_info *info,
+ range->throughput = 5000 * 1000;
+ else
+ range->throughput = 1500 * 1000;
+-
++ range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
++ IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
++
+ range->min_rts = MRVDRV_RTS_MIN_VALUE;
+ range->max_rts = MRVDRV_RTS_MAX_VALUE;
+ range->min_frag = MRVDRV_FRAG_MIN_VALUE;
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-2.6.24/smartq5/mer/0004-Mer-hardwire-USB-OTG-gadget-type.patch b/recipes/linux/linux-2.6.24/smartq5/mer/0004-Mer-hardwire-USB-OTG-gadget-type.patch
new file mode 100644
index 0000000000..325a12c81b
--- /dev/null
+++ b/recipes/linux/linux-2.6.24/smartq5/mer/0004-Mer-hardwire-USB-OTG-gadget-type.patch
@@ -0,0 +1,25 @@
+From 1f8979f17ddd3af08784d10171328a06dbb19181 Mon Sep 17 00:00:00 2001
+From: Carsten V. Munk <carsten.munk@gmail.com>
+Date: Thu, 6 Aug 2009 09:30:08 +0000
+Subject: [PATCH 04/13] Mer: hardwire USB OTG gadget type
+
+---
+ drivers/usb/gadget/Kconfig | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
+index f71d038..31888dc 100644
+--- a/drivers/usb/gadget/Kconfig
++++ b/drivers/usb/gadget/Kconfig
+@@ -307,7 +307,7 @@ config USB_GADGET_S3C_OTGD_HS
+
+ config USB_S3C
+ tristate
+- depends on USB_GADGET_S3C_FS || USB_GADGET_S3C_HS || USB_GADGET_S3C_OTGD_HS
++ depends on USB_GADGET_S3C_OTGD_HS
+ default USB_GADGET
+ select USB_GADGET_SELECTED
+
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-2.6.24/smartq5/mer/0005-backlight-parameter-and-fixes.patch b/recipes/linux/linux-2.6.24/smartq5/mer/0005-backlight-parameter-and-fixes.patch
new file mode 100644
index 0000000000..c50e721c54
--- /dev/null
+++ b/recipes/linux/linux-2.6.24/smartq5/mer/0005-backlight-parameter-and-fixes.patch
@@ -0,0 +1,67 @@
+From 64d9ed38c8e6c71ffdbc4640ae38cca3dbcbe782 Mon Sep 17 00:00:00 2001
+From: Carsten V. Munk <carsten.munk@gmail.com>
+Date: Thu, 6 Aug 2009 09:31:09 +0000
+Subject: [PATCH 05/13] backlight parameter and fixes
+
+---
+ drivers/video/s3c/s3cfb.c | 14 +++++++++++++-
+ 1 files changed, 13 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/video/s3c/s3cfb.c b/drivers/video/s3c/s3cfb.c
+index 19ab25f..b854645 100644
+--- a/drivers/video/s3c/s3cfb.c
++++ b/drivers/video/s3c/s3cfb.c
+@@ -14,6 +14,7 @@
+ */
+
+ #include <linux/module.h>
++#include <linux/moduleparam.h>
+ #include <linux/kernel.h>
+ #include <linux/errno.h>
+ #include <linux/string.h>
+@@ -40,8 +41,10 @@
+
+ #include "s3cfb.h"
+
+-//#define CONFIG_FB_COLORBAR 1
++/*
++#define CONFIG_FB_COLORBAR 1
+ #include "colorbar.c"
++*/
+
+ /*
+ * Globals
+@@ -270,7 +273,10 @@ static int s3cfb_blank(int blank_mode, struct fb_info *info)
+ switch (blank_mode) {
+ case VESA_NO_BLANKING: /* lcd on, backlight on */
+ if(!backlight_power)
++ {
+ s3cfb_set_backlight_power(1);
++ s3cfb_set_lcd_power(1);
++ }
+ break;
+
+ case VESA_VSYNC_SUSPEND: /* lcd on, backlight off */
+@@ -923,6 +929,10 @@ static int __init s3cfb_probe(struct platform_device *pdev)
+
+ s3cfb_set_par(&(s3c_fb_info[0].fb));
+ mdelay(10);
++
++ if(backlight_level != S3C_FB_MIN_BACKLIGHT_LEVEL)
++ s3cfb_set_backlight_level(backlight_level);
++
+ //draw_colorbar(&(s3c_fb_info[0].fb));
+
+ return 0;
+@@ -1004,6 +1014,8 @@ static void __exit s3cfb_cleanup(void)
+ module_init(s3cfb_init);
+ module_exit(s3cfb_cleanup);
+
++module_param_named(backlight, backlight_level, int, 0);
++
+ MODULE_AUTHOR("Jinsung Yang");
+ MODULE_DESCRIPTION("S3C Framebuffer Driver");
+ MODULE_LICENSE("GPL");
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-2.6.24/smartq5/mer/0006-tv-encoder.patch b/recipes/linux/linux-2.6.24/smartq5/mer/0006-tv-encoder.patch
new file mode 100644
index 0000000000..624b9c317e
--- /dev/null
+++ b/recipes/linux/linux-2.6.24/smartq5/mer/0006-tv-encoder.patch
@@ -0,0 +1,2624 @@
+From 002a069a3a52b8a2286e8c559a2d3d9a0a954501 Mon Sep 17 00:00:00 2001
+From: Carsten V. Munk <carsten.munk@gmail.com>
+Date: Thu, 6 Aug 2009 11:32:58 +0000
+Subject: [PATCH 06/13] tv encoder
+
+---
+ drivers/media/video/Kconfig | 16 +
+ drivers/media/video/samsung/Makefile | 2 +
+ drivers/media/video/samsung/s3c-tvenc.c | 1479 ++++++++++++++++++++++++++++
+ drivers/media/video/samsung/s3c-tvenc.h | 165 +++
+ drivers/media/video/samsung/s3c-tvscaler.c | 802 +++++++++++++++
+ drivers/media/video/samsung/s3c-tvscaler.h | 96 ++
+ 6 files changed, 2560 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/media/video/samsung/s3c-tvenc.c
+ create mode 100644 drivers/media/video/samsung/s3c-tvenc.h
+ create mode 100644 drivers/media/video/samsung/s3c-tvscaler.c
+ create mode 100644 drivers/media/video/samsung/s3c-tvscaler.h
+
+diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
+index 6506263..8797184 100644
+--- a/drivers/media/video/Kconfig
++++ b/drivers/media/video/Kconfig
+@@ -545,6 +545,22 @@ config VIDEO_ADV7180
+
+ endchoice
+
++config VIDEO_SAMSUNG_TVENC
++ tristate "Samsung TV encoder"
++ depends on I2C && VIDEO_V4L2
++ help
++ Samsung encoder
++
++ To compile this driver as a module, choose M here
++
++config VIDEO_SAMSUNG_TVSCALER
++ tristate "Samsung TV scaler"
++ depends on I2C && VIDEO_V4L2
++ help
++ Samsung TV scaler
++
++ To compile this driver as a module, choose M here
++
+
+ config VIDEO_VINO
+ tristate "SGI Vino Video For Linux (EXPERIMENTAL)"
+diff --git a/drivers/media/video/samsung/Makefile b/drivers/media/video/samsung/Makefile
+index 885512c..ede0269 100644
+--- a/drivers/media/video/samsung/Makefile
++++ b/drivers/media/video/samsung/Makefile
+@@ -7,3 +7,5 @@ obj-$(CONFIG_VIDEO_SAMSUNG_S5K4BA) += 4xa_sensor.o
+ obj-$(CONFIG_VIDEO_ADV7180) += adv7180.o
+ obj-$(CONFIG_VIDEO_APTINA_MT9P012) += mt9p012.o
+
++obj-$(CONFIG_VIDEO_SAMSUNG_TVENC) += s3c_tvenc.o
++obj-$(CONFIG_VIDEO_SAMSUNG_TVSCALER) += s3c_tvenc.o
+diff --git a/drivers/media/video/samsung/s3c-tvenc.c b/drivers/media/video/samsung/s3c-tvenc.c
+new file mode 100644
+index 0000000..11dfd37
+--- /dev/null
++++ b/drivers/media/video/samsung/s3c-tvenc.c
+@@ -0,0 +1,1479 @@
++
++/*
++ * linux/drivers/tvenc/s3c-tvenc.c
++ *
++ * Revision 1.0
++ *
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file COPYING in the main directory of this archive for
++ * more details.
++ *
++ * S3C TV Encoder driver
++ *
++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/types.h>
++#include <linux/timer.h>
++#include <linux/kernel.h>
++#include <linux/fs.h>
++#include <linux/platform_device.h>
++#include <linux/interrupt.h>
++#include <linux/clk.h>
++#include <linux/delay.h>
++#include <asm/uaccess.h>
++#include <linux/errno.h> /* error codes */
++#include <asm/div64.h>
++#include <linux/mm.h>
++#include <linux/tty.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/hardware.h>
++#include <asm/uaccess.h>
++#include <asm/arch/map.h>
++
++#include <linux/version.h>
++#if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,16)
++#include <linux/config.h>
++#include <asm/arch/registers.h>
++#include <linux/videodev2.h>
++#else
++#include <asm/arch/regs-tvenc.h>
++#include <asm/arch/regs-lcd.h>
++#include <media/v4l2-common.h>
++#endif
++
++#include "s3c-tvenc.h"
++
++#define PFX "s3c_tvenc"
++
++static struct clk *tvenc_clock;
++static struct clk *h_clk;
++static int s3c_tvenc_irq = NO_IRQ;
++static struct resource *s3c_tvenc_mem;
++static void __iomem *base;
++static wait_queue_head_t waitq;
++static tv_out_params_t tv_param = {0,};
++
++/* Backup SFR value */
++static u32 backup_reg[2];
++
++
++/* Structure that declares the access functions*/
++
++static void s3c_tvenc_switch(tv_enc_switch_t sw)
++{
++ if(sw == OFF) {
++ __raw_writel(__raw_readl(base + S3C_TVCTRL)
++ &~ S3C_TVCTRL_ON, base + S3C_TVCTRL);
++ } else if(sw == ON) {
++ __raw_writel(__raw_readl(base + S3C_TVCTRL)
++ | S3C_TVCTRL_ON, base + S3C_TVCTRL);
++ } else
++ printk("Error func:%s line:%d\n", __FUNCTION__, __LINE__);
++}
++
++static void s3c_tvenc_set_image_size(u32 width, u32 height)
++{
++ __raw_writel(IIS_WIDTH(width)| IIS_HEIGHT(height),
++ base + S3C_INIMAGESIZE);
++}
++
++#if 0
++static void s3c_tvenc_enable_macrovision(tv_standard_t tvmode, macro_pattern_t pattern)
++{
++ switch(pattern) {
++ case AGC4L :
++ break;
++ case AGC2L :
++ break;
++ case N01 :
++ break;
++ case N02 :
++ break;
++ case P01 :
++ break;
++ case P02 :
++ break;
++ default :
++ break;
++ }
++}
++
++static void s3c_tvenc_disable_macrovision(void)
++{
++ __raw_writel(__raw_readl(base + S3C_MACROVISION0)
++ &~0xff, base + S3C_MACROVISION0);
++}
++#endif
++
++static void s3c_tvenc_set_tv_mode(tv_standard_t mode, tv_conn_type_t out)
++{
++ u32 signal_type = 0, output_type = 0;
++
++ switch(mode) {
++ case PAL_N :
++ __raw_writel(VBP_VEFBPD_PAL|VBP_VOFBPD_PAL,
++ base + S3C_VBPORCH);
++ __raw_writel(HBP_HSPW_PAL|HBP_HBPD_PAL,
++ base + S3C_HBPORCH);
++ __raw_writel(HEO_DTO_PAL|HEO_HEOV_PAL,
++ base + S3C_HENHOFFSET);
++ __raw_writel(EPC_PED_ON,
++ base + S3C_PEDCTRL);
++ __raw_writel(YFB_YBW_26|YFB_CBW_06,
++ base + S3C_YCFILTERBW);
++ __raw_writel(SSC_HSYNC_PAL,
++ base + S3C_SYNCSIZECTRL);
++ __raw_writel(BSC_BEND_PAL|BSC_BSTART_PAL,
++ base + S3C_BURSTCTRL);
++ __raw_writel(MBS_BSTART_PAL,
++ base + S3C_MACROBURSTCTRL);
++ __raw_writel(AVP_AVEND_PAL|AVP_AVSTART_PAL,
++ base + S3C_ACTVIDPOCTRL);
++ break;
++ case PAL_NC :
++ case PAL_BGHID :
++ __raw_writel(VBP_VEFBPD_PAL|VBP_VOFBPD_PAL,
++ base + S3C_VBPORCH);
++ __raw_writel(HBP_HSPW_PAL|HBP_HBPD_PAL,
++ base + S3C_HBPORCH);
++ __raw_writel(HEO_DTO_PAL|HEO_HEOV_PAL,
++ base + S3C_HENHOFFSET);
++ __raw_writel(EPC_PED_OFF,
++ base + S3C_PEDCTRL);
++ __raw_writel(YFB_YBW_26|YFB_CBW_06,
++ base + S3C_YCFILTERBW);
++ __raw_writel(SSC_HSYNC_PAL,
++ base + S3C_SYNCSIZECTRL);
++ __raw_writel(BSC_BEND_PAL|BSC_BSTART_PAL,
++ base + S3C_BURSTCTRL);
++ __raw_writel(MBS_BSTART_PAL,
++ base + S3C_MACROBURSTCTRL);
++ __raw_writel(AVP_AVEND_PAL|AVP_AVSTART_PAL,
++ base + S3C_ACTVIDPOCTRL);
++ break;
++ case NTSC_443 :
++ __raw_writel(VBP_VEFBPD_NTSC|VBP_VOFBPD_NTSC,
++ base + S3C_VBPORCH);
++ __raw_writel(HBP_HSPW_NTSC|HBP_HBPD_NTSC,
++ base + S3C_HBPORCH);
++ __raw_writel(HEO_DTO_NTSC|HEO_HEOV_NTSC,
++ base + S3C_HENHOFFSET);
++ __raw_writel(EPC_PED_ON,
++ base + S3C_PEDCTRL);
++ __raw_writel(YFB_YBW_26|YFB_CBW_06,
++ base + S3C_YCFILTERBW);
++ __raw_writel(SSC_HSYNC_NTSC,
++ base + S3C_SYNCSIZECTRL);
++ __raw_writel(BSC_BEND_NTSC|BSC_BSTART_NTSC,
++ base + S3C_BURSTCTRL);
++ __raw_writel(MBS_BSTART_NTSC,
++ base + S3C_MACROBURSTCTRL);
++ __raw_writel(AVP_AVEND_NTSC|AVP_AVSTART_NTSC,
++ base + S3C_ACTVIDPOCTRL);
++ break;
++ case NTSC_J :
++ __raw_writel(VBP_VEFBPD_NTSC|VBP_VOFBPD_NTSC,
++ base + S3C_VBPORCH);
++ __raw_writel(HBP_HSPW_NTSC|HBP_HBPD_NTSC,
++ base + S3C_HBPORCH);
++ __raw_writel(HEO_DTO_NTSC|HEO_HEOV_NTSC,
++ base + S3C_HENHOFFSET);
++ __raw_writel(EPC_PED_OFF,
++ base + S3C_PEDCTRL);
++ __raw_writel(YFB_YBW_21|YFB_CBW_06,
++ base + S3C_YCFILTERBW);
++ __raw_writel(SSC_HSYNC_NTSC,
++ base + S3C_SYNCSIZECTRL);
++ __raw_writel(BSC_BEND_NTSC|BSC_BSTART_NTSC,
++ base + S3C_BURSTCTRL);
++ __raw_writel(MBS_BSTART_NTSC,
++ base + S3C_MACROBURSTCTRL);
++ __raw_writel(AVP_AVEND_NTSC|AVP_AVSTART_NTSC,
++ base + S3C_ACTVIDPOCTRL);
++ break;
++ case PAL_M :
++ case NTSC_M :
++ default :
++ __raw_writel(VBP_VEFBPD_NTSC|VBP_VOFBPD_NTSC,
++ base + S3C_VBPORCH);
++ __raw_writel(HBP_HSPW_NTSC|HBP_HBPD_NTSC,
++ base + S3C_HBPORCH);
++ __raw_writel(HEO_DTO_NTSC|HEO_HEOV_NTSC,
++ base + S3C_HENHOFFSET);
++ __raw_writel(EPC_PED_ON,
++ base + S3C_PEDCTRL);
++ __raw_writel(YFB_YBW_21|YFB_CBW_06,
++ base + S3C_YCFILTERBW);
++ __raw_writel(SSC_HSYNC_NTSC,
++ base + S3C_SYNCSIZECTRL);
++ __raw_writel(BSC_BEND_NTSC|BSC_BSTART_NTSC,
++ base + S3C_BURSTCTRL);
++ __raw_writel(MBS_BSTART_NTSC,
++ base + S3C_MACROBURSTCTRL);
++ __raw_writel(AVP_AVEND_NTSC|AVP_AVSTART_NTSC,
++ base + S3C_ACTVIDPOCTRL);
++ break;
++ }
++
++ if(out == S_VIDEO) {
++ __raw_writel(YFB_YBW_60|YFB_CBW_06,
++ base + S3C_YCFILTERBW);
++ output_type = S3C_TVCTRL_OUTTYPE_S;
++ } else
++ output_type = S3C_TVCTRL_OUTTYPE_C;
++
++ switch(mode) {
++ case NTSC_M :
++ signal_type = S3C_TVCTRL_OUTFMT_NTSC_M;
++ break;
++ case NTSC_J :
++ signal_type = S3C_TVCTRL_OUTFMT_NTSC_J;
++ break;
++ case PAL_BGHID :
++ signal_type = S3C_TVCTRL_OUTFMT_PAL_BDG;
++ break;
++ case PAL_M :
++ signal_type = S3C_TVCTRL_OUTFMT_PAL_M;
++ break;
++ case PAL_NC :
++ signal_type = S3C_TVCTRL_OUTFMT_PAL_NC;
++ break;
++ default:
++ printk("s3c_tvenc_set_tv_mode : No matching signal_type!\n");
++ break;
++ }
++
++ __raw_writel((__raw_readl(base + S3C_TVCTRL)
++ &~(0x1f<<4))| output_type | signal_type,
++ base + S3C_TVCTRL);
++
++ __raw_writel(0x01, base + S3C_FSCAUXCTRL);
++}
++
++#if 0
++static void s3c_tvenc_set_pedestal(tv_enc_switch_t sw)
++{
++ if(sw)
++ __raw_writel(EPC_PED_ON, base + S3C_PEDCTRL);
++ else
++ __raw_writel(EPC_PED_OFF, base + S3C_PEDCTRL);
++}
++
++static void s3c_tvenc_set_sub_carrier_freq(u32 freq)
++{
++ __raw_writel(FSC_CTRL(freq), base + S3C_FSCCTRL);
++}
++
++static void s3c_tvenc_set_fsc_dto(u32 val)
++{
++ unsigned int temp;
++
++ temp = (0x1<<31)|(val&0x7fffffff);
++ __raw_writel(temp, base + S3C_FSCDTOMANCTRL);
++}
++
++static void s3c_tvenc_disable_fsc_dto(void)
++{
++ __raw_writel(__raw_readl(base + S3C_FSCDTOMANCTRL)&~(1<<31),
++ base + S3C_FSCDTOMANCTRL);
++}
++
++static void s3c_tvenc_set_bg(u32 soft_mix, u32 color, u32 lum_offset)
++{
++ unsigned int bg_color;
++ switch(color) {
++ case 0 :
++ bg_color = BGC_BGCS_BLACK;
++ break;
++ case 1 :
++ bg_color = BGC_BGCS_BLUE;
++ break;
++ case 2 :
++ bg_color = BGC_BGCS_RED;
++ break;
++ case 3 :
++ bg_color = BGC_BGCS_MAGENTA;
++ break;
++ case 4 :
++ bg_color = BGC_BGCS_GREEN;
++ break;
++ case 5 :
++ bg_color = BGC_BGCS_CYAN;
++ break;
++ case 6 :
++ bg_color = BGC_BGCS_YELLOW;
++ break;
++ case 7 :
++ bg_color = BGC_BGCS_WHITE;
++ break;
++ }
++ if(soft_mix)
++ __raw_writel(BGC_SME_ENA|bg_color|BGC_BGYOFS(lum_offset),
++ base + S3C_BGCTRL);
++ else
++ __raw_writel(BGC_SME_DIS|bg_color|BGC_BGYOFS(lum_offset),
++ base + S3C_BGCTRL);
++
++}
++
++static void s3c_tvenc_set_bg_vav_hav(u32 hav_len, u32 vav_len, u32 hav_st, u32 vav_st)
++{
++ __raw_writel(BVH_BG_HL(hav_len)|BVH_BG_HS(hav_st)|BVH_BG_VL(vav_len)|BVH_BG_VS(vav_st),
++ base + S3C_BGHVAVCTRL);
++}
++#endif
++
++static void s3c_tvenc_set_hue_phase(u32 phase_val)
++{
++ __raw_writel(HUE_CTRL(phase_val),
++ base + S3C_HUECTRL);
++}
++
++#if 0
++static u32 s3c_tvenc_get_hue_phase(void)
++{
++ return __raw_readl(base + S3C_HUECTRL)&0xff;
++}
++#endif
++
++static void s3c_tvenc_set_contrast(u32 contrast)
++{
++ u32 temp;
++
++ temp = __raw_readl(base + S3C_CONTRABRIGHT);
++
++ __raw_writel((temp &~0xff)|contrast,
++ base + S3C_CONTRABRIGHT);
++}
++
++#if 0
++static u32 s3c_tvenc_get_contrast(void)
++{
++ return (__raw_readl(base + S3C_CONTRABRIGHT)&0xff);
++}
++#endif
++
++static void s3c_tvenc_set_bright(u32 bright)
++{
++ u32 temp;
++
++ temp = __raw_readl(base + S3C_CONTRABRIGHT);
++
++ __raw_writel((temp &~(0xff<<16))| (bright<<16),
++ base + S3C_CONTRABRIGHT);
++}
++
++#if 0
++static u32 s3c_tvenc_get_bright(void)
++{
++ return ((__raw_readl(base + S3C_CONTRABRIGHT)&(0xff<<16))>>16);
++}
++
++
++static void s3c_tvenc_set_cbgain(u32 cbgain)
++{
++ u32 temp;
++
++ temp = __raw_readl(base + S3C_CBCRGAINCTRL);
++
++ __raw_writel((temp &~0xff)|cbgain,
++ base + S3C_CBCRGAINCTRL);
++}
++
++
++static u32 s3c_tvenc_get_cbgain(void)
++{
++ return (__raw_readl(base + S3C_CBCRGAINCTRL)&0xff);
++}
++
++static void s3c_tvenc_set_crgain(u32 crgain)
++{
++ u32 temp;
++
++ temp = __raw_readl(base + S3C_CBCRGAINCTRL);
++
++ __raw_writel((temp &~(0xff<<16))| (crgain<<16),
++ base + S3C_CBCRGAINCTRL);
++}
++
++static u32 s3c_tvenc_get_crgain(void)
++{
++ return ((__raw_readl(base + S3C_CBCRGAINCTRL)&(0xff<<16))>>16);
++}
++#endif
++
++static void s3c_tvenc_enable_gamma_control(tv_enc_switch_t enable)
++{
++ u32 temp;
++
++ temp = __raw_readl(base + S3C_GAMMACTRL);
++ if(enable == ON)
++ temp |= (1<<12);
++ else
++ temp &= ~(1<<12);
++
++ __raw_writel(temp, base + S3C_GAMMACTRL);
++}
++
++static void s3c_tvenc_set_gamma_gain(u32 ggain)
++{
++ u32 temp;
++
++ temp = __raw_readl(base + S3C_GAMMACTRL);
++
++ __raw_writel((temp &~(0x7<<8))| (ggain<<8),
++ base + S3C_GAMMACTRL);
++}
++
++#if 0
++static u32 s3c_tvenc_get_gamma_gain(void)
++{
++ return ((__raw_readl(base + S3C_GAMMACTRL)&(0x7<<8))>>8);
++}
++
++static void s3c_tvenc_enable_mute_control(tv_enc_switch_t enable)
++{
++ u32 temp;
++
++ temp = __raw_readl(base + S3C_GAMMACTRL);
++ if(enable == ON)
++ temp |= (1<<12);
++ else
++ temp &= ~(1<<12);
++
++ __raw_writel(temp, base + S3C_GAMMACTRL);
++}
++
++static void s3c_tvenc_set_mute(u32 y, u32 cb, u32 cr)
++{
++ u32 temp;
++
++ temp = __raw_readl(base + S3C_MUTECTRL);
++
++ temp &=~(0xffffff<<8);
++ temp |= (cr & 0xff)<<24;
++ temp |= (cb & 0xff)<<16;
++ temp |= (y & 0xff)<<8;
++
++ __raw_writel(temp, base + S3C_MUTECTRL);
++}
++
++static void s3c_tvenc_get_mute(u32 *y, u32 *cb, u32 *cr)
++{
++ u32 temp;
++
++ temp = __raw_readl(base + S3C_MUTECTRL);
++
++ *y = (temp&(0xff<<8))>>8;
++ *cb = (temp&(0xff<<16))>>16;
++ *cr = (temp&(0xff<<24))>>24;
++}
++#endif
++
++static void s3c_tvenc_get_active_win_center(u32 *vert, u32 *horz)
++{
++ u32 temp;
++
++ temp = __raw_readl(base + S3C_HENHOFFSET);
++
++ *vert = (temp&(0x3f<<24))>>24;
++ *horz = (temp&(0xff<<16))>>16;
++}
++
++static void s3c_tvenc_set_active_win_center(u32 vert, u32 horz)
++{
++ u32 temp;
++
++ temp = __raw_readl(base + S3C_HENHOFFSET);
++
++ temp &=~(0x3ffff<<16);
++ temp |= (vert&0x3f)<<24;
++ temp |= (horz&0xff)<<16;
++
++ __raw_writel(temp, base + S3C_HENHOFFSET);
++}
++
++// LCD display controller configuration functions
++static void s3c_lcd_set_output_path(lcd_local_output_t out)
++{
++#if 0 // peter for 2.6.21 kernel
++ s3c_fb_set_output_path(out);
++#else // peter for 2.6.24 kernel
++ s3cfb_set_output_path(out);
++#endif
++}
++
++static void s3c_lcd_set_clkval(u32 clkval)
++{
++#if 0 // peter for 2.6.21 kernel
++ s3c_fb_set_clkval(clkval);
++#else // peter for 2.6.24 kernel
++ s3cfb_set_clock(clkval);
++#endif
++}
++
++static void s3c_lcd_enable_rgbport(u32 on_off)
++{
++#if 0 // peter for 2.6.21 kernel
++ s3c_fb_enable_rgbport(on_off);
++#else // peter for 2.6.24 kernel
++ s3cfb_enable_rgbport(on_off);
++#endif
++}
++
++static void s3c_lcd_start(void)
++{
++#if 0 // peter for 2.6.21 kernel
++ s3c_fb_start_lcd();
++#else // peter for 2.6.24 kernel
++ s3cfb_start_lcd();
++#endif
++}
++
++static void s3c_lcd_stop(void)
++{
++#if 0 // peter for 2.6.21 kernel
++ s3c_fb_stop_lcd();
++#else // peter for 2.6.24 kernel
++ s3cfb_stop_lcd();
++#endif
++}
++
++
++static void s3c_lcd_set_config(void)
++{
++ backup_reg[0] = __raw_readl(S3C_VIDCON0);
++ backup_reg[1] = __raw_readl(S3C_VIDCON2);
++
++ s3c_lcd_set_output_path(LCD_TVRGB);
++ tv_param.lcd_output_mode = LCD_TVRGB;
++
++ s3c_lcd_set_clkval(4);
++ s3c_lcd_enable_rgbport(1);
++}
++
++static void s3c_lcd_exit_config(void)
++{
++ __raw_writel(backup_reg[0], S3C_VIDCON0);
++ __raw_writel(backup_reg[1], S3C_VIDCON2);
++ tv_param.lcd_output_mode = LCD_RGB;
++}
++
++static int scaler_test_start(void)
++{
++ tv_param.sp.DstFullWidth = 640;
++ tv_param.sp.DstFullHeight= 480;
++ tv_param.sp.DstCSpace = RGB16;
++
++ s3c_tvscaler_config(&tv_param.sp);
++
++ s3c_tvscaler_int_enable(1);
++
++ s3c_tvscaler_start();
++
++ return 0;
++}
++
++static int scaler_test_stop(void)
++{
++ s3c_tvscaler_int_disable();
++
++ return 0;
++}
++
++
++static int tvout_start(void)
++{
++ u32 width, height;
++ tv_standard_t type;
++ tv_conn_type_t conn;
++
++ tv_param.sp.DstFullWidth *= 2; // For TV OUT
++
++ width = tv_param.sp.DstFullWidth;
++ height = tv_param.sp.DstFullHeight;
++ type = tv_param.sig_type;
++ conn = tv_param.connect;
++
++ /* Set TV-SCALER parameter */
++ switch(tv_param.v2.input->type) {
++ case V4L2_INPUT_TYPE_FIFO: // LCD FIFO-OUT
++ tv_param.sp.Mode = FREE_RUN;
++ tv_param.sp.DstCSpace = YCBYCR;
++ /* Display controller setting */
++ s3c_lcd_stop();
++ s3c_lcd_set_config();
++ break;
++ case V4L2_INPUT_TYPE_MSDMA: // MSDMA
++ tv_param.sp.Mode = FREE_RUN;
++ tv_param.sp.DstCSpace = YCBYCR;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ s3c_tvenc_set_tv_mode(type, conn);
++ s3c_tvenc_set_image_size(width, height);
++ s3c_tvenc_switch(ON);
++
++ s3c_tvscaler_config(&tv_param.sp); // for setting DstStartX/Y, DstWidth/Height
++ s3c_tvscaler_set_interlace(1);
++ if(tv_param.v2.input->type == V4L2_INPUT_TYPE_FIFO)
++ s3c_tvscaler_int_disable();
++ else
++ s3c_tvscaler_int_enable(1);
++ s3c_tvscaler_start();
++
++ if(tv_param.v2.input->type == V4L2_INPUT_TYPE_FIFO)
++ s3c_lcd_start();
++
++ return 0;
++}
++
++static int tvout_stop(void)
++{
++
++ s3c_tvscaler_set_interlace(0);
++ s3c_tvscaler_stop_freerun();
++ s3c_tvscaler_int_disable();
++ s3c_tvenc_switch(OFF);
++
++ switch(tv_param.v2.input->type) {
++ case V4L2_INPUT_TYPE_FIFO: // LCD FIFO-OUT
++ /* Display controller setting */
++ s3c_lcd_stop();
++ s3c_lcd_exit_config();
++ s3c_lcd_start();
++ break;
++ default:
++ break;
++ }
++ return 0;
++}
++
++/* ------------------------------------------ V4L2 SUPPORT ----------------------------------------------*/
++/* ------------- In FIFO and MSDMA, v4l2_input supported by S3C TVENC controller ------------------*/
++static struct v4l2_input tvenc_inputs[] = {
++ {
++ .index = 0,
++ .name = "LCD FIFO_OUT",
++ .type = V4L2_INPUT_TYPE_FIFO,
++ .audioset = 1,
++ .tuner = 0, /* ignored */
++ .std = 0,
++ .status = 0,
++ },
++ {
++ .index = 1,
++ .name = "Memory input (MSDMA)",
++ .type = V4L2_INPUT_TYPE_MSDMA,
++ .audioset = 2,
++ .tuner = 0,
++ .std = 0,
++ .status = 0,
++ }
++};
++
++/* ------------ Out FIFO and MADMA, v4l2_output supported by S3C TVENC controller ----------------*/
++static struct v4l2_output tvenc_outputs[] = {
++ {
++ .index = 0,
++ .name = "TV-OUT",
++ .type = V4L2_OUTPUT_TYPE_ANALOG,
++ .audioset = 0,
++ .modulator = 0,
++ .std = V4L2_STD_PAL | V4L2_STD_NTSC_M,
++ },
++ {
++ .index = 1,
++ .name = "Memory output (MSDMA)",
++ .type = V4L2_OUTPUT_TYPE_MSDMA,
++ .audioset = 0,
++ .modulator = 0,
++ .std = 0,
++ },
++
++};
++
++const struct v4l2_fmtdesc tvenc_input_formats[] = {
++ {
++ .index = 0,
++ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
++ .description = "16 bpp RGB, le",
++ .pixelformat = V4L2_PIX_FMT_RGB565,
++ .flags = FORMAT_FLAGS_PACKED,
++ },
++ {
++ .index = 1,
++ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
++ .flags = FORMAT_FLAGS_PACKED,
++ .description = "24 bpp RGB, le",
++ .pixelformat = V4L2_PIX_FMT_RGB24,
++ },
++ {
++ .index = 2,
++ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
++ .flags = FORMAT_FLAGS_PLANAR,
++ .description = "4:2:2, planar, Y-Cb-Cr",
++ .pixelformat = V4L2_PIX_FMT_YUV422P,
++
++ },
++ {
++ .index = 3,
++ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
++ .flags = FORMAT_FLAGS_PLANAR,
++ .description = "4:2:0, planar, Y-Cb-Cr",
++ .pixelformat = V4L2_PIX_FMT_YUV420,
++ }
++};
++
++
++const struct v4l2_fmtdesc tvenc_output_formats[] = {
++ {
++ .index = 0,
++ .type = V4L2_BUF_TYPE_VIDEO_OUTPUT,
++ .description = "16 bpp RGB, le",
++ .pixelformat = V4L2_PIX_FMT_RGB565,
++ .flags = FORMAT_FLAGS_PACKED,
++ },
++ {
++ .index = 1,
++ .type = V4L2_BUF_TYPE_VIDEO_OUTPUT,
++ .flags = FORMAT_FLAGS_PACKED,
++ .description = "24 bpp RGB, le",
++ .pixelformat = V4L2_PIX_FMT_RGB24,
++ },
++ {
++ .index = 2,
++ .type = V4L2_BUF_TYPE_VIDEO_OUTPUT,
++ .flags = FORMAT_FLAGS_PLANAR,
++ .description = "4:2:2, planar, Y-Cb-Cr",
++ .pixelformat = V4L2_PIX_FMT_YUV422P,
++
++ },
++ {
++ .index = 3,
++ .type = V4L2_BUF_TYPE_VIDEO_OUTPUT,
++ .flags = FORMAT_FLAGS_PLANAR,
++ .description = "4:2:0, planar, Y-Cb-Cr",
++ .pixelformat = V4L2_PIX_FMT_YUV420,
++ }
++};
++
++const struct v4l2_standard tvout_standards[] = {
++ {
++ .index = 0,
++ .id = V4L2_STD_NTSC_M,
++ .name = "NTSC type",
++ },
++ {
++ .index = 1,
++ .id = V4L2_STD_PAL,
++ .name = "PAL type",
++ }
++};
++
++#define NUMBER_OF_INPUT_FORMATS ARRAY_SIZE(tvenc_input_formats)
++#define NUMBER_OF_OUTPUT_FORMATS ARRAY_SIZE(tvenc_output_formats)
++#define NUMBER_OF_INPUTS ARRAY_SIZE(tvenc_inputs)
++#define NUMBER_OF_OUTPUTS ARRAY_SIZE(tvenc_outputs)
++#define NUMBER_OF_STANDARDS ARRAY_SIZE(tvout_standards)
++
++static int s3c_tvenc_g_fmt(struct v4l2_format *f)
++{
++ int size = sizeof(struct v4l2_pix_format);
++
++ memset(&f->fmt.pix, 0, size);
++ memcpy(&f->fmt.pix, &tv_param.v2.pixfmt, size);
++
++ return 0;
++}
++
++static int s3c_tvenc_s_fmt(struct v4l2_format *f)
++{
++ /* update our state informations */
++ tv_param.v2.pixfmt= f->fmt.pix;
++
++ // peter LCD output related operation
++ if (tv_param.v2.pixfmt.pixelformat == V4L2_PIX_FMT_RGB565 ) {
++
++ tv_param.sp.SrcFullWidth = tv_param.v2.pixfmt.width;
++ tv_param.sp.SrcFullHeight = tv_param.v2.pixfmt.height;
++ tv_param.sp.SrcStartX = 0;
++ tv_param.sp.SrcStartY = 0;
++ tv_param.sp.SrcWidth = tv_param.sp.SrcFullWidth;
++ tv_param.sp.SrcHeight = tv_param.sp.SrcFullHeight;
++
++ printk("TV-OUT: LCD path operation set\n");
++
++ // peter for padded data of mfc output
++ } else if (tv_param.v2.pixfmt.pixelformat == V4L2_PIX_FMT_YUV420) {
++
++#ifdef DIVX_TEST // padded output
++ tv_param.sp.SrcFullWidth = tv_param.v2.pixfmt.width + 2*16;
++ tv_param.sp.SrcFullHeight = tv_param.v2.pixfmt.height + 2*16;
++ tv_param.sp.SrcStartX = 16;
++ tv_param.sp.SrcStartY = 16;
++ tv_param.sp.SrcWidth = tv_param.sp.SrcFullWidth - 2*tv_param.sp.SrcStartX;
++ tv_param.sp.SrcHeight = tv_param.sp.SrcFullHeight - 2*tv_param.sp.SrcStartY;
++#else // not padded output
++ tv_param.sp.SrcFullWidth = tv_param.v2.pixfmt.width;
++ tv_param.sp.SrcFullHeight = tv_param.v2.pixfmt.height;
++ tv_param.sp.SrcStartX = 0;
++ tv_param.sp.SrcStartY = 0;
++ tv_param.sp.SrcWidth = tv_param.sp.SrcFullWidth;
++ tv_param.sp.SrcHeight = tv_param.sp.SrcFullHeight;
++#endif
++
++ printk("TV-OUT: MFC path operation set\n");
++
++ }
++
++ switch(tv_param.v2.pixfmt.pixelformat) {
++ case V4L2_PIX_FMT_RGB565:
++ tv_param.sp.SrcCSpace = RGB16;
++ break;
++ case V4L2_PIX_FMT_RGB24:
++ tv_param.sp.SrcCSpace = RGB24;
++ break;
++ case V4L2_PIX_FMT_YUV420:
++ tv_param.sp.SrcCSpace = YC420;
++ break;
++ case V4L2_PIX_FMT_YUV422P:
++ tv_param.sp.SrcCSpace = YC422;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++// camif_convert_into_camif_cfg_t(cfg, 1);
++ return 0;
++}
++
++static int s3c_tvenc_s_input(int index)
++{
++
++ tv_param.v2.input = &tvenc_inputs[index];
++ switch(tv_param.v2.input->type) {
++ case V4L2_INPUT_TYPE_FIFO: // LCD FIFO-OUT
++ tv_param.sp.InPath = POST_FIFO;
++ break;
++ case V4L2_INPUT_TYPE_MSDMA: // MSDMA
++ tv_param.sp.InPath = POST_DMA;
++ break;
++ default:
++ return -EINVAL;
++ }
++ return 0;
++}
++
++static int s3c_tvenc_s_output(int index)
++{
++ tv_param.v2.output = &tvenc_outputs[index];
++ switch(tv_param.v2.output->type) {
++ case V4L2_OUTPUT_TYPE_ANALOG: // TV-OUT (FIFO-OUT)
++ tv_param.sp.OutPath = POST_FIFO;
++ break;
++ case V4L2_OUTPUT_TYPE_MSDMA: // MSDMA
++ tv_param.sp.OutPath = POST_DMA;
++ break;
++ default:
++ return -EINVAL;
++ }
++ return 0;
++}
++
++static int s3c_tvenc_s_std(v4l2_std_id *id)
++{
++// printk("s3c_tvenc_s_std: *id=0x%x",*id);
++ switch(*id) {
++ case V4L2_STD_NTSC_M:
++ tv_param.sig_type = NTSC_M;
++ tv_param.sp.DstFullWidth = 720;
++ tv_param.sp.DstFullHeight = 480;
++ break;
++ case V4L2_STD_PAL:
++ tv_param.sig_type = PAL_M;
++ tv_param.sp.DstFullWidth = 720;
++ tv_param.sp.DstFullHeight = 576;
++ break;
++ default:
++ return -EINVAL;
++ }
++ return 0;
++}
++
++static int s3c_tvenc_v4l2_control(struct v4l2_control *ctrl)
++{
++ switch(ctrl->id) {
++
++ // peter added for MFC related op.
++ case V4L2_CID_MPEG_STREAM_PID_VIDEO:
++ {
++ tv_param.sp.SrcFrmSt = ctrl->value;
++ return 0;
++ }
++
++ case V4L2_CID_CONNECT_TYPE:
++ {
++ if(ctrl->value == 0) { // COMPOSITE
++ tv_param.connect = COMPOSITE;
++ } else if(ctrl->value == 1) { //S-VIDEO
++ tv_param.connect = S_VIDEO;
++ } else {
++ return -EINVAL;
++ }
++ return 0;
++ }
++
++ case V4L2_CID_BRIGHTNESS:
++ {
++ s32 val = ctrl->value;
++ if((val > 0xff)||(val < 0))
++ return -EINVAL;
++ else
++ s3c_tvenc_set_bright(val);
++
++ return 0;
++ }
++
++ case V4L2_CID_CONTRAST:
++ {
++ s32 val = ctrl->value;
++ if((val > 0xff)||(val < 0))
++ return -EINVAL;
++ else
++ s3c_tvenc_set_contrast(val);
++
++ return 0;
++ }
++
++ case V4L2_CID_GAMMA:
++ {
++ s32 val = ctrl->value;
++ if((val > 0x3)||(val < 0)) {
++ return -EINVAL;
++ } else {
++ s3c_tvenc_enable_gamma_control(ON);
++ s3c_tvenc_set_gamma_gain(val);
++ s3c_tvenc_enable_gamma_control(OFF);
++ }
++ return 0;
++ }
++
++ case V4L2_CID_HUE:
++ {
++ s32 val = ctrl->value;
++ if((val > 0xff)||(val < 0))
++ return -EINVAL;
++ else
++ s3c_tvenc_set_hue_phase(val);
++
++ return 0;
++ }
++
++ case V4L2_CID_HCENTER:
++ {
++ s32 val = ctrl->value;
++ u32 curr_horz, curr_vert;
++
++ if((val > 0xff)||(val < 0)) {
++ return -EINVAL;
++ } else {
++ s3c_tvenc_get_active_win_center(&curr_vert, &curr_horz);
++ s3c_tvenc_set_active_win_center(curr_vert, val);
++ }
++
++ return 0;
++ }
++
++ case V4L2_CID_VCENTER:
++ {
++ s32 val = ctrl->value;
++ u32 curr_horz, curr_vert;
++
++ if((val > 0x3f)||(val < 0)) {
++ return -EINVAL;
++ } else {
++ s3c_tvenc_get_active_win_center(&curr_vert, &curr_horz);
++ s3c_tvenc_set_active_win_center(val, curr_horz);
++ }
++
++ return 0;
++ }
++
++ default:
++ return -EINVAL;
++ }
++ return 0;
++}
++
++int s3c_tvenc_open(struct inode *inode, struct file *filp)
++{
++ int err;
++
++ err = video_exclusive_open(inode, filp); // One function of V4l2 driver
++
++ if(err < 0)
++ return err;
++ filp->private_data = &tv_param;
++
++ s3c_tvscaler_init();
++
++ /* Success */
++ return 0;
++}
++
++int s3c_tvenc_release(struct inode *inode, struct file *filp)
++{
++ video_exclusive_release(inode, filp);
++
++ /* Success */
++ return 0;
++}
++
++static int s3c_tvenc_do_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,void *arg)
++{
++ int ret;
++
++ switch(cmd){
++ case VIDIOC_QUERYCAP:
++ {
++ struct v4l2_capability *cap = arg;
++ strcpy(cap->driver, "S3C TV-OUT driver");
++ strlcpy(cap->card, tv_param.v->name, sizeof(cap->card));
++ sprintf(cap->bus_info, "ARM AHB BUS");
++ cap->version = 0;
++ cap->capabilities = tv_param.v->type2;
++ return 0;
++ }
++
++ case VIDIOC_OVERLAY:
++ {
++ int on = *(int *)arg;
++
++ printk("TV-OUT: VIDIOC_OVERLAY on:%d\n", on);
++ if (on != 0) {
++ ret = tvout_start();
++ } else {
++ ret = tvout_stop();
++ }
++ return ret;
++ }
++
++ case VIDIOC_ENUMINPUT:
++ {
++ struct v4l2_input *i = arg;
++ printk("TV-OUT: VIDIOC_ENUMINPUT : index = %d\n", i->index);
++
++ if ((i->index) >= NUMBER_OF_INPUTS) {
++ return -EINVAL;
++ }
++ memcpy(i, &tvenc_inputs[i->index], sizeof(struct v4l2_input));
++ return 0;
++ }
++
++ case VIDIOC_S_INPUT: // 0 -> LCD FIFO-OUT, 1 -> MSDMA
++ {
++ int index = *((int *)arg);
++ printk("TV-OUT: VIDIOC_S_INPUT \n");
++
++ if (index >= NUMBER_OF_INPUTS) {
++ return -EINVAL;
++ }
++ else {
++ s3c_tvenc_s_input(index);
++ return 0;
++ }
++ }
++
++ case VIDIOC_G_INPUT:
++ {
++ u32 *i = arg;
++ printk("TV-OUT: VIDIOC_G_INPUT \n");
++ *i = tv_param.v2.input->type;
++ return 0;
++ }
++
++ case VIDIOC_ENUMOUTPUT:
++ {
++ struct v4l2_output *i = arg;
++ printk("TV-OUT: VIDIOC_ENUMOUTPUT : index = %d\n", i->index);
++
++ if ((i->index) >= NUMBER_OF_OUTPUTS) {
++ return -EINVAL;
++ }
++ memcpy(i, &tvenc_outputs[i->index], sizeof(struct v4l2_output));
++ return 0;
++ }
++
++ case VIDIOC_S_OUTPUT: // 0 -> TV / FIFO , 1 -> MSDMA
++ {
++ int index = *((int *)arg);
++ printk("TV-OUT: VIDIOC_S_OUTPUT \n");
++
++ if (index >= NUMBER_OF_OUTPUTS) {
++ return -EINVAL;
++ }
++ else {
++ s3c_tvenc_s_output(index);
++ return 0;
++ }
++ }
++
++ case VIDIOC_G_OUTPUT:
++ {
++ u32 *i = arg;
++ printk("VIDIOC_G_OUTPUT \n");
++ *i = tv_param.v2.output->type;
++ return 0;
++ }
++
++ case VIDIOC_ENUM_FMT:
++ { struct v4l2_fmtdesc *f = arg;
++ enum v4l2_buf_type type = f->type;
++ int index = f->index;
++
++ printk("C: VIDIOC_ENUM_FMT : index = %d\n", index);
++ if (index >= NUMBER_OF_INPUT_FORMATS)
++ return -EINVAL;
++
++ switch (type) {
++ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
++ break;
++ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
++ default:
++ return -EINVAL;
++ }
++ memset(f, 0, sizeof(*f));
++ memcpy(f, tv_param.v2.fmtdesc+index, sizeof(*f));
++ return 0;
++ }
++
++ case VIDIOC_G_FMT:
++ {
++ struct v4l2_format *f = arg;
++ printk("C: VIDIOC_G_FMT \n");
++ ret = s3c_tvenc_g_fmt(f);
++ return ret;
++ }
++
++ case VIDIOC_S_FMT:
++ {
++ struct v4l2_format *f = arg;
++ printk("C: VIDIOC_S_FMT \n");
++ ret = s3c_tvenc_s_fmt(f);
++ if(ret != 0) {
++ printk("s3c_tvenc_set_fmt() failed !\n");
++ return -EINVAL;
++ }
++ return ret;
++ }
++
++ case VIDIOC_S_CTRL:
++ {
++ struct v4l2_control *ctrl = arg;
++ //printk("P: VIDIOC_S_CTRL \n");
++ ret = s3c_tvenc_v4l2_control(ctrl);
++ return ret;
++ }
++
++ case VIDIOC_ENUMSTD:
++ {
++ struct v4l2_standard *e = arg;
++ unsigned int index = e->index;
++
++ if (index >= NUMBER_OF_STANDARDS)
++ return -EINVAL;
++ v4l2_video_std_construct(e, tvout_standards[e->index].id,
++ &tvout_standards[e->index].name);
++ e->index = index;
++ return 0;
++ }
++
++ case VIDIOC_G_STD:
++ {
++ v4l2_std_id *id = arg;
++ *id = tvout_standards[0].id;
++ return 0;
++ }
++
++ case VIDIOC_S_STD:
++ {
++ v4l2_std_id *id = arg;
++ unsigned int i;
++
++ for (i = 0; i < NUMBER_OF_STANDARDS; i++) {
++ //printk("P: *id = %d, tvout_standards[i].id = %d\n", *id, tvout_standards[i].id);
++ if (*id & tvout_standards[i].id)
++ break;
++ }
++ if (i == NUMBER_OF_STANDARDS)
++ return -EINVAL;
++
++ ret = s3c_tvenc_s_std(id);
++ return ret;
++ }
++
++ case VIDIOC_S_TVOUT_ON:
++ {
++ //int *SrcFrmSt = arg;
++ //printk("---peter VIDIOC_S_TVOUT_ON : SrcFrmSt = 0x%08x\n", *SrcFrmSt);
++ ret = tvout_start();
++ return ret;
++ }
++
++ case VIDIOC_S_TVOUT_OFF:
++ {
++ ret = tvout_stop();
++ return ret;
++ }
++
++ case VIDIOC_S_SCALER_TEST:
++ {
++ ret = scaler_test_start();
++ mdelay(1);
++ ret = scaler_test_stop();
++ return ret;
++ }
++
++ default:
++ return -EINVAL;
++ }
++ return 0;
++}
++
++static int s3c_tvenc_ioctl_v4l2(struct inode *inode, struct file *filp, unsigned int cmd,
++ unsigned long arg)
++{
++ return video_usercopy(inode, filp, cmd, arg, s3c_tvenc_do_ioctl);
++}
++
++int s3c_tvenc_read(struct file *filp, char *buf, size_t count,
++ loff_t *f_pos)
++{
++ return 0;
++}
++
++int s3c_tvenc_write(struct file *filp, const char *buf, size_t
++ count, loff_t *f_pos)
++{
++ return 0;
++}
++
++int s3c_tvenc_mmap(struct file *filp, struct vm_area_struct *vma)
++{
++ u32 size = vma->vm_end - vma->vm_start;
++ u32 max_size;
++ u32 page_frame_no;
++
++ page_frame_no = __phys_to_pfn(POST_BUFF_BASE_ADDR);
++
++ max_size = RESERVE_POST_MEM + PAGE_SIZE - (RESERVE_POST_MEM % PAGE_SIZE);
++
++ if(size > max_size) {
++ return -EINVAL;
++ }
++
++ vma->vm_flags |= VM_RESERVED;
++
++ if( remap_pfn_range(vma, vma->vm_start, page_frame_no,
++ size, vma->vm_page_prot)) {
++ printk(KERN_ERR "%s: mmap_error\n", __FUNCTION__);
++ return -EAGAIN;
++
++ }
++
++ return 0;
++}
++
++struct file_operations s3c_tvenc_fops = {
++ .owner = THIS_MODULE,
++ .open = s3c_tvenc_open,
++ .ioctl = s3c_tvenc_ioctl_v4l2,
++ .release = s3c_tvenc_release,
++ .read = s3c_tvenc_read,
++ .write = s3c_tvenc_write,
++ .mmap = s3c_tvenc_mmap,
++};
++
++void s3c_tvenc_vdev_release (struct video_device *vdev) {
++ kfree(vdev);
++}
++
++struct video_device tvencoder = {
++ .name = "TVENCODER",
++ .type = VID_TYPE_OVERLAY | VID_TYPE_CAPTURE | VID_TYPE_SCALES,
++ .type2 = V4L2_CAP_VIDEO_OUTPUT| V4L2_CAP_VIDEO_CAPTURE, /* V4L2 */
++ //.hardware = 0x01, // peter for 2.6.24 kernel
++ .fops = &s3c_tvenc_fops,
++ .release = s3c_tvenc_vdev_release,
++ .minor = TVENC_MINOR,
++};
++
++irqreturn_t s3c_tvenc_isr(int irq, void *dev_id,
++ struct pt_regs *regs)
++{
++ u32 mode;
++
++ mode = __raw_readl(base + S3C_TVCTRL);
++
++ // Clear FIFO under-run status pending bit
++ mode |= (1<<12);
++
++ __raw_writel(mode, base + S3C_TVCTRL);
++
++ wake_up_interruptible(&waitq);
++ return IRQ_HANDLED;
++}
++
++static int s3c_tvenc_probe(struct platform_device *pdev)
++{
++
++ struct resource *res;
++
++ int ret;
++
++ /* find the IRQs */
++ s3c_tvenc_irq = platform_get_irq(pdev, 0);
++ if(s3c_tvenc_irq <= 0) {
++ printk(KERN_ERR PFX "failed to get irq resouce\n");
++ return -ENOENT;
++ }
++
++ /* get the memory region for the tv scaler driver */
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if(res == NULL) {
++ printk(KERN_ERR PFX "failed to get memory region resouce\n");
++ return -ENOENT;
++ }
++
++ s3c_tvenc_mem = request_mem_region(res->start, res->end-res->start+1, pdev->name);
++ if(s3c_tvenc_mem == NULL) {
++ printk(KERN_ERR PFX "failed to reserve memory region\n");
++ return -ENOENT;
++ }
++
++
++ base = ioremap(s3c_tvenc_mem->start, s3c_tvenc_mem->end - res->start + 1);
++ if(s3c_tvenc_mem == NULL) {
++ printk(KERN_ERR PFX "failed ioremap\n");
++ return -ENOENT;
++ }
++
++ tvenc_clock = clk_get(&pdev->dev, "tv_encoder");
++ if(tvenc_clock == NULL) {
++ printk(KERN_ERR PFX "failed to find tvenc clock source\n");
++ return -ENOENT;
++ }
++
++ clk_enable(tvenc_clock);
++
++ h_clk = clk_get(&pdev->dev, "hclk");
++ if(h_clk == NULL) {
++ printk(KERN_ERR PFX "failed to find h_clk clock source\n");
++ return -ENOENT;
++ }
++
++ init_waitqueue_head(&waitq);
++
++ tv_param.v = video_device_alloc();
++ if(!tv_param.v) {
++ printk(KERN_ERR "s3c-tvenc: video_device_alloc() failed\n");
++ return -ENOMEM;
++ }
++ memcpy(tv_param.v, &tvencoder, sizeof(tvencoder));
++ if(video_register_device(tv_param.v, VFL_TYPE_GRABBER, TVENC_MINOR) != 0) {
++ printk("s3c_camera_driver.c : Couldn't register this codec driver.\n");
++ return 0;
++ }
++
++ ret = request_irq(s3c_tvenc_irq, s3c_tvenc_isr, SA_INTERRUPT,
++ "TV_ENCODER", NULL);
++ if (ret) {
++ printk("request_irq(TV_ENCODER) failed.\n");
++ return ret;
++ }
++
++ printk(" Success\n");
++ return 0;
++}
++
++static int s3c_tvenc_remove(struct platform_device *dev)
++{
++ printk(KERN_INFO "s3c_tvenc_remove called !\n");
++ clk_disable(tvenc_clock);
++ free_irq(s3c_tvenc_irq, NULL);
++ if (s3c_tvenc_mem != NULL) {
++ pr_debug("s3-tvenc: releasing s3c_tvenc_mem\n");
++ iounmap(base);
++ release_resource(s3c_tvenc_mem);
++ kfree(s3c_tvenc_mem);
++ }
++// video_unregister_device(tv_param.v);
++ return 0;
++}
++
++static int s3c_tvenc_suspend(struct platform_device *dev, pm_message_t state)
++{
++ clk_disable(tvenc_clock);
++ return 0;
++}
++
++static int s3c_tvenc_resume(struct platform_device *pdev)
++{
++ clk_enable(tvenc_clock);
++ return 0;
++}
++
++static struct platform_driver s3c_tvenc_driver = {
++ .probe = s3c_tvenc_probe,
++ .remove = s3c_tvenc_remove,
++ .suspend = s3c_tvenc_suspend,
++ .resume = s3c_tvenc_resume,
++ .driver = {
++ .owner = THIS_MODULE,
++ .name = "s3c-tvenc",
++ },
++};
++
++static char banner[] __initdata = KERN_INFO "S3C6410 TV encoder Driver, (c) 2008 Samsung Electronics\n";
++
++static int __init s3c_tvenc_init(void)
++{
++
++ printk(banner);
++
++ if(platform_driver_register(&s3c_tvenc_driver) != 0)
++ {
++ printk("Platform Device Register Failed \n");
++ return -1;
++ }
++
++ printk(" S3C6410 TV encoder Driver module init OK. \n");
++ return 0;
++}
++
++static void __exit s3c_tvenc_exit(void)
++{
++
++ video_unregister_device(tv_param.v);
++ platform_driver_unregister(&s3c_tvenc_driver);
++
++ printk("S3C6410 TV encoder Driver module exit. \n");
++}
++
++
++module_init(s3c_tvenc_init);
++module_exit(s3c_tvenc_exit);
++
++
++MODULE_AUTHOR("Peter, Oh");
++MODULE_DESCRIPTION("S3C TV Encoder Device Driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/media/video/samsung/s3c-tvenc.h b/drivers/media/video/samsung/s3c-tvenc.h
+new file mode 100644
+index 0000000..30a66a2
+--- /dev/null
++++ b/drivers/media/video/samsung/s3c-tvenc.h
+@@ -0,0 +1,165 @@
++#ifndef __S3CTVENC_H_
++#define __S3CTVENC_H_
++
++#include "s3c-tvscaler.h"
++
++
++#define TVENC_IOCTL_MAGIC 'T'
++
++typedef struct {
++
++} s3c_tvenc_info;
++
++#define TV_ON _IO(TVENC_IOCTL_MAGIC, 0)
++#define TV_OFF _IO(TVENC_IOCTL_MAGIC, 1)
++#define SELECT_TV_OUT_FORMAT _IO(TVENC_IOCTL_MAGIC, 2)
++
++#define TVENC_IOCTL_MAXNR 6
++
++#define TVENC_MINOR 14 // Just some number
++
++typedef enum {
++ OFF,
++ ON
++} tv_enc_switch_t;
++
++typedef enum {
++ NTSC_M,
++ PAL_M,
++ PAL_BGHID,
++ PAL_N,
++ PAL_NC,
++ PAL_60,
++ NTSC_443,
++ NTSC_J
++} tv_standard_t;
++
++typedef enum {
++ QCIF, CIF/*352x288*/,
++ QQVGA, QVGA, VGA, SVGA/*800x600*/, SXGA/*1280x1024*/, UXGA/*1600x1200*/, QXGA/*2048x1536*/,
++ WVGA/*854x480*/, HD720/*1280x720*/, HD1080/*1920x1080*/
++} img_size_t;
++
++typedef enum {
++ BLACKSTRETCH, WHITESTRETCH, BLUESTRETCH
++} stretch_color_t;
++
++typedef enum {
++ COMPOSITE, S_VIDEO
++} tv_conn_type_t;
++
++typedef enum {
++ BLACK, BLUE, RED, MAGENTA, GREEN, CYAN, YELLOW, WHITE
++} bg_color_t;
++
++typedef enum {
++ MUTE_Y, MUTE_CB, MUTE_CR
++} mute_type_t;
++
++typedef enum {
++ AGC4L, AGC2L, N01, N02, P01, P02
++} macro_pattern_t;
++
++typedef enum {
++ LCD_RGB, LCD_TV, LCD_I80F, LCD_I80S,
++ LCD_TVRGB, LCD_TVI80F, LCD_TVI80S
++} lcd_local_output_t;
++
++/* when App want to change v4l2 parameter,
++ * we instantly store it into v4l2_t v2
++ * and then reflect it to hardware
++ */
++typedef struct v4l2 {
++ struct v4l2_fmtdesc *fmtdesc;
++// struct v4l2_framebuffer frmbuf; /* current frame buffer */
++ struct v4l2_pix_format pixfmt;
++ struct v4l2_input *input;
++ struct v4l2_output *output;
++// enum v4l2_status status;
++} v4l2_t;
++
++
++typedef struct {
++ tv_standard_t sig_type;
++ tv_conn_type_t connect;
++ /* Width of input image. The input value is twice original output image
++ * width. For example, you must set 1440 when the image width is 720.
++ * Max value is 1440
++ */
++ unsigned int in_width;
++ /* Height of input image
++ * Max value is 576
++ */
++ unsigned int in_height;
++
++ // Setting value of VIDOUT[28:26] in Display
++ // controller(VIDCON0)
++ lcd_local_output_t lcd_output_mode;
++ // Set CLKVAL_F[13:6] of VIDCON0 with
++ // this value
++ unsigned int lcd_clkval_f;
++
++ // Flag of lcd rgb port
++ // 0 : disable, 1 : enable
++ unsigned int lcd_rgb_port_flag;
++
++ scaler_params_t sp;
++
++ struct video_device *v;
++ v4l2_t v2;
++
++} tv_out_params_t;
++
++#define V4L2_INPUT_TYPE_MSDMA 3
++#define V4L2_INPUT_TYPE_FIFO 4
++#define V4L2_OUTPUT_TYPE_MSDMA 4
++
++#define FORMAT_FLAGS_DITHER 0x01
++#define FORMAT_FLAGS_PACKED 0x02
++#define FORMAT_FLAGS_PLANAR 0x04
++#define FORMAT_FLAGS_RAW 0x08
++#define FORMAT_FLAGS_CrCb 0x10
++
++/****************************************************************
++* struct v4l2_control
++* Control IDs defined by S3C
++*****************************************************************/
++
++/* TV-OUT connector type */
++#define V4L2_CID_CONNECT_TYPE (V4L2_CID_PRIVATE_BASE+0)
++
++/****************************************************************
++* I O C T L C O D E S F O R V I D E O D E V I C E S
++* It's only for S3C
++*****************************************************************/
++#define VIDIOC_S_TVOUT_ON _IO ('V', BASE_VIDIOC_PRIVATE+0)
++#define VIDIOC_S_TVOUT_OFF _IO ('V', BASE_VIDIOC_PRIVATE+1)
++#define VIDIOC_S_SCALER_TEST _IO ('V', BASE_VIDIOC_PRIVATE+3)
++
++
++extern void s3c_tvscaler_config(scaler_params_t * sp);
++extern void s3c_tvscaler_int_enable(unsigned int int_type);
++extern void s3c_tvscaler_int_disable(void);
++extern void s3c_tvscaler_start(void);
++extern void s3c_tvscaler_stop_freerun(void);
++extern void s3c_tvscaler_init(void);
++extern void s3c_tvscaler_set_interlace(unsigned int on_off);
++extern int video_exclusive_release(struct inode * inode, struct file * file);
++extern int video_exclusive_open(struct inode * inode, struct file * file);
++
++#if 0 // peter for 2.6.21 kernel
++extern void s3c_fb_start_lcd(void);
++extern void s3c_fb_stop_lcd(void);
++extern void s3c_fb_set_output_path(int out);
++extern void s3c_fb_set_clkval(unsigned int clkval);
++extern void s3c_fb_enable_rgbport(unsigned int on_off);
++#else // peter for 2.6.24 kernel
++extern void s3cfb_start_lcd(void);
++extern void s3cfb_stop_lcd(void);
++extern void s3cfb_set_output_path(int out);
++extern void s3cfb_set_clock(unsigned int clkval);
++extern void s3cfb_enable_rgbport(unsigned int on_off);
++#endif
++
++
++#endif // __S3CTVENC_H_
+diff --git a/drivers/media/video/samsung/s3c-tvscaler.c b/drivers/media/video/samsung/s3c-tvscaler.c
+new file mode 100644
+index 0000000..376c866
+--- /dev/null
++++ b/drivers/media/video/samsung/s3c-tvscaler.c
+@@ -0,0 +1,802 @@
++
++/*
++ * linux/drivers/tvenc/s3c-tvscaler.c
++ *
++ * Revision 1.0
++ *
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file COPYING in the main directory of this archive for
++ * more details.
++ *
++ * S3C TV Scaler driver
++ *
++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/types.h>
++#include <linux/timer.h>
++#include <linux/kernel.h>
++#include <linux/fs.h>
++#include <linux/platform_device.h>
++#include <linux/interrupt.h>
++#include <linux/clk.h>
++#include <linux/delay.h>
++#include <asm/uaccess.h>
++#include <linux/errno.h> /* error codes */
++#include <asm/div64.h>
++#include <linux/mm.h>
++#include <linux/tty.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/hardware.h>
++#include <asm/uaccess.h>
++#include <asm/arch/map.h>
++#include <linux/miscdevice.h>
++
++#include <linux/version.h>
++#if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,16)
++#include <linux/config.h>
++#include <asm/arch/registers.h>
++#else
++#include <asm/arch/regs-tvscaler.h>
++#include <asm/arch/regs-s3c6400-clock.h>
++#endif
++
++#include "s3c-tvscaler.h"
++
++#define PFX "s3c_tv_scaler"
++
++#define SINGLE_BUF 1 // Single buffer mode
++
++
++static struct clk *h_clk;
++static struct clk *tvscaler_clock;
++static void __iomem *base;
++static int s3c_tvscaler_irq = NO_IRQ;
++static struct resource *s3c_tvscaler_mem;
++
++
++//static unsigned char *addr_start_y;
++//static unsigned char *addr_start_rgb;
++
++static wait_queue_head_t waitq;
++
++irqreturn_t s3c_tvscaler_isr(int irq, void *dev_id,
++ struct pt_regs *regs)
++{
++ u32 mode;
++ mode = __raw_readl(base + S3C_MODE);
++ mode &= ~(1 << 6); /* Clear Source in POST Processor */
++ __raw_writel(mode, base + S3C_MODE);
++
++// wake_up_interruptible(&waitq);
++ return IRQ_HANDLED;
++}
++
++#if 0
++static buff_addr_t buf_addr = { NULL };
++
++
++static u32 post_alloc_pre_buff(scaler_params_t *sp)
++{
++ u32 size;
++
++#ifdef USE_DEDICATED_MEM
++
++ buf_addr.pre_phy_addr = PHYS_OFFSET + (SYSTEM_RAM - RESERVE_POST_MEM);
++ buf_addr.pre_virt_addr = ioremap_nocache(buf_addr.pre_phy_addr, PRE_BUFF_SIZE);
++ if( !buf_addr.pre_virt_addr ) {
++ printk(KERN_ERR "%s: Failed to allocate pre buffer \n",__FUNCTION__);
++ return -ENOMEM;
++ }
++
++ sp->SrcFrmSt = buf_addr.pre_phy_addr;
++#else
++ size = sp->SrcWidth * sp->SrcHeight * 2;
++ addr_start_y = kmalloc(size, GFP_DMA);
++ if(addr_start_y != NULL) return -ENOMEM;
++#endif
++ return 0;
++}
++
++static u32 post_alloc_post_buff(scaler_params_t *sp)
++{
++ u32 size;
++
++#ifdef USE_DEDICATED_MEM
++
++ buf_addr.post_phy_addr = PHYS_OFFSET + (SYSTEM_RAM - RESERVE_POST_MEM + PRE_BUFF_SIZE);
++ buf_addr.post_virt_addr = ioremap_nocache(buf_addr.post_phy_addr, POST_BUFF_SIZE);
++ if( !buf_addr.post_virt_addr ) {
++ printk(KERN_ERR "%s: Failed to allocate post buffer \n",__FUNCTION__);
++ return -ENOMEM;
++ }
++
++ sp->DstFrmSt = buf_addr.post_phy_addr;
++#else
++ size = sp->DstWidth * sp->DstHeight * 2;
++ addr_start_rgb = kmalloc(size, GFP_DMA);
++ if(addr_start_rgb != NULL) return -ENOMEM;
++#endif
++ return 0;
++}
++
++static u32 post_free_all_buffer(void)
++{
++#ifdef USE_DEDICATED_MEM
++ if( buf_addr.pre_virt_addr ) {
++ iounmap(buf_addr.pre_virt_addr);
++ }
++ if( buf_addr.post_virt_addr ) {
++ iounmap(buf_addr.post_virt_addr);
++ }
++#endif
++ return 0;
++}
++#endif
++
++static void s3c_tvscaler_set_clk_src(scaler_clk_src_t clk_src)
++{
++ u32 tmp, rate;
++
++ tmp = __raw_readl(base + S3C_MODE);
++
++ h_clk = clk_get(NULL, "hclk");
++
++ rate = clk_get_rate(h_clk);
++
++ if(clk_src == HCLK) {
++ if(rate > 66000000) {
++ tmp &= ~(0x7f<<23);
++ tmp |= (1<<24);
++ tmp |= (1<<23);
++ } else {
++ tmp &=~ (0x7f<<23);
++ }
++
++ } else if(clk_src == PLL_EXT) {
++ } else {
++ tmp &=~(0x7f<<23);
++ }
++
++ tmp = (tmp &~ (0x3<<21)) | (clk_src<<21);
++
++ __raw_writel(tmp, base + S3C_MODE);
++}
++
++static void s3c_tvscaler_set_fmt(cspace_t src, cspace_t dst, s3c_scaler_path_t in,
++ s3c_scaler_path_t out, u32 *in_pixel_size,
++ u32 *out_pixel_size)
++{
++ u32 tmp;
++
++ tmp = __raw_readl(base + S3C_MODE);
++ tmp |= (0x1<<16);
++ tmp |= (0x2<<10);
++
++ if(in == POST_DMA) {
++
++ switch(src) {
++ case YC420:
++ tmp &=~((0x1<<3)|(0x1<<2));
++ tmp |= (0x1<<8)|(0x1<<1);
++ *in_pixel_size = 1;
++ break;
++ case CRYCBY:
++ tmp &= ~((0x1<<15)|(0x1<<8)|(0x1<<3)|(0x1<<0));
++ tmp |= (0x1<<2)|(0x1<<1);
++ *in_pixel_size = 2;
++ break;
++ case CBYCRY:
++ tmp &= ~((0x1<<8)|(0x1<<3)|(0x1<<0));
++ tmp |= (0x1<<15)|(0x1<<2)|(0x1<<1);
++ *in_pixel_size = 2;
++ break;
++ case YCRYCB:
++ tmp &= ~((0x1<<15)|(0x1<<8)|(0x1<<3));
++ tmp |= (0x1<<2)|(0x1<<1)|(0x1<<0);
++ *in_pixel_size = 2;
++ break;
++ case YCBYCR:
++ tmp &= ~((0x1<<8)|(0x1<<3));
++ tmp |= (0x1<<15)|(0x1<<2)|(0x1<<1)|(0x1<<0);
++ *in_pixel_size = 2;
++ break;
++ case RGB24:
++ tmp &= ~(0x1<<8);
++ tmp |= (0x1<<3)|(0x1<<2)|(0x1<<1);
++ *in_pixel_size = 4;
++ break;
++ case RGB16:
++ tmp &= ~((0x1<<8)|(0x1<<1));
++ tmp |= (0x1<<3)|(0x1<<2);
++ *in_pixel_size = 2;
++ break;
++ default:
++ break;
++ }
++
++ }
++ else if(in == POST_FIFO) {
++ }
++
++ if(out == POST_DMA) {
++ switch(dst) {
++ case YC420:
++ tmp &= ~(0x1<<18);
++ tmp |= (0x1<<17);
++ *out_pixel_size = 1;
++ break;
++ case CRYCBY:
++ tmp &= ~((0x1<<20)|(0x1<<19)|(0x1<<18)|(0x1<<17));
++ *out_pixel_size = 2;
++ break;
++ case CBYCRY:
++ tmp &= ~((0x1<<19)|(0x1<<18)|(0x1<<17));
++ tmp |= (0x1<<20);
++ *out_pixel_size = 2;
++ break;
++ case YCRYCB:
++ tmp &= ~((0x1<<20)|(0x1<<18)|(0x1<<17));
++ tmp |= (0x1<<19);
++ *out_pixel_size = 2;
++ break;
++ case YCBYCR:
++ tmp &= ~((0x1<<18)|(0x1<<17));
++ tmp |= (0x1<<20)|(0x1<<19);
++ *out_pixel_size = 2;
++ break;
++ case RGB24:
++ tmp |= (0x1<<18)|(0x1<<4);
++ *out_pixel_size = 4;
++ break;
++ case RGB16:
++ tmp &= ~(0x1<<4);
++ tmp |= (0x1<<18);
++ *out_pixel_size = 2;
++ break;
++ default:
++ break;
++ }
++ }
++ else if(out == POST_FIFO) {
++ if(dst == RGB24) {
++ tmp |= (0x1<<18)|(0x1<<13);
++
++ } else if(dst == YCBYCR) {
++ tmp |= (0x1<<13);
++ tmp &= ~(0x1<<18)|(0x1<<17);
++ } else {
++ }
++ }
++
++ __raw_writel(tmp, base + S3C_MODE);
++}
++
++static void s3c_tvscaler_set_path(s3c_scaler_path_t in, s3c_scaler_path_t out)
++{
++ u32 tmp;
++
++ tmp = __raw_readl(base + S3C_MODE);
++
++ tmp &=~(0x1<<12); // 0: progressive mode, 1: interlace mode
++
++ if(in == POST_FIFO) {
++ tmp |= (0x1<<31);
++ } else if(in == POST_DMA) {
++ tmp &=~(0x1<<31);
++ }
++
++ if(out == POST_FIFO) {
++ tmp |= (0x1<<13);
++ } else if(out == POST_DMA) {
++ tmp &=~(0x1<<13);
++ }
++
++ __raw_writel(tmp, base + S3C_MODE);
++}
++
++static void s3c_tvscaler_set_addr(scaler_params_t *sp, u32 in_pixel_size, u32 out_pixel_size)
++{
++ u32 offset_y, offset_cb, offset_cr;
++ u32 src_start_y, src_start_cb, src_start_cr;
++ u32 src_end_y, src_end_cb, src_end_cr;
++ u32 start_pos_y, end_pos_y;
++ u32 start_pos_cb, end_pos_cb;
++ u32 start_pos_cr, end_pos_cr;
++ u32 start_pos_rgb, end_pos_rgb;
++ u32 dst_start_rgb, dst_end_rgb;
++ u32 src_frm_start_addr;
++
++ u32 offset_rgb, out_offset_cb, out_offset_cr;
++ u32 out_start_pos_cb, out_start_pos_cr;
++ u32 out_end_pos_cb, out_end_pos_cr;
++ u32 out_src_start_cb, out_src_start_cr;
++ u32 out_src_end_cb, out_src_end_cr;
++
++ if(sp->InPath == POST_DMA) {
++ offset_y = (sp->SrcFullWidth - sp->SrcWidth) * in_pixel_size;
++ start_pos_y = (sp->SrcFullWidth*sp->SrcStartY+sp->SrcStartX)*in_pixel_size;
++ end_pos_y = sp->SrcWidth*sp->SrcHeight*in_pixel_size + offset_y*(sp->SrcHeight-1);
++ src_frm_start_addr = sp->SrcFrmSt;
++ src_start_y = sp->SrcFrmSt + start_pos_y;
++ src_end_y = src_start_y + end_pos_y;
++
++ __raw_writel(src_start_y, base + S3C_ADDRSTART_Y);
++ __raw_writel(offset_y, base + S3C_OFFSET_Y);
++ __raw_writel(src_end_y, base + S3C_ADDREND_Y);
++
++ if(sp->SrcCSpace == YC420) {
++ offset_cb = offset_cr = ((sp->SrcFullWidth - sp->SrcWidth) / 2) * in_pixel_size;
++ start_pos_cb = sp->SrcFullWidth * sp->SrcFullHeight * 1 \
++ + (sp->SrcFullWidth * sp->SrcStartY / 2 + sp->SrcStartX) /2 * 1;
++
++ end_pos_cb = sp->SrcWidth/2*sp->SrcHeight/2*in_pixel_size \
++ + (sp->SrcHeight/2 -1)*offset_cb;
++ start_pos_cr = sp->SrcFullWidth * sp->SrcFullHeight *1 \
++ + sp->SrcFullWidth*sp->SrcFullHeight/4 *1 \
++ + (sp->SrcFullWidth*sp->SrcStartY/2 + sp->SrcStartX)/2*1;
++ end_pos_cr = sp->SrcWidth/2*sp->SrcHeight/2*in_pixel_size \
++ + (sp->SrcHeight/2-1)*offset_cr;
++
++ src_start_cb = sp->SrcFrmSt + start_pos_cb;
++ src_end_cb = src_start_cb + end_pos_cb;
++
++ src_start_cr = sp->SrcFrmSt + start_pos_cr;
++ src_end_cr = src_start_cr + end_pos_cr;
++
++ __raw_writel(src_start_cb, base + S3C_ADDRSTART_CB);
++ __raw_writel(offset_cr, base + S3C_OFFSET_CB);
++ __raw_writel(src_end_cb, base + S3C_ADDREND_CB);
++ __raw_writel(src_start_cr, base + S3C_ADDRSTART_CR);
++ __raw_writel(offset_cb, base + S3C_OFFSET_CR);
++ __raw_writel(src_end_cr, base + S3C_ADDREND_CR);
++ }
++ }
++ if(sp->OutPath == POST_DMA) {
++ offset_rgb = (sp->DstFullWidth - sp->DstWidth)*out_pixel_size;
++ start_pos_rgb = (sp->DstFullWidth*sp->DstStartY + sp->DstStartX)*out_pixel_size;
++ end_pos_rgb = sp->DstWidth*sp->DstHeight*out_pixel_size + offset_rgb*(sp->DstHeight - 1);
++ dst_start_rgb = sp->DstFrmSt + start_pos_rgb;
++ dst_end_rgb = dst_start_rgb + end_pos_rgb;
++
++ __raw_writel(dst_start_rgb, base + S3C_ADDRSTART_RGB);
++ __raw_writel(offset_rgb, base + S3C_OFFSET_RGB);
++ __raw_writel(dst_end_rgb, base + S3C_ADDREND_RGB);
++
++ if(sp->DstCSpace == YC420) {
++ out_offset_cb = out_offset_cr = ((sp->DstFullWidth - sp->DstWidth)/2)*out_pixel_size;
++ out_start_pos_cb = sp->DstFullWidth*sp->DstFullHeight*1 \
++ + (sp->DstFullWidth*sp->DstStartY/2 + sp->DstStartX)/2*1;
++ out_end_pos_cb = sp->DstWidth/2*sp->DstHeight/2*out_pixel_size \
++ + (sp->DstHeight/2 -1)*out_offset_cr;
++
++ out_start_pos_cr = sp->DstFullWidth*sp->DstFullHeight*1 \
++ + (sp->DstFullWidth*sp->DstFullHeight/4)*1 \
++ + (sp->DstFullWidth*sp->DstStartY/2 +sp->DstStartX)/2*1;
++ out_end_pos_cr = sp->DstWidth/2*sp->DstHeight/2*out_pixel_size \
++ + (sp->DstHeight/2 -1)*out_offset_cb;
++
++ out_src_start_cb = sp->DstFrmSt + out_start_pos_cb;
++ out_src_end_cb = out_src_start_cb + out_end_pos_cb;
++ out_src_start_cr = sp->DstFrmSt + out_start_pos_cr;
++ out_src_end_cr = out_src_start_cr + out_end_pos_cr;
++
++ __raw_writel(out_src_start_cb, base + S3C_ADDRSTART_OCB);
++ __raw_writel(out_offset_cb, base + S3C_OFFSET_OCB);
++ __raw_writel(out_src_end_cb, base + S3C_ADDREND_OCB);
++ __raw_writel(out_src_start_cr, base + S3C_ADDRSTART_OCR);
++ __raw_writel(out_offset_cr, base + S3C_OFFSET_OCR);
++ __raw_writel(out_src_end_cr, base + S3C_ADDREND_OCR);
++
++ }
++ }
++
++
++}
++
++#if 0
++static void s3c_tvscaler_set_fifo_in(s3c_scaler_path_t in_path)
++{
++ u32 tmp;
++
++ tmp = __raw_readl(base + S3C_MODE);
++
++ if(in_path == POST_FIFO) tmp |= (0x1<<31);
++ else tmp &=~(0x1<<31);
++
++ __raw_writel(tmp, base + S3C_MODE);
++
++}
++#endif
++
++void s3c_tvscaler_set_interlace(u32 on_off)
++{
++ u32 tmp;
++
++ tmp = __raw_readl(base + S3C_MODE);
++
++ if(on_off == 1) tmp |=(1<<12);
++ else tmp &=~(1<<12);
++
++ __raw_writel(tmp, base + S3C_MODE);
++}
++EXPORT_SYMBOL(s3c_tvscaler_set_interlace);
++
++static void s3c_tvscaler_set_size(scaler_params_t *sp)
++{
++ u32 pre_h_ratio, pre_v_ratio, h_shift, v_shift, sh_factor;
++ u32 pre_dst_width, pre_dst_height, dx, dy;
++
++ if (sp->SrcWidth >= (sp->DstWidth<<6)) {
++ printk("Out of PreScalar range !!!\n");
++ return;
++ }
++ if(sp->SrcWidth >= (sp->DstWidth<<5)) {
++ pre_h_ratio = 32;
++ h_shift = 5;
++ } else if(sp->SrcWidth >= (sp->DstWidth<<4)) {
++ pre_h_ratio = 16;
++ h_shift = 4;
++ } else if(sp->SrcWidth >= (sp->DstWidth<<3)) {
++ pre_h_ratio = 8;
++ h_shift = 3;
++ } else if(sp->SrcWidth >= (sp->DstWidth<<2)) {
++ pre_h_ratio = 4;
++ h_shift = 2;
++ } else if(sp->SrcWidth >= (sp->DstWidth<<1)) {
++ pre_h_ratio = 2;
++ h_shift = 1;
++ } else {
++ pre_h_ratio = 1;
++ h_shift = 0;
++ }
++
++ pre_dst_width = sp->SrcWidth / pre_h_ratio;
++ dx = (sp->SrcWidth<<8) / (sp->DstWidth<<h_shift);
++
++
++ if (sp->SrcHeight >= (sp->DstHeight<<6)) {
++ printk("Out of PreScalar range !!!\n");
++ return;
++ }
++ if(sp->SrcHeight>= (sp->DstHeight<<5)) {
++ pre_v_ratio = 32;
++ v_shift = 5;
++ } else if(sp->SrcHeight >= (sp->DstHeight<<4)) {
++ pre_v_ratio = 16;
++ v_shift = 4;
++ } else if(sp->SrcHeight >= (sp->DstHeight<<3)) {
++ pre_v_ratio = 8;
++ v_shift = 3;
++ } else if(sp->SrcHeight >= (sp->DstHeight<<2)) {
++ pre_v_ratio = 4;
++ v_shift = 2;
++ } else if(sp->SrcHeight >= (sp->DstHeight<<1)) {
++ pre_v_ratio = 2;
++ v_shift = 1;
++ } else {
++ pre_v_ratio = 1;
++ v_shift = 0;
++ }
++
++ pre_dst_height = sp->SrcHeight / pre_v_ratio;
++ dy = (sp->SrcHeight<<8) / (sp->DstHeight<<v_shift);
++ sh_factor = 10 - (h_shift + v_shift);
++
++ __raw_writel((pre_v_ratio<<7)|(pre_h_ratio<<0), base + S3C_PRESCALE_RATIO);
++ __raw_writel((pre_dst_height<<12)|(pre_dst_width<<0), base + S3C_PRESCALEIMGSIZE);
++ __raw_writel(sh_factor, base + S3C_PRESCALE_SHFACTOR);
++ __raw_writel(dx, base + S3C_MAINSCALE_H_RATIO);
++ __raw_writel(dy, base + S3C_MAINSCALE_V_RATIO);
++ __raw_writel((sp->SrcHeight<<12)|(sp->SrcWidth), base + S3C_SRCIMGSIZE);
++ __raw_writel((sp->DstHeight<<12)|(sp->DstWidth), base + S3C_DSTIMGSIZE);
++
++}
++
++
++static void s3c_tvscaler_set_auto_load(scaler_params_t *sp)
++{
++ u32 tmp;
++
++ tmp = __raw_readl(base + S3C_MODE);
++
++ if(sp->Mode == FREE_RUN) {
++ tmp |= (1<<14);
++ } else if(sp->Mode == ONE_SHOT) {
++ tmp &=~(1<<14);
++ }
++
++ __raw_writel(tmp, base + S3C_MODE);
++
++}
++
++void s3c_tvscaler_set_base_addr(void __iomem * base_addr)
++{
++ base = base_addr;
++}
++EXPORT_SYMBOL(s3c_tvscaler_set_base_addr);
++
++void s3c_tvscaler_free_base_addr(void)
++{
++ base = NULL;
++}
++EXPORT_SYMBOL(s3c_tvscaler_free_base_addr);
++
++void s3c_tvscaler_int_enable(u32 int_type)
++{
++ u32 tmp;
++
++ tmp = __raw_readl(base + S3C_MODE);
++
++ if(int_type == 0) { //Edge triggering
++ tmp &= ~(S3C_MODE_IRQ_LEVEL);
++ } else if(int_type == 1) { //level triggering
++ tmp |= S3C_MODE_IRQ_LEVEL;
++ }
++
++ tmp |= S3C_MODE_POST_INT_ENABLE;
++
++ __raw_writel(tmp, base + S3C_MODE);
++}
++EXPORT_SYMBOL(s3c_tvscaler_int_enable);
++
++void s3c_tvscaler_int_disable(void)
++{
++ u32 tmp;
++
++ tmp = __raw_readl(base + S3C_MODE);
++
++ tmp &=~ (S3C_MODE_POST_INT_ENABLE);
++
++ __raw_writel(tmp, base + S3C_MODE);
++
++}
++EXPORT_SYMBOL(s3c_tvscaler_int_disable);
++
++
++void s3c_tvscaler_start(void)
++{
++ __raw_writel(S3C_POSTENVID_ENABLE, base + S3C_POSTENVID);
++
++}
++EXPORT_SYMBOL(s3c_tvscaler_start);
++
++void s3c_tvscaler_stop_freerun(void)
++{
++ u32 tmp;
++
++ tmp = __raw_readl(base + S3C_MODE);
++
++ tmp &=~(1<<14);
++
++ __raw_writel(tmp, base + S3C_MODE);
++}
++EXPORT_SYMBOL(s3c_tvscaler_stop_freerun);
++
++
++void s3c_tvscaler_config(scaler_params_t *sp)
++{
++ u32 tmp = 0;
++ u32 in_pixel_size = 0;
++ u32 out_pixel_size = 0;
++ u32 loop = 0;
++
++ tmp = __raw_readl(base + S3C_POSTENVID);
++ tmp &= ~S3C_POSTENVID_ENABLE;
++ __raw_writel(tmp, base + S3C_POSTENVID);
++#ifdef SINGLE_BUF
++ tmp = S3C_MODE2_ADDR_CHANGE_DISABLE |S3C_MODE2_CHANGE_AT_FRAME_END |S3C_MODE2_SOFTWARE_TRIGGER;
++#else
++ tmp = S3C_MODE2_ADDR_CHANGE_ENABLE |S3C_MODE2_CHANGE_AT_FRAME_END |S3C_MODE2_SOFTWARE_TRIGGER;
++#endif
++ __raw_writel(tmp, base + S3C_MODE2);
++
++// peter mod. start
++ sp->DstStartX = sp->DstStartY = 0;
++ sp->DstWidth = sp->DstFullWidth;
++ sp->DstHeight = sp->DstFullHeight;
++// peter mod. end
++
++ sp->DstFrmSt = ( POST_BUFF_BASE_ADDR + PRE_BUFF_SIZE );
++ //printk("\n---peter s3c_tvscaler_config : SrcFrmSt = 0x%08x\n", sp->SrcFrmSt);
++ //printk("---peter s3c_tvscaler_config : DstFrmSt = 0x%08x\n", sp->DstFrmSt);
++
++ s3c_tvscaler_set_clk_src(HCLK);
++
++ s3c_tvscaler_set_path(sp->InPath, sp->OutPath);
++
++ s3c_tvscaler_set_fmt(sp->SrcCSpace, sp->DstCSpace, sp->InPath,
++ sp->OutPath, &in_pixel_size, &out_pixel_size);
++
++ s3c_tvscaler_set_size(sp);
++
++ s3c_tvscaler_set_addr(sp, in_pixel_size, out_pixel_size);
++
++ s3c_tvscaler_set_auto_load(sp);
++
++}
++EXPORT_SYMBOL(s3c_tvscaler_config);
++
++void s3c_tvscaler_set_param(scaler_params_t *sp)
++{
++#if 0
++ param.SrcFullWidth = sp->SrcFullWidth;
++ param.SrcFullHeight = sp->SrcFullHeight;
++ param.SrcStartX = sp->SrcStartX;
++ param.SrcStartY = sp->SrcStartY;
++ param.SrcWidth = sp->SrcWidth;
++ param.SrcHeight = sp->SrcHeight;
++ param.SrcFrmSt = sp->SrcFrmSt;
++ param.SrcCSpace = sp->SrcCSpace;
++ param.DstFullWidth = sp->DstFullWidth;
++ param.DstFullHeight = sp->DstFullHeight;
++ param.DstStartX = sp->DstStartX;
++ param.DstStartY = sp->DstStartY;
++ param.DstWidth = sp->DstWidth;
++ param.DstHeight = sp->DstHeight;
++ param.DstFrmSt = sp->DstFrmSt;
++ param.DstCSpace = sp->DstCSpace;
++ param.SrcFrmBufNum = sp->SrcFrmBufNum;
++ param.DstFrmSt = sp->DstFrmSt;
++ param.Mode = sp->Mode;
++ param.InPath = sp->InPath;
++ param.OutPath = sp->OutPath;
++#endif
++}
++EXPORT_SYMBOL(s3c_tvscaler_set_param);
++
++void s3c_tvscaler_init(void)
++{
++
++ int tmp;
++
++ // Use DOUTmpll source clock as a scaler clock
++ tmp = __raw_readl(S3C_CLK_SRC);
++
++ tmp &=~(0x3<<28);
++ tmp |= (0x1<<28);
++ __raw_writel(tmp, S3C_CLK_SRC);
++
++ printk(" %s \n", __FUNCTION__);
++
++}
++EXPORT_SYMBOL(s3c_tvscaler_init);
++
++
++static int s3c_tvscaler_probe(struct platform_device *pdev)
++{
++
++ struct resource *res;
++
++ int ret;
++
++ /* find the IRQs */
++ s3c_tvscaler_irq = platform_get_irq(pdev, 0);
++ if(s3c_tvscaler_irq <= 0) {
++ printk(KERN_ERR PFX "failed to get irq resouce\n");
++ return -ENOENT;
++ }
++
++ /* get the memory region for the tv scaler driver */
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if(res == NULL) {
++ printk(KERN_ERR PFX "failed to get memory region resouce\n");
++ return -ENOENT;
++ }
++
++ s3c_tvscaler_mem = request_mem_region(res->start, res->end-res->start+1, pdev->name);
++ if(s3c_tvscaler_mem == NULL) {
++ printk(KERN_ERR PFX "failed to reserve memory region\n");
++ return -ENOENT;
++ }
++
++ base = ioremap(s3c_tvscaler_mem->start, s3c_tvscaler_mem->end - res->start + 1);
++ if(s3c_tvscaler_mem == NULL) {
++ printk(KERN_ERR PFX "failed ioremap\n");
++ return -ENOENT;
++ }
++
++ tvscaler_clock = clk_get(&pdev->dev, "tv_encoder");
++ if(tvscaler_clock == NULL) {
++ printk(KERN_ERR PFX "failed to find tvscaler clock source\n");
++ return -ENOENT;
++ }
++
++ clk_enable(tvscaler_clock);
++
++ h_clk = clk_get(&pdev->dev, "hclk");
++ if(h_clk == NULL) {
++ printk(KERN_ERR PFX "failed to find h_clk clock source\n");
++ return -ENOENT;
++ }
++
++ init_waitqueue_head(&waitq);
++
++ ret = request_irq(s3c_tvscaler_irq, s3c_tvscaler_isr, SA_INTERRUPT,
++ "TV_SCALER", NULL);
++ if (ret) {
++ printk("request_irq(TV_SCALER) failed.\n");
++ return ret;
++ }
++
++ printk(" Success\n");
++
++ return 0;
++}
++
++static int s3c_tvscaler_remove(struct platform_device *dev)
++{
++ printk(KERN_INFO "s3c_tvscaler_remove called !\n");
++ clk_disable(tvscaler_clock);
++ free_irq(s3c_tvscaler_irq, NULL);
++ if (s3c_tvscaler_mem != NULL) {
++ pr_debug("s3-tvscaler: releasing s3c_tvscaler_mem\n");
++ iounmap(base);
++ release_resource(s3c_tvscaler_mem);
++ kfree(s3c_tvscaler_mem);
++ }
++
++ return 0;
++}
++
++static int s3c_tvscaler_suspend(struct platform_device *dev, pm_message_t state)
++{
++ clk_disable(tvscaler_clock);
++ return 0;
++}
++
++static int s3c_tvscaler_resume(struct platform_device *pdev)
++{
++ clk_enable(tvscaler_clock);
++ return 0;
++}
++
++static struct platform_driver s3c_tvscaler_driver = {
++ .probe = s3c_tvscaler_probe,
++ .remove = s3c_tvscaler_remove,
++ .suspend = s3c_tvscaler_suspend,
++ .resume = s3c_tvscaler_resume,
++ .driver = {
++ .owner = THIS_MODULE,
++ .name = "s3c-tvscaler",
++ },
++};
++
++static char banner[] __initdata = KERN_INFO "S3C6410 TV scaler Driver, (c) 2008 Samsung Electronics\n";
++
++
++int __init s3c_tvscaler_pre_init(void)
++{
++
++ printk(banner);
++
++ if(platform_driver_register(&s3c_tvscaler_driver) != 0)
++ {
++ printk("platform device register Failed \n");
++ return -1;
++ }
++
++ printk(" S3C6410 TV scaler Driver module init OK. \n");
++
++ return 0;
++}
++
++void s3c_tvscaler_exit(void)
++{
++ platform_driver_unregister(&s3c_tvscaler_driver);
++ printk("S3C: tvscaler module exit\n");
++}
++
++module_init(s3c_tvscaler_pre_init);
++module_exit(s3c_tvscaler_exit);
++
++
++MODULE_AUTHOR("Peter, Oh");
++MODULE_DESCRIPTION("S3C TV Controller Device Driver");
++MODULE_LICENSE("GPL");
++
++
+diff --git a/drivers/media/video/samsung/s3c-tvscaler.h b/drivers/media/video/samsung/s3c-tvscaler.h
+new file mode 100644
+index 0000000..d8079a3
+--- /dev/null
++++ b/drivers/media/video/samsung/s3c-tvscaler.h
+@@ -0,0 +1,96 @@
++#ifndef __S3CTVSCALER_H_
++#define __S3CTVSCALER_H_
++
++#include <asm-arm/arch-s3c2410/reserved_mem.h>
++
++#define TVSCALER_IOCTL_MAGIC 'S'
++
++#define PPROC_SET_PARAMS _IO(TVSCALER_IOCTL_MAGIC, 0)
++#define PPROC_START _IO(TVSCALER_IOCTL_MAGIC, 1)
++#define PPROC_STOP _IO(TVSCALER_IOCTL_MAGIC, 2)
++#define PPROC_INTERLACE_MODE _IO(TVSCALER_IOCTL_MAGIC, 3)
++#define PPROC_PROGRESSIVE_MODE _IO(TVSCALER_IOCTL_MAGIC, 4)
++
++
++#define QVGA_XSIZE 320
++#define QVGA_YSIZE 240
++
++#define LCD_XSIZE 320
++#define LCD_YSIZE 240
++
++#define SCALER_MINOR 251 // Just some number
++
++
++//#define SYSTEM_RAM 0x08000000 // 128mb
++#define SYSTEM_RAM 0x07800000 // 120mb
++#define RESERVE_POST_MEM 8*1024*1024 // 8mb
++#define PRE_BUFF_SIZE 4*1024*1024 //4 // 4mb
++#define POST_BUFF_SIZE ( RESERVE_POST_MEM - PRE_BUFF_SIZE )
++#if 0
++#define POST_BUFF_BASE_ADDR (0x50000000 + (SYSTEM_RAM - RESERVE_POST_MEM))
++#else // TV_RESERVED_MEM_START is defined in the s3c-linux-2.6.21_dev_4_4_15
++#define POST_BUFF_BASE_ADDR TV_RESERVED_MEM_START
++#endif
++
++#define USE_DEDICATED_MEM 1
++
++typedef enum {
++ INTERLACE_MODE,
++ PROGRESSIVE_MODE
++} s3c_scaler_scan_mode_t;
++
++typedef enum {
++ POST_DMA, POST_FIFO
++} s3c_scaler_path_t;
++
++typedef enum {
++ ONE_SHOT, FREE_RUN
++} s3c_scaler_run_mode_t;
++
++typedef enum {
++ PAL1, PAL2, PAL4, PAL8,
++ RGB8, ARGB8, RGB16, ARGB16, RGB18, RGB24, RGB30, ARGB24,
++ YC420, YC422, // Non-interleave
++ CRYCBY, CBYCRY, YCRYCB, YCBYCR, YUV444 // Interleave
++} cspace_t;
++
++typedef enum
++{
++ HCLK = 0, PLL_EXT = 1, EXT_27MHZ = 3
++} scaler_clk_src_t;
++
++typedef struct{
++ unsigned int SrcFullWidth; // Source Image Full Width(Virtual screen size)
++ unsigned int SrcFullHeight; // Source Image Full Height(Virtual screen size)
++ unsigned int SrcStartX; // Source Image Start width offset
++ unsigned int SrcStartY; // Source Image Start height offset
++ unsigned int SrcWidth; // Source Image Width
++ unsigned int SrcHeight; // Source Image Height
++ unsigned int SrcFrmSt; // Base Address of the Source Image : Physical Address
++ cspace_t SrcCSpace; // Color Space ot the Source Image
++
++ unsigned int DstFullWidth; // Source Image Full Width(Virtual screen size)
++ unsigned int DstFullHeight; // Source Image Full Height(Virtual screen size)
++ unsigned int DstStartX; // Source Image Start width offset
++ unsigned int DstStartY; // Source Image Start height offset
++ unsigned int DstWidth; // Source Image Width
++ unsigned int DstHeight; // Source Image Height
++ unsigned int DstFrmSt; // Base Address of the Source Image : Physical Address
++ cspace_t DstCSpace; // Color Space ot the Source Image
++
++ unsigned int SrcFrmBufNum; // Frame buffer number
++ s3c_scaler_run_mode_t Mode; // POST running mode(PER_FRAME or FREE_RUN)
++ s3c_scaler_path_t InPath; // Data path of the source image
++ s3c_scaler_path_t OutPath; // Data path of the desitination image
++
++}scaler_params_t;
++
++typedef struct{
++ unsigned int pre_phy_addr;
++ unsigned char *pre_virt_addr;
++
++ unsigned int post_phy_addr;
++ unsigned char *post_virt_addr;
++} buff_addr_t;
++
++#endif //__S3CTVSCALER_H_
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-2.6.24/smartq5/mer/0007-make-tv-encoder-scaler-compile.patch b/recipes/linux/linux-2.6.24/smartq5/mer/0007-make-tv-encoder-scaler-compile.patch
new file mode 100644
index 0000000000..9dfa4cc6e9
--- /dev/null
+++ b/recipes/linux/linux-2.6.24/smartq5/mer/0007-make-tv-encoder-scaler-compile.patch
@@ -0,0 +1,5208 @@
+From 148e57efdb357f7178ef2610caa9e33974965b4f Mon Sep 17 00:00:00 2001
+From: Carsten V. Munk <carsten.munk@gmail.com>
+Date: Thu, 6 Aug 2009 12:03:27 +0000
+Subject: [PATCH 07/13] make tv encoder + scaler compile
+
+---
+ drivers/media/video/Makefile | 3 +
+ drivers/media/video/s3c-tvenc.c | 1479 +++++++++++++++++++++++++++
+ drivers/media/video/s3c-tvenc.h | 165 +++
+ drivers/media/video/s3c-tvscaler.c | 802 +++++++++++++++
+ drivers/media/video/s3c-tvscaler.h | 96 ++
+ drivers/media/video/samsung/Makefile | 2 -
+ drivers/media/video/samsung/s3c-tvenc.c | 1479 ---------------------------
+ drivers/media/video/samsung/s3c-tvenc.h | 165 ---
+ drivers/media/video/samsung/s3c-tvscaler.c | 802 ---------------
+ drivers/media/video/samsung/s3c-tvscaler.h | 96 --
+ include/asm-arm/arch-s3c2410/reserved_mem.h | 4 +-
+ 11 files changed, 2547 insertions(+), 2546 deletions(-)
+ create mode 100644 drivers/media/video/s3c-tvenc.c
+ create mode 100644 drivers/media/video/s3c-tvenc.h
+ create mode 100644 drivers/media/video/s3c-tvscaler.c
+ create mode 100644 drivers/media/video/s3c-tvscaler.h
+ delete mode 100644 drivers/media/video/samsung/s3c-tvenc.c
+ delete mode 100644 drivers/media/video/samsung/s3c-tvenc.h
+ delete mode 100644 drivers/media/video/samsung/s3c-tvscaler.c
+ delete mode 100644 drivers/media/video/samsung/s3c-tvscaler.h
+
+diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
+index cd3d371..92a1e45 100644
+--- a/drivers/media/video/Makefile
++++ b/drivers/media/video/Makefile
+@@ -126,6 +126,9 @@ obj-$(CONFIG_USB_QUICKCAM_MESSENGER) += usbvideo/
+ obj-$(CONFIG_VIDEO_IVTV) += ivtv/
+
+ obj-$(CONFIG_VIDEO_SAMSUNG) += s3c_camera_driver.o s3c_camif.o samsung/
++obj-$(CONFIG_VIDEO_SAMSUNG_TVENC) += s3c-tvenc.o
++obj-$(CONFIG_VIDEO_SAMSUNG_TVSCALER) += s3c-tvscaler.o
++
+ obj-$(CONFIG_VIDEO_VIVI) += vivi.o
+ obj-$(CONFIG_VIDEO_CX23885) += cx23885/
+
+diff --git a/drivers/media/video/s3c-tvenc.c b/drivers/media/video/s3c-tvenc.c
+new file mode 100644
+index 0000000..11dfd37
+--- /dev/null
++++ b/drivers/media/video/s3c-tvenc.c
+@@ -0,0 +1,1479 @@
++
++/*
++ * linux/drivers/tvenc/s3c-tvenc.c
++ *
++ * Revision 1.0
++ *
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file COPYING in the main directory of this archive for
++ * more details.
++ *
++ * S3C TV Encoder driver
++ *
++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/types.h>
++#include <linux/timer.h>
++#include <linux/kernel.h>
++#include <linux/fs.h>
++#include <linux/platform_device.h>
++#include <linux/interrupt.h>
++#include <linux/clk.h>
++#include <linux/delay.h>
++#include <asm/uaccess.h>
++#include <linux/errno.h> /* error codes */
++#include <asm/div64.h>
++#include <linux/mm.h>
++#include <linux/tty.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/hardware.h>
++#include <asm/uaccess.h>
++#include <asm/arch/map.h>
++
++#include <linux/version.h>
++#if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,16)
++#include <linux/config.h>
++#include <asm/arch/registers.h>
++#include <linux/videodev2.h>
++#else
++#include <asm/arch/regs-tvenc.h>
++#include <asm/arch/regs-lcd.h>
++#include <media/v4l2-common.h>
++#endif
++
++#include "s3c-tvenc.h"
++
++#define PFX "s3c_tvenc"
++
++static struct clk *tvenc_clock;
++static struct clk *h_clk;
++static int s3c_tvenc_irq = NO_IRQ;
++static struct resource *s3c_tvenc_mem;
++static void __iomem *base;
++static wait_queue_head_t waitq;
++static tv_out_params_t tv_param = {0,};
++
++/* Backup SFR value */
++static u32 backup_reg[2];
++
++
++/* Structure that declares the access functions*/
++
++static void s3c_tvenc_switch(tv_enc_switch_t sw)
++{
++ if(sw == OFF) {
++ __raw_writel(__raw_readl(base + S3C_TVCTRL)
++ &~ S3C_TVCTRL_ON, base + S3C_TVCTRL);
++ } else if(sw == ON) {
++ __raw_writel(__raw_readl(base + S3C_TVCTRL)
++ | S3C_TVCTRL_ON, base + S3C_TVCTRL);
++ } else
++ printk("Error func:%s line:%d\n", __FUNCTION__, __LINE__);
++}
++
++static void s3c_tvenc_set_image_size(u32 width, u32 height)
++{
++ __raw_writel(IIS_WIDTH(width)| IIS_HEIGHT(height),
++ base + S3C_INIMAGESIZE);
++}
++
++#if 0
++static void s3c_tvenc_enable_macrovision(tv_standard_t tvmode, macro_pattern_t pattern)
++{
++ switch(pattern) {
++ case AGC4L :
++ break;
++ case AGC2L :
++ break;
++ case N01 :
++ break;
++ case N02 :
++ break;
++ case P01 :
++ break;
++ case P02 :
++ break;
++ default :
++ break;
++ }
++}
++
++static void s3c_tvenc_disable_macrovision(void)
++{
++ __raw_writel(__raw_readl(base + S3C_MACROVISION0)
++ &~0xff, base + S3C_MACROVISION0);
++}
++#endif
++
++static void s3c_tvenc_set_tv_mode(tv_standard_t mode, tv_conn_type_t out)
++{
++ u32 signal_type = 0, output_type = 0;
++
++ switch(mode) {
++ case PAL_N :
++ __raw_writel(VBP_VEFBPD_PAL|VBP_VOFBPD_PAL,
++ base + S3C_VBPORCH);
++ __raw_writel(HBP_HSPW_PAL|HBP_HBPD_PAL,
++ base + S3C_HBPORCH);
++ __raw_writel(HEO_DTO_PAL|HEO_HEOV_PAL,
++ base + S3C_HENHOFFSET);
++ __raw_writel(EPC_PED_ON,
++ base + S3C_PEDCTRL);
++ __raw_writel(YFB_YBW_26|YFB_CBW_06,
++ base + S3C_YCFILTERBW);
++ __raw_writel(SSC_HSYNC_PAL,
++ base + S3C_SYNCSIZECTRL);
++ __raw_writel(BSC_BEND_PAL|BSC_BSTART_PAL,
++ base + S3C_BURSTCTRL);
++ __raw_writel(MBS_BSTART_PAL,
++ base + S3C_MACROBURSTCTRL);
++ __raw_writel(AVP_AVEND_PAL|AVP_AVSTART_PAL,
++ base + S3C_ACTVIDPOCTRL);
++ break;
++ case PAL_NC :
++ case PAL_BGHID :
++ __raw_writel(VBP_VEFBPD_PAL|VBP_VOFBPD_PAL,
++ base + S3C_VBPORCH);
++ __raw_writel(HBP_HSPW_PAL|HBP_HBPD_PAL,
++ base + S3C_HBPORCH);
++ __raw_writel(HEO_DTO_PAL|HEO_HEOV_PAL,
++ base + S3C_HENHOFFSET);
++ __raw_writel(EPC_PED_OFF,
++ base + S3C_PEDCTRL);
++ __raw_writel(YFB_YBW_26|YFB_CBW_06,
++ base + S3C_YCFILTERBW);
++ __raw_writel(SSC_HSYNC_PAL,
++ base + S3C_SYNCSIZECTRL);
++ __raw_writel(BSC_BEND_PAL|BSC_BSTART_PAL,
++ base + S3C_BURSTCTRL);
++ __raw_writel(MBS_BSTART_PAL,
++ base + S3C_MACROBURSTCTRL);
++ __raw_writel(AVP_AVEND_PAL|AVP_AVSTART_PAL,
++ base + S3C_ACTVIDPOCTRL);
++ break;
++ case NTSC_443 :
++ __raw_writel(VBP_VEFBPD_NTSC|VBP_VOFBPD_NTSC,
++ base + S3C_VBPORCH);
++ __raw_writel(HBP_HSPW_NTSC|HBP_HBPD_NTSC,
++ base + S3C_HBPORCH);
++ __raw_writel(HEO_DTO_NTSC|HEO_HEOV_NTSC,
++ base + S3C_HENHOFFSET);
++ __raw_writel(EPC_PED_ON,
++ base + S3C_PEDCTRL);
++ __raw_writel(YFB_YBW_26|YFB_CBW_06,
++ base + S3C_YCFILTERBW);
++ __raw_writel(SSC_HSYNC_NTSC,
++ base + S3C_SYNCSIZECTRL);
++ __raw_writel(BSC_BEND_NTSC|BSC_BSTART_NTSC,
++ base + S3C_BURSTCTRL);
++ __raw_writel(MBS_BSTART_NTSC,
++ base + S3C_MACROBURSTCTRL);
++ __raw_writel(AVP_AVEND_NTSC|AVP_AVSTART_NTSC,
++ base + S3C_ACTVIDPOCTRL);
++ break;
++ case NTSC_J :
++ __raw_writel(VBP_VEFBPD_NTSC|VBP_VOFBPD_NTSC,
++ base + S3C_VBPORCH);
++ __raw_writel(HBP_HSPW_NTSC|HBP_HBPD_NTSC,
++ base + S3C_HBPORCH);
++ __raw_writel(HEO_DTO_NTSC|HEO_HEOV_NTSC,
++ base + S3C_HENHOFFSET);
++ __raw_writel(EPC_PED_OFF,
++ base + S3C_PEDCTRL);
++ __raw_writel(YFB_YBW_21|YFB_CBW_06,
++ base + S3C_YCFILTERBW);
++ __raw_writel(SSC_HSYNC_NTSC,
++ base + S3C_SYNCSIZECTRL);
++ __raw_writel(BSC_BEND_NTSC|BSC_BSTART_NTSC,
++ base + S3C_BURSTCTRL);
++ __raw_writel(MBS_BSTART_NTSC,
++ base + S3C_MACROBURSTCTRL);
++ __raw_writel(AVP_AVEND_NTSC|AVP_AVSTART_NTSC,
++ base + S3C_ACTVIDPOCTRL);
++ break;
++ case PAL_M :
++ case NTSC_M :
++ default :
++ __raw_writel(VBP_VEFBPD_NTSC|VBP_VOFBPD_NTSC,
++ base + S3C_VBPORCH);
++ __raw_writel(HBP_HSPW_NTSC|HBP_HBPD_NTSC,
++ base + S3C_HBPORCH);
++ __raw_writel(HEO_DTO_NTSC|HEO_HEOV_NTSC,
++ base + S3C_HENHOFFSET);
++ __raw_writel(EPC_PED_ON,
++ base + S3C_PEDCTRL);
++ __raw_writel(YFB_YBW_21|YFB_CBW_06,
++ base + S3C_YCFILTERBW);
++ __raw_writel(SSC_HSYNC_NTSC,
++ base + S3C_SYNCSIZECTRL);
++ __raw_writel(BSC_BEND_NTSC|BSC_BSTART_NTSC,
++ base + S3C_BURSTCTRL);
++ __raw_writel(MBS_BSTART_NTSC,
++ base + S3C_MACROBURSTCTRL);
++ __raw_writel(AVP_AVEND_NTSC|AVP_AVSTART_NTSC,
++ base + S3C_ACTVIDPOCTRL);
++ break;
++ }
++
++ if(out == S_VIDEO) {
++ __raw_writel(YFB_YBW_60|YFB_CBW_06,
++ base + S3C_YCFILTERBW);
++ output_type = S3C_TVCTRL_OUTTYPE_S;
++ } else
++ output_type = S3C_TVCTRL_OUTTYPE_C;
++
++ switch(mode) {
++ case NTSC_M :
++ signal_type = S3C_TVCTRL_OUTFMT_NTSC_M;
++ break;
++ case NTSC_J :
++ signal_type = S3C_TVCTRL_OUTFMT_NTSC_J;
++ break;
++ case PAL_BGHID :
++ signal_type = S3C_TVCTRL_OUTFMT_PAL_BDG;
++ break;
++ case PAL_M :
++ signal_type = S3C_TVCTRL_OUTFMT_PAL_M;
++ break;
++ case PAL_NC :
++ signal_type = S3C_TVCTRL_OUTFMT_PAL_NC;
++ break;
++ default:
++ printk("s3c_tvenc_set_tv_mode : No matching signal_type!\n");
++ break;
++ }
++
++ __raw_writel((__raw_readl(base + S3C_TVCTRL)
++ &~(0x1f<<4))| output_type | signal_type,
++ base + S3C_TVCTRL);
++
++ __raw_writel(0x01, base + S3C_FSCAUXCTRL);
++}
++
++#if 0
++static void s3c_tvenc_set_pedestal(tv_enc_switch_t sw)
++{
++ if(sw)
++ __raw_writel(EPC_PED_ON, base + S3C_PEDCTRL);
++ else
++ __raw_writel(EPC_PED_OFF, base + S3C_PEDCTRL);
++}
++
++static void s3c_tvenc_set_sub_carrier_freq(u32 freq)
++{
++ __raw_writel(FSC_CTRL(freq), base + S3C_FSCCTRL);
++}
++
++static void s3c_tvenc_set_fsc_dto(u32 val)
++{
++ unsigned int temp;
++
++ temp = (0x1<<31)|(val&0x7fffffff);
++ __raw_writel(temp, base + S3C_FSCDTOMANCTRL);
++}
++
++static void s3c_tvenc_disable_fsc_dto(void)
++{
++ __raw_writel(__raw_readl(base + S3C_FSCDTOMANCTRL)&~(1<<31),
++ base + S3C_FSCDTOMANCTRL);
++}
++
++static void s3c_tvenc_set_bg(u32 soft_mix, u32 color, u32 lum_offset)
++{
++ unsigned int bg_color;
++ switch(color) {
++ case 0 :
++ bg_color = BGC_BGCS_BLACK;
++ break;
++ case 1 :
++ bg_color = BGC_BGCS_BLUE;
++ break;
++ case 2 :
++ bg_color = BGC_BGCS_RED;
++ break;
++ case 3 :
++ bg_color = BGC_BGCS_MAGENTA;
++ break;
++ case 4 :
++ bg_color = BGC_BGCS_GREEN;
++ break;
++ case 5 :
++ bg_color = BGC_BGCS_CYAN;
++ break;
++ case 6 :
++ bg_color = BGC_BGCS_YELLOW;
++ break;
++ case 7 :
++ bg_color = BGC_BGCS_WHITE;
++ break;
++ }
++ if(soft_mix)
++ __raw_writel(BGC_SME_ENA|bg_color|BGC_BGYOFS(lum_offset),
++ base + S3C_BGCTRL);
++ else
++ __raw_writel(BGC_SME_DIS|bg_color|BGC_BGYOFS(lum_offset),
++ base + S3C_BGCTRL);
++
++}
++
++static void s3c_tvenc_set_bg_vav_hav(u32 hav_len, u32 vav_len, u32 hav_st, u32 vav_st)
++{
++ __raw_writel(BVH_BG_HL(hav_len)|BVH_BG_HS(hav_st)|BVH_BG_VL(vav_len)|BVH_BG_VS(vav_st),
++ base + S3C_BGHVAVCTRL);
++}
++#endif
++
++static void s3c_tvenc_set_hue_phase(u32 phase_val)
++{
++ __raw_writel(HUE_CTRL(phase_val),
++ base + S3C_HUECTRL);
++}
++
++#if 0
++static u32 s3c_tvenc_get_hue_phase(void)
++{
++ return __raw_readl(base + S3C_HUECTRL)&0xff;
++}
++#endif
++
++static void s3c_tvenc_set_contrast(u32 contrast)
++{
++ u32 temp;
++
++ temp = __raw_readl(base + S3C_CONTRABRIGHT);
++
++ __raw_writel((temp &~0xff)|contrast,
++ base + S3C_CONTRABRIGHT);
++}
++
++#if 0
++static u32 s3c_tvenc_get_contrast(void)
++{
++ return (__raw_readl(base + S3C_CONTRABRIGHT)&0xff);
++}
++#endif
++
++static void s3c_tvenc_set_bright(u32 bright)
++{
++ u32 temp;
++
++ temp = __raw_readl(base + S3C_CONTRABRIGHT);
++
++ __raw_writel((temp &~(0xff<<16))| (bright<<16),
++ base + S3C_CONTRABRIGHT);
++}
++
++#if 0
++static u32 s3c_tvenc_get_bright(void)
++{
++ return ((__raw_readl(base + S3C_CONTRABRIGHT)&(0xff<<16))>>16);
++}
++
++
++static void s3c_tvenc_set_cbgain(u32 cbgain)
++{
++ u32 temp;
++
++ temp = __raw_readl(base + S3C_CBCRGAINCTRL);
++
++ __raw_writel((temp &~0xff)|cbgain,
++ base + S3C_CBCRGAINCTRL);
++}
++
++
++static u32 s3c_tvenc_get_cbgain(void)
++{
++ return (__raw_readl(base + S3C_CBCRGAINCTRL)&0xff);
++}
++
++static void s3c_tvenc_set_crgain(u32 crgain)
++{
++ u32 temp;
++
++ temp = __raw_readl(base + S3C_CBCRGAINCTRL);
++
++ __raw_writel((temp &~(0xff<<16))| (crgain<<16),
++ base + S3C_CBCRGAINCTRL);
++}
++
++static u32 s3c_tvenc_get_crgain(void)
++{
++ return ((__raw_readl(base + S3C_CBCRGAINCTRL)&(0xff<<16))>>16);
++}
++#endif
++
++static void s3c_tvenc_enable_gamma_control(tv_enc_switch_t enable)
++{
++ u32 temp;
++
++ temp = __raw_readl(base + S3C_GAMMACTRL);
++ if(enable == ON)
++ temp |= (1<<12);
++ else
++ temp &= ~(1<<12);
++
++ __raw_writel(temp, base + S3C_GAMMACTRL);
++}
++
++static void s3c_tvenc_set_gamma_gain(u32 ggain)
++{
++ u32 temp;
++
++ temp = __raw_readl(base + S3C_GAMMACTRL);
++
++ __raw_writel((temp &~(0x7<<8))| (ggain<<8),
++ base + S3C_GAMMACTRL);
++}
++
++#if 0
++static u32 s3c_tvenc_get_gamma_gain(void)
++{
++ return ((__raw_readl(base + S3C_GAMMACTRL)&(0x7<<8))>>8);
++}
++
++static void s3c_tvenc_enable_mute_control(tv_enc_switch_t enable)
++{
++ u32 temp;
++
++ temp = __raw_readl(base + S3C_GAMMACTRL);
++ if(enable == ON)
++ temp |= (1<<12);
++ else
++ temp &= ~(1<<12);
++
++ __raw_writel(temp, base + S3C_GAMMACTRL);
++}
++
++static void s3c_tvenc_set_mute(u32 y, u32 cb, u32 cr)
++{
++ u32 temp;
++
++ temp = __raw_readl(base + S3C_MUTECTRL);
++
++ temp &=~(0xffffff<<8);
++ temp |= (cr & 0xff)<<24;
++ temp |= (cb & 0xff)<<16;
++ temp |= (y & 0xff)<<8;
++
++ __raw_writel(temp, base + S3C_MUTECTRL);
++}
++
++static void s3c_tvenc_get_mute(u32 *y, u32 *cb, u32 *cr)
++{
++ u32 temp;
++
++ temp = __raw_readl(base + S3C_MUTECTRL);
++
++ *y = (temp&(0xff<<8))>>8;
++ *cb = (temp&(0xff<<16))>>16;
++ *cr = (temp&(0xff<<24))>>24;
++}
++#endif
++
++static void s3c_tvenc_get_active_win_center(u32 *vert, u32 *horz)
++{
++ u32 temp;
++
++ temp = __raw_readl(base + S3C_HENHOFFSET);
++
++ *vert = (temp&(0x3f<<24))>>24;
++ *horz = (temp&(0xff<<16))>>16;
++}
++
++static void s3c_tvenc_set_active_win_center(u32 vert, u32 horz)
++{
++ u32 temp;
++
++ temp = __raw_readl(base + S3C_HENHOFFSET);
++
++ temp &=~(0x3ffff<<16);
++ temp |= (vert&0x3f)<<24;
++ temp |= (horz&0xff)<<16;
++
++ __raw_writel(temp, base + S3C_HENHOFFSET);
++}
++
++// LCD display controller configuration functions
++static void s3c_lcd_set_output_path(lcd_local_output_t out)
++{
++#if 0 // peter for 2.6.21 kernel
++ s3c_fb_set_output_path(out);
++#else // peter for 2.6.24 kernel
++ s3cfb_set_output_path(out);
++#endif
++}
++
++static void s3c_lcd_set_clkval(u32 clkval)
++{
++#if 0 // peter for 2.6.21 kernel
++ s3c_fb_set_clkval(clkval);
++#else // peter for 2.6.24 kernel
++ s3cfb_set_clock(clkval);
++#endif
++}
++
++static void s3c_lcd_enable_rgbport(u32 on_off)
++{
++#if 0 // peter for 2.6.21 kernel
++ s3c_fb_enable_rgbport(on_off);
++#else // peter for 2.6.24 kernel
++ s3cfb_enable_rgbport(on_off);
++#endif
++}
++
++static void s3c_lcd_start(void)
++{
++#if 0 // peter for 2.6.21 kernel
++ s3c_fb_start_lcd();
++#else // peter for 2.6.24 kernel
++ s3cfb_start_lcd();
++#endif
++}
++
++static void s3c_lcd_stop(void)
++{
++#if 0 // peter for 2.6.21 kernel
++ s3c_fb_stop_lcd();
++#else // peter for 2.6.24 kernel
++ s3cfb_stop_lcd();
++#endif
++}
++
++
++static void s3c_lcd_set_config(void)
++{
++ backup_reg[0] = __raw_readl(S3C_VIDCON0);
++ backup_reg[1] = __raw_readl(S3C_VIDCON2);
++
++ s3c_lcd_set_output_path(LCD_TVRGB);
++ tv_param.lcd_output_mode = LCD_TVRGB;
++
++ s3c_lcd_set_clkval(4);
++ s3c_lcd_enable_rgbport(1);
++}
++
++static void s3c_lcd_exit_config(void)
++{
++ __raw_writel(backup_reg[0], S3C_VIDCON0);
++ __raw_writel(backup_reg[1], S3C_VIDCON2);
++ tv_param.lcd_output_mode = LCD_RGB;
++}
++
++static int scaler_test_start(void)
++{
++ tv_param.sp.DstFullWidth = 640;
++ tv_param.sp.DstFullHeight= 480;
++ tv_param.sp.DstCSpace = RGB16;
++
++ s3c_tvscaler_config(&tv_param.sp);
++
++ s3c_tvscaler_int_enable(1);
++
++ s3c_tvscaler_start();
++
++ return 0;
++}
++
++static int scaler_test_stop(void)
++{
++ s3c_tvscaler_int_disable();
++
++ return 0;
++}
++
++
++static int tvout_start(void)
++{
++ u32 width, height;
++ tv_standard_t type;
++ tv_conn_type_t conn;
++
++ tv_param.sp.DstFullWidth *= 2; // For TV OUT
++
++ width = tv_param.sp.DstFullWidth;
++ height = tv_param.sp.DstFullHeight;
++ type = tv_param.sig_type;
++ conn = tv_param.connect;
++
++ /* Set TV-SCALER parameter */
++ switch(tv_param.v2.input->type) {
++ case V4L2_INPUT_TYPE_FIFO: // LCD FIFO-OUT
++ tv_param.sp.Mode = FREE_RUN;
++ tv_param.sp.DstCSpace = YCBYCR;
++ /* Display controller setting */
++ s3c_lcd_stop();
++ s3c_lcd_set_config();
++ break;
++ case V4L2_INPUT_TYPE_MSDMA: // MSDMA
++ tv_param.sp.Mode = FREE_RUN;
++ tv_param.sp.DstCSpace = YCBYCR;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ s3c_tvenc_set_tv_mode(type, conn);
++ s3c_tvenc_set_image_size(width, height);
++ s3c_tvenc_switch(ON);
++
++ s3c_tvscaler_config(&tv_param.sp); // for setting DstStartX/Y, DstWidth/Height
++ s3c_tvscaler_set_interlace(1);
++ if(tv_param.v2.input->type == V4L2_INPUT_TYPE_FIFO)
++ s3c_tvscaler_int_disable();
++ else
++ s3c_tvscaler_int_enable(1);
++ s3c_tvscaler_start();
++
++ if(tv_param.v2.input->type == V4L2_INPUT_TYPE_FIFO)
++ s3c_lcd_start();
++
++ return 0;
++}
++
++static int tvout_stop(void)
++{
++
++ s3c_tvscaler_set_interlace(0);
++ s3c_tvscaler_stop_freerun();
++ s3c_tvscaler_int_disable();
++ s3c_tvenc_switch(OFF);
++
++ switch(tv_param.v2.input->type) {
++ case V4L2_INPUT_TYPE_FIFO: // LCD FIFO-OUT
++ /* Display controller setting */
++ s3c_lcd_stop();
++ s3c_lcd_exit_config();
++ s3c_lcd_start();
++ break;
++ default:
++ break;
++ }
++ return 0;
++}
++
++/* ------------------------------------------ V4L2 SUPPORT ----------------------------------------------*/
++/* ------------- In FIFO and MSDMA, v4l2_input supported by S3C TVENC controller ------------------*/
++static struct v4l2_input tvenc_inputs[] = {
++ {
++ .index = 0,
++ .name = "LCD FIFO_OUT",
++ .type = V4L2_INPUT_TYPE_FIFO,
++ .audioset = 1,
++ .tuner = 0, /* ignored */
++ .std = 0,
++ .status = 0,
++ },
++ {
++ .index = 1,
++ .name = "Memory input (MSDMA)",
++ .type = V4L2_INPUT_TYPE_MSDMA,
++ .audioset = 2,
++ .tuner = 0,
++ .std = 0,
++ .status = 0,
++ }
++};
++
++/* ------------ Out FIFO and MADMA, v4l2_output supported by S3C TVENC controller ----------------*/
++static struct v4l2_output tvenc_outputs[] = {
++ {
++ .index = 0,
++ .name = "TV-OUT",
++ .type = V4L2_OUTPUT_TYPE_ANALOG,
++ .audioset = 0,
++ .modulator = 0,
++ .std = V4L2_STD_PAL | V4L2_STD_NTSC_M,
++ },
++ {
++ .index = 1,
++ .name = "Memory output (MSDMA)",
++ .type = V4L2_OUTPUT_TYPE_MSDMA,
++ .audioset = 0,
++ .modulator = 0,
++ .std = 0,
++ },
++
++};
++
++const struct v4l2_fmtdesc tvenc_input_formats[] = {
++ {
++ .index = 0,
++ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
++ .description = "16 bpp RGB, le",
++ .pixelformat = V4L2_PIX_FMT_RGB565,
++ .flags = FORMAT_FLAGS_PACKED,
++ },
++ {
++ .index = 1,
++ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
++ .flags = FORMAT_FLAGS_PACKED,
++ .description = "24 bpp RGB, le",
++ .pixelformat = V4L2_PIX_FMT_RGB24,
++ },
++ {
++ .index = 2,
++ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
++ .flags = FORMAT_FLAGS_PLANAR,
++ .description = "4:2:2, planar, Y-Cb-Cr",
++ .pixelformat = V4L2_PIX_FMT_YUV422P,
++
++ },
++ {
++ .index = 3,
++ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
++ .flags = FORMAT_FLAGS_PLANAR,
++ .description = "4:2:0, planar, Y-Cb-Cr",
++ .pixelformat = V4L2_PIX_FMT_YUV420,
++ }
++};
++
++
++const struct v4l2_fmtdesc tvenc_output_formats[] = {
++ {
++ .index = 0,
++ .type = V4L2_BUF_TYPE_VIDEO_OUTPUT,
++ .description = "16 bpp RGB, le",
++ .pixelformat = V4L2_PIX_FMT_RGB565,
++ .flags = FORMAT_FLAGS_PACKED,
++ },
++ {
++ .index = 1,
++ .type = V4L2_BUF_TYPE_VIDEO_OUTPUT,
++ .flags = FORMAT_FLAGS_PACKED,
++ .description = "24 bpp RGB, le",
++ .pixelformat = V4L2_PIX_FMT_RGB24,
++ },
++ {
++ .index = 2,
++ .type = V4L2_BUF_TYPE_VIDEO_OUTPUT,
++ .flags = FORMAT_FLAGS_PLANAR,
++ .description = "4:2:2, planar, Y-Cb-Cr",
++ .pixelformat = V4L2_PIX_FMT_YUV422P,
++
++ },
++ {
++ .index = 3,
++ .type = V4L2_BUF_TYPE_VIDEO_OUTPUT,
++ .flags = FORMAT_FLAGS_PLANAR,
++ .description = "4:2:0, planar, Y-Cb-Cr",
++ .pixelformat = V4L2_PIX_FMT_YUV420,
++ }
++};
++
++const struct v4l2_standard tvout_standards[] = {
++ {
++ .index = 0,
++ .id = V4L2_STD_NTSC_M,
++ .name = "NTSC type",
++ },
++ {
++ .index = 1,
++ .id = V4L2_STD_PAL,
++ .name = "PAL type",
++ }
++};
++
++#define NUMBER_OF_INPUT_FORMATS ARRAY_SIZE(tvenc_input_formats)
++#define NUMBER_OF_OUTPUT_FORMATS ARRAY_SIZE(tvenc_output_formats)
++#define NUMBER_OF_INPUTS ARRAY_SIZE(tvenc_inputs)
++#define NUMBER_OF_OUTPUTS ARRAY_SIZE(tvenc_outputs)
++#define NUMBER_OF_STANDARDS ARRAY_SIZE(tvout_standards)
++
++static int s3c_tvenc_g_fmt(struct v4l2_format *f)
++{
++ int size = sizeof(struct v4l2_pix_format);
++
++ memset(&f->fmt.pix, 0, size);
++ memcpy(&f->fmt.pix, &tv_param.v2.pixfmt, size);
++
++ return 0;
++}
++
++static int s3c_tvenc_s_fmt(struct v4l2_format *f)
++{
++ /* update our state informations */
++ tv_param.v2.pixfmt= f->fmt.pix;
++
++ // peter LCD output related operation
++ if (tv_param.v2.pixfmt.pixelformat == V4L2_PIX_FMT_RGB565 ) {
++
++ tv_param.sp.SrcFullWidth = tv_param.v2.pixfmt.width;
++ tv_param.sp.SrcFullHeight = tv_param.v2.pixfmt.height;
++ tv_param.sp.SrcStartX = 0;
++ tv_param.sp.SrcStartY = 0;
++ tv_param.sp.SrcWidth = tv_param.sp.SrcFullWidth;
++ tv_param.sp.SrcHeight = tv_param.sp.SrcFullHeight;
++
++ printk("TV-OUT: LCD path operation set\n");
++
++ // peter for padded data of mfc output
++ } else if (tv_param.v2.pixfmt.pixelformat == V4L2_PIX_FMT_YUV420) {
++
++#ifdef DIVX_TEST // padded output
++ tv_param.sp.SrcFullWidth = tv_param.v2.pixfmt.width + 2*16;
++ tv_param.sp.SrcFullHeight = tv_param.v2.pixfmt.height + 2*16;
++ tv_param.sp.SrcStartX = 16;
++ tv_param.sp.SrcStartY = 16;
++ tv_param.sp.SrcWidth = tv_param.sp.SrcFullWidth - 2*tv_param.sp.SrcStartX;
++ tv_param.sp.SrcHeight = tv_param.sp.SrcFullHeight - 2*tv_param.sp.SrcStartY;
++#else // not padded output
++ tv_param.sp.SrcFullWidth = tv_param.v2.pixfmt.width;
++ tv_param.sp.SrcFullHeight = tv_param.v2.pixfmt.height;
++ tv_param.sp.SrcStartX = 0;
++ tv_param.sp.SrcStartY = 0;
++ tv_param.sp.SrcWidth = tv_param.sp.SrcFullWidth;
++ tv_param.sp.SrcHeight = tv_param.sp.SrcFullHeight;
++#endif
++
++ printk("TV-OUT: MFC path operation set\n");
++
++ }
++
++ switch(tv_param.v2.pixfmt.pixelformat) {
++ case V4L2_PIX_FMT_RGB565:
++ tv_param.sp.SrcCSpace = RGB16;
++ break;
++ case V4L2_PIX_FMT_RGB24:
++ tv_param.sp.SrcCSpace = RGB24;
++ break;
++ case V4L2_PIX_FMT_YUV420:
++ tv_param.sp.SrcCSpace = YC420;
++ break;
++ case V4L2_PIX_FMT_YUV422P:
++ tv_param.sp.SrcCSpace = YC422;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++// camif_convert_into_camif_cfg_t(cfg, 1);
++ return 0;
++}
++
++static int s3c_tvenc_s_input(int index)
++{
++
++ tv_param.v2.input = &tvenc_inputs[index];
++ switch(tv_param.v2.input->type) {
++ case V4L2_INPUT_TYPE_FIFO: // LCD FIFO-OUT
++ tv_param.sp.InPath = POST_FIFO;
++ break;
++ case V4L2_INPUT_TYPE_MSDMA: // MSDMA
++ tv_param.sp.InPath = POST_DMA;
++ break;
++ default:
++ return -EINVAL;
++ }
++ return 0;
++}
++
++static int s3c_tvenc_s_output(int index)
++{
++ tv_param.v2.output = &tvenc_outputs[index];
++ switch(tv_param.v2.output->type) {
++ case V4L2_OUTPUT_TYPE_ANALOG: // TV-OUT (FIFO-OUT)
++ tv_param.sp.OutPath = POST_FIFO;
++ break;
++ case V4L2_OUTPUT_TYPE_MSDMA: // MSDMA
++ tv_param.sp.OutPath = POST_DMA;
++ break;
++ default:
++ return -EINVAL;
++ }
++ return 0;
++}
++
++static int s3c_tvenc_s_std(v4l2_std_id *id)
++{
++// printk("s3c_tvenc_s_std: *id=0x%x",*id);
++ switch(*id) {
++ case V4L2_STD_NTSC_M:
++ tv_param.sig_type = NTSC_M;
++ tv_param.sp.DstFullWidth = 720;
++ tv_param.sp.DstFullHeight = 480;
++ break;
++ case V4L2_STD_PAL:
++ tv_param.sig_type = PAL_M;
++ tv_param.sp.DstFullWidth = 720;
++ tv_param.sp.DstFullHeight = 576;
++ break;
++ default:
++ return -EINVAL;
++ }
++ return 0;
++}
++
++static int s3c_tvenc_v4l2_control(struct v4l2_control *ctrl)
++{
++ switch(ctrl->id) {
++
++ // peter added for MFC related op.
++ case V4L2_CID_MPEG_STREAM_PID_VIDEO:
++ {
++ tv_param.sp.SrcFrmSt = ctrl->value;
++ return 0;
++ }
++
++ case V4L2_CID_CONNECT_TYPE:
++ {
++ if(ctrl->value == 0) { // COMPOSITE
++ tv_param.connect = COMPOSITE;
++ } else if(ctrl->value == 1) { //S-VIDEO
++ tv_param.connect = S_VIDEO;
++ } else {
++ return -EINVAL;
++ }
++ return 0;
++ }
++
++ case V4L2_CID_BRIGHTNESS:
++ {
++ s32 val = ctrl->value;
++ if((val > 0xff)||(val < 0))
++ return -EINVAL;
++ else
++ s3c_tvenc_set_bright(val);
++
++ return 0;
++ }
++
++ case V4L2_CID_CONTRAST:
++ {
++ s32 val = ctrl->value;
++ if((val > 0xff)||(val < 0))
++ return -EINVAL;
++ else
++ s3c_tvenc_set_contrast(val);
++
++ return 0;
++ }
++
++ case V4L2_CID_GAMMA:
++ {
++ s32 val = ctrl->value;
++ if((val > 0x3)||(val < 0)) {
++ return -EINVAL;
++ } else {
++ s3c_tvenc_enable_gamma_control(ON);
++ s3c_tvenc_set_gamma_gain(val);
++ s3c_tvenc_enable_gamma_control(OFF);
++ }
++ return 0;
++ }
++
++ case V4L2_CID_HUE:
++ {
++ s32 val = ctrl->value;
++ if((val > 0xff)||(val < 0))
++ return -EINVAL;
++ else
++ s3c_tvenc_set_hue_phase(val);
++
++ return 0;
++ }
++
++ case V4L2_CID_HCENTER:
++ {
++ s32 val = ctrl->value;
++ u32 curr_horz, curr_vert;
++
++ if((val > 0xff)||(val < 0)) {
++ return -EINVAL;
++ } else {
++ s3c_tvenc_get_active_win_center(&curr_vert, &curr_horz);
++ s3c_tvenc_set_active_win_center(curr_vert, val);
++ }
++
++ return 0;
++ }
++
++ case V4L2_CID_VCENTER:
++ {
++ s32 val = ctrl->value;
++ u32 curr_horz, curr_vert;
++
++ if((val > 0x3f)||(val < 0)) {
++ return -EINVAL;
++ } else {
++ s3c_tvenc_get_active_win_center(&curr_vert, &curr_horz);
++ s3c_tvenc_set_active_win_center(val, curr_horz);
++ }
++
++ return 0;
++ }
++
++ default:
++ return -EINVAL;
++ }
++ return 0;
++}
++
++int s3c_tvenc_open(struct inode *inode, struct file *filp)
++{
++ int err;
++
++ err = video_exclusive_open(inode, filp); // One function of V4l2 driver
++
++ if(err < 0)
++ return err;
++ filp->private_data = &tv_param;
++
++ s3c_tvscaler_init();
++
++ /* Success */
++ return 0;
++}
++
++int s3c_tvenc_release(struct inode *inode, struct file *filp)
++{
++ video_exclusive_release(inode, filp);
++
++ /* Success */
++ return 0;
++}
++
++static int s3c_tvenc_do_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,void *arg)
++{
++ int ret;
++
++ switch(cmd){
++ case VIDIOC_QUERYCAP:
++ {
++ struct v4l2_capability *cap = arg;
++ strcpy(cap->driver, "S3C TV-OUT driver");
++ strlcpy(cap->card, tv_param.v->name, sizeof(cap->card));
++ sprintf(cap->bus_info, "ARM AHB BUS");
++ cap->version = 0;
++ cap->capabilities = tv_param.v->type2;
++ return 0;
++ }
++
++ case VIDIOC_OVERLAY:
++ {
++ int on = *(int *)arg;
++
++ printk("TV-OUT: VIDIOC_OVERLAY on:%d\n", on);
++ if (on != 0) {
++ ret = tvout_start();
++ } else {
++ ret = tvout_stop();
++ }
++ return ret;
++ }
++
++ case VIDIOC_ENUMINPUT:
++ {
++ struct v4l2_input *i = arg;
++ printk("TV-OUT: VIDIOC_ENUMINPUT : index = %d\n", i->index);
++
++ if ((i->index) >= NUMBER_OF_INPUTS) {
++ return -EINVAL;
++ }
++ memcpy(i, &tvenc_inputs[i->index], sizeof(struct v4l2_input));
++ return 0;
++ }
++
++ case VIDIOC_S_INPUT: // 0 -> LCD FIFO-OUT, 1 -> MSDMA
++ {
++ int index = *((int *)arg);
++ printk("TV-OUT: VIDIOC_S_INPUT \n");
++
++ if (index >= NUMBER_OF_INPUTS) {
++ return -EINVAL;
++ }
++ else {
++ s3c_tvenc_s_input(index);
++ return 0;
++ }
++ }
++
++ case VIDIOC_G_INPUT:
++ {
++ u32 *i = arg;
++ printk("TV-OUT: VIDIOC_G_INPUT \n");
++ *i = tv_param.v2.input->type;
++ return 0;
++ }
++
++ case VIDIOC_ENUMOUTPUT:
++ {
++ struct v4l2_output *i = arg;
++ printk("TV-OUT: VIDIOC_ENUMOUTPUT : index = %d\n", i->index);
++
++ if ((i->index) >= NUMBER_OF_OUTPUTS) {
++ return -EINVAL;
++ }
++ memcpy(i, &tvenc_outputs[i->index], sizeof(struct v4l2_output));
++ return 0;
++ }
++
++ case VIDIOC_S_OUTPUT: // 0 -> TV / FIFO , 1 -> MSDMA
++ {
++ int index = *((int *)arg);
++ printk("TV-OUT: VIDIOC_S_OUTPUT \n");
++
++ if (index >= NUMBER_OF_OUTPUTS) {
++ return -EINVAL;
++ }
++ else {
++ s3c_tvenc_s_output(index);
++ return 0;
++ }
++ }
++
++ case VIDIOC_G_OUTPUT:
++ {
++ u32 *i = arg;
++ printk("VIDIOC_G_OUTPUT \n");
++ *i = tv_param.v2.output->type;
++ return 0;
++ }
++
++ case VIDIOC_ENUM_FMT:
++ { struct v4l2_fmtdesc *f = arg;
++ enum v4l2_buf_type type = f->type;
++ int index = f->index;
++
++ printk("C: VIDIOC_ENUM_FMT : index = %d\n", index);
++ if (index >= NUMBER_OF_INPUT_FORMATS)
++ return -EINVAL;
++
++ switch (type) {
++ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
++ break;
++ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
++ default:
++ return -EINVAL;
++ }
++ memset(f, 0, sizeof(*f));
++ memcpy(f, tv_param.v2.fmtdesc+index, sizeof(*f));
++ return 0;
++ }
++
++ case VIDIOC_G_FMT:
++ {
++ struct v4l2_format *f = arg;
++ printk("C: VIDIOC_G_FMT \n");
++ ret = s3c_tvenc_g_fmt(f);
++ return ret;
++ }
++
++ case VIDIOC_S_FMT:
++ {
++ struct v4l2_format *f = arg;
++ printk("C: VIDIOC_S_FMT \n");
++ ret = s3c_tvenc_s_fmt(f);
++ if(ret != 0) {
++ printk("s3c_tvenc_set_fmt() failed !\n");
++ return -EINVAL;
++ }
++ return ret;
++ }
++
++ case VIDIOC_S_CTRL:
++ {
++ struct v4l2_control *ctrl = arg;
++ //printk("P: VIDIOC_S_CTRL \n");
++ ret = s3c_tvenc_v4l2_control(ctrl);
++ return ret;
++ }
++
++ case VIDIOC_ENUMSTD:
++ {
++ struct v4l2_standard *e = arg;
++ unsigned int index = e->index;
++
++ if (index >= NUMBER_OF_STANDARDS)
++ return -EINVAL;
++ v4l2_video_std_construct(e, tvout_standards[e->index].id,
++ &tvout_standards[e->index].name);
++ e->index = index;
++ return 0;
++ }
++
++ case VIDIOC_G_STD:
++ {
++ v4l2_std_id *id = arg;
++ *id = tvout_standards[0].id;
++ return 0;
++ }
++
++ case VIDIOC_S_STD:
++ {
++ v4l2_std_id *id = arg;
++ unsigned int i;
++
++ for (i = 0; i < NUMBER_OF_STANDARDS; i++) {
++ //printk("P: *id = %d, tvout_standards[i].id = %d\n", *id, tvout_standards[i].id);
++ if (*id & tvout_standards[i].id)
++ break;
++ }
++ if (i == NUMBER_OF_STANDARDS)
++ return -EINVAL;
++
++ ret = s3c_tvenc_s_std(id);
++ return ret;
++ }
++
++ case VIDIOC_S_TVOUT_ON:
++ {
++ //int *SrcFrmSt = arg;
++ //printk("---peter VIDIOC_S_TVOUT_ON : SrcFrmSt = 0x%08x\n", *SrcFrmSt);
++ ret = tvout_start();
++ return ret;
++ }
++
++ case VIDIOC_S_TVOUT_OFF:
++ {
++ ret = tvout_stop();
++ return ret;
++ }
++
++ case VIDIOC_S_SCALER_TEST:
++ {
++ ret = scaler_test_start();
++ mdelay(1);
++ ret = scaler_test_stop();
++ return ret;
++ }
++
++ default:
++ return -EINVAL;
++ }
++ return 0;
++}
++
++static int s3c_tvenc_ioctl_v4l2(struct inode *inode, struct file *filp, unsigned int cmd,
++ unsigned long arg)
++{
++ return video_usercopy(inode, filp, cmd, arg, s3c_tvenc_do_ioctl);
++}
++
++int s3c_tvenc_read(struct file *filp, char *buf, size_t count,
++ loff_t *f_pos)
++{
++ return 0;
++}
++
++int s3c_tvenc_write(struct file *filp, const char *buf, size_t
++ count, loff_t *f_pos)
++{
++ return 0;
++}
++
++int s3c_tvenc_mmap(struct file *filp, struct vm_area_struct *vma)
++{
++ u32 size = vma->vm_end - vma->vm_start;
++ u32 max_size;
++ u32 page_frame_no;
++
++ page_frame_no = __phys_to_pfn(POST_BUFF_BASE_ADDR);
++
++ max_size = RESERVE_POST_MEM + PAGE_SIZE - (RESERVE_POST_MEM % PAGE_SIZE);
++
++ if(size > max_size) {
++ return -EINVAL;
++ }
++
++ vma->vm_flags |= VM_RESERVED;
++
++ if( remap_pfn_range(vma, vma->vm_start, page_frame_no,
++ size, vma->vm_page_prot)) {
++ printk(KERN_ERR "%s: mmap_error\n", __FUNCTION__);
++ return -EAGAIN;
++
++ }
++
++ return 0;
++}
++
++struct file_operations s3c_tvenc_fops = {
++ .owner = THIS_MODULE,
++ .open = s3c_tvenc_open,
++ .ioctl = s3c_tvenc_ioctl_v4l2,
++ .release = s3c_tvenc_release,
++ .read = s3c_tvenc_read,
++ .write = s3c_tvenc_write,
++ .mmap = s3c_tvenc_mmap,
++};
++
++void s3c_tvenc_vdev_release (struct video_device *vdev) {
++ kfree(vdev);
++}
++
++struct video_device tvencoder = {
++ .name = "TVENCODER",
++ .type = VID_TYPE_OVERLAY | VID_TYPE_CAPTURE | VID_TYPE_SCALES,
++ .type2 = V4L2_CAP_VIDEO_OUTPUT| V4L2_CAP_VIDEO_CAPTURE, /* V4L2 */
++ //.hardware = 0x01, // peter for 2.6.24 kernel
++ .fops = &s3c_tvenc_fops,
++ .release = s3c_tvenc_vdev_release,
++ .minor = TVENC_MINOR,
++};
++
++irqreturn_t s3c_tvenc_isr(int irq, void *dev_id,
++ struct pt_regs *regs)
++{
++ u32 mode;
++
++ mode = __raw_readl(base + S3C_TVCTRL);
++
++ // Clear FIFO under-run status pending bit
++ mode |= (1<<12);
++
++ __raw_writel(mode, base + S3C_TVCTRL);
++
++ wake_up_interruptible(&waitq);
++ return IRQ_HANDLED;
++}
++
++static int s3c_tvenc_probe(struct platform_device *pdev)
++{
++
++ struct resource *res;
++
++ int ret;
++
++ /* find the IRQs */
++ s3c_tvenc_irq = platform_get_irq(pdev, 0);
++ if(s3c_tvenc_irq <= 0) {
++ printk(KERN_ERR PFX "failed to get irq resouce\n");
++ return -ENOENT;
++ }
++
++ /* get the memory region for the tv scaler driver */
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if(res == NULL) {
++ printk(KERN_ERR PFX "failed to get memory region resouce\n");
++ return -ENOENT;
++ }
++
++ s3c_tvenc_mem = request_mem_region(res->start, res->end-res->start+1, pdev->name);
++ if(s3c_tvenc_mem == NULL) {
++ printk(KERN_ERR PFX "failed to reserve memory region\n");
++ return -ENOENT;
++ }
++
++
++ base = ioremap(s3c_tvenc_mem->start, s3c_tvenc_mem->end - res->start + 1);
++ if(s3c_tvenc_mem == NULL) {
++ printk(KERN_ERR PFX "failed ioremap\n");
++ return -ENOENT;
++ }
++
++ tvenc_clock = clk_get(&pdev->dev, "tv_encoder");
++ if(tvenc_clock == NULL) {
++ printk(KERN_ERR PFX "failed to find tvenc clock source\n");
++ return -ENOENT;
++ }
++
++ clk_enable(tvenc_clock);
++
++ h_clk = clk_get(&pdev->dev, "hclk");
++ if(h_clk == NULL) {
++ printk(KERN_ERR PFX "failed to find h_clk clock source\n");
++ return -ENOENT;
++ }
++
++ init_waitqueue_head(&waitq);
++
++ tv_param.v = video_device_alloc();
++ if(!tv_param.v) {
++ printk(KERN_ERR "s3c-tvenc: video_device_alloc() failed\n");
++ return -ENOMEM;
++ }
++ memcpy(tv_param.v, &tvencoder, sizeof(tvencoder));
++ if(video_register_device(tv_param.v, VFL_TYPE_GRABBER, TVENC_MINOR) != 0) {
++ printk("s3c_camera_driver.c : Couldn't register this codec driver.\n");
++ return 0;
++ }
++
++ ret = request_irq(s3c_tvenc_irq, s3c_tvenc_isr, SA_INTERRUPT,
++ "TV_ENCODER", NULL);
++ if (ret) {
++ printk("request_irq(TV_ENCODER) failed.\n");
++ return ret;
++ }
++
++ printk(" Success\n");
++ return 0;
++}
++
++static int s3c_tvenc_remove(struct platform_device *dev)
++{
++ printk(KERN_INFO "s3c_tvenc_remove called !\n");
++ clk_disable(tvenc_clock);
++ free_irq(s3c_tvenc_irq, NULL);
++ if (s3c_tvenc_mem != NULL) {
++ pr_debug("s3-tvenc: releasing s3c_tvenc_mem\n");
++ iounmap(base);
++ release_resource(s3c_tvenc_mem);
++ kfree(s3c_tvenc_mem);
++ }
++// video_unregister_device(tv_param.v);
++ return 0;
++}
++
++static int s3c_tvenc_suspend(struct platform_device *dev, pm_message_t state)
++{
++ clk_disable(tvenc_clock);
++ return 0;
++}
++
++static int s3c_tvenc_resume(struct platform_device *pdev)
++{
++ clk_enable(tvenc_clock);
++ return 0;
++}
++
++static struct platform_driver s3c_tvenc_driver = {
++ .probe = s3c_tvenc_probe,
++ .remove = s3c_tvenc_remove,
++ .suspend = s3c_tvenc_suspend,
++ .resume = s3c_tvenc_resume,
++ .driver = {
++ .owner = THIS_MODULE,
++ .name = "s3c-tvenc",
++ },
++};
++
++static char banner[] __initdata = KERN_INFO "S3C6410 TV encoder Driver, (c) 2008 Samsung Electronics\n";
++
++static int __init s3c_tvenc_init(void)
++{
++
++ printk(banner);
++
++ if(platform_driver_register(&s3c_tvenc_driver) != 0)
++ {
++ printk("Platform Device Register Failed \n");
++ return -1;
++ }
++
++ printk(" S3C6410 TV encoder Driver module init OK. \n");
++ return 0;
++}
++
++static void __exit s3c_tvenc_exit(void)
++{
++
++ video_unregister_device(tv_param.v);
++ platform_driver_unregister(&s3c_tvenc_driver);
++
++ printk("S3C6410 TV encoder Driver module exit. \n");
++}
++
++
++module_init(s3c_tvenc_init);
++module_exit(s3c_tvenc_exit);
++
++
++MODULE_AUTHOR("Peter, Oh");
++MODULE_DESCRIPTION("S3C TV Encoder Device Driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/media/video/s3c-tvenc.h b/drivers/media/video/s3c-tvenc.h
+new file mode 100644
+index 0000000..30a66a2
+--- /dev/null
++++ b/drivers/media/video/s3c-tvenc.h
+@@ -0,0 +1,165 @@
++#ifndef __S3CTVENC_H_
++#define __S3CTVENC_H_
++
++#include "s3c-tvscaler.h"
++
++
++#define TVENC_IOCTL_MAGIC 'T'
++
++typedef struct {
++
++} s3c_tvenc_info;
++
++#define TV_ON _IO(TVENC_IOCTL_MAGIC, 0)
++#define TV_OFF _IO(TVENC_IOCTL_MAGIC, 1)
++#define SELECT_TV_OUT_FORMAT _IO(TVENC_IOCTL_MAGIC, 2)
++
++#define TVENC_IOCTL_MAXNR 6
++
++#define TVENC_MINOR 14 // Just some number
++
++typedef enum {
++ OFF,
++ ON
++} tv_enc_switch_t;
++
++typedef enum {
++ NTSC_M,
++ PAL_M,
++ PAL_BGHID,
++ PAL_N,
++ PAL_NC,
++ PAL_60,
++ NTSC_443,
++ NTSC_J
++} tv_standard_t;
++
++typedef enum {
++ QCIF, CIF/*352x288*/,
++ QQVGA, QVGA, VGA, SVGA/*800x600*/, SXGA/*1280x1024*/, UXGA/*1600x1200*/, QXGA/*2048x1536*/,
++ WVGA/*854x480*/, HD720/*1280x720*/, HD1080/*1920x1080*/
++} img_size_t;
++
++typedef enum {
++ BLACKSTRETCH, WHITESTRETCH, BLUESTRETCH
++} stretch_color_t;
++
++typedef enum {
++ COMPOSITE, S_VIDEO
++} tv_conn_type_t;
++
++typedef enum {
++ BLACK, BLUE, RED, MAGENTA, GREEN, CYAN, YELLOW, WHITE
++} bg_color_t;
++
++typedef enum {
++ MUTE_Y, MUTE_CB, MUTE_CR
++} mute_type_t;
++
++typedef enum {
++ AGC4L, AGC2L, N01, N02, P01, P02
++} macro_pattern_t;
++
++typedef enum {
++ LCD_RGB, LCD_TV, LCD_I80F, LCD_I80S,
++ LCD_TVRGB, LCD_TVI80F, LCD_TVI80S
++} lcd_local_output_t;
++
++/* when App want to change v4l2 parameter,
++ * we instantly store it into v4l2_t v2
++ * and then reflect it to hardware
++ */
++typedef struct v4l2 {
++ struct v4l2_fmtdesc *fmtdesc;
++// struct v4l2_framebuffer frmbuf; /* current frame buffer */
++ struct v4l2_pix_format pixfmt;
++ struct v4l2_input *input;
++ struct v4l2_output *output;
++// enum v4l2_status status;
++} v4l2_t;
++
++
++typedef struct {
++ tv_standard_t sig_type;
++ tv_conn_type_t connect;
++ /* Width of input image. The input value is twice original output image
++ * width. For example, you must set 1440 when the image width is 720.
++ * Max value is 1440
++ */
++ unsigned int in_width;
++ /* Height of input image
++ * Max value is 576
++ */
++ unsigned int in_height;
++
++ // Setting value of VIDOUT[28:26] in Display
++ // controller(VIDCON0)
++ lcd_local_output_t lcd_output_mode;
++ // Set CLKVAL_F[13:6] of VIDCON0 with
++ // this value
++ unsigned int lcd_clkval_f;
++
++ // Flag of lcd rgb port
++ // 0 : disable, 1 : enable
++ unsigned int lcd_rgb_port_flag;
++
++ scaler_params_t sp;
++
++ struct video_device *v;
++ v4l2_t v2;
++
++} tv_out_params_t;
++
++#define V4L2_INPUT_TYPE_MSDMA 3
++#define V4L2_INPUT_TYPE_FIFO 4
++#define V4L2_OUTPUT_TYPE_MSDMA 4
++
++#define FORMAT_FLAGS_DITHER 0x01
++#define FORMAT_FLAGS_PACKED 0x02
++#define FORMAT_FLAGS_PLANAR 0x04
++#define FORMAT_FLAGS_RAW 0x08
++#define FORMAT_FLAGS_CrCb 0x10
++
++/****************************************************************
++* struct v4l2_control
++* Control IDs defined by S3C
++*****************************************************************/
++
++/* TV-OUT connector type */
++#define V4L2_CID_CONNECT_TYPE (V4L2_CID_PRIVATE_BASE+0)
++
++/****************************************************************
++* I O C T L C O D E S F O R V I D E O D E V I C E S
++* It's only for S3C
++*****************************************************************/
++#define VIDIOC_S_TVOUT_ON _IO ('V', BASE_VIDIOC_PRIVATE+0)
++#define VIDIOC_S_TVOUT_OFF _IO ('V', BASE_VIDIOC_PRIVATE+1)
++#define VIDIOC_S_SCALER_TEST _IO ('V', BASE_VIDIOC_PRIVATE+3)
++
++
++extern void s3c_tvscaler_config(scaler_params_t * sp);
++extern void s3c_tvscaler_int_enable(unsigned int int_type);
++extern void s3c_tvscaler_int_disable(void);
++extern void s3c_tvscaler_start(void);
++extern void s3c_tvscaler_stop_freerun(void);
++extern void s3c_tvscaler_init(void);
++extern void s3c_tvscaler_set_interlace(unsigned int on_off);
++extern int video_exclusive_release(struct inode * inode, struct file * file);
++extern int video_exclusive_open(struct inode * inode, struct file * file);
++
++#if 0 // peter for 2.6.21 kernel
++extern void s3c_fb_start_lcd(void);
++extern void s3c_fb_stop_lcd(void);
++extern void s3c_fb_set_output_path(int out);
++extern void s3c_fb_set_clkval(unsigned int clkval);
++extern void s3c_fb_enable_rgbport(unsigned int on_off);
++#else // peter for 2.6.24 kernel
++extern void s3cfb_start_lcd(void);
++extern void s3cfb_stop_lcd(void);
++extern void s3cfb_set_output_path(int out);
++extern void s3cfb_set_clock(unsigned int clkval);
++extern void s3cfb_enable_rgbport(unsigned int on_off);
++#endif
++
++
++#endif // __S3CTVENC_H_
+diff --git a/drivers/media/video/s3c-tvscaler.c b/drivers/media/video/s3c-tvscaler.c
+new file mode 100644
+index 0000000..376c866
+--- /dev/null
++++ b/drivers/media/video/s3c-tvscaler.c
+@@ -0,0 +1,802 @@
++
++/*
++ * linux/drivers/tvenc/s3c-tvscaler.c
++ *
++ * Revision 1.0
++ *
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file COPYING in the main directory of this archive for
++ * more details.
++ *
++ * S3C TV Scaler driver
++ *
++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/types.h>
++#include <linux/timer.h>
++#include <linux/kernel.h>
++#include <linux/fs.h>
++#include <linux/platform_device.h>
++#include <linux/interrupt.h>
++#include <linux/clk.h>
++#include <linux/delay.h>
++#include <asm/uaccess.h>
++#include <linux/errno.h> /* error codes */
++#include <asm/div64.h>
++#include <linux/mm.h>
++#include <linux/tty.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/hardware.h>
++#include <asm/uaccess.h>
++#include <asm/arch/map.h>
++#include <linux/miscdevice.h>
++
++#include <linux/version.h>
++#if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,16)
++#include <linux/config.h>
++#include <asm/arch/registers.h>
++#else
++#include <asm/arch/regs-tvscaler.h>
++#include <asm/arch/regs-s3c6400-clock.h>
++#endif
++
++#include "s3c-tvscaler.h"
++
++#define PFX "s3c_tv_scaler"
++
++#define SINGLE_BUF 1 // Single buffer mode
++
++
++static struct clk *h_clk;
++static struct clk *tvscaler_clock;
++static void __iomem *base;
++static int s3c_tvscaler_irq = NO_IRQ;
++static struct resource *s3c_tvscaler_mem;
++
++
++//static unsigned char *addr_start_y;
++//static unsigned char *addr_start_rgb;
++
++static wait_queue_head_t waitq;
++
++irqreturn_t s3c_tvscaler_isr(int irq, void *dev_id,
++ struct pt_regs *regs)
++{
++ u32 mode;
++ mode = __raw_readl(base + S3C_MODE);
++ mode &= ~(1 << 6); /* Clear Source in POST Processor */
++ __raw_writel(mode, base + S3C_MODE);
++
++// wake_up_interruptible(&waitq);
++ return IRQ_HANDLED;
++}
++
++#if 0
++static buff_addr_t buf_addr = { NULL };
++
++
++static u32 post_alloc_pre_buff(scaler_params_t *sp)
++{
++ u32 size;
++
++#ifdef USE_DEDICATED_MEM
++
++ buf_addr.pre_phy_addr = PHYS_OFFSET + (SYSTEM_RAM - RESERVE_POST_MEM);
++ buf_addr.pre_virt_addr = ioremap_nocache(buf_addr.pre_phy_addr, PRE_BUFF_SIZE);
++ if( !buf_addr.pre_virt_addr ) {
++ printk(KERN_ERR "%s: Failed to allocate pre buffer \n",__FUNCTION__);
++ return -ENOMEM;
++ }
++
++ sp->SrcFrmSt = buf_addr.pre_phy_addr;
++#else
++ size = sp->SrcWidth * sp->SrcHeight * 2;
++ addr_start_y = kmalloc(size, GFP_DMA);
++ if(addr_start_y != NULL) return -ENOMEM;
++#endif
++ return 0;
++}
++
++static u32 post_alloc_post_buff(scaler_params_t *sp)
++{
++ u32 size;
++
++#ifdef USE_DEDICATED_MEM
++
++ buf_addr.post_phy_addr = PHYS_OFFSET + (SYSTEM_RAM - RESERVE_POST_MEM + PRE_BUFF_SIZE);
++ buf_addr.post_virt_addr = ioremap_nocache(buf_addr.post_phy_addr, POST_BUFF_SIZE);
++ if( !buf_addr.post_virt_addr ) {
++ printk(KERN_ERR "%s: Failed to allocate post buffer \n",__FUNCTION__);
++ return -ENOMEM;
++ }
++
++ sp->DstFrmSt = buf_addr.post_phy_addr;
++#else
++ size = sp->DstWidth * sp->DstHeight * 2;
++ addr_start_rgb = kmalloc(size, GFP_DMA);
++ if(addr_start_rgb != NULL) return -ENOMEM;
++#endif
++ return 0;
++}
++
++static u32 post_free_all_buffer(void)
++{
++#ifdef USE_DEDICATED_MEM
++ if( buf_addr.pre_virt_addr ) {
++ iounmap(buf_addr.pre_virt_addr);
++ }
++ if( buf_addr.post_virt_addr ) {
++ iounmap(buf_addr.post_virt_addr);
++ }
++#endif
++ return 0;
++}
++#endif
++
++static void s3c_tvscaler_set_clk_src(scaler_clk_src_t clk_src)
++{
++ u32 tmp, rate;
++
++ tmp = __raw_readl(base + S3C_MODE);
++
++ h_clk = clk_get(NULL, "hclk");
++
++ rate = clk_get_rate(h_clk);
++
++ if(clk_src == HCLK) {
++ if(rate > 66000000) {
++ tmp &= ~(0x7f<<23);
++ tmp |= (1<<24);
++ tmp |= (1<<23);
++ } else {
++ tmp &=~ (0x7f<<23);
++ }
++
++ } else if(clk_src == PLL_EXT) {
++ } else {
++ tmp &=~(0x7f<<23);
++ }
++
++ tmp = (tmp &~ (0x3<<21)) | (clk_src<<21);
++
++ __raw_writel(tmp, base + S3C_MODE);
++}
++
++static void s3c_tvscaler_set_fmt(cspace_t src, cspace_t dst, s3c_scaler_path_t in,
++ s3c_scaler_path_t out, u32 *in_pixel_size,
++ u32 *out_pixel_size)
++{
++ u32 tmp;
++
++ tmp = __raw_readl(base + S3C_MODE);
++ tmp |= (0x1<<16);
++ tmp |= (0x2<<10);
++
++ if(in == POST_DMA) {
++
++ switch(src) {
++ case YC420:
++ tmp &=~((0x1<<3)|(0x1<<2));
++ tmp |= (0x1<<8)|(0x1<<1);
++ *in_pixel_size = 1;
++ break;
++ case CRYCBY:
++ tmp &= ~((0x1<<15)|(0x1<<8)|(0x1<<3)|(0x1<<0));
++ tmp |= (0x1<<2)|(0x1<<1);
++ *in_pixel_size = 2;
++ break;
++ case CBYCRY:
++ tmp &= ~((0x1<<8)|(0x1<<3)|(0x1<<0));
++ tmp |= (0x1<<15)|(0x1<<2)|(0x1<<1);
++ *in_pixel_size = 2;
++ break;
++ case YCRYCB:
++ tmp &= ~((0x1<<15)|(0x1<<8)|(0x1<<3));
++ tmp |= (0x1<<2)|(0x1<<1)|(0x1<<0);
++ *in_pixel_size = 2;
++ break;
++ case YCBYCR:
++ tmp &= ~((0x1<<8)|(0x1<<3));
++ tmp |= (0x1<<15)|(0x1<<2)|(0x1<<1)|(0x1<<0);
++ *in_pixel_size = 2;
++ break;
++ case RGB24:
++ tmp &= ~(0x1<<8);
++ tmp |= (0x1<<3)|(0x1<<2)|(0x1<<1);
++ *in_pixel_size = 4;
++ break;
++ case RGB16:
++ tmp &= ~((0x1<<8)|(0x1<<1));
++ tmp |= (0x1<<3)|(0x1<<2);
++ *in_pixel_size = 2;
++ break;
++ default:
++ break;
++ }
++
++ }
++ else if(in == POST_FIFO) {
++ }
++
++ if(out == POST_DMA) {
++ switch(dst) {
++ case YC420:
++ tmp &= ~(0x1<<18);
++ tmp |= (0x1<<17);
++ *out_pixel_size = 1;
++ break;
++ case CRYCBY:
++ tmp &= ~((0x1<<20)|(0x1<<19)|(0x1<<18)|(0x1<<17));
++ *out_pixel_size = 2;
++ break;
++ case CBYCRY:
++ tmp &= ~((0x1<<19)|(0x1<<18)|(0x1<<17));
++ tmp |= (0x1<<20);
++ *out_pixel_size = 2;
++ break;
++ case YCRYCB:
++ tmp &= ~((0x1<<20)|(0x1<<18)|(0x1<<17));
++ tmp |= (0x1<<19);
++ *out_pixel_size = 2;
++ break;
++ case YCBYCR:
++ tmp &= ~((0x1<<18)|(0x1<<17));
++ tmp |= (0x1<<20)|(0x1<<19);
++ *out_pixel_size = 2;
++ break;
++ case RGB24:
++ tmp |= (0x1<<18)|(0x1<<4);
++ *out_pixel_size = 4;
++ break;
++ case RGB16:
++ tmp &= ~(0x1<<4);
++ tmp |= (0x1<<18);
++ *out_pixel_size = 2;
++ break;
++ default:
++ break;
++ }
++ }
++ else if(out == POST_FIFO) {
++ if(dst == RGB24) {
++ tmp |= (0x1<<18)|(0x1<<13);
++
++ } else if(dst == YCBYCR) {
++ tmp |= (0x1<<13);
++ tmp &= ~(0x1<<18)|(0x1<<17);
++ } else {
++ }
++ }
++
++ __raw_writel(tmp, base + S3C_MODE);
++}
++
++static void s3c_tvscaler_set_path(s3c_scaler_path_t in, s3c_scaler_path_t out)
++{
++ u32 tmp;
++
++ tmp = __raw_readl(base + S3C_MODE);
++
++ tmp &=~(0x1<<12); // 0: progressive mode, 1: interlace mode
++
++ if(in == POST_FIFO) {
++ tmp |= (0x1<<31);
++ } else if(in == POST_DMA) {
++ tmp &=~(0x1<<31);
++ }
++
++ if(out == POST_FIFO) {
++ tmp |= (0x1<<13);
++ } else if(out == POST_DMA) {
++ tmp &=~(0x1<<13);
++ }
++
++ __raw_writel(tmp, base + S3C_MODE);
++}
++
++static void s3c_tvscaler_set_addr(scaler_params_t *sp, u32 in_pixel_size, u32 out_pixel_size)
++{
++ u32 offset_y, offset_cb, offset_cr;
++ u32 src_start_y, src_start_cb, src_start_cr;
++ u32 src_end_y, src_end_cb, src_end_cr;
++ u32 start_pos_y, end_pos_y;
++ u32 start_pos_cb, end_pos_cb;
++ u32 start_pos_cr, end_pos_cr;
++ u32 start_pos_rgb, end_pos_rgb;
++ u32 dst_start_rgb, dst_end_rgb;
++ u32 src_frm_start_addr;
++
++ u32 offset_rgb, out_offset_cb, out_offset_cr;
++ u32 out_start_pos_cb, out_start_pos_cr;
++ u32 out_end_pos_cb, out_end_pos_cr;
++ u32 out_src_start_cb, out_src_start_cr;
++ u32 out_src_end_cb, out_src_end_cr;
++
++ if(sp->InPath == POST_DMA) {
++ offset_y = (sp->SrcFullWidth - sp->SrcWidth) * in_pixel_size;
++ start_pos_y = (sp->SrcFullWidth*sp->SrcStartY+sp->SrcStartX)*in_pixel_size;
++ end_pos_y = sp->SrcWidth*sp->SrcHeight*in_pixel_size + offset_y*(sp->SrcHeight-1);
++ src_frm_start_addr = sp->SrcFrmSt;
++ src_start_y = sp->SrcFrmSt + start_pos_y;
++ src_end_y = src_start_y + end_pos_y;
++
++ __raw_writel(src_start_y, base + S3C_ADDRSTART_Y);
++ __raw_writel(offset_y, base + S3C_OFFSET_Y);
++ __raw_writel(src_end_y, base + S3C_ADDREND_Y);
++
++ if(sp->SrcCSpace == YC420) {
++ offset_cb = offset_cr = ((sp->SrcFullWidth - sp->SrcWidth) / 2) * in_pixel_size;
++ start_pos_cb = sp->SrcFullWidth * sp->SrcFullHeight * 1 \
++ + (sp->SrcFullWidth * sp->SrcStartY / 2 + sp->SrcStartX) /2 * 1;
++
++ end_pos_cb = sp->SrcWidth/2*sp->SrcHeight/2*in_pixel_size \
++ + (sp->SrcHeight/2 -1)*offset_cb;
++ start_pos_cr = sp->SrcFullWidth * sp->SrcFullHeight *1 \
++ + sp->SrcFullWidth*sp->SrcFullHeight/4 *1 \
++ + (sp->SrcFullWidth*sp->SrcStartY/2 + sp->SrcStartX)/2*1;
++ end_pos_cr = sp->SrcWidth/2*sp->SrcHeight/2*in_pixel_size \
++ + (sp->SrcHeight/2-1)*offset_cr;
++
++ src_start_cb = sp->SrcFrmSt + start_pos_cb;
++ src_end_cb = src_start_cb + end_pos_cb;
++
++ src_start_cr = sp->SrcFrmSt + start_pos_cr;
++ src_end_cr = src_start_cr + end_pos_cr;
++
++ __raw_writel(src_start_cb, base + S3C_ADDRSTART_CB);
++ __raw_writel(offset_cr, base + S3C_OFFSET_CB);
++ __raw_writel(src_end_cb, base + S3C_ADDREND_CB);
++ __raw_writel(src_start_cr, base + S3C_ADDRSTART_CR);
++ __raw_writel(offset_cb, base + S3C_OFFSET_CR);
++ __raw_writel(src_end_cr, base + S3C_ADDREND_CR);
++ }
++ }
++ if(sp->OutPath == POST_DMA) {
++ offset_rgb = (sp->DstFullWidth - sp->DstWidth)*out_pixel_size;
++ start_pos_rgb = (sp->DstFullWidth*sp->DstStartY + sp->DstStartX)*out_pixel_size;
++ end_pos_rgb = sp->DstWidth*sp->DstHeight*out_pixel_size + offset_rgb*(sp->DstHeight - 1);
++ dst_start_rgb = sp->DstFrmSt + start_pos_rgb;
++ dst_end_rgb = dst_start_rgb + end_pos_rgb;
++
++ __raw_writel(dst_start_rgb, base + S3C_ADDRSTART_RGB);
++ __raw_writel(offset_rgb, base + S3C_OFFSET_RGB);
++ __raw_writel(dst_end_rgb, base + S3C_ADDREND_RGB);
++
++ if(sp->DstCSpace == YC420) {
++ out_offset_cb = out_offset_cr = ((sp->DstFullWidth - sp->DstWidth)/2)*out_pixel_size;
++ out_start_pos_cb = sp->DstFullWidth*sp->DstFullHeight*1 \
++ + (sp->DstFullWidth*sp->DstStartY/2 + sp->DstStartX)/2*1;
++ out_end_pos_cb = sp->DstWidth/2*sp->DstHeight/2*out_pixel_size \
++ + (sp->DstHeight/2 -1)*out_offset_cr;
++
++ out_start_pos_cr = sp->DstFullWidth*sp->DstFullHeight*1 \
++ + (sp->DstFullWidth*sp->DstFullHeight/4)*1 \
++ + (sp->DstFullWidth*sp->DstStartY/2 +sp->DstStartX)/2*1;
++ out_end_pos_cr = sp->DstWidth/2*sp->DstHeight/2*out_pixel_size \
++ + (sp->DstHeight/2 -1)*out_offset_cb;
++
++ out_src_start_cb = sp->DstFrmSt + out_start_pos_cb;
++ out_src_end_cb = out_src_start_cb + out_end_pos_cb;
++ out_src_start_cr = sp->DstFrmSt + out_start_pos_cr;
++ out_src_end_cr = out_src_start_cr + out_end_pos_cr;
++
++ __raw_writel(out_src_start_cb, base + S3C_ADDRSTART_OCB);
++ __raw_writel(out_offset_cb, base + S3C_OFFSET_OCB);
++ __raw_writel(out_src_end_cb, base + S3C_ADDREND_OCB);
++ __raw_writel(out_src_start_cr, base + S3C_ADDRSTART_OCR);
++ __raw_writel(out_offset_cr, base + S3C_OFFSET_OCR);
++ __raw_writel(out_src_end_cr, base + S3C_ADDREND_OCR);
++
++ }
++ }
++
++
++}
++
++#if 0
++static void s3c_tvscaler_set_fifo_in(s3c_scaler_path_t in_path)
++{
++ u32 tmp;
++
++ tmp = __raw_readl(base + S3C_MODE);
++
++ if(in_path == POST_FIFO) tmp |= (0x1<<31);
++ else tmp &=~(0x1<<31);
++
++ __raw_writel(tmp, base + S3C_MODE);
++
++}
++#endif
++
++void s3c_tvscaler_set_interlace(u32 on_off)
++{
++ u32 tmp;
++
++ tmp = __raw_readl(base + S3C_MODE);
++
++ if(on_off == 1) tmp |=(1<<12);
++ else tmp &=~(1<<12);
++
++ __raw_writel(tmp, base + S3C_MODE);
++}
++EXPORT_SYMBOL(s3c_tvscaler_set_interlace);
++
++static void s3c_tvscaler_set_size(scaler_params_t *sp)
++{
++ u32 pre_h_ratio, pre_v_ratio, h_shift, v_shift, sh_factor;
++ u32 pre_dst_width, pre_dst_height, dx, dy;
++
++ if (sp->SrcWidth >= (sp->DstWidth<<6)) {
++ printk("Out of PreScalar range !!!\n");
++ return;
++ }
++ if(sp->SrcWidth >= (sp->DstWidth<<5)) {
++ pre_h_ratio = 32;
++ h_shift = 5;
++ } else if(sp->SrcWidth >= (sp->DstWidth<<4)) {
++ pre_h_ratio = 16;
++ h_shift = 4;
++ } else if(sp->SrcWidth >= (sp->DstWidth<<3)) {
++ pre_h_ratio = 8;
++ h_shift = 3;
++ } else if(sp->SrcWidth >= (sp->DstWidth<<2)) {
++ pre_h_ratio = 4;
++ h_shift = 2;
++ } else if(sp->SrcWidth >= (sp->DstWidth<<1)) {
++ pre_h_ratio = 2;
++ h_shift = 1;
++ } else {
++ pre_h_ratio = 1;
++ h_shift = 0;
++ }
++
++ pre_dst_width = sp->SrcWidth / pre_h_ratio;
++ dx = (sp->SrcWidth<<8) / (sp->DstWidth<<h_shift);
++
++
++ if (sp->SrcHeight >= (sp->DstHeight<<6)) {
++ printk("Out of PreScalar range !!!\n");
++ return;
++ }
++ if(sp->SrcHeight>= (sp->DstHeight<<5)) {
++ pre_v_ratio = 32;
++ v_shift = 5;
++ } else if(sp->SrcHeight >= (sp->DstHeight<<4)) {
++ pre_v_ratio = 16;
++ v_shift = 4;
++ } else if(sp->SrcHeight >= (sp->DstHeight<<3)) {
++ pre_v_ratio = 8;
++ v_shift = 3;
++ } else if(sp->SrcHeight >= (sp->DstHeight<<2)) {
++ pre_v_ratio = 4;
++ v_shift = 2;
++ } else if(sp->SrcHeight >= (sp->DstHeight<<1)) {
++ pre_v_ratio = 2;
++ v_shift = 1;
++ } else {
++ pre_v_ratio = 1;
++ v_shift = 0;
++ }
++
++ pre_dst_height = sp->SrcHeight / pre_v_ratio;
++ dy = (sp->SrcHeight<<8) / (sp->DstHeight<<v_shift);
++ sh_factor = 10 - (h_shift + v_shift);
++
++ __raw_writel((pre_v_ratio<<7)|(pre_h_ratio<<0), base + S3C_PRESCALE_RATIO);
++ __raw_writel((pre_dst_height<<12)|(pre_dst_width<<0), base + S3C_PRESCALEIMGSIZE);
++ __raw_writel(sh_factor, base + S3C_PRESCALE_SHFACTOR);
++ __raw_writel(dx, base + S3C_MAINSCALE_H_RATIO);
++ __raw_writel(dy, base + S3C_MAINSCALE_V_RATIO);
++ __raw_writel((sp->SrcHeight<<12)|(sp->SrcWidth), base + S3C_SRCIMGSIZE);
++ __raw_writel((sp->DstHeight<<12)|(sp->DstWidth), base + S3C_DSTIMGSIZE);
++
++}
++
++
++static void s3c_tvscaler_set_auto_load(scaler_params_t *sp)
++{
++ u32 tmp;
++
++ tmp = __raw_readl(base + S3C_MODE);
++
++ if(sp->Mode == FREE_RUN) {
++ tmp |= (1<<14);
++ } else if(sp->Mode == ONE_SHOT) {
++ tmp &=~(1<<14);
++ }
++
++ __raw_writel(tmp, base + S3C_MODE);
++
++}
++
++void s3c_tvscaler_set_base_addr(void __iomem * base_addr)
++{
++ base = base_addr;
++}
++EXPORT_SYMBOL(s3c_tvscaler_set_base_addr);
++
++void s3c_tvscaler_free_base_addr(void)
++{
++ base = NULL;
++}
++EXPORT_SYMBOL(s3c_tvscaler_free_base_addr);
++
++void s3c_tvscaler_int_enable(u32 int_type)
++{
++ u32 tmp;
++
++ tmp = __raw_readl(base + S3C_MODE);
++
++ if(int_type == 0) { //Edge triggering
++ tmp &= ~(S3C_MODE_IRQ_LEVEL);
++ } else if(int_type == 1) { //level triggering
++ tmp |= S3C_MODE_IRQ_LEVEL;
++ }
++
++ tmp |= S3C_MODE_POST_INT_ENABLE;
++
++ __raw_writel(tmp, base + S3C_MODE);
++}
++EXPORT_SYMBOL(s3c_tvscaler_int_enable);
++
++void s3c_tvscaler_int_disable(void)
++{
++ u32 tmp;
++
++ tmp = __raw_readl(base + S3C_MODE);
++
++ tmp &=~ (S3C_MODE_POST_INT_ENABLE);
++
++ __raw_writel(tmp, base + S3C_MODE);
++
++}
++EXPORT_SYMBOL(s3c_tvscaler_int_disable);
++
++
++void s3c_tvscaler_start(void)
++{
++ __raw_writel(S3C_POSTENVID_ENABLE, base + S3C_POSTENVID);
++
++}
++EXPORT_SYMBOL(s3c_tvscaler_start);
++
++void s3c_tvscaler_stop_freerun(void)
++{
++ u32 tmp;
++
++ tmp = __raw_readl(base + S3C_MODE);
++
++ tmp &=~(1<<14);
++
++ __raw_writel(tmp, base + S3C_MODE);
++}
++EXPORT_SYMBOL(s3c_tvscaler_stop_freerun);
++
++
++void s3c_tvscaler_config(scaler_params_t *sp)
++{
++ u32 tmp = 0;
++ u32 in_pixel_size = 0;
++ u32 out_pixel_size = 0;
++ u32 loop = 0;
++
++ tmp = __raw_readl(base + S3C_POSTENVID);
++ tmp &= ~S3C_POSTENVID_ENABLE;
++ __raw_writel(tmp, base + S3C_POSTENVID);
++#ifdef SINGLE_BUF
++ tmp = S3C_MODE2_ADDR_CHANGE_DISABLE |S3C_MODE2_CHANGE_AT_FRAME_END |S3C_MODE2_SOFTWARE_TRIGGER;
++#else
++ tmp = S3C_MODE2_ADDR_CHANGE_ENABLE |S3C_MODE2_CHANGE_AT_FRAME_END |S3C_MODE2_SOFTWARE_TRIGGER;
++#endif
++ __raw_writel(tmp, base + S3C_MODE2);
++
++// peter mod. start
++ sp->DstStartX = sp->DstStartY = 0;
++ sp->DstWidth = sp->DstFullWidth;
++ sp->DstHeight = sp->DstFullHeight;
++// peter mod. end
++
++ sp->DstFrmSt = ( POST_BUFF_BASE_ADDR + PRE_BUFF_SIZE );
++ //printk("\n---peter s3c_tvscaler_config : SrcFrmSt = 0x%08x\n", sp->SrcFrmSt);
++ //printk("---peter s3c_tvscaler_config : DstFrmSt = 0x%08x\n", sp->DstFrmSt);
++
++ s3c_tvscaler_set_clk_src(HCLK);
++
++ s3c_tvscaler_set_path(sp->InPath, sp->OutPath);
++
++ s3c_tvscaler_set_fmt(sp->SrcCSpace, sp->DstCSpace, sp->InPath,
++ sp->OutPath, &in_pixel_size, &out_pixel_size);
++
++ s3c_tvscaler_set_size(sp);
++
++ s3c_tvscaler_set_addr(sp, in_pixel_size, out_pixel_size);
++
++ s3c_tvscaler_set_auto_load(sp);
++
++}
++EXPORT_SYMBOL(s3c_tvscaler_config);
++
++void s3c_tvscaler_set_param(scaler_params_t *sp)
++{
++#if 0
++ param.SrcFullWidth = sp->SrcFullWidth;
++ param.SrcFullHeight = sp->SrcFullHeight;
++ param.SrcStartX = sp->SrcStartX;
++ param.SrcStartY = sp->SrcStartY;
++ param.SrcWidth = sp->SrcWidth;
++ param.SrcHeight = sp->SrcHeight;
++ param.SrcFrmSt = sp->SrcFrmSt;
++ param.SrcCSpace = sp->SrcCSpace;
++ param.DstFullWidth = sp->DstFullWidth;
++ param.DstFullHeight = sp->DstFullHeight;
++ param.DstStartX = sp->DstStartX;
++ param.DstStartY = sp->DstStartY;
++ param.DstWidth = sp->DstWidth;
++ param.DstHeight = sp->DstHeight;
++ param.DstFrmSt = sp->DstFrmSt;
++ param.DstCSpace = sp->DstCSpace;
++ param.SrcFrmBufNum = sp->SrcFrmBufNum;
++ param.DstFrmSt = sp->DstFrmSt;
++ param.Mode = sp->Mode;
++ param.InPath = sp->InPath;
++ param.OutPath = sp->OutPath;
++#endif
++}
++EXPORT_SYMBOL(s3c_tvscaler_set_param);
++
++void s3c_tvscaler_init(void)
++{
++
++ int tmp;
++
++ // Use DOUTmpll source clock as a scaler clock
++ tmp = __raw_readl(S3C_CLK_SRC);
++
++ tmp &=~(0x3<<28);
++ tmp |= (0x1<<28);
++ __raw_writel(tmp, S3C_CLK_SRC);
++
++ printk(" %s \n", __FUNCTION__);
++
++}
++EXPORT_SYMBOL(s3c_tvscaler_init);
++
++
++static int s3c_tvscaler_probe(struct platform_device *pdev)
++{
++
++ struct resource *res;
++
++ int ret;
++
++ /* find the IRQs */
++ s3c_tvscaler_irq = platform_get_irq(pdev, 0);
++ if(s3c_tvscaler_irq <= 0) {
++ printk(KERN_ERR PFX "failed to get irq resouce\n");
++ return -ENOENT;
++ }
++
++ /* get the memory region for the tv scaler driver */
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if(res == NULL) {
++ printk(KERN_ERR PFX "failed to get memory region resouce\n");
++ return -ENOENT;
++ }
++
++ s3c_tvscaler_mem = request_mem_region(res->start, res->end-res->start+1, pdev->name);
++ if(s3c_tvscaler_mem == NULL) {
++ printk(KERN_ERR PFX "failed to reserve memory region\n");
++ return -ENOENT;
++ }
++
++ base = ioremap(s3c_tvscaler_mem->start, s3c_tvscaler_mem->end - res->start + 1);
++ if(s3c_tvscaler_mem == NULL) {
++ printk(KERN_ERR PFX "failed ioremap\n");
++ return -ENOENT;
++ }
++
++ tvscaler_clock = clk_get(&pdev->dev, "tv_encoder");
++ if(tvscaler_clock == NULL) {
++ printk(KERN_ERR PFX "failed to find tvscaler clock source\n");
++ return -ENOENT;
++ }
++
++ clk_enable(tvscaler_clock);
++
++ h_clk = clk_get(&pdev->dev, "hclk");
++ if(h_clk == NULL) {
++ printk(KERN_ERR PFX "failed to find h_clk clock source\n");
++ return -ENOENT;
++ }
++
++ init_waitqueue_head(&waitq);
++
++ ret = request_irq(s3c_tvscaler_irq, s3c_tvscaler_isr, SA_INTERRUPT,
++ "TV_SCALER", NULL);
++ if (ret) {
++ printk("request_irq(TV_SCALER) failed.\n");
++ return ret;
++ }
++
++ printk(" Success\n");
++
++ return 0;
++}
++
++static int s3c_tvscaler_remove(struct platform_device *dev)
++{
++ printk(KERN_INFO "s3c_tvscaler_remove called !\n");
++ clk_disable(tvscaler_clock);
++ free_irq(s3c_tvscaler_irq, NULL);
++ if (s3c_tvscaler_mem != NULL) {
++ pr_debug("s3-tvscaler: releasing s3c_tvscaler_mem\n");
++ iounmap(base);
++ release_resource(s3c_tvscaler_mem);
++ kfree(s3c_tvscaler_mem);
++ }
++
++ return 0;
++}
++
++static int s3c_tvscaler_suspend(struct platform_device *dev, pm_message_t state)
++{
++ clk_disable(tvscaler_clock);
++ return 0;
++}
++
++static int s3c_tvscaler_resume(struct platform_device *pdev)
++{
++ clk_enable(tvscaler_clock);
++ return 0;
++}
++
++static struct platform_driver s3c_tvscaler_driver = {
++ .probe = s3c_tvscaler_probe,
++ .remove = s3c_tvscaler_remove,
++ .suspend = s3c_tvscaler_suspend,
++ .resume = s3c_tvscaler_resume,
++ .driver = {
++ .owner = THIS_MODULE,
++ .name = "s3c-tvscaler",
++ },
++};
++
++static char banner[] __initdata = KERN_INFO "S3C6410 TV scaler Driver, (c) 2008 Samsung Electronics\n";
++
++
++int __init s3c_tvscaler_pre_init(void)
++{
++
++ printk(banner);
++
++ if(platform_driver_register(&s3c_tvscaler_driver) != 0)
++ {
++ printk("platform device register Failed \n");
++ return -1;
++ }
++
++ printk(" S3C6410 TV scaler Driver module init OK. \n");
++
++ return 0;
++}
++
++void s3c_tvscaler_exit(void)
++{
++ platform_driver_unregister(&s3c_tvscaler_driver);
++ printk("S3C: tvscaler module exit\n");
++}
++
++module_init(s3c_tvscaler_pre_init);
++module_exit(s3c_tvscaler_exit);
++
++
++MODULE_AUTHOR("Peter, Oh");
++MODULE_DESCRIPTION("S3C TV Controller Device Driver");
++MODULE_LICENSE("GPL");
++
++
+diff --git a/drivers/media/video/s3c-tvscaler.h b/drivers/media/video/s3c-tvscaler.h
+new file mode 100644
+index 0000000..d8079a3
+--- /dev/null
++++ b/drivers/media/video/s3c-tvscaler.h
+@@ -0,0 +1,96 @@
++#ifndef __S3CTVSCALER_H_
++#define __S3CTVSCALER_H_
++
++#include <asm-arm/arch-s3c2410/reserved_mem.h>
++
++#define TVSCALER_IOCTL_MAGIC 'S'
++
++#define PPROC_SET_PARAMS _IO(TVSCALER_IOCTL_MAGIC, 0)
++#define PPROC_START _IO(TVSCALER_IOCTL_MAGIC, 1)
++#define PPROC_STOP _IO(TVSCALER_IOCTL_MAGIC, 2)
++#define PPROC_INTERLACE_MODE _IO(TVSCALER_IOCTL_MAGIC, 3)
++#define PPROC_PROGRESSIVE_MODE _IO(TVSCALER_IOCTL_MAGIC, 4)
++
++
++#define QVGA_XSIZE 320
++#define QVGA_YSIZE 240
++
++#define LCD_XSIZE 320
++#define LCD_YSIZE 240
++
++#define SCALER_MINOR 251 // Just some number
++
++
++//#define SYSTEM_RAM 0x08000000 // 128mb
++#define SYSTEM_RAM 0x07800000 // 120mb
++#define RESERVE_POST_MEM 8*1024*1024 // 8mb
++#define PRE_BUFF_SIZE 4*1024*1024 //4 // 4mb
++#define POST_BUFF_SIZE ( RESERVE_POST_MEM - PRE_BUFF_SIZE )
++#if 0
++#define POST_BUFF_BASE_ADDR (0x50000000 + (SYSTEM_RAM - RESERVE_POST_MEM))
++#else // TV_RESERVED_MEM_START is defined in the s3c-linux-2.6.21_dev_4_4_15
++#define POST_BUFF_BASE_ADDR TV_RESERVED_MEM_START
++#endif
++
++#define USE_DEDICATED_MEM 1
++
++typedef enum {
++ INTERLACE_MODE,
++ PROGRESSIVE_MODE
++} s3c_scaler_scan_mode_t;
++
++typedef enum {
++ POST_DMA, POST_FIFO
++} s3c_scaler_path_t;
++
++typedef enum {
++ ONE_SHOT, FREE_RUN
++} s3c_scaler_run_mode_t;
++
++typedef enum {
++ PAL1, PAL2, PAL4, PAL8,
++ RGB8, ARGB8, RGB16, ARGB16, RGB18, RGB24, RGB30, ARGB24,
++ YC420, YC422, // Non-interleave
++ CRYCBY, CBYCRY, YCRYCB, YCBYCR, YUV444 // Interleave
++} cspace_t;
++
++typedef enum
++{
++ HCLK = 0, PLL_EXT = 1, EXT_27MHZ = 3
++} scaler_clk_src_t;
++
++typedef struct{
++ unsigned int SrcFullWidth; // Source Image Full Width(Virtual screen size)
++ unsigned int SrcFullHeight; // Source Image Full Height(Virtual screen size)
++ unsigned int SrcStartX; // Source Image Start width offset
++ unsigned int SrcStartY; // Source Image Start height offset
++ unsigned int SrcWidth; // Source Image Width
++ unsigned int SrcHeight; // Source Image Height
++ unsigned int SrcFrmSt; // Base Address of the Source Image : Physical Address
++ cspace_t SrcCSpace; // Color Space ot the Source Image
++
++ unsigned int DstFullWidth; // Source Image Full Width(Virtual screen size)
++ unsigned int DstFullHeight; // Source Image Full Height(Virtual screen size)
++ unsigned int DstStartX; // Source Image Start width offset
++ unsigned int DstStartY; // Source Image Start height offset
++ unsigned int DstWidth; // Source Image Width
++ unsigned int DstHeight; // Source Image Height
++ unsigned int DstFrmSt; // Base Address of the Source Image : Physical Address
++ cspace_t DstCSpace; // Color Space ot the Source Image
++
++ unsigned int SrcFrmBufNum; // Frame buffer number
++ s3c_scaler_run_mode_t Mode; // POST running mode(PER_FRAME or FREE_RUN)
++ s3c_scaler_path_t InPath; // Data path of the source image
++ s3c_scaler_path_t OutPath; // Data path of the desitination image
++
++}scaler_params_t;
++
++typedef struct{
++ unsigned int pre_phy_addr;
++ unsigned char *pre_virt_addr;
++
++ unsigned int post_phy_addr;
++ unsigned char *post_virt_addr;
++} buff_addr_t;
++
++#endif //__S3CTVSCALER_H_
+diff --git a/drivers/media/video/samsung/Makefile b/drivers/media/video/samsung/Makefile
+index ede0269..885512c 100644
+--- a/drivers/media/video/samsung/Makefile
++++ b/drivers/media/video/samsung/Makefile
+@@ -7,5 +7,3 @@ obj-$(CONFIG_VIDEO_SAMSUNG_S5K4BA) += 4xa_sensor.o
+ obj-$(CONFIG_VIDEO_ADV7180) += adv7180.o
+ obj-$(CONFIG_VIDEO_APTINA_MT9P012) += mt9p012.o
+
+-obj-$(CONFIG_VIDEO_SAMSUNG_TVENC) += s3c_tvenc.o
+-obj-$(CONFIG_VIDEO_SAMSUNG_TVSCALER) += s3c_tvenc.o
+diff --git a/drivers/media/video/samsung/s3c-tvenc.c b/drivers/media/video/samsung/s3c-tvenc.c
+deleted file mode 100644
+index 11dfd37..0000000
+--- a/drivers/media/video/samsung/s3c-tvenc.c
++++ /dev/null
+@@ -1,1479 +0,0 @@
+-
+-/*
+- * linux/drivers/tvenc/s3c-tvenc.c
+- *
+- * Revision 1.0
+- *
+- *
+- * This file is subject to the terms and conditions of the GNU General Public
+- * License. See the file COPYING in the main directory of this archive for
+- * more details.
+- *
+- * S3C TV Encoder driver
+- *
+- */
+-
+-#include <linux/init.h>
+-#include <linux/module.h>
+-#include <linux/moduleparam.h>
+-#include <linux/types.h>
+-#include <linux/timer.h>
+-#include <linux/kernel.h>
+-#include <linux/fs.h>
+-#include <linux/platform_device.h>
+-#include <linux/interrupt.h>
+-#include <linux/clk.h>
+-#include <linux/delay.h>
+-#include <asm/uaccess.h>
+-#include <linux/errno.h> /* error codes */
+-#include <asm/div64.h>
+-#include <linux/mm.h>
+-#include <linux/tty.h>
+-#include <asm/io.h>
+-#include <asm/irq.h>
+-#include <asm/hardware.h>
+-#include <asm/uaccess.h>
+-#include <asm/arch/map.h>
+-
+-#include <linux/version.h>
+-#if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,16)
+-#include <linux/config.h>
+-#include <asm/arch/registers.h>
+-#include <linux/videodev2.h>
+-#else
+-#include <asm/arch/regs-tvenc.h>
+-#include <asm/arch/regs-lcd.h>
+-#include <media/v4l2-common.h>
+-#endif
+-
+-#include "s3c-tvenc.h"
+-
+-#define PFX "s3c_tvenc"
+-
+-static struct clk *tvenc_clock;
+-static struct clk *h_clk;
+-static int s3c_tvenc_irq = NO_IRQ;
+-static struct resource *s3c_tvenc_mem;
+-static void __iomem *base;
+-static wait_queue_head_t waitq;
+-static tv_out_params_t tv_param = {0,};
+-
+-/* Backup SFR value */
+-static u32 backup_reg[2];
+-
+-
+-/* Structure that declares the access functions*/
+-
+-static void s3c_tvenc_switch(tv_enc_switch_t sw)
+-{
+- if(sw == OFF) {
+- __raw_writel(__raw_readl(base + S3C_TVCTRL)
+- &~ S3C_TVCTRL_ON, base + S3C_TVCTRL);
+- } else if(sw == ON) {
+- __raw_writel(__raw_readl(base + S3C_TVCTRL)
+- | S3C_TVCTRL_ON, base + S3C_TVCTRL);
+- } else
+- printk("Error func:%s line:%d\n", __FUNCTION__, __LINE__);
+-}
+-
+-static void s3c_tvenc_set_image_size(u32 width, u32 height)
+-{
+- __raw_writel(IIS_WIDTH(width)| IIS_HEIGHT(height),
+- base + S3C_INIMAGESIZE);
+-}
+-
+-#if 0
+-static void s3c_tvenc_enable_macrovision(tv_standard_t tvmode, macro_pattern_t pattern)
+-{
+- switch(pattern) {
+- case AGC4L :
+- break;
+- case AGC2L :
+- break;
+- case N01 :
+- break;
+- case N02 :
+- break;
+- case P01 :
+- break;
+- case P02 :
+- break;
+- default :
+- break;
+- }
+-}
+-
+-static void s3c_tvenc_disable_macrovision(void)
+-{
+- __raw_writel(__raw_readl(base + S3C_MACROVISION0)
+- &~0xff, base + S3C_MACROVISION0);
+-}
+-#endif
+-
+-static void s3c_tvenc_set_tv_mode(tv_standard_t mode, tv_conn_type_t out)
+-{
+- u32 signal_type = 0, output_type = 0;
+-
+- switch(mode) {
+- case PAL_N :
+- __raw_writel(VBP_VEFBPD_PAL|VBP_VOFBPD_PAL,
+- base + S3C_VBPORCH);
+- __raw_writel(HBP_HSPW_PAL|HBP_HBPD_PAL,
+- base + S3C_HBPORCH);
+- __raw_writel(HEO_DTO_PAL|HEO_HEOV_PAL,
+- base + S3C_HENHOFFSET);
+- __raw_writel(EPC_PED_ON,
+- base + S3C_PEDCTRL);
+- __raw_writel(YFB_YBW_26|YFB_CBW_06,
+- base + S3C_YCFILTERBW);
+- __raw_writel(SSC_HSYNC_PAL,
+- base + S3C_SYNCSIZECTRL);
+- __raw_writel(BSC_BEND_PAL|BSC_BSTART_PAL,
+- base + S3C_BURSTCTRL);
+- __raw_writel(MBS_BSTART_PAL,
+- base + S3C_MACROBURSTCTRL);
+- __raw_writel(AVP_AVEND_PAL|AVP_AVSTART_PAL,
+- base + S3C_ACTVIDPOCTRL);
+- break;
+- case PAL_NC :
+- case PAL_BGHID :
+- __raw_writel(VBP_VEFBPD_PAL|VBP_VOFBPD_PAL,
+- base + S3C_VBPORCH);
+- __raw_writel(HBP_HSPW_PAL|HBP_HBPD_PAL,
+- base + S3C_HBPORCH);
+- __raw_writel(HEO_DTO_PAL|HEO_HEOV_PAL,
+- base + S3C_HENHOFFSET);
+- __raw_writel(EPC_PED_OFF,
+- base + S3C_PEDCTRL);
+- __raw_writel(YFB_YBW_26|YFB_CBW_06,
+- base + S3C_YCFILTERBW);
+- __raw_writel(SSC_HSYNC_PAL,
+- base + S3C_SYNCSIZECTRL);
+- __raw_writel(BSC_BEND_PAL|BSC_BSTART_PAL,
+- base + S3C_BURSTCTRL);
+- __raw_writel(MBS_BSTART_PAL,
+- base + S3C_MACROBURSTCTRL);
+- __raw_writel(AVP_AVEND_PAL|AVP_AVSTART_PAL,
+- base + S3C_ACTVIDPOCTRL);
+- break;
+- case NTSC_443 :
+- __raw_writel(VBP_VEFBPD_NTSC|VBP_VOFBPD_NTSC,
+- base + S3C_VBPORCH);
+- __raw_writel(HBP_HSPW_NTSC|HBP_HBPD_NTSC,
+- base + S3C_HBPORCH);
+- __raw_writel(HEO_DTO_NTSC|HEO_HEOV_NTSC,
+- base + S3C_HENHOFFSET);
+- __raw_writel(EPC_PED_ON,
+- base + S3C_PEDCTRL);
+- __raw_writel(YFB_YBW_26|YFB_CBW_06,
+- base + S3C_YCFILTERBW);
+- __raw_writel(SSC_HSYNC_NTSC,
+- base + S3C_SYNCSIZECTRL);
+- __raw_writel(BSC_BEND_NTSC|BSC_BSTART_NTSC,
+- base + S3C_BURSTCTRL);
+- __raw_writel(MBS_BSTART_NTSC,
+- base + S3C_MACROBURSTCTRL);
+- __raw_writel(AVP_AVEND_NTSC|AVP_AVSTART_NTSC,
+- base + S3C_ACTVIDPOCTRL);
+- break;
+- case NTSC_J :
+- __raw_writel(VBP_VEFBPD_NTSC|VBP_VOFBPD_NTSC,
+- base + S3C_VBPORCH);
+- __raw_writel(HBP_HSPW_NTSC|HBP_HBPD_NTSC,
+- base + S3C_HBPORCH);
+- __raw_writel(HEO_DTO_NTSC|HEO_HEOV_NTSC,
+- base + S3C_HENHOFFSET);
+- __raw_writel(EPC_PED_OFF,
+- base + S3C_PEDCTRL);
+- __raw_writel(YFB_YBW_21|YFB_CBW_06,
+- base + S3C_YCFILTERBW);
+- __raw_writel(SSC_HSYNC_NTSC,
+- base + S3C_SYNCSIZECTRL);
+- __raw_writel(BSC_BEND_NTSC|BSC_BSTART_NTSC,
+- base + S3C_BURSTCTRL);
+- __raw_writel(MBS_BSTART_NTSC,
+- base + S3C_MACROBURSTCTRL);
+- __raw_writel(AVP_AVEND_NTSC|AVP_AVSTART_NTSC,
+- base + S3C_ACTVIDPOCTRL);
+- break;
+- case PAL_M :
+- case NTSC_M :
+- default :
+- __raw_writel(VBP_VEFBPD_NTSC|VBP_VOFBPD_NTSC,
+- base + S3C_VBPORCH);
+- __raw_writel(HBP_HSPW_NTSC|HBP_HBPD_NTSC,
+- base + S3C_HBPORCH);
+- __raw_writel(HEO_DTO_NTSC|HEO_HEOV_NTSC,
+- base + S3C_HENHOFFSET);
+- __raw_writel(EPC_PED_ON,
+- base + S3C_PEDCTRL);
+- __raw_writel(YFB_YBW_21|YFB_CBW_06,
+- base + S3C_YCFILTERBW);
+- __raw_writel(SSC_HSYNC_NTSC,
+- base + S3C_SYNCSIZECTRL);
+- __raw_writel(BSC_BEND_NTSC|BSC_BSTART_NTSC,
+- base + S3C_BURSTCTRL);
+- __raw_writel(MBS_BSTART_NTSC,
+- base + S3C_MACROBURSTCTRL);
+- __raw_writel(AVP_AVEND_NTSC|AVP_AVSTART_NTSC,
+- base + S3C_ACTVIDPOCTRL);
+- break;
+- }
+-
+- if(out == S_VIDEO) {
+- __raw_writel(YFB_YBW_60|YFB_CBW_06,
+- base + S3C_YCFILTERBW);
+- output_type = S3C_TVCTRL_OUTTYPE_S;
+- } else
+- output_type = S3C_TVCTRL_OUTTYPE_C;
+-
+- switch(mode) {
+- case NTSC_M :
+- signal_type = S3C_TVCTRL_OUTFMT_NTSC_M;
+- break;
+- case NTSC_J :
+- signal_type = S3C_TVCTRL_OUTFMT_NTSC_J;
+- break;
+- case PAL_BGHID :
+- signal_type = S3C_TVCTRL_OUTFMT_PAL_BDG;
+- break;
+- case PAL_M :
+- signal_type = S3C_TVCTRL_OUTFMT_PAL_M;
+- break;
+- case PAL_NC :
+- signal_type = S3C_TVCTRL_OUTFMT_PAL_NC;
+- break;
+- default:
+- printk("s3c_tvenc_set_tv_mode : No matching signal_type!\n");
+- break;
+- }
+-
+- __raw_writel((__raw_readl(base + S3C_TVCTRL)
+- &~(0x1f<<4))| output_type | signal_type,
+- base + S3C_TVCTRL);
+-
+- __raw_writel(0x01, base + S3C_FSCAUXCTRL);
+-}
+-
+-#if 0
+-static void s3c_tvenc_set_pedestal(tv_enc_switch_t sw)
+-{
+- if(sw)
+- __raw_writel(EPC_PED_ON, base + S3C_PEDCTRL);
+- else
+- __raw_writel(EPC_PED_OFF, base + S3C_PEDCTRL);
+-}
+-
+-static void s3c_tvenc_set_sub_carrier_freq(u32 freq)
+-{
+- __raw_writel(FSC_CTRL(freq), base + S3C_FSCCTRL);
+-}
+-
+-static void s3c_tvenc_set_fsc_dto(u32 val)
+-{
+- unsigned int temp;
+-
+- temp = (0x1<<31)|(val&0x7fffffff);
+- __raw_writel(temp, base + S3C_FSCDTOMANCTRL);
+-}
+-
+-static void s3c_tvenc_disable_fsc_dto(void)
+-{
+- __raw_writel(__raw_readl(base + S3C_FSCDTOMANCTRL)&~(1<<31),
+- base + S3C_FSCDTOMANCTRL);
+-}
+-
+-static void s3c_tvenc_set_bg(u32 soft_mix, u32 color, u32 lum_offset)
+-{
+- unsigned int bg_color;
+- switch(color) {
+- case 0 :
+- bg_color = BGC_BGCS_BLACK;
+- break;
+- case 1 :
+- bg_color = BGC_BGCS_BLUE;
+- break;
+- case 2 :
+- bg_color = BGC_BGCS_RED;
+- break;
+- case 3 :
+- bg_color = BGC_BGCS_MAGENTA;
+- break;
+- case 4 :
+- bg_color = BGC_BGCS_GREEN;
+- break;
+- case 5 :
+- bg_color = BGC_BGCS_CYAN;
+- break;
+- case 6 :
+- bg_color = BGC_BGCS_YELLOW;
+- break;
+- case 7 :
+- bg_color = BGC_BGCS_WHITE;
+- break;
+- }
+- if(soft_mix)
+- __raw_writel(BGC_SME_ENA|bg_color|BGC_BGYOFS(lum_offset),
+- base + S3C_BGCTRL);
+- else
+- __raw_writel(BGC_SME_DIS|bg_color|BGC_BGYOFS(lum_offset),
+- base + S3C_BGCTRL);
+-
+-}
+-
+-static void s3c_tvenc_set_bg_vav_hav(u32 hav_len, u32 vav_len, u32 hav_st, u32 vav_st)
+-{
+- __raw_writel(BVH_BG_HL(hav_len)|BVH_BG_HS(hav_st)|BVH_BG_VL(vav_len)|BVH_BG_VS(vav_st),
+- base + S3C_BGHVAVCTRL);
+-}
+-#endif
+-
+-static void s3c_tvenc_set_hue_phase(u32 phase_val)
+-{
+- __raw_writel(HUE_CTRL(phase_val),
+- base + S3C_HUECTRL);
+-}
+-
+-#if 0
+-static u32 s3c_tvenc_get_hue_phase(void)
+-{
+- return __raw_readl(base + S3C_HUECTRL)&0xff;
+-}
+-#endif
+-
+-static void s3c_tvenc_set_contrast(u32 contrast)
+-{
+- u32 temp;
+-
+- temp = __raw_readl(base + S3C_CONTRABRIGHT);
+-
+- __raw_writel((temp &~0xff)|contrast,
+- base + S3C_CONTRABRIGHT);
+-}
+-
+-#if 0
+-static u32 s3c_tvenc_get_contrast(void)
+-{
+- return (__raw_readl(base + S3C_CONTRABRIGHT)&0xff);
+-}
+-#endif
+-
+-static void s3c_tvenc_set_bright(u32 bright)
+-{
+- u32 temp;
+-
+- temp = __raw_readl(base + S3C_CONTRABRIGHT);
+-
+- __raw_writel((temp &~(0xff<<16))| (bright<<16),
+- base + S3C_CONTRABRIGHT);
+-}
+-
+-#if 0
+-static u32 s3c_tvenc_get_bright(void)
+-{
+- return ((__raw_readl(base + S3C_CONTRABRIGHT)&(0xff<<16))>>16);
+-}
+-
+-
+-static void s3c_tvenc_set_cbgain(u32 cbgain)
+-{
+- u32 temp;
+-
+- temp = __raw_readl(base + S3C_CBCRGAINCTRL);
+-
+- __raw_writel((temp &~0xff)|cbgain,
+- base + S3C_CBCRGAINCTRL);
+-}
+-
+-
+-static u32 s3c_tvenc_get_cbgain(void)
+-{
+- return (__raw_readl(base + S3C_CBCRGAINCTRL)&0xff);
+-}
+-
+-static void s3c_tvenc_set_crgain(u32 crgain)
+-{
+- u32 temp;
+-
+- temp = __raw_readl(base + S3C_CBCRGAINCTRL);
+-
+- __raw_writel((temp &~(0xff<<16))| (crgain<<16),
+- base + S3C_CBCRGAINCTRL);
+-}
+-
+-static u32 s3c_tvenc_get_crgain(void)
+-{
+- return ((__raw_readl(base + S3C_CBCRGAINCTRL)&(0xff<<16))>>16);
+-}
+-#endif
+-
+-static void s3c_tvenc_enable_gamma_control(tv_enc_switch_t enable)
+-{
+- u32 temp;
+-
+- temp = __raw_readl(base + S3C_GAMMACTRL);
+- if(enable == ON)
+- temp |= (1<<12);
+- else
+- temp &= ~(1<<12);
+-
+- __raw_writel(temp, base + S3C_GAMMACTRL);
+-}
+-
+-static void s3c_tvenc_set_gamma_gain(u32 ggain)
+-{
+- u32 temp;
+-
+- temp = __raw_readl(base + S3C_GAMMACTRL);
+-
+- __raw_writel((temp &~(0x7<<8))| (ggain<<8),
+- base + S3C_GAMMACTRL);
+-}
+-
+-#if 0
+-static u32 s3c_tvenc_get_gamma_gain(void)
+-{
+- return ((__raw_readl(base + S3C_GAMMACTRL)&(0x7<<8))>>8);
+-}
+-
+-static void s3c_tvenc_enable_mute_control(tv_enc_switch_t enable)
+-{
+- u32 temp;
+-
+- temp = __raw_readl(base + S3C_GAMMACTRL);
+- if(enable == ON)
+- temp |= (1<<12);
+- else
+- temp &= ~(1<<12);
+-
+- __raw_writel(temp, base + S3C_GAMMACTRL);
+-}
+-
+-static void s3c_tvenc_set_mute(u32 y, u32 cb, u32 cr)
+-{
+- u32 temp;
+-
+- temp = __raw_readl(base + S3C_MUTECTRL);
+-
+- temp &=~(0xffffff<<8);
+- temp |= (cr & 0xff)<<24;
+- temp |= (cb & 0xff)<<16;
+- temp |= (y & 0xff)<<8;
+-
+- __raw_writel(temp, base + S3C_MUTECTRL);
+-}
+-
+-static void s3c_tvenc_get_mute(u32 *y, u32 *cb, u32 *cr)
+-{
+- u32 temp;
+-
+- temp = __raw_readl(base + S3C_MUTECTRL);
+-
+- *y = (temp&(0xff<<8))>>8;
+- *cb = (temp&(0xff<<16))>>16;
+- *cr = (temp&(0xff<<24))>>24;
+-}
+-#endif
+-
+-static void s3c_tvenc_get_active_win_center(u32 *vert, u32 *horz)
+-{
+- u32 temp;
+-
+- temp = __raw_readl(base + S3C_HENHOFFSET);
+-
+- *vert = (temp&(0x3f<<24))>>24;
+- *horz = (temp&(0xff<<16))>>16;
+-}
+-
+-static void s3c_tvenc_set_active_win_center(u32 vert, u32 horz)
+-{
+- u32 temp;
+-
+- temp = __raw_readl(base + S3C_HENHOFFSET);
+-
+- temp &=~(0x3ffff<<16);
+- temp |= (vert&0x3f)<<24;
+- temp |= (horz&0xff)<<16;
+-
+- __raw_writel(temp, base + S3C_HENHOFFSET);
+-}
+-
+-// LCD display controller configuration functions
+-static void s3c_lcd_set_output_path(lcd_local_output_t out)
+-{
+-#if 0 // peter for 2.6.21 kernel
+- s3c_fb_set_output_path(out);
+-#else // peter for 2.6.24 kernel
+- s3cfb_set_output_path(out);
+-#endif
+-}
+-
+-static void s3c_lcd_set_clkval(u32 clkval)
+-{
+-#if 0 // peter for 2.6.21 kernel
+- s3c_fb_set_clkval(clkval);
+-#else // peter for 2.6.24 kernel
+- s3cfb_set_clock(clkval);
+-#endif
+-}
+-
+-static void s3c_lcd_enable_rgbport(u32 on_off)
+-{
+-#if 0 // peter for 2.6.21 kernel
+- s3c_fb_enable_rgbport(on_off);
+-#else // peter for 2.6.24 kernel
+- s3cfb_enable_rgbport(on_off);
+-#endif
+-}
+-
+-static void s3c_lcd_start(void)
+-{
+-#if 0 // peter for 2.6.21 kernel
+- s3c_fb_start_lcd();
+-#else // peter for 2.6.24 kernel
+- s3cfb_start_lcd();
+-#endif
+-}
+-
+-static void s3c_lcd_stop(void)
+-{
+-#if 0 // peter for 2.6.21 kernel
+- s3c_fb_stop_lcd();
+-#else // peter for 2.6.24 kernel
+- s3cfb_stop_lcd();
+-#endif
+-}
+-
+-
+-static void s3c_lcd_set_config(void)
+-{
+- backup_reg[0] = __raw_readl(S3C_VIDCON0);
+- backup_reg[1] = __raw_readl(S3C_VIDCON2);
+-
+- s3c_lcd_set_output_path(LCD_TVRGB);
+- tv_param.lcd_output_mode = LCD_TVRGB;
+-
+- s3c_lcd_set_clkval(4);
+- s3c_lcd_enable_rgbport(1);
+-}
+-
+-static void s3c_lcd_exit_config(void)
+-{
+- __raw_writel(backup_reg[0], S3C_VIDCON0);
+- __raw_writel(backup_reg[1], S3C_VIDCON2);
+- tv_param.lcd_output_mode = LCD_RGB;
+-}
+-
+-static int scaler_test_start(void)
+-{
+- tv_param.sp.DstFullWidth = 640;
+- tv_param.sp.DstFullHeight= 480;
+- tv_param.sp.DstCSpace = RGB16;
+-
+- s3c_tvscaler_config(&tv_param.sp);
+-
+- s3c_tvscaler_int_enable(1);
+-
+- s3c_tvscaler_start();
+-
+- return 0;
+-}
+-
+-static int scaler_test_stop(void)
+-{
+- s3c_tvscaler_int_disable();
+-
+- return 0;
+-}
+-
+-
+-static int tvout_start(void)
+-{
+- u32 width, height;
+- tv_standard_t type;
+- tv_conn_type_t conn;
+-
+- tv_param.sp.DstFullWidth *= 2; // For TV OUT
+-
+- width = tv_param.sp.DstFullWidth;
+- height = tv_param.sp.DstFullHeight;
+- type = tv_param.sig_type;
+- conn = tv_param.connect;
+-
+- /* Set TV-SCALER parameter */
+- switch(tv_param.v2.input->type) {
+- case V4L2_INPUT_TYPE_FIFO: // LCD FIFO-OUT
+- tv_param.sp.Mode = FREE_RUN;
+- tv_param.sp.DstCSpace = YCBYCR;
+- /* Display controller setting */
+- s3c_lcd_stop();
+- s3c_lcd_set_config();
+- break;
+- case V4L2_INPUT_TYPE_MSDMA: // MSDMA
+- tv_param.sp.Mode = FREE_RUN;
+- tv_param.sp.DstCSpace = YCBYCR;
+- break;
+- default:
+- return -EINVAL;
+- }
+-
+- s3c_tvenc_set_tv_mode(type, conn);
+- s3c_tvenc_set_image_size(width, height);
+- s3c_tvenc_switch(ON);
+-
+- s3c_tvscaler_config(&tv_param.sp); // for setting DstStartX/Y, DstWidth/Height
+- s3c_tvscaler_set_interlace(1);
+- if(tv_param.v2.input->type == V4L2_INPUT_TYPE_FIFO)
+- s3c_tvscaler_int_disable();
+- else
+- s3c_tvscaler_int_enable(1);
+- s3c_tvscaler_start();
+-
+- if(tv_param.v2.input->type == V4L2_INPUT_TYPE_FIFO)
+- s3c_lcd_start();
+-
+- return 0;
+-}
+-
+-static int tvout_stop(void)
+-{
+-
+- s3c_tvscaler_set_interlace(0);
+- s3c_tvscaler_stop_freerun();
+- s3c_tvscaler_int_disable();
+- s3c_tvenc_switch(OFF);
+-
+- switch(tv_param.v2.input->type) {
+- case V4L2_INPUT_TYPE_FIFO: // LCD FIFO-OUT
+- /* Display controller setting */
+- s3c_lcd_stop();
+- s3c_lcd_exit_config();
+- s3c_lcd_start();
+- break;
+- default:
+- break;
+- }
+- return 0;
+-}
+-
+-/* ------------------------------------------ V4L2 SUPPORT ----------------------------------------------*/
+-/* ------------- In FIFO and MSDMA, v4l2_input supported by S3C TVENC controller ------------------*/
+-static struct v4l2_input tvenc_inputs[] = {
+- {
+- .index = 0,
+- .name = "LCD FIFO_OUT",
+- .type = V4L2_INPUT_TYPE_FIFO,
+- .audioset = 1,
+- .tuner = 0, /* ignored */
+- .std = 0,
+- .status = 0,
+- },
+- {
+- .index = 1,
+- .name = "Memory input (MSDMA)",
+- .type = V4L2_INPUT_TYPE_MSDMA,
+- .audioset = 2,
+- .tuner = 0,
+- .std = 0,
+- .status = 0,
+- }
+-};
+-
+-/* ------------ Out FIFO and MADMA, v4l2_output supported by S3C TVENC controller ----------------*/
+-static struct v4l2_output tvenc_outputs[] = {
+- {
+- .index = 0,
+- .name = "TV-OUT",
+- .type = V4L2_OUTPUT_TYPE_ANALOG,
+- .audioset = 0,
+- .modulator = 0,
+- .std = V4L2_STD_PAL | V4L2_STD_NTSC_M,
+- },
+- {
+- .index = 1,
+- .name = "Memory output (MSDMA)",
+- .type = V4L2_OUTPUT_TYPE_MSDMA,
+- .audioset = 0,
+- .modulator = 0,
+- .std = 0,
+- },
+-
+-};
+-
+-const struct v4l2_fmtdesc tvenc_input_formats[] = {
+- {
+- .index = 0,
+- .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+- .description = "16 bpp RGB, le",
+- .pixelformat = V4L2_PIX_FMT_RGB565,
+- .flags = FORMAT_FLAGS_PACKED,
+- },
+- {
+- .index = 1,
+- .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+- .flags = FORMAT_FLAGS_PACKED,
+- .description = "24 bpp RGB, le",
+- .pixelformat = V4L2_PIX_FMT_RGB24,
+- },
+- {
+- .index = 2,
+- .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+- .flags = FORMAT_FLAGS_PLANAR,
+- .description = "4:2:2, planar, Y-Cb-Cr",
+- .pixelformat = V4L2_PIX_FMT_YUV422P,
+-
+- },
+- {
+- .index = 3,
+- .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+- .flags = FORMAT_FLAGS_PLANAR,
+- .description = "4:2:0, planar, Y-Cb-Cr",
+- .pixelformat = V4L2_PIX_FMT_YUV420,
+- }
+-};
+-
+-
+-const struct v4l2_fmtdesc tvenc_output_formats[] = {
+- {
+- .index = 0,
+- .type = V4L2_BUF_TYPE_VIDEO_OUTPUT,
+- .description = "16 bpp RGB, le",
+- .pixelformat = V4L2_PIX_FMT_RGB565,
+- .flags = FORMAT_FLAGS_PACKED,
+- },
+- {
+- .index = 1,
+- .type = V4L2_BUF_TYPE_VIDEO_OUTPUT,
+- .flags = FORMAT_FLAGS_PACKED,
+- .description = "24 bpp RGB, le",
+- .pixelformat = V4L2_PIX_FMT_RGB24,
+- },
+- {
+- .index = 2,
+- .type = V4L2_BUF_TYPE_VIDEO_OUTPUT,
+- .flags = FORMAT_FLAGS_PLANAR,
+- .description = "4:2:2, planar, Y-Cb-Cr",
+- .pixelformat = V4L2_PIX_FMT_YUV422P,
+-
+- },
+- {
+- .index = 3,
+- .type = V4L2_BUF_TYPE_VIDEO_OUTPUT,
+- .flags = FORMAT_FLAGS_PLANAR,
+- .description = "4:2:0, planar, Y-Cb-Cr",
+- .pixelformat = V4L2_PIX_FMT_YUV420,
+- }
+-};
+-
+-const struct v4l2_standard tvout_standards[] = {
+- {
+- .index = 0,
+- .id = V4L2_STD_NTSC_M,
+- .name = "NTSC type",
+- },
+- {
+- .index = 1,
+- .id = V4L2_STD_PAL,
+- .name = "PAL type",
+- }
+-};
+-
+-#define NUMBER_OF_INPUT_FORMATS ARRAY_SIZE(tvenc_input_formats)
+-#define NUMBER_OF_OUTPUT_FORMATS ARRAY_SIZE(tvenc_output_formats)
+-#define NUMBER_OF_INPUTS ARRAY_SIZE(tvenc_inputs)
+-#define NUMBER_OF_OUTPUTS ARRAY_SIZE(tvenc_outputs)
+-#define NUMBER_OF_STANDARDS ARRAY_SIZE(tvout_standards)
+-
+-static int s3c_tvenc_g_fmt(struct v4l2_format *f)
+-{
+- int size = sizeof(struct v4l2_pix_format);
+-
+- memset(&f->fmt.pix, 0, size);
+- memcpy(&f->fmt.pix, &tv_param.v2.pixfmt, size);
+-
+- return 0;
+-}
+-
+-static int s3c_tvenc_s_fmt(struct v4l2_format *f)
+-{
+- /* update our state informations */
+- tv_param.v2.pixfmt= f->fmt.pix;
+-
+- // peter LCD output related operation
+- if (tv_param.v2.pixfmt.pixelformat == V4L2_PIX_FMT_RGB565 ) {
+-
+- tv_param.sp.SrcFullWidth = tv_param.v2.pixfmt.width;
+- tv_param.sp.SrcFullHeight = tv_param.v2.pixfmt.height;
+- tv_param.sp.SrcStartX = 0;
+- tv_param.sp.SrcStartY = 0;
+- tv_param.sp.SrcWidth = tv_param.sp.SrcFullWidth;
+- tv_param.sp.SrcHeight = tv_param.sp.SrcFullHeight;
+-
+- printk("TV-OUT: LCD path operation set\n");
+-
+- // peter for padded data of mfc output
+- } else if (tv_param.v2.pixfmt.pixelformat == V4L2_PIX_FMT_YUV420) {
+-
+-#ifdef DIVX_TEST // padded output
+- tv_param.sp.SrcFullWidth = tv_param.v2.pixfmt.width + 2*16;
+- tv_param.sp.SrcFullHeight = tv_param.v2.pixfmt.height + 2*16;
+- tv_param.sp.SrcStartX = 16;
+- tv_param.sp.SrcStartY = 16;
+- tv_param.sp.SrcWidth = tv_param.sp.SrcFullWidth - 2*tv_param.sp.SrcStartX;
+- tv_param.sp.SrcHeight = tv_param.sp.SrcFullHeight - 2*tv_param.sp.SrcStartY;
+-#else // not padded output
+- tv_param.sp.SrcFullWidth = tv_param.v2.pixfmt.width;
+- tv_param.sp.SrcFullHeight = tv_param.v2.pixfmt.height;
+- tv_param.sp.SrcStartX = 0;
+- tv_param.sp.SrcStartY = 0;
+- tv_param.sp.SrcWidth = tv_param.sp.SrcFullWidth;
+- tv_param.sp.SrcHeight = tv_param.sp.SrcFullHeight;
+-#endif
+-
+- printk("TV-OUT: MFC path operation set\n");
+-
+- }
+-
+- switch(tv_param.v2.pixfmt.pixelformat) {
+- case V4L2_PIX_FMT_RGB565:
+- tv_param.sp.SrcCSpace = RGB16;
+- break;
+- case V4L2_PIX_FMT_RGB24:
+- tv_param.sp.SrcCSpace = RGB24;
+- break;
+- case V4L2_PIX_FMT_YUV420:
+- tv_param.sp.SrcCSpace = YC420;
+- break;
+- case V4L2_PIX_FMT_YUV422P:
+- tv_param.sp.SrcCSpace = YC422;
+- break;
+- default:
+- return -EINVAL;
+- }
+-
+-// camif_convert_into_camif_cfg_t(cfg, 1);
+- return 0;
+-}
+-
+-static int s3c_tvenc_s_input(int index)
+-{
+-
+- tv_param.v2.input = &tvenc_inputs[index];
+- switch(tv_param.v2.input->type) {
+- case V4L2_INPUT_TYPE_FIFO: // LCD FIFO-OUT
+- tv_param.sp.InPath = POST_FIFO;
+- break;
+- case V4L2_INPUT_TYPE_MSDMA: // MSDMA
+- tv_param.sp.InPath = POST_DMA;
+- break;
+- default:
+- return -EINVAL;
+- }
+- return 0;
+-}
+-
+-static int s3c_tvenc_s_output(int index)
+-{
+- tv_param.v2.output = &tvenc_outputs[index];
+- switch(tv_param.v2.output->type) {
+- case V4L2_OUTPUT_TYPE_ANALOG: // TV-OUT (FIFO-OUT)
+- tv_param.sp.OutPath = POST_FIFO;
+- break;
+- case V4L2_OUTPUT_TYPE_MSDMA: // MSDMA
+- tv_param.sp.OutPath = POST_DMA;
+- break;
+- default:
+- return -EINVAL;
+- }
+- return 0;
+-}
+-
+-static int s3c_tvenc_s_std(v4l2_std_id *id)
+-{
+-// printk("s3c_tvenc_s_std: *id=0x%x",*id);
+- switch(*id) {
+- case V4L2_STD_NTSC_M:
+- tv_param.sig_type = NTSC_M;
+- tv_param.sp.DstFullWidth = 720;
+- tv_param.sp.DstFullHeight = 480;
+- break;
+- case V4L2_STD_PAL:
+- tv_param.sig_type = PAL_M;
+- tv_param.sp.DstFullWidth = 720;
+- tv_param.sp.DstFullHeight = 576;
+- break;
+- default:
+- return -EINVAL;
+- }
+- return 0;
+-}
+-
+-static int s3c_tvenc_v4l2_control(struct v4l2_control *ctrl)
+-{
+- switch(ctrl->id) {
+-
+- // peter added for MFC related op.
+- case V4L2_CID_MPEG_STREAM_PID_VIDEO:
+- {
+- tv_param.sp.SrcFrmSt = ctrl->value;
+- return 0;
+- }
+-
+- case V4L2_CID_CONNECT_TYPE:
+- {
+- if(ctrl->value == 0) { // COMPOSITE
+- tv_param.connect = COMPOSITE;
+- } else if(ctrl->value == 1) { //S-VIDEO
+- tv_param.connect = S_VIDEO;
+- } else {
+- return -EINVAL;
+- }
+- return 0;
+- }
+-
+- case V4L2_CID_BRIGHTNESS:
+- {
+- s32 val = ctrl->value;
+- if((val > 0xff)||(val < 0))
+- return -EINVAL;
+- else
+- s3c_tvenc_set_bright(val);
+-
+- return 0;
+- }
+-
+- case V4L2_CID_CONTRAST:
+- {
+- s32 val = ctrl->value;
+- if((val > 0xff)||(val < 0))
+- return -EINVAL;
+- else
+- s3c_tvenc_set_contrast(val);
+-
+- return 0;
+- }
+-
+- case V4L2_CID_GAMMA:
+- {
+- s32 val = ctrl->value;
+- if((val > 0x3)||(val < 0)) {
+- return -EINVAL;
+- } else {
+- s3c_tvenc_enable_gamma_control(ON);
+- s3c_tvenc_set_gamma_gain(val);
+- s3c_tvenc_enable_gamma_control(OFF);
+- }
+- return 0;
+- }
+-
+- case V4L2_CID_HUE:
+- {
+- s32 val = ctrl->value;
+- if((val > 0xff)||(val < 0))
+- return -EINVAL;
+- else
+- s3c_tvenc_set_hue_phase(val);
+-
+- return 0;
+- }
+-
+- case V4L2_CID_HCENTER:
+- {
+- s32 val = ctrl->value;
+- u32 curr_horz, curr_vert;
+-
+- if((val > 0xff)||(val < 0)) {
+- return -EINVAL;
+- } else {
+- s3c_tvenc_get_active_win_center(&curr_vert, &curr_horz);
+- s3c_tvenc_set_active_win_center(curr_vert, val);
+- }
+-
+- return 0;
+- }
+-
+- case V4L2_CID_VCENTER:
+- {
+- s32 val = ctrl->value;
+- u32 curr_horz, curr_vert;
+-
+- if((val > 0x3f)||(val < 0)) {
+- return -EINVAL;
+- } else {
+- s3c_tvenc_get_active_win_center(&curr_vert, &curr_horz);
+- s3c_tvenc_set_active_win_center(val, curr_horz);
+- }
+-
+- return 0;
+- }
+-
+- default:
+- return -EINVAL;
+- }
+- return 0;
+-}
+-
+-int s3c_tvenc_open(struct inode *inode, struct file *filp)
+-{
+- int err;
+-
+- err = video_exclusive_open(inode, filp); // One function of V4l2 driver
+-
+- if(err < 0)
+- return err;
+- filp->private_data = &tv_param;
+-
+- s3c_tvscaler_init();
+-
+- /* Success */
+- return 0;
+-}
+-
+-int s3c_tvenc_release(struct inode *inode, struct file *filp)
+-{
+- video_exclusive_release(inode, filp);
+-
+- /* Success */
+- return 0;
+-}
+-
+-static int s3c_tvenc_do_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,void *arg)
+-{
+- int ret;
+-
+- switch(cmd){
+- case VIDIOC_QUERYCAP:
+- {
+- struct v4l2_capability *cap = arg;
+- strcpy(cap->driver, "S3C TV-OUT driver");
+- strlcpy(cap->card, tv_param.v->name, sizeof(cap->card));
+- sprintf(cap->bus_info, "ARM AHB BUS");
+- cap->version = 0;
+- cap->capabilities = tv_param.v->type2;
+- return 0;
+- }
+-
+- case VIDIOC_OVERLAY:
+- {
+- int on = *(int *)arg;
+-
+- printk("TV-OUT: VIDIOC_OVERLAY on:%d\n", on);
+- if (on != 0) {
+- ret = tvout_start();
+- } else {
+- ret = tvout_stop();
+- }
+- return ret;
+- }
+-
+- case VIDIOC_ENUMINPUT:
+- {
+- struct v4l2_input *i = arg;
+- printk("TV-OUT: VIDIOC_ENUMINPUT : index = %d\n", i->index);
+-
+- if ((i->index) >= NUMBER_OF_INPUTS) {
+- return -EINVAL;
+- }
+- memcpy(i, &tvenc_inputs[i->index], sizeof(struct v4l2_input));
+- return 0;
+- }
+-
+- case VIDIOC_S_INPUT: // 0 -> LCD FIFO-OUT, 1 -> MSDMA
+- {
+- int index = *((int *)arg);
+- printk("TV-OUT: VIDIOC_S_INPUT \n");
+-
+- if (index >= NUMBER_OF_INPUTS) {
+- return -EINVAL;
+- }
+- else {
+- s3c_tvenc_s_input(index);
+- return 0;
+- }
+- }
+-
+- case VIDIOC_G_INPUT:
+- {
+- u32 *i = arg;
+- printk("TV-OUT: VIDIOC_G_INPUT \n");
+- *i = tv_param.v2.input->type;
+- return 0;
+- }
+-
+- case VIDIOC_ENUMOUTPUT:
+- {
+- struct v4l2_output *i = arg;
+- printk("TV-OUT: VIDIOC_ENUMOUTPUT : index = %d\n", i->index);
+-
+- if ((i->index) >= NUMBER_OF_OUTPUTS) {
+- return -EINVAL;
+- }
+- memcpy(i, &tvenc_outputs[i->index], sizeof(struct v4l2_output));
+- return 0;
+- }
+-
+- case VIDIOC_S_OUTPUT: // 0 -> TV / FIFO , 1 -> MSDMA
+- {
+- int index = *((int *)arg);
+- printk("TV-OUT: VIDIOC_S_OUTPUT \n");
+-
+- if (index >= NUMBER_OF_OUTPUTS) {
+- return -EINVAL;
+- }
+- else {
+- s3c_tvenc_s_output(index);
+- return 0;
+- }
+- }
+-
+- case VIDIOC_G_OUTPUT:
+- {
+- u32 *i = arg;
+- printk("VIDIOC_G_OUTPUT \n");
+- *i = tv_param.v2.output->type;
+- return 0;
+- }
+-
+- case VIDIOC_ENUM_FMT:
+- { struct v4l2_fmtdesc *f = arg;
+- enum v4l2_buf_type type = f->type;
+- int index = f->index;
+-
+- printk("C: VIDIOC_ENUM_FMT : index = %d\n", index);
+- if (index >= NUMBER_OF_INPUT_FORMATS)
+- return -EINVAL;
+-
+- switch (type) {
+- case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+- break;
+- case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+- default:
+- return -EINVAL;
+- }
+- memset(f, 0, sizeof(*f));
+- memcpy(f, tv_param.v2.fmtdesc+index, sizeof(*f));
+- return 0;
+- }
+-
+- case VIDIOC_G_FMT:
+- {
+- struct v4l2_format *f = arg;
+- printk("C: VIDIOC_G_FMT \n");
+- ret = s3c_tvenc_g_fmt(f);
+- return ret;
+- }
+-
+- case VIDIOC_S_FMT:
+- {
+- struct v4l2_format *f = arg;
+- printk("C: VIDIOC_S_FMT \n");
+- ret = s3c_tvenc_s_fmt(f);
+- if(ret != 0) {
+- printk("s3c_tvenc_set_fmt() failed !\n");
+- return -EINVAL;
+- }
+- return ret;
+- }
+-
+- case VIDIOC_S_CTRL:
+- {
+- struct v4l2_control *ctrl = arg;
+- //printk("P: VIDIOC_S_CTRL \n");
+- ret = s3c_tvenc_v4l2_control(ctrl);
+- return ret;
+- }
+-
+- case VIDIOC_ENUMSTD:
+- {
+- struct v4l2_standard *e = arg;
+- unsigned int index = e->index;
+-
+- if (index >= NUMBER_OF_STANDARDS)
+- return -EINVAL;
+- v4l2_video_std_construct(e, tvout_standards[e->index].id,
+- &tvout_standards[e->index].name);
+- e->index = index;
+- return 0;
+- }
+-
+- case VIDIOC_G_STD:
+- {
+- v4l2_std_id *id = arg;
+- *id = tvout_standards[0].id;
+- return 0;
+- }
+-
+- case VIDIOC_S_STD:
+- {
+- v4l2_std_id *id = arg;
+- unsigned int i;
+-
+- for (i = 0; i < NUMBER_OF_STANDARDS; i++) {
+- //printk("P: *id = %d, tvout_standards[i].id = %d\n", *id, tvout_standards[i].id);
+- if (*id & tvout_standards[i].id)
+- break;
+- }
+- if (i == NUMBER_OF_STANDARDS)
+- return -EINVAL;
+-
+- ret = s3c_tvenc_s_std(id);
+- return ret;
+- }
+-
+- case VIDIOC_S_TVOUT_ON:
+- {
+- //int *SrcFrmSt = arg;
+- //printk("---peter VIDIOC_S_TVOUT_ON : SrcFrmSt = 0x%08x\n", *SrcFrmSt);
+- ret = tvout_start();
+- return ret;
+- }
+-
+- case VIDIOC_S_TVOUT_OFF:
+- {
+- ret = tvout_stop();
+- return ret;
+- }
+-
+- case VIDIOC_S_SCALER_TEST:
+- {
+- ret = scaler_test_start();
+- mdelay(1);
+- ret = scaler_test_stop();
+- return ret;
+- }
+-
+- default:
+- return -EINVAL;
+- }
+- return 0;
+-}
+-
+-static int s3c_tvenc_ioctl_v4l2(struct inode *inode, struct file *filp, unsigned int cmd,
+- unsigned long arg)
+-{
+- return video_usercopy(inode, filp, cmd, arg, s3c_tvenc_do_ioctl);
+-}
+-
+-int s3c_tvenc_read(struct file *filp, char *buf, size_t count,
+- loff_t *f_pos)
+-{
+- return 0;
+-}
+-
+-int s3c_tvenc_write(struct file *filp, const char *buf, size_t
+- count, loff_t *f_pos)
+-{
+- return 0;
+-}
+-
+-int s3c_tvenc_mmap(struct file *filp, struct vm_area_struct *vma)
+-{
+- u32 size = vma->vm_end - vma->vm_start;
+- u32 max_size;
+- u32 page_frame_no;
+-
+- page_frame_no = __phys_to_pfn(POST_BUFF_BASE_ADDR);
+-
+- max_size = RESERVE_POST_MEM + PAGE_SIZE - (RESERVE_POST_MEM % PAGE_SIZE);
+-
+- if(size > max_size) {
+- return -EINVAL;
+- }
+-
+- vma->vm_flags |= VM_RESERVED;
+-
+- if( remap_pfn_range(vma, vma->vm_start, page_frame_no,
+- size, vma->vm_page_prot)) {
+- printk(KERN_ERR "%s: mmap_error\n", __FUNCTION__);
+- return -EAGAIN;
+-
+- }
+-
+- return 0;
+-}
+-
+-struct file_operations s3c_tvenc_fops = {
+- .owner = THIS_MODULE,
+- .open = s3c_tvenc_open,
+- .ioctl = s3c_tvenc_ioctl_v4l2,
+- .release = s3c_tvenc_release,
+- .read = s3c_tvenc_read,
+- .write = s3c_tvenc_write,
+- .mmap = s3c_tvenc_mmap,
+-};
+-
+-void s3c_tvenc_vdev_release (struct video_device *vdev) {
+- kfree(vdev);
+-}
+-
+-struct video_device tvencoder = {
+- .name = "TVENCODER",
+- .type = VID_TYPE_OVERLAY | VID_TYPE_CAPTURE | VID_TYPE_SCALES,
+- .type2 = V4L2_CAP_VIDEO_OUTPUT| V4L2_CAP_VIDEO_CAPTURE, /* V4L2 */
+- //.hardware = 0x01, // peter for 2.6.24 kernel
+- .fops = &s3c_tvenc_fops,
+- .release = s3c_tvenc_vdev_release,
+- .minor = TVENC_MINOR,
+-};
+-
+-irqreturn_t s3c_tvenc_isr(int irq, void *dev_id,
+- struct pt_regs *regs)
+-{
+- u32 mode;
+-
+- mode = __raw_readl(base + S3C_TVCTRL);
+-
+- // Clear FIFO under-run status pending bit
+- mode |= (1<<12);
+-
+- __raw_writel(mode, base + S3C_TVCTRL);
+-
+- wake_up_interruptible(&waitq);
+- return IRQ_HANDLED;
+-}
+-
+-static int s3c_tvenc_probe(struct platform_device *pdev)
+-{
+-
+- struct resource *res;
+-
+- int ret;
+-
+- /* find the IRQs */
+- s3c_tvenc_irq = platform_get_irq(pdev, 0);
+- if(s3c_tvenc_irq <= 0) {
+- printk(KERN_ERR PFX "failed to get irq resouce\n");
+- return -ENOENT;
+- }
+-
+- /* get the memory region for the tv scaler driver */
+-
+- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+- if(res == NULL) {
+- printk(KERN_ERR PFX "failed to get memory region resouce\n");
+- return -ENOENT;
+- }
+-
+- s3c_tvenc_mem = request_mem_region(res->start, res->end-res->start+1, pdev->name);
+- if(s3c_tvenc_mem == NULL) {
+- printk(KERN_ERR PFX "failed to reserve memory region\n");
+- return -ENOENT;
+- }
+-
+-
+- base = ioremap(s3c_tvenc_mem->start, s3c_tvenc_mem->end - res->start + 1);
+- if(s3c_tvenc_mem == NULL) {
+- printk(KERN_ERR PFX "failed ioremap\n");
+- return -ENOENT;
+- }
+-
+- tvenc_clock = clk_get(&pdev->dev, "tv_encoder");
+- if(tvenc_clock == NULL) {
+- printk(KERN_ERR PFX "failed to find tvenc clock source\n");
+- return -ENOENT;
+- }
+-
+- clk_enable(tvenc_clock);
+-
+- h_clk = clk_get(&pdev->dev, "hclk");
+- if(h_clk == NULL) {
+- printk(KERN_ERR PFX "failed to find h_clk clock source\n");
+- return -ENOENT;
+- }
+-
+- init_waitqueue_head(&waitq);
+-
+- tv_param.v = video_device_alloc();
+- if(!tv_param.v) {
+- printk(KERN_ERR "s3c-tvenc: video_device_alloc() failed\n");
+- return -ENOMEM;
+- }
+- memcpy(tv_param.v, &tvencoder, sizeof(tvencoder));
+- if(video_register_device(tv_param.v, VFL_TYPE_GRABBER, TVENC_MINOR) != 0) {
+- printk("s3c_camera_driver.c : Couldn't register this codec driver.\n");
+- return 0;
+- }
+-
+- ret = request_irq(s3c_tvenc_irq, s3c_tvenc_isr, SA_INTERRUPT,
+- "TV_ENCODER", NULL);
+- if (ret) {
+- printk("request_irq(TV_ENCODER) failed.\n");
+- return ret;
+- }
+-
+- printk(" Success\n");
+- return 0;
+-}
+-
+-static int s3c_tvenc_remove(struct platform_device *dev)
+-{
+- printk(KERN_INFO "s3c_tvenc_remove called !\n");
+- clk_disable(tvenc_clock);
+- free_irq(s3c_tvenc_irq, NULL);
+- if (s3c_tvenc_mem != NULL) {
+- pr_debug("s3-tvenc: releasing s3c_tvenc_mem\n");
+- iounmap(base);
+- release_resource(s3c_tvenc_mem);
+- kfree(s3c_tvenc_mem);
+- }
+-// video_unregister_device(tv_param.v);
+- return 0;
+-}
+-
+-static int s3c_tvenc_suspend(struct platform_device *dev, pm_message_t state)
+-{
+- clk_disable(tvenc_clock);
+- return 0;
+-}
+-
+-static int s3c_tvenc_resume(struct platform_device *pdev)
+-{
+- clk_enable(tvenc_clock);
+- return 0;
+-}
+-
+-static struct platform_driver s3c_tvenc_driver = {
+- .probe = s3c_tvenc_probe,
+- .remove = s3c_tvenc_remove,
+- .suspend = s3c_tvenc_suspend,
+- .resume = s3c_tvenc_resume,
+- .driver = {
+- .owner = THIS_MODULE,
+- .name = "s3c-tvenc",
+- },
+-};
+-
+-static char banner[] __initdata = KERN_INFO "S3C6410 TV encoder Driver, (c) 2008 Samsung Electronics\n";
+-
+-static int __init s3c_tvenc_init(void)
+-{
+-
+- printk(banner);
+-
+- if(platform_driver_register(&s3c_tvenc_driver) != 0)
+- {
+- printk("Platform Device Register Failed \n");
+- return -1;
+- }
+-
+- printk(" S3C6410 TV encoder Driver module init OK. \n");
+- return 0;
+-}
+-
+-static void __exit s3c_tvenc_exit(void)
+-{
+-
+- video_unregister_device(tv_param.v);
+- platform_driver_unregister(&s3c_tvenc_driver);
+-
+- printk("S3C6410 TV encoder Driver module exit. \n");
+-}
+-
+-
+-module_init(s3c_tvenc_init);
+-module_exit(s3c_tvenc_exit);
+-
+-
+-MODULE_AUTHOR("Peter, Oh");
+-MODULE_DESCRIPTION("S3C TV Encoder Device Driver");
+-MODULE_LICENSE("GPL");
+diff --git a/drivers/media/video/samsung/s3c-tvenc.h b/drivers/media/video/samsung/s3c-tvenc.h
+deleted file mode 100644
+index 30a66a2..0000000
+--- a/drivers/media/video/samsung/s3c-tvenc.h
++++ /dev/null
+@@ -1,165 +0,0 @@
+-#ifndef __S3CTVENC_H_
+-#define __S3CTVENC_H_
+-
+-#include "s3c-tvscaler.h"
+-
+-
+-#define TVENC_IOCTL_MAGIC 'T'
+-
+-typedef struct {
+-
+-} s3c_tvenc_info;
+-
+-#define TV_ON _IO(TVENC_IOCTL_MAGIC, 0)
+-#define TV_OFF _IO(TVENC_IOCTL_MAGIC, 1)
+-#define SELECT_TV_OUT_FORMAT _IO(TVENC_IOCTL_MAGIC, 2)
+-
+-#define TVENC_IOCTL_MAXNR 6
+-
+-#define TVENC_MINOR 14 // Just some number
+-
+-typedef enum {
+- OFF,
+- ON
+-} tv_enc_switch_t;
+-
+-typedef enum {
+- NTSC_M,
+- PAL_M,
+- PAL_BGHID,
+- PAL_N,
+- PAL_NC,
+- PAL_60,
+- NTSC_443,
+- NTSC_J
+-} tv_standard_t;
+-
+-typedef enum {
+- QCIF, CIF/*352x288*/,
+- QQVGA, QVGA, VGA, SVGA/*800x600*/, SXGA/*1280x1024*/, UXGA/*1600x1200*/, QXGA/*2048x1536*/,
+- WVGA/*854x480*/, HD720/*1280x720*/, HD1080/*1920x1080*/
+-} img_size_t;
+-
+-typedef enum {
+- BLACKSTRETCH, WHITESTRETCH, BLUESTRETCH
+-} stretch_color_t;
+-
+-typedef enum {
+- COMPOSITE, S_VIDEO
+-} tv_conn_type_t;
+-
+-typedef enum {
+- BLACK, BLUE, RED, MAGENTA, GREEN, CYAN, YELLOW, WHITE
+-} bg_color_t;
+-
+-typedef enum {
+- MUTE_Y, MUTE_CB, MUTE_CR
+-} mute_type_t;
+-
+-typedef enum {
+- AGC4L, AGC2L, N01, N02, P01, P02
+-} macro_pattern_t;
+-
+-typedef enum {
+- LCD_RGB, LCD_TV, LCD_I80F, LCD_I80S,
+- LCD_TVRGB, LCD_TVI80F, LCD_TVI80S
+-} lcd_local_output_t;
+-
+-/* when App want to change v4l2 parameter,
+- * we instantly store it into v4l2_t v2
+- * and then reflect it to hardware
+- */
+-typedef struct v4l2 {
+- struct v4l2_fmtdesc *fmtdesc;
+-// struct v4l2_framebuffer frmbuf; /* current frame buffer */
+- struct v4l2_pix_format pixfmt;
+- struct v4l2_input *input;
+- struct v4l2_output *output;
+-// enum v4l2_status status;
+-} v4l2_t;
+-
+-
+-typedef struct {
+- tv_standard_t sig_type;
+- tv_conn_type_t connect;
+- /* Width of input image. The input value is twice original output image
+- * width. For example, you must set 1440 when the image width is 720.
+- * Max value is 1440
+- */
+- unsigned int in_width;
+- /* Height of input image
+- * Max value is 576
+- */
+- unsigned int in_height;
+-
+- // Setting value of VIDOUT[28:26] in Display
+- // controller(VIDCON0)
+- lcd_local_output_t lcd_output_mode;
+- // Set CLKVAL_F[13:6] of VIDCON0 with
+- // this value
+- unsigned int lcd_clkval_f;
+-
+- // Flag of lcd rgb port
+- // 0 : disable, 1 : enable
+- unsigned int lcd_rgb_port_flag;
+-
+- scaler_params_t sp;
+-
+- struct video_device *v;
+- v4l2_t v2;
+-
+-} tv_out_params_t;
+-
+-#define V4L2_INPUT_TYPE_MSDMA 3
+-#define V4L2_INPUT_TYPE_FIFO 4
+-#define V4L2_OUTPUT_TYPE_MSDMA 4
+-
+-#define FORMAT_FLAGS_DITHER 0x01
+-#define FORMAT_FLAGS_PACKED 0x02
+-#define FORMAT_FLAGS_PLANAR 0x04
+-#define FORMAT_FLAGS_RAW 0x08
+-#define FORMAT_FLAGS_CrCb 0x10
+-
+-/****************************************************************
+-* struct v4l2_control
+-* Control IDs defined by S3C
+-*****************************************************************/
+-
+-/* TV-OUT connector type */
+-#define V4L2_CID_CONNECT_TYPE (V4L2_CID_PRIVATE_BASE+0)
+-
+-/****************************************************************
+-* I O C T L C O D E S F O R V I D E O D E V I C E S
+-* It's only for S3C
+-*****************************************************************/
+-#define VIDIOC_S_TVOUT_ON _IO ('V', BASE_VIDIOC_PRIVATE+0)
+-#define VIDIOC_S_TVOUT_OFF _IO ('V', BASE_VIDIOC_PRIVATE+1)
+-#define VIDIOC_S_SCALER_TEST _IO ('V', BASE_VIDIOC_PRIVATE+3)
+-
+-
+-extern void s3c_tvscaler_config(scaler_params_t * sp);
+-extern void s3c_tvscaler_int_enable(unsigned int int_type);
+-extern void s3c_tvscaler_int_disable(void);
+-extern void s3c_tvscaler_start(void);
+-extern void s3c_tvscaler_stop_freerun(void);
+-extern void s3c_tvscaler_init(void);
+-extern void s3c_tvscaler_set_interlace(unsigned int on_off);
+-extern int video_exclusive_release(struct inode * inode, struct file * file);
+-extern int video_exclusive_open(struct inode * inode, struct file * file);
+-
+-#if 0 // peter for 2.6.21 kernel
+-extern void s3c_fb_start_lcd(void);
+-extern void s3c_fb_stop_lcd(void);
+-extern void s3c_fb_set_output_path(int out);
+-extern void s3c_fb_set_clkval(unsigned int clkval);
+-extern void s3c_fb_enable_rgbport(unsigned int on_off);
+-#else // peter for 2.6.24 kernel
+-extern void s3cfb_start_lcd(void);
+-extern void s3cfb_stop_lcd(void);
+-extern void s3cfb_set_output_path(int out);
+-extern void s3cfb_set_clock(unsigned int clkval);
+-extern void s3cfb_enable_rgbport(unsigned int on_off);
+-#endif
+-
+-
+-#endif // __S3CTVENC_H_
+diff --git a/drivers/media/video/samsung/s3c-tvscaler.c b/drivers/media/video/samsung/s3c-tvscaler.c
+deleted file mode 100644
+index 376c866..0000000
+--- a/drivers/media/video/samsung/s3c-tvscaler.c
++++ /dev/null
+@@ -1,802 +0,0 @@
+-
+-/*
+- * linux/drivers/tvenc/s3c-tvscaler.c
+- *
+- * Revision 1.0
+- *
+- *
+- * This file is subject to the terms and conditions of the GNU General Public
+- * License. See the file COPYING in the main directory of this archive for
+- * more details.
+- *
+- * S3C TV Scaler driver
+- *
+- */
+-
+-#include <linux/init.h>
+-#include <linux/module.h>
+-#include <linux/moduleparam.h>
+-#include <linux/types.h>
+-#include <linux/timer.h>
+-#include <linux/kernel.h>
+-#include <linux/fs.h>
+-#include <linux/platform_device.h>
+-#include <linux/interrupt.h>
+-#include <linux/clk.h>
+-#include <linux/delay.h>
+-#include <asm/uaccess.h>
+-#include <linux/errno.h> /* error codes */
+-#include <asm/div64.h>
+-#include <linux/mm.h>
+-#include <linux/tty.h>
+-#include <asm/io.h>
+-#include <asm/irq.h>
+-#include <asm/hardware.h>
+-#include <asm/uaccess.h>
+-#include <asm/arch/map.h>
+-#include <linux/miscdevice.h>
+-
+-#include <linux/version.h>
+-#if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,16)
+-#include <linux/config.h>
+-#include <asm/arch/registers.h>
+-#else
+-#include <asm/arch/regs-tvscaler.h>
+-#include <asm/arch/regs-s3c6400-clock.h>
+-#endif
+-
+-#include "s3c-tvscaler.h"
+-
+-#define PFX "s3c_tv_scaler"
+-
+-#define SINGLE_BUF 1 // Single buffer mode
+-
+-
+-static struct clk *h_clk;
+-static struct clk *tvscaler_clock;
+-static void __iomem *base;
+-static int s3c_tvscaler_irq = NO_IRQ;
+-static struct resource *s3c_tvscaler_mem;
+-
+-
+-//static unsigned char *addr_start_y;
+-//static unsigned char *addr_start_rgb;
+-
+-static wait_queue_head_t waitq;
+-
+-irqreturn_t s3c_tvscaler_isr(int irq, void *dev_id,
+- struct pt_regs *regs)
+-{
+- u32 mode;
+- mode = __raw_readl(base + S3C_MODE);
+- mode &= ~(1 << 6); /* Clear Source in POST Processor */
+- __raw_writel(mode, base + S3C_MODE);
+-
+-// wake_up_interruptible(&waitq);
+- return IRQ_HANDLED;
+-}
+-
+-#if 0
+-static buff_addr_t buf_addr = { NULL };
+-
+-
+-static u32 post_alloc_pre_buff(scaler_params_t *sp)
+-{
+- u32 size;
+-
+-#ifdef USE_DEDICATED_MEM
+-
+- buf_addr.pre_phy_addr = PHYS_OFFSET + (SYSTEM_RAM - RESERVE_POST_MEM);
+- buf_addr.pre_virt_addr = ioremap_nocache(buf_addr.pre_phy_addr, PRE_BUFF_SIZE);
+- if( !buf_addr.pre_virt_addr ) {
+- printk(KERN_ERR "%s: Failed to allocate pre buffer \n",__FUNCTION__);
+- return -ENOMEM;
+- }
+-
+- sp->SrcFrmSt = buf_addr.pre_phy_addr;
+-#else
+- size = sp->SrcWidth * sp->SrcHeight * 2;
+- addr_start_y = kmalloc(size, GFP_DMA);
+- if(addr_start_y != NULL) return -ENOMEM;
+-#endif
+- return 0;
+-}
+-
+-static u32 post_alloc_post_buff(scaler_params_t *sp)
+-{
+- u32 size;
+-
+-#ifdef USE_DEDICATED_MEM
+-
+- buf_addr.post_phy_addr = PHYS_OFFSET + (SYSTEM_RAM - RESERVE_POST_MEM + PRE_BUFF_SIZE);
+- buf_addr.post_virt_addr = ioremap_nocache(buf_addr.post_phy_addr, POST_BUFF_SIZE);
+- if( !buf_addr.post_virt_addr ) {
+- printk(KERN_ERR "%s: Failed to allocate post buffer \n",__FUNCTION__);
+- return -ENOMEM;
+- }
+-
+- sp->DstFrmSt = buf_addr.post_phy_addr;
+-#else
+- size = sp->DstWidth * sp->DstHeight * 2;
+- addr_start_rgb = kmalloc(size, GFP_DMA);
+- if(addr_start_rgb != NULL) return -ENOMEM;
+-#endif
+- return 0;
+-}
+-
+-static u32 post_free_all_buffer(void)
+-{
+-#ifdef USE_DEDICATED_MEM
+- if( buf_addr.pre_virt_addr ) {
+- iounmap(buf_addr.pre_virt_addr);
+- }
+- if( buf_addr.post_virt_addr ) {
+- iounmap(buf_addr.post_virt_addr);
+- }
+-#endif
+- return 0;
+-}
+-#endif
+-
+-static void s3c_tvscaler_set_clk_src(scaler_clk_src_t clk_src)
+-{
+- u32 tmp, rate;
+-
+- tmp = __raw_readl(base + S3C_MODE);
+-
+- h_clk = clk_get(NULL, "hclk");
+-
+- rate = clk_get_rate(h_clk);
+-
+- if(clk_src == HCLK) {
+- if(rate > 66000000) {
+- tmp &= ~(0x7f<<23);
+- tmp |= (1<<24);
+- tmp |= (1<<23);
+- } else {
+- tmp &=~ (0x7f<<23);
+- }
+-
+- } else if(clk_src == PLL_EXT) {
+- } else {
+- tmp &=~(0x7f<<23);
+- }
+-
+- tmp = (tmp &~ (0x3<<21)) | (clk_src<<21);
+-
+- __raw_writel(tmp, base + S3C_MODE);
+-}
+-
+-static void s3c_tvscaler_set_fmt(cspace_t src, cspace_t dst, s3c_scaler_path_t in,
+- s3c_scaler_path_t out, u32 *in_pixel_size,
+- u32 *out_pixel_size)
+-{
+- u32 tmp;
+-
+- tmp = __raw_readl(base + S3C_MODE);
+- tmp |= (0x1<<16);
+- tmp |= (0x2<<10);
+-
+- if(in == POST_DMA) {
+-
+- switch(src) {
+- case YC420:
+- tmp &=~((0x1<<3)|(0x1<<2));
+- tmp |= (0x1<<8)|(0x1<<1);
+- *in_pixel_size = 1;
+- break;
+- case CRYCBY:
+- tmp &= ~((0x1<<15)|(0x1<<8)|(0x1<<3)|(0x1<<0));
+- tmp |= (0x1<<2)|(0x1<<1);
+- *in_pixel_size = 2;
+- break;
+- case CBYCRY:
+- tmp &= ~((0x1<<8)|(0x1<<3)|(0x1<<0));
+- tmp |= (0x1<<15)|(0x1<<2)|(0x1<<1);
+- *in_pixel_size = 2;
+- break;
+- case YCRYCB:
+- tmp &= ~((0x1<<15)|(0x1<<8)|(0x1<<3));
+- tmp |= (0x1<<2)|(0x1<<1)|(0x1<<0);
+- *in_pixel_size = 2;
+- break;
+- case YCBYCR:
+- tmp &= ~((0x1<<8)|(0x1<<3));
+- tmp |= (0x1<<15)|(0x1<<2)|(0x1<<1)|(0x1<<0);
+- *in_pixel_size = 2;
+- break;
+- case RGB24:
+- tmp &= ~(0x1<<8);
+- tmp |= (0x1<<3)|(0x1<<2)|(0x1<<1);
+- *in_pixel_size = 4;
+- break;
+- case RGB16:
+- tmp &= ~((0x1<<8)|(0x1<<1));
+- tmp |= (0x1<<3)|(0x1<<2);
+- *in_pixel_size = 2;
+- break;
+- default:
+- break;
+- }
+-
+- }
+- else if(in == POST_FIFO) {
+- }
+-
+- if(out == POST_DMA) {
+- switch(dst) {
+- case YC420:
+- tmp &= ~(0x1<<18);
+- tmp |= (0x1<<17);
+- *out_pixel_size = 1;
+- break;
+- case CRYCBY:
+- tmp &= ~((0x1<<20)|(0x1<<19)|(0x1<<18)|(0x1<<17));
+- *out_pixel_size = 2;
+- break;
+- case CBYCRY:
+- tmp &= ~((0x1<<19)|(0x1<<18)|(0x1<<17));
+- tmp |= (0x1<<20);
+- *out_pixel_size = 2;
+- break;
+- case YCRYCB:
+- tmp &= ~((0x1<<20)|(0x1<<18)|(0x1<<17));
+- tmp |= (0x1<<19);
+- *out_pixel_size = 2;
+- break;
+- case YCBYCR:
+- tmp &= ~((0x1<<18)|(0x1<<17));
+- tmp |= (0x1<<20)|(0x1<<19);
+- *out_pixel_size = 2;
+- break;
+- case RGB24:
+- tmp |= (0x1<<18)|(0x1<<4);
+- *out_pixel_size = 4;
+- break;
+- case RGB16:
+- tmp &= ~(0x1<<4);
+- tmp |= (0x1<<18);
+- *out_pixel_size = 2;
+- break;
+- default:
+- break;
+- }
+- }
+- else if(out == POST_FIFO) {
+- if(dst == RGB24) {
+- tmp |= (0x1<<18)|(0x1<<13);
+-
+- } else if(dst == YCBYCR) {
+- tmp |= (0x1<<13);
+- tmp &= ~(0x1<<18)|(0x1<<17);
+- } else {
+- }
+- }
+-
+- __raw_writel(tmp, base + S3C_MODE);
+-}
+-
+-static void s3c_tvscaler_set_path(s3c_scaler_path_t in, s3c_scaler_path_t out)
+-{
+- u32 tmp;
+-
+- tmp = __raw_readl(base + S3C_MODE);
+-
+- tmp &=~(0x1<<12); // 0: progressive mode, 1: interlace mode
+-
+- if(in == POST_FIFO) {
+- tmp |= (0x1<<31);
+- } else if(in == POST_DMA) {
+- tmp &=~(0x1<<31);
+- }
+-
+- if(out == POST_FIFO) {
+- tmp |= (0x1<<13);
+- } else if(out == POST_DMA) {
+- tmp &=~(0x1<<13);
+- }
+-
+- __raw_writel(tmp, base + S3C_MODE);
+-}
+-
+-static void s3c_tvscaler_set_addr(scaler_params_t *sp, u32 in_pixel_size, u32 out_pixel_size)
+-{
+- u32 offset_y, offset_cb, offset_cr;
+- u32 src_start_y, src_start_cb, src_start_cr;
+- u32 src_end_y, src_end_cb, src_end_cr;
+- u32 start_pos_y, end_pos_y;
+- u32 start_pos_cb, end_pos_cb;
+- u32 start_pos_cr, end_pos_cr;
+- u32 start_pos_rgb, end_pos_rgb;
+- u32 dst_start_rgb, dst_end_rgb;
+- u32 src_frm_start_addr;
+-
+- u32 offset_rgb, out_offset_cb, out_offset_cr;
+- u32 out_start_pos_cb, out_start_pos_cr;
+- u32 out_end_pos_cb, out_end_pos_cr;
+- u32 out_src_start_cb, out_src_start_cr;
+- u32 out_src_end_cb, out_src_end_cr;
+-
+- if(sp->InPath == POST_DMA) {
+- offset_y = (sp->SrcFullWidth - sp->SrcWidth) * in_pixel_size;
+- start_pos_y = (sp->SrcFullWidth*sp->SrcStartY+sp->SrcStartX)*in_pixel_size;
+- end_pos_y = sp->SrcWidth*sp->SrcHeight*in_pixel_size + offset_y*(sp->SrcHeight-1);
+- src_frm_start_addr = sp->SrcFrmSt;
+- src_start_y = sp->SrcFrmSt + start_pos_y;
+- src_end_y = src_start_y + end_pos_y;
+-
+- __raw_writel(src_start_y, base + S3C_ADDRSTART_Y);
+- __raw_writel(offset_y, base + S3C_OFFSET_Y);
+- __raw_writel(src_end_y, base + S3C_ADDREND_Y);
+-
+- if(sp->SrcCSpace == YC420) {
+- offset_cb = offset_cr = ((sp->SrcFullWidth - sp->SrcWidth) / 2) * in_pixel_size;
+- start_pos_cb = sp->SrcFullWidth * sp->SrcFullHeight * 1 \
+- + (sp->SrcFullWidth * sp->SrcStartY / 2 + sp->SrcStartX) /2 * 1;
+-
+- end_pos_cb = sp->SrcWidth/2*sp->SrcHeight/2*in_pixel_size \
+- + (sp->SrcHeight/2 -1)*offset_cb;
+- start_pos_cr = sp->SrcFullWidth * sp->SrcFullHeight *1 \
+- + sp->SrcFullWidth*sp->SrcFullHeight/4 *1 \
+- + (sp->SrcFullWidth*sp->SrcStartY/2 + sp->SrcStartX)/2*1;
+- end_pos_cr = sp->SrcWidth/2*sp->SrcHeight/2*in_pixel_size \
+- + (sp->SrcHeight/2-1)*offset_cr;
+-
+- src_start_cb = sp->SrcFrmSt + start_pos_cb;
+- src_end_cb = src_start_cb + end_pos_cb;
+-
+- src_start_cr = sp->SrcFrmSt + start_pos_cr;
+- src_end_cr = src_start_cr + end_pos_cr;
+-
+- __raw_writel(src_start_cb, base + S3C_ADDRSTART_CB);
+- __raw_writel(offset_cr, base + S3C_OFFSET_CB);
+- __raw_writel(src_end_cb, base + S3C_ADDREND_CB);
+- __raw_writel(src_start_cr, base + S3C_ADDRSTART_CR);
+- __raw_writel(offset_cb, base + S3C_OFFSET_CR);
+- __raw_writel(src_end_cr, base + S3C_ADDREND_CR);
+- }
+- }
+- if(sp->OutPath == POST_DMA) {
+- offset_rgb = (sp->DstFullWidth - sp->DstWidth)*out_pixel_size;
+- start_pos_rgb = (sp->DstFullWidth*sp->DstStartY + sp->DstStartX)*out_pixel_size;
+- end_pos_rgb = sp->DstWidth*sp->DstHeight*out_pixel_size + offset_rgb*(sp->DstHeight - 1);
+- dst_start_rgb = sp->DstFrmSt + start_pos_rgb;
+- dst_end_rgb = dst_start_rgb + end_pos_rgb;
+-
+- __raw_writel(dst_start_rgb, base + S3C_ADDRSTART_RGB);
+- __raw_writel(offset_rgb, base + S3C_OFFSET_RGB);
+- __raw_writel(dst_end_rgb, base + S3C_ADDREND_RGB);
+-
+- if(sp->DstCSpace == YC420) {
+- out_offset_cb = out_offset_cr = ((sp->DstFullWidth - sp->DstWidth)/2)*out_pixel_size;
+- out_start_pos_cb = sp->DstFullWidth*sp->DstFullHeight*1 \
+- + (sp->DstFullWidth*sp->DstStartY/2 + sp->DstStartX)/2*1;
+- out_end_pos_cb = sp->DstWidth/2*sp->DstHeight/2*out_pixel_size \
+- + (sp->DstHeight/2 -1)*out_offset_cr;
+-
+- out_start_pos_cr = sp->DstFullWidth*sp->DstFullHeight*1 \
+- + (sp->DstFullWidth*sp->DstFullHeight/4)*1 \
+- + (sp->DstFullWidth*sp->DstStartY/2 +sp->DstStartX)/2*1;
+- out_end_pos_cr = sp->DstWidth/2*sp->DstHeight/2*out_pixel_size \
+- + (sp->DstHeight/2 -1)*out_offset_cb;
+-
+- out_src_start_cb = sp->DstFrmSt + out_start_pos_cb;
+- out_src_end_cb = out_src_start_cb + out_end_pos_cb;
+- out_src_start_cr = sp->DstFrmSt + out_start_pos_cr;
+- out_src_end_cr = out_src_start_cr + out_end_pos_cr;
+-
+- __raw_writel(out_src_start_cb, base + S3C_ADDRSTART_OCB);
+- __raw_writel(out_offset_cb, base + S3C_OFFSET_OCB);
+- __raw_writel(out_src_end_cb, base + S3C_ADDREND_OCB);
+- __raw_writel(out_src_start_cr, base + S3C_ADDRSTART_OCR);
+- __raw_writel(out_offset_cr, base + S3C_OFFSET_OCR);
+- __raw_writel(out_src_end_cr, base + S3C_ADDREND_OCR);
+-
+- }
+- }
+-
+-
+-}
+-
+-#if 0
+-static void s3c_tvscaler_set_fifo_in(s3c_scaler_path_t in_path)
+-{
+- u32 tmp;
+-
+- tmp = __raw_readl(base + S3C_MODE);
+-
+- if(in_path == POST_FIFO) tmp |= (0x1<<31);
+- else tmp &=~(0x1<<31);
+-
+- __raw_writel(tmp, base + S3C_MODE);
+-
+-}
+-#endif
+-
+-void s3c_tvscaler_set_interlace(u32 on_off)
+-{
+- u32 tmp;
+-
+- tmp = __raw_readl(base + S3C_MODE);
+-
+- if(on_off == 1) tmp |=(1<<12);
+- else tmp &=~(1<<12);
+-
+- __raw_writel(tmp, base + S3C_MODE);
+-}
+-EXPORT_SYMBOL(s3c_tvscaler_set_interlace);
+-
+-static void s3c_tvscaler_set_size(scaler_params_t *sp)
+-{
+- u32 pre_h_ratio, pre_v_ratio, h_shift, v_shift, sh_factor;
+- u32 pre_dst_width, pre_dst_height, dx, dy;
+-
+- if (sp->SrcWidth >= (sp->DstWidth<<6)) {
+- printk("Out of PreScalar range !!!\n");
+- return;
+- }
+- if(sp->SrcWidth >= (sp->DstWidth<<5)) {
+- pre_h_ratio = 32;
+- h_shift = 5;
+- } else if(sp->SrcWidth >= (sp->DstWidth<<4)) {
+- pre_h_ratio = 16;
+- h_shift = 4;
+- } else if(sp->SrcWidth >= (sp->DstWidth<<3)) {
+- pre_h_ratio = 8;
+- h_shift = 3;
+- } else if(sp->SrcWidth >= (sp->DstWidth<<2)) {
+- pre_h_ratio = 4;
+- h_shift = 2;
+- } else if(sp->SrcWidth >= (sp->DstWidth<<1)) {
+- pre_h_ratio = 2;
+- h_shift = 1;
+- } else {
+- pre_h_ratio = 1;
+- h_shift = 0;
+- }
+-
+- pre_dst_width = sp->SrcWidth / pre_h_ratio;
+- dx = (sp->SrcWidth<<8) / (sp->DstWidth<<h_shift);
+-
+-
+- if (sp->SrcHeight >= (sp->DstHeight<<6)) {
+- printk("Out of PreScalar range !!!\n");
+- return;
+- }
+- if(sp->SrcHeight>= (sp->DstHeight<<5)) {
+- pre_v_ratio = 32;
+- v_shift = 5;
+- } else if(sp->SrcHeight >= (sp->DstHeight<<4)) {
+- pre_v_ratio = 16;
+- v_shift = 4;
+- } else if(sp->SrcHeight >= (sp->DstHeight<<3)) {
+- pre_v_ratio = 8;
+- v_shift = 3;
+- } else if(sp->SrcHeight >= (sp->DstHeight<<2)) {
+- pre_v_ratio = 4;
+- v_shift = 2;
+- } else if(sp->SrcHeight >= (sp->DstHeight<<1)) {
+- pre_v_ratio = 2;
+- v_shift = 1;
+- } else {
+- pre_v_ratio = 1;
+- v_shift = 0;
+- }
+-
+- pre_dst_height = sp->SrcHeight / pre_v_ratio;
+- dy = (sp->SrcHeight<<8) / (sp->DstHeight<<v_shift);
+- sh_factor = 10 - (h_shift + v_shift);
+-
+- __raw_writel((pre_v_ratio<<7)|(pre_h_ratio<<0), base + S3C_PRESCALE_RATIO);
+- __raw_writel((pre_dst_height<<12)|(pre_dst_width<<0), base + S3C_PRESCALEIMGSIZE);
+- __raw_writel(sh_factor, base + S3C_PRESCALE_SHFACTOR);
+- __raw_writel(dx, base + S3C_MAINSCALE_H_RATIO);
+- __raw_writel(dy, base + S3C_MAINSCALE_V_RATIO);
+- __raw_writel((sp->SrcHeight<<12)|(sp->SrcWidth), base + S3C_SRCIMGSIZE);
+- __raw_writel((sp->DstHeight<<12)|(sp->DstWidth), base + S3C_DSTIMGSIZE);
+-
+-}
+-
+-
+-static void s3c_tvscaler_set_auto_load(scaler_params_t *sp)
+-{
+- u32 tmp;
+-
+- tmp = __raw_readl(base + S3C_MODE);
+-
+- if(sp->Mode == FREE_RUN) {
+- tmp |= (1<<14);
+- } else if(sp->Mode == ONE_SHOT) {
+- tmp &=~(1<<14);
+- }
+-
+- __raw_writel(tmp, base + S3C_MODE);
+-
+-}
+-
+-void s3c_tvscaler_set_base_addr(void __iomem * base_addr)
+-{
+- base = base_addr;
+-}
+-EXPORT_SYMBOL(s3c_tvscaler_set_base_addr);
+-
+-void s3c_tvscaler_free_base_addr(void)
+-{
+- base = NULL;
+-}
+-EXPORT_SYMBOL(s3c_tvscaler_free_base_addr);
+-
+-void s3c_tvscaler_int_enable(u32 int_type)
+-{
+- u32 tmp;
+-
+- tmp = __raw_readl(base + S3C_MODE);
+-
+- if(int_type == 0) { //Edge triggering
+- tmp &= ~(S3C_MODE_IRQ_LEVEL);
+- } else if(int_type == 1) { //level triggering
+- tmp |= S3C_MODE_IRQ_LEVEL;
+- }
+-
+- tmp |= S3C_MODE_POST_INT_ENABLE;
+-
+- __raw_writel(tmp, base + S3C_MODE);
+-}
+-EXPORT_SYMBOL(s3c_tvscaler_int_enable);
+-
+-void s3c_tvscaler_int_disable(void)
+-{
+- u32 tmp;
+-
+- tmp = __raw_readl(base + S3C_MODE);
+-
+- tmp &=~ (S3C_MODE_POST_INT_ENABLE);
+-
+- __raw_writel(tmp, base + S3C_MODE);
+-
+-}
+-EXPORT_SYMBOL(s3c_tvscaler_int_disable);
+-
+-
+-void s3c_tvscaler_start(void)
+-{
+- __raw_writel(S3C_POSTENVID_ENABLE, base + S3C_POSTENVID);
+-
+-}
+-EXPORT_SYMBOL(s3c_tvscaler_start);
+-
+-void s3c_tvscaler_stop_freerun(void)
+-{
+- u32 tmp;
+-
+- tmp = __raw_readl(base + S3C_MODE);
+-
+- tmp &=~(1<<14);
+-
+- __raw_writel(tmp, base + S3C_MODE);
+-}
+-EXPORT_SYMBOL(s3c_tvscaler_stop_freerun);
+-
+-
+-void s3c_tvscaler_config(scaler_params_t *sp)
+-{
+- u32 tmp = 0;
+- u32 in_pixel_size = 0;
+- u32 out_pixel_size = 0;
+- u32 loop = 0;
+-
+- tmp = __raw_readl(base + S3C_POSTENVID);
+- tmp &= ~S3C_POSTENVID_ENABLE;
+- __raw_writel(tmp, base + S3C_POSTENVID);
+-#ifdef SINGLE_BUF
+- tmp = S3C_MODE2_ADDR_CHANGE_DISABLE |S3C_MODE2_CHANGE_AT_FRAME_END |S3C_MODE2_SOFTWARE_TRIGGER;
+-#else
+- tmp = S3C_MODE2_ADDR_CHANGE_ENABLE |S3C_MODE2_CHANGE_AT_FRAME_END |S3C_MODE2_SOFTWARE_TRIGGER;
+-#endif
+- __raw_writel(tmp, base + S3C_MODE2);
+-
+-// peter mod. start
+- sp->DstStartX = sp->DstStartY = 0;
+- sp->DstWidth = sp->DstFullWidth;
+- sp->DstHeight = sp->DstFullHeight;
+-// peter mod. end
+-
+- sp->DstFrmSt = ( POST_BUFF_BASE_ADDR + PRE_BUFF_SIZE );
+- //printk("\n---peter s3c_tvscaler_config : SrcFrmSt = 0x%08x\n", sp->SrcFrmSt);
+- //printk("---peter s3c_tvscaler_config : DstFrmSt = 0x%08x\n", sp->DstFrmSt);
+-
+- s3c_tvscaler_set_clk_src(HCLK);
+-
+- s3c_tvscaler_set_path(sp->InPath, sp->OutPath);
+-
+- s3c_tvscaler_set_fmt(sp->SrcCSpace, sp->DstCSpace, sp->InPath,
+- sp->OutPath, &in_pixel_size, &out_pixel_size);
+-
+- s3c_tvscaler_set_size(sp);
+-
+- s3c_tvscaler_set_addr(sp, in_pixel_size, out_pixel_size);
+-
+- s3c_tvscaler_set_auto_load(sp);
+-
+-}
+-EXPORT_SYMBOL(s3c_tvscaler_config);
+-
+-void s3c_tvscaler_set_param(scaler_params_t *sp)
+-{
+-#if 0
+- param.SrcFullWidth = sp->SrcFullWidth;
+- param.SrcFullHeight = sp->SrcFullHeight;
+- param.SrcStartX = sp->SrcStartX;
+- param.SrcStartY = sp->SrcStartY;
+- param.SrcWidth = sp->SrcWidth;
+- param.SrcHeight = sp->SrcHeight;
+- param.SrcFrmSt = sp->SrcFrmSt;
+- param.SrcCSpace = sp->SrcCSpace;
+- param.DstFullWidth = sp->DstFullWidth;
+- param.DstFullHeight = sp->DstFullHeight;
+- param.DstStartX = sp->DstStartX;
+- param.DstStartY = sp->DstStartY;
+- param.DstWidth = sp->DstWidth;
+- param.DstHeight = sp->DstHeight;
+- param.DstFrmSt = sp->DstFrmSt;
+- param.DstCSpace = sp->DstCSpace;
+- param.SrcFrmBufNum = sp->SrcFrmBufNum;
+- param.DstFrmSt = sp->DstFrmSt;
+- param.Mode = sp->Mode;
+- param.InPath = sp->InPath;
+- param.OutPath = sp->OutPath;
+-#endif
+-}
+-EXPORT_SYMBOL(s3c_tvscaler_set_param);
+-
+-void s3c_tvscaler_init(void)
+-{
+-
+- int tmp;
+-
+- // Use DOUTmpll source clock as a scaler clock
+- tmp = __raw_readl(S3C_CLK_SRC);
+-
+- tmp &=~(0x3<<28);
+- tmp |= (0x1<<28);
+- __raw_writel(tmp, S3C_CLK_SRC);
+-
+- printk(" %s \n", __FUNCTION__);
+-
+-}
+-EXPORT_SYMBOL(s3c_tvscaler_init);
+-
+-
+-static int s3c_tvscaler_probe(struct platform_device *pdev)
+-{
+-
+- struct resource *res;
+-
+- int ret;
+-
+- /* find the IRQs */
+- s3c_tvscaler_irq = platform_get_irq(pdev, 0);
+- if(s3c_tvscaler_irq <= 0) {
+- printk(KERN_ERR PFX "failed to get irq resouce\n");
+- return -ENOENT;
+- }
+-
+- /* get the memory region for the tv scaler driver */
+- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+- if(res == NULL) {
+- printk(KERN_ERR PFX "failed to get memory region resouce\n");
+- return -ENOENT;
+- }
+-
+- s3c_tvscaler_mem = request_mem_region(res->start, res->end-res->start+1, pdev->name);
+- if(s3c_tvscaler_mem == NULL) {
+- printk(KERN_ERR PFX "failed to reserve memory region\n");
+- return -ENOENT;
+- }
+-
+- base = ioremap(s3c_tvscaler_mem->start, s3c_tvscaler_mem->end - res->start + 1);
+- if(s3c_tvscaler_mem == NULL) {
+- printk(KERN_ERR PFX "failed ioremap\n");
+- return -ENOENT;
+- }
+-
+- tvscaler_clock = clk_get(&pdev->dev, "tv_encoder");
+- if(tvscaler_clock == NULL) {
+- printk(KERN_ERR PFX "failed to find tvscaler clock source\n");
+- return -ENOENT;
+- }
+-
+- clk_enable(tvscaler_clock);
+-
+- h_clk = clk_get(&pdev->dev, "hclk");
+- if(h_clk == NULL) {
+- printk(KERN_ERR PFX "failed to find h_clk clock source\n");
+- return -ENOENT;
+- }
+-
+- init_waitqueue_head(&waitq);
+-
+- ret = request_irq(s3c_tvscaler_irq, s3c_tvscaler_isr, SA_INTERRUPT,
+- "TV_SCALER", NULL);
+- if (ret) {
+- printk("request_irq(TV_SCALER) failed.\n");
+- return ret;
+- }
+-
+- printk(" Success\n");
+-
+- return 0;
+-}
+-
+-static int s3c_tvscaler_remove(struct platform_device *dev)
+-{
+- printk(KERN_INFO "s3c_tvscaler_remove called !\n");
+- clk_disable(tvscaler_clock);
+- free_irq(s3c_tvscaler_irq, NULL);
+- if (s3c_tvscaler_mem != NULL) {
+- pr_debug("s3-tvscaler: releasing s3c_tvscaler_mem\n");
+- iounmap(base);
+- release_resource(s3c_tvscaler_mem);
+- kfree(s3c_tvscaler_mem);
+- }
+-
+- return 0;
+-}
+-
+-static int s3c_tvscaler_suspend(struct platform_device *dev, pm_message_t state)
+-{
+- clk_disable(tvscaler_clock);
+- return 0;
+-}
+-
+-static int s3c_tvscaler_resume(struct platform_device *pdev)
+-{
+- clk_enable(tvscaler_clock);
+- return 0;
+-}
+-
+-static struct platform_driver s3c_tvscaler_driver = {
+- .probe = s3c_tvscaler_probe,
+- .remove = s3c_tvscaler_remove,
+- .suspend = s3c_tvscaler_suspend,
+- .resume = s3c_tvscaler_resume,
+- .driver = {
+- .owner = THIS_MODULE,
+- .name = "s3c-tvscaler",
+- },
+-};
+-
+-static char banner[] __initdata = KERN_INFO "S3C6410 TV scaler Driver, (c) 2008 Samsung Electronics\n";
+-
+-
+-int __init s3c_tvscaler_pre_init(void)
+-{
+-
+- printk(banner);
+-
+- if(platform_driver_register(&s3c_tvscaler_driver) != 0)
+- {
+- printk("platform device register Failed \n");
+- return -1;
+- }
+-
+- printk(" S3C6410 TV scaler Driver module init OK. \n");
+-
+- return 0;
+-}
+-
+-void s3c_tvscaler_exit(void)
+-{
+- platform_driver_unregister(&s3c_tvscaler_driver);
+- printk("S3C: tvscaler module exit\n");
+-}
+-
+-module_init(s3c_tvscaler_pre_init);
+-module_exit(s3c_tvscaler_exit);
+-
+-
+-MODULE_AUTHOR("Peter, Oh");
+-MODULE_DESCRIPTION("S3C TV Controller Device Driver");
+-MODULE_LICENSE("GPL");
+-
+-
+diff --git a/drivers/media/video/samsung/s3c-tvscaler.h b/drivers/media/video/samsung/s3c-tvscaler.h
+deleted file mode 100644
+index d8079a3..0000000
+--- a/drivers/media/video/samsung/s3c-tvscaler.h
++++ /dev/null
+@@ -1,96 +0,0 @@
+-#ifndef __S3CTVSCALER_H_
+-#define __S3CTVSCALER_H_
+-
+-#include <asm-arm/arch-s3c2410/reserved_mem.h>
+-
+-#define TVSCALER_IOCTL_MAGIC 'S'
+-
+-#define PPROC_SET_PARAMS _IO(TVSCALER_IOCTL_MAGIC, 0)
+-#define PPROC_START _IO(TVSCALER_IOCTL_MAGIC, 1)
+-#define PPROC_STOP _IO(TVSCALER_IOCTL_MAGIC, 2)
+-#define PPROC_INTERLACE_MODE _IO(TVSCALER_IOCTL_MAGIC, 3)
+-#define PPROC_PROGRESSIVE_MODE _IO(TVSCALER_IOCTL_MAGIC, 4)
+-
+-
+-#define QVGA_XSIZE 320
+-#define QVGA_YSIZE 240
+-
+-#define LCD_XSIZE 320
+-#define LCD_YSIZE 240
+-
+-#define SCALER_MINOR 251 // Just some number
+-
+-
+-//#define SYSTEM_RAM 0x08000000 // 128mb
+-#define SYSTEM_RAM 0x07800000 // 120mb
+-#define RESERVE_POST_MEM 8*1024*1024 // 8mb
+-#define PRE_BUFF_SIZE 4*1024*1024 //4 // 4mb
+-#define POST_BUFF_SIZE ( RESERVE_POST_MEM - PRE_BUFF_SIZE )
+-#if 0
+-#define POST_BUFF_BASE_ADDR (0x50000000 + (SYSTEM_RAM - RESERVE_POST_MEM))
+-#else // TV_RESERVED_MEM_START is defined in the s3c-linux-2.6.21_dev_4_4_15
+-#define POST_BUFF_BASE_ADDR TV_RESERVED_MEM_START
+-#endif
+-
+-#define USE_DEDICATED_MEM 1
+-
+-typedef enum {
+- INTERLACE_MODE,
+- PROGRESSIVE_MODE
+-} s3c_scaler_scan_mode_t;
+-
+-typedef enum {
+- POST_DMA, POST_FIFO
+-} s3c_scaler_path_t;
+-
+-typedef enum {
+- ONE_SHOT, FREE_RUN
+-} s3c_scaler_run_mode_t;
+-
+-typedef enum {
+- PAL1, PAL2, PAL4, PAL8,
+- RGB8, ARGB8, RGB16, ARGB16, RGB18, RGB24, RGB30, ARGB24,
+- YC420, YC422, // Non-interleave
+- CRYCBY, CBYCRY, YCRYCB, YCBYCR, YUV444 // Interleave
+-} cspace_t;
+-
+-typedef enum
+-{
+- HCLK = 0, PLL_EXT = 1, EXT_27MHZ = 3
+-} scaler_clk_src_t;
+-
+-typedef struct{
+- unsigned int SrcFullWidth; // Source Image Full Width(Virtual screen size)
+- unsigned int SrcFullHeight; // Source Image Full Height(Virtual screen size)
+- unsigned int SrcStartX; // Source Image Start width offset
+- unsigned int SrcStartY; // Source Image Start height offset
+- unsigned int SrcWidth; // Source Image Width
+- unsigned int SrcHeight; // Source Image Height
+- unsigned int SrcFrmSt; // Base Address of the Source Image : Physical Address
+- cspace_t SrcCSpace; // Color Space ot the Source Image
+-
+- unsigned int DstFullWidth; // Source Image Full Width(Virtual screen size)
+- unsigned int DstFullHeight; // Source Image Full Height(Virtual screen size)
+- unsigned int DstStartX; // Source Image Start width offset
+- unsigned int DstStartY; // Source Image Start height offset
+- unsigned int DstWidth; // Source Image Width
+- unsigned int DstHeight; // Source Image Height
+- unsigned int DstFrmSt; // Base Address of the Source Image : Physical Address
+- cspace_t DstCSpace; // Color Space ot the Source Image
+-
+- unsigned int SrcFrmBufNum; // Frame buffer number
+- s3c_scaler_run_mode_t Mode; // POST running mode(PER_FRAME or FREE_RUN)
+- s3c_scaler_path_t InPath; // Data path of the source image
+- s3c_scaler_path_t OutPath; // Data path of the desitination image
+-
+-}scaler_params_t;
+-
+-typedef struct{
+- unsigned int pre_phy_addr;
+- unsigned char *pre_virt_addr;
+-
+- unsigned int post_phy_addr;
+- unsigned char *post_virt_addr;
+-} buff_addr_t;
+-
+-#endif //__S3CTVSCALER_H_
+diff --git a/include/asm-arm/arch-s3c2410/reserved_mem.h b/include/asm-arm/arch-s3c2410/reserved_mem.h
+index ba921a4..e6c029d 100644
+--- a/include/asm-arm/arch-s3c2410/reserved_mem.h
++++ b/include/asm-arm/arch-s3c2410/reserved_mem.h
+@@ -17,7 +17,7 @@
+ //#define CONFIG_RESERVED_MEM_JPEG
+ //#define CONFIG_RESERVED_MEM_JPEG_POST
+ //#define CONFIG_RESERVED_MEM_MFC
+-#define CONFIG_RESERVED_MEM_MFC_POST
++//#define CONFIG_RESERVED_MEM_MFC_POST
+ //#define CONFIG_RESERVED_MEM_JPEG_MFC_POST
+ //#define CONFIG_RESERVED_MEM_JPEG_CAMERA
+ //#define CONFIG_RESERVED_MEM_JPEG_POST_CAMERA
+@@ -26,7 +26,7 @@
+ //#define CONFIG_RESERVED_MEM_JPEG_MFC_POST_CAMERA
+ //#define CONFIG_RESERVED_MEM_CMM_MFC_POST
+ //#define CONFIG_RESERVED_MEM_CMM_JPEG_MFC_POST_CAMERA
+-//#define CONFIG_RESERVED_MEM_TV_MFC_POST_CAMERA
++#define CONFIG_RESERVED_MEM_TV_MFC_POST_CAMERA
+
+ #if defined(CONFIG_RESERVED_MEM_JPEG)
+ #define JPEG_RESERVED_MEM_START 0x57800000
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-2.6.24/smartq5/mer/0008-build-TV-by-default.patch b/recipes/linux/linux-2.6.24/smartq5/mer/0008-build-TV-by-default.patch
new file mode 100644
index 0000000000..9425f55361
--- /dev/null
+++ b/recipes/linux/linux-2.6.24/smartq5/mer/0008-build-TV-by-default.patch
@@ -0,0 +1,136 @@
+From fc4f45f5d2c2fd7fa5e4a1b5923129bd6722f102 Mon Sep 17 00:00:00 2001
+From: Carsten V. Munk <carsten.munk@gmail.com>
+Date: Thu, 6 Aug 2009 12:18:57 +0000
+Subject: [PATCH 08/13] build TV by default.
+
+---
+ arch/arm/configs/hhs3c6410_4_3_defconfig | 36 ++++++++++++++++++++-
+ arch/arm/configs/hhs3c6410_7_defconfig | 51 ++++++++++++++++++++++++++++-
+ 2 files changed, 83 insertions(+), 4 deletions(-)
+
+diff --git a/arch/arm/configs/hhs3c6410_4_3_defconfig b/arch/arm/configs/hhs3c6410_4_3_defconfig
+index aa1758a..d503e12 100644
+--- a/arch/arm/configs/hhs3c6410_4_3_defconfig
++++ b/arch/arm/configs/hhs3c6410_4_3_defconfig
+@@ -1,7 +1,7 @@
+ #
+ # Automatically generated make config: don't edit
+ # Linux kernel version: 2.6.24.7
+-# Tue Jun 16 10:48:11 2009
++# Thu Aug 6 11:55:46 2009
+ #
+ CONFIG_ARM=y
+ CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+@@ -910,7 +910,39 @@ CONFIG_SSB_POSSIBLE=y
+ #
+ # Multimedia devices
+ #
+-# CONFIG_VIDEO_DEV is not set
++CONFIG_VIDEO_DEV=m
++# CONFIG_VIDEO_V4L1 is not set
++CONFIG_VIDEO_V4L1_COMPAT=y
++CONFIG_VIDEO_V4L2=y
++CONFIG_VIDEO_CAPTURE_DRIVERS=y
++# CONFIG_VIDEO_ADV_DEBUG is not set
++CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
++# CONFIG_VIDEO_VIVI is not set
++# CONFIG_VIDEO_SAA5246A is not set
++# CONFIG_VIDEO_SAA5249 is not set
++# CONFIG_VIDEO_SAMSUNG is not set
++CONFIG_VIDEO_SAMSUNG_TVENC=m
++CONFIG_VIDEO_SAMSUNG_TVSCALER=m
++CONFIG_V4L_USB_DRIVERS=y
++# CONFIG_VIDEO_PVRUSB2 is not set
++# CONFIG_VIDEO_USBVISION is not set
++# CONFIG_USB_ET61X251 is not set
++# CONFIG_USB_SN9C102 is not set
++# CONFIG_USB_ZC0301 is not set
++# CONFIG_USB_ZR364XX is not set
++CONFIG_RADIO_ADAPTERS=y
++# CONFIG_RADIO_CADET is not set
++# CONFIG_RADIO_RTRACK is not set
++# CONFIG_RADIO_RTRACK2 is not set
++# CONFIG_RADIO_AZTECH is not set
++# CONFIG_RADIO_GEMTEK is not set
++# CONFIG_RADIO_SF16FMI is not set
++# CONFIG_RADIO_SF16FMR2 is not set
++# CONFIG_RADIO_TERRATEC is not set
++# CONFIG_RADIO_TRUST is not set
++# CONFIG_RADIO_TYPHOON is not set
++# CONFIG_RADIO_ZOLTRIX is not set
++# CONFIG_USB_DSBR is not set
+ # CONFIG_DVB_CORE is not set
+ # CONFIG_DAB is not set
+
+diff --git a/arch/arm/configs/hhs3c6410_7_defconfig b/arch/arm/configs/hhs3c6410_7_defconfig
+index 2d3147a..b0a4f48 100644
+--- a/arch/arm/configs/hhs3c6410_7_defconfig
++++ b/arch/arm/configs/hhs3c6410_7_defconfig
+@@ -1,7 +1,7 @@
+ #
+ # Automatically generated make config: don't edit
+ # Linux kernel version: 2.6.24.7
+-# Tue Jun 16 10:44:09 2009
++# Thu Aug 6 12:17:50 2009
+ #
+ CONFIG_ARM=y
+ CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+@@ -910,7 +910,54 @@ CONFIG_SSB_POSSIBLE=y
+ #
+ # Multimedia devices
+ #
+-# CONFIG_VIDEO_DEV is not set
++CONFIG_VIDEO_DEV=m
++CONFIG_VIDEO_V4L1=y
++CONFIG_VIDEO_V4L1_COMPAT=y
++CONFIG_VIDEO_V4L2=y
++CONFIG_VIDEO_CAPTURE_DRIVERS=y
++# CONFIG_VIDEO_ADV_DEBUG is not set
++CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
++# CONFIG_VIDEO_VIVI is not set
++# CONFIG_VIDEO_PMS is not set
++# CONFIG_VIDEO_CPIA is not set
++# CONFIG_VIDEO_CPIA2 is not set
++# CONFIG_VIDEO_SAA5246A is not set
++# CONFIG_VIDEO_SAA5249 is not set
++# CONFIG_TUNER_3036 is not set
++# CONFIG_VIDEO_SAMSUNG is not set
++CONFIG_VIDEO_SAMSUNG_TVENC=m
++CONFIG_VIDEO_SAMSUNG_TVSCALER=m
++CONFIG_V4L_USB_DRIVERS=y
++# CONFIG_VIDEO_PVRUSB2 is not set
++# CONFIG_VIDEO_EM28XX is not set
++# CONFIG_VIDEO_USBVISION is not set
++# CONFIG_USB_VICAM is not set
++# CONFIG_USB_IBMCAM is not set
++# CONFIG_USB_KONICAWC is not set
++# CONFIG_USB_QUICKCAM_MESSENGER is not set
++# CONFIG_USB_ET61X251 is not set
++# CONFIG_VIDEO_OVCAMCHIP is not set
++# CONFIG_USB_W9968CF is not set
++# CONFIG_USB_OV511 is not set
++# CONFIG_USB_SE401 is not set
++# CONFIG_USB_SN9C102 is not set
++# CONFIG_USB_STV680 is not set
++# CONFIG_USB_ZC0301 is not set
++# CONFIG_USB_PWC is not set
++# CONFIG_USB_ZR364XX is not set
++CONFIG_RADIO_ADAPTERS=y
++# CONFIG_RADIO_CADET is not set
++# CONFIG_RADIO_RTRACK is not set
++# CONFIG_RADIO_RTRACK2 is not set
++# CONFIG_RADIO_AZTECH is not set
++# CONFIG_RADIO_GEMTEK is not set
++# CONFIG_RADIO_SF16FMI is not set
++# CONFIG_RADIO_SF16FMR2 is not set
++# CONFIG_RADIO_TERRATEC is not set
++# CONFIG_RADIO_TRUST is not set
++# CONFIG_RADIO_TYPHOON is not set
++# CONFIG_RADIO_ZOLTRIX is not set
++# CONFIG_USB_DSBR is not set
+ # CONFIG_DVB_CORE is not set
+ # CONFIG_DAB is not set
+
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-2.6.24/smartq5/mer/0009-Apply-cpufreq-patch-from-gqwang.patch b/recipes/linux/linux-2.6.24/smartq5/mer/0009-Apply-cpufreq-patch-from-gqwang.patch
new file mode 100644
index 0000000000..f83a944e05
--- /dev/null
+++ b/recipes/linux/linux-2.6.24/smartq5/mer/0009-Apply-cpufreq-patch-from-gqwang.patch
@@ -0,0 +1,113 @@
+From 6a2a98218695242634c6f601dd956ef06369d1d3 Mon Sep 17 00:00:00 2001
+From: YouSheng <david.ysh@gmail.com>
+Date: Thu, 20 Aug 2009 13:58:48 +0800
+Subject: [PATCH 09/13] Apply cpufreq patch from gqwang
+
+---
+ arch/arm/plat-s3c64xx/clock.c | 23 +++++++++++------------
+ arch/arm/plat-s3c64xx/s3c64xx-cpufreq.c | 18 +++++++++---------
+ 2 files changed, 20 insertions(+), 21 deletions(-)
+
+diff --git a/arch/arm/plat-s3c64xx/clock.c b/arch/arm/plat-s3c64xx/clock.c
+index a776437..1cb7fd4 100644
+--- a/arch/arm/plat-s3c64xx/clock.c
++++ b/arch/arm/plat-s3c64xx/clock.c
+@@ -63,14 +63,17 @@
+ #define PLL_CALC_VAL(MDIV,PDIV,SDIV) ((1<<31)|(MDIV)<<16 |(PDIV)<<8 |(SDIV))
+ #define GET_ARM_CLOCK(baseclk) s3c6400_get_pll(__raw_readl(S3C_APLL_CON),baseclk)
+
+-#define MHZ 1000*1000
+ #define INIT_XTAL 12 * MHZ
+
+ /* enable and disable calls for use with the clk struct */
+ static const u32 s3c_cpu_clock_table[][6] = {
++ //{1100*MHZ, 266, 3, 1, 0, 0},
++ //{800*MHZ, 266, 3, 1, 0, 0},
++ {666*MHZ, 266, 3, 1, 0, 0},
+ {532*MHZ, 266, 3, 1, 0, 0},
+- {266*MHZ, 266, 3, 1, 0, 1},
+- {133*MHZ, 266, 3, 1, 0, 3},
++ {266*MHZ, 266, 3, 1, 0, 0},
++ {133*MHZ, 266, 3, 1, 0, 0},
++ {100*MHZ, 266, 3, 1, 0, 0},
+ };
+
+ /* clock information */
+@@ -286,6 +289,7 @@ unsigned long s3c_fclk_round_rate(struct clk *clk, unsigned long rate)
+ return s3c_cpu_clock_table[ARRAY_SIZE(s3c_cpu_clock_table) - 1][0];
+ }
+
++#define APLL_MDIV_MASK (0x3ff << 16)
+ int s3c_fclk_set_rate(struct clk *clk, unsigned long rate)
+ {
+ u32 ret = -EINVAL;
+@@ -296,20 +300,15 @@ int s3c_fclk_set_rate(struct clk *clk, unsigned long rate)
+
+ round_tmp = s3c_fclk_round_rate(clk,rate);
+
+- if(round_tmp == (int)s3c_fclk_get_rate())
+- return 0;
+-
+ for (iter = 0 ; iter < ARRAY_SIZE(s3c_cpu_clock_table) ; iter++){
+ if(round_tmp == s3c_cpu_clock_table[iter][0])
+ break;
+ }
+
+- clk_div0_tmp = __raw_readl(ARM_CLK_DIV) & ~(ARM_DIV_MASK);
+- clk_div0_tmp |= s3c_cpu_clock_table[iter][5];
+-
+- __raw_writel(clk_div0_tmp, ARM_CLK_DIV);
+-
+- if (__raw_readl(ARM_CLK_DIV) == clk_div0_tmp)
++ apll_con_tmp = __raw_readl(S3C_APLL_CON) & ~(APLL_MDIV_MASK);
++ apll_con_tmp |= (round_tmp / 2000000) << 16;
++ __raw_writel(apll_con_tmp, S3C_APLL_CON);
++ if (__raw_readl(S3C_APLL_CON) == apll_con_tmp)
+ ret = 0;
+
+ clk->rate = s3c_cpu_clock_table[iter][0];
+diff --git a/arch/arm/plat-s3c64xx/s3c64xx-cpufreq.c b/arch/arm/plat-s3c64xx/s3c64xx-cpufreq.c
+index a509071..fae9890 100644
+--- a/arch/arm/plat-s3c64xx/s3c64xx-cpufreq.c
++++ b/arch/arm/plat-s3c64xx/s3c64xx-cpufreq.c
+@@ -44,13 +44,13 @@ extern int ltc3714_init(void);
+
+ /* frequency */
+ static struct cpufreq_frequency_table s3c6410_freq_table[] = {
+- {APLL_GEN_CLK, 667*1000},
+- {APLL_GEN_CLK, APLL_GEN_CLK},
+- {APLL_GEN_CLK, APLL_GEN_CLK2},
+- {APLL_GEN_CLK, APLL_GEN_CLK/2},
+- {APLL_GEN_CLK, APLL_GEN_CLK2/2},
+- {APLL_GEN_CLK, APLL_GEN_CLK/4},
+- {APLL_GEN_CLK, APLL_GEN_CLK2/4},
++// {0, 1100*1000},
++// {1, 800*1000},
++ {2, 666*1000},
++ {3, 532*1000},
++ {4, 266*1000},
++ {5, 133*1000},
++ {6, 100*1000},
+ {0, CPUFREQ_TABLE_END},
+ };
+
+@@ -142,14 +142,14 @@ static int s3c6410_target(struct cpufreq_policy *policy,
+ set_power(freqs.new);
+
+ /* frequency scaling */
+- ret = clk_set_rate(mpu_clk, target_freq * KHZ_T);
++ ret = clk_set_rate(mpu_clk, freqs.new * KHZ_T);
+ if(ret != 0)
+ printk("frequency scaling error\n");
+ }
+
+
+ #else
+- ret = clk_set_rate(mpu_clk, target_freq * KHZ_T);
++ ret = clk_set_rate(mpu_clk, freqs.new * KHZ_T);
+ if(ret != 0)
+ printk("frequency scaling error\n");
+
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-2.6.24/smartq5/mer/0010-Better-compatibility-with-some-memory-chips.patch b/recipes/linux/linux-2.6.24/smartq5/mer/0010-Better-compatibility-with-some-memory-chips.patch
new file mode 100644
index 0000000000..162335e0c2
--- /dev/null
+++ b/recipes/linux/linux-2.6.24/smartq5/mer/0010-Better-compatibility-with-some-memory-chips.patch
@@ -0,0 +1,77 @@
+From 112a485fecdaeabe2b5fc7c1eea0832d2da26c0d Mon Sep 17 00:00:00 2001
+From: YouSheng <david.ysh@gmail.com>
+Date: Thu, 20 Aug 2009 13:59:22 +0800
+Subject: [PATCH 10/13] Better compatibility with some memory chips
+
+---
+ arch/arm/mach-s3c6410/pm.c | 21 ++++++++++++++++++++-
+ arch/arm/plat-s3c64xx/clock.c | 1 +
+ 2 files changed, 21 insertions(+), 1 deletions(-)
+
+diff --git a/arch/arm/mach-s3c6410/pm.c b/arch/arm/mach-s3c6410/pm.c
+index af53fdc..4d4ef08 100644
+--- a/arch/arm/mach-s3c6410/pm.c
++++ b/arch/arm/mach-s3c6410/pm.c
+@@ -25,6 +25,7 @@
+ #include <linux/errno.h>
+ #include <linux/time.h>
+ #include <linux/sysdev.h>
++#include <linux/delay.h>
+
+ #include <asm/hardware.h>
+ #include <asm/io.h>
+@@ -84,20 +85,38 @@ static struct sleep_save s3c6410_sleep[] = {
+
+ static int s3c6410_pm_suspend(struct sys_device *dev, pm_message_t state)
+ {
++ u32 apll_con;
+ s3c2410_pm_do_save(s3c6410_sleep, ARRAY_SIZE(s3c6410_sleep));
++
++ /* CPU speed set to 532MHZ */
++ apll_con = __raw_readl(S3C_APLL_CON);
++ apll_con &= ~(0x3FF << 16);
++ apll_con |= 266 << 16;
++ __raw_writel(apll_con, S3C_APLL_CON);
++ udelay(200);
++ /* CPU into sync mode. System clock from APLL */
++ __raw_writel(__raw_readl(S3C_OTHERS) | 0xC0, S3C_OTHERS);
++ /* Wait sync finish */
++ while ((__raw_readl(S3C_OTHERS) & 0xF00) != 0xF00);
++
+ return 0;
+ }
+
+ static int s3c6410_pm_resume(struct sys_device *dev)
+ {
+- unsigned long tmp;
+ #if 0
++ unsigned long tmp;
+ tmp = __raw_readl(S3C_PWR_CFG);
+ tmp &= ~(0x60<<0);
+ tmp |= (0x1<<5);
+ __raw_writel(tmp, S3C_PWR_CFG);
+ #endif
++ /* CPU into async mode. System clock from MPLL */
++ __raw_writel(__raw_readl(S3C_OTHERS) & 0xFF3F, S3C_OTHERS);
++ /* Wait async finish */
++ while (__raw_readl(S3C_OTHERS) & 0xF00);
+ s3c2410_pm_do_restore(s3c6410_sleep, ARRAY_SIZE(s3c6410_sleep));
++
+ return 0;
+ }
+
+diff --git a/arch/arm/plat-s3c64xx/clock.c b/arch/arm/plat-s3c64xx/clock.c
+index 1cb7fd4..2eb7e99 100644
+--- a/arch/arm/plat-s3c64xx/clock.c
++++ b/arch/arm/plat-s3c64xx/clock.c
+@@ -308,6 +308,7 @@ int s3c_fclk_set_rate(struct clk *clk, unsigned long rate)
+ apll_con_tmp = __raw_readl(S3C_APLL_CON) & ~(APLL_MDIV_MASK);
+ apll_con_tmp |= (round_tmp / 2000000) << 16;
+ __raw_writel(apll_con_tmp, S3C_APLL_CON);
++ udelay(200);
+ if (__raw_readl(S3C_APLL_CON) == apll_con_tmp)
+ ret = 0;
+
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-2.6.24/smartq5/mer/0011-Only-reserve-memory-for-TV-if-CONFIG_VIDEO_SAMSUNG_T.patch b/recipes/linux/linux-2.6.24/smartq5/mer/0011-Only-reserve-memory-for-TV-if-CONFIG_VIDEO_SAMSUNG_T.patch
new file mode 100644
index 0000000000..1a39d4cbc0
--- /dev/null
+++ b/recipes/linux/linux-2.6.24/smartq5/mer/0011-Only-reserve-memory-for-TV-if-CONFIG_VIDEO_SAMSUNG_T.patch
@@ -0,0 +1,32 @@
+From d4c0c216128feee090df41f81552cca7ff3f44bc Mon Sep 17 00:00:00 2001
+From: David Greaves <david@dgreaves.com>
+Date: Mon, 21 Sep 2009 23:19:36 +0100
+Subject: [PATCH 11/13] Only reserve memory for TV if CONFIG_VIDEO_SAMSUNG_TVENC/TVSCALER are defined
+
+---
+ include/asm-arm/arch-s3c2410/reserved_mem.h | 8 ++++++++
+ 1 files changed, 8 insertions(+), 0 deletions(-)
+
+diff --git a/include/asm-arm/arch-s3c2410/reserved_mem.h b/include/asm-arm/arch-s3c2410/reserved_mem.h
+index e6c029d..9ac227b 100644
+--- a/include/asm-arm/arch-s3c2410/reserved_mem.h
++++ b/include/asm-arm/arch-s3c2410/reserved_mem.h
+@@ -26,7 +26,15 @@
+ //#define CONFIG_RESERVED_MEM_JPEG_MFC_POST_CAMERA
+ //#define CONFIG_RESERVED_MEM_CMM_MFC_POST
+ //#define CONFIG_RESERVED_MEM_CMM_JPEG_MFC_POST_CAMERA
++//#define CONFIG_RESERVED_MEM_TV_MFC_POST_CAMERA
++
++// Should do a full config logic here...
++#if defined(CONFIG_VIDEO_SAMSUNG_TVENC) || defined(CONFIG_VIDEO_SAMSUNG_TVSCALER)
+ #define CONFIG_RESERVED_MEM_TV_MFC_POST_CAMERA
++#else
++#define CONFIG_RESERVED_MEM_MFC_POST
++#endif
++
+
+ #if defined(CONFIG_RESERVED_MEM_JPEG)
+ #define JPEG_RESERVED_MEM_START 0x57800000
+--
+1.6.2.4
+
diff --git a/recipes/linux/linux-2.6.24/smartq5/mer/0012-Disable-TV-out-to-save-RAM.patch b/recipes/linux/linux-2.6.24/smartq5/mer/0012-Disable-TV-out-to-save-RAM.patch
new file mode 100644
index 0000000000..8e0d311714
--- /dev/null
+++ b/recipes/linux/linux-2.6.24/smartq5/mer/0012-Disable-TV-out-to-save-RAM.patch
@@ -0,0 +1,100 @@
+From aa8822574f0c07f391b29737ca00f08d641cb93f Mon Sep 17 00:00:00 2001
+From: David Greaves <david@dgreaves.com>
+Date: Tue, 22 Sep 2009 10:01:40 +0100
+Subject: [PATCH 12/13] Disable TV-out to save RAM
+
+---
+ arch/arm/configs/hhs3c6410_4_3_defconfig | 18 +++++++++---------
+ arch/arm/configs/hhs3c6410_7_defconfig | 20 ++++++++++----------
+ 2 files changed, 19 insertions(+), 19 deletions(-)
+
+diff --git a/arch/arm/configs/hhs3c6410_4_3_defconfig b/arch/arm/configs/hhs3c6410_4_3_defconfig
+index d503e12..e71e588 100644
+--- a/arch/arm/configs/hhs3c6410_4_3_defconfig
++++ b/arch/arm/configs/hhs3c6410_4_3_defconfig
+@@ -910,27 +910,27 @@ CONFIG_SSB_POSSIBLE=y
+ #
+ # Multimedia devices
+ #
+-CONFIG_VIDEO_DEV=m
++# CONFIG_VIDEO_DEV is not set
+ # CONFIG_VIDEO_V4L1 is not set
+-CONFIG_VIDEO_V4L1_COMPAT=y
+-CONFIG_VIDEO_V4L2=y
+-CONFIG_VIDEO_CAPTURE_DRIVERS=y
++# CONFIG_VIDEO_V4L1_COMPAT is not set
++# CONFIG_VIDEO_V4L2 is not set
++# CONFIG_VIDEO_CAPTURE_DRIVERS is not set
+ # CONFIG_VIDEO_ADV_DEBUG is not set
+-CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
++# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set
+ # CONFIG_VIDEO_VIVI is not set
+ # CONFIG_VIDEO_SAA5246A is not set
+ # CONFIG_VIDEO_SAA5249 is not set
+ # CONFIG_VIDEO_SAMSUNG is not set
+-CONFIG_VIDEO_SAMSUNG_TVENC=m
+-CONFIG_VIDEO_SAMSUNG_TVSCALER=m
+-CONFIG_V4L_USB_DRIVERS=y
++# CONFIG_VIDEO_SAMSUNG_TVENC is not set
++# CONFIG_VIDEO_SAMSUNG_TVSCALER is not set
++# CONFIG_V4L_USB_DRIVERS is not set
+ # CONFIG_VIDEO_PVRUSB2 is not set
+ # CONFIG_VIDEO_USBVISION is not set
+ # CONFIG_USB_ET61X251 is not set
+ # CONFIG_USB_SN9C102 is not set
+ # CONFIG_USB_ZC0301 is not set
+ # CONFIG_USB_ZR364XX is not set
+-CONFIG_RADIO_ADAPTERS=y
++# CONFIG_RADIO_ADAPTERS is not set
+ # CONFIG_RADIO_CADET is not set
+ # CONFIG_RADIO_RTRACK is not set
+ # CONFIG_RADIO_RTRACK2 is not set
+diff --git a/arch/arm/configs/hhs3c6410_7_defconfig b/arch/arm/configs/hhs3c6410_7_defconfig
+index b0a4f48..2694716 100644
+--- a/arch/arm/configs/hhs3c6410_7_defconfig
++++ b/arch/arm/configs/hhs3c6410_7_defconfig
+@@ -910,13 +910,13 @@ CONFIG_SSB_POSSIBLE=y
+ #
+ # Multimedia devices
+ #
+-CONFIG_VIDEO_DEV=m
+-CONFIG_VIDEO_V4L1=y
+-CONFIG_VIDEO_V4L1_COMPAT=y
+-CONFIG_VIDEO_V4L2=y
+-CONFIG_VIDEO_CAPTURE_DRIVERS=y
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_VIDEO_V4L1 is not set
++# CONFIG_VIDEO_V4L1_COMPAT is not set
++# CONFIG_VIDEO_V4L2 is not set
++# CONFIG_VIDEO_CAPTURE_DRIVERS is not set
+ # CONFIG_VIDEO_ADV_DEBUG is not set
+-CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
++# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set
+ # CONFIG_VIDEO_VIVI is not set
+ # CONFIG_VIDEO_PMS is not set
+ # CONFIG_VIDEO_CPIA is not set
+@@ -925,9 +925,9 @@ CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+ # CONFIG_VIDEO_SAA5249 is not set
+ # CONFIG_TUNER_3036 is not set
+ # CONFIG_VIDEO_SAMSUNG is not set
+-CONFIG_VIDEO_SAMSUNG_TVENC=m
+-CONFIG_VIDEO_SAMSUNG_TVSCALER=m
+-CONFIG_V4L_USB_DRIVERS=y
++# CONFIG_VIDEO_SAMSUNG_TVENC is not set
++# CONFIG_VIDEO_SAMSUNG_TVSCALER is not set
++# CONFIG_V4L_USB_DRIVERS is not set
+ # CONFIG_VIDEO_PVRUSB2 is not set
+ # CONFIG_VIDEO_EM28XX is not set
+ # CONFIG_VIDEO_USBVISION is not set
+@@ -945,7 +945,7 @@ CONFIG_V4L_USB_DRIVERS=y
+ # CONFIG_USB_ZC0301 is not set
+ # CONFIG_USB_PWC is not set
+ # CONFIG_USB_ZR364XX is not set
+-CONFIG_RADIO_ADAPTERS=y
++# CONFIG_RADIO_ADAPTERS is not set
+ # CONFIG_RADIO_CADET is not set
+ # CONFIG_RADIO_RTRACK is not set
+ # CONFIG_RADIO_RTRACK2 is not set
+--
+1.6.2.4
+