aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorPawit Pornkitprasan <p.pawit@gmail.com>2011-12-24 09:34:37 +0700
committerPawit Pornkitprasan <p.pawit@gmail.com>2011-12-24 09:35:11 +0700
commitfdc19983538bec90010fa7f344a7417ff4731ba8 (patch)
tree8a84a1edd1c026b71fec4756caf27cbbb9e827d5 /drivers/media
parentb55e9ac4df4d240b39eda4cd9c0198453dd59061 (diff)
downloadkernel_samsung_aries-fdc19983538bec90010fa7f344a7417ff4731ba8.zip
kernel_samsung_aries-fdc19983538bec90010fa7f344a7417ff4731ba8.tar.gz
kernel_samsung_aries-fdc19983538bec90010fa7f344a7417ff4731ba8.tar.bz2
Added support for aries
Reverts "S5PC11X : FIMC apply v4l2 standard for asynchronous dequeue/queue" 5f4b037e6ebb18d65a3ac896032eb559d7fe2baf
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/radio/Kconfig12
-rw-r--r--drivers/media/radio/Makefile1
-rw-r--r--drivers/media/radio/si4709/Makefile6
-rwxr-xr-xdrivers/media/radio/si4709/radio-si4709_common.h41
-rw-r--r--drivers/media/radio/si4709/radio-si4709_dev.c2563
-rw-r--r--drivers/media/radio/si4709/radio-si4709_dev.h181
-rw-r--r--drivers/media/radio/si4709/radio-si4709_i2c_drv.c196
-rw-r--r--drivers/media/radio/si4709/radio-si4709_i2c_drv.h8
-rw-r--r--drivers/media/radio/si4709/radio-si4709_ioctl.h104
-rw-r--r--drivers/media/radio/si4709/radio-si4709_main.c799
-rw-r--r--drivers/media/radio/si4709/radio-si4709_main.h9
-rw-r--r--drivers/media/radio/si4709/radio-si4709_regs.h859
-rw-r--r--drivers/media/video/Kconfig6
-rw-r--r--drivers/media/video/Makefile2
-rwxr-xr-xdrivers/media/video/ce147.c5670
-rw-r--r--drivers/media/video/samsung/Kconfig2
-rw-r--r--drivers/media/video/samsung/Makefile2
-rw-r--r--drivers/media/video/samsung/fimc/fimc.h5
-rw-r--r--drivers/media/video/samsung/fimc/fimc_capture.c154
-rw-r--r--drivers/media/video/samsung/fimc/fimc_dev.c8
-rw-r--r--drivers/media/video/samsung/fimc/fimc_output.c4
-rw-r--r--drivers/media/video/samsung/fimc/fimc_v4l2.c7
-rwxr-xr-xdrivers/media/video/samsung/mfc50/mfc.c12
-rw-r--r--drivers/media/video/samsung/tv20/Kconfig51
-rw-r--r--drivers/media/video/samsung/tv20/Makefile50
-rw-r--r--drivers/media/video/samsung/tv20/cec.c426
-rw-r--r--drivers/media/video/samsung/tv20/cec.h104
-rw-r--r--drivers/media/video/samsung/tv20/ddc.c133
-rw-r--r--drivers/media/video/samsung/tv20/ddc.h7
-rw-r--r--drivers/media/video/samsung/tv20/hpd.c394
-rw-r--r--drivers/media/video/samsung/tv20/hpd.h36
-rw-r--r--drivers/media/video/samsung/tv20/s5p_stda_grp.c1103
-rw-r--r--drivers/media/video/samsung/tv20/s5p_stda_hdmi.c242
-rw-r--r--drivers/media/video/samsung/tv20/s5p_stda_tvout_if.c1261
-rw-r--r--drivers/media/video/samsung/tv20/s5p_stda_video_layer.c924
-rw-r--r--drivers/media/video/samsung/tv20/s5p_tv.h1099
-rw-r--r--drivers/media/video/samsung/tv20/s5p_tv_base.c1431
-rw-r--r--drivers/media/video/samsung/tv20/s5p_tv_v4l2.c1822
-rw-r--r--drivers/media/video/samsung/tv20/s5pc100/hdcp_s5pc100.c1596
-rw-r--r--drivers/media/video/samsung/tv20/s5pc100/hdmi_s5pc100.c1435
-rw-r--r--drivers/media/video/samsung/tv20/s5pc100/regs/regs-clock_extra.h79
-rw-r--r--drivers/media/video/samsung/tv20/s5pc100/regs/regs-hdmi.h978
-rw-r--r--drivers/media/video/samsung/tv20/s5pc100/regs/regs-sdaout.h455
-rw-r--r--drivers/media/video/samsung/tv20/s5pc100/regs/regs-vmx.h209
-rw-r--r--drivers/media/video/samsung/tv20/s5pc100/regs/regs-vprocessor.h366
-rw-r--r--drivers/media/video/samsung/tv20/s5pc100/sdout_s5pc100.c2031
-rw-r--r--drivers/media/video/samsung/tv20/s5pc100/tv_clock_s5pc100.c406
-rw-r--r--drivers/media/video/samsung/tv20/s5pc100/tv_out_s5pc100.h486
-rw-r--r--drivers/media/video/samsung/tv20/s5pc100/tv_power_s5pc100.c140
-rw-r--r--drivers/media/video/samsung/tv20/s5pc100/vmixer_s5pc100.c1047
-rw-r--r--drivers/media/video/samsung/tv20/s5pc100/vp_coeff_s5pc100.h310
-rw-r--r--drivers/media/video/samsung/tv20/s5pc100/vprocessor_s5pc100.c809
-rw-r--r--drivers/media/video/samsung/tv20/s5pv210/cec_s5pv210.c294
-rw-r--r--drivers/media/video/samsung/tv20/s5pv210/cec_s5pv210.h23
-rw-r--r--drivers/media/video/samsung/tv20/s5pv210/hdcp_s5pv210.c1790
-rw-r--r--drivers/media/video/samsung/tv20/s5pv210/hdmi_param.h414
-rw-r--r--drivers/media/video/samsung/tv20/s5pv210/hdmi_s5pv210.c2131
-rw-r--r--drivers/media/video/samsung/tv20/s5pv210/regs/regs-cec.h101
-rw-r--r--drivers/media/video/samsung/tv20/s5pv210/regs/regs-clock_extra.h103
-rw-r--r--drivers/media/video/samsung/tv20/s5pv210/regs/regs-hdmi.h1552
-rw-r--r--drivers/media/video/samsung/tv20/s5pv210/regs/regs-sdaout.h517
-rw-r--r--drivers/media/video/samsung/tv20/s5pv210/regs/regs-vmx.h254
-rw-r--r--drivers/media/video/samsung/tv20/s5pv210/regs/regs-vprocessor.h447
-rw-r--r--drivers/media/video/samsung/tv20/s5pv210/sdout_s5pv210.c2038
-rw-r--r--drivers/media/video/samsung/tv20/s5pv210/tv_clock_s5pv210.c286
-rw-r--r--drivers/media/video/samsung/tv20/s5pv210/tv_out_s5pv210.h597
-rw-r--r--drivers/media/video/samsung/tv20/s5pv210/tv_power_s5pv210.c133
-rw-r--r--drivers/media/video/samsung/tv20/s5pv210/vmixer_s5pv210.c1256
-rw-r--r--drivers/media/video/samsung/tv20/s5pv210/vp_coeff_s5pv210.h310
-rw-r--r--drivers/media/video/samsung/tv20/s5pv210/vprocessor_s5pv210.c814
70 files changed, 43082 insertions, 59 deletions
diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig
index 52798a1..a7ab498 100644
--- a/drivers/media/radio/Kconfig
+++ b/drivers/media/radio/Kconfig
@@ -357,6 +357,18 @@ config RADIO_SI470X
source "drivers/media/radio/si470x/Kconfig"
+config RADIO_SI4709
+ bool "Silicon Labs Si4709 FM Radio Receiver support"
+ ---help---
+ This is a driver for I2C devices with the Silicon Labs SI4709
+ chip.
+
+ Say Y here if you want to connect this type of radio to your
+ computer's I2C port.
+
+ To compile this driver as a module, choose M here: the
+ module will be called radio-i2c-si470x.
+
config USB_MR800
tristate "AverMedia MR 800 USB FM radio support"
depends on USB && VIDEO_V4L2
diff --git a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile
index f484a6e..5d0e62f 100644
--- a/drivers/media/radio/Makefile
+++ b/drivers/media/radio/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_RADIO_SI4713) += radio-si4713.o
obj-$(CONFIG_RADIO_MIROPCM20) += radio-miropcm20.o
obj-$(CONFIG_USB_DSBR) += dsbr100.o
obj-$(CONFIG_RADIO_SI470X) += si470x/
+obj-$(CONFIG_RADIO_SI4709) += si4709/
obj-$(CONFIG_USB_MR800) += radio-mr800.o
obj-$(CONFIG_RADIO_TEA5764) += radio-tea5764.o
obj-$(CONFIG_RADIO_SAA7706H) += saa7706h.o
diff --git a/drivers/media/radio/si4709/Makefile b/drivers/media/radio/si4709/Makefile
new file mode 100644
index 0000000..d110423
--- /dev/null
+++ b/drivers/media/radio/si4709/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for Silicon Labs Si4709 FM Radio Receiver
+#
+
+radio-si4709-i2c-objs := radio-si4709_dev.o radio-si4709_i2c_drv.o radio-si4709_main.o
+obj-$(CONFIG_RADIO_SI4709) += radio-si4709-i2c.o
diff --git a/drivers/media/radio/si4709/radio-si4709_common.h b/drivers/media/radio/si4709/radio-si4709_common.h
new file mode 100755
index 0000000..c81ed92
--- /dev/null
+++ b/drivers/media/radio/si4709/radio-si4709_common.h
@@ -0,0 +1,41 @@
+#ifndef _COMMON_H
+#define _COMMON_H
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <mach/gpio.h>
+
+//#define Si4709_DEBUG
+
+#define error(fmt,arg...) printk(KERN_CRIT fmt "\n",## arg)
+
+#ifdef Si4709_DEBUG
+#define debug(fmt,arg...) printk(KERN_CRIT "--------" fmt "\n",## arg)
+#else
+#define debug(fmt,arg...)
+#endif
+
+#define FM_RESET GPIO_FM_RST
+
+/*VNVS:28-OCT'09---- For testing FM tune and seek operation status*/
+#define TEST_FM
+
+/*VNVS:7-JUNE'10 ---- RDS Interrupt ON Always (Enabling interrupt when RDS is enabled)*/
+#define RDS_INTERRUPT_ON_ALWAYS
+
+/*VNVS:18-JUN'10---- For testing RDS*/
+/*Enable only for debugging RDS*/
+//#define RDS_TESTING
+#ifdef RDS_TESTING
+#define debug_rds(fmt,arg...) printk(KERN_CRIT "--------" fmt "\n",## arg)
+#define GROUP_TYPE_2A ( 2 * 2 + 0)
+#define GROUP_TYPE_2B ( 2 * 2 + 1)
+#else
+#define debug_rds(fmt,arg...)
+#endif
+
+#define YES 1
+#define NO 0
+
+#endif
+
diff --git a/drivers/media/radio/si4709/radio-si4709_dev.c b/drivers/media/radio/si4709/radio-si4709_dev.c
new file mode 100644
index 0000000..6a65da9
--- /dev/null
+++ b/drivers/media/radio/si4709/radio-si4709_dev.c
@@ -0,0 +1,2563 @@
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/time.h>
+#include <linux/workqueue.h>
+
+#include <mach/gpio.h>
+#include <plat/gpio-cfg.h>
+#include <../../../arch/arm/mach-s5pv210/include/mach/gpio-aries.h>
+
+#include "radio-si4709_regs.h"
+#include "radio-si4709_main.h"
+#include "radio-si4709_dev.h"
+#include "radio-si4709_common.h"
+
+enum
+{
+ eTRUE,
+ eFALSE,
+}dev_struct_status_t;
+
+/*dev_state*/
+/*power_state*/
+#define RADIO_ON 1
+#define RADIO_POWERDOWN 0
+/*seek_state*/
+#define RADIO_SEEK_ON 1
+#define RADIO_SEEK_OFF 0
+
+#define FREQ_87500_kHz 8750
+#define FREQ_76000_kHz 7600
+
+#define RSSI_seek_th_MAX 0x7F
+#define RSSI_seek_th_MIN 0x00
+
+#define seek_SNR_th_DISB 0x00
+#define seek_SNR_th_MIN 0x01 /*most stops*/
+#define seek_SNR_th_MAX 0x0F /*fewest stops*/
+
+#define seek_FM_ID_th_DISB 0x00
+#define seek_FM_ID_th_MAX 0x01 /*most stops*/
+#define seek_FM_ID_th_MIN 0x0F /*fewest stops*/
+
+#define TUNE_RSSI_THRESHOLD 0x00
+#define TUNE_SNR_THRESHOLD 0x01
+#define TUNE_CNT_THRESHOLD 0x00
+
+typedef struct
+{
+ u32 frequency;
+ u8 rsssi_val;
+}channel_into_t;
+
+typedef struct
+{
+ u16 band;
+ u32 bottom_of_band;
+ u16 channel_spacing;
+ u32 timeout_RDS; /****For storing the jiffy value****/
+ u32 seek_preset[NUM_SEEK_PRESETS];
+ u8 curr_snr;
+ u8 curr_rssi_th;
+}dev_settings_t;
+
+typedef struct
+{
+ /*Any function which
+ - views/modifies the fields of this structure
+ - does i2c communication
+ should lock the mutex before doing so.
+ Recursive locking should not be done.
+ In this file all the exported functions will take care
+ of this. The static functions will not deal with the
+ mutex*/
+ struct mutex lock;
+
+ struct i2c_client const *client;
+
+ dev_state_t state;
+
+ dev_settings_t settings;
+
+ channel_into_t rssi_freq[50];
+
+ u16 registers[NUM_OF_REGISTERS];
+
+ /* This field will be checked by all the functions
+ exported by this file (except the init function),
+ to validate the the fields of this structure.
+ if eTRUE: the fileds are valid
+ if eFALSE: do not trust the values of the fields
+ of this structure*/
+ unsigned short valid;
+
+ /*will be true is the client ans state fields are correct*/
+ unsigned short valid_client_state;
+}Si4709_device_t;
+
+
+/*extern functions*/
+/**********************************************/
+/*All the exported functions which view or modify the device
+ state/data, do i2c com will have to lock the mutex before
+ doing so*/
+/**********************************************/
+int Si4709_dev_init(struct i2c_client *);
+int Si4709_dev_exit(void);
+
+void Si4709_dev_mutex_init(void);
+
+int Si4709_dev_suspend(void);
+int Si4709_dev_resume(void);
+
+int Si4709_dev_powerup(void);
+int Si4709_dev_powerdown(void);
+
+int Si4709_dev_band_set(int);
+int Si4709_dev_ch_spacing_set(int);
+
+int Si4709_dev_chan_select(u32);
+int Si4709_dev_chan_get(u32*);
+
+int Si4709_dev_seek_up(u32*);
+int Si4709_dev_seek_down(u32*);
+int Si4709_dev_seek_auto(u32*);
+
+int Si4709_dev_RSSI_seek_th_set(u8);
+int Si4709_dev_seek_SNR_th_set(u8);
+int Si4709_dev_seek_FM_ID_th_set(u8);
+int Si4709_dev_cur_RSSI_get(rssi_snr_t*);
+int Si4709_dev_VOLEXT_ENB(void);
+int Si4709_dev_VOLEXT_DISB(void);
+int Si4709_dev_volume_set(u8);
+int Si4709_dev_volume_get(u8 *);
+int Si4709_dev_DSMUTE_ON(void);
+int Si4709_dev_DSMUTE_OFF(void);
+int Si4709_dev_MUTE_ON(void);
+int Si4709_dev_MUTE_OFF(void);
+int Si4709_dev_MONO_SET(void);
+int Si4709_dev_STEREO_SET(void);
+int Si4709_dev_RDS_ENABLE(void);
+int Si4709_dev_RDS_DISABLE(void);
+int Si4709_dev_RDS_timeout_set(u32);
+int Si4709_dev_rstate_get(dev_state_t*);
+int Si4709_dev_RDS_data_get(radio_data_t*);
+int Si4709_dev_device_id(device_id *);
+int Si4709_dev_chip_id(chip_id *);
+int Si4709_dev_sys_config2(sys_config2 *);
+int Si4709_dev_power_config(power_config *);
+int Si4709_dev_AFCRL_get(u8*);
+int Si4709_dev_DE_set(u8);
+/***********************************************/
+
+#ifdef RDS_INTERRUPT_ON_ALWAYS
+#define RDS_BUFFER_LENGTH 50
+static u16 *RDS_Block_Data_buffer;
+static u8 *RDS_Block_Error_buffer;
+static u8 RDS_Buffer_Index_read; //index number for last read data
+static u8 RDS_Buffer_Index_write; //index number for last written data
+
+int Si4709_RDS_flag;
+int RDS_Data_Available;
+int RDS_Data_Lost;
+int RDS_Groups_Available_till_now;
+struct workqueue_struct *Si4709_wq;
+struct work_struct Si4709_work;
+#endif
+
+/*static functions*/
+/**********************************************/
+static void wait(void);
+
+static void wait_RDS(void );
+
+static int powerup(void);
+static int powerdown(void);
+
+static int seek(u32*, int);
+static int tune_freq(u32);
+
+static void get_cur_chan_freq(u32 *, u16);
+
+static u16 freq_to_channel(u32);
+static u32 channel_to_freq(u16);
+
+static int insert_preset(u32,u8,u8*);
+
+static int i2c_read(u8);
+static int i2c_write(u8);
+/**********************************************/
+
+/*Si4709 device structure*/
+static Si4709_device_t Si4709_dev =
+{
+ .client = NULL,
+ .valid = eFALSE,
+ .valid_client_state = eFALSE,
+};
+
+/*Wait flag*/
+/*WAITING or WAIT_OVER or NO_WAIT*/
+int Si4709_dev_wait_flag = NO_WAIT;
+#ifdef RDS_INTERRUPT_ON_ALWAYS
+int Si4709_RDS_flag = NO_WAIT;
+#endif
+
+int Si4709_dev_init(struct i2c_client *client)
+{
+ int ret = 0;
+
+ debug("Si4709_dev_init called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ Si4709_dev.client = client;
+
+ /***reset the device here****/
+ gpio_set_value(FM_RESET, GPIO_LEVEL_LOW);
+ mdelay(1);
+ gpio_set_value(FM_RESET, GPIO_LEVEL_HIGH);
+ mdelay(2);
+
+ s3c_gpio_setpull(GPIO_FM_INT, S3C_GPIO_PULL_UP);
+ s3c_gpio_slp_setpull_updown(GPIO_FM_INT, S3C_GPIO_PULL_UP);
+
+ Si4709_dev.state.power_state = RADIO_POWERDOWN;
+ Si4709_dev.state.seek_state = RADIO_SEEK_OFF;
+
+ if( (ret = i2c_read(BOOTCONFIG) ) < 0 )
+ {
+ debug("i2c_read failed");
+ }
+ else
+ {
+ Si4709_dev.valid_client_state = eTRUE;
+ }
+
+#ifdef RDS_INTERRUPT_ON_ALWAYS
+ /*Creating Circular Buffer*/
+ /*Single RDS_Block_Data buffer size is 4x16 bits*/
+ RDS_Block_Data_buffer = kzalloc(RDS_BUFFER_LENGTH*8,GFP_KERNEL);
+ if(!RDS_Block_Data_buffer)
+ {
+ error("Not sufficient memory for creating RDS_Block_Data_buffer");
+ ret = -ENOMEM;
+ goto EXIT;
+ }
+
+ /*Single RDS_Block_Error buffer size is 4x8 bits*/
+ RDS_Block_Error_buffer = kzalloc(RDS_BUFFER_LENGTH*4,GFP_KERNEL);
+ if(!RDS_Block_Error_buffer)
+ {
+ error("Not sufficient memory for creating RDS_Block_Error_buffer");
+ ret = -ENOMEM;
+ kfree(RDS_Block_Data_buffer);
+ goto EXIT;
+ }
+
+ /*Initialising read and write indices*/
+ RDS_Buffer_Index_read= 0;
+ RDS_Buffer_Index_write= 0;
+
+ /*Creating work-queue*/
+ Si4709_wq = create_singlethread_workqueue("Si4709_wq");
+ if(!Si4709_wq)
+ {
+ error("Not sufficient memory for Si4709_wq, work-queue");
+ ret = -ENOMEM;
+ kfree(RDS_Block_Error_buffer);
+ kfree(RDS_Block_Data_buffer);
+ goto EXIT;
+ }
+
+ /*Initialising work_queue*/
+ INIT_WORK(&Si4709_work, Si4709_work_func);
+
+ RDS_Data_Available = 0;
+ RDS_Data_Lost =0;
+ RDS_Groups_Available_till_now = 0;
+EXIT:
+#endif
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ debug("Si4709_dev_init call over");
+
+ return ret;
+}
+
+int Si4709_dev_exit(void)
+{
+ int ret = 0;
+
+ debug("Si4709_dev_exit called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ // Temporary blocked by abnormal function call(E-CIM 2657654) - DW Shim. 2010.03.04
+ printk(KERN_ERR "Si4709_dev_exit() is called!!");
+// Si4709_dev.client = NULL;
+
+// Si4709_dev.valid_client_state = eFALSE;
+// Si4709_dev.valid = eFALSE;
+
+#ifdef RDS_INTERRUPT_ON_ALWAYS
+ if(Si4709_wq)
+ destroy_workqueue(Si4709_wq);
+
+ if(RDS_Block_Error_buffer)
+ kfree(RDS_Block_Error_buffer);
+
+ if(RDS_Block_Data_buffer)
+ kfree(RDS_Block_Data_buffer);
+#endif
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ debug("Si4709_dev_exit call over");
+
+ return ret;
+}
+
+void Si4709_dev_mutex_init(void)
+{
+ mutex_init(&(Si4709_dev.lock));
+}
+
+int Si4709_dev_powerup(void)
+{
+ int ret = 0;
+ u32 value = 100;
+
+ debug("Si4709_dev_powerup called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ if(!(RADIO_ON==Si4709_dev.state.power_state))
+ {
+ if( (ret = powerup()) < 0 )
+ {
+ debug("powerup failed");
+ }
+ else if( Si4709_dev.valid_client_state == eFALSE )
+ {
+ debug("Si4709_dev_powerup called when DS (state, client) is invalid");
+ ret = -1;
+ }
+ else
+ {
+ /*initial settings*/
+#if 0
+ POWERCFG_BITSET_RDSM_LOW(&Si4709_dev.registers[POWERCFG]);
+#else
+ POWERCFG_BITSET_RDSM_HIGH(&Si4709_dev.registers[POWERCFG]);
+#endif
+ // POWERCFG_BITSET_SKMODE_HIGH(&Si4709_dev.registers[POWERCFG]);
+ POWERCFG_BITSET_SKMODE_LOW(&Si4709_dev.registers[POWERCFG]); /*VNVS:18-NOV'09---- wrap at the upper and lower band limit and continue seeking*/
+ SYSCONFIG1_BITSET_STCIEN_HIGH(&Si4709_dev.registers[SYSCONFIG1]);
+ SYSCONFIG1_BITSET_RDSIEN_LOW(&Si4709_dev.registers[SYSCONFIG1]);
+ SYSCONFIG1_BITSET_RDS_HIGH(&Si4709_dev.registers[SYSCONFIG1]);
+ SYSCONFIG1_BITSET_DE_50(&Si4709_dev.registers[SYSCONFIG1]); /*VNVS:18-NOV'09--- Setting DE-Time Constant as 50us(Europe,Japan,Australia)*/
+ SYSCONFIG1_BITSET_GPIO_STC_RDS_INT(&Si4709_dev.registers[SYSCONFIG1]);
+ SYSCONFIG1_BITSET_RESERVED(&Si4709_dev.registers[SYSCONFIG1]);
+
+ // SYSCONFIG2_BITSET_SEEKTH(&Si4709_dev.registers[SYSCONFIG2],2);
+ SYSCONFIG2_BITSET_SEEKTH(&Si4709_dev.registers[SYSCONFIG2], TUNE_RSSI_THRESHOLD); /*VNVS:18-NOV'09---- modified for detecting more stations of good quality*/
+ SYSCONFIG2_BITSET_VOLUME(&Si4709_dev.registers[SYSCONFIG2],0x0F);
+ SYSCONFIG2_BITSET_BAND_87p5_108_MHz(&Si4709_dev.registers[SYSCONFIG2]);
+ Si4709_dev.settings.band = BAND_87500_108000_kHz;
+ Si4709_dev.settings.bottom_of_band = FREQ_87500_kHz;
+
+ SYSCONFIG2_BITSET_SPACE_100_KHz(&Si4709_dev.registers[SYSCONFIG2]);
+ Si4709_dev.settings.channel_spacing = CHAN_SPACING_100_kHz;
+
+
+ // SYSCONFIG3_BITSET_SKSNR(&Si4709_dev.registers[SYSCONFIG3],3);
+ SYSCONFIG3_BITSET_SKSNR(&Si4709_dev.registers[SYSCONFIG3], TUNE_SNR_THRESHOLD);/*VNVS:18-NOV'09---- modified for detecting more stations of good quality*/
+ SYSCONFIG3_BITSET_SKCNT(&Si4709_dev.registers[SYSCONFIG3], TUNE_CNT_THRESHOLD);
+
+ SYSCONFIG3_BITSET_RESERVED(&Si4709_dev.registers[SYSCONFIG3]);
+
+ Si4709_dev.settings.timeout_RDS = msecs_to_jiffies(value);
+ Si4709_dev.settings.curr_snr = TUNE_SNR_THRESHOLD;
+ Si4709_dev.settings.curr_rssi_th = TUNE_RSSI_THRESHOLD;
+
+ /*this will write all the above registers*/
+ if( (ret = i2c_write(SYSCONFIG3)) < 0 )
+ {
+ debug("Si4709_dev_powerup i2c_write 1 failed");
+ }
+ else
+ {
+ Si4709_dev.valid = eTRUE;
+#ifdef RDS_INTERRUPT_ON_ALWAYS
+ /*Initialising read and write indices*/
+ RDS_Buffer_Index_read= 0;
+ RDS_Buffer_Index_write= 0;
+
+ RDS_Data_Available = 0;
+ RDS_Data_Lost =0;
+ RDS_Groups_Available_till_now = 0;
+#endif
+ }
+
+ }
+ }
+ else
+ debug("Device already Powered-ON");
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+
+int Si4709_dev_powerdown(void)
+{
+ int ret = 0;
+
+ msleep(500); // For avoiding turned off pop noise
+ debug("Si4709_dev_powerdown called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_powerdown called when DS is invalid");
+ ret = -1;
+ }
+ else if ( ( ret = powerdown()) < 0 )
+ {
+ debug("powerdown failed");
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_suspend(void)
+{
+ int ret = 0;
+
+ debug("Si4709_dev_suspend called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ if( Si4709_dev.valid_client_state== eFALSE )
+ {
+ debug("Si4709_dev_suspend called when DS (state, client) is invalid");
+ ret = -1;
+ }
+#if 0
+ else if( Si4709_dev.state.power_state == RADIO_ON )
+ {
+ ret = powerdown();
+ }
+#endif
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ debug("Si4709_dev_enable call over");
+
+ return ret;
+}
+
+int Si4709_dev_resume(void)
+{
+ int ret = 0;
+
+// debug("Si4709_dev_resume called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ if( Si4709_dev.valid_client_state == eFALSE )
+ {
+ debug("Si4709_dev_resume called when DS (state, client) is invalid");
+ ret = -1;
+ }
+#if 0
+ else if( Si4709_dev.state.power_state == RADIO_POWERDOWN )
+ {
+ if( (ret = powerup()) < 0 )
+ {
+ debug("powerup failed");
+ }
+ }
+#endif
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+// debug("Si4709_dev_disable call over");
+
+ return ret;
+}
+
+int Si4709_dev_band_set(int band)
+{
+ int ret = 0;
+ u16 sysconfig2 =0;
+ u16 prev_band = 0;
+ u32 prev_bottom_of_band = 0;
+
+ debug("Si4709_dev_band_set called");
+
+ mutex_lock(&(Si4709_dev.lock));
+ sysconfig2 = Si4709_dev.registers[SYSCONFIG2];
+ prev_band = Si4709_dev.settings.band;
+ prev_bottom_of_band = Si4709_dev.settings.bottom_of_band;
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_band_set called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ switch (band)
+ {
+ case BAND_87500_108000_kHz:
+ SYSCONFIG2_BITSET_BAND_87p5_108_MHz(&Si4709_dev.registers[SYSCONFIG2]);
+ Si4709_dev.settings.band = BAND_87500_108000_kHz;
+ Si4709_dev.settings.bottom_of_band = FREQ_87500_kHz;
+ break;
+
+ case BAND_76000_108000_kHz:
+ SYSCONFIG2_BITSET_BAND_76_108_MHz(&Si4709_dev.registers[SYSCONFIG2]);
+ Si4709_dev.settings.band = BAND_76000_108000_kHz;
+ Si4709_dev.settings.bottom_of_band = FREQ_76000_kHz;
+ break;
+
+ case BAND_76000_90000_kHz:
+ SYSCONFIG2_BITSET_BAND_76_90_MHz(&Si4709_dev.registers[SYSCONFIG2]);
+ Si4709_dev.settings.band = BAND_76000_90000_kHz;
+ Si4709_dev.settings.bottom_of_band = FREQ_76000_kHz;
+ break;
+
+ default:
+ ret = -1;
+ }
+
+ if(ret == 0)
+ {
+ if( (ret = i2c_write(SYSCONFIG2)) < 0 )
+ {
+ debug("Si4709_dev_band_set i2c_write 1 failed");
+ Si4709_dev.settings.band = prev_band;
+ Si4709_dev.settings.bottom_of_band = prev_bottom_of_band;
+ Si4709_dev.registers[SYSCONFIG2] = sysconfig2;
+ }
+ }
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_ch_spacing_set(int ch_spacing)
+{
+ int ret = 0;
+ u16 sysconfig2 = 0;
+ u16 prev_ch_spacing = 0;
+
+ debug("Si4709_dev_ch_spacing_set called");
+
+ mutex_lock(&(Si4709_dev.lock));
+ sysconfig2 = Si4709_dev.registers[SYSCONFIG2];
+ prev_ch_spacing = Si4709_dev.settings.channel_spacing;
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_ch_spacing_set called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ switch (ch_spacing)
+ {
+ case CHAN_SPACING_200_kHz:
+ SYSCONFIG2_BITSET_SPACE_200_KHz(&Si4709_dev.registers[SYSCONFIG2]);
+ Si4709_dev.settings.channel_spacing = CHAN_SPACING_200_kHz;
+ break;
+
+ case CHAN_SPACING_100_kHz:
+ SYSCONFIG2_BITSET_SPACE_100_KHz(&Si4709_dev.registers[SYSCONFIG2]);
+ Si4709_dev.settings.channel_spacing = CHAN_SPACING_100_kHz;
+ break;
+
+ case CHAN_SPACING_50_kHz:
+ SYSCONFIG2_BITSET_SPACE_50_KHz(&Si4709_dev.registers[SYSCONFIG2]);
+ Si4709_dev.settings.channel_spacing = CHAN_SPACING_50_kHz;
+ break;
+
+ default:
+ ret = -1;
+ }
+
+ if(ret == 0)
+ {
+ if( (ret = i2c_write(SYSCONFIG2)) < 0 )
+ {
+ debug("Si4709_dev_ch_spacing_set i2c_write 1 failed");
+ Si4709_dev.settings.channel_spacing = prev_ch_spacing;
+ Si4709_dev.registers[SYSCONFIG2] = sysconfig2;
+ }
+
+ }
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_chan_select(u32 frequency)
+{
+ int ret = 0;
+
+ debug("Si4709_dev_chan_select called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_chan_select called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ Si4709_dev.state.seek_state = RADIO_SEEK_ON;
+
+ ret = tune_freq(frequency);
+ debug("Si4709_dev_chan_select called1");
+ Si4709_dev.state.seek_state = RADIO_SEEK_OFF;
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_chan_get(u32 *frequency)
+{
+ int ret = 0;
+
+
+ debug("Si4709_dev_chan_get called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_chan_get called when DS is invalid");
+ ret = -1;
+ }
+ else if( (ret = i2c_read(READCHAN)) < 0 )
+ {
+ debug("Si4709_dev_chan_get i2c_read failed");
+ }
+ else
+ {
+ get_cur_chan_freq(frequency, Si4709_dev.registers[READCHAN]);
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_seek_up(u32 *frequency)
+{
+ int ret = 0;
+
+ debug("Si4709_dev_seek_up called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_seek_up called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ Si4709_dev.state.seek_state = RADIO_SEEK_ON;
+
+ ret = seek(frequency, 1);
+
+ Si4709_dev.state.seek_state = RADIO_SEEK_OFF;
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_seek_down(u32 *frequency)
+{
+ int ret = 0;
+
+ debug("Si4709_dev_seek_down called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_seek_down called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ Si4709_dev.state.seek_state = RADIO_SEEK_ON;
+
+ ret = seek(frequency, 0);
+
+ Si4709_dev.state.seek_state = RADIO_SEEK_OFF;
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+
+#if 0
+int Si4709_dev_seek_auto(u32 *seek_preset_user)
+{
+ u8 *rssi_seek;
+ int ret = 0;
+ int i =0;
+ int j = 0;
+ channel_into_t temp;
+
+ debug("Si4709_dev_seek_auto called");
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_seek_auto called when DS is invalid");
+ ret = -1;
+ }
+
+ else if( (rssi_seek = (u8 *)kzalloc(sizeof(u8) * NUM_SEEK_PRESETS, GFP_KERNEL)) == NULL )
+ {
+ debug("Si4709_ioctl: no memory");
+ ret = -ENOMEM;
+ }
+
+ else
+ {
+
+ if( (ret = tune_freq(FREQ_87500_kHz)) == 0 )
+ {
+ debug("Si4709_dev_seek_auto tune_freq success");
+ get_cur_chan_freq(&(Si4709_dev.rssi_freq[0].frequency), Si4709_dev.registers[READCHAN]);
+ Si4709_dev_cur_RSSI_get(&(Si4709_dev.rssi_freq[0].rsssi_val));
+
+ }
+ else
+ {
+ debug("tunning failed, seek auto failed");
+ ret =-1;
+ }
+ #if 0
+ for(i=0;i<50; i++)
+ {
+ if( (ret = seek(&(Si4709_dev.settings.seek_preset[i]),1)) == 0 )
+ {
+ get_cur_chan_freq(&(Si4709_dev.rssi_freq[i].frequency), Si4709_dev.registers[READCHAN]);
+ Si4709_dev_cur_RSSI_get(&(Si4709_dev.rssi_freq[i].rsssi_val));
+ rssi_seek ++;
+ }
+
+ else
+ {
+ debug("seek failed");
+
+ }
+ }
+ #endif
+
+
+
+ /***new method ****/
+ for(i=1;i<30; i++)
+ {
+ if( (ret = seek(&(Si4709_dev.settings.seek_preset[i]),1)) == 0 )
+ {
+ get_cur_chan_freq(&(Si4709_dev.rssi_freq[i].frequency), Si4709_dev.registers[READCHAN]);
+ Si4709_dev_cur_RSSI_get(&(Si4709_dev.rssi_freq[i].rsssi_val));
+ }
+
+ else
+ {
+ debug("seek failed");
+
+ }
+ }
+ /***Sort the array of structures on the basis of RSSI value****/
+ for(i=0;i<29;i++)
+ {
+
+ for(j=i+1;j<30;j++)
+ {
+
+ if( Si4709_dev.rssi_freq[j].rsssi_val>Si4709_dev.rssi_freq[i].rsssi_val)
+ {
+ temp=Si4709_dev.rssi_freq[i];
+ Si4709_dev.rssi_freq[i]=Si4709_dev.rssi_freq[j];
+ Si4709_dev.rssi_freq[j]=temp;
+ }
+
+ }
+
+ }
+
+ /***Store the frequency in Array*****/
+ for(i=0;i<19;i++)
+ {
+ Si4709_dev.settings.seek_preset[i]=Si4709_dev.rssi_freq[i].frequency;
+ }
+
+
+
+ }
+ memcpy(seek_preset_user, Si4709_dev.settings.seek_preset , sizeof(int)*NUM_SEEK_PRESETS);
+ kfree(rssi_seek);
+ return ret;
+}
+#endif
+
+
+
+int Si4709_dev_RSSI_seek_th_set(u8 seek_th)
+{
+ int ret = 0;
+ u16 sysconfig2 = 0;
+
+ debug("Si4709_dev_RSSI_seek_th_set called");
+
+ mutex_lock(&(Si4709_dev.lock));
+ sysconfig2 = Si4709_dev.registers[SYSCONFIG2];
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_RSSI_seek_th_set called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ SYSCONFIG2_BITSET_SEEKTH(&Si4709_dev.registers[SYSCONFIG2], seek_th);
+ Si4709_dev.settings.curr_rssi_th=seek_th;
+ if( (ret = i2c_write( SYSCONFIG2 )) < 0 )
+ {
+ debug("Si4709_dev_RSSI_seek_th_set i2c_write 1 failed");
+ Si4709_dev.registers[SYSCONFIG2] = sysconfig2;
+ }
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_seek_SNR_th_set(u8 seek_SNR)
+{
+ int ret = 0;
+ u16 sysconfig3 = 0;
+
+ debug("Si4709_dev_seek_SNR_th_set called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ sysconfig3 = Si4709_dev.registers[SYSCONFIG3];
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_seek_SNR_th_set called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ SYSCONFIG3_BITSET_SKSNR(&Si4709_dev.registers[SYSCONFIG3], seek_SNR);
+ SYSCONFIG3_BITSET_RESERVED(&Si4709_dev.registers[SYSCONFIG3]);
+ Si4709_dev.settings.curr_snr=seek_SNR;
+
+ if( (ret = i2c_write( SYSCONFIG3 )) < 0 )
+ {
+ debug("Si4709_dev_seek_SNR_th_set i2c_write 1 failed");
+ Si4709_dev.registers[SYSCONFIG3] = sysconfig3;
+ }
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_seek_FM_ID_th_set(u8 seek_FM_ID_th)
+{
+ int ret = 0;
+ u16 sysconfig3 = 0;
+
+ debug("Si4709_dev_seek_FM_ID_th_set called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ sysconfig3 = Si4709_dev.registers[SYSCONFIG3];
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_seek_SNR_th_set called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ SYSCONFIG3_BITSET_SKCNT(&Si4709_dev.registers[SYSCONFIG3], seek_FM_ID_th);
+ SYSCONFIG3_BITSET_RESERVED(&Si4709_dev.registers[SYSCONFIG3]);
+
+ if( (ret = i2c_write( SYSCONFIG3 )) < 0 )
+ {
+ debug("Si4709_dev_seek_FM_ID_th_set i2c_write 1 failed");
+ sysconfig3 = Si4709_dev.registers[SYSCONFIG3];
+ }
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_cur_RSSI_get(rssi_snr_t *cur_RSSI)
+{
+ int ret = 0;
+
+ debug("Si4709_dev_cur_RSSI_get called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_cur_RSSI_get called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ if( (ret = i2c_read(STATUSRSSI)) < 0 )
+ {
+ debug("Si4709_dev_cur_RSSI_get i2c_read 1 failed");
+ }
+ else
+ {
+
+ cur_RSSI->curr_rssi= STATUSRSSI_RSSI_SIGNAL_STRENGTH(Si4709_dev.registers[STATUSRSSI]);
+ cur_RSSI->curr_rssi_th=Si4709_dev.settings.curr_rssi_th;
+ cur_RSSI->curr_snr=Si4709_dev.settings.curr_snr;
+ }
+ }
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+/*VNVS:START 13-OCT'09---- Functions which reads device-id,chip-id,power configuration, system configuration2 registers */
+int Si4709_dev_device_id(device_id *dev_id)
+{
+ int ret = 0;
+
+ debug("Si4709_dev_device_id called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_device_id called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ if( (ret = i2c_read(DEVICE_ID)) < 0 )
+ {
+ debug("Si4709_dev_device_id i2c_read failed");
+ }
+ else
+ {
+
+ dev_id->part_number= DEVICE_ID_PART_NUMBER(Si4709_dev.registers[DEVICE_ID]);
+ dev_id->manufact_number = DEVICE_ID_MANUFACT_NUMBER(Si4709_dev.registers[DEVICE_ID]);
+
+ }
+ }
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_chip_id(chip_id *chp_id)
+{
+ int ret = 0;
+
+ debug("Si4709_dev_chip_id called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_chip_id called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ if( (ret = i2c_read(CHIP_ID)) < 0 )
+ {
+ debug("Si4709_dev_chip_id i2c_read failed");
+ }
+ else
+ {
+
+ chp_id->chip_version= CHIP_ID_CHIP_VERSION(Si4709_dev.registers[CHIP_ID]);
+ chp_id->device = CHIP_ID_DEVICE(Si4709_dev.registers[CHIP_ID]);
+ chp_id->firmware_version = CHIP_ID_FIRMWARE_VERSION(Si4709_dev.registers[CHIP_ID]);
+ }
+ }
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_sys_config2(sys_config2 *sys_conf2)
+{
+ int ret = 0;
+
+ debug("Si4709_sys_config2 called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_sys_config2 called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ if((ret = i2c_read(SYSCONFIG2)) < 0)
+ {
+ debug("Si4709_sys_config2 i2c_read failed");
+ }
+ else
+ {
+ sys_conf2->rssi_th =SYS_CONFIG2_RSSI_TH(Si4709_dev.registers[SYSCONFIG2]);
+ sys_conf2->fm_band = SYS_CONFIG2_FM_BAND(Si4709_dev.registers[SYSCONFIG2]);
+ sys_conf2->fm_chan_spac = SYS_CONFIG2_FM_CHAN_SPAC(Si4709_dev.registers[SYSCONFIG2]);
+ sys_conf2->fm_vol = SYS_CONFIG2_FM_VOL(Si4709_dev.registers[SYSCONFIG2]);
+ }
+ }
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_sys_config3(sys_config3 *sys_conf3)
+{
+ int ret = 0;
+
+ debug("Si4709_sys_config3 called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_sys_config3 called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ if((ret = i2c_read(SYSCONFIG3)) < 0)
+ {
+ debug("Si4709_sys_config3 i2c_read failed");
+ }
+ else
+ {
+ sys_conf3->smmute = (Si4709_dev.registers[SYSCONFIG3] & 0xC000) >> 14;
+ sys_conf3->smutea = (Si4709_dev.registers[SYSCONFIG3] & 0x3000) >> 12;
+ sys_conf3->volext = (Si4709_dev.registers[SYSCONFIG3] & 0x0100) >> 8;
+ sys_conf3->sksnr = (Si4709_dev.registers[SYSCONFIG3] & 0x00F0) >> 4;
+ sys_conf3->skcnt = (Si4709_dev.registers[SYSCONFIG3] & 0x000F);
+ }
+ }
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_status_rssi(status_rssi *status)
+{
+ int ret = 0;
+
+ debug("Si4709_dev_status_rssi called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_status_rssi called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ if((ret = i2c_read(STATUSRSSI)) < 0)
+ {
+ debug("Si4709_sys_config3 i2c_read failed");
+ }
+ else
+ {
+ status->rdsr = (Si4709_dev.registers[STATUSRSSI] & 0x8000) >> 15;
+ status->stc = (Si4709_dev.registers[STATUSRSSI] & 0x4000) >> 14;
+ status->sfbl = (Si4709_dev.registers[STATUSRSSI] & 0x2000) >> 13;
+ status->afcrl = (Si4709_dev.registers[STATUSRSSI] & 0x1000) >> 12;
+ status->rdss = (Si4709_dev.registers[STATUSRSSI] & 0x0800) >> 11;
+ status->blera = (Si4709_dev.registers[STATUSRSSI] & 0x0600) >> 9;
+ status->st = (Si4709_dev.registers[STATUSRSSI] & 0x0100) >> 8;
+ status->rssi = (Si4709_dev.registers[STATUSRSSI] & 0x00FF);
+ }
+ }
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_sys_config2_set(sys_config2 *sys_conf2)
+{
+ int ret = 0;
+ u16 register_bak = 0;
+
+ debug("Si4709_dev_sys_config2_set called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ register_bak = Si4709_dev.registers[SYSCONFIG2];
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_sys_config2_set called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ printk(KERN_ERR "Si4709_dev_sys_config2_set() : Register Value = [0x%X], rssi-th = [%X]\n", Si4709_dev.registers[SYSCONFIG2], sys_conf2->rssi_th);
+ Si4709_dev.registers[SYSCONFIG2] = (Si4709_dev.registers[SYSCONFIG2] & 0x00FF) | ((sys_conf2->rssi_th) << 8);
+ Si4709_dev.registers[SYSCONFIG2] = (Si4709_dev.registers[SYSCONFIG2] & 0xFF3F) | ((sys_conf2->fm_band) << 6);
+ Si4709_dev.registers[SYSCONFIG2] = (Si4709_dev.registers[SYSCONFIG2] & 0xFFCF) | ((sys_conf2->fm_chan_spac) << 4);
+ Si4709_dev.registers[SYSCONFIG2] = (Si4709_dev.registers[SYSCONFIG2] & 0xFFF0) | (sys_conf2->fm_vol);
+ printk(KERN_ERR "Si4709_dev_sys_config2_set() : After Register Value = [0x%X]\n", Si4709_dev.registers[SYSCONFIG2]);
+
+ if( (ret = i2c_write( SYSCONFIG2 )) < 0 )
+ {
+ debug("Si4709_dev_sys_config2_set i2c_write 1 failed");
+ Si4709_dev.registers[SYSCONFIG2] = register_bak;
+ }
+ else
+ printk(KERN_ERR "Si4709_dev_sys_config2_set() : Write Sucess!!");
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_sys_config3_set(sys_config3 *sys_conf3)
+{
+ int ret = 0;
+ u16 register_bak = 0;
+
+ debug("Si4709_dev_sys_config3_set called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ register_bak = Si4709_dev.registers[SYSCONFIG3];
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_sys_config3_set called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ printk(KERN_ERR "Si4709_dev_sys_config3_set() : Register Value = [0x%X], sksnrth = [%X]\n", Si4709_dev.registers[SYSCONFIG3], sys_conf3->sksnr);
+ Si4709_dev.registers[SYSCONFIG3] = (Si4709_dev.registers[SYSCONFIG3] & 0x3FFF) | ((sys_conf3->smmute) << 14);
+ Si4709_dev.registers[SYSCONFIG3] = (Si4709_dev.registers[SYSCONFIG3] & 0xCFFF) | ((sys_conf3->smutea) << 12);
+ Si4709_dev.registers[SYSCONFIG3] = (Si4709_dev.registers[SYSCONFIG3] & 0xFEFF) | ((sys_conf3->volext) << 8);
+ Si4709_dev.registers[SYSCONFIG3] = (Si4709_dev.registers[SYSCONFIG3] & 0xFF0F) | ((sys_conf3->sksnr) << 4);
+ Si4709_dev.registers[SYSCONFIG3] = (Si4709_dev.registers[SYSCONFIG3] & 0xFFF0) | (sys_conf3->skcnt);
+ printk(KERN_ERR "Si4709_dev_sys_config3_set() : After Register Value = [0x%X]\n", Si4709_dev.registers[SYSCONFIG3]);
+
+ if((ret = i2c_write( SYSCONFIG3)) < 0)
+ {
+ debug("Si4709_dev_sys_config3_set i2c_write 1 failed");
+ Si4709_dev.registers[SYSCONFIG3] = register_bak;
+ }
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_power_config(power_config *pow_conf)
+{
+ int ret =0;
+
+ debug("Si4709_dev_power_config called");
+ mutex_lock(&(Si4709_dev.lock));
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_power_config called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ if( (ret = i2c_read(POWERCFG)) < 0 )
+ {
+ debug("Si4709_dev_power_config i2c_read failed");
+ }
+ else
+ {
+
+ pow_conf->dsmute =POWER_CONFIG_SOFTMUTE_STATUS(Si4709_dev.registers[POWERCFG]);
+ pow_conf->dmute =POWER_CONFIG_MUTE_STATUS(Si4709_dev.registers[POWERCFG]);
+ pow_conf->mono =POWER_CONFIG_MONO_STATUS(Si4709_dev.registers[POWERCFG]);
+ pow_conf->rds_mode =POWER_CONFIG_RDS_MODE_STATUS(Si4709_dev.registers[POWERCFG]);
+ pow_conf->sk_mode =POWER_CONFIG_SKMODE_STATUS(Si4709_dev.registers[POWERCFG]);
+ pow_conf->seek_up =POWER_CONFIG_SEEKUP_STATUS(Si4709_dev.registers[POWERCFG]);
+ pow_conf->seek =POWER_CONFIG_SEEK_STATUS(Si4709_dev.registers[POWERCFG]);
+ pow_conf->power_disable =POWER_CONFIG_DISABLE_STATUS(Si4709_dev.registers[POWERCFG]);
+ pow_conf->power_enable =POWER_CONFIG_ENABLE_STATUS(Si4709_dev.registers[POWERCFG]);
+ }
+ }
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+/*VNVS:END*/
+
+/*VNVS:START 18-NOV'09*/
+/*Reading AFCRL Bit*/
+int Si4709_dev_AFCRL_get(u8 *afc)
+{
+ int ret = 0;
+
+ debug("Si4709_dev_AFCRL_get called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_AFCRL_get called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ if( (ret = i2c_read(STATUSRSSI)) < 0 )
+ {
+ debug("Si4709_dev_AFCRL_get i2c_read failed");
+ }
+ *afc = STATUSRSSI_AFC_RAIL_STATUS(Si4709_dev.registers[STATUSRSSI]);
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+/*Setting DE-emphasis time constant 50us(Europe,Japan,Australia) or 75us(USA)*/
+int Si4709_dev_DE_set(u8 de_tc)
+{
+ u16 sysconfig1 = 0;
+ int ret = 0;
+
+ debug("Si4709_dev_DE_set called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ sysconfig1 = Si4709_dev.registers[SYSCONFIG1];
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_DE_set called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ switch(de_tc)
+ {
+ case DE_TIME_CONSTANT_50:
+ SYSCONFIG1_BITSET_DE_50(&Si4709_dev.registers[SYSCONFIG1]);
+ SYSCONFIG1_BITSET_RESERVED( &Si4709_dev.registers[SYSCONFIG1] );
+ break;
+ case DE_TIME_CONSTANT_75:
+ SYSCONFIG1_BITSET_DE_75(&Si4709_dev.registers[SYSCONFIG1]);
+ SYSCONFIG1_BITSET_RESERVED( &Si4709_dev.registers[SYSCONFIG1] );
+ break;
+ default:
+ ret = -1;
+ }
+
+ if(0==ret)
+ if( (ret = i2c_write(SYSCONFIG1)) < 0 )
+ {
+ debug("Si4709_dev_DE_set i2c_write failed");
+ Si4709_dev.registers[SYSCONFIG1] = sysconfig1;
+ }
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+/*Resetting the RDS Data Buffer*/
+int Si4709_dev_reset_rds_data()
+{
+ int ret = 0;
+
+ debug_rds("Si4709_dev_reset_rds_data called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_reset_rds_data called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ RDS_Buffer_Index_write = 0;
+ RDS_Buffer_Index_read = 0;
+ RDS_Data_Lost = 0;
+ RDS_Data_Available = 0;
+ memset(RDS_Block_Data_buffer,0,RDS_BUFFER_LENGTH*8);
+ memset(RDS_Block_Error_buffer,0,RDS_BUFFER_LENGTH*4);
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+/*VNVS:END*/
+int Si4709_dev_VOLEXT_ENB(void)
+{
+ int ret = 0;
+ u16 sysconfig3 = 0;
+
+ debug("Si4709_dev_VOLEXT_ENB called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ sysconfig3 = Si4709_dev.registers[SYSCONFIG3];
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_VOLEXT_ENB called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ SYSCONFIG3_BITSET_VOLEXT_ENB(&Si4709_dev.registers[SYSCONFIG3]);
+ SYSCONFIG3_BITSET_RESERVED(&Si4709_dev.registers[SYSCONFIG3]);
+
+ if( (ret = i2c_write( SYSCONFIG3 )) < 0 )
+ {
+ debug("Si4709_dev_VOLEXT_ENB i2c_write failed");
+ Si4709_dev.registers[SYSCONFIG3] = sysconfig3;
+ }
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_VOLEXT_DISB(void)
+{
+ int ret = 0;
+ u16 sysconfig3 = 0;
+
+ debug("Si4709_dev_VOLEXT_DISB called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ sysconfig3 = Si4709_dev.registers[SYSCONFIG3];
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_VOLEXT_DISB called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ SYSCONFIG3_BITSET_VOLEXT_DISB(&Si4709_dev.registers[SYSCONFIG3]);
+ SYSCONFIG3_BITSET_RESERVED(&Si4709_dev.registers[SYSCONFIG3]);
+
+ if( (ret = i2c_write( SYSCONFIG3 )) < 0 )
+ {
+ debug("Si4709_dev_VOLEXT_DISB i2c_write failed");
+ Si4709_dev.registers[SYSCONFIG3] = sysconfig3;
+ }
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_volume_set(u8 volume)
+{
+ int ret = 0;
+ u16 sysconfig2 = 0;
+
+ debug("Si4709_dev_volume_set called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ sysconfig2 = Si4709_dev.registers[SYSCONFIG2];
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_volume_set called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ SYSCONFIG2_BITSET_VOLUME(&Si4709_dev.registers[SYSCONFIG2], volume);
+
+ if( (ret = i2c_write( SYSCONFIG2 )) < 0 )
+ {
+ debug("Si4709_dev_volume_set i2c_write failed");
+ Si4709_dev.registers[SYSCONFIG2] = sysconfig2;
+ }
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_volume_get(u8 *volume)
+{
+ int ret = 0;
+
+ debug("Si4709_dev_volume_get called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_volume_get called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ *volume = SYSCONFIG2_GET_VOLUME(Si4709_dev.registers[SYSCONFIG2]);
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+/*
+ VNVS:START 19-AUG'10---- Adding DSMUTE ON/OFF feature.The Soft Mute feature is available to attenuate the audio
+ outputs and minimize audible noise in very weak signal conditions.
+ */
+int Si4709_dev_DSMUTE_ON(void)
+{
+ int ret = 0;
+ u16 powercfg = 0;
+
+ debug("Si4709_dev_DSMUTE_ON called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ powercfg = Si4709_dev.registers[POWERCFG];
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_DSMUTE_ON called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ POWERCFG_BITSET_DSMUTE_LOW(&Si4709_dev.registers[POWERCFG]);
+ POWERCFG_BITSET_RESERVED(&Si4709_dev.registers[POWERCFG]);
+
+ if( (ret = i2c_write( POWERCFG )) < 0 )
+ {
+ error("Si4709_dev_DSMUTE_ON i2c_write failed");
+ Si4709_dev.registers[POWERCFG] = powercfg;
+ }
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_DSMUTE_OFF(void)
+{
+ int ret = 0;
+ u16 powercfg = 0;
+
+ debug("Si4709_dev_DSMUTE_OFF called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ powercfg = Si4709_dev.registers[POWERCFG];
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_DSMUTE_OFF called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ POWERCFG_BITSET_DSMUTE_HIGH(&Si4709_dev.registers[POWERCFG]);
+ POWERCFG_BITSET_RESERVED(&Si4709_dev.registers[POWERCFG]);
+
+ if( (ret = i2c_write( POWERCFG )) < 0 )
+ {
+ error("Si4709_dev_DSMUTE_OFF i2c_write failed");
+ Si4709_dev.registers[POWERCFG] = powercfg;
+ }
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+/*VNVS:END*/
+
+int Si4709_dev_MUTE_ON(void)
+{
+ int ret = 0;
+ u16 powercfg = 0;
+
+ debug("Si4709_dev_MUTE_ON called");
+
+ mutex_lock(&(Si4709_dev.lock));
+ powercfg = Si4709_dev.registers[POWERCFG];
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_MUTE_ON called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ POWERCFG_BITSET_DMUTE_LOW(&Si4709_dev.registers[POWERCFG]);
+ POWERCFG_BITSET_RESERVED(&Si4709_dev.registers[POWERCFG]);
+
+ if( (ret = i2c_write( POWERCFG )) < 0 )
+ {
+ debug("Si4709_dev_MUTE_ON i2c_write failed");
+ Si4709_dev.registers[POWERCFG] = powercfg;
+ }
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_MUTE_OFF(void)
+{
+ int ret = 0;
+ u16 powercfg = 0;
+
+ debug("Si4709_dev_MUTE_OFF called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ powercfg = Si4709_dev.registers[POWERCFG];
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_MUTE_OFF called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ POWERCFG_BITSET_DMUTE_HIGH(&Si4709_dev.registers[POWERCFG]);
+ POWERCFG_BITSET_RESERVED(&Si4709_dev.registers[POWERCFG]);
+
+ if( (ret = i2c_write( POWERCFG )) < 0 )
+ {
+ debug("Si4709_dev_MUTE_OFF i2c_write failed");
+ Si4709_dev.registers[POWERCFG] = powercfg;
+ }
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_MONO_SET(void)
+{
+ int ret = 0;
+ u16 powercfg = 0;
+
+ debug("Si4709_dev_MONO_SET called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ powercfg = Si4709_dev.registers[POWERCFG];
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_MONO_SET called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ POWERCFG_BITSET_MONO_HIGH(&Si4709_dev.registers[POWERCFG]);
+ POWERCFG_BITSET_RESERVED(&Si4709_dev.registers[POWERCFG]);
+
+ if( (ret = i2c_write( POWERCFG )) < 0 )
+ {
+ debug("Si4709_dev_MONO_SET i2c_write failed");
+ Si4709_dev.registers[POWERCFG] = powercfg;
+ }
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_STEREO_SET(void)
+{
+ int ret = 0;
+ u16 powercfg = 0;
+
+ debug("Si4709_dev_STEREO_SET called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ powercfg = Si4709_dev.registers[POWERCFG];
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_STEREO_SET called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ POWERCFG_BITSET_MONO_LOW(&Si4709_dev.registers[POWERCFG]);
+ POWERCFG_BITSET_RESERVED(&Si4709_dev.registers[POWERCFG]);
+
+ if( (ret = i2c_write( POWERCFG )) < 0 )
+ {
+ debug("Si4709_dev_STEREO_SET i2c_write failed");
+ Si4709_dev.registers[POWERCFG] = powercfg;
+ }
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_RDS_ENABLE(void)
+{
+ u16 sysconfig1 = 0;
+ int ret = 0;
+
+ debug("Si4709_dev_RDS_ENABLE called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ sysconfig1 = Si4709_dev.registers[SYSCONFIG1];
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_RDS_ENABLE called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ SYSCONFIG1_BITSET_RDS_HIGH(&Si4709_dev.registers[SYSCONFIG1]);
+#ifdef RDS_INTERRUPT_ON_ALWAYS
+ SYSCONFIG1_BITSET_RDSIEN_HIGH(&Si4709_dev.registers[SYSCONFIG1]);
+#endif
+ SYSCONFIG1_BITSET_RESERVED( &Si4709_dev.registers[SYSCONFIG1] );
+ if( (ret = i2c_write(SYSCONFIG1)) < 0 )
+ {
+ debug("Si4709_dev_RDS_ENABLE i2c_write failed");
+ Si4709_dev.registers[SYSCONFIG1] = sysconfig1;
+ }
+#ifdef RDS_INTERRUPT_ON_ALWAYS
+ else
+ Si4709_RDS_flag = RDS_WAITING;
+#endif
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+
+
+int Si4709_dev_RDS_DISABLE(void)
+{
+ u16 sysconfig1 = 0;
+ int ret = 0;
+
+ debug("Si4709_dev_RDS_DISABLE called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ sysconfig1 = Si4709_dev.registers[SYSCONFIG1];
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_RDS_DISABLE called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ SYSCONFIG1_BITSET_RDS_LOW(&Si4709_dev.registers[SYSCONFIG1]);
+#ifdef RDS_INTERRUPT_ON_ALWAYS
+ SYSCONFIG1_BITSET_RDSIEN_LOW(&Si4709_dev.registers[SYSCONFIG1]);
+#endif
+ SYSCONFIG1_BITSET_RESERVED( &Si4709_dev.registers[SYSCONFIG1] );
+ if( (ret = i2c_write(SYSCONFIG1)) < 0 )
+ {
+ debug("Si4709_dev_RDS_DISABLE i2c_write failed");
+ Si4709_dev.registers[SYSCONFIG1] = sysconfig1;
+ }
+#ifdef RDS_INTERRUPT_ON_ALWAYS
+ else
+ Si4709_RDS_flag = NO_WAIT;
+#endif
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+
+int Si4709_dev_rstate_get(dev_state_t *dev_state)
+{
+ int ret = 0;
+
+ debug("Si4709_dev_rstate_get called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_rstate_get called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ dev_state->power_state = Si4709_dev.state.power_state;
+ dev_state->seek_state = Si4709_dev.state.seek_state;
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+
+/*VNVS:START 7-JUNE'10 Function call for work-queue "Si4709_wq"*/
+#ifdef RDS_INTERRUPT_ON_ALWAYS
+void Si4709_work_func(struct work_struct *work)
+{
+ int i,ret = 0;
+#ifdef RDS_TESTING
+ u8 group_type;
+#endif
+ debug_rds("%s",__func__);
+// mutex_lock(&(Si4709_dev.lock));
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ error("Si4709_dev_RDS_data_get called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+
+ if(RDS_Data_Lost > 1)
+ debug_rds("No_of_RDS_groups_Lost till now : %d",RDS_Data_Lost);
+
+
+ /*RDSR bit and RDS Block data, so reading the RDS registers*/
+ if((ret = i2c_read(RDSD)) < 0)
+ error("Si4709_work_func i2c_read failed");
+ else
+ {
+ /*Checking whether RDS Ready bit is set or not, if not set return immediately*/
+ if(!(STATUSRSSI_RDS_READY_STATUS(Si4709_dev.registers[STATUSRSSI])))
+ {
+ error("RDS Ready Bit Not set");
+ return;
+ }
+
+ debug_rds("RDS Ready bit is set");
+
+ debug_rds("No_of_RDS_groups_Available : %d",RDS_Data_Available);
+
+ RDS_Data_Available = 0;
+
+ debug_rds("RDS_Buffer_Index_write = %d",RDS_Buffer_Index_write);
+
+ /*Writing into the Circular Buffer*/
+
+ /*Writing into RDS_Block_Data_buffer*/
+ i = 0;
+ RDS_Block_Data_buffer[i++ + 4*RDS_Buffer_Index_write] = Si4709_dev.registers[RDSA];
+ RDS_Block_Data_buffer[i++ + 4*RDS_Buffer_Index_write] = Si4709_dev.registers[RDSB];
+ RDS_Block_Data_buffer[i++ + 4*RDS_Buffer_Index_write] = Si4709_dev.registers[RDSC];
+ RDS_Block_Data_buffer[i++ + 4*RDS_Buffer_Index_write] = Si4709_dev.registers[RDSD];
+
+ /*Writing into RDS_Block_Error_buffer*/
+ i = 0;
+ RDS_Block_Error_buffer[i++ + 4*RDS_Buffer_Index_write] = STATUSRSSI_RDS_BLOCK_A_ERRORS(Si4709_dev.registers[STATUSRSSI]);
+ RDS_Block_Error_buffer[i++ + 4*RDS_Buffer_Index_write] = READCHAN_BLOCK_B_ERRORS(Si4709_dev.registers[READCHAN]);
+ RDS_Block_Error_buffer[i++ + 4*RDS_Buffer_Index_write] = READCHAN_BLOCK_C_ERRORS(Si4709_dev.registers[READCHAN]);
+ RDS_Block_Error_buffer[i++ + 4*RDS_Buffer_Index_write] = READCHAN_BLOCK_D_ERRORS(Si4709_dev.registers[READCHAN]);
+
+#ifdef RDS_TESTING
+ if(RDS_Block_Error_buffer[0 + 4*RDS_Buffer_Index_write] < 3)
+ {
+ debug_rds("PI Code is %d",RDS_Block_Data_buffer[0 + 4*RDS_Buffer_Index_write]);
+ }
+ if(RDS_Block_Error_buffer[1 + 4*RDS_Buffer_Index_write] < 2)
+ {
+ group_type = RDS_Block_Data_buffer[1 + 4*RDS_Buffer_Index_write] >> 11;
+
+ if (group_type & 0x01)
+ {
+ debug_rds("PI Code is %d",RDS_Block_Data_buffer[2 + 4*RDS_Buffer_Index_write]);
+ }
+ if(group_type == GROUP_TYPE_2A || group_type == GROUP_TYPE_2B )
+ {
+ if(RDS_Block_Error_buffer[2 + 4*RDS_Buffer_Index_write] < 3)
+ {
+ debug_rds("Update RT with RDSC");
+ }
+ else
+ {
+ debug_rds("RDS_Block_Error_buffer of Block C is greater than 3");
+ }
+ }
+ }
+#endif
+ RDS_Buffer_Index_write++;
+
+ if(RDS_Buffer_Index_write >= RDS_BUFFER_LENGTH)
+ RDS_Buffer_Index_write = 0;
+
+ debug_rds("RDS_Buffer_Index_write = %d",RDS_Buffer_Index_write);
+ }
+ }
+
+// mutex_unlock(&(Si4709_dev.lock));
+}
+#endif
+/*VNVS:END*/
+
+int Si4709_dev_RDS_data_get(radio_data_t *data)
+{
+ int i,ret = 0;
+ u16 sysconfig1 = 0;
+
+ debug_rds("Si4709_dev_RDS_data_get called");
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ sysconfig1 = Si4709_dev.registers[SYSCONFIG1];
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ error("Si4709_dev_RDS_data_get called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+#ifdef RDS_INTERRUPT_ON_ALWAYS
+
+ debug_rds("RDS_Buffer_Index_read = %d",RDS_Buffer_Index_read);
+
+ /*If No New RDS Data is available return error*/
+ if(RDS_Buffer_Index_read == RDS_Buffer_Index_write)
+ {
+ debug_rds("No_New_RDS_Data_is_available");
+ if((ret = i2c_read(READCHAN)) < 0)
+ error("Si4709_dev_RDS_data_get i2c_read 1 failed");
+ else
+ {
+ get_cur_chan_freq(&(data->curr_channel), Si4709_dev.registers[READCHAN]);
+ data->curr_rssi = STATUSRSSI_RSSI_SIGNAL_STRENGTH(Si4709_dev.registers[STATUSRSSI]);
+ debug_rds("curr_channel: %u, curr_rssi:%u",data->curr_channel,(u32)data->curr_rssi);
+ }
+ ret = -1;
+ }
+ else
+ {
+ if((ret = i2c_read(READCHAN)) < 0)
+ error("Si4709_dev_RDS_data_get i2c_read 2 failed");
+ else
+ {
+ get_cur_chan_freq(&(data->curr_channel), Si4709_dev.registers[READCHAN]);
+ data->curr_rssi = STATUSRSSI_RSSI_SIGNAL_STRENGTH(Si4709_dev.registers[STATUSRSSI]);
+ debug_rds("curr_channel: %u, curr_rssi:%u",data->curr_channel,(u32)data->curr_rssi);
+
+ /*Reading from RDS_Block_Data_buffer*/
+ i = 0;
+ data->rdsa = RDS_Block_Data_buffer[i++ + 4*RDS_Buffer_Index_read];
+ data->rdsb = RDS_Block_Data_buffer[i++ + 4*RDS_Buffer_Index_read];
+ data->rdsc = RDS_Block_Data_buffer[i++ + 4*RDS_Buffer_Index_read];
+ data->rdsd = RDS_Block_Data_buffer[i++ + 4*RDS_Buffer_Index_read];
+
+ /*Reading from RDS_Block_Error_buffer*/
+ i = 0;
+ data->blera = RDS_Block_Error_buffer[i++ + 4*RDS_Buffer_Index_read];
+ data->blerb = RDS_Block_Error_buffer[i++ + 4*RDS_Buffer_Index_read];
+ data->blerc = RDS_Block_Error_buffer[i++ + 4*RDS_Buffer_Index_read];
+ data->blerd = RDS_Block_Error_buffer[i++ + 4*RDS_Buffer_Index_read];
+
+ /*Flushing the read data*/
+ memset(&RDS_Block_Data_buffer[0+4*RDS_Buffer_Index_read],0,8);
+ memset(&RDS_Block_Error_buffer[0+4*RDS_Buffer_Index_read],0,4);
+
+ RDS_Buffer_Index_read++;
+
+ if(RDS_Buffer_Index_read >= RDS_BUFFER_LENGTH)
+ RDS_Buffer_Index_read = 0;
+ }
+ }
+
+ debug_rds("RDS_Buffer_Index_read = %d",RDS_Buffer_Index_read);
+
+#else
+ SYSCONFIG1_BITSET_RDSIEN_HIGH(&Si4709_dev.registers[SYSCONFIG1]);
+
+ if((ret = i2c_write(SYSCONFIG1)) < 0)
+ {
+ debug("Si4709_dev_RDS_data_get i2c_write 1 failed");
+ Si4709_dev.registers[SYSCONFIG1] = sysconfig1;
+ }
+ else
+ {
+ if( (ret=i2c_read(SYSCONFIG1)) < 0)
+ debug("Si4709_dev_RDS_data_get i2c_read 1 failed");
+
+ debug("sysconfig1: 0x%x",Si4709_dev.registers[SYSCONFIG1] );
+ sysconfig1 = Si4709_dev.registers[SYSCONFIG1];
+
+ Si4709_dev_wait_flag = RDS_WAITING;
+
+ wait_RDS();
+
+ if((ret=i2c_read(STATUSRSSI)) < 0)
+ debug("Si4709_dev_RDS_data_get i2c_read 2 failed");
+
+ debug("statusrssi: 0x%x",Si4709_dev.registers[STATUSRSSI] );
+ SYSCONFIG1_BITSET_RDSIEN_LOW(&Si4709_dev.registers[SYSCONFIG1]);
+
+ if ((ret = i2c_write(SYSCONFIG1)) < 0)
+ {
+ debug("Si4709_dev_RDS_data_get i2c_write 2 failed");
+ Si4709_dev.registers[SYSCONFIG1] = sysconfig1;
+ }
+ else if(Si4709_dev_wait_flag == WAIT_OVER)
+ {
+ Si4709_dev_wait_flag = NO_WAIT;
+
+ if((ret = i2c_read(RDSD)) < 0)
+ debug("Si4709_dev_RDS_data_get i2c_read 3 failed");
+ else
+ {
+ data->rdsa = Si4709_dev.registers[RDSA];
+ data->rdsb = Si4709_dev.registers[RDSB];
+ data->rdsc = Si4709_dev.registers[RDSC];
+ data->rdsd = Si4709_dev.registers[RDSD];
+
+ get_cur_chan_freq(&(data->curr_channel), Si4709_dev.registers[READCHAN]);
+ debug("curr_channel: %u",data->curr_channel);
+ data->curr_rssi = STATUSRSSI_RSSI_SIGNAL_STRENGTH(Si4709_dev.registers[STATUSRSSI]);
+ debug("curr_rssi:%u",(u32)data->curr_rssi);
+ data->blera = STATUSRSSI_RDS_BLOCK_A_ERRORS(Si4709_dev.registers[STATUSRSSI]);
+ data->blerb = READCHAN_BLOCK_B_ERRORS(Si4709_dev.registers[READCHAN]);
+ data->blerc = READCHAN_BLOCK_C_ERRORS(Si4709_dev.registers[READCHAN]);
+ data->blerd = READCHAN_BLOCK_D_ERRORS(Si4709_dev.registers[READCHAN]);
+ }
+ }
+ else
+ {
+ debug("Si4709_dev_RDS_data_get failure no interrupt or timeout");
+ Si4709_dev_wait_flag = NO_WAIT;
+ ret = -1;
+ }
+ }
+#endif
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+int Si4709_dev_RDS_timeout_set(u32 time_out)
+{
+ int ret = 0;
+ u32 jiffy_count = 0;
+
+ debug("Si4709_dev_RDS_timeout_set called");
+ /****convert time_out(in milliseconds) into jiffies*****/
+
+ jiffy_count = msecs_to_jiffies(time_out);
+
+ debug("jiffy_count%d",jiffy_count);
+
+ mutex_lock(&(Si4709_dev.lock));
+
+ if( Si4709_dev.valid == eFALSE )
+ {
+ debug("Si4709_dev_RDS_timeout_set called when DS is invalid");
+ ret = -1;
+ }
+ else
+ {
+ Si4709_dev.settings.timeout_RDS = jiffy_count;
+ }
+
+ mutex_unlock(&(Si4709_dev.lock));
+
+ return ret;
+}
+
+
+/**************************************************************/
+static int powerup(void)
+{
+ int ret=0;
+ u16 powercfg = Si4709_dev.registers[POWERCFG];
+ int reg;
+ /****Resetting the device****/
+
+ gpio_set_value(FM_RESET, GPIO_LEVEL_LOW);
+ gpio_set_value(FM_RESET, GPIO_LEVEL_HIGH);
+
+#if 0
+ /*Add the i2c driver*/
+ if ( (ret = Si4709_i2c_drv_init() < 0) )
+ {
+ debug("Si4709_i2c_drv_init failed");
+ }
+#endif
+ /*Resetting the Si4709_dev.registers[] array*/
+ for(reg=0;reg < NUM_OF_REGISTERS;reg++)
+ Si4709_dev.registers[reg] = 0;
+
+ debug("Resetting the Si4709_dev.registers[] array");
+
+ POWERCFG_BITSET_DMUTE_HIGH( &Si4709_dev.registers[POWERCFG] );
+ POWERCFG_BITSET_ENABLE_HIGH( &Si4709_dev.registers[POWERCFG] );
+ POWERCFG_BITSET_DISABLE_LOW( &Si4709_dev.registers[POWERCFG] );
+ POWERCFG_BITSET_RESERVED( &Si4709_dev.registers[POWERCFG] );
+
+ if( (ret = i2c_write(POWERCFG)) < 0 )
+ {
+ debug("powerup->i2c_write 1 failed");
+ Si4709_dev.registers[POWERCFG] = powercfg;
+ }
+ else
+ {
+ /*Si4709/09 datasheet: Table 7*/
+ mdelay(110);
+ Si4709_dev.state.power_state = RADIO_ON;
+ }
+
+ return ret;
+}
+
+static int powerdown(void)
+{
+ int ret = 0;
+ u16 test1 = Si4709_dev.registers[TEST1],
+ sysconfig1 = Si4709_dev.registers[SYSCONFIG1],
+ powercfg = Si4709_dev.registers[POWERCFG];
+
+ if(!(RADIO_POWERDOWN==Si4709_dev.state.power_state))
+ {
+ //TEST1_BITSET_AHIZEN_HIGH( &Si4709_dev.registers[TEST1] );
+ //TEST1_BITSET_RESERVED( &Si4709_dev.registers[TEST1] );
+
+ SYSCONFIG1_BITSET_GPIO_LOW(&Si4709_dev.registers[SYSCONFIG1]);
+ SYSCONFIG1_BITSET_RESERVED( &Si4709_dev.registers[SYSCONFIG1] );
+ /*VNVS: 13-OCT'09---- During Powerdown of the device RDS should be disabled
+ according to the Si4708/09 datasheet*/
+ SYSCONFIG1_BITSET_RDS_LOW(&Si4709_dev.registers[SYSCONFIG1]);
+
+ POWERCFG_BITSET_DMUTE_LOW( &Si4709_dev.registers[POWERCFG] );
+ POWERCFG_BITSET_ENABLE_HIGH( &Si4709_dev.registers[POWERCFG] );
+ POWERCFG_BITSET_DISABLE_HIGH( &Si4709_dev.registers[POWERCFG] );
+ POWERCFG_BITSET_RESERVED( &Si4709_dev.registers[POWERCFG] );
+
+ /*this will write all the above registers*/
+ if( (ret = i2c_write( TEST1 )) < 0 )
+ {
+ debug("powerdown->i2c_write failed");
+ Si4709_dev.registers[SYSCONFIG1] = sysconfig1;
+ Si4709_dev.registers[POWERCFG] = powercfg;
+ Si4709_dev.registers[TEST1] = test1;
+ }
+ else
+ {
+ Si4709_dev.state.power_state = RADIO_POWERDOWN;
+ }
+
+ /****Resetting the device****/
+ gpio_set_value(FM_RESET, GPIO_LEVEL_LOW);
+ gpio_set_value(FM_RESET, GPIO_LEVEL_HIGH);
+ gpio_set_value(FM_RESET, GPIO_LEVEL_LOW);
+ }
+ else
+ debug("Device already Powered-OFF");
+
+ return ret;
+}
+
+static int seek(u32 *frequency, int up)
+{
+ int ret = 0;
+ u16 powercfg = Si4709_dev.registers[POWERCFG];
+ u16 channel = 0;
+ int valid_station_found = 0;
+
+ if( up )
+ {
+ POWERCFG_BITSET_SEEKUP_HIGH(&Si4709_dev.registers[POWERCFG]);
+ }
+ else
+ {
+ POWERCFG_BITSET_SEEKUP_LOW(&Si4709_dev.registers[POWERCFG]);
+ }
+
+ POWERCFG_BITSET_SKMODE_HIGH(&Si4709_dev.registers[POWERCFG]);
+ POWERCFG_BITSET_SEEK_HIGH(&Si4709_dev.registers[POWERCFG]);
+ POWERCFG_BITSET_RESERVED(&Si4709_dev.registers[POWERCFG]);
+
+ if( (ret = i2c_write(POWERCFG)) < 0 )
+ {
+ debug("seek i2c_write 1 failed");
+ Si4709_dev.registers[POWERCFG] = powercfg;
+ }
+ else
+ {
+ Si4709_dev_wait_flag = SEEK_WAITING;
+
+ wait();
+
+ if ( Si4709_dev_wait_flag == SEEK_CANCEL )
+ {
+ powercfg = Si4709_dev.registers[POWERCFG];
+ POWERCFG_BITSET_SEEK_LOW(&Si4709_dev.registers[POWERCFG]);
+ POWERCFG_BITSET_RESERVED(&Si4709_dev.registers[POWERCFG]);
+
+ if( (ret = i2c_write(POWERCFG)) < 0 )
+ {
+ debug("seek i2c_write 2 failed");
+ Si4709_dev.registers[POWERCFG] = powercfg;
+ }
+
+ if( (ret = i2c_read( READCHAN )) < 0 )
+ {
+ debug("seek i2c_read 1 failed");
+ }
+ else
+ {
+ channel = READCHAN_GET_CHAN(Si4709_dev.registers[READCHAN]);
+ *frequency = channel_to_freq(channel);
+ }
+ *frequency = 0;
+ }
+
+ Si4709_dev_wait_flag = NO_WAIT;
+
+ if( (ret = i2c_read(STATUSRSSI)) < 0 )
+ {
+ debug("seek i2c_read 2 failed");
+ }
+ else
+ {
+ /*VNVS:START 13-OCT'09---- Checking the status of Seek/Tune Bit*/
+#ifdef TEST_FM
+ if(STATUSRSSI_SEEK_TUNE_STATUS(Si4709_dev.registers[STATUSRSSI]) == COMPLETE)
+ {
+ debug("Seek/Tune Status is set to 1 by device");
+ if(STATUSRSSI_SF_BL_STATUS(Si4709_dev.registers[STATUSRSSI]) == SEEK_SUCCESSFUL)
+ {
+ debug("Seek Fail/Band Limit Status is set to 0 by device ---SeekUp Operation Completed");
+ valid_station_found = 1;
+ }
+ else
+ debug("Seek Fail/Band Limit Status is set to 1 by device ---SeekUp Operation Not Completed");
+ }
+ else
+ debug("Seek/Tune Status is set to 0 by device ---SeekUp Operation Not Completed");
+
+#endif
+ /*VNVS:END*/
+
+ powercfg = Si4709_dev.registers[POWERCFG];
+
+ POWERCFG_BITSET_SEEK_LOW(&Si4709_dev.registers[POWERCFG]);
+ POWERCFG_BITSET_RESERVED(&Si4709_dev.registers[POWERCFG]);
+
+ if( (ret = i2c_write(POWERCFG)) < 0 )
+ {
+ debug("seek i2c_write 2 failed");
+ Si4709_dev.registers[POWERCFG] = powercfg;
+ }
+ else
+ {
+ do
+ {
+ if( (ret = i2c_read(STATUSRSSI)) < 0 )
+ {
+ debug("seek i2c_read 3 failed");
+ break;
+ }
+ }while( STATUSRSSI_SEEK_TUNE_STATUS(Si4709_dev.registers[STATUSRSSI]) != CLEAR );
+
+ if( ret == 0 && valid_station_found == 1 )
+ {
+ if( (ret = i2c_read( READCHAN )) < 0 )
+ {
+ debug("seek i2c_read 4 failed");
+ }
+ else
+ {
+ channel = READCHAN_GET_CHAN(Si4709_dev.registers[READCHAN]);
+ *frequency = channel_to_freq(channel);
+ debug("Frequency after seek-up is %d \n",*frequency);
+ }
+ }
+ else
+ {
+ debug("Valid station not found \n");
+ *frequency = 0;
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
+static int tune_freq(u32 frequency)
+{
+ int ret = 0;
+ u16 channel = Si4709_dev.registers[CHANNEL];
+#ifdef TEST_FM
+ u16 read_channel;
+#endif
+ debug("tune_freq called");
+
+ Si4709_dev.registers[CHANNEL] = freq_to_channel(frequency);
+#ifdef TEST_FM
+ read_channel = Si4709_dev.registers[CHANNEL];
+ debug(" Input read_channel =%x",read_channel);
+#endif
+ CHANNEL_BITSET_TUNE_HIGH(&Si4709_dev.registers[CHANNEL]);
+ CHANNEL_BITSET_RESERVED(&Si4709_dev.registers[CHANNEL]);
+
+ if( (ret = i2c_write(CHANNEL)) < 0 )
+ {
+ debug("tune_freq i2c_write 1 failed");
+ Si4709_dev.registers[CHANNEL] = channel;
+ }
+ else
+ {
+
+ Si4709_dev_wait_flag = TUNE_WAITING;
+ debug("Si4709_dev_wait_flag = TUNE_WAITING");
+#ifdef TEST_FM
+ if( (ret = i2c_read(READCHAN)) < 0 )
+ {
+ debug("tune_freq i2c_read 1 failed");
+ }
+ else
+ {
+ read_channel=READCHAN_GET_CHAN(Si4709_dev.registers[READCHAN]);
+ debug("curr_channel before tuning = %x",read_channel);
+ }
+#endif
+
+ wait();
+
+ Si4709_dev_wait_flag = NO_WAIT;
+
+ /*VNVS:START 13-OCT'09---- Checking the status of Seek/Tune Bit*/
+#ifdef TEST_FM
+ if( (ret = i2c_read(STATUSRSSI)) < 0 )
+ {
+ debug("tune_freq i2c_read 2 failed");
+
+ }
+ else if(STATUSRSSI_SEEK_TUNE_STATUS(Si4709_dev.registers[STATUSRSSI]) == COMPLETE)
+ debug("Seek/Tune Status is set to 1 by device ---Tuning Operation Completed");
+ else
+ debug("Seek/Tune Status is set to 0 by device ---Tuning Operation Not Completed");
+#endif
+ /*VNVS:END*/
+
+ channel = Si4709_dev.registers[CHANNEL];
+
+ CHANNEL_BITSET_TUNE_LOW(&Si4709_dev.registers[CHANNEL]);
+ CHANNEL_BITSET_RESERVED(&Si4709_dev.registers[CHANNEL]);
+
+ if( (ret = i2c_write(CHANNEL)) < 0 )
+ {
+ debug("tune_freq i2c_write 2 failed");
+ Si4709_dev.registers[CHANNEL] = channel;
+ }
+ else
+ {
+ do
+ {
+ if( (ret = i2c_read(STATUSRSSI)) < 0 )
+ {
+ debug("tune_freq i2c_read 3 failed");
+ break;
+ }
+ }while( STATUSRSSI_SEEK_TUNE_STATUS(Si4709_dev.registers[STATUSRSSI]) != CLEAR );
+
+ }
+
+ /*VNVS:START 13-OCT'09---- Reading the READCHAN register after tuning operation*/
+#ifdef TEST_FM
+ if( (ret = i2c_read(READCHAN)) < 0 )
+ {
+ debug("tune_freq i2c_read 2 failed");
+ }
+ else
+ {
+ read_channel=READCHAN_GET_CHAN(Si4709_dev.registers[READCHAN]);
+ debug("curr_channel after tuning= %x",read_channel);
+ }
+#endif
+ /*VNVS:END*/
+ }
+
+ return ret;
+}
+
+static void get_cur_chan_freq(u32 *frequency, u16 readchan)
+{
+
+ u16 channel = 0;
+ debug("get_cur_chan_freq called");
+
+ channel = READCHAN_GET_CHAN(readchan);
+ debug("read_channel=%x",channel);
+
+ *frequency = channel_to_freq(channel);
+
+ debug("frequency-> %u",*frequency);
+}
+
+static u16 freq_to_channel(u32 frequency)
+{
+ u16 channel;
+
+ if( frequency < Si4709_dev.settings.bottom_of_band )
+ {
+ frequency = Si4709_dev.settings.bottom_of_band;
+ }
+
+ channel = (frequency - Si4709_dev.settings.bottom_of_band)
+ / Si4709_dev.settings.channel_spacing;
+
+ return channel;
+}
+
+static u32 channel_to_freq(u16 channel)
+{
+ u32 frequency;
+
+ frequency = Si4709_dev.settings.bottom_of_band +
+ Si4709_dev.settings.channel_spacing * channel;
+
+ return frequency;
+}
+
+/*Only one thread will be able to call this, since this function call is
+ protected by a mutex, so no race conditions can arise*/
+static void wait(void)
+{
+ wait_event_interruptible(Si4709_waitq,
+ (Si4709_dev_wait_flag == WAIT_OVER) || (Si4709_dev_wait_flag == SEEK_CANCEL));
+}
+
+static void wait_RDS(void)
+{
+ wait_event_interruptible_timeout(Si4709_waitq,
+ (Si4709_dev_wait_flag == WAIT_OVER),Si4709_dev.settings.timeout_RDS);
+}
+
+/*i2c read function*/
+/*Si4709_dev.client should be set before calling this function.
+ If Si4709_dev.valid = eTRUE then Si4709_dev.client will b valid
+ This function should be called from the functions in this file. The
+ callers should check if Si4709_dev.valid = eTRUE before
+ calling this function. If it is eFALSE then this function should not
+ be called*/
+static int i2c_read( u8 reg )
+{
+ u8 idx, reading_reg = STATUSRSSI;
+ u8 data[NUM_OF_REGISTERS * 2], data_high, data_low;
+ int msglen = 0, ret = 0;
+
+ for(idx = 0; idx < NUM_OF_REGISTERS * 2; idx++)
+ {
+ data[idx] = 0x00;
+ }
+
+ msglen = reg - reading_reg + 1;
+
+ if(msglen > 0)
+ {
+ msglen = msglen * 2;
+ }
+ else
+ {
+ msglen = (msglen + NUM_OF_REGISTERS) * 2;
+ }
+
+ ret = i2c_master_recv((struct i2c_client*)(Si4709_dev.client), data, msglen);
+
+ if(ret == msglen)
+ {
+ idx = 0;
+ do
+ {
+ data_high = data[idx];
+ data_low = data[idx+1];
+
+ Si4709_dev.registers[reading_reg] = 0x0000;
+ Si4709_dev.registers[reading_reg] = (data_high << 8) + data_low;
+ reading_reg = (reading_reg + 1) & RDSD;
+ idx = idx + 2;
+ } while(reading_reg != ((reg +1) & RDSD));
+
+ ret = 0;
+ }
+ else
+ {
+ ret = -1;
+ }
+
+ return ret;
+}
+
+/*i2c write function*/
+/*Si4709_dev.client should be set before calling this function.
+ If Si4709_dev.valid = eTRUE then Si4709_dev.client will b valid
+ This function should be called from the functions in this file. The
+ callers should check if Si4709_dev.valid = eTRUE before
+ calling this function. If it is eFALSE then this function should not
+ be called*/
+static int i2c_write( u8 reg )
+{
+ u8 writing_reg = POWERCFG;
+ u8 data[NUM_OF_REGISTERS * 2];
+ int i, msglen = 0, ret = 0;
+
+ for(i = 0; i < NUM_OF_REGISTERS * 2; i++)
+ {
+ data[i] = 0x00;
+ }
+
+ do
+ {
+ data[msglen++] = (u8)(Si4709_dev.registers[writing_reg] >> 8);
+ data[msglen++] = (u8)(Si4709_dev.registers[writing_reg] & 0xFF);
+
+ writing_reg = (writing_reg +1) & RDSD;
+ } while(writing_reg != ((reg + 1) & RDSD));
+
+ ret = i2c_master_send((struct i2c_client*)(Si4709_dev.client), ( const char *)data, msglen);
+
+ if(ret == msglen)
+ {
+ ret = 0;
+ }
+ else
+ {
+ ret = -1;
+ }
+
+ return ret;
+}
+
+static int insert_preset(u32 frequency,u8 rssi,u8 *seek_preset_rssi)
+{
+ u8 i;
+ u8 min_rssi = 0xff;
+ u8 min_rssi_preset=0;
+ int ret = 0;
+
+ /* first find the minimum rssi and its location
+ this will always stop at the first location with a zero rssi */
+
+ debug("si4709 autoseek : insert preset\n");
+
+ for (i=0; i<NUM_SEEK_PRESETS; i++)
+ {
+ if (seek_preset_rssi[i] < min_rssi)
+ {
+ min_rssi = seek_preset_rssi[i];
+ min_rssi_preset = i;
+ }
+ }
+
+ if (rssi < min_rssi)
+ ret = -1;
+
+ /***Delete the preset with the minimum rssi, and clear the last preset
+ since it would only be a copy of the second to last preset after
+ the deletion ***/
+ for (i=min_rssi_preset; i<NUM_SEEK_PRESETS-1; i++)
+ {
+ Si4709_dev.settings.seek_preset[i]= Si4709_dev.settings.seek_preset[i+1];
+ seek_preset_rssi[i] = seek_preset_rssi[i+1];
+ }
+
+ Si4709_dev.settings.seek_preset[i] = 0;
+ seek_preset_rssi[i] = 0;
+
+ /*** Fill the first preset with a zero for the frequency. This will
+ always overwrite the last preset once all presets have been filled. ***/
+ for (i=min_rssi_preset; i<NUM_SEEK_PRESETS; i++)
+ {
+ if(Si4709_dev.settings.seek_preset[i] == 0)
+ {
+ Si4709_dev.settings.seek_preset[i]= frequency;
+ seek_preset_rssi[i] = rssi;
+ break;
+ }
+ }
+ return ret;
+}
+
+
diff --git a/drivers/media/radio/si4709/radio-si4709_dev.h b/drivers/media/radio/si4709/radio-si4709_dev.h
new file mode 100644
index 0000000..bdcde4f
--- /dev/null
+++ b/drivers/media/radio/si4709/radio-si4709_dev.h
@@ -0,0 +1,181 @@
+#ifndef _Si4709_DEV_H
+#define _Si4709_DEV_H
+
+#include <linux/i2c.h>
+#include "radio-si4709_common.h"
+
+typedef struct
+{
+ int power_state;
+ int seek_state;
+}dev_state_t;
+
+typedef struct
+{
+ u8 curr_rssi;
+ u8 curr_rssi_th;
+ u8 curr_snr;
+}rssi_snr_t;
+
+typedef struct
+{
+ u8 part_number;
+ u16 manufact_number;
+} device_id;
+
+typedef struct
+{
+ u8 chip_version;
+ u8 device;
+ u8 firmware_version;
+}chip_id;
+
+typedef struct
+{
+ u16 rssi_th;
+ u8 fm_band;
+ u8 fm_chan_spac;
+ u8 fm_vol;
+} sys_config2;
+
+typedef struct
+{
+ u8 smmute;
+ u8 smutea;
+ u8 volext;
+ u8 sksnr;
+ u8 skcnt;
+} sys_config3;
+
+typedef struct
+{
+ u8 rdsr;
+ u8 stc;
+ u8 sfbl;
+ u8 afcrl;
+ u8 rdss;
+ u8 blera;
+ u8 st;
+ u16 rssi;
+} status_rssi;
+
+typedef struct
+{
+ u16 dsmute :1;
+ u16 dmute:1;
+ u16 mono:1;
+ u16 rds_mode:1;
+ u16 sk_mode:1;
+ u16 seek_up:1;
+ u16 seek:1;
+ u16 power_disable:1;
+ u16 power_enable:1;
+} power_config;
+
+typedef struct
+{
+ u16 rdsa;
+ u16 rdsb;
+ u16 rdsc;
+ u16 rdsd;
+ u8 curr_rssi;
+ u32 curr_channel;
+ u8 blera;
+ u8 blerb;
+ u8 blerc;
+ u8 blerd;
+}radio_data_t;
+
+#define NUM_SEEK_PRESETS 20
+
+#define WAIT_OVER 0
+#define SEEK_WAITING 1
+#define NO_WAIT 2
+#define TUNE_WAITING 4
+#define RDS_WAITING 5
+#define SEEK_CANCEL 6
+
+/*dev settings*/
+/*band*/
+#define BAND_87500_108000_kHz 1
+#define BAND_76000_108000_kHz 2
+#define BAND_76000_90000_kHz 3
+
+/*channel spacing*/
+#define CHAN_SPACING_200_kHz 20 /*US*/
+#define CHAN_SPACING_100_kHz 10 /*Europe,Japan*/
+#define CHAN_SPACING_50_kHz 5
+
+/*DE-emphasis Time Constant*/
+#define DE_TIME_CONSTANT_50 1 /*Europe,Japan,Australia*/
+#define DE_TIME_CONSTANT_75 0 /*US*/
+
+extern int Si4709_dev_wait_flag;
+
+#ifdef RDS_INTERRUPT_ON_ALWAYS
+extern int Si4709_RDS_flag;
+extern int RDS_Data_Available;
+extern int RDS_Data_Lost;
+extern int RDS_Groups_Available_till_now;
+extern struct workqueue_struct *Si4709_wq;
+extern struct work_struct Si4709_work;
+#endif
+
+/*Function prototypes*/
+extern int Si4709_dev_init(struct i2c_client *);
+extern int Si4709_dev_exit(void);
+
+extern void Si4709_dev_mutex_init(void);
+
+extern int Si4709_dev_suspend(void);
+extern int Si4709_dev_resume(void);
+
+extern int Si4709_dev_powerup(void);
+extern int Si4709_dev_powerdown(void);
+
+extern int Si4709_dev_band_set(int);
+extern int Si4709_dev_ch_spacing_set(int);
+
+extern int Si4709_dev_chan_select(u32);
+extern int Si4709_dev_chan_get(u32*);
+
+extern int Si4709_dev_seek_up(u32*);
+extern int Si4709_dev_seek_down(u32*);
+extern int Si4709_dev_seek_auto(u32*);
+
+extern int Si4709_dev_RSSI_seek_th_set(u8);
+extern int Si4709_dev_seek_SNR_th_set(u8);
+extern int Si4709_dev_seek_FM_ID_th_set(u8);
+extern int Si4709_dev_cur_RSSI_get(rssi_snr_t*);
+extern int Si4709_dev_VOLEXT_ENB(void);
+extern int Si4709_dev_VOLEXT_DISB(void);
+extern int Si4709_dev_volume_set(u8);
+extern int Si4709_dev_volume_get(u8*);
+extern int Si4709_dev_DSMUTE_ON(void);
+extern int Si4709_dev_DSMUTE_OFF(void);
+extern int Si4709_dev_MUTE_ON(void);
+extern int Si4709_dev_MUTE_OFF(void);
+extern int Si4709_dev_MONO_SET(void);
+extern int Si4709_dev_STEREO_SET(void);
+extern int Si4709_dev_rstate_get(dev_state_t*);
+extern int Si4709_dev_RDS_data_get(radio_data_t*);
+extern int Si4709_dev_RDS_ENABLE(void);
+extern int Si4709_dev_RDS_DISABLE(void);
+extern int Si4709_dev_RDS_timeout_set(u32);
+extern int Si4709_dev_device_id(device_id *);
+extern int Si4709_dev_chip_id(chip_id *);
+extern int Si4709_dev_sys_config2(sys_config2 *);
+extern int Si4709_dev_sys_config3(sys_config3 *);
+extern int Si4709_dev_power_config(power_config *);
+extern int Si4709_dev_AFCRL_get(u8*);
+extern int Si4709_dev_DE_set(u8);
+extern int Si4709_dev_status_rssi(status_rssi *status);
+extern int Si4709_dev_sys_config2_set(sys_config2 *sys_conf2);
+extern int Si4709_dev_sys_config3_set(sys_config3 *sys_conf3);
+extern int Si4709_dev_reset_rds_data(void);
+
+#ifdef RDS_INTERRUPT_ON_ALWAYS
+extern void Si4709_work_func(struct work_struct*);
+#endif
+#endif
+
diff --git a/drivers/media/radio/si4709/radio-si4709_i2c_drv.c b/drivers/media/radio/si4709/radio-si4709_i2c_drv.c
new file mode 100644
index 0000000..5885b04
--- /dev/null
+++ b/drivers/media/radio/si4709/radio-si4709_i2c_drv.c
@@ -0,0 +1,196 @@
+
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+
+#include "radio-si4709_dev.h"
+#include "radio-si4709_common.h"
+
+/*extern functions*/
+int Si4709_i2c_drv_init(void);
+void Si4709_i2c_drv_exit(void);
+
+/*static functions*/
+static int Si4709_probe (struct i2c_client *);
+static int Si4709_remove(struct i2c_client *);
+static int Si4709_suspend(struct i2c_client *, pm_message_t mesg);
+static int Si4709_resume(struct i2c_client *);
+
+static struct i2c_client *Si4709_i2c_client;
+
+
+struct si4709_data {
+ struct i2c_client *client;
+};
+
+/*I2C Setting*/
+#define SI4709_I2C_ADDRESS 0x20
+
+static unsigned short Si4709_normal_i2c[] = { I2C_CLIENT_END };
+
+static struct i2c_driver Si4709_i2c_driver;
+
+static const struct i2c_device_id si4709_id[] = {
+ {"Si4709", 0},
+ {}
+};
+
+static int Si4709_probe (struct i2c_client *client)
+{
+ int ret = 0;
+
+ debug("Si4709 i2c driver Si4709_probe called");
+
+ if( strcmp(client->name, "Si4709") != 0 )
+ {
+ ret = -1;
+ debug("Si4709_probe: device not supported");
+ }
+ else if( (ret = Si4709_dev_init(client)) < 0 )
+ {
+ debug("Si4709_dev_init failed");
+ }
+
+ return ret;
+}
+
+static int Si4709_remove(struct i2c_client *client)
+{
+ int ret = 0;
+
+ debug("Si4709 i2c driver Si4709_remove called");
+
+ if( strcmp(client->name, "Si4709") != 0 )
+ {
+ ret = -1;
+ debug("Si4709_remove: device not supported");
+ }
+ else if( (ret = Si4709_dev_exit()) < 0 )
+ {
+ debug("Si4709_dev_exit failed");
+ }
+
+ return ret;
+}
+
+static int __devinit si4709_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+ int err = 0;
+ struct si4709_data *si4709_dev;
+
+ debug("----- %s %d\n", __func__, __LINE__);
+
+ si4709_dev = kzalloc(sizeof(struct si4709_data), GFP_KERNEL);
+
+ if(!si4709_dev)
+ {
+ err = -ENOMEM;
+ return err;
+ }
+
+ Si4709_i2c_client = client;
+ i2c_set_clientdata(client, si4709_dev);
+
+ if(Si4709_i2c_client == NULL)
+ {
+ error("Si4709 i2c_client is NULL");
+ return -ENODEV;
+ }
+
+ Si4709_probe(Si4709_i2c_client);
+
+ return 0;
+}
+
+static int __devexit si4709_i2c_remove(struct i2c_client *client)
+{
+ struct si4709_data *si4709_dev = i2c_get_clientdata(client);
+
+ printk("----- %s %d\n", __func__, __LINE__);
+
+ Si4709_remove(Si4709_i2c_client);
+ kfree(si4709_dev);
+ kfree(client);
+ si4709_dev = NULL;
+ Si4709_i2c_client = NULL;
+
+ return 0;
+}
+
+
+MODULE_DEVICE_TABLE(i2c, si4709_id);
+
+static struct i2c_driver Si4709_i2c_driver =
+{
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "Si4709",
+ },
+ .id_table = si4709_id,
+ .probe = si4709_i2c_probe,
+ .remove = __devexit_p(si4709_i2c_remove),
+ .suspend = Si4709_suspend,
+ .resume = Si4709_resume,
+ .address_list = Si4709_normal_i2c,
+};
+
+static int Si4709_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+ int ret = 0;
+
+ debug("Si4709 i2c driver Si4709_suspend called");
+
+ if( strcmp(client->name, "Si4709") != 0 )
+ {
+ ret = -1;
+ debug("Si4709_suspend: device not supported");
+ }
+ else if( (ret = Si4709_dev_suspend()) < 0 )
+ {
+ debug("Si4709_dev_disable failed");
+ }
+
+ return 0;
+}
+
+static int Si4709_resume(struct i2c_client *client)
+{
+ int ret = 0;
+
+// debug("Si4709 i2c driver Si4709_resume called");
+
+ if( strcmp(client->name, "Si4709") != 0 )
+ {
+ ret = -1;
+ debug("Si4709_resume: device not supported");
+ }
+ else if( (ret = Si4709_dev_resume()) < 0 )
+ {
+ debug("Si4709_dev_enable failed");
+ }
+
+ return 0;
+}
+
+int Si4709_i2c_drv_init(void)
+{
+ int ret = 0;
+
+ debug("Si4709 i2c driver Si4709_i2c_driver_init called");
+
+ if ( (ret = i2c_add_driver(&Si4709_i2c_driver) < 0) )
+ {
+ error("Si4709 i2c_add_driver failed");
+ }
+
+ return ret;
+}
+
+void Si4709_i2c_drv_exit(void)
+{
+ debug("Si4709 i2c driver Si4709_i2c_driver_exit called");
+
+ i2c_del_driver(&Si4709_i2c_driver);
+}
+
+
diff --git a/drivers/media/radio/si4709/radio-si4709_i2c_drv.h b/drivers/media/radio/si4709/radio-si4709_i2c_drv.h
new file mode 100644
index 0000000..fb705a3
--- /dev/null
+++ b/drivers/media/radio/si4709/radio-si4709_i2c_drv.h
@@ -0,0 +1,8 @@
+#ifndef _Si4709_I2C_DRV_H
+#define _Si4709_I2C_DRV_H
+
+extern int Si4709_i2c_drv_init(void);
+extern int Si4709_i2c_drv_exit(void);
+
+#endif
+
diff --git a/drivers/media/radio/si4709/radio-si4709_ioctl.h b/drivers/media/radio/si4709/radio-si4709_ioctl.h
new file mode 100644
index 0000000..5165a99
--- /dev/null
+++ b/drivers/media/radio/si4709/radio-si4709_ioctl.h
@@ -0,0 +1,104 @@
+#ifndef _Si4709_IOCTL_H
+#define _Si4709_IOCTL_H
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+#include "radio-si4709_dev.h"
+
+/*****************IOCTLS******************/
+/*magic no*/
+#define Si4709_IOC_MAGIC 0xFA
+/*max seq no*/
+#define Si4709_IOC_NR_MAX 40
+
+/*commands*/
+
+#define Si4709_IOC_POWERUP _IO(Si4709_IOC_MAGIC, 0)
+
+#define Si4709_IOC_POWERDOWN _IO(Si4709_IOC_MAGIC, 1)
+
+#define Si4709_IOC_BAND_SET _IOW(Si4709_IOC_MAGIC, 2, int)
+
+#define Si4709_IOC_CHAN_SPACING_SET _IOW(Si4709_IOC_MAGIC, 3, int)
+
+#define Si4709_IOC_CHAN_SELECT _IOW(Si4709_IOC_MAGIC, 4, u32)
+
+#define Si4709_IOC_CHAN_GET _IOR(Si4709_IOC_MAGIC, 5, u32)
+
+#define Si4709_IOC_SEEK_UP _IOR(Si4709_IOC_MAGIC, 6, u32)
+
+#define Si4709_IOC_SEEK_DOWN _IOR(Si4709_IOC_MAGIC, 7, u32)
+
+/*VNVS:28OCT'09---- Si4709_IOC_SEEK_AUTO is disabled as of now*/
+//#define Si4709_IOC_SEEK_AUTO _IOR(Si4709_IOC_MAGIC, 8, u32)
+
+#define Si4709_IOC_RSSI_SEEK_TH_SET _IOW(Si4709_IOC_MAGIC, 9, u8)
+
+#define Si4709_IOC_SEEK_SNR_SET _IOW(Si4709_IOC_MAGIC, 10, u8)
+
+#define Si4709_IOC_SEEK_CNT_SET _IOW(Si4709_IOC_MAGIC, 11, u8)
+
+#define Si4709_IOC_CUR_RSSI_GET _IOR(Si4709_IOC_MAGIC, 12, rssi_snr_t)
+
+#define Si4709_IOC_VOLEXT_ENB _IO(Si4709_IOC_MAGIC, 13)
+
+#define Si4709_IOC_VOLEXT_DISB _IO(Si4709_IOC_MAGIC, 14)
+
+#define Si4709_IOC_VOLUME_SET _IOW(Si4709_IOC_MAGIC, 15, u8)
+
+#define Si4709_IOC_VOLUME_GET _IOR(Si4709_IOC_MAGIC, 16, u8)
+
+#define Si4709_IOC_MUTE_ON _IO(Si4709_IOC_MAGIC, 17)
+
+#define Si4709_IOC_MUTE_OFF _IO(Si4709_IOC_MAGIC, 18)
+
+#define Si4709_IOC_MONO_SET _IO(Si4709_IOC_MAGIC, 19)
+
+#define Si4709_IOC_STEREO_SET _IO(Si4709_IOC_MAGIC, 20)
+
+#define Si4709_IOC_RSTATE_GET _IOR(Si4709_IOC_MAGIC, 21, dev_state_t)
+
+#define Si4709_IOC_RDS_DATA_GET _IOR(Si4709_IOC_MAGIC, 22, radio_data_t)
+
+#define Si4709_IOC_RDS_ENABLE _IO(Si4709_IOC_MAGIC, 23)
+
+#define Si4709_IOC_RDS_DISABLE _IO(Si4709_IOC_MAGIC, 24)
+
+#define Si4709_IOC_RDS_TIMEOUT_SET _IOW(Si4709_IOC_MAGIC, 25, u32)
+
+#define Si4709_IOC_SEEK_CANCEL _IO(Si4709_IOC_MAGIC, 26)
+
+/*VNVS:START 13-OCT'09---- Added IOCTLs for reading the device-id,chip-id,power configuration, system configuration2 registers*/
+#define Si4709_IOC_DEVICE_ID_GET _IOR(Si4709_IOC_MAGIC, 27,device_id)
+
+#define Si4709_IOC_CHIP_ID_GET _IOR(Si4709_IOC_MAGIC, 28,chip_id)
+
+#define Si4709_IOC_SYS_CONFIG2_GET _IOR(Si4709_IOC_MAGIC,29,sys_config2)
+
+#define Si4709_IOC_POWER_CONFIG_GET _IOR(Si4709_IOC_MAGIC,30,power_config)
+
+#define Si4709_IOC_AFCRL_GET _IOR(Si4709_IOC_MAGIC,31,u8) /*For reading AFCRL bit, to check for a valid channel*/
+
+#define Si4709_IOC_DE_SET _IOW(Si4709_IOC_MAGIC,32,u8) /*Setting DE-emphasis Time Constant. For DE=0,TC=50us(Europe,Japan,Australia) and DE=1,TC=75us(USA)*/
+/*VNVS:END*/
+
+#define Si4709_IOC_SYS_CONFIG3_GET _IOR(Si4709_IOC_MAGIC, 33, sys_config3)
+
+#define Si4709_IOC_STATUS_RSSI_GET _IOR(Si4709_IOC_MAGIC, 34, status_rssi)
+
+#define Si4709_IOC_SYS_CONFIG2_SET _IOW(Si4709_IOC_MAGIC, 35, sys_config2)
+
+#define Si4709_IOC_SYS_CONFIG3_SET _IOW(Si4709_IOC_MAGIC, 36, sys_config3)
+
+#define Si4709_IOC_DSMUTE_ON _IO(Si4709_IOC_MAGIC, 37)
+
+#define Si4709_IOC_DSMUTE_OFF _IO(Si4709_IOC_MAGIC, 38)
+
+#define Si4709_IOC_RESET_RDS_DATA _IO(Si4709_IOC_MAGIC, 39)
+
+
+/*****************************************/
+
+#endif
+
diff --git a/drivers/media/radio/si4709/radio-si4709_main.c b/drivers/media/radio/si4709/radio-si4709_main.c
new file mode 100644
index 0000000..a202b50
--- /dev/null
+++ b/drivers/media/radio/si4709/radio-si4709_main.c
@@ -0,0 +1,799 @@
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/miscdevice.h>
+#include <linux/interrupt.h>
+#include <asm/uaccess.h>
+#include <linux/irq.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <linux/wait.h>
+#include <linux/stat.h>
+#include <linux/ioctl.h>
+
+#include <plat/gpio-cfg.h>
+#include <mach/gpio.h>
+#include <../../../arch/arm/mach-s5pv210/include/mach/gpio-aries.h>
+
+#include "radio-si4709_i2c_drv.h"
+#include "radio-si4709_dev.h"
+#include "radio-si4709_ioctl.h"
+#include "radio-si4709_common.h"
+
+/*******************************************************/
+
+/*Si4709 IRQ Number*/
+
+#define FM_IRQ_INT (IRQ_EINT_GROUP20_BASE+4) /* J2_4 */
+
+/*static functions*/
+
+/*file operatons*/
+static int Si4709_open (struct inode *, struct file *);
+static int Si4709_release (struct inode *, struct file *);
+static int Si4709_ioctl(struct file *, unsigned int, unsigned long);
+
+static DEFINE_MUTEX(Si4709_mutex);
+
+/*ISR*/
+static irqreturn_t Si4709_isr( int irq, void *unused );
+//static void __iomem *gpio_mask_mem;
+/**********************************************************/
+
+static struct file_operations Si4709_fops =
+{
+ .owner = THIS_MODULE,
+ .open = Si4709_open,
+ .unlocked_ioctl = Si4709_ioctl,
+ .release = Si4709_release,
+};
+
+static struct miscdevice Si4709_misc_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "radio0",
+ .fops = &Si4709_fops,
+};
+/*VNVS:START 13-OCT'09----dummy struct which is used as a cookie for FM Radio interrupt */
+typedef struct
+{
+ int i;
+ int j;
+} radio0;
+radio0 radio0_1;
+/*VNVS:END*/
+
+wait_queue_head_t Si4709_waitq;
+
+/***************************************************************/
+
+static int Si4709_open (struct inode *inode, struct file *filp)
+{
+ debug("Si4709_open called");
+
+ return nonseekable_open(inode, filp);
+}
+
+static int Si4709_release (struct inode *inode, struct file *filp)
+{
+ debug("Si4709_release called");
+
+ return 0;
+}
+
+static int Si4709_ioctl(struct file *filp, unsigned int ioctl_cmd, unsigned long arg)
+{
+ int ret = 0;
+ void __user *argp = (void __user *)arg;
+
+ mutex_lock(&Si4709_mutex);
+
+ if( _IOC_TYPE(ioctl_cmd) != Si4709_IOC_MAGIC )
+ {
+ debug("Inappropriate ioctl 1 0x%x",ioctl_cmd);
+ ret = -ENOTTY;
+ goto exit;
+ }
+
+ if( _IOC_NR(ioctl_cmd) > Si4709_IOC_NR_MAX )
+ {
+ debug("Inappropriate ioctl 2 0x%x",ioctl_cmd);
+ ret = -ENOTTY;
+ goto exit;
+ }
+
+ switch (ioctl_cmd)
+ {
+ case Si4709_IOC_POWERUP:
+ debug("Si4709_IOC_POWERUP called");
+
+ if( (ret = Si4709_dev_powerup()) < 0 )
+ debug("Si4709_IOC_POWERUP failed");
+ break;
+
+ case Si4709_IOC_POWERDOWN:
+ debug("Si4709_IOC_POWERDOWN called");
+
+ if( (ret = Si4709_dev_powerdown()) < 0 )
+ debug("Si4709_IOC_POWERDOWN failed");
+ break;
+
+ case Si4709_IOC_BAND_SET:
+ {
+ int band;
+ debug("Si4709_IOC_BAND_SET called");
+
+ if(copy_from_user((void*) &band, argp, sizeof(int)))
+ ret = -EFAULT;
+ else if( (ret = Si4709_dev_band_set(band)) < 0)
+ debug("Si4709_IOC_BAND_SET failed");
+
+ }
+ break;
+
+ case Si4709_IOC_CHAN_SPACING_SET:
+ {
+ int ch_spacing;
+ debug("Si4709_IOC_CHAN_SPACING_SET called");
+
+ if( copy_from_user((void*) &ch_spacing, argp, sizeof(int)) )
+ ret = -EFAULT;
+ else if ((ret = Si4709_dev_ch_spacing_set(ch_spacing)) < 0)
+ debug("Si4709_IOC_CHAN_SPACING_SET failed");
+
+ }
+ break;
+
+ case Si4709_IOC_CHAN_SELECT:
+ {
+ u32 frequency;
+ debug("Si4709_IOC_CHAN_SELECT called");
+
+ if( copy_from_user((void*) &frequency, argp, sizeof(u32)) )
+ ret = -EFAULT;
+ else if ( (ret = Si4709_dev_chan_select(frequency)) < 0 )
+ debug("Si4709_IOC_CHAN_SELECT failed");
+ }
+ break;
+
+ case Si4709_IOC_CHAN_GET:
+ {
+ u32 frequency;
+ debug("Si4709_IOC_CHAN_GET called");
+
+ if( (ret = Si4709_dev_chan_get(&frequency)) < 0)
+ debug("Si4709_IOC_CHAN_GET failed");
+ else if( copy_to_user(argp, (void*) &frequency, sizeof(u32)))
+ ret = -EFAULT;
+ }
+ break;
+
+ case Si4709_IOC_SEEK_UP:
+ {
+ u32 frequency;
+ debug("Si4709_IOC_SEEK_UP called");
+
+ if( (ret = Si4709_dev_seek_up(&frequency)) < 0)
+ debug("Si4709_IOC_SEEK_UP failed");
+ else if( copy_to_user(argp, (void*) &frequency, sizeof(u32)) )
+ ret = -EFAULT;
+ }
+ break;
+
+ case Si4709_IOC_SEEK_DOWN:
+ {
+ u32 frequency;
+ debug("Si4709_IOC_SEEK_DOWN called");
+
+ if( (ret = Si4709_dev_seek_down(&frequency)) < 0)
+ debug("Si4709_IOC_SEEK_DOWN failed");
+ else if( copy_to_user(argp, (void*) &frequency, sizeof(u32)) )
+ ret = -EFAULT;
+ }
+ break;
+
+#if 0
+ case Si4709_IOC_SEEK_AUTO:
+ {
+ u32 *seek_preset_user;
+ int i = 0;
+
+ debug("Si4709_IOC_SEEK_AUTO called");
+
+ if( (seek_preset_user = (u32 *)kzalloc(sizeof(u32) * NUM_SEEK_PRESETS,
+ GFP_KERNEL)) == NULL )
+ {
+ debug("Si4709_ioctl: no memory");
+ ret = -ENOMEM;
+ }
+ else
+ {
+ if((ret = Si4709_dev_seek_auto(seek_preset_user)) < 0)
+ {
+ debug("Si4709_IOC_SEEK_AUTO failed");
+ }
+
+ else if ( copy_to_user(argp, (u32*) seek_preset_user, sizeof(int) * NUM_SEEK_PRESETS) )
+ {
+ ret = -EFAULT;
+ }
+
+ kfree(seek_preset_user);
+ }
+ }
+ break;
+#endif
+
+ case Si4709_IOC_RSSI_SEEK_TH_SET:
+ {
+ u8 RSSI_seek_th;
+ debug("Si4709_IOC_RSSI_SEEK_TH_SET called");
+
+ if( copy_from_user((void*) &RSSI_seek_th, argp, sizeof(u8)) )
+ ret = -EFAULT;
+ else if ( (ret = Si4709_dev_RSSI_seek_th_set(RSSI_seek_th)) < 0 )
+ debug("Si4709_IOC_RSSI_SEEK_TH_SET failed");
+ }
+ break;
+
+ case Si4709_IOC_SEEK_SNR_SET:
+ {
+ u8 seek_SNR_th;
+ debug("Si4709_IOC_SEEK_SNR_SET called");
+
+ if( copy_from_user((void*) &seek_SNR_th, argp, sizeof(u8)) )
+ ret = -EFAULT;
+ else if( (ret = Si4709_dev_seek_SNR_th_set(seek_SNR_th)) < 0 )
+ debug("Si4709_IOC_SEEK_SNR_SET failed");
+ }
+ break;
+
+ case Si4709_IOC_SEEK_CNT_SET:
+ {
+ u8 seek_FM_ID_th;
+ debug("Si4709_IOC_SEEK_CNT_SET called");
+
+ if( copy_from_user((void*) &seek_FM_ID_th, argp, sizeof(u8)) )
+ ret = -EFAULT;
+ else if ( (ret = Si4709_dev_seek_FM_ID_th_set(seek_FM_ID_th)) < 0 )
+ debug("Si4709_IOC_SEEK_CNT_SET failed");
+ }
+ break;
+
+ case Si4709_IOC_CUR_RSSI_GET:
+ {
+ rssi_snr_t data;
+ debug("Si4709_IOC_CUR_RSSI_GET called");
+
+ if( (ret = Si4709_dev_cur_RSSI_get(&data)) < 0)
+ debug("Si4709_IOC_CUR_RSSI_GET failed");
+ else if( copy_to_user(argp, (void*) &data, sizeof(rssi_snr_t )) )
+ ret = -EFAULT;
+
+ debug("curr_rssi:%d\ncurr_rssi_th:%d\ncurr_snr:%d\n",data.curr_rssi,data.curr_rssi_th,data.curr_snr);
+ }
+ break;
+
+ case Si4709_IOC_VOLEXT_ENB:
+ debug("Si4709_IOC_VOLEXT_ENB called");
+
+ if( (ret = Si4709_dev_VOLEXT_ENB()) < 0 )
+ debug("Si4709_IOC_VOLEXT_ENB failed");
+ break;
+
+ case Si4709_IOC_VOLEXT_DISB:
+ debug("Si4709_IOC_VOLEXT_DISB called");
+
+ if( (ret = Si4709_dev_VOLEXT_DISB()) < 0 )
+ debug("Si4709_IOC_VOLEXT_DISB failed");
+ break;
+
+ case Si4709_IOC_VOLUME_SET:
+ {
+ u8 volume;
+ debug("Si4709_IOC_VOLUME_SET called");
+
+ if( copy_from_user((void*) &volume, argp, sizeof(u8)) )
+ ret = -EFAULT;
+ else if ( (ret = Si4709_dev_volume_set(volume)) < 0 )
+ debug("Si4709_IOC_VOLUME_SET failed");
+ }
+ break;
+
+ case Si4709_IOC_VOLUME_GET:
+ {
+ u8 volume;
+ debug("Si4709_IOC_VOLUME_GET called");
+
+ if( (ret = Si4709_dev_volume_get(&volume)) < 0)
+ debug("Si4709_IOC_VOLUME_GET failed");
+ else if( copy_to_user(argp, (void*) &volume, sizeof(u8)) )
+ ret = -EFAULT;
+ }
+ break;
+
+ case Si4709_IOC_DSMUTE_ON:
+ debug("Si4709_IOC_DSMUTE_ON called");
+
+ if( (ret = Si4709_dev_DSMUTE_ON()) < 0 )
+ error("Si4709_IOC_DSMUTE_ON failed");
+ break;
+
+ case Si4709_IOC_DSMUTE_OFF:
+ debug("Si4709_IOC_DSMUTE_OFF called");
+
+ if( (ret = Si4709_dev_DSMUTE_OFF()) < 0 )
+ error("Si4709_IOC_DSMUTE_OFF failed");
+ break;
+
+ case Si4709_IOC_MUTE_ON:
+ debug("Si4709_IOC_MUTE_ON called");
+
+ if( (ret = Si4709_dev_MUTE_ON()) < 0 )
+ debug("Si4709_IOC_MUTE_ON failed");
+ break;
+
+ case Si4709_IOC_MUTE_OFF:
+ debug("Si4709_IOC_MUTE_OFF called");
+
+ if( (ret = Si4709_dev_MUTE_OFF()) < 0 )
+ debug("Si4709_IOC_MUTE_OFF failed");
+ break;
+
+ case Si4709_IOC_MONO_SET:
+ debug("Si4709_IOC_MONO_SET called");
+
+ if( (ret = Si4709_dev_MONO_SET()) < 0 )
+ debug("Si4709_IOC_MONO_SET failed");
+ break;
+
+ case Si4709_IOC_STEREO_SET:
+ debug("Si4709_IOC_STEREO_SET called");
+
+ if( (ret = Si4709_dev_STEREO_SET()) < 0 )
+ debug("Si4709_IOC_STEREO_SET failed");
+ break;
+
+ case Si4709_IOC_RSTATE_GET:
+ {
+ dev_state_t dev_state;
+
+ debug("Si4709_IOC_RSTATE_GET called");
+
+ if( (ret = Si4709_dev_rstate_get(&dev_state)) < 0)
+ debug("Si4709_IOC_RSTATE_GET failed");
+ else if( copy_to_user(argp, (void*) &dev_state, sizeof(dev_state_t)) )
+ ret = -EFAULT;
+ }
+ break;
+
+ case Si4709_IOC_RDS_DATA_GET:
+ {
+ radio_data_t data;
+ debug("Si4709_IOC_RDS_DATA_GET called");
+
+ if( (ret = Si4709_dev_RDS_data_get(&data)) < 0)
+ debug("Si4709_IOC_RDS_DATA_GET failed");
+ else if( copy_to_user(argp, (void*) &data, sizeof(radio_data_t)) )
+ ret = -EFAULT;
+ }
+ break;
+
+ case Si4709_IOC_RDS_ENABLE:
+ debug("Si4709_IOC_RDS_ENABLE called");
+
+ if( (ret = Si4709_dev_RDS_ENABLE()) < 0 )
+ debug("Si4709_IOC_RDS_ENABLE failed");
+ break;
+
+ case Si4709_IOC_RDS_DISABLE:
+ debug("Si4709_IOC_RDS_DISABLE called");
+
+ if( (ret = Si4709_dev_RDS_DISABLE()) < 0 )
+ debug("Si4709_IOC_RDS_DISABLE failed");
+ break;
+
+ case Si4709_IOC_RDS_TIMEOUT_SET:
+ {
+ u32 time_out;
+ debug("Si4709_IOC_RDS_TIMEOUT_SET called");
+
+ if( copy_from_user((void*) &time_out, argp, sizeof(u32)) )
+ ret = -EFAULT;
+ else if ( (ret = Si4709_dev_RDS_timeout_set(time_out)) < 0 )
+ debug("Si4709_IOC_RDS_TIMEOUT_SET failed");
+ }
+ break;
+
+ case Si4709_IOC_SEEK_CANCEL:
+ debug("Si4709_IOC_SEEK_CANCEL called");
+
+ if( Si4709_dev_wait_flag == SEEK_WAITING )
+ {
+ Si4709_dev_wait_flag = SEEK_CANCEL;
+ wake_up_interruptible(&Si4709_waitq);
+ }
+ break;
+
+ /*VNVS:START 13-OCT'09---- Switch Case statements for calling functions which reads device-id,
+ chip-id,power configuration, system configuration2 registers */
+ case Si4709_IOC_CHIP_ID_GET:
+ {
+ chip_id chp_id;
+ debug("Si4709_IOC_CHIP_ID called");
+
+ if( (ret = Si4709_dev_chip_id(&chp_id)) < 0)
+ debug("Si4709_IOC_CHIP_ID failed");
+ else if( copy_to_user(argp, (void*) &chp_id, sizeof(chip_id)) )
+ ret = -EFAULT;
+ }
+ break;
+
+ case Si4709_IOC_DEVICE_ID_GET:
+ {
+ device_id dev_id;
+ debug("Si4709_IOC_DEVICE_ID called");
+
+ if( (ret = Si4709_dev_device_id(&dev_id)) < 0)
+ debug("Si4709_IOC_DEVICE_ID failed");
+ else if( copy_to_user(argp, (void*) &dev_id, sizeof(device_id)) )
+ ret = -EFAULT;
+ }
+ break;
+
+ case Si4709_IOC_SYS_CONFIG2_GET:
+ {
+ sys_config2 sys_conf2;
+ debug("Si4709_IOC_SYS_CONFIG2 called");
+
+ if( (ret = Si4709_dev_sys_config2(&sys_conf2)) < 0)
+ debug("Si4709_IOC_SYS_CONFIG2 failed");
+ else if( copy_to_user(argp, (void*) &sys_conf2, sizeof(sys_config2)) )
+ ret = -EFAULT;
+ }
+ break;
+
+ case Si4709_IOC_SYS_CONFIG3_GET:
+ {
+ sys_config3 sys_conf3;
+ debug("Si4709_IOC_SYS_CONFIG3 called");
+
+ if( (ret = Si4709_dev_sys_config3(&sys_conf3)) < 0)
+ debug("Si4709_IOC_SYS_CONFIG3 failed");
+ else if(copy_to_user(argp, (void*) &sys_conf3, sizeof(sys_config3)))
+ ret = -EFAULT;
+ }
+ break;
+
+ case Si4709_IOC_POWER_CONFIG_GET:
+ {
+ power_config pow_conf;
+ debug("Si4709_IOC_POWER_CONFIG called");
+
+ if( (ret = Si4709_dev_power_config(&pow_conf)) < 0)
+ debug("Si4709_IOC_POWER_CONFIG failed");
+ else if( copy_to_user(argp, (void*) &pow_conf, sizeof(power_config)) )
+ ret = -EFAULT;
+ }
+ break;
+ /*VNVS:END*/
+ /*VNVS:START 18-NOV'09*/
+ /*Reading AFCRL Bit*/
+ case Si4709_IOC_AFCRL_GET:
+ {
+ u8 afc;
+ debug("Si4709_IOC_AFCRL_GET called");
+
+ if( (ret = Si4709_dev_AFCRL_get(&afc)) < 0)
+ debug("Si4709_IOC_AFCRL_GET failed");
+ else if( copy_to_user(argp, (void*) &afc, sizeof(u8)) )
+ ret = -EFAULT;
+ }
+ break;
+ /*Setting DE-emphasis Time Constant. For DE=0,TC=50us(Europe,Japan,Australia) and DE=1,TC=75us(USA)*/
+ case Si4709_IOC_DE_SET:
+ {
+ u8 de_tc;
+ debug("Si4709_IOC_DE_SET called");
+
+ if( copy_from_user((void*) &de_tc, argp, sizeof(u8)) )
+ ret = -EFAULT;
+ else if ( (ret = Si4709_dev_DE_set(de_tc)) < 0 )
+ debug("Si4709_IOC_DE_SET failed");
+ }
+ break;
+
+ case Si4709_IOC_STATUS_RSSI_GET:
+ {
+ status_rssi status;
+ debug("Si4709_IOC_STATUS_RSSI_GET called");
+
+ if( (ret = Si4709_dev_status_rssi(&status)) < 0)
+ debug("Si4709_IOC_STATUS_RSSI_GET failed");
+ else if(copy_to_user(argp, (void*) &status, sizeof(status_rssi)))
+ ret = -EFAULT;
+ }
+ break;
+
+
+ case Si4709_IOC_SYS_CONFIG2_SET:
+ {
+ sys_config2 sys_conf2;
+ unsigned long n;
+ debug("Si4709_IOC_SYS_CONFIG2_SET called");
+
+ n = copy_from_user((void*) &sys_conf2, argp, sizeof(sys_config2));
+
+ if(n)
+ {
+ debug("Si4709_IOC_SYS_CONFIG2_SET() : copy_from_user() has error!!Failed to read [%d] byes!", n);
+ ret = -EFAULT;
+ }
+ else if ( (ret = Si4709_dev_sys_config2_set(&sys_conf2)) < 0 )
+ debug("Si4709_IOC_SYS_CONFIG2_SET failed");
+ }
+ break;
+
+ case Si4709_IOC_SYS_CONFIG3_SET:
+ {
+ sys_config3 sys_conf3;
+ unsigned long n;
+
+ debug("Si4709_IOC_SYS_CONFIG3_SET called");
+
+ n = copy_from_user((void*) &sys_conf3, argp, sizeof(sys_config3));
+
+ if(n < 0)
+ {
+ debug("Si4709_IOC_SYS_CONFIG3_SET() : copy_from_user() has error!!Failed to read [%d] byes!", n);
+ ret = -EFAULT;
+ }else if ( (ret = Si4709_dev_sys_config3_set(&sys_conf3)) < 0 )
+ debug("Si4709_IOC_SYS_CONFIG3_SET failed");
+ }
+ break;
+ /*Resetting the RDS Data Buffer*/
+ case Si4709_IOC_RESET_RDS_DATA:
+ {
+ debug("Si4709_IOC_RESET_RDS_DATA called");
+
+ if( (ret = Si4709_dev_reset_rds_data()) < 0)
+ error("Si4709_IOC_RESET_RDS_DATA failed");
+ }
+ break;
+
+ /*VNVS:END*/
+ default:
+ debug(" ioctl default");
+ ret = -ENOTTY;
+ break;
+ }
+
+exit:
+ mutex_unlock(&Si4709_mutex);
+ return ret;
+}
+
+static irqreturn_t Si4709_isr( int irq, void *unused )
+{
+ debug("Si4709_isr: FM device called IRQ: %d",irq);
+#ifdef RDS_INTERRUPT_ON_ALWAYS
+ if( (Si4709_dev_wait_flag == SEEK_WAITING) || (Si4709_dev_wait_flag == TUNE_WAITING))
+ {
+ debug("Si4709_isr: FM Seek/Tune Interrupt called IRQ %d",irq);
+ Si4709_dev_wait_flag = WAIT_OVER;
+ wake_up_interruptible(&Si4709_waitq);
+ }
+ else if(Si4709_RDS_flag == RDS_WAITING) //RDS Interrupt
+ {
+ debug_rds("Si4709_isr: FM RDS Interrupt called IRQ %d",irq);
+ RDS_Data_Available++;
+ RDS_Groups_Available_till_now++;
+
+ debug_rds("RDS_Groups_Available_till_now b/w Power ON/OFF : %d",RDS_Groups_Available_till_now);
+
+ if (RDS_Data_Available > 1)
+ RDS_Data_Lost++;
+
+ if(!work_pending(&Si4709_work))
+ queue_work(Si4709_wq,&Si4709_work);
+ }
+#else
+ if( (Si4709_dev_wait_flag == SEEK_WAITING) || (Si4709_dev_wait_flag == TUNE_WAITING) ||(Si4709_dev_wait_flag == RDS_WAITING))
+ {
+ Si4709_dev_wait_flag = WAIT_OVER;
+ wake_up_interruptible(&Si4709_waitq);
+ }
+#endif
+ return IRQ_HANDLED;
+}
+
+#if 0
+int Si4709_dev_abort_seek(void)
+{
+ int ret = 0;
+
+ if( Si4709_dev_wait_flag = SEEK_WAITING )
+ {
+ wake_up_interruptible(&Si4709_waitq);
+ }
+ return ret;
+}
+#endif
+
+
+/************************************************************/
+
+
+void debug_ioctls(void)
+{
+
+ debug("------------------------------------------------");
+
+ debug("Si4709_IOC_POWERUP 0x%x",Si4709_IOC_POWERUP );
+
+ debug("Si4709_IOC_POWERDOWN 0x%x",Si4709_IOC_POWERDOWN );
+
+ debug("Si4709_IOC_BAND_SET 0x%x",Si4709_IOC_BAND_SET );
+
+ debug("Si4709_IOC_CHAN_SPACING_SET 0x%x",Si4709_IOC_CHAN_SPACING_SET );
+
+ debug("Si4709_IOC_CHAN_SELECT 0x%x",Si4709_IOC_CHAN_SELECT );
+
+ debug("Si4709_IOC_CHAN_GET 0x%x",Si4709_IOC_CHAN_GET );
+
+ debug("Si4709_IOC_SEEK_UP 0x%x",Si4709_IOC_SEEK_UP );
+
+ debug("Si4709_IOC_SEEK_DOWN 0x%x",Si4709_IOC_SEEK_DOWN );
+
+ /*VNVS:28OCT'09---- Si4709_IOC_SEEK_AUTO is disabled as of now*/
+ // debug("Si4709_IOC_SEEK_AUTO 0x%x",Si4709_IOC_SEEK_AUTO );
+
+ debug("Si4709_IOC_RSSI_SEEK_TH_SET 0x%x",Si4709_IOC_RSSI_SEEK_TH_SET );
+
+ debug("Si4709_IOC_SEEK_SNR_SET 0x%x",Si4709_IOC_SEEK_SNR_SET );
+
+ debug("Si4709_IOC_SEEK_CNT_SET 0x%x",Si4709_IOC_SEEK_CNT_SET );
+
+ debug("Si4709_IOC_CUR_RSSI_GET 0x%x",Si4709_IOC_CUR_RSSI_GET );
+
+ debug("Si4709_IOC_VOLEXT_ENB 0x%x",Si4709_IOC_VOLEXT_ENB );
+
+ debug("Si4709_IOC_VOLEXT_DISB 0x%x",Si4709_IOC_VOLEXT_DISB );
+
+ debug("Si4709_IOC_VOLUME_SET 0x%x",Si4709_IOC_VOLUME_SET );
+
+ debug("Si4709_IOC_VOLUME_GET 0x%x",Si4709_IOC_VOLUME_GET );
+
+ debug("Si4709_IOC_MUTE_ON 0x%x",Si4709_IOC_MUTE_ON );
+
+ debug("Si4709_IOC_MUTE_OFF 0x%x",Si4709_IOC_MUTE_OFF );
+
+ debug("Si4709_IOC_MONO_SET 0x%x",Si4709_IOC_MONO_SET );
+
+ debug("Si4709_IOC_STEREO_SET 0x%x",Si4709_IOC_STEREO_SET );
+
+ debug("Si4709_IOC_RSTATE_GET 0x%x",Si4709_IOC_RSTATE_GET );
+
+ debug("Si4709_IOC_RDS_DATA_GET 0x%x",Si4709_IOC_RDS_DATA_GET );
+
+ debug("Si4709_IOC_RDS_ENABLE 0x%x",Si4709_IOC_RDS_ENABLE);
+
+ debug("Si4709_IOC_RDS_DISABLE 0x%x",Si4709_IOC_RDS_DISABLE);
+
+ debug("Si4709_IOC_RDS_TIMEOUT_SET 0x%x",Si4709_IOC_RDS_TIMEOUT_SET);
+
+ debug("Si4709_IOC_DEVICE_ID_GET 0x%x",Si4709_IOC_DEVICE_ID_GET);
+
+ debug("Si4709_IOC_CHIP_ID_GET 0x%x",Si4709_IOC_CHIP_ID_GET);
+
+ debug("Si4709_IOC_SYS_CONFIG2_GET 0x%x",Si4709_IOC_SYS_CONFIG2_GET);
+
+ debug("Si4709_IOC_POWER_CONFIG_GET 0x%x",Si4709_IOC_POWER_CONFIG_GET);
+
+ debug("Si4709_IOC_AFCRL_GET 0x%x",Si4709_IOC_AFCRL_GET);
+
+ debug("Si4709_IOC_DE_SET 0x%x",Si4709_IOC_DE_SET);
+
+ debug("Si4709_IOC_DSMUTE_ON 0x%x",Si4709_IOC_DSMUTE_ON);
+
+ debug("Si4709_IOC_DSMUTE_OFF 0x%x",Si4709_IOC_DSMUTE_OFF);
+
+ debug("Si4709_IOC_RESET_RDS_DATA 0x%x",Si4709_IOC_RESET_RDS_DATA);
+
+ debug("------------------------------------------------");
+
+}
+
+
+
+
+ int __init Si4709_driver_init(void)
+{
+ int ret = 0;
+
+
+ debug("Si4709_driver_init called");
+
+ /*Initialize the Si4709 dev mutex*/
+ Si4709_dev_mutex_init();
+
+
+ /*misc device registration*/
+ if( (ret = misc_register(&Si4709_misc_device)) < 0 )
+ {
+ error("Si4709_driver_init misc_register failed");
+ return ret;
+ }
+
+ s3c_gpio_cfgpin(GPIO_FM_INT, S3C_GPIO_SFN(0xF));
+ s3c_gpio_setpull(GPIO_FM_INT, S3C_GPIO_PULL_NONE);
+
+ irq_set_irq_type(FM_IRQ_INT, IRQ_TYPE_EDGE_FALLING);
+
+ /*KGVS: Configuring the GPIO_FM_INT in mach-jupiter.c*/
+ if( (ret = request_irq(FM_IRQ_INT, Si4709_isr, IRQF_DISABLED , "Si4709", NULL )) )
+ {
+ error("Si4709_driver_init request_irq failed %d", GPIO_FM_INT);
+ goto MISC_DREG;
+ }
+ else
+ debug("Si4709_driver_init request_irq success %d", GPIO_FM_INT);
+
+ if (gpio_is_valid(FM_RESET)) {
+ if (gpio_request(FM_RESET, "GPJ2"))
+ printk(KERN_ERR "Failed to request FM_RESET!\n");
+ gpio_direction_output(FM_RESET, GPIO_LEVEL_LOW);
+ }
+
+ /*VNVS: 13-OCT'09---- Initially Pulling the interrupt pin HIGH as the FM Radio device gives 5ms low pulse*/
+ s3c_gpio_setpull(GPIO_FM_INT, S3C_GPIO_PULL_UP);
+
+ /****Resetting the device****/
+ gpio_set_value(FM_RESET, GPIO_LEVEL_LOW);
+ gpio_set_value(FM_RESET, GPIO_LEVEL_HIGH);
+ /*VNVS: 13-OCT'09---- Freeing the FM_RESET pin*/
+ gpio_free(FM_RESET);
+
+ /*Add the i2c driver*/
+ if ( (ret = Si4709_i2c_drv_init() < 0) )
+ {
+ goto MISC_IRQ_DREG;
+ }
+
+ init_waitqueue_head(&Si4709_waitq);
+
+ debug("Si4709_driver_init successful");
+
+ return ret;
+
+MISC_IRQ_DREG:
+ free_irq(FM_IRQ_INT, NULL);
+MISC_DREG:
+ misc_deregister(&Si4709_misc_device);
+
+ return ret;
+}
+
+
+void __exit Si4709_driver_exit(void)
+{
+ debug("Si4709_driver_exit called");
+
+ /*Delete the i2c driver*/
+ Si4709_i2c_drv_exit();
+ free_irq(FM_IRQ_INT, NULL);
+
+ /*misc device deregistration*/
+ misc_deregister(&Si4709_misc_device);
+}
+
+module_init(Si4709_driver_init);
+module_exit(Si4709_driver_exit);
+MODULE_AUTHOR("Varun Mahajan <m.varun@samsung.com>");
+MODULE_DESCRIPTION("Si4709 FM tuner driver");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/media/radio/si4709/radio-si4709_main.h b/drivers/media/radio/si4709/radio-si4709_main.h
new file mode 100644
index 0000000..adf98e1
--- /dev/null
+++ b/drivers/media/radio/si4709/radio-si4709_main.h
@@ -0,0 +1,9 @@
+#ifndef _Si4709_MAIN_H
+#define _Si4709_MAIN_H
+
+#include <linux/wait.h>
+
+extern wait_queue_head_t Si4709_waitq;
+
+#endif
+
diff --git a/drivers/media/radio/si4709/radio-si4709_regs.h b/drivers/media/radio/si4709/radio-si4709_regs.h
new file mode 100644
index 0000000..599d009
--- /dev/null
+++ b/drivers/media/radio/si4709/radio-si4709_regs.h
@@ -0,0 +1,859 @@
+#ifndef _Si4709_REGS_H
+#define _Si4709_REGS_H
+
+#define NUM_OF_REGISTERS 0x10
+
+/*Si4709 registers*/
+#define DEVICE_ID 0x00
+#define CHIP_ID 0x01
+#define POWERCFG 0x02
+#define CHANNEL 0x03
+#define SYSCONFIG1 0x04
+#define SYSCONFIG2 0x05
+#define SYSCONFIG3 0x06
+#define TEST1 0x07
+#define TEST2 0x08
+#define BOOTCONFIG 0x09
+#define STATUSRSSI 0x0A
+#define READCHAN 0x0B
+#define RDSA 0x0C
+#define RDSB 0x0D
+#define RDSC 0x0E
+#define RDSD 0x0F
+
+/***********POWERCFG************/
+#define POWERCFG_DSMUTE 0x8000
+#define POWERCFG_DMUTE 0x4000
+#define POWERCFG_MONO 0x2000
+#define POWERCFG_RDSM 0x0800
+#define POWERCFG_SKMODE 0x0400
+#define POWERCFG_SEEKUP 0x0200
+#define POWERCFG_SEEK 0x0100
+#define POWERCFG_DISABLE 0x0040
+#define POWERCFG_ENABLE 0x0001
+/************************************/
+
+/***********CHANNEL************/
+#define CHANNEL_TUNE 0x8000
+/************************************/
+
+/***********SYSCONFIG1************/
+#define SYSCONFIG1_RDSIEN 0x8000
+#define SYSCONFIG1_STCIEN 0x4000
+#define SYSCONFIG1_RDS 0x1000
+#define SYSCONFIG1_DE 0x0800
+#define SYSCONFIG1_AGCD 0x0400
+#define SYSCONFIG1_BLNDADJ1 0x0080
+#define SYSCONFIG1_BLNDADJ0 0x0040
+#define SYSCONFIG1_GPO1 0x0008
+#define SYSCONFIG1_GPO0 0x0004
+/************************************/
+
+/***********SYSCONFIG2************/
+#define SYSCONFIG2_BAND1 0x0080
+#define SYSCONFIG2_BAND0 0x0040
+#define SYSCONFIG2_SPACE1 0x0020
+#define SYSCONFIG2_SPACE0 0x0010
+#define SYSCONFIG2_VOLUME3 0x0008
+#define SYSCONFIG2_VOLUME2 0x0004
+#define SYSCONFIG2_VOLUME1 0x0002
+#define SYSCONFIG2_VOLUME0 0x0001
+/************************************/
+
+/***********SYSCONFIG3************/
+#define SYSCONFIG3_SMUTER1 0x8000
+#define SYSCONFIG3_SMUTER0 0x4000
+#define SYSCONFIG3_SMUTEA1 0x2000
+#define SYSCONFIG3_SMUTEA0 0x1000
+#define SYSCONFIG3_VOLEXT 0x0100
+#define SYSCONFIG3_SKSNR3 0x0080
+#define SYSCONFIG3_SKSNR2 0x0040
+#define SYSCONFIG3_SKSNR1 0x0020
+#define SYSCONFIG3_SKSNR0 0x0010
+#define SYSCONFIG3_SKCNT3 0x0008
+#define SYSCONFIG3_SKCNT2 0x0004
+#define SYSCONFIG3_SKCNT1 0x0002
+#define SYSCONFIG3_SKCNT0 0x0001
+/************************************/
+
+/***********TEST1************/
+#define TEST1_AHIZEN 0x4000
+/************************************/
+
+/***********STATUSRSSI************/
+#define STATUSRSSI_RDSR 0x8000
+#define STATUSRSSI_STC 0x4000
+#define STATUSRSSI_SF_BL 0x2000
+#define STATUSRSSI_AFCRL 0x1000
+#define STATUSRSSI_RDSS 0x0800
+#define STATUSRSSI_BLERA1 0x0400
+#define STATUSRSSI_BLERA0 0x0200
+#define STATUSRSSI_ST 0x0100
+/************************************/
+
+/***********READCHAN************/
+#define READCHAN_BLERB1 0x8000
+#define READCHAN_BLERB0 0x4000
+#define READCHAN_BLERC1 0x2000
+#define READCHAN_BLERC0 0x1000
+#define READCHAN_BLERD1 0x0800
+#define READCHAN_BLERD0 0x0400
+
+#define READCHAN_CHAN_MASK 0x03FF
+/************************************/
+
+/*************************************************************/
+static inline void switch_on_bits(u16 *data, u16 bits_on)
+{
+ *data |= bits_on;
+}
+
+static inline void switch_off_bits(u16 *data, u16 bits_off)
+{
+ u16 aux = 0xFFFF;
+ aux ^= bits_off;
+ *data &= aux;
+}
+
+#define BIT_ON 1
+#define BIT_OFF 0
+
+static inline int check_bit(u16 data, u16 bit)
+{
+ return (data&bit) ? BIT_ON : BIT_OFF;
+}
+/**************************************************************/
+
+
+/********************************************************************/
+static inline void POWERCFG_BITSET_ENABLE_HIGH(u16 *data)
+{
+ switch_on_bits(data, (POWERCFG_ENABLE));
+}
+
+static inline void POWERCFG_BITSET_DISABLE_HIGH(u16 *data)
+{
+ switch_on_bits(data, (POWERCFG_DISABLE));
+}
+
+static inline void POWERCFG_BITSET_DISABLE_LOW(u16 *data)
+{
+ switch_off_bits(data, (POWERCFG_DISABLE));
+}
+
+static inline void POWERCFG_BITSET_DMUTE_HIGH(u16 *data)
+{
+ switch_on_bits(data, (POWERCFG_DMUTE));
+}
+
+static inline void POWERCFG_BITSET_DMUTE_LOW(u16 *data)
+{
+ switch_off_bits(data, (POWERCFG_DMUTE));
+}
+
+static inline void POWERCFG_BITSET_DSMUTE_HIGH(u16 *data)
+{
+ switch_on_bits(data, (POWERCFG_DSMUTE));
+}
+
+static inline void POWERCFG_BITSET_DSMUTE_LOW(u16 *data)
+{
+ switch_off_bits(data, (POWERCFG_DSMUTE));
+}
+
+static inline void POWERCFG_BITSET_MONO_HIGH(u16 *data)
+{
+ switch_on_bits(data, (POWERCFG_MONO));
+}
+
+static inline void POWERCFG_BITSET_MONO_LOW(u16 *data)
+{
+ switch_off_bits(data, (POWERCFG_MONO));
+}
+
+static inline void POWERCFG_BITSET_RDSM_HIGH(u16 *data)
+{
+ switch_on_bits(data, (POWERCFG_RDSM));
+}
+
+static inline void POWERCFG_BITSET_RDSM_LOW(u16 *data)
+{
+ switch_off_bits(data, (POWERCFG_RDSM));
+}
+
+static inline void POWERCFG_BITSET_SKMODE_HIGH(u16 *data)
+{
+ switch_on_bits(data, (POWERCFG_SKMODE));
+}
+
+static inline void POWERCFG_BITSET_SKMODE_LOW(u16 *data)
+{
+ switch_off_bits(data, (POWERCFG_SKMODE));
+}
+
+static inline void POWERCFG_BITSET_SEEKUP_HIGH(u16 *data)
+{
+ switch_on_bits(data, (POWERCFG_SEEKUP));
+}
+
+static inline void POWERCFG_BITSET_SEEKUP_LOW(u16 *data)
+{
+ switch_off_bits(data, (POWERCFG_SEEKUP));
+}
+
+static inline void POWERCFG_BITSET_SEEK_HIGH(u16 *data)
+{
+ switch_on_bits(data, (POWERCFG_SEEK));
+}
+
+static inline void POWERCFG_BITSET_SEEK_LOW(u16 *data)
+{
+ switch_off_bits(data, (POWERCFG_SEEK));
+}
+
+static inline void POWERCFG_BITSET_RESERVED(u16 *data)
+{
+ *data &= 0xEF41;
+}
+
+/********************************************************************/
+
+static inline void CHANNEL_BITSET_TUNE_HIGH(u16 *data)
+{
+ switch_on_bits(data, (CHANNEL_TUNE));
+}
+
+static inline void CHANNEL_BITSET_TUNE_LOW(u16 *data)
+{
+ switch_off_bits(data, (CHANNEL_TUNE));
+}
+
+static inline void CHANNEL_BITSET_RESERVED(u16 *data)
+{
+ *data &= 0x83FF;
+}
+
+/********************************************************************/
+
+static inline void SYSCONFIG1_BITSET_RDSIEN_HIGH(u16 *data)
+{
+ switch_on_bits(data, (SYSCONFIG1_RDSIEN));
+}
+
+static inline void SYSCONFIG1_BITSET_RDSIEN_LOW(u16 *data)
+{
+ switch_off_bits(data, (SYSCONFIG1_RDSIEN));
+}
+
+static inline void SYSCONFIG1_BITSET_STCIEN_HIGH(u16 *data)
+{
+ switch_on_bits(data, (SYSCONFIG1_STCIEN));
+}
+
+static inline void SYSCONFIG1_BITSET_STCIEN_LOW(u16 *data)
+{
+ switch_off_bits(data, (SYSCONFIG1_STCIEN));
+}
+
+static inline void SYSCONFIG1_BITSET_RDS_HIGH(u16 *data)
+{
+ switch_on_bits(data, (SYSCONFIG1_RDS));
+}
+
+static inline void SYSCONFIG1_BITSET_RDS_LOW(u16 *data)
+{
+ switch_off_bits(data, (SYSCONFIG1_RDS));
+}
+
+static inline void SYSCONFIG1_BITSET_DE_50(u16 *data)
+{
+ switch_on_bits(data, (SYSCONFIG1_DE));
+}
+
+static inline void SYSCONFIG1_BITSET_DE_75(u16 *data)
+{
+ switch_off_bits(data, (SYSCONFIG1_DE));
+}
+
+static inline void SYSCONFIG1_BITSET_AGCD_HIGH(u16 *data)
+{
+ switch_on_bits(data, (SYSCONFIG1_AGCD));
+}
+
+static inline void SYSCONFIG1_BITSET_AGCD_LOW(u16 *data)
+{
+ switch_off_bits(data, (SYSCONFIG1_AGCD));
+}
+
+static inline void SYSCONFIG1_BITSET_RSSI_DEF_31_49(u16 *data)
+{
+ switch_off_bits(data, (SYSCONFIG1_BLNDADJ1|SYSCONFIG1_BLNDADJ0));
+}
+
+static inline void SYSCONFIG1_BITSET_RSSI_37_55(u16 *data)
+{
+ switch_on_bits(data, (SYSCONFIG1_BLNDADJ0));
+ switch_off_bits(data, (SYSCONFIG1_BLNDADJ1));
+}
+
+static inline void SYSCONFIG1_BITSET_RSSI_19_37(u16 *data)
+{
+ switch_on_bits(data, (SYSCONFIG1_BLNDADJ1));
+ switch_off_bits(data, (SYSCONFIG1_BLNDADJ0));
+}
+
+static inline void SYSCONFIG1_BITSET_RSSI_25_43(u16 *data)
+{
+ switch_on_bits(data, (SYSCONFIG1_BLNDADJ1|SYSCONFIG1_BLNDADJ0));
+}
+
+static inline void SYSCONFIG1_BITSET_GPIO_HIGH_IMP(u16 *data)
+{
+ switch_off_bits(data, (SYSCONFIG1_GPO1|SYSCONFIG1_GPO0));
+}
+
+static inline void SYSCONFIG1_BITSET_GPIO_STC_RDS_INT(u16 *data)
+{
+ switch_on_bits(data, (SYSCONFIG1_GPO0));
+ switch_off_bits(data, (SYSCONFIG1_GPO1));
+}
+
+static inline void SYSCONFIG1_BITSET_GPIO_LOW(u16 *data)
+{
+ switch_on_bits(data, (SYSCONFIG1_GPO1));
+ switch_off_bits(data, (SYSCONFIG1_GPO0));
+}
+
+static inline void SYSCONFIG1_BITSET_GPIO_HIGH(u16 *data)
+{
+ switch_on_bits(data, (SYSCONFIG1_GPO1|SYSCONFIG1_GPO0));
+}
+
+static inline void SYSCONFIG1_BITSET_RESERVED(u16 *data)
+{
+ *data &= 0xDCCC;
+ *data |= 0x22;
+}
+
+/********************************************************************/
+
+/*US/EUROPE (Default)*/
+static inline void SYSCONFIG2_BITSET_BAND_87p5_108_MHz(u16 *data)
+{
+ switch_off_bits(data, (SYSCONFIG2_BAND1|SYSCONFIG2_BAND0));
+}
+
+/*Japan wide band*/
+static inline void SYSCONFIG2_BITSET_BAND_76_108_MHz(u16 *data)
+{
+ switch_on_bits(data, (SYSCONFIG2_BAND0));
+ switch_off_bits(data, (SYSCONFIG2_BAND1));
+}
+
+/*Japan*/
+static inline void SYSCONFIG2_BITSET_BAND_76_90_MHz(u16 *data)
+{
+ switch_on_bits(data, (SYSCONFIG2_BAND1));
+ switch_off_bits(data, (SYSCONFIG2_BAND0));
+}
+
+/*US, Australia (Default)*/
+static inline void SYSCONFIG2_BITSET_SPACE_200_KHz(u16 *data)
+{
+ switch_off_bits(data, (SYSCONFIG2_SPACE1|SYSCONFIG2_SPACE0));
+}
+
+/*Europe, Japan*/
+static inline void SYSCONFIG2_BITSET_SPACE_100_KHz(u16 *data)
+{
+ switch_on_bits(data, (SYSCONFIG2_SPACE0));
+ switch_off_bits(data, (SYSCONFIG2_SPACE1));
+}
+
+static inline void SYSCONFIG2_BITSET_SPACE_50_KHz(u16 *data)
+{
+ switch_on_bits(data, (SYSCONFIG2_SPACE1));
+ switch_off_bits(data, (SYSCONFIG2_SPACE0));
+}
+
+static inline void SYSCONFIG2_BITSET_VOLUME(u16 *data, u8 volume)
+{
+ *data &= 0xFFF0;
+ *data |= (volume & 0x0F);
+}
+
+static inline void SYSCONFIG2_BITSET_SEEKTH(u16 *data, u8 seek_th)
+{
+ *data &= 0x00FF;
+ *data |= ((seek_th << 8) & 0xFF00);
+}
+
+static inline u8 SYSCONFIG2_GET_VOLUME(u16 data)
+{
+ return ( (u8) (data & 0x000F) );
+}
+
+/********************************************************************/
+
+static inline void SYSCONFIG3_BITSET_SMUTER_FASTEST(u16 *data)
+{
+ switch_off_bits(data, (SYSCONFIG3_SMUTER1|SYSCONFIG3_SMUTER0));
+}
+
+static inline void SYSCONFIG3_BITSET_SMUTER_FAST(u16 *data)
+{
+ switch_off_bits(data, (SYSCONFIG3_SMUTER1));
+ switch_on_bits(data, (SYSCONFIG3_SMUTER0));
+}
+
+static inline void SYSCONFIG3_BITSET_SMUTER_SLOW(u16 *data)
+{
+ switch_off_bits(data, (SYSCONFIG3_SMUTER0));
+ switch_on_bits(data, (SYSCONFIG3_SMUTER1));
+}
+
+static inline void SYSCONFIG3_BITSET_SMUTER_SLOWEST(u16 *data)
+{
+ switch_on_bits(data, (SYSCONFIG3_SMUTER1|SYSCONFIG3_SMUTER0));
+}
+
+static inline void SYSCONFIG3_BITSET_SMUTEA_16_dB(u16 *data)
+{
+ switch_off_bits(data, (SYSCONFIG3_SMUTEA1|SYSCONFIG3_SMUTEA0));
+}
+
+static inline void SYSCONFIG3_BITSET_SMUTEA_14dB(u16 *data)
+{
+ switch_off_bits(data, (SYSCONFIG3_SMUTEA1));
+ switch_on_bits(data, (SYSCONFIG3_SMUTEA0));
+}
+
+static inline void SYSCONFIG3_BITSET_SMUTEA_12dB(u16 *data)
+{
+ switch_off_bits(data, (SYSCONFIG3_SMUTEA0));
+ switch_on_bits(data, (SYSCONFIG3_SMUTEA1));
+}
+
+static inline void SYSCONFIG3_BITSET_SMUTEA_10dB(u16 *data)
+{
+ switch_on_bits(data, (SYSCONFIG3_SMUTEA1|SYSCONFIG3_SMUTEA0));
+}
+
+static inline void SYSCONFIG3_BITSET_VOLEXT_DISB(u16 *data)
+{
+ switch_off_bits(data, (SYSCONFIG3_VOLEXT));
+}
+
+static inline void SYSCONFIG3_BITSET_VOLEXT_ENB(u16 *data)
+{
+ switch_on_bits(data, (SYSCONFIG3_VOLEXT));
+}
+
+static inline void SYSCONFIG3_BITSET_SKSNR(u16 *data, u8 seeksnr)
+{
+ *data &= 0xFF0F;
+ *data |= ((seeksnr<<4) & 0xF0);
+}
+
+static inline void SYSCONFIG3_BITSET_SKCNT(u16 *data, u8 seekcnt)
+{
+ *data &= 0xFFF0;
+ *data |= ((seekcnt) & 0x0F);
+}
+
+static inline void SYSCONFIG3_BITSET_RESERVED(u16 *data)
+{
+ *data &= 0xF1FF;
+}
+
+/********************************************************************/
+
+static inline void TEST1_BITSET_AHIZEN_HIGH(u16 *data)
+{
+ switch_on_bits(data, (TEST1_AHIZEN));
+}
+
+static inline void TEST1_BITSET_AHIZEN_LOW(u16 *data)
+{
+ switch_off_bits(data, (TEST1_AHIZEN));
+}
+
+static inline void TEST1_BITSET_RESERVED(u16 *data)
+{
+ *data &= 0x7FFF;
+}
+
+/********************************************************************/
+
+#define NEW_RDS_GROUP_READY 1
+#define NO_RDS_GROUP_READY 0
+
+#define COMPLETE 1
+#define CLEAR 0
+
+#define SEEK_SUCCESSFUL 1
+#define SEEK_FAILURE_BAND_LMT_RCHD 0
+
+#define AFC_RAILED 1
+#define AFC_NOT_RAILED 0
+
+#define RDS_DECODER_SYNCHRONIZED 1
+#define RDS_DECODER_NOT_SYNCHRONIZED 0
+
+#define STEREO 1
+#define MONO 0
+
+#define ERRORS_0 0
+#define ERRORS_1_2 1
+#define ERRORS_3_5 2
+#define ERRORS_NO_CORREC_POSSIBLE_6_p 3
+
+static inline int STATUSRSSI_RDS_READY_STATUS(u16 data)
+{
+ if( check_bit(data, STATUSRSSI_RDSR) == BIT_ON )
+ {
+ return NEW_RDS_GROUP_READY;
+ }
+ else
+ {
+ return NO_RDS_GROUP_READY;
+ }
+}
+
+static inline int STATUSRSSI_SEEK_TUNE_STATUS(u16 data)
+{
+ if( check_bit(data, STATUSRSSI_STC) == BIT_ON )
+ {
+ return COMPLETE;
+ }
+ else
+ {
+ return CLEAR;
+ }
+}
+
+static inline int STATUSRSSI_SF_BL_STATUS(u16 data)
+{
+ if( check_bit(data, STATUSRSSI_SF_BL) == BIT_ON )
+ {
+ return SEEK_FAILURE_BAND_LMT_RCHD;
+ }
+ else
+ {
+ return SEEK_SUCCESSFUL;
+ }
+}
+
+static inline int STATUSRSSI_AFC_RAIL_STATUS(u16 data)
+{
+ if( check_bit(data, STATUSRSSI_AFCRL) == BIT_ON )
+ {
+ return AFC_RAILED;
+ }
+ else
+ {
+ return AFC_NOT_RAILED;
+ }
+}
+
+static inline int STATUSRSSI_RDS_SYNC_STATUS(u16 data)
+{
+ if( check_bit(data, STATUSRSSI_RDSS) == BIT_ON )
+ {
+ return RDS_DECODER_SYNCHRONIZED;
+ }
+ else
+ {
+ return RDS_DECODER_NOT_SYNCHRONIZED;
+ }
+}
+
+static inline int STATUSRSSI_RDS_BLOCK_A_ERRORS(u16 data)
+{
+ int ret = 0;
+ int bits_status = 0;
+
+ ret = check_bit(data,STATUSRSSI_BLERA1);
+
+ if( ret == BIT_ON )
+ bits_status = 0x02;
+ else
+ bits_status = 0x00;
+
+ ret = check_bit(data,STATUSRSSI_BLERA0);
+
+ if( ret == BIT_ON )
+ bits_status |= 0x01;
+
+ return bits_status;
+}
+
+static inline int STATUSRSSI_STEREO_STATUS(u16 data)
+{
+ if( check_bit(data, STATUSRSSI_RDSS) == BIT_ON )
+ {
+ return STEREO;
+ }
+ else
+ {
+ return MONO;
+ }
+}
+
+static inline u8 STATUSRSSI_RSSI_SIGNAL_STRENGTH(u16 data)
+{
+ return ((u8) (0x00FF & data));
+}
+
+static inline u8 DEVICE_ID_PART_NUMBER(u16 data) //vnv.srikanth
+{
+ data = data>>12;
+ return((u8)(0x000F & data));
+}
+
+static inline u16 DEVICE_ID_MANUFACT_NUMBER(u16 data) //vnv.srikanth
+{
+ return((u16)(0x0FFF & data));
+}
+
+static inline u8 CHIP_ID_CHIP_VERSION(u16 data) //vnv.srikanth
+{
+ data = data>>10;
+ return((u8)(0x003F & data));
+}
+
+static inline u8 CHIP_ID_DEVICE(u16 data) //vnv.srikanth
+{
+ data = data>>6;
+ return((u8)(0x000F & data));
+}
+
+static inline u8 CHIP_ID_FIRMWARE_VERSION(u16 data) //vnv.srikanth
+{
+ return((u8)(0x003F & data));
+}
+
+static inline u8 SYS_CONFIG2_RSSI_TH(u16 data) //vnv.srikanth
+{
+ data=data>>8;
+ return((u8)(0x00FF&data));
+}
+
+static inline u8 SYS_CONFIG2_FM_BAND(u16 data) //vnv.srikanth
+{
+ data=data>>6;
+ return((u8)(0x0003&data));
+}
+
+static inline u8 SYS_CONFIG2_FM_CHAN_SPAC(u16 data) //vnv.srikanth
+{
+ data=data>>4;
+ return((u8)(0x0003&data));
+}
+
+static inline u8 SYS_CONFIG2_FM_VOL(u16 data) //vnv.srikanth
+{
+ return((u8)(0x000F&data));
+}
+
+//POWER_CONFIG_STATUS
+ //vnv.srikanth-start
+#define SOFTMUTE_ENABLE 0
+#define SOFTMUTE_DISABLE 1
+
+#define MUTE_ENABLE 0
+#define MUTE_DISABLE 1
+
+#define STEREO_SELECT 0
+#define MONO_SELECT 1
+
+#define RDS_MODE_STANDARD 0
+#define RDS_MODE_VERBOSE 1
+
+#define SEEK_MODE_CONT_SEEK 0
+#define SEEK_MODE_STOP_SEEK 1
+
+#define SEEK_DOWN 0
+#define SEEK_UP 1
+
+#define SEEK_DISABLE 0
+#define SEEK_ABLE 1
+
+static inline int POWER_CONFIG_SOFTMUTE_STATUS(u16 data)
+{
+ if( check_bit(data, POWERCFG_DSMUTE) == BIT_ON )
+ {
+ return SOFTMUTE_DISABLE;
+ }
+ else
+ {
+ return SOFTMUTE_ENABLE;
+ }
+}
+
+static inline int POWER_CONFIG_MUTE_STATUS(u16 data)
+{
+ if( check_bit(data, POWERCFG_DMUTE) == BIT_ON )
+ {
+ return MUTE_DISABLE;
+ }
+ else
+ {
+ return MUTE_ENABLE;
+ }
+}
+
+static inline int POWER_CONFIG_MONO_STATUS(u16 data)
+{
+ if( check_bit(data, POWERCFG_MONO) == BIT_ON )
+ {
+ return MONO_SELECT;
+ }
+ else
+ {
+ return STEREO_SELECT;
+ }
+}
+
+static inline int POWER_CONFIG_RDS_MODE_STATUS(u16 data)
+{
+ if( check_bit(data, POWERCFG_RDSM ) == BIT_ON )
+ {
+ return RDS_MODE_VERBOSE;
+ }
+ else
+ {
+ return RDS_MODE_STANDARD;
+ }
+}
+
+static inline int POWER_CONFIG_SKMODE_STATUS(u16 data)
+{
+ if( check_bit(data, POWERCFG_SKMODE ) == BIT_ON )
+ {
+ return SEEK_MODE_STOP_SEEK;
+ }
+ else
+ {
+ return SEEK_MODE_CONT_SEEK;
+ }
+}
+
+static inline int POWER_CONFIG_SEEKUP_STATUS(u16 data)
+{
+ if( check_bit(data, POWERCFG_SEEKUP ) == BIT_ON )
+ {
+ return SEEK_UP;
+ }
+ else
+ {
+ return SEEK_DOWN;
+ }
+}
+
+static inline int POWER_CONFIG_SEEK_STATUS(u16 data)
+{
+ if( check_bit(data, POWERCFG_SEEK ) == BIT_ON )
+ {
+ return SEEK_ABLE;
+ }
+ else
+ {
+ return SEEK_DISABLE;
+ }
+}
+
+static inline int POWER_CONFIG_DISABLE_STATUS(u16 data)
+{
+ if( check_bit(data, POWERCFG_DISABLE ) == BIT_ON )
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+static inline int POWER_CONFIG_ENABLE_STATUS(u16 data)
+{
+ if( check_bit(data, POWERCFG_ENABLE ) == BIT_ON )
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+} //vnv.srikanth-end
+/********************************************************************/
+
+static inline int READCHAN_BLOCK_B_ERRORS(u16 data)
+{
+ int ret = 0;
+ int bits_status = 0;
+
+ ret = check_bit(data,READCHAN_BLERB1);
+
+ if( ret == BIT_ON )
+ bits_status = 0x02;
+ else
+ bits_status = 0x00;
+
+ ret = check_bit(data,READCHAN_BLERB0);
+
+ if( ret == BIT_ON )
+ bits_status |= 0x01;
+
+ return bits_status;
+}
+
+static inline int READCHAN_BLOCK_C_ERRORS(u16 data)
+{
+ int ret = 0;
+ int bits_status = 0;
+
+ ret = check_bit(data,READCHAN_BLERC1);
+
+ if( ret == BIT_ON )
+ bits_status = 0x02;
+ else
+ bits_status = 0x00;
+
+ ret = check_bit(data,READCHAN_BLERC0);
+
+ if( ret == BIT_ON )
+ bits_status |= 0x01;
+
+ return bits_status;
+}
+
+static inline int READCHAN_BLOCK_D_ERRORS(u16 data)
+{
+ int ret = 0;
+ int bits_status = 0;
+
+ ret = check_bit(data,READCHAN_BLERD1);
+
+ if( ret == BIT_ON )
+ bits_status = 0x02;
+ else
+ bits_status = 0x00;
+
+ ret = check_bit(data,READCHAN_BLERD0);
+
+ if( ret == BIT_ON )
+ bits_status |= 0x01;
+
+ return bits_status;
+}
+
+static inline u16 READCHAN_GET_CHAN(u16 data)
+{
+ return ( data & READCHAN_CHAN_MASK );
+}
+
+/********************************************************************/
+
+#endif
+
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 7937b34..515f638 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -1032,6 +1032,12 @@ config USB_S2255
endif # V4L_USB_DRIVERS
+config VIDEO_CE147
+ tristate "CE147 Camera Sensor"
+ depends on I2C && VIDEO_V4L2
+ ---help---
+ This driver supports CE147 SoC camera module
+
config VIDEO_S5KA3DFX
tristate "S5KA3DFX Camera Sensor"
depends on I2C && VIDEO_V4L2
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index c4ce996b..bea5bbb 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -84,7 +84,7 @@ obj-$(CONFIG_SOC_CAMERA_OV9640) += ov9640.o
obj-$(CONFIG_SOC_CAMERA_OV9740) += ov9740.o
obj-$(CONFIG_SOC_CAMERA_RJ54N1) += rj54n1cb0c.o
obj-$(CONFIG_SOC_CAMERA_TW9910) += tw9910.o
-
+obj-$(CONFIG_VIDEO_CE147) += ce147.o
obj-$(CONFIG_VIDEO_S5KA3DFX) += s5ka3dfx.o
obj-$(CONFIG_VIDEO_S5K4ECGX) += s5k4ecgx.o
# And now the v4l2 drivers:
diff --git a/drivers/media/video/ce147.c b/drivers/media/video/ce147.c
new file mode 100755
index 0000000..bdf48e1
--- /dev/null
+++ b/drivers/media/video/ce147.c
@@ -0,0 +1,5670 @@
+/*
+ * Driver for CE147 (5MP Camera) from NEC
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/vmalloc.h>
+#include <linux/rtc.h>
+#include <linux/completion.h>
+#include <media/v4l2-device.h>
+#include <media/ce147_platform.h>
+
+#ifdef CONFIG_VIDEO_SAMSUNG_V4L2
+#include <linux/videodev2_samsung.h>
+#endif
+
+/* #define MDNIE_TUNING */
+
+#define CE147_DRIVER_NAME "CE147"
+
+#define FORMAT_FLAGS_COMPRESSED 0x3
+#define SENSOR_JPEG_SNAPSHOT_MEMSIZE 0x360000
+
+/* #define CE147_DEBUG */
+/* #define CE147_INFO */
+
+#ifdef CE147_DEBUG
+#define ce147_msg dev_err
+#else
+#define ce147_msg dev_dbg
+#endif
+
+#ifdef CE147_INFO
+#define ce147_info dev_err
+#else
+#define ce147_info dev_dbg
+#endif
+
+/* Default resolution & pixelformat. plz ref ce147_platform.h */
+#define DEFAULT_PIX_FMT V4L2_PIX_FMT_UYVY /* YUV422 */
+#define DEFAULT_MCLK 24000000
+#define POLL_TIME_MS 10
+
+/* Camera ISP command */
+#define CMD_VERSION 0x00
+#define DATA_VERSION_FW 0x00
+#define DATA_VERSION_DATE 0x01
+#define CMD_GET_BATCH_REFLECTION_STATUS 0x02
+#define DATA_VERSION_SENSOR 0x03
+#define CMD_HD_PREVIEW 0x03
+#define CMD_SET_WB 0x04
+#define DATA_VERSION_AF 0x05
+#define CMD_SET_FLASH_MANUAL 0x06
+#define CMD_SET_EXIF_CTRL 0x07
+#define CMD_AE_WB_LOCK 0x11
+#define CMD_SET_ANTI_BANDING 0x14
+#define CMD_SET_WB_AUTO 0x1A
+#define CMD_SET_AUTO_FOCUS_MODE 0x20
+#define CMD_START_AUTO_FOCUS_SEARCH 0x23
+#define CMD_CHECK_AUTO_FOCUS_SEARCH 0x24
+#define CMD_STOP_LENS_MOVEMENT 0x35
+#define CMD_SET_EFFECT 0x3D
+#define CMD_SET_TOUCH_AUTO_FOCUS 0x4D
+#define CMD_START_OT 0x50
+#define CMD_CHECK_OT 0x51
+#define CMD_PREVIEW_SIZE 0x54
+#define CMD_FPS 0x5A
+#define CMD_SET_ANTI_SHAKE 0x5B
+#define CMD_SET_DATA 0x65
+#define CMD_DATA_OUT_REQ 0x66
+#define CMD_PREVIEW 0x6B
+#define CMD_PREVIEW_STATUS 0x6C
+#define CMD_CAPTURE_SIZE 0x73
+#define CMD_BUFFERING_CAPTURE 0x74
+#define CMD_SET_SMART_AUTO 0x82
+#define CMD_GET_SMART_AUTO_STATUS 0x83
+#define CMD_SET_WDR 0x88
+#define CMD_JPEG_SIZE 0x8E
+#define CMD_JPEG_BUFFERING 0x8F
+#define CMD_JPEG_CONFIG 0x90
+#define CMD_JPEG_BUFFERING2 0x92
+#define CMD_SET_FACE_DETECTION 0x9A
+#define CMD_SET_FACE_LOCK 0x9C
+#define CMD_INFO_EXIF 0xA0
+#define CMD_INFO_MODEL 0xA1
+#define CMD_INFO_ROT 0xA2
+#define CMD_INFO_LONGITUDE_LATITUDE 0xA3
+#define CMD_INFO_ALTITUDE 0xA4
+#define CMD_SET_FLASH 0xB2
+#ifdef CONFIG_SAMSUNG_FASCINATE
+#define CMD_SET_FLASH_POWER 0xB3
+#endif
+#define CMD_SET_DZOOM 0xB9
+#define CMD_GET_DZOOM_LEVEL 0xBA
+#define CMD_SET_EFFECT_SHOT 0xC0
+#define DATA_VERSION_GAMMA 0xE0
+#define DATA_VERSION_SENSOR_MAKER 0xE0
+#define CMD_CHECK_DATALINE 0xEC
+#define CMD_INIT 0xF0
+#define CMD_FW_INFO 0xF2
+#define CMD_FWU_UPDATE 0xF3
+#define CMD_FW_UPDATE 0xF4
+#define CMD_FW_STATUS 0xF5
+#define CMD_FW_DUMP 0xFB
+#define CMD_GPS_TIMESTAMP 0xA7
+
+#define CE147_FW_F2_PATH "/system/firmware/CE147F02.bin"
+#define FACTORY_CHECK
+
+/* { FW Maj, FW Min, PRM Maj, PRM Min } */
+static unsigned char MAIN_SW_FW[4] = { 0x0, 0x0, 0x0, 0x0 };
+/* { Year, Month, Date } */
+static int MAIN_SW_DATE_INFO[3] = { 0x0, 0x0, 0x0 };
+
+static unsigned char ce147_buf_set_dzoom[31] = {
+ 0xff, 0xe7, 0xd3, 0xc2, 0xb4, 0xa7, 0x9c, 0x93, 0x8b, 0x83,
+ 0x7c, 0x76, 0x71, 0x6c, 0x67, 0x63, 0x5f, 0x5b, 0x58, 0x55,
+ 0x52, 0x4f, 0x4d, 0x4a, 0x48, 0x46, 0x44, 0x42, 0x41, 0x40,
+ 0x3f
+};
+static int DZoom_State;
+#ifdef CONFIG_SAMSUNG_FASCINATE
+static int Flash_Mode = 0;
+#endif
+
+enum ce147_oprmode {
+ CE147_OPRMODE_VIDEO = 0,
+ CE147_OPRMODE_IMAGE = 1,
+};
+
+/* Declare Funtion */
+static int ce147_set_awb_lock(struct v4l2_subdev *sd, int lock);
+static int ce147_set_iso(struct v4l2_subdev *sd, struct v4l2_control *ctrl);
+static int ce147_set_metering(struct v4l2_subdev *sd,
+ struct v4l2_control *ctrl);
+static int ce147_set_ev(struct v4l2_subdev *sd, struct v4l2_control *ctrl);
+static int ce147_set_slow_ae(struct v4l2_subdev *sd, struct v4l2_control *ctrl);
+static int ce147_set_gamma(struct v4l2_subdev *sd, struct v4l2_control *ctrl);
+static int ce147_set_effect(struct v4l2_subdev *sd, struct v4l2_control *ctrl);
+static int ce147_set_white_balance(struct v4l2_subdev *sd,
+ struct v4l2_control *ctrl);
+static int ce147_s_ext_ctrl(struct v4l2_subdev *sd,
+ struct v4l2_ext_control *ctrl);
+#ifdef CONFIG_SAMSUNG_FASCINATE
+static int ce147_set_preflash(struct v4l2_subdev *sd, int flash_mode);
+#endif
+
+enum {
+ AUTO_FOCUS_FAILED,
+ AUTO_FOCUS_DONE,
+ AUTO_FOCUS_CANCELLED,
+};
+
+enum af_operation_status {
+ AF_NONE = 0,
+ AF_START,
+ AF_CANCEL,
+ AF_INITIAL,
+};
+
+enum ce147_frame_size {
+ CE147_PREVIEW_QCIF = 0,
+ CE147_PREVIEW_QVGA,
+ CE147_PREVIEW_592x480,
+ CE147_PREVIEW_VGA,
+ CE147_PREVIEW_D1,
+ CE147_PREVIEW_WVGA,
+ CE147_PREVIEW_720P,
+ CE147_PREVIEW_VERTICAL_QCIF,
+ CE147_CAPTURE_VGA, /* 640 x 480 */
+ CE147_CAPTURE_WVGA, /* 800 x 480 */
+ CE147_CAPTURE_W1MP, /* 1600 x 960 */
+ CE147_CAPTURE_2MP, /* UXGA - 1600 x 1200 */
+ CE147_CAPTURE_W2MP, /* 35mm Academy Offset Standard 1.66
+ - 2048 x 1232, 2.4MP */
+ CE147_CAPTURE_3MP, /* QXGA - 2048 x 1536 */
+ CE147_CAPTURE_W4MP, /* WQXGA - 2560 x 1536 */
+ CE147_CAPTURE_5MP, /* 2560 x 1920 */
+};
+
+struct ce147_enum_framesize {
+ /* mode is 0 for preview, 1 for capture */
+ enum ce147_oprmode mode;
+ unsigned int index;
+ unsigned int width;
+ unsigned int height;
+};
+
+static struct ce147_enum_framesize ce147_framesize_list[] = {
+ { CE147_OPRMODE_VIDEO, CE147_PREVIEW_QCIF, 176, 144 },
+ { CE147_OPRMODE_VIDEO, CE147_PREVIEW_QVGA, 320, 240 },
+ { CE147_OPRMODE_VIDEO, CE147_PREVIEW_592x480, 592, 480 },
+ { CE147_OPRMODE_VIDEO, CE147_PREVIEW_VGA, 640, 480 },
+ { CE147_OPRMODE_VIDEO, CE147_PREVIEW_D1, 720, 480 },
+ { CE147_OPRMODE_VIDEO, CE147_PREVIEW_WVGA, 800, 480 },
+ { CE147_OPRMODE_VIDEO, CE147_PREVIEW_720P, 1280, 720 },
+ { CE147_OPRMODE_VIDEO, CE147_PREVIEW_VERTICAL_QCIF, 144, 176},
+ { CE147_OPRMODE_IMAGE, CE147_CAPTURE_VGA, 640, 480 },
+ { CE147_OPRMODE_IMAGE, CE147_CAPTURE_WVGA, 800, 480 },
+ { CE147_OPRMODE_IMAGE, CE147_CAPTURE_W1MP, 1600, 960 },
+ { CE147_OPRMODE_IMAGE, CE147_CAPTURE_2MP, 1600, 1200 },
+ { CE147_OPRMODE_IMAGE, CE147_CAPTURE_W2MP, 2048, 1232 },
+ { CE147_OPRMODE_IMAGE, CE147_CAPTURE_3MP, 2048, 1536 },
+ { CE147_OPRMODE_IMAGE, CE147_CAPTURE_W4MP, 2560, 1536 },
+ { CE147_OPRMODE_IMAGE, CE147_CAPTURE_5MP, 2560, 1920 },
+};
+
+struct ce147_version {
+ unsigned int major;
+ unsigned int minor;
+};
+
+struct ce147_date_info {
+ unsigned int year;
+ unsigned int month;
+ unsigned int date;
+};
+
+enum ce147_runmode {
+ CE147_RUNMODE_NOTREADY,
+ CE147_RUNMODE_IDLE,
+ CE147_RUNMODE_READY,
+ CE147_RUNMODE_RUNNING,
+};
+
+struct ce147_firmware {
+ unsigned int addr;
+ unsigned int size;
+};
+
+/* Camera functional setting values configured by user concept */
+struct ce147_userset {
+ signed int exposure_bias; /* V4L2_CID_EXPOSURE */
+ unsigned int ae_lock;
+ unsigned int awb_lock;
+ unsigned int auto_wb; /* V4L2_CID_AUTO_WHITE_BALANCE */
+ unsigned int manual_wb; /* V4L2_CID_WHITE_BALANCE_PRESET */
+ unsigned int wb_temp; /* V4L2_CID_WHITE_BALANCE_TEMPERATURE */
+ unsigned int effect; /* Color FX (AKA Color tone) */
+ unsigned int contrast; /* V4L2_CID_CONTRAST */
+ unsigned int saturation; /* V4L2_CID_SATURATION */
+ unsigned int sharpness; /* V4L2_CID_SHARPNESS */
+ unsigned int glamour;
+};
+
+struct ce147_jpeg_param {
+ unsigned int enable;
+ unsigned int quality;
+ unsigned int main_size; /* Main JPEG file size */
+ unsigned int thumb_size; /* Thumbnail file size */
+ unsigned int main_offset;
+ unsigned int thumb_offset;
+ unsigned int postview_offset;
+} ;
+
+struct ce147_position {
+ int x;
+ int y;
+} ;
+
+struct ce147_gps_info {
+ unsigned char ce147_gps_buf[8];
+ unsigned char ce147_altitude_buf[4];
+ unsigned long gps_timeStamp;
+ char gps_processingmethod[50];
+};
+
+struct ce147_sensor_maker {
+ unsigned int maker;
+ unsigned int optical;
+};
+
+struct ce147_version_af {
+ unsigned int low;
+ unsigned int high;
+};
+
+struct ce147_gamma {
+ unsigned int rg_low;
+ unsigned int rg_high;
+ unsigned int bg_low;
+ unsigned int bg_high;
+};
+
+#if 0
+struct tm {
+ int tm_sec; /* seconds */
+ int tm_min; /* minutes */
+ int tm_hour; /* hours */
+ int tm_mday; /* day of the month */
+ int tm_mon; /* month */
+ int tm_year; /* year */
+ int tm_wday; /* day of the week */
+ int tm_yday; /* day in the year */
+ int tm_isdst; /* daylight saving time */
+
+ long int tm_gmtoff; /* Seconds east of UTC. */
+ const char *tm_zone; /* Timezone abbreviation. */
+};
+#endif
+
+struct gps_info_common {
+ unsigned int direction;
+ unsigned int dgree;
+ unsigned int minute;
+ unsigned int second;
+};
+
+struct ce147_state {
+ struct ce147_platform_data *pdata;
+ struct v4l2_subdev sd;
+ struct v4l2_pix_format pix;
+ struct v4l2_fract timeperframe;
+ struct ce147_userset userset;
+ struct ce147_jpeg_param jpeg;
+ struct ce147_version fw;
+ struct ce147_version prm;
+ struct ce147_date_info dateinfo;
+ struct ce147_firmware fw_info;
+ struct ce147_position position;
+ struct ce147_sensor_maker sensor_info;
+ struct ce147_version_af af_info;
+ struct ce147_gamma gamma;
+ struct v4l2_streamparm strm;
+ struct ce147_gps_info gpsInfo;
+ struct mutex ctrl_lock;
+ enum ce147_runmode runmode;
+ enum ce147_oprmode oprmode;
+ int framesize_index;
+ int sensor_version;
+ int freq; /* MCLK in Hz */
+ int fps;
+ int ot_status;
+ int sa_status;
+ int anti_banding;
+ int preview_size;
+ unsigned int fw_dump_size;
+ int hd_preview_on;
+ int pre_focus_mode;
+ enum af_operation_status af_status;
+ struct ce147_version main_sw_fw;
+ struct ce147_version main_sw_prm;
+ struct ce147_date_info main_sw_dateinfo;
+ int exif_orientation_info;
+ int check_dataline;
+ int hd_slow_ae;
+ int hd_gamma;
+ int iso;
+ int metering;
+ int ev;
+ int effect;
+ int wb;
+ struct tm *exifTimeInfo;
+#if defined(CONFIG_ARIES_NTT) || defined(CONFIG_SAMSUNG_FASCINATE)
+ int disable_aeawb_lock;
+#endif
+ int exif_ctrl;
+ int thumb_null;
+};
+
+static int condition;
+
+static const struct v4l2_mbus_framefmt capture_fmts[] = {
+ {
+ .code = V4L2_MBUS_FMT_FIXED,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ },
+};
+
+static inline struct ce147_state *to_state(struct v4l2_subdev *sd)
+{
+ return container_of(sd, struct ce147_state, sd);
+}
+
+/**
+ * ce147_i2c_write_multi: Write (I2C) multiple bytes to the camera sensor
+ * @client: pointer to i2c_client
+ * @cmd: command register
+ * @w_data: data to be written
+ * @w_len: length of data to be written
+ *
+ * Returns 0 on success, <0 on error
+ */
+static int ce147_i2c_write_multi(struct i2c_client *client, unsigned char cmd,
+ unsigned char *w_data, unsigned int w_len)
+{
+ int retry_count = 1;
+ unsigned char buf[w_len + 1];
+ struct i2c_msg msg = { client->addr, 0, w_len + 1, buf };
+
+ int ret = -1;
+
+ buf[0] = cmd;
+ memcpy(buf + 1, w_data, w_len);
+
+#ifdef CE147_DEBUG
+ {
+ int j;
+ pr_debug("W: ");
+ for (j = 0; j <= w_len; j++)
+ pr_debug("0x%02x ", buf[j]);
+ pr_debug("\n");
+ }
+#endif
+
+ while (retry_count--) {
+ ret = i2c_transfer(client->adapter, &msg, 1);
+ if (ret == 1)
+ break;
+ msleep(POLL_TIME_MS);
+ }
+
+ return (ret == 1) ? 0 : -EIO;
+}
+
+/**
+ * ce147_i2c_read_multi: Read (I2C) multiple bytes to the camera sensor
+ * @client: pointer to i2c_client
+ * @cmd: command register
+ * @w_data: data to be written
+ * @w_len: length of data to be written
+ * @r_data: buffer where data is read
+ * @r_len: number of bytes to read
+ *
+ * Returns 0 on success, <0 on error
+ */
+static int ce147_i2c_read_multi(struct i2c_client *client, unsigned char cmd,
+ unsigned char *w_data, unsigned int w_len,
+ unsigned char *r_data, unsigned int r_len)
+{
+ unsigned char buf[w_len + 1];
+ struct i2c_msg msg = { client->addr, 0, w_len + 1, buf };
+ int ret = -1;
+ int retry_count = 1;
+
+ buf[0] = cmd;
+ memcpy(buf + 1, w_data, w_len);
+
+#ifdef CE147_DEBUG
+ {
+ int j;
+ pr_debug("R: ");
+ for (j = 0; j <= w_len; j++)
+ pr_debug("0x%02x ", buf[j]);
+ pr_debug("\n");
+ }
+#endif
+
+ while (retry_count--) {
+ ret = i2c_transfer(client->adapter, &msg, 1);
+ if (ret == 1)
+ break;
+ msleep(POLL_TIME_MS);
+ }
+
+ if (ret < 0)
+ return -EIO;
+
+ msg.flags = I2C_M_RD;
+ msg.len = r_len;
+ msg.buf = r_data;
+
+ retry_count = 1;
+ while (retry_count--) {
+ ret = i2c_transfer(client->adapter, &msg, 1);
+ if (ret == 1)
+ break;
+ msleep(POLL_TIME_MS);
+ }
+
+ return (ret == 1) ? 0 : -EIO;
+}
+
+/**
+ * ce147_power_en: Enable or disable the camera sensor power
+ * Use only for updating camera firmware
+ * Returns 0 forever
+ */
+static int ce147_power_en(int onoff, struct v4l2_subdev *sd)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ce147_platform_data *pdata;
+
+ pdata = client->dev.platform_data;
+
+ if (onoff == 1)
+ pdata->power_en(1);
+ else
+ pdata->power_en(0);
+
+ return 0;
+}
+
+/**
+ * This function checks the status of the camera sensor by polling
+ * through the 'cmd' command register.
+ *
+ * 'polling_interval' is the delay between successive polling events
+ *
+ * The function returns if
+ * o 'timeout' (in ms) expires
+ * o the data read from device matches 'value'
+ *
+ * On success it returns the time taken for successful wait.
+ * On failure, it returns -EBUSY.
+ * On I2C related failure, it returns -EIO.
+ */
+static int ce147_waitfordone_timeout(struct i2c_client *client,
+ unsigned char cmd, unsigned char value,
+ int timeout, int polling_interval)
+{
+ int err;
+ unsigned char cam_status = 0xFF;
+ unsigned long jiffies_start = jiffies;
+ unsigned long jiffies_timeout =
+ jiffies_start + msecs_to_jiffies(timeout);
+
+ if (polling_interval < 0)
+ polling_interval = POLL_TIME_MS;
+
+ while (time_before(jiffies, jiffies_timeout)) {
+ cam_status = 0xFF;
+ err = ce147_i2c_read_multi(client,
+ cmd, NULL, 0, &cam_status, 1);
+ if (err < 0)
+ return -EIO;
+
+ ce147_msg(&client->dev, "Status check returns %02x\n",
+ cam_status);
+
+ if (cam_status == value)
+ break;
+
+ msleep(polling_interval);
+ }
+
+ if (cam_status != value)
+ return -EBUSY;
+ else
+ return jiffies_to_msecs(jiffies - jiffies_start);
+}
+
+static int ce147_get_batch_reflection_status(struct v4l2_subdev *sd)
+{
+ int err;
+ int end_cnt = 0;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ unsigned char ce147_buf_batch_data[1] = { 0x00 };
+ unsigned char ce147_batch_ref_status = 0x00;
+
+ err = ce147_i2c_write_multi(client, 0x01, ce147_buf_batch_data, 1);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write "
+ "forget_batch_reflection_status\n", __func__);
+ return -EIO;
+ }
+
+ /* TODO: This code needs timeout API for do-while */
+ do {
+ msleep(10);
+ err = ce147_i2c_read_multi(client,
+ CMD_GET_BATCH_REFLECTION_STATUS, NULL, 0,
+ &ce147_batch_ref_status, 1);
+
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_read "
+ "for get_batch_reflection_status\n",
+ __func__);
+ return -EIO;
+ }
+ end_cnt++;
+ } while (ce147_batch_ref_status && end_cnt < 200);
+
+ if (end_cnt > 5) {
+ ce147_msg(&client->dev, "%s: count(%d) status(%02x)\n",
+ __func__, end_cnt, ce147_batch_ref_status);
+ }
+
+ if (ce147_batch_ref_status != 0x00) {
+ dev_err(&client->dev, "%s: failed: "
+ "to get_batch_reflection_status\n", __func__);
+ return -EINVAL;
+ }
+
+ ce147_msg(&client->dev, "%s: done\n", __func__);
+
+ return 0;
+}
+
+static int ce147_read_fw_bin(const char *path, char *fwBin, int *fwSize)
+{
+ char *buffer = NULL;
+ unsigned int file_size = 0;
+
+ struct file *filep = NULL;
+ mm_segment_t old_fs;
+
+ filep = filp_open(path, O_RDONLY, 0) ;
+
+ if (filep && (filep != ERR_PTR(-ENOENT))) {
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ file_size = filep->f_op->llseek(filep, 0, SEEK_END);
+ filep->f_op->llseek(filep, 0, SEEK_SET);
+
+ buffer = kmalloc(file_size + 1, GFP_KERNEL);
+
+ filep->f_op->read(filep, buffer, file_size, &filep->f_pos);
+ buffer[file_size] = '\0';
+
+ filp_close(filep, current->files);
+
+ set_fs(old_fs);
+
+ pr_debug("File size : %d\n", file_size);
+ } else
+ return -EINVAL;
+
+ memcpy(fwBin, buffer, file_size);
+ *fwSize = file_size;
+
+ kfree(buffer);
+
+ return 0;
+}
+
+static int ce147_get_main_sw_fw_version(struct v4l2_subdev *sd)
+{
+ struct ce147_state *state = to_state(sd);
+ char fw_data[20] = { 0, };
+ int fw_size = 0;
+ int main_sw_fw_prm_offset = 4;
+ int main_sw_date_offset = 10;
+ int err = 0;
+#if 0
+ int i;
+#endif
+
+ pr_debug("ce147_get_main_sw_fw_version Enter\n");
+
+ if ((MAIN_SW_DATE_INFO[0] == 0x00) && (MAIN_SW_DATE_INFO[1] == 0x00)
+ && (MAIN_SW_DATE_INFO[2] == 0x00)) {
+ err = ce147_read_fw_bin(CE147_FW_F2_PATH, fw_data, &fw_size);
+ if (err < 0) {
+ pr_debug("fail : read main_sw_version\n");
+ return err;
+ }
+
+#if 0
+ pr_debug("fw_size : %d\n", fw_size);
+
+ for (i = 0; i < fw_size; i++)
+ pr_debug("fw_data : %x\n", fw_data[i]);
+#endif
+
+ /* Main SW FW/PRM info */
+ MAIN_SW_FW[0] = fw_data[main_sw_fw_prm_offset];
+ MAIN_SW_FW[1] = fw_data[main_sw_fw_prm_offset + 1];
+ MAIN_SW_FW[2] = fw_data[main_sw_fw_prm_offset + 2];
+ MAIN_SW_FW[3] = fw_data[main_sw_fw_prm_offset + 3];
+
+ /* Main SW Date info */
+ MAIN_SW_DATE_INFO[0] = (2000 + fw_data[main_sw_date_offset]);
+ MAIN_SW_DATE_INFO[1] = fw_data[main_sw_date_offset + 1];
+ MAIN_SW_DATE_INFO[2] = fw_data[main_sw_date_offset + 2];
+
+ pr_debug("fw M:%d m:%d |prm M:%d m:%d\n",
+ MAIN_SW_FW[0], MAIN_SW_FW[1],
+ MAIN_SW_FW[2], MAIN_SW_FW[3]);
+ pr_debug("y. m. d = %d.%d.%d\n",
+ MAIN_SW_DATE_INFO[0], MAIN_SW_DATE_INFO[1],
+ MAIN_SW_DATE_INFO[2]);
+ } else
+ pr_debug("already read main sw version\n");
+
+ state->main_sw_fw.major = MAIN_SW_FW[0];
+ state->main_sw_fw.minor = MAIN_SW_FW[1];
+ state->main_sw_prm.major = MAIN_SW_FW[2];
+ state->main_sw_prm.minor = MAIN_SW_FW[3];
+ state->main_sw_dateinfo.year = MAIN_SW_DATE_INFO[0];
+ state->main_sw_dateinfo.month = MAIN_SW_DATE_INFO[1];
+ state->main_sw_dateinfo.date = MAIN_SW_DATE_INFO[2];
+
+ return 0;
+}
+
+static int ce147_load_fw(struct v4l2_subdev *sd)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ce147_state *state = to_state(sd);
+ int ce147_reglen_init = 1;
+ unsigned char ce147_regbuf_init[1] = { 0x00 };
+ int err;
+
+ /* Just before this function call, we enable the power and clock. Hence
+ * we need to wait for some time before we can start communicating
+ * with the sensor.
+ */
+ msleep(10);
+
+ err = ce147_i2c_write_multi(client, CMD_INIT,
+ ce147_regbuf_init, ce147_reglen_init);
+ if (err < 0)
+ return -EIO;
+
+ /* At least 700ms delay required to load the firmware
+ * for ce147 camera ISP */
+ msleep(700);
+
+ state->runmode = CE147_RUNMODE_IDLE;
+
+ return 0;
+}
+
+
+static int ce147_get_version(struct v4l2_subdev *sd, int object_id,
+ unsigned char version_info[])
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ unsigned char cmd_buf[1] = { 0x00 };
+ unsigned int cmd_len = 1;
+ unsigned int info_len = 4;
+ int err;
+
+ switch (object_id) {
+ case DATA_VERSION_FW:
+ case DATA_VERSION_DATE:
+ case DATA_VERSION_SENSOR:
+ case DATA_VERSION_SENSOR_MAKER:
+ case DATA_VERSION_AF:
+ cmd_buf[0] = object_id;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ err = ce147_i2c_read_multi(client, CMD_VERSION, cmd_buf, cmd_len,
+ version_info, info_len);
+ if (err < 0)
+ return -EIO;
+
+ return 0;
+}
+
+static int ce147_get_fw_version(struct v4l2_subdev *sd)
+{
+ struct ce147_state *state = to_state(sd);
+ unsigned char version_info[4] = { 0x00, 0x00, 0x00, 0x00 };
+ int err = -1;
+
+ err = ce147_get_version(sd, DATA_VERSION_FW, version_info);
+
+ if (err < 0)
+ return err;
+
+ state->fw.minor = version_info[0];
+ state->fw.major = version_info[1];
+
+ state->prm.minor = version_info[2];
+ state->prm.major = version_info[3];
+
+ return 0;
+}
+
+static int ce147_get_dateinfo(struct v4l2_subdev *sd)
+{
+ struct ce147_state *state = to_state(sd);
+ unsigned char version_info[4] = { 0x00, 0x00, 0x00, 0x00 };
+ int err = -1;
+
+ err = ce147_get_version(sd, DATA_VERSION_DATE, version_info);
+
+ if (err < 0)
+ return err;
+
+ state->dateinfo.year = version_info[0] - 'A' + 2007;
+ state->dateinfo.month = version_info[1] - 'A' + 1;
+ state->dateinfo.date = version_info[2];
+
+ return 0;
+}
+
+static int ce147_get_sensor_version(struct v4l2_subdev *sd)
+{
+ struct ce147_state *state = to_state(sd);
+ unsigned char version_info[4] = { 0x00, 0x00, 0x00, 0x00 };
+ int err = -1;
+
+ err = ce147_get_version(sd, DATA_VERSION_SENSOR, version_info);
+
+ if (err < 0)
+ return err;
+
+ state->sensor_version = version_info[0];
+
+ return 0;
+}
+
+static int ce147_get_sensor_maker_version(struct v4l2_subdev *sd)
+{
+ struct ce147_state *state = to_state(sd);
+ unsigned char version_info[4] = { 0x00, 0x00, 0x00, 0x00 };
+ int err = -1;
+
+ err = ce147_get_version(sd, DATA_VERSION_SENSOR_MAKER, version_info);
+
+ if (err < 0)
+ return err;
+
+ state->sensor_info.maker = version_info[0];
+ state->sensor_info.optical = version_info[1];
+
+ return 0;
+}
+
+static int ce147_get_af_version(struct v4l2_subdev *sd)
+{
+ struct ce147_state *state = to_state(sd);
+ unsigned char version_info[4] = { 0x00, 0x00, 0x00, 0x00 };
+ int err = -1;
+
+ err = ce147_get_version(sd, DATA_VERSION_AF, version_info);
+
+ if (err < 0)
+ return err;
+
+ /* pr_debug("ce147_get_af_version: data0: 0x%02x, data1: 0x%02x\n",
+ version_info[0], version_info[1]); */
+
+ state->af_info.low = version_info[1];
+ state->af_info.high = version_info[0];
+
+ return 0;
+}
+
+static int ce147_get_gamma_version(struct v4l2_subdev *sd)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ce147_state *state = to_state(sd);
+ unsigned char gamma_info[2] = { 0x00, 0x00 };
+ unsigned int info_len = 2;
+ int err = -1;
+
+ unsigned char rg_low_buf[2] = { 0x0C, 0x00 };
+ unsigned char rg_high_buf[2] = { 0x0D, 0x00 };
+ unsigned char bg_low_buf[2] = { 0x0E, 0x00 };
+ unsigned char bg_high_buf[2] = { 0x0F, 0x00 };
+ unsigned int buf_len = 2;
+
+
+ err = ce147_i2c_read_multi(client, DATA_VERSION_GAMMA,
+ rg_low_buf, buf_len, gamma_info, info_len);
+ if (err < 0)
+ return -EIO;
+
+ state->gamma.rg_low = gamma_info[1];
+ /* pr_debug("ce147_get_gamma_version1: data1: 0x%02x, data1: 0x%02x\n",
+ gamma_info[0], gamma_info[1]); */
+
+ err = ce147_i2c_read_multi(client, DATA_VERSION_GAMMA,
+ rg_high_buf, buf_len, gamma_info, info_len);
+ if (err < 0)
+ return -EIO;
+
+ state->gamma.rg_high = gamma_info[1];
+ /* pr_debug("ce147_get_gamma_version1: data1: 0x%02x, data1: 0x%02x\n",
+ gamma_info[0], gamma_info[1]); */
+
+ err = ce147_i2c_read_multi(client, DATA_VERSION_GAMMA,
+ bg_low_buf, buf_len, gamma_info, info_len);
+ if (err < 0)
+ return -EIO;
+
+ state->gamma.bg_low = gamma_info[1];
+ /* pr_debug("ce147_get_gamma_version1: data1: 0x%02x, data1: 0x%02x\n",
+ gamma_info[0], gamma_info[1]); */
+
+ err = ce147_i2c_read_multi(client, DATA_VERSION_GAMMA,
+ bg_high_buf, buf_len, gamma_info, info_len);
+ if (err < 0)
+ return -EIO;
+
+ state->gamma.bg_high = gamma_info[1];
+ /* pr_debug("ce147_get_gamma_version1: data1: 0x%02x, data1: 0x%02x\n",
+ gamma_info[0], gamma_info[1]); */
+
+ return 0;
+}
+
+#ifndef MDNIE_TUNING
+static int ce147_update_fw(struct v4l2_subdev *sd)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ce147_state *state = to_state(sd);
+ unsigned char *mbuf = NULL;
+ unsigned char *fw_buf[4];
+ int fw_size[4];
+ int index = 0;
+ int i = 0;
+ int err;
+
+ const unsigned int packet_size = 129; /* Data 128 + Checksum 1 */
+ unsigned int packet_num, k, j = 0, l = 0;
+ unsigned char res = 0x00;
+ unsigned char data[129];
+ unsigned char data2[129];
+
+ /* dev_err(&client->dev, "%s: ce147_fw: buf = 0x%p, len = %d\n",
+ __func__, (void*)state->fw_info.addr, state->fw_info.size); */
+
+ mbuf = vmalloc(state->fw_info.size);
+
+ if (NULL == mbuf)
+ return -ENOMEM;
+
+ if (copy_from_user(mbuf, (void *)state->fw_info.addr,
+ state->fw_info.size)) {
+ err = -EFAULT;
+ goto out;
+ }
+
+ /* The firmware buffer is now copied to mbuf,
+ * so the firmware code is now in mbuf.
+ * We can use mbuf with i2c_tranfer call
+ */
+ for (i = 0; i < 4; i++) {
+ if (index > state->fw_info.size - 4) {
+ dev_err(&client->dev, "%s:Error size parameter\n",
+ __func__);
+ break;
+ }
+ memcpy(fw_size + i, mbuf + index, 4);
+ index += 4;
+ fw_buf[i] = mbuf + index;
+ index += ((fw_size[i] - 1) & (~0x3)) + 4;
+ dev_err(&client->dev, "%s: [%d] fw_size = %d, fw_buf = 0x%p\n",
+ __func__, i, fw_size[i], fw_buf[i]);
+ }
+
+ err = ce147_power_en(1, sd);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: ce147_power_en(on)\n",
+ __func__);
+ err = -EIO;
+ goto out;
+ }
+
+ msleep(100);
+
+ /* [1] set fw updater info */
+ err = ce147_i2c_write_multi(client, CMD_FW_INFO, fw_buf[0], 4);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for 0xf2, "
+ "fw_size[0]: %d, fw_buf[0]: 0x%02x\n",
+ __func__, fw_size[0],
+ (unsigned int)(fw_buf[0]));
+ err = -EIO;
+ goto out;
+ }
+ msleep(100);
+
+ /* pr_debug("ce147_update_fw: i2c_write for 0xf2, "
+ "fw_size[0]: %d, fw_buf[0]: 0x%02x\n",
+ fw_size[0], fw_buf[0]); */
+
+ packet_num = *(fw_buf[0]) + (*(fw_buf[0]+1)<<8);
+
+ /* [2] update firmware */
+ for (k = 0; k < packet_num; k++) {
+ memcpy(&data[0], fw_buf[1]+j, packet_size);
+ err = ce147_i2c_read_multi(client, CMD_FWU_UPDATE,
+ data, packet_size, &res, 1);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: fail: i2c_read for 0xf3, "
+ "data: 0x%02x\n", __func__, data[0]);
+ err = -EIO;
+ goto out;
+ }
+ msleep(10);
+ j += 129;
+ /* pr_debug("ce147_update_fw: i2c_read for 0xf3, "
+ "data: 0x%02x, count: %d\n", data[0], k); */
+ }
+
+ k = 0;
+ /* [3] get fw status */
+ do {
+ msleep(100);
+
+ err = ce147_i2c_read_multi(client, CMD_FW_STATUS, NULL, 0,
+ &res, 1);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: fail: i2c_read for 0xf5",
+ __func__);
+ err = -EIO;
+ goto out;
+ }
+ /* pr_debug("ce147_update_fw: i2c_read for 0xf5, "
+ "data: 0x%02x\n", res); */
+
+ k++;
+ if (k == 500)
+ break;
+ } while (res != 0x05);
+
+ msleep(500);
+
+ fw_size[2] = 4;
+
+ /* [4] set fw updater info */
+ err = ce147_i2c_write_multi(client, CMD_FW_INFO, fw_buf[2], fw_size[2]);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for 0xf2, "
+ "fw_size[2]: %d, fw_buf[2]: 0x%02x\n",
+ __func__, fw_size[2],
+ (unsigned int)(fw_buf[2]));
+ err = -EIO;
+ goto out;
+ }
+ msleep(100);
+
+ /* pr_debug("ce147_update_fw: i2c_write for 0xf2, fw_size[2]: %d,
+ fw_buf[2]: 0x%02x\n", fw_size[2], fw_buf[2]); */
+
+ packet_num = *(fw_buf[2]) + (*(fw_buf[2] + 1) << 8);
+
+ /* pr_debug("ce147_update_fw: packet_num: %d\n", packet_num); */
+
+ j = 0;
+
+ /* [5] update firmware */
+ for (l = 0; l < packet_num; l++) {
+ memcpy(&data2[0], fw_buf[3] + j, packet_size);
+ err = ce147_i2c_write_multi(client, CMD_FW_UPDATE,
+ data2, packet_size);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: fail: i2c_read "
+ "for 0xf4, data:2 0x%02x\n",
+ __func__, data2[0]);
+ err = -EIO;
+ goto out;
+ }
+
+ /* pr_debug("ce147_update_fw: i2c_write for 0xf4, "
+ "data2: 0x%02x, count: %d\n", data2[0], l); */
+
+ msleep(10);
+ j += 129;
+ }
+
+ l = 0;
+ /* [6] get fw status */
+ do {
+ msleep(100);
+
+ err = ce147_i2c_read_multi(client, CMD_FW_STATUS,
+ NULL, 0, &res, 1);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: fail: i2c_read for 0xf5",
+ __func__);
+ err = -EIO;
+ goto out;
+ }
+ /* pr_debug("ce147_update_fw: i2c_read for 0xf5, "
+ "data: 0x%02x\n", res); */
+
+ l++;
+ if (l == 500)
+ break;
+ } while (res != 0x06);
+
+ vfree(mbuf);
+
+ err = ce147_power_en(0, sd);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: ce147_power_en(off)\n",
+ __func__);
+ return -EIO;
+ }
+
+ dev_err(&client->dev, "%s: ce147_power_en(off)\n", __func__);
+
+ return 0;
+out:
+ vfree(mbuf);
+
+ return err;
+}
+
+#else
+unsigned short *test[1];
+EXPORT_SYMBOL(test);
+extern void mDNIe_txtbuf_to_parsing(void);
+extern void mDNIe_txtbuf_to_parsing_for_lightsensor(void);
+extern void mDNIe_txtbuf_to_parsing_for_backlight(void);
+static int ce147_update_fw(struct v4l2_subdev *sd)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ce147_state *state = to_state(sd);
+ unsigned char *mbuf = NULL;
+ unsigned char *fw_buf[4];
+ int fw_size[4];
+ int index = 0;
+ int i = 0;
+ int err;
+
+ const unsigned int packet_size = 129; /* Data 128 + Checksum 1 */
+ unsigned int packet_num, k, j, l = 0;
+ unsigned char res = 0x00;
+ unsigned char data[129];
+ unsigned char data2[129];
+
+ /* dev_err(&client->dev, "%s: ce147_fw: buf = 0x%p, len = %d\n",
+ __func__, (void*)state->fw_info.addr,
+ state->fw_info.size); */
+
+ mbuf = vmalloc(state->fw_info.size);
+
+ if (!mbuf)
+ return -ENOMEM;
+
+ if (copy_from_user(mbuf, (void *)state->fw_info.addr,
+ state->fw_info.size)) {
+ vfree(mbuf);
+ return -EFAULT;
+ }
+
+ /* The firmware buffer is now copied to mbuf,
+ * so the firmware code is now in mbuf.
+ * We can use mbuf with i2c_tranfer call */
+ for (i = 0; i < 4; i++) {
+ if (index > state->fw_info.size - 4) {
+ dev_err(&client->dev, "%s:Error size parameter\n",
+ __func__);
+ break;
+ }
+ memcpy(fw_size + i, mbuf + index, 4);
+ index += 4;
+ fw_buf[i] = mbuf + index;
+ index += ((fw_size[i] - 1) & (~0x3)) + 4;
+ dev_err(&client->dev, "%s: [%d] fw_size = %d, fw_buf = 0x%p\n",
+ __func__, i, fw_size[i], fw_buf[i]);
+ }
+
+ test[0] = fw_buf[0];
+
+ for (j = 0; j < fw_size[0]; j++) {
+ pr_debug("ce147_update_fw: , fw_size[0]: %d, test[0]: 0x%x\n",
+ fw_size[0], test[0][j]);
+ test[0][j] = ((test[0][j] & 0xff00) >> 8) |
+ ((test[0][j] & 0x00ff) << 8);
+ pr_debug("ce147_update_fw: , test1[0]: 0x%x\n", test[0][j]);
+ }
+
+ /* for mdnie tuning */
+
+ mDNIe_txtbuf_to_parsing();
+ /* mDNIe_txtbuf_to_parsing_for_lightsensor(); */
+ /* mDNIe_txtbuf_to_parsing_for_backlight(); */
+
+ return 0;
+}
+#endif
+
+static int ce147_dump_fw(struct v4l2_subdev *sd)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ce147_state *state = to_state(sd);
+ unsigned char *mbuf = NULL;
+ unsigned char *fw_buf[4];
+ int fw_size[4];
+ int index = 0;
+ int i = 0;
+ int err;
+
+ const unsigned int packet_size = 129; /* Data 128 + Checksum 1 */
+ unsigned int packet_num, k, j = 0, l = 0;
+ unsigned char res = 0x00;
+ unsigned char data[129];
+ unsigned char data2[130];
+ unsigned char addr[4] = { 0x03, 0x00, 0x00, 0x01 };
+ unsigned int addr_len = 4;
+ unsigned char dump[1] = { 0x00 };
+
+ /* dev_err(&client->dev, "%s: ce147_fw: buf = 0x%p, len = %d\n",
+ __func__, (void*)state->fw_info.addr, state->fw_info.size); */
+
+ mbuf = vmalloc(state->fw_info.size);
+
+ if (NULL == mbuf)
+ return -ENOMEM;
+
+ if (copy_from_user(mbuf, (void *)state->fw_info.addr,
+ state->fw_info.size)) {
+ err = -EFAULT;
+ goto out;
+ }
+
+ /* The firmware buffer is now copied to mbuf,
+ * so the firmware code is now in mbuf.
+ * We can use mbuf with i2c_tranfer call */
+ for (i = 0; i < 4; i++) {
+ if (index > state->fw_info.size - 4) {
+ dev_err(&client->dev, "%s:Error size parameter\n",
+ __func__);
+ break;
+ }
+ memcpy(fw_size+i, mbuf + index, 4);
+ index += 4;
+ fw_buf[i] = mbuf + index;
+ index += ((fw_size[i] - 1) & (~0x3)) + 4;
+ dev_err(&client->dev, "%s: [%d] fw_size = %d, fw_buf = 0x%p\n",
+ __func__, i, fw_size[i], fw_buf[i]);
+ }
+
+ err = ce147_power_en(1, sd);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: ce147_power_en(on)\n",
+ __func__);
+ err = -EIO;
+ goto out;
+ }
+
+ msleep(100);
+
+ /* [1] set fw updater info */
+ err = ce147_i2c_write_multi(client, CMD_FW_INFO, fw_buf[0], 4);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for 0xf2, "
+ "fw_size[0]: %d, fw_buf[0]: 0x%02x\n",
+ __func__, fw_size[0],
+ (unsigned int)(fw_buf[0]));
+ err = -EIO;
+ goto out;
+ }
+ msleep(100);
+
+ /* pr_debug("ce147_update_fw: i2c_write for 0xf2, fw_size[0]: %d, "
+ "fw_buf[0]: 0x%02x\n", fw_size[0], fw_buf[0]); */
+
+ packet_num = *(fw_buf[0]) + (*(fw_buf[0] + 1) << 8);
+
+ /* [2] update firmware */
+ for (k = 0; k < packet_num; k++) {
+ memcpy(&data[0], fw_buf[1] + j, packet_size);
+ err = ce147_i2c_read_multi(client, CMD_FWU_UPDATE,
+ data, packet_size, &res, 1);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: fail: i2c_read for 0xf3, "
+ "data: 0x%02x\n", __func__, data[0]);
+ err = -EIO;
+ goto out;
+ }
+ msleep(10);
+ j += 129;
+ /* pr_debug("ce147_update_fw: i2c_read for 0xf3, data: 0x%02x, "
+ "count: %d\n", data[0], k); */
+ }
+
+ k = 0;
+ /* [3] get fw status */
+ do {
+ msleep(100);
+
+ err = ce147_i2c_read_multi(client, CMD_FW_STATUS, NULL, 0,
+ &res, 1);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: fail: i2c_read for 0xf5",
+ __func__);
+ err = -EIO;
+ goto out;
+ }
+ /* pr_debug("ce147_update_fw: i2c_read for 0xf5, "
+ "data: 0x%02x\n", res); */
+
+ k++;
+ if (k == 500)
+ break;
+ } while (res != 0x05);
+
+ msleep(500);
+
+ /* [4] change from dump mode */
+ err = ce147_i2c_write_multi(client, CMD_FW_DUMP, dump, 1);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for 0xfb, 0x00",
+ __func__);
+ err = -EIO;
+ goto out;
+ }
+ msleep(100);
+
+ dump[0] = 0x02;
+
+ /* [5] check fw mode is in dump mode */
+ err = ce147_i2c_read_multi(client, CMD_FW_DUMP, dump, 1, &res, 1);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: fail: i2c_read for 0xfb", __func__);
+ err = -EIO;
+ goto out;
+ }
+
+ if (res != 1) {
+ dev_err(&client->dev, "%s: fail: res is %x", __func__, res);
+ err = -EIO;
+ goto out;
+ }
+
+ msleep(100);
+
+ /* [6] set dump start address */
+ err = ce147_i2c_write_multi(client, CMD_FW_DUMP, addr, addr_len);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for 0xfb, 0x03",
+ __func__);
+ err = -EIO;
+ goto out;
+ }
+ msleep(100);
+
+ j = 0;
+
+ packet_num = *(fw_buf[2]) + (*(fw_buf[2] + 1) << 8);
+ /* pr_debug("ce147_update_fw: i2c_read for 0xfb, packet_num: %d\n",
+ packet_num); */
+
+ dump[0] = 0x04;
+
+ /* [7] dump firmware data */
+ for (l = 0; l < packet_num; l++) {
+ err = ce147_i2c_read_multi(client, CMD_FW_DUMP, dump, 1,
+ data2, packet_size + 1);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: fail: i2c_read for 0xfb, "
+ "0x04\n", __func__);
+ err = -EIO;
+ goto out;
+ }
+ memcpy(fw_buf[3] + j, &data2[0], packet_size - 1);
+
+ msleep(10);
+ j += 129;
+ /* pr_debug("ce147_update_fw: i2c_read for 0xfb, count: %d\n",
+ l); */
+ }
+
+ state->fw_dump_size = packet_num * packet_size;
+
+ if (copy_to_user((void *)(state->fw_info.addr), fw_buf[3],
+ state->fw_dump_size)) {
+ err = -EIO;
+ goto out;
+ }
+
+ vfree(mbuf);
+
+ err = ce147_power_en(0, sd);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: ce147_power_en(off)\n",
+ __func__);
+ return -EIO;
+ }
+
+ dev_err(&client->dev, "%s: ce147_power_en(off)\n", __func__);
+
+ return 0;
+out:
+ vfree(mbuf);
+
+ return err;
+}
+
+static int ce147_check_dataline(struct v4l2_subdev *sd)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ unsigned char ce147_buf_check_dataline[2] = { 0x01, 0x01 };
+ unsigned int ce147_len_check_dataline = 2;
+
+ err = ce147_i2c_write_multi(client, CMD_CHECK_DATALINE,
+ ce147_buf_check_dataline, ce147_len_check_dataline);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for "
+ "check_dataline\n", __func__);
+ return -EIO;
+ }
+
+ ce147_msg(&client->dev, "%s: done\n", __func__);
+
+ return 0;
+}
+
+static int ce147_check_dataline_stop(struct v4l2_subdev *sd)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ unsigned char ce147_buf_check_dataline[2] = { 0x00, 0x00 };
+ unsigned int ce147_len_check_dataline = 2;
+
+ err = ce147_i2c_write_multi(client, CMD_CHECK_DATALINE,
+ ce147_buf_check_dataline, ce147_len_check_dataline);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for "
+ "check_dataline stop\n", __func__);
+ return -EIO;
+ }
+
+ ce147_msg(&client->dev, "%s: done\n", __func__);
+
+ return 0;
+}
+
+static int ce147_set_preview_size(struct v4l2_subdev *sd)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ce147_state *state = to_state(sd);
+ int index = state->framesize_index;
+ /* Default VGA resolution = { 0x04, 0x01 } */
+ unsigned char ce147_regbuf_preview_size[2] = { 0x04, 0x01 };
+ unsigned int ce147_reglen_preview_size = 2;
+ unsigned char ce147_regbuf_hd_preview[1] = { 0x00 };
+ unsigned int ce147_reglen_hd_preview = 1;
+
+ ce147_msg(&client->dev, "%s: index = %d\n", __func__, index);
+
+ switch (index) {
+ case CE147_PREVIEW_QCIF:
+ ce147_regbuf_preview_size[0] = 0x1E;
+ break;
+ case CE147_PREVIEW_QVGA:
+ ce147_regbuf_preview_size[0] = 0x02;
+ break;
+
+ case CE147_PREVIEW_592x480:
+ ce147_regbuf_preview_size[0] = 0x24;
+ break;
+
+ case CE147_PREVIEW_VGA:
+ ce147_regbuf_preview_size[0] = 0x04;
+ break;
+ case CE147_PREVIEW_WVGA:
+ ce147_regbuf_preview_size[0] = 0x13;
+ break;
+ case CE147_PREVIEW_D1:
+ ce147_regbuf_preview_size[0] = 0x20;
+ break;
+ case CE147_PREVIEW_720P:
+ ce147_regbuf_preview_size[0] = 0x16;
+ ce147_regbuf_preview_size[1] = 0x02;
+ break;
+ case CE147_PREVIEW_VERTICAL_QCIF:
+ ce147_regbuf_preview_size[0] = 0x26;
+ break;
+ default:
+ /* When running in image capture mode, the call comes here.
+ * Set the default video resolution - CE147_PREVIEW_VGA
+ */
+ ce147_msg(&client->dev, "Setting preview resoution as VGA "
+ "for image capture mode\n");
+ break;
+ }
+
+ if (index == CE147_PREVIEW_720P) {
+ ce147_regbuf_hd_preview[0] = 0x01;
+ state->hd_preview_on = 1;
+ pr_info("%s: preview_size is HD (%d)\n",
+ __func__, state->hd_preview_on);
+ err = ce147_i2c_write_multi(client, CMD_HD_PREVIEW,
+ ce147_regbuf_hd_preview,
+ ce147_reglen_hd_preview);
+ if (err < 0)
+ return -EIO;
+ } else {
+ state->hd_preview_on = 0;
+ pr_info("%s: preview_size is not HD (%d)\n",
+ __func__, state->hd_preview_on);
+ err = ce147_i2c_write_multi(client, CMD_HD_PREVIEW,
+ ce147_regbuf_hd_preview,
+ ce147_reglen_hd_preview);
+ if (err < 0)
+ return -EIO;
+ }
+ mdelay(5);
+
+ err = ce147_i2c_write_multi(client, CMD_PREVIEW_SIZE,
+ ce147_regbuf_preview_size, ce147_reglen_preview_size);
+ if (err < 0) {
+ pr_info("%s: preview_size is not HD (%d)\n",
+ __func__, state->hd_preview_on);
+ return -EIO;
+ }
+
+ ce147_msg(&client->dev, "Done\n");
+
+ return err;
+}
+
+static int ce147_set_frame_rate(struct v4l2_subdev *sd)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ce147_state *state = to_state(sd);
+
+ unsigned char ce147_regbuf_fps[2] = { 0x1E, 0x00 };
+ unsigned int ce147_reglen_fps = 2;
+
+ switch (state->fps) {
+ case FRAME_RATE_7:
+ ce147_regbuf_fps[0] = 0x07;
+ break;
+
+ case FRAME_RATE_10:
+ ce147_regbuf_fps[0] = 0x0A;
+ break;
+
+ case FRAME_RATE_15:
+ ce147_regbuf_fps[0] = 0x0F;
+ break;
+
+ case FRAME_RATE_20:
+ ce147_regbuf_fps[0] = 0x14;
+ break;
+
+ case FRAME_RATE_30:
+ ce147_regbuf_fps[0] = 0x1E;
+ break;
+
+ case FRAME_RATE_60:
+ ce147_regbuf_fps[0] = 0x3C;
+ break;
+
+ case FRAME_RATE_120:
+ ce147_regbuf_fps[0] = 0x78;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ err = ce147_i2c_write_multi(client, CMD_FPS, ce147_regbuf_fps,
+ ce147_reglen_fps);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write "
+ "for set_frame_rate\n", __func__);
+ return -EIO;
+ }
+#if 0 /* remove batch */
+ err = ce147_get_batch_reflection_status(sd);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: ce147_get_batch_reflection"
+ "_status for set_frame_rate\n", __func__);
+ return -EIO;
+ }
+#endif
+ ce147_msg(&client->dev, "%s: done\n", __func__);
+
+ return 0;
+}
+
+static int ce147_set_anti_banding(struct v4l2_subdev *sd)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ce147_state *state = to_state(sd);
+
+ unsigned char ce147_regbuf_anti_banding[1] = { 0x02 };
+ unsigned int ce147_reglen_anti_banding = 1;
+
+ switch (state->anti_banding) {
+ case ANTI_BANDING_OFF:
+ ce147_regbuf_anti_banding[0] = 0x00;
+ break;
+
+ case ANTI_BANDING_AUTO:
+ ce147_regbuf_anti_banding[0] = 0x01;
+ break;
+
+ case ANTI_BANDING_50HZ:
+ ce147_regbuf_anti_banding[0] = 0x02;
+ break;
+
+ case ANTI_BANDING_60HZ:
+ default:
+ ce147_regbuf_anti_banding[0] = 0x03;
+ break;
+ }
+
+ err = ce147_i2c_write_multi(client, CMD_SET_ANTI_BANDING,
+ ce147_regbuf_anti_banding, ce147_reglen_anti_banding);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for "
+ "anti_banding\n", __func__);
+ return -EIO;
+ }
+
+ ce147_msg(&client->dev, "%s: done\n", __func__);
+
+ return 0;
+}
+
+static int ce147_set_preview_stop(struct v4l2_subdev *sd)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ce147_state *state = to_state(sd);
+ int ce147_reglen_preview = 1;
+ unsigned char ce147_regbuf_preview_stop[1] = { 0x00 };
+ int err;
+
+ /* pr_debug("%s: (%d)\n", __func__, state->runmode); */
+
+ if (CE147_RUNMODE_RUNNING == state->runmode) {
+ err = ce147_i2c_write_multi(client, CMD_PREVIEW,
+ ce147_regbuf_preview_stop,
+ ce147_reglen_preview);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write "
+ "for preview_stop\n", __func__);
+ return -EIO;
+ }
+
+ err = ce147_waitfordone_timeout(client, CMD_PREVIEW_STATUS,
+ 0x00, 3000, POLL_TIME_MS);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: Wait for preview_stop "
+ "failed\n", __func__);
+ return err;
+ }
+ ce147_msg(&client->dev, "%s: preview_stop - wait time %d ms\n",
+ __func__, err);
+
+ state->runmode = CE147_RUNMODE_READY;
+ }
+ return 0;
+}
+
+static int ce147_set_dzoom(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ struct ce147_state *state = to_state(sd);
+ int err;
+ int count;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ unsigned char ce147_buf_get_dzoom_status[2] = { 0x00, 0x00 };
+ unsigned int ce147_len_get_dzoom_status = 2;
+
+ if (CE147_RUNMODE_RUNNING == state->runmode) {
+ err = ce147_i2c_write_multi(client, CMD_SET_DZOOM,
+ &ce147_buf_set_dzoom[ctrl->value], 1);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write "
+ "for set_dzoom\n", __func__);
+ return -EIO;
+ }
+
+ /* TODO: This code needs to use
+ * ce147_waitfordone_timeout() API
+ */
+ for (count = 0; count < 300; count++) {
+ err = ce147_i2c_read_multi(client, CMD_GET_DZOOM_LEVEL,
+ NULL, 0, ce147_buf_get_dzoom_status,
+ ce147_len_get_dzoom_status);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_read "
+ "for set_dzoom\n", __func__);
+ return -EIO;
+ }
+ if (ce147_buf_get_dzoom_status[1] == 0x00)
+ break;
+ }
+ }
+
+ DZoom_State = ctrl->value;
+
+ ce147_msg(&client->dev, "%s: done\n", __func__);
+
+ return 0;
+}
+
+static int ce147_set_preview_start(struct v4l2_subdev *sd)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ce147_state *state = to_state(sd);
+ struct v4l2_control ctrl;
+ int ce147_reglen_preview = 1;
+ unsigned char ce147_regbuf_preview_start[1] = { 0x01 };
+
+ int count;
+ unsigned char ce147_buf_get_dzoom_status[2] = { 0x00, 0x00 };
+ unsigned int ce147_len_get_dzoom_status = 2;
+
+ if (!state->pix.width || !state->pix.height || !state->fps)
+ return -EINVAL;
+
+ /* This is for 15 testmode */
+ if (state->check_dataline) {
+ err = ce147_check_dataline(sd);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: Could not check data"
+ "line.\n", __func__);
+ return -EIO;
+ }
+ } else { /* Normal preview sequence */
+ /* Stop it if it is already running */
+ err = ce147_set_preview_stop(sd);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: Could not stop the "
+ "running preview.\n", __func__);
+ return -EIO;
+ }
+
+ err = ce147_set_preview_size(sd);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: Could not set "
+ "preview size\n", __func__);
+ return -EIO;
+ }
+
+ if (DZoom_State != 0) {
+ err = ce147_i2c_write_multi(client, CMD_SET_DZOOM,
+ &ce147_buf_set_dzoom[DZoom_State], 1);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write "
+ "for set_dzoom in "
+ "preview_start\n", __func__);
+ return -EIO;
+ }
+
+ for (count = 0; count < 300; count++) {
+ err = ce147_i2c_read_multi(client,
+ CMD_GET_DZOOM_LEVEL, NULL, 0,
+ ce147_buf_get_dzoom_status,
+ ce147_len_get_dzoom_status);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: "
+ "i2c_read for set_dzoom"
+ "in preview_start\n",
+ __func__);
+ return -EIO;
+ }
+ if (ce147_buf_get_dzoom_status[1] == 0x00)
+ break;
+ }
+ }
+
+ err = ce147_set_anti_banding(sd);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: Could not set anti "
+ "banding\n", __func__);
+ return -EIO;
+ }
+
+ err = ce147_set_frame_rate(sd);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: Could not set fps\n",
+ __func__);
+ return -EIO;
+ }
+
+ if (state->runmode != CE147_RUNMODE_READY) {
+ /* iso */
+ ctrl.value = state->iso;
+ err = ce147_set_iso(sd, &ctrl);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: ce147_set_"
+ "iso, err %d\n", __func__, err);
+ return -EIO;
+ }
+
+ /* metering */
+ ctrl.value = state->metering;
+ err = ce147_set_metering(sd, &ctrl);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: ce147_set_"
+ "metering, err %d\n",
+ __func__, err);
+ return -EIO;
+ }
+
+ /* ev */
+ ctrl.value = state->ev;
+ err = ce147_set_ev(sd, &ctrl);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: ce147_set_"
+ "ev, err %d\n", __func__, err);
+ return -EIO;
+ }
+
+ /* effect */
+ ctrl.value = state->effect;
+ err = ce147_set_effect(sd, &ctrl);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: ce147_set_"
+ "effect, err %d\n",
+ __func__, err);
+ return -EIO;
+ }
+
+ /* wb */
+ ctrl.value = state->wb;
+ err = ce147_set_white_balance(sd, &ctrl);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: ce147_set_"
+ "white_balance, err %d\n",
+ __func__, err);
+ return -EIO;
+ }
+ }
+ /* slow ae */
+ ctrl.value = state->hd_slow_ae;
+ err = ce147_set_slow_ae(sd, &ctrl);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: ce147_set_slow_ae, "
+ "err %d\n", __func__, err);
+ return -EIO;
+ }
+
+ /* RGB gamma */
+ ctrl.value = state->hd_gamma;
+ err = ce147_set_gamma(sd, &ctrl);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: ce147_set_gamma, "
+ "err %d\n", __func__, err);
+ return -EIO;
+ }
+
+ /* batch reflection */
+ err = ce147_get_batch_reflection_status(sd);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: ce147_get_batch_"
+ "reflection_status for "
+ "set_frame_rate\n", __func__);
+ return -EIO;
+ }
+
+ /* Release AWB unLock */
+ err = ce147_set_awb_lock(sd, 0);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: ce147_set_awb_lock, "
+ "err %d\n", __func__, err);
+ return -EIO;
+ }
+
+ /* Start preview */
+ err = ce147_i2c_write_multi(client, CMD_PREVIEW,
+ ce147_regbuf_preview_start,
+ ce147_reglen_preview);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for "
+ "preview_start\n", __func__);
+ return -EIO;
+ }
+
+ err = ce147_waitfordone_timeout(client, CMD_PREVIEW_STATUS,
+ 0x08, 3000, POLL_TIME_MS);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: Wait for preview_start "
+ "failed\n", __func__);
+ return err;
+ }
+ ce147_msg(&client->dev, "%s: preview_start - wait time %d ms\n",
+ __func__, err);
+ }
+
+ state->runmode = CE147_RUNMODE_RUNNING;
+
+ return 0;
+}
+
+static int ce147_set_capture_size(struct v4l2_subdev *sd)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ce147_state *state = to_state(sd);
+
+ int index = state->framesize_index;
+ /* Default 5 MP = { 0x08, 0x00, 0x01, 0x00 } */
+ unsigned char ce147_regbuf_capture_size[4] = { 0x0B, 0x00, 0x01, 0x00 };
+ unsigned int ce147_reglen_capture_size = 4;
+
+ switch (index) {
+ case CE147_CAPTURE_VGA: /* 640x480 */
+ ce147_regbuf_capture_size[0] = 0x04;
+ break;
+ case CE147_CAPTURE_WVGA: /* 800x480 */
+ ce147_regbuf_capture_size[0] = 0x13;
+ break;
+ case CE147_CAPTURE_W1MP: /* 1600x960 */
+ ce147_regbuf_capture_size[0] = 0x0E;
+ break;
+ case CE147_CAPTURE_2MP: /* 1600x1200 */
+ ce147_regbuf_capture_size[0] = 0x08;
+ break;
+ case CE147_CAPTURE_W2MP: /* 2048x1232 */
+ ce147_regbuf_capture_size[0] = 0x0F;
+ break;
+ case CE147_CAPTURE_3MP: /* 2048x1536 */
+ ce147_regbuf_capture_size[0] = 0x09;
+ break;
+ case CE147_CAPTURE_W4MP: /* 2560x1536 */
+ ce147_regbuf_capture_size[0] = 0x15;
+ break;
+ case CE147_CAPTURE_5MP: /* 2560x1920 */
+ ce147_regbuf_capture_size[0] = 0x0B;
+ break;
+ default:
+ /* The framesize index was not set properly.
+ * Check s_fmt call - it must be for video mode. */
+ return -EINVAL;
+ }
+
+ /* Set capture image size */
+ err = ce147_i2c_write_multi(client, CMD_CAPTURE_SIZE,
+ ce147_regbuf_capture_size, ce147_reglen_capture_size);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write "
+ "for capture_resolution\n", __func__);
+ return -EIO;
+ }
+
+ /* This is for postview */
+ if (ce147_regbuf_capture_size[0] < 0x0C) {
+ state->preview_size = CE147_PREVIEW_VGA;
+ /* pr_debug("%s: preview_size is VGA (%d)\n",
+ __func__, state->preview_size); */
+ } else {
+ state->preview_size = CE147_PREVIEW_WVGA;
+ /* pr_debug("%s: preview_size is WVGA (%d)\n",
+ __func__, state->preview_size); */
+ }
+
+ /* pr_debug("%s: 0x%02x\n", __func__, index); */
+
+ return 0;
+}
+
+static int ce147_set_ae_awb(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ unsigned char ce147_buf_set_ae_awb[1] = { 0x00 };
+
+ switch (ctrl->value) {
+ case AE_LOCK_AWB_UNLOCK:
+ ce147_buf_set_ae_awb[0] = 0x01;
+ break;
+
+ case AE_UNLOCK_AWB_LOCK:
+ ce147_buf_set_ae_awb[0] = 0x10;
+ break;
+
+ case AE_LOCK_AWB_LOCK:
+ ce147_buf_set_ae_awb[0] = 0x11;
+ break;
+
+ case AE_UNLOCK_AWB_UNLOCK:
+ default:
+ ce147_buf_set_ae_awb[0] = 0x00;
+ break;
+ }
+ err = ce147_i2c_write_multi(client, CMD_AE_WB_LOCK,
+ ce147_buf_set_ae_awb, 1);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for set_effect\n",
+ __func__);
+ return -EIO;
+ }
+
+ ce147_msg(&client->dev, "%s: done\n", __func__);
+
+ return 0;
+}
+
+/**
+ * lock: 1 to lock, 0 to unlock
+ */
+static int ce147_set_awb_lock(struct v4l2_subdev *sd, int lock)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ unsigned char ce147_regbuf_awb_lock[1] = { 0x11 };
+ unsigned int ce147_reglen_awb_lock = 1;
+
+ if (lock)
+ ce147_regbuf_awb_lock[0] = 0x11;
+ else
+ ce147_regbuf_awb_lock[0] = 0x00;
+
+ err = ce147_i2c_write_multi(client, CMD_AE_WB_LOCK,
+ ce147_regbuf_awb_lock, ce147_reglen_awb_lock);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for awb_lock\n",
+ __func__);
+ return -EIO;
+ }
+
+ ce147_msg(&client->dev, "%s: done\n", __func__);
+
+ return 0;
+}
+
+static int ce147_set_capture_cmd(struct v4l2_subdev *sd)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ unsigned char ce147_regbuf_buffering_capture[1] = { 0x00 };
+ unsigned int ce147_reglen_buffering_capture = 1;
+
+ err = ce147_i2c_write_multi(client, CMD_BUFFERING_CAPTURE,
+ ce147_regbuf_buffering_capture,
+ ce147_reglen_buffering_capture);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write "
+ "for buffering_capture\n", __func__);
+ return -EIO;
+ }
+
+ ce147_msg(&client->dev, "%s: done\n", __func__);
+
+ return 0;
+}
+static int ce147_set_exif_ctrl(struct v4l2_subdev *sd , int onoff)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ce147_state *state = to_state(sd);
+
+ unsigned char ce147_regbuf_exif_ctrl[2] = { 0x10, 0x00 };
+ unsigned int ce147_reglen_exif_ctrl = 2;
+
+ if ((onoff == 0) && (state->thumb_null == 0))
+ ce147_regbuf_exif_ctrl[1] = 0x00;
+ else if ((onoff == 1) && (state->thumb_null == 0))
+ ce147_regbuf_exif_ctrl[1] = 0x01;
+ else if ((onoff == 0) && (state->thumb_null == 0))
+ ce147_regbuf_exif_ctrl[1] = 0x02;
+ else if ((onoff == 0) && (state->thumb_null == 1))
+ ce147_regbuf_exif_ctrl[1] = 0x03;
+ else if ((onoff == 1) && (state->thumb_null == 1))
+ ce147_regbuf_exif_ctrl[1] = 0x04;
+
+ err = ce147_i2c_write_multi(client, CMD_SET_EXIF_CTRL,
+ ce147_regbuf_exif_ctrl, ce147_reglen_exif_ctrl);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write "
+ "for ce147_reglen_exif_ctrl\n", __func__);
+ return -EIO;
+ }
+
+ ce147_msg(&client->dev, "%s: done\n", __func__);
+
+ return 0;
+}
+
+static int ce147_set_capture_exif(struct v4l2_subdev *sd)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ce147_state *state = to_state(sd);
+
+ struct rtc_time gps_timestamp;
+
+ unsigned char ce147_regbuf_exif[7] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ unsigned int ce147_reglen_exif = 7;
+
+ unsigned char ce147_regbuf_timestamp[7] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ unsigned int ce147_reglen_timestamp = 7;
+
+ unsigned char ce147_regbuf_rot[1] = { 0x01 };
+ unsigned int ce147_reglen_rot = 1;
+
+ unsigned char ce147_model_name[130] = { 0x00, };
+ unsigned int ce147_reglen_model = 130;
+
+ unsigned char ce147_gps_processing[130] = { 0x00, };
+ unsigned int ce147_reglen_gps_processing = 130;
+#if !defined(CONFIG_ARIES_NTT)
+ unsigned char ce147_str_model[9] = "GT-I9000\0";
+#elif defined(CONFIG_SAMSUNG_FASCINATE)
+ unsigned char ce147_str_model[9] = "SCH-I500\0";
+#else /* Modify NTTS1 */
+ unsigned char ce147_str_model[7] = "SC-02B\0";
+#endif
+#if 0
+ struct timeval curr_time;
+ struct rtc_time time;
+#endif
+ ce147_model_name[0] = 0x06;
+ ce147_model_name[1] = 0x09;
+
+ memcpy(ce147_model_name + 2, ce147_str_model, sizeof(ce147_str_model));
+
+ ce147_gps_processing[0] = 0x10;
+ ce147_gps_processing[1] = 0x32;
+
+ memcpy(ce147_gps_processing + 2, state->gpsInfo.gps_processingmethod,
+ sizeof(state->gpsInfo.gps_processingmethod));
+
+#if 0
+ do_gettimeofday(&curr_time);
+ rtc_time_to_tm(curr_time.tv_sec, &time);
+
+ time.tm_year += 1900;
+ time.tm_mon += 1;
+
+ ce147_regbuf_exif[0] = (time.tm_year & 0x00FF);
+ ce147_regbuf_exif[1] = (time.tm_year & 0xFF00) >> 8;
+ ce147_regbuf_exif[2] = time.tm_mon;
+ ce147_regbuf_exif[3] = time.tm_mday;
+ ce147_regbuf_exif[4] = time.tm_hour;
+ ce147_regbuf_exif[5] = time.tm_min;
+ ce147_regbuf_exif[6] = time.tm_sec;
+#else
+ state->exifTimeInfo->tm_year += 1900;
+ state->exifTimeInfo->tm_mon += 1;
+ ce147_regbuf_exif[0] = (state->exifTimeInfo->tm_year & 0x00FF);
+ ce147_regbuf_exif[1] = (state->exifTimeInfo->tm_year & 0xFF00) >> 8;
+ ce147_regbuf_exif[2] = state->exifTimeInfo->tm_mon;
+ ce147_regbuf_exif[3] = state->exifTimeInfo->tm_mday;
+ ce147_regbuf_exif[4] = state->exifTimeInfo->tm_hour;
+ ce147_regbuf_exif[5] = state->exifTimeInfo->tm_min;
+ ce147_regbuf_exif[6] = state->exifTimeInfo->tm_sec;
+#endif
+
+ rtc_time_to_tm(state->gpsInfo.gps_timeStamp, &gps_timestamp);
+ gps_timestamp.tm_year += 1900;
+ gps_timestamp.tm_mon += 1;
+
+ pr_debug("====!! Exif Time YEAR: %d, MONTH: %d, "
+ "DAY: %d, HOUR: %d, MIN: %d, SEC: %d\n",
+ gps_timestamp.tm_year, gps_timestamp.tm_mon,
+ gps_timestamp.tm_mday, gps_timestamp.tm_hour,
+ gps_timestamp.tm_min, gps_timestamp.tm_sec);
+
+ ce147_regbuf_timestamp[0] = (gps_timestamp.tm_year & 0x00FF);
+ ce147_regbuf_timestamp[1] = (gps_timestamp.tm_year & 0xFF00) >> 8;
+ ce147_regbuf_timestamp[2] = gps_timestamp.tm_mon;
+ ce147_regbuf_timestamp[3] = gps_timestamp.tm_mday;
+ ce147_regbuf_timestamp[4] = gps_timestamp.tm_hour;
+ ce147_regbuf_timestamp[5] = gps_timestamp.tm_min;
+ ce147_regbuf_timestamp[6] = gps_timestamp.tm_sec;
+
+
+ pr_debug("Exif Time YEAR: %ld, MONTH: %d, DAY: %d, "
+ "HOUR: %d, MIN: %d, SEC: %d\n",
+ state->exifTimeInfo->tm_year,
+ state->exifTimeInfo->tm_mon,
+ state->exifTimeInfo->tm_mday,
+ state->exifTimeInfo->tm_hour,
+ state->exifTimeInfo->tm_min,
+ state->exifTimeInfo->tm_sec);
+
+ ce147_regbuf_rot[0] = state->exif_orientation_info;
+
+ err = ce147_i2c_write_multi(client, CMD_INFO_MODEL, ce147_model_name,
+ ce147_reglen_model);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for exif model "
+ "name\n", __func__);
+ return -EIO;
+ }
+
+ err = ce147_i2c_write_multi(client, CMD_INFO_EXIF, ce147_regbuf_exif,
+ ce147_reglen_exif);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for exif\n",
+ __func__);
+ return -EIO;
+ }
+
+ err = ce147_i2c_write_multi(client, CMD_INFO_ROT, ce147_regbuf_rot,
+ ce147_reglen_rot);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for exif\n",
+ __func__);
+ return -EIO;
+ }
+
+ err = ce147_i2c_write_multi(client, CMD_INFO_LONGITUDE_LATITUDE,
+ state->gpsInfo.ce147_gps_buf,
+ sizeof(state->gpsInfo.ce147_gps_buf));
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for gps "
+ "longitude latitude\n", __func__);
+ return -EIO;
+ }
+
+ err = ce147_i2c_write_multi(client, CMD_INFO_ALTITUDE,
+ state->gpsInfo.ce147_altitude_buf,
+ sizeof(state->gpsInfo.ce147_altitude_buf));
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for gps "
+ "altitude\n", __func__);
+ return -EIO;
+ }
+
+ err = ce147_i2c_write_multi(client, CMD_GPS_TIMESTAMP,
+ ce147_regbuf_timestamp, ce147_reglen_timestamp);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for gps "
+ "timestamp\n", __func__);
+ return -EIO;
+ }
+
+ err = ce147_i2c_write_multi(client, CMD_INFO_MODEL,
+ ce147_gps_processing, ce147_reglen_gps_processing);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for gps method\n",
+ __func__);
+ return -EIO;
+ }
+
+ ce147_msg(&client->dev, "%s: done\n", __func__);
+
+ return 0;
+}
+
+static int ce147_set_jpeg_quality(struct v4l2_subdev *sd)
+{
+ struct ce147_state *state = to_state(sd);
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+#if 0
+ unsigned char ce147_regbuf_jpeg_comp_level[7] = {
+ 0x00, 0xF4, 0x01, 0x90, 0x01, 0x05, 0x01
+ };
+ unsigned int ce147_reglen_jpeg_comp_level = 7;
+
+ unsigned int comp_ratio = 1500;
+
+ int err;
+
+ if (state->jpeg.quality < 0)
+ state->jpeg.quality = 0;
+ if (state->jpeg.quality > 100)
+ state->jpeg.quality = 100;
+
+ comp_ratio -= (100 - state->jpeg.quality) * 10;
+ ce147_regbuf_jpeg_comp_level[1] = comp_ratio & 0xFF;
+ ce147_regbuf_jpeg_comp_level[2] = (comp_ratio & 0xFF00) >> 8;
+
+ ce147_msg(&client->dev, "Quality = %d, Max value = %d\n",
+ state->jpeg.quality, comp_ratio);
+
+ /* 10% range for final JPEG image size */
+ comp_ratio = (comp_ratio * 9) / 10;
+ ce147_regbuf_jpeg_comp_level[3] = comp_ratio & 0xFF;
+ ce147_regbuf_jpeg_comp_level[4] = (comp_ratio & 0xFF00) >> 8;
+
+ ce147_msg(&client->dev, "Quality = %d, Min Comp Ratio = %d\n",
+ state->jpeg.quality, comp_ratio);
+#endif
+
+ unsigned char ce147_regbuf_jpeg_comp_level[7] = {
+ 0x00, 0xA4, 0x06, 0x78, 0x05, 0x05, 0x01
+ };
+ unsigned int ce147_reglen_jpeg_comp_level = 7;
+ unsigned int quality = state->jpeg.quality;
+ unsigned int compressionRatio = 0;
+ unsigned int minimumCompressionRatio = 0;
+ int err;
+
+ if (quality >= 91 && quality <= 100) { /* 91 ~ 100 */
+ compressionRatio = 17; /* 17% */
+ } else if (quality >= 81 && quality <= 90) { /* 81 ~ 90 */
+ compressionRatio = 16; /* 16% */
+ } else if (quality >= 71 && quality <= 80) { /* 71 ~ 80 */
+ compressionRatio = 15; /* 15% */
+ } else if (quality >= 61 && quality <= 70) { /* 61 ~ 70 */
+ compressionRatio = 14; /* 14% */
+ } else if (quality >= 51 && quality <= 60) { /* 51 ~ 60 */
+ compressionRatio = 13; /* 13% */
+ } else if (quality >= 41 && quality <= 50) { /* 41 ~ 50 */
+ compressionRatio = 12; /* 12% */
+ } else if (quality >= 31 && quality <= 40) { /* 31 ~ 40 */
+ compressionRatio = 11; /* 11% */
+ } else if (quality >= 21 && quality <= 30) { /* 21 ~ 30 */
+ compressionRatio = 10; /* 10% */
+ } else if (quality >= 11 && quality <= 20) { /* 11 ~ 20 */
+ compressionRatio = 9; /* 9% */
+ } else if (quality >= 1 && quality <= 10) { /* 1 ~ 10 */
+ compressionRatio = 8; /* 8% */
+ } else {
+ dev_err(&client->dev, "%s: Invalid Quality(%d)\n",
+ __func__, quality);
+ return -1;
+ }
+
+ /* ex) if compression ratio is 17%, minimum compression ratio is 14%*/
+ minimumCompressionRatio = compressionRatio - 3;
+ ce147_regbuf_jpeg_comp_level[1] = (compressionRatio * 100) & 0xFF;
+ ce147_regbuf_jpeg_comp_level[2] = ((compressionRatio * 100) & 0xFF00)
+ >> 8;
+ ce147_regbuf_jpeg_comp_level[3] = (minimumCompressionRatio * 100)
+ & 0xFF;
+ ce147_regbuf_jpeg_comp_level[4] = ((minimumCompressionRatio * 100)
+ & 0xFF00) >> 8;
+
+ err = ce147_i2c_write_multi(client, CMD_JPEG_CONFIG,
+ ce147_regbuf_jpeg_comp_level,
+ ce147_reglen_jpeg_comp_level);
+
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for "
+ "jpeg_comp_level\n", __func__);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int ce147_set_jpeg_config(struct v4l2_subdev *sd)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ce147_state *state = to_state(sd);
+ int preview_size = state->preview_size;
+
+ unsigned char ce147_regbuf_set_lump[2] = { 0x00, 0x04};
+ unsigned int ce147_reglen_set_lump = 2;
+
+ /* unsigned char ce147_regbuf_set_lump2[1] = {0x00};
+ unsigned int ce147_reglen_set_lump2 = 1; */
+
+ err = ce147_set_jpeg_quality(sd);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: ce147_set_jpeg_quality\n",
+ __func__);
+ return -EIO;
+ }
+
+ if (preview_size != CE147_PREVIEW_VGA) {
+ /* pr_debug("[5B] ce147_set_jpeg_config: preview_size is WVGA "
+ "(%d)\n", preview_size); */
+ ce147_regbuf_set_lump[1] = 0x13;
+ }
+
+ /* if (!state->thumb_null) */
+ err = ce147_i2c_write_multi(client, CMD_JPEG_BUFFERING,
+ ce147_regbuf_set_lump, ce147_reglen_set_lump);
+ /* else if (state->thumb_null) */
+ /* err = ce147_i2c_write_multi(client, CMD_JPEG_BUFFERING2,
+ ce147_regbuf_set_lump2, ce147_reglen_set_lump2); */
+
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for set_lump\n",
+ __func__);
+ return -EIO;
+ }
+
+ ce147_msg(&client->dev, "%s: done\n", __func__);
+
+ return 0;
+}
+
+static int ce147_get_snapshot_data(struct v4l2_subdev *sd)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ce147_state *state = to_state(sd);
+
+ unsigned char cmd_buf_framesize[1] = { 0x00 };
+ unsigned int cmd_len_framesize = 1;
+
+ unsigned char cmd_buf_setdata[2] = { 0x02, 0x00 };
+ unsigned int cmd_len_setdata = 2;
+
+ unsigned char jpeg_status[3] = { 0x00, 0x00, 0x00 };
+ unsigned char jpeg_status_len = 3;
+
+ unsigned char jpeg_framesize[4] = { 0x00, 0x00, 0x00, 0x00 };
+ unsigned int jpeg_framesize_len = 4;
+
+ if (state->jpeg.enable) {
+ /* Get main JPEG size */
+ cmd_buf_framesize[0] = 0x00;
+ err = ce147_i2c_read_multi(client, CMD_JPEG_SIZE,
+ cmd_buf_framesize, cmd_len_framesize,
+ jpeg_framesize, jpeg_framesize_len);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_read for "
+ "jpeg_framesize\n", __func__);
+ return -EIO;
+ }
+ state->jpeg.main_size = jpeg_framesize[1]
+ | (jpeg_framesize[2] << 8)
+ | (jpeg_framesize[3] << 16);
+
+ ce147_info(&client->dev, "%s: JPEG main filesize = %d bytes\n",
+ __func__, state->jpeg.main_size);
+
+ /* Get Thumbnail size */
+ if (!state->thumb_null) {
+ cmd_buf_framesize[0] = 0x01;
+ err = ce147_i2c_read_multi(client, CMD_JPEG_SIZE,
+ cmd_buf_framesize, cmd_len_framesize,
+ jpeg_framesize, jpeg_framesize_len);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_read "
+ "for jpeg_framesize\n",
+ __func__);
+ return -EIO;
+ }
+ state->jpeg.thumb_size = jpeg_framesize[1]
+ | (jpeg_framesize[2] << 8)
+ | (jpeg_framesize[3] << 16);
+ } else
+ state->jpeg.thumb_size = 0;
+
+ ce147_msg(&client->dev, "%s: JPEG thumb filesize = %d bytes\n",
+ __func__, state->jpeg.thumb_size);
+
+ state->jpeg.main_offset = 0;
+ state->jpeg.thumb_offset = 0x271000;
+ state->jpeg.postview_offset = 0x280A00;
+ }
+
+ if (state->jpeg.enable)
+ cmd_buf_setdata[0] = 0x02;
+ else
+ cmd_buf_setdata[0] = 0x01;
+ /* Set Data out */
+ err = ce147_i2c_read_multi(client, CMD_SET_DATA,
+ cmd_buf_setdata, cmd_len_setdata,
+ jpeg_status, jpeg_status_len);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_read for set_data\n",
+ __func__);
+ return -EIO;
+ }
+ ce147_msg(&client->dev, "%s:JPEG framesize (after set_data_out) = "
+ "0x%02x.%02x.%02x\n", __func__,
+ jpeg_status[2], jpeg_status[1], jpeg_status[0]);
+
+ /* 0x66 */
+ err = ce147_i2c_read_multi(client, CMD_DATA_OUT_REQ, NULL, 0,
+ jpeg_status, jpeg_status_len);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_read for "
+ "set_data_request\n", __func__);
+ return -EIO;
+ }
+ ce147_msg(&client->dev, "%s:JPEG framesize (after set_data_request) "
+ "= 0x%02x.%02x.%02x\n", __func__,
+ jpeg_status[2], jpeg_status[1], jpeg_status[0]);
+
+ ce147_msg(&client->dev, "%s: done\n", __func__);
+
+ return 0;
+}
+
+static int ce147_set_capture_config(struct v4l2_subdev *sd,
+ struct v4l2_control *ctrl)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ /*
+ * 1. Set image size
+ */
+ err = ce147_set_capture_size(sd);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for "
+ "capture_resolution\n", __func__);
+ return -EIO;
+ }
+
+ /*
+ * Set DZoom
+ */
+ if (DZoom_State != 0) {
+ ctrl->value = DZoom_State;
+ err = ce147_set_dzoom(sd, ctrl);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: Could not set Zoom "
+ "in Capture_start\n", __func__);
+ return -EIO;
+ }
+ }
+
+#ifdef CONFIG_SAMSUNG_FASCINATE
+ /*
+ * Set Flash
+ */
+ err = ce147_set_awb_lock(sd, 0);
+ if(err < 0){
+ dev_err(&client->dev, "%s: failed: ce147_set_awb_lock, err %d\n", __func__, err);
+ return -EIO;
+ }
+ ce147_set_preflash(sd, 1);
+#endif
+
+ /*
+ * Set AWB Lock
+ */
+ err = ce147_set_awb_lock(sd, 1);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: ce147_set_awb_lock, "
+ "err %d\n", __func__, err);
+ return -EIO;
+ }
+ /*
+ * 2. Set Capture Command
+ */
+ err = ce147_set_capture_cmd(sd);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: set_capture_cmd failed\n",
+ __func__);
+ return err;
+ }
+
+ return 0;
+}
+
+static int ce147_set_capture_start(struct v4l2_subdev *sd,
+ struct v4l2_control *ctrl)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ce147_state *state = to_state(sd);
+
+ /*
+ * Right after ce147_set_capture_config,
+ * 3. Wait for capture to complete for ce147_set_capture_cmd()
+ * in ce147_set_capture_config()
+ */
+ err = ce147_waitfordone_timeout(client, 0x6C, 0x00, 3000, POLL_TIME_MS);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: Wait for "
+ "buffering_capture\n", __func__);
+ return err;
+ }
+ ce147_msg(&client->dev, "%s: buffering_capture - wait time %d ms\n",
+ __func__, err);
+
+
+ err = ce147_set_exif_ctrl(sd, state->exif_ctrl);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: set_capture_cmd failed\n",
+ __func__);
+ return err;
+ }
+
+
+ if (state->jpeg.enable) {
+ /*
+ * 4. Set EXIF information
+ */
+ err = ce147_set_capture_exif(sd);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for "
+ "exif\n", __func__);
+ return -EIO;
+ }
+
+ /*
+ * 6. Set JPEG Encoding parameters
+ */
+ err = ce147_set_jpeg_config(sd);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: Setting JPEG encoding "
+ "parameters\n", __func__);
+ return err;
+ }
+ /*
+ * 7. Wait for encoding to complete
+ */
+ err = ce147_waitfordone_timeout(client, 0x6C, 0x00, 3000,
+ POLL_TIME_MS);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: Wait for "
+ "jpeg_encoding\n", __func__);
+ return err;
+ }
+ ce147_msg(&client->dev, "%s: jpeg_encoding - wait time %d ms\n",
+ __func__, err);
+ }
+ /*
+ * 8. Get JPEG Main Data
+ */
+ err = ce147_get_snapshot_data(sd);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: get_snapshot_data\n",
+ __func__);
+ return err;
+ }
+ /*
+ * 9. Wait for done
+ */
+ err = ce147_waitfordone_timeout(client, 0x61, 0x00, 3000, POLL_TIME_MS);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: Wait for data_transfer\n",
+ __func__);
+ return err;
+ }
+ ce147_msg(&client->dev, "%s: data_transfer - wait time %d ms\n",
+ __func__, err);
+
+ return 0;
+}
+
+static int ce147_get_focus_mode(struct i2c_client *client, unsigned char cmd,
+ unsigned char *value)
+{
+ int err;
+ int count;
+
+ unsigned char ce147_buf_get_af_status[1] = { 0x00 };
+
+ /* set focus mode: AF or MACRO */
+ err = ce147_i2c_write_multi(client, cmd, value, 1);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for "
+ "get_focus_mode\n", __func__);
+ return -EIO;
+ }
+ /* check whether af data is valid or not */
+ for (count = 0; count < 600; count++) {
+ msleep(10);
+ ce147_buf_get_af_status[0] = 0xFF;
+ err = ce147_i2c_read_multi(client, CMD_CHECK_AUTO_FOCUS_SEARCH,
+ NULL, 0, ce147_buf_get_af_status, 1);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_read for "
+ "get_focus_mode\n", __func__);
+ return -EIO;
+ }
+ if ((ce147_buf_get_af_status[0] & 0x01) == 0x00)
+ break;
+ }
+
+ if ((ce147_buf_get_af_status[0] & 0x01) != 0x00)
+ return -EBUSY;
+ else
+ return ce147_buf_get_af_status[0] & 0x01;
+}
+
+static int ce147_set_af_softlanding(struct v4l2_subdev *sd)
+{
+ int err;
+ int count;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ce147_state *state = to_state(sd);
+
+ unsigned char ce147_buf_get_af_status[1] = { 0x00 };
+ unsigned char ce147_buf_set_af_land[1] = { 0x08 };
+ unsigned int ce147_len_set_af_land = 1;
+
+ if (state->runmode > CE147_RUNMODE_IDLE) {
+ /* make lens landing mode */
+ err = ce147_i2c_write_multi(client, CMD_SET_AUTO_FOCUS_MODE,
+ ce147_buf_set_af_land, ce147_len_set_af_land);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for "
+ "auto_focus\n", __func__);
+ return -EIO;
+ }
+ /* check whether af data is valid or not */
+ for (count = 0; count < 600; count++) {
+ msleep(10);
+ ce147_buf_get_af_status[0] = 0xFF;
+ err = ce147_i2c_read_multi(client,
+ CMD_CHECK_AUTO_FOCUS_SEARCH, NULL, 0,
+ ce147_buf_get_af_status, 1);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_read "
+ "for get_focus_mode\n",
+ __func__);
+ return -EIO;
+ }
+ if ((ce147_buf_get_af_status[0]) == 0x08)
+ break;
+ }
+ }
+ return 0;
+}
+
+static int ce147_set_flash(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ unsigned char ce147_buf_set_flash[2] = { 0x03, 0x00 };
+ unsigned int ce147_len_set_flash = 2;
+ unsigned char ce147_buf_set_flash_manual[2] = { 0x00, 0x00 };
+ unsigned int ce147_len_set_flash_manual = 2;
+
+#ifdef CONFIG_SAMSUNG_FASCINATE
+ unsigned char ce147_buf_set_flash_power_control[4] = {0x03,0x01,0x1D,0x0c};
+ unsigned int ce147_len_set_flash_power_control = 4;
+
+ if(ctrl->value != FLASH_MODE_TORCH_ON && ctrl->value != FLASH_MODE_TORCH_OFF)
+ Flash_Mode = ctrl->value;
+#endif
+
+ switch (ctrl->value) {
+ case FLASH_MODE_OFF:
+ ce147_buf_set_flash[1] = 0x00;
+ break;
+
+ case FLASH_MODE_AUTO:
+ ce147_buf_set_flash[1] = 0x02;
+ break;
+
+ case FLASH_MODE_ON:
+ ce147_buf_set_flash[1] = 0x01;
+ break;
+
+#ifdef CONFIG_SAMSUNG_FASCINATE
+ case FLASH_MODE_TORCH_ON:
+ ce147_buf_set_flash_manual[1] = 0x01;
+ break;
+
+ case FLASH_MODE_TORCH_OFF:
+ ce147_buf_set_flash_manual[1] = 0x00;
+ break;
+
+ case FLASH_MODE_BACKLIGHT_ON:
+ ce147_buf_set_flash_power_control[1] = 0x00;
+ ce147_buf_set_flash[1] = 0x01;
+ break;
+#else
+ case FLASH_MODE_TORCH:
+ ce147_buf_set_flash_manual[1] = 0x01;
+ break;
+#endif
+
+ default:
+ ce147_buf_set_flash[1] = 0x00;
+ break;
+ }
+
+#ifdef CONFIG_SAMSUNG_FASCINATE
+ // set flash power
+ err = ce147_i2c_write_multi(client, CMD_SET_FLASH_POWER, ce147_buf_set_flash_power_control, ce147_len_set_flash_power_control);
+ if(err < 0){
+ dev_err(&client->dev, "%s: failed: i2c_write for set_flash_power\n", __func__);
+ return -EIO;
+ }
+ //need to modify flash off for torch mode
+ if(ctrl->value == FLASH_MODE_TORCH_ON ||ctrl->value == FLASH_MODE_TORCH_OFF) {
+ err = ce147_i2c_write_multi(client, CMD_SET_FLASH_MANUAL, ce147_buf_set_flash_manual, ce147_len_set_flash_manual);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for set_flash\n", __func__);
+ return -EIO;
+ }
+ ce147_msg(&client->dev, "%s: done, camcorder_flash: 0x%02x\n", __func__, ce147_buf_set_flash_manual[1]);
+ }
+ else {
+ err = ce147_i2c_write_multi(client, CMD_SET_FLASH, ce147_buf_set_flash, ce147_len_set_flash);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for set_flash\n", __func__);
+ return -EIO;
+ }
+ ce147_msg(&client->dev, "%s: done, flash: 0x%02x\n", __func__, ce147_buf_set_flash[1]);
+ }
+#else
+ if (ctrl->value == FLASH_MODE_OFF) {
+ err = ce147_i2c_write_multi(client, CMD_SET_FLASH_MANUAL,
+ ce147_buf_set_flash_manual,
+ ce147_len_set_flash_manual);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for "
+ "set_flash\n", __func__);
+ return -EIO;
+ }
+ }
+
+ err = ce147_i2c_write_multi(client, CMD_SET_FLASH,
+ ce147_buf_set_flash, ce147_len_set_flash);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for set_flash\n",
+ __func__);
+ return -EIO;
+ }
+
+ ce147_msg(&client->dev, "%s: done, flash: 0x%02x\n",
+ __func__, ce147_buf_set_flash[1]);
+#endif
+
+ return 0;
+}
+
+#ifdef CONFIG_SAMSUNG_FASCINATE
+static int ce147_set_preflash(struct v4l2_subdev *sd, int flash_mode) //SecFeature.Camera aswoogi
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ unsigned char ce147_buf_set_preflash[2] = { 0x01, 0x00 };
+ unsigned int ce147_len_set_preflash = 2;
+ unsigned char ce147_buf_set_preflash_manual[2] = { 0x00, 0x00 };
+ unsigned int ce147_len_set_preflash_manual = 2;
+ unsigned char ce147_buf_set_flash[2] = { 0x03, 0x00 };
+ unsigned int ce147_len_set_flash = 2;
+ unsigned char ce147_buf_set_flash_manual[2] = { 0x00, 0x00 };
+ unsigned int ce147_len_set_flash_manual = 2;
+ unsigned char ce147_buf_set_flash_off[2] = { 0x03, 0x00 };
+ unsigned int ce147_len_set_flash_off = 2;
+ unsigned char ce147_buf_set_preflash_off[2] = { 0x01, 0x00 };
+ unsigned int ce147_len_set_preflash_off = 2;
+ unsigned char ce147_buf_set_preflash_init[2] = { 0x02, 0x02 };
+ unsigned int ce147_len_set_preflash_init = 2;
+ unsigned char ce147_buf_set_preflash_init2[2] = { 0x02, 0x00 };
+ unsigned int ce147_len_set_preflash_init2 = 2;
+
+
+ ce147_msg(&client->dev, "%s, %d\n", __func__, flash_mode);
+
+ switch(Flash_Mode) {
+ case FLASH_MODE_OFF:
+ ce147_buf_set_preflash[1] = 0x00;
+ ce147_buf_set_flash[1] = 0x00;
+ break;
+
+ case FLASH_MODE_AUTO:
+ ce147_buf_set_preflash[1] = 0x02;
+ ce147_buf_set_flash[1] = 0x02;
+ err = ce147_i2c_write_multi(client, 0x07, ce147_buf_set_preflash_init2, ce147_len_set_preflash_init2);
+ if(err < 0){
+ dev_err(&client->dev, "%s: failed: i2c_write for set_preflash\n", __func__);
+ return -EIO;
+ }
+ break;
+
+ case FLASH_MODE_ON:
+ ce147_buf_set_preflash[1] = 0x01;
+ ce147_buf_set_flash[1] = 0x01;
+ err = ce147_i2c_write_multi(client, 0x07, ce147_buf_set_preflash_init2, ce147_len_set_preflash_init2);
+ if(err < 0){
+ dev_err(&client->dev, "%s: failed: i2c_write for set_preflash\n", __func__);
+ return -EIO;
+ }
+ break;
+
+ case FLASH_MODE_BACKLIGHT_ON:
+ ce147_buf_set_preflash[1] = 0x01;
+ ce147_buf_set_flash[1] = 0x01;
+ err = ce147_i2c_write_multi(client, 0x07, ce147_buf_set_preflash_init, ce147_len_set_preflash_init);
+ if(err < 0){
+ dev_err(&client->dev, "%s: failed: i2c_write for set_preflash\n", __func__);
+ return -EIO;
+ }
+ break;
+ default:
+ ce147_buf_set_preflash[1] = 0x00;
+ ce147_buf_set_flash[1] = 0x00;
+ break;
+ }
+
+ //need to modify flash off for torch mode
+ if(flash_mode == 0) {
+ err = ce147_i2c_write_multi(client, CMD_SET_FLASH, ce147_buf_set_preflash, ce147_len_set_preflash);
+ if(err < 0){
+ dev_err(&client->dev, "%s: failed: i2c_write for set_preflash\n", __func__);
+ return -EIO;
+ }
+
+ err = ce147_i2c_write_multi(client, CMD_SET_FLASH, ce147_buf_set_flash_off, ce147_len_set_flash_off);
+ if(err < 0){
+ dev_err(&client->dev, "%s: failed: i2c_write for set_flash_off\n", __func__);
+ return -EIO;
+ }
+
+ dev_err(&client->dev, "%s: done, preflash: 0x%02x\n", __func__, ce147_buf_set_preflash[1]);
+ }
+ else {
+ err = ce147_i2c_write_multi(client, CMD_SET_FLASH, ce147_buf_set_flash, ce147_len_set_flash);
+ if(err < 0){
+ dev_err(&client->dev, "%s: failed: i2c_write for set_flash\n", __func__);
+ return -EIO;
+ }
+
+ err = ce147_i2c_write_multi(client, CMD_SET_FLASH, ce147_buf_set_preflash_off, ce147_len_set_preflash_off);
+ if(err < 0){
+ dev_err(&client->dev, "%s: failed: i2c_write for set_preflash_off\n", __func__);
+ return -EIO;
+ }
+
+ ce147_msg(&client->dev, "%s: done, flash: 0x%02x\n", __func__, ce147_buf_set_flash[1]);
+ }
+
+ return 0;
+}
+#endif
+
+static int ce147_set_effect(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ unsigned char ce147_buf_set_effect[2] = { 0x05, 0x00 };
+ unsigned int ce147_len_set_effect = 2;
+
+ switch (ctrl->value) {
+ case IMAGE_EFFECT_NONE:
+ ce147_buf_set_effect[1] = 0x00;
+ break;
+
+ case IMAGE_EFFECT_BNW:
+ ce147_buf_set_effect[1] = 0x01;
+ break;
+
+ case IMAGE_EFFECT_SEPIA:
+ ce147_buf_set_effect[1] = 0x03;
+ break;
+
+ case IMAGE_EFFECT_AQUA:
+ ce147_buf_set_effect[1] = 0x0D;
+ break;
+
+ case IMAGE_EFFECT_ANTIQUE:
+ ce147_buf_set_effect[1] = 0x06;
+ break;
+
+ case IMAGE_EFFECT_NEGATIVE:
+ ce147_buf_set_effect[1] = 0x05;
+ break;
+
+ case IMAGE_EFFECT_SHARPEN:
+ ce147_buf_set_effect[1] = 0x04;
+ break;
+
+ default:
+ ce147_buf_set_effect[1] = 0x00;
+ break;
+ }
+
+ err = ce147_i2c_write_multi(client, CMD_SET_EFFECT,
+ ce147_buf_set_effect, ce147_len_set_effect);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for set_effect\n",
+ __func__);
+ return -EIO;
+ }
+#if 0 /* remove batch */
+ err = ce147_get_batch_reflection_status(sd);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: ce147_get_batch_"
+ "reflection_status for set_effect\n", __func__);
+ return -EIO;
+ }
+#endif
+ ce147_msg(&client->dev, "%s: done\n", __func__);
+
+ return 0;
+}
+
+static int ce147_set_saturation(struct v4l2_subdev *sd,
+ struct v4l2_control *ctrl)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ unsigned char ce147_buf_set_saturation[2] = { 0x06, 0x00 };
+ unsigned int ce147_len_set_saturation = 2;
+
+ switch (ctrl->value) {
+ case SATURATION_MINUS_2:
+ ce147_buf_set_saturation[1] = 0x01;
+ break;
+
+ case SATURATION_MINUS_1:
+ ce147_buf_set_saturation[1] = 0x02;
+ break;
+
+ case SATURATION_DEFAULT:
+ ce147_buf_set_saturation[1] = 0x03;
+ break;
+
+ case SATURATION_PLUS_1:
+ ce147_buf_set_saturation[1] = 0x04;
+ break;
+
+ case SATURATION_PLUS_2:
+ ce147_buf_set_saturation[1] = 0x05;
+ break;
+
+ default:
+ ce147_buf_set_saturation[1] = 0x03;
+ break;
+ }
+
+ err = ce147_i2c_write_multi(client, CMD_SET_EFFECT,
+ ce147_buf_set_saturation, ce147_len_set_saturation);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for "
+ "set_saturation\n", __func__);
+ return -EIO;
+ }
+#if 0 /* remove batch */
+ err = ce147_get_batch_reflection_status(sd);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: ce147_get_batch_"
+ "reflection_status for set_saturation\n",
+ __func__);
+ return -EIO;
+ }
+#endif
+ ce147_msg(&client->dev, "%s: done, saturation: 0x%02x\n",
+ __func__, ce147_buf_set_saturation[1]);
+
+ return 0;
+}
+
+static int ce147_set_contrast(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ unsigned char ce147_buf_set_contrast[2] = { 0x07, 0x00 };
+ unsigned int ce147_len_set_contrast = 2;
+
+ switch (ctrl->value) {
+ case CONTRAST_MINUS_2:
+ ce147_buf_set_contrast[1] = 0x01;
+ break;
+
+ case CONTRAST_MINUS_1:
+ ce147_buf_set_contrast[1] = 0x02;
+ break;
+
+ case CONTRAST_DEFAULT:
+ ce147_buf_set_contrast[1] = 0x03;
+ break;
+
+ case CONTRAST_PLUS_1:
+ ce147_buf_set_contrast[1] = 0x04;
+ break;
+
+ case CONTRAST_PLUS_2:
+ ce147_buf_set_contrast[1] = 0x05;
+ break;
+
+ default:
+ ce147_buf_set_contrast[1] = 0x03;
+ break;
+ }
+
+ err = ce147_i2c_write_multi(client, CMD_SET_EFFECT,
+ ce147_buf_set_contrast, ce147_len_set_contrast);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for "
+ "set_contrast\n", __func__);
+ return -EIO;
+ }
+#if 0 /* remove batch */
+ err = ce147_get_batch_reflection_status(sd);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: ce147_get_batch_"
+ "reflection_status for set_contrast\n",
+ __func__);
+ return -EIO;
+ }
+#endif
+ ce147_msg(&client->dev, "%s: done, contrast: 0x%02x\n",
+ __func__, ce147_buf_set_contrast[1]);
+
+ return 0;
+}
+
+static int ce147_set_sharpness(struct v4l2_subdev *sd,
+ struct v4l2_control *ctrl)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ unsigned char ce147_buf_set_saturation[2] = { 0x02, 0x00 };
+ unsigned int ce147_len_set_saturation = 2;
+
+ switch (ctrl->value) {
+ case SHARPNESS_MINUS_2:
+ ce147_buf_set_saturation[1] = 0x01;
+ break;
+
+ case SHARPNESS_MINUS_1:
+ ce147_buf_set_saturation[1] = 0x02;
+ break;
+
+ case SHARPNESS_DEFAULT:
+ ce147_buf_set_saturation[1] = 0x03;
+ break;
+
+ case SHARPNESS_PLUS_1:
+ ce147_buf_set_saturation[1] = 0x04;
+ break;
+
+ case SHARPNESS_PLUS_2:
+ ce147_buf_set_saturation[1] = 0x05;
+ break;
+
+ default:
+ ce147_buf_set_saturation[1] = 0x03;
+ break;
+ }
+
+ err = ce147_i2c_write_multi(client, CMD_SET_EFFECT,
+ ce147_buf_set_saturation, ce147_len_set_saturation);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for "
+ "set_saturation\n", __func__);
+ return -EIO;
+ }
+#if 0 /* remove batch */
+ err = ce147_get_batch_reflection_status(sd);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: ce147_get_batch_"
+ "reflection_status for set_saturation\n",
+ __func__);
+ return -EIO;
+ }
+#endif
+ ce147_msg(&client->dev, "%s: done, sharpness: 0x%02x\n",
+ __func__, ce147_buf_set_saturation[1]);
+
+ return 0;
+}
+
+static int ce147_set_wdr(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ unsigned char ce147_buf_set_wdr[1] = { 0x00 };
+ unsigned int ce147_len_set_wdr = 1;
+
+ switch (ctrl->value) {
+ case WDR_ON:
+ ce147_buf_set_wdr[0] = 0x01;
+ break;
+
+ case WDR_OFF:
+ default:
+ ce147_buf_set_wdr[0] = 0x00;
+ break;
+ }
+
+ err = ce147_i2c_write_multi(client, CMD_SET_WDR,
+ ce147_buf_set_wdr, ce147_len_set_wdr);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for set_wdr\n",
+ __func__);
+ return -EIO;
+ }
+
+ ce147_msg(&client->dev, "%s: done, wdr: 0x%02x\n",
+ __func__, ce147_buf_set_wdr[0]);
+
+ return 0;
+}
+
+static int ce147_set_anti_shake(struct v4l2_subdev *sd,
+ struct v4l2_control *ctrl)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ unsigned char ce147_buf_set_anti_shake[1] = { 0x00 };
+ unsigned int ce147_len_set_anti_shake = 1;
+
+ switch (ctrl->value) {
+ case ANTI_SHAKE_STILL_ON:
+ ce147_buf_set_anti_shake[0] = 0x01;
+ break;
+
+ case ANTI_SHAKE_MOVIE_ON:
+ ce147_buf_set_anti_shake[0] = 0x10;
+ break;
+
+ case ANTI_SHAKE_OFF:
+ default:
+ ce147_buf_set_anti_shake[0] = 0x00;
+ break;
+ }
+
+ err = ce147_i2c_write_multi(client, CMD_SET_ANTI_SHAKE,
+ ce147_buf_set_anti_shake, ce147_len_set_anti_shake);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for anti_shake\n",
+ __func__);
+ return -EIO;
+ }
+
+ ce147_msg(&client->dev, "%s: done, AHS: 0x%02x\n",
+ __func__, ce147_buf_set_anti_shake[0]);
+
+ return 0;
+}
+
+static int ce147_set_continous_af(struct v4l2_subdev *sd,
+ struct v4l2_control *ctrl)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ unsigned char ce147_buf_set_caf[1] = { 0x02 };
+ unsigned char ce147_buf_start_af_search[1] = { 0x00 };
+ unsigned int ce147_len_start_af_search = 1;
+#if 0
+ unsigned char ce147_buf_set_af[1] = { 0x00 };
+#endif
+ unsigned char ce147_buf_stop_lens_movement[1] = { 0x00 };
+
+ /* need to set face_detection with noline */
+
+ if (ctrl->value) {
+ err = ce147_get_focus_mode(client, CMD_SET_AUTO_FOCUS_MODE,
+ ce147_buf_set_caf);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: "
+ "start_continous_af\n", __func__);
+ return -EIO;
+ }
+
+ /* start af search */
+ err = ce147_i2c_write_multi(client, CMD_START_AUTO_FOCUS_SEARCH,
+ ce147_buf_start_af_search,
+ ce147_len_start_af_search);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for "
+ "start_continous_af\n", __func__);
+ return -EIO;
+ }
+ } else {
+ err = ce147_get_focus_mode(client, CMD_STOP_LENS_MOVEMENT,
+ ce147_buf_stop_lens_movement);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: stop_continous_af\n",
+ __func__);
+ return -EIO;
+ }
+#if 0
+ err = ce147_get_focus_mode(client, CMD_SET_AUTO_FOCUS_MODE,
+ ce147_buf_set_af);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: stop_continous_af\n",
+ __func__);
+ return -EIO;
+ }
+#endif
+ }
+
+ ce147_msg(&client->dev, "%s: done\n", __func__);
+
+ return 0;
+}
+
+static int ce147_set_object_tracking(struct v4l2_subdev *sd,
+ struct v4l2_control *ctrl)
+{
+ int err;
+ int count;
+ unsigned short x;
+ unsigned short y;
+
+ struct ce147_state *state = to_state(sd);
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ unsigned char ce147_buf_set_object_tracking[7] = { 0x00, };
+ unsigned int ce147_len_set_object_tracking = 7;
+ unsigned char ce147_buf_check_object_tracking[9] = { 0x00, };
+ unsigned int ce147_len_check_object_tracking = 9;
+ unsigned char ce147_buf_stop_lens[1] = { 0x00 };
+
+ /* get x,y touch position */
+ x = state->position.x;
+ y = state->position.y;
+
+ if (OT_START) {
+ ce147_buf_set_object_tracking[3] = (x & 0x00FF);
+ ce147_buf_set_object_tracking[4] = ((x & 0xFF00) >> 8);
+ ce147_buf_set_object_tracking[5] = (y & 0x00FF);
+ ce147_buf_set_object_tracking[6] = ((y & 0xFF00) >> 8);
+
+ err = ce147_i2c_write_multi(client, CMD_START_OT,
+ ce147_buf_set_object_tracking,
+ ce147_len_set_object_tracking);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for "
+ "object_tracking\n", __func__);
+ return -EIO;
+ }
+
+ /* Read status whether AF Tracking is successful or fail */
+ for (count = 0; count < 300; count++) {
+ msleep(10);
+ ce147_buf_check_object_tracking[0] = 0xFF;
+ err = ce147_i2c_read_multi(client, CMD_CHECK_OT,
+ NULL, 0,
+ ce147_buf_check_object_tracking,
+ ce147_len_check_object_tracking);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_read "
+ "for object_tracking\n",
+ __func__);
+ return -EIO;
+ }
+ if (ce147_buf_check_object_tracking[0] == 0x02
+ || ce147_buf_check_object_tracking[0] == 0x03)
+ break;
+ }
+
+ /* OT status: searching an object in progess */
+ if (ce147_buf_check_object_tracking[0] == 0x01) {
+ state->ot_status = 1;
+ } else if (ce147_buf_check_object_tracking[0] == 0x02) {
+ /* OT status: an object is detected successfully */
+ err = ce147_set_continous_af(sd, ctrl);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: "
+ "ce147_start_continous_af for "
+ "object_tracking\n", __func__);
+ return -EIO;
+ }
+ state->ot_status = 2;
+ } else if (ce147_buf_check_object_tracking[0] == 0x03) {
+ /* OT status: an object detecting is failed */
+ state->ot_status = 3;
+ }
+ } else {
+ err = ce147_get_focus_mode(client, CMD_STOP_LENS_MOVEMENT,
+ ce147_buf_stop_lens);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: "
+ "ce147_start_continous_af for "
+ "object_tracking\n", __func__);
+ return -EIO;
+ }
+
+ err = ce147_i2c_write_multi(client, CMD_START_OT,
+ ce147_buf_set_object_tracking,
+ ce147_len_set_object_tracking);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for "
+ "object_tracking\n", __func__);
+ return -EIO;
+ }
+ }
+ ce147_msg(&client->dev, "%s: done\n", __func__);
+
+ return 0;
+}
+
+static int ce147_get_object_tracking(struct v4l2_subdev *sd,
+ struct v4l2_control *ctrl)
+{
+ int err;
+
+ struct ce147_state *state = to_state(sd);
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ unsigned char ce147_buf_check_object_tracking[9] = { 0x00, };
+ unsigned int ce147_len_check_object_tracking = 9;
+
+ ce147_buf_check_object_tracking[0] = 0xFF;
+ err = ce147_i2c_read_multi(client, CMD_CHECK_OT, NULL, 0,
+ ce147_buf_check_object_tracking,
+ ce147_len_check_object_tracking);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_read for "
+ "object_tracking\n", __func__);
+ return -EIO;
+ }
+
+ /* OT status: searching an object in progess */
+ if (ce147_buf_check_object_tracking[0] == 0x01) {
+ state->ot_status = 1;
+ } else if (ce147_buf_check_object_tracking[0] == 0x02) {
+ /* OT status: an object is detected successfully */
+ state->ot_status = 2;
+ } else if (ce147_buf_check_object_tracking[0] == 0x03) {
+ /* OT status: an object detecting is failed */
+ state->ot_status = 3;
+ } else if (ce147_buf_check_object_tracking[0] == 0x04) {
+ /* OT status: detected object is missing */
+ state->ot_status = 4;
+ }
+
+ ce147_msg(&client->dev, "%s: done\n", __func__);
+
+ return 0;
+}
+
+static int ce147_set_face_detection(struct v4l2_subdev *sd,
+ struct v4l2_control *ctrl)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ unsigned char ce147_buf_set_fd[3] = { 0x00, 0x00, 0x00 };
+ unsigned int ce147_len_set_fd = 3;
+
+ switch (ctrl->value) {
+ case FACE_DETECTION_ON:
+ ce147_buf_set_fd[0] = 0x03;
+ ce147_buf_set_fd[1] = 0x01;
+ ce147_buf_set_fd[2] = 0x0A;
+ break;
+
+ case FACE_DETECTION_ON_BEAUTY:
+ ce147_buf_set_fd[0] = 0x01;
+ ce147_buf_set_fd[1] = 0x01;
+ ce147_buf_set_fd[2] = 0x0A;
+ break;
+
+ case FACE_DETECTION_NOLINE:
+ ce147_buf_set_fd[0] = 0x03;
+ ce147_buf_set_fd[1] = 0x00;
+ ce147_buf_set_fd[2] = 0x0A;
+ break;
+
+ case FACE_DETECTION_OFF:
+ default:
+ ce147_buf_set_fd[0] = 0x00;
+ ce147_buf_set_fd[1] = 0x00;
+ ce147_buf_set_fd[2] = 0x00;
+ break;
+ }
+
+ err = ce147_i2c_write_multi(client, CMD_SET_FACE_DETECTION,
+ ce147_buf_set_fd, ce147_len_set_fd);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for "
+ "face_detection\n", __func__);
+ return -EIO;
+ }
+
+ ce147_msg(&client->dev, "%s: done\n", __func__);
+
+ return 0;
+}
+
+static int ce147_set_smart_auto(struct v4l2_subdev *sd,
+ struct v4l2_control *ctrl)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ unsigned char ce147_buf_set_smart_auto[1] = { 0x00 };
+ unsigned int ce147_len_set_smart_auto = 1;
+
+ if (ctrl->value == SMART_AUTO_ON) {
+ ce147_buf_set_smart_auto[0] = 0x01;
+ err = ce147_i2c_write_multi(client, CMD_SET_SMART_AUTO,
+ ce147_buf_set_smart_auto,
+ ce147_len_set_smart_auto);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for "
+ "smart_auto\n", __func__);
+ return -EIO;
+ }
+#if 0
+ err = ce147_set_continous_af(sd, CAF_START);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: CAF_START for "
+ "smart_auto\n", __func__);
+ return -EIO;
+ }
+#endif
+ } else {
+#if 0
+ err = ce147_set_continous_af(sd, CAF_STOP);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: CAF_START for "
+ "smart_auto\n", __func__);
+ return -EIO;
+ }
+#endif
+
+ ce147_buf_set_smart_auto[0] = 0x00;
+ err = ce147_i2c_write_multi(client, CMD_SET_SMART_AUTO,
+ ce147_buf_set_smart_auto,
+ ce147_len_set_smart_auto);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for "
+ "smart_auto\n", __func__);
+ return -EIO;
+ }
+ }
+
+ ce147_msg(&client->dev, "%s: done\n", __func__);
+
+ return 0;
+}
+
+static int ce147_get_smart_auto_status(struct v4l2_subdev *sd,
+ struct v4l2_control *ctrl)
+{
+ int err;
+
+ struct ce147_state *state = to_state(sd);
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ unsigned char ce147_buf_smart_auto_status[2] = {0x00, 0x00};
+
+ ce147_buf_smart_auto_status[0] = 0xFF;
+ err = ce147_i2c_read_multi(client, CMD_GET_SMART_AUTO_STATUS, NULL, 0,
+ ce147_buf_smart_auto_status, 2);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_read for auto_status\n",
+ __func__);
+ return -EIO;
+ }
+
+ if (ce147_buf_smart_auto_status[0] == 0x00
+ || ce147_buf_smart_auto_status[0] == 0x01) {
+ state->sa_status = SMART_AUTO_STATUS_AUTO;
+ } else {
+ switch (ce147_buf_smart_auto_status[1]) {
+ case 0x00:
+ state->sa_status = SMART_AUTO_STATUS_LANDSCAPE;
+ break;
+
+ case 0x01:
+ state->sa_status = SMART_AUTO_STATUS_PORTRAIT;
+ break;
+
+ case 0x02:
+ state->sa_status = SMART_AUTO_STATUS_NIGHT;
+ break;
+
+ case 0x03:
+ state->sa_status = SMART_AUTO_STATUS_PORTRAIT_NIGHT;
+ break;
+
+ case 0x04:
+ state->sa_status = SMART_AUTO_STATUS_MACRO;
+ break;
+
+ case 0x05:
+ state->sa_status = SMART_AUTO_STATUS_PORTRAIT_BACKLIT;
+ break;
+
+ case 0x06:
+ state->sa_status = SMART_AUTO_STATUS_PORTRAIT_ANTISHAKE;
+ break;
+
+ case 0x07:
+ state->sa_status = SMART_AUTO_STATUS_ANTISHAKE;
+ break;
+ }
+ }
+
+ ce147_msg(&client->dev, "%s: done(smartauto_status:%d)\n",
+ __func__, state->sa_status);
+
+ return 0;
+}
+
+static int ce147_set_touch_auto_focus(struct v4l2_subdev *sd,
+ struct v4l2_control *ctrl)
+{
+ int err;
+ unsigned short x;
+ unsigned short y;
+
+ struct ce147_state *state = to_state(sd);
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ unsigned char ce147_buf_set_touch_af[11] = { 0x00, };
+ unsigned int ce147_len_set_touch_af = 11;
+
+#if defined(CONFIG_ARIES_NTT) || defined(CONFIG_SAMSUNG_FASCINATE)/* Modify NTTS1 */
+ state->disable_aeawb_lock = 1;
+ err = ce147_set_awb_lock(sd, 0);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: ce147_set_awb_lock, "
+ "err %d\n", __func__, err);
+ return -EIO;
+ }
+#endif
+ /* get x,y touch position */
+ x = state->position.x;
+ y = state->position.y;
+
+ if (ctrl->value == TOUCH_AF_START) {
+ ce147_buf_set_touch_af[0] = 0x01;
+ ce147_buf_set_touch_af[1] = 0x03;
+ ce147_buf_set_touch_af[2] = 0x00;
+ ce147_buf_set_touch_af[3] = ((x - 0x32) & 0x00FF);
+ ce147_buf_set_touch_af[4] = (((x - 0x32) & 0xFF00) >> 8);
+ ce147_buf_set_touch_af[5] = ((y - 0x32) & 0x00FF);
+ ce147_buf_set_touch_af[6] = (((y - 0x32) & 0xFF00) >> 8);
+ ce147_buf_set_touch_af[7] = ((x + 0x32) & 0x00FF);
+ ce147_buf_set_touch_af[8] = (((x + 0x32) & 0xFF00) >> 8);
+ ce147_buf_set_touch_af[9] = ((y + 0x32) & 0x00FF);
+ ce147_buf_set_touch_af[10] = (((y + 0x32) & 0xFF00) >> 8);
+ }
+
+ err = ce147_i2c_write_multi(client, CMD_SET_TOUCH_AUTO_FOCUS,
+ ce147_buf_set_touch_af, ce147_len_set_touch_af);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for "
+ "touch_auto_focus\n", __func__);
+ return -EIO;
+ }
+
+ ce147_msg(&client->dev, "%s: done\n", __func__);
+
+ return 0;
+}
+
+static int ce147_set_focus_mode(struct v4l2_subdev *sd,
+ struct v4l2_control *ctrl)
+{
+ int err;
+ struct ce147_state *state = to_state(sd);
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ unsigned char ce147_buf_set_focus_mode[1] = { 0x00 };
+
+ switch (ctrl->value) {
+ case FOCUS_MODE_MACRO:
+ case FOCUS_MODE_MACRO_DEFAULT:
+ ce147_buf_set_focus_mode[0] = 0x01;
+ break;
+
+ /* case FOCUS_MODE_FD:
+ break; */
+
+ case FOCUS_MODE_AUTO:
+ case FOCUS_MODE_AUTO_DEFAULT:
+ /* case FOCUS_MODE_FD_DEFAULT: */
+ default:
+ ce147_buf_set_focus_mode[0] = 0x00;
+ break;
+ }
+#if 0
+ if (state->hd_preview_on == 1)
+ ce147_buf_set_focus_mode[0] = 0x07;
+#endif
+ /* if (ctrl->value != FOCUS_MODE_FD) { */
+ if ((state->pre_focus_mode != ce147_buf_set_focus_mode[0])
+ || (ctrl->value == FOCUS_MODE_MACRO_DEFAULT)
+ || (ctrl->value == FOCUS_MODE_AUTO_DEFAULT)) {
+ /* || (ctrl->value == FOCUS_MODE_FD_DEFAULT)) */
+#if defined(CONFIG_ARIES_NTT) || defined(CONFIG_SAMSUNG_FASCINATE)/* Modify NTTS1 */
+ ce147_msg(&client->dev, "%s: unlock\n", __func__);
+ state->disable_aeawb_lock = 0;
+ err = ce147_set_awb_lock(sd, 0);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: ce147_set_awb_"
+ "unlock, err %d\n", __func__, err);
+ return -EIO;
+ }
+#endif
+ /* pr_debug("[5B] ce147_set_focus_mode: %d\n",
+ ce147_buf_set_focus_mode[0]); */
+ err = ce147_get_focus_mode(client, CMD_SET_AUTO_FOCUS_MODE,
+ ce147_buf_set_focus_mode);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: get_focus_mode\n",
+ __func__);
+ return -EIO;
+ }
+ }
+ state->pre_focus_mode = ce147_buf_set_focus_mode[0];
+ /* } */
+
+ return 0;
+}
+
+static int ce147_set_vintage_mode(struct v4l2_subdev *sd,
+ struct v4l2_control *ctrl)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ unsigned char ce147_buf_set_vintage_mode[4] = {
+ 0x10, 0x01, 0x32, 0x00
+ };
+ unsigned int ce147_len_set_vintage_mode = 4;
+
+ switch (ctrl->value) {
+ case VINTAGE_MODE_OFF:
+ ce147_buf_set_vintage_mode[1] = 0x00;
+ ce147_buf_set_vintage_mode[2] = 0x00;
+ ce147_buf_set_vintage_mode[3] = 0x00;
+ break;
+
+ case VINTAGE_MODE_NORMAL:
+ ce147_buf_set_vintage_mode[3] = 0x00;
+ break;
+
+ case VINTAGE_MODE_WARM:
+ ce147_buf_set_vintage_mode[3] = 0x02;
+ break;
+
+ case VINTAGE_MODE_COOL:
+ ce147_buf_set_vintage_mode[3] = 0x01;
+ break;
+
+ case VINTAGE_MODE_BNW:
+ ce147_buf_set_vintage_mode[3] = 0x03;
+ break;
+
+ default:
+ ce147_buf_set_vintage_mode[1] = 0x00;
+ ce147_buf_set_vintage_mode[2] = 0x00;
+ ce147_buf_set_vintage_mode[3] = 0x00;
+ break;
+ }
+
+ err = ce147_i2c_write_multi(client, CMD_SET_EFFECT_SHOT,
+ ce147_buf_set_vintage_mode,
+ ce147_len_set_vintage_mode);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for "
+ "vintage_mode\n", __func__);
+ return -EIO;
+ }
+
+ ce147_msg(&client->dev, "%s: done\n", __func__);
+
+ return 0;
+}
+
+static int ce147_set_face_beauty(struct v4l2_subdev *sd,
+ struct v4l2_control *ctrl)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ unsigned char ce147_buf_set_face_beauty[4] = { 0x00, 0x00, 0x00, 0x00 };
+ unsigned int ce147_len_set_face_beauty = 4;
+
+ switch (ctrl->value) {
+ case BEAUTY_SHOT_ON:
+ ce147_buf_set_face_beauty[1] = 0x01;
+ ce147_buf_set_face_beauty[2] = 0x32;
+ ce147_buf_set_face_beauty[3] = 0x01;
+ break;
+
+ case BEAUTY_SHOT_OFF:
+ default:
+ break;
+ }
+
+ /* Need to set face detection as 'face beauty on' mode. */
+ err = ce147_i2c_write_multi(client, CMD_SET_EFFECT_SHOT,
+ ce147_buf_set_face_beauty, ce147_len_set_face_beauty);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for "
+ "set_face_beauty\n", __func__);
+ return -EIO;
+ }
+
+ ce147_msg(&client->dev, "%s: done\n", __func__);
+
+ return 0;
+}
+
+
+static int ce147_set_white_balance(struct v4l2_subdev *sd,
+ struct v4l2_control *ctrl)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ unsigned char ce147_buf_set_wb_auto[1] = { 0x01 };
+ unsigned char ce147_buf_set_wb[2] = { 0x10, 0x00 };
+ unsigned int ce147_len_set_wb_auto = 1;
+ unsigned int ce147_len_set_wb = 2;
+
+ switch (ctrl->value) {
+ case WHITE_BALANCE_AUTO:
+ ce147_buf_set_wb_auto[0] = 0x00;
+ break;
+
+ case WHITE_BALANCE_SUNNY:
+ ce147_buf_set_wb[1] = 0x00;
+ break;
+
+ case WHITE_BALANCE_CLOUDY:
+ ce147_buf_set_wb[1] = 0x01;
+ break;
+
+ case WHITE_BALANCE_TUNGSTEN:
+ ce147_buf_set_wb[1] = 0x02;
+ break;
+
+ case WHITE_BALANCE_FLUORESCENT:
+ ce147_buf_set_wb[1] = 0x03;
+ break;
+
+ default:
+ dev_err(&client->dev, "%s: failed: to set_white_balance, "
+ "enum: %d\n", __func__, ctrl->value);
+ return -EINVAL;
+ }
+
+ if (ctrl->value != WHITE_BALANCE_AUTO) {
+ err = ce147_i2c_write_multi(client, CMD_SET_WB,
+ ce147_buf_set_wb, ce147_len_set_wb);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for "
+ "white_balance\n", __func__);
+ return -EIO;
+ }
+ }
+ err = ce147_i2c_write_multi(client, CMD_SET_WB_AUTO,
+ ce147_buf_set_wb_auto, ce147_len_set_wb_auto);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for "
+ "white_balance\n", __func__);
+ return -EIO;
+ }
+#if 0 /* remove batch */
+ err = ce147_get_batch_reflection_status(sd);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: ce147_get_batch_"
+ "reflection_status for white_balance\n",
+ __func__);
+ return -EIO;
+ }
+#endif
+ ce147_msg(&client->dev, "%s: done\n", __func__);
+
+ return 0;
+}
+
+static int ce147_set_ev(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ce147_state *state = to_state(sd);
+
+ unsigned char ce147_buf_set_ev[2] = { 0x02, 0x00 };
+ unsigned int ce147_len_set_ev = 2;
+ unsigned int ce147_ev_offset = 13;
+
+ switch (ctrl->value) {
+ case EV_MINUS_4:
+ ce147_buf_set_ev[1] = 0x02;
+ break;
+
+ case EV_MINUS_3:
+ ce147_buf_set_ev[1] = 0x03;
+ break;
+
+ case EV_MINUS_2:
+ ce147_buf_set_ev[1] = 0x04;
+ break;
+
+ case EV_MINUS_1:
+ ce147_buf_set_ev[1] = 0x05;
+ break;
+
+ case EV_DEFAULT:
+ ce147_buf_set_ev[1] = 0x06;
+ break;
+
+ case EV_PLUS_1:
+ ce147_buf_set_ev[1] = 0x07;
+ break;
+
+ case EV_PLUS_2:
+ ce147_buf_set_ev[1] = 0x08;
+ break;
+
+ case EV_PLUS_3:
+ ce147_buf_set_ev[1] = 0x09;
+ break;
+
+ case EV_PLUS_4:
+ ce147_buf_set_ev[1] = 0x0A;
+ break;
+
+ default:
+ dev_err(&client->dev, "%s: failed: to set_ev, enum: %d\n",
+ __func__, ctrl->value);
+ return -EINVAL;
+ }
+
+ if (state->hd_preview_on) { /* This is for HD REC preview */
+ ce147_buf_set_ev[1] += ce147_ev_offset;
+ }
+ /* pr_debug("ce147_set_ev: set_ev:, data: 0x%02x\n",
+ ce147_buf_set_ev[1]); */
+
+ err = ce147_i2c_write_multi(client, CMD_SET_WB,
+ ce147_buf_set_ev, ce147_len_set_ev);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for set_ev, "
+ "HD preview(%d)\n",
+ __func__, state->hd_preview_on);
+ return -EIO;
+ }
+#if 0 /* remove batch */
+ err = ce147_get_batch_reflection_status(sd);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: ce147_get_batch_"
+ "reflection_status for set_ev\n", __func__);
+ return -EIO;
+ }
+#endif
+ ce147_msg(&client->dev, "%s: done\n", __func__);
+
+ return 0;
+}
+
+static int ce147_set_metering(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ce147_state *state = to_state(sd);
+
+ unsigned char ce147_buf_set_metering[2] = { 0x00, 0x00 };
+ unsigned int ce147_len_set_metering = 2;
+
+ switch (ctrl->value) {
+ case METERING_MATRIX:
+ ce147_buf_set_metering[1] = 0x02;
+ break;
+
+ case METERING_CENTER:
+ ce147_buf_set_metering[1] = 0x00;
+ break;
+
+ case METERING_SPOT:
+ ce147_buf_set_metering[1] = 0x01;
+ break;
+
+ default:
+ dev_err(&client->dev, "%s: failed: to set_photometry, "
+ "enum: %d\n", __func__, ctrl->value);
+ return -EINVAL;
+ }
+
+ if (state->hd_preview_on)
+ ce147_buf_set_metering[1] = 0x03;
+
+ err = ce147_i2c_write_multi(client, CMD_SET_WB,
+ ce147_buf_set_metering, ce147_len_set_metering);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for "
+ "set_photometry\n", __func__);
+ return -EIO;
+ }
+#if 0 /* remove batch */
+ err = ce147_get_batch_reflection_status(sd);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: ce147_get_batch_"
+ "reflection_status for set_photometry\n",
+ __func__);
+ return -EIO;
+ }
+#endif
+ ce147_msg(&client->dev, "%s: done\n", __func__);
+
+ return 0;
+}
+
+static int ce147_set_iso(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ unsigned char ce147_buf_set_iso[2] = { 0x01, 0x00 };
+ unsigned int ce147_len_set_iso = 2;
+
+ ce147_msg(&client->dev, "%s: Enter : iso %d\n", __func__, ctrl->value);
+
+ switch (ctrl->value) {
+ case ISO_AUTO:
+ ce147_buf_set_iso[1] = 0x06;
+ break;
+
+ case ISO_50:
+ ce147_buf_set_iso[1] = 0x07;
+ break;
+
+ case ISO_100:
+ ce147_buf_set_iso[1] = 0x08;
+ break;
+
+ case ISO_200:
+ ce147_buf_set_iso[1] = 0x09;
+ break;
+
+ case ISO_400:
+ ce147_buf_set_iso[1] = 0x0A;
+ break;
+
+ case ISO_800:
+ ce147_buf_set_iso[1] = 0x0B;
+ break;
+
+ case ISO_1600:
+ ce147_buf_set_iso[1] = 0x0C;
+ break;
+
+ /* This is additional setting for Sports' scene mode */
+ case ISO_SPORTS:
+ ce147_buf_set_iso[1] = 0x12;
+ break;
+
+ /* This is additional setting for 'Night' scene mode */
+ case ISO_NIGHT:
+ ce147_buf_set_iso[1] = 0x17;
+ break;
+
+ /* This is additional setting for video recording mode */
+ case ISO_MOVIE:
+ ce147_buf_set_iso[1] = 0x02;
+ break;
+
+ default:
+ dev_err(&client->dev, "%s: failed: to set_iso, enum: %d\n",
+ __func__, ctrl->value);
+ return -EINVAL;
+ }
+
+ err = ce147_i2c_write_multi(client, CMD_SET_WB,
+ ce147_buf_set_iso, ce147_len_set_iso);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for set_iso\n",
+ __func__);
+ return -EIO;
+ }
+#if 0 /* remove batch */
+ err = ce147_get_batch_reflection_status(sd);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: ce147_get_batch_"
+ "reflection_status for set_iso\n", __func__);
+ return -EIO;
+ }
+#endif
+ ce147_msg(&client->dev, "%s: done, iso: 0x%02x\n",
+ __func__, ce147_buf_set_iso[1]);
+
+ return 0;
+}
+
+static int ce147_set_gamma(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ce147_state *state = to_state(sd);
+
+ unsigned char ce147_buf_set_gamma[2] = { 0x01, 0x00 };
+ unsigned int ce147_len_set_gamma = 2;
+
+ unsigned char ce147_buf_set_uv[2] = { 0x03, 0x00 };
+ unsigned int ce147_len_set_uv = 2;
+
+ if (ctrl->value == GAMMA_ON) {
+ if (state->hd_preview_on) {
+ ce147_buf_set_gamma[1] = 0x01;
+ ce147_buf_set_uv[1] = 0x01;
+ }
+ }
+
+ err = ce147_i2c_write_multi(client, CMD_SET_EFFECT,
+ ce147_buf_set_gamma, ce147_len_set_gamma);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for "
+ "ce147_set_gamma\n", __func__);
+ return -EIO;
+ }
+
+ err = ce147_i2c_write_multi(client, CMD_SET_EFFECT,
+ ce147_buf_set_uv, ce147_len_set_uv);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for "
+ "ce147_set_gamma\n", __func__);
+ return -EIO;
+ }
+
+ ce147_msg(&client->dev, "%s: done, gamma: 0x%02x, uv: 0x%02x, hd: %d\n",
+ __func__, ce147_buf_set_gamma[1], ce147_buf_set_uv[1],
+ state->hd_preview_on);
+
+ return 0;
+}
+
+static int ce147_set_slow_ae(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ce147_state *state = to_state(sd);
+
+ unsigned char ce147_buf_set_slow_ae[2] = { 0x03, 0x00 };
+ unsigned int ce147_len_set_slow_ae = 2;
+
+ if (ctrl->value == SLOW_AE_ON)
+ if (state->hd_preview_on)
+ ce147_buf_set_slow_ae[1] = 0x02;
+
+ err = ce147_i2c_write_multi(client, CMD_SET_WB,
+ ce147_buf_set_slow_ae, ce147_len_set_slow_ae);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for "
+ "ce147_set_slow_ae\n", __func__);
+ return -EIO;
+ }
+
+ ce147_msg(&client->dev, "%s: done, slow_ae: 0x%02x, hd: %d\n",
+ __func__, ce147_buf_set_slow_ae[1],
+ state->hd_preview_on);
+
+ return 0;
+}
+
+static int ce147_set_face_lock(struct v4l2_subdev *sd,
+ struct v4l2_control *ctrl)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ unsigned char ce147_buf_set_fd_lock[1] = { 0x00 };
+ unsigned int ce147_len_set_fd_lock = 1;
+
+ switch (ctrl->value) {
+ case FACE_LOCK_ON:
+ ce147_buf_set_fd_lock[0] = 0x01;
+ break;
+
+ case FIRST_FACE_TRACKING:
+ ce147_buf_set_fd_lock[0] = 0x02;
+ break;
+
+ case FACE_LOCK_OFF:
+ default:
+ ce147_buf_set_fd_lock[0] = 0x00;
+ break;
+ }
+
+ err = ce147_i2c_write_multi(client, CMD_SET_FACE_LOCK,
+ ce147_buf_set_fd_lock, ce147_len_set_fd_lock);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for "
+ "face_lock\n", __func__);
+ return -EIO;
+ }
+
+ ce147_msg(&client->dev, "%s: done\n", __func__);
+
+ return 0;
+}
+
+static int ce147_finish_auto_focus(struct v4l2_subdev *sd)
+{
+ struct ce147_state *state = to_state(sd);
+#if defined(CONFIG_ARIES_NTT) || defined(CONFIG_SAMSUNG_FASCINATE)
+ if (!state->disable_aeawb_lock) {
+ err = ce147_set_awb_lock(sd, 1);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: ce147_set_awb_lock, err %d\n",__func__, err);
+ return -EIO;
+ }
+ }
+#endif
+
+ state->af_status = AF_NONE;
+ return 0;
+}
+
+static int ce147_start_auto_focus(struct v4l2_subdev *sd,
+ struct v4l2_control *ctrl)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ unsigned char ce147_buf_set_af[1] = { 0x00 };
+ unsigned int ce147_len_set_af = 1;
+ struct ce147_state *state = to_state(sd);
+
+ ce147_msg(&client->dev, "%s\n", __func__);
+
+#ifdef CONFIG_SAMSUNG_FASCINATE
+ ce147_msg(&client->dev, "%s: unlock\n", __func__);
+ err = ce147_set_awb_lock(sd, 0);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: ce147_set_awb_"
+ "unlock, err %d\n", __func__, err);
+ return -EIO;
+ }
+#endif
+
+ /* start af */
+ err = ce147_i2c_write_multi(client, CMD_START_AUTO_FOCUS_SEARCH,
+ ce147_buf_set_af, ce147_len_set_af);
+ state->af_status = AF_INITIAL;
+
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_write for "
+ "auto_focus\n", __func__);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int ce147_stop_auto_focus(struct v4l2_subdev *sd)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ce147_state *state = to_state(sd);
+ int err;
+ unsigned char ce147_buf_set_af = 0x00;
+
+ ce147_msg(&client->dev, "%s\n", __func__);
+ /* stop af */
+ err = ce147_i2c_write_multi(client, CMD_STOP_LENS_MOVEMENT,
+ &ce147_buf_set_af, 1);
+ if (err < 0)
+ dev_err(&client->dev, "%s: failed: i2c_write for auto_focus\n",
+ __func__);
+
+ if (state->af_status != AF_START) {
+ /* we weren't in the middle auto focus operation, we're done */
+ dev_dbg(&client->dev,
+ "%s: auto focus not in progress, done\n", __func__);
+
+ return 0;
+ }
+
+ state->af_status = AF_CANCEL;
+
+ return err;
+}
+
+static int ce147_get_auto_focus_status(struct v4l2_subdev *sd,
+ struct v4l2_control *ctrl)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ce147_state *state = to_state(sd);
+ unsigned char ce147_buf_get_af_status[1] = { 0x00 };
+ int err;
+
+ ce147_msg(&client->dev, "%s\n", __func__);
+
+ if (state->af_status == AF_INITIAL) {
+ dev_dbg(&client->dev, "%s: Check AF Result\n", __func__);
+ if (state->af_status == AF_NONE) {
+ dev_dbg(&client->dev,
+ "%s: auto focus never started, returning 0x2\n",
+ __func__);
+ ctrl->value = AUTO_FOCUS_CANCELLED;
+ return 0;
+ }
+ } else if (state->af_status == AF_CANCEL) {
+ dev_dbg(&client->dev,
+ "%s: AF is cancelled while doing\n", __func__);
+ ctrl->value = AUTO_FOCUS_CANCELLED;
+ ce147_finish_auto_focus(sd);
+ return 0;
+ }
+
+ ce147_buf_get_af_status[0] = 0xFF;
+ err = ce147_i2c_read_multi(client,
+ CMD_CHECK_AUTO_FOCUS_SEARCH, NULL, 0,
+ ce147_buf_get_af_status, 1);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: i2c_read "
+ "for auto_focus\n", __func__);
+ return -EIO;
+ }
+
+ if (ce147_buf_get_af_status[0] != 0x02 && ce147_buf_get_af_status[0] != 0x05) {
+ ce147_set_focus_mode(sd, ctrl);
+ }
+
+ ctrl->value = ce147_buf_get_af_status[0];
+ ce147_msg(&client->dev, "%s: done\n", __func__);
+ return 0;
+}
+
+static void ce147_init_parameters(struct v4l2_subdev *sd)
+{
+ struct ce147_state *state = to_state(sd);
+
+ /* Set initial values for the sensor stream parameters */
+ state->strm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ state->strm.parm.capture.timeperframe.numerator = 1;
+ state->strm.parm.capture.capturemode = 0;
+
+ /* state->framesize_index = CE147_PREVIEW_VGA; */
+ /*state->fps = 30;*/ /* Default value */
+
+ state->jpeg.enable = 0;
+ state->jpeg.quality = 100;
+ state->jpeg.main_offset = 0;
+ state->jpeg.main_size = 0;
+ state->jpeg.thumb_offset = 0;
+ state->jpeg.thumb_size = 0;
+ state->jpeg.postview_offset = 0;
+
+}
+
+static int ce147_get_fw_data(struct v4l2_subdev *sd)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ce147_state *state = to_state(sd);
+ int err = -EINVAL;
+
+ err = ce147_power_en(1, sd);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: ce147_power_en(on)\n",
+ __func__);
+ return -EIO;
+ }
+
+ err = ce147_load_fw(sd);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: Failed: Camera Initialization\n",
+ __func__);
+ return -EIO;
+ }
+
+ /* pr_debug("ce147_get_fw_data: ce147_load_fw is ok\n"); */
+
+ ce147_init_parameters(sd);
+
+ /* pr_debug("ce147_get_fw_data: ce147_init_parameters is ok\n"); */
+
+ err = ce147_get_fw_version(sd);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: Failed: Reading firmware version\n",
+ __func__);
+ return -EIO;
+ }
+
+ /* pr_debug("ce147_get_fw_data: ce147_get_fw_version is ok\n"); */
+
+ err = ce147_get_dateinfo(sd);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: Failed: Reading dateinfo\n",
+ __func__);
+ return -EIO;
+ }
+
+ /* pr_debug("ce147_get_fw_data: ce147_get_dateinfo is ok\n"); */
+
+ err = ce147_get_sensor_version(sd);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: Failed: Reading sensor info\n",
+ __func__);
+ return -EIO;
+ }
+
+ /* pr_debug("ce147_get_fw_data: ce147_get_sensor_version is ok\n"); */
+
+ err = ce147_get_sensor_maker_version(sd);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: Failed: Reading maker info\n",
+ __func__);
+ return -EIO;
+ }
+
+ err = ce147_get_af_version(sd);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: Failed: Reading af info\n",
+ __func__);
+ return -EIO;
+ }
+
+ err = ce147_get_gamma_version(sd);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: Failed: Reading camera gamma info\n",
+ __func__);
+ return -EIO;
+ }
+
+ err = ce147_power_en(0, sd);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: ce147_power_en(off)\n",
+ __func__);
+ return -EIO;
+ }
+
+ /* pr_debug("ce147_get_fw_data: ce147_power_en is ok\n"); */
+
+ ce147_info(&client->dev, "FW Version: %d.%d\n",
+ state->fw.major, state->fw.minor);
+ ce147_info(&client->dev, "PRM Version: %d.%d\n",
+ state->prm.major, state->prm.minor);
+ ce147_info(&client->dev, "Date(y.m.d): %d.%d.%d\n",
+ state->dateinfo.year, state->dateinfo.month,
+ state->dateinfo.date);
+ ce147_info(&client->dev, "Sensor version: %d\n",
+ state->sensor_version);
+
+ return 0;
+}
+
+/* s1_camera [ Defense process by ESD input ] _[ */
+static int ce147_reset(struct v4l2_subdev *sd)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ int err = -EINVAL;
+
+ dev_err(&client->dev, "%s: Enter\n", __func__);
+
+ err = ce147_power_en(0, sd);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: ce147_power_en(off)\n",
+ __func__);
+ return -EIO;
+ }
+
+ mdelay(5);
+
+ err = ce147_power_en(1, sd);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: failed: ce147_power_en(off)\n",
+ __func__);
+ return -EIO;
+ }
+
+ err = ce147_load_fw(sd); /* ce147_init(sd); */
+ if (err < 0) {
+ dev_err(&client->dev, "%s: Failed: Camera Initialization\n",
+ __func__);
+ return -EIO;
+ }
+
+ return 0;
+}
+/* _] */
+
+#if 0
+/* Sample code */
+static const char *ce147_querymenu_wb_preset[] = {
+ "WB Tungsten", "WB Fluorescent", "WB sunny", "WB cloudy", NULL
+};
+#endif
+
+static struct v4l2_queryctrl ce147_controls[] = {
+#if 0
+ /* Sample code */
+ {
+ .id = V4L2_CID_WHITE_BALANCE_PRESET,
+ .type = V4L2_CTRL_TYPE_MENU,
+ .name = "White balance preset",
+ .minimum = 0,
+ .maximum = ARRAY_SIZE(ce147_querymenu_wb_preset) - 2,
+ .step = 1,
+ .default_value = 0,
+ },
+#endif
+};
+
+const char **ce147_ctrl_get_menu(u32 id)
+{
+ switch (id) {
+#if 0
+ /* Sample code */
+ case V4L2_CID_WHITE_BALANCE_PRESET:
+ return ce147_querymenu_wb_preset;
+#endif
+ default:
+ return v4l2_ctrl_get_menu(id);
+ }
+}
+
+static inline struct v4l2_queryctrl const *ce147_find_qctrl(int id)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(ce147_controls); i++)
+ if (ce147_controls[i].id == id)
+ return &ce147_controls[i];
+
+ return NULL;
+}
+
+static int ce147_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(ce147_controls); i++) {
+ if (ce147_controls[i].id == qc->id) {
+ memcpy(qc, &ce147_controls[i],
+ sizeof(struct v4l2_queryctrl));
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static int ce147_querymenu(struct v4l2_subdev *sd, struct v4l2_querymenu *qm)
+{
+ struct v4l2_queryctrl qctrl;
+
+ qctrl.id = qm->id;
+ ce147_queryctrl(sd, &qctrl);
+
+ return v4l2_ctrl_query_menu(qm, &qctrl, ce147_ctrl_get_menu(qm->id));
+}
+
+/*
+ * Clock configuration
+ * Configure expected MCLK from host and return EINVAL if not supported clock
+ * frequency is expected
+ * freq : in Hz
+ * flag : not supported for now
+ */
+static int ce147_s_crystal_freq(struct v4l2_subdev *sd, u32 freq, u32 flags)
+{
+ int err = -EINVAL;
+
+ return err;
+}
+
+static int ce147_g_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
+{
+ int err = 0;
+
+ return err;
+}
+
+static int ce147_get_framesize_index(struct v4l2_subdev *sd);
+static int ce147_set_framesize_index(struct v4l2_subdev *sd,
+ unsigned int index);
+/* Information received:
+ * width, height
+ * pixel_format -> to be handled in the upper layer
+ *
+ * */
+static int ce147_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
+{
+ int err = 0;
+ struct ce147_state *state = to_state(sd);
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ int framesize_index = -1;
+
+ if (fmt->code == V4L2_MBUS_FMT_FIXED &&
+ fmt->colorspace != V4L2_COLORSPACE_JPEG) {
+ dev_err(&client->dev, "%s: mismatch in pixelformat and "
+ "colorspace\n", __func__);
+ return -EINVAL;
+ }
+
+ state->pix.width = fmt->width;
+ state->pix.height = fmt->height;
+ if (fmt->colorspace == V4L2_COLORSPACE_JPEG)
+ state->pix.pixelformat = V4L2_PIX_FMT_JPEG;
+ else
+ state->pix.pixelformat = 0; /* is this used anywhere? */
+
+ if (fmt->colorspace == V4L2_COLORSPACE_JPEG)
+ state->oprmode = CE147_OPRMODE_IMAGE;
+ else
+ state->oprmode = CE147_OPRMODE_VIDEO;
+
+ framesize_index = ce147_get_framesize_index(sd);
+
+ ce147_msg(&client->dev, "%s:framesize_index = %d\n",
+ __func__, framesize_index);
+
+ err = ce147_set_framesize_index(sd, framesize_index);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: set_framesize_index failed\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ if (state->pix.pixelformat == V4L2_PIX_FMT_JPEG)
+ state->jpeg.enable = 1;
+ else
+ state->jpeg.enable = 0;
+
+ if (state->oprmode == CE147_OPRMODE_VIDEO) {
+ if (framesize_index == CE147_PREVIEW_720P)
+ state->hd_preview_on = 1;
+ else
+ state->hd_preview_on = 0;
+ }
+
+ return 0;
+}
+
+static int ce147_enum_framesizes(struct v4l2_subdev *sd,
+ struct v4l2_frmsizeenum *fsize)
+{
+ struct ce147_state *state = to_state(sd);
+ int num_entries = sizeof(ce147_framesize_list)
+ / sizeof(struct ce147_enum_framesize);
+ struct ce147_enum_framesize *elem;
+ int index = 0;
+ int i = 0;
+
+ /* The camera interface should read this value, this is the resolution
+ * at which the sensor would provide framedata to the camera i/f
+ * In case of image capture,
+ * this returns the default camera resolution (VGA)
+ */
+ fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+
+ if (state->pix.pixelformat == V4L2_PIX_FMT_JPEG)
+ index = CE147_PREVIEW_VGA;
+ else
+ index = state->framesize_index;
+
+ for (i = 0; i < num_entries; i++) {
+ elem = &ce147_framesize_list[i];
+ if (elem->index == index) {
+ fsize->discrete.width =
+ ce147_framesize_list[index].width;
+ fsize->discrete.height =
+ ce147_framesize_list[index].height;
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static int ce147_enum_frameintervals(struct v4l2_subdev *sd,
+ struct v4l2_frmivalenum *fival)
+{
+ int err = 0;
+
+ return err;
+}
+
+static int ce147_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index,
+ enum v4l2_mbus_pixelcode *code)
+{
+ int num_entries;
+
+ num_entries = sizeof(capture_fmts) / sizeof(struct v4l2_mbus_framefmt);
+
+ if (index >= num_entries)
+ return -EINVAL;
+
+ *code = capture_fmts[index].code;
+
+ return 0;
+}
+
+static int ce147_try_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
+{
+ int num_entries;
+ int i;
+
+ num_entries = sizeof(capture_fmts) / sizeof(struct v4l2_mbus_framefmt);
+
+ for (i = 0; i < num_entries; i++) {
+ if (capture_fmts[i].code == fmt->code &&
+ capture_fmts[i].colorspace == fmt->colorspace) {
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+/** Gets current FPS value */
+static int ce147_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *param)
+{
+ struct ce147_state *state = to_state(sd);
+ int err = 0;
+
+ state->strm.parm.capture.timeperframe.numerator = 1;
+ state->strm.parm.capture.timeperframe.denominator = state->fps;
+
+ memcpy(param, &state->strm, sizeof(param));
+
+ return err;
+}
+
+/** Sets the FPS value */
+static int ce147_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *param)
+{
+ int err = 0;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ce147_state *state = to_state(sd);
+
+ if (param->parm.capture.timeperframe.numerator
+ != state->strm.parm.capture.timeperframe.numerator
+ || param->parm.capture.timeperframe.denominator
+ != state->strm.parm.capture.timeperframe.denominator) {
+
+ int fps = 0;
+ int fps_max = 30;
+
+ if (param->parm.capture.timeperframe.numerator
+ && param->parm.capture.timeperframe.denominator)
+ fps = (int)(param->parm.capture.timeperframe.denominator
+ / param->parm.capture
+ .timeperframe.numerator);
+ else
+ fps = 0;
+
+ if (fps <= 0 || fps > fps_max) {
+ dev_err(&client->dev, "%s: Framerate %d not supported, "
+ "setting it to %d fps.\n",
+ __func__, fps, fps_max);
+ fps = fps_max;
+ }
+
+ state->strm.parm.capture.timeperframe.numerator = 1;
+ state->strm.parm.capture.timeperframe.denominator = fps;
+
+ state->fps = fps;
+ }
+
+ /* Don't set the fps value, just update it in the state
+ * We will set the resolution and fps in the start operation
+ * (preview/capture) call */
+
+ return err;
+}
+
+/* This function is called from the g_ctrl api
+ *
+ * This function should be called only after the s_fmt call,
+ * which sets the required width/height value.
+ *
+ * It checks a list of available frame sizes and returns the
+ * most appropriate index of the frame size.
+ *
+ * Note: The index is not the index of the entry in the list. It is
+ * the value of the member 'index' of the particular entry. This is
+ * done to add additional layer of error checking.
+ *
+ * The list is stored in an increasing order (as far as possible).
+ * Hene the first entry (searching from the beginning) where both the
+ * width and height is more than the required value is returned.
+ * In case of no match, we return the last entry (which is supposed
+ * to be the largest resolution supported.)
+ *
+ * It returns the index (enum ce147_frame_size) of the framesize entry.
+ */
+static int ce147_get_framesize_index(struct v4l2_subdev *sd)
+{
+ int i = 0;
+ struct ce147_state *state = to_state(sd);
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ce147_enum_framesize *frmsize;
+
+ ce147_msg(&client->dev, "%s: Requested Res: %dx%d\n",
+ __func__, state->pix.width, state->pix.height);
+
+ /* Check for video/image mode */
+ for (i = 0; i < (sizeof(ce147_framesize_list)
+ / sizeof(struct ce147_enum_framesize)); i++) {
+ frmsize = &ce147_framesize_list[i];
+
+ if (frmsize->mode != state->oprmode)
+ continue;
+
+ if (state->oprmode == CE147_OPRMODE_IMAGE) {
+ /* In case of image capture mode,
+ * if the given image resolution is not supported,
+ * return the next higher image resolution. */
+ /* pr_debug("frmsize->width(%d) state->pix.width(%d) "
+ "frmsize->height(%d) "
+ "state->pix.height(%d)\n",
+ frmsize->width,
+ state->pix.width,
+ frmsize->height,
+ state->pix.height); */
+ if (frmsize->width == state->pix.width
+ && frmsize->height == state->pix.height) {
+ /* pr_debug("frmsize->index(%d)\n",
+ frmsize->index); */
+ return frmsize->index;
+ }
+ } else {
+ /* In case of video mode,
+ * if the given video resolution is not matching, use
+ * the default rate (currently CE147_PREVIEW_VGA).
+ */
+ /* pr_debug("frmsize->width(%d) state->pix.width(%d) "
+ "frmsize->height(%d) "
+ "state->pix.height(%d)\n",
+ frmsize->width,
+ state->pix.width,
+ frmsize->height,
+ state->pix.height); */
+ if (frmsize->width == state->pix.width
+ && frmsize->height == state->pix.height) {
+ /* pr_debug("frmsize->index(%d)\n",
+ frmsize->index); */
+ return frmsize->index;
+ }
+ }
+ }
+ /* If it fails, return the default value. */
+ return (state->oprmode == CE147_OPRMODE_IMAGE)
+ ? CE147_CAPTURE_3MP : CE147_PREVIEW_VGA;
+}
+
+
+/* This function is called from the s_ctrl api
+ * Given the index, it checks if it is a valid index.
+ * On success, it returns 0.
+ * On Failure, it returns -EINVAL
+ */
+static int ce147_set_framesize_index(struct v4l2_subdev *sd, unsigned int index)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ce147_state *state = to_state(sd);
+ int i = 0;
+
+ for (i = 0; i < (sizeof(ce147_framesize_list)
+ / sizeof(struct ce147_enum_framesize)); i++) {
+ if (ce147_framesize_list[i].index == index
+ && ce147_framesize_list[i].mode == state->oprmode) {
+ state->framesize_index = ce147_framesize_list[i].index;
+ state->pix.width = ce147_framesize_list[i].width;
+ state->pix.height = ce147_framesize_list[i].height;
+ ce147_info(&client->dev, "%s: Camera Res: %dx%d\n",
+ __func__, state->pix.width,
+ state->pix.height);
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static int ce147_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ce147_state *state = to_state(sd);
+ struct ce147_userset userset = state->userset;
+ int err = -ENOIOCTLCMD;
+
+ mutex_lock(&state->ctrl_lock);
+
+ switch (ctrl->id) {
+ case V4L2_CID_EXPOSURE:
+ ctrl->value = userset.exposure_bias;
+ err = 0;
+ break;
+
+ case V4L2_CID_AUTO_WHITE_BALANCE:
+ ctrl->value = userset.auto_wb;
+ err = 0;
+ break;
+
+ case V4L2_CID_WHITE_BALANCE_PRESET:
+ ctrl->value = userset.manual_wb;
+ err = 0;
+ break;
+
+ case V4L2_CID_COLORFX:
+ ctrl->value = userset.effect;
+ err = 0;
+ break;
+
+ case V4L2_CID_CONTRAST:
+ ctrl->value = userset.contrast;
+ err = 0;
+ break;
+
+ case V4L2_CID_SATURATION:
+ ctrl->value = userset.saturation;
+ err = 0;
+ break;
+
+ case V4L2_CID_SHARPNESS:
+ ctrl->value = userset.sharpness;
+ err = 0;
+ break;
+
+ case V4L2_CID_CAM_JPEG_MAIN_SIZE:
+ ctrl->value = state->jpeg.main_size;
+ err = 0;
+ break;
+
+ case V4L2_CID_CAM_JPEG_MAIN_OFFSET:
+ ctrl->value = state->jpeg.main_offset;
+ err = 0;
+ break;
+
+ case V4L2_CID_CAM_JPEG_THUMB_SIZE:
+ ctrl->value = state->jpeg.thumb_size;
+ err = 0;
+ break;
+
+ case V4L2_CID_CAM_JPEG_THUMB_OFFSET:
+ ctrl->value = state->jpeg.thumb_offset;
+ err = 0;
+ break;
+
+ case V4L2_CID_CAM_JPEG_POSTVIEW_OFFSET:
+ ctrl->value = state->jpeg.postview_offset;
+ err = 0;
+ break;
+
+ case V4L2_CID_CAM_JPEG_MEMSIZE:
+ ctrl->value = SENSOR_JPEG_SNAPSHOT_MEMSIZE;
+ err = 0;
+ break;
+
+ /* need to be modified */
+ case V4L2_CID_CAM_JPEG_QUALITY:
+ ctrl->value = state->jpeg.quality;
+ err = 0;
+ break;
+
+ case V4L2_CID_CAMERA_OBJ_TRACKING_STATUS:
+ err = ce147_get_object_tracking(sd, ctrl);
+ ctrl->value = state->ot_status;
+ break;
+
+ case V4L2_CID_CAMERA_SMART_AUTO_STATUS:
+ err = ce147_get_smart_auto_status(sd, ctrl);
+ ctrl->value = state->sa_status;
+ break;
+
+ case V4L2_CID_CAMERA_AUTO_FOCUS_RESULT_FIRST:
+ err = ce147_get_auto_focus_status(sd, ctrl);
+ break;
+
+ case V4L2_CID_CAM_DATE_INFO_YEAR:
+ ctrl->value = state->dateinfo.year;
+ err = 0;
+ break;
+
+ case V4L2_CID_CAM_DATE_INFO_MONTH:
+ ctrl->value = state->dateinfo.month;
+ err = 0;
+ break;
+
+ case V4L2_CID_CAM_DATE_INFO_DATE:
+ ctrl->value = state->dateinfo.date;
+ err = 0;
+ break;
+
+ case V4L2_CID_CAM_SENSOR_VER:
+ ctrl->value = state->sensor_version;
+ err = 0;
+ break;
+
+ case V4L2_CID_CAM_FW_MINOR_VER:
+ ctrl->value = state->fw.minor;
+ err = 0;
+ break;
+
+ case V4L2_CID_CAM_FW_MAJOR_VER:
+ ctrl->value = state->fw.major;
+ err = 0;
+ break;
+
+ case V4L2_CID_CAM_PRM_MINOR_VER:
+ ctrl->value = state->prm.minor;
+ err = 0;
+ break;
+
+ case V4L2_CID_CAM_PRM_MAJOR_VER:
+ ctrl->value = state->prm.major;
+ err = 0;
+ break;
+
+ case V4L2_CID_CAM_SENSOR_MAKER:
+ ctrl->value = state->sensor_info.maker;
+ err = 0;
+ break;
+
+ case V4L2_CID_CAM_SENSOR_OPTICAL:
+ ctrl->value = state->sensor_info.optical;
+ err = 0;
+ break;
+
+ case V4L2_CID_CAM_AF_VER_LOW:
+ ctrl->value = state->af_info.low;
+ err = 0;
+ break;
+
+ case V4L2_CID_CAM_AF_VER_HIGH:
+ ctrl->value = state->af_info.high;
+ err = 0;
+ break;
+
+ case V4L2_CID_CAM_GAMMA_RG_LOW:
+ ctrl->value = state->gamma.rg_low;
+ err = 0;
+ break;
+
+ case V4L2_CID_CAM_GAMMA_RG_HIGH:
+ ctrl->value = state->gamma.rg_high;
+ err = 0;
+ break;
+
+ case V4L2_CID_CAM_GAMMA_BG_LOW:
+ ctrl->value = state->gamma.bg_low;
+ err = 0;
+ break;
+
+ case V4L2_CID_CAM_GAMMA_BG_HIGH:
+ ctrl->value = state->gamma.bg_high;
+ err = 0;
+ break;
+
+ case V4L2_CID_CAM_GET_DUMP_SIZE:
+ ctrl->value = state->fw_dump_size;
+ err = 0;
+ break;
+
+ case V4L2_CID_MAIN_SW_DATE_INFO_YEAR:
+ ctrl->value = state->main_sw_dateinfo.year;
+ err = 0;
+ break;
+
+ case V4L2_CID_MAIN_SW_DATE_INFO_MONTH:
+ ctrl->value = state->main_sw_dateinfo.month;
+ err = 0;
+ break;
+
+ case V4L2_CID_MAIN_SW_DATE_INFO_DATE:
+ ctrl->value = state->main_sw_dateinfo.date;
+ err = 0;
+ break;
+
+ case V4L2_CID_MAIN_SW_FW_MINOR_VER:
+ ctrl->value = state->main_sw_fw.minor;
+ err = 0;
+ break;
+
+ case V4L2_CID_MAIN_SW_FW_MAJOR_VER:
+ ctrl->value = state->main_sw_fw.major;
+ err = 0;
+ break;
+
+ case V4L2_CID_MAIN_SW_PRM_MINOR_VER:
+ ctrl->value = state->main_sw_prm.minor;
+ err = 0;
+ break;
+
+ case V4L2_CID_MAIN_SW_PRM_MAJOR_VER:
+ ctrl->value = state->main_sw_prm.major;
+ err = 0;
+ break;
+
+ default:
+ dev_err(&client->dev, "%s: no such ctrl\n", __func__);
+ break;
+ }
+
+ mutex_unlock(&state->ctrl_lock);
+
+ return err;
+}
+
+static int ce147_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ce147_state *state = to_state(sd);
+ int err = -ENOIOCTLCMD;
+ int offset = 134217728;
+ int value = ctrl->value;
+
+ mutex_lock(&state->ctrl_lock);
+
+ switch (ctrl->id) {
+ case V4L2_CID_CAMERA_AEAWB_LOCK_UNLOCK:
+ err = ce147_set_ae_awb(sd, ctrl);
+ break;
+
+ case V4L2_CID_CAMERA_FLASH_MODE:
+ err = ce147_set_flash(sd, ctrl);
+ break;
+
+ case V4L2_CID_CAMERA_BRIGHTNESS:
+ if (state->runmode != CE147_RUNMODE_RUNNING) {
+ state->ev = ctrl->value;
+ err = 0;
+ } else
+ err = ce147_set_ev(sd, ctrl);
+ break;
+
+ case V4L2_CID_CAMERA_WHITE_BALANCE:
+ if (state->runmode != CE147_RUNMODE_RUNNING) {
+ state->wb = ctrl->value;
+ err = 0;
+ } else
+ err = ce147_set_white_balance(sd, ctrl);
+ break;
+
+ case V4L2_CID_CAMERA_EFFECT:
+ if (state->runmode != CE147_RUNMODE_RUNNING) {
+ state->effect = ctrl->value;
+ err = 0;
+ } else
+ err = ce147_set_effect(sd, ctrl);
+ break;
+
+ case V4L2_CID_CAMERA_ISO:
+ if (state->runmode != CE147_RUNMODE_RUNNING) {
+ state->iso = ctrl->value;
+ err = 0;
+ } else
+ err = ce147_set_iso(sd, ctrl);
+ break;
+
+ case V4L2_CID_CAMERA_METERING:
+ if (state->runmode != CE147_RUNMODE_RUNNING) {
+ state->metering = ctrl->value;
+ err = 0;
+ } else
+ err = ce147_set_metering(sd, ctrl);
+ break;
+
+ case V4L2_CID_CAMERA_CONTRAST:
+ err = ce147_set_contrast(sd, ctrl);
+ break;
+
+ case V4L2_CID_CAMERA_SATURATION:
+ err = ce147_set_saturation(sd, ctrl);
+ break;
+
+ case V4L2_CID_CAMERA_SHARPNESS:
+ err = ce147_set_sharpness(sd, ctrl);
+ break;
+
+ case V4L2_CID_CAMERA_WDR:
+ err = ce147_set_wdr(sd, ctrl);
+ break;
+
+ case V4L2_CID_CAMERA_ANTI_SHAKE:
+ err = ce147_set_anti_shake(sd, ctrl);
+ break;
+
+ case V4L2_CID_CAMERA_FACE_DETECTION:
+ err = ce147_set_face_detection(sd, ctrl);
+ break;
+
+ case V4L2_CID_CAMERA_SMART_AUTO:
+ err = ce147_set_smart_auto(sd, ctrl);
+ break;
+
+ case V4L2_CID_CAMERA_FOCUS_MODE:
+ err = ce147_set_focus_mode(sd, ctrl);
+ break;
+
+ case V4L2_CID_CAMERA_VINTAGE_MODE:
+ err = ce147_set_vintage_mode(sd, ctrl);
+ break;
+
+ case V4L2_CID_CAMERA_BEAUTY_SHOT:
+ err = ce147_set_face_beauty(sd, ctrl);
+ break;
+
+ case V4L2_CID_CAMERA_FACEDETECT_LOCKUNLOCK:
+ err = ce147_set_face_lock(sd, ctrl);
+ break;
+
+ /* need to be modified */
+ case V4L2_CID_CAM_JPEG_QUALITY:
+ if (ctrl->value < 0 || ctrl->value > 100)
+ err = -EINVAL;
+ else {
+ state->jpeg.quality = ctrl->value;
+ err = 0;
+ }
+ break;
+
+ case V4L2_CID_CAMERA_ZOOM:
+ err = ce147_set_dzoom(sd, ctrl);
+ break;
+
+ case V4L2_CID_CAMERA_TOUCH_AF_START_STOP:
+ err = ce147_set_touch_auto_focus(sd, ctrl);
+ break;
+
+ case V4L2_CID_CAMERA_CAF_START_STOP:
+ err = ce147_set_continous_af(sd, ctrl);
+ break;
+
+ case V4L2_CID_CAMERA_OBJECT_POSITION_X:
+ state->position.x = ctrl->value;
+ err = 0;
+ break;
+
+ case V4L2_CID_CAMERA_OBJECT_POSITION_Y:
+ state->position.y = ctrl->value;
+ err = 0;
+ break;
+
+ case V4L2_CID_CAMERA_OBJ_TRACKING_START_STOP:
+ err = ce147_set_object_tracking(sd, ctrl);
+ break;
+
+ case V4L2_CID_CAMERA_SET_AUTO_FOCUS:
+#ifdef CONFIG_SAMSUNG_FASCINATE
+ ce147_set_preflash(sd, 0);
+#endif
+ if (value == AUTO_FOCUS_ON)
+ err = ce147_start_auto_focus(sd, ctrl);
+ else if (value == AUTO_FOCUS_OFF)
+ err = ce147_stop_auto_focus(sd);
+ else {
+ err = -EINVAL;
+ dev_err(&client->dev,
+ "%s: bad focus value requestion %d\n",
+ __func__, value);
+ }
+ break;
+
+ case V4L2_CID_CAMERA_FRAME_RATE:
+ state->fps = ctrl->value;
+ err = 0;
+ break;
+
+ case V4L2_CID_CAMERA_ANTI_BANDING:
+ state->anti_banding = ctrl->value;
+ err = 0;
+ break;
+
+ case V4L2_CID_CAMERA_SET_GAMMA:
+ state->hd_gamma = ctrl->value;
+ err = 0;
+ break;
+
+ case V4L2_CID_CAMERA_SET_SLOW_AE:
+ state->hd_slow_ae = ctrl->value;
+ err = 0;
+ break;
+
+ case V4L2_CID_CAMERA_CAPTURE:
+ err = ce147_set_capture_start(sd, ctrl);
+ break;
+
+ case V4L2_CID_CAM_CAPTURE:
+ err = ce147_set_capture_config(sd, ctrl);
+ break;
+
+ /* Used to start / stop preview operation.
+ * This call can be modified to START/STOP operation,
+ * which can be used in image capture also */
+ case V4L2_CID_CAM_PREVIEW_ONOFF:
+ if (ctrl->value)
+ err = ce147_set_preview_start(sd);
+ else
+ err = ce147_set_preview_stop(sd);
+ break;
+
+ case V4L2_CID_CAM_UPDATE_FW:
+ err = ce147_update_fw(sd);
+ break;
+
+ case V4L2_CID_CAM_SET_FW_ADDR:
+ state->fw_info.addr = ctrl->value;
+ err = 0;
+ break;
+
+ case V4L2_CID_CAM_SET_FW_SIZE:
+ state->fw_info.size = ctrl->value;
+ err = 0;
+ break;
+
+#if defined(CONFIG_ARIES_NTT) || defined(CONFIG_SAMSUNG_FASCINATE) /* Modify NTTS1 */
+ case V4L2_CID_CAMERA_AE_AWB_DISABLE_LOCK:
+ state->disable_aeawb_lock = ctrl->value;
+ err = 0;
+ break;
+#endif
+
+ case V4L2_CID_CAMERA_FINISH_AUTO_FOCUS:
+ err = ce147_finish_auto_focus(sd);
+ break;
+
+ case V4L2_CID_CAM_FW_VER:
+ err = ce147_get_fw_data(sd);
+ break;
+
+ case V4L2_CID_CAM_DUMP_FW:
+ err = ce147_dump_fw(sd);
+ break;
+
+ case V4L2_CID_CAMERA_BATCH_REFLECTION:
+ err = ce147_get_batch_reflection_status(sd);
+ break;
+
+ case V4L2_CID_CAMERA_EXIF_ORIENTATION:
+ state->exif_orientation_info = ctrl->value;
+ err = 0;
+ break;
+
+ /* s1_camera [ Defense process by ESD input ] _[ */
+ case V4L2_CID_CAMERA_RESET:
+ dev_err(&client->dev, "%s: V4L2_CID_CAMERA_RESET\n", __func__);
+ pr_debug("======ESD\n");
+ err = ce147_reset(sd);
+ break;
+ /* _] */
+
+ case V4L2_CID_CAMERA_CHECK_DATALINE:
+ state->check_dataline = ctrl->value;
+ err = 0;
+ break;
+
+ case V4L2_CID_CAMERA_CHECK_DATALINE_STOP:
+ err = ce147_check_dataline_stop(sd);
+ break;
+
+ case V4L2_CID_CAMERA_THUMBNAIL_NULL:
+ state->thumb_null = ctrl->value;
+ err = 0;
+ break;
+
+#ifdef CONFIG_SAMSUNG_FASCINATE
+ case V4L2_CID_CAMERA_LENS_SOFTLANDING:
+ ce147_set_af_softlanding(sd);
+ err = 0;
+#endif
+
+ default:
+ dev_err(&client->dev, "%s: no such control\n", __func__);
+ break;
+ }
+
+ if (err < 0)
+ dev_err(&client->dev, "%s: vidioc_s_ctrl failed %d, "
+ "s_ctrl: id(%d), value(%d)\n",
+ __func__, err, (ctrl->id - offset),
+ ctrl->value);
+
+ mutex_unlock(&state->ctrl_lock);
+
+ return err;
+}
+static int ce147_s_ext_ctrls(struct v4l2_subdev *sd,
+ struct v4l2_ext_controls *ctrls)
+{
+ struct v4l2_ext_control *ctrl = ctrls->controls;
+ int ret = 0;
+ int i;
+
+ for (i = 0; i < ctrls->count; i++, ctrl++) {
+ ret = ce147_s_ext_ctrl(sd, ctrl);
+
+ if (ret) {
+ ctrls->error_idx = i;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int ce147_s_ext_ctrl(struct v4l2_subdev *sd,
+ struct v4l2_ext_control *ctrl)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ce147_state *state = to_state(sd);
+ int err = -ENOIOCTLCMD;
+ unsigned long temp = 0;
+ char *temp2;
+ struct gps_info_common *tempGPSType = NULL;
+
+ state->exif_ctrl = 0;
+
+ switch (ctrl->id) {
+
+ case V4L2_CID_CAMERA_GPS_LATITUDE:
+ tempGPSType = (struct gps_info_common *)ctrl->reserved2[1];
+ state->gpsInfo.ce147_gps_buf[0] = tempGPSType->direction;
+ state->gpsInfo.ce147_gps_buf[1] = tempGPSType->dgree;
+ state->gpsInfo.ce147_gps_buf[2] = tempGPSType->minute;
+ state->gpsInfo.ce147_gps_buf[3] = tempGPSType->second;
+
+ if ((tempGPSType->direction == 0)
+ && (tempGPSType->dgree == 0)
+ && (tempGPSType->minute == 0)
+ && (tempGPSType->second == 0))
+ condition = 1;
+ else
+ condition = 0;
+
+ err = 0;
+ break;
+
+ case V4L2_CID_CAMERA_GPS_LONGITUDE:
+ tempGPSType = (struct gps_info_common *)ctrl->reserved2[1];
+ state->gpsInfo.ce147_gps_buf[4] = tempGPSType->direction;
+ state->gpsInfo.ce147_gps_buf[5] = tempGPSType->dgree;
+ state->gpsInfo.ce147_gps_buf[6] = tempGPSType->minute;
+ state->gpsInfo.ce147_gps_buf[7] = tempGPSType->second;
+
+ if ((tempGPSType->direction == 0)
+ && (tempGPSType->dgree == 0)
+ && (tempGPSType->minute == 0)
+ && (tempGPSType->second == 0))
+ condition = 1;
+ else
+ condition = 0;
+
+ err = 0;
+ break;
+
+ case V4L2_CID_CAMERA_GPS_ALTITUDE:
+ tempGPSType = (struct gps_info_common *)ctrl->reserved2[1];
+ state->gpsInfo.ce147_altitude_buf[0] = tempGPSType->direction;
+ state->gpsInfo.ce147_altitude_buf[1] = (tempGPSType->dgree)
+ & 0x00ff;
+ state->gpsInfo.ce147_altitude_buf[2] = ((tempGPSType->dgree)
+ & 0xff00) >> 8;
+ state->gpsInfo.ce147_altitude_buf[3] = tempGPSType->minute;
+
+ err = 0;
+ break;
+
+ case V4L2_CID_CAMERA_GPS_TIMESTAMP:
+ /* state->gpsInfo.gps_timeStamp =
+ (struct tm*)ctrl->reserved2[1]; */
+ temp = *((unsigned long *)ctrl->reserved2[1]);
+ state->gpsInfo.gps_timeStamp = temp;
+ err = 0;
+ break;
+
+ case V4L2_CID_CAMERA_EXIF_TIME_INFO:
+ state->exifTimeInfo = (struct tm *)ctrl->reserved2[1];
+ err = 0;
+ break;
+
+ case V4L2_CID_CAMERA_GPS_PROCESSINGMETHOD:
+ temp2 = ((char *)ctrl->reserved2[1]);
+ strcpy(state->gpsInfo.gps_processingmethod, temp2);
+ err = 0;
+ break;
+ }
+
+ if (condition)
+ state->exif_ctrl = 1;
+
+ if (err < 0)
+ dev_err(&client->dev, "%s: vidioc_s_ext_ctrl failed %d\n",
+ __func__, err);
+
+ return err;
+}
+
+#ifdef FACTORY_CHECK
+ssize_t camtype_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ printk("%s \n", __func__);
+ char * sensorname = "NG";
+ sensorname = "SONY_IMX072ES_CE147";
+ return sprintf(buf,"%s\n", sensorname);
+}
+
+
+ssize_t camtype_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ printk(KERN_NOTICE "%s:%s\n", __func__, buf);
+
+ return size;
+}
+
+static DEVICE_ATTR(camtype,0644, camtype_show, camtype_store);
+
+extern struct class *sec_class;
+struct device *sec_cam_dev = NULL;
+#endif
+
+static int ce147_init(struct v4l2_subdev *sd, u32 val)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct ce147_state *state = to_state(sd);
+ int err = -EINVAL;
+
+ err = ce147_load_fw(sd);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: Failed: Camera Initialization\n",
+ __func__);
+ return -EIO;
+ }
+
+ ce147_init_parameters(sd);
+
+ err = ce147_get_fw_version(sd);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: Failed: Reading firmware version\n",
+ __func__);
+ return -EIO;
+ }
+
+ err = ce147_get_dateinfo(sd);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: Failed: Reading dateinfo\n",
+ __func__);
+ return -EIO;
+ }
+
+ err = ce147_get_sensor_version(sd);
+ if (err < 0) {
+ dev_err(&client->dev, "%s: Failed: Reading sensor info\n",
+ __func__);
+ return -EIO;
+ }
+ pr_debug("fw M:%d m:%d |prm M:%d m:%d\n",
+ MAIN_SW_FW[0], MAIN_SW_FW[1],
+ MAIN_SW_FW[2], MAIN_SW_FW[3]);
+ pr_debug("y. m. d = %d.%d.%d\n",
+ MAIN_SW_DATE_INFO[0], MAIN_SW_DATE_INFO[1],
+ MAIN_SW_DATE_INFO[2]);
+
+ err = ce147_get_main_sw_fw_version(sd);
+ if (err < 0) {
+ /*dev_err(&client->dev, "%s: Failed: Reading Main SW Version\n",
+ __func__);*/
+ return -EIO;
+ }
+
+ pr_debug("FW Version: %d.%d\n", state->fw.major, state->fw.minor);
+ pr_debug("PRM Version: %d.%d\n", state->prm.major, state->prm.minor);
+ pr_debug("Date(y.m.d): %d.%d.%d\n", state->dateinfo.year,
+ state->dateinfo.month, state->dateinfo.date);
+ pr_debug("Sensor version: %d\n", state->sensor_version);
+
+ return 0;
+}
+
+static const struct v4l2_subdev_core_ops ce147_core_ops = {
+ .init = ce147_init, /* initializing API */
+ .queryctrl = ce147_queryctrl,
+ .querymenu = ce147_querymenu,
+ .g_ctrl = ce147_g_ctrl,
+ .s_ctrl = ce147_s_ctrl,
+ .s_ext_ctrls = ce147_s_ext_ctrls,
+};
+
+static const struct v4l2_subdev_video_ops ce147_video_ops = {
+ .s_crystal_freq = ce147_s_crystal_freq,
+ .g_mbus_fmt = ce147_g_mbus_fmt,
+ .s_mbus_fmt = ce147_s_mbus_fmt,
+ .enum_framesizes = ce147_enum_framesizes,
+ .enum_frameintervals = ce147_enum_frameintervals,
+ .enum_mbus_fmt = ce147_enum_mbus_fmt,
+ .try_mbus_fmt = ce147_try_mbus_fmt,
+ .g_parm = ce147_g_parm,
+ .s_parm = ce147_s_parm,
+};
+
+static const struct v4l2_subdev_ops ce147_ops = {
+ .core = &ce147_core_ops,
+ .video = &ce147_video_ops,
+};
+
+/*
+ * ce147_probe
+ * Fetching platform data is being done with s_config subdev call.
+ * In probe routine, we just register subdev device
+ */
+static int ce147_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct ce147_state *state;
+ struct v4l2_subdev *sd;
+ struct ce147_platform_data *pdata = client->dev.platform_data;
+
+ state = kzalloc(sizeof(struct ce147_state), GFP_KERNEL);
+ if (state == NULL)
+ return -ENOMEM;
+
+ mutex_init(&state->ctrl_lock);
+
+ state->runmode = CE147_RUNMODE_NOTREADY;
+ state->pre_focus_mode = -1;
+ state->af_status = -2;
+
+ sd = &state->sd;
+ strcpy(sd->name, CE147_DRIVER_NAME);
+
+ /*
+ * Assign default format and resolution
+ * Use configured default information in platform data
+ * or without them, use default information in driver
+ */
+ state->pix.width = pdata->default_width;
+ state->pix.height = pdata->default_height;
+
+ if (!pdata->pixelformat)
+ state->pix.pixelformat = DEFAULT_PIX_FMT;
+ else
+ state->pix.pixelformat = pdata->pixelformat;
+
+ if (!pdata->freq)
+ state->freq = DEFAULT_MCLK; /* 24MHz default */
+ else
+ state->freq = pdata->freq;
+
+ /* Registering subdev */
+ v4l2_i2c_subdev_init(sd, client, &ce147_ops);
+
+#ifdef FACTORY_CHECK
+ {
+ static bool camtype_init = false;
+ if (sec_cam_dev == NULL)
+ {
+ sec_cam_dev = device_create(sec_class, NULL, 0, NULL, "sec_cam");
+ if (IS_ERR(sec_cam_dev))
+ pr_err("Failed to create device(sec_lcd_dev)!\n");
+ }
+
+ if (sec_cam_dev != NULL && camtype_init == false)
+ {
+ camtype_init = true;
+ if (device_create_file(sec_cam_dev, &dev_attr_camtype) < 0)
+ pr_err("Failed to create device file(%s)!\n", dev_attr_camtype.attr.name);
+ }
+ }
+#endif
+
+ ce147_info(&client->dev, "5MP camera CE147 loaded.\n");
+
+ return 0;
+}
+
+static int ce147_remove(struct i2c_client *client)
+{
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+ struct ce147_state *state = to_state(sd);
+
+ ce147_set_af_softlanding(sd);
+
+ v4l2_device_unregister_subdev(sd);
+ mutex_destroy(&state->ctrl_lock);
+ kfree(to_state(sd));
+
+ ce147_info(&client->dev, "Unloaded camera sensor CE147.\n");
+
+ return 0;
+}
+
+static const struct i2c_device_id ce147_id[] = {
+ { CE147_DRIVER_NAME, 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, ce147_id);
+
+static struct i2c_driver v4l2_i2c_driver = {
+ .driver.name = CE147_DRIVER_NAME,
+ .probe = ce147_probe,
+ .remove = ce147_remove,
+ .id_table = ce147_id,
+};
+
+static int __init v4l2_i2c_drv_init(void)
+{
+ return i2c_add_driver(&v4l2_i2c_driver);
+}
+
+static void __exit v4l2_i2c_drv_cleanup(void)
+{
+ i2c_del_driver(&v4l2_i2c_driver);
+}
+
+module_init(v4l2_i2c_drv_init);
+module_exit(v4l2_i2c_drv_cleanup);
+
+
+MODULE_DESCRIPTION("NEC CE147-NEC 5MP camera driver");
+MODULE_AUTHOR("Tushar Behera <tushar.b@samsung.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/samsung/Kconfig b/drivers/media/video/samsung/Kconfig
index 39ef521..15c0eb2 100644
--- a/drivers/media/video/samsung/Kconfig
+++ b/drivers/media/video/samsung/Kconfig
@@ -17,7 +17,7 @@ if CPU_S5PV210
source "drivers/media/video/samsung/fimc/Kconfig"
source "drivers/media/video/samsung/mfc50/Kconfig"
source "drivers/media/video/samsung/jpeg_v2/Kconfig"
-#source "drivers/media/video/samsung/tv20/Kconfig"
+source "drivers/media/video/samsung/tv20/Kconfig"
#source "drivers/media/video/samsung/tsi/Kconfig"
if CPU_S5PV210_EVT1
#source "drivers/media/video/samsung/rotator/Kconfig"
diff --git a/drivers/media/video/samsung/Makefile b/drivers/media/video/samsung/Makefile
index b363793..1f99c16 100644
--- a/drivers/media/video/samsung/Makefile
+++ b/drivers/media/video/samsung/Makefile
@@ -2,7 +2,7 @@ obj-$(CONFIG_VIDEO_FIMC) += fimc/
obj-$(CONFIG_VIDEO_MFC50) += mfc50/
obj-$(CONFIG_VIDEO_JPEG_V2) += jpeg_v2/
#obj-$(CONFIG_VIDEO_ROTATOR) += rotator/
-#obj-$(CONFIG_VIDEO_TV20) += tv20/
+obj-$(CONFIG_VIDEO_TV20) += tv20/
#obj-$(CONFIG_VIDEO_G2D) += g2d/
#obj-$(CONFIG_VIDEO_TSI) += tsi/
diff --git a/drivers/media/video/samsung/fimc/fimc.h b/drivers/media/video/samsung/fimc/fimc.h
index 3e61a98..b3df54d 100644
--- a/drivers/media/video/samsung/fimc/fimc.h
+++ b/drivers/media/video/samsung/fimc/fimc.h
@@ -65,7 +65,10 @@
#define FIMC_SCLK 1
#define FIMC_OVLY_MODE FIMC_OVLY_DMA_AUTO
+#define PINGPONG_2ADDR_MODE
+#if defined(PINGPONG_2ADDR_MODE)
#define FIMC_PINGPONG 2
+#endif
/*
* ENUMERATIONS
@@ -483,7 +486,7 @@ extern void fimc_dma_free(struct fimc_control *ctrl,
extern u32 fimc_mapping_rot_flip(u32 rot, u32 flip);
extern int fimc_get_scaler_factor(u32 src, u32 tar, u32 *ratio, u32 *shift);
extern void fimc_get_nv12t_size(int img_hres, int img_vres,
- int *y_size, int *cb_size);
+ int *y_size, int *cb_size, int rotate);
extern void fimc_clk_en(struct fimc_control *ctrl, bool on);
/* camera */
diff --git a/drivers/media/video/samsung/fimc/fimc_capture.c b/drivers/media/video/samsung/fimc/fimc_capture.c
index 2367bf6..09a9b22 100644
--- a/drivers/media/video/samsung/fimc/fimc_capture.c
+++ b/drivers/media/video/samsung/fimc/fimc_capture.c
@@ -40,6 +40,9 @@
#define fimc_dbg fimc_err
#endif
+static int vtmode = 0;
+static int device_id = 0;
+
static const struct v4l2_fmtdesc capture_fmts[] = {
{
.index = 0,
@@ -257,20 +260,34 @@ static int fimc_camera_start(struct fimc_control *ctrl)
struct v4l2_frmsizeenum cam_frmsize;
struct v4l2_control cam_ctrl;
int ret;
-
ret = subdev_call(ctrl, video, enum_framesizes, &cam_frmsize);
if (ret < 0) {
fimc_err("%s: enum_framesizes failed\n", __func__);
if (ret != -ENOIOCTLCMD)
return ret;
} else {
- ctrl->cam->width = cam_frmsize.discrete.width;
- ctrl->cam->height = cam_frmsize.discrete.height;
-
- ctrl->cam->window.left = 0;
- ctrl->cam->window.top = 0;
- ctrl->cam->window.width = ctrl->cam->width;
- ctrl->cam->window.height = ctrl->cam->height;
+ if (vtmode == 1 && device_id != 0 && (ctrl->cap->rotate == 90 || ctrl->cap->rotate == 270)) {
+ ctrl->cam->window.left = 136;
+ ctrl->cam->window.top = 0;
+ ctrl->cam->window.width = 368;
+ ctrl->cam->window.height = 480;
+ ctrl->cam->width = cam_frmsize.discrete.width;
+ ctrl->cam->height = cam_frmsize.discrete.height;
+ dev_err(ctrl->dev, "vtmode = 1, rotate = %d, device = front, cam->width = %d, cam->height = %d\n", ctrl->cap->rotate, ctrl->cam->width, ctrl->cam->height);
+ } else if (device_id != 0 && vtmode != 1) {
+ ctrl->cam->window.left = 136;
+ ctrl->cam->window.top = 0;
+ ctrl->cam->window.width = 368;
+ ctrl->cam->window.height = 480;
+ ctrl->cam->width = cam_frmsize.discrete.width;
+ ctrl->cam->height = cam_frmsize.discrete.height;
+ dev_err(ctrl->dev, "%s, crop(368x480), vtmode = 0, device = front, cam->width = %d, cam->height = %d\n", __func__, ctrl->cam->width, ctrl->cam->height);
+ } else {
+ ctrl->cam->window.left = 0;
+ ctrl->cam->window.top = 0;
+ ctrl->cam->window.width = ctrl->cam->width;
+ ctrl->cam->window.height = ctrl->cam->height;
+ }
}
cam_ctrl.id = V4L2_CID_CAM_PREVIEW_ONOFF;
@@ -389,34 +406,19 @@ static int fimc_add_outqueue(struct fimc_control *ctrl, int i)
struct fimc_capinfo *cap = ctrl->cap;
struct fimc_buf_set *buf;
- unsigned int mask = 0x2;
+ if (cap->nr_bufs > FIMC_PHYBUFS) {
+ if (list_empty(&cap->inq))
+ return -ENOENT;
- /* PINGPONG_2ADDR_MODE Only */
- /* pair_buf_index stands for pair index of i. (0<->2) (1<->3) */
-
- int pair_buf_index = (i^mask);
-
- /* FIMC have 4 h/w registers */
- if (i < 0 || i >= FIMC_PHYBUFS) {
- fimc_err("%s: invalid queue index : %d\n", __func__, i);
- return -ENOENT;
+ buf = list_first_entry(&cap->inq, struct fimc_buf_set, list);
+ list_del(&buf->list);
+ } else {
+ buf = &cap->bufs[i];
}
- if (list_empty(&cap->inq))
- return -ENOENT;
-
- buf = list_first_entry(&cap->inq, struct fimc_buf_set, list);
-
- /* pair index buffer should be allocated first */
- cap->outq[pair_buf_index] = buf->id;
- fimc_hwset_output_address(ctrl, buf, pair_buf_index);
-
cap->outq[i] = buf->id;
fimc_hwset_output_address(ctrl, buf, i);
- if (cap->nr_bufs != 1)
- list_del(&buf->list);
-
return 0;
}
@@ -424,7 +426,7 @@ static int fimc_update_hwaddr(struct fimc_control *ctrl)
{
int i;
- for (i = 0; i < FIMC_PINGPONG; i++)
+ for (i = 0; i < FIMC_PHYBUFS; i++)
fimc_add_outqueue(ctrl, i);
return 0;
@@ -705,6 +707,7 @@ int fimc_enum_fmt_vid_capture(struct file *file, void *fh,
return ret;
}
+ memset(f, 0, sizeof(*f));
memcpy(f, &capture_fmts[i], sizeof(*f));
return 0;
@@ -723,6 +726,7 @@ int fimc_g_fmt_vid_capture(struct file *file, void *fh, struct v4l2_format *f)
mutex_lock(&ctrl->v4l2_lock);
+ memset(&f->fmt.pix, 0, sizeof(f->fmt.pix));
memcpy(&f->fmt.pix, &ctrl->cap->fmt, sizeof(f->fmt.pix));
mutex_unlock(&ctrl->v4l2_lock);
@@ -823,20 +827,23 @@ int fimc_s_fmt_vid_capture(struct file *file, void *fh, struct v4l2_format *f)
* released at the file close.
* Anyone has better idea to do this?
*/
- mutex_lock(&ctrl->v4l2_lock);
-
- if (!ctrl->cap) {
- ctrl->cap = kmalloc(sizeof(*cap), GFP_KERNEL);
- if (!ctrl->cap) {
- mutex_unlock(&ctrl->v4l2_lock);
+ if (!cap) {
+ cap = kzalloc(sizeof(*cap), GFP_KERNEL);
+ if (!cap) {
fimc_err("%s: no memory for "
"capture device info\n", __func__);
return -ENOMEM;
}
+ /* assign to ctrl */
+ ctrl->cap = cap;
+ } else {
+ memset(cap, 0, sizeof(*cap));
}
- cap = ctrl->cap;
- memset(cap, 0, sizeof(*cap));
+
+ mutex_lock(&ctrl->v4l2_lock);
+
+ memset(&cap->fmt, 0, sizeof(cap->fmt));
memcpy(&cap->fmt, &f->fmt.pix, sizeof(cap->fmt));
v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, 0);
@@ -936,7 +943,7 @@ static void fimc_free_buffers(struct fimc_control *ctrl)
return;
- for (i = 0; i < cap->nr_bufs; i++) {
+ for (i = 0; i < FIMC_PHYBUFS; i++) {
memset(&cap->bufs[i], 0, sizeof(cap->bufs[i]));
cap->bufs[i].state = VIDEOBUF_NEEDS_INIT;
}
@@ -1214,6 +1221,11 @@ int fimc_s_ctrl_capture(void *fh, struct v4l2_control *c)
ret = 0;
break;
+ case V4L2_CID_CAMERA_VT_MODE:
+ vtmode = c->value;
+ ret = subdev_call(ctrl, core, s_ctrl, c);
+ break;
+
default:
/* try on subdev */
mutex_unlock(&ctrl->v4l2_lock);
@@ -1509,7 +1521,7 @@ static void fimc_reset_capture(struct fimc_control *ctrl)
fimc_stop_capture(ctrl);
- for (i = 0; i < FIMC_PINGPONG; i++)
+ for (i = 0; i < FIMC_PHYBUFS; i++)
fimc_add_inqueue(ctrl, ctrl->cap->outq[i]);
fimc_hwset_reset(ctrl);
@@ -1525,10 +1537,14 @@ int fimc_streamon_capture(void *fh)
{
struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
struct fimc_capinfo *cap = ctrl->cap;
+ struct v4l2_frmsizeenum cam_frmsize;
int rot;
int ret;
fimc_dbg("%s\n", __func__);
+ char *ce147 = "CE147 0-003c";
+ device_id = strcmp(ctrl->cam->sd->name, ce147);
+ fimc_dbg("%s, name(%s), device_id(%d), vtmode(%d)\n", __func__, ctrl->cam->sd->name , device_id, vtmode);
if (!ctrl->cam || !ctrl->cam->sd) {
fimc_err("%s: No capture device.\n", __func__);
@@ -1553,6 +1569,36 @@ int fimc_streamon_capture(void *fh)
if (!ctrl->cam->initialized)
fimc_camera_init(ctrl);
+ ret = subdev_call(ctrl, video, enum_framesizes, &cam_frmsize);
+ if (ret < 0) {
+ dev_err(ctrl->dev, "%s: enum_framesizes failed\n", __func__);
+ if(ret != -ENOIOCTLCMD)
+ return ret;
+ } else {
+ if (vtmode == 1 && device_id != 0 && (cap->rotate == 90 || cap->rotate == 270)) {
+ ctrl->cam->window.left = 136;
+ ctrl->cam->window.top = 0;//
+ ctrl->cam->window.width = 368;
+ ctrl->cam->window.height = 480;
+ ctrl->cam->width = cam_frmsize.discrete.width;
+ ctrl->cam->height = cam_frmsize.discrete.height;
+ dev_err(ctrl->dev, "vtmode = 1, rotate = %d, device = front, cam->width = %d, cam->height = %d\n", cap->rotate, ctrl->cam->width, ctrl->cam->height);
+ } else if (device_id != 0 && vtmode != 1) {
+ ctrl->cam->window.left = 136;
+ ctrl->cam->window.top = 0;
+ ctrl->cam->window.width = 368;
+ ctrl->cam->window.height = 480;
+ ctrl->cam->width = cam_frmsize.discrete.width;
+ ctrl->cam->height =cam_frmsize.discrete.height;
+ dev_err(ctrl->dev, "%s, crop(368x480), vtmode = 0, device = front, cam->width = %d, cam->height = %d\n", __func__, ctrl->cam->width, ctrl->cam->height);
+ } else {
+ ctrl->cam->window.left = 0;
+ ctrl->cam->window.top = 0;
+ ctrl->cam->width = ctrl->cam->window.width = cam_frmsize.discrete.width;
+ ctrl->cam->height = ctrl->cam->window.height = cam_frmsize.discrete.height;
+ }
+ }
+
if (ctrl->id != 2 &&
ctrl->cap->fmt.colorspace != V4L2_COLORSPACE_JPEG) {
ret = fimc_camera_start(ctrl);
@@ -1587,6 +1633,11 @@ int fimc_streamon_capture(void *fh)
fimc_hwset_output_size(ctrl, cap->fmt.width, cap->fmt.height);
+ if ((device_id != 0) && (vtmode != 1)) {
+ ctrl->cap->rotate = 90;
+ dev_err(ctrl->dev, "%s, rotate 90", __func__);
+ }
+
fimc_hwset_output_scan(ctrl, &cap->fmt);
fimc_hwset_output_rot_flip(ctrl, cap->rotate, cap->flip);
rot = fimc_mapping_rot_flip(cap->rotate, cap->flip);
@@ -1654,19 +1705,16 @@ int fimc_qbuf_capture(void *fh, struct v4l2_buffer *b)
{
struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
- if (!ctrl->cap || !ctrl->cap->nr_bufs) {
- fimc_err("%s: Invalid capture setting.\n", __func__);
- return -EINVAL;
- }
-
if (b->memory != V4L2_MEMORY_MMAP) {
fimc_err("%s: invalid memory type\n", __func__);
return -EINVAL;
}
- mutex_lock(&ctrl->v4l2_lock);
- fimc_add_inqueue(ctrl, b->index);
- mutex_unlock(&ctrl->v4l2_lock);
+ if (ctrl->cap->nr_bufs > FIMC_PHYBUFS) {
+ mutex_lock(&ctrl->v4l2_lock);
+ fimc_add_inqueue(ctrl, b->index);
+ mutex_unlock(&ctrl->v4l2_lock);
+ }
return 0;
}
@@ -1698,7 +1746,7 @@ int fimc_dqbuf_capture(void *fh, struct v4l2_buffer *b)
}
/* find out the real index */
- pp = ((fimc_hwget_frame_count(ctrl) + 2) % 4);
+ pp = ((fimc_hwget_frame_count(ctrl) + 2) % 4) % cap->nr_bufs;
/* We have read the latest frame, hence should reset availability
* flag
@@ -1709,14 +1757,16 @@ int fimc_dqbuf_capture(void *fh, struct v4l2_buffer *b)
if (cap->fmt.field == V4L2_FIELD_INTERLACED_TB)
pp &= ~0x1;
+ if (cap->nr_bufs > FIMC_PHYBUFS) {
b->index = cap->outq[pp];
- fimc_dbg("%s: buffer(%d) outq[%d]\n", __func__, b->index, pp);
-
ret = fimc_add_outqueue(ctrl, pp);
if (ret) {
b->index = -1;
fimc_err("%s: no inqueue buffer\n", __func__);
}
+ } else {
+ b->index = pp;
+ }
mutex_unlock(&ctrl->v4l2_lock);
diff --git a/drivers/media/video/samsung/fimc/fimc_dev.c b/drivers/media/video/samsung/fimc/fimc_dev.c
index 1441367..2554d7e 100644
--- a/drivers/media/video/samsung/fimc/fimc_dev.c
+++ b/drivers/media/video/samsung/fimc/fimc_dev.c
@@ -797,7 +797,7 @@ int fimc_get_scaler_factor(u32 src, u32 tar, u32 *ratio, u32 *shift)
}
void fimc_get_nv12t_size(int img_hres, int img_vres,
- int *y_size, int *cb_size)
+ int *y_size, int *cb_size, int rotate)
{
int remain;
int y_hres_byte, y_vres_byte;
@@ -805,6 +805,12 @@ void fimc_get_nv12t_size(int img_hres, int img_vres,
int y_hres_roundup, y_vres_roundup;
int cb_hres_roundup, cb_vres_roundup;
+ if (rotate == 90 || rotate == 270) {
+ int tmp = img_hres;
+ img_hres = img_vres;
+ img_vres = tmp;
+ }
+
/* to make 'img_hres and img_vres' be 16 multiple */
remain = img_hres % 16;
if (remain != 0) {
diff --git a/drivers/media/video/samsung/fimc/fimc_output.c b/drivers/media/video/samsung/fimc/fimc_output.c
index c66f995..98ff74e 100644
--- a/drivers/media/video/samsung/fimc/fimc_output.c
+++ b/drivers/media/video/samsung/fimc/fimc_output.c
@@ -226,7 +226,7 @@ static int fimc_outdev_set_src_buf(struct fimc_control *ctrl,
size = PAGE_ALIGN(y_size + cb_size);
break;
case V4L2_PIX_FMT_NV12T:
- fimc_get_nv12t_size(width, height, &y_size, &cb_size);
+ fimc_get_nv12t_size(width, height, &y_size, &cb_size, 0);
size = PAGE_ALIGN(y_size + cb_size);
break;
case V4L2_PIX_FMT_NV16:
@@ -1774,7 +1774,7 @@ int fimc_output_set_dst_addr(struct fimc_control *ctrl,
memset(&buf_set, 0x00, sizeof(buf_set));
if (V4L2_PIX_FMT_NV12T == format)
- fimc_get_nv12t_size(width, height, &y_size, &c_size);
+ fimc_get_nv12t_size(width, height, &y_size, &c_size, ctx->rotate);
switch (format) {
case V4L2_PIX_FMT_RGB32:
diff --git a/drivers/media/video/samsung/fimc/fimc_v4l2.c b/drivers/media/video/samsung/fimc/fimc_v4l2.c
index 3632ded..73202f4 100644
--- a/drivers/media/video/samsung/fimc/fimc_v4l2.c
+++ b/drivers/media/video/samsung/fimc/fimc_v4l2.c
@@ -81,8 +81,15 @@ static int fimc_querybuf(struct file *filp, void *fh, struct v4l2_buffer *b)
static int fimc_g_ctrl(struct file *filp, void *fh, struct v4l2_control *c)
{
struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
int ret = -1;
+ /* can get hw version at any time */
+ if (c->id == V4L2_CID_FIMC_VERSION) {
+ c->value = pdata->hw_ver;
+ return 0;
+ }
+
if (ctrl->cap != NULL) {
ret = fimc_g_ctrl_capture(fh, c);
} else if (ctrl->out != NULL) {
diff --git a/drivers/media/video/samsung/mfc50/mfc.c b/drivers/media/video/samsung/mfc50/mfc.c
index 17a9da8..5472c9d 100755
--- a/drivers/media/video/samsung/mfc50/mfc.c
+++ b/drivers/media/video/samsung/mfc50/mfc.c
@@ -49,6 +49,9 @@
#include <plat/media.h>
#include <mach/media.h>
#include <plat/mfc.h>
+#ifdef CONFIG_DVFS_LIMIT
+#include <mach/cpu-freq-v210.h>
+#endif
#include "mfc_interface.h"
#include "mfc_logmsg.h"
@@ -81,6 +84,9 @@ static int mfc_open(struct inode *inode, struct file *file)
goto err_open;
}
+#ifdef CONFIG_DVFS_LIMIT
+ s5pv210_lock_dvfs_high_level(DVFS_LOCK_TOKEN_1, L2);
+#endif
clk_enable(mfc_sclk);
mfc_load_firmware(mfc_fw_info->data, mfc_fw_info->size);
@@ -133,6 +139,9 @@ err_mem_inst:
kfree(mfc_ctx);
err_regulator:
if (!mfc_is_running()) {
+#ifdef CONFIG_DVFS_LIMIT
+ s5pv210_unlock_dvfs_high_level(DVFS_LOCK_TOKEN_1);
+#endif
/* Turn off mfc power domain regulator */
ret = regulator_disable(mfc_pd_regulator);
if (ret < 0)
@@ -175,6 +184,9 @@ static int mfc_release(struct inode *inode, struct file *file)
ret = 0;
if (!mfc_is_running()) {
+#ifdef CONFIG_DVFS_LIMIT
+ s5pv210_unlock_dvfs_high_level(DVFS_LOCK_TOKEN_1);
+#endif
/* Turn off mfc power domain regulator */
ret = regulator_disable(mfc_pd_regulator);
if (ret < 0) {
diff --git a/drivers/media/video/samsung/tv20/Kconfig b/drivers/media/video/samsung/tv20/Kconfig
new file mode 100644
index 0000000..e839ebc
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/Kconfig
@@ -0,0 +1,51 @@
+#
+# Configuration for TV-OUT/HDMI
+#
+
+config VIDEO_TV20
+ bool "Samsung TV Driver"
+ depends on VIDEO_SAMSUNG
+ default y
+ ---help---
+ This is a TV driver for Samsung S5P platform
+
+config HDMI_CEC
+ bool "HDMI CEC driver support."
+ depends on VIDEO_TV20 && CPU_S5PV210
+ default n
+ ---help---
+ This is a HDMI CEC driver for Samsung SMDK_S5PV210
+ Check dev node (major 10, minor 242)
+
+config HDMI_HPD
+ bool "HDMI HPD driver support."
+ depends on VIDEO_TV20 && CPU_S5PV210
+ default n
+ ---help---
+ This is a HDMI HPD driver for Samsung SMDK_S5PV210
+ Check dev node (major 10, minor 243)
+
+config TV_FB
+ bool "TV frame buffer driver support."
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+
+ depends on VIDEO_TV20 && FB && CPU_S5PV210
+ default n
+ ---help---
+
+config USER_ALLOC_TVOUT
+ bool "Support pre allocated frame buffer memory."
+ depends on VIDEO_TV20 && TV_FB
+ default n
+ ---help---
+ TV Driver doesn't allocate memory for frame buffer.
+ So, before enabling TV out, the frame buffer should be allocated.
+
+config TV_FB_NUM
+ int "Index of TV frame buffer"
+ depends on VIDEO_TV20 && TV_FB && !USER_ALLOC_TVOUT
+ default 5
+ ---help---
+
diff --git a/drivers/media/video/samsung/tv20/Makefile b/drivers/media/video/samsung/tv20/Makefile
new file mode 100644
index 0000000..3cd0c92
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/Makefile
@@ -0,0 +1,50 @@
+#################################################
+# Makefile for TVOut for S5PC100
+# 2010 (C) Samsung Electronics
+# Author : sangpil moon <sangpil.moon@samsung.com>
+#################################################
+
+obj-$(CONFIG_VIDEO_TV20) += s5p_tvout.o
+
+s5p_tvout-y += ddc.o
+
+ifeq ($(CONFIG_HDMI_HPD), y)
+s5p_tvout-y += hpd.o
+endif
+
+ifeq ($(CONFIG_HDMI_CEC), y)
+s5p_tvout-y += cec.o \
+ s5pv210/cec_s5pv210.o
+endif
+
+ifeq ($(CONFIG_CPU_S5PC100), y)
+s5p_tvout-y += s5pc100/hdcp_s5pc100.o \
+ s5pc100/hdmi_s5pc100.o \
+ s5pc100/sdout_s5pc100.o \
+ s5pc100/tv_power_s5pc100.o \
+ s5pc100/vmixer_s5pc100.o \
+ s5pc100/vprocessor_s5pc100.o \
+ s5pc100/tv_clock_s5pc100.o
+endif
+
+
+ifeq ($(CONFIG_CPU_S5PV210), y)
+s5p_tvout-y += s5pv210/hdcp_s5pv210.o \
+ s5pv210/hdmi_s5pv210.o \
+ s5pv210/sdout_s5pv210.o \
+ s5pv210/tv_power_s5pv210.o \
+ s5pv210/vmixer_s5pv210.o \
+ s5pv210/vprocessor_s5pv210.o
+endif
+
+
+s5p_tvout-y += s5p_stda_tvout_if.o \
+ s5p_stda_grp.o \
+ s5p_stda_hdmi.o \
+ s5p_stda_video_layer.o \
+ s5p_tv_v4l2.o \
+ s5p_tv_base.o
+
+ifeq ($(CONFIG_VIDEO_TV20_DEBUG), y)
+EXTRA_CFLAGS += -DDEBUG
+endif
diff --git a/drivers/media/video/samsung/tv20/cec.c b/drivers/media/video/samsung/tv20/cec.c
new file mode 100644
index 0000000..1422823
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/cec.c
@@ -0,0 +1,426 @@
+/* linux/drivers/media/video/samsung/tv20/cec.c
+ *
+ * cec interface file for Samsung TVOut driver (only s5pv210)
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/errno.h>
+#include <linux/wait.h>
+#include <linux/poll.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+
+#include <mach/gpio.h>
+#include <plat/gpio-cfg.h>
+#include <mach/regs-gpio.h>
+
+#include "s5p_tv.h"
+#include "cec.h"
+
+/*#define CECDEBUG*/
+#ifdef CECDEBUG
+#define CECIFPRINTK(fmt, args...) \
+ printk(KERN_INFO "\t[CEC_IF] %s: " fmt, __func__ , ## args)
+#else
+#define CECIFPRINTK(fmt, args...)
+#endif
+
+static struct cec_rx_struct cec_rx_struct;
+static struct cec_tx_struct cec_tx_struct;
+
+static bool hdmi_on;
+
+/**
+ * Change CEC Tx state to state
+ * @param state [in] new CEC Tx state.
+ */
+void __s5p_cec_set_tx_state(enum cec_state state)
+{
+ atomic_set(&cec_tx_struct.state, state);
+}
+
+/**
+ * Change CEC Rx state to @c state.
+ * @param state [in] new CEC Rx state.
+ */
+void __s5p_cec_set_rx_state(enum cec_state state)
+{
+ atomic_set(&cec_rx_struct.state, state);
+}
+
+
+int s5p_cec_open(struct inode *inode, struct file *file)
+{
+ s5p_tv_clk_gate(true);
+
+ hdmi_on = true;
+
+ __s5p_cec_reset();
+
+ __s5p_cec_set_divider();
+
+ __s5p_cec_threshold();
+
+ __s5p_cec_unmask_tx_interrupts();
+
+ __s5p_cec_set_rx_state(STATE_RX);
+ __s5p_cec_unmask_rx_interrupts();
+ __s5p_cec_enable_rx();
+
+ return 0;
+}
+
+int s5p_cec_release(struct inode *inode, struct file *file)
+{
+ s5p_tv_clk_gate(false);
+
+ hdmi_on = false;
+
+ __s5p_cec_mask_tx_interrupts();
+ __s5p_cec_mask_rx_interrupts();
+
+
+ return 0;
+}
+
+ssize_t s5p_cec_read(struct file *file, char __user *buffer, size_t count,
+ loff_t *ppos)
+{
+ ssize_t retval;
+
+ if (wait_event_interruptible(cec_rx_struct.waitq,
+ atomic_read(&cec_rx_struct.state)
+ == STATE_DONE)) {
+ return -ERESTARTSYS;
+ }
+
+ spin_lock_irq(&cec_rx_struct.lock);
+
+ if (cec_rx_struct.size > count) {
+ spin_unlock_irq(&cec_rx_struct.lock);
+ return -1;
+ }
+
+ if (copy_to_user(buffer, cec_rx_struct.buffer, cec_rx_struct.size)) {
+ spin_unlock_irq(&cec_rx_struct.lock);
+ printk(KERN_ERR " copy_to_user() failed!\n");
+ return -EFAULT;
+ }
+
+ retval = cec_rx_struct.size;
+
+ __s5p_cec_set_rx_state(STATE_RX);
+ spin_unlock_irq(&cec_rx_struct.lock);
+
+ return retval;
+}
+
+ssize_t s5p_cec_write(struct file *file, const char __user *buffer,
+ size_t count, loff_t *ppos)
+{
+ char *data;
+
+ /* check data size */
+
+ if (count > CEC_TX_BUFF_SIZE || count == 0)
+ return -1;
+
+ data = kmalloc(count, GFP_KERNEL);
+
+ if (!data) {
+ printk(KERN_ERR " kmalloc() failed!\n");
+ return -1;
+ }
+
+ if (copy_from_user(data, buffer, count)) {
+ printk(KERN_ERR " copy_from_user() failed!\n");
+ kfree(data);
+ return -EFAULT;
+ }
+
+ __s5p_cec_copy_packet(data, count);
+
+ kfree(data);
+
+ /* wait for interrupt */
+ if (wait_event_interruptible(cec_tx_struct.waitq,
+ atomic_read(&cec_tx_struct.state)
+ != STATE_TX)) {
+ return -ERESTARTSYS;
+ }
+
+ if (atomic_read(&cec_tx_struct.state) == STATE_ERROR)
+ return -1;
+
+ return count;
+}
+
+int s5p_cec_ioctl(struct inode *inode, struct file *file, u32 cmd,
+ unsigned long arg)
+{
+ u32 laddr;
+
+ switch (cmd) {
+
+ case CEC_IOC_SETLADDR:
+ CECIFPRINTK("ioctl(CEC_IOC_SETLADDR)\n");
+
+ if (get_user(laddr, (u32 __user *) arg))
+ return -EFAULT;
+
+ CECIFPRINTK("logical address = 0x%02x\n", laddr);
+
+ __s5p_cec_set_addr(laddr);
+
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+u32 s5p_cec_poll(struct file *file, poll_table *wait)
+{
+ poll_wait(file, &cec_rx_struct.waitq, wait);
+
+ if (atomic_read(&cec_rx_struct.state) == STATE_DONE)
+ return POLLIN | POLLRDNORM;
+
+ return 0;
+}
+
+static const struct file_operations cec_fops = {
+ .owner = THIS_MODULE,
+ .open = s5p_cec_open,
+ .release = s5p_cec_release,
+ .read = s5p_cec_read,
+ .write = s5p_cec_write,
+ .ioctl = s5p_cec_ioctl,
+ .poll = s5p_cec_poll,
+};
+
+static struct miscdevice cec_misc_device = {
+ .minor = CEC_MINOR,
+ .name = "CEC",
+ .fops = &cec_fops,
+};
+
+
+/**
+ * @brief CEC interrupt handler
+ *
+ * Handles interrupt requests from CEC hardware. \n
+ * Action depends on current state of CEC hardware.
+ */
+irqreturn_t s5p_cec_irq_handler(int irq, void *dev_id)
+{
+
+ u32 status = 0;
+
+ /* read flag register */
+
+
+ /* is this our interrupt? */
+/*
+ if (!(flag & (1 << HDMI_IRQ_CEC))) {
+ return IRQ_NONE;
+ }
+*/
+ status = __s5p_cec_get_status();
+
+ if (status & CEC_STATUS_TX_DONE) {
+ if (status & CEC_STATUS_TX_ERROR) {
+ CECIFPRINTK(" CEC_STATUS_TX_ERROR!\n");
+ __s5p_cec_set_tx_state(STATE_ERROR);
+ } else {
+ CECIFPRINTK(" CEC_STATUS_TX_DONE!\n");
+ __s5p_cec_set_tx_state(STATE_DONE);
+ }
+
+ __s5p_clr_pending_tx();
+
+
+ wake_up_interruptible(&cec_tx_struct.waitq);
+ }
+
+ if (status & CEC_STATUS_RX_DONE) {
+ if (status & CEC_STATUS_RX_ERROR) {
+ CECIFPRINTK(" CEC_STATUS_RX_ERROR!\n");
+ __s5p_cec_rx_reset();
+
+ } else {
+ u32 size;
+
+ CECIFPRINTK(" CEC_STATUS_RX_DONE!\n");
+
+ /* copy data from internal buffer */
+ size = status >> 24;
+
+ spin_lock(&cec_rx_struct.lock);
+
+ __s5p_cec_get_rx_buf(size, cec_rx_struct.buffer);
+
+ cec_rx_struct.size = size;
+
+ __s5p_cec_set_rx_state(STATE_DONE);
+
+ spin_unlock(&cec_rx_struct.lock);
+
+ __s5p_cec_enable_rx();
+ }
+
+ /* clear interrupt pending bit */
+ __s5p_clr_pending_rx();
+
+
+ wake_up_interruptible(&cec_rx_struct.waitq);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int __init s5p_cec_probe(struct platform_device *pdev)
+{
+ u8 *buffer;
+ int irq_num;
+ int ret;
+
+ s3c_gpio_cfgpin(S5PV210_GPH1(4), S3C_GPIO_SFN(0x4));
+ s3c_gpio_setpull(S5PV210_GPH1(4), S3C_GPIO_PULL_NONE);
+
+ /* get ioremap addr */
+ __s5p_cec_probe(pdev);
+
+ if (misc_register(&cec_misc_device)) {
+ printk(KERN_WARNING " Couldn't register device 10, %d.\n",
+ CEC_MINOR);
+ return -EBUSY;
+ }
+
+ irq_num = platform_get_irq(pdev, 0);
+ if (irq_num < 0) {
+ printk(KERN_ERR "failed to get %s irq resource\n", "cec");
+ ret = -ENOENT;
+ return ret;
+ }
+
+ ret = request_irq(irq_num, s5p_cec_irq_handler, IRQF_DISABLED,
+ pdev->name, &pdev->id);
+ if (ret != 0) {
+ printk(KERN_ERR "failed to install %s irq (%d)\n", "cec", ret);
+ return ret;
+ }
+
+
+ init_waitqueue_head(&cec_rx_struct.waitq);
+ spin_lock_init(&cec_rx_struct.lock);
+ init_waitqueue_head(&cec_tx_struct.waitq);
+
+ buffer = kmalloc(CEC_TX_BUFF_SIZE, GFP_KERNEL);
+
+ if (!buffer) {
+ printk(KERN_ERR " kmalloc() failed!\n");
+ misc_deregister(&cec_misc_device);
+ return -EIO;
+ }
+
+ cec_rx_struct.buffer = buffer;
+
+ cec_rx_struct.size = 0;
+
+ return 0;
+}
+
+/*
+ * Remove
+ */
+static int s5p_cec_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+
+#ifdef CONFIG_PM
+/*
+ * Suspend
+ */
+int s5p_cec_suspend(struct platform_device *dev, pm_message_t state)
+{
+ if (hdmi_on)
+ s5p_tv_clk_gate(false);
+
+ return 0;
+}
+
+/*
+ * Resume
+ */
+int s5p_cec_resume(struct platform_device *dev)
+{
+ if (hdmi_on)
+ s5p_tv_clk_gate(true);
+
+ return 0;
+}
+#else
+#define s5p_cec_suspend NULL
+#define s5p_cec_resume NULL
+#endif
+
+static struct platform_driver s5p_cec_driver = {
+ .probe = s5p_cec_probe,
+ .remove = s5p_cec_remove,
+ .suspend = s5p_cec_suspend,
+ .resume = s5p_cec_resume,
+ .driver = {
+ .name = "s5p-cec",
+ .owner = THIS_MODULE,
+ },
+};
+
+static char banner[] __initdata =
+ "S5P CEC Driver, (c) 2010 Samsung Electronics\n";
+
+int __init s5p_cec_init(void)
+{
+ int ret;
+
+ printk(banner);
+
+ ret = platform_driver_register(&s5p_cec_driver);
+
+ if (ret) {
+ printk(KERN_ERR "Platform Device Register Failed %d\n", ret);
+ return -1;
+ }
+
+ return 0;
+}
+
+static void __exit s5p_cec_exit(void)
+{
+ kfree(cec_rx_struct.buffer);
+
+ platform_driver_unregister(&s5p_cec_driver);
+
+}
+
+module_init(s5p_cec_init);
+module_exit(s5p_cec_exit);
+
+MODULE_AUTHOR("SangPil Moon");
+MODULE_DESCRIPTION("SS5PC11X CEC driver");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/media/video/samsung/tv20/cec.h b/drivers/media/video/samsung/tv20/cec.h
new file mode 100644
index 0000000..58bcc6b
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/cec.h
@@ -0,0 +1,104 @@
+/* linux/drivers/media/video/samsung/tv20/cec.h
+ *
+ * cec interface header for Samsung TVOut driver
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/*#define CECDEBUG 1*/
+
+#include <linux/platform_device.h>
+
+#define VERSION "1.0" /* Driver version number */
+#define CEC_MINOR 242 /* Major 10, Minor 242, /dev/cec */
+
+#define CEC_MESSAGE_BROADCAST_MASK 0x0F
+#define CEC_MESSAGE_BROADCAST 0x0F
+
+#define CEC_FILTER_THRESHOLD 0x15
+
+/*
+ * @enum cec_state
+ * Defines all possible states of CEC software state machine
+ */
+enum cec_state {
+ STATE_RX,
+ STATE_TX,
+ STATE_DONE,
+ STATE_ERROR
+};
+
+/*
+ * @struct cec_rx_struct
+ * Holds CEC Rx state and data
+ */
+
+struct cec_rx_struct {
+ spinlock_t lock;
+ wait_queue_head_t waitq;
+ atomic_t state;
+ u8 *buffer;
+ unsigned int size;
+};
+
+/*
+ * @struct cec_tx_struct
+ * Holds CEC Tx state and data
+ */
+
+struct cec_tx_struct {
+ wait_queue_head_t waitq;
+ atomic_t state;
+};
+
+#define CEC_STATUS_TX_RUNNING (1<<0)
+#define CEC_STATUS_TX_TRANSFERRING (1<<1)
+#define CEC_STATUS_TX_DONE (1<<2)
+#define CEC_STATUS_TX_ERROR (1<<3)
+#define CEC_STATUS_TX_BYTES (0xFF<<8)
+#define CEC_STATUS_RX_RUNNING (1<<16)
+#define CEC_STATUS_RX_RECEIVING (1<<17)
+#define CEC_STATUS_RX_DONE (1<<18)
+#define CEC_STATUS_RX_ERROR (1<<19)
+#define CEC_STATUS_RX_BCAST (1<<20)
+#define CEC_STATUS_RX_BYTES (0xFF<<24)
+
+
+#define CEC_IOC_MAGIC 'c'
+
+/*
+ * CEC device request code to set logical address.
+ */
+#define CEC_IOC_SETLADDR _IOW(CEC_IOC_MAGIC, 0, unsigned int)
+
+
+/* CEC Rx buffer size */
+#define CEC_RX_BUFF_SIZE 16
+/* CEC Tx buffer size */
+#define CEC_TX_BUFF_SIZE 16
+
+extern void __s5p_cec_set_divider(void);
+extern void __s5p_cec_enable_rx(void);
+extern void __s5p_cec_mask_rx_interrupts(void);
+extern void __s5p_cec_unmask_rx_interrupts(void);
+extern void __s5p_cec_mask_tx_interrupts(void);
+extern void __s5p_cec_unmask_tx_interrupts(void);
+extern void __s5p_cec_set_tx_state(enum cec_state state);
+extern void __s5p_cec_set_rx_state(enum cec_state state);
+extern void __s5p_cec_reset(void);
+extern void __s5p_cec_tx_reset(void);
+extern void __s5p_cec_rx_reset(void);
+extern void __s5p_cec_threshold(void);
+extern void __s5p_cec_copy_packet(char *data, size_t count);
+extern void __s5p_cec_set_addr(u32 addr);
+extern u32 __s5p_cec_get_status(void);
+extern void __s5p_clr_pending_tx(void);
+extern void __s5p_clr_pending_rx(void);
+extern void __s5p_cec_get_rx_buf(u32 size, u8 *buffer);
+extern void __init __s5p_cec_probe(struct platform_device *pdev);
+
diff --git a/drivers/media/video/samsung/tv20/ddc.c b/drivers/media/video/samsung/tv20/ddc.c
new file mode 100644
index 0000000..2f949bc
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/ddc.c
@@ -0,0 +1,133 @@
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+
+#define I2C_DRIVERID_S5P_HDCP 510
+#define S5P_HDCP_I2C_ADDR 0x74
+
+const static u16 ignore[] = { I2C_CLIENT_END };
+const static u16 normal_addr[] = {
+ (S5P_HDCP_I2C_ADDR >> 1),
+ I2C_CLIENT_END
+};
+
+struct i2c_client *ddc_port;
+
+/*
+ * DDC read ftn.
+ */
+int ddc_read(u8 subaddr, u8 *data, u16 len)
+{
+ u8 addr = subaddr;
+ int ret = 0;
+
+ struct i2c_msg msg[] = {
+ [0] = {
+ .addr = ddc_port->addr,
+ .flags = 0,
+ .len = 1,
+ .buf = &addr
+ },
+ [1] = {
+ .addr = ddc_port->addr,
+ .flags = I2C_M_RD,
+ .len = len,
+ .buf = data
+ }
+ };
+
+ if (i2c_transfer(ddc_port->adapter, msg, 2) != 2)
+ ret = -EIO;
+
+ return ret;
+}
+EXPORT_SYMBOL(ddc_read);
+
+
+/*
+ * DDC_write ftn.
+ */
+int ddc_write(u8 *data, u16 len)
+{
+ int ret = 0;
+
+ if (i2c_master_send(ddc_port, (const char *) data, len) != len)
+ ret = -EIO;
+
+ return ret;
+}
+EXPORT_SYMBOL(ddc_write);
+
+/*
+ * i2c client ftn.
+ */
+static int __devinit ddc_probe(struct i2c_client *client,
+ const struct i2c_device_id *dev_id)
+{
+ int ret = 0;
+
+ ddc_port = client;
+
+ dev_info(&client->adapter->dev, "attached s5p_ddc "
+ "into i2c adapter successfully\n");
+
+ return ret;
+}
+
+static int ddc_remove(struct i2c_client *client)
+{
+ dev_info(&client->adapter->dev, "detached s5p_ddc "
+ "from i2c adapter successfully\n");
+
+ return 0;
+}
+
+static int ddc_suspend(struct i2c_client *cl, pm_message_t mesg)
+{
+ return 0;
+};
+
+static int ddc_resume(struct i2c_client *cl)
+{
+ return 0;
+};
+
+
+static struct i2c_device_id ddc_idtable[] = {
+ {"s5p_ddc", 0},
+};
+
+MODULE_DEVICE_TABLE(i2c, ddc_idtable);
+
+static struct i2c_driver ddc_driver = {
+ .driver = {
+ .name = "s5p_ddc",
+ },
+ .id_table = ddc_idtable,
+ .probe = ddc_probe,
+ .remove = __devexit_p(ddc_remove),
+ .address_list = &normal_addr,
+ .suspend = ddc_suspend,
+ .resume = ddc_resume,
+};
+
+static int __init ddc_init(void)
+{
+ return i2c_add_driver(&ddc_driver);
+}
+
+static void __exit ddc_exit(void)
+{
+ i2c_del_driver(&ddc_driver);
+}
+
+
+MODULE_AUTHOR("SangPil Moon <sangpil.moon@samsung.com>");
+MODULE_DESCRIPTION("Driver for SMDKV210 I2C DDC devices");
+
+MODULE_LICENSE("GPL");
+
+module_init(ddc_init);
+module_exit(ddc_exit);
+
+
diff --git a/drivers/media/video/samsung/tv20/ddc.h b/drivers/media/video/samsung/tv20/ddc.h
new file mode 100644
index 0000000..8e6982b
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/ddc.h
@@ -0,0 +1,7 @@
+/*
+ * i2c ddc port
+ */
+
+
+extern int ddc_read(u8 subaddr, u8 *data, u16 len);
+extern int ddc_write(u8 *data, u16 len);
diff --git a/drivers/media/video/samsung/tv20/hpd.c b/drivers/media/video/samsung/tv20/hpd.c
new file mode 100644
index 0000000..0edb72c
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/hpd.c
@@ -0,0 +1,394 @@
+/* linux/drivers/media/video/samsung/tv20/hpd.c
+ *
+ * hpd interface ftn file for Samsung TVOut driver
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/errno.h>
+#include <linux/wait.h>
+#include <linux/poll.h>
+#include <linux/irq.h>
+#include <linux/kobject.h>
+#include <linux/io.h>
+
+#include <mach/gpio.h>
+#include <plat/gpio-cfg.h>
+#include <mach/gpio-p1.h>
+#include <mach/regs-gpio.h>
+#include <mach/gpio.h>
+#include "s5p_tv.h"
+#include "hpd.h"
+
+/*#define HPDDEBUG*/
+#ifdef HPDDEBUG
+#define HPDIFPRINTK(fmt, args...) \
+ printk(KERN_INFO "[HPD_IF] %s: " fmt, __func__ , ## args)
+#else
+#define HPDIFPRINTK(fmt, args...)
+#endif
+
+static struct hpd_struct hpd_struct;
+
+static int last_hpd_state;
+atomic_t hdmi_status;
+atomic_t poll_state;
+
+static DECLARE_WORK(hpd_work, (void *)s5p_handle_cable);
+
+int s5p_hpd_get_state(void)
+{
+ return atomic_read(&hpd_struct.state);
+}
+
+int s5p_hpd_open(struct inode *inode, struct file *file)
+{
+ atomic_set(&poll_state, 1);
+
+ return 0;
+}
+
+int s5p_hpd_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+ssize_t s5p_hpd_read(struct file *file, char __user *buffer, size_t count,
+ loff_t *ppos)
+{
+ ssize_t retval;
+
+ spin_lock_irq(&hpd_struct.lock);
+
+ retval = put_user(atomic_read(&hpd_struct.state),
+ (unsigned int __user *) buffer);
+
+ atomic_set(&poll_state, -1);
+
+ spin_unlock_irq(&hpd_struct.lock);
+
+ return retval;
+}
+
+unsigned int s5p_hpd_poll(struct file *file, poll_table *wait)
+{
+ poll_wait(file, &hpd_struct.waitq, wait);
+
+ if (atomic_read(&poll_state) != -1)
+ return POLLIN | POLLRDNORM;
+
+ return 0;
+}
+
+static const struct file_operations hpd_fops = {
+ .owner = THIS_MODULE,
+ .open = s5p_hpd_open,
+ .release = s5p_hpd_release,
+ .read = s5p_hpd_read,
+ .poll = s5p_hpd_poll,
+};
+
+static struct miscdevice hpd_misc_device = {
+ HPD_MINOR,
+ "HPD",
+ &hpd_fops,
+};
+
+int s5p_hpd_set_hdmiint(void)
+{
+ /* EINT -> HDMI */
+
+ set_irq_type(IRQ_EINT13, IRQ_TYPE_NONE);
+
+ if (last_hpd_state)
+ s5p_hdmi_disable_interrupts(HDMI_IRQ_HPD_UNPLUG);
+ else
+ s5p_hdmi_disable_interrupts(HDMI_IRQ_HPD_PLUG);
+
+ atomic_set(&hdmi_status, HDMI_ON);
+
+ s3c_gpio_cfgpin(S5PV210_GPH1(5), S5PV210_GPH1_5_HDMI_HPD);
+ s3c_gpio_setpull(S5PV210_GPH1(5), S3C_GPIO_PULL_DOWN);
+ s3c_gpio_set_drvstrength(S5PV210_GPH1(5), S3C_GPIO_DRVSTR_4X);
+
+ s5p_hdmi_hpd_gen();
+
+ if (s5p_hdmi_get_hpd_status())
+ s5p_hdmi_enable_interrupts(HDMI_IRQ_HPD_UNPLUG);
+ else {
+ s5p_hdmi_enable_interrupts(HDMI_IRQ_HPD_PLUG);
+ printk("\n++ %d", __LINE__);
+ }
+ return 0;
+}
+EXPORT_SYMBOL(s5p_hpd_set_hdmiint);
+
+int s5p_hpd_set_eint(void)
+{
+ /* HDMI -> EINT */
+ atomic_set(&hdmi_status, HDMI_OFF);
+
+ s5p_hdmi_clear_pending(HDMI_IRQ_HPD_PLUG);
+ s5p_hdmi_clear_pending(HDMI_IRQ_HPD_UNPLUG);
+
+ s5p_hdmi_disable_interrupts(HDMI_IRQ_HPD_PLUG);
+ s5p_hdmi_disable_interrupts(HDMI_IRQ_HPD_UNPLUG);
+
+ s3c_gpio_cfgpin(S5PV210_GPH1(5), S5PV210_GPH1_5_EXT_INT31_5);
+ s3c_gpio_setpull(S5PV210_GPH1(5), S3C_GPIO_PULL_DOWN);
+ s3c_gpio_set_drvstrength(S5PV210_GPH1(5), S3C_GPIO_DRVSTR_4X);
+
+ printk(KERN_INFO "\n++ s5p_hpd_set_eint\n");
+ return 0;
+}
+EXPORT_SYMBOL(s5p_hpd_set_eint);
+
+int irq_eint(int irq)
+{
+ if (gpio_get_value(S5PV210_GPH1(5))) {
+ atomic_set(&hpd_struct.state, HPD_HI);
+ atomic_set(&poll_state, 1);
+
+ last_hpd_state = HPD_HI;
+ wake_up_interruptible(&hpd_struct.waitq);
+ } else {
+ atomic_set(&hpd_struct.state, HPD_LO);
+ atomic_set(&poll_state, 1);
+
+ last_hpd_state = HPD_LO;
+ wake_up_interruptible(&hpd_struct.waitq);
+ }
+
+ if (atomic_read(&hpd_struct.state))
+ set_irq_type(IRQ_EINT13, IRQ_TYPE_EDGE_FALLING);
+ else
+ set_irq_type(IRQ_EINT13, IRQ_TYPE_EDGE_RISING);
+
+ schedule_work(&hpd_work);
+
+ HPDIFPRINTK("%s\n", atomic_read(&hpd_struct.state) == HPD_HI ?
+ "HPD HI" : "HPD LO");
+
+ return IRQ_HANDLED;
+
+}
+
+int irq_hdmi(int irq)
+{
+ u8 flag;
+ int ret = IRQ_HANDLED;
+
+ /* read flag register */
+ flag = s5p_hdmi_get_interrupts();
+
+ if (s5p_hdmi_get_hpd_status())
+ s5p_hdmi_disable_interrupts(HDMI_IRQ_HPD_UNPLUG);
+ else
+ s5p_hdmi_disable_interrupts(HDMI_IRQ_HPD_PLUG);
+
+ s5p_hdmi_clear_pending(HDMI_IRQ_HPD_PLUG);
+ s5p_hdmi_clear_pending(HDMI_IRQ_HPD_UNPLUG);
+
+
+ /* is this our interrupt? */
+
+ if (!(flag & (1 << HDMI_IRQ_HPD_PLUG | 1 << HDMI_IRQ_HPD_UNPLUG))) {
+ ret = IRQ_NONE;
+ goto out;
+ }
+
+ if (flag == (1 << HDMI_IRQ_HPD_PLUG | 1 << HDMI_IRQ_HPD_UNPLUG)) {
+
+ HPDIFPRINTK("HPD_HI && HPD_LO\n");
+
+ if (last_hpd_state == HPD_HI && s5p_hdmi_get_hpd_status())
+ flag = 1 << HDMI_IRQ_HPD_UNPLUG;
+ else
+ flag = 1 << HDMI_IRQ_HPD_PLUG;
+ }
+
+ if (flag & (1 << HDMI_IRQ_HPD_PLUG)) {
+
+ s5p_hdmi_enable_interrupts(HDMI_IRQ_HPD_UNPLUG);
+
+ atomic_set(&hpd_struct.state, HPD_HI);
+ atomic_set(&poll_state, 1);
+
+ last_hpd_state = HPD_HI;
+ wake_up_interruptible(&hpd_struct.waitq);
+
+ s5p_hdcp_encrypt_stop(true);
+
+ HPDIFPRINTK("HPD_HI\n");
+
+ } else if (flag & (1 << HDMI_IRQ_HPD_UNPLUG)) {
+
+ s5p_hdcp_encrypt_stop(false);
+
+ s5p_hdmi_enable_interrupts(HDMI_IRQ_HPD_PLUG);
+
+ atomic_set(&hpd_struct.state, HPD_LO);
+ atomic_set(&poll_state, 1);
+
+ last_hpd_state = HPD_LO;
+ wake_up_interruptible(&hpd_struct.waitq);
+
+ HPDIFPRINTK("HPD_LO\n");
+ }
+
+ schedule_work(&hpd_work);
+
+out:
+ return IRQ_HANDLED;
+}
+
+/*
+ * HPD interrupt handler
+ *
+ * Handles interrupt requests from HPD hardware.
+ * Handler changes value of internal variable and notifies waiting thread.
+ */
+irqreturn_t s5p_hpd_irq_handler(int irq, void *dev_id)
+{
+ int ret = IRQ_HANDLED;
+
+ spin_lock_irq(&hpd_struct.lock);
+
+ /* check HDMI status */
+ if (atomic_read(&hdmi_status)) {
+ /* HDMI on */
+ ret = irq_hdmi(irq);
+ HPDIFPRINTK("HDMI HPD interrupt\n");
+ } else {
+ /* HDMI off */
+ ret = irq_eint(irq);
+ HPDIFPRINTK("EINT HPD interrupt\n");
+ }
+
+ spin_unlock_irq(&hpd_struct.lock);
+
+ return ret;
+}
+
+static int __init s5p_hpd_probe(struct platform_device *pdev)
+{
+ if (misc_register(&hpd_misc_device)) {
+ printk(KERN_WARNING " Couldn't register device 10, %d.\n",
+ HPD_MINOR);
+ return -EBUSY;
+ }
+
+ init_waitqueue_head(&hpd_struct.waitq);
+
+ spin_lock_init(&hpd_struct.lock);
+
+ atomic_set(&hpd_struct.state, -1);
+
+ atomic_set(&hdmi_status, HDMI_OFF);
+
+ s3c_gpio_cfgpin(S5PV210_GPH1(5), S5PV210_GPH1_5_EXT_INT31_5);
+ s3c_gpio_setpull(S5PV210_GPH1(5), S3C_GPIO_PULL_DOWN);
+ s3c_gpio_set_drvstrength(S5PV210_GPH1(5), S3C_GPIO_DRVSTR_4X);
+
+ if (gpio_get_value(S5PV210_GPH1(5))) {
+ atomic_set(&hpd_struct.state, HPD_HI);
+ last_hpd_state = HPD_HI;
+ } else {
+ atomic_set(&hpd_struct.state, HPD_LO);
+ last_hpd_state = HPD_LO;
+ }
+
+ set_irq_type(IRQ_EINT13, IRQ_TYPE_EDGE_BOTH);
+
+ if (request_irq(IRQ_EINT13, s5p_hpd_irq_handler, IRQF_DISABLED,
+ "hpd", s5p_hpd_irq_handler)) {
+ printk(KERN_ERR "failed to install %s irq\n", "hpd");
+ misc_deregister(&hpd_misc_device);
+ return -EIO;
+ }
+
+ s5p_hdmi_register_isr((void *) s5p_hpd_irq_handler, (u8)HDMI_IRQ_HPD_PLUG);
+ s5p_hdmi_register_isr((void *) s5p_hpd_irq_handler, (u8)HDMI_IRQ_HPD_UNPLUG);
+
+ return 0;
+}
+
+/*
+ * Remove
+ */
+static int s5p_hpd_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+
+
+#ifdef CONFIG_PM
+/*
+ * Suspend
+ */
+int s5p_hpd_suspend(struct platform_device *dev, pm_message_t state)
+{
+ return 0;
+}
+
+/*
+ * Resume
+ */
+int s5p_hpd_resume(struct platform_device *dev)
+{
+ return 0;
+}
+#else
+#define s5p_hpd_suspend NULL
+#define s5p_hpd_resume NULL
+#endif
+
+static struct platform_driver s5p_hpd_driver = {
+ .probe = s5p_hpd_probe,
+ .remove = s5p_hpd_remove,
+ .suspend = s5p_hpd_suspend,
+ .resume = s5p_hpd_resume,
+ .driver = {
+ .name = "s5p-hpd",
+ .owner = THIS_MODULE,
+ },
+};
+
+static char banner[] __initdata =
+ "S5P HPD Driver, (c) 2010 Samsung Electronics\n";
+
+int __init s5p_hpd_init(void)
+{
+ int ret;
+
+ printk(banner);
+
+ ret = platform_driver_register(&s5p_hpd_driver);
+
+ if (ret) {
+ printk(KERN_ERR "Platform Device Register Failed %d\n", ret);
+ return -1;
+ }
+
+ return 0;
+}
+
+static void __exit s5p_hpd_exit(void)
+{
+ misc_deregister(&hpd_misc_device);
+}
+
+module_init(s5p_hpd_init);
+module_exit(s5p_hpd_exit);
+
+
diff --git a/drivers/media/video/samsung/tv20/hpd.h b/drivers/media/video/samsung/tv20/hpd.h
new file mode 100644
index 0000000..4fa4d27
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/hpd.h
@@ -0,0 +1,36 @@
+/* linux/drivers/media/video/samsung/tv20/hpd.h
+ *
+ * hpd interface header file for Samsung TVOut driver
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#define VERSION "1.2" /* Driver version number */
+#define HPD_MINOR 243 /* Major 10, Minor 243, /dev/hpd */
+
+#define HPD_LO 0
+#define HPD_HI 1
+
+#define HDMI_ON 1
+#define HDMI_OFF 0
+
+struct hpd_struct {
+ spinlock_t lock;
+ wait_queue_head_t waitq;
+ atomic_t state;
+};
+
+extern int s5p_hpd_set_eint(void);
+extern int s5p_hpd_set_hdmiint(void);
+
+#define S5PV210_GPH1_4_HDMI_CEC (0x4 << 16)
+#define S5PV210_GPH1_4_EXT_INT31_4 (0xf << 16)
+
+#define S5PV210_GPH1_5_HDMI_HPD (0x4 << 20)
+#define S5PV210_GPH1_5_EXT_INT31_5 (0xf << 20)
+
diff --git a/drivers/media/video/samsung/tv20/s5p_stda_grp.c b/drivers/media/video/samsung/tv20/s5p_stda_grp.c
new file mode 100644
index 0000000..61bfba0
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/s5p_stda_grp.c
@@ -0,0 +1,1103 @@
+/* linux/drivers/media/video/samsung/tv20/s5p_stda_grp.c
+ *
+ * Graphic Layer ftn. file for Samsung TVOut driver
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/stddef.h>
+#include <linux/ioctl.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+
+#include "s5p_tv.h"
+
+#ifdef COFIG_TVOUT_DBG
+#define S5P_GRP_DEBUG 1
+#endif
+
+#ifdef S5P_GRP_DEBUG
+#define GRPPRINTK(fmt, args...) \
+ printk(KERN_INFO "\t[GRP] %s: " fmt, __func__ , ## args)
+#else
+#define GRPPRINTK(fmt, args...)
+#endif
+
+
+bool _s5p_grp_start(enum s5p_tv_vmx_layer vm_layer)
+{
+ enum s5p_tv_vmx_err merr;
+ struct s5p_tv_status *st = &s5ptv_status;
+
+ if (!(st->grp_layer_enable[0] || st->grp_layer_enable[1])) {
+
+ merr = __s5p_vm_init_status_reg(st->grp_burst,
+ st->grp_endian);
+
+ if (merr != VMIXER_NO_ERROR)
+ return false;
+ }
+
+#ifdef CONFIG_CPU_S5PC100
+ merr = __s5p_vm_init_layer(vm_layer,
+ true,
+ s5ptv_overlay[vm_layer].win_blending,
+ s5ptv_overlay[vm_layer].win.global_alpha,
+ s5ptv_overlay[vm_layer].priority,
+ s5ptv_overlay[vm_layer].fb.fmt.pixelformat,
+ s5ptv_overlay[vm_layer].blank_change,
+ s5ptv_overlay[vm_layer].pixel_blending,
+ s5ptv_overlay[vm_layer].pre_mul,
+ s5ptv_overlay[vm_layer].blank_color,
+ s5ptv_overlay[vm_layer].base_addr,
+ s5ptv_overlay[vm_layer].fb.fmt.bytesperline,
+ s5ptv_overlay[vm_layer].win.w.width,
+ s5ptv_overlay[vm_layer].win.w.height,
+ s5ptv_overlay[vm_layer].win.w.left,
+ s5ptv_overlay[vm_layer].win.w.top,
+ s5ptv_overlay[vm_layer].dst_rect.left,
+ s5ptv_overlay[vm_layer].dst_rect.top);
+#endif
+
+#ifdef CONFIG_CPU_S5PV210
+ merr = __s5p_vm_init_layer(s5ptv_status.tvout_param.disp_mode,
+ vm_layer,
+ true,
+ s5ptv_overlay[vm_layer].win_blending,
+ s5ptv_overlay[vm_layer].win.global_alpha,
+ s5ptv_overlay[vm_layer].priority,
+ s5ptv_overlay[vm_layer].fb.fmt.pixelformat,
+ s5ptv_overlay[vm_layer].blank_change,
+ s5ptv_overlay[vm_layer].pixel_blending,
+ s5ptv_overlay[vm_layer].pre_mul,
+ s5ptv_overlay[vm_layer].blank_color,
+ s5ptv_overlay[vm_layer].base_addr,
+ s5ptv_overlay[vm_layer].fb.fmt.bytesperline,
+ s5ptv_overlay[vm_layer].win.w.width,
+ s5ptv_overlay[vm_layer].win.w.height,
+ s5ptv_overlay[vm_layer].win.w.left,
+ s5ptv_overlay[vm_layer].win.w.top,
+ s5ptv_overlay[vm_layer].dst_rect.left,
+ s5ptv_overlay[vm_layer].dst_rect.top,
+ s5ptv_overlay[vm_layer].dst_rect.width,
+ s5ptv_overlay[vm_layer].dst_rect.height);
+#endif
+
+
+ if (merr != VMIXER_NO_ERROR) {
+ GRPPRINTK("can't initialize layer(%d)\n\r", merr);
+ return false;
+ }
+
+ __s5p_vm_start();
+
+
+ st->grp_layer_enable[vm_layer] = true;
+
+ GRPPRINTK("()\n\r");
+
+ return true;
+}
+
+bool _s5p_grp_stop(enum s5p_tv_vmx_layer vm_layer)
+{
+ enum s5p_tv_vmx_err merr;
+ struct s5p_tv_status *st = &s5ptv_status;
+
+ GRPPRINTK("()\n\r");
+
+ merr = __s5p_vm_set_layer_show(vm_layer, false);
+
+ if (merr != VMIXER_NO_ERROR)
+ return false;
+
+ merr = __s5p_vm_set_layer_priority(vm_layer, 0);
+
+ if (merr != VMIXER_NO_ERROR)
+ return false;
+
+ __s5p_vm_start();
+
+
+ st->grp_layer_enable[vm_layer] = false;
+
+ GRPPRINTK("()\n\r");
+
+ return true;
+}
+
+int s5ptvfb_set_output(struct s5p_tv_status *ctrl) { return 0; }
+
+int s5ptvfb_set_display_mode(struct s5p_tv_status *ctrl)
+{
+ enum s5p_tv_vmx_layer layer = VM_GPR0_LAYER;
+ bool premul = false;
+ bool pixel_blending = false;
+ bool blank_change = false;
+ bool win_blending = false;
+ u32 blank_color = 0x0;
+ enum s5p_tv_vmx_color_fmt color;
+ u32 bpp;
+ u32 alpha = 0;
+
+ bpp = ((struct fb_var_screeninfo)(ctrl->fb->var)).bits_per_pixel;
+
+ if (bpp == 32)
+ color = VM_DIRECT_RGB8888;
+ else
+ color = VM_DIRECT_RGB565;
+
+ __s5p_vm_set_ctrl(layer, premul, pixel_blending, blank_change,
+ win_blending, color, alpha, blank_color);
+
+ return 0;
+}
+
+int s5ptvfb_display_on(struct s5p_tv_status *ctrl)
+{
+ __s5p_vm_set_layer_priority(VM_GPR0_LAYER, 10);
+ __s5p_vm_set_layer_show(VM_GPR0_LAYER, true);
+
+ return 0;
+}
+
+int s5ptvfb_display_off(struct s5p_tv_status *ctrl)
+{
+ __s5p_vm_set_layer_priority(VM_GPR0_LAYER, 10);
+ __s5p_vm_set_layer_show(VM_GPR0_LAYER, false);
+
+ return 0;
+}
+
+int s5ptvfb_frame_off(struct s5p_tv_status *ctrl) { return 0; }
+int s5ptvfb_set_clock(struct s5p_tv_status *ctrl) { return 0; }
+int s5ptvfb_set_polarity(struct s5p_tv_status *ctrl) { return 0; }
+int s5ptvfb_set_timing(struct s5p_tv_status *ctrl) { return 0; }
+int s5ptvfb_set_lcd_size(struct s5p_tv_status *ctrl) { return 0; }
+int s5ptvfb_window_on(struct s5p_tv_status *ctrl, int id)
+{
+ __s5p_vm_set_layer_show(VM_GPR0_LAYER, true);
+
+ return 0;
+}
+
+int s5ptvfb_window_off(struct s5p_tv_status *ctrl, int id)
+{
+ __s5p_vm_set_layer_show(VM_GPR0_LAYER, false);
+ return 0;
+}
+
+int s5ptvfb_set_window_control(struct s5p_tv_status *ctrl, int id) { return 0; }
+int s5ptvfb_set_alpha_blending(struct s5p_tv_status *ctrl, int id) { return 0; }
+int s5ptvfb_set_window_position(struct s5p_tv_status *ctrl, int id)
+{
+ u32 off_x, off_y;
+ u32 w_t, h_t;
+ u32 w, h;
+
+ struct fb_var_screeninfo *var = &ctrl->fb->var;
+ struct s5ptvfb_window *win = ctrl->fb->par;
+
+ off_x = (u32)win->x;
+ off_y = (u32)win->y;
+
+ w = var->xres;
+ h = var->yres;
+
+ /*
+ * When tvout resolution was overscanned, there is no
+ * adjust method in H/W. So, framebuffer should be resized.
+ * In this case - TV w/h is greater than FB w/h, grp layer's
+ * dst offset must be changed to fix tv screen.
+ */
+
+ switch (ctrl->tvout_param.disp_mode) {
+
+ case TVOUT_NTSC_M:
+ case TVOUT_480P_60_16_9:
+ case TVOUT_480P_60_4_3:
+ case TVOUT_480P_59:
+ w_t = 720;
+ h_t = 480;
+ break;
+
+ case TVOUT_576P_50_16_9:
+ case TVOUT_576P_50_4_3:
+ w_t = 720;
+ h_t = 576;
+ break;
+
+ case TVOUT_720P_60:
+ case TVOUT_720P_59:
+ case TVOUT_720P_50:
+ w_t = 1280;
+ h_t = 720;
+ break;
+
+ case TVOUT_1080I_60:
+ case TVOUT_1080I_59:
+ case TVOUT_1080I_50:
+ case TVOUT_1080P_60:
+ case TVOUT_1080P_59:
+ case TVOUT_1080P_50:
+ case TVOUT_1080P_30:
+ w_t = 1920;
+ h_t = 1080;
+ break;
+
+ default:
+ w_t = 0;
+ h_t = 0;
+ break;
+ }
+
+ if (w_t > w)
+ off_x = (w_t - w) / 2;
+
+ if (h_t > h)
+ off_y = (h_t - h) / 2;
+
+ __s5p_vm_set_grp_layer_position(VM_GPR0_LAYER, off_x, off_y);
+
+ return 0;
+}
+
+int s5ptvfb_set_window_size(struct s5p_tv_status *ctrl, int id)
+{
+ struct fb_var_screeninfo *var = &ctrl->fb->var;
+ int w, h, xo, yo;
+
+ w = var->xres;
+ h = var->yres;
+ xo = var->xoffset;
+ yo = var->yoffset;
+
+ __s5p_vm_set_grp_layer_size(VM_GPR0_LAYER, w, w, h, xo, yo);
+
+
+ dev_dbg(ctrl->dev_fb, "[fb%d] resolution: %d x %d\n", id,
+ var->xres, var->yres);
+
+ return 0;
+}
+int s5ptvfb_set_buffer_address(struct s5p_tv_status *ctrl, int id)
+{
+ struct fb_fix_screeninfo *fix = &ctrl->fb->fix;
+ struct fb_var_screeninfo *var = &ctrl->fb->var;
+ dma_addr_t start_addr = 0, end_addr = 0;
+
+ if (fix->smem_start) {
+ start_addr = fix->smem_start + (var->xres_virtual *
+ (var->bits_per_pixel / 8) * var->yoffset);
+
+ end_addr = start_addr + (var->xres_virtual *
+ (var->bits_per_pixel / 8) * var->yres);
+ }
+
+ __s5p_vm_set_grp_base_address(VM_GPR0_LAYER, start_addr);
+ return 0;
+}
+
+int s5ptvfb_set_buffer_size(struct s5p_tv_status *ctrl, int id) { return 0; }
+
+int s5ptvfb_set_chroma_key(struct s5p_tv_status *ctrl, int id)
+{
+ struct s5ptvfb_window *win = ctrl->fb->par;
+ struct s5ptvfb_chroma *chroma = &win->chroma;
+
+ enum s5p_tv_vmx_layer layer = VM_GPR0_LAYER;
+
+ bool blank_change = (chroma->enabled) ? true : false;
+ u32 blank_color = chroma->key;
+
+ bool win_blending = (chroma->blended) ? true : false;
+ bool alpha = chroma->alpha;
+
+ enum s5p_tv_vmx_color_fmt color = VM_DIRECT_RGB8888;
+
+ __s5p_vm_set_ctrl(layer, false, false, blank_change,
+ win_blending, color, alpha, blank_color);
+
+ return 0;
+}
+
+
+
+
+static inline unsigned int __chan_to_field(unsigned int chan,
+ struct fb_bitfield bf)
+{
+ chan &= 0xffff;
+ chan >>= 16 - bf.length;
+
+ return chan << bf.offset;
+}
+
+static int s5ptvfb_set_alpha_info(struct fb_var_screeninfo *var,
+ struct s5ptvfb_window *win)
+{
+ if (var->transp.length > 0)
+ win->alpha.mode = PIXEL_BLENDING;
+ else {
+ win->alpha.mode = PLANE_BLENDING;
+ win->alpha.channel = 0;
+ win->alpha.value = S5PTVFB_AVALUE(0xf, 0xf, 0xf);
+ }
+
+ return 0;
+}
+
+
+static int s5ptvfb_enable_window(int id)
+{
+ struct s5ptvfb_window *win = s5ptv_status.fb->par;
+
+ if (s5ptvfb_window_on(&s5ptv_status, id)) {
+ win->enabled = 0;
+ return -EFAULT;
+ } else {
+ win->enabled = 1;
+ return 0;
+ }
+}
+
+
+static int s5ptvfb_disable_window(int id)
+{
+ struct s5ptvfb_window *win = s5ptv_status.fb->par;
+
+ if (s5ptvfb_window_off(&s5ptv_status, id)) {
+ win->enabled = 1;
+ return -EFAULT;
+ } else {
+ win->enabled = 0;
+ return 0;
+ }
+}
+
+int s5ptvfb_unmap_video_memory(struct fb_info *fb)
+{
+ struct fb_fix_screeninfo *fix = &fb->fix;
+ struct s5ptvfb_window *win = fb->par;
+
+ if (fix->smem_start) {
+ dma_free_writecombine(s5ptv_status.dev_fb, fix->smem_len,
+ fb->screen_base, fix->smem_start);
+ fix->smem_start = 0;
+ fix->smem_len = 0;
+ dev_info(s5ptv_status.dev_fb,
+ "[fb%d] video memory released\n", win->id);
+ }
+
+ return 0;
+}
+
+static int s5ptvfb_release_window(struct fb_info *fb)
+{
+ struct s5ptvfb_window *win = fb->par;
+
+ win->x = 0;
+ win->y = 0;
+
+ return 0;
+}
+
+int s5ptvfb_map_video_memory(struct fb_info *fb)
+{
+ struct fb_fix_screeninfo *fix = &fb->fix;
+ struct s5ptvfb_window *win = fb->par;
+
+ if (win->path == DATA_PATH_FIFO)
+ return 0;
+
+ fb->screen_base = dma_alloc_writecombine(s5ptv_status.dev_fb,
+ PAGE_ALIGN(fix->smem_len),
+ (unsigned int *) &fix->smem_start, GFP_KERNEL);
+ if (!fb->screen_base)
+ return -ENOMEM;
+ else
+ dev_info(s5ptv_status.dev_fb,
+ "[fb%d] dma: 0x%08x, cpu: 0x%08x,size: 0x%08x\n",
+ win->id, (unsigned int) fix->smem_start,
+ (unsigned int) fb->screen_base,
+ fix->smem_len);
+
+ memset(fb->screen_base, 0, fix->smem_len);
+
+ return 0;
+}
+
+
+static int s5ptvfb_set_bitfield(struct fb_var_screeninfo *var)
+{
+ switch (var->bits_per_pixel) {
+ case 16:
+ if (var->transp.length == 1) {
+ var->red.offset = 10;
+ var->red.length = 5;
+ var->green.offset = 5;
+ var->green.length = 5;
+ var->blue.offset = 0;
+ var->blue.length = 5;
+ var->transp.offset = 15;
+ } else if (var->transp.length == 4) {
+ var->red.offset = 8;
+ var->red.length = 4;
+ var->green.offset = 4;
+ var->green.length = 4;
+ var->blue.offset = 0;
+ var->blue.length = 4;
+ var->transp.offset = 12;
+ } else {
+ var->red.offset = 11;
+ var->red.length = 5;
+ var->green.offset = 5;
+ var->green.length = 6;
+ var->blue.offset = 0;
+ var->blue.length = 5;
+ var->transp.offset = 0;
+ }
+ break;
+
+ case 24:
+ var->red.offset = 16;
+ var->red.length = 8;
+ var->green.offset = 8;
+ var->green.length = 8;
+ var->blue.offset = 0;
+ var->blue.length = 8;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ break;
+
+ case 32:
+ var->red.offset = 16;
+ var->red.length = 8;
+ var->green.offset = 8;
+ var->green.length = 8;
+ var->blue.offset = 0;
+ var->blue.length = 8;
+ var->transp.offset = 24;
+ break;
+ }
+
+ return 0;
+}
+
+#define TV_LOGO_W 800
+#define TV_LOGO_H 480
+
+int s5ptvfb_draw_logo(struct fb_info *fb)
+{
+#if 0
+ struct fb_fix_screeninfo *fix = &fb->fix;
+ int i;
+
+/* memcpy(s5ptv_status.fb->screen_base,
+ TV_LOGO_RGB24, fix->line_length * var->yres);
+ */
+ char *base = s5ptv_status.fb->screen_base;
+
+ for (i = 0; i < TV_LOGO_H; i++) {
+ memcpy(base, &TV_LOGO_RGB24[i*TV_LOGO_W], TV_LOGO_W * 4);
+ base += fix->line_length;
+ }
+#endif
+ return 0;
+}
+
+static int s5ptvfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+ /* nothing to do for removing cursor */
+ return 0;
+}
+
+
+static int s5ptvfb_setcolreg(unsigned int regno, unsigned int red,
+ unsigned int green, unsigned int blue,
+ unsigned int transp, struct fb_info *fb)
+{
+ unsigned int *pal = (unsigned int *) fb->pseudo_palette;
+ unsigned int val = 0;
+
+ if (regno < 16) {
+ /* fake palette of 16 colors */
+ val |= __chan_to_field(red, fb->var.red);
+ val |= __chan_to_field(green, fb->var.green);
+ val |= __chan_to_field(blue, fb->var.blue);
+ val |= __chan_to_field(transp, fb->var.transp);
+
+ pal[regno] = val;
+ }
+
+ return 0;
+}
+
+
+static int s5ptvfb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *fb)
+{
+ struct s5ptvfb_window *win = fb->par;
+
+ if (var->yoffset + var->yres > var->yres_virtual) {
+ dev_err(s5ptv_status.dev_fb, "invalid yoffset value\n");
+ return -EINVAL;
+ }
+
+ fb->var.yoffset = var->yoffset;
+
+ dev_dbg(s5ptv_status.dev_fb, "[fb%d] yoffset for pan display: %d\n",
+ win->id,
+ var->yoffset);
+
+ s5ptvfb_set_buffer_address(&s5ptv_status, win->id);
+
+ return 0;
+}
+
+
+static int s5ptvfb_blank(int blank_mode, struct fb_info *fb)
+{
+ struct s5ptvfb_window *win = fb->par;
+
+ dev_dbg(s5ptv_status.dev_fb, "change blank mode\n");
+
+ switch (blank_mode) {
+ case FB_BLANK_UNBLANK:
+ if (fb->fix.smem_start) {
+ s5ptvfb_display_on(&s5ptv_status);
+ s5ptvfb_enable_window(win->id);
+ } else
+ dev_info(s5ptv_status.dev_fb,
+ "[fb%d] no allocated memory for unblank\n",
+ win->id);
+ break;
+
+ case FB_BLANK_POWERDOWN:
+ s5ptvfb_display_off(&s5ptv_status);
+ s5ptvfb_disable_window(win->id);
+ break;
+
+ default:
+ dev_dbg(s5ptv_status.dev_fb, "unsupported blank mode\n");
+ /* return -EINVAL; */
+ }
+
+ return 0;
+}
+
+int s5ptvfb_set_par(struct fb_info *fb)
+{
+ struct s5ptvfb_window *win = fb->par;
+
+ dev_dbg(s5ptv_status.dev_fb, "[fb%d] set_par\n", win->id);
+
+ if (!fb->fix.smem_start) {
+#ifndef CONFIG_USER_ALLOC_TVOUT
+ GRPPRINTK(" The frame buffer is allocated here\n");
+ s5ptvfb_map_video_memory(fb);
+#else
+ printk(KERN_ERR
+ "[Warning] The frame buffer should be allocated by ioctl\n");
+#endif
+ }
+
+ ((struct fb_var_screeninfo) (s5ptv_status.fb->var)).bits_per_pixel =
+ ((struct fb_var_screeninfo) (fb->var)).bits_per_pixel;
+
+ s5ptvfb_set_display_mode(&s5ptv_status);
+
+ s5ptvfb_set_window_control(&s5ptv_status, win->id);
+ s5ptvfb_set_window_position(&s5ptv_status, win->id);
+ s5ptvfb_set_window_size(&s5ptv_status, win->id);
+ s5ptvfb_set_buffer_address(&s5ptv_status, win->id);
+ s5ptvfb_set_buffer_size(&s5ptv_status, win->id);
+
+ if (win->id > 0)
+ s5ptvfb_set_alpha_blending(&s5ptv_status, win->id);
+
+ return 0;
+}
+
+int s5ptvfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fb)
+{
+ struct fb_fix_screeninfo *fix = &fb->fix;
+ struct s5ptvfb_window *win = fb->par;
+ struct s5ptvfb_lcd *lcd = s5ptv_status.lcd;
+
+ dev_dbg(s5ptv_status.dev_fb, "[fb%d] check_var\n", win->id);
+
+ if (var->bits_per_pixel != 16 && var->bits_per_pixel != 24 &&
+ var->bits_per_pixel != 32) {
+ dev_err(s5ptv_status.dev_fb, "invalid bits per pixel\n");
+ return -EINVAL;
+ }
+
+ if (var->xres > lcd->width)
+ var->xres = lcd->width;
+
+ if (var->yres > lcd->height)
+ var->yres = lcd->height;
+
+ if (var->xres_virtual != var->xres)
+ var->xres_virtual = var->xres;
+
+ if (var->yres_virtual > var->yres * (fb->fix.ypanstep + 1))
+ var->yres_virtual = var->yres * (fb->fix.ypanstep + 1);
+
+ if (var->xoffset != 0)
+ var->xoffset = 0;
+
+ if (var->yoffset + var->yres > var->yres_virtual)
+ var->yoffset = var->yres_virtual - var->yres;
+
+ if (win->x + var->xres > lcd->width)
+ win->x = lcd->width - var->xres;
+
+ if (win->y + var->yres > lcd->height)
+ win->y = lcd->height - var->yres;
+
+ /* modify the fix info */
+ fix->line_length = var->xres_virtual * var->bits_per_pixel / 8;
+ fix->smem_len = fix->line_length * var->yres_virtual;
+
+
+ s5ptvfb_set_bitfield(var);
+ s5ptvfb_set_alpha_info(var, win);
+
+ return 0;
+}
+
+static int s5ptvfb_release(struct fb_info *fb, int user)
+{
+/*
+ * Following block is deleted for enabling multiple open of TV frame buffer
+ *
+ * struct s5ptvfb_window *win = fb->par;
+ */
+ int ret;
+ struct s5ptvfb_window *win = fb->par;
+
+ s5ptvfb_release_window(fb);
+
+/*
+ * Following block is deleted for enabling multiple open of TV frame buffer
+ *
+ * mutex_lock(&s5ptv_status.fb_lock);
+ * atomic_dec(&win->in_use);
+ * mutex_unlock(&s5ptv_status.fb_lock);
+ */
+
+ _s5p_vlayer_stop();
+ _s5p_tv_if_stop();
+
+ s5ptv_status.hdcp_en = false;
+
+ s5ptv_status.tvout_output_enable = false;
+
+ /*
+ * drv. release
+ * - just check drv. state reg. or not.
+ */
+
+ ret = s5p_tv_clk_gate(false);
+ if (ret < 0) {
+ printk(KERN_ERR "[Error]Cannot release\n");
+ return -1;
+ }
+ tv_phy_power(false);
+
+ mutex_lock(&s5ptv_status.fb_lock);
+ atomic_dec(&win->in_use);
+ mutex_unlock(&s5ptv_status.fb_lock);
+
+ return 0;
+}
+
+static int s5ptvfb_ioctl(struct fb_info *fb, unsigned int cmd,
+ unsigned long arg)
+{
+ struct fb_var_screeninfo *var = &fb->var;
+ struct s5ptvfb_window *win = fb->par;
+ struct s5ptvfb_lcd *lcd = s5ptv_status.lcd;
+ int ret = 0;
+ void *argp = (void *) arg;
+
+ union {
+ struct s5ptvfb_user_window user_window;
+ struct s5ptvfb_user_plane_alpha user_alpha;
+ struct s5ptvfb_user_chroma user_chroma;
+ int vsync;
+ } p;
+
+ switch (cmd) {
+
+ case FBIO_ALLOC:
+ win->path = (enum s5ptvfb_data_path_t) argp;
+ break;
+
+ case FBIOGET_FSCREENINFO:
+ ret = memcpy(argp, &fb->fix, sizeof(fb->fix)) ? 0 : -EFAULT;
+ break;
+
+ case FBIOGET_VSCREENINFO:
+ ret = memcpy(argp, &fb->var, sizeof(fb->var)) ? 0 : -EFAULT;
+ break;
+
+ case FBIOPUT_VSCREENINFO:
+ ret = s5ptvfb_check_var((struct fb_var_screeninfo *) argp, fb);
+ if (ret) {
+ dev_err(s5ptv_status.dev_fb, "invalid vscreeninfo\n");
+ break;
+ }
+
+ ret = memcpy(&fb->var, (struct fb_var_screeninfo *) argp,
+ sizeof(fb->var)) ? 0 : -EFAULT;
+ if (ret) {
+ dev_err(s5ptv_status.dev_fb,
+ "failed to put new vscreeninfo\n");
+ break;
+ }
+
+ ret = s5ptvfb_set_par(fb);
+ break;
+
+ case S5PTVFB_WIN_POSITION:
+ if (copy_from_user(&p.user_window,
+ (struct s5ptvfb_user_window __user *) arg,
+ sizeof(p.user_window)))
+ ret = -EFAULT;
+ else {
+ if (p.user_window.x < 0)
+ p.user_window.x = 0;
+
+ if (p.user_window.y < 0)
+ p.user_window.y = 0;
+
+ if (p.user_window.x + var->xres > lcd->width)
+ win->x = lcd->width - var->xres;
+ else
+ win->x = p.user_window.x;
+
+ if (p.user_window.y + var->yres > lcd->height)
+ win->y = lcd->height - var->yres;
+ else
+ win->y = p.user_window.y;
+
+ s5ptvfb_set_window_position(&s5ptv_status, win->id);
+ }
+ break;
+
+ case S5PTVFB_WIN_SET_PLANE_ALPHA:
+ if (copy_from_user(&p.user_alpha,
+ (struct s5ptvfb_user_plane_alpha __user *) arg,
+ sizeof(p.user_alpha)))
+ ret = -EFAULT;
+ else {
+ win->alpha.mode = PLANE_BLENDING;
+ win->alpha.channel = p.user_alpha.channel;
+ win->alpha.value =
+ S5PTVFB_AVALUE(p.user_alpha.red,
+ p.user_alpha.green,
+ p.user_alpha.blue);
+
+ s5ptvfb_set_alpha_blending(&s5ptv_status, win->id);
+ }
+ break;
+
+ case S5PTVFB_WIN_SET_CHROMA:
+ if (copy_from_user(&p.user_chroma,
+ (struct s5ptvfb_user_chroma __user *) arg,
+ sizeof(p.user_chroma)))
+ ret = -EFAULT;
+ else {
+ win->chroma.enabled = p.user_chroma.enabled;
+ win->chroma.key = S5PTVFB_CHROMA(p.user_chroma.red,
+ p.user_chroma.green,
+ p.user_chroma.blue);
+
+ s5ptvfb_set_chroma_key(&s5ptv_status, win->id);
+ }
+ break;
+
+ case S5PTVFB_WIN_SET_ADDR:
+ fb->fix.smem_start = (unsigned long)argp;
+ s5ptvfb_set_buffer_address(&s5ptv_status, win->id);
+ break;
+
+ case S5PTVFB_SET_WIN_ON:
+#ifdef CONFIG_USER_ALLOC_TVOUT
+ s5ptvfb_display_on(&s5ptv_status);
+ s5ptvfb_enable_window(0);
+#endif
+ break;
+
+ case S5PTVFB_SET_WIN_OFF:
+#ifdef CONFIG_USER_ALLOC_TVOUT
+ s5ptvfb_display_off(&s5ptv_status);
+ s5ptvfb_disable_window(0);
+#endif
+ break;
+
+ }
+
+ return 0;
+}
+
+static int s5ptvfb_open(struct fb_info *fb, int user)
+{
+ struct s5ptvfb_window *win = fb->par;
+ int ret = 0;
+
+ ret = s5p_tv_clk_gate(true);
+ if (ret < 0) {
+ printk(KERN_ERR "[Error]Cannot open it\n");
+ return -1;
+ }
+
+ tv_phy_power(true);
+
+ _s5p_tv_if_init_param();
+
+ s5p_tv_v4l2_init_param();
+
+ /* s5ptv_status.tvout_param.disp_mode = TVOUT_720P_60; */
+ s5ptv_status.tvout_param.out_mode = TVOUT_OUTPUT_HDMI_RGB;
+
+ _s5p_tv_if_set_disp();
+
+#ifndef CONFIG_USER_ALLOC_TVOUT
+ s5ptvfb_display_on(&s5ptv_status);
+
+ s5ptvfb_enable_window(0);
+#endif
+
+ mutex_lock(&s5ptv_status.fb_lock);
+
+ if (atomic_read(&win->in_use)) {
+ dev_dbg(s5ptv_status.dev_fb,
+ "do not allow multiple open "
+ "for window\n");
+ ret = -EBUSY;
+
+ } else
+ atomic_inc(&win->in_use);
+
+ mutex_unlock(&s5ptv_status.fb_lock);
+
+ return ret;
+
+}
+
+struct fb_ops s5ptvfb_ops = {
+ .owner = THIS_MODULE,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+ .fb_check_var = s5ptvfb_check_var,
+ .fb_set_par = s5ptvfb_set_par,
+ .fb_blank = s5ptvfb_blank,
+ .fb_pan_display = s5ptvfb_pan_display,
+ .fb_setcolreg = s5ptvfb_setcolreg,
+ .fb_cursor = s5ptvfb_cursor,
+ .fb_ioctl = s5ptvfb_ioctl,
+ .fb_open = s5ptvfb_open,
+ .fb_release = s5ptvfb_release,
+};
+
+int s5ptvfb_direct_ioctl(int id, unsigned int cmd, unsigned long arg)
+{
+ struct fb_info *fb = s5ptv_status.fb;
+ struct fb_fix_screeninfo *fix = &fb->fix;
+ struct s5ptvfb_window *win = fb->par;
+ void *argp = (void *) arg;
+ int ret = 0;
+
+ switch (cmd) {
+
+ case FBIO_ALLOC:
+ win->path = (enum s5ptvfb_data_path_t) argp;
+ break;
+
+ case FBIOGET_FSCREENINFO:
+ ret = memcpy(argp, &fb->fix, sizeof(fb->fix)) ? 0 : -EFAULT;
+ break;
+
+ case FBIOGET_VSCREENINFO:
+ ret = memcpy(argp, &fb->var, sizeof(fb->var)) ? 0 : -EFAULT;
+ break;
+
+ case FBIOPUT_VSCREENINFO:
+ ret = s5ptvfb_check_var((struct fb_var_screeninfo *) argp, fb);
+ if (ret) {
+ dev_err(s5ptv_status.dev_fb, "invalid vscreeninfo\n");
+ break;
+ }
+
+ ret = memcpy(&fb->var, (struct fb_var_screeninfo *) argp,
+ sizeof(fb->var)) ? 0 : -EFAULT;
+ if (ret) {
+ dev_err(s5ptv_status.dev_fb,
+ "failed to put new vscreeninfo\n");
+ break;
+ }
+
+ ret = s5ptvfb_set_par(fb);
+ break;
+
+ case S5PTVFB_SET_WIN_ON:
+#ifdef CONFIG_USER_ALLOC_TVOUT
+ s5ptvfb_display_on(&s5ptv_status);
+ s5ptvfb_enable_window(0);
+#endif
+ break;
+
+ case S5PTVFB_SET_WIN_OFF:
+#ifdef CONFIG_USER_ALLOC_TVOUT
+ s5ptvfb_display_off(&s5ptv_status);
+ s5ptvfb_disable_window(0);
+#endif
+ break;
+
+ case S5PTVFB_POWER_ON:
+ s5p_tv_clk_gate(true);
+ tv_phy_power(true);
+
+ _s5p_tv_if_init_param();
+
+ s5p_tv_v4l2_init_param();
+
+ /* s5ptv_status.tvout_param.disp_mode = TVOUT_720P_60; */
+ s5ptv_status.tvout_param.out_mode = TVOUT_OUTPUT_HDMI;
+
+ _s5p_tv_if_set_disp();
+
+ break;
+
+ case S5PTVFB_POWER_OFF:
+ _s5p_vlayer_stop();
+ _s5p_tv_if_stop();
+
+ s5p_tv_clk_gate(false);
+ tv_phy_power(false);
+ break;
+
+ case S5PTVFB_WIN_SET_ADDR:
+ fix->smem_start = (unsigned long)argp;
+ s5ptvfb_set_buffer_address(&s5ptv_status, win->id);
+ break;
+
+ default:
+ ret = s5ptvfb_ioctl(fb, cmd, arg);
+ break;
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(s5ptvfb_direct_ioctl);
+
+int s5ptvfb_init_fbinfo(int id)
+{
+ struct fb_info *fb = s5ptv_status.fb;
+ struct fb_fix_screeninfo *fix = &fb->fix;
+ struct fb_var_screeninfo *var = &fb->var;
+ struct s5ptvfb_window *win = fb->par;
+ struct s5ptvfb_alpha *alpha = &win->alpha;
+ struct s5ptvfb_lcd *lcd = s5ptv_status.lcd;
+ struct s5ptvfb_lcd_timing *timing = &lcd->timing;
+
+ memset(win, 0, sizeof(struct s5ptvfb_window));
+
+ platform_set_drvdata(to_platform_device(s5ptv_status.dev_fb), fb);
+
+ strcpy(fix->id, S5PTVFB_NAME);
+
+ /* fimd specific */
+ win->id = id;
+ win->path = DATA_PATH_DMA;
+ win->dma_burst = 16;
+ alpha->mode = PLANE_BLENDING;
+
+ /* fbinfo */
+ fb->fbops = &s5ptvfb_ops;
+ fb->flags = FBINFO_FLAG_DEFAULT;
+ fb->pseudo_palette = &win->pseudo_pal;
+ fix->xpanstep = 0;
+ fix->ypanstep = 0;
+ fix->type = FB_TYPE_PACKED_PIXELS;
+ fix->accel = FB_ACCEL_NONE;
+ fix->visual = FB_VISUAL_TRUECOLOR;
+ var->xres = lcd->width;
+ var->yres = lcd->height;
+ var->xres_virtual = var->xres;
+ var->yres_virtual = var->yres + (var->yres * fix->ypanstep);
+ var->bits_per_pixel = 32;
+ var->xoffset = 0;
+ var->yoffset = 0;
+ var->width = 0;
+ var->height = 0;
+ var->transp.length = 0;
+
+ fix->line_length = var->xres_virtual * var->bits_per_pixel / 8;
+ fix->smem_len = fix->line_length * var->yres_virtual;
+
+ var->nonstd = 0;
+ var->activate = FB_ACTIVATE_NOW;
+ var->vmode = FB_VMODE_NONINTERLACED;
+ var->hsync_len = timing->h_sw;
+ var->vsync_len = timing->v_sw;
+ var->left_margin = timing->h_fp;
+ var->right_margin = timing->h_bp;
+ var->upper_margin = timing->v_fp;
+ var->lower_margin = timing->v_bp;
+
+ var->pixclock = lcd->freq * (var->left_margin + var->right_margin +
+ var->hsync_len + var->xres) *
+ (var->upper_margin + var->lower_margin +
+ var->vsync_len + var->yres);
+
+ dev_dbg(s5ptv_status.dev_fb, "pixclock: %d\n", var->pixclock);
+
+ s5ptvfb_set_bitfield(var);
+ s5ptvfb_set_alpha_info(var, win);
+
+ return 0;
+}
+
+static struct s5ptvfb_lcd max_tvfb = {
+ .width = 1920,
+ .height = 1080,
+ .bpp = 32,
+ .freq = 60,
+
+ .timing = {
+ .h_fp = 49,
+ .h_bp = 17,
+ .h_sw = 33,
+ .v_fp = 4,
+ .v_fpe = 1,
+ .v_bp = 15,
+ .v_bpe = 1,
+ .v_sw = 6,
+ },
+
+ .polarity = {
+ .rise_vclk = 0,
+ .inv_hsync = 1,
+ .inv_vsync = 1,
+ .inv_vden = 0,
+ },
+};
+
+void s5ptvfb_set_lcd_info(struct s5p_tv_status *ctrl)
+{
+ ctrl->lcd = &max_tvfb;
+}
diff --git a/drivers/media/video/samsung/tv20/s5p_stda_hdmi.c b/drivers/media/video/samsung/tv20/s5p_stda_hdmi.c
new file mode 100644
index 0000000..15e90ad
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/s5p_stda_hdmi.c
@@ -0,0 +1,242 @@
+/* linux/drivers/media/video/samsung/tv20/s5p_stda_hdmi.c
+ *
+ * HDMI ftn. file for Samsung TVOut driver
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/stddef.h>
+#include <linux/ioctl.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include "s5p_tv.h"
+
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+
+#ifdef COFIG_TVOUT_DBG
+#define S5P_STDA_HDMI_DEBUG 1
+#endif
+
+#ifdef S5P_STDA_HDMI_DEBUG
+#define STHDPRINTK(fmt, args...) \
+ printk(KERN_INFO "\t[STDA_HDMI] %s: " fmt, __func__ , ## args)
+#else
+#define STHDPRINTK(fmt, args...)
+#endif
+
+/*
+static bool _s5p_hdmi_spd_infoframe(unsigned long p_buf_in)
+{
+ STHDPRINTK("(0x%x)\n\r", (unsigned int)p_buf_in);
+
+ if (!p_buf_in)
+ {
+ STHDPRINTK("(ERR) p_buf_in is NULL\n\r");
+ return false;
+ }
+
+ memcpy((void *)(&(s5ptv_status.hdmi_spd_info_frame)),
+ (const void *)p_buf_in, sizeof(s5p_hdmi_spd_infoframe));
+
+ memcpy((void *)(s5ptv_status.spd_header),
+ (const void *)(s5ptv_status.hdmi_spd_info_frame.spd_header), 3);
+ s5ptv_status.hdmi_spd_info_frame.spd_header = s5ptv_status.spd_header;
+
+ memcpy((void *)(s5ptv_status.spd_data),
+ (const void *)(s5ptv_status.hdmi_spd_info_frame.spd_data), 28);
+ s5ptv_status.hdmi_spd_info_frame.spd_data = s5ptv_status.spd_data;
+
+ STHDPRINTK("(0x%08x)\n\r",
+ (unsigned int)&s5ptv_status.hdmi_spd_info_frame);
+
+ return true;
+}
+*/
+
+#if 0
+static bool _s5p_hdmi_init_hdcp_en(unsigned long p_buf_in)
+{
+ if (!p_buf_in) {
+ STHDPRINTK("(ERR) p_buf_in is NULL\n\r");
+ return false;
+ }
+
+ STHDPRINTK("(%d)\n\r", (bool)p_buf_in);
+
+ s5ptv_status.hdcp_en = (bool)p_buf_in;
+
+ STHDPRINTK("(%d)\n\r", s5ptv_status.hdcp_en);
+
+ return true;
+}
+
+static bool _s5p_hdmi_init_audio(unsigned long p_buf_in)
+{
+ STHDPRINTK("(%d)\n\r", (bool)p_buf_in);
+
+ if (!p_buf_in) {
+ STHDPRINTK("(ERR) p_buf_in is NULL\n\r");
+ return false;
+ }
+
+ s5ptv_status.hdmi_audio_type = (enum s5p_hdmi_audio_type)p_buf_in;
+
+ STHDPRINTK("(%d)\n\r", s5ptv_status.hdmi_audio_type);
+
+ return true;
+}
+
+static bool _s5p_hdmi_get_hpd_status(unsigned long p_buf_out)
+{
+ bool *pOut;
+
+ STHDPRINTK("()\n\r");
+
+ if (!p_buf_out) {
+ STHDPRINTK("(ERR) p_buf_out is NULL\n\r");
+ return false;
+ }
+
+ pOut = (bool *)p_buf_out;
+
+ *pOut = s5ptv_status.hpd_status;
+
+ STHDPRINTK("()\n\r");
+
+ return true;
+}
+
+static bool _s5p_hdmi_wait_hpd_status_change(unsigned long p_buf_out)
+{
+ unsigned int *pOut;
+
+ STHDPRINTK("()\n\r");
+
+ if (!p_buf_out) {
+ STHDPRINTK("(ERR) p_buf_out is NULL\n\r");
+ return false;
+ }
+
+ pOut = (unsigned int *)p_buf_out;
+
+
+ /*
+ if (*pOut == WAIT_TIMEOUT)
+ {
+ STHDPRINTK("(ERR) TIMEOUT~\n\r");
+ }
+ else if (*pOut == WAIT_FAILED)
+ {
+ STHDPRINTK("(ERR) WAIT_FAILED\n\r");
+ }
+ */
+
+ return true;
+}
+
+#endif
+
+/*============================================================================*/
+
+/*
+static bool _s5p_hdmi_video_init_bluescreen(unsigned long p_buf_in)
+{
+
+ STHDPRINTK("(0x%x)\n\r", (unsigned int)p_buf_in);
+
+ if (!p_buf_in)
+ {
+ STHDPRINTK("(ERR) p_buf_in is NULL\n\r");
+ return false;
+ }
+
+ memcpy((void *)(&(s5ptv_status.hdmi_video_blue_screen)),
+ (const void *)p_buf_in, sizeof(s5p_hdmi_bluescreen));
+
+ STHDPRINTK("(0x%08x)\n\r",
+ (unsigned int)&s5ptv_status.hdmi_video_blue_screen);
+
+ return true;
+}
+
+static bool _s5p_hdmi_video_init_avi_infoframe(unsigned long p_buf_in)
+{
+ STHDPRINTK("(0x%x)\n\r", (unsigned int)p_buf_in);
+
+ if (!p_buf_in)
+ {
+ STHDPRINTK("(ERR) p_buf_in is NULL\n\r");
+ return false;
+ }
+
+ memcpy((void *)(&(s5ptv_status.hdmi_av_info_frame)),
+ (const void *)p_buf_in, sizeof(s5p_hdmi_video_infoframe));
+
+ memcpy((void *)(s5ptv_status.avi_byte),
+ (const void *)(s5ptv_status.hdmi_av_info_frame.data), 13);
+ s5ptv_status.hdmi_av_info_frame.data = s5ptv_status.avi_byte;
+
+ STHDPRINTK("(0x%08x)\n\r",
+ (unsigned int)&s5ptv_status.hdmi_av_info_frame);
+
+ return true;
+}
+
+static bool _s5p_hdmi_video_init_mpg_infoframe(unsigned long p_buf_in)
+{
+ STHDPRINTK("(0x%x)\n\r", (unsigned int)p_buf_in);
+
+ if (!p_buf_in)
+ {
+ STHDPRINTK("(ERR) p_buf_in is NULL\n\r");
+ return false;
+ }
+
+ memcpy((void *)(&(s5ptv_status.hdmi_mpg_info_frame)),
+ (const void *)p_buf_in, sizeof(s5p_hdmi_video_infoframe));
+
+ memcpy((void *)(s5ptv_status.mpg_byte),
+ (const void *)(s5ptv_status.hdmi_mpg_info_frame.data), 5);
+ s5ptv_status.hdmi_mpg_info_frame.data = s5ptv_status.avi_byte;
+
+ STHDPRINTK("(0x%08x)\n\r",
+ (unsigned int)&s5ptv_status.hdmi_mpg_info_frame);
+
+ return true;
+}
+
+static bool _s5p_hdmi_video_set_bluescreen(unsigned long p_buf_in)
+{
+ STHDPRINTK("(0x%x)\n\r", (unsigned int)p_buf_in);
+
+ if (!p_buf_in)
+ {
+ STHDPRINTK("(ERR) p_buf_in is NULL\n\r");
+ return false;
+ }
+
+ memcpy((void *)(&(s5ptv_status.hdmi_video_blue_screen)),
+ (const void *)p_buf_in, sizeof(s5p_hdmi_bluescreen));
+
+ __s5p_hdmi_video_set_bluescreen(s5ptv_status.hdmi_video_blue_screen.en,
+ s5ptv_status.hdmi_video_blue_screen.cb_b,
+ s5ptv_status.hdmi_video_blue_screen.y_g,
+ s5ptv_status.hdmi_video_blue_screen.cr_r);
+
+ STHDPRINTK("(0x%08x)\n\r",
+ (unsigned int)&s5ptv_status.hdmi_video_blue_screen);
+
+ return true;
+}
+
+*/
+
diff --git a/drivers/media/video/samsung/tv20/s5p_stda_tvout_if.c b/drivers/media/video/samsung/tv20/s5p_stda_tvout_if.c
new file mode 100644
index 0000000..2d22d9e
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/s5p_stda_tvout_if.c
@@ -0,0 +1,1261 @@
+/* linux/drivers/media/video/samsung/tv20/s5p_stda_tvout_if.c
+ *
+ * TVOut interface ftn. file for Samsung TVOut driver
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/stddef.h>
+#include <linux/ioctl.h>
+#include <linux/fs.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <linux/delay.h>
+
+#include <plat/clock.h>
+
+#include "s5p_tv.h"
+
+#ifdef COFIG_TVOUT_DBG
+#define S5P_STDA_TVOUTIF_DEBUG 1
+#endif
+
+#ifdef S5P_STDA_TVOUTIF_DEBUG
+#define TVOUTIFPRINTK(fmt, args...) \
+ printk(KERN_INFO "\t[TVOUT_IF] %s: " fmt, __func__ , ## args)
+#else
+#define TVOUTIFPRINTK(fmt, args...)
+#endif
+
+bool _s5p_tv_if_init_param(void)
+{
+ struct s5p_tv_status *st = &s5ptv_status;
+
+ /* Initialize GRPx Layer Parameters to Default Values */
+ st->grp_burst = VM_BURST_16;
+ st->grp_endian = TVOUT_LITTLE_ENDIAN_MODE;
+
+ /* Initialize BG Layer Parameters to Default Values */
+ st->bg_dither.cr_dither_en = false;
+ st->bg_dither.cb_dither_en = false;
+ st->bg_dither.y_dither_en = false;
+
+ st->bg_color[0].color_y = 0;
+ st->bg_color[0].color_cb = 128;
+ st->bg_color[0].color_cr = 128;
+ st->bg_color[1].color_y = 0;
+ st->bg_color[1].color_cb = 128;
+ st->bg_color[1].color_cr = 128;
+ st->bg_color[2].color_y = 0;
+ st->bg_color[2].color_cb = 128;
+ st->bg_color[2].color_cr = 128;
+
+ /* Initialize Video Mixer Parameters to Default Values */
+ st->vm_csc_coeff_default = true;
+
+ /* Initialize SDout Parameters to Default Values */
+ st->sdout_sync_pin = SDOUT_SYNC_SIG_YG;
+ st->sdout_vbi.wss_cvbs = true;
+ st->sdout_vbi.caption_cvbs = SDOUT_INS_OTHERS;
+ st->sdout_vbi.wss_y_svideo = true;
+ st->sdout_vbi.caption_y_svideo = SDOUT_INS_OTHERS;
+ st->sdout_vbi.cgmsa_rgb = true;
+ st->sdout_vbi.wss_rgb = true;
+ st->sdout_vbi.caption_rgb = SDOUT_INS_OTHERS;
+ st->sdout_vbi.cgmsa_y_pb_pr = true;
+ st->sdout_vbi.wss_y_pb_pr = true;
+ st->sdout_vbi.caption_y_pb_pr = SDOUT_INS_OTHERS;
+ st->sdout_offset_gain[0].channel = SDOUT_CHANNEL_0;
+ st->sdout_offset_gain[0].offset = 0;
+ st->sdout_offset_gain[0].gain = 0x800;
+ st->sdout_offset_gain[1].channel = SDOUT_CHANNEL_1;
+ st->sdout_offset_gain[1].offset = 0;
+ st->sdout_offset_gain[1].gain = 0x800;
+ st->sdout_offset_gain[2].channel = SDOUT_CHANNEL_2;
+ st->sdout_offset_gain[2].offset = 0;
+ st->sdout_offset_gain[2].gain = 0x800;
+ st->sdout_delay.delay_y = 0x00;
+ st->sdout_delay.offset_video_start = 0xfa;
+ st->sdout_delay.offset_video_end = 0x00;
+ st->sdout_color_sub_carrier_phase_adj = false;
+ st->sdout_bri_hue_set.bright_hue_sat_adj = false;
+ st->sdout_bri_hue_set.gain_brightness = 0x80;
+ st->sdout_bri_hue_set.offset_brightness = 0x00;
+ st->sdout_bri_hue_set.gain0_cb_hue_saturation = 0x00;
+ st->sdout_bri_hue_set.gain1_cb_hue_saturation = 0x00;
+ st->sdout_bri_hue_set.gain0_cr_hue_saturation = 0x00;
+ st->sdout_bri_hue_set.gain1_cr_hue_saturation = 0x00;
+ st->sdout_bri_hue_set.offset_cb_hue_saturation = 0x00;
+ st->sdout_bri_hue_set.offset_cr_hue_saturation = 0x00;
+ st->sdout_y_pb_pr_comp = false;
+ st->sdout_rgb_compen.rgb_color_compensation = false;
+ st->sdout_rgb_compen.max_rgb_cube = 0xeb;
+ st->sdout_rgb_compen.min_rgb_cube = 0x10;
+ st->sdout_cvbs_compen.cvbs_color_compensation = false;
+ st->sdout_cvbs_compen.y_lower_mid = 0x200;
+ st->sdout_cvbs_compen.y_bottom = 0x000;
+ st->sdout_cvbs_compen.y_top = 0x3ff;
+ st->sdout_cvbs_compen.y_upper_mid = 0x200;
+ st->sdout_cvbs_compen.radius = 0x1ff;
+ st->sdout_svideo_compen.y_color_compensation = false;
+ st->sdout_svideo_compen.y_top = 0x3ff;
+ st->sdout_svideo_compen.y_bottom = 0x000;
+ st->sdout_svideo_compen.yc_cylinder = 0x1ff;
+ st->sdout_comp_porch.back_525 = 0x8a;
+ st->sdout_comp_porch.front_525 = 0x359;
+ st->sdout_comp_porch.back_625 = 0x96;
+ st->sdout_comp_porch.front_625 = 0x35c;
+ st->sdout_rgb_sync.sync_type = SDOUT_VESA_RGB_SYNC_COMPOSITE;
+ st->sdout_rgb_sync.vsync_active = TVOUT_POL_ACTIVE_HIGH;
+ st->sdout_rgb_sync.hsync_active = TVOUT_POL_ACTIVE_HIGH;
+ st->sdout_xtalk_cc[0].channel = SDOUT_CHANNEL_0;
+ st->sdout_xtalk_cc[0].coeff2 = 0;
+ st->sdout_xtalk_cc[0].coeff1 = 0;
+ st->sdout_xtalk_cc[1].channel = SDOUT_CHANNEL_1;
+ st->sdout_xtalk_cc[1].coeff2 = 0;
+ st->sdout_xtalk_cc[1].coeff1 = 0;
+ st->sdout_xtalk_cc[2].channel = SDOUT_CHANNEL_2;
+ st->sdout_xtalk_cc[2].coeff2 = 0;
+ st->sdout_xtalk_cc[2].coeff1 = 0;
+ st->sdout_closed_capt.display_cc = 0;
+ st->sdout_closed_capt.nondisplay_cc = 0;
+ st->sdout_wss_525.copy_permit = SDO_525_COPY_PERMIT;
+ st->sdout_wss_525.mv_psp = SDO_525_MV_PSP_OFF;
+ st->sdout_wss_525.copy_info = SDO_525_COPY_INFO;
+ st->sdout_wss_525.analog_on = false;
+ st->sdout_wss_525.display_ratio = SDO_525_4_3_NORMAL;
+ st->sdout_wss_625.surroun_f_sound = false;
+ st->sdout_wss_625.copyright = false;
+ st->sdout_wss_625.copy_protection = false;
+ st->sdout_wss_625.text_subtitles = false;
+ st->sdout_wss_625.open_subtitles = SDO_625_NO_OPEN_SUBTITLES;
+ st->sdout_wss_625.camera_film = SDO_625_CAMERA;
+ st->sdout_wss_625.color_encoding = SDO_625_NORMAL_PAL;
+ st->sdout_wss_625.helper_signal = false;
+ st->sdout_wss_625.display_ratio = SDO_625_4_3_FULL_576;
+ st->sdout_cgms_525.copy_permit = SDO_525_COPY_PERMIT;
+ st->sdout_cgms_525.mv_psp = SDO_525_MV_PSP_OFF;
+ st->sdout_cgms_525.copy_info = SDO_525_COPY_INFO;
+ st->sdout_cgms_525.analog_on = false;
+ st->sdout_cgms_525.display_ratio = SDO_525_4_3_NORMAL;
+ st->sdout_cgms_625.surroun_f_sound = false;
+ st->sdout_cgms_625.copyright = false;
+ st->sdout_cgms_625.copy_protection = false;
+ st->sdout_cgms_625.text_subtitles = false;
+ st->sdout_cgms_625.open_subtitles = SDO_625_NO_OPEN_SUBTITLES;
+ st->sdout_cgms_625.camera_film = SDO_625_CAMERA;
+ st->sdout_cgms_625.color_encoding = SDO_625_NORMAL_PAL;
+ st->sdout_cgms_625.helper_signal = false;
+ st->sdout_cgms_625.display_ratio = SDO_625_4_3_FULL_576;
+
+ /* Initialize HDMI video Parameters to Default Values */
+ st->hdmi_video_blue_screen.enable = false;
+ st->hdmi_color_range.y_min = 1;
+ st->hdmi_color_range.y_max = 254;
+ st->hdmi_color_range.c_min = 1;
+ st->hdmi_color_range.c_max = 254;
+ st->hdmi_av_info_frame.trans_type = HDMI_DO_NOT_TANS;
+ st->hdmi_av_info_frame.check_sum = 0;
+ st->hdmi_av_info_frame.data = st->avi_byte;
+ st->hdmi_mpg_info_frame.trans_type = HDMI_DO_NOT_TANS;
+ st->hdmi_mpg_info_frame.check_sum = 0;
+ st->hdmi_mpg_info_frame.data = st->mpg_byte;
+ memset((void *)(st->avi_byte), 0, 13);
+ memset((void *)(st->mpg_byte), 0, 5);
+ st->hdmi_tg_cmd.timing_correction_en = false;
+ st->hdmi_tg_cmd.bt656_sync_en = false;
+ st->hdmi_tg_cmd.tg_en = false;
+
+ /* Initialize HDMI Parameters to Default Values */
+ st->hdmi_spd_info_frame.trans_type = HDMI_TRANS_EVERY_SYNC;
+ st->hdmi_spd_info_frame.spd_header = NULL;
+ st->hdmi_spd_info_frame.spd_data = NULL;
+
+ st->hdcp_en = false;
+ st->hdmi_audio_type = HDMI_AUDIO_PCM;
+
+ st->tvout_param_available = true;
+
+ return true;
+}
+
+
+bool _s5p_tv_if_init_vm_reg(void)
+{
+ u8 i = 0;
+ enum s5p_tv_vmx_err merr = 0;
+ struct s5p_tv_status *st = &s5ptv_status;
+ enum s5p_tv_o_mode out_mode = st->tvout_param.out_mode;
+ enum s5p_tv_disp_mode disp_mode = st->tvout_param.disp_mode;
+
+ bool cr_en = st->bg_dither.cr_dither_en;
+ bool cb_en = st->bg_dither.cr_dither_en;
+ bool y_en = st->bg_dither.cr_dither_en;
+
+ enum s5p_vmx_burst_mode burst = st->grp_burst;
+ enum s5p_endian_type endian = st->grp_endian;
+
+
+ merr = __s5p_vm_init_status_reg(burst, endian);
+
+ if (merr != VMIXER_NO_ERROR)
+ return false;
+
+
+ merr = __s5p_vm_init_display_mode(disp_mode, out_mode);
+
+ if (merr != VMIXER_NO_ERROR)
+ return false;
+
+
+ __s5p_vm_init_bg_dither_enable(cr_en, cb_en, y_en);
+
+ for (i = VMIXER_BG_COLOR_0; i <= VMIXER_BG_COLOR_2; i++) {
+ merr = __s5p_vm_init_bg_color(i,
+ st->bg_color[i].color_y,
+ st->bg_color[i].color_cb,
+ st->bg_color[i].color_cr);
+
+ if (merr != VMIXER_NO_ERROR)
+ return false;
+ }
+
+ switch (out_mode) {
+
+ case TVOUT_OUTPUT_COMPOSITE:
+
+ case TVOUT_OUTPUT_SVIDEO:
+
+ case TVOUT_OUTPUT_COMPONENT_YPBPR_INERLACED:
+
+ case TVOUT_OUTPUT_COMPONENT_YPBPR_PROGRESSIVE:
+
+ case TVOUT_OUTPUT_COMPONENT_RGB_PROGRESSIVE:
+ __s5p_vm_init_csc_coef_default(VMIXER_CSC_RGB_TO_YUV601_FR);
+ break;
+
+ case TVOUT_OUTPUT_HDMI_RGB:
+ case TVOUT_OUTPUT_HDMI:
+ case TVOUT_OUTPUT_DVI:
+
+ switch (disp_mode) {
+
+ case TVOUT_NTSC_M:
+
+ case TVOUT_PAL_BDGHI:
+
+ case TVOUT_PAL_M:
+
+ case TVOUT_PAL_N:
+
+ case TVOUT_PAL_NC:
+
+ case TVOUT_PAL_60:
+
+ case TVOUT_NTSC_443:
+ break;
+
+ case TVOUT_480P_60_16_9:
+
+ case TVOUT_480P_60_4_3:
+#ifdef CONFIG_CPU_S5PV210
+ case TVOUT_480P_59:
+#endif
+ case TVOUT_576P_50_16_9:
+
+ case TVOUT_576P_50_4_3:
+ __s5p_vm_init_csc_coef_default(
+ VMIXER_CSC_RGB_TO_YUV601_FR);
+ break;
+
+ case TVOUT_720P_60:
+
+ case TVOUT_720P_50:
+
+#ifdef CONFIG_CPU_S5PV210
+ case TVOUT_720P_59:
+
+ case TVOUT_1080I_60:
+
+ case TVOUT_1080I_59:
+
+ case TVOUT_1080I_50:
+
+ case TVOUT_1080P_60:
+
+ case TVOUT_1080P_30:
+
+ case TVOUT_1080P_59:
+
+ case TVOUT_1080P_50:
+#endif
+ __s5p_vm_init_csc_coef_default(
+ VMIXER_CSC_RGB_TO_YUV709_FR);
+ break;
+ }
+
+ break;
+
+ default:
+ TVOUTIFPRINTK("invalid tvout_param.out_mode parameter(%d)\n\r",
+ out_mode);
+ return false;
+ break;
+ }
+
+ __s5p_vm_start();
+
+ return true;
+}
+
+bool _s5p_tv_if_init_sd_reg(void)
+{
+ u8 i = 0;
+ enum s5p_tv_sd_err sderr = 0;
+ struct s5p_tv_status *st = &s5ptv_status;
+ enum s5p_tv_o_mode out_mode = st->tvout_param.out_mode;
+ enum s5p_tv_disp_mode disp_mode = st->tvout_param.disp_mode;
+ enum s5p_sd_order order = st->sdout_order;
+
+ u32 delay = st->sdout_delay.delay_y;
+ u32 off_v_start = st->sdout_delay.offset_video_start;
+ u32 off_v_end = st->sdout_delay.offset_video_end;
+
+ u32 g_bright = st->sdout_bri_hue_set.gain_brightness;
+ u32 off_bright = st->sdout_bri_hue_set.offset_brightness;
+ u32 g0_cb_h_sat = st->sdout_bri_hue_set.gain0_cb_hue_saturation;
+ u32 g1_cb_h_sat = st->sdout_bri_hue_set.gain1_cb_hue_saturation;
+ u32 g0_cr_h_sat = st->sdout_bri_hue_set.gain0_cr_hue_saturation;
+ u32 g1_cr_h_sat = st->sdout_bri_hue_set.gain1_cr_hue_saturation;
+ u32 off_cb_h_sat = st->sdout_bri_hue_set.offset_cb_hue_saturation;
+ u32 off_cr_h_sat = st->sdout_bri_hue_set.offset_cr_hue_saturation;
+
+ u32 max_rgb_cube = st->sdout_rgb_compen.max_rgb_cube;
+ u32 min_rgb_cube = st->sdout_rgb_compen.min_rgb_cube;
+ u32 y_l_m_c = st->sdout_cvbs_compen.y_lower_mid;
+ u32 y_b_c = st->sdout_cvbs_compen.y_bottom;
+ u32 y_t_c = st->sdout_cvbs_compen.y_top;
+ u32 y_u_m_c = st->sdout_cvbs_compen.y_upper_mid;
+ u32 rad_c = st->sdout_cvbs_compen.radius;
+ u32 y_t_s = st->sdout_svideo_compen.y_top;
+ u32 y_b_s = st->sdout_svideo_compen.y_bottom;
+ u32 y_cylinder_s = st->sdout_svideo_compen.yc_cylinder;
+
+ u32 back_525 = st->sdout_comp_porch.back_525;
+ u32 front_525 = st->sdout_comp_porch.front_525;
+ u32 back_625 = st->sdout_comp_porch.back_625;
+ u32 front_625 = st->sdout_comp_porch.front_625;
+
+ u32 display_cc = st->sdout_closed_capt.display_cc;
+ u32 nondisplay_cc = st->sdout_closed_capt.nondisplay_cc;
+
+ bool br_hue_sat_adj = st->sdout_bri_hue_set.bright_hue_sat_adj;
+ bool wss_cvbs = st->sdout_vbi.wss_cvbs;
+ bool wss_y_svideo = st->sdout_vbi.wss_y_svideo;
+ bool cgmsa_rgb = st->sdout_vbi.cgmsa_rgb;
+ bool wss_rgb = st->sdout_vbi.wss_rgb;
+ bool cgmsa_y = st->sdout_vbi.cgmsa_y_pb_pr;
+ bool wss_y = st->sdout_vbi.wss_y_pb_pr;
+ bool phase_adj = st->sdout_color_sub_carrier_phase_adj;
+ bool ypbpr_comp = st->sdout_y_pb_pr_comp;
+ bool rgb_compen = st->sdout_rgb_compen.rgb_color_compensation;
+ bool y_compen = st->sdout_svideo_compen.y_color_compensation;
+ bool cvbs_compen = st->sdout_cvbs_compen.cvbs_color_compensation;
+
+ bool w5_analog_on = st->sdout_wss_525.analog_on;
+ bool w6_surroun_f_sound = st->sdout_wss_625.surroun_f_sound;
+ bool w6_copyright = st->sdout_wss_625.copyright;
+ bool w6_copy_protection = st->sdout_wss_625.copy_protection;
+ bool w6_text_subtitles = st->sdout_wss_625.text_subtitles;
+ bool w6_helper_signal = st->sdout_wss_625.helper_signal;
+
+ bool c5_analog_on = st->sdout_cgms_525.analog_on;
+ bool c6_surroun_f_sound = st->sdout_cgms_625.surroun_f_sound;
+ bool c6_copyright = st->sdout_cgms_625.copyright;
+ bool c6_copy_protection = st->sdout_cgms_625.copy_protection;
+ bool c6_text_subtitles = st->sdout_cgms_625.text_subtitles;
+ bool c6_helper_signal = st->sdout_cgms_625.helper_signal;
+
+ enum s5p_sd_level cpn_lev = st->sdout_video_scale_cfg.component_level;
+ enum s5p_sd_level cps_lev = st->sdout_video_scale_cfg.composite_level;
+ enum s5p_sd_vsync_ratio cpn_rat =
+ st->sdout_video_scale_cfg.component_ratio;
+ enum s5p_sd_vsync_ratio cps_rat =
+ st->sdout_video_scale_cfg.composite_ratio;
+ enum s5p_sd_closed_caption_type cap_cvbs = st->sdout_vbi.caption_cvbs;
+ enum s5p_sd_closed_caption_type cap_y_svideo =
+ st->sdout_vbi.caption_y_svideo;
+ enum s5p_sd_closed_caption_type cap_rgb = st->sdout_vbi.caption_rgb;
+ enum s5p_sd_closed_caption_type cap_y_pb_pr =
+ st->sdout_vbi.caption_y_pb_pr;
+ enum s5p_sd_sync_sig_pin sync_pin = st->sdout_sync_pin;
+ enum s5p_sd_vesa_rgb_sync_type sync_type =
+ st->sdout_rgb_sync.sync_type;
+ enum s5p_tv_active_polarity vsync_active =
+ st->sdout_rgb_sync.vsync_active;
+ enum s5p_tv_active_polarity hsync_active =
+ st->sdout_rgb_sync.hsync_active;
+
+ enum s5p_sd_525_copy_permit w5_copy_permit =
+ st->sdout_wss_525.copy_permit;
+ enum s5p_sd_525_mv_psp w5_mv_psp = st->sdout_wss_525.mv_psp;
+ enum s5p_sd_525_copy_info w5_copy_info = st->sdout_wss_525.copy_info;
+ enum s5p_sd_525_aspect_ratio w5_display_ratio =
+ st->sdout_wss_525.display_ratio;
+ enum s5p_sd_625_subtitles w6_open_subtitles =
+ st->sdout_wss_625.open_subtitles;
+ enum s5p_sd_625_camera_film w6_camera_film =
+ st->sdout_wss_625.camera_film;
+ enum s5p_sd_625_color_encoding w6_color_encoding =
+ st->sdout_wss_625.color_encoding;
+ enum s5p_sd_625_aspect_ratio w6_display_ratio =
+ st->sdout_wss_625.display_ratio;
+
+ enum s5p_sd_525_copy_permit c5_copy_permit =
+ st->sdout_cgms_525.copy_permit;
+ enum s5p_sd_525_mv_psp c5_mv_psp = st->sdout_cgms_525.mv_psp;
+ enum s5p_sd_525_copy_info c5_copy_info =
+ st->sdout_cgms_525.copy_info;
+ enum s5p_sd_525_aspect_ratio c5_display_ratio =
+ st->sdout_cgms_525.display_ratio;
+ enum s5p_sd_625_subtitles c6_open_subtitles =
+ st->sdout_cgms_625.open_subtitles;
+ enum s5p_sd_625_camera_film c6_camera_film =
+ st->sdout_cgms_625.camera_film;
+ enum s5p_sd_625_color_encoding c6_color_encoding =
+ st->sdout_cgms_625.color_encoding;
+ enum s5p_sd_625_aspect_ratio c6_display_ratio =
+ st->sdout_cgms_625.display_ratio;
+
+ __s5p_sdout_sw_reset(true);
+
+ sderr = __s5p_sdout_init_display_mode(disp_mode, out_mode, order);
+
+ if (sderr != SDOUT_NO_ERROR)
+ return false;
+
+
+ sderr = __s5p_sdout_init_video_scale_cfg(cpn_lev, cpn_rat,
+ cps_lev, cps_rat);
+
+ if (sderr != SDOUT_NO_ERROR)
+ return false;
+
+
+ sderr = __s5p_sdout_init_sync_signal_pin(sync_pin);
+
+ if (sderr != SDOUT_NO_ERROR)
+ return false;
+
+
+ sderr = __s5p_sdout_init_vbi(wss_cvbs, cap_cvbs, wss_y_svideo,
+ cap_y_svideo, cgmsa_rgb, wss_rgb, cap_rgb, cgmsa_y,
+ wss_y, cap_y_pb_pr);
+
+ if (sderr != SDOUT_NO_ERROR)
+ return false;
+
+
+ for (i = SDOUT_CHANNEL_0; i <= SDOUT_CHANNEL_2; i++) {
+
+ u32 offset = st->sdout_offset_gain[i].offset;
+ u32 gain = st->sdout_offset_gain[i].gain;
+
+ sderr = __s5p_sdout_init_offset_gain(i, offset, gain);
+
+ if (sderr != SDOUT_NO_ERROR)
+ return false;
+ }
+
+
+ __s5p_sdout_init_delay(delay, off_v_start, off_v_end);
+
+ __s5p_sdout_init_schlock(phase_adj);
+
+ __s5p_sdout_init_color_compensaton_onoff(br_hue_sat_adj, ypbpr_comp,
+ rgb_compen, y_compen, cvbs_compen);
+
+ __s5p_sdout_init_brightness_hue_saturation(g_bright, off_bright,
+ g0_cb_h_sat, g1_cb_h_sat, g0_cr_h_sat,
+ g1_cr_h_sat, off_cb_h_sat,
+ off_cr_h_sat);
+
+ __s5p_sdout_init_rgb_color_compensation(max_rgb_cube, min_rgb_cube);
+
+ __s5p_sdout_init_cvbs_color_compensation(y_l_m_c, y_b_c, y_t_c,
+ y_u_m_c, rad_c);
+
+ __s5p_sdout_init_svideo_color_compensation(y_t_s, y_b_s, y_cylinder_s);
+
+ __s5p_sdout_init_component_porch(back_525, front_525, back_625,
+ front_625);
+
+ sderr = __s5p_sdout_init_vesa_rgb_sync(sync_type, vsync_active,
+ hsync_active);
+
+ if (sderr != SDOUT_NO_ERROR)
+ return false;
+
+
+ for (i = SDOUT_CHANNEL_0; i <= SDOUT_CHANNEL_2; i++) {
+ enum s5p_sd_channel_sel channel = st->sdout_xtalk_cc[i].channel;
+ u32 coeff1 = st->sdout_xtalk_cc[i].coeff1;
+ u32 coeff2 = st->sdout_xtalk_cc[i].coeff2;
+
+ sderr = __s5p_sdout_init_ch_xtalk_cancel_coef(channel,
+ coeff2, coeff1);
+
+ if (sderr != SDOUT_NO_ERROR)
+ return false;
+ }
+
+ __s5p_sdout_init_closed_caption(display_cc, nondisplay_cc);
+
+ sderr = __s5p_sdout_init_wss525_data(w5_copy_permit, w5_mv_psp,
+ w5_copy_info, w5_analog_on, w5_display_ratio);
+
+ if (sderr != SDOUT_NO_ERROR)
+ return false;
+
+
+ sderr = __s5p_sdout_init_wss625_data(w6_surroun_f_sound, w6_copyright,
+ w6_copy_protection, w6_text_subtitles,
+ w6_open_subtitles, w6_camera_film,
+ w6_color_encoding, w6_helper_signal,
+ w6_display_ratio);
+
+ if (sderr != SDOUT_NO_ERROR)
+ return false;
+
+
+ sderr = __s5p_sdout_init_cgmsa525_data(c5_copy_permit, c5_mv_psp,
+ c5_copy_info, c5_analog_on,
+ c5_display_ratio);
+
+ if (sderr != SDOUT_NO_ERROR)
+ return false;
+
+
+ sderr = __s5p_sdout_init_cgmsa625_data(c6_surroun_f_sound, c6_copyright,
+ c6_copy_protection, c6_text_subtitles,
+ c6_open_subtitles, c6_camera_film,
+ c6_color_encoding, c6_helper_signal,
+ c6_display_ratio);
+
+ if (sderr != SDOUT_NO_ERROR)
+ return false;
+
+
+ /* Disable All Interrupt */
+ __s5p_sdout_set_interrupt_enable(false);
+
+ /* Clear All Interrupt Pending */
+ __s5p_sdout_clear_interrupt_pending();
+
+ __s5p_sdout_start();
+
+ __s5p_tv_powerset_dac_onoff(true);
+
+ for (i = SDOUT_CHANNEL_0; i <= SDOUT_CHANNEL_2; i++) {
+
+ bool dac = st->sdout_dac_on[i];
+
+ sderr = __s5p_sdout_init_dac_power_onoff(i, dac);
+
+ if (sderr != SDOUT_NO_ERROR)
+ return false;
+ }
+
+ return true;
+}
+
+unsigned char _s5p_tv_if_video_avi_checksum(void)
+{
+ u8 i;
+ u32 sum = 0;
+ struct s5p_tv_status *st = &s5ptv_status;
+
+ for (i = 0; i < 13; i++)
+ sum += (u32)(st->avi_byte[i]);
+
+
+ return (u8)(0x100 - ((0x91 + sum) & 0xff));
+}
+
+bool _s5p_tv_if_init_avi_frame(struct tvout_output_if *tvout_if)
+{
+ struct s5p_tv_status *st = &s5ptv_status;
+ TVOUTIFPRINTK("(%d, %d)\n\r", tvout_if->disp_mode,
+ tvout_if->out_mode);
+
+ st->hdmi_av_info_frame.trans_type = HDMI_TRANS_EVERY_SYNC;
+ st->avi_byte[1] = AVI_ITU709;
+ st->avi_byte[4] = AVI_NO_PIXEL_REPEAT;
+
+ switch (tvout_if->disp_mode) {
+
+#ifdef CONFIG_CPU_S5PV210
+ case TVOUT_480P_59:
+#endif
+ case TVOUT_480P_60_16_9:
+ st->avi_byte[1] = AVI_PAR_16_9 | AVI_ITU601;
+ st->avi_byte[3] = AVI_VIC_3;
+ break;
+
+ case TVOUT_480P_60_4_3:
+ st->avi_byte[1] = AVI_PAR_4_3 | AVI_ITU601;
+ st->avi_byte[3] = AVI_VIC_2;
+ break;
+
+ case TVOUT_576P_50_16_9:
+ st->avi_byte[1] = AVI_PAR_16_9 | AVI_ITU601;
+ st->avi_byte[3] = AVI_VIC_18;
+ break;
+
+ case TVOUT_576P_50_4_3:
+ st->avi_byte[1] = AVI_PAR_4_3 | AVI_ITU601;
+ st->avi_byte[3] = AVI_VIC_17;
+ break;
+
+ case TVOUT_720P_50:
+ st->avi_byte[1] = AVI_PAR_16_9 | AVI_ITU709;
+ st->avi_byte[3] = AVI_VIC_19;
+ break;
+
+ case TVOUT_720P_60:
+#ifdef CONFIG_CPU_S5PV210
+ case TVOUT_720P_59:
+ st->avi_byte[1] = AVI_PAR_16_9 | AVI_ITU709;
+ st->avi_byte[3] = AVI_VIC_4;
+ break;
+
+ case TVOUT_1080I_50:
+ st->avi_byte[1] = AVI_PAR_16_9 | AVI_ITU709;
+ st->avi_byte[3] = AVI_VIC_20;
+ break;
+
+ case TVOUT_1080I_59:
+ case TVOUT_1080I_60:
+ st->avi_byte[1] = AVI_PAR_16_9 | AVI_ITU709;
+ st->avi_byte[3] = AVI_VIC_5;
+ break;
+
+ case TVOUT_1080P_50:
+ st->avi_byte[1] = AVI_PAR_16_9 | AVI_ITU709;
+ st->avi_byte[3] = AVI_VIC_31;
+ break;
+
+ case TVOUT_1080P_30:
+ st->avi_byte[1] = AVI_PAR_16_9 | AVI_ITU709;
+ st->avi_byte[3] = AVI_VIC_34;
+
+ case TVOUT_1080P_59:
+ case TVOUT_1080P_60:
+ st->avi_byte[1] = AVI_PAR_16_9 | AVI_ITU709;
+ st->avi_byte[3] = AVI_VIC_16;
+ break;
+#endif
+ default:
+ TVOUTIFPRINTK("invalid disp_mode parameter(%d)\n\r",
+ tvout_if->out_mode);
+ return false;
+ break;
+ }
+
+ switch (tvout_if->out_mode) {
+
+ case TVOUT_OUTPUT_DVI:
+ st->hdmi_av_info_frame.trans_type = HDMI_DO_NOT_TANS;
+ st->avi_byte[0] = AVI_RGB_IF;
+ break;
+
+ case TVOUT_OUTPUT_HDMI_RGB:
+ st->hdmi_av_info_frame.trans_type = HDMI_TRANS_EVERY_SYNC;
+ st->avi_byte[0] = AVI_RGB_IF;
+ break;
+
+ case TVOUT_OUTPUT_HDMI:
+ st->hdmi_av_info_frame.trans_type = HDMI_TRANS_EVERY_SYNC;
+ st->avi_byte[0] = AVI_YCBCR444_IF;
+ break;
+
+ default:
+ TVOUTIFPRINTK("invalid out_mode parameter(%d)\n\r",
+ tvout_if->out_mode);
+ return false;
+ break;
+ }
+
+ st->avi_byte[1] |= AVI_SAME_WITH_PICTURE_AR;
+
+ TVOUTIFPRINTK("()\n\r");
+ return true;
+}
+
+bool _s5p_tv_if_init_hd_video_reg(void)
+{
+ enum s5p_tv_hdmi_err herr = 0;
+ enum s5p_tv_hdmi_csc_type cscType;
+ struct s5p_tv_status *st = &s5ptv_status;
+
+ u8 cb_b = st->hdmi_video_blue_screen.cb_b;
+ u8 y_g = st->hdmi_video_blue_screen.y_g;
+ u8 cr_r = st->hdmi_video_blue_screen.cr_r;
+
+ u8 y_min = st->hdmi_color_range.y_min;
+ u8 y_max = st->hdmi_color_range.y_max;
+ u8 c_min = st->hdmi_color_range.c_min;
+ u8 c_max = st->hdmi_color_range.c_max;
+
+ enum s5p_tv_disp_mode disp_mode = st->tvout_param.disp_mode;
+ enum s5p_tv_o_mode out_mode = st->tvout_param.out_mode;
+
+ enum s5p_hdmi_transmit *a_trans_type =
+ &st->hdmi_av_info_frame.trans_type;
+ u8 *a_check_sum = &st->hdmi_av_info_frame.check_sum;
+ u8 *a_data = st->hdmi_av_info_frame.data;
+
+ enum s5p_hdmi_transmit m_trans_type =
+ st->hdmi_mpg_info_frame.trans_type;
+ u8 m_check_sum = st->hdmi_mpg_info_frame.check_sum;
+ u8 *m_data = st->hdmi_mpg_info_frame.data;
+
+ enum s5p_hdmi_transmit s_trans_type =
+ st->hdmi_spd_info_frame.trans_type;
+ u8 *spd_header = st->hdmi_spd_info_frame.spd_header;
+ u8 *spd_data = st->hdmi_spd_info_frame.spd_data;
+
+ if (!_s5p_tv_if_init_avi_frame(&st->tvout_param)) {
+ st->tvout_param_available = false;
+ return false;
+ }
+
+ herr = __s5p_hdmi_video_init_display_mode(disp_mode, out_mode, a_data);
+
+ if (herr != HDMI_NO_ERROR)
+ return false;
+
+ st->hdmi_av_info_frame.check_sum = _s5p_tv_if_video_avi_checksum();
+
+ if (!st->hdcp_en)
+ __s5p_hdmi_video_init_bluescreen(
+ st->hdmi_video_blue_screen.enable,
+ cb_b, y_g, cr_r);
+
+ __s5p_hdmi_video_init_color_range(y_min, y_max, c_min, c_max);
+
+ switch (out_mode) {
+
+ case TVOUT_OUTPUT_HDMI_RGB:
+ case TVOUT_OUTPUT_HDMI:
+ cscType = HDMI_BYPASS;
+ break;
+
+ case TVOUT_OUTPUT_DVI:
+ cscType = HDMI_CSC_YUV601_TO_RGB_LR;
+ s_trans_type = HDMI_DO_NOT_TANS;
+ break;
+
+ default:
+ TVOUTIFPRINTK("invalid out_mode parameter(%d)\n\r",
+ out_mode);
+ return false;
+ break;
+ }
+
+ herr = __s5p_hdmi_video_init_csc(cscType);
+
+ if (herr != HDMI_NO_ERROR)
+ return false;
+
+
+ herr = __s5p_hdmi_video_init_avi_infoframe(*a_trans_type,
+ *a_check_sum, a_data);
+
+ if (herr != HDMI_NO_ERROR)
+ return false;
+
+
+ herr = __s5p_hdmi_video_init_mpg_infoframe(m_trans_type,
+ m_check_sum, m_data);
+
+ if (herr != HDMI_NO_ERROR)
+ return false;
+
+
+ herr = __s5p_hdmi_init_spd_infoframe(s_trans_type,
+ spd_header, spd_data);
+
+ if (herr != HDMI_NO_ERROR)
+ return false;
+
+ return true;
+}
+
+bool _s5p_tv_if_init_hd_reg(void)
+{
+ struct s5p_tv_status *st = &s5ptv_status;
+ bool timing_correction_en = st->hdmi_tg_cmd.timing_correction_en;
+ bool bt656_sync_en = st->hdmi_tg_cmd.bt656_sync_en;
+ bool tg_en;
+
+ TVOUTIFPRINTK("audio type : %d, hdcp : %s)\n\r",
+ st->hdmi_audio_type, st->hdcp_en ? "enabled" : "disabled");
+
+/* C110_HDCP:
+ if (st->hdcp_en) {
+ if (!(st->hpd_status)) {
+ TVOUTIFPRINTK("HPD is not detected\n\r");
+ return false;
+ }
+ }
+*/
+
+ if (!_s5p_tv_if_init_hd_video_reg())
+ return false;
+
+ switch (st->hdmi_audio_type) {
+
+ case HDMI_AUDIO_PCM:
+ /*
+ * PCM, Samplingrate 44100, 16bit,
+ * ignore framesize cuz stream is PCM.
+ */
+ __s5p_hdmi_audio_init(PCM, 44100, 16, 0);
+ break;
+
+ case HDMI_AUDIO_NO:
+ break;
+
+ default:
+ TVOUTIFPRINTK("invalid hdmi_audio_type(%d)\n\r",
+ st->hdmi_audio_type);
+ return false;
+ break;
+ }
+
+ if (!__s5p_hdmi_start(st->hdmi_audio_type,
+ st->hdcp_en,
+ st->hdcp_i2c_client)) {
+ return false;
+ }
+
+ st->hdmi_tg_cmd.tg_en = true;
+ tg_en = st->hdmi_tg_cmd.tg_en;
+
+ __s5p_hdmi_video_init_tg_cmd(timing_correction_en,
+ bt656_sync_en, tg_en);
+
+ return true;
+}
+
+bool _s5p_tv_if_start(void)
+{
+ struct s5p_tv_status *st = &s5ptv_status;
+
+#ifdef CONFIG_CPU_S5PC100
+ enum s5p_tv_clk_err cerr = HDMI_NO_ERROR;
+#endif
+
+ enum s5p_tv_o_mode out_mode = st->tvout_param.out_mode;
+
+#if 0
+ __s5p_vm_set_underflow_interrupt_enable(VM_VIDEO_LAYER,
+ false);
+ __s5p_vm_set_underflow_interrupt_enable(VM_GPR0_LAYER,
+ false);
+ __s5p_vm_set_underflow_interrupt_enable(VM_GPR1_LAYER,
+ false);
+
+ _s5p_tv_if_stop();
+
+ if (st->vp_layer_enable) {
+ _s5p_vlayer_stop();
+ /* In order to start video layer on the s5p_tv_resume()
+ * or handle_calbe() function*/
+ st->vp_layer_enable = true;
+ }
+
+ /* Clear All Interrupt Pending*/
+ __s5p_vm_clear_pend_all();
+
+#endif
+ /*
+ * have not to call
+ * another request function simultaneously
+ */
+#ifdef CONFIG_CPU_S5PC100
+
+ enum s5p_tv_disp_mode disp_mode = st->tvout_param.disp_mode;
+
+ if (!__s5p_tv_power_get_power_status())
+ __s5p_tv_poweron();
+
+#endif
+#ifdef CONFIG_CPU_S5PV210
+ /* move to tv_phy_power()*/
+ /*__s5p_tv_poweron();*/
+#endif
+
+ switch (out_mode) {
+
+ case TVOUT_OUTPUT_COMPOSITE:
+
+ case TVOUT_OUTPUT_SVIDEO:
+
+ case TVOUT_OUTPUT_COMPONENT_YPBPR_INERLACED:
+
+ case TVOUT_OUTPUT_COMPONENT_YPBPR_PROGRESSIVE:
+
+ case TVOUT_OUTPUT_COMPONENT_RGB_PROGRESSIVE:
+
+#ifdef CONFIG_CPU_S5PC100
+ __s5p_tv_clk_init_video_mixer(TVOUT_CLK_VMIXER_SRCCLK_VCLK_54);
+
+ __s5p_tv_clk_init_hpll(0xffff, 96, 6, 3);
+#endif
+
+#ifdef CONFIG_CPU_S5PV210
+ clk_set_parent(st->sclk_mixer, st->sclk_dac);
+#endif
+ break;
+
+ case TVOUT_OUTPUT_HDMI:
+ case TVOUT_OUTPUT_HDMI_RGB:
+ case TVOUT_OUTPUT_DVI:
+
+#ifdef CONFIG_CPU_S5PC100
+ __s5p_tv_clk_init_video_mixer(
+ TVOUT_CLK_VMIXER_SRCCLK_MOUT_HPLL);
+
+ cerr = __s5p_tv_clk_init_mout_hpll(
+ S5P_TV_CLK_MOUT_HPLL_FOUT_HPLL);
+ if (cerr != S5P_TV_CLK_ERR_NO_ERROR)
+ return false;
+#endif
+
+#ifdef CONFIG_CPU_S5PV210
+ clk_set_parent(st->sclk_mixer, st->sclk_hdmi);
+ clk_set_parent(st->sclk_hdmi, st->sclk_hdmiphy);
+#endif
+
+#ifdef CONFIG_CPU_S5PC100
+
+ __s5p_tv_clk_init_hdmi_ratio(2);
+
+ switch (disp_mode) {
+
+ case TVOUT_480P_60_16_9:
+
+ case TVOUT_480P_60_4_3:
+
+ case TVOUT_576P_50_16_9:
+
+ case TVOUT_576P_50_4_3:
+ __s5p_tv_clk_init_hpll(0xffff, 96, 6, 3);
+ break;
+
+
+ case TVOUT_720P_50:
+
+ case TVOUT_720P_60:
+ __s5p_tv_clk_init_hpll(0xffff, 132, 6, 2);
+ break;
+
+ default:
+ _s5p_tv_if_stop();
+ TVOUTIFPRINTK("invalid out_mode parameter(%d)\n\r",
+ out_mode);
+ st->tvout_param_available = false;
+ return false;
+ break;
+ }
+#endif
+
+#ifdef CONFIG_CPU_S5PC100
+ __s5p_tv_poweroff();
+ __s5p_tv_poweron();
+#endif
+ break;
+
+ default:
+ _s5p_tv_if_stop();
+ TVOUTIFPRINTK("invalid out_mode parameter(%d)\n\r",
+ st->tvout_param.out_mode);
+ st->tvout_param_available = false;
+ return false;
+ break;
+ }
+
+ if (!_s5p_tv_if_init_vm_reg())
+ return false;
+
+
+ switch (out_mode) {
+
+ case TVOUT_OUTPUT_COMPOSITE:
+
+ case TVOUT_OUTPUT_SVIDEO:
+
+ case TVOUT_OUTPUT_COMPONENT_YPBPR_INERLACED:
+
+ case TVOUT_OUTPUT_COMPONENT_YPBPR_PROGRESSIVE:
+
+ case TVOUT_OUTPUT_COMPONENT_RGB_PROGRESSIVE:
+
+ if (!_s5p_tv_if_init_sd_reg())
+ return false;
+
+
+ break;
+
+ case TVOUT_OUTPUT_DVI:
+ st->hdmi_audio_type = HDMI_AUDIO_NO;
+
+ case TVOUT_OUTPUT_HDMI:
+ case TVOUT_OUTPUT_HDMI_RGB:
+ if (!_s5p_tv_if_init_hd_reg())
+ return false;
+
+
+ break;
+
+ default:
+ _s5p_tv_if_stop();
+ TVOUTIFPRINTK("invalid out_mode parameter(%d)\n\r",
+ out_mode);
+ return false;
+ break;
+ }
+
+ st->tvout_output_enable = true;
+#if 0
+ __s5p_vm_set_underflow_interrupt_enable(VM_VIDEO_LAYER,
+ true);
+ __s5p_vm_set_underflow_interrupt_enable(VM_GPR0_LAYER,
+ true);
+ __s5p_vm_set_underflow_interrupt_enable(VM_GPR1_LAYER,
+ true);
+
+ /* Clear All Interrupt Pending */
+ __s5p_vm_clear_pend_all();
+#endif
+ TVOUTIFPRINTK("()\n\r");
+
+ return true;
+}
+
+/*
+ * TV cut off sequence
+ * VP stop -> Mixer stop -> HDMI stop -> HDMI TG stop
+ * Above sequence should be satisfied.
+ */
+bool _s5p_tv_if_stop(void)
+{
+ struct s5p_tv_status *st = &s5ptv_status;
+
+ bool t_corr_en = st->hdmi_tg_cmd.timing_correction_en;
+ bool sync_en = st->hdmi_tg_cmd.bt656_sync_en;
+ enum s5p_tv_o_mode out_mode = st->tvout_param.out_mode;
+
+ TVOUTIFPRINTK("tvout sub sys. stopped!!\n");
+
+ __s5p_vm_stop();
+
+ switch (out_mode) {
+
+ case TVOUT_OUTPUT_COMPOSITE:
+
+ case TVOUT_OUTPUT_SVIDEO:
+
+ case TVOUT_OUTPUT_COMPONENT_YPBPR_INERLACED:
+
+ case TVOUT_OUTPUT_COMPONENT_YPBPR_PROGRESSIVE:
+
+ case TVOUT_OUTPUT_COMPONENT_RGB_PROGRESSIVE:
+ if (st->tvout_output_enable)
+ __s5p_sdout_stop();
+ break;
+
+ case TVOUT_OUTPUT_HDMI:
+ case TVOUT_OUTPUT_HDMI_RGB:
+ case TVOUT_OUTPUT_DVI:
+ if (st->tvout_output_enable) {
+ __s5p_hdmi_stop();
+ __s5p_hdmi_video_init_tg_cmd(t_corr_en, sync_en,
+ false);
+ }
+ break;
+
+ default:
+ TVOUTIFPRINTK("invalid out_mode parameter(%d)\n\r", out_mode);
+ return false;
+ break;
+ }
+
+
+#ifdef CONFIG_CPU_S5PC100
+ if (__s5p_tv_power_get_power_status()) {
+ __s5p_tv_clk_stop();
+ __s5p_tv_poweroff();
+ }
+#endif
+
+ st->tvout_output_enable = false;
+ st->tvout_param_available = false;
+
+ return true;
+}
+
+/*
+* before call this ftn. set the status data!!
+*/
+bool _s5p_tv_if_set_disp(void)
+{
+ struct s5p_tv_status *st = &s5ptv_status;
+
+ enum s5p_tv_disp_mode disp_mode = st->tvout_param.disp_mode;
+ enum s5p_tv_o_mode out_mode = st->tvout_param.out_mode;
+
+ TVOUTIFPRINTK("(%d, %d)\n\r", disp_mode, out_mode);
+
+ switch (disp_mode) {
+
+ case TVOUT_NTSC_M:
+
+ case TVOUT_NTSC_443:
+ st->sdout_video_scale_cfg.component_level =
+ S5P_TV_SD_LEVEL_0IRE;
+ st->sdout_video_scale_cfg.component_ratio =
+ SDOUT_VTOS_RATIO_7_3;
+ st->sdout_video_scale_cfg.composite_level =
+ S5P_TV_SD_LEVEL_75IRE;
+ st->sdout_video_scale_cfg.composite_ratio =
+ SDOUT_VTOS_RATIO_10_4;
+ break;
+
+ case TVOUT_PAL_BDGHI:
+
+ case TVOUT_PAL_M:
+
+ case TVOUT_PAL_N:
+
+ case TVOUT_PAL_NC:
+
+ case TVOUT_PAL_60:
+ st->sdout_video_scale_cfg.component_level =
+ S5P_TV_SD_LEVEL_0IRE;
+ st->sdout_video_scale_cfg.component_ratio =
+ SDOUT_VTOS_RATIO_7_3;
+ st->sdout_video_scale_cfg.composite_level =
+ S5P_TV_SD_LEVEL_0IRE;
+ st->sdout_video_scale_cfg.composite_ratio =
+ SDOUT_VTOS_RATIO_7_3;
+ break;
+
+ case TVOUT_480P_60_16_9:
+
+ case TVOUT_480P_60_4_3:
+
+ case TVOUT_576P_50_16_9:
+
+ case TVOUT_576P_50_4_3:
+
+ case TVOUT_720P_50:
+
+ case TVOUT_720P_60:
+
+#ifdef CONFIG_CPU_S5PV210
+
+ case TVOUT_1080I_50:
+
+ case TVOUT_1080I_60:
+
+ case TVOUT_1080P_50:
+
+ case TVOUT_1080P_60:
+
+ case TVOUT_1080P_30:
+
+ case TVOUT_480P_59:
+
+ case TVOUT_720P_59:
+
+ case TVOUT_1080I_59:
+
+ case TVOUT_1080P_59:
+#endif
+ break;
+ default:
+ TVOUTIFPRINTK("invalid disp_mode parameter(%d)\n\r",
+ disp_mode);
+ st->tvout_param_available = false;
+ return false;
+ break;
+ }
+
+ switch (out_mode) {
+
+ case TVOUT_OUTPUT_COMPOSITE:
+ st->sdout_order = S5P_TV_SD_O_ORDER_COMPOSITE_Y_C_CVBS;
+ st->sdout_dac_on[2] = false;
+ st->sdout_dac_on[1] = false;
+ st->sdout_dac_on[0] = true;
+ break;
+
+ case TVOUT_OUTPUT_SVIDEO:
+ st->sdout_order = S5P_TV_SD_O_ORDER_COMPOSITE_C_Y_CVBS;
+ st->sdout_dac_on[2] = true;
+ st->sdout_dac_on[1] = true;
+ st->sdout_dac_on[0] = false;
+ break;
+
+ case TVOUT_OUTPUT_COMPONENT_YPBPR_INERLACED:
+
+ case TVOUT_OUTPUT_COMPONENT_YPBPR_PROGRESSIVE:
+
+ case TVOUT_OUTPUT_COMPONENT_RGB_PROGRESSIVE:
+ st->sdout_order = S5P_TV_SD_O_ORDER_COMPONENT_RBG_PRPBY;
+ st->sdout_dac_on[2] = true;
+ st->sdout_dac_on[1] = true;
+ st->sdout_dac_on[0] = true;
+ break;
+
+ case TVOUT_OUTPUT_HDMI_RGB:
+ case TVOUT_OUTPUT_HDMI:
+ case TVOUT_OUTPUT_DVI:
+ st->hdmi_video_blue_screen.cb_b = 0;/* 128 */;
+ st->hdmi_video_blue_screen.y_g = 0;
+ st->hdmi_video_blue_screen.cr_r = 0;/* 128 */;
+ break;
+
+ default:
+ TVOUTIFPRINTK("invalid out_mode parameter(%d)\n\r",
+ out_mode);
+ st->tvout_param_available = false;
+ return false;
+ break;
+ }
+#if defined(CONFIG_CPU_S5PV210) && defined(CONFIG_PM)
+ if ((st->hpd_status) && st->suspend_status == false) {
+#endif
+ _s5p_tv_if_start();
+#if defined(CONFIG_CPU_S5PV210) && defined(CONFIG_PM)
+ }
+ /* If the cable is not inserted or system is on suspend mode
+ Just set variable, _s5p_tv_if_start() function will be called
+ in resume or handle_cable function according to this variable*/
+ else
+ st->tvout_output_enable = true;
+#endif
+ return true;
+}
+
diff --git a/drivers/media/video/samsung/tv20/s5p_stda_video_layer.c b/drivers/media/video/samsung/tv20/s5p_stda_video_layer.c
new file mode 100644
index 0000000..05a937d
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/s5p_stda_video_layer.c
@@ -0,0 +1,924 @@
+/* linux/drivers/media/video/samsung/tv20/s5p_stda_video_layer.c
+ *
+ * Video Layer ftn. file for Samsung TVOut driver
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/stddef.h>
+#include <linux/delay.h>
+#include <linux/ioctl.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+
+#include "s5p_tv.h"
+
+#ifdef COFIG_TVOUT_DBG
+#define S5P_VLAYER_DEBUG 1
+#endif
+
+#ifdef S5P_VLAYER_DEBUG
+#define VLAYERPRINTK(fmt, args...) \
+ printk(KERN_INFO "\t[VLAYER] %s: " fmt, __func__ , ## args)
+#else
+#define VLAYERPRINTK(fmt, args...)
+#endif
+
+#define INTERLACED 0
+#define PROGRESSIVE 1
+
+u8 check_input_mode(enum s5p_vp_src_color color)
+{
+ u8 ret = PROGRESSIVE;
+
+ /* check i_mode */
+ if (color == VPROC_SRC_COLOR_NV12IW ||
+ color == VPROC_SRC_COLOR_TILE_NV12IW)
+ ret = INTERLACED; /* interlaced */
+ else
+ ret = PROGRESSIVE; /* progressive */
+
+ return ret;
+}
+
+u8 check_output_mode(enum s5p_tv_disp_mode display,
+ enum s5p_tv_o_mode out)
+{
+ u8 ret = PROGRESSIVE;
+
+ switch (out) {
+ case TVOUT_OUTPUT_COMPOSITE:
+ case TVOUT_OUTPUT_SVIDEO:
+ case TVOUT_OUTPUT_COMPONENT_YPBPR_INERLACED:
+ ret = INTERLACED;
+ break;
+ case TVOUT_OUTPUT_COMPONENT_YPBPR_PROGRESSIVE:
+ case TVOUT_OUTPUT_COMPONENT_RGB_PROGRESSIVE:
+ case TVOUT_OUTPUT_HDMI_RGB:
+ case TVOUT_OUTPUT_HDMI:
+ case TVOUT_OUTPUT_DVI:
+#ifdef CONFIG_CPU_S5PV210
+ if (display == TVOUT_1080I_60 ||
+ display == TVOUT_1080I_59 ||
+ display == TVOUT_1080I_50)
+
+ ret = INTERLACED;
+ else
+#endif
+ ret = PROGRESSIVE;
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+
+}
+
+
+static bool _s5p_vlayer_wait_previous_update(void)
+{
+ __s5p_vp_get_update_status();
+ return false;
+}
+
+
+static void _s5p_vlayer_calc_inner_values(void)
+{
+ struct s5p_tv_status *st = &s5ptv_status;
+ struct s5p_vl_param *video = &(s5ptv_status.vl_basic_param);
+ u8 o_mode, i_mode;
+
+ u32 t_y_addr = video->top_y_address;
+ u32 t_c_addr = video->top_c_address;
+ u32 img_w = video->img_width;
+ u32 s_ox = video->src_offset_x;
+ u32 s_oy = video->src_offset_y;
+ u32 d_ox = video->dest_offset_x;
+ u32 d_oy = video->dest_offset_y;
+ u32 s_w = video->src_width;
+ u32 s_h = video->src_height;
+ u32 d_w = video->dest_width;
+ u32 d_h = video->dest_height;
+
+ i_mode = check_input_mode(st->src_color);
+ o_mode = check_output_mode(st->tvout_param.disp_mode,
+ st->tvout_param.out_mode);
+
+ st->vl_top_y_address = t_y_addr;
+ st->vl_top_c_address = t_c_addr;
+
+ if (st->src_color == VPROC_SRC_COLOR_NV12IW) {
+ st->vl_bottom_y_address = t_y_addr + img_w;
+ st->vl_bottom_c_address = t_c_addr + img_w;
+ } else if (st->src_color == VPROC_SRC_COLOR_TILE_NV12IW) {
+ st->vl_bottom_y_address = t_y_addr + 0x40;
+ st->vl_bottom_c_address = t_c_addr + 0x40;
+ }
+
+ st->vl_src_offset_x = s_ox;
+ st->vl_src_offset_y = s_oy;
+ st->vl_src_width = s_w;
+ st->vl_src_height = s_h;
+ st->vl_dest_offset_x = d_ox;
+ st->vl_dest_offset_y = d_oy;
+ st->vl_dest_width = d_w;
+ st->vl_dest_height = d_h;
+
+
+ if (o_mode == INTERLACED) {
+ st->vl_src_height = s_h / 2;
+ st->vl_src_offset_y = s_oy / 2;
+ st->vl_dest_height = d_h / 2;
+ st->vl_dest_offset_y = d_oy / 2;
+ } else {
+ if (i_mode == INTERLACED) {
+ st->vl_src_height = s_h / 2;
+ st->vl_src_offset_y = s_oy / 2;
+ }
+ }
+}
+
+bool _s5p_vlayer_start(void)
+{
+ int i;
+
+ enum s5p_tv_vp_err verr;
+ enum s5p_tv_vmx_err merr;
+ struct s5p_video_img_address temp_addr;
+ struct s5p_img_size img_size;
+
+ struct s5p_vl_param param = s5ptv_status.vl_basic_param;
+
+ u8 contrast = s5ptv_status.vl_contrast;
+
+ u32 ty_addr = s5ptv_status.vl_top_y_address;
+ u32 tc_addr = s5ptv_status.vl_top_c_address;
+ u32 by_addr = s5ptv_status.vl_bottom_y_address;
+ u32 bc_addr = s5ptv_status.vl_bottom_c_address;
+ u32 endian = param.src_img_endian;
+ u32 i_w = param.img_width;
+ u32 i_h = param.img_height;
+ u32 s_ox = s5ptv_status.vl_src_offset_x;
+ u32 s_xf = s5ptv_status.vl_src_x_fact_step;
+ u32 s_oy = s5ptv_status.vl_src_offset_y;
+ u32 s_w = s5ptv_status.vl_src_width;
+ u32 s_h = s5ptv_status.vl_src_height;
+ u32 d_ox = s5ptv_status.vl_dest_offset_x;
+ u32 d_oy = s5ptv_status.vl_dest_offset_y;
+ u32 d_w = s5ptv_status.vl_dest_width;
+ u32 d_h = s5ptv_status.vl_dest_height;
+ u32 noise = s5ptv_status.vl_sharpness.th_noise;
+ u32 saturation = s5ptv_status.vl_saturation;
+ u32 alpha = param.alpha;
+ u32 priority = param.priority;
+ u32 br_offset = s5ptv_status.vl_bright_offset;
+
+ bool ipc = s5ptv_status.vl2d_ipc;
+ bool l_skip = s5ptv_status.vl_op_mode.line_skip;
+ bool bypass = s5ptv_status.vl_bypass_post_process;
+ bool po_def = s5ptv_status.vl_poly_filter_default;
+ bool bright = s5ptv_status.us_vl_brightness;
+ bool w_blend = param.win_blending;
+ bool csc_en = s5ptv_status.vl_csc_control.csc_en;
+ bool s_off_en = s5ptv_status.vl_csc_control.sub_y_offset_en;
+ bool csc_coef_def = s5ptv_status.vl_csc_coef_default;
+
+ enum s5p_vp_field f_id = s5ptv_status.field_id;
+ enum s5p_vp_mem_mode m_mode = s5ptv_status.vl_op_mode.mem_mode;
+ enum s5p_vp_chroma_expansion cro_ex =
+ s5ptv_status.vl_op_mode.chroma_exp;
+ enum s5p_vp_filed_id_toggle f_id_tog =
+ s5ptv_status.vl_op_mode.toggle_id;
+ enum s5p_vp_pxl_rate p_rate = s5ptv_status.vl_rate;
+ enum s5p_vp_sharpness_control sharp =
+ s5ptv_status.vl_sharpness.sharpness;
+ enum s5p_vp_csc_type csc_type = s5ptv_status.vl_csc_type;
+
+#ifdef CONFIG_CPU_S5PC100
+ __s5p_tv_clk_set_vp_clk_onoff(true);
+#endif
+ __s5p_vp_sw_reset();
+ __s5p_vp_init_field_id(f_id);
+ __s5p_vp_init_op_mode(l_skip, m_mode, cro_ex, f_id_tog);
+ __s5p_vp_init_pixel_rate_control(p_rate);
+
+ temp_addr.y_address = param.top_y_address;
+ temp_addr.c_address = param.top_c_address;
+ img_size.img_width = param.img_width;
+ img_size.img_height = param.img_height;
+
+ _s5p_vlayer_set_top_address((unsigned long)&temp_addr);
+ _s5p_vlayer_set_img_size((unsigned long)&img_size);
+
+ img_size.img_width = param.src_width;
+ img_size.img_height = param.src_height;
+ _s5p_vlayer_set_src_size((unsigned long)&img_size);
+
+ if (po_def)
+ verr = __s5p_vp_init_layer_def_poly_filter_coef(ty_addr,
+ tc_addr, by_addr, bc_addr, endian, i_w, i_h, s_ox,
+ s_xf, s_oy, s_w, s_h, d_ox, d_oy, d_w, d_h, ipc);
+ else
+ verr = __s5p_vp_init_layer(ty_addr, tc_addr, by_addr, bc_addr,
+ endian, i_w, i_h, s_ox, s_xf, s_oy, s_w, s_h, d_ox,
+ d_oy, d_w, d_h, ipc);
+
+ if (verr != VPROC_NO_ERROR)
+ return false;
+
+ __s5p_vp_init_bypass_post_process(bypass);
+ __s5p_vp_init_sharpness(noise, sharp);
+ __s5p_vp_init_saturation(saturation);
+ __s5p_vp_init_brightness(bright);
+ __s5p_vp_init_contrast(contrast);
+
+ for (i = VProc_LINE_EQ_0; i <= VProc_LINE_EQ_7; i++) {
+ if (s5ptv_status.vl_bc_control[i].eq_num == i)
+ verr = __s5p_vp_init_brightness_contrast_control(
+ s5ptv_status.vl_bc_control[i].eq_num,
+ s5ptv_status.vl_bc_control[i].intc,
+ s5ptv_status.vl_bc_control[i].slope);
+
+ if (verr != VPROC_NO_ERROR)
+ return false;
+ }
+
+ __s5p_vp_init_brightness_offset(br_offset);
+
+ __s5p_vp_init_csc_control(s_off_en, csc_en);
+
+ if (csc_en && csc_coef_def) {
+ verr = __s5p_vp_init_csc_coef_default(csc_type);
+
+ if (verr != VPROC_NO_ERROR)
+ return false;
+ }
+
+ verr = __s5p_vp_start();
+
+ if (verr != VPROC_NO_ERROR)
+ return false;
+
+#ifdef CONFIG_CPU_S5PC100
+ merr = __s5p_vm_init_layer(VM_VIDEO_LAYER, true, w_blend, alpha,
+ priority, VM_DIRECT_RGB565, false,
+ false, false, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+#endif
+
+#ifdef CONFIG_CPU_S5PV210
+ merr = __s5p_vm_init_layer(s5ptv_status.tvout_param.disp_mode,
+ VM_VIDEO_LAYER, true, w_blend, alpha, priority,
+ VM_DIRECT_RGB565, false, false, false,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+#endif
+
+ if (merr != VPROC_NO_ERROR)
+ return false;
+
+ __s5p_vm_start();
+
+ s5ptv_status.vp_layer_enable = true;
+
+ return true;
+}
+
+bool _s5p_vlayer_stop(void)
+{
+ enum s5p_tv_vp_err verr;
+
+ __s5p_vm_set_layer_show(VM_VIDEO_LAYER, false);
+
+ if (_s5p_vlayer_wait_previous_update())
+ return false;
+
+ verr = __s5p_vp_stop();
+
+ if (verr != VPROC_NO_ERROR)
+ return false;
+
+#ifdef CONFIG_CPU_S5PC100
+ __s5p_tv_clk_set_vp_clk_onoff(false);
+#endif
+
+ s5ptv_status.vp_layer_enable = false;
+
+ return true;
+}
+
+
+bool _s5p_vlayer_set_priority(unsigned long buf_in)
+{
+ enum s5p_tv_vmx_err merr;
+ u32 pri;
+
+ s5ptv_status.vl_basic_param.priority = (unsigned int)(buf_in);
+
+ pri = s5ptv_status.vl_basic_param.priority;
+
+ merr = __s5p_vm_set_layer_priority(VM_VIDEO_LAYER, pri);
+
+ if (merr != VMIXER_NO_ERROR)
+ return false;
+
+ return true;
+}
+
+bool _s5p_vlayer_set_blending(unsigned long buf_in)
+{
+ enum s5p_tv_vmx_err merr;
+ bool blend;
+
+ s5ptv_status.vl_basic_param.win_blending = (bool)(buf_in);
+ blend = s5ptv_status.vl_basic_param.win_blending;
+
+ merr = __s5p_vm_set_win_blend(VM_VIDEO_LAYER, blend);
+
+ if (merr != VMIXER_NO_ERROR)
+ return false;
+
+ return true;
+}
+
+bool _s5p_vlayer_set_alpha(unsigned long buf_in)
+{
+ enum s5p_tv_vmx_err merr;
+ u32 alpha;
+
+ s5ptv_status.vl_basic_param.alpha = (unsigned int)(buf_in);
+ alpha = s5ptv_status.vl_basic_param.alpha;
+
+ merr = __s5p_vm_set_layer_alpha(VM_VIDEO_LAYER, alpha);
+
+ if (merr != VMIXER_NO_ERROR)
+ return false;
+
+
+ return true;
+}
+
+bool _s5p_vlayer_set_field_id(unsigned long buf_in)
+{
+ enum s5p_tv_vp_err verr;
+
+ s5ptv_status.field_id = (enum s5p_vp_field)(buf_in);
+
+ if (_s5p_vlayer_wait_previous_update())
+ return false;
+
+
+ __s5p_vp_set_field_id(s5ptv_status.field_id);
+
+ verr = __s5p_vp_update();
+
+ if (verr != VPROC_NO_ERROR)
+ return false;
+
+ return true;
+}
+
+bool _s5p_vlayer_set_top_address(unsigned long buf_in)
+{
+ u32 t_y_addr = 0;
+ u32 t_c_addr = 0;
+ u32 b_y_addr = 0;
+ u32 b_c_addr = 0;
+
+ struct s5p_video_img_address *addr =
+ (struct s5p_video_img_address *)buf_in;
+ enum s5p_tv_vp_err verr;
+
+ s5ptv_status.vl_basic_param.top_y_address = addr->y_address;
+ s5ptv_status.vl_basic_param.top_c_address = addr->c_address;
+
+ _s5p_vlayer_calc_inner_values();
+
+ t_y_addr = s5ptv_status.vl_top_y_address;
+ t_c_addr = s5ptv_status.vl_top_c_address;
+ b_y_addr = s5ptv_status.vl_bottom_y_address;
+ b_c_addr = s5ptv_status.vl_bottom_c_address;
+
+ if (_s5p_vlayer_wait_previous_update())
+ return false;
+
+
+ verr = __s5p_vp_set_top_field_address(t_y_addr, t_c_addr);
+
+ if (verr != VPROC_NO_ERROR)
+ return false;
+
+
+ if (check_input_mode(s5ptv_status.src_color) == INTERLACED) {
+ __s5p_vp_set_field_id(s5ptv_status.field_id);
+ verr = __s5p_vp_set_bottom_field_address(b_y_addr, b_c_addr);
+
+ if (verr != VPROC_NO_ERROR)
+ return false;
+ }
+
+ verr = __s5p_vp_update();
+
+ if (verr != VPROC_NO_ERROR)
+ return false;
+
+ return true;
+}
+
+bool _s5p_vlayer_set_bottom_address(unsigned long buf_in)
+{
+ u32 t_y_addr = 0;
+ u32 t_c_addr = 0;
+ u32 b_y_addr = 0;
+ u32 b_c_addr = 0;
+
+ u32 img_width = s5ptv_status.vl_basic_param.img_width;
+
+ struct s5p_video_img_address *addr =
+ (struct s5p_video_img_address *)buf_in;
+ enum s5p_tv_vp_err verr;
+ enum s5p_vp_src_color s_color = s5ptv_status.src_color;
+
+ if (s_color == VPROC_SRC_COLOR_NV12IW) {
+ s5ptv_status.vl_basic_param.top_y_address =
+ addr->y_address - img_width;
+ s5ptv_status.vl_basic_param.top_c_address =
+ addr->c_address - img_width;
+ }
+
+ _s5p_vlayer_calc_inner_values();
+
+ t_y_addr = s5ptv_status.vl_top_y_address;
+ t_c_addr = s5ptv_status.vl_top_c_address;
+ b_y_addr = s5ptv_status.vl_bottom_y_address;
+ b_c_addr = s5ptv_status.vl_bottom_c_address;
+
+ if (_s5p_vlayer_wait_previous_update())
+ return false;
+
+ verr = __s5p_vp_set_bottom_field_address(b_y_addr, b_c_addr);
+
+ if (verr != VPROC_NO_ERROR)
+ return false;
+
+
+ if (s5ptv_status.src_color == VPROC_SRC_COLOR_NV12IW) {
+ verr = __s5p_vp_set_top_field_address(t_y_addr, t_c_addr);
+
+ if (verr != VPROC_NO_ERROR)
+ return false;
+
+ }
+
+ verr = __s5p_vp_update();
+
+ if (verr != VPROC_NO_ERROR)
+ return false;
+
+
+ return true;
+}
+
+bool _s5p_vlayer_set_img_size(unsigned long buf_in)
+{
+ struct s5p_img_size *size = (struct s5p_img_size *)buf_in;
+ enum s5p_tv_vp_err verr;
+
+ s5ptv_status.vl_basic_param.img_width = size->img_width;
+ s5ptv_status.vl_basic_param.img_height = size->img_height;
+
+ if (_s5p_vlayer_wait_previous_update())
+ return false;
+
+
+ verr = __s5p_vp_set_img_size(size->img_width, size->img_height);
+
+ if (verr != VPROC_NO_ERROR)
+ return false;
+
+
+ verr = __s5p_vp_update();
+
+ if (verr != VPROC_NO_ERROR)
+ return false;
+
+
+ VLAYERPRINTK("()\n\r");
+
+ return true;
+}
+
+bool _s5p_vlayer_set_src_position(unsigned long buf_in)
+{
+ struct s5p_img_offset *offset = (struct s5p_img_offset *)buf_in;
+ enum s5p_tv_vp_err verr;
+
+ s5ptv_status.vl_basic_param.src_offset_x = offset->offset_x;
+ s5ptv_status.vl_basic_param.src_offset_y = offset->offset_y;
+ _s5p_vlayer_calc_inner_values();
+
+ if (_s5p_vlayer_wait_previous_update())
+ return false;
+
+
+ __s5p_vp_set_src_position(s5ptv_status.vl_src_offset_x,
+ s5ptv_status.vl_src_x_fact_step,
+ s5ptv_status.vl_src_offset_y);
+
+ verr = __s5p_vp_update();
+
+ if (verr != VPROC_NO_ERROR)
+ return false;
+
+
+ return true;
+}
+
+bool _s5p_vlayer_set_dest_position(unsigned long buf_in)
+{
+ u32 d_ox = 0;
+ u32 d_oy = 0;
+ struct s5p_img_offset *offset = (struct s5p_img_offset *)buf_in;
+ enum s5p_tv_vp_err verr;
+
+ s5ptv_status.vl_basic_param.dest_offset_x = offset->offset_x;
+ s5ptv_status.vl_basic_param.dest_offset_y = offset->offset_y;
+ _s5p_vlayer_calc_inner_values();
+
+ d_ox = s5ptv_status.vl_dest_offset_x;
+ d_oy = s5ptv_status.vl_dest_offset_y;
+
+ if (_s5p_vlayer_wait_previous_update())
+ return false;
+
+ __s5p_vp_set_dest_position(d_ox, d_oy);
+
+ verr = __s5p_vp_update();
+
+ if (verr != VPROC_NO_ERROR)
+ return false;
+
+ return true;
+}
+
+bool _s5p_vlayer_set_src_size(unsigned long buf_in)
+{
+ u32 s_w = 0;
+ u32 s_h = 0;
+ u32 d_w = 0;
+ u32 d_h = 0;
+ bool ipc = false;
+
+ struct s5p_img_size *size = (struct s5p_img_size *)buf_in;
+ enum s5p_tv_vp_err verr;
+
+ s5ptv_status.vl_basic_param.src_width = size->img_width;
+ s5ptv_status.vl_basic_param.src_height = size->img_height;
+ _s5p_vlayer_calc_inner_values();
+
+ s_w = s5ptv_status.vl_src_width;
+ s_h = s5ptv_status.vl_src_height;
+ d_w = s5ptv_status.vl_dest_width;
+ d_h = s5ptv_status.vl_dest_height;
+ ipc = s5ptv_status.vl2d_ipc;
+
+ if (_s5p_vlayer_wait_previous_update())
+ return false;
+
+ __s5p_vp_set_src_dest_size(s_w, s_h, d_w, d_h, ipc);
+
+ verr = __s5p_vp_update();
+
+ if (verr != VPROC_NO_ERROR)
+ return false;
+
+ return true;
+}
+
+bool _s5p_vlayer_set_dest_size(unsigned long buf_in)
+{
+ u32 s_w = 0;
+ u32 s_h = 0;
+ u32 d_w = 0;
+ u32 d_h = 0;
+ bool ipc = false;
+
+ struct s5p_img_size *size = (struct s5p_img_size *)buf_in;
+ enum s5p_tv_vp_err verr;
+
+ s5ptv_status.vl_basic_param.dest_width = size->img_width;
+ s5ptv_status.vl_basic_param.dest_height = size->img_height;
+ _s5p_vlayer_calc_inner_values();
+
+ s_w = s5ptv_status.vl_src_width;
+ s_h = s5ptv_status.vl_src_height;
+ d_w = s5ptv_status.vl_dest_width;
+ d_h = s5ptv_status.vl_dest_height;
+ ipc = s5ptv_status.vl2d_ipc;
+
+ if (_s5p_vlayer_wait_previous_update())
+ return false;
+
+ __s5p_vp_set_src_dest_size(s_w, s_h, d_w, d_h, ipc);
+
+ verr = __s5p_vp_update();
+
+ if (verr != VPROC_NO_ERROR)
+ return false;
+
+ return true;
+}
+
+bool _s5p_vlayer_set_brightness(unsigned long buf_in)
+{
+ enum s5p_tv_vp_err verr;
+
+ s5ptv_status.us_vl_brightness = (unsigned short)buf_in;
+
+ if (_s5p_vlayer_wait_previous_update())
+ return false;
+
+
+ __s5p_vp_set_brightness(s5ptv_status.us_vl_brightness);
+
+
+ verr = __s5p_vp_update();
+
+ if (verr != VPROC_NO_ERROR)
+ return false;
+
+
+ return true;
+}
+
+bool _s5p_vlayer_set_contrast(unsigned long buf_in)
+{
+ enum s5p_tv_vp_err verr;
+
+ s5ptv_status.vl_contrast = (unsigned char)buf_in;
+
+ if (_s5p_vlayer_wait_previous_update())
+ return false;
+
+
+ __s5p_vp_set_contrast(s5ptv_status.vl_contrast);
+
+ verr = __s5p_vp_update();
+
+ if (verr != VPROC_NO_ERROR)
+ return false;
+
+
+ return true;
+}
+
+void _s5p_vlayer_get_priority(unsigned long buf_out)
+{
+ unsigned int *id = (unsigned int *)buf_out;
+
+ *id = s5ptv_status.vl_basic_param.priority;
+}
+
+bool _s5p_vlayer_set_brightness_contrast_control(unsigned long buf_in)
+{
+ u32 intc;
+ u32 slope;
+
+ enum s5p_vp_line_eq eq_num;
+ enum s5p_tv_vp_err verr;
+ struct s5p_vl_bright_contrast_ctrl *ctrl =
+ (struct s5p_vl_bright_contrast_ctrl *)buf_in;
+
+ if (ctrl->eq_num > VProc_LINE_EQ_7 ||
+ ctrl->eq_num < VProc_LINE_EQ_0) {
+ VLAYERPRINTK("(ERR) : invalid eq_num(%d)\n\r", ctrl->eq_num);
+ return false;
+ }
+
+ memcpy((void *)&(s5ptv_status.vl_bc_control[ctrl->eq_num]),
+ (const void *)ctrl, sizeof(struct s5p_vl_csc_ctrl));
+
+ eq_num = s5ptv_status.vl_bc_control[ctrl->eq_num].eq_num;
+ intc = s5ptv_status.vl_bc_control[ctrl->eq_num].intc;
+ slope = s5ptv_status.vl_bc_control[ctrl->eq_num].slope;
+
+ if (_s5p_vlayer_wait_previous_update())
+ return false;
+
+
+ verr = __s5p_vp_set_brightness_contrast_control(eq_num, intc, slope);
+
+ if (verr != VPROC_NO_ERROR)
+ return false;
+
+
+ verr = __s5p_vp_update();
+
+ if (verr != VPROC_NO_ERROR)
+ return false;
+
+
+ return true;
+}
+
+bool _s5p_vlayer_set_poly_filter_coef(unsigned long buf_in)
+{
+ struct s5p_video_poly_filter_coef *coef =
+ (struct s5p_video_poly_filter_coef *)buf_in;
+ enum s5p_tv_vp_err verr;
+
+ if (coef->poly_coeff < VPROC_POLY8_Y0_LL ||
+ (coef->poly_coeff > VPROC_POLY8_Y3_HH &&
+ coef->poly_coeff < VPROC_POLY4_Y0_LL) ||
+ coef->poly_coeff > VPROC_POLY4_C1_HH) {
+ VLAYERPRINTK("(ERR) : invalid poly_coeff(%d)\n\r",
+ coef->poly_coeff);
+ return false;
+ }
+
+ if (_s5p_vlayer_wait_previous_update())
+ return false;
+
+
+ verr = __s5p_vp_init_poly_filter_coef(coef->poly_coeff,
+ coef->ch0, coef->ch1,
+ coef->ch2, coef->ch3);
+
+ if (verr != VPROC_NO_ERROR)
+ return false;
+
+ verr = __s5p_vp_update();
+
+ if (verr != VPROC_NO_ERROR)
+ return false;
+
+ s5ptv_status.vl_poly_filter_default = false;
+
+ return true;
+}
+
+bool _s5p_vlayer_set_csc_coef(unsigned long buf_in)
+{
+ struct s5p_video_csc_coef *coef = (struct s5p_video_csc_coef *)buf_in;
+ enum s5p_tv_vp_err verr;
+
+ if (coef->csc_coeff < VPROC_CSC_Y2Y_COEF ||
+ coef->csc_coeff > VPROC_CSC_CR2CR_COEF) {
+ VLAYERPRINTK("(ERR) : invalid csc_coeff(%d)\n\r",
+ coef->csc_coeff);
+ return false;
+ }
+
+ if (_s5p_vlayer_wait_previous_update())
+ return false;
+
+ verr = __s5p_vp_init_csc_coef(coef->csc_coeff, coef->coeff);
+
+ if (verr != VPROC_NO_ERROR)
+ return false;
+
+
+ verr = __s5p_vp_update();
+
+ if (verr != VPROC_NO_ERROR)
+ return false;
+
+
+ s5ptv_status.vl_csc_coef_default = false;
+
+ return true;
+}
+
+bool _s5p_vlayer_init_param(unsigned long buf_in)
+{
+ struct s5p_tv_status *st = &s5ptv_status;
+
+ bool i_mode, o_mode; /* 0 for interlaced, 1 for progressive */
+
+ switch (st->tvout_param.disp_mode) {
+
+ case TVOUT_480P_60_16_9:
+
+ case TVOUT_480P_60_4_3:
+
+ case TVOUT_576P_50_16_9:
+
+ case TVOUT_576P_50_4_3:
+
+#ifdef CONFIG_CPU_S5PV210
+ case TVOUT_480P_59:
+ st->vl_csc_type = VPROC_CSC_SD_HD;
+ break;
+
+ case TVOUT_1080I_50:
+
+ case TVOUT_1080I_60:
+
+ case TVOUT_1080P_50:
+
+ case TVOUT_1080P_30:
+
+ case TVOUT_1080P_60:
+
+ case TVOUT_720P_59:
+
+ case TVOUT_1080I_59:
+
+ case TVOUT_1080P_59:
+#endif
+ case TVOUT_720P_50:
+
+ case TVOUT_720P_60:
+ st->vl_csc_type = VPROC_CSC_HD_SD;
+ break;
+
+ default:
+ break;
+ }
+
+ st->vl_csc_control.csc_en = false;
+
+
+ i_mode = check_input_mode(st->src_color);
+ o_mode = check_output_mode(st->tvout_param.disp_mode,
+ st->tvout_param.out_mode);
+
+ /* check o_mode */
+ if (i_mode == INTERLACED) {
+ /* i to i : line skip 1, ipc 0, auto toggle 0 */
+ if (o_mode == INTERLACED) {
+ st->vl_op_mode.line_skip = true;
+ st->vl2d_ipc = false;
+ st->vl_op_mode.toggle_id = false;
+ } else {
+ /* i to p : line skip 1, ipc 1, auto toggle 0 */
+ st->vl_op_mode.line_skip = true;
+ st->vl2d_ipc = true;
+ st->vl_op_mode.toggle_id = false;
+ }
+ } else {
+ /* p to i : line skip 1, ipc 0, auto toggle 0 */
+ if (o_mode == INTERLACED) {
+ st->vl_op_mode.line_skip = true;
+ st->vl2d_ipc = false;
+ st->vl_op_mode.toggle_id = false;
+ } else {
+ /* p to p : line skip 0, ipc 0, auto toggle 0 */
+ st->vl_op_mode.line_skip = false;
+ st->vl2d_ipc = false;
+ st->vl_op_mode.toggle_id = false;
+ }
+ }
+
+
+
+ st->vl_op_mode.mem_mode = ((st->src_color == VPROC_SRC_COLOR_NV12) ||
+ st->src_color == VPROC_SRC_COLOR_NV12IW) ?
+ VPROC_LINEAR_MODE : VPROC_2D_TILE_MODE;
+/*
+ st->vl_op_mode.chroma_exp = (pro) ? VPROC_USING_C_TOP
+ : VPROC_USING_C_TOP_BOTTOM;
+*/
+ st->vl_op_mode.chroma_exp = 0; /* use only top y addr */
+
+ _s5p_vlayer_calc_inner_values();
+
+ if (st->vl_mode) {
+ VLAYERPRINTK("(ERR) : Default values are already updated\n\r");
+ return true;
+ }
+
+ /* Initialize Video Layer Parameters to Default Values */
+ st->vl_src_x_fact_step = 0;
+ st->field_id = VPROC_TOP_FIELD;
+ st->vl_rate = VPROC_PIXEL_PER_RATE_1_1;
+ st->vl_poly_filter_default = true;
+ st->vl_bypass_post_process = false;
+ st->vl_saturation = 0x80;
+ st->vl_sharpness.th_noise = 0;
+ st->vl_sharpness.sharpness = VPROC_SHARPNESS_NO;
+ st->us_vl_brightness = 0x00;
+ st->vl_contrast = 0x80;
+ st->vl_bright_offset = 0x00;
+ st->vl_csc_control.sub_y_offset_en = false;
+ st->vl_csc_coef_default = true;
+ st->vl_bc_control[0].eq_num = VProc_LINE_EQ_7 + 1;
+ st->vl_bc_control[1].eq_num = VProc_LINE_EQ_7 + 1;
+ st->vl_bc_control[2].eq_num = VProc_LINE_EQ_7 + 1;
+ st->vl_bc_control[3].eq_num = VProc_LINE_EQ_7 + 1;
+ st->vl_bc_control[4].eq_num = VProc_LINE_EQ_7 + 1;
+ st->vl_bc_control[5].eq_num = VProc_LINE_EQ_7 + 1;
+ st->vl_bc_control[6].eq_num = VProc_LINE_EQ_7 + 1;
+ st->vl_bc_control[7].eq_num = VProc_LINE_EQ_7 + 1;
+ st->vl_mode = true;
+
+ return true;
+}
+
diff --git a/drivers/media/video/samsung/tv20/s5p_tv.h b/drivers/media/video/samsung/tv20/s5p_tv.h
new file mode 100644
index 0000000..ac3eab6
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/s5p_tv.h
@@ -0,0 +1,1099 @@
+/* linux/drivers/media/video/samsung/tv20/s5p_tv.h
+ *
+ * TV out driver header file for Samsung TVOut driver
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_samsung.h>
+#include <linux/platform_device.h>
+#include <linux/fb.h>
+
+#ifdef CONFIG_CPU_S5PV210
+#include "s5pv210/tv_out_s5pv210.h"
+#endif
+
+#ifdef CONFIG_CPU_S5PC100
+#include "s5pc100/tv_out_s5pc100.h"
+#endif
+
+/* #define COFIG_TVOUT_DBG */
+
+#ifdef CONFIG_CPU_S5PC100
+#define FIX_27M_UNSTABLE_ISSUE
+#define S5P_HDCP_I2C_ADDR 0x74
+#define I2C_DRIVERID_S5P_HDCP 510
+#endif
+
+#define V4L2_STD_ALL_HD ((v4l2_std_id)0xffffffff)
+
+
+#ifdef CONFIG_TV_FB
+#define TVOUT_MINOR_TVOUT 14
+#define TVOUT_MINOR_VID 21
+#else
+#define TVOUT_MINOR_VIDEO 14
+#define TVOUT_MINOR_GRP0 21
+#define TVOUT_MINOR_GRP1 22
+#endif
+
+#define USE_VMIXER_INTERRUPT 1
+
+#define AVI_SAME_WITH_PICTURE_AR (0x1<<3)
+
+#define AVI_RGB_IF (0x0<<5)
+#define AVI_YCBCR444_IF (0x2<<5)
+
+#define AVI_ITU601 (0x1<<6)
+#define AVI_ITU709 (0x2<<6)
+
+#define AVI_PAR_4_3 (0x1<<4)
+#define AVI_PAR_16_9 (0x2<<4)
+
+#define AVI_NO_PIXEL_REPEAT (0x0<<0)
+
+#define AVI_VIC_2 (2<<0)
+#define AVI_VIC_3 (3<<0)
+#define AVI_VIC_4 (4<<0)
+#define AVI_VIC_5 (5<<0)
+#define AVI_VIC_16 (16<<0)
+#define AVI_VIC_17 (17<<0)
+#define AVI_VIC_18 (18<<0)
+#define AVI_VIC_19 (19<<0)
+#define AVI_VIC_20 (20<<0)
+#define AVI_VIC_31 (31<<0)
+#define AVI_VIC_34 (34<<0)
+
+
+#define VP_UPDATE_RETRY_MAXIMUM 30
+#define VP_WAIT_UPDATE_SLEEP 3
+
+struct tvout_output_if {
+ enum s5p_tv_disp_mode disp_mode;
+ enum s5p_tv_o_mode out_mode;
+};
+
+struct s5p_img_size {
+ u32 img_width;
+ u32 img_height;
+};
+
+struct s5p_img_offset {
+ u32 offset_x;
+ u32 offset_y;
+};
+
+struct s5p_video_img_address {
+ u32 y_address;
+ u32 c_address;
+};
+
+struct s5p_vl_mode {
+ bool line_skip;
+ enum s5p_vp_mem_mode mem_mode;
+ enum s5p_vp_chroma_expansion chroma_exp;
+ enum s5p_vp_filed_id_toggle toggle_id;
+};
+
+struct s5p_vl_sharpness {
+ u32 th_noise;
+ enum s5p_vp_sharpness_control sharpness;
+};
+
+struct s5p_vl_csc_ctrl {
+ bool sub_y_offset_en;
+ bool csc_en;
+};
+
+struct s5p_video_poly_filter_coef {
+ enum s5p_vp_poly_coeff poly_coeff;
+ signed char ch0;
+ signed char ch1;
+ signed char ch2;
+ signed char ch3;
+};
+
+struct s5p_vl_bright_contrast_ctrl {
+ enum s5p_vp_line_eq eq_num;
+ u32 intc;
+ u32 slope;
+};
+
+struct s5p_video_csc_coef {
+ enum s5p_vp_csc_coeff csc_coeff;
+ u32 coeff;
+};
+
+struct s5p_vl_param {
+ bool win_blending;
+ u32 alpha;
+ u32 priority;
+ u32 top_y_address;
+ u32 top_c_address;
+ enum s5p_endian_type src_img_endian;
+ u32 img_width;
+ u32 img_height;
+ u32 src_offset_x;
+ u32 src_offset_y;
+ u32 src_width;
+ u32 src_height;
+ u32 dest_offset_x;
+ u32 dest_offset_y;
+ u32 dest_width;
+ u32 dest_height;
+};
+
+struct s5p_tv_vo {
+ u32 index;
+ struct v4l2_framebuffer fb;
+ struct v4l2_window win;
+ struct v4l2_rect dst_rect;
+ bool win_blending;
+ bool blank_change;
+ bool pixel_blending;
+ bool pre_mul;
+ u32 blank_color;
+ u32 priority;
+ u32 base_addr;
+};
+
+struct s5p_bg_dither {
+ bool cr_dither_en;
+ bool cb_dither_en;
+ bool y_dither_en;
+};
+
+
+struct s5p_bg_color {
+ u32 color_y;
+ u32 color_cb;
+ u32 color_cr;
+};
+
+struct s5p_vm_csc_coef {
+ enum s5p_yuv_fmt_component component;
+ enum s5p_tv_coef_y_mode mode;
+ u32 coeff_0;
+ u32 coeff_1;
+ u32 coeff_2;
+};
+
+struct s5p_sdout_order {
+ enum s5p_sd_order order;
+ bool dac[3];
+};
+
+struct s5p_sd_vscale_cfg {
+ enum s5p_sd_level component_level;
+ enum s5p_sd_vsync_ratio component_ratio;
+ enum s5p_sd_level composite_level;
+ enum s5p_sd_vsync_ratio composite_ratio;
+};
+
+struct s5p_sd_vbi {
+ bool wss_cvbs;
+ enum s5p_sd_closed_caption_type caption_cvbs;
+ bool wss_y_svideo;
+ enum s5p_sd_closed_caption_type caption_y_svideo;
+ bool cgmsa_rgb;
+ bool wss_rgb;
+ enum s5p_sd_closed_caption_type caption_rgb;
+ bool cgmsa_y_pb_pr;
+ bool wss_y_pb_pr;
+ enum s5p_sd_closed_caption_type caption_y_pb_pr;
+};
+
+struct s5p_sd_offset_gain {
+ enum s5p_sd_channel_sel channel;
+ u32 offset;
+ u32 gain;
+};
+
+struct s5p_sd_delay {
+ u32 delay_y;
+ u32 offset_video_start;
+ u32 offset_video_end;
+};
+
+struct s5p_sd_bright_hue_saturat {
+ bool bright_hue_sat_adj;
+ u32 gain_brightness;
+ u32 offset_brightness;
+ u32 gain0_cb_hue_saturation;
+ u32 gain1_cb_hue_saturation;
+ u32 gain0_cr_hue_saturation;
+ u32 gain1_cr_hue_saturation;
+ u32 offset_cb_hue_saturation;
+ u32 offset_cr_hue_saturation;
+};
+
+struct s5p_sd_rgb_compensat {
+ bool rgb_color_compensation;
+ u32 max_rgb_cube;
+ u32 min_rgb_cube;
+};
+
+struct s5p_sd_cvbs_compensat {
+ bool cvbs_color_compensation;
+ u32 y_lower_mid;
+ u32 y_bottom;
+ u32 y_top;
+ u32 y_upper_mid;
+ u32 radius;
+};
+
+struct s5p_sd_svideo_compensat {
+ bool y_color_compensation;
+ u32 y_top;
+ u32 y_bottom;
+ u32 yc_cylinder;
+};
+
+struct s5p_sd_component_porch {
+ u32 back_525;
+ u32 front_525;
+ u32 back_625;
+ u32 front_625;
+};
+
+struct s5p_sd_vesa_rgb_sync {
+ enum s5p_sd_vesa_rgb_sync_type sync_type;
+ enum s5p_tv_active_polarity vsync_active;
+ enum s5p_tv_active_polarity hsync_active;
+};
+
+struct s5p_sd_ch_xtalk_cancellat_coeff {
+ enum s5p_sd_channel_sel channel;
+ u32 coeff1;
+ u32 coeff2;
+};
+
+struct s5p_sd_closed_caption {
+ u32 display_cc;
+ u32 nondisplay_cc;
+};
+
+struct s5p_sd_525_data {
+ bool analog_on;
+ enum s5p_sd_525_copy_permit copy_permit;
+ enum s5p_sd_525_mv_psp mv_psp;
+ enum s5p_sd_525_copy_info copy_info;
+ enum s5p_sd_525_aspect_ratio display_ratio;
+};
+
+struct s5p_sd_625_data {
+ bool surroun_f_sound;
+ bool copyright;
+ bool copy_protection;
+ bool text_subtitles;
+ enum s5p_sd_625_subtitles open_subtitles;
+ enum s5p_sd_625_camera_film camera_film;
+ enum s5p_sd_625_color_encoding color_encoding;
+ bool helper_signal;
+ enum s5p_sd_625_aspect_ratio display_ratio;
+};
+
+struct s5p_hdmi_bluescreen {
+ bool enable;
+ u8 cb_b;
+ u8 y_g;
+ u8 cr_r;
+};
+
+struct s5p_hdmi_color_range {
+ u8 y_min;
+ u8 y_max;
+ u8 c_min;
+ u8 c_max;
+};
+
+struct s5p_hdmi_video_infoframe {
+ enum s5p_hdmi_transmit trans_type;
+ u8 check_sum;
+ u8 *data;
+};
+
+struct s5p_hdmi_tg_cmd {
+ bool timing_correction_en;
+ bool bt656_sync_en;
+ bool tg_en;
+};
+
+struct s5p_hdmi_spd_infoframe {
+ enum s5p_hdmi_transmit trans_type;
+ u8 *spd_header;
+ u8 *spd_data;
+};
+
+struct s5p_tv_v4l2 {
+ struct v4l2_output *output;
+ struct v4l2_standard *std;
+ struct v4l2_format *fmt_v;
+ struct v4l2_format *fmt_vo_0;
+ struct v4l2_format *fmt_vo_1;
+};
+
+
+#define S5PTVFB_AVALUE(r, g, b) \
+ (((r & 0xf) << 8) | ((g & 0xf) << 4) | ((b & 0xf) << 0))
+#define S5PTVFB_CHROMA(r, g, b) \
+ (((r & 0xff) << 16) | ((g & 0xff) << 8) | ((b & 0xff) << 0))
+
+#define S5PTVFB_WIN_POSITION \
+ _IOW('F', 213, struct s5ptvfb_user_window)
+#define S5PTVFB_WIN_SET_PLANE_ALPHA \
+ _IOW('F', 214, struct s5ptvfb_user_plane_alpha)
+#define S5PTVFB_WIN_SET_CHROMA \
+ _IOW('F', 215, struct s5ptvfb_user_chroma)
+
+enum s5ptvfb_data_path_t {
+ DATA_PATH_FIFO = 0,
+ DATA_PATH_DMA = 1,
+};
+
+enum s5ptvfb_alpha_t {
+ PLANE_BLENDING,
+ PIXEL_BLENDING,
+};
+
+enum s5ptvfb_chroma_dir_t {
+ CHROMA_FG,
+ CHROMA_BG,
+};
+
+struct s5ptvfb_alpha {
+ enum s5ptvfb_alpha_t mode;
+ int channel;
+ unsigned int value;
+};
+
+struct s5ptvfb_chroma {
+ int enabled;
+ int blended;
+ unsigned int key;
+ unsigned int comp_key;
+ unsigned int alpha;
+ enum s5ptvfb_chroma_dir_t dir;
+};
+
+struct s5ptvfb_user_window {
+ int x;
+ int y;
+};
+
+struct s5ptvfb_user_plane_alpha {
+ int channel;
+ unsigned char red;
+ unsigned char green;
+ unsigned char blue;
+};
+
+struct s5ptvfb_user_chroma {
+ int enabled;
+ unsigned char red;
+ unsigned char green;
+ unsigned char blue;
+};
+
+
+struct s5ptvfb_window {
+ int id;
+ int enabled;
+ atomic_t in_use;
+ int x;
+ int y;
+ enum s5ptvfb_data_path_t path;
+ int local_channel;
+ int dma_burst;
+ unsigned int pseudo_pal[16];
+ struct s5ptvfb_alpha alpha;
+ struct s5ptvfb_chroma chroma;
+ int (*suspend_fifo)(void);
+ int (*resume_fifo)(void);
+};
+
+struct s5ptvfb_lcd_timing {
+ int h_fp;
+ int h_bp;
+ int h_sw;
+ int v_fp;
+ int v_fpe;
+ int v_bp;
+ int v_bpe;
+ int v_sw;
+};
+
+struct s5ptvfb_lcd_polarity {
+ int rise_vclk;
+ int inv_hsync;
+ int inv_vsync;
+ int inv_vden;
+};
+
+struct s5ptvfb_lcd {
+ int width;
+ int height;
+ int bpp;
+ int freq;
+ struct s5ptvfb_lcd_timing timing;
+ struct s5ptvfb_lcd_polarity polarity;
+
+ void (*init_ldi)(void);
+};
+
+struct s5p_tv_status {
+ /* TVOUT_SET_INTERFACE_PARAM */
+ bool tvout_param_available;
+ struct tvout_output_if tvout_param;
+
+ /* TVOUT_SET_OUTPUT_ENABLE/DISABLE */
+ bool tvout_output_enable;
+
+ /* TVOUT_SET_LAYER_MODE/POSITION */
+ bool vl_mode;
+ bool grp_mode[2];
+
+ /* Video Layer Parameters */
+ struct s5p_vl_param vl_basic_param;
+ struct s5p_vl_mode vl_op_mode;
+ struct s5p_vl_sharpness vl_sharpness;
+ struct s5p_vl_csc_ctrl vl_csc_control;
+ struct s5p_vl_bright_contrast_ctrl vl_bc_control[8];
+
+ enum s5p_vp_src_color src_color;
+ enum s5p_vp_field field_id;
+ enum s5p_vp_pxl_rate vl_rate;
+ enum s5p_vp_csc_type vl_csc_type;
+
+ u32 vl_top_y_address;
+ u32 vl_top_c_address;
+ u32 vl_bottom_y_address;
+ u32 vl_bottom_c_address;
+ u32 vl_src_offset_x;
+ u32 vl_src_x_fact_step;
+ u32 vl_src_offset_y;
+ u32 vl_src_width;
+ u32 vl_src_height;
+ u32 vl_dest_offset_x;
+ u32 vl_dest_offset_y;
+ u32 vl_dest_width;
+ u32 vl_dest_height;
+ bool vl2d_ipc;
+
+ bool vl_poly_filter_default;
+ bool vl_bypass_post_process;
+ u32 vl_saturation;
+ bool us_vl_brightness;
+ u8 vl_contrast;
+ u32 vl_bright_offset;
+ bool vl_csc_coef_default;
+
+ /* GRP Layer Common Parameters */
+ enum s5p_vmx_burst_mode grp_burst;
+ enum s5p_endian_type grp_endian;
+
+ /* BackGroung Layer Parameters */
+ struct s5p_bg_dither bg_dither;
+ struct s5p_bg_color bg_color[3];
+
+ /* Video Mixer Parameters */
+ bool vm_csc_coeff_default;
+
+ /* SDout Parameters */
+ struct s5p_sd_vscale_cfg sdout_video_scale_cfg;
+ struct s5p_sd_vbi sdout_vbi;
+ struct s5p_sd_offset_gain sdout_offset_gain[3];
+ struct s5p_sd_delay sdout_delay;
+ struct s5p_sd_bright_hue_saturat sdout_bri_hue_set;
+ struct s5p_sd_rgb_compensat sdout_rgb_compen;
+ struct s5p_sd_cvbs_compensat sdout_cvbs_compen;
+ struct s5p_sd_svideo_compensat sdout_svideo_compen;
+ struct s5p_sd_component_porch sdout_comp_porch;
+ struct s5p_sd_vesa_rgb_sync sdout_rgb_sync;
+ struct s5p_sd_ch_xtalk_cancellat_coeff sdout_xtalk_cc[3];
+ struct s5p_sd_closed_caption sdout_closed_capt;
+ struct s5p_sd_525_data sdout_wss_525;
+ struct s5p_sd_625_data sdout_wss_625;
+ struct s5p_sd_525_data sdout_cgms_525;
+ struct s5p_sd_625_data sdout_cgms_625;
+
+ enum s5p_sd_order sdout_order;
+ enum s5p_sd_sync_sig_pin sdout_sync_pin;
+
+ bool sdout_color_sub_carrier_phase_adj;
+ bool sdout_dac_on[3];
+ bool sdout_y_pb_pr_comp;
+
+ /* HDMI video parameters */
+ struct s5p_hdmi_bluescreen hdmi_video_blue_screen;
+ struct s5p_hdmi_color_range hdmi_color_range;
+ struct s5p_hdmi_video_infoframe hdmi_av_info_frame;
+ struct s5p_hdmi_video_infoframe hdmi_mpg_info_frame;
+ struct s5p_hdmi_tg_cmd hdmi_tg_cmd;
+ u8 avi_byte[13];
+ u8 mpg_byte[5];
+
+ /* HDMI parameters */
+ struct s5p_hdmi_spd_infoframe hdmi_spd_info_frame;
+ u8 spd_header[3];
+ u8 spd_data[28];
+ bool hdcp_en;
+ enum s5p_hdmi_audio_type hdmi_audio_type;
+ bool hpd_status;
+ bool suspend_status;
+
+ /* TVOUT_SET_LAYER_ENABLE/DISABLE */
+ bool vp_layer_enable;
+ bool grp_layer_enable[2];
+
+ /* i2c for hdcp port */
+ struct i2c_client *hdcp_i2c_client;
+
+ struct s5p_tv_vo overlay[2];
+
+ struct video_device *video_dev[3];
+
+ struct regulator *tv_tv;
+ struct regulator *tv_tvout;
+ struct regulator *tv_regulator;
+
+ struct clk *tvenc_clk;
+ struct clk *vp_clk;
+ struct clk *mixer_clk;
+ struct clk *hdmi_clk;
+ struct clk *i2c_phy_clk;
+ struct clk *sclk_hdmiphy;
+ struct clk *sclk_pixel;
+ struct clk *sclk_dac;
+ struct clk *sclk_hdmi;
+ struct clk *sclk_mixer;
+
+ struct s5p_tv_v4l2 v4l2;
+
+ struct s5ptvfb_window win;
+ struct fb_info *fb;
+ struct device *dev_fb;
+
+ struct s5ptvfb_lcd *lcd;
+ struct mutex fb_lock;
+};
+
+/* F R A M E B U F F E R */
+#define S5PTVFB_NAME "s5ptvfb"
+
+/*
+* V4L2 TVOUT EXTENSIONS
+*
+*/
+#define V4L2_INPUT_TYPE_MSDMA 3
+#define V4L2_INPUT_TYPE_FIFO 4
+
+#define V4L2_OUTPUT_TYPE_MSDMA 4
+#define V4L2_OUTPUT_TYPE_COMPOSITE 5
+#define V4L2_OUTPUT_TYPE_SVIDEO 6
+#define V4L2_OUTPUT_TYPE_YPBPR_INERLACED 7
+#define V4L2_OUTPUT_TYPE_YPBPR_PROGRESSIVE 8
+#define V4L2_OUTPUT_TYPE_RGB_PROGRESSIVE 9
+#define V4L2_OUTPUT_TYPE_DIGITAL 10
+#define V4L2_OUTPUT_TYPE_HDMI V4L2_OUTPUT_TYPE_DIGITAL
+#define V4L2_OUTPUT_TYPE_HDMI_RGB 11
+#define V4L2_OUTPUT_TYPE_DVI 12
+
+#define V4L2_STD_PAL_BDGHI (V4L2_STD_PAL_B| \
+ V4L2_STD_PAL_D| \
+ V4L2_STD_PAL_G| \
+ V4L2_STD_PAL_H| \
+ V4L2_STD_PAL_I)
+
+#define V4L2_STD_480P_60_16_9 ((v4l2_std_id)0x04000000)
+#define V4L2_STD_480P_60_4_3 ((v4l2_std_id)0x05000000)
+#define V4L2_STD_576P_50_16_9 ((v4l2_std_id)0x06000000)
+#define V4L2_STD_576P_50_4_3 ((v4l2_std_id)0x07000000)
+#define V4L2_STD_720P_60 ((v4l2_std_id)0x08000000)
+#define V4L2_STD_720P_50 ((v4l2_std_id)0x09000000)
+#define V4L2_STD_1080P_60 ((v4l2_std_id)0x0a000000)
+#define V4L2_STD_1080P_50 ((v4l2_std_id)0x0b000000)
+#define V4L2_STD_1080I_60 ((v4l2_std_id)0x0c000000)
+#define V4L2_STD_1080I_50 ((v4l2_std_id)0x0d000000)
+#define V4L2_STD_480P_59 ((v4l2_std_id)0x0e000000)
+#define V4L2_STD_720P_59 ((v4l2_std_id)0x0f000000)
+#define V4L2_STD_1080I_59 ((v4l2_std_id)0x10000000)
+#define V4L2_STD_1080P_59 ((v4l2_std_id)0x11000000)
+#define V4L2_STD_1080P_30 ((v4l2_std_id)0x12000000)
+
+#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
+
+#define V4L2_FBUF_FLAG_PRE_MULTIPLY 0x0040
+#define V4L2_FBUF_CAP_PRE_MULTIPLY 0x0080
+
+struct v4l2_window_s5p_tvout {
+ u32 capability;
+ u32 flags;
+ u32 priority;
+
+ struct v4l2_window win;
+};
+
+struct v4l2_pix_format_s5p_tvout {
+ void *base_y;
+ void *base_c;
+ bool src_img_endian;
+
+ struct v4l2_pix_format pix_fmt;
+};
+
+extern const struct v4l2_ioctl_ops s5p_tv_v4l2_v_ops;
+extern const struct v4l2_ioctl_ops s5p_tv_v4l2_vo_ops;
+extern const struct v4l2_ioctl_ops s5p_tv_v4l2_ops;
+extern const struct v4l2_ioctl_ops s5p_tv_v4l2_vid_ops;
+
+
+extern void s5p_tv_v4l2_init_param(void);
+
+extern long s5p_tv_ioctl(struct file *file, u32 cmd, unsigned long arg);
+extern long s5p_tv_vid_ioctl(struct file *file, u32 cmd, unsigned long arg);
+extern long s5p_tv_v_ioctl(struct file *file, u32 cmd, unsigned long arg);
+extern long s5p_tv_vo_ioctl(struct file *file, u32 cmd, unsigned long arg);
+
+
+#ifdef CONFIG_CPU_S5PC100
+int __init __s5p_hdmi_probe(struct platform_device *pdev, u32 res_num);
+#endif
+
+#ifdef CONFIG_CPU_S5PV210
+int __init __s5p_hdmi_probe(struct platform_device *pdev,
+ u32 res_num, u32 res_num2);
+int __s5p_hdmi_phy_power(bool on);
+#endif
+
+int __init __s5p_sdout_probe(struct platform_device *pdev, u32 res_num);
+int __init __s5p_mixer_probe(struct platform_device *pdev, u32 res_num);
+int __init __s5p_vp_probe(struct platform_device *pdev, u32 res_num);
+int __init __s5p_tvclk_probe(struct platform_device *pdev, u32 res_num);
+
+int __init __s5p_hdmi_release(struct platform_device *pdev);
+int __init __s5p_sdout_release(struct platform_device *pdev);
+int __init __s5p_mixer_release(struct platform_device *pdev);
+int __init __s5p_vp_release(struct platform_device *pdev);
+int __init __s5p_tvclk_release(struct platform_device *pdev);
+
+
+extern bool _s5p_hdmi_api_proc(unsigned long arg, u32 cmd);
+extern bool _s5p_hdmi_video_api_proc(unsigned long arg, u32 cmd);
+
+extern bool _s5p_grp_api_proc(unsigned long arg, u32 cmd);
+extern bool _s5p_grp_init_param(enum s5p_tv_vmx_layer vm_layer,
+ unsigned long p_buf_in);
+extern bool _s5p_grp_start(enum s5p_tv_vmx_layer vmLayer);
+extern bool _s5p_grp_stop(enum s5p_tv_vmx_layer vmLayer);
+
+extern bool _s5p_tv_if_api_proc(unsigned long arg, u32 cmd);
+extern bool _s5p_tv_if_init_param(void);
+extern bool _s5p_tv_if_start(void);
+extern bool _s5p_tv_if_stop(void);
+extern bool _s5p_tv_if_set_disp(void);
+
+extern bool _s5p_bg_api_proc(unsigned long arg, u32 cmd);
+extern bool _s5p_sdout_api_proc(unsigned long arg, u32 cmd);
+
+extern bool _s5p_vlayer_set_blending(unsigned long p_buf_in);
+extern bool _s5p_vlayer_set_alpha(unsigned long p_buf_in);
+extern bool _s5p_vlayer_api_proc(unsigned long arg, u32 cmd);
+extern bool _s5p_vlayer_init_param(unsigned long p_buf_in);
+extern bool _s5p_vlayer_set_priority(unsigned long p_buf_in);
+extern bool _s5p_vlayer_set_field_id(unsigned long p_buf_in);
+extern bool _s5p_vlayer_set_top_address(unsigned long p_buf_in);
+extern bool _s5p_vlayer_set_bottom_address(unsigned long p_buf_in);
+extern bool _s5p_vlayer_set_img_size(unsigned long p_buf_in);
+extern bool _s5p_vlayer_set_src_position(unsigned long p_buf_in);
+extern bool _s5p_vlayer_set_dest_position(unsigned long p_buf_in);
+extern bool _s5p_vlayer_set_src_size(unsigned long p_buf_in);
+extern bool _s5p_vlayer_set_dest_size(unsigned long p_buf_in);
+extern bool _s5p_vlayer_set_brightness(unsigned long p_buf_in);
+extern bool _s5p_vlayer_set_contrast(unsigned long p_buf_in);
+extern void _s5p_vlayer_get_priority(unsigned long p_buf_out);
+extern bool _s5p_vlayer_set_brightness_contrast_control(unsigned long
+ p_buf_in);
+extern bool _s5p_vlayer_set_poly_filter_coef(unsigned long p_buf_in);
+extern bool _s5p_vlayer_set_csc_coef(unsigned long p_buf_in);
+extern bool _s5p_vlayer_start(void);
+extern bool _s5p_vlayer_stop(void);
+
+void __s5p_read_hdcp_data(u8 reg_addr, u8 count, u8 *data);
+void __s5p_write_hdcp_data(u8 reg_addr, u8 count, u8 *data);
+void __s5p_write_ainfo(void);
+void __s5p_write_an(void);
+void __s5p_write_aksv(void);
+void __s5p_read_bcaps(void);
+void __s5p_read_bksv(void);
+bool __s5p_compare_p_value(void);
+bool __s5p_compare_r_value(void);
+void __s5p_reset_authentication(void);
+void __s5p_make_aes_key(void);
+void __s5p_set_av_mute_on_off(u32 on_off);
+void __s5p_start_encryption(void);
+void __s5p_start_decrypting(const u8 *hdcp_key, u32 hdcp_key_size);
+bool __s5p_check_repeater(void);
+bool __s5p_is_occurred_hdcp_event(void);
+irqreturn_t __s5p_hdmi_irq(int irq, void *dev_id);
+bool __s5p_is_decrypting_done(void);
+void __s5p_set_hpd_detection(u32 detection_type, bool hdcp_enabled,
+ struct i2c_client *client);
+
+#ifdef CONFIG_CPU_S5PC100
+bool __s5p_start_hdcp(void);
+void __s5p_stop_hdcp(void);
+void __s5p_hdcp_reset(void);
+#endif
+
+void __s5p_hdmi_set_hpd_onoff(bool on_off);
+void __s5p_hdmi_audio_set_config(enum s5p_tv_audio_codec_type audio_codec);
+void __s5p_hdmi_audio_set_acr(u32 sample_rate);
+void __s5p_hdmi_audio_set_asp(void);
+void __s5p_hdmi_audio_clock_enable(void);
+void __s5p_hdmi_audio_set_repetition_time(
+ enum s5p_tv_audio_codec_type audio_codec,
+ u32 bits, u32 frame_size_code);
+void __s5p_hdmi_audio_irq_enable(u32 irq_en);
+void __s5p_hdmi_audio_set_aui(enum s5p_tv_audio_codec_type audio_codec,
+ u32 sample_rate, u32 bits);
+void __s5p_hdmi_video_set_bluescreen(bool en, u8 cb, u8 y_g, u8 cr_r);
+enum s5p_tv_hdmi_err __s5p_hdmi_init_spd_infoframe(
+ enum s5p_hdmi_transmit trans_type,
+ u8 *spd_header, u8 *spd_data);
+void __s5p_hdmi_init_hpd_onoff(bool on_off);
+enum s5p_tv_hdmi_err __s5p_hdmi_audio_init(
+ enum s5p_tv_audio_codec_type audio_codec,
+ u32 sample_rate, u32 bits, u32 frame_size_code);
+enum s5p_tv_hdmi_err __s5p_hdmi_video_init_display_mode(
+ enum s5p_tv_disp_mode disp_mode,
+ enum s5p_tv_o_mode out_mode, u8 *avidata);
+void __s5p_hdmi_video_init_bluescreen(bool en, u8 cb, u8 y_g, u8 cr_r);
+void __s5p_hdmi_video_init_color_range(u8 y_min, u8 y_max, u8 c_min, u8 c_max);
+enum s5p_tv_hdmi_err __s5p_hdmi_video_init_csc(
+ enum s5p_tv_hdmi_csc_type csc_type);
+enum s5p_tv_hdmi_err __s5p_hdmi_video_init_avi_infoframe(
+ enum s5p_hdmi_transmit trans_type, u8 check_sum, u8 *pavi_data);
+enum s5p_tv_hdmi_err __s5p_hdmi_video_init_mpg_infoframe(
+ enum s5p_hdmi_transmit trans_type, u8 check_sum, u8 *pmpg_data);
+void __s5p_hdmi_video_init_tg_cmd(bool t_correction_en, bool BT656_sync_en,
+ bool tg_en);
+bool __s5p_hdmi_start(enum s5p_hdmi_audio_type hdmi_audio_type, bool HDCP_en,
+ struct i2c_client *ddc_port);
+void __s5p_hdmi_stop(void);
+
+enum s5p_tv_sd_err __s5p_sdout_init_video_scale_cfg(
+ enum s5p_sd_level component_level,
+ enum s5p_sd_vsync_ratio component_ratio,
+ enum s5p_sd_level composite_level,
+ enum s5p_sd_vsync_ratio composite_ratio);
+enum s5p_tv_sd_err __s5p_sdout_init_sync_signal_pin(
+ enum s5p_sd_sync_sig_pin pin);
+enum s5p_tv_sd_err __s5p_sdout_init_vbi(bool wss_cvbs,
+ enum s5p_sd_closed_caption_type caption_cvbs, bool wss_y_sideo,
+ enum s5p_sd_closed_caption_type caption_y_sideo, bool cgmsa_rgb,
+ bool wss_rgb, enum s5p_sd_closed_caption_type caption_rgb,
+ bool cgmsa_y_ppr, bool wss_y_ppr,
+ enum s5p_sd_closed_caption_type caption_y_ppr);
+enum s5p_tv_sd_err __s5p_sdout_init_offset_gain(
+ enum s5p_sd_channel_sel channel,
+ u32 offset, u32 gain);
+void __s5p_sdout_init_delay(u32 delay_y, u32 offset_video_start,
+ u32 offset_video_end);
+void __s5p_sdout_init_schlock(bool color_sucarrier_pha_adj);
+enum s5p_tv_sd_err __s5p_sdout_init_dac_power_onoff(
+ enum s5p_sd_channel_sel channel,
+ bool dac_on);
+void __s5p_sdout_init_color_compensaton_onoff(bool bright_hue_saturation_adj,
+ bool y_ppr_color_compensation, bool rgb_color_compensation,
+ bool y_c_color_compensation, bool y_cvbs_color_compensation);
+void __s5p_sdout_init_brightness_hue_saturation(u32 gain_brightness,
+ u32 offset_brightness, u32 gain0_cb_hue_saturation,
+ u32 gain1_cb_hue_saturation, u32 gain0_cr_hue_saturation,
+ u32 gain1_cr_hue_saturation, u32 offset_cb_hue_saturation,
+ u32 offset_cr_hue_saturation);
+void __s5p_sdout_init_rgb_color_compensation(u32 max_rgb_cube,
+ u32 min_rgb_cube);
+void __s5p_sdout_init_cvbs_color_compensation(u32 y_lower_mid,
+ u32 y_bottom, u32 y_top, u32 y_upper_mid, u32 radius);
+void __s5p_sdout_init_svideo_color_compensation(u32 y_top, u32 y_bottom,
+ u32 y_c_cylinder);
+void __s5p_sdout_init_component_porch(u32 back_525, u32 front_525,
+ u32 back_625, u32 front_625);
+enum s5p_tv_sd_err __s5p_sdout_init_vesa_rgb_sync(
+ enum s5p_sd_vesa_rgb_sync_type sync_type,
+ enum s5p_tv_active_polarity v_sync_active,
+ enum s5p_tv_active_polarity h_sync_active);
+void __s5p_sdout_init_oversampling_filter_coeff(u32 size, u32 *pcoeff0,
+ u32 *pcoeff1, u32 *pcoeff2);
+enum s5p_tv_sd_err __s5p_sdout_init_ch_xtalk_cancel_coef(
+ enum s5p_sd_channel_sel channel,
+ u32 coeff2, u32 coeff1);
+void __s5p_sdout_init_closed_caption(u32 display_cc, u32 non_display_cc);
+enum s5p_tv_sd_err __s5p_sdout_init_wss525_data(
+ enum s5p_sd_525_copy_permit copy_permit,
+ enum s5p_sd_525_mv_psp mv_psp, enum s5p_sd_525_copy_info copy_info,
+ bool analog_on, enum s5p_sd_525_aspect_ratio display_ratio);
+enum s5p_tv_sd_err __s5p_sdout_init_wss625_data(bool surround_sound,
+ bool copyright, bool copy_protection, bool text_subtitles,
+ enum s5p_sd_625_subtitles open_subtitles,
+ enum s5p_sd_625_camera_film camera_film,
+ enum s5p_sd_625_color_encoding color_encoding,
+ bool helper_signal, enum s5p_sd_625_aspect_ratio display_ratio);
+enum s5p_tv_sd_err __s5p_sdout_init_cgmsa525_data(
+ enum s5p_sd_525_copy_permit copy_permit, enum s5p_sd_525_mv_psp mv_psp,
+ enum s5p_sd_525_copy_info copy_info, bool analog_on,
+ enum s5p_sd_525_aspect_ratio display_ratio);
+enum s5p_tv_sd_err __s5p_sdout_init_cgmsa625_data(bool surround_sound,
+ bool copyright, bool copy_protection, bool text_subtitles,
+ enum s5p_sd_625_subtitles open_subtitles,
+ enum s5p_sd_625_camera_film camera_film,
+ enum s5p_sd_625_color_encoding color_encoding, bool helper_signal,
+ enum s5p_sd_625_aspect_ratio display_ratio);
+enum s5p_tv_sd_err __s5p_sdout_init_display_mode(
+ enum s5p_tv_disp_mode disp_mode,
+ enum s5p_tv_o_mode out_mode, enum s5p_sd_order order);
+void __s5p_sdout_start(void);
+void __s5p_sdout_stop(void);
+void __s5p_sdout_sw_reset(bool active);
+void __s5p_sdout_set_interrupt_enable(bool vsync_intr_en);
+void __s5p_sdout_clear_interrupt_pending(void);
+bool __s5p_sdout_get_interrupt_pending(void);
+
+enum s5p_tv_vmx_err __s5p_vm_set_win_blend(enum s5p_tv_vmx_layer layer,
+ bool enable);
+enum s5p_tv_vmx_err __s5p_vm_set_layer_alpha(enum s5p_tv_vmx_layer layer,
+ u32 alpha);
+enum s5p_tv_vmx_err __s5p_vm_set_layer_show(enum s5p_tv_vmx_layer layer,
+ bool show);
+enum s5p_tv_vmx_err __s5p_vm_set_layer_priority(enum s5p_tv_vmx_layer layer,
+ u32 priority);
+enum s5p_tv_vmx_err __s5p_vm_set_grp_base_address(enum s5p_tv_vmx_layer layer,
+ u32 baseaddr);
+enum s5p_tv_vmx_err __s5p_vm_set_grp_layer_position(
+ enum s5p_tv_vmx_layer layer,
+ u32 dst_offs_x, u32 dst_offs_y);
+enum s5p_tv_vmx_err __s5p_vm_set_grp_layer_size(enum s5p_tv_vmx_layer layer,
+ u32 span, u32 width, u32 height, u32 src_offs_x, u32 src_offs_y);
+enum s5p_tv_vmx_err __s5p_vm_set_bg_color(
+ enum s5p_tv_vmx_bg_color_num colornum,
+ u32 color_y, u32 color_cb, u32 color_cr);
+enum s5p_tv_vmx_err __s5p_vm_init_status_reg(enum s5p_vmx_burst_mode burst,
+ enum s5p_endian_type endian);
+enum s5p_tv_vmx_err __s5p_vm_init_display_mode(enum s5p_tv_disp_mode mode,
+ enum s5p_tv_o_mode output_mode);
+
+#ifdef CONFIG_CPU_S5PC100
+enum s5p_tv_vmx_err __s5p_vm_init_layer(enum s5p_tv_vmx_layer layer, bool show,
+ bool winblending, u32 alpha, u32 priority,
+ enum s5p_tv_vmx_color_fmt color, bool blankchange,
+ bool pixelblending, bool premul, u32 blankcolor,
+ u32 baseaddr, u32 span, u32 width, u32 height,
+ u32 src_offs_x, u32 src_offs_y, u32 dst_offs_x, u32 dst_offs_y);
+#endif
+
+#ifdef CONFIG_CPU_S5PV210
+enum s5p_tv_vmx_err __s5p_vm_init_layer(enum s5p_tv_disp_mode mode,
+ enum s5p_tv_vmx_layer layer, bool show, bool winblending,
+ u32 alpha, u32 priority, enum s5p_tv_vmx_color_fmt color,
+ bool blankchange, bool pixelblending, bool premul,
+ u32 blankcolor, u32 baseaddr, u32 span, u32 width,
+ u32 height, u32 src_offs_x, u32 src_offs_y, u32 dst_offs_x,
+ u32 dst_offs_y, u32 dst_x, u32 dst_y);
+void __s5p_vm_set_ctrl(enum s5p_tv_vmx_layer layer, bool premul,
+ bool pixel_blending, bool blank_change, bool win_blending,
+ enum s5p_tv_vmx_color_fmt color, u32 alpha, u32 blank_color);
+#endif
+
+void __s5p_vm_init_bg_dither_enable(bool cr_dither_enable,
+ bool cdither_enable, bool y_dither_enable);
+enum s5p_tv_vmx_err __s5p_vm_init_bg_color(
+ enum s5p_tv_vmx_bg_color_num color_num,
+ u32 color_y, u32 color_cb, u32 color_cr);
+enum s5p_tv_vmx_err __s5p_vm_init_csc_coef(
+ enum s5p_yuv_fmt_component component,
+ enum s5p_tv_coef_y_mode mode, u32 coeff0, u32 coeff1, u32 coeff2);
+void __s5p_vm_init_csc_coef_default(enum s5p_tv_vmx_csc_type csc_type);
+enum s5p_tv_vmx_err __s5p_vm_get_layer_info(enum s5p_tv_vmx_layer layer,
+ bool *show,
+ u32 *priority);
+void __s5p_vm_start(void);
+void __s5p_vm_stop(void);
+enum s5p_tv_vmx_err __s5p_vm_set_underflow_interrupt_enable(
+ enum s5p_tv_vmx_layer layer,
+ bool en);
+void __s5p_vm_clear_pend_all(void);
+irqreturn_t __s5p_mixer_irq(int irq, void *dev_id);
+
+void __s5p_vp_set_field_id(enum s5p_vp_field mode);
+enum s5p_tv_vp_err __s5p_vp_set_top_field_address(u32 top_y_addr,
+ u32 top_c_addr);
+enum s5p_tv_vp_err __s5p_vp_set_bottom_field_address(u32 bottom_y_addr,
+ u32 bottom_c_addr);
+enum s5p_tv_vp_err __s5p_vp_set_img_size(u32 img_width, u32 img_height);
+void __s5p_vp_set_src_position(u32 src_off_x, u32 src_x_fract_step,
+ u32 src_off_y);
+void __s5p_vp_set_dest_position(u32 dst_off_x, u32 dst_off_y);
+void __s5p_vp_set_src_dest_size(u32 src_width, u32 src_height,
+ u32 dst_width, u32 dst_height, bool ipc_2d);
+enum s5p_tv_vp_err __s5p_vp_set_poly_filter_coef(
+ enum s5p_vp_poly_coeff poly_coeff,
+ signed char ch0, signed char ch1, signed char ch2, signed char ch3);
+void __s5p_vp_set_poly_filter_coef_default(u32 h_ratio, u32 v_ratio);
+void __s5p_vp_set_src_dest_size_with_default_poly_filter_coef(u32 src_width,
+ u32 src_height, u32 dst_width, u32 dst_height, bool ipc_2d);
+enum s5p_tv_vp_err __s5p_vp_set_brightness_contrast_control(
+ enum s5p_vp_line_eq eq_num,
+ u32 intc, u32 slope);
+void __s5p_vp_set_brightness(bool brightness);
+void __s5p_vp_set_contrast(u8 contrast);
+enum s5p_tv_vp_err __s5p_vp_update(void);
+enum s5p_vp_field __s5p_vp_get_field_id(void);
+bool __s5p_vp_get_update_status(void);
+void __s5p_vp_init_field_id(enum s5p_vp_field mode);
+void __s5p_vp_init_op_mode(bool line_skip, enum s5p_vp_mem_mode mem_mode,
+ enum s5p_vp_chroma_expansion chroma_exp,
+ enum s5p_vp_filed_id_toggle toggle_id);
+void __s5p_vp_init_pixel_rate_control(enum s5p_vp_pxl_rate rate);
+enum s5p_tv_vp_err __s5p_vp_init_layer(u32 top_y_addr, u32 top_c_addr,
+ u32 bottom_y_addr, u32 bottom_c_addr,
+ enum s5p_endian_type src_img_endian,
+ u32 img_width, u32 img_height, u32 src_off_x, u32 src_x_fract_step,
+ u32 src_off_y, u32 src_width, u32 src_height, u32 dst_off_x,
+ u32 dst_off_y, u32 dst_width, u32 dst_height, bool ipc_2d);
+enum s5p_tv_vp_err __s5p_vp_init_layer_def_poly_filter_coef(u32 top_y_addr,
+ u32 top_c_addr, u32 bottom_y_addr, u32 bottom_c_addr,
+ enum s5p_endian_type src_img_endian, u32 img_width, u32 img_height,
+ u32 src_off_x, u32 src_x_fract_step, u32 src_off_y, u32 src_width,
+ u32 src_height, u32 dst_off_x, u32 dst_off_y, u32 dst_width,
+ u32 dst_height, bool ipc_2d);
+enum s5p_tv_vp_err __s5p_vp_init_poly_filter_coef(
+ enum s5p_vp_poly_coeff poly_coeff,
+ signed char ch0, signed char ch1, signed char ch2, signed char ch3);
+void __s5p_vp_init_bypass_post_process(bool bypass);
+enum s5p_tv_vp_err __s5p_vp_init_csc_coef(enum s5p_vp_csc_coeff csc_coeff,
+ u32 coeff);
+void __s5p_vp_init_saturation(u32 sat);
+void __s5p_vp_init_sharpness(u32 th_h_noise,
+ enum s5p_vp_sharpness_control sharpness);
+enum s5p_tv_vp_err __s5p_vp_init_brightness_contrast_control(
+ enum s5p_vp_line_eq eq_num,
+ u32 intc, u32 slope);
+void __s5p_vp_init_brightness(bool brightness);
+void __s5p_vp_init_contrast(u8 contrast);
+void __s5p_vp_init_brightness_offset(u32 offset);
+void __s5p_vp_init_csc_control(bool suy_offset_en, bool csc_en);
+enum s5p_tv_vp_err __s5p_vp_init_csc_coef_default(
+ enum s5p_vp_csc_type csc_type);
+enum s5p_tv_vp_err __s5p_vp_start(void);
+enum s5p_tv_vp_err __s5p_vp_stop(void);
+void __s5p_vp_sw_reset(void);
+
+#ifdef CONFIG_CPU_S5PC100
+void __s5p_tv_clk_init_hpll(u32 lock_time, u32 mdiv, u32 pdiv, u32 sdiv);
+#endif
+
+#ifdef CONFIG_CPU_S5PV210
+int __s5p_tv_clk_change_internal(void);
+#endif
+
+void __s5p_tv_clk_hpll_onoff(bool en);
+#ifdef CONFIG_CPU_S5PC100
+enum s5p_tv_clk_err __s5p_tv_clk_init_href(
+ enum s5p_tv_clk_hpll_ref hpll_ref);
+enum s5p_tv_clk_err __s5p_tv_clk_init_mout_hpll(
+ enum s5p_tv_clk_mout_hpll mout_hpll);
+enum s5p_tv_clk_err __s5p_tv_clk_init_video_mixer(
+ enum s5p_tv_clk_vmiexr_srcclk src_clk);
+#endif
+void __s5p_tv_clk_init_hdmi_ratio(u32 clk_div);
+void __s5p_tv_clk_set_vp_clk_onoff(bool clk_on);
+void __s5p_tv_clk_set_vmixer_hclk_onoff(bool clk_on);
+void __s5p_tv_clk_set_vmixer_sclk_onoff(bool clk_on);
+void __s5p_tv_clk_set_sdout_hclk_onoff(bool clk_on);
+void __s5p_tv_clk_set_sdout_sclk_onoff(bool clk_on);
+void __s5p_tv_clk_set_hdmi_hclk_onoff(bool clk_on);
+void __s5p_tv_clk_set_hdmi_sclk_onoff(bool clk_on);
+void __s5p_tv_clk_set_hdmi_i2c_clk_onoff(bool clk_on);
+void __s5p_tv_clk_start(bool vp_hclk_on, bool sdout_hclk_on,
+ bool hdmi_hclk_on);
+void __s5p_tv_clk_stop(void);
+
+void __s5p_tv_power_init_mtc_stable_counter(u32 value);
+void __s5p_tv_powerinitialize_dac_onoff(bool on);
+void __s5p_tv_powerset_dac_onoff(bool on);
+bool __s5p_tv_power_get_power_status(void);
+bool __s5p_tv_power_get_dac_power_status(void);
+void __s5p_tv_poweron(void);
+void __s5p_tv_poweroff(void);
+
+extern struct s5p_tv_status s5ptv_status;
+extern struct s5p_tv_vo s5ptv_overlay[2];
+
+#ifdef CONFIG_CPU_S5PV210
+extern void s5p_hdmi_enable_interrupts(enum s5p_tv_hdmi_interrrupt intr);
+extern void s5p_hdmi_disable_interrupts(enum s5p_tv_hdmi_interrrupt intr);
+extern void s5p_hdmi_clear_pending(enum s5p_tv_hdmi_interrrupt intr);
+extern u8 s5p_hdmi_get_interrupts(void);
+extern int s5p_hdmi_register_isr(hdmi_isr isr, u8 irq_num);
+extern int s5p_hpd_init(void);
+extern u8 s5p_hdmi_get_swhpd_status(void);
+extern u8 s5p_hdmi_get_hpd_status(void);
+extern void s5p_hdmi_swhpd_disable(void);
+extern void s5p_hdmi_hpd_gen(void);
+extern int __init __s5p_hdcp_init(void);
+extern int s5p_tv_clk_gate(bool on);
+#endif
+
+extern int s5ptvfb_init_fbinfo(int id);
+extern int s5ptvfb_map_video_memory(struct fb_info *fb);
+extern int s5ptvfb_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *fb);
+extern int s5ptvfb_set_par(struct fb_info *fb);
+extern int s5ptvfb_draw_logo(struct fb_info *fb);
+extern void s5ptvfb_set_lcd_info(struct s5p_tv_status *ctrl);
+extern int s5ptvfb_display_on(struct s5p_tv_status *ctrl);
+extern int s5p_hpd_get_state(void);
+extern void s5p_handle_cable(void);
+
+#define S5PTVFB_POWER_OFF _IOW('F', 217, u32)
+#define S5PTVFB_POWER_ON _IOW('F', 218, u32)
+#define S5PTVFB_WIN_SET_ADDR _IOW('F', 219, u32)
+#define S5PTVFB_SET_WIN_ON _IOW('F', 220, u32)
+#define S5PTVFB_SET_WIN_OFF _IOW('F', 221, u32)
+
+extern int s5p_tv_clk_gate(bool on);
+extern int s5p_hdcp_is_reset(void);
+extern int tv_phy_power(bool on);
+extern int s5ptvfb_unmap_video_memory(struct fb_info *fb);
+
+extern struct s5p_tv_status s5ptv_status;
+extern bool _s5p_tv_if_set_disp(void);
+extern int s5p_hdcp_encrypt_stop(bool on);
+extern int s5p_hdmi_set_dvi(bool en);
+extern int s5p_hdmi_set_mute(bool en);
+extern int s5p_hdmi_get_mute(void);
+extern int s5p_hdmi_audio_enable(bool en);
+extern void s5p_hdmi_set_audio(bool en);
+extern void s5p_hdmi_mute_en(bool en);
+extern bool __s5p_start_hdcp(void);
+extern bool __s5p_stop_hdcp(void);
+
+#if defined(CONFIG_MACH_P1)
+extern struct i2c_driver SII9234_i2c_driver;
+extern struct i2c_driver SII9234A_i2c_driver;
+extern struct i2c_driver SII9234B_i2c_driver;
+extern struct i2c_driver SII9234C_i2c_driver;
+#endif
+
diff --git a/drivers/media/video/samsung/tv20/s5p_tv_base.c b/drivers/media/video/samsung/tv20/s5p_tv_base.c
new file mode 100644
index 0000000..89543d2
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/s5p_tv_base.c
@@ -0,0 +1,1431 @@
+/* linux/drivers/media/video/samsung/tv20/s5p_tv_base.c
+ *
+ * Entry file for Samsung TVOut driver
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/miscdevice.h>
+#include <linux/platform_device.h>
+#include <linux/workqueue.h>
+#include <linux/wait.h>
+#include <linux/ioctl.h>
+#include <linux/device.h>
+#include <linux/clk.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <linux/regulator/consumer.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <mach/map.h>
+
+#include <mach/gpio.h>
+#include <plat/gpio-cfg.h>
+#include <mach/regs-gpio.h>
+/*#include <mach/max8998_function.h>*/
+#include <linux/earlysuspend.h>
+#ifdef CONFIG_CPU_FREQ_S5PV210
+#include <mach/cpu-freq-v210.h>
+#endif /* CONFIG_CPU_FREQ_S5PV210 */
+
+#ifdef CONFIG_S5PV210_PM_LEGACY
+#include <mach/pd.h>
+#endif
+
+#include "s5p_tv.h"
+
+#ifdef COFIG_TVOUT_DBG
+#define S5P_TV_BASE_DEBUG 1
+#endif
+
+#ifdef S5P_TV_BASE_DEBUG
+#define BASEPRINTK(fmt, args...) \
+ printk(KERN_INFO "[TVBASE] %s: " fmt, __func__ , ## args)
+#else
+#define BASEPRINTK(fmt, args...)
+#endif
+
+#ifdef CONFIG_CPU_S5PV210
+#define TVOUT_CLK_INIT(dev, clk, name)
+#else
+#define TVOUT_CLK_INIT(dev, clk, name) \
+ do { \
+ clk = clk_get(dev, name); \
+ if (clk == NULL) { \
+ printk(KERN_ERR \
+ "failed to find %s clock source\n", name); \
+ return -ENOENT; \
+ } \
+ clk_enable(clk) \
+ } while (0);
+#endif
+
+#define TVOUT_IRQ_INIT(x, ret, dev, num, jump, ftn, m_name) \
+ do { \
+ x = platform_get_irq(dev, num); \
+ if (x < 0) { \
+ printk(KERN_ERR \
+ "failed to get %s irq resource\n", m_name); \
+ ret = -ENOENT; \
+ goto jump; \
+ } \
+ ret = request_irq(x, ftn, IRQF_DISABLED, \
+ dev->name, dev); \
+ if (ret != 0) { \
+ printk(KERN_ERR \
+ "failed to install %s irq (%d)\n", m_name, ret);\
+ goto jump; \
+ } \
+ } while (0);
+
+
+#ifdef CONFIG_CPU_S5PC100
+#define I2C_BASE
+#endif
+
+static struct mutex *mutex_for_fo;
+
+
+struct s5p_tv_status s5ptv_status;
+struct s5p_tv_vo s5ptv_overlay[2];
+
+#ifdef I2C_BASE
+static struct mutex *mutex_for_i2c;
+static struct work_struct ws_hpd;
+spinlock_t slock_hpd;
+
+static struct i2c_driver hdcp_i2c_driver;
+static bool hdcp_i2c_drv_state;
+
+const static u16 ignore[] = { I2C_CLIENT_END };
+const static u16 normal_addr[] = {(S5P_HDCP_I2C_ADDR >> 1), I2C_CLIENT_END };
+const static u16 *forces[] = { NULL };
+
+static struct i2c_client_address_data addr_data = {
+ .normal_i2c = normal_addr,
+ .probe = ignore,
+ .ignore = ignore,
+ .forces = forces,
+};
+
+/*
+ * i2c client drv. - register client drv
+ */
+static int hdcp_i2c_attach(struct i2c_adapter *adap, int addr, int kind)
+{
+
+ struct i2c_client *c;
+
+ c = kzalloc(sizeof(*c), GFP_KERNEL);
+
+ if (!c)
+ return -ENOMEM;
+
+ strcpy(c->name, "s5p_ddc_client");
+
+ c->addr = addr;
+
+ c->adapter = adap;
+
+ c->driver = &hdcp_i2c_driver;
+
+ s5ptv_status.hdcp_i2c_client = c;
+
+ dev_info(&adap->dev, "s5p_ddc_client attached "
+ "into s5p_ddc_port successfully\n");
+
+ return i2c_attach_client(c);
+}
+
+static int hdcp_i2c_attach_adapter(struct i2c_adapter *adap)
+{
+ int ret = 0;
+
+ ret = i2c_probe(adap, &addr_data, hdcp_i2c_attach);
+
+ if (ret) {
+ dev_err(&adap->dev,
+ "failed to attach s5p_hdcp_port driver\n");
+ ret = -ENODEV;
+ }
+
+ return ret;
+}
+
+static int hdcp_i2c_detach(struct i2c_client *client)
+{
+ dev_info(&client->adapter->dev, "s5p_ddc_client detached "
+ "from s5p_ddc_port successfully\n");
+
+ i2c_detach_client(client);
+
+ return 0;
+}
+
+static struct i2c_driver hdcp_i2c_driver = {
+ .driver = {
+ .name = "s5p_ddc_port",
+ },
+ .id = I2C_DRIVERID_S5P_HDCP,
+ .attach_adapter = hdcp_i2c_attach_adapter,
+ .detach_client = hdcp_i2c_detach,
+};
+
+static void set_ddc_port(void)
+{
+ mutex_lock(mutex_for_i2c);
+
+ if (s5ptv_status.hpd_status) {
+
+ if (!hdcp_i2c_drv_state)
+ /* cable : plugged, drv : unregistered */
+ if (i2c_add_driver(&hdcp_i2c_driver))
+ printk(KERN_ERR "HDCP port add failed\n");
+
+ /* changed drv. status */
+ hdcp_i2c_drv_state = true;
+
+
+ /* cable inserted -> removed */
+ __s5p_set_hpd_detection(true, s5ptv_status.hdcp_en,
+ s5ptv_status.hdcp_i2c_client);
+
+ } else {
+
+ if (hdcp_i2c_drv_state)
+ /* cable : unplugged, drv : registered */
+ i2c_del_driver(&hdcp_i2c_driver);
+
+ /* changed drv. status */
+ hdcp_i2c_drv_state = false;
+
+ /* cable removed -> inserted */
+ __s5p_set_hpd_detection(false, s5ptv_status.hdcp_en,
+ s5ptv_status.hdcp_i2c_client);
+ printk(KERN_INFO "%s cable removed\n", __func__);
+ }
+
+ mutex_unlock(mutex_for_i2c);
+}
+#endif
+
+#ifdef CONFIG_CPU_S5PC100
+static irqreturn_t __s5p_hpd_irq(int irq, void *dev_id)
+{
+
+ spin_lock_irq(&slock_hpd);
+
+ s5ptv_status.hpd_status = gpio_get_value(S5PC1XX_GPH0(5))
+ ? false : true;
+
+ if (s5ptv_status.hpd_status)
+ set_irq_type(IRQ_EINT5, IRQ_TYPE_EDGE_RISING);
+ else
+ set_irq_type(IRQ_EINT5, IRQ_TYPE_EDGE_FALLING);
+
+
+ if (s5ptv_status.hdcp_en)
+ schedule_work(&ws_hpd);
+
+ spin_unlock_irq(&slock_hpd);
+
+ BASEPRINTK("hpd_status = %d\n", s5ptv_status.hpd_status);
+
+ return IRQ_HANDLED;
+}
+#endif
+
+#ifdef CONFIG_CPU_S5PV210
+int tv_phy_power(bool on)
+{
+ if (on) {
+ __s5p_tv_poweron();
+ /* on */
+ clk_enable(s5ptv_status.i2c_phy_clk);
+ __s5p_hdmi_phy_power(true);
+
+ } else {
+ /*
+ * for preventing hdmi hang up when restart
+ * switch to internal clk - SCLK_DAC, SCLK_PIXEL
+ */
+ clk_set_parent(s5ptv_status.sclk_mixer,
+ s5ptv_status.sclk_dac);
+ clk_set_parent(s5ptv_status.sclk_hdmi,
+ s5ptv_status.sclk_pixel);
+
+ __s5p_hdmi_phy_power(false);
+ clk_disable(s5ptv_status.i2c_phy_clk);
+ __s5p_tv_poweroff();
+ }
+
+ return 0;
+}
+
+
+int s5p_tv_clk_gate(bool on)
+{
+ if (on) {
+#ifdef CONFIG_S5PV210_PM_LEGACY
+ if (s5pv210_pd_enable("vp_pd") < 0) {
+ printk(KERN_ERR "[Error]The power is not on for VP\n");
+ goto err_pm;
+ }
+#endif
+ clk_enable(s5ptv_status.vp_clk);
+
+#ifdef CONFIG_S5PV210_PM_LEGACY
+ if (s5pv210_pd_enable("mixer_pd") < 0) {
+ printk(KERN_ERR "[Error]The power is not on for mixer\n");
+ goto err_pm;
+ }
+#endif
+ clk_enable(s5ptv_status.mixer_clk);
+
+#ifdef CONFIG_S5PV210_PM_LEGACY
+ if (s5pv210_pd_enable("tv_enc_pd") < 0) {
+ printk(KERN_ERR "[Error]The power is not on for TV ENC\n");
+ goto err_pm;
+ }
+#endif
+ clk_enable(s5ptv_status.tvenc_clk);
+
+#ifdef CONFIG_S5PV210_PM_LEGACY
+ if (s5pv210_pd_enable("hdmi_pd") < 0) {
+ printk(KERN_ERR "[Error]The power is not on for HDMI\n");
+ goto err_pm;
+ }
+#endif
+ clk_enable(s5ptv_status.hdmi_clk);
+ } else {
+
+ /* off */
+ clk_disable(s5ptv_status.vp_clk);
+#ifdef CONFIG_S5PV210_PM_LEGACY
+ if (s5pv210_pd_disable("vp_pd") < 0) {
+ printk(KERN_ERR "[Error]The power is not off for VP\n");
+ goto err_pm;
+ }
+#endif
+ clk_disable(s5ptv_status.mixer_clk);
+#ifdef CONFIG_S5PV210_PM_LEGACY
+ if (0 != s5pv210_pd_disable("mixer_pd")) {
+ printk(KERN_ERR "[Error]The power is not off for mixer\n");
+ goto err_pm;
+ }
+#endif
+ clk_disable(s5ptv_status.tvenc_clk);
+#ifdef CONFIG_S5PV210_PM_LEGACY
+ if (s5pv210_pd_disable("tv_enc_pd") < 0) {
+ printk(KERN_ERR "[Error]The power is not off for TV ENC\n");
+ goto err_pm;
+ }
+#endif
+ clk_disable(s5ptv_status.hdmi_clk);
+#ifdef CONFIG_S5PV210_PM_LEGACY
+ if (s5pv210_pd_disable("hdmi_pd") < 0) {
+ printk(KERN_ERR "[Error]The power is not off for HDMI\n");
+ goto err_pm;
+ }
+#endif
+ }
+
+ return 0;
+#ifdef CONFIG_S5PV210_PM_LEGACY
+err_pm:
+ return -1;
+#endif
+}
+EXPORT_SYMBOL(s5p_tv_clk_gate);
+
+#define TV_CLK_GET_WITH_ERR_CHECK(clk, pdev, clk_name) \
+ do { \
+ clk = clk_get(&pdev->dev, clk_name); \
+ if (IS_ERR(clk)) { \
+ printk(KERN_ERR \
+ "failed to find clock \"%s\"\n", clk_name); \
+ return ENOENT; \
+ } \
+ } while (0);
+
+static int __devinit tv_clk_get(struct platform_device *pdev,
+ struct s5p_tv_status *ctrl)
+{
+ struct clk *ext_xtal_clk,
+ *mout_vpll_src,
+ *fout_vpll,
+ *mout_vpll;
+
+ TV_CLK_GET_WITH_ERR_CHECK(ctrl->tvenc_clk, pdev, "tvenc");
+ TV_CLK_GET_WITH_ERR_CHECK(ctrl->vp_clk, pdev, "vp");
+ TV_CLK_GET_WITH_ERR_CHECK(ctrl->mixer_clk, pdev, "mixer");
+ TV_CLK_GET_WITH_ERR_CHECK(ctrl->hdmi_clk, pdev, "hdmi");
+ TV_CLK_GET_WITH_ERR_CHECK(ctrl->i2c_phy_clk, pdev, "i2c-hdmiphy");
+
+ TV_CLK_GET_WITH_ERR_CHECK(ctrl->sclk_dac, pdev, "sclk_dac");
+ TV_CLK_GET_WITH_ERR_CHECK(ctrl->sclk_mixer, pdev, "sclk_mixer");
+ TV_CLK_GET_WITH_ERR_CHECK(ctrl->sclk_hdmi, pdev, "sclk_hdmi");
+
+ TV_CLK_GET_WITH_ERR_CHECK(ctrl->sclk_pixel, pdev, "sclk_pixel");
+ TV_CLK_GET_WITH_ERR_CHECK(ctrl->sclk_hdmiphy, pdev, "sclk_hdmiphy");
+
+ TV_CLK_GET_WITH_ERR_CHECK(ext_xtal_clk, pdev, "ext_xtal");
+ TV_CLK_GET_WITH_ERR_CHECK(mout_vpll_src, pdev, "mout_vpll_src");
+ TV_CLK_GET_WITH_ERR_CHECK(fout_vpll, pdev, "fout_vpll");
+ TV_CLK_GET_WITH_ERR_CHECK(mout_vpll, pdev, "mout_vpll");
+
+ clk_set_parent(mout_vpll_src, ext_xtal_clk);
+ clk_set_parent(mout_vpll, fout_vpll);
+
+ /* sclk_dac's parent is fixed as mout_vpll */
+ clk_set_parent(ctrl->sclk_dac, mout_vpll);
+
+ clk_set_rate(fout_vpll, 54000000);
+ clk_set_rate(ctrl->sclk_pixel, 54000000);
+
+ clk_enable(ctrl->sclk_dac);
+ clk_enable(ctrl->sclk_mixer);
+ clk_enable(ctrl->sclk_hdmi);
+
+ clk_enable(mout_vpll_src);
+ clk_enable(fout_vpll);
+ clk_enable(mout_vpll);
+
+ clk_put(ext_xtal_clk);
+ clk_put(mout_vpll_src);
+ clk_put(fout_vpll);
+ clk_put(mout_vpll);
+
+ return 0;
+}
+#else
+#define s5p_tv_clk_gate NULL
+#define tv_phy_power NULL
+#define tv_clk_get NULL
+#endif
+
+/*
+ * ftn for irq
+ */
+static irqreturn_t s5p_tvenc_irq(int irq, void *dev_id)
+{
+ return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_TV_FB
+static int s5p_tv_open(struct file *file)
+{
+ return 0;
+}
+
+static int s5p_tv_release(struct file *file)
+{
+ s5ptv_status.hdcp_en = false;
+ return 0;
+}
+
+static int s5p_tv_vid_open(struct file *file)
+{
+ int ret = 0;
+
+ mutex_lock(mutex_for_fo);
+
+ if (s5ptv_status.vp_layer_enable) {
+ printk(KERN_ERR "video layer. already used !!\n");
+ ret = -EBUSY;
+ }
+
+ mutex_unlock(mutex_for_fo);
+ return ret;
+}
+
+static int s5p_tv_vid_release(struct file *file)
+{
+ s5ptv_status.vp_layer_enable = false;
+
+ _s5p_vlayer_stop();
+
+ return 0;
+}
+#else
+
+/*
+ * ftn for video
+ */
+static int s5p_tv_v_open(struct file *file)
+{
+ int ret = 0;
+
+ printk(KERN_INFO "%s", __func__);
+ mutex_lock(mutex_for_fo);
+
+ if (s5ptv_status.tvout_output_enable) {
+ BASEPRINTK("tvout drv. already used !!\n");
+ ret = -EBUSY;
+ goto drv_used;
+ }
+
+ s5p_tv_clk_gate(true);
+ tv_phy_power(true);
+
+#ifdef CONFIG_CPU_S5PV210
+#ifdef CONFIG_PM
+ if ((s5ptv_status.hpd_status) && !(s5ptv_status.suspend_status)) {
+ BASEPRINTK("tv is turned on\n");
+#endif
+#ifdef CONFIG_CPU_FREQ_S5PV210
+ if ((s5ptv_status.hpd_status))
+ s5pv210_set_cpufreq_level(RESTRICT_TABLE);
+#endif /* CONFIG_CPU_FREQ_S5PV210 */
+// s5p_tv_clk_gate(true);
+/*
+ if ((s5ptv_status.tvout_param.out_mode == TVOUT_OUTPUT_HDMI)\
+ || \
+ (s5ptv_status.tvout_param.out_mode == TVOUT_OUTPUT_HDMI_RGB))
+*/
+// tv_phy_power(true);
+#ifdef CONFIG_PM
+ } else
+ BASEPRINTK("tv is off\n");
+#endif
+#endif
+ _s5p_tv_if_init_param();
+
+ s5p_tv_v4l2_init_param();
+
+ mutex_unlock(mutex_for_fo);
+
+#ifdef I2C_BASE
+ mutex_lock(mutex_for_i2c);
+ /* for ddc(hdcp port) */
+ if (s5ptv_status.hpd_status) {
+ if (i2c_add_driver(&hdcp_i2c_driver))
+ BASEPRINTK("HDCP port add failed\n");
+ hdcp_i2c_drv_state = true;
+ } else
+ hdcp_i2c_drv_state = false;
+
+ mutex_unlock(mutex_for_i2c);
+ /* for i2c probing */
+ udelay(100);
+#endif
+
+ return 0;
+
+drv_used:
+ mutex_unlock(mutex_for_fo);
+ return ret;
+}
+
+int s5p_tv_v_read(struct file *filp, char *buf, size_t count,
+ loff_t *f_pos)
+{
+ return 0;
+}
+
+int s5p_tv_v_write(struct file *filp, const char *buf, size_t
+ count, loff_t *f_pos)
+{
+ return 0;
+}
+
+int s5p_tv_v_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+ return 0;
+}
+
+int s5p_tv_v_release(struct file *filp)
+{
+ printk(KERN_INFO "%s", __func__);
+
+#if defined(CONFIG_CPU_S5PV210) && defined(CONFIG_PM)
+ if ((s5ptv_status.hpd_status) && !(s5ptv_status.suspend_status)) {
+#endif
+ if (s5ptv_status.vp_layer_enable)
+ _s5p_vlayer_stop();
+ if (s5ptv_status.tvout_output_enable)
+ _s5p_tv_if_stop();
+#if defined(CONFIG_CPU_S5PV210) && defined(CONFIG_PM)
+ } else
+ s5ptv_status.vp_layer_enable = false;
+#endif
+ s5ptv_status.hdcp_en = false;
+
+ s5ptv_status.tvout_output_enable = false;
+
+ /*
+ * drv. release
+ * - just check drv. state reg. or not.
+ */
+#ifdef I2C_BASE
+ mutex_lock(mutex_for_i2c);
+
+ if (hdcp_i2c_drv_state) {
+ i2c_del_driver(&hdcp_i2c_driver);
+ hdcp_i2c_drv_state = false;
+ }
+
+ mutex_unlock(mutex_for_i2c);
+#endif
+
+#ifdef CONFIG_CPU_S5PV210
+#ifdef CONFIG_PM
+ if ((s5ptv_status.hpd_status) && !(s5ptv_status.suspend_status)) {
+#endif
+// s5p_tv_clk_gate(false);
+/* if (s5ptv_status.tvout_param.out_mode == TVOUT_OUTPUT_HDMI || \
+ s5ptv_status.tvout_param.out_mode == TVOUT_OUTPUT_HDMI_RGB)
+*/
+// tv_phy_power(false);
+#ifdef CONFIG_CPU_FREQ_S5PV210
+ if (s5ptv_status.hpd_status)
+ s5pv210_set_cpufreq_level(NORMAL_TABLE);
+#endif /* CONFIG_CPU_FREQ_S5PV210 */
+
+#ifdef CONFIG_PM
+ }
+#endif
+#endif
+
+ s5p_tv_clk_gate(false);
+ tv_phy_power(false);
+
+ return 0;
+}
+
+static int vo_open(int layer, struct file *file)
+{
+ int ret = 0;
+
+ mutex_lock(mutex_for_fo);
+
+ /* check tvout path available!! */
+ if (!s5ptv_status.tvout_output_enable) {
+ BASEPRINTK("check tvout start !!\n");
+ ret = -EACCES;
+ goto resource_busy;
+ }
+
+ if (s5ptv_status.grp_layer_enable[layer]) {
+ BASEPRINTK("grp %d layer is busy!!\n", layer);
+ ret = -EBUSY;
+ goto resource_busy;
+ }
+
+ /* set layer info.!! */
+ s5ptv_overlay[layer].index = layer;
+
+ /* set file private data.!! */
+ file->private_data = &s5ptv_overlay[layer];
+
+ mutex_unlock(mutex_for_fo);
+
+ return 0;
+
+resource_busy:
+ mutex_unlock(mutex_for_fo);
+
+ return ret;
+}
+
+int vo_release(int layer, struct file *filp)
+{
+ _s5p_grp_stop(layer);
+
+ return 0;
+}
+
+/* modified for 2.6.29 v4l2-dev.c */
+static int s5p_tv_vo0_open(struct file *file)
+{
+ vo_open(0, file);
+ return 0;
+}
+
+static int s5p_tv_vo0_release(struct file *file)
+{
+ vo_release(0, file);
+ return 0;
+}
+
+static int s5p_tv_vo1_open(struct file *file)
+{
+ vo_open(1, file);
+ return 0;
+}
+
+static int s5p_tv_vo1_release(struct file *file)
+{
+ vo_release(1, file);
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_TV_FB
+static int s5ptvfb_alloc_framebuffer(void)
+{
+ int ret;
+
+ /* alloc for each framebuffer */
+ s5ptv_status.fb = framebuffer_alloc(sizeof(struct s5ptvfb_window),
+ s5ptv_status.dev_fb);
+ if (!s5ptv_status.fb) {
+ dev_err(s5ptv_status.dev_fb, "not enough memory\n");
+ ret = -ENOMEM;
+ goto err_alloc_fb;
+ }
+
+ ret = s5ptvfb_init_fbinfo(5);
+ if (ret) {
+ dev_err(s5ptv_status.dev_fb,
+ "failed to allocate memory for fb for tv\n");
+ ret = -ENOMEM;
+ goto err_alloc_fb;
+ }
+#ifndef CONFIG_USER_ALLOC_TVOUT
+ if (s5ptvfb_map_video_memory(s5ptv_status.fb)) {
+ dev_err(s5ptv_status.dev_fb,
+ "failed to map video memory "
+ "for default window \n");
+ ret = -ENOMEM;
+ goto err_alloc_fb;
+ }
+#endif
+ return 0;
+
+err_alloc_fb:
+ if (s5ptv_status.fb)
+ framebuffer_release(s5ptv_status.fb);
+
+ kfree(s5ptv_status.fb);
+
+ return ret;
+}
+
+int s5ptvfb_free_framebuffer(void)
+{
+#ifndef CONFIG_USER_ALLOC_TVOUT
+ if (s5ptv_status.fb)
+ s5ptvfb_unmap_video_memory(s5ptv_status.fb);
+#endif
+
+ if (s5ptv_status.fb)
+ framebuffer_release(s5ptv_status.fb);
+
+ return 0;
+}
+
+int s5ptvfb_register_framebuffer(void)
+{
+ int ret;
+
+ ret = register_framebuffer(s5ptv_status.fb);
+ if (ret) {
+ dev_err(s5ptv_status.dev_fb, "failed to register "
+ "framebuffer device\n");
+ return -EINVAL;
+ }
+#ifndef CONFIG_FRAMEBUFFER_CONSOLE
+#ifndef CONFIG_USER_ALLOC_TVOUT
+ s5ptvfb_check_var(&s5ptv_status.fb->var, s5ptv_status.fb);
+ s5ptvfb_set_par(s5ptv_status.fb);
+ s5ptvfb_draw_logo(s5ptv_status.fb);
+#endif
+#endif
+
+ return 0;
+}
+#endif
+
+/*
+ * struct for video
+ */
+#ifdef CONFIG_TV_FB
+static struct v4l2_file_operations s5p_tv_fops = {
+ .owner = THIS_MODULE,
+ .open = s5p_tv_open,
+ .ioctl = s5p_tv_ioctl,
+ .release = s5p_tv_release
+};
+static struct v4l2_file_operations s5p_tv_vid_fops = {
+ .owner = THIS_MODULE,
+ .open = s5p_tv_vid_open,
+ .ioctl = s5p_tv_vid_ioctl,
+ .release = s5p_tv_vid_release
+};
+ #else
+static struct v4l2_file_operations s5p_tv_v_fops = {
+ .owner = THIS_MODULE,
+ .open = s5p_tv_v_open,
+ .read = s5p_tv_v_read,
+ .write = s5p_tv_v_write,
+ .ioctl = s5p_tv_v_ioctl,
+ .mmap = s5p_tv_v_mmap,
+ .release = s5p_tv_v_release
+};
+
+/*
+ * struct for graphic0
+ */
+static struct v4l2_file_operations s5p_tv_vo0_fops = {
+ .owner = THIS_MODULE,
+ .open = s5p_tv_vo0_open,
+ .ioctl = s5p_tv_vo_ioctl,
+ .release = s5p_tv_vo0_release
+};
+
+/*
+ * struct for graphic1
+ */
+static struct v4l2_file_operations s5p_tv_vo1_fops = {
+ .owner = THIS_MODULE,
+ .open = s5p_tv_vo1_open,
+ .ioctl = s5p_tv_vo_ioctl,
+ .release = s5p_tv_vo1_release
+};
+#endif
+
+void s5p_tv_vdev_release(struct video_device *vdev)
+{
+ kfree(vdev);
+}
+
+struct video_device s5p_tvout[] = {
+
+#ifdef CONFIG_TV_FB
+ [0] = {
+ .name = "S5PC1xx TVOUT ctrl",
+ .fops = &s5p_tv_fops,
+ .ioctl_ops = &s5p_tv_v4l2_ops,
+ .release = s5p_tv_vdev_release,
+ .minor = TVOUT_MINOR_TVOUT,
+ .tvnorms = V4L2_STD_ALL_HD,
+ },
+ [1] = {
+ .name = "S5PC1xx TVOUT for Video",
+ .fops = &s5p_tv_vid_fops,
+ .ioctl_ops = &s5p_tv_v4l2_vid_ops,
+ .release = s5p_tv_vdev_release,
+ .minor = TVOUT_MINOR_VID,
+ .tvnorms = V4L2_STD_ALL_HD,
+ },
+#else
+ [0] = {
+ .name = "S5PC1xx TVOUT Video",
+ .fops = &s5p_tv_v_fops,
+ .ioctl_ops = &s5p_tv_v4l2_v_ops,
+ .release = s5p_tv_vdev_release,
+ .minor = TVOUT_MINOR_VIDEO,
+ .tvnorms = V4L2_STD_ALL_HD,
+ },
+ [1] = {
+ .name = "S5PC1xx TVOUT Overlay0",
+ .fops = &s5p_tv_vo0_fops,
+ .ioctl_ops = &s5p_tv_v4l2_vo_ops,
+ .release = s5p_tv_vdev_release,
+ .minor = TVOUT_MINOR_GRP0,
+ .tvnorms = V4L2_STD_ALL_HD,
+ },
+ [2] = {
+ .name = "S5PC1xx TVOUT Overlay1",
+ .fops = &s5p_tv_vo1_fops,
+ .ioctl_ops = &s5p_tv_v4l2_vo_ops,
+ .release = s5p_tv_vdev_release,
+ .minor = TVOUT_MINOR_GRP1,
+ .tvnorms = V4L2_STD_ALL_HD,
+ },
+#endif
+};
+
+void s5p_handle_cable(void)
+{
+ char env_buf[120];
+ char *envp[2];
+ int env_offset = 0;
+
+ printk(KERN_INFO "%s....start", __func__);
+
+ if ((s5ptv_status.tvout_param.out_mode != TVOUT_OUTPUT_HDMI) && \
+ (s5ptv_status.tvout_param.out_mode != TVOUT_OUTPUT_HDMI_RGB) && \
+ (s5ptv_status.tvout_param.out_mode != TVOUT_OUTPUT_DVI))
+ return;
+
+ bool previous_hpd_status = s5ptv_status.hpd_status;
+#ifdef CONFIG_HDMI_HPD
+ s5ptv_status.hpd_status = s5p_hpd_get_state();
+#else
+ return;
+#endif
+
+ memset(env_buf, 0, sizeof(env_buf));
+
+ if (previous_hpd_status == s5ptv_status.hpd_status) {
+ BASEPRINTK("same hpd_status value: %d\n", previous_hpd_status);
+ return;
+ }
+
+ if (s5ptv_status.hpd_status) {
+ BASEPRINTK("\n hdmi cable is connected \n");
+
+ if (s5ptv_status.suspend_status)
+ return;
+
+#ifdef CONFIG_CPU_FREQ_S5PV210
+ s5pv210_set_cpufreq_level(RESTRICT_TABLE);
+#endif /* CONFIG_CPU_FREQ_S5PV210 */
+
+#ifdef CONFIG_PM
+ s5p_tv_clk_gate(true);
+/*
+ if ((s5ptv_status.tvout_param.out_mode == TVOUT_OUTPUT_HDMI)\
+ || (s5ptv_status.tvout_param.out_mode == TVOUT_OUTPUT_HDMI_RGB))
+*/
+ tv_phy_power(true);
+#endif
+ /* tv on */
+ if (s5ptv_status.tvout_output_enable)
+ _s5p_tv_if_start();
+
+ /* video layer start */
+ if (s5ptv_status.vp_layer_enable)
+ _s5p_vlayer_start();
+
+ /* grp0 layer start */
+ if (s5ptv_status.grp_layer_enable[0])
+ _s5p_grp_start(VM_GPR0_LAYER);
+
+ /* grp1 layer start */
+ if (s5ptv_status.grp_layer_enable[1])
+ _s5p_grp_start(VM_GPR1_LAYER);
+
+ sprintf(env_buf, "HDMI_STATE=online");
+ envp[env_offset++] = env_buf;
+ envp[env_offset] = NULL;
+ kobject_uevent_env(&(s5p_tvout[0].dev.kobj), KOBJ_CHANGE, envp);
+
+ } else {
+ BASEPRINTK("\n hdmi cable is disconnected \n");
+
+ if (s5ptv_status.suspend_status)
+ return;
+
+ if (s5ptv_status.vp_layer_enable) {
+ _s5p_vlayer_stop();
+ s5ptv_status.vp_layer_enable = true;
+
+ }
+
+ /* grp0 layer stop */
+ if (s5ptv_status.grp_layer_enable[0]) {
+ _s5p_grp_stop(VM_GPR0_LAYER);
+ s5ptv_status.grp_layer_enable[VM_GPR0_LAYER] = true;
+ }
+
+ /* grp1 layer stop */
+ if (s5ptv_status.grp_layer_enable[1]) {
+ _s5p_grp_stop(VM_GPR1_LAYER);
+ s5ptv_status.grp_layer_enable[VM_GPR0_LAYER] = true;
+ }
+
+ /* tv off */
+ if (s5ptv_status.tvout_output_enable) {
+ _s5p_tv_if_stop();
+ s5ptv_status.tvout_output_enable = true;
+ s5ptv_status.tvout_param_available = true;
+ }
+
+#ifdef CONFIG_PM
+ /* clk & power off */
+ s5p_tv_clk_gate(false);
+/*
+ if ((s5ptv_status.tvout_param.out_mode == TVOUT_OUTPUT_HDMI) ||\
+ (s5ptv_status.tvout_param.out_mode == TVOUT_OUTPUT_HDMI_RGB))
+*/
+ tv_phy_power(false);
+#endif
+
+ sprintf(env_buf, "HDMI_STATE=offline");
+ envp[env_offset++] = env_buf;
+ envp[env_offset] = NULL;
+ kobject_uevent_env(&(s5p_tvout[0].dev.kobj), KOBJ_CHANGE, envp);
+
+#ifdef CONFIG_CPU_FREQ_S5PV210
+ s5pv210_set_cpufreq_level(NORMAL_TABLE);
+#endif /* CONFIG_CPU_FREQ_S5PV210 */
+ }
+}
+
+#define S5P_TVMAX_CTRLS ARRAY_SIZE(s5p_tvout)
+/*
+ * Probe
+ */
+
+static int __devinit s5p_tv_probe(struct platform_device *pdev)
+{
+ int irq_num;
+ int ret;
+ int i, retval;
+
+
+ /* Get csis power domain regulator */
+ s5ptv_status.tv_regulator = regulator_get(&pdev->dev, "pd");
+ if (IS_ERR(s5ptv_status.tv_regulator)) {
+ printk(KERN_ERR "%s %d: failed to get resource %s\n",
+ __func__, __LINE__, "s3c-tv20 pd");
+ return PTR_ERR(s5ptv_status.tv_regulator);
+ }
+
+ s5ptv_status.tv_tvout = regulator_get(NULL, "tvout");
+ if (IS_ERR(s5ptv_status.tv_tvout)) {
+ printk(KERN_ERR "%s %d: failed to get resource %s\n",
+ __func__, __LINE__, "s3c-tv20 tvout");
+ return PTR_ERR(s5ptv_status.tv_tvout);
+ }
+
+#ifdef CONFIG_MACH_P1
+ s5ptv_status.tv_tv = regulator_get(NULL, "tv");
+ if (IS_ERR(s5ptv_status.tv_tv)) {
+ printk(KERN_ERR "%s %d: failed to get resource %s\n",
+ __func__, __LINE__, "s3c-tv20 tv");
+ return PTR_ERR(s5ptv_status.tv_tv);
+ }
+ regulator_enable(s5ptv_status.tv_tv);
+#endif
+ s5ptv_status.dev_fb = &pdev->dev;
+
+ __s5p_sdout_probe(pdev, 0);
+ __s5p_vp_probe(pdev, 1);
+ __s5p_mixer_probe(pdev, 2);
+
+#ifdef CONFIG_CPU_S5PC100
+ __s5p_hdmi_probe(pdev, 3);
+ __s5p_tvclk_probe(pdev, 4);
+#endif
+
+#ifdef CONFIG_CPU_S5PV210
+ tv_clk_get(pdev, &s5ptv_status);
+ s5p_tv_clk_gate(true);
+ __s5p_hdmi_probe(pdev, 3, 4);
+ __s5p_hdcp_init();
+#endif
+#if defined(CONFIG_MACH_P1)
+ retval = i2c_add_driver(&SII9234A_i2c_driver);
+ if (retval != 0)
+ printk(KERN_ERR "[MHL SII9234A] can't add i2c driver");
+
+ retval = i2c_add_driver(&SII9234B_i2c_driver);
+ if (retval != 0)
+ printk(KERN_ERR "[MHL SII9234B] can't add i2c driver");
+
+ retval = i2c_add_driver(&SII9234C_i2c_driver);
+ if (retval != 0)
+ printk(KERN_ERR "[MHL SII9234C] can't add i2c driver");
+
+ retval = i2c_add_driver(&SII9234_i2c_driver);
+ if (retval != 0)
+ printk(KERN_ERR "[MHL SII9234] can't add i2c driver");
+#endif
+
+#ifdef FIX_27M_UNSTABLE_ISSUE /* for smdkc100 pop */
+ writel(0x1, S5PC1XX_GPA0_BASE + 0x56c);
+#endif
+
+#ifdef I2C_BASE
+ /* for dev_dbg err. */
+ spin_lock_init(&slock_hpd);
+
+ /* for bh */
+ INIT_WORK(&ws_hpd, (void *)set_ddc_port);
+#endif
+ /* check EINT init state */
+#ifdef CONFIG_CPU_S5PC100
+ s3c_gpio_cfgpin(S5PC1XX_GPH0(5), S3C_GPIO_SFN(2));
+ s3c_gpio_setpull(S5PC1XX_GPH0(5), S3C_GPIO_PULL_UP);
+
+ s5ptv_status.hpd_status = gpio_get_value(S5PC1XX_GPH0(5)) ? \
+ false : true;
+#endif
+
+#ifdef CONFIG_CPU_S5PV210
+#ifdef CONFIG_HDMI_HPD
+ s5ptv_status.hpd_status = 0;
+#else
+ s5ptv_status.hpd_status = 0;
+#endif
+#endif
+ dev_info(&pdev->dev, "hpd status: cable %s\n",\
+ s5ptv_status.hpd_status ? "inserted":"removed/not connected");
+
+ /* Interrupt */
+ TVOUT_IRQ_INIT(irq_num, ret, pdev, 0, out, __s5p_mixer_irq, "mixer");
+ TVOUT_IRQ_INIT(irq_num, ret, pdev, 1, out_hdmi_irq, __s5p_hdmi_irq , \
+ "hdmi");
+ TVOUT_IRQ_INIT(irq_num, ret, pdev, 2, out_tvenc_irq, s5p_tvenc_irq, \
+ "tvenc");
+
+#ifdef CONFIG_CPU_S5PC100
+ TVOUT_IRQ_INIT(irq_num, ret, pdev, 3, out_hpd_irq, __s5p_hpd_irq, \
+ "hpd");
+ set_irq_type(IRQ_EINT5, IRQ_TYPE_LEVEL_LOW);
+#endif
+ /* v4l2 video device registration */
+ for (i = 0; i < S5P_TVMAX_CTRLS; i++) {
+ s5ptv_status.video_dev[i] = &s5p_tvout[i];
+
+ if (video_register_device(s5ptv_status.video_dev[i],
+ VFL_TYPE_GRABBER, s5p_tvout[i].minor) != 0) {
+
+ dev_err(&pdev->dev,
+ "Couldn't register tvout driver.\n");
+ return 0;
+ }
+ }
+
+#ifdef CONFIG_TV_FB
+ mutex_init(&s5ptv_status.fb_lock);
+
+ /* for default start up */
+ _s5p_tv_if_init_param();
+
+ s5ptv_status.tvout_param.disp_mode = TVOUT_720P_60;
+ s5ptv_status.tvout_param.out_mode = TVOUT_OUTPUT_HDMI;
+
+#ifndef CONFIG_USER_ALLOC_TVOUT
+ s5p_tv_clk_gate(true);
+/*
+ if ((s5ptv_status.tvout_param.out_mode == TVOUT_OUTPUT_HDMI) ||
+ (s5ptv_status.tvout_param.out_mode == TVOUT_OUTPUT_HDMI_RGB))
+*/
+ tv_phy_power(true);
+ _s5p_tv_if_set_disp();
+#endif
+ s5ptvfb_set_lcd_info(&s5ptv_status);
+
+ /* prepare memory */
+ if (s5ptvfb_alloc_framebuffer())
+ goto err_alloc;
+
+ if (s5ptvfb_register_framebuffer())
+ goto err_alloc;
+#ifndef CONFIG_USER_ALLOC_TVOUT
+ s5ptvfb_display_on(&s5ptv_status);
+#endif
+#endif
+ mutex_for_fo = kmalloc(sizeof(struct mutex),
+ GFP_KERNEL);
+
+ if (mutex_for_fo == NULL) {
+ dev_err(&pdev->dev,
+ "failed to create mutex handle\n");
+ goto out;
+ }
+#ifdef I2C_BASE
+ mutex_for_i2c = kmalloc(sizeof(struct mutex),
+ GFP_KERNEL);
+
+ if (mutex_for_i2c == NULL) {
+ dev_err(&pdev->dev,
+ "failed to create mutex handle\n");
+ goto out;
+ }
+ mutex_init(mutex_for_i2c);
+#endif
+ mutex_init(mutex_for_fo);
+
+#ifdef CONFIG_CPU_S5PV210
+ /* added for phy cut off when boot up */
+ clk_enable(s5ptv_status.i2c_phy_clk);
+
+ __s5p_hdmi_phy_power(false);
+ clk_disable(s5ptv_status.i2c_phy_clk);
+
+ s5p_tv_clk_gate(false);
+#endif
+ printk(KERN_INFO "%s TV Probing is done\n", __func__);
+ return 0;
+
+#ifdef CONFIG_TV_FB
+err_alloc:
+#endif
+
+#ifdef CONFIG_CPU_S5PC100
+out_hpd_irq:
+ free_irq(IRQ_TVENC, pdev);
+#endif
+
+out_tvenc_irq:
+ free_irq(IRQ_HDMI, pdev);
+
+out_hdmi_irq:
+ free_irq(IRQ_MIXER, pdev);
+
+out:
+ printk(KERN_ERR "not found (%d). \n", ret);
+
+ return ret;
+}
+
+/*
+ * Remove
+ */
+static int s5p_tv_remove(struct platform_device *pdev)
+{
+ __s5p_hdmi_release(pdev);
+ __s5p_sdout_release(pdev);
+ __s5p_mixer_release(pdev);
+ __s5p_vp_release(pdev);
+#ifdef CONFIG_CPU_S5PC100
+ __s5p_tvclk_release(pdev);
+#endif
+#ifdef I2C_BASE
+ i2c_del_driver(&hdcp_i2c_driver);
+#endif
+#if defined(CONFIG_MACH_P1)
+ i2c_del_driver(&SII9234A_i2c_driver);
+ i2c_del_driver(&SII9234B_i2c_driver);
+ i2c_del_driver(&SII9234C_i2c_driver);
+ i2c_del_driver(&SII9234_i2c_driver);
+#endif
+ clk_disable(s5ptv_status.tvenc_clk);
+ clk_disable(s5ptv_status.vp_clk);
+ clk_disable(s5ptv_status.mixer_clk);
+ clk_disable(s5ptv_status.hdmi_clk);
+ clk_disable(s5ptv_status.sclk_hdmi);
+ clk_disable(s5ptv_status.sclk_mixer);
+ clk_disable(s5ptv_status.sclk_dac);
+
+ clk_put(s5ptv_status.tvenc_clk);
+ clk_put(s5ptv_status.vp_clk);
+ clk_put(s5ptv_status.mixer_clk);
+ clk_put(s5ptv_status.hdmi_clk);
+ clk_put(s5ptv_status.sclk_hdmi);
+ clk_put(s5ptv_status.sclk_mixer);
+ clk_put(s5ptv_status.sclk_dac);
+ clk_put(s5ptv_status.sclk_pixel);
+ clk_put(s5ptv_status.sclk_hdmiphy);
+
+ free_irq(IRQ_MIXER, pdev);
+ free_irq(IRQ_HDMI, pdev);
+ free_irq(IRQ_TVENC, pdev);
+#ifdef CONFIG_CPU_S5PC100
+ free_irq(IRQ_EINT5, pdev);
+#endif
+
+ regulator_disable(s5ptv_status.tv_regulator);
+ regulator_put(s5ptv_status.tv_regulator);
+
+ regulator_disable(s5ptv_status.tv_tvout);
+ regulator_put(s5ptv_status.tv_tvout);
+#ifdef CONFIG_MACH_P1
+ regulator_disable(s5ptv_status.tv_tv);
+ regulator_put(s5ptv_status.tv_tv);
+#endif
+ mutex_destroy(mutex_for_fo);
+#ifdef I2C_BASE
+ mutex_destroy(mutex_for_i2c);
+#endif
+
+ return 0;
+}
+
+
+#ifdef CONFIG_PM
+/*
+ * Suspend
+ */
+void s5p_tv_early_suspend(struct early_suspend *h)
+{
+ BASEPRINTK("%s----------------start \n", __func__);
+
+ mutex_lock(mutex_for_fo);
+ s5ptv_status.suspend_status = true;
+
+ if (!(s5ptv_status.hpd_status)) {
+ printk(KERN_INFO "(hpd_status = %d)++\n", \
+ s5ptv_status.hpd_status);
+ mutex_unlock(mutex_for_fo);
+ return ;
+ } else {
+ /* video layer stop */
+ if (s5ptv_status.vp_layer_enable) {
+ _s5p_vlayer_stop();
+ s5ptv_status.vp_layer_enable = true;
+ }
+
+ /* grp0 layer stop */
+ if (s5ptv_status.grp_layer_enable[0]) {
+ _s5p_grp_stop(VM_GPR0_LAYER);
+ s5ptv_status.grp_layer_enable[VM_GPR0_LAYER] = true;
+ }
+
+ /* grp1 layer stop */
+ if (s5ptv_status.grp_layer_enable[1]) {
+ _s5p_grp_stop(VM_GPR1_LAYER);
+ s5ptv_status.grp_layer_enable[VM_GPR0_LAYER] = true;
+ }
+
+ /* tv off */
+ if (s5ptv_status.tvout_output_enable) {
+ _s5p_tv_if_stop();
+ s5ptv_status.tvout_output_enable = true;
+ s5ptv_status.tvout_param_available = true;
+ }
+
+ /* clk & power off */
+ s5p_tv_clk_gate(false);
+ if ((s5ptv_status.tvout_param.out_mode == TVOUT_OUTPUT_HDMI) ||\
+ (s5ptv_status.tvout_param.out_mode == TVOUT_OUTPUT_HDMI_RGB))
+ tv_phy_power(false);
+
+#ifdef CONFIG_CPU_FREQ_S5PV210
+ s5pv210_set_cpufreq_level(NORMAL_TABLE);
+#endif /* CONFIG_CPU_FREQ_S5PV210 */
+ }
+
+ mutex_unlock(mutex_for_fo);
+ BASEPRINTK("()--\n");
+ return ;
+}
+
+/*
+ * Resume
+ */
+void s5p_tv_late_resume(struct early_suspend *h)
+{
+ BASEPRINTK("%s----------------start \n", __func__);
+
+ mutex_lock(mutex_for_fo);
+ s5ptv_status.suspend_status = false;
+
+ if (!(s5ptv_status.hpd_status)) {
+ printk(KERN_INFO "(hpd_status = %d)++\n", \
+ s5ptv_status.hpd_status);
+ mutex_unlock(mutex_for_fo);
+ return ;
+ } else {
+#ifdef CONFIG_CPU_FREQ_S5PV210
+ s5pv210_set_cpufreq_level(RESTRICT_TABLE);
+#endif /* CONFIG_CPU_FREQ_S5PV210 */
+
+ /* clk & power on */
+ s5p_tv_clk_gate(true);
+ if ((s5ptv_status.tvout_param.out_mode == TVOUT_OUTPUT_HDMI) ||\
+ (s5ptv_status.tvout_param.out_mode == TVOUT_OUTPUT_HDMI_RGB))
+ tv_phy_power(true);
+
+ /* tv on */
+ if (s5ptv_status.tvout_output_enable)
+ _s5p_tv_if_start();
+
+ /* video layer start */
+ if (s5ptv_status.vp_layer_enable)
+ _s5p_vlayer_start();
+
+ /* grp0 layer start */
+ if (s5ptv_status.grp_layer_enable[0])
+ _s5p_grp_start(VM_GPR0_LAYER);
+
+ /* grp1 layer start */
+ if (s5ptv_status.grp_layer_enable[1])
+ _s5p_grp_start(VM_GPR1_LAYER);
+
+#ifdef CONFIG_TV_FB
+ if (s5ptv_status.tvout_output_enable) {
+ s5ptvfb_display_on(&s5ptv_status);
+ s5ptvfb_set_par(s5ptv_status.fb);
+ }
+#endif
+ }
+ mutex_unlock(mutex_for_fo);
+ BASEPRINTK("()--\n");
+ return ;
+}
+#else
+#define s5p_tv_suspend NULL
+#define s5p_tv_resume NULL
+#endif
+
+#ifdef CONFIG_PM
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static struct early_suspend s5p_tv_early_suspend_desc = {
+ .level = EARLY_SUSPEND_LEVEL_STOP_DRAWING,
+ .suspend = s5p_tv_early_suspend,
+ .resume = s5p_tv_late_resume,
+};
+#endif
+#endif
+
+static struct platform_driver s5p_tv_driver = {
+ .probe = s5p_tv_probe,
+ .remove = s5p_tv_remove,
+#ifdef CONFIG_PM
+#ifndef CONFIG_HAS_EARLYSUSPEND
+ .suspend = s5p_tv_early_suspend,
+ .resume = s5p_tv_late_resume,
+#endif
+#else
+ .suspend = NULL,
+ .resume = NULL,
+#endif
+ .driver = {
+ .name = "s5p-tvout",
+ .owner = THIS_MODULE,
+ },
+};
+
+static char banner[] __initdata =
+ KERN_INFO "S5P TVOUT Driver, (c) 2010 Samsung Electronics\n";
+
+int __init s5p_tv_init(void)
+{
+ int ret;
+
+ printk(banner);
+
+ ret = platform_driver_register(&s5p_tv_driver);
+
+ if (ret) {
+ printk(KERN_ERR "Platform Device Register Failed %d\n", ret);
+ return -1;
+ }
+
+#ifdef CONFIG_PM
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ register_early_suspend(&s5p_tv_early_suspend_desc);
+#endif
+#endif
+ return 0;
+}
+
+static void __exit s5p_tv_exit(void)
+{
+#ifdef CONFIG_PM
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&s5p_tv_early_suspend_desc);
+#endif
+#endif
+ platform_driver_unregister(&s5p_tv_driver);
+}
+
+late_initcall(s5p_tv_init);
+module_exit(s5p_tv_exit);
+
+MODULE_AUTHOR("SangPil Moon");
+MODULE_DESCRIPTION("SS5PC1XX TVOUT driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/samsung/tv20/s5p_tv_v4l2.c b/drivers/media/video/samsung/tv20/s5p_tv_v4l2.c
new file mode 100644
index 0000000..2a2a5e5
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/s5p_tv_v4l2.c
@@ -0,0 +1,1822 @@
+/* linux/drivers/media/video/samsung/tv20/s5p_tv_v4l2.c
+ *
+ * Video4Linux API ftn. file for Samsung TVOut driver
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/stddef.h>
+#include <linux/string.h>
+#include <linux/version.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <linux/delay.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+
+#include "s5p_tv.h"
+
+#ifdef COFIG_TVOUT_DBG
+#define S5P_V4L2_DEBUG 1
+#endif
+
+#ifdef S5P_V4L2_DEBUG
+#define V4L2PRINTK(fmt, args...)\
+ printk(KERN_INFO "[V4L2_IF] %s: " fmt, __func__ , ## args)
+#else
+#define V4L2PRINTK(fmt, args...)
+#endif
+
+/* 0 - hdcp stopped, 1 - hdcp started, 2 - hdcp reset */
+u8 hdcp_protocol_status;
+
+#define CVBS_S_VIDEO (V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_JP| \
+ V4L2_STD_PAL | V4L2_STD_PAL_M | V4L2_STD_PAL_N | V4L2_STD_PAL_Nc | \
+ V4L2_STD_PAL_60 | V4L2_STD_NTSC_443)
+
+static struct v4l2_output s5p_tv_outputs[] = {
+ {
+ .index = 0,
+ .name = "Analog COMPOSITE",
+ .type = V4L2_OUTPUT_TYPE_COMPOSITE,
+ .audioset = 0,
+ .modulator = 0,
+ .std = CVBS_S_VIDEO,
+ }, {
+ .index = 1,
+ .name = "Analog SVIDEO",
+ .type = V4L2_OUTPUT_TYPE_SVIDEO,
+ .audioset = 0,
+ .modulator = 0,
+ .std = CVBS_S_VIDEO,
+ }, {
+ .index = 2,
+ .name = "Analog COMPONENT_YPBPR_I",
+ .type = V4L2_OUTPUT_TYPE_YPBPR_INERLACED,
+ .audioset = 0,
+ .modulator = 0,
+ .std = V4L2_STD_ALL,
+ }, {
+ .index = 3,
+ .name = "Analog COMPONENT_YPBPR_P",
+ .type = V4L2_OUTPUT_TYPE_YPBPR_PROGRESSIVE,
+ .audioset = 0,
+ .modulator = 0,
+ .std = V4L2_STD_ALL,
+ }, {
+ .index = 4,
+ .name = "Analog COMPONENT_RGB_P",
+ .type = V4L2_OUTPUT_TYPE_RGB_PROGRESSIVE,
+ .audioset = 0,
+ .modulator = 0,
+ .std = V4L2_STD_ALL,
+ }, {
+ .index = 5,
+ .name = "Digital HDMI(YCbCr)",
+ .type = V4L2_OUTPUT_TYPE_HDMI,
+ .audioset = 2,
+ .modulator = 0,
+ .std = V4L2_STD_480P_60_16_9 |
+ V4L2_STD_480P_60_16_9 | V4L2_STD_720P_60 |
+ V4L2_STD_720P_50
+#ifdef CONFIG_CPU_S5PV210
+ | V4L2_STD_1080P_60 | V4L2_STD_1080P_50 |
+ V4L2_STD_1080I_60 | V4L2_STD_1080I_50 |
+ V4L2_STD_480P_59 | V4L2_STD_720P_59 |
+ V4L2_STD_1080I_59 | V4L2_STD_1080P_59 |
+ V4L2_STD_1080P_30,
+#endif
+ }, {
+ .index = 6,
+ .name = "Digital HDMI(RGB)",
+ .type = V4L2_OUTPUT_TYPE_HDMI_RGB,
+ .audioset = 2,
+ .modulator = 0,
+ .std = V4L2_STD_480P_60_16_9 |
+ V4L2_STD_480P_60_16_9 |
+ V4L2_STD_720P_60 | V4L2_STD_720P_50
+#ifdef CONFIG_CPU_S5PV210
+ | V4L2_STD_1080P_60 | V4L2_STD_1080P_50 |
+ V4L2_STD_1080I_60 | V4L2_STD_1080I_50 |
+ V4L2_STD_480P_59 | V4L2_STD_720P_59 |
+ V4L2_STD_1080I_59 | V4L2_STD_1080P_59 |
+ V4L2_STD_1080P_30,
+#endif
+ }, {
+ .index = 7,
+ .name = "Digital DVI",
+ .type = V4L2_OUTPUT_TYPE_DVI,
+ .audioset = 2,
+ .modulator = 0,
+ .std = V4L2_STD_480P_60_16_9 |
+ V4L2_STD_480P_60_16_9 |
+ V4L2_STD_720P_60 | V4L2_STD_720P_50
+#ifdef CONFIG_CPU_S5PV210
+ | V4L2_STD_1080P_60 | V4L2_STD_1080P_50 |
+ V4L2_STD_1080I_60 | V4L2_STD_1080I_50 |
+ V4L2_STD_480P_59 | V4L2_STD_720P_59 |
+ V4L2_STD_1080I_59 | V4L2_STD_1080P_59 |
+ V4L2_STD_1080P_30,
+#endif
+ }
+
+};
+
+const struct v4l2_fmtdesc s5p_tv_o_fmt_desc[] = {
+ {
+ .index = 0,
+ .type = V4L2_BUF_TYPE_VIDEO_OUTPUT,
+ .description = "YUV420, NV12 (Video Processor)",
+ .pixelformat = V4L2_PIX_FMT_NV12,
+ .flags = FORMAT_FLAGS_CrCb,
+ }
+};
+
+const struct v4l2_fmtdesc s5p_tv_o_overlay_fmt_desc[] = {
+ {
+ .index = 0,
+ .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY,
+ .description = "16bpp RGB, le - RGB[565]",
+ .pixelformat = V4L2_PIX_FMT_RGB565,
+ .flags = FORMAT_FLAGS_PACKED,
+ }, {
+ .index = 1,
+ .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY,
+ .description = "16bpp RGB, le - ARGB[1555]",
+ .pixelformat = V4L2_PIX_FMT_RGB555,
+ .flags = FORMAT_FLAGS_PACKED,
+ }, {
+ .index = 2,
+ .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY,
+ .description = "16bpp RGB, le - ARGB[4444]",
+ .pixelformat = V4L2_PIX_FMT_RGB444,
+ .flags = FORMAT_FLAGS_PACKED,
+ }, {
+ .index = 3,
+ .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY,
+ .description = "32bpp RGB, le - ARGB[8888]",
+ .pixelformat = V4L2_PIX_FMT_RGB32,
+ .flags = FORMAT_FLAGS_PACKED,
+ }
+};
+
+const struct v4l2_standard s5p_tv_standards[] = {
+ {
+ .index = 0,
+ .id = V4L2_STD_NTSC_M,
+ .name = "NTSC_M",
+ }, {
+
+ .index = 1,
+ .id = V4L2_STD_PAL_BDGHI,
+ .name = "PAL_BDGHI",
+ }, {
+ .index = 2,
+ .id = V4L2_STD_PAL_M,
+ .name = "PAL_M",
+ }, {
+ .index = 3,
+ .id = V4L2_STD_PAL_N,
+ .name = "PAL_N",
+ }, {
+ .index = 4,
+ .id = V4L2_STD_PAL_Nc,
+ .name = "PAL_Nc",
+ }, {
+ .index = 5,
+ .id = V4L2_STD_PAL_60,
+ .name = "PAL_60",
+ }, {
+ .index = 6,
+ .id = V4L2_STD_NTSC_443,
+ .name = "NTSC_443",
+ }, {
+ .index = 7,
+ .id = V4L2_STD_480P_60_16_9,
+ .name = "480P_60_16_9",
+ }, {
+ .index = 8,
+ .id = V4L2_STD_480P_60_4_3,
+ .name = "480P_60_4_3",
+ }, {
+ .index = 9,
+ .id = V4L2_STD_576P_50_16_9,
+ .name = "576P_50_16_9",
+ }, {
+ .index = 10,
+ .id = V4L2_STD_576P_50_4_3,
+ .name = "576P_50_4_3",
+ }, {
+ .index = 11,
+ .id = V4L2_STD_720P_60,
+ .name = "720P_60",
+ }, {
+ .index = 12,
+ .id = V4L2_STD_720P_50,
+ .name = "720P_50",
+ },
+#ifdef CONFIG_CPU_S5PV210
+ {
+ .index = 13,
+ .id = V4L2_STD_1080P_60,
+ .name = "1080P_60",
+ }, {
+ .index = 14,
+ .id = V4L2_STD_1080P_50,
+ .name = "1080P_50",
+ }, {
+ .index = 15,
+ .id = V4L2_STD_1080I_60,
+ .name = "1080I_60",
+ }, {
+ .index = 16,
+ .id = V4L2_STD_1080I_50,
+ .name = "1080I_50",
+ }, {
+ .index = 17,
+ .id = V4L2_STD_480P_59,
+ .name = "480P_59",
+ }, {
+ .index = 18,
+ .id = V4L2_STD_720P_59,
+ .name = "720P_59",
+ }, {
+ .index = 19,
+ .id = V4L2_STD_1080I_59,
+ .name = "1080I_59",
+ }, {
+ .index = 20,
+ .id = V4L2_STD_1080P_59,
+ .name = "1080I_50",
+ }, {
+ .index = 21,
+ .id = V4L2_STD_1080P_30,
+ .name = "1080I_30",
+ }
+#endif
+};
+
+/* TODO: set default format for v, vo0/1 */
+
+const struct v4l2_format s5p_tv_format[] = {
+ {
+ .type = V4L2_BUF_TYPE_VIDEO_OUTPUT,
+ }, {
+ .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY,
+ }, {
+ .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY,
+ },
+};
+
+#define S5P_TVOUT_MAX_STANDARDS \
+ ARRAY_SIZE(s5p_tv_standards)
+#define S5P_TVOUT_MAX_O_TYPES \
+ ARRAY_SIZE(s5p_tv_outputs)
+#define S5P_TVOUT_MAX_O_FMT \
+ ARRAY_SIZE(s5p_tv_format)
+#define S5P_TVOUT_MAX_O_FMT_DESC \
+ ARRAY_SIZE(s5p_tv_o_fmt_desc)
+#define S5P_TVOUT_MAX_O_OVERLAY_FMT_DESC \
+ ARRAY_SIZE(s5p_tv_o_overlay_fmt_desc)
+
+
+void s5p_tv_v4l2_init_param(void)
+{
+ s5ptv_status.v4l2.output = (struct v4l2_output *)&s5p_tv_outputs[0];
+ s5ptv_status.v4l2.std = (struct v4l2_standard *)&s5p_tv_standards[0];
+ s5ptv_status.v4l2.fmt_v = (struct v4l2_format *)&s5p_tv_o_fmt_desc[0];
+ s5ptv_status.v4l2.fmt_vo_0 = (struct v4l2_format *)&s5p_tv_format[1];
+ s5ptv_status.v4l2.fmt_vo_1 = (struct v4l2_format *)&s5p_tv_format[2];
+ s5ptv_status.hdmi_audio_type = HDMI_AUDIO_PCM;
+}
+
+/* VIDIOC_QUERYCAP handler */
+static int s5p_tv_v4l2_querycap(struct file *file, void *fh,
+ struct v4l2_capability *cap)
+{
+ struct s5p_tv_vo *layer = (struct s5p_tv_vo *)fh;
+ u32 index;
+
+ if (layer == NULL) {
+ index = 0;
+ strcpy(cap->driver, "S3C TV Vid drv");
+ cap->capabilities = V4L2_CAP_VIDEO_OUTPUT;
+ } else {
+ index = layer->index + 1;
+ strcpy(cap->driver, "S3C TV Grp drv");
+ cap->capabilities = V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
+ }
+
+ strlcpy(cap->card, s5ptv_status.video_dev[index]->name,
+ sizeof(cap->card));
+
+ sprintf(cap->bus_info, "ARM AHB BUS");
+ cap->version = KERNEL_VERSION(2, 6, 29);
+
+ return 0;
+}
+
+
+/* VIDIOC_ENUM_FMT handlers */
+static int s5p_tv_v4l2_enum_fmt_vid_out(struct file *file, void *fh,
+ struct v4l2_fmtdesc *f)
+{
+ int index = f->index;
+
+ V4L2PRINTK("(%d)++\n", f->index);
+
+ if (index >= S5P_TVOUT_MAX_O_FMT_DESC) {
+ V4L2PRINTK("exceeded S5P_TVOUT_MAX_O_FMT_DESC\n");
+ return -EINVAL;
+ }
+
+ memcpy(f, &s5p_tv_o_fmt_desc[index], sizeof(struct v4l2_fmtdesc));
+
+ V4L2PRINTK("()--\n");
+ return 0;
+
+}
+
+static int s5p_tv_v4l2_enum_fmt_vid_out_overlay(struct file *file,
+ void *fh, struct v4l2_fmtdesc *f)
+{
+ int index = f->index;
+
+ V4L2PRINTK("(%d)++\n", f->index);
+
+ if (index >= S5P_TVOUT_MAX_O_OVERLAY_FMT_DESC) {
+ V4L2PRINTK("exceeded S5P_TVOUT_MAX_O_OVERLAY_FMT_DESC\n");
+ return -EINVAL;
+ }
+
+ memcpy(f, &s5p_tv_o_overlay_fmt_desc[index],
+ sizeof(struct v4l2_fmtdesc));
+
+ V4L2PRINTK("()--\n");
+
+ return 0;
+}
+
+
+/* VIDIOC_G_FMT handlers */
+static int s5p_tv_v4l2_g_fmt_vid_out(struct file *file, void *fh,
+ struct v4l2_format *f)
+{
+
+ struct v4l2_format *vid_out_fmt = f;
+
+ V4L2PRINTK("(0x%08x)++\n", f->type);
+
+ switch (vid_out_fmt->type) {
+
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT: {
+
+ struct v4l2_pix_format_s5p_tvout vparam;
+ memset(&vparam, 0, sizeof(struct v4l2_pix_format_s5p_tvout));
+
+ vparam.base_y =
+ (void *)s5ptv_status.vl_basic_param.top_y_address;
+ vparam.base_c =
+ (void *)s5ptv_status.vl_basic_param.top_c_address;
+ vparam.pix_fmt.pixelformat =
+ s5ptv_status.src_color;
+ vparam.pix_fmt.width =
+ s5ptv_status.vl_basic_param.src_width;
+ vparam.pix_fmt.height =
+ s5ptv_status.vl_basic_param.src_height;
+ V4L2PRINTK("[type 0x%08x] : addr_y: [0x%08x],\
+ addr_c [0x%08x], width[%d], height[%d]\n",
+ f->type,
+ s5ptv_status.vl_basic_param.top_y_address,
+ s5ptv_status.vl_basic_param.top_c_address,
+ s5ptv_status.vl_basic_param.src_width,
+ s5ptv_status.vl_basic_param.src_height);
+ memcpy(vid_out_fmt->fmt.raw_data, &vparam,
+ sizeof(struct v4l2_pix_format_s5p_tvout));
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int s5p_tv_v4l2_g_fmt_vid_out_overlay(struct file *file,
+ void *fh, struct v4l2_format *f)
+{
+
+ struct v4l2_format *vid_out_fmt = f;
+
+ V4L2PRINTK("(0x%08x)++\n", f->type);
+
+ switch (vid_out_fmt->type) {
+
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: {
+
+ struct v4l2_window_s5p_tvout vparam;
+ memset(&vparam, 0, sizeof(struct v4l2_window_s5p_tvout));
+
+ if (s5ptv_status.vl_basic_param.win_blending) {
+ vparam.flags = V4L2_FBUF_FLAG_CHROMAKEY;
+ vparam.capability = V4L2_FBUF_CAP_CHROMAKEY;
+ }
+
+ if (s5ptv_status.vl_basic_param.alpha) {
+ vparam.flags = V4L2_FBUF_FLAG_LOCAL_ALPHA;
+ vparam.capability = V4L2_FBUF_CAP_LOCAL_ALPHA;
+ }
+
+ vparam.priority =
+ s5ptv_status.vl_basic_param.priority;
+
+ vparam.win.w.left =
+ s5ptv_status.vl_basic_param.src_offset_x;
+ vparam.win.w.top =
+ s5ptv_status.vl_basic_param.src_offset_y;
+ vparam.win.w.width =
+ s5ptv_status.vl_basic_param.src_width;
+ vparam.win.w.height =
+ s5ptv_status.vl_basic_param.src_height;
+ V4L2PRINTK("[type 0x%08x] : left: [%d], top [%d],\
+ width[%d], height[%d]\n",
+ f->type,
+ s5ptv_status.vl_basic_param.src_offset_x,
+ s5ptv_status.vl_basic_param.src_offset_y,
+ s5ptv_status.vl_basic_param.src_width,
+ s5ptv_status.vl_basic_param.src_height);
+ memcpy(vid_out_fmt->fmt.raw_data, &vparam,
+ sizeof(struct v4l2_window_s5p_tvout));
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ V4L2PRINTK("()--\n");
+
+ return 0;
+}
+
+/* VIDIOC_S_FMT handlers */
+static int s5p_tv_v4l2_s_fmt_vid_out(struct file *file, void *fh,
+ struct v4l2_format *f)
+{
+
+ struct v4l2_format *vid_out_fmt = f;
+
+ V4L2PRINTK("(0x%08x)++\n", f->type);
+
+ switch (vid_out_fmt->type) {
+
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT: {
+
+ struct v4l2_pix_format_s5p_tvout vparam;
+ memcpy(&vparam, vid_out_fmt->fmt.raw_data,
+ sizeof(struct v4l2_pix_format_s5p_tvout));
+
+ s5ptv_status.vl_basic_param.img_width =
+ vparam.pix_fmt.width;
+
+ s5ptv_status.vl_basic_param.img_height =
+ vparam.pix_fmt.height;
+
+ s5ptv_status.vl_basic_param.src_width =
+ vparam.pix_fmt.width;
+ s5ptv_status.vl_basic_param.src_height =
+ vparam.pix_fmt.height;
+ s5ptv_status.src_color =
+ vparam.pix_fmt.pixelformat;
+
+ s5ptv_status.vl_basic_param.top_y_address =
+ (unsigned int)vparam.base_y;
+ s5ptv_status.vl_basic_param.top_c_address =
+ (unsigned int)vparam.base_c;
+
+ /* check progressive or not */
+ if (vparam.pix_fmt.field == V4L2_FIELD_NONE) {
+
+ /* progressive */
+
+ switch (vparam.pix_fmt.pixelformat) {
+
+ case V4L2_PIX_FMT_NV12:
+ /* linear */
+ s5ptv_status.src_color =
+ VPROC_SRC_COLOR_NV12;
+ break;
+ case V4L2_PIX_FMT_NV12T:
+ /* tiled */
+ s5ptv_status.src_color =
+ VPROC_SRC_COLOR_TILE_NV12;
+ break;
+ default:
+ V4L2PRINTK("src img format not supported\n");
+ break;
+ }
+
+ s5ptv_status.field_id = VPROC_TOP_FIELD;
+
+ if ((s5ptv_status.hpd_status) && \
+ s5ptv_status.vp_layer_enable) {
+ struct s5p_video_img_address temp_addr;
+ struct s5p_img_size img_size;
+
+ temp_addr.y_address =
+ (unsigned int)vparam.base_y;
+ temp_addr.c_address =
+ (unsigned int)vparam.base_c;
+ img_size.img_width =
+ (unsigned int)vparam.pix_fmt.width;
+ img_size.img_height =
+ (unsigned int)vparam.pix_fmt.height;
+
+ _s5p_vlayer_set_top_address((unsigned long)
+ &temp_addr);
+ _s5p_vlayer_set_img_size((unsigned long)
+ &img_size);
+
+ }
+ } else if (vparam.pix_fmt.field == V4L2_FIELD_INTERLACED_TB) {
+
+ /* interlaced */
+
+ switch (vparam.pix_fmt.pixelformat) {
+
+ case V4L2_PIX_FMT_NV12:
+ /* linear */
+ s5ptv_status.src_color =
+ VPROC_SRC_COLOR_NV12IW;
+ break;
+ case V4L2_PIX_FMT_NV12T:
+ /* tiled */
+ s5ptv_status.src_color =
+ VPROC_SRC_COLOR_TILE_NV12IW;
+ break;
+ default:
+ V4L2PRINTK("src img format not supported\n");
+ break;
+ }
+
+ if (vparam.pix_fmt.priv == V4L2_FIELD_BOTTOM)
+ s5ptv_status.field_id = VPROC_BOTTOM_FIELD;
+ else
+ s5ptv_status.field_id = VPROC_TOP_FIELD;
+
+ if ((s5ptv_status.hpd_status) && \
+ s5ptv_status.vp_layer_enable) {
+ struct s5p_video_img_address temp_addr;
+ struct s5p_img_size img_size;
+
+ temp_addr.y_address =
+ (unsigned int)vparam.base_y;
+ temp_addr.c_address =
+ (unsigned int)vparam.base_c;
+ img_size.img_width =
+ (unsigned int)vparam.pix_fmt.width;
+ img_size.img_height =
+ (unsigned int)vparam.pix_fmt.height;
+
+ _s5p_vlayer_set_top_address((unsigned long)
+ &temp_addr);
+ _s5p_vlayer_set_img_size((unsigned long)
+ &img_size);
+
+ }
+
+ } else {
+ V4L2PRINTK("this field id not supported\n");
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ V4L2PRINTK("[type 0x%08x] : addr_y: [0x%08x], addr_c [0x%08x],\
+ width[%d], height[%d]\n",
+ f->type,
+ s5ptv_status.vl_basic_param.top_y_address,
+ s5ptv_status.vl_basic_param.top_c_address,
+ s5ptv_status.vl_basic_param.src_width,
+ s5ptv_status.vl_basic_param.src_height);
+ V4L2PRINTK("()--\n");
+
+ return 0;
+}
+
+
+static int s5p_tv_v4l2_s_fmt_vid_out_overlay(struct file *file, void *fh,
+ struct v4l2_format *f)
+{
+
+ struct v4l2_format *vid_out_fmt = f;
+
+ V4L2PRINTK("(0x%08x)++\n", f->type);
+
+ switch (vid_out_fmt->type) {
+
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: {
+
+ struct v4l2_window_s5p_tvout vparam;
+ memcpy(&vparam, vid_out_fmt->fmt.raw_data,
+ sizeof(struct v4l2_window_s5p_tvout));
+
+ s5ptv_status.vl_basic_param.win_blending =
+ (vparam.flags & V4L2_FBUF_FLAG_CHROMAKEY) ? 1 : 0;
+ s5ptv_status.vl_basic_param.alpha =
+ (vparam.flags & V4L2_FBUF_FLAG_LOCAL_ALPHA) ? 1 : 0;
+ s5ptv_status.vl_basic_param.priority =
+ vparam.priority;
+ s5ptv_status.vl_basic_param.src_offset_x =
+ vparam.win.w.left;
+ s5ptv_status.vl_basic_param.src_offset_y =
+ vparam.win.w.top;
+ s5ptv_status.vl_basic_param.src_width =
+ vparam.win.w.width;
+ s5ptv_status.vl_basic_param.src_height =
+ vparam.win.w.height;
+ V4L2PRINTK("[type 0x%08x] : left: [%d], top [%d],\
+ width[%d], height[%d]\n",
+ f->type,
+ s5ptv_status.vl_basic_param.src_offset_x ,
+ s5ptv_status.vl_basic_param.src_offset_y ,
+ s5ptv_status.vl_basic_param.src_width,
+ s5ptv_status.vl_basic_param.src_height);
+
+ if ((s5ptv_status.hpd_status) && s5ptv_status.vp_layer_enable) {
+ struct s5p_img_offset img_offset;
+ struct s5p_img_size img_size;
+
+ img_offset.offset_x = vparam.win.w.left;
+ img_offset.offset_y = vparam.win.w.top;
+ img_size.img_width = vparam.win.w.width;
+ img_size.img_height = vparam.win.w.height;
+ _s5p_vlayer_set_blending(
+ s5ptv_status.vl_basic_param.win_blending);
+ _s5p_vlayer_set_alpha(
+ s5ptv_status.vl_basic_param.alpha);
+ _s5p_vlayer_set_priority(vparam.priority);
+ _s5p_vlayer_set_src_position((unsigned long)
+ &img_offset);
+ _s5p_vlayer_set_src_size((unsigned long)
+ &img_size);
+ }
+
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ V4L2PRINTK("()--\n");
+
+ return 0;
+}
+
+/* start overlay * */
+static int s5p_tv_v4l2_overlay(struct file *file, void *fh, unsigned int i)
+{
+ struct s5p_tv_vo *layer = (struct s5p_tv_vo *)fh;
+ int start = i;
+ V4L2PRINTK("(0x%08x)++\n", i);
+
+ /* tv dirver is on suspend mode
+ Just set the status variable on this function
+ overlay will be enabled or disabled on resume or
+ handle_cable function according to this status variable*/
+ if (s5ptv_status.suspend_status == true || !(s5ptv_status.hpd_status)) {
+ if (start)
+ s5ptv_status.grp_layer_enable[layer->index] = true;
+ else
+ s5ptv_status.grp_layer_enable[layer->index] = false;
+
+ V4L2PRINTK("suspend mode/hdmi cable is not inserted\n");
+ return 0;
+ } else {
+ if (start)
+ _s5p_grp_start(layer->index);
+ else
+ _s5p_grp_stop(layer->index);
+ }
+ V4L2PRINTK("()--\n");
+ return 0;
+}
+
+static int s5p_tv_v4l2_g_fbuf(struct file *file, void *fh,
+ struct v4l2_framebuffer *a)
+{
+
+ struct v4l2_framebuffer *fbuf = a;
+ struct s5p_tv_vo *layer = (struct s5p_tv_vo *)fh;
+
+ fbuf->base = (void *)s5ptv_overlay[layer->index].base_addr;
+ fbuf->fmt.pixelformat = s5ptv_overlay[layer->index].fb.fmt.pixelformat;
+
+ return 0;
+}
+
+static int s5p_tv_v4l2_s_fbuf(struct file *file, void *fh,
+ struct v4l2_framebuffer *a)
+{
+
+ struct v4l2_framebuffer *fbuf = a;
+ struct s5p_tv_vo *layer = (struct s5p_tv_vo *)fh;
+
+ s5ptv_overlay[layer->index].base_addr = (unsigned int)fbuf->base;
+
+ switch (fbuf->fmt.pixelformat) {
+
+ case V4L2_PIX_FMT_RGB565:
+ s5ptv_overlay[layer->index].fb.fmt.pixelformat =
+ VM_DIRECT_RGB565;
+ break;
+
+ case V4L2_PIX_FMT_RGB555:
+ s5ptv_overlay[layer->index].fb.fmt.pixelformat =
+ VM_DIRECT_RGB1555;
+ break;
+
+ case V4L2_PIX_FMT_RGB444:
+ s5ptv_overlay[layer->index].fb.fmt.pixelformat =
+ VM_DIRECT_RGB4444;
+ break;
+
+ case V4L2_PIX_FMT_RGB32:
+ s5ptv_overlay[layer->index].fb.fmt.pixelformat =
+ VM_DIRECT_RGB8888;
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/* Stream on/off */
+static int s5p_tv_v4l2_streamon(struct file *file, void *fh,
+ enum v4l2_buf_type i)
+{
+ struct s5p_tv_vo *layer = (struct s5p_tv_vo *)fh;
+
+ V4L2PRINTK("(0x%08x)++\n", i);
+
+ /* tv dirver is on suspend mode or hdmi cable is not inserted
+ Just set the status variable on this function
+ overlay will be enabled or disabled on resume or handle_cable
+ function according to this status variable*/
+ if (s5ptv_status.suspend_status == true || !(s5ptv_status.hpd_status)) {
+ switch (i) {
+ /* Vlayer */
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ _s5p_vlayer_init_param(0);
+ s5ptv_status.vp_layer_enable = true;
+ break;
+ /* GRP0/1*/
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
+ s5ptv_status.grp_layer_enable[layer->index] = true;
+ break;
+
+ default:
+ break;
+ }
+ V4L2PRINTK("suspend mode/hdmi cable is not inserted\n");
+ return 0;
+ }
+
+ switch (i) {
+ /* Vlayer*/
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ if (!(s5ptv_status.vp_layer_enable)) {
+ _s5p_vlayer_init_param(0);
+ _s5p_vlayer_start();
+ s5ptv_status.vp_layer_enable = true;
+
+ mdelay(50);
+ } else
+ return -EBUSY;
+
+ break;
+ /* GRP0/1 */
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
+ _s5p_grp_start(layer->index);
+ break;
+
+ default:
+ break;
+ }
+
+ V4L2PRINTK("()--\n");
+
+ return 0;
+}
+
+static int s5p_tv_v4l2_streamoff(struct file *file, void *fh,
+ enum v4l2_buf_type i)
+{
+ struct s5p_tv_vo *layer = (struct s5p_tv_vo *)fh;
+
+ V4L2PRINTK("(0x%08x)++\n", i);
+
+ /* tv driver is on suspend mode or hdmi cable is not inserted
+ Each layer was disabled on suspend function already.
+ Just set the status variable on this function
+ Each layer will be enabled or disabled on resume or
+ handle_cable function according to this status variable*/
+ if (s5ptv_status.suspend_status == true || !(s5ptv_status.hpd_status)) {
+ switch (i) {
+ /* Vlayer*/
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ s5ptv_status.vp_layer_enable = false;
+ break;
+ /* GRP0/1*/
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
+ s5ptv_status.grp_layer_enable[layer->index] = false;
+ break;
+
+ default:
+ break;
+ }
+ V4L2PRINTK("suspend mode\hdmi cable is not inserted\n");
+ return 0;
+ }
+
+ switch (i) {
+ /* Vlayer */
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ _s5p_vlayer_stop();
+ break;
+ /* GRP0/1 */
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
+ _s5p_grp_stop(layer->index);
+ break;
+
+ default:
+ break;
+ }
+
+ V4L2PRINTK("()--\n");
+
+ return 0;
+}
+
+/* Standard handling ENUMSTD is handled by videodev.c */
+static int s5p_tv_v4l2_g_std(struct file *file, void *fh, v4l2_std_id *norm)
+{
+ V4L2PRINTK("()++\n");
+
+ *norm = s5ptv_status.v4l2.std->id;
+
+ V4L2PRINTK("(%d)++\n", (int)(*norm));
+
+ return 0;
+}
+
+static int s5p_tv_v4l2_s_std(struct file *file, void *fh, v4l2_std_id *norm)
+{
+ unsigned int i = 0;
+ v4l2_std_id std_id = *norm;
+
+ V4L2PRINTK("(0x%08Lx)++\n", std_id);
+
+ s5ptv_status.v4l2.std = NULL;
+
+ do {
+ if (s5p_tv_standards[i].id == std_id) {
+ s5ptv_status.v4l2.std = (struct v4l2_standard *)
+ &s5p_tv_standards[i];
+ break;
+ }
+
+ i++;
+ } while (i < S5P_TVOUT_MAX_STANDARDS);
+
+ if (i >= S5P_TVOUT_MAX_STANDARDS || s5ptv_status.v4l2.std == NULL) {
+ V4L2PRINTK("(ERR) There is no tv-out standards :\
+ index = 0x%08Lx\n", std_id);
+ return -EINVAL;
+ }
+
+ switch (std_id) {
+
+ case V4L2_STD_NTSC_M:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_NTSC_M;
+ break;
+
+ case V4L2_STD_PAL_BDGHI:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_PAL_BDGHI;
+ break;
+
+ case V4L2_STD_PAL_M:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_PAL_M;
+ break;
+
+ case V4L2_STD_PAL_N:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_PAL_N;
+ break;
+
+ case V4L2_STD_PAL_Nc:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_PAL_NC;
+ break;
+
+ case V4L2_STD_PAL_60:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_PAL_60;
+ break;
+
+ case V4L2_STD_NTSC_443:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_NTSC_443;
+ break;
+
+ case V4L2_STD_480P_60_16_9:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_480P_60_16_9;
+ break;
+
+ case V4L2_STD_480P_60_4_3:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_480P_60_4_3;
+ break;
+
+#ifdef CONFIG_CPU_S5PV210
+ case V4L2_STD_480P_59:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_480P_59;
+ break;
+#endif
+ case V4L2_STD_576P_50_16_9:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_576P_50_16_9;
+ break;
+
+ case V4L2_STD_576P_50_4_3:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_576P_50_4_3;
+ break;
+
+ case V4L2_STD_720P_60:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_720P_60;
+ break;
+
+#ifdef CONFIG_CPU_S5PV210
+ case V4L2_STD_720P_59:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_720P_59;
+ break;
+#endif
+
+ case V4L2_STD_720P_50:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_720P_50;
+ break;
+
+#ifdef CONFIG_CPU_S5PV210
+ case V4L2_STD_1080I_60:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_1080I_60;
+ break;
+
+ case V4L2_STD_1080I_59:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_1080I_59;
+ break;
+
+ case V4L2_STD_1080I_50:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_1080I_50;
+ break;
+
+ case V4L2_STD_1080P_30:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_1080P_30;
+ break;
+
+ case V4L2_STD_1080P_60:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_1080P_60;
+ break;
+
+ case V4L2_STD_1080P_59:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_1080P_59;
+ break;
+
+ case V4L2_STD_1080P_50:
+ s5ptv_status.tvout_param.disp_mode = TVOUT_1080P_50;
+ break;
+#endif
+ default:
+ V4L2PRINTK("(ERR) not supported standard id :\
+ index = 0x%08Lx\n", std_id);
+ return -EINVAL;
+ break;
+ }
+
+ V4L2PRINTK("()--\n");
+
+ return 0;
+}
+
+/* Output handling */
+static int s5p_tv_v4l2_enum_output(struct file *file, void *fh,
+ struct v4l2_output *a)
+{
+ unsigned int index = a->index;
+ V4L2PRINTK("(%d)++\n", a->index);
+
+ if (index >= S5P_TVOUT_MAX_O_TYPES) {
+ V4L2PRINTK("exceeded supported output!!\n");
+ return -EINVAL;
+ }
+
+ memcpy(a, &s5p_tv_outputs[index], sizeof(struct v4l2_output));
+
+ V4L2PRINTK("()--\n");
+
+ return 0;
+}
+
+static int s5p_tv_v4l2_g_output(struct file *file, void *fh, unsigned int *i)
+{
+ V4L2PRINTK("(%d)++\n", *i);
+
+ *i = s5ptv_status.v4l2.output->index;
+
+ V4L2PRINTK("()--\n");
+ return 0;
+}
+
+static int s5p_tv_v4l2_s_output(struct file *file, void *fh, unsigned int i)
+{
+ V4L2PRINTK("(%d)++\n", i);
+
+ if (i >= S5P_TVOUT_MAX_O_TYPES)
+ return -EINVAL;
+
+ s5ptv_status.v4l2.output = &s5p_tv_outputs[i];
+
+ switch (s5ptv_status.v4l2.output->type) {
+
+ case V4L2_OUTPUT_TYPE_COMPOSITE:
+ s5ptv_status.tvout_param.out_mode =
+ TVOUT_OUTPUT_COMPOSITE;
+ break;
+
+ case V4L2_OUTPUT_TYPE_SVIDEO:
+ s5ptv_status.tvout_param.out_mode =
+ TVOUT_OUTPUT_SVIDEO;
+ break;
+
+ case V4L2_OUTPUT_TYPE_YPBPR_INERLACED:
+ s5ptv_status.tvout_param.out_mode =
+ TVOUT_OUTPUT_COMPONENT_YPBPR_INERLACED;
+ break;
+
+ case V4L2_OUTPUT_TYPE_YPBPR_PROGRESSIVE:
+ s5ptv_status.tvout_param.out_mode =
+ TVOUT_OUTPUT_COMPONENT_YPBPR_PROGRESSIVE;
+ break;
+
+ case V4L2_OUTPUT_TYPE_RGB_PROGRESSIVE:
+ s5ptv_status.tvout_param.out_mode =
+ TVOUT_OUTPUT_COMPOSITE;
+ break;
+
+ case V4L2_OUTPUT_TYPE_HDMI:
+ s5ptv_status.tvout_param.out_mode =
+ TVOUT_OUTPUT_HDMI;
+ break;
+
+ case V4L2_OUTPUT_TYPE_HDMI_RGB:
+ s5ptv_status.tvout_param.out_mode =
+ TVOUT_OUTPUT_HDMI_RGB;
+ break;
+
+ case V4L2_OUTPUT_TYPE_DVI:
+ s5ptv_status.tvout_param.out_mode =
+ TVOUT_OUTPUT_DVI;
+ break;
+
+
+ default:
+ break;
+ }
+
+ if ((s5ptv_status.tvout_param.out_mode != TVOUT_OUTPUT_HDMI) && \
+ (s5ptv_status.tvout_param.out_mode != TVOUT_OUTPUT_HDMI_RGB) &&
+ (s5ptv_status.tvout_param.out_mode != TVOUT_OUTPUT_DVI)) {
+ if (!(s5ptv_status.hpd_status))
+ s5p_tv_clk_gate(true);
+
+ s5ptv_status.hpd_status = 1;
+ }
+
+ _s5p_tv_if_set_disp();
+
+ V4L2PRINTK("()--\n");
+
+ return 0;
+};
+
+/* Crop ioctls */
+
+/*
+ * Video Format Name Pixel aspect ratio Description
+ * STD(4:3) Anamorphic(16:9)
+ * 640x480 4:3 Used on YouTube
+ * 720x576 576i 5:4 64:45 Used on D1/DV PAL
+ * 704x576 576p 12:11 16:11 Used on EDTV PAL
+ * 720x480 480i 8:9 32:27 Used on DV NTSC
+ * 720x486 480i 8:9 32:27 Used on D1 NTSC
+ * 704x480 480p 10:11 40:33 Used on EDTV NTSC
+ */
+
+static int s5p_tv_v4l2_cropcap(struct file *file, void *fh,
+ struct v4l2_cropcap *a)
+{
+
+ struct v4l2_cropcap *cropcap = a;
+
+ switch (cropcap->type) {
+
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ break;
+
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
+ break;
+
+ default:
+ return -1;
+ break;
+ }
+
+ switch (s5ptv_status.tvout_param.disp_mode) {
+
+ case TVOUT_NTSC_M:
+
+ case TVOUT_NTSC_443:
+
+ case TVOUT_480P_60_16_9:
+
+ case TVOUT_480P_60_4_3:
+
+#ifdef CONFIG_CPU_S5PV210
+ case TVOUT_480P_59:
+#endif
+ cropcap->bounds.top = 0;
+ cropcap->bounds.left = 0;
+ cropcap->bounds.width = 720;
+ cropcap->bounds.height = 480;
+
+ cropcap->defrect.top = 0;
+ cropcap->defrect.left = 0;
+ cropcap->defrect.width = 720;
+ cropcap->defrect.height = 480;
+ break;
+
+ case TVOUT_PAL_M:
+
+ case TVOUT_PAL_BDGHI:
+
+ case TVOUT_PAL_N:
+
+ case TVOUT_PAL_NC:
+
+ case TVOUT_PAL_60:
+
+ case TVOUT_576P_50_16_9:
+
+ case TVOUT_576P_50_4_3:
+
+ cropcap->bounds.top = 0;
+ cropcap->bounds.left = 0;
+ cropcap->bounds.width = 720;
+ cropcap->bounds.height = 576;
+
+ cropcap->defrect.top = 0;
+ cropcap->defrect.left = 0;
+ cropcap->defrect.width = 720;
+ cropcap->defrect.height = 576;
+ break;
+
+ case TVOUT_720P_60:
+#ifdef CONFIG_CPU_S5PV210
+ case TVOUT_720P_59:
+#endif
+ case TVOUT_720P_50:
+ cropcap->bounds.top = 0;
+ cropcap->bounds.left = 0;
+ cropcap->bounds.width = 1280;
+ cropcap->bounds.height = 720;
+
+ cropcap->defrect.top = 0;
+ cropcap->defrect.left = 0;
+ cropcap->defrect.width = 1280;
+ cropcap->defrect.height = 720;
+ break;
+
+#ifdef CONFIG_CPU_S5PV210
+
+ case TVOUT_1080I_60:
+
+ case TVOUT_1080I_59:
+
+ case TVOUT_1080I_50:
+
+ case TVOUT_1080P_60:
+
+ case TVOUT_1080P_59:
+
+ case TVOUT_1080P_50:
+
+ case TVOUT_1080P_30:
+
+ cropcap->bounds.top = 0;
+ cropcap->bounds.left = 0;
+ cropcap->bounds.width = 1920;
+ cropcap->bounds.height = 1080;
+
+ cropcap->defrect.top = 0;
+ cropcap->defrect.left = 0;
+ cropcap->defrect.width = 1920;
+ cropcap->defrect.height = 1080;
+ break;
+#endif
+
+ default:
+ return -1;
+ break;
+
+ }
+
+ V4L2PRINTK("[input type 0x%08x] : left: [%d], top [%d],\
+ width[%d], height[%d]\n",
+
+ s5ptv_status.tvout_param.disp_mode,
+ cropcap->bounds.top ,
+ cropcap->bounds.left ,
+ cropcap->bounds.width,
+ cropcap->bounds.height);
+
+ return 0;
+}
+
+static int s5p_tv_v4l2_g_crop(struct file *file, void *fh, struct v4l2_crop *a)
+{
+
+ struct v4l2_crop *crop = a;
+ struct s5p_tv_vo *layer = (struct s5p_tv_vo *)fh;
+
+ switch (crop->type) {
+ /* Vlayer */
+
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ crop->c.left = s5ptv_status.vl_basic_param.dest_offset_x;
+ crop->c.top = s5ptv_status.vl_basic_param.dest_offset_y;
+ crop->c.width = s5ptv_status.vl_basic_param.dest_width;
+ crop->c.height = s5ptv_status.vl_basic_param.dest_height;
+ break;
+ /* GRP0/1 */
+
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
+ crop->c.left = s5ptv_overlay[layer->index].dst_rect.left;
+ crop->c.top = s5ptv_overlay[layer->index].dst_rect.top;
+ crop->c.width = s5ptv_overlay[layer->index].dst_rect.width;
+ crop->c.height = s5ptv_overlay[layer->index].dst_rect.height;
+
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int s5p_tv_v4l2_s_crop(struct file *file, void *fh, struct v4l2_crop *a)
+{
+
+ struct v4l2_crop *crop = a;
+ struct s5p_tv_vo *layer = (struct s5p_tv_vo *)fh;
+
+ switch (crop->type) {
+ /* Vlayer - scaling!! */
+
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+
+ s5ptv_status.vl_basic_param.dest_offset_x = crop->c.left;
+ s5ptv_status.vl_basic_param.dest_offset_y = crop->c.top;
+ s5ptv_status.vl_basic_param.dest_width = crop->c.width;
+ s5ptv_status.vl_basic_param.dest_height = crop->c.height;
+
+ if ((s5ptv_status.hpd_status) && s5ptv_status.vp_layer_enable) {
+ struct s5p_img_size img_size;
+ struct s5p_img_offset img_offset;
+ img_size.img_width = crop->c.width;
+ img_size.img_height = crop->c.height;
+ img_offset.offset_x = crop->c.left;
+ img_offset.offset_y = crop->c.top;
+
+ _s5p_vlayer_set_dest_size((unsigned long)
+ &img_size);
+ _s5p_vlayer_set_dest_position((unsigned long)
+ &img_offset);
+ }
+
+ break;
+
+ /* GRP0/1 */
+
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
+ s5ptv_overlay[layer->index].dst_rect.left = crop->c.left;
+ s5ptv_overlay[layer->index].dst_rect.top = crop->c.top;
+ s5ptv_overlay[layer->index].dst_rect.width = crop->c.width;
+ s5ptv_overlay[layer->index].dst_rect.height = crop->c.height;
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/* Stream type-dependent parameter ioctls */
+
+static int s5p_tv_v4l2_g_parm_v(struct file *file, void *fh,
+ struct v4l2_streamparm *a)
+{
+
+ struct v4l2_streamparm *param = a;
+
+ struct v4l2_window_s5p_tvout vparam;
+
+ if (s5ptv_status.vl_basic_param.win_blending) {
+ vparam.flags = V4L2_FBUF_FLAG_GLOBAL_ALPHA;
+ vparam.capability = V4L2_FBUF_FLAG_GLOBAL_ALPHA;
+ }
+
+ vparam.win.global_alpha = s5ptv_status.vl_basic_param.alpha;
+
+ vparam.priority = s5ptv_status.vl_basic_param.priority;
+ vparam.win.w.left = s5ptv_status.vl_basic_param.src_offset_x;
+ vparam.win.w.top = s5ptv_status.vl_basic_param.src_offset_y;
+ vparam.win.w.width = s5ptv_status.vl_basic_param.src_width;
+ vparam.win.w.height = s5ptv_status.vl_basic_param.src_height;
+
+ memcpy(param->parm.raw_data, &vparam,
+ sizeof(struct v4l2_window_s5p_tvout));
+
+ return 0;
+}
+
+static int s5p_tv_v4l2_s_parm_v(struct file *file, void *fh,
+ struct v4l2_streamparm *a)
+{
+
+ struct v4l2_streamparm *param = a;
+
+ struct v4l2_window_s5p_tvout vparam;
+
+ memcpy(&vparam, param->parm.raw_data,
+ sizeof(struct v4l2_window_s5p_tvout));
+
+ s5ptv_status.vl_basic_param.win_blending =
+ (vparam.flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) ? 1 : 0;
+ s5ptv_status.vl_basic_param.alpha = vparam.win.global_alpha;
+ s5ptv_status.vl_basic_param.priority = vparam.priority;
+ s5ptv_status.vl_basic_param.src_offset_x = vparam.win.w.left;
+ s5ptv_status.vl_basic_param.src_offset_y = vparam.win.w.top;
+ s5ptv_status.vl_basic_param.src_width = vparam.win.w.width;
+ s5ptv_status.vl_basic_param.src_height = vparam.win.w.height;
+
+ V4L2PRINTK("[type 0x%08x] : left: [%d], top [%d],\
+ width[%d], height[%d]\n",
+ a->type,
+ s5ptv_status.vl_basic_param.src_offset_x ,
+ s5ptv_status.vl_basic_param.src_offset_y ,
+ s5ptv_status.vl_basic_param.src_width,
+ s5ptv_status.vl_basic_param.src_height);
+
+ if ((s5ptv_status.hpd_status) && s5ptv_status.vp_layer_enable) {
+ struct s5p_img_offset img_offset;
+ struct s5p_img_size img_size;
+
+ img_offset.offset_x = vparam.win.w.left;
+ img_offset.offset_y = vparam.win.w.top;
+ img_size.img_width = vparam.win.w.width;
+ img_size.img_height = vparam.win.w.height;
+ _s5p_vlayer_set_blending(
+ s5ptv_status.vl_basic_param.win_blending);
+ _s5p_vlayer_set_alpha(s5ptv_status.vl_basic_param.alpha);
+ _s5p_vlayer_set_priority(vparam.priority);
+ _s5p_vlayer_set_src_position((unsigned long)&img_offset);
+ _s5p_vlayer_set_src_size((unsigned long)&img_size);
+ }
+
+ return 0;
+}
+
+static int s5p_tv_v4l2_g_parm_vo(struct file *file, void *fh,
+ struct v4l2_streamparm *a)
+{
+
+ struct v4l2_streamparm *param = a;
+
+ struct v4l2_window_s5p_tvout vparam;
+ struct s5p_tv_vo *layer = (struct s5p_tv_vo *)fh;
+
+ memset(&vparam, 0, sizeof(struct v4l2_window_s5p_tvout));
+
+ V4L2PRINTK("entered\n");
+
+ if (s5ptv_overlay[layer->index].win_blending) {
+ vparam.flags = V4L2_FBUF_FLAG_GLOBAL_ALPHA;
+ vparam.capability = V4L2_FBUF_CAP_GLOBAL_ALPHA;
+ }
+
+ if (s5ptv_overlay[layer->index].blank_change) {
+ vparam.flags |= V4L2_FBUF_FLAG_CHROMAKEY;
+ vparam.capability |= V4L2_FBUF_CAP_CHROMAKEY;
+ }
+
+ if (s5ptv_overlay[layer->index].pixel_blending) {
+ vparam.flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
+ vparam.capability |= V4L2_FBUF_CAP_LOCAL_ALPHA;
+ }
+
+ if (s5ptv_overlay[layer->index].pre_mul) {
+ vparam.flags |= V4L2_FBUF_FLAG_PRE_MULTIPLY;
+ vparam.capability |= V4L2_FBUF_CAP_PRE_MULTIPLY;
+ }
+
+ vparam.priority = s5ptv_overlay[layer->index].priority;
+
+ vparam.win.chromakey = s5ptv_overlay[layer->index].blank_color;
+ vparam.win.w.left = s5ptv_overlay[layer->index].dst_rect.left;
+ vparam.win.w.top = s5ptv_overlay[layer->index].dst_rect.top;
+ vparam.win.w.left = s5ptv_overlay[layer->index].win.w.left;
+ vparam.win.w.top = s5ptv_overlay[layer->index].win.w.top;
+ vparam.win.w.width = s5ptv_overlay[layer->index].win.w.width;
+ vparam.win.w.height = s5ptv_overlay[layer->index].win.w.height;
+ vparam.win.global_alpha = s5ptv_overlay[layer->index].win.global_alpha;
+
+ vparam.win.w.width =
+ s5ptv_overlay[layer->index].fb.fmt.bytesperline;
+
+ memcpy(param->parm.raw_data, &vparam,
+ sizeof(struct v4l2_window_s5p_tvout));
+
+ return 0;
+
+}
+
+static int s5p_tv_v4l2_s_parm_vo(struct file *file, void *fh,
+ struct v4l2_streamparm *a)
+{
+
+ struct v4l2_streamparm *param = a;
+
+ struct v4l2_window_s5p_tvout vparam;
+
+ struct s5p_tv_vo *layer = (struct s5p_tv_vo *)fh;
+ memcpy(&vparam, param->parm.raw_data,
+ sizeof(struct v4l2_window_s5p_tvout));
+
+ s5ptv_overlay[layer->index].win_blending =
+ (vparam.flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) ? 1 : 0;
+ s5ptv_overlay[layer->index].blank_change =
+ (vparam.flags & V4L2_FBUF_FLAG_CHROMAKEY) ? 1 : 0;
+ s5ptv_overlay[layer->index].pixel_blending =
+ (vparam.flags & V4L2_FBUF_FLAG_LOCAL_ALPHA) ? 1 : 0;
+ s5ptv_overlay[layer->index].pre_mul =
+ (vparam.flags & V4L2_FBUF_FLAG_PRE_MULTIPLY) ? 1 : 0;
+ s5ptv_overlay[layer->index].priority =
+ vparam.priority;
+ s5ptv_overlay[layer->index].blank_color =
+ vparam.win.chromakey;
+ s5ptv_overlay[layer->index].dst_rect.left =
+ vparam.win.w.left;
+ s5ptv_overlay[layer->index].dst_rect.top =
+ vparam.win.w.top;
+ s5ptv_overlay[layer->index].win.w.left =
+ vparam.win.w.left;
+ s5ptv_overlay[layer->index].win.w.top =
+ vparam.win.w.top;
+ s5ptv_overlay[layer->index].win.w.width =
+ vparam.win.w.width;
+ s5ptv_overlay[layer->index].win.w.height =
+ vparam.win.w.height;
+ s5ptv_overlay[layer->index].win.global_alpha =
+ vparam.win.global_alpha;
+
+ s5ptv_overlay[layer->index].fb.fmt.bytesperline =
+ vparam.win.w.width;
+
+ return 0;
+}
+
+#define VIDIOC_HDCP_ENABLE _IOWR('V', 100, unsigned int)
+#define VIDIOC_HDCP_STATUS _IOR('V', 101, unsigned int)
+#define VIDIOC_HDCP_PROT_STATUS _IOR('V', 102, unsigned int)
+#define VIDIOC_INIT_AUDIO _IOR('V', 103, unsigned int)
+#define VIDIOC_AV_MUTE _IOR('V', 104, unsigned int)
+#define VIDIOC_G_AVMUTE _IOR('V', 105, unsigned int)
+
+long s5p_tv_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ switch (cmd) {
+
+ case VIDIOC_HDCP_ENABLE:
+ s5ptv_status.hdcp_en = (unsigned int) arg;
+ V4L2PRINTK("HDCP status is %s\n",
+ s5ptv_status.hdcp_en ? "enabled" : "disabled");
+ return 0;
+
+ case VIDIOC_HDCP_STATUS: {
+
+ unsigned int *status = (unsigned int *)&arg;
+
+ *status = 1;
+
+ V4L2PRINTK("HPD status is %s\n",
+ s5ptv_status.hpd_status ? "plugged" : "unplugged");
+ return 0;
+ }
+
+ case VIDIOC_HDCP_PROT_STATUS: {
+
+ unsigned int *prot = (unsigned int *)&arg;
+
+ *prot = 1;
+
+ V4L2PRINTK("hdcp prot status is %d\n",
+ hdcp_protocol_status);
+ return 0;
+ }
+
+ case VIDIOC_ENUMSTD: {
+
+ struct v4l2_standard *p = (struct v4l2_standard *)arg;
+
+ if (p->index >= S5P_TVOUT_MAX_STANDARDS) {
+ V4L2PRINTK("exceeded S5P_TVOUT_MAX_STANDARDS\n");
+ return -EINVAL;
+ }
+
+ memcpy(p, &s5p_tv_standards[p->index],
+ sizeof(struct v4l2_standard));
+
+ return 0;
+}
+
+ default:
+ break;
+ }
+
+ /*
+ * in 2.6.28 version Mauro Carvalho Chehab added for removing inode
+ * but 2.6.29 is not applied. what is it?
+ */
+ return video_ioctl2(file, cmd, arg);
+}
+
+long s5p_tv_vid_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct video_device *vfd = video_devdata(file);
+ const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;
+
+ switch (cmd) {
+
+ case VIDIOC_S_FMT: {
+ struct v4l2_format *f = (struct v4l2_format *)arg;
+ void *fh = file->private_data;
+ long ret = -EINVAL;
+
+ if (ops->vidioc_s_fmt_vid_out)
+ ret = ops->vidioc_s_fmt_vid_out(file, fh, f);
+ return ret;
+ }
+
+ default:
+ break;
+ }
+
+ /*
+ * in 2.6.28 version Mauro Carvalho Chehab added for removing inode
+ * but 2.6.29 is not applied. what is it?
+ */
+ return video_ioctl2(file, cmd, arg);
+}
+
+
+long s5p_tv_v_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct video_device *vfd = video_devdata(file);
+ const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;
+
+ switch (cmd) {
+
+ case VIDIOC_INIT_AUDIO:
+ s5ptv_status.hdmi_audio_type = (unsigned int) arg;
+
+ if (arg) {
+ s5p_hdmi_set_audio(true);
+ if (s5ptv_status.tvout_output_enable)
+ s5p_hdmi_audio_enable(true);
+ } else {
+ s5p_hdmi_set_audio(false);
+ if (s5ptv_status.tvout_output_enable)
+ s5p_hdmi_audio_enable(false);
+
+ }
+
+ return 0;
+
+ case VIDIOC_AV_MUTE:
+ if (arg) {
+ s5ptv_status.hdmi_audio_type = HDMI_AUDIO_NO;
+ if (s5ptv_status.tvout_output_enable) {
+ s5p_hdmi_audio_enable(false);
+ __s5p_hdmi_video_set_bluescreen(true, 0, 0, 0);
+ }
+ s5p_hdmi_set_mute(true);
+ } else {
+ s5ptv_status.hdmi_audio_type = HDMI_AUDIO_PCM;
+ if (s5ptv_status.tvout_output_enable) {
+ s5p_hdmi_audio_enable(true);
+ __s5p_hdmi_video_set_bluescreen(false, 0, 0, 0);
+ }
+ s5p_hdmi_set_mute(false);
+ }
+ return 0;
+ case VIDIOC_G_AVMUTE:
+ return s5p_hdmi_get_mute();
+
+ case VIDIOC_S_FMT: {
+ struct v4l2_format *f = (struct v4l2_format *)arg;
+ void *fh = file->private_data;
+ long ret = -EINVAL;
+
+ if (ops->vidioc_s_fmt_vid_out)
+ ret = ops->vidioc_s_fmt_vid_out(file, fh, f);
+ return ret;
+ }
+
+ case VIDIOC_HDCP_ENABLE:
+ s5ptv_status.hdcp_en = (unsigned int) arg;
+ V4L2PRINTK("HDCP status is %s\n",
+ s5ptv_status.hdcp_en ? "enabled" : "disabled");
+ return 0;
+
+ case VIDIOC_HDCP_STATUS: {
+
+ unsigned int *status = (unsigned int *)arg;
+
+ *status = s5ptv_status.hpd_status;
+
+ V4L2PRINTK("HPD status is %s\n",
+ s5ptv_status.hpd_status ? "plugged" : "unplugged");
+ return 0;
+ }
+
+ case VIDIOC_HDCP_PROT_STATUS: {
+
+ unsigned int *prot = (unsigned int *)&arg;
+
+ *prot = 1;
+
+ V4L2PRINTK("hdcp prot status is %d\n",
+ hdcp_protocol_status);
+ return 0;
+ }
+
+ case VIDIOC_ENUMSTD: {
+
+ struct v4l2_standard *p = (struct v4l2_standard *)arg;
+
+ if (p->index >= S5P_TVOUT_MAX_STANDARDS) {
+ V4L2PRINTK("exceeded S5P_TVOUT_MAX_STANDARDS\n");
+ return -EINVAL;
+ }
+
+ memcpy(p, &s5p_tv_standards[p->index],
+ sizeof(struct v4l2_standard));
+
+ return 0;
+ }
+
+ default:
+ break;
+ }
+
+ /*
+ * in 2.6.28 version Mauro Carvalho Chehab added for removing inode
+ * but 2.6.29 is not applied. what is it?
+ */
+ return video_ioctl2(file, cmd, arg);
+}
+
+long s5p_tv_vo_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ void *fh = file->private_data;
+
+ switch (cmd) {
+
+ case VIDIOC_ENUM_FMT: {
+
+ struct v4l2_fmtdesc *f = (struct v4l2_fmtdesc *)arg;
+ enum v4l2_buf_type type;
+ unsigned int index;
+
+ index = f->index;
+ type = f->type;
+
+ if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY) {
+ memset(f, 0, sizeof(*f));
+ f->index = index;
+ f->type = type;
+
+ return s5p_tv_v4l2_enum_fmt_vid_out_overlay(file,
+ fh, f);
+ }
+
+ break;
+ }
+
+ case VIDIOC_G_FMT: {
+
+ struct v4l2_format *f = (struct v4l2_format *)arg;
+
+ return s5p_tv_v4l2_g_fmt_vid_out_overlay(file, fh, f);
+ }
+
+ break;
+
+ default:
+ break;
+ }
+
+ /*
+ * in 2.6.28 version Mauro Carvalho Chehab added for removing inode
+ * but 2.6.29 is not applied. what is it?
+ */
+ return video_ioctl2(file, cmd, arg);
+}
+
+const struct v4l2_ioctl_ops s5p_tv_v4l2_ops = {
+ .vidioc_querycap = s5p_tv_v4l2_querycap,
+ .vidioc_g_std = s5p_tv_v4l2_g_std,
+ .vidioc_s_std = s5p_tv_v4l2_s_std,
+ .vidioc_enum_output = s5p_tv_v4l2_enum_output,
+ .vidioc_g_output = s5p_tv_v4l2_g_output,
+ .vidioc_s_output = s5p_tv_v4l2_s_output,
+};
+
+const struct v4l2_ioctl_ops s5p_tv_v4l2_vid_ops = {
+ .vidioc_querycap = s5p_tv_v4l2_querycap,
+ .vidioc_enum_fmt_vid_out = s5p_tv_v4l2_enum_fmt_vid_out,
+ .vidioc_g_fmt_vid_out = s5p_tv_v4l2_g_fmt_vid_out,
+ .vidioc_s_fmt_vid_out = s5p_tv_v4l2_s_fmt_vid_out,
+ .vidioc_streamon = s5p_tv_v4l2_streamon,
+ .vidioc_streamoff = s5p_tv_v4l2_streamoff,
+ .vidioc_cropcap = s5p_tv_v4l2_cropcap,
+ .vidioc_g_crop = s5p_tv_v4l2_g_crop,
+ .vidioc_s_crop = s5p_tv_v4l2_s_crop,
+ .vidioc_g_parm = s5p_tv_v4l2_g_parm_v,
+ .vidioc_s_parm = s5p_tv_v4l2_s_parm_v,
+};
+
+const struct v4l2_ioctl_ops s5p_tv_v4l2_v_ops = {
+ .vidioc_querycap = s5p_tv_v4l2_querycap,
+ .vidioc_enum_fmt_vid_out = s5p_tv_v4l2_enum_fmt_vid_out,
+ .vidioc_g_fmt_vid_out = s5p_tv_v4l2_g_fmt_vid_out,
+ .vidioc_s_fmt_vid_out = s5p_tv_v4l2_s_fmt_vid_out,
+ .vidioc_streamon = s5p_tv_v4l2_streamon,
+ .vidioc_streamoff = s5p_tv_v4l2_streamoff,
+ .vidioc_g_std = s5p_tv_v4l2_g_std,
+ .vidioc_s_std = s5p_tv_v4l2_s_std,
+ .vidioc_enum_output = s5p_tv_v4l2_enum_output,
+ .vidioc_g_output = s5p_tv_v4l2_g_output,
+ .vidioc_s_output = s5p_tv_v4l2_s_output,
+ .vidioc_cropcap = s5p_tv_v4l2_cropcap,
+ .vidioc_g_crop = s5p_tv_v4l2_g_crop,
+ .vidioc_s_crop = s5p_tv_v4l2_s_crop,
+ .vidioc_g_parm = s5p_tv_v4l2_g_parm_v,
+ .vidioc_s_parm = s5p_tv_v4l2_s_parm_v,
+};
+
+const struct v4l2_ioctl_ops s5p_tv_v4l2_vo_ops = {
+ .vidioc_querycap = s5p_tv_v4l2_querycap,
+ .vidioc_g_fmt_vid_out_overlay = s5p_tv_v4l2_g_fmt_vid_out_overlay,
+ .vidioc_s_fmt_vid_out_overlay = s5p_tv_v4l2_s_fmt_vid_out_overlay,
+ .vidioc_overlay = s5p_tv_v4l2_overlay,
+ .vidioc_g_fbuf = s5p_tv_v4l2_g_fbuf,
+ .vidioc_s_fbuf = s5p_tv_v4l2_s_fbuf,
+ .vidioc_streamon = s5p_tv_v4l2_streamon,
+ .vidioc_streamoff = s5p_tv_v4l2_streamoff,
+ .vidioc_cropcap = s5p_tv_v4l2_cropcap,
+ .vidioc_g_crop = s5p_tv_v4l2_g_crop,
+ .vidioc_s_crop = s5p_tv_v4l2_s_crop,
+ .vidioc_g_parm = s5p_tv_v4l2_g_parm_vo,
+ .vidioc_s_parm = s5p_tv_v4l2_s_parm_vo,
+};
+
diff --git a/drivers/media/video/samsung/tv20/s5pc100/hdcp_s5pc100.c b/drivers/media/video/samsung/tv20/s5pc100/hdcp_s5pc100.c
new file mode 100644
index 0000000..7ca9cf4
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/s5pc100/hdcp_s5pc100.c
@@ -0,0 +1,1596 @@
+/* linux/drivers/media/video/samsung/tv20/s5pc100/hdcp_s5pc100.c
+ *
+ * hdcp raw ftn file for Samsung TVOut driver
+ *
+ * Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/device.h>
+#include <linux/wait.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include <mach/gpio.h>
+
+#include "tv_out_s5pc100.h"
+#include "regs/regs-hdmi.h"
+
+/* for Operation check */
+#ifdef COFIG_TVOUT_RAW_DBG
+#define S5P_HDCP_DEBUG 1
+#define S5P_HDCP_I2C_DEBUG 1
+#define S5P_HDCP_AUTH_DEBUG 1
+#endif
+
+#ifdef S5P_HDCP_DEBUG
+#define HDCPPRINTK(fmt, args...) \
+ printk(KERN_INFO "\t\t[HDCP] %s: " fmt, __func__ , ## args)
+#else
+#define HDCPPRINTK(fmt, args...)
+#endif
+
+/* for i2c bus check */
+#ifdef S5P_HDCP_I2C_DEBUG
+#define I2CPRINTK(fmt, args...) \
+ printk(KERN_INFO "\t\t\t\t[I2C] %s: " fmt, __func__ , ## args)
+#else
+#define I2CPRINTK(fmt, args...)
+#endif
+
+/* for authentication key check */
+#ifdef S5P_HDCP_AUTH_DEBUG
+#define AUTHPRINTK(fmt, args...) \
+ printk(KERN_INFO "\t\t\t[AUTHKEY] %s: " fmt, __func__ , ## args)
+#else
+#define AUTHPRINTK(fmt, args...)
+#endif
+
+
+
+enum hdmi_run_mode {
+ DVI_MODE,
+ HDMI_MODE
+};
+
+enum hdmi_resolution {
+ SD480P,
+ SD480I,
+ WWSD480P,
+ HD720P,
+ SD576P,
+ WWSD576P,
+ HD1080I
+};
+
+enum hdmi_color_bar_type {
+ HORIZONTAL,
+ VERTICAL
+};
+
+enum hdcp_event {
+ /* Stop HDCP */
+ HDCP_EVENT_STOP,
+ /* Start HDCP*/
+ HDCP_EVENT_START,
+ /* Start to read Bksv,Bcaps */
+ HDCP_EVENT_READ_BKSV_START,
+ /* Start to write Aksv,An */
+ HDCP_EVENT_WRITE_AKSV_START,
+ /* Start to check if Ri is equal to Rj */
+ HDCP_EVENT_CHECK_RI_START,
+ /* Start 2nd authentication process */
+ HDCP_EVENT_SECOND_AUTH_START
+};
+
+enum hdcp_state {
+ NOT_AUTHENTICATED,
+ RECEIVER_READ_READY,
+ BCAPS_READ_DONE,
+ BKSV_READ_DONE,
+ AN_WRITE_DONE,
+ AKSV_WRITE_DONE,
+ FIRST_AUTHENTICATION_DONE,
+ SECOND_AUTHENTICATION_RDY,
+ RECEIVER_FIFOLSIT_READY,
+ SECOND_AUTHENTICATION_DONE,
+};
+
+/*
+ * Below CSC_TYPE is temporary. CSC_TYPE enum.
+ * may be included in SetSD480pVars_60Hz etc.
+ *
+ * LR : Limited Range (16~235)
+ * FR : Full Range (0~255)
+ */
+enum hdmi_intr_src {
+ WAIT_FOR_ACTIVE_RX,
+ WDT_FOR_REPEATER,
+ EXCHANGE_KSV,
+ UPDATE_P_VAL,
+ UPDATE_R_VAL,
+ AUDIO_OVERFLOW,
+ AUTHEN_ACK,
+ UNKNOWN_INT
+};
+
+const u8 hdcp_key[288] = {
+ 0x48, 0xf8, 0x11, 0xb6, 0x85, 0x66, 0x9b, 0x65, 0x0b, 0x9f,
+ 0x5a, 0x01, 0xb4, 0x43, 0xaf, 0xd7, 0x34, 0xeb, 0xbe, 0xe0,
+ 0x52, 0xfb, 0x85, 0xfe, 0xfa, 0xb1, 0x2f, 0xe4, 0xc3, 0xce,
+ 0xa9, 0x27, 0x33, 0x74, 0x97, 0xd8, 0xfc, 0x62, 0xb8, 0x92,
+ 0x4a, 0xb6, 0xce, 0x7b, 0xb8, 0xda, 0x67, 0xbf, 0xda, 0xea,
+ 0xbf, 0xa9, 0xc0, 0x2a, 0xc8, 0xf6, 0x44, 0x41, 0x5a, 0x10,
+ 0x59, 0x88, 0x54, 0xcf, 0x51, 0x91, 0x12, 0xd5, 0xa8, 0x41,
+ 0x3a, 0x8a, 0x88, 0xd1, 0x5a, 0x9a, 0x55, 0xc1, 0xbb, 0x5e,
+ 0x8a, 0xa0, 0x84, 0x1b, 0xa8, 0xea, 0x31, 0x59, 0xea, 0x71,
+ 0x0c, 0xcf, 0x59, 0xf5, 0xa8, 0x32, 0x57, 0xbb, 0xd4, 0xa0,
+ 0x5b, 0x88, 0x44, 0x66, 0xd6, 0x80, 0xfa, 0xe9, 0x18, 0xe0,
+ 0x50, 0x73, 0x92, 0x63, 0xe1, 0x5c, 0x13, 0xbf, 0x7d, 0x0d,
+ 0x70, 0x0b, 0xf8, 0x25, 0x4a, 0x3b, 0x9c, 0x17, 0x56, 0xb3,
+ 0x71, 0x2b, 0xfe, 0x3c, 0xcb, 0x7c, 0x19, 0x28, 0x53, 0xa7,
+ 0x5c, 0x57, 0x47, 0xe3, 0xe1, 0x4c, 0x76, 0x62, 0x0a, 0x40,
+ 0x30, 0xcf, 0xbe, 0x51, 0xaf, 0x0d, 0x11, 0x73, 0xd6, 0x6a,
+ 0xc2, 0xbf, 0x4f, 0xc1, 0x88, 0x8d, 0x14, 0xa6, 0xd1, 0x92,
+ 0x6c, 0xf7, 0x8a, 0xe6, 0x9c, 0x96, 0xc5, 0xc4, 0x5c, 0x36,
+ 0xf6, 0xfb, 0x39, 0xf4, 0x79, 0x3f, 0x7a, 0x30, 0x71, 0x5e,
+ 0x3e, 0xfe, 0xf3, 0x4d, 0x0c, 0x02, 0x55, 0xeb, 0x08, 0x24,
+ 0x5f, 0x64, 0xd7, 0xcf, 0xf3, 0x48, 0x35, 0x03, 0xc4, 0xc8,
+ 0x29, 0xf7, 0x9d, 0xcf, 0x21, 0xb8, 0x67, 0x05, 0xc6, 0x47,
+ 0x05, 0x1b, 0x5f, 0xf3, 0xa7, 0xbc, 0x23, 0xf0, 0x09, 0xc4,
+ 0x90, 0x44, 0x5d, 0x3f, 0xf9, 0x79, 0x74, 0xea, 0x7b, 0x42,
+ 0x57, 0x88, 0xce, 0x32, 0x43, 0xa5, 0xf4, 0x4e, 0x05, 0xc9,
+ 0x73, 0xc2, 0x49, 0x94, 0x85, 0x5c, 0xa2, 0x11, 0x91, 0x1f,
+ 0x9e, 0xe3, 0x21, 0xbe, 0xe9, 0x36, 0x52, 0xec, 0x4b, 0xa6,
+ 0x7d, 0xf6, 0x8a, 0x85, 0xb9, 0xe1, 0xc7, 0x6e, 0x6b, 0x08,
+ 0x9d, 0xf2, 0xee, 0x7d, 0x28, 0xbd, 0xf0, 0x9d
+};
+
+struct s5p_hdcp_info {
+ bool is_repeater;
+ bool hpd_status;
+ u32 time_out;
+ u32 hdcp_enable;
+
+ spinlock_t lock;
+
+ struct i2c_client *client;
+
+ wait_queue_head_t waitq;
+ enum hdcp_event event;
+ enum hdcp_state auth_status;
+
+ struct work_struct work;
+};
+
+static struct s5p_hdcp_info hdcp_info = {
+ .is_repeater = false,
+ .time_out = 0,
+ .hdcp_enable = false,
+ .client = NULL,
+ .event = HDCP_EVENT_STOP,
+ .auth_status = NOT_AUTHENTICATED,
+
+};
+
+#define HDCP_RI_OFFSET 0x08
+#define INFINITE 0xffffffff
+
+#define DO_NOT_TRANSMIT (0)
+#define HDMI_SYS_ENABLE (1 << 0)
+#define HDMI_ASP_ENABLE (1 << 2)
+#define HDMI_ASP_DISABLE (~HDMI_ASP_ENABLE)
+
+#define MAX_DEVS_EXCEEDED (0x1 << 7)
+#define MAX_CASCADE_EXCEEDED (0x1 << 3)
+
+#define MAX_CASCADE_EXCEEDED_ERROR (-1)
+#define MAX_DEVS_EXCEEDED_ERROR (-2)
+#define REPEATER_ILLEGAL_DEVICE_ERROR (-3)
+
+#define AINFO_SIZE 1
+#define BCAPS_SIZE 1
+#define BSTATUS_SIZE 2
+#define SHA_1_HASH_SIZE 20
+
+#define KSV_FIFO_READY (0x1 << 5)
+
+#define SET_HDCP_KSV_WRITE_DONE (0x1 << 3)
+#define CLEAR_HDCP_KSV_WRITE_DONE (~SET_HDCP_KSV_WRITE_DONE)
+
+#define SET_HDCP_KSV_LIST_EMPTY (0x1 << 2)
+#define CLEAR_HDCP_KSV_LIST_EMPTY (~SET_HDCP_KSV_LIST_EMPTY)
+#define SET_HDCP_KSV_END (0x1 << 1)
+#define CLEAR_HDCP_KSV_END (~SET_HDCP_KSV_END)
+#define SET_HDCP_KSV_READ (0x1 << 0)
+#define CLEAR_HDCP_KSV_READ (~SET_HDCP_KSV_READ)
+
+#define SET_HDCP_SHA_VALID_READY (0x1 << 1)
+#define CLEAR_HDCP_SHA_VALID_READY (~SET_HDCP_SHA_VALID_READY)
+#define SET_HDCP_SHA_VALID (0x1 << 0)
+#define CLEAR_HDCP_SHA_VALID (~SET_HDCP_SHA_VALID)
+
+#define TRANSMIT_EVERY_VSYNC (0x1 << 1)
+
+/* must be checked */
+
+/*
+ * Read the HDCP data from Rx by using IIC
+ */
+static int hdcp_i2c_read(struct i2c_client *client, u8 subaddr,
+ u8 *data, u16 len)
+{
+ u8 addr = subaddr;
+ int ret = 0;
+
+ struct i2c_msg msg[] = {
+ { client->addr, 0, 1, &addr},
+ { client->addr, I2C_M_RD, len, data }
+ };
+
+ if (!hdcp_info.client) {
+ HDCPPRINTK("DDC port is not available!!"
+ "Check hdmi receiver's DDC Port \n");
+ return -EIO;
+ }
+
+ I2CPRINTK("sub addr = 0x%08x, data len = %d\n", subaddr, len);
+
+ if (i2c_transfer(client->adapter, msg, 2) != 2)
+ ret = -EIO;
+
+ I2CPRINTK("ret :%d\n", ret);
+
+#ifdef S5P_HDCP_I2C_DEBUG
+ {
+ int loop = 0;
+ HDCPPRINTK("read_data :: \n");
+ printk(KERN_INFO "\t\t\t");
+
+ for (loop = 0; loop < len; loop++)
+ printk("0x%02x ", data[loop]);
+
+ printk(KERN_INFO "\n");
+ }
+#endif
+ return ret;
+}
+
+/*
+ * Write the HDCP data to receiver by using IIC
+ * - use i2c_master_send()
+ */
+static int hdcp_i2c_write(struct i2c_client *client, u8 *data, u16 len)
+{
+ int ret = 0;
+
+ if (!hdcp_info.client) {
+ HDCPPRINTK("DDC port is not available!!"
+ "Check hdmi receiver's DDC Port \n");
+ return -EIO;
+ }
+
+ I2CPRINTK("sub addr = 0x%08x, data len = %d\n",
+
+ data[0], len);
+
+ if (i2c_master_send(client, (const char *) data, len) != len)
+ ret = -EIO;
+
+ I2CPRINTK("ret :%d\n", ret);
+
+ return ret;
+}
+
+/*
+ * 1st Authentication step func.
+ * Write the Ainfo data to Rx
+ */
+static bool write_ainfo(void)
+{
+ int ret = 0;
+ u8 ainfo[2];
+
+ ainfo[0] = HDCP_Ainfo;
+ ainfo[1] = 0;
+
+ ret = hdcp_i2c_write(hdcp_info.client, ainfo, 2);
+
+ if (ret < 0)
+ HDCPPRINTK("Can't write ainfo data through i2c bus\n");
+
+ return (ret < 0) ? false : true;
+}
+
+/*
+ * Write the An data to Rx
+ */
+static bool write_an(void)
+{
+ int ret = 0;
+ u8 an[AN_SIZE+1];
+
+ an[0] = HDCP_An;
+
+ /* Read An from HDMI */
+ an[1] = readb(hdmi_base + S5P_HDCP_An_0_0);
+ an[2] = readb(hdmi_base + S5P_HDCP_An_0_1);
+ an[3] = readb(hdmi_base + S5P_HDCP_An_0_2);
+ an[4] = readb(hdmi_base + S5P_HDCP_An_0_3);
+ an[5] = readb(hdmi_base + S5P_HDCP_An_1_0);
+ an[6] = readb(hdmi_base + S5P_HDCP_An_1_1);
+ an[7] = readb(hdmi_base + S5P_HDCP_An_1_2);
+ an[8] = readb(hdmi_base + S5P_HDCP_An_1_3);
+
+ ret = hdcp_i2c_write(hdcp_info.client, an, AN_SIZE + 1);
+
+ if (ret < 0)
+ HDCPPRINTK("Can't write an data through i2c bus\n");
+
+#ifdef S5P_HDCP_AUTH_DEBUG
+ {
+ u16 i = 0;
+
+ for (i = 1; i < AN_SIZE + 1; i++)
+ AUTHPRINTK("HDCPAn[%d]: 0x%x \n", i, an[i]);
+
+ }
+#endif
+
+ return (ret < 0) ? false : true;
+}
+
+/*
+ * Write the Aksv data to Rx
+ */
+static bool write_aksv(void)
+{
+ int ret = 0;
+ u8 aksv[AKSV_SIZE+1];
+
+ aksv[0] = HDCP_Aksv;
+
+ /* Read Aksv from HDMI */
+ aksv[1] = readb(hdmi_base + S5P_HDCP_AKSV_0_0);
+ aksv[2] = readb(hdmi_base + S5P_HDCP_AKSV_0_1);
+ aksv[3] = readb(hdmi_base + S5P_HDCP_AKSV_0_2);
+ aksv[4] = readb(hdmi_base + S5P_HDCP_AKSV_0_3);
+ aksv[5] = readb(hdmi_base + S5P_HDCP_AKSV_1);
+
+ ret = hdcp_i2c_write(hdcp_info.client, aksv, AKSV_SIZE + 1);
+
+ if (ret < 0)
+ HDCPPRINTK("Can't write aksv data through i2c bus\n");
+
+#ifdef S5P_HDCP_AUTH_DEBUG
+ {
+ u16 i = 0;
+
+ for (i = 1; i < AKSV_SIZE + 1; i++)
+ AUTHPRINTK("HDCPAksv[%d]: 0x%x\n", i, aksv[i]);
+
+ }
+#endif
+
+ return (ret < 0) ? false : true;
+}
+
+static bool read_bcaps(void)
+{
+ int ret = 0;
+ u8 bcaps[BCAPS_SIZE] = {0};
+
+ ret = hdcp_i2c_read(hdcp_info.client, HDCP_Bcaps, bcaps, BCAPS_SIZE);
+
+ if (ret < 0) {
+ HDCPPRINTK("Can't read bcaps data from i2c bus\n");
+ return false;
+ }
+
+ writel(bcaps[0], hdmi_base + S5P_HDCP_BCAPS);
+
+ HDCPPRINTK("BCAPS(from i2c) : 0x%08x\n", bcaps[0]);
+
+ if (bcaps[0] & REPEATER_SET)
+ hdcp_info.is_repeater = true;
+ else
+ hdcp_info.is_repeater = false;
+
+ HDCPPRINTK("attached device type : %s !! \n\r",
+ hdcp_info.is_repeater ? "REPEATER" : "SINK");
+
+ HDCPPRINTK("BCAPS(from sfr) = 0x%08x\n",
+ readl(hdmi_base + S5P_HDCP_BCAPS));
+
+ return true;
+}
+
+static bool read_again_bksv(void)
+{
+ u8 bk_sv[BKSV_SIZE] = {0, 0, 0, 0, 0};
+ u8 i = 0;
+ u8 j = 0;
+ u32 no_one = 0;
+ u32 no_zero = 0;
+ u32 result = 0;
+ int ret = 0;
+
+ ret = hdcp_i2c_read(hdcp_info.client, HDCP_Bksv, bk_sv, BKSV_SIZE);
+
+ if (ret < 0) {
+ HDCPPRINTK("Can't read bk_sv data from i2c bus\n");
+ return false;
+ }
+
+#ifdef S5P_HDCP_AUTH_DEBUG
+ for (i = 0; i < BKSV_SIZE; i++)
+ AUTHPRINTK("i2c read : Bksv[%d]: 0x%x\n", i, bk_sv[i]);
+
+#endif
+
+ for (i = 0; i < BKSV_SIZE; i++) {
+
+ for (j = 0; j < 8; j++) {
+
+ result = bk_sv[i] & (0x1 << j);
+
+ if (result == 0)
+ no_zero += 1;
+ else
+ no_one += 1;
+ }
+ }
+
+ if ((no_zero == 20) && (no_one == 20)) {
+ HDCPPRINTK("Suucess: no_zero, and no_one is 20\n");
+
+ writel(bk_sv[0], hdmi_base + S5P_HDCP_BKSV_0_0);
+ writel(bk_sv[1], hdmi_base + S5P_HDCP_BKSV_0_1);
+ writel(bk_sv[2], hdmi_base + S5P_HDCP_BKSV_0_2);
+ writel(bk_sv[3], hdmi_base + S5P_HDCP_BKSV_0_3);
+ writel(bk_sv[4], hdmi_base + S5P_HDCP_BKSV_1);
+
+#ifdef S5P_HDCP_AUTH_DEBUG
+
+ for (i = 0; i < BKSV_SIZE; i++)
+ AUTHPRINTK("set reg : Bksv[%d]: 0x%x\n", i, bk_sv[i]);
+
+#endif
+ return true;
+ } else {
+ HDCPPRINTK("Failed: no_zero or no_one is NOT 20\n");
+ return false;
+ }
+}
+
+static bool read_bksv(void)
+{
+ u8 bk_sv[BKSV_SIZE] = {0, 0, 0, 0, 0};
+
+ int i = 0;
+ int j = 0;
+
+ u32 no_one = 0;
+ u32 no_zero = 0;
+ u32 result = 0;
+ u32 count = 0;
+ int ret = 0;
+
+ ret = hdcp_i2c_read(hdcp_info.client, HDCP_Bksv, bk_sv, BKSV_SIZE);
+
+ if (ret < 0) {
+ HDCPPRINTK("Can't read bk_sv data from i2c bus\n");
+ return false;
+ }
+
+#ifdef S5P_HDCP_AUTH_DEBUG
+ for (i = 0; i < BKSV_SIZE; i++)
+ AUTHPRINTK("i2c read : Bksv[%d]: 0x%x\n", i, bk_sv[i]);
+
+#endif
+
+ for (i = 0; i < BKSV_SIZE; i++) {
+
+ for (j = 0; j < 8; j++) {
+
+ result = bk_sv[i] & (0x1 << j);
+
+ if (result == 0)
+ no_zero++;
+ else
+ no_one++;
+ }
+ }
+
+ if ((no_zero == 20) && (no_one == 20)) {
+
+ writel(bk_sv[0], hdmi_base + S5P_HDCP_BKSV_0_0);
+ writel(bk_sv[1], hdmi_base + S5P_HDCP_BKSV_0_1);
+ writel(bk_sv[2], hdmi_base + S5P_HDCP_BKSV_0_2);
+ writel(bk_sv[3], hdmi_base + S5P_HDCP_BKSV_0_3);
+ writel(bk_sv[4], hdmi_base + S5P_HDCP_BKSV_1);
+
+#ifdef S5P_HDCP_AUTH_DEBUG
+
+ for (i = 0; i < BKSV_SIZE; i++)
+ AUTHPRINTK("set reg : Bksv[%d]: 0x%x\n", i, bk_sv[i]);
+
+#endif
+
+ HDCPPRINTK("Success: no_zero, and no_one is 20\n");
+
+ } else {
+
+ HDCPPRINTK("Failed: no_zero or no_one is NOT 20\n");
+
+
+ while (!read_again_bksv()) {
+
+ count++;
+
+ mdelay(20);
+
+ if (count == 140)
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/*
+ * Compare the R value of Tx with that of Rx
+ */
+static bool compare_r_val(void)
+{
+ int ret = 0;
+ u8 ri[2] = {0, 0};
+ u8 rj[2] = {0, 0};
+ u16 i;
+
+ for (i = 0; i < R_VAL_RETRY_CNT; i++) {
+ /* Read R value from Tx */
+ ri[0] = readl(hdmi_base + S5P_HDCP_Ri_0);
+ ri[1] = readl(hdmi_base + S5P_HDCP_Ri_1);
+
+ /* Read R value from Rx */
+ ret = hdcp_i2c_read(hdcp_info.client, HDCP_Ri, rj, 2);
+
+ if (ret < 0) {
+ HDCPPRINTK("Can't read r data from i2c bus\n");
+ return false;
+ }
+
+#ifdef S5P_HDCP_AUTH_DEBUG
+ AUTHPRINTK("retries :: %d\n", i);
+
+ printk(KERN_INFO "\t\t\t Rx(ddc) ->");
+
+ printk(KERN_INFO "rj[0]: 0x%02x, rj[1]: 0x%02x\n",
+ rj[0], rj[1]);
+
+ printk(KERN_INFO "\t\t\t Tx(register) ->");
+
+ printk(KERN_INFO "ri[0]: 0x%02x, ri[1]: 0x%02x\n",
+ ri[0], ri[1]);
+
+#endif
+
+ /* Compare R value */
+ if ((ri[0] == rj[0]) && (ri[1] == rj[1]) && (ri[0] | ri[1])) {
+ writel(Ri_MATCH_RESULT__YES,
+ hdmi_base + S5P_HDCP_CHECK_RESULT);
+ HDCPPRINTK("R0, R0' is matched!!\n");
+ ret = true;
+ break;
+ } else {
+ writel(Ri_MATCH_RESULT__NO,
+ hdmi_base + S5P_HDCP_CHECK_RESULT);
+ HDCPPRINTK("R0, R0' is not matched!!\n");
+ ret = false;
+ }
+
+ }
+
+ return ret ? true : false;
+}
+
+static bool make_aes_key(void)
+{
+ u32 aes_reg_val;
+
+
+ aes_reg_val = readl(hdmi_base + S5P_HAES_CON);
+ aes_reg_val = SCRAMBLER_KEY_START_EN;
+
+ /* Start generation of AES key */
+ writel(aes_reg_val, hdmi_base + S5P_HAES_CON);
+
+ do {
+ aes_reg_val = readl(hdmi_base + S5P_HAES_CON);
+ } while (!(aes_reg_val & SCRAMBLER_KEY_DONE));
+
+ return true;
+}
+
+/*
+ * HAES function
+ */
+static void start_decrypting(const u8 *hdcp_key, u32 hdcp_key_size)
+{
+ u32 i = 0;
+ u32 aes_start = 0;
+ u32 aes_reg_val = 0;
+
+ make_aes_key();
+
+ writel(hdcp_key_size, hdmi_base + S5P_HAES_DATA_SIZE_L);
+
+ for (i = 0; i < hdcp_key_size; i++)
+ writel(hdcp_key[i], hdmi_base + S5P_HAES_DATA);
+
+
+ aes_reg_val = readl(hdmi_base + S5P_HAES_CON);
+
+ aes_reg_val |= HAES_START_EN;
+
+ writel(aes_reg_val, hdmi_base + S5P_HAES_CON);
+
+ do {
+ aes_start = readl(hdmi_base + S5P_HAES_CON);
+ } while (aes_start & HAES_START_EN);
+}
+
+/*
+ * Start encryption
+ */
+static void start_encryption(void)
+{
+ u32 hdcp_status;
+
+ /* Ri == Ri' |Ready the compared result of Ri */
+ writel(Ri_MATCH_RESULT__YES, hdmi_base + S5P_HDCP_CHECK_RESULT);
+
+ do {
+ hdcp_status = readl(hdmi_base + S5P_STATUS);
+ /* Wait for STATUS[7] to '1'*/
+ } while ((hdcp_status & AUTHENTICATED) != AUTHENTICATED);
+
+ /* Start encryption */
+ writel(HDCP_ENC_ENABLE, hdmi_base + S5P_ENC_EN);
+
+}
+
+/*
+ * Check whether Rx is repeater or not
+ */
+static int check_repeater(void)
+{
+ int ret = 0;
+
+ u8 i = 0;
+ u16 j = 0;
+
+ u8 bcaps[BCAPS_SIZE] = {0};
+ u8 status[BSTATUS_SIZE] = {0, 0};
+ u8 rx_v[SHA_1_HASH_SIZE];
+ u8 ksv_list[HDCP_MAX_DEVS*HDCP_KSV_SIZE];
+
+ u32 hdcp_ctrl;
+ u32 dev_cnt;
+ u32 stat;
+
+ bool ksv_fifo_ready = false;
+
+ while (j <= 500) {
+ ret = hdcp_i2c_read(hdcp_info.client, HDCP_Bcaps,
+ bcaps, BCAPS_SIZE);
+
+ if (ret < 0) {
+ HDCPPRINTK("Can't read bcaps data from i2c bus\n");
+ return false;
+ }
+
+ if (bcaps[0] & KSV_FIFO_READY) {
+ HDCPPRINTK("ksv fifo is ready\n");
+ ksv_fifo_ready = true;
+ writel(bcaps[0], hdmi_base + S5P_HDCP_BCAPS);
+ break;
+ } else {
+ HDCPPRINTK("ksv fifo is not ready\n");
+ ksv_fifo_ready = false;
+ mdelay(10);
+ j++;
+ }
+
+ }
+
+ if (j == 500) {
+ HDCPPRINTK("ksv fifo check timeout occurred!!\n");
+ return false;
+ }
+
+ if (ksv_fifo_ready) {
+ hdcp_ctrl = readl(hdmi_base + S5P_HDCP_CTRL);
+ hdcp_ctrl &= CLEAR_REPEATER_TIMEOUT;
+ writel(hdcp_ctrl, hdmi_base + S5P_HDCP_CTRL);
+ } else
+ return false;
+
+ /*
+ * Check MAX_CASCADE_EXCEEDED
+ * or MAX_DEVS_EXCEEDED indicator
+ */
+ ret = hdcp_i2c_read(hdcp_info.client, HDCP_BStatus,
+ status, BSTATUS_SIZE);
+
+ if (ret < 0) {
+ HDCPPRINTK("Can't read status data from i2c bus\n");
+ return false;
+ }
+
+ /* MAX_CASCADE_EXCEEDED || MAX_DEVS_EXCEEDED */
+ if (status[1] & MAX_CASCADE_EXCEEDED) {
+ HDCPPRINTK("MAX_CASCADE_EXCEEDED\n");
+ return MAX_CASCADE_EXCEEDED_ERROR;
+ } else if (status[0] & MAX_DEVS_EXCEEDED) {
+ HDCPPRINTK("MAX_CASCADE_EXCEEDED\n");
+ return MAX_DEVS_EXCEEDED_ERROR;
+ }
+
+
+ writel(status[0], hdmi_base + S5P_HDCP_BSTATUS_0);
+
+ writel(status[1], hdmi_base + S5P_HDCP_BSTATUS_1);
+
+ /* Read KSV list */
+ dev_cnt = (*status) & 0x7f;
+
+ HDCPPRINTK("status[0] :0x%08x, status[1] :0x%08x!!\n",
+ status[0], status[1]);
+
+ if (dev_cnt) {
+
+ u32 val;
+
+ /* read ksv */
+ ret = hdcp_i2c_read(hdcp_info.client, HDCP_KSVFIFO, ksv_list,
+ dev_cnt * HDCP_KSV_SIZE);
+
+ if (ret < 0) {
+ HDCPPRINTK("Can't read ksv fifo!!\n");
+ return false;
+ }
+
+ /* write ksv */
+ for (i = 0; i < dev_cnt; i++) {
+
+ writel(ksv_list[(i*5) + 0],
+ hdmi_base + S5P_HDCP_RX_KSV_0_0);
+ writel(ksv_list[(i*5) + 1],
+ hdmi_base + S5P_HDCP_RX_KSV_0_1);
+ writel(ksv_list[(i*5) + 2],
+ hdmi_base + S5P_HDCP_RX_KSV_0_2);
+ writel(ksv_list[(i*5) + 3],
+ hdmi_base + S5P_HDCP_RX_KSV_0_3);
+ writel(ksv_list[(i*5) + 4],
+ hdmi_base + S5P_HDCP_RX_KSV_0_4);
+
+ if (i != (dev_cnt - 1)) { /* if it's not end */
+ /* it's not in manual */
+ writel(SET_HDCP_KSV_WRITE_DONE,
+ S5P_HDCP_RX_KSV_LIST_CTRL);
+
+ mdelay(20);
+
+ /* check ksv readed */
+
+ do {
+ if (!hdcp_info.hdcp_enable)
+ return false;
+
+ stat = readl(hdmi_base +
+ S5P_HDCP_RX_KSV_LIST_CTRL);
+
+ } while (!(stat & SET_HDCP_KSV_READ));
+
+
+ HDCPPRINTK("read complete\n");
+
+ }
+
+ HDCPPRINTK("HDCP_RX_KSV_1 = 0x%x\n\r",
+ readl(hdmi_base +
+ S5P_HDCP_RX_KSV_LIST_CTRL));
+ HDCPPRINTK("i : %d, dev_cnt : %d, val = 0x%08x\n",
+ i, dev_cnt, val);
+ }
+
+ /* end of ksv */
+ val = readl(hdmi_base + S5P_HDCP_RX_KSV_LIST_CTRL);
+
+ val |= SET_HDCP_KSV_END | SET_HDCP_KSV_WRITE_DONE;
+
+ writel(val, hdmi_base + S5P_HDCP_RX_KSV_LIST_CTRL);
+
+ HDCPPRINTK("HDCP_RX_KSV_1 = 0x%x\n\r",
+ readl(hdmi_base + S5P_HDCP_RX_KSV_LIST_CTRL));
+
+ HDCPPRINTK("i : %d, dev_cnt : %d, val = 0x%08x\n",
+ i, dev_cnt, val);
+
+ } else {
+
+ writel(SET_HDCP_KSV_LIST_EMPTY,
+ hdmi_base + S5P_HDCP_RX_KSV_LIST_CTRL);
+ }
+
+
+ /* Read SHA-1 from receiver */
+ ret = hdcp_i2c_read(hdcp_info.client, HDCP_SHA1,
+ rx_v, SHA_1_HASH_SIZE);
+
+ if (ret < 0) {
+ HDCPPRINTK("Can't read sha_1_hash data from i2c bus\n");
+ return false;
+ }
+
+ for (i = 0; i < SHA_1_HASH_SIZE; i++)
+ HDCPPRINTK("SHA_1 rx :: %x\n", rx_v[i]);
+
+
+ /* write SHA-1 to register */
+ writel(rx_v[0], hdmi_base + S5P_HDCP_RX_SHA1_0_0);
+
+ writel(rx_v[1], hdmi_base + S5P_HDCP_RX_SHA1_0_1);
+
+ writel(rx_v[2], hdmi_base + S5P_HDCP_RX_SHA1_0_2);
+
+ writel(rx_v[3], hdmi_base + S5P_HDCP_RX_SHA1_0_3);
+
+ writel(rx_v[4], hdmi_base + S5P_HDCP_RX_SHA1_1_0);
+
+ writel(rx_v[5], hdmi_base + S5P_HDCP_RX_SHA1_1_1);
+
+ writel(rx_v[6], hdmi_base + S5P_HDCP_RX_SHA1_1_2);
+
+ writel(rx_v[7], hdmi_base + S5P_HDCP_RX_SHA1_1_3);
+
+ writel(rx_v[8], hdmi_base + S5P_HDCP_RX_SHA1_2_0);
+
+ writel(rx_v[9], hdmi_base + S5P_HDCP_RX_SHA1_2_1);
+
+ writel(rx_v[10], hdmi_base + S5P_HDCP_RX_SHA1_2_2);
+
+ writel(rx_v[11], hdmi_base + S5P_HDCP_RX_SHA1_2_3);
+
+ writel(rx_v[12], hdmi_base + S5P_HDCP_RX_SHA1_3_0);
+
+ writel(rx_v[13], hdmi_base + S5P_HDCP_RX_SHA1_3_1);
+
+ writel(rx_v[14], hdmi_base + S5P_HDCP_RX_SHA1_3_2);
+
+ writel(rx_v[15], hdmi_base + S5P_HDCP_RX_SHA1_3_3);
+
+ writel(rx_v[16], hdmi_base + S5P_HDCP_RX_SHA1_4_0);
+
+ writel(rx_v[17], hdmi_base + S5P_HDCP_RX_SHA1_4_1);
+
+ writel(rx_v[18], hdmi_base + S5P_HDCP_RX_SHA1_4_2);
+
+ writel(rx_v[19], hdmi_base + S5P_HDCP_RX_SHA1_4_3);
+
+ /* SHA write done, and wait for SHA computation being done */
+ mdelay(1);
+
+ /* check authentication success or not */
+ stat = readl(hdmi_base + S5P_HDCP_AUTH_STATUS);
+
+ HDCPPRINTK("auth status %d\n", stat);
+
+ if (stat & SET_HDCP_SHA_VALID_READY) {
+
+ HDCPPRINTK("SHA valid ready 0x%x \n\r", stat);
+
+ stat = readl(hdmi_base + S5P_HDCP_AUTH_STATUS);
+
+ if (stat & SET_HDCP_SHA_VALID) {
+
+ HDCPPRINTK("SHA valid 0x%x \n\r", stat);
+
+ ret = true;
+ } else {
+ HDCPPRINTK("SHA valid ready, but not valid 0x%x \n\r",
+ stat);
+ ret = false;
+ }
+
+ } else {
+
+ HDCPPRINTK("SHA not ready 0x%x \n\r", stat);
+ ret = false;
+ }
+
+
+ /* clear all validate bit */
+ writel(0x0, hdmi_base + S5P_HDCP_AUTH_STATUS);
+
+ return ret;
+
+}
+
+/*
+ * Check whether the HDCP event occurred or not
+ */
+/*
+static bool __s5p_is_occurred_hdcp_event(void)
+{
+ u32 status_val;
+
+ status_val = readl(hdmi_base + S5P_STATUS);
+
+ return (((status_val == (0x1 << 0) || status_val == (0x1 << 1) ||
+ status_val == (0x1 << 2) || status_val == (0x1 << 3) ||
+ status_val == (0x1 << 4))) ? true : false);
+}
+*/
+
+static bool try_read_receiver(void)
+{
+ u8 i = 0;
+ bool ret = false;
+
+ for (i = 0; i < 40; i++) {
+
+ mdelay(250);
+
+ if (hdcp_info.auth_status != RECEIVER_READ_READY) {
+
+ HDCPPRINTK("hdcp stat. changed!!"
+ "failed attempt no = %d\n\r", i);
+
+ return false;
+ }
+
+ ret = read_bcaps();
+
+ if (ret) {
+
+ HDCPPRINTK("succeeded at attempt no= %d \n\r", i);
+
+ return true;
+
+ } else
+ HDCPPRINTK("can't read bcaps!!"
+ "failed attempt no=%d\n\r", i);
+ }
+
+ return false;
+}
+
+
+/*
+ * stop - stop functions are only called under running HDCP
+ */
+bool __s5p_stop_hdcp(void)
+{
+ u32 sfr_val;
+
+ HDCPPRINTK("HDCP ftn. Stop!!\n");
+
+ hdcp_protocol_status = 0;
+
+ hdcp_info.time_out = INFINITE;
+ hdcp_info.event = HDCP_EVENT_STOP;
+ hdcp_info.auth_status = NOT_AUTHENTICATED;
+ hdcp_info.hdcp_enable = false;
+
+
+
+ /* 3. disable hdcp control reg. */
+ sfr_val = readl(hdmi_base + S5P_HDCP_CTRL);
+ sfr_val &= (ENABLE_1_DOT_1_FEATURE_DIS
+ & CLEAR_REPEATER_TIMEOUT
+ & EN_PJ_DIS
+ & CP_DESIRED_DIS);
+ writel(sfr_val, hdmi_base + S5P_HDCP_CTRL);
+
+ /* 2. disable aes_data_size & haes_con reg. */
+ sfr_val = readl(hdmi_base + S5P_HAES_CON);
+ sfr_val &= SCRAMBLER_KEY_START_DIS;
+ writel(sfr_val, hdmi_base + S5P_HAES_CON);
+
+ /* 1-3. disable hdmi hpd reg. */
+ writel(CABLE_UNPLUGGED, hdmi_base + S5P_HPD);
+
+ /* 1-2. disable hdmi status enable reg. */
+ sfr_val = readl(hdmi_base + S5P_STATUS_EN);
+ sfr_val &= HDCP_STATUS_DIS_ALL;
+ writel(sfr_val, hdmi_base + S5P_STATUS_EN);
+
+ /* 1-1. clear all status pending */
+ sfr_val = readl(hdmi_base + S5P_STATUS);
+ sfr_val |= HDCP_STATUS_EN_ALL;
+ writel(sfr_val, hdmi_base + S5P_STATUS);
+
+ /* disable encryption */
+ writel(HDCP_ENC_DISABLE, hdmi_base + S5P_ENC_EN);
+
+ /* clear result */
+ writel(Ri_MATCH_RESULT__NO, hdmi_base + S5P_HDCP_CHECK_RESULT);
+ writel(readl(hdmi_base + S5P_HDMI_CON_0) & HDMI_DIS,
+ hdmi_base + S5P_HDMI_CON_0);
+ writel(readl(hdmi_base + S5P_HDMI_CON_0) | HDMI_EN,
+ hdmi_base + S5P_HDMI_CON_0);
+ writel(CLEAR_ALL_RESULTS, hdmi_base + S5P_HDCP_CHECK_RESULT);
+
+ /* hdmi disable */
+ /*
+ sfr_val = readl(hdmi_base + S5P_HDMI_CON_0);
+ sfr_val &= ~(PWDN_ENB_NORMAL | HDMI_EN | ASP_EN);
+ writel( sfr_val, hdmi_base + S5P_HDMI_CON_0);
+ */
+ HDCPPRINTK("\tSTATUS \t0x%08x\n", readl(hdmi_base + S5P_STATUS));
+ HDCPPRINTK("\tSTATUS_EN \t0x%08x\n", readl(hdmi_base + S5P_STATUS_EN));
+ HDCPPRINTK("\tHPD \t0x%08x\n", readl(hdmi_base + S5P_HPD));
+ HDCPPRINTK("\tHDCP_CTRL \t0x%08x\n", readl(hdmi_base + S5P_HDCP_CTRL));
+ HDCPPRINTK("\tMODE_SEL \t0x%08x\n", readl(hdmi_base + S5P_MODE_SEL));
+ HDCPPRINTK("\tENC_EN \t0x%08x\n", readl(hdmi_base + S5P_ENC_EN));
+ HDCPPRINTK("\tHDMI_CON_0 \t0x%08x\n",
+ readl(hdmi_base + S5P_HDMI_CON_0));
+
+ return true;
+}
+
+
+void __s5p_hdcp_reset(void)
+{
+
+ __s5p_stop_hdcp();
+
+ hdcp_protocol_status = 2;
+
+ HDCPPRINTK("HDCP ftn. reset!!\n");
+
+}
+
+/*
+ * start - start functions are only called under stopping HDCP
+ */
+bool __s5p_start_hdcp(void)
+{
+ u32 sfr_val;
+
+ hdcp_info.event = HDCP_EVENT_STOP;
+ hdcp_info.time_out = INFINITE;
+ hdcp_info.auth_status = NOT_AUTHENTICATED;
+
+ HDCPPRINTK("HDCP ftn. Start!!\n");
+
+ hdcp_protocol_status = 1;
+
+ if (!read_bcaps()) {
+ HDCPPRINTK("can't read ddc port!\n");
+ __s5p_hdcp_reset();
+ }
+
+ /* for av mute */
+ writel(DO_NOT_TRANSMIT, hdmi_base + S5P_GCP_CON);
+
+ /*
+ * 1-1. set hdmi status enable reg.
+ * Update_Ri_int_en should be enabled after
+ * s/w gets ExchangeKSV_int.
+ */
+ writel(HDCP_STATUS_EN_ALL, hdmi_base + S5P_STATUS_EN);
+
+ /* 1-2. set hdmi hpd reg. */
+ writel(CABLE_PLUGGED, hdmi_base + S5P_HPD);
+
+ /*
+ * 1-3. set hdmi offset & cycle_aa reg.
+ * HDCP memory read cycle count(0x4 is recommanded)
+ */
+ writel(0x00, hdmi_base + S5P_HDCP_OFFSET_TX_0);
+
+ writel(0xA0, hdmi_base + S5P_HDCP_OFFSET_TX_1);
+
+ writel(0x00, hdmi_base + S5P_HDCP_OFFSET_TX_2);
+
+ writel(0x00, hdmi_base + S5P_HDCP_OFFSET_TX_3);
+
+ writel(0x04, hdmi_base + S5P_HDCP_CYCLE_AA);
+
+ /* 2. set aes_data_size & haes_con reg. */
+ start_decrypting(hdcp_key, 288);
+
+ /*
+ * 3. set hdcp control reg.
+ * Disable advance cipher option, Enable CP(Content Protection),
+ * Disable time-out (This bit is only available in a REPEATER)
+ * Disable XOR shift,Disable Pj port update,Use external key
+ */
+ sfr_val = 0;
+
+ sfr_val |= CP_DESIRED_EN;
+
+ writel(sfr_val, hdmi_base + S5P_HDCP_CTRL);
+
+ hdcp_info.hdcp_enable = true;
+
+ HDCPPRINTK("\tSTATUS \t0x%08x\n", readl(hdmi_base + S5P_STATUS));
+
+ HDCPPRINTK("\tSTATUS_EN \t0x%08x\n", readl(hdmi_base + S5P_STATUS_EN));
+
+ HDCPPRINTK("\tHPD \t0x%08x\n", readl(hdmi_base + S5P_HPD));
+
+ HDCPPRINTK("\tHDCP_CTRL \t0x%08x\n", readl(hdmi_base + S5P_HDCP_CTRL));
+
+ HDCPPRINTK("\tMODE_SEL \t0x%08x\n", readl(hdmi_base + S5P_MODE_SEL));
+
+ HDCPPRINTK("\tENC_EN \t0x%08x\n", readl(hdmi_base + S5P_ENC_EN));
+
+ HDCPPRINTK("\tHDMI_CON_0 \t0x%08x\n",
+ readl(hdmi_base + S5P_HDMI_CON_0));
+
+
+ return true;
+}
+
+
+static void bksv_start_bh(void)
+{
+ bool ret = false;
+
+ HDCPPRINTK("HDCP_EVENT_READ_BKSV_START bh\n");
+
+ hdcp_info.auth_status = RECEIVER_READ_READY;
+
+ ret = read_bcaps();
+
+ if (!ret) {
+
+ ret = try_read_receiver();
+
+ if (!ret) {
+ HDCPPRINTK("Can't read bcaps!! retry failed!!\n"
+ "\t\t\t\thdcp ftn. will be stopped\n");
+
+ __s5p_stop_hdcp();
+ return;
+ }
+ }
+
+ hdcp_info.auth_status = BCAPS_READ_DONE;
+
+ ret = read_bksv();
+
+ if (!ret) {
+ HDCPPRINTK("Can't read bksv!!"
+ "hdcp ftn. will be reset\n");
+
+ __s5p_stop_hdcp();
+ return;
+ }
+
+ hdcp_info.auth_status = BKSV_READ_DONE;
+
+ HDCPPRINTK("authentication status : bksv is done (0x%08x)\n",
+ hdcp_info.auth_status);
+}
+
+static void second_auth_start_bh(void)
+{
+ u8 count = 0;
+ bool ret = false;
+
+ int ret_err;
+
+ u32 bcaps;
+
+ HDCPPRINTK("HDCP_EVENT_SECOND_AUTH_START bh\n");
+
+ ret = read_bcaps();
+
+ if (!ret) {
+
+ ret = try_read_receiver();
+
+ if (!ret) {
+
+ HDCPPRINTK("Can't read bcaps!! retry failed!!\n"
+ "\t\t\t\thdcp ftn. will be stopped\n");
+
+ __s5p_stop_hdcp();
+ return;
+ }
+
+ }
+
+ bcaps = readl(hdmi_base + S5P_HDCP_BCAPS);
+
+ bcaps &= (KSV_FIFO_READY);
+
+ if (!bcaps) {
+
+ HDCPPRINTK("ksv fifo is not ready\n");
+
+ do {
+ count++;
+
+ ret = read_bcaps();
+
+ if (!ret) {
+
+ ret = try_read_receiver();
+
+ if (!ret)
+ __s5p_stop_hdcp();
+
+ return;
+
+ }
+
+ bcaps = readl(hdmi_base + S5P_HDCP_BCAPS);
+
+ bcaps &= (KSV_FIFO_READY);
+
+ if (bcaps) {
+ HDCPPRINTK("bcaps retries : %d\n", count);
+ break;
+ }
+
+ mdelay(100);
+
+ if (!hdcp_info.hdcp_enable) {
+
+ __s5p_stop_hdcp();
+
+ return;
+
+ }
+
+ } while (count <= 50);
+
+ /* wait times exceeded 5 seconds */
+ if (count > 50) {
+
+ hdcp_info.time_out = INFINITE;
+
+ /*
+ * time-out (This bit is only available in a REPEATER)
+ */
+ writel(readl(hdmi_base + S5P_HDCP_CTRL) | 0x1 << 2,
+ hdmi_base + S5P_HDCP_CTRL);
+
+ __s5p_hdcp_reset();
+
+ return;
+ }
+ }
+
+ HDCPPRINTK("ksv fifo ready\n");
+
+ ret_err = check_repeater();
+
+ if (ret_err == true) {
+ u32 flag;
+
+ hdcp_info.auth_status = SECOND_AUTHENTICATION_DONE;
+ HDCPPRINTK("second authentication done!!\n");
+
+ flag = readb(hdmi_base + S5P_STATUS);
+ HDCPPRINTK("hdcp state : %s authenticated!!\n",
+ flag & AUTHENTICATED ? "" : "not not");
+
+
+ start_encryption();
+ } else if (ret_err == false) {
+ /* i2c error */
+ HDCPPRINTK("repeater check error!!\n");
+ __s5p_hdcp_reset();
+ } else {
+ if (ret_err == REPEATER_ILLEGAL_DEVICE_ERROR) {
+ /*
+ * No need to start the HDCP
+ * in case of invalid KSV (revocation case)
+ */
+ HDCPPRINTK("illegal dev. error!!\n");
+
+ __s5p_stop_hdcp();
+ } else {
+ /*
+ * MAX_CASCADE_EXCEEDED_ERROR
+ * MAX_DEVS_EXCEEDED_ERROR
+ */
+ HDCPPRINTK("repeater check error(MAX_EXCEEDED)!!\n");
+ __s5p_hdcp_reset();
+ }
+ }
+}
+
+static bool write_aksv_start_bh(void)
+{
+ bool ret = false;
+
+ HDCPPRINTK("HDCP_EVENT_WRITE_AKSV_START bh\n");
+
+ if (hdcp_info.auth_status != BKSV_READ_DONE) {
+ HDCPPRINTK("bksv is not ready!!\n");
+ return false;
+ }
+
+ ret = write_ainfo();
+
+ if (!ret)
+ return false;
+
+ HDCPPRINTK("ainfo write done!!\n");
+
+ ret = write_an();
+
+ if (!ret)
+ return false;
+
+ hdcp_info.auth_status = AN_WRITE_DONE;
+
+ HDCPPRINTK("an write done!!\n");
+
+ ret = write_aksv();
+
+ if (!ret)
+ return false;
+
+ /*
+ * Wait for 100ms. Transmitter must not read
+ * Ro' value sooner than 100ms after writing
+ * Aksv
+ */
+ mdelay(100);
+
+ hdcp_info.auth_status = AKSV_WRITE_DONE;
+
+ HDCPPRINTK("aksv write done!!\n");
+
+ return ret;
+}
+
+static bool check_ri_start_bh(void)
+{
+ bool ret = false;
+
+
+ HDCPPRINTK("HDCP_EVENT_CHECK_RI_START bh\n");
+
+ if (hdcp_info.auth_status == AKSV_WRITE_DONE ||
+ hdcp_info.auth_status == FIRST_AUTHENTICATION_DONE ||
+ hdcp_info.auth_status == SECOND_AUTHENTICATION_DONE) {
+
+ ret = compare_r_val();
+
+ if (ret) {
+
+ if (hdcp_info.auth_status == AKSV_WRITE_DONE) {
+ /*
+ * Check whether HDMI receiver is
+ * repeater or not
+ */
+ if (hdcp_info.is_repeater)
+ hdcp_info.auth_status
+ = SECOND_AUTHENTICATION_RDY;
+ else {
+ hdcp_info.auth_status
+ = FIRST_AUTHENTICATION_DONE;
+ start_encryption();
+ }
+ }
+
+ } else {
+
+ HDCPPRINTK("authentication reset\n");
+
+ __s5p_hdcp_reset();
+ }
+
+ HDCPPRINTK("auth_status = 0x%08x\n",
+
+ hdcp_info.auth_status);
+
+
+ return true;
+ }
+
+ HDCPPRINTK("aksv_write or first/second"
+
+ " authentication is not done\n");
+
+ return false;
+}
+
+/*
+ * bottom half for hdmi interrupt
+ *
+ */
+static void hdcp_work(void *arg)
+{
+
+ /*
+ * I2C int. was occurred
+ * for reading Bksv and Bcaps
+ */
+
+ if (hdcp_info.event & (1 << HDCP_EVENT_READ_BKSV_START)) {
+
+ bksv_start_bh();
+
+ /* clear event */
+ hdcp_info.event &= ~(1 << HDCP_EVENT_READ_BKSV_START);
+ }
+
+ /*
+ * Watchdog timer int. was occurred
+ * for checking repeater
+ */
+ if (hdcp_info.event & (1 << HDCP_EVENT_SECOND_AUTH_START)) {
+
+ second_auth_start_bh();
+
+ /* clear event */
+ hdcp_info.event &= ~(1 << HDCP_EVENT_SECOND_AUTH_START);
+ }
+
+ /*
+ * An_Write int. was occurred
+ * for writing Ainfo, An and Aksv
+ */
+ if (hdcp_info.event & (1 << HDCP_EVENT_WRITE_AKSV_START)) {
+
+ write_aksv_start_bh();
+
+ /* clear event */
+ hdcp_info.event &= ~(1 << HDCP_EVENT_WRITE_AKSV_START);
+ }
+
+ /*
+ * Ri int. was occurred
+ * for comparing Ri and Ri'(from HDMI sink)
+ */
+ if (hdcp_info.event & (1 << HDCP_EVENT_CHECK_RI_START)) {
+
+
+ check_ri_start_bh();
+
+ /* clear event */
+ hdcp_info.event &= ~(1 << HDCP_EVENT_CHECK_RI_START);
+ }
+
+}
+
+void __s5p_init_hdcp(bool hpd_status, struct i2c_client *ddc_port)
+{
+
+ HDCPPRINTK("HDCP ftn. Init!!\n");
+
+ hdcp_info.client = ddc_port;
+
+ /* for bh */
+ INIT_WORK(&hdcp_info.work, (work_func_t)hdcp_work);
+
+ init_waitqueue_head(&hdcp_info.waitq);
+
+ /* for dev_dbg err. */
+ spin_lock_init(&hdcp_info.lock);
+
+}
+
+/*
+ * HDCP ISR.
+ * If HDCP IRQ occurs, set hdcp_event and wake up the waitqueue.
+ */
+irqreturn_t __s5p_hdmi_irq(int irq, void *dev_id)
+{
+ u8 flag;
+ u32 event;
+
+ event = 0;
+
+ /* check HDCP Status */
+ flag = readb(hdmi_base + S5P_STATUS);
+ HDCPPRINTK("irq_status : 0x%08x\n", readb(hdmi_base + S5P_STATUS));
+
+ HDCPPRINTK("hdcp state : %s authenticated!!\n",
+ flag & AUTHENTICATED ? "" : "not not");
+
+ spin_lock_irq(&hdcp_info.lock);
+
+ /*
+ * processing interrupt
+ * interrupt processing seq. is firstly set event for workqueue,
+ * and interrupt pending clear. 'flag|' was used for preventing
+ * to clear AUTHEN_ACK.- it caused many problem. be careful.
+ */
+ /* I2C INT */
+
+ if (flag & WTFORACTIVERX_INT_OCCURRED) {
+ event |= (1 << HDCP_EVENT_READ_BKSV_START);
+ writeb(flag | WTFORACTIVERX_INT_OCCURRED,
+ hdmi_base + S5P_STATUS);
+ }
+
+ /* AN INT */
+ if (flag & EXCHANGEKSV_INT_OCCURRED) {
+ event |= (1 << HDCP_EVENT_WRITE_AKSV_START);
+ writeb(flag | EXCHANGEKSV_INT_OCCURRED,
+ hdmi_base + S5P_STATUS);
+ }
+
+ /* RI INT */
+ if (flag & UPDATE_RI_INT_OCCURRED) {
+ event |= (1 << HDCP_EVENT_CHECK_RI_START);
+ writeb(flag | UPDATE_RI_INT_OCCURRED,
+ hdmi_base + S5P_STATUS);
+ }
+
+ /* WATCHDOG INT */
+ if (flag & WATCHDOG_INT_OCCURRED) {
+ event |= (1 << HDCP_EVENT_SECOND_AUTH_START);
+ writeb(flag | WATCHDOG_INT_OCCURRED,
+ hdmi_base + S5P_STATUS);
+ }
+
+ if (!event) {
+ HDCPPRINTK("unknown irq.\n");
+ return IRQ_HANDLED;
+ }
+
+ hdcp_info.event |= event;
+
+ schedule_work(&hdcp_info.work);
+
+ spin_unlock_irq(&hdcp_info.lock);
+
+ return IRQ_HANDLED;
+}
+
+bool __s5p_set_hpd_detection(bool detection, bool hdcp_enabled,
+ struct i2c_client *client)
+{
+ u32 hpd_reg_val = 0;
+
+ /* hdcp_enabled is status of tvout_sys */
+ /*
+ if (hdcp_enabled) {
+ if (detection) {
+ hdcp_info.client = client;
+ __s5p_start_hdcp();
+ } else {
+ hdcp_info.client = NULL;
+ __s5p_stop_hdcp();
+ }
+ } else {
+ */
+
+ if (detection)
+ hpd_reg_val = CABLE_PLUGGED;
+ else
+ hpd_reg_val = CABLE_UNPLUGGED;
+
+
+ writel(hpd_reg_val, hdmi_base + S5P_HPD);
+
+ HDCPPRINTK("HPD status :: 0x%08x\n\r",
+ readl(hdmi_base + S5P_HPD));
+
+ return true;
+}
diff --git a/drivers/media/video/samsung/tv20/s5pc100/hdmi_s5pc100.c b/drivers/media/video/samsung/tv20/s5pc100/hdmi_s5pc100.c
new file mode 100644
index 0000000..8b41b8b
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/s5pc100/hdmi_s5pc100.c
@@ -0,0 +1,1435 @@
+/* linux/drivers/media/video/samsung/tv20/s5pc100/hdmi_s5pc100.c
+ *
+ * hdmi raw ftn file for Samsung TVOut driver
+ *
+ * Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include "tv_out_s5pc100.h"
+
+#include "regs/regs-hdmi.h"
+
+#include "plat/regs-clock.h"
+
+#ifdef COFIG_TVOUT_RAW_DBG
+#define S5P_HDMI_DEBUG 1
+#endif
+
+#ifdef S5P_HDMI_DEBUG
+#define HDMIPRINTK(fmt, args...) \
+ printk(KERN_INFO "\t\t[HDMI] %s: " fmt, __func__ , ## args)
+#else
+#define HDMIPRINTK(fmt, args...)
+#endif
+
+static struct resource *hdmi_mem;
+void __iomem *hdmi_base;
+
+static unsigned short g_hdmi_video_parm_tbl[] = {
+ /* 480P_60, 576P_50, 720P_60, 720P_50, 1080I_60, 1080I_50, VGAP_60*/
+ 138, 144, 370, 700, 280, 720, 160,
+ 525, 625, 750, 750, 562, 562, 525,
+ 45, 49, 30, 30, 22, 22, 45,
+ 525, 625, 750, 750, 1125, 1125, 525,
+ 858, 864, 1650, 1980, 2200, 2640, 800,
+ 1, 1, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 585, 585, 0,
+ 0, 0, 0, 0, 1125, 1125, 0,
+ 14, 10, 108, 438, 86, 526, 14,
+ 76, 74, 148, 478, 130, 570, 110,
+ 1, 1, 0, 0, 0, 0, 1,
+ 15, 10, 10, 10, 7, 7, 12,
+ 9, 5, 5, 5, 2, 2, 10,
+ 0, 0, 0, 0, 569, 569, 0,
+ 0, 0, 0, 0, 564, 564, 0,
+ 0, 0, 0, 0, 1187, 1847, 0,
+ 0, 0, 0, 0, 1187, 1847, 0,
+ 858, 864, 1650, 1980, 2200, 2640, 800
+ 138, 144, 370, 700, 280, 720, 160,
+ 720, 720, 1280, 1280, 1920, 1920, 640,
+ 525, 625, 750, 750, 1125, 1125, 525,
+ 7, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 563, 563, 0,
+ 45, 49, 30, 30, 22, 22, 45,
+ 480, 576, 720, 720, 540, 540, 480,
+ 0, 0, 0, 0, 563, 563, 0,
+ 0, 0, 0, 0, 584, 584, 0,
+ 7, 1, 1, 1, 1, 1, 1,
+ 7, 1, 1, 1, 563, 563, 1,
+ 7, 1, 1, 1, 1, 1, 1,
+ 7, 1, 1, 1, 563, 563, 1
+};
+
+
+
+/*
+* set - set functions are only called under running HDMI
+*/
+void __s5p_hdmi_set_hpd_onoff(bool on_off)
+{
+ HDMIPRINTK("%d\n\r", on_off);
+
+ if (on_off)
+ writel(SW_HPD_PLUGGED, hdmi_base + S5P_HPD);
+ else
+ writel(SW_HPD_UNPLUGGED, hdmi_base + S5P_HPD);
+
+
+ HDMIPRINTK("0x%08x\n\r", readl(hdmi_base + S5P_HPD));
+}
+
+
+void __s5p_hdmi_audio_set_config(enum s5p_tv_audio_codec_type audio_codec)
+{
+
+ u32 data_type = (audio_codec == PCM) ? CONFIG_LINEAR_PCM_TYPE :
+ (audio_codec == AC3) ? CONFIG_NON_LINEAR_PCM_TYPE :
+ 0xff;
+
+ HDMIPRINTK("(%d)\n\r", audio_codec);
+
+ writel(CONFIG_FILTER_2_SAMPLE | data_type
+ | CONFIG_PCPD_MANUAL_SET | CONFIG_WORD_LENGTH_MANUAL_SET
+ | CONFIG_U_V_C_P_REPORT | CONFIG_BURST_SIZE_2
+ | CONFIG_DATA_ALIGN_32BIT
+ , hdmi_base + S5P_SPDIFIN_CONFIG_1);
+ writel(0, hdmi_base + S5P_SPDIFIN_CONFIG_2);
+ HDMIPRINTK("()\n\r");
+}
+
+void __s5p_hdmi_audio_set_acr(u32 sample_rate)
+{
+ u32 value_n = (sample_rate == 32000) ? 4096 :
+ (sample_rate == 44100) ? 6272 :
+ (sample_rate == 88200) ? 12544 :
+ (sample_rate == 176400) ? 25088 :
+ (sample_rate == 48000) ? 6144 :
+ (sample_rate == 96000) ? 12288 :
+ (sample_rate == 192000) ? 24576 : 0;
+
+ u32 cts = (sample_rate == 32000) ? 27000 :
+ (sample_rate == 44100) ? 30000 :
+ (sample_rate == 88200) ? 30000 :
+ (sample_rate == 176400) ? 30000 :
+ (sample_rate == 48000) ? 27000 :
+ (sample_rate == 96000) ? 27000 :
+ (sample_rate == 192000) ? 27000 : 0;
+
+ HDMIPRINTK("(%d)\n\r", sample_rate);
+
+ writel(value_n & 0xff, hdmi_base + S5P_ACR_N0);
+ writel((value_n >> 8) & 0xff, hdmi_base + S5P_ACR_N1);
+ writel((value_n >> 16) & 0xff, hdmi_base + S5P_ACR_N2);
+
+ writel(cts & 0xff, hdmi_base + S5P_ACR_MCTS0);
+ writel((cts >> 8) & 0xff, hdmi_base + S5P_ACR_MCTS1);
+ writel((cts >> 16) & 0xff, hdmi_base + S5P_ACR_MCTS2);
+
+ writel(cts & 0xff, hdmi_base + S5P_ACR_CTS0);
+ writel((cts >> 8) & 0xff, hdmi_base + S5P_ACR_CTS1);
+ writel((cts >> 16) & 0xff, hdmi_base + S5P_ACR_CTS2);
+
+ writel(4, hdmi_base + S5P_ACR_CON);
+
+ HDMIPRINTK("()\n\r");
+}
+
+void __s5p_hdmi_audio_set_asp(void)
+{
+ HDMIPRINTK("()\n\r");
+ writel(0x0, hdmi_base + S5P_ASP_CON);
+ writel(0x0, hdmi_base + S5P_ASP_SP_FLAT);
+
+ writel(1 << 3 | 0, hdmi_base + S5P_ASP_CHCFG0);
+ writel(1 << 3 | 0, hdmi_base + S5P_ASP_CHCFG1);
+ writel(1 << 3 | 0, hdmi_base + S5P_ASP_CHCFG2);
+ writel(1 << 3 | 0, hdmi_base + S5P_ASP_CHCFG3);
+ HDMIPRINTK("()\n\r");
+}
+
+void __s5p_hdmi_audio_clock_enable(void)
+{
+ HDMIPRINTK("()\n\r");
+ writel(0x1, hdmi_base + S5P_SPDIFIN_CLK_CTRL);
+ writel(0x3, hdmi_base + S5P_SPDIFIN_OP_CTRL);
+ HDMIPRINTK("()\n\r");
+}
+
+void __s5p_hdmi_audio_set_repetition_time(
+ enum s5p_tv_audio_codec_type audio_codec,
+ u32 bits, u32 frame_size_code)
+{
+ u32 wl = 5 << 1 | 1;
+ u32 rpt_cnt = (audio_codec == AC3) ? 1536 * 2 - 1 : 0;
+
+ HDMIPRINTK("()\n\r");
+
+ writel(((rpt_cnt&0xf) << 4) | wl,
+ hdmi_base + S5P_SPDIFIN_USER_VALUE_1);
+ writel((rpt_cnt >> 4)&0xff, hdmi_base + S5P_SPDIFIN_USER_VALUE_2);
+ writel(frame_size_code&0xff, hdmi_base + S5P_SPDIFIN_USER_VALUE_3);
+ writel((frame_size_code >> 8)&0xff,
+ hdmi_base + S5P_SPDIFIN_USER_VALUE_4);
+ HDMIPRINTK("()\n\r");
+}
+
+
+
+void __s5p_hdmi_audio_irq_enable(u32 irq_en)
+{
+ writel(irq_en, hdmi_base + S5P_SPDIFIN_IRQ_MASK);
+}
+
+
+void __s5p_hdmi_audio_set_aui(enum s5p_tv_audio_codec_type audio_codec,
+ u32 sample_rate,
+ u32 bits)
+{
+ u8 sum_of_bits, bytes1, bytes2, bytes3, check_sum;
+ u32 bit_rate;
+ u32 bps = (audio_codec == PCM) ? bits : 16;
+
+ u32 type = (audio_codec == PCM) ? 1 :
+ (audio_codec == AC3) ? 2 : 0;
+ u32 ch = (audio_codec == PCM) ? 1 : 0;
+
+ u32 sample = (sample_rate == 32000) ? 1 :
+ (sample_rate == 44100) ? 2 :
+ (sample_rate == 48000) ? 3 :
+ (sample_rate == 88200) ? 4 :
+ (sample_rate == 96000) ? 5 :
+ (sample_rate == 176400) ? 6 :
+ (sample_rate == 192000) ? 7 : 0;
+
+ u32 bpsType = (bps == 16) ? 1 :
+ (bps == 20) ? 2 :
+ (bps == 24) ? 3 : 0;
+
+ HDMIPRINTK("()\n\r");
+
+ bpsType = (audio_codec == PCM) ? bpsType : 0;
+
+ sum_of_bits = (0x84 + 0x1 + 10);
+
+ bytes1 = (u8)((type << 4) | ch);
+
+ bytes2 = (u8)((sample << 2) | bpsType);
+
+ bit_rate = 256;
+
+ bytes3 = (audio_codec == PCM) ? (u8)0 : (u8)(bit_rate / 8) ;
+
+
+ sum_of_bits += (bytes1 + bytes2 + bytes3);
+ check_sum = 256 - sum_of_bits;
+
+ writel(check_sum , hdmi_base + S5P_AUI_CHECK_SUM);
+ writel(bytes1 , hdmi_base + S5P_AUI_BYTE1);
+ writel(bytes2 , hdmi_base + S5P_AUI_BYTE2);
+ writel(bytes3 , hdmi_base + S5P_AUI_BYTE3);
+ writel(0x00 , hdmi_base + S5P_AUI_BYTE4);
+ writel(0x00 , hdmi_base + S5P_AUI_BYTE5);
+
+
+ writel(2 , hdmi_base + S5P_ACP_CON);
+ writel(1 , hdmi_base + S5P_ACP_TYPE);
+
+ writel(0x10 , hdmi_base + S5P_GCP_BYTE1);
+ writel(0x2 , hdmi_base + S5P_GCP_CON);
+
+ HDMIPRINTK("()\n\r");
+
+}
+
+void __s5p_hdmi_video_set_bluescreen(bool en,
+ u8 cb_b,
+ u8 y_g,
+ u8 cr_r)
+{
+ HDMIPRINTK("%d,%d,%d,%d\n\r", en, cb_b, y_g, cr_r);
+
+ if (en) {
+ writel(SET_BLUESCREEN_0(cb_b), hdmi_base + S5P_BLUE_SCREEN_0);
+ writel(SET_BLUESCREEN_1(y_g), hdmi_base + S5P_BLUE_SCREEN_1);
+ writel(SET_BLUESCREEN_2(cr_r), hdmi_base + S5P_BLUE_SCREEN_2);
+ writel(readl(hdmi_base + S5P_HDMI_CON_0) | BLUE_SCR_EN,
+ hdmi_base + S5P_HDMI_CON_0);
+
+ HDMIPRINTK("HDMI_BLUE_SCREEN0 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_BLUE_SCREEN_0));
+ HDMIPRINTK("HDMI_BLUE_SCREEN1 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_BLUE_SCREEN_1));
+ HDMIPRINTK("HDMI_BLUE_SCREEN2 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_BLUE_SCREEN_2));
+ } else {
+ writel(readl(hdmi_base + S5P_HDMI_CON_0)&~BLUE_SCR_EN,
+ hdmi_base + S5P_HDMI_CON_0);
+ }
+
+ HDMIPRINTK("HDMI_CON0 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_HDMI_CON_0));
+}
+
+
+/*
+* initialization - iniization functions are only called under stopping HDMI
+*/
+enum s5p_tv_hdmi_err __s5p_hdmi_init_spd_infoframe(
+ enum s5p_hdmi_transmit trans_type,
+ u8 *spd_header,
+ u8 *spd_data)
+{
+ HDMIPRINTK("%d,%d,%d\n\r", (u32)trans_type,
+ (u32)spd_header,
+ (u32)spd_data);
+
+ switch (trans_type) {
+
+ case HDMI_DO_NOT_TANS:
+ writel(SPD_TX_CON_NO_TRANS, hdmi_base + S5P_SPD_CON);
+ break;
+
+ case HDMI_TRANS_ONCE:
+ writel(SPD_TX_CON_TRANS_ONCE, hdmi_base + S5P_SPD_CON);
+ break;
+
+ case HDMI_TRANS_EVERY_SYNC:
+ writel(SPD_TX_CON_TRANS_EVERY_VSYNC, hdmi_base + S5P_SPD_CON);
+ break;
+
+ default:
+ HDMIPRINTK(" invalid out_mode parameter(%d)\n\r", trans_type);
+ return S5P_TV_HDMI_ERR_INVALID_PARAM;
+ break;
+ }
+
+ writel(SET_SPD_HEADER(*(spd_header)), hdmi_base + S5P_SPD_HEADER0);
+
+ writel(SET_SPD_HEADER(*(spd_header + 1)) , hdmi_base + S5P_SPD_HEADER1);
+ writel(SET_SPD_HEADER(*(spd_header + 2)) , hdmi_base + S5P_SPD_HEADER2);
+
+ writel(SET_SPD_DATA(*(spd_data)), hdmi_base + S5P_SPD_DATA0);
+ writel(SET_SPD_DATA(*(spd_data + 1)) , hdmi_base + S5P_SPD_DATA1);
+ writel(SET_SPD_DATA(*(spd_data + 2)) , hdmi_base + S5P_SPD_DATA2);
+ writel(SET_SPD_DATA(*(spd_data + 3)) , hdmi_base + S5P_SPD_DATA3);
+ writel(SET_SPD_DATA(*(spd_data + 4)) , hdmi_base + S5P_SPD_DATA4);
+ writel(SET_SPD_DATA(*(spd_data + 5)) , hdmi_base + S5P_SPD_DATA5);
+ writel(SET_SPD_DATA(*(spd_data + 6)) , hdmi_base + S5P_SPD_DATA6);
+ writel(SET_SPD_DATA(*(spd_data + 7)) , hdmi_base + S5P_SPD_DATA7);
+ writel(SET_SPD_DATA(*(spd_data + 8)) , hdmi_base + S5P_SPD_DATA8);
+ writel(SET_SPD_DATA(*(spd_data + 9)) , hdmi_base + S5P_SPD_DATA9);
+ writel(SET_SPD_DATA(*(spd_data + 10)) , hdmi_base + S5P_SPD_DATA10);
+ writel(SET_SPD_DATA(*(spd_data + 11)) , hdmi_base + S5P_SPD_DATA11);
+ writel(SET_SPD_DATA(*(spd_data + 12)) , hdmi_base + S5P_SPD_DATA12);
+ writel(SET_SPD_DATA(*(spd_data + 13)) , hdmi_base + S5P_SPD_DATA13);
+ writel(SET_SPD_DATA(*(spd_data + 14)) , hdmi_base + S5P_SPD_DATA14);
+ writel(SET_SPD_DATA(*(spd_data + 15)) , hdmi_base + S5P_SPD_DATA15);
+ writel(SET_SPD_DATA(*(spd_data + 16)) , hdmi_base + S5P_SPD_DATA16);
+ writel(SET_SPD_DATA(*(spd_data + 17)) , hdmi_base + S5P_SPD_DATA17);
+ writel(SET_SPD_DATA(*(spd_data + 18)) , hdmi_base + S5P_SPD_DATA18);
+ writel(SET_SPD_DATA(*(spd_data + 19)) , hdmi_base + S5P_SPD_DATA19);
+ writel(SET_SPD_DATA(*(spd_data + 20)) , hdmi_base + S5P_SPD_DATA20);
+ writel(SET_SPD_DATA(*(spd_data + 21)) , hdmi_base + S5P_SPD_DATA21);
+ writel(SET_SPD_DATA(*(spd_data + 22)) , hdmi_base + S5P_SPD_DATA22);
+ writel(SET_SPD_DATA(*(spd_data + 23)) , hdmi_base + S5P_SPD_DATA23);
+ writel(SET_SPD_DATA(*(spd_data + 24)) , hdmi_base + S5P_SPD_DATA24);
+ writel(SET_SPD_DATA(*(spd_data + 25)) , hdmi_base + S5P_SPD_DATA25);
+ writel(SET_SPD_DATA(*(spd_data + 26)) , hdmi_base + S5P_SPD_DATA26);
+ writel(SET_SPD_DATA(*(spd_data + 27)) , hdmi_base + S5P_SPD_DATA27);
+
+ HDMIPRINTK("SPD_CON = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_CON));
+ HDMIPRINTK("SPD_HEADER0 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_HEADER0));
+ HDMIPRINTK("SPD_HEADER1 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_HEADER1));
+ HDMIPRINTK("SPD_HEADER2 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_HEADER2));
+ HDMIPRINTK("SPD_DATA0 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA0));
+ HDMIPRINTK("SPD_DATA1 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA1));
+ HDMIPRINTK("SPD_DATA2 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA2));
+ HDMIPRINTK("SPD_DATA3 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA3));
+ HDMIPRINTK("SPD_DATA4 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA4));
+ HDMIPRINTK("SPD_DATA5 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA5));
+ HDMIPRINTK("SPD_DATA6 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA6));
+ HDMIPRINTK("SPD_DATA7 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA7));
+ HDMIPRINTK("SPD_DATA8 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA8));
+ HDMIPRINTK("SPD_DATA9 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA9));
+ HDMIPRINTK("SPD_DATA10 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA10));
+ HDMIPRINTK("SPD_DATA11 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA11));
+ HDMIPRINTK("SPD_DATA12 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA12));
+ HDMIPRINTK("SPD_DATA13 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA13));
+ HDMIPRINTK("SPD_DATA14 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA14));
+ HDMIPRINTK("SPD_DATA15 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA15));
+ HDMIPRINTK("SPD_DATA16 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA16));
+ HDMIPRINTK("SPD_DATA17 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA17));
+ HDMIPRINTK("SPD_DATA18 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA18));
+ HDMIPRINTK("SPD_DATA19 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA19));
+ HDMIPRINTK("SPD_DATA20 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA20));
+ HDMIPRINTK("SPD_DATA21 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA21));
+ HDMIPRINTK("SPD_DATA22 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA22));
+ HDMIPRINTK("SPD_DATA23 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA23));
+ HDMIPRINTK("SPD_DATA24 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA24));
+ HDMIPRINTK("SPD_DATA25 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA25));
+ HDMIPRINTK("SPD_DATA26 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA26));
+ HDMIPRINTK("SPD_DATA27 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA27));
+
+ return HDMI_NO_ERROR;
+}
+
+void __s5p_hdmi_init_hpd_onoff(bool on_off)
+{
+ HDMIPRINTK("%d\n\r", on_off);
+ __s5p_hdmi_set_hpd_onoff(on_off);
+ HDMIPRINTK("0x%08x\n\r", readl(hdmi_base + S5P_HPD));
+}
+
+enum s5p_tv_hdmi_err __s5p_hdmi_audio_init(
+ enum s5p_tv_audio_codec_type audio_codec,
+ u32 sample_rate, u32 bits, u32 frame_size_code)
+{
+ __s5p_hdmi_audio_set_config(audio_codec);
+ __s5p_hdmi_audio_set_repetition_time(audio_codec, bits,
+ frame_size_code);
+ __s5p_hdmi_audio_irq_enable(IRQ_BUFFER_OVERFLOW_ENABLE);
+ __s5p_hdmi_audio_clock_enable();
+ __s5p_hdmi_audio_set_asp();
+ __s5p_hdmi_audio_set_acr(sample_rate);
+ __s5p_hdmi_audio_set_aui(audio_codec, sample_rate, bits);
+
+ return HDMI_NO_ERROR;
+}
+
+enum s5p_tv_hdmi_err __s5p_hdmi_video_init_display_mode(
+ enum s5p_tv_disp_mode disp_mode,
+ enum s5p_tv_o_mode out_mode)
+{
+ enum s5p_tv_hdmi_disp_mode hdmi_disp_num;
+
+ HDMIPRINTK("%d,%d\n\r", disp_mode, out_mode);
+
+ switch (disp_mode) {
+
+ case TVOUT_480P_60_16_9:
+
+ case TVOUT_480P_60_4_3:
+
+ case TVOUT_576P_50_16_9:
+
+ case TVOUT_576P_50_4_3:
+
+ case TVOUT_720P_60:
+
+ case TVOUT_720P_50:
+ writel(INT_PRO_MODE_PROGRESSIVE, hdmi_base + S5P_INT_PRO_MODE);
+ break;
+
+ default:
+ HDMIPRINTK("invalid disp_mode parameter(%d)\n\r", disp_mode);
+ return S5P_TV_HDMI_ERR_INVALID_PARAM;
+ break;
+ }
+
+ switch (disp_mode) {
+
+ case TVOUT_480P_60_16_9:
+
+ case TVOUT_480P_60_4_3:
+ hdmi_disp_num = S5P_TV_HDMI_DISP_MODE_480P_60;
+ break;
+
+ case TVOUT_576P_50_16_9:
+
+ case TVOUT_576P_50_4_3:
+ hdmi_disp_num = S5P_TV_HDMI_DISP_MODE_576P_50;
+ break;
+
+ case TVOUT_720P_60:
+ hdmi_disp_num = S5P_TV_HDMI_DISP_MODE_720P_60;
+ break;
+
+ case TVOUT_720P_50:
+ hdmi_disp_num = S5P_TV_HDMI_DISP_MODE_720P_50;
+ break;
+
+ default:
+ HDMIPRINTK(" invalid disp_mode parameter(%d)\n\r", disp_mode);
+ return S5P_TV_HDMI_ERR_INVALID_PARAM;
+ break;
+ }
+
+ switch (out_mode) {
+
+ case TVOUT_OUTPUT_HDMI:
+ writel(PX_LMT_CTRL_BYPASS, hdmi_base + S5P_HDMI_CON_1);
+ writel(VID_PREAMBLE_EN | GUARD_BAND_EN,
+ hdmi_base + S5P_HDMI_CON_2);
+ writel(HDMI_MODE_EN | DVI_MODE_DIS, hdmi_base + S5P_MODE_SEL);
+ break;
+
+ default:
+ HDMIPRINTK("invalid out_mode parameter(%d)\n\r", out_mode);
+ return S5P_TV_HDMI_ERR_INVALID_PARAM;
+ break;
+ }
+
+ writel(0x2b, hdmi_base + S5P_VACT_ST_MG);
+
+ writel(0x30, hdmi_base + S5P_VACT_END_MG);
+
+ writel(SET_H_BLANK_L(g_hdmi_video_parm_tbl
+ [H_BLANK*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+ hdmi_base + S5P_H_BLANK_0);
+ writel(SET_H_BLANK_H(g_hdmi_video_parm_tbl
+ [H_BLANK*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+ hdmi_base + S5P_H_BLANK_1);
+
+ writel(SET_V2_BLANK_L(g_hdmi_video_parm_tbl
+ [V2_BLANK*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+ hdmi_base + S5P_V_BLANK_0);
+ writel(SET_V2_BLANK_H(g_hdmi_video_parm_tbl
+ [V2_BLANK*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]) |
+ SET_V1_BLANK_L(g_hdmi_video_parm_tbl
+ [V1_BLANK*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+ hdmi_base + S5P_V_BLANK_1);
+ writel(SET_V1_BLANK_H(g_hdmi_video_parm_tbl
+ [V1_BLANK*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+ hdmi_base + S5P_V_BLANK_2);
+
+ writel(SET_V_LINE_L(g_hdmi_video_parm_tbl
+ [V_LINE*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+ hdmi_base + S5P_H_V_LINE_0);
+ writel(SET_V_LINE_H(g_hdmi_video_parm_tbl
+ [V_LINE*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]) |
+ SET_H_LINE_L(g_hdmi_video_parm_tbl
+ [H_LINE*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+ hdmi_base + S5P_H_V_LINE_1);
+ writel(SET_H_LINE_H(g_hdmi_video_parm_tbl
+ [H_LINE*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+ hdmi_base + S5P_H_V_LINE_2);
+
+ writel(g_hdmi_video_parm_tbl
+ [VSYNC_POL*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num],
+ hdmi_base + S5P_SYNC_MODE);
+
+ writel(0xfd, hdmi_base + S5P_SEND_PER_START0);
+ writel(0x01, hdmi_base + S5P_SEND_PER_START1);
+ writel(0x0d, hdmi_base + S5P_SEND_PER_END0);
+ writel(0x3a, hdmi_base + S5P_SEND_PER_END1);
+ writel(0x08, hdmi_base + S5P_SEND_PER_END2);
+
+ writel(SET_V_BOT_ST_L(g_hdmi_video_parm_tbl
+ [V_BOT_ST*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+ hdmi_base + S5P_V_BLANK_F_0);
+ writel(SET_V_BOT_ST_H(g_hdmi_video_parm_tbl
+ [V_BOT_ST*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]) |
+ SET_V_BOT_END_L(g_hdmi_video_parm_tbl
+ [V_BOT_END*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+ hdmi_base + S5P_V_BLANK_F_1);
+ writel(SET_V_BOT_END_H(g_hdmi_video_parm_tbl
+ [V_BOT_END*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+ hdmi_base + S5P_V_BLANK_F_2);
+
+
+ writel(SET_HSYNC_START_L(g_hdmi_video_parm_tbl
+ [HSYNC_START*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+ hdmi_base + S5P_H_SYNC_GEN_0);
+ writel(SET_HSYNC_START_H(g_hdmi_video_parm_tbl
+ [HSYNC_START*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]) |
+ SET_HSYNC_END_L(g_hdmi_video_parm_tbl
+ [HSYNC_END*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+ hdmi_base + S5P_H_SYNC_GEN_1);
+ writel(SET_HSYNC_END_H(g_hdmi_video_parm_tbl
+ [HSYNC_END*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]) |
+ ((g_hdmi_video_parm_tbl
+ [HSYNC_POL*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]) ?
+ SET_HSYNC_POL_ACT_LOW : SET_HSYNC_POL_ACT_HIGH) ,
+ hdmi_base + S5P_H_SYNC_GEN_2);
+
+
+ writel(SET_VSYNC_T_END_L(g_hdmi_video_parm_tbl
+ [VSYNC_T_END*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+ hdmi_base + S5P_V_SYNC_GEN_1_0);
+ writel(SET_VSYNC_T_END_H(g_hdmi_video_parm_tbl
+ [VSYNC_T_END*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]) |
+ SET_VSYNC_T_ST_L(g_hdmi_video_parm_tbl
+ [VSYNC_T_START*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+
+ hdmi_base + S5P_V_SYNC_GEN_1_1);
+ writel(SET_VSYNC_T_ST_H(g_hdmi_video_parm_tbl
+ [VSYNC_T_START*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+ hdmi_base + S5P_V_SYNC_GEN_1_2);
+
+ writel(SET_VSYNC_B_END_L(g_hdmi_video_parm_tbl
+ [VSYNC_B_END*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+ hdmi_base + S5P_V_SYNC_GEN_2_0);
+ writel(SET_VSYNC_B_END_H(g_hdmi_video_parm_tbl
+ [VSYNC_B_END*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]) |
+ SET_VSYNC_B_ST_L(g_hdmi_video_parm_tbl
+ [VSYNC_B_START*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+ hdmi_base + S5P_V_SYNC_GEN_2_1);
+ writel(SET_VSYNC_B_ST_H(g_hdmi_video_parm_tbl
+ [VSYNC_B_START*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+ hdmi_base + S5P_V_SYNC_GEN_2_2);
+
+ writel(SET_VSYNC_H_POST_END_L(g_hdmi_video_parm_tbl
+ [VSYNC_h_POS_END*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+ hdmi_base + S5P_V_SYNC_GEN_3_0);
+
+ writel(SET_VSYNC_H_POST_END_H(g_hdmi_video_parm_tbl
+ [VSYNC_h_POS_END*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]) |
+ SET_VSYNC_H_POST_ST_L(g_hdmi_video_parm_tbl
+ [VSYNC_h_POS_START*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+ hdmi_base + S5P_V_SYNC_GEN_3_1);
+
+ writel(SET_VSYNC_H_POST_ST_H(g_hdmi_video_parm_tbl
+ [VSYNC_h_POS_START*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+ hdmi_base + S5P_V_SYNC_GEN_3_2);
+
+
+ writel(0 , hdmi_base + S5P_TG_CMD);
+ writel(SET_TG_H_FSZ_L(g_hdmi_video_parm_tbl
+ [TG_H_FSZ*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]) ,
+ hdmi_base + S5P_TG_H_FSZ_L);
+ writel(SET_TG_H_FSZ_H(g_hdmi_video_parm_tbl
+ [TG_H_FSZ*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]) ,
+ hdmi_base + S5P_TG_H_FSZ_H);
+
+ writel(SET_TG_HACT_ST_L(g_hdmi_video_parm_tbl
+ [TG_HACT_START*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]) ,
+ hdmi_base + S5P_TG_HACT_ST_L);
+ writel(SET_TG_HACT_ST_H(g_hdmi_video_parm_tbl
+ [TG_HACT_START*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+ hdmi_base + S5P_TG_HACT_ST_H);
+ writel(SET_TG_HACT_SZ_L(g_hdmi_video_parm_tbl
+ [TG_HACT_SZ*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+ hdmi_base + S5P_TG_HACT_SZ_L);
+ writel(SET_TG_HACT_SZ_H(g_hdmi_video_parm_tbl
+ [TG_HACT_SZ*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+ hdmi_base + S5P_TG_HACT_SZ_H);
+
+
+ writel(SET_TG_V_FSZ_L(g_hdmi_video_parm_tbl
+ [TG_V_FSZ*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+ hdmi_base + S5P_TG_V_FSZ_L);
+ writel(SET_TG_V_FSZ_H(g_hdmi_video_parm_tbl
+ [TG_V_FSZ*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+ hdmi_base + S5P_TG_V_FSZ_H);
+ writel(SET_TG_VSYNC_L(g_hdmi_video_parm_tbl
+ [TG_VSYNC*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+ hdmi_base + S5P_TG_VSYNC_L);
+ writel(SET_TG_VSYNC_H(g_hdmi_video_parm_tbl
+ [TG_VSYNC*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+ hdmi_base + S5P_TG_VSYNC_H);
+ writel(SET_TG_VSYNC2_L(g_hdmi_video_parm_tbl
+ [TG_VSYNC2*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+ hdmi_base + S5P_TG_VSYNC2_L);
+ writel(SET_TG_VSYNC2_H(g_hdmi_video_parm_tbl
+ [TG_VSYNC2*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+ hdmi_base + S5P_TG_VSYNC2_H);
+
+ writel(SET_TG_VACT_ST_L(g_hdmi_video_parm_tbl
+ [TG_VACT_START*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+ hdmi_base + S5P_TG_VACT_ST_L);
+ writel(SET_TG_VACT_ST_H(g_hdmi_video_parm_tbl
+ [TG_VACT_START*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+ hdmi_base + S5P_TG_VACT_ST_H);
+ writel(SET_TG_VACT_SZ_L(g_hdmi_video_parm_tbl
+ [TG_VACT_SZ*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+ hdmi_base + S5P_TG_VACT_SZ_L);
+ writel(SET_TG_VACT_SZ_H(g_hdmi_video_parm_tbl
+ [TG_VACT_SZ*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+ hdmi_base + S5P_TG_VACT_SZ_H);
+
+ writel(SET_TG_FIELD_CHG_L(g_hdmi_video_parm_tbl
+ [TG_FIELD_CHG*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+ hdmi_base + S5P_TG_FIELD_CHG_L);
+ writel(SET_TG_FIELD_CHG_H(g_hdmi_video_parm_tbl
+ [TG_FIELD_CHG*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+ hdmi_base + S5P_TG_FIELD_CHG_H);
+
+ writel(SET_TG_VACT_ST2_L(g_hdmi_video_parm_tbl
+ [TG_VACT_START2*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+ hdmi_base + S5P_TG_VACT_ST2_L);
+ writel(SET_TG_VACT_ST2_H(g_hdmi_video_parm_tbl
+ [TG_VACT_START2*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+ hdmi_base + S5P_TG_VACT_ST2_H);
+
+ writel(SET_TG_VSYNC_TOP_HDMI_L(g_hdmi_video_parm_tbl
+ [TG_VSYNC_TOP_HDMI*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+ hdmi_base + S5P_TG_VSYNC_TOP_HDMI_L);
+ writel(SET_TG_VSYNC_TOP_HDMI_H(g_hdmi_video_parm_tbl
+ [TG_VSYNC_TOP_HDMI*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+ hdmi_base + S5P_TG_VSYNC_TOP_HDMI_H);
+ writel(SET_TG_VSYNC_BOT_HDMI_L(g_hdmi_video_parm_tbl
+ [TG_VSYNC_BOTTOM_HDMI*S5P_TV_HDMI_DISP_MODE_NUM +
+ hdmi_disp_num]),
+ hdmi_base + S5P_TG_VSYNC_BOT_HDMI_L);
+ writel(SET_TG_VSYNC_BOT_HDMI_H(g_hdmi_video_parm_tbl
+ [TG_VSYNC_BOTTOM_HDMI*S5P_TV_HDMI_DISP_MODE_NUM +
+ hdmi_disp_num]),
+ hdmi_base + S5P_TG_VSYNC_BOT_HDMI_H);
+
+ writel(SET_TG_FIELD_TOP_HDMI_L(g_hdmi_video_parm_tbl
+ [TG_FIELD_TOP_HDMI*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+ hdmi_base + S5P_TG_FIELD_TOP_HDMI_L);
+ writel(SET_TG_FIELD_TOP_HDMI_H(g_hdmi_video_parm_tbl
+ [TG_FIELD_TOP_HDMI*S5P_TV_HDMI_DISP_MODE_NUM + hdmi_disp_num]),
+ hdmi_base + S5P_TG_FIELD_TOP_HDMI_H);
+ writel(SET_TG_FIELD_BOT_HDMI_L(g_hdmi_video_parm_tbl
+ [TG_FIELD_BOTTOM_HDMI*S5P_TV_HDMI_DISP_MODE_NUM +
+ hdmi_disp_num]),
+ hdmi_base + S5P_TG_FIELD_BOT_HDMI_L);
+ writel(SET_TG_FIELD_BOT_HDMI_H(g_hdmi_video_parm_tbl
+ [TG_FIELD_BOTTOM_HDMI*S5P_TV_HDMI_DISP_MODE_NUM +
+ hdmi_disp_num]),
+ hdmi_base + S5P_TG_FIELD_BOT_HDMI_H);
+
+ HDMIPRINTK("HDMI_CON_1 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_HDMI_CON_1));
+ HDMIPRINTK("HDMI_CON_2 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_HDMI_CON_2));
+ HDMIPRINTK("MODE_SEL = 0x%08x \n\r",
+ readl(hdmi_base + S5P_MODE_SEL));
+ HDMIPRINTK("BLUE_SCREEN_0 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_BLUE_SCREEN_0));
+ HDMIPRINTK("BLUE_SCREEN_1 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_BLUE_SCREEN_1));
+ HDMIPRINTK("BLUE_SCREEN_2 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_BLUE_SCREEN_2));
+ HDMIPRINTK("VBI_ST_MG = 0x%08x \n\r",
+ readl(hdmi_base + S5P_VBI_ST_MG));
+ HDMIPRINTK("VBI_END_MG = 0x%08x \n\r",
+ readl(hdmi_base + S5P_VBI_END_MG));
+ HDMIPRINTK("VACT_ST_MG = 0x%08x \n\r",
+ readl(hdmi_base + S5P_VACT_ST_MG));
+ HDMIPRINTK("VACT_END_MG = 0x%08x \n\r",
+ readl(hdmi_base + S5P_VACT_END_MG));
+ HDMIPRINTK("H_BLANK_0 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_H_BLANK_0));
+ HDMIPRINTK("H_BLANK_1 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_H_BLANK_1));
+ HDMIPRINTK("V_BLANK_0 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_V_BLANK_0));
+ HDMIPRINTK("V_BLANK_1 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_V_BLANK_1));
+ HDMIPRINTK("V_BLANK_2 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_V_BLANK_2));
+ HDMIPRINTK("H_V_LINE_0 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_H_V_LINE_0));
+ HDMIPRINTK("H_V_LINE_1 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_H_V_LINE_1));
+ HDMIPRINTK("H_V_LINE_2 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_H_V_LINE_2));
+ HDMIPRINTK("SYNC_MODE = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SYNC_MODE));
+ HDMIPRINTK("INT_PRO_MODE = 0x%08x \n\r",
+ readl(hdmi_base + S5P_INT_PRO_MODE));
+ HDMIPRINTK("SEND_PER_START0 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SEND_PER_START0));
+ HDMIPRINTK("SEND_PER_START1 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SEND_PER_START1));
+ HDMIPRINTK("SEND_PER_END0 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SEND_PER_END0));
+ HDMIPRINTK("SEND_PER_END1 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SEND_PER_END1));
+ HDMIPRINTK("SEND_PER_END2 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SEND_PER_END2));
+ HDMIPRINTK("V_BLANK_F_0 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_V_BLANK_F_0));
+ HDMIPRINTK("V_BLANK_F_1 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_V_BLANK_F_1));
+ HDMIPRINTK("V_BLANK_F_2 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_V_BLANK_F_2));
+ HDMIPRINTK("H_SYNC_GEN_0 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_H_SYNC_GEN_0));
+ HDMIPRINTK("H_SYNC_GEN_1 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_H_SYNC_GEN_1));
+ HDMIPRINTK("H_SYNC_GEN_2 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_H_SYNC_GEN_2));
+ HDMIPRINTK("V_SYNC_GEN_1_0 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_V_SYNC_GEN_1_0));
+ HDMIPRINTK("V_SYNC_GEN_1_1 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_V_SYNC_GEN_1_1));
+ HDMIPRINTK("V_SYNC_GEN_1_2 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_V_SYNC_GEN_1_2));
+ HDMIPRINTK("V_SYNC_GEN_2_0 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_V_SYNC_GEN_2_0));
+ HDMIPRINTK("V_SYNC_GEN_2_1 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_V_SYNC_GEN_2_1));
+ HDMIPRINTK("V_SYNC_GEN_2_2 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_V_SYNC_GEN_2_2));
+ HDMIPRINTK("V_SYNC_GEN_3_0 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_V_SYNC_GEN_3_0));
+ HDMIPRINTK("V_SYNC_GEN_3_1 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_V_SYNC_GEN_3_1));
+ HDMIPRINTK("V_SYNC_GEN_3_2 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_V_SYNC_GEN_3_2));
+ HDMIPRINTK("TG_CMD = 0x%08x \n\r",
+ readl(hdmi_base + S5P_TG_CMD));
+ HDMIPRINTK("TG_H_FSZ_L = 0x%08x \n\r",
+ readl(hdmi_base + S5P_TG_H_FSZ_L));
+ HDMIPRINTK("TG_H_FSZ_H = 0x%08x \n\r",
+ readl(hdmi_base + S5P_TG_H_FSZ_H));
+ HDMIPRINTK("TG_HACT_ST_L = 0x%08x \n\r",
+ readl(hdmi_base + S5P_TG_HACT_ST_L));
+ HDMIPRINTK("TG_HACT_ST_H = 0x%08x \n\r",
+ readl(hdmi_base + S5P_TG_HACT_ST_H));
+ HDMIPRINTK("TG_HACT_SZ_L = 0x%08x \n\r",
+ readl(hdmi_base + S5P_TG_HACT_SZ_L));
+ HDMIPRINTK("TG_HACT_SZ_H = 0x%08x \n\r",
+ readl(hdmi_base + S5P_TG_HACT_SZ_H));
+ HDMIPRINTK("TG_V_FSZ_L = 0x%08x \n\r",
+ readl(hdmi_base + S5P_TG_V_FSZ_L));
+ HDMIPRINTK("TG_V_FSZ_H = 0x%08x \n\r",
+ readl(hdmi_base + S5P_TG_V_FSZ_H));
+ HDMIPRINTK("TG_VSYNC_L = 0x%08x \n\r",
+ readl(hdmi_base + S5P_TG_VSYNC_L));
+ HDMIPRINTK("TG_VSYNC_H = 0x%08x \n\r",
+ readl(hdmi_base + S5P_TG_VSYNC_H));
+ HDMIPRINTK("TG_VSYNC2_L = 0x%08x \n\r",
+ readl(hdmi_base + S5P_TG_VSYNC2_L));
+ HDMIPRINTK("TG_VSYNC2_H = 0x%08x \n\r",
+ readl(hdmi_base + S5P_TG_VSYNC2_H));
+ HDMIPRINTK("TG_VACT_ST_L = 0x%08x \n\r",
+ readl(hdmi_base + S5P_TG_VACT_ST_L));
+ HDMIPRINTK("TG_VACT_ST_H = 0x%08x \n\r",
+ readl(hdmi_base + S5P_TG_VACT_ST_H));
+ HDMIPRINTK("TG_VACT_SZ_L = 0x%08x \n\r",
+ readl(hdmi_base + S5P_TG_VACT_SZ_L));
+ HDMIPRINTK("TG_VACT_SZ_H = 0x%08x \n\r",
+ readl(hdmi_base + S5P_TG_VACT_SZ_H));
+ HDMIPRINTK("TG_FIELD_CHG_L = 0x%08x \n\r",
+ readl(hdmi_base + S5P_TG_FIELD_CHG_L));
+ HDMIPRINTK("TG_FIELD_CHG_H = 0x%08x \n\r",
+ readl(hdmi_base + S5P_TG_FIELD_CHG_H));
+ HDMIPRINTK("TG_VACT_ST2_L = 0x%08x \n\r",
+ readl(hdmi_base + S5P_TG_VACT_ST2_L));
+ HDMIPRINTK("TG_VACT_ST2_H = 0x%08x \n\r",
+ readl(hdmi_base + S5P_TG_VACT_ST2_H));
+ HDMIPRINTK("TG_VSYNC_TOP_HDMI_L = 0x%08x \n\r",
+ readl(hdmi_base + S5P_TG_VSYNC_TOP_HDMI_L));
+ HDMIPRINTK("TG_VSYNC_TOP_HDMI_H = 0x%08x \n\r",
+ readl(hdmi_base + S5P_TG_VSYNC_TOP_HDMI_H));
+ HDMIPRINTK("TG_VSYNC_BOT_HDMI_L = 0x%08x \n\r",
+ readl(hdmi_base + S5P_TG_VSYNC_BOT_HDMI_L));
+ HDMIPRINTK("TG_VSYNC_BOT_HDMI_H = 0x%08x \n\r",
+ readl(hdmi_base + S5P_TG_VSYNC_BOT_HDMI_H));
+ HDMIPRINTK("TG_FIELD_TOP_HDMI_L = 0x%08x \n\r",
+ readl(hdmi_base + S5P_TG_FIELD_TOP_HDMI_L));
+ HDMIPRINTK("TG_FIELD_TOP_HDMI_H = 0x%08x \n\r",
+ readl(hdmi_base + S5P_TG_FIELD_TOP_HDMI_H));
+ HDMIPRINTK("TG_FIELD_BOT_HDMI_L = 0x%08x \n\r",
+ readl(hdmi_base + S5P_TG_FIELD_BOT_HDMI_L));
+ HDMIPRINTK("TG_FIELD_BOT_HDMI_H = 0x%08x \n\r",
+ readl(hdmi_base + S5P_TG_FIELD_BOT_HDMI_H));
+
+ return HDMI_NO_ERROR;
+}
+
+void __s5p_hdmi_video_init_bluescreen(bool en,
+ u8 cb_b,
+ u8 y_g,
+ u8 cr_r)
+{
+ HDMIPRINTK("()\n\r");
+
+ __s5p_hdmi_video_set_bluescreen(en, cb_b, y_g, cr_r);
+
+ HDMIPRINTK("()\n\r");
+}
+
+void __s5p_hdmi_video_init_color_range(u8 y_min,
+ u8 y_max,
+ u8 c_min,
+ u8 c_max)
+{
+ HDMIPRINTK("%d,%d,%d,%d\n\r", y_max, y_min, c_max, c_min);
+
+ writel(y_max, hdmi_base + S5P_HDMI_YMAX);
+ writel(y_min, hdmi_base + S5P_HDMI_YMIN);
+ writel(c_max, hdmi_base + S5P_HDMI_CMAX);
+ writel(c_min, hdmi_base + S5P_HDMI_CMIN);
+
+ HDMIPRINTK("HDMI_YMAX = 0x%08x \n\r",
+ readl(hdmi_base + S5P_HDMI_YMAX));
+ HDMIPRINTK("HDMI_YMIN = 0x%08x \n\r",
+ readl(hdmi_base + S5P_HDMI_YMIN));
+ HDMIPRINTK("HDMI_CMAX = 0x%08x \n\r",
+ readl(hdmi_base + S5P_HDMI_CMAX));
+ HDMIPRINTK("HDMI_CMIN = 0x%08x \n\r",
+ readl(hdmi_base + S5P_HDMI_CMIN));
+}
+
+enum s5p_tv_hdmi_err __s5p_hdmi_video_init_csc(
+ enum s5p_tv_hdmi_csc_type csc_type)
+{
+ unsigned short us_csc_coeff[10];
+
+ HDMIPRINTK("%d)\n\r", csc_type);
+
+ switch (csc_type) {
+
+ case HDMI_CSC_YUV601_TO_RGB_LR:
+ us_csc_coeff[0] = 0x23;
+ us_csc_coeff[1] = 256;
+ us_csc_coeff[2] = 938;
+ us_csc_coeff[3] = 846;
+ us_csc_coeff[4] = 256;
+ us_csc_coeff[5] = 443;
+ us_csc_coeff[6] = 0;
+ us_csc_coeff[7] = 256;
+ us_csc_coeff[8] = 0;
+ us_csc_coeff[9] = 350;
+ break;
+
+ case HDMI_CSC_YUV601_TO_RGB_FR:
+ us_csc_coeff[0] = 0x03;
+ us_csc_coeff[1] = 298;
+ us_csc_coeff[2] = 924;
+ us_csc_coeff[3] = 816;
+ us_csc_coeff[4] = 298;
+ us_csc_coeff[5] = 516;
+ us_csc_coeff[6] = 0;
+ us_csc_coeff[7] = 298;
+ us_csc_coeff[8] = 0;
+ us_csc_coeff[9] = 408;
+ break;
+
+ case HDMI_CSC_YUV709_TO_RGB_LR:
+ us_csc_coeff[0] = 0x23;
+ us_csc_coeff[1] = 256;
+ us_csc_coeff[2] = 978;
+ us_csc_coeff[3] = 907;
+ us_csc_coeff[4] = 256;
+ us_csc_coeff[5] = 464;
+ us_csc_coeff[6] = 0;
+ us_csc_coeff[7] = 256;
+ us_csc_coeff[8] = 0;
+ us_csc_coeff[9] = 394;
+ break;
+
+ case HDMI_CSC_YUV709_TO_RGB_FR:
+ us_csc_coeff[0] = 0x03;
+ us_csc_coeff[1] = 298;
+ us_csc_coeff[2] = 970;
+ us_csc_coeff[3] = 888;
+ us_csc_coeff[4] = 298;
+ us_csc_coeff[5] = 540;
+ us_csc_coeff[6] = 0;
+ us_csc_coeff[7] = 298;
+ us_csc_coeff[8] = 0;
+ us_csc_coeff[9] = 458;
+ break;
+
+ case HDMI_CSC_YUV601_TO_YUV709:
+ us_csc_coeff[0] = 0x33;
+ us_csc_coeff[1] = 256;
+ us_csc_coeff[2] = 995;
+ us_csc_coeff[3] = 971;
+ us_csc_coeff[4] = 0;
+ us_csc_coeff[5] = 260;
+ us_csc_coeff[6] = 29;
+ us_csc_coeff[7] = 0;
+ us_csc_coeff[8] = 19;
+ us_csc_coeff[9] = 262;
+ break;
+
+ case HDMI_CSC_RGB_FR_TO_RGB_LR:
+ us_csc_coeff[0] = 0x20;
+ us_csc_coeff[1] = 220;
+ us_csc_coeff[2] = 0;
+ us_csc_coeff[3] = 0;
+ us_csc_coeff[4] = 0;
+ us_csc_coeff[5] = 220;
+ us_csc_coeff[6] = 0;
+ us_csc_coeff[7] = 0;
+ us_csc_coeff[8] = 0;
+ us_csc_coeff[9] = 220;
+ break;
+
+ case HDMI_CSC_RGB_FR_TO_YUV601:
+ us_csc_coeff[0] = 0x30;
+ us_csc_coeff[1] = 129;
+ us_csc_coeff[2] = 25;
+ us_csc_coeff[3] = 65;
+ us_csc_coeff[4] = 950;
+ us_csc_coeff[5] = 112;
+ us_csc_coeff[6] = 986;
+ us_csc_coeff[7] = 930;
+ us_csc_coeff[8] = 1006;
+ us_csc_coeff[9] = 112;
+ break;
+
+ case HDMI_CSC_RGB_FR_TO_YUV709:
+ us_csc_coeff[0] = 0x30;
+ us_csc_coeff[1] = 157;
+ us_csc_coeff[2] = 16;
+ us_csc_coeff[3] = 47;
+ us_csc_coeff[4] = 937;
+ us_csc_coeff[5] = 112;
+ us_csc_coeff[6] = 999;
+ us_csc_coeff[7] = 922;
+ us_csc_coeff[8] = 1014;
+ us_csc_coeff[9] = 112;
+ break;
+
+ case HDMI_BYPASS:
+ us_csc_coeff[0] = 0x33;
+ us_csc_coeff[1] = 256;
+ us_csc_coeff[2] = 0;
+ us_csc_coeff[3] = 0;
+ us_csc_coeff[4] = 0;
+ us_csc_coeff[5] = 256;
+ us_csc_coeff[6] = 0;
+ us_csc_coeff[7] = 0;
+ us_csc_coeff[8] = 0;
+ us_csc_coeff[9] = 256;
+ break;
+
+ default:
+ HDMIPRINTK("invalid out_mode parameter(%d)\n\r", csc_type);
+ return S5P_TV_HDMI_ERR_INVALID_PARAM;
+ break;
+ }
+
+ writel(us_csc_coeff[0], hdmi_base + S5P_HDMI_CSC_CON);;
+
+ writel(SET_HDMI_CSC_COEF_L(us_csc_coeff[1]),
+ hdmi_base + S5P_HDMI_Y_G_COEF_L);
+ writel(SET_HDMI_CSC_COEF_H(us_csc_coeff[1]),
+ hdmi_base + S5P_HDMI_Y_G_COEF_H);
+ writel(SET_HDMI_CSC_COEF_L(us_csc_coeff[2]),
+ hdmi_base + S5P_HDMI_Y_B_COEF_L);
+ writel(SET_HDMI_CSC_COEF_H(us_csc_coeff[2]),
+ hdmi_base + S5P_HDMI_Y_B_COEF_H);
+ writel(SET_HDMI_CSC_COEF_L(us_csc_coeff[3]),
+ hdmi_base + S5P_HDMI_Y_R_COEF_L);
+ writel(SET_HDMI_CSC_COEF_H(us_csc_coeff[3]),
+ hdmi_base + S5P_HDMI_Y_R_COEF_H);
+ writel(SET_HDMI_CSC_COEF_L(us_csc_coeff[4]),
+ hdmi_base + S5P_HDMI_CB_G_COEF_L);
+ writel(SET_HDMI_CSC_COEF_H(us_csc_coeff[4]),
+ hdmi_base + S5P_HDMI_CB_G_COEF_H);
+ writel(SET_HDMI_CSC_COEF_L(us_csc_coeff[5]),
+ hdmi_base + S5P_HDMI_CB_B_COEF_L);
+ writel(SET_HDMI_CSC_COEF_H(us_csc_coeff[5]),
+ hdmi_base + S5P_HDMI_CB_B_COEF_H);
+ writel(SET_HDMI_CSC_COEF_L(us_csc_coeff[6]),
+ hdmi_base + S5P_HDMI_CB_R_COEF_L);
+ writel(SET_HDMI_CSC_COEF_H(us_csc_coeff[6]),
+ hdmi_base + S5P_HDMI_CB_R_COEF_H);
+ writel(SET_HDMI_CSC_COEF_L(us_csc_coeff[7]),
+ hdmi_base + S5P_HDMI_CR_G_COEF_L);
+ writel(SET_HDMI_CSC_COEF_H(us_csc_coeff[7]),
+ hdmi_base + S5P_HDMI_CR_G_COEF_H);
+ writel(SET_HDMI_CSC_COEF_L(us_csc_coeff[8]),
+ hdmi_base + S5P_HDMI_CR_B_COEF_L);
+ writel(SET_HDMI_CSC_COEF_H(us_csc_coeff[8]),
+ hdmi_base + S5P_HDMI_CR_B_COEF_H);
+ writel(SET_HDMI_CSC_COEF_L(us_csc_coeff[9]),
+ hdmi_base + S5P_HDMI_CR_R_COEF_L);
+ writel(SET_HDMI_CSC_COEF_H(us_csc_coeff[9]),
+ hdmi_base + S5P_HDMI_CR_R_COEF_H);
+
+ HDMIPRINTK("HDMI_CSC_CON = 0x%08x \n\r",
+ readl(hdmi_base + S5P_HDMI_CSC_CON));
+ HDMIPRINTK("HDMI_Y_G_COEF_L = 0x%08x \n\r",
+ readl(hdmi_base + S5P_HDMI_Y_G_COEF_L));
+ HDMIPRINTK("HDMI_Y_G_COEF_H = 0x%08x \n\r",
+ readl(hdmi_base + S5P_HDMI_Y_G_COEF_H));
+ HDMIPRINTK("HDMI_Y_B_COEF_L = 0x%08x \n\r",
+ readl(hdmi_base + S5P_HDMI_Y_B_COEF_L));
+ HDMIPRINTK("HDMI_Y_B_COEF_H = 0x%08x \n\r",
+ readl(hdmi_base + S5P_HDMI_Y_B_COEF_H));
+ HDMIPRINTK("HDMI_Y_R_COEF_L = 0x%08x \n\r",
+ readl(hdmi_base + S5P_HDMI_Y_R_COEF_L));
+ HDMIPRINTK("HDMI_Y_R_COEF_H = 0x%08x \n\r",
+ readl(hdmi_base + S5P_HDMI_Y_R_COEF_H));
+ HDMIPRINTK("HDMI_CB_G_COEF_L = 0x%08x \n\r",
+ readl(hdmi_base + S5P_HDMI_CB_G_COEF_L));
+ HDMIPRINTK("HDMI_CB_G_COEF_H = 0x%08x \n\r",
+ readl(hdmi_base + S5P_HDMI_CB_G_COEF_H));
+ HDMIPRINTK("HDMI_CB_B_COEF_L = 0x%08x \n\r",
+ readl(hdmi_base + S5P_HDMI_CB_B_COEF_L));
+ HDMIPRINTK("HDMI_CB_B_COEF_H = 0x%08x \n\r",
+ readl(hdmi_base + S5P_HDMI_CB_B_COEF_H));
+ HDMIPRINTK("HDMI_CB_R_COEF_L = 0x%08x \n\r",
+ readl(hdmi_base + S5P_HDMI_CB_R_COEF_L));
+ HDMIPRINTK("HDMI_CB_R_COEF_H = 0x%08x \n\r",
+ readl(hdmi_base + S5P_HDMI_CB_R_COEF_H));
+ HDMIPRINTK("HDMI_CR_G_COEF_L = 0x%08x \n\r",
+ readl(hdmi_base + S5P_HDMI_CR_G_COEF_L));
+ HDMIPRINTK("HDMI_CR_G_COEF_H = 0x%08x \n\r",
+ readl(hdmi_base + S5P_HDMI_CR_G_COEF_H));
+ HDMIPRINTK("HDMI_CR_B_COEF_L = 0x%08x \n\r",
+ readl(hdmi_base + S5P_HDMI_CR_B_COEF_L));
+ HDMIPRINTK("HDMI_CR_B_COEF_H = 0x%08x \n\r",
+ readl(hdmi_base + S5P_HDMI_CR_B_COEF_H));
+ HDMIPRINTK("HDMI_CR_R_COEF_L = 0x%08x \n\r",
+ readl(hdmi_base + S5P_HDMI_CR_R_COEF_L));
+ HDMIPRINTK("HDMI_CR_R_COEF_H = 0x%08x \n\r",
+ readl(hdmi_base + S5P_HDMI_CR_R_COEF_H));
+
+ return HDMI_NO_ERROR;
+}
+
+enum s5p_tv_hdmi_err __s5p_hdmi_video_init_avi_infoframe(
+ enum s5p_hdmi_transmit trans_type, u8 check_sum, u8 *avi_data)
+{
+ HDMIPRINTK("%d,%d,%d\n\r", (u32)trans_type, (u32)check_sum,
+ (u32)avi_data);
+
+ switch (trans_type) {
+
+ case HDMI_DO_NOT_TANS:
+ writel(AVI_TX_CON_NO_TRANS, hdmi_base + S5P_AVI_CON);
+ break;
+
+ case HDMI_TRANS_ONCE:
+ writel(AVI_TX_CON_TRANS_ONCE, hdmi_base + S5P_AVI_CON);
+ break;
+
+ case HDMI_TRANS_EVERY_SYNC:
+ writel(AVI_TX_CON_TRANS_EVERY_VSYNC, hdmi_base + S5P_AVI_CON);
+ break;
+
+ default:
+ HDMIPRINTK(" invalid out_mode parameter(%d)\n\r", trans_type);
+ return S5P_TV_HDMI_ERR_INVALID_PARAM;
+ break;
+ }
+
+ writel(SET_AVI_CHECK_SUM(check_sum), hdmi_base + S5P_AVI_CHECK_SUM);
+
+ writel(SET_AVI_BYTE(*(avi_data)), hdmi_base + S5P_AVI_BYTE1);
+ writel(SET_AVI_BYTE(*(avi_data + 1)), hdmi_base + S5P_AVI_BYTE2);
+ writel(SET_AVI_BYTE(*(avi_data + 2)), hdmi_base + S5P_AVI_BYTE3);
+ writel(SET_AVI_BYTE(*(avi_data + 3)), hdmi_base + S5P_AVI_BYTE4);
+ writel(SET_AVI_BYTE(*(avi_data + 4)), hdmi_base + S5P_AVI_BYTE5);
+ writel(SET_AVI_BYTE(*(avi_data + 5)), hdmi_base + S5P_AVI_BYTE6);
+ writel(SET_AVI_BYTE(*(avi_data + 6)), hdmi_base + S5P_AVI_BYTE7);
+ writel(SET_AVI_BYTE(*(avi_data + 7)), hdmi_base + S5P_AVI_BYTE8);
+ writel(SET_AVI_BYTE(*(avi_data + 8)), hdmi_base + S5P_AVI_BYTE9);
+ writel(SET_AVI_BYTE(*(avi_data + 9)), hdmi_base + S5P_AVI_BYTE10);
+ writel(SET_AVI_BYTE(*(avi_data + 10)), hdmi_base + S5P_AVI_BYTE11);
+ writel(SET_AVI_BYTE(*(avi_data + 11)), hdmi_base + S5P_AVI_BYTE12);
+ writel(SET_AVI_BYTE(*(avi_data + 12)), hdmi_base + S5P_AVI_BYTE13);
+
+ HDMIPRINTK("AVI_CON = 0x%08x \n\r", readl(hdmi_base + S5P_AVI_CON));
+ HDMIPRINTK("AVI_CHECK_SUM = 0x%08x \n\r",
+ readl(hdmi_base + S5P_AVI_CHECK_SUM));
+ HDMIPRINTK("AVI_BYTE1 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_AVI_BYTE1));
+ HDMIPRINTK("AVI_BYTE2 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_AVI_BYTE2));
+ HDMIPRINTK("AVI_BYTE3 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_AVI_BYTE3));
+ HDMIPRINTK("AVI_BYTE4 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_AVI_BYTE4));
+ HDMIPRINTK("AVI_BYTE5 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_AVI_BYTE5));
+ HDMIPRINTK("AVI_BYTE6 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_AVI_BYTE6));
+ HDMIPRINTK("AVI_BYTE7 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_AVI_BYTE7));
+ HDMIPRINTK("AVI_BYTE8 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_AVI_BYTE8));
+ HDMIPRINTK("AVI_BYTE9 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_AVI_BYTE9));
+ HDMIPRINTK("AVI_BYTE10 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_AVI_BYTE10));
+ HDMIPRINTK("AVI_BYTE11 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_AVI_BYTE11));
+ HDMIPRINTK("AVI_BYTE12 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_AVI_BYTE12));
+ HDMIPRINTK("AVI_BYTE13 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_AVI_BYTE13));
+
+ /*
+ * for test color bar
+ */
+ /*
+ {
+
+ writel( 0xff&32,HDMI_TPGEN_1);
+ writel( (32>>8)&0xff,HDMI_TPGEN_2);
+ writel( 0xff&480,HDMI_TPGEN_3);
+ writel( (480>>8)&0xff,HDMI_TPGEN_4);
+ writel( 0xff&720,HDMI_TPGEN_5);
+ writel( (720>>8)&0xff,HDMI_TPGEN_6);
+
+ u8 uTpGen0Reg = 0x1 | (0x1<<3) | (1<<4);
+ writel( uTpGen0Reg, HDMI_TPGEN_0);
+
+ HDMIPRINTK("HDMI_TPGEN_0 0x%08x\n",readl(HDMI_TPGEN_0));
+ HDMIPRINTK("HDMI_TPGEN_1 0x%08x\n",readl(HDMI_TPGEN_1));
+ HDMIPRINTK("HDMI_TPGEN_2 0x%08x\n",readl(HDMI_TPGEN_2));
+ HDMIPRINTK("HDMI_TPGEN_3 0x%08x\n",readl(HDMI_TPGEN_3));
+ HDMIPRINTK("HDMI_TPGEN_5 0x%08x\n",readl(HDMI_TPGEN_4));
+ HDMIPRINTK("HDMI_TPGEN_0 0x%08x\n",readl(HDMI_TPGEN_5));
+ HDMIPRINTK("HDMI_TPGEN_1 0x%08x\n",readl(HDMI_TPGEN_6));
+ }
+ */
+
+ return HDMI_NO_ERROR;
+}
+
+enum s5p_tv_hdmi_err __s5p_hdmi_video_init_mpg_infoframe(
+ enum s5p_hdmi_transmit trans_type, u8 check_sum, u8 *mpg_data)
+{
+ HDMIPRINTK("trans_type : %d,%d,%d\n\r", (u32)trans_type,
+ (u32)check_sum, (u32)mpg_data);
+
+ switch (trans_type) {
+
+ case HDMI_DO_NOT_TANS:
+ writel(MPG_TX_CON_NO_TRANS,
+ hdmi_base + S5P_MPG_CON);
+ break;
+
+ case HDMI_TRANS_ONCE:
+ writel(MPG_TX_CON_TRANS_ONCE,
+ hdmi_base + S5P_MPG_CON);
+ break;
+
+ case HDMI_TRANS_EVERY_SYNC:
+ writel(MPG_TX_CON_TRANS_EVERY_VSYNC,
+ hdmi_base + S5P_MPG_CON);
+ break;
+
+ default:
+ HDMIPRINTK("invalid out_mode parameter(%d)\n\r",
+ trans_type);
+ return S5P_TV_HDMI_ERR_INVALID_PARAM;
+ break;
+ }
+
+ writel(SET_MPG_CHECK_SUM(check_sum),
+
+ hdmi_base + S5P_MPG_CHECK_SUM);
+
+ writel(SET_MPG_BYTE(*(mpg_data)),
+ hdmi_base + S5P_MPEG_BYTE1);
+ writel(SET_MPG_BYTE(*(mpg_data + 1)),
+ hdmi_base + S5P_MPEG_BYTE2);
+ writel(SET_MPG_BYTE(*(mpg_data + 2)),
+ hdmi_base + S5P_MPEG_BYTE3);
+ writel(SET_MPG_BYTE(*(mpg_data + 3)),
+ hdmi_base + S5P_MPEG_BYTE4);
+ writel(SET_MPG_BYTE(*(mpg_data + 4)),
+ hdmi_base + S5P_MPEG_BYTE5);
+
+ HDMIPRINTK("MPG_CON = 0x%08x \n\r",
+ readl(hdmi_base + S5P_MPG_CON));
+ HDMIPRINTK("MPG_CHECK_SUM = 0x%08x \n\r",
+ readl(hdmi_base + S5P_MPG_CHECK_SUM));
+ HDMIPRINTK("MPEG_BYTE1 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_MPEG_BYTE1));
+ HDMIPRINTK("MPEG_BYTE2 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_MPEG_BYTE2));
+ HDMIPRINTK("MPEG_BYTE3 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_MPEG_BYTE3));
+ HDMIPRINTK("MPEG_BYTE4 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_MPEG_BYTE4));
+ HDMIPRINTK("MPEG_BYTE5 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_MPEG_BYTE5));
+
+ return HDMI_NO_ERROR;
+}
+
+void __s5p_hdmi_video_init_tg_cmd(bool time_c_e,
+ bool bt656_sync_en,
+ bool tg_en)
+{
+ u32 temp_reg = 0;
+
+ temp_reg = readl(hdmi_base + S5P_TG_CMD);
+
+ if (time_c_e)
+ temp_reg |= GETSYNC_TYPE_EN;
+ else
+ temp_reg &= GETSYNC_TYPE_DIS;
+
+ if (bt656_sync_en)
+ temp_reg |= GETSYNC_EN;
+ else
+ temp_reg &= GETSYNC_DIS;
+
+ if (tg_en)
+ temp_reg |= TG_EN;
+ else
+ temp_reg &= TG_DIS;
+
+ writel(temp_reg, hdmi_base + S5P_TG_CMD);
+
+ HDMIPRINTK("TG_CMD = 0x%08x \n\r", readl(hdmi_base + S5P_TG_CMD));
+}
+
+
+/*
+* start - start functions are only called under stopping HDMI
+*/
+bool __s5p_hdmi_start(enum s5p_hdmi_audio_type hdmi_audio_type,
+ bool hdcp_en,
+ struct i2c_client *ddc_port)
+{
+ u32 temp_reg = PWDN_ENB_NORMAL | HDMI_EN;;
+
+ HDMIPRINTK("aud type : %d, hdcp enable : %d\n\r",
+ hdmi_audio_type, hdcp_en);
+
+ switch (hdmi_audio_type) {
+
+ case HDMI_AUDIO_PCM:
+ temp_reg |= ASP_EN;
+ break;
+
+ case HDMI_AUDIO_NO:
+ break;
+
+ default:
+ HDMIPRINTK(" invalid hdmi_audio_type(%d)\n\r",
+ hdmi_audio_type);
+ return false;
+ break;
+ }
+
+ writel(readl(hdmi_base + S5P_HDMI_CON_0) | temp_reg,
+
+ hdmi_base + S5P_HDMI_CON_0);
+
+ if (hdcp_en) {
+ __s5p_init_hdcp(true, ddc_port);
+
+ if (!__s5p_start_hdcp())
+ HDMIPRINTK("HDCP start failed\n");
+
+ }
+
+ HDMIPRINTK("HDCP_CTRL : 0x%08x, HPD : 0x%08x, HDMI_CON_0 :\
+ 0x%08x\n\r",
+
+ readl(hdmi_base + S5P_HDCP_CTRL),
+ readl(hdmi_base + S5P_HPD),
+ readl(hdmi_base + S5P_HDMI_CON_0));
+
+ return true;
+}
+
+
+
+/*
+* stop - stop functions are only called under running HDMI
+*/
+void __s5p_hdmi_stop(void)
+{
+ HDMIPRINTK("\n\r");
+
+ __s5p_stop_hdcp();
+
+ writel(readl(hdmi_base + S5P_HDMI_CON_0) &
+ ~(PWDN_ENB_NORMAL | HDMI_EN | ASP_EN),
+ hdmi_base + S5P_HDMI_CON_0);
+
+ HDMIPRINTK("HDCP_CTRL 0x%08x, HPD 0x%08x,HDMI_CON_0 0x%08x\n\r",
+ readl(hdmi_base + S5P_HDCP_CTRL),
+ readl(hdmi_base + S5P_HPD),
+ readl(hdmi_base + S5P_HDMI_CON_0));
+}
+
+int __init __s5p_hdmi_probe(struct platform_device *pdev, u32 res_num)
+{
+
+ struct resource *res;
+ size_t size;
+ int ret;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, res_num);
+
+ if (res == NULL) {
+ dev_err(&pdev->dev,
+ "failed to get memory region resource\n");
+ ret = -ENOENT;
+ }
+
+ size = (res->end - res->start) + 1;
+
+ hdmi_mem = request_mem_region(res->start, size, pdev->name);
+
+ if (hdmi_mem == NULL) {
+ dev_err(&pdev->dev,
+ "failed to get memory region\n");
+ ret = -ENOENT;
+ }
+
+ hdmi_base = ioremap(res->start, size);
+
+ if (hdmi_base == NULL) {
+ dev_err(&pdev->dev,
+ "failed to ioremap address region\n");
+ ret = -ENOENT;
+ }
+
+ return ret;
+
+}
+
+int __init __s5p_hdmi_release(struct platform_device *pdev)
+{
+ iounmap(hdmi_base);
+
+ /* remove memory region */
+
+ if (hdmi_mem != NULL) {
+ if (release_resource(hdmi_mem))
+ dev_err(&pdev->dev,
+ "Can't remove tvout drv !!\n");
+
+ kfree(hdmi_mem);
+
+ hdmi_mem = NULL;
+ }
+
+ return 0;
+}
+
diff --git a/drivers/media/video/samsung/tv20/s5pc100/regs/regs-clock_extra.h b/drivers/media/video/samsung/tv20/s5pc100/regs/regs-clock_extra.h
new file mode 100644
index 0000000..ff00b23
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/s5pc100/regs/regs-clock_extra.h
@@ -0,0 +1,79 @@
+/* linux/drivers/media/video/samsung/tv20/s5pc100/regs/regs-clock_extra.h
+ *
+ * Clock Other header file for Samsung TVOut driver
+ *
+ * Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_REGS_CLK_EXTRA_H
+#define __ASM_ARCH_REGS_CLK_EXTRA_H
+
+#include <mach/map.h>
+
+#define S5P_CLK_OTHER_BASE(x) (x)
+
+#define S5P_CLK_OTHER_SWRESET S5P_CLK_OTHER_BASE(0x0000)
+#define S5P_CLK_OTHER_ONENAND_SWRESET S5P_CLK_OTHER_BASE(0x0008)
+#define S5P_CLK_OTHER_GENERAL_CTRL S5P_CLK_OTHER_BASE(0x0100)
+#define S5P_CLK_OTHER_GENERAL_STATUS S5P_CLK_OTHER_BASE(0x0104)
+#define S5P_CLK_OTHER_MEM_SYS_CFG S5P_CLK_OTHER_BASE(0x0200)
+#define S5P_CLK_OTHER_CAM_MUX_SEL S5P_CLK_OTHER_BASE(0x0300)
+#define S5P_CLK_OTHER_MIXER_OUT_SEL S5P_CLK_OTHER_BASE(0x0304)
+#define S5P_CLK_OTHER_LPMP3_MODE_SEL S5P_CLK_OTHER_BASE(0x0308)
+#define S5P_CLK_OTHER_MIPI_PHY_CON0 S5P_CLK_OTHER_BASE(0x0400)
+#define S5P_CLK_OTHER_MIPI_PHY_CON1 S5P_CLK_OTHER_BASE(0x0414)
+#define S5P_CLK_OTHER_HDMI_PHY_CON0 S5P_CLK_OTHER_BASE(0x0420)
+
+
+
+#define HPLL_LOCKTIME(a) (0xffff&a)
+
+#define HPLL_ENABLE (1<<31)
+#define HPLL_DISABLE (0<<31)
+#define HPLL_LOCKED(a) ((1<<30)&a)
+#define MDIV(a) ((0xff&a)<<16)
+#define PDIV(a) ((0x3f&a)<<8)
+#define SDIV(a) (0x7&a)
+
+#define HREF_SEL_FIN_27M (0<<20)
+#define HREF_SEL_SRCLK (1<<20)
+#define HREF_SEL_MASK (~(1<<20))
+#define HPLL_SEL_CLK27M (0<<12)
+#define HPLL_SEL_FOUT_HPLL (1<<12)
+#define HPLL_SEL_MASK (~(1<<12))
+
+#define VMIXER_SEL_CLK27M (0<<28)
+#define VMIXER_SEL_VCLK_54 (1<<28)
+#define VMIXER_SEL_MOUT_HPLL (2<<28)
+#define VMIXER_SEL_MASK (~(3<<28))
+
+#define HDMI_DIV_RATIO(a) ((0xf&((a)-1))<<28)
+#define HDMI_DIV_RATIO_MASK (~(0xf<<28))
+
+#define CLK_HCLK_HDMI_PASS (1<<3)
+#define CLK_HCLK_VMIXER_PASS (1<<2)
+#define CLK_HCLK_VP_PASS (1<<1)
+#define CLK_HCLK_SDOUT_PASS (1<<0)
+#define CLK_HCLK_MASK (~0xf)
+
+#define CLK_PCLK_IIC_HDMI_PASS (1<<5)
+#define CLK_PCLK_IIC_HDMI_MASK (~(1<<5))
+
+#define CLK_SCLK_HDMI_PASS (1<<7)
+#define CLK_SCLK_VMIXER_PASS (1<<6)
+#define CLK_SCLK_VDAC54_PASS (1<<5)
+#define CLK_SCLK_TV54_PASS (1<<4)
+#define CLK_SCLK_HDMI_MASK (~(1<<7))
+#define CLK_SCLK_VMIXER_MASK (~(1<<6))
+#define CLK_SCLK_VDAC54_MASK (~(1<<5))
+#define CLK_SCLK_TV54_MASK (~(1<<4))
+
+#define VMIXER_OUT_SEL_SDOUT (0)
+#define VMIXER_OUT_SEL_HDMI (1)
+
+#endif
diff --git a/drivers/media/video/samsung/tv20/s5pc100/regs/regs-hdmi.h b/drivers/media/video/samsung/tv20/s5pc100/regs/regs-hdmi.h
new file mode 100644
index 0000000..96c1958
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/s5pc100/regs/regs-hdmi.h
@@ -0,0 +1,978 @@
+/* linux/drivers/media/video/samsung/tv20/s5pc100/regs/regs-hdmi.h
+ *
+ * Hdmi register header file for Samsung TVOut driver
+ *
+ * Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_REGS_HDMI_H
+
+#include <mach/map.h>
+
+#define S5P_HDMI_BASE(x) (x)
+
+#define S5P_HDMI_CON_0 S5P_HDMI_BASE(0x0000)
+#define S5P_HDMI_CON_1 S5P_HDMI_BASE(0x0004)
+#define S5P_HDMI_CON_2 S5P_HDMI_BASE(0x0008)
+#define S5P_STATUS S5P_HDMI_BASE(0x0010)
+#define S5P_STATUS_EN S5P_HDMI_BASE(0x0020)
+#define S5P_HPD S5P_HDMI_BASE(0x0030)
+#define S5P_MODE_SEL S5P_HDMI_BASE(0x0040)
+#define S5P_ENC_EN S5P_HDMI_BASE(0x0044)
+#define S5P_BLUE_SCREEN_0 S5P_HDMI_BASE(0x0050)
+#define S5P_BLUE_SCREEN_1 S5P_HDMI_BASE(0x0054)
+#define S5P_BLUE_SCREEN_2 S5P_HDMI_BASE(0x0058)
+#define S5P_HDMI_YMAX S5P_HDMI_BASE(0x0060)
+#define S5P_HDMI_YMIN S5P_HDMI_BASE(0x0064)
+#define S5P_HDMI_CMAX S5P_HDMI_BASE(0x0068)
+#define S5P_HDMI_CMIN S5P_HDMI_BASE(0x006C)
+#define S5P_VBI_ST_MG S5P_HDMI_BASE(0x0080)
+#define S5P_VBI_END_MG S5P_HDMI_BASE(0x0084)
+#define S5P_VACT_ST_MG S5P_HDMI_BASE(0x0088)
+#define S5P_VACT_END_MG S5P_HDMI_BASE(0x008C)
+#define S5P_H_BLANK_0 S5P_HDMI_BASE(0x00A0)
+#define S5P_H_BLANK_1 S5P_HDMI_BASE(0x00A4)
+#define S5P_V_BLANK_0 S5P_HDMI_BASE(0x00B0)
+#define S5P_V_BLANK_1 S5P_HDMI_BASE(0x00B4)
+#define S5P_V_BLANK_2 S5P_HDMI_BASE(0x00B8)
+#define S5P_H_V_LINE_0 S5P_HDMI_BASE(0x00C0)
+#define S5P_H_V_LINE_1 S5P_HDMI_BASE(0x00C4)
+#define S5P_H_V_LINE_2 S5P_HDMI_BASE(0x00C8)
+#define S5P_SYNC_MODE S5P_HDMI_BASE(0x00E4)
+#define S5P_INT_PRO_MODE S5P_HDMI_BASE(0x00E8)
+#define S5P_SEND_PER_START0 S5P_HDMI_BASE(0x00f0)
+#define S5P_SEND_PER_START1 S5P_HDMI_BASE(0x00f4)
+#define S5P_SEND_PER_END0 S5P_HDMI_BASE(0x0100)
+#define S5P_SEND_PER_END1 S5P_HDMI_BASE(0x0104)
+#define S5P_SEND_PER_END2 S5P_HDMI_BASE(0x0108)
+#define S5P_V_BLANK_F_0 S5P_HDMI_BASE(0x0110)
+#define S5P_V_BLANK_F_1 S5P_HDMI_BASE(0x0114)
+#define S5P_V_BLANK_F_2 S5P_HDMI_BASE(0x0118)
+#define S5P_H_SYNC_GEN_0 S5P_HDMI_BASE(0x0120)
+#define S5P_H_SYNC_GEN_1 S5P_HDMI_BASE(0x0124)
+#define S5P_H_SYNC_GEN_2 S5P_HDMI_BASE(0x0128)
+#define S5P_V_SYNC_GEN_1_0 S5P_HDMI_BASE(0x0130)
+#define S5P_V_SYNC_GEN_1_1 S5P_HDMI_BASE(0x0134)
+#define S5P_V_SYNC_GEN_1_2 S5P_HDMI_BASE(0x0138)
+#define S5P_V_SYNC_GEN_2_0 S5P_HDMI_BASE(0x0140)
+#define S5P_V_SYNC_GEN_2_1 S5P_HDMI_BASE(0x0144)
+#define S5P_V_SYNC_GEN_2_2 S5P_HDMI_BASE(0x0148)
+#define S5P_V_SYNC_GEN_3_0 S5P_HDMI_BASE(0x0150)
+#define S5P_V_SYNC_GEN_3_1 S5P_HDMI_BASE(0x0154)
+#define S5P_V_SYNC_GEN_3_2 S5P_HDMI_BASE(0x0158)
+#define S5P_ASP_CON S5P_HDMI_BASE(0x0160)
+#define S5P_ASP_SP_FLAT S5P_HDMI_BASE(0x0164)
+#define S5P_ASP_CHCFG0 S5P_HDMI_BASE(0x0170)
+#define S5P_ASP_CHCFG1 S5P_HDMI_BASE(0x0174)
+#define S5P_ASP_CHCFG2 S5P_HDMI_BASE(0x0178)
+#define S5P_ASP_CHCFG3 S5P_HDMI_BASE(0x017C)
+#define S5P_ACR_CON S5P_HDMI_BASE(0x0180)
+#define S5P_ACR_MCTS0 S5P_HDMI_BASE(0x0184)
+#define S5P_ACR_MCTS1 S5P_HDMI_BASE(0x0188)
+#define S5P_ACR_MCTS2 S5P_HDMI_BASE(0x018C)
+#define S5P_ACR_CTS0 S5P_HDMI_BASE(0x0190)
+#define S5P_ACR_CTS1 S5P_HDMI_BASE(0x0194)
+#define S5P_ACR_CTS2 S5P_HDMI_BASE(0x0198)
+#define S5P_ACR_N0 S5P_HDMI_BASE(0x01A0)
+#define S5P_ACR_N1 S5P_HDMI_BASE(0x01A4)
+#define S5P_ACR_N2 S5P_HDMI_BASE(0x01A8)
+#define S5P_ACR_LSB2 S5P_HDMI_BASE(0x01B0)
+#define S5P_ACR_TXCNT S5P_HDMI_BASE(0x01B4)
+#define S5P_ACR_TXINTERVAL S5P_HDMI_BASE(0x01B8)
+#define S5P_ACR_CTS_OFFSET S5P_HDMI_BASE(0x01BC)
+#define S5P_GCP_CON S5P_HDMI_BASE(0x01C0)
+#define S5P_GCP_BYTE1 S5P_HDMI_BASE(0x01D0)
+#define S5P_ACP_CON S5P_HDMI_BASE(0x01E0)
+#define S5P_ACP_TYPE S5P_HDMI_BASE(0x01E4)
+
+#define S5P_ACP_DATA0 S5P_HDMI_BASE(0x0200)
+#define S5P_ACP_DATA1 S5P_HDMI_BASE(0x0204)
+#define S5P_ACP_DATA2 S5P_HDMI_BASE(0x0208)
+#define S5P_ACP_DATA3 S5P_HDMI_BASE(0x020c)
+#define S5P_ACP_DATA4 S5P_HDMI_BASE(0x0210)
+#define S5P_ACP_DATA5 S5P_HDMI_BASE(0x0214)
+#define S5P_ACP_DATA6 S5P_HDMI_BASE(0x0218)
+#define S5P_ACP_DATA7 S5P_HDMI_BASE(0x021c)
+#define S5P_ACP_DATA8 S5P_HDMI_BASE(0x0220)
+#define S5P_ACP_DATA9 S5P_HDMI_BASE(0x0224)
+#define S5P_ACP_DATA10 S5P_HDMI_BASE(0x0228)
+#define S5P_ACP_DATA11 S5P_HDMI_BASE(0x022c)
+#define S5P_ACP_DATA12 S5P_HDMI_BASE(0x0230)
+#define S5P_ACP_DATA13 S5P_HDMI_BASE(0x0234)
+#define S5P_ACP_DATA14 S5P_HDMI_BASE(0x0238)
+#define S5P_ACP_DATA15 S5P_HDMI_BASE(0x023c)
+#define S5P_ACP_DATA16 S5P_HDMI_BASE(0x0240)
+
+#define S5P_ISRC_CON S5P_HDMI_BASE(0x0250)
+#define S5P_ISRC1_HEADER1 S5P_HDMI_BASE(0x0264)
+
+#define S5P_ISRC1_DATA0 S5P_HDMI_BASE(0x0270)
+#define S5P_ISRC1_DATA1 S5P_HDMI_BASE(0x0274)
+#define S5P_ISRC1_DATA2 S5P_HDMI_BASE(0x0278)
+#define S5P_ISRC1_DATA3 S5P_HDMI_BASE(0x027c)
+#define S5P_ISRC1_DATA4 S5P_HDMI_BASE(0x0280)
+#define S5P_ISRC1_DATA5 S5P_HDMI_BASE(0x0284)
+#define S5P_ISRC1_DATA6 S5P_HDMI_BASE(0x0288)
+#define S5P_ISRC1_DATA7 S5P_HDMI_BASE(0x028c)
+#define S5P_ISRC1_DATA8 S5P_HDMI_BASE(0x0290)
+#define S5P_ISRC1_DATA9 S5P_HDMI_BASE(0x0294)
+#define S5P_ISRC1_DATA10 S5P_HDMI_BASE(0x0298)
+#define S5P_ISRC1_DATA11 S5P_HDMI_BASE(0x029c)
+#define S5P_ISRC1_DATA12 S5P_HDMI_BASE(0x02a0)
+#define S5P_ISRC1_DATA13 S5P_HDMI_BASE(0x02a4)
+#define S5P_ISRC1_DATA14 S5P_HDMI_BASE(0x02a8)
+#define S5P_ISRC1_DATA15 S5P_HDMI_BASE(0x02ac)
+
+#define S5P_ISRC2_DATA0 S5P_HDMI_BASE(0x02b0)
+#define S5P_ISRC2_DATA1 S5P_HDMI_BASE(0x02b4)
+#define S5P_ISRC2_DATA2 S5P_HDMI_BASE(0x02b8)
+#define S5P_ISRC2_DATA3 S5P_HDMI_BASE(0x02bc)
+#define S5P_ISRC2_DATA4 S5P_HDMI_BASE(0x02c0)
+#define S5P_ISRC2_DATA5 S5P_HDMI_BASE(0x02c4)
+#define S5P_ISRC2_DATA6 S5P_HDMI_BASE(0x02c8)
+#define S5P_ISRC2_DATA7 S5P_HDMI_BASE(0x02cc)
+#define S5P_ISRC2_DATA8 S5P_HDMI_BASE(0x02d0)
+#define S5P_ISRC2_DATA9 S5P_HDMI_BASE(0x02d4)
+#define S5P_ISRC2_DATA10 S5P_HDMI_BASE(0x02d8)
+#define S5P_ISRC2_DATA11 S5P_HDMI_BASE(0x02dc)
+#define S5P_ISRC2_DATA12 S5P_HDMI_BASE(0x02e0)
+#define S5P_ISRC2_DATA13 S5P_HDMI_BASE(0x02e4)
+#define S5P_ISRC2_DATA14 S5P_HDMI_BASE(0x02e8)
+#define S5P_ISRC2_DATA15 S5P_HDMI_BASE(0x02ec)
+
+#define S5P_AVI_CON S5P_HDMI_BASE(0x0300)
+#define S5P_AVI_CHECK_SUM S5P_HDMI_BASE(0x0310)
+
+#define S5P_AVI_BYTE1 S5P_HDMI_BASE(0x0320)
+#define S5P_AVI_BYTE2 S5P_HDMI_BASE(0x0324)
+#define S5P_AVI_BYTE3 S5P_HDMI_BASE(0x0328)
+#define S5P_AVI_BYTE4 S5P_HDMI_BASE(0x032c)
+#define S5P_AVI_BYTE5 S5P_HDMI_BASE(0x0330)
+#define S5P_AVI_BYTE6 S5P_HDMI_BASE(0x0334)
+#define S5P_AVI_BYTE7 S5P_HDMI_BASE(0x0338)
+#define S5P_AVI_BYTE8 S5P_HDMI_BASE(0x033c)
+#define S5P_AVI_BYTE9 S5P_HDMI_BASE(0x0340)
+#define S5P_AVI_BYTE10 S5P_HDMI_BASE(0x0344)
+#define S5P_AVI_BYTE11 S5P_HDMI_BASE(0x0348)
+#define S5P_AVI_BYTE12 S5P_HDMI_BASE(0x034c)
+#define S5P_AVI_BYTE13 S5P_HDMI_BASE(0x0350)
+
+#define S5P_AUI_CON S5P_HDMI_BASE(0x0360)
+#define S5P_AUI_CHECK_SUM S5P_HDMI_BASE(0x0370)
+
+#define S5P_AUI_BYTE1 S5P_HDMI_BASE(0x0380)
+#define S5P_AUI_BYTE2 S5P_HDMI_BASE(0x0384)
+#define S5P_AUI_BYTE3 S5P_HDMI_BASE(0x0388)
+#define S5P_AUI_BYTE4 S5P_HDMI_BASE(0x038c)
+#define S5P_AUI_BYTE5 S5P_HDMI_BASE(0x0390)
+
+#define S5P_MPG_CON S5P_HDMI_BASE(0x03A0)
+#define S5P_MPG_CHECK_SUM S5P_HDMI_BASE(0x03B0)
+
+#define S5P_MPEG_BYTE1 S5P_HDMI_BASE(0x03c0)
+#define S5P_MPEG_BYTE2 S5P_HDMI_BASE(0x03c4)
+#define S5P_MPEG_BYTE3 S5P_HDMI_BASE(0x03c8)
+#define S5P_MPEG_BYTE4 S5P_HDMI_BASE(0x03cc)
+#define S5P_MPEG_BYTE5 S5P_HDMI_BASE(0x03d0)
+
+#define S5P_SPD_CON S5P_HDMI_BASE(0x0400)
+#define S5P_SPD_HEADER0 S5P_HDMI_BASE(0x0410)
+#define S5P_SPD_HEADER1 S5P_HDMI_BASE(0x0414)
+#define S5P_SPD_HEADER2 S5P_HDMI_BASE(0x0418)
+
+#define S5P_SPD_DATA0 S5P_HDMI_BASE(0x0420)
+#define S5P_SPD_DATA1 S5P_HDMI_BASE(0x0424)
+#define S5P_SPD_DATA2 S5P_HDMI_BASE(0x0428)
+#define S5P_SPD_DATA3 S5P_HDMI_BASE(0x042c)
+#define S5P_SPD_DATA4 S5P_HDMI_BASE(0x0430)
+#define S5P_SPD_DATA5 S5P_HDMI_BASE(0x0434)
+#define S5P_SPD_DATA6 S5P_HDMI_BASE(0x0438)
+#define S5P_SPD_DATA7 S5P_HDMI_BASE(0x043c)
+#define S5P_SPD_DATA8 S5P_HDMI_BASE(0x0440)
+#define S5P_SPD_DATA9 S5P_HDMI_BASE(0x0444)
+#define S5P_SPD_DATA10 S5P_HDMI_BASE(0x0448)
+#define S5P_SPD_DATA11 S5P_HDMI_BASE(0x044c)
+#define S5P_SPD_DATA12 S5P_HDMI_BASE(0x0450)
+#define S5P_SPD_DATA13 S5P_HDMI_BASE(0x0454)
+#define S5P_SPD_DATA14 S5P_HDMI_BASE(0x0458)
+#define S5P_SPD_DATA15 S5P_HDMI_BASE(0x045c)
+#define S5P_SPD_DATA16 S5P_HDMI_BASE(0x0460)
+#define S5P_SPD_DATA17 S5P_HDMI_BASE(0x0464)
+#define S5P_SPD_DATA18 S5P_HDMI_BASE(0x0468)
+#define S5P_SPD_DATA19 S5P_HDMI_BASE(0x046c)
+#define S5P_SPD_DATA20 S5P_HDMI_BASE(0x0470)
+#define S5P_SPD_DATA21 S5P_HDMI_BASE(0x0474)
+#define S5P_SPD_DATA22 S5P_HDMI_BASE(0x0478)
+#define S5P_SPD_DATA23 S5P_HDMI_BASE(0x048c)
+#define S5P_SPD_DATA24 S5P_HDMI_BASE(0x0480)
+#define S5P_SPD_DATA25 S5P_HDMI_BASE(0x0484)
+#define S5P_SPD_DATA26 S5P_HDMI_BASE(0x0488)
+#define S5P_SPD_DATA27 S5P_HDMI_BASE(0x048c)
+#define S5P_HDMI_CSC_CON S5P_HDMI_BASE(0x0490)
+#define S5P_HDMI_Y_G_COEF_L S5P_HDMI_BASE(0x04A0)
+#define S5P_HDMI_Y_G_COEF_H S5P_HDMI_BASE(0x04A4)
+#define S5P_HDMI_Y_B_COEF_L S5P_HDMI_BASE(0x04A8)
+#define S5P_HDMI_Y_B_COEF_H S5P_HDMI_BASE(0x04AC)
+#define S5P_HDMI_Y_R_COEF_L S5P_HDMI_BASE(0x04B0)
+#define S5P_HDMI_Y_R_COEF_H S5P_HDMI_BASE(0x04B4)
+#define S5P_HDMI_CB_G_COEF_L S5P_HDMI_BASE(0x04B8)
+#define S5P_HDMI_CB_G_COEF_H S5P_HDMI_BASE(0x04BC)
+#define S5P_HDMI_CB_B_COEF_L S5P_HDMI_BASE(0x04C0)
+#define S5P_HDMI_CB_B_COEF_H S5P_HDMI_BASE(0x04C4)
+#define S5P_HDMI_CB_R_COEF_L S5P_HDMI_BASE(0x04C8)
+#define S5P_HDMI_CB_R_COEF_H S5P_HDMI_BASE(0x04CC)
+#define S5P_HDMI_CR_G_COEF_L S5P_HDMI_BASE(0x04D0)
+#define S5P_HDMI_CR_G_COEF_H S5P_HDMI_BASE(0x04D4)
+#define S5P_HDMI_CR_B_COEF_L S5P_HDMI_BASE(0x04D8)
+#define S5P_HDMI_CR_B_COEF_H S5P_HDMI_BASE(0x04DC)
+#define S5P_HDMI_CR_R_COEF_L S5P_HDMI_BASE(0x04E0)
+#define S5P_HDMI_CR_R_COEF_H S5P_HDMI_BASE(0x04E4)
+
+#define S5P_HDCP_RX_SHA1_0_0 S5P_HDMI_BASE(0x0600)
+#define S5P_HDCP_RX_SHA1_0_1 S5P_HDMI_BASE(0x0604)
+#define S5P_HDCP_RX_SHA1_0_2 S5P_HDMI_BASE(0x0608)
+#define S5P_HDCP_RX_SHA1_0_3 S5P_HDMI_BASE(0x060C)
+#define S5P_HDCP_RX_SHA1_1_0 S5P_HDMI_BASE(0x0610)
+#define S5P_HDCP_RX_SHA1_1_1 S5P_HDMI_BASE(0x0614)
+#define S5P_HDCP_RX_SHA1_1_2 S5P_HDMI_BASE(0x0618)
+#define S5P_HDCP_RX_SHA1_1_3 S5P_HDMI_BASE(0x061C)
+#define S5P_HDCP_RX_SHA1_2_0 S5P_HDMI_BASE(0x0620)
+#define S5P_HDCP_RX_SHA1_2_1 S5P_HDMI_BASE(0x0624)
+#define S5P_HDCP_RX_SHA1_2_2 S5P_HDMI_BASE(0x0628)
+#define S5P_HDCP_RX_SHA1_2_3 S5P_HDMI_BASE(0x062C)
+#define S5P_HDCP_RX_SHA1_3_0 S5P_HDMI_BASE(0x0630)
+#define S5P_HDCP_RX_SHA1_3_1 S5P_HDMI_BASE(0x0634)
+#define S5P_HDCP_RX_SHA1_3_2 S5P_HDMI_BASE(0x0638)
+#define S5P_HDCP_RX_SHA1_3_3 S5P_HDMI_BASE(0x063C)
+#define S5P_HDCP_RX_SHA1_4_0 S5P_HDMI_BASE(0x0640)
+#define S5P_HDCP_RX_SHA1_4_1 S5P_HDMI_BASE(0x0644)
+#define S5P_HDCP_RX_SHA1_4_2 S5P_HDMI_BASE(0x0648)
+#define S5P_HDCP_RX_SHA1_4_3 S5P_HDMI_BASE(0x064C)
+#define S5P_HDCP_RX_KSV_0_0 S5P_HDMI_BASE(0x0650)
+#define S5P_HDCP_RX_KSV_0_1 S5P_HDMI_BASE(0x0654)
+#define S5P_HDCP_RX_KSV_0_2 S5P_HDMI_BASE(0x0658)
+#define S5P_HDCP_RX_KSV_0_3 S5P_HDMI_BASE(0x065C)
+#define S5P_HDCP_RX_KSV_0_4 S5P_HDMI_BASE(0x0660)
+#define S5P_HDCP_RX_KSV_LIST_CTRL S5P_HDMI_BASE(0x0664)
+#define S5P_HDCP_AUTH_STATUS S5P_HDMI_BASE(0x0670)
+#define S5P_HDCP_CTRL S5P_HDMI_BASE(0x0680)
+#define S5P_HDCP_CHECK_RESULT S5P_HDMI_BASE(0x0690)
+
+#define S5P_HDCP_BKSV_0_0 S5P_HDMI_BASE(0x06A0)
+#define S5P_HDCP_BKSV_0_1 S5P_HDMI_BASE(0x06A4)
+#define S5P_HDCP_BKSV_0_2 S5P_HDMI_BASE(0x06A8)
+#define S5P_HDCP_BKSV_0_3 S5P_HDMI_BASE(0x06AC)
+#define S5P_HDCP_BKSV_1 S5P_HDMI_BASE(0x06B0)
+#define S5P_HDCP_AKSV_0_0 S5P_HDMI_BASE(0x06C0)
+#define S5P_HDCP_AKSV_0_1 S5P_HDMI_BASE(0x06C4)
+#define S5P_HDCP_AKSV_0_2 S5P_HDMI_BASE(0x06C8)
+#define S5P_HDCP_AKSV_0_3 S5P_HDMI_BASE(0x06CC)
+#define S5P_HDCP_AKSV_1 S5P_HDMI_BASE(0x06D0)
+#define S5P_HDCP_An_0_0 S5P_HDMI_BASE(0x06E0)
+#define S5P_HDCP_An_0_1 S5P_HDMI_BASE(0x06E4)
+#define S5P_HDCP_An_0_2 S5P_HDMI_BASE(0x06E8)
+#define S5P_HDCP_An_0_3 S5P_HDMI_BASE(0x06EC)
+#define S5P_HDCP_An_1_0 S5P_HDMI_BASE(0x06F0)
+#define S5P_HDCP_An_1_1 S5P_HDMI_BASE(0x06F4)
+#define S5P_HDCP_An_1_2 S5P_HDMI_BASE(0x06F8)
+#define S5P_HDCP_An_1_3 S5P_HDMI_BASE(0x06FC)
+#define S5P_HDCP_BCAPS S5P_HDMI_BASE(0x0700)
+#define S5P_HDCP_BSTATUS_0 S5P_HDMI_BASE(0x0710)
+#define S5P_HDCP_BSTATUS_1 S5P_HDMI_BASE(0x0714)
+#define S5P_HDCP_Ri_0 S5P_HDMI_BASE(0x0740)
+#define S5P_HDCP_Ri_1 S5P_HDMI_BASE(0x0744)
+#define S5P_HDCP_Pj S5P_HDMI_BASE(0x0750)
+#define S5P_HDCP_OFFSET_TX_0 S5P_HDMI_BASE(0x0760)
+#define S5P_HDCP_OFFSET_TX_1 S5P_HDMI_BASE(0x0764)
+#define S5P_HDCP_OFFSET_TX_2 S5P_HDMI_BASE(0x0768)
+#define S5P_HDCP_OFFSET_TX_3 S5P_HDMI_BASE(0x076C)
+#define S5P_HDCP_CYCLE_AA S5P_HDMI_BASE(0x0770)
+#define S5P_TG_CMD S5P_HDMI_BASE(0x1000)
+#define S5P_TG_H_FSZ_L S5P_HDMI_BASE(0x1018)
+#define S5P_TG_H_FSZ_H S5P_HDMI_BASE(0x101C)
+#define S5P_TG_HACT_ST_L S5P_HDMI_BASE(0x1020)
+#define S5P_TG_HACT_ST_H S5P_HDMI_BASE(0x1024)
+#define S5P_TG_HACT_SZ_L S5P_HDMI_BASE(0x1028)
+#define S5P_TG_HACT_SZ_H S5P_HDMI_BASE(0x102C)
+#define S5P_TG_V_FSZ_L S5P_HDMI_BASE(0x1030)
+#define S5P_TG_V_FSZ_H S5P_HDMI_BASE(0x1034)
+#define S5P_TG_VSYNC_L S5P_HDMI_BASE(0x1038)
+#define S5P_TG_VSYNC_H S5P_HDMI_BASE(0x103C)
+#define S5P_TG_VSYNC2_L S5P_HDMI_BASE(0x1040)
+#define S5P_TG_VSYNC2_H S5P_HDMI_BASE(0x1044)
+#define S5P_TG_VACT_ST_L S5P_HDMI_BASE(0x1048)
+#define S5P_TG_VACT_ST_H S5P_HDMI_BASE(0x104C)
+#define S5P_TG_VACT_SZ_L S5P_HDMI_BASE(0x1050)
+#define S5P_TG_VACT_SZ_H S5P_HDMI_BASE(0x1054)
+#define S5P_TG_FIELD_CHG_L S5P_HDMI_BASE(0x1058)
+#define S5P_TG_FIELD_CHG_H S5P_HDMI_BASE(0x105C)
+#define S5P_TG_VACT_ST2_L S5P_HDMI_BASE(0x1060)
+#define S5P_TG_VACT_ST2_H S5P_HDMI_BASE(0x1064)
+#define S5P_TG_VSYNC_TOP_HDMI_L S5P_HDMI_BASE(0x1078)
+#define S5P_TG_VSYNC_TOP_HDMI_H S5P_HDMI_BASE(0x107C)
+#define S5P_TG_VSYNC_BOT_HDMI_L S5P_HDMI_BASE(0x1080)
+#define S5P_TG_VSYNC_BOT_HDMI_H S5P_HDMI_BASE(0x1084)
+#define S5P_TG_FIELD_TOP_HDMI_L S5P_HDMI_BASE(0x1088)
+#define S5P_TG_FIELD_TOP_HDMI_H S5P_HDMI_BASE(0x108C)
+#define S5P_TG_FIELD_BOT_HDMI_L S5P_HDMI_BASE(0x1090)
+#define S5P_TG_FIELD_BOT_HDMI_H S5P_HDMI_BASE(0x1094)
+#define S5P_SPDIFIN_CLK_CTRL S5P_HDMI_BASE(0x5000)
+#define S5P_SPDIFIN_OP_CTRL S5P_HDMI_BASE(0x5004)
+#define S5P_SPDIFIN_IRQ_MASK S5P_HDMI_BASE(0x5008)
+#define S5P_SPDIFIN_IRQ_STATUS S5P_HDMI_BASE(0x500C)
+#define S5P_SPDIFIN_CONFIG_1 S5P_HDMI_BASE(0x5010)
+#define S5P_SPDIFIN_CONFIG_2 S5P_HDMI_BASE(0x5014)
+#define S5P_SPDIFIN_USER_VALUE_1 S5P_HDMI_BASE(0x5020)
+#define S5P_SPDIFIN_USER_VALUE_2 S5P_HDMI_BASE(0x5024)
+#define S5P_SPDIFIN_USER_VALUE_3 S5P_HDMI_BASE(0x5028)
+#define S5P_SPDIFIN_USER_VALUE_4 S5P_HDMI_BASE(0x502C)
+#define S5P_SPDIFIN_CH_STATUS_0_1 S5P_HDMI_BASE(0x5030)
+#define S5P_SPDIFIN_CH_STATUS_0_2 S5P_HDMI_BASE(0x5034)
+#define S5P_SPDIFIN_CH_STATUS_0_3 S5P_HDMI_BASE(0x5038)
+#define S5P_SPDIFIN_CH_STATUS_0_4 S5P_HDMI_BASE(0x503C)
+#define S5P_SPDIFIN_CH_STATUS_1 S5P_HDMI_BASE(0x5040)
+#define S5P_SPDIFIN_FRAME_PERIOD_1 S5P_HDMI_BASE(0x5048)
+#define S5P_SPDIFIN_FRAME_PERIOD_2 S5P_HDMI_BASE(0x504C)
+#define S5P_SPDIFIN_Pc_INFO_1 S5P_HDMI_BASE(0x5050)
+#define S5P_SPDIFIN_Pc_INFO_2 S5P_HDMI_BASE(0x5054)
+#define S5P_SPDIFIN_Pd_INFO_1 S5P_HDMI_BASE(0x5058)
+#define S5P_SPDIFIN_Pd_INFO_2 S5P_HDMI_BASE(0x505C)
+#define S5P_SPDIFIN_DATA_BUF_0_1 S5P_HDMI_BASE(0x5060)
+#define S5P_SPDIFIN_DATA_BUF_0_2 S5P_HDMI_BASE(0x5064)
+#define S5P_SPDIFIN_DATA_BUF_0_3 S5P_HDMI_BASE(0x5068)
+#define S5P_SPDIFIN_USER_BUF_0 S5P_HDMI_BASE(0x506C)
+#define S5P_SPDIFIN_DATA_BUF_1_1 S5P_HDMI_BASE(0x5070)
+#define S5P_SPDIFIN_DATA_BUF_1_2 S5P_HDMI_BASE(0x5074)
+#define S5P_SPDIFIN_DATA_BUF_1_3 S5P_HDMI_BASE(0x5078)
+#define S5P_SPDIFIN_USER_BUF_1 S5P_HDMI_BASE(0x507C)
+#define S5P_HAES_CON S5P_HDMI_BASE(0x6000)
+#define S5P_HAES_DATA_SIZE_L S5P_HDMI_BASE(0x6020)
+#define S5P_HAES_DATA_SIZE_H S5P_HDMI_BASE(0x6024)
+#define S5P_HAES_DATA S5P_HDMI_BASE(0x6030)
+
+#define HDMI_TPGEN_0 S5P_HDMI_BASE(0x500)
+#define HDMI_TPGEN_1 S5P_HDMI_BASE(0x504)
+#define HDMI_TPGEN_2 S5P_HDMI_BASE(0x508)
+#define HDMI_TPGEN_3 S5P_HDMI_BASE(0x50c)
+#define HDMI_TPGEN_4 S5P_HDMI_BASE(0x510)
+#define HDMI_TPGEN_5 S5P_HDMI_BASE(0x514)
+#define HDMI_TPGEN_6 S5P_HDMI_BASE(0x518)
+
+#define BLUE_SCR_EN (1<<5)
+#define BLUE_SCR_DIS (0<<5)
+#define ASP_EN (1<<2)
+#define ASP_DIS (0<<2)
+#define PWDN_ENB_NORMAL (1<<1)
+#define PWDN_ENB_PD (0<<1)
+#define HDMI_EN (1<<0)
+#define HDMI_DIS (~HDMI_EN)
+
+#define PX_LMT_CTRL_BYPASS (0<<5)
+#define PX_LMT_CTRL_RGB (1<<5)
+#define PX_LMT_CTRL_YPBPR (2<<5)
+#define PX_LMT_CTRL_RESERVED (3<<5)
+
+#define VID_PREAMBLE_EN (0<<5)
+#define VID_PREAMBLE_DIS (1<<5)
+#define GUARD_BAND_EN (0<<1)
+#define GUARD_BAND_DIS (1<<1)
+
+
+#define AUTHEN_ACK_AUTH (1<<7)
+#define AUTHEN_ACK_NOT (0<<7)
+#define AUD_FIFO_OVF_FULL (1<<6)
+#define AUD_FIFO_OVF_NOT (0<<6)
+#define UPDATE_RI_INT_OCC (1<<4)
+#define UPDATE_RI_INT_NOT (0<<4)
+#define UPDATE_RI_INT_CLEAR (1<<4)
+#define UPDATE_PJ_INT_OCC (1<<3)
+#define UPDATE_PJ_INT_NOT (0<<3)
+#define UPDATE_PJ_INT_CLEAR (1<<3)
+#define EXCHANGEKSV_INT_OCC (1<<2)
+#define EXCHANGEKSV_INT_NOT (0<<2)
+#define EXCHANGEKSV_INT_CLEAR (1<<2)
+#define WATCHDOG_INT_OCC (1<<1)
+#define WATCHDOG_INT_NOT (0<<1)
+#define WATCHDOG_INT_CLEAR (1<<1)
+#define WTFORACTIVERX_INT_OCC (1)
+#define WTFORACTIVERX_INT_NOT (0)
+#define WTFORACTIVERX_INT_CLEAR (1)
+
+#define AUD_FIFO_OVF_EN (1<<6)
+#define AUD_FIFO_OVF_DIS (0<<6)
+#define UPDATE_RI_INT_EN (1<<4)
+#define UPDATE_RI_INT_DIS (0<<4)
+#define UPDATE_PJ_INT_EN (1<<3)
+#define UPDATE_PJ_INT_DIS (0<<3)
+#define EXCHANGEKSV_INT_EN (1<<2)
+#define EXCHANGEKSV_INT_DIS (0<<2)
+#define WATCHDOG_INT_EN (1<<1)
+#define WATCHDOG_INT_DIS (0<<1)
+#define WTFORACTIVERX_INT_EN (1)
+#define WTFORACTIVERX_INT_DIS (0)
+#define HDCP_STATUS_EN_ALL (UPDATE_RI_INT_EN|\
+ UPDATE_PJ_INT_DIS|\
+ EXCHANGEKSV_INT_EN|\
+ WATCHDOG_INT_EN|\
+ WTFORACTIVERX_INT_EN)
+
+#define HDCP_STATUS_DIS_ALL (~0x1f)
+
+#define SW_HPD_PLUGGED (1<<1)
+#define SW_HPD_UNPLUGGED (0<<1)
+
+#define HDMI_MODE_EN (1<<1)
+#define HDMI_MODE_DIS (0<<1)
+#define DVI_MODE_EN (1)
+#define DVI_MODE_DIS (0)
+
+#define HDCP_ENC_ENABLE (1)
+#define HDCP_ENC_DISABLE (0)
+
+#define SET_BLUESCREEN_0(a) (0xff&(a))
+
+#define SET_BLUESCREEN_1(a) (0xff&(a))
+
+#define SET_BLUESCREEN_2(a) (0xff&(a))
+
+#define SET_HDMI_YMAX(a) (0xff&(a))
+
+#define SET_HDMI_YMIN(a) (0xff&(a))
+
+#define SET_HDMI_CMAX(a) (0xff&(a))
+
+#define SET_HDMI_CMIN(a) (0xff&(a))
+
+
+#define SET_VBI_ST_MG(a) (0xff&(a))
+
+#define SET_VBI_END_MG(a) (0xff&(a))
+
+#define SET_VACT_ST_MG(a) (0xff&(a))
+
+
+#define SET_H_BLANK_L(a) (0xff&(a))
+
+#define SET_H_BLANK_H(a) (0x7&((a)>>8))
+
+#define SET_V2_BLANK_L(a) (0xff&(a))
+
+#define SET_V1_BLANK_L(a) ((0x1f&(a))<<3)
+#define SET_V2_BLANK_H(a) (0x7&((a)>>8))
+
+#define SET_V1_BLANK_H(a) (0x3f&((a)>>5))
+
+#define SET_V_LINE_L(a) (0xff&(a))
+
+#define SET_H_LINE_L(a) ((0xf&(a))<<4)
+#define SET_V_LINE_H(a) (0xf&((a)>>8))
+
+#define SET_H_LINE_H(a) (0xff&((a)>>4))
+
+#define V_SYNC_POL_ACT_LOW (1)
+#define V_SYNC_POL_ACT_HIGH (0)
+
+#define INT_PRO_MODE_INTERLACE (1)
+#define INT_PRO_MODE_PROGRESSIVE (0)
+
+#define SET_V_BOT_ST_L(a) (0xff&(a))
+
+#define SET_V_BOT_END_L(a) ((0x1f&(a))<<3)
+#define SET_V_BOT_ST_H(a) (0x7&((a)>>8))
+
+#define SET_V_BOT_END_H(a) (0x3f&((a)>>5))
+
+
+#define SET_HSYNC_START_L(a) (0xff&(a))
+
+#define SET_HSYNC_END_L(a) ((0x3f&(a))<<2)
+#define SET_HSYNC_START_H(a) (0x3&((a)>>8))
+
+#define SET_HSYNC_POL_ACT_LOW (1<<4)
+#define SET_HSYNC_POL_ACT_HIGH (0<<4)
+#define SET_HSYNC_END_H(a) (0xf&((a)>>6))
+
+#define SET_VSYNC_T_END_L(a) (0xff&(a))
+
+#define SET_VSYNC_T_ST_L(a) ((0xf&(a))<<4)
+#define SET_VSYNC_T_END_H(a) (0xf&((a)>>8))
+
+#define SET_VSYNC_T_ST_H(a) (0xff&((a)>>4))
+
+#define SET_VSYNC_B_END_L(a) (0xff&(a))
+
+#define SET_VSYNC_B_ST_L(a) ((0xf&(a))<<4)
+#define SET_VSYNC_B_END_H(a) (0xf&((a)>>8))
+
+#define SET_VSYNC_B_ST_H(a) (0xff&((a)>>4))
+
+
+#define SET_VSYNC_H_POST_END_L(a) (0xff&(a))
+
+#define SET_VSYNC_H_POST_ST_L(a) ((0xf&(a))<<4)
+#define SET_VSYNC_H_POST_END_H(a) (0xf&((a)>>8))
+
+#define SET_VSYNC_H_POST_ST_H(a) (0xff&((a)>>4))
+
+
+#define SACD_EN (1<<5)
+#define SACD_DIS (0<<5)
+#define AUD_MODE_MULTI_CH (1<<4)
+#define AUD_MODE_2_CH (0<<4)
+#define SET_SP_PRE(a) (0xf&(a))
+
+#define SET_SP_FLAT(a) (0xf&(a))
+
+
+#define SPK3R_SEL_I_PCM0L (0<<27)
+#define SPK3R_SEL_I_PCM0R (1<<27)
+#define SPK3R_SEL_I_PCM1L (2<<27)
+#define SPK3R_SEL_I_PCM1R (3<<27)
+#define SPK3R_SEL_I_PCM2L (4<<27)
+#define SPK3R_SEL_I_PCM2R (5<<27)
+#define SPK3R_SEL_I_PCM3L (6<<27)
+#define SPK3R_SEL_I_PCM3R (7<<27)
+#define SPK3L_SEL_I_PCM0L (0<<24)
+#define SPK3L_SEL_I_PCM0R (1<<24)
+#define SPK3L_SEL_I_PCM1L (2<<24)
+#define SPK3L_SEL_I_PCM1R (3<<24)
+#define SPK3L_SEL_I_PCM2L (4<<24)
+#define SPK3L_SEL_I_PCM2R (5<<24)
+#define SPK3L_SEL_I_PCM3L (6<<24)
+#define SPK3L_SEL_I_PCM3R (7<<24)
+#define SPK2R_SEL_I_PCM0L (0<<19)
+#define SPK2R_SEL_I_PCM0R (1<<19)
+#define SPK2R_SEL_I_PCM1L (2<<19)
+#define SPK2R_SEL_I_PCM1R (3<<19)
+#define SPK2R_SEL_I_PCM2L (4<<19)
+#define SPK2R_SEL_I_PCM2R (5<<19)
+#define SPK2R_SEL_I_PCM3L (6<<19)
+#define SPK2R_SEL_I_PCM3R (7<<19)
+#define SPK2L_SEL_I_PCM0L (0<<16)
+#define SPK2L_SEL_I_PCM0R (1<<16)
+#define SPK2L_SEL_I_PCM1L (2<<16)
+#define SPK2L_SEL_I_PCM1R (3<<16)
+#define SPK2L_SEL_I_PCM2L (4<<16)
+#define SPK2L_SEL_I_PCM2R (5<<16)
+#define SPK2L_SEL_I_PCM3L (6<<16)
+#define SPK2L_SEL_I_PCM3R (7<<16)
+#define SPK1R_SEL_I_PCM0L (0<<11)
+#define SPK1R_SEL_I_PCM0R (1<<11)
+#define SPK1R_SEL_I_PCM1L (2<<11)
+#define SPK1R_SEL_I_PCM1R (3<<11)
+#define SPK1R_SEL_I_PCM2L (4<<11)
+#define SPK1R_SEL_I_PCM2R (5<<11)
+#define SPK1R_SEL_I_PCM3L (6<<11)
+#define SPK1R_SEL_I_PCM3R (7<<11)
+#define SPK1L_SEL_I_PCM0L (0<<8)
+#define SPK1L_SEL_I_PCM0R (1<<8)
+#define SPK1L_SEL_I_PCM1L (2<<8)
+#define SPK1L_SEL_I_PCM1R (3<<8)
+#define SPK1L_SEL_I_PCM2L (4<<8)
+#define SPK1L_SEL_I_PCM2R (5<<8)
+#define SPK1L_SEL_I_PCM3L (6<<8)
+#define SPK1L_SEL_I_PCM3R (7<<8)
+#define SPK0R_SEL_I_PCM0L (0<<3)
+#define SPK0R_SEL_I_PCM0R (1<<3)
+#define SPK0R_SEL_I_PCM1L (2<<3)
+#define SPK0R_SEL_I_PCM1R (3<<3)
+#define SPK0R_SEL_I_PCM2L (4<<3)
+#define SPK0R_SEL_I_PCM2R (5<<3)
+#define SPK0R_SEL_I_PCM3L (6<<3)
+#define SPK0R_SEL_I_PCM3R (7<<3)
+#define SPK0L_SEL_I_PCM0L (0)
+#define SPK0L_SEL_I_PCM0R (1)
+#define SPK0L_SEL_I_PCM1L (2)
+#define SPK0L_SEL_I_PCM1R (3)
+#define SPK0L_SEL_I_PCM2L (4)
+#define SPK0L_SEL_I_PCM2R (5)
+#define SPK0L_SEL_I_PCM3L (6)
+#define SPK0L_SEL_I_PCM3R (7)
+
+#define ALT_CTS_RATE_CTS_1 (0<<3)
+#define ALT_CTS_RATE_CTS_11 (1<<3)
+#define ALT_CTS_RATE_CTS_21 (2<<3)
+#define ALT_CTS_RATE_CTS_31 (3<<3)
+#define ACR_TX_MODE_NO_TX (0)
+#define ACR_TX_MODE_TX_ONCE (1)
+#define ACR_TX_MODE_TXCNT_VBI (2)
+#define ACR_TX_MODE_TX_VPC (3)
+#define ACR_TX_MODE_MESURE_CTS (4)
+
+
+#define SET_ACR_MCTS(a) (0xfffff&(a))
+
+
+#define SET_ACR_CTS(a) (0xfffff&(a))
+
+
+#define SET_ACR_N(a) (0xfffff&(a))
+
+#define SET_ACR_LSB2(a) (0xff&(a))
+
+#define SET_ACR_TXCNT(a) (0x1f&(a))
+
+#define SET_ACR_TX_INTERNAL(a) (0xff&(a))
+
+#define SET_ACR_CTS_OFFSET(a) (0xff&(a))
+
+#define GCP_CON_NO_TRAN (0)
+#define GCP_CON_TRANS_ONCE (1)
+#define GCP_CON_TRANS_EVERY_VSYNC (2)
+
+#define SET_GCP_BYTE1(a) (0xff&(a))
+
+
+#define SET_ACP_FR_RATE(a) ((0x1f&(a))<<3)
+#define ACP_CON_NO_TRAN (0)
+#define ACP_CON_TRANS_ONCE (1)
+#define ACP_CON_TRANS_EVERY_VSYNC (2)
+
+#define SET_ACP_TYPE(a) (0xff&(a))
+
+#define SET_ACP_DATA(a) (0xff&(a))
+
+#define SET_ISRC_FR_RATE(a) ((0x1f&(a))<<3)
+#define ISRC_EN (1<<2)
+#define ISRC_DIS (0<<2)
+#define ISRC_TX_CON_NO_TRANS (0)
+#define ISRC_TX_CON_TRANS_ONCE (1)
+#define ISRC_TX_CON_TRANS_EVERY_VSYNC (2)
+
+#define SET_ISRC1_HEADER(a) (0xff&(a))
+
+#define SET_ISRC1_DATA(a) (0xff&(a))
+
+#define SET_ISRC2_DATA(a) (0xff&(a))
+
+
+#define AVI_TX_CON_NO_TRANS (0)
+#define AVI_TX_CON_TRANS_ONCE (1)
+#define AVI_TX_CON_TRANS_EVERY_VSYNC (2)
+
+
+#define SET_AVI_CHECK_SUM(a) (0xff&(a))
+
+#define SET_AVI_BYTE(a) (0xff&(a))
+
+
+#define AUI_TX_CON_NO_TRANS (0)
+#define AUI_TX_CON_TRANS_ONCE (1)
+#define AUI_TX_CON_TRANS_EVERY_VSYNC (2)
+
+
+#define SET_AUI_CHECK_SUM(a) (0xff&(a))
+
+#define SET_AUI_BYTE(a) (0xff&(a))
+
+
+#define MPG_TX_CON_NO_TRANS (0)
+#define MPG_TX_CON_TRANS_ONCE (1)
+#define MPG_TX_CON_TRANS_EVERY_VSYNC (2)
+
+
+#define SET_MPG_CHECK_SUM(a) (0xff&(a))
+
+
+#define SET_MPG_BYTE(a) (0xff&(a))
+
+
+#define SPD_TX_CON_NO_TRANS (0)
+#define SPD_TX_CON_TRANS_ONCE (1)
+#define SPD_TX_CON_TRANS_EVERY_VSYNC (2)
+
+
+#define SET_SPD_HEADER(a) (0xff&(a))
+
+#define SET_SPD_DATA(a) (0xff&(a))
+
+
+#define OUT_OFFSET_SEL_RGB_FR (0<<4)
+#define OUT_OFFSET_SEL_RGB_LR (2<<4)
+#define OUT_OFFSET_SEL_YCBCR (3<<4)
+#define IN_CLIP_EN (1<<2)
+#define IN_CLIP_DIS (0<<2)
+#define IN_OFFSET_SEL_RGB_FR (0)
+#define IN_OFFSET_SEL_RGB_LR (2)
+#define IN_OFFSET_SEL_YCBCR (3)
+
+#define SET_HDMI_CSC_COEF_L(a) (0xff&(a))
+#define SET_HDMI_CSC_COEF_H(a) (0x3&((a)>>8))
+
+#define SET_HDMI_SHA1(a) (0xff&(a))
+
+#define GETSYNC_TYPE_EN (1<<4)
+#define GETSYNC_TYPE_DIS (0<<4)
+#define GETSYNC_EN (1<<3)
+#define GETSYNC_DIS (0<<3)
+#define FIELD_EN (1<<2)
+#define FIELD_DIS (0<<2)
+#define TG_EN (1)
+#define TG_DIS (0)
+
+#define SET_TG_H_FSZ_L(a) (0xff&(a))
+
+#define SET_TG_H_FSZ_H(a) (0x1f&((a)>>8))
+
+#define SET_TG_HACT_ST_L(a) (0xff&(a))
+
+#define SET_TG_HACT_ST_H(a) (0xf&((a)>>8))
+
+#define SET_TG_HACT_SZ_L(a) (0xff&(a))
+
+#define SET_TG_HACT_SZ_H(a) (0xf&((a)>>8))
+
+#define SET_TG_V_FSZ_L(a) (0xff&(a))
+
+#define SET_TG_V_FSZ_H(a) (0x7&((a)>>8))
+
+#define SET_TG_VSYNC_L(a) (0xff&(a))
+
+#define SET_TG_VSYNC_H(a) (0x7&((a)>>8))
+
+#define SET_TG_VSYNC2_L(a) (0xff&(a))
+
+#define SET_TG_VSYNC2_H(a) (0x7&((a)>>8))
+
+#define SET_TG_VACT_ST_L(a) (0xff&(a))
+
+#define SET_TG_VACT_ST_H(a) (0x7&((a)>>8))
+
+#define SET_TG_VACT_SZ_L(a) (0xff&(a))
+
+#define SET_TG_VACT_SZ_H(a) (0x7&((a)>>8))
+
+#define SET_TG_FIELD_CHG_L(a) (0xff&(a))
+
+#define SET_TG_FIELD_CHG_H(a) (0x7&((a)>>8))
+
+#define SET_TG_VACT_ST2_L(a) (0xff&(a))
+
+#define SET_TG_VACT_ST2_H(a) (0x7&((a)>>8))
+
+#define SET_TG_VSYNC_TOP_HDMI_L(a) (0xff&(a))
+
+#define SET_TG_VSYNC_TOP_HDMI_H(a) (0x7&((a)>>8))
+
+#define SET_TG_VSYNC_BOT_HDMI_L(a) (0xff&(a))
+
+#define SET_TG_VSYNC_BOT_HDMI_H(a) (0x7&((a)>>8))
+
+#define SET_TG_FIELD_TOP_HDMI_L(a) (0xff&(a))
+
+#define SET_TG_FIELD_TOP_HDMI_H(a) (0x7&((a)>>8))
+
+#define SET_TG_FIELD_BOT_HDMI_L(a) (0xff&(a))
+
+#define SET_TG_FIELD_BOT_HDMI_H(a) (0x7&((a)>>8))
+
+
+#define IRQ_WRONG_SIGNAL_ENABLE (1<<0)
+#define IRQ_CH_STATUS_RECOVERED_ENABLE (1<<1)
+#define IRQ_WRONG_PREAMBLE_ENABLE (1<<2)
+#define IRQ_STREAM_HEADER_NOT_DETECTED_ENABLE (1<<3)
+#define IRQ_STREAM_HEADER_DETECTED_ENABLE (1<<4)
+#define IRQ_STREAM_HEADER_NOT_DETECTED_AT_RIGHTTIME_ENABLE (1<<5)
+#define IRQ_ABNORMAL_PD_ENABLE (1<<6)
+#define IRQ_BUFFER_OVERFLOW_ENABLE (1<<7)
+
+#define CONFIG_FILTER_3_SAMPLE (0<<6)
+#define CONFIG_FILTER_2_SAMPLE (1<<6)
+#define CONFIG_LINEAR_PCM_TYPE (0<<5)
+#define CONFIG_NON_LINEAR_PCM_TYPE (1<<5)
+#define CONFIG_PCPD_AUTO_SET (0<<4)
+#define CONFIG_PCPD_MANUAL_SET (1<<4)
+#define CONFIG_WORD_LENGTH_AUTO_SET (0<<3)
+#define CONFIG_WORD_LENGTH_MANUAL_SET (1<<3)
+#define CONFIG_U_V_C_P_NEGLECT (0<<2)
+#define CONFIG_U_V_C_P_REPORT (1<<2)
+#define CONFIG_BURST_SIZE_1 (0<<1)
+#define CONFIG_BURST_SIZE_2 (1<<1)
+#define CONFIG_DATA_ALIGN_16BIT (0<<0)
+#define CONFIG_DATA_ALIGN_32BIT (1<<0)
+
+
+#define AUTHEN_ACK_POS 7
+#define AUD_FIFO_OVF_POS 6
+
+#define UPDATE_RI_INT_POS 4
+#define UPDATE_PJ_INT_POS 3
+#define EXCHANGEKSV_INT_POS 2
+#define WATCHDOG_INT_POS 1
+#define WTFORACTIVERX_INT_POS 0
+
+#define AUTHENTICATED (0x1<<7)
+#define NOT_YET_AUTHENTICATED (0x0<<7)
+#define AUD_FIFO_OVF_INT_OCCURRED (0x1<<6)
+#define AUD_FIFO_OVF_INT_NOT_OCCURRED (0x0<<6)
+
+#define UPDATE_RI_INT_OCCURRED (0x1<<4)
+#define UPDATE_RI_INT_NOT_OCCURRED (0x0<<4)
+#define UPDATE_PJ_INT_OCCURRED (0x1<<3)
+#define UPDATE_PJ_INT_NOT_OCCURRED (0x0<<3)
+#define EXCHANGEKSV_INT_OCCURRED (0x1<<2)
+#define EXCHANGEKSV_INT_NOT_OCCURRED (0x0<<2)
+#define WATCHDOG_INT_OCCURRED (0x1<<1)
+#define WATCHDOG_INT_NOT_OCCURRED (0x0<<1)
+#define WTFORACTIVERX_INT_OCCURRED (0x1<<0)
+#define WTFORACTIVERX_INT_NOT_OCCURRED (0x0<<0)
+
+#define AUD_FIFO_OVF_INT_EN (0x1<<6)
+#define AUD_FIFO_OVF_INT_DIS (0x0<<6)
+
+
+
+#define EN_PJ_EN (0x1<<4)
+#define EN_PJ_DIS (~EN_PJ_EN)
+
+#define SET_REPEATER_TIMEOUT (0x1<<2)
+#define CLEAR_REPEATER_TIMEOUT (~SET_REPEATER_TIMEOUT)
+#define CP_DESIRED_EN (0x1<<1)
+#define CP_DESIRED_DIS (~CP_DESIRED_EN)
+#define ENABLE_1_DOT_1_FEATURE_EN (0x1<<0)
+#define ENABLE_1_DOT_1_FEATURE_DIS (~ENABLE_1_DOT_1_FEATURE_EN)
+
+#define Pi_MATCH_RESULT__YES ((0x1<<3)<<(0x1<<2))
+#define Pi_MATCH_RESULT__NO ((0x1<<3)<<(0x0<<2))
+#define Ri_MATCH_RESULT__YES ((0x1<<1)<<(0x1<<0))
+#define Ri_MATCH_RESULT__NO ((0x1<<1)<<(0x0<<0))
+#define CLEAR_ALL_RESULTS 0x0
+
+#define HDCP_ENC_DIS (0x0<<0)
+
+#define REPEATER_SET (0x1<<6)
+#define REPEATERP_CLEAR (0x1<<6)
+#define READY_SET (0x1<<5)
+#define READY_CLEAR (0x1<<5)
+#define FAST_SET (0x1<<4)
+#define FAST_CLEAR (0x1<<4)
+
+#define ONE_DOT_ONE_FEATURES_SET (0x1<<1)
+#define ONE_DOT_ONE_FEATURES_CLEAR (0x1<<1)
+#define FAST_REAUTHENTICATION_SET (0x1<<0)
+#define FAST_REAUTHENTICATION_CLEAR (0x1<<0)
+
+
+#define SCRAMBLER_KEY_START_EN (0x1<<7)
+#define SCRAMBLER_KEY_START_DIS (~SCRAMBLER_KEY_START_EN)
+#define SCRAMBLER_KEY_DONE (0x1<<6)
+#define SCRAMBLER_KEY_GENERATING (0x0<<6)
+#define HAES_START_EN (0x1<<0)
+#define HAES_DECRYPTION_DONE (0x0<<0)
+
+
+#define AN_SIZE 8
+#define AKSV_SIZE 5
+#define BKSV_SIZE 5
+#define HDCPLink_Addr 0x74
+
+
+#define CABLE_PLUGGED (1<<1)
+#define CABLE_UNPLUGGED (0<<1)
+
+#define DDC_Addr 0xA0
+#define eDDC_Addr 0x60
+#define HDCPLink_Addr 0x74
+
+#define HDCP_Bksv 0x00
+#define HDCP_Aksv 0x10
+#define HDCP_Ainfo 0x15
+#define HDCP_An 0x18
+#define HDCP_Ri 0x08
+#define HDCP_Bcaps 0x40
+#define HDCP_BStatus 0x41
+#define HDCP_Pj 0x0a
+
+#define HDCP_KSVFIFO 0x43
+#define HDCP_SHA1 0x20
+
+#define HDMI_MODE_HDMI 0
+#define HDMI_MODE_DVI 1
+
+#define EDID_SEGMENT_ID 0x60
+#define EDID_SEGMENT0 0x00
+#define EDID_SEGMENT1 0x01
+
+#define EDID_DEVICE_ID 0xA0
+#define EDID_ADDR_START 0x00
+#define EDID_ADDR_EXT 0x80
+#define EDID_RCOUNT 127
+
+#define EDID_POS_EXTENSION 0x7E
+#define EDID_POS_CHECKSUM 0x7F
+#define VALID_EDID 0xA5
+#define NO_VALID_EDID 0
+
+#define EDID_POS_RBUFFER0 0x00
+#define EDID_POS_RBUFFER1 0x80
+#define EDID_POS_RBUFFER2 0x100
+#define EDID_POS_RBUFFER3 0x180
+
+#define EDID_TIMING_EXT_TAG_ADDR_POS 0x80
+#define EDID_TIMING_EXT_REV_NUMBER 0x81
+#define EDID_DETAILED_TIMING_OFFSET_POS 0x82
+#define EDID_COLOR_SPACE_ADDR 0x83
+#define EDID_DATA_BLOCK_ADDRESS 0x84
+#define EDID_TIMING_EXT_TAG_VAL 0x02
+#define EDID_YCBCR444_CS_MASK 0x20
+#define EDID_YCBCR422_CS_MASK 0x10
+#define EDID_TAG_CODE_MASK 0xE0
+#define EDID_DATA_BLOCK_SIZE_MASK 0x1F
+#define EDID_NATIVE_RESOLUTION_MASK 0x80
+
+#define EDID_SHORT_AUD_DEC_TAG 0x20
+#define EDID_SHORT_VID_DEC_TAG 0x40
+#define EDID_HDMI_VSDB_TAG 0x60
+#define EDID_SPEAKER_ALLOCATION_TAG 0x80
+
+#define COLOR_SPACE_RGB 0
+#define COLOR_SPACE_YCBCR444 1
+#define COLOR_SPACE_YCBCR422 2
+
+#define SHORT_VID_720_480P_4_3_NT 0x01
+#define SHORT_VID_720_480P_16_9_NT 0x02
+#define SHORT_VID_1280_720P_16_9_NT 0x04
+#define SHORT_VID_1920_1080i_16_9_NT 0x08
+#define SHORT_VID_720_576P_4_3_PAL 0x10
+#define SHORT_VID_720_576P_16_9_PAL 0x20
+#define SHORT_VID_1280_720P_16_9_PAL 0x40
+#define SHORT_VID_1920_1080i_16_9_PAL 0x80
+
+#define SET_HDMI_RESOLUTION_480P 0x00
+#define SET_HDMI_RESOLUTION_720P 0x01
+#define SET_HDMI_RESOLUTION_1080i 0x02
+
+
+#define HDMI_WAIT_TIMEOUT 20
+#define AUTHENTICATION_SUCCESS 0
+#define AUTHENTICATION_FAILURE 1
+#define AUTHENTICATION_FAIL_CNT 2
+
+
+#define HDCP_MAX_DEVS 128
+#define HDCP_KSV_SIZE 5
+
+#define CMD_IIC_ADDRMODE_CHANGE 0xFF
+
+#define IIC_ADDRMODE_1 0
+#define IIC_ADDRMODE_2 1
+#define IIC_ADDRMODE_3 2
+#define HDMI_IIC_ADDRMODE IIC_ADDRMODE_1
+
+#define IIC_ACK 0
+#define IIC_NOACK 1
+
+#define EDID_POS_ERROR 512
+#define R_VAL_RETRY_CNT 5
+
+#define CABLE_INSERT 1
+#define CABLE_REMOVE (~CABLE_INSERT)
+
+#endif
+
+
diff --git a/drivers/media/video/samsung/tv20/s5pc100/regs/regs-sdaout.h b/drivers/media/video/samsung/tv20/s5pc100/regs/regs-sdaout.h
new file mode 100644
index 0000000..02dacd0
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/s5pc100/regs/regs-sdaout.h
@@ -0,0 +1,455 @@
+/* linux/drivers/media/video/samsung/tv20/s5pc100/regs/regs-sdout.h
+ *
+ * TV Encoder register header file for Samsung TVOut driver
+ *
+ * Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_REGS_SDAOUT_H
+
+#include <mach/map.h>
+
+#define S5P_SDAOUT_BASE(x) (x)
+
+#define S5P_SDO_CLKCON S5P_SDAOUT_BASE(0x0000)
+#define S5P_SDO_CONFIG S5P_SDAOUT_BASE(0x0008)
+#define S5P_SDO_SCALE S5P_SDAOUT_BASE(0x000C)
+#define S5P_SDO_SYNC S5P_SDAOUT_BASE(0x0010)
+#define S5P_SDO_VBI S5P_SDAOUT_BASE(0x0014)
+#define S5P_SDO_SCALE_CH0 S5P_SDAOUT_BASE(0x001C)
+#define S5P_SDO_SCALE_CH1 S5P_SDAOUT_BASE(0x0020)
+#define S5P_SDO_SCALE_CH2 S5P_SDAOUT_BASE(0x0024)
+#define S5P_SDO_YCDELAY S5P_SDAOUT_BASE(0x0034)
+#define S5P_SDO_SCHLOCK S5P_SDAOUT_BASE(0x0038)
+#define S5P_SDO_DAC S5P_SDAOUT_BASE(0x003C)
+#define S5P_SDO_FINFO S5P_SDAOUT_BASE(0x0040)
+#define S5P_SDO_Y0 S5P_SDAOUT_BASE(0x0044)
+#define S5P_SDO_Y1 S5P_SDAOUT_BASE(0x0048)
+#define S5P_SDO_Y2 S5P_SDAOUT_BASE(0x004C)
+#define S5P_SDO_Y3 S5P_SDAOUT_BASE(0x0050)
+#define S5P_SDO_Y4 S5P_SDAOUT_BASE(0x0054)
+#define S5P_SDO_Y5 S5P_SDAOUT_BASE(0x0058)
+#define S5P_SDO_Y6 S5P_SDAOUT_BASE(0x005C)
+#define S5P_SDO_Y7 S5P_SDAOUT_BASE(0x0060)
+#define S5P_SDO_Y8 S5P_SDAOUT_BASE(0x0064)
+#define S5P_SDO_Y9 S5P_SDAOUT_BASE(0x0068)
+#define S5P_SDO_Y10 S5P_SDAOUT_BASE(0x006C)
+#define S5P_SDO_Y11 S5P_SDAOUT_BASE(0x0070)
+#define S5P_SDO_CB0 S5P_SDAOUT_BASE(0x0080)
+#define S5P_SDO_CB1 S5P_SDAOUT_BASE(0x0084)
+#define S5P_SDO_CB2 S5P_SDAOUT_BASE(0x0088)
+#define S5P_SDO_CB3 S5P_SDAOUT_BASE(0x008C)
+#define S5P_SDO_CB4 S5P_SDAOUT_BASE(0x0090)
+#define S5P_SDO_CB5 S5P_SDAOUT_BASE(0x0094)
+#define S5P_SDO_CB6 S5P_SDAOUT_BASE(0x0098)
+#define S5P_SDO_CB7 S5P_SDAOUT_BASE(0x009C)
+#define S5P_SDO_CB8 S5P_SDAOUT_BASE(0x00A0)
+#define S5P_SDO_CB9 S5P_SDAOUT_BASE(0x00A4)
+#define S5P_SDO_CB10 S5P_SDAOUT_BASE(0x00A8)
+#define S5P_SDO_CB11 S5P_SDAOUT_BASE(0x00AC)
+#define S5P_SDO_CR0 S5P_SDAOUT_BASE(0x00C0)
+#define S5P_SDO_CR1 S5P_SDAOUT_BASE(0x00C4)
+#define S5P_SDO_CR2 S5P_SDAOUT_BASE(0x00C8)
+#define S5P_SDO_CR3 S5P_SDAOUT_BASE(0x00CC)
+#define S5P_SDO_CR4 S5P_SDAOUT_BASE(0x00D0)
+#define S5P_SDO_CR5 S5P_SDAOUT_BASE(0x00D4)
+#define S5P_SDO_CR6 S5P_SDAOUT_BASE(0x00D8)
+#define S5P_SDO_CR7 S5P_SDAOUT_BASE(0x00DC)
+#define S5P_SDO_CR8 S5P_SDAOUT_BASE(0x00E0)
+#define S5P_SDO_CR9 S5P_SDAOUT_BASE(0x00E4)
+#define S5P_SDO_CR10 S5P_SDAOUT_BASE(0x00E8)
+#define S5P_SDO_CR11 S5P_SDAOUT_BASE(0x00EC)
+#define S5P_SDO_MV_ON S5P_SDAOUT_BASE(0x0100)
+#define S5P_SDO_MV_SLINE_FIRST_EVEN S5P_SDAOUT_BASE(0x0104)
+#define S5P_SDO_MV_SLINE_FIRST_SPACE_EVEN S5P_SDAOUT_BASE(0x0108)
+#define S5P_SDO_MV_SLINE_FIRST_ODD S5P_SDAOUT_BASE(0x010C)
+#define S5P_SDO_MV_SLINE_FIRST_SPACE_ODD S5P_SDAOUT_BASE(0x0110)
+#define S5P_SDO_MV_SLINE_SPACING S5P_SDAOUT_BASE(0x0114)
+#define S5P_SDO_MV_STRIPES_NUMBER S5P_SDAOUT_BASE(0x0118)
+#define S5P_SDO_MV_STRIPES_THICKNESS S5P_SDAOUT_BASE(0x011C)
+#define S5P_SDO_MV_PSP_DURATION S5P_SDAOUT_BASE(0x0120)
+#define S5P_SDO_MV_PSP_FIRST S5P_SDAOUT_BASE(0x0124)
+#define S5P_SDO_MV_PSP_SPACING S5P_SDAOUT_BASE(0x0128)
+#define S5P_SDO_MV_SEL_LINE_PSP_AGC S5P_SDAOUT_BASE(0x012C)
+#define S5P_SDO_MV_SEL_FORMAT_PSP_AGC S5P_SDAOUT_BASE(0x0130)
+#define S5P_SDO_MV_PSP_AGC_A_ON S5P_SDAOUT_BASE(0x0134)
+#define S5P_SDO_MV_PSP_AGC_B_ON S5P_SDAOUT_BASE(0x0138)
+#define S5P_SDO_MV_BACK_PORCH S5P_SDAOUT_BASE(0x013C)
+#define S5P_SDO_MV_BURST_ADVANCED_ON S5P_SDAOUT_BASE(0x0140)
+#define S5P_SDO_MV_BURST_DURATION_ZONE1 S5P_SDAOUT_BASE(0x0144)
+#define S5P_SDO_MV_BURST_DURATION_ZONE2 S5P_SDAOUT_BASE(0x0148)
+#define S5P_SDO_MV_BURST_DURATION_ZONE3 S5P_SDAOUT_BASE(0x014C)
+#define S5P_SDO_MV_BURST_PHASE_ZONE S5P_SDAOUT_BASE(0x0150)
+#define S5P_SDO_MV_SLICE_PHASE_LINE S5P_SDAOUT_BASE(0x0154)
+#define S5P_SDO_MV_RGB_PROTECTION_ON S5P_SDAOUT_BASE(0x0158)
+#define S5P_SDO_MV_480P_PROTECTION_ON S5P_SDAOUT_BASE(0x015C)
+#define S5P_SDO_CCCON S5P_SDAOUT_BASE(0x0180)
+#define S5P_SDO_YSCALE S5P_SDAOUT_BASE(0x0184)
+#define S5P_SDO_CBSCALE S5P_SDAOUT_BASE(0x0188)
+#define S5P_SDO_CRSCALE S5P_SDAOUT_BASE(0x018C)
+#define S5P_SDO_CB_CR_OFFSET S5P_SDAOUT_BASE(0x0190)
+#define S5P_SDO_RGB_CC S5P_SDAOUT_BASE(0x0194)
+#define S5P_SDO_CVBS_CC_Y1 S5P_SDAOUT_BASE(0x0198)
+#define S5P_SDO_CVBS_CC_Y2 S5P_SDAOUT_BASE(0x019C)
+#define S5P_SDO_CVBS_CC_C S5P_SDAOUT_BASE(0x01A0)
+#define S5P_SDO_YC_CC_Y S5P_SDAOUT_BASE(0x01A4)
+#define S5P_SDO_YC_CC_C S5P_SDAOUT_BASE(0x01A8)
+#define S5P_SDO_CSC_525_PORCH S5P_SDAOUT_BASE(0x01B0)
+#define S5P_SDO_CSC_625_PORCH S5P_SDAOUT_BASE(0x01B4)
+#define S5P_SDO_RGBSYNC S5P_SDAOUT_BASE(0x01C0)
+#define S5P_SDO_OSFC00_0 S5P_SDAOUT_BASE(0x0200)
+#define S5P_SDO_OSFC01_0 S5P_SDAOUT_BASE(0x0204)
+#define S5P_SDO_OSFC02_0 S5P_SDAOUT_BASE(0x0208)
+#define S5P_SDO_OSFC03_0 S5P_SDAOUT_BASE(0x020C)
+#define S5P_SDO_OSFC04_0 S5P_SDAOUT_BASE(0x0210)
+#define S5P_SDO_OSFC05_0 S5P_SDAOUT_BASE(0x0214)
+#define S5P_SDO_OSFC06_0 S5P_SDAOUT_BASE(0x0218)
+#define S5P_SDO_OSFC07_0 S5P_SDAOUT_BASE(0x021C)
+#define S5P_SDO_OSFC08_0 S5P_SDAOUT_BASE(0x0220)
+#define S5P_SDO_OSFC09_0 S5P_SDAOUT_BASE(0x0224)
+#define S5P_SDO_OSFC10_0 S5P_SDAOUT_BASE(0x0228)
+#define S5P_SDO_OSFC11_0 S5P_SDAOUT_BASE(0x022C)
+#define S5P_SDO_OSFC12_0 S5P_SDAOUT_BASE(0x0230)
+#define S5P_SDO_OSFC13_0 S5P_SDAOUT_BASE(0x0234)
+#define S5P_SDO_OSFC14_0 S5P_SDAOUT_BASE(0x0238)
+#define S5P_SDO_OSFC15_0 S5P_SDAOUT_BASE(0x023C)
+#define S5P_SDO_OSFC16_0 S5P_SDAOUT_BASE(0x0240)
+#define S5P_SDO_OSFC17_0 S5P_SDAOUT_BASE(0x0244)
+#define S5P_SDO_OSFC18_0 S5P_SDAOUT_BASE(0x0248)
+#define S5P_SDO_OSFC19_0 S5P_SDAOUT_BASE(0x024C)
+#define S5P_SDO_OSFC20_0 S5P_SDAOUT_BASE(0x0250)
+#define S5P_SDO_OSFC21_0 S5P_SDAOUT_BASE(0x0254)
+#define S5P_SDO_OSFC22_0 S5P_SDAOUT_BASE(0x0258)
+#define S5P_SDO_OSFC23_0 S5P_SDAOUT_BASE(0x025C)
+#define S5P_SDO_XTALK0 S5P_SDAOUT_BASE(0x0260)
+#define S5P_SDO_XTALK1 S5P_SDAOUT_BASE(0x0264)
+#define S5P_SDO_XTALK2 S5P_SDAOUT_BASE(0x0268)
+#define S5P_SDO_BB_CTRL S5P_SDAOUT_BASE(0x026C)
+#define S5P_SDO_IRQ S5P_SDAOUT_BASE(0x0280)
+#define S5P_SDO_IRQMASK S5P_SDAOUT_BASE(0x0284)
+#define S5P_SDO_OSFC00_1 S5P_SDAOUT_BASE(0x02C0)
+#define S5P_SDO_OSFC01_1 S5P_SDAOUT_BASE(0x02C4)
+#define S5P_SDO_OSFC02_1 S5P_SDAOUT_BASE(0x02C8)
+#define S5P_SDO_OSFC03_1 S5P_SDAOUT_BASE(0x02CC)
+#define S5P_SDO_OSFC04_1 S5P_SDAOUT_BASE(0x02D0)
+#define S5P_SDO_OSFC05_1 S5P_SDAOUT_BASE(0x02D4)
+#define S5P_SDO_OSFC06_1 S5P_SDAOUT_BASE(0x02D8)
+#define S5P_SDO_OSFC07_1 S5P_SDAOUT_BASE(0x02DC)
+#define S5P_SDO_OSFC08_1 S5P_SDAOUT_BASE(0x02E0)
+#define S5P_SDO_OSFC09_1 S5P_SDAOUT_BASE(0x02E4)
+#define S5P_SDO_OSFC10_1 S5P_SDAOUT_BASE(0x02E8)
+#define S5P_SDO_OSFC11_1 S5P_SDAOUT_BASE(0x02EC)
+#define S5P_SDO_OSFC12_1 S5P_SDAOUT_BASE(0x02E0)
+#define S5P_SDO_OSFC13_1 S5P_SDAOUT_BASE(0x02F4)
+#define S5P_SDO_OSFC14_1 S5P_SDAOUT_BASE(0x02F8)
+#define S5P_SDO_OSFC15_1 S5P_SDAOUT_BASE(0x02FC)
+#define S5P_SDO_OSFC16_1 S5P_SDAOUT_BASE(0x0300)
+#define S5P_SDO_OSFC17_1 S5P_SDAOUT_BASE(0x0304)
+#define S5P_SDO_OSFC18_1 S5P_SDAOUT_BASE(0x0308)
+#define S5P_SDO_OSFC19_1 S5P_SDAOUT_BASE(0x030C)
+#define S5P_SDO_OSFC20_1 S5P_SDAOUT_BASE(0x0310)
+#define S5P_SDO_OSFC21_1 S5P_SDAOUT_BASE(0x0314)
+#define S5P_SDO_OSFC22_1 S5P_SDAOUT_BASE(0x0318)
+#define S5P_SDO_OSFC23_1 S5P_SDAOUT_BASE(0x031C)
+#define S5P_SDO_OSFC00_2 S5P_SDAOUT_BASE(0x0320)
+#define S5P_SDO_OSFC01_2 S5P_SDAOUT_BASE(0x0324)
+#define S5P_SDO_OSFC02_2 S5P_SDAOUT_BASE(0x0328)
+#define S5P_SDO_OSFC03_2 S5P_SDAOUT_BASE(0x032C)
+#define S5P_SDO_OSFC04_2 S5P_SDAOUT_BASE(0x0330)
+#define S5P_SDO_OSFC05_2 S5P_SDAOUT_BASE(0x0334)
+#define S5P_SDO_OSFC06_2 S5P_SDAOUT_BASE(0x0338)
+#define S5P_SDO_OSFC07_2 S5P_SDAOUT_BASE(0x033C)
+#define S5P_SDO_OSFC08_2 S5P_SDAOUT_BASE(0x0340)
+#define S5P_SDO_OSFC09_2 S5P_SDAOUT_BASE(0x0344)
+#define S5P_SDO_OSFC10_2 S5P_SDAOUT_BASE(0x0348)
+#define S5P_SDO_OSFC11_2 S5P_SDAOUT_BASE(0x034C)
+#define S5P_SDO_OSFC12_2 S5P_SDAOUT_BASE(0x0350)
+#define S5P_SDO_OSFC13_2 S5P_SDAOUT_BASE(0x0354)
+#define S5P_SDO_OSFC14_2 S5P_SDAOUT_BASE(0x0358)
+#define S5P_SDO_OSFC15_2 S5P_SDAOUT_BASE(0x035C)
+#define S5P_SDO_OSFC16_2 S5P_SDAOUT_BASE(0x0360)
+#define S5P_SDO_OSFC17_2 S5P_SDAOUT_BASE(0x0364)
+#define S5P_SDO_OSFC18_2 S5P_SDAOUT_BASE(0x0368)
+#define S5P_SDO_OSFC19_2 S5P_SDAOUT_BASE(0x036C)
+#define S5P_SDO_OSFC20_2 S5P_SDAOUT_BASE(0x0370)
+#define S5P_SDO_OSFC21_2 S5P_SDAOUT_BASE(0x0374)
+#define S5P_SDO_OSFC22_2 S5P_SDAOUT_BASE(0x0378)
+#define S5P_SDO_OSFC23_2 S5P_SDAOUT_BASE(0x037C)
+#define S5P_SDO_ARMCC S5P_SDAOUT_BASE(0x03C0)
+#define S5P_SDO_ARMWSS525 S5P_SDAOUT_BASE(0x03C4)
+#define S5P_SDO_ARMWSS625 S5P_SDAOUT_BASE(0x03C8)
+#define S5P_SDO_ARMCGMS525 S5P_SDAOUT_BASE(0x03CC)
+#define S5P_SDO_ARMCGMS625 S5P_SDAOUT_BASE(0x03D4)
+#define S5P_SDO_VERSION S5P_SDAOUT_BASE(0x03D8)
+#define S5P_SDO_CC S5P_SDAOUT_BASE(0x0380)
+#define S5P_SDO_WSS525 S5P_SDAOUT_BASE(0x0384)
+#define S5P_SDO_WSS625 S5P_SDAOUT_BASE(0x0388)
+#define S5P_SDO_CGMS525 S5P_SDAOUT_BASE(0x038C)
+#define S5P_SDO_CGMS625 S5P_SDAOUT_BASE(0x0394)
+
+#define SDO_TVOUT_SW_RESET (1<<4)
+#define SDO_TVOUT_CLOCK_ON (1)
+#define SDO_TVOUT_CLOCK_OFF (0)
+
+#define SDO_DAC2_Y_G (0<<20)
+#define SDO_DAC2_PB_B (1<<20)
+#define SDO_DAC2_PR_R (2<<20)
+#define SDO_DAC1_Y_G (0<<18)
+#define SDO_DAC1_PB_B (1<<18)
+#define SDO_DAC1_PR_R (2<<18)
+#define SDO_DAC0_Y_G (0<<16)
+#define SDO_DAC0_PB_B (1<<16)
+#define SDO_DAC0_PR_R (2<<16)
+#define SDO_DAC2_CVBS (0<<12)
+#define SDO_DAC2_Y (1<<12)
+#define SDO_DAC2_C (2<<12)
+#define SDO_DAC1_CVBS (0<<10)
+#define SDO_DAC1_Y (1<<10)
+#define SDO_DAC1_C (2<<10)
+#define SDO_DAC0_CVBS (0<<8)
+#define SDO_DAC0_Y (1<<8)
+#define SDO_DAC0_C (2<<8)
+#define SDO_COMPOSITE (0<<6)
+#define SDO_COMPONENT (1<<6)
+#define SDO_RGB (0<<5)
+#define SDO_YPBPR (1<<5)
+#define SDO_INTERLACED (0<<4)
+#define SDO_PROGRESSIVE (1<<4)
+#define SDO_NTSC_M (0)
+#define SDO_PAL_M (1)
+#define SDO_PAL_BGHID (2)
+#define SDO_PAL_N (3)
+#define SDO_PAL_NC (4)
+#define SDO_NTSC_443 (8)
+#define SDO_PAL_60 (9)
+
+#define SDO_COMPONENT_LEVEL_SEL_0IRE (0<<3)
+#define SDO_COMPONENT_LEVEL_SEL_75IRE (1<<3)
+#define SDO_COMPONENT_VTOS_RATIO_10_4 (0<<2)
+#define SDO_COMPONENT_VTOS_RATIO_7_3 (1<<2)
+#define SDO_COMPOSITE_LEVEL_SEL_0IRE (0<<1)
+#define SDO_COMPOSITE_LEVEL_SEL_75IRE (1<<1)
+#define SDO_COMPOSITE_VTOS_RATIO_10_4 (0<<0)
+#define SDO_COMPOSITE_VTOS_RATIO_7_3 (1<<0)
+
+#define SDO_COMPONENT_SYNC_ABSENT (0)
+#define SDO_COMPONENT_SYNC_YG (1)
+#define SDO_COMPONENT_SYNC_ALL (3)
+
+#define SDO_CVBS_NO_WSS (0<<14)
+#define SDO_CVBS_WSS_INS (1<<14)
+#define SDO_CVBS_NO_CLOSED_CAPTION (0<<12)
+#define SDO_CVBS_21H_CLOSED_CAPTION (1<<12)
+#define SDO_CVBS_21H_284H_CLOSED_CAPTION (2<<12)
+#define SDO_CVBS_USE_OTHERS (3<<12)
+#define SDO_SVIDEO_NO_WSS (0<<10)
+#define SDO_SVIDEO_WSS_INS (1<<10)
+#define SDO_SVIDEO_NO_CLOSED_CAPTION (0<<8)
+#define SDO_SVIDEO_21H_CLOSED_CAPTION (1<<8)
+#define SDO_SVIDEO_21H_284H_CLOSED_CAPTION (2<<8)
+#define SDO_SVIDEO_USE_OTHERS (3<<8)
+#define SDO_RGB_NO_CGMSA (0<<7)
+#define SDO_RGB_CGMSA_INS (1<<7)
+#define SDO_RGB_NO_WSS (0<<6)
+#define SDO_RGB_WSS_INS (1<<6)
+#define SDO_RGB_NO_CLOSED_CAPTION (0<<4)
+#define SDO_RGB_21H_CLOSED_CAPTION (1<<4)
+#define SDO_RGB_21H_284H_CLOSED_CAPTION (2<<4)
+#define SDO_RGB_USE_OTHERS (3<<4)
+#define SDO_YPBPR_NO_CGMSA (0<<3)
+#define SDO_YPBPR_CGMSA_INS (1<<3)
+#define SDO_YPBPR_NO_WSS (0<<2)
+#define SDO_YPBPR_WSS_INS (1<<2)
+#define SDO_YPBPR_NO_CLOSED_CAPTION (0)
+#define SDO_YPBPR_21H_CLOSED_CAPTION (1)
+#define SDO_YPBPR_21H_284H_CLOSED_CAPTION (2)
+#define SDO_YPBPR_USE_OTHERS(3)
+
+#define SDO_SCALE_CONV_OFFSET(a) ((0x3ff&a)<<16)
+#define SDO_SCALE_CONV_GAIN(a) (0xfff&a)
+
+#define SDO_DELAY_YTOC(a) ((0xf&a)<<16)
+#define SDO_ACTIVE_START_OFFSET(a) ((0xff&a)<<8)
+#define SDO_ACTIVE_END_OFFSET(a) (0xff&a)
+
+#define SDO_COLOR_SC_PHASE_ADJ (1)
+#define SDO_COLOR_SC_PHASE_NOADJ (0)
+
+#define SDO_POWER_ON_DAC2 (1<<2)
+#define SDO_POWER_DOWN_DAC2 (0<<2)
+#define SDO_POWER_ON_DAC1 (1<<1)
+#define SDO_POWER_DOWN_DAC1 (0<<1)
+#define SDO_POWER_ON_DAC0 (1<<0)
+#define SDO_POWER_DOWN_DAC0 (0<<0)
+
+#define SDO_FIELD_MOD_1001(a) (((0x3ff<<16)&a)>>16)
+#define SDO_FIELD_ID_BOTTOM(a) ((1<<1)&a)
+#define SDO_FIELD_ID_BOTTOM_PI_INCATION(a) (1)
+
+#define SDO_MV_AGC_103_ON (1)
+
+#define SDO_COMPONENT_BHS_ADJ_ON (0<<4)
+#define SDO_COMPONENT_BHS_ADJ_OFF (1<<4)
+#define SDO_COMPONENT_YPBPR_COMP_ON (0<<3)
+#define SDO_COMPONENT_YPBPR_COMP_OFF (1<<3)
+#define SDO_COMPONENT_RGB_COMP_ON (0<<2)
+#define SDO_COMPONENT_RGB_COMP_OFF (1<<2)
+#define SDO_COMPONENT_YC_COMP_ON (0<<1)
+#define SDO_COMPONENT_YC_COMP_OFF (1<<1)
+#define SDO_COMPONENT_CVBS_COMP_ON (0)
+#define SDO_COMPONENT_CVBS_COMP_OFF (1)
+
+#define SDO_BRIGHTNESS_GAIN(a) ((0xff&a)<<16)
+#define SDO_BRIGHTNESS_OFFSET(a) (0xff&a)
+
+#define SDO_HS_CB_GAIN0(a) ((0x1ff&a)<<16)
+#define SDO_HS_CB_GAIN1(a) (0x1ff&a)
+
+#define SDO_HS_CR_GAIN0(a) ((0x1ff&a)<<16)
+#define SDO_HS_CR_GAIN1(a) (0x1ff&a)
+
+#define SDO_HS_CR_OFFSET(a) ((0x3ff&a)<<16)
+#define SDO_HS_CB_OFFSET(a) (0x3ff&a)
+
+#define SDO_MAX_RGB_CUBE(a) ((0xff&a)<<8)
+#define SDO_MIN_RGB_CUBE(a) (0xff&a)
+
+#define SDO_Y_LOWER_MID_CVBS_CORN(a) ((0x3ff&a)<<16)
+#define SDO_Y_BOTTOM_CVBS_CORN(a) (0x3ff&a)
+
+#define SDO_Y_TOP_CVBS_CORN(a) ((0x3ff&a)<<16)
+#define SDO_Y_UPPER_MID_CVBS_CORN(a) (0x3ff&a)
+
+#define SDO_RADIUS_CVBS_CORN(a) (0x1ff&a)
+
+#define SDO_Y_TOP_YC_CYLINDER(a) ((0x3ff&a)<<16)
+#define SDO_Y_BOTOM_YC_CYLINDER(a) (0x3ff&a)
+
+#define SDO_RADIUS_YC_CYLINDER(a) (0x1ff&a)
+
+#define SDO_COMPONENT_525_BP(a) ((0x3ff&a)<<16)
+#define SDO_COMPONENT_525_FP(a) (0x3ff&a)
+
+#define SDO_COMPONENT_625_BP(a) ((0x3ff&a)<<16)
+#define SDO_COMPONENT_625_FP(a) (0x3ff&a)
+
+#define SDO_RGB_SYNC_COMPOSITE (0<<8)
+#define SDO_RGB_SYNC_SEPERATE (1<<8)
+#define SDO_RGB_VSYNC_LOW_ACT (0<<4)
+#define SDO_RGB_VSYNC_HIGH_ACT (1<<4)
+#define SDO_RGB_HSYNC_LOW_ACT 0
+#define SDO_RGB_HSYNC_HIGH_ACT 1
+
+#define SDO_OSF_COEF_ODD(a) ((0xfff&a)<<16)
+#define SDO_OSF_COEF_EVEN(a) (0xfff&a)
+
+#define SDO_XTALK_COEF02(a) ((0xff&a)<<16)
+#define SDO_XTALK_COEF01(a) (0xff&a)
+
+#define SDO_REF_BB_LEVEL_NTSC (0x11a<<8)
+#define SDO_REF_BB_LEVEL_PAL (0xfb<<8)
+#define SDO_SEL_BB_CJAN_CVBS0_BB1_BB2 (0<<4)
+#define SDO_SEL_BB_CJAN_BB0_CVBS1_BB2 (1<<4)
+#define SDO_SEL_BB_CJAN_BB0_BB1_CVBS2 (2<<4)
+#define SDO_BB_MODE_ENABLE (1)
+#define SDO_BB_MODE_DISABLE (0)
+
+#define SDO_VSYNC_IRQ_PEND (1)
+#define SDO_VSYNC_NO_IRQ (0)
+
+#define SDO_VSYNC_IRQ_ENABLE (0)
+#define SDO_VSYNC_IRQ_DISABLE (1)
+
+#define SDO_DISPLAY_CC_CAPTION(a) ((0xff&a)<<16)
+#define SDO_NON_DISPLAY_CC_CAPTION(a) (0xff&a)
+
+#define SDO_CRC_WSS525(a) ((0x3f&a)<<14)
+#define SDO_WORD2_WSS525_COPY_PERMIT (0<<6)
+#define SDO_WORD2_WSS525_ONECOPY_PERMIT (1<<6)
+#define SDO_WORD2_WSS525_NOCOPY_PERMIT (3<<6)
+#define SDO_WORD2_WSS525_MV_PSP_OFF (0<<8)
+#define SDO_WORD2_WSS525_MV_PSP_ON_2LINE_BURST (1<<8)
+#define SDO_WORD2_WSS525_MV_PSP_ON_BURST_OFF (2<<8)
+#define SDO_WORD2_WSS525_MV_PSP_ON_4LINE_BURST (3<<8)
+#define SDO_WORD2_WSS525_ANALOG_OFF (0<<10)
+#define SDO_WORD2_WSS525_ANALOG_ON (1<<10)
+#define SDO_WORD1_WSS525_COPY_INFO (0<<2)
+#define SDO_WORD1_WSS525_DEFAULT (0xf<<2)
+#define SDO_WORD0_WSS525_4_3_NORMAL (0)
+#define SDO_WORD0_WSS525_16_9_ANAMORPIC (1)
+#define SDO_WORD0_WSS525_4_3_LETTERBOX (2)
+
+#define SDO_WSS625_SURROUND_SOUND_DISABLE (0<<11)
+#define SDO_WSS625_SURROUND_SOUND_ENABLE (1<<11)
+#define SDO_WSS625_NO_COPYRIGHT (0<<12)
+#define SDO_WSS625_COPYRIGHT (1<<12)
+#define SDO_WSS625_COPY_NOT_RESTRICTED (0<<13)
+#define SDO_WSS625_COPY_RESTRICTED (1<<13)
+#define SDO_WSS625_TELETEXT_NO_SUBTITLES (0<<8)
+#define SDO_WSS625_TELETEXT_SUBTITLES (1<<8)
+#define SDO_WSS625_NO_OPEN_SUBTITLES (0<<9)
+#define SDO_WSS625_INACT_OPEN_SUBTITLES (1<<9)
+#define SDO_WSS625_OUTACT_OPEN_SUBTITLES (2<<9)
+#define SDO_WSS625_CAMERA (0<<4)
+#define SDO_WSS625_FILM (1<<4)
+#define SDO_WSS625_NORMAL_PAL (0<<5)
+#define SDO_WSS625_MOTION_ADAPTIVE_COLORPLUS (1<<5)
+#define SDO_WSS625_HELPER_NO_SIG (0<<6)
+#define SDO_WSS625_HELPER_SIG (1<<6)
+#define SDO_WSS625_4_3_FULL_576 (0x8)
+#define SDO_WSS625_14_9_LETTERBOX_CENTER_504 (0x1)
+#define SDO_WSS625_14_9_LETTERBOX_TOP_504 (0x2)
+#define SDO_WSS625_16_9_LETTERBOX_CENTER_430 (0xb)
+#define SDO_WSS625_16_9_LETTERBOX_TOP_430 (0x4)
+#define SDO_WSS625_16_9_LETTERBOX_CENTER (0xd)
+#define SDO_WSS625_14_9_FULL_CENTER_576 (0xe)
+#define SDO_WSS625_16_9_ANAMORPIC_576 (0x7)
+
+#define SDO_CRC_CGMS525(a) ((0x3f&a)<<14)
+#define SDO_WORD2_CGMS525_COPY_PERMIT (0<<6)
+#define SDO_WORD2_CGMS525_ONECOPY_PERMIT (1<<6)
+#define SDO_WORD2_CGMS525_NOCOPY_PERMIT (3<<6)
+#define SDO_WORD2_CGMS525_MV_PSP_OFF (0<<8)
+#define SDO_WORD2_CGMS525_MV_PSP_ON_2LINE_BURST (1<<8)
+#define SDO_WORD2_CGMS525_MV_PSP_ON_BURST_OFF (2<<8)
+#define SDO_WORD2_CGMS525_MV_PSP_ON_4LINE_BURST (3<<8)
+#define SDO_WORD2_CGMS525_ANALOG_OFF (0<<10)
+#define SDO_WORD2_CGMS525_ANALOG_ON (1<<10)
+#define SDO_WORD1_CGMS525_COPY_INFO (0<<2)
+#define SDO_WORD1_CGMS525_DEFAULT (0xf<<2)
+#define SDO_WORD0_CGMS525_4_3_NORMAL (0)
+#define SDO_WORD0_CGMS525_16_9_ANAMORPIC (1)
+#define SDO_WORD0_CGMS525_4_3_LETTERBOX (2)
+
+#define SDO_CGMS625_SURROUND_SOUND_DISABLE (0<<11)
+#define SDO_CGMS625_SURROUND_SOUND_ENABLE (1<<11)
+#define SDO_CGMS625_NO_COPYRIGHT (0<<12)
+#define SDO_CGMS625_COPYRIGHT (1<<12)
+#define SDO_CGMS625_COPY_NOT_RESTRICTED (0<<13)
+#define SDO_CGMS625_COPY_RESTRICTED (1<<13)
+#define SDO_CGMS625_TELETEXT_NO_SUBTITLES (0<<8)
+#define SDO_CGMS625_TELETEXT_SUBTITLES (1<<8)
+#define SDO_CGMS625_NO_OPEN_SUBTITLES (0<<9)
+#define SDO_CGMS625_INACT_OPEN_SUBTITLES (1<<9)
+#define SDO_CGMS625_OUTACT_OPEN_SUBTITLES (2<<9)
+#define SDO_CGMS625_CAMERA (0<<4)
+#define SDO_CGMS625_FILM (1<<4)
+#define SDO_CGMS625_NORMAL_PAL (0<<5)
+#define SDO_CGMS625_MOTION_ADAPTIVE_COLORPLUS (1<<5)
+#define SDO_CGMS625_HELPER_NO_SIG (0<<6)
+#define SDO_CGMS625_HELPER_SIG (1<<6)
+#define SDO_CGMS625_4_3_FULL_576 (0x8)
+#define SDO_CGMS625_14_9_LETTERBOX_CENTER_504 (0x1)
+#define SDO_CGMS625_14_9_LETTERBOX_TOP_504 (0x2)
+#define SDO_CGMS625_16_9_LETTERBOX_CENTER_430 (0xb)
+#define SDO_CGMS625_16_9_LETTERBOX_TOP_430 (0x4)
+#define SDO_CGMS625_16_9_LETTERBOX_CENTER (0xd)
+#define SDO_CGMS625_14_9_FULL_CENTER_576 (0xe)
+#define SDO_CGMS625_16_9_ANAMORPIC_576 (0x7)
+
+#endif
diff --git a/drivers/media/video/samsung/tv20/s5pc100/regs/regs-vmx.h b/drivers/media/video/samsung/tv20/s5pc100/regs/regs-vmx.h
new file mode 100644
index 0000000..bd104342
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/s5pc100/regs/regs-vmx.h
@@ -0,0 +1,209 @@
+/* linux/drivers/media/video/samsung/tv20/s5pc100/regs/regs-vmx.h
+ *
+ * Mixer register header file for Samsung TVOut driver
+ *
+ * Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+#include <mach/map.h>
+
+#define S5P_MIXER_BASE(x) (x)
+
+#define S5P_MXR_STATUS S5P_MIXER_BASE(0x0000)
+#define S5P_MXR_CFG S5P_MIXER_BASE(0x0004)
+#define S5P_MXR_INT_EN S5P_MIXER_BASE(0x0008)
+#define S5P_MXR_INT_STATUS S5P_MIXER_BASE(0x000C)
+#define S5P_MXR_LAYER_CFG S5P_MIXER_BASE(0x0010)
+#define S5P_MXR_VIDEO_CFG S5P_MIXER_BASE(0x0014)
+#define S5P_MXR_GRAPHIC0_CFG S5P_MIXER_BASE(0x0020)
+#define S5P_MXR_GRAPHIC0_BASE S5P_MIXER_BASE(0x0024)
+#define S5P_MXR_GRAPHIC0_SPAN S5P_MIXER_BASE(0x0028)
+#define S5P_MXR_GRAPHIC0_SXY S5P_MIXER_BASE(0x002C)
+#define S5P_MXR_GRAPHIC0_WH S5P_MIXER_BASE(0x0030)
+#define S5P_MXR_GRAPHIC0_DXY S5P_MIXER_BASE(0x0034)
+#define S5P_MXR_GRAPHIC0_BLANK S5P_MIXER_BASE(0x0038)
+#define S5P_MXR_GRAPHIC1_CFG S5P_MIXER_BASE(0x0040)
+#define S5P_MXR_GRAPHIC1_BASE S5P_MIXER_BASE(0x0044)
+#define S5P_MXR_GRAPHIC1_SPAN S5P_MIXER_BASE(0x0048)
+#define S5P_MXR_GRAPHIC1_SXY S5P_MIXER_BASE(0x004C)
+#define S5P_MXR_GRAPHIC1_WH S5P_MIXER_BASE(0x0050)
+#define S5P_MXR_GRAPHIC1_DXY S5P_MIXER_BASE(0x0054)
+#define S5P_MXR_GRAPHIC1_BLANK S5P_MIXER_BASE(0x0058)
+#define S5P_MXR_BG_CFG S5P_MIXER_BASE(0x0060)
+#define S5P_MXR_BG_COLOR0 S5P_MIXER_BASE(0x0064)
+#define S5P_MXR_BG_COLOR1 S5P_MIXER_BASE(0x0068)
+#define S5P_MXR_BG_COLOR2 S5P_MIXER_BASE(0x006C)
+#define S5P_MXR_CM_COEFF_Y S5P_MIXER_BASE(0x0080)
+#define S5P_MXR_CM_COEFF_CB S5P_MIXER_BASE(0x0084)
+#define S5P_MXR_CM_COEFF_CR S5P_MIXER_BASE(0x0088)
+#define S5P_MXR_VER S5P_MIXER_BASE(0x0100)
+
+
+#define S5P_MXR_STATUS_S S5P_MIXER_BASE(0x2000)
+#define S5P_MXR_CFG_S S5P_MIXER_BASE(0x2004)
+#define S5P_MXR_LAYER_CFG_S S5P_MIXER_BASE(0x2010)
+#define S5P_MXR_VIDEO_CFG_S S5P_MIXER_BASE(0x2014)
+#define S5P_MXR_GRAPHIC0_CFG_S S5P_MIXER_BASE(0x2020)
+#define S5P_MXR_GRAPHIC0_BASE_S S5P_MIXER_BASE(0x2024)
+#define S5P_MXR_GRAPHIC0_SPAN_S S5P_MIXER_BASE(0x2028)
+#define S5P_MXR_GRAPHIC0_SXY_S S5P_MIXER_BASE(0x202C)
+#define S5P_MXR_GRAPHIC0_WH_S S5P_MIXER_BASE(0x2030)
+#define S5P_MXR_GRAPHIC0_DXY_S S5P_MIXER_BASE(0x2034)
+#define S5P_MXR_GRAPHIC0_BLANK_PIXEL_S S5P_MIXER_BASE(0x2038)
+#define S5P_MXR_GRAPHIC1_CFG_S S5P_MIXER_BASE(0x2040)
+#define S5P_MXR_GRAPHIC1_BASE_S S5P_MIXER_BASE(0x2044)
+#define S5P_MXR_GRAPHIC1_SPAN_S S5P_MIXER_BASE(0x2048)
+#define S5P_MXR_GRAPHIC1_SXY_S S5P_MIXER_BASE(0x204C)
+#define S5P_MXR_GRAPHIC1_WH_S S5P_MIXER_BASE(0x2050)
+#define S5P_MXR_GRAPHIC1_DXY_S S5P_MIXER_BASE(0x2054)
+#define S5P_MXR_GRAPHIC1_BLANK_PIXEL_S S5P_MIXER_BASE(0x2058)
+#define S5P_MXR_BG_COLOR0_S S5P_MIXER_BASE(0x2064)
+#define S5P_MXR_BG_COLOR1_S S5P_MIXER_BASE(0x2068)
+#define S5P_MXR_BG_COLOR2_S S5P_MIXER_BASE(0x206C)
+
+#define S5P_MXR_STATUS_RUN (1<<0)
+#define S5P_MXR_STATUS_STOP (0<<0)
+#define S5P_MXR_STATUS_SYNC_DISABLE (0<<2)
+#define S5P_MXR_STATUS_SYNC_ENABLE (1<<2)
+#define S5P_MXR_STATUS_LITTLE (0<<3)
+#define S5P_MXR_STATUS_BIT (1<<3)
+#define S5P_MXR_STATUS_8_BURST (0<<7)
+#define S5P_MXR_STATUS_16_BURST (1<<7)
+
+#define S5P_MXR_CFG_SD (0<<0)
+#define S5P_MXR_CFG_HD (1<<0)
+#define S5P_MXR_CFG_NTSC (0<<1)
+#define S5P_MXR_CFG_PAL (1<<1)
+#define S5P_MXR_CFG_INTERLACE (0<<2)
+#define S5P_MXR_CFG_PROGRASSIVE (1<<2)
+#define S5P_MXR_CFG_VIDEO_DISABLE (0<<3)
+#define S5P_MXR_CFG_VIDEO_ENABLE (1<<4)
+#define S5P_MXR_CFG_GRAPHIC0_DISABLE (0<<4)
+#define S5P_MXR_CFG_GRAPHIC0_ENABLE (1<<4)
+#define S5P_MXR_CFG_GRAPHIC1_DISABLE (0<<5)
+#define S5P_MXR_CFG_GRAPHIC1_ENABLE (1<<5)
+#define S5P_MXR_CFG_HD_720P (0<<6)
+#define S5P_MXR_CFG_HD_1080I (1<<6)
+
+#define S5P_MXR_INT_EN_GRP0_DISABLE (0<<8)
+#define S5P_MXR_INT_EN_GRP0_ENABLE (1<<8)
+#define S5P_MXR_INT_EN_GRP1_DISABLE (0<<9)
+#define S5P_MXR_INT_EN_GRP1_ENABLE (1<<9)
+#define S5P_MXR_INT_EN_VP_DISABLE (0<<10)
+#define S5P_MXR_INT_EN_VP_ENABLE (1<<10)
+
+#define S5P_MXR_STATUS_EN_GRP0_N_FIRED (0<<8)
+#define S5P_MXR_STATUS_EN_GRP0_FIRED (1<<8)
+#define S5P_MXR_STATUS_EN_GRP1_N_FIRED (0<<9)
+#define S5P_MXR_STATUS_EN_GRP1_FIRED (1<<9)
+#define S5P_MXR_STATUS_EN_VP_N_FIRED (0<<10)
+#define S5P_MXR_STATUS_EN_VP_FIRED (1<<10)
+
+#define S5P_MXR_LAYER_CFG_VP_HIDE (0<<0)
+#define S5P_MXR_LAYER_CFG_GRP0_HIDE (0<<4)
+#define S5P_MXR_LAYER_CFG_GRP1_HIDE (0<<8)
+
+#define S5P_MXR_VIDEO_CFG_BLEND_EN (1<<16)
+
+
+#define S5P_MXR_BURST16_MODE (1<<7)
+#define S5P_MXR_BURST8_MODE (0<<7)
+#define S5P_MXR_BIG_ENDIAN_SOURCE_FORMAT (1<<3)
+#define S5P_MXR_LITTLE_ENDIAN_SOURCE_FORMAT (0<<3)
+#define S5P_MXR_MIXER_RESERVED (1<<2)
+#define S5P_MXR_CMU_STOP_CLOCK (1<<1)
+#define S5P_MXR_CMU_CANNOT_STOP_CLOCK (0<<1)
+#define S5P_MXR_MIXER_START (1<<0)
+#define S5P_MXR_MIXER_STOP (0<<0)
+
+#define S5P_MXR_HD_1080I_MODE (1<<6)
+#define S5P_MXR_HD_720P_MODE (0<<6)
+#define S5P_MXR_GRAPHIC1_LAYER_SHOW (1<<5)
+#define S5P_MXR_GRAPHIC1_LAYER_HIDE (0<<5)
+#define S5P_MXR_GRAPHIC0_LAYER_SHOW (1<<4)
+#define S5P_MXR_GRAPHIC0_LAYER_HIDE (0<<4)
+#define S5P_MXR_VIDEO_LAYER_SHOW (1<<3)
+#define S5P_MXR_VIDEO_LAYER_HIDE (0<<3)
+#define S5P_MXR_PROGRESSVE_MODE (1<<2)
+#define S5P_MXR_INTERLACE_MODE (0<<2)
+#define S5P_MXR_PAL (1<<1)
+#define S5P_MXR_NTSC (0<<1)
+#define S5P_MXR_HD (1<<0)
+#define S5P_MXR_SD (0<<0)
+
+#define S5P_MXR_VP_INT_ENABLE (1<<10)
+#define S5P_MXR_VP_INT_DISABLE (0<<10)
+#define S5P_MXR_GRP1_INT_ENABLE (1<<9)
+#define S5P_MXR_GRP1_INT_DISABLE (0<<9)
+#define S5P_MXR_GRP0_INT_ENABLE (1<<8)
+#define S5P_MXR_GRP0_INT_DISABLE (0<<8)
+
+#define S5P_MXR_VP_INT_FIRED (1<<10)
+#define S5P_MXR_GRP1_INT_FIRED (1<<9)
+#define S5P_MXR_GRP0_INT_FIRED (1<<8)
+#define S5P_MXR_INT_FIRED (1<<0)
+
+#define S5P_MXR_ALPHA (0xff)
+
+#define S5P_MXR_GRP1_LAYER_PRIORITY(a) ((0xf&a)<<8)
+#define S5P_MXR_GRP0_LAYER_PRIORITY(a) ((0xf&a)<<4)
+#define S5P_MXR_VP_LAYER_PRIORITY(a) ((0xf&a)<<0)
+#define S5P_MXR_GRP1_LAYER_PRIORITY_CLEAR(a) ((~(0xf<<8))&a)
+#define S5P_MXR_GRP0_LAYER_PRIORITY_CLEAR(a) ((~(0xf<<4))&a)
+#define S5P_MXR_VP_LAYER_PRIORITY_CLEAR(a) ((~(0xf<<0))&a)
+#define S5P_MXR_GRP1_LAYER_PRIORITY_INFO(a) ((0xf<<8)&a)
+#define S5P_MXR_GRP0_LAYER_PRIORITY_INFO(a) ((0xf<<4)&a)
+#define S5P_MXR_VP_LAYER_PRIORITY_INFO(a) ((0xf<<0)&a)
+
+#define S5P_MXR_VP_BLEND_ENABLE (1<<16)
+#define S5P_MXR_VP_BLEND_DISABLE (0<<16)
+#define S5P_MXR_VP_ALPHA_VALUE(a) ((0xff&a)<<0)
+#define S5P_MXR_VP_ALPHA_VALUE_CLEAR(a) ((~(0xff<<0))&a)
+
+#define S5P_MXR_BLANK_CHANGE_NEW_PIXEL (1<<21)
+#define S5P_MXR_BLANK_NOT_CHANGE_NEW_PIXEL (0<<21)
+#define S5P_MXR_PRE_MUL_MODE (1<<20)
+#define S5P_MXR_NORMAL_MODE (0<<20)
+#define S5P_MXR_WIN_BLEND_ENABLE (1<<17)
+#define S5P_MXR_WIN_BLEND_DISABLE (0<<17)
+#define S5P_MXR_PIXEL_BLEND_ENABLE (1<<16)
+#define S5P_MXR_PIXEL_BLEND_DISABLE (0<<16)
+#define S5P_MXR_EG_COLOR_FORMAT(a) ((0xf&a)<<8)
+#define S5P_MXR_EG_COLOR_FORMAT_CLEAR(a) ((~(0xf<<8))&a)
+#define S5P_MXR_GRP_ALPHA_VALUE(a) ((0xff&a)<<0)
+#define S5P_MXR_GRP_ALPHA_VALUE_CLEAR(a) ((~(0xff<<0))&a)
+
+#define S5P_MXR_GPR_BASE(a) (0xffffffff&a)
+#define S5P_MXR_GRP_ADDR_ILLEGAL(a) (0x3&a)
+
+#define S5P_MXR_GRP_SPAN(a) (0x7fff&a)
+
+#define S5P_MXR_GRP_WIDTH(a) ((0x7ff&a)<<16)
+#define S5P_MXR_GRP_HEIGHT(a) ((0x7ff&a)<<0)
+
+#define S5P_MXR_GRP_STARTX(a) ((0x7ff&a)<<16)
+#define S5P_MXR_GRP_STARTY(a) ((0x7ff&a)<<0)
+
+#define S5P_MXR_GRP_DESTX(a) ((0x7ff&a)<<16)
+#define S5P_MXR_GRP_DESTY(a) ((0x7ff&a)<<0)
+
+#define S5P_MXR_GPR_BLANK_COLOR(a) (0xffffffff&a)
+
+#define S5P_MXR_BG_CR_DIHER_EN (1<<19)
+#define S5P_MXR_BG_CB_DIHER_EN (1<<18)
+#define S5P_MXR_BG_Y_DIHER_EN (1<<17)
+
+#define S5P_MXR_BG_COLOR_Y(a) ((0xff&a)<<16)
+#define S5P_MXR_BG_COLOR_CB(a) ((0xff&a)<<8)
+#define S5P_MXR_BG_COLOR_CR(a) ((0xff&a)<<0)
+
+#define S5P_MXR_BG_COLOR_WIDE (1<<30)
+#define S5P_MXR_BG_COLOR_NARROW (0<<30)
+#define S5P_MXR_BG_COEFF_0(a) ((0x3f&a)<<20)
+#define S5P_MXR_BG_COEFF_1(a) ((0x3f&a)<<10)
+#define S5P_MXR_BG_COEFF_2(a) ((0x3f&a)<<0)
+
diff --git a/drivers/media/video/samsung/tv20/s5pc100/regs/regs-vprocessor.h b/drivers/media/video/samsung/tv20/s5pc100/regs/regs-vprocessor.h
new file mode 100644
index 0000000..34c1d97
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/s5pc100/regs/regs-vprocessor.h
@@ -0,0 +1,366 @@
+/* linux/drivers/media/video/samsung/tv20/s5pc100/regs/regs-vprocessor.h
+ *
+ * Video Processor register header file for Samsung TVOut driver
+ *
+ * Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_REGS_VPROCESSOR_H
+
+#include <mach/map.h>
+
+#define S5P_VPROCESSOR_BASE(x) (x)
+
+#define S5P_VP_ENABLE S5P_VPROCESSOR_BASE(0x0000)
+#define S5P_VP_SRESET S5P_VPROCESSOR_BASE(0x0004)
+#define S5P_VP_SHADOW_UPDATE S5P_VPROCESSOR_BASE(0x0008)
+#define S5P_VP_FIELD_ID S5P_VPROCESSOR_BASE(0x000C)
+#define S5P_VP_MODE S5P_VPROCESSOR_BASE(0x0010)
+#define S5P_VP_IMG_SIZE_Y S5P_VPROCESSOR_BASE(0x0014)
+#define S5P_VP_IMG_SIZE_C S5P_VPROCESSOR_BASE(0x0018)
+#define S5P_VP_PER_RATE_CTRL S5P_VPROCESSOR_BASE(0x001C)
+#define S5P_VP_TOP_Y_PTR S5P_VPROCESSOR_BASE(0x0028)
+#define S5P_VP_BOT_Y_PTR S5P_VPROCESSOR_BASE(0x002C)
+#define S5P_VP_TOP_C_PTR S5P_VPROCESSOR_BASE(0x0030)
+#define S5P_VP_BOT_C_PTR S5P_VPROCESSOR_BASE(0x0034)
+#define S5P_VP_ENDIAN_MODE S5P_VPROCESSOR_BASE(0x03CC)
+#define S5P_VP_SRC_H_POSITION S5P_VPROCESSOR_BASE(0x0044)
+#define S5P_VP_SRC_V_POSITION S5P_VPROCESSOR_BASE(0x0048)
+#define S5P_VP_SRC_WIDTH S5P_VPROCESSOR_BASE(0x004C)
+#define S5P_VP_SRC_HEIGHT S5P_VPROCESSOR_BASE(0x0050)
+#define S5P_VP_DST_H_POSITION S5P_VPROCESSOR_BASE(0x0054)
+#define S5P_VP_DST_V_POSITION S5P_VPROCESSOR_BASE(0x0058)
+#define S5P_VP_DST_WIDTH S5P_VPROCESSOR_BASE(0x005C)
+#define S5P_VP_DST_HEIGHT S5P_VPROCESSOR_BASE(0x0060)
+#define S5P_VP_H_RATIO S5P_VPROCESSOR_BASE(0x0064)
+#define S5P_VP_V_RATIO S5P_VPROCESSOR_BASE(0x0068)
+#define S5P_VP_POLY8_Y0_LL S5P_VPROCESSOR_BASE(0x006C)
+#define S5P_VP_POLY8_Y0_LH S5P_VPROCESSOR_BASE(0x0070)
+#define S5P_VP_POLY8_Y0_HL S5P_VPROCESSOR_BASE(0x0074)
+#define S5P_VP_POLY8_Y0_HH S5P_VPROCESSOR_BASE(0x0078)
+#define S5P_VP_POLY8_Y1_LL S5P_VPROCESSOR_BASE(0x007C)
+#define S5P_VP_POLY8_Y1_LH S5P_VPROCESSOR_BASE(0x0080)
+#define S5P_VP_POLY8_Y1_HL S5P_VPROCESSOR_BASE(0x0084)
+#define S5P_VP_POLY8_Y1_HH S5P_VPROCESSOR_BASE(0x0088)
+#define S5P_VP_POLY8_Y2_LL S5P_VPROCESSOR_BASE(0x008C)
+#define S5P_VP_POLY8_Y2_LH S5P_VPROCESSOR_BASE(0x0090)
+#define S5P_VP_POLY8_Y2_HL S5P_VPROCESSOR_BASE(0x0094)
+#define S5P_VP_POLY8_Y2_HH S5P_VPROCESSOR_BASE(0x0098)
+#define S5P_VP_POLY8_Y3_LL S5P_VPROCESSOR_BASE(0x009C)
+#define S5P_VP_POLY8_Y3_LH S5P_VPROCESSOR_BASE(0x00A0)
+#define S5P_VP_POLY8_Y3_HL S5P_VPROCESSOR_BASE(0x00A4)
+#define S5P_VP_POLY8_Y3_HH S5P_VPROCESSOR_BASE(0x00A8)
+#define S5P_VP_POLY4_Y0_LL S5P_VPROCESSOR_BASE(0x00EC)
+#define S5P_VP_POLY4_Y0_LH S5P_VPROCESSOR_BASE(0x00F0)
+#define S5P_VP_POLY4_Y0_HL S5P_VPROCESSOR_BASE(0x00F4)
+#define S5P_VP_POLY4_Y0_HH S5P_VPROCESSOR_BASE(0x00F8)
+#define S5P_VP_POLY4_Y1_LL S5P_VPROCESSOR_BASE(0x00FC)
+#define S5P_VP_POLY4_Y1_LH S5P_VPROCESSOR_BASE(0x0100)
+#define S5P_VP_POLY4_Y1_HL S5P_VPROCESSOR_BASE(0x0104)
+#define S5P_VP_POLY4_Y1_HH S5P_VPROCESSOR_BASE(0x0108)
+#define S5P_VP_POLY4_Y2_LL S5P_VPROCESSOR_BASE(0x010C)
+#define S5P_VP_POLY4_Y2_LH S5P_VPROCESSOR_BASE(0x0110)
+#define S5P_VP_POLY4_Y2_HL S5P_VPROCESSOR_BASE(0x0114)
+#define S5P_VP_POLY4_Y2_HH S5P_VPROCESSOR_BASE(0x0118)
+#define S5P_VP_POLY4_Y3_LL S5P_VPROCESSOR_BASE(0x011C)
+#define S5P_VP_POLY4_Y3_LH S5P_VPROCESSOR_BASE(0x0120)
+#define S5P_VP_POLY4_Y3_HL S5P_VPROCESSOR_BASE(0x0124)
+#define S5P_VP_POLY4_Y3_HH S5P_VPROCESSOR_BASE(0x0128)
+#define S5P_VP_POLY4_C0_LL S5P_VPROCESSOR_BASE(0x012C)
+#define S5P_VP_POLY4_C0_LH S5P_VPROCESSOR_BASE(0x0130)
+#define S5P_VP_POLY4_C0_HL S5P_VPROCESSOR_BASE(0x0134)
+#define S5P_VP_POLY4_C0_HH S5P_VPROCESSOR_BASE(0x0138)
+#define S5P_VP_POLY4_C1_LL S5P_VPROCESSOR_BASE(0x013C)
+#define S5P_VP_POLY4_C1_LH S5P_VPROCESSOR_BASE(0x0140)
+#define S5P_VP_POLY4_C1_HL S5P_VPROCESSOR_BASE(0x0144)
+#define S5P_VP_POLY4_C1_HH S5P_VPROCESSOR_BASE(0x0148)
+#define S5P_PP_CSC_Y2Y_COEF S5P_VPROCESSOR_BASE(0x01D4)
+#define S5P_PP_CSC_CB2Y_COEF S5P_VPROCESSOR_BASE(0x01D8)
+#define S5P_PP_CSC_CR2Y_COEF S5P_VPROCESSOR_BASE(0x01DC)
+#define S5P_PP_CSC_Y2CB_COEF S5P_VPROCESSOR_BASE(0x01E0)
+#define S5P_PP_CSC_CB2CB_COEF S5P_VPROCESSOR_BASE(0x01E4)
+#define S5P_PP_CSC_CR2CB_COEF S5P_VPROCESSOR_BASE(0x01E8)
+#define S5P_PP_CSC_Y2CR_COEF S5P_VPROCESSOR_BASE(0x01EC)
+#define S5P_PP_CSC_CB2CR_COEF S5P_VPROCESSOR_BASE(0x01F0)
+#define S5P_PP_CSC_CR2CR_COEF S5P_VPROCESSOR_BASE(0x01F4)
+#define S5P_PP_BYPASS S5P_VPROCESSOR_BASE(0x0200)
+#define S5P_PP_SATURATION S5P_VPROCESSOR_BASE(0x020C)
+#define S5P_PP_SHARPNESS S5P_VPROCESSOR_BASE(0x0210)
+#define S5P_PP_LINE_EQ0 S5P_VPROCESSOR_BASE(0x0218)
+#define S5P_PP_LINE_EQ1 S5P_VPROCESSOR_BASE(0x021C)
+#define S5P_PP_LINE_EQ2 S5P_VPROCESSOR_BASE(0x0220)
+#define S5P_PP_LINE_EQ3 S5P_VPROCESSOR_BASE(0x0224)
+#define S5P_PP_LINE_EQ4 S5P_VPROCESSOR_BASE(0x0228)
+#define S5P_PP_LINE_EQ5 S5P_VPROCESSOR_BASE(0x022C)
+#define S5P_PP_LINE_EQ6 S5P_VPROCESSOR_BASE(0x0230)
+#define S5P_PP_LINE_EQ7 S5P_VPROCESSOR_BASE(0x0234)
+#define S5P_PP_BRIGHT_OFFSET S5P_VPROCESSOR_BASE(0x0238)
+#define S5P_PP_CSC_EN S5P_VPROCESSOR_BASE(0x023C)
+#define S5P_VP_VERSION_INFO S5P_VPROCESSOR_BASE(0x03FC)
+
+
+#define S5P_VP_FIELD_ID_S S5P_VPROCESSOR_BASE(0x016C)
+#define S5P_VP_MODE_S S5P_VPROCESSOR_BASE(0x0170)
+#define S5P_VP_IMG_SIZE_Y_S S5P_VPROCESSOR_BASE(0x0174)
+#define S5P_VP_IMG_SIZE_C_S S5P_VPROCESSOR_BASE(0x0178)
+#define S5P_VP_TOP_Y_PTR_S S5P_VPROCESSOR_BASE(0x0190)
+#define S5P_VP_BOT_Y_PTR_S S5P_VPROCESSOR_BASE(0x0194)
+#define S5P_VP_TOP_C_PTR_S S5P_VPROCESSOR_BASE(0x0198)
+#define S5P_VP_BOT_C_PTR_S S5P_VPROCESSOR_BASE(0x019C)
+#define S5P_VP_ENDIAN_MODE_S S5P_VPROCESSOR_BASE(0x03EC)
+#define S5P_VP_SRC_H_POSITION_S S5P_VPROCESSOR_BASE(0x01AC)
+#define S5P_VP_SRC_V_POSITION_S S5P_VPROCESSOR_BASE(0x01B0)
+#define S5P_VP_SRC_WIDTH_S S5P_VPROCESSOR_BASE(0x01B4)
+#define S5P_VP_SRC_HEIGHT_S S5P_VPROCESSOR_BASE(0x01B8)
+#define S5P_VP_DST_H_POSITION_S S5P_VPROCESSOR_BASE(0x01BC)
+#define S5P_VP_DST_V_POSITION_S S5P_VPROCESSOR_BASE(0x01C0)
+#define S5P_VP_DST_WIDTH_S S5P_VPROCESSOR_BASE(0x01C4)
+#define S5P_VP_DST_HEIGHT_S S5P_VPROCESSOR_BASE(0x01C8)
+#define S5P_VP_H_RATIO_S S5P_VPROCESSOR_BASE(0x01CC)
+#define S5P_VP_V_RATIO_S S5P_VPROCESSOR_BASE(0x01D0)
+#define S5P_PP_BYPASS_S S5P_VPROCESSOR_BASE(0x0258)
+#define S5P_PP_SATURATION_S S5P_VPROCESSOR_BASE(0x025C)
+#define S5P_PP_SHARPNESS_S S5P_VPROCESSOR_BASE(0x0260)
+#define S5P_PP_LINE_EQ0_S S5P_VPROCESSOR_BASE(0x0268)
+#define S5P_PP_LINE_EQ1_S S5P_VPROCESSOR_BASE(0x026C)
+#define S5P_PP_LINE_EQ2_S S5P_VPROCESSOR_BASE(0x0270)
+#define S5P_PP_LINE_EQ3_S S5P_VPROCESSOR_BASE(0x0274)
+#define S5P_PP_LINE_EQ4_S S5P_VPROCESSOR_BASE(0x0278)
+#define S5P_PP_LINE_EQ5_S S5P_VPROCESSOR_BASE(0x027C)
+#define S5P_PP_LINE_EQ6_S S5P_VPROCESSOR_BASE(0x0280)
+#define S5P_PP_LINE_EQ7_S S5P_VPROCESSOR_BASE(0x0284)
+#define S5P_PP_BRIGHT_OFFSET_S S5P_VPROCESSOR_BASE(0x0288)
+#define S5P_PP_CSC_EN_S S5P_VPROCESSOR_BASE(0x028C)
+#define S5P_PP_CSC_Y2Y_COEF_S S5P_VPROCESSOR_BASE(0x0290)
+#define S5P_PP_CSC_CB2Y_COEF_S S5P_VPROCESSOR_BASE(0x0294)
+#define S5P_PP_CSC_CR2Y_COEF_S S5P_VPROCESSOR_BASE(0x0298)
+#define S5P_PP_CSC_Y2CB_COEF_S S5P_VPROCESSOR_BASE(0x029C)
+#define S5P_PP_CSC_CB2CB_COEF_S S5P_VPROCESSOR_BASE(0x02A0)
+#define S5P_PP_CSC_CR2CB_COEF_S S5P_VPROCESSOR_BASE(0x02A4)
+#define S5P_PP_CSC_Y2CR_COEF_S S5P_VPROCESSOR_BASE(0x02A8)
+#define S5P_PP_CSC_CB2CR_COEF_S S5P_VPROCESSOR_BASE(0x02AC)
+#define S5P_PP_CSC_CR2CR_COEF_S S5P_VPROCESSOR_BASE(0x02B0)
+
+
+#define S5P_VP_ENABLE_ON (1<<0)
+#define S5P_VP_ENABLE_ON_S (1<<2)
+
+#define S5P_VP_SRESET_LAST_COMPLETE (0<<0)
+#define S5P_VP_SRESET_PROCESSING (1<<0)
+
+#define S5P_VP_SHADOW_UPDATE_DISABLE (0<<0)
+#define S5P_VP_SHADOW_UPDATE_ENABLE (1<<0)
+
+#define S5P_VP_FIELD_ID_TOP (0<<0)
+#define S5P_VP_FIELD_ID_BOTTOM (1<<0)
+
+#define S5P_VP_MODE_2D_IPC_ENABLE (1<<1)
+#define S5P_VP_MODE_2D_IPC_DISABLE (0<<1)
+#define S5P_VP_MODE_FIELD_ID_MAN_TOGGLING (0<<2)
+#define S5P_VP_MODE_FIELD_ID_AUTO_TOGGLING (1<<2)
+#define S5P_VP_MODE_CROMA_EXPANSION_C_TOP_PTR (0<<3)
+#define S5P_VP_MODE_CROMA_EXPANSION_C_TOPBOTTOM_PTR (1<<3)
+#define S5P_VP_MODE_MEM_MODE_LINEAR (0<<4)
+#define S5P_VP_MODE_MEM_MODE_2D_TILE (1<<4)
+#define S5P_VP_MODE_LINE_SKIP_OFF (0<<5)
+#define S5P_VP_MODE_LINE_SKIP_ON (1<<5)
+
+#define S5P_VP_ENDIAN_MODE_BIG (0<<0)
+#define S5P_VP_ENDIAN_MODE_LITTLE (1<<0)
+
+
+#define VP_ON_SW_RESET (1<<2)
+#define VP_POWER_DOWN_RDY (1<<1)
+#define VP_ON_ENABLE (1<<0)
+#define VP_ON_DISABLE (0<<0)
+
+#define VP_SOFT_RESET (1<<0)
+
+#define VP_SHADOW_UPDATE_ENABLE (1<<0)
+#define VP_SHADOW_UPDATE_DISABLE (0<<0)
+
+#define VP_FIELD_ID_BOTTOM (1<<0)
+#define VP_FIELD_ID_TOP (0<<0)
+
+#define VP_LINE_SKIP_ON (1<<5)
+#define VP_LINE_SKIP_OFF (0<<5)
+#define VP_MEM_2D_MODE (1<<4)
+#define VP_MEM_LINEAR_MODE (0<<4)
+#define VP_CHROMA_USE_TOP_BOTTOM (1<<3)
+#define VP_CHROMA_USE_TOP (0<<3)
+#define VP_FIELD_ID_TOGGLE_VSYNC (1<<2)
+#define VP_FIELD_ID_TOGGLE_USER (0<<2)
+#define VP_2D_IPC_ON (1<<1)
+#define VP_2D_IPC_OFF (0<<1)
+
+#define VP_IMG_HSIZE(a) ((0x3fff&a)<<16)
+#define VP_IMG_VSIZE(a) ((0x3fff&a)<<0)
+#define VP_IMG_SIZE_ILLEGAL(a) (0x7&a)
+
+#define VP_PEL_RATE_CTRL(a) ((0x3&a)<<0)
+
+
+#define VP_PTR_ILLEGAL(a) (0x7&a)
+
+#define VP_LITTLE_ENDIAN_MODE (1<<0)
+#define VP_BIG_ENDIAN_MODE (0<<0)
+
+#define VP_SRC_H_POSITION(a) ((0x7ff&a)<<4)
+#define VP_SRC_X_FRACT_STEP(a) (0xf&a)
+
+#define VP_SRC_V_POSITION(a) (0x3ff&a)
+
+#define VP_SRC_WIDTH(a) (0x7ff&a)
+
+#define VP_SRC_HEIGHT(a) (0x3ff&a)
+
+#define VP_DST_H_POSITION(a) (0x7ff&a)
+
+#define VP_DST_V_POSITION(a) (0x3ff&a)
+
+#define VP_DST_WIDTH(a) (0x7ff&a)
+
+#define VP_DST_HEIGHT(a) (0x3ff&a)
+
+#define VP_H_RATIO(a) (0x7ffff&a)
+
+#define VP_V_RATIO(a) (0x7ffff&a)
+
+#define VP_POLY8_Y0_x0(a) ((0x7&a)<<24)
+#define VP_POLY8_Y0_x1(a) ((0x7&a)<<16)
+#define VP_POLY8_Y0_x2(a) ((0x7&a)<<8)
+#define VP_POLY8_Y0_x3(a) ((0x7&a)<<0)
+
+#define VP_POLY8_Y1_x0(a) ((0x1f&a)<<24)
+#define VP_POLY8_Y1_x1(a) ((0x1f&a)<<16)
+#define VP_POLY8_Y1_x2(a) ((0x1f&a)<<8)
+#define VP_POLY8_Y1_x3(a) ((0x1f&a)<<0)
+
+#define VP_POLY8_Y2_x0(a) ((0x7f&a)<<24)
+#define VP_POLY8_Y2_x1(a) ((0x7f&a)<<16)
+#define VP_POLY8_Y2_x2(a) ((0x7f&a)<<8)
+#define VP_POLY8_Y2_x3(a) ((0x7f&a)<<0)
+
+#define VP_POLY8_Y3_x0(a) ((0x7f&a)<<24)
+#define VP_POLY8_Y3_x1(a) ((0x7f&a)<<16)
+#define VP_POLY8_Y3_x2(a) ((0x7f&a)<<8)
+#define VP_POLY8_Y3_x3(a) ((0x7f&a)<<0)
+
+#define VP_POLY4_Y0_x0(a) ((0x3f&a)<<24)
+#define VP_POLY4_Y0_x1(a) ((0x3f&a)<<16)
+#define VP_POLY4_Y0_x2(a) ((0x3f&a)<<8)
+#define VP_POLY4_Y0_x3(a) ((0x3f&a)<<0)
+
+#define VP_POLY4_Y1_x0(a) ((0x7f&a)<<24)
+#define VP_POLY4_Y1_x1(a) ((0x7f&a)<<16)
+#define VP_POLY4_Y1_x2(a) ((0x7f&a)<<8)
+#define VP_POLY4_Y1_x3(a) ((0x7f&a)<<0)
+
+#define VP_POLY4_Y2_x0(a) ((0x7f&a)<<24)
+#define VP_POLY4_Y2_x1(a) ((0x7f&a)<<16)
+#define VP_POLY4_Y2_x2(a) ((0x7f&a)<<8)
+#define VP_POLY4_Y2_x3(a) ((0x7f&a)<<0)
+
+#define VP_POLY4_Y3_x0(a) ((0x3f&a)<<24)
+#define VP_POLY4_Y3_x1(a) ((0x3f&a)<<16)
+#define VP_POLY4_Y3_x2(a) ((0x3f&a)<<8)
+#define VP_POLY4_Y3_x3(a) ((0x3f&a)<<0)
+
+#define VP_POLY4_C0_PH0(a) ((0x7f&a)<<24)
+#define VP_POLY4_C0_PH1(a) ((0x7f&a)<<16)
+#define VP_POLY4_C0_PH2(a) ((0x7f&a)<<8)
+#define VP_POLY4_C0_PH3(a) ((0x7f&a)<<0)
+
+#define VP_POLY4_C0_PH4(a) ((0x3f&a)<<24)
+#define VP_POLY4_C0_PH5(a) ((0x3f&a)<<16)
+#define VP_POLY4_C0_PH6(a) ((0x3f&a)<<8)
+#define VP_POLY4_C0_PH7(a) ((0x3f&a)<<0)
+
+#define VP_POLY4_C0_PH8(a) ((0x3f&a)<<24)
+#define VP_POLY4_C0_PH9(a) ((0x3f&a)<<16)
+#define VP_POLY4_C0_PH10(a) ((0x3f&a)<<8)
+#define VP_POLY4_C0_PH11(a) ((0x3f&a)<<0)
+
+#define VP_POLY4_C0_PH12(a) ((0x1f&a)<<24)
+#define VP_POLY4_C0_PH13(a) ((0x1f&a)<<16)
+#define VP_POLY4_C0_PH14(a) ((0x1f&a)<<8)
+#define VP_POLY4_C0_PH15(a) ((0x1f&a)<<0)
+
+#define VP_POLY4_C1_PH0(a) ((0xff&a)<<24)
+#define VP_POLY4_C1_PH1(a) ((0xff&a)<<16)
+#define VP_POLY4_C1_PH2(a) ((0xff&a)<<8)
+#define VP_POLY4_C1_PH3(a) ((0xff&a)<<0)
+
+#define VP_POLY4_C1_PH4(a) ((0xff&a)<<24)
+#define VP_POLY4_C1_PH5(a) ((0xff&a)<<16)
+#define VP_POLY4_C1_PH6(a) ((0xff&a)<<8)
+#define VP_POLY4_C1_PH7(a) ((0xff&a)<<0)
+
+#define VP_POLY4_C1_PH8(a) ((0xff&a)<<24)
+#define VP_POLY4_C1_PH9(a) ((0xff&a)<<16)
+#define VP_POLY4_C1_PH10(a) ((0xff&a)<<8)
+#define VP_POLY4_C1_PH11(a) ((0xff&a)<<0)
+
+#define VP_POLY4_C1_PH12(a) ((0x7f&a)<<24)
+#define VP_POLY4_C1_PH13(a) ((0x7f&a)<<16)
+#define VP_POLY4_C1_PH14(a) ((0x7f&a)<<8)
+#define VP_POLY4_C1_PH15(a) ((0x7f&a)<<0)
+
+#define VP_CSC_COEF(a) (0xfff&a)
+
+#define VP_BY_PASS_ENABLE (0)
+#define VP_BY_PASS_DISABLE (1)
+
+#define VP_SATURATION(a) (0xff&a)
+
+#define VP_TH_HNOISE(a) ((0xf&a)<<8)
+#define VP_SHARPNESS(a) (0x3&a)
+
+#define VP_LINE_INTC(a) ((0xffff&a)<<8)
+#define VP_LINE_SLOPE(a) (0xff&a)
+#define VP_LINE_INTC_CLEAR(a) (~(0xffff<<8)&a)
+#define VP_LINE_SLOPE_CLEAR(a) (~0xff&a)
+
+#define VP_BRIGHT_OFFSET(a) (0x1ff&a)
+
+#define VP_SUB_Y_OFFSET_ENABLE (1<<1)
+#define VP_SUB_Y_OFFSET_DISABLE (0<<1)
+#define VP_CSC_ENABLE (1)
+#define VP_CSC_DISABLE (0)
+
+static unsigned int g_vp_contrast_brightness;
+
+#define Y2Y_COEF_601_TO_709 0x400
+#define CB2Y_COEF_601_TO_709 0x879
+#define CR2Y_COEF_601_TO_709 0x8d9
+
+#define Y2CB_COEF_601_TO_709 0x0
+#define CB2CB_COEF_601_TO_709 0x413
+#define CR2CB_COEF_601_TO_709 0x875
+
+#define Y2CR_COEF_601_TO_709 0x0
+#define CB2CR_COEF_601_TO_709 0x04d
+#define CR2CR_COEF_601_TO_709 0x41a
+
+#define Y2Y_COEF_709_TO_601 0x400
+#define CB2Y_COEF_709_TO_601 0x068
+#define CR2Y_COEF_709_TO_601 0x0c9
+
+#define Y2CB_COEF_709_TO_601 0x0
+#define CB2CB_COEF_709_TO_601 0x3f6
+#define CR2CB_COEF_709_TO_601 0x871
+
+#define Y2CR_COEF_709_TO_601 0x0
+#define CB2CR_COEF_709_TO_601 0x84a
+#define CR2CR_COEF_709_TO_601 0xbef
+
+#define TILE_WIDTH 0x40
+#define MAX_NUM_OF_FRM 34
+
+#endif
+
diff --git a/drivers/media/video/samsung/tv20/s5pc100/sdout_s5pc100.c b/drivers/media/video/samsung/tv20/s5pc100/sdout_s5pc100.c
new file mode 100644
index 0000000..4346348
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/s5pc100/sdout_s5pc100.c
@@ -0,0 +1,2031 @@
+/* linux/drivers/media/video/samsung/tv20/s5pc100/sdout_s5pc100.c
+ *
+ * tv encoder raw ftn file for Samsung TVOut driver
+ *
+ * Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <linux/sizes.h>
+#include <linux/memory.h>
+
+#include "tv_out_s5pc100.h"
+
+#include "regs/regs-sdaout.h"
+
+#ifdef COFIG_TVOUT_RAW_DBG
+#define S5P_SDAOUT_DEBUG 1
+#endif
+
+#ifdef S5P_SDAOUT_DEBUG
+#define SDPRINTK(fmt, args...) \
+ printk(KERN_INFO "\t\t[SDOUT] %s: " fmt, __func__ , ## args)
+#else
+#define SDPRINTK(fmt, args...)
+#endif
+
+static struct resource *sdout_mem;
+void __iomem *sdout_base;
+
+/*
+* initialization - iniization functions are only called under stopping SDOUT
+*/
+enum s5p_tv_sd_err __s5p_sdout_init_video_scale_cfg(
+ enum s5p_sd_level component_level,
+ enum s5p_sd_vsync_ratio component_ratio,
+ enum s5p_sd_level composite_level,
+ enum s5p_sd_vsync_ratio composite_ratio)
+{
+ u32 temp_reg = 0;
+
+ SDPRINTK("%d, %d, %d, %d\n\r", component_level, component_ratio,
+ composite_level, composite_ratio);
+
+ switch (component_level) {
+
+ case S5P_TV_SD_LEVEL_0IRE:
+ temp_reg = SDO_COMPONENT_LEVEL_SEL_0IRE;
+ break;
+
+ case S5P_TV_SD_LEVEL_75IRE:
+ temp_reg = SDO_COMPONENT_LEVEL_SEL_75IRE;
+ break;
+
+ default:
+ SDPRINTK("invalid component_level parameter(%d)\n\r",
+ component_level);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ switch (composite_level) {
+
+ case SDOUT_VTOS_RATIO_10_4:
+ temp_reg |= SDO_COMPONENT_VTOS_RATIO_10_4;
+ break;
+
+ case SDOUT_VTOS_RATIO_7_3:
+ temp_reg |= SDO_COMPONENT_VTOS_RATIO_7_3;
+ break;
+
+ default:
+ SDPRINTK(" invalid composite_level parameter(%d)\n\r",
+ composite_level);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ switch (composite_level) {
+
+ case S5P_TV_SD_LEVEL_0IRE:
+ temp_reg |= SDO_COMPOSITE_LEVEL_SEL_0IRE;
+ break;
+
+ case S5P_TV_SD_LEVEL_75IRE:
+ temp_reg |= SDO_COMPOSITE_LEVEL_SEL_75IRE;
+ break;
+
+ default:
+ SDPRINTK("invalid composite_ratio parameter(%d)\n\r",
+ composite_ratio);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ switch (composite_ratio) {
+
+ case SDOUT_VTOS_RATIO_10_4:
+ temp_reg |= SDO_COMPOSITE_VTOS_RATIO_10_4;
+ break;
+
+ case SDOUT_VTOS_RATIO_7_3:
+ temp_reg |= SDO_COMPOSITE_VTOS_RATIO_7_3;
+ break;
+
+ default:
+ SDPRINTK("invalid component_ratio parameter(%d)\n\r",
+ component_ratio);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ writel(temp_reg, sdout_base + S5P_SDO_SCALE);
+
+ SDPRINTK("0x%08x)\n\r", readl(sdout_base + S5P_SDO_SCALE));
+
+ return SDOUT_NO_ERROR;
+}
+
+enum s5p_tv_sd_err __s5p_sdout_init_sync_signal_pin(
+ enum s5p_sd_sync_sig_pin pin)
+{
+ SDPRINTK("%d\n\r", pin);
+
+ switch (pin) {
+
+ case SDOUT_SYNC_SIG_NO:
+ writel(SDO_COMPONENT_SYNC_ABSENT, sdout_base + S5P_SDO_SYNC);
+ break;
+
+ case SDOUT_SYNC_SIG_YG:
+ writel(SDO_COMPONENT_SYNC_YG, sdout_base + S5P_SDO_SYNC);
+ break;
+
+ case SDOUT_SYNC_SIG_ALL:
+ writel(SDO_COMPONENT_SYNC_ALL, sdout_base + S5P_SDO_SYNC);
+ break;
+
+ default:
+ SDPRINTK("invalid pin parameter(%d)\n\r", pin);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ SDPRINTK("0x%08x\n\r", readl(sdout_base + S5P_SDO_SYNC));
+
+ return SDOUT_NO_ERROR;
+}
+
+enum s5p_tv_sd_err __s5p_sdout_init_vbi(bool wss_cvbs,
+ enum s5p_sd_closed_caption_type caption_cvbs,
+ bool wss_y_sideo,
+ enum s5p_sd_closed_caption_type caption_y_sideo,
+ bool cgmsa_rgb,
+ bool wss_rgb,
+ enum s5p_sd_closed_caption_type caption_rgb,
+ bool cgmsa_y_ppr,
+ bool wss_y_ppr,
+ enum s5p_sd_closed_caption_type caption_y_ppr)
+{
+ u32 temp_reg = 0;
+
+ SDPRINTK(" %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n\r",
+ wss_cvbs, caption_cvbs, wss_y_sideo, caption_y_sideo,
+ cgmsa_rgb, wss_rgb, caption_rgb, cgmsa_y_ppr, wss_y_ppr,
+ caption_y_ppr);
+
+ if (wss_cvbs)
+ temp_reg = SDO_CVBS_WSS_INS;
+ else
+ temp_reg = SDO_CVBS_NO_WSS;
+
+
+ switch (caption_cvbs) {
+
+ case SDOUT_NO_INS:
+ temp_reg |= SDO_CVBS_NO_CLOSED_CAPTION;
+ break;
+
+ case SDOUT_INS_1:
+ temp_reg |= SDO_CVBS_21H_CLOSED_CAPTION;
+ break;
+
+ case SDOUT_INS_2:
+ temp_reg |= SDO_CVBS_21H_284H_CLOSED_CAPTION;
+ break;
+
+ case SDOUT_INS_OTHERS:
+ temp_reg |= SDO_CVBS_USE_OTHERS;
+ break;
+
+ default:
+ SDPRINTK(" invalid caption_cvbs parameter(%d)\n\r",
+ caption_cvbs);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ if (wss_y_sideo)
+ temp_reg |= SDO_SVIDEO_WSS_INS;
+ else
+ temp_reg |= SDO_SVIDEO_NO_WSS;
+
+
+ switch (caption_y_sideo) {
+
+ case SDOUT_NO_INS:
+ temp_reg |= SDO_SVIDEO_NO_CLOSED_CAPTION;
+ break;
+
+ case SDOUT_INS_1:
+ temp_reg |= SDO_SVIDEO_21H_CLOSED_CAPTION;
+ break;
+
+ case SDOUT_INS_2:
+ temp_reg |= SDO_SVIDEO_21H_284H_CLOSED_CAPTION;
+ break;
+
+ case SDOUT_INS_OTHERS:
+ temp_reg |= SDO_SVIDEO_USE_OTHERS;
+ break;
+
+ default:
+ SDPRINTK("invalid caption_y_sideo parameter(%d)\n\r",
+ caption_y_sideo);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ if (cgmsa_rgb)
+ temp_reg |= SDO_RGB_CGMSA_INS;
+ else
+ temp_reg |= SDO_RGB_NO_CGMSA;
+
+
+ if (wss_rgb)
+ temp_reg |= SDO_RGB_WSS_INS;
+ else
+ temp_reg |= SDO_RGB_NO_WSS;
+
+
+ switch (caption_rgb) {
+
+ case SDOUT_NO_INS:
+ temp_reg |= SDO_RGB_NO_CLOSED_CAPTION;
+ break;
+
+ case SDOUT_INS_1:
+ temp_reg |= SDO_RGB_21H_CLOSED_CAPTION;
+ break;
+
+ case SDOUT_INS_2:
+ temp_reg |= SDO_RGB_21H_284H_CLOSED_CAPTION;
+ break;
+
+ case SDOUT_INS_OTHERS:
+ temp_reg |= SDO_RGB_USE_OTHERS;
+ break;
+
+ default:
+ SDPRINTK(" invalid caption_rgb parameter(%d)\n\r",
+ caption_rgb);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ if (cgmsa_y_ppr)
+ temp_reg |= SDO_YPBPR_CGMSA_INS;
+ else
+ temp_reg |= SDO_YPBPR_NO_CGMSA;
+
+ if (wss_y_ppr)
+ temp_reg |= SDO_YPBPR_WSS_INS;
+ else
+ temp_reg |= SDO_YPBPR_NO_WSS;
+
+
+ switch (caption_y_ppr) {
+
+ case SDOUT_NO_INS:
+ temp_reg |= SDO_YPBPR_NO_CLOSED_CAPTION;
+ break;
+
+ case SDOUT_INS_1:
+ temp_reg |= SDO_YPBPR_21H_CLOSED_CAPTION;
+ break;
+
+ case SDOUT_INS_2:
+ temp_reg |= SDO_YPBPR_21H_284H_CLOSED_CAPTION;
+ break;
+
+ case SDOUT_INS_OTHERS:
+ temp_reg |= SDO_YPBPR_USE_OTHERS;
+ break;
+
+ default:
+ SDPRINTK("invalid caption_y_ppr parameter(%d)\n\r",
+ caption_y_ppr);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ writel(temp_reg, sdout_base + S5P_SDO_VBI);
+
+ SDPRINTK("0x%08x\n\r", readl(sdout_base + S5P_SDO_VBI));
+
+ return SDOUT_NO_ERROR;
+}
+
+enum s5p_tv_sd_err __s5p_sdout_init_offset_gain(
+ enum s5p_sd_channel_sel channel,
+ u32 offset, u32 gain)
+{
+ SDPRINTK("%d, %d, %d\n\r", channel, offset, gain);
+
+ switch (channel) {
+
+ case SDOUT_CHANNEL_0:
+ writel(SDO_SCALE_CONV_OFFSET(offset) |
+ SDO_SCALE_CONV_GAIN(gain),
+ sdout_base + S5P_SDO_SCALE_CH0);
+ SDPRINTK("0x%08x\n\r", readl(sdout_base + S5P_SDO_SCALE_CH0));
+ break;
+
+ case SDOUT_CHANNEL_1:
+ writel(SDO_SCALE_CONV_OFFSET(offset) |
+ SDO_SCALE_CONV_GAIN(gain),
+ sdout_base + S5P_SDO_SCALE_CH1);
+ SDPRINTK(" 0x%08x\n\r", readl(sdout_base + S5P_SDO_SCALE_CH1));
+ break;
+
+ case SDOUT_CHANNEL_2:
+ writel(SDO_SCALE_CONV_OFFSET(offset) |
+ SDO_SCALE_CONV_GAIN(gain),
+ sdout_base + S5P_SDO_SCALE_CH2);
+ SDPRINTK(" 0x%08x\n\r", readl(sdout_base + S5P_SDO_SCALE_CH2));
+ break;
+
+ default:
+ SDPRINTK(" invalid channel parameter(%d)\n\r", channel);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ return SDOUT_NO_ERROR;
+}
+
+void __s5p_sdout_init_delay(u32 delay_y,
+ u32 offset_video_start,
+ u32 offset_video_end)
+{
+ SDPRINTK("%d, %d, %d\n\r", delay_y,
+ offset_video_start, offset_video_end);
+
+ writel(SDO_DELAY_YTOC(delay_y) |
+ SDO_ACTIVE_START_OFFSET(offset_video_start) |
+ SDO_ACTIVE_END_OFFSET(offset_video_end),
+ sdout_base + S5P_SDO_YCDELAY);
+
+ SDPRINTK("0x%08x\n\r", readl(sdout_base + S5P_SDO_YCDELAY));
+}
+
+void __s5p_sdout_init_schlock(bool color_sucarrier_pha_adj)
+{
+ SDPRINTK("%d\n\r", color_sucarrier_pha_adj);
+
+ if (color_sucarrier_pha_adj)
+ writel(SDO_COLOR_SC_PHASE_ADJ, sdout_base + S5P_SDO_SCHLOCK);
+ else
+ writel(SDO_COLOR_SC_PHASE_NOADJ, sdout_base + S5P_SDO_SCHLOCK);
+
+
+ SDPRINTK("0x%08x\n\r", readl(sdout_base + S5P_SDO_SCHLOCK));
+}
+
+enum s5p_tv_sd_err __s5p_sdout_init_dac_power_onoff(
+ enum s5p_sd_channel_sel channel, bool dac_on)
+{
+ u32 temp_on_off;
+
+ SDPRINTK("%d, %d)\n\r", channel, dac_on);
+
+ switch (channel) {
+
+ case SDOUT_CHANNEL_0:
+ temp_on_off = SDO_POWER_ON_DAC0;
+ break;
+
+ case SDOUT_CHANNEL_1:
+ temp_on_off = SDO_POWER_ON_DAC1;
+ break;
+
+ case SDOUT_CHANNEL_2:
+ temp_on_off = SDO_POWER_ON_DAC2;
+ break;
+
+ default:
+ SDPRINTK("invalid channel parameter(%d)\n\r", channel);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ if (dac_on)
+ writel(readl(sdout_base + S5P_SDO_DAC) | temp_on_off,
+ sdout_base + S5P_SDO_DAC);
+ else
+ writel(readl(sdout_base + S5P_SDO_DAC) & ~temp_on_off,
+ sdout_base + S5P_SDO_DAC);
+
+
+ SDPRINTK("0x%08x\n\r", readl(sdout_base + S5P_SDO_DAC));
+
+ return SDOUT_NO_ERROR;
+}
+
+void __s5p_sdout_init_color_compensaton_onoff(bool bright_hue_saturation_adj,
+ bool y_ppr_color_compensation,
+ bool rgcolor_compensation,
+ bool y_c_color_compensation,
+ bool y_cvbs_color_compensation)
+{
+ u32 temp_reg = 0;
+
+ SDPRINTK("%d, %d, %d, %d, %d)\n\r", bright_hue_saturation_adj,
+ y_ppr_color_compensation, rgcolor_compensation,
+ y_c_color_compensation, y_cvbs_color_compensation);
+
+ if (bright_hue_saturation_adj)
+ temp_reg &= ~SDO_COMPONENT_BHS_ADJ_OFF;
+ else
+ temp_reg |= SDO_COMPONENT_BHS_ADJ_OFF;
+
+
+ if (y_ppr_color_compensation)
+ temp_reg &= ~SDO_COMPONENT_YPBPR_COMP_OFF;
+ else
+ temp_reg |= SDO_COMPONENT_YPBPR_COMP_OFF;
+
+
+ if (rgcolor_compensation)
+ temp_reg &= ~SDO_COMPONENT_RGB_COMP_OFF;
+ else
+ temp_reg |= SDO_COMPONENT_RGB_COMP_OFF;
+
+
+ if (y_c_color_compensation)
+ temp_reg &= ~SDO_COMPONENT_YC_COMP_OFF;
+ else
+ temp_reg |= SDO_COMPONENT_YC_COMP_OFF;
+
+
+ if (y_cvbs_color_compensation)
+ temp_reg &= ~SDO_COMPONENT_CVBS_COMP_OFF;
+ else
+ temp_reg |= SDO_COMPONENT_CVBS_COMP_OFF;
+
+
+ writel(temp_reg, sdout_base + S5P_SDO_CCCON);
+
+ SDPRINTK("0x%08x\n\r", readl(sdout_base + S5P_SDO_CCCON));
+}
+
+void __s5p_sdout_init_brightness_hue_saturation(u32 gain_brightness,
+ u32 offset_brightness,
+ u32 gain0_cb_hue_saturation,
+ u32 gain1_cb_hue_saturation,
+ u32 gain0_cr_hue_saturation,
+ u32 gain1_cr_hue_saturation,
+ u32 offset_cb_hue_saturation,
+ u32 offset_cr_hue_saturation)
+{
+ SDPRINTK(" %d, %d, %d, %d, %d, %d, %d, %d)\n\r", gain_brightness,
+ offset_brightness, gain0_cb_hue_saturation,
+ gain1_cb_hue_saturation, gain0_cr_hue_saturation,
+ gain1_cr_hue_saturation, offset_cb_hue_saturation,
+ offset_cr_hue_saturation);
+
+ writel(SDO_BRIGHTNESS_GAIN(gain_brightness) |
+ SDO_BRIGHTNESS_OFFSET(offset_brightness),
+ sdout_base + S5P_SDO_YSCALE);
+
+ writel(SDO_HS_CB_GAIN0(gain0_cb_hue_saturation) |
+ SDO_HS_CB_GAIN1(gain1_cb_hue_saturation),
+ sdout_base + S5P_SDO_CBSCALE);
+
+ writel(SDO_HS_CR_GAIN0(gain0_cr_hue_saturation) |
+ SDO_HS_CR_GAIN1(gain1_cr_hue_saturation),
+ sdout_base + S5P_SDO_CRSCALE);
+
+ writel(SDO_HS_CR_OFFSET(offset_cr_hue_saturation) |
+ SDO_HS_CB_OFFSET(offset_cb_hue_saturation),
+ sdout_base + S5P_SDO_CB_CR_OFFSET);
+
+ SDPRINTK("0x%08x, 0x%08x, 0x%08x, 0x%08x)\n\r",
+ readl(sdout_base + S5P_SDO_YSCALE),
+ readl(sdout_base + S5P_SDO_CBSCALE),
+ readl(sdout_base + S5P_SDO_CRSCALE),
+ readl(sdout_base + S5P_SDO_CB_CR_OFFSET));
+}
+
+void __s5p_sdout_init_rgb_color_compensation(u32 max_rgbcube,
+ u32 min_rgbcube)
+{
+ SDPRINTK("0x%08x, 0x%08x\n\r", max_rgbcube, min_rgbcube);
+
+ writel(SDO_MAX_RGB_CUBE(max_rgbcube) | SDO_MIN_RGB_CUBE(min_rgbcube),
+ sdout_base + S5P_SDO_RGB_CC);
+
+ SDPRINTK("0x%08x)\n\r", readl(sdout_base + S5P_SDO_RGB_CC));
+}
+
+void __s5p_sdout_init_cvbs_color_compensation(u32 y_lower_mid,
+ u32 y_bottom,
+ u32 y_top,
+ u32 y_upper_mid,
+ u32 radius)
+{
+ SDPRINTK("%d, %d, %d, %d, %d\n\r", y_lower_mid, y_bottom,
+ y_top, y_upper_mid, radius);
+
+ writel(SDO_Y_LOWER_MID_CVBS_CORN(y_lower_mid) |
+ SDO_Y_BOTTOM_CVBS_CORN(y_bottom),
+ sdout_base + S5P_SDO_CVBS_CC_Y1);
+ writel(SDO_Y_TOP_CVBS_CORN(y_top) |
+ SDO_Y_UPPER_MID_CVBS_CORN(y_upper_mid),
+ sdout_base + S5P_SDO_CVBS_CC_Y2);
+ writel(SDO_RADIUS_CVBS_CORN(radius), sdout_base + S5P_SDO_CVBS_CC_C);
+
+ SDPRINTK("0x%08x, 0x%08x, 0x%08x)\n\r",
+ readl(sdout_base + S5P_SDO_CVBS_CC_Y1),
+ readl(sdout_base + S5P_SDO_CVBS_CC_Y2),
+ readl(sdout_base + S5P_SDO_CVBS_CC_C));
+}
+
+void __s5p_sdout_init_svideo_color_compensation(u32 y_top,
+ u32 y_bottom,
+ u32 y_c_cylinder)
+{
+ SDPRINTK(" %d, %d, %d)\n\r", y_top, y_bottom, y_c_cylinder);
+
+ writel(SDO_Y_TOP_YC_CYLINDER(y_top) |
+ SDO_Y_BOTOM_YC_CYLINDER(y_bottom),
+ sdout_base + S5P_SDO_YC_CC_Y);
+ writel(SDO_RADIUS_YC_CYLINDER(y_c_cylinder),
+ sdout_base + S5P_SDO_YC_CC_C);
+
+ SDPRINTK("0x%08x, 0x%08x)\n\r", readl(sdout_base + S5P_SDO_YC_CC_Y),
+ readl(sdout_base + S5P_SDO_YC_CC_C));
+}
+
+void __s5p_sdout_init_component_porch(u32 back_525,
+ u32 front_525,
+ u32 back_625,
+ u32 front_625)
+{
+ SDPRINTK(" %d, %d, %d, %d)\n\r", back_525,
+ front_525, back_625, front_625);
+
+ writel(SDO_COMPONENT_525_BP(back_525) |
+ SDO_COMPONENT_525_FP(front_525),
+ sdout_base + S5P_SDO_CSC_525_PORCH);
+ writel(SDO_COMPONENT_625_BP(back_625) |
+ SDO_COMPONENT_625_FP(front_625),
+ sdout_base + S5P_SDO_CSC_625_PORCH);
+
+ SDPRINTK(" 0x%08x, 0x%08x)\n\r",
+ readl(sdout_base + S5P_SDO_CSC_525_PORCH),
+ readl(sdout_base + S5P_SDO_CSC_625_PORCH));
+}
+
+enum s5p_tv_sd_err __s5p_sdout_init_vesa_rgb_sync(
+ enum s5p_sd_vesa_rgb_sync_type sync_type,
+ enum s5p_tv_active_polarity v_sync_active,
+ enum s5p_tv_active_polarity h_sync_active)
+{
+ u32 temp_reg = 0;
+
+ SDPRINTK("%d, %d, %d\n\r", sync_type, v_sync_active, h_sync_active);
+
+ switch (sync_type) {
+
+ case SDOUT_VESA_RGB_SYNC_COMPOSITE:
+ temp_reg |= SDO_RGB_SYNC_COMPOSITE;
+ break;
+
+ case SDOUT_VESA_RGB_SYNC_SEPARATE:
+ temp_reg |= SDO_RGB_SYNC_SEPERATE;
+ break;
+
+ default:
+ SDPRINTK(" invalid sync_type parameter(%d)\n\r", sync_type);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ switch (v_sync_active) {
+
+ case TVOUT_POL_ACTIVE_LOW:
+ temp_reg |= SDO_RGB_VSYNC_LOW_ACT;
+ break;
+
+ case TVOUT_POL_ACTIVE_HIGH:
+ temp_reg |= SDO_RGB_VSYNC_HIGH_ACT;
+ break;
+
+ default:
+ SDPRINTK(" invalid v_sync_active parameter(%d)\n\r",
+ v_sync_active);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ switch (h_sync_active) {
+
+ case TVOUT_POL_ACTIVE_LOW:
+ temp_reg |= SDO_RGB_HSYNC_LOW_ACT;
+ break;
+
+ case TVOUT_POL_ACTIVE_HIGH:
+ temp_reg |= SDO_RGB_HSYNC_HIGH_ACT;
+ break;
+
+ default:
+ SDPRINTK(" invalid h_sync_active parameter(%d)\n\r",
+ h_sync_active);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ writel(temp_reg, sdout_base + S5P_SDO_RGBSYNC);
+
+ SDPRINTK("0x%08x\n\r", readl(sdout_base + S5P_SDO_RGBSYNC));
+
+ return SDOUT_NO_ERROR;
+}
+
+void __s5p_sdout_init_oversampling_filter_coeff(u32 size,
+ u32 *coeff,
+ u32 *coeff1,
+ u32 *coeff2)
+{
+ u32 *temp_reg = 0;
+
+ SDPRINTK(" %d, 0x%x, 0x%x, 0x%x\n\r", (u32)size, (u32)coeff,
+ (u32)coeff1, (u32)coeff2);
+
+ if (coeff != NULL) {
+ temp_reg = (u32 *)readl(sdout_base + S5P_SDO_OSFC00_0);
+ memcpy((void *)temp_reg, (const void *)coeff, size*4);
+ }
+
+ if (coeff1 != NULL) {
+ temp_reg = (u32 *)readl(sdout_base + S5P_SDO_OSFC00_1);
+ memcpy((void *)temp_reg, (const void *)coeff1, size*4);
+ }
+
+ if (coeff2 != NULL) {
+ temp_reg = (u32 *)readl(sdout_base + S5P_SDO_OSFC00_2);
+ memcpy((void *)temp_reg, (const void *)coeff2, size*4);
+ }
+
+ SDPRINTK(" ()\n\r");
+}
+
+enum s5p_tv_sd_err __s5p_sdout_init_ch_xtalk_cancel_coef(
+ enum s5p_sd_channel_sel channel,
+ u32 coeff2, u32 coeff1)
+{
+ SDPRINTK(" %d, %d, %d\n\r", channel, coeff2, coeff1);
+
+ switch (channel) {
+
+ case SDOUT_CHANNEL_0:
+ writel(SDO_XTALK_COEF02(coeff2) | SDO_XTALK_COEF01(coeff1),
+ sdout_base + S5P_SDO_XTALK0);
+ SDPRINTK(" 0x%08x)\n\r", readl(sdout_base + S5P_SDO_XTALK0));
+ break;
+
+ case SDOUT_CHANNEL_1:
+ writel(SDO_XTALK_COEF02(coeff2) | SDO_XTALK_COEF01(coeff1),
+ sdout_base + S5P_SDO_XTALK1);
+ SDPRINTK(" 0x%08x)\n\r", readl(sdout_base + S5P_SDO_XTALK1));
+ break;
+
+ case SDOUT_CHANNEL_2:
+ writel(SDO_XTALK_COEF02(coeff2) | SDO_XTALK_COEF01(coeff1),
+ sdout_base + S5P_SDO_XTALK2);
+ SDPRINTK("0x%08x)\n\r", readl(sdout_base + S5P_SDO_XTALK2));
+ break;
+
+ default:
+ SDPRINTK(" invalid channel parameter(%d)\n\r", channel);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ return SDOUT_NO_ERROR;
+}
+
+void __s5p_sdout_init_closed_caption(u32 display_cc, u32 non_display_cc)
+{
+ SDPRINTK("%d, %d\n\r", display_cc, non_display_cc);
+
+ writel(SDO_DISPLAY_CC_CAPTION(display_cc) |
+ SDO_NON_DISPLAY_CC_CAPTION(non_display_cc),
+ sdout_base + S5P_SDO_ARMCC);
+
+ SDPRINTK("0x%x\n\r", readl(sdout_base + S5P_SDO_ARMCC));
+}
+
+
+static u32 __s5p_sdout_init_wss_cgms_crc(u32 value)
+{
+ u8 i;
+ u8 CGMS[14], CRC[6], OLD_CRC;
+ u32 temp_in;
+
+ temp_in = value;
+
+ for (i = 0; i < 14; i++)
+ CGMS[i] = (u8)(temp_in >> i) & 0x1 ;
+
+ for (i = 0; i < 6; i++)
+ CRC[i] = 0x1;
+
+ for (i = 0; i < 14; i++) {
+ OLD_CRC = CRC[0];
+ CRC[0] = CRC[1];
+ CRC[1] = CRC[2];
+ CRC[2] = CRC[3];
+ CRC[3] = CRC[4];
+ CRC[4] = OLD_CRC ^ CGMS[i] ^ CRC[5];
+ CRC[5] = OLD_CRC ^ CGMS[i];
+ }
+
+ temp_in &= 0x3fff;
+
+ for (i = 0; i < 6; i++)
+ temp_in |= ((u32)(CRC[i] & 0x1) << i);
+
+
+ return temp_in;
+}
+
+
+enum s5p_tv_sd_err __s5p_sdout_init_wss525_data(
+ enum s5p_sd_525_copy_permit copy_permit,
+ enum s5p_sd_525_mv_psp mv_psp,
+ enum s5p_sd_525_copy_info copy_info,
+ bool analog_on,
+ enum s5p_sd_525_aspect_ratio display_ratio)
+{
+ u32 temp_reg = 0;
+
+ SDPRINTK("%d, %d, %d, %d\n\r", copy_permit, mv_psp, copy_info,
+ display_ratio);
+
+ switch (copy_permit) {
+
+ case SDO_525_COPY_PERMIT:
+ temp_reg = SDO_WORD2_WSS525_COPY_PERMIT;
+ break;
+
+ case SDO_525_ONECOPY_PERMIT:
+ temp_reg = SDO_WORD2_WSS525_ONECOPY_PERMIT;
+ break;
+
+ case SDO_525_NOCOPY_PERMIT:
+ temp_reg = SDO_WORD2_WSS525_NOCOPY_PERMIT;
+ break;
+
+ default:
+ SDPRINTK(" invalid copy_permit parameter(%d)\n\r",
+ copy_permit);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ switch (mv_psp) {
+
+ case SDO_525_MV_PSP_OFF:
+ temp_reg |= SDO_WORD2_WSS525_MV_PSP_OFF;
+ break;
+
+ case SDO_525_MV_PSP_ON_2LINE_BURST:
+ temp_reg |= SDO_WORD2_WSS525_MV_PSP_ON_2LINE_BURST;
+ break;
+
+ case SDO_525_MV_PSP_ON_BURST_OFF:
+ temp_reg |= SDO_WORD2_WSS525_MV_PSP_ON_BURST_OFF;
+ break;
+
+ case SDO_525_MV_PSP_ON_4LINE_BURST:
+ temp_reg |= SDO_WORD2_WSS525_MV_PSP_ON_4LINE_BURST;
+ break;
+
+ default:
+ SDPRINTK(" invalid mv_psp parameter(%d)\n\r", mv_psp);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ switch (copy_info) {
+
+ case SDO_525_COPY_INFO:
+ temp_reg |= SDO_WORD1_WSS525_COPY_INFO;
+ break;
+
+ case SDO_525_DEFAULT:
+ temp_reg |= SDO_WORD1_WSS525_DEFAULT;
+ break;
+
+ default:
+ SDPRINTK(" invalid copy_info parameter(%d)\n\r", copy_info);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ if (analog_on)
+ temp_reg |= SDO_WORD2_WSS525_ANALOG_ON;
+ else
+ temp_reg |= SDO_WORD2_WSS525_ANALOG_OFF;
+
+
+ switch (display_ratio) {
+
+ case SDO_525_COPY_PERMIT:
+ temp_reg |= SDO_WORD0_WSS525_4_3_NORMAL;
+ break;
+
+ case SDO_525_ONECOPY_PERMIT:
+ temp_reg |= SDO_WORD0_WSS525_16_9_ANAMORPIC;
+ break;
+
+ case SDO_525_NOCOPY_PERMIT:
+ temp_reg |= SDO_WORD0_WSS525_4_3_LETTERBOX;
+ break;
+
+ default:
+ SDPRINTK(" invalid display_ratio parameter(%d)\n\r",
+ display_ratio);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ writel(temp_reg | SDO_CRC_WSS525(
+ __s5p_sdout_init_wss_cgms_crc(temp_reg)),
+ sdout_base + S5P_SDO_WSS525);
+
+ SDPRINTK("0x%08x)\n\r", readl(sdout_base + S5P_SDO_WSS525));
+
+ return SDOUT_NO_ERROR;
+}
+
+enum s5p_tv_sd_err __s5p_sdout_init_wss625_data(bool surround_sound,
+ bool copyright,
+ bool copy_protection,
+ bool text_subtitles,
+ enum s5p_sd_625_subtitles open_subtitles,
+ enum s5p_sd_625_camera_film camera_film,
+ enum s5p_sd_625_color_encoding color_encoding,
+ bool helper_signal,
+ enum s5p_sd_625_aspect_ratio display_ratio)
+{
+ u32 temp_reg = 0;
+
+ SDPRINTK("%d, %d, %d, %d, %d, %d, %d, %d, %d\n\r",
+ surround_sound, copyright, copy_protection,
+ text_subtitles, open_subtitles, camera_film,
+ color_encoding, helper_signal, display_ratio);
+
+ if (surround_sound)
+ temp_reg = SDO_WSS625_SURROUND_SOUND_ENABLE;
+ else
+ temp_reg = SDO_WSS625_SURROUND_SOUND_DISABLE;
+
+
+ if (copyright)
+ temp_reg |= SDO_WSS625_COPYRIGHT;
+ else
+ temp_reg |= SDO_WSS625_NO_COPYRIGHT;
+
+
+ if (copy_protection)
+ temp_reg |= SDO_WSS625_COPY_RESTRICTED;
+ else
+ temp_reg |= SDO_WSS625_COPY_NOT_RESTRICTED;
+
+
+ if (text_subtitles)
+ temp_reg |= SDO_WSS625_TELETEXT_SUBTITLES;
+ else
+ temp_reg |= SDO_WSS625_TELETEXT_NO_SUBTITLES;
+
+
+ switch (open_subtitles) {
+
+ case SDO_625_NO_OPEN_SUBTITLES:
+ temp_reg |= SDO_WSS625_NO_OPEN_SUBTITLES;
+ break;
+
+ case SDO_625_INACT_OPEN_SUBTITLES:
+ temp_reg |= SDO_WSS625_INACT_OPEN_SUBTITLES;
+ break;
+
+ case SDO_625_OUTACT_OPEN_SUBTITLES:
+ temp_reg |= SDO_WSS625_OUTACT_OPEN_SUBTITLES;
+ break;
+
+ default:
+ SDPRINTK(" invalid open_subtitles parameter(%d)\n\r",
+ open_subtitles);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ switch (camera_film) {
+
+ case SDO_625_CAMERA:
+ temp_reg |= SDO_WSS625_CAMERA;
+ break;
+
+ case SDO_625_FILM:
+ temp_reg |= SDO_WSS625_FILM;
+ break;
+
+ default:
+ SDPRINTK("invalid camera_film parameter(%d)\n\r", camera_film);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ switch (color_encoding) {
+
+ case SDO_625_NORMAL_PAL:
+ temp_reg |= SDO_WSS625_NORMAL_PAL;
+ break;
+
+ case SDO_625_MOTION_ADAPTIVE_COLORPLUS:
+ temp_reg |= SDO_WSS625_MOTION_ADAPTIVE_COLORPLUS;
+ break;
+
+ default:
+ SDPRINTK("invalid color_encoding parameter(%d)\n\r",
+ color_encoding);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ if (helper_signal)
+ temp_reg |= SDO_WSS625_HELPER_SIG;
+ else
+ temp_reg |= SDO_WSS625_HELPER_NO_SIG;
+
+
+ switch (display_ratio) {
+
+ case SDO_625_4_3_FULL_576:
+ temp_reg |= SDO_WSS625_4_3_FULL_576;
+ break;
+
+ case SDO_625_14_9_LETTERBOX_CENTER_504:
+ temp_reg |= SDO_WSS625_14_9_LETTERBOX_CENTER_504;
+ break;
+
+ case SDO_625_14_9_LETTERBOX_TOP_504:
+ temp_reg |= SDO_WSS625_14_9_LETTERBOX_TOP_504;
+ break;
+
+ case SDO_625_16_9_LETTERBOX_CENTER_430:
+ temp_reg |= SDO_WSS625_16_9_LETTERBOX_CENTER_430;
+ break;
+
+ case SDO_625_16_9_LETTERBOX_TOP_430:
+ temp_reg |= SDO_WSS625_16_9_LETTERBOX_TOP_430;
+ break;
+
+ case SDO_625_16_9_LETTERBOX_CENTER:
+ temp_reg |= SDO_WSS625_16_9_LETTERBOX_CENTER;
+ break;
+
+ case SDO_625_14_9_FULL_CENTER_576:
+ temp_reg |= SDO_WSS625_14_9_FULL_CENTER_576;
+ break;
+
+ case SDO_625_16_9_ANAMORPIC_576:
+ temp_reg |= SDO_WSS625_16_9_ANAMORPIC_576;
+ break;
+
+ default:
+ SDPRINTK("invalid display_ratio parameter(%d)\n\r",
+ display_ratio);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ writel(temp_reg, sdout_base + S5P_SDO_WSS625);
+
+ SDPRINTK("0x%08x\n\r", readl(sdout_base + S5P_SDO_WSS625));
+
+ return SDOUT_NO_ERROR;
+}
+
+enum s5p_tv_sd_err __s5p_sdout_init_cgmsa525_data(
+ enum s5p_sd_525_copy_permit copy_permit,
+ enum s5p_sd_525_mv_psp mv_psp,
+ enum s5p_sd_525_copy_info copy_info,
+ bool analog_on,
+ enum s5p_sd_525_aspect_ratio display_ratio)
+{
+ u32 temp_reg = 0;
+
+ SDPRINTK("%d, %d, %d, %d)\n\r", copy_permit, mv_psp,
+ copy_info, display_ratio);
+
+ switch (copy_permit) {
+
+ case SDO_525_COPY_PERMIT:
+ temp_reg = SDO_WORD2_CGMS525_COPY_PERMIT;
+ break;
+
+ case SDO_525_ONECOPY_PERMIT:
+ temp_reg = SDO_WORD2_CGMS525_ONECOPY_PERMIT;
+ break;
+
+ case SDO_525_NOCOPY_PERMIT:
+ temp_reg = SDO_WORD2_CGMS525_NOCOPY_PERMIT;
+ break;
+
+ default:
+ SDPRINTK("invalid copy_permit parameter(%d)\n\r", copy_permit);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ switch (mv_psp) {
+
+ case SDO_525_MV_PSP_OFF:
+ temp_reg |= SDO_WORD2_CGMS525_MV_PSP_OFF;
+ break;
+
+ case SDO_525_MV_PSP_ON_2LINE_BURST:
+ temp_reg |= SDO_WORD2_CGMS525_MV_PSP_ON_2LINE_BURST;
+ break;
+
+ case SDO_525_MV_PSP_ON_BURST_OFF:
+ temp_reg |= SDO_WORD2_CGMS525_MV_PSP_ON_BURST_OFF;
+ break;
+
+ case SDO_525_MV_PSP_ON_4LINE_BURST:
+ temp_reg |= SDO_WORD2_CGMS525_MV_PSP_ON_4LINE_BURST;
+ break;
+
+ default:
+ SDPRINTK(" invalid mv_psp parameter(%d)\n\r", mv_psp);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ switch (copy_info) {
+
+ case SDO_525_COPY_INFO:
+ temp_reg |= SDO_WORD1_CGMS525_COPY_INFO;
+ break;
+
+ case SDO_525_DEFAULT:
+ temp_reg |= SDO_WORD1_CGMS525_DEFAULT;
+ break;
+
+ default:
+ SDPRINTK("invalid copy_info parameter(%d)\n\r", copy_info);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ if (analog_on)
+ temp_reg |= SDO_WORD2_CGMS525_ANALOG_ON;
+ else
+ temp_reg |= SDO_WORD2_CGMS525_ANALOG_OFF;
+
+
+ switch (display_ratio) {
+
+ case SDO_525_COPY_PERMIT:
+ temp_reg |= SDO_WORD0_CGMS525_4_3_NORMAL;
+ break;
+
+ case SDO_525_ONECOPY_PERMIT:
+ temp_reg |= SDO_WORD0_CGMS525_16_9_ANAMORPIC;
+ break;
+
+ case SDO_525_NOCOPY_PERMIT:
+ temp_reg |= SDO_WORD0_CGMS525_4_3_LETTERBOX;
+ break;
+
+ default:
+ SDPRINTK(" invalid display_ratio parameter(%d)\n\r",
+ display_ratio);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ writel(temp_reg |
+ SDO_CRC_CGMS525(__s5p_sdout_init_wss_cgms_crc(temp_reg)),
+ sdout_base + S5P_SDO_CGMS525);
+
+ SDPRINTK(" 0x%08x)\n\r", readl(sdout_base + S5P_SDO_CGMS525));
+
+ return SDOUT_NO_ERROR;
+}
+
+enum s5p_tv_sd_err __s5p_sdout_init_cgmsa625_data(bool surround_sound,
+ bool copyright,
+ bool copy_protection,
+ bool text_subtitles,
+ enum s5p_sd_625_subtitles open_subtitles,
+ enum s5p_sd_625_camera_film camera_film,
+ enum s5p_sd_625_color_encoding color_encoding,
+ bool helper_signal,
+ enum s5p_sd_625_aspect_ratio display_ratio)
+{
+ u32 temp_reg = 0;
+
+ SDPRINTK("%d, %d, %d, %d, %d, %d, %d, %d, %d)\n\r",
+ surround_sound, copyright, copy_protection,
+ text_subtitles, open_subtitles, camera_film,
+ color_encoding, helper_signal, display_ratio);
+
+ if (surround_sound)
+ temp_reg = SDO_CGMS625_SURROUND_SOUND_ENABLE;
+ else
+ temp_reg = SDO_CGMS625_SURROUND_SOUND_DISABLE;
+
+
+ if (copyright)
+ temp_reg |= SDO_CGMS625_COPYRIGHT;
+ else
+ temp_reg |= SDO_CGMS625_NO_COPYRIGHT;
+
+
+ if (copy_protection)
+ temp_reg |= SDO_CGMS625_COPY_RESTRICTED;
+ else
+ temp_reg |= SDO_CGMS625_COPY_NOT_RESTRICTED;
+
+
+ if (text_subtitles)
+ temp_reg |= SDO_CGMS625_TELETEXT_SUBTITLES;
+ else
+ temp_reg |= SDO_CGMS625_TELETEXT_NO_SUBTITLES;
+
+ switch (open_subtitles) {
+
+ case SDO_625_NO_OPEN_SUBTITLES:
+ temp_reg |= SDO_CGMS625_NO_OPEN_SUBTITLES;
+ break;
+
+ case SDO_625_INACT_OPEN_SUBTITLES:
+ temp_reg |= SDO_CGMS625_INACT_OPEN_SUBTITLES;
+ break;
+
+ case SDO_625_OUTACT_OPEN_SUBTITLES:
+ temp_reg |= SDO_CGMS625_OUTACT_OPEN_SUBTITLES;
+ break;
+
+ default:
+ SDPRINTK("invalid open_subtitles parameter(%d)\n\r",
+ open_subtitles);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ switch (camera_film) {
+
+ case SDO_625_CAMERA:
+ temp_reg |= SDO_CGMS625_CAMERA;
+ break;
+
+ case SDO_625_FILM:
+ temp_reg |= SDO_CGMS625_FILM;
+ break;
+
+ default:
+ SDPRINTK(" invalid camera_film parameter(%d)\n\r",
+ camera_film);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ switch (color_encoding) {
+
+ case SDO_625_NORMAL_PAL:
+ temp_reg |= SDO_CGMS625_NORMAL_PAL;
+ break;
+
+ case SDO_625_MOTION_ADAPTIVE_COLORPLUS:
+ temp_reg |= SDO_CGMS625_MOTION_ADAPTIVE_COLORPLUS;
+ break;
+
+ default:
+ SDPRINTK(" invalid color_encoding parameter(%d)\n\r",
+ color_encoding);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ if (helper_signal)
+ temp_reg |= SDO_CGMS625_HELPER_SIG;
+ else
+ temp_reg |= SDO_CGMS625_HELPER_NO_SIG;
+
+
+ switch (display_ratio) {
+
+ case SDO_625_4_3_FULL_576:
+ temp_reg |= SDO_CGMS625_4_3_FULL_576;
+ break;
+
+ case SDO_625_14_9_LETTERBOX_CENTER_504:
+ temp_reg |= SDO_CGMS625_14_9_LETTERBOX_CENTER_504;
+ break;
+
+ case SDO_625_14_9_LETTERBOX_TOP_504:
+ temp_reg |= SDO_CGMS625_14_9_LETTERBOX_TOP_504;
+ break;
+
+ case SDO_625_16_9_LETTERBOX_CENTER_430:
+ temp_reg |= SDO_CGMS625_16_9_LETTERBOX_CENTER_430;
+ break;
+
+ case SDO_625_16_9_LETTERBOX_TOP_430:
+ temp_reg |= SDO_CGMS625_16_9_LETTERBOX_TOP_430;
+ break;
+
+ case SDO_625_16_9_LETTERBOX_CENTER:
+ temp_reg |= SDO_CGMS625_16_9_LETTERBOX_CENTER;
+ break;
+
+ case SDO_625_14_9_FULL_CENTER_576:
+ temp_reg |= SDO_CGMS625_14_9_FULL_CENTER_576;
+ break;
+
+ case SDO_625_16_9_ANAMORPIC_576:
+ temp_reg |= SDO_CGMS625_16_9_ANAMORPIC_576;
+ break;
+
+ default:
+ SDPRINTK("invalid display_ratio parameter(%d)\n\r",
+ display_ratio);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ writel(temp_reg, sdout_base + S5P_SDO_CGMS625);
+
+ SDPRINTK("0x%08x\n\r", readl(sdout_base + S5P_SDO_CGMS625));
+
+ return SDOUT_NO_ERROR;
+}
+
+
+static enum s5p_tv_sd_err __s5p_sdout_init_antialias_filter_coeff_default(
+ enum s5p_sd_level composite_level,
+ enum s5p_sd_vsync_ratio composite_ratio,
+ enum s5p_tv_o_mode out_mode)
+{
+ SDPRINTK("%d, %d, %d\n\r", composite_level, composite_ratio, out_mode);
+
+ switch (composite_level) {
+
+ case S5P_TV_SD_LEVEL_0IRE:
+
+ switch (composite_ratio) {
+
+ case SDOUT_VTOS_RATIO_10_4:
+
+ switch (out_mode) {
+
+ case TVOUT_OUTPUT_COMPOSITE:
+
+ case TVOUT_OUTPUT_SVIDEO:
+ writel(0x00000000 , sdout_base + S5P_SDO_Y3);
+ writel(0x00000000 , sdout_base + S5P_SDO_Y4);
+ writel(0x00000000 , sdout_base + S5P_SDO_Y5);
+ writel(0x00000000 , sdout_base + S5P_SDO_Y6);
+ writel(0x00000000 , sdout_base + S5P_SDO_Y7);
+ writel(0x00000000 , sdout_base + S5P_SDO_Y8);
+ writel(0x00000000 , sdout_base + S5P_SDO_Y9);
+ writel(0x00000000 , sdout_base + S5P_SDO_Y10);
+ writel(0x0000029a , sdout_base + S5P_SDO_Y11);
+ writel(0x00000000 , sdout_base + S5P_SDO_CB0);
+ writel(0x00000000 , sdout_base + S5P_SDO_CB1);
+ writel(0x00000000 , sdout_base + S5P_SDO_CB2);
+ writel(0x00000000 , sdout_base + S5P_SDO_CB3);
+ writel(0x00000000 , sdout_base + S5P_SDO_CB4);
+ writel(0x00000001 , sdout_base + S5P_SDO_CB5);
+ writel(0x00000007 , sdout_base + S5P_SDO_CB6);
+ writel(0x00000015 , sdout_base + S5P_SDO_CB7);
+ writel(0x0000002b , sdout_base + S5P_SDO_CB8);
+ writel(0x00000045 , sdout_base + S5P_SDO_CB9);
+ writel(0x00000059 , sdout_base + S5P_SDO_CB10);
+ writel(0x00000061 , sdout_base + S5P_SDO_CB11);
+ writel(0x00000000 , sdout_base + S5P_SDO_CR1);
+ writel(0x00000000 , sdout_base + S5P_SDO_CR2);
+ writel(0x00000000 , sdout_base + S5P_SDO_CR3);
+ writel(0x00000000 , sdout_base + S5P_SDO_CR4);
+ writel(0x00000002 , sdout_base + S5P_SDO_CR5);
+ writel(0x0000000a , sdout_base + S5P_SDO_CR6);
+ writel(0x0000001e , sdout_base + S5P_SDO_CR7);
+ writel(0x0000003d , sdout_base + S5P_SDO_CR8);
+ writel(0x00000061 , sdout_base + S5P_SDO_CR9);
+ writel(0x0000007a , sdout_base + S5P_SDO_CR10);
+ writel(0x0000008f , sdout_base + S5P_SDO_CR11);
+ break;
+
+ case TVOUT_OUTPUT_COMPONENT_YPBPR_INERLACED:
+
+ case TVOUT_OUTPUT_COMPONENT_YPBPR_PROGRESSIVE:
+
+ case TVOUT_OUTPUT_COMPONENT_RGB_PROGRESSIVE:
+ writel(0x00000000, sdout_base + S5P_SDO_Y0);
+ writel(0x00000000, sdout_base + S5P_SDO_Y1);
+ writel(0x00000000, sdout_base + S5P_SDO_Y2);
+ writel(0x00000000, sdout_base + S5P_SDO_Y3);
+ writel(0x00000000, sdout_base + S5P_SDO_Y4);
+ writel(0x00000000, sdout_base + S5P_SDO_Y5);
+ writel(0x00000000, sdout_base + S5P_SDO_Y6);
+ writel(0x00000000, sdout_base + S5P_SDO_Y7);
+ writel(0x00000000, sdout_base + S5P_SDO_Y8);
+ writel(0x00000000, sdout_base + S5P_SDO_Y9);
+ writel(0x00000000, sdout_base + S5P_SDO_Y10);
+ writel(0x0000029a, sdout_base + S5P_SDO_Y11);
+ writel(0x00000000, sdout_base + S5P_SDO_CB0);
+ writel(0x00000000, sdout_base + S5P_SDO_CB1);
+ writel(0x00000000, sdout_base + S5P_SDO_CB2);
+ writel(0x00000000, sdout_base + S5P_SDO_CB3);
+ writel(0x00000000, sdout_base + S5P_SDO_CB4);
+ writel(0x00000001, sdout_base + S5P_SDO_CB5);
+ writel(0x00000007, sdout_base + S5P_SDO_CB6);
+ writel(0x00000015, sdout_base + S5P_SDO_CB7);
+ writel(0x0000002b, sdout_base + S5P_SDO_CB8);
+ writel(0x00000045, sdout_base + S5P_SDO_CB9);
+ writel(0x00000059, sdout_base + S5P_SDO_CB10);
+ writel(0x00000061, sdout_base + S5P_SDO_CB11);
+ writel(0x00000000, sdout_base + S5P_SDO_CR1);
+ writel(0x00000000, sdout_base + S5P_SDO_CR2);
+ writel(0x00000000, sdout_base + S5P_SDO_CR3);
+ writel(0x00000000, sdout_base + S5P_SDO_CR4);
+ writel(0x00000002, sdout_base + S5P_SDO_CR5);
+ writel(0x0000000a, sdout_base + S5P_SDO_CR6);
+ writel(0x0000001e, sdout_base + S5P_SDO_CR7);
+ writel(0x0000003d, sdout_base + S5P_SDO_CR8);
+ writel(0x00000061, sdout_base + S5P_SDO_CR9);
+ writel(0x0000007a, sdout_base + S5P_SDO_CR10);
+ writel(0x0000008f, sdout_base + S5P_SDO_CR11);
+ break;
+
+ default:
+ SDPRINTK("invalid out_mode parameter(%d)\n\r",
+ out_mode);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ break;
+
+ case SDOUT_VTOS_RATIO_7_3:
+ writel(0x00000000, sdout_base + S5P_SDO_Y0);
+ writel(0x00000000, sdout_base + S5P_SDO_Y1);
+ writel(0x00000000, sdout_base + S5P_SDO_Y2);
+ writel(0x00000000, sdout_base + S5P_SDO_Y3);
+ writel(0x00000000, sdout_base + S5P_SDO_Y4);
+ writel(0x00000000, sdout_base + S5P_SDO_Y5);
+ writel(0x00000000, sdout_base + S5P_SDO_Y6);
+ writel(0x00000000, sdout_base + S5P_SDO_Y7);
+ writel(0x00000000, sdout_base + S5P_SDO_Y8);
+ writel(0x00000000, sdout_base + S5P_SDO_Y9);
+ writel(0x00000000, sdout_base + S5P_SDO_Y10);
+ writel(0x00000281, sdout_base + S5P_SDO_Y11);
+ writel(0x00000000, sdout_base + S5P_SDO_CB0);
+ writel(0x00000000, sdout_base + S5P_SDO_CB1);
+ writel(0x00000000, sdout_base + S5P_SDO_CB2);
+ writel(0x00000000, sdout_base + S5P_SDO_CB3);
+ writel(0x00000000, sdout_base + S5P_SDO_CB4);
+ writel(0x00000001, sdout_base + S5P_SDO_CB5);
+ writel(0x00000007, sdout_base + S5P_SDO_CB6);
+ writel(0x00000015, sdout_base + S5P_SDO_CB7);
+ writel(0x0000002a, sdout_base + S5P_SDO_CB8);
+ writel(0x00000044, sdout_base + S5P_SDO_CB9);
+ writel(0x00000057, sdout_base + S5P_SDO_CB10);
+ writel(0x0000005f, sdout_base + S5P_SDO_CB11);
+ writel(0x00000000, sdout_base + S5P_SDO_CR1);
+ writel(0x00000000, sdout_base + S5P_SDO_CR2);
+ writel(0x00000000, sdout_base + S5P_SDO_CR3);
+ writel(0x00000000, sdout_base + S5P_SDO_CR4);
+ writel(0x00000002, sdout_base + S5P_SDO_CR5);
+ writel(0x0000000a, sdout_base + S5P_SDO_CR6);
+ writel(0x0000001d, sdout_base + S5P_SDO_CR7);
+ writel(0x0000003c, sdout_base + S5P_SDO_CR8);
+ writel(0x0000005f, sdout_base + S5P_SDO_CR9);
+ writel(0x0000007b, sdout_base + S5P_SDO_CR10);
+ writel(0x00000086, sdout_base + S5P_SDO_CR11);
+ break;
+
+ default:
+ SDPRINTK("invalid composite_ratio parameter(%d)\n\r",
+ composite_ratio);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ break;
+
+ case S5P_TV_SD_LEVEL_75IRE:
+
+ switch (composite_ratio) {
+
+ case SDOUT_VTOS_RATIO_10_4:
+ writel(0x00000000, sdout_base + S5P_SDO_Y0);
+ writel(0x00000000, sdout_base + S5P_SDO_Y1);
+ writel(0x00000000, sdout_base + S5P_SDO_Y2);
+ writel(0x00000000, sdout_base + S5P_SDO_Y3);
+ writel(0x00000000, sdout_base + S5P_SDO_Y4);
+ writel(0x00000000, sdout_base + S5P_SDO_Y5);
+ writel(0x00000000, sdout_base + S5P_SDO_Y6);
+ writel(0x00000000, sdout_base + S5P_SDO_Y7);
+ writel(0x00000000, sdout_base + S5P_SDO_Y8);
+ writel(0x00000000, sdout_base + S5P_SDO_Y9);
+ writel(0x00000000, sdout_base + S5P_SDO_Y10);
+ writel(0x0000025d, sdout_base + S5P_SDO_Y11);
+ writel(0x00000000, sdout_base + S5P_SDO_CB0);
+ writel(0x00000000, sdout_base + S5P_SDO_CB1);
+ writel(0x00000000, sdout_base + S5P_SDO_CB2);
+ writel(0x00000000, sdout_base + S5P_SDO_CB3);
+ writel(0x00000000, sdout_base + S5P_SDO_CB4);
+ writel(0x00000001, sdout_base + S5P_SDO_CB5);
+ writel(0x00000007, sdout_base + S5P_SDO_CB6);
+ writel(0x00000014, sdout_base + S5P_SDO_CB7);
+ writel(0x00000028, sdout_base + S5P_SDO_CB8);
+ writel(0x0000003f, sdout_base + S5P_SDO_CB9);
+ writel(0x00000052, sdout_base + S5P_SDO_CB10);
+ writel(0x0000005a, sdout_base + S5P_SDO_CB11);
+ writel(0x00000000, sdout_base + S5P_SDO_CR1);
+ writel(0x00000000, sdout_base + S5P_SDO_CR2);
+ writel(0x00000000, sdout_base + S5P_SDO_CR3);
+ writel(0x00000000, sdout_base + S5P_SDO_CR4);
+ writel(0x00000001, sdout_base + S5P_SDO_CR5);
+ writel(0x00000009, sdout_base + S5P_SDO_CR6);
+ writel(0x0000001c, sdout_base + S5P_SDO_CR7);
+ writel(0x00000039, sdout_base + S5P_SDO_CR8);
+ writel(0x0000005a, sdout_base + S5P_SDO_CR9);
+ writel(0x00000074, sdout_base + S5P_SDO_CR10);
+ writel(0x0000007e, sdout_base + S5P_SDO_CR11);
+ break;
+
+ case SDOUT_VTOS_RATIO_7_3:
+ writel(0x00000000, sdout_base + S5P_SDO_Y0);
+ writel(0x00000000, sdout_base + S5P_SDO_Y1);
+ writel(0x00000000, sdout_base + S5P_SDO_Y2);
+ writel(0x00000000, sdout_base + S5P_SDO_Y3);
+ writel(0x00000000, sdout_base + S5P_SDO_Y4);
+ writel(0x00000000, sdout_base + S5P_SDO_Y5);
+ writel(0x00000000, sdout_base + S5P_SDO_Y6);
+ writel(0x00000000, sdout_base + S5P_SDO_Y7);
+ writel(0x00000000, sdout_base + S5P_SDO_Y8);
+ writel(0x00000000, sdout_base + S5P_SDO_Y9);
+ writel(0x00000000, sdout_base + S5P_SDO_Y10);
+ writel(0x00000251, sdout_base + S5P_SDO_Y11);
+ writel(0x00000000, sdout_base + S5P_SDO_CB0);
+ writel(0x00000000, sdout_base + S5P_SDO_CB1);
+ writel(0x00000000, sdout_base + S5P_SDO_CB2);
+ writel(0x00000000, sdout_base + S5P_SDO_CB3);
+ writel(0x00000000, sdout_base + S5P_SDO_CB4);
+ writel(0x00000001, sdout_base + S5P_SDO_CB5);
+ writel(0x00000006, sdout_base + S5P_SDO_CB6);
+ writel(0x00000013, sdout_base + S5P_SDO_CB7);
+ writel(0x00000028, sdout_base + S5P_SDO_CB8);
+ writel(0x0000003f, sdout_base + S5P_SDO_CB9);
+ writel(0x00000051, sdout_base + S5P_SDO_CB10);
+ writel(0x00000056, sdout_base + S5P_SDO_CB11);
+ writel(0x00000000, sdout_base + S5P_SDO_CR1);
+ writel(0x00000000, sdout_base + S5P_SDO_CR2);
+ writel(0x00000000, sdout_base + S5P_SDO_CR3);
+ writel(0x00000000, sdout_base + S5P_SDO_CR4);
+ writel(0x00000002, sdout_base + S5P_SDO_CR5);
+ writel(0x00000005, sdout_base + S5P_SDO_CR6);
+ writel(0x00000018, sdout_base + S5P_SDO_CR7);
+ writel(0x00000037, sdout_base + S5P_SDO_CR8);
+ writel(0x0000005A, sdout_base + S5P_SDO_CR9);
+ writel(0x00000076, sdout_base + S5P_SDO_CR10);
+ writel(0x0000007e, sdout_base + S5P_SDO_CR11);
+ break;
+
+ default:
+ SDPRINTK(" invalid composite_ratio parameter(%d)\n\r",
+ composite_ratio);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ break;
+
+ default:
+ SDPRINTK(" invalid composite_level parameter(%d)\n\r",
+ composite_level);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ SDPRINTK("()\n\r");
+
+ return SDOUT_NO_ERROR;
+
+}
+
+
+static enum s5p_tv_sd_err __s5p_sdout_init_oversampling_filter_coeff_default(
+ enum s5p_tv_o_mode out_mode)
+{
+ u32 temp_reg = 0;
+ u8 i;
+
+ SDPRINTK("%d\n\r", out_mode);
+
+ switch (out_mode) {
+
+ case TVOUT_OUTPUT_COMPOSITE:
+
+ case TVOUT_OUTPUT_SVIDEO:
+
+ case TVOUT_OUTPUT_COMPONENT_YPBPR_INERLACED:
+ temp_reg = (u32)(sdout_base + S5P_SDO_OSFC00_0);
+
+ for (i = 0; i < 3; i++) {
+ temp_reg = (u32)((i == 0) ?
+ sdout_base + S5P_SDO_OSFC00_0 :
+ (i == 1) ?
+ sdout_base + S5P_SDO_OSFC00_1 :
+ sdout_base + S5P_SDO_OSFC00_2);
+
+ writel(((-2&0xfff) << 0) | ((-3&0xfff) << 0),
+ temp_reg + 0);
+ writel(0,
+ temp_reg + 1);
+ writel((4 << 0) | (5 << 16),
+ temp_reg + 2);
+ writel(((-1&0xfff) << 0) | (0 << 16),
+ temp_reg + 3);
+ writel(((-6&0xfff) << 0) | ((-9&0xfff) << 16),
+ temp_reg + 4);
+ writel((1 << 0) | (0 << 16),
+ temp_reg + 5);
+ writel((10 << 0) | (14 << 16),
+ temp_reg + 6);
+ writel(((-1&0xfff) << 0) | (0 << 16),
+ temp_reg + 7);
+ writel(((-14&0xfff) << 0) | ((-20&0xfff) << 16),
+ temp_reg + 8);
+ writel((1 << 0) | (0 << 16),
+ temp_reg + 9);
+ writel((20 << 0) | (29 << 16),
+ temp_reg + 10);
+ writel(((-2&0xfff) << 0) | (0 << 16),
+ temp_reg + 11);
+ writel(((-28&0xfff) << 0) | ((-40&0xfff) << 16),
+ temp_reg + 12);
+ writel((2 << 0) | (0 << 16),
+ temp_reg + 13);
+ writel((40 << 0) | (56 << 16),
+ temp_reg + 14);
+ writel(((-3&0xfff) << 0) | (0 << 16),
+ temp_reg + 15);
+ writel(((-57&0xfff) << 0) | ((-80&0xfff) << 16),
+ temp_reg + 16);
+ writel((5 << 0) | (0 << 16),
+ temp_reg + 17);
+ writel((86 << 0) | (121 << 16),
+ temp_reg + 18);
+ writel(((-10&0xfff) << 0) | (0 << 16),
+ temp_reg + 19);
+ writel(((-154&0xfff) << 0) | ((-212&0xfff) << 16),
+ temp_reg + 20);
+ writel((27 << 0) | (0 << 16),
+ temp_reg + 21);
+ writel((613 << 0) | (651 << 16),
+ temp_reg + 22);
+ writel(((-308&0xfff) << 0) | (1024 << 16),
+ temp_reg + 23);
+ }
+
+ break;
+
+ default:
+ SDPRINTK("invalid out_mode parameter(%d)\n\r", out_mode);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ return SDOUT_NO_ERROR;
+}
+
+/*
+* initialization
+* - iniization functions are only called under stopping sdout
+*/
+enum s5p_tv_sd_err __s5p_sdout_init_display_mode(
+ enum s5p_tv_disp_mode disp_mode,
+ enum s5p_tv_o_mode out_mode,
+ enum s5p_sd_order order)
+{
+ u32 temp_reg = 0;
+
+ SDPRINTK(" %d, %d, %d\n\r", disp_mode, out_mode, order);
+
+ switch (disp_mode) {
+
+ case TVOUT_NTSC_M:
+ temp_reg |= SDO_NTSC_M;
+ __s5p_sdout_init_video_scale_cfg(S5P_TV_SD_LEVEL_0IRE,
+ SDOUT_VTOS_RATIO_7_3,
+ S5P_TV_SD_LEVEL_75IRE,
+ SDOUT_VTOS_RATIO_10_4);
+
+ __s5p_sdout_init_antialias_filter_coeff_default(
+ S5P_TV_SD_LEVEL_75IRE,
+ SDOUT_VTOS_RATIO_10_4,
+ out_mode);
+ break;
+
+ case TVOUT_PAL_BDGHI:
+ temp_reg |= SDO_PAL_BGHID;
+ __s5p_sdout_init_video_scale_cfg(S5P_TV_SD_LEVEL_0IRE,
+ SDOUT_VTOS_RATIO_7_3, S5P_TV_SD_LEVEL_0IRE,
+ SDOUT_VTOS_RATIO_7_3);
+
+ __s5p_sdout_init_antialias_filter_coeff_default(
+ S5P_TV_SD_LEVEL_0IRE,
+ SDOUT_VTOS_RATIO_7_3,
+ out_mode);
+ break;
+
+ case TVOUT_PAL_M:
+ temp_reg |= SDO_PAL_M;
+ __s5p_sdout_init_video_scale_cfg(S5P_TV_SD_LEVEL_0IRE,
+ SDOUT_VTOS_RATIO_7_3, S5P_TV_SD_LEVEL_0IRE,
+ SDOUT_VTOS_RATIO_7_3);
+
+ __s5p_sdout_init_antialias_filter_coeff_default(
+ S5P_TV_SD_LEVEL_0IRE,
+ SDOUT_VTOS_RATIO_7_3,
+ out_mode);
+ break;
+
+ case TVOUT_PAL_N:
+ temp_reg |= SDO_PAL_N;
+ __s5p_sdout_init_video_scale_cfg(S5P_TV_SD_LEVEL_0IRE,
+ SDOUT_VTOS_RATIO_7_3, S5P_TV_SD_LEVEL_0IRE,
+ SDOUT_VTOS_RATIO_7_3);
+
+ __s5p_sdout_init_antialias_filter_coeff_default(
+ S5P_TV_SD_LEVEL_75IRE,
+ SDOUT_VTOS_RATIO_10_4,
+ out_mode);
+ break;
+
+ case TVOUT_PAL_NC:
+ temp_reg |= SDO_PAL_NC;
+ __s5p_sdout_init_video_scale_cfg(S5P_TV_SD_LEVEL_0IRE,
+ SDOUT_VTOS_RATIO_7_3, S5P_TV_SD_LEVEL_0IRE,
+ SDOUT_VTOS_RATIO_7_3);
+
+ __s5p_sdout_init_antialias_filter_coeff_default(
+ S5P_TV_SD_LEVEL_0IRE,
+ DOUT_VTOS_RATIO_7_3,
+ ut_mode);
+ break;
+
+ case TVOUT_PAL_60:
+ temp_reg |= SDO_PAL_60;
+ __s5p_sdout_init_video_scale_cfg(S5P_TV_SD_LEVEL_0IRE,
+ SDOUT_VTOS_RATIO_7_3, S5P_TV_SD_LEVEL_0IRE,
+ SDOUT_VTOS_RATIO_7_3);
+ __s5p_sdout_init_antialias_filter_coeff_default(
+ S5P_TV_SD_LEVEL_0IRE,
+ SDOUT_VTOS_RATIO_7_3,
+ out_mode);
+ break;
+
+ case TVOUT_NTSC_443:
+ temp_reg |= SDO_NTSC_443;
+ __s5p_sdout_init_video_scale_cfg(S5P_TV_SD_LEVEL_0IRE,
+ SDOUT_VTOS_RATIO_7_3, S5P_TV_SD_LEVEL_75IRE,
+ SDOUT_VTOS_RATIO_10_4);
+ __s5p_sdout_init_antialias_filter_coeff_default(
+ S5P_TV_SD_LEVEL_75IRE,
+ SDOUT_VTOS_RATIO_10_4,
+ out_mode);
+ break;
+
+ default:
+ SDPRINTK("invalid disp_mode parameter(%d)\n\r", disp_mode);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ switch (out_mode) {
+
+ case TVOUT_OUTPUT_COMPOSITE:
+
+ case TVOUT_OUTPUT_SVIDEO:
+ temp_reg |= SDO_COMPOSITE | SDO_INTERLACED;
+
+ switch (order) {
+
+ case S5P_TV_SD_O_ORDER_COMPOSITE_CVBS_Y_C:
+ temp_reg |= SDO_DAC2_CVBS | SDO_DAC1_Y | SDO_DAC0_C;
+ break;
+
+ case S5P_TV_SD_O_ORDER_COMPOSITE_CVBS_C_Y:
+ temp_reg |= SDO_DAC2_CVBS | SDO_DAC1_C | SDO_DAC0_Y;
+ break;
+
+ case S5P_TV_SD_O_ORDER_COMPOSITE_Y_C_CVBS:
+ temp_reg |= SDO_DAC2_Y | SDO_DAC1_C | SDO_DAC0_CVBS;
+ break;
+
+ case S5P_TV_SD_O_ORDER_COMPOSITE_Y_CVBS_C:
+ temp_reg |= SDO_DAC2_Y | SDO_DAC1_CVBS | SDO_DAC0_C;
+ break;
+
+ case S5P_TV_SD_O_ORDER_COMPOSITE_C_CVBS_Y:
+ temp_reg |= SDO_DAC2_C | SDO_DAC1_CVBS | SDO_DAC0_Y;
+ break;
+
+ case S5P_TV_SD_O_ORDER_COMPOSITE_C_Y_CVBS:
+ temp_reg |= SDO_DAC2_C | SDO_DAC1_Y | SDO_DAC0_CVBS;
+ break;
+
+ default:
+ SDPRINTK(" invalid order parameter(%d)\n\r", order);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ break;
+
+ case TVOUT_OUTPUT_COMPONENT_YPBPR_INERLACED:
+ temp_reg |= SDO_COMPONENT | SDO_YPBPR | SDO_INTERLACED;
+
+ switch (order) {
+
+ case S5P_TV_SD_O_ORDER_COMPONENT_RGB_PRYPB:
+ temp_reg |= SDO_DAC2_PR_R | SDO_DAC1_Y_G |
+ SDO_DAC0_PB_B;
+ break;
+
+ case S5P_TV_SD_O_ORDER_COMPONENT_RBG_PRPBY:
+ temp_reg |= SDO_DAC2_PR_R | SDO_DAC1_PB_B |
+ SDO_DAC0_Y_G;
+ break;
+
+ case S5P_TV_SD_O_ORDER_COMPONENT_BGR_PBYPR:
+ temp_reg |= SDO_DAC2_PB_B | SDO_DAC1_Y_G |
+ SDO_DAC0_PR_R;
+ break;
+
+ case S5P_TV_SD_O_ORDER_COMPONENT_BRG_PBPRY:
+ temp_reg |= SDO_DAC2_PB_B | SDO_DAC1_PR_R |
+ SDO_DAC0_Y_G;
+ break;
+
+ case S5P_TV_SD_O_ORDER_COMPONENT_GRB_YPRPB:
+ temp_reg |= SDO_DAC2_Y_G | SDO_DAC1_PR_R |
+ SDO_DAC0_PB_B;
+ break;
+
+ case S5P_TV_SD_O_ORDER_COMPONENT_GBR_YPBPR:
+ temp_reg |= SDO_DAC2_Y_G | SDO_DAC1_PB_B |
+ SDO_DAC0_PR_R;
+ break;
+
+ default:
+ SDPRINTK(" invalid order parameter(%d)\n\r", order);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ break;
+
+ case TVOUT_OUTPUT_COMPONENT_YPBPR_PROGRESSIVE:
+ temp_reg |= SDO_COMPONENT | SDO_YPBPR | SDO_PROGRESSIVE;
+
+ switch (order) {
+
+ case S5P_TV_SD_O_ORDER_COMPONENT_RGB_PRYPB:
+ temp_reg |= SDO_DAC2_PR_R | SDO_DAC1_Y_G |
+ SDO_DAC0_PB_B;
+ break;
+
+ case S5P_TV_SD_O_ORDER_COMPONENT_RBG_PRPBY:
+ temp_reg |= SDO_DAC2_PR_R | SDO_DAC1_PB_B |
+ SDO_DAC0_Y_G;
+ break;
+
+ case S5P_TV_SD_O_ORDER_COMPONENT_BGR_PBYPR:
+ temp_reg |= SDO_DAC2_PB_B | SDO_DAC1_Y_G |
+ SDO_DAC0_PR_R;
+ break;
+
+ case S5P_TV_SD_O_ORDER_COMPONENT_BRG_PBPRY:
+ temp_reg |= SDO_DAC2_PB_B | SDO_DAC1_PR_R |
+ SDO_DAC0_Y_G;
+ break;
+
+ case S5P_TV_SD_O_ORDER_COMPONENT_GRB_YPRPB:
+ temp_reg |= SDO_DAC2_Y_G | SDO_DAC1_PR_R |
+ SDO_DAC0_PB_B;
+ break;
+
+ case S5P_TV_SD_O_ORDER_COMPONENT_GBR_YPBPR:
+ temp_reg |= SDO_DAC2_Y_G | SDO_DAC1_PB_B |
+ SDO_DAC0_PR_R;
+ break;
+
+ default:
+ SDPRINTK(" invalid order parameter(%d)\n\r", order);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ break;
+
+ case TVOUT_OUTPUT_COMPONENT_RGB_PROGRESSIVE:
+ temp_reg |= SDO_COMPONENT | SDO_RGB | SDO_PROGRESSIVE;
+
+ switch (order) {
+
+ case S5P_TV_SD_O_ORDER_COMPONENT_RGB_PRYPB:
+ temp_reg |= SDO_DAC2_PR_R | SDO_DAC1_Y_G |
+ SDO_DAC0_PB_B;
+ break;
+
+ case S5P_TV_SD_O_ORDER_COMPONENT_RBG_PRPBY:
+ temp_reg |= SDO_DAC2_PR_R | SDO_DAC1_PB_B |
+ SDO_DAC0_Y_G;
+ break;
+
+ case S5P_TV_SD_O_ORDER_COMPONENT_BGR_PBYPR:
+ temp_reg |= SDO_DAC2_PB_B | SDO_DAC1_Y_G |
+ SDO_DAC0_PR_R;
+ break;
+
+ case S5P_TV_SD_O_ORDER_COMPONENT_BRG_PBPRY:
+ temp_reg |= SDO_DAC2_PB_B | SDO_DAC1_PR_R |
+ SDO_DAC0_Y_G;
+ break;
+
+ case S5P_TV_SD_O_ORDER_COMPONENT_GRB_YPRPB:
+ temp_reg |= SDO_DAC2_Y_G | SDO_DAC1_PR_R |
+ SDO_DAC0_PB_B;
+ break;
+
+ case S5P_TV_SD_O_ORDER_COMPONENT_GBR_YPBPR:
+ temp_reg |= SDO_DAC2_Y_G | SDO_DAC1_PB_B |
+ SDO_DAC0_PR_R;
+ break;
+
+ default:
+ SDPRINTK("invalid order parameter(%d)\n\r", order);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ break;
+
+ default:
+ SDPRINTK(" invalid out_mode parameter(%d)\n\r", out_mode);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ __s5p_sdout_init_oversampling_filter_coeff_default(out_mode);
+
+ writel(temp_reg, sdout_base + S5P_SDO_CONFIG);
+
+ SDPRINTK("0x%08x\n\r", readl(sdout_base + S5P_SDO_CONFIG));
+
+ return SDOUT_NO_ERROR;
+}
+
+/*
+* start - start functions are only called under stopping SDOUT
+*/
+void __s5p_sdout_start(void)
+{
+ SDPRINTK("()\n\r");
+
+ writel(SDO_TVOUT_CLOCK_ON, sdout_base + S5P_SDO_CLKCON);
+
+ SDPRINTK("0x%x\n\r", readl(sdout_base + S5P_SDO_CLKCON));
+}
+
+/*
+/ stop - stop functions are only called under running SDOUT
+*/
+void __s5p_sdout_stop(void)
+{
+ SDPRINTK("()\n\r");
+
+ writel(SDO_TVOUT_CLOCK_OFF, sdout_base + S5P_SDO_CLKCON);
+
+ SDPRINTK(" 0x%x)\n\r", readl(sdout_base + S5P_SDO_CLKCON));
+}
+
+/*
+* reset
+* - reset function
+*/
+void __s5p_sdout_sw_reset(bool active)
+{
+ SDPRINTK("%d\n\r", active);
+
+ if (active)
+ writel(readl(sdout_base + S5P_SDO_CLKCON) | SDO_TVOUT_SW_RESET,
+ sdout_base + S5P_SDO_CLKCON);
+ else
+ writel(readl(sdout_base + S5P_SDO_CLKCON) & ~SDO_TVOUT_SW_RESET,
+ sdout_base + S5P_SDO_CLKCON);
+
+ SDPRINTK(" 0x%x\n\r", readl(sdout_base + S5P_SDO_CLKCON));
+}
+
+
+void __s5p_sdout_set_interrupt_enable(bool vsync_intr_en)
+{
+ SDPRINTK("%d)\n\r", vsync_intr_en);
+
+ if (vsync_intr_en)
+ writel(readl(sdout_base + S5P_SDO_IRQMASK) &
+ ~SDO_VSYNC_IRQ_DISABLE,
+ sdout_base + S5P_SDO_IRQMASK);
+ else
+ writel(readl(sdout_base + S5P_SDO_IRQMASK) |
+ SDO_VSYNC_IRQ_DISABLE,
+ sdout_base + S5P_SDO_IRQMASK);
+
+ SDPRINTK("0x%x)\n\r", readl(sdout_base + S5P_SDO_IRQMASK));
+}
+
+void __s5p_sdout_clear_interrupt_pending(void)
+{
+ SDPRINTK("0x%x\n\r", readl(sdout_base + S5P_SDO_IRQ));
+
+ writel(readl(sdout_base + S5P_SDO_IRQ) | SDO_VSYNC_IRQ_PEND,
+ sdout_base + S5P_SDO_IRQ);
+
+ SDPRINTK("0x%x\n\r", readl(sdout_base + S5P_SDO_IRQ));
+}
+
+bool __s5p_sdout_get_interrupt_pending(void)
+{
+ SDPRINTK(" 0x%x\n\r", readl(sdout_base + S5P_SDO_IRQ));
+
+ return (readl(sdout_base + S5P_SDO_IRQ) |
+ SDO_VSYNC_IRQ_PEND) ? 1 : 0;
+}
+
+int __init __s5p_sdout_probe(struct platform_device *pdev, u32 res_num)
+{
+
+ struct resource *res;
+ size_t size;
+ int ret;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, res_num);
+
+ if (res == NULL) {
+ dev_err(&pdev->dev,
+ "failed to get memory region resource\n");
+ ret = -ENOENT;
+ }
+
+ size = (res->end - res->start) + 1;
+
+ sdout_mem = request_mem_region(res->start, size, pdev->name);
+
+ if (sdout_mem == NULL) {
+ dev_err(&pdev->dev,
+ "failed to get memory region\n");
+ ret = -ENOENT;
+ }
+
+ sdout_base = ioremap(res->start, size);
+
+ if (sdout_base == NULL) {
+ dev_err(&pdev->dev,
+ "failed to ioremap address region\n");
+ ret = -ENOENT;
+
+ }
+
+ return ret;
+
+}
+
+int __init __s5p_sdout_release(struct platform_device *pdev)
+{
+ iounmap(sdout_base);
+
+ /* remove memory region */
+
+ if (sdout_mem != NULL) {
+ if (release_resource(sdout_mem))
+ dev_err(&pdev->dev,
+ "Can't remove tvout drv !!\n");
+
+ kfree(sdout_mem);
+
+ sdout_mem = NULL;
+ }
+
+ return 0;
+}
diff --git a/drivers/media/video/samsung/tv20/s5pc100/tv_clock_s5pc100.c b/drivers/media/video/samsung/tv20/s5pc100/tv_clock_s5pc100.c
new file mode 100644
index 0000000..63f565a
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/s5pc100/tv_clock_s5pc100.c
@@ -0,0 +1,406 @@
+/* linux/drivers/media/video/samsung/tv20/s5pc100/tv_clock_s5pc100.c
+ *
+ * clock raw ftn file for Samsung TVOut driver
+ *
+ * Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+
+#include <linux/uaccess.h>
+#include <linux/io.h>
+
+#include <plat/map.h>
+#include <plat/regs-clock.h>
+
+#include "tv_out_s5pc100.h"
+#include "regs/regs-clock_extra.h"
+
+#ifdef COFIG_TVOUT_RAW_DBG
+#define S5P_TVOUT_CLK_DEBUG 1
+#endif
+
+#ifdef S5P_TVOUT_CLK_DEBUG
+#define TVCLKPRINTK(fmt, args...) \
+ printk(KERN_INFO "\t\t[TVCLK] %s: " fmt, __func__ , ## args)
+#else
+#define TVCLKPRINTK(fmt, args...)
+#endif
+
+static struct resource *tvclk_mem;
+void __iomem *tvclk_base;
+
+/*
+* initialization
+* - iniization functions are only called under stopping tvout clock
+*/
+
+void __s5p_tv_clk_init_hpll(unsigned int lock_time,
+ unsigned int mdiv,
+ unsigned int pdiv,
+ unsigned int sdiv)
+{
+ TVCLKPRINTK("%d,%d,%d,%d\n\r", lock_time, mdiv, pdiv, sdiv);
+
+ writel(HPLL_LOCKTIME(lock_time), S5P_HPLL_LOCK);
+ writel(MDIV(mdiv) | PDIV(pdiv) | SDIV(sdiv), S5P_HPLL_CON);
+
+ TVCLKPRINTK("0x%08x,0x%08x\n\r", readl(S5P_HPLL_LOCK),
+ readl(S5P_HPLL_CON));
+}
+
+void __s5p_tv_clk_hpll_onoff(bool en)
+{
+ TVCLKPRINTK("%d\n\r", en);
+
+ if (en) {
+ writel(readl(S5P_HPLL_CON) | HPLL_ENABLE, S5P_HPLL_CON) ;
+
+ while (!HPLL_LOCKED(readl(S5P_HPLL_CON)))
+ msleep(1);
+
+ } else
+ writel(readl(S5P_HPLL_CON) & ~HPLL_ENABLE, S5P_HPLL_CON);
+
+
+ TVCLKPRINTK("0x%08x,0x%08x\n\r", readl(S5P_HPLL_LOCK),
+ readl(S5P_HPLL_CON));
+}
+
+enum s5p_tv_clk_err __s5p_tv_clk_init_href(enum s5p_tv_clk_hpll_ref hpll_ref)
+{
+ TVCLKPRINTK("(%d)\n\r", hpll_ref);
+
+ switch (hpll_ref) {
+
+ case S5P_TV_CLK_HPLL_REF_27M:
+ writel(readl(S5P_CLK_SRC0) & HREF_SEL_MASK, S5P_CLK_SRC0);
+ break;
+
+ case S5P_TV_CLK_HPLL_REF_SRCLK:
+ writel(readl(S5P_CLK_SRC0) | HREF_SEL_SRCLK, S5P_CLK_SRC0);
+ break;
+
+ default:
+ TVCLKPRINTK("invalid hpll_ref parameter = %d\n\r", hpll_ref);
+ return S5P_TV_CLK_ERR_INVALID_PARAM;
+ break;
+ }
+
+ TVCLKPRINTK("(0x%08x)\n\r", readl(S5P_CLK_SRC0));
+
+ return S5P_TV_CLK_ERR_NO_ERROR;
+}
+
+enum s5p_tv_clk_err __s5p_tv_clk_init_mout_hpll(
+ enum s5p_tv_clk_mout_hpll mout_hpll)
+{
+ TVCLKPRINTK("(%d)\n\r", mout_hpll);
+
+ switch (mout_hpll) {
+
+ case S5P_TV_CLK_MOUT_HPLL_27M:
+ writel(readl(S5P_CLK_SRC0) & HPLL_SEL_MASK, S5P_CLK_SRC0);
+ break;
+
+ case S5P_TV_CLK_MOUT_HPLL_FOUT_HPLL:
+ writel(readl(S5P_CLK_SRC0) | HPLL_SEL_FOUT_HPLL, S5P_CLK_SRC0);
+ break;
+
+ default:
+ TVCLKPRINTK(" invalid mout_hpll parameter = %d\n\r",
+ mout_hpll);
+ return S5P_TV_CLK_ERR_INVALID_PARAM;
+ break;
+ }
+
+ TVCLKPRINTK("(0x%08x)\n\r", readl(S5P_CLK_SRC0));
+
+ return S5P_TV_CLK_ERR_NO_ERROR;
+}
+
+enum s5p_tv_clk_err __s5p_tv_clk_init_video_mixer(
+ enum s5p_tv_clk_vmiexr_srcclk src_clk)
+{
+ TVCLKPRINTK("(%d)\n\r", src_clk);
+
+ switch (src_clk) {
+
+ case TVOUT_CLK_VMIXER_SRCCLK_CLK27M:
+ writel(((readl(S5P_CLK_SRC2) & VMIXER_SEL_MASK) |
+ VMIXER_SEL_CLK27M), S5P_CLK_SRC2);
+ break;
+
+ case TVOUT_CLK_VMIXER_SRCCLK_VCLK_54:
+ writel(((readl(S5P_CLK_SRC2) & VMIXER_SEL_MASK) |
+ VMIXER_SEL_VCLK_54), S5P_CLK_SRC2);
+ break;
+
+ case TVOUT_CLK_VMIXER_SRCCLK_MOUT_HPLL:
+ writel(((readl(S5P_CLK_SRC2) & VMIXER_SEL_MASK) |
+ VMIXER_SEL_MOUT_HPLL), S5P_CLK_SRC2);
+ break;
+
+ default:
+ TVCLKPRINTK("invalid src_clk parameter = %d\n\r", src_clk);
+ return S5P_TV_CLK_ERR_INVALID_PARAM;
+ break;
+ }
+
+ TVCLKPRINTK("(0x%08x)\n\r", readl(S5P_CLK_SRC2));
+
+ return S5P_TV_CLK_ERR_NO_ERROR;
+}
+
+void __s5p_tv_clk_init_hdmi_ratio(unsigned int clk_div)
+{
+ TVCLKPRINTK("(%d)\n\r", clk_div);
+
+ writel((readl(S5P_CLK_DIV3) & HDMI_DIV_RATIO_MASK) |
+ HDMI_DIV_RATIO(clk_div), S5P_CLK_DIV3);
+
+ TVCLKPRINTK("(0x%08x)\n\r", readl(S5P_CLK_DIV3));
+}
+
+/*
+* set
+* - set functions are only called under running tvout clock
+*/
+void __s5p_tv_clk_set_vp_clk_onoff(bool clk_on)
+{
+ TVCLKPRINTK("(%d)\n\r", clk_on);
+
+ if (clk_on)
+ writel(readl(S5P_CLKGATE_D12) | CLK_HCLK_VP_PASS,
+ S5P_CLKGATE_D12);
+ else
+ writel(readl(S5P_CLKGATE_D12) & ~CLK_HCLK_VP_PASS,
+ S5P_CLKGATE_D12);
+
+
+ TVCLKPRINTK("(0x%08x)\n\r", readl(S5P_CLKGATE_D12));
+}
+
+void __s5p_tv_clk_set_vmixer_hclk_onoff(bool clk_on)
+{
+ TVCLKPRINTK("(%d)\n\r", clk_on);
+
+ if (clk_on)
+ writel(readl(S5P_CLKGATE_D12) | CLK_HCLK_VMIXER_PASS,
+ S5P_CLKGATE_D12);
+ else
+ writel(readl(S5P_CLKGATE_D12) & ~CLK_HCLK_VMIXER_PASS,
+ S5P_CLKGATE_D12);
+
+
+ TVCLKPRINTK("(0x%08x)\n\r", readl(S5P_CLKGATE_D12));
+}
+
+void __s5p_tv_clk_set_vmixer_sclk_onoff(bool clk_on)
+{
+ TVCLKPRINTK("(%d)\n\r", clk_on);
+
+ if (clk_on)
+ writel(readl(S5P_SCLKGATE1) | CLK_SCLK_VMIXER_PASS,
+ S5P_SCLKGATE1);
+ else
+ writel(readl(S5P_SCLKGATE1) & ~CLK_SCLK_VMIXER_PASS,
+ S5P_SCLKGATE1);
+
+
+ TVCLKPRINTK("(0x%08x)\n\r", readl(S5P_SCLKGATE1));
+}
+
+void __s5p_tv_clk_set_sdout_hclk_onoff(bool clk_on)
+{
+ TVCLKPRINTK("(%d)\n\r", clk_on);
+
+ if (clk_on) {
+ writel((readl(S5P_CLKGATE_D12) | CLK_HCLK_SDOUT_PASS),
+ S5P_CLKGATE_D12);
+ writel(readl(tvclk_base + 0x304) | VMIXER_OUT_SEL_SDOUT,
+ tvclk_base + 0x304);
+ } else
+ writel((readl(S5P_CLKGATE_D12) & ~CLK_HCLK_SDOUT_PASS),
+ S5P_CLKGATE_D12);
+
+
+
+ TVCLKPRINTK("physical %p (0x%08x)\n\r", tvclk_base,
+ readl(tvclk_base + 0x304));
+
+ TVCLKPRINTK("after (0x%08x)\n\r", readl(S5P_CLKGATE_D12));
+}
+
+void __s5p_tv_clk_set_sdout_sclk_onoff(bool clk_on)
+{
+ TVCLKPRINTK("(%d)\n\r", clk_on);
+
+ if (clk_on)
+ writel((readl(S5P_SCLKGATE1) | CLK_SCLK_TV54_PASS |
+ CLK_SCLK_VDAC54_PASS),
+ S5P_SCLKGATE1);
+ else
+ writel((readl(S5P_SCLKGATE1) & (~CLK_SCLK_TV54_PASS &
+ ~CLK_SCLK_VDAC54_PASS)),
+ S5P_SCLKGATE1);
+
+
+ TVCLKPRINTK("(0x%08x)\n\r", readl(S5P_SCLKGATE1));
+}
+
+void __s5p_tv_clk_set_hdmi_hclk_onoff(bool clk_on)
+{
+ TVCLKPRINTK("(%d)\n\r", clk_on);
+
+ if (clk_on) {
+ writel((readl(S5P_CLKGATE_D12) | CLK_HCLK_HDMI_PASS),
+ S5P_CLKGATE_D12);
+ writel(readl(tvclk_base + 0x304) | VMIXER_OUT_SEL_HDMI,
+ tvclk_base + 0x304);
+ } else
+ writel((readl(S5P_CLKGATE_D12) & ~CLK_HCLK_HDMI_PASS),
+ S5P_CLKGATE_D12) ;
+
+
+ TVCLKPRINTK("physical %p (0x%08x)\n\r", tvclk_base,
+ readl(tvclk_base + 0x304));
+
+ TVCLKPRINTK("after (0x%08x)\n\r", readl(S5P_CLKGATE_D12));
+}
+
+void __s5p_tv_clk_set_hdmi_sclk_onoff(bool clk_on)
+{
+ TVCLKPRINTK("(%d)\n\r", clk_on);
+
+ if (clk_on)
+ writel((readl(S5P_SCLKGATE1) | CLK_SCLK_HDMI_PASS),
+ S5P_SCLKGATE1);
+ else
+ writel((readl(S5P_SCLKGATE1) & ~CLK_SCLK_HDMI_PASS),
+ S5P_SCLKGATE1);
+
+
+ TVCLKPRINTK("(0x%08x)\n\r", readl(S5P_SCLKGATE1));
+}
+
+void __s5p_tv_clk_set_hdmi_i2c_clk_onoff(bool clk_on)
+{
+ TVCLKPRINTK("(%d)\n\r", clk_on);
+
+ if (clk_on)
+ writel((readl(S5P_CLKGATE_D14) | CLK_PCLK_IIC_HDMI_PASS),
+ S5P_CLKGATE_D14);
+ else
+ writel((readl(S5P_CLKGATE_D14) & ~CLK_PCLK_IIC_HDMI_PASS),
+ S5P_CLKGATE_D14);
+
+
+ TVCLKPRINTK("(0x%08x)\n\r", readl(S5P_CLKGATE_D14));
+}
+
+/*
+* start
+* - start functions are only called under stopping tvout clock
+*/
+void __s5p_tv_clk_start(bool vp_hclk_on,
+ bool sdout_hclk_on,
+ bool hdmi_hclk_on)
+{
+ TVCLKPRINTK("(%d,%d,%d)\n\r", vp_hclk_on, sdout_hclk_on, hdmi_hclk_on);
+
+ __s5p_tv_clk_set_vp_clk_onoff(vp_hclk_on);
+ __s5p_tv_clk_set_sdout_hclk_onoff(sdout_hclk_on);
+ __s5p_tv_clk_set_sdout_sclk_onoff(sdout_hclk_on);
+ __s5p_tv_clk_set_hdmi_hclk_onoff(hdmi_hclk_on);
+ __s5p_tv_clk_set_vmixer_hclk_onoff(true);
+ __s5p_tv_clk_set_vmixer_sclk_onoff(true);
+
+ if (hdmi_hclk_on)
+ __s5p_tv_clk_hpll_onoff(true);
+
+}
+
+
+/*
+* stop
+* - stop functions are only called under running tvout clock
+*/
+void __s5p_tv_clk_stop(void)
+{
+ __s5p_tv_clk_set_sdout_sclk_onoff(false);
+ __s5p_tv_clk_set_sdout_hclk_onoff(false);
+ __s5p_tv_clk_set_hdmi_sclk_onoff(false);
+ __s5p_tv_clk_set_hdmi_hclk_onoff(false);
+ __s5p_tv_clk_set_vp_clk_onoff(false);
+ __s5p_tv_clk_set_vmixer_sclk_onoff(false);
+ __s5p_tv_clk_set_vmixer_hclk_onoff(false);
+ __s5p_tv_clk_hpll_onoff(false);
+}
+
+int __init __s5p_tvclk_probe(struct platform_device *pdev, u32 res_num)
+{
+
+ struct resource *res;
+ size_t size;
+ int ret;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, res_num);
+
+ if (res == NULL) {
+ dev_err(&pdev->dev,
+ "failed to get memory region resource\n");
+ ret = -ENOENT;
+
+ }
+
+ size = (res->end - res->start) + 1;
+
+ tvclk_mem = request_mem_region(res->start, size, pdev->name);
+
+ if (tvclk_mem == NULL) {
+ dev_err(&pdev->dev,
+ "failed to get memory region\n");
+ ret = -ENOENT;
+
+ }
+
+ tvclk_base = ioremap(res->start, size);
+
+ if (tvclk_base == NULL) {
+ dev_err(&pdev->dev,
+ "failed to ioremap address region\n");
+ ret = -ENOENT;
+
+ }
+
+ return ret;
+}
+
+int __init __s5p_tvclk_release(struct platform_device *pdev)
+{
+ iounmap(tvclk_base);
+
+ /* remove memory region */
+
+ if (tvclk_mem != NULL) {
+ if (release_resource(tvclk_mem))
+ dev_err(&pdev->dev,
+ "Can't remove tvout drv !!\n");
+
+ kfree(tvclk_mem);
+
+ tvclk_mem = NULL;
+ }
+
+ return 0;
+}
diff --git a/drivers/media/video/samsung/tv20/s5pc100/tv_out_s5pc100.h b/drivers/media/video/samsung/tv20/s5pc100/tv_out_s5pc100.h
new file mode 100644
index 0000000..19349be
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/s5pc100/tv_out_s5pc100.h
@@ -0,0 +1,486 @@
+/* linux/drivers/media/video/samsung/tv20/s5pc100/tv_out_s5pc100.h
+ *
+ * tv out header file for Samsung TVOut driver
+ *
+ * Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+/*#define COFIG_TVOUT_RAW_DBG */
+
+
+#define HDMI_START_NUM 0x1000
+
+enum s5p_tv_audio_codec_type {
+ PCM = 1, AC3, MP3, WMA
+};
+
+enum s5p_endian_type {
+ TVOUT_LITTLE_ENDIAN_MODE = 0,
+ TVOUT_BIG_ENDIAN_MODE = 1
+};
+
+enum s5p_tv_disp_mode {
+ TVOUT_NTSC_M = 0,
+ TVOUT_PAL_BDGHI,
+ TVOUT_PAL_M,
+ TVOUT_PAL_N,
+ TVOUT_PAL_NC,
+ TVOUT_PAL_60,
+ TVOUT_NTSC_443,
+ TVOUT_480P_60_16_9 = HDMI_START_NUM,
+ TVOUT_480P_60_4_3,
+ TVOUT_576P_50_16_9,
+ TVOUT_576P_50_4_3,
+ TVOUT_720P_60,
+ TVOUT_720P_50
+};
+
+enum s5p_tv_o_mode {
+ TVOUT_OUTPUT_COMPOSITE,
+ TVOUT_OUTPUT_SVIDEO,
+ TVOUT_OUTPUT_COMPONENT_YPBPR_INERLACED,
+ TVOUT_OUTPUT_COMPONENT_YPBPR_PROGRESSIVE,
+ TVOUT_OUTPUT_COMPONENT_RGB_PROGRESSIVE,
+ TVOUT_OUTPUT_HDMI,
+ TVOUT_OUTPUT_HDMI_RGB,
+ TVOUT_OUTPUT_DVI
+};
+
+enum s5p_tv_pwr_err {
+ S5P_TV_PWR_ERR_NO_ERROR = 0,
+ S5P_TV_PWR_ERR_NOT_INIT_PARAMETERS_UNDER_RUNNING = 0x5000,
+ S5P_TV_PWR_ERR_NOT_SET_PARAMETERS_UNDER_STOP,
+ S5P_TV_PWR_ERR_INVALID_PARAM
+};
+
+enum s5p_tv_clk_err {
+ S5P_TV_CLK_ERR_NO_ERROR = 0,
+ S5P_TV_CLK_ERR_NOT_INIT_PARAMETERS_UNDER_RUNNING = 0x4000,
+ S5P_TV_CLK_ERR_NOT_SET_PARAMETERS_UNDER_STOP,
+ S5P_TV_CLK_ERR_INVALID_PARAM
+};
+
+enum s5p_tv_vp_err {
+ VPROC_NO_ERROR = 0,
+ S5P_TV_VP_ERR_NOT_INIT_PARAMETERS_UNDER_RUNNING = 0x2000,
+ S5P_TV_VP_ERR_NOT_SET_PARAMETERS_UNDER_STOP,
+ S5P_TV_VP_ERR_BASE_ADDRESS_MUST_DOUBLE_WORD_ALIGN,
+ S5P_TV_VP_ERR_NOT_UPDATE_FOR_ANOTHER_UPDATE,
+ S5P_TV_VP_ERR_INVALID_PARAM
+};
+
+enum s5p_tv_vmx_err {
+ VMIXER_NO_ERROR = 0,
+ S5P_TV_VMX_ERR_NOT_INIT_PARAMETERS_UNDER_RUNNING = 0x1000,
+ S5P_TV_VMX_ERR_NOT_SET_PARAMETERS_UNDER_STOP,
+ S5P_TV_VMX_ERR_BASE_ADDRESS_MUST_WORD_ALIGN,
+ S5P_TV_VMX_ERR_INVALID_PARAM
+};
+
+enum s5p_tv_vmx_color_fmt {
+ VM_DIRECT_RGB565 = 4,
+ VM_DIRECT_RGB1555 = 5,
+ VM_DIRECT_RGB4444 = 6,
+ VM_DIRECT_RGB8888 = 7
+};
+
+enum s5p_tv_sd_err {
+ SDOUT_NO_ERROR = 0,
+ S5P_TV_SD_ERR_NOT_INIT_PARAMETERS_UNDER_RUNNING = 0x3000,
+ S5P_TV_SD_ERR_NOT_SET_PARAMETERS_UNDER_STOP,
+ S5P_TV_SD_ERR_INVALID_PARAM
+};
+
+enum s5p_sd_order {
+ S5P_TV_SD_O_ORDER_COMPONENT_RGB_PRYPB,
+ S5P_TV_SD_O_ORDER_COMPONENT_RBG_PRPBY,
+ S5P_TV_SD_O_ORDER_COMPONENT_BGR_PBYPR,
+ S5P_TV_SD_O_ORDER_COMPONENT_BRG_PBPRY,
+ S5P_TV_SD_O_ORDER_COMPONENT_GRB_YPRPB,
+ S5P_TV_SD_O_ORDER_COMPONENT_GBR_YPBPR,
+ S5P_TV_SD_O_ORDER_COMPOSITE_CVBS_Y_C,
+ S5P_TV_SD_O_ORDER_COMPOSITE_CVBS_C_Y,
+ S5P_TV_SD_O_ORDER_COMPOSITE_Y_C_CVBS,
+ S5P_TV_SD_O_ORDER_COMPOSITE_Y_CVBS_C,
+ S5P_TV_SD_O_ORDER_COMPOSITE_C_CVBS_Y,
+ S5P_TV_SD_O_ORDER_COMPOSITE_C_Y_CVBS
+};
+
+enum s5p_tv_hdmi_err {
+ HDMI_NO_ERROR = 0,
+ S5P_TV_HDMI_ERR_NOT_INIT_PARAMETERS_UNDER_RUNNING = 0x6000,
+ S5P_TV_HDMI_ERR_NOT_SET_PARAMETERS_UNDER_STOP,
+ S5P_TV_HDMI_ERR_INVALID_PARAM
+};
+
+enum s5p_hdmi_transmit {
+ HDMI_DO_NOT_TANS = 0,
+ HDMI_TRANS_ONCE,
+ HDMI_TRANS_EVERY_SYNC
+};
+
+enum s5p_hdmi_audio_type {
+ HDMI_AUDIO_NO,
+ HDMI_AUDIO_PCM
+};
+
+
+enum s5p_tv_stda_err {
+ STDA_NO_ERROR = 0,
+ S5P_TV_STDA_ERR_NOT_INIT_PARAMETERS_UNDER_RUNNING = 0x7000,
+ S5P_TV_STDA_ERR_NOT_SET_PARAMETERS_UNDER_STOP,
+ S5P_TV_STDA_ERR_INVALID_PARAM
+};
+
+
+/*
+* enum
+*/
+
+enum s5p_tv_active_polarity {
+ TVOUT_POL_ACTIVE_LOW,
+ TVOUT_POL_ACTIVE_HIGH
+};
+
+enum s5p_yuv_fmt_component {
+ TVOUT_YUV_Y,
+ TVOUT_YUV_CB,
+ TVOUT_YUV_CR
+};
+
+enum s5p_tv_clk_hpll_ref {
+ S5P_TV_CLK_HPLL_REF_27M,
+ S5P_TV_CLK_HPLL_REF_SRCLK
+};
+
+enum s5p_tv_clk_mout_hpll {
+ S5P_TV_CLK_MOUT_HPLL_27M,
+ S5P_TV_CLK_MOUT_HPLL_FOUT_HPLL
+};
+
+enum s5p_tv_clk_vmiexr_srcclk {
+ TVOUT_CLK_VMIXER_SRCCLK_CLK27M,
+ TVOUT_CLK_VMIXER_SRCCLK_VCLK_54,
+ TVOUT_CLK_VMIXER_SRCCLK_MOUT_HPLL
+};
+
+enum s5p_vp_src_color {
+ VPROC_SRC_COLOR_NV12 = 0,
+ VPROC_SRC_COLOR_NV12IW = 1,
+ VPROC_SRC_COLOR_TILE_NV12 = 2,
+ VPROC_SRC_COLOR_TILE_NV12IW = 3
+};
+
+enum s5p_vp_pxl_rate {
+ VPROC_PIXEL_PER_RATE_1_1 = 0,
+ VPROC_PIXEL_PER_RATE_1_2 = 1,
+ VPROC_PIXEL_PER_RATE_1_3 = 2,
+ VPROC_PIXEL_PER_RATE_1_4 = 3
+};
+
+enum s5p_vp_sharpness_control {
+ VPROC_SHARPNESS_NO = 0,
+ VPROC_SHARPNESS_MIN = 1,
+ VPROC_SHARPNESS_MOD = 2,
+ VPROC_SHARPNESS_MAX = 3
+};
+
+enum s5p_vp_line_eq {
+ VProc_LINE_EQ_0 = 0,
+ VProc_LINE_EQ_1 = 1,
+ VProc_LINE_EQ_2 = 2,
+ VProc_LINE_EQ_3 = 3,
+ VProc_LINE_EQ_4 = 4,
+ VProc_LINE_EQ_5 = 5,
+ VProc_LINE_EQ_6 = 6,
+ VProc_LINE_EQ_7 = 7
+};
+
+enum s5p_vp_mem_mode {
+ VPROC_LINEAR_MODE,
+ VPROC_2D_TILE_MODE
+};
+
+enum s5p_vp_chroma_expansion {
+ VPROC_USING_C_TOP,
+ VPROC_USING_C_TOP_BOTTOM
+};
+
+enum s5p_vp_filed_id_toggle {
+ S5P_TV_VP_FILED_ID_TOGGLE_USER,
+ S5P_TV_VP_FILED_ID_TOGGLE_VSYNC
+};
+
+enum s5p_vp_field {
+ VPROC_TOP_FIELD,
+ VPROC_BOTTOM_FIELD
+};
+
+enum s5p_vp_poly_coeff {
+ VPROC_POLY8_Y0_LL = 0,
+ VPROC_POLY8_Y0_LH,
+ VPROC_POLY8_Y0_HL,
+ VPROC_POLY8_Y0_HH,
+ VPROC_POLY8_Y1_LL,
+ VPROC_POLY8_Y1_LH,
+ VPROC_POLY8_Y1_HL,
+ VPROC_POLY8_Y1_HH,
+ VPROC_POLY8_Y2_LL,
+ VPROC_POLY8_Y2_LH,
+ VPROC_POLY8_Y2_HL,
+ VPROC_POLY8_Y2_HH,
+ VPROC_POLY8_Y3_LL,
+ VPROC_POLY8_Y3_LH,
+ VPROC_POLY8_Y3_HL,
+ VPROC_POLY8_Y3_HH,
+ VPROC_POLY4_Y0_LL = 32,
+ VPROC_POLY4_Y0_LH,
+ VPROC_POLY4_Y0_HL,
+ VPROC_POLY4_Y0_HH,
+ VPROC_POLY4_Y1_LL,
+ VPROC_POLY4_Y1_LH,
+ VPROC_POLY4_Y1_HL,
+ VPROC_POLY4_Y1_HH,
+ VPROC_POLY4_Y2_LL,
+ VPROC_POLY4_Y2_LH,
+ VPROC_POLY4_Y2_HL,
+ VPROC_POLY4_Y2_HH,
+ VPROC_POLY4_Y3_LL,
+ VPROC_POLY4_Y3_LH,
+ VPROC_POLY4_Y3_HL,
+ VPROC_POLY4_Y3_HH,
+ VPROC_POLY4_C0_LL,
+ VPROC_POLY4_C0_LH,
+ VPROC_POLY4_C0_HL,
+ VPROC_POLY4_C0_HH,
+ VPROC_POLY4_C1_LL,
+ VPROC_POLY4_C1_LH,
+ VPROC_POLY4_C1_HL,
+ VPROC_POLY4_C1_HH
+};
+
+enum s5p_vp_csc_coeff {
+ VPROC_CSC_Y2Y_COEF = 0,
+ VPROC_CSC_CB2Y_COEF,
+ VPROC_CSC_CR2Y_COEF,
+ VPROC_CSC_Y2CB_COEF,
+ VPROC_CSC_CB2CB_COEF,
+ VPROC_CSC_CR2CB_COEF,
+ VPROC_CSC_Y2CR_COEF,
+ VPROC_CSC_CB2CR_COEF,
+ VPROC_CSC_CR2CR_COEF
+};
+
+enum s5p_vp_csc_type {
+ VPROC_CSC_SD_HD,
+ VPROC_CSC_HD_SD
+};
+
+enum s5p_tv_vp_filter_h_pp {
+ /* Don't change the order and the value */
+ VPROC_PP_H_NORMAL = 0,
+ VPROC_PP_H_8_9, /* 720 to 640 */
+ VPROC_PP_H_1_2,
+ VPROC_PP_H_1_3,
+ VPROC_PP_H_1_4
+};
+
+enum s5p_tv_vp_filter_v_pp {
+ /* Don't change the order and the value */
+ VPROC_PP_V_NORMAL = 0,
+ VPROC_PP_V_5_6, /* PAL to NTSC */
+ VPROC_PP_V_3_4,
+ VPROC_PP_V_1_2,
+ VPROC_PP_V_1_3,
+ VPROC_PP_V_1_4
+};
+
+enum s5p_vmx_burst_mode {
+ VM_BURST_8 = 0,
+ VM_BURST_16 = 1
+};
+
+enum s5p_tv_vmx_scan_mode {
+ VMIXER_INTERLACED_MODE = 0,
+ VMIXER_PROGRESSIVE_MODE = 1
+};
+
+enum s5p_tv_vmx_layer {
+ VM_VIDEO_LAYER = 2,
+ VM_GPR0_LAYER = 0,
+ VM_GPR1_LAYER = 1
+};
+
+enum s5p_tv_vmx_bg_color_num {
+ VMIXER_BG_COLOR_0 = 0,
+ VMIXER_BG_COLOR_1 = 1,
+ VMIXER_BG_COLOR_2 = 2
+};
+
+enum s5p_tv_coef_y_mode {
+ VMIXER_COEF_Y_NARROW = 0,
+ VMIXER_COEF_Y_WIDE = 1
+};
+
+enum s5p_tv_vmx_csc_type {
+ VMIXER_CSC_RGB_TO_YUV601_LR,
+ VMIXER_CSC_RGB_TO_YUV601_FR,
+ VMIXER_CSC_RGB_TO_YUV709_LR,
+ VMIXER_CSC_RGB_TO_YUV709_FR
+};
+
+enum s5p_sd_level {
+ S5P_TV_SD_LEVEL_0IRE,
+ S5P_TV_SD_LEVEL_75IRE
+};
+
+enum s5p_sd_vsync_ratio {
+ SDOUT_VTOS_RATIO_10_4,
+ SDOUT_VTOS_RATIO_7_3
+};
+
+enum s5p_sd_sync_sig_pin {
+ SDOUT_SYNC_SIG_NO,
+ SDOUT_SYNC_SIG_YG,
+ SDOUT_SYNC_SIG_ALL
+};
+
+enum s5p_sd_closed_caption_type {
+ SDOUT_NO_INS,
+ SDOUT_INS_1,
+ SDOUT_INS_2,
+ SDOUT_INS_OTHERS
+};
+
+enum s5p_sd_channel_sel {
+ SDOUT_CHANNEL_0 = 0,
+ SDOUT_CHANNEL_1 = 1,
+ SDOUT_CHANNEL_2 = 2
+};
+
+enum s5p_sd_vesa_rgb_sync_type {
+ SDOUT_VESA_RGB_SYNC_COMPOSITE,
+ SDOUT_VESA_RGB_SYNC_SEPARATE
+};
+
+enum s5p_sd_525_copy_permit {
+ SDO_525_COPY_PERMIT,
+ SDO_525_ONECOPY_PERMIT,
+ SDO_525_NOCOPY_PERMIT
+};
+
+enum s5p_sd_525_mv_psp {
+ SDO_525_MV_PSP_OFF,
+ SDO_525_MV_PSP_ON_2LINE_BURST,
+ SDO_525_MV_PSP_ON_BURST_OFF,
+ SDO_525_MV_PSP_ON_4LINE_BURST,
+};
+
+enum s5p_sd_525_copy_info {
+ SDO_525_COPY_INFO,
+ SDO_525_DEFAULT,
+};
+
+enum s5p_sd_525_aspect_ratio {
+ SDO_525_4_3_NORMAL,
+ SDO_525_16_9_ANAMORPIC,
+ SDO_525_4_3_LETTERBOX
+};
+
+enum s5p_sd_625_subtitles {
+ SDO_625_NO_OPEN_SUBTITLES,
+ SDO_625_INACT_OPEN_SUBTITLES,
+ SDO_625_OUTACT_OPEN_SUBTITLES
+};
+
+enum s5p_sd_625_camera_film {
+ SDO_625_CAMERA,
+ SDO_625_FILM
+};
+
+enum s5p_sd_625_color_encoding {
+ SDO_625_NORMAL_PAL,
+ SDO_625_MOTION_ADAPTIVE_COLORPLUS
+};
+
+enum s5p_sd_625_aspect_ratio {
+ SDO_625_4_3_FULL_576,
+ SDO_625_14_9_LETTERBOX_CENTER_504,
+ SDO_625_14_9_LETTERBOX_TOP_504,
+ SDO_625_16_9_LETTERBOX_CENTER_430,
+ SDO_625_16_9_LETTERBOX_TOP_430,
+ SDO_625_16_9_LETTERBOX_CENTER,
+ SDO_625_14_9_FULL_CENTER_576,
+ SDO_625_16_9_ANAMORPIC_576
+};
+
+enum s5p_tv_hdmi_csc_type {
+ HDMI_CSC_YUV601_TO_RGB_LR,
+ HDMI_CSC_YUV601_TO_RGB_FR,
+ HDMI_CSC_YUV709_TO_RGB_LR,
+ HDMI_CSC_YUV709_TO_RGB_FR,
+ HDMI_CSC_YUV601_TO_YUV709,
+ HDMI_CSC_RGB_FR_TO_RGB_LR,
+ HDMI_CSC_RGB_FR_TO_YUV601,
+ HDMI_CSC_RGB_FR_TO_YUV709,
+ HDMI_BYPASS
+};
+
+enum s5p_tv_hdmi_tg_param {
+ H_BLANK = 0,
+ V2_BLANK,
+ V1_BLANK,
+ V_LINE,
+ H_LINE,
+ VSYNC_POL,
+ V_BOT_ST,
+ V_BOT_END,
+ HSYNC_START,
+ HSYNC_END,
+ HSYNC_POL,
+ VSYNC_T_END,
+ VSYNC_T_START,
+ VSYNC_B_END,
+ VSYNC_B_START,
+ VSYNC_h_POS_END,
+ VSYNC_h_POS_START,
+ TG_H_FSZ,
+ TG_HACT_START,
+ TG_HACT_SZ,
+ TG_V_FSZ,
+ TG_VSYNC,
+ TG_VSYNC2,
+ TG_VACT_START,
+ TG_VACT_SZ,
+ TG_FIELD_CHG,
+ TG_VACT_START2,
+ TG_VSYNC_TOP_HDMI,
+ TG_VSYNC_BOTTOM_HDMI,
+ TG_FIELD_TOP_HDMI,
+ TG_FIELD_BOTTOM_HDMI
+};
+
+enum s5p_tv_hdmi_disp_mode {
+ S5P_TV_HDMI_DISP_MODE_480P_60 = 0,
+ S5P_TV_HDMI_DISP_MODE_576P_50 = 1,
+ S5P_TV_HDMI_DISP_MODE_720P_60 = 2,
+ S5P_TV_HDMI_DISP_MODE_720P_50 = 3,
+ S5P_TV_HDMI_DISP_MODE_1080I_60 = 4,
+ S5P_TV_HDMI_DISP_MODE_1080I_50 = 5,
+ S5P_TV_HDMI_DISP_MODE_VGA_60 = 6,
+ S5P_TV_HDMI_DISP_MODE_NUM = 7
+};
+
+extern void __iomem *hdmi_base;
+
+/* 0 - hdcp stopped, 1 - hdcp started, 2 - hdcp reset */
+extern u8 hdcp_protocol_status;
+
+extern bool __s5p_start_hdcp(void);
+extern void __s5p_stop_hdcp(void);
+extern void __s5p_init_hdcp(bool hpd_status, struct i2c_client *ddc_port);
+
diff --git a/drivers/media/video/samsung/tv20/s5pc100/tv_power_s5pc100.c b/drivers/media/video/samsung/tv20/s5pc100/tv_power_s5pc100.c
new file mode 100644
index 0000000..cf7f0bd
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/s5pc100/tv_power_s5pc100.c
@@ -0,0 +1,140 @@
+/* linux/drivers/media/video/samsung/tv20/s5pc100/tv_power_s5pc100.c
+ *
+ * power raw ftn file for Samsung TVOut driver
+ *
+ * Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+
+#include <linux/uaccess.h>
+#include <linux/io.h>
+
+#include <mach/map.h>
+#include <plat/regs-clock.h>
+#include <plat/regs-power.h>
+
+#include "tv_out_s5pc100.h"
+
+#if defined USE_POWERCON_FUNCTION
+#undef USE_POWERCON_FUNCTION
+#endif
+
+#ifdef COFIG_TVOUT_RAW_DBG
+#define S5P_TVOUT_PM_DEBUG 1
+#endif
+
+#ifdef S5P_TVOUT_PM_DEBUG
+#define TVPMPRINTK(fmt, args...) \
+ printk(KERN_INFO "\t\t[TVPM] %s: " fmt, __func__ , ## args)
+#else
+#define TVPMPRINTK(fmt, args...)
+#endif
+
+#define TVPWR_SUBSYSTEM_ACTIVE (1<<4)
+#define TVPWR_SUBSYSTEM_LP (0<<4)
+
+#define TVPWR_MTC_COUNTER_CLEAR(a) (((~0xf)<<16)&a)
+#define TVPWR_MTC_COUNTER_SET(a) ((0xf&a)<<16)
+
+#define TVPWR_TV_BLOCK_STATUS(a) ((0x1<<4)&a)
+
+#define TVPWR_DAC_STATUS(a) ((0x1<<26)&a)
+#define TVPWR_DAC_ON (1<<26)
+
+static unsigned short g_dacPwrOn;
+
+
+void __s5p_tv_power_init_mtc_stable_counter(unsigned int value)
+{
+ TVPMPRINTK("(%d)\n\r", value);
+
+ writel(TVPWR_MTC_COUNTER_CLEAR((readl(S5P_MTC_STABLE) |
+ TVPWR_MTC_COUNTER_SET(value))),
+ S5P_MTC_STABLE);
+
+ TVPMPRINTK("(0x%08x)\n\r", readl(S5P_MTC_STABLE));
+}
+
+void __s5p_tv_powerinitialize_dac_onoff(unsigned short on)
+{
+ TVPMPRINTK("(%d)\n\r", on);
+
+ g_dacPwrOn = on;
+
+ TVPMPRINTK("(0x%08x)\n\r", g_dacPwrOn);
+}
+
+void __s5p_tv_powerset_dac_onoff(unsigned short on)
+{
+ TVPMPRINTK("(%d)\n\r", on);
+
+ if (on)
+ writel(readl(S5P_OTHERS) | TVPWR_DAC_ON, S5P_OTHERS);
+ else
+ writel(readl(S5P_OTHERS) & ~TVPWR_DAC_ON, S5P_OTHERS);
+
+
+ TVPMPRINTK("(0x%08x)\n\r", readl(S5P_OTHERS));
+}
+
+
+unsigned short __s5p_tv_power_get_power_status(void)
+{
+
+ TVPMPRINTK("()\n\r");
+
+ TVPMPRINTK("(0x%08x)\n\r", readl(S5P_BLK_PWR_STAT));
+
+
+ return TVPWR_TV_BLOCK_STATUS(readl(S5P_BLK_PWR_STAT)) ? 1 : 0;
+}
+
+unsigned short __s5p_tv_power_get_dac_power_status(void)
+{
+ TVPMPRINTK("()\n\r");
+
+ TVPMPRINTK("(0x%08x)\n\r", readl(S5P_OTHERS));
+
+ return TVPWR_DAC_STATUS(readl(S5P_OTHERS)) ? 1 : 0;
+}
+
+void __s5p_tv_poweron(void)
+{
+ TVPMPRINTK("()\n\r");
+
+ writel(readl(S5P_NORMAL_CFG) | TVPWR_SUBSYSTEM_ACTIVE,
+ S5P_NORMAL_CFG);
+
+ while (!TVPWR_TV_BLOCK_STATUS(readl(S5P_BLK_PWR_STAT)))
+ msleep(1);
+
+
+ TVPMPRINTK("0x%08x,0x%08x)\n\r", readl(S5P_NORMAL_CFG),
+ readl(S5P_BLK_PWR_STAT));
+}
+
+
+void __s5p_tv_poweroff(void)
+{
+ TVPMPRINTK("()\n\r");
+
+ __s5p_tv_powerset_dac_onoff(0);
+
+ writel(readl(S5P_NORMAL_CFG) & ~TVPWR_SUBSYSTEM_ACTIVE,
+ S5P_NORMAL_CFG);
+
+ while (TVPWR_TV_BLOCK_STATUS(readl(S5P_BLK_PWR_STAT)))
+ msleep(1);
+
+
+ TVPMPRINTK("0x%08x,0x%08x)\n\r", readl(S5P_NORMAL_CFG),
+ readl(S5P_BLK_PWR_STAT));
+}
diff --git a/drivers/media/video/samsung/tv20/s5pc100/vmixer_s5pc100.c b/drivers/media/video/samsung/tv20/s5pc100/vmixer_s5pc100.c
new file mode 100644
index 0000000..046f44b
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/s5pc100/vmixer_s5pc100.c
@@ -0,0 +1,1047 @@
+/* linux/drivers/media/video/samsung/tv20/s5pc100/vmixer_s5pc100.c
+ *
+ * Mixer raw ftn file for Samsung TVOut driver
+ *
+ * Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+
+#include <linux/io.h>
+
+#include "tv_out_s5pc100.h"
+
+#include "regs/regs-vmx.h"
+
+#ifdef COFIG_TVOUT_RAW_DBG
+#define S5P_MXR_DEBUG 1
+#endif
+
+#ifdef S5P_MXR_DEBUG
+#define VMPRINTK(fmt, args...) \
+ printk(KERN_INFO "\t\t[VM] %s: " fmt, __func__ , ## args)
+#else
+#define VMPRINTK(fmt, args...)
+#endif
+
+static struct resource *mixer_mem;
+void __iomem *mixer_base;
+
+/*
+*set - set functions are only called under running vmixer
+*/
+
+enum s5p_tv_vmx_err __s5p_vm_set_layer_show(enum s5p_tv_vmx_layer layer,
+ bool show)
+{
+ u32 mxr_config;
+
+ VMPRINTK("%d, %d\n\r", layer, show);
+
+ switch (layer) {
+
+ case VM_VIDEO_LAYER:
+ mxr_config = (show) ?
+ (readl(mixer_base + S5P_MXR_CFG) |
+ S5P_MXR_VIDEO_LAYER_SHOW) :
+ (readl(mixer_base + S5P_MXR_CFG) &
+ ~S5P_MXR_VIDEO_LAYER_SHOW);
+ break;
+
+ case VM_GPR0_LAYER:
+ mxr_config = (show) ?
+ (readl(mixer_base + S5P_MXR_CFG) |
+ S5P_MXR_GRAPHIC0_LAYER_SHOW) :
+ (readl(mixer_base + S5P_MXR_CFG) &
+ ~S5P_MXR_GRAPHIC0_LAYER_SHOW);
+ break;
+
+ case VM_GPR1_LAYER:
+ mxr_config = (show) ?
+ (readl(mixer_base + S5P_MXR_CFG) |
+ S5P_MXR_GRAPHIC1_LAYER_SHOW) :
+ (readl(mixer_base + S5P_MXR_CFG) &
+ ~S5P_MXR_GRAPHIC1_LAYER_SHOW);
+ break;
+
+ default:
+ VMPRINTK(" invalid layer parameter = %d\n\r", layer);
+ return S5P_TV_VMX_ERR_INVALID_PARAM;
+ break;
+ }
+
+ writel(mxr_config, mixer_base + S5P_MXR_CFG);
+
+ VMPRINTK("0x%x\n\r", readl(mixer_base + S5P_MXR_CFG));
+
+ return VMIXER_NO_ERROR;
+}
+
+enum s5p_tv_vmx_err __s5p_vm_set_layer_priority(enum s5p_tv_vmx_layer layer,
+ u32 priority)
+{
+ u32 layer_cfg;
+
+ VMPRINTK("%d, %d\n\r", layer, priority);
+
+ switch (layer) {
+
+ case VM_VIDEO_LAYER:
+ layer_cfg = S5P_MXR_VP_LAYER_PRIORITY_CLEAR(
+ readl(mixer_base + S5P_MXR_LAYER_CFG)) |
+ S5P_MXR_VP_LAYER_PRIORITY(priority);
+ break;
+
+ case VM_GPR0_LAYER:
+ layer_cfg = S5P_MXR_GRP0_LAYER_PRIORITY_CLEAR(
+ readl(mixer_base + S5P_MXR_LAYER_CFG)) |
+ S5P_MXR_GRP0_LAYER_PRIORITY(priority);
+ break;
+
+ case VM_GPR1_LAYER:
+ layer_cfg = S5P_MXR_GRP1_LAYER_PRIORITY_CLEAR(
+ readl(mixer_base + S5P_MXR_LAYER_CFG)) |
+ S5P_MXR_GRP1_LAYER_PRIORITY(priority);
+ break;
+
+ default:
+ VMPRINTK(" invalid layer parameter = %d\n\r", layer);
+ return S5P_TV_VMX_ERR_INVALID_PARAM;
+ break;
+ }
+
+ writel(layer_cfg, mixer_base + S5P_MXR_LAYER_CFG);
+
+ return VMIXER_NO_ERROR;
+}
+
+enum s5p_tv_vmx_err __s5p_vm_set_win_blend(
+ enum s5p_tv_vmx_layer layer, bool enable)
+{
+ u32 temp_reg;
+ VMPRINTK("%d, %d\n\r", layer, enable);
+
+ switch (layer) {
+
+ case VM_VIDEO_LAYER:
+ temp_reg = readl(mixer_base + S5P_MXR_VIDEO_CFG)
+ & (~S5P_MXR_VP_BLEND_ENABLE) ;
+
+ if (enable)
+ temp_reg |= S5P_MXR_VP_BLEND_ENABLE;
+ else
+ temp_reg |= S5P_MXR_VP_BLEND_DISABLE;
+
+ writel(temp_reg, mixer_base + S5P_MXR_VIDEO_CFG);
+
+ break;
+
+ case VM_GPR0_LAYER:
+ temp_reg = readl(mixer_base + S5P_MXR_GRAPHIC0_CFG)
+ & (~S5P_MXR_WIN_BLEND_ENABLE) ;
+
+ if (enable)
+ temp_reg |= S5P_MXR_WIN_BLEND_ENABLE;
+ else
+ temp_reg |= S5P_MXR_WIN_BLEND_DISABLE;
+
+ writel(temp_reg, mixer_base + S5P_MXR_GRAPHIC0_CFG);
+
+ break;
+
+ case VM_GPR1_LAYER:
+ temp_reg = readl(mixer_base + S5P_MXR_GRAPHIC1_CFG)
+ & (~S5P_MXR_WIN_BLEND_ENABLE) ;
+
+ if (enable)
+ temp_reg |= S5P_MXR_WIN_BLEND_ENABLE;
+ else
+ temp_reg |= S5P_MXR_WIN_BLEND_DISABLE;
+
+ writel(temp_reg, mixer_base + S5P_MXR_GRAPHIC1_CFG);
+
+ break;
+
+ default:
+ VMPRINTK(" invalid layer parameter = %d\n\r", layer);
+
+ return S5P_TV_VMX_ERR_INVALID_PARAM;
+
+ break;
+ }
+
+ VMPRINTK("0x08%x\n\r", readl(mixer_base + S5P_MXR_VIDEO_CFG));
+
+ VMPRINTK("0x08%x\n\r", readl(mixer_base + S5P_MXR_GRAPHIC0_CFG));
+ VMPRINTK("0x08%x\n\r", readl(mixer_base + S5P_MXR_GRAPHIC1_CFG));
+
+ return VMIXER_NO_ERROR;
+}
+
+
+enum s5p_tv_vmx_err __s5p_vm_set_layer_alpha(enum s5p_tv_vmx_layer layer,
+ u32 alpha)
+{
+ u32 temp_reg;
+ VMPRINTK("%d, %d\n\r", layer, alpha);
+
+ switch (layer) {
+
+ case VM_VIDEO_LAYER:
+ temp_reg = readl(mixer_base + S5P_MXR_VIDEO_CFG)
+ & (~S5P_MXR_ALPHA) ;
+ temp_reg |= S5P_MXR_VP_ALPHA_VALUE(alpha);
+ writel(temp_reg, mixer_base + S5P_MXR_VIDEO_CFG);
+ break;
+
+ case VM_GPR0_LAYER:
+ temp_reg = readl(mixer_base + S5P_MXR_GRAPHIC0_CFG)
+ & (~S5P_MXR_ALPHA) ;
+ temp_reg |= S5P_MXR_GRP_ALPHA_VALUE(alpha);
+ writel(temp_reg, mixer_base + S5P_MXR_GRAPHIC0_CFG);
+ break;
+
+ case VM_GPR1_LAYER:
+ temp_reg = readl(mixer_base + S5P_MXR_GRAPHIC1_CFG)
+ & (~S5P_MXR_ALPHA) ;
+ temp_reg |= S5P_MXR_GRP_ALPHA_VALUE(alpha);
+ writel(temp_reg, mixer_base + S5P_MXR_GRAPHIC1_CFG);
+ break;
+
+ default:
+ VMPRINTK(" invalid layer parameter = %d\n\r", layer);
+ return S5P_TV_VMX_ERR_INVALID_PARAM;
+ break;
+ }
+
+ VMPRINTK("0x08%x\n\r", readl(mixer_base + S5P_MXR_VIDEO_CFG));
+
+ VMPRINTK("0x08%x\n\r", readl(mixer_base + S5P_MXR_GRAPHIC0_CFG));
+ VMPRINTK("0x08%x\n\r", readl(mixer_base + S5P_MXR_GRAPHIC1_CFG));
+
+ return VMIXER_NO_ERROR;
+}
+
+
+enum s5p_tv_vmx_err __s5p_vm_set_grp_base_address(enum s5p_tv_vmx_layer layer,
+ u32 base_addr)
+{
+ VMPRINTK("%d, 0x%x\n\r", layer, base_addr);
+
+ if (S5P_MXR_GRP_ADDR_ILLEGAL(base_addr)) {
+ VMPRINTK(" address is not word align = %d\n\r", base_addr);
+ return S5P_TV_VMX_ERR_BASE_ADDRESS_MUST_WORD_ALIGN;
+ }
+
+ switch (layer) {
+
+ case VM_GPR0_LAYER:
+ writel(S5P_MXR_GPR_BASE(base_addr),
+ mixer_base + S5P_MXR_GRAPHIC0_BASE);
+ VMPRINTK("0x%x\n\r",
+ readl(mixer_base + S5P_MXR_GRAPHIC0_BASE));
+ break;
+
+ case VM_GPR1_LAYER:
+ writel(S5P_MXR_GPR_BASE(base_addr),
+ mixer_base + S5P_MXR_GRAPHIC1_BASE);
+ VMPRINTK("0x%x\n\r",
+ readl(mixer_base + S5P_MXR_GRAPHIC1_BASE));
+ break;
+
+ default:
+ VMPRINTK(" invalid layer parameter = %d\n\r", layer);
+ return S5P_TV_VMX_ERR_INVALID_PARAM;
+ break;
+ }
+
+ return VMIXER_NO_ERROR;
+}
+
+enum s5p_tv_vmx_err __s5p_vm_set_grp_layer_position(enum s5p_tv_vmx_layer
+ layer, u32 dst_offs_x, u32 dst_offs_y)
+{
+ VMPRINTK("%d, %d, %d)\n\r", layer, dst_offs_x, dst_offs_y);
+
+ switch (layer) {
+
+ case VM_GPR0_LAYER:
+ writel(S5P_MXR_GRP_DESTX(dst_offs_x) |
+ S5P_MXR_GRP_DESTY(dst_offs_y),
+ mixer_base + S5P_MXR_GRAPHIC0_DXY);
+ VMPRINTK("0x%x\n\r", readl(mixer_base + S5P_MXR_GRAPHIC0_DXY));
+ break;
+
+ case VM_GPR1_LAYER:
+ writel(S5P_MXR_GRP_DESTX(dst_offs_x) |
+ S5P_MXR_GRP_DESTY(dst_offs_y),
+ mixer_base + S5P_MXR_GRAPHIC1_DXY);
+ VMPRINTK("0x%x\n\r", readl(mixer_base + S5P_MXR_GRAPHIC1_DXY));
+ break;
+
+ default:
+ VMPRINTK("invalid layer parameter = %d\n\r", layer);
+ return S5P_TV_VMX_ERR_INVALID_PARAM;
+ break;
+ }
+
+ return VMIXER_NO_ERROR;
+}
+
+enum s5p_tv_vmx_err __s5p_vm_set_grp_layer_size(enum s5p_tv_vmx_layer layer,
+ u32 span,
+ u32 width,
+ u32 height,
+ u32 src_offs_x,
+ u32 src_offs_y)
+{
+ VMPRINTK("%d, %d, %d, %d, %d, %d)\n\r", layer, span, width, height,
+ src_offs_x, src_offs_y);
+
+ switch (layer) {
+
+ case VM_GPR0_LAYER:
+ writel(S5P_MXR_GRP_SPAN(span),
+ mixer_base + S5P_MXR_GRAPHIC0_SPAN);
+ writel(S5P_MXR_GRP_WIDTH(width) |
+ S5P_MXR_GRP_HEIGHT(height),
+ mixer_base + S5P_MXR_GRAPHIC0_WH);
+ writel(S5P_MXR_GRP_STARTX(src_offs_x) |
+ S5P_MXR_GRP_STARTY(src_offs_y),
+ mixer_base + S5P_MXR_GRAPHIC0_SXY);
+ VMPRINTK("0x%x, 0x%x, 0x%x\n\r",
+ readl(mixer_base + S5P_MXR_GRAPHIC0_SPAN),
+ readl(mixer_base + S5P_MXR_GRAPHIC0_WH),
+ readl(mixer_base + S5P_MXR_GRAPHIC0_SXY));
+ break;
+
+ case VM_GPR1_LAYER:
+ writel(S5P_MXR_GRP_SPAN(span),
+ mixer_base + S5P_MXR_GRAPHIC1_SPAN);
+ writel(S5P_MXR_GRP_WIDTH(width) | S5P_MXR_GRP_HEIGHT(height),
+ mixer_base + S5P_MXR_GRAPHIC1_WH);
+ writel(S5P_MXR_GRP_STARTX(src_offs_x) |
+ S5P_MXR_GRP_STARTY(src_offs_y),
+ mixer_base + S5P_MXR_GRAPHIC1_SXY);
+ VMPRINTK("0x%x, 0x%x, 0x%x\n\r",
+ readl(mixer_base + S5P_MXR_GRAPHIC1_SPAN),
+ readl(mixer_base + S5P_MXR_GRAPHIC1_WH),
+ readl(mixer_base + S5P_MXR_GRAPHIC1_SXY));
+ break;
+
+ default:
+ VMPRINTK(" invalid layer parameter = %d\n\r", layer);
+ return S5P_TV_VMX_ERR_INVALID_PARAM;
+ break;
+ }
+
+ return VMIXER_NO_ERROR;
+}
+
+enum s5p_tv_vmx_err __s5p_vm_set_bg_color(
+ enum s5p_tv_vmx_bg_color_num colornum,
+ u32 color_y,
+ u32 color_cb,
+ u32 color_cr)
+{
+ u32 reg_value;
+ VMPRINTK("%d, %d, %d, %d)\n\r", colornum, color_y, color_cb, color_cr);
+
+ reg_value = S5P_MXR_BG_COLOR_Y(color_y) |
+ S5P_MXR_BG_COLOR_CB(color_cb) |
+ S5P_MXR_BG_COLOR_CR(color_cr);
+
+ switch (colornum) {
+
+ case VMIXER_BG_COLOR_0:
+ writel(reg_value, mixer_base + S5P_MXR_BG_COLOR0);
+ VMPRINTK("0x%x\n\r", readl(mixer_base + S5P_MXR_BG_COLOR0));
+ break;
+
+ case VMIXER_BG_COLOR_1:
+ writel(reg_value, mixer_base + S5P_MXR_BG_COLOR1);
+ VMPRINTK("0x%x\n\r", readl(mixer_base + S5P_MXR_BG_COLOR1));
+ break;
+
+ case VMIXER_BG_COLOR_2:
+ writel(reg_value, mixer_base + S5P_MXR_BG_COLOR2);
+ VMPRINTK("0x%x\n\r", readl(mixer_base + S5P_MXR_BG_COLOR2));
+ break;
+
+ default:
+ VMPRINTK(" invalid uiColorNum parameter = %d\n\r", colornum);
+ return S5P_TV_VMX_ERR_INVALID_PARAM;
+ break;
+ }
+
+ return VMIXER_NO_ERROR;
+}
+
+
+
+/*
+* initialization - iniization functions are only called under stopping vmixer
+*/
+enum s5p_tv_vmx_err __s5p_vm_init_status_reg(enum s5p_vmx_burst_mode burst,
+ enum s5p_endian_type endian)
+{
+ u32 temp_reg = 0;
+
+ VMPRINTK("++(%d, %d)\n\r", burst, endian);
+
+ temp_reg = S5P_MXR_MIXER_RESERVED |
+ S5P_MXR_CMU_CANNOT_STOP_CLOCK;
+
+ switch (burst) {
+
+ case VM_BURST_8:
+ temp_reg |= S5P_MXR_BURST8_MODE;
+ break;
+
+ case VM_BURST_16:
+ temp_reg |= S5P_MXR_BURST16_MODE;
+ break;
+
+ default:
+ VMPRINTK("[ERR] : invalid burst parameter = %d\n\r", burst);
+ return S5P_TV_VMX_ERR_INVALID_PARAM;
+ break;
+ }
+
+ switch (endian) {
+
+ case TVOUT_BIG_ENDIAN_MODE:
+ temp_reg |= S5P_MXR_BIG_ENDIAN_SOURCE_FORMAT;
+ break;
+
+ case TVOUT_LITTLE_ENDIAN_MODE:
+ temp_reg |= S5P_MXR_LITTLE_ENDIAN_SOURCE_FORMAT;
+ break;
+
+ default:
+ VMPRINTK("[ERR] : invalid endian parameter = %d\n\r", endian);
+ return S5P_TV_VMX_ERR_INVALID_PARAM;
+ break;
+ }
+
+ writel(temp_reg, mixer_base + S5P_MXR_STATUS);
+
+ VMPRINTK("--(0x%x)\n\r", readl(mixer_base + S5P_MXR_STATUS));
+
+ return VMIXER_NO_ERROR;
+}
+
+enum s5p_tv_vmx_err __s5p_vm_init_display_mode(enum s5p_tv_disp_mode mode,
+ enum s5p_tv_o_mode output_mode)
+{
+ u32 temp_reg = 0;
+
+ VMPRINTK("%d, %d)\n\r", mode, output_mode);
+
+ switch (mode) {
+
+ case TVOUT_NTSC_M:
+
+ case TVOUT_NTSC_443:
+ temp_reg = S5P_MXR_SD | S5P_MXR_NTSC;
+ break;
+
+ case TVOUT_PAL_BDGHI:
+
+ case TVOUT_PAL_M:
+
+ case TVOUT_PAL_N:
+
+ case TVOUT_PAL_NC:
+
+ case TVOUT_PAL_60:
+ temp_reg = S5P_MXR_SD | S5P_MXR_PAL;
+ break;
+
+ case TVOUT_480P_60_16_9:
+
+ case TVOUT_480P_60_4_3:
+ temp_reg = S5P_MXR_SD | S5P_MXR_NTSC;
+ break;
+
+ case TVOUT_576P_50_16_9:
+
+ case TVOUT_576P_50_4_3:
+ temp_reg = S5P_MXR_SD | S5P_MXR_PAL;
+ break;
+
+ case TVOUT_720P_50:
+
+ case TVOUT_720P_60:
+ temp_reg = S5P_MXR_HD | S5P_MXR_HD_720P_MODE;
+ break;
+
+ default:
+ VMPRINTK(" invalid mode parameter = %d\n\r", mode);
+ return S5P_TV_VMX_ERR_INVALID_PARAM;
+ break;
+ }
+
+ switch (output_mode) {
+
+ case TVOUT_OUTPUT_COMPOSITE:
+
+ case TVOUT_OUTPUT_SVIDEO:
+
+ case TVOUT_OUTPUT_COMPONENT_YPBPR_INERLACED:
+ temp_reg |= S5P_MXR_INTERLACE_MODE;
+ break;
+
+ case TVOUT_OUTPUT_COMPONENT_YPBPR_PROGRESSIVE:
+
+ case TVOUT_OUTPUT_COMPONENT_RGB_PROGRESSIVE:
+ temp_reg |= S5P_MXR_PROGRESSVE_MODE;
+ break;
+
+ case TVOUT_OUTPUT_HDMI:
+ temp_reg |= S5P_MXR_PROGRESSVE_MODE;
+ break;
+
+ default:
+ VMPRINTK(" invalid mode parameter = %d\n\r", mode);
+ return S5P_TV_VMX_ERR_INVALID_PARAM;
+ break;
+ }
+
+ writel(temp_reg, mixer_base + S5P_MXR_CFG);
+
+ VMPRINTK("--(0x%x)\n\r", readl(mixer_base + S5P_MXR_CFG));
+
+ return VMIXER_NO_ERROR;
+}
+
+enum s5p_tv_vmx_err __s5p_vm_init_layer(enum s5p_tv_vmx_layer layer,
+ bool show,
+ bool win_blending,
+ u32 alpha,
+ u32 priority,
+ enum s5p_tv_vmx_color_fmt color,
+ bool blank_change,
+ bool pixel_blending,
+ bool premul,
+ u32 blank_color,
+ u32 base_addr,
+ u32 span,
+ u32 width,
+ u32 height,
+ u32 src_offs_x,
+ u32 src_offs_y,
+ u32 dst_offs_x,
+ u32 dst_offs_y)
+{
+ u32 temp_reg = 0;
+
+ VMPRINTK("%d, %d, %d, %d, %d, %d, %d, %d, %d, 0x%x,\
+ 0x%x, %d, %d, %d, %d, %d, %d, %d)\n\r",
+ layer, show, win_blending, alpha, priority,
+ color, blank_change, pixel_blending, premul,
+ blank_color, base_addr, span, width, height,
+ src_offs_x, src_offs_y, dst_offs_x, dst_offs_y);
+
+ switch (layer) {
+
+ case VM_VIDEO_LAYER:
+ temp_reg = (win_blending) ? S5P_MXR_VP_BLEND_ENABLE :
+ S5P_MXR_VP_BLEND_DISABLE;
+ temp_reg |= S5P_MXR_VP_ALPHA_VALUE(alpha);
+ writel(temp_reg, mixer_base + S5P_MXR_VIDEO_CFG);
+ break;
+
+ case VM_GPR0_LAYER:
+ temp_reg = (blank_change) ?
+ S5P_MXR_BLANK_NOT_CHANGE_NEW_PIXEL :
+ S5P_MXR_BLANK_CHANGE_NEW_PIXEL;
+ temp_reg |= (premul) ? S5P_MXR_PRE_MUL_MODE :
+ S5P_MXR_NORMAL_MODE;
+ temp_reg |= (win_blending) ? S5P_MXR_WIN_BLEND_ENABLE :
+ S5P_MXR_WIN_BLEND_DISABLE;
+ temp_reg |= (pixel_blending) ? S5P_MXR_PIXEL_BLEND_ENABLE :
+ S5P_MXR_PIXEL_BLEND_DISABLE;
+ temp_reg |= S5P_MXR_EG_COLOR_FORMAT(color);
+ temp_reg |= S5P_MXR_GRP_ALPHA_VALUE(alpha);
+ writel(temp_reg, mixer_base + S5P_MXR_GRAPHIC0_CFG);
+ writel(S5P_MXR_GPR_BLANK_COLOR(blank_color),
+ mixer_base + S5P_MXR_GRAPHIC0_BLANK);
+
+ VMPRINTK("--(0x%x)\n\r",
+ readl(mixer_base + S5P_MXR_GRAPHIC0_CFG));
+ VMPRINTK("--(0x%x)\n\r",
+ readl(mixer_base + S5P_MXR_GRAPHIC0_BLANK));
+
+ __s5p_vm_set_grp_layer_size(layer, span, width, height,
+ src_offs_x, src_offs_y);
+
+ __s5p_vm_set_grp_base_address(layer, base_addr);
+ __s5p_vm_set_grp_layer_position(layer, dst_offs_x, dst_offs_y);
+
+ break;
+
+ case VM_GPR1_LAYER:
+ temp_reg = (blank_change) ?
+ S5P_MXR_BLANK_NOT_CHANGE_NEW_PIXEL :
+ S5P_MXR_BLANK_CHANGE_NEW_PIXEL;
+ temp_reg |= (premul) ? S5P_MXR_PRE_MUL_MODE :
+ S5P_MXR_NORMAL_MODE;
+ temp_reg |= (win_blending) ? S5P_MXR_WIN_BLEND_ENABLE :
+ S5P_MXR_WIN_BLEND_DISABLE;
+ temp_reg |= (pixel_blending) ? S5P_MXR_PIXEL_BLEND_ENABLE :
+ S5P_MXR_PIXEL_BLEND_DISABLE;
+ temp_reg |= S5P_MXR_EG_COLOR_FORMAT(color);
+ temp_reg |= S5P_MXR_GRP_ALPHA_VALUE(alpha);
+
+ writel(temp_reg, mixer_base + S5P_MXR_GRAPHIC1_CFG);
+ writel(S5P_MXR_GPR_BLANK_COLOR(blank_color),
+ mixer_base + S5P_MXR_GRAPHIC1_BLANK);
+
+ VMPRINTK("--(0x%x)\n\r",
+ readl(mixer_base + S5P_MXR_GRAPHIC1_CFG));
+ VMPRINTK("--(0x%x)\n\r",
+ readl(mixer_base + S5P_MXR_GRAPHIC1_BLANK));
+
+ __s5p_vm_set_grp_layer_size(layer, span, width, height,
+ src_offs_x, src_offs_y);
+
+ __s5p_vm_set_grp_base_address(layer, base_addr);
+ __s5p_vm_set_grp_layer_position(layer, dst_offs_x, dst_offs_y);
+ break;
+
+ default:
+ VMPRINTK("invalid layer parameter = %d\n\r", layer);
+ return S5P_TV_VMX_ERR_INVALID_PARAM;
+ break;
+ }
+
+ __s5p_vm_set_layer_priority(layer, priority);
+
+ __s5p_vm_set_layer_show(layer, show);
+
+ return VMIXER_NO_ERROR;
+}
+
+void __s5p_vm_init_bg_dither_enable(bool cr_dither_enable,
+ bool cb_dither_enable,
+ bool y_dither_enable)
+{
+ u32 temp_reg = 0;
+
+ VMPRINTK("%d, %d, %d\n\r", cr_dither_enable,
+ cb_dither_enable, y_dither_enable);
+
+ temp_reg = (cr_dither_enable) ?
+ (temp_reg | S5P_MXR_BG_CR_DIHER_EN) :
+ (temp_reg & ~S5P_MXR_BG_CR_DIHER_EN);
+ temp_reg = (cb_dither_enable) ?
+ (temp_reg | S5P_MXR_BG_CB_DIHER_EN) :
+ (temp_reg & ~S5P_MXR_BG_CB_DIHER_EN);
+ temp_reg = (y_dither_enable) ?
+ (temp_reg | S5P_MXR_BG_Y_DIHER_EN) :
+ (temp_reg & ~S5P_MXR_BG_Y_DIHER_EN);
+
+ writel(temp_reg, mixer_base + S5P_MXR_BG_CFG);
+ VMPRINTK("--(0x%x)\n\r", readl(mixer_base + S5P_MXR_BG_CFG));
+
+}
+
+
+enum s5p_tv_vmx_err __s5p_vm_init_bg_color(
+ enum s5p_tv_vmx_bg_color_num color_num,
+ u32 color_y,
+ u32 color_cb,
+ u32 color_cr)
+{
+ return __s5p_vm_set_bg_color(color_num, color_y, color_cb, color_cr);
+}
+
+enum s5p_tv_vmx_err __s5p_vm_init_csc_coef(enum s5p_yuv_fmt_component component,
+ enum s5p_tv_coef_y_mode mode,
+ u32 coeff0,
+ u32 coeff1,
+ u32 coeff2)
+{
+ u32 mxr_cm;
+
+ VMPRINTK("%d, %d, %d, %d, %d\n\r", component, mode, coeff0,
+ coeff1, coeff2);
+
+ switch (component) {
+
+ case TVOUT_YUV_Y:
+ mxr_cm = (mode == VMIXER_COEF_Y_WIDE) ?
+ S5P_MXR_BG_COLOR_WIDE : S5P_MXR_BG_COLOR_NARROW;
+ mxr_cm |= S5P_MXR_BG_COEFF_0(coeff0) |
+ S5P_MXR_BG_COEFF_1(coeff1) |
+ S5P_MXR_BG_COEFF_2(coeff2);
+ writel(mxr_cm, mixer_base + S5P_MXR_CM_COEFF_Y);
+ VMPRINTK("--(0x%x)\n\r",
+ readl(mixer_base + S5P_MXR_CM_COEFF_Y));
+ break;
+
+ case TVOUT_YUV_CB:
+ mxr_cm = S5P_MXR_BG_COEFF_0(coeff0) |
+ S5P_MXR_BG_COEFF_1(coeff1) |
+ S5P_MXR_BG_COEFF_2(coeff2);
+ writel(mxr_cm, mixer_base + S5P_MXR_CM_COEFF_CB);
+ VMPRINTK("--(0x%x)\n\r",
+ readl(mixer_base + S5P_MXR_CM_COEFF_CB));
+ break;
+
+ case TVOUT_YUV_CR:
+ mxr_cm = S5P_MXR_BG_COEFF_0(coeff0) |
+ S5P_MXR_BG_COEFF_1(coeff1) |
+ S5P_MXR_BG_COEFF_2(coeff2);
+ writel(mxr_cm, S5P_MXR_CM_COEFF_CR);
+ VMPRINTK("--(0x%x)\n\r",
+ readl(mixer_base + S5P_MXR_CM_COEFF_CR));
+ break;
+
+ default:
+ VMPRINTK("invalid component parameter = %d\n\r", component);
+ return S5P_TV_VMX_ERR_INVALID_PARAM;
+ break;
+ }
+
+ return VMIXER_NO_ERROR;
+}
+
+void __s5p_vm_init_csc_coef_default(enum s5p_tv_vmx_csc_type csc_type)
+{
+ VMPRINTK("%d\n\r", csc_type);
+
+ switch (csc_type) {
+
+ case VMIXER_CSC_RGB_TO_YUV601_LR:
+ writel((0 << 30) | (153 << 20) | (300 << 10) | (58 << 0),
+ mixer_base + S5P_MXR_CM_COEFF_Y);
+ writel((936 << 20) | (851 << 10) | (262 << 0),
+ mixer_base + S5P_MXR_CM_COEFF_CB);
+ writel((262 << 20) | (805 << 10) | (982 << 0),
+ mixer_base + S5P_MXR_CM_COEFF_CR);
+ break;
+
+ case VMIXER_CSC_RGB_TO_YUV601_FR:
+ writel((1 << 30) | (132 << 20) | (258 << 10) | (50 << 0),
+ mixer_base + S5P_MXR_CM_COEFF_Y);
+ writel((948 << 20) | (875 << 10) | (225 << 0),
+ mixer_base + S5P_MXR_CM_COEFF_CB);
+ writel((225 << 20) | (836 << 10) | (988 << 0),
+ mixer_base + S5P_MXR_CM_COEFF_CR);
+ break;
+
+ case VMIXER_CSC_RGB_TO_YUV709_LR:
+ writel((0 << 30) | (109 << 20) | (366 << 10) | (36 << 0),
+ mixer_base + S5P_MXR_CM_COEFF_Y);
+ writel((964 << 20) | (822 << 10) | (216 << 0),
+ mixer_base + S5P_MXR_CM_COEFF_CB);
+ writel((262 << 20) | (787 << 10) | (1000 << 0),
+ mixer_base + S5P_MXR_CM_COEFF_CR);
+ break;
+
+ case VMIXER_CSC_RGB_TO_YUV709_FR:
+ writel((1 << 30) | (94 << 20) | (314 << 10) | (32 << 0),
+ mixer_base + S5P_MXR_CM_COEFF_Y);
+ writel((972 << 20) | (851 << 10) | (225 << 0),
+ mixer_base + S5P_MXR_CM_COEFF_CB);
+ writel((225 << 20) | (820 << 10) | (1004 << 0),
+ mixer_base + S5P_MXR_CM_COEFF_CR);
+ break;
+
+ default:
+ VMPRINTK(" invalid csc_type parameter = %d\n\r", csc_type);
+ break;
+ }
+
+ VMPRINTK("--(0x%x)\n\r", readl(mixer_base + S5P_MXR_CM_COEFF_Y));
+
+ VMPRINTK("--(0x%x)\n\r", readl(mixer_base + S5P_MXR_CM_COEFF_CB));
+ VMPRINTK("--(0x%x)\n\r", readl(mixer_base + S5P_MXR_CM_COEFF_CR));
+}
+
+/*
+* etc
+*/
+enum s5p_tv_vmx_err __s5p_vm_get_layer_info(enum s5p_tv_vmx_layer layer,
+ bool *show,
+ u32 *priority)
+{
+ VMPRINTK("%d\n\r", layer);
+
+ switch (layer) {
+
+ case VM_VIDEO_LAYER:
+ *show = (readl(mixer_base + S5P_MXR_LAYER_CFG) &
+ S5P_MXR_VIDEO_LAYER_SHOW) ? 1 : 0;
+ *priority = S5P_MXR_VP_LAYER_PRIORITY_INFO(
+ readl(mixer_base + S5P_MXR_LAYER_CFG));
+ break;
+
+ case VM_GPR0_LAYER:
+ *show = (readl(mixer_base + S5P_MXR_LAYER_CFG) &
+ S5P_MXR_GRAPHIC0_LAYER_SHOW) ? 1 : 0;
+ *priority = S5P_MXR_GRP0_LAYER_PRIORITY_INFO(
+ readl(mixer_base + S5P_MXR_LAYER_CFG));
+ break;
+
+ case VM_GPR1_LAYER:
+ *show = (readl(mixer_base + S5P_MXR_LAYER_CFG) &
+ S5P_MXR_GRAPHIC1_LAYER_SHOW) ? 1 : 0;
+ *priority = S5P_MXR_GRP1_LAYER_PRIORITY_INFO(
+ readl(mixer_base + S5P_MXR_LAYER_CFG));
+ break;
+
+ default:
+ VMPRINTK("invalid layer parameter = %d\n\r", layer);
+ return S5P_TV_VMX_ERR_INVALID_PARAM;
+ break;
+ }
+
+ VMPRINTK("%d, %d\n\r", *show, *priority);
+
+ return VMIXER_NO_ERROR;
+}
+
+/*
+* start - start functions are only called under stopping vmixer
+*/
+
+void __s5p_vm_start(void)
+{
+ VMPRINTK("()\n\r");
+ writel((readl(mixer_base + S5P_MXR_STATUS) | S5P_MXR_MIXER_START),
+ mixer_base + S5P_MXR_STATUS);
+ VMPRINTK("0x%x\n\r", readl(mixer_base + S5P_MXR_STATUS));
+
+
+ VMPRINTK("S5P_MXR_STATUS \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_STATUS));
+ VMPRINTK("S5P_MXR_INT_EN \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_INT_EN));
+ VMPRINTK("S5P_MXR_BG_CFG \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_BG_CFG));
+ VMPRINTK("S5P_MXR_BG_COLOR0 \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_BG_COLOR0));
+ VMPRINTK("S5P_MXR_BG_COLOR1 \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_BG_COLOR1));
+ VMPRINTK("S5P_MXR_BG_COLOR2 \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_BG_COLOR2));
+ VMPRINTK("S5P_MXR_CM_COEFF_Y \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_CM_COEFF_Y));
+ VMPRINTK("S5P_MXR_CM_COEFF_CB \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_CM_COEFF_CB));
+ VMPRINTK("S5P_MXR_CM_COEFF_CR \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_CM_COEFF_CR));
+ VMPRINTK("S5P_MXR_CM_COEFF_Y \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_CM_COEFF_Y));
+ VMPRINTK("S5P_MXR_CM_COEFF_CB \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_CM_COEFF_CB));
+ VMPRINTK("S5P_MXR_CM_COEFF_CR \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_CM_COEFF_CR));
+ VMPRINTK("S5P_MXR_GRAPHIC0_CFG \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_GRAPHIC0_CFG));
+ VMPRINTK("S5P_MXR_GRAPHIC0_BASE \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_GRAPHIC0_BASE));
+ VMPRINTK("S5P_MXR_GRAPHIC0_SPAN \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_GRAPHIC0_SPAN));
+ VMPRINTK("S5P_MXR_GRAPHIC0_WH \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_GRAPHIC0_WH));
+ VMPRINTK("S5P_MXR_GRAPHIC0_SXY \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_GRAPHIC0_SXY));
+ VMPRINTK("S5P_MXR_GRAPHIC0_DXY \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_GRAPHIC0_DXY));
+ VMPRINTK("S5P_MXR_GRAPHIC0_BLANK \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_GRAPHIC0_BLANK));
+ VMPRINTK("S5P_MXR_GRAPHIC1_BASE \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_GRAPHIC1_BASE));
+ VMPRINTK("S5P_MXR_GRAPHIC1_SPAN \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_GRAPHIC1_SPAN));
+ VMPRINTK("S5P_MXR_GRAPHIC1_WH \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_GRAPHIC1_WH));
+ VMPRINTK("S5P_MXR_GRAPHIC1_SXY \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_GRAPHIC1_SXY));
+ VMPRINTK("S5P_MXR_GRAPHIC1_DXY \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_GRAPHIC1_DXY));
+ VMPRINTK("S5P_MXR_GRAPHIC1_BLANK \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_GRAPHIC1_BLANK));
+ VMPRINTK("S5P_MXR_CFG \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_CFG));
+ VMPRINTK("S5P_MXR_LAYER_CFG \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_LAYER_CFG));
+
+}
+
+/*
+* stop - stop functions are only called under running vmixer
+*/
+
+void __s5p_vm_stop(void)
+{
+ VMPRINTK("()\n\r");
+ writel((readl(mixer_base + S5P_MXR_STATUS) & ~S5P_MXR_MIXER_START),
+ mixer_base + S5P_MXR_STATUS);
+ VMPRINTK("0x%x\n\r", readl(mixer_base + S5P_MXR_STATUS));
+}
+
+/*
+* interrupt - for debug
+*/
+
+enum s5p_tv_vmx_err __s5p_vm_set_underflow_interrupt_enable(
+ enum s5p_tv_vmx_layer layer, bool en)
+{
+ u32 enablemaks;
+
+ VMPRINTK("%d, %d\n\r", layer, en);
+
+ switch (layer) {
+
+ case VM_VIDEO_LAYER:
+ enablemaks = S5P_MXR_VP_INT_ENABLE;
+ break;
+
+ case VM_GPR0_LAYER:
+ enablemaks = S5P_MXR_GRP0_INT_ENABLE;
+ break;
+
+ case VM_GPR1_LAYER:
+ enablemaks = S5P_MXR_GRP1_INT_ENABLE;
+ break;
+
+ default:
+ VMPRINTK("invalid layer parameter = %d\n\r", layer);
+ return S5P_TV_VMX_ERR_INVALID_PARAM;
+ break;
+ }
+
+ if (en) {
+ writel((readl(mixer_base + S5P_MXR_INT_EN) | enablemaks),
+ mixer_base + S5P_MXR_INT_EN);
+ } else {
+ writel((readl(mixer_base + S5P_MXR_INT_EN) & ~enablemaks),
+ mixer_base + S5P_MXR_INT_EN);
+ }
+
+ VMPRINTK("0x%x)\n\r", readl(mixer_base + S5P_MXR_INT_EN));
+
+ return VMIXER_NO_ERROR;
+}
+
+void __s5p_vm_clear_pend_all(void)
+{
+ writel(S5P_MXR_INT_FIRED | S5P_MXR_VP_INT_FIRED |
+ S5P_MXR_GRP0_INT_FIRED | S5P_MXR_GRP1_INT_FIRED,
+ mixer_base + S5P_MXR_INT_EN);
+}
+
+irqreturn_t __s5p_mixer_irq(int irq, void *dev_id)
+{
+ bool v_i_f;
+ bool g0_i_f;
+ bool g1_i_f;
+ bool mxr_i_f;
+ u32 temp_reg = 0;
+
+ v_i_f = (readl(mixer_base + S5P_MXR_INT_STATUS)
+ & S5P_MXR_VP_INT_FIRED) ? true : false;
+ g0_i_f = (readl(mixer_base + S5P_MXR_INT_STATUS)
+ & S5P_MXR_GRP0_INT_FIRED) ? true : false;
+ g1_i_f = (readl(mixer_base + S5P_MXR_INT_STATUS)
+ & S5P_MXR_GRP1_INT_FIRED) ? true : false;
+ mxr_i_f = (readl(mixer_base + S5P_MXR_INT_STATUS)
+ & S5P_MXR_INT_FIRED) ? true : false;
+
+ if (mxr_i_f) {
+ temp_reg |= S5P_MXR_INT_FIRED;
+
+ if (v_i_f) {
+ temp_reg |= S5P_MXR_VP_INT_FIRED;
+ printk("VP fifo under run!!\n\r");
+ }
+
+ if (g0_i_f) {
+ temp_reg |= S5P_MXR_GRP0_INT_FIRED;
+ printk("GRP0 fifo under run!!\n\r");
+ }
+
+ if (g1_i_f) {
+ temp_reg |= S5P_MXR_GRP1_INT_FIRED;
+ printk("GRP1 fifo under run!!\n\r");
+ }
+
+ writel(temp_reg, mixer_base + S5P_MXR_INT_STATUS);
+ }
+
+ return IRQ_HANDLED;
+}
+
+int __init __s5p_mixer_probe(struct platform_device *pdev, u32 res_num)
+{
+
+ struct resource *res;
+ size_t size;
+ int ret;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, res_num);
+
+ if (res == NULL) {
+ dev_err(&pdev->dev,
+ "failed to get memory region resource\n");
+ ret = -ENOENT;
+
+ }
+
+ size = (res->end - res->start) + 1;
+
+ mixer_mem = request_mem_region(res->start, size, pdev->name);
+
+ if (mixer_mem == NULL) {
+ dev_err(&pdev->dev,
+ "failed to get memory region\n");
+ ret = -ENOENT;
+
+ }
+
+ mixer_base = ioremap(res->start, size);
+
+ if (mixer_base == NULL) {
+ dev_err(&pdev->dev,
+ "failed to ioremap address region\n");
+ ret = -ENOENT;
+
+
+ }
+
+ return ret;
+
+}
+
+int __init __s5p_mixer_release(struct platform_device *pdev)
+{
+ iounmap(mixer_base);
+
+ /* remove memory region */
+
+ if (mixer_mem != NULL) {
+ if (release_resource(mixer_mem))
+ dev_err(&pdev->dev,
+ "Can't remove tvout drv !!\n");
+
+ kfree(mixer_mem);
+
+ mixer_mem = NULL;
+ }
+
+ return 0;
+}
diff --git a/drivers/media/video/samsung/tv20/s5pc100/vp_coeff_s5pc100.h b/drivers/media/video/samsung/tv20/s5pc100/vp_coeff_s5pc100.h
new file mode 100644
index 0000000..3ec0343
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/s5pc100/vp_coeff_s5pc100.h
@@ -0,0 +1,310 @@
+/* linux/drivers/media/video/samsung/tv20/s5pc100/vp_coeff_s5pc100.h
+ *
+ * Video Processor coefficient header file for Samsung TVOut driver
+ *
+ * Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/* Horizontal Y 8tap */
+const signed char g_s_vp8tap_coef_y_h[] = {
+ /* VP_PP_H_NORMAL */
+ 0, 0, 0, 0, 127, 0, 0, 0,
+ 0, 1, -2, 8, 126, -6, 2, -1,
+ 0, 1, -5, 16, 125, -12, 4, -1,
+ 0, 2, -8, 25, 121, -16, 5, -1,
+ -1, 3, -10, 35, 114, -18, 6, -1,
+ -1, 4, -13, 46, 107, -20, 6, -1,
+ -1, 5, -16, 57, 99, -21, 6, -1,
+ -1, 5, -18, 68, 89, -20, 6, -1,
+ -1, 6, -20, 79, 79, -20, 6, -1,
+ -1, 6, -20, 89, 68, -18, 5, -1,
+ -1, 6, -21, 99, 57, -16, 5, -1,
+ -1, 6, -20, 107, 46, -13, 4, -1,
+ -1, 6, -18, 114, 35, -10, 3, -1,
+ -1, 5, -16, 121, 25, -8, 2, 0,
+ -1, 4, -12, 125, 16, -5, 1, 0,
+ -1, 2, -6, 126, 8, -2, 1, 0,
+
+ /* VP_PP_H_8_9 */
+ 0, 3, -7, 12, 112, 12, -7, 3,
+ -1, 3, -9, 19, 113, 6, -5, 2,
+ -1, 3, -11, 27, 111, 0, -3, 2,
+ -1, 4, -13, 35, 108, -5, -1, 1,
+ -1, 4, -14, 43, 104, -9, 0, 1,
+ -1, 5, -16, 52, 99, -12, 1, 0,
+ -1, 5, -17, 61, 92, -14, 2, 0,
+ 0, 4, -17, 69, 85, -16, 3, 0,
+ 0, 4, -17, 77, 77, -17, 4, 0,
+ 0, 3, -16, 85, 69, -17, 4, 0,
+ 0, 2, -14, 92, 61, -17, 5, -1,
+ 0, 1, -12, 99, 52, -16, 5, -1,
+ 1, 0, -9, 104, 43, -14, 4, -1,
+ 1, -1, -5, 108, 35, -13, 4, -1,
+ 2, -3, 0, 111, 27, -11, 3, -1,
+ 2, -5, 6, 113, 19, -9, 3, -1,
+
+ /* VP_PP_H_1_2 */
+ 0, -3, 0, 35, 64, 35, 0, -3,
+ 0, -3, 1, 38, 64, 32, -1, -3,
+ 0, -3, 2, 41, 63, 29, -2, -2,
+ 0, -4, 4, 43, 63, 27, -3, -2,
+ 0, -4, 5, 46, 62, 24, -3, -2,
+ 0, -4, 7, 49, 60, 21, -3, -2,
+ -1, -4, 9, 51, 59, 19, -4, -1,
+ -1, -4, 12, 53, 57, 16, -4, -1,
+ -1, -4, 14, 55, 55, 14, -4, -1,
+ -1, -4, 16, 57, 53, 12, -4, -1,
+ -1, -4, 19, 59, 51, 9, -4, -1,
+ -2, -3, 21, 60, 49, 7, -4, 0,
+ -2, -3, 24, 62, 46, 5, -4, 0,
+ -2, -3, 27, 63, 43, 4, -4, 0,
+ -2, -2, 29, 63, 41, 2, -3, 0,
+ -3, -1, 32, 64, 38, 1, -3, 0,
+
+ /* VP_PP_H_1_3 */
+ 0, 0, 10, 32, 44, 32, 10, 0,
+ -1, 0, 11, 33, 45, 31, 9, 0,
+ -1, 0, 12, 35, 45, 29, 8, 0,
+ -1, 1, 13, 36, 44, 28, 7, 0,
+ -1, 1, 15, 37, 44, 26, 6, 0,
+ -1, 2, 16, 38, 43, 25, 5, 0,
+ -1, 2, 18, 39, 43, 23, 5, -1,
+ -1, 3, 19, 40, 42, 22, 4, -1,
+ -1, 3, 21, 41, 41, 21, 3, -1,
+ -1, 4, 22, 42, 40, 19, 3, -1,
+ -1, 5, 23, 43, 39, 18, 2, -1,
+ 0, 5, 25, 43, 38, 16, 2, -1,
+ 0, 6, 26, 44, 37, 15, 1, -1,
+ 0, 7, 28, 44, 36, 13, 1, -1,
+ 0, 8, 29, 45, 35, 12, 0, -1,
+ 0, 9, 31, 45, 33, 11, 0, -1,
+
+ /* VP_PP_H_1_4 */
+ 0, 2, 13, 30, 38, 30, 13, 2,
+ 0, 3, 14, 30, 38, 29, 12, 2,
+ 0, 3, 15, 31, 38, 28, 11, 2,
+ 0, 4, 16, 32, 38, 27, 10, 1,
+ 0, 4, 17, 33, 37, 26, 10, 1,
+ 0, 5, 18, 34, 37, 24, 9, 1,
+ 0, 5, 19, 34, 37, 24, 8, 1,
+ 1, 6, 20, 35, 36, 22, 7, 1,
+ 1, 6, 21, 36, 36, 21, 6, 1,
+ 1, 7, 22, 36, 35, 20, 6, 1,
+ 1, 8, 24, 37, 34, 19, 5, 0,
+ 1, 9, 24, 37, 34, 18, 5, 0,
+ 1, 10, 26, 37, 33, 17, 4, 0,
+ 1, 10, 27, 38, 32, 16, 4, 0,
+ 2, 11, 28, 38, 31, 15, 3, 0,
+ 2, 12, 29, 38, 30, 14, 3, 0
+};
+
+/* Horizontal C 4tap */
+const signed char g_s_vp4tap_coef_c_h[] = {
+ /* VP_PP_H_NORMAL */
+ 0, 0, 128, 0,
+ 0, 5, 126, -3,
+ -1, 11, 124, -6,
+ -1, 19, 118, -8,
+ -2, 27, 111, -8,
+ -3, 37, 102, -8,
+ -4, 48, 92, -8,
+ -5, 59, 81, -7,
+ -6, 70, 70, -6,
+ -7, 81, 59, -5,
+ -8, 92, 48, -4,
+ -8, 102, 37, -3,
+ -8, 111, 27, -2,
+ -8, 118, 19, -1,
+ -6, 124, 11, -1,
+ -3, 126, 5, 0,
+
+ /* VP_PP_H_8_9 */
+ 0, 8, 112, 8,
+ -1, 13, 113, 3,
+ -2, 19, 111, 0,
+ -2, 26, 107, -3,
+ -3, 34, 101, -4,
+ -3, 42, 94, -5,
+ -4, 51, 86, -5,
+ -5, 60, 78, -5,
+ -5, 69, 69, -5,
+ -5, 78, 60, -5,
+ -5, 86, 51, -4,
+ -5, 94, 42, -3,
+ -4, 101, 34, -3,
+ -3, 107, 26, -2,
+ 0, 111, 19, -2,
+ 3, 113, 13, -1,
+
+ /* VP_PP_H_1_2 */
+ 0, 26, 76, 26,
+ 0, 30, 76, 22,
+ 0, 34, 75, 19,
+ 1, 38, 73, 16,
+ 1, 43, 71, 13,
+ 2, 47, 69, 10,
+ 3, 51, 66, 8,
+ 4, 55, 63, 6,
+ 5, 59, 59, 5,
+ 6, 63, 55, 4,
+ 8, 66, 51, 3,
+ 10, 69, 47, 2,
+ 13, 71, 43, 1,
+ 16, 73, 38, 1,
+ 19, 75, 34, 0,
+ 22, 76, 30, 0,
+
+ /* VP_PP_H_1_3 */
+ 0, 30, 68, 30,
+ 2, 33, 66, 27,
+ 3, 36, 66, 23,
+ 3, 39, 65, 21,
+ 4, 43, 63, 18,
+ 5, 46, 62, 15,
+ 6, 49, 60, 13,
+ 8, 52, 57, 11,
+ 9, 55, 55, 9,
+ 11, 57, 52, 8,
+ 13, 60, 49, 6,
+ 15, 62, 46, 5,
+ 18, 63, 43, 4,
+ 21, 65, 39, 3,
+ 23, 66, 36, 3,
+ 27, 66, 33, 2,
+
+ /* VP_PP_H_1_4 */
+ 0, 31, 66, 31,
+ 3, 34, 63, 28,
+ 4, 37, 62, 25,
+ 4, 40, 62, 22,
+ 5, 43, 61, 19,
+ 6, 46, 59, 17,
+ 7, 48, 58, 15,
+ 9, 51, 55, 13,
+ 11, 53, 53, 11,
+ 13, 55, 51, 9,
+ 15, 58, 48, 7,
+ 17, 59, 46, 6,
+ 19, 61, 43, 5,
+ 22, 62, 40, 4,
+ 25, 62, 37, 4,
+ 28, 63, 34, 3,
+};
+
+
+/* Vertical Y 8tap */
+const signed char g_s_vp4tap_coef_y_v[] = {
+ /* VP_PP_V_NORMAL */
+ 0, 0, 127, 0,
+ 0, 5, 126, -3,
+ -1, 11, 124, -6,
+ -1, 19, 118, -8,
+ -2, 27, 111, -8,
+ -3, 37, 102, -8,
+ -4, 48, 92, -8,
+ -5, 59, 81, -7,
+ -6, 70, 70, -6,
+ -7, 81, 59, -5,
+ -8, 92, 48, -4,
+ -8, 102, 37, -3,
+ -8, 111, 27, -2,
+ -8, 118, 19, -1,
+ -6, 124, 11, -1,
+ -3, 126, 5, 0,
+
+ /* VP_PP_V_5_6 */
+ 0, 11, 106, 11,
+ -2, 16, 107, 7,
+ -2, 22, 105, 3,
+ -2, 29, 101, 0,
+ -3, 36, 96, -1,
+ -3, 44, 90, -3,
+ -4, 52, 84, -4,
+ -4, 60, 76, -4,
+ -4, 68, 68, -4,
+ -4, 76, 60, -4,
+ -4, 84, 52, -4,
+ -3, 90, 44, -3,
+ -1, 96, 36, -3,
+ 0, 101, 29, -2,
+ 3, 105, 22, -2,
+ 7, 107, 16, -2,
+
+ /* VP_PP_V_3_4 */
+ 0, 15, 98, 15,
+ -2, 21, 97, 12,
+ -2, 26, 96, 8,
+ -2, 32, 93, 5,
+ -2, 39, 89, 2,
+ -2, 46, 84, 0,
+ -3, 53, 79, -1,
+ -2, 59, 73, -2,
+ -2, 66, 66, -2,
+ -2, 73, 59, -2,
+ -1, 79, 53, -3,
+ 0, 84, 46, -2,
+ 2, 89, 39, -2,
+ 5, 93, 32, -2,
+ 8, 96, 26, -2,
+ 12, 97, 21, -2,
+
+ /* VP_PP_V_1_2 */
+ 0, 26, 76, 26,
+ 0, 30, 76, 22,
+ 0, 34, 75, 19,
+ 1, 38, 73, 16,
+ 1, 43, 71, 13,
+ 2, 47, 69, 10,
+ 3, 51, 66, 8,
+ 4, 55, 63, 6,
+ 5, 59, 59, 5,
+ 6, 63, 55, 4,
+ 8, 66, 51, 3,
+ 10, 69, 47, 2,
+ 13, 71, 43, 1,
+ 16, 73, 38, 1,
+ 19, 75, 34, 0,
+ 22, 76, 30, 0,
+
+ /* VP_PP_V_1_3 */
+ 0, 30, 68, 30,
+ 2, 33, 66, 27,
+ 3, 36, 66, 23,
+ 3, 39, 65, 21,
+ 4, 43, 63, 18,
+ 5, 46, 62, 15,
+ 6, 49, 60, 13,
+ 8, 52, 57, 11,
+ 9, 55, 55, 9,
+ 11, 57, 52, 8,
+ 13, 60, 49, 6,
+ 15, 62, 46, 5,
+ 18, 63, 43, 4,
+ 21, 65, 39, 3,
+ 23, 66, 36, 3,
+ 27, 66, 33, 2,
+
+ /* VP_PP_V_1_4 */
+ 0, 31, 66, 31,
+ 3, 34, 63, 28,
+ 4, 37, 62, 25,
+ 4, 40, 62, 22,
+ 5, 43, 61, 19,
+ 6, 46, 59, 17,
+ 7, 48, 58, 15,
+ 9, 51, 55, 13,
+ 11, 53, 53, 11,
+ 13, 55, 51, 9,
+ 15, 58, 48, 7,
+ 17, 59, 46, 6,
+ 19, 61, 43, 5,
+ 22, 62, 40, 4,
+ 25, 62, 37, 4,
+ 28, 63, 34, 3
+};
+
diff --git a/drivers/media/video/samsung/tv20/s5pc100/vprocessor_s5pc100.c b/drivers/media/video/samsung/tv20/s5pc100/vprocessor_s5pc100.c
new file mode 100644
index 0000000..6a2a7ef
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/s5pc100/vprocessor_s5pc100.c
@@ -0,0 +1,809 @@
+/* linux/drivers/media/video/samsung/tv20/s5pc100/vprocessor_s5pc100.c
+ *
+ * Video Processor raw ftn file for Samsung TVOut driver
+ *
+ * Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+
+#include <linux/io.h>
+
+#include "tv_out_s5pc100.h"
+
+#include "regs/regs-vprocessor.h"
+#include "vp_coeff_s5pc100.h"
+
+#ifdef COFIG_TVOUT_RAW_DBG
+#define S5P_VP_DEBUG 1
+#endif
+
+#ifdef S5P_VP_DEBUG
+#define VPPRINTK(fmt, args...)\
+ printk(KERN_INFO "\t\t[VP] %s: " fmt, __func__ , ## args)
+#else
+#define VPPRINTK(fmt, args...)
+#endif
+
+static struct resource *vp_mem;
+void __iomem *vp_base;
+
+/*
+* set
+* - set functions are only called under running video processor
+* - after running set functions, it is need to run __s5p_vp_update() function
+* for update shadow registers
+*/
+void __s5p_vp_set_field_id(enum s5p_vp_field mode)
+{
+ VPPRINTK("%d\n\r", mode);
+
+ writel((mode == VPROC_TOP_FIELD) ?
+ vp_base + S5P_VP_FIELD_ID_TOP :
+ vp_base + S5P_VP_FIELD_ID_BOTTOM,
+ vp_base + S5P_VP_FIELD_ID);
+
+ VPPRINTK("0x%08x\n\r", readl(vp_base + S5P_VP_FIELD_ID));
+}
+
+enum s5p_tv_vp_err __s5p_vp_set_top_field_address(u32 top_y_addr,
+ u32 top_c_addr)
+{
+ VPPRINTK("0x%x, 0x%x\n\r", top_y_addr, top_c_addr);
+
+ if (VP_PTR_ILLEGAL(top_y_addr) || VP_PTR_ILLEGAL(top_c_addr)) {
+ VPPRINTK(" address is not double word align = 0x%x, 0x%x\n\r",
+ top_y_addr, top_c_addr);
+ return S5P_TV_VP_ERR_BASE_ADDRESS_MUST_DOUBLE_WORD_ALIGN;
+ }
+
+ writel(top_y_addr, vp_base + S5P_VP_TOP_Y_PTR);
+
+ writel(top_c_addr, vp_base + S5P_VP_TOP_C_PTR);
+
+
+ VPPRINTK("0x%x, 0x%x\n\r", readl(vp_base + S5P_VP_TOP_Y_PTR),
+ readl(vp_base + S5P_VP_TOP_C_PTR));
+
+ return VPROC_NO_ERROR;
+}
+
+enum s5p_tv_vp_err __s5p_vp_set_bottom_field_address(u32 bottom_y_addr,
+ u32 bottom_c_addr)
+{
+ VPPRINTK("0x%x, 0x%x\n\r", bottom_y_addr, bottom_c_addr);
+
+ if (VP_PTR_ILLEGAL(bottom_y_addr) || VP_PTR_ILLEGAL(bottom_c_addr)) {
+ VPPRINTK(" address is not double word align = 0x%x, 0x%x\n\r",
+ bottom_y_addr, bottom_c_addr);
+ return S5P_TV_VP_ERR_BASE_ADDRESS_MUST_DOUBLE_WORD_ALIGN;
+ }
+
+ writel(bottom_y_addr, vp_base + S5P_VP_BOT_Y_PTR);
+
+ writel(bottom_c_addr, vp_base + S5P_VP_BOT_C_PTR);
+
+
+ VPPRINTK("0x%x, 0x%x\n\r", readl(vp_base + S5P_VP_BOT_Y_PTR),
+ readl(vp_base + S5P_VP_BOT_C_PTR));
+
+ return VPROC_NO_ERROR;
+}
+
+
+enum s5p_tv_vp_err __s5p_vp_set_img_size(u32 img_width, u32 img_height)
+{
+ VPPRINTK("%d, %d\n\r", img_width, img_height);
+
+ if (VP_IMG_SIZE_ILLEGAL(img_width) ||
+ VP_IMG_SIZE_ILLEGAL(img_height / 2)) {
+ VPPRINTK(" image full size is not double word align\
+ = %d, %d\n\r",
+ img_width, img_height);
+ return S5P_TV_VP_ERR_BASE_ADDRESS_MUST_DOUBLE_WORD_ALIGN;
+ }
+
+ writel(VP_IMG_HSIZE(img_width) | VP_IMG_VSIZE(img_height),
+
+ vp_base + S5P_VP_IMG_SIZE_Y);
+
+ writel(VP_IMG_HSIZE(img_width) | VP_IMG_VSIZE(img_height / 2),
+ vp_base + S5P_VP_IMG_SIZE_C);
+
+ VPPRINTK("0x%x, 0x%x\n\r", readl(vp_base + S5P_VP_IMG_SIZE_Y),
+ readl(vp_base + S5P_VP_IMG_SIZE_C));
+
+ return VPROC_NO_ERROR;
+}
+
+void __s5p_vp_set_src_position(u32 src_off_x,
+ u32 src_x_fract_step,
+ u32 src_off_y)
+{
+ VPPRINTK("%d, %d, %d)\n\r", src_off_x, src_x_fract_step, src_off_y);
+
+ writel(VP_SRC_H_POSITION(src_off_x) |
+ VP_SRC_X_FRACT_STEP(src_x_fract_step),
+ vp_base + S5P_VP_SRC_H_POSITION);
+ writel(VP_SRC_V_POSITION(src_off_y), vp_base + S5P_VP_SRC_V_POSITION);
+
+ VPPRINTK("0x%x, 0x%x\n\r", readl(vp_base + S5P_VP_SRC_H_POSITION),
+ readl(vp_base + S5P_VP_SRC_V_POSITION));
+}
+
+void __s5p_vp_set_dest_position(u32 dst_off_x,
+ u32 dst_off_y)
+{
+ VPPRINTK("%d, %d)\n\r", dst_off_x, dst_off_y);
+
+
+ writel(VP_DST_H_POSITION(dst_off_x), vp_base + S5P_VP_DST_H_POSITION);
+ writel(VP_DST_V_POSITION(dst_off_y), vp_base + S5P_VP_DST_V_POSITION);
+
+ VPPRINTK("0x%x, 0x%x\n\r", readl(vp_base + S5P_VP_DST_H_POSITION),
+ readl(vp_base + S5P_VP_DST_V_POSITION));
+}
+
+void __s5p_vp_set_src_dest_size(u32 src_width,
+ u32 src_height,
+ u32 dst_width,
+ u32 dst_height,
+ bool ipc_2d)
+{
+ u32 h_ratio = (src_width << 16) / dst_width;
+ u32 v_ratio = (ipc_2d) ?
+ ((src_height << 17) / dst_height) :
+ ((src_height << 16) / dst_height);
+
+ VPPRINTK("(%d, %d, %d, %d)++\n\r", src_width, src_height,
+ dst_width, dst_height);
+
+ writel(VP_SRC_WIDTH(src_width), vp_base + S5P_VP_SRC_WIDTH);
+ writel(VP_SRC_HEIGHT(src_height), vp_base + S5P_VP_SRC_HEIGHT);
+ writel(VP_DST_WIDTH(dst_width), vp_base + S5P_VP_DST_WIDTH);
+ writel(VP_DST_HEIGHT(dst_height), vp_base + S5P_VP_DST_HEIGHT) ;
+ writel(VP_H_RATIO(h_ratio), vp_base + S5P_VP_H_RATIO);
+ writel(VP_V_RATIO(v_ratio), vp_base + S5P_VP_V_RATIO);
+
+ writel((ipc_2d) ? (readl(vp_base + S5P_VP_MODE) | VP_2D_IPC_ON) :
+ (readl(vp_base + S5P_VP_MODE) & ~VP_2D_IPC_ON),
+ vp_base + S5P_VP_MODE);
+
+ VPPRINTK("%d, %d, %d, %d, 0x%x, 0x%x\n\r",
+ readl(vp_base + S5P_VP_SRC_WIDTH),
+ readl(vp_base + S5P_VP_SRC_HEIGHT),
+ readl(vp_base + S5P_VP_DST_WIDTH),
+ readl(vp_base + S5P_VP_DST_HEIGHT),
+ readl(vp_base + S5P_VP_H_RATIO),
+ readl(vp_base + S5P_VP_V_RATIO));
+}
+
+enum s5p_tv_vp_err __s5p_vp_set_poly_filter_coef(
+ enum s5p_vp_poly_coeff poly_coeff,
+ signed char ch0,
+ signed char ch1,
+ signed char ch2,
+ signed char ch3)
+{
+ VPPRINTK("%d, %d, %d, %d, %d)\n\r", poly_coeff, ch0, ch1, ch2, ch3);
+
+ if (poly_coeff > VPROC_POLY4_C1_HH ||
+ poly_coeff < VPROC_POLY8_Y0_LL ||
+ (poly_coeff > VPROC_POLY8_Y3_HH &&
+ poly_coeff < VPROC_POLY4_Y0_LL)) {
+
+ VPPRINTK("invaild poly_coeff parameter \n\r");
+ return S5P_TV_VP_ERR_INVALID_PARAM;
+ }
+
+ writel((((0xff&ch0) << 24) | ((0xff&ch1) << 16) |
+ ((0xff&ch2) << 8) | (0xff&ch3)),
+ vp_base + S5P_VP_POLY8_Y0_LL + poly_coeff*4);
+
+ VPPRINTK("0x%08x, 0x%08x\n\r",
+ readl(vp_base + S5P_VP_POLY8_Y0_LL + poly_coeff*4),
+ vp_base + S5P_VP_POLY8_Y0_LL + poly_coeff*4);
+
+ return VPROC_NO_ERROR;
+}
+
+void __s5p_vp_set_poly_filter_coef_default(u32 h_ratio, u32 v_ratio)
+{
+ enum s5p_tv_vp_filter_h_pp e_h_filter;
+ enum s5p_tv_vp_filter_v_pp e_v_filter;
+ u8 *poly_flt_coeff;
+ int i, j;
+
+ VPPRINTK("%d, %d\n\r", h_ratio, v_ratio);
+
+ /*
+ * For the real interlace mode, the vertical ratio should be
+ * used after divided by 2. Because in the interlace mode,
+ * all the VP output is used for SDOUT display and it should
+ * be the same as one field of the progressive mode.
+ * Therefore the same filter coefficients should be used for
+ * the same the final output video.
+ * When half of the interlace V_RATIO is same as the progressive
+ * V_RATIO, the final output video scale is same. (20051104, ishan)
+ */
+
+ /*Horizontal Y 8tap */
+ /*Horizontal C 4tap */
+
+ if (h_ratio <= (0x1 << 16)) { /* 720->720 or zoom in */
+ e_h_filter = VPROC_PP_H_NORMAL;
+ }
+
+ else if (h_ratio <= (0x9 << 13)) /* 720->640 */
+ e_h_filter = VPROC_PP_H_8_9 ;
+
+ else if (h_ratio <= (0x1 << 17)) /* 2->1 */
+ e_h_filter = VPROC_PP_H_1_2;
+
+ else if (h_ratio <= (0x3 << 16)) /* 2->1 */
+ e_h_filter = VPROC_PP_H_1_3;
+ else
+ e_h_filter = VPROC_PP_H_1_4; /* 4->1 */
+
+ /* Vertical Y 4tap */
+ if (v_ratio <= (0x1 << 16)) /* 720->720 or zoom in*/
+ e_v_filter = VPROC_PP_V_NORMAL;
+ else if (v_ratio <= (0x3 << 15)) /* 6->5*/
+ e_v_filter = VPROC_PP_V_5_6;
+ else if (v_ratio <= (0x5 << 14)) /* 4->3*/
+ e_v_filter = VPROC_PP_V_3_4;
+ else if (v_ratio <= (0x1 << 17)) /* 2->1*/
+ e_v_filter = VPROC_PP_V_1_2;
+ else if (v_ratio <= (0x3 << 16)) /* 3->1*/
+ e_v_filter = VPROC_PP_V_1_3;
+ else /* 4->1*/
+ e_v_filter = VPROC_PP_V_1_4;
+
+ poly_flt_coeff = (u8 *)(g_s_vp8tap_coef_y_h + e_h_filter * 16 * 8);
+
+ for (i = 0; i < 4; i++) {
+ for (j = 0; j < 4; j++) {
+ __s5p_vp_set_poly_filter_coef(
+ VPROC_POLY8_Y0_LL + (i*4) + j,
+ *(poly_flt_coeff + 4*j*8 + (7 - i)),
+ *(poly_flt_coeff + (4*j + 1)*8 + (7 - i)),
+ *(poly_flt_coeff + (4*j + 2)*8 + (7 - i)),
+ *(poly_flt_coeff + (4*j + 3)*8 + (7 - i)));
+ }
+ }
+
+ poly_flt_coeff = (u8 *)(g_s_vp4tap_coef_c_h + e_h_filter * 16 * 4);
+
+ for (i = 0; i < 2; i++) {
+ for (j = 0; j < 4; j++) {
+ __s5p_vp_set_poly_filter_coef(
+ VPROC_POLY4_C0_LL + (i*4) + j,
+ *(poly_flt_coeff + 4*j*4 + (3 - i)),
+ *(poly_flt_coeff + (4*j + 1)*4 + (3 - i)),
+ *(poly_flt_coeff + (4*j + 2)*4 + (3 - i)),
+ *(poly_flt_coeff + (4*j + 3)*4 + (3 - i)));
+ }
+ }
+
+ poly_flt_coeff = (u8 *)(g_s_vp4tap_coef_y_v + e_v_filter * 16 * 4);
+
+ for (i = 0; i < 4; i++) {
+ for (j = 0; j < 4; j++) {
+ __s5p_vp_set_poly_filter_coef(
+ VPROC_POLY4_Y0_LL + (i*4) + j,
+ *(poly_flt_coeff + 4*j*4 + (3 - i)),
+ *(poly_flt_coeff + (4*j + 1)*4 + (3 - i)),
+ *(poly_flt_coeff + (4*j + 2)*4 + (3 - i)),
+ *(poly_flt_coeff + (4*j + 3)*4 + (3 - i)));
+ }
+ }
+
+ VPPRINTK("%d, %d\n\r", e_h_filter, e_v_filter);
+}
+
+void __s5p_vp_set_src_dest_size_with_default_poly_filter_coef(u32 src_width,
+ u32 src_height,
+ u32 dst_width,
+ u32 dst_height,
+ bool ipc_2d)
+{
+ u32 h_ratio = (src_width << 16) / dst_width;
+ u32 v_ratio = (ipc_2d) ? ((src_height << 17) / dst_height) :
+ ((src_height << 16) / dst_height);
+
+ __s5p_vp_set_src_dest_size(src_width, src_height, dst_width,
+ dst_height, ipc_2d);
+ __s5p_vp_set_poly_filter_coef_default(h_ratio, v_ratio);
+}
+
+enum s5p_tv_vp_err __s5p_vp_set_brightness_contrast_control(
+ enum s5p_vp_line_eq eq_num, u32 intc, u32 slope)
+{
+ VPPRINTK("%d, %d, %d\n\r", eq_num, intc, slope);
+
+ if (eq_num > VProc_LINE_EQ_7 || eq_num < VProc_LINE_EQ_0) {
+ VPPRINTK("invaild eq_num parameter \n\r");
+ return S5P_TV_VP_ERR_INVALID_PARAM;
+ }
+
+ writel(VP_LINE_INTC(intc) | VP_LINE_SLOPE(slope),
+
+ vp_base + S5P_PP_LINE_EQ0 + eq_num*4);
+
+ VPPRINTK("0x%08x, 0x%08x\n\r",
+ readl(vp_base + S5P_PP_LINE_EQ0 + eq_num*4),
+ vp_base + S5P_PP_LINE_EQ0 + eq_num*4);
+
+ return VPROC_NO_ERROR;
+}
+
+void __s5p_vp_set_brightness(bool brightness)
+{
+ unsigned short i;
+
+ VPPRINTK("%d\n\r", brightness);
+
+ g_vp_contrast_brightness =
+ VP_LINE_INTC_CLEAR(g_vp_contrast_brightness) |
+ VP_LINE_INTC(brightness);
+
+ for (i = 0; i < 8; i++)
+ writel(g_vp_contrast_brightness,
+ vp_base + S5P_PP_LINE_EQ0 + i*4);
+
+
+ VPPRINTK("%d\n\r", g_vp_contrast_brightness);
+}
+
+void __s5p_vp_set_contrast(u8 contrast)
+{
+ unsigned short i;
+
+ VPPRINTK("%d\n\r", contrast);
+
+ g_vp_contrast_brightness =
+ VP_LINE_SLOPE_CLEAR(g_vp_contrast_brightness) |
+ VP_LINE_SLOPE(contrast);
+
+ for (i = 0; i < 8; i++)
+ writel(g_vp_contrast_brightness,
+ vp_base + S5P_PP_LINE_EQ0 + i*4);
+
+
+ VPPRINTK("%d\n\r", g_vp_contrast_brightness);
+}
+
+enum s5p_tv_vp_err __s5p_vp_update(void)
+{
+ VPPRINTK("()\n\r");
+
+ writel(readl(vp_base + S5P_VP_SHADOW_UPDATE) |
+ S5P_VP_SHADOW_UPDATE_ENABLE,
+ vp_base + S5P_VP_SHADOW_UPDATE);
+
+ VPPRINTK("()\n\r");
+
+ return VPROC_NO_ERROR;
+}
+
+/*
+* get - get info
+*/
+enum s5p_vp_field __s5p_vp_get_field_id(void)
+{
+ VPPRINTK("()\n\r");
+ return (readl(vp_base + S5P_VP_FIELD_ID) == S5P_VP_FIELD_ID_BOTTOM) ?
+ VPROC_BOTTOM_FIELD : VPROC_TOP_FIELD;
+}
+
+/*
+* etc
+*/
+unsigned short __s5p_vp_get_update_status(void)
+{
+ VPPRINTK("()\n\r");
+ return readl(vp_base + S5P_VP_SHADOW_UPDATE) &
+ S5P_VP_SHADOW_UPDATE_ENABLE;
+}
+
+
+void __s5p_vp_init_field_id(enum s5p_vp_field mode)
+{
+ __s5p_vp_set_field_id(mode);
+}
+
+void __s5p_vp_init_op_mode(bool line_skip,
+ enum s5p_vp_mem_mode mem_mode,
+ enum s5p_vp_chroma_expansion chroma_exp,
+ enum s5p_vp_filed_id_toggle toggle_id)
+{
+ u32 temp_reg;
+ VPPRINTK("%d, %d, %d, %d\n\r", line_skip, mem_mode,
+ chroma_exp, toggle_id);
+
+ temp_reg = (line_skip) ? VP_LINE_SKIP_ON : VP_LINE_SKIP_OFF;
+ temp_reg |= (mem_mode == VPROC_2D_TILE_MODE) ?
+ VP_MEM_2D_MODE : VP_MEM_LINEAR_MODE;
+ temp_reg |= (chroma_exp == VPROC_USING_C_TOP_BOTTOM) ?
+ VP_CHROMA_USE_TOP_BOTTOM : VP_CHROMA_USE_TOP;
+ temp_reg |= (toggle_id == S5P_TV_VP_FILED_ID_TOGGLE_VSYNC) ?
+ VP_FIELD_ID_TOGGLE_VSYNC : VP_FIELD_ID_TOGGLE_USER;
+
+ writel(temp_reg, vp_base + S5P_VP_MODE);
+ VPPRINTK("0x%08x\n\r", readl(vp_base + S5P_VP_MODE));
+}
+
+void __s5p_vp_init_pixel_rate_control(enum s5p_vp_pxl_rate rate)
+{
+ VPPRINTK("%d\n\r", rate);
+
+ writel(VP_PEL_RATE_CTRL(rate), vp_base + S5P_VP_PER_RATE_CTRL);
+
+ VPPRINTK("0x%08x\n\r", readl(vp_base + S5P_VP_PER_RATE_CTRL));
+}
+
+enum s5p_tv_vp_err __s5p_vp_init_layer(u32 top_y_addr,
+ u32 top_c_addr,
+ u32 bottom_y_addr,
+ u32 bottom_c_addr,
+ enum s5p_endian_type src_img_endian,
+ u32 img_width,
+ u32 img_height,
+ u32 src_off_x,
+ u32 src_x_fract_step,
+ u32 src_off_y,
+ u32 src_width,
+ u32 src_height,
+ u32 dst_off_x,
+ u32 dst_off_y,
+ u32 dst_width,
+ u32 dst_height,
+ bool ipc_2d)
+{
+ enum s5p_tv_vp_err error = VPROC_NO_ERROR;
+
+ VPPRINTK("%d\n\r", src_img_endian);
+
+ writel(1, vp_base + S5P_VP_ENDIAN_MODE);
+
+ error = __s5p_vp_set_top_field_address(top_y_addr, top_c_addr);
+
+ if (error != VPROC_NO_ERROR)
+ return error;
+
+ error = __s5p_vp_set_bottom_field_address(bottom_y_addr,
+ bottom_c_addr);
+
+ if (error != VPROC_NO_ERROR)
+ return error;
+
+ error = __s5p_vp_set_img_size(img_width, img_height);
+
+ if (error != VPROC_NO_ERROR)
+ return error;
+
+ __s5p_vp_set_src_position(src_off_x, src_x_fract_step, src_off_y);
+
+ __s5p_vp_set_dest_position(dst_off_x, dst_off_y);
+
+ __s5p_vp_set_src_dest_size(src_width, src_height, dst_width,
+ dst_height, ipc_2d);
+
+ VPPRINTK("0x%08x\n\r", readl(vp_base + S5P_VP_ENDIAN_MODE));
+
+ return error;
+
+}
+
+enum s5p_tv_vp_err __s5p_vp_init_layer_def_poly_filter_coef(u32 top_y_addr,
+ u32 top_c_addr,
+ u32 bottom_y_addr,
+ u32 bottom_c_addr,
+ enum s5p_endian_type src_img_endian,
+ u32 img_width,
+ u32 img_height,
+ u32 src_off_x,
+ u32 src_x_fract_step,
+ u32 src_off_y,
+ u32 src_width,
+ u32 src_height,
+ u32 dst_off_x,
+ u32 dst_off_y,
+ u32 dst_width,
+ u32 dst_height,
+ bool ipc_2d)
+{
+ enum s5p_tv_vp_err error = VPROC_NO_ERROR;
+
+ u32 h_ratio = (src_width << 16) / dst_width;
+ u32 v_ratio = (ipc_2d) ? ((src_height << 17) / dst_height) :
+ ((src_height << 16) / dst_height);
+
+ __s5p_vp_set_poly_filter_coef_default(h_ratio, v_ratio);
+ error = __s5p_vp_init_layer(top_y_addr, top_c_addr,
+ bottom_y_addr, bottom_c_addr,
+ src_img_endian,
+ img_width, img_height,
+ src_off_x, src_x_fract_step, src_off_y,
+ src_width, src_height,
+ dst_off_x, dst_off_y,
+ dst_width, dst_height,
+ ipc_2d);
+ return error;
+}
+
+enum s5p_tv_vp_err __s5p_vp_init_poly_filter_coef(
+ enum s5p_vp_poly_coeff poly_coeff,
+ signed char ch0,
+ signed char ch1,
+ signed char ch2,
+ signed char ch3)
+{
+ return __s5p_vp_set_poly_filter_coef(poly_coeff, ch0, ch1, ch2, ch3);
+}
+
+void __s5p_vp_init_bypass_post_process(bool bypass)
+{
+ VPPRINTK("%d\n\r", bypass);
+
+ writel((bypass) ? VP_BY_PASS_ENABLE : VP_BY_PASS_DISABLE,
+ vp_base + S5P_PP_BYPASS);
+
+ VPPRINTK("0x%08x\n\r", readl(vp_base + S5P_PP_BYPASS));
+}
+
+enum s5p_tv_vp_err __s5p_vp_init_csc_coef(enum s5p_vp_csc_coeff csc_coeff,
+ u32 coeff)
+{
+ VPPRINTK("%d, %d\n\r", csc_coeff, coeff);
+
+ if (csc_coeff > VPROC_CSC_CR2CR_COEF ||
+ csc_coeff < VPROC_CSC_Y2Y_COEF) {
+ VPPRINTK("invaild csc_coeff parameter \n\r");
+ return S5P_TV_VP_ERR_INVALID_PARAM;
+ }
+
+ writel(VP_CSC_COEF(coeff),
+ vp_base + S5P_PP_CSC_Y2Y_COEF + csc_coeff*4);
+
+ VPPRINTK("0x%08x\n\r",
+ readl(vp_base + S5P_PP_CSC_Y2Y_COEF + csc_coeff*4));
+
+ return VPROC_NO_ERROR;
+}
+
+void __s5p_vp_init_saturation(u32 sat)
+{
+ VPPRINTK("%d\n\r", sat);
+
+ writel(VP_SATURATION(sat), vp_base + S5P_PP_SATURATION);
+
+ VPPRINTK("0x%08x\n\r", readl(vp_base + S5P_PP_SATURATION));
+}
+
+void __s5p_vp_init_sharpness(u32 th_h_noise,
+ enum s5p_vp_sharpness_control sharpness)
+{
+ VPPRINTK("%d, %d\n\r", th_h_noise, sharpness);
+
+ writel(VP_TH_HNOISE(th_h_noise) | VP_SHARPNESS(sharpness),
+ vp_base + S5P_PP_SHARPNESS);
+
+ VPPRINTK("0x%08x\n\r", readl(vp_base + S5P_PP_SHARPNESS));
+}
+
+enum s5p_tv_vp_err __s5p_vp_init_brightness_contrast_control(
+ enum s5p_vp_line_eq eq_num, u32 intc, u32 slope)
+{
+ return __s5p_vp_set_brightness_contrast_control(eq_num, intc, slope);
+}
+
+void __s5p_vp_init_brightness(bool brightness)
+{
+ __s5p_vp_set_brightness(brightness);
+}
+
+
+void __s5p_vp_init_contrast(u8 contrast)
+{
+ __s5p_vp_set_contrast(contrast);
+}
+
+void __s5p_vp_init_brightness_offset(u32 offset)
+{
+ VPPRINTK("%d\n\r", offset);
+
+ writel(VP_BRIGHT_OFFSET(offset), vp_base + S5P_PP_BRIGHT_OFFSET);
+
+ VPPRINTK("0x%08x\n\r", readl(vp_base + S5P_PP_BRIGHT_OFFSET));
+}
+
+void __s5p_vp_init_csc_control(bool sub_y_offset_en, bool csc_en)
+{
+ u32 temp_reg;
+ VPPRINTK("%d, %d\n\r", sub_y_offset_en, csc_en);
+
+ temp_reg = (sub_y_offset_en) ? VP_SUB_Y_OFFSET_ENABLE :
+ VP_SUB_Y_OFFSET_DISABLE;
+ temp_reg |= (csc_en) ? VP_CSC_ENABLE : VP_CSC_DISABLE;
+ writel(temp_reg, vp_base + S5P_PP_CSC_EN);
+
+ VPPRINTK("0x%08x\n\r", readl(vp_base + S5P_PP_CSC_EN));
+}
+
+enum s5p_tv_vp_err __s5p_vp_init_csc_coef_default(enum s5p_vp_csc_type csc_type)
+{
+ VPPRINTK("%d\n\r", csc_type);
+
+ switch (csc_type) {
+
+ case VPROC_CSC_SD_HD:
+ writel(Y2Y_COEF_601_TO_709, vp_base + S5P_PP_CSC_Y2Y_COEF);
+ writel(CB2Y_COEF_601_TO_709, vp_base + S5P_PP_CSC_CB2Y_COEF);
+ writel(CR2Y_COEF_601_TO_709, vp_base + S5P_PP_CSC_CR2Y_COEF);
+ writel(Y2CB_COEF_601_TO_709, vp_base + S5P_PP_CSC_Y2CB_COEF);
+ writel(CB2CB_COEF_601_TO_709, vp_base + S5P_PP_CSC_CB2CB_COEF);
+ writel(CR2CB_COEF_601_TO_709, vp_base + S5P_PP_CSC_CR2CB_COEF);
+ writel(Y2CR_COEF_601_TO_709, vp_base + S5P_PP_CSC_Y2CR_COEF);
+ writel(CB2CR_COEF_601_TO_709, vp_base + S5P_PP_CSC_CB2CR_COEF);
+ writel(CR2CR_COEF_601_TO_709, vp_base + S5P_PP_CSC_CR2CR_COEF);
+ break;
+
+ case VPROC_CSC_HD_SD:
+ writel(Y2Y_COEF_709_TO_601, vp_base + S5P_PP_CSC_Y2Y_COEF);
+ writel(CB2Y_COEF_709_TO_601, vp_base + S5P_PP_CSC_CB2Y_COEF);
+ writel(CR2Y_COEF_709_TO_601, vp_base + S5P_PP_CSC_CR2Y_COEF);
+ writel(Y2CB_COEF_709_TO_601, vp_base + S5P_PP_CSC_Y2CB_COEF);
+ writel(CB2CB_COEF_709_TO_601, vp_base + S5P_PP_CSC_CB2CB_COEF);
+ writel(CR2CB_COEF_709_TO_601, vp_base + S5P_PP_CSC_CR2CB_COEF);
+ writel(Y2CR_COEF_709_TO_601, vp_base + S5P_PP_CSC_Y2CR_COEF);
+ writel(CB2CR_COEF_709_TO_601, vp_base + S5P_PP_CSC_CB2CR_COEF);
+ writel(CR2CR_COEF_709_TO_601, vp_base + S5P_PP_CSC_CR2CR_COEF);
+ break;
+
+ default:
+ VPPRINTK("invalid csc_type parameter = %d\n\r", csc_type);
+ return S5P_TV_VP_ERR_INVALID_PARAM;
+ break;
+ }
+
+ VPPRINTK("0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x,\
+ 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n\r",
+
+ readl(vp_base + S5P_PP_CSC_Y2Y_COEF),
+ readl(vp_base + S5P_PP_CSC_CB2Y_COEF),
+ readl(vp_base + S5P_PP_CSC_CR2Y_COEF),
+ readl(vp_base + S5P_PP_CSC_Y2CB_COEF),
+ readl(vp_base + S5P_PP_CSC_CB2CB_COEF),
+ readl(vp_base + S5P_PP_CSC_CR2CB_COEF),
+ readl(vp_base + S5P_PP_CSC_Y2CR_COEF),
+ readl(vp_base + S5P_PP_CSC_CB2CR_COEF),
+ readl(vp_base + S5P_PP_CSC_CR2CR_COEF));
+
+ return VPROC_NO_ERROR;
+}
+
+/*
+* start - start functions are only called under stopping video processor
+*/
+enum s5p_tv_vp_err __s5p_vp_start(void)
+{
+ enum s5p_tv_vp_err error = VPROC_NO_ERROR;
+
+ VPPRINTK("()\n\r");
+
+ writel(VP_ON_ENABLE, vp_base + S5P_VP_ENABLE);
+
+ error = __s5p_vp_update();
+
+ VPPRINTK("()\n\r");
+ return error;
+}
+
+/*
+* stop - stop functions are only called under running video processor
+*/
+enum s5p_tv_vp_err __s5p_vp_stop(void)
+{
+ enum s5p_tv_vp_err error = VPROC_NO_ERROR;
+
+ VPPRINTK("()\n\r");
+
+ writel((readl(vp_base + S5P_VP_ENABLE) & ~VP_ON_ENABLE),
+ vp_base + S5P_VP_ENABLE);
+
+ error = __s5p_vp_update();
+
+ while (!(readl(vp_base + S5P_VP_ENABLE) & VP_POWER_DOWN_RDY))
+ msleep(1);
+
+
+ return error;
+}
+
+/*
+* reset - reset function
+*/
+void __s5p_vp_sw_reset(void)
+{
+ VPPRINTK("()\n\r");
+
+ writel((readl(vp_base + S5P_VP_SRESET) | VP_SOFT_RESET),
+ vp_base + S5P_VP_SRESET);
+
+ while (readl(vp_base + S5P_VP_SRESET) & VP_SOFT_RESET)
+ msleep(10);
+
+
+ VPPRINTK("()\n\r");
+}
+
+int __init __s5p_vp_probe(struct platform_device *pdev, u32 res_num)
+{
+
+ struct resource *res;
+ size_t size;
+ int ret;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, res_num);
+
+ if (res == NULL) {
+ dev_err(&pdev->dev,
+ "failed to get memory region resource\n");
+ ret = -ENOENT;
+
+ }
+
+ size = (res->end - res->start) + 1;
+
+ vp_mem = request_mem_region(res->start, size, pdev->name);
+
+ if (vp_mem == NULL) {
+ dev_err(&pdev->dev,
+ "failed to get memory region\n");
+ ret = -ENOENT;
+
+ }
+
+ vp_base = ioremap(res->start, size);
+
+ if (vp_base == NULL) {
+ dev_err(&pdev->dev,
+ "failed to ioremap address region\n");
+ ret = -ENOENT;
+
+
+ }
+
+ return ret;
+
+}
+
+int __init __s5p_vp_release(struct platform_device *pdev)
+{
+ iounmap(vp_base);
+
+ /* remove memory region */
+
+ if (vp_mem != NULL) {
+ if (release_resource(vp_mem))
+ dev_err(&pdev->dev,
+ "Can't remove tvout drv !!\n");
+
+ kfree(vp_mem);
+
+ vp_mem = NULL;
+ }
+
+ return 0;
+}
+
diff --git a/drivers/media/video/samsung/tv20/s5pv210/cec_s5pv210.c b/drivers/media/video/samsung/tv20/s5pv210/cec_s5pv210.c
new file mode 100644
index 0000000..91568d8
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/s5pv210/cec_s5pv210.c
@@ -0,0 +1,294 @@
+/* linux/drivers/media/video/samsung/tv20/s5pv210/cec_s5pv210.c
+ *
+ * cec ftn file for Samsung TVOut driver
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include "regs/regs-cec.h"
+#include <linux/slab.h>
+#include <linux/mm.h>
+
+#include "../cec.h"
+
+#ifdef CECDEBUG
+#define CECPRINTK(fmt, args...) \
+ printk(KERN_INFO "\t\t[CEC] %s: " fmt, __func__ , ## args)
+#else
+#define CECPRINTK(fmt, args...)
+#endif
+
+static struct resource *cec_mem;
+void __iomem *cec_base;
+
+#define S5P_HDMI_FIN 24000000
+#define CEC_DIV_RATIO 187500
+
+/**
+ * Set CEC divider value.
+ */
+void __s5p_cec_set_divider(void)
+{
+ u32 div_ratio, reg, div_val;
+
+ div_ratio = S5P_HDMI_FIN/CEC_DIV_RATIO - 1;
+
+ reg = readl(S5P_HDMI_PHY_CONTROL);
+ reg = (reg & ~(0x3FF<<16)) | (div_ratio << 16);
+
+ writel(reg, S5P_HDMI_PHY_CONTROL);
+
+ div_val = CEC_DIV_RATIO * 0.00005 - 1;
+
+ writeb(0x0, cec_base + CEC_DIVISOR_3);
+ writeb(0x0, cec_base + CEC_DIVISOR_2);
+ writeb(0x0, cec_base + CEC_DIVISOR_1);
+ writeb(div_val, cec_base + CEC_DIVISOR_0);
+
+ CECPRINTK("CEC_DIVISOR_3 = 0x%08x\n", readb(cec_base + CEC_DIVISOR_3));
+ CECPRINTK("CEC_DIVISOR_2 = 0x%08x\n", readb(cec_base + CEC_DIVISOR_2));
+ CECPRINTK("CEC_DIVISOR_1 = 0x%08x\n", readb(cec_base + CEC_DIVISOR_1));
+ CECPRINTK("CEC_DIVISOR_0 = 0x%08x\n", readb(cec_base + CEC_DIVISOR_0));
+}
+
+/**
+ * Enable CEC Rx engine
+ */
+void __s5p_cec_enable_rx(void)
+{
+ u8 reg;
+ reg = readb(cec_base + CEC_RX_CTRL);
+ reg |= CEC_RX_CTRL_ENABLE;
+ writeb(reg, cec_base + CEC_RX_CTRL);
+
+ CECPRINTK("CEC_RX_CTRL = 0x%08x \n", readb(cec_base + CEC_RX_CTRL));
+}
+
+/**
+ * Mask CEC Rx interrupts
+ */
+void __s5p_cec_mask_rx_interrupts(void)
+{
+ u8 reg;
+ reg = readb(cec_base + CEC_IRQ_MASK);
+ reg |= CEC_IRQ_RX_DONE;
+ reg |= CEC_IRQ_RX_ERROR;
+ writeb(reg, cec_base + CEC_IRQ_MASK);
+
+ CECPRINTK("CEC_IRQ_MASK = 0x%08x \n", readb(cec_base + CEC_IRQ_MASK));
+}
+
+/**
+ * Unmask CEC Rx interrupts
+ */
+void __s5p_cec_unmask_rx_interrupts(void)
+{
+ u8 reg;
+ reg = readb(cec_base + CEC_IRQ_MASK);
+ reg &= ~CEC_IRQ_RX_DONE;
+ reg &= ~CEC_IRQ_RX_ERROR;
+ writeb(reg, cec_base + CEC_IRQ_MASK);
+
+ CECPRINTK("CEC_IRQ_MASK = 0x%08x \n", readb(cec_base + CEC_IRQ_MASK));
+}
+
+/**
+ * Mask CEC Tx interrupts
+ */
+void __s5p_cec_mask_tx_interrupts(void)
+{
+ u8 reg;
+ reg = readb(cec_base + CEC_IRQ_MASK);
+ reg |= CEC_IRQ_TX_DONE;
+ reg |= CEC_IRQ_TX_ERROR;
+ writeb(reg, cec_base + CEC_IRQ_MASK);
+
+ CECPRINTK("CEC_IRQ_MASK = 0x%08x \n", readb(cec_base + CEC_IRQ_MASK));
+
+}
+
+/**
+ * Unmask CEC Tx interrupts
+ */
+void __s5p_cec_unmask_tx_interrupts(void)
+{
+ u8 reg;
+ reg = readb(cec_base + CEC_IRQ_MASK);
+ reg &= ~CEC_IRQ_TX_DONE;
+ reg &= ~CEC_IRQ_TX_ERROR;
+ writeb(reg, cec_base + CEC_IRQ_MASK);
+
+ CECPRINTK("CEC_IRQ_MASK = 0x%08x \n", readb(cec_base + CEC_IRQ_MASK));
+}
+
+void __s5p_cec_reset(void)
+{
+ writeb(CEC_RX_CTRL_RESET, cec_base + CEC_RX_CTRL);
+ writeb(CEC_TX_CTRL_RESET, cec_base + CEC_TX_CTRL);
+
+ CECPRINTK("CEC_RX_CTRL = 0x%08x \n", readb(cec_base + CEC_RX_CTRL));
+ CECPRINTK("CEC_TX_CTRL = 0x%08x \n", readb(cec_base + CEC_TX_CTRL));
+}
+
+void __s5p_cec_tx_reset(void)
+{
+ writeb(CEC_TX_CTRL_RESET, cec_base + CEC_TX_CTRL);
+
+ CECPRINTK("CEC_TX_CTRL = 0x%08x \n", readb(cec_base + CEC_TX_CTRL));
+}
+
+void __s5p_cec_rx_reset(void)
+{
+ writeb(CEC_RX_CTRL_RESET, cec_base + CEC_RX_CTRL);
+ CECPRINTK("CEC_RX_CTRL = 0x%08x \n", readb(cec_base + CEC_RX_CTRL));
+}
+
+void __s5p_cec_threshold(void)
+{
+ writeb(CEC_FILTER_THRESHOLD, cec_base + CEC_RX_FILTER_TH);
+ writeb(0, cec_base + CEC_RX_FILTER_CTRL);
+ CECPRINTK("CEC_RX_FILTER_TH = 0x%08x \n",
+ readb(cec_base + CEC_RX_FILTER_TH));
+}
+
+void __s5p_cec_copy_packet(char *data, size_t count)
+{
+ int i = 0;
+ u8 reg;
+ /* copy packet to hardware buffer */
+ while (i < count) {
+ writeb(data[i], cec_base + (CEC_TX_BUFF0 + (i*4)));
+ i++;
+ }
+
+ /* set number of bytes to transfer */
+ writeb(count, cec_base + CEC_TX_BYTES);
+
+ __s5p_cec_set_tx_state(STATE_TX);
+
+ /* start transfer */
+ reg = readb(cec_base + CEC_TX_CTRL);
+
+ reg |= CEC_TX_CTRL_START;
+
+ /* if message is broadcast message - set corresponding bit */
+ if ((data[0] & CEC_MESSAGE_BROADCAST_MASK) == CEC_MESSAGE_BROADCAST)
+ reg |= CEC_TX_CTRL_BCAST;
+ else
+ reg &= ~CEC_TX_CTRL_BCAST;
+
+ /* set number of retransmissions */
+ reg |= 0x50;
+
+ writeb(reg, cec_base + CEC_TX_CTRL);
+}
+
+void __s5p_cec_set_addr(u32 addr)
+{
+ writeb(addr & 0x0F, cec_base + CEC_LOGIC_ADDR);
+
+}
+
+u32 __s5p_cec_get_status(void)
+{
+ u32 status = 0;
+
+ status = readb(cec_base + CEC_STATUS_0);
+ status |= readb(cec_base + CEC_STATUS_1) << 8;
+ status |= readb(cec_base + CEC_STATUS_2) << 16;
+ status |= readb(cec_base + CEC_STATUS_3) << 24;
+
+ CECPRINTK("status = 0x%x!\n", status);
+
+ return status;
+}
+
+void __s5p_clr_pending_tx(void)
+{
+ /* clear interrupt pending bit */
+ writeb(CEC_IRQ_TX_DONE | CEC_IRQ_TX_ERROR, cec_base + CEC_IRQ_CLEAR);
+}
+
+void __s5p_clr_pending_rx(void)
+{
+ /* clear interrupt pending bit */
+ writeb(CEC_IRQ_RX_DONE | CEC_IRQ_RX_ERROR, cec_base + CEC_IRQ_CLEAR);
+}
+
+void __s5p_cec_get_rx_buf(u32 size, u8 *buffer)
+{
+ u32 i = 0;
+
+ while (i < size) {
+ buffer[i] = readb(cec_base + CEC_RX_BUFF0 + (i * 4));
+ i++;
+ }
+}
+
+void __init __s5p_cec_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ size_t size;
+ int ret;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ if (res == NULL) {
+ dev_err(&pdev->dev,
+ "failed to get memory region resource for cec\n");
+ ret = -ENOENT;
+
+ }
+
+ size = (res->end - res->start) + 1;
+
+ cec_mem = request_mem_region(res->start, size, pdev->name);
+
+ if (cec_mem == NULL) {
+ dev_err(&pdev->dev,
+ "failed to get memory region for cec\n");
+ ret = -ENOENT;
+
+ }
+
+ cec_base = ioremap(res->start, size);
+
+ if (cec_base == NULL) {
+ dev_err(&pdev->dev,
+ "failed to ioremap address region for cec\n");
+ ret = -ENOENT;
+
+
+ }
+
+}
+
+int __init __s5p_cec_release(struct platform_device *pdev)
+{
+ iounmap(cec_base);
+
+ /* remove memory region */
+ if (cec_mem != NULL) {
+ if (release_resource(cec_mem))
+ dev_err(&pdev->dev,
+ "Can't remove tvout drv !!\n");
+
+ kfree(cec_mem);
+
+ cec_mem = NULL;
+ }
+
+ return 0;
+}
+
diff --git a/drivers/media/video/samsung/tv20/s5pv210/cec_s5pv210.h b/drivers/media/video/samsung/tv20/s5pv210/cec_s5pv210.h
new file mode 100644
index 0000000..a5e6abf
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/s5pv210/cec_s5pv210.h
@@ -0,0 +1,23 @@
+/* linux/drivers/media/video/samsung/tv20/s5pv210/cec_s5pv210.h
+ *
+ * cec ftn header for Samsung TVOut driver
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef _LINUX_CEC_H_
+#define _LINUX_CEC_H_
+
+#define CEC_IOC_MAGIC 'c'
+
+/**
+ * CEC device request code to set logical address.
+ */
+#define CEC_IOC_SETLADDR _IOW(CEC_IOC_MAGIC, 0, unsigned int)
+
+#endif /* _LINUX_CEC_H_ */
diff --git a/drivers/media/video/samsung/tv20/s5pv210/hdcp_s5pv210.c b/drivers/media/video/samsung/tv20/s5pv210/hdcp_s5pv210.c
new file mode 100644
index 0000000..25ab4c5
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/s5pv210/hdcp_s5pv210.c
@@ -0,0 +1,1790 @@
+/* linux/drivers/media/video/samsung/tv20/s5pv210/hdcp_s5pv210.c
+ *
+ * hdcp raw ftn file for Samsung TVOut driver
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/wait.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include <plat/gpio-cfg.h>
+
+#include <mach/regs-gpio.h>
+#include <mach/gpio.h>
+
+#include "../ddc.h"
+#include "tv_out_s5pv210.h"
+#include "regs/regs-hdmi.h"
+
+/* for Operation check */
+#ifdef COFIG_TVOUT_RAW_DBG
+#define S5P_HDCP_DEBUG 1
+#define S5P_HDCP_I2C_DEBUG 1
+#define S5P_HDCP_AUTH_DEBUG 1
+#endif
+
+#ifdef S5P_HDCP_DEBUG
+#define HDCPPRINTK(fmt, args...) \
+ printk(KERN_INFO "\t\t[HDCP] %s: " fmt, __func__ , ## args)
+#else
+#define HDCPPRINTK(fmt, args...)
+#endif
+
+/* for authentication key check */
+#ifdef S5P_HDCP_AUTH_DEBUG
+#define AUTHPRINTK(fmt, args...) \
+ printk("\t\t\t[AUTHKEY] %s: " fmt, __func__ , ## args)
+#else
+#define AUTHPRINTK(fmt, args...)
+#endif
+
+enum hdmi_run_mode {
+ DVI_MODE,
+ HDMI_MODE
+};
+
+enum hdmi_resolution {
+ SD480P,
+ SD480I,
+ WWSD480P,
+ HD720P,
+ SD576P,
+ WWSD576P,
+ HD1080I
+};
+
+enum hdmi_color_bar_type {
+ HORIZONTAL,
+ VERTICAL
+};
+
+enum hdcp_event {
+ /* Stop HDCP */
+ HDCP_EVENT_STOP,
+ /* Start HDCP*/
+ HDCP_EVENT_START,
+ /* Start to read Bksv, Bcaps */
+ HDCP_EVENT_READ_BKSV_START,
+ /* Start to write Aksv, An */
+ HDCP_EVENT_WRITE_AKSV_START,
+ /* Start to check if Ri is equal to Rj */
+ HDCP_EVENT_CHECK_RI_START,
+ /* Start 2nd authentication process */
+ HDCP_EVENT_SECOND_AUTH_START
+};
+
+enum hdcp_state {
+ NOT_AUTHENTICATED,
+ RECEIVER_READ_READY,
+ BCAPS_READ_DONE,
+ BKSV_READ_DONE,
+ AN_WRITE_DONE,
+ AKSV_WRITE_DONE,
+ FIRST_AUTHENTICATION_DONE,
+ SECOND_AUTHENTICATION_RDY,
+ RECEIVER_FIFOLSIT_READY,
+ SECOND_AUTHENTICATION_DONE,
+};
+
+/*
+ * Below CSC_TYPE is temporary. CSC_TYPE enum.
+ * may be included in SetSD480pVars_60Hz etc.
+ *
+ * LR : Limited Range (16~235)
+ * FR : Full Range (0~255)
+ */
+enum hdmi_intr_src {
+ WAIT_FOR_ACTIVE_RX,
+ WDT_FOR_REPEATER,
+ EXCHANGE_KSV,
+ UPDATE_P_VAL,
+ UPDATE_R_VAL,
+ AUDIO_OVERFLOW,
+ AUTHEN_ACK,
+ UNKNOWN_INT
+};
+
+struct s5p_hdcp_info {
+ bool is_repeater;
+ bool hpd_status;
+ u32 time_out;
+ u32 hdcp_enable;
+
+ spinlock_t lock;
+ spinlock_t reset_lock;
+
+ struct i2c_client *client;
+
+ wait_queue_head_t waitq;
+ enum hdcp_event event;
+ enum hdcp_state auth_status;
+
+ struct work_struct work;
+};
+
+static struct s5p_hdcp_info hdcp_info = {
+ .is_repeater = false,
+ .time_out = 0,
+ .hdcp_enable = false,
+ .client = NULL,
+ .event = HDCP_EVENT_STOP,
+ .auth_status = NOT_AUTHENTICATED,
+
+};
+
+#define HDCP_RI_OFFSET 0x08
+#define INFINITE 0xffffffff
+
+#define HDMI_SYS_ENABLE (1 << 0)
+#define HDMI_ASP_ENABLE (1 << 2)
+#define HDMI_ASP_DISABLE (~HDMI_ASP_ENABLE)
+
+#define MAX_DEVS_EXCEEDED (0x1 << 7)
+#define MAX_CASCADE_EXCEEDED (0x1 << 3)
+
+#define MAX_CASCADE_EXCEEDED_ERROR (-1)
+#define MAX_DEVS_EXCEEDED_ERROR (-2)
+#define REPEATER_ILLEGAL_DEVICE_ERROR (-3)
+#define REPEATER_TIMEOUT_ERROR (-4)
+
+#define AINFO_SIZE 1
+#define BCAPS_SIZE 1
+#define BSTATUS_SIZE 2
+#define SHA_1_HASH_SIZE 20
+
+#define KSV_FIFO_READY (0x1 << 5)
+
+/* spmoon for test : it's not in manual */
+#define SET_HDCP_KSV_WRITE_DONE (0x1 << 3)
+#define CLEAR_HDCP_KSV_WRITE_DONE (~SET_HDCP_KSV_WRITE_DONE)
+
+#define SET_HDCP_KSV_LIST_EMPTY (0x1 << 2)
+#define CLEAR_HDCP_KSV_LIST_EMPTY (~SET_HDCP_KSV_LIST_EMPTY)
+#define SET_HDCP_KSV_END (0x1 << 1)
+#define CLEAR_HDCP_KSV_END (~SET_HDCP_KSV_END)
+#define SET_HDCP_KSV_READ (0x1 << 0)
+#define CLEAR_HDCP_KSV_READ (~SET_HDCP_KSV_READ)
+
+#define SET_HDCP_SHA_VALID_READY (0x1 << 1)
+#define CLEAR_HDCP_SHA_VALID_READY (~SET_HDCP_SHA_VALID_READY)
+#define SET_HDCP_SHA_VALID (0x1 << 0)
+#define CLEAR_HDCP_SHA_VALID (~SET_HDCP_SHA_VALID)
+
+#define TRANSMIT_EVERY_VSYNC (0x1 << 1)
+
+/* must be checked */
+static bool sw_reset;
+static bool is_dvi;
+static bool av_mute;
+static bool audio_en;
+
+void s5p_hdmi_set_audio(bool en)
+{
+ if (en)
+ audio_en = true;
+ else
+ audio_en = false;
+}
+
+int s5p_hdcp_is_reset(void)
+{
+ int ret = 0;
+
+ if (spin_is_locked(&hdcp_info.reset_lock))
+ return 1;
+
+ return ret;
+}
+
+int s5p_hdmi_set_dvi(bool en)
+{
+ if (en)
+ is_dvi = true;
+ else
+ is_dvi = false;
+
+ return 0;
+}
+
+int s5p_hdmi_set_mute(bool en)
+{
+ if (en)
+ av_mute = true;
+ else
+ av_mute = false;
+
+ return 0;
+}
+
+int s5p_hdmi_get_mute(void)
+{
+ return av_mute ? true : false;
+}
+
+int s5p_hdmi_audio_enable(bool en)
+{
+ u8 reg;
+
+ if (!is_dvi) {
+ reg = readl(hdmi_base + S5P_HDMI_CON_0);
+
+ if (en) {
+ reg |= ASP_EN;
+ writel(HDMI_TRANS_EVERY_SYNC , hdmi_base + S5P_AUI_CON);
+ } else {
+ reg &= ~ASP_EN;
+ writel(HDMI_DO_NOT_TANS , hdmi_base + S5P_AUI_CON);
+ }
+
+ writel(reg, hdmi_base + S5P_HDMI_CON_0);
+ }
+
+ return 0;
+}
+
+void s5p_hdmi_mute_en(bool en)
+{
+ if (!av_mute) {
+ if (en) {
+ __s5p_hdmi_video_set_bluescreen(true, 0, 0, 0);
+ s5p_hdmi_audio_enable(false);
+ } else {
+ __s5p_hdmi_video_set_bluescreen(false, 0, 0, 0);
+ if (audio_en)
+ s5p_hdmi_audio_enable(true);
+ }
+ }
+}
+
+/*
+ * 1st Authentication step func.
+ * Write the Ainfo data to Rx
+ */
+static bool write_ainfo(void)
+{
+ int ret = 0;
+ u8 ainfo[2];
+
+ ainfo[0] = HDCP_Ainfo;
+ ainfo[1] = 0;
+
+ ret = ddc_write(ainfo, 2);
+ if (ret < 0)
+ HDCPPRINTK("Can't write ainfo data through i2c bus\n");
+
+ return (ret < 0) ? false : true;
+}
+
+/*
+ * Write the An data to Rx
+ */
+static bool write_an(void)
+{
+ int ret = 0;
+ u8 an[AN_SIZE+1];
+
+ an[0] = HDCP_An;
+
+ an[1] = readb(hdmi_base + S5P_HDCP_An_0_0);
+ an[2] = readb(hdmi_base + S5P_HDCP_An_0_1);
+ an[3] = readb(hdmi_base + S5P_HDCP_An_0_2);
+ an[4] = readb(hdmi_base + S5P_HDCP_An_0_3);
+ an[5] = readb(hdmi_base + S5P_HDCP_An_1_0);
+ an[6] = readb(hdmi_base + S5P_HDCP_An_1_1);
+ an[7] = readb(hdmi_base + S5P_HDCP_An_1_2);
+ an[8] = readb(hdmi_base + S5P_HDCP_An_1_3);
+
+ ret = ddc_write(an, AN_SIZE + 1);
+ if (ret < 0)
+ HDCPPRINTK("Can't write an data through i2c bus\n");
+
+#ifdef S5P_HDCP_AUTH_DEBUG
+ {
+ u16 i = 0;
+ for (i = 1; i < AN_SIZE + 1; i++)
+ AUTHPRINTK("HDCPAn[%d]: 0x%x \n", i, an[i]);
+
+ }
+#endif
+
+ return (ret < 0) ? false : true;
+}
+
+/*
+ * Write the Aksv data to Rx
+ */
+static bool write_aksv(void)
+{
+ int ret = 0;
+ u8 aksv[AKSV_SIZE+1];
+
+ aksv[0] = HDCP_Aksv;
+
+ aksv[1] = readb(hdmi_base + S5P_HDCP_AKSV_0_0);
+ aksv[2] = readb(hdmi_base + S5P_HDCP_AKSV_0_1);
+ aksv[3] = readb(hdmi_base + S5P_HDCP_AKSV_0_2);
+ aksv[4] = readb(hdmi_base + S5P_HDCP_AKSV_0_3);
+ aksv[5] = readb(hdmi_base + S5P_HDCP_AKSV_1);
+
+ if (aksv[1] == 0 &&
+ aksv[2] == 0 &&
+ aksv[3] == 0 &&
+ aksv[4] == 0 &&
+ aksv[5] == 0)
+ return false;
+
+ ret = ddc_write(aksv, AKSV_SIZE + 1);
+ if (ret < 0)
+ HDCPPRINTK("Can't write aksv data through i2c bus\n");
+
+#ifdef S5P_HDCP_AUTH_DEBUG
+ {
+ u16 i = 0;
+ for (i = 1; i < AKSV_SIZE + 1; i++)
+ AUTHPRINTK("HDCPAksv[%d]: 0x%x\n", i, aksv[i]);
+
+ }
+#endif
+
+ return (ret < 0) ? false : true;
+}
+
+static bool read_bcaps(void)
+{
+ int ret = 0;
+ u8 bcaps[BCAPS_SIZE] = {0};
+
+ ret = ddc_read(HDCP_Bcaps, bcaps, BCAPS_SIZE);
+
+ if (ret < 0) {
+ HDCPPRINTK("Can't read bcaps data from i2c bus\n");
+ return false;
+ }
+
+ writel(bcaps[0], hdmi_base + S5P_HDCP_BCAPS);
+
+ HDCPPRINTK("BCAPS(from i2c) : 0x%08x\n", bcaps[0]);
+
+ if (bcaps[0] & REPEATER_SET)
+ hdcp_info.is_repeater = true;
+ else
+ hdcp_info.is_repeater = false;
+
+ HDCPPRINTK("attached device type : %s !! \n\r",
+ hdcp_info.is_repeater ? "REPEATER" : "SINK");
+ HDCPPRINTK("BCAPS(from sfr) = 0x%08x\n",
+ readl(hdmi_base + S5P_HDCP_BCAPS));
+
+ return true;
+}
+
+static bool read_again_bksv(void)
+{
+ u8 bk_sv[BKSV_SIZE] = {0, 0, 0, 0, 0};
+ u8 i = 0;
+ u8 j = 0;
+ u32 no_one = 0;
+ u32 no_zero = 0;
+ u32 result = 0;
+ int ret = 0;
+
+ ret = ddc_read(HDCP_Bksv, bk_sv, BKSV_SIZE);
+
+ if (ret < 0) {
+ HDCPPRINTK("Can't read bk_sv data from i2c bus\n");
+ return false;
+ }
+
+#ifdef S5P_HDCP_AUTH_DEBUG
+ for (i = 0; i < BKSV_SIZE; i++)
+ AUTHPRINTK("i2c read : Bksv[%d]: 0x%x\n", i, bk_sv[i]);
+#endif
+
+ for (i = 0; i < BKSV_SIZE; i++) {
+
+ for (j = 0; j < 8; j++) {
+
+ result = bk_sv[i] & (0x1 << j);
+
+ if (result == 0)
+ no_zero += 1;
+ else
+ no_one += 1;
+ }
+ }
+
+ if ((no_zero == 20) && (no_one == 20)) {
+ HDCPPRINTK("Suucess: no_zero, and no_one is 20\n");
+
+ writel(bk_sv[0], hdmi_base + S5P_HDCP_BKSV_0_0);
+ writel(bk_sv[1], hdmi_base + S5P_HDCP_BKSV_0_1);
+ writel(bk_sv[2], hdmi_base + S5P_HDCP_BKSV_0_2);
+ writel(bk_sv[3], hdmi_base + S5P_HDCP_BKSV_0_3);
+ writel(bk_sv[4], hdmi_base + S5P_HDCP_BKSV_1);
+
+#ifdef S5P_HDCP_AUTH_DEBUG
+ for (i = 0; i < BKSV_SIZE; i++)
+ AUTHPRINTK("set reg : Bksv[%d]: 0x%x\n", i, bk_sv[i]);
+
+ /*
+ writel(HDCP_ENC_ENABLE, hdmi_base + S5P_ENC_EN);
+ */
+#endif
+ return true;
+ } else {
+ HDCPPRINTK("Failed: no_zero or no_one is NOT 20\n");
+ return false;
+ }
+}
+
+static bool read_bksv(void)
+{
+ u8 bk_sv[BKSV_SIZE] = {0, 0, 0, 0, 0};
+
+ int i = 0;
+ int j = 0;
+
+ u32 no_one = 0;
+ u32 no_zero = 0;
+ u32 result = 0;
+ u32 count = 0;
+ int ret = 0;
+
+ ret = ddc_read(HDCP_Bksv, bk_sv, BKSV_SIZE);
+
+ if (ret < 0) {
+ HDCPPRINTK("Can't read bk_sv data from i2c bus\n");
+ return false;
+ }
+
+#ifdef S5P_HDCP_AUTH_DEBUG
+ for (i = 0; i < BKSV_SIZE; i++)
+ AUTHPRINTK("i2c read : Bksv[%d]: 0x%x\n", i, bk_sv[i]);
+#endif
+
+ for (i = 0; i < BKSV_SIZE; i++) {
+
+ for (j = 0; j < 8; j++) {
+
+ result = bk_sv[i] & (0x1 << j);
+
+ if (result == 0)
+ no_zero++;
+ else
+ no_one++;
+ }
+ }
+
+ if ((no_zero == 20) && (no_one == 20)) {
+
+ writel(bk_sv[0], hdmi_base + S5P_HDCP_BKSV_0_0);
+ writel(bk_sv[1], hdmi_base + S5P_HDCP_BKSV_0_1);
+ writel(bk_sv[2], hdmi_base + S5P_HDCP_BKSV_0_2);
+ writel(bk_sv[3], hdmi_base + S5P_HDCP_BKSV_0_3);
+ writel(bk_sv[4], hdmi_base + S5P_HDCP_BKSV_1);
+
+#ifdef S5P_HDCP_AUTH_DEBUG
+ for (i = 0; i < BKSV_SIZE; i++)
+ AUTHPRINTK("set reg : Bksv[%d]: 0x%x\n", i, bk_sv[i]);
+#endif
+
+ HDCPPRINTK("Success: no_zero, and no_one is 20\n");
+
+ } else {
+
+ HDCPPRINTK("Failed: no_zero or no_one is NOT 20\n");
+
+ while (!read_again_bksv()) {
+
+ count++;
+
+ mdelay(200);
+
+ if (count == 14)
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/*
+ * Compare the R value of Tx with that of Rx
+ */
+static bool compare_r_val(void)
+{
+ int ret = 0;
+ u8 ri[2] = {0, 0};
+ u8 rj[2] = {0, 0};
+ u16 i;
+
+ for (i = 0; i < R_VAL_RETRY_CNT; i++) {
+
+ if (hdcp_info.auth_status < AKSV_WRITE_DONE) {
+ ret = false;
+ break;
+ }
+
+ /* Read R value from Tx */
+ ri[0] = readl(hdmi_base + S5P_HDCP_Ri_0);
+ ri[1] = readl(hdmi_base + S5P_HDCP_Ri_1);
+
+ /* Read R value from Rx */
+ ret = ddc_read(HDCP_Ri, rj, 2);
+ if (ret < 0) {
+ HDCPPRINTK("Can't read r data from i2c bus\n");
+ return false;
+ }
+
+#ifdef S5P_HDCP_AUTH_DEBUG
+ AUTHPRINTK("retries :: %d\n", i);
+ printk(KERN_INFO "\t\t\t Rx(ddc) ->");
+ printk(KERN_INFO "rj[0]: 0x%02x, rj[1]: 0x%02x\n",
+ rj[0], rj[1]);
+ printk(KERN_INFO "\t\t\t Tx(register) ->");
+ printk(KERN_INFO "ri[0]: 0x%02x, ri[1]: 0x%02x\n",
+ ri[0], ri[1]);
+#endif
+
+ /* Compare R value */
+ if ((ri[0] == rj[0]) && (ri[1] == rj[1]) && (ri[0] | ri[1])) {
+ writel(Ri_MATCH_RESULT__YES,
+ hdmi_base + S5P_HDCP_CHECK_RESULT);
+ HDCPPRINTK("R0, R0' is matched!!\n");
+ ret = true;
+ break;
+ } else {
+ writel(Ri_MATCH_RESULT__NO,
+ hdmi_base + S5P_HDCP_CHECK_RESULT);
+ HDCPPRINTK("R0, R0' is not matched!!\n");
+ ret = false;
+ }
+
+ ri[0] = 0;
+ ri[1] = 0;
+ rj[0] = 0;
+ rj[1] = 0;
+
+ }
+
+ if (!ret) {
+ hdcp_info.event = HDCP_EVENT_STOP;
+ hdcp_info.auth_status = NOT_AUTHENTICATED;
+ }
+
+ return ret ? true : false;
+}
+
+
+/*
+ * Enable/Disable Software HPD control
+ */
+void sw_hpd_enable(bool enable)
+{
+ u8 reg;
+
+ reg = readb(hdmi_base + S5P_HPD);
+ reg &= ~HPD_SW_ENABLE;
+
+ if (enable)
+ writeb(reg | HPD_SW_ENABLE, hdmi_base + S5P_HPD);
+ else
+ writeb(reg, hdmi_base + S5P_HPD);
+}
+
+/*
+ * Set Software HPD level
+ *
+ * @param level [in] if 0 - low;othewise, high
+ */
+void set_sw_hpd(bool level)
+{
+ u8 reg;
+
+ reg = readb(hdmi_base + S5P_HPD);
+ reg &= ~HPD_ON;
+
+ if (level)
+ writeb(reg | HPD_ON, hdmi_base + S5P_HPD);
+ else
+ writeb(reg, hdmi_base + S5P_HPD);
+}
+
+
+/*
+ * Reset Authentication
+ */
+void reset_authentication(void)
+{
+ u8 reg;
+
+ spin_lock_irq(&hdcp_info.reset_lock);
+
+ hdcp_info.time_out = INFINITE;
+ hdcp_info.event = HDCP_EVENT_STOP;
+ hdcp_info.auth_status = NOT_AUTHENTICATED;
+
+
+ /* Disable hdcp */
+ writeb(0x0, hdmi_base + S5P_HDCP_CTRL1);
+ writeb(0x0, hdmi_base + S5P_HDCP_CTRL2);
+
+ s5p_hdmi_mute_en(true);
+
+ /* Disable encryption */
+ HDCPPRINTK("Stop Encryption by reset!!\n");
+ writeb(HDCP_ENC_DIS, hdmi_base + S5P_ENC_EN);
+
+ HDCPPRINTK("Now reset authentication\n");
+
+ /* disable hdmi status enable reg. */
+ reg = readb(hdmi_base + S5P_STATUS_EN);
+ reg &= HDCP_STATUS_DIS_ALL;
+ writeb(reg, hdmi_base + S5P_STATUS_EN);
+
+ /* clear all result */
+
+ writeb(CLEAR_ALL_RESULTS, hdmi_base + S5P_HDCP_CHECK_RESULT);
+
+ /*
+ * 1. Mask HPD plug and unplug interrupt
+ * disable HPD INT
+ */
+ sw_reset = true;
+ reg = s5p_hdmi_get_enabled_interrupt();
+
+ s5p_hdmi_disable_interrupts(HDMI_IRQ_HPD_PLUG);
+ s5p_hdmi_disable_interrupts(HDMI_IRQ_HPD_UNPLUG);
+
+ /* 2. Enable software HPD */
+ sw_hpd_enable(true);
+
+ /* 3. Make software HPD logical 0 */
+ set_sw_hpd(false);
+
+ /* 4. Make software HPD logical 1 */
+ set_sw_hpd(true);
+
+ /* 5. Disable software HPD */
+ sw_hpd_enable(false);
+
+ /* 6. Unmask HPD plug and unplug interrupt */
+ if (reg & 1<<HDMI_IRQ_HPD_PLUG)
+ s5p_hdmi_enable_interrupts(HDMI_IRQ_HPD_PLUG);
+ if (reg & 1<<HDMI_IRQ_HPD_UNPLUG)
+ s5p_hdmi_enable_interrupts(HDMI_IRQ_HPD_UNPLUG);
+
+
+ sw_reset = false;
+
+ /* clear result */
+#if 0
+ writel(Ri_MATCH_RESULT__NO, hdmi_base + S5P_HDCP_CHECK_RESULT);
+ writel(readl(hdmi_base + S5P_HDMI_CON_0) & HDMI_DIS,
+ hdmi_base + S5P_HDMI_CON_0);
+ writel(readl(hdmi_base + S5P_HDMI_CON_0) | HDMI_EN,
+ hdmi_base + S5P_HDMI_CON_0);
+#endif
+ writel(CLEAR_ALL_RESULTS, hdmi_base + S5P_HDCP_CHECK_RESULT);
+
+ /* set hdcp_int enable */
+ reg = readb(hdmi_base + S5P_STATUS_EN);
+ reg |= WTFORACTIVERX_INT_OCCURRED |
+ WATCHDOG_INT_OCCURRED |
+ EXCHANGEKSV_INT_OCCURRED |
+ UPDATE_RI_INT_OCCURRED;
+ writeb(reg, hdmi_base + S5P_STATUS_EN);
+
+ /* HDCP Enable */
+ writeb(CP_DESIRED_EN, hdmi_base + S5P_HDCP_CTRL1);
+
+ spin_unlock_irq(&hdcp_info.reset_lock);
+}
+
+/*
+ * Set the timing parameter for load e-fuse key.
+ */
+
+/* TODO: must use clk_get for pclk rate */
+#define PCLK_D_RATE_FOR_HDCP 166000000
+
+u32 efuse_ceil(u32 val, u32 time)
+{
+ u32 res;
+
+ res = val / time;
+
+ if (val % time)
+ res += 1;
+
+ return res;
+}
+
+#if 0
+static void hdcp_efuse_timing(void)
+{
+ u32 time, val;
+
+ /* TODO: must use clk_get for pclk rate */
+ time = 1000000000/PCLK_D_RATE_FOR_HDCP;
+
+ val = efuse_ceil(EFUSE_ADDR_WIDTH, time);
+ writeb(val, hdmi_base + S5P_EFUSE_ADDR_WIDTH);
+
+ val = efuse_ceil(EFUSE_SIGDEV_ASSERT, time);
+ writeb(val, hdmi_base + S5P_EFUSE_SIGDEV_ASSERT);
+
+ val = efuse_ceil(EFUSE_SIGDEV_DEASSERT, time);
+ writeb(val, hdmi_base + S5P_EFUSE_SIGDEV_DEASSERT);
+
+ val = efuse_ceil(EFUSE_PRCHG_ASSERT, time);
+ writeb(val, hdmi_base + S5P_EFUSE_PRCHG_ASSERT);
+
+ val = efuse_ceil(EFUSE_PRCHG_DEASSERT, time);
+ writeb(val, hdmi_base + S5P_EFUSE_PRCHG_DEASSERT);
+
+ val = efuse_ceil(EFUSE_FSET_ASSERT, time);
+ writeb(val, hdmi_base + S5P_EFUSE_FSET_ASSERT);
+
+ val = efuse_ceil(EFUSE_FSET_DEASSERT, time);
+ writeb(val, hdmi_base + S5P_EFUSE_FSET_DEASSERT);
+
+ val = efuse_ceil(EFUSE_SENSING, time);
+ writeb(val, hdmi_base + S5P_EFUSE_SENSING);
+
+ val = efuse_ceil(EFUSE_SCK_ASSERT, time);
+ writeb(val, hdmi_base + S5P_EFUSE_SCK_ASSERT);
+
+ val = efuse_ceil(EFUSE_SCK_DEASSERT, time);
+ writeb(val, hdmi_base + S5P_EFUSE_SCK_DEASSERT);
+
+ val = efuse_ceil(EFUSE_SDOUT_OFFSET, time);
+ writeb(val, hdmi_base + S5P_EFUSE_SDOUT_OFFSET);
+
+ val = efuse_ceil(EFUSE_READ_OFFSET, time);
+ writeb(val, hdmi_base + S5P_EFUSE_READ_OFFSET);
+
+}
+#endif
+
+/*
+ * load hdcp key from e-fuse mem.
+ */
+static int hdcp_loadkey(void)
+{
+ u8 status;
+
+#if 0
+ hdcp_efuse_timing();
+#endif
+ /* read HDCP key from E-Fuse */
+ writeb(EFUSE_CTRL_ACTIVATE, hdmi_base + S5P_EFUSE_CTRL);
+
+ do {
+ status = readb(hdmi_base + S5P_EFUSE_STATUS);
+ } while (!(status & EFUSE_ECC_DONE));
+
+ if (readb(hdmi_base + S5P_EFUSE_STATUS) & EFUSE_ECC_FAIL) {
+ HDCPPRINTK("Can't load key from fuse ctrl.\n");
+ return -EINVAL;
+ }
+
+ return 0;
+
+}
+
+/*
+ * Start encryption
+ */
+static void start_encryption(void)
+{
+ u32 time_out = 100;
+
+ if (readl(hdmi_base + S5P_HDCP_CHECK_RESULT) ==
+ Ri_MATCH_RESULT__YES) {
+
+ while (time_out) {
+
+ if (readl(hdmi_base + S5P_STATUS) & AUTHENTICATED) {
+ writel(HDCP_ENC_ENABLE,
+ hdmi_base + S5P_ENC_EN);
+ HDCPPRINTK("Encryption start!!\n");
+ s5p_hdmi_mute_en(false);
+ break;
+ } else {
+ time_out--;
+ mdelay(1);
+ }
+ }
+ } else {
+ writel(HDCP_ENC_DISABLE, hdmi_base + S5P_ENC_EN);
+ s5p_hdmi_mute_en(true);
+ HDCPPRINTK("Encryption stop!!\n");
+ }
+}
+
+/*
+ * Check whether Rx is repeater or not
+ */
+static int check_repeater(void)
+{
+ int ret = 0;
+
+ u8 i = 0;
+ u16 j = 0;
+
+ u8 bcaps[BCAPS_SIZE] = {0};
+ u8 status[BSTATUS_SIZE] = {0, 0};
+ u8 rx_v[SHA_1_HASH_SIZE] = {0};
+ u8 ksv_list[HDCP_MAX_DEVS*HDCP_KSV_SIZE] = {0};
+
+ u32 dev_cnt;
+ u32 stat;
+
+ bool ksv_fifo_ready = false;
+
+ memset(rx_v, 0x0, SHA_1_HASH_SIZE);
+ memset(ksv_list, 0x0, HDCP_MAX_DEVS*HDCP_KSV_SIZE);
+
+ while (j <= 50) {
+ ret = ddc_read(HDCP_Bcaps,
+ bcaps, BCAPS_SIZE);
+
+ if (ret < 0) {
+ HDCPPRINTK("Can't read bcaps data from i2c bus\n");
+ return false;
+ }
+
+ if (bcaps[0] & KSV_FIFO_READY) {
+ HDCPPRINTK("ksv fifo is ready\n");
+ ksv_fifo_ready = true;
+ writel(bcaps[0], hdmi_base + S5P_HDCP_BCAPS);
+ break;
+ } else {
+ HDCPPRINTK("ksv fifo is not ready\n");
+ ksv_fifo_ready = false;
+ mdelay(100);
+ j++;
+ }
+
+ bcaps[0] = 0;
+ }
+
+ if (!ksv_fifo_ready)
+ return REPEATER_TIMEOUT_ERROR;
+
+ /*
+ * Check MAX_CASCADE_EXCEEDED
+ * or MAX_DEVS_EXCEEDED indicator
+ */
+ ret = ddc_read(HDCP_BStatus,
+ status, BSTATUS_SIZE);
+
+ if (ret < 0) {
+ HDCPPRINTK("Can't read status data from i2c bus\n");
+ return false;
+ }
+
+ /* MAX_CASCADE_EXCEEDED || MAX_DEVS_EXCEEDED */
+ if (status[1] & MAX_CASCADE_EXCEEDED) {
+ HDCPPRINTK("MAX_CASCADE_EXCEEDED\n");
+ return MAX_CASCADE_EXCEEDED_ERROR;
+ } else if (status[0] & MAX_DEVS_EXCEEDED) {
+ HDCPPRINTK("MAX_CASCADE_EXCEEDED\n");
+ return MAX_DEVS_EXCEEDED_ERROR;
+ }
+
+ writel(status[0], hdmi_base + S5P_HDCP_BSTATUS_0);
+ writel(status[1], hdmi_base + S5P_HDCP_BSTATUS_1);
+
+ /* Read KSV list */
+ dev_cnt = status[0] & 0x7f;
+
+ HDCPPRINTK("status[0] :0x%08x, status[1] :0x%08x!!\n",
+ status[0], status[1]);
+
+ if (dev_cnt) {
+
+ u32 val = 0;
+
+ /* read ksv */
+ ret = ddc_read(HDCP_KSVFIFO, ksv_list,
+ dev_cnt * HDCP_KSV_SIZE);
+ if (ret < 0) {
+ HDCPPRINTK("Can't read ksv fifo!!\n");
+ return false;
+ }
+
+ /* write ksv */
+ for (i = 0; i < dev_cnt - 1; i++) {
+
+ writel(ksv_list[(i*5) + 0],
+ hdmi_base + S5P_HDCP_RX_KSV_0_0);
+ writel(ksv_list[(i*5) + 1],
+ hdmi_base + S5P_HDCP_RX_KSV_0_1);
+ writel(ksv_list[(i*5) + 2],
+ hdmi_base + S5P_HDCP_RX_KSV_0_2);
+ writel(ksv_list[(i*5) + 3],
+ hdmi_base + S5P_HDCP_RX_KSV_0_3);
+ writel(ksv_list[(i*5) + 4],
+ hdmi_base + S5P_HDCP_RX_KSV_0_4);
+
+ mdelay(1);
+ writel(SET_HDCP_KSV_WRITE_DONE,
+ hdmi_base + S5P_HDCP_RX_KSV_LIST_CTRL);
+ mdelay(1);
+
+ stat = readl(hdmi_base + S5P_HDCP_RX_KSV_LIST_CTRL);
+
+ if (!(stat & SET_HDCP_KSV_READ))
+ return false;
+
+ HDCPPRINTK("HDCP_RX_KSV_1 = 0x%x\n\r",
+ readl(hdmi_base + S5P_HDCP_RX_KSV_LIST_CTRL));
+ HDCPPRINTK("i : %d, dev_cnt : %d, val = 0x%08x\n",
+ i, dev_cnt, val);
+ }
+
+ writel(ksv_list[(i*5) + 0], hdmi_base + S5P_HDCP_RX_KSV_0_0);
+ writel(ksv_list[(i*5) + 1], hdmi_base + S5P_HDCP_RX_KSV_0_1);
+ writel(ksv_list[(i*5) + 2], hdmi_base + S5P_HDCP_RX_KSV_0_2);
+ writel(ksv_list[(i*5) + 3], hdmi_base + S5P_HDCP_RX_KSV_0_3);
+ writel(ksv_list[(i*5) + 4], hdmi_base + S5P_HDCP_RX_KSV_0_4);
+
+ mdelay(1);
+
+ /* end of ksv */
+ val = SET_HDCP_KSV_END|SET_HDCP_KSV_WRITE_DONE;
+ writel(val, hdmi_base + S5P_HDCP_RX_KSV_LIST_CTRL);
+
+ HDCPPRINTK("HDCP_RX_KSV_1 = 0x%x\n\r",
+ readl(hdmi_base + S5P_HDCP_RX_KSV_LIST_CTRL));
+ HDCPPRINTK("i : %d, dev_cnt : %d, val = 0x%08x\n",
+ i, dev_cnt, val);
+
+ } else {
+
+ /*
+ mdelay(200);
+ */
+
+ writel(SET_HDCP_KSV_LIST_EMPTY,
+ hdmi_base + S5P_HDCP_RX_KSV_LIST_CTRL);
+ }
+
+
+ /* Read SHA-1 from receiver */
+ ret = ddc_read(HDCP_SHA1,
+ rx_v, SHA_1_HASH_SIZE);
+
+ if (ret < 0) {
+ HDCPPRINTK("Can't read sha_1_hash data from i2c bus\n");
+ return false;
+ }
+
+#ifdef S5P_HDCP_DEBUG
+ for (i = 0; i < SHA_1_HASH_SIZE; i++)
+ HDCPPRINTK("SHA_1 rx :: %x\n", rx_v[i]);
+#endif
+
+ /* write SHA-1 to register */
+ writeb(rx_v[0], hdmi_base + S5P_HDCP_RX_SHA1_0_0);
+ writeb(rx_v[1], hdmi_base + S5P_HDCP_RX_SHA1_0_1);
+ writeb(rx_v[2], hdmi_base + S5P_HDCP_RX_SHA1_0_2);
+ writeb(rx_v[3], hdmi_base + S5P_HDCP_RX_SHA1_0_3);
+ writeb(rx_v[4], hdmi_base + S5P_HDCP_RX_SHA1_1_0);
+ writeb(rx_v[5], hdmi_base + S5P_HDCP_RX_SHA1_1_1);
+ writeb(rx_v[6], hdmi_base + S5P_HDCP_RX_SHA1_1_2);
+ writeb(rx_v[7], hdmi_base + S5P_HDCP_RX_SHA1_1_3);
+ writeb(rx_v[8], hdmi_base + S5P_HDCP_RX_SHA1_2_0);
+ writeb(rx_v[9], hdmi_base + S5P_HDCP_RX_SHA1_2_1);
+ writeb(rx_v[10], hdmi_base + S5P_HDCP_RX_SHA1_2_2);
+ writeb(rx_v[11], hdmi_base + S5P_HDCP_RX_SHA1_2_3);
+ writeb(rx_v[12], hdmi_base + S5P_HDCP_RX_SHA1_3_0);
+ writeb(rx_v[13], hdmi_base + S5P_HDCP_RX_SHA1_3_1);
+ writeb(rx_v[14], hdmi_base + S5P_HDCP_RX_SHA1_3_2);
+ writeb(rx_v[15], hdmi_base + S5P_HDCP_RX_SHA1_3_3);
+ writeb(rx_v[16], hdmi_base + S5P_HDCP_RX_SHA1_4_0);
+ writeb(rx_v[17], hdmi_base + S5P_HDCP_RX_SHA1_4_1);
+ writeb(rx_v[18], hdmi_base + S5P_HDCP_RX_SHA1_4_2);
+ writeb(rx_v[19], hdmi_base + S5P_HDCP_RX_SHA1_4_3);
+
+ /* SHA write done, and wait for SHA computation being done */
+ mdelay(1);
+
+ /* check authentication success or not */
+ stat = readb(hdmi_base + S5P_HDCP_AUTH_STATUS);
+
+ HDCPPRINTK("auth status %d\n", stat);
+
+ if (stat & SET_HDCP_SHA_VALID_READY) {
+
+ stat = readb(hdmi_base + S5P_HDCP_AUTH_STATUS);
+
+ if (stat & SET_HDCP_SHA_VALID)
+ ret = true;
+ else
+ ret = false;
+ } else {
+ HDCPPRINTK("SHA not ready 0x%x \n\r", stat);
+ ret = false;
+ }
+
+ /* clear all validate bit */
+ writeb(0x0, hdmi_base + S5P_HDCP_AUTH_STATUS);
+
+ return ret;
+
+}
+
+static bool try_read_receiver(void)
+{
+ u16 i = 0;
+ bool ret = false;
+
+ s5p_hdmi_mute_en(true);
+
+ for (i = 0; i < 400; i++) {
+
+ msleep(250);
+
+ if (hdcp_info.auth_status != RECEIVER_READ_READY) {
+
+ HDCPPRINTK("hdcp stat. changed!!"
+ "failed attempt no = %d\n\r", i);
+
+ return false;
+ }
+
+ ret = read_bcaps();
+
+ if (ret) {
+ HDCPPRINTK("succeeded at attempt no= %d \n\r", i);
+
+ return true;
+ } else
+ HDCPPRINTK("can't read bcaps!!"
+ "failed attempt no=%d\n\r", i);
+ }
+
+ return false;
+}
+
+/*
+ * stop - stop functions are only called under running HDCP
+ */
+bool __s5p_stop_hdcp(void)
+{
+ u32 sfr_val = 0;
+
+ HDCPPRINTK("HDCP ftn. Stop!!\n");
+#if 0
+ s5p_hdmi_disable_interrupts(HDMI_IRQ_HPD_PLUG);
+ s5p_hdmi_disable_interrupts(HDMI_IRQ_HPD_UNPLUG);
+#endif
+ s5p_hdmi_disable_interrupts(HDMI_IRQ_HDCP);
+
+ hdcp_protocol_status = 0;
+
+ hdcp_info.time_out = INFINITE;
+ hdcp_info.event = HDCP_EVENT_STOP;
+ hdcp_info.auth_status = NOT_AUTHENTICATED;
+ hdcp_info.hdcp_enable = false;
+
+ /*
+ hdcp_info.client = NULL;
+ */
+
+ /* 3. disable hdcp control reg. */
+ sfr_val = readl(hdmi_base + S5P_HDCP_CTRL1);
+ sfr_val &= (ENABLE_1_DOT_1_FEATURE_DIS
+ & CLEAR_REPEATER_TIMEOUT
+ & EN_PJ_DIS
+ & CP_DESIRED_DIS);
+ writel(sfr_val, hdmi_base + S5P_HDCP_CTRL1);
+
+ /* 1-3. disable hdmi hpd reg. */
+ sw_hpd_enable(false);
+
+ /* 1-2. disable hdmi status enable reg. */
+ sfr_val = readl(hdmi_base + S5P_STATUS_EN);
+ sfr_val &= HDCP_STATUS_DIS_ALL;
+ writel(sfr_val, hdmi_base + S5P_STATUS_EN);
+
+ /* 1-1. clear all status pending */
+ sfr_val = readl(hdmi_base + S5P_STATUS);
+ sfr_val |= HDCP_STATUS_EN_ALL;
+ writel(sfr_val, hdmi_base + S5P_STATUS);
+
+ /* disable encryption */
+ HDCPPRINTK("Stop Encryption by Stop!!\n");
+ writel(HDCP_ENC_DISABLE, hdmi_base + S5P_ENC_EN);
+ s5p_hdmi_mute_en(true);
+
+ /* clear result */
+ writel(Ri_MATCH_RESULT__NO, hdmi_base + S5P_HDCP_CHECK_RESULT);
+ writel(CLEAR_ALL_RESULTS, hdmi_base + S5P_HDCP_CHECK_RESULT);
+
+ /* hdmi disable */
+#if 0
+ sfr_val = readl(hdmi_base + S5P_HDMI_CON_0);
+ sfr_val &= ~(PWDN_ENB_NORMAL | HDMI_EN | ASP_EN);
+ writel(sfr_val, hdmi_base + S5P_HDMI_CON_0);
+ */
+ HDCPPRINTK("\tSTATUS \t0x%08x\n", readl(hdmi_base + S5P_STATUS));
+ HDCPPRINTK("\tSTATUS_EN \t0x%08x\n",
+ readl(hdmi_base + S5P_STATUS_EN));
+ HDCPPRINTK("\tHPD \t0x%08x\n", readl(hdmi_base + S5P_HPD));
+ HDCPPRINTK("\tHDCP_CTRL \t0x%08x\n",
+ readl(hdmi_base + S5P_HDCP_CTRL1));
+ HDCPPRINTK("\tMODE_SEL \t0x%08x\n",
+ readl(hdmi_base + S5P_MODE_SEL));
+ HDCPPRINTK("\tENC_EN \t0x%08x\n", readl(hdmi_base + S5P_ENC_EN));
+ HDCPPRINTK("\tHDMI_CON_0 \t0x%08x\n",
+ readl(hdmi_base + S5P_HDMI_CON_0));
+
+ writel(sfr_val, hdmi_base + S5P_HDMI_CON_0);
+#endif
+ return true;
+}
+
+
+void __s5p_hdcp_reset(void)
+{
+
+ __s5p_stop_hdcp();
+
+ hdcp_protocol_status = 2;
+
+ HDCPPRINTK("HDCP ftn. reset!!\n");
+}
+
+/*
+ * start - start functions are only called under stopping HDCP
+ */
+bool __s5p_start_hdcp(void)
+{
+ u8 reg;
+ u32 sfr_val;
+
+ hdcp_info.event = HDCP_EVENT_STOP;
+ hdcp_info.time_out = INFINITE;
+ hdcp_info.auth_status = NOT_AUTHENTICATED;
+
+ HDCPPRINTK("HDCP ftn. Start!!\n");
+
+ sw_reset = true;
+ reg = s5p_hdmi_get_enabled_interrupt();
+
+ s5p_hdmi_disable_interrupts(HDMI_IRQ_HPD_PLUG);
+ s5p_hdmi_disable_interrupts(HDMI_IRQ_HPD_UNPLUG);
+
+ /* 2. Enable software HPD */
+ sw_hpd_enable(true);
+
+ /* 3. Make software HPD logical */
+ set_sw_hpd(false);
+
+ /* 4. Make software HPD logical */
+ set_sw_hpd(true);
+
+ /* 5. Disable software HPD */
+ sw_hpd_enable(false);
+ set_sw_hpd(false);
+
+ /* 6. Unmask HPD plug and unplug interrupt */
+
+ if (reg & 1<<HDMI_IRQ_HPD_PLUG)
+ s5p_hdmi_enable_interrupts(HDMI_IRQ_HPD_PLUG);
+ if (reg & 1<<HDMI_IRQ_HPD_UNPLUG)
+ s5p_hdmi_enable_interrupts(HDMI_IRQ_HPD_UNPLUG);
+
+ sw_reset = false;
+ HDCPPRINTK("Stop Encryption by Start!!\n");
+
+ writel(HDCP_ENC_DISABLE, hdmi_base + S5P_ENC_EN);
+ s5p_hdmi_mute_en(true);
+
+ hdcp_protocol_status = 1;
+
+ if (hdcp_loadkey() < 0)
+ return false;
+
+ /* for av mute */
+ writel(DO_NOT_TRANSMIT, hdmi_base + S5P_GCP_CON);
+
+ /*
+ * 1-1. set hdmi status enable reg.
+ * Update_Ri_int_en should be enabled after
+ * s/w gets ExchangeKSV_int.
+ */
+ writel(HDCP_STATUS_EN_ALL, hdmi_base + S5P_STATUS_EN);
+
+ /*
+ * 3. set hdcp control reg.
+ * Disable advance cipher option, Enable CP(Content Protection),
+ * Disable time-out (This bit is only available in a REPEATER)
+ * Disable XOR shift, Disable Pj port update, Use external key
+ */
+ sfr_val = 0;
+ sfr_val |= CP_DESIRED_EN;
+ writel(sfr_val, hdmi_base + S5P_HDCP_CTRL1);
+
+ s5p_hdmi_enable_interrupts(HDMI_IRQ_HDCP);
+
+ if (!read_bcaps()) {
+ HDCPPRINTK("can't read ddc port!\n");
+ reset_authentication();
+ }
+
+ hdcp_info.hdcp_enable = true;
+
+ HDCPPRINTK("\tSTATUS \t0x%08x\n",
+ readl(hdmi_base + S5P_STATUS));
+ HDCPPRINTK("\tSTATUS_EN \t0x%08x\n",
+ readl(hdmi_base + S5P_STATUS_EN));
+ HDCPPRINTK("\tHPD \t0x%08x\n", readl(hdmi_base + S5P_HPD));
+ HDCPPRINTK("\tHDCP_CTRL \t0x%08x\n",
+ readl(hdmi_base + S5P_HDCP_CTRL1));
+ HDCPPRINTK("\tMODE_SEL \t0x%08x\n",
+ readl(hdmi_base + S5P_MODE_SEL));
+ HDCPPRINTK("\tENC_EN \t0x%08x\n",
+ readl(hdmi_base + S5P_ENC_EN));
+ HDCPPRINTK("\tHDMI_CON_0 \t0x%08x\n",
+ readl(hdmi_base + S5P_HDMI_CON_0));
+
+ return true;
+}
+
+
+static void bksv_start_bh(void)
+{
+ bool ret = false;
+
+ HDCPPRINTK("HDCP_EVENT_READ_BKSV_START bh\n");
+
+ hdcp_info.auth_status = RECEIVER_READ_READY;
+
+ ret = read_bcaps();
+
+ if (!ret) {
+
+ ret = try_read_receiver();
+
+ if (!ret) {
+ HDCPPRINTK("Can't read bcaps!! retry failed!!\n"
+ "\t\t\t\thdcp ftn. will be stopped\n");
+
+ reset_authentication();
+ return;
+ }
+ }
+
+ hdcp_info.auth_status = BCAPS_READ_DONE;
+
+ ret = read_bksv();
+
+ if (!ret) {
+ HDCPPRINTK("Can't read bksv!!"
+ "hdcp ftn. will be reset\n");
+
+ reset_authentication();
+ return;
+ }
+
+ hdcp_info.auth_status = BKSV_READ_DONE;
+
+ HDCPPRINTK("authentication status : bksv is done (0x%08x)\n",
+ hdcp_info.auth_status);
+}
+
+static void second_auth_start_bh(void)
+{
+ u8 count = 0;
+ int reg;
+ bool ret = false;
+
+ int ret_err;
+
+ u32 bcaps;
+
+ HDCPPRINTK("HDCP_EVENT_SECOND_AUTH_START bh\n");
+
+ ret = read_bcaps();
+
+ if (!ret) {
+
+ ret = try_read_receiver();
+
+ if (!ret) {
+
+ HDCPPRINTK("Can't read bcaps!! retry failed!!\n"
+ "\t\t\t\thdcp ftn. will be stopped\n");
+
+ reset_authentication();
+ return;
+ }
+
+ }
+
+ bcaps = readl(hdmi_base + S5P_HDCP_BCAPS);
+ bcaps &= (KSV_FIFO_READY);
+
+ if (!bcaps) {
+
+ HDCPPRINTK("ksv fifo is not ready\n");
+
+ do {
+ count++;
+
+ ret = read_bcaps();
+
+ if (!ret) {
+
+ ret = try_read_receiver();
+ if (!ret)
+ reset_authentication();
+ return;
+
+ }
+
+ bcaps = readl(hdmi_base + S5P_HDCP_BCAPS);
+ bcaps &= (KSV_FIFO_READY);
+
+ if (bcaps) {
+ HDCPPRINTK("bcaps retries : %d\n", count);
+ break;
+ }
+
+ mdelay(100);
+
+ if (!hdcp_info.hdcp_enable) {
+
+ reset_authentication();
+ return;
+
+ }
+
+ } while (count <= 50);
+
+ /* wait times exceeded 5 seconds */
+ if (count > 50) {
+
+ hdcp_info.time_out = INFINITE;
+
+ /*
+ * time-out (This bit is only available in a REPEATER)
+ */
+ writel(readl(hdmi_base + S5P_HDCP_CTRL1) | 0x1 << 2,
+ hdmi_base + S5P_HDCP_CTRL1);
+
+ reset_authentication();
+
+ return;
+ }
+ }
+
+ HDCPPRINTK("ksv fifo ready\n");
+
+ ret_err = check_repeater();
+
+ if (ret_err == true) {
+ u32 flag;
+
+ hdcp_info.auth_status = SECOND_AUTHENTICATION_DONE;
+ HDCPPRINTK("second authentication done!!\n");
+
+ flag = readb(hdmi_base + S5P_STATUS);
+ HDCPPRINTK("hdcp state : %s authenticated!!\n",
+ flag & AUTHENTICATED ? "" : "not not");
+
+ start_encryption();
+ } else if (ret_err == false) {
+ /* i2c error */
+ HDCPPRINTK("repeater check error!!\n");
+ reset_authentication();
+ } else {
+ if (ret_err == REPEATER_ILLEGAL_DEVICE_ERROR) {
+ /*
+ * No need to start the HDCP
+ * in case of invalid KSV (revocation case)
+ */
+ HDCPPRINTK("illegal dev. error!!\n");
+ reg = readl(hdmi_base + S5P_HDCP_CTRL2);
+ reg = 0x1;
+ writel(reg, hdmi_base + S5P_HDCP_CTRL2);
+ reg = 0x0;
+ writel(reg, hdmi_base + S5P_HDCP_CTRL2);
+
+ hdcp_info.auth_status = NOT_AUTHENTICATED;
+
+ } else if (ret_err == REPEATER_TIMEOUT_ERROR) {
+ reg = readl(hdmi_base + S5P_HDCP_CTRL1);
+ reg |= SET_REPEATER_TIMEOUT;
+ writel(reg, hdmi_base + S5P_HDCP_CTRL1);
+ reg &= ~SET_REPEATER_TIMEOUT;
+ writel(reg, hdmi_base + S5P_HDCP_CTRL1);
+
+ hdcp_info.auth_status = NOT_AUTHENTICATED;
+ } else {
+ /*
+ * MAX_CASCADE_EXCEEDED_ERROR
+ * MAX_DEVS_EXCEEDED_ERROR
+ */
+ HDCPPRINTK("repeater check error(MAX_EXCEEDED)!!\n");
+ reset_authentication();
+ }
+ }
+}
+
+static bool write_aksv_start_bh(void)
+{
+ bool ret = false;
+
+ HDCPPRINTK("HDCP_EVENT_WRITE_AKSV_START bh\n");
+
+ if (hdcp_info.auth_status != BKSV_READ_DONE) {
+ HDCPPRINTK("bksv is not ready!!\n");
+ return false;
+ }
+
+ ret = write_an();
+ if (!ret)
+ return false;
+
+ hdcp_info.auth_status = AN_WRITE_DONE;
+
+ HDCPPRINTK("an write done!!\n");
+
+ ret = write_aksv();
+ if (!ret)
+ return false;
+
+ /*
+ * Wait for 100ms. Transmitter must not read
+ * Ro' value sooner than 100ms after writing
+ * Aksv
+ */
+ mdelay(100);
+
+ hdcp_info.auth_status = AKSV_WRITE_DONE;
+
+ HDCPPRINTK("aksv write done!!\n");
+
+ return ret;
+}
+
+static bool check_ri_start_bh(void)
+{
+ bool ret = false;
+
+
+ HDCPPRINTK("HDCP_EVENT_CHECK_RI_START bh\n");
+
+ if (hdcp_info.auth_status == AKSV_WRITE_DONE ||
+ hdcp_info.auth_status == FIRST_AUTHENTICATION_DONE ||
+ hdcp_info.auth_status == SECOND_AUTHENTICATION_DONE) {
+
+ ret = compare_r_val();
+
+ if (ret) {
+
+ if (hdcp_info.auth_status == AKSV_WRITE_DONE) {
+ /*
+ * Check whether HDMI receiver is
+ * repeater or not
+ */
+ if (hdcp_info.is_repeater)
+ hdcp_info.auth_status
+ = SECOND_AUTHENTICATION_RDY;
+ else {
+ hdcp_info.auth_status
+ = FIRST_AUTHENTICATION_DONE;
+ start_encryption();
+ }
+ }
+
+ } else {
+
+ HDCPPRINTK("authentication reset\n");
+ reset_authentication();
+
+ }
+
+ HDCPPRINTK("auth_status = 0x%08x\n",
+ hdcp_info.auth_status);
+
+
+ return true;
+ } else
+ reset_authentication();
+
+ HDCPPRINTK("aksv_write or first/second"
+ " authentication is not done\n");
+
+ return false;
+}
+
+/*
+ * bottom half for hdmi interrupt
+ *
+ */
+static void hdcp_work(void *arg)
+{
+ /*
+ * I2C int. was occurred
+ * for reading Bksv and Bcaps
+ */
+ if (hdcp_info.event & (1 << HDCP_EVENT_READ_BKSV_START)) {
+
+ bksv_start_bh();
+
+ /* clear event */
+ /*
+ spin_lock_bh(&hdcp_info.lock);
+ */
+ hdcp_info.event &= ~(1 << HDCP_EVENT_READ_BKSV_START);
+ /*
+ spin_unlock_bh(&hdcp_info.lock);
+ */
+ }
+ /*
+ * Watchdog timer int. was occurred
+ * for checking repeater
+ */
+ if (hdcp_info.event & (1 << HDCP_EVENT_SECOND_AUTH_START)) {
+
+ second_auth_start_bh();
+
+ /* clear event */
+ /*
+ spin_lock_bh(&hdcp_info.lock);
+ */
+ hdcp_info.event &= ~(1 << HDCP_EVENT_SECOND_AUTH_START);
+ /*
+ spin_unlock_bh(&hdcp_info.lock);
+ */
+ }
+
+ /*
+ * An_Write int. was occurred
+ * for writing Ainfo, An and Aksv
+ */
+ if (hdcp_info.event & (1 << HDCP_EVENT_WRITE_AKSV_START)) {
+
+ write_aksv_start_bh();
+
+ /* clear event */
+ /*
+ spin_lock_bh(&hdcp_info.lock);
+ */
+ hdcp_info.event &= ~(1 << HDCP_EVENT_WRITE_AKSV_START);
+ /*
+ spin_unlock_bh(&hdcp_info.lock);
+ */
+ }
+
+ /*
+ * Ri int. was occurred
+ * for comparing Ri and Ri'(from HDMI sink)
+ */
+ if (hdcp_info.event & (1 << HDCP_EVENT_CHECK_RI_START)) {
+
+
+ check_ri_start_bh();
+
+ /* clear event */
+ /*
+ spin_lock_bh(&hdcp_info.lock);
+ */
+ hdcp_info.event &= ~(1 << HDCP_EVENT_CHECK_RI_START);
+ /*
+ spin_unlock_bh(&hdcp_info.lock);
+ */
+ }
+
+}
+
+void __s5p_init_hdcp(bool hpd_status, struct i2c_client *ddc_port)
+{
+
+ HDCPPRINTK("HDCP ftn. Init!!\n");
+
+ is_dvi = false;
+ av_mute = false;
+ audio_en = true;
+
+ /* for bh */
+ INIT_WORK(&hdcp_info.work, (work_func_t)hdcp_work);
+
+ init_waitqueue_head(&hdcp_info.waitq);
+
+ /* for dev_dbg err. */
+ spin_lock_init(&hdcp_info.lock);
+
+}
+
+
+irqreturn_t __s5p_hdcp_irq_handler(int irq)
+
+{
+ u32 event = 0;
+ u8 flag;
+
+ event = 0;
+ /* check HDCP Status */
+ flag = readb(hdmi_base + S5P_STATUS);
+
+ HDCPPRINTK("irq_status : 0x%08x\n", readb(hdmi_base + S5P_STATUS));
+
+ HDCPPRINTK("hdcp state : %s authenticated!!\n",
+ flag & AUTHENTICATED ? "" : "not");
+
+ spin_lock_irq(&hdcp_info.lock);
+
+ /*
+ * processing interrupt
+ * interrupt processing seq. is firstly set event for workqueue,
+ * and interrupt pending clear. 'flag|' was used for preventing
+ * to clear AUTHEN_ACK.- it caused many problem. be careful.
+ */
+ /* I2C INT */
+ if (flag & WTFORACTIVERX_INT_OCCURRED) {
+ event |= (1 << HDCP_EVENT_READ_BKSV_START);
+ writeb(flag | WTFORACTIVERX_INT_OCCURRED,
+ hdmi_base + S5P_STATUS);
+ writeb(0x0, hdmi_base + S5P_HDCP_I2C_INT);
+ }
+
+ /* AN INT */
+ if (flag & EXCHANGEKSV_INT_OCCURRED) {
+ event |= (1 << HDCP_EVENT_WRITE_AKSV_START);
+ writeb(flag | EXCHANGEKSV_INT_OCCURRED,
+ hdmi_base + S5P_STATUS);
+ writeb(0x0, hdmi_base + S5P_HDCP_AN_INT);
+ }
+
+ /* RI INT */
+ if (flag & UPDATE_RI_INT_OCCURRED) {
+ event |= (1 << HDCP_EVENT_CHECK_RI_START);
+ writeb(flag | UPDATE_RI_INT_OCCURRED,
+ hdmi_base + S5P_STATUS);
+ writeb(0x0, hdmi_base + S5P_HDCP_RI_INT);
+ }
+
+ /* WATCHDOG INT */
+ if (flag & WATCHDOG_INT_OCCURRED) {
+ event |= (1 << HDCP_EVENT_SECOND_AUTH_START);
+ writeb(flag | WATCHDOG_INT_OCCURRED,
+ hdmi_base + S5P_STATUS);
+ writeb(0x0, hdmi_base + S5P_HDCP_WDT_INT);
+ }
+
+ if (!event) {
+ HDCPPRINTK("unknown irq.\n");
+ return IRQ_HANDLED;
+ }
+
+ hdcp_info.event |= event;
+
+ schedule_work(&hdcp_info.work);
+
+ spin_unlock_irq(&hdcp_info.lock);
+
+ return IRQ_HANDLED;
+}
+
+bool __s5p_set_hpd_detection(bool detection, bool hdcp_enabled,
+ struct i2c_client *client)
+{
+ u32 hpd_reg_val = 0;
+
+ if (detection)
+ hpd_reg_val = CABLE_PLUGGED;
+ else
+ hpd_reg_val = CABLE_UNPLUGGED;
+
+
+ writel(hpd_reg_val, hdmi_base + S5P_HPD);
+
+ HDCPPRINTK("HPD status :: 0x%08x\n\r",
+ readl(hdmi_base + S5P_HPD));
+
+ return true;
+}
+
+int __s5p_hdcp_init(void)
+{
+ /* for bh */
+ INIT_WORK(&hdcp_info.work, (work_func_t)hdcp_work);
+ is_dvi = false;
+ av_mute = false;
+ audio_en = true;
+
+ init_waitqueue_head(&hdcp_info.waitq);
+
+ /* for dev_dbg err. */
+ spin_lock_init(&hdcp_info.lock);
+ spin_lock_init(&hdcp_info.reset_lock);
+
+ s5p_hdmi_register_isr((hdmi_isr)__s5p_hdcp_irq_handler,
+ (u8)HDMI_IRQ_HDCP);
+
+ return 0;
+}
+
+/* called by hpd */
+int s5p_hdcp_encrypt_stop(bool on)
+{
+ u32 reg;
+
+ if (hdcp_info.hdcp_enable) {
+ /* clear interrupt pending all */
+ writeb(0x0, hdmi_base + S5P_HDCP_I2C_INT);
+ writeb(0x0, hdmi_base + S5P_HDCP_AN_INT);
+ writeb(0x0, hdmi_base + S5P_HDCP_RI_INT);
+ writeb(0x0, hdmi_base + S5P_HDCP_WDT_INT);
+
+ writel(HDCP_ENC_DISABLE, hdmi_base + S5P_ENC_EN);
+ s5p_hdmi_mute_en(true);
+
+ if (!sw_reset) {
+ reg = readl(hdmi_base + S5P_HDCP_CTRL1);
+
+ if (on) {
+ writel(reg | CP_DESIRED_EN,
+ hdmi_base + S5P_HDCP_CTRL1);
+ s5p_hdmi_enable_interrupts(HDMI_IRQ_HDCP);
+ } else {
+ hdcp_info.event
+ = HDCP_EVENT_STOP;
+ hdcp_info.auth_status
+ = NOT_AUTHENTICATED;
+ writel(reg & ~CP_DESIRED_EN,
+ hdmi_base + S5P_HDCP_CTRL1);
+ s5p_hdmi_disable_interrupts(HDMI_IRQ_HDCP);
+ }
+ }
+
+ HDCPPRINTK("Stop Encryption by HPD Event!!\n");
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(s5p_hdcp_encrypt_stop);
+
diff --git a/drivers/media/video/samsung/tv20/s5pv210/hdmi_param.h b/drivers/media/video/samsung/tv20/s5pv210/hdmi_param.h
new file mode 100644
index 0000000..a8c6338
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/s5pv210/hdmi_param.h
@@ -0,0 +1,414 @@
+/* linux/drivers/media/video/samsung/tv20/s5pv210/hdmi_param.h
+ *
+ * hdmi parameter header file for Samsung TVOut driver
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#define PHY_I2C_ADDRESS 0x70
+#define PHY_REG_MODE_SET_DONE 0x1F
+
+struct hdmi_v_params {
+ u16 h_blank;
+ u32 v_blank;
+ u32 hvline;
+ u32 h_sync_gen;
+ u32 v_sync_gen;
+ u8 avi_vic;
+ u8 avi_vic_16_9;
+ u8 interlaced;
+ u8 repetition;
+ u8 polarity;
+ u32 v_blank_f;
+ u32 v_sync_gen2;
+ u32 v_sync_gen3;
+ enum phy_freq pixel_clock;
+};
+
+struct _hdmi_tg_param {
+ u16 h_fsz;
+ u16 hact_st;
+ u16 hact_sz;
+ u16 v_fsz;
+ u16 vsync;
+ u16 vsync2;
+ u16 vact_st;
+ u16 vact_sz;
+ u16 field_chg;
+ u16 vact_st2;
+ u16 vsync_top_hdmi;
+ u16 vsync_bot_hdmi;
+ u16 field_top_hdmi;
+ u16 field_bot_hdmi;
+ u8 mhl_hsync_width;
+ u8 mhl_vsync_width;
+};
+
+static const struct hdmi_v_params video_params[] = {
+ { 0xA0 , 0x16A0D, 0x32020D, 0x11B80E, 0xA00C , 1 , 1 , 0, 0, 1,
+ 0, 0, 0, ePHY_FREQ_25_200,},
+ { 0x8A , 0x16A0D, 0x35A20D, 0x11300E, 0x900F , 2 , 3 , 0, 0, 1,
+ 0, 0, 0, ePHY_FREQ_27_027,},
+ { 0x172, 0xF2EE , 0x6722EE, 0x2506C , 0x500A , 4 , 4 , 0, 0, 0,
+ 0, 0, 0, ePHY_FREQ_74_250,},
+ { 0x118, 0xB232 , 0x898465, 0x20856, 0x2007 , 5 , 5 , 1, 0, 0,
+ 0x232A49, 0x234239, 0x4A44A4, ePHY_FREQ_74_250,},
+ { 0x114, 0xB106 , 0x6B420D, 0x128024, 0x4007 , 6 , 7 , 1, 1, 1,
+ 0x10691D, 0x10A10D, 0x380380, ePHY_FREQ_27_027,},
+ { 0x114, 0xB106 , 0x6B4106, 0x128024, 0x4007 , 8 , 9 , 0, 1, 1,
+ 0, 0, 0, ePHY_FREQ_27_027,},
+ { 0x228, 0xB106 , 0xD6820D, 0x15084A, 0x4007 , 10, 11, 1, 1, 1,
+ 0x10691D, 0x10A10D, 0x700700, ePHY_FREQ_54_054,},
+ { 0x228, 0xB106 , 0x6B4106, 0x15084A, 0x4007 , 12, 13, 0, 1, 1,
+ 0, 0, 0, ePHY_FREQ_54_054,},
+ { 0x114, 0x16A0D, 0x6B420D, 0x12681E, 0x900F , 14, 15, 0, 1, 1,
+ 0, 0, 0, ePHY_FREQ_54_054,},
+ { 0x118, 0x16C65, 0x898465, 0x20856 , 0x4009 , 16, 16, 0, 0, 0,
+ 0, 0, 0, ePHY_FREQ_148_500},
+
+
+ { 0x90 , 0x18A71, 0x360271, 0x11280A, 0x500A , 17, 18, 0, 0, 1,
+ 0, 0, 0, ePHY_FREQ_27, },
+ { 0x2BC, 0xF2EE , 0x7BC2EE, 0x779B6 , 0x500A , 19, 19, 0, 0, 0,
+ 0, 0, 0, ePHY_FREQ_74_250,},
+ { 0x2D0, 0xB232 , 0xA50465, 0x8EA0E , 0x2007 , 20, 20, 1, 0, 0,
+ 0x232A49, 0x234239, 0x738738, ePHY_FREQ_74_250,},
+ { 0x120, 0xC138 , 0x6C0271, 0x125016, 0x2005 , 21, 22, 1, 1, 1,
+ 0x138951, 0x13A13D, 0x378378, ePHY_FREQ_27, },
+ { 0x120, 0xC138 , 0x6C0138, 0x125016, 0x3006 , 23, 24, 0, 1, 1,
+ 0, 0, 0, ePHY_FREQ_27, },
+ { 0x240, 0xC138 , 0xD80271, 0x14A82E, 0x2005 , 25, 26, 1, 1, 1,
+ 0x138951, 0x13A13D, 0x6F06F0, ePHY_FREQ_54, },
+ { 0x240, 0xC138 , 0xD80138, 0x14A82E, 0x2005 , 27, 28, 0, 1, 1,
+ 0, 0, 0, ePHY_FREQ_54, },
+ { 0x120, 0x18A71, 0x6C0271, 0x125816, 0x500A , 29, 30, 0, 1, 1,
+ 0, 0, 0, ePHY_FREQ_54, },
+ { 0x2D0, 0x16C65, 0xA50465, 0x8EA0E , 0x4009 , 31, 31, 0, 0, 0,
+ 0, 0, 0, ePHY_FREQ_148_500,},
+ { 0x33E, 0x16C65, 0xABE465, 0xAA27C , 0x4009 , 32, 32, 0, 0, 0,
+ 0, 0, 0, ePHY_FREQ_74_250,},
+
+
+ { 0x2D0, 0x16C65, 0xA50465, 0x8EA0E , 0x4009 , 33, 33, 0, 0, 0,
+ 0, 0, 0, ePHY_FREQ_74_250, },
+ { 0x118, 0x16C65, 0x898465, 0x20856 , 0x4009 , 34, 34, 0, 0, 0,
+ 0, 0, 0, ePHY_FREQ_74_250, },
+ { 0x228, 0x16A0D, 0xD6820D, 0x14D83E, 0x900F , 35, 36, 0, 0, 1,
+ 0, 0, 0, ePHY_FREQ_108_108, },
+ { 0x240, 0x18A71, 0xD80271, 0x14B82E, 0x500A , 37, 38, 0, 1, 1,
+ 0, 0, 0, ePHY_FREQ_108, },
+ { 0x180, 0x2AA71, 0x9004E2, 0x3181E , 0x1701C, 39, 39, 0, 0, 0,
+ 0x2712C6, 0x28728F, 0x4a44a4, ePHY_FREQ_72, },
+ { 0x2D0, 0xB232 , 0xA50465, 0x8EA0E , 0x2007 , 40, 40, 1, 0, 0,
+ 0x232A49, 0x234239, 0x738738, ePHY_FREQ_148_500, },
+ { 0x2BC, 0xF2EE , 0x7BC2EE, 0x779B6 , 0x500A , 41, 41, 0, 0, 0,
+ 0, 0, 0, ePHY_FREQ_148_500, },
+ { 0x90 , 0x18A71, 0x360271, 0x11280A, 0x500A , 42, 43, 0, 0, 1,
+ 0, 0, 0, ePHY_FREQ_54, },
+ { 0x120, 0xC138 , 0x6C0271, 0x125016, 0x2005 , 44, 45, 1, 1, 1,
+ 0x138951, 0x13A13D, 0x378378, ePHY_FREQ_54, },
+ { 0x118, 0xB232 , 0x898465, 0x20856 , 0x2007 , 46, 46, 1, 0, 0,
+ 0x232A49, 0x234239, 0x4A44A4, ePHY_FREQ_148_500, },
+
+
+ { 0x172, 0xF2EE , 0x6722EE, 0x2506C , 0x500A , 47, 47, 0, 0, 0,
+ 0, 0, 0, ePHY_FREQ_148_500,},
+ { 0x8A , 0x16A0D, 0x35A20D, 0x11300E, 0x900F , 48, 49, 0, 0, 1,
+ 0, 0, 0, ePHY_FREQ_54_054, },
+ { 0x114, 0xB106 , 0x6B420D, 0x128024, 0x4007 , 50, 51, 1, 1, 1,
+ 0x10691D, 0x10A10D, 0x380380, ePHY_FREQ_54_054, },
+ { 0x90 , 0x18A71, 0x360271, 0x11280A, 0x500A , 52, 53, 0, 0, 1,
+ 0, 0, 0, ePHY_FREQ_108, },
+ { 0x120, 0xC138 , 0x6C0271, 0x125016, 0x2005 , 54, 55, 1, 1, 1,
+ 0x138951, 0x13A13D, 0x378378, ePHY_FREQ_108, },
+ { 0x8A , 0x16A0D, 0x35A20D, 0x11300E, 0x900F , 56, 57, 0, 0, 1,
+ 0, 0, 0, ePHY_FREQ_108_108,},
+ { 0x114, 0xB106 , 0x6B420D, 0x128024, 0x4007 , 58, 59, 1, 1, 1,
+ 0x10691D, 0x10A10D, 0x380380, ePHY_FREQ_108_108,},
+
+ { 0x8A , 0x16A0D, 0x35A20D, 0x11300E, 0x900F , 2 , 3 , 0, 0, 1,
+ 0, 0, 0, ePHY_FREQ_27, },
+ { 0x172, 0xF2EE , 0x6722EE, 0x2506C , 0x500A , 4 , 4 , 0, 0, 0,
+ 0, 0, 0, ePHY_FREQ_74_176, },
+ { 0x118, 0xB232 , 0x898465, 0x20856, 0x2007 , 5 , 5 , 1, 0, 0,
+ 0x232A49, 0x234239, 0x4A44A4, ePHY_FREQ_74_176, },
+ { 0x118, 0x16C65, 0x898465, 0x20856 , 0x4009 , 16, 16, 0, 0, 0,
+ 0, 0, 0, ePHY_FREQ_148_352,},
+};
+
+static const struct _hdmi_tg_param hdmi_tg_param[] = {
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
+
+ {0x35a , 0x8a , 0x2d0 , 0x20d , 0x1 , 0x233 , 0x2d , 0x1e0 ,
+ 0x233 , 0x248 , 0x1 , 0x1 , 0x1 , 0x233 , 0xf , 0x1 },
+
+ {0x672 , 0x172 , 0x500 , 0x2ee , 0x1 , 0x233 , 0x1e , 0x2d0 ,
+ 0x233 , 0x248 , 0x1 , 0x1 , 0x1 , 0x233 , 0xf , 0x1 },
+
+ {0x898 , 0x118 , 0x780 , 0x465 , 0x1 , 0x233 , 0x16 , 0x21c ,
+ 0x233 , 0x249 , 0x1 , 0x233 , 0x1 , 0x233 , 0xf , 0x1 },
+
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
+
+ {0x898 , 0x118 , 0x780 , 0x465 , 0x1 , 0x233 , 0x2d , 0x438 ,
+ 0x233 , 0x248 , 0x1 , 0x1 , 0x1 , 0x233 , 0xf , 0x1 },
+
+ {0x360 , 0x90 , 0x2d0 , 0x271 , 0x1 , 0x233 , 0x31 , 0x240 ,
+ 0x233 , 0x248 , 0x1 , 0x1 , 0x1 , 0x233 , 0xf , 0x1 },
+
+ {0x7bc , 0x2bc , 0x500 , 0x2ee , 0x1 , 0x233 , 0x1e , 0x2d0 ,
+ 0x233 , 0x248 , 0x1 , 0x1 , 0x1 , 0x233 , 0xf , 0x1 },
+
+ {0xa50 , 0x2d0 , 0x780 , 0x465 , 0x1 , 0x233 , 0x16 , 0x21c ,
+ 0x233 , 0x249 , 0x1 , 0x233 , 0x1 , 0x233 , 0xf , 0x1 },
+
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
+
+ {0xa50 , 0x2d0 , 0x780 , 0x465 , 0x1 , 0x233 , 0x2d , 0x438 ,
+ 0x233 , 0x248 , 0x1 , 0x1 , 0x1 , 0x233 , 0xf , 0x1 },
+
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
+
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
+
+ {0x898 , 0x118 , 0x780 , 0x465 , 0x1 , 0x233 , 0x2d , 0x438 ,
+ 0x233 , 0x248 , 0x1 , 0x1 , 0x1 , 0x233 , 0xf , 0x1 },
+
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
+
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
+
+ {0x35a , 0x8a , 0x2d0 , 0x20d , 0x1 , 0x233 , 0x2d , 0x1e0 ,
+ 0x233 , 0x248 , 0x1 , 0x1 , 0x1 , 0x233 , 0xf , 0x1 },
+
+ {0x672 , 0x172 , 0x500 , 0x2ee , 0x1 , 0x233 , 0x1e , 0x2d0 ,
+ 0x233 , 0x248 , 0x1 , 0x1 , 0x1 , 0x233 , 0xf , 0x1 },
+
+ {0x898 , 0x118 , 0x780 , 0x465 , 0x1 , 0x233 , 0x16 , 0x21c ,
+ 0x233 , 0x249 , 0x1 , 0x233 , 0x1 , 0x233 , 0xf , 0x1 },
+
+ {0x898 , 0x118 , 0x780 , 0x465 , 0x1 , 0x233 , 0x2d , 0x438 ,
+ 0x233 , 0x248 , 0x1 , 0x1 , 0x1 , 0x233 , 0xf , 0x1 },
+
+};
+
+static const u8 phy_config[][3][32] = {
+ { /* freq = 25.200 MHz */
+ { 0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40, 0x6B, 0x10, 0x02,
+ 0x51, 0x5f, 0xF1, 0x54, 0x7e, 0x84, 0x00, 0x10, 0x38, 0x00, 0x08,
+ 0x10, 0xE0, 0x22, 0x40, 0xf3, 0x26, 0x00, 0x00, 0x00, 0x80, },
+ { 0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40, 0x6B, 0x10, 0x02,
+ 0x51, 0x9f, 0xF6, 0x54, 0x9e, 0x84, 0x00, 0x32, 0x38, 0x00, 0xB8,
+ 0x10, 0xE0, 0x22, 0x40, 0xc2, 0x26, 0x00, 0x00, 0x00, 0x80, },
+ { 0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40, 0x6B, 0x10, 0x02,
+ 0x51, 0xFf, 0xF3, 0x54, 0xbd, 0x84, 0x00, 0x30, 0x38, 0x00, 0xA4,
+ 0x10, 0xE0, 0x22, 0x40, 0xa2, 0x26, 0x00, 0x00, 0x00, 0x80, },
+ },
+
+ { /* freq = 25.175 MHz */
+ { 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0x1e, 0x20, 0x6B, 0x50, 0x10,
+ 0x51, 0xf1, 0x31, 0x54, 0xbd, 0x84, 0x00, 0x10, 0x38, 0x00, 0x08,
+ 0x10, 0xE0, 0x22, 0x40, 0xf3, 0x26, 0x00, 0x00, 0x00, 0x80, },
+ { 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0x2b, 0x40, 0x6B, 0x50, 0x10,
+ 0x51, 0xF2, 0x32, 0x54, 0xec, 0x84, 0x00, 0x10, 0x38, 0x00, 0xB8,
+ 0x10, 0xE0, 0x22, 0x40, 0xc2, 0x26, 0x00, 0x00, 0x00, 0x80, },
+ { 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0x1e, 0x20, 0x6B, 0x10, 0x02,
+ 0x51, 0xf1, 0x31, 0x54, 0xbd, 0x84, 0x00, 0x10, 0x38, 0x00, 0xA4,
+ 0x10, 0xE0, 0x22, 0x40, 0xa2, 0x26, 0x00, 0x00, 0x00, 0x80, },
+ },
+
+ { /* freq = 27 MHz */
+ { 0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40, 0x6B, 0x10, 0x02,
+ 0x51, 0xDf, 0xF2, 0x54, 0x87, 0x84, 0x00, 0x30, 0x38, 0x00, 0x08,
+ 0x10, 0xE0, 0x22, 0x40, 0xe3, 0x26, 0x00, 0x00, 0x00, 0x80, },
+ { 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0x02, 0x08, 0x6A, 0x10, 0x02,
+ 0x51, 0xCf, 0xF1, 0x54, 0xa9, 0x84, 0x00, 0x10, 0x38, 0x00, 0xB8,
+ 0x10, 0xE0, 0x22, 0x40, 0xb5, 0x26, 0x00, 0x00, 0x00, 0x80, },
+ { 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xfc, 0x08, 0x6B, 0x10, 0x02,
+ 0x51, 0x2f, 0xF2, 0x54, 0xcb, 0x84, 0x00, 0x10, 0x38, 0x00, 0xA4,
+ 0x10, 0xE0, 0x22, 0x40, 0x97, 0x26, 0x00, 0x00, 0x00, 0x80, },
+ },
+
+ { /* freq = 27.027 MHz */
+ { 0x01, 0x05, 0x00, 0xD4, 0x10, 0x9C, 0x09, 0x64, 0x6B, 0x10, 0x02,
+ 0x51, 0xDf, 0xF2, 0x54, 0x87, 0x84, 0x00, 0x30, 0x38, 0x00, 0x08,
+ 0x10, 0xE0, 0x22, 0x40, 0xe2, 0x26, 0x00, 0x00, 0x00, 0x80, },
+ { 0x01, 0x05, 0x00, 0xD4, 0x10, 0x9C, 0x31, 0x50, 0x6B, 0x10, 0x02,
+ 0x51, 0x8f, 0xF3, 0x54, 0xa9, 0x84, 0x00, 0x30, 0x38, 0x00, 0xB8,
+ 0x10, 0xE0, 0x22, 0x40, 0xb5, 0x26, 0x00, 0x00, 0x00, 0x80, },
+ { 0x01, 0x05, 0x00, 0x10, 0x10, 0x9C, 0x1b, 0x64, 0x6F, 0x10, 0x02,
+ 0x51, 0x7f, 0xF8, 0x54, 0xcb, 0x84, 0x00, 0x32, 0x38, 0x00, 0xA4,
+ 0x10, 0xE0, 0x22, 0x40, 0x97, 0x26, 0x00, 0x00, 0x00, 0x80, },
+ },
+
+ { /* freq = 54 MHz */
+ { 0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40, 0x6B, 0x10, 0x01,
+ 0x51, 0xDf, 0xF2, 0x54, 0x87, 0x84, 0x00, 0x30, 0x38, 0x00, 0x08,
+ 0x10, 0xE0, 0x22, 0x40, 0xe3, 0x26, 0x01, 0x00, 0x00, 0x80, },
+ { 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0x02, 0x08, 0x6A, 0x10, 0x01,
+ 0x51, 0xCf, 0xF1, 0x54, 0xa9, 0x84, 0x00, 0x10, 0x38, 0x00, 0xF8,
+ 0x10, 0xE0, 0x22, 0x40, 0xb5, 0x26, 0x01, 0x00, 0x00, 0x80, },
+ { 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xfc, 0x08, 0x6B, 0x10, 0x01,
+ 0x51, 0x2f, 0xF2, 0x54, 0xcb, 0x84, 0x00, 0x10, 0x38, 0x00, 0xE4,
+ 0x10, 0xE0, 0x22, 0x40, 0x97, 0x26, 0x01, 0x00, 0x00, 0x80, },
+ },
+
+ { /* freq = 54.054 MHz */
+ { 0x01, 0x05, 0x00, 0xd4, 0x10, 0x9C, 0x09, 0x64, 0x6B, 0x10, 0x01,
+ 0x51, 0xDf, 0xF2, 0x54, 0x87, 0x84, 0x00, 0x30, 0x38, 0x00, 0x08,
+ 0x10, 0xE0, 0x22, 0x40, 0xe2, 0x26, 0x01, 0x00, 0x00, 0x80, },
+ { 0x01, 0x05, 0x00, 0xd4, 0x10, 0x9C, 0x31, 0x50, 0x6B, 0x10, 0x01,
+ 0x51, 0x8f, 0xF3, 0x54, 0xa9, 0x84, 0x00, 0x30, 0x38, 0x00, 0xF8,
+ 0x10, 0xE0, 0x22, 0x40, 0xb5, 0x26, 0x01, 0x00, 0x00, 0x80, },
+ { 0x01, 0x05, 0x00, 0x10, 0x10, 0x9C, 0x1b, 0x64, 0x6F, 0x10, 0x01,
+ 0x51, 0x7f, 0xF8, 0x54, 0xcb, 0x84, 0x00, 0x32, 0x38, 0x00, 0xE4,
+ 0x10, 0xE0, 0x22, 0x40, 0x97, 0x26, 0x01, 0x00, 0x00, 0x80, },
+ },
+
+ { /* freq = 74.250 MHz */
+ { 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xf8, 0x40, 0x6A, 0x10, 0x01,
+ 0x51, 0xff, 0xF1, 0x54, 0xba, 0x84, 0x00, 0x10, 0x38, 0x00, 0x08,
+ 0x10, 0xE0, 0x22, 0x40, 0xa4, 0x26, 0x01, 0x00, 0x00, 0x80, },
+ { 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xd6, 0x40, 0x6B, 0x10, 0x01,
+ 0x51, 0x7f, 0xF2, 0x54, 0xe8, 0x84, 0x00, 0x10, 0x38, 0x00, 0xF8,
+ 0x10, 0xE0, 0x22, 0x40, 0x83, 0x26, 0x01, 0x00, 0x00, 0x80, },
+ { 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0x34, 0x40, 0x6B, 0x10, 0x01,
+ 0x51, 0xef, 0xF2, 0x54, 0x16, 0x85, 0x00, 0x10, 0x38, 0x00, 0xE4,
+ 0x10, 0xE0, 0x22, 0x40, 0xdc, 0x26, 0x02, 0x00, 0x00, 0x80, },
+ },
+
+ { /* freq = 74.176 MHz */
+ { 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xef, 0x5B, 0x6D, 0x10, 0x01,
+ 0x51, 0xef, 0xF3, 0x54, 0xb9, 0x84, 0x00, 0x30, 0x38, 0x00, 0x08,
+ 0x10, 0xE0, 0x22, 0x40, 0xa5, 0x26, 0x01, 0x00, 0x00, 0x80, },
+ { 0x01, 0x05, 0x00, 0x10, 0x10, 0x9C, 0xab, 0x5B, 0x6F, 0x10, 0x01,
+ 0x51, 0xbf, 0xF9, 0x54, 0xe8, 0x84, 0x00, 0x32, 0x38, 0x00, 0xF8,
+ 0x10, 0xE0, 0x22, 0x40, 0x84, 0x26, 0x01, 0x00, 0x00, 0x80, },
+ { 0x01, 0x05, 0x00, 0xD4, 0x10, 0x9C, 0xcd, 0x5B, 0x6F, 0x10, 0x01,
+ 0x51, 0xdf, 0xF5, 0x54, 0x16, 0x85, 0x00, 0x30, 0x38, 0x00, 0xE4,
+ 0x10, 0xE0, 0x22, 0x40, 0xdc, 0x26, 0x02, 0x00, 0x00, 0x80, },
+ },
+
+ { /* freq = 148.500 MHz - Pre-emph + Higher Tx amp. */
+ { 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xf8, 0x40, 0x6A, 0x18, 0x00,
+ 0x51, 0xff, 0xF1, 0x54, 0xba, 0x84, 0x00, 0x10, 0x38, 0x00, 0x08,
+ 0x10, 0xE0, 0x22, 0x40, 0xa4, 0x26, 0x02, 0x00, 0x00, 0x80, },
+ { 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xd6, 0x40, 0x6B, 0x18, 0x00,
+ 0x51, 0x7f, 0xF2, 0x54, 0xe8, 0x84, 0x00, 0x10, 0x38, 0x00, 0xF8,
+ 0x10, 0xE0, 0x23, 0x41, 0x83, 0x26, 0x02, 0x00, 0x00, 0x80, },
+ { 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0x34, 0x40, 0x6B, 0x18, 0x00,
+ 0x51, 0xef, 0xF2, 0x54, 0x16, 0x85, 0x00, 0x10, 0x38, 0x00, 0xE4,
+ 0x10, 0xE0, 0x23, 0x41, 0x6d, 0x26, 0x02, 0x00, 0x00, 0x80, },
+ },
+
+ { /* freq = 148.352 MHz */
+ { 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xef, 0x5B, 0x6D, 0x18, 0x00,
+ 0x51, 0xef, 0xF3, 0x54, 0xb9, 0x84, 0x00, 0x30, 0x38, 0x00, 0x08,
+ 0x10, 0xE0, 0x22, 0x40, 0xa5, 0x26, 0x02, 0x00, 0x00, 0x80, },
+ { 0x01, 0x05, 0x00, 0x10, 0x10, 0x9C, 0xab, 0x5B, 0x6F, 0x18, 0x00,
+ 0x51, 0xbf, 0xF9, 0x54, 0xe8, 0x84, 0x00, 0x32, 0x38, 0x00, 0xF8,
+ 0x10, 0xE0, 0x23, 0x41, 0x84, 0x26, 0x02, 0x00, 0x00, 0x80, },
+ { 0x01, 0x05, 0x00, 0xD4, 0x10, 0x9C, 0xcd, 0x5B, 0x6F, 0x18, 0x00,
+ 0x51, 0xdf, 0xF5, 0x54, 0x16, 0x85, 0x00, 0x30, 0x38, 0x00, 0xE4,
+ 0x10, 0xE0, 0x23, 0x41, 0x6d, 0x26, 0x02, 0x00, 0x00, 0x80, },
+ },
+
+ { /* freq = 108.108 MHz */
+ { 0x01, 0x05, 0x00, 0xD4, 0x10, 0x9C, 0x09, 0x64, 0x6B, 0x18, 0x00,
+ 0x51, 0xDf, 0xF2, 0x54, 0x87, 0x84, 0x00, 0x30, 0x38, 0x00, 0x08,
+ 0x10, 0xE0, 0x22, 0x40, 0xe2, 0x26, 0x02, 0x00, 0x00, 0x80, },
+ { 0x01, 0x05, 0x00, 0xD4, 0x10, 0x9C, 0x31, 0x50, 0x6D, 0x18, 0x00,
+ 0x51, 0x8f, 0xF3, 0x54, 0xa9, 0x84, 0x00, 0x30, 0x38, 0x00, 0xF8,
+ 0x10, 0xE0, 0x22, 0x40, 0xb5, 0x26, 0x02, 0x00, 0x00, 0x80, },
+ { 0x01, 0x05, 0x00, 0x10, 0x10, 0x9C, 0x1b, 0x64, 0x6F, 0x18, 0x00,
+ 0x51, 0x7f, 0xF8, 0x54, 0xcb, 0x84, 0x00, 0x32, 0x38, 0x00, 0xE4,
+ 0x10, 0xE0, 0x22, 0x40, 0x97, 0x26, 0x02, 0x00, 0x00, 0x80, },
+ },
+
+ { /* freq = 72 MHz */
+ { 0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40, 0x6B, 0x10, 0x01,
+ 0x51, 0xEf, 0xF1, 0x54, 0xb4, 0x84, 0x00, 0x10, 0x38, 0x00, 0x08,
+ 0x10, 0xE0, 0x22, 0x40, 0xaa, 0x26, 0x01, 0x00, 0x00, 0x80, },
+ { 0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40, 0x6F, 0x10, 0x01,
+ 0x51, 0xBf, 0xF4, 0x54, 0xe1, 0x84, 0x00, 0x30, 0x38, 0x00, 0xF8,
+ 0x10, 0xE0, 0x22, 0x40, 0x88, 0x26, 0x01, 0x00, 0x00, 0x80, },
+ { 0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40, 0x6B, 0x18, 0x00,
+ 0x51, 0xDf, 0xF2, 0x54, 0x87, 0x84, 0x00, 0x30, 0x38, 0x00, 0xE4,
+ 0x10, 0xE0, 0x22, 0x40, 0xe3, 0x26, 0x02, 0x00, 0x00, 0x80, },
+ },
+
+ { /* freq = 25 MHz */
+ { 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0x20, 0x40, 0x6B, 0x50, 0x10,
+ 0x51, 0xff, 0xF1, 0x54, 0xbc, 0x84, 0x00, 0x10, 0x38, 0x00, 0x08,
+ 0x10, 0xE0, 0x22, 0x40, 0xf5, 0x26, 0x00, 0x00, 0x00, 0x80, },
+ { 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0x08, 0x40, 0x6B, 0x50, 0x10,
+ 0x51, 0x7f, 0xF2, 0x54, 0xea, 0x84, 0x00, 0x10, 0x38, 0x00, 0xB8,
+ 0x10, 0xE0, 0x22, 0x40, 0xc4, 0x26, 0x00, 0x00, 0x00, 0x80, },
+ { 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0x20, 0x40, 0x6B, 0x10, 0x02,
+ 0x51, 0xff, 0xF1, 0x54, 0xbc, 0x84, 0x00, 0x10, 0x38, 0x00, 0xA4,
+ 0x10, 0xE0, 0x22, 0x40, 0xa3, 0x26, 0x00, 0x00, 0x00, 0x80, },
+ },
+
+ { /* freq = 65 MHz */
+ { 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0x02, 0x0c, 0x6B, 0x10, 0x01,
+ 0x51, 0xBf, 0xF1, 0x54, 0xa3, 0x84, 0x00, 0x10, 0x38, 0x00, 0x08,
+ 0x10, 0xE0, 0x22, 0x40, 0xbc, 0x26, 0x01, 0x00, 0x00, 0x80, },
+ { 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xf2, 0x30, 0x6A, 0x10, 0x01,
+ 0x51, 0x2f, 0xF2, 0x54, 0xcb, 0x84, 0x00, 0x10, 0x38, 0x00, 0xF8,
+ 0x10, 0xE0, 0x22, 0x40, 0x96, 0x26, 0x01, 0x00, 0x00, 0x80, },
+ { 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xd0, 0x40, 0x6B, 0x10, 0x01,
+ 0x51, 0x9f, 0xF2, 0x54, 0xf4, 0x84, 0x00, 0x10, 0x38, 0x00, 0xE4,
+ 0x10, 0xE0, 0x22, 0x40, 0x7D, 0x26, 0x01, 0x00, 0x00, 0x80, },
+ },
+
+ { /* freq = 108 MHz */
+ { 0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40, 0x6D, 0x18, 0x00,
+ 0x51, 0xDf, 0xF2, 0x54, 0x87, 0x84, 0x00, 0x30, 0x38, 0x00, 0x08,
+ 0x10, 0xE0, 0x22, 0x40, 0xe3, 0x26, 0x02, 0x00, 0x00, 0x80, },
+ { 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0x02, 0x08, 0x6A, 0x18, 0x00,
+ 0x51, 0xCf, 0xF1, 0x54, 0xa9, 0x84, 0x00, 0x10, 0x38, 0x00, 0xF8,
+ 0x10, 0xE0, 0x22, 0x40, 0xb5, 0x26, 0x02, 0x00, 0x00, 0x80, },
+ { 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xfc, 0x08, 0x6B, 0x18, 0x00,
+ 0x51, 0x2f, 0xF2, 0x54, 0xcb, 0x84, 0x00, 0x10, 0x38, 0x00, 0xE4,
+ 0x10, 0xE0, 0x22, 0x40, 0x97, 0x26, 0x02, 0x00, 0x00, 0x80, },
+ },
+
+ { /* freq = 162 MHz */
+ { 0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40, 0x6F, 0x18, 0x00,
+ 0x51, 0x7f, 0xF8, 0x54, 0xcb, 0x84, 0x00, 0x32, 0x38, 0x00, 0x08,
+ 0x10, 0xE0, 0x22, 0x40, 0x97, 0x26, 0x02, 0x00, 0x00, 0x80, },
+ { 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0x18, 0x40, 0x6B, 0x18, 0x00,
+ 0x51, 0xAf, 0xF2, 0x54, 0xfd, 0x84, 0x00, 0x10, 0x38, 0x00, 0xF8,
+ 0x10, 0xE0, 0x23, 0x41, 0x78, 0x26, 0x02, 0x00, 0x00, 0x80, },
+ { 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xd0, 0x40, 0x6B, 0x18, 0x00,
+ 0x51, 0x3f, 0xF3, 0x54, 0x30, 0x85, 0x00, 0x10, 0x38, 0x00, 0xE4,
+ 0x10, 0xE0, 0x23, 0x41, 0x64, 0x26, 0x02, 0x00, 0x00, 0x80, },
+ },
+};
+
diff --git a/drivers/media/video/samsung/tv20/s5pv210/hdmi_s5pv210.c b/drivers/media/video/samsung/tv20/s5pv210/hdmi_s5pv210.c
new file mode 100644
index 0000000..58bdcad
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/s5pv210/hdmi_s5pv210.c
@@ -0,0 +1,2131 @@
+/* linux/drivers/media/video/samsung/tv20/s5pv210/hdmi_s5pv210.c
+ *
+ * hdmi raw ftn file for Samsung TVOut driver
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include <plat/clock.h>
+
+#include "tv_out_s5pv210.h"
+
+#include "regs/regs-hdmi.h"
+#include "hdmi_param.h"
+
+#include "../hpd.h"
+
+#ifdef COFIG_TVOUT_RAW_DBG
+#define S5P_HDMI_DEBUG 1
+#endif
+
+#ifdef S5P_HDMI_DEBUG
+#define HDMIPRINTK(fmt, args...) \
+ printk(KERN_INFO "\t\t[HDMI] %s: " fmt, __func__ , ## args)
+#else
+#define HDMIPRINTK(fmt, args...)
+#endif
+
+static struct resource *hdmi_mem;
+void __iomem *hdmi_base;
+
+static struct resource *i2c_hdmi_phy_mem;
+void __iomem *i2c_hdmi_phy_base;
+
+spinlock_t lock_hdmi;
+
+/*
+ * i2c_hdmi_phy related
+ */
+
+#define PHY_I2C_ADDRESS 0x70
+
+#define I2C_ACK (1<<7)
+#define I2C_INT (1<<5)
+#define I2C_PEND (1<<4)
+
+#define I2C_INT_CLEAR (0<<4)
+
+#define I2C_CLK (0<<6)
+#define I2C_CLK_PEND_INT (I2C_CLK|I2C_INT_CLEAR|I2C_INT)
+
+#define I2C_ENABLE (1<<4)
+#define I2C_START (1<<5)
+
+#define I2C_MODE_MTX (0x3<<6)
+#define I2C_MODE_MRX (0x2<<6)
+#define I2C_MODE_SRX (0x0<<6)
+
+#define I2C_IDLE 0
+
+static struct {
+ s32 state;
+ u8 *buffer;
+ s32 bytes;
+} i2c_hdmi_phy_context;
+
+
+#define STATE_IDLE 0
+#define STATE_TX_EDDC_SEGADDR 1
+#define STATE_TX_EDDC_SEGNUM 2
+#define STATE_TX_DDC_ADDR 3
+#define STATE_TX_DDC_OFFSET 4
+#define STATE_RX_DDC_ADDR 5
+#define STATE_RX_DDC_DATA 6
+#define STATE_RX_ADDR 7
+#define STATE_RX_DATA 8
+#define STATE_TX_ADDR 9
+#define STATE_TX_DATA 10
+#define STATE_TX_STOP 11
+#define STATE_RX_STOP 12
+
+static s32 i2c_hdmi_phy_interruptwait(void)
+{
+ u8 status, reg;
+ s32 retval = 0;
+
+ do {
+ status = readb(i2c_hdmi_phy_base + I2C_HDMI_CON);
+
+ if (status & I2C_PEND) {
+ /* check status flags */
+ reg = readb(i2c_hdmi_phy_base + I2C_HDMI_STAT);
+ break;
+ }
+ } while (1);
+
+ return retval;
+}
+
+s32 i2c_hdmi_phy_read(u8 addr, u8 nbytes, u8 *buffer)
+{
+ u8 reg;
+ s32 ret = 0;
+ u32 proc = true;
+
+ i2c_hdmi_phy_context.state = STATE_RX_ADDR;
+ i2c_hdmi_phy_context.buffer = buffer;
+ i2c_hdmi_phy_context.bytes = nbytes;
+
+ writeb(I2C_CLK | I2C_INT | I2C_ACK,
+ i2c_hdmi_phy_base + I2C_HDMI_CON);
+
+ writeb(I2C_ENABLE | I2C_MODE_MRX,
+ i2c_hdmi_phy_base + I2C_HDMI_STAT);
+
+ writeb(addr & 0xFE,
+ i2c_hdmi_phy_base + I2C_HDMI_DS);
+
+ writeb(I2C_ENABLE | I2C_START | I2C_MODE_MRX,
+ i2c_hdmi_phy_base + I2C_HDMI_STAT);
+
+ while (proc) {
+
+ if (i2c_hdmi_phy_context.state != STATE_RX_STOP) {
+ if (i2c_hdmi_phy_interruptwait() != 0) {
+ HDMIPRINTK("interrupt wait failed!!!\n");
+ ret = EINVAL;
+ break;
+ }
+ }
+
+ switch (i2c_hdmi_phy_context.state) {
+
+ case STATE_RX_DATA:
+
+ reg = readb(i2c_hdmi_phy_base + I2C_HDMI_DS);
+ *(i2c_hdmi_phy_context.buffer) = reg;
+
+ i2c_hdmi_phy_context.buffer++;
+ --(i2c_hdmi_phy_context.bytes);
+
+ if (i2c_hdmi_phy_context.bytes == 1) {
+ i2c_hdmi_phy_context.state = STATE_RX_STOP;
+ writeb(I2C_CLK_PEND_INT,
+ i2c_hdmi_phy_base + I2C_HDMI_CON);
+ } else {
+ writeb(I2C_CLK_PEND_INT | I2C_ACK,
+ i2c_hdmi_phy_base + I2C_HDMI_CON);
+
+ }
+ break;
+
+ case STATE_RX_ADDR:
+ i2c_hdmi_phy_context.state = STATE_RX_DATA;
+
+ if (i2c_hdmi_phy_context.bytes == 1) {
+ i2c_hdmi_phy_context.state = STATE_RX_STOP;
+ writeb(I2C_CLK_PEND_INT,
+ i2c_hdmi_phy_base + I2C_HDMI_CON);
+ } else {
+ writeb(I2C_CLK_PEND_INT | I2C_ACK,
+ i2c_hdmi_phy_base + I2C_HDMI_CON);
+ }
+
+ break;
+
+ case STATE_RX_STOP:
+
+ i2c_hdmi_phy_context.state = STATE_IDLE;
+
+ reg = readb(i2c_hdmi_phy_base + I2C_HDMI_DS);
+
+ *(i2c_hdmi_phy_context.buffer) = reg;
+
+ writeb(I2C_MODE_MRX|I2C_ENABLE,
+ i2c_hdmi_phy_base + I2C_HDMI_STAT);
+
+ writeb(I2C_CLK_PEND_INT,
+ i2c_hdmi_phy_base + I2C_HDMI_CON);
+
+ writeb(I2C_MODE_MRX,
+ i2c_hdmi_phy_base + I2C_HDMI_STAT);
+
+ while (readb(i2c_hdmi_phy_base + I2C_HDMI_STAT) &
+ (1<<5))
+ msleep(1);
+
+ proc = false;
+
+ break;
+
+ case STATE_IDLE:
+
+ default:
+ HDMIPRINTK("error state!!!\n");
+
+ ret = EINVAL;
+
+ proc = false;
+
+ break;
+ }
+ }
+
+ return ret;
+}
+
+s32 i2c_hdmi_phy_write(u8 addr, u8 nbytes, u8 *buffer)
+{
+ u8 reg;
+ s32 ret = 0;
+ u32 proc = true;
+
+ i2c_hdmi_phy_context.state = STATE_TX_ADDR;
+ i2c_hdmi_phy_context.buffer = buffer;
+ i2c_hdmi_phy_context.bytes = nbytes;
+
+ writeb(I2C_CLK | I2C_INT | I2C_ACK,
+ i2c_hdmi_phy_base + I2C_HDMI_CON);
+
+ writeb(I2C_ENABLE | I2C_MODE_MTX,
+ i2c_hdmi_phy_base + I2C_HDMI_STAT);
+
+ writeb(addr & 0xFE,
+ i2c_hdmi_phy_base + I2C_HDMI_DS);
+
+ writeb(I2C_ENABLE | I2C_START | I2C_MODE_MTX,
+ i2c_hdmi_phy_base + I2C_HDMI_STAT);
+
+ while (proc) {
+
+ if (i2c_hdmi_phy_interruptwait() != 0) {
+ HDMIPRINTK("interrupt wait failed!!!\n");
+ ret = EINVAL;
+ break;
+ }
+
+ switch (i2c_hdmi_phy_context.state) {
+
+ case STATE_TX_ADDR:
+
+ case STATE_TX_DATA:
+ i2c_hdmi_phy_context.state = STATE_TX_DATA;
+
+ reg = *(i2c_hdmi_phy_context.buffer);
+
+ writeb(reg, i2c_hdmi_phy_base + I2C_HDMI_DS);
+
+ i2c_hdmi_phy_context.buffer++;
+ --(i2c_hdmi_phy_context.bytes);
+
+ if (i2c_hdmi_phy_context.bytes == 0) {
+ i2c_hdmi_phy_context.state = STATE_TX_STOP;
+ writeb(I2C_CLK_PEND_INT,
+ i2c_hdmi_phy_base + I2C_HDMI_CON);
+ } else
+ writeb(I2C_CLK_PEND_INT | I2C_ACK,
+ i2c_hdmi_phy_base + I2C_HDMI_CON);
+ break;
+
+ case STATE_TX_STOP:
+ i2c_hdmi_phy_context.state = STATE_IDLE;
+
+ writeb(I2C_MODE_MTX | I2C_ENABLE,
+ i2c_hdmi_phy_base + I2C_HDMI_STAT);
+
+ writeb(I2C_CLK_PEND_INT,
+ i2c_hdmi_phy_base + I2C_HDMI_CON);
+
+ writeb(I2C_MODE_MTX,
+ i2c_hdmi_phy_base + I2C_HDMI_STAT);
+
+ while (readb(i2c_hdmi_phy_base + I2C_HDMI_STAT) &
+ (1<<5))
+ msleep(1);
+
+ proc = false;
+
+ break;
+
+ case STATE_IDLE:
+ break;
+
+ default:
+ HDMIPRINTK("error state!!!\n");
+
+ ret = EINVAL;
+
+ proc = false;
+
+ break;
+ }
+ }
+
+ return ret;
+}
+
+int hdmi_phy_down(bool on, u8 addr, u8 offset, u8 *read_buffer)
+{
+ u8 buff[2] = {0};
+
+ buff[0] = addr;
+ buff[1] = (on) ? (read_buffer[addr] & (~(1<<offset))) :
+ (read_buffer[addr] | (1<<offset));
+
+ if (i2c_hdmi_phy_write(PHY_I2C_ADDRESS, 2, buff) != 0)
+ return EINVAL;
+
+ return 0;
+}
+
+int __s5p_hdmi_phy_power(bool on)
+{
+#if !defined(CONFIG_MACH_P1)
+ /* for the case that
+ - only analog tv is supported
+ - and the power for the hdmi phy is not supported*/
+ return 0;
+#endif
+
+ u32 size;
+ u8 *buffer;
+ u8 read_buffer[0x40] = {0, };
+
+ size = sizeof(phy_config[0][0])
+ / sizeof(phy_config[0][0][0]);
+
+ buffer = (u8 *) phy_config[0][0];
+
+ /* write offset */
+ if (i2c_hdmi_phy_write(PHY_I2C_ADDRESS, 1, buffer) != 0) {
+ HDMIPRINTK("%s I2C Write Error!...\n", __func__);
+ return EINVAL;
+ }
+
+ /* read data */
+ if (i2c_hdmi_phy_read(PHY_I2C_ADDRESS, size, read_buffer) != 0) {
+ HDMIPRINTK("i2c_hdmi_phy_read failed.\n");
+ return EINVAL;
+ }
+
+ /* i can't get the information about phy setting */
+ if (on) {
+ /* on */
+ /* biaspd */
+ hdmi_phy_down(true, 0x1, 0x5, read_buffer);
+ /* clockgenpd */
+ hdmi_phy_down(true, 0x1, 0x7, read_buffer);
+ /* pllpd */
+ hdmi_phy_down(true, 0x5, 0x5, read_buffer);
+ /* pcgpd */
+ hdmi_phy_down(true, 0x17, 0x0, read_buffer);
+ /* txpd */
+ hdmi_phy_down(true, 0x17, 0x1, read_buffer);
+ } else {
+ /* off */
+ /* biaspd */
+ hdmi_phy_down(false, 0x1, 0x5, read_buffer);
+ /* clockgenpd */
+ hdmi_phy_down(false, 0x1, 0x7, read_buffer);
+ /* pllpd */
+ hdmi_phy_down(false, 0x5, 0x5, read_buffer);
+ /* pcgpd */
+ hdmi_phy_down(false, 0x17, 0x0, read_buffer);
+ /* txpd */
+ hdmi_phy_down(false, 0x17, 0x1, read_buffer);
+ }
+
+ return 0;
+}
+
+s32 hdmi_corereset(void)
+{
+ writeb(0x0, hdmi_base + S5P_HDMI_CTRL_CORE_RSTOUT);
+
+ mdelay(10);
+
+ writeb(0x1, hdmi_base + S5P_HDMI_CTRL_CORE_RSTOUT);
+
+ return 0;
+}
+
+s32 hdmi_phy_config(enum phy_freq freq, enum s5p_hdmi_color_depth cd)
+{
+ s32 index;
+ s32 size;
+ u8 buffer[32] = {0, };
+ u8 reg;
+
+ switch (cd) {
+
+ case HDMI_CD_24:
+ index = 0;
+ break;
+
+ case HDMI_CD_30:
+ index = 1;
+ break;
+
+ case HDMI_CD_36:
+ index = 2;
+ break;
+
+ default:
+ return false;
+ }
+
+ /* i2c_hdmi init - set i2c filtering */
+ buffer[0] = PHY_REG_MODE_SET_DONE;
+ buffer[1] = 0x00;
+
+ if (i2c_hdmi_phy_write(PHY_I2C_ADDRESS, 2, buffer) != 0) {
+ HDMIPRINTK("i2c_hdmi_phy_write failed.\n");
+ return EINVAL;
+ }
+
+ writeb(0x5, i2c_hdmi_phy_base + I2C_HDMI_LC);
+
+ size = sizeof(phy_config[freq][index])
+ / sizeof(phy_config[freq][index][0]);
+
+ memcpy(buffer, phy_config[freq][index], sizeof(buffer));
+
+ if (i2c_hdmi_phy_write(PHY_I2C_ADDRESS, size, buffer) != 0)
+ return EINVAL;
+
+ /* write offset */
+ buffer[0] = 0x01;
+
+ if (i2c_hdmi_phy_write(PHY_I2C_ADDRESS, 1, buffer) != 0) {
+ HDMIPRINTK("i2c_hdmi_phy_write failed.\n");
+ return EINVAL;
+ }
+
+#ifdef S5P_HDMI_DEBUG
+ {
+ int i = 0;
+ u8 read_buffer[0x40] = {0, };
+
+ /* read data */
+ if (i2c_hdmi_phy_read(PHY_I2C_ADDRESS, size, read_buffer) != 0) {
+ HDMIPRINTK("i2c_hdmi_phy_read failed.\n");
+ return EINVAL;
+ }
+
+ HDMIPRINTK("read buffer :\n\t\t");
+
+ for (i = 1; i < size; i++) {
+
+ printk("0x%02x", read_buffer[i]);
+
+ if (i % 8)
+ printk(" ");
+ else
+ printk("\n\t\t");
+ }
+ printk("\n");
+}
+#endif
+ hdmi_corereset();
+
+ do {
+ reg = readb(hdmi_base + HDMI_PHY_STATUS);
+ } while (!(reg & HDMI_PHY_READY));
+
+ writeb(I2C_CLK_PEND_INT, i2c_hdmi_phy_base + I2C_HDMI_CON);
+ /* disable */
+ writeb(I2C_IDLE, i2c_hdmi_phy_base + I2C_HDMI_STAT);
+
+ return 0;
+}
+
+s32 hdmi_set_tg(enum s5p_hdmi_v_fmt mode)
+{
+ u16 temp_reg;
+ u8 tc_cmd;
+
+ temp_reg = hdmi_tg_param[mode].h_fsz;
+ writeb((u8)(temp_reg&0xff) , hdmi_base + S5P_TG_H_FSZ_L);
+ writeb((u8)(temp_reg >> 8) , hdmi_base + S5P_TG_H_FSZ_H);
+
+ /* set Horizontal Active Start Position */
+ temp_reg = hdmi_tg_param[mode].hact_st ;
+ writeb((u8)(temp_reg&0xff) , hdmi_base + S5P_TG_HACT_ST_L);
+ writeb((u8)(temp_reg >> 8) , hdmi_base + S5P_TG_HACT_ST_H);
+
+ /* set Horizontal Active Size */
+ temp_reg = hdmi_tg_param[mode].hact_sz ;
+ writeb((u8)(temp_reg&0xff) , hdmi_base + S5P_TG_HACT_SZ_L);
+ writeb((u8)(temp_reg >> 8) , hdmi_base + S5P_TG_HACT_SZ_H);
+
+ /* set Vertical Full Size */
+ temp_reg = hdmi_tg_param[mode].v_fsz ;
+ writeb((u8)(temp_reg&0xff) , hdmi_base + S5P_TG_V_FSZ_L);
+ writeb((u8)(temp_reg >> 8) , hdmi_base + S5P_TG_V_FSZ_H);
+
+ /* set VSYNC Position */
+ temp_reg = hdmi_tg_param[mode].vsync ;
+ writeb((u8)(temp_reg&0xff) , hdmi_base + S5P_TG_VSYNC_L);
+ writeb((u8)(temp_reg >> 8) , hdmi_base + S5P_TG_VSYNC_H);
+
+ /* set Bottom Field VSYNC Position */
+ temp_reg = hdmi_tg_param[mode].vsync2;
+ writeb((u8)(temp_reg&0xff) , hdmi_base + S5P_TG_VSYNC2_L);
+ writeb((u8)(temp_reg >> 8) , hdmi_base + S5P_TG_VSYNC2_H);
+
+ /* set Vertical Active Start Position */
+ temp_reg = hdmi_tg_param[mode].vact_st ;
+ writeb((u8)(temp_reg&0xff) , hdmi_base + S5P_TG_VACT_ST_L);
+ writeb((u8)(temp_reg >> 8) , hdmi_base + S5P_TG_VACT_ST_H);
+
+ /* set Vertical Active Size */
+ temp_reg = hdmi_tg_param[mode].vact_sz ;
+ writeb((u8)(temp_reg&0xff) , hdmi_base + S5P_TG_VACT_SZ_L);
+ writeb((u8)(temp_reg >> 8) , hdmi_base + S5P_TG_VACT_SZ_H);
+
+ /* set Field Change Position */
+ temp_reg = hdmi_tg_param[mode].field_chg ;
+ writeb((u8)(temp_reg&0xff) , hdmi_base + S5P_TG_FIELD_CHG_L);
+ writeb((u8)(temp_reg >> 8) , hdmi_base + S5P_TG_FIELD_CHG_H);
+
+ /* set Bottom Field Vertical Active Start Position */
+ temp_reg = hdmi_tg_param[mode].vact_st2;
+ writeb((u8)(temp_reg&0xff) , hdmi_base + S5P_TG_VACT_ST2_L);
+ writeb((u8)(temp_reg >> 8) , hdmi_base + S5P_TG_VACT_ST2_H);
+
+ /* set VSYNC Position for HDMI */
+ temp_reg = hdmi_tg_param[mode].vsync_top_hdmi;
+ writeb((u8)(temp_reg&0xff) , hdmi_base + S5P_TG_VSYNC_TOP_HDMI_L);
+ writeb((u8)(temp_reg >> 8) , hdmi_base + S5P_TG_VSYNC_TOP_HDMI_H);
+
+ /* set Bottom Field VSYNC Position */
+ temp_reg = hdmi_tg_param[mode].vsync_bot_hdmi;
+ writeb((u8)(temp_reg&0xff) , hdmi_base + S5P_TG_VSYNC_BOT_HDMI_L);
+ writeb((u8)(temp_reg >> 8) , hdmi_base + S5P_TG_VSYNC_BOT_HDMI_H);
+
+ /* set Top Field Change Position for HDMI */
+ temp_reg = hdmi_tg_param[mode].field_top_hdmi ;
+ writeb((u8)(temp_reg&0xff) , hdmi_base + S5P_TG_FIELD_TOP_HDMI_L);
+ writeb((u8)(temp_reg >> 8) , hdmi_base + S5P_TG_FIELD_TOP_HDMI_H);
+
+ /* set Bottom Field Change Position for HDMI */
+ temp_reg = hdmi_tg_param[mode].field_bot_hdmi ;
+ writeb((u8)(temp_reg&0xff) , hdmi_base + S5P_TG_FIELD_BOT_HDMI_L);
+ writeb((u8)(temp_reg >> 8) , hdmi_base + S5P_TG_FIELD_BOT_HDMI_H);
+
+ tc_cmd = readb(hdmi_base + S5P_TG_CMD);
+
+ if (video_params[mode].interlaced == 1)
+ /* Field Mode enable(interlace mode) */
+ tc_cmd |= (1<<1);
+ else
+ /* Field Mode disable */
+ tc_cmd &= ~(1<<1);
+
+ writeb(tc_cmd, hdmi_base + S5P_TG_CMD);
+
+ return 0;
+}
+
+/**
+ * Set registers related to color depth.
+ */
+static s32 hdmi_set_clr_depth(enum s5p_hdmi_color_depth cd)
+{
+ /* if color depth is supported by RX, set GCP packet */
+ switch (cd) {
+
+ case HDMI_CD_48:
+ writeb(GCP_CD_48BPP, hdmi_base + S5P_GCP_BYTE2);
+ break;
+
+ case HDMI_CD_36:
+ writeb(GCP_CD_36BPP, hdmi_base + S5P_GCP_BYTE2);
+ /* set DC register */
+ writeb(HDMI_DC_CTL_12, hdmi_base + S5P_HDMI_DC_CONTROL);
+ break;
+
+ case HDMI_CD_30:
+ writeb(GCP_CD_30BPP, hdmi_base + S5P_GCP_BYTE2);
+ /* set DC register */
+ writeb(HDMI_DC_CTL_10, hdmi_base + S5P_HDMI_DC_CONTROL);
+ break;
+
+ case HDMI_CD_24:
+ writeb(GCP_CD_24BPP, hdmi_base + S5P_GCP_BYTE2);
+ /* set DC register */
+ writeb(HDMI_DC_CTL_8, hdmi_base + S5P_HDMI_DC_CONTROL);
+ /* disable GCP */
+ writeb(DO_NOT_TRANSMIT, hdmi_base + S5P_GCP_CON);
+ break;
+
+ default:
+ HDMIPRINTK("HDMI core does not support \
+ requested Deep Color mode\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+s32 hdmi_set_video_mode(enum s5p_hdmi_v_fmt mode, enum s5p_hdmi_color_depth cd,
+ enum s5p_tv_hdmi_pxl_aspect pxl_ratio, u8 *avidata)
+{
+ u8 temp_reg8;
+ u16 temp_reg16;
+ u32 temp_reg32, temp_sync2, temp_sync3;
+
+ /* check if HDMI code support that mode */
+ if (mode > (sizeof(video_params)/sizeof(struct hdmi_v_params)) ||
+ (s32)mode < 0) {
+ HDMIPRINTK("This video mode is not Supported\n");
+ return -EINVAL;
+ }
+
+ hdmi_set_tg(mode);
+
+ /* set HBlank */
+ temp_reg16 = video_params[mode].h_blank;
+ writeb((u8)(temp_reg16&0xff), hdmi_base + S5P_H_BLANK_0);
+ writeb((u8)(temp_reg16 >> 8), hdmi_base + S5P_H_BLANK_1);
+
+ /* set VBlank */
+ temp_reg32 = video_params[mode].v_blank;
+ writeb((u8)(temp_reg32&0xff), hdmi_base + S5P_V_BLANK_0);
+ writeb((u8)(temp_reg32 >> 8), hdmi_base + S5P_V_BLANK_1);
+ writeb((u8)(temp_reg32 >> 16), hdmi_base + S5P_V_BLANK_2);
+
+ /* set HVLine */
+ temp_reg32 = video_params[mode].hvline;
+ writeb((u8)(temp_reg32&0xff), hdmi_base + S5P_H_V_LINE_0);
+ writeb((u8)(temp_reg32 >> 8), hdmi_base + S5P_H_V_LINE_1);
+ writeb((u8)(temp_reg32 >> 16), hdmi_base + S5P_H_V_LINE_2);
+
+ /* set VSYNC polarity */
+ writeb(video_params[mode].polarity, hdmi_base + S5P_SYNC_MODE);
+
+ /* set HSyncGen */
+ temp_reg32 = video_params[mode].h_sync_gen;
+ writeb((u8)(temp_reg32&0xff), hdmi_base + S5P_H_SYNC_GEN_0);
+ writeb((u8)(temp_reg32 >> 8), hdmi_base + S5P_H_SYNC_GEN_1);
+ writeb((u8)(temp_reg32 >> 16), hdmi_base + S5P_H_SYNC_GEN_2);
+
+ /* set VSyncGen1 */
+ temp_reg32 = video_params[mode].v_sync_gen;
+ writeb((u8)(temp_reg32&0xff), hdmi_base + S5P_V_SYNC_GEN_1_0);
+ writeb((u8)(temp_reg32 >> 8), hdmi_base + S5P_V_SYNC_GEN_1_1);
+ writeb((u8)(temp_reg32 >> 16), hdmi_base + S5P_V_SYNC_GEN_1_2);
+
+ if (video_params[mode].interlaced) {
+ /* set up v_blank_f, v_sync_gen2, v_sync_gen3 */
+ temp_reg32 = video_params[mode].v_blank_f;
+ temp_sync2 = video_params[mode].v_sync_gen2;
+ temp_sync3 = video_params[mode].v_sync_gen3;
+
+ writeb((u8)(temp_reg32 & 0xff), hdmi_base + S5P_V_BLANK_F_0);
+ writeb((u8)(temp_reg32 >> 8), hdmi_base + S5P_V_BLANK_F_1);
+ writeb((u8)(temp_reg32 >> 16), hdmi_base + S5P_V_BLANK_F_2);
+
+ writeb((u8)(temp_sync2 & 0xff),
+ hdmi_base + S5P_V_SYNC_GEN_2_0);
+ writeb((u8)(temp_sync2 >> 8), hdmi_base + S5P_V_SYNC_GEN_2_1);
+ writeb((u8)(temp_sync2 >> 16), hdmi_base + S5P_V_SYNC_GEN_2_2);
+
+ writeb((u8)(temp_sync3 & 0xff),
+ hdmi_base + S5P_V_SYNC_GEN_3_0);
+ writeb((u8)(temp_sync3 >> 8), hdmi_base + S5P_V_SYNC_GEN_3_1);
+ writeb((u8)(temp_sync3 >> 16), hdmi_base + S5P_V_SYNC_GEN_3_2);
+ } else {
+ /* progressive mode */
+ writeb(0x00, hdmi_base + S5P_V_BLANK_F_0);
+ writeb(0x00, hdmi_base + S5P_V_BLANK_F_1);
+ writeb(0x00, hdmi_base + S5P_V_BLANK_F_2);
+
+ writeb(0x01, hdmi_base + S5P_V_SYNC_GEN_2_0);
+ writeb(0x10, hdmi_base + S5P_V_SYNC_GEN_2_1);
+ writeb(0x00, hdmi_base + S5P_V_SYNC_GEN_2_2);
+
+ writeb(0x01, hdmi_base + S5P_V_SYNC_GEN_3_0);
+ writeb(0x10, hdmi_base + S5P_V_SYNC_GEN_3_1);
+ writeb(0x00, hdmi_base + S5P_V_SYNC_GEN_3_2);
+ }
+
+ /* set interlaced mode */
+ writeb(video_params[mode].interlaced, hdmi_base + S5P_INT_PRO_MODE);
+
+ /* pixel repetition */
+ temp_reg8 = readb(hdmi_base + S5P_HDMI_CON_1);
+
+ /* clear */
+ temp_reg8 &= ~HDMI_CON_PXL_REP_RATIO_MASK;
+
+ if (video_params[mode].repetition) {
+ /* set pixel repetition */
+ temp_reg8 |= HDMI_DOUBLE_PIXEL_REPETITION;
+ /* AVI Packet */
+ avidata[4] = AVI_PIXEL_REPETITION_DOUBLE;
+ } else { /* clear pixel repetition */
+ /* AVI Packet */
+ avidata[4] = 0;
+ }
+
+ /* set pixel repetition */
+ writeb(temp_reg8, hdmi_base + S5P_HDMI_CON_1);
+
+ /* set AVI packet VIC */
+
+ if (pxl_ratio == HDMI_PIXEL_RATIO_16_9)
+ avidata[3] = video_params[mode].avi_vic_16_9;
+ else
+ avidata[3] = video_params[mode].avi_vic;
+
+ /* clear */
+ temp_reg8 = readb(hdmi_base + S5P_AVI_BYTE2) &
+ ~(AVI_PICTURE_ASPECT_4_3 | AVI_PICTURE_ASPECT_16_9);
+
+ if (pxl_ratio == HDMI_PIXEL_RATIO_16_9)
+ temp_reg8 |= AVI_PICTURE_ASPECT_16_9;
+ else
+ temp_reg8 |= AVI_PICTURE_ASPECT_4_3;
+
+ /* set color depth */
+ if (hdmi_set_clr_depth(cd) != 0) {
+ HDMIPRINTK("[ERR] Can't set hdmi clr. depth.\n");
+ return -EINVAL;
+ }
+
+ if (video_params[mode].interlaced == 1) {
+ u32 gcp_con;
+
+ gcp_con = readb(hdmi_base + S5P_GCP_CON);
+ gcp_con |= (3<<2);
+
+ writeb(gcp_con, hdmi_base + S5P_GCP_CON);
+ } else {
+ u32 gcp_con;
+
+ gcp_con = readb(hdmi_base + S5P_GCP_CON);
+ gcp_con &= (~(3<<2));
+
+ writeb(gcp_con, hdmi_base + S5P_GCP_CON);
+ }
+
+#if 0
+ /* config Phy */
+ if (hdmi_phy_config(video_params[mode].pixel_clock, cd) == EINVAL) {
+ HDMIPRINTK("[ERR] hdmi_phy_config() failed.\n");
+ return EINVAL;
+ }
+#endif
+ return 0;
+}
+
+void __s5p_hdmi_set_hpd_onoff(bool on_off)
+{
+ HDMIPRINTK("hpd is %s\n\r", on_off ? "on" : "off");
+
+ if (on_off)
+ writel(SW_HPD_PLUGGED, hdmi_base + S5P_HPD);
+ else
+ writel(SW_HPD_UNPLUGGED, hdmi_base + S5P_HPD);
+
+
+ HDMIPRINTK("0x%08x\n\r", readl(hdmi_base + S5P_HPD));
+}
+
+void __s5p_hdmi_audio_set_config(enum s5p_tv_audio_codec_type audio_codec)
+{
+
+ u32 data_type = (audio_codec == PCM) ? CONFIG_LINEAR_PCM_TYPE :
+ (audio_codec == AC3) ? CONFIG_NON_LINEAR_PCM_TYPE :
+ 0xff;
+
+ HDMIPRINTK("audio codec type = %s\n\r",
+ (audio_codec&PCM) ? "PCM" :
+ (audio_codec&AC3) ? "AC3" :
+ (audio_codec&MP3) ? "MP3" :
+ (audio_codec&WMA) ? "WMA" : "Unknown");
+
+ /* open SPDIF path on HDMI_I2S */
+ writel(0x01, hdmi_base + S5P_HDMI_I2S_CLK_CON);
+ writel(readl(hdmi_base + S5P_HDMI_I2S_MUX_CON) | 0x11,
+ hdmi_base + S5P_HDMI_I2S_MUX_CON);
+ writel(0xFF, hdmi_base + S5P_HDMI_I2S_MUX_CH);
+ writel(0x03, hdmi_base + S5P_HDMI_I2S_MUX_CUV);
+
+ writel(CONFIG_FILTER_2_SAMPLE | data_type
+ | CONFIG_PCPD_MANUAL_SET | CONFIG_WORD_LENGTH_MANUAL_SET
+ | CONFIG_U_V_C_P_REPORT | CONFIG_BURST_SIZE_2
+ | CONFIG_DATA_ALIGN_32BIT
+ , hdmi_base + S5P_SPDIFIN_CONFIG_1);
+ writel(0, hdmi_base + S5P_SPDIFIN_CONFIG_2);
+}
+
+void __s5p_hdmi_audio_set_acr(u32 sample_rate)
+{
+ u32 value_n = (sample_rate == 32000) ? 4096 :
+ (sample_rate == 44100) ? 6272 :
+ (sample_rate == 88200) ? 12544 :
+ (sample_rate == 176400) ? 25088 :
+ (sample_rate == 48000) ? 6144 :
+ (sample_rate == 96000) ? 12288 :
+ (sample_rate == 192000) ? 24576 : 0;
+
+ u32 cts = (sample_rate == 32000) ? 27000 :
+ (sample_rate == 44100) ? 30000 :
+ (sample_rate == 88200) ? 30000 :
+ (sample_rate == 176400) ? 30000 :
+ (sample_rate == 48000) ? 27000 :
+ (sample_rate == 96000) ? 27000 :
+ (sample_rate == 192000) ? 27000 : 0;
+
+ HDMIPRINTK("sample rate = %d\n\r", sample_rate);
+ HDMIPRINTK("cts = %d\n\r", cts);
+
+ writel(value_n & 0xff, hdmi_base + S5P_ACR_N0);
+ writel((value_n >> 8) & 0xff, hdmi_base + S5P_ACR_N1);
+ writel((value_n >> 16) & 0xff, hdmi_base + S5P_ACR_N2);
+
+ writel(cts & 0xff, hdmi_base + S5P_ACR_MCTS0);
+ writel((cts >> 8) & 0xff, hdmi_base + S5P_ACR_MCTS1);
+ writel((cts >> 16) & 0xff, hdmi_base + S5P_ACR_MCTS2);
+
+ writel(cts & 0xff, hdmi_base + S5P_ACR_CTS0);
+ writel((cts >> 8) & 0xff, hdmi_base + S5P_ACR_CTS1);
+ writel((cts >> 16) & 0xff, hdmi_base + S5P_ACR_CTS2);
+
+ writel(4, hdmi_base + S5P_ACR_CON);
+}
+
+void __s5p_hdmi_audio_set_asp(void)
+{
+ writel(0x0, hdmi_base + S5P_ASP_CON);
+ /* All Subpackets contain audio samples */
+ writel(0x0, hdmi_base + S5P_ASP_SP_FLAT);
+
+ writel(1 << 3 | 0, hdmi_base + S5P_ASP_CHCFG0);
+ writel(1 << 3 | 0, hdmi_base + S5P_ASP_CHCFG1);
+ writel(1 << 3 | 0, hdmi_base + S5P_ASP_CHCFG2);
+ writel(1 << 3 | 0, hdmi_base + S5P_ASP_CHCFG3);
+}
+
+void __s5p_hdmi_audio_clock_enable(void)
+{
+ writel(0x1, hdmi_base + S5P_SPDIFIN_CLK_CTRL);
+ /* HDMI operation mode */
+ writel(0x3, hdmi_base + S5P_SPDIFIN_OP_CTRL);
+}
+
+
+void __s5p_hdmi_audio_set_repetition_time(
+ enum s5p_tv_audio_codec_type audio_codec,
+ u32 bits, u32 frame_size_code)
+{
+ /* Only 4'b1011 24bit */
+ u32 wl = 5 << 1 | 1;
+ u32 rpt_cnt = (audio_codec == AC3) ? 1536 * 2 - 1 : 0;
+
+ HDMIPRINTK("repetition count = %d\n\r", rpt_cnt);
+
+ /* 24bit and manual mode */
+ writel(((rpt_cnt&0xf) << 4) | wl,
+ hdmi_base + S5P_SPDIFIN_USER_VALUE_1);
+ /* if PCM this value is 0 */
+ writel((rpt_cnt >> 4)&0xff,
+ hdmi_base + S5P_SPDIFIN_USER_VALUE_2);
+ /* if PCM this value is 0 */
+ writel(frame_size_code&0xff,
+ hdmi_base + S5P_SPDIFIN_USER_VALUE_3);
+ /* if PCM this value is 0 */
+ writel((frame_size_code >> 8)&0xff,
+ hdmi_base + S5P_SPDIFIN_USER_VALUE_4);
+}
+
+void __s5p_hdmi_audio_irq_enable(u32 irq_en)
+{
+ writel(irq_en, hdmi_base + S5P_SPDIFIN_IRQ_MASK);
+}
+
+
+void __s5p_hdmi_audio_set_aui(enum s5p_tv_audio_codec_type audio_codec,
+ u32 sample_rate,
+ u32 bits)
+{
+ u8 sum_of_bits, bytes1, bytes2, bytes3, check_sum;
+#if 1
+ /* Fix TestID 7-31 Audio InfoFrame issue*/
+ u32 bit_rate;
+ u32 type = 0;
+ u32 ch = (audio_codec == PCM) ? 1 : 0;
+ u32 sample = 0;
+ u32 bpsType = 0;
+#else
+ /* Ac3 16bit only */
+ u32 bps = (audio_codec == PCM) ? bits : 16;
+
+ /* AUI Packet set. */
+ u32 type = (audio_codec == PCM) ? 1 : /* PCM */
+ (audio_codec == AC3) ? 2 : 0;
+ /* AC3 or Refer stream header */
+ u32 ch = (audio_codec == PCM) ? 1 : 0;
+ /* 2ch or refer to stream header */
+
+ u32 sample = (sample_rate == 32000) ? 1 :
+ (sample_rate == 44100) ? 2 :
+ (sample_rate == 48000) ? 3 :
+ (sample_rate == 88200) ? 4 :
+ (sample_rate == 96000) ? 5 :
+ (sample_rate == 176400) ? 6 :
+ (sample_rate == 192000) ? 7 : 0;
+
+ u32 bpsType = (bps == 16) ? 1 :
+ (bps == 20) ? 2 :
+ (bps == 24) ? 3 : 0;
+#endif
+
+ bpsType = (audio_codec == PCM) ? bpsType : 0;
+
+ sum_of_bits = (0x84 + 0x1 + 10);
+
+ bytes1 = (u8)((type << 4) | ch);
+
+ bytes2 = (u8)((sample << 2) | bpsType);
+
+ bit_rate = 256;
+
+ bytes3 = (audio_codec == PCM) ? (u8)0 : (u8)(bit_rate / 8) ;
+
+
+ sum_of_bits += (bytes1 + bytes2 + bytes3);
+ check_sum = 256 - sum_of_bits;
+
+ /* AUI Packet set. */
+ writel(check_sum , hdmi_base + S5P_AUI_CHECK_SUM);
+ writel(bytes1 , hdmi_base + S5P_AUI_BYTE1);
+ writel(bytes2 , hdmi_base + S5P_AUI_BYTE2);
+ writel(bytes3 , hdmi_base + S5P_AUI_BYTE3);/* Pcm or stream */
+ writel(0x00 , hdmi_base + S5P_AUI_BYTE4); /* 2ch pcm or Stream */
+ writel(0x00 , hdmi_base + S5P_AUI_BYTE5); /* 2ch pcm or Stream */
+
+ writel(HDMI_DO_NOT_TANS, hdmi_base + S5P_ACP_CON);
+ writel(1 , hdmi_base + S5P_ACP_TYPE);
+
+ writel(0x10 , hdmi_base + S5P_GCP_BYTE1);
+ /*
+ * packet will be transmitted within 384 cycles
+ * after active sync.
+ */
+}
+
+void __s5p_hdmi_video_set_bluescreen(bool en,
+ u8 cb_b,
+ u8 y_g,
+ u8 cr_r)
+{
+ HDMIPRINTK("%d, %d, %d, %d\n\r", en, cb_b, y_g, cr_r);
+
+ if (en) {
+ writel(SET_BLUESCREEN_0(cb_b), hdmi_base + S5P_BLUE_SCREEN_0);
+ writel(SET_BLUESCREEN_1(y_g), hdmi_base + S5P_BLUE_SCREEN_1);
+ writel(SET_BLUESCREEN_2(cr_r), hdmi_base + S5P_BLUE_SCREEN_2);
+ writel(readl(hdmi_base + S5P_HDMI_CON_0) | BLUE_SCR_EN,
+ hdmi_base + S5P_HDMI_CON_0);
+
+ HDMIPRINTK("HDMI_BLUE_SCREEN0 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_BLUE_SCREEN_0));
+ HDMIPRINTK("HDMI_BLUE_SCREEN1 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_BLUE_SCREEN_1));
+ HDMIPRINTK("HDMI_BLUE_SCREEN2 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_BLUE_SCREEN_2));
+ } else
+ writel(readl(hdmi_base + S5P_HDMI_CON_0)&~BLUE_SCR_EN,
+ hdmi_base + S5P_HDMI_CON_0);
+
+ HDMIPRINTK("HDMI_CON0 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_HDMI_CON_0));
+}
+
+enum s5p_tv_hdmi_err __s5p_hdmi_init_spd_infoframe(
+ enum s5p_hdmi_transmit trans_type,
+ u8 *spd_header,
+ u8 *spd_data)
+{
+ HDMIPRINTK("%d, %d, %d\n\r", (u32)trans_type,
+ (u32)spd_header,
+ (u32)spd_data);
+
+ switch (trans_type) {
+
+ case HDMI_DO_NOT_TANS:
+ writel(SPD_TX_CON_NO_TRANS, hdmi_base + S5P_SPD_CON);
+ break;
+
+ case HDMI_TRANS_ONCE:
+ writel(SPD_TX_CON_TRANS_ONCE, hdmi_base + S5P_SPD_CON);
+ break;
+
+ case HDMI_TRANS_EVERY_SYNC:
+ writel(SPD_TX_CON_TRANS_EVERY_VSYNC, hdmi_base + S5P_SPD_CON);
+ break;
+
+ default:
+ HDMIPRINTK(" invalid out_mode parameter(%d)\n\r", trans_type);
+ return S5P_TV_HDMI_ERR_INVALID_PARAM;
+ break;
+ }
+
+ /*
+ * spd_data, spd_header be specified by Vendor's specific
+ * data. below codes is sample usage
+ */
+
+ if (spd_data == NULL || spd_header == NULL) {
+ HDMIPRINTK("Set default SPD\n");
+ writel(SET_SPD_HEADER(0x83), hdmi_base + S5P_SPD_HEADER0);
+ writel(SET_SPD_HEADER(0x01), hdmi_base + S5P_SPD_HEADER1);
+ writel(SET_SPD_HEADER(0x19), hdmi_base + S5P_SPD_HEADER2);
+
+ writel(0x0, hdmi_base + S5P_SPD_DATA0);
+ writel(SET_SPD_DATA('S'), hdmi_base + S5P_SPD_DATA1);
+ writel(SET_SPD_DATA('A'), hdmi_base + S5P_SPD_DATA2);
+ writel(SET_SPD_DATA('M'), hdmi_base + S5P_SPD_DATA3);
+ writel(SET_SPD_DATA('S'), hdmi_base + S5P_SPD_DATA4);
+ writel(SET_SPD_DATA('U'), hdmi_base + S5P_SPD_DATA5);
+ writel(SET_SPD_DATA('N'), hdmi_base + S5P_SPD_DATA6);
+ writel(SET_SPD_DATA('G'), hdmi_base + S5P_SPD_DATA7);
+
+ writel(0x0, hdmi_base + S5P_SPD_DATA8);
+ writel(SET_SPD_DATA('S'), hdmi_base + S5P_SPD_DATA9);
+ writel(SET_SPD_DATA('5'), hdmi_base + S5P_SPD_DATA10);
+ writel(SET_SPD_DATA('P'), hdmi_base + S5P_SPD_DATA11);
+ writel(SET_SPD_DATA('C'), hdmi_base + S5P_SPD_DATA12);
+ writel(SET_SPD_DATA('1'), hdmi_base + S5P_SPD_DATA13);
+ writel(SET_SPD_DATA('1'), hdmi_base + S5P_SPD_DATA14);
+ writel(SET_SPD_DATA('0'), hdmi_base + S5P_SPD_DATA15);
+ writel(0x0, hdmi_base + S5P_SPD_DATA16);
+ writel(0x0, hdmi_base + S5P_SPD_DATA17);
+ writel(0x0, hdmi_base + S5P_SPD_DATA18);
+ writel(0x0, hdmi_base + S5P_SPD_DATA19);
+ writel(0x0, hdmi_base + S5P_SPD_DATA20);
+ writel(0x0, hdmi_base + S5P_SPD_DATA21);
+ writel(0x0, hdmi_base + S5P_SPD_DATA22);
+ writel(0x0, hdmi_base + S5P_SPD_DATA23);
+ writel(0x0, hdmi_base + S5P_SPD_DATA24);
+ writel(0x0, hdmi_base + S5P_SPD_DATA25);
+ writel(SET_SPD_DATA(0x2), hdmi_base + S5P_SPD_DATA26);
+ writel(0x0, hdmi_base + S5P_SPD_DATA27);
+ } else {
+
+ writel(SET_SPD_HEADER(*(spd_header)),
+ hdmi_base + S5P_SPD_HEADER0);
+
+ writel(SET_SPD_HEADER(*(spd_header + 1)) ,
+ hdmi_base + S5P_SPD_HEADER1);
+ writel(SET_SPD_HEADER(*(spd_header + 2)) ,
+ hdmi_base + S5P_SPD_HEADER2);
+
+ writel(SET_SPD_DATA(*(spd_data)) ,
+ hdmi_base + S5P_SPD_DATA0);
+ writel(SET_SPD_DATA(*(spd_data + 1)) ,
+ hdmi_base + S5P_SPD_DATA1);
+ writel(SET_SPD_DATA(*(spd_data + 2)) ,
+ hdmi_base + S5P_SPD_DATA2);
+ writel(SET_SPD_DATA(*(spd_data + 3)) ,
+ hdmi_base + S5P_SPD_DATA3);
+ writel(SET_SPD_DATA(*(spd_data + 4)) ,
+ hdmi_base + S5P_SPD_DATA4);
+ writel(SET_SPD_DATA(*(spd_data + 5)) ,
+ hdmi_base + S5P_SPD_DATA5);
+ writel(SET_SPD_DATA(*(spd_data + 6)) ,
+ hdmi_base + S5P_SPD_DATA6);
+ writel(SET_SPD_DATA(*(spd_data + 7)) ,
+ hdmi_base + S5P_SPD_DATA7);
+ writel(SET_SPD_DATA(*(spd_data + 8)) ,
+ hdmi_base + S5P_SPD_DATA8);
+ writel(SET_SPD_DATA(*(spd_data + 9)) ,
+ hdmi_base + S5P_SPD_DATA9);
+ writel(SET_SPD_DATA(*(spd_data + 10)) ,
+ hdmi_base + S5P_SPD_DATA10);
+ writel(SET_SPD_DATA(*(spd_data + 11)) ,
+ hdmi_base + S5P_SPD_DATA11);
+ writel(SET_SPD_DATA(*(spd_data + 12)) ,
+ hdmi_base + S5P_SPD_DATA12);
+ writel(SET_SPD_DATA(*(spd_data + 13)) ,
+ hdmi_base + S5P_SPD_DATA13);
+ writel(SET_SPD_DATA(*(spd_data + 14)) ,
+ hdmi_base + S5P_SPD_DATA14);
+ writel(SET_SPD_DATA(*(spd_data + 15)) ,
+ hdmi_base + S5P_SPD_DATA15);
+ writel(SET_SPD_DATA(*(spd_data + 16)) ,
+ hdmi_base + S5P_SPD_DATA16);
+ writel(SET_SPD_DATA(*(spd_data + 17)) ,
+ hdmi_base + S5P_SPD_DATA17);
+ writel(SET_SPD_DATA(*(spd_data + 18)) ,
+ hdmi_base + S5P_SPD_DATA18);
+ writel(SET_SPD_DATA(*(spd_data + 19)) ,
+ hdmi_base + S5P_SPD_DATA19);
+ writel(SET_SPD_DATA(*(spd_data + 20)) ,
+ hdmi_base + S5P_SPD_DATA20);
+ writel(SET_SPD_DATA(*(spd_data + 21)) ,
+ hdmi_base + S5P_SPD_DATA21);
+ writel(SET_SPD_DATA(*(spd_data + 22)) ,
+ hdmi_base + S5P_SPD_DATA22);
+ writel(SET_SPD_DATA(*(spd_data + 23)) ,
+ hdmi_base + S5P_SPD_DATA23);
+ writel(SET_SPD_DATA(*(spd_data + 24)) ,
+ hdmi_base + S5P_SPD_DATA24);
+ writel(SET_SPD_DATA(*(spd_data + 25)) ,
+ hdmi_base + S5P_SPD_DATA25);
+ writel(SET_SPD_DATA(*(spd_data + 26)) ,
+ hdmi_base + S5P_SPD_DATA26);
+ writel(SET_SPD_DATA(*(spd_data + 27)) ,
+ hdmi_base + S5P_SPD_DATA27);
+ }
+
+ HDMIPRINTK("SPD_CON = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_CON));
+ HDMIPRINTK("SPD_HEADER0 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_HEADER0));
+ HDMIPRINTK("SPD_HEADER1 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_HEADER1));
+ HDMIPRINTK("SPD_HEADER2 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_HEADER2));
+ HDMIPRINTK("SPD_DATA0 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA0));
+ HDMIPRINTK("SPD_DATA1 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA1));
+ HDMIPRINTK("SPD_DATA2 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA2));
+ HDMIPRINTK("SPD_DATA3 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA3));
+ HDMIPRINTK("SPD_DATA4 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA4));
+ HDMIPRINTK("SPD_DATA5 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA5));
+ HDMIPRINTK("SPD_DATA6 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA6));
+ HDMIPRINTK("SPD_DATA7 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA7));
+ HDMIPRINTK("SPD_DATA8 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA8));
+ HDMIPRINTK("SPD_DATA9 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA9));
+ HDMIPRINTK("SPD_DATA10 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA10));
+ HDMIPRINTK("SPD_DATA11 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA11));
+ HDMIPRINTK("SPD_DATA12 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA12));
+ HDMIPRINTK("SPD_DATA13 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA13));
+ HDMIPRINTK("SPD_DATA14 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA14));
+ HDMIPRINTK("SPD_DATA15 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA15));
+ HDMIPRINTK("SPD_DATA16 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA16));
+ HDMIPRINTK("SPD_DATA17 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA17));
+ HDMIPRINTK("SPD_DATA18 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA18));
+ HDMIPRINTK("SPD_DATA19 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA19));
+ HDMIPRINTK("SPD_DATA20 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA20));
+ HDMIPRINTK("SPD_DATA21 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA21));
+ HDMIPRINTK("SPD_DATA22 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA22));
+ HDMIPRINTK("SPD_DATA23 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA23));
+ HDMIPRINTK("SPD_DATA24 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA24));
+ HDMIPRINTK("SPD_DATA25 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA25));
+ HDMIPRINTK("SPD_DATA26 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA26));
+ HDMIPRINTK("SPD_DATA27 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_SPD_DATA27));
+
+ return HDMI_NO_ERROR;
+}
+
+void __s5p_hdmi_init_hpd_onoff(bool on_off)
+{
+ HDMIPRINTK("%d\n\r", on_off);
+ __s5p_hdmi_set_hpd_onoff(on_off);
+ HDMIPRINTK("0x%08x\n\r", readl(hdmi_base + S5P_HPD));
+}
+
+#ifndef CONFIG_SND_S5P_SPDIF
+static void __s5p_hdmi_audio_i2s_config(
+ enum s5p_tv_audio_codec_type audio_codec,
+ u32 sample_rate,
+ u32 bits_per_sample,
+ u32 frame_size_code)
+{
+ u32 data_num, bit_ch, sample_frq;
+
+ if (bits_per_sample == 20) {
+ data_num = 2;
+ bit_ch = 1;
+ } else if (bits_per_sample == 24) {
+ data_num = 3;
+ bit_ch = 1;
+ } else {
+ data_num = 1;
+ bit_ch = 0;
+ }
+ sample_frq = (sample_rate == 44100) ? 0 :
+ (sample_rate == 48000) ? 2 :
+ (sample_rate == 32000) ? 3 :
+ (sample_rate == 96000) ? 0xa : 0x0;
+
+ /* readl(hdmi_base + S5P_HDMI_YMAX) */
+ writel(0x00, hdmi_base + S5P_HDMI_I2S_CLK_CON);
+ writel(0x01, hdmi_base + S5P_HDMI_I2S_CLK_CON);
+
+ writel(readl(hdmi_base + S5P_HDMI_I2S_DSD_CON) | 0x01,
+ hdmi_base + S5P_HDMI_I2S_DSD_CON);
+
+ /* Configuration I2S input ports. Configure I2S_PIN_SEL_0~4 */
+ writel((readl(hdmi_base + S5P_HDMI_I2S_PIN_SEL_0) &
+ ~(7<<4 | 7<<0)) | (5<<4|6<<0),
+ hdmi_base + S5P_HDMI_I2S_PIN_SEL_0);
+ writel((readl(hdmi_base + S5P_HDMI_I2S_PIN_SEL_1) &
+ ~(7<<4 | 7<<0)) | (1<<4|4<<0),
+ hdmi_base + S5P_HDMI_I2S_PIN_SEL_1);
+ writel((readl(hdmi_base + S5P_HDMI_I2S_PIN_SEL_2) &
+ ~(7<<4 | 7<<0)) | (1<<4|2<<0),
+ hdmi_base + S5P_HDMI_I2S_PIN_SEL_2);
+ writel((readl(hdmi_base + S5P_HDMI_I2S_PIN_SEL_3) &
+ ~(7<<0)) | (0<<0),
+ hdmi_base + S5P_HDMI_I2S_PIN_SEL_3);
+
+ /* I2S_CON_1 & 2 */
+ writel((readl(hdmi_base + S5P_HDMI_I2S_CON_1) &
+ ~(1<<1 | 1<<0)) | (1<<1|0<<0),
+ hdmi_base + S5P_HDMI_I2S_CON_1);
+ writel((readl(hdmi_base + S5P_HDMI_I2S_CON_2) &
+ ~(1<<6 | 3<<4 | 3<<2 | 3<<0))
+ | (0<<6 | bit_ch<<4 | data_num<<2 | 0<<0),
+ hdmi_base + S5P_HDMI_I2S_CON_2);
+
+ /* Configure register related to CUV information */
+ writel((readl(hdmi_base + S5P_HDMI_I2S_CH_ST_0) &
+ ~(3<<6 | 7<<3 | 1<<2 | 1<<1 | 1<<0))
+ | (0<<6 | 0<<3 | 0<<2 | 0<<1 | 1<<0),
+ hdmi_base + S5P_HDMI_I2S_CH_ST_0);
+ writel((readl(hdmi_base + S5P_HDMI_I2S_CH_ST_1) &
+ ~(0xff<<0)) | (0<<0),
+ hdmi_base + S5P_HDMI_I2S_CH_ST_1);
+ writel((readl(hdmi_base + S5P_HDMI_I2S_CH_ST_2) &
+ ~(0xff<<0)) | (0<<0),
+ hdmi_base + S5P_HDMI_I2S_CH_ST_2);
+ writel((readl(hdmi_base + S5P_HDMI_I2S_CH_ST_3) &
+ ~(3<<4 | 0xf<<0))
+ | (0<<4 | sample_frq<<0),
+ hdmi_base + S5P_HDMI_I2S_CH_ST_3);
+ writel((readl(hdmi_base + S5P_HDMI_I2S_CH_ST_4) &
+ ~(0xf<<4 | 7<<1 | 1<<0))
+ | (0xf<<4 | 5<<1 | 1<<0),
+ hdmi_base + S5P_HDMI_I2S_CH_ST_4);
+
+ writel(0x00, hdmi_base + S5P_HDMI_I2S_CH_ST_SH_0);
+ writel(0x00, hdmi_base + S5P_HDMI_I2S_CH_ST_SH_1);
+ writel(0x00, hdmi_base + S5P_HDMI_I2S_CH_ST_SH_2);
+ writel(0x00, hdmi_base + S5P_HDMI_I2S_CH_ST_SH_3);
+ writel(0x00, hdmi_base + S5P_HDMI_I2S_CH_ST_SH_4);
+
+ writel((readl(hdmi_base + S5P_HDMI_I2S_CH_ST_CON) &
+ ~(1<<0)) | (1<<0),
+ hdmi_base + S5P_HDMI_I2S_CH_ST_CON);
+
+ writel((readl(hdmi_base + S5P_HDMI_I2S_MUX_CON) &
+ ~(1<<4 | 3<<2 | 1<<1 | 1<<0))
+ | (1<<4 | 1<<2 | 1<<1 | 1<<0),
+ hdmi_base + S5P_HDMI_I2S_MUX_CON);
+
+ writel((readl(hdmi_base + S5P_HDMI_I2S_MUX_CH) &
+ ~(0xff<<0)) | (0x3f<<0),
+ hdmi_base + S5P_HDMI_I2S_MUX_CH);
+
+ writel((readl(hdmi_base + S5P_HDMI_I2S_MUX_CUV) &
+ ~(0x3<<0)) | (0x3<<0),
+ hdmi_base + S5P_HDMI_I2S_MUX_CUV);
+}
+#endif
+
+enum s5p_tv_hdmi_err __s5p_hdmi_audio_init(
+ enum s5p_tv_audio_codec_type audio_codec,
+ u32 sample_rate, u32 bits, u32 frame_size_code)
+{
+#ifdef CONFIG_SND_S5P_SPDIF
+ __s5p_hdmi_audio_set_config(audio_codec);
+ __s5p_hdmi_audio_set_repetition_time(audio_codec, bits,
+ frame_size_code);
+ __s5p_hdmi_audio_irq_enable(IRQ_BUFFER_OVERFLOW_ENABLE);
+ __s5p_hdmi_audio_clock_enable();
+#else
+ __s5p_hdmi_audio_i2s_config(audio_codec, sample_rate, bits,
+ frame_size_code);
+#endif
+ __s5p_hdmi_audio_set_asp();
+ __s5p_hdmi_audio_set_acr(sample_rate);
+
+ __s5p_hdmi_audio_set_aui(audio_codec, sample_rate, bits);
+
+ return HDMI_NO_ERROR;
+}
+
+enum s5p_tv_hdmi_err __s5p_hdmi_video_init_display_mode(
+ enum s5p_tv_disp_mode disp_mode,
+ enum s5p_tv_o_mode out_mode, u8 *avidata)
+{
+ enum s5p_hdmi_v_fmt hdmi_v_fmt;
+ enum s5p_tv_hdmi_pxl_aspect aspect;
+
+ HDMIPRINTK("disp mode %d, output mode%d\n\r", disp_mode, out_mode);
+
+ aspect = HDMI_PIXEL_RATIO_16_9;
+
+ switch (disp_mode) {
+ /* 480p */
+ case TVOUT_480P_60_16_9:
+ hdmi_v_fmt = v720x480p_60Hz;
+ break;
+
+ case TVOUT_480P_60_4_3:
+ hdmi_v_fmt = v720x480p_60Hz;
+ aspect = HDMI_PIXEL_RATIO_4_3;
+ break;
+
+ case TVOUT_480P_59:
+ hdmi_v_fmt = v720x480p_59Hz;
+ break;
+
+ /* 576p */
+ case TVOUT_576P_50_16_9:
+ hdmi_v_fmt = v720x576p_50Hz;
+ break;
+
+ case TVOUT_576P_50_4_3:
+ hdmi_v_fmt = v720x576p_50Hz;
+ aspect = HDMI_PIXEL_RATIO_4_3;
+ break;
+
+ /* 720p */
+ case TVOUT_720P_60:
+ hdmi_v_fmt = v1280x720p_60Hz;
+ break;
+
+ case TVOUT_720P_59:
+ hdmi_v_fmt = v1280x720p_59Hz;
+ break;
+
+ case TVOUT_720P_50:
+ hdmi_v_fmt = v1280x720p_50Hz;
+ break;
+
+ /* 1080p */
+ case TVOUT_1080P_30:
+ hdmi_v_fmt = v1920x1080p_30Hz;
+ break;
+
+ case TVOUT_1080P_60:
+ hdmi_v_fmt = v1920x1080p_60Hz;
+ break;
+
+ case TVOUT_1080P_59:
+ hdmi_v_fmt = v1920x1080p_59Hz;
+ break;
+
+ case TVOUT_1080P_50:
+ hdmi_v_fmt = v1920x1080p_50Hz;
+ break;
+
+ /* 1080i */
+ case TVOUT_1080I_60:
+ hdmi_v_fmt = v1920x1080i_60Hz;
+ break;
+
+ case TVOUT_1080I_59:
+ hdmi_v_fmt = v1920x1080i_59Hz;
+ break;
+
+ case TVOUT_1080I_50:
+ hdmi_v_fmt = v1920x1080i_50Hz;
+ break;
+
+ default:
+ HDMIPRINTK(" invalid disp_mode parameter(%d)\n\r", disp_mode);
+ return S5P_TV_HDMI_ERR_INVALID_PARAM;
+ break;
+ }
+
+ if (hdmi_phy_config(video_params[hdmi_v_fmt].pixel_clock, HDMI_CD_24)
+ == EINVAL) {
+ HDMIPRINTK("[ERR] hdmi_phy_config() failed.\n");
+ return EINVAL;
+ }
+
+ switch (out_mode) {
+ case TVOUT_OUTPUT_HDMI_RGB:
+ s5p_hdmi_set_dvi(false);
+ writel(PX_LMT_CTRL_RGB, hdmi_base + S5P_HDMI_CON_1);
+ writel(VID_PREAMBLE_EN | GUARD_BAND_EN,
+ hdmi_base + S5P_HDMI_CON_2);
+ writel(HDMI_MODE_EN | DVI_MODE_DIS,
+ hdmi_base + S5P_MODE_SEL);
+
+ /* there's no ACP packet api */
+ writel(HDMI_DO_NOT_TANS , hdmi_base + S5P_ACP_CON);
+ writel(HDMI_TRANS_EVERY_SYNC , hdmi_base + S5P_AUI_CON);
+ break;
+
+ case TVOUT_OUTPUT_HDMI:
+ s5p_hdmi_set_dvi(false);
+ writel(PX_LMT_CTRL_BYPASS, hdmi_base + S5P_HDMI_CON_1);
+ writel(VID_PREAMBLE_EN | GUARD_BAND_EN,
+ hdmi_base + S5P_HDMI_CON_2);
+ writel(HDMI_MODE_EN | DVI_MODE_DIS,
+ hdmi_base + S5P_MODE_SEL);
+
+ /* there's no ACP packet api */
+ writel(HDMI_DO_NOT_TANS , hdmi_base + S5P_ACP_CON);
+ writel(HDMI_TRANS_EVERY_SYNC , hdmi_base + S5P_AUI_CON);
+ break;
+
+
+ case TVOUT_OUTPUT_DVI:
+ s5p_hdmi_set_dvi(true);
+ writel(PX_LMT_CTRL_RGB, hdmi_base + S5P_HDMI_CON_1);
+ writel(VID_PREAMBLE_DIS | GUARD_BAND_DIS,
+ hdmi_base + S5P_HDMI_CON_2);
+ writel(HDMI_MODE_DIS | DVI_MODE_EN,
+ hdmi_base + S5P_MODE_SEL);
+
+ /* disable ACP & Audio Info.frame packet */
+ writel(HDMI_DO_NOT_TANS , hdmi_base + S5P_ACP_CON);
+ writel(HDMI_DO_NOT_TANS , hdmi_base + S5P_AUI_CON);
+ break;
+
+ default:
+ HDMIPRINTK("invalid out_mode parameter(%d)\n\r", out_mode);
+ return S5P_TV_HDMI_ERR_INVALID_PARAM;
+ break;
+ }
+
+ hdmi_set_video_mode(hdmi_v_fmt, HDMI_CD_24, aspect, avidata);
+
+ return HDMI_NO_ERROR;
+}
+
+void __s5p_hdmi_video_init_bluescreen(bool en,
+ u8 cb_b,
+ u8 y_g,
+ u8 cr_r)
+{
+ __s5p_hdmi_video_set_bluescreen(en, cb_b, y_g, cr_r);
+
+}
+
+void __s5p_hdmi_video_init_color_range(u8 y_min,
+ u8 y_max,
+ u8 c_min,
+ u8 c_max)
+{
+ HDMIPRINTK("%d, %d, %d, %d\n\r", y_max, y_min, c_max, c_min);
+
+ writel(y_max, hdmi_base + S5P_HDMI_YMAX);
+ writel(y_min, hdmi_base + S5P_HDMI_YMIN);
+ writel(c_max, hdmi_base + S5P_HDMI_CMAX);
+ writel(c_min, hdmi_base + S5P_HDMI_CMIN);
+
+ HDMIPRINTK("HDMI_YMAX = 0x%08x \n\r",
+ readl(hdmi_base + S5P_HDMI_YMAX));
+ HDMIPRINTK("HDMI_YMIN = 0x%08x \n\r",
+ readl(hdmi_base + S5P_HDMI_YMIN));
+ HDMIPRINTK("HDMI_CMAX = 0x%08x \n\r",
+ readl(hdmi_base + S5P_HDMI_CMAX));
+ HDMIPRINTK("HDMI_CMIN = 0x%08x \n\r",
+ readl(hdmi_base + S5P_HDMI_CMIN));
+}
+
+enum s5p_tv_hdmi_err __s5p_hdmi_video_init_csc(
+ enum s5p_tv_hdmi_csc_type csc_type)
+{
+ unsigned short us_csc_coeff[10];
+
+ HDMIPRINTK("%d)\n\r", csc_type);
+
+ switch (csc_type) {
+
+ case HDMI_CSC_YUV601_TO_RGB_LR:
+ us_csc_coeff[0] = 0x23;
+ us_csc_coeff[1] = 256;
+ us_csc_coeff[2] = 938;
+ us_csc_coeff[3] = 846;
+ us_csc_coeff[4] = 256;
+ us_csc_coeff[5] = 443;
+ us_csc_coeff[6] = 0;
+ us_csc_coeff[7] = 256;
+ us_csc_coeff[8] = 0;
+ us_csc_coeff[9] = 350;
+ break;
+
+ case HDMI_CSC_YUV601_TO_RGB_FR:
+ us_csc_coeff[0] = 0x03;
+ us_csc_coeff[1] = 298;
+ us_csc_coeff[2] = 924;
+ us_csc_coeff[3] = 816;
+ us_csc_coeff[4] = 298;
+ us_csc_coeff[5] = 516;
+ us_csc_coeff[6] = 0;
+ us_csc_coeff[7] = 298;
+ us_csc_coeff[8] = 0;
+ us_csc_coeff[9] = 408;
+ break;
+
+ case HDMI_CSC_YUV709_TO_RGB_LR:
+ us_csc_coeff[0] = 0x23;
+ us_csc_coeff[1] = 256;
+ us_csc_coeff[2] = 978;
+ us_csc_coeff[3] = 907;
+ us_csc_coeff[4] = 256;
+ us_csc_coeff[5] = 464;
+ us_csc_coeff[6] = 0;
+ us_csc_coeff[7] = 256;
+ us_csc_coeff[8] = 0;
+ us_csc_coeff[9] = 394;
+ break;
+
+ case HDMI_CSC_YUV709_TO_RGB_FR:
+ us_csc_coeff[0] = 0x03;
+ us_csc_coeff[1] = 298;
+ us_csc_coeff[2] = 970;
+ us_csc_coeff[3] = 888;
+ us_csc_coeff[4] = 298;
+ us_csc_coeff[5] = 540;
+ us_csc_coeff[6] = 0;
+ us_csc_coeff[7] = 298;
+ us_csc_coeff[8] = 0;
+ us_csc_coeff[9] = 458;
+ break;
+
+ case HDMI_CSC_YUV601_TO_YUV709:
+ us_csc_coeff[0] = 0x33;
+ us_csc_coeff[1] = 256;
+ us_csc_coeff[2] = 995;
+ us_csc_coeff[3] = 971;
+ us_csc_coeff[4] = 0;
+ us_csc_coeff[5] = 260;
+ us_csc_coeff[6] = 29;
+ us_csc_coeff[7] = 0;
+ us_csc_coeff[8] = 19;
+ us_csc_coeff[9] = 262;
+ break;
+
+ case HDMI_CSC_RGB_FR_TO_RGB_LR:
+ us_csc_coeff[0] = 0x20;
+ us_csc_coeff[1] = 220;
+ us_csc_coeff[2] = 0;
+ us_csc_coeff[3] = 0;
+ us_csc_coeff[4] = 0;
+ us_csc_coeff[5] = 220;
+ us_csc_coeff[6] = 0;
+ us_csc_coeff[7] = 0;
+ us_csc_coeff[8] = 0;
+ us_csc_coeff[9] = 220;
+ break;
+
+ case HDMI_CSC_RGB_FR_TO_YUV601:
+ us_csc_coeff[0] = 0x30;
+ us_csc_coeff[1] = 129;
+ us_csc_coeff[2] = 25;
+ us_csc_coeff[3] = 65;
+ us_csc_coeff[4] = 950;
+ us_csc_coeff[5] = 112;
+ us_csc_coeff[6] = 986;
+ us_csc_coeff[7] = 930;
+ us_csc_coeff[8] = 1006;
+ us_csc_coeff[9] = 112;
+ break;
+
+ case HDMI_CSC_RGB_FR_TO_YUV709:
+ us_csc_coeff[0] = 0x30;
+ us_csc_coeff[1] = 157;
+ us_csc_coeff[2] = 16;
+ us_csc_coeff[3] = 47;
+ us_csc_coeff[4] = 937;
+ us_csc_coeff[5] = 112;
+ us_csc_coeff[6] = 999;
+ us_csc_coeff[7] = 922;
+ us_csc_coeff[8] = 1014;
+ us_csc_coeff[9] = 112;
+ break;
+
+ case HDMI_BYPASS:
+ us_csc_coeff[0] = 0x33;
+ us_csc_coeff[1] = 256;
+ us_csc_coeff[2] = 0;
+ us_csc_coeff[3] = 0;
+ us_csc_coeff[4] = 0;
+ us_csc_coeff[5] = 256;
+ us_csc_coeff[6] = 0;
+ us_csc_coeff[7] = 0;
+ us_csc_coeff[8] = 0;
+ us_csc_coeff[9] = 256;
+ break;
+
+ default:
+ HDMIPRINTK("invalid out_mode parameter(%d)\n\r", csc_type);
+ return S5P_TV_HDMI_ERR_INVALID_PARAM;
+ break;
+ }
+ return HDMI_NO_ERROR;
+}
+
+enum s5p_tv_hdmi_err __s5p_hdmi_video_init_avi_infoframe(
+ enum s5p_hdmi_transmit trans_type, u8 check_sum, u8 *avi_data)
+{
+ HDMIPRINTK("%d, %d, %d\n\r", (u32)trans_type, (u32)check_sum,
+ (u32)avi_data);
+
+ switch (trans_type) {
+
+ case HDMI_DO_NOT_TANS:
+ writel(AVI_TX_CON_NO_TRANS, hdmi_base + S5P_AVI_CON);
+ break;
+
+ case HDMI_TRANS_ONCE:
+ writel(AVI_TX_CON_TRANS_ONCE, hdmi_base + S5P_AVI_CON);
+ break;
+
+ case HDMI_TRANS_EVERY_SYNC:
+ writel(AVI_TX_CON_TRANS_EVERY_VSYNC, hdmi_base + S5P_AVI_CON);
+ break;
+
+ default:
+ HDMIPRINTK(" invalid out_mode parameter(%d)\n\r", trans_type);
+ return S5P_TV_HDMI_ERR_INVALID_PARAM;
+ break;
+ }
+
+ writel(SET_AVI_CHECK_SUM(check_sum), hdmi_base + S5P_AVI_CHECK_SUM);
+
+ writel(SET_AVI_BYTE(*(avi_data)), hdmi_base + S5P_AVI_BYTE1);
+ writel(SET_AVI_BYTE(*(avi_data + 1)), hdmi_base + S5P_AVI_BYTE2);
+ writel(SET_AVI_BYTE(*(avi_data + 2)), hdmi_base + S5P_AVI_BYTE3);
+ writel(SET_AVI_BYTE(*(avi_data + 3)), hdmi_base + S5P_AVI_BYTE4);
+ writel(SET_AVI_BYTE(*(avi_data + 4)), hdmi_base + S5P_AVI_BYTE5);
+ writel(SET_AVI_BYTE(*(avi_data + 5)), hdmi_base + S5P_AVI_BYTE6);
+ writel(SET_AVI_BYTE(*(avi_data + 6)), hdmi_base + S5P_AVI_BYTE7);
+ writel(SET_AVI_BYTE(*(avi_data + 7)), hdmi_base + S5P_AVI_BYTE8);
+ writel(SET_AVI_BYTE(*(avi_data + 8)), hdmi_base + S5P_AVI_BYTE9);
+ writel(SET_AVI_BYTE(*(avi_data + 9)), hdmi_base + S5P_AVI_BYTE10);
+ writel(SET_AVI_BYTE(*(avi_data + 10)), hdmi_base + S5P_AVI_BYTE11);
+ writel(SET_AVI_BYTE(*(avi_data + 11)), hdmi_base + S5P_AVI_BYTE12);
+ writel(SET_AVI_BYTE(*(avi_data + 12)), hdmi_base + S5P_AVI_BYTE13);
+
+ HDMIPRINTK("AVI_CON = 0x%08x \n\r", readl(hdmi_base + S5P_AVI_CON));
+ HDMIPRINTK("AVI_CHECK_SUM = 0x%08x \n\r",
+ readl(hdmi_base + S5P_AVI_CHECK_SUM));
+ HDMIPRINTK("AVI_BYTE1 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_AVI_BYTE1));
+ HDMIPRINTK("AVI_BYTE2 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_AVI_BYTE2));
+ HDMIPRINTK("AVI_BYTE3 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_AVI_BYTE3));
+ HDMIPRINTK("AVI_BYTE4 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_AVI_BYTE4));
+ HDMIPRINTK("AVI_BYTE5 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_AVI_BYTE5));
+ HDMIPRINTK("AVI_BYTE6 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_AVI_BYTE6));
+ HDMIPRINTK("AVI_BYTE7 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_AVI_BYTE7));
+ HDMIPRINTK("AVI_BYTE8 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_AVI_BYTE8));
+ HDMIPRINTK("AVI_BYTE9 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_AVI_BYTE9));
+ HDMIPRINTK("AVI_BYTE10 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_AVI_BYTE10));
+ HDMIPRINTK("AVI_BYTE11 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_AVI_BYTE11));
+ HDMIPRINTK("AVI_BYTE12 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_AVI_BYTE12));
+ HDMIPRINTK("AVI_BYTE13 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_AVI_BYTE13));
+
+ return HDMI_NO_ERROR;
+}
+
+enum s5p_tv_hdmi_err __s5p_hdmi_video_init_mpg_infoframe(
+ enum s5p_hdmi_transmit trans_type, u8 check_sum, u8 *mpg_data)
+{
+ HDMIPRINTK("trans_type : %d, %d, %d\n\r", (u32)trans_type,
+ (u32)check_sum, (u32)mpg_data);
+
+ switch (trans_type) {
+
+ case HDMI_DO_NOT_TANS:
+ writel(MPG_TX_CON_NO_TRANS,
+ hdmi_base + S5P_MPG_CON);
+ break;
+
+ case HDMI_TRANS_ONCE:
+ writel(MPG_TX_CON_TRANS_ONCE,
+ hdmi_base + S5P_MPG_CON);
+ break;
+
+ case HDMI_TRANS_EVERY_SYNC:
+ writel(MPG_TX_CON_TRANS_EVERY_VSYNC,
+ hdmi_base + S5P_MPG_CON);
+ break;
+
+ default:
+ HDMIPRINTK("invalid out_mode parameter(%d)\n\r",
+ trans_type);
+ return S5P_TV_HDMI_ERR_INVALID_PARAM;
+ break;
+ }
+
+ writel(SET_MPG_CHECK_SUM(check_sum),
+
+ hdmi_base + S5P_MPG_CHECK_SUM);
+
+ writel(SET_MPG_BYTE(*(mpg_data)),
+ hdmi_base + S5P_MPEG_BYTE1);
+ writel(SET_MPG_BYTE(*(mpg_data + 1)),
+ hdmi_base + S5P_MPEG_BYTE2);
+ writel(SET_MPG_BYTE(*(mpg_data + 2)),
+ hdmi_base + S5P_MPEG_BYTE3);
+ writel(SET_MPG_BYTE(*(mpg_data + 3)),
+ hdmi_base + S5P_MPEG_BYTE4);
+ writel(SET_MPG_BYTE(*(mpg_data + 4)),
+ hdmi_base + S5P_MPEG_BYTE5);
+
+ HDMIPRINTK("MPG_CON = 0x%08x \n\r",
+ readl(hdmi_base + S5P_MPG_CON));
+ HDMIPRINTK("MPG_CHECK_SUM = 0x%08x \n\r",
+ readl(hdmi_base + S5P_MPG_CHECK_SUM));
+ HDMIPRINTK("MPEG_BYTE1 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_MPEG_BYTE1));
+ HDMIPRINTK("MPEG_BYTE2 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_MPEG_BYTE2));
+ HDMIPRINTK("MPEG_BYTE3 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_MPEG_BYTE3));
+ HDMIPRINTK("MPEG_BYTE4 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_MPEG_BYTE4));
+ HDMIPRINTK("MPEG_BYTE5 = 0x%08x \n\r",
+ readl(hdmi_base + S5P_MPEG_BYTE5));
+
+ return HDMI_NO_ERROR;
+}
+
+void __s5p_hdmi_video_init_tg_cmd(bool time_c_e,
+ bool bt656_sync_en,
+ bool tg_en)
+{
+ u32 temp_reg = 0;
+
+ temp_reg = readl(hdmi_base + S5P_TG_CMD);
+
+ if (time_c_e)
+ temp_reg |= GETSYNC_TYPE_EN;
+ else
+ temp_reg &= GETSYNC_TYPE_DIS;
+
+ if (bt656_sync_en)
+ temp_reg |= GETSYNC_EN;
+ else
+ temp_reg &= GETSYNC_DIS;
+
+ if (tg_en)
+ temp_reg |= TG_EN;
+ else
+ temp_reg &= TG_DIS;
+
+ writel(temp_reg, hdmi_base + S5P_TG_CMD);
+
+ HDMIPRINTK("TG_CMD = 0x%08x \n\r", readl(hdmi_base + S5P_TG_CMD));
+}
+
+bool __s5p_hdmi_start(enum s5p_hdmi_audio_type hdmi_audio_type,
+ bool hdcp_en,
+ struct i2c_client *ddc_port)
+{
+ u32 temp_reg = HDMI_EN;
+
+ HDMIPRINTK("aud type : %d, hdcp enable : %d\n\r",
+ hdmi_audio_type, hdcp_en);
+
+ switch (hdmi_audio_type) {
+
+ case HDMI_AUDIO_PCM:
+ temp_reg |= ASP_EN;
+ break;
+
+ case HDMI_AUDIO_NO:
+ break;
+
+ default:
+ HDMIPRINTK(" invalid hdmi_audio_type(%d)\n\r",
+ hdmi_audio_type);
+ return false;
+ break;
+ }
+ if (hdcp_en) {
+ writel(HDCP_ENC_DISABLE, hdmi_base + S5P_ENC_EN);
+ s5p_hdmi_mute_en(true);
+ }
+
+ writel(readl(hdmi_base + S5P_HDMI_CON_0) | temp_reg,
+ hdmi_base + S5P_HDMI_CON_0);
+
+#ifdef CONFIG_HDMI_HPD
+ s5p_hpd_set_hdmiint();
+#endif
+
+#if 1
+ if (hdcp_en) {
+
+
+ if (!__s5p_start_hdcp())
+ HDMIPRINTK("HDCP start failed\n");
+
+ }
+
+#endif
+ HDMIPRINTK("HPD : 0x%08x, HDMI_CON_0 : 0x%08x\n\r",
+ readl(hdmi_base + S5P_HPD),
+ readl(hdmi_base + S5P_HDMI_CON_0));
+
+ return true;
+}
+
+/*
+* stop - stop functions are only called under running HDMI
+*/
+void __s5p_hdmi_stop(void)
+{
+ u32 temp = 0, result = 0;
+
+ HDMIPRINTK("\n\r");
+
+ __s5p_stop_hdcp();
+
+ /*
+ * Before stopping hdmi, stop the hdcp first. However,
+ * if there's no delay between hdcp stop & hdmi stop,
+ * re-opening would be failed.
+ */
+ mdelay(100);
+
+ temp = readl(hdmi_base + S5P_HDMI_CON_0);
+ result = temp & HDMI_EN;
+
+ if (result)
+ writel(temp & ~(HDMI_EN | ASP_EN),
+ hdmi_base + S5P_HDMI_CON_0);
+
+ do {
+ temp = readl(hdmi_base + S5P_HDMI_CON_0);
+ } while (temp & HDMI_EN);
+
+#ifdef CONFIG_HDMI_HPD
+ s5p_hpd_set_eint();
+#endif
+ HDMIPRINTK("HPD 0x%08x, HDMI_CON_0 0x%08x\n\r",
+ readl(hdmi_base + S5P_HPD),
+ readl(hdmi_base + S5P_HDMI_CON_0));
+}
+
+int __init __s5p_hdmi_probe(struct platform_device *pdev,
+ u32 res_num, u32 res_num2)
+{
+ struct resource *res;
+ size_t size;
+ u32 reg;
+
+ spin_lock_init(&lock_hdmi);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, res_num);
+
+ if (res == NULL) {
+ dev_err(&pdev->dev,
+ "failed to get memory region resource\n");
+ goto error;
+ }
+
+ size = (res->end - res->start) + 1;
+
+ hdmi_mem = request_mem_region(res->start, size, pdev->name);
+
+ if (hdmi_mem == NULL) {
+ dev_err(&pdev->dev,
+ "failed to get memory region\n");
+ goto error;
+ }
+
+ hdmi_base = ioremap(res->start, size);
+
+ if (hdmi_base == NULL) {
+ dev_err(&pdev->dev,
+ "failed to ioremap address region\n");
+ goto error;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, res_num2);
+
+ if (res == NULL) {
+ dev_err(&pdev->dev,
+ "failed to get memory region resource\n");
+ goto error;
+ }
+
+ size = (res->end - res->start) + 1;
+
+ i2c_hdmi_phy_mem = request_mem_region(res->start, size, pdev->name);
+
+ if (i2c_hdmi_phy_mem == NULL) {
+ dev_err(&pdev->dev,
+ "failed to get memory region\n");
+ goto error;
+ }
+
+ i2c_hdmi_phy_base = ioremap(res->start, size);
+
+ if (i2c_hdmi_phy_base == NULL) {
+ dev_err(&pdev->dev,
+ "failed to ioremap address region\n");
+ goto error;
+ }
+
+ /* PMU Block : HDMI PHY Enable */
+ reg = readl(S3C_VA_SYS+0xE804);
+ reg |= (1<<0);
+ writel(reg, S3C_VA_SYS+0xE804);
+
+ /* i2c_hdmi init - set i2c filtering */
+ writeb(0x5, i2c_hdmi_phy_base + I2C_HDMI_LC);
+
+ /* temp for test - hdmi intr. global enable */
+ reg = readb(hdmi_base+S5P_HDMI_CTRL_INTC_CON);
+ writeb(reg | (1<<HDMI_IRQ_GLOBAL), hdmi_base+S5P_HDMI_CTRL_INTC_CON);
+
+ return 0;
+error:
+ return -ENOENT;
+}
+
+int __init __s5p_hdmi_release(struct platform_device *pdev)
+{
+ iounmap(hdmi_base);
+
+ /* remove memory region */
+ if (hdmi_mem != NULL) {
+ if (release_resource(hdmi_mem))
+ dev_err(&pdev->dev,
+ "Can't remove tvout drv !!\n");
+
+ kfree(hdmi_mem);
+
+ hdmi_mem = NULL;
+ }
+
+ return 0;
+}
+
+/*
+ * HDCP ISR.
+ * If HDCP IRQ occurs, set hdcp_event and wake up the waitqueue.
+ */
+
+#define HDMI_IRQ_TOTAL_NUM 6
+
+hdmi_isr hdmi_isr_ftn[HDMI_IRQ_TOTAL_NUM];
+
+int s5p_hdmi_register_isr(hdmi_isr isr, u8 irq_num)
+{
+ HDMIPRINTK("Try to register ISR for IRQ number (%d)\n", irq_num);
+
+ if (isr == NULL) {
+ HDMIPRINTK("Invaild ISR\n");
+ return -EINVAL;
+ }
+
+ /* check IRQ number */
+ if (irq_num > HDMI_IRQ_TOTAL_NUM) {
+ HDMIPRINTK("irq_num exceeds allowed IRQ number(%d)\n",
+ HDMI_IRQ_TOTAL_NUM);
+ return -EINVAL;
+ }
+
+ /* check if is the number already registered? */
+ if (hdmi_isr_ftn[irq_num]) {
+ HDMIPRINTK("the %d th ISR is already registered\n",
+ irq_num);
+ }
+
+ hdmi_isr_ftn[irq_num] = isr;
+
+ HDMIPRINTK("Success to register ISR for IRQ number (%d)\n",
+ irq_num);
+
+ return 0;
+}
+EXPORT_SYMBOL(s5p_hdmi_register_isr);
+
+irqreturn_t __s5p_hdmi_irq(int irq, void *dev_id)
+{
+ u8 irq_state, irq_num;
+
+ spin_lock_irq(&lock_hdmi);
+
+ irq_state = readb(hdmi_base+S5P_HDMI_CTRL_INTC_FLAG);
+
+ HDMIPRINTK("S5P_HDMI_CTRL_INTC_FLAG = 0x%02x\n", irq_state);
+
+ /* Check interrupt happened */
+ /* Priority of Interrupt HDCP> I2C > Audio > CEC (Not implemented) */
+
+ if (irq_state) {
+ /* HDCP IRQ*/
+ irq_num = 0;
+ /* check if ISR is null or not */
+ while (irq_num < HDMI_IRQ_TOTAL_NUM) {
+ if (irq_state & (1<<irq_num)) {
+ if (hdmi_isr_ftn[irq_num] != NULL)
+ (hdmi_isr_ftn[irq_num])(irq_num);
+ else
+ HDMIPRINTK(
+ "No registered ISR for IRQ[%d]\n",
+ irq_num);
+
+ }
+ ++irq_num;
+ }
+
+ } else {
+ HDMIPRINTK("Undefined IRQ happened[%x]\n", irq_state);
+ }
+
+ spin_unlock_irq(&lock_hdmi);
+
+ return IRQ_HANDLED;
+}
+
+u8 s5p_hdmi_get_enabled_interrupt(void)
+{
+ u8 reg;
+ reg = readb(hdmi_base+S5P_HDMI_CTRL_INTC_CON);
+ return reg;
+}
+
+void s5p_hdmi_enable_interrupts(enum s5p_tv_hdmi_interrrupt intr)
+{
+ u8 reg;
+ reg = readb(hdmi_base+S5P_HDMI_CTRL_INTC_CON);
+ writeb(reg | (1<<intr) | (1<<HDMI_IRQ_GLOBAL),
+ hdmi_base+S5P_HDMI_CTRL_INTC_CON);
+}
+EXPORT_SYMBOL(s5p_hdmi_enable_interrupts);
+
+void s5p_hdmi_disable_interrupts(enum s5p_tv_hdmi_interrrupt intr)
+{
+ u8 reg;
+ reg = readb(hdmi_base+S5P_HDMI_CTRL_INTC_CON);
+ writeb(reg & ~(1<<intr), hdmi_base+S5P_HDMI_CTRL_INTC_CON);
+}
+EXPORT_SYMBOL(s5p_hdmi_disable_interrupts);
+
+void s5p_hdmi_clear_pending(enum s5p_tv_hdmi_interrrupt intr)
+{
+ u8 reg;
+ reg = readb(hdmi_base+S5P_HDMI_CTRL_INTC_FLAG);
+ writeb(reg | (1<<intr), hdmi_base+S5P_HDMI_CTRL_INTC_FLAG);
+}
+EXPORT_SYMBOL(s5p_hdmi_clear_pending);
+
+u8 s5p_hdmi_get_interrupts(void)
+{
+ u8 reg;
+ reg = readb(hdmi_base+S5P_HDMI_CTRL_INTC_FLAG);
+ return reg;
+}
+EXPORT_SYMBOL(s5p_hdmi_get_interrupts);
+
+u8 s5p_hdmi_get_swhpd_status(void)
+{
+ u8 reg;
+ reg = readb(hdmi_base+S5P_HPD) & HPD_SW_ENABLE;
+ return reg;
+}
+EXPORT_SYMBOL(s5p_hdmi_get_swhpd_status);
+
+u8 s5p_hdmi_get_hpd_status(void)
+{
+ u8 reg;
+ reg = readb(hdmi_base+S5P_HDMI_CTRL_HPD);
+ return reg;
+}
+EXPORT_SYMBOL(s5p_hdmi_get_hpd_status);
+
+void s5p_hdmi_swhpd_disable(void)
+{
+ writeb(HPD_SW_DISABLE, hdmi_base+S5P_HPD);
+}
+EXPORT_SYMBOL(s5p_hdmi_swhpd_disable);
+
+void s5p_hdmi_hpd_gen(void)
+{
+ writeb(0xFF, hdmi_base+S5P_HDMI_HPD_GEN);
+}
+EXPORT_SYMBOL(s5p_hdmi_hpd_gen);
+
diff --git a/drivers/media/video/samsung/tv20/s5pv210/regs/regs-cec.h b/drivers/media/video/samsung/tv20/s5pv210/regs/regs-cec.h
new file mode 100644
index 0000000..9e29d0e
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/s5pv210/regs/regs-cec.h
@@ -0,0 +1,101 @@
+/* linux/drivers/media/video/samsung/tv20/s5pc110/regs/regs-cec.h
+ *
+ * CEC register header file for Samsung TVOut driver
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ * http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __REGS_CEC_H
+#define __REGS_CEC_H
+
+#define HDMIDP_CECREG(x) (x)
+
+/**
+ * @name CEC config/status registers
+ */
+#define CEC_STATUS_0 HDMIDP_CECREG(0x0000)
+#define CEC_STATUS_1 HDMIDP_CECREG(0x0004)
+#define CEC_STATUS_2 HDMIDP_CECREG(0x0008)
+#define CEC_STATUS_3 HDMIDP_CECREG(0x000C)
+#define CEC_IRQ_MASK HDMIDP_CECREG(0x0010)
+#define CEC_IRQ_CLEAR HDMIDP_CECREG(0x0014)
+#define CEC_LOGIC_ADDR HDMIDP_CECREG(0x0020)
+#define CEC_DIVISOR_0 HDMIDP_CECREG(0x0030)
+#define CEC_DIVISOR_1 HDMIDP_CECREG(0x0034)
+#define CEC_DIVISOR_2 HDMIDP_CECREG(0x0038)
+#define CEC_DIVISOR_3 HDMIDP_CECREG(0x003C)
+
+/**
+ * @name CEC Tx related registers
+ */
+#define CEC_TX_CTRL HDMIDP_CECREG(0x0040)
+#define CEC_TX_BYTES HDMIDP_CECREG(0x0044)
+#define CEC_TX_STAT0 HDMIDP_CECREG(0x0060)
+#define CEC_TX_STAT1 HDMIDP_CECREG(0x0064)
+#define CEC_TX_BUFF0 HDMIDP_CECREG(0x0080)
+#define CEC_TX_BUFF1 HDMIDP_CECREG(0x0084)
+#define CEC_TX_BUFF2 HDMIDP_CECREG(0x0088)
+#define CEC_TX_BUFF3 HDMIDP_CECREG(0x008C)
+#define CEC_TX_BUFF4 HDMIDP_CECREG(0x0090)
+#define CEC_TX_BUFF5 HDMIDP_CECREG(0x0094)
+#define CEC_TX_BUFF6 HDMIDP_CECREG(0x0098)
+#define CEC_TX_BUFF7 HDMIDP_CECREG(0x009C)
+#define CEC_TX_BUFF8 HDMIDP_CECREG(0x00A0)
+#define CEC_TX_BUFF9 HDMIDP_CECREG(0x00A4)
+#define CEC_TX_BUFF10 HDMIDP_CECREG(0x00A8)
+#define CEC_TX_BUFF11 HDMIDP_CECREG(0x00AC)
+#define CEC_TX_BUFF12 HDMIDP_CECREG(0x00B0)
+#define CEC_TX_BUFF13 HDMIDP_CECREG(0x00B4)
+#define CEC_TX_BUFF14 HDMIDP_CECREG(0x00B8)
+#define CEC_TX_BUFF15 HDMIDP_CECREG(0x00BC)
+
+/**
+ * @name CEC Rx related registers
+ */
+#define CEC_RX_CTRL HDMIDP_CECREG(0x00C0)
+#define CEC_RX_STAT0 HDMIDP_CECREG(0x00E0)
+#define CEC_RX_STAT1 HDMIDP_CECREG(0x00E4)
+#define CEC_RX_BUFF0 HDMIDP_CECREG(0x0100)
+#define CEC_RX_BUFF1 HDMIDP_CECREG(0x0104)
+#define CEC_RX_BUFF2 HDMIDP_CECREG(0x0108)
+#define CEC_RX_BUFF3 HDMIDP_CECREG(0x010C)
+#define CEC_RX_BUFF4 HDMIDP_CECREG(0x0110)
+#define CEC_RX_BUFF5 HDMIDP_CECREG(0x0114)
+#define CEC_RX_BUFF6 HDMIDP_CECREG(0x0118)
+#define CEC_RX_BUFF7 HDMIDP_CECREG(0x011C)
+#define CEC_RX_BUFF8 HDMIDP_CECREG(0x0120)
+#define CEC_RX_BUFF9 HDMIDP_CECREG(0x0124)
+#define CEC_RX_BUFF10 HDMIDP_CECREG(0x0128)
+#define CEC_RX_BUFF11 HDMIDP_CECREG(0x012C)
+#define CEC_RX_BUFF12 HDMIDP_CECREG(0x0130)
+#define CEC_RX_BUFF13 HDMIDP_CECREG(0x0134)
+#define CEC_RX_BUFF14 HDMIDP_CECREG(0x0138)
+#define CEC_RX_BUFF15 HDMIDP_CECREG(0x013C)
+
+#define CEC_RX_FILTER_CTRL HDMIDP_CECREG(0x0180)
+#define CEC_RX_FILTER_TH HDMIDP_CECREG(0x0184)
+
+/**
+ * @name Bit values
+ */
+#define CEC_IRQ_TX_DONE (1<<0)
+#define CEC_IRQ_TX_ERROR (1<<1)
+#define CEC_IRQ_RX_DONE (1<<4)
+#define CEC_IRQ_RX_ERROR (1<<5)
+
+#define CEC_TX_CTRL_START (1<<0)
+#define CEC_TX_CTRL_BCAST (1<<1)
+#define CEC_TX_CTRL_RETRY (0x04<<4)
+#define CEC_TX_CTRL_RESET (1<<7)
+
+#define CEC_RX_CTRL_ENABLE (1<<0)
+#define CEC_RX_CTRL_RESET (1<<7)
+
+#define CEC_LOGIC_ADDR_MASK 0x0F
+
+#endif /* __REGS_CEC_H */
diff --git a/drivers/media/video/samsung/tv20/s5pv210/regs/regs-clock_extra.h b/drivers/media/video/samsung/tv20/s5pv210/regs/regs-clock_extra.h
new file mode 100644
index 0000000..d4cede6
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/s5pv210/regs/regs-clock_extra.h
@@ -0,0 +1,103 @@
+/* linux/drivers/media/video/samsung/tv20/s5pc100/regs/regs-clock_extra.h
+ *
+ * Clock Other header file for Samsung TVOut driver
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ * http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_REGS_CLK_EXTRA_H
+#define __ASM_ARCH_REGS_CLK_EXTRA_H
+
+#include <mach/map.h>
+
+#define S5P_CLK_OTHER_BASE(x) (x)
+/*
+ * Registers
+ * */
+/* Generate software reset 0x0000_0000 */
+#define S5P_CLK_OTHER_SWRESET S5P_CLK_OTHER_BASE(0x0000)
+/* OneNAND controller setting 0x0000_0000 */
+#define S5P_CLK_OTHER_ONENAND_SWRESET S5P_CLK_OTHER_BASE(0x0008)
+/* General Control Register 0x0000_0000 */
+#define S5P_CLK_OTHER_GENERAL_CTRL S5P_CLK_OTHER_BASE(0x0100)
+/* General Status Register 0x0000_0000 */
+#define S5P_CLK_OTHER_GENERAL_STATUS S5P_CLK_OTHER_BASE(0x0104)
+/* ENDIAN & EBI configuration 0x0000_0000 */
+#define S5P_CLK_OTHER_MEM_SYS_CFG S5P_CLK_OTHER_BASE(0x0200)
+/* Camera mapping to FIMC selection 0x0000_0000 */
+#define S5P_CLK_OTHER_CAM_MUX_SEL S5P_CLK_OTHER_BASE(0x0300)
+/* Video Mixer output to TVENC / HDMI selection 0x0000_0000*/
+#define S5P_CLK_OTHER_MIXER_OUT_SEL S5P_CLK_OTHER_BASE(0x0304)
+/* Low power MP3 mode selection 0x0000_0000 */
+#define S5P_CLK_OTHER_LPMP3_MODE_SEL S5P_CLK_OTHER_BASE(0x0308)
+/* MIPI D-PHY control register0 0x0000_0000 */
+#define S5P_CLK_OTHER_MIPI_PHY_CON0 S5P_CLK_OTHER_BASE(0x0400)
+/* MIPI D-PHY control register1 0x0000_0000 */
+#define S5P_CLK_OTHER_MIPI_PHY_CON1 S5P_CLK_OTHER_BASE(0x0414)
+/* HDMI PHY control register0 0x0000_0000 */
+#define S5P_CLK_OTHER_HDMI_PHY_CON0 S5P_CLK_OTHER_BASE(0x0420)
+
+/*
+ * Macros
+ * */
+/* VPLL_LOCK */
+#define VPLL_LOCKTIME(a) (0xffff&a)
+
+/* VPLL_CON */
+#define VPLL_ENABLE (1<<31)
+#define VPLL_DISABLE (0<<31)
+#define VPLL_LOCKED(a) ((1<<29)&a)
+#define VCO_FREQ_SEL (1<<27)
+#define MDIV(a) ((0xff&a)<<16)
+#define PDIV(a) ((0x3f&a)<<8)
+#define SDIV(a) (0x7&a)
+
+/* CLK_SRC0 */
+#define HREF_SEL_FIN_27M (0<<20)
+#define HREF_SEL_SRCLK (1<<20)
+#define HREF_SEL_MASK (~(1<<20))
+#define VPLL_SEL_CLK27M (0<<12)
+#define VPLL_SEL_FOUT_VPLL (1<<12)
+#define VPLL_SEL_MASK (~(1<<12))
+
+/* CLK_SRC2 */
+#define VMIXER_SEL_MOUT_VPLL (1<<4)
+#define VMIXER_SEL_MASK (~(1<<4))
+#define HDMI_SEL_HDMIPHY (1<<0)
+#define HDMI_SEL_MASK (~(1<<0))
+
+/* CLK_DIV3 */
+#define HDMI_DIV_RATIO(a) (0xf&(a))
+#define HDMI_DIV_RATIO_MASK (~(0xf))
+
+/* CLK_GATE_D1_2 */
+#define CLK_HCLK_HDMI_PASS (1<<11)
+#define CLK_HCLK_SDOUT_PASS (1<<10)
+#define CLK_HCLK_VMIXER_PASS (1<<9)
+#define CLK_HCLK_VP_PASS (1<<8)
+#define CLK_HCLK_MASK (~0xf)
+
+/* CLK_GATE_D1_4 */
+#define CLK_PCLK_IIC_HDMI_PASS (1<<5)
+#define CLK_PCLK_IIC_HDMI_MASK (~(1<<5))
+
+/* CLK_GATE_SCLK_1 */
+#define CLK_SCLK_HDMI_PASS (1<<19)
+#define CLK_SCLK_VMIXER_PASS (1<<20)
+#define CLK_SCLK_VDAC54_PASS (1<<21)
+#define CLK_SCLK_TV54_PASS (1<<22)
+#define CLK_SCLK_HDMI_MASK (~(1<<19))
+#define CLK_SCLK_VMIXER_MASK (~(1<<20))
+#define CLK_SCLK_VDAC54_MASK (~(1<<21))
+#define CLK_SCLK_TV54_MASK (~(1<<22))
+
+/* MIXER_OUT_SEL */
+#define VMIXER_OUT_SEL_SDOUT (0)
+#define VMIXER_OUT_SEL_HDMI (1)
+
+#endif /*__ASM_ARCH_REGS_CLK_EXTRA_H */
diff --git a/drivers/media/video/samsung/tv20/s5pv210/regs/regs-hdmi.h b/drivers/media/video/samsung/tv20/s5pv210/regs/regs-hdmi.h
new file mode 100644
index 0000000..8094417
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/s5pv210/regs/regs-hdmi.h
@@ -0,0 +1,1552 @@
+/* linux/drivers/media/video/samsung/tv20/s5pc100/regs/regs-hdmi.h
+ *
+ * Hdmi register header file for Samsung TVOut driver
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ * http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_REGS_HDMI_H
+
+#include <mach/map.h>
+
+#define S5P_I2C_HDMI_PHY_BASE(x) (x)
+
+/*
+ * HDMI PHY is configured through the dedicated I2C.
+ * The dedicated I2C for HDMI PHY is only used as TX mode
+ * I2C-BUS Interface for HDMI PHY is internally connected
+ */
+#define I2C_HDMI_CON S5P_I2C_HDMI_PHY_BASE(0x0000)
+#define I2C_HDMI_STAT S5P_I2C_HDMI_PHY_BASE(0x0004)
+#define I2C_HDMI_ADD S5P_I2C_HDMI_PHY_BASE(0x0008)
+#define I2C_HDMI_DS S5P_I2C_HDMI_PHY_BASE(0x000c)
+#define I2C_HDMI_LC S5P_I2C_HDMI_PHY_BASE(0x0010)
+
+#define S5P_HDMI_CTRL_BASE(x) (x)
+#define S5P_HDMI_BASE(x) (x + 0x00010000)
+#define S5P_HDMI_SPDIF_BASE(x) (x + 0x00030000)
+#define S5P_HDMI_I2S_BASE(x) (x + 0x00040000)
+#define S5P_HDMI_TG_BASE(x) (x + 0x00050000)
+#define S5P_HDMI_EFUSE_BASE(x) (x + 0x00060000)
+
+#define S5P_HDMI_CTRL_INTC_CON S5P_HDMI_CTRL_BASE(0x0000) /* Interrupt Control Register */
+#define S5P_HDMI_CTRL_INTC_FLAG S5P_HDMI_CTRL_BASE(0x0004) /* Interrupt Flag Register */
+#define S5P_HDMI_CTRL_HDCP_KEY_LOAD S5P_HDMI_CTRL_BASE(0x0008) /* HDCP KEY Status */
+#define S5P_HDMI_CTRL_HPD S5P_HDMI_CTRL_BASE(0x000C) /* HPD signal */
+#define S5P_HDMI_CTRL_AUDIO_CLKSEL S5P_HDMI_CTRL_BASE(0x0010) /* Audio system clock selection */
+#define S5P_HDMI_CTRL_PHY_RSTOUT S5P_HDMI_CTRL_BASE(0x0014) /* HDMI PHY Reset Out */
+#define S5P_HDMI_CTRL_PHY_VPLL S5P_HDMI_CTRL_BASE(0x0018) /* HDMI PHY VPLL Monitor */
+#define S5P_HDMI_CTRL_PHY_CMU S5P_HDMI_CTRL_BASE(0x001C) /* HDMI PHY CMU Monitor */
+#define S5P_HDMI_CTRL_CORE_RSTOUT S5P_HDMI_CTRL_BASE(0x0020) /* HDMI TX Core S/W reset */
+
+#define S5P_HDMI_CON_0 S5P_HDMI_BASE(0x0000) /* HDMI System Control Register 0 0x00 */
+#define S5P_HDMI_CON_1 S5P_HDMI_BASE(0x0004) /* HDMI System Control Register 1 0x00 */
+#define S5P_HDMI_CON_2 S5P_HDMI_BASE(0x0008) /* HDMI System Control Register 2. 0x00 */
+#define S5P_STATUS S5P_HDMI_BASE(0x0010) /* HDMI System Status Register 0x00 */
+#define HDMI_PHY_STATUS S5P_HDMI_BASE(0x0014) /* HDMI Phy Status */
+#define S5P_STATUS_EN S5P_HDMI_BASE(0x0020) /* HDMI System Status Enable Register 0x00 */
+#define S5P_HPD S5P_HDMI_BASE(0x0030) /* Hot Plug Detection Control Register 0x00 */
+#define S5P_MODE_SEL S5P_HDMI_BASE(0x0040) /* HDMI/DVI Mode Selection 0x00 */
+#define S5P_ENC_EN S5P_HDMI_BASE(0x0044) /* HDCP Encryption Enable Register 0x00 */
+
+#define S5P_BLUE_SCREEN_0 S5P_HDMI_BASE(0x0050) /* Pixel Values for Blue Screen 0x00 */
+#define S5P_BLUE_SCREEN_1 S5P_HDMI_BASE(0x0054) /* Pixel Values for Blue Screen 0x00 */
+#define S5P_BLUE_SCREEN_2 S5P_HDMI_BASE(0x0058) /* Pixel Values for Blue Screen 0x00 */
+
+#define S5P_HDMI_YMAX S5P_HDMI_BASE(0x0060) /* Maximum Y (or R,G,B) Pixel Value 0xEB */
+#define S5P_HDMI_YMIN S5P_HDMI_BASE(0x0064) /* Minimum Y (or R,G,B) Pixel Value 0x10 */
+#define S5P_HDMI_CMAX S5P_HDMI_BASE(0x0068) /* Maximum Cb/ Cr Pixel Value 0xF0 */
+#define S5P_HDMI_CMIN S5P_HDMI_BASE(0x006C) /* Minimum Cb/ Cr Pixel Value 0x10 */
+
+#define S5P_H_BLANK_0 S5P_HDMI_BASE(0x00A0) /* Horizontal Blanking Setting 0x00 */
+#define S5P_H_BLANK_1 S5P_HDMI_BASE(0x00A4) /* Horizontal Blanking Setting 0x00 */
+#define S5P_V_BLANK_0 S5P_HDMI_BASE(0x00B0) /* Vertical Blanking Setting 0x00 */
+#define S5P_V_BLANK_1 S5P_HDMI_BASE(0x00B4) /* Vertical Blanking Setting 0x00 */
+#define S5P_V_BLANK_2 S5P_HDMI_BASE(0x00B8) /* Vertical Blanking Setting 0x00 */
+#define S5P_H_V_LINE_0 S5P_HDMI_BASE(0x00C0) /* Hori. Line and Ver. Line 0x00 */
+#define S5P_H_V_LINE_1 S5P_HDMI_BASE(0x00C4) /* Hori. Line and Ver. Line 0x00 */
+#define S5P_H_V_LINE_2 S5P_HDMI_BASE(0x00C8) /* Hori. Line and Ver. Line 0x00 */
+
+#define S5P_SYNC_MODE S5P_HDMI_BASE(0x00E4) /* Vertical Sync Polarity Control Register 0x00 */
+#define S5P_INT_PRO_MODE S5P_HDMI_BASE(0x00E8) /* Interlace/ Progressive Control Register 0x00 */
+
+#define S5P_V_BLANK_F_0 S5P_HDMI_BASE(0x0110) /* Vertical Blanking Setting for Bottom Field 0x00 */
+#define S5P_V_BLANK_F_1 S5P_HDMI_BASE(0x0114) /* Vertical Blanking Setting for Bottom Field 0x00 */
+#define S5P_V_BLANK_F_2 S5P_HDMI_BASE(0x0118) /* Vertical Blanking Setting for Bottom Field 0x00 */
+#define S5P_H_SYNC_GEN_0 S5P_HDMI_BASE(0x0120) /* Horizontal Sync Generation Setting 0x00 */
+#define S5P_H_SYNC_GEN_1 S5P_HDMI_BASE(0x0124) /* Horizontal Sync Generation Setting 0x00 */
+#define S5P_H_SYNC_GEN_2 S5P_HDMI_BASE(0x0128) /* Horizontal Sync Generation Setting 0x00 */
+#define S5P_V_SYNC_GEN_1_0 S5P_HDMI_BASE(0x0130) /* Vertical Sync Generation for Top Field or Frame. 0x01 */
+#define S5P_V_SYNC_GEN_1_1 S5P_HDMI_BASE(0x0134) /* Vertical Sync Generation for Top Field or Frame. 0x10 */
+#define S5P_V_SYNC_GEN_1_2 S5P_HDMI_BASE(0x0138) /* Vertical Sync Generation for Top Field or Frame. 0x00 */
+#define S5P_V_SYNC_GEN_2_0 S5P_HDMI_BASE(0x0140) /* Vertical Sync Generation for Bottom field ? Vertical position. 0x01 */
+#define S5P_V_SYNC_GEN_2_1 S5P_HDMI_BASE(0x0144) /* Vertical Sync Generation for Bottom field ? Vertical position. 0x10 */
+#define S5P_V_SYNC_GEN_2_2 S5P_HDMI_BASE(0x0148) /* Vertical Sync Generation for Bottom field ? Vertical position. 0x00 */
+#define S5P_V_SYNC_GEN_3_0 S5P_HDMI_BASE(0x0150) /* Vertical Sync Generation for Bottom field ? Horizontal position. 0x01 */
+#define S5P_V_SYNC_GEN_3_1 S5P_HDMI_BASE(0x0154) /* Vertical Sync Generation for Bottom field ? Horizontal position. 0x10 */
+#define S5P_V_SYNC_GEN_3_2 S5P_HDMI_BASE(0x0158) /* Vertical Sync Generation for Bottom field ? Horizontal position. 0x00 */
+
+#define S5P_ASP_CON S5P_HDMI_BASE(0x0160) /* ASP Packet Control Register 0x00 */
+#define S5P_ASP_SP_FLAT S5P_HDMI_BASE(0x0164) /* ASP Packet sp_flat Bit Control 0x00 */
+#define S5P_ASP_CHCFG0 S5P_HDMI_BASE(0x0170) /* ASP Audio Channel Configuration 0x04 */
+#define S5P_ASP_CHCFG1 S5P_HDMI_BASE(0x0174) /* ASP Audio Channel Configuration 0x1A */
+#define S5P_ASP_CHCFG2 S5P_HDMI_BASE(0x0178) /* ASP Audio Channel Configuration 0x2C */
+#define S5P_ASP_CHCFG3 S5P_HDMI_BASE(0x017C) /* ASP Audio Channel Configuration 0x3E */
+
+#define S5P_ACR_CON S5P_HDMI_BASE(0x0180) /* ACR Packet Control Register 0x00 */
+#define S5P_ACR_MCTS0 S5P_HDMI_BASE(0x0184) /* Measured CTS Value 0x01 */
+#define S5P_ACR_MCTS1 S5P_HDMI_BASE(0x0188) /* Measured CTS Value 0x00 */
+#define S5P_ACR_MCTS2 S5P_HDMI_BASE(0x018C) /* Measured CTS Value 0x00 */
+#define S5P_ACR_CTS0 S5P_HDMI_BASE(0x0190) /* CTS Value for Fixed CTS Transmission Mode. 0xE8 */
+#define S5P_ACR_CTS1 S5P_HDMI_BASE(0x0194) /* CTS Value for Fixed CTS Transmission Mode. 0x03 */
+#define S5P_ACR_CTS2 S5P_HDMI_BASE(0x0198) /* CTS Value for Fixed CTS Transmission Mode. 0x00 */
+#define S5P_ACR_N0 S5P_HDMI_BASE(0x01A0) /* N Value for ACR Packet. 0xE8 */
+#define S5P_ACR_N1 S5P_HDMI_BASE(0x01A4) /* N Value for ACR Packet. 0x03 */
+#define S5P_ACR_N2 S5P_HDMI_BASE(0x01A8) /* N Value for ACR Packet. 0x00 */
+#define S5P_ACR_LSB2 S5P_HDMI_BASE(0x01B0) /* Altenate LSB for Fixed CTS Transmission Mode 0x00 */
+#define S5P_ACR_TXCNT S5P_HDMI_BASE(0x01B4) /* Number of ACR Packet Transmission per frame 0x1F */
+#define S5P_ACR_TXINTERVAL S5P_HDMI_BASE(0x01B8) /* Interval for ACR Packet Transmission 0x63 */
+#define S5P_ACR_CTS_OFFSET S5P_HDMI_BASE(0x01BC) /* CTS Offset for Measured CTS mode. 0x00 */
+
+#define S5P_GCP_CON S5P_HDMI_BASE(0x01C0) /* ACR Packet Control register 0x00 */
+#define S5P_GCP_BYTE1 S5P_HDMI_BASE(0x01D0) /* GCP Packet Body 0x00 */
+#define S5P_GCP_BYTE2 S5P_HDMI_BASE(0x01D4) /* GCP Packet Body 0x01 */
+#define S5P_GCP_BYTE3 S5P_HDMI_BASE(0x01D8) /* GCP Packet Body 0x02 */
+
+#define S5P_ACP_CON S5P_HDMI_BASE(0x01E0) /* ACP Packet Control register 0x00 */
+#define S5P_ACP_TYPE S5P_HDMI_BASE(0x01E4) /* ACP Packet Header 0x00 */
+
+#define S5P_ACP_DATA0 S5P_HDMI_BASE(0x0200) /* ACP Packet Body 0x00 */
+#define S5P_ACP_DATA1 S5P_HDMI_BASE(0x0204) /* ACP Packet Body 0x00 */
+#define S5P_ACP_DATA2 S5P_HDMI_BASE(0x0208) /* ACP Packet Body 0x00 */
+#define S5P_ACP_DATA3 S5P_HDMI_BASE(0x020c) /* ACP Packet Body 0x00 */
+#define S5P_ACP_DATA4 S5P_HDMI_BASE(0x0210) /* ACP Packet Body 0x00 */
+#define S5P_ACP_DATA5 S5P_HDMI_BASE(0x0214) /* ACP Packet Body 0x00 */
+#define S5P_ACP_DATA6 S5P_HDMI_BASE(0x0218) /* ACP Packet Body 0x00 */
+#define S5P_ACP_DATA7 S5P_HDMI_BASE(0x021c) /* ACP Packet Body 0x00 */
+#define S5P_ACP_DATA8 S5P_HDMI_BASE(0x0220) /* ACP Packet Body 0x00 */
+#define S5P_ACP_DATA9 S5P_HDMI_BASE(0x0224) /* ACP Packet Body 0x00 */
+#define S5P_ACP_DATA10 S5P_HDMI_BASE(0x0228) /* ACP Packet Body 0x00 */
+#define S5P_ACP_DATA11 S5P_HDMI_BASE(0x022c) /* ACP Packet Body 0x00 */
+#define S5P_ACP_DATA12 S5P_HDMI_BASE(0x0230) /* ACP Packet Body 0x00 */
+#define S5P_ACP_DATA13 S5P_HDMI_BASE(0x0234) /* ACP Packet Body 0x00 */
+#define S5P_ACP_DATA14 S5P_HDMI_BASE(0x0238) /* ACP Packet Body 0x00 */
+#define S5P_ACP_DATA15 S5P_HDMI_BASE(0x023c) /* ACP Packet Body 0x00 */
+#define S5P_ACP_DATA16 S5P_HDMI_BASE(0x0240) /* ACP Packet Body 0x00 */
+
+#define S5P_ISRC_CON S5P_HDMI_BASE(0x0250) /* ACR Packet Control Register 0x00 */
+#define S5P_ISRC1_HEADER1 S5P_HDMI_BASE(0x0264) /* ISCR1 Packet Header 0x00 */
+
+#define S5P_ISRC1_DATA0 S5P_HDMI_BASE(0x0270) /* ISRC1 Packet Body 0x00 */
+#define S5P_ISRC1_DATA1 S5P_HDMI_BASE(0x0274) /* ISRC1 Packet Body 0x00 */
+#define S5P_ISRC1_DATA2 S5P_HDMI_BASE(0x0278) /* ISRC1 Packet Body 0x00 */
+#define S5P_ISRC1_DATA3 S5P_HDMI_BASE(0x027c) /* ISRC1 Packet Body 0x00 */
+#define S5P_ISRC1_DATA4 S5P_HDMI_BASE(0x0280) /* ISRC1 Packet Body 0x00 */
+#define S5P_ISRC1_DATA5 S5P_HDMI_BASE(0x0284) /* ISRC1 Packet Body 0x00 */
+#define S5P_ISRC1_DATA6 S5P_HDMI_BASE(0x0288) /* ISRC1 Packet Body 0x00 */
+#define S5P_ISRC1_DATA7 S5P_HDMI_BASE(0x028c) /* ISRC1 Packet Body 0x00 */
+#define S5P_ISRC1_DATA8 S5P_HDMI_BASE(0x0290) /* ISRC1 Packet Body 0x00 */
+#define S5P_ISRC1_DATA9 S5P_HDMI_BASE(0x0294) /* ISRC1 Packet Body 0x00 */
+#define S5P_ISRC1_DATA10 S5P_HDMI_BASE(0x0298) /* ISRC1 Packet Body 0x00 */
+#define S5P_ISRC1_DATA11 S5P_HDMI_BASE(0x029c) /* ISRC1 Packet Body 0x00 */
+#define S5P_ISRC1_DATA12 S5P_HDMI_BASE(0x02a0) /* ISRC1 Packet Body 0x00 */
+#define S5P_ISRC1_DATA13 S5P_HDMI_BASE(0x02a4) /* ISRC1 Packet Body 0x00 */
+#define S5P_ISRC1_DATA14 S5P_HDMI_BASE(0x02a8) /* ISRC1 Packet Body 0x00 */
+#define S5P_ISRC1_DATA15 S5P_HDMI_BASE(0x02ac) /* ISRC1 Packet Body 0x00 */
+
+#define S5P_ISRC2_DATA0 S5P_HDMI_BASE(0x02b0) /* ISRC2 Packet Body 0x00 */
+#define S5P_ISRC2_DATA1 S5P_HDMI_BASE(0x02b4) /* ISRC2 Packet Body 0x00 */
+#define S5P_ISRC2_DATA2 S5P_HDMI_BASE(0x02b8) /* ISRC2 Packet Body 0x00 */
+#define S5P_ISRC2_DATA3 S5P_HDMI_BASE(0x02bc) /* ISRC2 Packet Body 0x00 */
+#define S5P_ISRC2_DATA4 S5P_HDMI_BASE(0x02c0) /* ISRC2 Packet Body 0x00 */
+#define S5P_ISRC2_DATA5 S5P_HDMI_BASE(0x02c4) /* ISRC2 Packet Body 0x00 */
+#define S5P_ISRC2_DATA6 S5P_HDMI_BASE(0x02c8) /* ISRC2 Packet Body 0x00 */
+#define S5P_ISRC2_DATA7 S5P_HDMI_BASE(0x02cc) /* ISRC2 Packet Body 0x00 */
+#define S5P_ISRC2_DATA8 S5P_HDMI_BASE(0x02d0) /* ISRC2 Packet Body 0x00 */
+#define S5P_ISRC2_DATA9 S5P_HDMI_BASE(0x02d4) /* ISRC2 Packet Body 0x00 */
+#define S5P_ISRC2_DATA10 S5P_HDMI_BASE(0x02d8) /* ISRC2 Packet Body 0x00 */
+#define S5P_ISRC2_DATA11 S5P_HDMI_BASE(0x02dc) /* ISRC2 Packet Body 0x00 */
+#define S5P_ISRC2_DATA12 S5P_HDMI_BASE(0x02e0) /* ISRC2 Packet Body 0x00 */
+#define S5P_ISRC2_DATA13 S5P_HDMI_BASE(0x02e4) /* ISRC2 Packet Body 0x00 */
+#define S5P_ISRC2_DATA14 S5P_HDMI_BASE(0x02e8) /* ISRC2 Packet Body 0x00 */
+#define S5P_ISRC2_DATA15 S5P_HDMI_BASE(0x02ec) /* ISRC2 Packet Body 0x00 */
+
+#define S5P_AVI_CON S5P_HDMI_BASE(0x0300) /* AVI Packet Control Register 0x00 */
+#define S5P_AVI_CHECK_SUM S5P_HDMI_BASE(0x0310) /* AVI Packet Checksum 0x00 */
+
+#define S5P_AVI_BYTE1 S5P_HDMI_BASE(0x0320) /* AVI Packet Body 0x00 */
+#define S5P_AVI_BYTE2 S5P_HDMI_BASE(0x0324) /* AVI Packet Body 0x00 */
+#define S5P_AVI_BYTE3 S5P_HDMI_BASE(0x0328) /* AVI Packet Body 0x00 */
+#define S5P_AVI_BYTE4 S5P_HDMI_BASE(0x032c) /* AVI Packet Body 0x00 */
+#define S5P_AVI_BYTE5 S5P_HDMI_BASE(0x0330) /* AVI Packet Body 0x00 */
+#define S5P_AVI_BYTE6 S5P_HDMI_BASE(0x0334) /* AVI Packet Body 0x00 */
+#define S5P_AVI_BYTE7 S5P_HDMI_BASE(0x0338) /* AVI Packet Body 0x00 */
+#define S5P_AVI_BYTE8 S5P_HDMI_BASE(0x033c) /* AVI Packet Body 0x00 */
+#define S5P_AVI_BYTE9 S5P_HDMI_BASE(0x0340) /* AVI Packet Body 0x00 */
+#define S5P_AVI_BYTE10 S5P_HDMI_BASE(0x0344) /* AVI Packet Body 0x00 */
+#define S5P_AVI_BYTE11 S5P_HDMI_BASE(0x0348) /* AVI Packet Body 0x00 */
+#define S5P_AVI_BYTE12 S5P_HDMI_BASE(0x034c) /* AVI Packet Body 0x00 */
+#define S5P_AVI_BYTE13 S5P_HDMI_BASE(0x0350) /* AVI Packet Body 0x00 */
+
+#define S5P_AUI_CON S5P_HDMI_BASE(0x0360) /* AUI Packet Control Register 0x00 */
+#define S5P_AUI_CHECK_SUM S5P_HDMI_BASE(0x0370) /* AUI Packet Checksum 0x00 */
+
+#define S5P_AUI_BYTE1 S5P_HDMI_BASE(0x0380) /* AUI Packet Body 0x00 */
+#define S5P_AUI_BYTE2 S5P_HDMI_BASE(0x0384) /* AUI Packet Body 0x00 */
+#define S5P_AUI_BYTE3 S5P_HDMI_BASE(0x0388) /* AUI Packet Body 0x00 */
+#define S5P_AUI_BYTE4 S5P_HDMI_BASE(0x038c) /* AUI Packet Body 0x00 */
+#define S5P_AUI_BYTE5 S5P_HDMI_BASE(0x0390) /* AUI Packet Body 0x00 */
+
+#define S5P_MPG_CON S5P_HDMI_BASE(0x03A0) /* ACR Packet Control Register 0x00 */
+#define S5P_MPG_CHECK_SUM S5P_HDMI_BASE(0x03B0) /* MPG Packet Checksum 0x00 */
+
+#define S5P_MPEG_BYTE1 S5P_HDMI_BASE(0x03c0) /* MPEG Packet Body 0x00 */
+#define S5P_MPEG_BYTE2 S5P_HDMI_BASE(0x03c4) /* MPEG Packet Body 0x00 */
+#define S5P_MPEG_BYTE3 S5P_HDMI_BASE(0x03c8) /* MPEG Packet Body 0x00 */
+#define S5P_MPEG_BYTE4 S5P_HDMI_BASE(0x03cc) /* MPEG Packet Body 0x00 */
+#define S5P_MPEG_BYTE5 S5P_HDMI_BASE(0x03d0) /* MPEG Packet Body 0x00 */
+
+#define S5P_SPD_CON S5P_HDMI_BASE(0x0400) /* SPD Packet Control Register 0x00 */
+#define S5P_SPD_HEADER0 S5P_HDMI_BASE(0x0410) /* SPD Packet Header 0x00 */
+#define S5P_SPD_HEADER1 S5P_HDMI_BASE(0x0414) /* SPD Packet Header 0x00 */
+#define S5P_SPD_HEADER2 S5P_HDMI_BASE(0x0418) /* SPD Packet Header 0x00 */
+
+#define S5P_SPD_DATA0 S5P_HDMI_BASE(0x0420) /* SPD Packet Body 0x00 */
+#define S5P_SPD_DATA1 S5P_HDMI_BASE(0x0424) /* SPD Packet Body 0x00 */
+#define S5P_SPD_DATA2 S5P_HDMI_BASE(0x0428) /* SPD Packet Body 0x00 */
+#define S5P_SPD_DATA3 S5P_HDMI_BASE(0x042c) /* SPD Packet Body 0x00 */
+#define S5P_SPD_DATA4 S5P_HDMI_BASE(0x0430) /* SPD Packet Body 0x00 */
+#define S5P_SPD_DATA5 S5P_HDMI_BASE(0x0434) /* SPD Packet Body 0x00 */
+#define S5P_SPD_DATA6 S5P_HDMI_BASE(0x0438) /* SPD Packet Body 0x00 */
+#define S5P_SPD_DATA7 S5P_HDMI_BASE(0x043c) /* SPD Packet Body 0x00 */
+#define S5P_SPD_DATA8 S5P_HDMI_BASE(0x0440) /* SPD Packet Body 0x00 */
+#define S5P_SPD_DATA9 S5P_HDMI_BASE(0x0444) /* SPD Packet Body 0x00 */
+#define S5P_SPD_DATA10 S5P_HDMI_BASE(0x0448) /* SPD Packet Body 0x00 */
+#define S5P_SPD_DATA11 S5P_HDMI_BASE(0x044c) /* SPD Packet Body 0x00 */
+#define S5P_SPD_DATA12 S5P_HDMI_BASE(0x0450) /* SPD Packet Body 0x00 */
+#define S5P_SPD_DATA13 S5P_HDMI_BASE(0x0454) /* SPD Packet Body 0x00 */
+#define S5P_SPD_DATA14 S5P_HDMI_BASE(0x0458) /* SPD Packet Body 0x00 */
+#define S5P_SPD_DATA15 S5P_HDMI_BASE(0x045c) /* SPD Packet Body 0x00 */
+#define S5P_SPD_DATA16 S5P_HDMI_BASE(0x0460) /* SPD Packet Body 0x00 */
+#define S5P_SPD_DATA17 S5P_HDMI_BASE(0x0464) /* SPD Packet Body 0x00 */
+#define S5P_SPD_DATA18 S5P_HDMI_BASE(0x0468) /* SPD Packet Body 0x00 */
+#define S5P_SPD_DATA19 S5P_HDMI_BASE(0x046c) /* SPD Packet Body 0x00 */
+#define S5P_SPD_DATA20 S5P_HDMI_BASE(0x0470) /* SPD Packet Body 0x00 */
+#define S5P_SPD_DATA21 S5P_HDMI_BASE(0x0474) /* SPD Packet Body 0x00 */
+#define S5P_SPD_DATA22 S5P_HDMI_BASE(0x0478) /* SPD Packet Body 0x00 */
+#define S5P_SPD_DATA23 S5P_HDMI_BASE(0x048c) /* SPD Packet Body 0x00 */
+#define S5P_SPD_DATA24 S5P_HDMI_BASE(0x0480) /* SPD Packet Body 0x00 */
+#define S5P_SPD_DATA25 S5P_HDMI_BASE(0x0484) /* SPD Packet Body 0x00 */
+#define S5P_SPD_DATA26 S5P_HDMI_BASE(0x0488) /* SPD Packet Body 0x00 */
+#define S5P_SPD_DATA27 S5P_HDMI_BASE(0x048c) /* SPD Packet Body 0x00 */
+
+#define S5P_HDCP_RX_SHA1_0_0 S5P_HDMI_BASE(0x0600) /* SHA-1 Value from Repeater 0x00 */
+#define S5P_HDCP_RX_SHA1_0_1 S5P_HDMI_BASE(0x0604) /* SHA-1 Value from Repeater 0x00 */
+#define S5P_HDCP_RX_SHA1_0_2 S5P_HDMI_BASE(0x0608) /* SHA-1 value from Repeater 0x00 */
+#define S5P_HDCP_RX_SHA1_0_3 S5P_HDMI_BASE(0x060C) /* SHA-1 value from Repeater 0x00 */
+#define S5P_HDCP_RX_SHA1_1_0 S5P_HDMI_BASE(0x0610) /* SHA-1 value from Repeater 0x00 */
+#define S5P_HDCP_RX_SHA1_1_1 S5P_HDMI_BASE(0x0614) /* SHA-1 value from Repeater 0x00 */
+#define S5P_HDCP_RX_SHA1_1_2 S5P_HDMI_BASE(0x0618) /* SHA-1 value from Repeater 0x00 */
+#define S5P_HDCP_RX_SHA1_1_3 S5P_HDMI_BASE(0x061C) /* SHA-1 value from Repeater 0x00 */
+#define S5P_HDCP_RX_SHA1_2_0 S5P_HDMI_BASE(0x0620) /* SHA-1 value from Repeater 0x00 */
+#define S5P_HDCP_RX_SHA1_2_1 S5P_HDMI_BASE(0x0624) /* SHA-1 value from Repeater 0x00 */
+#define S5P_HDCP_RX_SHA1_2_2 S5P_HDMI_BASE(0x0628) /* SHA-1 value from Repeater 0x00 */
+#define S5P_HDCP_RX_SHA1_2_3 S5P_HDMI_BASE(0x062C) /* SHA-1 value from Repeater 0x00 */
+#define S5P_HDCP_RX_SHA1_3_0 S5P_HDMI_BASE(0x0630) /* SHA-1 value from Repeater 0x00 */
+#define S5P_HDCP_RX_SHA1_3_1 S5P_HDMI_BASE(0x0634) /* SHA-1 value from Repeater 0x00 */
+#define S5P_HDCP_RX_SHA1_3_2 S5P_HDMI_BASE(0x0638) /* SHA-1 value from Repeater 0x00 */
+#define S5P_HDCP_RX_SHA1_3_3 S5P_HDMI_BASE(0x063C) /* SHA-1 value from Repeater 0x00 */
+#define S5P_HDCP_RX_SHA1_4_0 S5P_HDMI_BASE(0x0640) /* SHA-1 value from Repeater 0x00 */
+#define S5P_HDCP_RX_SHA1_4_1 S5P_HDMI_BASE(0x0644) /* SHA-1 value from Repeater 0x00 */
+#define S5P_HDCP_RX_SHA1_4_2 S5P_HDMI_BASE(0x0648) /* SHA-1 value from Repeater 0x00 */
+#define S5P_HDCP_RX_SHA1_4_3 S5P_HDMI_BASE(0x064C) /* SHA-1 value from Repeater 0x00 */
+
+#define S5P_HDCP_RX_KSV_0_0 S5P_HDMI_BASE(0x0650) /* Receiver¡¯s KSV 0 0x00 */
+#define S5P_HDCP_RX_KSV_0_1 S5P_HDMI_BASE(0x0654) /* Receiver¡¯s KSV 0 0x00 */
+#define S5P_HDCP_RX_KSV_0_2 S5P_HDMI_BASE(0x0658) /* Receiver¡¯s KSV 0 0x00 */
+#define S5P_HDCP_RX_KSV_0_3 S5P_HDMI_BASE(0x065C) /* Receiver¡¯s KSV 0 0x00 */
+#define S5P_HDCP_RX_KSV_0_4 S5P_HDMI_BASE(0x0660) /* Receiver¡¯s KSV 1 0x00 */
+
+#define S5P_HDCP_RX_KSV_LIST_CTRL S5P_HDMI_BASE(0x0664) /* Receiver¡¯s KSV 1 0x00 */
+#define S5P_HDCP_AUTH_STATUS S5P_HDMI_BASE(0x0670) /* 2nd authentication status 0x00 */
+#define S5P_HDCP_CTRL1 S5P_HDMI_BASE(0x0680) /* HDCP Control 0x00 */
+#define S5P_HDCP_CTRL2 S5P_HDMI_BASE(0x0684) /* HDCP Control 0x00 */
+#define S5P_HDCP_CHECK_RESULT S5P_HDMI_BASE(0x0690) /* HDCP Ri, Pj, V result 0x00 */
+
+#define S5P_HDCP_BKSV_0_0 S5P_HDMI_BASE(0x06A0) /* Receiver¡¯s BKSV 0x00 */
+#define S5P_HDCP_BKSV_0_1 S5P_HDMI_BASE(0x06A4) /* Receiver¡¯s BKSV 0x00 */
+#define S5P_HDCP_BKSV_0_2 S5P_HDMI_BASE(0x06A8) /* Receiver¡¯s BKSV 0x00 */
+#define S5P_HDCP_BKSV_0_3 S5P_HDMI_BASE(0x06AC) /* Receiver¡¯s BKSV 0x00 */
+#define S5P_HDCP_BKSV_1 S5P_HDMI_BASE(0x06B0) /* Receiver¡¯s BKSV 0x00 */
+
+#define S5P_HDCP_AKSV_0_0 S5P_HDMI_BASE(0x06C0) /* Transmitter¡¯s AKSV 0x00 */
+#define S5P_HDCP_AKSV_0_1 S5P_HDMI_BASE(0x06C4) /* Transmitter¡¯s AKSV 0x00 */
+#define S5P_HDCP_AKSV_0_2 S5P_HDMI_BASE(0x06C8) /* Transmitter¡¯s AKSV 0x00 */
+#define S5P_HDCP_AKSV_0_3 S5P_HDMI_BASE(0x06CC) /* Transmitter¡¯s AKSV 0x00 */
+#define S5P_HDCP_AKSV_1 S5P_HDMI_BASE(0x06D0) /* Transmitter¡¯s AKSV 0x00 */
+
+#define S5P_HDCP_An_0_0 S5P_HDMI_BASE(0x06E0) /* Transmitter¡¯s An 0x00 */
+#define S5P_HDCP_An_0_1 S5P_HDMI_BASE(0x06E4) /* Transmitter¡¯s An 0x00 */
+#define S5P_HDCP_An_0_2 S5P_HDMI_BASE(0x06E8) /* Transmitter¡¯s An 0x00 */
+#define S5P_HDCP_An_0_3 S5P_HDMI_BASE(0x06EC) /* Transmitter¡¯s An 0x00 */
+#define S5P_HDCP_An_1_0 S5P_HDMI_BASE(0x06F0) /* Transmitter¡¯s An 0x00 */
+#define S5P_HDCP_An_1_1 S5P_HDMI_BASE(0x06F4) /* Transmitter¡¯s An 0x00 */
+#define S5P_HDCP_An_1_2 S5P_HDMI_BASE(0x06F8) /* Transmitter¡¯s An 0x00 */
+#define S5P_HDCP_An_1_3 S5P_HDMI_BASE(0x06FC) /* Transmitter¡¯s An 0x00 */
+
+#define S5P_HDCP_BCAPS S5P_HDMI_BASE(0x0700) /* Receiver¡¯s BCAPS 0x00 */
+#define S5P_HDCP_BSTATUS_0 S5P_HDMI_BASE(0x0710) /* Receiver¡¯s BSTATUS 0x00 */
+#define S5P_HDCP_BSTATUS_1 S5P_HDMI_BASE(0x0714) /* Receiver¡¯s BSTATUS 0x00 */
+#define S5P_HDCP_Ri_0 S5P_HDMI_BASE(0x0740) /* Transmitter¡¯s Ri 0x00 */
+#define S5P_HDCP_Ri_1 S5P_HDMI_BASE(0x0744) /* Transmitter¡¯s Ri 0x00 */
+
+#define S5P_HDCP_I2C_INT S5P_HDMI_BASE(0x0780) /* HDCP I2C interrupt status */
+#define S5P_HDCP_AN_INT S5P_HDMI_BASE(0x0790) /* HDCP An interrupt status */
+#define S5P_HDCP_WDT_INT S5P_HDMI_BASE(0x07a0) /* HDCP Watchdog interrupt status */
+#define S5P_HDCP_RI_INT S5P_HDMI_BASE(0x07b0) /* HDCP RI interrupt status */
+
+#define S5P_HDCP_RI_COMPARE_0 S5P_HDMI_BASE(0x07d0) /* HDCP Ri Interrupt Frame number index register 0 */
+#define S5P_HDCP_RI_COMPARE_1 S5P_HDMI_BASE(0x07d4) /* HDCP Ri Interrupt Frame number index register 1 */
+#define S5P_HDCP_FRAME_COUNT S5P_HDMI_BASE(0x07e0) /* Current value of the frame count index in the hardware */
+
+#define HDMI_GAMUT_CON S5P_HDMI_BASE(0x0500) /* Gamut Metadata packet transmission control register */
+#define HDMI_GAMUT_HEADER0 S5P_HDMI_BASE(0x0504) /* Gamut metadata packet header */
+#define HDMI_GAMUT_HEADER1 S5P_HDMI_BASE(0x0508) /* Gamut metadata packet header */
+#define HDMI_GAMUT_HEADER2 S5P_HDMI_BASE(0x050c) /* Gamut metadata packet header */
+#define HDMI_GAMUT_DATA00 S5P_HDMI_BASE(0x0510) /* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA01 S5P_HDMI_BASE(0x0514) /* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA02 S5P_HDMI_BASE(0x0518) /* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA03 S5P_HDMI_BASE(0x051c) /* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA04 S5P_HDMI_BASE(0x0520) /* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA05 S5P_HDMI_BASE(0x0524) /* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA06 S5P_HDMI_BASE(0x0528) /* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA07 S5P_HDMI_BASE(0x052c) /* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA08 S5P_HDMI_BASE(0x0530) /* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA09 S5P_HDMI_BASE(0x0534) /* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA10 S5P_HDMI_BASE(0x0538) /* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA11 S5P_HDMI_BASE(0x053c) /* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA12 S5P_HDMI_BASE(0x0540) /* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA13 S5P_HDMI_BASE(0x0544) /* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA14 S5P_HDMI_BASE(0x0548) /* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA15 S5P_HDMI_BASE(0x054c) /* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA16 S5P_HDMI_BASE(0x0550) /* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA17 S5P_HDMI_BASE(0x0554) /* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA18 S5P_HDMI_BASE(0x0558) /* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA19 S5P_HDMI_BASE(0x055c) /* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA20 S5P_HDMI_BASE(0x0560) /* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA21 S5P_HDMI_BASE(0x0564) /* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA22 S5P_HDMI_BASE(0x0568) /* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA23 S5P_HDMI_BASE(0x056c) /* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA24 S5P_HDMI_BASE(0x0570) /* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA25 S5P_HDMI_BASE(0x0574) /* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA26 S5P_HDMI_BASE(0x0578) /* Gamut Metadata packet body data */
+#define HDMI_GAMUT_DATA27 S5P_HDMI_BASE(0x057c) /* Gamut Metadata packet body data */
+
+#define S5P_HDMI_DC_CONTROL S5P_HDMI_BASE(0x05C0) /* Gamut Metadata packet body data */
+#define S5P_HDMI_VIDEO_PATTERN_GEN S5P_HDMI_BASE(0x05C4) /* Gamut Metadata packet body data */
+#define S5P_HDMI_HPD_GEN S5P_HDMI_BASE(0x05C8) /* Gamut Metadata packet body data */
+
+#define S5P_TG_CMD S5P_HDMI_TG_BASE(0x0000) /* Command Register 0x00 */
+#define S5P_TG_H_FSZ_L S5P_HDMI_TG_BASE(0x0018) /* Horizontal Full Size 0x72 */
+#define S5P_TG_H_FSZ_H S5P_HDMI_TG_BASE(0x001C) /* Horizontal Full Size 0x06 */
+#define S5P_TG_HACT_ST_L S5P_HDMI_TG_BASE(0x0020) /* Horizontal Active Start 0x05 */
+#define S5P_TG_HACT_ST_H S5P_HDMI_TG_BASE(0x0024) /* Horizontal Active Start 0x01 */
+#define S5P_TG_HACT_SZ_L S5P_HDMI_TG_BASE(0x0028) /* Horizontal Active Size 0x00 */
+#define S5P_TG_HACT_SZ_H S5P_HDMI_TG_BASE(0x002C) /* Horizontal Active Size 0x05 */
+#define S5P_TG_V_FSZ_L S5P_HDMI_TG_BASE(0x0030) /* Vertical Full Line Size 0xEE */
+#define S5P_TG_V_FSZ_H S5P_HDMI_TG_BASE(0x0034) /* Vertical Full Line Size 0x02 */
+#define S5P_TG_VSYNC_L S5P_HDMI_TG_BASE(0x0038) /* Vertical Sync Position 0x01 */
+#define S5P_TG_VSYNC_H S5P_HDMI_TG_BASE(0x003C) /* Vertical Sync Position 0x00 */
+#define S5P_TG_VSYNC2_L S5P_HDMI_TG_BASE(0x0040) /* Vertical Sync Position for Bottom Field 0x33 */
+#define S5P_TG_VSYNC2_H S5P_HDMI_TG_BASE(0x0044) /* Vertical Sync Position for Bottom Field 0x02 */
+#define S5P_TG_VACT_ST_L S5P_HDMI_TG_BASE(0x0048) /* Vertical Sync Active Start Position 0x1a */
+#define S5P_TG_VACT_ST_H S5P_HDMI_TG_BASE(0x004C) /* Vertical Sync Active Start Position 0x00 */
+#define S5P_TG_VACT_SZ_L S5P_HDMI_TG_BASE(0x0050) /* Vertical Active Size 0xd0 */
+#define S5P_TG_VACT_SZ_H S5P_HDMI_TG_BASE(0x0054) /* Vertical Active Size 0x02 */
+#define S5P_TG_FIELD_CHG_L S5P_HDMI_TG_BASE(0x0058) /* Field Change Position 0x33 */
+#define S5P_TG_FIELD_CHG_H S5P_HDMI_TG_BASE(0x005C) /* Field Change Position 0x02 */
+#define S5P_TG_VACT_ST2_L S5P_HDMI_TG_BASE(0x0060) /* Vertical Sync Active Start Position for Bottom Field 0x48 */
+#define S5P_TG_VACT_ST2_H S5P_HDMI_TG_BASE(0x0064) /* Vertical Sync Active Start Position for Bottom Field 0x02 */
+
+#define S5P_TG_VSYNC_TOP_HDMI_L S5P_HDMI_TG_BASE(0x0078) /* HDMI Vsync Positon for Top Field 0x01 */
+#define S5P_TG_VSYNC_TOP_HDMI_H S5P_HDMI_TG_BASE(0x007C) /* HDMI Vsync Positon for Top Field 0x00 */
+#define S5P_TG_VSYNC_BOT_HDMI_L S5P_HDMI_TG_BASE(0x0080) /* HDMI Vsync Positon for Bottom Field 0x33 */
+#define S5P_TG_VSYNC_BOT_HDMI_H S5P_HDMI_TG_BASE(0x0084) /* HDMI Vsync Positon for Bottom Field 0x02 */
+#define S5P_TG_FIELD_TOP_HDMI_L S5P_HDMI_TG_BASE(0x0088) /* HDMI Top Field Start Position 0x01 */
+#define S5P_TG_FIELD_TOP_HDMI_H S5P_HDMI_TG_BASE(0x008C) /* HDMI Top Field Start Position 0x00 */
+#define S5P_TG_FIELD_BOT_HDMI_L S5P_HDMI_TG_BASE(0x0090) /* HDMI Bottom Field Start Position 0x33 */
+#define S5P_TG_FIELD_BOT_HDMI_H S5P_HDMI_TG_BASE(0x0094) /* HDMI Bottom Field Start Position 0x02 */
+
+#define S5P_EFUSE_CTRL S5P_HDMI_EFUSE_BASE(0x0000)
+#define S5P_EFUSE_STATUS S5P_HDMI_EFUSE_BASE(0x0004)
+#define S5P_EFUSE_ADDR_WIDTH S5P_HDMI_EFUSE_BASE(0x0008)
+#define S5P_EFUSE_SIGDEV_ASSERT S5P_HDMI_EFUSE_BASE(0x000c)
+#define S5P_EFUSE_SIGDEV_DEASSERT S5P_HDMI_EFUSE_BASE(0x0010)
+#define S5P_EFUSE_PRCHG_ASSERT S5P_HDMI_EFUSE_BASE(0x0014)
+#define S5P_EFUSE_PRCHG_DEASSERT S5P_HDMI_EFUSE_BASE(0x0018)
+#define S5P_EFUSE_FSET_ASSERT S5P_HDMI_EFUSE_BASE(0x001c)
+#define S5P_EFUSE_FSET_DEASSERT S5P_HDMI_EFUSE_BASE(0x0020)
+#define S5P_EFUSE_SENSING S5P_HDMI_EFUSE_BASE(0x0024)
+#define S5P_EFUSE_SCK_ASSERT S5P_HDMI_EFUSE_BASE(0x0028)
+#define S5P_EFUSE_SCK_DEASSERT S5P_HDMI_EFUSE_BASE(0x002c)
+#define S5P_EFUSE_SDOUT_OFFSET S5P_HDMI_EFUSE_BASE(0x0030)
+#define S5P_EFUSE_READ_OFFSET S5P_HDMI_EFUSE_BASE(0x0034)
+
+#define S5P_HDMI_I2S_CLK_CON S5P_HDMI_I2S_BASE(0x0000) /* I2S Clock Enable Register0x00 */
+#define S5P_HDMI_I2S_CON_1 S5P_HDMI_I2S_BASE(0x0004) /* I2S Control Register 10x00 */
+#define S5P_HDMI_I2S_CON_2 S5P_HDMI_I2S_BASE(0x0008) /* I2S Control Register 20x00 */
+#define S5P_HDMI_I2S_PIN_SEL_0 S5P_HDMI_I2S_BASE(0x000C) /* I2S Input Pin Selection Register 0 0x77 */
+#define S5P_HDMI_I2S_PIN_SEL_1 S5P_HDMI_I2S_BASE(0x0010) /* I2S Input Pin Selection Register 1 0x77 */
+#define S5P_HDMI_I2S_PIN_SEL_2 S5P_HDMI_I2S_BASE(0x0014) /* I2S Input Pin Selection Register 2 0x77 */
+#define S5P_HDMI_I2S_PIN_SEL_3 S5P_HDMI_I2S_BASE(0x0018) /* I2S Input Pin Selection Register 30x07 */
+#define S5P_HDMI_I2S_DSD_CON S5P_HDMI_I2S_BASE(0x001C) /* I2S DSD Control Register0x02 */
+#define S5P_HDMI_I2S_MUX_CON S5P_HDMI_I2S_BASE(0x0020) /* I2S In/Mux Control Register 0x60 */
+#define S5P_HDMI_I2S_CH_ST_CON S5P_HDMI_I2S_BASE(0x0024) /* I2S Channel Status Control Register0x00 */
+#define S5P_HDMI_I2S_CH_ST_0 S5P_HDMI_I2S_BASE(0x0028) /* I2S Channel Status Block 00x00 */
+#define S5P_HDMI_I2S_CH_ST_1 S5P_HDMI_I2S_BASE(0x002C) /* I2S Channel Status Block 10x00 */
+#define S5P_HDMI_I2S_CH_ST_2 S5P_HDMI_I2S_BASE(0x0030) /* I2S Channel Status Block 20x00 */
+#define S5P_HDMI_I2S_CH_ST_3 S5P_HDMI_I2S_BASE(0x0034) /* I2S Channel Status Block 30x00 */
+#define S5P_HDMI_I2S_CH_ST_4 S5P_HDMI_I2S_BASE(0x0038) /* I2S Channel Status Block 40x00 */
+#define S5P_HDMI_I2S_CH_ST_SH_0 S5P_HDMI_I2S_BASE(0x003C) /* I2S Channel Status Block Shadow Register 00x00 */
+#define S5P_HDMI_I2S_CH_ST_SH_1 S5P_HDMI_I2S_BASE(0x0040) /* I2S Channel Status Block Shadow Register 10x00 */
+#define S5P_HDMI_I2S_CH_ST_SH_2 S5P_HDMI_I2S_BASE(0x0044) /* I2S Channel Status Block Shadow Register 20x00 */
+#define S5P_HDMI_I2S_CH_ST_SH_3 S5P_HDMI_I2S_BASE(0x0048) /* I2S Channel Status Block Shadow Register 30x00 */
+#define S5P_HDMI_I2S_CH_ST_SH_4 S5P_HDMI_I2S_BASE(0x004C) /* I2S Channel Status Block Shadow Register 40x00 */
+#define S5P_HDMI_I2S_VD_DATA S5P_HDMI_I2S_BASE(0x0050) /* I2S Audio Sample Validity Register0x00 */
+#define S5P_HDMI_I2S_MUX_CH S5P_HDMI_I2S_BASE(0x0054) /* I2S Channel Enable Register0x03 */
+#define S5P_HDMI_I2S_MUX_CUV S5P_HDMI_I2S_BASE(0x0058) /* I2S CUV Enable Register0x03 */
+#define S5P_HDMI_I2S_IRQ_MASK S5P_HDMI_I2S_BASE(0x005C) /* I2S Interrupt Request Mask Register0x03 */
+#define S5P_HDMI_I2S_IRQ_STATUS S5P_HDMI_I2S_BASE(0x0060) /* I2S Interrupt Request Status Register0x00 */
+#define S5P_HDMI_I2S_CH0_L_0 S5P_HDMI_I2S_BASE(0x0064) /* I2S PCM Output Data Register0x00 */
+#define S5P_HDMI_I2S_CH0_L_1 S5P_HDMI_I2S_BASE(0x0068) /* I2S PCM Output Data Register0x00 */
+#define S5P_HDMI_I2S_CH0_L_2 S5P_HDMI_I2S_BASE(0x006C) /* I2S PCM Output Data Register0x00 */
+#define S5P_HDMI_I2S_CH0_L_3 S5P_HDMI_I2S_BASE(0x0070) /* I2S PCM Output Data Register0x00 */
+#define S5P_HDMI_I2S_CH0_R_0 S5P_HDMI_I2S_BASE(0x0074) /* I2S PCM Output Data Register0x00 */
+#define S5P_HDMI_I2S_CH0_R_1 S5P_HDMI_I2S_BASE(0x0078) /* I2S PCM Output Data Register0x00 */
+#define S5P_HDMI_I2S_CH0_R_2 S5P_HDMI_I2S_BASE(0x007C) /* I2S PCM Output Data Register0x00 */
+#define S5P_HDMI_I2S_CH0_R_3 S5P_HDMI_I2S_BASE(0x0080) /* I2S PCM Output Data Register0x00 */
+#define S5P_HDMI_I2S_CH1_L_0 S5P_HDMI_I2S_BASE(0x0084) /* I2S PCM Output Data Register0x00 */
+#define S5P_HDMI_I2S_CH1_L_1 S5P_HDMI_I2S_BASE(0x0088) /* I2S PCM Output Data Register0x00 */
+#define S5P_HDMI_I2S_CH1_L_2 S5P_HDMI_I2S_BASE(0x008C) /* I2S PCM Output Data Register0x00 */
+#define S5P_HDMI_I2S_CH1_L_3 S5P_HDMI_I2S_BASE(0x0090) /* I2S PCM Output Data Register0x00 */
+#define S5P_HDMI_I2S_CH1_R_0 S5P_HDMI_I2S_BASE(0x0094) /* I2S PCM Output Data Register0x00 */
+#define S5P_HDMI_I2S_CH1_R_1 S5P_HDMI_I2S_BASE(0x0098) /* I2S PCM Output Data Register0x00 */
+#define S5P_HDMI_I2S_CH1_R_2 S5P_HDMI_I2S_BASE(0x009C) /* I2S PCM Output Data Register0x00 */
+#define S5P_HDMI_I2S_CH1_R_3 S5P_HDMI_I2S_BASE(0x00A0) /* I2S PCM Output Data Register0x00 */
+#define S5P_HDMI_I2S_CH2_L_0 S5P_HDMI_I2S_BASE(0x00A4) /* I2S PCM Output Data Register0x00 */
+#define S5P_HDMI_I2S_CH2_L_1 S5P_HDMI_I2S_BASE(0x00A8) /* I2S PCM Output Data Register0x00 */
+#define S5P_HDMI_I2S_CH2_L_2 S5P_HDMI_I2S_BASE(0x00AC) /* I2S PCM Output Data Register0x00 */
+#define S5P_HDMI_I2S_CH2_L_3 S5P_HDMI_I2S_BASE(0x00B0) /* I2S PCM Output Data Register0x00 */
+#define S5P_HDMI_I2S_CH2_R_0 S5P_HDMI_I2S_BASE(0x00B4) /* I2S PCM Output Data Register0x00 */
+#define S5P_HDMI_I2S_CH2_R_1 S5P_HDMI_I2S_BASE(0x00B8) /* I2S PCM Output Data Register0x00 */
+#define S5P_HDMI_I2S_CH2_R_2 S5P_HDMI_I2S_BASE(0x00BC) /* I2S PCM Output Data Register0x00 */
+#define S5P_HDMI_I2S_Ch2_R_3 S5P_HDMI_I2S_BASE(0x00C0) /* I2S PCM Output Data Register0x00 */
+#define S5P_HDMI_I2S_CH3_L_0 S5P_HDMI_I2S_BASE(0x00C4) /* I2S PCM Output Data Register0x00 */
+#define S5P_HDMI_I2S_CH3_L_1 S5P_HDMI_I2S_BASE(0x00C8) /* I2S PCM Output Data Register0x00 */
+#define S5P_HDMI_I2S_CH3_L_2 S5P_HDMI_I2S_BASE(0x00CC) /* I2S PCM Output Data Register0x00 */
+#define S5P_HDMI_I2S_CH3_R_0 S5P_HDMI_I2S_BASE(0x00D0) /* I2S PCM Output Data Register0x00 */
+#define S5P_HDMI_I2S_CH3_R_1 S5P_HDMI_I2S_BASE(0x00D4) /* I2S PCM Output Data Register0x00 */
+#define S5P_HDMI_I2S_CH3_R_2 S5P_HDMI_I2S_BASE(0x00D8) /* I2S PCM Output Data Register0x00 */
+#define S5P_HDMI_I2S_CUV_L_R S5P_HDMI_I2S_BASE(0x00DC) /* I2S CUV Output Data Register0x00 */
+
+#define S5P_SPDIFIN_CLK_CTRL S5P_HDMI_SPDIF_BASE(0x0000) /* SPDIFIN_CLK_CTRL [1:0] 0x02 */
+#define S5P_SPDIFIN_OP_CTRL S5P_HDMI_SPDIF_BASE(0x0004) /* SPDIFIN_OP_CTRL [1:0] 0x00 */
+#define S5P_SPDIFIN_IRQ_MASK S5P_HDMI_SPDIF_BASE(0x0008) /* SPDIFIN_IRQ_MASK[7:0] 0x00 */
+#define S5P_SPDIFIN_IRQ_STATUS S5P_HDMI_SPDIF_BASE(0x000C) /* SPDIFIN_IRQ_STATUS [7:0] 0x00 */
+#define S5P_SPDIFIN_CONFIG_1 S5P_HDMI_SPDIF_BASE(0x0010) /* SPDIFIN_CONFIG [7:0] 0x00 */
+#define S5P_SPDIFIN_CONFIG_2 S5P_HDMI_SPDIF_BASE(0x0014) /* SPDIFIN_CONFIG [11:8] 0x00 */
+#define S5P_SPDIFIN_USER_VALUE_1 S5P_HDMI_SPDIF_BASE(0x0020) /* SPDIFIN_USER_VALUE [7:0] 0x00 */
+#define S5P_SPDIFIN_USER_VALUE_2 S5P_HDMI_SPDIF_BASE(0x0024) /* SPDIFIN_USER_VALUE [15:8] 0x00 */
+#define S5P_SPDIFIN_USER_VALUE_3 S5P_HDMI_SPDIF_BASE(0x0028) /* SPDIFIN_USER_VALUE [23:16] 0x00 */
+#define S5P_SPDIFIN_USER_VALUE_4 S5P_HDMI_SPDIF_BASE(0x002C) /* SPDIFIN_USER_VALUE [31:24] 0x00 */
+#define S5P_SPDIFIN_CH_STATUS_0_1 S5P_HDMI_SPDIF_BASE(0x0030) /* SPDIFIN_CH_STATUS_0 [7:0] 0x00 */
+#define S5P_SPDIFIN_CH_STATUS_0_2 S5P_HDMI_SPDIF_BASE(0x0034) /* SPDIFIN_CH_STATUS_0 [15:8] 0x00 */
+#define S5P_SPDIFIN_CH_STATUS_0_3 S5P_HDMI_SPDIF_BASE(0x0038) /* SPDIFIN_CH_STATUS_0 [23:16] 0x00 */
+#define S5P_SPDIFIN_CH_STATUS_0_4 S5P_HDMI_SPDIF_BASE(0x003C) /* SPDIFIN_CH_STATUS_0 [31:24] 0x00 */
+#define S5P_SPDIFIN_CH_STATUS_1 S5P_HDMI_SPDIF_BASE(0x0040) /* SPDIFIN_CH_STATUS_1 0x00 */
+#define S5P_SPDIFIN_FRAME_PERIOD_1 S5P_HDMI_SPDIF_BASE(0x0048) /* SPDIF_FRAME_PERIOD [7:0] 0x00 */
+#define S5P_SPDIFIN_FRAME_PERIOD_2 S5P_HDMI_SPDIF_BASE(0x004C) /* SPDIF_FRAME_PERIOD [15:8] 0x00 */
+#define S5P_SPDIFIN_Pc_INFO_1 S5P_HDMI_SPDIF_BASE(0x0050) /* SPDIFIN_Pc_INFO [7:0] 0x00 */
+#define S5P_SPDIFIN_Pc_INFO_2 S5P_HDMI_SPDIF_BASE(0x0054) /* SPDIFIN_Pc_INFO [15:8] 0x00 */
+#define S5P_SPDIFIN_Pd_INFO_1 S5P_HDMI_SPDIF_BASE(0x0058) /* SPDIFIN_Pd_INFO [7:0] 0x00 */
+#define S5P_SPDIFIN_Pd_INFO_2 S5P_HDMI_SPDIF_BASE(0x005C) /* SPDIFIN_Pd_INFO [15:8] 0x00 */
+#define S5P_SPDIFIN_DATA_BUF_0_1 S5P_HDMI_SPDIF_BASE(0x0060) /* SPDIFIN_DATA_BUF_0 [7:0] 0x00 */
+#define S5P_SPDIFIN_DATA_BUF_0_2 S5P_HDMI_SPDIF_BASE(0x0064) /* SPDIFIN_DATA_BUF_0 [15:8] 0x00 */
+#define S5P_SPDIFIN_DATA_BUF_0_3 S5P_HDMI_SPDIF_BASE(0x0068) /* SPDIFIN_DATA_BUF_0 [23:16] 0x00 */
+#define S5P_SPDIFIN_USER_BUF_0 S5P_HDMI_SPDIF_BASE(0x006C) /* SPDIFIN_DATA_BUF_0 [31:28] 0x00 */
+#define S5P_SPDIFIN_DATA_BUF_1_1 S5P_HDMI_SPDIF_BASE(0x0070) /* SPDIFIN_DATA_BUF_1 [7:0] 0x00 */
+#define S5P_SPDIFIN_DATA_BUF_1_2 S5P_HDMI_SPDIF_BASE(0x0074) /* SPDIFIN_DATA_BUF_1 [15:8] 0x00 */
+#define S5P_SPDIFIN_DATA_BUF_1_3 S5P_HDMI_SPDIF_BASE(0x0078) /* SPDIFIN_DATA_BUF_1 [23:16] 0x00 */
+#define S5P_SPDIFIN_USER_BUF_1 S5P_HDMI_SPDIF_BASE(0x007C) /* SPDIFIN_DATA_BUF_1 [31:28] 0x00 */
+
+/* HDMI_CON0 */
+#define BLUE_SCR_EN (1<<5)
+#define BLUE_SCR_DIS (0<<5)
+#define ASP_EN (1<<2)
+#define ASP_DIS (0<<2)
+#define PWDN_ENB_NORMAL (1<<1)
+#define PWDN_ENB_PD (0<<1)
+#define HDMI_EN (1<<0)
+#define HDMI_DIS (~HDMI_EN)
+
+/* HDMI_CON1 */
+#define PX_LMT_CTRL_BYPASS (0<<5)
+#define PX_LMT_CTRL_RGB (1<<5)
+#define PX_LMT_CTRL_YPBPR (2<<5)
+#define PX_LMT_CTRL_RESERVED (3<<5)
+
+/* HDMI_CON2 */
+#define VID_PREAMBLE_EN (0<<5)
+#define VID_PREAMBLE_DIS (1<<5)
+#define GUARD_BAND_EN (0<<1)
+#define GUARD_BAND_DIS (1<<1)
+
+/* HDMI_STATUS */
+#define AUTHEN_ACK_AUTH (1<<7)
+#define AUTHEN_ACK_NOT (0<<7)
+#define AUD_FIFO_OVF_FULL (1<<6)
+#define AUD_FIFO_OVF_NOT (0<<6)
+#define UPDATE_RI_INT_OCC (1<<4)
+#define UPDATE_RI_INT_NOT (0<<4)
+#define UPDATE_RI_INT_CLEAR (1<<4)
+#define UPDATE_PJ_INT_OCC (1<<3)
+#define UPDATE_PJ_INT_NOT (0<<3)
+#define UPDATE_PJ_INT_CLEAR (1<<3)
+#define EXCHANGEKSV_INT_OCC (1<<2)
+#define EXCHANGEKSV_INT_NOT (0<<2)
+#define EXCHANGEKSV_INT_CLEAR (1<<2)
+#define WATCHDOG_INT_OCC (1<<1)
+#define WATCHDOG_INT_NOT (0<<1)
+#define WATCHDOG_INT_CLEAR (1<<1)
+#define WTFORACTIVERX_INT_OCC (1)
+#define WTFORACTIVERX_INT_NOT (0)
+#define WTFORACTIVERX_INT_CLEAR (1)
+
+/* HDMI_STATUS_EN */
+#define AUD_FIFO_OVF_EN (1<<6)
+#define AUD_FIFO_OVF_DIS (0<<6)
+#define UPDATE_RI_INT_EN (1<<4)
+#define UPDATE_RI_INT_DIS (0<<4)
+#define UPDATE_PJ_INT_EN (1<<3)
+#define UPDATE_PJ_INT_DIS (0<<3)
+#define EXCHANGEKSV_INT_EN (1<<2)
+#define EXCHANGEKSV_INT_DIS (0<<2)
+#define WATCHDOG_INT_EN (1<<1)
+#define WATCHDOG_INT_DIS (0<<1)
+#define WTFORACTIVERX_INT_EN (1)
+#define WTFORACTIVERX_INT_DIS (0)
+#define HDCP_STATUS_EN_ALL UPDATE_RI_INT_EN|\
+ UPDATE_PJ_INT_DIS|\
+ EXCHANGEKSV_INT_EN|\
+ WATCHDOG_INT_EN|\
+ WTFORACTIVERX_INT_EN
+
+#define HDCP_STATUS_DIS_ALL (~0x1f)
+
+/* HDMI_HPD */
+#define SW_HPD_PLUGGED (1<<1)
+#define SW_HPD_UNPLUGGED (0<<1)
+
+/* HDMI_MODE_SEL */
+#define HDMI_MODE_EN (1<<1)
+#define HDMI_MODE_DIS (0<<1)
+#define DVI_MODE_EN (1)
+#define DVI_MODE_DIS (0)
+
+/* HDCP_ENC_EN */
+#define HDCP_ENC_ENABLE (1)
+#define HDCP_ENC_DISABLE (0)
+
+/* HDMI_BLUE_SCREEN0 */
+#define SET_BLUESCREEN_0(a) (0xff&(a))
+
+/* HDMI_BLUE_SCREEN1 */
+#define SET_BLUESCREEN_1(a) (0xff&(a))
+
+/* HDMI_BLUE_SCREEN2 */
+#define SET_BLUESCREEN_2(a) (0xff&(a))
+
+/* HDMI_YMAX */
+#define SET_HDMI_YMAX(a) (0xff&(a))
+
+/* HDMI_YMIN */
+#define SET_HDMI_YMIN(a) (0xff&(a))
+
+/* HDMI_CMAX */
+#define SET_HDMI_CMAX(a) (0xff&(a))
+
+/* HDMI_CMIN */
+#define SET_HDMI_CMIN(a) (0xff&(a))
+
+/* HDMI_DI_PREFIX */
+
+/* HDMI_VBI_ST_MG */
+#define SET_VBI_ST_MG(a) (0xff&(a))
+
+/* HDMI_VBI_END_MG */
+#define SET_VBI_END_MG(a) (0xff&(a))
+
+/* HDMI_VACT_ST_MG */
+#define SET_VACT_ST_MG(a) (0xff&(a))
+
+/* HDMI_VACT_END_MG
+ HDMI_AUTH_ST_MG0
+ HDMI_AUTH_ST_MG1
+ HDMI_AUTH_END_MG0
+ HDMI_AUTH_END_MG1 */
+
+/* HDMI_H_BLANK0 */
+#define SET_H_BLANK_L(a) (0xff&(a))
+
+/* HDMI_H_BLANK1 */
+#define SET_H_BLANK_H(a) (0x7&((a)>>8))
+
+/* HDMI_V_BLANK0 */
+#define SET_V2_BLANK_L(a) (0xff&(a))
+
+/* HDMI_V_BLANK1 */
+#define SET_V1_BLANK_L(a) ((0x1f&(a))<<3)
+#define SET_V2_BLANK_H(a) (0x7&((a)>>8))
+
+/* HDMI_V_BLANK2 */
+#define SET_V1_BLANK_H(a) (0x3f&((a)>>5))
+
+/* HDMI_H_V_LINE0 */
+#define SET_V_LINE_L(a) (0xff&(a))
+
+/* HDMI_H_V_LINE1 */
+#define SET_H_LINE_L(a) ((0xf&(a))<<4)
+#define SET_V_LINE_H(a) (0xf&((a)>>8))
+
+/* HDMI_H_V_LINE2 */
+#define SET_H_LINE_H(a) (0xff&((a)>>4))
+
+/* HDMI_SYNC_MODE */
+#define V_SYNC_POL_ACT_LOW (1)
+#define V_SYNC_POL_ACT_HIGH (0)
+
+/* HDMI_INT_PRO_MODE */
+#define INT_PRO_MODE_INTERLACE (1)
+#define INT_PRO_MODE_PROGRESSIVE (0)
+
+/* HDMI_SEND_PER_START0
+ HDMI_SEND_PER_START1
+ HDMI_SEND_PER_END0 */
+#define SET_V_BOT_ST_L(a) (0xff&(a))
+
+/* HDMI_SEND_PER_END1 */
+#define SET_V_BOT_END_L(a) ((0x1f&(a))<<3)
+#define SET_V_BOT_ST_H(a) (0x7&((a)>>8))
+
+/* HDMI_SEND_PER_END2 */
+#define SET_V_BOT_END_H(a) (0x3f&((a)>>5))
+
+/* HDMI_V_BLANK_INTERLACE
+ HDMI_V_BLANK_INTERLACE
+ HDMI_V_BLANK_INTERLACE */
+
+/* HDMI_H_SYNC_GEN0 */
+#define SET_HSYNC_START_L(a) (0xff&(a))
+
+/* HDMI_H_SYNC_GEN1 */
+#define SET_HSYNC_END_L(a) ((0x3f&(a))<<2)
+#define SET_HSYNC_START_H(a) (0x3&((a)>>8))
+
+/* HDMI_H_SYNC_GEN2 */
+#define SET_HSYNC_POL_ACT_LOW (1<<4)
+#define SET_HSYNC_POL_ACT_HIGH (0<<4)
+#define SET_HSYNC_END_H(a) (0xf&((a)>>6))
+
+/* HDMI_V_SYNC_GEN1_0 */
+#define SET_VSYNC_T_END_L(a) (0xff&(a))
+
+/* HDMI_V_SYNC_GEN1_1 */
+#define SET_VSYNC_T_ST_L(a) ((0xf&(a))<<4)
+#define SET_VSYNC_T_END_H(a) (0xf&((a)>>8))
+
+/* HDMI_V_SYNC_GEN1_2 */
+#define SET_VSYNC_T_ST_H(a) (0xff&((a)>>4))
+
+/* HDMI_V_SYNC_GEN2_0 */
+#define SET_VSYNC_B_END_L(a) (0xff&(a))
+
+/* HDMI_V_SYNC_GEN2_1 */
+#define SET_VSYNC_B_ST_L(a) ((0xf&(a))<<4)
+#define SET_VSYNC_B_END_H(a) (0xf&((a)>>8))
+
+/* HDMI_V_SYNC_GEN2_2 */
+#define SET_VSYNC_B_ST_H(a) (0xff&((a)>>4))
+
+
+/* HDMI_V_SYNC_GEN3_0 */
+#define SET_VSYNC_H_POST_END_L(a) (0xff&(a))
+
+/* HDMI_V_SYNC_GEN3_1 */
+#define SET_VSYNC_H_POST_ST_L(a) ((0xf&(a))<<4)
+#define SET_VSYNC_H_POST_END_H(a) (0xf&((a)>>8))
+
+/* HDMI_V_SYNC_GEN3_2 */
+#define SET_VSYNC_H_POST_ST_H(a) (0xff&((a)>>4))
+
+
+/* Audio releated packet register
+ HDMI_ASP_CON */
+#define SACD_EN (1<<5)
+#define SACD_DIS (0<<5)
+#define AUD_MODE_MULTI_CH (1<<4)
+#define AUD_MODE_2_CH (0<<4)
+#define SET_SP_PRE(a) (0xf&(a))
+
+/* HDMI_ASP_SP_FLAT */
+#define SET_SP_FLAT(a) (0xf&(a))
+
+/* HDMI_ASP_CHCFG0
+ HDMI_ASP_CHCFG1
+ HDMI_ASP_CHCFG2
+ HDMI_ASP_CHCFG3 */
+#define SPK3R_SEL_I_PCM0L (0<<27)
+#define SPK3R_SEL_I_PCM0R (1<<27)
+#define SPK3R_SEL_I_PCM1L (2<<27)
+#define SPK3R_SEL_I_PCM1R (3<<27)
+#define SPK3R_SEL_I_PCM2L (4<<27)
+#define SPK3R_SEL_I_PCM2R (5<<27)
+#define SPK3R_SEL_I_PCM3L (6<<27)
+#define SPK3R_SEL_I_PCM3R (7<<27)
+#define SPK3L_SEL_I_PCM0L (0<<24)
+#define SPK3L_SEL_I_PCM0R (1<<24)
+#define SPK3L_SEL_I_PCM1L (2<<24)
+#define SPK3L_SEL_I_PCM1R (3<<24)
+#define SPK3L_SEL_I_PCM2L (4<<24)
+#define SPK3L_SEL_I_PCM2R (5<<24)
+#define SPK3L_SEL_I_PCM3L (6<<24)
+#define SPK3L_SEL_I_PCM3R (7<<24)
+#define SPK2R_SEL_I_PCM0L (0<<19)
+#define SPK2R_SEL_I_PCM0R (1<<19)
+#define SPK2R_SEL_I_PCM1L (2<<19)
+#define SPK2R_SEL_I_PCM1R (3<<19)
+#define SPK2R_SEL_I_PCM2L (4<<19)
+#define SPK2R_SEL_I_PCM2R (5<<19)
+#define SPK2R_SEL_I_PCM3L (6<<19)
+#define SPK2R_SEL_I_PCM3R (7<<19)
+#define SPK2L_SEL_I_PCM0L (0<<16)
+#define SPK2L_SEL_I_PCM0R (1<<16)
+#define SPK2L_SEL_I_PCM1L (2<<16)
+#define SPK2L_SEL_I_PCM1R (3<<16)
+#define SPK2L_SEL_I_PCM2L (4<<16)
+#define SPK2L_SEL_I_PCM2R (5<<16)
+#define SPK2L_SEL_I_PCM3L (6<<16)
+#define SPK2L_SEL_I_PCM3R (7<<16)
+#define SPK1R_SEL_I_PCM0L (0<<11)
+#define SPK1R_SEL_I_PCM0R (1<<11)
+#define SPK1R_SEL_I_PCM1L (2<<11)
+#define SPK1R_SEL_I_PCM1R (3<<11)
+#define SPK1R_SEL_I_PCM2L (4<<11)
+#define SPK1R_SEL_I_PCM2R (5<<11)
+#define SPK1R_SEL_I_PCM3L (6<<11)
+#define SPK1R_SEL_I_PCM3R (7<<11)
+#define SPK1L_SEL_I_PCM0L (0<<8)
+#define SPK1L_SEL_I_PCM0R (1<<8)
+#define SPK1L_SEL_I_PCM1L (2<<8)
+#define SPK1L_SEL_I_PCM1R (3<<8)
+#define SPK1L_SEL_I_PCM2L (4<<8)
+#define SPK1L_SEL_I_PCM2R (5<<8)
+#define SPK1L_SEL_I_PCM3L (6<<8)
+#define SPK1L_SEL_I_PCM3R (7<<8)
+#define SPK0R_SEL_I_PCM0L (0<<3)
+#define SPK0R_SEL_I_PCM0R (1<<3)
+#define SPK0R_SEL_I_PCM1L (2<<3)
+#define SPK0R_SEL_I_PCM1R (3<<3)
+#define SPK0R_SEL_I_PCM2L (4<<3)
+#define SPK0R_SEL_I_PCM2R (5<<3)
+#define SPK0R_SEL_I_PCM3L (6<<3)
+#define SPK0R_SEL_I_PCM3R (7<<3)
+#define SPK0L_SEL_I_PCM0L (0)
+#define SPK0L_SEL_I_PCM0R (1)
+#define SPK0L_SEL_I_PCM1L (2)
+#define SPK0L_SEL_I_PCM1R (3)
+#define SPK0L_SEL_I_PCM2L (4)
+#define SPK0L_SEL_I_PCM2R (5)
+#define SPK0L_SEL_I_PCM3L (6)
+#define SPK0L_SEL_I_PCM3R (7)
+
+/* HDMI_ACR_CON */
+#define ALT_CTS_RATE_CTS_1 (0<<3)
+#define ALT_CTS_RATE_CTS_11 (1<<3)
+#define ALT_CTS_RATE_CTS_21 (2<<3)
+#define ALT_CTS_RATE_CTS_31 (3<<3)
+#define ACR_TX_MODE_NO_TX (0)
+#define ACR_TX_MODE_TX_ONCE (1)
+#define ACR_TX_MODE_TXCNT_VBI (2)
+#define ACR_TX_MODE_TX_VPC (3)
+#define ACR_TX_MODE_MESURE_CTS (4)
+
+/* HDMI_ACR_MCTS0
+ HDMI_ACR_MCTS1
+ HDMI_ACR_MCTS2 */
+#define SET_ACR_MCTS(a) (0xfffff&(a))
+
+/* HDMI_ACR_CTS0
+ HDMI_ACR_CTS1
+ HDMI_ACR_CTS2 */
+#define SET_ACR_CTS(a) (0xfffff&(a))
+
+/* HDMI_ACR_N0
+ HDMI_ACR_N1
+ HDMI_ACR_N2 */
+#define SET_ACR_N(a) (0xfffff&(a))
+
+/* HDMI_ACR_LSB2 */
+#define SET_ACR_LSB2(a) (0xff&(a))
+
+/* HDMI_ACR_TXCNT */
+#define SET_ACR_TXCNT(a) (0x1f&(a))
+
+/* HDMI_ACR_TXINTERNAL */
+#define SET_ACR_TX_INTERNAL(a) (0xff&(a))
+
+/* HDMI_ACR_CTS_OFFSET */
+#define SET_ACR_CTS_OFFSET(a) (0xff&(a))
+
+/* HDMI_GCP_CON */
+#define GCP_CON_NO_TRAN (0)
+#define GCP_CON_TRANS_ONCE (1)
+#define GCP_CON_TRANS_EVERY_VSYNC (2)
+
+/* HDMI_GCP_BYTE1 */
+#define SET_GCP_BYTE1(a) (0xff&(a))
+
+
+/* ACP and ISRC1/2 packet registers
+ HDMI_ACP_CON */
+#define SET_ACP_FR_RATE(a) ((0x1f&(a))<<3)
+#define ACP_CON_NO_TRAN (0)
+#define ACP_CON_TRANS_ONCE (1)
+#define ACP_CON_TRANS_EVERY_VSYNC (2)
+
+/* HDMI_ACP_TYPE */
+#define SET_ACP_TYPE(a) (0xff&(a))
+
+
+/* HDMI_ACP_DATA0
+ HDMI_ACP_DATA1
+ HDMI_ACP_DATA2
+ HDMI_ACP_DATA3
+ HDMI_ACP_DATA4
+ HDMI_ACP_DATA5
+ HDMI_ACP_DATA6
+ HDMI_ACP_DATA7
+ HDMI_ACP_DATA8
+ HDMI_ACP_DATA9
+ HDMI_ACP_DATA10
+ HDMI_ACP_DATA11
+ HDMI_ACP_DATA12
+ HDMI_ACP_DATA13
+ HDMI_ACP_DATA14
+ HDMI_ACP_DATA15
+ HDMI_ACP_DATA16 */
+#define SET_ACP_DATA(a) (0xff&(a))
+
+
+/* HDMI_ISRC_CON */
+#define SET_ISRC_FR_RATE(a) ((0x1f&(a))<<3)
+#define ISRC_EN (1<<2)
+#define ISRC_DIS (0<<2)
+#define ISRC_TX_CON_NO_TRANS (0)
+#define ISRC_TX_CON_TRANS_ONCE (1)
+#define ISRC_TX_CON_TRANS_EVERY_VSYNC (2)
+
+/* HDMI_ISRC1_HEADER1 */
+#define SET_ISRC1_HEADER(a) (0xff&(a))
+
+/* HDMI_ISRC1_DATA0
+ HDMI_ISRC1_DATA1
+ HDMI_ISRC1_DATA2
+ HDMI_ISRC1_DATA3
+ HDMI_ISRC1_DATA4
+ HDMI_ISRC1_DATA5
+ HDMI_ISRC1_DATA6
+ HDMI_ISRC1_DATA7
+ HDMI_ISRC1_DATA8
+ HDMI_ISRC1_DATA9
+ HDMI_ISRC1_DATA10
+ HDMI_ISRC1_DATA11
+ HDMI_ISRC1_DATA12
+ HDMI_ISRC1_DATA13
+ HDMI_ISRC1_DATA14
+ HDMI_ISRC1_DATA15 */
+#define SET_ISRC1_DATA(a) (0xff&(a))
+
+/* HDMI_ISRC2_DATA0
+ HDMI_ISRC2_DATA1
+ HDMI_ISRC2_DATA2
+ HDMI_ISRC2_DATA3
+ HDMI_ISRC2_DATA4
+ HDMI_ISRC2_DATA5
+ HDMI_ISRC2_DATA6
+ HDMI_ISRC2_DATA7
+ HDMI_ISRC2_DATA8
+ HDMI_ISRC2_DATA9
+ HDMI_ISRC2_DATA10
+ HDMI_ISRC2_DATA11
+ HDMI_ISRC2_DATA12
+ HDMI_ISRC2_DATA13
+ HDMI_ISRC2_DATA14
+ HDMI_ISRC2_DATA15 */
+#define SET_ISRC2_DATA(a) (0xff&(a))
+
+
+/* AVI info-frame registers
+ HDMI_AVI_CON */
+#define AVI_TX_CON_NO_TRANS (0)
+#define AVI_TX_CON_TRANS_ONCE (1)
+#define AVI_TX_CON_TRANS_EVERY_VSYNC (2)
+
+
+/* HDMI_AVI_CHECK_SUM */
+#define SET_AVI_CHECK_SUM(a) (0xff&(a))
+
+#define HDMI_CON_PXL_REP_RATIO_MASK (1<<1 | 1<<0)
+#define HDMI_DOUBLE_PIXEL_REPETITION (0x01)
+#define AVI_PIXEL_REPETITION_DOUBLE (1<<0)
+#define AVI_PICTURE_ASPECT_4_3 (1<<4)
+#define AVI_PICTURE_ASPECT_16_9 (1<<5)
+
+/* HDMI_AVI_BYTE1
+ HDMI_AVI_BYTE2
+ HDMI_AVI_BYTE3
+ HDMI_AVI_BYTE4
+ HDMI_AVI_BYTE5
+ HDMI_AVI_BYTE6
+ HDMI_AVI_BYTE7
+ HDMI_AVI_BYTE8
+ HDMI_AVI_BYTE9
+ HDMI_AVI_BYTE10
+ HDMI_AVI_BYTE11
+ HDMI_AVI_BYTE12
+ HDMI_AVI_BYTE13 */
+#define SET_AVI_BYTE(a) (0xff&(a))
+
+/* Audio info-frame registers
+ HDMI_AUI_CON */
+#define AUI_TX_CON_NO_TRANS (0)
+#define AUI_TX_CON_TRANS_ONCE (1)
+#define AUI_TX_CON_TRANS_EVERY_VSYNC (2)
+
+/* HDMI_AUI_CHECK_SUM
+ HDMI_AVI_CHECK_SUM */
+#define SET_AUI_CHECK_SUM(a) (0xff&(a))
+
+/* HDMI_AUI_BYTE1
+ HDMI_AUI_BYTE2
+ HDMI_AUI_BYTE3
+ HDMI_AUI_BYTE4
+ HDMI_AUI_BYTE5 */
+#define SET_AUI_BYTE(a) (0xff&(a))
+
+/* MPEG source info-frame registers
+ HDMI_MPG_CON */
+#define MPG_TX_CON_NO_TRANS (0)
+#define MPG_TX_CON_TRANS_ONCE (1)
+#define MPG_TX_CON_TRANS_EVERY_VSYNC (2)
+
+/* HDMI_MPG_CHECK_SUM */
+#define SET_MPG_CHECK_SUM(a) (0xff&(a))
+
+/* HDMI_MPG_BYTE1
+ HDMI_MPG_BYTE2
+ HDMI_MPG_BYTE3
+ HDMI_MPG_BYTE4
+ HDMI_MPG_BYTE5 */
+#define SET_MPG_BYTE(a) (0xff&(a))
+
+/* Souerce product desciptor info-f
+ HDMI_SPD_CON */
+#define SPD_TX_CON_NO_TRANS (0)
+#define SPD_TX_CON_TRANS_ONCE (1)
+#define SPD_TX_CON_TRANS_EVERY_VSYNC (2)
+
+/* HDMI_SPD_HEADER0
+ HDMI_SPD_HEADER1
+ HDMI_SPD_HEADER2 */
+#define SET_SPD_HEADER(a) (0xff&(a))
+
+/* HDMI_SPD_DATA0
+ HDMI_SPD_DATA1
+ HDMI_SPD_DATA2
+ HDMI_SPD_DATA3
+ HDMI_SPD_DATA4
+ HDMI_SPD_DATA5
+ HDMI_SPD_DATA6
+ HDMI_SPD_DATA7
+ HDMI_SPD_DATA8
+ HDMI_SPD_DATA9
+ HDMI_SPD_DATA10
+ HDMI_SPD_DATA11
+ HDMI_SPD_DATA12
+ HDMI_SPD_DATA13
+ HDMI_SPD_DATA14
+ HDMI_SPD_DATA15
+ HDMI_SPD_DATA16
+ HDMI_SPD_DATA17
+ HDMI_SPD_DATA18
+ HDMI_SPD_DATA19
+ HDMI_SPD_DATA20
+ HDMI_SPD_DATA21
+ HDMI_SPD_DATA22
+ HDMI_SPD_DATA23
+ HDMI_SPD_DATA24
+ HDMI_SPD_DATA25
+ HDMI_SPD_DATA26
+ HDMI_SPD_DATA27 */
+#define SET_SPD_DATA(a) (0xff&(a))
+
+
+/* HDMI_CSC_CON */
+#define OUT_OFFSET_SEL_RGB_FR (0<<4)
+#define OUT_OFFSET_SEL_RGB_LR (2<<4)
+#define OUT_OFFSET_SEL_YCBCR (3<<4)
+#define IN_CLIP_EN (1<<2)
+#define IN_CLIP_DIS (0<<2)
+#define IN_OFFSET_SEL_RGB_FR (0)
+#define IN_OFFSET_SEL_RGB_LR (2)
+#define IN_OFFSET_SEL_YCBCR (3)
+
+/* HDMI_Y_G_COEF_L
+ HDMI_Y_G_COEF_H
+ HDMI_Y_B_COEF_L
+ HDMI_Y_B_COEF_H
+ HDMI_Y_R_COEF_L
+ HDMI_Y_R_COEF_H
+ HDMI_CB_G_COEF_L
+ HDMI_CB_G_COEF_H
+ HDMI_CB_B_COEF_L
+ HDMI_CB_B_COEF_H
+ HDMI_CB_R_COEF_L
+ HDMI_CB_R_COEF_H
+ HDMI_CR_G_COEF_L
+ HDMI_CR_G_COEF_H
+ HDMI_CR_B_COEF_L
+ HDMI_CR_B_COEF_H
+ HDMI_CR_R_COEF_L
+ HDMI_CR_R_COEF_H */
+#define SET_HDMI_CSC_COEF_L(a) (0xff&(a))
+#define SET_HDMI_CSC_COEF_H(a) (0x3&((a)>>8))
+
+/* Test pattern generation register
+ HDMI_TPGEN_0
+ HDMI_TPGEN_1
+ HDMI_TPGEN_2
+ HDMI_TPGEN_3
+ HDMI_TPGEN_4
+ HDMI_TPGEN_5
+ HDMI_TPGEN_6
+
+ HDCP_RX_SHA_1_0_0
+ HDCP_RX_SHA_1_0_1
+ HDCP_RX_SHA_1_0_2
+ HDCP_RX_SHA_1_0_3
+ HDCP_RX_SHA_1_1_0
+ HDCP_RX_SHA_1_1_1
+ HDCP_RX_SHA_1_1_2
+ HDCP_RX_SHA_1_1_3
+ HDCP_RX_SHA_1_2_0
+ HDCP_RX_SHA_1_2_1
+ HDCP_RX_SHA_1_2_2
+ HDCP_RX_SHA_1_2_3
+ HDCP_RX_SHA_1_3_0
+ HDCP_RX_SHA_1_3_1
+ HDCP_RX_SHA_1_3_2
+ HDCP_RX_SHA_1_3_3
+ HDCP_RX_SHA_1_4_0
+ HDCP_RX_SHA_1_4_1
+ HDCP_RX_SHA_1_4_2
+ HDCP_RX_SHA_1_4_3 */
+#define SET_HDMI_SHA1(a) (0xff&(a))
+
+/* HDCP_RX_KSV_0_0
+ HDCP_RX_KSV_0_1
+ HDCP_RX_KSV_0_2
+ HDCP_RX_KSV_0_3
+ HDCP_RX_KSV_1_0
+ HDCP_RX_KSV_1_1
+
+ HDCP_AUTH_STAT
+
+ HDCP_CTRL
+
+ HDCP_CHECK_RESULT
+
+ HDCP_BKSV0_0
+ HDCP_BKSV0_1
+ HDCP_BKSV0_2
+ HDCP_BKSV0_3
+ HDCP_BKSV1
+ HDCP_AKSV0_0
+ HDCP_AKSV0_1
+ HDCP_AKSV0_2
+ HDCP_AKSV0_3
+ HDCP_AKSV1
+
+ HDCP_AN0_0
+ HDCP_AN0_1
+ HDCP_AN0_2
+ HDCP_AN0_3
+ HDCP_AN1_0
+ HDCP_AN1_1
+ HDCP_AN1_2
+ HDCP_AN1_3
+
+ HDCP_BCAPS
+ HDCP_BSTATUS0
+ HDCP_BSTATUS1
+
+ HDCP_RI_0
+ HDCP_RI_1
+ HDCP_PJ
+
+ HDCP_OFFSET_TX0
+ HDCP_OFFSET_TX1
+ HDCP_OFFSET_TX2
+ HDCP_OFFSET_TX3
+ HDCP_CYCLE_AA
+ HDCP_I2C_INT
+ HDCP_AN_INT
+ HDCP_WATCHDOG_INT
+ HDCP_RI_INT
+ HDCP_PJ_INT
+
+ TG SFR
+ TG_CMD */
+#define GETSYNC_TYPE_EN (1<<4)
+#define GETSYNC_TYPE_DIS (~GETSYNC_TYPE_EN)
+#define GETSYNC_EN (1<<3)
+#define GETSYNC_DIS (~GETSYNC_EN)
+#define FIELD_EN (1<<1)
+#define FIELD_DIS (~FIELD_EN)
+#define TG_EN (1)
+#define TG_DIS (~TG_EN)
+
+/* TG_CFG
+ TG_CB_SZ
+ TG_INDELAY_L
+ TG_INDELAY_H
+ TG_POL_CTRL
+
+ TG_H_FSZ_L */
+#define SET_TG_H_FSZ_L(a) (0xff&(a))
+
+/* TG_H_FSZ_H */
+#define SET_TG_H_FSZ_H(a) (0x1f&((a)>>8))
+
+/* TG_HACT_ST_L */
+#define SET_TG_HACT_ST_L(a) (0xff&(a))
+
+/* TG_HACT_ST_H */
+#define SET_TG_HACT_ST_H(a) (0xf&((a)>>8))
+
+/* TG_HACT_SZ_L */
+#define SET_TG_HACT_SZ_L(a) (0xff&(a))
+
+/* TG_HACT_SZ_H */
+#define SET_TG_HACT_SZ_H(a) (0xf&((a)>>8))
+
+/* TG_V_FSZ_L */
+#define SET_TG_V_FSZ_L(a) (0xff&(a))
+
+/* TG_V_FSZ_H */
+#define SET_TG_V_FSZ_H(a) (0x7&((a)>>8))
+
+/* TG_VSYNC_L */
+#define SET_TG_VSYNC_L(a) (0xff&(a))
+
+/* TG_VSYNC_H */
+#define SET_TG_VSYNC_H(a) (0x7&((a)>>8))
+
+/* TG_VSYNC2_L */
+#define SET_TG_VSYNC2_L(a) (0xff&(a))
+
+/* TG_VSYNC2_H */
+#define SET_TG_VSYNC2_H(a) (0x7&((a)>>8))
+
+/* TG_VACT_ST_L */
+#define SET_TG_VACT_ST_L(a) (0xff&(a))
+
+/* TG_VACT_ST_H */
+#define SET_TG_VACT_ST_H(a) (0x7&((a)>>8))
+
+/* TG_VACT_SZ_L */
+#define SET_TG_VACT_SZ_L(a) (0xff&(a))
+
+/* TG_VACT_SZ_H */
+#define SET_TG_VACT_SZ_H(a) (0x7&((a)>>8))
+
+/* TG_FIELD_CHG_L */
+#define SET_TG_FIELD_CHG_L(a) (0xff&(a))
+
+/* TG_FIELD_CHG_H */
+#define SET_TG_FIELD_CHG_H(a) (0x7&((a)>>8))
+
+/* TG_VACT_ST2_L */
+#define SET_TG_VACT_ST2_L(a) (0xff&(a))
+
+/* TG_VACT_ST2_H */
+#define SET_TG_VACT_ST2_H(a) (0x7&((a)>>8))
+
+/* TG_VACT_SC_ST_L
+ TG_VACT_SC_ST_H
+ TG_VACT_SC_SZ_L
+ TG_VACT_SC_SZ_H
+
+ TG_VSYNC_TOP_HDMI_L */
+#define SET_TG_VSYNC_TOP_HDMI_L(a) (0xff&(a))
+
+/* TG_VSYNC_TOP_HDMI_H */
+#define SET_TG_VSYNC_TOP_HDMI_H(a) (0x7&((a)>>8))
+
+/* TG_VSYNC_BOT_HDMI_L */
+#define SET_TG_VSYNC_BOT_HDMI_L(a) (0xff&(a))
+
+/* TG_VSYNC_BOT_HDMI_H */
+#define SET_TG_VSYNC_BOT_HDMI_H(a) (0x7&((a)>>8))
+
+/* TG_FIELD_TOP_HDMI_L */
+#define SET_TG_FIELD_TOP_HDMI_L(a) (0xff&(a))
+
+/* TG_FIELD_TOP_HDMI_H */
+#define SET_TG_FIELD_TOP_HDMI_H(a) (0x7&((a)>>8))
+
+/* TG_FIELD_BOT_HDMI_L */
+#define SET_TG_FIELD_BOT_HDMI_L(a) (0xff&(a))
+
+/* TG_FIELD_BOT_HDMI_H */
+#define SET_TG_FIELD_BOT_HDMI_H(a) (0x7&((a)>>8))
+
+/* TG_HSYNC_HDOUT_ST_L
+ TG_HSYNC_HDOUT_ST_H
+ TG_HSYNC_HDOUT_END_L
+ TG_HSYNC_HDOUT_END_H
+ TG_VSYNC_HDOUT_ST_L
+ TG_VSYNC_HDOUT_ST_H
+ TG_VSYNC_HDOUT_END_L
+ TG_VSYNC_HDOUT_END_H
+ TG_VSYNC_HDOUT_DLY_L
+ TG_VSYNC_HDOUT_DLY_H
+ TG_BT_ERR_RANGE
+ TG_BT_ERR_RESULT
+ TG_COR_THR
+ TG_COR_NUM
+ TG_BT_CON
+ TG_BT_H_FSZ_L
+ TG_BT_H_FSZ_H
+ TG_BT_HSYNC_ST
+ TG_BT_HSYNC_SZ
+ TG_BT_FSZ_L
+ TG_BT_FSZ_H
+ TG_BT_VACT_T_ST_L
+ TG_BT_VACT_T_ST_H
+ TG_BT_VACT_B_ST_L
+ TG_BT_VACT_B_ST_H
+ TG_BT_VACT_SZ_L
+ TG_BT_VACT_SZ_H
+ TG_BT_VSYNC_SZ
+ SPDIFIN_CLK_CTRL
+ SPDIFIN_OP_CTRL
+
+ SPDIFIN_IRQ_MASK */
+#define IRQ_WRONG_SIGNAL_ENABLE (1<<0)
+#define IRQ_CH_STATUS_RECOVERED_ENABLE (1<<1)
+#define IRQ_WRONG_PREAMBLE_ENABLE (1<<2)
+#define IRQ_STREAM_HEADER_NOT_DETECTED_ENABLE (1<<3)
+#define IRQ_STREAM_HEADER_DETECTED_ENABLE (1<<4)
+#define IRQ_STREAM_HEADER_NOT_DETECTED_AT_RIGHTTIME_ENABLE (1<<5)
+#define IRQ_ABNORMAL_PD_ENABLE (1<<6)
+#define IRQ_BUFFER_OVERFLOW_ENABLE (1<<7)
+
+/* SPDIFIN_IRQ_STATUS
+SPDIFIN_CONFIG_1 */
+
+#define CONFIG_FILTER_3_SAMPLE (0<<6)
+#define CONFIG_FILTER_2_SAMPLE (1<<6)
+#define CONFIG_LINEAR_PCM_TYPE (0<<5)
+#define CONFIG_NON_LINEAR_PCM_TYPE (1<<5)
+#define CONFIG_PCPD_AUTO_SET (0<<4)
+#define CONFIG_PCPD_MANUAL_SET (1<<4)
+#define CONFIG_WORD_LENGTH_AUTO_SET (0<<3)
+#define CONFIG_WORD_LENGTH_MANUAL_SET (1<<3)
+#define CONFIG_U_V_C_P_NEGLECT (0<<2)
+#define CONFIG_U_V_C_P_REPORT (1<<2)
+#define CONFIG_BURST_SIZE_1 (0<<1)
+#define CONFIG_BURST_SIZE_2 (1<<1)
+#define CONFIG_DATA_ALIGN_16BIT (0<<0)
+#define CONFIG_DATA_ALIGN_32BIT (1<<0)
+
+/* SPDIFIN_CONFIG_2
+ SPDIFIN_USER_VALUE_1
+ SPDIFIN_USER_VALUE_2
+ SPDIFIN_USER_VALUE_3
+ SPDIFIN_USER_VALUE_4
+ SPDIFIN_CH_STATUS_0_1
+ SPDIFIN_CH_STATUS_0_2
+ SPDIFIN_CH_STATUS_0_3
+ SPDIFIN_CH_STATUS_0_4
+ SPDIFIN_CH_STATUS_1
+ SPDIFIN_FRAME_PERIOD_1
+ SPDIFIN_FRAME_PERIOD_2
+ SPDIFIN_PC_INFO_1
+ SPDIFIN_PC_INFO_2
+ SPDIFIN_PD_INFO_1
+ SPDIFIN_PD_INFO_2
+ SPDIFIN_DATA_BUF_0_1
+ SPDIFIN_DATA_BUF_0_2
+ SPDIFIN_DATA_BUF_0_3
+ SPDIFIN_USER_BUF_0
+ SPDIFIN_USER_BUF_1_1
+ SPDIFIN_USER_BUF_1_2
+ SPDIFIN_USER_BUF_1_3
+ SPDIFIN_USER_BUF_1
+
+ HAES_START
+ HAES_DATA_SIZE_L
+ HAES_DATA_SIZE_H
+ HAES_DATA */
+
+/* Macros - for HDCP */
+
+/* HDMI SYSTEM STATUS FLAG REGISTER (STATUS, R/W, ADDRESS = 0XF030_0010) */
+#define AUTHEN_ACK_POS 7
+#define AUD_FIFO_OVF_POS 6
+/* RESERVED 5 */
+#define UPDATE_RI_INT_POS 4
+#define UPDATE_PJ_INT_POS 3
+#define EXCHANGEKSV_INT_POS 2
+#define WATCHDOG_INT_POS 1
+#define WTFORACTIVERX_INT_POS 0
+
+#define AUTHENTICATED (0x1 << 7)
+#define NOT_YET_AUTHENTICATED (0x0 << 7)
+#define AUD_FIFO_OVF_INT_OCCURRED (0x1 << 6)
+#define AUD_FIFO_OVF_INT_NOT_OCCURRED (0x0 << 6)
+/* RESERVED 5 */
+#define UPDATE_RI_INT_OCCURRED (0x1 << 4)
+#define UPDATE_RI_INT_NOT_OCCURRED (0x0 << 4)
+#define UPDATE_PJ_INT_OCCURRED (0x1 << 3)
+#define UPDATE_PJ_INT_NOT_OCCURRED (0x0 << 3)
+#define EXCHANGEKSV_INT_OCCURRED (0x1 << 2)
+#define EXCHANGEKSV_INT_NOT_OCCURRED (0x0 << 2)
+#define WATCHDOG_INT_OCCURRED (0x1 << 1)
+#define WATCHDOG_INT_NOT_OCCURRED (0x0 << 1)
+#define WTFORACTIVERX_INT_OCCURRED (0x1 << 0)
+#define WTFORACTIVERX_INT_NOT_OCCURRED (0x0 << 0)
+
+/* HDMI SYSTEM STATUS ENABLE REGISTER (STATUS_EN, R/W, ADDRESS = 0XF030_0020) */
+/* RESERVED 7 */
+#define AUD_FIFO_OVF_INT_EN (0x1 << 6)
+#define AUD_FIFO_OVF_INT_DIS (0x0 << 6)
+/* RESERVED 5 */
+
+/* EFUSE CONTROL REGISTER */
+#define EFUSE_CTRL_ACTIVATE (1)
+#define EFUSE_ADDR_WIDTH (240)
+#define EFUSE_SIGDEV_ASSERT (0)
+#define EFUSE_SIGDEV_DEASSERT (96)
+#define EFUSE_PRCHG_ASSERT (0)
+#define EFUSE_PRCHG_DEASSERT (144)
+#define EFUSE_FSET_ASSERT (48)
+#define EFUSE_FSET_DEASSERT (192)
+#define EFUSE_SENSING (240)
+#define EFUSE_SCK_ASSERT (48)
+#define EFUSE_SCK_DEASSERT (144)
+#define EFUSE_SDOUT_OFFSET (192)
+#define EFUSE_READ_OFFSET (192)
+
+#define EFUSE_ECC_DONE (1<<0)
+#define EFUSE_ECC_BUSY (1<<1)
+#define EFUSE_ECC_FAIL (1<<2)
+
+/* HDCP CONTROL REGISTER (HDCP_CTRL1, R/W, ADDRESS = 0XF030_ 0680) */
+#define EN_PJ_EN (0x1 << 4)
+#define EN_PJ_DIS (~EN_PJ_EN)
+/* RESERVED 3 */
+#define SET_REPEATER_TIMEOUT (0x1 << 2)
+#define CLEAR_REPEATER_TIMEOUT (~SET_REPEATER_TIMEOUT)
+#define CP_DESIRED_EN (0x1 << 1)
+#define CP_DESIRED_DIS (~CP_DESIRED_EN)
+#define ENABLE_1_DOT_1_FEATURE_EN (0x1 << 0)
+#define ENABLE_1_DOT_1_FEATURE_DIS (~ENABLE_1_DOT_1_FEATURE_EN)
+
+/* HDCP_CHECK_RESULT, R/W, ADDRESS = 0XF030_ 0690 */
+#define Pi_MATCH_RESULT__YES ((0x1<<3) | (0x1<<2))
+#define Pi_MATCH_RESULT__NO ((0x1<<3) | (0x0<<2))
+#define Ri_MATCH_RESULT__YES ((0x1<<1) | (0x1<<0))
+#define Ri_MATCH_RESULT__NO ((0x1<<1) | (0x0<<0))
+#define CLEAR_ALL_RESULTS 0x0
+
+/* HDCP ENCRYPTION ENABLE REGISTER (ENC_EN, R/W, ADDRESS = 0XF030_0044) */
+#define HDCP_ENC_DIS (0x0 << 0)
+
+/* BCAPS INFORMATION FROM RX. THIS VALUE IS THE DATA READ FROM RX
+ * (HDCP_BCAPS, R/W,ADDRESS = 0XF030_0700)
+ RESERVED 7 */
+#define REPEATER_SET (0x1 << 6)
+#define REPEATERP_CLEAR (0x1 << 6)
+#define READY_SET (0x1 << 5)
+#define READY_CLEAR (0x1 << 5)
+#define FAST_SET (0x1 << 4)
+#define FAST_CLEAR (0x1 << 4)
+/* RESERVED 3
+ RESERVED 2 */
+#define ONE_DOT_ONE_FEATURES_SET (0x1 << 1)
+#define ONE_DOT_ONE_FEATURES_CLEAR (0x1 << 1)
+#define FAST_REAUTHENTICATION_SET (0x1 << 0)
+#define FAST_REAUTHENTICATION_CLEAR (0x1 << 0)
+
+/* HAES REGISTERS
+ HAES CONTROL */
+#define SCRAMBLER_KEY_START_EN (0x1 << 7)
+#define SCRAMBLER_KEY_START_DIS (~SCRAMBLER_KEY_START_EN)
+#define SCRAMBLER_KEY_DONE (0x1 << 6)
+#define SCRAMBLER_KEY_GENERATING (0x0 << 6)
+/* RESERVED 1<-->5 */
+#define HAES_START_EN (0x1 << 0)
+#define HAES_DECRYPTION_DONE (0x0 << 0)
+
+#define AN_SIZE 8
+#define AKSV_SIZE 5
+#define BKSV_SIZE 5
+#define HDCPLink_Addr 0x74
+
+#define CABLE_PLUGGED 1<<1
+#define CABLE_UNPLUGGED 0<<1
+
+#define DDC_Addr 0xA0
+#define eDDC_Addr 0x60
+#define HDCPLink_Addr 0x74
+
+#define HDCP_Bksv 0x00
+#define HDCP_Aksv 0x10
+#define HDCP_Ainfo 0x15
+#define HDCP_An 0x18
+#define HDCP_Ri 0x08
+#define HDCP_Bcaps 0x40
+#define HDCP_BStatus 0x41
+#define HDCP_Pj 0x0a
+
+#define HDCP_KSVFIFO 0x43
+#define HDCP_SHA1 0x20
+
+#define HDMI_MODE_HDMI 0
+#define HDMI_MODE_DVI 1
+
+#define EDID_SEGMENT_ID 0x60
+#define EDID_SEGMENT0 0x00
+#define EDID_SEGMENT1 0x01
+
+#define EDID_DEVICE_ID 0xA0
+#define EDID_ADDR_START 0x00
+#define EDID_ADDR_EXT 0x80
+#define EDID_RCOUNT 127
+
+#define EDID_POS_EXTENSION 0x7E
+#define EDID_POS_CHECKSUM 0x7F
+/* #define EDID_POS_ERROR 516 // 512+1 // move to hdmi.h by shin...1229 */
+#define VALID_EDID 0xA5
+#define NO_VALID_EDID 0
+
+#define EDID_POS_RBUFFER0 0x00 //segment0, 128-byte
+#define EDID_POS_RBUFFER1 0x80 //segment0, 256-byte
+#define EDID_POS_RBUFFER2 0x100 //segment1, 128-byte
+#define EDID_POS_RBUFFER3 0x180 //segment1, 256-byte
+
+#define EDID_TIMING_EXT_TAG_ADDR_POS 0x80
+#define EDID_TIMING_EXT_REV_NUMBER 0x81
+#define EDID_DETAILED_TIMING_OFFSET_POS 0x82
+#define EDID_COLOR_SPACE_ADDR 0x83
+#define EDID_DATA_BLOCK_ADDRESS 0x84
+#define EDID_TIMING_EXT_TAG_VAL 0x02
+#define EDID_YCBCR444_CS_MASK 0x20
+#define EDID_YCBCR422_CS_MASK 0x10
+#define EDID_TAG_CODE_MASK 0xE0
+#define EDID_DATA_BLOCK_SIZE_MASK 0x1F
+#define EDID_NATIVE_RESOLUTION_MASK 0x80
+
+#define EDID_SHORT_AUD_DEC_TAG 0x20
+#define EDID_SHORT_VID_DEC_TAG 0x40
+#define EDID_HDMI_VSDB_TAG 0x60
+#define EDID_SPEAKER_ALLOCATION_TAG 0x80
+
+#define COLOR_SPACE_RGB 0
+#define COLOR_SPACE_YCBCR444 1
+#define COLOR_SPACE_YCBCR422 2
+
+#define SHORT_VID_720_480P_4_3_NT 0x01
+#define SHORT_VID_720_480P_16_9_NT 0x02
+#define SHORT_VID_1280_720P_16_9_NT 0x04
+#define SHORT_VID_1920_1080i_16_9_NT 0x08
+#define SHORT_VID_720_576P_4_3_PAL 0x10
+#define SHORT_VID_720_576P_16_9_PAL 0x20
+#define SHORT_VID_1280_720P_16_9_PAL 0x40
+#define SHORT_VID_1920_1080i_16_9_PAL 0x80
+
+#define SET_HDMI_RESOLUTION_480P 0x00
+#define SET_HDMI_RESOLUTION_720P 0x01
+#define SET_HDMI_RESOLUTION_1080i 0x02
+
+#define HDMI_WAIT_TIMEOUT 20
+#define AUTHENTICATION_SUCCESS 0
+#define AUTHENTICATION_FAILURE 1
+#define AUTHENTICATION_FAIL_CNT 2
+
+#define HDCP_MAX_DEVS 128
+#define HDCP_KSV_SIZE 5
+
+#define CMD_IIC_ADDRMODE_CHANGE 0xFF
+
+/* IIC Addressing Mode Definition */
+#define IIC_ADDRMODE_1 0
+#define IIC_ADDRMODE_2 1
+#define IIC_ADDRMODE_3 2
+#define HDMI_IIC_ADDRMODE IIC_ADDRMODE_1
+
+#define IIC_ACK 0
+#define IIC_NOACK 1
+
+#define EDID_POS_ERROR 512
+#define R_VAL_RETRY_CNT 5
+
+#define CABLE_INSERT 1
+#define CABLE_REMOVE (~CABLE_INSERT)
+
+#define HDMI_PHY_READY (1<<0)
+
+/* Color Depth
+ CD0, CD1, CD2, CD3 */
+
+#define GCP_CD_NOT_INDICATED 0
+#define GCP_CD_24BPP (1<<2)
+#define GCP_CD_30BPP (1<<0 | 1<<2)
+#define GCP_CD_36BPP (1<<1 | 1<<2)
+#define GCP_CD_48BPP (1<<0 | 1<<1 | 1<<2)
+
+#define GCP_DEFAULT_PHASE 1
+
+/* for DC_CONTRAL */
+#define HDMI_DC_CTL_8 0
+#define HDMI_DC_CTL_10 (1<<0)
+#define HDMI_DC_CTL_12 (1<<1)
+
+#define DO_NOT_TRANSMIT (0)
+
+#define HPD_SW_ENABLE (1<<0)
+#define HPD_SW_DISABLE (0)
+#define HPD_ON (1<<1)
+#define HPD_OFF (0)
+
+
+#endif /* __ASM_ARCH_REGS_HDMI_H */
+
+
diff --git a/drivers/media/video/samsung/tv20/s5pv210/regs/regs-sdaout.h b/drivers/media/video/samsung/tv20/s5pv210/regs/regs-sdaout.h
new file mode 100644
index 0000000..2553b57
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/s5pv210/regs/regs-sdaout.h
@@ -0,0 +1,517 @@
+/* linux/drivers/media/video/samsung/tv20/s5pc100/regs/regs-sdout.h
+ *
+ * TV Encoder register header file for Samsung TVOut driver
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ * http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_REGS_SDAOUT_H
+
+#include <mach/map.h>
+
+#define S5P_SDAOUT_BASE(x) (x)
+/*
+ Registers
+*/
+#define S5P_SDO_CLKCON S5P_SDAOUT_BASE(0x0000) // Clock Control Register 0x0000_0000
+#define S5P_SDO_CONFIG S5P_SDAOUT_BASE(0x0008) // Video Standard Configuration Register 0x0024_2430
+#define S5P_SDO_SCALE S5P_SDAOUT_BASE(0x000C) // Video Scale Configuration Register 0x0000_0006
+#define S5P_SDO_SYNC S5P_SDAOUT_BASE(0x0010) // Video Sync Configuration Register 0x0000_0001
+#define S5P_SDO_VBI S5P_SDAOUT_BASE(0x0014) // VBI Configuration Register 0x0007_77FF
+#define S5P_SDO_SCALE_CH0 S5P_SDAOUT_BASE(0x001C) // Scale Control Register for DAC Channel0 0x0000_0800
+#define S5P_SDO_SCALE_CH1 S5P_SDAOUT_BASE(0x0020) // Scale Control Register for DAC Channel1 0x0000_0800
+#define S5P_SDO_SCALE_CH2 S5P_SDAOUT_BASE(0x0024) // Scale Control Register for DAC Channel2 0x0000_0800
+#define S5P_SDO_YCDELAY S5P_SDAOUT_BASE(0x0034) // Video Delay Control Register 0x0000_FA00
+#define S5P_SDO_SCHLOCK S5P_SDAOUT_BASE(0x0038) // SCH Phase Control Register 0x0000_0000
+#define S5P_SDO_DAC S5P_SDAOUT_BASE(0x003C) // DAC Configuration Register 0x0000_0000
+#define S5P_SDO_FINFO S5P_SDAOUT_BASE(0x0040) // Status Register 0x0000_0002
+#define S5P_SDO_Y0 S5P_SDAOUT_BASE(0x0044) // Y- AAF 1¡¯st and 23¡¯th Coefficient (AAF : Anti-Aliasing Filter) 0x0000_0000
+#define S5P_SDO_Y1 S5P_SDAOUT_BASE(0x0048) // Y- AAF 2¡¯nd and 22¡¯th Coefficient 0x0000_0000
+#define S5P_SDO_Y2 S5P_SDAOUT_BASE(0x004C) // Y- AAF 3¡¯rd and 21¡¯th Coefficient 0x0000_0000
+#define S5P_SDO_Y3 S5P_SDAOUT_BASE(0x0050) // Y- AAF 4¡¯th and 20¡¯th Coefficient 0x0000_0000
+#define S5P_SDO_Y4 S5P_SDAOUT_BASE(0x0054) // Y- AAF 5¡¯th and 19¡¯th Coefficient 0x0000_0000
+#define S5P_SDO_Y5 S5P_SDAOUT_BASE(0x0058) // Y- AAF 6¡¯th and 18¡¯th Coefficient 0x0000_0000
+#define S5P_SDO_Y6 S5P_SDAOUT_BASE(0x005C) // Y- AAF 7¡¯th and 17¡¯th Coefficient 0x0000_0000
+#define S5P_SDO_Y7 S5P_SDAOUT_BASE(0x0060) // Y- AAF 8¡¯th and 16¡¯th Coefficient 0x0000_0000
+#define S5P_SDO_Y8 S5P_SDAOUT_BASE(0x0064) // Y - AAF 9¡¯th and 15¡¯th Coefficient 0x0000_0000
+#define S5P_SDO_Y9 S5P_SDAOUT_BASE(0x0068) // Y- AAF 10¡¯th and 14¡¯th Coefficient 0x0000_0000
+#define S5P_SDO_Y10 S5P_SDAOUT_BASE(0x006C) // Y- AAF 11¡¯th and 13¡¯th Coefficient 0x0000_0000
+#define S5P_SDO_Y11 S5P_SDAOUT_BASE(0x0070) // Y- AAF 12¡¯th Coefficient 0x0000_025D
+#define S5P_SDO_CB0 S5P_SDAOUT_BASE(0x0080) // CB- AAF 1¡¯st and 23¡¯th Coefficient 0x0000_0000
+#define S5P_SDO_CB1 S5P_SDAOUT_BASE(0x0084) // CB- AAF 2¡¯nd and 22¡¯th Coefficient 0x0000_0000
+#define S5P_SDO_CB2 S5P_SDAOUT_BASE(0x0088) // CB- AAF 3¡¯rd and 21¡¯th Coefficient 0x0000_0000
+#define S5P_SDO_CB3 S5P_SDAOUT_BASE(0x008C) // CB-AAF 4¡¯th and 20¡¯th Coefficient 0x0000_0000
+#define S5P_SDO_CB4 S5P_SDAOUT_BASE(0x0090) // CB- AAF 5¡¯th and 19¡¯th Coefficient 0x0000_0000
+#define S5P_SDO_CB5 S5P_SDAOUT_BASE(0x0094) // CB- AAF 6¡¯th and 18¡¯th Coefficient 0x0000_0001
+#define S5P_SDO_CB6 S5P_SDAOUT_BASE(0x0098) // CB- AAF 7¡¯th and 17¡¯th Coefficient 0x0000_0007
+#define S5P_SDO_CB7 S5P_SDAOUT_BASE(0x009C) // CB- AAF 8¡¯th and 16¡¯th Coefficient 0x0000_0014
+#define S5P_SDO_CB8 S5P_SDAOUT_BASE(0x00A0) // CB- AAF 9¡¯th and 15¡¯th Coefficient 0x0000_0028
+#define S5P_SDO_CB9 S5P_SDAOUT_BASE(0x00A4) // CB- AAF 10¡¯th and 14¡¯th Coefficient 0x0000_003F
+#define S5P_SDO_CB10 S5P_SDAOUT_BASE(0x00A8) // CB- AAF 11¡¯th and 13¡¯th Coefficient 0x0000_0052
+#define S5P_SDO_CB11 S5P_SDAOUT_BASE(0x00AC) // CB- AAF 12¡¯th Coefficient 0x0000_005A
+#define S5P_SDO_CR0 S5P_SDAOUT_BASE(0x00C0) // CR- AAF 1¡¯st and 23¡¯th Coefficient 0x0000_0000
+#define S5P_SDO_CR1 S5P_SDAOUT_BASE(0x00C4) // CR- AAF 2¡¯nd and 22¡¯th Coefficient 0x0000_0000
+#define S5P_SDO_CR2 S5P_SDAOUT_BASE(0x00C8) // CR- AAF 3¡¯rd and 21¡¯th Coefficient 0x0000_0000
+#define S5P_SDO_CR3 S5P_SDAOUT_BASE(0x00CC) // CR-AAF 4¡¯th and 20¡¯th Coefficient 0x0000_0000
+#define S5P_SDO_CR4 S5P_SDAOUT_BASE(0x00D0) // CR- AAF 5¡¯th and 19¡¯th Coefficient 0x0000_0000
+#define S5P_SDO_CR5 S5P_SDAOUT_BASE(0x00D4) // CR- AAF 6¡¯th and 18¡¯th Coefficient 0x0000_0001
+#define S5P_SDO_CR6 S5P_SDAOUT_BASE(0x00D8) // CR- AAF 7¡¯th and 17¡¯th Coefficient 0x0000_0009
+#define S5P_SDO_CR7 S5P_SDAOUT_BASE(0x00DC) // CR- AAF 8¡¯th and 16¡¯th Coefficient 0x0000_001C
+#define S5P_SDO_CR8 S5P_SDAOUT_BASE(0x00E0) // CR- AAF 9¡¯th and 15¡¯th Coefficient 0x0000_0039
+#define S5P_SDO_CR9 S5P_SDAOUT_BASE(0x00E4) // CR- AAF 10¡¯th and 14¡¯th Coefficient 0x0000_005A
+#define S5P_SDO_CR10 S5P_SDAOUT_BASE(0x00E8) // CR- AAF 11¡¯th and 13¡¯th Coefficient 0x0000_0074
+#define S5P_SDO_CR11 S5P_SDAOUT_BASE(0x00EC) // CR- AAF 12¡¯th Coefficient 0x0000_007E
+#define S5P_SDO_MV_ON S5P_SDAOUT_BASE(0x0100)
+#define S5P_SDO_MV_SLINE_FIRST_EVEN S5P_SDAOUT_BASE(0x0104)
+#define S5P_SDO_MV_SLINE_FIRST_SPACE_EVEN S5P_SDAOUT_BASE(0x0108)
+#define S5P_SDO_MV_SLINE_FIRST_ODD S5P_SDAOUT_BASE(0x010C)
+#define S5P_SDO_MV_SLINE_FIRST_SPACE_ODD S5P_SDAOUT_BASE(0x0110)
+#define S5P_SDO_MV_SLINE_SPACING S5P_SDAOUT_BASE(0x0114)
+#define S5P_SDO_MV_STRIPES_NUMBER S5P_SDAOUT_BASE(0x0118)
+#define S5P_SDO_MV_STRIPES_THICKNESS S5P_SDAOUT_BASE(0x011C)
+#define S5P_SDO_MV_PSP_DURATION S5P_SDAOUT_BASE(0x0120)
+#define S5P_SDO_MV_PSP_FIRST S5P_SDAOUT_BASE(0x0124)
+#define S5P_SDO_MV_PSP_SPACING S5P_SDAOUT_BASE(0x0128)
+#define S5P_SDO_MV_SEL_LINE_PSP_AGC S5P_SDAOUT_BASE(0x012C)
+#define S5P_SDO_MV_SEL_FORMAT_PSP_AGC S5P_SDAOUT_BASE(0x0130)
+#define S5P_SDO_MV_PSP_AGC_A_ON S5P_SDAOUT_BASE(0x0134)
+#define S5P_SDO_MV_PSP_AGC_B_ON S5P_SDAOUT_BASE(0x0138)
+#define S5P_SDO_MV_BACK_PORCH S5P_SDAOUT_BASE(0x013C)
+#define S5P_SDO_MV_BURST_ADVANCED_ON S5P_SDAOUT_BASE(0x0140)
+#define S5P_SDO_MV_BURST_DURATION_ZONE1 S5P_SDAOUT_BASE(0x0144)
+#define S5P_SDO_MV_BURST_DURATION_ZONE2 S5P_SDAOUT_BASE(0x0148)
+#define S5P_SDO_MV_BURST_DURATION_ZONE3 S5P_SDAOUT_BASE(0x014C)
+#define S5P_SDO_MV_BURST_PHASE_ZONE S5P_SDAOUT_BASE(0x0150)
+#define S5P_SDO_MV_SLICE_PHASE_LINE S5P_SDAOUT_BASE(0x0154)
+#define S5P_SDO_MV_RGB_PROTECTION_ON S5P_SDAOUT_BASE(0x0158)
+#define S5P_SDO_MV_480P_PROTECTION_ON S5P_SDAOUT_BASE(0x015C)
+#define S5P_SDO_CCCON S5P_SDAOUT_BASE(0x0180) // Color Compensation On/ Off Control 0x0000_0000
+#define S5P_SDO_YSCALE S5P_SDAOUT_BASE(0x0184) // Brightness Control for Y 0x0080_0000
+#define S5P_SDO_CBSCALE S5P_SDAOUT_BASE(0x0188) // Hue/ Saturation Control for CB 0x0080_0000
+#define S5P_SDO_CRSCALE S5P_SDAOUT_BASE(0x018C) // Hue/ Saturation Control for CR 0x0000_0080
+#define S5P_SDO_CB_CR_OFFSET S5P_SDAOUT_BASE(0x0190) // Hue/ Sat Offset Control for CB/CR 0x0000_0000
+#define S5P_SDO_RGB_CC S5P_SDAOUT_BASE(0x0194) // Color Compensation of RGB Output 0x0000_EB10
+#define S5P_SDO_CVBS_CC_Y1 S5P_SDAOUT_BASE(0x0198) // Color Compensation of CVBS Output 0x0200_0000
+#define S5P_SDO_CVBS_CC_Y2 S5P_SDAOUT_BASE(0x019C) // Color Compensation of CVBS Output 0x03FF_0200
+#define S5P_SDO_CVBS_CC_C S5P_SDAOUT_BASE(0x01A0) // Color Compensation of CVBS Output 0x0000_01FF
+#define S5P_SDO_YC_CC_Y S5P_SDAOUT_BASE(0x01A4) // Color Compensation of S-video Output 0x03FF_0000
+#define S5P_SDO_YC_CC_C S5P_SDAOUT_BASE(0x01A8) // Color Compensation of S-video Output 0x0000_01FF
+#define S5P_SDO_CSC_525_PORCH S5P_SDAOUT_BASE(0x01B0) // Porch Position Control of CSC in 525 Line 0x008A_0359
+#define S5P_SDO_CSC_625_PORCH S5P_SDAOUT_BASE(0x01B4) // Porch Position Control of CSC in 625 Line 0x0096_035C
+#define S5P_SDO_RGBSYNC S5P_SDAOUT_BASE(0x01C0) // VESA RGB Sync Control Register 0x0000_0000
+#define S5P_SDO_OSFC00_0 S5P_SDAOUT_BASE(0x0200) // OverSampling Filter (OSF) Coefficient 1 & 0. of channel #0 0x00FD_00FE
+#define S5P_SDO_OSFC01_0 S5P_SDAOUT_BASE(0x0204) // OSF Coefficient 3 & 2 of Channel #0 0x0000_0000
+#define S5P_SDO_OSFC02_0 S5P_SDAOUT_BASE(0x0208) // OSF Coefficient 5 & 4 of Channel #0 0x0005_0004
+#define S5P_SDO_OSFC03_0 S5P_SDAOUT_BASE(0x020C) // OSF Coefficient 7 & 6 of Channel #0 0x0000_00FF
+#define S5P_SDO_OSFC04_0 S5P_SDAOUT_BASE(0x0210) // OSF Coefficient 9 & 8 of Channel #0 0x00F7_00FA
+#define S5P_SDO_OSFC05_0 S5P_SDAOUT_BASE(0x0214) // OSF Coefficient 11 & 10 of Channel #0 0x0000_0001
+#define S5P_SDO_OSFC06_0 S5P_SDAOUT_BASE(0x0218) // OSF Coefficient 13 & 12 of Channel #0 0x000E_000A
+#define S5P_SDO_OSFC07_0 S5P_SDAOUT_BASE(0x021C) // OSF Coefficient 15 & 14 of Channel #0 0x0000_01FF
+#define S5P_SDO_OSFC08_0 S5P_SDAOUT_BASE(0x0220) // OSF Coefficient 17 & 16 of Channel #0 0x01EC_01F2
+#define S5P_SDO_OSFC09_0 S5P_SDAOUT_BASE(0x0224) // OSF Coefficient 19 & 18 of Channel #0 0x0000_0001
+#define S5P_SDO_OSFC10_0 S5P_SDAOUT_BASE(0x0228) // OSF Coefficient 21 & 20 of Channel #0 0x001D_0014
+#define S5P_SDO_OSFC11_0 S5P_SDAOUT_BASE(0x022C) // OSF Coefficient 23 & 22 of Channel #0 0x0000_01FE
+#define S5P_SDO_OSFC12_0 S5P_SDAOUT_BASE(0x0230) // OSF Coefficient 25 & 24 of Channel #0 0x03D8_03E4
+#define S5P_SDO_OSFC13_0 S5P_SDAOUT_BASE(0x0234) // OSF Coefficient 27 & 26 of Channel #0 0x0000_0002
+#define S5P_SDO_OSFC14_0 S5P_SDAOUT_BASE(0x0238) // OSF Coefficient 29 & 28 of Channel #0 0x0038_0028
+#define S5P_SDO_OSFC15_0 S5P_SDAOUT_BASE(0x023C) // OSF Coefficient 31 & 30 of Channel #0 0x0000_03FD
+#define S5P_SDO_OSFC16_0 S5P_SDAOUT_BASE(0x0240) // OSF Coefficient 33 & 32 of Channel #0 0x03B0_03C7
+#define S5P_SDO_OSFC17_0 S5P_SDAOUT_BASE(0x0244) // OSF Coefficient 35 & 34 of Channel #0 0x0000_0005
+#define S5P_SDO_OSFC18_0 S5P_SDAOUT_BASE(0x0248) // OSF Coefficient 37 & 36 of Channel #0 0x0079_0056
+#define S5P_SDO_OSFC19_0 S5P_SDAOUT_BASE(0x024C) // OSF Coefficient 39 & 38 of Channel #0 0x0000_03F6
+#define S5P_SDO_OSFC20_0 S5P_SDAOUT_BASE(0x0250) // OSF Coefficient 41 & 40 of Channel #0 0x072C_0766
+#define S5P_SDO_OSFC21_0 S5P_SDAOUT_BASE(0x0254) // OSF Coefficient 43 & 42 of Channel #0 0x0000_001B
+#define S5P_SDO_OSFC22_0 S5P_SDAOUT_BASE(0x0258) // OSF Coefficient 45 & 44 of Channel #0 0x028B_0265
+#define S5P_SDO_OSFC23_0 S5P_SDAOUT_BASE(0x025C) // OSF Coefficient 47 & 46 of Channel #0 0x0400_0ECC
+#define S5P_SDO_XTALK0 S5P_SDAOUT_BASE(0x0260) // Crosstalk Cancel Coefficient for Ch.0 0x0000_0000
+#define S5P_SDO_XTALK1 S5P_SDAOUT_BASE(0x0264) // Crosstalk Cancel Coefficient for Ch.1 0x0000_0000
+#define S5P_SDO_XTALK2 S5P_SDAOUT_BASE(0x0268) // Crosstalk Cancel Coefficient for Ch.2 0x0000_0000
+#define S5P_SDO_BB_CTRL S5P_SDAOUT_BASE(0x026C) // Blackburst Test Control 0x0001_1A00
+#define S5P_SDO_IRQ S5P_SDAOUT_BASE(0x0280) // Interrupt Request Register 0x0000_0000
+#define S5P_SDO_IRQMASK S5P_SDAOUT_BASE(0x0284) // Interrupt Request Enable Register 0x0000_0000
+#define S5P_SDO_OSFC00_1 S5P_SDAOUT_BASE(0x02C0) // OverSampling Filter (OSF) Coefficient 1 & 0. of Channel #1 0x00FD_00FE
+#define S5P_SDO_OSFC01_1 S5P_SDAOUT_BASE(0x02C4) // OSF Coefficient 3 & 2 of Channel #1 0x0000_0000
+#define S5P_SDO_OSFC02_1 S5P_SDAOUT_BASE(0x02C8) // OSF Coefficient 5 & 4 of Channel #1 0x0005_0004
+#define S5P_SDO_OSFC03_1 S5P_SDAOUT_BASE(0x02CC) // OSF Coefficient 7 & 6 of Channel #1 0x0000_00FF
+#define S5P_SDO_OSFC04_1 S5P_SDAOUT_BASE(0x02D0) // OSF Coefficient 9 & 8 of Channel #1 0x00F7_00FA
+#define S5P_SDO_OSFC05_1 S5P_SDAOUT_BASE(0x02D4) // OSF Coefficient 11 & 10 of Channel #1 0x0000_0001
+#define S5P_SDO_OSFC06_1 S5P_SDAOUT_BASE(0x02D8) // OSF Coefficient 13 & 12 of Channel #1 0x000E_000A
+#define S5P_SDO_OSFC07_1 S5P_SDAOUT_BASE(0x02DC) // OSF Coefficient 15 & 14 of Channel #1 0x0000_01FF
+#define S5P_SDO_OSFC08_1 S5P_SDAOUT_BASE(0x02E0) // OSF Coefficient 17 & 16 of Channel #1 0x01EC_01F2
+#define S5P_SDO_OSFC09_1 S5P_SDAOUT_BASE(0x02E4) // OSF Coefficient 19 & 18 of Channel #1 0x0000_0001
+#define S5P_SDO_OSFC10_1 S5P_SDAOUT_BASE(0x02E8) // OSF Coefficient 21 & 20 of Channel #1 0x001D_0014
+#define S5P_SDO_OSFC11_1 S5P_SDAOUT_BASE(0x02EC) // OSF Coefficient 23 & 22 of Channel #1 0x0000_01FE
+#define S5P_SDO_OSFC12_1 S5P_SDAOUT_BASE(0x02E0) // OSF Coefficient 25 & 24 of Channel #1 0x03D8_03E4
+#define S5P_SDO_OSFC13_1 S5P_SDAOUT_BASE(0x02F4) // OSF Coefficient 27 & 26 of Channel #1 0x0000_0002
+#define S5P_SDO_OSFC14_1 S5P_SDAOUT_BASE(0x02F8) // OSF Coefficient 29 & 28 of Channel #1 0x0038_0028
+#define S5P_SDO_OSFC15_1 S5P_SDAOUT_BASE(0x02FC) // OSF Coefficient 31 & 30 of Channel #1 0x0000_03FD
+#define S5P_SDO_OSFC16_1 S5P_SDAOUT_BASE(0x0300) // OSF Coefficient 33 & 32 of Channel #1 0x03B0_03C7
+#define S5P_SDO_OSFC17_1 S5P_SDAOUT_BASE(0x0304) // OSF Coefficient 35 & 34 of Channel #1 0x0000_0005
+#define S5P_SDO_OSFC18_1 S5P_SDAOUT_BASE(0x0308) // OSF Coefficient 37 & 36 of Channel #1 0x0079_0056
+#define S5P_SDO_OSFC19_1 S5P_SDAOUT_BASE(0x030C) // OSF Coefficient 39 & 38 of Channel #1 0x0000_03F6
+#define S5P_SDO_OSFC20_1 S5P_SDAOUT_BASE(0x0310) // OSF Coefficient 41 & 40 of Channel #1 0x072C_0766
+#define S5P_SDO_OSFC21_1 S5P_SDAOUT_BASE(0x0314) // OSF Coefficient 43 & 42 of Channel #1 0x0000_001B
+#define S5P_SDO_OSFC22_1 S5P_SDAOUT_BASE(0x0318) // OSF Coefficient 45 & 44 of Channel #1 0x028B_0265
+#define S5P_SDO_OSFC23_1 S5P_SDAOUT_BASE(0x031C) // OSF Coefficient 47 & 46 of Channel #1 0x0400_0ECC
+#define S5P_SDO_OSFC00_2 S5P_SDAOUT_BASE(0x0320) // OverSampling Filter (OSF) Coefficient 1 & 0. of Channel #2 0x00FD_00FE
+#define S5P_SDO_OSFC01_2 S5P_SDAOUT_BASE(0x0324) // OSF Coefficient 3 & 2 of Channel #2 0x0000_0000
+#define S5P_SDO_OSFC02_2 S5P_SDAOUT_BASE(0x0328) // OSF Coefficient 5 & 4 of Channel #2 0x0005_0004
+#define S5P_SDO_OSFC03_2 S5P_SDAOUT_BASE(0x032C) // OSF Coefficient 7 & 6 of Channel #2 0x0000_00FF
+#define S5P_SDO_OSFC04_2 S5P_SDAOUT_BASE(0x0330) // OSF Coefficient 9 & 8 of Channel #2 0x00F7_00FA
+#define S5P_SDO_OSFC05_2 S5P_SDAOUT_BASE(0x0334) // OSF Coefficient 11 & 10 of Channel #2 0x0000_0001
+#define S5P_SDO_OSFC06_2 S5P_SDAOUT_BASE(0x0338) // OSF Coefficient 13 & 12 of Channel #2 0x000E_000A
+#define S5P_SDO_OSFC07_2 S5P_SDAOUT_BASE(0x033C) // OSF Coefficient 15 & 14 of Channel #2 0x0000_01FF
+#define S5P_SDO_OSFC08_2 S5P_SDAOUT_BASE(0x0340) // OSF Coefficient 17 & 16 of Channel #2 0x01EC_01F2
+#define S5P_SDO_OSFC09_2 S5P_SDAOUT_BASE(0x0344) // OSF Coefficient 19 & 18 of Channel #2 0x0000_0001
+#define S5P_SDO_OSFC10_2 S5P_SDAOUT_BASE(0x0348) // OSF Coefficient 21 & 20 of Channel #2 0x001D_0014
+#define S5P_SDO_OSFC11_2 S5P_SDAOUT_BASE(0x034C) // OSF Coefficient 23 & 22 of Channel #2 0x0000_01FE
+#define S5P_SDO_OSFC12_2 S5P_SDAOUT_BASE(0x0350) // OSF Coefficient 25 & 24 of Channel #2 0x03D8_03E4
+#define S5P_SDO_OSFC13_2 S5P_SDAOUT_BASE(0x0354) // OSF Coefficient 27 & 26 of Channel #2 0x0000_0002
+#define S5P_SDO_OSFC14_2 S5P_SDAOUT_BASE(0x0358) // OSF Coefficient 29 & 28 of Channel #2 0x0038_0028
+#define S5P_SDO_OSFC15_2 S5P_SDAOUT_BASE(0x035C) // OSF Coefficient 31 & 30 of Channel #2 0x0000_03FD
+#define S5P_SDO_OSFC16_2 S5P_SDAOUT_BASE(0x0360) // OSF Coefficient 33 & 32 of Channel #2 0x03B0_03C7
+#define S5P_SDO_OSFC17_2 S5P_SDAOUT_BASE(0x0364) // OSF Coefficient 35 & 34 of Channel #2 0x0000_0005
+#define S5P_SDO_OSFC18_2 S5P_SDAOUT_BASE(0x0368) // OSF Coefficient 37 & 36 of Channel #2 0x0079_0056
+#define S5P_SDO_OSFC19_2 S5P_SDAOUT_BASE(0x036C) // OSF Coefficient 39 & 38 of Channel #2 0x0000_03F6
+#define S5P_SDO_OSFC20_2 S5P_SDAOUT_BASE(0x0370) // OSF Coefficient 41 & 40 of Channel #2 0x072C_0766
+#define S5P_SDO_OSFC21_2 S5P_SDAOUT_BASE(0x0374) // OSF Coefficient 43 & 42 of Channel #2 0x0000_001B
+#define S5P_SDO_OSFC22_2 S5P_SDAOUT_BASE(0x0378) // OSF Coefficient 45 & 44 of Channel #2 0x028B_0265
+#define S5P_SDO_OSFC23_2 S5P_SDAOUT_BASE(0x037C) // OSF Coefficient 47 & 46 of Channel #2 0x0400_0ECC
+#define S5P_SDO_ARMCC S5P_SDAOUT_BASE(0x03C0) // Closed Caption Data Register 0x0000_0000
+#define S5P_SDO_ARMWSS525 S5P_SDAOUT_BASE(0x03C4) // WSS 525 Data Register 0x0000_0000
+#define S5P_SDO_ARMWSS625 S5P_SDAOUT_BASE(0x03C8) // WSS 625 Data Register 0x0000_0000
+#define S5P_SDO_ARMCGMS525 S5P_SDAOUT_BASE(0x03CC) // CGMS-A 525 Data Register 0x0000_0000
+#define S5P_SDO_ARMCGMS625 S5P_SDAOUT_BASE(0x03D4) // CGMS-A 625 Data Register 0x0000_0000
+#define S5P_SDO_VERSION S5P_SDAOUT_BASE(0x03D8) // TVOUT Version Number Read Register 0x0000_000C
+#define S5P_SDO_CC S5P_SDAOUT_BASE(0x0380) // Closed Caption Data Shadow register 0x0000_0000
+#define S5P_SDO_WSS525 S5P_SDAOUT_BASE(0x0384) // WSS 525 Data Shadow Register 0x0000_0000
+#define S5P_SDO_WSS625 S5P_SDAOUT_BASE(0x0388) // WSS 625 Data Shadow Register 0x0000_0000
+#define S5P_SDO_CGMS525 S5P_SDAOUT_BASE(0x038C) // CGMS-A 525 Data Shadow Register 0x0000_0000
+#define S5P_SDO_CGMS625 S5P_SDAOUT_BASE(0x0394) // CGMS-A 625 Data Shadow Register 0x0000_0000
+
+/*
+ Shadow Registers
+*/
+
+/*
+ Registers Bit Description
+*/
+/*
+ Macros
+*/
+/* SDO_CLKCON */
+#define SDO_TVOUT_SW_RESET (1<<4)
+#define SDO_TVOUT_CLK_DOWN_RDY (1<<1)
+#define SDO_TVOUT_CLOCK_ON (1)
+#define SDO_TVOUT_CLOCK_OFF (0)
+
+/* SDO_CONFIG */
+#define SDO_DAC2_Y_G (0<<20)
+#define SDO_DAC2_PB_B (1<<20)
+#define SDO_DAC2_PR_R (2<<20)
+#define SDO_DAC1_Y_G (0<<18)
+#define SDO_DAC1_PB_B (1<<18)
+#define SDO_DAC1_PR_R (2<<18)
+#define SDO_DAC0_Y_G (0<<16)
+#define SDO_DAC0_PB_B (1<<16)
+#define SDO_DAC0_PR_R (2<<16)
+#define SDO_DAC2_CVBS (0<<12)
+#define SDO_DAC2_Y (1<<12)
+#define SDO_DAC2_C (2<<12)
+#define SDO_DAC1_CVBS (0<<10)
+#define SDO_DAC1_Y (1<<10)
+#define SDO_DAC1_C (2<<10)
+#define SDO_DAC0_CVBS (0<<8)
+#define SDO_DAC0_Y (1<<8)
+#define SDO_DAC0_C (2<<8)
+#define SDO_COMPOSITE (0<<6)
+#define SDO_COMPONENT (1<<6)
+#define SDO_RGB (0<<5)
+#define SDO_YPBPR (1<<5)
+#define SDO_INTERLACED (0<<4)
+#define SDO_PROGRESSIVE (1<<4)
+#define SDO_NTSC_M (0)
+#define SDO_PAL_M (1)
+#define SDO_PAL_BGHID (2)
+#define SDO_PAL_N (3)
+#define SDO_PAL_NC (4)
+#define SDO_NTSC_443 (8)
+#define SDO_PAL_60 (9)
+
+/* SDO_SCALE */
+#define SDO_COMPONENT_LEVEL_SEL_0IRE (0<<3)
+#define SDO_COMPONENT_LEVEL_SEL_75IRE (1<<3)
+#define SDO_COMPONENT_VTOS_RATIO_10_4 (0<<2)
+#define SDO_COMPONENT_VTOS_RATIO_7_3 (1<<2)
+#define SDO_COMPOSITE_LEVEL_SEL_0IRE (0<<1)
+#define SDO_COMPOSITE_LEVEL_SEL_75IRE (1<<1)
+#define SDO_COMPOSITE_VTOS_RATIO_10_4 (0<<0)
+#define SDO_COMPOSITE_VTOS_RATIO_7_3 (1<<0)
+
+/* SDO_SYNC */
+#define SDO_COMPONENT_SYNC_ABSENT (0)
+#define SDO_COMPONENT_SYNC_YG (1)
+#define SDO_COMPONENT_SYNC_ALL (3)
+
+/* SDO_VBI */
+#define SDO_CVBS_NO_WSS (0<<14)
+#define SDO_CVBS_WSS_INS (1<<14)
+#define SDO_CVBS_NO_CLOSED_CAPTION (0<<12)
+#define SDO_CVBS_21H_CLOSED_CAPTION (1<<12)
+#define SDO_CVBS_21H_284H_CLOSED_CAPTION (2<<12)
+#define SDO_CVBS_USE_OTHERS (3<<12)
+#define SDO_SVIDEO_NO_WSS (0<<10)
+#define SDO_SVIDEO_WSS_INS (1<<10)
+#define SDO_SVIDEO_NO_CLOSED_CAPTION (0<<8)
+#define SDO_SVIDEO_21H_CLOSED_CAPTION (1<<8)
+#define SDO_SVIDEO_21H_284H_CLOSED_CAPTION (2<<8)
+#define SDO_SVIDEO_USE_OTHERS (3<<8)
+#define SDO_RGB_NO_CGMSA (0<<7)
+#define SDO_RGB_CGMSA_INS (1<<7)
+#define SDO_RGB_NO_WSS (0<<6)
+#define SDO_RGB_WSS_INS (1<<6)
+#define SDO_RGB_NO_CLOSED_CAPTION (0<<4)
+#define SDO_RGB_21H_CLOSED_CAPTION (1<<4)
+#define SDO_RGB_21H_284H_CLOSED_CAPTION (2<<4)
+#define SDO_RGB_USE_OTHERS (3<<4)
+#define SDO_YPBPR_NO_CGMSA (0<<3)
+#define SDO_YPBPR_CGMSA_INS (1<<3)
+#define SDO_YPBPR_NO_WSS (0<<2)
+#define SDO_YPBPR_WSS_INS (1<<2)
+#define SDO_YPBPR_NO_CLOSED_CAPTION (0)
+#define SDO_YPBPR_21H_CLOSED_CAPTION (1)
+#define SDO_YPBPR_21H_284H_CLOSED_CAPTION (2)
+#define SDO_YPBPR_USE_OTHERS (3)
+
+/* SDO_SCALE_CHx */
+#define SDO_SCALE_CONV_OFFSET(a) ((0x3ff&a)<<16)
+#define SDO_SCALE_CONV_GAIN(a) (0xfff&a)
+
+/* SDO_YCDELAY */
+#define SDO_DELAY_YTOC(a) ((0xf&a)<<16)
+#define SDO_ACTIVE_START_OFFSET(a) ((0xff&a)<<8)
+#define SDO_ACTIVE_END_OFFSET(a) (0xff&a)
+
+/* SDO_SCHLOCK */
+#define SDO_COLOR_SC_PHASE_ADJ (1)
+#define SDO_COLOR_SC_PHASE_NOADJ (0)
+
+/* SDO_DAC */
+#define SDO_POWER_ON_DAC2 (1<<2)
+#define SDO_POWER_DOWN_DAC2 (0<<2)
+#define SDO_POWER_ON_DAC1 (1<<1)
+#define SDO_POWER_DOWN_DAC1 (0<<1)
+#define SDO_POWER_ON_DAC0 (1<<0)
+#define SDO_POWER_DOWN_DAC0 (0<<0)
+
+/* SDO_FINFO */
+#define SDO_FIELD_MOD_1001(a) (((0x3ff<<16)&a)>>16)
+#define SDO_FIELD_ID_BOTTOM(a) ((1<<1)&a)
+#define SDO_FIELD_ID_BOTTOM_PI_INCATION(a) (1)
+/* SDO_Y0 */
+/*
+#define SDO_AA_75_73_CB (0x251)
+#define SDO_AA_75_104_CB (0x25d)
+#define SDO_AA_75_73_CB (0x281)
+#define SDO_AA_0_73_CB (0x28f)
+#define SDO_AA_75_73_CR (0x1f3)
+#define SDO_AA_75_104_CR (0x200)
+#define SDO_AA_75_73_CR (0x21e)
+#define SDO_AA_0_73_CR (0x228)
+#define SDO_AA_75_73 (0x2c0)
+#define SDO_AA_75_104 (0x2d1)
+#define SDO_AA_75_73 (0x2c0)
+#define SDO_AA_0_73 (0x30d)
+*/
+/* SDO_MV_480P_PROTECTION_ON */
+#define SDO_MV_AGC_103_ON (1)
+
+/* SDO_CCCON */
+#define SDO_COMPONENT_BHS_ADJ_ON (0<<4)
+#define SDO_COMPONENT_BHS_ADJ_OFF (1<<4)
+#define SDO_COMPONENT_YPBPR_COMP_ON (0<<3)
+#define SDO_COMPONENT_YPBPR_COMP_OFF (1<<3)
+#define SDO_COMPONENT_RGB_COMP_ON (0<<2)
+#define SDO_COMPONENT_RGB_COMP_OFF (1<<2)
+#define SDO_COMPONENT_YC_COMP_ON (0<<1)
+#define SDO_COMPONENT_YC_COMP_OFF (1<<1)
+#define SDO_COMPONENT_CVBS_COMP_ON (0)
+#define SDO_COMPONENT_CVBS_COMP_OFF (1)
+
+/* SDO_YSCALE */
+#define SDO_BRIGHTNESS_GAIN(a) ((0xff&a)<<16)
+#define SDO_BRIGHTNESS_OFFSET(a) (0xff&a)
+
+/* SDO_CBSCALE */
+#define SDO_HS_CB_GAIN0(a) ((0x1ff&a)<<16)
+#define SDO_HS_CB_GAIN1(a) (0x1ff&a)
+
+/* SDO_CRSCALE */
+#define SDO_HS_CR_GAIN0(a) ((0x1ff&a)<<16)
+#define SDO_HS_CR_GAIN1(a) (0x1ff&a)
+
+/* SDO_CB_CR_OFFSET */
+#define SDO_HS_CR_OFFSET(a) ((0x3ff&a)<<16)
+#define SDO_HS_CB_OFFSET(a) (0x3ff&a)
+
+/* SDO_RGB_CC */
+#define SDO_MAX_RGB_CUBE(a) ((0xff&a)<<8)
+#define SDO_MIN_RGB_CUBE(a) (0xff&a)
+
+/* SDO_CVBS_CC_Y1 */
+#define SDO_Y_LOWER_MID_CVBS_CORN(a) ((0x3ff&a)<<16)
+#define SDO_Y_BOTTOM_CVBS_CORN(a) (0x3ff&a)
+
+/* SDO_CVBS_CC_Y2 */
+#define SDO_Y_TOP_CVBS_CORN(a) ((0x3ff&a)<<16)
+#define SDO_Y_UPPER_MID_CVBS_CORN(a) (0x3ff&a)
+
+/* SDO_CVBS_CC_C */
+#define SDO_RADIUS_CVBS_CORN(a) (0x1ff&a)
+
+/* SDO_YC_CC_Y */
+#define SDO_Y_TOP_YC_CYLINDER(a) ((0x3ff&a)<<16)
+#define SDO_Y_BOTOM_YC_CYLINDER(a) (0x3ff&a)
+
+/* SDO_CVBS_CC_C */
+#define SDO_RADIUS_YC_CYLINDER(a) (0x1ff&a)
+
+/* SDO_CSC_525_PORCH */
+#define SDO_COMPONENT_525_BP(a) ((0x3ff&a)<<16)
+#define SDO_COMPONENT_525_FP(a) (0x3ff&a)
+
+/* SDO_CSC_525_PORCH */
+#define SDO_COMPONENT_625_BP(a) ((0x3ff&a)<<16)
+#define SDO_COMPONENT_625_FP(a) (0x3ff&a)
+
+/* SDO_RGBSYNC */
+#define SDO_RGB_SYNC_COMPOSITE (0<<8)
+#define SDO_RGB_SYNC_SEPERATE (1<<8)
+#define SDO_RGB_VSYNC_LOW_ACT (0<<4)
+#define SDO_RGB_VSYNC_HIGH_ACT (1<<4)
+#define SDO_RGB_HSYNC_LOW_ACT 0
+#define SDO_RGB_HSYNC_HIGH_ACT 1
+
+/* SDO_OSFCxx_x */
+#define SDO_OSF_COEF_ODD(a) ((0xfff&a)<<16)
+#define SDO_OSF_COEF_EVEN(a) (0xfff&a)
+
+/* SDO_XTALKx */
+#define SDO_XTALK_COEF02(a) ((0xff&a)<<16)
+#define SDO_XTALK_COEF01(a) (0xff&a)
+
+/* SDO_BB_CTRL */
+#define SDO_REF_BB_LEVEL_NTSC (0x11a<<8)
+#define SDO_REF_BB_LEVEL_PAL (0xfb<<8)
+#define SDO_SEL_BB_CJAN_CVBS0_BB1_BB2 (0<<4)
+#define SDO_SEL_BB_CJAN_BB0_CVBS1_BB2 (1<<4)
+#define SDO_SEL_BB_CJAN_BB0_BB1_CVBS2 (2<<4)
+#define SDO_BB_MODE_ENABLE (1)
+#define SDO_BB_MODE_DISABLE (0)
+
+/* SDO_IRQ */
+#define SDO_VSYNC_IRQ_PEND (1)
+#define SDO_VSYNC_NO_IRQ (0)
+
+/* SDO_IRQMASK */
+#define SDO_VSYNC_IRQ_ENABLE (0)
+#define SDO_VSYNC_IRQ_DISABLE (1)
+
+/* SDO_ARMCC */
+#define SDO_DISPLAY_CC_CAPTION(a) ((0xff&a)<<16)
+#define SDO_NON_DISPLAY_CC_CAPTION(a) (0xff&a)
+
+/* SDO_WSS525 */
+#define SDO_CRC_WSS525(a) ((0x3f&a)<<14)
+#define SDO_WORD2_WSS525_COPY_PERMIT (0<<6)
+#define SDO_WORD2_WSS525_ONECOPY_PERMIT (1<<6)
+#define SDO_WORD2_WSS525_NOCOPY_PERMIT (3<<6)
+#define SDO_WORD2_WSS525_MV_PSP_OFF (0<<8)
+#define SDO_WORD2_WSS525_MV_PSP_ON_2LINE_BURST (1<<8)
+#define SDO_WORD2_WSS525_MV_PSP_ON_BURST_OFF (2<<8)
+#define SDO_WORD2_WSS525_MV_PSP_ON_4LINE_BURST (3<<8)
+#define SDO_WORD2_WSS525_ANALOG_OFF (0<<10)
+#define SDO_WORD2_WSS525_ANALOG_ON (1<<10)
+#define SDO_WORD1_WSS525_COPY_INFO (0<<2)
+#define SDO_WORD1_WSS525_DEFAULT (0xf<<2)
+#define SDO_WORD0_WSS525_4_3_NORMAL (0)
+#define SDO_WORD0_WSS525_16_9_ANAMORPIC (1)
+#define SDO_WORD0_WSS525_4_3_LETTERBOX (2)
+
+/* SDO_WSS625 */
+#define SDO_WSS625_SURROUND_SOUND_DISABLE (0<<11)
+#define SDO_WSS625_SURROUND_SOUND_ENABLE (1<<11)
+#define SDO_WSS625_NO_COPYRIGHT (0<<12)
+#define SDO_WSS625_COPYRIGHT (1<<12)
+#define SDO_WSS625_COPY_NOT_RESTRICTED (0<<13)
+#define SDO_WSS625_COPY_RESTRICTED (1<<13)
+#define SDO_WSS625_TELETEXT_NO_SUBTITLES (0<<8)
+#define SDO_WSS625_TELETEXT_SUBTITLES (1<<8)
+#define SDO_WSS625_NO_OPEN_SUBTITLES (0<<9)
+#define SDO_WSS625_INACT_OPEN_SUBTITLES (1<<9)
+#define SDO_WSS625_OUTACT_OPEN_SUBTITLES (2<<9)
+#define SDO_WSS625_CAMERA (0<<4)
+#define SDO_WSS625_FILM (1<<4)
+#define SDO_WSS625_NORMAL_PAL (0<<5)
+#define SDO_WSS625_MOTION_ADAPTIVE_COLORPLUS (1<<5)
+#define SDO_WSS625_HELPER_NO_SIG (0<<6)
+#define SDO_WSS625_HELPER_SIG (1<<6)
+#define SDO_WSS625_4_3_FULL_576 (0x8)
+#define SDO_WSS625_14_9_LETTERBOX_CENTER_504 (0x1)
+#define SDO_WSS625_14_9_LETTERBOX_TOP_504 (0x2)
+#define SDO_WSS625_16_9_LETTERBOX_CENTER_430 (0xb)
+#define SDO_WSS625_16_9_LETTERBOX_TOP_430 (0x4)
+#define SDO_WSS625_16_9_LETTERBOX_CENTER (0xd)
+#define SDO_WSS625_14_9_FULL_CENTER_576 (0xe)
+#define SDO_WSS625_16_9_ANAMORPIC_576 (0x7)
+
+/* SDO_CGMS525 */
+#define SDO_CRC_CGMS525(a) ((0x3f&a)<<14)
+#define SDO_WORD2_CGMS525_COPY_PERMIT (0<<6)
+#define SDO_WORD2_CGMS525_ONECOPY_PERMIT (1<<6)
+#define SDO_WORD2_CGMS525_NOCOPY_PERMIT (3<<6)
+#define SDO_WORD2_CGMS525_MV_PSP_OFF (0<<8)
+#define SDO_WORD2_CGMS525_MV_PSP_ON_2LINE_BURST (1<<8)
+#define SDO_WORD2_CGMS525_MV_PSP_ON_BURST_OFF (2<<8)
+#define SDO_WORD2_CGMS525_MV_PSP_ON_4LINE_BURST (3<<8)
+#define SDO_WORD2_CGMS525_ANALOG_OFF (0<<10)
+#define SDO_WORD2_CGMS525_ANALOG_ON (1<<10)
+#define SDO_WORD1_CGMS525_COPY_INFO (0<<2)
+#define SDO_WORD1_CGMS525_DEFAULT (0xf<<2)
+#define SDO_WORD0_CGMS525_4_3_NORMAL (0)
+#define SDO_WORD0_CGMS525_16_9_ANAMORPIC (1)
+#define SDO_WORD0_CGMS525_4_3_LETTERBOX (2)
+
+/* SDO_CGMS625 */
+#define SDO_CGMS625_SURROUND_SOUND_DISABLE (0<<11)
+#define SDO_CGMS625_SURROUND_SOUND_ENABLE (1<<11)
+#define SDO_CGMS625_NO_COPYRIGHT (0<<12)
+#define SDO_CGMS625_COPYRIGHT (1<<12)
+#define SDO_CGMS625_COPY_NOT_RESTRICTED (0<<13)
+#define SDO_CGMS625_COPY_RESTRICTED (1<<13)
+#define SDO_CGMS625_TELETEXT_NO_SUBTITLES (0<<8)
+#define SDO_CGMS625_TELETEXT_SUBTITLES (1<<8)
+#define SDO_CGMS625_NO_OPEN_SUBTITLES (0<<9)
+#define SDO_CGMS625_INACT_OPEN_SUBTITLES (1<<9)
+#define SDO_CGMS625_OUTACT_OPEN_SUBTITLES (2<<9)
+#define SDO_CGMS625_CAMERA (0<<4)
+#define SDO_CGMS625_FILM (1<<4)
+#define SDO_CGMS625_NORMAL_PAL (0<<5)
+#define SDO_CGMS625_MOTION_ADAPTIVE_COLORPLUS (1<<5)
+#define SDO_CGMS625_HELPER_NO_SIG (0<<6)
+#define SDO_CGMS625_HELPER_SIG (1<<6)
+#define SDO_CGMS625_4_3_FULL_576 (0x8)
+#define SDO_CGMS625_14_9_LETTERBOX_CENTER_504 (0x1)
+#define SDO_CGMS625_14_9_LETTERBOX_TOP_504 (0x2)
+#define SDO_CGMS625_16_9_LETTERBOX_CENTER_430 (0xb)
+#define SDO_CGMS625_16_9_LETTERBOX_TOP_430 (0x4)
+#define SDO_CGMS625_16_9_LETTERBOX_CENTER (0xd)
+#define SDO_CGMS625_14_9_FULL_CENTER_576 (0xe)
+#define SDO_CGMS625_16_9_ANAMORPIC_576 (0x7)
+
+#endif /*__ASM_ARCH_REGS_SDAOUT_H */
diff --git a/drivers/media/video/samsung/tv20/s5pv210/regs/regs-vmx.h b/drivers/media/video/samsung/tv20/s5pv210/regs/regs-vmx.h
new file mode 100644
index 0000000..24126cb
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/s5pv210/regs/regs-vmx.h
@@ -0,0 +1,254 @@
+/* linux/drivers/media/video/samsung/tv20/s5pc100/regs/regs-vmx.h
+ *
+ * Mixer register header file for Samsung TVOut driver
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ * http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+#include <mach/map.h>
+
+#define S5P_MIXER_BASE(x) (x)
+/*
+ Registers
+*/
+#define S5P_MXR_STATUS S5P_MIXER_BASE(0x0000) //Status of MIXER Operation
+#define S5P_MXR_CFG S5P_MIXER_BASE(0x0004) //MIXER Mode Setting
+#define S5P_MXR_INT_EN S5P_MIXER_BASE(0x0008) //Interrupt Enable
+#define S5P_MXR_INT_STATUS S5P_MIXER_BASE(0x000C) //Interrupt Status
+#define S5P_MXR_LAYER_CFG S5P_MIXER_BASE(0x0010) //Video & Graphic Layer Priority and On// Off
+#define S5P_MXR_VIDEO_CFG S5P_MIXER_BASE(0x0014) //Video Layer Configuration
+#define S5P_MXR_GRAPHIC0_CFG S5P_MIXER_BASE(0x0020) //Graphic Layer0 Configuration
+#define S5P_MXR_GRAPHIC0_BASE S5P_MIXER_BASE(0x0024) //Base Address for Graphic Layer0
+#define S5P_MXR_GRAPHIC0_SPAN S5P_MIXER_BASE(0x0028) //Span for Graphic Layer0
+#define S5P_MXR_GRAPHIC0_SXY S5P_MIXER_BASE(0x002C) //Source X//Y Positions for Graphic Layer0
+#define S5P_MXR_GRAPHIC0_WH S5P_MIXER_BASE(0x0030) //Width// Height for Graphic Layer0
+#define S5P_MXR_GRAPHIC0_DXY S5P_MIXER_BASE(0x0034) //Destination X//Y Positions for Graphic Layer0
+#define S5P_MXR_GRAPHIC0_BLANK S5P_MIXER_BASE(0x0038) //Blank Pixel Value for Graphic Layer0
+#define S5P_MXR_GRAPHIC1_CFG S5P_MIXER_BASE(0x0040) //Graphic Layer1 Configuration
+#define S5P_MXR_GRAPHIC1_BASE S5P_MIXER_BASE(0x0044) //Base Address for Graphic Layer1
+#define S5P_MXR_GRAPHIC1_SPAN S5P_MIXER_BASE(0x0048) //Span for Graphic Layer1
+#define S5P_MXR_GRAPHIC1_SXY S5P_MIXER_BASE(0x004C) //Source X//Y Positions for Graphic Layer1
+#define S5P_MXR_GRAPHIC1_WH S5P_MIXER_BASE(0x0050) //Width// Height for Graphic Layer1
+#define S5P_MXR_GRAPHIC1_DXY S5P_MIXER_BASE(0x0054) //Destination X//Y Positions for Graphic Layer1
+#define S5P_MXR_GRAPHIC1_BLANK S5P_MIXER_BASE(0x0058) //Blank Pixel Value for Graphic Layer1
+#define S5P_MXR_BG_CFG S5P_MIXER_BASE(0x0060)
+#define S5P_MXR_BG_COLOR0 S5P_MIXER_BASE(0x0064) //Background Color of First Point
+#define S5P_MXR_BG_COLOR1 S5P_MIXER_BASE(0x0068) //Background Color of Second Point
+#define S5P_MXR_BG_COLOR2 S5P_MIXER_BASE(0x006C) //Background Color of Last Point
+#define S5P_MXR_CM_COEFF_Y S5P_MIXER_BASE(0x0080) //Scaled Color Space Conversion (RGB to Y) Coefficient for Graphic Layer
+#define S5P_MXR_CM_COEFF_CB S5P_MIXER_BASE(0x0084) //Scaled Color Space Conversion (RGB to CB) Coefficient for Graphic Layer
+#define S5P_MXR_CM_COEFF_CR S5P_MIXER_BASE(0x0088) //Scaled Color Space Conversion (RGB to Cr) Coefficient for Graphic Layer
+#define S5P_MXR_VER S5P_MIXER_BASE(0x0100) //Mixer Version
+
+/*
+ Shadow Registers
+*/
+#define S5P_MXR_STATUS_S S5P_MIXER_BASE(0x2000) //Status of MIXER Operation (Shadow)
+#define S5P_MXR_CFG_S S5P_MIXER_BASE(0x2004) //MIXER Mode Setting (Shadow)
+#define S5P_MXR_LAYER_CFG_S S5P_MIXER_BASE(0x2010) //Video & Graphic Layer Priority and On// Off (Shadow)
+#define S5P_MXR_VIDEO_CFG_S S5P_MIXER_BASE(0x2014) //Video Layer Configuration (Shadow)
+#define S5P_MXR_GRAPHIC0_CFG_S S5P_MIXER_BASE(0x2020) //Graphic Layer0 Configuration (Shadow)
+#define S5P_MXR_GRAPHIC0_BASE_S S5P_MIXER_BASE(0x2024) //Graphic0 Base Address (Shadow)
+#define S5P_MXR_GRAPHIC0_SPAN_S S5P_MIXER_BASE(0x2028) //Graphic0 Span (Shadow)
+#define S5P_MXR_GRAPHIC0_SXY_S S5P_MIXER_BASE(0x202C) //Graphic0 Source X//Y Coordinates (Shadow)
+#define S5P_MXR_GRAPHIC0_WH_S S5P_MIXER_BASE(0x2030) //Graphic0 Width// Height (Shadow)
+#define S5P_MXR_GRAPHIC0_DXY_S S5P_MIXER_BASE(0x2034) //Graphic0 Destination X//Y Coordinates (Shadow)
+#define S5P_MXR_GRAPHIC0_BLANK_PIXEL_S S5P_MIXER_BASE(0x2038) //Graphic0 Blank Pixel (Shadow)
+#define S5P_MXR_GRAPHIC1_CFG_S S5P_MIXER_BASE(0x2040) //Graphic Layer1 Configuration (Shadow)
+#define S5P_MXR_GRAPHIC1_BASE_S S5P_MIXER_BASE(0x2044) //Graphic1 Base Address (Shadow)
+#define S5P_MXR_GRAPHIC1_SPAN_S S5P_MIXER_BASE(0x2048) //Graphic1 Span (Shadow)
+#define S5P_MXR_GRAPHIC1_SXY_S S5P_MIXER_BASE(0x204C) //Graphic1 Source X//Y Coordinates (Shadow)
+#define S5P_MXR_GRAPHIC1_WH_S S5P_MIXER_BASE(0x2050) //Graphic1 Width// Height (Shadow)
+#define S5P_MXR_GRAPHIC1_DXY_S S5P_MIXER_BASE(0x2054) //Graphic1 Destination X//YCoordinates (Shadow)
+#define S5P_MXR_GRAPHIC1_BLANK_PIXEL_S S5P_MIXER_BASE(0x2058) //Graphic1 Blank Pixel (Shadow)
+#define S5P_MXR_BG_COLOR0_S S5P_MIXER_BASE(0x2064) //Background First Color (Shadow)
+#define S5P_MXR_BG_COLOR1_S S5P_MIXER_BASE(0x2068) //Background Second Color (Shadow)
+#define S5P_MXR_BG_COLOR2_S S5P_MIXER_BASE(0x206C) //Background Last Color (Shadow)
+
+/*
+ Registers Bit Description
+*/
+/* S5P_MXR_STATUS */
+#define S5P_MXR_STATUS_RUN (1<<0)
+#define S5P_MXR_STATUS_STOP (0<<0)
+#define S5P_MXR_STATUS_SYNC_DISABLE (0<<2)
+#define S5P_MXR_STATUS_SYNC_ENABLE (1<<2)
+#define S5P_MXR_STATUS_LITTLE (0<<3)
+#define S5P_MXR_STATUS_BIT (1<<3)
+#define S5P_MXR_STATUS_8_BURST (0<<7)
+#define S5P_MXR_STATUS_16_BURST (1<<7)
+
+/* S5P_MXR_CFG */
+#define S5P_MXR_CFG_SD (0<<0)
+#define S5P_MXR_CFG_HD (1<<0)
+#define S5P_MXR_CFG_NTSC (0<<1)
+#define S5P_MXR_CFG_PAL (1<<1)
+#define S5P_MXR_CFG_INTERLACE (0<<2)
+#define S5P_MXR_CFG_PROGRASSIVE (1<<2)
+#define S5P_MXR_CFG_VIDEO_DISABLE (0<<3)
+#define S5P_MXR_CFG_VIDEO_ENABLE (1<<4)
+#define S5P_MXR_CFG_GRAPHIC0_DISABLE (0<<4)
+#define S5P_MXR_CFG_GRAPHIC0_ENABLE (1<<4)
+#define S5P_MXR_CFG_GRAPHIC1_DISABLE (0<<5)
+#define S5P_MXR_CFG_GRAPHIC1_ENABLE (1<<5)
+#define S5P_MXR_CFG_HD_720P (0<<6)
+#define S5P_MXR_CFG_HD_1080I (1<<6)
+#define S5P_MXR_CFG_TV_OUT (0<<7)
+#define S5P_MXR_CFG_HDMI_OUT (1<<7)
+
+/* S5P_MXR_INT_EN */
+#define S5P_MXR_INT_EN_GRP0_DISABLE (0<<8)
+#define S5P_MXR_INT_EN_GRP0_ENABLE (1<<8)
+#define S5P_MXR_INT_EN_GRP1_DISABLE (0<<9)
+#define S5P_MXR_INT_EN_GRP1_ENABLE (1<<9)
+#define S5P_MXR_INT_EN_VP_DISABLE (0<<10)
+#define S5P_MXR_INT_EN_VP_ENABLE (1<<10)
+
+/* S5P_MXR_INT_STATUS */
+#define S5P_MXR_STATUS_EN_GRP0_N_FIRED (0<<8)
+#define S5P_MXR_STATUS_EN_GRP0_FIRED (1<<8)
+#define S5P_MXR_STATUS_EN_GRP1_N_FIRED (0<<9)
+#define S5P_MXR_STATUS_EN_GRP1_FIRED (1<<9)
+#define S5P_MXR_STATUS_EN_VP_N_FIRED (0<<10)
+#define S5P_MXR_STATUS_EN_VP_FIRED (1<<10)
+
+/* S5P_MXR_LAYER_CFG */
+#define S5P_MXR_LAYER_CFG_VP_HIDE (0<<0)
+#define S5P_MXR_LAYER_CFG_GRP0_HIDE (0<<4)
+#define S5P_MXR_LAYER_CFG_GRP1_HIDE (0<<8)
+
+/* S5P_MXR_VIDEO_CFG */
+#define S5P_MXR_VIDEO_CFG_BLEND_EN (1<<16)
+
+/* Macros */
+/* MIXER_STATUS */
+#define S5P_MXR_BURST16_MODE (1<<7)
+#define S5P_MXR_BURST8_MODE (0<<7)
+#define S5P_MXR_BIG_ENDIAN_SOURCE_FORMAT (1<<3)
+#define S5P_MXR_LITTLE_ENDIAN_SOURCE_FORMAT (0<<3)
+#define S5P_MXR_MIXER_RESERVED (1<<2)
+#define S5P_MXR_CMU_STOP_CLOCK (1<<1)
+#define S5P_MXR_CMU_CANNOT_STOP_CLOCK (0<<1)
+#define S5P_MXR_MIXER_START (1<<0)
+#define S5P_MXR_MIXER_STOP (0<<0)
+
+/* MIXER_CFG */
+#define S5P_MXR_DST_SEL_HDMI (1<<7)
+#define S5P_MXR_DST_SEL_ANALOG ~(1<<7)
+#define S5P_MXR_HD_1080I_MODE (1<<6)
+/* C110 */
+#define S5P_MXR_HD_1080P_MODE S5P_MXR_HD_1080I_MODE
+
+#define S5P_MXR_HD_720P_MODE (0<<6)
+#define S5P_MXR_GRAPHIC1_LAYER_SHOW (1<<5)
+#define S5P_MXR_GRAPHIC1_LAYER_HIDE (0<<5)
+#define S5P_MXR_GRAPHIC0_LAYER_SHOW (1<<4)
+#define S5P_MXR_GRAPHIC0_LAYER_HIDE (0<<4)
+#define S5P_MXR_VIDEO_LAYER_SHOW (1<<3)
+#define S5P_MXR_VIDEO_LAYER_HIDE (0<<3)
+#define S5P_MXR_PROGRESSVE_MODE (1<<2)
+#define S5P_MXR_INTERLACE_MODE ~(1<<2)
+#define S5P_MXR_PAL (1<<1)
+#define S5P_MXR_NTSC (0<<1)
+#define S5P_MXR_HD (1<<0)
+#define S5P_MXR_SD (0<<0)
+
+/* MIXER_INT_EN */
+#define S5P_MXR_VP_INT_ENABLE (1<<10)
+#define S5P_MXR_VP_INT_DISABLE (0<<10)
+#define S5P_MXR_GRP1_INT_ENABLE (1<<9)
+#define S5P_MXR_GRP1_INT_DISABLE (0<<9)
+#define S5P_MXR_GRP0_INT_ENABLE (1<<8)
+#define S5P_MXR_GRP0_INT_DISABLE (0<<8)
+
+/* MIXER_INT_STATUS */
+#define S5P_MXR_VP_INT_FIRED (1<<10)
+#define S5P_MXR_GRP1_INT_FIRED (1<<9)
+#define S5P_MXR_GRP0_INT_FIRED (1<<8)
+#define S5P_MXR_INT_FIRED (1<<0)
+
+#define S5P_MXR_ALPHA (0xff)
+
+/* MIXER_LAYER_CFG */
+#define S5P_MXR_GRP1_LAYER_PRIORITY(a) ((0xf&a)<<8)
+#define S5P_MXR_GRP0_LAYER_PRIORITY(a) ((0xf&a)<<4)
+#define S5P_MXR_VP_LAYER_PRIORITY(a) ((0xf&a)<<0)
+#define S5P_MXR_GRP1_LAYER_PRIORITY_CLEAR(a) ((~(0xf<<8))&a)
+#define S5P_MXR_GRP0_LAYER_PRIORITY_CLEAR(a) ((~(0xf<<4))&a)
+#define S5P_MXR_VP_LAYER_PRIORITY_CLEAR(a) ((~(0xf<<0))&a)
+#define S5P_MXR_GRP1_LAYER_PRIORITY_INFO(a) ((0xf<<8)&a)
+#define S5P_MXR_GRP0_LAYER_PRIORITY_INFO(a) ((0xf<<4)&a)
+#define S5P_MXR_VP_LAYER_PRIORITY_INFO(a) ((0xf<<0)&a)
+
+/* MIXER_VIDEO_CFG */
+#define S5P_MXR_VP_BLEND_ENABLE (1<<16)
+#define S5P_MXR_VP_BLEND_DISABLE (0<<16)
+#define S5P_MXR_VP_ALPHA_VALUE(a) ((0xff&a)<<0)
+#define S5P_MXR_VP_ALPHA_VALUE_CLEAR(a) ((~(0xff<<0))&a)
+
+/* MIXER_GRAPHx_CFG */
+#define S5P_MXR_BLANK_CHANGE_NEW_PIXEL (1<<21)
+#define S5P_MXR_BLANK_NOT_CHANGE_NEW_PIXEL (0<<21)
+#define S5P_MXR_PRE_MUL_MODE (1<<20)
+#define S5P_MXR_NORMAL_MODE (0<<20)
+#define S5P_MXR_WIN_BLEND_ENABLE (1<<17)
+#define S5P_MXR_WIN_BLEND_DISABLE (0<<17)
+#define S5P_MXR_PIXEL_BLEND_ENABLE (1<<16)
+#define S5P_MXR_PIXEL_BLEND_DISABLE (0<<16)
+#define S5P_MXR_EG_COLOR_FORMAT(a) ((0xf&a)<<8)
+#define S5P_MXR_EG_COLOR_FORMAT_CLEAR(a) ((~(0xf<<8))&a)
+#define S5P_MXR_GRP_ALPHA_VALUE(a) ((0xff&a)<<0)
+#define S5P_MXR_GRP_ALPHA_VALUE_CLEAR(a) ((~(0xff<<0))&a)
+/*
+enum s5p_tv_vmx_color_fmt
+{
+ S5P_MXR_DIRECT_RGB565 = 4,
+ S5P_MXR_DIRECT_RGB1555 = 5,
+ S5P_MXR_DIRECT_RGB4444 = 6,
+ S5P_MXR_DIRECT_RGB8888 = 7
+}
+*/
+
+/* MIXER_GRAPHx_BASE */
+#define S5P_MXR_GPR_BASE(a) (0xffffffff&a)
+#define S5P_MXR_GRP_ADDR_ILLEGAL(a) (0x3&a)
+
+/* MIXER_GRAPH1_SPAN */
+#define S5P_MXR_GRP_SPAN(a) (0x7fff&a)
+
+/* MIXER_GRAPH1_WH */
+#define S5P_MXR_GRP_WIDTH(a) ((0x7ff&a)<<16)
+#define S5P_MXR_GRP_HEIGHT(a) ((0x7ff&a)<<0)
+
+/* MIXER_GRAPH1_SXY */
+#define S5P_MXR_GRP_STARTX(a) ((0x7ff&a)<<16)
+#define S5P_MXR_GRP_STARTY(a) ((0x7ff&a)<<0)
+
+/* MIXER_GRAPH1_DXY */
+#define S5P_MXR_GRP_DESTX(a) ((0x7ff&a)<<16)
+#define S5P_MXR_GRP_DESTY(a) ((0x7ff&a)<<0)
+
+/* MIXER_GRAPH1_BLANK */
+#define S5P_MXR_GPR_BLANK_COLOR(a) (0xffffffff&a)
+
+/* MIXER_BG_CFG */
+#define S5P_MXR_BG_CR_DIHER_EN (1<<19)
+#define S5P_MXR_BG_CB_DIHER_EN (1<<18)
+#define S5P_MXR_BG_Y_DIHER_EN (1<<17)
+
+/* MIXER_BG_COLORx */
+#define S5P_MXR_BG_COLOR_Y(a) ((0xff&a)<<16)
+#define S5P_MXR_BG_COLOR_CB(a) ((0xff&a)<<8)
+#define S5P_MXR_BG_COLOR_CR(a) ((0xff&a)<<0)
+
+/* MIXER_CM_COEFF_x */
+#define S5P_MXR_BG_COLOR_WIDE (1<<30)
+#define S5P_MXR_BG_COLOR_NARROW (0<<30)
+#define S5P_MXR_BG_COEFF_0(a) ((0x3f&a)<<20)
+#define S5P_MXR_BG_COEFF_1(a) ((0x3f&a)<<10)
+#define S5P_MXR_BG_COEFF_2(a) ((0x3f&a)<<0)
+
diff --git a/drivers/media/video/samsung/tv20/s5pv210/regs/regs-vprocessor.h b/drivers/media/video/samsung/tv20/s5pv210/regs/regs-vprocessor.h
new file mode 100644
index 0000000..a450018
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/s5pv210/regs/regs-vprocessor.h
@@ -0,0 +1,447 @@
+/* linux/drivers/media/video/samsung/tv20/s5pc100/regs/regs-vprocessor.h
+ *
+ * Video Processor register header file for Samsung TVOut driver
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ * http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_REGS_VPROCESSOR_H
+
+#include <mach/map.h>
+
+#define S5P_VPROCESSOR_BASE(x) (x)
+/*
+ Registers
+*/
+#define S5P_VP_ENABLE S5P_VPROCESSOR_BASE(0x0000) // Power-Down Ready & Enable
+#define S5P_VP_SRESET S5P_VPROCESSOR_BASE(0x0004) // Software Reset
+#define S5P_VP_SHADOW_UPDATE S5P_VPROCESSOR_BASE(0x0008) // Shadow Register Update Enable
+#define S5P_VP_FIELD_ID S5P_VPROCESSOR_BASE(0x000C) // Field ID of the "Source" Image
+#define S5P_VP_MODE S5P_VPROCESSOR_BASE(0x0010) // VP Operation Mode
+#define S5P_VP_IMG_SIZE_Y S5P_VPROCESSOR_BASE(0x0014) // Luminance Date Size
+#define S5P_VP_IMG_SIZE_C S5P_VPROCESSOR_BASE(0x0018) // Chrominance Date Size
+#define S5P_VP_PER_RATE_CTRL S5P_VPROCESSOR_BASE(0x001C)
+#define S5P_VP_TOP_Y_PTR S5P_VPROCESSOR_BASE(0x0028) // Base Address for Y of Top Field (Frame)
+#define S5P_VP_BOT_Y_PTR S5P_VPROCESSOR_BASE(0x002C) // Base Address for Y of Bottom Field
+#define S5P_VP_TOP_C_PTR S5P_VPROCESSOR_BASE(0x0030) // Base Address for C of Top
+#define S5P_VP_BOT_C_PTR S5P_VPROCESSOR_BASE(0x0034) // Base Address for C of Bottom Field
+#define S5P_VP_ENDIAN_MODE S5P_VPROCESSOR_BASE(0x03CC) // Big/Little Endian Mode Selection
+#define S5P_VP_SRC_H_POSITION S5P_VPROCESSOR_BASE(0x0044) // Horizontal Offset in the Source Image
+#define S5P_VP_SRC_V_POSITION S5P_VPROCESSOR_BASE(0x0048) // Vertical Offset in the Source Image
+#define S5P_VP_SRC_WIDTH S5P_VPROCESSOR_BASE(0x004C) // Width of the Source Image
+#define S5P_VP_SRC_HEIGHT S5P_VPROCESSOR_BASE(0x0050) // Height of the Source Image
+#define S5P_VP_DST_H_POSITION S5P_VPROCESSOR_BASE(0x0054) // Horizontal Offset in the Display
+#define S5P_VP_DST_V_POSITION S5P_VPROCESSOR_BASE(0x0058) // Vertical Offset in the Display
+#define S5P_VP_DST_WIDTH S5P_VPROCESSOR_BASE(0x005C) // Width of the Display
+#define S5P_VP_DST_HEIGHT S5P_VPROCESSOR_BASE(0x0060) // Height of the Display
+#define S5P_VP_H_RATIO S5P_VPROCESSOR_BASE(0x0064) // Horizontal Zoom Ratio of SRC:DST
+#define S5P_VP_V_RATIO S5P_VPROCESSOR_BASE(0x0068) // Vertical Zoom Ratio of SRC:DST
+#define S5P_VP_POLY8_Y0_LL S5P_VPROCESSOR_BASE(0x006C) // 8-Tap Poly-phase Filter Coefficients for Luminance Horizontal Scaling
+#define S5P_VP_POLY8_Y0_LH S5P_VPROCESSOR_BASE(0x0070) // 8-Tap Poly-phase Filter Coefficients for Luminance Horizontal Scaling
+#define S5P_VP_POLY8_Y0_HL S5P_VPROCESSOR_BASE(0x0074) // 8-Tap Poly-phase Filter Coefficients for Luminance Horizontal Scaling
+#define S5P_VP_POLY8_Y0_HH S5P_VPROCESSOR_BASE(0x0078) // 8-Tap Poly-phase Filter Coefficients for Luminance Horizontal Scaling
+#define S5P_VP_POLY8_Y1_LL S5P_VPROCESSOR_BASE(0x007C) // 8-Tap Poly-phase Filter Coefficients for Luminance Horizontal Scaling
+#define S5P_VP_POLY8_Y1_LH S5P_VPROCESSOR_BASE(0x0080) // 8-Tap Poly-phase Filter Coefficients for Luminance Horizontal Scaling
+#define S5P_VP_POLY8_Y1_HL S5P_VPROCESSOR_BASE(0x0084) // 8-Tap Poly-phase Filter Coefficients for Luminance Horizontal Scaling
+#define S5P_VP_POLY8_Y1_HH S5P_VPROCESSOR_BASE(0x0088) // 8-Tap Poly-phase Filter Coefficients for Luminance Horizontal Scaling
+#define S5P_VP_POLY8_Y2_LL S5P_VPROCESSOR_BASE(0x008C) // 8-Tap Poly-phase Filter Coefficients for Luminance Horizontal Scaling
+#define S5P_VP_POLY8_Y2_LH S5P_VPROCESSOR_BASE(0x0090) // 8-Tap Poly-phase Filter Coefficients for Luminance Horizontal Scaling
+#define S5P_VP_POLY8_Y2_HL S5P_VPROCESSOR_BASE(0x0094) // 8-Tap Poly-phase Filter Coefficients for Luminance Horizontal Scaling
+#define S5P_VP_POLY8_Y2_HH S5P_VPROCESSOR_BASE(0x0098) // 8-Tap Poly-phase Filter Coefficients for Luminance Horizontal Scaling
+#define S5P_VP_POLY8_Y3_LL S5P_VPROCESSOR_BASE(0x009C) // 8-Tap Poly-phase Filter Coefficients for Luminance Horizontal Scaling
+#define S5P_VP_POLY8_Y3_LH S5P_VPROCESSOR_BASE(0x00A0) // 8-Tap Poly-phase Filter Coefficients for Luminance Horizontal Scaling
+#define S5P_VP_POLY8_Y3_HL S5P_VPROCESSOR_BASE(0x00A4) // 8-Tap Poly-phase Filter Coefficients for Luminance Horizontal Scaling
+#define S5P_VP_POLY8_Y3_HH S5P_VPROCESSOR_BASE(0x00A8) // 8-Tap Poly-phase Filter Coefficients for Luminance Horizontal Scaling
+#define S5P_VP_POLY4_Y0_LL S5P_VPROCESSOR_BASE(0x00EC) // 4-Tap Poly-phase Filter Coefficients for Luminance Horizontal Scaling
+#define S5P_VP_POLY4_Y0_LH S5P_VPROCESSOR_BASE(0x00F0) // 4-Tap Poly-phase Filter Coefficients for Luminance Vertical Scaling
+#define S5P_VP_POLY4_Y0_HL S5P_VPROCESSOR_BASE(0x00F4) // 4-Tap Poly-phase Filter Coefficients for Luminance Vertical Scaling
+#define S5P_VP_POLY4_Y0_HH S5P_VPROCESSOR_BASE(0x00F8) // 4-Tap Poly-phase Filter Coefficients for Luminance Vertical Scaling
+#define S5P_VP_POLY4_Y1_LL S5P_VPROCESSOR_BASE(0x00FC) // 4-Tap Poly-phase Filter Coefficients for Luminance Vertical Scaling
+#define S5P_VP_POLY4_Y1_LH S5P_VPROCESSOR_BASE(0x0100) // 4-Tap Poly-phase Filter Coefficients for Luminance Vertical Scaling
+#define S5P_VP_POLY4_Y1_HL S5P_VPROCESSOR_BASE(0x0104) // 4-Tap Poly-phase Filter Coefficients for Luminance Vertical Scaling
+#define S5P_VP_POLY4_Y1_HH S5P_VPROCESSOR_BASE(0x0108) // 4-Tap Poly-phase Filter Coefficients for Luminance Vertical Scaling
+#define S5P_VP_POLY4_Y2_LL S5P_VPROCESSOR_BASE(0x010C) // 4-Tap Poly-phase Filter Coefficients for Luminance Vertical Scaling
+#define S5P_VP_POLY4_Y2_LH S5P_VPROCESSOR_BASE(0x0110) // 4-Tap Poly-phase Filter Coefficients for Luminance Vertical Scaling
+#define S5P_VP_POLY4_Y2_HL S5P_VPROCESSOR_BASE(0x0114) // 4-Tap Poly-phase Filter Coefficients for Luminance Vertical Scaling
+#define S5P_VP_POLY4_Y2_HH S5P_VPROCESSOR_BASE(0x0118) // 4-Tap Poly-phase Filter Coefficients for Luminance Vertical Scaling
+#define S5P_VP_POLY4_Y3_LL S5P_VPROCESSOR_BASE(0x011C) // 4-Tap Poly-phase Filter Coefficients for Luminance Vertical Scaling
+#define S5P_VP_POLY4_Y3_LH S5P_VPROCESSOR_BASE(0x0120) // 4-Tap Poly-phase Filter Coefficients for Luminance Vertical Scaling
+#define S5P_VP_POLY4_Y3_HL S5P_VPROCESSOR_BASE(0x0124) // 4-Tap Poly-phase Filter Coefficients for Luminance Vertical Scaling
+#define S5P_VP_POLY4_Y3_HH S5P_VPROCESSOR_BASE(0x0128) // 4-Tap Poly-phase Filter Coefficients for Luminance Vertical Scaling
+#define S5P_VP_POLY4_C0_LL S5P_VPROCESSOR_BASE(0x012C) // 4-Tap Poly-phase Filter Coefficients for Luminance Vertical Scaling
+#define S5P_VP_POLY4_C0_LH S5P_VPROCESSOR_BASE(0x0130) // 4-Tap Poly-phase Filter Coefficients for Chrominance Horizontal Scaling
+#define S5P_VP_POLY4_C0_HL S5P_VPROCESSOR_BASE(0x0134) // 4-Tap Poly-phase Filter Coefficients for Chrominance Horizontal Scaling
+#define S5P_VP_POLY4_C0_HH S5P_VPROCESSOR_BASE(0x0138) // 4-Tap Poly-phase Filter Coefficients for Chrominance Horizontal Scaling
+#define S5P_VP_POLY4_C1_LL S5P_VPROCESSOR_BASE(0x013C) // 4-Tap Poly-phase Filter Coefficients for Chrominance Horizontal Scaling
+#define S5P_VP_POLY4_C1_LH S5P_VPROCESSOR_BASE(0x0140) // 4-Tap Poly-phase Filter Coefficients for Chrominance Horizontal Scaling
+#define S5P_VP_POLY4_C1_HL S5P_VPROCESSOR_BASE(0x0144) // 4-Tap Poly-phase Filter Coefficients for Chrominance Horizontal Scaling
+#define S5P_VP_POLY4_C1_HH S5P_VPROCESSOR_BASE(0x0148) // 4-Tap Poly-phase Filter Coefficients for Chrominance Horizontal Scaling
+#define S5P_PP_CSC_Y2Y_COEF S5P_VPROCESSOR_BASE(0x01D4) // Y to Y CSC Coefficient Setting
+#define S5P_PP_CSC_CB2Y_COEF S5P_VPROCESSOR_BASE(0x01D8) // CB to Y CSC Coefficient Setting
+#define S5P_PP_CSC_CR2Y_COEF S5P_VPROCESSOR_BASE(0x01DC) // CR to Y CSC Coefficient Setting
+#define S5P_PP_CSC_Y2CB_COEF S5P_VPROCESSOR_BASE(0x01E0) // Y to Y CSC Coefficient Setting
+#define S5P_PP_CSC_CB2CB_COEF S5P_VPROCESSOR_BASE(0x01E4) // CB to Y CSC Coefficient Setting
+#define S5P_PP_CSC_CR2CB_COEF S5P_VPROCESSOR_BASE(0x01E8) // CR to Y CSC Coefficient Setting
+#define S5P_PP_CSC_Y2CR_COEF S5P_VPROCESSOR_BASE(0x01EC) // Y to Y CSC Coefficient Setting
+#define S5P_PP_CSC_CB2CR_COEF S5P_VPROCESSOR_BASE(0x01F0) // CB to Y CSC Coefficient Setting
+#define S5P_PP_CSC_CR2CR_COEF S5P_VPROCESSOR_BASE(0x01F4) // CR to Y CSC Coefficient Setting
+#define S5P_PP_BYPASS S5P_VPROCESSOR_BASE(0x0200) // Disable the Post Image Processor
+#define S5P_PP_SATURATION S5P_VPROCESSOR_BASE(0x020C) // Color Saturation Factor
+#define S5P_PP_SHARPNESS S5P_VPROCESSOR_BASE(0x0210) // Control for the Edge Enhancement
+#define S5P_PP_LINE_EQ0 S5P_VPROCESSOR_BASE(0x0218) // Line Equation for Contrast Duration "0"
+#define S5P_PP_LINE_EQ1 S5P_VPROCESSOR_BASE(0x021C) // Line Equation for Contrast Duration "1"
+#define S5P_PP_LINE_EQ2 S5P_VPROCESSOR_BASE(0x0220) // Line Equation for Contrast Duration "2"
+#define S5P_PP_LINE_EQ3 S5P_VPROCESSOR_BASE(0x0224) // Line Equation for Contrast Duration "3"
+#define S5P_PP_LINE_EQ4 S5P_VPROCESSOR_BASE(0x0228) // Line Equation for Contrast Duration "4"
+#define S5P_PP_LINE_EQ5 S5P_VPROCESSOR_BASE(0x022C) // Line Equation for Contrast Duration "5"
+#define S5P_PP_LINE_EQ6 S5P_VPROCESSOR_BASE(0x0230) // Line Equation for Contrast Duration "6"
+#define S5P_PP_LINE_EQ7 S5P_VPROCESSOR_BASE(0x0234) // Line Equation for Contrast Duration "7"
+#define S5P_PP_BRIGHT_OFFSET S5P_VPROCESSOR_BASE(0x0238) // Brightness Offset Control for Y
+#define S5P_PP_CSC_EN S5P_VPROCESSOR_BASE(0x023C) // Color Space Conversion Control
+#define S5P_VP_VERSION_INFO S5P_VPROCESSOR_BASE(0x03FC) // VP Version Information
+
+/*
+ Shadow Registers
+*/
+#define S5P_VP_FIELD_ID_S S5P_VPROCESSOR_BASE(0x016C) // Field ID of the "Source" Image
+#define S5P_VP_MODE_S S5P_VPROCESSOR_BASE(0x0170) // VP Operation Mode
+#define S5P_VP_IMG_SIZE_Y_S S5P_VPROCESSOR_BASE(0x0174) // Luminance Date Tiled Size
+#define S5P_VP_IMG_SIZE_C_S S5P_VPROCESSOR_BASE(0x0178) // Chrominance Date Tiled Size
+#define S5P_VP_TOP_Y_PTR_S S5P_VPROCESSOR_BASE(0x0190) // Base Address for Y of Top Field
+#define S5P_VP_BOT_Y_PTR_S S5P_VPROCESSOR_BASE(0x0194) // Base Address for Y of Bottom Field
+#define S5P_VP_TOP_C_PTR_S S5P_VPROCESSOR_BASE(0x0198) // Base Address for C of Top Frame
+#define S5P_VP_BOT_C_PTR_S S5P_VPROCESSOR_BASE(0x019C) // Base Address for C of Bottom field
+#define S5P_VP_ENDIAN_MODE_S S5P_VPROCESSOR_BASE(0x03EC) // Big/ Little Endian Mode Selection
+#define S5P_VP_SRC_H_POSITION_S S5P_VPROCESSOR_BASE(0x01AC) // Horizontal Offset in the Source Image
+#define S5P_VP_SRC_V_POSITION_S S5P_VPROCESSOR_BASE(0x01B0) // Vertical Offset in the Source Image
+#define S5P_VP_SRC_WIDTH_S S5P_VPROCESSOR_BASE(0x01B4) // Width of the Source Image
+#define S5P_VP_SRC_HEIGHT_S S5P_VPROCESSOR_BASE(0x01B8) // Height of the Source Image
+#define S5P_VP_DST_H_POSITION_S S5P_VPROCESSOR_BASE(0x01BC) // Horizontal Offset in the Display
+#define S5P_VP_DST_V_POSITION_S S5P_VPROCESSOR_BASE(0x01C0) // Vertical Offset in the Display
+#define S5P_VP_DST_WIDTH_S S5P_VPROCESSOR_BASE(0x01C4) // Width of the Display
+#define S5P_VP_DST_HEIGHT_S S5P_VPROCESSOR_BASE(0x01C8) // Height of the Display
+#define S5P_VP_H_RATIO_S S5P_VPROCESSOR_BASE(0x01CC) // Horizontal Zoom Ratio of SRC:DST
+#define S5P_VP_V_RATIO_S S5P_VPROCESSOR_BASE(0x01D0) // Vertical Zoom Ratio of SRC:DST
+#define S5P_PP_BYPASS_S S5P_VPROCESSOR_BASE(0x0258) // Disable the Post Image Processor
+#define S5P_PP_SATURATION_S S5P_VPROCESSOR_BASE(0x025C) // Color Saturation Factor
+#define S5P_PP_SHARPNESS_S S5P_VPROCESSOR_BASE(0x0260) // Control for the Edge Enhancement
+#define S5P_PP_LINE_EQ0_S S5P_VPROCESSOR_BASE(0x0268) // Line Equation for Contrast Duration "0"
+#define S5P_PP_LINE_EQ1_S S5P_VPROCESSOR_BASE(0x026C) // Line Equation for Contrast Duration "1"
+#define S5P_PP_LINE_EQ2_S S5P_VPROCESSOR_BASE(0x0270) // Line Equation for Contrast Duration "2"
+#define S5P_PP_LINE_EQ3_S S5P_VPROCESSOR_BASE(0x0274) // Line Equation for Contrast Duration "3"
+#define S5P_PP_LINE_EQ4_S S5P_VPROCESSOR_BASE(0x0278) // Line Equation for Contrast Duration "4"
+#define S5P_PP_LINE_EQ5_S S5P_VPROCESSOR_BASE(0x027C) // Line Equation for Contrast Duration "5"
+#define S5P_PP_LINE_EQ6_S S5P_VPROCESSOR_BASE(0x0280) // Line Equation for Contrast Duration "6"
+#define S5P_PP_LINE_EQ7_S S5P_VPROCESSOR_BASE(0x0284) // Line Equation for Contrast Duration "7"
+#define S5P_PP_BRIGHT_OFFSET_S S5P_VPROCESSOR_BASE(0x0288) // Brightness Offset Control for Y
+#define S5P_PP_CSC_EN_S S5P_VPROCESSOR_BASE(0x028C) // Color Space Conversion Control
+#define S5P_PP_CSC_Y2Y_COEF_S S5P_VPROCESSOR_BASE(0x0290) // Y to Y CSC Coefficient Setting
+#define S5P_PP_CSC_CB2Y_COEF_S S5P_VPROCESSOR_BASE(0x0294) // CB to Y CSC Coefficient Setting
+#define S5P_PP_CSC_CR2Y_COEF_S S5P_VPROCESSOR_BASE(0x0298) // CR to Y CSC Coefficient Setting
+#define S5P_PP_CSC_Y2CB_COEF_S S5P_VPROCESSOR_BASE(0x029C) // Y to Y CSC Coefficient Setting
+#define S5P_PP_CSC_CB2CB_COEF_S S5P_VPROCESSOR_BASE(0x02A0) // CB to Y CSC Coefficient Setting
+#define S5P_PP_CSC_CR2CB_COEF_S S5P_VPROCESSOR_BASE(0x02A4) // CR to Y CSC Coefficient Setting
+#define S5P_PP_CSC_Y2CR_COEF_S S5P_VPROCESSOR_BASE(0x02A8) // Y to Y CSC Coefficient Setting
+#define S5P_PP_CSC_CB2CR_COEF_S S5P_VPROCESSOR_BASE(0x02AC) // CB to Y CSC Coefficient Setting
+#define S5P_PP_CSC_CR2CR_COEF_S S5P_VPROCESSOR_BASE(0x02B0) // CR to Y CSC Coefficient Setting
+
+/*
+ Registers Bit Description
+*/
+/* S5P_VP_ENABLE */
+#define S5P_VP_ENABLE_ON (1<<0)
+#define S5P_VP_ENABLE_ON_S (1<<2) /* R_ONLY, Shadow bit of the bit [0]*/
+
+/* S5P_VP_SRESET */
+#define S5P_VP_SRESET_LAST_COMPLETE (0<<0)
+#define S5P_VP_SRESET_PROCESSING (1<<0)
+
+/* S5P_VP_SHADOW_UPDATE */
+#define S5P_VP_SHADOW_UPDATE_DISABLE (0<<0)
+#define S5P_VP_SHADOW_UPDATE_ENABLE (1<<0)
+
+/* S5P_VP_FIELD_ID */
+#define S5P_VP_FIELD_ID_TOP (0<<0)
+#define S5P_VP_FIELD_ID_BOTTOM (1<<0)
+
+/* S5P_VP_MODE */
+#define S5P_VP_MODE_2D_IPC_ENABLE (1<<1)
+#define S5P_VP_MODE_2D_IPC_DISABLE (0<<1)
+#define S5P_VP_MODE_FIELD_ID_MAN_TOGGLING (0<<2)
+#define S5P_VP_MODE_FIELD_ID_AUTO_TOGGLING (1<<2)
+#define S5P_VP_MODE_CROMA_EXPANSION_C_TOP_PTR (0<<3)
+#define S5P_VP_MODE_CROMA_EXPANSION_C_TOPBOTTOM_PTR (1<<3)
+#define S5P_VP_MODE_MEM_MODE_LINEAR (0<<4)
+#define S5P_VP_MODE_MEM_MODE_2D_TILE (1<<4)
+#define S5P_VP_MODE_LINE_SKIP_OFF (0<<5)
+#define S5P_VP_MODE_LINE_SKIP_ON (1<<5)
+
+/* S5P_VP_ENDIAN_MODE */
+#define S5P_VP_ENDIAN_MODE_BIG (0<<0)
+#define S5P_VP_ENDIAN_MODE_LITTLE (1<<0)
+
+/* Macros */
+/* S5P_VP_ENABLE */
+#define VP_ON_SW_RESET (1<<2)
+#define VP_POWER_DOWN_RDY (1<<1)
+#define VP_ON_ENABLE (1<<0)
+#define VP_ON_DISABLE (0<<0)
+
+/* S5P_VP_SRESET */
+#define VP_SOFT_RESET (1<<0)
+
+/* S5P_VP_SHADOW_UPDATA */
+#define VP_SHADOW_UPDATE_ENABLE (1<<0)
+#define VP_SHADOW_UPDATE_DISABLE (0<<0)
+
+/* S5P_VP_FIELD_ID */
+#define VP_FIELD_ID_BOTTOM (1<<0)
+#define VP_FIELD_ID_TOP (0<<0)
+
+/* S5P_VP_MODE */
+#define VP_LINE_SKIP_ON (1<<5)
+#define VP_LINE_SKIP_OFF (0<<5)
+#define VP_MEM_2D_MODE (1<<4)
+#define VP_MEM_LINEAR_MODE (0<<4)
+#define VP_CHROMA_USE_TOP_BOTTOM (1<<3)
+#define VP_CHROMA_USE_TOP (0<<3)
+#define VP_FIELD_ID_TOGGLE_VSYNC (1<<2)
+#define VP_FIELD_ID_TOGGLE_USER (0<<2)
+#define VP_2D_IPC_ON (1<<1)
+#define VP_2D_IPC_OFF (0<<1)
+
+/* S5P_VP_TILE_SIZE_x */
+#define VP_IMG_HSIZE(a) ((0x3fff&a)<<16)
+#define VP_IMG_VSIZE(a) ((0x3fff&a)<<0)
+#define VP_IMG_SIZE_ILLEGAL(a) (0x7&a)
+
+/* S5P_VP_PER_RATE_CTRL */
+#define VP_PEL_RATE_CTRL(a) ((0x3&a)<<0)
+/*
+enum VP_PIXEL_RATE
+{
+ VP_PIXEL_PER_RATE_1_1 = 0,
+ VP_PIXEL_PER_RATE_1_2 = 1,
+ VP_PIXEL_PER_RATE_1_3 = 2,
+ VP_PIXEL_PER_RATE_1_4 = 3
+}
+*/
+
+/* S5P_VP_TOP_x_PTR , VP_BOT_x_PTR */
+#define VP_PTR_ILLEGAL(a) (0x7&a)
+
+/* S5P_ VP_ENDIAN_MODE */
+#define VP_LITTLE_ENDIAN_MODE (1<<0)
+#define VP_BIG_ENDIAN_MODE (0<<0)
+
+/* S5P_VP_SRC_H_POSITION */
+#define VP_SRC_H_POSITION(a) ((0x7ff&a)<<4)
+#define VP_SRC_X_FRACT_STEP(a) (0xf&a)
+
+/* S5P_VP_SRC_V_POSITION */
+#define VP_SRC_V_POSITION(a) (0x7ff&a)
+
+/* S5P_VP_SRC_WIDTH */
+#define VP_SRC_WIDTH(a) (0x7ff&a)
+
+/* S5P_VP_SRC_WIDTH */
+#define VP_SRC_HEIGHT(a) (0x7ff&a)
+
+/* S5P_VP_DST_H_POSITION */
+#define VP_DST_H_POSITION(a) (0x7ff&a)
+
+/* S5P_VP_DST_V_POSITION */
+#define VP_DST_V_POSITION(a) (0x7ff&a)
+
+/* S5P_VP_DST_WIDTH */
+#define VP_DST_WIDTH(a) (0x7ff&a)
+
+/* S5P_VP_DST_WIDTH
+#define VP_DST_HEIGHT(a) (0x3ff&a)
+C110:*/
+#define VP_DST_HEIGHT(a) (0x7ff&a)
+
+/* S5P_VP_H_RATIO */
+#define VP_H_RATIO(a) (0x7ffff&a)
+
+/* S5P_VP_V_RATIO */
+#define VP_V_RATIO(a) (0x7ffff&a)
+
+/* S5P_VP_POLY8_Y0_xx */
+#define VP_POLY8_Y0_x0(a) ((0x7&a)<<24)
+#define VP_POLY8_Y0_x1(a) ((0x7&a)<<16)
+#define VP_POLY8_Y0_x2(a) ((0x7&a)<<8)
+#define VP_POLY8_Y0_x3(a) ((0x7&a)<<0)
+
+/* S5P_VP_POLY8_Y1_xx */
+#define VP_POLY8_Y1_x0(a) ((0x1f&a)<<24)
+#define VP_POLY8_Y1_x1(a) ((0x1f&a)<<16)
+#define VP_POLY8_Y1_x2(a) ((0x1f&a)<<8)
+#define VP_POLY8_Y1_x3(a) ((0x1f&a)<<0)
+
+/* VP_POLY8_Y2_xx */
+#define VP_POLY8_Y2_x0(a) ((0x7f&a)<<24)
+#define VP_POLY8_Y2_x1(a) ((0x7f&a)<<16)
+#define VP_POLY8_Y2_x2(a) ((0x7f&a)<<8)
+#define VP_POLY8_Y2_x3(a) ((0x7f&a)<<0)
+
+/* VP_POLY8_Y3_xx */
+#define VP_POLY8_Y3_x0(a) ((0x7f&a)<<24)
+#define VP_POLY8_Y3_x1(a) ((0x7f&a)<<16)
+#define VP_POLY8_Y3_x2(a) ((0x7f&a)<<8)
+#define VP_POLY8_Y3_x3(a) ((0x7f&a)<<0)
+
+/* VP_POLY4_Y0_xx */
+#define VP_POLY4_Y0_x0(a) ((0x3f&a)<<24)
+#define VP_POLY4_Y0_x1(a) ((0x3f&a)<<16)
+#define VP_POLY4_Y0_x2(a) ((0x3f&a)<<8)
+#define VP_POLY4_Y0_x3(a) ((0x3f&a)<<0)
+
+/* VP_POLY4_Y1_xx */
+#define VP_POLY4_Y1_x0(a) ((0x7f&a)<<24)
+#define VP_POLY4_Y1_x1(a) ((0x7f&a)<<16)
+#define VP_POLY4_Y1_x2(a) ((0x7f&a)<<8)
+#define VP_POLY4_Y1_x3(a) ((0x7f&a)<<0)
+
+/* VP_POLY4_Y2_xx */
+#define VP_POLY4_Y2_x0(a) ((0x7f&a)<<24)
+#define VP_POLY4_Y2_x1(a) ((0x7f&a)<<16)
+#define VP_POLY4_Y2_x2(a) ((0x7f&a)<<8)
+#define VP_POLY4_Y2_x3(a) ((0x7f&a)<<0)
+
+/* VP_POLY4_Y3_xx */
+#define VP_POLY4_Y3_x0(a) ((0x3f&a)<<24)
+#define VP_POLY4_Y3_x1(a) ((0x3f&a)<<16)
+#define VP_POLY4_Y3_x2(a) ((0x3f&a)<<8)
+#define VP_POLY4_Y3_x3(a) ((0x3f&a)<<0)
+
+/* VP_POLY4_C0_LL */
+#define VP_POLY4_C0_PH0(a) ((0x7f&a)<<24)
+#define VP_POLY4_C0_PH1(a) ((0x7f&a)<<16)
+#define VP_POLY4_C0_PH2(a) ((0x7f&a)<<8)
+#define VP_POLY4_C0_PH3(a) ((0x7f&a)<<0)
+
+/* VP_POLY4_C0_LH */
+#define VP_POLY4_C0_PH4(a) ((0x3f&a)<<24)
+#define VP_POLY4_C0_PH5(a) ((0x3f&a)<<16)
+#define VP_POLY4_C0_PH6(a) ((0x3f&a)<<8)
+#define VP_POLY4_C0_PH7(a) ((0x3f&a)<<0)
+
+/* VP_POLY4_C0_HL */
+#define VP_POLY4_C0_PH8(a) ((0x3f&a)<<24)
+#define VP_POLY4_C0_PH9(a) ((0x3f&a)<<16)
+#define VP_POLY4_C0_PH10(a) ((0x3f&a)<<8)
+#define VP_POLY4_C0_PH11(a) ((0x3f&a)<<0)
+
+/* VP_POLY4_C0_HH */
+#define VP_POLY4_C0_PH12(a) ((0x1f&a)<<24)
+#define VP_POLY4_C0_PH13(a) ((0x1f&a)<<16)
+#define VP_POLY4_C0_PH14(a) ((0x1f&a)<<8)
+#define VP_POLY4_C0_PH15(a) ((0x1f&a)<<0)
+
+/* VP_POLY4_C1_LL */
+#define VP_POLY4_C1_PH0(a) ((0xff&a)<<24)
+#define VP_POLY4_C1_PH1(a) ((0xff&a)<<16)
+#define VP_POLY4_C1_PH2(a) ((0xff&a)<<8)
+#define VP_POLY4_C1_PH3(a) ((0xff&a)<<0)
+
+/* VP_POLY4_C1_LH */
+#define VP_POLY4_C1_PH4(a) ((0xff&a)<<24)
+#define VP_POLY4_C1_PH5(a) ((0xff&a)<<16)
+#define VP_POLY4_C1_PH6(a) ((0xff&a)<<8)
+#define VP_POLY4_C1_PH7(a) ((0xff&a)<<0)
+
+/* VP_POLY4_C1_HL */
+#define VP_POLY4_C1_PH8(a) ((0xff&a)<<24)
+#define VP_POLY4_C1_PH9(a) ((0xff&a)<<16)
+#define VP_POLY4_C1_PH10(a) ((0xff&a)<<8)
+#define VP_POLY4_C1_PH11(a) ((0xff&a)<<0)
+
+/* VP_POLY4_C1_HH */
+#define VP_POLY4_C1_PH12(a) ((0x7f&a)<<24)
+#define VP_POLY4_C1_PH13(a) ((0x7f&a)<<16)
+#define VP_POLY4_C1_PH14(a) ((0x7f&a)<<8)
+#define VP_POLY4_C1_PH15(a) ((0x7f&a)<<0)
+
+/* PP_CSC_COEF */
+#define VP_CSC_COEF(a) (0xfff&a)
+
+/* PP_BYPASS */
+#define VP_BY_PASS_ENABLE (0)
+#define VP_BY_PASS_DISABLE (1)
+
+/* PP_SATURATION */
+#define VP_SATURATION(a) (0xff&a)
+
+/* PP_SHARPNESS */
+#define VP_TH_HNOISE(a) ((0xf&a)<<8)
+#define VP_SHARPNESS(a) (0x3&a)
+/*
+enum VP_SHARPNESS_CONTROL
+{
+ VP_SHARPNESS_NO = 0,
+ VP_SHARPNESS_MIN = 1,
+ VP_SHARPNESS_MOD = 2,
+ VP_SHARPNESS_MAX = 3
+}
+*/
+
+/* PP_LINE_EQx */
+#define VP_LINE_INTC(a) ((0xffff&a)<<8)
+#define VP_LINE_SLOPE(a) (0xff&a)
+#define VP_LINE_INTC_CLEAR(a) (~(0xffff<<8)&a)
+#define VP_LINE_SLOPE_CLEAR(a) (~0xff&a)
+
+/* PP_BRIGHT_OFFSET */
+#define VP_BRIGHT_OFFSET(a) (0x1ff&a)
+
+/* PP_CSC_EN */
+#define VP_SUB_Y_OFFSET_ENABLE (1<<1)
+#define VP_SUB_Y_OFFSET_DISABLE (0<<1)
+#define VP_CSC_ENABLE (1)
+#define VP_CSC_DISABLE (0)
+
+/* global variables */
+static unsigned int g_vp_contrast_brightness = 0;
+
+/*#define VP_UPDATE_RETRY_MAXIMUM 30
+#define VP_WAIT_UPDATE_SLEEP 3 */
+
+/* Ref. to VP manual p37-39
+ [11] : sign bit, [10] : integer bit, [9:0] : fraction bit
+ CSC from BT.601(SD) to BT.709(HD) */
+#define Y2Y_COEF_601_TO_709 0x400 // 1.0
+#define CB2Y_COEF_601_TO_709 0x879 // about -0.118188 ex) 0.118188*1024 = 121.024512 --> about 121 convert to hex(0x79)
+#define CR2Y_COEF_601_TO_709 0x8d9 // about -0.212685
+
+#define Y2CB_COEF_601_TO_709 0x0 // 0
+#define CB2CB_COEF_601_TO_709 0x413 // about 1.018640
+#define CR2CB_COEF_601_TO_709 0x875 // about -0.114618
+
+#define Y2CR_COEF_601_TO_709 0x0
+#define CB2CR_COEF_601_TO_709 0x04d // about 0.075049
+#define CR2CR_COEF_601_TO_709 0x41a // about 1.025327
+
+/* CSC from BT.709(HD) to BT.601(SD) */
+#define Y2Y_COEF_709_TO_601 0x400
+#define CB2Y_COEF_709_TO_601 0x068 // about 0.101579
+#define CR2Y_COEF_709_TO_601 0x0c9 // about 0.196076
+
+#define Y2CB_COEF_709_TO_601 0x0
+#define CB2CB_COEF_709_TO_601 0x3f6 // about 0.989854
+#define CR2CB_COEF_709_TO_601 0x871 // about -0.110653
+
+#define Y2CR_COEF_709_TO_601 0x0
+#define CB2CR_COEF_709_TO_601 0x84a // about -0.072453
+#define CR2CR_COEF_709_TO_601 0xbef // about -0.983398
+
+#define TILE_WIDTH 0x40
+#define MAX_NUM_OF_FRM 34 // according to MFC
+
+#endif /* __ASM_ARCH_REGS_VPROCESSOR_H */
+
diff --git a/drivers/media/video/samsung/tv20/s5pv210/sdout_s5pv210.c b/drivers/media/video/samsung/tv20/s5pv210/sdout_s5pv210.c
new file mode 100644
index 0000000..4a4ea66
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/s5pv210/sdout_s5pv210.c
@@ -0,0 +1,2038 @@
+/* linux/drivers/media/video/samsung/tv20/s5pv210/sdout_s5pv210.c
+ *
+ * tv encoder raw ftn file for Samsung TVOut driver
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <linux/memory.h>
+#include <linux/mm.h>
+
+#include <plat/clock.h>
+#include "tv_out_s5pv210.h"
+
+#include "regs/regs-sdaout.h"
+
+#ifdef COFIG_TVOUT_RAW_DBG
+#define S5P_SDAOUT_DEBUG 1
+#endif
+
+#ifdef S5P_SDAOUT_DEBUG
+#define SDPRINTK(fmt, args...) \
+ printk(KERN_INFO "\t\t[SDOUT] %s: " fmt, __func__ , ## args)
+#else
+#define SDPRINTK(fmt, args...)
+#endif
+
+static struct resource *sdout_mem;
+void __iomem *sdout_base;
+
+/*
+* initialization - iniization functions are only called under stopping SDOUT
+*/
+enum s5p_tv_sd_err __s5p_sdout_init_video_scale_cfg(
+ enum s5p_sd_level component_level,
+ enum s5p_sd_vsync_ratio component_ratio,
+ enum s5p_sd_level composite_level,
+ enum s5p_sd_vsync_ratio composite_ratio)
+{
+ u32 temp_reg = 0;
+
+ SDPRINTK("%d, %d, %d, %d\n\r", component_level, component_ratio,
+ composite_level, composite_ratio);
+
+ switch (component_level) {
+
+ case S5P_TV_SD_LEVEL_0IRE:
+ temp_reg = SDO_COMPONENT_LEVEL_SEL_0IRE;
+ break;
+
+ case S5P_TV_SD_LEVEL_75IRE:
+ temp_reg = SDO_COMPONENT_LEVEL_SEL_75IRE;
+ break;
+
+ default:
+ SDPRINTK("invalid component_level parameter(%d)\n\r",
+ component_level);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ switch (composite_level) {
+
+ case SDOUT_VTOS_RATIO_10_4:
+ temp_reg |= SDO_COMPONENT_VTOS_RATIO_10_4;
+ break;
+
+ case SDOUT_VTOS_RATIO_7_3:
+ temp_reg |= SDO_COMPONENT_VTOS_RATIO_7_3;
+ break;
+
+ default:
+ SDPRINTK(" invalid composite_level parameter(%d)\n\r",
+ composite_level);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ switch (composite_level) {
+
+ case S5P_TV_SD_LEVEL_0IRE:
+ temp_reg |= SDO_COMPOSITE_LEVEL_SEL_0IRE;
+ break;
+
+ case S5P_TV_SD_LEVEL_75IRE:
+ temp_reg |= SDO_COMPOSITE_LEVEL_SEL_75IRE;
+ break;
+
+ default:
+ SDPRINTK("invalid composite_ratio parameter(%d)\n\r",
+ composite_ratio);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ switch (composite_ratio) {
+
+ case SDOUT_VTOS_RATIO_10_4:
+ temp_reg |= SDO_COMPOSITE_VTOS_RATIO_10_4;
+ break;
+
+ case SDOUT_VTOS_RATIO_7_3:
+ temp_reg |= SDO_COMPOSITE_VTOS_RATIO_7_3;
+ break;
+
+ default:
+ SDPRINTK("invalid component_ratio parameter(%d)\n\r",
+ component_ratio);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ writel(temp_reg, sdout_base + S5P_SDO_SCALE);
+
+ SDPRINTK("0x%08x)\n\r", readl(sdout_base + S5P_SDO_SCALE));
+
+ return SDOUT_NO_ERROR;
+}
+
+enum s5p_tv_sd_err __s5p_sdout_init_sync_signal_pin(
+ enum s5p_sd_sync_sig_pin pin)
+{
+ SDPRINTK("%d\n\r", pin);
+
+ switch (pin) {
+
+ case SDOUT_SYNC_SIG_NO:
+ writel(SDO_COMPONENT_SYNC_ABSENT, sdout_base + S5P_SDO_SYNC);
+ break;
+
+ case SDOUT_SYNC_SIG_YG:
+ writel(SDO_COMPONENT_SYNC_YG, sdout_base + S5P_SDO_SYNC);
+ break;
+
+ case SDOUT_SYNC_SIG_ALL:
+ writel(SDO_COMPONENT_SYNC_ALL, sdout_base + S5P_SDO_SYNC);
+ break;
+
+ default:
+ SDPRINTK("invalid pin parameter(%d)\n\r", pin);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ SDPRINTK("0x%08x\n\r", readl(sdout_base + S5P_SDO_SYNC));
+
+ return SDOUT_NO_ERROR;
+}
+
+enum s5p_tv_sd_err __s5p_sdout_init_vbi(bool wss_cvbs,
+ enum s5p_sd_closed_caption_type caption_cvbs,
+ bool wss_y_sideo,
+ enum s5p_sd_closed_caption_type caption_y_sideo,
+ bool cgmsa_rgb,
+ bool wss_rgb,
+ enum s5p_sd_closed_caption_type caption_rgb,
+ bool cgmsa_y_ppr,
+ bool wss_y_ppr,
+ enum s5p_sd_closed_caption_type caption_y_ppr)
+{
+ u32 temp_reg = 0;
+
+ SDPRINTK(" %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n\r",
+ wss_cvbs, caption_cvbs,
+ wss_y_sideo, caption_y_sideo, cgmsa_rgb, wss_rgb, caption_rgb,
+ cgmsa_y_ppr, wss_y_ppr, caption_y_ppr);
+
+ if (wss_cvbs)
+ temp_reg = SDO_CVBS_WSS_INS;
+ else
+ temp_reg = SDO_CVBS_NO_WSS;
+
+
+ switch (caption_cvbs) {
+
+ case SDOUT_NO_INS:
+ temp_reg |= SDO_CVBS_NO_CLOSED_CAPTION;
+ break;
+
+ case SDOUT_INS_1:
+ temp_reg |= SDO_CVBS_21H_CLOSED_CAPTION;
+ break;
+
+ case SDOUT_INS_2:
+ temp_reg |= SDO_CVBS_21H_284H_CLOSED_CAPTION;
+ break;
+
+ case SDOUT_INS_OTHERS:
+ temp_reg |= SDO_CVBS_USE_OTHERS;
+ break;
+
+ default:
+ SDPRINTK(" invalid caption_cvbs parameter(%d)\n\r",
+ caption_cvbs);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ if (wss_y_sideo)
+ temp_reg |= SDO_SVIDEO_WSS_INS;
+ else
+ temp_reg |= SDO_SVIDEO_NO_WSS;
+
+
+ switch (caption_y_sideo) {
+
+ case SDOUT_NO_INS:
+ temp_reg |= SDO_SVIDEO_NO_CLOSED_CAPTION;
+ break;
+
+ case SDOUT_INS_1:
+ temp_reg |= SDO_SVIDEO_21H_CLOSED_CAPTION;
+ break;
+
+ case SDOUT_INS_2:
+ temp_reg |= SDO_SVIDEO_21H_284H_CLOSED_CAPTION;
+ break;
+
+ case SDOUT_INS_OTHERS:
+ temp_reg |= SDO_SVIDEO_USE_OTHERS;
+ break;
+
+ default:
+ SDPRINTK("invalid caption_y_sideo parameter(%d)\n\r",
+ caption_y_sideo);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ if (cgmsa_rgb)
+ temp_reg |= SDO_RGB_CGMSA_INS;
+ else
+ temp_reg |= SDO_RGB_NO_CGMSA;
+
+
+ if (wss_rgb)
+ temp_reg |= SDO_RGB_WSS_INS;
+ else
+ temp_reg |= SDO_RGB_NO_WSS;
+
+
+ switch (caption_rgb) {
+
+ case SDOUT_NO_INS:
+ temp_reg |= SDO_RGB_NO_CLOSED_CAPTION;
+ break;
+
+ case SDOUT_INS_1:
+ temp_reg |= SDO_RGB_21H_CLOSED_CAPTION;
+ break;
+
+ case SDOUT_INS_2:
+ temp_reg |= SDO_RGB_21H_284H_CLOSED_CAPTION;
+ break;
+
+ case SDOUT_INS_OTHERS:
+ temp_reg |= SDO_RGB_USE_OTHERS;
+ break;
+
+ default:
+ SDPRINTK(" invalid caption_rgb parameter(%d)\n\r",
+ caption_rgb);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ if (cgmsa_y_ppr)
+ temp_reg |= SDO_YPBPR_CGMSA_INS;
+ else
+ temp_reg |= SDO_YPBPR_NO_CGMSA;
+
+
+ if (wss_y_ppr)
+ temp_reg |= SDO_YPBPR_WSS_INS;
+ else
+ temp_reg |= SDO_YPBPR_NO_WSS;
+
+
+ switch (caption_y_ppr) {
+
+ case SDOUT_NO_INS:
+ temp_reg |= SDO_YPBPR_NO_CLOSED_CAPTION;
+ break;
+
+ case SDOUT_INS_1:
+ temp_reg |= SDO_YPBPR_21H_CLOSED_CAPTION;
+ break;
+
+ case SDOUT_INS_2:
+ temp_reg |= SDO_YPBPR_21H_284H_CLOSED_CAPTION;
+ break;
+
+ case SDOUT_INS_OTHERS:
+ temp_reg |= SDO_YPBPR_USE_OTHERS;
+ break;
+
+ default:
+ SDPRINTK("invalid caption_y_ppr parameter(%d)\n\r",
+ caption_y_ppr);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ writel(temp_reg, sdout_base + S5P_SDO_VBI);
+
+ SDPRINTK("0x%08x\n\r", readl(sdout_base + S5P_SDO_VBI));
+
+ return SDOUT_NO_ERROR;
+}
+
+enum s5p_tv_sd_err __s5p_sdout_init_offset_gain(
+ enum s5p_sd_channel_sel channel,
+ u32 offset, u32 gain)
+{
+ SDPRINTK("%d, %d, %d\n\r", channel, offset, gain);
+
+ switch (channel) {
+
+ case SDOUT_CHANNEL_0:
+ writel(SDO_SCALE_CONV_OFFSET(offset) |
+ SDO_SCALE_CONV_GAIN(gain),
+ sdout_base + S5P_SDO_SCALE_CH0);
+ SDPRINTK("0x%08x\n\r", readl(sdout_base + S5P_SDO_SCALE_CH0));
+ break;
+
+ case SDOUT_CHANNEL_1:
+ writel(SDO_SCALE_CONV_OFFSET(offset) |
+ SDO_SCALE_CONV_GAIN(gain),
+ sdout_base + S5P_SDO_SCALE_CH1);
+ SDPRINTK(" 0x%08x\n\r", readl(sdout_base + S5P_SDO_SCALE_CH1));
+ break;
+
+ case SDOUT_CHANNEL_2:
+ writel(SDO_SCALE_CONV_OFFSET(offset) |
+ SDO_SCALE_CONV_GAIN(gain),
+ sdout_base + S5P_SDO_SCALE_CH2);
+ SDPRINTK(" 0x%08x\n\r", readl(sdout_base + S5P_SDO_SCALE_CH2));
+ break;
+
+ default:
+ SDPRINTK(" invalid channel parameter(%d)\n\r", channel);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ return SDOUT_NO_ERROR;
+}
+
+void __s5p_sdout_init_delay(u32 delay_y,
+ u32 offset_video_start,
+ u32 offset_video_end)
+{
+ SDPRINTK("%d, %d, %d\n\r", delay_y, offset_video_start,
+ offset_video_end);
+
+ writel(SDO_DELAY_YTOC(delay_y) |
+ SDO_ACTIVE_START_OFFSET(offset_video_start) |
+ SDO_ACTIVE_END_OFFSET(offset_video_end),
+ sdout_base + S5P_SDO_YCDELAY);
+
+ SDPRINTK("0x%08x\n\r", readl(sdout_base + S5P_SDO_YCDELAY));
+}
+
+void __s5p_sdout_init_schlock(bool color_sucarrier_pha_adj)
+{
+ SDPRINTK("%d\n\r", color_sucarrier_pha_adj);
+
+ if (color_sucarrier_pha_adj)
+ writel(SDO_COLOR_SC_PHASE_ADJ, sdout_base + S5P_SDO_SCHLOCK);
+ else
+ writel(SDO_COLOR_SC_PHASE_NOADJ, sdout_base + S5P_SDO_SCHLOCK);
+
+
+ SDPRINTK("0x%08x\n\r", readl(sdout_base + S5P_SDO_SCHLOCK));
+}
+
+enum s5p_tv_sd_err __s5p_sdout_init_dac_power_onoff(
+ enum s5p_sd_channel_sel channel, bool dac_on)
+{
+ u32 temp_on_off;
+
+ SDPRINTK("%d, %d)\n\r", channel, dac_on);
+
+ switch (channel) {
+
+ case SDOUT_CHANNEL_0:
+ temp_on_off = SDO_POWER_ON_DAC0;
+ break;
+
+ case SDOUT_CHANNEL_1:
+ temp_on_off = SDO_POWER_ON_DAC1;
+ break;
+
+ case SDOUT_CHANNEL_2:
+ temp_on_off = SDO_POWER_ON_DAC2;
+ break;
+
+ default:
+ SDPRINTK("invalid channel parameter(%d)\n\r", channel);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ if (dac_on)
+ writel(readl(sdout_base + S5P_SDO_DAC) | temp_on_off,
+ sdout_base + S5P_SDO_DAC);
+ else
+ writel(readl(sdout_base + S5P_SDO_DAC) & ~temp_on_off,
+ sdout_base + S5P_SDO_DAC);
+
+
+ SDPRINTK("0x%08x\n\r", readl(sdout_base + S5P_SDO_DAC));
+
+ return SDOUT_NO_ERROR;
+}
+
+void __s5p_sdout_init_color_compensaton_onoff(bool bright_hue_saturation_adj,
+ bool y_ppr_color_compensation,
+ bool rgcolor_compensation,
+ bool y_c_color_compensation,
+ bool y_cvbs_color_compensation)
+{
+ u32 temp_reg = 0;
+
+ SDPRINTK("%d, %d, %d, %d, %d)\n\r", bright_hue_saturation_adj,
+ y_ppr_color_compensation, rgcolor_compensation,
+ y_c_color_compensation, y_cvbs_color_compensation);
+
+ if (bright_hue_saturation_adj)
+ temp_reg &= ~SDO_COMPONENT_BHS_ADJ_OFF;
+ else
+ temp_reg |= SDO_COMPONENT_BHS_ADJ_OFF;
+
+
+ if (y_ppr_color_compensation)
+ temp_reg &= ~SDO_COMPONENT_YPBPR_COMP_OFF;
+ else
+ temp_reg |= SDO_COMPONENT_YPBPR_COMP_OFF;
+
+
+ if (rgcolor_compensation)
+ temp_reg &= ~SDO_COMPONENT_RGB_COMP_OFF;
+ else
+ temp_reg |= SDO_COMPONENT_RGB_COMP_OFF;
+
+
+ if (y_c_color_compensation)
+ temp_reg &= ~SDO_COMPONENT_YC_COMP_OFF;
+ else
+ temp_reg |= SDO_COMPONENT_YC_COMP_OFF;
+
+
+ if (y_cvbs_color_compensation)
+ temp_reg &= ~SDO_COMPONENT_CVBS_COMP_OFF;
+ else
+ temp_reg |= SDO_COMPONENT_CVBS_COMP_OFF;
+
+
+ writel(temp_reg, sdout_base + S5P_SDO_CCCON);
+
+ SDPRINTK("0x%08x\n\r", readl(sdout_base + S5P_SDO_CCCON));
+}
+
+void __s5p_sdout_init_brightness_hue_saturation(u32 gain_brightness,
+ u32 offset_brightness,
+ u32 gain0_cb_hue_saturation,
+ u32 gain1_cb_hue_saturation,
+ u32 gain0_cr_hue_saturation,
+ u32 gain1_cr_hue_saturation,
+ u32 offset_cb_hue_saturation,
+ u32 offset_cr_hue_saturation)
+{
+ SDPRINTK(" %d, %d, %d, %d, %d, %d, %d, %d)\n\r", gain_brightness,
+ offset_brightness, gain0_cb_hue_saturation,
+ gain1_cb_hue_saturation, gain0_cr_hue_saturation,
+ gain1_cr_hue_saturation, offset_cb_hue_saturation,
+ offset_cr_hue_saturation);
+
+ writel(SDO_BRIGHTNESS_GAIN(gain_brightness) |
+ SDO_BRIGHTNESS_OFFSET(offset_brightness),
+ sdout_base + S5P_SDO_YSCALE);
+
+ writel(SDO_HS_CB_GAIN0(gain0_cb_hue_saturation) |
+ SDO_HS_CB_GAIN1(gain1_cb_hue_saturation),
+ sdout_base + S5P_SDO_CBSCALE);
+
+ writel(SDO_HS_CR_GAIN0(gain0_cr_hue_saturation) |
+ SDO_HS_CR_GAIN1(gain1_cr_hue_saturation),
+ sdout_base + S5P_SDO_CRSCALE);
+
+ writel(SDO_HS_CR_OFFSET(offset_cr_hue_saturation) |
+ SDO_HS_CB_OFFSET(offset_cb_hue_saturation),
+ sdout_base + S5P_SDO_CB_CR_OFFSET);
+
+ SDPRINTK("0x%08x, 0x%08x, 0x%08x, 0x%08x)\n\r",
+ readl(sdout_base + S5P_SDO_YSCALE),
+ readl(sdout_base + S5P_SDO_CBSCALE),
+ readl(sdout_base + S5P_SDO_CRSCALE),
+ readl(sdout_base + S5P_SDO_CB_CR_OFFSET));
+}
+
+void __s5p_sdout_init_rgb_color_compensation(u32 max_rgbcube,
+ u32 min_rgbcube)
+{
+ SDPRINTK("0x%08x, 0x%08x\n\r", max_rgbcube, min_rgbcube);
+
+ writel(SDO_MAX_RGB_CUBE(max_rgbcube) | SDO_MIN_RGB_CUBE(min_rgbcube),
+ sdout_base + S5P_SDO_RGB_CC);
+
+ SDPRINTK("0x%08x)\n\r", readl(sdout_base + S5P_SDO_RGB_CC));
+}
+
+void __s5p_sdout_init_cvbs_color_compensation(u32 y_lower_mid,
+ u32 y_bottom,
+ u32 y_top,
+ u32 y_upper_mid,
+ u32 radius)
+{
+ SDPRINTK("%d, %d, %d, %d, %d\n\r", y_lower_mid, y_bottom, y_top,
+ y_upper_mid, radius);
+
+ writel(SDO_Y_LOWER_MID_CVBS_CORN(y_lower_mid) |
+ SDO_Y_BOTTOM_CVBS_CORN(y_bottom),
+ sdout_base + S5P_SDO_CVBS_CC_Y1);
+ writel(SDO_Y_TOP_CVBS_CORN(y_top) |
+ SDO_Y_UPPER_MID_CVBS_CORN(y_upper_mid),
+ sdout_base + S5P_SDO_CVBS_CC_Y2);
+ writel(SDO_RADIUS_CVBS_CORN(radius), sdout_base + S5P_SDO_CVBS_CC_C);
+
+ SDPRINTK("0x%08x, 0x%08x, 0x%08x)\n\r",
+ readl(sdout_base + S5P_SDO_CVBS_CC_Y1),
+ readl(sdout_base + S5P_SDO_CVBS_CC_Y2),
+ readl(sdout_base + S5P_SDO_CVBS_CC_C));
+}
+
+void __s5p_sdout_init_svideo_color_compensation(u32 y_top,
+ u32 y_bottom,
+ u32 y_c_cylinder)
+{
+ SDPRINTK(" %d, %d, %d)\n\r", y_top, y_bottom, y_c_cylinder);
+
+ writel(SDO_Y_TOP_YC_CYLINDER(y_top) |
+ SDO_Y_BOTOM_YC_CYLINDER(y_bottom),
+ sdout_base + S5P_SDO_YC_CC_Y);
+ writel(SDO_RADIUS_YC_CYLINDER(y_c_cylinder),
+ sdout_base + S5P_SDO_YC_CC_C);
+
+ SDPRINTK("0x%08x, 0x%08x)\n\r", readl(sdout_base + S5P_SDO_YC_CC_Y),
+ readl(sdout_base + S5P_SDO_YC_CC_C));
+}
+
+void __s5p_sdout_init_component_porch(u32 back_525,
+ u32 front_525,
+ u32 back_625,
+ u32 front_625)
+{
+ SDPRINTK(" %d, %d, %d, %d)\n\r", back_525,
+ front_525, back_625, front_625);
+
+ writel(SDO_COMPONENT_525_BP(back_525) |
+ SDO_COMPONENT_525_FP(front_525),
+ sdout_base + S5P_SDO_CSC_525_PORCH);
+ writel(SDO_COMPONENT_625_BP(back_625) |
+ SDO_COMPONENT_625_FP(front_625),
+ sdout_base + S5P_SDO_CSC_625_PORCH);
+
+ SDPRINTK(" 0x%08x, 0x%08x)\n\r",
+ readl(sdout_base + S5P_SDO_CSC_525_PORCH),
+ readl(sdout_base + S5P_SDO_CSC_625_PORCH));
+}
+
+enum s5p_tv_sd_err __s5p_sdout_init_vesa_rgb_sync(
+ enum s5p_sd_vesa_rgb_sync_type sync_type,
+ enum s5p_tv_active_polarity v_sync_active,
+ enum s5p_tv_active_polarity h_sync_active)
+{
+ u32 temp_reg = 0;
+
+ SDPRINTK("%d, %d, %d\n\r", sync_type, v_sync_active, h_sync_active);
+
+ switch (sync_type) {
+
+ case SDOUT_VESA_RGB_SYNC_COMPOSITE:
+ temp_reg |= SDO_RGB_SYNC_COMPOSITE;
+ break;
+
+ case SDOUT_VESA_RGB_SYNC_SEPARATE:
+ temp_reg |= SDO_RGB_SYNC_SEPERATE;
+ break;
+
+ default:
+ SDPRINTK(" invalid sync_type parameter(%d)\n\r", sync_type);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ switch (v_sync_active) {
+
+ case TVOUT_POL_ACTIVE_LOW:
+ temp_reg |= SDO_RGB_VSYNC_LOW_ACT;
+ break;
+
+ case TVOUT_POL_ACTIVE_HIGH:
+ temp_reg |= SDO_RGB_VSYNC_HIGH_ACT;
+ break;
+
+ default:
+ SDPRINTK(" invalid v_sync_active parameter(%d)\n\r",
+ v_sync_active);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ switch (h_sync_active) {
+
+ case TVOUT_POL_ACTIVE_LOW:
+ temp_reg |= SDO_RGB_HSYNC_LOW_ACT;
+ break;
+
+ case TVOUT_POL_ACTIVE_HIGH:
+ temp_reg |= SDO_RGB_HSYNC_HIGH_ACT;
+ break;
+
+ default:
+ SDPRINTK(" invalid h_sync_active parameter(%d)\n\r",
+ h_sync_active);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ writel(temp_reg, sdout_base + S5P_SDO_RGBSYNC);
+
+ SDPRINTK("0x%08x\n\r", readl(sdout_base + S5P_SDO_RGBSYNC));
+
+ return SDOUT_NO_ERROR;
+}
+
+void __s5p_sdout_init_oversampling_filter_coeff(u32 size,
+ u32 *coeff,
+ u32 *coeff1,
+ u32 *coeff2)
+{
+ u32 *temp_reg = 0;
+
+ SDPRINTK(" %d, 0x%x, 0x%x, 0x%x\n\r", (u32)size, (u32)coeff,
+ (u32)coeff1, (u32)coeff2);
+
+ if (coeff != NULL) {
+ temp_reg = (u32 *)readl(sdout_base + S5P_SDO_OSFC00_0);
+ memcpy((void *)temp_reg, (const void *)coeff, size*4);
+ }
+
+ if (coeff1 != NULL) {
+ temp_reg = (u32 *)readl(sdout_base + S5P_SDO_OSFC00_1);
+ memcpy((void *)temp_reg, (const void *)coeff1, size*4);
+ }
+
+ if (coeff2 != NULL) {
+ temp_reg = (u32 *)readl(sdout_base + S5P_SDO_OSFC00_2);
+ memcpy((void *)temp_reg, (const void *)coeff2, size*4);
+ }
+
+ SDPRINTK(" ()\n\r");
+}
+
+enum s5p_tv_sd_err __s5p_sdout_init_ch_xtalk_cancel_coef(
+ enum s5p_sd_channel_sel channel,
+ u32 coeff2, u32 coeff1)
+{
+ SDPRINTK(" %d, %d, %d\n\r", channel, coeff2, coeff1);
+
+ switch (channel) {
+
+ case SDOUT_CHANNEL_0:
+ writel(SDO_XTALK_COEF02(coeff2) | SDO_XTALK_COEF01(coeff1),
+ sdout_base + S5P_SDO_XTALK0);
+ SDPRINTK(" 0x%08x)\n\r", readl(sdout_base + S5P_SDO_XTALK0));
+ break;
+
+ case SDOUT_CHANNEL_1:
+ writel(SDO_XTALK_COEF02(coeff2) | SDO_XTALK_COEF01(coeff1),
+ sdout_base + S5P_SDO_XTALK1);
+ SDPRINTK(" 0x%08x)\n\r", readl(sdout_base + S5P_SDO_XTALK1));
+ break;
+
+ case SDOUT_CHANNEL_2:
+ writel(SDO_XTALK_COEF02(coeff2) | SDO_XTALK_COEF01(coeff1),
+ sdout_base + S5P_SDO_XTALK2);
+ SDPRINTK("0x%08x)\n\r", readl(sdout_base + S5P_SDO_XTALK2));
+ break;
+
+ default:
+ SDPRINTK(" invalid channel parameter(%d)\n\r", channel);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ return SDOUT_NO_ERROR;
+}
+
+void __s5p_sdout_init_closed_caption(u32 display_cc, u32 non_display_cc)
+{
+ SDPRINTK("%d, %d\n\r", display_cc, non_display_cc);
+
+ writel(SDO_DISPLAY_CC_CAPTION(display_cc) |
+ SDO_NON_DISPLAY_CC_CAPTION(non_display_cc),
+ sdout_base + S5P_SDO_ARMCC);
+
+ SDPRINTK("0x%x\n\r", readl(sdout_base + S5P_SDO_ARMCC));
+}
+
+
+/* static functions */
+static u32 __s5p_sdout_init_wss_cgms_crc(u32 value)
+{
+ u8 i;
+ u8 CGMS[14], CRC[6], OLD_CRC;
+ u32 temp_in;
+
+ temp_in = value;
+
+ for (i = 0; i < 14; i++)
+ CGMS[i] = (u8)(temp_in >> i) & 0x1 ;
+
+ /* initialize state */
+ for (i = 0; i < 6; i++)
+ CRC[i] = 0x1;
+
+ /* round 20 */
+ for (i = 0; i < 14; i++) {
+ OLD_CRC = CRC[0];
+ CRC[0] = CRC[1];
+ CRC[1] = CRC[2];
+ CRC[2] = CRC[3];
+ CRC[3] = CRC[4];
+ CRC[4] = OLD_CRC ^ CGMS[i] ^ CRC[5];
+ CRC[5] = OLD_CRC ^ CGMS[i];
+ }
+
+ /* recompose to return crc */
+ temp_in &= 0x3fff;
+
+ for (i = 0; i < 6; i++)
+ temp_in |= ((u32)(CRC[i] & 0x1) << i);
+
+
+ return temp_in;
+}
+
+
+enum s5p_tv_sd_err __s5p_sdout_init_wss525_data(
+ enum s5p_sd_525_copy_permit copy_permit,
+ enum s5p_sd_525_mv_psp mv_psp,
+ enum s5p_sd_525_copy_info copy_info,
+ bool analog_on,
+ enum s5p_sd_525_aspect_ratio display_ratio)
+{
+ u32 temp_reg = 0;
+
+ SDPRINTK("%d, %d, %d, %d\n\r", copy_permit, mv_psp, copy_info,
+ display_ratio);
+
+ switch (copy_permit) {
+
+ case SDO_525_COPY_PERMIT:
+ temp_reg = SDO_WORD2_WSS525_COPY_PERMIT;
+ break;
+
+ case SDO_525_ONECOPY_PERMIT:
+ temp_reg = SDO_WORD2_WSS525_ONECOPY_PERMIT;
+ break;
+
+ case SDO_525_NOCOPY_PERMIT:
+ temp_reg = SDO_WORD2_WSS525_NOCOPY_PERMIT;
+ break;
+
+ default:
+ SDPRINTK(" invalid copy_permit parameter(%d)\n\r", copy_permit);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ switch (mv_psp) {
+
+ case SDO_525_MV_PSP_OFF:
+ temp_reg |= SDO_WORD2_WSS525_MV_PSP_OFF;
+ break;
+
+ case SDO_525_MV_PSP_ON_2LINE_BURST:
+ temp_reg |= SDO_WORD2_WSS525_MV_PSP_ON_2LINE_BURST;
+ break;
+
+ case SDO_525_MV_PSP_ON_BURST_OFF:
+ temp_reg |= SDO_WORD2_WSS525_MV_PSP_ON_BURST_OFF;
+ break;
+
+ case SDO_525_MV_PSP_ON_4LINE_BURST:
+ temp_reg |= SDO_WORD2_WSS525_MV_PSP_ON_4LINE_BURST;
+ break;
+
+ default:
+ SDPRINTK(" invalid mv_psp parameter(%d)\n\r", mv_psp);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ switch (copy_info) {
+
+ case SDO_525_COPY_INFO:
+ temp_reg |= SDO_WORD1_WSS525_COPY_INFO;
+ break;
+
+ case SDO_525_DEFAULT:
+ temp_reg |= SDO_WORD1_WSS525_DEFAULT;
+ break;
+
+ default:
+ SDPRINTK(" invalid copy_info parameter(%d)\n\r", copy_info);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ if (analog_on)
+ temp_reg |= SDO_WORD2_WSS525_ANALOG_ON;
+ else
+ temp_reg |= SDO_WORD2_WSS525_ANALOG_OFF;
+
+
+ switch (display_ratio) {
+
+ case SDO_525_COPY_PERMIT:
+ temp_reg |= SDO_WORD0_WSS525_4_3_NORMAL;
+ break;
+
+ case SDO_525_ONECOPY_PERMIT:
+ temp_reg |= SDO_WORD0_WSS525_16_9_ANAMORPIC;
+ break;
+
+ case SDO_525_NOCOPY_PERMIT:
+ temp_reg |= SDO_WORD0_WSS525_4_3_LETTERBOX;
+ break;
+
+ default:
+ SDPRINTK(" invalid display_ratio parameter(%d)\n\r",
+ display_ratio);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ writel(temp_reg |
+ SDO_CRC_WSS525(__s5p_sdout_init_wss_cgms_crc(temp_reg)),
+ sdout_base + S5P_SDO_WSS525);
+
+ SDPRINTK("0x%08x)\n\r", readl(sdout_base + S5P_SDO_WSS525));
+
+ return SDOUT_NO_ERROR;
+}
+
+enum s5p_tv_sd_err __s5p_sdout_init_wss625_data(bool surround_sound,
+ bool copyright,
+ bool copy_protection,
+ bool text_subtitles,
+ enum s5p_sd_625_subtitles open_subtitles,
+ enum s5p_sd_625_camera_film camera_film,
+ enum s5p_sd_625_color_encoding color_encoding,
+ bool helper_signal,
+ enum s5p_sd_625_aspect_ratio display_ratio)
+{
+ u32 temp_reg = 0;
+
+ SDPRINTK("%d, %d, %d, %d, %d, %d, %d, %d, %d\n\r",
+ surround_sound, copyright, copy_protection,
+ text_subtitles, open_subtitles, camera_film,
+ color_encoding, helper_signal, display_ratio);
+
+ if (surround_sound)
+ temp_reg = SDO_WSS625_SURROUND_SOUND_ENABLE;
+ else
+ temp_reg = SDO_WSS625_SURROUND_SOUND_DISABLE;
+
+
+ if (copyright)
+ temp_reg |= SDO_WSS625_COPYRIGHT;
+ else
+ temp_reg |= SDO_WSS625_NO_COPYRIGHT;
+
+
+ if (copy_protection)
+ temp_reg |= SDO_WSS625_COPY_RESTRICTED;
+ else
+ temp_reg |= SDO_WSS625_COPY_NOT_RESTRICTED;
+
+
+ if (text_subtitles)
+ temp_reg |= SDO_WSS625_TELETEXT_SUBTITLES;
+ else
+ temp_reg |= SDO_WSS625_TELETEXT_NO_SUBTITLES;
+
+
+ switch (open_subtitles) {
+
+ case SDO_625_NO_OPEN_SUBTITLES:
+ temp_reg |= SDO_WSS625_NO_OPEN_SUBTITLES;
+ break;
+
+ case SDO_625_INACT_OPEN_SUBTITLES:
+ temp_reg |= SDO_WSS625_INACT_OPEN_SUBTITLES;
+ break;
+
+ case SDO_625_OUTACT_OPEN_SUBTITLES:
+ temp_reg |= SDO_WSS625_OUTACT_OPEN_SUBTITLES;
+ break;
+
+ default:
+ SDPRINTK(" invalid open_subtitles parameter(%d)\n\r",
+ open_subtitles);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ switch (camera_film) {
+
+ case SDO_625_CAMERA:
+ temp_reg |= SDO_WSS625_CAMERA;
+ break;
+
+ case SDO_625_FILM:
+ temp_reg |= SDO_WSS625_FILM;
+ break;
+
+ default:
+ SDPRINTK("invalid camera_film parameter(%d)\n\r",
+ camera_film);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ switch (color_encoding) {
+
+ case SDO_625_NORMAL_PAL:
+ temp_reg |= SDO_WSS625_NORMAL_PAL;
+ break;
+
+ case SDO_625_MOTION_ADAPTIVE_COLORPLUS:
+ temp_reg |= SDO_WSS625_MOTION_ADAPTIVE_COLORPLUS;
+ break;
+
+ default:
+ SDPRINTK("invalid color_encoding parameter(%d)\n\r",
+ color_encoding);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ if (helper_signal)
+ temp_reg |= SDO_WSS625_HELPER_SIG;
+ else
+ temp_reg |= SDO_WSS625_HELPER_NO_SIG;
+
+
+ switch (display_ratio) {
+
+ case SDO_625_4_3_FULL_576:
+ temp_reg |= SDO_WSS625_4_3_FULL_576;
+ break;
+
+ case SDO_625_14_9_LETTERBOX_CENTER_504:
+ temp_reg |= SDO_WSS625_14_9_LETTERBOX_CENTER_504;
+ break;
+
+ case SDO_625_14_9_LETTERBOX_TOP_504:
+ temp_reg |= SDO_WSS625_14_9_LETTERBOX_TOP_504;
+ break;
+
+ case SDO_625_16_9_LETTERBOX_CENTER_430:
+ temp_reg |= SDO_WSS625_16_9_LETTERBOX_CENTER_430;
+ break;
+
+ case SDO_625_16_9_LETTERBOX_TOP_430:
+ temp_reg |= SDO_WSS625_16_9_LETTERBOX_TOP_430;
+ break;
+
+ case SDO_625_16_9_LETTERBOX_CENTER:
+ temp_reg |= SDO_WSS625_16_9_LETTERBOX_CENTER;
+ break;
+
+ case SDO_625_14_9_FULL_CENTER_576:
+ temp_reg |= SDO_WSS625_14_9_FULL_CENTER_576;
+ break;
+
+ case SDO_625_16_9_ANAMORPIC_576:
+ temp_reg |= SDO_WSS625_16_9_ANAMORPIC_576;
+ break;
+
+ default:
+ SDPRINTK("invalid display_ratio parameter(%d)\n\r",
+ display_ratio);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ writel(temp_reg, sdout_base + S5P_SDO_WSS625);
+
+ SDPRINTK("0x%08x\n\r", readl(sdout_base + S5P_SDO_WSS625));
+
+ return SDOUT_NO_ERROR;
+}
+
+enum s5p_tv_sd_err __s5p_sdout_init_cgmsa525_data(
+ enum s5p_sd_525_copy_permit copy_permit,
+ enum s5p_sd_525_mv_psp mv_psp,
+ enum s5p_sd_525_copy_info copy_info,
+ bool analog_on,
+ enum s5p_sd_525_aspect_ratio display_ratio)
+{
+ u32 temp_reg = 0;
+
+ SDPRINTK("%d, %d, %d, %d)\n\r", copy_permit, mv_psp, copy_info,
+ display_ratio);
+
+ switch (copy_permit) {
+
+ case SDO_525_COPY_PERMIT:
+ temp_reg = SDO_WORD2_CGMS525_COPY_PERMIT;
+ break;
+
+ case SDO_525_ONECOPY_PERMIT:
+ temp_reg = SDO_WORD2_CGMS525_ONECOPY_PERMIT;
+ break;
+
+ case SDO_525_NOCOPY_PERMIT:
+ temp_reg = SDO_WORD2_CGMS525_NOCOPY_PERMIT;
+ break;
+
+ default:
+ SDPRINTK("invalid copy_permit parameter(%d)\n\r", copy_permit);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ switch (mv_psp) {
+
+ case SDO_525_MV_PSP_OFF:
+ temp_reg |= SDO_WORD2_CGMS525_MV_PSP_OFF;
+ break;
+
+ case SDO_525_MV_PSP_ON_2LINE_BURST:
+ temp_reg |= SDO_WORD2_CGMS525_MV_PSP_ON_2LINE_BURST;
+ break;
+
+ case SDO_525_MV_PSP_ON_BURST_OFF:
+ temp_reg |= SDO_WORD2_CGMS525_MV_PSP_ON_BURST_OFF;
+ break;
+
+ case SDO_525_MV_PSP_ON_4LINE_BURST:
+ temp_reg |= SDO_WORD2_CGMS525_MV_PSP_ON_4LINE_BURST;
+ break;
+
+ default:
+ SDPRINTK(" invalid mv_psp parameter(%d)\n\r", mv_psp);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ switch (copy_info) {
+
+ case SDO_525_COPY_INFO:
+ temp_reg |= SDO_WORD1_CGMS525_COPY_INFO;
+ break;
+
+ case SDO_525_DEFAULT:
+ temp_reg |= SDO_WORD1_CGMS525_DEFAULT;
+ break;
+
+ default:
+ SDPRINTK("invalid copy_info parameter(%d)\n\r", copy_info);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ if (analog_on)
+ temp_reg |= SDO_WORD2_CGMS525_ANALOG_ON;
+ else
+ temp_reg |= SDO_WORD2_CGMS525_ANALOG_OFF;
+
+
+ switch (display_ratio) {
+
+ case SDO_525_COPY_PERMIT:
+ temp_reg |= SDO_WORD0_CGMS525_4_3_NORMAL;
+ break;
+
+ case SDO_525_ONECOPY_PERMIT:
+ temp_reg |= SDO_WORD0_CGMS525_16_9_ANAMORPIC;
+ break;
+
+ case SDO_525_NOCOPY_PERMIT:
+ temp_reg |= SDO_WORD0_CGMS525_4_3_LETTERBOX;
+ break;
+
+ default:
+ SDPRINTK(" invalid display_ratio parameter(%d)\n\r",
+ display_ratio);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ writel(temp_reg | SDO_CRC_CGMS525(
+ __s5p_sdout_init_wss_cgms_crc(temp_reg)),
+ sdout_base + S5P_SDO_CGMS525);
+
+ SDPRINTK(" 0x%08x)\n\r", readl(sdout_base + S5P_SDO_CGMS525));
+
+ return SDOUT_NO_ERROR;
+}
+
+enum s5p_tv_sd_err __s5p_sdout_init_cgmsa625_data(bool surround_sound,
+ bool copyright,
+ bool copy_protection,
+ bool text_subtitles,
+ enum s5p_sd_625_subtitles open_subtitles,
+ enum s5p_sd_625_camera_film camera_film,
+ enum s5p_sd_625_color_encoding color_encoding,
+ bool helper_signal,
+ enum s5p_sd_625_aspect_ratio display_ratio)
+{
+ u32 temp_reg = 0;
+
+ SDPRINTK("%d, %d, %d, %d, %d, %d, %d, %d, %d)\n\r", surround_sound,
+ copyright, copy_protection,
+ text_subtitles, open_subtitles,
+ camera_film, color_encoding, helper_signal,
+ display_ratio);
+
+ if (surround_sound)
+ temp_reg = SDO_CGMS625_SURROUND_SOUND_ENABLE;
+ else
+ temp_reg = SDO_CGMS625_SURROUND_SOUND_DISABLE;
+
+
+ if (copyright)
+ temp_reg |= SDO_CGMS625_COPYRIGHT;
+ else
+ temp_reg |= SDO_CGMS625_NO_COPYRIGHT;
+
+
+ if (copy_protection)
+ temp_reg |= SDO_CGMS625_COPY_RESTRICTED;
+ else
+ temp_reg |= SDO_CGMS625_COPY_NOT_RESTRICTED;
+
+
+ if (text_subtitles)
+ temp_reg |= SDO_CGMS625_TELETEXT_SUBTITLES;
+ else
+ temp_reg |= SDO_CGMS625_TELETEXT_NO_SUBTITLES;
+
+
+ switch (open_subtitles) {
+
+ case SDO_625_NO_OPEN_SUBTITLES:
+ temp_reg |= SDO_CGMS625_NO_OPEN_SUBTITLES;
+ break;
+
+ case SDO_625_INACT_OPEN_SUBTITLES:
+ temp_reg |= SDO_CGMS625_INACT_OPEN_SUBTITLES;
+ break;
+
+ case SDO_625_OUTACT_OPEN_SUBTITLES:
+ temp_reg |= SDO_CGMS625_OUTACT_OPEN_SUBTITLES;
+ break;
+
+ default:
+ SDPRINTK("invalid open_subtitles parameter(%d)\n\r",
+ open_subtitles);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ switch (camera_film) {
+
+ case SDO_625_CAMERA:
+ temp_reg |= SDO_CGMS625_CAMERA;
+ break;
+
+ case SDO_625_FILM:
+ temp_reg |= SDO_CGMS625_FILM;
+ break;
+
+ default:
+ SDPRINTK(" invalid camera_film parameter(%d)\n\r",
+ camera_film);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ switch (color_encoding) {
+
+ case SDO_625_NORMAL_PAL:
+ temp_reg |= SDO_CGMS625_NORMAL_PAL;
+ break;
+
+ case SDO_625_MOTION_ADAPTIVE_COLORPLUS:
+ temp_reg |= SDO_CGMS625_MOTION_ADAPTIVE_COLORPLUS;
+ break;
+
+ default:
+ SDPRINTK(" invalid color_encoding parameter(%d)\n\r",
+ color_encoding);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ if (helper_signal)
+ temp_reg |= SDO_CGMS625_HELPER_SIG;
+ else
+ temp_reg |= SDO_CGMS625_HELPER_NO_SIG;
+
+
+ switch (display_ratio) {
+
+ case SDO_625_4_3_FULL_576:
+ temp_reg |= SDO_CGMS625_4_3_FULL_576;
+ break;
+
+ case SDO_625_14_9_LETTERBOX_CENTER_504:
+ temp_reg |= SDO_CGMS625_14_9_LETTERBOX_CENTER_504;
+ break;
+
+ case SDO_625_14_9_LETTERBOX_TOP_504:
+ temp_reg |= SDO_CGMS625_14_9_LETTERBOX_TOP_504;
+ break;
+
+ case SDO_625_16_9_LETTERBOX_CENTER_430:
+ temp_reg |= SDO_CGMS625_16_9_LETTERBOX_CENTER_430;
+ break;
+
+ case SDO_625_16_9_LETTERBOX_TOP_430:
+ temp_reg |= SDO_CGMS625_16_9_LETTERBOX_TOP_430;
+ break;
+
+ case SDO_625_16_9_LETTERBOX_CENTER:
+ temp_reg |= SDO_CGMS625_16_9_LETTERBOX_CENTER;
+ break;
+
+ case SDO_625_14_9_FULL_CENTER_576:
+ temp_reg |= SDO_CGMS625_14_9_FULL_CENTER_576;
+ break;
+
+ case SDO_625_16_9_ANAMORPIC_576:
+ temp_reg |= SDO_CGMS625_16_9_ANAMORPIC_576;
+ break;
+
+ default:
+ SDPRINTK("invalid display_ratio parameter(%d)\n\r",
+ display_ratio);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ writel(temp_reg, sdout_base + S5P_SDO_CGMS625);
+
+ SDPRINTK("0x%08x\n\r", readl(sdout_base + S5P_SDO_CGMS625));
+
+ return SDOUT_NO_ERROR;
+}
+
+
+static enum s5p_tv_sd_err __s5p_sdout_init_antialias_filter_coeff_default(
+ enum s5p_sd_level composite_level,
+ enum s5p_sd_vsync_ratio composite_ratio,
+ enum s5p_tv_o_mode out_mode)
+{
+ SDPRINTK("%d, %d, %d\n\r", composite_level, composite_ratio, out_mode);
+
+ switch (composite_level) {
+
+ case S5P_TV_SD_LEVEL_0IRE:
+
+ switch (composite_ratio) {
+
+ case SDOUT_VTOS_RATIO_10_4:
+
+ switch (out_mode) {
+
+ case TVOUT_OUTPUT_COMPOSITE:
+
+ case TVOUT_OUTPUT_SVIDEO:
+ writel(0x00000000 , sdout_base + S5P_SDO_Y3);
+ writel(0x00000000 , sdout_base + S5P_SDO_Y4);
+ writel(0x00000000 , sdout_base + S5P_SDO_Y5);
+ writel(0x00000000 , sdout_base + S5P_SDO_Y6);
+ writel(0x00000000 , sdout_base + S5P_SDO_Y7);
+ writel(0x00000000 , sdout_base + S5P_SDO_Y8);
+ writel(0x00000000 , sdout_base + S5P_SDO_Y9);
+ writel(0x00000000 , sdout_base + S5P_SDO_Y10);
+ writel(0x0000029a , sdout_base + S5P_SDO_Y11);
+ writel(0x00000000 , sdout_base + S5P_SDO_CB0);
+ writel(0x00000000 , sdout_base + S5P_SDO_CB1);
+ writel(0x00000000 , sdout_base + S5P_SDO_CB2);
+ writel(0x00000000 , sdout_base + S5P_SDO_CB3);
+ writel(0x00000000 , sdout_base + S5P_SDO_CB4);
+ writel(0x00000001 , sdout_base + S5P_SDO_CB5);
+ writel(0x00000007 , sdout_base + S5P_SDO_CB6);
+ writel(0x00000015 , sdout_base + S5P_SDO_CB7);
+ writel(0x0000002b , sdout_base + S5P_SDO_CB8);
+ writel(0x00000045 , sdout_base + S5P_SDO_CB9);
+ writel(0x00000059 , sdout_base + S5P_SDO_CB10);
+ writel(0x00000061 , sdout_base + S5P_SDO_CB11);
+ writel(0x00000000 , sdout_base + S5P_SDO_CR1);
+ writel(0x00000000 , sdout_base + S5P_SDO_CR2);
+ writel(0x00000000 , sdout_base + S5P_SDO_CR3);
+ writel(0x00000000 , sdout_base + S5P_SDO_CR4);
+ writel(0x00000002 , sdout_base + S5P_SDO_CR5);
+ writel(0x0000000a , sdout_base + S5P_SDO_CR6);
+ writel(0x0000001e , sdout_base + S5P_SDO_CR7);
+ writel(0x0000003d , sdout_base + S5P_SDO_CR8);
+ writel(0x00000061 , sdout_base + S5P_SDO_CR9);
+ writel(0x0000007a , sdout_base + S5P_SDO_CR10);
+ writel(0x0000008f , sdout_base + S5P_SDO_CR11);
+ break;
+
+ case TVOUT_OUTPUT_COMPONENT_YPBPR_INERLACED:
+
+ case TVOUT_OUTPUT_COMPONENT_YPBPR_PROGRESSIVE:
+
+ case TVOUT_OUTPUT_COMPONENT_RGB_PROGRESSIVE:
+ writel(0x00000000, sdout_base + S5P_SDO_Y0);
+ writel(0x00000000, sdout_base + S5P_SDO_Y1);
+ writel(0x00000000, sdout_base + S5P_SDO_Y2);
+ writel(0x00000000, sdout_base + S5P_SDO_Y3);
+ writel(0x00000000, sdout_base + S5P_SDO_Y4);
+ writel(0x00000000, sdout_base + S5P_SDO_Y5);
+ writel(0x00000000, sdout_base + S5P_SDO_Y6);
+ writel(0x00000000, sdout_base + S5P_SDO_Y7);
+ writel(0x00000000, sdout_base + S5P_SDO_Y8);
+ writel(0x00000000, sdout_base + S5P_SDO_Y9);
+ writel(0x00000000, sdout_base + S5P_SDO_Y10);
+ writel(0x0000029a, sdout_base + S5P_SDO_Y11);
+ writel(0x00000000, sdout_base + S5P_SDO_CB0);
+ writel(0x00000000, sdout_base + S5P_SDO_CB1);
+ writel(0x00000000, sdout_base + S5P_SDO_CB2);
+ writel(0x00000000, sdout_base + S5P_SDO_CB3);
+ writel(0x00000000, sdout_base + S5P_SDO_CB4);
+ writel(0x00000001, sdout_base + S5P_SDO_CB5);
+ writel(0x00000007, sdout_base + S5P_SDO_CB6);
+ writel(0x00000015, sdout_base + S5P_SDO_CB7);
+ writel(0x0000002b, sdout_base + S5P_SDO_CB8);
+ writel(0x00000045, sdout_base + S5P_SDO_CB9);
+ writel(0x00000059, sdout_base + S5P_SDO_CB10);
+ writel(0x00000061, sdout_base + S5P_SDO_CB11);
+ writel(0x00000000, sdout_base + S5P_SDO_CR1);
+ writel(0x00000000, sdout_base + S5P_SDO_CR2);
+ writel(0x00000000, sdout_base + S5P_SDO_CR3);
+ writel(0x00000000, sdout_base + S5P_SDO_CR4);
+ writel(0x00000002, sdout_base + S5P_SDO_CR5);
+ writel(0x0000000a, sdout_base + S5P_SDO_CR6);
+ writel(0x0000001e, sdout_base + S5P_SDO_CR7);
+ writel(0x0000003d, sdout_base + S5P_SDO_CR8);
+ writel(0x00000061, sdout_base + S5P_SDO_CR9);
+ writel(0x0000007a, sdout_base + S5P_SDO_CR10);
+ writel(0x0000008f, sdout_base + S5P_SDO_CR11);
+ break;
+
+ default:
+ SDPRINTK("invalid out_mode parameter(%d)\n\r",
+ out_mode);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ break;
+
+ case SDOUT_VTOS_RATIO_7_3:
+ writel(0x00000000, sdout_base + S5P_SDO_Y0);
+ writel(0x00000000, sdout_base + S5P_SDO_Y1);
+ writel(0x00000000, sdout_base + S5P_SDO_Y2);
+ writel(0x00000000, sdout_base + S5P_SDO_Y3);
+ writel(0x00000000, sdout_base + S5P_SDO_Y4);
+ writel(0x00000000, sdout_base + S5P_SDO_Y5);
+ writel(0x00000000, sdout_base + S5P_SDO_Y6);
+ writel(0x00000000, sdout_base + S5P_SDO_Y7);
+ writel(0x00000000, sdout_base + S5P_SDO_Y8);
+ writel(0x00000000, sdout_base + S5P_SDO_Y9);
+ writel(0x00000000, sdout_base + S5P_SDO_Y10);
+ writel(0x00000281, sdout_base + S5P_SDO_Y11);
+ writel(0x00000000, sdout_base + S5P_SDO_CB0);
+ writel(0x00000000, sdout_base + S5P_SDO_CB1);
+ writel(0x00000000, sdout_base + S5P_SDO_CB2);
+ writel(0x00000000, sdout_base + S5P_SDO_CB3);
+ writel(0x00000000, sdout_base + S5P_SDO_CB4);
+ writel(0x00000001, sdout_base + S5P_SDO_CB5);
+ writel(0x00000007, sdout_base + S5P_SDO_CB6);
+ writel(0x00000015, sdout_base + S5P_SDO_CB7);
+ writel(0x0000002a, sdout_base + S5P_SDO_CB8);
+ writel(0x00000044, sdout_base + S5P_SDO_CB9);
+ writel(0x00000057, sdout_base + S5P_SDO_CB10);
+ writel(0x0000005f, sdout_base + S5P_SDO_CB11);
+ writel(0x00000000, sdout_base + S5P_SDO_CR1);
+ writel(0x00000000, sdout_base + S5P_SDO_CR2);
+ writel(0x00000000, sdout_base + S5P_SDO_CR3);
+ writel(0x00000000, sdout_base + S5P_SDO_CR4);
+ writel(0x00000002, sdout_base + S5P_SDO_CR5);
+ writel(0x0000000a, sdout_base + S5P_SDO_CR6);
+ writel(0x0000001d, sdout_base + S5P_SDO_CR7);
+ writel(0x0000003c, sdout_base + S5P_SDO_CR8);
+ writel(0x0000005f, sdout_base + S5P_SDO_CR9);
+ writel(0x0000007b, sdout_base + S5P_SDO_CR10);
+ writel(0x00000086, sdout_base + S5P_SDO_CR11);
+ break;
+
+ default:
+ SDPRINTK("invalid composite_ratio parameter(%d)\n\r",
+ composite_ratio);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ break;
+
+ case S5P_TV_SD_LEVEL_75IRE:
+
+ switch (composite_ratio) {
+
+ case SDOUT_VTOS_RATIO_10_4:
+ writel(0x00000000, sdout_base + S5P_SDO_Y0);
+ writel(0x00000000, sdout_base + S5P_SDO_Y1);
+ writel(0x00000000, sdout_base + S5P_SDO_Y2);
+ writel(0x00000000, sdout_base + S5P_SDO_Y3);
+ writel(0x00000000, sdout_base + S5P_SDO_Y4);
+ writel(0x00000000, sdout_base + S5P_SDO_Y5);
+ writel(0x00000000, sdout_base + S5P_SDO_Y6);
+ writel(0x00000000, sdout_base + S5P_SDO_Y7);
+ writel(0x00000000, sdout_base + S5P_SDO_Y8);
+ writel(0x00000000, sdout_base + S5P_SDO_Y9);
+ writel(0x00000000, sdout_base + S5P_SDO_Y10);
+ writel(0x0000025d, sdout_base + S5P_SDO_Y11);
+ writel(0x00000000, sdout_base + S5P_SDO_CB0);
+ writel(0x00000000, sdout_base + S5P_SDO_CB1);
+ writel(0x00000000, sdout_base + S5P_SDO_CB2);
+ writel(0x00000000, sdout_base + S5P_SDO_CB3);
+ writel(0x00000000, sdout_base + S5P_SDO_CB4);
+ writel(0x00000001, sdout_base + S5P_SDO_CB5);
+ writel(0x00000007, sdout_base + S5P_SDO_CB6);
+ writel(0x00000014, sdout_base + S5P_SDO_CB7);
+ writel(0x00000028, sdout_base + S5P_SDO_CB8);
+ writel(0x0000003f, sdout_base + S5P_SDO_CB9);
+ writel(0x00000052, sdout_base + S5P_SDO_CB10);
+ writel(0x0000005a, sdout_base + S5P_SDO_CB11);
+ writel(0x00000000, sdout_base + S5P_SDO_CR1);
+ writel(0x00000000, sdout_base + S5P_SDO_CR2);
+ writel(0x00000000, sdout_base + S5P_SDO_CR3);
+ writel(0x00000000, sdout_base + S5P_SDO_CR4);
+ writel(0x00000001, sdout_base + S5P_SDO_CR5);
+ writel(0x00000009, sdout_base + S5P_SDO_CR6);
+ writel(0x0000001c, sdout_base + S5P_SDO_CR7);
+ writel(0x00000039, sdout_base + S5P_SDO_CR8);
+ writel(0x0000005a, sdout_base + S5P_SDO_CR9);
+ writel(0x00000074, sdout_base + S5P_SDO_CR10);
+ writel(0x0000007e, sdout_base + S5P_SDO_CR11);
+ break;
+
+ case SDOUT_VTOS_RATIO_7_3:
+ writel(0x00000000, sdout_base + S5P_SDO_Y0);
+ writel(0x00000000, sdout_base + S5P_SDO_Y1);
+ writel(0x00000000, sdout_base + S5P_SDO_Y2);
+ writel(0x00000000, sdout_base + S5P_SDO_Y3);
+ writel(0x00000000, sdout_base + S5P_SDO_Y4);
+ writel(0x00000000, sdout_base + S5P_SDO_Y5);
+ writel(0x00000000, sdout_base + S5P_SDO_Y6);
+ writel(0x00000000, sdout_base + S5P_SDO_Y7);
+ writel(0x00000000, sdout_base + S5P_SDO_Y8);
+ writel(0x00000000, sdout_base + S5P_SDO_Y9);
+ writel(0x00000000, sdout_base + S5P_SDO_Y10);
+ writel(0x00000251, sdout_base + S5P_SDO_Y11);
+ writel(0x00000000, sdout_base + S5P_SDO_CB0);
+ writel(0x00000000, sdout_base + S5P_SDO_CB1);
+ writel(0x00000000, sdout_base + S5P_SDO_CB2);
+ writel(0x00000000, sdout_base + S5P_SDO_CB3);
+ writel(0x00000000, sdout_base + S5P_SDO_CB4);
+ writel(0x00000001, sdout_base + S5P_SDO_CB5);
+ writel(0x00000006, sdout_base + S5P_SDO_CB6);
+ writel(0x00000013, sdout_base + S5P_SDO_CB7);
+ writel(0x00000028, sdout_base + S5P_SDO_CB8);
+ writel(0x0000003f, sdout_base + S5P_SDO_CB9);
+ writel(0x00000051, sdout_base + S5P_SDO_CB10);
+ writel(0x00000056, sdout_base + S5P_SDO_CB11);
+ writel(0x00000000, sdout_base + S5P_SDO_CR1);
+ writel(0x00000000, sdout_base + S5P_SDO_CR2);
+ writel(0x00000000, sdout_base + S5P_SDO_CR3);
+ writel(0x00000000, sdout_base + S5P_SDO_CR4);
+ writel(0x00000002, sdout_base + S5P_SDO_CR5);
+ writel(0x00000005, sdout_base + S5P_SDO_CR6);
+ writel(0x00000018, sdout_base + S5P_SDO_CR7);
+ writel(0x00000037, sdout_base + S5P_SDO_CR8);
+ writel(0x0000005A, sdout_base + S5P_SDO_CR9);
+ writel(0x00000076, sdout_base + S5P_SDO_CR10);
+ writel(0x0000007e, sdout_base + S5P_SDO_CR11);
+ break;
+
+ default:
+ SDPRINTK(" invalid composite_ratio parameter(%d)\n\r",
+ composite_ratio);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ break;
+
+ default:
+ SDPRINTK(" invalid composite_level parameter(%d)\n\r",
+ composite_level);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ SDPRINTK("()\n\r");
+
+ return SDOUT_NO_ERROR;
+
+}
+
+
+static enum s5p_tv_sd_err __s5p_sdout_init_oversampling_filter_coeff_default(
+ enum s5p_tv_o_mode out_mode)
+{
+
+ SDPRINTK("%d\n\r", out_mode);
+
+ switch (out_mode) {
+
+ case TVOUT_OUTPUT_COMPOSITE:
+
+ case TVOUT_OUTPUT_SVIDEO:
+
+ case TVOUT_OUTPUT_COMPONENT_YPBPR_INERLACED:
+ /*
+ temp_reg = (u32)(sdout_base + S5P_SDO_OSFC00_0);
+
+ for (i = 0; i < 3; i++) {
+
+ temp_reg = (u32)((i == 0) ?
+ sdout_base + S5P_SDO_OSFC00_0 :
+ (i == 1) ? sdout_base + S5P_SDO_OSFC00_1 :
+ sdout_base + S5P_SDO_OSFC00_2);
+
+ writel(((-2&0xfff) << 0) | ((-3&0xfff) << 0),
+ temp_reg + 0);
+ writel(0,
+ temp_reg + 1);
+ writel((4 << 0) | (5 << 16),
+ temp_reg + 2);
+ writel(((-1&0xfff) << 0) | (0 << 16),
+ temp_reg + 3);
+ writel(((-6&0xfff) << 0) | ((-9&0xfff) << 16),
+ temp_reg + 4);
+ writel((1 << 0) | (0 << 16),
+ temp_reg + 5);
+ writel((10 << 0) | (14 << 16),
+ temp_reg + 6);
+ writel(((-1&0xfff) << 0) | (0 << 16),
+ temp_reg + 7);
+ writel(((-14&0xfff) << 0) | ((-20&0xfff) << 16),
+ temp_reg + 8);
+ writel((1 << 0) | (0 << 16),
+ temp_reg + 9);
+ writel((20 << 0) | (29 << 16),
+ temp_reg + 10);
+ writel(((-2&0xfff) << 0) | (0 << 16),
+ temp_reg + 11);
+ writel(((-28&0xfff) << 0) | ((-40&0xfff) << 16),
+ temp_reg + 12);
+ writel((2 << 0) | (0 << 16),
+ temp_reg + 13);
+ writel((40 << 0) | (56 << 16),
+ temp_reg + 14);
+ writel(((-3&0xfff) << 0) | (0 << 16),
+ temp_reg + 15);
+ writel(((-57&0xfff) << 0) | ((-80&0xfff) << 16),
+ temp_reg + 16);
+ writel((5 << 0) | (0 << 16),
+ temp_reg + 17);
+ writel((86 << 0) | (121 << 16),
+ temp_reg + 18);
+ writel(((-10&0xfff) << 0) | (0 << 16),
+ temp_reg + 19);
+ writel(((-154&0xfff) << 0) | ((-212&0xfff) << 16),
+ temp_reg + 20);
+ writel((27 << 0) | (0 << 16),
+ temp_reg + 21);
+ writel((613 << 0) | (651 << 16),
+ temp_reg + 22);
+ writel(((-308&0xfff) << 0) | (1024 << 16),
+ temp_reg + 23);
+ }
+*/
+ break;
+
+ default:
+ SDPRINTK("invalid out_mode parameter(%d)\n\r", out_mode);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ return SDOUT_NO_ERROR;
+}
+
+/*
+* initialization
+* - iniization functions are only called under stopping sdout
+*/
+enum s5p_tv_sd_err __s5p_sdout_init_display_mode(
+ enum s5p_tv_disp_mode disp_mode,
+ enum s5p_tv_o_mode out_mode,
+ enum s5p_sd_order order)
+{
+ u32 temp_reg = 0;
+
+ SDPRINTK(" %d, %d, %d\n\r", disp_mode, out_mode, order);
+
+ switch (disp_mode) {
+
+ case TVOUT_NTSC_M:
+ temp_reg |= SDO_NTSC_M;
+ __s5p_sdout_init_video_scale_cfg(S5P_TV_SD_LEVEL_0IRE,
+ SDOUT_VTOS_RATIO_7_3, S5P_TV_SD_LEVEL_75IRE,
+ SDOUT_VTOS_RATIO_10_4);
+
+ __s5p_sdout_init_antialias_filter_coeff_default(
+ S5P_TV_SD_LEVEL_75IRE,
+ SDOUT_VTOS_RATIO_10_4,
+ out_mode);
+ break;
+
+ case TVOUT_PAL_BDGHI:
+ temp_reg |= SDO_PAL_BGHID;
+ __s5p_sdout_init_video_scale_cfg(S5P_TV_SD_LEVEL_0IRE,
+ SDOUT_VTOS_RATIO_7_3, S5P_TV_SD_LEVEL_0IRE,
+ SDOUT_VTOS_RATIO_7_3);
+
+ __s5p_sdout_init_antialias_filter_coeff_default(
+ S5P_TV_SD_LEVEL_0IRE,
+ SDOUT_VTOS_RATIO_7_3, out_mode);
+ break;
+
+ case TVOUT_PAL_M:
+ temp_reg |= SDO_PAL_M;
+ __s5p_sdout_init_video_scale_cfg(S5P_TV_SD_LEVEL_0IRE,
+ SDOUT_VTOS_RATIO_7_3, S5P_TV_SD_LEVEL_0IRE,
+ SDOUT_VTOS_RATIO_7_3);
+
+ __s5p_sdout_init_antialias_filter_coeff_default(
+ S5P_TV_SD_LEVEL_0IRE,
+ SDOUT_VTOS_RATIO_7_3,
+ out_mode);
+ break;
+
+ case TVOUT_PAL_N:
+ temp_reg |= SDO_PAL_N;
+ __s5p_sdout_init_video_scale_cfg(S5P_TV_SD_LEVEL_0IRE,
+ SDOUT_VTOS_RATIO_7_3, S5P_TV_SD_LEVEL_0IRE,
+ SDOUT_VTOS_RATIO_7_3);
+
+ __s5p_sdout_init_antialias_filter_coeff_default(
+ S5P_TV_SD_LEVEL_75IRE,
+ SDOUT_VTOS_RATIO_10_4,
+ out_mode);
+ break;
+
+ case TVOUT_PAL_NC:
+ temp_reg |= SDO_PAL_NC;
+ __s5p_sdout_init_video_scale_cfg(S5P_TV_SD_LEVEL_0IRE,
+ SDOUT_VTOS_RATIO_7_3, S5P_TV_SD_LEVEL_0IRE,
+ SDOUT_VTOS_RATIO_7_3);
+
+ __s5p_sdout_init_antialias_filter_coeff_default(
+ S5P_TV_SD_LEVEL_0IRE,
+ SDOUT_VTOS_RATIO_7_3,
+ out_mode);
+ break;
+
+ case TVOUT_PAL_60:
+ temp_reg |= SDO_PAL_60;
+ __s5p_sdout_init_video_scale_cfg(S5P_TV_SD_LEVEL_0IRE,
+ SDOUT_VTOS_RATIO_7_3, S5P_TV_SD_LEVEL_0IRE,
+ SDOUT_VTOS_RATIO_7_3);
+ __s5p_sdout_init_antialias_filter_coeff_default(
+ S5P_TV_SD_LEVEL_0IRE,
+ SDOUT_VTOS_RATIO_7_3,
+ out_mode);
+ break;
+
+ case TVOUT_NTSC_443:
+ temp_reg |= SDO_NTSC_443;
+ __s5p_sdout_init_video_scale_cfg(S5P_TV_SD_LEVEL_0IRE,
+ SDOUT_VTOS_RATIO_7_3, S5P_TV_SD_LEVEL_75IRE,
+ SDOUT_VTOS_RATIO_10_4);
+ __s5p_sdout_init_antialias_filter_coeff_default(
+ S5P_TV_SD_LEVEL_75IRE,
+ SDOUT_VTOS_RATIO_10_4,
+ out_mode);
+ break;
+
+ default:
+ SDPRINTK("invalid disp_mode parameter(%d)\n\r", disp_mode);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ switch (out_mode) {
+
+ case TVOUT_OUTPUT_COMPOSITE:
+
+ case TVOUT_OUTPUT_SVIDEO:
+ temp_reg |= SDO_COMPOSITE | SDO_INTERLACED;
+
+ switch (order) {
+
+ case S5P_TV_SD_O_ORDER_COMPOSITE_CVBS_Y_C:
+ temp_reg |= SDO_DAC2_CVBS | SDO_DAC1_Y | SDO_DAC0_C;
+ break;
+
+ case S5P_TV_SD_O_ORDER_COMPOSITE_CVBS_C_Y:
+ temp_reg |= SDO_DAC2_CVBS | SDO_DAC1_C | SDO_DAC0_Y;
+ break;
+
+ case S5P_TV_SD_O_ORDER_COMPOSITE_Y_C_CVBS:
+ temp_reg |= SDO_DAC2_Y | SDO_DAC1_C | SDO_DAC0_CVBS;
+ break;
+
+ case S5P_TV_SD_O_ORDER_COMPOSITE_Y_CVBS_C:
+ temp_reg |= SDO_DAC2_Y | SDO_DAC1_CVBS | SDO_DAC0_C;
+ break;
+
+ case S5P_TV_SD_O_ORDER_COMPOSITE_C_CVBS_Y:
+ temp_reg |= SDO_DAC2_C | SDO_DAC1_CVBS | SDO_DAC0_Y;
+ break;
+
+ case S5P_TV_SD_O_ORDER_COMPOSITE_C_Y_CVBS:
+ temp_reg |= SDO_DAC2_C | SDO_DAC1_Y | SDO_DAC0_CVBS;
+ break;
+
+ default:
+ SDPRINTK(" invalid order parameter(%d)\n\r", order);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ break;
+
+ case TVOUT_OUTPUT_COMPONENT_YPBPR_INERLACED:
+ temp_reg |= SDO_COMPONENT | SDO_YPBPR | SDO_INTERLACED;
+
+ switch (order) {
+
+ case S5P_TV_SD_O_ORDER_COMPONENT_RGB_PRYPB:
+ temp_reg |= SDO_DAC2_PR_R | SDO_DAC1_Y_G |
+ SDO_DAC0_PB_B;
+ break;
+
+ case S5P_TV_SD_O_ORDER_COMPONENT_RBG_PRPBY:
+ temp_reg |= SDO_DAC2_PR_R | SDO_DAC1_PB_B |
+ SDO_DAC0_Y_G;
+ break;
+
+ case S5P_TV_SD_O_ORDER_COMPONENT_BGR_PBYPR:
+ temp_reg |= SDO_DAC2_PB_B | SDO_DAC1_Y_G |
+ SDO_DAC0_PR_R;
+ break;
+
+ case S5P_TV_SD_O_ORDER_COMPONENT_BRG_PBPRY:
+ temp_reg |= SDO_DAC2_PB_B | SDO_DAC1_PR_R |
+ SDO_DAC0_Y_G;
+ break;
+
+ case S5P_TV_SD_O_ORDER_COMPONENT_GRB_YPRPB:
+ temp_reg |= SDO_DAC2_Y_G | SDO_DAC1_PR_R |
+ SDO_DAC0_PB_B;
+ break;
+
+ case S5P_TV_SD_O_ORDER_COMPONENT_GBR_YPBPR:
+ temp_reg |= SDO_DAC2_Y_G | SDO_DAC1_PB_B |
+ SDO_DAC0_PR_R;
+ break;
+
+ default:
+ SDPRINTK(" invalid order parameter(%d)\n\r", order);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ break;
+
+ case TVOUT_OUTPUT_COMPONENT_YPBPR_PROGRESSIVE:
+ temp_reg |= SDO_COMPONENT | SDO_YPBPR | SDO_PROGRESSIVE;
+
+ switch (order) {
+
+ case S5P_TV_SD_O_ORDER_COMPONENT_RGB_PRYPB:
+ temp_reg |= SDO_DAC2_PR_R | SDO_DAC1_Y_G |
+ SDO_DAC0_PB_B;
+ break;
+
+ case S5P_TV_SD_O_ORDER_COMPONENT_RBG_PRPBY:
+ temp_reg |= SDO_DAC2_PR_R | SDO_DAC1_PB_B |
+ SDO_DAC0_Y_G;
+ break;
+
+ case S5P_TV_SD_O_ORDER_COMPONENT_BGR_PBYPR:
+ temp_reg |= SDO_DAC2_PB_B | SDO_DAC1_Y_G |
+ SDO_DAC0_PR_R;
+ break;
+
+ case S5P_TV_SD_O_ORDER_COMPONENT_BRG_PBPRY:
+ temp_reg |= SDO_DAC2_PB_B | SDO_DAC1_PR_R |
+ SDO_DAC0_Y_G;
+ break;
+
+ case S5P_TV_SD_O_ORDER_COMPONENT_GRB_YPRPB:
+ temp_reg |= SDO_DAC2_Y_G | SDO_DAC1_PR_R |
+ SDO_DAC0_PB_B;
+ break;
+
+ case S5P_TV_SD_O_ORDER_COMPONENT_GBR_YPBPR:
+ temp_reg |= SDO_DAC2_Y_G | SDO_DAC1_PB_B |
+ SDO_DAC0_PR_R;
+ break;
+
+ default:
+ SDPRINTK(" invalid order parameter(%d)\n\r", order);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ break;
+
+ case TVOUT_OUTPUT_COMPONENT_RGB_PROGRESSIVE:
+ temp_reg |= SDO_COMPONENT | SDO_RGB | SDO_PROGRESSIVE;
+
+ switch (order) {
+
+ case S5P_TV_SD_O_ORDER_COMPONENT_RGB_PRYPB:
+ temp_reg |= SDO_DAC2_PR_R | SDO_DAC1_Y_G |
+ SDO_DAC0_PB_B;
+ break;
+
+ case S5P_TV_SD_O_ORDER_COMPONENT_RBG_PRPBY:
+ temp_reg |= SDO_DAC2_PR_R | SDO_DAC1_PB_B |
+ SDO_DAC0_Y_G;
+ break;
+
+ case S5P_TV_SD_O_ORDER_COMPONENT_BGR_PBYPR:
+ temp_reg |= SDO_DAC2_PB_B | SDO_DAC1_Y_G |
+ SDO_DAC0_PR_R;
+ break;
+
+ case S5P_TV_SD_O_ORDER_COMPONENT_BRG_PBPRY:
+ temp_reg |= SDO_DAC2_PB_B | SDO_DAC1_PR_R |
+ SDO_DAC0_Y_G;
+ break;
+
+ case S5P_TV_SD_O_ORDER_COMPONENT_GRB_YPRPB:
+ temp_reg |= SDO_DAC2_Y_G | SDO_DAC1_PR_R |
+ SDO_DAC0_PB_B;
+ break;
+
+ case S5P_TV_SD_O_ORDER_COMPONENT_GBR_YPBPR:
+ temp_reg |= SDO_DAC2_Y_G | SDO_DAC1_PB_B |
+ SDO_DAC0_PR_R;
+ break;
+
+ default:
+ SDPRINTK("invalid order parameter(%d)\n\r", order);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ break;
+
+ default:
+ SDPRINTK(" invalid out_mode parameter(%d)\n\r", out_mode);
+ return S5P_TV_SD_ERR_INVALID_PARAM;
+ break;
+ }
+
+ __s5p_sdout_init_oversampling_filter_coeff_default(out_mode);
+
+ writel(temp_reg, sdout_base + S5P_SDO_CONFIG);
+
+ SDPRINTK("0x%08x\n\r", readl(sdout_base + S5P_SDO_CONFIG));
+
+ return SDOUT_NO_ERROR;
+}
+
+/*
+* start - start functions are only called under stopping SDOUT
+*/
+void __s5p_sdout_start(void)
+{
+ SDPRINTK("()\n\r");
+
+ writel(SDO_TVOUT_CLOCK_ON, sdout_base + S5P_SDO_CLKCON);
+
+ SDPRINTK("0x%x\n\r", readl(sdout_base + S5P_SDO_CLKCON));
+}
+
+/*
+/ stop - stop functions are only called under running SDOUT
+*/
+void __s5p_sdout_stop(void)
+{
+ SDPRINTK("()\n\r");
+
+ mdelay(100);
+
+ writel(SDO_TVOUT_CLOCK_OFF, sdout_base + S5P_SDO_CLKCON);
+
+ SDPRINTK(" 0x%x)\n\r", readl(sdout_base + S5P_SDO_CLKCON));
+}
+
+/*
+* reset
+* - reset function
+*/
+void __s5p_sdout_sw_reset(bool active)
+{
+ SDPRINTK("%d\n\r", active);
+
+ if (active)
+ writel(readl(sdout_base + S5P_SDO_CLKCON) | SDO_TVOUT_SW_RESET,
+ sdout_base + S5P_SDO_CLKCON);
+ else
+ writel(readl(sdout_base + S5P_SDO_CLKCON) &
+ ~SDO_TVOUT_SW_RESET,
+ sdout_base + S5P_SDO_CLKCON);
+
+ SDPRINTK(" 0x%x\n\r", readl(sdout_base + S5P_SDO_CLKCON));
+}
+
+
+void __s5p_sdout_set_interrupt_enable(bool vsync_intr_en)
+{
+ SDPRINTK("%d)\n\r", vsync_intr_en);
+
+ if (vsync_intr_en)
+ writel(readl(sdout_base + S5P_SDO_IRQMASK) &
+ ~SDO_VSYNC_IRQ_DISABLE,
+ sdout_base + S5P_SDO_IRQMASK);
+ else
+ writel(readl(sdout_base + S5P_SDO_IRQMASK) |
+ SDO_VSYNC_IRQ_DISABLE,
+ sdout_base + S5P_SDO_IRQMASK);
+
+ SDPRINTK("0x%x)\n\r", readl(sdout_base + S5P_SDO_IRQMASK));
+}
+
+void __s5p_sdout_clear_interrupt_pending(void)
+{
+ SDPRINTK("0x%x\n\r", readl(sdout_base + S5P_SDO_IRQ));
+
+ writel(readl(sdout_base + S5P_SDO_IRQ) | SDO_VSYNC_IRQ_PEND,
+ sdout_base + S5P_SDO_IRQ);
+
+ SDPRINTK("0x%x\n\r", readl(sdout_base + S5P_SDO_IRQ));
+}
+
+bool __s5p_sdout_get_interrupt_pending(void)
+{
+ SDPRINTK(" 0x%x\n\r", readl(sdout_base + S5P_SDO_IRQ));
+
+ return (readl(sdout_base + S5P_SDO_IRQ) | SDO_VSYNC_IRQ_PEND) ? 1 : 0;
+}
+
+int __init __s5p_sdout_probe(struct platform_device *pdev, u32 res_num)
+{
+ struct resource *res;
+ size_t size;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, res_num);
+
+ if (res == NULL) {
+ dev_err(&pdev->dev,
+ "failed to get memory region resource\n");
+ goto error;
+ }
+
+ size = (res->end - res->start) + 1;
+
+ sdout_mem = request_mem_region(res->start, size, pdev->name);
+
+ if (sdout_mem == NULL) {
+ dev_err(&pdev->dev,
+ "failed to get memory region\n");
+ goto error;
+ }
+
+ sdout_base = ioremap(res->start, size);
+
+ if (sdout_base == NULL) {
+ dev_err(&pdev->dev,
+ "failed to ioremap address region\n");
+ goto error;
+
+ }
+
+ return 0;
+error:
+ return -ENOENT;
+
+}
+
+int __init __s5p_sdout_release(struct platform_device *pdev)
+{
+ iounmap(sdout_base);
+
+ /* remove memory region */
+ if (sdout_mem != NULL) {
+ if (release_resource(sdout_mem))
+ dev_err(&pdev->dev,
+ "Can't remove tvout drv !!\n");
+
+ kfree(sdout_mem);
+
+ sdout_mem = NULL;
+ }
+
+ return 0;
+}
diff --git a/drivers/media/video/samsung/tv20/s5pv210/tv_clock_s5pv210.c b/drivers/media/video/samsung/tv20/s5pv210/tv_clock_s5pv210.c
new file mode 100644
index 0000000..c0de6b3
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/s5pv210/tv_clock_s5pv210.c
@@ -0,0 +1,286 @@
+/* linux/drivers/media/video/samsung/tv20/s5pv210/tv_clock_s5pc110.c
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ * http://www.samsung.com/
+ *
+ * clock raw ftn file for Samsung TVOut driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+
+#include "tv_out_s5pv210.h"
+#include "regs/regs-clock_extra.h"
+
+#ifdef COFIG_TVOUT_RAW_DBG
+#define S5P_TVOUT_CLK_DEBUG 1
+#endif
+
+#ifdef S5P_TVOUT_CLK_DEBUG
+#define TVCLKPRINTK(fmt, args...) \
+ printk(KERN_INFO "\t\t[TVCLK] %s: " fmt, __func__ , ## args)
+#else
+#define TVCLKPRINTK(fmt, args...)
+#endif
+
+void __s5p_tv_clk_init_hpll(unsigned int lock_time,
+ bool vsel,
+ unsigned int mdiv,
+ unsigned int pdiv,
+ unsigned int sdiv)
+{
+ u32 temp;
+
+ TVCLKPRINTK("%d,%d,%d,%d\n\r", lock_time, mdiv, pdiv, sdiv);
+
+ temp = readl(S5P_VPLL_CON);
+
+ temp &= ~VPLL_ENABLE;
+
+ writel(temp, S5P_VPLL_CON);
+
+ temp = 0;
+
+ if (vsel)
+ temp |= VCO_FREQ_SEL;
+
+ temp |= VPLL_ENABLE;
+ temp |= MDIV(mdiv) | PDIV(pdiv) | SDIV(sdiv);
+
+ writel(VPLL_LOCKTIME(lock_time), S5P_VPLL_LOCK);
+ writel(temp, S5P_VPLL_CON);
+
+ while (!VPLL_LOCKED(readl(S5P_VPLL_CON)));
+
+ TVCLKPRINTK("0x%08x,0x%08x\n\r", readl(S5P_VPLL_LOCK), \
+ readl(S5P_VPLL_CON));
+}
+
+void __s5p_tv_clk_hpll_onoff(bool en)
+{
+}
+
+s5p_tv_clk_err __s5p_tv_clk_init_href(s5p_tv_clk_hpll_ref hpll_ref)
+{
+ return S5P_TV_CLK_ERR_NO_ERROR;
+}
+
+/* prevent hdmi hang-up when reboot */
+int __s5p_tv_clk_change_internal(void)
+{
+ u32 reg = readl(S5P_CLK_SRC1);
+ /* set to SCLK_DAC */
+ reg &= HDMI_SEL_MASK;
+ /* set to SCLK_PIXEL */
+ reg &= VMIXER_SEL_MASK;
+
+ writel(reg, S5P_CLK_SRC1);
+
+ return 0;
+}
+
+s5p_tv_clk_err __s5p_tv_clk_init_mout_hpll(s5p_tv_clk_mout_hpll mout_hpll)
+{
+ TVCLKPRINTK("(%d)\n\r", mout_hpll);
+
+ writel(readl(S5P_CLK_SRC1) | HDMI_SEL_HDMIPHY, S5P_CLK_SRC1);
+
+ TVCLKPRINTK("S5P_CLK_SRC1 :0x%08x\n", readl(S5P_CLK_SRC1));
+ return S5P_TV_CLK_ERR_NO_ERROR;
+}
+
+s5p_tv_clk_err __s5p_tv_clk_init_video_mixer(s5p_tv_clk_vmiexr_srcclk src_clk)
+{
+ switch (src_clk) {
+
+ /* for analog tv out 0:SCLK_DAC */
+ case TVOUT_CLK_VMIXER_SRCCLK_VCLK_54:
+ writel(readl(S5P_CLK_SRC1) & VMIXER_SEL_MASK, S5P_CLK_SRC1);
+ break;
+
+ /* for digital hdmi_phy 1: SCLK_HDMI */
+ case TVOUT_CLK_VMIXER_SRCCLK_MOUT_HPLL:
+ writel(readl(S5P_CLK_SRC1) | VMIXER_SEL_MOUT_VPLL, \
+ S5P_CLK_SRC1);
+ break;
+
+ default:
+ TVCLKPRINTK("[ERR] invalid src_clk parameter = %d\n", src_clk);
+ return S5P_TV_CLK_ERR_INVALID_PARAM;
+ break;
+ }
+
+ TVCLKPRINTK("S5P_CLK_SRC1 :0x%08x\n", readl(S5P_CLK_SRC1));
+
+ return S5P_TV_CLK_ERR_NO_ERROR;
+}
+
+void __s5p_tv_clk_init_hdmi_ratio(unsigned int clk_div)
+{
+ TVCLKPRINTK("(%d)\n\r", clk_div);
+
+ writel((readl(S5P_CLK_DIV1) & HDMI_DIV_RATIO_MASK) | \
+ HDMI_DIV_RATIO(clk_div), S5P_CLK_DIV1);
+
+ TVCLKPRINTK("(0x%08x)\n\r", readl(S5P_CLK_DIV3));
+}
+
+/*
+ * hclk gating
+ */
+
+/* VP */
+void __s5p_tv_clk_set_vp_clk_onoff(bool clk_on)
+{
+ /*
+ TVCLKPRINTK("VP hclk : %s\n\r", clk_on ? "on":"off");
+
+ if (clk_on)
+ bit_add_l(S5P_CLKGATE_IP1_VP, S5P_CLKGATE_IP1);
+ else
+ bit_del_l(S5P_CLKGATE_IP1_VP, S5P_CLKGATE_IP1);
+
+ TVCLKPRINTK("S5P_CLKGATE_MAIN1 :0x%08x\n\r", readl(S5P_CLKGATE_MAIN1));
+ */
+}
+
+/* MIXER */
+void __s5p_tv_clk_set_vmixer_hclk_onoff(bool clk_on)
+{
+ /*
+ TVCLKPRINTK("MIXER hclk : %s\n\r", clk_on ? "on":"off");
+
+ if (clk_on)
+ bit_add_l(S5P_CLKGATE_IP1_MIXER, S5P_CLKGATE_IP1);
+ else
+ bit_del_l(S5P_CLKGATE_IP1_MIXER, S5P_CLKGATE_IP1);
+
+ TVCLKPRINTK("S5P_CLKGATE_MAIN1 :0x%08x\n\r", readl(S5P_CLKGATE_MAIN1));
+ */
+}
+
+/* TVENC */
+void __s5p_tv_clk_set_sdout_hclk_onoff(bool clk_on)
+{
+ /*
+ TVCLKPRINTK("TVENC hclk : %s\n\r", clk_on ? "on":"off");
+
+ if (clk_on)
+ bit_add_l(S5P_CLKGATE_IP1_TVENC, S5P_CLKGATE_IP1);
+ else
+ bit_del_l(S5P_CLKGATE_IP1_TVENC, S5P_CLKGATE_IP1);
+ */
+}
+
+/* HDMI */
+void __s5p_tv_clk_set_hdmi_hclk_onoff(bool clk_on)
+{
+ /*
+ TVCLKPRINTK("HDMI hclk : %s\n\r", clk_on ? "on":"off");
+
+ if (clk_on) {
+ bit_add_l(S5P_CLKGATE_IP1_HDMI, S5P_CLKGATE_IP1);
+ bit_add_l(VMIXER_OUT_SEL_HDMI, S5P_MIXER_OUT_SEL);
+ } else
+ bit_del_l(S5P_CLKGATE_IP1_HDMI, S5P_CLKGATE_IP1);
+
+ TVCLKPRINTK("S5P_CLKGATE_PERI1 :0x%08x\n\r", readl(S5P_CLKGATE_PERI1));
+ TVCLKPRINTK("clk output is %s\n\r", readl(S5P_MIXER_OUT_SEL) ? "HDMI":"SDOUT");
+ */
+}
+
+/*
+ * sclk gating
+ */
+
+/* MIXER */
+void __s5p_tv_clk_set_vmixer_sclk_onoff(bool clk_on)
+{
+#if 0
+ TVCLKPRINTK("MIXER sclk : %s\n\r", clk_on ? "on":"off");
+
+ if (clk_on)
+ bit_add_l(CLK_SCLK_VMIXER_PASS, S5P_SCLKGATE0);
+ else
+ bit_del_l(CLK_SCLK_VMIXER_PASS, S5P_SCLKGATE0);
+
+ TVCLKPRINTK("S5P_SCLKGATE0 :0x%08x\n\r", readl(S5P_SCLKGATE0));
+#endif
+}
+
+/* TVENC */
+void __s5p_tv_clk_set_sdout_sclk_onoff(bool clk_on)
+{
+#if 0
+ TVCLKPRINTK("TVENC sclk : %s\n\r", clk_on ? "on":"off");
+
+ if (clk_on)
+ bit_add_l(CLK_SCLK_TV54_PASS | CLK_SCLK_VDAC54_PASS, S5P_SCLKGATE0);
+ else
+ bit_del_l(CLK_SCLK_TV54_PASS | CLK_SCLK_VDAC54_PASS, S5P_SCLKGATE0);
+
+ TVCLKPRINTK("S5P_SCLKGATE0 :0x%08x\n\r", readl(S5P_SCLKGATE0));
+#endif
+}
+
+/* HDMI */
+void __s5p_tv_clk_set_hdmi_sclk_onoff(bool clk_on)
+{
+#if 0
+ TVCLKPRINTK("HDMI sclk : %s\n\r", clk_on ? "on":"off");
+
+ if (clk_on)
+ bit_add_l(CLK_SCLK_HDMI_PASS, S5P_SCLKGATE0);
+ else
+ bit_del_l(CLK_SCLK_HDMI_PASS, S5P_SCLKGATE0);
+
+ TVCLKPRINTK("S5P_SCLKGATE0 :0x%08x\n\r", readl(S5P_SCLKGATE0));
+#endif
+}
+
+void __s5p_tv_clk_start(bool vp, bool sdout, bool hdmi)
+{
+ __s5p_tv_clk_set_vp_clk_onoff(vp);
+ __s5p_tv_clk_set_sdout_hclk_onoff(sdout);
+ __s5p_tv_clk_set_sdout_sclk_onoff(sdout);
+ __s5p_tv_clk_set_hdmi_hclk_onoff(hdmi);
+ __s5p_tv_clk_set_vmixer_hclk_onoff(true);
+ __s5p_tv_clk_set_vmixer_sclk_onoff(true);
+
+ if (hdmi)
+ __s5p_tv_clk_hpll_onoff(true);
+}
+
+void __s5p_tv_clk_stop(void)
+{
+ __s5p_tv_clk_set_sdout_sclk_onoff(false);
+ __s5p_tv_clk_set_sdout_hclk_onoff(false);
+ __s5p_tv_clk_set_hdmi_sclk_onoff(false);
+ __s5p_tv_clk_set_hdmi_hclk_onoff(false);
+ __s5p_tv_clk_set_vp_clk_onoff(false);
+ __s5p_tv_clk_set_vmixer_sclk_onoff(false);
+ __s5p_tv_clk_set_vmixer_hclk_onoff(false);
+ __s5p_tv_clk_hpll_onoff(false);
+}
+
+int __init __s5p_tvclk_probe(struct platform_device *pdev, u32 res_num)
+{
+ return 0;
+}
+
+int __init __s5p_tvclk_release(struct platform_device *pdev)
+{
+ return 0;
+}
diff --git a/drivers/media/video/samsung/tv20/s5pv210/tv_out_s5pv210.h b/drivers/media/video/samsung/tv20/s5pv210/tv_out_s5pv210.h
new file mode 100644
index 0000000..fd326dd
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/s5pv210/tv_out_s5pv210.h
@@ -0,0 +1,597 @@
+/* linux/drivers/media/video/samsung/tv20/s5pv210/tv_out_s5pv210.h
+ *
+ * tv out header file for Samsung TVOut driver
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+/* #define COFIG_TVOUT_RAW_DBG */
+
+
+#define HDMI_START_NUM 0x1000
+
+#define bit_add_l(val, addr) writel(readl(addr) | val, addr)
+#define bit_add_s(val, addr) writes(reads(addr) | val, addr)
+#define bit_add_b(val, addr) writeb(readb(addr) | val, addr)
+#define bit_del_l(val, addr) writel(readl(addr) & ~val, addr)
+#define bit_del_s(val, addr) writes(reads(addr) & ~val, addr)
+#define bit_del_b(val, addr) writeb(readb(addr) & ~val, addr)
+
+
+enum s5p_tv_audio_codec_type {
+ PCM = 1, AC3, MP3, WMA
+};
+
+enum s5p_endian_type {
+ TVOUT_LITTLE_ENDIAN_MODE = 0,
+ TVOUT_BIG_ENDIAN_MODE = 1
+};
+
+enum s5p_tv_disp_mode {
+ TVOUT_NTSC_M = 0,
+ TVOUT_PAL_BDGHI,
+ TVOUT_PAL_M,
+ TVOUT_PAL_N,
+ TVOUT_PAL_NC,
+ TVOUT_PAL_60,
+ TVOUT_NTSC_443,
+
+ TVOUT_480P_60_16_9 = HDMI_START_NUM,
+ TVOUT_480P_60_4_3,
+ TVOUT_480P_59,
+
+ TVOUT_576P_50_16_9,
+ TVOUT_576P_50_4_3,
+
+ TVOUT_720P_60,
+ TVOUT_720P_50,
+ TVOUT_720P_59,
+
+ TVOUT_1080P_60,
+ TVOUT_1080P_50,
+ TVOUT_1080P_59,
+ TVOUT_1080P_30,
+
+ TVOUT_1080I_60,
+ TVOUT_1080I_50,
+ TVOUT_1080I_59,
+};
+
+enum s5p_tv_o_mode {
+ TVOUT_OUTPUT_COMPOSITE,
+ TVOUT_OUTPUT_SVIDEO,
+ TVOUT_OUTPUT_COMPONENT_YPBPR_INERLACED,
+ TVOUT_OUTPUT_COMPONENT_YPBPR_PROGRESSIVE,
+ TVOUT_OUTPUT_COMPONENT_RGB_PROGRESSIVE,
+ TVOUT_OUTPUT_HDMI,
+ TVOUT_OUTPUT_HDMI_RGB,
+ TVOUT_OUTPUT_DVI
+};
+
+enum s5p_tv_pwr_err {
+ S5P_TV_PWR_ERR_NO_ERROR = 0,
+ S5P_TV_PWR_ERR_NOT_INIT_PARAMETERS_UNDER_RUNNING = 0x5000,
+ S5P_TV_PWR_ERR_NOT_SET_PARAMETERS_UNDER_STOP,
+ S5P_TV_PWR_ERR_INVALID_PARAM
+};
+
+enum s5p_tv_clk_err {
+ S5P_TV_CLK_ERR_NO_ERROR = 0,
+ S5P_TV_CLK_ERR_NOT_INIT_PARAMETERS_UNDER_RUNNING = 0x4000,
+ S5P_TV_CLK_ERR_NOT_SET_PARAMETERS_UNDER_STOP,
+ S5P_TV_CLK_ERR_INVALID_PARAM
+};
+
+enum s5p_tv_vp_err {
+ VPROC_NO_ERROR = 0,
+ S5P_TV_VP_ERR_NOT_INIT_PARAMETERS_UNDER_RUNNING = 0x2000,
+ S5P_TV_VP_ERR_NOT_SET_PARAMETERS_UNDER_STOP,
+ S5P_TV_VP_ERR_BASE_ADDRESS_MUST_DOUBLE_WORD_ALIGN,
+ S5P_TV_VP_ERR_NOT_UPDATE_FOR_ANOTHER_UPDATE,
+ S5P_TV_VP_ERR_INVALID_PARAM
+};
+
+enum s5p_tv_vmx_err {
+ VMIXER_NO_ERROR = 0,
+ S5P_TV_VMX_ERR_NOT_INIT_PARAMETERS_UNDER_RUNNING = 0x1000,
+ S5P_TV_VMX_ERR_NOT_SET_PARAMETERS_UNDER_STOP,
+ S5P_TV_VMX_ERR_BASE_ADDRESS_MUST_WORD_ALIGN,
+ S5P_TV_VMX_ERR_INVALID_PARAM
+};
+
+enum s5p_tv_vmx_color_fmt {
+ VM_DIRECT_RGB565 = 4,
+ VM_DIRECT_RGB1555 = 5,
+ VM_DIRECT_RGB4444 = 6,
+ VM_DIRECT_RGB8888 = 7
+};
+
+enum s5p_tv_sd_err {
+ SDOUT_NO_ERROR = 0,
+ S5P_TV_SD_ERR_NOT_INIT_PARAMETERS_UNDER_RUNNING = 0x3000,
+ S5P_TV_SD_ERR_NOT_SET_PARAMETERS_UNDER_STOP,
+ S5P_TV_SD_ERR_INVALID_PARAM
+};
+
+enum s5p_sd_order {
+ S5P_TV_SD_O_ORDER_COMPONENT_RGB_PRYPB,
+ S5P_TV_SD_O_ORDER_COMPONENT_RBG_PRPBY,
+ S5P_TV_SD_O_ORDER_COMPONENT_BGR_PBYPR,
+ S5P_TV_SD_O_ORDER_COMPONENT_BRG_PBPRY,
+ S5P_TV_SD_O_ORDER_COMPONENT_GRB_YPRPB,
+ S5P_TV_SD_O_ORDER_COMPONENT_GBR_YPBPR,
+ S5P_TV_SD_O_ORDER_COMPOSITE_CVBS_Y_C,
+ S5P_TV_SD_O_ORDER_COMPOSITE_CVBS_C_Y,
+ S5P_TV_SD_O_ORDER_COMPOSITE_Y_C_CVBS,
+ S5P_TV_SD_O_ORDER_COMPOSITE_Y_CVBS_C,
+ S5P_TV_SD_O_ORDER_COMPOSITE_C_CVBS_Y,
+ S5P_TV_SD_O_ORDER_COMPOSITE_C_Y_CVBS
+};
+
+enum s5p_tv_hdmi_err {
+ HDMI_NO_ERROR = 0,
+ S5P_TV_HDMI_ERR_NOT_INIT_PARAMETERS_UNDER_RUNNING = 0x6000,
+ S5P_TV_HDMI_ERR_NOT_SET_PARAMETERS_UNDER_STOP,
+ S5P_TV_HDMI_ERR_INVALID_PARAM
+};
+
+enum s5p_hdmi_transmit {
+ HDMI_DO_NOT_TANS = 0,
+ HDMI_TRANS_ONCE,
+ HDMI_TRANS_EVERY_SYNC
+};
+
+enum s5p_hdmi_audio_type {
+ HDMI_AUDIO_NO,
+ HDMI_AUDIO_PCM
+};
+
+
+enum s5p_tv_stda_err {
+ STDA_NO_ERROR = 0,
+ S5P_TV_STDA_ERR_NOT_INIT_PARAMETERS_UNDER_RUNNING = 0x7000,
+ S5P_TV_STDA_ERR_NOT_SET_PARAMETERS_UNDER_STOP,
+ S5P_TV_STDA_ERR_INVALID_PARAM
+};
+
+
+/*
+* enum
+*/
+
+enum s5p_tv_active_polarity {
+ TVOUT_POL_ACTIVE_LOW,
+ TVOUT_POL_ACTIVE_HIGH
+};
+
+enum s5p_yuv_fmt_component {
+ TVOUT_YUV_Y,
+ TVOUT_YUV_CB,
+ TVOUT_YUV_CR
+};
+
+enum s5p_tv_clk_hpll_ref {
+ S5P_TV_CLK_HPLL_REF_27M,
+ S5P_TV_CLK_HPLL_REF_SRCLK
+};
+
+enum s5p_tv_clk_mout_hpll {
+ S5P_TV_CLK_MOUT_HPLL_27M,
+ S5P_TV_CLK_MOUT_HPLL_FOUT_HPLL
+};
+
+enum s5p_tv_clk_vmiexr_srcclk {
+ TVOUT_CLK_VMIXER_SRCCLK_CLK27M,
+ TVOUT_CLK_VMIXER_SRCCLK_VCLK_54,
+ TVOUT_CLK_VMIXER_SRCCLK_MOUT_HPLL
+};
+
+enum s5p_vp_src_color {
+ VPROC_SRC_COLOR_NV12 = 0,
+ VPROC_SRC_COLOR_NV12IW = 1,
+ VPROC_SRC_COLOR_TILE_NV12 = 2,
+ VPROC_SRC_COLOR_TILE_NV12IW = 3
+};
+
+enum s5p_vp_pxl_rate {
+ VPROC_PIXEL_PER_RATE_1_1 = 0,
+ VPROC_PIXEL_PER_RATE_1_2 = 1,
+ VPROC_PIXEL_PER_RATE_1_3 = 2,
+ VPROC_PIXEL_PER_RATE_1_4 = 3
+};
+
+enum s5p_vp_sharpness_control {
+ VPROC_SHARPNESS_NO = 0,
+ VPROC_SHARPNESS_MIN = 1,
+ VPROC_SHARPNESS_MOD = 2,
+ VPROC_SHARPNESS_MAX = 3
+};
+
+enum s5p_vp_line_eq {
+ VProc_LINE_EQ_0 = 0,
+ VProc_LINE_EQ_1 = 1,
+ VProc_LINE_EQ_2 = 2,
+ VProc_LINE_EQ_3 = 3,
+ VProc_LINE_EQ_4 = 4,
+ VProc_LINE_EQ_5 = 5,
+ VProc_LINE_EQ_6 = 6,
+ VProc_LINE_EQ_7 = 7
+};
+
+enum s5p_vp_mem_mode {
+ VPROC_LINEAR_MODE,
+ VPROC_2D_TILE_MODE
+};
+
+enum s5p_vp_chroma_expansion {
+ VPROC_USING_C_TOP,
+ VPROC_USING_C_TOP_BOTTOM
+};
+
+enum s5p_vp_filed_id_toggle {
+ S5P_TV_VP_FILED_ID_TOGGLE_USER,
+ S5P_TV_VP_FILED_ID_TOGGLE_VSYNC
+};
+
+enum s5p_vp_field {
+ VPROC_TOP_FIELD,
+ VPROC_BOTTOM_FIELD
+};
+
+enum s5p_vp_poly_coeff {
+ VPROC_POLY8_Y0_LL = 0,
+ VPROC_POLY8_Y0_LH,
+ VPROC_POLY8_Y0_HL,
+ VPROC_POLY8_Y0_HH,
+ VPROC_POLY8_Y1_LL,
+ VPROC_POLY8_Y1_LH,
+ VPROC_POLY8_Y1_HL,
+ VPROC_POLY8_Y1_HH,
+ VPROC_POLY8_Y2_LL,
+ VPROC_POLY8_Y2_LH,
+ VPROC_POLY8_Y2_HL,
+ VPROC_POLY8_Y2_HH,
+ VPROC_POLY8_Y3_LL,
+ VPROC_POLY8_Y3_LH,
+ VPROC_POLY8_Y3_HL,
+ VPROC_POLY8_Y3_HH,
+ VPROC_POLY4_Y0_LL = 32,
+ VPROC_POLY4_Y0_LH,
+ VPROC_POLY4_Y0_HL,
+ VPROC_POLY4_Y0_HH,
+ VPROC_POLY4_Y1_LL,
+ VPROC_POLY4_Y1_LH,
+ VPROC_POLY4_Y1_HL,
+ VPROC_POLY4_Y1_HH,
+ VPROC_POLY4_Y2_LL,
+ VPROC_POLY4_Y2_LH,
+ VPROC_POLY4_Y2_HL,
+ VPROC_POLY4_Y2_HH,
+ VPROC_POLY4_Y3_LL,
+ VPROC_POLY4_Y3_LH,
+ VPROC_POLY4_Y3_HL,
+ VPROC_POLY4_Y3_HH,
+ VPROC_POLY4_C0_LL,
+ VPROC_POLY4_C0_LH,
+ VPROC_POLY4_C0_HL,
+ VPROC_POLY4_C0_HH,
+ VPROC_POLY4_C1_LL,
+ VPROC_POLY4_C1_LH,
+ VPROC_POLY4_C1_HL,
+ VPROC_POLY4_C1_HH
+};
+
+enum s5p_vp_csc_coeff {
+ VPROC_CSC_Y2Y_COEF = 0,
+ VPROC_CSC_CB2Y_COEF,
+ VPROC_CSC_CR2Y_COEF,
+ VPROC_CSC_Y2CB_COEF,
+ VPROC_CSC_CB2CB_COEF,
+ VPROC_CSC_CR2CB_COEF,
+ VPROC_CSC_Y2CR_COEF,
+ VPROC_CSC_CB2CR_COEF,
+ VPROC_CSC_CR2CR_COEF
+};
+
+enum s5p_vp_csc_type {
+ VPROC_CSC_SD_HD,
+ VPROC_CSC_HD_SD
+};
+
+enum s5p_tv_vp_filter_h_pp {
+ /* Don't change the order and the value */
+ VPROC_PP_H_NORMAL = 0,
+ VPROC_PP_H_8_9, /* 720 to 640 */
+ VPROC_PP_H_1_2,
+ VPROC_PP_H_1_3,
+ VPROC_PP_H_1_4
+};
+
+enum s5p_tv_vp_filter_v_pp {
+ /* Don't change the order and the value */
+ VPROC_PP_V_NORMAL = 0,
+ VPROC_PP_V_5_6, /* PAL to NTSC */
+ VPROC_PP_V_3_4,
+ VPROC_PP_V_1_2,
+ VPROC_PP_V_1_3,
+ VPROC_PP_V_1_4
+};
+
+enum s5p_vmx_burst_mode {
+ VM_BURST_8 = 0,
+ VM_BURST_16 = 1
+};
+
+enum s5p_tv_vmx_scan_mode {
+ VMIXER_INTERLACED_MODE = 0,
+ VMIXER_PROGRESSIVE_MODE = 1
+};
+
+enum s5p_tv_vmx_layer {
+ VM_VIDEO_LAYER = 2,
+ VM_GPR0_LAYER = 0,
+ VM_GPR1_LAYER = 1
+};
+
+enum s5p_tv_vmx_bg_color_num {
+ VMIXER_BG_COLOR_0 = 0,
+ VMIXER_BG_COLOR_1 = 1,
+ VMIXER_BG_COLOR_2 = 2
+};
+
+enum s5p_tv_coef_y_mode {
+ VMIXER_COEF_Y_NARROW = 0,
+ VMIXER_COEF_Y_WIDE = 1
+};
+
+enum s5p_tv_vmx_csc_type {
+ VMIXER_CSC_RGB_TO_YUV601_LR,
+ VMIXER_CSC_RGB_TO_YUV601_FR,
+ VMIXER_CSC_RGB_TO_YUV709_LR,
+ VMIXER_CSC_RGB_TO_YUV709_FR
+};
+
+enum s5p_tv_vmx_rgb {
+ RGB601_0_255,
+ RGB601_16_235,
+ RGB709_0_255,
+ RGB709_16_235
+};
+
+enum s5p_tv_vmx_out_type {
+ MX_YUV444,
+ MX_RGB888
+};
+
+enum s5p_sd_level {
+ S5P_TV_SD_LEVEL_0IRE,
+ S5P_TV_SD_LEVEL_75IRE
+};
+
+enum s5p_sd_vsync_ratio {
+ SDOUT_VTOS_RATIO_10_4,
+ SDOUT_VTOS_RATIO_7_3
+};
+
+enum s5p_sd_sync_sig_pin {
+ SDOUT_SYNC_SIG_NO,
+ SDOUT_SYNC_SIG_YG,
+ SDOUT_SYNC_SIG_ALL
+};
+
+enum s5p_sd_closed_caption_type {
+ SDOUT_NO_INS,
+ SDOUT_INS_1,
+ SDOUT_INS_2,
+ SDOUT_INS_OTHERS
+};
+
+enum s5p_sd_channel_sel {
+ SDOUT_CHANNEL_0 = 0,
+ SDOUT_CHANNEL_1 = 1,
+ SDOUT_CHANNEL_2 = 2
+};
+
+enum s5p_sd_vesa_rgb_sync_type {
+ SDOUT_VESA_RGB_SYNC_COMPOSITE,
+ SDOUT_VESA_RGB_SYNC_SEPARATE
+};
+
+enum s5p_sd_525_copy_permit {
+ SDO_525_COPY_PERMIT,
+ SDO_525_ONECOPY_PERMIT,
+ SDO_525_NOCOPY_PERMIT
+};
+
+enum s5p_sd_525_mv_psp {
+ SDO_525_MV_PSP_OFF,
+ SDO_525_MV_PSP_ON_2LINE_BURST,
+ SDO_525_MV_PSP_ON_BURST_OFF,
+ SDO_525_MV_PSP_ON_4LINE_BURST,
+};
+
+enum s5p_sd_525_copy_info {
+ SDO_525_COPY_INFO,
+ SDO_525_DEFAULT,
+};
+
+enum s5p_sd_525_aspect_ratio {
+ SDO_525_4_3_NORMAL,
+ SDO_525_16_9_ANAMORPIC,
+ SDO_525_4_3_LETTERBOX
+};
+
+enum s5p_sd_625_subtitles {
+ SDO_625_NO_OPEN_SUBTITLES,
+ SDO_625_INACT_OPEN_SUBTITLES,
+ SDO_625_OUTACT_OPEN_SUBTITLES
+};
+
+enum s5p_sd_625_camera_film {
+ SDO_625_CAMERA,
+ SDO_625_FILM
+};
+
+enum s5p_sd_625_color_encoding {
+ SDO_625_NORMAL_PAL,
+ SDO_625_MOTION_ADAPTIVE_COLORPLUS
+};
+
+enum s5p_sd_625_aspect_ratio {
+ SDO_625_4_3_FULL_576,
+ SDO_625_14_9_LETTERBOX_CENTER_504,
+ SDO_625_14_9_LETTERBOX_TOP_504,
+ SDO_625_16_9_LETTERBOX_CENTER_430,
+ SDO_625_16_9_LETTERBOX_TOP_430,
+ SDO_625_16_9_LETTERBOX_CENTER,
+ SDO_625_14_9_FULL_CENTER_576,
+ SDO_625_16_9_ANAMORPIC_576
+};
+
+enum s5p_tv_hdmi_csc_type {
+ HDMI_CSC_YUV601_TO_RGB_LR,
+ HDMI_CSC_YUV601_TO_RGB_FR,
+ HDMI_CSC_YUV709_TO_RGB_LR,
+ HDMI_CSC_YUV709_TO_RGB_FR,
+ HDMI_CSC_YUV601_TO_YUV709,
+ HDMI_CSC_RGB_FR_TO_RGB_LR,
+ HDMI_CSC_RGB_FR_TO_YUV601,
+ HDMI_CSC_RGB_FR_TO_YUV709,
+ HDMI_BYPASS
+};
+
+/*
+ * Color Depth for HDMI HW (settings and GCP packet),
+ * EDID and PHY HW
+ */
+enum s5p_hdmi_color_depth {
+ HDMI_CD_48,
+ HDMI_CD_36,
+ HDMI_CD_30,
+ HDMI_CD_24
+};
+
+enum phy_freq {
+ ePHY_FREQ_25_200,
+ ePHY_FREQ_25_175,
+ ePHY_FREQ_27,
+ ePHY_FREQ_27_027,
+ ePHY_FREQ_54,
+ ePHY_FREQ_54_054,
+ ePHY_FREQ_74_250,
+ ePHY_FREQ_74_176,
+ ePHY_FREQ_148_500,
+ ePHY_FREQ_148_352,
+ ePHY_FREQ_108_108,
+ ePHY_FREQ_72,
+ ePHY_FREQ_25,
+ ePHY_FREQ_65,
+ ePHY_FREQ_108,
+ ePHY_FREQ_162
+};
+
+/* video format for HDMI HW (timings and AVI) and EDID */
+enum s5p_hdmi_v_fmt {
+ v640x480p_60Hz = 0,
+ v720x480p_60Hz,
+ v1280x720p_60Hz,
+ v1920x1080i_60Hz,
+ v720x480i_60Hz,
+ v720x240p_60Hz,
+ v2880x480i_60Hz,
+ v2880x240p_60Hz,
+ v1440x480p_60Hz,
+ v1920x1080p_60Hz,
+ v720x576p_50Hz,
+ v1280x720p_50Hz,
+ v1920x1080i_50Hz,
+ v720x576i_50Hz,
+ v720x288p_50Hz,
+ v2880x576i_50Hz,
+ v2880x288p_50Hz,
+ v1440x576p_50Hz,
+ v1920x1080p_50Hz,
+ v1920x1080p_24Hz,
+ v1920x1080p_25Hz,
+ v1920x1080p_30Hz,
+ v2880x480p_60Hz,
+ v2880x576p_50Hz,
+ v1920x1080i_50Hz_1250,
+ v1920x1080i_100Hz,
+ v1280x720p_100Hz,
+ v720x576p_100Hz,
+ v720x576i_100Hz,
+ v1920x1080i_120Hz,
+ v1280x720p_120Hz,
+ v720x480p_120Hz,
+ v720x480i_120Hz,
+ v720x576p_200Hz,
+ v720x576i_200Hz,
+ v720x480p_240Hz,
+ v720x480i_240Hz,
+ v720x480p_59Hz,
+ v1280x720p_59Hz,
+ v1920x1080i_59Hz,
+ v1920x1080p_59Hz,
+
+};
+
+
+enum s5p_tv_hdmi_disp_mode {
+ S5P_TV_HDMI_DISP_MODE_480P_60 = 0,
+ S5P_TV_HDMI_DISP_MODE_576P_50 = 1,
+ S5P_TV_HDMI_DISP_MODE_720P_60 = 2,
+ S5P_TV_HDMI_DISP_MODE_720P_50 = 3,
+ S5P_TV_HDMI_DISP_MODE_1080I_60 = 4,
+ S5P_TV_HDMI_DISP_MODE_1080I_50 = 5,
+ S5P_TV_HDMI_DISP_MODE_VGA_60 = 6,
+ S5P_TV_HDMI_DISP_MODE_1080P_60 = 7,
+ S5P_TV_HDMI_DISP_MODE_1080P_50 = 8,
+ S5P_TV_HDMI_DISP_MODE_NUM = 9
+};
+
+/* pixel aspect ratio for HDMI HW (AVI packet and EDID) */
+enum s5p_tv_hdmi_pxl_aspect {
+ HDMI_PIXEL_RATIO_4_3,
+ HDMI_PIXEL_RATIO_16_9
+};
+
+enum s5p_tv_hdmi_interrrupt {
+ HDMI_IRQ_PIN_POLAR_CTL = 7,
+ HDMI_IRQ_GLOBAL = 6,
+ HDMI_IRQ_I2S = 5,
+ HDMI_IRQ_CEC = 4,
+ HDMI_IRQ_HPD_PLUG = 3,
+ HDMI_IRQ_HPD_UNPLUG = 2,
+ HDMI_IRQ_SPDIF = 1,
+ HDMI_IRQ_HDCP = 0
+};
+
+typedef int (*hdmi_isr)(int irq);
+
+
+extern int s5p_hdmi_register_isr(hdmi_isr isr, u8 irq_num);
+extern void s5p_hdmi_enable_interrupts(enum s5p_tv_hdmi_interrrupt intr);
+extern void s5p_hdmi_disable_interrupts(enum s5p_tv_hdmi_interrrupt intr);
+extern void s5p_hdmi_hpd_gen(void);
+extern u8 s5p_hdmi_get_interrupts(void);
+extern u8 s5p_hdmi_get_enabled_interrupt(void);
+extern int s5p_hdmi_set_dvi(bool en);
+extern void s5p_hdmi_mute_en(bool en);
+
+extern void __iomem *hdmi_base;
+extern bool __s5p_start_hdcp(void);
+extern bool __s5p_stop_hdcp(void);
+extern void __s5p_init_hdcp(bool hpd_status, struct i2c_client *ddc_port);
+
+ /* 0 - hdcp stopped, 1 - hdcp started, 2 - hdcp reset */
+extern u8 hdcp_protocol_status;
+
+void __s5p_hdmi_video_set_bluescreen(bool en, u8 cb, u8 y_g, u8 cr_r);
diff --git a/drivers/media/video/samsung/tv20/s5pv210/tv_power_s5pv210.c b/drivers/media/video/samsung/tv20/s5pv210/tv_power_s5pv210.c
new file mode 100644
index 0000000..4276df2
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/s5pv210/tv_power_s5pv210.c
@@ -0,0 +1,133 @@
+/* linux/drivers/media/video/samsung/tv20/s5pv210/tv_power_s5pv210.c
+ *
+ * power raw ftn file for Samsung TVOut driver
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <linux/regulator/consumer.h>
+
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+
+#include "../s5p_tv.h"
+
+
+#if defined USE_POWERCON_FUNCTION
+#undef USE_POWERCON_FUNCTION
+#endif
+
+#ifdef COFIG_TVOUT_RAW_DBG
+#define S5P_TVOUT_PM_DEBUG 1
+#endif
+
+#ifdef S5P_TVOUT_PM_DEBUG
+#define TVPMPRINTK(fmt, args...) \
+ printk(KERN_INFO "\t\t[TVPM] %s: " fmt, __func__ , ## args)
+#else
+#define TVPMPRINTK(fmt, args...)
+#endif
+
+/* NORMAL_CFG */
+#define TVPWR_SUBSYSTEM_ACTIVE (1<<4)
+#define TVPWR_SUBSYSTEM_LP (0<<4)
+
+/* MTC_STABLE */
+#define TVPWR_MTC_COUNTER_CLEAR(a) (((~0xf)<<16)&a)
+#define TVPWR_MTC_COUNTER_SET(a) ((0xf&a)<<16)
+
+/* BLK_PWR_STAT */
+#define TVPWR_TV_BLOCK_STATUS(a) ((0x1<<4)&a)
+
+static unsigned short g_dacPwrOn;
+extern struct s5p_tv_status s5ptv_status;
+
+void __s5p_tv_power_init_mtc_stable_counter(unsigned int value)
+{
+ TVPMPRINTK("(%d)\n\r", value);
+
+ writel(TVPWR_MTC_COUNTER_CLEAR((readl(S5P_MTC_STABLE) |
+ TVPWR_MTC_COUNTER_SET(value))),
+ S5P_MTC_STABLE);
+
+ TVPMPRINTK("(0x%08x)\n\r", readl(S5P_MTC_STABLE));
+}
+
+void __s5p_tv_powerinitialize_dac_onoff(bool on)
+{
+ TVPMPRINTK("(%d)\n\r", on);
+
+ g_dacPwrOn = on;
+
+ TVPMPRINTK("(0x%08x)\n\r", g_dacPwrOn);
+}
+
+void __s5p_tv_powerset_dac_onoff(bool on)
+{
+ TVPMPRINTK("(%d)\n\r", on);
+
+ if (on) {
+ regulator_enable(s5ptv_status.tv_tvout);
+ writel(S5P_DAC_ENABLE, S5P_DAC_CONTROL);
+ } else {
+ writel(S5P_DAC_DISABLE, S5P_DAC_CONTROL);
+ regulator_disable(s5ptv_status.tv_tvout);
+ }
+
+ TVPMPRINTK("(0x%08x)\n\r", readl(S5P_DAC_CONTROL));
+}
+
+
+bool __s5p_tv_power_get_power_status(void)
+{
+ TVPMPRINTK("(0x%08x)\n\r", readl(S5P_BLK_PWR_STAT));
+
+
+ return TVPWR_TV_BLOCK_STATUS(readl(S5P_BLK_PWR_STAT)) ? 1 : 0;
+}
+
+bool __s5p_tv_power_get_dac_power_status(void)
+{
+ TVPMPRINTK("()\n\r");
+
+ TVPMPRINTK("(0x%08x)\n\r", readl(S5P_DAC_CONTROL));
+
+ return (readl(S5P_DAC_CONTROL) & S5P_DAC_ENABLE) ? 1 : 0;
+}
+
+
+void __s5p_tv_poweron(void)
+{
+ TVPMPRINTK("0x%08x\n\r", readl(S3C_VA_SYS + 0xE804));
+
+ writel(readl(S3C_VA_SYS + 0xE804) | 0x1, S3C_VA_SYS + 0xE804);
+
+ if (regulator_enable(s5ptv_status.tv_regulator))
+ pr_err("%s : failed to turn tv-power-domain on\n", __func__);
+
+ TVPMPRINTK("0x%08x, 0x%08x)\n\r", readl(S5P_NORMAL_CFG),
+ readl(S5P_BLK_PWR_STAT));
+}
+
+
+void __s5p_tv_poweroff(void)
+{
+ TVPMPRINTK("()\n\r");
+
+ __s5p_tv_powerset_dac_onoff(0);
+
+ if (regulator_disable(s5ptv_status.tv_regulator))
+ pr_err("%s : failed to turn tv-power-domain off\n", __func__);
+
+ TVPMPRINTK("0x%08x, 0x%08x)\n\r", readl(S5P_NORMAL_CFG),
+ readl(S5P_BLK_PWR_STAT));
+}
diff --git a/drivers/media/video/samsung/tv20/s5pv210/vmixer_s5pv210.c b/drivers/media/video/samsung/tv20/s5pv210/vmixer_s5pv210.c
new file mode 100644
index 0000000..b38f57a
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/s5pv210/vmixer_s5pv210.c
@@ -0,0 +1,1256 @@
+/* linux/drivers/media/video/samsung/tv20/s5pv210/vmixer_s5pv210.c
+ *
+ * Mixer raw ftn file for Samsung TVOut driver
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <plat/clock.h>
+
+/* #include <mach/regs-vmx.h> */
+
+#include "tv_out_s5pv210.h"
+
+#include "regs/regs-vmx.h"
+#ifdef COFIG_TVOUT_RAW_DBG
+#define S5P_MXR_DEBUG 1
+#endif
+
+#ifdef S5P_MXR_DEBUG
+#define VMPRINTK(fmt, args...) \
+ printk(KERN_INFO "\t\t[VM] %s: " fmt, __func__ , ## args)
+#else
+#define VMPRINTK(fmt, args...)
+#endif
+
+static struct resource *mixer_mem;
+void __iomem *mixer_base;
+
+/*
+*set - set functions are only called under running vmixer
+*/
+
+enum s5p_tv_vmx_err __s5p_vm_set_layer_show(
+ enum s5p_tv_vmx_layer layer, bool show)
+{
+ u32 mxr_config;
+
+ VMPRINTK("%d, %d\n\r", layer, show);
+
+ switch (layer) {
+
+ case VM_VIDEO_LAYER:
+ mxr_config = (show) ?
+ (readl(mixer_base + S5P_MXR_CFG) |
+ S5P_MXR_VIDEO_LAYER_SHOW) :
+ (readl(mixer_base + S5P_MXR_CFG) &
+ ~S5P_MXR_VIDEO_LAYER_SHOW);
+ break;
+
+ case VM_GPR0_LAYER:
+ mxr_config = (show) ?
+ (readl(mixer_base + S5P_MXR_CFG) |
+ S5P_MXR_GRAPHIC0_LAYER_SHOW) :
+ (readl(mixer_base + S5P_MXR_CFG) &
+ ~S5P_MXR_GRAPHIC0_LAYER_SHOW);
+ break;
+
+ case VM_GPR1_LAYER:
+ mxr_config = (show) ?
+ (readl(mixer_base + S5P_MXR_CFG) |
+ S5P_MXR_GRAPHIC1_LAYER_SHOW) :
+ (readl(mixer_base + S5P_MXR_CFG) &
+ ~S5P_MXR_GRAPHIC1_LAYER_SHOW);
+ break;
+
+ default:
+ VMPRINTK(" invalid layer parameter = %d\n\r", layer);
+ return S5P_TV_VMX_ERR_INVALID_PARAM;
+ break;
+ }
+
+ writel(mxr_config, mixer_base + S5P_MXR_CFG);
+
+ VMPRINTK("0x%x\n\r", readl(mixer_base + S5P_MXR_CFG));
+
+ return VMIXER_NO_ERROR;
+}
+
+enum s5p_tv_vmx_err __s5p_vm_set_layer_priority(enum s5p_tv_vmx_layer layer,
+ u32 priority)
+{
+ u32 layer_cfg;
+
+ VMPRINTK("%d, %d\n\r", layer, priority);
+
+ switch (layer) {
+
+ case VM_VIDEO_LAYER:
+ layer_cfg = S5P_MXR_VP_LAYER_PRIORITY_CLEAR(
+ readl(mixer_base + S5P_MXR_LAYER_CFG)) |
+ S5P_MXR_VP_LAYER_PRIORITY(priority);
+ break;
+
+ case VM_GPR0_LAYER:
+ layer_cfg = S5P_MXR_GRP0_LAYER_PRIORITY_CLEAR(
+ readl(mixer_base + S5P_MXR_LAYER_CFG)) |
+ S5P_MXR_GRP0_LAYER_PRIORITY(priority);
+ break;
+
+ case VM_GPR1_LAYER:
+ layer_cfg = S5P_MXR_GRP1_LAYER_PRIORITY_CLEAR(
+ readl(mixer_base + S5P_MXR_LAYER_CFG)) |
+ S5P_MXR_GRP1_LAYER_PRIORITY(priority);
+ break;
+
+ default:
+ VMPRINTK(" invalid layer parameter = %d\n\r", layer);
+ return S5P_TV_VMX_ERR_INVALID_PARAM;
+ break;
+ }
+
+ writel(layer_cfg, mixer_base + S5P_MXR_LAYER_CFG);
+
+ return VMIXER_NO_ERROR;
+}
+
+enum s5p_tv_vmx_err __s5p_vm_set_win_blend(enum s5p_tv_vmx_layer layer,
+ bool enable)
+{
+ u32 temp_reg;
+ VMPRINTK("%d, %d\n\r", layer, enable);
+
+ switch (layer) {
+
+ case VM_VIDEO_LAYER:
+ temp_reg = readl(mixer_base + S5P_MXR_VIDEO_CFG)
+ & (~S5P_MXR_VP_BLEND_ENABLE) ;
+
+ if (enable)
+ temp_reg |= S5P_MXR_VP_BLEND_ENABLE;
+ else
+ temp_reg |= S5P_MXR_VP_BLEND_DISABLE;
+
+ writel(temp_reg, mixer_base + S5P_MXR_VIDEO_CFG);
+
+ break;
+
+ case VM_GPR0_LAYER:
+ temp_reg = readl(mixer_base + S5P_MXR_GRAPHIC0_CFG)
+ & (~S5P_MXR_WIN_BLEND_ENABLE) ;
+
+ if (enable)
+ temp_reg |= S5P_MXR_WIN_BLEND_ENABLE;
+ else
+ temp_reg |= S5P_MXR_WIN_BLEND_DISABLE;
+
+ writel(temp_reg, mixer_base + S5P_MXR_GRAPHIC0_CFG);
+
+ break;
+
+ case VM_GPR1_LAYER:
+ temp_reg = readl(mixer_base + S5P_MXR_GRAPHIC1_CFG)
+ & (~S5P_MXR_WIN_BLEND_ENABLE) ;
+
+ if (enable)
+ temp_reg |= S5P_MXR_WIN_BLEND_ENABLE;
+ else
+ temp_reg |= S5P_MXR_WIN_BLEND_DISABLE;
+
+ writel(temp_reg, mixer_base + S5P_MXR_GRAPHIC1_CFG);
+
+ break;
+
+ default:
+ VMPRINTK(" invalid layer parameter = %d\n\r", layer);
+
+ return S5P_TV_VMX_ERR_INVALID_PARAM;
+
+ break;
+ }
+
+ VMPRINTK("0x08%x\n\r", readl(mixer_base + S5P_MXR_VIDEO_CFG));
+ VMPRINTK("0x08%x\n\r", readl(mixer_base + S5P_MXR_GRAPHIC0_CFG));
+ VMPRINTK("0x08%x\n\r", readl(mixer_base + S5P_MXR_GRAPHIC1_CFG));
+
+ return VMIXER_NO_ERROR;
+}
+
+
+enum s5p_tv_vmx_err __s5p_vm_set_layer_alpha(enum s5p_tv_vmx_layer layer,
+ u32 alpha)
+{
+ u32 temp_reg;
+ VMPRINTK("%d, %d\n\r", layer, alpha);
+
+ switch (layer) {
+
+ case VM_VIDEO_LAYER:
+ temp_reg = readl(mixer_base + S5P_MXR_VIDEO_CFG)
+ & (~S5P_MXR_ALPHA) ;
+ temp_reg |= S5P_MXR_VP_ALPHA_VALUE(alpha);
+ writel(temp_reg, mixer_base + S5P_MXR_VIDEO_CFG);
+ break;
+
+ case VM_GPR0_LAYER:
+ temp_reg = readl(mixer_base + S5P_MXR_GRAPHIC0_CFG)
+ & (~S5P_MXR_ALPHA) ;
+ temp_reg |= S5P_MXR_GRP_ALPHA_VALUE(alpha);
+ writel(temp_reg, mixer_base + S5P_MXR_GRAPHIC0_CFG);
+ break;
+
+ case VM_GPR1_LAYER:
+ temp_reg = readl(mixer_base + S5P_MXR_GRAPHIC1_CFG)
+ & (~S5P_MXR_ALPHA) ;
+ temp_reg |= S5P_MXR_GRP_ALPHA_VALUE(alpha);
+ writel(temp_reg, mixer_base + S5P_MXR_GRAPHIC1_CFG);
+ break;
+
+ default:
+ VMPRINTK(" invalid layer parameter = %d\n\r", layer);
+ return S5P_TV_VMX_ERR_INVALID_PARAM;
+ break;
+ }
+
+ VMPRINTK("0x08%x\n\r", readl(mixer_base + S5P_MXR_VIDEO_CFG));
+ VMPRINTK("0x08%x\n\r", readl(mixer_base + S5P_MXR_GRAPHIC0_CFG));
+ VMPRINTK("0x08%x\n\r", readl(mixer_base + S5P_MXR_GRAPHIC1_CFG));
+
+ return VMIXER_NO_ERROR;
+}
+
+
+enum s5p_tv_vmx_err __s5p_vm_set_grp_base_address(enum s5p_tv_vmx_layer layer,
+ u32 base_addr)
+{
+ VMPRINTK("%d, 0x%x\n\r", layer, base_addr);
+
+ if (S5P_MXR_GRP_ADDR_ILLEGAL(base_addr)) {
+ VMPRINTK(" address is not word align = %d\n\r", base_addr);
+ return S5P_TV_VMX_ERR_BASE_ADDRESS_MUST_WORD_ALIGN;
+ }
+
+ switch (layer) {
+
+ case VM_GPR0_LAYER:
+ writel(S5P_MXR_GPR_BASE(base_addr),
+ mixer_base + S5P_MXR_GRAPHIC0_BASE);
+ VMPRINTK("0x%x\n\r",
+ readl(mixer_base + S5P_MXR_GRAPHIC0_BASE));
+ break;
+
+ case VM_GPR1_LAYER:
+ writel(S5P_MXR_GPR_BASE(base_addr),
+ mixer_base + S5P_MXR_GRAPHIC1_BASE);
+ VMPRINTK("0x%x\n\r",
+ readl(mixer_base + S5P_MXR_GRAPHIC1_BASE));
+ break;
+
+ default:
+ VMPRINTK(" invalid layer parameter = %d\n\r", layer);
+ return S5P_TV_VMX_ERR_INVALID_PARAM;
+ break;
+ }
+
+ return VMIXER_NO_ERROR;
+}
+
+enum s5p_tv_vmx_err __s5p_vm_set_grp_layer_position(enum s5p_tv_vmx_layer layer,
+ u32 dst_offs_x, u32 dst_offs_y)
+{
+ VMPRINTK("%d, %d, %d)\n\r", layer, dst_offs_x, dst_offs_y);
+
+ switch (layer) {
+
+ case VM_GPR0_LAYER:
+ writel(S5P_MXR_GRP_DESTX(dst_offs_x) |
+ S5P_MXR_GRP_DESTY(dst_offs_y),
+ mixer_base + S5P_MXR_GRAPHIC0_DXY);
+ VMPRINTK("0x%x\n\r",
+ readl(mixer_base + S5P_MXR_GRAPHIC0_DXY));
+ break;
+
+ case VM_GPR1_LAYER:
+ writel(S5P_MXR_GRP_DESTX(dst_offs_x) |
+ S5P_MXR_GRP_DESTY(dst_offs_y),
+ mixer_base + S5P_MXR_GRAPHIC1_DXY);
+ VMPRINTK("0x%x\n\r",
+ readl(mixer_base + S5P_MXR_GRAPHIC1_DXY));
+ break;
+
+ default:
+ VMPRINTK("invalid layer parameter = %d\n\r", layer);
+ return S5P_TV_VMX_ERR_INVALID_PARAM;
+ break;
+ }
+
+ return VMIXER_NO_ERROR;
+}
+
+enum s5p_tv_vmx_err __s5p_vm_set_grp_layer_size(enum s5p_tv_vmx_layer layer,
+ u32 span,
+ u32 width,
+ u32 height,
+ u32 src_offs_x,
+ u32 src_offs_y)
+{
+ VMPRINTK("%d, %d, %d, %d, %d, %d)\n\r", layer, span, width, height,
+ src_offs_x, src_offs_y);
+
+ switch (layer) {
+
+ case VM_GPR0_LAYER:
+ writel(S5P_MXR_GRP_SPAN(span),
+ mixer_base + S5P_MXR_GRAPHIC0_SPAN);
+ writel(S5P_MXR_GRP_WIDTH(width) | S5P_MXR_GRP_HEIGHT(height),
+ mixer_base + S5P_MXR_GRAPHIC0_WH);
+ writel(S5P_MXR_GRP_STARTX(src_offs_x) |
+ S5P_MXR_GRP_STARTY(src_offs_y),
+ mixer_base + S5P_MXR_GRAPHIC0_SXY);
+ VMPRINTK("0x%x, 0x%x, 0x%x\n\r",
+ readl(mixer_base + S5P_MXR_GRAPHIC0_SPAN),
+ readl(mixer_base + S5P_MXR_GRAPHIC0_WH),
+ readl(mixer_base + S5P_MXR_GRAPHIC0_SXY));
+ break;
+
+ case VM_GPR1_LAYER:
+ writel(S5P_MXR_GRP_SPAN(span),
+ mixer_base + S5P_MXR_GRAPHIC1_SPAN);
+ writel(S5P_MXR_GRP_WIDTH(width) | S5P_MXR_GRP_HEIGHT(height),
+ mixer_base + S5P_MXR_GRAPHIC1_WH);
+ writel(S5P_MXR_GRP_STARTX(src_offs_x) |
+ S5P_MXR_GRP_STARTY(src_offs_y),
+ mixer_base + S5P_MXR_GRAPHIC1_SXY);
+ VMPRINTK("0x%x, 0x%x, 0x%x\n\r",
+ readl(mixer_base + S5P_MXR_GRAPHIC1_SPAN),
+ readl(mixer_base + S5P_MXR_GRAPHIC1_WH),
+ readl(mixer_base + S5P_MXR_GRAPHIC1_SXY));
+ break;
+
+ default:
+ VMPRINTK(" invalid layer parameter = %d\n\r", layer);
+ return S5P_TV_VMX_ERR_INVALID_PARAM;
+ break;
+ }
+
+ return VMIXER_NO_ERROR;
+}
+
+enum s5p_tv_vmx_err __s5p_vm_set_bg_color(enum s5p_tv_vmx_bg_color_num colornum,
+ u32 color_y,
+ u32 color_cb,
+ u32 color_cr)
+{
+ u32 reg_value;
+ VMPRINTK("%d, %d, %d, %d)\n\r", colornum, color_y, color_cb, color_cr);
+
+ reg_value = S5P_MXR_BG_COLOR_Y(color_y) |
+ S5P_MXR_BG_COLOR_CB(color_cb) |
+ S5P_MXR_BG_COLOR_CR(color_cr);
+
+ switch (colornum) {
+
+ case VMIXER_BG_COLOR_0:
+ writel(reg_value, mixer_base + S5P_MXR_BG_COLOR0);
+ VMPRINTK("0x%x\n\r", readl(mixer_base + S5P_MXR_BG_COLOR0));
+ break;
+
+ case VMIXER_BG_COLOR_1:
+ writel(reg_value, mixer_base + S5P_MXR_BG_COLOR1);
+ VMPRINTK("0x%x\n\r", readl(mixer_base + S5P_MXR_BG_COLOR1));
+ break;
+
+ case VMIXER_BG_COLOR_2:
+ writel(reg_value, mixer_base + S5P_MXR_BG_COLOR2);
+ VMPRINTK("0x%x\n\r", readl(mixer_base + S5P_MXR_BG_COLOR2));
+ break;
+
+ default:
+ VMPRINTK(" invalid uiColorNum parameter = %d\n\r", colornum);
+ return S5P_TV_VMX_ERR_INVALID_PARAM;
+ break;
+ }
+
+ return VMIXER_NO_ERROR;
+}
+
+
+
+/*
+* initialization - iniization functions are only called under stopping vmixer
+*/
+enum s5p_tv_vmx_err __s5p_vm_init_status_reg(enum s5p_vmx_burst_mode burst,
+ enum s5p_endian_type endian)
+{
+ u32 temp_reg = 0;
+
+ VMPRINTK("++(%d, %d)\n\r", burst, endian);
+
+ temp_reg = S5P_MXR_MIXER_RESERVED | S5P_MXR_CMU_CANNOT_STOP_CLOCK;
+
+ switch (burst) {
+
+ case VM_BURST_8:
+ temp_reg |= S5P_MXR_BURST8_MODE;
+ break;
+
+ case VM_BURST_16:
+ temp_reg |= S5P_MXR_BURST16_MODE;
+ break;
+
+ default:
+ VMPRINTK("[ERR] : invalid burst parameter = %d\n\r", burst);
+ return S5P_TV_VMX_ERR_INVALID_PARAM;
+ break;
+ }
+
+ switch (endian) {
+
+ case TVOUT_BIG_ENDIAN_MODE:
+ temp_reg |= S5P_MXR_BIG_ENDIAN_SOURCE_FORMAT;
+ break;
+
+ case TVOUT_LITTLE_ENDIAN_MODE:
+ temp_reg |= S5P_MXR_LITTLE_ENDIAN_SOURCE_FORMAT;
+ break;
+
+ default:
+ VMPRINTK("[ERR] : invalid endian parameter = %d\n\r", endian);
+ return S5P_TV_VMX_ERR_INVALID_PARAM;
+ break;
+ }
+
+ writel(temp_reg, mixer_base + S5P_MXR_STATUS);
+
+ VMPRINTK("--(0x%x)\n\r", readl(mixer_base + S5P_MXR_STATUS));
+
+ return VMIXER_NO_ERROR;
+}
+
+enum s5p_tv_vmx_err __s5p_vm_init_display_mode(enum s5p_tv_disp_mode mode,
+ enum s5p_tv_o_mode output_mode)
+{
+ u32 temp_reg = readl(mixer_base + S5P_MXR_CFG);
+
+ VMPRINTK("%d, %d)\n\r", mode, output_mode);
+
+ switch (mode) {
+
+ case TVOUT_NTSC_M:
+
+ case TVOUT_NTSC_443:
+ temp_reg &= ~S5P_MXR_HD;
+ temp_reg &= ~S5P_MXR_PAL;
+ temp_reg &= S5P_MXR_INTERLACE_MODE;
+ break;
+
+ case TVOUT_PAL_BDGHI:
+
+ case TVOUT_PAL_M:
+
+ case TVOUT_PAL_N:
+
+ case TVOUT_PAL_NC:
+
+ case TVOUT_PAL_60:
+ temp_reg &= ~S5P_MXR_HD;
+ temp_reg |= S5P_MXR_PAL;
+ temp_reg &= S5P_MXR_INTERLACE_MODE;
+ break;
+
+ case TVOUT_480P_60_16_9:
+
+ case TVOUT_480P_60_4_3:
+
+ case TVOUT_480P_59:
+ temp_reg &= ~S5P_MXR_HD;
+ temp_reg &= ~S5P_MXR_PAL;
+ temp_reg |= S5P_MXR_PROGRESSVE_MODE;
+ temp_reg |= RGB601_16_235<<9;
+ break;
+
+ case TVOUT_576P_50_16_9:
+
+ case TVOUT_576P_50_4_3:
+ temp_reg &= ~S5P_MXR_HD;
+ temp_reg |= S5P_MXR_PAL;
+ temp_reg |= S5P_MXR_PROGRESSVE_MODE;
+ temp_reg |= RGB601_16_235<<9;
+ break;
+
+ case TVOUT_720P_50:
+
+ case TVOUT_720P_59:
+
+ case TVOUT_720P_60:
+ temp_reg |= S5P_MXR_HD;
+ temp_reg &= ~S5P_MXR_HD_1080I_MODE;
+ temp_reg |= S5P_MXR_PROGRESSVE_MODE;
+ temp_reg |= RGB709_16_235<<9;
+ break;
+
+ case TVOUT_1080I_50:
+
+ case TVOUT_1080I_59:
+
+ case TVOUT_1080I_60:
+ temp_reg |= S5P_MXR_HD;
+ temp_reg |= S5P_MXR_HD_1080I_MODE;
+ temp_reg &= S5P_MXR_INTERLACE_MODE;
+ temp_reg |= RGB709_16_235<<9;
+ break;
+
+ case TVOUT_1080P_50:
+
+ case TVOUT_1080P_59:
+
+ case TVOUT_1080P_60:
+
+ case TVOUT_1080P_30:
+ temp_reg |= S5P_MXR_HD;
+ temp_reg |= S5P_MXR_HD_1080P_MODE;
+ temp_reg |= S5P_MXR_PROGRESSVE_MODE;
+ temp_reg |= RGB709_16_235<<9;
+ break;
+
+ default:
+ VMPRINTK(" invalid mode parameter = %d\n\r", mode);
+ return S5P_TV_VMX_ERR_INVALID_PARAM;
+ break;
+ }
+
+ switch (output_mode) {
+
+ case TVOUT_OUTPUT_COMPOSITE:
+ case TVOUT_OUTPUT_SVIDEO:
+ case TVOUT_OUTPUT_COMPONENT_YPBPR_INERLACED:
+ case TVOUT_OUTPUT_COMPONENT_YPBPR_PROGRESSIVE:
+ case TVOUT_OUTPUT_COMPONENT_RGB_PROGRESSIVE:
+ temp_reg &= S5P_MXR_DST_SEL_ANALOG;
+ break;
+
+ case TVOUT_OUTPUT_HDMI_RGB:
+ case TVOUT_OUTPUT_DVI:
+ temp_reg |= S5P_MXR_DST_SEL_HDMI;
+ temp_reg &= ~(0x1<<8);
+ temp_reg |= MX_RGB888<<8;
+ break;
+
+ case TVOUT_OUTPUT_HDMI:
+ temp_reg |= S5P_MXR_DST_SEL_HDMI;
+ temp_reg &= ~(0x1<<8);
+ temp_reg |= MX_YUV444<<8;
+ break;
+
+ default:
+ VMPRINTK(" invalid mode parameter = %d\n\r", mode);
+ return S5P_TV_VMX_ERR_INVALID_PARAM;
+ break;
+ }
+
+ writel(temp_reg, mixer_base + S5P_MXR_CFG);
+
+ VMPRINTK("--(0x%x)\n\r", readl(mixer_base + S5P_MXR_CFG));
+
+ return VMIXER_NO_ERROR;
+}
+
+u32 grp_scaling_factor(u32 src, u32 dst, u32 h_v)
+{
+ u32 factor; /* for scaling factor */
+
+ /* check scale or not */
+ if (src == dst)
+ factor = 0;
+
+ if (dst % src) {
+ factor = 0;
+
+ VMPRINTK(" can't %s scaling src(%d) into dst(%d)\n"
+ , h_v ? "horizontal" : "vertical"
+ , src_w, dst_w);
+ VMPRINTK(" scaling vector must be 2/4/8x\n");
+ }
+
+ factor = dst / src;
+
+ switch (factor) {
+ case 2:
+ factor = 1;
+ break;
+ case 4:
+ factor = 2;
+ break;
+ case 8:
+ factor = 3;
+ break;
+ default:
+ VMPRINTK(" scaling vector must be 2/4/8x\n");
+ factor = 0;
+ break;
+ }
+
+ return factor;
+}
+
+void __s5p_vm_set_ctrl(enum s5p_tv_vmx_layer layer,
+ bool premul,
+ bool pixel_blending,
+ bool blank_change,
+ bool win_blending,
+ enum s5p_tv_vmx_color_fmt color,
+ u32 alpha, u32 blank_color)
+{
+ u32 reg = readl(mixer_base + S5P_MXR_GRAPHIC0_CFG);
+
+ if (blank_change)
+ reg &= ~S5P_MXR_BLANK_CHANGE_NEW_PIXEL;
+ else
+ reg |= S5P_MXR_BLANK_CHANGE_NEW_PIXEL;
+
+
+ if (premul)
+ reg |= S5P_MXR_PRE_MUL_MODE;
+ else
+ reg &= ~S5P_MXR_PRE_MUL_MODE;
+
+ if (win_blending)
+ reg |= S5P_MXR_WIN_BLEND_ENABLE;
+ else
+ reg &= ~S5P_MXR_WIN_BLEND_ENABLE;
+
+ reg &= ~S5P_MXR_EG_COLOR_FORMAT(0xf);
+ reg |= S5P_MXR_EG_COLOR_FORMAT(color);
+ reg |= S5P_MXR_GRP_ALPHA_VALUE(alpha);
+
+ writel(reg, mixer_base + S5P_MXR_GRAPHIC0_CFG);
+ writel(S5P_MXR_GPR_BLANK_COLOR(blank_color),
+ mixer_base + S5P_MXR_GRAPHIC0_BLANK);
+
+}
+
+enum s5p_tv_vmx_err __s5p_vm_init_layer(enum s5p_tv_disp_mode mode,
+ enum s5p_tv_vmx_layer layer,
+ bool show,
+ bool win_blending,
+ u32 alpha,
+ u32 priority,
+ enum s5p_tv_vmx_color_fmt color,
+ bool blank_change,
+ bool pixel_blending,
+ bool premul,
+ u32 blank_color,
+ u32 base_addr,
+ u32 span,
+ u32 width,
+ u32 height,
+ u32 src_offs_x,
+ u32 src_offs_y,
+ u32 dst_offs_x,
+ u32 dst_offs_y,
+ u32 dst_width,
+ u32 dst_height)
+{
+ u32 temp_reg = 0;
+ u32 h_factor = 0, v_factor = 0;
+
+ VMPRINTK("%d, %d, %d, %d, %d, %d, %d, %d, %d, 0x%x,\
+ 0x%x, %d, %d, %d, %d, %d, %d, %d)\n\r",
+ layer, show, win_blending, alpha, priority,
+ color, blank_change, pixel_blending, premul,
+ blank_color, base_addr, span, width, height,
+ src_offs_x, src_offs_y, dst_offs_x, dst_offs_y);
+
+ switch (layer) {
+
+ case VM_VIDEO_LAYER:
+ temp_reg = (win_blending) ? S5P_MXR_VP_BLEND_ENABLE :
+ S5P_MXR_VP_BLEND_DISABLE;
+ temp_reg |= S5P_MXR_VP_ALPHA_VALUE(alpha);
+ /* temp yuv pxl limiter setting*/
+ temp_reg &= ~(1<<17);
+ writel(temp_reg, mixer_base + S5P_MXR_VIDEO_CFG);
+ break;
+
+ case VM_GPR0_LAYER:
+ temp_reg = (blank_change) ?
+ S5P_MXR_BLANK_NOT_CHANGE_NEW_PIXEL :
+ S5P_MXR_BLANK_CHANGE_NEW_PIXEL;
+ temp_reg |= (premul) ? S5P_MXR_PRE_MUL_MODE :
+ S5P_MXR_NORMAL_MODE;
+ temp_reg |= (win_blending) ? S5P_MXR_WIN_BLEND_ENABLE :
+ S5P_MXR_WIN_BLEND_DISABLE;
+ temp_reg |= (pixel_blending) ? S5P_MXR_PIXEL_BLEND_ENABLE :
+ S5P_MXR_PIXEL_BLEND_DISABLE;
+ temp_reg |= S5P_MXR_EG_COLOR_FORMAT(color);
+ temp_reg |= S5P_MXR_GRP_ALPHA_VALUE(alpha);
+ writel(temp_reg, mixer_base + S5P_MXR_GRAPHIC0_CFG);
+ writel(S5P_MXR_GPR_BLANK_COLOR(blank_color),
+ mixer_base + S5P_MXR_GRAPHIC0_BLANK);
+
+ VMPRINTK("--(0x%x)\n\r",
+ readl(mixer_base + S5P_MXR_GRAPHIC0_CFG));
+ VMPRINTK("--(0x%x)\n\r",
+ readl(mixer_base + S5P_MXR_GRAPHIC0_BLANK));
+
+ __s5p_vm_set_grp_layer_size(layer, span, width, height,
+ src_offs_x, src_offs_y);
+
+ __s5p_vm_set_grp_base_address(layer, base_addr);
+ __s5p_vm_set_grp_layer_position(layer, dst_offs_x,
+ dst_offs_y);
+
+ temp_reg = readl(mixer_base + S5P_MXR_GRAPHIC0_WH);
+ h_factor = grp_scaling_factor(width, dst_width, 1);
+ v_factor = grp_scaling_factor(height, dst_height, 0);
+
+ temp_reg &= ~((0x3<<28)|(0x3<<12));
+
+ if (v_factor) {
+
+ u32 reg = readl(mixer_base + S5P_MXR_CFG);
+
+ /* In interlaced mode, vertical scaling must be
+ * replaced by PROGRESSIVE_MODE - pixel duplication
+ */
+ if (mode == TVOUT_1080I_50 ||
+ mode == TVOUT_1080I_59 ||
+ mode == TVOUT_1080I_60) {
+ /* scaled up by progressive setting */
+ reg |= S5P_MXR_PROGRESSVE_MODE;
+ writel(reg, mixer_base + S5P_MXR_CFG);
+ } else
+ /* scaled up by scale factor */
+ temp_reg |= v_factor << 12;
+ } else {
+ u32 reg = readl(mixer_base + S5P_MXR_CFG);
+
+ /*
+ * if v_factor is 0, recover the original mode
+ */
+ if (mode == TVOUT_1080I_50 ||
+ mode == TVOUT_1080I_59 ||
+ mode == TVOUT_1080I_60) {
+ reg &= S5P_MXR_INTERLACE_MODE;
+ writel(reg, mixer_base + S5P_MXR_CFG);
+ }
+ }
+
+ temp_reg |= h_factor << 28;
+
+ writel(temp_reg , mixer_base + S5P_MXR_GRAPHIC0_WH);
+
+
+ break;
+
+ case VM_GPR1_LAYER:
+ temp_reg = (blank_change) ?
+ S5P_MXR_BLANK_NOT_CHANGE_NEW_PIXEL :
+ S5P_MXR_BLANK_CHANGE_NEW_PIXEL;
+ temp_reg |= (premul) ? S5P_MXR_PRE_MUL_MODE :
+ S5P_MXR_NORMAL_MODE;
+ temp_reg |= (win_blending) ? S5P_MXR_WIN_BLEND_ENABLE :
+ S5P_MXR_WIN_BLEND_DISABLE;
+ temp_reg |= (pixel_blending) ? S5P_MXR_PIXEL_BLEND_ENABLE :
+ S5P_MXR_PIXEL_BLEND_DISABLE;
+ temp_reg |= S5P_MXR_EG_COLOR_FORMAT(color);
+ temp_reg |= S5P_MXR_GRP_ALPHA_VALUE(alpha);
+
+ writel(temp_reg, mixer_base + S5P_MXR_GRAPHIC1_CFG);
+ writel(S5P_MXR_GPR_BLANK_COLOR(blank_color),
+ mixer_base + S5P_MXR_GRAPHIC1_BLANK);
+
+ VMPRINTK("--(0x%x)\n\r",
+ readl(mixer_base + S5P_MXR_GRAPHIC1_CFG));
+ VMPRINTK("--(0x%x)\n\r",
+ readl(mixer_base + S5P_MXR_GRAPHIC1_BLANK));
+
+ __s5p_vm_set_grp_layer_size(layer, span, width, height,
+ src_offs_x, src_offs_y);
+
+ __s5p_vm_set_grp_base_address(layer, base_addr);
+ __s5p_vm_set_grp_layer_position(layer, dst_offs_x, dst_offs_y);
+
+ temp_reg = readl(mixer_base + S5P_MXR_GRAPHIC1_WH);
+ h_factor = grp_scaling_factor(width, dst_width, 1);
+ v_factor = grp_scaling_factor(height, dst_height, 0);
+
+ temp_reg &= ~((0x3<<28)|(0x3<<12));
+
+ if (v_factor) {
+
+ u32 reg = readl(mixer_base + S5P_MXR_CFG);
+
+ /* In interlaced mode, vertical scaling must be
+ * replaced by PROGRESSIVE_MODE - pixel duplication
+ */
+ if (mode == TVOUT_1080I_50 ||
+ mode == TVOUT_1080I_59 ||
+ mode == TVOUT_1080I_60) {
+ /* scaled up by progressive setting */
+ reg |= S5P_MXR_PROGRESSVE_MODE;
+ writel(reg, mixer_base + S5P_MXR_CFG);
+ } else
+ /* scaled up by scale factor */
+ temp_reg |= v_factor << 12;
+ } else {
+ u32 reg = readl(mixer_base + S5P_MXR_CFG);
+
+ /*
+ * if v_factor is 0, recover the original mode
+ */
+ if (mode == TVOUT_1080I_50 ||
+ mode == TVOUT_1080I_59 ||
+ mode == TVOUT_1080I_60) {
+ reg &= S5P_MXR_INTERLACE_MODE;
+ writel(reg, mixer_base + S5P_MXR_CFG);
+ }
+ }
+
+ temp_reg |= h_factor << 28;
+
+ writel(temp_reg , mixer_base + S5P_MXR_GRAPHIC1_WH);
+ break;
+
+ default:
+ VMPRINTK("invalid layer parameter = %d\n\r", layer);
+ return S5P_TV_VMX_ERR_INVALID_PARAM;
+ break;
+ }
+
+ __s5p_vm_set_layer_priority(layer, priority);
+
+ __s5p_vm_set_layer_show(layer, show);
+
+ return VMIXER_NO_ERROR;
+}
+
+void __s5p_vm_init_bg_dither_enable(bool cr_dither_enable,
+ bool cb_dither_enable,
+ bool y_dither_enable)
+{
+ u32 temp_reg = 0;
+
+ VMPRINTK("%d, %d, %d\n\r", cr_dither_enable, cb_dither_enable,
+ y_dither_enable);
+
+ temp_reg = (cr_dither_enable) ?
+ (temp_reg | S5P_MXR_BG_CR_DIHER_EN) :
+ (temp_reg & ~S5P_MXR_BG_CR_DIHER_EN);
+ temp_reg = (cb_dither_enable) ?
+ (temp_reg | S5P_MXR_BG_CB_DIHER_EN) :
+ (temp_reg & ~S5P_MXR_BG_CB_DIHER_EN);
+ temp_reg = (y_dither_enable) ?
+ (temp_reg | S5P_MXR_BG_Y_DIHER_EN) :
+ (temp_reg & ~S5P_MXR_BG_Y_DIHER_EN);
+
+ writel(temp_reg, mixer_base + S5P_MXR_BG_CFG);
+ VMPRINTK("--(0x%x)\n\r", readl(mixer_base + S5P_MXR_BG_CFG));
+
+}
+
+
+enum s5p_tv_vmx_err __s5p_vm_init_bg_color(
+ enum s5p_tv_vmx_bg_color_num color_num,
+ u32 color_y,
+ u32 color_cb,
+ u32 color_cr)
+{
+ return __s5p_vm_set_bg_color(color_num, color_y, color_cb, color_cr);
+}
+
+enum s5p_tv_vmx_err __s5p_vm_init_csc_coef(enum s5p_yuv_fmt_component component,
+ enum s5p_tv_coef_y_mode mode,
+ u32 coeff0,
+ u32 coeff1,
+ u32 coeff2)
+{
+ u32 mxr_cm;
+
+ VMPRINTK("%d, %d, %d, %d, %d\n\r", component, mode, coeff0, coeff1,
+ coeff2);
+
+ switch (component) {
+
+ case TVOUT_YUV_Y:
+ mxr_cm = (mode == VMIXER_COEF_Y_WIDE) ?
+ S5P_MXR_BG_COLOR_WIDE : S5P_MXR_BG_COLOR_NARROW;
+ mxr_cm |= S5P_MXR_BG_COEFF_0(coeff0) |
+ S5P_MXR_BG_COEFF_1(coeff1) |
+ S5P_MXR_BG_COEFF_2(coeff2);
+ writel(mxr_cm, mixer_base + S5P_MXR_CM_COEFF_Y);
+ VMPRINTK("--(0x%x)\n\r",
+ readl(mixer_base + S5P_MXR_CM_COEFF_Y));
+ break;
+
+ case TVOUT_YUV_CB:
+ mxr_cm = S5P_MXR_BG_COEFF_0(coeff0) |
+ S5P_MXR_BG_COEFF_1(coeff1) |
+ S5P_MXR_BG_COEFF_2(coeff2);
+ writel(mxr_cm, mixer_base + S5P_MXR_CM_COEFF_CB);
+ VMPRINTK("--(0x%x)\n\r",
+ readl(mixer_base + S5P_MXR_CM_COEFF_CB));
+ break;
+
+ case TVOUT_YUV_CR:
+ mxr_cm = S5P_MXR_BG_COEFF_0(coeff0) |
+ S5P_MXR_BG_COEFF_1(coeff1) |
+ S5P_MXR_BG_COEFF_2(coeff2);
+ writel(mxr_cm, S5P_MXR_CM_COEFF_CR);
+ VMPRINTK("--(0x%x)\n\r",
+ readl(mixer_base + S5P_MXR_CM_COEFF_CR));
+ break;
+
+ default:
+ VMPRINTK("invalid component parameter = %d\n\r", component);
+ return S5P_TV_VMX_ERR_INVALID_PARAM;
+ break;
+ }
+
+ return VMIXER_NO_ERROR;
+}
+
+void __s5p_vm_init_csc_coef_default(enum s5p_tv_vmx_csc_type csc_type)
+{
+ VMPRINTK("%d\n\r", csc_type);
+
+ switch (csc_type) {
+
+ case VMIXER_CSC_RGB_TO_YUV601_LR:
+ writel((0 << 30) | (153 << 20) | (300 << 10) | (58 << 0),
+ mixer_base + S5P_MXR_CM_COEFF_Y);
+ writel((936 << 20) | (851 << 10) | (262 << 0),
+ mixer_base + S5P_MXR_CM_COEFF_CB);
+ writel((262 << 20) | (805 << 10) | (982 << 0),
+ mixer_base + S5P_MXR_CM_COEFF_CR);
+ break;
+
+ case VMIXER_CSC_RGB_TO_YUV601_FR:
+ writel((1 << 30) | (132 << 20) | (258 << 10) | (50 << 0),
+ mixer_base + S5P_MXR_CM_COEFF_Y);
+ writel((948 << 20) | (875 << 10) | (225 << 0),
+ mixer_base + S5P_MXR_CM_COEFF_CB);
+ writel((225 << 20) | (836 << 10) | (988 << 0),
+ mixer_base + S5P_MXR_CM_COEFF_CR);
+ break;
+
+ case VMIXER_CSC_RGB_TO_YUV709_LR:
+ writel((0 << 30) | (109 << 20) | (366 << 10) | (36 << 0),
+ mixer_base + S5P_MXR_CM_COEFF_Y);
+ writel((964 << 20) | (822 << 10) | (216 << 0),
+ mixer_base + S5P_MXR_CM_COEFF_CB);
+ writel((262 << 20) | (787 << 10) | (1000 << 0),
+ mixer_base + S5P_MXR_CM_COEFF_CR);
+ break;
+
+ case VMIXER_CSC_RGB_TO_YUV709_FR:
+ writel((1 << 30) | (94 << 20) | (314 << 10) | (32 << 0),
+ mixer_base + S5P_MXR_CM_COEFF_Y);
+ writel((972 << 20) | (851 << 10) | (225 << 0),
+ mixer_base + S5P_MXR_CM_COEFF_CB);
+ writel((225 << 20) | (820 << 10) | (1004 << 0),
+ mixer_base + S5P_MXR_CM_COEFF_CR);
+ break;
+
+ default:
+ VMPRINTK(" invalid csc_type parameter = %d\n\r", csc_type);
+ break;
+ }
+
+ VMPRINTK("--(0x%x)\n\r", readl(mixer_base + S5P_MXR_CM_COEFF_Y));
+
+ VMPRINTK("--(0x%x)\n\r", readl(mixer_base + S5P_MXR_CM_COEFF_CB));
+ VMPRINTK("--(0x%x)\n\r", readl(mixer_base + S5P_MXR_CM_COEFF_CR));
+}
+
+/*
+* etc
+*/
+enum s5p_tv_vmx_err __s5p_vm_get_layer_info(enum s5p_tv_vmx_layer layer,
+ bool *show,
+ u32 *priority)
+{
+ VMPRINTK("%d\n\r", layer);
+
+ switch (layer) {
+
+ case VM_VIDEO_LAYER:
+ *show = (readl(mixer_base + S5P_MXR_LAYER_CFG) &
+ S5P_MXR_VIDEO_LAYER_SHOW) ? 1 : 0;
+ *priority = S5P_MXR_VP_LAYER_PRIORITY_INFO(
+ readl(mixer_base + S5P_MXR_LAYER_CFG));
+ break;
+
+ case VM_GPR0_LAYER:
+ *show = (readl(mixer_base + S5P_MXR_LAYER_CFG) &
+ S5P_MXR_GRAPHIC0_LAYER_SHOW) ? 1 : 0;
+ *priority = S5P_MXR_GRP0_LAYER_PRIORITY_INFO(
+ readl(mixer_base + S5P_MXR_LAYER_CFG));
+ break;
+
+ case VM_GPR1_LAYER:
+ *show = (readl(mixer_base + S5P_MXR_LAYER_CFG) &
+ S5P_MXR_GRAPHIC1_LAYER_SHOW) ? 1 : 0;
+ *priority = S5P_MXR_GRP1_LAYER_PRIORITY_INFO(
+ readl(mixer_base + S5P_MXR_LAYER_CFG));
+ break;
+
+ default:
+ VMPRINTK("invalid layer parameter = %d\n\r", layer);
+ return S5P_TV_VMX_ERR_INVALID_PARAM;
+ break;
+ }
+
+ VMPRINTK("%d, %d\n\r", *show, *priority);
+
+ return VMIXER_NO_ERROR;
+}
+
+/*
+* start - start functions are only called under stopping vmixer
+*/
+
+void __s5p_vm_start(void)
+{
+ VMPRINTK("()\n\r");
+ writel((readl(mixer_base + S5P_MXR_STATUS) | S5P_MXR_MIXER_START),
+ mixer_base + S5P_MXR_STATUS);
+ VMPRINTK("0x%x\n\r", readl(mixer_base + S5P_MXR_STATUS));
+
+
+ VMPRINTK("S5P_MXR_STATUS \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_STATUS));
+ VMPRINTK("S5P_MXR_INT_EN \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_INT_EN));
+ VMPRINTK("S5P_MXR_BG_CFG \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_BG_CFG));
+ VMPRINTK("S5P_MXR_BG_COLOR0 \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_BG_COLOR0));
+ VMPRINTK("S5P_MXR_BG_COLOR1 \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_BG_COLOR1));
+ VMPRINTK("S5P_MXR_BG_COLOR2 \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_BG_COLOR2));
+ VMPRINTK("S5P_MXR_CM_COEFF_Y \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_CM_COEFF_Y));
+ VMPRINTK("S5P_MXR_CM_COEFF_CB \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_CM_COEFF_CB));
+ VMPRINTK("S5P_MXR_CM_COEFF_CR \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_CM_COEFF_CR));
+ VMPRINTK("S5P_MXR_CM_COEFF_Y \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_CM_COEFF_Y));
+ VMPRINTK("S5P_MXR_CM_COEFF_CB \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_CM_COEFF_CB));
+ VMPRINTK("S5P_MXR_CM_COEFF_CR \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_CM_COEFF_CR));
+ VMPRINTK("S5P_MXR_GRAPHIC0_CFG \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_GRAPHIC0_CFG));
+ VMPRINTK("S5P_MXR_GRAPHIC0_BASE \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_GRAPHIC0_BASE));
+ VMPRINTK("S5P_MXR_GRAPHIC0_SPAN \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_GRAPHIC0_SPAN));
+ VMPRINTK("S5P_MXR_GRAPHIC0_WH \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_GRAPHIC0_WH));
+ VMPRINTK("S5P_MXR_GRAPHIC0_SXY \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_GRAPHIC0_SXY));
+ VMPRINTK("S5P_MXR_GRAPHIC0_DXY \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_GRAPHIC0_DXY));
+ VMPRINTK("S5P_MXR_GRAPHIC0_BLANK \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_GRAPHIC0_BLANK));
+ VMPRINTK("S5P_MXR_GRAPHIC1_BASE \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_GRAPHIC1_BASE));
+ VMPRINTK("S5P_MXR_GRAPHIC1_SPAN \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_GRAPHIC1_SPAN));
+ VMPRINTK("S5P_MXR_GRAPHIC1_WH \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_GRAPHIC1_WH));
+ VMPRINTK("S5P_MXR_GRAPHIC1_SXY \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_GRAPHIC1_SXY));
+ VMPRINTK("S5P_MXR_GRAPHIC1_DXY \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_GRAPHIC1_DXY));
+ VMPRINTK("S5P_MXR_GRAPHIC1_BLANK \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_GRAPHIC1_BLANK));
+ VMPRINTK("S5P_MXR_CFG \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_CFG));
+ VMPRINTK("S5P_MXR_LAYER_CFG \t\t 0x%08x\n ",
+ readl(mixer_base + S5P_MXR_LAYER_CFG));
+
+}
+
+/*
+* stop - stop functions are only called under running vmixer
+*/
+
+void __s5p_vm_stop(void)
+{
+ u32 reg = readl(mixer_base + S5P_MXR_STATUS);
+
+ reg &= ~S5P_MXR_MIXER_START;
+
+ writel(reg, mixer_base + S5P_MXR_STATUS);
+
+ do {
+ reg = readl(mixer_base + S5P_MXR_STATUS);
+ } while (reg & S5P_MXR_MIXER_START);
+}
+
+/*
+* interrupt - for debug
+*/
+
+enum s5p_tv_vmx_err __s5p_vm_set_underflow_interrupt_enable(
+ enum s5p_tv_vmx_layer layer, bool en)
+{
+ u32 enablemaks;
+
+ VMPRINTK("%d, %d\n\r", layer, en);
+
+ switch (layer) {
+
+ case VM_VIDEO_LAYER:
+ enablemaks = S5P_MXR_VP_INT_ENABLE;
+ break;
+
+ case VM_GPR0_LAYER:
+ enablemaks = S5P_MXR_GRP0_INT_ENABLE;
+ break;
+
+ case VM_GPR1_LAYER:
+ enablemaks = S5P_MXR_GRP1_INT_ENABLE;
+ break;
+
+ default:
+ VMPRINTK("invalid layer parameter = %d\n\r", layer);
+ return S5P_TV_VMX_ERR_INVALID_PARAM;
+ break;
+ }
+
+ if (en) {
+ writel((readl(mixer_base + S5P_MXR_INT_EN) | enablemaks),
+ mixer_base + S5P_MXR_INT_EN);
+ } else {
+ writel((readl(mixer_base + S5P_MXR_INT_EN) & ~enablemaks),
+ mixer_base + S5P_MXR_INT_EN);
+ }
+
+ VMPRINTK("0x%x)\n\r", readl(mixer_base + S5P_MXR_INT_EN));
+
+ return VMIXER_NO_ERROR;
+}
+
+void __s5p_vm_clear_pend_all(void)
+{
+ writel(S5P_MXR_INT_FIRED | S5P_MXR_VP_INT_FIRED |
+ S5P_MXR_GRP0_INT_FIRED | S5P_MXR_GRP1_INT_FIRED,
+ mixer_base + S5P_MXR_INT_STATUS);
+}
+
+irqreturn_t __s5p_mixer_irq(int irq, void *dev_id)
+{
+ bool v_i_f;
+ bool g0_i_f;
+ bool g1_i_f;
+ bool mxr_i_f;
+ u32 temp_reg = 0;
+
+ v_i_f = (readl(mixer_base + S5P_MXR_INT_STATUS)
+ & S5P_MXR_VP_INT_FIRED) ? true : false;
+ g0_i_f = (readl(mixer_base + S5P_MXR_INT_STATUS)
+ & S5P_MXR_GRP0_INT_FIRED) ? true : false;
+ g1_i_f = (readl(mixer_base + S5P_MXR_INT_STATUS)
+ & S5P_MXR_GRP1_INT_FIRED) ? true : false;
+ mxr_i_f = (readl(mixer_base + S5P_MXR_INT_STATUS)
+ & S5P_MXR_INT_FIRED) ? true : false;
+
+ if (mxr_i_f) {
+ temp_reg |= S5P_MXR_INT_FIRED;
+
+ if (v_i_f) {
+ temp_reg |= S5P_MXR_VP_INT_FIRED;
+ printk("VP fifo under run!!\n\r");
+ }
+
+ if (g0_i_f) {
+ temp_reg |= S5P_MXR_GRP0_INT_FIRED;
+ printk("GRP0 fifo under run!!\n\r");
+ }
+
+ if (g1_i_f) {
+ temp_reg |= S5P_MXR_GRP1_INT_FIRED;
+ printk("GRP1 fifo under run!!\n\r");
+ }
+
+ writel(temp_reg, mixer_base + S5P_MXR_INT_STATUS);
+ }
+
+ return IRQ_HANDLED;
+}
+
+int __init __s5p_mixer_probe(struct platform_device *pdev, u32 res_num)
+{
+ struct resource *res;
+ size_t size;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, res_num);
+
+ if (res == NULL) {
+ dev_err(&pdev->dev,
+ "failed to get memory region resource\n");
+ goto error;
+
+ }
+
+ size = (res->end - res->start) + 1;
+
+ mixer_mem = request_mem_region(res->start, size, pdev->name);
+
+ if (mixer_mem == NULL) {
+ dev_err(&pdev->dev,
+ "failed to get memory region\n");
+ goto error;
+
+ }
+
+ mixer_base = ioremap(res->start, size);
+
+ if (mixer_base == NULL) {
+ dev_err(&pdev->dev,
+ "failed to ioremap address region\n");
+ goto error;
+
+
+ }
+ return 0;
+error:
+ return -ENOENT;
+
+}
+
+int __init __s5p_mixer_release(struct platform_device *pdev)
+{
+ iounmap(mixer_base);
+
+ /* remove memory region */
+ if (mixer_mem != NULL) {
+ if (release_resource(mixer_mem))
+ dev_err(&pdev->dev,
+ "Can't remove tvout drv !!\n");
+
+ kfree(mixer_mem);
+
+ mixer_mem = NULL;
+ }
+
+ return 0;
+}
diff --git a/drivers/media/video/samsung/tv20/s5pv210/vp_coeff_s5pv210.h b/drivers/media/video/samsung/tv20/s5pv210/vp_coeff_s5pv210.h
new file mode 100644
index 0000000..fb939fe
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/s5pv210/vp_coeff_s5pv210.h
@@ -0,0 +1,310 @@
+/* linux/drivers/media/video/samsung/tv20/s5pv210/vp_coeff_s5pv210.h
+ *
+ * Video Processor coefficient header file for Samsung TVOut driver
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/* Horizontal Y 8tap */
+const signed char g_s_vp8tap_coef_y_h[] = {
+ /* VP_PP_H_NORMAL */
+ 0, 0, 0, 0, 127, 0, 0, 0,
+ 0, 1, -2, 8, 126, -6, 2, -1,
+ 0, 1, -5, 16, 125, -12, 4, -1,
+ 0, 2, -8, 25, 121, -16, 5, -1,
+ -1, 3, -10, 35, 114, -18, 6, -1,
+ -1, 4, -13, 46, 107, -20, 6, -1,
+ -1, 5, -16, 57, 99, -21, 6, -1,
+ -1, 5, -18, 68, 89, -20, 6, -1,
+ -1, 6, -20, 79, 79, -20, 6, -1,
+ -1, 6, -20, 89, 68, -18, 5, -1,
+ -1, 6, -21, 99, 57, -16, 5, -1,
+ -1, 6, -20, 107, 46, -13, 4, -1,
+ -1, 6, -18, 114, 35, -10, 3, -1,
+ -1, 5, -16, 121, 25, -8, 2, 0,
+ -1, 4, -12, 125, 16, -5, 1, 0,
+ -1, 2, -6, 126, 8, -2, 1, 0,
+
+ /* VP_PP_H_8_9 */
+ 0, 3, -7, 12, 112, 12, -7, 3,
+ -1, 3, -9, 19, 113, 6, -5, 2,
+ -1, 3, -11, 27, 111, 0, -3, 2,
+ -1, 4, -13, 35, 108, -5, -1, 1,
+ -1, 4, -14, 43, 104, -9, 0, 1,
+ -1, 5, -16, 52, 99, -12, 1, 0,
+ -1, 5, -17, 61, 92, -14, 2, 0,
+ 0, 4, -17, 69, 85, -16, 3, 0,
+ 0, 4, -17, 77, 77, -17, 4, 0,
+ 0, 3, -16, 85, 69, -17, 4, 0,
+ 0, 2, -14, 92, 61, -17, 5, -1,
+ 0, 1, -12, 99, 52, -16, 5, -1,
+ 1, 0, -9, 104, 43, -14, 4, -1,
+ 1, -1, -5, 108, 35, -13, 4, -1,
+ 2, -3, 0, 111, 27, -11, 3, -1,
+ 2, -5, 6, 113, 19, -9, 3, -1,
+
+ /* VP_PP_H_1_2 */
+ 0, -3, 0, 35, 64, 35, 0, -3,
+ 0, -3, 1, 38, 64, 32, -1, -3,
+ 0, -3, 2, 41, 63, 29, -2, -2,
+ 0, -4, 4, 43, 63, 27, -3, -2,
+ 0, -4, 5, 46, 62, 24, -3, -2,
+ 0, -4, 7, 49, 60, 21, -3, -2,
+ -1, -4, 9, 51, 59, 19, -4, -1,
+ -1, -4, 12, 53, 57, 16, -4, -1,
+ -1, -4, 14, 55, 55, 14, -4, -1,
+ -1, -4, 16, 57, 53, 12, -4, -1,
+ -1, -4, 19, 59, 51, 9, -4, -1,
+ -2, -3, 21, 60, 49, 7, -4, 0,
+ -2, -3, 24, 62, 46, 5, -4, 0,
+ -2, -3, 27, 63, 43, 4, -4, 0,
+ -2, -2, 29, 63, 41, 2, -3, 0,
+ -3, -1, 32, 64, 38, 1, -3, 0,
+
+ /* VP_PP_H_1_3 */
+ 0, 0, 10, 32, 44, 32, 10, 0,
+ -1, 0, 11, 33, 45, 31, 9, 0,
+ -1, 0, 12, 35, 45, 29, 8, 0,
+ -1, 1, 13, 36, 44, 28, 7, 0,
+ -1, 1, 15, 37, 44, 26, 6, 0,
+ -1, 2, 16, 38, 43, 25, 5, 0,
+ -1, 2, 18, 39, 43, 23, 5, -1,
+ -1, 3, 19, 40, 42, 22, 4, -1,
+ -1, 3, 21, 41, 41, 21, 3, -1,
+ -1, 4, 22, 42, 40, 19, 3, -1,
+ -1, 5, 23, 43, 39, 18, 2, -1,
+ 0, 5, 25, 43, 38, 16, 2, -1,
+ 0, 6, 26, 44, 37, 15, 1, -1,
+ 0, 7, 28, 44, 36, 13, 1, -1,
+ 0, 8, 29, 45, 35, 12, 0, -1,
+ 0, 9, 31, 45, 33, 11, 0, -1,
+
+ /* VP_PP_H_1_4 */
+ 0, 2, 13, 30, 38, 30, 13, 2,
+ 0, 3, 14, 30, 38, 29, 12, 2,
+ 0, 3, 15, 31, 38, 28, 11, 2,
+ 0, 4, 16, 32, 38, 27, 10, 1,
+ 0, 4, 17, 33, 37, 26, 10, 1,
+ 0, 5, 18, 34, 37, 24, 9, 1,
+ 0, 5, 19, 34, 37, 24, 8, 1,
+ 1, 6, 20, 35, 36, 22, 7, 1,
+ 1, 6, 21, 36, 36, 21, 6, 1,
+ 1, 7, 22, 36, 35, 20, 6, 1,
+ 1, 8, 24, 37, 34, 19, 5, 0,
+ 1, 9, 24, 37, 34, 18, 5, 0,
+ 1, 10, 26, 37, 33, 17, 4, 0,
+ 1, 10, 27, 38, 32, 16, 4, 0,
+ 2, 11, 28, 38, 31, 15, 3, 0,
+ 2, 12, 29, 38, 30, 14, 3, 0
+};
+
+/* Horizontal C 4tap */
+const signed char g_s_vp4tap_coef_c_h[] = {
+ /* VP_PP_H_NORMAL */
+ 0, 0, 128, 0,
+ 0, 5, 126, -3,
+ -1, 11, 124, -6,
+ -1, 19, 118, -8,
+ -2, 27, 111, -8,
+ -3, 37, 102, -8,
+ -4, 48, 92, -8,
+ -5, 59, 81, -7,
+ -6, 70, 70, -6,
+ -7, 81, 59, -5,
+ -8, 92, 48, -4,
+ -8, 102, 37, -3,
+ -8, 111, 27, -2,
+ -8, 118, 19, -1,
+ -6, 124, 11, -1,
+ -3, 126, 5, 0,
+
+ /* VP_PP_H_8_9 */
+ 0, 8, 112, 8,
+ -1, 13, 113, 3,
+ -2, 19, 111, 0,
+ -2, 26, 107, -3,
+ -3, 34, 101, -4,
+ -3, 42, 94, -5,
+ -4, 51, 86, -5,
+ -5, 60, 78, -5,
+ -5, 69, 69, -5,
+ -5, 78, 60, -5,
+ -5, 86, 51, -4,
+ -5, 94, 42, -3,
+ -4, 101, 34, -3,
+ -3, 107, 26, -2,
+ 0, 111, 19, -2,
+ 3, 113, 13, -1,
+
+ /* VP_PP_H_1_2 */
+ 0, 26, 76, 26,
+ 0, 30, 76, 22,
+ 0, 34, 75, 19,
+ 1, 38, 73, 16,
+ 1, 43, 71, 13,
+ 2, 47, 69, 10,
+ 3, 51, 66, 8,
+ 4, 55, 63, 6,
+ 5, 59, 59, 5,
+ 6, 63, 55, 4,
+ 8, 66, 51, 3,
+ 10, 69, 47, 2,
+ 13, 71, 43, 1,
+ 16, 73, 38, 1,
+ 19, 75, 34, 0,
+ 22, 76, 30, 0,
+
+ /* VP_PP_H_1_3 */
+ 0, 30, 68, 30,
+ 2, 33, 66, 27,
+ 3, 36, 66, 23,
+ 3, 39, 65, 21,
+ 4, 43, 63, 18,
+ 5, 46, 62, 15,
+ 6, 49, 60, 13,
+ 8, 52, 57, 11,
+ 9, 55, 55, 9,
+ 11, 57, 52, 8,
+ 13, 60, 49, 6,
+ 15, 62, 46, 5,
+ 18, 63, 43, 4,
+ 21, 65, 39, 3,
+ 23, 66, 36, 3,
+ 27, 66, 33, 2,
+
+ /* VP_PP_H_1_4 */
+ 0, 31, 66, 31,
+ 3, 34, 63, 28,
+ 4, 37, 62, 25,
+ 4, 40, 62, 22,
+ 5, 43, 61, 19,
+ 6, 46, 59, 17,
+ 7, 48, 58, 15,
+ 9, 51, 55, 13,
+ 11, 53, 53, 11,
+ 13, 55, 51, 9,
+ 15, 58, 48, 7,
+ 17, 59, 46, 6,
+ 19, 61, 43, 5,
+ 22, 62, 40, 4,
+ 25, 62, 37, 4,
+ 28, 63, 34, 3,
+};
+
+
+/* Vertical Y 8tap */
+const signed char g_s_vp4tap_coef_y_v[] = {
+ /* VP_PP_V_NORMAL */
+ 0, 0, 127, 0,
+ 0, 5, 126, -3,
+ -1, 11, 124, -6,
+ -1, 19, 118, -8,
+ -2, 27, 111, -8,
+ -3, 37, 102, -8,
+ -4, 48, 92, -8,
+ -5, 59, 81, -7,
+ -6, 70, 70, -6,
+ -7, 81, 59, -5,
+ -8, 92, 48, -4,
+ -8, 102, 37, -3,
+ -8, 111, 27, -2,
+ -8, 118, 19, -1,
+ -6, 124, 11, -1,
+ -3, 126, 5, 0,
+
+ /* VP_PP_V_5_6 */
+ 0, 11, 106, 11,
+ -2, 16, 107, 7,
+ -2, 22, 105, 3,
+ -2, 29, 101, 0,
+ -3, 36, 96, -1,
+ -3, 44, 90, -3,
+ -4, 52, 84, -4,
+ -4, 60, 76, -4,
+ -4, 68, 68, -4,
+ -4, 76, 60, -4,
+ -4, 84, 52, -4,
+ -3, 90, 44, -3,
+ -1, 96, 36, -3,
+ 0, 101, 29, -2,
+ 3, 105, 22, -2,
+ 7, 107, 16, -2,
+
+ /* VP_PP_V_3_4 */
+ 0, 15, 98, 15,
+ -2, 21, 97, 12,
+ -2, 26, 96, 8,
+ -2, 32, 93, 5,
+ -2, 39, 89, 2,
+ -2, 46, 84, 0,
+ -3, 53, 79, -1,
+ -2, 59, 73, -2,
+ -2, 66, 66, -2,
+ -2, 73, 59, -2,
+ -1, 79, 53, -3,
+ 0, 84, 46, -2,
+ 2, 89, 39, -2,
+ 5, 93, 32, -2,
+ 8, 96, 26, -2,
+ 12, 97, 21, -2,
+
+ /* VP_PP_V_1_2 */
+ 0, 26, 76, 26,
+ 0, 30, 76, 22,
+ 0, 34, 75, 19,
+ 1, 38, 73, 16,
+ 1, 43, 71, 13,
+ 2, 47, 69, 10,
+ 3, 51, 66, 8,
+ 4, 55, 63, 6,
+ 5, 59, 59, 5,
+ 6, 63, 55, 4,
+ 8, 66, 51, 3,
+ 10, 69, 47, 2,
+ 13, 71, 43, 1,
+ 16, 73, 38, 1,
+ 19, 75, 34, 0,
+ 22, 76, 30, 0,
+
+ /* VP_PP_V_1_3 */
+ 0, 30, 68, 30,
+ 2, 33, 66, 27,
+ 3, 36, 66, 23,
+ 3, 39, 65, 21,
+ 4, 43, 63, 18,
+ 5, 46, 62, 15,
+ 6, 49, 60, 13,
+ 8, 52, 57, 11,
+ 9, 55, 55, 9,
+ 11, 57, 52, 8,
+ 13, 60, 49, 6,
+ 15, 62, 46, 5,
+ 18, 63, 43, 4,
+ 21, 65, 39, 3,
+ 23, 66, 36, 3,
+ 27, 66, 33, 2,
+
+ /* VP_PP_V_1_4 */
+ 0, 31, 66, 31,
+ 3, 34, 63, 28,
+ 4, 37, 62, 25,
+ 4, 40, 62, 22,
+ 5, 43, 61, 19,
+ 6, 46, 59, 17,
+ 7, 48, 58, 15,
+ 9, 51, 55, 13,
+ 11, 53, 53, 11,
+ 13, 55, 51, 9,
+ 15, 58, 48, 7,
+ 17, 59, 46, 6,
+ 19, 61, 43, 5,
+ 22, 62, 40, 4,
+ 25, 62, 37, 4,
+ 28, 63, 34, 3
+};
+
diff --git a/drivers/media/video/samsung/tv20/s5pv210/vprocessor_s5pv210.c b/drivers/media/video/samsung/tv20/s5pv210/vprocessor_s5pv210.c
new file mode 100644
index 0000000..34bcdf2
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/s5pv210/vprocessor_s5pv210.c
@@ -0,0 +1,814 @@
+/* linux/drivers/media/video/samsung/tv20/s5pv210/vprocessor_s5pv210.c
+ *
+ * Video Processor raw ftn file for Samsung TVOut driver
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <plat/clock.h>
+
+#include "tv_out_s5pv210.h"
+
+#include "regs/regs-vprocessor.h"
+#include "vp_coeff_s5pv210.h"
+
+#ifdef COFIG_TVOUT_RAW_DBG
+#define S5P_VP_DEBUG 1
+#endif
+
+#ifdef S5P_VP_DEBUG
+#define VPPRINTK(fmt, args...)\
+ printk(KERN_ERR "\t\t[VP] %s: " fmt, __func__ , ## args)
+#else
+#define VPPRINTK(fmt, args...)
+#endif
+
+static struct resource *vp_mem;
+void __iomem *vp_base;
+
+/*
+* set
+* - set functions are only called under running video processor
+* - after running set functions, it is need to run __s5p_vp_update() function
+* for update shadow registers
+*/
+void __s5p_vp_set_field_id(enum s5p_vp_field mode)
+{
+ VPPRINTK("%d\n\r", mode);
+
+ writel((mode == VPROC_TOP_FIELD) ?
+ vp_base + S5P_VP_FIELD_ID_TOP :
+ vp_base + S5P_VP_FIELD_ID_BOTTOM,
+ vp_base + S5P_VP_FIELD_ID);
+
+ VPPRINTK("0x%08x\n\r", readl(vp_base + S5P_VP_FIELD_ID));
+}
+
+enum s5p_tv_vp_err __s5p_vp_set_top_field_address(u32 top_y_addr,
+ u32 top_c_addr)
+{
+ VPPRINTK("0x%x, 0x%x\n\r", top_y_addr, top_c_addr);
+
+ if (VP_PTR_ILLEGAL(top_y_addr) || VP_PTR_ILLEGAL(top_c_addr)) {
+ VPPRINTK(" address is not double word align = 0x%x, 0x%x\n\r",
+ top_y_addr, top_c_addr);
+ return S5P_TV_VP_ERR_BASE_ADDRESS_MUST_DOUBLE_WORD_ALIGN;
+ }
+
+ writel(top_y_addr, vp_base + S5P_VP_TOP_Y_PTR);
+
+ writel(top_c_addr, vp_base + S5P_VP_TOP_C_PTR);
+
+
+ VPPRINTK("0x%x, 0x%x\n\r", readl(vp_base + S5P_VP_TOP_Y_PTR),
+ readl(vp_base + S5P_VP_TOP_C_PTR));
+
+ return VPROC_NO_ERROR;
+}
+
+enum s5p_tv_vp_err __s5p_vp_set_bottom_field_address(u32 bottom_y_addr,
+ u32 bottom_c_addr)
+{
+ VPPRINTK("0x%x, 0x%x\n\r", bottom_y_addr, bottom_c_addr);
+
+ if (VP_PTR_ILLEGAL(bottom_y_addr) || VP_PTR_ILLEGAL(bottom_c_addr)) {
+ VPPRINTK(" address is not double word align = 0x%x, 0x%x\n\r",
+ bottom_y_addr, bottom_c_addr);
+ return S5P_TV_VP_ERR_BASE_ADDRESS_MUST_DOUBLE_WORD_ALIGN;
+ }
+
+ writel(bottom_y_addr, vp_base + S5P_VP_BOT_Y_PTR);
+
+ writel(bottom_c_addr, vp_base + S5P_VP_BOT_C_PTR);
+
+
+ VPPRINTK("0x%x, 0x%x\n\r", readl(vp_base + S5P_VP_BOT_Y_PTR),
+ readl(vp_base + S5P_VP_BOT_C_PTR));
+
+ return VPROC_NO_ERROR;
+}
+
+
+enum s5p_tv_vp_err __s5p_vp_set_img_size(u32 img_width, u32 img_height)
+{
+ VPPRINTK("%d, %d\n\r", img_width, img_height);
+
+ if (VP_IMG_SIZE_ILLEGAL(img_width) ||
+ VP_IMG_SIZE_ILLEGAL(img_height)) {
+ VPPRINTK(" image full size is not double word align =\
+ %d, %d\n\r",
+ img_width, img_height);
+
+ return S5P_TV_VP_ERR_BASE_ADDRESS_MUST_DOUBLE_WORD_ALIGN;
+ }
+
+ writel(VP_IMG_HSIZE(img_width) | VP_IMG_VSIZE(img_height),
+ vp_base + S5P_VP_IMG_SIZE_Y);
+
+ writel(VP_IMG_HSIZE(img_width) | VP_IMG_VSIZE(img_height / 2),
+ vp_base + S5P_VP_IMG_SIZE_C);
+
+ VPPRINTK("0x%x, 0x%x\n\r", readl(vp_base + S5P_VP_IMG_SIZE_Y),
+ readl(vp_base + S5P_VP_IMG_SIZE_C));
+
+ return VPROC_NO_ERROR;
+}
+
+void __s5p_vp_set_src_position(u32 src_off_x,
+ u32 src_x_fract_step,
+ u32 src_off_y)
+{
+ VPPRINTK("%d, %d, %d)\n\r", src_off_x, src_x_fract_step, src_off_y);
+
+ writel(VP_SRC_H_POSITION(src_off_x) |
+ VP_SRC_X_FRACT_STEP(src_x_fract_step),
+ vp_base + S5P_VP_SRC_H_POSITION);
+ writel(VP_SRC_V_POSITION(src_off_y), vp_base + S5P_VP_SRC_V_POSITION);
+
+ VPPRINTK("0x%x, 0x%x\n\r", readl(vp_base + S5P_VP_SRC_H_POSITION),
+ readl(vp_base + S5P_VP_SRC_V_POSITION));
+}
+
+void __s5p_vp_set_dest_position(u32 dst_off_x,
+ u32 dst_off_y)
+{
+ VPPRINTK("%d, %d)\n\r", dst_off_x, dst_off_y);
+
+
+ writel(VP_DST_H_POSITION(dst_off_x), vp_base + S5P_VP_DST_H_POSITION);
+ writel(VP_DST_V_POSITION(dst_off_y), vp_base + S5P_VP_DST_V_POSITION);
+
+ VPPRINTK("0x%x, 0x%x\n\r", readl(vp_base + S5P_VP_DST_H_POSITION),
+ readl(vp_base + S5P_VP_DST_V_POSITION));
+}
+
+void __s5p_vp_set_src_dest_size(u32 src_width,
+ u32 src_height,
+ u32 dst_width,
+ u32 dst_height,
+ bool ipc_2d)
+{
+ u32 h_ratio = (src_width << 16) / dst_width;
+ u32 v_ratio = (ipc_2d) ?
+ ((src_height << 17) / dst_height) :
+ ((src_height << 16) / dst_height);
+
+ VPPRINTK("(%d, %d, %d, %d)++\n\r", src_width, src_height,
+ dst_width, dst_height);
+
+ writel(VP_SRC_WIDTH(src_width), vp_base + S5P_VP_SRC_WIDTH);
+ writel(VP_SRC_HEIGHT(src_height), vp_base + S5P_VP_SRC_HEIGHT);
+ writel(VP_DST_WIDTH(dst_width), vp_base + S5P_VP_DST_WIDTH);
+ writel(VP_DST_HEIGHT(dst_height), vp_base + S5P_VP_DST_HEIGHT) ;
+ writel(VP_H_RATIO(h_ratio), vp_base + S5P_VP_H_RATIO);
+ writel(VP_V_RATIO(v_ratio), vp_base + S5P_VP_V_RATIO);
+
+ writel((ipc_2d) ? (readl(vp_base + S5P_VP_MODE) | VP_2D_IPC_ON) :
+ (readl(vp_base + S5P_VP_MODE) & ~VP_2D_IPC_ON),
+ vp_base + S5P_VP_MODE);
+
+ VPPRINTK("%d, %d, %d, %d, 0x%x, 0x%x\n\r",
+ readl(vp_base + S5P_VP_SRC_WIDTH),
+ readl(vp_base + S5P_VP_SRC_HEIGHT),
+ readl(vp_base + S5P_VP_DST_WIDTH),
+ readl(vp_base + S5P_VP_DST_HEIGHT),
+ readl(vp_base + S5P_VP_H_RATIO),
+ readl(vp_base + S5P_VP_V_RATIO));
+}
+
+enum s5p_tv_vp_err __s5p_vp_set_poly_filter_coef(
+ enum s5p_vp_poly_coeff poly_coeff,
+ signed char ch0,
+ signed char ch1,
+ signed char ch2,
+ signed char ch3)
+{
+ VPPRINTK("%d, %d, %d, %d, %d)\n\r", poly_coeff, ch0, ch1, ch2, ch3);
+
+ if (poly_coeff > VPROC_POLY4_C1_HH || poly_coeff < VPROC_POLY8_Y0_LL ||
+ (poly_coeff > VPROC_POLY8_Y3_HH &&
+ poly_coeff < VPROC_POLY4_Y0_LL)) {
+
+ VPPRINTK("invaild poly_coeff parameter \n\r");
+ return S5P_TV_VP_ERR_INVALID_PARAM;
+ }
+
+ writel((((0xff&ch0) << 24) | ((0xff&ch1) << 16) | ((0xff&ch2) << 8) |
+ (0xff&ch3)), vp_base + S5P_VP_POLY8_Y0_LL + poly_coeff*4);
+
+ VPPRINTK("0x%08x, 0x%08x\n\r",
+ readl(vp_base + S5P_VP_POLY8_Y0_LL + poly_coeff*4),
+ vp_base + S5P_VP_POLY8_Y0_LL + poly_coeff*4);
+
+ return VPROC_NO_ERROR;
+}
+
+void __s5p_vp_set_poly_filter_coef_default(u32 h_ratio, u32 v_ratio)
+{
+ enum s5p_tv_vp_filter_h_pp e_h_filter;
+ enum s5p_tv_vp_filter_v_pp e_v_filter;
+ u8 *poly_flt_coeff;
+ int i, j;
+
+ VPPRINTK("%d, %d\n\r", h_ratio, v_ratio);
+
+ /*
+ * For the real interlace mode, the vertical ratio should be
+ * used after divided by 2. Because in the interlace mode, all
+ * the VP output is used for SDOUT display and it should be the
+ * same as one field of the progressive mode. Therefore the same
+ * filter coefficients should be used for the same the final
+ * output video. When half of the interlace V_RATIO is same as
+ * the progressive V_RATIO, the final output video scale is same.
+ */
+
+ /*Horizontal Y 8tap */
+ /*Horizontal C 4tap */
+
+
+ if (h_ratio <= (0x1 << 16)) /* 720->720 or zoom in */
+ e_h_filter = VPROC_PP_H_NORMAL;
+
+
+
+ else if (h_ratio <= (0x9 << 13)) /* 720->640 */
+ e_h_filter = VPROC_PP_H_8_9;
+
+
+ else if (h_ratio <= (0x1 << 17)) /* 2->1 */
+ e_h_filter = VPROC_PP_H_1_2;
+
+
+ else if (h_ratio <= (0x3 << 16)) /* 2->1 */
+ e_h_filter = VPROC_PP_H_1_3;
+ else
+ e_h_filter = VPROC_PP_H_1_4; /* 4->1 */
+
+ /* Vertical Y 4tap */
+
+ if (v_ratio <= (0x1 << 16)) /* 720->720 or zoom in*/
+ e_v_filter = VPROC_PP_V_NORMAL;
+ else if (v_ratio <= (0x5 << 14)) /* 4->3*/
+ e_v_filter = VPROC_PP_V_3_4;
+ else if (v_ratio <= (0x3 << 15)) /*6->5*/
+ e_v_filter = VPROC_PP_V_5_6;
+ else if (v_ratio <= (0x1 << 17)) /* 2->1*/
+ e_v_filter = VPROC_PP_V_1_2;
+ else if (v_ratio <= (0x3 << 16)) /* 3->1*/
+ e_v_filter = VPROC_PP_V_1_3;
+ else
+ e_v_filter = VPROC_PP_V_1_4;
+
+ poly_flt_coeff = (u8 *)(g_s_vp8tap_coef_y_h + e_h_filter * 16 * 8);
+
+ for (i = 0; i < 4; i++) {
+ for (j = 0; j < 4; j++) {
+ __s5p_vp_set_poly_filter_coef(
+ VPROC_POLY8_Y0_LL + (i*4) + j,
+ *(poly_flt_coeff + 4*j*8 + (7 - i)),
+ *(poly_flt_coeff + (4*j + 1)*8 + (7 - i)),
+ *(poly_flt_coeff + (4*j + 2)*8 + (7 - i)),
+ *(poly_flt_coeff + (4*j + 3)*8 + (7 - i)));
+ }
+ }
+
+ poly_flt_coeff = (u8 *)(g_s_vp4tap_coef_c_h + e_h_filter * 16 * 4);
+
+ for (i = 0; i < 2; i++) {
+ for (j = 0; j < 4; j++) {
+ __s5p_vp_set_poly_filter_coef(
+ VPROC_POLY4_C0_LL + (i*4) + j,
+ *(poly_flt_coeff + 4*j*4 + (3 - i)),
+ *(poly_flt_coeff + (4*j + 1)*4 + (3 - i)),
+ *(poly_flt_coeff + (4*j + 2)*4 + (3 - i)),
+ *(poly_flt_coeff + (4*j + 3)*4 + (3 - i)));
+ }
+ }
+
+ poly_flt_coeff = (u8 *)(g_s_vp4tap_coef_y_v + e_v_filter * 16 * 4);
+
+ for (i = 0; i < 4; i++) {
+ for (j = 0; j < 4; j++) {
+ __s5p_vp_set_poly_filter_coef(
+ VPROC_POLY4_Y0_LL + (i*4) + j,
+ *(poly_flt_coeff + 4*j*4 + (3 - i)),
+ *(poly_flt_coeff + (4*j + 1)*4 + (3 - i)),
+ *(poly_flt_coeff + (4*j + 2)*4 + (3 - i)),
+ *(poly_flt_coeff + (4*j + 3)*4 + (3 - i)));
+ }
+ }
+
+ VPPRINTK("%d, %d\n\r", e_h_filter, e_v_filter);
+}
+
+void __s5p_vp_set_src_dest_size_with_default_poly_filter_coef(u32 src_width,
+ u32 src_height,
+ u32 dst_width,
+ u32 dst_height,
+ bool ipc_2d)
+{
+ u32 h_ratio = (src_width << 16) / dst_width;
+ u32 v_ratio = (ipc_2d) ? ((src_height << 17) / dst_height) :
+ ((src_height << 16) / dst_height);
+
+ __s5p_vp_set_src_dest_size(src_width, src_height, dst_width,
+ dst_height, ipc_2d);
+ __s5p_vp_set_poly_filter_coef_default(h_ratio, v_ratio);
+}
+
+enum s5p_tv_vp_err __s5p_vp_set_brightness_contrast_control(
+ enum s5p_vp_line_eq eq_num,
+ u32 intc,
+ u32 slope)
+{
+ VPPRINTK("%d, %d, %d\n\r", eq_num, intc, slope);
+
+ if ((eq_num > VProc_LINE_EQ_7) || (eq_num < VProc_LINE_EQ_0)) {
+ VPPRINTK("invaild eq_num parameter \n\r");
+ return S5P_TV_VP_ERR_INVALID_PARAM;
+ }
+
+ writel(VP_LINE_INTC(intc) | VP_LINE_SLOPE(slope),
+ vp_base + S5P_PP_LINE_EQ0 + eq_num*4);
+
+ VPPRINTK("0x%08x, 0x%08x\n\r",
+ readl(vp_base + S5P_PP_LINE_EQ0 + eq_num*4),
+ vp_base + S5P_PP_LINE_EQ0 + eq_num*4);
+
+ return VPROC_NO_ERROR;
+}
+
+void __s5p_vp_set_brightness(bool brightness)
+{
+ unsigned short i;
+
+ VPPRINTK("%d\n\r", brightness);
+
+ g_vp_contrast_brightness =
+ VP_LINE_INTC_CLEAR(g_vp_contrast_brightness) |
+ VP_LINE_INTC(brightness);
+
+ for (i = 0; i < 8; i++)
+ writel(g_vp_contrast_brightness,
+ vp_base + S5P_PP_LINE_EQ0 + i*4);
+
+
+ VPPRINTK("%d\n\r", g_vp_contrast_brightness);
+}
+
+void __s5p_vp_set_contrast(u8 contrast)
+{
+ unsigned short i;
+
+ VPPRINTK("%d\n\r", contrast);
+
+ g_vp_contrast_brightness =
+ VP_LINE_SLOPE_CLEAR(g_vp_contrast_brightness) |
+ VP_LINE_SLOPE(contrast);
+
+ for (i = 0; i < 8; i++)
+ writel(g_vp_contrast_brightness,
+ vp_base + S5P_PP_LINE_EQ0 + i*4);
+
+ VPPRINTK("%d\n\r", g_vp_contrast_brightness);
+}
+
+enum s5p_tv_vp_err __s5p_vp_update(void)
+{
+ VPPRINTK("()\n\r");
+
+ writel(readl(vp_base + S5P_VP_SHADOW_UPDATE) |
+ S5P_VP_SHADOW_UPDATE_ENABLE,
+ vp_base + S5P_VP_SHADOW_UPDATE);
+
+ VPPRINTK("()\n\r");
+
+ return VPROC_NO_ERROR;
+}
+
+/*
+* get - get info
+*/
+enum s5p_vp_field __s5p_vp_get_field_id(void)
+{
+ VPPRINTK("()\n\r");
+ return (readl(vp_base + S5P_VP_FIELD_ID) ==
+ S5P_VP_FIELD_ID_BOTTOM) ?
+ VPROC_BOTTOM_FIELD : VPROC_TOP_FIELD;
+}
+
+/*
+* etc
+*/
+unsigned short __s5p_vp_get_update_status(void)
+{
+ VPPRINTK("()\n\r");
+ return readl(vp_base + S5P_VP_SHADOW_UPDATE) &
+ S5P_VP_SHADOW_UPDATE_ENABLE;
+}
+
+
+void __s5p_vp_init_field_id(enum s5p_vp_field mode)
+{
+ __s5p_vp_set_field_id(mode);
+}
+
+void __s5p_vp_init_op_mode(bool line_skip,
+ enum s5p_vp_mem_mode mem_mode,
+ enum s5p_vp_chroma_expansion chroma_exp,
+ enum s5p_vp_filed_id_toggle toggle_id)
+{
+ u32 temp_reg;
+ VPPRINTK("%d, %d, %d, %d\n\r", line_skip, mem_mode,
+ chroma_exp, toggle_id);
+
+ temp_reg = (line_skip) ? VP_LINE_SKIP_ON : VP_LINE_SKIP_OFF;
+ temp_reg |= (mem_mode == VPROC_2D_TILE_MODE) ?
+ VP_MEM_2D_MODE : VP_MEM_LINEAR_MODE;
+ temp_reg |= (chroma_exp == VPROC_USING_C_TOP_BOTTOM) ?
+ VP_CHROMA_USE_TOP_BOTTOM : VP_CHROMA_USE_TOP;
+ temp_reg |= (toggle_id == S5P_TV_VP_FILED_ID_TOGGLE_VSYNC) ?
+ VP_FIELD_ID_TOGGLE_VSYNC : VP_FIELD_ID_TOGGLE_USER;
+
+ writel(temp_reg, vp_base + S5P_VP_MODE);
+ VPPRINTK("0x%08x\n\r", readl(vp_base + S5P_VP_MODE));
+}
+
+void __s5p_vp_init_pixel_rate_control(enum s5p_vp_pxl_rate rate)
+{
+ VPPRINTK("%d\n\r", rate);
+
+ writel(VP_PEL_RATE_CTRL(rate), vp_base + S5P_VP_PER_RATE_CTRL);
+
+ VPPRINTK("0x%08x\n\r", readl(vp_base + S5P_VP_PER_RATE_CTRL));
+}
+
+enum s5p_tv_vp_err __s5p_vp_init_layer(u32 top_y_addr,
+ u32 top_c_addr,
+ u32 bottom_y_addr,
+ u32 bottom_c_addr,
+ enum s5p_endian_type src_img_endian,
+ u32 img_width,
+ u32 img_height,
+ u32 src_off_x,
+ u32 src_x_fract_step,
+ u32 src_off_y,
+ u32 src_width,
+ u32 src_height,
+ u32 dst_off_x,
+ u32 dst_off_y,
+ u32 dst_width,
+ u32 dst_height,
+ bool ipc_2d)
+{
+ enum s5p_tv_vp_err error = VPROC_NO_ERROR;
+
+ VPPRINTK("%d\n\r", src_img_endian);
+
+ writel(1, vp_base + S5P_VP_ENDIAN_MODE);
+
+ error = __s5p_vp_set_top_field_address(top_y_addr, top_c_addr);
+
+ if (error != VPROC_NO_ERROR)
+ return error;
+
+ error = __s5p_vp_set_bottom_field_address(bottom_y_addr,
+ bottom_c_addr);
+
+ if (error != VPROC_NO_ERROR)
+ return error;
+
+ error = __s5p_vp_set_img_size(img_width, img_height);
+
+ if (error != VPROC_NO_ERROR)
+ return error;
+
+ __s5p_vp_set_src_position(src_off_x, src_x_fract_step, src_off_y);
+
+ __s5p_vp_set_dest_position(dst_off_x, dst_off_y);
+
+ __s5p_vp_set_src_dest_size(src_width, src_height, dst_width,
+ dst_height, ipc_2d);
+
+ VPPRINTK("0x%08x\n\r", readl(vp_base + S5P_VP_ENDIAN_MODE));
+
+ return error;
+
+}
+
+enum s5p_tv_vp_err __s5p_vp_init_layer_def_poly_filter_coef(u32 top_y_addr,
+ u32 top_c_addr,
+ u32 bottom_y_addr,
+ u32 bottom_c_addr,
+ enum s5p_endian_type src_img_endian,
+ u32 img_width,
+ u32 img_height,
+ u32 src_off_x,
+ u32 src_x_fract_step,
+ u32 src_off_y,
+ u32 src_width,
+ u32 src_height,
+ u32 dst_off_x,
+ u32 dst_off_y,
+ u32 dst_width,
+ u32 dst_height,
+ bool ipc_2d)
+{
+ enum s5p_tv_vp_err error = VPROC_NO_ERROR;
+
+ u32 h_ratio = (src_width << 16) / dst_width;
+ u32 v_ratio = (ipc_2d) ? ((src_height << 17) / dst_height) :
+ ((src_height << 16) / dst_height);
+
+ __s5p_vp_set_poly_filter_coef_default(h_ratio, v_ratio);
+ error = __s5p_vp_init_layer(top_y_addr, top_c_addr,
+ bottom_y_addr, bottom_c_addr,
+ src_img_endian,
+ img_width, img_height,
+ src_off_x, src_x_fract_step, src_off_y,
+ src_width, src_height,
+ dst_off_x, dst_off_y,
+ dst_width, dst_height,
+ ipc_2d);
+ return error;
+}
+
+enum s5p_tv_vp_err __s5p_vp_init_poly_filter_coef(
+ enum s5p_vp_poly_coeff poly_coeff,
+ signed char ch0,
+ signed char ch1,
+ signed char ch2,
+ signed char ch3)
+{
+ return __s5p_vp_set_poly_filter_coef(poly_coeff, ch0, ch1, ch2, ch3);
+}
+
+void __s5p_vp_init_bypass_post_process(bool bypass)
+{
+ VPPRINTK("%d\n\r", bypass);
+
+ writel((bypass) ? VP_BY_PASS_ENABLE : VP_BY_PASS_DISABLE,
+ vp_base + S5P_PP_BYPASS);
+
+ VPPRINTK("0x%08x\n\r", readl(vp_base + S5P_PP_BYPASS));
+}
+
+enum s5p_tv_vp_err __s5p_vp_init_csc_coef(
+ enum s5p_vp_csc_coeff csc_coeff, u32 coeff)
+{
+ VPPRINTK("%d, %d\n\r", csc_coeff, coeff);
+
+ if (csc_coeff > VPROC_CSC_CR2CR_COEF ||
+ csc_coeff < VPROC_CSC_Y2Y_COEF) {
+ VPPRINTK("invaild csc_coeff parameter \n\r");
+ return S5P_TV_VP_ERR_INVALID_PARAM;
+ }
+
+ writel(VP_CSC_COEF(coeff),
+ vp_base + S5P_PP_CSC_Y2Y_COEF + csc_coeff*4);
+
+ VPPRINTK("0x%08x\n\r",
+ readl(vp_base + S5P_PP_CSC_Y2Y_COEF + csc_coeff*4));
+
+ return VPROC_NO_ERROR;
+}
+
+void __s5p_vp_init_saturation(u32 sat)
+{
+ VPPRINTK("%d\n\r", sat);
+
+ writel(VP_SATURATION(sat), vp_base + S5P_PP_SATURATION);
+
+ VPPRINTK("0x%08x\n\r", readl(vp_base + S5P_PP_SATURATION));
+}
+
+void __s5p_vp_init_sharpness(u32 th_h_noise,
+ enum s5p_vp_sharpness_control sharpness)
+{
+ VPPRINTK("%d, %d\n\r", th_h_noise, sharpness);
+
+ writel(VP_TH_HNOISE(th_h_noise) | VP_SHARPNESS(sharpness),
+ vp_base + S5P_PP_SHARPNESS);
+
+ VPPRINTK("0x%08x\n\r", readl(vp_base + S5P_PP_SHARPNESS));
+}
+
+enum s5p_tv_vp_err __s5p_vp_init_brightness_contrast_control(
+ enum s5p_vp_line_eq eq_num,
+ u32 intc,
+ u32 slope)
+{
+ return __s5p_vp_set_brightness_contrast_control(eq_num, intc, slope);
+}
+
+void __s5p_vp_init_brightness(bool brightness)
+{
+ __s5p_vp_set_brightness(brightness);
+}
+
+
+void __s5p_vp_init_contrast(u8 contrast)
+{
+ __s5p_vp_set_contrast(contrast);
+}
+
+void __s5p_vp_init_brightness_offset(u32 offset)
+{
+ VPPRINTK("%d\n\r", offset);
+
+ writel(VP_BRIGHT_OFFSET(offset), vp_base + S5P_PP_BRIGHT_OFFSET);
+
+ VPPRINTK("0x%08x\n\r", readl(vp_base + S5P_PP_BRIGHT_OFFSET));
+}
+
+void __s5p_vp_init_csc_control(bool sub_y_offset_en, bool csc_en)
+{
+ u32 temp_reg;
+ VPPRINTK("%d, %d\n\r", sub_y_offset_en, csc_en);
+
+ temp_reg = (sub_y_offset_en) ? VP_SUB_Y_OFFSET_ENABLE :
+ VP_SUB_Y_OFFSET_DISABLE;
+ temp_reg |= (csc_en) ? VP_CSC_ENABLE : VP_CSC_DISABLE;
+ writel(temp_reg, vp_base + S5P_PP_CSC_EN);
+
+ VPPRINTK("0x%08x\n\r", readl(vp_base + S5P_PP_CSC_EN));
+}
+
+enum s5p_tv_vp_err __s5p_vp_init_csc_coef_default(enum s5p_vp_csc_type csc_type)
+{
+ VPPRINTK("%d\n\r", csc_type);
+
+ switch (csc_type) {
+
+ case VPROC_CSC_SD_HD:
+ writel(Y2Y_COEF_601_TO_709, vp_base + S5P_PP_CSC_Y2Y_COEF);
+ writel(CB2Y_COEF_601_TO_709, vp_base + S5P_PP_CSC_CB2Y_COEF);
+ writel(CR2Y_COEF_601_TO_709, vp_base + S5P_PP_CSC_CR2Y_COEF);
+ writel(Y2CB_COEF_601_TO_709, vp_base + S5P_PP_CSC_Y2CB_COEF);
+ writel(CB2CB_COEF_601_TO_709, vp_base + S5P_PP_CSC_CB2CB_COEF);
+ writel(CR2CB_COEF_601_TO_709, vp_base + S5P_PP_CSC_CR2CB_COEF);
+ writel(Y2CR_COEF_601_TO_709, vp_base + S5P_PP_CSC_Y2CR_COEF);
+ writel(CB2CR_COEF_601_TO_709, vp_base + S5P_PP_CSC_CB2CR_COEF);
+ writel(CR2CR_COEF_601_TO_709, vp_base + S5P_PP_CSC_CR2CR_COEF);
+ break;
+
+ case VPROC_CSC_HD_SD:
+ writel(Y2Y_COEF_709_TO_601, vp_base + S5P_PP_CSC_Y2Y_COEF);
+ writel(CB2Y_COEF_709_TO_601, vp_base + S5P_PP_CSC_CB2Y_COEF);
+ writel(CR2Y_COEF_709_TO_601, vp_base + S5P_PP_CSC_CR2Y_COEF);
+ writel(Y2CB_COEF_709_TO_601, vp_base + S5P_PP_CSC_Y2CB_COEF);
+ writel(CB2CB_COEF_709_TO_601, vp_base + S5P_PP_CSC_CB2CB_COEF);
+ writel(CR2CB_COEF_709_TO_601, vp_base + S5P_PP_CSC_CR2CB_COEF);
+ writel(Y2CR_COEF_709_TO_601, vp_base + S5P_PP_CSC_Y2CR_COEF);
+ writel(CB2CR_COEF_709_TO_601, vp_base + S5P_PP_CSC_CB2CR_COEF);
+ writel(CR2CR_COEF_709_TO_601, vp_base + S5P_PP_CSC_CR2CR_COEF);
+ break;
+
+ default:
+ VPPRINTK("invalid csc_type parameter = %d\n\r", csc_type);
+ return S5P_TV_VP_ERR_INVALID_PARAM;
+ break;
+ }
+
+ VPPRINTK("0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x,\
+ 0x%08x, 0x%08x)\n\r",
+ readl(vp_base + S5P_PP_CSC_Y2Y_COEF),
+ readl(vp_base + S5P_PP_CSC_CB2Y_COEF),
+ readl(vp_base + S5P_PP_CSC_CR2Y_COEF),
+ readl(vp_base + S5P_PP_CSC_Y2CB_COEF),
+ readl(vp_base + S5P_PP_CSC_CB2CB_COEF),
+ readl(vp_base + S5P_PP_CSC_CR2CB_COEF),
+ readl(vp_base + S5P_PP_CSC_Y2CR_COEF),
+ readl(vp_base + S5P_PP_CSC_CB2CR_COEF),
+ readl(vp_base + S5P_PP_CSC_CR2CR_COEF));
+
+ return VPROC_NO_ERROR;
+}
+
+/*
+* start - start functions are only called under stopping video processor
+*/
+enum s5p_tv_vp_err __s5p_vp_start(void)
+{
+ enum s5p_tv_vp_err error = VPROC_NO_ERROR;
+
+ VPPRINTK("()\n\r");
+
+ writel(VP_ON_ENABLE, vp_base + S5P_VP_ENABLE);
+
+ error = __s5p_vp_update();
+
+ VPPRINTK("()\n\r");
+ return error;
+}
+
+/*
+* stop - stop functions are only called under running video processor
+*/
+enum s5p_tv_vp_err __s5p_vp_stop(void)
+{
+ enum s5p_tv_vp_err error = VPROC_NO_ERROR;
+
+ VPPRINTK("()\n\r");
+
+ writel((readl(vp_base + S5P_VP_ENABLE) & ~VP_ON_ENABLE),
+ vp_base + S5P_VP_ENABLE);
+
+ error = __s5p_vp_update();
+
+ while (!(readl(vp_base + S5P_VP_ENABLE) & VP_POWER_DOWN_RDY))
+ msleep(1);
+
+
+ return error;
+}
+
+/*
+* reset - reset function
+*/
+void __s5p_vp_sw_reset(void)
+{
+ VPPRINTK("()\n\r");
+
+ writel((readl(vp_base + S5P_VP_SRESET) | VP_SOFT_RESET),
+ vp_base + S5P_VP_SRESET);
+
+ while (readl(vp_base + S5P_VP_SRESET) & VP_SOFT_RESET)
+ msleep(10);
+
+
+ VPPRINTK("()\n\r");
+}
+
+int __init __s5p_vp_probe(struct platform_device *pdev, u32 res_num)
+{
+ struct resource *res;
+ size_t size;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, res_num);
+
+ if (res == NULL) {
+ dev_err(&pdev->dev,
+ "failed to get memory region resource\n");
+ goto error;
+
+ }
+
+ size = (res->end - res->start) + 1;
+
+ vp_mem = request_mem_region(res->start, size, pdev->name);
+
+ if (vp_mem == NULL) {
+ dev_err(&pdev->dev,
+ "failed to get memory region\n");
+ goto error;
+
+ }
+
+ vp_base = ioremap(res->start, size);
+
+ if (vp_base == NULL) {
+ dev_err(&pdev->dev,
+ "failed to ioremap address region\n");
+ goto error;
+
+
+ }
+
+ return 0;
+error:
+ return -ENOENT;
+
+}
+
+int __init __s5p_vp_release(struct platform_device *pdev)
+{
+ iounmap(vp_base);
+
+ /* remove memory region */
+ if (vp_mem != NULL) {
+ if (release_resource(vp_mem))
+ dev_err(&pdev->dev,
+ "Can't remove tvout drv !!\n");
+
+ kfree(vp_mem);
+
+ vp_mem = NULL;
+ }
+
+ return 0;
+}
+