aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video')
-rw-r--r--drivers/media/video/Kconfig42
-rw-r--r--drivers/media/video/Makefile5
-rwxr-xr-xdrivers/media/video/ce147.c5640
-rwxr-xr-xdrivers/media/video/s5k4ecgx.c2837
-rwxr-xr-xdrivers/media/video/s5k4ecgx_regs_1_0.h4797
-rwxr-xr-xdrivers/media/video/s5k4ecgx_regs_1_1.h4783
-rwxr-xr-xdrivers/media/video/s5ka3dfx.c1229
-rwxr-xr-xdrivers/media/video/s5ka3dfx.h1691
-rw-r--r--drivers/media/video/samsung/Kconfig26
-rw-r--r--drivers/media/video/samsung/Makefile10
-rw-r--r--drivers/media/video/samsung/fimc/Kconfig32
-rw-r--r--drivers/media/video/samsung/fimc/Makefile12
-rw-r--r--drivers/media/video/samsung/fimc/csis.c431
-rw-r--r--drivers/media/video/samsung/fimc/csis.h42
-rw-r--r--drivers/media/video/samsung/fimc/fimc.h707
-rw-r--r--drivers/media/video/samsung/fimc/fimc_capture.c1794
-rw-r--r--drivers/media/video/samsung/fimc/fimc_dev.c1689
-rw-r--r--drivers/media/video/samsung/fimc/fimc_output.c2563
-rw-r--r--drivers/media/video/samsung/fimc/fimc_overlay.c312
-rw-r--r--drivers/media/video/samsung/fimc/fimc_regs.c1801
-rw-r--r--drivers/media/video/samsung/fimc/fimc_v4l2.c303
-rw-r--r--drivers/media/video/samsung/jpeg_v2/Kconfig15
-rw-r--r--drivers/media/video/samsung/jpeg_v2/Makefile3
-rw-r--r--drivers/media/video/samsung/jpeg_v2/jpg_conf.h282
-rw-r--r--drivers/media/video/samsung/jpeg_v2/jpg_mem.c61
-rw-r--r--drivers/media/video/samsung/jpeg_v2/jpg_mem.h111
-rw-r--r--drivers/media/video/samsung/jpeg_v2/jpg_misc.c81
-rw-r--r--drivers/media/video/samsung/jpeg_v2/jpg_misc.h27
-rw-r--r--drivers/media/video/samsung/jpeg_v2/jpg_opr.c320
-rw-r--r--drivers/media/video/samsung/jpeg_v2/jpg_opr.h158
-rw-r--r--drivers/media/video/samsung/jpeg_v2/regs-jpeg.h143
-rw-r--r--drivers/media/video/samsung/jpeg_v2/s3c-jpeg.c613
-rw-r--r--drivers/media/video/samsung/jpeg_v2/s3c-jpeg.h36
-rw-r--r--drivers/media/video/samsung/mfc50/Kconfig23
-rw-r--r--drivers/media/video/samsung/mfc50/Makefile7
-rwxr-xr-xdrivers/media/video/samsung/mfc50/mfc.c835
-rw-r--r--drivers/media/video/samsung/mfc50/mfc_buffer_manager.c350
-rw-r--r--drivers/media/video/samsung/mfc50/mfc_buffer_manager.h56
-rw-r--r--drivers/media/video/samsung/mfc50/mfc_errorno.h83
-rw-r--r--drivers/media/video/samsung/mfc50/mfc_interface.h340
-rw-r--r--drivers/media/video/samsung/mfc50/mfc_intr.c202
-rw-r--r--drivers/media/video/samsung/mfc50/mfc_intr.h25
-rw-r--r--drivers/media/video/samsung/mfc50/mfc_logmsg.h72
-rw-r--r--drivers/media/video/samsung/mfc50/mfc_memory.c70
-rw-r--r--drivers/media/video/samsung/mfc50/mfc_memory.h111
-rw-r--r--drivers/media/video/samsung/mfc50/mfc_opr.c2576
-rw-r--r--drivers/media/video/samsung/mfc50/mfc_opr.h204
-rw-r--r--drivers/media/video/samsung/mfc50/mfc_shared_mem.c123
-rw-r--r--drivers/media/video/samsung/mfc50/mfc_shared_mem.h97
-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.c1102
-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
96 files changed, 70258 insertions, 1 deletions
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index bb53de7..515f638 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -1031,6 +1031,48 @@ config USB_S2255
This driver can be compiled as a module, called s2255drv.
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
+ ---help---
+ This driver supports S5KA3DFX SoC camera module
+
+config VIDEO_S5K4ECGX
+ tristate "S5K4ECGX Camera Sensor"
+ depends on I2C && VIDEO_V4L2
+ ---help---
+ This driver supports S5K4ECGX SoC camera module
+
+config VIDEO_S5K4ECGX_DEBUG
+ bool "S5K4ECGX Camera Sensor Debugging"
+ depends on VIDEO_S5K4ECGX
+ default n
+ ---help---
+ Enable extra debug messages for S5K4ECGX camera driver
+
+config VIDEO_S5K4ECGX_V_1_0
+ bool "S5K4ECGX Camera Sensor Version 1.0 Support"
+ depends on VIDEO_S5K4ECGX
+ default y
+ ---help---
+ Enabled support for Rev 1.0 sensor
+
+config VIDEO_S5K4ECGX_V_1_1
+ bool "S5K4ECGX Camera Sensor Version 1.1 Support"
+ depends on VIDEO_S5K4ECGX
+ default y
+ ---help---
+ Enabled support for Rev 1.1 sensor
+
+source "drivers/media/video/samsung/Kconfig"
+
endif # VIDEO_CAPTURE_DRIVERS
menuconfig V4L_MEM2MEM_DRIVERS
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index f0fecd6..bea5bbb 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -84,7 +84,9 @@ 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:
obj-$(CONFIG_VIDEO_BT848) += bt8xx/
@@ -174,6 +176,7 @@ obj-$(CONFIG_ARCH_DAVINCI) += davinci/
obj-$(CONFIG_VIDEO_SH_VOU) += sh_vou.o
obj-$(CONFIG_VIDEO_AU0828) += au0828/
+obj-$(CONFIG_VIDEO_SAMSUNG) += samsung/
obj-$(CONFIG_USB_VIDEO_CLASS) += uvc/
obj-$(CONFIG_VIDEO_SAA7164) += saa7164/
diff --git a/drivers/media/video/ce147.c b/drivers/media/video/ce147.c
new file mode 100755
index 0000000..a3e2b1e
--- /dev/null
+++ b/drivers/media/video/ce147.c
@@ -0,0 +1,5640 @@
+/*
+ * 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)
+ 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;
+
+ case FLASH_MODE_TORCH:
+ ce147_buf_set_flash_manual[1] = 0x01;
+ break;
+
+ 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 || 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;
+ }
+ 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_flash[2] = { 0x03, 0x00 };
+ unsigned int ce147_len_set_flash = 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;
+
+ 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)
+{
+ int err;
+ struct ce147_state *state = to_state(sd);
+ struct i2c_client *client = v4l2_get_subdevdata(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;
+
+ case V4L2_CID_CAMERA_FINISH_AUTO_FOCUS:
+#if defined(CONFIG_SAMSUNG_FASCINATE)
+ state->disable_aeawb_lock = ctrl->value;
+#endif
+ 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/s5k4ecgx.c b/drivers/media/video/s5k4ecgx.c
new file mode 100755
index 0000000..9d9d5b4
--- /dev/null
+++ b/drivers/media/video/s5k4ecgx.c
@@ -0,0 +1,2837 @@
+/* drivers/media/video/s5k4ecgx.c
+ *
+ * Driver for s5k4ecgx (5MP Camera) from SEC
+ *
+ * Copyright (C) 2010, SAMSUNG ELECTRONICS
+ *
+ * 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/version.h>
+#include <linux/vmalloc.h>
+#include <linux/completion.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <media/s5k4ecgx.h>
+#include <linux/videodev2_samsung.h>
+
+#ifdef CONFIG_VIDEO_S5K4ECGX_V_1_0
+#include "s5k4ecgx_regs_1_0.h"
+#define S5K4ECGX_VERSION_1_0 0x00
+#endif
+
+#ifdef CONFIG_VIDEO_S5K4ECGX_V_1_1
+#include "s5k4ecgx_regs_1_1.h"
+#define S5K4ECGX_VERSION_1_1 0x11
+#endif
+
+#define FORMAT_FLAGS_COMPRESSED 0x3
+#define SENSOR_JPEG_SNAPSHOT_MEMSIZE 0x410580
+
+#define DEFAULT_PIX_FMT V4L2_PIX_FMT_UYVY /* YUV422 */
+#define DEFAULT_MCLK 24000000
+#define POLL_TIME_MS 10
+#define CAPTURE_POLL_TIME_MS 1000
+
+/* maximum time for one frame at minimum fps (15fps) in normal mode */
+#define NORMAL_MODE_MAX_ONE_FRAME_DELAY_MS 67
+/* maximum time for one frame at minimum fps (4fps) in night mode */
+#define NIGHT_MODE_MAX_ONE_FRAME_DELAY_MS 250
+
+/* time to move lens to target position before last af mode register write */
+#define LENS_MOVE_TIME_MS 100
+
+/* level at or below which we need to enable flash when in auto mode */
+#define LOW_LIGHT_LEVEL 0x1D
+
+/* level at or below which we need to use low light capture mode */
+#define HIGH_LIGHT_LEVEL 0x80
+
+#define FIRST_AF_SEARCH_COUNT 80
+#define SECOND_AF_SEARCH_COUNT 80
+#define AE_STABLE_SEARCH_COUNT 4
+
+#define FIRST_SETTING_FOCUS_MODE_DELAY_MS 100
+#define SECOND_SETTING_FOCUS_MODE_DELAY_MS 200
+
+#ifdef CONFIG_VIDEO_S5K4ECGX_DEBUG
+enum {
+ S5K4ECGX_DEBUG_I2C = 1U << 0,
+ S5K4ECGX_DEBUG_I2C_BURSTS = 1U << 1,
+};
+static uint32_t s5k4ecgx_debug_mask = S5K4ECGX_DEBUG_I2C_BURSTS;
+module_param_named(debug_mask, s5k4ecgx_debug_mask, uint, S_IWUSR | S_IRUGO);
+
+#define s5k4ecgx_debug(mask, x...) \
+ do { \
+ if (s5k4ecgx_debug_mask & mask) \
+ pr_info(x); \
+ } while (0)
+#else
+
+#define s5k4ecgx_debug(mask, x...)
+
+#endif
+
+#define S5K4ECGX_VERSION_1_1 0x11
+
+/* result values returned to HAL */
+enum {
+ AUTO_FOCUS_FAILED,
+ AUTO_FOCUS_DONE,
+ AUTO_FOCUS_CANCELLED,
+};
+
+enum af_operation_status {
+ AF_NONE = 0,
+ AF_START,
+ AF_CANCEL,
+ AF_INITIAL,
+};
+
+enum s5k4ecgx_oprmode {
+ S5K4ECGX_OPRMODE_VIDEO = 0,
+ S5K4ECGX_OPRMODE_IMAGE = 1,
+};
+
+enum s5k4ecgx_preview_frame_size {
+ S5K4ECGX_PREVIEW_QCIF = 0, /* 176x144 */
+ S5K4ECGX_PREVIEW_CIF, /* 352x288 */
+ S5K4ECGX_PREVIEW_VGA, /* 640x480 */
+ S5K4ECGX_PREVIEW_D1, /* 720x480 */
+ S5K4ECGX_PREVIEW_WVGA, /* 800x480 */
+ S5K4ECGX_PREVIEW_SVGA, /* 800x600 */
+ S5K4ECGX_PREVIEW_WSVGA, /* 1024x600*/
+ S5K4ECGX_PREVIEW_MAX,
+};
+
+enum s5k4ecgx_capture_frame_size {
+ S5K4ECGX_CAPTURE_VGA = 0, /* 640x480 */
+ S5K4ECGX_CAPTURE_WVGA, /* 800x480 */
+ S5K4ECGX_CAPTURE_SVGA, /* 800x600 */
+ S5K4ECGX_CAPTURE_WSVGA, /* 1024x600 */
+ S5K4ECGX_CAPTURE_1MP, /* 1280x960 */
+ S5K4ECGX_CAPTURE_W1MP, /* 1600x960 */
+ S5K4ECGX_CAPTURE_2MP, /* UXGA - 1600x1200 */
+ S5K4ECGX_CAPTURE_W2MP, /* 35mm Academy Offset Standard 1.66 */
+ /* 2048x1232, 2.4MP */
+ S5K4ECGX_CAPTURE_3MP, /* QXGA - 2048x1536 */
+ S5K4ECGX_CAPTURE_W4MP, /* WQXGA - 2560x1536 */
+ S5K4ECGX_CAPTURE_5MP, /* 2560x1920 */
+ S5K4ECGX_CAPTURE_MAX,
+};
+
+struct s5k4ecgx_framesize {
+ u32 index;
+ u32 width;
+ u32 height;
+};
+
+static const struct s5k4ecgx_framesize s5k4ecgx_preview_framesize_list[] = {
+ { S5K4ECGX_PREVIEW_QCIF, 176, 144 },
+ { S5K4ECGX_PREVIEW_CIF, 352, 288 },
+ { S5K4ECGX_PREVIEW_VGA, 640, 480 },
+ { S5K4ECGX_PREVIEW_D1, 720, 480 },
+};
+
+static const struct s5k4ecgx_framesize s5k4ecgx_capture_framesize_list[] = {
+ { S5K4ECGX_CAPTURE_VGA, 640, 480 },
+ { S5K4ECGX_CAPTURE_1MP, 1280, 960 },
+ { S5K4ECGX_CAPTURE_2MP, 1600, 1200 },
+ { S5K4ECGX_CAPTURE_3MP, 2048, 1536 },
+ { S5K4ECGX_CAPTURE_5MP, 2560, 1920 },
+};
+
+struct s5k4ecgx_version {
+ u32 major;
+ u32 minor;
+};
+
+struct s5k4ecgx_date_info {
+ u32 year;
+ u32 month;
+ u32 date;
+};
+
+enum s5k4ecgx_runmode {
+ S5K4ECGX_RUNMODE_NOTREADY,
+ S5K4ECGX_RUNMODE_IDLE,
+ S5K4ECGX_RUNMODE_RUNNING,
+ S5K4ECGX_RUNMODE_CAPTURE,
+};
+
+struct s5k4ecgx_firmware {
+ u32 addr;
+ u32 size;
+};
+
+struct s5k4ecgx_jpeg_param {
+ u32 enable;
+ u32 quality;
+ u32 main_size; /* Main JPEG file size */
+ u32 thumb_size; /* Thumbnail file size */
+ u32 main_offset;
+ u32 thumb_offset;
+ u32 postview_offset;
+};
+
+struct s5k4ecgx_position {
+ int x;
+ int y;
+};
+
+struct gps_info_common {
+ u32 direction;
+ u32 dgree;
+ u32 minute;
+ u32 second;
+};
+
+struct s5k4ecgx_gps_info {
+ unsigned char gps_buf[8];
+ unsigned char altitude_buf[4];
+ int gps_timeStamp;
+};
+
+struct s5k4ecgx_regset {
+ u32 size;
+ u8 *data;
+};
+
+struct s5k4ecgx_regset_table {
+ const u32 *reg;
+ int array_size;
+};
+
+#define S5K4ECGX_REGSET(x, y) \
+ [(x)] = { \
+ .reg = (y), \
+ .array_size = ARRAY_SIZE((y)), \
+}
+
+#define S5K4ECGX_REGSET_TABLE(y) \
+ { \
+ .reg = (y), \
+ .array_size = ARRAY_SIZE((y)), \
+}
+
+struct s5k4ecgx_regs {
+ struct s5k4ecgx_regset_table ev[EV_MAX];
+ struct s5k4ecgx_regset_table metering[METERING_MAX];
+ struct s5k4ecgx_regset_table iso[ISO_MAX];
+ struct s5k4ecgx_regset_table effect[IMAGE_EFFECT_MAX];
+ struct s5k4ecgx_regset_table white_balance[WHITE_BALANCE_MAX];
+ struct s5k4ecgx_regset_table preview_size[S5K4ECGX_PREVIEW_MAX];
+ struct s5k4ecgx_regset_table capture_size[S5K4ECGX_CAPTURE_MAX];
+ struct s5k4ecgx_regset_table scene_mode[SCENE_MODE_MAX];
+ struct s5k4ecgx_regset_table saturation[SATURATION_MAX];
+ struct s5k4ecgx_regset_table contrast[CONTRAST_MAX];
+ struct s5k4ecgx_regset_table sharpness[SHARPNESS_MAX];
+ struct s5k4ecgx_regset_table fps[FRAME_RATE_MAX];
+ struct s5k4ecgx_regset_table preview_return;
+ struct s5k4ecgx_regset_table jpeg_quality_high;
+ struct s5k4ecgx_regset_table jpeg_quality_normal;
+ struct s5k4ecgx_regset_table jpeg_quality_low;
+ struct s5k4ecgx_regset_table flash_start;
+ struct s5k4ecgx_regset_table flash_end;
+ struct s5k4ecgx_regset_table af_assist_flash_start;
+ struct s5k4ecgx_regset_table af_assist_flash_end;
+ struct s5k4ecgx_regset_table af_low_light_mode_on;
+ struct s5k4ecgx_regset_table af_low_light_mode_off;
+ struct s5k4ecgx_regset_table ae_awb_lock_on;
+ struct s5k4ecgx_regset_table ae_awb_lock_off;
+ struct s5k4ecgx_regset_table low_cap_on;
+ struct s5k4ecgx_regset_table low_cap_off;
+ struct s5k4ecgx_regset_table wdr_on;
+ struct s5k4ecgx_regset_table wdr_off;
+ struct s5k4ecgx_regset_table face_detection_on;
+ struct s5k4ecgx_regset_table face_detection_off;
+ struct s5k4ecgx_regset_table capture_start;
+ struct s5k4ecgx_regset_table af_macro_mode_1;
+ struct s5k4ecgx_regset_table af_macro_mode_2;
+ struct s5k4ecgx_regset_table af_macro_mode_3;
+ struct s5k4ecgx_regset_table af_normal_mode_1;
+ struct s5k4ecgx_regset_table af_normal_mode_2;
+ struct s5k4ecgx_regset_table af_normal_mode_3;
+ struct s5k4ecgx_regset_table af_return_macro_position;
+ struct s5k4ecgx_regset_table single_af_start;
+ struct s5k4ecgx_regset_table single_af_off_1;
+ struct s5k4ecgx_regset_table single_af_off_2;
+ struct s5k4ecgx_regset_table dtp_start;
+ struct s5k4ecgx_regset_table dtp_stop;
+ struct s5k4ecgx_regset_table init_reg_1;
+ struct s5k4ecgx_regset_table init_reg_2;
+ struct s5k4ecgx_regset_table flash_init;
+ struct s5k4ecgx_regset_table reset_crop;
+ struct s5k4ecgx_regset_table get_ae_stable_status;
+ struct s5k4ecgx_regset_table get_light_level;
+ struct s5k4ecgx_regset_table get_1st_af_search_status;
+ struct s5k4ecgx_regset_table get_2nd_af_search_status;
+ struct s5k4ecgx_regset_table get_capture_status;
+ struct s5k4ecgx_regset_table get_esd_status;
+ struct s5k4ecgx_regset_table get_iso;
+ struct s5k4ecgx_regset_table get_shutterspeed;
+};
+
+#ifdef CONFIG_VIDEO_S5K4ECGX_V_1_0
+static const struct s5k4ecgx_regs regs_for_fw_version_1_0 = {
+ .ev = {
+ S5K4ECGX_REGSET(EV_MINUS_4, s5k4ecgx_EV_Minus_4_v1),
+ S5K4ECGX_REGSET(EV_MINUS_3, s5k4ecgx_EV_Minus_3_v1),
+ S5K4ECGX_REGSET(EV_MINUS_2, s5k4ecgx_EV_Minus_2_v1),
+ S5K4ECGX_REGSET(EV_MINUS_1, s5k4ecgx_EV_Minus_1_v1),
+ S5K4ECGX_REGSET(EV_DEFAULT, s5k4ecgx_EV_Default_v1),
+ S5K4ECGX_REGSET(EV_PLUS_1, s5k4ecgx_EV_Plus_1_v1),
+ S5K4ECGX_REGSET(EV_PLUS_2, s5k4ecgx_EV_Plus_2_v1),
+ S5K4ECGX_REGSET(EV_PLUS_3, s5k4ecgx_EV_Plus_3_v1),
+ S5K4ECGX_REGSET(EV_PLUS_4, s5k4ecgx_EV_Plus_4_v1),
+ },
+ .metering = {
+ S5K4ECGX_REGSET(METERING_MATRIX, s5k4ecgx_Metering_Matrix_v1),
+ S5K4ECGX_REGSET(METERING_CENTER, s5k4ecgx_Metering_Center_v1),
+ S5K4ECGX_REGSET(METERING_SPOT, s5k4ecgx_Metering_Spot_v1),
+ },
+ .iso = {
+ S5K4ECGX_REGSET(ISO_AUTO, s5k4ecgx_ISO_Auto_v1),
+ S5K4ECGX_REGSET(ISO_50, s5k4ecgx_ISO_100_v1), /* use 100 */
+ S5K4ECGX_REGSET(ISO_100, s5k4ecgx_ISO_100_v1),
+ S5K4ECGX_REGSET(ISO_200, s5k4ecgx_ISO_200_v1),
+ S5K4ECGX_REGSET(ISO_400, s5k4ecgx_ISO_400_v1),
+ S5K4ECGX_REGSET(ISO_800, s5k4ecgx_ISO_400_v1), /* use 400 */
+ S5K4ECGX_REGSET(ISO_1600, s5k4ecgx_ISO_400_v1), /* use 400 */
+ S5K4ECGX_REGSET(ISO_SPORTS, s5k4ecgx_ISO_Auto_v1),/* use auto */
+ S5K4ECGX_REGSET(ISO_NIGHT, s5k4ecgx_ISO_Auto_v1), /* use auto */
+ S5K4ECGX_REGSET(ISO_MOVIE, s5k4ecgx_ISO_Auto_v1), /* use auto */
+ },
+ .effect = {
+ S5K4ECGX_REGSET(IMAGE_EFFECT_NONE, s5k4ecgx_Effect_Normal_v1),
+ S5K4ECGX_REGSET(IMAGE_EFFECT_BNW,
+ s5k4ecgx_Effect_Black_White_v1),
+ S5K4ECGX_REGSET(IMAGE_EFFECT_SEPIA, s5k4ecgx_Effect_Sepia_v1),
+ S5K4ECGX_REGSET(IMAGE_EFFECT_NEGATIVE,
+ s5k4ecgx_Effect_Negative_v1),
+ },
+ .white_balance = {
+ S5K4ECGX_REGSET(WHITE_BALANCE_AUTO, s5k4ecgx_WB_Auto_v1),
+ S5K4ECGX_REGSET(WHITE_BALANCE_SUNNY, s5k4ecgx_WB_Sunny_v1),
+ S5K4ECGX_REGSET(WHITE_BALANCE_CLOUDY, s5k4ecgx_WB_Cloudy_v1),
+ S5K4ECGX_REGSET(WHITE_BALANCE_TUNGSTEN,
+ s5k4ecgx_WB_Tungsten_v1),
+ S5K4ECGX_REGSET(WHITE_BALANCE_FLUORESCENT,
+ s5k4ecgx_WB_Fluorescent_v1),
+ },
+ .preview_size = {
+ S5K4ECGX_REGSET(S5K4ECGX_PREVIEW_QCIF, s5k4ecgx_176_Preview_v1),
+ S5K4ECGX_REGSET(S5K4ECGX_PREVIEW_CIF, s5k4ecgx_352_Preview_v1),
+ S5K4ECGX_REGSET(S5K4ECGX_PREVIEW_VGA, s5k4ecgx_640_Preview_v1),
+ S5K4ECGX_REGSET(S5K4ECGX_PREVIEW_D1, s5k4ecgx_720_Preview_v1),
+ },
+ .capture_size = {
+ S5K4ECGX_REGSET(S5K4ECGX_CAPTURE_VGA, s5k4ecgx_VGA_Capture_v1),
+ S5K4ECGX_REGSET(S5K4ECGX_CAPTURE_1MP, s5k4ecgx_1M_Capture_v1),
+ S5K4ECGX_REGSET(S5K4ECGX_CAPTURE_2MP, s5k4ecgx_2M_Capture_v1),
+ S5K4ECGX_REGSET(S5K4ECGX_CAPTURE_3MP, s5k4ecgx_3M_Capture_v1),
+ S5K4ECGX_REGSET(S5K4ECGX_CAPTURE_5MP, s5k4ecgx_5M_Capture_v1),
+ },
+ .scene_mode = {
+ S5K4ECGX_REGSET(SCENE_MODE_NONE, s5k4ecgx_Scene_Default_v1),
+ S5K4ECGX_REGSET(SCENE_MODE_PORTRAIT,
+ s5k4ecgx_Scene_Portrait_v1),
+ S5K4ECGX_REGSET(SCENE_MODE_NIGHTSHOT,
+ s5k4ecgx_Scene_Nightshot_v1),
+ S5K4ECGX_REGSET(SCENE_MODE_LANDSCAPE,
+ s5k4ecgx_Scene_Landscape_v1),
+ S5K4ECGX_REGSET(SCENE_MODE_SPORTS, s5k4ecgx_Scene_Sports_v1),
+ S5K4ECGX_REGSET(SCENE_MODE_PARTY_INDOOR,
+ s5k4ecgx_Scene_Party_Indoor_v1),
+ S5K4ECGX_REGSET(SCENE_MODE_BEACH_SNOW,
+ s5k4ecgx_Scene_Beach_Snow_v1),
+ S5K4ECGX_REGSET(SCENE_MODE_SUNSET, s5k4ecgx_Scene_Sunset_v1),
+ S5K4ECGX_REGSET(SCENE_MODE_FIREWORKS,
+ s5k4ecgx_Scene_Fireworks_v1),
+ S5K4ECGX_REGSET(SCENE_MODE_CANDLE_LIGHT,
+ s5k4ecgx_Scene_Candle_Light_v1),
+ },
+ .saturation = {
+ S5K4ECGX_REGSET(SATURATION_MINUS_2,
+ s5k4ecgx_Saturation_Minus_2_v1),
+ S5K4ECGX_REGSET(SATURATION_MINUS_1,
+ s5k4ecgx_Saturation_Minus_1_v1),
+ S5K4ECGX_REGSET(SATURATION_DEFAULT,
+ s5k4ecgx_Saturation_Default_v1),
+ S5K4ECGX_REGSET(SATURATION_PLUS_1,
+ s5k4ecgx_Saturation_Plus_1_v1),
+ S5K4ECGX_REGSET(SATURATION_PLUS_2,
+ s5k4ecgx_Saturation_Plus_2_v1),
+ },
+ .contrast = {
+ S5K4ECGX_REGSET(CONTRAST_MINUS_2, s5k4ecgx_Contrast_Minus_2_v1),
+ S5K4ECGX_REGSET(CONTRAST_MINUS_1, s5k4ecgx_Contrast_Minus_1_v1),
+ S5K4ECGX_REGSET(CONTRAST_DEFAULT, s5k4ecgx_Contrast_Default_v1),
+ S5K4ECGX_REGSET(CONTRAST_PLUS_1, s5k4ecgx_Contrast_Plus_1_v1),
+ S5K4ECGX_REGSET(CONTRAST_PLUS_2, s5k4ecgx_Contrast_Plus_2_v1),
+ },
+ .sharpness = {
+ S5K4ECGX_REGSET(SHARPNESS_MINUS_2,
+ s5k4ecgx_Sharpness_Minus_2_v1),
+ S5K4ECGX_REGSET(SHARPNESS_MINUS_1,
+ s5k4ecgx_Sharpness_Minus_1_v1),
+ S5K4ECGX_REGSET(SHARPNESS_DEFAULT,
+ s5k4ecgx_Sharpness_Default_v1),
+ S5K4ECGX_REGSET(SHARPNESS_PLUS_1, s5k4ecgx_Sharpness_Plus_1_v1),
+ S5K4ECGX_REGSET(SHARPNESS_PLUS_2, s5k4ecgx_Sharpness_Plus_2_v1),
+ },
+ .preview_return = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Preview_Return_v1),
+ .jpeg_quality_high =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_Jpeg_Quality_High_v1),
+ .jpeg_quality_normal =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_Jpeg_Quality_Normal_v1),
+ .jpeg_quality_low = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Jpeg_Quality_Low_v1),
+ .flash_start = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Flash_Start_v1),
+ .flash_end = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Flash_End_v1),
+ .af_assist_flash_start =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_Pre_Flash_Start_v1),
+ .af_assist_flash_end =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_Pre_Flash_End_v1),
+ .af_low_light_mode_on =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_AF_Low_Light_Mode_On_v1),
+ .af_low_light_mode_off =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_AF_Low_Light_Mode_Off_v1),
+ .ae_awb_lock_on =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_AE_AWB_Lock_On_v1),
+ .ae_awb_lock_off =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_AE_AWB_Lock_Off_v1),
+ .low_cap_on = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Low_Cap_On_v1),
+ .low_cap_off = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Low_Cap_Off_v1),
+ .wdr_on = S5K4ECGX_REGSET_TABLE(s5k4ecgx_WDR_on_v1),
+ .wdr_off = S5K4ECGX_REGSET_TABLE(s5k4ecgx_WDR_off_v1),
+ .face_detection_on =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_Face_Detection_On_v1),
+ .face_detection_off =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_Face_Detection_Off_v1),
+ .capture_start = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Capture_Start_v1),
+ .af_macro_mode_1 = S5K4ECGX_REGSET_TABLE(s5k4ecgx_AF_Macro_mode_1_v1),
+ .af_macro_mode_2 = S5K4ECGX_REGSET_TABLE(s5k4ecgx_AF_Macro_mode_2_v1),
+ .af_macro_mode_3 = S5K4ECGX_REGSET_TABLE(s5k4ecgx_AF_Macro_mode_3_v1),
+ .af_normal_mode_1 = S5K4ECGX_REGSET_TABLE(s5k4ecgx_AF_Normal_mode_1_v1),
+ .af_normal_mode_2 = S5K4ECGX_REGSET_TABLE(s5k4ecgx_AF_Normal_mode_2_v1),
+ .af_normal_mode_3 = S5K4ECGX_REGSET_TABLE(s5k4ecgx_AF_Normal_mode_3_v1),
+ .af_return_macro_position =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_AF_Return_Macro_pos_v1),
+ .single_af_start = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Single_AF_Start_v1),
+ .single_af_off_1 = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Single_AF_Off_1_v1),
+ .single_af_off_2 = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Single_AF_Off_2_v1),
+ .dtp_start = S5K4ECGX_REGSET_TABLE(s5k4ecgx_DTP_init_v1),
+ .dtp_stop = S5K4ECGX_REGSET_TABLE(s5k4ecgx_DTP_stop_v1),
+ .init_reg_1 = S5K4ECGX_REGSET_TABLE(s5k4ecgx_init_reg1_v1),
+ .init_reg_2 = S5K4ECGX_REGSET_TABLE(s5k4ecgx_init_reg2_v1),
+ .flash_init = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Flash_init_v1),
+ .reset_crop = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Reset_Crop_v1),
+ .get_ae_stable_status =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_Get_AE_Stable_Status_v1),
+ .get_light_level = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Get_Light_Level_v1),
+ .get_1st_af_search_status =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_get_1st_af_search_status_v1),
+ .get_2nd_af_search_status =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_get_2nd_af_search_status_v1),
+ .get_capture_status =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_get_capture_status_v1),
+ .get_esd_status = S5K4ECGX_REGSET_TABLE(s5k4ecgx_get_esd_status_v1),
+ .get_iso = S5K4ECGX_REGSET_TABLE(s5k4ecgx_get_iso_reg_v1),
+ .get_shutterspeed =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_get_shutterspeed_reg_v1),
+};
+#endif
+
+#ifdef CONFIG_VIDEO_S5K4ECGX_V_1_1
+static const struct s5k4ecgx_regs regs_for_fw_version_1_1 = {
+ .ev = {
+ S5K4ECGX_REGSET(EV_MINUS_4, s5k4ecgx_EV_Minus_4),
+ S5K4ECGX_REGSET(EV_MINUS_3, s5k4ecgx_EV_Minus_3),
+ S5K4ECGX_REGSET(EV_MINUS_2, s5k4ecgx_EV_Minus_2),
+ S5K4ECGX_REGSET(EV_MINUS_1, s5k4ecgx_EV_Minus_1),
+ S5K4ECGX_REGSET(EV_DEFAULT, s5k4ecgx_EV_Default),
+ S5K4ECGX_REGSET(EV_PLUS_1, s5k4ecgx_EV_Plus_1),
+ S5K4ECGX_REGSET(EV_PLUS_2, s5k4ecgx_EV_Plus_2),
+ S5K4ECGX_REGSET(EV_PLUS_3, s5k4ecgx_EV_Plus_3),
+ S5K4ECGX_REGSET(EV_PLUS_4, s5k4ecgx_EV_Plus_4),
+ },
+ .metering = {
+ S5K4ECGX_REGSET(METERING_MATRIX, s5k4ecgx_Metering_Matrix),
+ S5K4ECGX_REGSET(METERING_CENTER, s5k4ecgx_Metering_Center),
+ S5K4ECGX_REGSET(METERING_SPOT, s5k4ecgx_Metering_Spot),
+ },
+ .iso = {
+ S5K4ECGX_REGSET(ISO_AUTO, s5k4ecgx_ISO_Auto),
+ S5K4ECGX_REGSET(ISO_50, s5k4ecgx_ISO_100), /* map to 100 */
+ S5K4ECGX_REGSET(ISO_100, s5k4ecgx_ISO_100),
+ S5K4ECGX_REGSET(ISO_200, s5k4ecgx_ISO_200),
+ S5K4ECGX_REGSET(ISO_400, s5k4ecgx_ISO_400),
+ S5K4ECGX_REGSET(ISO_800, s5k4ecgx_ISO_400), /* map to 400 */
+ S5K4ECGX_REGSET(ISO_1600, s5k4ecgx_ISO_400), /* map to 400 */
+ S5K4ECGX_REGSET(ISO_SPORTS, s5k4ecgx_ISO_Auto),/* map to auto */
+ S5K4ECGX_REGSET(ISO_NIGHT, s5k4ecgx_ISO_Auto), /* map to auto */
+ S5K4ECGX_REGSET(ISO_MOVIE, s5k4ecgx_ISO_Auto), /* map to auto */
+ },
+ .effect = {
+ S5K4ECGX_REGSET(IMAGE_EFFECT_NONE, s5k4ecgx_Effect_Normal),
+ S5K4ECGX_REGSET(IMAGE_EFFECT_BNW, s5k4ecgx_Effect_Black_White),
+ S5K4ECGX_REGSET(IMAGE_EFFECT_SEPIA, s5k4ecgx_Effect_Sepia),
+ S5K4ECGX_REGSET(IMAGE_EFFECT_NEGATIVE,
+ s5k4ecgx_Effect_Negative),
+ },
+ .white_balance = {
+ S5K4ECGX_REGSET(WHITE_BALANCE_AUTO, s5k4ecgx_WB_Auto),
+ S5K4ECGX_REGSET(WHITE_BALANCE_SUNNY, s5k4ecgx_WB_Sunny),
+ S5K4ECGX_REGSET(WHITE_BALANCE_CLOUDY, s5k4ecgx_WB_Cloudy),
+ S5K4ECGX_REGSET(WHITE_BALANCE_TUNGSTEN, s5k4ecgx_WB_Tungsten),
+ S5K4ECGX_REGSET(WHITE_BALANCE_FLUORESCENT,
+ s5k4ecgx_WB_Fluorescent),
+ },
+ .preview_size = {
+ S5K4ECGX_REGSET(S5K4ECGX_PREVIEW_QCIF, s5k4ecgx_176_Preview),
+ S5K4ECGX_REGSET(S5K4ECGX_PREVIEW_CIF, s5k4ecgx_352_Preview),
+ S5K4ECGX_REGSET(S5K4ECGX_PREVIEW_VGA, s5k4ecgx_640_Preview),
+ S5K4ECGX_REGSET(S5K4ECGX_PREVIEW_D1, s5k4ecgx_720_Preview),
+ },
+ .capture_size = {
+ S5K4ECGX_REGSET(S5K4ECGX_CAPTURE_VGA, s5k4ecgx_VGA_Capture),
+ S5K4ECGX_REGSET(S5K4ECGX_CAPTURE_1MP, s5k4ecgx_1M_Capture),
+ S5K4ECGX_REGSET(S5K4ECGX_CAPTURE_2MP, s5k4ecgx_2M_Capture),
+ S5K4ECGX_REGSET(S5K4ECGX_CAPTURE_3MP, s5k4ecgx_3M_Capture),
+ S5K4ECGX_REGSET(S5K4ECGX_CAPTURE_5MP, s5k4ecgx_5M_Capture),
+ },
+ .scene_mode = {
+ S5K4ECGX_REGSET(SCENE_MODE_NONE, s5k4ecgx_Scene_Default),
+ S5K4ECGX_REGSET(SCENE_MODE_PORTRAIT, s5k4ecgx_Scene_Portrait),
+ S5K4ECGX_REGSET(SCENE_MODE_NIGHTSHOT, s5k4ecgx_Scene_Nightshot),
+ S5K4ECGX_REGSET(SCENE_MODE_LANDSCAPE, s5k4ecgx_Scene_Landscape),
+ S5K4ECGX_REGSET(SCENE_MODE_SPORTS, s5k4ecgx_Scene_Sports),
+ S5K4ECGX_REGSET(SCENE_MODE_PARTY_INDOOR,
+ s5k4ecgx_Scene_Party_Indoor),
+ S5K4ECGX_REGSET(SCENE_MODE_BEACH_SNOW,
+ s5k4ecgx_Scene_Beach_Snow),
+ S5K4ECGX_REGSET(SCENE_MODE_SUNSET, s5k4ecgx_Scene_Sunset),
+ S5K4ECGX_REGSET(SCENE_MODE_FIREWORKS, s5k4ecgx_Scene_Fireworks),
+ S5K4ECGX_REGSET(SCENE_MODE_CANDLE_LIGHT,
+ s5k4ecgx_Scene_Candle_Light),
+ },
+ .saturation = {
+ S5K4ECGX_REGSET(SATURATION_MINUS_2,
+ s5k4ecgx_Saturation_Minus_2),
+ S5K4ECGX_REGSET(SATURATION_MINUS_1,
+ s5k4ecgx_Saturation_Minus_1),
+ S5K4ECGX_REGSET(SATURATION_DEFAULT,
+ s5k4ecgx_Saturation_Default),
+ S5K4ECGX_REGSET(SATURATION_PLUS_1, s5k4ecgx_Saturation_Plus_1),
+ S5K4ECGX_REGSET(SATURATION_PLUS_2, s5k4ecgx_Saturation_Plus_2),
+ },
+ .contrast = {
+ S5K4ECGX_REGSET(CONTRAST_MINUS_2, s5k4ecgx_Contrast_Minus_2),
+ S5K4ECGX_REGSET(CONTRAST_MINUS_1, s5k4ecgx_Contrast_Minus_1),
+ S5K4ECGX_REGSET(CONTRAST_DEFAULT, s5k4ecgx_Contrast_Default),
+ S5K4ECGX_REGSET(CONTRAST_PLUS_1, s5k4ecgx_Contrast_Plus_1),
+ S5K4ECGX_REGSET(CONTRAST_PLUS_2, s5k4ecgx_Contrast_Plus_2),
+ },
+ .sharpness = {
+ S5K4ECGX_REGSET(SHARPNESS_MINUS_2, s5k4ecgx_Sharpness_Minus_2),
+ S5K4ECGX_REGSET(SHARPNESS_MINUS_1, s5k4ecgx_Sharpness_Minus_1),
+ S5K4ECGX_REGSET(SHARPNESS_DEFAULT, s5k4ecgx_Sharpness_Default),
+ S5K4ECGX_REGSET(SHARPNESS_PLUS_1, s5k4ecgx_Sharpness_Plus_1),
+ S5K4ECGX_REGSET(SHARPNESS_PLUS_2, s5k4ecgx_Sharpness_Plus_2),
+ },
+ .fps = {
+ S5K4ECGX_REGSET(FRAME_RATE_AUTO, s5k4ecgx_FPS_Auto),
+ S5K4ECGX_REGSET(FRAME_RATE_7, s5k4ecgx_FPS_7),
+ S5K4ECGX_REGSET(FRAME_RATE_15, s5k4ecgx_FPS_15),
+ S5K4ECGX_REGSET(FRAME_RATE_30, s5k4ecgx_FPS_30),
+ },
+ .preview_return = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Preview_Return),
+ .jpeg_quality_high = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Jpeg_Quality_High),
+ .jpeg_quality_normal =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_Jpeg_Quality_Normal),
+ .jpeg_quality_low = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Jpeg_Quality_Low),
+ .flash_start = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Flash_Start),
+ .flash_end = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Flash_End),
+ .af_assist_flash_start =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_Pre_Flash_Start),
+ .af_assist_flash_end =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_Pre_Flash_End),
+ .af_low_light_mode_on =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_AF_Low_Light_Mode_On),
+ .af_low_light_mode_off =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_AF_Low_Light_Mode_Off),
+ .ae_awb_lock_on =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_AE_AWB_Lock_On),
+ .ae_awb_lock_off =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_AE_AWB_Lock_Off),
+ .low_cap_on = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Low_Cap_On),
+ .low_cap_off = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Low_Cap_Off),
+ .wdr_on = S5K4ECGX_REGSET_TABLE(s5k4ecgx_WDR_on),
+ .wdr_off = S5K4ECGX_REGSET_TABLE(s5k4ecgx_WDR_off),
+ .face_detection_on = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Face_Detection_On),
+ .face_detection_off =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_Face_Detection_Off),
+ .capture_start = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Capture_Start),
+ .af_macro_mode_1 = S5K4ECGX_REGSET_TABLE(s5k4ecgx_AF_Macro_mode_1),
+ .af_macro_mode_2 = S5K4ECGX_REGSET_TABLE(s5k4ecgx_AF_Macro_mode_2),
+ .af_macro_mode_3 = S5K4ECGX_REGSET_TABLE(s5k4ecgx_AF_Macro_mode_3),
+ .af_normal_mode_1 = S5K4ECGX_REGSET_TABLE(s5k4ecgx_AF_Normal_mode_1),
+ .af_normal_mode_2 = S5K4ECGX_REGSET_TABLE(s5k4ecgx_AF_Normal_mode_2),
+ .af_normal_mode_3 = S5K4ECGX_REGSET_TABLE(s5k4ecgx_AF_Normal_mode_3),
+ .af_return_macro_position =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_AF_Return_Macro_pos),
+ .single_af_start = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Single_AF_Start),
+ .single_af_off_1 = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Single_AF_Off_1),
+ .single_af_off_2 = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Single_AF_Off_2),
+ .dtp_start = S5K4ECGX_REGSET_TABLE(s5k4ecgx_DTP_init),
+ .dtp_stop = S5K4ECGX_REGSET_TABLE(s5k4ecgx_DTP_stop),
+ .init_reg_1 = S5K4ECGX_REGSET_TABLE(s5k4ecgx_init_reg1),
+ .init_reg_2 = S5K4ECGX_REGSET_TABLE(s5k4ecgx_init_reg2),
+ .flash_init = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Flash_init),
+ .reset_crop = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Reset_Crop),
+ .get_ae_stable_status =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_Get_AE_Stable_Status),
+ .get_light_level = S5K4ECGX_REGSET_TABLE(s5k4ecgx_Get_Light_Level),
+ .get_1st_af_search_status =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_get_1st_af_search_status),
+ .get_2nd_af_search_status =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_get_2nd_af_search_status),
+ .get_capture_status =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_get_capture_status),
+ .get_esd_status = S5K4ECGX_REGSET_TABLE(s5k4ecgx_get_esd_status),
+ .get_iso = S5K4ECGX_REGSET_TABLE(s5k4ecgx_get_iso_reg),
+ .get_shutterspeed =
+ S5K4ECGX_REGSET_TABLE(s5k4ecgx_get_shutterspeed_reg),
+};
+#endif
+
+struct s5k4ecgx_state {
+ struct s5k4ecgx_platform_data *pdata;
+ struct v4l2_subdev sd;
+ struct v4l2_pix_format pix;
+ struct v4l2_fract timeperframe;
+ struct s5k4ecgx_jpeg_param jpeg;
+ struct s5k4ecgx_version fw;
+ struct s5k4ecgx_version prm;
+ struct s5k4ecgx_date_info dateinfo;
+ struct s5k4ecgx_position position;
+ struct v4l2_streamparm strm;
+ struct s5k4ecgx_gps_info gps_info;
+ struct mutex ctrl_lock;
+ enum s5k4ecgx_runmode runmode;
+ enum s5k4ecgx_oprmode oprmode;
+ enum af_operation_status af_status;
+ int preview_framesize_index;
+ int capture_framesize_index;
+ int sensor_version;
+ int freq; /* MCLK in Hz */
+ int check_dataline;
+ int check_previewdata;
+ bool flash_on;
+ bool torch_on;
+ bool sensor_af_in_low_light_mode;
+ bool flash_state_on_previous_capture;
+ bool initialized;
+ bool restore_preview_size_needed;
+ int one_frame_delay_ms;
+ const struct s5k4ecgx_regs *regs;
+};
+
+static const struct v4l2_mbus_framefmt capture_fmts[] = {
+ {
+ .code = V4L2_MBUS_FMT_FIXED,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ },
+};
+
+/**
+ * s5k4ecgx_i2c_read_twobyte: Read 2 bytes from sensor
+ */
+static int s5k4ecgx_i2c_read_twobyte(struct i2c_client *client,
+ u16 subaddr, u16 *data)
+{
+ int err;
+ unsigned char buf[2];
+ struct i2c_msg msg[2];
+
+ cpu_to_be16s(&subaddr);
+
+ msg[0].addr = client->addr;
+ msg[0].flags = 0;
+ msg[0].len = 2;
+ msg[0].buf = (u8 *)&subaddr;
+
+ msg[1].addr = client->addr;
+ msg[1].flags = I2C_M_RD;
+ msg[1].len = 2;
+ msg[1].buf = buf;
+
+ err = i2c_transfer(client->adapter, msg, 2);
+ if (unlikely(err != 2)) {
+ dev_err(&client->dev,
+ "%s: register read fail\n", __func__);
+ return -EIO;
+ }
+
+ *data = ((buf[0] << 8) | buf[1]);
+
+ return 0;
+}
+
+/**
+ * s5k4ecgx_i2c_write_twobyte: 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 s5k4ecgx_i2c_write_twobyte(struct i2c_client *client,
+ u16 addr, u16 w_data)
+{
+ int retry_count = 5;
+ unsigned char buf[4];
+ struct i2c_msg msg = {client->addr, 0, 4, buf};
+ int ret = 0;
+
+ buf[0] = addr >> 8;
+ buf[1] = addr;
+ buf[2] = w_data >> 8;
+ buf[3] = w_data & 0xff;
+
+ s5k4ecgx_debug(S5K4ECGX_DEBUG_I2C, "%s : W(0x%02X%02X%02X%02X)\n",
+ __func__, buf[0], buf[1], buf[2], buf[3]);
+
+ do {
+ ret = i2c_transfer(client->adapter, &msg, 1);
+ if (likely(ret == 1))
+ break;
+ msleep(POLL_TIME_MS);
+ dev_err(&client->dev, "%s: I2C err %d, retry %d.\n",
+ __func__, ret, retry_count);
+ } while (retry_count-- > 0);
+ if (ret != 1) {
+ dev_err(&client->dev, "%s: I2C is not working.\n", __func__);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int s5k4ecgx_write_regs(struct v4l2_subdev *sd, const u32 regs[],
+ int size)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ int i, err;
+
+ for (i = 0; i < size; i++) {
+ err = s5k4ecgx_i2c_write_twobyte(client,
+ (regs[i] >> 16), regs[i]);
+ if (unlikely(err != 0)) {
+ dev_err(&client->dev,
+ "%s: register write failed\n", __func__);
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+static int s5k4ecgx_set_from_table(struct v4l2_subdev *sd,
+ const char *setting_name,
+ const struct s5k4ecgx_regset_table *table,
+ int table_size, int index)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ dev_dbg(&client->dev, "%s: set %s index %d\n",
+ __func__, setting_name, index);
+ if ((index < 0) || (index >= table_size)) {
+ dev_err(&client->dev,
+ "%s: index(%d) out of range[0:%d] for table for %s\n",
+ __func__, index, table_size, setting_name);
+ return -EINVAL;
+ }
+ table += index;
+ if (table->reg == NULL)
+ return -EINVAL;
+ return s5k4ecgx_write_regs(sd, table->reg, table->array_size);
+}
+
+static int s5k4ecgx_set_parameter(struct v4l2_subdev *sd,
+ int *current_value_ptr,
+ int new_value,
+ const char *setting_name,
+ const struct s5k4ecgx_regset_table *table,
+ int table_size)
+{
+ int err;
+
+ if (*current_value_ptr == new_value)
+ return 0;
+
+ err = s5k4ecgx_set_from_table(sd, setting_name, table,
+ table_size, new_value);
+
+ if (!err)
+ *current_value_ptr = new_value;
+ return err;
+}
+
+static int s5k4ecgx_set_preview_stop(struct v4l2_subdev *sd)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+
+ if (state->runmode == S5K4ECGX_RUNMODE_RUNNING)
+ state->runmode = S5K4ECGX_RUNMODE_IDLE;
+
+ dev_dbg(&client->dev, "%s:\n", __func__);
+
+ return 0;
+}
+
+static int s5k4ecgx_set_preview_start(struct v4l2_subdev *sd)
+{
+ int err;
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ bool set_size = true;
+
+ dev_dbg(&client->dev, "%s: runmode = %d\n",
+ __func__, state->runmode);
+
+ if (!state->pix.width || !state->pix.height ||
+ !state->strm.parm.capture.timeperframe.denominator)
+ return -EINVAL;
+
+ if (state->runmode == S5K4ECGX_RUNMODE_CAPTURE) {
+ dev_dbg(&client->dev, "%s: sending Preview_Return cmd\n",
+ __func__);
+ err = s5k4ecgx_set_from_table(sd, "preview return",
+ &state->regs->preview_return, 1, 0);
+ if (err < 0) {
+ dev_err(&client->dev,
+ "%s: failed: s5k4ecgx_Preview_Return\n",
+ __func__);
+ return -EIO;
+ }
+ set_size = state->restore_preview_size_needed;
+ }
+
+ if (set_size) {
+ err = s5k4ecgx_set_from_table(sd, "preview_size",
+ state->regs->preview_size,
+ ARRAY_SIZE(state->regs->preview_size),
+ state->preview_framesize_index);
+ if (err < 0) {
+ dev_err(&client->dev,
+ "%s: failed: Could not set preview size\n",
+ __func__);
+ return -EIO;
+ }
+ }
+
+ dev_dbg(&client->dev, "%s: runmode now RUNNING\n", __func__);
+ state->runmode = S5K4ECGX_RUNMODE_RUNNING;
+
+ return 0;
+}
+
+static int s5k4ecgx_set_capture_size(struct v4l2_subdev *sd)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ int err;
+
+ dev_dbg(&client->dev, "%s: index:%d\n", __func__,
+ state->capture_framesize_index);
+
+ err = s5k4ecgx_set_from_table(sd, "capture_size",
+ state->regs->capture_size,
+ ARRAY_SIZE(state->regs->capture_size),
+ state->capture_framesize_index);
+ if (err < 0) {
+ dev_err(&client->dev,
+ "%s: failed: i2c_write for capture_size index %d\n",
+ __func__, state->capture_framesize_index);
+ }
+ state->runmode = S5K4ECGX_RUNMODE_CAPTURE;
+
+ return err;
+}
+
+static int s5k4ecgx_set_jpeg_quality(struct v4l2_subdev *sd)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+
+ dev_dbg(&client->dev,
+ "%s: jpeg.quality %d\n", __func__, state->jpeg.quality);
+ if (state->jpeg.quality < 0)
+ state->jpeg.quality = 0;
+ if (state->jpeg.quality > 100)
+ state->jpeg.quality = 100;
+
+ switch (state->jpeg.quality) {
+ case 90 ... 100:
+ dev_dbg(&client->dev,
+ "%s: setting to high jpeg quality\n", __func__);
+ return s5k4ecgx_set_from_table(sd, "jpeg quality high",
+ &state->regs->jpeg_quality_high, 1, 0);
+ case 80 ... 89:
+ dev_dbg(&client->dev,
+ "%s: setting to normal jpeg quality\n", __func__);
+ return s5k4ecgx_set_from_table(sd, "jpeg quality normal",
+ &state->regs->jpeg_quality_normal, 1, 0);
+ default:
+ dev_dbg(&client->dev,
+ "%s: setting to low jpeg quality\n", __func__);
+ return s5k4ecgx_set_from_table(sd, "jpeg quality low",
+ &state->regs->jpeg_quality_low, 1, 0);
+ }
+}
+
+static u16 s5k4ecgx_get_light_level(struct v4l2_subdev *sd)
+{
+ int err;
+ u16 read_value = 0;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+
+ err = s5k4ecgx_set_from_table(sd, "get light level",
+ &state->regs->get_light_level, 1, 0);
+ if (err) {
+ dev_err(&client->dev,
+ "%s: write cmd failed, returning 0\n", __func__);
+ goto out;
+ }
+ err = s5k4ecgx_i2c_read_twobyte(client, 0x0F12, &read_value);
+ if (err) {
+ dev_err(&client->dev,
+ "%s: read cmd failed, returning 0\n", __func__);
+ goto out;
+ }
+
+ dev_dbg(&client->dev, "%s: read_value = %d (0x%X)\n",
+ __func__, read_value, read_value);
+
+out:
+ /* restore write mode */
+ s5k4ecgx_i2c_write_twobyte(client, 0x0028, 0x7000);
+ return read_value;
+}
+
+static int s5k4ecgx_start_capture(struct v4l2_subdev *sd)
+{
+ int err;
+ u16 read_value;
+ u16 light_level;
+ int poll_time_ms;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ struct sec_cam_parm *parms =
+ (struct sec_cam_parm *)&state->strm.parm.raw_data;
+ struct s5k4ecgx_platform_data *pdata = client->dev.platform_data;
+
+ /* reset cropping if our current preview is not 640x480,
+ * otherwise the capture will be wrong because of the cropping
+ */
+ if (state->preview_framesize_index != S5K4ECGX_PREVIEW_VGA) {
+ int err = s5k4ecgx_set_from_table(sd, "reset crop",
+ &state->regs->reset_crop, 1, 0);
+ if (err < 0) {
+ dev_err(&client->dev,
+ "%s: failed: Could not set preview size\n",
+ __func__);
+ return -EIO;
+ }
+ state->restore_preview_size_needed = true;
+ } else
+ state->restore_preview_size_needed = false;
+
+ msleep(50);
+ light_level = s5k4ecgx_get_light_level(sd);
+
+ dev_dbg(&client->dev, "%s: light_level = %d\n", __func__,
+ light_level);
+
+ state->flash_state_on_previous_capture = false;
+ if (parms->scene_mode != SCENE_MODE_NIGHTSHOT) {
+ switch (parms->flash_mode) {
+ case FLASH_MODE_AUTO:
+ if (light_level > LOW_LIGHT_LEVEL) {
+ /* light level bright enough
+ * that we don't need flash
+ */
+ break;
+ }
+ /* fall through to flash start */
+ case FLASH_MODE_ON:
+ if (parms->focus_mode == FOCUS_MODE_INFINITY) {
+ s5k4ecgx_set_from_table(sd,
+ "AF assist flash start",
+ &state->regs->af_assist_flash_start,
+ 1, 0);
+ s5k4ecgx_set_from_table(sd,
+ "AF assist flash end",
+ &state->regs->af_assist_flash_end,
+ 1, 0);
+ msleep(10);
+ }
+ s5k4ecgx_set_from_table(sd, "flash start",
+ &state->regs->flash_start, 1, 0);
+ state->flash_on = true;
+ state->flash_state_on_previous_capture = true;
+ pdata->flash_onoff(1);
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* if light is low, use low light capture settings, EXCEPT
+ * if scene mode set to NIGHTSHOT or SPORTS because they
+ * have their own settings (though a low light sport setting
+ * could be useful)
+ */
+ if ((light_level <= HIGH_LIGHT_LEVEL) &&
+ (parms->scene_mode != SCENE_MODE_NIGHTSHOT) &&
+ (parms->scene_mode != SCENE_MODE_SPORTS)) {
+ s5k4ecgx_set_from_table(sd, "low cap on",
+ &state->regs->low_cap_on, 1, 0);
+ }
+
+ err = s5k4ecgx_set_capture_size(sd);
+ if (err < 0) {
+ dev_err(&client->dev,
+ "%s: failed: i2c_write for capture_resolution\n",
+ __func__);
+ return -EIO;
+ }
+
+ dev_dbg(&client->dev, "%s: send Capture_Start cmd\n", __func__);
+ s5k4ecgx_set_from_table(sd, "capture start",
+ &state->regs->capture_start, 1, 0);
+
+ /* a shot takes takes at least 50ms so sleep that amount first
+ * and then start polling for completion.
+ */
+ msleep(50);
+ /* Enter read mode */
+ s5k4ecgx_i2c_write_twobyte(client, 0x002C, 0x7000);
+ poll_time_ms = 50;
+ do {
+ s5k4ecgx_set_from_table(sd, "get capture status",
+ &state->regs->get_capture_status, 1, 0);
+ s5k4ecgx_i2c_read_twobyte(client, 0x0F12, &read_value);
+ dev_dbg(&client->dev,
+ "%s: s5k4ecgx_Capture_Start check = %#x\n",
+ __func__, read_value);
+ if (read_value != 0x00)
+ break;
+ msleep(POLL_TIME_MS);
+ poll_time_ms += POLL_TIME_MS;
+ } while (poll_time_ms < CAPTURE_POLL_TIME_MS);
+
+ dev_dbg(&client->dev, "%s: capture done check finished after %d ms\n",
+ __func__, poll_time_ms);
+
+ /* restore write mode */
+ s5k4ecgx_i2c_write_twobyte(client, 0x0028, 0x7000);
+
+ s5k4ecgx_set_from_table(sd, "ae awb lock off",
+ &state->regs->ae_awb_lock_off, 1, 0);
+
+ if ((light_level <= HIGH_LIGHT_LEVEL) &&
+ (parms->scene_mode != SCENE_MODE_NIGHTSHOT) &&
+ (parms->scene_mode != SCENE_MODE_SPORTS)) {
+ s5k4ecgx_set_from_table(sd, "low cap off",
+ &state->regs->low_cap_off, 1, 0);
+ }
+
+ if ((parms->scene_mode != SCENE_MODE_NIGHTSHOT) && (state->flash_on)) {
+ state->flash_on = false;
+ pdata->flash_onoff(0);
+ s5k4ecgx_set_from_table(sd, "flash end",
+ &state->regs->flash_end, 1, 0);
+ }
+
+ return 0;
+}
+
+/* wide dynamic range support */
+static int s5k4ecgx_set_wdr(struct v4l2_subdev *sd, int value)
+{
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+
+ if (value == WDR_ON)
+ return s5k4ecgx_set_from_table(sd, "wdr on",
+ &state->regs->wdr_on, 1, 0);
+ return s5k4ecgx_set_from_table(sd, "wdr off",
+ &state->regs->wdr_off, 1, 0);
+}
+
+static int s5k4ecgx_set_face_detection(struct v4l2_subdev *sd, int value)
+{
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+
+ if (value == FACE_DETECTION_ON)
+ return s5k4ecgx_set_from_table(sd, "face detection on",
+ &state->regs->face_detection_on, 1, 0);
+ return s5k4ecgx_set_from_table(sd, "face detection off",
+ &state->regs->face_detection_off, 1, 0);
+}
+
+static int s5k4ecgx_return_focus(struct v4l2_subdev *sd)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+
+ err = s5k4ecgx_set_from_table(sd,
+ "af normal mode 1",
+ &state->regs->af_normal_mode_1, 1, 0);
+ if (err < 0)
+ goto fail;
+ msleep(FIRST_SETTING_FOCUS_MODE_DELAY_MS);
+ err = s5k4ecgx_set_from_table(sd,
+ "af normal mode 2",
+ &state->regs->af_normal_mode_2, 1, 0);
+ if (err < 0)
+ goto fail;
+ msleep(SECOND_SETTING_FOCUS_MODE_DELAY_MS);
+ err = s5k4ecgx_set_from_table(sd,
+ "af normal mode 3",
+ &state->regs->af_normal_mode_3, 1, 0);
+ if (err < 0)
+ goto fail;
+
+ return 0;
+fail:
+ dev_err(&client->dev,
+ "%s: i2c_write failed\n", __func__);
+ return -EIO;
+}
+
+static int s5k4ecgx_set_focus_mode(struct v4l2_subdev *sd, int value)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ struct sec_cam_parm *parms =
+ (struct sec_cam_parm *)&state->strm.parm.raw_data;
+ int err;
+
+ if (parms->focus_mode == value)
+ return 0;
+
+ dev_dbg(&client->dev, "%s value(%d)\n", __func__, value);
+
+ switch (value) {
+ case FOCUS_MODE_MACRO:
+ dev_dbg(&client->dev,
+ "%s: FOCUS_MODE_MACRO\n", __func__);
+ err = s5k4ecgx_set_from_table(sd, "af macro mode 1",
+ &state->regs->af_macro_mode_1, 1, 0);
+ if (err < 0)
+ goto fail;
+ msleep(FIRST_SETTING_FOCUS_MODE_DELAY_MS);
+ err = s5k4ecgx_set_from_table(sd, "af macro mode 2",
+ &state->regs->af_macro_mode_2, 1, 0);
+ if (err < 0)
+ goto fail;
+ msleep(SECOND_SETTING_FOCUS_MODE_DELAY_MS);
+ err = s5k4ecgx_set_from_table(sd, "af macro mode 3",
+ &state->regs->af_macro_mode_3, 1, 0);
+ if (err < 0)
+ goto fail;
+ parms->focus_mode = FOCUS_MODE_MACRO;
+ break;
+
+ case FOCUS_MODE_INFINITY:
+ case FOCUS_MODE_AUTO:
+ err = s5k4ecgx_set_from_table(sd,
+ "af normal mode 1",
+ &state->regs->af_normal_mode_1, 1, 0);
+ if (err < 0)
+ goto fail;
+ msleep(FIRST_SETTING_FOCUS_MODE_DELAY_MS);
+ err = s5k4ecgx_set_from_table(sd,
+ "af normal mode 2",
+ &state->regs->af_normal_mode_2, 1, 0);
+ if (err < 0)
+ goto fail;
+ msleep(SECOND_SETTING_FOCUS_MODE_DELAY_MS);
+ err = s5k4ecgx_set_from_table(sd,
+ "af normal mode 3",
+ &state->regs->af_normal_mode_3, 1, 0);
+ if (err < 0)
+ goto fail;
+ parms->focus_mode = value;
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
+
+ return 0;
+fail:
+ dev_err(&client->dev,
+ "%s: i2c_write failed\n", __func__);
+ return -EIO;
+}
+
+static void s5k4ecgx_auto_focus_flash_start(struct v4l2_subdev *sd)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ struct s5k4ecgx_platform_data *pdata = client->dev.platform_data;
+ int count;
+ u16 read_value;
+
+ s5k4ecgx_set_from_table(sd, "AF assist flash start",
+ &state->regs->af_assist_flash_start, 1, 0);
+ state->flash_on = true;
+ pdata->af_assist_onoff(1);
+
+ /* delay 200ms (SLSI value) and then poll to see if AE is stable.
+ * once it is stable, lock it and then return to do AF
+ */
+ msleep(200);
+
+ /* enter read mode */
+ s5k4ecgx_i2c_write_twobyte(client, 0x002C, 0x7000);
+ for (count = 0; count < AE_STABLE_SEARCH_COUNT; count++) {
+ if (state->af_status == AF_CANCEL)
+ break;
+ s5k4ecgx_set_from_table(sd, "get ae stable status",
+ &state->regs->get_ae_stable_status, 1, 0);
+ s5k4ecgx_i2c_read_twobyte(client, 0x0F12, &read_value);
+ dev_dbg(&client->dev, "%s: ae stable status = %#x\n",
+ __func__, read_value);
+ if (read_value == 0x1)
+ break;
+ msleep(state->one_frame_delay_ms);
+ }
+
+ /* restore write mode */
+ s5k4ecgx_i2c_write_twobyte(client, 0x0028, 0x7000);
+
+ /* if we were cancelled, turn off flash */
+ if (state->af_status == AF_CANCEL) {
+ dev_dbg(&client->dev,
+ "%s: AF cancelled\n", __func__);
+ s5k4ecgx_set_from_table(sd, "AF assist flash end",
+ &state->regs->af_assist_flash_end, 1, 0);
+ state->flash_on = false;
+ pdata->af_assist_onoff(0);
+ }
+}
+
+static int s5k4ecgx_start_auto_focus(struct v4l2_subdev *sd)
+{
+ int light_level;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ struct sec_cam_parm *parms =
+ (struct sec_cam_parm *)&state->strm.parm.raw_data;
+
+ dev_dbg(&client->dev, "%s: start SINGLE AF operation, flash mode %d\n",
+ __func__, parms->flash_mode);
+
+ /* in case user calls auto_focus repeatedly without a cancel
+ * or a capture, we need to cancel here to allow ae_awb
+ * to work again, or else we could be locked forever while
+ * that app is running, which is not the expected behavior.
+ */
+ s5k4ecgx_set_from_table(sd, "ae awb lock off",
+ &state->regs->ae_awb_lock_off, 1, 0);
+
+ if (parms->scene_mode == SCENE_MODE_NIGHTSHOT) {
+ /* user selected night shot mode, assume we need low light
+ * af mode. flash is always off in night shot mode
+ */
+ goto enable_af_low_light_mode;
+ }
+
+ light_level = s5k4ecgx_get_light_level(sd);
+
+ switch (parms->flash_mode) {
+ case FLASH_MODE_AUTO:
+ if (light_level > LOW_LIGHT_LEVEL) {
+ /* flash not needed */
+ break;
+ }
+ /* fall through to turn on flash for AF assist */
+ case FLASH_MODE_ON:
+ s5k4ecgx_auto_focus_flash_start(sd);
+ if (state->af_status == AF_CANCEL)
+ return 0;
+ break;
+ case FLASH_MODE_OFF:
+ break;
+ default:
+ dev_err(&client->dev,
+ "%s: Unknown Flash mode 0x%x\n",
+ __func__, parms->flash_mode);
+ break;
+ }
+
+ if (light_level > LOW_LIGHT_LEVEL) {
+ if (state->sensor_af_in_low_light_mode) {
+ state->sensor_af_in_low_light_mode = false;
+ s5k4ecgx_set_from_table(sd, "af low light mode off",
+ &state->regs->af_low_light_mode_off, 1, 0);
+ }
+ } else {
+enable_af_low_light_mode:
+ if (!state->sensor_af_in_low_light_mode) {
+ state->sensor_af_in_low_light_mode = true;
+ s5k4ecgx_set_from_table(sd, "af low light mode on",
+ &state->regs->af_low_light_mode_on, 1, 0);
+ }
+ }
+
+ s5k4ecgx_set_from_table(sd, "single af start",
+ &state->regs->single_af_start, 1, 0);
+ state->af_status = AF_INITIAL;
+ dev_dbg(&client->dev, "%s: af_status set to start\n", __func__);
+
+ return 0;
+}
+
+/* called by HAL after auto focus was finished.
+ * it might off the assist flash
+ */
+static int s5k4ecgx_finish_auto_focus(struct v4l2_subdev *sd)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+
+ /* restore write mode */
+ s5k4ecgx_i2c_write_twobyte(client, 0x0028, 0x7000);
+
+ if (state->flash_on) {
+ struct s5k4ecgx_platform_data *pd = client->dev.platform_data;
+ s5k4ecgx_set_from_table(sd, "AF assist flash end",
+ &state->regs->af_assist_flash_end, 1, 0);
+ state->flash_on = false;
+ pd->af_assist_onoff(0);
+ }
+
+ dev_dbg(&client->dev, "%s: single AF finished\n", __func__);
+ state->af_status = AF_NONE;
+ return 0;
+}
+
+static int s5k4ecgx_stop_auto_focus(struct v4l2_subdev *sd)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ struct sec_cam_parm *parms =
+ (struct sec_cam_parm *)&state->strm.parm.raw_data;
+ int focus_mode = parms->focus_mode;
+
+ dev_dbg(&client->dev, "%s: single AF Off command Setting\n", __func__);
+
+ /* always cancel ae_awb, in case AF already finished before
+ * we got called.
+ */
+ /* restore write mode */
+ s5k4ecgx_i2c_write_twobyte(client, 0x0028, 0x7000);
+
+ s5k4ecgx_set_from_table(sd, "ae awb lock off",
+ &state->regs->ae_awb_lock_off, 1, 0);
+ if (state->flash_on)
+ s5k4ecgx_finish_auto_focus(sd);
+
+ 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__);
+
+ if (focus_mode == FOCUS_MODE_MACRO) {
+ /* for change focus mode forcely */
+ parms->focus_mode = -1;
+ s5k4ecgx_set_focus_mode(sd, FOCUS_MODE_MACRO);
+ } else if (focus_mode == FOCUS_MODE_AUTO) {
+ /* for change focus mode forcely */
+ parms->focus_mode = -1;
+ s5k4ecgx_set_focus_mode(sd, FOCUS_MODE_AUTO);
+ }
+
+ return 0;
+ }
+
+ /* auto focus was in progress. the other thread
+ * is either in the middle of s5k4ecgx_get_auto_focus_result_first(),
+ * s5k4ecgx_get_auto_focus_result_second()
+ * or will call it shortly. set a flag to have
+ * it abort it's polling. that thread will
+ * also do cleanup like restore focus position.
+ *
+ * it might be enough to just send sensor commands
+ * to abort auto focus and the other thread would get
+ * that state from it's polling calls, but I'm not sure.
+ */
+ state->af_status = AF_CANCEL;
+ dev_dbg(&client->dev,
+ "%s: sending Single_AF_Off commands to sensor\n", __func__);
+
+ s5k4ecgx_set_from_table(sd, "single af off 1",
+ &state->regs->single_af_off_1, 1, 0);
+
+ msleep(state->one_frame_delay_ms);
+
+ s5k4ecgx_set_from_table(sd, "single af off 2",
+ &state->regs->single_af_off_2, 1, 0);
+
+ return 0;
+}
+
+/* called by HAL after auto focus was started to get the first search result*/
+static int s5k4ecgx_get_auto_focus_result_first(struct v4l2_subdev *sd,
+ struct v4l2_control *ctrl)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ u16 read_value;
+
+ 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;
+ }
+
+ /* must delay 2 frame times before checking result of 1st phase */
+ mutex_unlock(&state->ctrl_lock);
+ msleep(state->one_frame_delay_ms*2);
+ mutex_lock(&state->ctrl_lock);
+
+ /* lock AE and AWB after first AF search */
+ s5k4ecgx_set_from_table(sd, "ae awb lock on",
+ &state->regs->ae_awb_lock_on, 1, 0);
+
+ dev_dbg(&client->dev, "%s: 1st AF search\n", __func__);
+ /* enter read mode */
+ s5k4ecgx_i2c_write_twobyte(client, 0x002C, 0x7000);
+ state->af_status = AF_START;
+ } else if (state->af_status == AF_CANCEL) {
+ dev_dbg(&client->dev,
+ "%s: AF is cancelled while doing\n", __func__);
+ ctrl->value = AUTO_FOCUS_CANCELLED;
+ s5k4ecgx_finish_auto_focus(sd);
+ return 0;
+ }
+ s5k4ecgx_set_from_table(sd, "get 1st af search status",
+ &state->regs->get_1st_af_search_status,
+ 1, 0);
+ s5k4ecgx_i2c_read_twobyte(client, 0x0F12, &read_value);
+ dev_dbg(&client->dev,
+ "%s: 1st i2c_read --- read_value == 0x%x\n",
+ __func__, read_value);
+ ctrl->value = read_value;
+ return 0;
+}
+
+/* called by HAL after first search was succeed to get the second search result*/
+static int s5k4ecgx_get_auto_focus_result_second(struct v4l2_subdev *sd,
+ struct v4l2_control *ctrl)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ u16 read_value;
+
+ if (state->af_status == AF_CANCEL) {
+ dev_dbg(&client->dev,
+ "%s: AF is cancelled while doing\n", __func__);
+ ctrl->value = AUTO_FOCUS_CANCELLED;
+ s5k4ecgx_finish_auto_focus(sd);
+ return 0;
+ }
+ s5k4ecgx_set_from_table(sd, "get 2nd af search status",
+ &state->regs->get_2nd_af_search_status,
+ 1, 0);
+ s5k4ecgx_i2c_read_twobyte(client, 0x0F12, &read_value);
+ dev_dbg(&client->dev,
+ "%s: 2nd i2c_read --- read_value == 0x%x\n",
+ __func__, read_value);
+ ctrl->value = read_value;
+ return 0;
+}
+
+static void s5k4ecgx_init_parameters(struct v4l2_subdev *sd)
+{
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ struct sec_cam_parm *parms =
+ (struct sec_cam_parm *)&state->strm.parm.raw_data;
+
+ state->strm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ parms->capture.capturemode = 0;
+ parms->capture.timeperframe.numerator = 1;
+ parms->capture.timeperframe.denominator = 30;
+ parms->contrast = CONTRAST_DEFAULT;
+ parms->effects = IMAGE_EFFECT_NONE;
+ parms->brightness = EV_DEFAULT;
+ parms->flash_mode = FLASH_MODE_AUTO;
+ parms->focus_mode = FOCUS_MODE_AUTO;
+ parms->iso = ISO_AUTO;
+ parms->metering = METERING_CENTER;
+ parms->saturation = SATURATION_DEFAULT;
+ parms->scene_mode = SCENE_MODE_NONE;
+ parms->sharpness = SHARPNESS_DEFAULT;
+ parms->white_balance = WHITE_BALANCE_AUTO;
+
+ 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;
+
+ state->fw.major = 1;
+
+ state->one_frame_delay_ms = NORMAL_MODE_MAX_ONE_FRAME_DELAY_MS;
+}
+
+static void s5k4ecgx_set_framesize(struct v4l2_subdev *sd,
+ const struct s5k4ecgx_framesize *frmsize,
+ int frmsize_count, bool exact_match);
+static int s5k4ecgx_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
+{
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ dev_dbg(&client->dev, "%s: code = 0x%x, field = 0x%x,"
+ " colorspace = 0x%x, width = %d, height = %d\n",
+ __func__, fmt->code, fmt->field,
+ fmt->colorspace,
+ fmt->width, fmt->height);
+
+ 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 = S5K4ECGX_OPRMODE_IMAGE;
+ /*
+ * In case of image capture mode,
+ * if the given image resolution is not supported,
+ * use the next higher image resolution. */
+ s5k4ecgx_set_framesize(sd, s5k4ecgx_capture_framesize_list,
+ ARRAY_SIZE(s5k4ecgx_capture_framesize_list),
+ false);
+
+ } else {
+ state->oprmode = S5K4ECGX_OPRMODE_VIDEO;
+ /*
+ * In case of video mode,
+ * if the given video resolution is not matching, use
+ * the default rate (currently S5K4ECGX_PREVIEW_WVGA).
+ */
+ s5k4ecgx_set_framesize(sd, s5k4ecgx_preview_framesize_list,
+ ARRAY_SIZE(s5k4ecgx_preview_framesize_list),
+ true);
+ }
+
+ state->jpeg.enable = state->pix.pixelformat == V4L2_PIX_FMT_JPEG;
+
+ return 0;
+}
+
+static int s5k4ecgx_enum_framesizes(struct v4l2_subdev *sd,
+ struct v4l2_frmsizeenum *fsize)
+{
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+
+ /* 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 (SVGA)
+ */
+ fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+ fsize->discrete.width = state->pix.width;
+ fsize->discrete.height = state->pix.height;
+ return 0;
+}
+
+static int s5k4ecgx_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index,
+ enum v4l2_mbus_pixelcode *code)
+{
+ pr_debug("%s: index = %d\n", __func__, index);
+
+ if (index >= ARRAY_SIZE(capture_fmts))
+ return -EINVAL;
+
+ *code = capture_fmts[index].code;
+
+ return 0;
+}
+
+static int s5k4ecgx_try_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
+{
+ int num_entries;
+ int i;
+
+ num_entries = ARRAY_SIZE(capture_fmts);
+
+ pr_debug("%s: code = 0x%x, colorspace = 0x%x, num_entries = %d\n",
+ __func__, fmt->code, fmt->colorspace, num_entries);
+
+ for (i = 0; i < num_entries; i++) {
+ if (capture_fmts[i].code == fmt->code &&
+ capture_fmts[i].colorspace == fmt->colorspace) {
+ pr_debug("%s: match found, returning 0\n", __func__);
+ return 0;
+ }
+ }
+
+ pr_debug("%s: no match found, returning -EINVAL\n", __func__);
+ return -EINVAL;
+}
+
+static void s5k4ecgx_enable_torch(struct v4l2_subdev *sd)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ struct s5k4ecgx_platform_data *pdata = client->dev.platform_data;
+
+ s5k4ecgx_set_from_table(sd, "torch start",
+ &state->regs->flash_start, 1, 0);
+ state->torch_on = true;
+ pdata->torch_onoff(1);
+}
+
+static void s5k4ecgx_disable_torch(struct v4l2_subdev *sd)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ struct s5k4ecgx_platform_data *pdata = client->dev.platform_data;
+
+ if (state->torch_on) {
+ state->torch_on = false;
+ pdata->torch_onoff(0);
+ s5k4ecgx_set_from_table(sd, "torch end",
+ &state->regs->flash_end, 1, 0);
+ }
+}
+static int s5k4ecgx_set_flash_mode(struct v4l2_subdev *sd, int value)
+{
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ struct sec_cam_parm *parms =
+ (struct sec_cam_parm *)&state->strm.parm.raw_data;
+
+ if (parms->flash_mode == value)
+ return 0;
+
+ if ((value >= FLASH_MODE_OFF) && (value <= FLASH_MODE_TORCH)) {
+ pr_debug("%s: setting flash mode to %d\n",
+ __func__, value);
+ parms->flash_mode = value;
+ if (parms->flash_mode == FLASH_MODE_TORCH)
+ s5k4ecgx_enable_torch(sd);
+ else
+ s5k4ecgx_disable_torch(sd);
+ return 0;
+ }
+ pr_debug("%s: trying to set invalid flash mode %d\n",
+ __func__, value);
+ return -EINVAL;
+}
+
+static int s5k4ecgx_g_parm(struct v4l2_subdev *sd,
+ struct v4l2_streamparm *param)
+{
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+
+ memcpy(param, &state->strm, sizeof(param));
+ return 0;
+}
+
+static int s5k4ecgx_s_parm(struct v4l2_subdev *sd,
+ struct v4l2_streamparm *param)
+{
+ int err = 0;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ struct sec_cam_parm *new_parms =
+ (struct sec_cam_parm *)&param->parm.raw_data;
+ struct sec_cam_parm *parms =
+ (struct sec_cam_parm *)&state->strm.parm.raw_data;
+
+ dev_dbg(&client->dev, "%s: start\n", __func__);
+
+ if (param->parm.capture.timeperframe.numerator !=
+ parms->capture.timeperframe.numerator ||
+ param->parm.capture.timeperframe.denominator !=
+ parms->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;
+ }
+
+ /*
+ * 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
+ */
+ parms->capture.timeperframe.numerator = 1;
+ parms->capture.timeperframe.denominator = fps;
+ }
+
+ /* we return an error if one happened but don't stop trying to
+ * set all parameters passed
+ */
+ err = s5k4ecgx_set_parameter(sd, &parms->contrast, new_parms->contrast,
+ "contrast", state->regs->contrast,
+ ARRAY_SIZE(state->regs->contrast));
+ err |= s5k4ecgx_set_parameter(sd, &parms->effects, new_parms->effects,
+ "effect", state->regs->effect,
+ ARRAY_SIZE(state->regs->effect));
+ err |= s5k4ecgx_set_parameter(sd, &parms->brightness,
+ new_parms->brightness, "brightness",
+ state->regs->ev, ARRAY_SIZE(state->regs->ev));
+ err |= s5k4ecgx_set_flash_mode(sd, new_parms->flash_mode);
+ /* Must delay 150ms before setting macro mode due to a camera
+ * sensor requirement */
+ if ((new_parms->focus_mode == FOCUS_MODE_MACRO) &&
+ (parms->focus_mode != FOCUS_MODE_MACRO))
+ msleep(150);
+ err |= s5k4ecgx_set_focus_mode(sd, new_parms->focus_mode);
+ err |= s5k4ecgx_set_parameter(sd, &parms->iso, new_parms->iso,
+ "iso", state->regs->iso,
+ ARRAY_SIZE(state->regs->iso));
+ err |= s5k4ecgx_set_parameter(sd, &parms->metering, new_parms->metering,
+ "metering", state->regs->metering,
+ ARRAY_SIZE(state->regs->metering));
+ err |= s5k4ecgx_set_parameter(sd, &parms->saturation,
+ new_parms->saturation, "saturation",
+ state->regs->saturation,
+ ARRAY_SIZE(state->regs->saturation));
+ err |= s5k4ecgx_set_parameter(sd, &parms->scene_mode,
+ new_parms->scene_mode, "scene_mode",
+ state->regs->scene_mode,
+ ARRAY_SIZE(state->regs->scene_mode));
+ err |= s5k4ecgx_set_parameter(sd, &parms->sharpness,
+ new_parms->sharpness, "sharpness",
+ state->regs->sharpness,
+ ARRAY_SIZE(state->regs->sharpness));
+ err |= s5k4ecgx_set_parameter(sd, &parms->white_balance,
+ new_parms->white_balance, "white balance",
+ state->regs->white_balance,
+ ARRAY_SIZE(state->regs->white_balance));
+ err |= s5k4ecgx_set_parameter(sd, &parms->fps,
+ new_parms->fps, "fps",
+ state->regs->fps,
+ ARRAY_SIZE(state->regs->fps));
+
+ if (parms->scene_mode == SCENE_MODE_NIGHTSHOT)
+ state->one_frame_delay_ms = NIGHT_MODE_MAX_ONE_FRAME_DELAY_MS;
+ else
+ state->one_frame_delay_ms = NORMAL_MODE_MAX_ONE_FRAME_DELAY_MS;
+
+ dev_dbg(&client->dev, "%s: returning %d\n", __func__, err);
+ 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 sets the
+ * most appropriate frame size.
+ *
+ * The list is stored in an increasing order (as far as possible).
+ * Hence 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 perfect match, we set the last entry (which is supposed
+ * to be the largest resolution supported.)
+ */
+static void s5k4ecgx_set_framesize(struct v4l2_subdev *sd,
+ const struct s5k4ecgx_framesize *frmsize,
+ int frmsize_count, bool preview)
+{
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ const struct s5k4ecgx_framesize *last_frmsize =
+ &frmsize[frmsize_count - 1];
+
+ dev_dbg(&client->dev, "%s: Requested Res: %dx%d\n", __func__,
+ state->pix.width, state->pix.height);
+
+ do {
+ /*
+ * In case of image capture mode,
+ * if the given image resolution is not supported,
+ * return the next higher image resolution. */
+ if (preview) {
+ if (frmsize->width == state->pix.width &&
+ frmsize->height == state->pix.height) {
+ break;
+ }
+ } else {
+ dev_dbg(&client->dev,
+ "%s: compare frmsize %dx%d to %dx%d\n",
+ __func__,
+ frmsize->width, frmsize->height,
+ state->pix.width, state->pix.height);
+ if (frmsize->width >= state->pix.width &&
+ frmsize->height >= state->pix.height) {
+ dev_dbg(&client->dev,
+ "%s: select frmsize %dx%d, index=%d\n",
+ __func__,
+ frmsize->width, frmsize->height,
+ frmsize->index);
+ break;
+ }
+ }
+
+ frmsize++;
+ } while (frmsize <= last_frmsize);
+
+ if (frmsize > last_frmsize)
+ frmsize = last_frmsize;
+
+ state->pix.width = frmsize->width;
+ state->pix.height = frmsize->height;
+ if (preview) {
+ state->preview_framesize_index = frmsize->index;
+ dev_dbg(&client->dev, "%s: Preview Res Set: %dx%d, index %d\n",
+ __func__, state->pix.width, state->pix.height,
+ state->preview_framesize_index);
+ } else {
+ state->capture_framesize_index = frmsize->index;
+ dev_dbg(&client->dev, "%s: Capture Res Set: %dx%d, index %d\n",
+ __func__, state->pix.width, state->pix.height,
+ state->capture_framesize_index);
+ }
+}
+
+static int s5k4ecgx_check_dataline_stop(struct v4l2_subdev *sd)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ int err;
+
+ dev_dbg(&client->dev, "%s\n", __func__);
+
+ err = s5k4ecgx_set_from_table(sd, "DTP stop",
+ &state->regs->dtp_stop, 1, 0);
+ if (err < 0) {
+ v4l_info(client, "%s: register set failed\n", __func__);
+ return -EIO;
+ }
+
+ state->check_dataline = 0;
+
+ return err;
+}
+
+static void s5k4ecgx_get_esd_int(struct v4l2_subdev *sd,
+ struct v4l2_control *ctrl)
+{
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ u16 read_value;
+ int err;
+
+ if ((S5K4ECGX_RUNMODE_RUNNING == state->runmode) &&
+ (state->af_status != AF_START)) {
+ err = s5k4ecgx_set_from_table(sd, "get esd status",
+ &state->regs->get_esd_status,
+ 1, 0);
+ err |= s5k4ecgx_i2c_read_twobyte(client, 0x0F12, &read_value);
+ dev_dbg(&client->dev,
+ "%s: read_value == 0x%x\n", __func__, read_value);
+ /* return to write mode */
+ err |= s5k4ecgx_i2c_write_twobyte(client, 0x0028, 0x7000);
+
+ if (err < 0) {
+ v4l_info(client,
+ "Failed I2C for getting ESD information\n");
+ ctrl->value = 0x01;
+ } else {
+ if (read_value != 0x0000) {
+ v4l_info(client, "ESD interrupt happened!!\n");
+ ctrl->value = 0x01;
+ } else {
+ dev_dbg(&client->dev,
+ "%s: No ESD interrupt!!\n", __func__);
+ ctrl->value = 0x00;
+ }
+ }
+ } else
+ ctrl->value = 0x00;
+}
+
+/* returns the real iso currently used by sensor due to lighting
+ * conditions, not the requested iso we sent using s_ctrl.
+ */
+static int s5k4ecgx_get_iso(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ u16 read_value1 = 0;
+ u16 read_value2 = 0;
+ int read_value;
+
+ err = s5k4ecgx_set_from_table(sd, "get iso",
+ &state->regs->get_iso, 1, 0);
+ err |= s5k4ecgx_i2c_read_twobyte(client, 0x0F12, &read_value1);
+ err |= s5k4ecgx_i2c_read_twobyte(client, 0x0F12, &read_value2);
+
+ /* restore write mode */
+ s5k4ecgx_i2c_write_twobyte(client, 0x0028, 0x7000);
+
+ read_value = read_value1 * read_value2 / 384;
+
+ if (read_value > 0x400)
+ ctrl->value = ISO_400;
+ else if (read_value > 0x200)
+ ctrl->value = ISO_200;
+ else if (read_value > 0x100)
+ ctrl->value = ISO_100;
+ else
+ ctrl->value = ISO_50;
+
+ dev_dbg(&client->dev, "%s: get iso == %d (0x%x, 0x%x)\n",
+ __func__, ctrl->value, read_value1, read_value2);
+
+ return err;
+}
+
+static int s5k4ecgx_get_shutterspeed(struct v4l2_subdev *sd,
+ struct v4l2_control *ctrl)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ u16 read_value_1;
+ u16 read_value_2;
+ u32 read_value;
+
+ err = s5k4ecgx_set_from_table(sd, "get shutterspeed",
+ &state->regs->get_shutterspeed, 1, 0);
+ err |= s5k4ecgx_i2c_read_twobyte(client, 0x0F12, &read_value_1);
+ err |= s5k4ecgx_i2c_read_twobyte(client, 0x0F12, &read_value_2);
+
+ read_value = (read_value_2 << 16) | (read_value_1 & 0xffff);
+ /* restore write mode */
+ s5k4ecgx_i2c_write_twobyte(client, 0x0028, 0x7000);
+
+ ctrl->value = read_value * 1000 / 400;
+ dev_dbg(&client->dev,
+ "%s: get shutterspeed == %d\n", __func__, ctrl->value);
+
+ return err;
+}
+
+static int s5k4ecgx_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ struct sec_cam_parm *parms =
+ (struct sec_cam_parm *)&state->strm.parm.raw_data;
+ int err = 0;
+
+ if (!state->initialized) {
+ dev_err(&client->dev,
+ "%s: return error because uninitialized\n", __func__);
+ return -ENODEV;
+ }
+
+ mutex_lock(&state->ctrl_lock);
+
+ switch (ctrl->id) {
+ case V4L2_CID_CAMERA_WHITE_BALANCE:
+ ctrl->value = parms->white_balance;
+ break;
+ case V4L2_CID_CAMERA_EFFECT:
+ ctrl->value = parms->effects;
+ break;
+ case V4L2_CID_CAMERA_CONTRAST:
+ ctrl->value = parms->contrast;
+ break;
+ case V4L2_CID_CAMERA_SATURATION:
+ ctrl->value = parms->saturation;
+ break;
+ case V4L2_CID_CAMERA_SHARPNESS:
+ ctrl->value = parms->sharpness;
+ break;
+ case V4L2_CID_CAM_JPEG_MAIN_SIZE:
+ ctrl->value = state->jpeg.main_size;
+ break;
+ case V4L2_CID_CAM_JPEG_MAIN_OFFSET:
+ ctrl->value = state->jpeg.main_offset;
+ break;
+ case V4L2_CID_CAM_JPEG_THUMB_SIZE:
+ ctrl->value = state->jpeg.thumb_size;
+ break;
+ case V4L2_CID_CAM_JPEG_THUMB_OFFSET:
+ ctrl->value = state->jpeg.thumb_offset;
+ break;
+ case V4L2_CID_CAM_JPEG_POSTVIEW_OFFSET:
+ ctrl->value = state->jpeg.postview_offset;
+ break;
+ case V4L2_CID_CAM_JPEG_MEMSIZE:
+ ctrl->value = SENSOR_JPEG_SNAPSHOT_MEMSIZE;
+ break;
+ case V4L2_CID_CAM_JPEG_QUALITY:
+ ctrl->value = state->jpeg.quality;
+ break;
+ case V4L2_CID_CAMERA_AUTO_FOCUS_RESULT_FIRST:
+ err = s5k4ecgx_get_auto_focus_result_first(sd, ctrl);
+ break;
+ case V4L2_CID_CAMERA_AUTO_FOCUS_RESULT_SECOND:
+ err = s5k4ecgx_get_auto_focus_result_second(sd, ctrl);
+ break;
+ case V4L2_CID_CAM_DATE_INFO_YEAR:
+ ctrl->value = 2010;
+ break;
+ case V4L2_CID_CAM_DATE_INFO_MONTH:
+ ctrl->value = 2;
+ break;
+ case V4L2_CID_CAM_DATE_INFO_DATE:
+ ctrl->value = 25;
+ break;
+ case V4L2_CID_CAM_SENSOR_VER:
+ ctrl->value = 1;
+ break;
+ case V4L2_CID_CAM_FW_MINOR_VER:
+ ctrl->value = state->fw.minor;
+ break;
+ case V4L2_CID_CAM_FW_MAJOR_VER:
+ ctrl->value = state->fw.major;
+ break;
+ case V4L2_CID_CAM_PRM_MINOR_VER:
+ ctrl->value = state->prm.minor;
+ break;
+ case V4L2_CID_CAM_PRM_MAJOR_VER:
+ ctrl->value = state->prm.major;
+ break;
+ case V4L2_CID_ESD_INT:
+ s5k4ecgx_get_esd_int(sd, ctrl);
+ break;
+ case V4L2_CID_CAMERA_GET_ISO:
+ err = s5k4ecgx_get_iso(sd, ctrl);
+ break;
+ case V4L2_CID_CAMERA_GET_SHT_TIME:
+ err = s5k4ecgx_get_shutterspeed(sd, ctrl);
+ break;
+ case V4L2_CID_CAMERA_GET_FLASH_ONOFF:
+ ctrl->value = state->flash_state_on_previous_capture;
+ break;
+ case V4L2_CID_CAMERA_OBJ_TRACKING_STATUS:
+ case V4L2_CID_CAMERA_SMART_AUTO_STATUS:
+ break;
+ default:
+ err = -ENOIOCTLCMD;
+ dev_err(&client->dev, "%s: unknown ctrl id 0x%x\n",
+ __func__, ctrl->id);
+ break;
+ }
+
+ mutex_unlock(&state->ctrl_lock);
+
+ return err;
+}
+
+static int s5k4ecgx_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ struct sec_cam_parm *parms =
+ (struct sec_cam_parm *)&state->strm.parm.raw_data;
+ int err = 0;
+ int value = ctrl->value;
+
+ if (!state->initialized &&
+ (ctrl->id != V4L2_CID_CAMERA_CHECK_DATALINE)) {
+ dev_err(&client->dev,
+ "%s: return error because uninitialized\n", __func__);
+ return -ENODEV;
+ }
+
+ dev_dbg(&client->dev, "%s: V4l2 control ID =%d, val = %d\n",
+ __func__, ctrl->id - V4L2_CID_PRIVATE_BASE, value);
+
+ mutex_lock(&state->ctrl_lock);
+
+ switch (ctrl->id) {
+ case V4L2_CID_CAMERA_FLASH_MODE:
+ err = s5k4ecgx_set_flash_mode(sd, value);
+ break;
+ case V4L2_CID_CAMERA_BRIGHTNESS:
+ if (state->runmode == S5K4ECGX_RUNMODE_RUNNING) {
+ err = s5k4ecgx_set_parameter(sd, &parms->brightness,
+ value, "brightness",
+ state->regs->ev,
+ ARRAY_SIZE(state->regs->ev));
+ } else {
+ dev_err(&client->dev,
+ "%s: trying to set brightness when not "
+ "in preview mode\n",
+ __func__);
+ err = -EINVAL;
+ }
+ break;
+ case V4L2_CID_CAMERA_WHITE_BALANCE:
+ if (state->runmode == S5K4ECGX_RUNMODE_RUNNING) {
+ err = s5k4ecgx_set_parameter(sd, &parms->white_balance,
+ value, "white balance",
+ state->regs->white_balance,
+ ARRAY_SIZE(state->regs->white_balance));
+ } else {
+ dev_err(&client->dev,
+ "%s: trying to set white balance when not "
+ "in preview mode\n",
+ __func__);
+ err = -EINVAL;
+ }
+ break;
+ case V4L2_CID_CAMERA_EFFECT:
+ if (state->runmode == S5K4ECGX_RUNMODE_RUNNING) {
+ err = s5k4ecgx_set_parameter(sd, &parms->effects,
+ value, "effects", state->regs->effect,
+ ARRAY_SIZE(state->regs->effect));
+ } else {
+ dev_err(&client->dev,
+ "%s: trying to set effect when not "
+ "in preview mode\n",
+ __func__);
+ err = -EINVAL;
+ }
+ break;
+ case V4L2_CID_CAMERA_ISO:
+ if (state->runmode == S5K4ECGX_RUNMODE_RUNNING) {
+ err = s5k4ecgx_set_parameter(sd, &parms->iso,
+ value, "iso",
+ state->regs->iso,
+ ARRAY_SIZE(state->regs->iso));
+ } else {
+ dev_err(&client->dev,
+ "%s: trying to set iso when not "
+ "in preview mode\n",
+ __func__);
+ err = -EINVAL;
+ }
+ break;
+ case V4L2_CID_CAMERA_METERING:
+ if (state->runmode == S5K4ECGX_RUNMODE_RUNNING) {
+ err = s5k4ecgx_set_parameter(sd, &parms->metering,
+ value, "metering",
+ state->regs->metering,
+ ARRAY_SIZE(state->regs->metering));
+ } else {
+ dev_err(&client->dev,
+ "%s: trying to set metering when not "
+ "in preview mode\n",
+ __func__);
+ err = -EINVAL;
+ }
+ break;
+ case V4L2_CID_CAMERA_CONTRAST:
+ err = s5k4ecgx_set_parameter(sd, &parms->contrast,
+ value, "contrast",
+ state->regs->contrast,
+ ARRAY_SIZE(state->regs->contrast));
+ break;
+ case V4L2_CID_CAMERA_SATURATION:
+ err = s5k4ecgx_set_parameter(sd, &parms->saturation,
+ value, "saturation",
+ state->regs->saturation,
+ ARRAY_SIZE(state->regs->saturation));
+ break;
+ case V4L2_CID_CAMERA_SHARPNESS:
+ err = s5k4ecgx_set_parameter(sd, &parms->sharpness,
+ value, "sharpness",
+ state->regs->sharpness,
+ ARRAY_SIZE(state->regs->sharpness));
+ break;
+ case V4L2_CID_CAMERA_WDR:
+ err = s5k4ecgx_set_wdr(sd, value);
+ break;
+ case V4L2_CID_CAMERA_FACE_DETECTION:
+ err = s5k4ecgx_set_face_detection(sd, value);
+ break;
+ case V4L2_CID_CAMERA_FOCUS_MODE:
+ err = s5k4ecgx_set_focus_mode(sd, value);
+ break;
+ case V4L2_CID_CAM_JPEG_QUALITY:
+ if (state->runmode == S5K4ECGX_RUNMODE_RUNNING) {
+ state->jpeg.quality = value;
+ err = s5k4ecgx_set_jpeg_quality(sd);
+ } else {
+ dev_err(&client->dev,
+ "%s: trying to set jpeg quality when not "
+ "in preview mode\n",
+ __func__);
+ err = -EINVAL;
+ }
+ break;
+ case V4L2_CID_CAMERA_SCENE_MODE:
+ err = s5k4ecgx_set_parameter(sd, &parms->scene_mode,
+ SCENE_MODE_NONE, "scene_mode",
+ state->regs->scene_mode,
+ ARRAY_SIZE(state->regs->scene_mode));
+ if (err < 0) {
+ dev_err(&client->dev,
+ "%s: failed to set scene-mode default value\n",
+ __func__);
+ break;
+ }
+ if (value != SCENE_MODE_NONE) {
+ err = s5k4ecgx_set_parameter(sd, &parms->scene_mode,
+ value, "scene_mode",
+ state->regs->scene_mode,
+ ARRAY_SIZE(state->regs->scene_mode));
+ }
+ if (parms->scene_mode == SCENE_MODE_NIGHTSHOT) {
+ state->one_frame_delay_ms =
+ NIGHT_MODE_MAX_ONE_FRAME_DELAY_MS;
+ } else {
+ state->one_frame_delay_ms =
+ NORMAL_MODE_MAX_ONE_FRAME_DELAY_MS;
+ }
+
+ break;
+ case V4L2_CID_CAMERA_GPS_LATITUDE:
+ dev_err(&client->dev,
+ "%s: V4L2_CID_CAMERA_GPS_LATITUDE: not implemented\n",
+ __func__);
+ break;
+ case V4L2_CID_CAMERA_GPS_LONGITUDE:
+ dev_err(&client->dev,
+ "%s: V4L2_CID_CAMERA_GPS_LONGITUDE: not implemented\n",
+ __func__);
+ break;
+ case V4L2_CID_CAMERA_GPS_TIMESTAMP:
+ dev_err(&client->dev,
+ "%s: V4L2_CID_CAMERA_GPS_TIMESTAMP: not implemented\n",
+ __func__);
+ break;
+ case V4L2_CID_CAMERA_GPS_ALTITUDE:
+ dev_err(&client->dev,
+ "%s: V4L2_CID_CAMERA_GPS_ALTITUDE: not implemented\n",
+ __func__);
+ break;
+ case V4L2_CID_CAMERA_OBJECT_POSITION_X:
+ state->position.x = value;
+ break;
+ case V4L2_CID_CAMERA_OBJECT_POSITION_Y:
+ state->position.y = value;
+ break;
+ case V4L2_CID_CAMERA_SET_AUTO_FOCUS:
+ if (value == AUTO_FOCUS_ON)
+ err = s5k4ecgx_start_auto_focus(sd);
+ else if (value == AUTO_FOCUS_OFF)
+ err = s5k4ecgx_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:
+ dev_dbg(&client->dev,
+ "%s: camera frame rate request for %d fps\n",
+ __func__, value);
+ err = s5k4ecgx_set_parameter(sd, &parms->fps,
+ value, "fps",
+ state->regs->fps,
+ ARRAY_SIZE(state->regs->fps));
+ break;
+ case V4L2_CID_CAM_CAPTURE:
+ err = s5k4ecgx_start_capture(sd);
+ 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 (value)
+ err = s5k4ecgx_set_preview_start(sd);
+ else
+ err = s5k4ecgx_set_preview_stop(sd);
+ break;
+ case V4L2_CID_CAMERA_CHECK_DATALINE:
+ dev_dbg(&client->dev, "%s: check_dataline set to %d\n",
+ __func__, value);
+ state->check_dataline = value;
+ break;
+ case V4L2_CID_CAMERA_CHECK_DATALINE_STOP:
+ err = s5k4ecgx_check_dataline_stop(sd);
+ break;
+ case V4L2_CID_CAMERA_RETURN_FOCUS:
+ if (parms->focus_mode != FOCUS_MODE_MACRO)
+ err = s5k4ecgx_return_focus(sd);
+ break;
+ case V4L2_CID_CAMERA_FINISH_AUTO_FOCUS:
+ err = s5k4ecgx_finish_auto_focus(sd);
+ break;
+ default:
+ dev_err(&client->dev, "%s: unknown set ctrl id 0x%x\n",
+ __func__, ctrl->id);
+ err = -ENOIOCTLCMD;
+ break;
+ }
+
+ if (err < 0)
+ dev_err(&client->dev, "%s: videoc_s_ctrl failed %d\n", __func__,
+ err);
+
+ mutex_unlock(&state->ctrl_lock);
+
+ dev_dbg(&client->dev, "%s: videoc_s_ctrl returning %d\n",
+ __func__, err);
+
+ return err;
+}
+
+static int s5k4ecgx_s_ext_ctrl(struct v4l2_subdev *sd,
+ struct v4l2_ext_control *ctrl)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ int err = 0;
+ struct gps_info_common *tempGPSType = NULL;
+
+ switch (ctrl->id) {
+
+ case V4L2_CID_CAMERA_GPS_LATITUDE:
+ tempGPSType = (struct gps_info_common *)ctrl->reserved2[1];
+ state->gps_info.gps_buf[0] = tempGPSType->direction;
+ state->gps_info.gps_buf[1] = tempGPSType->dgree;
+ state->gps_info.gps_buf[2] = tempGPSType->minute;
+ state->gps_info.gps_buf[3] = tempGPSType->second;
+ break;
+ case V4L2_CID_CAMERA_GPS_LONGITUDE:
+ tempGPSType = (struct gps_info_common *)ctrl->reserved2[1];
+ state->gps_info.gps_buf[4] = tempGPSType->direction;
+ state->gps_info.gps_buf[5] = tempGPSType->dgree;
+ state->gps_info.gps_buf[6] = tempGPSType->minute;
+ state->gps_info.gps_buf[7] = tempGPSType->second;
+ break;
+ case V4L2_CID_CAMERA_GPS_ALTITUDE:
+ tempGPSType = (struct gps_info_common *)ctrl->reserved2[1];
+ state->gps_info.altitude_buf[0] = tempGPSType->direction;
+ state->gps_info.altitude_buf[1] =
+ (tempGPSType->dgree) & 0x00ff;
+ state->gps_info.altitude_buf[2] =
+ ((tempGPSType->dgree) & 0xff00) >> 8;
+ state->gps_info.altitude_buf[3] = tempGPSType->minute;
+ break;
+ case V4L2_CID_CAMERA_GPS_TIMESTAMP:
+ state->gps_info.gps_timeStamp = *((int *)ctrl->reserved2[1]);
+ err = 0;
+ break;
+ default:
+ dev_err(&client->dev, "%s: unknown ctrl->id %d\n",
+ __func__, ctrl->id);
+ err = -ENOIOCTLCMD;
+ break;
+ }
+
+ if (err < 0)
+ dev_err(&client->dev, "%s: vidioc_s_ext_ctrl failed %d\n",
+ __func__, err);
+
+ return err;
+}
+
+static int s5k4ecgx_s_ext_ctrls(struct v4l2_subdev *sd,
+ struct v4l2_ext_controls *ctrls)
+{
+ struct v4l2_ext_control *ctrl = ctrls->controls;
+ int ret;
+ int i;
+
+ for (i = 0; i < ctrls->count; i++, ctrl++) {
+ ret = s5k4ecgx_s_ext_ctrl(sd, ctrl);
+
+ if (ret) {
+ ctrls->error_idx = i;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+#ifdef CONFIG_VIDEO_S5K4ECGX_DEBUG
+static void s5k4ecgx_dump_regset(struct s5k4ecgx_regset *regset)
+{
+ if ((regset->data[0] == 0x00) && (regset->data[1] == 0x2A)) {
+ if (regset->size <= 6)
+ pr_err("odd regset size %d\n", regset->size);
+ pr_info("regset: addr = 0x%02X%02X, data[0,1] = 0x%02X%02X,"
+ " total data size = %d\n",
+ regset->data[2], regset->data[3],
+ regset->data[6], regset->data[7],
+ regset->size-6);
+ } else {
+ pr_info("regset: 0x%02X%02X%02X%02X\n",
+ regset->data[0], regset->data[1],
+ regset->data[2], regset->data[3]);
+ if (regset->size != 4)
+ pr_err("odd regset size %d\n", regset->size);
+ }
+}
+#endif
+
+static int s5k4ecgx_i2c_write_block(struct v4l2_subdev *sd, u8 *buf, int size)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ int retry_count = 5;
+ int ret;
+ struct i2c_msg msg = {client->addr, 0, size, buf};
+
+#ifdef CONFIG_VIDEO_S5K4ECGX_DEBUG
+ if (s5k4ecgx_debug_mask & S5K4ECGX_DEBUG_I2C_BURSTS) {
+ if ((buf[0] == 0x0F) && (buf[1] == 0x12))
+ pr_info("%s : data[0,1] = 0x%02X%02X,"
+ " total data size = %d\n",
+ __func__, buf[2], buf[3], size-2);
+ else
+ pr_info("%s : 0x%02X%02X%02X%02X\n",
+ __func__, buf[0], buf[1], buf[2], buf[3]);
+ }
+#endif
+
+ do {
+ ret = i2c_transfer(client->adapter, &msg, 1);
+ if (likely(ret == 1))
+ break;
+ msleep(POLL_TIME_MS);
+ } while (retry_count-- > 0);
+ if (ret != 1) {
+ dev_err(&client->dev, "%s: I2C is not working.\n", __func__);
+ return -EIO;
+ }
+
+#ifdef CONFIG_VIDEO_S5K4ECGX_V_1_0
+ {
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ if (state->fw.minor == 0) {
+ /* v1.0 sensor have problems sometimes if we write
+ * too much data too fast, so add a sleep. I've
+ * tried various combinations of size/delay. Checking
+ * for a larger size doesn't seem to work reliably, and
+ * a delay of 1ms sometimes isn't enough either.
+ */
+ if (size > 16)
+ msleep(2);
+ }
+ }
+#endif
+ return 0;
+}
+
+/*
+ * Parse the init_reg2 array into a number of register sets that
+ * we can send over as i2c burst writes instead of writing each
+ * entry of init_reg2 as a single 4 byte write. Write the
+ * new data structures and then free them.
+ */
+static int s5k4ecgx_write_init_reg2_burst(struct v4l2_subdev *sd)
+{
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ struct s5k4ecgx_regset *regset_table;
+ struct s5k4ecgx_regset *regset;
+ struct s5k4ecgx_regset *end_regset;
+ u8 *regset_data;
+ u8 *dst_ptr;
+ const u32 *end_src_ptr;
+ bool flag_copied;
+ int init_reg_2_array_size = state->regs->init_reg_2.array_size;
+ int init_reg_2_size = init_reg_2_array_size * sizeof(u32);
+ const u32 *src_ptr = state->regs->init_reg_2.reg;
+ u32 src_value;
+ int err;
+
+ pr_debug("%s : start\n", __func__);
+
+ regset_data = vmalloc(init_reg_2_size);
+ if (regset_data == NULL)
+ return -ENOMEM;
+ regset_table = vmalloc(sizeof(struct s5k4ecgx_regset) *
+ init_reg_2_size);
+ if (regset_table == NULL) {
+ kfree(regset_data);
+ return -ENOMEM;
+ }
+
+ dst_ptr = regset_data;
+ regset = regset_table;
+ end_src_ptr = &state->regs->init_reg_2.reg[init_reg_2_array_size];
+
+ src_value = *src_ptr++;
+ while (src_ptr <= end_src_ptr) {
+ /* initial value for a regset */
+ regset->data = dst_ptr;
+ flag_copied = false;
+ *dst_ptr++ = src_value >> 24;
+ *dst_ptr++ = src_value >> 16;
+ *dst_ptr++ = src_value >> 8;
+ *dst_ptr++ = src_value;
+
+ /* check subsequent values for a data flag (starts with
+ 0x0F12) or something else */
+ do {
+ src_value = *src_ptr++;
+ if ((src_value & 0xFFFF0000) != 0x0F120000) {
+ /* src_value is start of next regset */
+ regset->size = dst_ptr - regset->data;
+ regset++;
+ break;
+ }
+ /* copy the 0x0F12 flag if not done already */
+ if (!flag_copied) {
+ *dst_ptr++ = src_value >> 24;
+ *dst_ptr++ = src_value >> 16;
+ flag_copied = true;
+ }
+ /* copy the data part */
+ *dst_ptr++ = src_value >> 8;
+ *dst_ptr++ = src_value;
+ } while (src_ptr < end_src_ptr);
+ }
+ pr_debug("%s : finished creating table\n", __func__);
+
+ end_regset = regset;
+ pr_debug("%s : first regset = %p, last regset = %p, count = %d\n",
+ __func__, regset_table, regset, end_regset - regset_table);
+ pr_debug("%s : regset_data = %p, end = %p, dst_ptr = %p\n", __func__,
+ regset_data, regset_data + (init_reg_2_size * sizeof(u32)),
+ dst_ptr);
+
+#ifdef CONFIG_VIDEO_S5K4ECGX_DEBUG
+ if (s5k4ecgx_debug_mask & S5K4ECGX_DEBUG_I2C_BURSTS) {
+ int last_regset_end_addr = 0;
+ regset = regset_table;
+ do {
+ s5k4ecgx_dump_regset(regset);
+ if (regset->size > 4) {
+ int regset_addr = (regset->data[2] << 8 |
+ regset->data[3]);
+ if (last_regset_end_addr == regset_addr)
+ pr_info("%s : this regset can be"
+ " combined with previous\n",
+ __func__);
+ last_regset_end_addr = (regset_addr +
+ regset->size - 6);
+ }
+ regset++;
+ } while (regset < end_regset);
+ }
+#endif
+ regset = regset_table;
+ pr_debug("%s : start writing init reg 2 bursts\n", __func__);
+ do {
+ if (regset->size > 4) {
+ /* write the address packet */
+ err = s5k4ecgx_i2c_write_block(sd, regset->data, 4);
+ if (err)
+ break;
+ /* write the data in a burst */
+ err = s5k4ecgx_i2c_write_block(sd, regset->data+4,
+ regset->size-4);
+
+ } else
+ err = s5k4ecgx_i2c_write_block(sd, regset->data,
+ regset->size);
+ if (err)
+ break;
+ regset++;
+ } while (regset < end_regset);
+
+ pr_debug("%s : finished writing init reg 2 bursts\n", __func__);
+
+ vfree(regset_data);
+ vfree(regset_table);
+
+ return err;
+}
+
+static int s5k4ecgx_init_regs(struct v4l2_subdev *sd)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+ u16 read_value;
+
+ /* we'd prefer to do this in probe, but the framework hasn't
+ * turned on the camera yet so our i2c operations would fail
+ * if we tried to do it in probe, so we have to do it here
+ * and keep track if we succeeded or not.
+ */
+
+ /* enter read mode */
+ s5k4ecgx_i2c_write_twobyte(client, 0x002C, 0x7000);
+
+ s5k4ecgx_i2c_write_twobyte(client, 0x002E, 0x01A6);
+ s5k4ecgx_i2c_read_twobyte(client, 0x0F12, &read_value);
+
+ pr_info("%s : revision %08X\n", __func__, read_value);
+
+ /* restore write mode */
+ s5k4ecgx_i2c_write_twobyte(client, 0x0028, 0x7000);
+
+#ifdef CONFIG_VIDEO_S5K4ECGX_V_1_0
+ if (read_value == S5K4ECGX_VERSION_1_0) {
+ state->regs = &regs_for_fw_version_1_0;
+ state->initialized = true;
+ return 0;
+ }
+#endif
+#ifdef CONFIG_VIDEO_S5K4ECGX_V_1_1
+ if (read_value == S5K4ECGX_VERSION_1_1) {
+ state->fw.minor = 1;
+ state->regs = &regs_for_fw_version_1_1;
+ state->initialized = true;
+ return 0;
+ }
+#endif
+
+ dev_err(&client->dev, "%s: unknown fw version 0x%x\n",
+ __func__, read_value);
+ return -ENODEV;
+}
+
+static int s5k4ecgx_init(struct v4l2_subdev *sd, u32 val)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+
+ dev_dbg(&client->dev, "%s: start\n", __func__);
+
+ s5k4ecgx_init_parameters(sd);
+
+ if (s5k4ecgx_init_regs(&state->sd) < 0)
+ return -ENODEV;
+
+ dev_dbg(&client->dev, "%s: state->check_dataline : %d\n",
+ __func__, state->check_dataline);
+
+ if (s5k4ecgx_set_from_table(sd, "init reg 1",
+ &state->regs->init_reg_1, 1, 0) < 0)
+ return -EIO;
+
+ /* delay 10ms after wakeup of SOC processor */
+ msleep(10);
+
+ if (s5k4ecgx_write_init_reg2_burst(sd) < 0)
+ return -EIO;
+
+ if (s5k4ecgx_set_from_table(sd, "flash init",
+ &state->regs->flash_init, 1, 0) < 0)
+ return -EIO;
+
+ if (state->check_dataline) {
+ if (s5k4ecgx_set_from_table(sd, "dtp start",
+ &state->regs->dtp_start, 1, 0) < 0)
+ return -EIO;
+ }
+
+ dev_dbg(&client->dev, "%s: end\n", __func__);
+
+ return 0;
+}
+
+static const struct v4l2_subdev_core_ops s5k4ecgx_core_ops = {
+ .init = s5k4ecgx_init, /* initializing API */
+ .g_ctrl = s5k4ecgx_g_ctrl,
+ .s_ctrl = s5k4ecgx_s_ctrl,
+ .s_ext_ctrls = s5k4ecgx_s_ext_ctrls,
+};
+
+static const struct v4l2_subdev_video_ops s5k4ecgx_video_ops = {
+ .s_mbus_fmt = s5k4ecgx_s_mbus_fmt,
+ .enum_framesizes = s5k4ecgx_enum_framesizes,
+ .enum_mbus_fmt = s5k4ecgx_enum_mbus_fmt,
+ .try_mbus_fmt = s5k4ecgx_try_mbus_fmt,
+ .g_parm = s5k4ecgx_g_parm,
+ .s_parm = s5k4ecgx_s_parm,
+};
+
+static const struct v4l2_subdev_ops s5k4ecgx_ops = {
+ .core = &s5k4ecgx_core_ops,
+ .video = &s5k4ecgx_video_ops,
+};
+
+
+/*
+ * s5k4ecgx_probe
+ * Fetching platform data is being done with s_config subdev call.
+ * In probe routine, we just register subdev device
+ */
+static int s5k4ecgx_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct v4l2_subdev *sd;
+ struct s5k4ecgx_state *state;
+ struct s5k4ecgx_platform_data *pdata = client->dev.platform_data;
+
+ if ((pdata == NULL) || (pdata->flash_onoff == NULL)) {
+ dev_err(&client->dev, "%s: bad platform data\n", __func__);
+ return -ENODEV;
+ }
+
+ state = kzalloc(sizeof(struct s5k4ecgx_state), GFP_KERNEL);
+ if (state == NULL)
+ return -ENOMEM;
+
+ mutex_init(&state->ctrl_lock);
+
+ state->runmode = S5K4ECGX_RUNMODE_NOTREADY;
+ sd = &state->sd;
+ strcpy(sd->name, S5K4ECGX_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, &s5k4ecgx_ops);
+
+ dev_dbg(&client->dev, "5MP camera S5K4ECGX loaded.\n");
+
+ return 0;
+}
+
+static int s5k4ecgx_remove(struct i2c_client *client)
+{
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+ struct s5k4ecgx_state *state =
+ container_of(sd, struct s5k4ecgx_state, sd);
+
+ v4l2_device_unregister_subdev(sd);
+ mutex_destroy(&state->ctrl_lock);
+ kfree(state);
+
+ dev_dbg(&client->dev, "Unloaded camera sensor S5K4ECGX.\n");
+
+ return 0;
+}
+
+static const struct i2c_device_id s5k4ecgx_id[] = {
+ { S5K4ECGX_DRIVER_NAME, 0 },
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, s5k4ecgx_id);
+
+static struct i2c_driver v4l2_i2c_driver = {
+ .driver.name = S5K4ECGX_DRIVER_NAME,
+ .probe = s5k4ecgx_probe,
+ .remove = s5k4ecgx_remove,
+ .id_table = s5k4ecgx_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("LSI S5K4ECGX 5MP SOC camera driver");
+MODULE_AUTHOR("Seok-Young Jang <quartz.jang@samsung.com>");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/media/video/s5k4ecgx_regs_1_0.h b/drivers/media/video/s5k4ecgx_regs_1_0.h
new file mode 100755
index 0000000..afafe7f
--- /dev/null
+++ b/drivers/media/video/s5k4ecgx_regs_1_0.h
@@ -0,0 +1,4797 @@
+/* drivers/media/video/s5k4ecgx_regs_1_0.h
+ *
+ * Driver for s5k4ecgx (5MP Camera) from SEC(LSI), firmware EVT1.0
+ *
+ * Copyright (C) 2010, SAMSUNG ELECTRONICS
+ *
+ * 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.
+ */
+
+
+#ifndef __S5K4ECGX_REGS_1_0_H__
+#define __S5K4ECGX_REGS_1_0_H__
+
+/* ARM initialization */
+static const u32 s5k4ecgx_init_reg1_v1[] = {
+ /* direct addressing, hw addresses */
+ 0xFCFCD000,
+ 0x00040000,
+ 0xFCFCD000,
+ 0x00100001,
+ 0xFCFCD000,
+ 0x10300000,
+ 0x00140001,
+};
+
+static const u32 s5k4ecgx_init_reg2_v1[] = {
+ /* start analog settings, indirect addressing mode */
+ 0x0028D000,
+
+ 0x002A007A,
+ 0x0F120000,
+
+ 0x002AE406,
+ 0x0F120092,
+
+ 0x002AE410,
+ 0x0F123804,
+
+ 0x002AE420,
+ 0x0F120003,
+ 0x0F120060,
+
+ 0x002AE42E,
+ 0x0F120004,
+
+ 0x002AF400,
+ 0x0F125A3C,
+ 0x0F120023,
+ 0x0F128080,
+ 0x0F1203AF,
+ 0x0F12000A,
+ 0x0F12AA54,
+ 0x0F120040,
+ 0x0F12464E,
+ 0x0F120240,
+ 0x0F120240,
+ 0x0F120040,
+ 0x0F121000,
+ 0x0F125558,
+ 0x0F12D000,
+ 0x0F120010,
+ 0x0F120202,
+ 0x0F120401,
+ 0x0F120022,
+ 0x0F120088,
+ 0x0F12009F,
+ 0x0F120000,
+ 0x0F121800,
+ 0x0F120088,
+ 0x0F120000,
+ 0x0F122428,
+ 0x0F120000,
+ 0x0F1203EE,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+
+ 0x002AF480,
+ 0x0F120004,
+ 0x0F1205B6,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F1205BA,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120007,
+ 0x0F1205BA,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1201F4,
+ 0x0F12024E,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1201F4,
+ 0x0F1205B6,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1201F4,
+ 0x0F1205BA,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1201F4,
+ 0x0F12024F,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120075,
+ 0x0F1200CF,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120075,
+ 0x0F1200D6,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120004,
+ 0x0F1201F4,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1200F0,
+ 0x0F1201F4,
+ 0x0F12029E,
+ 0x0F1205B2,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1201F8,
+ 0x0F120228,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120208,
+ 0x0F120238,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+
+ 0x002AF590,
+ 0x0F120000,
+
+ 0x002AF500,
+ 0x0F120218,
+ 0x0F120238,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F120009,
+ 0x0F1200DE,
+ 0x0F1205C0,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1200DF,
+ 0x0F1200E4,
+ 0x0F1201F8,
+ 0x0F1201FD,
+ 0x0F1205B6,
+ 0x0F1205BB,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1201F8,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120077,
+ 0x0F12007E,
+ 0x0F12024F,
+ 0x0F12025E,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120708,
+ 0x0F12080C,
+
+ 0x002A1082,
+ 0x0F125555,
+ 0x0F125555,
+
+ 0x002A1088,
+ 0x0F12055D,
+
+ 0x002A100E,
+ 0x0F120000,
+
+ /* switch to sw address bank */
+ 0x00287000,
+
+ 0x002A0716,
+ 0x0F120100,
+
+ /* Start of Patch Data for firmware */
+ 0x002A3A10,
+ 0x0F12B5F8,
+ 0x0F124A3E,
+ 0x0F12493E,
+ 0x0F12483F,
+ 0x0F12C004,
+ 0x0F126001,
+ 0x0F124C3E,
+ 0x0F122500,
+ 0x0F128265,
+ 0x0F128025,
+ 0x0F12493D,
+ 0x0F12483E,
+ 0x0F122701,
+ 0x0F12002A,
+ 0x0F12F000,
+ 0x0F12FC38,
+ 0x0F12493C,
+ 0x0F12483D,
+ 0x0F122602,
+ 0x0F12003A,
+ 0x0F12F000,
+ 0x0F12FC32,
+ 0x0F12493B,
+ 0x0F12483C,
+ 0x0F120032,
+ 0x0F122703,
+ 0x0F12F000,
+ 0x0F12FC2C,
+ 0x0F128225,
+ 0x0F12493A,
+ 0x0F12483A,
+ 0x0F122604,
+ 0x0F12003A,
+ 0x0F12F000,
+ 0x0F12FC25,
+ 0x0F12200E,
+ 0x0F128420,
+ 0x0F122701,
+ 0x0F1283E7,
+ 0x0F124937,
+ 0x0F124837,
+ 0x0F120032,
+ 0x0F122405,
+ 0x0F12F000,
+ 0x0F12FC1B,
+ 0x0F124936,
+ 0x0F124836,
+ 0x0F122606,
+ 0x0F120022,
+ 0x0F12F000,
+ 0x0F12FC15,
+ 0x0F124C28,
+ 0x0F123460,
+ 0x0F1281E7,
+ 0x0F124825,
+ 0x0F123824,
+ 0x0F1286C5,
+ 0x0F124932,
+ 0x0F124832,
+ 0x0F120032,
+ 0x0F122707,
+ 0x0F12F000,
+ 0x0F12FC09,
+ 0x0F124931,
+ 0x0F124831,
+ 0x0F122608,
+ 0x0F12003A,
+ 0x0F12F000,
+ 0x0F12FC03,
+ 0x0F124930,
+ 0x0F124830,
+ 0x0F120032,
+ 0x0F122709,
+ 0x0F12F000,
+ 0x0F12FBFD,
+ 0x0F122005,
+ 0x0F128160,
+ 0x0F12492E,
+ 0x0F12482E,
+ 0x0F126281,
+ 0x0F128225,
+ 0x0F128265,
+ 0x0F12482D,
+ 0x0F128320,
+ 0x0F12482D,
+ 0x0F128360,
+ 0x0F120270,
+ 0x0F1283A0,
+ 0x0F122005,
+ 0x0F120300,
+ 0x0F1283E0,
+ 0x0F124828,
+ 0x0F12492A,
+ 0x0F123840,
+ 0x0F126001,
+ 0x0F12492A,
+ 0x0F12482A,
+ 0x0F12240A,
+ 0x0F12003A,
+ 0x0F12F000,
+ 0x0F12FBE3,
+ 0x0F124929,
+ 0x0F124829,
+ 0x0F120022,
+ 0x0F12250B,
+ 0x0F12F000,
+ 0x0F12FBDD,
+ 0x0F124820,
+ 0x0F124927,
+ 0x0F123080,
+ 0x0F126381,
+ 0x0F124927,
+ 0x0F124827,
+ 0x0F12240C,
+ 0x0F12002A,
+ 0x0F12F000,
+ 0x0F12FBD3,
+ 0x0F124926,
+ 0x0F124826,
+ 0x0F120022,
+ 0x0F12F000,
+ 0x0F12FBCE,
+ 0x0F12BCF8,
+ 0x0F12BC08,
+ 0x0F124718,
+ 0x0F120000,
+ 0x0F120174,
+ 0x0F124EC1,
+ 0x0F12FFFE,
+ 0x0F120000,
+ 0x0F121EF0,
+ 0x0F127000,
+ 0x0F124780,
+ 0x0F127000,
+ 0x0F123BF3,
+ 0x0F127000,
+ 0x0F12A1D9,
+ 0x0F120000,
+ 0x0F123B9D,
+ 0x0F127000,
+ 0x0F12A0BD,
+ 0x0F120000,
+ 0x0F123C8D,
+ 0x0F127000,
+ 0x0F12217B,
+ 0x0F120000,
+ 0x0F123CE9,
+ 0x0F127000,
+ 0x0F12E0DF,
+ 0x0F120000,
+ 0x0F123E73,
+ 0x0F127000,
+ 0x0F12053B,
+ 0x0F120000,
+ 0x0F123D71,
+ 0x0F127000,
+ 0x0F12509B,
+ 0x0F120000,
+ 0x0F123FF9,
+ 0x0F127000,
+ 0x0F12D42F,
+ 0x0F120000,
+ 0x0F123EB5,
+ 0x0F127000,
+ 0x0F1249D1,
+ 0x0F120000,
+ 0x0F123F4F,
+ 0x0F127000,
+ 0x0F121E57,
+ 0x0F120000,
+ 0x0F124033,
+ 0x0F127000,
+ 0x0F1200C0,
+ 0x0F127000,
+ 0x0F124E34,
+ 0x0F120000,
+ 0x0F127C53,
+ 0x0F120000,
+ 0x0F1240BF,
+ 0x0F127000,
+ 0x0F1240FB,
+ 0x0F127000,
+ 0x0F12F5D7,
+ 0x0F120000,
+ 0x0F12406F,
+ 0x0F127000,
+ 0x0F12BAB1,
+ 0x0F120000,
+ 0x0F124187,
+ 0x0F127000,
+ 0x0F124129,
+ 0x0F127000,
+ 0x0F12C10D,
+ 0x0F120000,
+ 0x0F124203,
+ 0x0F127000,
+ 0x0F12B231,
+ 0x0F120000,
+ 0x0F12B570,
+ 0x0F12000C,
+ 0x0F126820,
+ 0x0F126865,
+ 0x0F12F000,
+ 0x0F12FB84,
+ 0x0F124BFC,
+ 0x0F120402,
+ 0x0F120C12,
+ 0x0F12819A,
+ 0x0F1248FB,
+ 0x0F1289C1,
+ 0x0F12428A,
+ 0x0F12D305,
+ 0x0F124AFA,
+ 0x0F128986,
+ 0x0F128852,
+ 0x0F1242B2,
+ 0x0F12D300,
+ 0x0F128199,
+ 0x0F128801,
+ 0x0F122900,
+ 0x0F12D008,
+ 0x0F1249F7,
+ 0x0F12002B,
+ 0x0F126E0A,
+ 0x0F122105,
+ 0x0F121C80,
+ 0x0F12F000,
+ 0x0F12FB74,
+ 0x0F126020,
+ 0x0F12E006,
+ 0x0F12899A,
+ 0x0F1248F3,
+ 0x0F12002B,
+ 0x0F122105,
+ 0x0F12F000,
+ 0x0F12FB6C,
+ 0x0F126020,
+ 0x0F126820,
+ 0x0F12BC70,
+ 0x0F12BC08,
+ 0x0F124718,
+ 0x0F12B5F8,
+ 0x0F120004,
+ 0x0F122000,
+ 0x0F129000,
+ 0x0F120020,
+ 0x0F122501,
+ 0x0F123810,
+ 0x0F122601,
+ 0x0F1240A5,
+ 0x0F124086,
+ 0x0F124FEA,
+ 0x0F122C10,
+ 0x0F12DA03,
+ 0x0F128838,
+ 0x0F1243A8,
+ 0x0F128038,
+ 0x0F12E002,
+ 0x0F128878,
+ 0x0F1243B0,
+ 0x0F128078,
+ 0x0F12F000,
+ 0x0F12FB59,
+ 0x0F122C10,
+ 0x0F12DA03,
+ 0x0F128838,
+ 0x0F124328,
+ 0x0F128038,
+ 0x0F12E002,
+ 0x0F128878,
+ 0x0F124330,
+ 0x0F128078,
+ 0x0F1248DA,
+ 0x0F122105,
+ 0x0F128982,
+ 0x0F1248DD,
+ 0x0F12466B,
+ 0x0F12F000,
+ 0x0F12FB41,
+ 0x0F121C41,
+ 0x0F124CD7,
+ 0x0F120049,
+ 0x0F120040,
+ 0x0F121909,
+ 0x0F121900,
+ 0x0F12466B,
+ 0x0F128A89,
+ 0x0F128A80,
+ 0x0F12881A,
+ 0x0F12F000,
+ 0x0F12FB45,
+ 0x0F128A61,
+ 0x0F120540,
+ 0x0F1202C9,
+ 0x0F120D40,
+ 0x0F124301,
+ 0x0F1248D4,
+ 0x0F128081,
+ 0x0F1249D4,
+ 0x0F1248D4,
+ 0x0F123120,
+ 0x0F128BC0,
+ 0x0F128809,
+ 0x0F121841,
+ 0x0F120020,
+ 0x0F123060,
+ 0x0F128A82,
+ 0x0F124291,
+ 0x0F12D205,
+ 0x0F128AC0,
+ 0x0F1249CF,
+ 0x0F127388,
+ 0x0F122001,
+ 0x0F1231A0,
+ 0x0F1270C8,
+ 0x0F12BCF8,
+ 0x0F12BC08,
+ 0x0F124718,
+ 0x0F12B5F8,
+ 0x0F1248C6,
+ 0x0F122200,
+ 0x0F1230A0,
+ 0x0F1281C2,
+ 0x0F126808,
+ 0x0F124669,
+ 0x0F12F000,
+ 0x0F12FB29,
+ 0x0F12466B,
+ 0x0F128818,
+ 0x0F12F000,
+ 0x0F12FB2D,
+ 0x0F120005,
+ 0x0F12466B,
+ 0x0F128858,
+ 0x0F12F000,
+ 0x0F12FB30,
+ 0x0F120004,
+ 0x0F122101,
+ 0x0F121928,
+ 0x0F1202C9,
+ 0x0F121A08,
+ 0x0F120286,
+ 0x0F120029,
+ 0x0F120030,
+ 0x0F12F000,
+ 0x0F12FB2E,
+ 0x0F120005,
+ 0x0F122701,
+ 0x0F1202BF,
+ 0x0F120021,
+ 0x0F120030,
+ 0x0F12F000,
+ 0x0F12FB27,
+ 0x0F1249B5,
+ 0x0F124AB8,
+ 0x0F123140,
+ 0x0F123220,
+ 0x0F12808D,
+ 0x0F128295,
+ 0x0F1280CF,
+ 0x0F1282D7,
+ 0x0F128108,
+ 0x0F128310,
+ 0x0F12E7CE,
+ 0x0F126808,
+ 0x0F120400,
+ 0x0F120C00,
+ 0x0F126849,
+ 0x0F120409,
+ 0x0F120C09,
+ 0x0F124AAA,
+ 0x0F128A12,
+ 0x0F122A00,
+ 0x0F12D00D,
+ 0x0F122300,
+ 0x0F121A89,
+ 0x0F12D400,
+ 0x0F12000B,
+ 0x0F120419,
+ 0x0F120C09,
+ 0x0F1223FF,
+ 0x0F1233C1,
+ 0x0F121810,
+ 0x0F124298,
+ 0x0F12D800,
+ 0x0F120003,
+ 0x0F120418,
+ 0x0F120C00,
+ 0x0F124AA9,
+ 0x0F128150,
+ 0x0F128191,
+ 0x0F124770,
+ 0x0F12B5F8,
+ 0x0F122400,
+ 0x0F124DA7,
+ 0x0F124F9E,
+ 0x0F1248A7,
+ 0x0F128C39,
+ 0x0F128041,
+ 0x0F122101,
+ 0x0F128001,
+ 0x0F12F000,
+ 0x0F12FAFB,
+ 0x0F1248A5,
+ 0x0F128BC0,
+ 0x0F12F000,
+ 0x0F12FAFF,
+ 0x0F12260D,
+ 0x0F120736,
+ 0x0F122000,
+ 0x0F1200E1,
+ 0x0F1219CA,
+ 0x0F120041,
+ 0x0F12194B,
+ 0x0F12199B,
+ 0x0F12881B,
+ 0x0F121851,
+ 0x0F12844B,
+ 0x0F121C40,
+ 0x0F120400,
+ 0x0F120C00,
+ 0x0F122804,
+ 0x0F12D3F4,
+ 0x0F123508,
+ 0x0F12042D,
+ 0x0F120C2D,
+ 0x0F121C64,
+ 0x0F120424,
+ 0x0F120C24,
+ 0x0F122C07,
+ 0x0F12D3E9,
+ 0x0F12E78A,
+ 0x0F12B5F0,
+ 0x0F12B087,
+ 0x0F126808,
+ 0x0F129006,
+ 0x0F126848,
+ 0x0F120405,
+ 0x0F120C2D,
+ 0x0F126888,
+ 0x0F120403,
+ 0x0F120C1B,
+ 0x0F124892,
+ 0x0F128B80,
+ 0x0F122800,
+ 0x0F12D100,
+ 0x0F122300,
+ 0x0F12001C,
+ 0x0F124A90,
+ 0x0F12466E,
+ 0x0F121E91,
+ 0x0F121E88,
+ 0x0F12C607,
+ 0x0F12498F,
+ 0x0F120023,
+ 0x0F122207,
+ 0x0F120028,
+ 0x0F12F000,
+ 0x0F12FAD3,
+ 0x0F12487E,
+ 0x0F128BC1,
+ 0x0F122900,
+ 0x0F12D030,
+ 0x0F122100,
+ 0x0F124888,
+ 0x0F124A7B,
+ 0x0F12380A,
+ 0x0F1288C0,
+ 0x0F1200C3,
+ 0x0F12189A,
+ 0x0F124696,
+ 0x0F124A86,
+ 0x0F121C40,
+ 0x0F12189B,
+ 0x0F12469C,
+ 0x0F124B76,
+ 0x0F1200C0,
+ 0x0F1218C6,
+ 0x0F121887,
+ 0x0F120048,
+ 0x0F124672,
+ 0x0F124663,
+ 0x0F121812,
+ 0x0F12181B,
+ 0x0F128C52,
+ 0x0F128EDB,
+ 0x0F12435A,
+ 0x0F120092,
+ 0x0F120C15,
+ 0x0F124A6F,
+ 0x0F121882,
+ 0x0F12235A,
+ 0x0F12529D,
+ 0x0F121833,
+ 0x0F121838,
+ 0x0F128C5B,
+ 0x0F128EC0,
+ 0x0F124343,
+ 0x0F120098,
+ 0x0F120C00,
+ 0x0F123260,
+ 0x0F128050,
+ 0x0F121C49,
+ 0x0F120409,
+ 0x0F120C09,
+ 0x0F122904,
+ 0x0F12D3E3,
+ 0x0F124A66,
+ 0x0F12325A,
+ 0x0F120013,
+ 0x0F123308,
+ 0x0F12E00A,
+ 0x0F124870,
+ 0x0F124971,
+ 0x0F12380A,
+ 0x0F1288C0,
+ 0x0F1200C2,
+ 0x0F121852,
+ 0x0F123236,
+ 0x0F121C40,
+ 0x0F1200C0,
+ 0x0F121843,
+ 0x0F123336,
+ 0x0F122100,
+ 0x0F124864,
+ 0x0F123020,
+ 0x0F124684,
+ 0x0F124E69,
+ 0x0F120048,
+ 0x0F123E0A,
+ 0x0F128937,
+ 0x0F125A15,
+ 0x0F128976,
+ 0x0F12437D,
+ 0x0F125A1F,
+ 0x0F124377,
+ 0x0F124E65,
+ 0x0F1219ED,
+ 0x0F121986,
+ 0x0F123660,
+ 0x0F1289F6,
+ 0x0F124366,
+ 0x0F1219AD,
+ 0x0F12022D,
+ 0x0F120C2D,
+ 0x0F12AE04,
+ 0x0F125235,
+ 0x0F124666,
+ 0x0F127C76,
+ 0x0F124375,
+ 0x0F129E06,
+ 0x0F12026D,
+ 0x0F120C2D,
+ 0x0F125235,
+ 0x0F121C49,
+ 0x0F122904,
+ 0x0F12D3E1,
+ 0x0F12B007,
+ 0x0F12BCF0,
+ 0x0F12BC08,
+ 0x0F124718,
+ 0x0F12B5F8,
+ 0x0F120004,
+ 0x0F12F7FF,
+ 0x0F12FF53,
+ 0x0F122101,
+ 0x0F12000D,
+ 0x0F120020,
+ 0x0F123810,
+ 0x0F124081,
+ 0x0F1240A5,
+ 0x0F124F4A,
+ 0x0F12000E,
+ 0x0F122C10,
+ 0x0F12DA03,
+ 0x0F128838,
+ 0x0F1243A8,
+ 0x0F128038,
+ 0x0F12E002,
+ 0x0F128878,
+ 0x0F1243B0,
+ 0x0F128078,
+ 0x0F12F000,
+ 0x0F12FA5E,
+ 0x0F122C10,
+ 0x0F12DA03,
+ 0x0F128838,
+ 0x0F124328,
+ 0x0F128038,
+ 0x0F12E6EC,
+ 0x0F128878,
+ 0x0F124330,
+ 0x0F128078,
+ 0x0F12E6E8,
+ 0x0F12B5F8,
+ 0x0F120004,
+ 0x0F124F48,
+ 0x0F124949,
+ 0x0F1278FA,
+ 0x0F122001,
+ 0x0F122A00,
+ 0x0F12D102,
+ 0x0F122000,
+ 0x0F1286C8,
+ 0x0F12E003,
+ 0x0F127AFA,
+ 0x0F122A00,
+ 0x0F12D000,
+ 0x0F1286C8,
+ 0x0F122101,
+ 0x0F12000D,
+ 0x0F120020,
+ 0x0F123810,
+ 0x0F124081,
+ 0x0F1240A5,
+ 0x0F12000E,
+ 0x0F122C10,
+ 0x0F12DA04,
+ 0x0F124932,
+ 0x0F128808,
+ 0x0F1243A8,
+ 0x0F128008,
+ 0x0F12E003,
+ 0x0F124930,
+ 0x0F128848,
+ 0x0F1243B0,
+ 0x0F128048,
+ 0x0F12F000,
+ 0x0F12FA39,
+ 0x0F122C10,
+ 0x0F12DA04,
+ 0x0F12482C,
+ 0x0F128801,
+ 0x0F124329,
+ 0x0F128001,
+ 0x0F12E003,
+ 0x0F124829,
+ 0x0F128841,
+ 0x0F124331,
+ 0x0F128041,
+ 0x0F124934,
+ 0x0F128B08,
+ 0x0F1206C2,
+ 0x0F12D50A,
+ 0x0F127ABA,
+ 0x0F120652,
+ 0x0F12D507,
+ 0x0F122210,
+ 0x0F124390,
+ 0x0F128308,
+ 0x0F124830,
+ 0x0F127AF9,
+ 0x0F126B00,
+ 0x0F12F000,
+ 0x0F12FA27,
+ 0x0F12481C,
+ 0x0F123060,
+ 0x0F1289C0,
+ 0x0F122800,
+ 0x0F12D009,
+ 0x0F1278F8,
+ 0x0F122800,
+ 0x0F12D006,
+ 0x0F127AF8,
+ 0x0F122800,
+ 0x0F12D003,
+ 0x0F127AB8,
+ 0x0F122140,
+ 0x0F124308,
+ 0x0F1272B8,
+ 0x0F12E69B,
+ 0x0F12B5F8,
+ 0x0F120004,
+ 0x0F124826,
+ 0x0F128981,
+ 0x0F122900,
+ 0x0F12D007,
+ 0x0F128940,
+ 0x0F122800,
+ 0x0F12D104,
+ 0x0F12481E,
+ 0x0F1222BF,
+ 0x0F127A81,
+ 0x0F124011,
+ 0x0F127281,
+ 0x0F122101,
+ 0x0F12000D,
+ 0x0F120020,
+ 0x0F123810,
+ 0x0F124081,
+ 0x0F1240A5,
+ 0x0F124F0E,
+ 0x0F12000E,
+ 0x0F122C10,
+ 0x0F12DA03,
+ 0x0F128838,
+ 0x0F1243A8,
+ 0x0F128038,
+ 0x0F12E002,
+ 0x0F128878,
+ 0x0F1243B0,
+ 0x0F128078,
+ 0x0F12F000,
+ 0x0F12F9FE,
+ 0x0F122C10,
+ 0x0F12DA2D,
+ 0x0F128838,
+ 0x0F124328,
+ 0x0F128038,
+ 0x0F12E674,
+ 0x0F1221C0,
+ 0x0F127000,
+ 0x0F124780,
+ 0x0F127000,
+ 0x0F122D00,
+ 0x0F127000,
+ 0x0F122AD0,
+ 0x0F127000,
+ 0x0F120924,
+ 0x0F127000,
+ 0x0F121100,
+ 0x0F12D000,
+ 0x0F12E300,
+ 0x0F12D000,
+ 0x0F1229D0,
+ 0x0F127000,
+ 0x0F122C30,
+ 0x0F127000,
+ 0x0F125000,
+ 0x0F12D000,
+ 0x0F12A006,
+ 0x0F120000,
+ 0x0F12A000,
+ 0x0F12D000,
+ 0x0F1206F8,
+ 0x0F127000,
+ 0x0F120888,
+ 0x0F127000,
+ 0x0F1221DA,
+ 0x0F127000,
+ 0x0F1208AC,
+ 0x0F127000,
+ 0x0F1220BC,
+ 0x0F127000,
+ 0x0F121ECC,
+ 0x0F127000,
+ 0x0F122FA4,
+ 0x0F127000,
+ 0x0F12235C,
+ 0x0F127000,
+ 0x0F120234,
+ 0x0F127000,
+ 0x0F128878,
+ 0x0F124330,
+ 0x0F128078,
+ 0x0F12E646,
+ 0x0F12B570,
+ 0x0F124D99,
+ 0x0F124C99,
+ 0x0F128B28,
+ 0x0F120701,
+ 0x0F12D507,
+ 0x0F122108,
+ 0x0F124388,
+ 0x0F128328,
+ 0x0F124997,
+ 0x0F126B20,
+ 0x0F1268C9,
+ 0x0F12F000,
+ 0x0F12F9C4,
+ 0x0F128B28,
+ 0x0F1206C1,
+ 0x0F12D50A,
+ 0x0F124994,
+ 0x0F127A8A,
+ 0x0F120652,
+ 0x0F12D406,
+ 0x0F122210,
+ 0x0F124390,
+ 0x0F128328,
+ 0x0F127AC9,
+ 0x0F126B20,
+ 0x0F12F000,
+ 0x0F12F9A6,
+ 0x0F12E5DC,
+ 0x0F12B570,
+ 0x0F124D8E,
+ 0x0F124C8F,
+ 0x0F1288EA,
+ 0x0F122A14,
+ 0x0F12D101,
+ 0x0F122200,
+ 0x0F1281A2,
+ 0x0F12F000,
+ 0x0F12F9B3,
+ 0x0F1288E8,
+ 0x0F122821,
+ 0x0F12D10F,
+ 0x0F128B28,
+ 0x0F122800,
+ 0x0F12D10C,
+ 0x0F12200C,
+ 0x0F125E20,
+ 0x0F128961,
+ 0x0F124288,
+ 0x0F12DC07,
+ 0x0F124882,
+ 0x0F123880,
+ 0x0F126B80,
+ 0x0F12F000,
+ 0x0F12F9AB,
+ 0x0F1289A0,
+ 0x0F121C40,
+ 0x0F1281A0,
+ 0x0F12E5BE,
+ 0x0F12B5F8,
+ 0x0F120004,
+ 0x0F122101,
+ 0x0F12000D,
+ 0x0F120020,
+ 0x0F123810,
+ 0x0F124081,
+ 0x0F1240A5,
+ 0x0F124F7E,
+ 0x0F12000E,
+ 0x0F122C10,
+ 0x0F12DA03,
+ 0x0F128838,
+ 0x0F1243A8,
+ 0x0F128038,
+ 0x0F12E002,
+ 0x0F128878,
+ 0x0F1243B0,
+ 0x0F128078,
+ 0x0F12F000,
+ 0x0F12F99A,
+ 0x0F122C10,
+ 0x0F12DA03,
+ 0x0F128838,
+ 0x0F124328,
+ 0x0F128038,
+ 0x0F12E002,
+ 0x0F128878,
+ 0x0F124330,
+ 0x0F128078,
+ 0x0F124874,
+ 0x0F128800,
+ 0x0F120400,
+ 0x0F12D504,
+ 0x0F12F000,
+ 0x0F12F993,
+ 0x0F12496E,
+ 0x0F122012,
+ 0x0F1280C8,
+ 0x0F12E5E3,
+ 0x0F12B570,
+ 0x0F124E6A,
+ 0x0F128881,
+ 0x0F1278F2,
+ 0x0F124D6E,
+ 0x0F124C6A,
+ 0x0F122A00,
+ 0x0F12D005,
+ 0x0F128A62,
+ 0x0F121889,
+ 0x0F128081,
+ 0x0F128B61,
+ 0x0F128029,
+ 0x0F12E004,
+ 0x0F128A22,
+ 0x0F121889,
+ 0x0F128081,
+ 0x0F128B21,
+ 0x0F128029,
+ 0x0F12F000,
+ 0x0F12F982,
+ 0x0F1278F0,
+ 0x0F122800,
+ 0x0F12D002,
+ 0x0F128BE0,
+ 0x0F1282E8,
+ 0x0F12E57B,
+ 0x0F128BA0,
+ 0x0F1282E8,
+ 0x0F12E578,
+ 0x0F12B430,
+ 0x0F12680B,
+ 0x0F12684D,
+ 0x0F12688C,
+ 0x0F1268C8,
+ 0x0F124A5F,
+ 0x0F128054,
+ 0x0F124958,
+ 0x0F1278CC,
+ 0x0F124959,
+ 0x0F122C00,
+ 0x0F12D003,
+ 0x0F128A49,
+ 0x0F121808,
+ 0x0F128090,
+ 0x0F12E002,
+ 0x0F128A09,
+ 0x0F121808,
+ 0x0F128090,
+ 0x0F1280D3,
+ 0x0F128115,
+ 0x0F12BC30,
+ 0x0F124770,
+ 0x0F12B5F3,
+ 0x0F120004,
+ 0x0F12B081,
+ 0x0F129802,
+ 0x0F126800,
+ 0x0F120600,
+ 0x0F120E00,
+ 0x0F122201,
+ 0x0F120015,
+ 0x0F120021,
+ 0x0F123910,
+ 0x0F12408A,
+ 0x0F1240A5,
+ 0x0F124F4D,
+ 0x0F120016,
+ 0x0F122C10,
+ 0x0F12DA03,
+ 0x0F128839,
+ 0x0F1243A9,
+ 0x0F128039,
+ 0x0F12E002,
+ 0x0F128879,
+ 0x0F1243B1,
+ 0x0F128079,
+ 0x0F12F000,
+ 0x0F12F950,
+ 0x0F122C10,
+ 0x0F12DA03,
+ 0x0F128839,
+ 0x0F124329,
+ 0x0F128039,
+ 0x0F12E002,
+ 0x0F128879,
+ 0x0F124331,
+ 0x0F128079,
+ 0x0F124946,
+ 0x0F128809,
+ 0x0F122900,
+ 0x0F12D102,
+ 0x0F12F000,
+ 0x0F12F949,
+ 0x0F122000,
+ 0x0F129902,
+ 0x0F126008,
+ 0x0F12BCFE,
+ 0x0F12BC08,
+ 0x0F124718,
+ 0x0F12B538,
+ 0x0F124C40,
+ 0x0F1289E5,
+ 0x0F12F000,
+ 0x0F12F946,
+ 0x0F121FE8,
+ 0x0F1238FD,
+ 0x0F12D132,
+ 0x0F1289E0,
+ 0x0F121FC1,
+ 0x0F1239FF,
+ 0x0F12D12E,
+ 0x0F12483C,
+ 0x0F1269E1,
+ 0x0F126840,
+ 0x0F121809,
+ 0x0F120200,
+ 0x0F12F000,
+ 0x0F12F8BA,
+ 0x0F120400,
+ 0x0F120C00,
+ 0x0F124A38,
+ 0x0F122305,
+ 0x0F120011,
+ 0x0F123114,
+ 0x0F12F000,
+ 0x0F12F938,
+ 0x0F120002,
+ 0x0F1266E0,
+ 0x0F124D34,
+ 0x0F128CE0,
+ 0x0F123D14,
+ 0x0F1289E9,
+ 0x0F12F000,
+ 0x0F12F88A,
+ 0x0F12466B,
+ 0x0F128018,
+ 0x0F128A29,
+ 0x0F128D20,
+ 0x0F126EE2,
+ 0x0F12F000,
+ 0x0F12F883,
+ 0x0F12466B,
+ 0x0F128058,
+ 0x0F120021,
+ 0x0F129800,
+ 0x0F123170,
+ 0x0F12F000,
+ 0x0F12F92A,
+ 0x0F120020,
+ 0x0F123060,
+ 0x0F128A02,
+ 0x0F124928,
+ 0x0F123980,
+ 0x0F12808A,
+ 0x0F128A42,
+ 0x0F1280CA,
+ 0x0F128A80,
+ 0x0F128108,
+ 0x0F12BC38,
+ 0x0F12BC08,
+ 0x0F124718,
+ 0x0F12B5F8,
+ 0x0F120004,
+ 0x0F126808,
+ 0x0F120400,
+ 0x0F120C00,
+ 0x0F122201,
+ 0x0F120015,
+ 0x0F120021,
+ 0x0F123910,
+ 0x0F12408A,
+ 0x0F1240A5,
+ 0x0F124F17,
+ 0x0F120016,
+ 0x0F122C10,
+ 0x0F12DA03,
+ 0x0F128839,
+ 0x0F1243A9,
+ 0x0F128039,
+ 0x0F12E002,
+ 0x0F128879,
+ 0x0F1243B1,
+ 0x0F128079,
+ 0x0F12F000,
+ 0x0F12F90D,
+ 0x0F122C10,
+ 0x0F12DA03,
+ 0x0F128838,
+ 0x0F124328,
+ 0x0F128038,
+ 0x0F12E002,
+ 0x0F128878,
+ 0x0F124330,
+ 0x0F128078,
+ 0x0F12480D,
+ 0x0F128800,
+ 0x0F120400,
+ 0x0F12D507,
+ 0x0F124B12,
+ 0x0F127819,
+ 0x0F124A12,
+ 0x0F127810,
+ 0x0F127018,
+ 0x0F127011,
+ 0x0F124905,
+ 0x0F128188,
+ 0x0F12E513,
+ 0x0F120000,
+ 0x0F122FA4,
+ 0x0F127000,
+ 0x0F12235C,
+ 0x0F127000,
+ 0x0F120140,
+ 0x0F127000,
+ 0x0F1220BC,
+ 0x0F127000,
+ 0x0F122DF0,
+ 0x0F127000,
+ 0x0F1247E0,
+ 0x0F127000,
+ 0x0F121100,
+ 0x0F12D000,
+ 0x0F122EE2,
+ 0x0F127000,
+ 0x0F12F400,
+ 0x0F12D000,
+ 0x0F123200,
+ 0x0F12D000,
+ 0x0F1216DE,
+ 0x0F127000,
+ 0x0F1236F8,
+ 0x0F127000,
+ 0x0F122B90,
+ 0x0F127000,
+ 0x0F1217B4,
+ 0x0F127000,
+ 0x0F122EDD,
+ 0x0F127000,
+ 0x0F122EDE,
+ 0x0F127000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F1213D5,
+ 0x0F120001,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F12A083,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F12A035,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F12A1D9,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F122D27,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F127D47,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F127AB1,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F127ACB,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12F004,
+ 0x0F12E51F,
+ 0x0F122630,
+ 0x0F120001,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F12ED4D,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F12EDDB,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F124EB5,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F12053B,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F1249D1,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F12D411,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F121E57,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F122603,
+ 0x0F120001,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F12BC3D,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F122601,
+ 0x0F120001,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F12BAB1,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F12B89F,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F12F077,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F12C10D,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F12C0C9,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F12EAF9,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F122E61,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F12E86B,
+ 0x0F120000,
+ 0x0F124778,
+ 0x0F1246C0,
+ 0x0F12C000,
+ 0x0F12E59F,
+ 0x0F12FF1C,
+ 0x0F12E12F,
+ 0x0F12B231,
+ 0x0F120000,
+ /* End of Patch Data*/
+
+ /* switch to firmware address bank */
+ 0x0028D000,
+ 0x002A1000,
+ 0x0F120001,
+ /* End of factory settings*/
+
+ /* Switch to sw address bank */
+ 0x00287000,
+
+ 0x002A479E,
+ 0x0F120001,
+
+ 0x002A1432,
+ 0x0F120000,
+
+ 0x002A47EE,
+ 0x0F120001,
+ 0x0F12000A,
+ 0x0F120014,
+ 0x0F120070,
+ 0x0F120005,
+ 0x0F125A3C,
+
+ 0x002A4780,
+ 0x0F120000,
+ 0x0F120014,
+ 0x0F1200D2,
+ 0x0F120384,
+ 0x0F1207D0,
+ 0x0F121388,
+ 0x0F120180,
+ 0x0F120196,
+ 0x0F120054,
+ 0x0F120001,
+ 0x0F1201CC,
+ 0x0F1201CC,
+ 0x0F1201CC,
+ 0x0F1201CC,
+ 0x0F1201CC,
+
+ 0x002A0EF0,
+ 0x0F120001,
+
+ 0x002A0EF6,
+ 0x0F120002,
+
+ 0x002A1A84,
+ 0x0F12001C,
+
+ 0x002A01F8,
+ 0x0F120000,
+
+ 0x002A16E4,
+ 0x0F120100,
+
+ 0x002A01FA,
+ 0x0F120003,
+ 0x0F120000,
+
+ 0x002A0200,
+ 0x0F120061,
+
+ 0x002A0208,
+ 0x0F122F0C,
+ 0x0F120190,
+
+ 0x002A028E,
+ 0x0F120100,
+ 0x0F1200E3,
+ 0x0F120200,
+ 0x0F120238,
+ 0x0F1201C6,
+ 0x0F120166,
+ 0x0F120074,
+ 0x0F120132,
+ 0x0F120001,
+
+ 0x002A0702,
+ 0x0F1200FF,
+
+ 0x002A1600,
+ 0x0F120000,
+
+ 0x002A0712,
+ 0x0F120001,
+
+ 0x002A160C,
+ 0x0F129002,
+
+ 0x002A1616,
+ 0x0F120003,
+
+ 0x002A15A4,
+ 0x0F120902,
+
+ 0x002A1618,
+ 0x0F120000,
+
+ 0x002A1610,
+ 0x0F120003,
+
+ 0x002A1602,
+ 0x0F1200E5,
+ 0x0F120098,
+
+ 0x002A1598,
+ 0x0F120000,
+ 0x0F12D000,
+
+ 0x002A165E,
+ 0x0F12FF95,
+
+ 0x002A162E,
+ 0x0F120280,
+
+ 0x002A163A,
+ 0x0F1203A0,
+ 0x0F120320,
+
+ 0x002A1680,
+ 0x0F120030,
+
+ 0x002A16A4,
+ 0x0F120060,
+
+ 0x002A1698,
+ 0x0F120010,
+
+ 0x002A161A,
+ 0x0F120000,
+
+ 0x002A15AA,
+ 0x0F12003C,
+ 0x0F120018,
+ 0x0F12002A,
+ 0x0F120030,
+ 0x0F120036,
+ 0x0F12003C,
+ 0x0F120042,
+ 0x0F120048,
+ 0x0F12004E,
+ 0x0F120054,
+ 0x0F12005A,
+ 0x0F120060,
+ 0x0F120066,
+ 0x0F12006C,
+ 0x0F120072,
+ 0x0F120078,
+ 0x0F12007E,
+ 0x0F120084,
+ 0x0F12008A,
+ 0x0F120090,
+ 0x0F120096,
+ 0x0F12009C,
+ 0x0F1200A2,
+ 0x0F1200A8,
+ 0x0F1200AE,
+ 0x0F1200B4,
+ 0x0F1200BA,
+
+ 0x002A16E6,
+ 0x0F128000,
+ 0x0F120006,
+ 0x0F123FF0,
+ 0x0F1203E8,
+ 0x0F120000,
+ 0x0F120080,
+ 0x0F120009,
+ 0x0F120020,
+ 0x0F120040,
+ 0x0F120080,
+ 0x0F1200C0,
+ 0x0F1200E0,
+
+ 0x002A0286,
+ 0x0F120003,
+
+ 0x002A11B4,
+ 0x0F12012C,
+ 0x0F120121,
+
+ 0x002A1A00,
+ 0x0F12192E,
+ 0x0F127000,
+
+ 0x002A185C,
+ 0x0F120004,
+ 0x0F1209D1,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F1209D5,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120008,
+ 0x0F1209D5,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1202AA,
+ 0x0F120326,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1202AA,
+ 0x0F1209D1,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1202AA,
+ 0x0F1209D5,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1202AA,
+ 0x0F120327,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120008,
+ 0x0F120084,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120008,
+ 0x0F12008D,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120008,
+ 0x0F1202AA,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1200AA,
+ 0x0F1202AA,
+ 0x0F1203AD,
+ 0x0F1209CD,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1202AE,
+ 0x0F1202DE,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1202BE,
+ 0x0F1202EE,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1202CE,
+ 0x0F1202EE,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F120009,
+ 0x0F120095,
+ 0x0F1209DB,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120096,
+ 0x0F12009B,
+ 0x0F1202AE,
+ 0x0F1202B3,
+ 0x0F1209D1,
+ 0x0F1209D6,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1202AE,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120009,
+ 0x0F120010,
+ 0x0F120327,
+ 0x0F120336,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120004,
+ 0x0F1205B6,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F1205BA,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120007,
+ 0x0F1205BA,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1201F4,
+ 0x0F12024E,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1201F4,
+ 0x0F1205B6,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1201F4,
+ 0x0F1205BA,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1201F4,
+ 0x0F12024F,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120075,
+ 0x0F1200CF,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120075,
+ 0x0F1200D6,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120004,
+ 0x0F1201F4,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1200F0,
+ 0x0F1201F4,
+ 0x0F12029E,
+ 0x0F1205B2,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1201F8,
+ 0x0F120228,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120208,
+ 0x0F120238,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120218,
+ 0x0F120238,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F120009,
+ 0x0F1200DE,
+ 0x0F1205C0,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1200DF,
+ 0x0F1200E4,
+ 0x0F1201F8,
+ 0x0F1201FD,
+ 0x0F1205B6,
+ 0x0F1205BB,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1201F8,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120077,
+ 0x0F12007E,
+ 0x0F12024F,
+ 0x0F12025E,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+
+ 0x002A1836,
+ 0x0F120002,
+ 0x0F120000,
+ 0x0F120003,
+
+ 0x002A183E,
+ 0x0F120FB0,
+
+ 0x002A184C,
+ 0x0F120060,
+ 0x0F120060,
+ 0x0F1205C0,
+ 0x0F1205C0,
+
+ 0x002A1A8A,
+ 0x0F128080,
+ 0x0F120080,
+
+ 0x002A1A80,
+ 0x0F120000,
+
+ 0x002A1A12,
+ 0x0F120000,
+
+ 0x002A1842,
+ 0x0F120004,
+
+ 0x002A1A0A,
+ 0x0F12009A,
+
+ 0x002A3776,
+ 0x0F12024C,
+
+ 0x002A0EB2,
+ 0x0F120000,
+
+ 0x002A08C6,
+ 0x0F120001,
+
+ 0x002A08A4,
+ 0x0F120001,
+
+ 0x002A08E2,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124500,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+
+ 0x002A08E0,
+ 0x0F120001,
+
+ 0x002A1456,
+ 0x0F120000,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120000,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120201,
+ 0x0F120303,
+ 0x0F120303,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120403,
+ 0x0F120304,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120403,
+ 0x0F120304,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120403,
+ 0x0F120304,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120303,
+ 0x0F120303,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120202,
+ 0x0F120202,
+ 0x0F120102,
+
+ 0x002A1448,
+ 0x0F12003C,
+
+ 0x002A144E,
+ 0x0F12000F,
+
+ 0x002A0580,
+ 0x0F123520,
+ 0x0F120000,
+ 0x0F12C350,
+ 0x0F120000,
+ 0x0F123520,
+ 0x0F120000,
+ 0x0F12C350,
+ 0x0F120000,
+ 0x0F120470,
+ 0x0F120C00,
+ 0x0F120100,
+ 0x0F121000,
+
+ 0x002A0538,
+ 0x0F120111,
+ 0x0F1200EF,
+
+ 0x002A05FC,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F120600,
+ 0x0F120100,
+ 0x0F120001,
+ 0x0F120000,
+ 0x0F120A3C,
+ 0x0F120000,
+ 0x0F120D04,
+ 0x0F120000,
+ 0x0F124008,
+ 0x0F120000,
+ 0x0F127000,
+ 0x0F120000,
+ 0x0F129C00,
+ 0x0F120000,
+ 0x0F12AD00,
+ 0x0F120001,
+ 0x0F12F1D4,
+ 0x0F120002,
+ 0x0F12DC00,
+ 0x0F120005,
+ 0x0F12DC00,
+ 0x0F120005,
+ 0x0F120001,
+ 0x0F120000,
+ 0x0F120A3C,
+ 0x0F120000,
+ 0x0F120D05,
+ 0x0F120000,
+ 0x0F123408,
+ 0x0F120000,
+ 0x0F123408,
+ 0x0F120000,
+ 0x0F126810,
+ 0x0F120000,
+ 0x0F128214,
+ 0x0F120000,
+ 0x0F12C350,
+ 0x0F120000,
+ 0x0F12C350,
+ 0x0F120000,
+ 0x0F12C350,
+ 0x0F120000,
+ 0x0F120650,
+ 0x0F120100,
+
+ 0x002A06AC,
+ 0x0F12452C,
+ 0x0F120004,
+
+ 0x002A0280,
+ 0x0F120001,
+
+ 0x002A05C4,
+ 0x0F120000,
+
+ 0x002A0476,
+ 0x0F120001,
+ 0x0F120280,
+ 0x0F1201E0,
+ 0x0F120005,
+
+ 0x002A01F4,
+ 0x0F125DC0,
+
+ 0x002A020E,
+ 0x0F120002,
+ 0x0F120000,
+ 0x0F120000,
+
+ 0x002A0216,
+ 0x0F123A98,
+ 0x0F124F1A,
+ 0x0F124F1A,
+ 0x0F124F1A,
+ 0x0F124F1A,
+ 0x0F124F1A,
+
+ 0x002A0228,
+ 0x0F120001,
+
+ 0x002A02A0,
+ 0x0F120280,
+ 0x0F1201E0,
+ 0x0F120005,
+ 0x0F124F1A,
+ 0x0F124F1A,
+
+ 0x002A02AE,
+ 0x0F120052,
+
+ 0x002A02B6,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F12029A,
+ 0x0F12014D,
+
+ 0x002A02AA,
+ 0x0F120080,
+
+ 0x002A024C,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120010,
+ 0x0F12000C,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120010,
+ 0x0F12000C,
+
+ 0x002A048E,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120000,
+ 0x0F120000,
+
+ 0x002A025E,
+ 0x0F120001,
+ 0x0F120001,
+
+ 0x002A0392,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120009,
+ 0x0F124F1A,
+ 0x0F124F1A,
+
+ 0x002A03A0,
+ 0x0F120002,
+
+ 0x002A03A8,
+ 0x0F120001,
+ 0x0F120000,
+ 0x0F120002,
+ 0x0F120535,
+ 0x0F12029A,
+
+ 0x002A039C,
+ 0x0F120080,
+
+ 0x002A0476,
+ 0x0F120001,
+ 0x0F120280,
+ 0x0F1201E0,
+ 0x0F120005,
+
+ 0x002A0262,
+ 0x0F120000,
+
+ 0x002A0266,
+ 0x0F120001,
+
+ 0x002A024A,
+ 0x0F120001,
+
+ 0x002A0264,
+ 0x0F120001,
+
+ 0x002A026C,
+ 0x0F120001,
+
+ 0x002A023A,
+ 0x0F120001,
+ 0x0F120001,
+
+ 0x002A0472,
+ 0x0F12005F,
+ 0x0F12005F,
+
+ 0x002A0FE0,
+ 0x0F1203B8,
+ 0x0F1203CE,
+ 0x0F120350,
+ 0x0F1203C4,
+ 0x0F1202F2,
+ 0x0F120394,
+ 0x0F1202C0,
+ 0x0F120364,
+ 0x0F12029E,
+ 0x0F120334,
+ 0x0F12027C,
+ 0x0F120312,
+ 0x0F12025E,
+ 0x0F1202F2,
+ 0x0F120246,
+ 0x0F1202D0,
+ 0x0F120230,
+ 0x0F1202B0,
+ 0x0F120218,
+ 0x0F12029E,
+ 0x0F120208,
+ 0x0F120290,
+ 0x0F1201F8,
+ 0x0F120284,
+ 0x0F1201E8,
+ 0x0F120276,
+ 0x0F1201DA,
+ 0x0F12026A,
+ 0x0F1201CE,
+ 0x0F12025E,
+ 0x0F1201EC,
+ 0x0F12022E,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120005,
+
+ 0x002A1034,
+ 0x0F120010,
+
+ 0x002A1038,
+ 0x0F120126,
+
+ 0x002A103C,
+ 0x0F12026C,
+ 0x0F12029A,
+ 0x0F12025C,
+ 0x0F1202B6,
+ 0x0F12024E,
+ 0x0F1202C0,
+ 0x0F120240,
+ 0x0F1202BE,
+ 0x0F12023A,
+ 0x0F1202B4,
+ 0x0F12023A,
+ 0x0F1202AA,
+ 0x0F120240,
+ 0x0F12029E,
+ 0x0F12025C,
+ 0x0F120294,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120004,
+
+ 0x002A1070,
+ 0x0F120008,
+
+ 0x002A1074,
+ 0x0F1201E2,
+
+ 0x002A1078,
+ 0x0F120350,
+ 0x0F120422,
+ 0x0F1202C4,
+ 0x0F120452,
+ 0x0F120278,
+ 0x0F12041C,
+ 0x0F120230,
+ 0x0F1203EE,
+ 0x0F1201F0,
+ 0x0F120392,
+ 0x0F1201C0,
+ 0x0F120340,
+ 0x0F120194,
+ 0x0F120302,
+ 0x0F12016E,
+ 0x0F1202C2,
+ 0x0F120148,
+ 0x0F120286,
+ 0x0F12018A,
+ 0x0F120242,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120006,
+
+ 0x002A10AC,
+ 0x0F12000A,
+
+ 0x002A10B0,
+ 0x0F120106,
+
+ 0x002A10B4,
+ 0x0F120380,
+ 0x0F120000,
+ 0x0F120168,
+ 0x0F120000,
+ 0x0F122D90,
+ 0x0F120000,
+
+ 0x002A1428,
+ 0x0F120008,
+ 0x0F120190,
+ 0x0F1200A0,
+
+ 0x002A11EC,
+ 0x0F1200C0,
+
+ 0x002A11F0,
+ 0x0F120010,
+
+ 0x002A11EE,
+ 0x0F120010,
+
+ 0x002A11CE,
+ 0x0F1205D5,
+
+ 0x002A11D2,
+ 0x0F120000,
+ 0x0F120771,
+ 0x0F1203A4,
+ 0x0F120036,
+ 0x0F12002A,
+
+ 0x002A08AC,
+ 0x0F1200C0,
+ 0x0F1200DF,
+ 0x0F120100,
+ 0x0F120125,
+ 0x0F12015F,
+ 0x0F12017C,
+ 0x0F120194,
+
+ 0x002A123C,
+ 0x0F12FEF7,
+ 0x0F120021,
+ 0x0F120E74,
+ 0x0F120E74,
+ 0x0F12018F,
+ 0x0F120096,
+ 0x0F12000E,
+
+ 0x002A11E8,
+ 0x0F120032,
+ 0x0F12001E,
+
+ 0x002A2ABC,
+ 0x0F120006,
+
+ 0x002A1430,
+ 0x0F120002,
+
+ 0x002A140A,
+ 0x0F1200AB,
+ 0x0F1200BF,
+ 0x0F1200D2,
+ 0x0F120093,
+
+ 0x002A13F8,
+ 0x0F120300,
+ 0x0F12036E,
+ 0x0F1203C2,
+ 0x0F121015,
+ 0x0F1210E1,
+ 0x0F121154,
+ 0x0F1211A8,
+ 0x0F1211BB,
+ 0x0F12123B,
+
+ 0x002A1368,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120008,
+ 0x0F120030,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120008,
+ 0x0F120030,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120008,
+ 0x0F120030,
+ 0x0F12FFE0,
+ 0x0F12FFE0,
+ 0x0F12FFC0,
+ 0x0F12FFC0,
+ 0x0F12FFA0,
+ 0x0F12FE36,
+ 0x0F12FFE0,
+ 0x0F12FFE0,
+ 0x0F12FFC0,
+ 0x0F12FFC0,
+ 0x0F12FFA0,
+ 0x0F12FE36,
+ 0x0F12FFE0,
+ 0x0F12FFE0,
+ 0x0F12FFC0,
+ 0x0F12FFC0,
+ 0x0F12FFA0,
+ 0x0F12FE36,
+ 0x0F12FFEA,
+ 0x0F12FFEA,
+ 0x0F12FFC8,
+ 0x0F12FFC8,
+ 0x0F12FFC8,
+ 0x0F12FFC8,
+ 0x0F12FFEA,
+ 0x0F12FFEA,
+ 0x0F12FFC8,
+ 0x0F12FFC8,
+ 0x0F12FFC8,
+ 0x0F12FFC8,
+ 0x0F12FFEA,
+ 0x0F12FFEA,
+ 0x0F12FFC8,
+ 0x0F12FFC8,
+ 0x0F12FFC8,
+ 0x0F12FFC8,
+ 0x0F120014,
+ 0x0F120014,
+ 0x0F120014,
+ 0x0F12FDA0,
+ 0x0F12FCF0,
+ 0x0F12FCD0,
+ 0x0F120014,
+ 0x0F120014,
+ 0x0F120014,
+ 0x0F12FDA0,
+ 0x0F12FCF0,
+ 0x0F12FCD0,
+ 0x0F120014,
+ 0x0F120014,
+ 0x0F120014,
+ 0x0F12FDA0,
+ 0x0F12FCF0,
+ 0x0F12FCD0,
+
+ 0x002A13FE,
+ 0x0F121015,
+ 0x0F12106C,
+ 0x0F1210CA,
+ 0x0F121142,
+ 0x0F1211BB,
+ 0x0F12123B,
+ 0x0F1200AB,
+ 0x0F1200BF,
+ 0x0F1200D2,
+ 0x0F120093,
+
+ 0x002A11CC,
+ 0x0F120020,
+
+ 0x002A1412,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+
+ 0x002A0724,
+ 0x0F120001,
+ 0x0F120007,
+ 0x0F120010,
+ 0x0F120028,
+ 0x0F120062,
+ 0x0F1200D3,
+ 0x0F120130,
+ 0x0F120158,
+ 0x0F12017D,
+ 0x0F1201BE,
+ 0x0F1201F8,
+ 0x0F12022C,
+ 0x0F12025B,
+ 0x0F1202AA,
+ 0x0F1202EC,
+ 0x0F12034E,
+ 0x0F120396,
+ 0x0F1203C6,
+ 0x0F1203E9,
+ 0x0F1203F9,
+ 0x0F120001,
+ 0x0F120007,
+ 0x0F120010,
+ 0x0F120028,
+ 0x0F120062,
+ 0x0F1200D3,
+ 0x0F120130,
+ 0x0F120158,
+ 0x0F12017D,
+ 0x0F1201BE,
+ 0x0F1201F8,
+ 0x0F12022C,
+ 0x0F12025B,
+ 0x0F1202AA,
+ 0x0F1202EC,
+ 0x0F12034E,
+ 0x0F120396,
+ 0x0F1203C6,
+ 0x0F1203E9,
+ 0x0F1203F9,
+ 0x0F120001,
+ 0x0F120007,
+ 0x0F120010,
+ 0x0F120028,
+ 0x0F120062,
+ 0x0F1200D3,
+ 0x0F120130,
+ 0x0F120158,
+ 0x0F12017D,
+ 0x0F1201BE,
+ 0x0F1201F8,
+ 0x0F12022C,
+ 0x0F12025B,
+ 0x0F1202AA,
+ 0x0F1202EC,
+ 0x0F12034E,
+ 0x0F120396,
+ 0x0F1203C6,
+ 0x0F1203E9,
+ 0x0F1203F9,
+ 0x0F120000,
+ 0x0F12000F,
+ 0x0F120020,
+ 0x0F120043,
+ 0x0F120086,
+ 0x0F1200ED,
+ 0x0F12013E,
+ 0x0F120163,
+ 0x0F120185,
+ 0x0F1201BF,
+ 0x0F1201F2,
+ 0x0F120221,
+ 0x0F12024A,
+ 0x0F120294,
+ 0x0F1202D0,
+ 0x0F12032A,
+ 0x0F12036A,
+ 0x0F12039F,
+ 0x0F1203CC,
+ 0x0F1203F9,
+ 0x0F120000,
+ 0x0F12000F,
+ 0x0F120020,
+ 0x0F120043,
+ 0x0F120086,
+ 0x0F1200ED,
+ 0x0F12013E,
+ 0x0F120163,
+ 0x0F120185,
+ 0x0F1201BF,
+ 0x0F1201F2,
+ 0x0F120221,
+ 0x0F12024A,
+ 0x0F120294,
+ 0x0F1202D0,
+ 0x0F12032A,
+ 0x0F12036A,
+ 0x0F12039F,
+ 0x0F1203CC,
+ 0x0F1203F9,
+ 0x0F120000,
+ 0x0F12000F,
+ 0x0F120020,
+ 0x0F120043,
+ 0x0F120086,
+ 0x0F1200ED,
+ 0x0F12013E,
+ 0x0F120163,
+ 0x0F120185,
+ 0x0F1201BF,
+ 0x0F1201F2,
+ 0x0F120221,
+ 0x0F12024A,
+ 0x0F120294,
+ 0x0F1202D0,
+ 0x0F12032A,
+ 0x0F12036A,
+ 0x0F12039F,
+ 0x0F1203CC,
+ 0x0F1203F9,
+
+ 0x002A0896,
+ 0x0F1200C0,
+ 0x0F120100,
+ 0x0F120125,
+ 0x0F12015F,
+ 0x0F12017C,
+ 0x0F120194,
+ 0x0F120001,
+
+ 0x002A0888,
+ 0x0F124800,
+ 0x0F127000,
+
+ 0x002A4800,
+ 0x0F12016C,
+ 0x0F12FF94,
+ 0x0F12FFCE,
+ 0x0F12FF20,
+ 0x0F1201BF,
+ 0x0F12FF53,
+ 0x0F12003F,
+ 0x0F120007,
+ 0x0F1201DF,
+ 0x0F120110,
+ 0x0F1200DF,
+ 0x0F12FF47,
+ 0x0F120206,
+ 0x0F12FF7F,
+ 0x0F120191,
+ 0x0F12FF06,
+ 0x0F1201BA,
+ 0x0F120108,
+ 0x0F12016C,
+ 0x0F12FF94,
+ 0x0F12FFCE,
+ 0x0F12FF20,
+ 0x0F1201BF,
+ 0x0F12FF53,
+ 0x0F12003F,
+ 0x0F120007,
+ 0x0F1201DF,
+ 0x0F120110,
+ 0x0F1200DF,
+ 0x0F12FF47,
+ 0x0F120206,
+ 0x0F12FF7F,
+ 0x0F120191,
+ 0x0F12FF06,
+ 0x0F1201BA,
+ 0x0F120108,
+ 0x0F12016C,
+ 0x0F12FF94,
+ 0x0F12FFCE,
+ 0x0F12FF20,
+ 0x0F1201BF,
+ 0x0F12FF53,
+ 0x0F12003F,
+ 0x0F120007,
+ 0x0F1201DF,
+ 0x0F120110,
+ 0x0F1200DF,
+ 0x0F12FF47,
+ 0x0F120206,
+ 0x0F12FF7F,
+ 0x0F120191,
+ 0x0F12FF06,
+ 0x0F1201BA,
+ 0x0F120108,
+ 0x0F120208,
+ 0x0F12FFD3,
+ 0x0F12FFE9,
+ 0x0F12FF5B,
+ 0x0F12025A,
+ 0x0F12FF80,
+ 0x0F12FFC8,
+ 0x0F12FFC1,
+ 0x0F12013A,
+ 0x0F120112,
+ 0x0F1200EE,
+ 0x0F12FF99,
+ 0x0F12009E,
+ 0x0F12FF5F,
+ 0x0F1201A8,
+ 0x0F12FF75,
+ 0x0F120187,
+ 0x0F1201BF,
+ 0x0F120208,
+ 0x0F12FFD3,
+ 0x0F12FFE9,
+ 0x0F12FF5B,
+ 0x0F12025A,
+ 0x0F12FF80,
+ 0x0F12FFC8,
+ 0x0F12FFC1,
+ 0x0F12013A,
+ 0x0F120112,
+ 0x0F1200EE,
+ 0x0F12FF99,
+ 0x0F12009E,
+ 0x0F12FF5F,
+ 0x0F1201A8,
+ 0x0F12FF75,
+ 0x0F120187,
+ 0x0F1201BF,
+ 0x0F120208,
+ 0x0F12FFD3,
+ 0x0F12FFE9,
+ 0x0F12FF5B,
+ 0x0F12025A,
+ 0x0F12FF80,
+ 0x0F12FFC8,
+ 0x0F12FFC1,
+ 0x0F12013A,
+ 0x0F120112,
+ 0x0F1200EE,
+ 0x0F12FF99,
+ 0x0F12009E,
+ 0x0F12FF5F,
+ 0x0F1201A8,
+ 0x0F12FF75,
+ 0x0F120187,
+ 0x0F1201BF,
+
+ 0x002A0890,
+ 0x0F1248D8,
+ 0x0F127000,
+
+ 0x002A48D8,
+ 0x0F1201AA,
+ 0x0F12FFB6,
+ 0x0F12FFD4,
+ 0x0F12FF6C,
+ 0x0F1201E8,
+ 0x0F12FF79,
+ 0x0F120000,
+ 0x0F12FFF5,
+ 0x0F12023C,
+ 0x0F1200BF,
+ 0x0F1200E0,
+ 0x0F12FF5B,
+ 0x0F12022D,
+ 0x0F12FF9B,
+ 0x0F1201E1,
+ 0x0F12FF34,
+ 0x0F12014B,
+ 0x0F1201B6,
+
+ 0x002A0924,
+ 0x0F120050,
+ 0x0F1200B0,
+ 0x0F120196,
+ 0x0F120245,
+ 0x0F120300,
+
+ 0x002A0958,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1200C0,
+ 0x0F120064,
+ 0x0F120384,
+ 0x0F120032,
+ 0x0F1201F4,
+ 0x0F120070,
+ 0x0F120040,
+ 0x0F1200A0,
+ 0x0F120100,
+ 0x0F120010,
+ 0x0F120040,
+ 0x0F1200A0,
+ 0x0F121430,
+ 0x0F120201,
+ 0x0F120204,
+ 0x0F123604,
+ 0x0F12032A,
+ 0x0F120403,
+ 0x0F121B06,
+ 0x0F126015,
+ 0x0F1200C0,
+ 0x0F126080,
+ 0x0F124080,
+ 0x0F120640,
+ 0x0F120306,
+ 0x0F122003,
+ 0x0F12FF01,
+ 0x0F120000,
+ 0x0F120400,
+ 0x0F12365A,
+ 0x0F12102A,
+ 0x0F12000B,
+ 0x0F120600,
+ 0x0F125A0F,
+ 0x0F120505,
+ 0x0F121802,
+ 0x0F120000,
+ 0x0F122006,
+ 0x0F123028,
+ 0x0F120418,
+ 0x0F120101,
+ 0x0F120800,
+ 0x0F121804,
+ 0x0F124008,
+ 0x0F120540,
+ 0x0F128006,
+ 0x0F120020,
+ 0x0F120000,
+ 0x0F121800,
+ 0x0F120000,
+ 0x0F121E10,
+ 0x0F12000B,
+ 0x0F120607,
+ 0x0F120005,
+ 0x0F120607,
+ 0x0F120405,
+ 0x0F120205,
+ 0x0F120304,
+ 0x0F120409,
+ 0x0F120306,
+ 0x0F120407,
+ 0x0F121C04,
+ 0x0F120214,
+ 0x0F121002,
+ 0x0F120610,
+ 0x0F120F02,
+ 0x0F124A18,
+ 0x0F120080,
+ 0x0F120040,
+ 0x0F120180,
+ 0x0F120A0A,
+ 0x0F120101,
+ 0x0F122A36,
+ 0x0F126024,
+ 0x0F122A36,
+ 0x0F12FFFF,
+ 0x0F120808,
+ 0x0F120A01,
+ 0x0F12010A,
+ 0x0F123601,
+ 0x0F12242A,
+ 0x0F123660,
+ 0x0F12FF2A,
+ 0x0F1208FF,
+ 0x0F120008,
+ 0x0F120001,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1200C0,
+ 0x0F120064,
+ 0x0F120384,
+ 0x0F120032,
+ 0x0F1201F4,
+ 0x0F120070,
+ 0x0F120040,
+ 0x0F1200A0,
+ 0x0F120100,
+ 0x0F120010,
+ 0x0F120060,
+ 0x0F120100,
+ 0x0F121430,
+ 0x0F120201,
+ 0x0F120204,
+ 0x0F122404,
+ 0x0F12031B,
+ 0x0F120103,
+ 0x0F121205,
+ 0x0F12400D,
+ 0x0F120080,
+ 0x0F122080,
+ 0x0F123040,
+ 0x0F120630,
+ 0x0F120306,
+ 0x0F122003,
+ 0x0F12FF01,
+ 0x0F120404,
+ 0x0F120300,
+ 0x0F12245A,
+ 0x0F121018,
+ 0x0F12000B,
+ 0x0F120B00,
+ 0x0F125A0F,
+ 0x0F120505,
+ 0x0F121802,
+ 0x0F120000,
+ 0x0F122006,
+ 0x0F123428,
+ 0x0F12041C,
+ 0x0F120101,
+ 0x0F120800,
+ 0x0F121004,
+ 0x0F124008,
+ 0x0F120540,
+ 0x0F128006,
+ 0x0F120020,
+ 0x0F120000,
+ 0x0F121800,
+ 0x0F120000,
+ 0x0F121E10,
+ 0x0F12000B,
+ 0x0F120607,
+ 0x0F120005,
+ 0x0F120607,
+ 0x0F120405,
+ 0x0F120205,
+ 0x0F120304,
+ 0x0F120409,
+ 0x0F120306,
+ 0x0F120407,
+ 0x0F121F04,
+ 0x0F120218,
+ 0x0F121102,
+ 0x0F120611,
+ 0x0F121002,
+ 0x0F128018,
+ 0x0F120080,
+ 0x0F120080,
+ 0x0F120180,
+ 0x0F120A0A,
+ 0x0F120101,
+ 0x0F121B24,
+ 0x0F126024,
+ 0x0F121010,
+ 0x0F12FFFF,
+ 0x0F120808,
+ 0x0F120A01,
+ 0x0F12010A,
+ 0x0F122401,
+ 0x0F12241B,
+ 0x0F121E60,
+ 0x0F12FF18,
+ 0x0F1208FF,
+ 0x0F120008,
+ 0x0F120001,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1200C0,
+ 0x0F120064,
+ 0x0F120384,
+ 0x0F120032,
+ 0x0F1201F4,
+ 0x0F120070,
+ 0x0F120040,
+ 0x0F1200A0,
+ 0x0F120100,
+ 0x0F120010,
+ 0x0F120060,
+ 0x0F120100,
+ 0x0F121430,
+ 0x0F120201,
+ 0x0F120204,
+ 0x0F121B04,
+ 0x0F120312,
+ 0x0F120003,
+ 0x0F120C03,
+ 0x0F122806,
+ 0x0F120060,
+ 0x0F121580,
+ 0x0F122020,
+ 0x0F120620,
+ 0x0F120306,
+ 0x0F122003,
+ 0x0F12FF01,
+ 0x0F120404,
+ 0x0F120300,
+ 0x0F12145A,
+ 0x0F121010,
+ 0x0F12000B,
+ 0x0F120E00,
+ 0x0F125A0F,
+ 0x0F120504,
+ 0x0F121802,
+ 0x0F120000,
+ 0x0F122006,
+ 0x0F123828,
+ 0x0F120428,
+ 0x0F120101,
+ 0x0F128000,
+ 0x0F120A04,
+ 0x0F124008,
+ 0x0F120540,
+ 0x0F128006,
+ 0x0F120020,
+ 0x0F120000,
+ 0x0F121800,
+ 0x0F120000,
+ 0x0F121E10,
+ 0x0F12000B,
+ 0x0F120607,
+ 0x0F120005,
+ 0x0F120607,
+ 0x0F120405,
+ 0x0F120207,
+ 0x0F120304,
+ 0x0F120409,
+ 0x0F120306,
+ 0x0F120407,
+ 0x0F122404,
+ 0x0F120221,
+ 0x0F121202,
+ 0x0F120613,
+ 0x0F121202,
+ 0x0F128018,
+ 0x0F120080,
+ 0x0F120080,
+ 0x0F120180,
+ 0x0F120A0A,
+ 0x0F120101,
+ 0x0F12121B,
+ 0x0F126024,
+ 0x0F120C0C,
+ 0x0F12FFFF,
+ 0x0F120808,
+ 0x0F120A01,
+ 0x0F12010A,
+ 0x0F121B01,
+ 0x0F122412,
+ 0x0F120C60,
+ 0x0F12FF0C,
+ 0x0F1208FF,
+ 0x0F120008,
+ 0x0F120001,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1200C0,
+ 0x0F120064,
+ 0x0F120384,
+ 0x0F120032,
+ 0x0F1201F4,
+ 0x0F120070,
+ 0x0F120040,
+ 0x0F1200A0,
+ 0x0F120100,
+ 0x0F120010,
+ 0x0F120060,
+ 0x0F120100,
+ 0x0F121430,
+ 0x0F120201,
+ 0x0F120204,
+ 0x0F121504,
+ 0x0F12030F,
+ 0x0F120003,
+ 0x0F120902,
+ 0x0F122004,
+ 0x0F120050,
+ 0x0F121140,
+ 0x0F12201C,
+ 0x0F120620,
+ 0x0F120306,
+ 0x0F122003,
+ 0x0F12FF01,
+ 0x0F120404,
+ 0x0F120300,
+ 0x0F12145A,
+ 0x0F121010,
+ 0x0F12000B,
+ 0x0F121000,
+ 0x0F125A0F,
+ 0x0F120503,
+ 0x0F121802,
+ 0x0F120000,
+ 0x0F122006,
+ 0x0F123C28,
+ 0x0F12042C,
+ 0x0F120101,
+ 0x0F12FF00,
+ 0x0F120904,
+ 0x0F124008,
+ 0x0F120540,
+ 0x0F128006,
+ 0x0F120020,
+ 0x0F120000,
+ 0x0F121800,
+ 0x0F120000,
+ 0x0F121E10,
+ 0x0F12000B,
+ 0x0F120607,
+ 0x0F120005,
+ 0x0F120607,
+ 0x0F120405,
+ 0x0F120206,
+ 0x0F120304,
+ 0x0F120409,
+ 0x0F120305,
+ 0x0F120406,
+ 0x0F122804,
+ 0x0F120228,
+ 0x0F121402,
+ 0x0F120618,
+ 0x0F121402,
+ 0x0F128018,
+ 0x0F120080,
+ 0x0F120080,
+ 0x0F120180,
+ 0x0F120A0A,
+ 0x0F120101,
+ 0x0F120F15,
+ 0x0F126024,
+ 0x0F120A0A,
+ 0x0F12FFFF,
+ 0x0F120808,
+ 0x0F120A01,
+ 0x0F12010A,
+ 0x0F121501,
+ 0x0F12240F,
+ 0x0F120A60,
+ 0x0F12FF0A,
+ 0x0F1208FF,
+ 0x0F120008,
+ 0x0F120001,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1200C0,
+ 0x0F120064,
+ 0x0F120384,
+ 0x0F120032,
+ 0x0F1201F4,
+ 0x0F120070,
+ 0x0F120040,
+ 0x0F1200A0,
+ 0x0F120100,
+ 0x0F120010,
+ 0x0F120060,
+ 0x0F120100,
+ 0x0F121430,
+ 0x0F120201,
+ 0x0F120204,
+ 0x0F120F04,
+ 0x0F12030C,
+ 0x0F120003,
+ 0x0F120602,
+ 0x0F121803,
+ 0x0F120040,
+ 0x0F120E20,
+ 0x0F122018,
+ 0x0F120620,
+ 0x0F120306,
+ 0x0F122003,
+ 0x0F12FF01,
+ 0x0F120404,
+ 0x0F120200,
+ 0x0F12145A,
+ 0x0F121010,
+ 0x0F12000B,
+ 0x0F121200,
+ 0x0F125A0F,
+ 0x0F120502,
+ 0x0F121802,
+ 0x0F120000,
+ 0x0F122006,
+ 0x0F124028,
+ 0x0F120430,
+ 0x0F120101,
+ 0x0F12FF00,
+ 0x0F120804,
+ 0x0F124008,
+ 0x0F120540,
+ 0x0F128006,
+ 0x0F120020,
+ 0x0F120000,
+ 0x0F121800,
+ 0x0F120000,
+ 0x0F121E10,
+ 0x0F12000B,
+ 0x0F120607,
+ 0x0F120005,
+ 0x0F120607,
+ 0x0F120405,
+ 0x0F120205,
+ 0x0F120304,
+ 0x0F120409,
+ 0x0F120306,
+ 0x0F120407,
+ 0x0F122C04,
+ 0x0F12022C,
+ 0x0F121402,
+ 0x0F120618,
+ 0x0F121402,
+ 0x0F128018,
+ 0x0F120080,
+ 0x0F120080,
+ 0x0F120180,
+ 0x0F120A0A,
+ 0x0F120101,
+ 0x0F120C0F,
+ 0x0F126024,
+ 0x0F120808,
+ 0x0F12FFFF,
+ 0x0F120808,
+ 0x0F120A01,
+ 0x0F12010A,
+ 0x0F120F01,
+ 0x0F12240C,
+ 0x0F120860,
+ 0x0F12FF08,
+ 0x0F1208FF,
+ 0x0F120008,
+ 0x0F120001,
+ 0x0F1223CE,
+ 0x0F12FDC8,
+ 0x0F12112E,
+ 0x0F1293A5,
+ 0x0F12FE67,
+ 0x0F120000,
+
+ 0xFCFCD000,
+ 0x00287000,
+ 0x002A01A2,
+ 0x0F120A0A,
+
+ 0xFCFCD000,
+ 0x00040001,
+};
+
+static const u32 s5k4ecgx_DTP_init_v1[] = {
+ 0x0028D000,
+ 0x002AB054,
+ 0x0F120001,
+ 0x00287000,
+};
+
+static const u32 s5k4ecgx_DTP_stop_v1[] = {
+ 0x0028D000,
+ 0x002AB054,
+ 0x0F120000,
+ 0x00287000,
+};
+
+static const u32 s5k4ecgx_Effect_Normal_v1[] = {
+ 0x002A0238,
+ 0x0F120000,
+};
+
+static const u32 s5k4ecgx_Effect_Negative_v1[] = {
+ 0x002A0238,
+ 0x0F120003,
+};
+
+static const u32 s5k4ecgx_Effect_Sepia_v1[] = {
+ 0x002A0238,
+ 0x0F120004,
+};
+
+static const u32 s5k4ecgx_Effect_Black_White_v1[] = {
+ 0x002A0238,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_WB_Auto_v1[] = {
+ 0x002a04E0,
+ 0x0f12077F,
+};
+
+static const u32 s5k4ecgx_WB_Sunny_v1[] = {
+ 0x002a04E0,
+ 0x0f120777,
+ 0x002a04B4,
+ 0x0f1205E0,
+ 0x0f120001,
+ 0x0f120400,
+ 0x0f120001,
+ 0x0f120530,
+ 0x0f120001,
+ 0x0f120001,
+};
+
+static const u32 s5k4ecgx_WB_Cloudy_v1[] = {
+ 0x002a04E0,
+ 0x0f120777,
+ 0x002a04B4,/* USER RGB Gain */
+ 0x0f120710,/* R */
+ 0x0f120001,/* Changed */
+ 0x0f120400,/* G */
+ 0x0f120001,
+ 0x0f120420,/* B 480-reference */
+ 0x0f120001,
+ 0x0f120001,
+};
+
+static const u32 s5k4ecgx_WB_Tungsten_v1[] = {
+ 0x002a04E0,
+ 0x0f120777,
+ 0x002a04B4,
+ 0x0f120390,
+ 0x0f120001,
+ 0x0f120400,
+ 0x0f120001,
+ 0x0f120920,
+ 0x0f120001,
+ 0x0f120001,
+};
+
+static const u32 s5k4ecgx_WB_Fluorescent_v1[] = {
+ 0x002a04E0,
+ 0x0f120777,
+ 0x002a04B4,
+ 0x0f120505,
+ 0x0f120001,
+ 0x0f120400,
+ 0x0f120001,
+ 0x0f120875,
+ 0x0f120001,
+ 0x0f120001,
+};
+
+static const u32 s5k4ecgx_WDR_on_v1[] = {
+ 0x002A1B4A,
+ 0x0F120000,
+};
+
+static const u32 s5k4ecgx_WDR_off_v1[] = {
+ 0x002A1B4A,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_ISO_Auto_v1[] = {
+ 0x002A4780,
+ 0x0F120000,
+
+ 0x002A0EF0,
+ 0x0F120001,
+ 0x002A04E0,
+ 0x0F12077F,
+ 0x002A04CA,
+ 0x0F120000,
+
+ 0x002A04CA,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120001,
+ 0x002A06B6,
+ 0x0F120200,
+};
+
+static const u32 s5k4ecgx_ISO_100_v1[] = {
+ 0x002A04E0,
+ 0x0F12065F,
+ 0x002A04D0,
+ 0x0F120000,
+ 0x0F120001,
+
+ 0x002A04CA,
+ 0x0F120001,
+ 0x0F1201A0,
+ 0x0F120001,
+ 0x002A06B6,
+ 0x0F120100,
+
+ 0x002A4780,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_ISO_200_v1[] = {
+ 0x002A04E0,
+ 0x0F12065F,
+ 0x002A04D0,
+ 0x0F120000,
+ 0x0F120001,
+
+ 0x002A04CA,
+ 0x0F120001,
+ 0x0F120340,
+ 0x0F120001,
+ 0x002A06B6,
+ 0x0F120100,
+
+ 0x002A4780,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_ISO_400_v1[] = {
+ 0x002A04E0,
+ 0x0F12065F,
+ 0x002A04D0,
+ 0x0F120000,
+ 0x0F120001,
+
+ 0x002A04CA,
+ 0x0F120001,
+ 0x0F120680,
+ 0x0F120001,
+ 0x002A06B6,
+ 0x0F120100,
+
+ 0x002A4780,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Metering_Matrix_v1[] = {
+ 0x002A1456,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+};
+
+static const u32 s5k4ecgx_Metering_Center_v1[] = {
+ 0x002A1456,
+ 0x0F120000,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120000,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120201,
+ 0x0F120303,
+ 0x0F120303,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120403,
+ 0x0F120304,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120403,
+ 0x0F120304,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120403,
+ 0x0F120304,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120303,
+ 0x0F120303,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120202,
+ 0x0F120202,
+ 0x0F120102,
+};
+
+static const u32 s5k4ecgx_Metering_Spot_v1[] = {
+ 0x002A1456,
+ 0x0f120000,
+ 0x0f120000,
+ 0x0f120000,
+ 0x0f120000,
+ 0x0f120000,
+ 0x0f120000,
+ 0x0f120000,
+ 0x0f120000,
+ 0x0f120000,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120000,
+ 0x0f120000,
+ 0x0f12010f,
+ 0x0f120f01,
+ 0x0f120000,
+ 0x0f120000,
+ 0x0f12010f,
+ 0x0f120f01,
+ 0x0f120000,
+ 0x0f120000,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120000,
+ 0x0f120000,
+ 0x0f120000,
+ 0x0f120000,
+ 0x0f120000,
+ 0x0f120000,
+ 0x0f120000,
+ 0x0f120000,
+ 0x0f120000,
+};
+
+static const u32 s5k4ecgx_EV_Minus_4_v1[] = {
+ 0x002A022C,
+ 0x0F12FF30,
+};
+
+static const u32 s5k4ecgx_EV_Minus_3_v1[] = {
+ 0x002A022C,
+ 0x0F12FFA0,
+};
+
+static const u32 s5k4ecgx_EV_Minus_2_v1[] = {
+ 0x002A022C,
+ 0x0F12FFC8,
+};
+
+static const u32 s5k4ecgx_EV_Minus_1_v1[] = {
+ 0x002A022C,
+ 0x0F12FFE0,
+};
+
+static const u32 s5k4ecgx_EV_Default_v1[] = {
+ 0x002A022C,
+ 0x0F120000,
+};
+
+static const u32 s5k4ecgx_EV_Plus_1_v1[] = {
+ 0x002A022C,
+ 0x0F120020,
+};
+
+static const u32 s5k4ecgx_EV_Plus_2_v1[] = {
+ 0x002A022C,
+ 0x0F120038,
+};
+
+static const u32 s5k4ecgx_EV_Plus_3_v1[] = {
+ 0x002A022C,
+ 0x0F120060,
+};
+
+static const u32 s5k4ecgx_EV_Plus_4_v1[] = {
+ 0x002A022C,
+ 0x0F12007F,
+};
+
+static const u32 s5k4ecgx_Contrast_Minus_4_v1[] = {
+ 0x002A022E,
+ 0x0F12FF81,
+};
+
+static const u32 s5k4ecgx_Contrast_Minus_3_v1[] = {
+ 0x002A022E,
+ 0x0F12FFA0,
+};
+
+static const u32 s5k4ecgx_Contrast_Minus_2_v1[] = {
+ 0x002A022E,
+ 0x0F12FFC0,
+};
+
+static const u32 s5k4ecgx_Contrast_Minus_1_v1[] = {
+ 0x002A022E,
+ 0x0F12FFE0,
+};
+
+static const u32 s5k4ecgx_Contrast_Default_v1[] = {
+ 0x002A022E,
+ 0x0F120000,
+};
+
+static const u32 s5k4ecgx_Contrast_Plus_1_v1[] = {
+ 0x002A022E,
+ 0x0F120020,
+};
+
+static const u32 s5k4ecgx_Contrast_Plus_2_v1[] = {
+ 0x002A022E,
+ 0x0F120040,
+};
+
+static const u32 s5k4ecgx_Contrast_Plus_3_v1[] = {
+ 0x002A022E,
+ 0x0F120060,
+};
+
+static const u32 s5k4ecgx_Contrast_Plus_4_v1[] = {
+ 0x002A022E,
+ 0x0F12007F,
+};
+
+static const u32 s5k4ecgx_Sharpness_Minus_3_v1[] = {
+ 0x002A09F4,
+ 0x0F120000,
+ 0x002A0AAA,
+ 0x0F120000,
+ 0x002A0B60,
+ 0x0F120000,
+ 0x002A0C16,
+ 0x0F120000,
+ 0x002A0CCC,
+ 0x0F120000,
+};
+
+static const u32 s5k4ecgx_Sharpness_Minus_2_v1[] = {
+ 0x002A09F4,
+ 0x0F122010,
+ 0x002A0AAA,
+ 0x0F122010,
+ 0x002A0B60,
+ 0x0F122010,
+ 0x002A0C16,
+ 0x0F122010,
+ 0x002A0CCC,
+ 0x0F122010,
+};
+
+static const u32 s5k4ecgx_Sharpness_Minus_1_v1[] = {
+ 0x002A09F4,
+ 0x0F124020,
+ 0x002A0AAA,
+ 0x0F124020,
+ 0x002A0B60,
+ 0x0F124020,
+ 0x002A0C16,
+ 0x0F124020,
+ 0x002A0CCC,
+ 0x0F124020,
+};
+
+static const u32 s5k4ecgx_Sharpness_Default_v1[] = {
+ 0x002A09F4,
+ 0x0F126024,
+ 0x002A0AAA,
+ 0x0F126024,
+ 0x002A0B60,
+ 0x0F126024,
+ 0x002A0C16,
+ 0x0F126024,
+ 0x002A0CCC,
+ 0x0F126024,
+};
+
+static const u32 s5k4ecgx_Sharpness_Plus_1_v1[] = {
+ 0x002A09F4,
+ 0x0F128040,
+ 0x002A0AAA,
+ 0x0F128040,
+ 0x002A0B60,
+ 0x0F128040,
+ 0x002A0C16,
+ 0x0F128040,
+ 0x002A0CCC,
+ 0x0F128040,
+};
+
+static const u32 s5k4ecgx_Sharpness_Plus_2_v1[] = {
+ 0x002A09F4,
+ 0x0F12A060,
+ 0x002A0AAA,
+ 0x0F12A060,
+ 0x002A0B60,
+ 0x0F12A060,
+ 0x002A0C16,
+ 0x0F12A060,
+ 0x002A0CCC,
+ 0x0F12A060,
+};
+
+static const u32 s5k4ecgx_Sharpness_Plus_3_v1[] = {
+ 0x002A09F4,
+ 0x0F12C080,
+ 0x002A0AAA,
+ 0x0F12C080,
+ 0x002A0B60,
+ 0x0F12C080,
+ 0x002A0C16,
+ 0x0F12C080,
+ 0x002A0CCC,
+ 0x0F12C080,
+};
+
+static const u32 s5k4ecgx_Saturation_Minus_2_v1[] = {
+ 0x002A0230,
+ 0x0F12FF81,
+};
+
+static const u32 s5k4ecgx_Saturation_Minus_1_v1[] = {
+ 0x002A0230,
+ 0x0F12FFC0,
+};
+
+static const u32 s5k4ecgx_Saturation_Default_v1[] = {
+ 0x002A0230,
+ 0x0F120000,
+};
+
+static const u32 s5k4ecgx_Saturation_Plus_1_v1[] = {
+ 0x002A0230,
+ 0x0F120040,
+};
+
+static const u32 s5k4ecgx_Saturation_Plus_2_v1[] = {
+ 0x002A0230,
+ 0x0F12007F,
+};
+
+static const u32 s5k4ecgx_Jpeg_Quality_High_v1[] = {
+ 0x002A0472,
+ 0x0F12005F,
+ 0x0F12005F,
+};
+
+static const u32 s5k4ecgx_Jpeg_Quality_Normal_v1[] = {
+ 0x002A0472,
+ 0x0F120050,
+ 0x0F120050,
+};
+
+static const u32 s5k4ecgx_Jpeg_Quality_Low_v1[] = {
+ 0x002A0472,
+ 0x0F12004B,
+ 0x0F12004B,
+};
+
+static const u32 s5k4ecgx_Scene_Default_v1[] = {
+ 0x002A1456,
+ 0x0F120000,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120000,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120201,
+ 0x0F120303,
+ 0x0F120303,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120403,
+ 0x0F120304,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120403,
+ 0x0F120304,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120403,
+ 0x0F120304,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120303,
+ 0x0F120303,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120202,
+ 0x0F120202,
+ 0x0F120102,
+
+ 0x002A4780,
+ 0x0F120000,
+
+ 0x002A06AC,
+ 0x0F12452C,
+ 0x0F120004,
+
+ 0x002A0EF0,
+ 0x0F120001,
+ 0x002A0EF6,
+ 0x0F120001,
+ 0x002A04E0,
+ 0x0F12077F,
+ 0x002A04CA,
+ 0x0F120000,
+
+ 0x002A04CA,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120001,
+ 0x002A06B6,
+ 0x0F120200,
+
+ 0x002a2B7E,
+ 0x0f120001,
+
+
+ 0x002A1448,
+ 0x0F12003C,
+ 0x002A144E,
+ 0x0F12000F,
+ 0x002A0580,
+ 0x0F123520,
+ 0x0F120000,
+ 0x0F12C350,
+ 0x0F120000,
+ 0x0F123520,
+ 0x0F120000,
+ 0x0F12C350,
+ 0x0F120000,
+ 0x0F120470,
+ 0x0F120C00,
+ 0x0F120100,
+ 0x0F121000,
+
+ 0x002A0538,
+ 0x0F120111,
+ 0x0F1200EF,
+
+
+ 0x002A05FC,
+ 0x0F120000,
+ 0x0F120001,
+
+ 0x002A09F4,
+ 0x0F126024,
+ 0x002A0AAA,
+ 0x0F126024,
+ 0x002A0B60,
+ 0x0F126024,
+ 0x002A0C16,
+ 0x0F126024,
+ 0x002A0CCC,
+ 0x0F126024,
+
+ 0x002A0230,
+ 0x0F120000,
+
+ 0x002A062C,
+ 0x0F120001,
+ 0x0F120000,
+ 0x002A0630,
+ 0x0F120A3C,
+ 0x0F120000,
+ 0x002A0634,
+ 0x0F120D05,
+ 0x0F120000,
+ 0x002A0638,
+ 0x0F123408,
+ 0x0F120000,
+ 0x002A063C,
+ 0x0F123408,
+ 0x0F120000,
+ 0x002A0640,
+ 0x0F126810,
+ 0x0F120000,
+ 0x002A0644,
+ 0x0F128214,
+ 0x0F120000,
+ 0x002A0648,
+ 0x0F12C350,
+ 0x0F120000,
+ 0x002A064C,
+ 0x0F12C350,
+ 0x0F120000,
+ 0x002A0650,
+ 0x0F12C350,
+ 0x0F120000,
+
+ 0x002A03AE,
+ 0x0F120535,
+ 0x0F12029A,
+
+
+ 0x002A0262,
+ 0x0F120000,
+ 0x002A0266,
+ 0x0F120001,
+ 0x002A024A,
+ 0x0F120001,
+ 0x002A0264,
+ 0x0F120001,
+ 0x002A026C,
+ 0x0F120001,
+ 0x002A023A,
+ 0x0F120001,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Scene_Portrait_v1[] = {
+ 0x002A09F4,
+ 0x0F124020,
+ 0x002A0AAA,
+ 0x0F124020,
+ 0x002A0B60,
+ 0x0F124020,
+ 0x002A0C16,
+ 0x0F124020,
+ 0x002A0CCC,
+ 0x0F124020,
+};
+
+static const u32 s5k4ecgx_Scene_Nightshot_v1[] = {
+ 0x002A06AC,
+ 0x0F12FFFF,
+ 0x0F1200FF,
+
+ 0x002A05FC,
+ 0x0F120000,
+ 0x0F120000,
+
+ 0x002A0580,
+ 0x0F12F424,
+ 0x0F120001,
+ 0x0F12F424,
+ 0x0F120001,
+ 0x0F12F424,
+ 0x0F120001,
+ 0x0F12F424,
+ 0x0F120001,
+ 0x0F120100,
+ 0x0F120700,
+ 0x0F120100,
+ 0x0F122000,
+
+ 0x002A03AE,
+ 0x0F121388,
+ 0x0F121388,
+
+ 0x002A02BC,
+ 0x0F1209C4,
+ 0x0F12014D,
+
+ 0x002A0262,
+ 0x0F120000,
+
+ 0x002A0266,
+ 0x0F120001,
+
+ 0x002A024A,
+ 0x0F120001,
+
+ 0x002A0264,
+ 0x0F120001,
+
+ 0x002A026C,
+ 0x0F120001,
+
+ 0x002A023A,
+ 0x0F120001,
+ 0x0F120001,
+
+ 0x002A09EA,
+ 0x0F121580,
+};
+
+static const u32 s5k4ecgx_Scene_Landscape_v1[] = {
+ 0x002A1456,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x0f120101,
+ 0x002A09F4,
+ 0x0F128040,
+ 0x002A0AAA,
+ 0x0F128040,
+ 0x002A0B60,
+ 0x0F128040,
+ 0x002A0C16,
+ 0x0F128040,
+ 0x002A0CCC,
+ 0x0F128040,
+ 0x002A0230,
+ 0x0F120040,
+};
+
+static const u32 s5k4ecgx_Scene_Sports_v1[] = {
+ 0x002A05FC,
+
+ 0x0F120000,
+ 0x0F120000,
+
+ 0x002A0580,
+ 0x0F123520,
+ 0x0F120000,
+ 0x0F123520,
+ 0x0F120000,
+ 0x0F123520,
+ 0x0F120000,
+ 0x0F123520,
+ 0x0F120000,
+ 0x0F120200,
+ 0x0F120200,
+ 0x0F120200,
+ 0x0F120200,
+
+ 0x002A0262,
+ 0x0F120000,
+ 0x002A0266,
+ 0x0F120001,
+ 0x002A024A,
+ 0x0F120001,
+ 0x002A0264,
+ 0x0F120001,
+ 0x002A026C,
+ 0x0F120001,
+ 0x002A023A,
+ 0x0F120001,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Scene_Party_Indoor_v1[] = {
+ 0x002A04E0,
+ 0x0F12065F,
+ 0x002A04D0,
+ 0x0F120000,
+ 0x0F120001,
+
+ 0x002A04CA,
+ 0x0F120001,
+ 0x0F120340,
+ 0x0F120001,
+ 0x002A06B6,
+ 0x0F120100,
+
+
+ 0x002A4780,
+ 0x0F120001,
+
+ 0x002A0230,
+ 0x0F120031,
+};
+
+static const u32 s5k4ecgx_Scene_Beach_Snow_v1[] = {
+ 0x002A04E0,
+ 0x0F12065F,
+ 0x002A04D0,
+ 0x0F120000,
+ 0x0F120001,
+ 0x002A04CA,
+ 0x0F120001,
+ 0x0F1200D0,
+ 0x0F120001,
+ 0x002A06B6,
+ 0x0F120100,
+
+
+ 0x002A4780,
+ 0x0F120001,
+
+ 0x002A0230,
+ 0x0F120031,
+};
+
+static const u32 s5k4ecgx_Scene_Sunset_v1[] = {
+ 0x002a2B7E,
+ 0x0f120000,
+
+ 0x002a04B4,
+ 0x0f1205E0,
+ 0x0f120001,
+ 0x0f120400,
+ 0x0f120001,
+ 0x0f120520,
+ 0x0f120001,
+};
+
+static const u32 s5k4ecgx_Scene_Duskdawn_v1[] = {
+ 0x002a2B7E,
+ 0x0f120000,
+
+ 0x002a04B4,
+ 0x0f120575,
+ 0x0f120001,
+ 0x0f120400,
+ 0x0f120001,
+ 0x0f120835,
+ 0x0f120001,
+};
+
+static const u32 s5k4ecgx_Scene_Fireworks_v1[] = {
+ 0x002A062C,
+ 0x0F120001,
+ 0x0F120000,
+ 0x002A0630,
+ 0x0F121478,
+ 0x0F120000,
+ 0x002A0634,
+ 0x0F121A0A,
+ 0x0F120000,
+ 0x002A0638,
+ 0x0F126810,
+ 0x0F120000,
+ 0x002A063C,
+ 0x0F126810,
+ 0x0F120000,
+ 0x002A0640,
+ 0x0F12D020,
+ 0x0F120000,
+ 0x002A0644,
+ 0x0F120428,
+ 0x0F120001,
+ 0x002A0648,
+ 0x0F121A80,
+ 0x0F120006,
+ 0x002A064C,
+ 0x0F121A80,
+ 0x0F120006,
+ 0x002A0650,
+ 0x0F121A80,
+ 0x0F120006,
+
+ 0x002A03AE,
+ 0x0F122710,
+ 0x0F122710,
+
+ 0x002A0262,
+ 0x0F120000,
+ 0x002A0266,
+ 0x0F120001,
+ 0x002A024A,
+ 0x0F120001,
+ 0x002A0264,
+ 0x0F120001,
+ 0x002A026C,
+ 0x0F120001,
+ 0x002A023A,
+ 0x0F120001,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Scene_Candle_Light_v1[] = {
+ 0x002a04E0,
+ 0x0f120777,
+ 0x002a04B4,
+ 0x0f1205E0,
+ 0x0f120001,
+ 0x0f120400,
+ 0x0f120001,
+ 0x0f120530,
+ 0x0f120001,
+};
+
+static const u32 s5k4ecgx_Night_Capture_v1[] = {
+ 0x002A09EA,
+ 0x0F120AAA,
+ 0x002A0AA0,
+ 0x0F120AAA,
+};
+
+static const u32 s5k4ecgx_AF_Return_Macro_pos_v1[] = {
+ 0x002A15AC,
+ 0x0F120018,
+ 0x0F12002A,
+ 0x0F120030,
+ 0x0F120036,
+ 0x0F12003C,
+ 0x0F120042,
+ 0x0F120048,
+ 0x0F12004E,
+ 0x0F120054,
+ 0x0F12005A,
+ 0x0F120060,
+ 0x0F120066,
+ 0x0F12006C,
+ 0x0F120072,
+ 0x0F120078,
+ 0x0F12007E,
+ 0x0F120084,
+ 0x0F12008A,
+ 0x0F120090,
+ 0x0F120096,
+ 0x0F12009C,
+ 0x0F1200A2,
+ 0x0F1200A8,
+ 0x0F1200AE,
+ 0x0F1200B4,
+ 0x0F1200BA,
+};
+
+static const u32 s5k4ecgx_AF_Normal_mode_1_v1[] = {
+ 0x002A0288,
+ 0x0F12002A,
+};
+
+static const u32 s5k4ecgx_AF_Normal_mode_2_v1[] = {
+ 0x002A0286,
+ 0x0F120004,
+};
+
+
+static const u32 s5k4ecgx_AF_Normal_mode_3_v1[] = {
+ 0x002A160C,
+ 0x0F129002,
+};
+
+static const u32 s5k4ecgx_AF_Macro_mode_1_v1[] = {
+ 0x002A0288,
+ 0x0F1200D0,
+};
+
+static const u32 s5k4ecgx_AF_Macro_mode_2_v1[] = {
+ 0x002A0286,
+ 0x0F120004,
+};
+
+static const u32 s5k4ecgx_AF_Macro_mode_3_v1[] = {
+ 0x002A160C,
+ 0x0F129042,
+ 0x002A159E,
+ 0x0F121800,
+};
+
+static const u32 s5k4ecgx_AF_Low_Light_Mode_On_v1[] = {
+ 0x002A1616,
+ 0x0F120003,
+
+ 0x002A15A4,
+ 0x0F120902,
+
+ 0x002A159E,
+ 0x0F120C00,
+
+ 0x002A15AC,
+ 0x0F12002A,
+ 0x0F120033,
+ 0x0F12003C,
+ 0x0F120045,
+ 0x0F12004E,
+ 0x0F120057,
+ 0x0F120063,
+ 0x0F12006F,
+ 0x0F12007B,
+ 0x0F120087,
+ 0x0F120093,
+ 0x0F1200A2,
+ 0x0F1200B1,
+};
+
+static const u32 s5k4ecgx_AF_Low_Light_Mode_Off_v1[] = {
+ 0x002A1616,
+ 0x0F120003,
+
+ 0x002A15A4,
+ 0x0F120902,
+
+ 0x002A159E,
+ 0x0F121800,
+
+ 0x002A15AC,
+ 0x0F120018,
+ 0x0F12002A,
+ 0x0F120030,
+ 0x0F120036,
+ 0x0F12003C,
+ 0x0F120042,
+ 0x0F120048,
+ 0x0F12004E,
+ 0x0F120054,
+ 0x0F12005A,
+ 0x0F120060,
+ 0x0F120066,
+ 0x0F12006C,
+ 0x0F120072,
+ 0x0F120078,
+ 0x0F12007E,
+ 0x0F120084,
+ 0x0F12008A,
+ 0x0F120090,
+ 0x0F120096,
+ 0x0F12009C,
+ 0x0F1200A2,
+ 0x0F1200A8,
+ 0x0F1200AE,
+ 0x0F1200B4,
+ 0x0F1200BA,
+};
+
+static const u32 s5k4ecgx_Single_AF_Start_v1[] = {
+ 0x002A0286,
+ 0x0F120005,
+};
+
+static const u32 s5k4ecgx_Single_AF_Off_1_v1[] = {
+ 0x002A0288,
+ 0x0F120000,
+};
+
+static const u32 s5k4ecgx_Single_AF_Off_2_v1[] = {
+ 0x002A0286,
+ 0x0F120004,
+};
+
+static const u32 s5k4ecgx_Face_Detection_On_v1[] = {
+ 0x002A028E,
+ 0x0F120100,
+ 0x0F1200E3,
+ 0x0F120200,
+ 0x0F120238,
+ 0x0F1201C6,
+ 0x0F120166,
+ 0x0F120074,
+ 0x0F120132,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Face_Detection_Off_v1[] = {
+ 0x002A028E,
+ 0x0F120100,
+ 0x0F1200E3,
+ 0x0F120200,
+ 0x0F120238,
+ 0x0F1201C6,
+ 0x0F120166,
+ 0x0F120074,
+ 0x0F120132,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Low_Cap_On_v1[] = {
+ 0x002A09EA,
+ 0x0F120D58,
+ 0x002A0AA0,
+ 0x0F120A53,
+};
+
+static const u32 s5k4ecgx_Low_Cap_Off_v1[] = {
+ 0x002A09EA,
+ 0x0F120040,
+ 0x002A0AA0,
+ 0x0F120080,
+};
+
+/* restores crop settings to full resolution */
+static const u32 s5k4ecgx_Reset_Crop_v1[] = {
+ 0x002A024C,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120010,
+ 0x0F12000C,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120010,
+ 0x0F12000C,
+ 0x002A048E,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120000,
+ 0x0F120000,
+
+ 0x002A025E,
+ 0x0F120001,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Capture_Start_v1[] = {
+ 0x002A1A00,
+ 0x0F12185C,
+ 0x0F127000,
+ 0x002A023E,
+ 0x0F120001,
+ 0x002A024A,
+ 0x0F120001,
+ 0x002A0240,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Preview_Return_v1[] = {
+ 0x002A05C4,
+ 0x0F120000,
+ 0x002A1A00,
+ 0x0F12192E,
+ 0x0F127000,
+ 0x002A0952,
+ 0x0F120000,
+ 0x002A023E,
+ 0x0F120000,
+ 0x002A024A,
+ 0x0F120001,
+ 0x002A0240,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Flash_init_v1[] = {
+ 0x002A17DC,
+ 0x0F120001, /* one frame AE */
+
+ 0x002A17AE,
+ 0x0F120270, /* AWB R point */
+
+ 0x002A17B0,
+ 0x0F120210, /* AWB B point */
+
+ 0x002A17E2,
+ 0x0F120001, /* Flash AE tune start*/
+ 0x0F120030, /* 0x100 for Rin output */
+ 0x0F120040,
+ 0x0F120050,
+ 0x0F120060,
+ 0x0F120070,
+ 0x0F120080,
+ 0x0F120090,
+ 0x0F1200A0,
+ 0x0F120050, /* 0x100 for Rout output-20 */
+ 0x0F120014,
+ 0x0F12000A,
+ 0x0F120008,
+ 0x0F120005,
+ 0x0F120004,
+ 0x0F120002,
+ 0x0F120001,
+
+ 0x002A1824,
+ 0x0F120100, /* 0x100 for NB output */
+ 0x0F120100,
+ 0x0F120100,
+ 0x0F120100,
+ 0x0F120100,
+ 0x0F120100,
+ 0x0F120100,
+ 0x0F120100,
+
+ 0x002A17B4,
+ 0x0F120100,
+ 0x0F1200A0,
+ 0x0F120080,
+ 0x0F120020,
+ 0x0F120001,
+
+ 0x002A17C8,
+ 0x0F120025,
+ 0x0F120030,
+ 0x0F120050,
+ 0x0F120070,
+ 0x0F120080,
+};
+
+static const u32 s5k4ecgx_Pre_Flash_Start_v1[] = {
+ 0x002A057C, /* set AE speed to fast */
+ 0x0F120000,
+
+ 0x002A1F06, /* fls_afl_FlashWP_Weight_0_ Pre_Flash_Start */
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Pre_Flash_End_v1[] = {
+ 0x002A057C, /* set AE speed to normal */
+ 0x0F120002,
+
+ 0x002A1F08, /* fls_afl_FlashWP_Weight_0_ Pre_Flash_end */
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Flash_Start_v1[] = {
+ 0x002A17A8,
+ 0x0F120001,
+
+ 0x002A047E,
+ 0x0F120002,
+
+ 0x002A1448,
+ 0x0F120027,
+};
+
+static const u32 s5k4ecgx_Flash_End_v1[] = {
+ 0x002A17A8,
+ 0x0F120000,
+
+ 0x002A047E,
+ 0x0F120000,
+
+ 0x002A1448,
+ 0x0F12003C,
+};
+
+static const u32 s5k4ecgx_5M_Capture_v1[] = { /* 2560 x 1920 */
+ 0x002A0392,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120009,
+
+ 0x002A03AC,
+ 0x0F120002,
+
+ 0x002A03AA,
+ 0x0F120000,
+
+ 0x002A026C,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_3M_Capture_v1[] = { /* 2048 x 1536 */
+ 0x002A0392,
+ 0x0F120800,
+ 0x0F120600,
+ 0x0F120009,
+
+ 0x002A03AC,
+ 0x0F120002,
+
+ 0x002A03AA,
+ 0x0F120000,
+
+ 0x002A024A,
+ 0x0F120001,
+
+ 0x002A026C,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_2M_Capture_v1[] = { /* 1600 x 1200 */
+ 0x002A0392,
+ 0x0F120640,
+ 0x0F1204B0,
+ 0x0F120009,
+
+ 0x002A03AC,
+ 0x0F120002,
+
+ 0x002A03AA,
+ 0x0F120000,
+
+ 0x002A024A,
+ 0x0F120001,
+
+ 0x002A026C,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_1M_Capture_v1[] = { /* 1280 x 960 */
+ 0x002A0392,
+ 0x0F120500,
+ 0x0F1203C0,
+ 0x0F120009,
+
+ 0x002A03AC,
+ 0x0F120002,
+
+ 0x002A03AA,
+ 0x0F120000,
+
+ 0x002A024A,
+ 0x0F120001,
+
+ 0x002A026C,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_VGA_Capture_v1[] = { /* 640 x 480 */
+ 0x002A0392,
+ 0x0F120280,
+ 0x0F1201E0,
+ 0x0F120009,
+
+ 0x002A03AC,
+ 0x0F120002,
+
+ 0x002A03AA,
+ 0x0F120000,
+
+ 0x002A024A,
+ 0x0F120001,
+
+ 0x002A026C,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_720_Preview_v1[] = { /* 720 x 480 */
+ 0x002A02A0,
+ 0x0F1202D0,
+ 0x0F1201E0,
+ 0x0F120005,
+ 0x002A02AE,
+ 0x0F120052,
+ 0x002A02B8,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F12029A,
+ 0x0F12014D,
+ 0x002A02CA,
+ 0x0F120000,
+ 0x0F120000,
+ 0x002A0262,
+ 0x0F120000,
+ 0x002A0266,
+ 0x0F120001,
+ 0x002A024A,
+ 0x0F120001,
+ 0x002A0264,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_640_Preview_v1[] = { /* 640 x 480 */
+ 0x002A02A0,
+ 0x0F120280,
+ 0x0F1201E0,
+ 0x0F120005,
+ 0x002A02AE,
+ 0x0F120052,
+ 0x002A02B8,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F12029A,
+ 0x0F12014D,
+ 0x002A02CA,
+ 0x0F120000,
+ 0x0F120000,
+ 0x002A0262,
+ 0x0F120000,
+ 0x002A0266,
+ 0x0F120001,
+ 0x002A024A,
+ 0x0F120001,
+ 0x002A0264,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_352_Preview_v1[] = { /* 352 x 288 */
+ 0x002A02A0,
+ 0x0F120160,
+ 0x0F120120,
+ 0x0F120005,
+ 0x002A02AE,
+ 0x0F120052,
+ 0x002A02B8,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F12029A,
+ 0x0F12014D,
+ 0x002A02CA,
+ 0x0F120000,
+ 0x0F120000,
+ 0x002A0262,
+ 0x0F120000,
+ 0x002A0266,
+ 0x0F120001,
+ 0x002A024A,
+ 0x0F120001,
+ 0x002A0264,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_176_Preview_v1[] = { /* 176 x 144 */
+ 0x002A02A0,
+ 0x0F1200B0,
+ 0x0F120090,
+ 0x0F120005,
+ 0x002A02AE,
+ 0x0F120052,
+ 0x002A02B8,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F12029A,
+ 0x0F12014D,
+ 0x002A02CA,
+ 0x0F120000,
+ 0x0F120000,
+ 0x002A0262,
+ 0x0F120000,
+ 0x002A0266,
+ 0x0F120001,
+ 0x002A024A,
+ 0x0F120001,
+ 0x002A0264,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_AE_AWB_Lock_On_v1[] = {
+ 0x002A2B76, /* AE Lock On */
+ 0x0F120000,
+ 0x002A2B7E, /* AWB Lock On */
+ 0x0F120000,
+};
+
+static const u32 s5k4ecgx_AE_AWB_Lock_Off_v1[] = {
+ 0x002A2B76, /* AE Lock Off */
+ 0x0F120001,
+ 0x002A2B7E, /* AWB Lock Off */
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Get_AE_Stable_Status_v1[] = {
+ 0x002E2B8C,
+};
+
+static const u32 s5k4ecgx_Get_Light_Level_v1[] = {
+ 0x002C7000,
+ 0x002E2B30,
+};
+
+static const u32 s5k4ecgx_get_1st_af_search_status_v1[] = {
+ 0x002E2E06,
+};
+
+static const u32 s5k4ecgx_get_2nd_af_search_status_v1[] = {
+ 0x002E2167,
+};
+
+static const u32 s5k4ecgx_get_capture_status_v1[] = {
+ 0x002E1F02,
+};
+
+static const u32 s5k4ecgx_get_esd_status_v1[] = {
+ 0xFCFCD000,
+ 0x002CD000,
+ 0x002E0060,
+};
+
+static const u32 s5k4ecgx_get_iso_reg_v1[] = {
+ 0x002C7000,
+ 0x002E2ADC,
+};
+
+static const u32 s5k4ecgx_get_shutterspeed_reg_v1[] = {
+ 0x002C7000,
+ 0x002E2AD8,
+};
+
+#endif /* __S5K4ECGX_REGS_1_0_H__ */
diff --git a/drivers/media/video/s5k4ecgx_regs_1_1.h b/drivers/media/video/s5k4ecgx_regs_1_1.h
new file mode 100755
index 0000000..4001d36
--- /dev/null
+++ b/drivers/media/video/s5k4ecgx_regs_1_1.h
@@ -0,0 +1,4783 @@
+/* drivers/media/video/s5k4ecgx_regs_1_1.h
+ *
+ * Driver for s5k4ecgx (5MP Camera) from SEC(LSI), firmware EVT1.1
+ *
+ * Copyright (C) 2010, SAMSUNG ELECTRONICS
+ *
+ * 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.
+ */
+
+
+#ifndef __S5K4ECGX_REGS_1_1_H__
+#define __S5K4ECGX_REGS_1_1_H__
+
+/* ARM Initiation */
+static const u32 s5k4ecgx_init_reg1[] = {
+ 0xFCFCD000,
+ 0x00100001,
+ 0x10300000,
+ 0x00140001,
+};
+
+static const u32 s5k4ecgx_init_reg2[] = {
+ /* Drive current setting */
+ 0x0028D000,
+ 0x002A1082,
+ 0x0F120155, /*d0_d4_cd10, d0_d4_cd10 9:0*/
+ 0x0F120155, /*d5_d9_cd10, d5_d9_cd10 9:0*/
+ 0x0F120055, /*gpio_cd10, gpio_cd10*/
+ 0x0F120555, /*clks_output_cd10, clks_output_cd10 11:0*/
+ 0x002A100E,
+ 0x0F120000, /*pclk_delay_r*/
+
+ 0x002A007A,
+ 0x0F120000,
+
+ /* ISP FE(ADLC) */
+ 0x002AE406,
+ 0x0F120092,
+ 0x002AE410,
+ 0x0F123804,
+ 0x002AE41A,
+ 0x0F120010, /*101022 ADD adlcptune_total */
+ 0x002AE420,
+ 0x0F120003,
+ 0x0F120060,
+ 0x002AE42E,
+ 0x0F120004,
+ 0x002AF400,
+ 0x0F125A3C,
+ 0x0F120023,
+ 0x0F128080,
+ 0x0F1203AF,
+ 0x0F12000A,
+ 0x0F12AA54,
+ 0x0F120040,
+ 0x0F12464E,
+ 0x0F120240,
+ 0x0F120240,
+ 0x0F120040,
+ 0x0F121000,
+ 0x0F12555C,
+ 0x0F12D000,
+ 0x0F120010,
+ 0x0F120202,
+ 0x0F120401,
+ 0x0F120022,
+ 0x0F120088,
+ 0x0F12009F,
+ 0x0F120000,
+ 0x0F121800,
+ 0x0F120088,
+ 0x0F120000,
+ 0x0F122428,
+ 0x0F120000,
+ 0x0F1203EE,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x002AF552,
+ 0x0F120708,
+ 0x0F12080C,
+
+ /* For subsampling Size */
+ 0x00287000,
+ 0x002A18BC,
+ 0x0F120004,
+ 0x0F1205B6,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F1205BA,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120007,
+ 0x0F1205BA,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1201F4,
+ 0x0F12024E,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1201F4,
+ 0x0F1205B6,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1201F4,
+ 0x0F1205BA,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1201F4,
+ 0x0F12024F,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120075,
+ 0x0F1200CF,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120075,
+ 0x0F1200D6,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120004,
+ 0x0F1201F4,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1200F0,
+ 0x0F1201F4,
+ 0x0F12029E,
+ 0x0F1205B2,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1201F8,
+ 0x0F120228,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120208,
+ 0x0F120238,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120218,
+ 0x0F120238,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F120009,
+ 0x0F1200DE,
+ 0x0F1205C0,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1200DF,
+ 0x0F1200E4,
+ 0x0F1201F8,
+ 0x0F1201FD,
+ 0x0F1205B6,
+ 0x0F1205BB,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1201F8,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120077,
+ 0x0F12007E,
+ 0x0F12024F,
+ 0x0F12025E,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+
+ /* For Capture */
+ 0x0F120004,
+ 0x0F1209D1,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F1209D5,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120008,
+ 0x0F1209D5,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1202AA,
+ 0x0F120326,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1202AA,
+ 0x0F1209D1,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1202AA,
+ 0x0F1209D5,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1202AA,
+ 0x0F120327,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120008,
+ 0x0F120084,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120008,
+ 0x0F12008D,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120008,
+ 0x0F1202AA,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1200AA,
+ 0x0F1202AA,
+ 0x0F1203AD,
+ 0x0F1209CD,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1202AE,
+ 0x0F1202DE,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1202BE,
+ 0x0F1202EE,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1202CE,
+ 0x0F1202EE,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F120009,
+ 0x0F120095,
+ 0x0F1209DB,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120096,
+ 0x0F12009B,
+ 0x0F1202AE,
+ 0x0F1202B3,
+ 0x0F1209D1,
+ 0x0F1209D6,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1202AE,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120009,
+ 0x0F120010,
+ 0x0F120327,
+ 0x0F120336,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+
+ 0x002A1AF8,
+ 0x0F125A3C, /*#senHal_TuneStr_AngTuneData1_2_D000F400
+ register at subsampling*/
+
+ 0x002A1896,
+ 0x0F120002, /*#senHal_SamplingType 0002 03EE: PLA setting*/
+ 0x0F120000, /*#senHal_SamplingMode 0 : 2 PLA / 1 : 4PLA*/
+ 0x0F120003, /*#senHal_PLAOption
+ [0] VPLA enable , [1] HPLA enable*/
+
+ 0x002A189E,
+ 0x0F120FB0, /*#senHal_ExpMinPixels*/
+
+ 0x002A18AC,
+ 0x0F120060, /*#senHal_uAddColsBin*/
+ 0x0F120060, /*#senHal_uAddColsNoBin*/
+ 0x0F1205C0, /*#senHal_uMinColsBin*/
+ 0x0F1205C0, /*#senHal_uMinColsNoBin*/
+
+ 0x002A1AEA,
+ 0x0F128080, /*#senHal_SubF404Tune*/
+ 0x0F120080, /*#senHal_FullF404Tune*/
+ 0x002A1AE0,
+ 0x0F120000, /*#senHal_bSenAAC*/
+
+ 0x002A1A72,
+ 0x0F120000, /*#senHal_bSRX SRX off*/
+ 0x002A18A2,
+ 0x0F120004, /*#senHal_NExpLinesCheckFine,
+ extend Forbidden area line*/
+ 0x002A1A6A,
+ 0x0F12009A, /*#senHal_usForbiddenRightOfs,
+ extend right Forbidden area line*/
+ 0x002A385E,
+ 0x0F12024C, /*#Mon_Sen_uExpPixelsOfs*/
+
+ 0x002A0EE6,
+ 0x0F120000, /*#setot_bUseDigitalHbin*/
+ 0x002A1B2A,
+ 0x0F120300, /*#senHal_TuneStr2_usAngTuneGainTh 2 70001B2A*/
+ 0x0F1200D6, /*#senHal_TuneStr2_AngTuneF4CA_0_ 2 70001B2C*/
+ 0x0F12008D, /*#senHal_TuneStr2_AngTuneF4CA_1_ 2 70001B2E*/
+ 0x0F1200CF, /*#senHal_TuneStr2_AngTuneF4C2_0_ 2 70001B30*/
+ 0x0F120084, /*#senHal_TuneStr2_AngTuneF4C2_1_ 2 70001B32*/
+
+ /* OTP setting */
+
+ 0x002A0722,
+ 0x0F120100, /*#skl_OTP_usWaitTime,
+ This register should be positioned in
+ front of D0001000*/
+ 0x002A0726,
+ 0x0F120001, /*#skl_bUseOTPfunc, This is OTP on/off function*/
+ 0x002A08D6,
+ 0x0F120001, /*#ash_bUseOTPData*/
+ 0x002A146E,
+ 0x0F120000, /*#awbb_otp_disable*/
+ 0x002A08DC,
+ 0x0F120001, /*#ash_bUseGasAlphaOTP*/
+
+ /* TnP setting */
+ /* Start of Patch data */
+ 0x002A3AF8, /* TnP */
+ 0x0F12B570, /* 70003AF8 */
+ 0x0F124B36, /* 70003AFA */
+ 0x0F12216F, /* 70003AFC */
+ 0x0F124836, /* 70003AFE */
+ 0x0F128C80, /* 70003B00 */
+ 0x0F122200, /* 70003B02 */
+ 0x0F12C008, /* 70003B04 */
+ 0x0F126001, /* 70003B06 */
+ 0x0F124934, /* 70003B08 */
+ 0x0F124835, /* 70003B0A */
+ 0x0F122501, /* 70003B0C */
+ 0x0F12F000, /* 70003B0E */
+ 0x0F12FB77, /* 70003B10 */
+ 0x0F124934, /* 70003B12 */
+ 0x0F124834, /* 70003B14 */
+ 0x0F122402, /* 70003B16 */
+ 0x0F12002A, /* 70003B18 */
+ 0x0F12F000, /* 70003B1A */
+ 0x0F12FB71, /* 70003B1C */
+ 0x0F124833, /* 70003B1E */
+ 0x0F120221, /* 70003B20 */
+ 0x0F128001, /* 70003B22 */
+ 0x0F122100, /* 70003B24 */
+ 0x0F128041, /* 70003B26 */
+ 0x0F124931, /* 70003B28 */
+ 0x0F124832, /* 70003B2A */
+ 0x0F126041, /* 70003B2C */
+ 0x0F124932, /* 70003B2E */
+ 0x0F124832, /* 70003B30 */
+ 0x0F120022, /* 70003B32 */
+ 0x0F122503, /* 70003B34 */
+ 0x0F12F000, /* 70003B36 */
+ 0x0F12FB63, /* 70003B38 */
+ 0x0F12482E, /* 70003B3A */
+ 0x0F124930, /* 70003B3C */
+ 0x0F1230C0, /* 70003B3E */
+ 0x0F1263C1, /* 70003B40 */
+ 0x0F12492C, /* 70003B42 */
+ 0x0F12482F, /* 70003B44 */
+ 0x0F123980, /* 70003B46 */
+ 0x0F126408, /* 70003B48 */
+ 0x0F12482F, /* 70003B4A */
+ 0x0F12492F, /* 70003B4C */
+ 0x0F126388, /* 70003B4E */
+ 0x0F12492F, /* 70003B50 */
+ 0x0F124830, /* 70003B52 */
+ 0x0F122404, /* 70003B54 */
+ 0x0F12002A, /* 70003B56 */
+ 0x0F12F000, /* 70003B58 */
+ 0x0F12FB52, /* 70003B5A */
+ 0x0F12492E, /* 70003B5C */
+ 0x0F12482F, /* 70003B5E */
+ 0x0F120022, /* 70003B60 */
+ 0x0F122505, /* 70003B62 */
+ 0x0F12F000, /* 70003B64 */
+ 0x0F12F876, /* 70003B66 */
+ 0x0F12482C, /* 70003B68 */
+ 0x0F12492D, /* 70003B6A */
+ 0x0F122406, /* 70003B6C */
+ 0x0F12002A, /* 70003B6E */
+ 0x0F121D80, /* 70003B70 */
+ 0x0F12F000, /* 70003B72 */
+ 0x0F12F86F, /* 70003B74 */
+ 0x0F124829, /* 70003B76 */
+ 0x0F12492A, /* 70003B78 */
+ 0x0F120022, /* 70003B7A */
+ 0x0F122507, /* 70003B7C */
+ 0x0F12300C, /* 70003B7E */
+ 0x0F12F000, /* 70003B80 */
+ 0x0F12F868, /* 70003B82 */
+ 0x0F124825, /* 70003B84 */
+ 0x0F124928, /* 70003B86 */
+ 0x0F122408, /* 70003B88 */
+ 0x0F12002A, /* 70003B8A */
+ 0x0F123010, /* 70003B8C */
+ 0x0F12F000, /* 70003B8E */
+ 0x0F12F861, /* 70003B90 */
+ 0x0F124926, /* 70003B92 */
+ 0x0F124826, /* 70003B94 */
+ 0x0F120022, /* 70003B96 */
+ 0x0F122509, /* 70003B98 */
+ 0x0F12F000, /* 70003B9A */
+ 0x0F12FB31, /* 70003B9C */
+ 0x0F124925, /* 70003B9E */
+ 0x0F124825, /* 70003BA0 */
+ 0x0F12240A, /* 70003BA2 */
+ 0x0F12002A, /* 70003BA4 */
+ 0x0F12F000, /* 70003BA6 */
+ 0x0F12FB2B, /* 70003BA8 */
+ 0x0F124924, /* 70003BAA */
+ 0x0F124824, /* 70003BAC */
+ 0x0F12250B, /* 70003BAE */
+ 0x0F120022, /* 70003BB0 */
+ 0x0F12F000, /* 70003BB2 */
+ 0x0F12FB25, /* 70003BB4 */
+ 0x0F124923, /* 70003BB6 */
+ 0x0F124823, /* 70003BB8 */
+ 0x0F12002A, /* 70003BBA */
+ 0x0F12240C, /* 70003BBC */
+ 0x0F12F000, /* 70003BBE */
+ 0x0F12FB1F, /* 70003BC0 */
+ 0x0F124922, /* 70003BC2 */
+ 0x0F124822, /* 70003BC4 */
+ 0x0F120022, /* 70003BC6 */
+ 0x0F12F000, /* 70003BC8 */
+ 0x0F12FB1A, /* 70003BCA */
+ 0x0F12BC70, /* 70003BCC */
+ 0x0F12BC08, /* 70003BCE */
+ 0x0F124718, /* 70003BD0 */
+ 0x0F120000, /* 70003BD2 */
+ 0x0F120185, /* 70003BD4 */
+ 0x0F124EC2, /* 70003BD6 */
+ 0x0F121F6C, /* 70003BD8 */
+ 0x0F127000, /* 70003BDA */
+ 0x0F123C6D, /* 70003BDC */
+ 0x0F127000, /* 70003BDE */
+ 0x0F12E38B, /* 70003BE0 */
+ 0x0F120000, /* 70003BE2 */
+ 0x0F123CA5, /* 70003BE4 */
+ 0x0F127000, /* 70003BE6 */
+ 0x0F12C3B1, /* 70003BE8 */
+ 0x0F120000, /* 70003BEA */
+ 0x0F124780, /* 70003BEC */
+ 0x0F127000, /* 70003BEE */
+ 0x0F123D03, /* 70003BF0 */
+ 0x0F127000, /* 70003BF2 */
+ 0x0F120080, /* 70003BF4 */
+ 0x0F127000, /* 70003BF6 */
+ 0x0F123D3F, /* 70003BF8 */
+ 0x0F127000, /* 70003BFA */
+ 0x0F12B49D, /* 70003BFC */
+ 0x0F120000, /* 70003BFE */
+ 0x0F123DEB, /* 70003C00 */
+ 0x0F127000, /* 70003C02 */
+ 0x0F123D9F, /* 70003C04 */
+ 0x0F127000, /* 70003C06 */
+ 0x0F12FFFF, /* 70003C08 */
+ 0x0F1200FF, /* 70003C0A */
+ 0x0F1217E0, /* 70003C0C */
+ 0x0F127000, /* 70003C0E */
+ 0x0F123F67, /* 70003C10 */
+ 0x0F127000, /* 70003C12 */
+ 0x0F12053D, /* 70003C14 */
+ 0x0F120000, /* 70003C16 */
+ 0x0F120000, /* 70003C18 */
+ 0x0F120A89, /* 70003C1A */
+ 0x0F126CD2, /* 70003C1C */
+ 0x0F120000, /* 70003C1E */
+ 0x0F1202C9, /* 70003C20 */
+ 0x0F120000, /* 70003C22 */
+ 0x0F120000, /* 70003C24 */
+ 0x0F120A9A, /* 70003C26 */
+ 0x0F120000, /* 70003C28 */
+ 0x0F1202D2, /* 70003C2A */
+ 0x0F123FB5, /* 70003C2C */
+ 0x0F127000, /* 70003C2E */
+ 0x0F129E65, /* 70003C30 */
+ 0x0F120000, /* 70003C32 */
+ 0x0F124029, /* 70003C34 */
+ 0x0F127000, /* 70003C36 */
+ 0x0F127C49, /* 70003C38 */
+ 0x0F120000, /* 70003C3A */
+ 0x0F12409D, /* 70003C3C */
+ 0x0F127000, /* 70003C3E */
+ 0x0F127C63, /* 70003C40 */
+ 0x0F120000, /* 70003C42 */
+ 0x0F1240B9, /* 70003C44 */
+ 0x0F127000, /* 70003C46 */
+ 0x0F128F01, /* 70003C48 */
+ 0x0F120000, /* 70003C4A */
+ 0x0F12415B, /* 70003C4C */
+ 0x0F127000, /* 70003C4E */
+ 0x0F127F3F, /* 70003C50 */
+ 0x0F120000, /* 70003C52 */
+ 0x0F12B570, /* 70003C54 */
+ 0x0F12000C, /* 70003C56 */
+ 0x0F120015, /* 70003C58 */
+ 0x0F120029, /* 70003C5A */
+ 0x0F12F000, /* 70003C5C */
+ 0x0F12FAD8, /* 70003C5E */
+ 0x0F1249F8, /* 70003C60 */
+ 0x0F1200A8, /* 70003C62 */
+ 0x0F12500C, /* 70003C64 */
+ 0x0F12BC70, /* 70003C66 */
+ 0x0F12BC08, /* 70003C68 */
+ 0x0F124718, /* 70003C6A */
+ 0x0F126808, /* 70003C6C */
+ 0x0F120400, /* 70003C6E */
+ 0x0F120C00, /* 70003C70 */
+ 0x0F126849, /* 70003C72 */
+ 0x0F120409, /* 70003C74 */
+ 0x0F120C09, /* 70003C76 */
+ 0x0F124AF3, /* 70003C78 */
+ 0x0F128992, /* 70003C7A */
+ 0x0F122A00, /* 70003C7C */
+ 0x0F12D00D, /* 70003C7E */
+ 0x0F122300, /* 70003C80 */
+ 0x0F121A89, /* 70003C82 */
+ 0x0F12D400, /* 70003C84 */
+ 0x0F12000B, /* 70003C86 */
+ 0x0F120419, /* 70003C88 */
+ 0x0F120C09, /* 70003C8A */
+ 0x0F1223FF, /* 70003C8C */
+ 0x0F1233C1, /* 70003C8E */
+ 0x0F121810, /* 70003C90 */
+ 0x0F124298, /* 70003C92 */
+ 0x0F12D800, /* 70003C94 */
+ 0x0F120003, /* 70003C96 */
+ 0x0F120418, /* 70003C98 */
+ 0x0F120C00, /* 70003C9A */
+ 0x0F124AEB, /* 70003C9C */
+ 0x0F128150, /* 70003C9E */
+ 0x0F128191, /* 70003CA0 */
+ 0x0F124770, /* 70003CA2 */
+ 0x0F12B5F3, /* 70003CA4 */
+ 0x0F120004, /* 70003CA6 */
+ 0x0F12B081, /* 70003CA8 */
+ 0x0F129802, /* 70003CAA */
+ 0x0F126800, /* 70003CAC */
+ 0x0F120600, /* 70003CAE */
+ 0x0F120E00, /* 70003CB0 */
+ 0x0F122201, /* 70003CB2 */
+ 0x0F120015, /* 70003CB4 */
+ 0x0F120021, /* 70003CB6 */
+ 0x0F123910, /* 70003CB8 */
+ 0x0F12408A, /* 70003CBA */
+ 0x0F1240A5, /* 70003CBC */
+ 0x0F124FE4, /* 70003CBE */
+ 0x0F120016, /* 70003CC0 */
+ 0x0F122C10, /* 70003CC2 */
+ 0x0F12DA03, /* 70003CC4 */
+ 0x0F128839, /* 70003CC6 */
+ 0x0F1243A9, /* 70003CC8 */
+ 0x0F128039, /* 70003CCA */
+ 0x0F12E002, /* 70003CCC */
+ 0x0F128879, /* 70003CCE */
+ 0x0F1243B1, /* 70003CD0 */
+ 0x0F128079, /* 70003CD2 */
+ 0x0F12F000, /* 70003CD4 */
+ 0x0F12FAA4, /* 70003CD6 */
+ 0x0F122C10, /* 70003CD8 */
+ 0x0F12DA03, /* 70003CDA */
+ 0x0F128839, /* 70003CDC */
+ 0x0F124329, /* 70003CDE */
+ 0x0F128039, /* 70003CE0 */
+ 0x0F12E002, /* 70003CE2 */
+ 0x0F128879, /* 70003CE4 */
+ 0x0F124331, /* 70003CE6 */
+ 0x0F128079, /* 70003CE8 */
+ 0x0F1249DA, /* 70003CEA */
+ 0x0F128809, /* 70003CEC */
+ 0x0F122900, /* 70003CEE */
+ 0x0F12D102, /* 70003CF0 */
+ 0x0F12F000, /* 70003CF2 */
+ 0x0F12FA9D, /* 70003CF4 */
+ 0x0F122000, /* 70003CF6 */
+ 0x0F129902, /* 70003CF8 */
+ 0x0F126008, /* 70003CFA */
+ 0x0F12BCFE, /* 70003CFC */
+ 0x0F12BC08, /* 70003CFE */
+ 0x0F124718, /* 70003D00 */
+ 0x0F12B538, /* 70003D02 */
+ 0x0F129C04, /* 70003D04 */
+ 0x0F120015, /* 70003D06 */
+ 0x0F12002A, /* 70003D08 */
+ 0x0F129400, /* 70003D0A */
+ 0x0F12F000, /* 70003D0C */
+ 0x0F12FA98, /* 70003D0E */
+ 0x0F124AD1, /* 70003D10 */
+ 0x0F128811, /* 70003D12 */
+ 0x0F122900, /* 70003D14 */
+ 0x0F12D00F, /* 70003D16 */
+ 0x0F128820, /* 70003D18 */
+ 0x0F124281, /* 70003D1A */
+ 0x0F12D20C, /* 70003D1C */
+ 0x0F128861, /* 70003D1E */
+ 0x0F128853, /* 70003D20 */
+ 0x0F124299, /* 70003D22 */
+ 0x0F12D200, /* 70003D24 */
+ 0x0F121E40, /* 70003D26 */
+ 0x0F120400, /* 70003D28 */
+ 0x0F120C00, /* 70003D2A */
+ 0x0F128020, /* 70003D2C */
+ 0x0F128851, /* 70003D2E */
+ 0x0F128061, /* 70003D30 */
+ 0x0F124368, /* 70003D32 */
+ 0x0F121840, /* 70003D34 */
+ 0x0F126060, /* 70003D36 */
+ 0x0F12BC38, /* 70003D38 */
+ 0x0F12BC08, /* 70003D3A */
+ 0x0F124718, /* 70003D3C */
+ 0x0F12B5F8, /* 70003D3E */
+ 0x0F120004, /* 70003D40 */
+ 0x0F126808, /* 70003D42 */
+ 0x0F120400, /* 70003D44 */
+ 0x0F120C00, /* 70003D46 */
+ 0x0F122201, /* 70003D48 */
+ 0x0F120015, /* 70003D4A */
+ 0x0F120021, /* 70003D4C */
+ 0x0F123910, /* 70003D4E */
+ 0x0F12408A, /* 70003D50 */
+ 0x0F1240A5, /* 70003D52 */
+ 0x0F124FBE, /* 70003D54 */
+ 0x0F120016, /* 70003D56 */
+ 0x0F122C10, /* 70003D58 */
+ 0x0F12DA03, /* 70003D5A */
+ 0x0F128839, /* 70003D5C */
+ 0x0F1243A9, /* 70003D5E */
+ 0x0F128039, /* 70003D60 */
+ 0x0F12E002, /* 70003D62 */
+ 0x0F128879, /* 70003D64 */
+ 0x0F1243B1, /* 70003D66 */
+ 0x0F128079, /* 70003D68 */
+ 0x0F12F000, /* 70003D6A */
+ 0x0F12FA71, /* 70003D6C */
+ 0x0F122C10, /* 70003D6E */
+ 0x0F12DA03, /* 70003D70 */
+ 0x0F128838, /* 70003D72 */
+ 0x0F124328, /* 70003D74 */
+ 0x0F128038, /* 70003D76 */
+ 0x0F12E002, /* 70003D78 */
+ 0x0F128878, /* 70003D7A */
+ 0x0F124330, /* 70003D7C */
+ 0x0F128078, /* 70003D7E */
+ 0x0F1248B6, /* 70003D80 */
+ 0x0F128800, /* 70003D82 */
+ 0x0F120400, /* 70003D84 */
+ 0x0F12D507, /* 70003D86 */
+ 0x0F124BB5, /* 70003D88 */
+ 0x0F127819, /* 70003D8A */
+ 0x0F124AB5, /* 70003D8C */
+ 0x0F127810, /* 70003D8E */
+ 0x0F127018, /* 70003D90 */
+ 0x0F127011, /* 70003D92 */
+ 0x0F1249B4, /* 70003D94 */
+ 0x0F128188, /* 70003D96 */
+ 0x0F12BCF8, /* 70003D98 */
+ 0x0F12BC08, /* 70003D9A */
+ 0x0F124718, /* 70003D9C */
+ 0x0F12B538, /* 70003D9E */
+ 0x0F1248B2, /* 70003DA0 */
+ 0x0F124669, /* 70003DA2 */
+ 0x0F12F000, /* 70003DA4 */
+ 0x0F12FA5C, /* 70003DA6 */
+ 0x0F1248B1, /* 70003DA8 */
+ 0x0F1249B0, /* 70003DAA */
+ 0x0F1269C2, /* 70003DAC */
+ 0x0F122400, /* 70003DAE */
+ 0x0F1231A8, /* 70003DB0 */
+ 0x0F122A00, /* 70003DB2 */
+ 0x0F12D008, /* 70003DB4 */
+ 0x0F1261C4, /* 70003DB6 */
+ 0x0F12684A, /* 70003DB8 */
+ 0x0F126242, /* 70003DBA */
+ 0x0F126282, /* 70003DBC */
+ 0x0F12466B, /* 70003DBE */
+ 0x0F12881A, /* 70003DC0 */
+ 0x0F126302, /* 70003DC2 */
+ 0x0F12885A, /* 70003DC4 */
+ 0x0F126342, /* 70003DC6 */
+ 0x0F126A02, /* 70003DC8 */
+ 0x0F122A00, /* 70003DCA */
+ 0x0F12D00A, /* 70003DCC */
+ 0x0F126204, /* 70003DCE */
+ 0x0F126849, /* 70003DD0 */
+ 0x0F126281, /* 70003DD2 */
+ 0x0F12466B, /* 70003DD4 */
+ 0x0F128819, /* 70003DD6 */
+ 0x0F126301, /* 70003DD8 */
+ 0x0F128859, /* 70003DDA */
+ 0x0F126341, /* 70003DDC */
+ 0x0F1249A5, /* 70003DDE */
+ 0x0F1288C9, /* 70003DE0 */
+ 0x0F1263C1, /* 70003DE2 */
+ 0x0F12F000, /* 70003DE4 */
+ 0x0F12FA44, /* 70003DE6 */
+ 0x0F12E7A6, /* 70003DE8 */
+ 0x0F12B5F0, /* 70003DEA */
+ 0x0F12B08B, /* 70003DEC */
+ 0x0F1220FF, /* 70003DEE */
+ 0x0F121C40, /* 70003DF0 */
+ 0x0F1249A1, /* 70003DF2 */
+ 0x0F1289CC, /* 70003DF4 */
+ 0x0F124E9E, /* 70003DF6 */
+ 0x0F126AB1, /* 70003DF8 */
+ 0x0F124284, /* 70003DFA */
+ 0x0F12D101, /* 70003DFC */
+ 0x0F12489F, /* 70003DFE */
+ 0x0F126081, /* 70003E00 */
+ 0x0F126A70, /* 70003E02 */
+ 0x0F120200, /* 70003E04 */
+ 0x0F12F000, /* 70003E06 */
+ 0x0F12FA3B, /* 70003E08 */
+ 0x0F120400, /* 70003E0A */
+ 0x0F120C00, /* 70003E0C */
+ 0x0F124A96, /* 70003E0E */
+ 0x0F128A11, /* 70003E10 */
+ 0x0F129109, /* 70003E12 */
+ 0x0F122101, /* 70003E14 */
+ 0x0F120349, /* 70003E16 */
+ 0x0F124288, /* 70003E18 */
+ 0x0F12D200, /* 70003E1A */
+ 0x0F120001, /* 70003E1C */
+ 0x0F124A92, /* 70003E1E */
+ 0x0F128211, /* 70003E20 */
+ 0x0F124D97, /* 70003E22 */
+ 0x0F128829, /* 70003E24 */
+ 0x0F129108, /* 70003E26 */
+ 0x0F124A8B, /* 70003E28 */
+ 0x0F122303, /* 70003E2A */
+ 0x0F123222, /* 70003E2C */
+ 0x0F121F91, /* 70003E2E */
+ 0x0F12F000, /* 70003E30 */
+ 0x0F12FA2C, /* 70003E32 */
+ 0x0F128028, /* 70003E34 */
+ 0x0F12488E, /* 70003E36 */
+ 0x0F124987, /* 70003E38 */
+ 0x0F126BC2, /* 70003E3A */
+ 0x0F126AC0, /* 70003E3C */
+ 0x0F124282, /* 70003E3E */
+ 0x0F12D201, /* 70003E40 */
+ 0x0F128CC8, /* 70003E42 */
+ 0x0F128028, /* 70003E44 */
+ 0x0F1288E8, /* 70003E46 */
+ 0x0F129007, /* 70003E48 */
+ 0x0F122240, /* 70003E4A */
+ 0x0F124310, /* 70003E4C */
+ 0x0F1280E8, /* 70003E4E */
+ 0x0F122000, /* 70003E50 */
+ 0x0F120041, /* 70003E52 */
+ 0x0F12194B, /* 70003E54 */
+ 0x0F12001E, /* 70003E56 */
+ 0x0F123680, /* 70003E58 */
+ 0x0F128BB2, /* 70003E5A */
+ 0x0F12AF04, /* 70003E5C */
+ 0x0F12527A, /* 70003E5E */
+ 0x0F124A7D, /* 70003E60 */
+ 0x0F12188A, /* 70003E62 */
+ 0x0F128897, /* 70003E64 */
+ 0x0F1283B7, /* 70003E66 */
+ 0x0F1233A0, /* 70003E68 */
+ 0x0F12891F, /* 70003E6A */
+ 0x0F12AE01, /* 70003E6C */
+ 0x0F125277, /* 70003E6E */
+ 0x0F128A11, /* 70003E70 */
+ 0x0F128119, /* 70003E72 */
+ 0x0F121C40, /* 70003E74 */
+ 0x0F120400, /* 70003E76 */
+ 0x0F120C00, /* 70003E78 */
+ 0x0F122806, /* 70003E7A */
+ 0x0F12D3E9, /* 70003E7C */
+ 0x0F12F000, /* 70003E7E */
+ 0x0F12FA0D, /* 70003E80 */
+ 0x0F12F000, /* 70003E82 */
+ 0x0F12FA13, /* 70003E84 */
+ 0x0F124F79, /* 70003E86 */
+ 0x0F1237A8, /* 70003E88 */
+ 0x0F122800, /* 70003E8A */
+ 0x0F12D10A, /* 70003E8C */
+ 0x0F121FE0, /* 70003E8E */
+ 0x0F1238FD, /* 70003E90 */
+ 0x0F12D001, /* 70003E92 */
+ 0x0F121CC0, /* 70003E94 */
+ 0x0F12D105, /* 70003E96 */
+ 0x0F124874, /* 70003E98 */
+ 0x0F128829, /* 70003E9A */
+ 0x0F123818, /* 70003E9C */
+ 0x0F126840, /* 70003E9E */
+ 0x0F124348, /* 70003EA0 */
+ 0x0F126078, /* 70003EA2 */
+ 0x0F124972, /* 70003EA4 */
+ 0x0F126878, /* 70003EA6 */
+ 0x0F126B89, /* 70003EA8 */
+ 0x0F124288, /* 70003EAA */
+ 0x0F12D300, /* 70003EAC */
+ 0x0F120008, /* 70003EAE */
+ 0x0F126078, /* 70003EB0 */
+ 0x0F122000, /* 70003EB2 */
+ 0x0F120041, /* 70003EB4 */
+ 0x0F12AA04, /* 70003EB6 */
+ 0x0F125A53, /* 70003EB8 */
+ 0x0F12194A, /* 70003EBA */
+ 0x0F12269C, /* 70003EBC */
+ 0x0F1252B3, /* 70003EBE */
+ 0x0F12AB01, /* 70003EC0 */
+ 0x0F125A59, /* 70003EC2 */
+ 0x0F1232A0, /* 70003EC4 */
+ 0x0F128111, /* 70003EC6 */
+ 0x0F121C40, /* 70003EC8 */
+ 0x0F120400, /* 70003ECA */
+ 0x0F120C00, /* 70003ECC */
+ 0x0F122806, /* 70003ECE */
+ 0x0F12D3F0, /* 70003ED0 */
+ 0x0F124965, /* 70003ED2 */
+ 0x0F129809, /* 70003ED4 */
+ 0x0F128208, /* 70003ED6 */
+ 0x0F129808, /* 70003ED8 */
+ 0x0F128028, /* 70003EDA */
+ 0x0F129807, /* 70003EDC */
+ 0x0F1280E8, /* 70003EDE */
+ 0x0F121FE0, /* 70003EE0 */
+ 0x0F1238FD, /* 70003EE2 */
+ 0x0F12D13B, /* 70003EE4 */
+ 0x0F124D64, /* 70003EE6 */
+ 0x0F1289E8, /* 70003EE8 */
+ 0x0F121FC1, /* 70003EEA */
+ 0x0F1239FF, /* 70003EEC */
+ 0x0F12D136, /* 70003EEE */
+ 0x0F124C5F, /* 70003EF0 */
+ 0x0F128AE0, /* 70003EF2 */
+ 0x0F12F000, /* 70003EF4 */
+ 0x0F12F9E2, /* 70003EF6 */
+ 0x0F120006, /* 70003EF8 */
+ 0x0F128B20, /* 70003EFA */
+ 0x0F12F000, /* 70003EFC */
+ 0x0F12F9E6, /* 70003EFE */
+ 0x0F129000, /* 70003F00 */
+ 0x0F126AA1, /* 70003F02 */
+ 0x0F126878, /* 70003F04 */
+ 0x0F121809, /* 70003F06 */
+ 0x0F120200, /* 70003F08 */
+ 0x0F12F000, /* 70003F0A */
+ 0x0F12F9B9, /* 70003F0C */
+ 0x0F120400, /* 70003F0E */
+ 0x0F120C00, /* 70003F10 */
+ 0x0F120022, /* 70003F12 */
+ 0x0F123246, /* 70003F14 */
+ 0x0F120011, /* 70003F16 */
+ 0x0F12310A, /* 70003F18 */
+ 0x0F122305, /* 70003F1A */
+ 0x0F12F000, /* 70003F1C */
+ 0x0F12F9B6, /* 70003F1E */
+ 0x0F1266E8, /* 70003F20 */
+ 0x0F126B23, /* 70003F22 */
+ 0x0F120002, /* 70003F24 */
+ 0x0F120031, /* 70003F26 */
+ 0x0F120018, /* 70003F28 */
+ 0x0F12F000, /* 70003F2A */
+ 0x0F12F9D7, /* 70003F2C */
+ 0x0F12466B, /* 70003F2E */
+ 0x0F128518, /* 70003F30 */
+ 0x0F126EEA, /* 70003F32 */
+ 0x0F126B60, /* 70003F34 */
+ 0x0F129900, /* 70003F36 */
+ 0x0F12F000, /* 70003F38 */
+ 0x0F12F9D0, /* 70003F3A */
+ 0x0F12466B, /* 70003F3C */
+ 0x0F128558, /* 70003F3E */
+ 0x0F120029, /* 70003F40 */
+ 0x0F12980A, /* 70003F42 */
+ 0x0F123170, /* 70003F44 */
+ 0x0F12F000, /* 70003F46 */
+ 0x0F12F9D1, /* 70003F48 */
+ 0x0F120028, /* 70003F4A */
+ 0x0F123060, /* 70003F4C */
+ 0x0F128A02, /* 70003F4E */
+ 0x0F124946, /* 70003F50 */
+ 0x0F123128, /* 70003F52 */
+ 0x0F12808A, /* 70003F54 */
+ 0x0F128A42, /* 70003F56 */
+ 0x0F1280CA, /* 70003F58 */
+ 0x0F128A80, /* 70003F5A */
+ 0x0F128108, /* 70003F5C */
+ 0x0F12B00B, /* 70003F5E */
+ 0x0F12BCF0, /* 70003F60 */
+ 0x0F12BC08, /* 70003F62 */
+ 0x0F124718, /* 70003F64 */
+ 0x0F12B570, /* 70003F66 */
+ 0x0F122400, /* 70003F68 */
+ 0x0F124D46, /* 70003F6A */
+ 0x0F124846, /* 70003F6C */
+ 0x0F128881, /* 70003F6E */
+ 0x0F124846, /* 70003F70 */
+ 0x0F128041, /* 70003F72 */
+ 0x0F122101, /* 70003F74 */
+ 0x0F128001, /* 70003F76 */
+ 0x0F12F000, /* 70003F78 */
+ 0x0F12F9C0, /* 70003F7A */
+ 0x0F124842, /* 70003F7C */
+ 0x0F123820, /* 70003F7E */
+ 0x0F128BC0, /* 70003F80 */
+ 0x0F12F000, /* 70003F82 */
+ 0x0F12F9C3, /* 70003F84 */
+ 0x0F124B42, /* 70003F86 */
+ 0x0F12220D, /* 70003F88 */
+ 0x0F120712, /* 70003F8A */
+ 0x0F1218A8, /* 70003F8C */
+ 0x0F128806, /* 70003F8E */
+ 0x0F1200E1, /* 70003F90 */
+ 0x0F1218C9, /* 70003F92 */
+ 0x0F1281CE, /* 70003F94 */
+ 0x0F128846, /* 70003F96 */
+ 0x0F12818E, /* 70003F98 */
+ 0x0F128886, /* 70003F9A */
+ 0x0F12824E, /* 70003F9C */
+ 0x0F1288C0, /* 70003F9E */
+ 0x0F128208, /* 70003FA0 */
+ 0x0F123508, /* 70003FA2 */
+ 0x0F12042D, /* 70003FA4 */
+ 0x0F120C2D, /* 70003FA6 */
+ 0x0F121C64, /* 70003FA8 */
+ 0x0F120424, /* 70003FAA */
+ 0x0F120C24, /* 70003FAC */
+ 0x0F122C07, /* 70003FAE */
+ 0x0F12D3EC, /* 70003FB0 */
+ 0x0F12E658, /* 70003FB2 */
+ 0x0F12B510, /* 70003FB4 */
+ 0x0F124834, /* 70003FB6 */
+ 0x0F124C34, /* 70003FB8 */
+ 0x0F1288C0, /* 70003FBA */
+ 0x0F128060, /* 70003FBC */
+ 0x0F122001, /* 70003FBE */
+ 0x0F128020, /* 70003FC0 */
+ 0x0F124831, /* 70003FC2 */
+ 0x0F123820, /* 70003FC4 */
+ 0x0F128BC0, /* 70003FC6 */
+ 0x0F12F000, /* 70003FC8 */
+ 0x0F12F9A0, /* 70003FCA */
+ 0x0F1288E0, /* 70003FCC */
+ 0x0F124A31, /* 70003FCE */
+ 0x0F122800, /* 70003FD0 */
+ 0x0F12D003, /* 70003FD2 */
+ 0x0F124930, /* 70003FD4 */
+ 0x0F128849, /* 70003FD6 */
+ 0x0F122900, /* 70003FD8 */
+ 0x0F12D009, /* 70003FDA */
+ 0x0F122001, /* 70003FDC */
+ 0x0F1203C0, /* 70003FDE */
+ 0x0F128050, /* 70003FE0 */
+ 0x0F1280D0, /* 70003FE2 */
+ 0x0F122000, /* 70003FE4 */
+ 0x0F128090, /* 70003FE6 */
+ 0x0F128110, /* 70003FE8 */
+ 0x0F12BC10, /* 70003FEA */
+ 0x0F12BC08, /* 70003FEC */
+ 0x0F124718, /* 70003FEE */
+ 0x0F128050, /* 70003FF0 */
+ 0x0F128920, /* 70003FF2 */
+ 0x0F1280D0, /* 70003FF4 */
+ 0x0F128960, /* 70003FF6 */
+ 0x0F120400, /* 70003FF8 */
+ 0x0F121400, /* 70003FFA */
+ 0x0F128090, /* 70003FFC */
+ 0x0F1289A1, /* 70003FFE */
+ 0x0F120409, /* 70004000 */
+ 0x0F121409, /* 70004002 */
+ 0x0F128111, /* 70004004 */
+ 0x0F1289E3, /* 70004006 */
+ 0x0F128A24, /* 70004008 */
+ 0x0F122B00, /* 7000400A */
+ 0x0F12D104, /* 7000400C */
+ 0x0F1217C3, /* 7000400E */
+ 0x0F120F5B, /* 70004010 */
+ 0x0F121818, /* 70004012 */
+ 0x0F1210C0, /* 70004014 */
+ 0x0F128090, /* 70004016 */
+ 0x0F122C00, /* 70004018 */
+ 0x0F12D1E6, /* 7000401A */
+ 0x0F1217C8, /* 7000401C */
+ 0x0F120F40, /* 7000401E */
+ 0x0F121840, /* 70004020 */
+ 0x0F1210C0, /* 70004022 */
+ 0x0F128110, /* 70004024 */
+ 0x0F12E7E0, /* 70004026 */
+ 0x0F12B510, /* 70004028 */
+ 0x0F12000C, /* 7000402A */
+ 0x0F124919, /* 7000402C */
+ 0x0F122204, /* 7000402E */
+ 0x0F126820, /* 70004030 */
+ 0x0F125E8A, /* 70004032 */
+ 0x0F120140, /* 70004034 */
+ 0x0F121A80, /* 70004036 */
+ 0x0F120280, /* 70004038 */
+ 0x0F128849, /* 7000403A */
+ 0x0F12F000, /* 7000403C */
+ 0x0F12F96E, /* 7000403E */
+ 0x0F126020, /* 70004040 */
+ 0x0F12E7D2, /* 70004042 */
+ 0x0F1238D4, /* 70004044 */
+ 0x0F127000, /* 70004046 */
+ 0x0F1217D0, /* 70004048 */
+ 0x0F127000, /* 7000404A */
+ 0x0F125000, /* 7000404C */
+ 0x0F12D000, /* 7000404E */
+ 0x0F121100, /* 70004050 */
+ 0x0F12D000, /* 70004052 */
+ 0x0F12171A, /* 70004054 */
+ 0x0F127000, /* 70004056 */
+ 0x0F124780, /* 70004058 */
+ 0x0F127000, /* 7000405A */
+ 0x0F122FCA, /* 7000405C */
+ 0x0F127000, /* 7000405E */
+ 0x0F122FC5, /* 70004060 */
+ 0x0F127000, /* 70004062 */
+ 0x0F122FC6, /* 70004064 */
+ 0x0F127000, /* 70004066 */
+ 0x0F122ED8, /* 70004068 */
+ 0x0F127000, /* 7000406A */
+ 0x0F122BD0, /* 7000406C */
+ 0x0F127000, /* 7000406E */
+ 0x0F1217E0, /* 70004070 */
+ 0x0F127000, /* 70004072 */
+ 0x0F122DE8, /* 70004074 */
+ 0x0F127000, /* 70004076 */
+ 0x0F1237E0, /* 70004078 */
+ 0x0F127000, /* 7000407A */
+ 0x0F12210C, /* 7000407C */
+ 0x0F127000, /* 7000407E */
+ 0x0F121484, /* 70004080 */
+ 0x0F127000, /* 70004082 */
+ 0x0F12A006, /* 70004084 */
+ 0x0F120000, /* 70004086 */
+ 0x0F120724, /* 70004088 */
+ 0x0F127000, /* 7000408A */
+ 0x0F12A000, /* 7000408C */
+ 0x0F12D000, /* 7000408E */
+ 0x0F122270, /* 70004090 */
+ 0x0F127000, /* 70004092 */
+ 0x0F122558, /* 70004094 */
+ 0x0F127000, /* 70004096 */
+ 0x0F12146C, /* 70004098 */
+ 0x0F127000, /* 7000409A */
+ 0x0F12B510, /* 7000409C */
+ 0x0F12000C, /* 7000409E */
+ 0x0F124951, /* 700040A0 */
+ 0x0F122208, /* 700040A2 */
+ 0x0F126820, /* 700040A4 */
+ 0x0F125E8A, /* 700040A6 */
+ 0x0F120140, /* 700040A8 */
+ 0x0F121A80, /* 700040AA */
+ 0x0F120280, /* 700040AC */
+ 0x0F1288C9, /* 700040AE */
+ 0x0F12F000, /* 700040B0 */
+ 0x0F12F934, /* 700040B2 */
+ 0x0F126020, /* 700040B4 */
+ 0x0F12E798, /* 700040B6 */
+ 0x0F12B5FE, /* 700040B8 */
+ 0x0F12000C, /* 700040BA */
+ 0x0F126825, /* 700040BC */
+ 0x0F126866, /* 700040BE */
+ 0x0F1268A0, /* 700040C0 */
+ 0x0F129001, /* 700040C2 */
+ 0x0F1268E7, /* 700040C4 */
+ 0x0F121BA8, /* 700040C6 */
+ 0x0F1242B5, /* 700040C8 */
+ 0x0F12DA00, /* 700040CA */
+ 0x0F121B70, /* 700040CC */
+ 0x0F129000, /* 700040CE */
+ 0x0F124945, /* 700040D0 */
+ 0x0F124846, /* 700040D2 */
+ 0x0F12884A, /* 700040D4 */
+ 0x0F128843, /* 700040D6 */
+ 0x0F12435A, /* 700040D8 */
+ 0x0F122304, /* 700040DA */
+ 0x0F125ECB, /* 700040DC */
+ 0x0F120A92, /* 700040DE */
+ 0x0F1218D2, /* 700040E0 */
+ 0x0F1202D2, /* 700040E2 */
+ 0x0F120C12, /* 700040E4 */
+ 0x0F1288CB, /* 700040E6 */
+ 0x0F128880, /* 700040E8 */
+ 0x0F124343, /* 700040EA */
+ 0x0F120A98, /* 700040EC */
+ 0x0F122308, /* 700040EE */
+ 0x0F125ECB, /* 700040F0 */
+ 0x0F1218C0, /* 700040F2 */
+ 0x0F1202C0, /* 700040F4 */
+ 0x0F120C00, /* 700040F6 */
+ 0x0F120411, /* 700040F8 */
+ 0x0F120400, /* 700040FA */
+ 0x0F121409, /* 700040FC */
+ 0x0F121400, /* 700040FE */
+ 0x0F121A08, /* 70004100 */
+ 0x0F12493A, /* 70004102 */
+ 0x0F1239E0, /* 70004104 */
+ 0x0F126148, /* 70004106 */
+ 0x0F129801, /* 70004108 */
+ 0x0F123040, /* 7000410A */
+ 0x0F127880, /* 7000410C */
+ 0x0F122800, /* 7000410E */
+ 0x0F12D103, /* 70004110 */
+ 0x0F129801, /* 70004112 */
+ 0x0F120029, /* 70004114 */
+ 0x0F12F000, /* 70004116 */
+ 0x0F12F907, /* 70004118 */
+ 0x0F128839, /* 7000411A */
+ 0x0F129800, /* 7000411C */
+ 0x0F124281, /* 7000411E */
+ 0x0F12D814, /* 70004120 */
+ 0x0F128879, /* 70004122 */
+ 0x0F129800, /* 70004124 */
+ 0x0F124281, /* 70004126 */
+ 0x0F12D20C, /* 70004128 */
+ 0x0F129801, /* 7000412A */
+ 0x0F120029, /* 7000412C */
+ 0x0F12F000, /* 7000412E */
+ 0x0F12F903, /* 70004130 */
+ 0x0F129801, /* 70004132 */
+ 0x0F120029, /* 70004134 */
+ 0x0F12F000, /* 70004136 */
+ 0x0F12F8FF, /* 70004138 */
+ 0x0F129801, /* 7000413A */
+ 0x0F120029, /* 7000413C */
+ 0x0F12F000, /* 7000413E */
+ 0x0F12F8FB, /* 70004140 */
+ 0x0F12E003, /* 70004142 */
+ 0x0F129801, /* 70004144 */
+ 0x0F120029, /* 70004146 */
+ 0x0F12F000, /* 70004148 */
+ 0x0F12F8F6, /* 7000414A */
+ 0x0F129801, /* 7000414C */
+ 0x0F120032, /* 7000414E */
+ 0x0F120039, /* 70004150 */
+ 0x0F12F000, /* 70004152 */
+ 0x0F12F8F9, /* 70004154 */
+ 0x0F126020, /* 70004156 */
+ 0x0F12E5D0, /* 70004158 */
+ 0x0F12B57C, /* 7000415A */
+ 0x0F124824, /* 7000415C */
+ 0x0F12A901, /* 7000415E */
+ 0x0F120004, /* 70004160 */
+ 0x0F12F000, /* 70004162 */
+ 0x0F12F87D, /* 70004164 */
+ 0x0F12466B, /* 70004166 */
+ 0x0F1288D9, /* 70004168 */
+ 0x0F128898, /* 7000416A */
+ 0x0F124B1F, /* 7000416C */
+ 0x0F123346, /* 7000416E */
+ 0x0F121E9A, /* 70004170 */
+ 0x0F12F000, /* 70004172 */
+ 0x0F12F8F1, /* 70004174 */
+ 0x0F12481E, /* 70004176 */
+ 0x0F12491C, /* 70004178 */
+ 0x0F123812, /* 7000417A */
+ 0x0F123140, /* 7000417C */
+ 0x0F128A42, /* 7000417E */
+ 0x0F12888B, /* 70004180 */
+ 0x0F1218D2, /* 70004182 */
+ 0x0F128242, /* 70004184 */
+ 0x0F128AC2, /* 70004186 */
+ 0x0F1288C9, /* 70004188 */
+ 0x0F121851, /* 7000418A */
+ 0x0F1282C1, /* 7000418C */
+ 0x0F120020, /* 7000418E */
+ 0x0F124669, /* 70004190 */
+ 0x0F12F000, /* 70004192 */
+ 0x0F12F865, /* 70004194 */
+ 0x0F124817, /* 70004196 */
+ 0x0F12214D, /* 70004198 */
+ 0x0F128301, /* 7000419A */
+ 0x0F122196, /* 7000419C */
+ 0x0F128381, /* 7000419E */
+ 0x0F12211D, /* 700041A0 */
+ 0x0F123020, /* 700041A2 */
+ 0x0F128001, /* 700041A4 */
+ 0x0F12F000, /* 700041A6 */
+ 0x0F12F8DF, /* 700041A8 */
+ 0x0F12F000, /* 700041AA */
+ 0x0F12F8E5, /* 700041AC */
+ 0x0F124812, /* 700041AE */
+ 0x0F124C12, /* 700041B0 */
+ 0x0F126E00, /* 700041B2 */
+ 0x0F1260E0, /* 700041B4 */
+ 0x0F12466B, /* 700041B6 */
+ 0x0F128818, /* 700041B8 */
+ 0x0F128859, /* 700041BA */
+ 0x0F120025, /* 700041BC */
+ 0x0F121A40, /* 700041BE */
+ 0x0F123540, /* 700041C0 */
+ 0x0F1261A8, /* 700041C2 */
+ 0x0F124809, /* 700041C4 */
+ 0x0F129900, /* 700041C6 */
+ 0x0F123060, /* 700041C8 */
+ 0x0F12F000, /* 700041CA */
+ 0x0F12F8DD, /* 700041CC */
+ 0x0F12466B, /* 700041CE */
+ 0x0F128819, /* 700041D0 */
+ 0x0F121DE0, /* 700041D2 */
+ 0x0F1230F9, /* 700041D4 */
+ 0x0F128741, /* 700041D6 */
+ 0x0F128859, /* 700041D8 */
+ 0x0F128781, /* 700041DA */
+ 0x0F122000, /* 700041DC */
+ 0x0F1271A0, /* 700041DE */
+ 0x0F1274A8, /* 700041E0 */
+ 0x0F12BC7C, /* 700041E2 */
+ 0x0F12BC08, /* 700041E4 */
+ 0x0F124718, /* 700041E6 */
+ 0x0F122558, /* 700041E8 */
+ 0x0F127000, /* 700041EA */
+ 0x0F122AB8, /* 700041EC */
+ 0x0F127000, /* 700041EE */
+ 0x0F12145E, /* 700041F0 */
+ 0x0F127000, /* 700041F2 */
+ 0x0F122698, /* 700041F4 */
+ 0x0F127000, /* 700041F6 */
+ 0x0F122BB8, /* 700041F8 */
+ 0x0F127000, /* 700041FA */
+ 0x0F122998, /* 700041FC */
+ 0x0F127000, /* 700041FE */
+ 0x0F124778, /* 70004200 */
+ 0x0F1246C0, /* 70004202 */
+ 0x0F12C000, /* 70004204 */
+ 0x0F12E59F, /* 70004206 */
+ 0x0F12FF1C, /* 70004208 */
+ 0x0F12E12F, /* 7000420A */
+ 0x0F121789, /* 7000420C */
+ 0x0F120001, /* 7000420E */
+ 0x0F124778, /* 70004210 */
+ 0x0F1246C0, /* 70004212 */
+ 0x0F12C000, /* 70004214 */
+ 0x0F12E59F, /* 70004216 */
+ 0x0F12FF1C, /* 70004218 */
+ 0x0F12E12F, /* 7000421A */
+ 0x0F1216F1, /* 7000421C */
+ 0x0F120001, /* 7000421E */
+ 0x0F124778, /* 70004220 */
+ 0x0F1246C0, /* 70004222 */
+ 0x0F12C000, /* 70004224 */
+ 0x0F12E59F, /* 70004226 */
+ 0x0F12FF1C, /* 70004228 */
+ 0x0F12E12F, /* 7000422A */
+ 0x0F12C3B1, /* 7000422C */
+ 0x0F120000, /* 7000422E */
+ 0x0F124778, /* 70004230 */
+ 0x0F1246C0, /* 70004232 */
+ 0x0F12C000, /* 70004234 */
+ 0x0F12E59F, /* 70004236 */
+ 0x0F12FF1C, /* 70004238 */
+ 0x0F12E12F, /* 7000423A */
+ 0x0F12C36D, /* 7000423C */
+ 0x0F120000, /* 7000423E */
+ 0x0F124778, /* 70004240 */
+ 0x0F1246C0, /* 70004242 */
+ 0x0F12C000, /* 70004244 */
+ 0x0F12E59F, /* 70004246 */
+ 0x0F12FF1C, /* 70004248 */
+ 0x0F12E12F, /* 7000424A */
+ 0x0F12F6D7, /* 7000424C */
+ 0x0F120000, /* 7000424E */
+ 0x0F124778, /* 70004250 */
+ 0x0F1246C0, /* 70004252 */
+ 0x0F12C000, /* 70004254 */
+ 0x0F12E59F, /* 70004256 */
+ 0x0F12FF1C, /* 70004258 */
+ 0x0F12E12F, /* 7000425A */
+ 0x0F12B49D, /* 7000425C */
+ 0x0F120000, /* 7000425E */
+ 0x0F124778, /* 70004260 */
+ 0x0F1246C0, /* 70004262 */
+ 0x0F12C000, /* 70004264 */
+ 0x0F12E59F, /* 70004266 */
+ 0x0F12FF1C, /* 70004268 */
+ 0x0F12E12F, /* 7000426A */
+ 0x0F127EDF, /* 7000426C */
+ 0x0F120000, /* 7000426E */
+ 0x0F124778, /* 70004270 */
+ 0x0F1246C0, /* 70004272 */
+ 0x0F12C000, /* 70004274 */
+ 0x0F12E59F, /* 70004276 */
+ 0x0F12FF1C, /* 70004278 */
+ 0x0F12E12F, /* 7000427A */
+ 0x0F12448D, /* 7000427C */
+ 0x0F120000, /* 7000427E */
+ 0x0F124778, /* 70004280 */
+ 0x0F1246C0, /* 70004282 */
+ 0x0F12F004, /* 70004284 */
+ 0x0F12E51F, /* 70004286 */
+ 0x0F1229EC, /* 70004288 */
+ 0x0F120001, /* 7000428A */
+ 0x0F124778, /* 7000428C */
+ 0x0F1246C0, /* 7000428E */
+ 0x0F12C000, /* 70004290 */
+ 0x0F12E59F, /* 70004292 */
+ 0x0F12FF1C, /* 70004294 */
+ 0x0F12E12F, /* 70004296 */
+ 0x0F122EF1, /* 70004298 */
+ 0x0F120000, /* 7000429A */
+ 0x0F124778, /* 7000429C */
+ 0x0F1246C0, /* 7000429E */
+ 0x0F12C000, /* 700042A0 */
+ 0x0F12E59F, /* 700042A2 */
+ 0x0F12FF1C, /* 700042A4 */
+ 0x0F12E12F, /* 700042A6 */
+ 0x0F12EE03, /* 700042A8 */
+ 0x0F120000, /* 700042AA */
+ 0x0F124778, /* 700042AC */
+ 0x0F1246C0, /* 700042AE */
+ 0x0F12C000, /* 700042B0 */
+ 0x0F12E59F, /* 700042B2 */
+ 0x0F12FF1C, /* 700042B4 */
+ 0x0F12E12F, /* 700042B6 */
+ 0x0F12A58B, /* 700042B8 */
+ 0x0F120000, /* 700042BA */
+ 0x0F124778, /* 700042BC */
+ 0x0F1246C0, /* 700042BE */
+ 0x0F12C000, /* 700042C0 */
+ 0x0F12E59F, /* 700042C2 */
+ 0x0F12FF1C, /* 700042C4 */
+ 0x0F12E12F, /* 700042C6 */
+ 0x0F127C49, /* 700042C8 */
+ 0x0F120000, /* 700042CA */
+ 0x0F124778, /* 700042CC */
+ 0x0F1246C0, /* 700042CE */
+ 0x0F12C000, /* 700042D0 */
+ 0x0F12E59F, /* 700042D2 */
+ 0x0F12FF1C, /* 700042D4 */
+ 0x0F12E12F, /* 700042D6 */
+ 0x0F127C63, /* 700042D8 */
+ 0x0F120000, /* 700042DA */
+ 0x0F124778, /* 700042DC */
+ 0x0F1246C0, /* 700042DE */
+ 0x0F12C000, /* 700042E0 */
+ 0x0F12E59F, /* 700042E2 */
+ 0x0F12FF1C, /* 700042E4 */
+ 0x0F12E12F, /* 700042E6 */
+ 0x0F122DB7, /* 700042E8 */
+ 0x0F120000, /* 700042EA */
+ 0x0F124778, /* 700042EC */
+ 0x0F1246C0, /* 700042EE */
+ 0x0F12C000, /* 700042F0 */
+ 0x0F12E59F, /* 700042F2 */
+ 0x0F12FF1C, /* 700042F4 */
+ 0x0F12E12F, /* 700042F6 */
+ 0x0F12EB3D, /* 700042F8 */
+ 0x0F120000, /* 700042FA */
+ 0x0F124778, /* 700042FC */
+ 0x0F1246C0, /* 700042FE */
+ 0x0F12C000, /* 70004300 */
+ 0x0F12E59F, /* 70004302 */
+ 0x0F12FF1C, /* 70004304 */
+ 0x0F12E12F, /* 70004306 */
+ 0x0F12F061, /* 70004308 */
+ 0x0F120000, /* 7000430A */
+ 0x0F124778, /* 7000430C */
+ 0x0F1246C0, /* 7000430E */
+ 0x0F12C000, /* 70004310 */
+ 0x0F12E59F, /* 70004312 */
+ 0x0F12FF1C, /* 70004314 */
+ 0x0F12E12F, /* 70004316 */
+ 0x0F12F0EF, /* 70004318 */
+ 0x0F120000, /* 7000431A */
+ 0x0F124778, /* 7000431C */
+ 0x0F1246C0, /* 7000431E */
+ 0x0F12F004, /* 70004320 */
+ 0x0F12E51F, /* 70004322 */
+ 0x0F122824, /* 70004324 */
+ 0x0F120001, /* 70004326 */
+ 0x0F124778, /* 70004328 */
+ 0x0F1246C0, /* 7000432A */
+ 0x0F12C000, /* 7000432C */
+ 0x0F12E59F, /* 7000432E */
+ 0x0F12FF1C, /* 70004330 */
+ 0x0F12E12F, /* 70004332 */
+ 0x0F128EDD, /* 70004334 */
+ 0x0F120000, /* 70004336 */
+ 0x0F124778, /* 70004338 */
+ 0x0F1246C0, /* 7000433A */
+ 0x0F12C000, /* 7000433C */
+ 0x0F12E59F, /* 7000433E */
+ 0x0F12FF1C, /* 70004340 */
+ 0x0F12E12F, /* 70004342 */
+ 0x0F128DCB, /* 70004344 */
+ 0x0F120000, /* 70004346 */
+ 0x0F124778, /* 70004348 */
+ 0x0F1246C0, /* 7000434A */
+ 0x0F12C000, /* 7000434C */
+ 0x0F12E59F, /* 7000434E */
+ 0x0F12FF1C, /* 70004350 */
+ 0x0F12E12F, /* 70004352 */
+ 0x0F128E17, /* 70004354 */
+ 0x0F120000, /* 70004356 */
+ 0x0F124778, /* 70004358 */
+ 0x0F1246C0, /* 7000435A */
+ 0x0F12C000, /* 7000435C */
+ 0x0F12E59F, /* 7000435E */
+ 0x0F12FF1C, /* 70004360 */
+ 0x0F12E12F, /* 70004362 */
+ 0x0F1298C5, /* 70004364 */
+ 0x0F120000, /* 70004366 */
+ 0x0F124778, /* 70004368 */
+ 0x0F1246C0, /* 7000436A */
+ 0x0F12C000, /* 7000436C */
+ 0x0F12E59F, /* 7000436E */
+ 0x0F12FF1C, /* 70004370 */
+ 0x0F12E12F, /* 70004372 */
+ 0x0F127C7D, /* 70004374 */
+ 0x0F120000, /* 70004376 */
+ 0x0F124778, /* 70004378 */
+ 0x0F1246C0, /* 7000437A */
+ 0x0F12C000, /* 7000437C */
+ 0x0F12E59F, /* 7000437E */
+ 0x0F12FF1C, /* 70004380 */
+ 0x0F12E12F, /* 70004382 */
+ 0x0F127E31, /* 70004384 */
+ 0x0F120000, /* 70004386 */
+ 0x0F124778, /* 70004388 */
+ 0x0F1246C0, /* 7000438A */
+ 0x0F12C000, /* 7000438C */
+ 0x0F12E59F, /* 7000438E */
+ 0x0F12FF1C, /* 70004390 */
+ 0x0F12E12F, /* 70004392 */
+ 0x0F127EAB, /* 70004394 */
+ 0x0F120000, /* 70004396 */
+ /* End of Patch Data(Last : 70004396h)*/
+ /* Total Size 2208 (08A0) */
+ /* Addr : 3AF8 , Size : 2206(89Eh) */
+
+ /*#define TNP_USER_MBCV_CONTROL */
+ /*#define TNP_4EC_MBR_TUNE */
+ /*#define TNP_4EC_FORBIDDEN_TUNE */
+ /*#define TNP_AF_FINESEARCH_DRIVEBACK */
+ /*#define TNP_FLASH_ALG */
+ /*#define TNP_GAS_ALPHA_OTP */
+ /*#define TNP_AWB_MODUL_COMP */
+ /*#define TNP_AWB_INIT_QUEUE */
+
+ /*TNP_Regs_usCintrTh 2 70004780 */
+ /*TNP_Regs_usFixedCintc 2 70004782 */
+ /*TNP_Regs_FlsWeightRIn_0_ 2 70004784 */
+ /*TNP_Regs_FlsWeightRIn_1_ 2 70004786 */
+ /*TNP_Regs_FlsWeightRIn_2_ 2 70004788 */
+ /*TNP_Regs_FlsWeightRIn_3_ 2 7000478A */
+ /*TNP_Regs_FlsWeightRIn_4_ 2 7000478C */
+ /*TNP_Regs_FlsWeightRIn_5_ 2 7000478E */
+ /*TNP_Regs_FlsWeightROut_0_ 2 70004790 */
+ /*TNP_Regs_FlsWeightROut_1_ 2 70004792 */
+ /*TNP_Regs_FlsWeightROut_2_ 2 70004794 */
+ /*TNP_Regs_FlsWeightROut_3_ 2 70004796 */
+ /*TNP_Regs_FlsWeightROut_4_ 2 70004798 */
+ /*TNP_Regs_FlsWeightROut_5_ 2 7000479A */
+
+ /*TNP_Regs_FlBRIn_0_ 2 7000479C */
+ /*TNP_Regs_FlBRIn_1_ 2 7000479E */
+ /*TNP_Regs_FlBRIn_2_ 2 700047A0 */
+ /*TNP_Regs_FlBRInOut_0_ 2 700047A2 */
+ /*TNP_Regs_FlBRInOut_1_ 2 700047A4 */
+ /*TNP_Regs_FlBRInOut_2_ 2 700047A6 */
+
+ 0x0028D000,
+ 0x002A1000,
+ 0x0F120001,
+
+ /* AF setting */
+ 0x00287000,
+ 0x002A01FC,
+ 0x0F120001, /* #REG_TC_IPRM_LedGpio */
+ 0x002A1720,
+ 0x0F120100,
+ 0x002A01FE,
+ 0x0F120003,
+ 0x0F120000,
+ 0x002A0204,
+ 0x0F120061,
+ 0x002A020C,
+ 0x0F122F0C,
+ 0x0F120190,
+ 0x002A0294,
+ 0x0F120100,
+ 0x0F1200E3,
+ 0x0F120200,
+ 0x0F120238,
+ 0x0F1201C6,
+ 0x0F120166,
+ 0x0F120074,
+ 0x0F120132,
+ 0x0F120001,
+
+ 0x002A070E,
+ 0x0F1200C0,
+ 0x002A071E,
+ 0x0F120001,
+ 0x002A163C,
+ 0x0F120000,
+ 0x002A1648,
+ 0x0F129002,
+ 0x002A1652,
+ 0x0F120002,
+ 0x0F120000,
+ 0x002A15E0,
+ 0x0F120902,
+
+ 0x002A164C,
+ 0x0F120003,
+ 0x002A163E,
+ 0x0F1200D5,
+ 0x0F120098,
+ 0x002A15D4,
+ 0x0F120000,
+ 0x0F12D000,
+ 0x002A169A,
+ 0x0F12FF95,
+ 0x002A166A,
+ 0x0F120280,
+ 0x002A1676,
+ 0x0F1203A0,
+ 0x0F120320,
+ 0x002A16BC,
+ 0x0F120030,
+ 0x002A16E0,
+ 0x0F120060,
+ 0x002A16D4,
+ 0x0F120010,
+ 0x002A1656,
+ 0x0F120000,
+ 0x002A15E6,
+ 0x0F12003C,
+
+ 0x0F120018, /*#af_pos_usTableLastInd*/
+ 0x0F12002A,
+ 0x0F120030,
+ 0x0F120036,
+ 0x0F12003C,
+ 0x0F120042,
+ 0x0F120048,
+ 0x0F12004E,
+ 0x0F120054,
+ 0x0F12005A,
+ 0x0F120060,
+ 0x0F120066,
+ 0x0F12006C,
+ 0x0F120072,
+ 0x0F120078,
+ 0x0F12007E,
+ 0x0F120084,
+ 0x0F12008A,
+ 0x0F120090,
+ 0x0F120096,
+ 0x0F12009C,
+ 0x0F1200A2,
+ 0x0F1200A8,
+ 0x0F1200AE,
+ 0x0F1200B4,
+ 0x0F1200BA, /*#af_pos_usTable_24_*/
+
+ 0x002A1722,
+ 0x0F128000,
+ 0x0F120006,
+ 0x0F123FF0,
+ 0x0F1203E8,
+ 0x0F120000,
+ 0x0F120020,
+ 0x0F120010,
+ 0x0F120008,
+ 0x0F120040,
+ 0x0F120080,
+ 0x0F1200C0,
+ 0x0F1200E0,
+
+ 0x002A028C,
+ 0x0F120003, /*#REG_TC_AF_AfCmd*/
+
+ /* GAS TBL setting */
+ 0x002A08B4,
+ 0x0F120001, /*#wbt_bUseOutdoorASH*/
+
+ /*TVAR_ash_AwbAshCord, Refer Mon_AWB_RotGain*/
+ 0x002A08BC,
+ 0x0F1200C0, /*#TVAR_ash_AwbAshCord_0_ 2300K*/
+ 0x0F1200DF, /*#TVAR_ash_AwbAshCord_1_ 2750K*/
+ 0x0F120100, /*#TVAR_ash_AwbAshCord_2_ 3300K*/
+ 0x0F120125, /*#TVAR_ash_AwbAshCord_3_ 4150K*/
+ 0x0F12015F, /*#TVAR_ash_AwbAshCord_4_ 5250K*/
+ 0x0F12017C, /*#TVAR_ash_AwbAshCord_5_ 6400K*/
+ 0x0F120194, /*#TVAR_ash_AwbAshCord_6_ 7500K*/
+
+
+ 0x002A08F6,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+
+ 0x0F124500,
+ 0x0F124000,
+ 0x0F124000,
+ 0x0F124000,
+
+ 0x002A08F4,
+ 0x0F120001, /*#ash_bUseGasAlpha*/
+
+ /* AE START */
+
+ /*AE WEIGHT */
+ 0x002A1492,
+ 0x0F120000,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120000,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120201,
+ 0x0F120303,
+ 0x0F120303,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120403,
+ 0x0F120304,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120403,
+ 0x0F120304,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120403,
+ 0x0F120304,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120303,
+ 0x0F120303,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120202,
+ 0x0F120202,
+ 0x0F120102,
+
+ 0x002A1484,
+ 0x0F12003C, /*#TVAR_ae_BrAve*/
+ 0x002A148A,
+ 0x0F12000F, /*#ae_StatMode*/
+ 0x002A058C,
+ 0x0F123520,
+ 0x0F120000, /*#lt_uMaxExp1*/
+ 0x0F12C350,
+ 0x0F120000, /*#lt_uMaxExp2*/
+ 0x0F123520,
+ 0x0F120000, /*#lt_uCapMaxExp1*/
+ 0x0F12C350,
+ 0x0F120000, /*#lt_uCapMaxExp2*/
+ 0x0F120470, /*#lt_uMaxAnGain1*/
+ 0x0F120C00, /*#lt_uMaxAnGain2*/
+ 0x0F120100, /*#lt_uMaxDigGain*/
+ 0x0F121000, /*#lt_uMaxTotGain*/
+
+ 0x002A0544,
+ 0x0F120111, /*#lt_uLimitHigh*/
+ 0x0F1200EF, /*#lt_uLimitLow*/
+
+ 0x002A0F2A,
+ 0x0F120001, /*#AFC_Default60Hz*/
+ 0x002A0F30,
+ 0x0F120002, /*#AFC_D_ConvAccelerPower*/
+
+ 0x002A0588, /*#lt_uInitPostToleranceCnt*/
+ 0x0F120000, /*AE Speed-up*/
+
+ 0x002A0600, /*#lt_uleiInit*/
+ 0x0F12D000,
+
+ 0x002A0608,
+ 0x0F120001, /*#lt_ExpGain_uSubsamplingmode*/
+ 0x0F120001, /*#lt_ExpGain_uNonSubsampling*/
+ 0x0F120C00, /*#lt_ExpGain_ExpCurveGainMaxStr*/
+ 0x0F120100, /*#lt_ExpGain_ExpCurveGainMaxStr_0__uMaxDigGain*/
+ 0x0F120001,
+ 0x0F120000, /*#lt_ExpGain_ExpCurveGainMaxStr_0__ulExpIn_0_*/
+ 0x0F120A3C,
+ 0x0F120000,
+ 0x0F120D04,
+ 0x0F120000,
+ 0x0F124008,
+ 0x0F120000,
+ 0x0F127000,
+ 0x0F120000,
+ 0x0F129C00,
+ 0x0F120000,
+ 0x0F12AD00,
+ 0x0F120001,
+ 0x0F12F1D4,
+ 0x0F120002,
+ 0x0F12DC00,
+ 0x0F120005,
+ 0x0F12DC00,
+ 0x0F120005,
+ 0x0F120001,
+ 0x0F120000, /*#lt_ExpGain_ExpCurveGainMaxStr_0__ulExpOut_0_*/
+ 0x0F120A3C,
+ 0x0F120000,
+ 0x0F120D05,
+ 0x0F120000,
+ 0x0F123408,
+ 0x0F120000,
+ 0x0F123408,
+ 0x0F120000,
+ 0x0F126810,
+ 0x0F120000,
+ 0x0F128214,
+ 0x0F120000,
+ 0x0F12C350,
+ 0x0F120000,
+ 0x0F12C350,
+ 0x0F120000,
+ 0x0F12C350,
+ 0x0F120000,
+ 0x0F120650, /*#lt_ExpGain_ExpCurveGainMaxStr_1_*/
+ 0x0F120100, /*#lt_ExpGain_ExpCurveGainMaxStr_1__uMaxDigGain*/
+
+ 0x002A06B8,
+ 0x0F12452C,
+ 0x0F12000C, /*#lt_uMaxLei*/
+
+ 0x002A05D0,
+ 0x0F120000, /*#lt_mbr_Peak_behind*/
+
+ /* AWB init Start point */
+ 0x002A145E,
+ 0x0F120470, /* 0400 */
+ 0x0F120400, /* 0428 */
+ 0x0F1209F0, /* 9B3 */
+
+ /* AWB Init */
+ /*White Locus */
+ 0x002A11F0,
+ 0x0F12012C, /*#awbb_IntcR*/
+ 0x0F120121, /*#awbb_IntcB*/
+
+ /* IndoorZone*/
+ 0x002A101C,
+ 0x0F12039A,
+ 0x0F1203E8,
+ 0x0F12033C,
+ 0x0F1203AE,
+ 0x0F1202DE,
+ 0x0F120376,
+ 0x0F12029C,
+ 0x0F12033C,
+ 0x0F12027E,
+ 0x0F120312,
+ 0x0F12025E,
+ 0x0F1202F6,
+ 0x0F12023E,
+ 0x0F1202DA,
+ 0x0F12022A,
+ 0x0F1202BC,
+ 0x0F120214,
+ 0x0F1202A2,
+ 0x0F1201FE,
+ 0x0F120292,
+ 0x0F1201F0,
+ 0x0F120284,
+ 0x0F1201E0,
+ 0x0F120276,
+ 0x0F1201D2,
+ 0x0F120266,
+ 0x0F1201C4,
+ 0x0F120258,
+ 0x0F1201D8,
+ 0x0F120216,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+
+ 0x0F120005, /*#awbb_IndoorGrZones_m_GridStep*/
+ 0x002A1070,
+ 0x0F12000F, /*#awbb_IndoorGrZones_ZInfo_m_GridSz*/
+ 0x002A1074,
+ 0x0F12013C, /*#awbb_IndoorGrZones_m_Boffs*/
+
+ /*Outdoor Zone*/
+ 0x002A1078,
+ 0x0F120254,
+ 0x0F120296,
+ 0x0F120246,
+ 0x0F1202B4,
+ 0x0F120238,
+ 0x0F1202B8,
+ 0x0F12022A,
+ 0x0F1202B0,
+ 0x0F12021C,
+ 0x0F1202A6,
+ 0x0F12021A,
+ 0x0F12029C,
+ 0x0F12021A,
+ 0x0F120292,
+ 0x0F120220,
+ 0x0F120288,
+ 0x0F120226,
+ 0x0F12027E,
+ 0x0F120244,
+ 0x0F120274,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+
+ 0x0F120004, /*#awbb_OutdoorGrZones_m_GridStep*/
+ 0x002A10AC,
+ 0x0F12000A, /*#awbb_OutdoorGrZones_ZInfo_m_GridSz*/
+ 0x002A10B0,
+ 0x0F1201EE, /*#awbb_OutdoorGrZones_m_Boffs*/
+
+ /*LowBR Zone*/
+ 0x002A10B4,
+ 0x0F120350,
+ 0x0F120422,
+ 0x0F1202C4,
+ 0x0F120452,
+ 0x0F120278,
+ 0x0F12041C,
+ 0x0F120230,
+ 0x0F1203EE,
+ 0x0F1201F0,
+ 0x0F120392,
+ 0x0F1201C0,
+ 0x0F120340,
+ 0x0F120194,
+ 0x0F120302,
+ 0x0F12016E,
+ 0x0F1202C2,
+ 0x0F120148,
+ 0x0F120286,
+ 0x0F12018A,
+ 0x0F120242,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+
+ 0x0F120006, /*#awbb_LowBrGrZones_m_GridStep*/
+ 0x002A10E8,
+ 0x0F12000A, /*#awbb_LowBrGrZones_ZInfo_m_GridSz*/
+ 0x002A10EC,
+ 0x0F120106, /*#awbb_LowBrGrZones_m_Boffs*/
+
+ /*LowTemp Zone*/
+ 0x002A10F0,
+ 0x0F120380,
+ 0x0F120000, /*#awbb_CrclLowT_R_c*/
+ 0x0F120168,
+ 0x0F120000, /*#awbb_CrclLowT_B_c*/
+ 0x0F122D90,
+ 0x0F120000, /*#awbb_CrclLowT_Rad_c*/
+
+ /*AWB Convergence Speed*/
+ 0x002A1464,
+ 0x0F120008,
+ 0x0F120190,
+ 0x0F1200A0,
+
+ 0x002A1228,
+ 0x0F1200C0,
+ 0x002A122C,
+ 0x0F120010,
+ 0x002A122A,
+ 0x0F120010,
+
+ 0x002A120A,
+ 0x0F1205D5, /*#awbb_MvEq_RBthresh*/
+ 0x002A120E,
+ 0x0F120000,
+
+ 0x0F120771,
+ 0x0F1203A4,
+ 0x0F120036,
+ 0x0F12002A,
+
+ 0x002A1278,
+ 0x0F12FEF7,
+ 0x0F120021,
+ 0x0F120E74,
+ 0x0F120E74,
+ 0x0F12018F,
+ 0x0F120096,
+ 0x0F12000E,
+ 0x002A1224,
+ 0x0F120032,
+ 0x0F12001E,
+ 0x0F1200C0,
+ 0x0F120010,
+ 0x0F120002, /*awbb_YThreshLow_Low */
+ 0x002A2BA4,
+ 0x0F120006, /*#Mon_AWB_ByPassMode*/
+
+ 0x002A146C,
+ 0x0F120002, /*#awbb_GridEnable*/
+
+ /*Grid*/
+ 0x002A1434,
+ 0x0F120300, /* awbb_GridConst_1 */
+ 0x0F12036E, /* awbb_GridConst_1_1_ */
+ 0x0F1203C2, /* awbb_GridConst_1_2_ */
+ 0x0F121074, /* awbb_GridConst_2 */
+ 0x0F1210C2, /* awbb_GridConst_2_1_ */
+ 0x0F121104, /* awbb_GridConst_2_2_ */
+ 0x0F121142, /* awbb_GridConst_2_3_ */
+ 0x0F1211BB, /* awbb_GridConst_2_4_ */
+ 0x0F12123B, /* awbb_GridConst_2_5_ */
+ 0x0F1200AB, /* awbb_GridCoeff_R_1 */
+ 0x0F1200BF, /* awbb_GridCoeff_B_1 */
+ 0x0F1200D2, /* awbb_GridCoeff_R_2 */
+ 0x0F120093, /* awbb_GridCoeff_B_2 */
+
+ /*Indoor Grid Offset*/
+ 0x002A13A4,
+ 0x0F120000,
+ 0x0F12FFD0,
+ 0x0F12FFD0,
+ 0x0F120000,
+ 0x0F120008,
+ 0x0F120018,
+ 0x0F120000,
+ 0x0F12FFD0,
+ 0x0F12FFD0,
+ 0x0F120000,
+ 0x0F120008,
+ 0x0F120018,
+ 0x0F120000,
+ 0x0F12FFD0,
+ 0x0F12FFD0,
+ 0x0F120000,
+ 0x0F120008,
+ 0x0F120018,
+ 0x0F12FFE0,
+ 0x0F12FFE0,
+ 0x0F12FFC0,
+ 0x0F12FFC0,
+ 0x0F12FFB0,
+ 0x0F12FFB0,
+ 0x0F12FFE0,
+ 0x0F12FFE0,
+ 0x0F12FFC0,
+ 0x0F12FFC0,
+ 0x0F12FFB0,
+ 0x0F12FFB0,
+ 0x0F12FFE0,
+ 0x0F12FFE0,
+ 0x0F12FFC0,
+ 0x0F12FFC0,
+ 0x0F12FFB0,
+ 0x0F12FFB0,
+
+ /*Outdoor Grid Offset*/
+ 0x0F12FFB0,
+ 0x0F12FFD0,
+ 0x0F12FFD0,
+ 0x0F12FFD0,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F12FFB0,
+ 0x0F12FFD0,
+ 0x0F12FFD0,
+ 0x0F12FFD0,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F12FFB0,
+ 0x0F12FFD0,
+ 0x0F12FFD0,
+ 0x0F12FFD0,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F12FFC8,
+ 0x0F12FFB8,
+ 0x0F12FFB8,
+ 0x0F12FFB8,
+ 0x0F12FFB8,
+ 0x0F120000,
+ 0x0F12FFC8,
+ 0x0F12FFB8,
+ 0x0F12FFB8,
+ 0x0F12FFB8,
+ 0x0F12FFB8,
+ 0x0F120000,
+ 0x0F12FFC8,
+ 0x0F12FFB8,
+ 0x0F12FFB8,
+ 0x0F12FFB8,
+ 0x0F12FFB8,
+
+ 0x002A1208,
+ 0x0F120020,
+
+ 0x002A144E,
+ 0x0F120000, /*#awbb_RGainOff*/
+ 0x0F120000, /*#awbb_BGainOff*/
+ 0x0F120000, /*#awbb_GGainOff*/
+
+ /*RGB Indoor Gamma*/
+ 0x002A0734,
+ 0x0F120001,
+ 0x0F120007,
+ 0x0F120011,
+ 0x0F12002D,
+ 0x0F12006B,
+ 0x0F1200DC,
+ 0x0F12013B,
+ 0x0F120166,
+ 0x0F12018D,
+ 0x0F1201CD,
+ 0x0F120204,
+ 0x0F120235,
+ 0x0F120260,
+ 0x0F1202AA,
+ 0x0F1202EC,
+ 0x0F12034E,
+ 0x0F120396,
+ 0x0F1203C6,
+ 0x0F1203E9,
+ 0x0F1203F9,
+ 0x0F120001,
+ 0x0F120007,
+ 0x0F120011,
+ 0x0F12002D,
+ 0x0F12006B,
+ 0x0F1200DC,
+ 0x0F12013B,
+ 0x0F120166,
+ 0x0F12018D,
+ 0x0F1201CD,
+ 0x0F120204,
+ 0x0F120235,
+ 0x0F120260,
+ 0x0F1202AA,
+ 0x0F1202EC,
+ 0x0F12034E,
+ 0x0F120396,
+ 0x0F1203C6,
+ 0x0F1203E9,
+ 0x0F1203F9,
+ 0x0F120001,
+ 0x0F120007,
+ 0x0F120011,
+ 0x0F12002D,
+ 0x0F12006B,
+ 0x0F1200DC,
+ 0x0F12013B,
+ 0x0F120166,
+ 0x0F12018D,
+ 0x0F1201CD,
+ 0x0F120204,
+ 0x0F120235,
+ 0x0F120260,
+ 0x0F1202AA,
+ 0x0F1202EC,
+ 0x0F12034E,
+ 0x0F120396,
+ 0x0F1203C6,
+ 0x0F1203E9,
+ 0x0F1203F9,
+
+ /*RGB Outdoor Gamma*/
+ 0x0F120001,
+ 0x0F120007,
+ 0x0F120011,
+ 0x0F12002D,
+ 0x0F12006B,
+ 0x0F1200DC,
+ 0x0F12013B,
+ 0x0F120166,
+ 0x0F12018D,
+ 0x0F1201CD,
+ 0x0F120204,
+ 0x0F120235,
+ 0x0F120260,
+ 0x0F1202AA,
+ 0x0F1202EC,
+ 0x0F12034E,
+ 0x0F120396,
+ 0x0F1203C6,
+ 0x0F1203E9,
+ 0x0F1203F9,
+ 0x0F120001,
+ 0x0F120007,
+ 0x0F120011,
+ 0x0F12002D,
+ 0x0F12006B,
+ 0x0F1200DC,
+ 0x0F12013B,
+ 0x0F120166,
+ 0x0F12018D,
+ 0x0F1201CD,
+ 0x0F120204,
+ 0x0F120235,
+ 0x0F120260,
+ 0x0F1202AA,
+ 0x0F1202EC,
+ 0x0F12034E,
+ 0x0F120396,
+ 0x0F1203C6,
+ 0x0F1203E9,
+ 0x0F1203F9,
+ 0x0F120001,
+ 0x0F120007,
+ 0x0F120011,
+ 0x0F12002D,
+ 0x0F12006B,
+ 0x0F1200DC,
+ 0x0F12013B,
+ 0x0F120166,
+ 0x0F12018D,
+ 0x0F1201CD,
+ 0x0F120204,
+ 0x0F120235,
+ 0x0F120260,
+ 0x0F1202AA,
+ 0x0F1202EC,
+ 0x0F12034E,
+ 0x0F120396,
+ 0x0F1203C6,
+ 0x0F1203E9,
+ 0x0F1203F9,
+
+ /*CCM*/
+ 0x002A08A6,
+ 0x0F1200C0,
+ 0x0F1200D0,
+ 0x0F1200E0,
+ 0x0F120110,
+ 0x0F12017C,
+ 0x0F120194,
+
+ 0x0F120001,
+
+ 0x002A0898,
+ 0x0F124800,
+ 0x0F127000,
+ 0x002A08A0,
+ 0x0F1248D8,
+ 0x0F127000,
+
+ 0x002A4800,
+ 0x0F12010F, /*hor*/
+ 0x0F12FF90,
+ 0x0F12FF7D,
+ 0x0F12FEF1,
+ 0x0F120137,
+ 0x0F12FF68,
+ 0x0F12FFEE,
+ 0x0F12FF8A,
+ 0x0F12013A,
+ 0x0F12006E,
+ 0x0F120089,
+ 0x0F12FEFE,
+ 0x0F120175,
+ 0x0F12FF4A,
+ 0x0F1200D6,
+ 0x0F12FEFE,
+ 0x0F120113,
+ 0x0F1200E6,
+ 0x0F12010F, /*incaA*/
+ 0x0F12FF90,
+ 0x0F12FF7D,
+ 0x0F12FEF1,
+ 0x0F120137,
+ 0x0F12FF68,
+ 0x0F12FFEE,
+ 0x0F12FF8A,
+ 0x0F12013A,
+ 0x0F12006E,
+ 0x0F120089,
+ 0x0F12FEFE,
+ 0x0F120175,
+ 0x0F12FF4A,
+ 0x0F1200D6,
+ 0x0F12FEFE,
+ 0x0F120113,
+ 0x0F1200E6,
+ 0x0F12010F, /*WW*/
+ 0x0F12FF90,
+ 0x0F12FF7D,
+ 0x0F12FEF1,
+ 0x0F120137,
+ 0x0F12FF68,
+ 0x0F12FFEE,
+ 0x0F12FF8A,
+ 0x0F12013A,
+ 0x0F12006E,
+ 0x0F120089,
+ 0x0F12FEFE,
+ 0x0F120175,
+ 0x0F12FF4A,
+ 0x0F1200D6,
+ 0x0F12FEFE,
+ 0x0F120113,
+ 0x0F1200E6,
+ 0x0F12017B, /*CW*/
+ 0x0F12FFB5,
+ 0x0F12FFF9,
+ 0x0F12FF5E,
+ 0x0F12019D,
+ 0x0F12FFA2,
+ 0x0F12FFD9,
+ 0x0F12FFCB,
+ 0x0F12012C,
+ 0x0F1200C9,
+ 0x0F1200B0,
+ 0x0F12FF2F,
+ 0x0F1200CA,
+ 0x0F12FF91,
+ 0x0F12015E,
+ 0x0F12FF47,
+ 0x0F120129,
+ 0x0F120125,
+ 0x0F1201AF, /*D50*/
+ 0x0F12FFBA,
+ 0x0F12FFF1,
+ 0x0F12FF27,
+ 0x0F1201DE,
+ 0x0F12FF77,
+ 0x0F12FFCB,
+ 0x0F12FFC5,
+ 0x0F120136,
+ 0x0F120110,
+ 0x0F1200EF,
+ 0x0F12FFA0,
+ 0x0F1200A3,
+ 0x0F12FF7B,
+ 0x0F12018C,
+ 0x0F12FF1D,
+ 0x0F120138,
+ 0x0F120138,
+ 0x0F1201AF, /*D65*/
+ 0x0F12FFBA,
+ 0x0F12FFF1,
+ 0x0F12FF27,
+ 0x0F1201DE,
+ 0x0F12FF77,
+ 0x0F12FFCB,
+ 0x0F12FFC5,
+ 0x0F120136,
+ 0x0F120110,
+ 0x0F1200EF,
+ 0x0F12FFA0,
+ 0x0F1200A3,
+ 0x0F12FF7B,
+ 0x0F12018C,
+ 0x0F12FF1D,
+ 0x0F120138,
+ 0x0F120138,
+
+ 0x0F12019F, /*#TVAR_wbt_pOutdoorCcm[0]*/
+ 0x0F12FFBF,
+ 0x0F12FFFD,
+ 0x0F12FF10,
+ 0x0F1201D4,
+ 0x0F12FFA4,
+ 0x0F12FFE8,
+ 0x0F12FFE0,
+ 0x0F1201C2,
+ 0x0F120087,
+ 0x0F1200A5,
+ 0x0F12FF17,
+ 0x0F1201DD,
+ 0x0F12FF0E,
+ 0x0F12010B,
+ 0x0F12FF24,
+ 0x0F1200F0,
+ 0x0F1201DB,
+
+
+ /*System Setting*/
+ 0x002A01F8,
+ 0x0F125DC0, /*#REG_TC_IPRM_InClockLSBs, MCLK: 24Mhz*/
+ 0x002A0212,
+ 0x0F120002, /*#REG_TC_IPRM_UseNPviClocks*/
+ 0x0F120000, /*#REG_TC_IPRM_UseNMipiClocks*/
+ 0x0F120000, /*#REG_TC_IPRM_NumberOfMipiLanes*/
+ 0x002A021A,
+ 0x0F123A98, /*#REG_TC_IPRM_OpClk4KHz_0, SCLK: 60Mhz*/
+ 0x0F124F1A, /*#REG_TC_IPRM_MinOutRate4KHz_0 PCLK Min : 81Mhz*/
+ 0x0F124F1A, /*#REG_TC_IPRM_MaxOutRate4KHz_0 PCLK Max : 81Mhz*/
+ 0x0F124F1A, /*#REG_TC_IPRM_OpClk4KHz_1 SCLK : 81Mhz*/
+ 0x0F124F1A, /*#REG_TC_IPRM_MinOutRate4KHz_1 PCLK Min : 81Mhz*/
+ 0x0F124F1A, /*#REG_TC_IPRM_MaxOutRate4KHz_1 PCLK Max : 81Mhz*/
+ 0x002A022C,
+ 0x0F120001, /*#REG_TC_IPRM_InitParamsUpdated*/
+
+ /*ETC.. Setting*/
+ 0x002A0478,
+ 0x0F12005F, /*#REG_TC_BRC_usPrevQuality*/
+ 0x0F12005F, /*#REG_TC_BRC_usCaptureQuality*/
+
+ 0x0F120001, /*#REG_TC_THUMB_Thumb_bActive*/
+ 0x0F120280, /*#REG_TC_THUMB_Thumb_uWidth*/
+ 0x0F1201E0, /*#REG_TC_THUMB_Thumb_uHeight*/
+ 0x0F120005, /*#REG_TC_THUMB_Thumb_Format*/
+
+ 0x002A17DC,
+ 0x0F120054, /*#jpeg_ManualMBCV*/
+ 0x002A1AE4,
+ 0x0F12001C, /*#senHal_bExtraAddLine*/
+ 0x002A0284,
+ 0x0F120001, /*#REG_TC_GP_bBypassScalerJpg*/
+ 0x002A028A,
+ 0x0F120001, /*#REG_TC_GP_bUse1FrameCaptureMode*/
+ /*0 : Continuous mode,1 : Single frame mode*/
+
+ /*Configuration Setting*/
+ 0x002A02A6,
+ 0x0F120280, /*#REG_0TC_PCFG_usWidth : 640*/
+ 0x0F1201E0, /*#REG_0TC_PCFG_usHeight : 480*/
+ 0x0F120005, /*#REG_0TC_PCFG_Format 5 : YUV 7 : Raw 9 : JPG*/
+ 0x0F124F1A, /*#REG_0TC_PCFG_usMaxOut4KHzRate*/
+ 0x0F124F1A, /*#REG_0TC_PCFG_usMinOut4KHzRate*/
+ 0x0F120100, /*#REG_0TC_PCFG_OutClkPerPix88*/
+ 0x0F120300, /*#REG_0TC_PCFG_uBpp88*/
+ 0x0F120052, /*#REG_0TC_PCFG_PVIMask*/
+ 0x0F120000, /*#REG_0TC_PCFG_OIFMask*/
+ 0x0F1201E0, /*#REG_0TC_PCFG_usJpegPacketSize*/
+ 0x0F120000, /*#REG_0TC_PCFG_usJpegTotalPackets*/
+ 0x0F120000, /*#REG_0TC_PCFG_uClockInd*/
+ 0x0F120000, /*#REG_0TC_PCFG_usFrTimeType*/
+ 0x0F120001, /*#REG_0TC_PCFG_FrRateQualityType*/
+ 0x0F12029A, /*#REG_0TC_PCFG_usMaxFrTimeMsecMult10*/
+ 0x0F12014A, /*#REG_0TC_PCFG_usMinFrTimeMsecMult10*/
+ 0x002A02D0,
+ 0x0F120000, /*#REG_0TC_PCFG_uPrevMirror*/
+ 0x0F120000, /*#REG_0TC_PCFG_uCaptureMirror*/
+ 0x0F120000, /*#REG_0TC_PCFG_uRotation*/
+
+ 0x002A0396,
+ 0x0F120000, /*#REG_0TC_CCFG_uCaptureMode*/
+ 0x0F120A00, /*#REG_0TC_CCFG_usWidth*/
+ 0x0F120780, /*#REG_0TC_CCFG_usHeight*/
+ 0x0F120009, /*#REG_0TC_CCFG_Format*/
+ 0x0F124F1A, /*#REG_0TC_CCFG_usMaxOut4KHzRate*/
+ 0x0F124F1A, /*#REG_0TC_CCFG_usMinOut4KHzRate*/
+ 0x0F120100, /*#REG_0TC_CCFG_OutClkPerPix88*/
+ 0x0F120300, /*#REG_0TC_CCFG_uBpp88*/
+ 0x0F120042, /*#REG_0TC_CCFG_PVIMask*/
+ 0x0F120000, /*#REG_0TC_CCFG_OIFMask*/
+ 0x0F1201E0, /*#REG_0TC_CCFG_usJpegPacketSize*/
+ 0x0F120000, /*#REG_0TC_CCFG_usJpegTotalPackets*/
+ 0x0F120001, /*#REG_0TC_CCFG_uClockInd*/
+ 0x0F120000, /*#REG_0TC_CCFG_usFrTimeType*/
+ 0x0F120002, /*#REG_0TC_CCFG_FrRateQualityType*/
+ 0x0F120535, /*#REG_0TC_CCFG_usMaxFrTimeMsecMult10*/
+ 0x0F12029A, /*#REG_0TC_CCFG_usMinFrTimeMsecMult10*/
+
+ 0x002A0250,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120010,
+ 0x0F12000C,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120010,
+ 0x0F12000C,
+ 0x002A0494,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120000,
+ 0x0F120000,
+
+ 0x002A0262,
+ 0x0F120001,
+ 0x0F120001,
+ 0x0F120000, /*#REG_TC_GP_ActivePrevConfig*/
+ 0x002A026A,
+ 0x0F120001, /*#REG_TC_GP_PrevOpenAfterChange*/
+ 0x002A024E,
+ 0x0F120001, /*#REG_TC_GP_NewConfigSync*/
+ 0x002A0268,
+ 0x0F120001, /*#REG_TC_GP_PrevConfigChanged*/
+ 0x002A0270,
+ 0x0F120001, /*#REG_TC_GP_CapConfigChanged*/
+ 0x002A023E,
+ 0x0F120001, /*#REG_TC_GP_EnablePreview*/
+ 0x0F120001, /*#REG_TC_GP_EnablePreviewChanged*/
+
+
+ /*AFIT*/
+ 0x002A0944,
+ 0x0F120050, /*#afit_uNoiseIndInDoor_0_*/
+ 0x0F120103, /*#afit_uNoiseIndInDoor_1_*/
+ 0x0F120196, /*#afit_uNoiseIndInDoor_2_*/
+ 0x0F120245, /*#afit_uNoiseIndInDoor_3_*/
+ 0x0F120300, /*#afit_uNoiseIndInDoor_4_*/
+
+ 0x002A097A,
+ 0x0F120001, /*#afit_bUseSenBpr*/
+ 0x0F1201CC, /*#afit_usBprThr_0_*/
+ 0x0F1201CC, /*#afit_usBprThr_1_*/
+ 0x0F1201CC, /*#afit_usBprThr_2_*/
+ 0x0F1201CC, /*#afit_usBprThr_3_*/
+ 0x0F1201CC, /*#afit_usBprThr_4_*/
+ 0x0F120180, /*#afit_NIContrastAFITValue*/
+ 0x0F120196, /*#afit_NIContrastTh*/
+
+ 0x002A0976,
+ 0x0F120070,
+ 0x0F120005,
+
+ 0x002A0938,
+ 0x0F120000,
+ 0x0F120014, /*#SARR_uNormBrInDoor_0_*/
+ 0x0F1200D2, /*#SARR_uNormBrInDoor_1_*/
+ 0x0F120384, /*#SARR_uNormBrInDoor_2_*/
+ 0x0F1207D0, /*#SARR_uNormBrInDoor_3_*/
+ 0x0F121388, /*#SARR_uNormBrInDoor_4_*/
+
+ 0x002A098C,
+ 0x0F120000, /*AFIT 0*/
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1200C0,
+ 0x0F120064,
+ 0x0F120384,
+ 0x0F12005F,
+ 0x0F1201F4,
+ 0x0F120070,
+ 0x0F120040,
+ 0x0F1200A0,
+ 0x0F120100,
+ 0x0F120010,
+ 0x0F120040,
+ 0x0F1200A0,
+ 0x0F121430,
+ 0x0F120201,
+ 0x0F120204,
+ 0x0F123604,
+ 0x0F12032A,
+ 0x0F120403,
+ 0x0F121B06,
+ 0x0F126015,
+ 0x0F1200C0,
+ 0x0F126080,
+ 0x0F124080,
+ 0x0F120640,
+ 0x0F120306,
+ 0x0F122003,
+ 0x0F12FF01,
+ 0x0F120000,
+ 0x0F120400,
+ 0x0F12365A,
+ 0x0F12102A,
+ 0x0F12000B,
+ 0x0F120600,
+ 0x0F125A0F,
+ 0x0F120505,
+ 0x0F121802,
+ 0x0F120000,
+ 0x0F122006,
+ 0x0F123028,
+ 0x0F120418,
+ 0x0F120101,
+ 0x0F120800,
+ 0x0F121804,
+ 0x0F124008,
+ 0x0F120540,
+ 0x0F128006,
+ 0x0F120020,
+ 0x0F120000,
+ 0x0F121800,
+ 0x0F120000,
+ 0x0F121E10,
+ 0x0F12000B,
+ 0x0F120607,
+ 0x0F120005,
+ 0x0F120607,
+ 0x0F120705,
+ 0x0F120206,
+ 0x0F120304,
+ 0x0F120309,
+ 0x0F120305,
+ 0x0F122006,
+ 0x0F121320,
+ 0x0F121014,
+ 0x0F121010,
+ 0x0F120C10,
+ 0x0F121A0C,
+ 0x0F124A18,
+ 0x0F120080,
+ 0x0F120050,
+ 0x0F120180,
+ 0x0F120A0A,
+ 0x0F120101,
+ 0x0F122A36,
+ 0x0F126024,
+ 0x0F122A36,
+ 0x0F12FFFF,
+ 0x0F120808,
+ 0x0F120A01,
+ 0x0F12010A,
+ 0x0F123601,
+ 0x0F12242A,
+ 0x0F123660,
+ 0x0F12FF2A,
+ 0x0F1208FF,
+ 0x0F120008,
+ 0x0F120001,
+ 0x0F120000, /*AFIT 1*/
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1200C0,
+ 0x0F120064,
+ 0x0F120384,
+ 0x0F120051,
+ 0x0F1201F4,
+ 0x0F120070,
+ 0x0F120040,
+ 0x0F1200A0,
+ 0x0F120100,
+ 0x0F120010,
+ 0x0F120060,
+ 0x0F120100,
+ 0x0F121430,
+ 0x0F120201,
+ 0x0F120204,
+ 0x0F122404,
+ 0x0F12031B,
+ 0x0F120103,
+ 0x0F121205,
+ 0x0F12400D,
+ 0x0F120080,
+ 0x0F121980,
+ 0x0F12272E,
+ 0x0F120629,
+ 0x0F120306,
+ 0x0F122003,
+ 0x0F12FF01,
+ 0x0F120404,
+ 0x0F120300,
+ 0x0F12245A,
+ 0x0F121018,
+ 0x0F12000B,
+ 0x0F120B00,
+ 0x0F125A0F,
+ 0x0F120505,
+ 0x0F121802,
+ 0x0F120000,
+ 0x0F122006,
+ 0x0F123828,
+ 0x0F120425,
+ 0x0F120101,
+ 0x0F120800,
+ 0x0F121004,
+ 0x0F124008,
+ 0x0F120540,
+ 0x0F128006,
+ 0x0F120020,
+ 0x0F120000,
+ 0x0F121800,
+ 0x0F120000,
+ 0x0F121E10,
+ 0x0F12000B,
+ 0x0F120607,
+ 0x0F120005,
+ 0x0F120607,
+ 0x0F120405,
+ 0x0F120205,
+ 0x0F120304,
+ 0x0F120409,
+ 0x0F120306,
+ 0x0F120407,
+ 0x0F122204,
+ 0x0F12021C,
+ 0x0F121102,
+ 0x0F120611,
+ 0x0F121A02,
+ 0x0F128018,
+ 0x0F120080,
+ 0x0F120074,
+ 0x0F120180,
+ 0x0F120A0A,
+ 0x0F120101,
+ 0x0F12141D,
+ 0x0F126024,
+ 0x0F121217,
+ 0x0F12FFFF,
+ 0x0F120808,
+ 0x0F120A01,
+ 0x0F12010A,
+ 0x0F122401,
+ 0x0F12241B,
+ 0x0F121E60,
+ 0x0F12FF18,
+ 0x0F1208FF,
+ 0x0F120008,
+ 0x0F120001,
+ 0x0F120000, /*AFIT 2*/
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1200C0,
+ 0x0F120064,
+ 0x0F120384,
+ 0x0F120043,
+ 0x0F1201F4,
+ 0x0F120070,
+ 0x0F120040,
+ 0x0F1200A0,
+ 0x0F120100,
+ 0x0F120010,
+ 0x0F120060,
+ 0x0F120100,
+ 0x0F121430,
+ 0x0F120201,
+ 0x0F120204,
+ 0x0F121B04,
+ 0x0F120312,
+ 0x0F120003,
+ 0x0F120C03,
+ 0x0F122806,
+ 0x0F120060,
+ 0x0F121580,
+ 0x0F122020,
+ 0x0F120620,
+ 0x0F120306,
+ 0x0F122003,
+ 0x0F12FF01,
+ 0x0F120404,
+ 0x0F120300,
+ 0x0F12145A,
+ 0x0F121010,
+ 0x0F12000B,
+ 0x0F120E00,
+ 0x0F125A0F,
+ 0x0F120504,
+ 0x0F121802,
+ 0x0F120000,
+ 0x0F122006,
+ 0x0F123828,
+ 0x0F120428,
+ 0x0F120101,
+ 0x0F128000,
+ 0x0F120A04,
+ 0x0F124008,
+ 0x0F120540,
+ 0x0F128006,
+ 0x0F120020,
+ 0x0F120000,
+ 0x0F121800,
+ 0x0F120000,
+ 0x0F121E10,
+ 0x0F12000B,
+ 0x0F120607,
+ 0x0F120005,
+ 0x0F120607,
+ 0x0F120405,
+ 0x0F120207,
+ 0x0F120304,
+ 0x0F120409,
+ 0x0F120306,
+ 0x0F120407,
+ 0x0F122404,
+ 0x0F120221,
+ 0x0F121202,
+ 0x0F120613,
+ 0x0F121A02,
+ 0x0F128018,
+ 0x0F120080,
+ 0x0F120080,
+ 0x0F120180,
+ 0x0F120A0A,
+ 0x0F120101,
+ 0x0F12121B,
+ 0x0F126024,
+ 0x0F120C0C,
+ 0x0F12FFFF,
+ 0x0F120808,
+ 0x0F120A01,
+ 0x0F12010A,
+ 0x0F121B01,
+ 0x0F122412,
+ 0x0F120C60,
+ 0x0F12FF0C,
+ 0x0F1208FF,
+ 0x0F120008,
+ 0x0F120001,
+ 0x0F120000, /*AFIT 3*/
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1200C0,
+ 0x0F120064,
+ 0x0F120384,
+ 0x0F120032,
+ 0x0F1201F4,
+ 0x0F120070,
+ 0x0F120040,
+ 0x0F1200A0,
+ 0x0F120100,
+ 0x0F120010,
+ 0x0F120060,
+ 0x0F120100,
+ 0x0F121430,
+ 0x0F120201,
+ 0x0F120204,
+ 0x0F121504,
+ 0x0F12030F,
+ 0x0F120003,
+ 0x0F120902,
+ 0x0F122004,
+ 0x0F120050,
+ 0x0F121140,
+ 0x0F12201C,
+ 0x0F120620,
+ 0x0F120306,
+ 0x0F122003,
+ 0x0F12FF01,
+ 0x0F120404,
+ 0x0F120300,
+ 0x0F12145A,
+ 0x0F121010,
+ 0x0F12000B,
+ 0x0F121000,
+ 0x0F125A0F,
+ 0x0F120503,
+ 0x0F121802,
+ 0x0F120000,
+ 0x0F122006,
+ 0x0F123C28,
+ 0x0F12042C,
+ 0x0F120101,
+ 0x0F12FF00,
+ 0x0F120904,
+ 0x0F124008,
+ 0x0F120540,
+ 0x0F128006,
+ 0x0F120020,
+ 0x0F120000,
+ 0x0F121800,
+ 0x0F120000,
+ 0x0F121E10,
+ 0x0F12000B,
+ 0x0F120607,
+ 0x0F120005,
+ 0x0F120607,
+ 0x0F120405,
+ 0x0F120206,
+ 0x0F120304,
+ 0x0F120409,
+ 0x0F120305,
+ 0x0F120406,
+ 0x0F122804,
+ 0x0F120228,
+ 0x0F121402,
+ 0x0F120618,
+ 0x0F121A02,
+ 0x0F128018,
+ 0x0F120080,
+ 0x0F120080,
+ 0x0F120180,
+ 0x0F120A0A,
+ 0x0F120101,
+ 0x0F120F15,
+ 0x0F126024,
+ 0x0F120A0A,
+ 0x0F12FFFF,
+ 0x0F120808,
+ 0x0F120A01,
+ 0x0F12010A,
+ 0x0F121501,
+ 0x0F12240F,
+ 0x0F120A60,
+ 0x0F12FF0A,
+ 0x0F1208FF,
+ 0x0F120008,
+ 0x0F120001,
+ 0x0F120000, /*AFIT 4*/
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F1200C0,
+ 0x0F120064,
+ 0x0F120384,
+ 0x0F120032,
+ 0x0F1201F4,
+ 0x0F120070,
+ 0x0F120040,
+ 0x0F1200A0,
+ 0x0F120100,
+ 0x0F120010,
+ 0x0F120060,
+ 0x0F120100,
+ 0x0F121430,
+ 0x0F120201,
+ 0x0F120204,
+ 0x0F120F04,
+ 0x0F12030C,
+ 0x0F120003,
+ 0x0F120602,
+ 0x0F121803,
+ 0x0F120040,
+ 0x0F120E20,
+ 0x0F122018,
+ 0x0F120620,
+ 0x0F120306,
+ 0x0F122003,
+ 0x0F12FF01,
+ 0x0F120404,
+ 0x0F120200,
+ 0x0F12145A,
+ 0x0F121010,
+ 0x0F12000B,
+ 0x0F121200,
+ 0x0F125A0F,
+ 0x0F120502,
+ 0x0F121802,
+ 0x0F120000,
+ 0x0F122006,
+ 0x0F124028,
+ 0x0F120430,
+ 0x0F120101,
+ 0x0F12FF00,
+ 0x0F120804,
+ 0x0F124008,
+ 0x0F120540,
+ 0x0F128006,
+ 0x0F120020,
+ 0x0F120000,
+ 0x0F121800,
+ 0x0F120000,
+ 0x0F121E10,
+ 0x0F12000B,
+ 0x0F120607,
+ 0x0F120005,
+ 0x0F120607,
+ 0x0F120405,
+ 0x0F120205,
+ 0x0F120304,
+ 0x0F120409,
+ 0x0F120306,
+ 0x0F120407,
+ 0x0F122C04,
+ 0x0F12022C,
+ 0x0F121402,
+ 0x0F120618,
+ 0x0F121A02,
+ 0x0F128018,
+ 0x0F120080,
+ 0x0F120080,
+ 0x0F120180,
+ 0x0F120A0A,
+ 0x0F120101,
+ 0x0F120C0F,
+ 0x0F126024,
+ 0x0F120808,
+ 0x0F12FFFF,
+ 0x0F120808,
+ 0x0F120A01,
+ 0x0F12010A,
+ 0x0F120F01,
+ 0x0F12240C,
+ 0x0F120860,
+ 0x0F12FF08,
+ 0x0F1208FF,
+ 0x0F120008,
+ 0x0F120001,
+ 0x0F1223CE,
+ 0x0F12FDC8,
+ 0x0F12112E,
+ 0x0F1283A5,
+ 0x0F12FE67,
+ 0x0F120000,
+
+ 0x002A0588, /*lt_uInitPostToleranceCnt*/
+ 0x0F120002, /*AE Speed Normal*/
+
+};
+
+static const u32 s5k4ecgx_DTP_init[] = {
+ 0x0028D000,
+ 0x002AB054,
+ 0x0F120001,
+ 0x00287000,
+};
+
+static const u32 s5k4ecgx_DTP_stop[] = {
+ 0x0028D000,
+ 0x002AB054,
+ 0x0F120000,
+ 0x00287000,
+};
+
+static const u32 s5k4ecgx_FPS_Auto[] = {
+ 0x002A02B4,
+ 0x0F120052,
+ 0x002A02BE,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F12029A,
+ 0x0F12014A,
+ 0x002A02D0,
+ 0x0F120000,
+ 0x0F120000,
+ 0x002A0266,
+ 0x0F120000,
+ 0x002A026A,
+ 0x0F120001,
+ 0x002A024E,
+ 0x0F120001,
+ 0x002A0268,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_FPS_5[] = {
+
+};
+
+static const u32 s5k4ecgx_FPS_7[] = {
+ 0x002A02B4,
+ 0x0F120052,
+ 0x002A02BE,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F120535,
+ 0x0F120535,
+ 0x002A02D0,
+ 0x0F120000,
+ 0x0F120000,
+ 0x002A0266,
+ 0x0F120000,
+ 0x002A026A,
+ 0x0F120001,
+ 0x002A024E,
+ 0x0F120001,
+ 0x002A0268,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_FPS_10[] = {
+
+};
+
+static const u32 s5k4ecgx_FPS_15[] = {
+ 0x002A02B4,
+ 0x0F120052,
+ 0x002A02BE,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F12029A,
+ 0x0F12029A,
+ 0x002A02D0,
+ 0x0F120000,
+ 0x0F120000,
+ 0x002A0266,
+ 0x0F120000,
+ 0x002A026A,
+ 0x0F120001,
+ 0x002A024E,
+ 0x0F120001,
+ 0x002A0268,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_FPS_30[] = {
+ 0x002A02B4,
+ 0x0F120052,
+ 0x002A02BE,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F12014D,
+ 0x0F12014D,
+ 0x002A02D0,
+ 0x0F120000,
+ 0x0F120000,
+ 0x002A0266,
+ 0x0F120000,
+ 0x002A026A,
+ 0x0F120001,
+ 0x002A024E,
+ 0x0F120001,
+ 0x002A0268,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_FPS_60[] = {
+
+};
+
+static const u32 s5k4ecgx_FPS_120[] = {
+
+};
+
+static const u32 s5k4ecgx_Effect_Normal[] = {
+ 0x002A023C,
+ 0x0F120000,
+};
+
+static const u32 s5k4ecgx_Effect_Solarization[] = {
+ 0x002A023C,
+ 0x0F120002,
+};
+
+static const u32 s5k4ecgx_Effect_Negative[] = {
+ 0x002A023C,
+ 0x0F120003,
+};
+
+static const u32 s5k4ecgx_Effect_Sepia[] = {
+ 0x002A023C,
+ 0x0F120004,
+};
+
+static const u32 s5k4ecgx_Effect_Black_White[] = {
+ 0x002A023C,
+ 0x0F120001,
+};
+
+
+static const u32 s5k4ecgx_WB_Auto[] = {
+ 0x002A04E6,
+ 0x0F12077F,
+};
+
+static const u32 s5k4ecgx_WB_Sunny[] = {
+ 0x002A04E6,
+ 0x0F120777,
+ 0x002A04BA,
+ 0x0F1205E0,
+ 0x0F120001,
+ 0x0F120400,
+ 0x0F120001,
+ 0x0F120530,
+ 0x0F120001,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_WB_Cloudy[] = {
+ 0x002A04E6,
+ 0x0F120777,
+ 0x002A04BA,
+ 0x0F120710,
+ 0x0F120001,
+ 0x0F120400,
+ 0x0F120001,
+ 0x0F120420,
+ 0x0F120001,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_WB_Tungsten[] = {
+ 0x002A04E6,
+ 0x0F120777,
+ 0x002A04BA,
+ 0x0F120390,
+ 0x0F120001,
+ 0x0F120400,
+ 0x0F120001,
+ 0x0F120920,
+ 0x0F120001,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_WB_Fluorescent[] = {
+ 0x002A04E6,
+ 0x0F120777,
+ 0x002A04BA,
+ 0x0F120505,
+ 0x0F120001,
+ 0x0F120400,
+ 0x0F120001,
+ 0x0F120875,
+ 0x0F120001,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_WDR_on[] = {
+ 0x002A1BEA,
+ 0x0F120000,
+};
+
+static const u32 s5k4ecgx_WDR_off[] = {
+ 0x002A1BEA,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_ISO_Auto[] = {
+ 0x002A0938,
+ 0x0F120000,
+
+ 0x002A0F2A,
+ 0x0F120001,
+ 0x002A04E6,
+ 0x0F12077F,
+
+ 0x002A04D0,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120001,
+ 0x002A06C2,
+ 0x0F120200,
+};
+
+static const u32 s5k4ecgx_ISO_100[] = {
+ 0x002A04E6,
+ 0x0F12065F,
+ 0x002A04D6,
+ 0x0F120000,
+ 0x0F120001,
+
+ 0x002A04D0,
+ 0x0F120001,
+ 0x0F1201A0,
+ 0x0F120001,
+ 0x002A06C2,
+ 0x0F120100,
+
+ 0x002A0938,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_ISO_200[] = {
+ 0x002A04E6,
+ 0x0F12065F,
+ 0x002A04D6,
+ 0x0F120000,
+ 0x0F120001,
+
+ 0x002A04D0,
+ 0x0F120001,
+ 0x0F120340,
+ 0x0F120001,
+ 0x002A06C2,
+ 0x0F120100,
+
+ 0x002A0938,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_ISO_400[] = {
+ 0x002A04E6,
+ 0x0F12065F,
+ 0x002A04D6,
+ 0x0F120000,
+ 0x0F120001,
+
+ 0x002A04D0,
+ 0x0F120001,
+ 0x0F120680,
+ 0x0F120001,
+ 0x002A06C2,
+ 0x0F120100,
+
+ 0x002A0938,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Metering_Matrix[] = {
+ 0x002A1492,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+};
+
+static const u32 s5k4ecgx_Metering_Center[] = {
+ 0x002A1492,
+ 0x0F120000,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120000,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120201,
+ 0x0F120303,
+ 0x0F120303,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120403,
+ 0x0F120304,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120403,
+ 0x0F120304,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120403,
+ 0x0F120304,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120303,
+ 0x0F120303,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120202,
+ 0x0F120202,
+ 0x0F120102,
+};
+
+static const u32 s5k4ecgx_Metering_Spot[] = {
+ 0x002A1492,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F12010F,
+ 0x0F120F01,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F12010F,
+ 0x0F120F01,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+};
+
+static const u32 s5k4ecgx_EV_Minus_4[] = {
+ 0x002A0230,
+ 0x0F12FF30,
+};
+
+static const u32 s5k4ecgx_EV_Minus_3[] = {
+ 0x002A0230,
+ 0x0F12FFA0,
+};
+
+static const u32 s5k4ecgx_EV_Minus_2[] = {
+ 0x002A0230,
+ 0x0F12FFC8,
+};
+
+static const u32 s5k4ecgx_EV_Minus_1[] = {
+ 0x002A0230,
+ 0x0F12FFE0,
+};
+
+static const u32 s5k4ecgx_EV_Default[] = {
+ 0x002A0230,
+ 0x0F120000,
+};
+
+static const u32 s5k4ecgx_EV_Plus_1[] = {
+ 0x002A0230,
+ 0x0F120020,
+};
+
+static const u32 s5k4ecgx_EV_Plus_2[] = {
+ 0x002A0230,
+ 0x0F120038,
+};
+
+static const u32 s5k4ecgx_EV_Plus_3[] = {
+ 0x002A0230,
+ 0x0F120060,
+};
+
+static const u32 s5k4ecgx_EV_Plus_4[] = {
+ 0x002A0230,
+ 0x0F12007F,
+};
+
+static const u32 s5k4ecgx_Contrast_Minus_4[] = {
+ 0x002A0232,
+ 0x0F12FF81,
+};
+
+static const u32 s5k4ecgx_Contrast_Minus_3[] = {
+ 0x002A0232,
+ 0x0F12FFA0,
+};
+
+static const u32 s5k4ecgx_Contrast_Minus_2[] = {
+ 0x002A0232,
+ 0x0F12FFC0,
+};
+
+static const u32 s5k4ecgx_Contrast_Minus_1[] = {
+ 0x002A0232,
+ 0x0F12FFE0,
+};
+
+static const u32 s5k4ecgx_Contrast_Default[] = {
+ 0x002A0232,
+ 0x0F120000,
+};
+
+static const u32 s5k4ecgx_Contrast_Plus_1[] = {
+ 0x002A0232,
+ 0x0F120020,
+};
+
+static const u32 s5k4ecgx_Contrast_Plus_2[] = {
+ 0x002A0232,
+ 0x0F120040,
+};
+
+static const u32 s5k4ecgx_Contrast_Plus_3[] = {
+ 0x002A0232,
+ 0x0F120060,
+};
+
+static const u32 s5k4ecgx_Contrast_Plus_4[] = {
+ 0x002A0232,
+ 0x0F12007F,
+};
+
+static const u32 s5k4ecgx_Sharpness_Minus_3[] = {
+ 0x002A0A28,
+ 0x0F120000,
+ 0x002A0ADE,
+ 0x0F120000,
+ 0x002A0B94,
+ 0x0F120000,
+ 0x002A0C4A,
+ 0x0F120000,
+ 0x002A0D00,
+ 0x0F120000,
+};
+
+static const u32 s5k4ecgx_Sharpness_Minus_2[] = {
+ 0x002A0A28,
+ 0x0F122010,
+ 0x002A0ADE,
+ 0x0F122010,
+ 0x002A0B94,
+ 0x0F122010,
+ 0x002A0C4A,
+ 0x0F122010,
+ 0x002A0D00,
+ 0x0F122010,
+};
+
+static const u32 s5k4ecgx_Sharpness_Minus_1[] = {
+ 0x002A0A28,
+ 0x0F124020,
+ 0x002A0ADE,
+ 0x0F124020,
+ 0x002A0B94,
+ 0x0F124020,
+ 0x002A0C4A,
+ 0x0F124020,
+ 0x002A0D00,
+ 0x0F124020,
+};
+
+static const u32 s5k4ecgx_Sharpness_Default[] = {
+ 0x002A0A28,
+ 0x0F126024,
+ 0x002A0ADE,
+ 0x0F126024,
+ 0x002A0B94,
+ 0x0F126024,
+ 0x002A0C4A,
+ 0x0F126024,
+ 0x002A0D00,
+ 0x0F126024,
+};
+
+static const u32 s5k4ecgx_Sharpness_Plus_1[] = {
+ 0x002A0A28,
+ 0x0F128040,
+ 0x002A0ADE,
+ 0x0F128040,
+ 0x002A0B94,
+ 0x0F128040,
+ 0x002A0C4A,
+ 0x0F128040,
+ 0x002A0D00,
+ 0x0F128040,
+};
+
+static const u32 s5k4ecgx_Sharpness_Plus_2[] = {
+ 0x002A0A28,
+ 0x0F12A060,
+ 0x002A0ADE,
+ 0x0F12A060,
+ 0x002A0B94,
+ 0x0F12A060,
+ 0x002A0C4A,
+ 0x0F12A060,
+ 0x002A0D00,
+ 0x0F12A060,
+};
+
+static const u32 s5k4ecgx_Sharpness_Plus_3[] = {
+ 0x002A0A28,
+ 0x0F12C080,
+ 0x002A0ADE,
+ 0x0F12C080,
+ 0x002A0B94,
+ 0x0F12C080,
+ 0x002A0C4A,
+ 0x0F12C080,
+ 0x002A0D00,
+ 0x0F12C080,
+};
+
+static const u32 s5k4ecgx_Saturation_Minus_2[] = {
+ 0x002A0234,
+ 0x0F12FF81,
+};
+
+static const u32 s5k4ecgx_Saturation_Minus_1[] = {
+ 0x002A0234,
+ 0x0F12FFC0,
+};
+
+static const u32 s5k4ecgx_Saturation_Default[] = {
+ 0x002A0234,
+ 0x0F120000,
+};
+
+static const u32 s5k4ecgx_Saturation_Plus_1[] = {
+ 0x002A0234,
+ 0x0F120040,
+};
+
+static const u32 s5k4ecgx_Saturation_Plus_2[] = {
+ 0x002A0234,
+ 0x0F12007F,
+};
+
+static const u32 s5k4ecgx_Jpeg_Quality_High[] = {
+ 0x002A0478,
+ 0x0F12005F,
+ 0x0F12005F,
+};
+
+static const u32 s5k4ecgx_Jpeg_Quality_Normal[] = {
+ 0x002A0478,
+ 0x0F12005A,
+ 0x0F12005A,
+};
+
+static const u32 s5k4ecgx_Jpeg_Quality_Low[] = {
+ 0x002A0478,
+ 0x0F120054,
+ 0x0F120054,
+};
+
+static const u32 s5k4ecgx_Scene_Default[] = {
+ 0x002A1492,
+ 0x0F120000,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120000,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120201,
+ 0x0F120303,
+ 0x0F120303,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120403,
+ 0x0F120304,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120403,
+ 0x0F120304,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120403,
+ 0x0F120304,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120303,
+ 0x0F120303,
+ 0x0F120102,
+ 0x0F120201,
+ 0x0F120202,
+ 0x0F120202,
+ 0x0F120102,
+
+ 0x002A0938,
+ 0x0F120000,
+
+ 0x002A06B8,
+ 0x0F12452C,
+ 0x0F12000C,
+
+ 0x002A0F2A,
+ 0x0F120001,
+ 0x002A0F30,
+ 0x0F120001,
+ 0x002A04E6,
+ 0x0F12077F,
+
+ 0x002A04D0,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120001,
+ 0x002A06C2,
+ 0x0F120200,
+
+ 0x002A2C66,
+ 0x0F120001,
+
+ 0x002A1484,
+ 0x0F12003C,
+ 0x002A148A,
+ 0x0F12000F,
+ 0x002A058C,
+ 0x0F123520,
+ 0x0F120000,
+ 0x0F12C350,
+ 0x0F120000,
+ 0x0F123520,
+ 0x0F120000,
+ 0x0F12C350,
+ 0x0F120000,
+ 0x0F120470,
+ 0x0F120C00,
+ 0x0F120100,
+ 0x0F121000,
+
+ 0x002A0544,
+ 0x0F120111,
+ 0x0F1200EF,
+
+ 0x002A0608,
+ 0x0F120001,
+ 0x0F120001,
+
+ 0x002A0A28,
+ 0x0F126024,
+ 0x002A0ADE,
+ 0x0F126024,
+ 0x002A0B94,
+ 0x0F126024,
+ 0x002A0C4A,
+ 0x0F126024,
+ 0x002A0D00,
+ 0x0F126024,
+
+ 0x002A0234,
+ 0x0F120000,
+
+ 0x002A0638,
+ 0x0F120001,
+ 0x0F120000,
+ 0x002A063C,
+ 0x0F120A3C,
+ 0x0F120000,
+ 0x002A0640,
+ 0x0F120D05,
+ 0x0F120000,
+ 0x002A0644,
+ 0x0F123408,
+ 0x0F120000,
+ 0x002A0648,
+ 0x0F123408,
+ 0x0F120000,
+ 0x002A064C,
+ 0x0F126810,
+ 0x0F120000,
+ 0x002A0650,
+ 0x0F128214,
+ 0x0F120000,
+ 0x002A0654,
+ 0x0F12C350,
+ 0x0F120000,
+ 0x002A0658,
+ 0x0F12C350,
+ 0x0F120000,
+ 0x002A065C,
+ 0x0F12C350,
+ 0x0F120000,
+
+ 0x002A02C2,
+ 0x0F12029A, /*#REG_0TC_PCFG_usMaxFrTimeMsecMult10*/
+ 0x0F12014A, /*#REG_0TC_PCFG_usMinFrTimeMsecMult10*/
+
+ 0x002A03B4,
+ 0x0F120535,
+ 0x0F12029A,
+
+ 0x002A0266,
+ 0x0F120000,
+ 0x002A026A,
+ 0x0F120001,
+ 0x002A024E,
+ 0x0F120001,
+ 0x002A0268,
+ 0x0F120001,
+ 0x002A0270,
+ 0x0F120001,
+ 0x002A023E,
+ 0x0F120001,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Scene_Portrait[] = {
+ 0x002A0A28,
+ 0x0F122010,
+ 0x002A0ADE,
+ 0x0F122010,
+ 0x002A0B94,
+ 0x0F122010,
+ 0x002A0C4A,
+ 0x0F122010,
+ 0x002A0D00,
+ 0x0F122010,
+};
+
+static const u32 s5k4ecgx_Scene_Nightshot[] = {
+ 0x002A06B8,
+ 0x0F12FFFF,
+ 0x0F1200FF,
+
+ 0x002A0608,
+ 0x0F120001, /*#lt_ExpGain_uSubsamplingmode*/
+ 0x0F120001, /*#lt_ExpGain_uNonSubsampling*/
+ 0x0F120900, /*#lt_ExpGain_ExpCurveGainMaxStr*/
+
+ 0x002A0658,
+ 0x0F12D090,
+ 0x0F120007,
+ 0x0F12D090,
+ 0x0F120007,
+
+ 0x002A03B4,
+ 0x0F121388,
+ 0x0F121388,
+ 0x002A02C2,
+ 0x0F1209C4,
+ 0x0F12014A,
+ 0x002A0266,
+ 0x0F120000,
+ 0x002A026A,
+ 0x0F120001,
+ 0x002A024E,
+ 0x0F120001,
+ 0x002A0268,
+ 0x0F120001,
+ 0x002A0270,
+ 0x0F120001,
+ 0x002A023E,
+ 0x0F120001,
+ 0x0F120001,
+
+ 0x002A0A1E,
+ 0x0F121580,
+};
+
+static const u32 s5k4ecgx_Scene_Backlight[] = {
+ 0x002A1492,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F12010F,
+ 0x0F120F01,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F12010F,
+ 0x0F120F01,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120000,
+};
+
+static const u32 s5k4ecgx_Scene_Landscape[] = {
+ 0x002A1492,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x0F120101,
+ 0x002A0A28,
+ 0x0F12E082,
+ 0x002A0ADE,
+ 0x0F12E082,
+ 0x002A0B94,
+ 0x0F12E082,
+ 0x002A0C4A,
+ 0x0F12E082,
+ 0x002A0D00,
+ 0x0F12E082,
+ 0x002A0234,
+ 0x0F120030,
+};
+
+static const u32 s5k4ecgx_Scene_Sports[] = {
+ 0x002A0608,
+ 0x0F120000,
+ 0x0F120000,
+
+ 0x002A058C,
+ 0x0F123520,
+ 0x0F120000,
+ 0x0F123520,
+ 0x0F120000,
+ 0x0F123520,
+ 0x0F120000,
+ 0x0F123520,
+ 0x0F120000,
+ 0x0F120200,
+ 0x0F120200,
+ 0x0F120200,
+ 0x0F120200,
+
+ 0x002A0266,
+ 0x0F120000,
+ 0x002A026A,
+ 0x0F120001,
+ 0x002A024E,
+ 0x0F120001,
+ 0x002A0268,
+ 0x0F120001,
+ 0x002A0270,
+ 0x0F120001,
+ 0x002A023E,
+ 0x0F120001,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Scene_Party_Indoor[] = {
+ 0x002A04E6,
+ 0x0F12065F,
+ 0x002A04D6,
+ 0x0F120000,
+ 0x0F120001,
+
+ 0x002A04D0,
+ 0x0F120001,
+ 0x0F120340,
+ 0x0F120001,
+ 0x002A06C2,
+ 0x0F120100,
+
+ 0x002A0938,
+ 0x0F120001,
+
+ 0x002A0234,
+ 0x0F120030,
+};
+
+static const u32 s5k4ecgx_Scene_Beach_Snow[] = {
+ 0x002A1484,
+ 0x0F120045, /*#TVAR_ae_BrAve*/
+ 0x002A04E6,
+ 0x0F12065F,
+ 0x002A04D6,
+ 0x0F120000,
+ 0x0F120001,
+ 0x002A04D0,
+ 0x0F120001,
+ 0x0F1200D0,
+ 0x0F120001,
+ 0x002A06C2,
+ 0x0F120100,
+
+ 0x002A0938,
+ 0x0F120001,
+
+ 0x002A0234,
+ 0x0F120030,
+};
+
+static const u32 s5k4ecgx_Scene_Sunset[] = {
+ 0x002A04E6,
+ 0x0F120777,
+
+ 0x002A04BA,
+ 0x0F1205E0,
+ 0x0F120001,
+ 0x0F120400,
+ 0x0F120001,
+ 0x0F120530,
+ 0x0F120001,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Scene_Duskdawn[] = {
+ 0x002A04E6,
+ 0x0F120777,
+ 0x002A04BA,
+ 0x0F120505,
+ 0x0F120001,
+ 0x0F120400,
+ 0x0F120001,
+ 0x0F120875,
+ 0x0F120001,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Scene_Fall_Color[] = {
+ 0x002A0234,
+ 0x0F120060,
+};
+
+static const u32 s5k4ecgx_Scene_Fireworks[] = {
+ 0x002A0638,
+ 0x0F120001,
+ 0x0F120000,
+ 0x002A063C,
+ 0x0F121478,
+ 0x0F120000,
+ 0x002A0640,
+ 0x0F121A0A,
+ 0x0F120000,
+ 0x002A0644,
+ 0x0F126810,
+ 0x0F120000,
+ 0x002A0648,
+ 0x0F126810,
+ 0x0F120000,
+ 0x002A064C,
+ 0x0F12D020,
+ 0x0F120000,
+ 0x002A0650,
+ 0x0F120428,
+ 0x0F120001,
+ 0x002A0654,
+ 0x0F121A80,
+ 0x0F120006,
+ 0x002A0658,
+ 0x0F121A80,
+ 0x0F120006,
+ 0x002A065C,
+ 0x0F121A80,
+ 0x0F120006,
+
+ 0x002A03B4,
+ 0x0F122710,
+ 0x0F122710,
+
+ 0x002A0266,
+ 0x0F120000,
+ 0x002A026A,
+ 0x0F120001,
+ 0x002A024E,
+ 0x0F120001,
+ 0x002A0268,
+ 0x0F120001,
+ 0x002A0270,
+ 0x0F120001,
+ 0x002A023E,
+ 0x0F120001,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Scene_Text[] = {
+ 0x002A0A28,
+ 0x0F12A060,
+ 0x002A0ADE,
+ 0x0F12A060,
+ 0x002A0B94,
+ 0x0F12A060,
+ 0x002A0C4A,
+ 0x0F12A060,
+ 0x002A0D00,
+ 0x0F12A060,
+};
+
+static const u32 s5k4ecgx_Scene_Candle_Light[] = {
+ 0x002A04E6,
+ 0x0F120777,
+ 0x002A04BA,
+ 0x0F1205E0,
+ 0x0F120001,
+ 0x0F120400,
+ 0x0F120001,
+ 0x0F120530,
+ 0x0F120001,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Night_Capture[] = {
+ 0x002A0608,
+ 0x0F120001, /*#lt_ExpGain_uSubsamplingmode*/
+ 0x0F120001, /*#lt_ExpGain_uNonSubsampling*/
+ 0x0F120900, /*#lt_ExpGain_ExpCurveGainMaxStr*/
+};
+
+static const u32 s5k4ecgx_AF_Return_Macro_pos[] = {
+ 0x002A15E8,
+ 0x0F120018,
+ 0x0F12002A,
+ 0x0F120030,
+ 0x0F120036,
+ 0x0F12003C,
+ 0x0F120042,
+ 0x0F120048,
+ 0x0F12004E,
+ 0x0F120054,
+ 0x0F12005A,
+ 0x0F120060,
+ 0x0F120066,
+ 0x0F12006C,
+ 0x0F120072,
+ 0x0F120078,
+ 0x0F12007E,
+ 0x0F120084,
+ 0x0F12008A,
+ 0x0F120090,
+ 0x0F120096,
+ 0x0F12009C,
+ 0x0F1200A2,
+ 0x0F1200A8,
+ 0x0F1200AE,
+ 0x0F1200B4,
+ 0x0F1200BA,
+};
+
+static const u32 s5k4ecgx_AF_Normal_mode_1[] = {
+ 0x002A028E,
+ 0x0F120000,
+};
+
+static const u32 s5k4ecgx_AF_Normal_mode_2[] = {
+ 0x002A028C,
+ 0x0F120004,
+};
+
+static const u32 s5k4ecgx_AF_Normal_mode_3[] = {
+ 0x002A1648,
+ 0x0F129002,
+};
+
+static const u32 s5k4ecgx_AF_Macro_mode_1[] = {
+ 0x002A028E,
+ 0x0F1200D0,
+};
+
+static const u32 s5k4ecgx_AF_Macro_mode_2[] = {
+ 0x002A028C,
+ 0x0F120004,
+};
+
+static const u32 s5k4ecgx_AF_Macro_mode_3[] = {
+ 0x002A1648,
+ 0x0F129042,
+ 0x002A15DA,
+ 0x0F121800,
+};
+
+static const u32 s5k4ecgx_AF_Low_Light_Mode_On[] = {
+ 0x002A15DA,
+ 0x0F120C00,
+
+ 0x002A15E8,
+ 0x0F12000C,
+ 0x0F12002A,
+ 0x0F120033,
+ 0x0F12003C,
+ 0x0F120045,
+ 0x0F12004E,
+ 0x0F120057,
+ 0x0F120063,
+ 0x0F12006F,
+ 0x0F12007B,
+ 0x0F120087,
+ 0x0F120093,
+ 0x0F1200A2,
+ 0x0F1200B1,
+};
+
+static const u32 s5k4ecgx_AF_Low_Light_Mode_Off[] = {
+ 0x002A15DA,
+ 0x0F121800,
+
+ 0x002A15E8,
+ 0x0F120018,
+ 0x0F12002A,
+ 0x0F120030,
+ 0x0F120036,
+ 0x0F12003C,
+ 0x0F120042,
+ 0x0F120048,
+ 0x0F12004E,
+ 0x0F120054,
+ 0x0F12005A,
+ 0x0F120060,
+ 0x0F120066,
+ 0x0F12006C,
+ 0x0F120072,
+ 0x0F120078,
+ 0x0F12007E,
+ 0x0F120084,
+ 0x0F12008A,
+ 0x0F120090,
+ 0x0F120096,
+ 0x0F12009C,
+ 0x0F1200A2,
+ 0x0F1200A8,
+ 0x0F1200AE,
+ 0x0F1200B4,
+ 0x0F1200BA,
+};
+
+static const u32 s5k4ecgx_Single_AF_Start[] = {
+ 0x002A028C,
+ 0x0F120005,
+};
+
+static const u32 s5k4ecgx_Single_AF_Off_1[] = {
+ 0x002A028E,
+ 0x0F120000,
+};
+
+static const u32 s5k4ecgx_Single_AF_Off_2[] = {
+ 0x002A028C,
+ 0x0F120004,
+};
+
+static const u32 s5k4ecgx_Single_AF_Off_3[] = {
+
+};
+
+
+static const u32 s5k4ecgx_Face_Detection_On[] = {
+ 0x002A0294,
+ 0x0F120100,
+ 0x0F1200E3,
+ 0x0F120200,
+ 0x0F120238,
+ 0x0F1201C6,
+ 0x0F120166,
+ 0x0F120074,
+ 0x0F120132,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Face_Detection_Off[] = {
+ 0x002A0294,
+ 0x0F120100,
+ 0x0F1200E3,
+ 0x0F120200,
+ 0x0F120238,
+ 0x0F1201C6,
+ 0x0F120166,
+ 0x0F120074,
+ 0x0F120132,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Low_Cap_On[] = {
+ 0x002A06B8,
+ 0x0F12FFFF,
+ 0x0F1200FF, /*#lt_uMaxLei*/
+
+ 0x002A0A1A,
+ 0x0F124A18, /*#Gamma linearity*/
+
+
+ 0x002A0608,
+ 0x0F120001, /*#lt_ExpGain_uSubsamplingmode*/
+ 0x0F120001, /*#lt_ExpGain_uNonSubsampling*/
+ 0x0F120850, /*#lt_ExpGain_ExpCurveGainMaxStr*/
+
+ 0x002A0938,
+ 0x0F120001,
+ 0x0F120012, /*#SARR_uNormBrInDoor_0_*/
+ 0x0F120022, /*#SARR_uNormBrInDoor_1_*/
+ 0x0F120384, /*#SARR_uNormBrInDoor_2_*/
+ 0x0F1207D0, /*#SARR_uNormBrInDoor_3_*/
+ 0x0F121388, /*#SARR_uNormBrInDoor_4_*/
+};
+
+static const u32 s5k4ecgx_Low_Cap_Off[] = {
+ 0x002A06B8,
+ 0x0F12452C,
+ 0x0F12000C, /*#lt_uMaxLei*/
+
+ 0x002A0A1A,
+ 0x0F128F18, /*#Gamma linearity*/
+
+
+ 0x002A0608,
+ 0x0F120001, /*#lt_ExpGain_uSubsamplingmode*/
+ 0x0F120001, /*#lt_ExpGain_uNonSubsampling*/
+ 0x0F120C00, /*#lt_ExpGain_ExpCurveGainMaxStr*/
+
+ 0x002A0938,
+ 0x0F120000,
+ 0x0F120014, /*#SARR_uNormBrInDoor_0_*/
+ 0x0F1200D2, /*#SARR_uNormBrInDoor_1_*/
+ 0x0F120384, /*#SARR_uNormBrInDoor_2_*/
+ 0x0F1207D0, /*#SARR_uNormBrInDoor_3_*/
+ 0x0F121388, /*#SARR_uNormBrInDoor_4_*/
+};
+
+/* restores crop settings to full resolution */
+static const u32 s5k4ecgx_Reset_Crop[] = {
+ 0x002A0250,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120010,
+ 0x0F12000C,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120010,
+ 0x0F12000C,
+ 0x002A0494,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120000,
+ 0x0F120000,
+
+ 0x002A0262,
+ 0x0F120001,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Capture_Start[] = {
+ 0x002A0A1E,
+ 0x0F120050,
+
+ 0x002A0AD4,
+ 0x0F120074,
+
+ 0x002A0608,
+ 0x0F120001, /*#lt_ExpGain_uSubsamplingmode*/
+ 0x0F120001, /*#lt_ExpGain_uNonSubsampling*/
+ 0x0F120850, /*#lt_ExpGain_ExpCurveGainMaxStr*/
+
+ 0x002A0242,
+ 0x0F120001,
+
+ 0x002A024E,
+ 0x0F120001,
+
+ 0x002A0244,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Preview_Return[] = {
+ 0x002A0A1E,
+ 0x0F120028,
+
+ 0x002A0AD4,
+ 0x0F12003C,
+
+ 0x002A0608,
+ 0x0F120001, /*#lt_ExpGain_uSubsamplingmode*/
+ 0x0F120001, /*#lt_ExpGain_uNonSubsampling*/
+ 0x0F120C00, /*#lt_ExpGain_ExpCurveGainMaxStr*/
+
+ 0x002A05D0,
+ 0x0F120000,
+
+ 0x002A0972,
+ 0x0F120000,
+
+ 0x002A0242,
+ 0x0F120000,
+
+ 0x002A024E,
+ 0x0F120001,
+
+ 0x002A0244,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Flash_init[] = {
+ 0x002A0484,
+ 0x0F120002, /* capture flash on */
+
+ 0x002A183A,
+ 0x0F120001, /* one frame AE*/
+
+ 0x002A17F6,
+ 0x0F120258, /* AWB R point */
+ 0x0F120248, /* AWB B point */
+
+ 0x002A1840,
+ 0x0F120001, /* Fls AE tune start */
+
+ 0x0F120100, /* fls_afl_FlsAFIn Rin */
+ 0x0F120120,
+ 0x0F120180,
+ 0x0F120200,
+ 0x0F120400,
+ 0x0F120800,
+ 0x0F120A00,
+ 0x0F121000,
+
+ 0x0F120100, /* fls_afl_FlsAFOut Rout */
+ 0x0F1200A0,
+ 0x0F120090,
+ 0x0F120080,
+ 0x0F120070,
+ 0x0F120045,
+ 0x0F120030,
+ 0x0F120010,
+
+ 0x002A1884,
+ 0x0F120100, /* fls_afl_FlsNBOut flash NB default */
+ 0x0F120100,
+ 0x0F120100,
+ 0x0F120100,
+ 0x0F120100,
+ 0x0F120100,
+ 0x0F120100,
+ 0x0F120100,
+
+ 0x002A1826,
+
+ 0x0F120100, /* fls_afl_FlashWP_Weight flash NB default */
+ 0x0F1200C0,
+ 0x0F120080,
+ 0x0F12000A,
+ 0x0F120000,
+
+ 0x0F120030, /* fls_afl_FlashWP_Weight flash NB default */
+ 0x0F120040,
+ 0x0F120048,
+ 0x0F120050,
+ 0x0F120060,
+
+ 0x002A4784,
+ 0x0F1200A0, /* TNP_Regs_FlsWeightRIn weight tune start in*/
+ 0x0F1200C0,
+ 0x0F1200D0,
+ 0x0F120100,
+ 0x0F120200,
+ 0x0F120300,
+
+ 0x0F120088, /* TNP_Regs_FlsWeightROut weight tune start out*/
+ 0x0F1200B0,
+ 0x0F1200C0,
+ 0x0F120100,
+ 0x0F120200,
+ 0x0F120300,
+
+ 0x002A479C,
+
+ 0x0F120120, /*Fls BRIn */
+ 0x0F120150,
+ 0x0F120200,
+
+ 0x0F12003C, /* Fls BROut*/
+ 0x0F12003B,
+ 0x0F120030,
+
+};
+
+static const u32 s5k4ecgx_Pre_Flash_Start[] = {
+ 0x002A0588, /* set AE speed to fast */
+ 0x0F120000,
+
+ 0x002A17FC, /* fls_afl_FlashWP_Weight_0_ Pre_Flash_Start */
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Pre_Flash_End[] = {
+ 0x002A0588, /* set AE speed to normal */
+ 0x0F120002,
+
+ 0x002A1800, /* fls_afl_FlashWP_Weight_0_ Pre_Flash_end */
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Flash_Start[] = {
+ 0x002A17E8, /* fls_afl_FlashMode : Flash alg start */
+ 0x0F120001,
+
+ 0x002A180C, /* fls_afl_FlashWP_Weight_4_ flash br avg */
+ 0x0F120027,
+};
+
+static const u32 s5k4ecgx_Flash_End[] = {
+ 0x002A17E8, /* fls_afl_FlashMode Flash alg end */
+ 0x0F120000,
+};
+
+/* 2560 x 1920 */
+static const u32 s5k4ecgx_5M_Capture[] = {
+ 0x002A0398,
+ 0x0F120A00, /* #REG_0TC_CCFG_usWidth */
+ 0x0F120780, /* #REG_0TC_CCFG_usHeight */
+ 0x0F120009,
+
+ 0x002A03B2,
+ 0x0F120002,
+ 0x002A03B0,
+ 0x0F120002,
+ 0x002A0270,
+ 0x0F120001,
+};
+/* 2048 x 1536 */
+static const u32 s5k4ecgx_3M_Capture[] = {
+ 0x002A0398,
+ 0x0F120800, /* REG_0TC_CCFG_usWidth */
+ 0x0F120600, /* REG_0TC_CCFG_usWidth */
+ 0x0F120009, /* REG_0TC_CCFG_Format */
+
+ 0x002A03B2,
+ 0x0F120002, /* REG_0TC_CCFG_FrRateQualityType */
+ 0x002A03B0,
+ 0x0F120002, /* REG_0TC_CCFG_usFrTimeType */
+ 0x002A024E,
+ 0x0F120001, /* REG_TC_GP_NewConfigSync */
+ 0x002A0270,
+ 0x0F120001, /* REG_TC_GP_CapConfigChanged */
+};
+/* 1600 x 1200 */
+static const u32 s5k4ecgx_2M_Capture[] = {
+ 0x002A0398,
+ 0x0F120640, /* #REG_0TC_CCFG_usWidth */
+ 0x0F1204B0, /* #REG_0TC_CCFG_usHeight */
+ 0x0F120009,
+ 0x002A03B2,
+ 0x0F120002,
+ 0x002A03B0,
+ 0x0F120002,
+ 0x002A024E,
+ 0x0F120001,
+ 0x002A0270,
+ 0x0F120001,
+};
+/* 1280 x 960 */
+static const u32 s5k4ecgx_1M_Capture[] = {
+ 0x002A0398,
+ 0x0F120500, /* #REG_0TC_CCFG_usWidth */
+ 0x0F1203C0, /* #REG_0TC_CCFG_usHeight */
+ 0x0F120009,
+ 0x002A03B2,
+ 0x0F120002,
+ 0x002A03B0,
+ 0x0F120002,
+ 0x002A024E,
+ 0x0F120001,
+ 0x002A0270,
+ 0x0F120001,
+};
+/* 640 x 480 */
+static const u32 s5k4ecgx_VGA_Capture[] = {
+ 0x002A0398,
+ 0x0F120280, /* #REG_0TC_CCFG_usWidth */
+ 0x0F1201E0, /* #REG_0TC_CCFG_usHeight */
+ 0x0F120009,
+ 0x002A03B2,
+ 0x0F120002,
+ 0x002A03B0,
+ 0x0F120002,
+ 0x002A024E,
+ 0x0F120001,
+ 0x002A0270,
+ 0x0F120001,
+};
+/* 720 x 480 */
+static const u32 s5k4ecgx_720_Preview[] = {
+ 0x002A0250,
+ 0x0F120A00,
+ 0x0F1206A8,
+ 0x0F120010,
+ 0x0F120078,
+ 0x0F120A00,
+ 0x0F1206A8,
+ 0x0F120010,
+ 0x0F120078,
+ 0x002A0494,
+ 0x0F120A00,
+ 0x0F1206A8,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120A00,
+ 0x0F1206A8,
+ 0x0F120000,
+ 0x0F120000,
+
+ 0x002A0262,
+ 0x0F120001, /* #REG_TC_GP_bUseReqInputInPre */
+ 0x002A0A1E,
+ 0x0F120028,
+ 0x002A0AD4,
+ 0x0F12003C,
+
+ 0x002A02A6,
+ 0x0F1202D0,
+ 0x0F1201E0,
+ 0x0F120005,
+ 0x002A02B4,
+ 0x0F120052,
+ 0x002A02BE,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F12029A,
+ 0x0F12014D,
+ 0x002A02D0,
+ 0x0F120000,
+ 0x0F120000,
+ 0x002A0266,
+ 0x0F120000,
+ 0x002A026A,
+ 0x0F120001,
+ 0x002A024E,
+ 0x0F120001, /* #REG_TC_GP_NewConfigSync */
+ 0x002A0268,
+ 0x0F120001, /* #REG_TC_GP_CapConfigChanged */
+};
+/* 640 x 480 */
+static const u32 s5k4ecgx_640_Preview[] = {
+ 0x002A0250,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120010,
+ 0x0F12000C,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120010,
+ 0x0F12000C,
+ 0x002A0494,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120A00,
+ 0x0F120780,
+ 0x0F120000,
+ 0x0F120000,
+
+ 0x002A0262,
+ 0x0F120001, /* #REG_TC_GP_bUseReqInputInPre */
+ 0x002A0A1E,
+ 0x0F120028,
+ 0x002A0AD4,
+ 0x0F12003C,
+
+ 0x002A02A6,
+ 0x0F120280,
+ 0x0F1201E0,
+ 0x0F120005,
+ 0x002A02B4,
+ 0x0F120052,
+ 0x002A02BE,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F12029A,
+ 0x0F12014A,
+ 0x002A02D0,
+ 0x0F120000,
+ 0x0F120000,
+ 0x002A0266,
+ 0x0F120000,
+ 0x002A026A,
+ 0x0F120001,
+ 0x002A024E,
+ 0x0F120001, /* #REG_TC_GP_NewConfigSync */
+ 0x002A0268,
+ 0x0F120001, /* #REG_TC_GP_CapConfigChanged */
+};
+/* 352 x 288 */
+static const u32 s5k4ecgx_352_Preview[] = {
+ 0x002A0250,
+ 0x0F120928,
+ 0x0F120780,
+ 0x0F12007C,
+ 0x0F12000C,
+ 0x0F120928,
+ 0x0F120780,
+ 0x0F12007C,
+ 0x0F12000C,
+ 0x002A0494,
+ 0x0F120928,
+ 0x0F120780,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120928,
+ 0x0F120780,
+ 0x0F120000,
+ 0x0F120000,
+
+ 0x002A0262,
+ 0x0F120001, /* #REG_TC_GP_bUseReqInputInPre */
+ 0x002A0A1E,
+ 0x0F120028,
+ 0x002A0AD4,
+ 0x0F12003C,
+
+ 0x002A02A6,
+ 0x0F120160,
+ 0x0F120120,
+ 0x0F120005,
+ 0x002A02B4,
+ 0x0F120052,
+ 0x002A02BE,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F12029A,
+ 0x0F12014D,
+ 0x002A02D0,
+ 0x0F120000,
+ 0x0F120000,
+ 0x002A0266,
+ 0x0F120000,
+ 0x002A026A,
+ 0x0F120001,
+ 0x002A024E,
+ 0x0F120001, /* #REG_TC_GP_NewConfigSync */
+ 0x002A0268,
+ 0x0F120001, /* #REG_TC_GP_CapConfigChanged */
+};
+/* 176 x 144 */
+static const u32 s5k4ecgx_176_Preview[] = {
+ 0x002A0250,
+ 0x0F120928,
+ 0x0F120780,
+ 0x0F12007C,
+ 0x0F12000C,
+ 0x0F120928,
+ 0x0F120780,
+ 0x0F12007C,
+ 0x0F12000C,
+ 0x002A0494,
+ 0x0F120928,
+ 0x0F120780,
+ 0x0F120000,
+ 0x0F120000,
+ 0x0F120928,
+ 0x0F120780,
+ 0x0F120000,
+ 0x0F120000,
+
+ 0x002A0262,
+ 0x0F120001, /* #REG_TC_GP_bUseReqInputInPre */
+ 0x002A0A1E,
+ 0x0F120028,
+ 0x002A0AD4,
+ 0x0F12003C,
+
+ 0x002A02A6,
+ 0x0F1200B0,
+ 0x0F120090,
+ 0x0F120005,
+ 0x002A02B4,
+ 0x0F120052,
+ 0x002A02BE,
+ 0x0F120000,
+ 0x0F120001,
+ 0x0F12029A,
+ 0x0F12014D,
+ 0x002A02D0,
+ 0x0F120000,
+ 0x0F120000,
+ 0x002A0266,
+ 0x0F120000,
+ 0x002A026A,
+ 0x0F120001,
+ 0x002A024E,
+ 0x0F120001, /* #REG_TC_GP_NewConfigSync */
+ 0x002A0268,
+ 0x0F120001, /* #REG_TC_GP_CapConfigChanged */
+};
+
+static const u32 s5k4ecgx_AE_AWB_Lock_On[] = {
+ 0x002A2C5E,
+ 0x0F120000,
+};
+
+static const u32 s5k4ecgx_AE_AWB_Lock_Off[] = {
+ 0x002A2C5E,
+ 0x0F120001,
+};
+
+static const u32 s5k4ecgx_Get_AE_Stable_Status[] = {
+ 0x002E2C74,
+};
+
+static const u32 s5k4ecgx_Get_Light_Level[] = {
+ 0x002C7000,
+ 0x002E2C18,
+};
+
+static const u32 s5k4ecgx_get_1st_af_search_status[] = {
+ 0x002E2EEE,
+};
+
+static const u32 s5k4ecgx_get_2nd_af_search_status[] = {
+ 0x002E2207,
+};
+
+static const u32 s5k4ecgx_get_capture_status[] = {
+ 0x002E0530,
+};
+
+static const u32 s5k4ecgx_get_esd_status[] = {
+ 0xFCFCD000,
+ 0x002CD000,
+ 0x002E0060,
+};
+
+static const u32 s5k4ecgx_get_iso_reg[] = {
+ 0x002C7000,
+ 0x002E2BC4,
+};
+
+static const u32 s5k4ecgx_get_shutterspeed_reg[] = {
+ 0x002C7000,
+ 0x002E2BC0,
+};
+
+#endif /* __S5K4ECGX_REGS_1_0_H__ */
diff --git a/drivers/media/video/s5ka3dfx.c b/drivers/media/video/s5ka3dfx.c
new file mode 100755
index 0000000..e4ca5f0
--- /dev/null
+++ b/drivers/media/video/s5ka3dfx.c
@@ -0,0 +1,1229 @@
+/*
+ * Driver for S5KA3DFX (UXGA camera) from Samsung Electronics
+ *
+ * 1/4" 2.0Mp CMOS Image Sensor SoC with an Embedded Image Processor
+ *
+ * Copyright (C) 2009, Jinsung Yang <jsgood.yang@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/version.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <media/s5ka3dfx_platform.h>
+
+#ifdef CONFIG_VIDEO_SAMSUNG_V4L2
+#include <linux/videodev2_samsung.h>
+#endif
+
+#include "s5ka3dfx.h"
+
+#define S5KA3DFX_DRIVER_NAME "S5KA3DFX"
+
+/* #define VGA_CAM_DEBUG */
+
+#ifdef VGA_CAM_DEBUG
+#define dev_dbg dev_err
+#endif
+
+/* Default resolution & pixelformat. plz ref s5ka3dfx_platform.h */
+#define DEFAULT_RESOLUTION WVGA /* Index of resoultion */
+#define DEFAUT_FPS_INDEX S5KA3DFX_15FPS
+#define DEFUALT_MCLK 24000000 /* 24MHz default */
+#define DEFAULT_FMT V4L2_PIX_FMT_UYVY /* YUV422 */
+#define POLL_TIME_MS 10
+
+/*
+ * Specification
+ * Parallel : ITU-R. 656/601 YUV422, RGB565, RGB888 (Up to VGA), RAW10
+ * Serial : MIPI CSI2 (single lane) YUV422, RGB565, RGB888 (Up to VGA), RAW10
+ * Resolution : 1280 (H) x 1024 (V)
+ * Image control : Brightness, Contrast, Saturation, Sharpness, Glamour
+ * Effect : Mono, Negative, Sepia, Aqua, Sketch
+ * FPS : 15fps @full resolution, 30fps @VGA, 24fps @720p
+ * Max. pixel clock frequency : 48MHz(upto)
+ * Internal PLL (6MHz to 27MHz input frequency)
+ */
+
+static int s5ka3dfx_init(struct v4l2_subdev *sd, u32 val);
+
+/* Camera functional setting values configured by user concept */
+struct s5ka3dfx_userset {
+ 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 s5ka3dfx_state {
+ struct s5ka3dfx_platform_data *pdata;
+ struct v4l2_subdev sd;
+ struct v4l2_pix_format pix;
+ struct v4l2_fract timeperframe;
+ struct s5ka3dfx_userset userset;
+ struct v4l2_streamparm strm;
+ int framesize_index;
+ int freq; /* MCLK in KHz */
+ int is_mipi;
+ int isize;
+ int ver;
+ int fps;
+ int vt_mode; /*For VT camera */
+ int check_dataline;
+ int check_previewdata;
+};
+
+enum {
+ S5KA3DFX_PREVIEW_QCIF,
+ S5KA3DFX_PREVIEW_QVGA,
+ S5KA3DFX_PREVIEW_VGA,
+};
+
+struct s5ka3dfx_enum_framesize {
+ unsigned int index;
+ unsigned int width;
+ unsigned int height;
+};
+
+struct s5ka3dfx_enum_framesize s5ka3dfx_framesize_list[] = {
+ { S5KA3DFX_PREVIEW_QCIF, 176, 144 },
+ { S5KA3DFX_PREVIEW_QVGA, 320, 240 },
+ { S5KA3DFX_PREVIEW_VGA, 640, 480 }
+};
+
+static inline struct s5ka3dfx_state *to_state(struct v4l2_subdev *sd)
+{
+ return container_of(sd, struct s5ka3dfx_state, sd);
+}
+
+struct s5ka3dfx_regset_table {
+ struct s5ka3dfx_reg *regset;
+ int array_size;
+};
+
+#define S5KA3DFX_REGSET_TABLE_ELEMENT(x, y) \
+ [(x)] = { \
+ .regset = (y), \
+ .array_size = ARRAY_SIZE((y)), \
+ }
+
+static struct s5ka3dfx_regset_table brightness_vt[] = {
+ S5KA3DFX_REGSET_TABLE_ELEMENT(EV_MINUS_4, s5ka3dfx_ev_vt_m4),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(EV_MINUS_3, s5ka3dfx_ev_vt_m3),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(EV_MINUS_2, s5ka3dfx_ev_vt_m2),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(EV_MINUS_1, s5ka3dfx_ev_vt_m1),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(EV_DEFAULT, s5ka3dfx_ev_vt_default),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(EV_PLUS_1, s5ka3dfx_ev_vt_p1),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(EV_PLUS_2, s5ka3dfx_ev_vt_p2),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(EV_PLUS_3, s5ka3dfx_ev_vt_p3),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(EV_PLUS_4, s5ka3dfx_ev_vt_p4),
+};
+
+static struct s5ka3dfx_regset_table brightness[] = {
+ S5KA3DFX_REGSET_TABLE_ELEMENT(EV_MINUS_4, s5ka3dfx_ev_m4),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(EV_MINUS_3, s5ka3dfx_ev_m3),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(EV_MINUS_2, s5ka3dfx_ev_m2),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(EV_MINUS_1, s5ka3dfx_ev_m1),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(EV_DEFAULT, s5ka3dfx_ev_default),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(EV_PLUS_1, s5ka3dfx_ev_p1),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(EV_PLUS_2, s5ka3dfx_ev_p2),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(EV_PLUS_3, s5ka3dfx_ev_p3),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(EV_PLUS_4, s5ka3dfx_ev_p4),
+};
+
+static struct s5ka3dfx_regset_table white_balance[] = {
+ S5KA3DFX_REGSET_TABLE_ELEMENT(WHITE_BALANCE_AUTO,
+ s5ka3dfx_wb_auto),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(WHITE_BALANCE_SUNNY,
+ s5ka3dfx_wb_sunny),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(WHITE_BALANCE_CLOUDY,
+ s5ka3dfx_wb_cloudy),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(WHITE_BALANCE_TUNGSTEN,
+ s5ka3dfx_wb_tungsten),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(WHITE_BALANCE_FLUORESCENT,
+ s5ka3dfx_wb_fluorescent),
+};
+
+static struct s5ka3dfx_regset_table effects[] = {
+ S5KA3DFX_REGSET_TABLE_ELEMENT(IMAGE_EFFECT_NONE,
+ s5ka3dfx_effect_none),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(IMAGE_EFFECT_BNW,
+ s5ka3dfx_effect_gray),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(IMAGE_EFFECT_SEPIA,
+ s5ka3dfx_effect_sepia),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(IMAGE_EFFECT_NEGATIVE,
+ s5ka3dfx_effect_negative),
+};
+
+static struct s5ka3dfx_regset_table fps_vt_table[] = {
+ S5KA3DFX_REGSET_TABLE_ELEMENT(0, s5ka3dfx_vt_fps_7),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(1, s5ka3dfx_vt_fps_10),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(2, s5ka3dfx_vt_fps_15),
+};
+
+static struct s5ka3dfx_regset_table fps_table[] = {
+ S5KA3DFX_REGSET_TABLE_ELEMENT(0, s5ka3dfx_fps_7),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(1, s5ka3dfx_fps_10),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(2, s5ka3dfx_fps_15),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(3, s5ka3dfx_fps_auto),
+};
+
+static struct s5ka3dfx_regset_table blur_vt[] = {
+ S5KA3DFX_REGSET_TABLE_ELEMENT(BLUR_LEVEL_0, s5ka3dfx_blur_vt_none),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(BLUR_LEVEL_1, s5ka3dfx_blur_vt_p1),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(BLUR_LEVEL_2, s5ka3dfx_blur_vt_p2),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(BLUR_LEVEL_3, s5ka3dfx_blur_vt_p3),
+};
+
+static struct s5ka3dfx_regset_table blur[] = {
+ S5KA3DFX_REGSET_TABLE_ELEMENT(BLUR_LEVEL_0, s5ka3dfx_blur_none),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(BLUR_LEVEL_1, s5ka3dfx_blur_p1),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(BLUR_LEVEL_2, s5ka3dfx_blur_p2),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(BLUR_LEVEL_3, s5ka3dfx_blur_p3),
+};
+
+static struct s5ka3dfx_regset_table dataline[] = {
+ S5KA3DFX_REGSET_TABLE_ELEMENT(0, s5ka3dfx_dataline),
+};
+
+static struct s5ka3dfx_regset_table dataline_stop[] = {
+ S5KA3DFX_REGSET_TABLE_ELEMENT(0, s5ka3dfx_dataline_stop),
+};
+
+static struct s5ka3dfx_regset_table init_reg[] = {
+ S5KA3DFX_REGSET_TABLE_ELEMENT(0, s5ka3dfx_init_reg),
+};
+
+static struct s5ka3dfx_regset_table init_vt_reg[] = {
+ S5KA3DFX_REGSET_TABLE_ELEMENT(0, s5ka3dfx_init_vt_reg),
+};
+
+static struct s5ka3dfx_regset_table frame_size[] = {
+ S5KA3DFX_REGSET_TABLE_ELEMENT(0, s5ka3dfx_QCIF),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(1, s5ka3dfx_QVGA),
+ S5KA3DFX_REGSET_TABLE_ELEMENT(2, s5ka3dfx_Return_VGA),
+};
+static int s5ka3dfx_reset(struct v4l2_subdev *sd)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5ka3dfx_platform_data *pdata;
+
+ pdata = client->dev.platform_data;
+
+ if (pdata->cam_power) {
+ pdata->cam_power(0);
+ msleep(5);
+ pdata->cam_power(1);
+ msleep(5);
+ s5ka3dfx_init(sd, 0);
+ }
+
+ return 0;
+}
+
+static int s5ka3dfx_i2c_write_multi(struct i2c_client *client,
+ unsigned short addr, unsigned int w_data)
+{
+ int retry_count = 4;
+ unsigned char buf[2];
+ struct i2c_msg msg = { client->addr, 0, 2, buf };
+ int ret;
+
+ buf[0] = addr;
+ buf[1] = w_data;
+
+#ifdef VGA_CAM_DEBUG
+ int i;
+ for (i = 0; i < 2; i++) {
+ dev_err(&client->dev, "buf[%d] = %x ", i, buf[i]);
+ if (i == 1)
+ dev_err(&client->dev, "\n");
+ }
+#endif
+
+ do {
+ ret = i2c_transfer(client->adapter, &msg, 1);
+ if (likely(ret == 1))
+ break;
+ msleep(POLL_TIME_MS);
+ } while (retry_count--);
+
+ if (ret != 1)
+ dev_err(&client->dev, "I2C is not working.\n");
+
+ return (ret == 1) ? 0 : -EIO;
+}
+
+static int s5ka3dfx_write_regs(struct v4l2_subdev *sd,
+ struct s5ka3dfx_reg regs[], int size)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ int i, err;
+
+ for (i = 0; i < size; i++) {
+ err = s5ka3dfx_i2c_write_multi(client,
+ regs[i].addr, regs[i].val);
+ if (err < 0) {
+ v4l_info(client, "%s: register set failed\n", __func__);
+ break;
+ }
+ }
+ if (err < 0)
+ return -EIO;
+
+ return 0;
+}
+
+static int s5ka3dfx_write_regset_table(struct v4l2_subdev *sd,
+ const struct s5ka3dfx_regset_table *regset_table)
+{
+ int err;
+
+ if (regset_table->regset)
+ err = s5ka3dfx_write_regs(sd, regset_table->regset,
+ regset_table->array_size);
+ else
+ err = -EINVAL;
+
+ return err;
+}
+
+static int s5ka3dfx_set_from_table(struct v4l2_subdev *sd,
+ const char *setting_name,
+ const struct s5ka3dfx_regset_table *table,
+ int table_size, int index)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ dev_dbg(&client->dev, "%s: set %s index %d\n",
+ __func__, setting_name, index);
+
+ if ((index < 0) || (index >= table_size)) {
+ dev_err(&client->dev,
+ "%s: index(%d) out of range[0:%d] for table for %s\n",
+ __func__, index, table_size, setting_name);
+ return -EINVAL;
+ }
+ table += index;
+ if (table == NULL)
+ return -EINVAL;
+ return s5ka3dfx_write_regset_table(sd, table);
+}
+
+static int s5ka3dfx_set_parameter(struct v4l2_subdev *sd,
+ int *current_value_ptr,
+ int new_value,
+ const char *setting_name,
+ const struct s5ka3dfx_regset_table *table,
+ int table_size)
+{
+ int err;
+
+ if (*current_value_ptr == new_value)
+ return 0;
+
+ err = s5ka3dfx_set_from_table(sd, setting_name, table,
+ table_size, new_value);
+
+ if (!err)
+ *current_value_ptr = new_value;
+
+ return err;
+}
+static int s5ka3dfx_set_preview_start(struct v4l2_subdev *sd)
+{
+ int err;
+ struct s5ka3dfx_state *state =
+ container_of(sd, struct s5ka3dfx_state, sd);
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ if (!state->pix.width || !state->pix.height)
+ return -EINVAL;
+
+ err = s5ka3dfx_set_from_table(sd, "frame_size", frame_size,
+ ARRAY_SIZE(frame_size), state->framesize_index);
+ if (err < 0) {
+ dev_err(&client->dev,
+ "%s: failed: Could not set preview size\n",
+ __func__);
+ return -EIO;
+ }
+
+ return 0;
+}
+static struct v4l2_queryctrl s5ka3dfx_controls[] = {
+ /* Add here if needed */
+};
+
+const char * const *s5ka3dfx_ctrl_get_menu(u32 id)
+{
+ pr_debug("%s is called... id : %d\n", __func__, id);
+
+ switch (id) {
+ default:
+ return v4l2_ctrl_get_menu(id);
+ }
+}
+
+static inline struct v4l2_queryctrl const *s5ka3dfx_find_qctrl(int id)
+{
+ int i;
+
+ pr_debug("%s is called... id : %d\n", __func__, id);
+
+ for (i = 0; i < ARRAY_SIZE(s5ka3dfx_controls); i++)
+ if (s5ka3dfx_controls[i].id == id)
+ return &s5ka3dfx_controls[i];
+
+ return NULL;
+}
+
+static int s5ka3dfx_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
+{
+ int i;
+
+ pr_debug("%s is called...\n", __func__);
+
+ for (i = 0; i < ARRAY_SIZE(s5ka3dfx_controls); i++) {
+ if (s5ka3dfx_controls[i].id == qc->id) {
+ memcpy(qc, &s5ka3dfx_controls[i],
+ sizeof(struct v4l2_queryctrl));
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static int s5ka3dfx_querymenu(struct v4l2_subdev *sd, struct v4l2_querymenu *qm)
+{
+ struct v4l2_queryctrl qctrl;
+
+ pr_debug("%s is called...\n", __func__);
+
+ qctrl.id = qm->id;
+ s5ka3dfx_queryctrl(sd, &qctrl);
+
+ return v4l2_ctrl_query_menu(qm, &qctrl, s5ka3dfx_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 s5ka3dfx_s_crystal_freq(struct v4l2_subdev *sd, u32 freq, u32 flags)
+{
+ int err = -EINVAL;
+
+ pr_debug("%s is called...\n", __func__);
+
+ return err;
+}
+
+static int s5ka3dfx_g_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
+{
+ int err = 0;
+
+ pr_debug("%s is called...\n", __func__);
+
+ return err;
+}
+
+static void s5ka3dfx_set_framesize(struct v4l2_subdev *sd,
+ const struct s5ka3dfx_enum_framesize *frmsize,
+ int frmsize_count)
+{
+ struct s5ka3dfx_state *state =
+ container_of(sd, struct s5ka3dfx_state, sd);
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ const struct s5ka3dfx_enum_framesize *last_frmsize =
+ &frmsize[frmsize_count - 1];
+
+ dev_dbg(&client->dev, "%s: Requested Res: %dx%d\n", __func__,
+ state->pix.width, state->pix.height);
+
+ do {
+ if (frmsize->width == state->pix.width &&
+ frmsize->height == state->pix.height) {
+ break;
+ }
+
+ frmsize++;
+ } while (frmsize <= last_frmsize);
+
+ if (frmsize > last_frmsize)
+ frmsize = last_frmsize;
+
+ state->pix.width = frmsize->width;
+ state->pix.height = frmsize->height;
+ state->framesize_index = frmsize->index;
+
+ dev_dbg(&client->dev, "%s: Preview Res Set: %dx%d, index %d\n",
+ __func__, state->pix.width, state->pix.height,
+ state->framesize_index);
+}
+static int s5ka3dfx_s_mbus_fmt(struct v4l2_subdev *sd,
+ struct v4l2_mbus_framefmt *fmt)
+{
+ struct s5ka3dfx_state *state =
+ container_of(sd, struct s5ka3dfx_state, sd);
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ int err = 0;
+
+ if (fmt->code == V4L2_MBUS_FMT_FIXED &&
+ fmt->colorspace != V4L2_COLORSPACE_JPEG) {
+ dev_dbg(&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? */
+
+ s5ka3dfx_set_framesize(sd, s5ka3dfx_framesize_list,
+ ARRAY_SIZE(s5ka3dfx_framesize_list));
+
+ return err;
+}
+
+static int s5ka3dfx_enum_framesizes(struct v4l2_subdev *sd,
+ struct v4l2_frmsizeenum *fsize)
+{
+ struct s5ka3dfx_state *state =
+ container_of(sd, struct s5ka3dfx_state, sd);
+ int num_entries = sizeof(s5ka3dfx_framesize_list) /
+ sizeof(struct s5ka3dfx_enum_framesize);
+ struct s5ka3dfx_enum_framesize *elem;
+ int index = 0;
+ int i = 0;
+
+ pr_debug("%s is called...\n", __func__);
+
+ /* 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 (WVGA)
+ */
+ fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+
+ index = state->framesize_index;
+
+ for (i = 0; i < num_entries; i++) {
+ elem = &s5ka3dfx_framesize_list[i];
+ if (elem->index == index) {
+ fsize->discrete.width =
+ s5ka3dfx_framesize_list[index].width;
+ fsize->discrete.height =
+ s5ka3dfx_framesize_list[index].height;
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static int s5ka3dfx_enum_frameintervals(struct v4l2_subdev *sd,
+ struct v4l2_frmivalenum *fival)
+{
+ int err = 0;
+
+ pr_debug("%s is called...\n", __func__);
+
+ return err;
+}
+
+static int s5ka3dfx_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index,
+ enum v4l2_mbus_pixelcode *code)
+{
+ int err = 0;
+
+ pr_debug("%s is called...\n", __func__);
+
+ return err;
+}
+
+static int s5ka3dfx_try_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
+{
+ int err = 0;
+
+ pr_debug("%s is called...\n", __func__);
+
+ return err;
+}
+
+static int s5ka3dfx_g_parm(struct v4l2_subdev *sd,
+ struct v4l2_streamparm *param)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ int err = 0;
+
+ dev_dbg(&client->dev, "%s\n", __func__);
+
+ return err;
+}
+
+static int s5ka3dfx_s_parm(struct v4l2_subdev *sd,
+ struct v4l2_streamparm *param)
+{
+ int err = 0;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5ka3dfx_state *state =
+ container_of(sd, struct s5ka3dfx_state, sd);
+ struct sec_cam_parm *new_parms =
+ (struct sec_cam_parm *)&param->parm.raw_data;
+ struct sec_cam_parm *parms =
+ (struct sec_cam_parm *)&state->strm.parm.raw_data;
+
+ dev_dbg(&client->dev, "%s: start\n", __func__);
+
+ /* we return an error if one happened but don't stop trying to
+ * set all parameters passed
+ */
+
+ err = s5ka3dfx_set_parameter(sd, &parms->brightness,
+ new_parms->brightness, "brightness",
+ brightness, ARRAY_SIZE(brightness));
+ err |= s5ka3dfx_set_parameter(sd, &parms->effects, new_parms->effects,
+ "effects", effects,
+ ARRAY_SIZE(effects));
+ err |= s5ka3dfx_set_parameter(sd, &parms->white_balance,
+ new_parms->white_balance,
+ "white_balance", white_balance,
+ ARRAY_SIZE(white_balance));
+
+ dev_dbg(&client->dev, "%s: returning %d\n", __func__, err);
+
+ return err;
+}
+
+/* set sensor register values for adjusting brightness */
+static int s5ka3dfx_set_brightness(struct v4l2_subdev *sd,
+ struct v4l2_control *ctrl)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5ka3dfx_state *state =
+ container_of(sd, struct s5ka3dfx_state, sd);
+ struct s5ka3dfx_regset_table *ev;
+ int err = -EINVAL;
+ int ev_index;
+ int array_size;
+
+ dev_dbg(&client->dev, "%s: value : %d state->vt_mode %d\n",
+ __func__, ctrl->value, state->vt_mode);
+
+ pr_debug("state->vt_mode : %d\n", state->vt_mode);
+
+ if ((ctrl->value < 0) || (ctrl->value >= EV_MAX))
+ ev_index = EV_DEFAULT;
+ else
+ ev_index = ctrl->value;
+
+ if (state->vt_mode == 1) {
+ ev = brightness_vt;
+ array_size = ARRAY_SIZE(brightness_vt);
+ } else {
+ ev = brightness;
+ array_size = ARRAY_SIZE(brightness);
+ }
+
+ if (ev_index >= array_size)
+ ev_index = EV_DEFAULT;
+
+ ev += ev_index;
+
+ err = s5ka3dfx_write_regset_table(sd, ev);
+
+ if (err)
+ dev_dbg(&client->dev, "%s: register set failed\n", __func__);
+
+ return err;
+}
+
+/*
+ * set sensor register values for
+ * adjusting whitebalance, both auto and manual
+ */
+static int s5ka3dfx_set_wb(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5ka3dfx_regset_table *wb = white_balance;
+ int err = -EINVAL;
+
+ dev_dbg(&client->dev, "%s: value : %d\n", __func__, ctrl->value);
+
+ if ((ctrl->value < WHITE_BALANCE_BASE) ||
+ (ctrl->value > WHITE_BALANCE_MAX) ||
+ (ctrl->value >= ARRAY_SIZE(white_balance))) {
+ dev_dbg(&client->dev, "%s: Value(%d) out of range([%d:%d])\n",
+ __func__, ctrl->value,
+ WHITE_BALANCE_BASE, WHITE_BALANCE_MAX);
+ dev_dbg(&client->dev, "%s: Value out of range\n", __func__);
+ goto out;
+ }
+
+ wb += ctrl->value;
+
+ err = s5ka3dfx_write_regset_table(sd, wb);
+
+ if (err)
+ dev_dbg(&client->dev, "%s: register set failed\n", __func__);
+out:
+ return err;
+}
+
+/* set sensor register values for adjusting color effect */
+static int s5ka3dfx_set_effect(struct v4l2_subdev *sd,
+ struct v4l2_control *ctrl)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5ka3dfx_regset_table *effect = effects;
+ int err = -EINVAL;
+
+ dev_dbg(&client->dev, "%s: value : %d\n", __func__, ctrl->value);
+
+ if ((ctrl->value < IMAGE_EFFECT_BASE) ||
+ (ctrl->value > IMAGE_EFFECT_MAX) ||
+ (ctrl->value >= ARRAY_SIZE(effects))) {
+ dev_dbg(&client->dev, "%s: Value(%d) out of range([%d:%d])\n",
+ __func__, ctrl->value,
+ IMAGE_EFFECT_BASE, IMAGE_EFFECT_MAX);
+ goto out;
+ }
+
+ effect += ctrl->value;
+
+ err = s5ka3dfx_write_regset_table(sd, effect);
+
+ if (err)
+ dev_dbg(&client->dev, "%s: register set failed\n", __func__);
+out:
+ return err;
+}
+
+/* set sensor register values for frame rate(fps) setting */
+static int s5ka3dfx_set_frame_rate(struct v4l2_subdev *sd,
+ struct v4l2_control *ctrl)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5ka3dfx_state *state =
+ container_of(sd, struct s5ka3dfx_state, sd);
+ struct s5ka3dfx_regset_table *fps;
+
+ int err = -EINVAL;
+ int fps_index;
+
+ dev_dbg(&client->dev, "%s: value : %d\n", __func__, ctrl->value);
+
+ pr_debug("state->vt_mode : %d\n", state->vt_mode);
+
+ switch (ctrl->value) {
+ case 0:
+ fps_index = 3;
+ break;
+
+ case 7:
+ fps_index = 0;
+ break;
+
+ case 10:
+ fps_index = 1;
+ break;
+
+ case 15:
+ fps_index = 2;
+ break;
+
+ default:
+ dev_dbg(&client->dev, "%s: Value(%d) is not supported\n",
+ __func__, ctrl->value);
+ goto out;
+ }
+
+ if (state->vt_mode == 1)
+ fps = fps_vt_table;
+ else
+ fps = fps_table;
+
+ fps += fps_index;
+ state->fps = fps_index;
+
+ err = s5ka3dfx_write_regset_table(sd, fps);
+out:
+ return err;
+}
+
+/* set sensor register values for adjusting blur effect */
+static int s5ka3dfx_set_blur(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5ka3dfx_state *state =
+ container_of(sd, struct s5ka3dfx_state, sd);
+ struct s5ka3dfx_regset_table *bl;
+ int err = -EINVAL;
+ int array_size;
+
+ dev_dbg(&client->dev, "%s: value : %d\n", __func__, ctrl->value);
+
+ pr_debug("state->vt_mode : %d\n", state->vt_mode);
+
+ if ((ctrl->value < BLUR_LEVEL_0) || (ctrl->value > BLUR_LEVEL_MAX)) {
+ dev_dbg(&client->dev, "%s: Value(%d) out of range([%d:%d])\n",
+ __func__, ctrl->value,
+ BLUR_LEVEL_0, BLUR_LEVEL_MAX);
+ goto out;
+ }
+
+ if (state->vt_mode == 1) {
+ bl = blur_vt;
+ array_size = ARRAY_SIZE(blur_vt);
+ } else {
+ bl = blur;
+ array_size = ARRAY_SIZE(blur);
+ }
+
+ if (ctrl->value >= array_size) {
+ dev_dbg(&client->dev, "%s: Value(%d) out of range([%d:%d))\n",
+ __func__, ctrl->value,
+ BLUR_LEVEL_0, array_size);
+ goto out;
+ }
+
+ bl += ctrl->value;
+
+ err = s5ka3dfx_write_regset_table(sd, bl);
+out:
+ return err;
+}
+
+static int s5ka3dfx_check_dataline_stop(struct v4l2_subdev *sd)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5ka3dfx_state *state =
+ container_of(sd, struct s5ka3dfx_state, sd);
+ int err = -EINVAL;
+
+ dev_dbg(&client->dev, "%s\n", __func__);
+
+ err = s5ka3dfx_write_regset_table(sd, dataline_stop);
+ if (err < 0) {
+ v4l_info(client, "%s: register set failed\n", __func__);
+ return -EIO;
+ }
+
+ state->check_dataline = 0;
+ err = s5ka3dfx_reset(sd);
+ if (err < 0) {
+ v4l_info(client, "%s: register set failed\n", __func__);
+ return -EIO;
+ }
+ return err;
+}
+
+/* returns the real iso currently used by sensor due to lighting
+ * conditions, not the requested iso we sent using s_ctrl.
+ */
+static int s5ka3dfx_get_iso(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ int err;
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ s32 read_value;
+ int gain;
+
+ err = s5ka3dfx_i2c_write_multi(client, 0xEF, 0x02);
+ if (err < 0)
+ return err;
+
+ read_value = i2c_smbus_read_byte_data(client, 0x1D);
+ if (read_value < 0)
+ return read_value;
+
+ read_value &= 0x7F;
+ gain = (128 * 100) / (128 - read_value);
+
+ if (gain > 280)
+ ctrl->value = ISO_400;
+ else if (gain > 230)
+ ctrl->value = ISO_200;
+ else if (gain > 190)
+ ctrl->value = ISO_100;
+ else if (gain > 100)
+ ctrl->value = ISO_50;
+ else
+ ctrl->value = gain;
+
+ dev_dbg(&client->dev, "%s: get iso == %d (0x%x)\n",
+ __func__, ctrl->value, read_value);
+
+ return err;
+}
+
+static int s5ka3dfx_get_shutterspeed(struct v4l2_subdev *sd,
+ struct v4l2_control *ctrl)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5ka3dfx_state *state = to_state(sd);
+ s32 read_value;
+ int cintr;
+ int err;
+
+ err = s5ka3dfx_i2c_write_multi(client, 0xEF, 0x02);
+ if (err < 0)
+ return err;
+
+ read_value = i2c_smbus_read_byte_data(client, 0x0E);
+ if (read_value < 0)
+ return read_value;
+ cintr = (read_value & 0x1F) << 8;
+
+ read_value = i2c_smbus_read_byte_data(client, 0x0F);
+ if (read_value < 0)
+ return read_value;
+ cintr |= read_value & 0xFF;
+
+ /* A3D Shutter Speed (Micro Sec.) =
+ (2 * (cintr - 1) * 814) / MCLK * 1000 */
+ ctrl->value = ((cintr - 1) * 1628) / (state->freq / 1000) * 1000;
+
+ dev_dbg(&client->dev,
+ "%s: get shutterspeed == %d\n", __func__, ctrl->value);
+
+ return err;
+}
+
+static int s5ka3dfx_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5ka3dfx_state *state =
+ container_of(sd, struct s5ka3dfx_state, sd);
+ struct s5ka3dfx_userset userset = state->userset;
+ int err = 0;
+
+ dev_dbg(&client->dev, "%s: id : 0x%08x\n", __func__, ctrl->id);
+
+ switch (ctrl->id) {
+ case V4L2_CID_EXPOSURE:
+ ctrl->value = userset.exposure_bias;
+ break;
+
+ case V4L2_CID_AUTO_WHITE_BALANCE:
+ ctrl->value = userset.auto_wb;
+ break;
+
+ case V4L2_CID_WHITE_BALANCE_PRESET:
+ ctrl->value = userset.manual_wb;
+ break;
+
+ case V4L2_CID_COLORFX:
+ ctrl->value = userset.effect;
+ break;
+
+ case V4L2_CID_CONTRAST:
+ ctrl->value = userset.contrast;
+ break;
+
+ case V4L2_CID_SATURATION:
+ ctrl->value = userset.saturation;
+ break;
+
+ case V4L2_CID_SHARPNESS:
+ ctrl->value = userset.saturation;
+ break;
+
+ case V4L2_CID_CAMERA_GET_ISO:
+ err = s5ka3dfx_get_iso(sd, ctrl);
+ break;
+
+ case V4L2_CID_CAMERA_GET_SHT_TIME:
+ err = s5ka3dfx_get_shutterspeed(sd, ctrl);
+ break;
+
+ case V4L2_CID_ESD_INT:
+ ctrl->value = 0;
+ break;
+
+ default:
+ dev_dbg(&client->dev, "%s: no such ctrl\n", __func__);
+ err = -EINVAL;
+ break;
+ }
+
+ return err;
+}
+
+static int s5ka3dfx_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5ka3dfx_state *state =
+ container_of(sd, struct s5ka3dfx_state, sd);
+
+ int err = -EINVAL;
+
+ pr_debug("%s : ctrl->id 0x%08x, ctrl->value %d\n", __func__,
+ ctrl->id, ctrl->value);
+
+ switch (ctrl->id) {
+
+ case V4L2_CID_CAMERA_BRIGHTNESS:
+ dev_dbg(&client->dev, "%s: "
+ "V4L2_CID_CAMERA_BRIGHTNESS\n", __func__);
+ err = s5ka3dfx_set_brightness(sd, ctrl);
+ break;
+
+ case V4L2_CID_CAMERA_WHITE_BALANCE:
+ dev_dbg(&client->dev, "%s: "
+ "V4L2_CID_AUTO_WHITE_BALANCE\n", __func__);
+ err = s5ka3dfx_set_wb(sd, ctrl);
+ break;
+
+ case V4L2_CID_CAMERA_EFFECT:
+ dev_dbg(&client->dev, "%s: "
+ "V4L2_CID_CAMERA_EFFECT\n", __func__);
+ err = s5ka3dfx_set_effect(sd, ctrl);
+ break;
+
+ case V4L2_CID_CAMERA_FRAME_RATE:
+ dev_dbg(&client->dev, "%s: "
+ "V4L2_CID_CAMERA_FRAME_RATE\n", __func__);
+ err = s5ka3dfx_set_frame_rate(sd, ctrl);
+ break;
+
+ case V4L2_CID_CAMERA_VGA_BLUR:
+ dev_dbg(&client->dev, "%s: "
+ "V4L2_CID_CAMERA_VGA_BLUR\n", __func__);
+ err = s5ka3dfx_set_blur(sd, ctrl);
+ break;
+
+ case V4L2_CID_CAMERA_VT_MODE:
+ state->vt_mode = ctrl->value;
+ dev_dbg(&client->dev, "%s: V4L2_CID_CAMERA_VT_MODE : "
+ "state->vt_mode %d\n",
+ __func__, state->vt_mode);
+ err = 0;
+ break;
+
+ case V4L2_CID_CAMERA_CHECK_DATALINE:
+ state->check_dataline = ctrl->value;
+ err = 0;
+ break;
+
+ case V4L2_CID_CAMERA_CHECK_DATALINE_STOP:
+ err = s5ka3dfx_check_dataline_stop(sd);
+ break;
+
+ case V4L2_CID_CAM_PREVIEW_ONOFF:
+ if (state->check_previewdata == 0)
+ err = s5ka3dfx_set_preview_start(sd);
+ else
+ err = -EIO;
+ break;
+
+ case V4L2_CID_CAMERA_RESET:
+ dev_dbg(&client->dev, "%s: V4L2_CID_CAMERA_RESET\n", __func__);
+ err = s5ka3dfx_reset(sd);
+ break;
+
+ default:
+ dev_dbg(&client->dev, "%s: no support control "
+ "in camera sensor, S5KA3DFX\n", __func__);
+ err = 0;
+ break;
+ }
+
+ if (err < 0)
+ goto out;
+ else
+ return 0;
+
+ out:
+ dev_dbg(&client->dev, "%s: vidioc_s_ctrl failed\n", __func__);
+ return err;
+}
+
+static void s5ka3dfx_init_parameters(struct v4l2_subdev *sd)
+{
+ struct s5ka3dfx_state *state =
+ container_of(sd, struct s5ka3dfx_state, sd);
+ struct sec_cam_parm *parms =
+ (struct sec_cam_parm *)&state->strm.parm.raw_data;
+
+ parms->effects = IMAGE_EFFECT_NONE;
+ parms->brightness = EV_DEFAULT;
+ parms->white_balance = WHITE_BALANCE_AUTO;
+
+}
+
+static int s5ka3dfx_init(struct v4l2_subdev *sd, u32 val)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct s5ka3dfx_state *state =
+ container_of(sd, struct s5ka3dfx_state, sd);
+ int err = -EINVAL;
+
+ pr_debug("camera initialization start, state->vt_mode : %d\n",
+ state->vt_mode);
+ pr_debug("state->check_dataline : %d\n", state->check_dataline);
+
+ s5ka3dfx_init_parameters(sd);
+ if (state->vt_mode == 0) {
+ if (state->check_dataline)
+ err = s5ka3dfx_write_regset_table(sd, dataline);
+ else
+ err = s5ka3dfx_write_regset_table(sd, init_reg);
+ } else
+ err = s5ka3dfx_write_regset_table(sd, init_vt_reg);
+
+ if (err < 0) {
+ /* This is preview fail */
+ state->check_previewdata = 100;
+ v4l_err(client,
+ "%s: camera initialization failed. err(%d)\n",
+ __func__, state->check_previewdata);
+ return -EIO;
+ }
+
+ /* This is preview success */
+ state->check_previewdata = 0;
+ return 0;
+}
+
+static const struct v4l2_subdev_core_ops s5ka3dfx_core_ops = {
+ .init = s5ka3dfx_init, /* initializing API */
+ .queryctrl = s5ka3dfx_queryctrl,
+ .querymenu = s5ka3dfx_querymenu,
+ .g_ctrl = s5ka3dfx_g_ctrl,
+ .s_ctrl = s5ka3dfx_s_ctrl,
+};
+
+static const struct v4l2_subdev_video_ops s5ka3dfx_video_ops = {
+ .s_crystal_freq = s5ka3dfx_s_crystal_freq,
+ .g_mbus_fmt = s5ka3dfx_g_mbus_fmt,
+ .s_mbus_fmt = s5ka3dfx_s_mbus_fmt,
+ .enum_framesizes = s5ka3dfx_enum_framesizes,
+ .enum_frameintervals = s5ka3dfx_enum_frameintervals,
+ .enum_mbus_fmt = s5ka3dfx_enum_mbus_fmt,
+ .try_mbus_fmt = s5ka3dfx_try_mbus_fmt,
+ .g_parm = s5ka3dfx_g_parm,
+ .s_parm = s5ka3dfx_s_parm,
+};
+
+static const struct v4l2_subdev_ops s5ka3dfx_ops = {
+ .core = &s5ka3dfx_core_ops,
+ .video = &s5ka3dfx_video_ops,
+};
+
+/*
+ * s5ka3dfx_probe
+ * Fetching platform data is being done with s_config subdev call.
+ * In probe routine, we just register subdev device
+ */
+static int s5ka3dfx_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct s5ka3dfx_state *state;
+ struct v4l2_subdev *sd;
+ struct s5ka3dfx_platform_data *pdata = client->dev.platform_data;
+
+ state = kzalloc(sizeof(struct s5ka3dfx_state), GFP_KERNEL);
+ if (state == NULL)
+ return -ENOMEM;
+
+ sd = &state->sd;
+ strcpy(sd->name, S5KA3DFX_DRIVER_NAME);
+
+ /*
+ * Assign default format and resolution
+ * Use configured default information in platform data
+ * or without them, use default information in driver
+ */
+ if (!(pdata->default_width && pdata->default_height)) {
+ /* TODO: assign driver default resolution */
+ } else {
+ state->pix.width = pdata->default_width;
+ state->pix.height = pdata->default_height;
+ }
+
+ if (!pdata->pixelformat)
+ state->pix.pixelformat = DEFAULT_FMT;
+ else
+ state->pix.pixelformat = pdata->pixelformat;
+
+ if (pdata->freq == 0)
+ state->freq = DEFUALT_MCLK;
+ else
+ state->freq = pdata->freq;
+
+ if (!pdata->is_mipi) {
+ state->is_mipi = 0;
+ dev_dbg(&client->dev, "parallel mode\n");
+ } else
+ state->is_mipi = pdata->is_mipi;
+
+ /* Registering subdev */
+ v4l2_i2c_subdev_init(sd, client, &s5ka3dfx_ops);
+
+ dev_dbg(&client->dev, "s5ka3dfx has been probed\n");
+ return 0;
+}
+
+static int s5ka3dfx_remove(struct i2c_client *client)
+{
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+ struct s5ka3dfx_state *state =
+ container_of(sd, struct s5ka3dfx_state, sd);
+
+ v4l2_device_unregister_subdev(sd);
+ kfree(state);
+ return 0;
+}
+
+static const struct i2c_device_id s5ka3dfx_id[] = {
+ { S5KA3DFX_DRIVER_NAME, 0 },
+ { },
+};
+
+MODULE_DEVICE_TABLE(i2c, s5ka3dfx_id);
+
+static struct i2c_driver v4l2_i2c_driver = {
+ .driver.name = S5KA3DFX_DRIVER_NAME,
+ .probe = s5ka3dfx_probe,
+ .remove = s5ka3dfx_remove,
+ .id_table = s5ka3dfx_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("Samsung Electronics S5KA3DFX UXGA camera driver");
+MODULE_AUTHOR("Jinsung Yang <jsgood.yang@samsung.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/s5ka3dfx.h b/drivers/media/video/s5ka3dfx.h
new file mode 100755
index 0000000..7bf2a8e
--- /dev/null
+++ b/drivers/media/video/s5ka3dfx.h
@@ -0,0 +1,1691 @@
+/*
+ * Driver for S5KA3DFX (VGA camera) from Samsung Electronics
+ *
+ * 1/4" 2.0Mp CMOS Image Sensor SoC with an Embedded Image Processor
+ *
+ * Copyright (C) 2009, Jinsung Yang <jsgood.yang@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#ifndef __S5KA3DFX_H__
+#define __S5KA3DFX_H__
+
+struct s5ka3dfx_reg {
+ unsigned char addr;
+ unsigned char val;
+};
+
+struct s5ka3dfx_regset_type {
+ unsigned char *regset;
+ int len;
+};
+
+/*
+ * Macro
+ */
+#define REGSET_LENGTH(x) (sizeof(x) / sizeof(s5ka3dfx_reg))
+
+/*
+ * User defined commands
+ */
+/* S/W defined features for tune */
+#define REG_DELAY 0xFF00 /* in ms */
+#define REG_CMD 0xFFFF /* Followed by command */
+
+/* Following order should not be changed */
+enum image_size_s5ka3dfx {
+ SVGA, /* 800*600 */
+};
+
+/*
+ * Following values describe controls of camera
+ * in user aspect and must be match with index of s5ka3dfx_regset[]
+ * These values indicates each controls and should be used
+ * to control each control
+ */
+enum s5ka3dfx_control {
+ S5KA3DFX_INIT,
+ S5KA3DFX_EV,
+ S5KA3DFX_AWB,
+ S5KA3DFX_MWB,
+ S5KA3DFX_EFFECT,
+ S5KA3DFX_CONTRAST,
+ S5KA3DFX_SATURATION,
+ S5KA3DFX_SHARPNESS,
+};
+
+#define S5KA3DFX_REGSET(x) { \
+ .regset = (x), \
+ .len = sizeof((x))/sizeof(s5ka3dfx_reg),}
+
+/*
+ * VGA Self shot init setting
+ */
+struct s5ka3dfx_reg s5ka3dfx_init_reg[] = {
+ { 0xef, 0x02 },
+ { 0x13, 0xa0 },
+ { 0x23, 0x53 },
+ { 0x26, 0x24 },
+ { 0x2c, 0x05 },
+ { 0x05, 0x00 },
+ { 0x03, 0x58 },
+ { 0x24, 0x0a },
+ { 0x0b, 0x84 },
+ { 0x1e, 0xb7 },
+ { 0x56, 0x05 },
+ { 0x28, 0x96 },
+ { 0x67, 0x3c },
+
+ { 0xef, 0x03 },
+ { 0x50, 0xd2 },
+ { 0x0f, 0x31 },
+ { 0xef, 0x03 },
+ { 0x70, 0x00 }, /*un-mirrored*/
+ { 0x5F, 0x03 },
+ { 0x60, 0x02 },
+ { 0x61, 0x0F },
+ { 0x62, 0x0C },
+ { 0x63, 0x01 },
+ { 0x64, 0xE7 },
+ { 0x65, 0x01 },
+ { 0x66, 0xE7 },
+
+ { 0x6d, 0x56 },
+ { 0x6e, 0xC0 },
+ { 0x6f, 0xC0 },
+
+ { 0x4c, 0x00 },
+ { 0x4d, 0x9e },
+
+ { 0xef, 0x03 },
+ { 0x00, 0x07 },
+ { 0x01, 0x80 },
+ { 0x02, 0x7f },
+ { 0x2b, 0x41 },
+ { 0x31, 0x00 },
+ { 0x32, 0x09 },
+
+ { 0x33, 0x80 },
+ { 0x34, 0x79 },
+
+ { 0x36, 0x3A }, /*39, 3a, N.L. ST */
+ { 0x37, 0x38 },
+
+ { 0x6a, 0x00 },
+ { 0x7b, 0x05 },
+ { 0x38, 0x05 },
+ { 0x39, 0x03 },
+
+ { 0x2d, 0x08 },
+ { 0x2e, 0x20 },
+ { 0x2f, 0x30 },
+ { 0x30, 0xff },
+ { 0x7c, 0x06 },
+ { 0x7d, 0x20 },
+ { 0x7e, 0x0c },
+ { 0x7f, 0x20 },
+
+ { 0x28, 0x02 },
+ { 0x29, 0x9f },
+ { 0x2a, 0x00 },
+
+ { 0x13, 0x00 },
+ { 0x14, 0xa0 },
+
+ { 0x1a, 0x5d },
+ { 0x1b, 0x58 },
+ { 0x1c, 0x60 },
+ { 0x1d, 0x4f },
+
+ { 0x1e, 0x68 },
+ { 0x1f, 0x42 }, /*44, Indoor Rgain Min */
+ { 0x20, 0x7A }, /*75 82, 8a, Indoor Bgain Max */
+ { 0x21, 0x4D }, /* 4Indoor Bgain Min */
+
+ { 0x3a, 0x13 },
+ { 0x3b, 0x3c },
+ { 0x3c, 0x00 },
+ { 0x3d, 0x18 },
+
+ { 0x23, 0x80 },
+
+ { 0x15, 0x0b },
+ { 0x16, 0xd2 },
+ { 0x17, 0x64 },
+ { 0x18, 0x78 },
+
+ { 0xef, 0x00 },
+ { 0xde, 0x00 },
+ { 0xdf, 0x1f },
+ { 0xe0, 0x00 },
+ { 0xe1, 0x37 },
+ { 0xe2, 0x08 },
+ { 0xe3, 0x42 },
+ { 0xe4, 0x00 },
+ { 0xe5, 0x12 },
+ { 0xe6, 0x9e },
+ { 0xe9, 0x00 },
+ { 0xe7, 0x01 },
+ { 0xe8, 0x13 },
+ { 0xe9, 0x01 },
+ { 0xe7, 0x01 },
+ { 0xe8, 0x06 },
+ { 0xe9, 0x02 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0xef },
+ { 0xe9, 0x03 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0xe0 },
+ { 0xe9, 0x04 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0xc3 },
+ { 0xe9, 0x05 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0xab },
+ { 0xe9, 0x06 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0x91 },
+ { 0xe9, 0x07 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0xbd },
+ { 0xe9, 0x08 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0xab },
+ { 0xe9, 0x09 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0x9a },
+ { 0xe9, 0x0a },
+ { 0xe7, 0x00 },
+ { 0xe8, 0x8f },
+ { 0xe9, 0x0b },
+ { 0xe7, 0x00 },
+ { 0xe8, 0x78 },
+ { 0xe9, 0x0c },
+ { 0xe7, 0x00 },
+ { 0xe8, 0x69 },
+ { 0xe9, 0x0d },
+ { 0xe7, 0x00 },
+ { 0xe8, 0x55 },
+ { 0xe9, 0x0e },
+ { 0xe7, 0x00 },
+ { 0xe8, 0x4c },
+ { 0xe9, 0x0f },
+ { 0xe7, 0x00 },
+ { 0xe8, 0x4d },
+ { 0xe9, 0x10 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0x43 },
+ { 0xe9, 0x11 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0x39 },
+ { 0xe9, 0x12 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0x26 },
+ { 0xe9, 0x13 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0x1e },
+ { 0xe9, 0x14 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0x0d },
+ { 0xe9, 0x15 },
+ { 0xe7, 0x07 },
+ { 0xe8, 0xd8 },
+ { 0xe9, 0x16 },
+ { 0xe7, 0x07 },
+ { 0xe8, 0xd8 },
+ { 0xe9, 0x17 },
+ { 0xe7, 0x07 },
+ { 0xe8, 0xe1 },
+ { 0xe9, 0x18 },
+ { 0xe7, 0x07 },
+ { 0xe8, 0xdc },
+ { 0xe9, 0x19 },
+ { 0xe7, 0x07 },
+ { 0xe8, 0xd3 },
+ { 0xe9, 0x1a },
+ { 0xe7, 0x07 },
+ { 0xe8, 0xcb },
+ { 0xe9, 0x1b },
+ { 0xe7, 0x07 },
+ { 0xe8, 0xbe },
+ { 0xe9, 0x1c },
+ { 0xe7, 0x07 },
+ { 0xe8, 0x62 },
+ { 0xe9, 0x1d },
+ { 0xe7, 0x07 },
+ { 0xe8, 0x66 },
+ { 0xe9, 0x1e },
+ { 0xe7, 0x07 },
+ { 0xe8, 0x71 },
+ { 0xe9, 0x1f },
+ { 0xe7, 0x07 },
+ { 0xe8, 0x80 },
+ { 0xe9, 0x20 },
+ { 0xe7, 0x07 },
+ { 0xe8, 0x75 },
+ { 0xe9, 0x21 },
+ { 0xe7, 0x07 },
+ { 0xe8, 0x67 },
+ { 0xe9, 0x22 },
+ { 0xe7, 0x07 },
+ { 0xe8, 0x85 },
+ { 0xe9, 0x40 },
+
+
+ { 0xd1, 0x08 },
+ { 0xdd, 0x03 },
+
+ { 0x23, 0x17 },
+ { 0x24, 0x17 },
+ { 0x25, 0x17 },
+ { 0x27, 0x18 },
+ { 0x29, 0x60 },
+ { 0x2a, 0x22 },
+
+ { 0x2f, 0x01 },
+
+ { 0x36, 0x01 },
+ { 0x37, 0xc2 },
+ { 0x38, 0xa8 },
+ { 0x39, 0x98 },
+ { 0x3a, 0x00 },
+ { 0x3b, 0xf0 },
+ { 0x3c, 0x01 },
+ { 0x3d, 0x5e },
+ { 0xb9, 0x02 },
+ { 0xbb, 0xb0 },
+ { 0xbc, 0x18 },
+ { 0xbd, 0x30 },
+ { 0xbf, 0x38 },
+ { 0xc1, 0x88 },
+ { 0xc8, 0x11 },
+ { 0xeb, 0x81 },
+ { 0xed, 0x05 },
+ { 0xb1, 0x00 },
+ { 0xb2, 0x62 },
+ { 0xb3, 0x00 },
+ { 0xb4, 0x00 },
+ { 0xb5, 0x01 },
+ { 0xb6, 0xa3 },
+ { 0xb7, 0x02 },
+ { 0xb8, 0x80 },
+ { 0x77, 0x00 },
+ { 0x78, 0x00 },
+ { 0xef, 0x00 },
+ { 0x93, 0x40 },
+ { 0x94, 0x80 },
+ { 0x95, 0xc0 },
+ { 0x96, 0xc0 },
+ { 0x97, 0x20 },
+ { 0x98, 0x20 },
+ { 0x99, 0x30 },
+ { 0xA0, 0x00 },
+ { 0xA1, 0x00 },
+ { 0xA2, 0x1c },
+ { 0xA3, 0x16 },
+ { 0xA4, 0x03 },
+ { 0xA5, 0x07 },
+ { 0xA6, 0x00 },
+ { 0xef, 0x00 },
+ { 0xad, 0xd0 },
+ { 0xaf, 0x10 },
+ { 0xef, 0x00 },
+ { 0x42, 0x65 },
+ { 0x44, 0x61 },
+
+ { 0x57, 0x00 },
+
+ { 0xef, 0x03 },
+ { 0x01, 0x3C },
+ { 0x02, 0x05 },
+ { 0x03, 0x21 },
+ { 0x04, 0x60 },
+ { 0x06, 0x1c },
+ { 0x07, 0x01 },
+ { 0x08, 0x01 },
+ { 0x0b, 0x01 },
+ { 0x51, 0x10 },
+ { 0x52, 0x00 },
+ { 0x53, 0x00 },
+ { 0x54, 0x00 },
+ { 0x55, 0x22 },
+ { 0x56, 0x01 },
+ { 0x57, 0x61 },
+ { 0x58, 0x25 },
+ { 0x67, 0xcf },
+ { 0x69, 0x17 },
+ { 0xef, 0x00 },
+ { 0x58, 0x00 },
+ { 0x59, 0x00 },
+ { 0x5a, 0x02 },
+ { 0x5b, 0x73 },
+ { 0x5c, 0x00 },
+ { 0x5d, 0x00 },
+ { 0x5e, 0x01 },
+ { 0x5f, 0xe0 },
+ { 0x60, 0x00 },
+ { 0x61, 0xEA },
+ { 0x62, 0x01 },
+ { 0x63, 0x80 },
+ { 0x64, 0x00 },
+ { 0x65, 0xAF },
+ { 0x66, 0x01 },
+ { 0x67, 0x2D },
+ { 0xef, 0x00 },
+ { 0x6a, 0x01 },
+ { 0x6b, 0xe0 },
+ { 0x6c, 0x05 },
+ { 0x6d, 0x00 },
+ { 0x6e, 0x0e },
+ { 0x6f, 0x00 },
+ { 0x70, 0x10 },
+ { 0xef, 0x03 },
+ { 0x22, 0x24 },
+ { 0x3e, 0x23 },
+ { 0x3f, 0x23 },
+ { 0x40, 0x00 },
+ { 0x41, 0x09 },
+ { 0x4a, 0x09 },
+ { 0x4b, 0x04 },
+ { 0x5b, 0x20 },
+ { 0x5d, 0x35 },
+ { 0x5e, 0x13 },
+ { 0x78, 0x0f },
+ { 0xef, 0x00 },
+ { 0x4c, 0x80 },
+ { 0x4d, 0xbb },
+ { 0x4e, 0x84 },
+ { 0x4f, 0x91 },
+ { 0x50, 0x64 },
+ { 0x51, 0x93 },
+ { 0x52, 0x03 },
+ { 0x53, 0xc7 },
+ { 0x54, 0x83 },
+ { 0xef, 0x03 },
+ { 0x6e, 0x40 },
+ { 0x6f, 0x50 }, /* dgain for shutter 700lux*/
+
+ { 0xef, 0x00 },
+ { 0x48, 0x00 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x03 },
+ { 0x48, 0x01 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x06 },
+ { 0x48, 0x02 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x24 },
+ { 0x48, 0x03 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x8a },
+ { 0x48, 0x04 },
+ { 0x49, 0x01 },
+ { 0x4A, 0x20 },
+ { 0x48, 0x05 },
+ { 0x49, 0x01 },
+ { 0x4A, 0xB4 },
+ { 0x48, 0x06 },
+ { 0x49, 0x02 },
+ { 0x4A, 0x23 },
+ { 0x48, 0x07 },
+ { 0x49, 0x02 },
+ { 0x4A, 0x72 },
+ { 0x48, 0x08 },
+ { 0x49, 0x02 },
+ { 0x4A, 0xBE },
+ { 0x48, 0x09 },
+ { 0x49, 0x02 },
+ { 0x4A, 0xFA },
+ { 0x48, 0x0A },
+ { 0x49, 0x03 },
+ { 0x4A, 0x27 },
+ { 0x48, 0x0B },
+ { 0x49, 0x03 },
+ { 0x4A, 0x55 },
+ { 0x48, 0x0C },
+ { 0x49, 0x03 },
+ { 0x4A, 0x81 },
+ { 0x48, 0x0D },
+ { 0x49, 0x03 },
+ { 0x4A, 0xA2 },
+ { 0x48, 0x0E },
+ { 0x49, 0x03 },
+ { 0x4A, 0xBC },
+ { 0x48, 0x0F },
+ { 0x49, 0x03 },
+ { 0x4A, 0xD4 },
+ { 0x48, 0x10 },
+ { 0x49, 0x03 },
+ { 0x4A, 0xE8 },
+ { 0x48, 0x11 },
+ { 0x49, 0x03 },
+ { 0x4A, 0xF4 },
+ { 0x48, 0x12 },
+ { 0x49, 0x03 },
+ { 0x4A, 0xFF },
+ { 0x48, 0x20 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x03 },
+ { 0x48, 0x21 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x06 },
+ { 0x48, 0x22 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x24 },
+ { 0x48, 0x23 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x8a },
+ { 0x48, 0x24 },
+ { 0x49, 0x01 },
+ { 0x4A, 0x20 },
+ { 0x48, 0x25 },
+ { 0x49, 0x01 },
+ { 0x4A, 0xB4 },
+ { 0x48, 0x26 },
+ { 0x49, 0x02 },
+ { 0x4A, 0x23 },
+ { 0x48, 0x27 },
+ { 0x49, 0x02 },
+ { 0x4A, 0x72 },
+ { 0x48, 0x28 },
+ { 0x49, 0x02 },
+ { 0x4A, 0xBE },
+ { 0x48, 0x29 },
+ { 0x49, 0x02 },
+ { 0x4A, 0xFA },
+ { 0x48, 0x2A },
+ { 0x49, 0x03 },
+ { 0x4A, 0x27 },
+ { 0x48, 0x2B },
+ { 0x49, 0x03 },
+ { 0x4A, 0x55 },
+ { 0x48, 0x2C },
+ { 0x49, 0x03 },
+ { 0x4A, 0x81 },
+ { 0x48, 0x2D },
+ { 0x49, 0x03 },
+ { 0x4A, 0xA2 },
+ { 0x48, 0x2E },
+ { 0x49, 0x03 },
+ { 0x4A, 0xBC },
+ { 0x48, 0x2F },
+ { 0x49, 0x03 },
+ { 0x4A, 0xD4 },
+ { 0x48, 0x30 },
+ { 0x49, 0x03 },
+ { 0x4A, 0xE8 },
+ { 0x48, 0x31 },
+ { 0x49, 0x03 },
+ { 0x4A, 0xF4 },
+ { 0x48, 0x32 },
+ { 0x49, 0x03 },
+ { 0x4A, 0xFF },
+ { 0x48, 0x40 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x03 },
+ { 0x48, 0x41 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x06 },
+ { 0x48, 0x42 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x24 },
+ { 0x48, 0x43 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x8a },
+ { 0x48, 0x44 },
+ { 0x49, 0x01 },
+ { 0x4A, 0x20 },
+ { 0x48, 0x45 },
+ { 0x49, 0x01 },
+ { 0x4A, 0xB4 },
+ { 0x48, 0x46 },
+ { 0x49, 0x02 },
+ { 0x4A, 0x23 },
+ { 0x48, 0x47 },
+ { 0x49, 0x02 },
+ { 0x4A, 0x72 },
+ { 0x48, 0x48 },
+ { 0x49, 0x02 },
+ { 0x4A, 0xBE },
+ { 0x48, 0x49 },
+ { 0x49, 0x02 },
+ { 0x4A, 0xFA },
+ { 0x48, 0x4A },
+ { 0x49, 0x03 },
+ { 0x4A, 0x27 },
+ { 0x48, 0x4B },
+ { 0x49, 0x03 },
+ { 0x4A, 0x55 },
+ { 0x48, 0x4C },
+ { 0x49, 0x03 },
+ { 0x4A, 0x81 },
+ { 0x48, 0x4D },
+ { 0x49, 0x03 },
+ { 0x4A, 0xA2 },
+ { 0x48, 0x4E },
+ { 0x49, 0x03 },
+ { 0x4A, 0xBC },
+ { 0x48, 0x4F },
+ { 0x49, 0x03 },
+ { 0x4A, 0xD4 },
+ { 0x48, 0x50 },
+ { 0x49, 0x03 },
+ { 0x4A, 0xE8 },
+ { 0x48, 0x51 },
+ { 0x49, 0x03 },
+ { 0x4A, 0xF4 },
+ { 0x48, 0x52 },
+ { 0x49, 0x03 },
+ { 0x4A, 0xFF },
+ { 0xEF, 0x03 },
+ { 0x00, 0x03 },
+};
+
+/*
+ * VT init setting
+ */
+struct s5ka3dfx_reg s5ka3dfx_init_vt_reg[] = {
+ { 0xef, 0x02 },
+ { 0x13, 0xa0 },
+ { 0x23, 0x53 },
+ { 0x26, 0x24 },
+ { 0x2c, 0x05 },
+ { 0x05, 0x00 },
+ { 0x03, 0x58 },
+ { 0x24, 0x0a },
+ { 0x0b, 0x82 },
+ { 0x1e, 0xb7 },
+ { 0x56, 0x05 },
+ { 0x28, 0x96 },
+ { 0x67, 0x3c },
+ { 0x4b, 0x5e },
+ { 0xef, 0x03 },
+ { 0x50, 0xd2 },
+ { 0x0f, 0x31 },
+ { 0xef, 0x03 },
+ { 0x5F, 0x03 },
+ { 0x60, 0x02 },
+ { 0x61, 0x0f },
+ { 0x62, 0x0c },
+ { 0x63, 0x05 },
+ { 0x64, 0x43 },
+ { 0x65, 0x05 },
+ { 0x66, 0x43 },
+ { 0x6d, 0x5a },
+ { 0x6e, 0x40 },
+ { 0x6f, 0x70 },
+ { 0x4c, 0x00 },
+ { 0x4d, 0x9e },
+ { 0xef, 0x03 },
+ { 0x00, 0x87 },
+ { 0x01, 0x80 },
+ { 0x02, 0x7f },
+ { 0x2b, 0x41 },
+ { 0x31, 0x07 },
+ { 0x32, 0x18 },
+ { 0x33, 0x80 },
+ { 0x34, 0x79 },
+ { 0x36, 0x36 },
+ { 0x37, 0x27 },
+ { 0x6a, 0x00 },
+ { 0x7b, 0x05 },
+ { 0x38, 0x05 },
+ { 0x39, 0x03 },
+ { 0x2d, 0x08 },
+ { 0x2e, 0x20 },
+ { 0x2f, 0x30 },
+ { 0x30, 0xff },
+ { 0x7c, 0x06 },
+ { 0x7d, 0x20 },
+ { 0x7e, 0x0c },
+ { 0x7f, 0x20 },
+ { 0x28, 0x02 },
+ { 0x29, 0xa8 },
+ { 0x2a, 0x00 },
+ { 0x13, 0x00 },
+ { 0x14, 0xa0 },
+ { 0x1a, 0x6a },
+ { 0x1b, 0x50 },
+ { 0x1c, 0x63 },
+ { 0x1d, 0x4b },
+ { 0x1e, 0x6a },
+ { 0x1f, 0x3c },
+ { 0x20, 0x9a },
+ { 0x21, 0x4b },
+ { 0x3a, 0x13 },
+ { 0x3b, 0x3e },
+ { 0x3c, 0x00 },
+ { 0x3d, 0x18 },
+ { 0x23, 0x80 },
+ { 0x15, 0x0b },
+ { 0x16, 0xd2 },
+ { 0x17, 0x64 },
+ { 0x18, 0x78 },
+ { 0xef, 0x00 },
+ { 0xde, 0x00 },
+ { 0xdf, 0x1F },
+ { 0xe0, 0x00 },
+ { 0xe1, 0x37 },
+ { 0xe2, 0x08 },
+ { 0xe3, 0x42 },
+ { 0xe4, 0x00 },
+ { 0xe5, 0x12 },
+ { 0xe6, 0x9E },
+ { 0xe9, 0x00 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0xA8 },
+ { 0xe9, 0x01 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0xB1 },
+ { 0xe9, 0x02 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0xC4 },
+ { 0xe9, 0x03 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0xBA },
+ { 0xe9, 0x04 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0xC4 },
+ { 0xe9, 0x05 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0xE5 },
+ { 0xe9, 0x06 },
+ { 0xe7, 0x01 },
+ { 0xe8, 0x13 },
+ { 0xe9, 0x07 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0x4B },
+ { 0xe9, 0x08 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0x4B },
+ { 0xe9, 0x09 },
+ { 0xe7, 0x00 },
+ { 0xe8, 0x4E },
+ { 0xe9, 0x0A },
+ { 0xe7, 0x00 },
+ { 0xe8, 0x4F },
+ { 0xe9, 0x0B },
+ { 0xe7, 0x00 },
+ { 0xe8, 0x42 },
+ { 0xe9, 0x0C },
+ { 0xe7, 0x00 },
+ { 0xe8, 0x6A },
+ { 0xe9, 0x0D },
+ { 0xe7, 0x00 },
+ { 0xe8, 0x89 },
+ { 0xe9, 0x0E },
+ { 0xe7, 0x07 },
+ { 0xe8, 0xD9 },
+ { 0xe9, 0x0F },
+ { 0xe7, 0x07 },
+ { 0xe8, 0xD8 },
+ { 0xe9, 0x10 },
+ { 0xe7, 0x07 },
+ { 0xe8, 0xDD },
+ { 0xe9, 0x11 },
+ { 0xe7, 0x07 },
+ { 0xe8, 0xD1 },
+ { 0xe9, 0x12 },
+ { 0xe7, 0x07 },
+ { 0xe8, 0xCA },
+ { 0xe9, 0x13 },
+ { 0xe7, 0x07 },
+ { 0xe8, 0xCE },
+ { 0xe9, 0x14 },
+ { 0xe7, 0x07 },
+ { 0xe8, 0xFA },
+ { 0xe9, 0x15 },
+ { 0xe7, 0x07 },
+ { 0xe8, 0x6A },
+ { 0xe9, 0x16 },
+ { 0xe7, 0x07 },
+ { 0xe8, 0x71 },
+ { 0xe9, 0x17 },
+ { 0xe7, 0x07 },
+ { 0xe8, 0x70 },
+ { 0xe9, 0x18 },
+ { 0xe7, 0x07 },
+ { 0xe8, 0x5E },
+ { 0xe9, 0x19 },
+ { 0xe7, 0x07 },
+ { 0xe8, 0x50 },
+ { 0xe9, 0x1A },
+ { 0xe7, 0x07 },
+ { 0xe8, 0x55 },
+ { 0xe9, 0x1B },
+ { 0xe7, 0x07 },
+ { 0xe8, 0x6D },
+ { 0xe9, 0x1C },
+ { 0xe7, 0x07 },
+ { 0xe8, 0x1C },
+ { 0xe9, 0x1D },
+ { 0xe7, 0x07 },
+ { 0xe8, 0x12 },
+ { 0xe9, 0x1E },
+ { 0xe7, 0x07 },
+ { 0xe8, 0x07 },
+ { 0xe9, 0x1F },
+ { 0xe7, 0x06 },
+ { 0xe8, 0xFA },
+ { 0xe9, 0x20 },
+ { 0xe7, 0x06 },
+ { 0xe8, 0xE5 },
+ { 0xe9, 0x21 },
+ { 0xe7, 0x06 },
+ { 0xe8, 0xF0 },
+ { 0xe9, 0x22 },
+ { 0xe7, 0x07 },
+ { 0xe8, 0x0A },
+ { 0xe9, 0x40 },
+ { 0xd1, 0x08 },
+ { 0xdd, 0x03 },
+ { 0x23, 0x10 },
+ { 0x24, 0x10 },
+ { 0x25, 0x10 },
+ { 0x27, 0x18 },
+ { 0x29, 0x60 },
+ { 0x2a, 0x22 },
+ { 0x2f, 0x01 },
+ { 0x36, 0x01 },
+ { 0x37, 0xe1 },
+ { 0x38, 0xc7 },
+ { 0x39, 0xb1 },
+ { 0x3a, 0x01 },
+ { 0x3b, 0x04 },
+ { 0x3c, 0x01 },
+ { 0x3d, 0x54 },
+ { 0xb9, 0x02 },
+ { 0xbb, 0xb0 },
+ { 0xbc, 0x18 },
+ { 0xbd, 0x30 },
+ { 0xbf, 0x38 },
+ { 0xc1, 0x88 },
+ { 0xc8, 0x11 },
+ { 0xeb, 0x81 },
+ { 0xed, 0x05 },
+ { 0xb1, 0x00 },
+ { 0xb2, 0x62 },
+ { 0xb3, 0x00 },
+ { 0xb4, 0x00 },
+ { 0xb5, 0x01 },
+ { 0xb6, 0xa3 },
+ { 0xb7, 0x02 },
+ { 0xb8, 0x80 },
+ { 0x77, 0x00 },
+ { 0x78, 0x10 },
+ { 0xef, 0x00 },
+ { 0x93, 0x40 },
+ { 0x94, 0x80 },
+ { 0x95, 0xc0 },
+ { 0x96, 0xc0 },
+ { 0x97, 0x20 },
+ { 0x98, 0x20 },
+ { 0x99, 0x30 },
+ { 0xA0, 0x00 },
+ { 0xA1, 0x00 },
+ { 0xA2, 0x1c },
+ { 0xA3, 0x16 },
+ { 0xA4, 0x03 },
+ { 0xA5, 0x07 },
+ { 0xA6, 0x00 },
+ { 0xef, 0x00 },
+ { 0xad, 0xd0 },
+ { 0xaf, 0x10 },
+ { 0xef, 0x00 },
+ { 0x42, 0x5f },
+ { 0x44, 0x61 },
+ { 0x57, 0x00 },
+ { 0xef, 0x03 },
+ { 0x00, 0x87 },
+ { 0x01, 0x3c },
+ { 0x02, 0x05 },
+ { 0x03, 0x21 },
+ { 0x04, 0x6c },
+ { 0x06, 0x1c },
+ { 0x07, 0x01 },
+ { 0x08, 0x01 },
+ { 0x0b, 0x01 },
+ { 0x51, 0x10 },
+ { 0x52, 0x00 },
+ { 0x53, 0x00 },
+ { 0x54, 0x00 },
+ { 0x55, 0x22 },
+ { 0x56, 0x01 },
+ { 0x57, 0x61 },
+ { 0x58, 0x25 },
+ { 0x67, 0xcf },
+ { 0x69, 0x17 },
+ { 0xef, 0x00 },
+ { 0x58, 0x00 },
+ { 0x59, 0x00 },
+ { 0x5a, 0x02 },
+ { 0x5b, 0x73 },
+ { 0x5c, 0x00 },
+ { 0x5d, 0x00 },
+ { 0x5e, 0x01 },
+ { 0x5f, 0xe0 },
+ { 0x60, 0x00 },
+ { 0x61, 0xae },
+ { 0x62, 0x01 },
+ { 0x63, 0xbb },
+ { 0x64, 0x00 },
+ { 0x65, 0x7e },
+ { 0x66, 0x01 },
+ { 0x67, 0x8e },
+ { 0xef, 0x00 },
+ { 0x6a, 0x01 },
+ { 0x6b, 0xe0 },
+ { 0x6c, 0x05 },
+ { 0x6d, 0x00 },
+ { 0x6e, 0x0e },
+ { 0x6f, 0x00 },
+ { 0x70, 0x10 },
+ { 0xef, 0x03 },
+ { 0x22, 0x24 },
+ { 0x3e, 0x23 },
+ { 0x3f, 0x23 },
+ { 0x40, 0x00 },
+ { 0x41, 0x09 },
+ { 0x4a, 0x09 },
+ { 0x4b, 0x04 },
+ { 0x5b, 0x20 },
+ { 0x5d, 0x35 },
+ { 0x5e, 0x13 },
+ { 0x78, 0x0f },
+ { 0xef, 0x00 },
+ { 0x4c, 0x79 },
+ { 0x4d, 0xbe },
+ { 0x4e, 0x08 },
+ { 0x4f, 0x9c },
+ { 0x50, 0x7a },
+ { 0x51, 0x9e },
+ { 0x52, 0x8f },
+ { 0x53, 0xbb },
+ { 0x54, 0x8a },
+ { 0xef, 0x03 },
+ { 0x70, 0x00 },
+ { 0xef, 0x00 },
+ { 0x48, 0x00 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x03 },
+ { 0x48, 0x01 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x08 },
+ { 0x48, 0x02 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x4A },
+ { 0x48, 0x03 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x96 },
+ { 0x48, 0x04 },
+ { 0x49, 0x01 },
+ { 0x4A, 0x24 },
+ { 0x48, 0x05 },
+ { 0x49, 0x01 },
+ { 0x4A, 0xB4 },
+ { 0x48, 0x06 },
+ { 0x49, 0x02 },
+ { 0x4A, 0x23 },
+ { 0x48, 0x07 },
+ { 0x49, 0x02 },
+ { 0x4A, 0x72 },
+ { 0x48, 0x08 },
+ { 0x49, 0x02 },
+ { 0x4A, 0xBE },
+ { 0x48, 0x09 },
+ { 0x49, 0x02 },
+ { 0x4A, 0xFA },
+ { 0x48, 0x0A },
+ { 0x49, 0x03 },
+ { 0x4A, 0x27 },
+ { 0x48, 0x0B },
+ { 0x49, 0x03 },
+ { 0x4A, 0x55 },
+ { 0x48, 0x0C },
+ { 0x49, 0x03 },
+ { 0x4A, 0x81 },
+ { 0x48, 0x0D },
+ { 0x49, 0x03 },
+ { 0x4A, 0xA2 },
+ { 0x48, 0x0E },
+ { 0x49, 0x03 },
+ { 0x4A, 0xBC },
+ { 0x48, 0x0F },
+ { 0x49, 0x03 },
+ { 0x4A, 0xD4 },
+ { 0x48, 0x10 },
+ { 0x49, 0x03 },
+ { 0x4A, 0xE8 },
+ { 0x48, 0x11 },
+ { 0x49, 0x03 },
+ { 0x4A, 0xF4 },
+ { 0x48, 0x12 },
+ { 0x49, 0x03 },
+ { 0x4A, 0xFF },
+ { 0x48, 0x20 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x03 },
+ { 0x48, 0x21 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x08 },
+ { 0x48, 0x22 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x4A },
+ { 0x48, 0x23 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x96 },
+ { 0x48, 0x24 },
+ { 0x49, 0x01 },
+ { 0x4A, 0x24 },
+ { 0x48, 0x25 },
+ { 0x49, 0x01 },
+ { 0x4A, 0xB4 },
+ { 0x48, 0x26 },
+ { 0x49, 0x02 },
+ { 0x4A, 0x23 },
+ { 0x48, 0x27 },
+ { 0x49, 0x02 },
+ { 0x4A, 0x72 },
+ { 0x48, 0x28 },
+ { 0x49, 0x02 },
+ { 0x4A, 0xBE },
+ { 0x48, 0x29 },
+ { 0x49, 0x02 },
+ { 0x4A, 0xFA },
+ { 0x48, 0x2A },
+ { 0x49, 0x03 },
+ { 0x4A, 0x27 },
+ { 0x48, 0x2B },
+ { 0x49, 0x03 },
+ { 0x4A, 0x55 },
+ { 0x48, 0x2C },
+ { 0x49, 0x03 },
+ { 0x4A, 0x81 },
+ { 0x48, 0x2D },
+ { 0x49, 0x03 },
+ { 0x4A, 0xA2 },
+ { 0x48, 0x2E },
+ { 0x49, 0x03 },
+ { 0x4A, 0xBC },
+ { 0x48, 0x2F },
+ { 0x49, 0x03 },
+ { 0x4A, 0xD4 },
+ { 0x48, 0x30 },
+ { 0x49, 0x03 },
+ { 0x4A, 0xE8 },
+ { 0x48, 0x31 },
+ { 0x49, 0x03 },
+ { 0x4A, 0xF4 },
+ { 0x48, 0x32 },
+ { 0x49, 0x03 },
+ { 0x4A, 0xFF },
+ { 0x48, 0x40 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x03 },
+ { 0x48, 0x41 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x08 },
+ { 0x48, 0x42 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x4A },
+ { 0x48, 0x43 },
+ { 0x49, 0x00 },
+ { 0x4A, 0x96 },
+ { 0x48, 0x44 },
+ { 0x49, 0x01 },
+ { 0x4A, 0x24 },
+ { 0x48, 0x45 },
+ { 0x49, 0x01 },
+ { 0x4A, 0xB4 },
+ { 0x48, 0x46 },
+ { 0x49, 0x02 },
+ { 0x4A, 0x23 },
+ { 0x48, 0x47 },
+ { 0x49, 0x02 },
+ { 0x4A, 0x72 },
+ { 0x48, 0x48 },
+ { 0x49, 0x02 },
+ { 0x4A, 0xBE },
+ { 0x48, 0x49 },
+ { 0x49, 0x02 },
+ { 0x4A, 0xFA },
+ { 0x48, 0x4A },
+ { 0x49, 0x03 },
+ { 0x4A, 0x27 },
+ { 0x48, 0x4B },
+ { 0x49, 0x03 },
+ { 0x4A, 0x55 },
+ { 0x48, 0x4C },
+ { 0x49, 0x03 },
+ { 0x4A, 0x81 },
+ { 0x48, 0x4D },
+ { 0x49, 0x03 },
+ { 0x4A, 0xA2 },
+ { 0x48, 0x4E },
+ { 0x49, 0x03 },
+ { 0x4A, 0xBC },
+ { 0x48, 0x4F },
+ { 0x49, 0x03 },
+ { 0x4A, 0xD4 },
+ { 0x48, 0x50 },
+ { 0x49, 0x03 },
+ { 0x4A, 0xE8 },
+ { 0x48, 0x51 },
+ { 0x49, 0x03 },
+ { 0x4A, 0xF4 },
+ { 0x48, 0x52 },
+ { 0x49, 0x03 },
+ { 0x4A, 0xFF },
+};
+
+/* Exposure Value Setting */
+/* EV bias */
+struct s5ka3dfx_reg s5ka3dfx_ev_m5[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0xc0 },
+ { 0x32, 0x98 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_ev_m4[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0xA5 },
+ { 0x32, 0x90 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_ev_m3[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0x9E },
+ { 0x32, 0x88 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_ev_m2[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0x90 },
+ { 0x32, 0x00 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_ev_m1[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0x8A },
+ { 0x32, 0x08 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_ev_default[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0x00 },
+ { 0x32, 0x09 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_ev_p1[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0x0A },
+ { 0x32, 0x20 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_ev_p2[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0x14 },
+ { 0x32, 0x30 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_ev_p3[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0x1E },
+ { 0x32, 0x38 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_ev_p4[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0x28 },
+ { 0x32, 0x40 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_ev_p5[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0x30 },
+ { 0x32, 0x48 },
+};
+
+/* EV bias for VT */
+struct s5ka3dfx_reg s5ka3dfx_ev_vt_m5[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0xa9 },
+ { 0x32, 0xa4 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_ev_vt_m4[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0x99 },
+ { 0x32, 0x9c },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_ev_vt_m3[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0x91 },
+ { 0x32, 0x94 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_ev_vt_m2[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0x89 },
+ { 0x32, 0x08 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_ev_vt_m1[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0x81 },
+ { 0x32, 0x10 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_ev_vt_default[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0x07 },
+ { 0x32, 0x18 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_ev_vt_p1[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0x0e },
+ { 0x32, 0x28 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_ev_vt_p2[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0x17 },
+ { 0x32, 0x38 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_ev_vt_p3[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0x27 },
+ { 0x32, 0x40 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_ev_vt_p4[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0x2a },
+ { 0x32, 0x3e },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_ev_vt_p5[] = {
+ { 0xef, 0x03 },
+ { 0x31, 0x32 },
+ { 0x32, 0x46 },
+};
+
+/* White Balance Setting */
+struct s5ka3dfx_reg s5ka3dfx_wb_auto[] = {
+ { 0xef, 0x03 },
+ { 0x00, 0x87 },
+ { 0xef, 0x00 },
+ { 0x42, 0x6f },
+ { 0x43, 0x40 },
+ { 0x44, 0x5a },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_wb_tungsten[] = {
+ { 0xef, 0x03 },
+ { 0x00, 0x85 },
+ { 0xef, 0x00 },
+ { 0x42, 0x48 },
+ { 0x43, 0x43 },
+ { 0x44, 0x7e },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_wb_fluorescent[] = {
+ { 0xef, 0x03 },
+ { 0x00, 0x85 },
+ { 0xef, 0x00 },
+ { 0x42, 0x5c },
+ { 0x43, 0x40 },
+ { 0x44, 0x6d },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_wb_sunny[] = {
+ { 0xef, 0x03 },
+ { 0x00, 0x85 },
+ { 0xef, 0x00 },
+ { 0x42, 0x67 },
+ { 0x43, 0x40 },
+ { 0x44, 0x4c },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_wb_cloudy[] = {
+ { 0xef, 0x03 },
+ { 0x00, 0x85 },
+ { 0xef, 0x00 },
+ { 0x42, 0x75 },
+ { 0x43, 0x3d },
+ { 0x44, 0x42 },
+};
+
+/* Effect Setting */
+struct s5ka3dfx_reg s5ka3dfx_effect_none[] = {
+ { 0xef, 0x00 },
+ { 0xd3, 0x00 },
+ { 0xd4, 0x00 },
+ { 0xd5, 0x01 },
+ { 0xd6, 0xa3 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_effect_gray[] = {
+ { 0xef, 0x00 },
+ { 0xd3, 0x00 },
+ { 0xd4, 0x03 },
+ { 0xd5, 0x80 },
+ { 0xd6, 0x80 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_effect_sepia[] = {
+ { 0xef, 0x00 },
+ { 0xd3, 0x00 },
+ { 0xd4, 0x03 },
+ { 0xd5, 0x60 },
+ { 0xd6, 0x8c },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_effect_negative[] = {
+ { 0xef, 0x00 },
+ { 0xd3, 0x01 },
+ { 0xd4, 0x00 },
+ { 0xd5, 0x2c },
+ { 0xd6, 0x81 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_effect_aqua[] = {
+ { 0xef, 0x00 },
+ { 0xd3, 0x00 },
+ { 0xd4, 0x03 },
+ { 0xd5, 0xdc },
+ { 0xd6, 0x00 },
+};
+
+/* Blur Setting */
+/*Self shot*/
+struct s5ka3dfx_reg s5ka3dfx_blur_none[] = {
+ { 0xef, 0x03 },
+ { 0x01, 0x3c },
+ { 0x29, 0x8f },
+ { 0x34, 0x79 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_blur_p1[] = {
+ { 0xef, 0x03 },
+ { 0x01, 0x4a },
+ { 0x29, 0x5f },
+ { 0x34, 0x89 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_blur_p2[] = {
+ { 0xef, 0x03 },
+ { 0x01, 0x58 },
+ { 0x29, 0x2f },
+ { 0x34, 0x99 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_blur_p3[] = {
+ { 0xef, 0x03 },
+ { 0x01, 0x66 },
+ { 0x29, 0x00 },
+ { 0x34, 0xa9 },
+};
+
+/*vt call*/
+struct s5ka3dfx_reg s5ka3dfx_blur_vt_none[] = {
+ { 0xef, 0x03 },
+ { 0x01, 0x3c },
+ { 0x29, 0xa8 },
+ { 0x34, 0x79 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_blur_vt_p1[] = {
+ { 0xef, 0x03 },
+ { 0x01, 0x4a },
+ { 0x29, 0x68 },
+ { 0x34, 0x89 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_blur_vt_p2[] = {
+ { 0xef, 0x03 },
+ { 0x01, 0x58 },
+ { 0x29, 0x38 },
+ { 0x34, 0x99 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_blur_vt_p3[] = {
+ { 0xef, 0x03 },
+ { 0x01, 0x66 },
+ { 0x29, 0x18 },
+ { 0x34, 0xa9 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_dataline[] = {
+ { 0xef, 0x00 },
+ { 0x0a, 0x01 }, /* s/w reset */
+ { 0x04, 0x01 },
+ { 0xcb, 0x01 },
+ { 0xd1, 0x08 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_dataline_stop[] = {
+ { 0xef, 0x00 },
+ { 0xcb, 0x00 },
+};
+
+/* FPS */
+struct s5ka3dfx_reg s5ka3dfx_fps_7[] = {
+ { 0xEF, 0x03 },
+ { 0x5F, 0x03 },
+ { 0x60, 0x02 },
+ { 0x61, 0x11 },
+ { 0x62, 0x0E },
+ { 0x63, 0x06 },
+ { 0x64, 0x4B },
+ { 0x65, 0x06 },
+ { 0x66, 0x4B },
+ { 0x48, 0x00 },
+ { 0x49, 0x9E },
+ { 0x4C, 0x00 },
+ { 0x4D, 0x9E },
+ { 0xEF, 0x03 },
+ { 0x51, 0x10 },
+ { 0x52, 0x00 },
+ { 0x53, 0x00 },
+ { 0x54, 0x00 },
+ { 0x56, 0x01 },
+ { 0x57, 0x61 },
+ { 0x58, 0x25 },
+ { 0x67, 0xCF },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_fps_10[] = {
+ { 0xEF, 0x03 },
+ { 0x5F, 0x03 },
+ { 0x60, 0x02 },
+ { 0x61, 0x0C },
+ { 0x62, 0x0A },
+ { 0x63, 0x03 },
+ { 0x64, 0xD3 },
+ { 0x65, 0x03 },
+ { 0x66, 0xD3 },
+ { 0x48, 0x00 },
+ { 0x49, 0x9E },
+ { 0x4C, 0x00 },
+ { 0x4D, 0x9E },
+ { 0xEF, 0x03 },
+ { 0x51, 0x10 },
+ { 0x52, 0x00 },
+ { 0x53, 0x00 },
+ { 0x54, 0x00 },
+ { 0x56, 0x01 },
+ { 0x57, 0x61 },
+ { 0x58, 0x25 },
+ { 0x67, 0xCF },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_fps_15[] = {
+ { 0xEF, 0x03 },
+ { 0x5F, 0x03 },
+ { 0x60, 0x02 },
+ { 0x61, 0x08 },
+ { 0x62, 0x06 },
+ { 0x63, 0x01 },
+ { 0x64, 0xE7 },
+ { 0x65, 0x01 },
+ { 0x66, 0xE7 },
+ { 0x48, 0x00 },
+ { 0x49, 0x9E },
+ { 0x4C, 0x00 },
+ { 0x4D, 0x9E },
+ { 0xEF, 0x03 },
+ { 0x51, 0x10 },
+ { 0x52, 0x00 },
+ { 0x53, 0x00 },
+ { 0x54, 0x00 },
+ { 0x56, 0x01 },
+ { 0x57, 0x61 },
+ { 0x58, 0x25 },
+ { 0x67, 0xCF },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_fps_auto[] = {
+ { 0xEF, 0x03 },
+ { 0x5F, 0x03 },
+ { 0x60, 0x02 },
+ { 0x61, 0x0F },
+ { 0x62, 0x0C },
+ { 0x63, 0x01 },
+ { 0x64, 0xE7 },
+ { 0x65, 0x01 },
+ { 0x66, 0xE7 },
+ { 0x48, 0x00 },
+ { 0x49, 0x9E },
+ { 0x4C, 0x00 },
+ { 0x4D, 0x9E },
+ { 0xEF, 0x03 },
+ { 0x51, 0x10 },
+ { 0x52, 0x00 },
+ { 0x53, 0x00 },
+ { 0x54, 0x00 },
+ { 0x56, 0x01 },
+ { 0x57, 0x61 },
+ { 0x58, 0x25 },
+ { 0x67, 0xCF },
+};
+struct s5ka3dfx_reg s5ka3dfx_vt_fps_7[] = {
+ { 0xef, 0x03 },
+ { 0x50, 0xd2 },
+ { 0x0f, 0x31 },
+ { 0xef, 0x03 },
+ { 0x5f, 0x11 },
+ { 0x60, 0x0e },
+ { 0x61, 0x11 },
+ { 0x62, 0x0e },
+ { 0x63, 0x06 },
+ { 0x64, 0x4b },
+ { 0x65, 0x06 },
+ { 0x66, 0x4b },
+ { 0x6d, 0x6c },
+ { 0x6E, 0x40 },
+ { 0x6f, 0x40 },
+ { 0x4c, 0x00 },
+ { 0x4d, 0x9E },
+ { 0x51, 0x10 },
+ { 0x52, 0x00 },
+ { 0x53, 0x00 },
+ { 0x54, 0x00 },
+ { 0x55, 0x22 },
+ { 0x56, 0x01 },
+ { 0x57, 0x61 },
+ { 0x58, 0x25 },
+ { 0x67, 0xcf },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_vt_fps_10[] = {
+ { 0xef, 0x03 },
+ { 0x50, 0xd2 },
+ { 0x0f, 0x31 },
+ { 0xef, 0x03 },
+ { 0x5f, 0x0c },
+ { 0x60, 0x0a },
+ { 0x61, 0x0c },
+ { 0x62, 0x0a },
+ { 0x63, 0x03 },
+ { 0x64, 0xd3 },
+ { 0x65, 0x03 },
+ { 0x66, 0xd3 },
+ { 0x6d, 0x6C },
+ { 0x6E, 0x40 },
+ { 0x6f, 0x40 },
+ { 0x4c, 0x00 },
+ { 0x4d, 0x9E },
+ { 0x51, 0x10 },
+ { 0x52, 0x00 },
+ { 0x53, 0x00 },
+ { 0x54, 0x00 },
+ { 0x55, 0x22 },
+ { 0x56, 0x01 },
+ { 0x57, 0x61 },
+ { 0x58, 0x25 },
+ { 0x67, 0xcf },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_vt_fps_15[] = {
+ { 0xef, 0x03 },
+ { 0x50, 0xd2 },
+ { 0x0f, 0x31 },
+ { 0xef, 0x03 },
+ { 0x5f, 0x08 },
+ { 0x60, 0x06 },
+ { 0x61, 0x08 },
+ { 0x62, 0x06 },
+ { 0x63, 0x01 },
+ { 0x64, 0xE7 },
+ { 0x65, 0x01 },
+ { 0x66, 0xE7 },
+ { 0x6d, 0x6C },
+ { 0x6E, 0x40 },
+ { 0x6f, 0x40 },
+ { 0x4c, 0x00 },
+ { 0x4d, 0x9E },
+ { 0x51, 0x10 },
+ { 0x52, 0x00 },
+ { 0x53, 0x00 },
+ { 0x54, 0x00 },
+ { 0x55, 0x22 },
+ { 0x56, 0x01 },
+ { 0x57, 0x61 },
+ { 0x58, 0x25 },
+ { 0x67, 0xcf },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_vt_fps_auto[] = {
+ { 0xef, 0x03 },
+ { 0x50, 0xd2 },
+ { 0x0f, 0x31 },
+ { 0xef, 0x03 },
+ { 0x5f, 0x03 },
+ { 0x60, 0x02 },
+ { 0x61, 0x0f },
+ { 0x62, 0x0c },
+ { 0x63, 0x05 },
+ { 0x64, 0x43 },
+ { 0x65, 0x05 },
+ { 0x66, 0x43 },
+ { 0x6d, 0x5a },
+ { 0x6E, 0x40 },
+ { 0x6f, 0x70 },
+ { 0x4c, 0x00 },
+ { 0x4d, 0x9E },
+ { 0x51, 0x10 },
+ { 0x52, 0x00 },
+ { 0x53, 0x00 },
+ { 0x54, 0x00 },
+ { 0x55, 0x22 },
+ { 0x56, 0x01 },
+ { 0x57, 0x61 },
+ { 0x58, 0x25 },
+ { 0x67, 0xcf },
+
+};
+
+struct s5ka3dfx_reg s5ka3dfx_Return_VGA[] = {
+ { 0xef, 0x00 },
+ { 0x7a, 0x00 },
+ { 0x11, 0x00 },
+ { 0x12, 0x00 },
+ { 0x15, 0x02 },
+ { 0x16, 0x90 },
+ { 0x13, 0x01 },
+ { 0x14, 0xF0 },
+ { 0x31, 0x04 },
+ { 0x30, 0x06 },
+ { 0x34, 0x02 },
+ { 0x35, 0x88 },
+ { 0x32, 0x01 },
+ { 0x33, 0xE8 },
+ { 0x7d, 0x02 },
+ { 0x7e, 0x88 },
+ { 0x7b, 0x01 },
+ { 0x7C, 0xe8 },
+ { 0x81, 0x02 },
+ { 0x82, 0x01 },
+ { 0x7f, 0x01 },
+ { 0x80, 0xe8 },
+ { 0xc3, 0x04 },
+ { 0xc2, 0x04 },
+ { 0xc6, 0x02 },
+ { 0xc7, 0x80 },
+ { 0xc4, 0x01 },
+ { 0xc5, 0xe0 },
+ { 0x7a, 0x01 },
+};
+
+struct s5ka3dfx_reg s5ka3dfx_QVGA[] = { /* 320 x 240 */
+ { 0xef, 0x00 },
+ { 0x7a, 0x00 },
+ { 0x11, 0x00 },
+ { 0x12, 0x00 },
+ { 0x15, 0x02 },
+ { 0x16, 0x90 },
+ { 0x13, 0x01 },
+ { 0x14, 0xF0 },
+ { 0x31, 0x04 },
+ { 0x30, 0x06 },
+ { 0x34, 0x02 },
+ { 0x35, 0x88 },
+ { 0x32, 0x01 },
+ { 0x33, 0xE8 },
+ { 0x7d, 0x02 },
+ { 0x7e, 0x88 },
+ { 0x7b, 0x01 },
+ { 0x7c, 0xe8 },
+ { 0x81, 0x01 },
+ { 0x82, 0x48 },
+ { 0x7f, 0x00 },
+ { 0x80, 0xf8 },
+ { 0xc3, 0x04 },
+ { 0xc2, 0x04 },
+ { 0xc6, 0x01 },
+ { 0xc7, 0x40 },
+ { 0xc4, 0x00 },
+ { 0xc5, 0xf0 },
+ { 0x7a, 0x03 },
+};
+
+
+struct s5ka3dfx_reg s5ka3dfx_QCIF[] = { /* 176 x 144 */
+ { 0xef, 0x00 },
+ { 0x7a, 0x00 },
+ { 0x11, 0x00 },
+ { 0x12, 0x00 },
+ { 0x15, 0x02 },
+ { 0x16, 0x90 },
+ { 0x13, 0x01 },
+ { 0x14, 0xF0 },
+ { 0x31, 0x04 },
+ { 0x30, 0x06 },
+ { 0x34, 0x02 },
+ { 0x35, 0x88 },
+ { 0x32, 0x01 },
+ { 0x33, 0xE8 },
+ { 0x7d, 0x02 },
+ { 0x7e, 0x88 },
+ { 0x7b, 0x01 },
+ { 0x7c, 0xe8 },
+ { 0x81, 0x00 },
+ { 0x82, 0xc0 },
+ { 0x7f, 0x00 },
+ { 0x80, 0x98 },
+ { 0xc3, 0x08 },
+ { 0xc2, 0x04 },
+ { 0xc6, 0x00 },
+ { 0xc7, 0xb0 },
+ { 0xc4, 0x00 },
+ { 0xc5, 0x90 },
+ { 0x7a, 0x03 },
+};
+#endif
diff --git a/drivers/media/video/samsung/Kconfig b/drivers/media/video/samsung/Kconfig
new file mode 100644
index 0000000..15c0eb2
--- /dev/null
+++ b/drivers/media/video/samsung/Kconfig
@@ -0,0 +1,26 @@
+config VIDEO_SAMSUNG
+ bool "Samsung Multimedia Devices"
+ depends on VIDEO_CAPTURE_DRIVERS && VIDEO_V4L2
+ select VIDEO_FIXED_MINOR_RANGES
+ default n
+ ---help---
+ This is a representative video4linux configuration for Samsung multimedia devices.
+
+config VIDEO_SAMSUNG_V4L2
+ bool "V4L2 API for digital camera to be contributed by samsung"
+ depends on VIDEO_DEV && VIDEO_SAMSUNG
+ default n
+ ---help---
+ This feature is for new V4L2 APIs all about digital camera
+
+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/tsi/Kconfig"
+if CPU_S5PV210_EVT1
+#source "drivers/media/video/samsung/rotator/Kconfig"
+#source "drivers/media/video/samsung/g2d/Kconfig"
+endif
+endif
diff --git a/drivers/media/video/samsung/Makefile b/drivers/media/video/samsung/Makefile
new file mode 100644
index 0000000..1f99c16
--- /dev/null
+++ b/drivers/media/video/samsung/Makefile
@@ -0,0 +1,10 @@
+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_G2D) += g2d/
+#obj-$(CONFIG_VIDEO_TSI) += tsi/
+
+EXTRA_CFLAGS += -Idrivers/media/video
+
diff --git a/drivers/media/video/samsung/fimc/Kconfig b/drivers/media/video/samsung/fimc/Kconfig
new file mode 100644
index 0000000..c9eae69
--- /dev/null
+++ b/drivers/media/video/samsung/fimc/Kconfig
@@ -0,0 +1,32 @@
+config VIDEO_FIMC
+ bool "Samsung Camera Interface (FIMC) driver"
+ depends on VIDEO_SAMSUNG && ARCH_S5PV210
+ default n
+ help
+ This is a video4linux driver for Samsung FIMC device.
+
+choice
+depends on VIDEO_FIMC
+prompt "Select CSC Range config"
+default VIDEO_FIMC_RANGE_NARROW
+config VIDEO_FIMC_RANGE_NARROW
+ bool "Narrow"
+ depends on VIDEO_FIMC && ARCH_S5PV210
+ ---help---
+ RGB <-> YUV Color Conversion Narrow Range Equation
+
+config VIDEO_FIMC_RANGE_WIDE
+ bool "Wide"
+ depends on VIDEO_FIMC && ARCH_S5PV210
+ ---help---
+ RGB <-> YUV Color Conversion Wide Range Equation
+endchoice
+
+config VIDEO_FIMC_DEBUG
+ bool "FIMC driver debug messages"
+ depends on VIDEO_FIMC
+
+config VIDEO_FIMC_MIPI
+ bool "MIPI-CSI2 Slave Interface support"
+ depends on VIDEO_FIMC && ARCH_S5PV210
+ default y
diff --git a/drivers/media/video/samsung/fimc/Makefile b/drivers/media/video/samsung/fimc/Makefile
new file mode 100644
index 0000000..4f6e5c9
--- /dev/null
+++ b/drivers/media/video/samsung/fimc/Makefile
@@ -0,0 +1,12 @@
+obj-$(CONFIG_VIDEO_FIMC) += fimc_dev.o fimc_v4l2.o fimc_capture.o fimc_output.o fimc_overlay.o fimc_regs.o
+obj-$(CONFIG_VIDEO_FIMC_MIPI) += csis.o
+
+ifeq ($(CONFIG_CPU_S5PV210),y)
+EXTRA_CFLAGS += -DCONFIG_MIPI_CSI_ADV_FEATURE
+endif
+
+EXTRA_CFLAGS += -Idrivers/media/video
+
+ifeq ($(CONFIG_VIDEO_FIMC_DEBUG),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
diff --git a/drivers/media/video/samsung/fimc/csis.c b/drivers/media/video/samsung/fimc/csis.c
new file mode 100644
index 0000000..f512d10
--- /dev/null
+++ b/drivers/media/video/samsung/fimc/csis.c
@@ -0,0 +1,431 @@
+/* linux/drivers/media/video/samsung/csis.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co,. Ltd.
+ * http://www.samsung.com/
+ *
+ * MIPI-CSI2 Support file for FIMC 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/errno.h>
+#include <linux/clk.h>
+#include <linux/fs.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/videodev2.h>
+#include <linux/slab.h>
+
+#include <linux/io.h>
+#include <linux/memory.h>
+#include <plat/clock.h>
+#include <plat/regs-csis.h>
+#include <plat/csis.h>
+#include "csis.h"
+
+static struct s3c_csis_info *s3c_csis;
+
+static struct s3c_platform_csis *to_csis_plat(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+
+ return (struct s3c_platform_csis *) pdev->dev.platform_data;
+}
+
+static int s3c_csis_set_info(void)
+{
+ s3c_csis = (struct s3c_csis_info *) \
+ kmalloc(sizeof(struct s3c_csis_info), GFP_KERNEL);
+ if (!s3c_csis) {
+ err("no memory for configuration\n");
+ return -ENOMEM;
+ }
+
+ strcpy(s3c_csis->name, S3C_CSIS_NAME);
+ s3c_csis->nr_lanes = S3C_CSIS_NR_LANES;
+
+ return 0;
+}
+
+static void s3c_csis_reset(void)
+{
+ u32 cfg;
+
+ cfg = readl(s3c_csis->regs + S3C_CSIS_CONTROL);
+ cfg |= S3C_CSIS_CONTROL_RESET;
+ writel(cfg, s3c_csis->regs + S3C_CSIS_CONTROL);
+}
+
+static void s3c_csis_set_nr_lanes(int lanes)
+{
+ u32 cfg;
+
+ cfg = readl(s3c_csis->regs + S3C_CSIS_CONFIG);
+ cfg &= ~S3C_CSIS_CONFIG_NR_LANE_MASK;
+
+ if (lanes == 1)
+ cfg |= S3C_CSIS_CONFIG_NR_LANE_1;
+ else
+ cfg |= S3C_CSIS_CONFIG_NR_LANE_2;
+
+ writel(cfg, s3c_csis->regs + S3C_CSIS_CONFIG);
+}
+
+static void s3c_csis_enable_interrupt(void)
+{
+ u32 cfg = 0;
+
+ /* enable all interrupts */
+ cfg |= S3C_CSIS_INTMSK_EVEN_BEFORE_ENABLE | \
+ S3C_CSIS_INTMSK_EVEN_AFTER_ENABLE | \
+ S3C_CSIS_INTMSK_ODD_BEFORE_ENABLE | \
+ S3C_CSIS_INTMSK_ODD_AFTER_ENABLE | \
+ S3C_CSIS_INTMSK_ERR_SOT_HS_ENABLE | \
+ S3C_CSIS_INTMSK_ERR_ESC_ENABLE | \
+ S3C_CSIS_INTMSK_ERR_CTRL_ENABLE | \
+ S3C_CSIS_INTMSK_ERR_ECC_ENABLE | \
+ S3C_CSIS_INTMSK_ERR_CRC_ENABLE | \
+ S3C_CSIS_INTMSK_ERR_ID_ENABLE;
+
+ writel(cfg, s3c_csis->regs + S3C_CSIS_INTMSK);
+}
+
+static void s3c_csis_disable_interrupt(void)
+{
+ /* disable all interrupts */
+ writel(0, s3c_csis->regs + S3C_CSIS_INTMSK);
+}
+
+static void s3c_csis_system_on(void)
+{
+ u32 cfg;
+
+ cfg = readl(s3c_csis->regs + S3C_CSIS_CONTROL);
+ cfg |= S3C_CSIS_CONTROL_ENABLE;
+ writel(cfg, s3c_csis->regs + S3C_CSIS_CONTROL);
+}
+
+static void s3c_csis_system_off(void)
+{
+ u32 cfg;
+
+ cfg = readl(s3c_csis->regs + S3C_CSIS_CONTROL);
+ cfg &= ~S3C_CSIS_CONTROL_ENABLE;
+ writel(cfg, s3c_csis->regs + S3C_CSIS_CONTROL);
+}
+
+static void s3c_csis_phy_on(void)
+{
+ u32 cfg;
+ cfg = readl(s3c_csis->regs + S3C_CSIS_DPHYCTRL);
+ cfg |= S3C_CSIS_DPHYCTRL_ENABLE;
+ writel(cfg, s3c_csis->regs + S3C_CSIS_DPHYCTRL);
+}
+
+static void s3c_csis_phy_off(void)
+{
+ u32 cfg;
+
+ cfg = readl(s3c_csis->regs + S3C_CSIS_DPHYCTRL);
+ cfg &= ~S3C_CSIS_DPHYCTRL_ENABLE;
+ writel(cfg, s3c_csis->regs + S3C_CSIS_DPHYCTRL);
+}
+
+#ifdef CONFIG_MIPI_CSI_ADV_FEATURE
+static void s3c_csis_update_shadow(void)
+{
+ u32 cfg;
+
+ cfg = readl(s3c_csis->regs + S3C_CSIS_CONTROL);
+ cfg |= S3C_CSIS_CONTROL_UPDATE_SHADOW;
+ writel(cfg, s3c_csis->regs + S3C_CSIS_CONTROL);
+}
+
+static void s3c_csis_set_data_align(int align)
+{
+ u32 cfg;
+
+ cfg = readl(s3c_csis->regs + S3C_CSIS_CONTROL);
+ cfg &= ~S3C_CSIS_CONTROL_ALIGN_MASK;
+
+ if (align == 24)
+ cfg |= S3C_CSIS_CONTROL_ALIGN_24BIT;
+ else
+ cfg |= S3C_CSIS_CONTROL_ALIGN_32BIT;
+
+ writel(cfg, s3c_csis->regs + S3C_CSIS_CONTROL);
+}
+
+static void s3c_csis_set_wclk(int extclk)
+{
+ u32 cfg;
+
+ cfg = readl(s3c_csis->regs + S3C_CSIS_CONTROL);
+ cfg &= ~S3C_CSIS_CONTROL_WCLK_MASK;
+
+ if (extclk)
+ cfg |= S3C_CSIS_CONTROL_WCLK_EXTCLK;
+ else
+ cfg |= S3C_CSIS_CONTROL_WCLK_PCLK;
+
+ writel(cfg, s3c_csis->regs + S3C_CSIS_CONTROL);
+}
+
+static void s3c_csis_set_format(enum mipi_format fmt)
+{
+ u32 cfg;
+
+ cfg = readl(s3c_csis->regs + S3C_CSIS_CONFIG);
+ cfg &= ~S3C_CSIS_CONFIG_FORMAT_MASK;
+ cfg |= (fmt << S3C_CSIS_CONFIG_FORMAT_SHIFT);
+
+ writel(cfg, s3c_csis->regs + S3C_CSIS_CONFIG);
+}
+
+static void s3c_csis_set_resol(int width, int height)
+{
+ u32 cfg = 0;
+
+ cfg |= width << S3C_CSIS_RESOL_HOR_SHIFT;
+ cfg |= height << S3C_CSIS_RESOL_VER_SHIFT;
+
+ writel(cfg, s3c_csis->regs + S3C_CSIS_RESOL);
+}
+
+static void s3c_csis_set_hs_settle(int settle)
+{
+ u32 cfg;
+
+ cfg = readl(s3c_csis->regs + S3C_CSIS_DPHYCTRL);
+ cfg &= ~S3C_CSIS_DPHYCTRL_HS_SETTLE_MASK;
+ cfg |= (settle << S3C_CSIS_DPHYCTRL_HS_SETTLE_SHIFT);
+
+ writel(cfg, s3c_csis->regs + S3C_CSIS_DPHYCTRL);
+}
+#endif
+
+void s3c_csis_start(int lanes, int settle, int align, int width,
+ int height, int pixel_format)
+{
+ struct platform_device *pdev = to_platform_device(s3c_csis->dev);
+ struct s3c_platform_csis *pdata;
+
+ pdata = to_csis_plat(s3c_csis->dev);
+ if (pdata->cfg_phy_global)
+ pdata->cfg_phy_global(pdev, 1);
+
+ s3c_csis_reset();
+ s3c_csis_set_nr_lanes(lanes);
+
+#ifdef CONFIG_MIPI_CSI_ADV_FEATURE
+ /* FIXME: how configure the followings with FIMC dynamically? */
+ s3c_csis_set_hs_settle(settle); /* s5k6aa */
+ s3c_csis_set_data_align(align);
+ s3c_csis_set_wclk(0);
+ if (pixel_format == V4L2_PIX_FMT_JPEG)
+ s3c_csis_set_format(MIPI_USER_DEF_PACKET_1);
+ else
+ s3c_csis_set_format(MIPI_CSI_YCBCR422_8BIT);
+ s3c_csis_set_resol(width, height);
+ s3c_csis_update_shadow();
+#endif
+
+ s3c_csis_enable_interrupt();
+ s3c_csis_system_on();
+ s3c_csis_phy_on();
+
+ info("Samsung MIPI-CSI2 operation started\n");
+}
+
+static void s3c_csis_stop(struct platform_device *pdev)
+{
+ struct s3c_platform_csis *plat;
+
+ s3c_csis_disable_interrupt();
+ s3c_csis_system_off();
+ s3c_csis_phy_off();
+
+ plat = to_csis_plat(&pdev->dev);
+ if (plat->cfg_phy_global)
+ plat->cfg_phy_global(pdev, 0);
+}
+
+static irqreturn_t s3c_csis_irq(int irq, void *dev_id)
+{
+ u32 cfg;
+
+ /* just clearing the pends */
+ cfg = readl(s3c_csis->regs + S3C_CSIS_INTSRC);
+ writel(cfg, s3c_csis->regs + S3C_CSIS_INTSRC);
+
+ return IRQ_HANDLED;
+}
+
+static int s3c_csis_clk_on(struct platform_device *pdev)
+{
+ struct s3c_platform_csis *pdata;
+ struct clk *parent, *mout_csis;
+
+ pdata = to_csis_plat(&pdev->dev);
+
+ /* mout_mpll */
+ parent = clk_get(&pdev->dev, pdata->srclk_name);
+ if (IS_ERR(parent)) {
+ err("failed to get parent clock for csis\n");
+ return -EINVAL;
+ }
+
+ /* mout_csis */
+ mout_csis = clk_get(&pdev->dev, "mout_csis");
+
+ /* sclk_csis */
+ s3c_csis->clock = clk_get(&pdev->dev, pdata->clk_name);
+ if (IS_ERR(s3c_csis->clock)) {
+ err("failed to get csis clock source\n");
+ return -EINVAL;
+ }
+
+ clk_set_parent(mout_csis, parent);
+ clk_set_parent(s3c_csis->clock, mout_csis);
+
+ /* Turn on csis power domain regulator */
+ regulator_enable(s3c_csis->regulator);
+ /* clock enable for csis */
+ clk_enable(s3c_csis->clock);
+
+ return 0;
+}
+
+static int s3c_csis_clk_off(struct platform_device *pdev)
+{
+ struct s3c_platform_csis *plat;
+
+ plat = to_csis_plat(&pdev->dev);
+
+ /* sclk_csis */
+ s3c_csis->clock = clk_get(&pdev->dev, plat->clk_name);
+ if (IS_ERR(s3c_csis->clock)) {
+ err("failed to get csis clock source\n");
+ return -EINVAL;
+ }
+
+ /* clock disable for csis */
+ clk_disable(s3c_csis->clock);
+ /* Turn off csis power domain regulator */
+ regulator_disable(s3c_csis->regulator);
+
+ return 0;
+}
+
+static int s3c_csis_probe(struct platform_device *pdev)
+{
+ struct s3c_platform_csis *pdata;
+ struct resource *res;
+
+ s3c_csis_set_info();
+
+ s3c_csis->dev = &pdev->dev;
+
+ pdata = to_csis_plat(&pdev->dev);
+ if (pdata->cfg_gpio)
+ pdata->cfg_gpio();
+
+ /* Get csis power domain regulator */
+ s3c_csis->regulator = regulator_get(&pdev->dev, "pd");
+ if (IS_ERR(s3c_csis->regulator)) {
+ err("%s: failed to get resource %s\n",
+ __func__, "s3c-csis");
+ return PTR_ERR(s3c_csis->regulator);
+ }
+ /* clock & power on */
+ s3c_csis_clk_on(pdev);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ err("failed to get io memory region\n");
+ return -EINVAL;
+ }
+
+ res = request_mem_region(res->start,
+ res->end - res->start + 1, pdev->name);
+ if (!res) {
+ err("failed to request io memory region\n");
+ return -EINVAL;
+ }
+
+ /* ioremap for register block */
+ s3c_csis->regs = ioremap(res->start, res->end - res->start + 1);
+ if (!s3c_csis->regs) {
+ err("failed to remap io region\n");
+ return -EINVAL;
+ }
+
+ /* irq */
+ s3c_csis->irq = platform_get_irq(pdev, 0);
+ if (request_irq(s3c_csis->irq, s3c_csis_irq, IRQF_DISABLED, \
+ s3c_csis->name, s3c_csis))
+ err("request_irq failed\n");
+
+ info("Samsung MIPI-CSI2 driver probed successfully\n");
+
+ return 0;
+}
+
+static int s3c_csis_remove(struct platform_device *pdev)
+{
+ s3c_csis_stop(pdev);
+ kfree(s3c_csis);
+
+ return 0;
+}
+
+/* sleep */
+int s3c_csis_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ s3c_csis_clk_off(pdev);
+ return 0;
+}
+
+/* wakeup */
+int s3c_csis_resume(struct platform_device *pdev)
+{
+ s3c_csis_clk_on(pdev);
+ return 0;
+}
+
+static struct platform_driver s3c_csis_driver = {
+ .probe = s3c_csis_probe,
+ .remove = s3c_csis_remove,
+ .suspend = s3c_csis_suspend,
+ .resume = s3c_csis_resume,
+ .driver = {
+ .name = "s5p-mipi-csis",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int s3c_csis_register(void)
+{
+ platform_driver_register(&s3c_csis_driver);
+
+ return 0;
+}
+
+static void s3c_csis_unregister(void)
+{
+ platform_driver_unregister(&s3c_csis_driver);
+}
+
+module_init(s3c_csis_register);
+module_exit(s3c_csis_unregister);
+
+MODULE_AUTHOR("Jinsung, Yang <jsgood.yang@samsung.com>");
+MODULE_AUTHOR("Sewoon, Park <seuni.park@samsung.com>");
+MODULE_DESCRIPTION("MIPI-CSI2 support for FIMC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/samsung/fimc/csis.h b/drivers/media/video/samsung/fimc/csis.h
new file mode 100644
index 0000000..4943c8f
--- /dev/null
+++ b/drivers/media/video/samsung/fimc/csis.h
@@ -0,0 +1,42 @@
+/* linux/drivers/media/video/samsung/csis.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co,. Ltd.
+ * http://www.samsung.com/
+ *
+ * Header file for Samsung MIPI-CSI2 driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __CSIS_H
+#define __CSIS_H __FILE__
+
+#define S3C_CSIS_NAME "s5p-mipi-csis"
+#define S3C_CSIS_NR_LANES 1
+
+#define info(args...) \
+ do { printk(KERN_INFO S3C_CSIS_NAME ": " args); } while (0)
+#define err(args...) \
+ do { printk(KERN_ERR S3C_CSIS_NAME ": " args); } while (0)
+
+enum mipi_format {
+ MIPI_CSI_YCBCR422_8BIT = 0x1e,
+ MIPI_CSI_RAW8 = 0x2a,
+ MIPI_CSI_RAW10 = 0x2b,
+ MIPI_CSI_RAW12 = 0x2c,
+ MIPI_USER_DEF_PACKET_1 = 0x30, /* User defined Byte-based packet 1 */
+};
+
+struct s3c_csis_info {
+ char name[16];
+ struct device *dev;
+ struct clk *clock;
+ struct regulator *regulator;
+ void __iomem *regs;
+ int irq;
+ int nr_lanes;
+};
+
+#endif /* __CSIS_H */
diff --git a/drivers/media/video/samsung/fimc/fimc.h b/drivers/media/video/samsung/fimc/fimc.h
new file mode 100644
index 0000000..e261382
--- /dev/null
+++ b/drivers/media/video/samsung/fimc/fimc.h
@@ -0,0 +1,707 @@
+/* linux/drivers/media/video/samsung/fimc/fimc.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Header file for Samsung Camera Interface (FIMC) driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+
+#ifndef __FIMC_H
+#define __FIMC_H __FILE__
+
+#ifdef __KERNEL__
+#include <linux/wait.h>
+#include <linux/mutex.h>
+#include <linux/i2c.h>
+#include <linux/fb.h>
+#include <linux/videodev2.h>
+#include <linux/platform_device.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/videobuf-core.h>
+#include <plat/media.h>
+#include <plat/fimc.h>
+#endif
+
+#define FIMC_NAME "s3c-fimc"
+
+#define FIMC_DEVICES 3
+#define FIMC_SUBDEVS 3
+#define FIMC_MAXCAMS 5 /* added 1 because of WriteBack */
+#define FIMC_PHYBUFS 4
+#define FIMC_OUTBUFS 3
+#define FIMC_INQUEUES 10
+#define FIMC_MAX_CTXS 1
+#define FIMC_TPID 3
+#define FIMC_CAPBUFS 16
+#define FIMC_ONESHOT_TIMEOUT 200
+#define FIMC_DQUEUE_TIMEOUT 200
+#define FIMC_FIFOOFF_CNT 1000000 /* Sufficiently big value for stop */
+
+#define FORMAT_FLAGS_PACKED 0x1
+#define FORMAT_FLAGS_PLANAR 0x2
+#define FORMAT_FLAGS_ENCODED 0x3
+
+#define FIMC_ADDR_Y 0
+#define FIMC_ADDR_CB 1
+#define FIMC_ADDR_CR 2
+
+#define FIMC_HD_WIDTH 1280
+#define FIMC_HD_HEIGHT 720
+
+#define FIMC_FHD_WIDTH 1920
+#define FIMC_FHD_HEIGHT 1080
+
+#define FIMC_MMAP_IDX -1
+#define FIMC_USERPTR_IDX -2
+
+#define FIMC_HCLK 0
+#define FIMC_SCLK 1
+#define FIMC_OVLY_MODE FIMC_OVLY_DMA_AUTO
+
+#define FIMC_PINGPONG 2
+
+/*
+ * ENUMERATIONS
+*/
+enum fimc_status {
+ FIMC_READY_OFF = 0x00,
+ FIMC_STREAMOFF = 0x01,
+ FIMC_READY_ON = 0x02,
+ FIMC_STREAMON = 0x03,
+ FIMC_STREAMON_IDLE = 0x04, /* oneshot mode */
+ FIMC_OFF_SLEEP = 0x05,
+ FIMC_ON_SLEEP = 0x06,
+ FIMC_ON_IDLE_SLEEP = 0x07, /* oneshot mode */
+ FIMC_READY_RESUME = 0x08,
+};
+
+enum fimc_fifo_state {
+ FIFO_CLOSE,
+ FIFO_SLEEP,
+};
+
+enum fimc_fimd_state {
+ FIMD_OFF,
+ FIMD_ON,
+};
+
+enum fimc_rot_flip {
+ FIMC_XFLIP = 0x01,
+ FIMC_YFLIP = 0x02,
+ FIMC_ROT = 0x10,
+};
+
+enum fimc_input {
+ FIMC_SRC_CAM,
+ FIMC_SRC_MSDMA,
+};
+
+enum fimc_overlay_mode {
+ /* Overlay mode isn't fixed. */
+ FIMC_OVLY_NOT_FIXED = 0x0,
+ /* Non-destructive Overlay with DMA */
+ FIMC_OVLY_DMA_AUTO = 0x1,
+ /* Non-destructive Overlay with DMA */
+ FIMC_OVLY_DMA_MANUAL = 0x2,
+ /* Destructive Overlay with DMA single destination buffer */
+ FIMC_OVLY_NONE_SINGLE_BUF = 0x3,
+ /* Destructive Overlay with DMA multiple dstination buffer */
+ FIMC_OVLY_NONE_MULTI_BUF = 0x4,
+};
+
+enum fimc_autoload {
+ FIMC_AUTO_LOAD,
+ FIMC_ONE_SHOT,
+};
+
+enum fimc_log {
+ FIMC_LOG_DEBUG = 0x1000,
+ FIMC_LOG_INFO_L2 = 0x0200,
+ FIMC_LOG_INFO_L1 = 0x0100,
+ FIMC_LOG_WARN = 0x0010,
+ FIMC_LOG_ERR = 0x0001,
+};
+
+enum fimc_pixel_format_type{
+ FIMC_RGB,
+ FIMC_YUV420,
+ FIMC_YUV422,
+ FIMC_YUV444,
+};
+
+/*
+ * STRUCTURES
+*/
+
+/* for reserved memory */
+struct fimc_meminfo {
+ dma_addr_t base; /* buffer base */
+ size_t size; /* total length */
+ dma_addr_t curr; /* current addr */
+};
+
+struct fimc_buf {
+ dma_addr_t base[3];
+ size_t length[3];
+};
+
+struct fimc_overlay_buf {
+ u32 vir_addr[3];
+ size_t size[3];
+ u32 phy_addr[3];
+};
+
+struct fimc_overlay {
+ enum fimc_overlay_mode mode;
+ struct fimc_overlay_buf buf;
+ s32 req_idx;
+ int fb_id;
+};
+
+/* general buffer */
+struct fimc_buf_set {
+ int id;
+ /* Plane 0/1/2 for raw data, Plane 3 for padding buffer (if required) */
+ dma_addr_t base[4];
+ size_t length[4];
+ size_t garbage[4];
+ enum videobuf_state state;
+ u32 flags;
+ atomic_t mapped_cnt;
+ struct list_head list;
+};
+
+/* for capture device */
+struct fimc_capinfo {
+ struct v4l2_cropcap cropcap;
+ struct v4l2_rect crop;
+ struct v4l2_pix_format fmt;
+ struct fimc_buf_set bufs[FIMC_CAPBUFS];
+ struct list_head inq;
+ int outq[FIMC_PHYBUFS];
+ int nr_bufs;
+ int irq;
+ int lastirq;
+
+ /* flip: V4L2_CID_xFLIP, rotate: 90, 180, 270 */
+ u32 flip;
+ u32 rotate;
+};
+
+/* for output overlay device */
+struct fimc_idx {
+ int ctx;
+ int idx;
+};
+
+struct fimc_ctx_idx {
+ struct fimc_idx prev;
+ struct fimc_idx active;
+ struct fimc_idx next;
+};
+
+/* scaler abstraction: local use recommended */
+struct fimc_scaler {
+ u32 bypass;
+ u32 hfactor;
+ u32 vfactor;
+ u32 pre_hratio;
+ u32 pre_vratio;
+ u32 pre_dst_width;
+ u32 pre_dst_height;
+ u32 scaleup_h;
+ u32 scaleup_v;
+ u32 main_hratio;
+ u32 main_vratio;
+ u32 real_width;
+ u32 real_height;
+ u32 shfactor;
+ u32 skipline;
+};
+
+struct fimc_ctx {
+ u32 ctx_num;
+ struct v4l2_cropcap cropcap;
+ struct v4l2_rect crop;
+ struct v4l2_pix_format pix;
+ struct v4l2_window win;
+ struct v4l2_framebuffer fbuf;
+ struct fimc_scaler sc;
+ struct fimc_overlay overlay;
+
+ u32 buf_num;
+ u32 is_requested;
+ struct fimc_buf_set src[FIMC_OUTBUFS];
+ struct fimc_buf_set dst[FIMC_OUTBUFS];
+ s32 inq[FIMC_OUTBUFS];
+ s32 outq[FIMC_OUTBUFS];
+
+ u32 flip;
+ u32 rotate;
+ enum fimc_status status;
+};
+
+struct fimc_outinfo {
+ int last_ctx;
+ spinlock_t lock_in;
+ spinlock_t lock_out;
+ struct fimc_idx inq[FIMC_INQUEUES];
+ struct fimc_ctx ctx[FIMC_MAX_CTXS];
+ struct fimc_ctx_idx idxs;
+};
+
+struct s3cfb_user_window {
+ int x;
+ int y;
+};
+
+enum s3cfb_data_path_t {
+ DATA_PATH_FIFO = 0,
+ DATA_PATH_DMA = 1,
+ DATA_PATH_IPC = 2,
+};
+
+enum s3cfb_mem_owner_t {
+ DMA_MEM_NONE = 0,
+ DMA_MEM_FIMD = 1,
+ DMA_MEM_OTHER = 2,
+};
+
+enum s3cfb_alpha_t {
+ PLANE_BLENDING,
+ PIXEL_BLENDING,
+};
+
+enum s3cfb_chroma_dir_t {
+ CHROMA_FG,
+ CHROMA_BG,
+};
+
+struct s3cfb_alpha {
+ enum s3cfb_alpha_t mode;
+ int channel;
+ unsigned int value;
+};
+
+
+struct s3cfb_chroma {
+ int enabled;
+ int blended;
+ unsigned int key;
+ unsigned int comp_key;
+ unsigned int alpha;
+ enum s3cfb_chroma_dir_t dir;
+};
+
+struct s3cfb_window {
+ int id;
+ int enabled;
+ atomic_t in_use;
+ int x;
+ int y;
+ enum s3cfb_data_path_t path;
+ enum s3cfb_mem_owner_t owner;
+ unsigned int other_mem_addr;
+ unsigned int other_mem_size;
+ int local_channel;
+ int dma_burst;
+ unsigned int pseudo_pal[16];
+ struct s3cfb_alpha alpha;
+ struct s3cfb_chroma chroma;
+};
+
+#define S3CFB_WIN_OFF_ALL _IO('F', 202)
+#define S3CFB_WIN_POSITION _IOW('F', 203, struct s3cfb_user_window)
+#define S3CFB_GET_LCD_WIDTH _IOR('F', 302, int)
+#define S3CFB_GET_LCD_HEIGHT _IOR('F', 303, int)
+#define S3CFB_SET_WRITEBACK _IOW('F', 304, u32)
+#define S3CFB_SET_WIN_ON _IOW('F', 306, u32)
+#define S3CFB_SET_WIN_OFF _IOW('F', 307, u32)
+#define S3CFB_SET_WIN_PATH _IOW('F', 308, enum s3cfb_data_path_t)
+#define S3CFB_SET_WIN_ADDR _IOW('F', 309, unsigned long)
+#define S3CFB_SET_WIN_MEM _IOW('F', 310, enum s3cfb_mem_owner_t)
+/* ------------------------------------------------------------------------ */
+
+struct fimc_fbinfo {
+ struct fb_fix_screeninfo *fix;
+ struct fb_var_screeninfo *var;
+ int lcd_hres;
+ int lcd_vres;
+ u32 is_enable;
+};
+
+struct fimc_limit {
+ u32 pre_dst_w;
+ u32 bypass_w;
+ u32 trg_h_no_rot;
+ u32 trg_h_rot;
+ u32 real_w_no_rot;
+ u32 real_h_rot;
+};
+
+enum FIMC_EFFECT_FIN {
+ FIMC_EFFECT_FIN_BYPASS = 0,
+ FIMC_EFFECT_FIN_ARBITRARY_CBCR,
+ FIMC_EFFECT_FIN_NEGATIVE,
+ FIMC_EFFECT_FIN_ART_FREEZE,
+ FIMC_EFFECT_FIN_EMBOSSING,
+ FIMC_EFFECT_FIN_SILHOUETTE,
+};
+
+
+struct fimc_effect {
+ int ie_on;
+ int ie_after_sc;
+ enum FIMC_EFFECT_FIN fin;
+ int pat_cb;
+ int pat_cr;
+};
+
+/* fimc controller abstration */
+struct fimc_control {
+ int id; /* controller id */
+ char name[16];
+ atomic_t in_use;
+ void __iomem *regs; /* register i/o */
+ struct clk *clk; /* interface clock */
+ struct regulator *regulator; /* pd regulator */
+ struct fimc_meminfo mem; /* for reserved mem */
+
+ /* kernel helpers */
+ struct mutex lock; /* controller lock */
+ struct mutex alloc_lock;
+ struct mutex v4l2_lock;
+ wait_queue_head_t wq;
+ struct device *dev;
+ int irq;
+
+ /* v4l2 related */
+ struct video_device *vd;
+ struct v4l2_device v4l2_dev;
+
+ /* fimc specific */
+ struct fimc_limit *limit; /* H/W limitation */
+ struct s3c_platform_camera *cam; /* activated camera */
+ struct fimc_capinfo *cap; /* capture dev info */
+ struct fimc_outinfo *out; /* output dev info */
+ struct fimc_fbinfo fb; /* fimd info */
+ struct fimc_scaler sc; /* scaler info */
+ struct fimc_effect fe; /* fimc effect info */
+
+ enum fimc_status status;
+ enum fimc_log log;
+
+ u32 ctx_busy[FIMC_MAX_CTXS];
+};
+
+/* global */
+struct fimc_global {
+ struct fimc_control ctrl[FIMC_DEVICES];
+ struct s3c_platform_camera camera[FIMC_MAXCAMS];
+ int camera_isvalid[FIMC_MAXCAMS];
+ int active_camera;
+ int initialized;
+};
+
+struct fimc_prv_data {
+ struct fimc_control *ctrl;
+ int ctx_id;
+};
+
+/* debug macro */
+#define FIMC_LOG_DEFAULT (FIMC_LOG_WARN | FIMC_LOG_ERR)
+
+#define FIMC_DEBUG(fmt, ...) \
+ do { \
+ if (ctrl->log & FIMC_LOG_DEBUG) \
+ printk(KERN_DEBUG FIMC_NAME "-%d : " \
+ fmt, ctrl->id, ##__VA_ARGS__); \
+ } while (0)
+
+#define FIMC_INFO_L2(fmt, ...) \
+ do { \
+ if (ctrl->log & FIMC_LOG_INFO_L2) \
+ printk(KERN_INFO FIMC_NAME "-%d : " \
+ fmt, ctrl->id, ##__VA_ARGS__); \
+ } while (0)
+
+#define FIMC_INFO_L1(fmt, ...) \
+ do { \
+ if (ctrl->log & FIMC_LOG_INFO_L1) \
+ printk(KERN_INFO FIMC_NAME "-%d : " \
+ fmt, ctrl->id, ##__VA_ARGS__); \
+ } while (0)
+
+#define FIMC_WARN(fmt, ...) \
+ do { \
+ if (ctrl->log & FIMC_LOG_WARN) \
+ printk(KERN_WARNING FIMC_NAME "-%d : " \
+ fmt, ctrl->id, ##__VA_ARGS__); \
+ } while (0)
+
+
+#define FIMC_ERROR(fmt, ...) \
+ do { \
+ if (ctrl->log & FIMC_LOG_ERR) \
+ printk(KERN_ERR FIMC_NAME "-%d : " \
+ fmt, ctrl->id, ##__VA_ARGS__); \
+ } while (0)
+
+
+#define fimc_dbg(fmt, ...) FIMC_DEBUG(fmt, ##__VA_ARGS__)
+#define fimc_info2(fmt, ...) FIMC_INFO_L2(fmt, ##__VA_ARGS__)
+#define fimc_info1(fmt, ...) FIMC_INFO_L1(fmt, ##__VA_ARGS__)
+#define fimc_warn(fmt, ...) FIMC_WARN(fmt, ##__VA_ARGS__)
+#define fimc_err(fmt, ...) FIMC_ERROR(fmt, ##__VA_ARGS__)
+
+/*
+ * EXTERNS
+*/
+extern struct fimc_global *fimc_dev;
+extern struct video_device fimc_video_device[FIMC_DEVICES];
+extern const struct v4l2_ioctl_ops fimc_v4l2_ops;
+extern struct fimc_limit fimc40_limits[FIMC_DEVICES];
+extern struct fimc_limit fimc43_limits[FIMC_DEVICES];
+extern struct fimc_limit fimc50_limits[FIMC_DEVICES];
+
+/* general */
+extern void s3c_csis_start(int lanes, int settle, int align,
+ int width, int height,
+ int pixel_format);
+extern int fimc_dma_alloc(struct fimc_control *ctrl,
+ struct fimc_buf_set *bs,
+ int i, int align);
+extern void fimc_dma_free(struct fimc_control *ctrl,
+ struct fimc_buf_set *bs, int i);
+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 rotate);
+extern void fimc_clk_en(struct fimc_control *ctrl, bool on);
+
+/* camera */
+extern int fimc_select_camera(struct fimc_control *ctrl);
+
+/* capture device */
+extern int fimc_enum_input(struct file *file, void *fh,
+ struct v4l2_input *inp);
+extern int fimc_g_input(struct file *file, void *fh, unsigned int *i);
+extern int fimc_s_input(struct file *file, void *fh, unsigned int i);
+extern int fimc_enum_fmt_vid_capture(struct file *file, void *fh,
+ struct v4l2_fmtdesc *f);
+extern int fimc_g_fmt_vid_capture(struct file *file, void *fh,
+ struct v4l2_format *f);
+extern int fimc_s_fmt_vid_capture(struct file *file, void *fh,
+ struct v4l2_format *f);
+extern int fimc_try_fmt_vid_capture(struct file *file, void *fh,
+ struct v4l2_format *f);
+extern int fimc_reqbufs_capture(void *fh, struct v4l2_requestbuffers *b);
+extern int fimc_querybuf_capture(void *fh, struct v4l2_buffer *b);
+extern int fimc_g_ctrl_capture(void *fh, struct v4l2_control *c);
+extern int fimc_s_ctrl_capture(void *fh, struct v4l2_control *c);
+extern int fimc_s_ext_ctrls_capture(void *fh, struct v4l2_ext_controls *c);
+extern int fimc_cropcap_capture(void *fh, struct v4l2_cropcap *a);
+extern int fimc_g_crop_capture(void *fh, struct v4l2_crop *a);
+extern int fimc_s_crop_capture(void *fh, struct v4l2_crop *a);
+extern int fimc_streamon_capture(void *fh);
+extern int fimc_streamoff_capture(void *fh);
+extern int fimc_qbuf_capture(void *fh, struct v4l2_buffer *b);
+extern int fimc_dqbuf_capture(void *fh, struct v4l2_buffer *b);
+extern int fimc_g_parm(struct file *file, void *fh,
+ struct v4l2_streamparm *a);
+extern int fimc_s_parm(struct file *file, void *fh,
+ struct v4l2_streamparm *a);
+extern int fimc_queryctrl(struct file *file, void *fh,
+ struct v4l2_queryctrl *qc);
+extern int fimc_querymenu(struct file *file, void *fh,
+ struct v4l2_querymenu *qm);
+
+#if defined(CONFIG_CPU_S5PV210)
+extern int fimc_change_clksrc(struct fimc_control *ctrl, int fimc_clk);
+#endif
+extern int fimc_release_subdev(struct fimc_control *ctrl);
+
+/* output device */
+extern void fimc_outdev_set_src_addr(struct fimc_control *ctrl,
+ dma_addr_t *base);
+extern int fimc_outdev_set_ctx_param(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx);
+extern int fimc_start_fifo(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx);
+extern int fimc_fimd_rect(const struct fimc_control *ctrl,
+ const struct fimc_ctx *ctx,
+ struct v4l2_rect *fimd_rect);
+extern int fimc_outdev_stop_streaming(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx);
+extern int fimc_outdev_resume_dma(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx);
+extern int fimc_outdev_start_camif(void *param);
+extern int fimc_reqbufs_output(void *fh, struct v4l2_requestbuffers *b);
+extern int fimc_querybuf_output(void *fh, struct v4l2_buffer *b);
+extern int fimc_g_ctrl_output(void *fh, struct v4l2_control *c);
+extern int fimc_s_ctrl_output(struct file *filp, void *fh,
+ struct v4l2_control *c);
+extern int fimc_cropcap_output(void *fh, struct v4l2_cropcap *a);
+extern int fimc_g_crop_output(void *fh, struct v4l2_crop *a);
+extern int fimc_s_crop_output(void *fh, struct v4l2_crop *a);
+extern int fimc_streamon_output(void *fh);
+extern int fimc_streamoff_output(void *fh);
+extern int fimc_qbuf_output(void *fh, struct v4l2_buffer *b);
+extern int fimc_dqbuf_output(void *fh, struct v4l2_buffer *b);
+extern int fimc_g_fmt_vid_out(struct file *filp, void *fh,
+ struct v4l2_format *f);
+extern int fimc_s_fmt_vid_out(struct file *filp, void *fh,
+ struct v4l2_format *f);
+extern int fimc_try_fmt_vid_out(struct file *filp, void *fh,
+ struct v4l2_format *f);
+extern int fimc_output_set_dst_addr(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx, int idx);
+extern int fimc_init_in_queue(struct fimc_control *ctrl, struct fimc_ctx *ctx);
+extern int fimc_push_inq(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx, int idx);
+extern int fimc_pop_inq(struct fimc_control *ctrl, int *ctx_num, int *idx);
+extern int fimc_push_outq(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx, int idx);
+extern int fimc_pop_outq(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx, int *idx);
+extern int fimc_init_out_queue(struct fimc_control *ctrl, struct fimc_ctx *ctx);
+extern void fimc_outdev_init_idxs(struct fimc_control *ctrl);
+
+extern void fimc_dump_context(struct fimc_control *ctrl, struct fimc_ctx *ctx);
+extern void fimc_print_signal(struct fimc_control *ctrl);
+
+/* overlay device */
+extern int fimc_try_fmt_overlay(struct file *filp, void *fh,
+ struct v4l2_format *f);
+extern int fimc_g_fmt_vid_overlay(struct file *filp, void *fh,
+ struct v4l2_format *f);
+extern int fimc_s_fmt_vid_overlay(struct file *filp, void *fh,
+ struct v4l2_format *f);
+extern int fimc_g_fbuf(struct file *filp, void *fh,
+ struct v4l2_framebuffer *fb);
+extern int fimc_s_fbuf(struct file *filp, void *fh,
+ struct v4l2_framebuffer *fb);
+
+/* Register access file */
+extern void fimc_reset(struct fimc_control *ctrl);
+extern int fimc_hwset_camera_source(struct fimc_control *ctrl);
+extern int fimc_hwset_enable_irq(struct fimc_control *ctrl,
+ int overflow, int level);
+extern int fimc_hwset_disable_irq(struct fimc_control *ctrl);
+extern int fimc_hwset_clear_irq(struct fimc_control *ctrl);
+extern int fimc_hwset_reset(struct fimc_control *ctrl);
+extern int fimc_hwset_sw_reset(struct fimc_control *ctrl);
+extern int fimc_hwset_clksrc(struct fimc_control *ctrl, int src_clk);
+extern int fimc_hwget_overflow_state(struct fimc_control *ctrl);
+extern int fimc_hwset_camera_offset(struct fimc_control *ctrl);
+extern int fimc_hwset_camera_polarity(struct fimc_control *ctrl);
+extern int fimc_hwset_camera_type(struct fimc_control *ctrl);
+extern int fimc_hwset_output_size(struct fimc_control *ctrl,
+ int width, int height);
+extern int fimc_hwset_output_colorspace(struct fimc_control *ctrl,
+ u32 pixelformat);
+extern int fimc_hwset_output_rot_flip(struct fimc_control *ctrl,
+ u32 rot, u32 flip);
+extern int fimc_hwset_output_area(struct fimc_control *ctrl,
+ u32 width, u32 height);
+extern int fimc_hwset_output_area_size(struct fimc_control *ctrl, u32 size);
+extern int fimc_hwset_output_scan(struct fimc_control *ctrl,
+ struct v4l2_pix_format *fmt);
+extern int fimc_hwset_enable_lastirq(struct fimc_control *ctrl);
+extern int fimc_hwset_disable_lastirq(struct fimc_control *ctrl);
+extern int fimc_hwset_prescaler(struct fimc_control *ctrl,
+ struct fimc_scaler *sc);
+extern int fimc_hwset_output_yuv(struct fimc_control *ctrl, u32 pixelformat);
+extern int fimc_hwset_output_address(struct fimc_control *ctrl,
+ struct fimc_buf_set *bs,
+ int id);
+extern int fimc_hwset_input_rot(struct fimc_control *ctrl, u32 rot, u32 flip);
+extern int fimc_hwset_scaler(struct fimc_control *ctrl, struct fimc_scaler *sc);
+extern int fimc_hwset_scaler_bypass(struct fimc_control *ctrl);
+extern int fimc_hwset_enable_lcdfifo(struct fimc_control *ctrl);
+extern int fimc_hwset_disable_lcdfifo(struct fimc_control *ctrl);
+extern int fimc_hwset_start_scaler(struct fimc_control *ctrl);
+extern int fimc_hwset_stop_scaler(struct fimc_control *ctrl);
+extern int fimc_hwset_input_rgb(struct fimc_control *ctrl, u32 pixelformat);
+extern int fimc_hwset_intput_field(struct fimc_control *ctrl,
+ enum v4l2_field field);
+extern int fimc_hwset_output_rgb(struct fimc_control *ctrl, u32 pixelformat);
+extern int fimc_hwset_ext_rgb(struct fimc_control *ctrl, int enable);
+extern int fimc_hwset_enable_capture(struct fimc_control *ctrl,
+ u32 bypass);
+extern int fimc_hwset_disable_capture(struct fimc_control *ctrl);
+extern void fimc_wait_disable_capture(struct fimc_control *ctrl);
+extern int fimc_hwset_input_address(struct fimc_control *ctrl,
+ dma_addr_t *base);
+extern int fimc_hwset_enable_autoload(struct fimc_control *ctrl);
+extern int fimc_hwset_disable_autoload(struct fimc_control *ctrl);
+extern int fimc_hwset_real_input_size(struct fimc_control *ctrl,
+ u32 width, u32 height);
+extern int fimc_hwset_addr_change_enable(struct fimc_control *ctrl);
+extern int fimc_hwset_addr_change_disable(struct fimc_control *ctrl);
+extern int fimc_hwset_input_burst_cnt(struct fimc_control *ctrl, u32 cnt);
+extern int fimc_hwset_input_colorspace(struct fimc_control *ctrl,
+ u32 pixelformat);
+extern int fimc_hwset_input_yuv(struct fimc_control *ctrl, u32 pixelformat);
+extern int fimc_hwset_input_flip(struct fimc_control *ctrl, u32 rot, u32 flip);
+extern int fimc_hwset_input_source(struct fimc_control *ctrl,
+ enum fimc_input path);
+extern int fimc_hwset_start_input_dma(struct fimc_control *ctrl);
+extern int fimc_hwset_stop_input_dma(struct fimc_control *ctrl);
+extern int fimc_hwset_output_offset(struct fimc_control *ctrl,
+ u32 pixelformat,
+ struct v4l2_rect *bound,
+ struct v4l2_rect *crop);
+extern int fimc_hwset_input_offset(struct fimc_control *ctrl,
+ u32 pixelformat,
+ struct v4l2_rect *bound,
+ struct v4l2_rect *crop);
+extern int fimc_hwset_org_input_size(struct fimc_control *ctrl,
+ u32 width, u32 height);
+extern int fimc_hwset_org_output_size(struct fimc_control *ctrl,
+ u32 width, u32 height);
+extern int fimc_hwset_ext_output_size(struct fimc_control *ctrl,
+ u32 width, u32 height);
+extern int fimc_hwset_input_addr_style(struct fimc_control *ctrl,
+ u32 pixelformat);
+extern int fimc_hwset_output_addr_style(struct fimc_control *ctrl,
+ u32 pixelformat);
+extern int fimc_hwset_jpeg_mode(struct fimc_control *ctrl, bool enable);
+extern int fimc_hwget_frame_count(struct fimc_control *ctrl);
+extern int fimc_hw_wait_winoff(struct fimc_control *ctrl);
+extern int fimc_hw_wait_stop_input_dma(struct fimc_control *ctrl);
+extern int fimc_hwset_input_lineskip(struct fimc_control *ctrl);
+extern int fimc_hw_reset_camera(struct fimc_control *ctrl);
+extern void fimc_hwset_stop_processing(struct fimc_control *ctrl);
+extern int fimc_hwset_image_effect(struct fimc_control *ctrl);
+extern int fimc_hwset_shadow_enable(struct fimc_control *ctrl);
+extern int fimc_hwset_shadow_disable(struct fimc_control *ctrl);
+extern void fimc_save_regs(struct fimc_control *ctrl);
+extern void fimc_load_regs(struct fimc_control *ctrl);
+extern void fimc_dump_regs(struct fimc_control *ctrl);
+
+/*
+ * D R I V E R H E L P E R S
+ *
+*/
+#define to_fimc_plat(d) (to_platform_device(d)->dev.platform_data)
+
+static inline struct fimc_global *get_fimc_dev(void)
+{
+ return fimc_dev;
+}
+
+static inline struct fimc_control *get_fimc_ctrl(int id)
+{
+ return &fimc_dev->ctrl[id];
+}
+
+#endif /* _FIMC_H */
+
diff --git a/drivers/media/video/samsung/fimc/fimc_capture.c b/drivers/media/video/samsung/fimc/fimc_capture.c
new file mode 100644
index 0000000..6b4fd85
--- /dev/null
+++ b/drivers/media/video/samsung/fimc/fimc_capture.c
@@ -0,0 +1,1794 @@
+/* linux/drivers/media/video/samsung/fimc/fimc_capture.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * V4L2 Capture device support file for Samsung Camera Interface (FIMC) 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/slab.h>
+#include <linux/bootmem.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_samsung.h>
+#include <linux/clk.h>
+#include <linux/mm.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <plat/media.h>
+#include <plat/clock.h>
+#include <plat/fimc.h>
+#include <linux/delay.h>
+
+#include "fimc.h"
+
+/* subdev handling macro */
+#define subdev_call(ctrl, o, f, args...) \
+ v4l2_subdev_call(ctrl->cam->sd, o, f, ##args)
+
+/* #define FIMC_CAP_DEBUG */
+
+#ifdef FIMC_CAP_DEBUG
+#ifdef fimc_dbg
+#undef fimc_dbg
+#endif
+#define fimc_dbg fimc_err
+#endif
+
+static int vtmode = 0;
+static int device_id = 0;
+
+static const struct v4l2_fmtdesc capture_fmts[] = {
+ {
+ .index = 0,
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ .flags = FORMAT_FLAGS_PACKED,
+ .description = "RGB-5-6-5",
+ .pixelformat = V4L2_PIX_FMT_RGB565,
+ }, {
+ .index = 1,
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ .flags = FORMAT_FLAGS_PACKED,
+ .description = "RGB-8-8-8, unpacked 24 bpp",
+ .pixelformat = V4L2_PIX_FMT_RGB32,
+ }, {
+ .index = 2,
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ .flags = FORMAT_FLAGS_PACKED,
+ .description = "YUV 4:2:2 packed, YCbYCr",
+ .pixelformat = V4L2_PIX_FMT_YUYV,
+ }, {
+ .index = 3,
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ .flags = FORMAT_FLAGS_PACKED,
+ .description = "YUV 4:2:2 packed, CbYCrY",
+ .pixelformat = V4L2_PIX_FMT_UYVY,
+ }, {
+ .index = 4,
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ .flags = FORMAT_FLAGS_PACKED,
+ .description = "YUV 4:2:2 packed, CrYCbY",
+ .pixelformat = V4L2_PIX_FMT_VYUY,
+ }, {
+ .index = 5,
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ .flags = FORMAT_FLAGS_PACKED,
+ .description = "YUV 4:2:2 packed, YCrYCb",
+ .pixelformat = V4L2_PIX_FMT_YVYU,
+ }, {
+ .index = 6,
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ .flags = FORMAT_FLAGS_PLANAR,
+ .description = "YUV 4:2:2 planar, Y/Cb/Cr",
+ .pixelformat = V4L2_PIX_FMT_YUV422P,
+ }, {
+ .index = 7,
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ .flags = FORMAT_FLAGS_PLANAR,
+ .description = "YUV 4:2:0 planar, Y/CbCr",
+ .pixelformat = V4L2_PIX_FMT_NV12,
+ }, {
+ .index = 8,
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ .flags = FORMAT_FLAGS_PLANAR,
+ .description = "YUV 4:2:0 planar, Y/CbCr, Tiled",
+ .pixelformat = V4L2_PIX_FMT_NV12T,
+ }, {
+ .index = 9,
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ .flags = FORMAT_FLAGS_PLANAR,
+ .description = "YUV 4:2:0 planar, Y/CrCb",
+ .pixelformat = V4L2_PIX_FMT_NV21,
+ }, {
+ .index = 10,
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ .flags = FORMAT_FLAGS_PLANAR,
+ .description = "YUV 4:2:2 planar, Y/CbCr",
+ .pixelformat = V4L2_PIX_FMT_NV16,
+ }, {
+ .index = 11,
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ .flags = FORMAT_FLAGS_PLANAR,
+ .description = "YUV 4:2:2 planar, Y/CrCb",
+ .pixelformat = V4L2_PIX_FMT_NV61,
+ }, {
+ .index = 12,
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ .flags = FORMAT_FLAGS_PLANAR,
+ .description = "YUV 4:2:0 planar, Y/Cb/Cr",
+ .pixelformat = V4L2_PIX_FMT_YUV420,
+ }, {
+ .index = 13,
+ .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ .flags = FORMAT_FLAGS_ENCODED,
+ .description = "Encoded JPEG bitstream",
+ .pixelformat = V4L2_PIX_FMT_JPEG,
+ },
+};
+
+static const struct v4l2_queryctrl fimc_controls[] = {
+ {
+ .id = V4L2_CID_ROTATION,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Roataion",
+ .minimum = 0,
+ .maximum = 270,
+ .step = 90,
+ .default_value = 0,
+ }, {
+ .id = V4L2_CID_HFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Horizontal Flip",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ }, {
+ .id = V4L2_CID_VFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Vertical Flip",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ }, {
+ .id = V4L2_CID_PADDR_Y,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Physical address Y",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ .flags = V4L2_CTRL_FLAG_READ_ONLY,
+ }, {
+ .id = V4L2_CID_PADDR_CB,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Physical address Cb",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ .flags = V4L2_CTRL_FLAG_READ_ONLY,
+ }, {
+ .id = V4L2_CID_PADDR_CR,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Physical address Cr",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ .flags = V4L2_CTRL_FLAG_READ_ONLY,
+ }, {
+ .id = V4L2_CID_PADDR_CBCR,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Physical address CbCr",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ .flags = V4L2_CTRL_FLAG_READ_ONLY,
+ },
+};
+
+#ifndef CONFIG_VIDEO_FIMC_MIPI
+void s3c_csis_start(int lanes, int settle, int align, int width, int height,
+ int pixel_format) {}
+#endif
+
+static int fimc_camera_init(struct fimc_control *ctrl)
+{
+ int ret;
+
+ fimc_dbg("%s\n", __func__);
+
+ /* do nothing if already initialized */
+ if (ctrl->cam->initialized)
+ return 0;
+
+ /* enable camera power if needed */
+ if (ctrl->cam->cam_power)
+ ctrl->cam->cam_power(1);
+
+ /* subdev call for init */
+ ret = subdev_call(ctrl, core, init, 0);
+ if (ret == -ENOIOCTLCMD) {
+ fimc_err("%s: init subdev api not supported\n",
+ __func__);
+ return ret;
+ }
+
+ if (ctrl->cam->type == CAM_TYPE_MIPI) {
+ /* subdev call for sleep/wakeup:
+ * no error although no s_stream api support
+ */
+ u32 pixelformat;
+ if (ctrl->cap->fmt.pixelformat == V4L2_PIX_FMT_JPEG)
+ pixelformat = V4L2_PIX_FMT_JPEG;
+ else
+ pixelformat = ctrl->cam->pixelformat;
+
+ subdev_call(ctrl, video, s_stream, 0);
+ s3c_csis_start(ctrl->cam->mipi_lanes, ctrl->cam->mipi_settle, \
+ ctrl->cam->mipi_align, ctrl->cam->width, \
+ ctrl->cam->height, pixelformat);
+ subdev_call(ctrl, video, s_stream, 1);
+ }
+
+ ctrl->cam->initialized = 1;
+
+ return 0;
+}
+
+
+/* This function must be called after s_fmt and s_parm call to the subdev
+ * has already been made.
+ *
+ * - obtains the camera output (input to FIMC) resolution.
+ * - sets the preview size (aka camera output resolution) and framerate.
+ * - starts the preview operation.
+ *
+ * On success, returns 0.
+ * On failure, returns the error code of the call that failed.
+ */
+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 {
+ 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;
+ cam_ctrl.value = 1;
+ ret = subdev_call(ctrl, core, s_ctrl, &cam_ctrl);
+
+ /* When the device is waking up from sleep, this call may fail. In
+ * that case, it is better to reset the camera sensor and start again.
+ * If the preview fails again, the reason might be something else and
+ * we should return the error.
+ */
+ if (ret < 0 && ret != -ENOIOCTLCMD) {
+ ctrl->cam->initialized = 0;
+ fimc_camera_init(ctrl);
+ ret = subdev_call(ctrl, core, s_ctrl, &cam_ctrl);
+ if (ret < 0 && ret != -ENOIOCTLCMD) {
+ fimc_err("%s: Error in V4L2_CID_CAM_PREVIEW_ONOFF"
+ " - start\n", __func__);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int fimc_camera_get_jpeg_memsize(struct fimc_control *ctrl)
+{
+ int ret;
+ struct v4l2_control cam_ctrl;
+ cam_ctrl.id = V4L2_CID_CAM_JPEG_MEMSIZE;
+
+ ret = subdev_call(ctrl, core, g_ctrl, &cam_ctrl);
+ if (ret < 0) {
+ fimc_err("%s: Subdev doesn't support JEPG encoding.\n", \
+ __func__);
+ return 0;
+ }
+
+ return cam_ctrl.value;
+}
+
+
+static int fimc_capture_scaler_info(struct fimc_control *ctrl)
+{
+ struct fimc_scaler *sc = &ctrl->sc;
+ struct v4l2_rect *window = &ctrl->cam->window;
+ int tx, ty, sx, sy;
+
+ sx = window->width;
+ sy = window->height;
+ tx = ctrl->cap->fmt.width;
+ ty = ctrl->cap->fmt.height;
+
+ sc->real_width = sx;
+ sc->real_height = sy;
+
+ fimc_dbg("%s: CamOut (%d, %d), TargetOut (%d, %d)\n", \
+ __func__, sx, sy, tx, ty);
+
+ if (sx <= 0 || sy <= 0) {
+ fimc_err("%s: invalid source size\n", __func__);
+ return -EINVAL;
+ }
+
+ if (tx <= 0 || ty <= 0) {
+ fimc_err("%s: invalid target size\n", __func__);
+ return -EINVAL;
+ }
+
+ fimc_get_scaler_factor(sx, tx, &sc->pre_hratio, &sc->hfactor);
+ fimc_get_scaler_factor(sy, ty, &sc->pre_vratio, &sc->vfactor);
+
+ /* Tushar - sx and sy should be multiple of pre_hratio and pre_vratio */
+ sc->pre_dst_width = sx / sc->pre_hratio;
+ sc->pre_dst_height = sy / sc->pre_vratio;
+
+ sc->main_hratio = (sx << 8) / (tx << sc->hfactor);
+ sc->main_vratio = (sy << 8) / (ty << sc->vfactor);
+
+ sc->scaleup_h = (tx >= sx) ? 1 : 0;
+ sc->scaleup_v = (ty >= sy) ? 1 : 0;
+
+ return 0;
+}
+
+/**
+ * fimc_add_inqueue: used to add the buffer at given index to inqueue
+ *
+ * Called from qbuf().
+ *
+ * Returns error if buffer is already in queue or buffer index is out of range.
+ */
+static int fimc_add_inqueue(struct fimc_control *ctrl, int i)
+{
+ struct fimc_capinfo *cap = ctrl->cap;
+
+ struct fimc_buf_set *buf;
+
+ if (i >= cap->nr_bufs)
+ return -EINVAL;
+
+ list_for_each_entry(buf, &cap->inq, list) {
+ if (buf->id == i) {
+ fimc_dbg("%s: buffer %d already in inqueue.\n", \
+ __func__, i);
+ return -EINVAL;
+ }
+ }
+ list_add_tail(&cap->bufs[i].list, &cap->inq);
+
+ return 0;
+}
+
+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;
+
+ /* 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;
+ }
+
+ 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;
+}
+
+static int fimc_update_hwaddr(struct fimc_control *ctrl)
+{
+ int i;
+
+ for (i = 0; i < FIMC_PINGPONG; i++)
+ fimc_add_outqueue(ctrl, i);
+
+ return 0;
+}
+
+int fimc_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ret;
+
+ fimc_dbg("%s\n", __func__);
+
+ if (!ctrl->cam || !ctrl->cam->sd) {
+ fimc_err("%s: No capture device.\n", __func__);
+ return -ENODEV;
+ }
+
+ mutex_lock(&ctrl->v4l2_lock);
+ ret = subdev_call(ctrl, video, g_parm, a);
+ mutex_unlock(&ctrl->v4l2_lock);
+
+ return ret;
+}
+
+int fimc_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ret = 0;
+
+ fimc_dbg("%s\n", __func__);
+
+ if (!ctrl->cam || !ctrl->cam->sd) {
+ fimc_err("%s: No capture device.\n", __func__);
+ return -ENODEV;
+ }
+
+ mutex_lock(&ctrl->v4l2_lock);
+ if (ctrl->id != 2)
+ ret = subdev_call(ctrl, video, s_parm, a);
+ mutex_unlock(&ctrl->v4l2_lock);
+
+ return ret;
+}
+
+/* Enumerate controls */
+int fimc_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *qc)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int i, ret;
+
+ fimc_dbg("%s\n", __func__);
+
+ for (i = 0; i < ARRAY_SIZE(fimc_controls); i++) {
+ if (fimc_controls[i].id == qc->id) {
+ memcpy(qc, &fimc_controls[i], \
+ sizeof(struct v4l2_queryctrl));
+ return 0;
+ }
+ }
+
+ mutex_lock(&ctrl->v4l2_lock);
+ ret = subdev_call(ctrl, core, queryctrl, qc);
+ mutex_unlock(&ctrl->v4l2_lock);
+
+ return ret;
+}
+
+/* Menu control items */
+int fimc_querymenu(struct file *file, void *fh, struct v4l2_querymenu *qm)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ret;
+
+ fimc_dbg("%s\n", __func__);
+
+ mutex_lock(&ctrl->v4l2_lock);
+ ret = subdev_call(ctrl, core, querymenu, qm);
+ mutex_unlock(&ctrl->v4l2_lock);
+
+ return ret;
+}
+
+
+/* Given the index, we will return the camera name if there is any camera
+ * present at the given id.
+ */
+int fimc_enum_input(struct file *file, void *fh, struct v4l2_input *inp)
+{
+ struct fimc_global *fimc = get_fimc_dev();
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+
+ fimc_dbg("%s: index %d\n", __func__, inp->index);
+
+ if (inp->index < 0 || inp->index >= FIMC_MAXCAMS) {
+ fimc_err("%s: invalid input index, received = %d\n", \
+ __func__, inp->index);
+ return -EINVAL;
+ }
+
+ if (!fimc->camera_isvalid[inp->index])
+ return -EINVAL;
+
+ strcpy(inp->name, fimc->camera[inp->index].info->type);
+ inp->type = V4L2_INPUT_TYPE_CAMERA;
+
+ return 0;
+}
+
+int fimc_g_input(struct file *file, void *fh, unsigned int *i)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ struct fimc_global *fimc = get_fimc_dev();
+
+ /* In case of isueing g_input before s_input */
+ if (!ctrl->cam) {
+ fimc_err("no camera device selected yet!" \
+ "do VIDIOC_S_INPUT first\n");
+ return -ENODEV;
+ }
+
+ *i = (unsigned int) fimc->active_camera;
+
+ fimc_dbg("%s: index %d\n", __func__, *i);
+
+ return 0;
+}
+
+int fimc_release_subdev(struct fimc_control *ctrl)
+{
+ struct fimc_global *fimc = get_fimc_dev();
+ struct i2c_client *client;
+
+ if (ctrl && ctrl->cam && ctrl->cam->sd) {
+ fimc_dbg("%s called\n", __func__);
+ client = v4l2_get_subdevdata(ctrl->cam->sd);
+ i2c_unregister_device(client);
+ ctrl->cam->sd = NULL;
+ if (ctrl->cam->cam_power)
+ ctrl->cam->cam_power(0);
+ ctrl->cam->initialized = 0;
+ ctrl->cam = NULL;
+ fimc->active_camera = -1;
+ }
+ return 0;
+}
+
+static int fimc_configure_subdev(struct fimc_control *ctrl)
+{
+ struct i2c_adapter *i2c_adap;
+ struct i2c_board_info *i2c_info;
+ struct v4l2_subdev *sd;
+ unsigned short addr;
+ char *name;
+
+ /* set parent for mclk */
+ if (clk_get_parent(ctrl->cam->clk->parent))
+ clk_set_parent(ctrl->cam->clk->parent, ctrl->cam->srclk);
+
+ /* set rate for mclk */
+ if (clk_get_rate(ctrl->cam->clk))
+ clk_set_rate(ctrl->cam->clk, ctrl->cam->clk_rate);
+
+ i2c_adap = i2c_get_adapter(ctrl->cam->i2c_busnum);
+ if (!i2c_adap)
+ fimc_err("subdev i2c_adapter missing-skip registration\n");
+
+ i2c_info = ctrl->cam->info;
+ if (!i2c_info) {
+ fimc_err("%s: subdev i2c board info missing\n", __func__);
+ return -ENODEV;
+ }
+
+ name = i2c_info->type;
+ if (!name) {
+ fimc_err("subdev i2c driver name missing-skip registration\n");
+ return -ENODEV;
+ }
+
+ addr = i2c_info->addr;
+ if (!addr) {
+ fimc_err("subdev i2c address missing-skip registration\n");
+ return -ENODEV;
+ }
+ /*
+ * NOTE: first time subdev being registered,
+ * s_config is called and try to initialize subdev device
+ * but in this point, we are not giving MCLK and power to subdev
+ * so nothing happens but pass platform data through
+ */
+ sd = v4l2_i2c_new_subdev_board(&ctrl->v4l2_dev, i2c_adap,
+ i2c_info, &addr);
+ if (!sd) {
+ fimc_err("%s: v4l2 subdev board registering failed\n",
+ __func__);
+ }
+
+ /* Assign subdev to proper camera device pointer */
+ ctrl->cam->sd = sd;
+
+ return 0;
+}
+
+int fimc_s_input(struct file *file, void *fh, unsigned int i)
+{
+ struct fimc_global *fimc = get_fimc_dev();
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ret = 0;
+
+ fimc_dbg("%s: index %d\n", __func__, i);
+
+ if (i < 0 || i >= FIMC_MAXCAMS) {
+ fimc_err("%s: invalid input index\n", __func__);
+ return -EINVAL;
+ }
+
+ if (!fimc->camera_isvalid[i])
+ return -EINVAL;
+
+ if (fimc->camera[i].sd && ctrl->id != 2) {
+ fimc_err("%s: Camera already in use.\n", __func__);
+ return -EBUSY;
+ }
+
+ mutex_lock(&ctrl->v4l2_lock);
+ /* If ctrl->cam is not NULL, there is one subdev already registered.
+ * We need to unregister that subdev first.
+ */
+ if (i != fimc->active_camera) {
+ fimc_release_subdev(ctrl);
+ ctrl->cam = &fimc->camera[i];
+ ret = fimc_configure_subdev(ctrl);
+ if (ret < 0) {
+ mutex_unlock(&ctrl->v4l2_lock);
+ fimc_err("%s: Could not register camera sensor "
+ "with V4L2.\n", __func__);
+ return -ENODEV;
+ }
+ fimc->active_camera = i;
+ }
+
+ if (ctrl->id == 2) {
+ if (i == fimc->active_camera) {
+ ctrl->cam = &fimc->camera[i];
+ } else {
+ mutex_unlock(&ctrl->v4l2_lock);
+ return -EINVAL;
+ }
+ }
+
+ mutex_unlock(&ctrl->v4l2_lock);
+
+ return 0;
+}
+
+int fimc_enum_fmt_vid_capture(struct file *file, void *fh,
+ struct v4l2_fmtdesc *f)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int i = f->index;
+ int num_entries = 0;
+ int ret = 0;
+ enum v4l2_mbus_pixelcode code;
+
+ fimc_dbg("%s\n", __func__);
+
+ if (ctrl->out) {
+ fimc_err("%s: fimc is already used for output mode\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ if (!ctrl->cam || !ctrl->cam->sd) {
+ fimc_err("%s: No capture device.\n", __func__);
+ return -ENODEV;
+ }
+
+ num_entries = sizeof(capture_fmts)/sizeof(struct v4l2_fmtdesc);
+
+ if (i >= num_entries) {
+ mutex_lock(&ctrl->v4l2_lock);
+ ret = subdev_call(ctrl, video, enum_mbus_fmt,
+ f->index - num_entries, &code);
+ mutex_unlock(&ctrl->v4l2_lock);
+ return ret;
+ }
+
+ memcpy(f, &capture_fmts[i], sizeof(*f));
+
+ return 0;
+}
+
+int fimc_g_fmt_vid_capture(struct file *file, void *fh, struct v4l2_format *f)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+
+ fimc_dbg("%s\n", __func__);
+
+ if (!ctrl->cap) {
+ fimc_err("%s: no capture device info\n", __func__);
+ return -EINVAL;
+ }
+
+ mutex_lock(&ctrl->v4l2_lock);
+
+ memcpy(&f->fmt.pix, &ctrl->cap->fmt, sizeof(f->fmt.pix));
+
+ mutex_unlock(&ctrl->v4l2_lock);
+
+ return 0;
+}
+
+/*
+ * Check for whether the requested format
+ * can be streamed out from FIMC
+ * depends on FIMC node
+ */
+static int fimc_fmt_avail(struct fimc_control *ctrl,
+ struct v4l2_format *f)
+{
+ int i;
+
+ /*
+ * TODO: check for which FIMC is used.
+ * Available fmt should be varied for each FIMC
+ */
+
+ for (i = 0; i < sizeof(capture_fmts); i++) {
+ if (capture_fmts[i].pixelformat == f->fmt.pix.pixelformat)
+ return 0;
+ }
+
+ fimc_err("Not supported pixelformat requested\n");
+
+ return -1;
+}
+
+/*
+ * figures out the depth of requested format
+ */
+static int fimc_fmt_depth(struct fimc_control *ctrl, struct v4l2_format *f)
+{
+ int err, depth = 0;
+
+ /* First check for available format or not */
+ err = fimc_fmt_avail(ctrl, f);
+ if (err < 0)
+ return -EINVAL;
+
+ /* handles only supported pixelformats */
+ switch (f->fmt.pix.pixelformat) {
+ case V4L2_PIX_FMT_RGB32:
+ depth = 32;
+ fimc_dbg("32bpp\n");
+ break;
+ case V4L2_PIX_FMT_RGB565:
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_UYVY:
+ case V4L2_PIX_FMT_VYUY:
+ case V4L2_PIX_FMT_YVYU:
+ case V4L2_PIX_FMT_YUV422P:
+ case V4L2_PIX_FMT_NV16:
+ case V4L2_PIX_FMT_NV61:
+ depth = 16;
+ fimc_dbg("16bpp\n");
+ break;
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV12T:
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_YUV420:
+ depth = 12;
+ fimc_dbg("12bpp\n");
+ break;
+ case V4L2_PIX_FMT_JPEG:
+ depth = -1;
+ fimc_dbg("Compressed format.\n");
+ break;
+ default:
+ fimc_dbg("why am I here? - received %x\n",
+ f->fmt.pix.pixelformat);
+ break;
+ }
+
+ return depth;
+}
+
+int fimc_s_fmt_vid_capture(struct file *file, void *fh, struct v4l2_format *f)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ struct fimc_capinfo *cap;
+ struct v4l2_mbus_framefmt mbus_fmt;
+ int ret = 0;
+ int depth;
+
+ fimc_dbg("%s\n", __func__);
+
+ if (!ctrl->cam || !ctrl->cam->sd) {
+ fimc_err("%s: No capture device.\n", __func__);
+ return -ENODEV;
+ }
+ /*
+ * The first time alloc for struct cap_info, and will be
+ * 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);
+ fimc_err("%s: no memory for "
+ "capture device info\n", __func__);
+ return -ENOMEM;
+ }
+
+ }
+ cap = ctrl->cap;
+ memset(cap, 0, sizeof(*cap));
+ memcpy(&cap->fmt, &f->fmt.pix, sizeof(cap->fmt));
+ v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, 0);
+
+ /*
+ * Note that expecting format only can be with
+ * available output format from FIMC
+ * Following items should be handled in driver
+ * bytesperline = width * depth / 8
+ * sizeimage = bytesperline * height
+ */
+ /* This function may return 0 or -1 in case of error, hence need to
+ * check here.
+ */
+ depth = fimc_fmt_depth(ctrl, f);
+ if (depth == 0) {
+ mutex_unlock(&ctrl->v4l2_lock);
+ fimc_err("%s: Invalid pixel format\n", __func__);
+ return -EINVAL;
+ } else if (depth < 0) {
+ /*
+ * When the pixelformat is JPEG, the application is requesting
+ * for data in JPEG compressed format.
+ */
+ mbus_fmt.code = V4L2_MBUS_FMT_FIXED;
+ ret = subdev_call(ctrl, video, try_mbus_fmt, &mbus_fmt);
+ if (ret < 0) {
+ mutex_unlock(&ctrl->v4l2_lock);
+ return -EINVAL;
+ }
+ cap->fmt.colorspace = V4L2_COLORSPACE_JPEG;
+ } else {
+ cap->fmt.bytesperline = (cap->fmt.width * depth) >> 3;
+ cap->fmt.sizeimage = (cap->fmt.bytesperline * cap->fmt.height);
+ }
+
+ if (cap->fmt.colorspace == V4L2_COLORSPACE_JPEG) {
+ ctrl->sc.bypass = 1;
+ cap->lastirq = 1;
+ }
+
+ if (ctrl->id != 2) {
+ ret = subdev_call(ctrl, video, s_mbus_fmt, &mbus_fmt);
+ }
+
+ mutex_unlock(&ctrl->v4l2_lock);
+
+ return ret;
+}
+
+int fimc_try_fmt_vid_capture(struct file *file, void *fh, struct v4l2_format *f)
+{
+ return 0;
+}
+
+static int fimc_alloc_buffers(struct fimc_control *ctrl, int size[], int align)
+{
+ struct fimc_capinfo *cap = ctrl->cap;
+ int i, plane;
+
+ for (i = 0; i < cap->nr_bufs; i++) {
+ for (plane = 0; plane < 4; plane++) {
+ cap->bufs[i].length[plane] = size[plane];
+ if (!cap->bufs[i].length[plane])
+ continue;
+
+ fimc_dma_alloc(ctrl, &cap->bufs[i], plane, align);
+
+ if (!cap->bufs[i].base[plane])
+ goto err_alloc;
+ }
+
+ cap->bufs[i].state = VIDEOBUF_PREPARED;
+ cap->bufs[i].id = i;
+ }
+
+ return 0;
+
+err_alloc:
+ for (i = 0; i < cap->nr_bufs; i++) {
+ if (cap->bufs[i].base[plane])
+ fimc_dma_free(ctrl, &cap->bufs[i], plane);
+
+ memset(&cap->bufs[i], 0, sizeof(cap->bufs[i]));
+ }
+
+ return -ENOMEM;
+}
+
+static void fimc_free_buffers(struct fimc_control *ctrl)
+{
+ struct fimc_capinfo *cap;
+ int i;
+
+ if (ctrl && ctrl->cap)
+ cap = ctrl->cap;
+ else
+ return;
+
+
+ for (i = 0; i < cap->nr_bufs; i++) {
+ memset(&cap->bufs[i], 0, sizeof(cap->bufs[i]));
+ cap->bufs[i].state = VIDEOBUF_NEEDS_INIT;
+ }
+
+ ctrl->mem.curr = ctrl->mem.base;
+}
+
+int fimc_reqbufs_capture(void *fh, struct v4l2_requestbuffers *b)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ struct fimc_capinfo *cap = ctrl->cap;
+ int ret = 0, i;
+ int size[4] = { 0, 0, 0, 0};
+ int align = 0;
+
+ if (b->memory != V4L2_MEMORY_MMAP) {
+ fimc_err("%s: invalid memory type\n", __func__);
+ return -EINVAL;
+ }
+
+ if (!cap) {
+ fimc_err("%s: no capture device info\n", __func__);
+ return -ENODEV;
+ }
+
+ if (!ctrl->cam || !ctrl->cam->sd) {
+ fimc_err("%s: No capture device.\n", __func__);
+ return -ENODEV;
+ }
+
+ mutex_lock(&ctrl->v4l2_lock);
+
+ if (b->count < 1 || b->count > FIMC_CAPBUFS)
+ return -EINVAL;
+
+ /* It causes flickering as buf_0 and buf_3 refer to same hardware
+ * address.
+ */
+ if (b->count == 3)
+ b->count = 4;
+
+ cap->nr_bufs = b->count;
+
+ fimc_dbg("%s: requested %d buffers\n", __func__, b->count);
+
+ INIT_LIST_HEAD(&cap->inq);
+ fimc_free_buffers(ctrl);
+
+ switch (cap->fmt.pixelformat) {
+ case V4L2_PIX_FMT_RGB32: /* fall through */
+ case V4L2_PIX_FMT_RGB565: /* fall through */
+ case V4L2_PIX_FMT_YUYV: /* fall through */
+ case V4L2_PIX_FMT_UYVY: /* fall through */
+ case V4L2_PIX_FMT_VYUY: /* fall through */
+ case V4L2_PIX_FMT_YVYU: /* fall through */
+ case V4L2_PIX_FMT_YUV422P: /* fall through */
+ size[0] = cap->fmt.sizeimage;
+ break;
+
+ case V4L2_PIX_FMT_NV16: /* fall through */
+ case V4L2_PIX_FMT_NV61:
+ size[0] = cap->fmt.width * cap->fmt.height;
+ size[1] = cap->fmt.width * cap->fmt.height;
+ break;
+ case V4L2_PIX_FMT_NV12:
+ size[0] = cap->fmt.width * cap->fmt.height;
+ size[1] = cap->fmt.width * cap->fmt.height/2;
+ break;
+ case V4L2_PIX_FMT_NV21:
+ size[0] = cap->fmt.width * cap->fmt.height;
+ size[1] = cap->fmt.width * cap->fmt.height/2;
+ break;
+ case V4L2_PIX_FMT_NV12T:
+ /* Tiled frame size calculations as per 4x2 tiles
+ * - Width: Has to be aligned to 2 times the tile width
+ * - Height: Has to be aligned to the tile height
+ * - Alignment: Has to be aligned to the size of the
+ * macrotile (size of 4 tiles)
+ *
+ * NOTE: In case of rotation, we need modified calculation as
+ * width and height are aligned to different values.
+ */
+ if (cap->rotate == 90 || cap->rotate == 270) {
+ size[0] = ALIGN(ALIGN(cap->fmt.height, 128) *
+ ALIGN(cap->fmt.width, 32),
+ SZ_8K);
+ size[1] = ALIGN(ALIGN(cap->fmt.height, 128) *
+ ALIGN(cap->fmt.width/2, 32),
+ SZ_8K);
+ } else {
+ size[0] = ALIGN(ALIGN(cap->fmt.width, 128) *
+ ALIGN(cap->fmt.height, 32),
+ SZ_8K);
+ size[1] = ALIGN(ALIGN(cap->fmt.width, 128) *
+ ALIGN(cap->fmt.height/2, 32),
+ SZ_8K);
+ }
+ align = SZ_8K;
+ break;
+
+ case V4L2_PIX_FMT_YUV420:
+ size[0] = cap->fmt.width * cap->fmt.height;
+ size[1] = cap->fmt.width * cap->fmt.height >> 2;
+ size[2] = cap->fmt.width * cap->fmt.height >> 2;
+ break;
+
+ case V4L2_PIX_FMT_JPEG:
+ size[0] = fimc_camera_get_jpeg_memsize(ctrl);
+ default:
+ break;
+ }
+
+ ret = fimc_alloc_buffers(ctrl, size, align);
+ if (ret) {
+ fimc_err("%s: no memory for "
+ "capture buffer\n", __func__);
+ mutex_unlock(&ctrl->v4l2_lock);
+ return -ENOMEM;
+ }
+
+ for (i = cap->nr_bufs; i < FIMC_PHYBUFS; i++) {
+ memcpy(&cap->bufs[i], \
+ &cap->bufs[i - cap->nr_bufs], sizeof(cap->bufs[i]));
+ }
+
+ mutex_unlock(&ctrl->v4l2_lock);
+
+ return 0;
+}
+
+int fimc_querybuf_capture(void *fh, struct v4l2_buffer *b)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+
+ if (!ctrl->cap || !ctrl->cap->bufs) {
+ fimc_err("%s: no capture device info\n", __func__);
+ return -ENODEV;
+ }
+
+ if (ctrl->status != FIMC_STREAMOFF) {
+ fimc_err("fimc is running\n");
+ return -EBUSY;
+ }
+
+ mutex_lock(&ctrl->v4l2_lock);
+
+ b->length = ctrl->cap->bufs[b->index].length[FIMC_ADDR_Y]
+ + ctrl->cap->bufs[b->index].length[FIMC_ADDR_CB]
+ + ctrl->cap->bufs[b->index].length[FIMC_ADDR_CR];
+
+ b->m.offset = b->index * PAGE_SIZE;
+
+ ctrl->cap->bufs[b->index].state = VIDEOBUF_IDLE;
+
+ mutex_unlock(&ctrl->v4l2_lock);
+
+ fimc_dbg("%s: %d bytes at index: %d\n", __func__, b->length, b->index);
+
+ return 0;
+}
+
+int fimc_g_ctrl_capture(void *fh, struct v4l2_control *c)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ret = 0;
+
+ fimc_dbg("%s\n", __func__);
+
+ if (!ctrl->cam || !ctrl->cam->sd || !ctrl->cap) {
+ fimc_err("%s: No capture device.\n", __func__);
+ return -ENODEV;
+ }
+
+ mutex_lock(&ctrl->v4l2_lock);
+
+ switch (c->id) {
+ case V4L2_CID_ROTATION:
+ c->value = ctrl->cap->rotate;
+ break;
+
+ case V4L2_CID_HFLIP:
+ c->value = (ctrl->cap->flip & FIMC_XFLIP) ? 1 : 0;
+ break;
+
+ case V4L2_CID_VFLIP:
+ c->value = (ctrl->cap->flip & FIMC_YFLIP) ? 1 : 0;
+ break;
+
+ default:
+ /* get ctrl supported by subdev */
+ mutex_unlock(&ctrl->v4l2_lock);
+ ret = subdev_call(ctrl, core, g_ctrl, c);
+ mutex_lock(&ctrl->v4l2_lock);
+ break;
+ }
+
+ mutex_unlock(&ctrl->v4l2_lock);
+
+ return ret;
+}
+
+/**
+ * We used s_ctrl API to get the physical address of the buffers.
+ * In g_ctrl, we can pass only one parameter, thus we cannot pass
+ * the index of the buffer.
+ * In order to use g_ctrl for obtaining the physical address, we
+ * will have to create CID ids for all values (4 ids for Y0~Y3 and 4 ids
+ * for C0~C3). Currently, we will continue with the existing
+ * implementation till we get any better idea to implement.
+ */
+int fimc_s_ctrl_capture(void *fh, struct v4l2_control *c)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ret = 0;
+
+ fimc_info2("%s\n", __func__);
+
+ if (!ctrl->cam || !ctrl->cam->sd || !ctrl->cap || !ctrl->cap->bufs) {
+ fimc_err("%s: No capture device.\n", __func__);
+ return -ENODEV;
+ }
+
+ mutex_lock(&ctrl->v4l2_lock);
+
+ switch (c->id) {
+ case V4L2_CID_ROTATION:
+ ctrl->cap->rotate = c->value;
+ break;
+
+ case V4L2_CID_HFLIP: /* fall through */
+ ctrl->cap->flip |= FIMC_XFLIP;
+ break;
+ case V4L2_CID_VFLIP:
+ ctrl->cap->flip |= FIMC_YFLIP;
+ break;
+
+ case V4L2_CID_PADDR_Y:
+ c->value = ctrl->cap->bufs[c->value].base[FIMC_ADDR_Y];
+ break;
+
+ case V4L2_CID_PADDR_CB: /* fall through */
+ case V4L2_CID_PADDR_CBCR:
+ c->value = ctrl->cap->bufs[c->value].base[FIMC_ADDR_CB];
+ break;
+
+ case V4L2_CID_PADDR_CR:
+ c->value = ctrl->cap->bufs[c->value].base[FIMC_ADDR_CR];
+ break;
+
+ /* Implementation as per C100 FIMC driver */
+ case V4L2_CID_STREAM_PAUSE:
+ fimc_hwset_stop_processing(ctrl);
+ break;
+
+ case V4L2_CID_IMAGE_EFFECT_APPLY:
+ ctrl->fe.ie_on = c->value ? 1 : 0;
+ ctrl->fe.ie_after_sc = 0;
+ ret = fimc_hwset_image_effect(ctrl);
+ break;
+
+ case V4L2_CID_IMAGE_EFFECT_FN:
+ if (c->value < 0 || c->value > FIMC_EFFECT_FIN_SILHOUETTE)
+ return -EINVAL;
+ ctrl->fe.fin = c->value;
+ ret = 0;
+ break;
+
+ case V4L2_CID_IMAGE_EFFECT_CB:
+ ctrl->fe.pat_cb = c->value & 0xFF;
+ ret = 0;
+ break;
+
+ case V4L2_CID_IMAGE_EFFECT_CR:
+ ctrl->fe.pat_cr = c->value & 0xFF;
+ 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);
+ if (2 != ctrl->id)
+ ret = subdev_call(ctrl, core, s_ctrl, c);
+ else
+ ret = 0;
+ mutex_lock(&ctrl->v4l2_lock);
+ break;
+ }
+
+ mutex_unlock(&ctrl->v4l2_lock);
+
+ return ret;
+}
+
+int fimc_s_ext_ctrls_capture(void *fh, struct v4l2_ext_controls *c)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ret = 0;
+
+ mutex_lock(&ctrl->v4l2_lock);
+
+ /* try on subdev */
+ ret = subdev_call(ctrl, core, s_ext_ctrls, c);
+
+ mutex_unlock(&ctrl->v4l2_lock);
+
+ return ret;
+}
+
+int fimc_cropcap_capture(void *fh, struct v4l2_cropcap *a)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ struct fimc_capinfo *cap = ctrl->cap;
+
+ fimc_dbg("%s\n", __func__);
+
+ if (!ctrl->cam || !ctrl->cam->sd || !ctrl->cap) {
+ fimc_err("%s: No capture device.\n", __func__);
+ return -ENODEV;
+ }
+
+ mutex_lock(&ctrl->v4l2_lock);
+
+ /* crop limitations */
+ cap->cropcap.bounds.left = 0;
+ cap->cropcap.bounds.top = 0;
+ cap->cropcap.bounds.width = ctrl->cam->width;
+ cap->cropcap.bounds.height = ctrl->cam->height;
+
+ /* crop default values */
+ cap->cropcap.defrect.left = 0;
+ cap->cropcap.defrect.top = 0;
+ cap->cropcap.defrect.width = ctrl->cam->width;
+ cap->cropcap.defrect.height = ctrl->cam->height;
+
+ a->bounds = cap->cropcap.bounds;
+ a->defrect = cap->cropcap.defrect;
+
+ mutex_unlock(&ctrl->v4l2_lock);
+
+ return 0;
+}
+
+int fimc_g_crop_capture(void *fh, struct v4l2_crop *a)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+
+ fimc_dbg("%s\n", __func__);
+
+ if (!ctrl->cap) {
+ fimc_err("%s: No capture device.\n", __func__);
+ return -ENODEV;
+ }
+
+ mutex_lock(&ctrl->v4l2_lock);
+ a->c = ctrl->cap->crop;
+ mutex_unlock(&ctrl->v4l2_lock);
+
+ return 0;
+}
+
+static int fimc_capture_crop_size_check(struct fimc_control *ctrl)
+{
+ struct fimc_capinfo *cap = ctrl->cap;
+ int win_hor_offset = 0, win_hor_offset2 = 0;
+ int win_ver_offset = 0, win_ver_offset2 = 0;
+ int crop_width = 0, crop_height = 0;
+
+ /* check win_hor_offset, win_hor_offset2 */
+ win_hor_offset = ctrl->cam->window.left;
+ win_hor_offset2 = ctrl->cam->width - ctrl->cam->window.left -
+ ctrl->cam->window.width;
+
+ win_ver_offset = ctrl->cam->window.top;
+ win_ver_offset2 = ctrl->cam->height - ctrl->cam->window.top -
+ ctrl->cam->window.height;
+
+ if (win_hor_offset < 0 || win_hor_offset2 < 0) {
+ fimc_err("%s: Offset (left-side(%d) or right-side(%d) "
+ "is negative.\n", __func__, \
+ win_hor_offset, win_hor_offset2);
+ return -1;
+ }
+
+ if (win_ver_offset < 0 || win_ver_offset2 < 0) {
+ fimc_err("%s: Offset (top-side(%d) or bottom-side(%d)) "
+ "is negative.\n", __func__, \
+ win_ver_offset, win_ver_offset2);
+ return -1;
+ }
+
+ if ((win_hor_offset % 2) || (win_hor_offset2 % 2)) {
+ fimc_err("%s: win_hor_offset must be multiple of 2\n", \
+ __func__);
+ return -1;
+ }
+
+ /* check crop_width, crop_height */
+ crop_width = ctrl->cam->window.width;
+ crop_height = ctrl->cam->window.height;
+
+ if (crop_width % 16) {
+ fimc_err("%s: crop_width must be multiple of 16\n", __func__);
+ return -1;
+ }
+
+ switch (cap->fmt.pixelformat) {
+ case V4L2_PIX_FMT_YUV420: /* fall through */
+ case V4L2_PIX_FMT_NV12: /* fall through */
+ case V4L2_PIX_FMT_NV21: /* fall through */
+ case V4L2_PIX_FMT_NV12T: /* fall through */
+ if ((crop_height % 2) || (crop_height < 8)) {
+ fimc_err("%s: crop_height error!\n", __func__);
+ return -1;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/** Given crop parameters are w.r.t. target resolution. Scale
+ * it w.r.t. camera source resolution.
+ *
+ * Steps:
+ * 1. Scale as camera resolution with fixed-point calculation
+ * 2. Check for overflow condition
+ * 3. Apply FIMC constrainsts
+ */
+static void fimc_capture_update_crop_window(struct fimc_control *ctrl)
+{
+ unsigned int zoom_hor = 0;
+ unsigned int zoom_ver = 0;
+ unsigned int multiplier = 1024;
+
+ if (!ctrl->cam->width || !ctrl->cam->height)
+ return;
+
+ zoom_hor = ctrl->cap->fmt.width * multiplier / ctrl->cam->width;
+ zoom_ver = ctrl->cap->fmt.height * multiplier / ctrl->cam->height;
+
+ if (!zoom_hor || !zoom_ver)
+ return;
+
+ /* Width */
+ ctrl->cam->window.width = ctrl->cap->crop.width * multiplier / zoom_hor;
+ if (ctrl->cam->window.width > ctrl->cam->width)
+ ctrl->cam->window.width = ctrl->cam->width;
+ if (ctrl->cam->window.width % 16)
+ ctrl->cam->window.width =
+ (ctrl->cam->window.width + 0xF) & ~0xF;
+
+ /* Left offset */
+ ctrl->cam->window.left = ctrl->cap->crop.left * multiplier / zoom_hor;
+ if (ctrl->cam->window.width + ctrl->cam->window.left > ctrl->cam->width)
+ ctrl->cam->window.left =
+ (ctrl->cam->width - ctrl->cam->window.width)/2;
+ if (ctrl->cam->window.left % 2)
+ ctrl->cam->window.left--;
+
+ /* Height */
+ ctrl->cam->window.height =
+ (ctrl->cap->crop.height * multiplier) / zoom_ver;
+ if (ctrl->cam->window.top > ctrl->cam->height)
+ ctrl->cam->window.height = ctrl->cam->height;
+ if (ctrl->cam->window.height % 2)
+ ctrl->cam->window.height--;
+
+ /* Top offset */
+ ctrl->cam->window.top = ctrl->cap->crop.top * multiplier / zoom_ver;
+ if (ctrl->cam->window.height + ctrl->cam->window.top >
+ ctrl->cam->height)
+ ctrl->cam->window.top =
+ (ctrl->cam->height - ctrl->cam->window.height)/2;
+ if (ctrl->cam->window.top % 2)
+ ctrl->cam->window.top--;
+
+ fimc_dbg("Cam (%dx%d) Crop: (%d %d %d %d) Win: (%d %d %d %d)\n", \
+ ctrl->cam->width, ctrl->cam->height, \
+ ctrl->cap->crop.left, ctrl->cap->crop.top, \
+ ctrl->cap->crop.width, ctrl->cap->crop.height, \
+ ctrl->cam->window.left, ctrl->cam->window.top, \
+ ctrl->cam->window.width, ctrl->cam->window.height);
+
+}
+
+int fimc_s_crop_capture(void *fh, struct v4l2_crop *a)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ret = 0;
+
+ fimc_dbg("%s\n", __func__);
+
+ if (!ctrl->cap) {
+ fimc_err("%s: No capture device.\n", __func__);
+ return -ENODEV;
+ }
+
+ mutex_lock(&ctrl->v4l2_lock);
+ ctrl->cap->crop = a->c;
+
+ fimc_capture_update_crop_window(ctrl);
+
+ ret = fimc_capture_crop_size_check(ctrl);
+ if (ret < 0) {
+ mutex_unlock(&ctrl->v4l2_lock);
+ fimc_err("%s: Invalid crop parameters.\n", __func__);
+ return -EINVAL;
+ }
+
+ if (ctrl->status == FIMC_STREAMON &&
+ ctrl->cap->fmt.pixelformat != V4L2_PIX_FMT_JPEG) {
+ fimc_hwset_shadow_disable(ctrl);
+ fimc_hwset_camera_offset(ctrl);
+ fimc_capture_scaler_info(ctrl);
+ fimc_hwset_prescaler(ctrl, &ctrl->sc);
+ fimc_hwset_scaler(ctrl, &ctrl->sc);
+ fimc_hwset_shadow_enable(ctrl);
+ }
+
+ mutex_unlock(&ctrl->v4l2_lock);
+
+ return 0;
+}
+
+int fimc_start_capture(struct fimc_control *ctrl)
+{
+ fimc_dbg("%s\n", __func__);
+
+ if (!ctrl->sc.bypass)
+ fimc_hwset_start_scaler(ctrl);
+
+ fimc_hwset_enable_capture(ctrl, ctrl->sc.bypass);
+
+ return 0;
+}
+
+int fimc_stop_capture(struct fimc_control *ctrl)
+{
+ fimc_dbg("%s\n", __func__);
+
+ if (ctrl->cap->lastirq) {
+ fimc_hwset_enable_lastirq(ctrl);
+ fimc_hwset_disable_capture(ctrl);
+ fimc_hwset_disable_lastirq(ctrl);
+ ctrl->cap->lastirq = 0;
+ } else {
+ fimc_hwset_disable_capture(ctrl);
+ }
+
+ fimc_hwset_disable_irq(ctrl);
+ fimc_hwset_clear_irq(ctrl);
+
+ if (!ctrl->sc.bypass)
+ fimc_hwset_stop_scaler(ctrl);
+ else
+ ctrl->sc.bypass = 0;
+
+ fimc_wait_disable_capture(ctrl);
+
+ return 0;
+}
+
+static void fimc_reset_capture(struct fimc_control *ctrl)
+{
+ int i;
+
+ ctrl->status = FIMC_READY_OFF;
+
+ fimc_stop_capture(ctrl);
+
+ for (i = 0; i < FIMC_PINGPONG; i++)
+ fimc_add_inqueue(ctrl, ctrl->cap->outq[i]);
+
+ fimc_hwset_reset(ctrl);
+
+ if (0 != ctrl->id)
+ fimc_clk_en(ctrl, false);
+
+ ctrl->status = FIMC_STREAMOFF;
+}
+
+
+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__);
+ return -ENODEV;
+ }
+
+ if (ctrl->status == FIMC_STREAMON) {
+ fimc_err("%s: Camera already running.\n", __func__);
+ return -EBUSY;
+ }
+
+ mutex_lock(&ctrl->v4l2_lock);
+
+ if (0 != ctrl->id)
+ fimc_clk_en(ctrl, true);
+
+ ctrl->status = FIMC_READY_ON;
+ cap->irq = 0;
+
+ fimc_hwset_enable_irq(ctrl, 0, 1);
+
+ 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);
+ if (ret < 0) {
+ fimc_reset_capture(ctrl);
+ mutex_unlock(&ctrl->v4l2_lock);
+ return ret;
+ }
+ }
+
+ fimc_hwset_camera_type(ctrl);
+ fimc_hwset_camera_polarity(ctrl);
+ fimc_update_hwaddr(ctrl);
+
+ if (cap->fmt.pixelformat != V4L2_PIX_FMT_JPEG) {
+ fimc_hwset_camera_source(ctrl);
+ fimc_hwset_camera_offset(ctrl);
+
+ fimc_capture_scaler_info(ctrl);
+ fimc_hwset_prescaler(ctrl, &ctrl->sc);
+ fimc_hwset_scaler(ctrl, &ctrl->sc);
+
+ fimc_hwset_output_colorspace(ctrl, cap->fmt.pixelformat);
+ fimc_hwset_output_addr_style(ctrl, cap->fmt.pixelformat);
+ fimc_hwset_output_area(ctrl, cap->fmt.width, cap->fmt.height);
+
+ if (cap->fmt.pixelformat == V4L2_PIX_FMT_RGB32 ||
+ cap->fmt.pixelformat == V4L2_PIX_FMT_RGB565)
+ fimc_hwset_output_rgb(ctrl, cap->fmt.pixelformat);
+ else
+ fimc_hwset_output_yuv(ctrl, cap->fmt.pixelformat);
+
+ 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);
+
+ if (rot & FIMC_ROT) {
+ fimc_hwset_org_output_size(ctrl, cap->fmt.height,
+ cap->fmt.width);
+ } else {
+ fimc_hwset_org_output_size(ctrl, cap->fmt.width,
+ cap->fmt.height);
+ }
+ fimc_hwset_jpeg_mode(ctrl, false);
+ } else {
+ fimc_hwset_output_area_size(ctrl, \
+ fimc_camera_get_jpeg_memsize(ctrl)/2);
+ fimc_hwset_jpeg_mode(ctrl, true);
+ }
+
+ if (ctrl->cap->fmt.colorspace == V4L2_COLORSPACE_JPEG)
+ fimc_hwset_scaler_bypass(ctrl);
+
+ fimc_start_capture(ctrl);
+
+ if (ctrl->cap->fmt.colorspace == V4L2_COLORSPACE_JPEG &&
+ ctrl->id != 2) {
+ struct v4l2_control cam_ctrl;
+
+ cam_ctrl.id = V4L2_CID_CAM_CAPTURE;
+ ret = subdev_call(ctrl, core, s_ctrl, &cam_ctrl);
+ if (ret < 0 && ret != -ENOIOCTLCMD) {
+ fimc_reset_capture(ctrl);
+ mutex_unlock(&ctrl->v4l2_lock);
+ fimc_err("%s: Error in V4L2_CID_CAM_CAPTURE\n", \
+ __func__);
+ return -EPERM;
+ }
+ }
+
+ ctrl->status = FIMC_STREAMON;
+
+ mutex_unlock(&ctrl->v4l2_lock);
+
+ return 0;
+}
+
+int fimc_streamoff_capture(void *fh)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+
+ fimc_dbg("%s\n", __func__);
+
+ if (!ctrl->cap || !ctrl->cam || !ctrl->cam->sd) {
+ fimc_err("%s: No capture info.\n", __func__);
+ return -ENODEV;
+ }
+
+ mutex_lock(&ctrl->v4l2_lock);
+ fimc_reset_capture(ctrl);
+ mutex_unlock(&ctrl->v4l2_lock);
+
+ return 0;
+}
+
+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);
+
+ return 0;
+}
+
+int fimc_dqbuf_capture(void *fh, struct v4l2_buffer *b)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ struct fimc_capinfo *cap;
+ int pp, ret = 0;
+
+ 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;
+ }
+
+ cap = ctrl->cap;
+
+ mutex_lock(&ctrl->v4l2_lock);
+
+ if (ctrl->status != FIMC_STREAMON) {
+ mutex_unlock(&ctrl->v4l2_lock);
+ fimc_dbg("%s: FIMC is not active.\n", __func__);
+ return -EINVAL;
+ }
+
+ /* find out the real index */
+ pp = ((fimc_hwget_frame_count(ctrl) + 2) % 4);
+
+ /* We have read the latest frame, hence should reset availability
+ * flag
+ */
+ cap->irq = 0;
+
+ /* skip even frame: no data */
+ if (cap->fmt.field == V4L2_FIELD_INTERLACED_TB)
+ pp &= ~0x1;
+
+ 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__);
+ }
+
+ mutex_unlock(&ctrl->v4l2_lock);
+
+ /* fimc_dbg("%s: buf_index = %d\n", __func__, b->index); */
+
+ return ret;
+}
+
diff --git a/drivers/media/video/samsung/fimc/fimc_dev.c b/drivers/media/video/samsung/fimc/fimc_dev.c
new file mode 100644
index 0000000..aadae21
--- /dev/null
+++ b/drivers/media/video/samsung/fimc/fimc_dev.c
@@ -0,0 +1,1689 @@
+/* linux/drivers/media/video/samsung/fimc/fimc_dev.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Core file for Samsung Camera Interface (FIMC) 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/errno.h>
+#include <linux/clk.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/poll.h>
+#include <linux/wait.h>
+#include <linux/fs.h>
+#include <linux/irq.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <media/v4l2-device.h>
+#include <linux/io.h>
+#include <linux/memory.h>
+#include <linux/ctype.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <plat/clock.h>
+#include <plat/media.h>
+#include <mach/media.h>
+#include <plat/fimc.h>
+#include <linux/videodev2_samsung.h>
+#include <linux/delay.h>
+#include <plat/regs-fimc.h>
+
+#include "fimc.h"
+
+struct fimc_global *fimc_dev;
+
+int fimc_dma_alloc(struct fimc_control *ctrl, struct fimc_buf_set *bs,
+ int i, int align)
+{
+ dma_addr_t end, *curr;
+
+ mutex_lock(&ctrl->alloc_lock);
+
+ end = ctrl->mem.base + ctrl->mem.size;
+ curr = &ctrl->mem.curr;
+
+ if (!bs->length[i])
+ return -EINVAL;
+
+ if (!align) {
+ if (*curr + bs->length[i] > end) {
+ goto overflow;
+ } else {
+ bs->base[i] = *curr;
+ bs->garbage[i] = 0;
+ *curr += bs->length[i];
+ }
+ } else {
+ if (ALIGN(*curr, align) + bs->length[i] > end)
+ goto overflow;
+ else {
+ bs->base[i] = ALIGN(*curr, align);
+ bs->garbage[i] = ALIGN(*curr, align) - *curr;
+ *curr += (bs->length[i] + bs->garbage[i]);
+ }
+ }
+
+ mutex_unlock(&ctrl->alloc_lock);
+
+ return 0;
+
+overflow:
+ bs->base[i] = 0;
+ bs->length[i] = 0;
+ bs->garbage[i] = 0;
+
+ mutex_unlock(&ctrl->alloc_lock);
+
+ return -ENOMEM;
+}
+
+void fimc_dma_free(struct fimc_control *ctrl, struct fimc_buf_set *bs, int i)
+{
+ int total = bs->length[i] + bs->garbage[i];
+ mutex_lock(&ctrl->alloc_lock);
+
+ if (bs->base[i]) {
+ if (ctrl->mem.curr - total >= ctrl->mem.base)
+ ctrl->mem.curr -= total;
+
+ bs->base[i] = 0;
+ bs->length[i] = 0;
+ bs->garbage[i] = 0;
+ }
+
+ mutex_unlock(&ctrl->alloc_lock);
+}
+
+void fimc_clk_en(struct fimc_control *ctrl, bool on)
+{
+ struct platform_device *pdev;
+ struct s3c_platform_fimc *pdata;
+ struct clk *lclk;
+
+ pdev = to_platform_device(ctrl->dev);
+ pdata = to_fimc_plat(ctrl->dev);
+ lclk = clk_get(&pdev->dev, pdata->lclk_name);
+
+ if (on) {
+ if (!lclk->usage) {
+ if (!ctrl->out)
+ fimc_info1("(%d) Clock %s(%d) enabled.\n",
+ ctrl->id, ctrl->clk->name,
+ ctrl->clk->id);
+
+ /* Turn on fimc power domain regulator */
+ regulator_enable(ctrl->regulator);
+ clk_enable(lclk);
+ }
+ } else {
+ while (lclk->usage > 0) {
+ if (!ctrl->out)
+ fimc_info1("(%d) Clock %s(%d) disabled.\n",
+ ctrl->id, ctrl->clk->name,
+ ctrl->clk->id);
+ clk_disable(lclk);
+ /* Turn off fimc power domain regulator */
+ regulator_disable(ctrl->regulator);
+ }
+ }
+
+}
+
+static inline u32 fimc_irq_out_single_buf(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx)
+{
+ int ret = -1, ctx_num, next;
+ u32 wakeup = 1;
+
+ if (ctx->status == FIMC_READY_OFF) {
+ ctrl->out->idxs.active.ctx = -1;
+ ctrl->out->idxs.active.idx = -1;
+ ctx->status = FIMC_STREAMOFF;
+ ctrl->status = FIMC_STREAMOFF;
+
+ return wakeup;
+ }
+
+ ctx->status = FIMC_STREAMON_IDLE;
+
+ /* Attach done buffer to outgoing queue. */
+ ret = fimc_push_outq(ctrl, ctx, ctrl->out->idxs.active.idx);
+ if (ret < 0)
+ fimc_err("Failed: fimc_push_outq\n");
+
+ /* Detach buffer from incomming queue. */
+ ret = fimc_pop_inq(ctrl, &ctx_num, &next);
+ if (ret == 0) { /* There is a buffer in incomming queue. */
+ if (ctx_num != ctrl->out->last_ctx) {
+ ctx = &ctrl->out->ctx[ctx_num];
+ ctrl->out->last_ctx = ctx->ctx_num;
+ fimc_outdev_set_ctx_param(ctrl, ctx);
+ }
+
+ fimc_outdev_set_src_addr(ctrl, ctx->src[next].base);
+
+ fimc_output_set_dst_addr(ctrl, ctx, next);
+
+ ret = fimc_outdev_start_camif(ctrl);
+ if (ret < 0)
+ fimc_err("Fail: fimc_start_camif\n");
+
+ ctrl->out->idxs.active.ctx = ctx_num;
+ ctrl->out->idxs.active.idx = next;
+ ctx->status = FIMC_STREAMON;
+ ctrl->status = FIMC_STREAMON;
+ } else { /* There is no buffer in incomming queue. */
+ ctrl->out->idxs.active.ctx = -1;
+ ctrl->out->idxs.active.idx = -1;
+ ctx->status = FIMC_STREAMON_IDLE;
+ ctrl->status = FIMC_STREAMON_IDLE;
+ }
+
+ return wakeup;
+}
+
+static inline u32 fimc_irq_out_multi_buf(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx)
+{
+ int ret = -1, ctx_num, next;
+ u32 wakeup = 1;
+
+ if (ctx->status == FIMC_READY_OFF) {
+ if (ctrl->out->idxs.active.ctx == ctx->ctx_num) {
+ ctrl->out->idxs.active.ctx = -1;
+ ctrl->out->idxs.active.idx = -1;
+ }
+
+ ctx->status = FIMC_STREAMOFF;
+
+ return wakeup;
+ }
+
+ /* Attach done buffer to outgoing queue. */
+ ret = fimc_push_outq(ctrl, ctx, ctrl->out->idxs.active.idx);
+ if (ret < 0)
+ fimc_err("Failed: fimc_push_outq\n");
+
+ /* Detach buffer from incomming queue. */
+ ret = fimc_pop_inq(ctrl, &ctx_num, &next);
+ if (ret == 0) { /* There is a buffer in incomming queue. */
+ if (ctx_num != ctrl->out->last_ctx) {
+ ctx = &ctrl->out->ctx[ctx_num];
+ ctrl->out->last_ctx = ctx->ctx_num;
+ fimc_outdev_set_ctx_param(ctrl, ctx);
+ }
+
+ fimc_outdev_set_src_addr(ctrl, ctx->src[next].base);
+
+ fimc_output_set_dst_addr(ctrl, ctx, next);
+
+ ret = fimc_outdev_start_camif(ctrl);
+ if (ret < 0)
+ fimc_err("Fail: fimc_start_camif\n");
+
+ ctrl->out->idxs.active.ctx = ctx_num;
+ ctrl->out->idxs.active.idx = next;
+ ctx->status = FIMC_STREAMON;
+ ctrl->status = FIMC_STREAMON;
+ } else { /* There is no buffer in incomming queue. */
+ ctrl->out->idxs.active.ctx = -1;
+ ctrl->out->idxs.active.idx = -1;
+ ctx->status = FIMC_STREAMON_IDLE;
+ ctrl->status = FIMC_STREAMON_IDLE;
+ }
+
+ return wakeup;
+}
+
+static inline u32 fimc_irq_out_dma(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx)
+{
+ struct fimc_buf_set buf_set;
+ int idx = ctrl->out->idxs.active.idx;
+ int ret = -1, i, ctx_num, next;
+ u32 wakeup = 1;
+
+ if (ctx->status == FIMC_READY_OFF) {
+ ctrl->out->idxs.active.ctx = -1;
+ ctrl->out->idxs.active.idx = -1;
+ ctx->status = FIMC_STREAMOFF;
+ ctrl->status = FIMC_STREAMOFF;
+ return wakeup;
+ }
+
+ /* Attach done buffer to outgoing queue. */
+ ret = fimc_push_outq(ctrl, ctx, idx);
+ if (ret < 0)
+ fimc_err("Failed: fimc_push_outq\n");
+
+ if (ctx->overlay.mode == FIMC_OVLY_DMA_AUTO) {
+ struct s3cfb_window *win;
+ struct fb_info *fbinfo;
+
+ fbinfo = registered_fb[ctx->overlay.fb_id];
+ win = (struct s3cfb_window *)fbinfo->par;
+
+ win->other_mem_addr = ctx->dst[idx].base[FIMC_ADDR_Y];
+
+ ret = fb_pan_display(fbinfo, &fbinfo->var);
+ if (ret < 0) {
+ fimc_err("%s: fb_pan_display fail (ret=%d)\n",
+ __func__, ret);
+ return -EINVAL;
+ }
+ }
+
+ /* Detach buffer from incomming queue. */
+ ret = fimc_pop_inq(ctrl, &ctx_num, &next);
+ if (ret == 0) { /* There is a buffer in incomming queue. */
+ ctx = &ctrl->out->ctx[ctx_num];
+ fimc_outdev_set_src_addr(ctrl, ctx->src[next].base);
+
+ memset(&buf_set, 0x00, sizeof(buf_set));
+ buf_set.base[FIMC_ADDR_Y] = ctx->dst[next].base[FIMC_ADDR_Y];
+
+ for (i = 0; i < FIMC_PHYBUFS; i++)
+ fimc_hwset_output_address(ctrl, &buf_set, i);
+
+ ret = fimc_outdev_start_camif(ctrl);
+ if (ret < 0)
+ fimc_err("Fail: fimc_start_camif\n");
+
+ ctrl->out->idxs.active.ctx = ctx_num;
+ ctrl->out->idxs.active.idx = next;
+
+ ctx->status = FIMC_STREAMON;
+ ctrl->status = FIMC_STREAMON;
+ } else { /* There is no buffer in incomming queue. */
+ ctrl->out->idxs.active.ctx = -1;
+ ctrl->out->idxs.active.idx = -1;
+
+ ctx->status = FIMC_STREAMON_IDLE;
+ ctrl->status = FIMC_STREAMON_IDLE;
+ }
+
+ return wakeup;
+}
+
+static inline u32 fimc_irq_out_fimd(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx)
+{
+ struct fimc_idx prev;
+ int ret = -1, ctx_num, next;
+ u32 wakeup = 0;
+
+ /* Attach done buffer to outgoing queue. */
+ if (ctrl->out->idxs.prev.idx != -1) {
+ ret = fimc_push_outq(ctrl, ctx, ctrl->out->idxs.prev.idx);
+ if (ret < 0) {
+ fimc_err("Failed: fimc_push_outq\n");
+ } else {
+ ctrl->out->idxs.prev.ctx = -1;
+ ctrl->out->idxs.prev.idx = -1;
+ wakeup = 1; /* To wake up fimc_v4l2_dqbuf */
+ }
+ }
+
+ /* Update index structure. */
+ if (ctrl->out->idxs.next.idx != -1) {
+ ctrl->out->idxs.active.ctx = ctrl->out->idxs.next.ctx;
+ ctrl->out->idxs.active.idx = ctrl->out->idxs.next.idx;
+ ctrl->out->idxs.next.idx = -1;
+ ctrl->out->idxs.next.ctx = -1;
+ }
+
+ /* Detach buffer from incomming queue. */
+ ret = fimc_pop_inq(ctrl, &ctx_num, &next);
+ if (ret == 0) { /* There is a buffer in incomming queue. */
+ prev.ctx = ctrl->out->idxs.active.ctx;
+ prev.idx = ctrl->out->idxs.active.idx;
+
+ ctrl->out->idxs.prev.ctx = prev.ctx;
+ ctrl->out->idxs.prev.idx = prev.idx;
+
+ ctrl->out->idxs.next.ctx = ctx_num;
+ ctrl->out->idxs.next.idx = next;
+
+ /* set source address */
+ fimc_outdev_set_src_addr(ctrl, ctx->src[next].base);
+ }
+
+ return wakeup;
+}
+
+static inline void fimc_irq_out(struct fimc_control *ctrl)
+{
+ struct fimc_ctx *ctx;
+ u32 wakeup = 1;
+ int ctx_num = ctrl->out->idxs.active.ctx;
+
+ /* Interrupt pendding clear */
+ fimc_hwset_clear_irq(ctrl);
+
+ /* check context num */
+ if (ctx_num < 0 || ctx_num >= FIMC_MAX_CTXS) {
+ fimc_err("fimc_irq_out: invalid ctx (ctx=%d)\n", ctx_num);
+ wake_up(&ctrl->wq);
+ return;
+ }
+
+ ctx = &ctrl->out->ctx[ctx_num];
+
+ switch (ctx->overlay.mode) {
+ case FIMC_OVLY_NONE_SINGLE_BUF:
+ wakeup = fimc_irq_out_single_buf(ctrl, ctx);
+ break;
+ case FIMC_OVLY_NONE_MULTI_BUF:
+ wakeup = fimc_irq_out_multi_buf(ctrl, ctx);
+ break;
+ case FIMC_OVLY_DMA_AUTO: /* fall through */
+ case FIMC_OVLY_DMA_MANUAL:
+ wakeup = fimc_irq_out_dma(ctrl, ctx);
+ break;
+ default:
+ fimc_err("[ctx=%d] fimc_irq_out: wrong overlay.mode (%d)\n",
+ ctx_num, ctx->overlay.mode);
+ break;
+ }
+
+ if (wakeup == 1)
+ wake_up(&ctrl->wq);
+}
+
+static inline void fimc_irq_cap(struct fimc_control *ctrl)
+{
+ struct fimc_capinfo *cap = ctrl->cap;
+ int pp;
+ u32 cfg;
+
+ fimc_hwset_clear_irq(ctrl);
+ if (fimc_hwget_overflow_state(ctrl)) {
+ /* s/w reset -- added for recovering module in ESD state*/
+ cfg = readl(ctrl->regs + S3C_CIGCTRL);
+ cfg |= (S3C_CIGCTRL_SWRST);
+ writel(cfg, ctrl->regs + S3C_CIGCTRL);
+ msleep(1);
+
+ cfg = readl(ctrl->regs + S3C_CIGCTRL);
+ cfg &= ~S3C_CIGCTRL_SWRST;
+ writel(cfg, ctrl->regs + S3C_CIGCTRL);
+ }
+ pp = ((fimc_hwget_frame_count(ctrl) + 2) % 4);
+ if (cap->fmt.field == V4L2_FIELD_INTERLACED_TB) {
+ /* odd value of pp means one frame is made with top/bottom */
+ if (pp & 0x1) {
+ cap->irq = 1;
+ wake_up(&ctrl->wq);
+ }
+ } else {
+ cap->irq = 1;
+ wake_up(&ctrl->wq);
+ }
+}
+
+static irqreturn_t fimc_irq(int irq, void *dev_id)
+{
+ struct fimc_control *ctrl = (struct fimc_control *) dev_id;
+
+ if (ctrl->cap)
+ fimc_irq_cap(ctrl);
+ else if (ctrl->out)
+ fimc_irq_out(ctrl);
+
+ return IRQ_HANDLED;
+}
+
+static
+struct fimc_control *fimc_register_controller(struct platform_device *pdev)
+{
+ struct s3c_platform_fimc *pdata;
+ struct fimc_control *ctrl;
+ struct resource *res;
+ int id, mdev_id;
+
+ id = pdev->id;
+ mdev_id = S5P_MDEV_FIMC0 + id;
+ pdata = to_fimc_plat(&pdev->dev);
+
+ ctrl = get_fimc_ctrl(id);
+ ctrl->id = id;
+ ctrl->dev = &pdev->dev;
+ ctrl->vd = &fimc_video_device[id];
+ ctrl->vd->minor = id;
+
+ /* alloc from bank1 as default */
+ ctrl->mem.base = pdata->pmem_start;
+ ctrl->mem.size = pdata->pmem_size;
+ ctrl->mem.curr = ctrl->mem.base;
+
+ ctrl->status = FIMC_STREAMOFF;
+ switch (pdata->hw_ver) {
+ case 0x40:
+ ctrl->limit = &fimc40_limits[id];
+ break;
+ case 0x43:
+ case 0x45:
+ ctrl->limit = &fimc43_limits[id];
+ break;
+ case 0x50:
+ ctrl->limit = &fimc50_limits[id];
+ break;
+ }
+
+ ctrl->log = FIMC_LOG_DEFAULT;
+
+ sprintf(ctrl->name, "%s%d", FIMC_NAME, id);
+ strcpy(ctrl->vd->name, ctrl->name);
+
+ atomic_set(&ctrl->in_use, 0);
+ mutex_init(&ctrl->lock);
+ mutex_init(&ctrl->alloc_lock);
+ mutex_init(&ctrl->v4l2_lock);
+ init_waitqueue_head(&ctrl->wq);
+
+ /* get resource for io memory */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ fimc_err("%s: failed to get io memory region\n", __func__);
+ return NULL;
+ }
+
+ /* request mem region */
+ res = request_mem_region(res->start, res->end - res->start + 1,
+ pdev->name);
+ if (!res) {
+ fimc_err("%s: failed to request io memory region\n", __func__);
+ return NULL;
+ }
+
+ /* ioremap for register block */
+ ctrl->regs = ioremap(res->start, res->end - res->start + 1);
+ if (!ctrl->regs) {
+ fimc_err("%s: failed to remap io region\n", __func__);
+ return NULL;
+ }
+
+ /* irq */
+ ctrl->irq = platform_get_irq(pdev, 0);
+ if (request_irq(ctrl->irq, fimc_irq, IRQF_DISABLED, ctrl->name, ctrl))
+ fimc_err("%s: request_irq failed\n", __func__);
+
+ fimc_hwset_reset(ctrl);
+
+ return ctrl;
+}
+
+static int fimc_unregister_controller(struct platform_device *pdev)
+{
+ struct s3c_platform_fimc *pdata;
+ struct fimc_control *ctrl;
+ int id = pdev->id;
+
+ pdata = to_fimc_plat(&pdev->dev);
+ ctrl = get_fimc_ctrl(id);
+
+ free_irq(ctrl->irq, ctrl);
+ mutex_destroy(&ctrl->lock);
+ mutex_destroy(&ctrl->alloc_lock);
+ mutex_destroy(&ctrl->v4l2_lock);
+
+ fimc_clk_en(ctrl, false);
+
+ iounmap(ctrl->regs);
+ memset(ctrl, 0, sizeof(*ctrl));
+
+ return 0;
+}
+
+static void fimc_mmap_open(struct vm_area_struct *vma)
+{
+ struct fimc_global *dev = fimc_dev;
+ int pri_data = (int)vma->vm_private_data;
+ u32 id = pri_data / 0x100;
+ u32 ctx = (pri_data - (id * 0x100)) / 0x10;
+ u32 idx = pri_data % 0x10;
+
+ atomic_inc(&dev->ctrl[id].out->ctx[ctx].src[idx].mapped_cnt);
+}
+
+static void fimc_mmap_close(struct vm_area_struct *vma)
+{
+ struct fimc_global *dev = fimc_dev;
+ int pri_data = (int)vma->vm_private_data;
+ u32 id = pri_data / 0x100;
+ u32 ctx = (pri_data - (id * 0x100)) / 0x10;
+ u32 idx = pri_data % 0x10;
+
+ atomic_dec(&dev->ctrl[id].out->ctx[ctx].src[idx].mapped_cnt);
+}
+
+static struct vm_operations_struct fimc_mmap_ops = {
+ .open = fimc_mmap_open,
+ .close = fimc_mmap_close,
+};
+
+static inline
+int fimc_mmap_out_src(struct file *filp, struct vm_area_struct *vma)
+{
+ struct fimc_prv_data *prv_data =
+ (struct fimc_prv_data *)filp->private_data;
+ struct fimc_control *ctrl = prv_data->ctrl;
+ int ctx_id = prv_data->ctx_id;
+ struct fimc_ctx *ctx = &ctrl->out->ctx[ctx_id];
+ u32 start_phy_addr = 0;
+ u32 size = vma->vm_end - vma->vm_start;
+ u32 pfn, idx = vma->vm_pgoff;
+ u32 buf_length = 0;
+ int pri_data = 0;
+
+ buf_length = PAGE_ALIGN(ctx->src[idx].length[FIMC_ADDR_Y] +
+ ctx->src[idx].length[FIMC_ADDR_CB] +
+ ctx->src[idx].length[FIMC_ADDR_CR]);
+ if (size > PAGE_ALIGN(buf_length)) {
+ fimc_err("Requested mmap size is too big\n");
+ return -EINVAL;
+ }
+
+ pri_data = (ctrl->id * 0x100) + (ctx_id * 0x10) + idx;
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ vma->vm_flags |= VM_RESERVED;
+ vma->vm_ops = &fimc_mmap_ops;
+ vma->vm_private_data = (void *)pri_data;
+
+ if ((vma->vm_flags & VM_WRITE) && !(vma->vm_flags & VM_SHARED)) {
+ fimc_err("writable mapping must be shared\n");
+ return -EINVAL;
+ }
+
+ start_phy_addr = ctx->src[idx].base[FIMC_ADDR_Y];
+ pfn = __phys_to_pfn(start_phy_addr);
+
+ if (remap_pfn_range(vma, vma->vm_start, pfn, size, vma->vm_page_prot)) {
+ fimc_err("mmap fail\n");
+ return -EINVAL;
+ }
+
+ vma->vm_ops->open(vma);
+
+ ctx->src[idx].flags |= V4L2_BUF_FLAG_MAPPED;
+
+ return 0;
+}
+
+static inline
+int fimc_mmap_out_dst(struct file *filp, struct vm_area_struct *vma, u32 idx)
+{
+ struct fimc_prv_data *prv_data =
+ (struct fimc_prv_data *)filp->private_data;
+ struct fimc_control *ctrl = prv_data->ctrl;
+ int ctx_id = prv_data->ctx_id;
+ unsigned long pfn = 0, size;
+ int ret = 0;
+
+ size = vma->vm_end - vma->vm_start;
+
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ vma->vm_flags |= VM_RESERVED;
+
+ pfn = __phys_to_pfn(ctrl->out->ctx[ctx_id].dst[idx].base[0]);
+ ret = remap_pfn_range(vma, vma->vm_start, pfn, size, vma->vm_page_prot);
+ if (ret != 0)
+ fimc_err("remap_pfn_range fail.\n");
+
+ return ret;
+}
+
+static inline int fimc_mmap_out(struct file *filp, struct vm_area_struct *vma)
+{
+ struct fimc_prv_data *prv_data =
+ (struct fimc_prv_data *)filp->private_data;
+ struct fimc_control *ctrl = prv_data->ctrl;
+ int ctx_id = prv_data->ctx_id;
+ int idx = ctrl->out->ctx[ctx_id].overlay.req_idx;
+ int ret = -1;
+
+ if (idx >= 0)
+ ret = fimc_mmap_out_dst(filp, vma, idx);
+ else if (idx == FIMC_MMAP_IDX)
+ ret = fimc_mmap_out_src(filp, vma);
+
+ return ret;
+}
+
+static inline int fimc_mmap_cap(struct file *filp, struct vm_area_struct *vma)
+{
+ struct fimc_prv_data *prv_data =
+ (struct fimc_prv_data *)filp->private_data;
+ struct fimc_control *ctrl = prv_data->ctrl;
+ u32 size = vma->vm_end - vma->vm_start;
+ u32 pfn, idx = vma->vm_pgoff;
+
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ vma->vm_flags |= VM_RESERVED;
+
+ /*
+ * page frame number of the address for a source frame
+ * to be stored at.
+ */
+ pfn = __phys_to_pfn(ctrl->cap->bufs[idx].base[0]);
+
+ if ((vma->vm_flags & VM_WRITE) && !(vma->vm_flags & VM_SHARED)) {
+ fimc_err("%s: writable mapping must be shared\n", __func__);
+ return -EINVAL;
+ }
+
+ if (remap_pfn_range(vma, vma->vm_start, pfn, size, vma->vm_page_prot)) {
+ fimc_err("%s: mmap fail\n", __func__);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int fimc_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+ struct fimc_prv_data *prv_data =
+ (struct fimc_prv_data *)filp->private_data;
+ struct fimc_control *ctrl = prv_data->ctrl;
+ int ret;
+
+ if (ctrl->cap)
+ ret = fimc_mmap_cap(filp, vma);
+ else
+ ret = fimc_mmap_out(filp, vma);
+
+ return ret;
+}
+
+static u32 fimc_poll(struct file *filp, poll_table *wait)
+{
+ struct fimc_prv_data *prv_data =
+ (struct fimc_prv_data *)filp->private_data;
+ struct fimc_control *ctrl = prv_data->ctrl;
+ struct fimc_capinfo *cap = ctrl->cap;
+ u32 mask = 0;
+
+ if (cap) {
+ if (cap->irq || (ctrl->status != FIMC_STREAMON)) {
+ mask = POLLIN | POLLRDNORM;
+ cap->irq = 0;
+ } else {
+ poll_wait(filp, &ctrl->wq, wait);
+ }
+ }
+
+ return mask;
+}
+
+static
+ssize_t fimc_read(struct file *filp, char *buf, size_t count, loff_t *pos)
+{
+ return 0;
+}
+
+static
+ssize_t fimc_write(struct file *filp, const char *b, size_t c, loff_t *offset)
+{
+ return 0;
+}
+
+u32 fimc_mapping_rot_flip(u32 rot, u32 flip)
+{
+ u32 ret = 0;
+
+ switch (rot) {
+ case 0:
+ if (flip & FIMC_XFLIP)
+ ret |= FIMC_XFLIP;
+
+ if (flip & FIMC_YFLIP)
+ ret |= FIMC_YFLIP;
+ break;
+
+ case 90:
+ ret = FIMC_ROT;
+ if (flip & FIMC_XFLIP)
+ ret |= FIMC_XFLIP;
+
+ if (flip & FIMC_YFLIP)
+ ret |= FIMC_YFLIP;
+ break;
+
+ case 180:
+ ret = (FIMC_XFLIP | FIMC_YFLIP);
+ if (flip & FIMC_XFLIP)
+ ret &= ~FIMC_XFLIP;
+
+ if (flip & FIMC_YFLIP)
+ ret &= ~FIMC_YFLIP;
+ break;
+
+ case 270:
+ ret = (FIMC_XFLIP | FIMC_YFLIP | FIMC_ROT);
+ if (flip & FIMC_XFLIP)
+ ret &= ~FIMC_XFLIP;
+
+ if (flip & FIMC_YFLIP)
+ ret &= ~FIMC_YFLIP;
+ break;
+ }
+
+ return ret;
+}
+
+int fimc_get_scaler_factor(u32 src, u32 tar, u32 *ratio, u32 *shift)
+{
+ if (src >= tar * 64) {
+ return -EINVAL;
+ } else if (src >= tar * 32) {
+ *ratio = 32;
+ *shift = 5;
+ } else if (src >= tar * 16) {
+ *ratio = 16;
+ *shift = 4;
+ } else if (src >= tar * 8) {
+ *ratio = 8;
+ *shift = 3;
+ } else if (src >= tar * 4) {
+ *ratio = 4;
+ *shift = 2;
+ } else if (src >= tar * 2) {
+ *ratio = 2;
+ *shift = 1;
+ } else {
+ *ratio = 1;
+ *shift = 0;
+ }
+
+ return 0;
+}
+
+void fimc_get_nv12t_size(int img_hres, int img_vres,
+ int *y_size, int *cb_size, int rotate)
+{
+ int remain;
+ int y_hres_byte, y_vres_byte;
+ int cb_hres_byte, cb_vres_byte;
+ 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) {
+ remain = 16 - remain;
+ img_hres = img_hres + remain;
+ }
+ remain = img_vres % 16;
+ if (remain != 0) {
+ remain = 16 - remain;
+ img_vres = img_vres + remain;
+ }
+
+ cb_hres_byte = img_hres;
+ cb_vres_byte = img_vres;
+
+ y_hres_byte = img_hres - 1;
+ y_vres_byte = img_vres - 1;
+ y_hres_roundup = ((y_hres_byte >> 4) >> 3) + 1;
+ y_vres_roundup = ((y_vres_byte >> 4) >> 2) + 1;
+ if ((y_vres_byte & 0x20) == 0) {
+ y_hres_byte = y_hres_byte & 0x7f00;
+ y_hres_byte = y_hres_byte >> 8;
+ y_hres_byte = y_hres_byte & 0x7f;
+
+ y_vres_byte = y_vres_byte & 0x7fc0;
+ y_vres_byte = y_vres_byte >> 6;
+ y_vres_byte = y_vres_byte & 0x1ff;
+
+ *y_size = y_hres_byte +\
+ (y_vres_byte * y_hres_roundup) + 1;
+ } else {
+ *y_size = y_hres_roundup * y_vres_roundup;
+ }
+
+ *y_size = *(y_size) << 13;
+
+ cb_hres_byte = img_hres - 1;
+ cb_vres_byte = (img_vres >> 1) - 1;
+ cb_hres_roundup = ((cb_hres_byte >> 4) >> 3) + 1;
+ cb_vres_roundup = ((cb_vres_byte >> 4) >> 2) + 1;
+ if ((cb_vres_byte & 0x20) == 0) {
+ cb_hres_byte = cb_hres_byte & 0x7f00;
+ cb_hres_byte = cb_hres_byte >> 8;
+ cb_hres_byte = cb_hres_byte & 0x7f;
+
+ cb_vres_byte = cb_vres_byte & 0x7fc0;
+ cb_vres_byte = cb_vres_byte >> 6;
+ cb_vres_byte = cb_vres_byte & 0x1ff;
+
+ *cb_size = cb_hres_byte + (cb_vres_byte * cb_hres_roundup) + 1;
+ } else {
+ *cb_size = cb_hres_roundup * cb_vres_roundup;
+ }
+ *cb_size = (*cb_size) << 13;
+
+}
+
+static int fimc_get_free_ctx(struct fimc_control *ctrl)
+{
+ int i;
+
+ if (1 != ctrl->id)
+ return 0;
+
+ for (i = 0; i < FIMC_MAX_CTXS; i++) {
+ if (ctrl->ctx_busy[i] == 0) {
+ ctrl->ctx_busy[i] = 1;
+ fimc_info1("Current context is %d\n", i);
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+static int fimc_open(struct file *filp)
+{
+ struct fimc_control *ctrl;
+ struct s3c_platform_fimc *pdata;
+ struct fimc_prv_data *prv_data;
+ int in_use;
+ int ret;
+
+ ctrl = video_get_drvdata(video_devdata(filp));
+ pdata = to_fimc_plat(ctrl->dev);
+
+ mutex_lock(&ctrl->lock);
+
+ in_use = atomic_read(&ctrl->in_use);
+ if (in_use >= FIMC_MAX_CTXS || (in_use && 1 != ctrl->id)) {
+ fimc_err("%s: Device busy.\n", __func__);
+ ret = -EBUSY;
+ goto resource_busy;
+ } else {
+ atomic_inc(&ctrl->in_use);
+ }
+ in_use = atomic_read(&ctrl->in_use);
+
+ prv_data = kzalloc(sizeof(struct fimc_prv_data), GFP_KERNEL);
+ if (!prv_data) {
+ fimc_err("%s: not enough memory\n", __func__);
+ ret = -ENOMEM;
+ goto kzalloc_err;
+ }
+
+ prv_data->ctx_id = fimc_get_free_ctx(ctrl);
+ if (prv_data->ctx_id < 0) {
+ fimc_err("%s: Context busy flag not reset.\n", __func__);
+ ret = -EBUSY;
+ goto ctx_err;
+ }
+ prv_data->ctrl = ctrl;
+ filp->private_data = prv_data;
+
+ if (in_use == 1) {
+ fimc_clk_en(ctrl, true);
+
+ if (pdata->hw_ver == 0x40)
+ fimc_hw_reset_camera(ctrl);
+
+ /* Apply things to interface register */
+ fimc_hwset_reset(ctrl);
+
+ if (num_registered_fb > 0) {
+ struct fb_info *fbinfo = registered_fb[0];
+ ctrl->fb.lcd_hres = (int)fbinfo->var.xres;
+ ctrl->fb.lcd_vres = (int)fbinfo->var.yres;
+ fimc_info1("%s: fd.lcd_hres=%d fd.lcd_vres=%d\n",
+ __func__, ctrl->fb.lcd_hres,
+ ctrl->fb.lcd_vres);
+ }
+
+ ctrl->mem.curr = ctrl->mem.base;
+ ctrl->status = FIMC_STREAMOFF;
+
+ if (0 != ctrl->id)
+ fimc_clk_en(ctrl, false);
+ }
+
+ mutex_unlock(&ctrl->lock);
+
+ fimc_info1("%s opened.\n", ctrl->name);
+
+ return 0;
+
+ctx_err:
+ kfree(prv_data);
+
+kzalloc_err:
+ atomic_dec(&ctrl->in_use);
+
+resource_busy:
+ mutex_unlock(&ctrl->lock);
+ return ret;
+}
+
+static int fimc_release(struct file *filp)
+{
+ struct fimc_prv_data *prv_data =
+ (struct fimc_prv_data *)filp->private_data;
+ struct fimc_control *ctrl = prv_data->ctrl;
+ int ctx_id = prv_data->ctx_id;
+ struct s3c_platform_fimc *pdata;
+ struct fimc_overlay_buf *buf;
+ struct mm_struct *mm = current->mm;
+ struct fimc_ctx *ctx;
+ int ret = 0, i;
+ ctx = &ctrl->out->ctx[ctx_id];
+
+ pdata = to_fimc_plat(ctrl->dev);
+
+ mutex_lock(&ctrl->lock);
+ atomic_dec(&ctrl->in_use);
+
+ /* FIXME: turning off actual working camera */
+ if (ctrl->cam && ctrl->id != 2) {
+ /* Unload the subdev (camera sensor) module,
+ * reset related status flags
+ */
+ fimc_release_subdev(ctrl);
+ }
+
+ if (ctrl->cap) {
+ ctrl->mem.curr = ctrl->mem.base;
+ kfree(filp->private_data);
+ filp->private_data = NULL;
+
+ for (i = 0; i < FIMC_CAPBUFS; i++) {
+ fimc_dma_free(ctrl, &ctrl->cap->bufs[i], 0);
+ fimc_dma_free(ctrl, &ctrl->cap->bufs[i], 1);
+ fimc_dma_free(ctrl, &ctrl->cap->bufs[i], 2);
+ }
+
+ fimc_clk_en(ctrl, false);
+
+ kfree(ctrl->cap);
+ ctrl->cap = NULL;
+ }
+
+ if (ctrl->out) {
+ if (ctx->status != FIMC_STREAMOFF) {
+ fimc_clk_en(ctrl, true);
+ ret = fimc_outdev_stop_streaming(ctrl, ctx);
+ fimc_clk_en(ctrl, false);
+ if (ret < 0)
+ fimc_err("Fail: fimc_stop_streaming\n");
+
+ ret = fimc_init_in_queue(ctrl, ctx);
+ if (ret < 0) {
+ fimc_err("Fail: fimc_init_in_queue\n");
+ ret = -EINVAL;
+ goto release_err;
+ }
+
+ ret = fimc_init_out_queue(ctrl, ctx);
+ if (ret < 0) {
+ fimc_err("Fail: fimc_init_out_queue\n");
+ ret = -EINVAL;
+ goto release_err;
+ }
+
+ /* Make all buffers DQUEUED state. */
+ for (i = 0; i < FIMC_OUTBUFS; i++) {
+ ctx->src[i].state = VIDEOBUF_IDLE;
+ ctx->src[i].flags = V4L2_BUF_FLAG_MAPPED;
+ }
+
+ if (ctx->overlay.mode == FIMC_OVLY_DMA_AUTO) {
+ ctrl->mem.curr = ctx->dst[0].base[FIMC_ADDR_Y];
+
+ for (i = 0; i < FIMC_OUTBUFS; i++) {
+ ctx->dst[i].base[FIMC_ADDR_Y] = 0;
+ ctx->dst[i].length[FIMC_ADDR_Y] = 0;
+
+ ctx->dst[i].base[FIMC_ADDR_CB] = 0;
+ ctx->dst[i].length[FIMC_ADDR_CB] = 0;
+
+ ctx->dst[i].base[FIMC_ADDR_CR] = 0;
+ ctx->dst[i].length[FIMC_ADDR_CR] = 0;
+ }
+ }
+
+ ctx->status = FIMC_STREAMOFF;
+ }
+
+ buf = &ctx->overlay.buf;
+ for (i = 0; i < FIMC_OUTBUFS; i++) {
+ if (buf->vir_addr[i]) {
+ ret = do_munmap(mm, buf->vir_addr[i],
+ buf->size[i]);
+ if (ret < 0)
+ fimc_err("%s: do_munmap fail\n", \
+ __func__);
+ }
+ }
+
+ ctrl->ctx_busy[ctx_id] = 0;
+ memset(ctx, 0x00, sizeof(struct fimc_ctx));
+
+ if (atomic_read(&ctrl->in_use) == 0) {
+ ctrl->status = FIMC_STREAMOFF;
+ fimc_outdev_init_idxs(ctrl);
+
+ fimc_clk_en(ctrl, false);
+
+ ctrl->mem.curr = ctrl->mem.base;
+
+ kfree(ctrl->out);
+ ctrl->out = NULL;
+
+ kfree(filp->private_data);
+ filp->private_data = NULL;
+ }
+ }
+
+ /*
+ * it remain afterimage when I play movie using overlay and exit
+ */
+ if (ctrl->fb.is_enable == 1) {
+ fimc_info2("WIN_OFF for FIMC%d\n", ctrl->id);
+ ret = fb_blank(registered_fb[ctx->overlay.fb_id],
+ FB_BLANK_POWERDOWN);
+ if (ret < 0) {
+ fimc_err("%s: fb_blank: fb[%d] " \
+ "mode=FB_BLANK_POWERDOWN\n",
+ __func__, ctx->overlay.fb_id);
+ ret = -EINVAL;
+ goto release_err;
+ }
+
+ ctrl->fb.is_enable = 0;
+ }
+
+ mutex_unlock(&ctrl->lock);
+
+ fimc_info1("%s released.\n", ctrl->name);
+
+ return 0;
+
+release_err:
+ mutex_unlock(&ctrl->lock);
+ return ret;
+
+}
+
+static const struct v4l2_file_operations fimc_fops = {
+ .owner = THIS_MODULE,
+ .open = fimc_open,
+ .release = fimc_release,
+ .ioctl = video_ioctl2,
+ .read = fimc_read,
+ .write = fimc_write,
+ .mmap = fimc_mmap,
+ .poll = fimc_poll,
+};
+
+static void fimc_vdev_release(struct video_device *vdev)
+{
+ kfree(vdev);
+}
+
+struct video_device fimc_video_device[FIMC_DEVICES] = {
+ [0] = {
+ .fops = &fimc_fops,
+ .ioctl_ops = &fimc_v4l2_ops,
+ .release = fimc_vdev_release,
+ },
+ [1] = {
+ .fops = &fimc_fops,
+ .ioctl_ops = &fimc_v4l2_ops,
+ .release = fimc_vdev_release,
+ },
+ [2] = {
+ .fops = &fimc_fops,
+ .ioctl_ops = &fimc_v4l2_ops,
+ .release = fimc_vdev_release,
+ },
+};
+
+static int fimc_init_global(struct platform_device *pdev)
+{
+ struct s3c_platform_fimc *pdata;
+ struct s3c_platform_camera *cam;
+ int i;
+
+ pdata = to_fimc_plat(&pdev->dev);
+
+ /* Registering external camera modules. re-arrange order to be sure */
+ for (i = 0; i < FIMC_MAXCAMS; i++) {
+ cam = pdata->camera[i];
+ if (!cam)
+ break;
+
+ cam->srclk = clk_get(&pdev->dev, cam->srclk_name);
+ if (IS_ERR(cam->srclk)) {
+ dev_err(&pdev->dev, "%s: failed to get mclk source\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ /* mclk */
+ cam->clk = clk_get(&pdev->dev, cam->clk_name);
+ if (IS_ERR(cam->clk)) {
+ dev_err(&pdev->dev, "%s: failed to get mclk source\n",
+ __func__);
+ clk_put(cam->srclk);
+ return -EINVAL;
+ }
+
+ clk_put(cam->clk);
+ clk_put(cam->srclk);
+
+ /* Assign camera device to fimc */
+ memcpy(&fimc_dev->camera[i], cam, sizeof(*cam));
+ fimc_dev->camera_isvalid[i] = 1;
+ fimc_dev->camera[i].initialized = 0;
+ }
+
+ fimc_dev->active_camera = -1;
+ fimc_dev->initialized = 1;
+
+ return 0;
+}
+
+static int fimc_show_log_level(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fimc_control *ctrl;
+ struct platform_device *pdev;
+ int id = -1;
+
+ char temp[150];
+
+ pdev = to_platform_device(dev);
+ id = pdev->id;
+ ctrl = get_fimc_ctrl(id);
+
+ sprintf(temp, "\t");
+ strcat(buf, temp);
+ if (ctrl->log & FIMC_LOG_DEBUG) {
+ sprintf(temp, "FIMC_LOG_DEBUG | ");
+ strcat(buf, temp);
+ }
+
+ if (ctrl->log & FIMC_LOG_INFO_L2) {
+ sprintf(temp, "FIMC_LOG_INFO_L2 | ");
+ strcat(buf, temp);
+ }
+
+ if (ctrl->log & FIMC_LOG_INFO_L1) {
+ sprintf(temp, "FIMC_LOG_INFO_L1 | ");
+ strcat(buf, temp);
+ }
+
+ if (ctrl->log & FIMC_LOG_WARN) {
+ sprintf(temp, "FIMC_LOG_WARN | ");
+ strcat(buf, temp);
+ }
+
+ if (ctrl->log & FIMC_LOG_ERR) {
+ sprintf(temp, "FIMC_LOG_ERR\n");
+ strcat(buf, temp);
+ }
+
+ return strlen(buf);
+}
+
+static int fimc_store_log_level(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t len)
+{
+ struct fimc_control *ctrl;
+ struct platform_device *pdev;
+
+ const char *p = buf;
+ char msg[150] = {0, };
+ int id = -1;
+ u32 match = 0;
+
+ pdev = to_platform_device(dev);
+ id = pdev->id;
+ ctrl = get_fimc_ctrl(id);
+
+ while (*p != '\0') {
+ if (!isspace(*p))
+ strncat(msg, p, 1);
+ p++;
+ }
+
+ ctrl->log = 0;
+ printk(KERN_INFO "FIMC.%d log level is set as below.\n", id);
+
+ if (strstr(msg, "FIMC_LOG_ERR") != NULL) {
+ ctrl->log |= FIMC_LOG_ERR;
+ match = 1;
+ printk(KERN_INFO "\tFIMC_LOG_ERR\n");
+ }
+
+ if (strstr(msg, "FIMC_LOG_WARN") != NULL) {
+ ctrl->log |= FIMC_LOG_WARN;
+ match = 1;
+ printk(KERN_INFO "\tFIMC_LOG_WARN\n");
+ }
+
+ if (strstr(msg, "FIMC_LOG_INFO_L1") != NULL) {
+ ctrl->log |= FIMC_LOG_INFO_L1;
+ match = 1;
+ printk(KERN_INFO "\tFIMC_LOG_INFO_L1\n");
+ }
+
+ if (strstr(msg, "FIMC_LOG_INFO_L2") != NULL) {
+ ctrl->log |= FIMC_LOG_INFO_L2;
+ match = 1;
+ printk(KERN_INFO "\tFIMC_LOG_INFO_L2\n");
+ }
+
+ if (strstr(msg, "FIMC_LOG_DEBUG") != NULL) {
+ ctrl->log |= FIMC_LOG_DEBUG;
+ match = 1;
+ printk(KERN_INFO "\tFIMC_LOG_DEBUG\n");
+ }
+
+ if (!match) {
+ printk(KERN_INFO "FIMC_LOG_ERR \t: Error condition.\n");
+ printk(KERN_INFO "FIMC_LOG_WARN \t: WARNING condition.\n");
+ printk(KERN_INFO "FIMC_LOG_INFO_L1 \t: V4L2 API without QBUF, DQBUF.\n");
+ printk(KERN_INFO "FIMC_LOG_INFO_L2 \t: V4L2 API QBUF, DQBUF.\n");
+ printk(KERN_INFO "FIMC_LOG_DEBUG \t: Queue status report.\n");
+ }
+
+ return len;
+}
+
+static DEVICE_ATTR(log_level, 0644, \
+ fimc_show_log_level,
+ fimc_store_log_level);
+
+static int __devinit fimc_probe(struct platform_device *pdev)
+{
+ struct s3c_platform_fimc *pdata;
+ struct fimc_control *ctrl;
+ struct clk *srclk;
+ int ret;
+
+ if (!fimc_dev) {
+ fimc_dev = kzalloc(sizeof(*fimc_dev), GFP_KERNEL);
+ if (!fimc_dev) {
+ dev_err(&pdev->dev, "%s: not enough memory\n",
+ __func__);
+ return -ENOMEM;
+ }
+ }
+
+ ctrl = fimc_register_controller(pdev);
+ if (!ctrl) {
+ printk(KERN_ERR "%s: cannot register fimc\n", __func__);
+ goto err_alloc;
+ }
+
+ pdata = to_fimc_plat(&pdev->dev);
+ if (pdata->cfg_gpio)
+ pdata->cfg_gpio(pdev);
+
+ /* Get fimc power domain regulator */
+ ctrl->regulator = regulator_get(&pdev->dev, "pd");
+ if (IS_ERR(ctrl->regulator)) {
+ fimc_err("%s: failed to get resource %s\n",
+ __func__, "s3c-fimc");
+ return PTR_ERR(ctrl->regulator);
+ }
+
+ /* fimc source clock */
+ srclk = clk_get(&pdev->dev, pdata->srclk_name);
+ if (IS_ERR(srclk)) {
+ fimc_err("%s: failed to get source clock of fimc\n",
+ __func__);
+ goto err_v4l2;
+ }
+
+ /* fimc clock */
+ ctrl->clk = clk_get(&pdev->dev, pdata->clk_name);
+ if (IS_ERR(ctrl->clk)) {
+ fimc_err("%s: failed to get fimc clock source\n",
+ __func__);
+ goto err_v4l2;
+ }
+
+ /* set parent for mclk */
+ clk_set_parent(ctrl->clk, srclk);
+
+ /* set rate for mclk */
+ clk_set_rate(ctrl->clk, pdata->clk_rate);
+
+ /* V4L2 device-subdev registration */
+ ret = v4l2_device_register(&pdev->dev, &ctrl->v4l2_dev);
+ if (ret) {
+ fimc_err("%s: v4l2 device register failed\n", __func__);
+ goto err_fimc;
+ }
+
+ /* things to initialize once */
+ if (!fimc_dev->initialized) {
+ ret = fimc_init_global(pdev);
+ if (ret)
+ goto err_v4l2;
+ }
+
+ /* video device register */
+ ret = video_register_device(ctrl->vd, VFL_TYPE_GRABBER, ctrl->id);
+ if (ret) {
+ fimc_err("%s: cannot register video driver\n", __func__);
+ goto err_v4l2;
+ }
+
+ video_set_drvdata(ctrl->vd, ctrl);
+
+ ret = device_create_file(&(pdev->dev), &dev_attr_log_level);
+ if (ret < 0) {
+ fimc_err("failed to add sysfs entries\n");
+ goto err_global;
+ }
+ printk(KERN_INFO "FIMC%d registered successfully\n", ctrl->id);
+
+ return 0;
+
+err_global:
+ video_unregister_device(ctrl->vd);
+
+err_v4l2:
+ v4l2_device_unregister(&ctrl->v4l2_dev);
+
+err_fimc:
+ fimc_unregister_controller(pdev);
+
+err_alloc:
+ kfree(fimc_dev);
+ return -EINVAL;
+
+}
+
+static int fimc_remove(struct platform_device *pdev)
+{
+ fimc_unregister_controller(pdev);
+
+ device_remove_file(&(pdev->dev), &dev_attr_log_level);
+
+ kfree(fimc_dev);
+ fimc_dev = NULL;
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static inline void fimc_suspend_out_ctx(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx)
+{
+ switch (ctx->overlay.mode) {
+ case FIMC_OVLY_DMA_AUTO: /* fall through */
+ case FIMC_OVLY_DMA_MANUAL: /* fall through */
+ case FIMC_OVLY_NONE_MULTI_BUF: /* fall through */
+ case FIMC_OVLY_NONE_SINGLE_BUF:
+ if (ctx->status == FIMC_STREAMON) {
+ if (ctx->inq[0] != -1)
+ fimc_err("%s : %d in queue unstable\n",
+ __func__, __LINE__);
+
+ fimc_outdev_stop_streaming(ctrl, ctx);
+ ctx->status = FIMC_ON_SLEEP;
+ } else if (ctx->status == FIMC_STREAMON_IDLE) {
+ fimc_outdev_stop_streaming(ctrl, ctx);
+ ctx->status = FIMC_ON_IDLE_SLEEP;
+ } else {
+ ctx->status = FIMC_OFF_SLEEP;
+ }
+
+ break;
+ case FIMC_OVLY_NOT_FIXED:
+ ctx->status = FIMC_OFF_SLEEP;
+ break;
+ }
+}
+
+static inline int fimc_suspend_out(struct fimc_control *ctrl)
+{
+ struct fimc_ctx *ctx;
+ int i, on_sleep = 0, idle_sleep = 0, off_sleep = 0;
+
+ for (i = 0; i < FIMC_MAX_CTXS; i++) {
+ ctx = &ctrl->out->ctx[i];
+ fimc_suspend_out_ctx(ctrl, ctx);
+
+ switch (ctx->status) {
+ case FIMC_ON_SLEEP:
+ on_sleep++;
+ break;
+ case FIMC_ON_IDLE_SLEEP:
+ idle_sleep++;
+ break;
+ case FIMC_OFF_SLEEP:
+ off_sleep++;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (on_sleep)
+ ctrl->status = FIMC_ON_SLEEP;
+ else if (idle_sleep)
+ ctrl->status = FIMC_ON_IDLE_SLEEP;
+ else
+ ctrl->status = FIMC_OFF_SLEEP;
+
+ ctrl->out->last_ctx = -1;
+
+ return 0;
+}
+
+static inline int fimc_suspend_cap(struct fimc_control *ctrl)
+{
+ if (ctrl->cam->id == CAMERA_WB && ctrl->status == FIMC_STREAMON)
+ fimc_streamoff_capture((void *)ctrl);
+ ctrl->status = FIMC_ON_SLEEP;
+
+ return 0;
+}
+
+int fimc_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct fimc_control *ctrl;
+ struct s3c_platform_fimc *pdata;
+ int id;
+
+ id = pdev->id;
+ ctrl = get_fimc_ctrl(id);
+ pdata = to_fimc_plat(ctrl->dev);
+
+ if (ctrl->out)
+ fimc_suspend_out(ctrl);
+ else if (ctrl->cap)
+ fimc_suspend_cap(ctrl);
+ else
+ ctrl->status = FIMC_OFF_SLEEP;
+
+ if (atomic_read(&ctrl->in_use) && ctrl->status != FIMC_OFF_SLEEP)
+ fimc_clk_en(ctrl, false);
+
+ return 0;
+}
+
+static inline void fimc_resume_out_ctx(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx)
+{
+ int ret = -1;
+
+ switch (ctx->overlay.mode) {
+ case FIMC_OVLY_DMA_AUTO:
+ if (ctx->status == FIMC_ON_IDLE_SLEEP) {
+ fimc_outdev_resume_dma(ctrl, ctx);
+ ret = fimc_outdev_set_ctx_param(ctrl, ctx);
+ if (ret < 0)
+ fimc_err("Fail: fimc_outdev_set_ctx_param\n");
+
+ ctx->status = FIMC_STREAMON_IDLE;
+ } else if (ctx->status == FIMC_OFF_SLEEP) {
+ ctx->status = FIMC_STREAMOFF;
+ } else {
+ fimc_err("%s: Abnormal (%d)\n", __func__, ctx->status);
+ }
+
+ break;
+ case FIMC_OVLY_DMA_MANUAL:
+ if (ctx->status == FIMC_ON_IDLE_SLEEP) {
+ ret = fimc_outdev_set_ctx_param(ctrl, ctx);
+ if (ret < 0)
+ fimc_err("Fail: fimc_outdev_set_ctx_param\n");
+
+ ctx->status = FIMC_STREAMON_IDLE;
+
+ } else if (ctx->status == FIMC_OFF_SLEEP) {
+ ctx->status = FIMC_STREAMOFF;
+ } else {
+ fimc_err("%s: Abnormal (%d)\n", __func__, ctx->status);
+ }
+
+ break;
+ case FIMC_OVLY_NONE_SINGLE_BUF: /* fall through */
+ case FIMC_OVLY_NONE_MULTI_BUF:
+ if (ctx->status == FIMC_ON_IDLE_SLEEP) {
+ ret = fimc_outdev_set_ctx_param(ctrl, ctx);
+ if (ret < 0)
+ fimc_err("Fail: fimc_outdev_set_ctx_param\n");
+
+ ctx->status = FIMC_STREAMON_IDLE;
+ } else if (ctx->status == FIMC_OFF_SLEEP) {
+ ctx->status = FIMC_STREAMOFF;
+ } else {
+ fimc_err("%s: Abnormal (%d)\n", __func__, ctx->status);
+ }
+
+ break;
+ default:
+ ctx->status = FIMC_STREAMOFF;
+ break;
+ }
+}
+
+static inline int fimc_resume_out(struct fimc_control *ctrl)
+{
+ struct fimc_ctx *ctx;
+ int i;
+ u32 state = 0;
+
+ for (i = 0; i < FIMC_MAX_CTXS; i++) {
+ ctx = &ctrl->out->ctx[i];
+ fimc_resume_out_ctx(ctrl, ctx);
+
+ switch (ctx->status) {
+ case FIMC_STREAMON:
+ state |= FIMC_STREAMON;
+ break;
+ case FIMC_STREAMON_IDLE:
+ state |= FIMC_STREAMON_IDLE;
+ break;
+ case FIMC_STREAMOFF:
+ state |= FIMC_STREAMOFF;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if ((state & FIMC_STREAMON) == FIMC_STREAMON)
+ ctrl->status = FIMC_STREAMON;
+ else if ((state & FIMC_STREAMON_IDLE) == FIMC_STREAMON_IDLE)
+ ctrl->status = FIMC_STREAMON_IDLE;
+ else
+ ctrl->status = FIMC_STREAMOFF;
+
+ return 0;
+}
+
+static inline int fimc_resume_cap(struct fimc_control *ctrl)
+{
+ if (ctrl->cam->id == CAMERA_WB)
+ fimc_streamon_capture((void *)ctrl);
+
+ return 0;
+}
+
+int fimc_resume(struct platform_device *pdev)
+{
+ struct fimc_control *ctrl;
+ struct s3c_platform_fimc *pdata;
+ int id = pdev->id;
+
+ ctrl = get_fimc_ctrl(id);
+ pdata = to_fimc_plat(ctrl->dev);
+
+ if (atomic_read(&ctrl->in_use) && ctrl->status != FIMC_OFF_SLEEP)
+ fimc_clk_en(ctrl, true);
+
+ if (ctrl->out)
+ fimc_resume_out(ctrl);
+ else if (ctrl->cap)
+ fimc_resume_cap(ctrl);
+ else
+ ctrl->status = FIMC_STREAMOFF;
+
+ return 0;
+}
+#else
+#define fimc_suspend NULL
+#define fimc_resume NULL
+#endif
+
+static struct platform_driver fimc_driver = {
+ .probe = fimc_probe,
+ .remove = fimc_remove,
+ .suspend = fimc_suspend,
+ .resume = fimc_resume,
+ .driver = {
+ .name = FIMC_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int fimc_register(void)
+{
+ platform_driver_register(&fimc_driver);
+
+ return 0;
+}
+
+static void fimc_unregister(void)
+{
+ platform_driver_unregister(&fimc_driver);
+}
+
+late_initcall(fimc_register);
+module_exit(fimc_unregister);
+
+MODULE_AUTHOR("Dongsoo, Kim <dongsoo45.kim@samsung.com>");
+MODULE_AUTHOR("Jinsung, Yang <jsgood.yang@samsung.com>");
+MODULE_AUTHOR("Jonghun, Han <jonghun.han@samsung.com>");
+MODULE_DESCRIPTION("Samsung Camera Interface (FIMC) driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/samsung/fimc/fimc_output.c b/drivers/media/video/samsung/fimc/fimc_output.c
new file mode 100644
index 0000000..ebae1ad
--- /dev/null
+++ b/drivers/media/video/samsung/fimc/fimc_output.c
@@ -0,0 +1,2563 @@
+/* linux/drivers/media/video/samsung/fimc/fimc_output.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * V4L2 Output device support file for Samsung Camera Interface (FIMC) 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/slab.h>
+#include <linux/bootmem.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+#include <linux/mm.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_samsung.h>
+#include <media/videobuf-core.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <linux/mman.h>
+#include <plat/media.h>
+#include <linux/clk.h>
+
+#include "fimc.h"
+
+static __u32 fimc_get_pixel_format_type(__u32 pixelformat)
+{
+ switch (pixelformat) {
+ case V4L2_PIX_FMT_RGB32:
+ case V4L2_PIX_FMT_RGB565:
+ return FIMC_RGB;
+
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV12T:
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_YUV420:
+ return FIMC_YUV420;
+
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_UYVY:
+ case V4L2_PIX_FMT_YVYU:
+ case V4L2_PIX_FMT_VYUY:
+ case V4L2_PIX_FMT_NV16:
+ case V4L2_PIX_FMT_NV61:
+ case V4L2_PIX_FMT_YUV422P:
+ return FIMC_YUV422;
+
+ default:
+ return FIMC_YUV444;
+ }
+}
+
+void fimc_outdev_set_src_addr(struct fimc_control *ctrl, dma_addr_t *base)
+{
+ fimc_hwset_addr_change_disable(ctrl);
+ fimc_hwset_input_address(ctrl, base);
+ fimc_hwset_addr_change_enable(ctrl);
+}
+
+int fimc_outdev_start_camif(void *param)
+{
+ struct fimc_control *ctrl = (struct fimc_control *)param;
+
+ fimc_hwset_start_scaler(ctrl);
+ fimc_hwset_enable_capture(ctrl, 0); /* bypass disable */
+ fimc_hwset_start_input_dma(ctrl);
+
+ return 0;
+}
+
+static int fimc_outdev_stop_camif(void *param)
+{
+ struct fimc_control *ctrl = (struct fimc_control *)param;
+
+ fimc_hwset_stop_input_dma(ctrl);
+ fimc_hwset_disable_autoload(ctrl);
+ fimc_hwset_stop_scaler(ctrl);
+ fimc_hwset_disable_capture(ctrl);
+ fimc_hwset_sw_reset(ctrl);
+
+ fimc_clk_en(ctrl, false);
+ return 0;
+}
+
+int fimc_outdev_stop_streaming(struct fimc_control *ctrl, struct fimc_ctx *ctx)
+{
+ int ret = 0;
+
+ fimc_dbg("%s: called\n", __func__);
+
+ switch (ctx->overlay.mode) {
+ case FIMC_OVLY_DMA_AUTO: /* fall through */
+ case FIMC_OVLY_DMA_MANUAL:
+ if (ctx->status == FIMC_STREAMON_IDLE)
+ ctx->status = FIMC_STREAMOFF;
+ else
+ ctx->status = FIMC_READY_OFF;
+ break;
+ case FIMC_OVLY_NONE_SINGLE_BUF: /* fall through */
+ case FIMC_OVLY_NONE_MULTI_BUF:
+ if (ctx->status == FIMC_STREAMON_IDLE)
+ ctx->status = FIMC_STREAMOFF;
+ else
+ ctx->status = FIMC_READY_OFF;
+ ret = wait_event_timeout(ctrl->wq,
+ (ctx->status == FIMC_STREAMOFF),
+ FIMC_ONESHOT_TIMEOUT);
+ if (ret == 0) {
+ fimc_dump_context(ctrl, ctx);
+ fimc_err("fail %s: %d\n", __func__, ctx->ctx_num);
+ }
+
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+int fimc_outdev_resume_dma(struct fimc_control *ctrl, struct fimc_ctx *ctx)
+{
+ struct v4l2_rect fimd_rect;
+ struct fb_var_screeninfo var;
+ struct fb_info *fbinfo;
+ struct s3cfb_window *win;
+ int ret = -1, idx;
+
+ fbinfo = registered_fb[ctx->overlay.fb_id];
+ win = (struct s3cfb_window *)fbinfo->par;
+
+ memcpy(&var, &fbinfo->var, sizeof(struct fb_var_screeninfo));
+ memset(&fimd_rect, 0, sizeof(struct v4l2_rect));
+ ret = fimc_fimd_rect(ctrl, ctx, &fimd_rect);
+ if (ret < 0) {
+ fimc_err("fimc_fimd_rect fail\n");
+ return -EINVAL;
+ }
+
+ /* set window path & owner */
+ win->path = DATA_PATH_DMA;
+ win->owner = DMA_MEM_OTHER;
+ win->other_mem_addr = ctx->dst[1].base[FIMC_ADDR_Y];
+ win->other_mem_size = ctx->dst[1].length[FIMC_ADDR_Y];
+
+ /* Update WIN size */
+ var.xres_virtual = fimd_rect.width;
+ var.yres_virtual = fimd_rect.height;
+ var.xres = fimd_rect.width;
+ var.yres = fimd_rect.height;
+
+ /* Update WIN position */
+ win->x = fimd_rect.left;
+ win->y = fimd_rect.top;
+
+ var.activate = FB_ACTIVATE_FORCE;
+ ret = fb_set_var(fbinfo, &var);
+ if (ret < 0) {
+ fimc_err("fb_set_var fail (ret=%d)\n", ret);
+ return -EINVAL;
+ }
+
+ idx = ctx->outq[0];
+ if (idx == -1) {
+ fimc_err("out going queue is empty.\n");
+ return -EINVAL;
+ }
+
+ win->other_mem_addr = ctx->dst[idx].base[FIMC_ADDR_Y];
+ ret = fb_pan_display(fbinfo, &fbinfo->var);
+ if (ret < 0) {
+ fimc_err("%s: fb_pan_display fail (ret=%d)\n", __func__, ret);
+ return -EINVAL;
+ }
+
+ ctrl->fb.is_enable = 1;
+
+ return 0;
+}
+
+static void fimc_init_out_buf(struct fimc_ctx *ctx)
+{
+ int i;
+
+ for (i = 0; i < FIMC_OUTBUFS; i++) {
+ ctx->src[i].state = VIDEOBUF_IDLE;
+ ctx->src[i].flags = 0x0;
+
+ ctx->inq[i] = -1;
+ ctx->outq[i] = -1;
+ }
+}
+
+static int fimc_outdev_set_src_buf(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx)
+{
+ u32 width = ctx->pix.width;
+ u32 height = ctx->pix.height;
+ u32 format = ctx->pix.pixelformat;
+ u32 y_size = width * height;
+ u32 cb_size = 0, cr_size = 0;
+ u32 i, size;
+ dma_addr_t *curr = &ctrl->mem.curr;
+
+ switch (format) {
+ case V4L2_PIX_FMT_RGB32:
+ size = PAGE_ALIGN(y_size << 2);
+ break;
+ case V4L2_PIX_FMT_RGB565: /* fall through */
+ case V4L2_PIX_FMT_UYVY: /* fall through */
+ case V4L2_PIX_FMT_YVYU: /* fall through */
+ case V4L2_PIX_FMT_VYUY: /* fall through */
+ case V4L2_PIX_FMT_YUYV:
+ size = PAGE_ALIGN(y_size << 1);
+ break;
+ case V4L2_PIX_FMT_YUV420:
+ cb_size = y_size >> 2;
+ cr_size = y_size >> 2;
+ size = PAGE_ALIGN(y_size + cb_size + cr_size);
+ break;
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV21:
+ cb_size = y_size >> 1;
+ size = PAGE_ALIGN(y_size + cb_size);
+ break;
+ case V4L2_PIX_FMT_NV12T:
+ fimc_get_nv12t_size(width, height, &y_size, &cb_size, 0);
+ size = PAGE_ALIGN(y_size + cb_size);
+ break;
+ case V4L2_PIX_FMT_NV16:
+ case V4L2_PIX_FMT_NV61:
+ cb_size = y_size;
+ size = PAGE_ALIGN(y_size + cb_size);
+ break;
+ default:
+ fimc_err("%s: Invalid pixelformt : %d\n", __func__, format);
+ return -EINVAL;
+ }
+
+ if ((*curr + size * FIMC_OUTBUFS) > (ctrl->mem.base + ctrl->mem.size)) {
+ fimc_err("%s: Reserved memory is not sufficient\n", __func__);
+ return -EINVAL;
+ }
+
+ /* Initialize source buffer addr */
+ switch (format) {
+ case V4L2_PIX_FMT_RGB565: /* fall through */
+ case V4L2_PIX_FMT_RGB32: /* fall through */
+ case V4L2_PIX_FMT_UYVY: /* fall through */
+ case V4L2_PIX_FMT_YVYU: /* fall through */
+ case V4L2_PIX_FMT_VYUY: /* fall through */
+ case V4L2_PIX_FMT_YUYV:
+ for (i = 0; i < FIMC_OUTBUFS; i++) {
+ ctx->src[i].base[FIMC_ADDR_Y] = *curr;
+ ctx->src[i].length[FIMC_ADDR_Y] = size;
+ ctx->src[i].base[FIMC_ADDR_CB] = 0;
+ ctx->src[i].length[FIMC_ADDR_CB] = 0;
+ ctx->src[i].base[FIMC_ADDR_CR] = 0;
+ ctx->src[i].length[FIMC_ADDR_CR] = 0;
+ *curr += size;
+ }
+ break;
+ case V4L2_PIX_FMT_NV12: /* fall through */
+ case V4L2_PIX_FMT_NV21: /* fall through */
+ case V4L2_PIX_FMT_NV16: /* fall through */
+ case V4L2_PIX_FMT_NV61: /* fall through */
+ case V4L2_PIX_FMT_NV12T:
+ for (i = 0; i < FIMC_OUTBUFS; i++) {
+ ctx->src[i].base[FIMC_ADDR_Y] = *curr;
+ ctx->src[i].length[FIMC_ADDR_Y] = y_size;
+ ctx->src[i].base[FIMC_ADDR_CB] = *curr + y_size;
+ ctx->src[i].length[FIMC_ADDR_CB] = cb_size;
+ ctx->src[i].base[FIMC_ADDR_CR] = 0;
+ ctx->src[i].length[FIMC_ADDR_CR] = 0;
+ *curr += size;
+ }
+ break;
+ case V4L2_PIX_FMT_YUV420:
+ for (i = 0; i < FIMC_OUTBUFS; i++) {
+ ctx->src[i].base[FIMC_ADDR_Y] = *curr;
+ ctx->src[i].base[FIMC_ADDR_CB] = *curr + y_size;
+ ctx->src[i].base[FIMC_ADDR_CR] = *curr + y_size +
+ cb_size;
+ ctx->src[i].length[FIMC_ADDR_Y] = y_size;
+ ctx->src[i].length[FIMC_ADDR_CB] = cb_size;
+ ctx->src[i].length[FIMC_ADDR_CR] = cr_size;
+ *curr += size;
+ }
+ break;
+
+ default:
+ fimc_err("%s: Invalid pixelformt : %d\n", __func__, format);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int fimc_outdev_set_dst_buf(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx)
+{
+ dma_addr_t *curr = &ctrl->mem.curr;
+ dma_addr_t end;
+ u32 width = ctrl->fb.lcd_hres;
+ u32 height = ctrl->fb.lcd_vres;
+ u32 i, size;
+
+ end = ctrl->mem.base + ctrl->mem.size;
+ size = PAGE_ALIGN(width * height * 4);
+
+ if ((*curr + (size * FIMC_OUTBUFS)) > end) {
+ fimc_err("%s: Reserved memory is not sufficient\n", __func__);
+ return -EINVAL;
+ }
+
+ /* Initialize destination buffer addr */
+ for (i = 0; i < FIMC_OUTBUFS; i++) {
+ ctx->dst[i].base[FIMC_ADDR_Y] = *curr;
+ ctx->dst[i].length[FIMC_ADDR_Y] = size;
+ ctx->dst[i].base[FIMC_ADDR_CB] = 0;
+ ctx->dst[i].length[FIMC_ADDR_CB] = 0;
+ ctx->dst[i].base[FIMC_ADDR_CR] = 0;
+ ctx->dst[i].length[FIMC_ADDR_CR] = 0;
+ *curr += size;
+ }
+
+ return 0;
+}
+
+static int fimc_set_rot_degree(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx,
+ int degree)
+{
+ switch (degree) {
+ case 0: /* fall through */
+ case 90: /* fall through */
+ case 180: /* fall through */
+ case 270:
+ ctx->rotate = degree;
+ break;
+
+ default:
+ fimc_err("Invalid rotate value : %d\n", degree);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int fimc_outdev_check_param(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx)
+{
+ struct v4l2_rect dst, bound;
+ u32 rot = 0;
+ int ret = 0, i, exclusive = 0;
+
+ rot = fimc_mapping_rot_flip(ctx->rotate, ctx->flip);
+ dst.top = ctx->win.w.top;
+ dst.left = ctx->win.w.left;
+ dst.width = ctx->win.w.width;
+ dst.height = ctx->win.w.height;
+
+ switch (ctx->overlay.mode) {
+ case FIMC_OVLY_DMA_AUTO: /* fall through */
+ case FIMC_OVLY_DMA_MANUAL:
+ if (rot & FIMC_ROT) {
+ bound.width = ctrl->fb.lcd_vres;
+ bound.height = ctrl->fb.lcd_hres;
+ } else {
+ bound.width = ctrl->fb.lcd_hres;
+ bound.height = ctrl->fb.lcd_vres;
+ }
+ break;
+ case FIMC_OVLY_NONE_SINGLE_BUF: /* fall through */
+ case FIMC_OVLY_NONE_MULTI_BUF:
+ bound.width = ctx->fbuf.fmt.width;
+ bound.height = ctx->fbuf.fmt.height;
+ break;
+
+ default:
+ fimc_err("%s: invalid ovelay mode.\n", __func__);
+ return -EINVAL;
+ }
+
+ if ((dst.left + dst.width) > bound.width) {
+ fimc_err("Horizontal position setting is failed\n");
+ fimc_err("\tleft = %d, width = %d, bound width = %d,\n",
+ dst.left, dst.width, bound.width);
+ ret = -EINVAL;
+ } else if ((dst.top + dst.height) > bound.height) {
+ fimc_err("Vertical position setting is failed\n");
+ fimc_err("\ttop = %d, height = %d, bound height = %d,\n",
+ dst.top, dst.height, bound.height);
+ ret = -EINVAL;
+ }
+
+ if ((ctx->status != FIMC_STREAMOFF) &&
+ (ctx->status != FIMC_READY_ON) &&
+ (ctx->status != FIMC_ON_IDLE_SLEEP)) {
+ fimc_err("FIMC is running\n");
+ return -EBUSY;
+ }
+
+ /* check other open instance */
+ for (i = 0; i < FIMC_MAX_CTXS; i++) {
+ switch (ctrl->out->ctx[i].overlay.mode) {
+ case FIMC_OVLY_DMA_AUTO: /* fall through */
+ case FIMC_OVLY_DMA_MANUAL:
+ exclusive++;
+ break;
+ case FIMC_OVLY_NONE_SINGLE_BUF: /* fall through */
+ case FIMC_OVLY_NONE_MULTI_BUF: /* fall through */
+ case FIMC_OVLY_NOT_FIXED:
+ break;
+ }
+ }
+
+ if (exclusive > 1) {
+ for (i = 0; i < FIMC_MAX_CTXS; i++)
+ fimc_err("%s: ctx %d mode = %d", __func__, i,
+ ctrl->out->ctx[i].overlay.mode);
+ return -EBUSY;
+ }
+
+ return ret;
+}
+
+static void fimc_outdev_set_src_format(struct fimc_control *ctrl,
+ u32 pixfmt, enum v4l2_field field)
+{
+ fimc_hwset_input_burst_cnt(ctrl, 4);
+ fimc_hwset_input_colorspace(ctrl, pixfmt);
+ fimc_hwset_input_yuv(ctrl, pixfmt);
+ fimc_hwset_input_rgb(ctrl, pixfmt);
+ fimc_hwset_intput_field(ctrl, field);
+ fimc_hwset_ext_rgb(ctrl, 1);
+ fimc_hwset_input_addr_style(ctrl, pixfmt);
+}
+
+static void fimc_outdev_set_dst_format(struct fimc_control *ctrl,
+ struct v4l2_pix_format *pixfmt)
+{
+ fimc_hwset_output_colorspace(ctrl, pixfmt->pixelformat);
+ fimc_hwset_output_yuv(ctrl, pixfmt->pixelformat);
+ fimc_hwset_output_rgb(ctrl, pixfmt->pixelformat);
+ fimc_hwset_output_scan(ctrl, pixfmt);
+ fimc_hwset_output_addr_style(ctrl, pixfmt->pixelformat);
+}
+
+static void fimc_outdev_set_format(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx)
+{
+ struct v4l2_pix_format pixfmt;
+ memset(&pixfmt, 0, sizeof(pixfmt));
+
+ fimc_outdev_set_src_format(ctrl, ctx->pix.pixelformat, ctx->pix.field);
+
+ switch (ctx->overlay.mode) {
+ case FIMC_OVLY_DMA_AUTO: /* fall through */
+ case FIMC_OVLY_DMA_MANUAL: /* Non-destructive overlay mode */
+ if (ctx->pix.field == V4L2_FIELD_NONE) {
+ pixfmt.pixelformat = V4L2_PIX_FMT_RGB32;
+ pixfmt.field = V4L2_FIELD_NONE;
+ } else if (ctx->pix.field == V4L2_FIELD_INTERLACED_TB) {
+ pixfmt.pixelformat = V4L2_PIX_FMT_YUV444;
+ pixfmt.field = V4L2_FIELD_INTERLACED_TB;
+ } else if (ctx->pix.field == V4L2_FIELD_ANY) {
+ pixfmt.pixelformat = V4L2_PIX_FMT_RGB32;
+ pixfmt.field = V4L2_FIELD_NONE;
+ }
+
+ break;
+ case FIMC_OVLY_NONE_SINGLE_BUF: /* fall through */
+ case FIMC_OVLY_NONE_MULTI_BUF: /* Destructive overlay mode */
+ pixfmt.pixelformat = ctx->fbuf.fmt.pixelformat;
+ pixfmt.field = V4L2_FIELD_NONE;
+
+ break;
+ default:
+ fimc_err("Invalid overlay mode %d\n", ctx->overlay.mode);
+ break;
+ }
+
+ fimc_outdev_set_dst_format(ctrl, &pixfmt);
+}
+
+static void fimc_outdev_set_path(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx)
+{
+ /* source path */
+ fimc_hwset_input_source(ctrl, FIMC_SRC_MSDMA);
+
+ fimc_hwset_disable_lcdfifo(ctrl);
+ fimc_hwset_disable_autoload(ctrl);
+}
+
+static void fimc_outdev_set_rot(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx)
+{
+ u32 rot = ctx->rotate;
+ u32 flip = ctx->flip;
+
+ fimc_hwset_input_rot(ctrl, 0, 0);
+ fimc_hwset_input_flip(ctrl, 0, 0);
+ fimc_hwset_output_rot_flip(ctrl, rot, flip);
+}
+
+static void fimc_outdev_set_src_dma_offset(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx)
+{
+ struct v4l2_rect bound, crop;
+ u32 pixfmt = ctx->pix.pixelformat;
+
+ bound.width = ctx->pix.width;
+ bound.height = ctx->pix.height;
+
+ crop.left = ctx->crop.left;
+ crop.top = ctx->crop.top;
+ crop.width = ctx->crop.width;
+ crop.height = ctx->crop.height;
+
+ fimc_hwset_input_offset(ctrl, pixfmt, &bound, &crop);
+}
+
+static int fimc4x_outdev_check_src_size(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx,
+ struct v4l2_rect *real,
+ struct v4l2_rect *org)
+{
+ /* No Input Rotator */
+ if (real->height < 8) {
+ fimc_err("SRC Real_H: Min 8\n");
+ return -EINVAL;
+ }
+
+ if (real->width < 16) {
+ fimc_err("SRC Real_W: Min 16\n");
+ return -EINVAL;
+ }
+
+ if (real->width > ctrl->limit->real_w_no_rot) {
+ fimc_err("SRC REAL_W: Real_W <= %d\n",
+ ctrl->limit->real_w_no_rot);
+ return -EINVAL;
+ }
+
+ if (org->height < real->height) {
+ fimc_err("SRC Org_H: larger than Real_H\n");
+ return -EINVAL;
+ }
+
+ if (org->width < real->width) {
+ fimc_err("SRC Org_W: Org_W >= Real_W\n");
+ return -EINVAL;
+ }
+
+ if (ctx->sc.pre_vratio) {
+ if (real->height % ctx->sc.pre_vratio) {
+ fimc_err("SRC Real_H: multiple of pre_vratio!\n");
+ return -EINVAL;
+ }
+ }
+
+ if (real->width % 16) {
+ fimc_err("SRC Real_W: multiple of 16 !\n");
+ return -EINVAL;
+ }
+
+ if (ctx->sc.pre_hratio) {
+ if (real->width % (ctx->sc.pre_hratio * 4)) {
+ fimc_err("SRC Real_W: multiple of 4 * pre_hratio!\n");
+ return -EINVAL;
+ }
+ }
+
+ if (org->width % 16) {
+ fimc_err("SRC Org_W: multiple of 16\n");
+ return -EINVAL;
+ }
+
+ if (org->height < 8) {
+ fimc_err("SRC Org_H: Min 8\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int fimc50_outdev_check_src_size(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx,
+ struct v4l2_rect *real,
+ struct v4l2_rect *org)
+{
+ u32 pixelformat = ctx->pix.pixelformat;
+
+ /* No Input Rotator */
+ if (real->height < 8) {
+ fimc_err("SRC Real_H: Min 8\n");
+ return -EINVAL;
+ }
+
+ if (real->width < 16) {
+ fimc_err("SRC Real_W: Min 16\n");
+ return -EINVAL;
+ }
+
+ if (real->width > ctrl->limit->real_w_no_rot) {
+ fimc_err("SRC REAL_W: Real_W <= %d\n",
+ ctrl->limit->real_w_no_rot);
+ return -EINVAL;
+ }
+
+ if (org->height < real->height) {
+ fimc_err("SRC Org_H: larger than Real_H\n");
+ return -EINVAL;
+ }
+
+ if (org->width < real->width) {
+ fimc_err("SRC Org_W: Org_W >= Real_W\n");
+ return -EINVAL;
+ }
+
+ if (ctx->pix.field == V4L2_FIELD_INTERLACED_TB) {
+ switch (pixelformat) {
+ case V4L2_PIX_FMT_YUV444: /* fall through */
+ case V4L2_PIX_FMT_RGB32:
+ if (real->height % 2) {
+ fimc_err("SRC Real_H: multiple of 2\n");
+ return -EINVAL;
+ }
+ case V4L2_PIX_FMT_YUV422P:
+ if (real->height % 2) {
+ fimc_err("SRC Real_H: multiple of 2\n");
+ return -EINVAL;
+ } else if (real->width % 2) {
+ fimc_err("SRC Real_H: multiple of 2\n");
+ return -EINVAL;
+ }
+ case V4L2_PIX_FMT_YVU420:
+ if (real->height % 4) {
+ fimc_err("SRC Real_H: multiple of 4\n");
+ return -EINVAL;
+ } else if (real->width % 2) {
+ fimc_err("SRC Real_H: multiple of 2\n");
+ return -EINVAL;
+ }
+ }
+ } else if (ctx->pix.field == V4L2_FIELD_NONE) {
+ if (pixelformat == V4L2_PIX_FMT_YUV422P) {
+ if (real->height % 2) {
+ fimc_err("SRC Real_H: multiple of 2\n");
+ return -EINVAL;
+ } else if (real->width % 2) {
+ fimc_err("SRC Real_H: multiple of 2\n");
+ return -EINVAL;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int fimc_outdev_set_src_dma_size(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx)
+{
+ struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
+ struct v4l2_rect real, org;
+ int ret = 0;
+
+ real.width = ctx->crop.width;
+ real.height = ctx->crop.height;
+ org.width = ctx->pix.width;
+ org.height = ctx->pix.height;
+
+ if (pdata->hw_ver == 0x50)
+ ret = fimc50_outdev_check_src_size(ctrl, ctx, &real, &org);
+ else
+ ret = fimc4x_outdev_check_src_size(ctrl, ctx, &real, &org);
+
+ if (ret < 0)
+ return ret;
+
+ fimc_hwset_org_input_size(ctrl, org.width, org.height);
+ fimc_hwset_real_input_size(ctrl, real.width, real.height);
+
+ return 0;
+}
+
+static void fimc_outdev_set_dst_dma_offset(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx)
+{
+ struct v4l2_rect bound, win;
+ struct v4l2_rect *w = &ctx->win.w;
+ u32 pixfmt = ctx->fbuf.fmt.pixelformat;
+
+ memset(&bound, 0, sizeof(bound));
+ memset(&win, 0, sizeof(win));
+
+ switch (ctx->rotate) {
+ case 0:
+ bound.width = ctx->fbuf.fmt.width;
+ bound.height = ctx->fbuf.fmt.height;
+
+ win.left = w->left;
+ win.top = w->top;
+ win.width = w->width;
+ win.height = w->height;
+
+ break;
+ case 90:
+ bound.width = ctx->fbuf.fmt.height;
+ bound.height = ctx->fbuf.fmt.width;
+
+ win.left = ctx->fbuf.fmt.height - (w->height + w->top);
+ win.top = w->left;
+ win.width = w->height;
+ win.height = w->width;
+
+ break;
+ case 180:
+ bound.width = ctx->fbuf.fmt.width;
+ bound.height = ctx->fbuf.fmt.height;
+
+ win.left = ctx->fbuf.fmt.width - (w->left + w->width);
+ win.top = ctx->fbuf.fmt.height - (w->top + w->height);
+ win.width = w->width;
+ win.height = w->height;
+
+ break;
+ case 270:
+ bound.width = ctx->fbuf.fmt.height;
+ bound.height = ctx->fbuf.fmt.width;
+
+ win.left = ctx->win.w.top;
+ win.top = ctx->fbuf.fmt.width - (w->left + w->width);
+ win.width = w->height;
+ win.height = w->width;
+
+ break;
+ default:
+ fimc_err("Rotation degree is invalid\n");
+ break;
+ }
+
+ switch (ctx->overlay.mode) {
+ case FIMC_OVLY_DMA_AUTO: /* fall through */
+ case FIMC_OVLY_DMA_MANUAL:
+ memset(&bound, 0, sizeof(bound));
+ memset(&win, 0, sizeof(win));
+ fimc_hwset_output_offset(ctrl, pixfmt, &bound, &win);
+ break;
+ default:
+ fimc_hwset_output_offset(ctrl, pixfmt, &bound, &win);
+ break;
+ }
+
+ fimc_dbg("bound:width(%d), height(%d)\n", bound.width, bound.height);
+ fimc_dbg("win:width(%d), height(%d)\n", win.width, win.height);
+ fimc_dbg("win:top(%d), left(%d)\n", win.top, win.left);
+}
+
+static int fimc_outdev_check_dst_size(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx,
+ struct v4l2_rect *real,
+ struct v4l2_rect *org)
+{
+ u32 rot = ctx->rotate;
+ __u32 pixel_type;
+
+ pixel_type = fimc_get_pixel_format_type(ctx->fbuf.fmt.pixelformat);
+
+ if (FIMC_YUV420 == pixel_type && real->height % 2) {
+ fimc_err("DST Real_H: even number for YUV420 formats\n");
+ return -EINVAL;
+ }
+
+ if ((rot == 90) || (rot == 270)) {
+ /* Use Output Rotator */
+ if (org->height < real->width) {
+ fimc_err("DST Org_H: Org_H(%d) >= Real_W(%d)\n",
+ org->height, real->width);
+ return -EINVAL;
+ }
+
+ if (org->width < real->height) {
+ fimc_err("DST Org_W: Org_W(%d) >= Real_H(%d)\n",
+ org->width, real->height);
+ return -EINVAL;
+ }
+
+ if (real->height > ctrl->limit->trg_h_rot) {
+ fimc_err("DST REAL_H: Real_H <= %d\n",
+ ctrl->limit->trg_h_rot);
+ return -EINVAL;
+ }
+ } else {
+ /* No Output Rotator */
+ if (org->height < 8) {
+ fimc_err("DST Org_H: Min 8\n");
+ return -EINVAL;
+ }
+
+ if (org->height < real->height) {
+ fimc_err("DST Org_H: Org_H >= Real_H\n");
+ return -EINVAL;
+ }
+
+ if (org->width % 8) {
+ fimc_err("DST Org_W: multiple of 8\n");
+ return -EINVAL;
+ }
+
+ if (org->width < real->width) {
+ fimc_err("DST Org_W: Org_W >= Real_W\n");
+ return -EINVAL;
+ }
+
+ if (real->height > ctrl->limit->trg_h_no_rot) {
+ fimc_err("DST REAL_H: Real_H <= %d\n",
+ ctrl->limit->trg_h_no_rot);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static int fimc_outdev_set_dst_dma_size(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx)
+{
+ struct v4l2_rect org, real;
+ int ret = -1;
+
+ memset(&org, 0, sizeof(org));
+ memset(&real, 0, sizeof(real));
+
+ switch (ctx->overlay.mode) {
+ case FIMC_OVLY_NONE_MULTI_BUF: /* fall through */
+ case FIMC_OVLY_NONE_SINGLE_BUF:
+ real.width = ctx->win.w.width;
+ real.height = ctx->win.w.height;
+
+ switch (ctx->rotate) {
+ case 0: /* fall through */
+ case 180:
+ org.width = ctx->fbuf.fmt.width;
+ org.height = ctx->fbuf.fmt.height;
+ break;
+ case 90: /* fall through */
+ case 270:
+ org.width = ctx->fbuf.fmt.height;
+ org.height = ctx->fbuf.fmt.width;
+ break;
+ default:
+ fimc_err("Rotation degree is invalid\n");
+ break;
+ }
+
+ break;
+
+ case FIMC_OVLY_DMA_MANUAL: /* fall through */
+ case FIMC_OVLY_DMA_AUTO:
+ real.width = ctx->win.w.width;
+ real.height = ctx->win.w.height;
+
+ switch (ctx->rotate) {
+ case 0: /* fall through */
+ case 180:
+ org.width = ctx->win.w.width;
+ org.height = ctx->win.w.height;
+ break;
+ case 90: /* fall through */
+ case 270:
+ org.width = ctx->win.w.height;
+ org.height = ctx->win.w.width;
+ break;
+ default:
+ fimc_err("Rotation degree is invalid\n");
+ break;
+ }
+
+ break;
+ default:
+ break;
+ }
+
+ fimc_dbg("DST org: width(%d), height(%d)\n", org.width, org.height);
+ fimc_dbg("DST real: width(%d), height(%d)\n", real.width, real.height);
+
+ ret = fimc_outdev_check_dst_size(ctrl, ctx, &real, &org);
+ if (ret < 0)
+ return ret;
+
+ fimc_hwset_output_size(ctrl, real.width, real.height);
+ fimc_hwset_output_area(ctrl, real.width, real.height);
+ fimc_hwset_org_output_size(ctrl, org.width, org.height);
+ fimc_hwset_ext_output_size(ctrl, real.width, real.height);
+
+ return 0;
+}
+
+static void fimc_outdev_calibrate_scale_info(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx,
+ struct v4l2_rect *src,
+ struct v4l2_rect *dst)
+{
+ /* OUTPUT ROTATOR */
+ src->width = ctx->crop.width;
+ src->height = ctx->crop.height;
+ dst->width = ctx->win.w.width;
+ dst->height = ctx->win.w.height;
+
+ fimc_dbg("src->width(%d), src->height(%d)\n", src->width, src->height);
+ fimc_dbg("dst->width(%d), dst->height(%d)\n", dst->width, dst->height);
+}
+
+static int fimc_outdev_check_scaler(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx,
+ struct v4l2_rect *src,
+ struct v4l2_rect *dst)
+{
+ u32 pixels = 0, dstfmt = 0;
+
+ /* Check scaler limitation */
+ if (ctx->sc.pre_dst_width > ctrl->limit->pre_dst_w) {
+ fimc_err("FIMC%d : MAX PreDstWidth is %d\n",
+ ctrl->id, ctrl->limit->pre_dst_w);
+ return -EDOM;
+ }
+
+ /* SRC width double boundary check */
+ switch (ctx->pix.pixelformat) {
+ case V4L2_PIX_FMT_RGB32:
+ pixels = 1;
+ break;
+ case V4L2_PIX_FMT_YUYV: /* fall through */
+ case V4L2_PIX_FMT_UYVY: /* fall through */
+ case V4L2_PIX_FMT_YVYU: /* fall through */
+ case V4L2_PIX_FMT_VYUY: /* fall through */
+ case V4L2_PIX_FMT_NV16: /* fall through */
+ case V4L2_PIX_FMT_NV61: /* fall through */
+ case V4L2_PIX_FMT_RGB565:
+ pixels = 2;
+ break;
+ case V4L2_PIX_FMT_YUV420: /* fall through */
+ case V4L2_PIX_FMT_NV12: /* fall through */
+ case V4L2_PIX_FMT_NV21: /* fall through */
+ case V4L2_PIX_FMT_NV12T:
+ pixels = 8;
+ break;
+ default:
+ fimc_err("Invalid color format\n");
+ return -EINVAL;
+ }
+
+ if (src->width % pixels) {
+ fimc_err("source width multiple of %d pixels\n", pixels);
+ return -EDOM;
+ }
+
+ /* DST width double boundary check */
+ switch (ctx->overlay.mode) {
+ case FIMC_OVLY_DMA_AUTO: /* fall through */
+ case FIMC_OVLY_DMA_MANUAL:
+ dstfmt = V4L2_PIX_FMT_RGB32;
+ break;
+ case FIMC_OVLY_NONE_SINGLE_BUF: /* fall through */
+ case FIMC_OVLY_NONE_MULTI_BUF:
+ dstfmt = ctx->fbuf.fmt.pixelformat;
+ break;
+ default:
+ break;
+ }
+
+ switch (dstfmt) {
+ case V4L2_PIX_FMT_RGB32:
+ pixels = 1;
+ break;
+ case V4L2_PIX_FMT_RGB565:
+ case V4L2_PIX_FMT_YUYV: /* fall through */
+ case V4L2_PIX_FMT_UYVY: /* fall through */
+ case V4L2_PIX_FMT_YVYU: /* fall through */
+ case V4L2_PIX_FMT_VYUY: /* fall through */
+ case V4L2_PIX_FMT_NV16: /* fall through */
+ case V4L2_PIX_FMT_NV61:
+ pixels = 2;
+ break;
+ case V4L2_PIX_FMT_YUV420: /* fall through */
+ case V4L2_PIX_FMT_NV12: /* fall through */
+ case V4L2_PIX_FMT_NV21: /* fall through */
+ case V4L2_PIX_FMT_NV12T:
+ pixels = 8;
+ break;
+ default:
+ fimc_err("Invalid color format\n");
+ return -EINVAL;
+ }
+
+ if (dst->width % pixels) {
+ fimc_err("source width multiple of %d pixels\n", pixels);
+ return -EDOM;
+ }
+
+ return 0;
+}
+
+static int fimc_outdev_set_scaler(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx)
+{
+ struct v4l2_rect src, dst;
+ int ret = 0;
+ struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
+
+ memset(&src, 0, sizeof(src));
+ memset(&dst, 0, sizeof(dst));
+
+ fimc_outdev_calibrate_scale_info(ctrl, ctx, &src, &dst);
+
+ ret = fimc_get_scaler_factor(src.width, dst.width,
+ &ctx->sc.pre_hratio, &ctx->sc.hfactor);
+ if (ret < 0) {
+ fimc_err("Fail : Out of Width scale range\n");
+ return ret;
+ }
+
+ ret = fimc_get_scaler_factor(src.height, dst.height,
+ &ctx->sc.pre_vratio, &ctx->sc.vfactor);
+ if (ret < 0) {
+ fimc_err("Fail : Out of Height scale range\n");
+ return ret;
+ }
+
+ ctx->sc.pre_dst_width = src.width / ctx->sc.pre_hratio;
+ ctx->sc.pre_dst_height = src.height / ctx->sc.pre_vratio;
+
+ if (pdata->hw_ver == 0x50) {
+ ctx->sc.main_hratio = (src.width << 14) /
+ (dst.width << ctx->sc.hfactor);
+ ctx->sc.main_vratio = (src.height << 14) /
+ (dst.height << ctx->sc.vfactor);
+ } else {
+ ctx->sc.main_hratio = (src.width << 8) /
+ (dst.width << ctx->sc.hfactor);
+ ctx->sc.main_vratio = (src.height << 8) /
+ (dst.height << ctx->sc.vfactor);
+ }
+
+ fimc_dbg("pre_hratio(%d), hfactor(%d), pre_vratio(%d), vfactor(%d)\n",
+ ctx->sc.pre_hratio, ctx->sc.hfactor,
+ ctx->sc.pre_vratio, ctx->sc.vfactor);
+
+
+ fimc_dbg("pre_dst_width(%d), main_hratio(%d), "
+ "pre_dst_height(%d), main_vratio(%d)\n",
+ ctx->sc.pre_dst_width, ctx->sc.main_hratio,
+ ctx->sc.pre_dst_height, ctx->sc.main_vratio);
+
+ ctx->sc.bypass = 0; /* Input DMA cannot support scaler bypass. */
+ ctx->sc.scaleup_h = (dst.width >= src.width) ? 1 : 0;
+ ctx->sc.scaleup_v = (dst.height >= src.height) ? 1 : 0;
+ ctx->sc.shfactor = 10 - (ctx->sc.hfactor + ctx->sc.vfactor);
+
+ if (pdata->hw_ver != 0x50) {
+ ret = fimc_outdev_check_scaler(ctrl, ctx, &src, &dst);
+ if (ret < 0)
+ return ret;
+ }
+
+ fimc_hwset_prescaler(ctrl, &ctx->sc);
+ fimc_hwset_scaler(ctrl, &ctx->sc);
+
+ return 0;
+}
+
+int fimc_outdev_set_ctx_param(struct fimc_control *ctrl, struct fimc_ctx *ctx)
+{
+ int ret;
+
+ if (ctrl->status == FIMC_READY_ON || ctrl->status == FIMC_STREAMON_IDLE)
+ fimc_hwset_enable_irq(ctrl, 0, 1);
+
+ fimc_outdev_set_format(ctrl, ctx);
+ fimc_outdev_set_path(ctrl, ctx);
+ fimc_outdev_set_rot(ctrl, ctx);
+
+ fimc_outdev_set_src_dma_offset(ctrl, ctx);
+ ret = fimc_outdev_set_src_dma_size(ctrl, ctx);
+ if (ret < 0)
+ return ret;
+
+ fimc_outdev_set_dst_dma_offset(ctrl, ctx);
+
+ ret = fimc_outdev_set_dst_dma_size(ctrl, ctx);
+ if (ret < 0)
+ return ret;
+
+ ret = fimc_outdev_set_scaler(ctrl, ctx);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+int fimc_fimd_rect(const struct fimc_control *ctrl,
+ const struct fimc_ctx *ctx,
+ struct v4l2_rect *fimd_rect)
+{
+ switch (ctx->rotate) {
+ case 0:
+ fimd_rect->left = ctx->win.w.left;
+ fimd_rect->top = ctx->win.w.top;
+ fimd_rect->width = ctx->win.w.width;
+ fimd_rect->height = ctx->win.w.height;
+
+ break;
+
+ case 90:
+ fimd_rect->left = ctrl->fb.lcd_hres -
+ (ctx->win.w.top + ctx->win.w.height);
+ fimd_rect->top = ctx->win.w.left;
+ fimd_rect->width = ctx->win.w.height;
+ fimd_rect->height = ctx->win.w.width;
+
+ break;
+
+ case 180:
+ fimd_rect->left = ctrl->fb.lcd_hres -
+ (ctx->win.w.left + ctx->win.w.width);
+ fimd_rect->top = ctrl->fb.lcd_vres -
+ (ctx->win.w.top + ctx->win.w.height);
+ fimd_rect->width = ctx->win.w.width;
+ fimd_rect->height = ctx->win.w.height;
+
+ break;
+
+ case 270:
+ fimd_rect->left = ctx->win.w.top;
+ fimd_rect->top = ctrl->fb.lcd_vres -
+ (ctx->win.w.left + ctx->win.w.width);
+ fimd_rect->width = ctx->win.w.height;
+ fimd_rect->height = ctx->win.w.width;
+
+ break;
+
+ default:
+ fimc_err("Rotation degree is invalid\n");
+ return -EINVAL;
+
+ break;
+ }
+
+ return 0;
+}
+
+int fimc_outdev_overlay_buf(struct file *filp,
+ struct fimc_control *ctrl,
+ struct fimc_ctx *ctx)
+{
+ int ret = 0, i;
+ struct fimc_overlay_buf *buf;
+
+ buf = &ctx->overlay.buf;
+
+ for (i = 0; i < FIMC_OUTBUFS; i++) {
+ ctx->overlay.req_idx = i;
+ buf->size[i] = ctx->dst[i].length[0];
+ buf->phy_addr[i] = ctx->dst[i].base[0];
+ buf->vir_addr[i] = do_mmap(filp, 0, buf->size[i],
+ PROT_READ|PROT_WRITE, MAP_SHARED, 0);
+ if (buf->vir_addr[i] == -EINVAL) {
+ fimc_err("%s: fail\n", __func__);
+ return -EINVAL;
+ }
+
+ fimc_dbg("idx : %d, size(0x%08x), phy_addr(0x%08x), "
+ "vir_addr(0x%08x)\n", i, buf->size[i],
+ buf->phy_addr[i], buf->vir_addr[i]);
+ }
+
+ ctx->overlay.req_idx = -1;
+
+ return ret;
+}
+
+int fimc_reqbufs_output(void *fh, struct v4l2_requestbuffers *b)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ struct fimc_ctx *ctx;
+ struct fimc_overlay_buf *buf;
+ struct mm_struct *mm = current->mm;
+ enum fimc_overlay_mode mode;
+ int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
+ int ret = -1, i;
+
+ ctx = &ctrl->out->ctx[ctx_id];
+ buf = &ctx->overlay.buf;
+ mode = ctx->overlay.mode;
+
+ fimc_info1("%s: called\n", __func__);
+
+ if (ctx->status != FIMC_STREAMOFF) {
+ fimc_err("FIMC is running\n");
+ return -EBUSY;
+ }
+
+ if (ctx->is_requested == 1 && b->count != 0) {
+ fimc_err("Buffers were already requested\n");
+ return -EBUSY;
+ }
+
+ if (b->count > FIMC_OUTBUFS) {
+ fimc_warn("The buffer count is modified by driver "
+ "from %d to %d\n", b->count, FIMC_OUTBUFS);
+ b->count = FIMC_OUTBUFS;
+ }
+
+ fimc_init_out_buf(ctx);
+ ctx->is_requested = 0;
+
+ if (b->count == 0) {
+ ctrl->mem.curr = ctrl->mem.base;
+
+ switch (ctx->overlay.mode) {
+ case FIMC_OVLY_DMA_AUTO: /* fall through */
+ case FIMC_OVLY_DMA_MANUAL:
+ for (i = 0; i < FIMC_OUTBUFS; i++) {
+ if (buf->vir_addr[i]) {
+ ret = do_munmap(mm,
+ buf->vir_addr[i],
+ buf->size[i]);
+ if (ret < 0)
+ fimc_err("%s: do_munmap fail. "
+ "vir_addr[%d](0x%08x)\n",
+ __func__, i, buf->vir_addr[i]);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ } else {
+ /* initialize source buffers */
+ if (b->memory == V4L2_MEMORY_MMAP) {
+ ret = fimc_outdev_set_src_buf(ctrl, ctx);
+ ctx->overlay.req_idx = FIMC_MMAP_IDX;
+ if (ret)
+ return ret;
+ } else if (b->memory == V4L2_MEMORY_USERPTR) {
+ if (mode == FIMC_OVLY_DMA_AUTO)
+ ctx->overlay.req_idx = FIMC_USERPTR_IDX;
+ }
+ ctx->is_requested = 1;
+ }
+
+ ctx->buf_num = b->count;
+
+ return 0;
+}
+
+int fimc_querybuf_output(void *fh, struct v4l2_buffer *b)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ struct fimc_ctx *ctx;
+ int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
+ u32 buf_length = 0;
+
+ fimc_info1("%s: called\n", __func__);
+
+ ctx = &ctrl->out->ctx[ctx_id];
+ if (ctx->status != FIMC_STREAMOFF) {
+ fimc_err("FIMC is running\n");
+ return -EBUSY;
+ }
+
+ if (b->index >= ctx->buf_num) {
+ fimc_err("The index is out of bounds. You requested %d buffers."
+ "But requested index is %d\n", ctx->buf_num, b->index);
+ return -EINVAL;
+ }
+
+ b->flags = ctx->src[b->index].flags;
+ b->m.offset = b->index * PAGE_SIZE;
+ buf_length = ctx->src[b->index].length[FIMC_ADDR_Y] +
+ ctx->src[b->index].length[FIMC_ADDR_CB] +
+ ctx->src[b->index].length[FIMC_ADDR_CR];
+ b->length = PAGE_ALIGN(buf_length);
+
+ return 0;
+}
+
+int fimc_g_ctrl_output(void *fh, struct v4l2_control *c)
+{
+ struct fimc_ctx *ctx;
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
+ struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
+ ctx = &ctrl->out->ctx[ctx_id];
+
+ if (ctx->status != FIMC_STREAMOFF) {
+ fimc_err("FIMC is running\n");
+ return -EBUSY;
+ }
+
+ switch (c->id) {
+ case V4L2_CID_ROTATION:
+ c->value = ctx->rotate;
+ break;
+
+ case V4L2_CID_HFLIP:
+ if (ctx->flip & V4L2_CID_HFLIP)
+ c->value = 1;
+ else
+ c->value = 0;
+ break;
+
+ case V4L2_CID_VFLIP:
+ if (ctx->flip & V4L2_CID_VFLIP)
+ c->value = 1;
+ else
+ c->value = 0;
+ break;
+
+ case V4L2_CID_OVERLAY_VADDR0:
+ c->value = ctx->overlay.buf.vir_addr[0];
+ break;
+
+ case V4L2_CID_OVERLAY_VADDR1:
+ c->value = ctx->overlay.buf.vir_addr[1];
+ break;
+
+ case V4L2_CID_OVERLAY_VADDR2:
+ c->value = ctx->overlay.buf.vir_addr[2];
+ break;
+
+ case V4L2_CID_OVERLAY_AUTO:
+ if (ctx->overlay.mode == FIMC_OVLY_DMA_AUTO)
+ c->value = 1;
+ else
+ c->value = 0;
+ break;
+
+ case V4L2_CID_RESERVED_MEM_BASE_ADDR:
+ c->value = ctrl->mem.base;
+ if (2 == ctrl->id) {
+ /* Clearing the buffer for FIMC-2
+ * This is required because the same buffer is used
+ * for both Camcorder recording and HDMI display.
+ */
+ char *fimc_mem = NULL;
+ fimc_mem = (char *) ioremap(ctrl->mem.base, \
+ ctrl->mem.size);
+ if (fimc_mem) {
+ memset(fimc_mem, 0x00, ctrl->mem.size);
+ iounmap(fimc_mem);
+ }
+ }
+ break;
+
+ case V4L2_CID_FIMC_VERSION:
+ c->value = pdata->hw_ver;
+ break;
+
+ default:
+ fimc_err("Invalid control id: %d\n", c->id);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int fimc_set_dst_info(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx,
+ struct fimc_buf *fimc_buf)
+{
+ struct fimc_buf *buf;
+ int i;
+
+ for (i = 0; i < ctx->buf_num; i++) {
+ buf = &fimc_buf[i];
+
+ ctx->dst[i].base[FIMC_ADDR_Y] = buf->base[FIMC_ADDR_Y];
+ ctx->dst[i].length[FIMC_ADDR_Y] = buf->length[FIMC_ADDR_Y];
+
+ ctx->dst[i].base[FIMC_ADDR_CB] = buf->base[FIMC_ADDR_CB];
+ ctx->dst[i].length[FIMC_ADDR_CB] = buf->length[FIMC_ADDR_CB];
+
+ ctx->dst[i].base[FIMC_ADDR_CR] = buf->base[FIMC_ADDR_CR];
+ ctx->dst[i].length[FIMC_ADDR_CR] = buf->length[FIMC_ADDR_CR];
+ }
+
+ for (i = ctx->buf_num; i < FIMC_OUTBUFS; i++) {
+ ctx->dst[i].base[FIMC_ADDR_Y] = 0;
+ ctx->dst[i].length[FIMC_ADDR_Y] = 0;
+
+ ctx->dst[i].base[FIMC_ADDR_CB] = 0;
+ ctx->dst[i].length[FIMC_ADDR_CB] = 0;
+
+ ctx->dst[i].base[FIMC_ADDR_CR] = 0;
+ ctx->dst[i].length[FIMC_ADDR_CR] = 0;
+ }
+
+ /* for debugging */
+ for (i = 0; i < FIMC_OUTBUFS; i++) {
+ fimc_dbg("dst[%d]: base[0]=0x%08x, size[0]=0x%08x\n",
+ i, ctx->dst[i].base[0], ctx->dst[i].length[0]);
+
+ fimc_dbg("dst[%d]: base[1]=0x%08x, size[1]=0x%08x\n",
+ i, ctx->dst[i].base[1], ctx->dst[i].length[2]);
+
+ fimc_dbg("dst[%d]: base[2]=0x%08x, size[2]=0x%08x\n",
+ i, ctx->dst[i].base[1], ctx->dst[i].length[2]);
+ }
+
+ return 0;
+}
+int fimc_s_ctrl_output(struct file *filp, void *fh, struct v4l2_control *c)
+{
+ struct fimc_ctx *ctx;
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
+ int ret = 0;
+
+ ctx = &ctrl->out->ctx[ctx_id];
+ if (ctx->status != FIMC_STREAMOFF) {
+ fimc_err("FIMC is running\n");
+ return -EBUSY;
+ }
+
+ switch (c->id) {
+ case V4L2_CID_ROTATION:
+ ret = fimc_set_rot_degree(ctrl, ctx, c->value);
+
+ break;
+ case V4L2_CID_HFLIP:
+ if (c->value)
+ ctx->flip |= FIMC_XFLIP;
+ else
+ ctx->flip &= ~FIMC_XFLIP;
+
+ break;
+ case V4L2_CID_VFLIP:
+ if (c->value)
+ ctx->flip |= FIMC_YFLIP;
+ else
+ ctx->flip &= ~FIMC_YFLIP;
+
+ break;
+ case V4L2_CID_OVERLAY_AUTO:
+ if (c->value == 1) {
+ ctx->overlay.mode = FIMC_OVLY_DMA_AUTO;
+ } else {
+ ctx->overlay.mode = FIMC_OVLY_DMA_MANUAL;
+ ret = fimc_outdev_set_dst_buf(ctrl, ctx);
+ fimc_outdev_overlay_buf(filp, ctrl, ctx);
+ }
+
+ break;
+ case V4L2_CID_OVLY_MODE:
+ ctx->overlay.mode = c->value;
+
+ break;
+ case V4L2_CID_DST_INFO:
+ ret = fimc_set_dst_info(ctrl, ctx,
+ (struct fimc_buf *)c->value);
+ break;
+ default:
+ fimc_err("Invalid control id: %d\n", c->id);
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+int fimc_cropcap_output(void *fh, struct v4l2_cropcap *a)
+{
+ struct fimc_ctx *ctx;
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
+ u32 is_rotate = 0, max_w = 0, max_h = 0, pixelformat;
+
+ fimc_info1("%s: called\n", __func__);
+
+ ctx = &ctrl->out->ctx[ctx_id];
+ pixelformat = ctx->pix.pixelformat;
+ if (ctx->status != FIMC_STREAMOFF) {
+ fimc_err("FIMC is running\n");
+ return -EBUSY;
+ }
+
+ is_rotate = fimc_mapping_rot_flip(ctx->rotate, ctx->flip);
+ switch (pixelformat) {
+ case V4L2_PIX_FMT_NV12: /* fall through */
+ case V4L2_PIX_FMT_NV21: /* fall through */
+ case V4L2_PIX_FMT_NV12T: /* fall through */
+ case V4L2_PIX_FMT_YUYV: /* fall through */
+ case V4L2_PIX_FMT_UYVY: /* fall through */
+ case V4L2_PIX_FMT_YVYU: /* fall through */
+ case V4L2_PIX_FMT_VYUY: /* fall through */
+ case V4L2_PIX_FMT_NV16: /* fall through */
+ case V4L2_PIX_FMT_NV61: /* fall through */
+ case V4L2_PIX_FMT_YUV420:
+ max_w = FIMC_SRC_MAX_W;
+ max_h = FIMC_SRC_MAX_H;
+ case V4L2_PIX_FMT_RGB32: /* fall through */
+ case V4L2_PIX_FMT_RGB565: /* fall through */
+ if (is_rotate & FIMC_ROT) { /* Landscape mode */
+ max_w = ctrl->fb.lcd_vres;
+ max_h = ctrl->fb.lcd_hres;
+ } else { /* Portrait */
+ max_w = ctrl->fb.lcd_hres;
+ max_h = ctrl->fb.lcd_vres;
+ }
+
+ break;
+ default:
+ fimc_warn("Supported format : \
+ V4L2_PIX_FMT_YUYV, V4L2_PIX_FMT_UYVY, \
+ V4L2_PIX_FMT_YVYU, V4L2_PIX_FMT_VYUY, \
+ V4L2_PIX_FMT_NV12, V4L2_PIX_FMT_NV12T, \
+ V4L2_PIX_FMT_NV21, V4L2_PIX_FMT_RGB32, \
+ V4L2_PIX_FMT_RGB565\n");
+ fimc_warn("%s: Received pixel format = %x\n",
+ __func__, pixelformat);
+ return -EINVAL;
+ }
+
+ /* crop bounds */
+ ctx->cropcap.bounds.left = 0;
+ ctx->cropcap.bounds.top = 0;
+ ctx->cropcap.bounds.width = max_w;
+ ctx->cropcap.bounds.height = max_h;
+
+ /* crop default values */
+ ctx->cropcap.defrect.left = 0;
+ ctx->cropcap.defrect.top = 0;
+ ctx->cropcap.defrect.width = max_w;
+ ctx->cropcap.defrect.height = max_h;
+
+ /* crop pixel aspec values */
+ /* To Do : Have to modify but I don't know the meaning. */
+ ctx->cropcap.pixelaspect.numerator = 16;
+ ctx->cropcap.pixelaspect.denominator = 9;
+
+ a->bounds = ctx->cropcap.bounds;
+ a->defrect = ctx->cropcap.defrect;
+ a->pixelaspect = ctx->cropcap.pixelaspect;
+
+ return 0;
+}
+
+int fimc_g_crop_output(void *fh, struct v4l2_crop *a)
+{
+ struct fimc_ctx *ctx;
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
+
+ ctx = &ctrl->out->ctx[ctx_id];
+
+ fimc_info1("%s: called\n", __func__);
+
+ mutex_lock(&ctrl->v4l2_lock);
+ a->c.left = ctx->crop.left;
+ a->c.top = ctx->crop.top;
+ a->c.width = ctx->crop.width;
+ a->c.height = ctx->crop.height;
+ mutex_unlock(&ctrl->v4l2_lock);
+
+ return 0;
+}
+
+int fimc_s_crop_output(void *fh, struct v4l2_crop *a)
+{
+ struct fimc_ctx *ctx;
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
+
+ fimc_info1("%s: called: left(%d), top(%d), width(%d), height(%d),\n",
+ __func__, a->c.left, a->c.top, a->c.width, a->c.height);
+
+ ctx = &ctrl->out->ctx[ctx_id];
+ if (ctx->status != FIMC_STREAMOFF) {
+ fimc_err("FIMC is running\n");
+ return -EBUSY;
+ }
+
+ /* Check arguments : widht and height */
+ if ((a->c.width < 0) || (a->c.height < 0)) {
+ fimc_err("The crop rect must be bigger than 0\n");
+ return -EINVAL;
+ }
+
+ if ((a->c.width > FIMC_SRC_MAX_W) || (a->c.height > FIMC_SRC_MAX_H)) {
+ fimc_err("The crop width/height must be smaller than "
+ "%d and %d\n", FIMC_SRC_MAX_W, FIMC_SRC_MAX_H);
+ return -EINVAL;
+ }
+
+ /* Check arguments : left and top */
+ if ((a->c.left < 0) || (a->c.top < 0)) {
+ fimc_err("The crop left, top must be bigger than 0\n");
+ return -EINVAL;
+ }
+
+ if ((a->c.left > FIMC_SRC_MAX_W) || (a->c.top > FIMC_SRC_MAX_H)) {
+ fimc_err("The crop left, top must be smaller than %d, %d\n",
+ FIMC_SRC_MAX_W, FIMC_SRC_MAX_H);
+ return -EINVAL;
+ }
+
+ if ((a->c.left + a->c.width) > FIMC_SRC_MAX_W) {
+ fimc_err("The crop rect must be in bound rect\n");
+ return -EINVAL;
+ }
+
+ if ((a->c.top + a->c.height) > FIMC_SRC_MAX_H) {
+ fimc_err("The crop rect must be in bound rect\n");
+ return -EINVAL;
+ }
+
+ ctx->crop.left = a->c.left;
+ ctx->crop.top = a->c.top;
+ ctx->crop.width = a->c.width;
+ ctx->crop.height = a->c.height;
+
+ return 0;
+}
+
+int fimc_streamon_output(void *fh)
+{
+ struct fimc_ctx *ctx;
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
+ int ret = -1;
+
+ fimc_info1("%s: called\n", __func__);
+
+ ctx = &ctrl->out->ctx[ctx_id];
+ if (ctx->overlay.mode == FIMC_OVLY_NOT_FIXED)
+ ctx->overlay.mode = FIMC_OVLY_MODE;
+
+ /* initialize destination buffers */
+ if (ctx->overlay.mode == FIMC_OVLY_DMA_AUTO) {
+ ret = fimc_outdev_set_dst_buf(ctrl, ctx);
+ if (ret)
+ return ret;
+ }
+
+ ret = fimc_outdev_check_param(ctrl, ctx);
+ if (ret < 0) {
+ fimc_err("Fail: fimc_outdev_check_param\n");
+ return ret;
+ }
+
+ ctx->status = FIMC_READY_ON;
+ if (ctrl->status == FIMC_STREAMOFF)
+ ctrl->status = FIMC_READY_ON;
+
+ return ret;
+}
+
+void fimc_outdev_init_idxs(struct fimc_control *ctrl)
+{
+ ctrl->out->idxs.prev.ctx = -1;
+ ctrl->out->idxs.prev.idx = -1;
+ ctrl->out->idxs.active.ctx = -1;
+ ctrl->out->idxs.active.idx = -1;
+ ctrl->out->idxs.next.ctx = -1;
+ ctrl->out->idxs.next.idx = -1;
+}
+
+int fimc_streamoff_output(void *fh)
+{
+ struct fimc_ctx *ctx;
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
+ int ret = -1, i = 0, off_cnt = 0;
+
+ fimc_info1("%s: called\n", __func__);
+
+ ctx = &ctrl->out->ctx[ctx_id];
+ ret = fimc_outdev_stop_streaming(ctrl, ctx);
+ if (ret < 0) {
+ fimc_err("Fail: fimc_outdev_stop_streaming\n");
+ return -EINVAL;
+ }
+
+ ret = fimc_init_in_queue(ctrl, ctx);
+ if (ret < 0) {
+ fimc_err("Fail: fimc_init_in_queue\n");
+ return -EINVAL;
+ }
+
+ ret = fimc_init_out_queue(ctrl, ctx);
+ if (ret < 0) {
+ fimc_err("Fail: fimc_init_out_queue\n");
+ return -EINVAL;
+ }
+
+ /* Make all buffers DQUEUED state. */
+ for (i = 0; i < FIMC_OUTBUFS; i++) {
+ ctx->src[i].state = VIDEOBUF_IDLE;
+ ctx->src[i].flags = V4L2_BUF_FLAG_MAPPED;
+ }
+
+ ctx->status = FIMC_STREAMOFF;
+
+ if (ctrl->out->last_ctx == ctx->ctx_num)
+ ctrl->out->last_ctx = -1;
+
+ if (ctx->overlay.mode == FIMC_OVLY_DMA_AUTO) {
+ ctrl->mem.curr = ctx->dst[0].base[FIMC_ADDR_Y];
+
+ for (i = 0; i < FIMC_OUTBUFS; i++) {
+ ctx->dst[i].base[FIMC_ADDR_Y] = 0;
+ ctx->dst[i].length[FIMC_ADDR_Y] = 0;
+
+ ctx->dst[i].base[FIMC_ADDR_CB] = 0;
+ ctx->dst[i].length[FIMC_ADDR_CB] = 0;
+
+ ctx->dst[i].base[FIMC_ADDR_CR] = 0;
+ ctx->dst[i].length[FIMC_ADDR_CR] = 0;
+ }
+ }
+
+ /* check all ctx to change ctrl->status from streamon to streamoff */
+ for (i = 0; i < FIMC_MAX_CTXS; i++) {
+ if (ctrl->out->ctx[i].status == FIMC_STREAMOFF)
+ off_cnt++;
+ }
+
+ if (off_cnt == FIMC_MAX_CTXS) {
+ ctrl->status = FIMC_STREAMOFF;
+ fimc_outdev_init_idxs(ctrl);
+ fimc_outdev_stop_camif(ctrl);
+ }
+
+ if (ctx_id == ctrl->out->last_ctx)
+ ctrl->out->last_ctx = -1;
+
+ mutex_lock(&ctrl->lock);
+ if (ctx->overlay.mode == FIMC_OVLY_DMA_AUTO && ctrl->fb.is_enable == 1) {
+ fimc_info2("WIN_OFF for FIMC%d\n", ctrl->id);
+ ret = fb_blank(registered_fb[ctx->overlay.fb_id],
+ FB_BLANK_POWERDOWN);
+ if (ret < 0) {
+ fimc_err("%s: fb_blank: fb[%d] " \
+ "mode=FB_BLANK_POWERDOWN\n",
+ __func__, ctx->overlay.fb_id);
+ mutex_unlock(&ctrl->lock);
+ return -EINVAL;
+ }
+
+ ctrl->fb.is_enable = 0;
+ }
+ mutex_unlock(&ctrl->lock);
+
+ return 0;
+}
+
+
+int fimc_output_set_dst_addr(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx, int idx)
+{
+ struct fimc_buf_set buf_set; /* destination addr */
+ u32 format = ctx->fbuf.fmt.pixelformat;
+ u32 width = ctx->fbuf.fmt.width;
+ u32 height = ctx->fbuf.fmt.height;
+ u32 y_size = width * height;
+ u32 c_size = y_size >> 2;
+ int i;
+
+ memset(&buf_set, 0x00, sizeof(buf_set));
+
+ if (V4L2_PIX_FMT_NV12T == format)
+ fimc_get_nv12t_size(width, height, &y_size, &c_size, ctx->rotate);
+
+ switch (format) {
+ case V4L2_PIX_FMT_RGB32:
+ case V4L2_PIX_FMT_RGB565:
+ case V4L2_PIX_FMT_YUYV: /* fall through */
+ case V4L2_PIX_FMT_UYVY: /* fall through */
+ case V4L2_PIX_FMT_YVYU: /* fall through */
+ case V4L2_PIX_FMT_VYUY: /* fall through */
+ if (ctx->overlay.mode == FIMC_OVLY_NONE_SINGLE_BUF)
+ buf_set.base[FIMC_ADDR_Y] =
+ (dma_addr_t)ctx->fbuf.base;
+ else
+ buf_set.base[FIMC_ADDR_Y] =
+ ctx->dst[idx].base[FIMC_ADDR_Y];
+ break;
+ case V4L2_PIX_FMT_YUV420:
+ if (ctx->overlay.mode == FIMC_OVLY_NONE_SINGLE_BUF) {
+ buf_set.base[FIMC_ADDR_Y] =
+ (dma_addr_t)ctx->fbuf.base;
+ buf_set.base[FIMC_ADDR_CB] =
+ buf_set.base[FIMC_ADDR_Y] + y_size;
+ buf_set.base[FIMC_ADDR_CR] =
+ buf_set.base[FIMC_ADDR_CB] + c_size;
+ } else {
+ buf_set.base[FIMC_ADDR_Y] =
+ ctx->dst[idx].base[FIMC_ADDR_Y];
+ buf_set.base[FIMC_ADDR_CB] =
+ ctx->dst[idx].base[FIMC_ADDR_CB];
+ buf_set.base[FIMC_ADDR_CR] =
+ ctx->dst[idx].base[FIMC_ADDR_CR];
+ }
+ break;
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_NV16:
+ case V4L2_PIX_FMT_NV61:
+ case V4L2_PIX_FMT_NV12T:
+ if (ctx->overlay.mode == FIMC_OVLY_NONE_SINGLE_BUF) {
+ buf_set.base[FIMC_ADDR_Y] =
+ (dma_addr_t)ctx->fbuf.base;
+ buf_set.base[FIMC_ADDR_CB] =
+ buf_set.base[FIMC_ADDR_Y] + y_size;
+ } else {
+ buf_set.base[FIMC_ADDR_Y] =
+ ctx->dst[idx].base[FIMC_ADDR_Y];
+ buf_set.base[FIMC_ADDR_CB] =
+ ctx->dst[idx].base[FIMC_ADDR_CB];
+ }
+ break;
+ default:
+ fimc_err("%s: Invalid pixelformt : %d\n", \
+ __func__, format);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < FIMC_PHYBUFS; i++)
+ fimc_hwset_output_address(ctrl, &buf_set, i);
+
+ return 0;
+}
+
+
+static int fimc_qbuf_output_single_buf(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx,
+ int idx)
+{
+ int ret = -1;
+
+ fimc_outdev_set_src_addr(ctrl, ctx->src[idx].base);
+
+ ret = fimc_output_set_dst_addr(ctrl, ctx, idx);
+ if (ret < 0) {
+ fimc_err("%s: Fail: fimc_output_set_dst_addr\n", __func__);
+ return -EINVAL;
+ }
+
+ ctrl->out->idxs.active.idx = idx;
+ ctrl->out->idxs.active.ctx = ctx->ctx_num;
+
+ ctrl->status = FIMC_STREAMON;
+ ctx->status = FIMC_STREAMON;
+
+ ret = fimc_outdev_start_camif(ctrl);
+ if (ret < 0) {
+ fimc_err("Fail: fimc_start_camif\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int fimc_qbuf_output_multi_buf(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx,
+ int idx)
+{
+ int ret = -1;
+
+ fimc_outdev_set_src_addr(ctrl, ctx->src[idx].base);
+
+ fimc_output_set_dst_addr(ctrl, ctx, idx);
+ if (ret < 0) {
+ fimc_err("%s: Fail: fimc_output_set_dst_addr\n", __func__);
+ return -EINVAL;
+ }
+
+ ret = fimc_outdev_start_camif(ctrl);
+ if (ret < 0) {
+ fimc_err("Fail: fimc_start_camif\n");
+ return -EINVAL;
+ }
+
+ ctrl->out->idxs.active.idx = idx;
+ ctrl->out->idxs.active.ctx = ctx->ctx_num;
+
+ ctrl->status = FIMC_STREAMON;
+ ctx->status = FIMC_STREAMON;
+
+ return 0;
+}
+
+static int fimc_qbuf_output_dma_auto(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx,
+ int idx)
+{
+ struct fb_var_screeninfo var;
+ struct fb_info *fbinfo;
+ struct s3cfb_window *win;
+ struct v4l2_rect fimd_rect;
+ struct fimc_buf_set buf_set; /* destination addr */
+ int ret = -1, i;
+
+ switch (ctx->status) {
+ case FIMC_READY_ON:
+ fbinfo = registered_fb[ctx->overlay.fb_id];
+ win = (struct s3cfb_window *)fbinfo->par;
+
+ memcpy(&var, &fbinfo->var, sizeof(struct fb_var_screeninfo));
+ memset(&fimd_rect, 0, sizeof(struct v4l2_rect));
+ ret = fimc_fimd_rect(ctrl, ctx, &fimd_rect);
+ if (ret < 0) {
+ fimc_err("fimc_fimd_rect fail\n");
+ return -EINVAL;
+ }
+
+ /* set window path & owner */
+ win->path = DATA_PATH_DMA;
+ win->owner = DMA_MEM_OTHER;
+ win->other_mem_addr = ctx->dst[1].base[FIMC_ADDR_Y];
+ win->other_mem_size = ctx->dst[1].length[FIMC_ADDR_Y];
+
+ /* Update WIN size */
+ var.xres_virtual = fimd_rect.width;
+ var.yres_virtual = fimd_rect.height;
+ var.xres = fimd_rect.width;
+ var.yres = fimd_rect.height;
+
+ /* Update WIN position */
+ win->x = fimd_rect.left;
+ win->y = fimd_rect.top;
+
+ var.activate = FB_ACTIVATE_FORCE;
+ ret = fb_set_var(fbinfo, &var);
+ if (ret < 0) {
+ fimc_err("fb_set_var fail (ret=%d)\n", ret);
+ return -EINVAL;
+ }
+
+ /* fall through */
+
+ case FIMC_STREAMON_IDLE:
+ fimc_outdev_set_src_addr(ctrl, ctx->src[idx].base);
+
+ memset(&buf_set, 0x00, sizeof(buf_set));
+ buf_set.base[FIMC_ADDR_Y] = ctx->dst[idx].base[FIMC_ADDR_Y];
+
+ for (i = 0; i < FIMC_PHYBUFS; i++)
+ fimc_hwset_output_address(ctrl, &buf_set, i);
+
+ ret = fimc_outdev_start_camif(ctrl);
+ if (ret < 0) {
+ fimc_err("Fail: fimc_start_camif\n");
+ return -EINVAL;
+ }
+
+ ctrl->out->idxs.active.idx = idx;
+ ctrl->out->idxs.active.ctx = ctx->ctx_num;
+
+ ctrl->status = FIMC_STREAMON;
+ ctx->status = FIMC_STREAMON;
+
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int fimc_qbuf_output_dma_manual(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx,
+ int idx)
+{
+ struct fimc_buf_set buf_set; /* destination addr */
+ int ret = -1, i;
+
+ fimc_outdev_set_src_addr(ctrl, ctx->src[idx].base);
+
+ memset(&buf_set, 0x00, sizeof(buf_set));
+ buf_set.base[FIMC_ADDR_Y] = ctx->dst[idx].base[FIMC_ADDR_Y];
+
+ for (i = 0; i < FIMC_PHYBUFS; i++)
+ fimc_hwset_output_address(ctrl, &buf_set, i);
+
+ ret = fimc_outdev_start_camif(ctrl);
+ if (ret < 0) {
+ fimc_err("Fail: fimc_start_camif\n");
+ return -EINVAL;
+ }
+
+ ctrl->out->idxs.active.idx = idx;
+ ctrl->out->idxs.active.ctx = ctx->ctx_num;
+
+ ctrl->status = FIMC_STREAMON;
+ ctx->status = FIMC_STREAMON;
+
+ return 0;
+}
+
+static int fimc_update_in_queue_addr(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx,
+ u32 idx, dma_addr_t *addr)
+{
+ if (idx >= FIMC_OUTBUFS) {
+ fimc_err("%s: Failed\n", __func__);
+ return -EINVAL;
+ }
+
+ ctx->src[idx].base[FIMC_ADDR_Y] = addr[FIMC_ADDR_Y];
+ ctx->src[idx].base[FIMC_ADDR_CB] = addr[FIMC_ADDR_CB];
+ ctx->src[idx].base[FIMC_ADDR_CR] = addr[FIMC_ADDR_CR];
+
+ return 0;
+}
+
+int fimc_qbuf_output(void *fh, struct v4l2_buffer *b)
+{
+ struct fimc_buf *buf = (struct fimc_buf *)b->m.userptr;
+ struct fimc_ctx *ctx;
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
+ int idx, ctx_num;
+ int ret = -1;
+
+ ctx = &ctrl->out->ctx[ctx_id];
+ fimc_info2("ctx(%d) queued idx = %d\n", ctx->ctx_num, b->index);
+
+ if (b->index >= ctx->buf_num) {
+ fimc_err("The index is out of bounds. "
+ "You requested %d buffers. "
+ "But you set the index as %d\n",
+ ctx->buf_num, b->index);
+ return -EINVAL;
+ }
+
+ /* Check the buffer state if the state is VIDEOBUF_IDLE. */
+ if (ctx->src[b->index].state != VIDEOBUF_IDLE) {
+ fimc_err("The index(%d) buffer must be dequeued state(%d)\n",
+ b->index, ctx->src[b->index].state);
+ return -EINVAL;
+ }
+
+ if (b->memory == V4L2_MEMORY_USERPTR) {
+ ret = fimc_update_in_queue_addr(ctrl, ctx, b->index, buf->base);
+ if (ret < 0)
+ return ret;
+ }
+
+ /* Attach the buffer to the incoming queue. */
+ ret = fimc_push_inq(ctrl, ctx, b->index);
+ if (ret < 0) {
+ fimc_err("Fail: fimc_push_inq\n");
+ return -EINVAL;
+ }
+
+ if ((ctrl->status == FIMC_READY_ON) ||
+ (ctrl->status == FIMC_STREAMON_IDLE)) {
+ ret = fimc_pop_inq(ctrl, &ctx_num, &idx);
+ if (ret < 0) {
+ fimc_err("Fail: fimc_pop_inq\n");
+ return -EINVAL;
+ }
+
+ fimc_clk_en(ctrl, true);
+
+ ctx = &ctrl->out->ctx[ctx_num];
+ if (ctx_num != ctrl->out->last_ctx) {
+ ctrl->out->last_ctx = ctx->ctx_num;
+ fimc_outdev_set_ctx_param(ctrl, ctx);
+ }
+
+ switch (ctx->overlay.mode) {
+ case FIMC_OVLY_DMA_AUTO:
+ ret = fimc_qbuf_output_dma_auto(ctrl, ctx, idx);
+ break;
+ case FIMC_OVLY_DMA_MANUAL:
+ ret = fimc_qbuf_output_dma_manual(ctrl, ctx, idx);
+ break;
+ case FIMC_OVLY_NONE_SINGLE_BUF:
+ ret = fimc_qbuf_output_single_buf(ctrl, ctx, idx);
+ break;
+ case FIMC_OVLY_NONE_MULTI_BUF:
+ ret = fimc_qbuf_output_multi_buf(ctrl, ctx, idx);
+ break;
+ default:
+ break;
+ }
+ }
+
+ return ret;
+}
+
+int fimc_dqbuf_output(void *fh, struct v4l2_buffer *b)
+{
+ struct fimc_ctx *ctx;
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
+ int idx = -1, ret = -1;
+
+ ctx = &ctrl->out->ctx[ctx_id];
+ ret = fimc_pop_outq(ctrl, ctx, &idx);
+ if (ret < 0) {
+ ret = wait_event_timeout(ctrl->wq, (ctx->outq[0] != -1),
+ FIMC_DQUEUE_TIMEOUT);
+ if (ret == 0) {
+ fimc_dump_context(ctrl, ctx);
+ fimc_err("[0] out_queue is empty\n");
+ ctx->status = FIMC_STREAMON_IDLE;
+ return -EAGAIN;
+ } else if (ret == -ERESTARTSYS) {
+ fimc_print_signal(ctrl);
+ } else {
+ /* Normal case */
+ ret = fimc_pop_outq(ctrl, ctx, &idx);
+ if (ret < 0) {
+ fimc_err("[1] out_queue is empty\n");
+ fimc_dump_context(ctrl, ctx);
+ return -EINVAL;
+ }
+ }
+ }
+
+ mutex_lock(&ctrl->lock);
+ if (ctx->overlay.mode == FIMC_OVLY_DMA_AUTO && ctrl->fb.is_enable == 0) {
+ ret = fb_blank(registered_fb[ctx->overlay.fb_id],
+ FB_BLANK_UNBLANK);
+ if (ret < 0) {
+ fimc_err("%s: fb_blank: fb[%d] " \
+ "mode=FB_BLANK_UNBLANK\n",
+ __func__, ctx->overlay.fb_id);
+ mutex_unlock(&ctrl->lock);
+ return -EINVAL;
+ }
+ ctrl->fb.is_enable = 1;
+ }
+ mutex_unlock(&ctrl->lock);
+
+ b->index = idx;
+
+ fimc_info2("ctx(%d) dqueued idx = %d\n", ctx->ctx_num, b->index);
+
+ return ret;
+}
+
+int fimc_g_fmt_vid_out(struct file *filp, void *fh, struct v4l2_format *f)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ struct fimc_outinfo *out = ctrl->out;
+ struct fimc_ctx *ctx;
+ int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
+ int i, j;
+
+ fimc_info1("%s: called\n", __func__);
+
+ if (ctrl->cap) {
+ fimc_err("%s: fimc is already used for capture mode\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ if (!out) {
+ out = kzalloc(sizeof(*out), GFP_KERNEL);
+ if (!out) {
+ fimc_err("%s: no memory for outdev info\n", __func__);
+ return -ENOMEM;
+ }
+ ctrl->out = out;
+
+ /* init: struct fimc_outinfo */
+ out->last_ctx = -1;
+
+ spin_lock_init(&ctrl->out->lock_in);
+ spin_lock_init(&ctrl->out->lock_out);
+
+ for (i = 0; i < FIMC_INQUEUES; i++) {
+ ctrl->out->inq[i].ctx = -1;
+ ctrl->out->inq[i].idx = -1;
+ }
+
+ for (i = 0; i < FIMC_MAX_CTXS; i++) {
+ ctx = &ctrl->out->ctx[i];
+ ctx->ctx_num = i;
+ ctx->overlay.mode = FIMC_OVLY_NOT_FIXED;
+ ctx->status = FIMC_STREAMOFF;
+
+ for (j = 0; j < FIMC_OUTBUFS; j++) {
+ ctx->inq[j] = -1;
+ ctx->outq[j] = -1;
+ }
+ }
+
+ ctrl->out->idxs.prev.ctx = -1;
+ ctrl->out->idxs.prev.idx = -1;
+ ctrl->out->idxs.active.ctx = -1;
+ ctrl->out->idxs.active.idx = -1;
+ ctrl->out->idxs.next.ctx = -1;
+ ctrl->out->idxs.next.idx = -1;
+ }
+
+ f->fmt.pix = ctrl->out->ctx[ctx_id].pix;
+
+ return 0;
+}
+
+int fimc_try_fmt_vid_out(struct file *filp, void *fh, struct v4l2_format *f)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
+ struct fimc_ctx *ctx;
+ u32 format = f->fmt.pix.pixelformat;
+
+ fimc_info1("%s: called. width(%d), height(%d)\n", __func__,
+ f->fmt.pix.width, f->fmt.pix.height);
+
+ ctx = &ctrl->out->ctx[ctx_id];
+ if (ctx->status != FIMC_STREAMOFF) {
+ fimc_err("FIMC is running\n");
+ return -EBUSY;
+ }
+
+ /* Check pixel format */
+ switch (format) {
+ case V4L2_PIX_FMT_NV16: /* fall through */
+ case V4L2_PIX_FMT_NV61: /* fall through */
+ case V4L2_PIX_FMT_NV12: /* fall through */
+ case V4L2_PIX_FMT_NV12T: /* fall through */
+ case V4L2_PIX_FMT_NV21: /* fall through */
+ case V4L2_PIX_FMT_YUYV: /* fall through */
+ case V4L2_PIX_FMT_UYVY: /* fall through */
+ case V4L2_PIX_FMT_YVYU: /* fall through */
+ case V4L2_PIX_FMT_VYUY: /* fall through */
+ case V4L2_PIX_FMT_RGB32: /* fall through */
+ case V4L2_PIX_FMT_RGB565: /* fall through */
+ case V4L2_PIX_FMT_YUV420:
+ break;
+ default:
+ fimc_warn("Supported format : \
+ V4L2_PIX_FMT_YUYV, V4L2_PIX_FMT_UYVY, \
+ V4L2_PIX_FMT_YVYU, V4L2_PIX_FMT_VYUY, \
+ V4L2_PIX_FMT_NV12, V4L2_PIX_FMT_NV12T, \
+ V4L2_PIX_FMT_NV21, V4L2_PIX_FMT_RGB32, \
+ V4L2_PIX_FMT_RGB565\n");
+ fimc_warn("Changed format : V4L2_PIX_FMT_RGB32\n");
+ f->fmt.pix.pixelformat = V4L2_PIX_FMT_RGB32;
+ return -EINVAL;
+ }
+
+ /* Fill the return value. */
+ switch (format) {
+ case V4L2_PIX_FMT_RGB32:
+ f->fmt.pix.bytesperline = f->fmt.pix.width << 2;
+ break;
+ case V4L2_PIX_FMT_NV16: /* fall through */
+ case V4L2_PIX_FMT_NV61: /* fall through */
+ case V4L2_PIX_FMT_YUYV: /* fall through */
+ case V4L2_PIX_FMT_UYVY: /* fall through */
+ case V4L2_PIX_FMT_YVYU: /* fall through */
+ case V4L2_PIX_FMT_VYUY: /* fall through */
+ case V4L2_PIX_FMT_RGB565:
+ f->fmt.pix.bytesperline = f->fmt.pix.width << 1;
+ break;
+ case V4L2_PIX_FMT_YUV420: /* fall through */
+ case V4L2_PIX_FMT_NV12: /* fall through */
+ case V4L2_PIX_FMT_NV21: /* fall through */
+ case V4L2_PIX_FMT_NV12T:
+ f->fmt.pix.bytesperline = (f->fmt.pix.width * 3) >> 1;
+ break;
+
+ default:
+ /* dummy value*/
+ f->fmt.pix.bytesperline = f->fmt.pix.width;
+ }
+
+ f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height;
+
+ return 0;
+}
+
+int fimc_s_fmt_vid_out(struct file *filp, void *fh, struct v4l2_format *f)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
+ struct fimc_ctx *ctx;
+ int ret = -1;
+
+ fimc_info1("%s: called\n", __func__);
+
+ /* Check stream status */
+ ctx = &ctrl->out->ctx[ctx_id];
+ if (ctx->status != FIMC_STREAMOFF) {
+ fimc_err("FIMC is running\n");
+ return -EBUSY;
+ }
+
+ ret = fimc_try_fmt_vid_out(filp, fh, f);
+ if (ret < 0)
+ return ret;
+
+ ctx->pix = f->fmt.pix;
+
+ return ret;
+}
+
+int fimc_init_in_queue(struct fimc_control *ctrl, struct fimc_ctx *ctx)
+{
+ struct fimc_idx swap_queue[FIMC_INQUEUES];
+ int swap_cnt = 0, i;
+ unsigned long spin_flags;
+
+ spin_lock_irqsave(&ctrl->out->lock_in, spin_flags);
+
+ /* init incoming queue */
+ for (i = 0; i < FIMC_OUTBUFS; i++)
+ ctx->inq[i] = -1;
+
+ /* init common incoming queue */
+ for (i = 0; i < FIMC_INQUEUES; i++) {
+ if (ctrl->out->inq[i].ctx != ctx->ctx_num) {
+ swap_queue[swap_cnt].ctx = ctrl->out->inq[i].ctx;
+ swap_queue[swap_cnt].idx = ctrl->out->inq[i].idx;
+ swap_cnt++;
+ }
+
+ ctrl->out->inq[i].ctx = -1;
+ ctrl->out->inq[i].idx = -1;
+ }
+
+ /* restore common incoming queue */
+ for (i = 0; i < swap_cnt; i++) {
+ ctrl->out->inq[i].ctx = swap_queue[i].ctx;
+ ctrl->out->inq[i].idx = swap_queue[i].idx;
+ }
+
+ spin_unlock_irqrestore(&ctrl->out->lock_in, spin_flags);
+
+ return 0;
+}
+
+int fimc_init_out_queue(struct fimc_control *ctrl, struct fimc_ctx *ctx)
+{
+ unsigned long spin_flags;
+ int i;
+
+ spin_lock_irqsave(&ctrl->out->lock_out, spin_flags);
+
+ /* Init incoming queue */
+ for (i = 0; i < FIMC_OUTBUFS; i++)
+ ctx->outq[i] = -1;
+
+ spin_unlock_irqrestore(&ctrl->out->lock_out, spin_flags);
+
+ return 0;
+}
+
+int fimc_push_inq(struct fimc_control *ctrl, struct fimc_ctx *ctx, int idx)
+{
+ struct fimc_idx swap_common_inq[FIMC_INQUEUES];
+ int swap_queue[FIMC_OUTBUFS];
+ int i;
+ unsigned long spin_flags;
+
+ fimc_dbg("%s: idx = %d\n", __func__, idx);
+
+ if (ctrl->out->inq[FIMC_INQUEUES-1].idx != -1) {
+ fimc_err("FULL: common incoming queue\n");
+ return -EBUSY;
+ }
+
+ spin_lock_irqsave(&ctrl->out->lock_in, spin_flags);
+
+ /* ctx own incoming queue */
+ /* Backup original queue */
+ for (i = 0; i < FIMC_OUTBUFS; i++)
+ swap_queue[i] = ctx->inq[i];
+
+ /* Attach new idx */
+ ctx->inq[0] = idx;
+ ctx->src[idx].state = VIDEOBUF_QUEUED;
+ ctx->src[idx].flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED;
+
+ /* Shift the origonal queue */
+ for (i = 1; i < FIMC_OUTBUFS; i++)
+ ctx->inq[i] = swap_queue[i-1];
+
+ /* Common incoming queue */
+ /* Backup original queue */
+ for (i = 0; i < FIMC_INQUEUES; i++) {
+ swap_common_inq[i].ctx = ctrl->out->inq[i].ctx;
+ swap_common_inq[i].idx = ctrl->out->inq[i].idx;
+ }
+
+ /* Attach new idx */
+ ctrl->out->inq[0].ctx = ctx->ctx_num;
+ ctrl->out->inq[0].idx = idx;
+
+ /* Shift the origonal queue */
+ for (i = 1; i < FIMC_INQUEUES; i++) {
+ ctrl->out->inq[i].ctx = swap_common_inq[i-1].ctx;
+ ctrl->out->inq[i].idx = swap_common_inq[i-1].idx;
+ }
+
+ spin_unlock_irqrestore(&ctrl->out->lock_in, spin_flags);
+
+ return 0;
+}
+
+int fimc_pop_inq(struct fimc_control *ctrl, int *ctx_num, int *idx)
+{
+ struct fimc_ctx *ctx;
+ unsigned long spin_flags;
+ int i, ret = 0;
+ int ctx_idx = -1;
+
+ spin_lock_irqsave(&ctrl->out->lock_in, spin_flags);
+
+ /* find valid index from common incoming queue */
+ for (i = (FIMC_INQUEUES-1); i >= 0; i--) {
+ if (ctrl->out->inq[i].ctx != -1) {
+ *ctx_num = ctrl->out->inq[i].ctx;
+ *idx = ctrl->out->inq[i].idx;
+ ctrl->out->inq[i].ctx = -1;
+ ctrl->out->inq[i].idx = -1;
+ break;
+ }
+ }
+
+ /* common incoming queue is empty. */
+ if (i < 0) {
+ spin_unlock_irqrestore(&ctrl->out->lock_in, spin_flags);
+ return -EINVAL;
+ }
+
+ /* find valid index from incoming queue. */
+ ctx = &ctrl->out->ctx[*ctx_num];
+ for (i = (FIMC_OUTBUFS-1); i >= 0; i--) {
+ if (ctx->inq[i] != -1) {
+ ctx_idx = ctx->inq[i];
+ ctx->inq[i] = -1;
+ ctx->src[ctx_idx].state = VIDEOBUF_ACTIVE;
+ ctx->src[ctx_idx].flags = V4L2_BUF_FLAG_MAPPED;
+ break;
+ }
+ }
+
+ if (*idx != ctx_idx)
+ fimc_err("common inq(%d) vs inq(%d) mismatch\n", *idx, ctx_idx);
+
+ /* incoming queue is empty. */
+ if (i < 0)
+ ret = -EINVAL;
+ else
+ fimc_dbg("%s: index = %d\n", __func__, *idx);
+
+ spin_unlock_irqrestore(&ctrl->out->lock_in, spin_flags);
+
+ return ret;
+}
+
+int fimc_push_outq(struct fimc_control *ctrl, struct fimc_ctx *ctx, int idx)
+{
+ unsigned long spin_flags;
+ int swap_queue[FIMC_OUTBUFS];
+ int i;
+
+ fimc_dbg("%s: index = %d\n", __func__, idx);
+
+ spin_lock_irqsave(&ctrl->out->lock_out, spin_flags);
+
+ /* Backup original queue */
+ for (i = 0; i < FIMC_OUTBUFS; i++)
+ swap_queue[i] = ctx->outq[i];
+
+ /* Attach new index */
+ ctx->outq[0] = idx;
+ ctx->src[idx].state = VIDEOBUF_DONE;
+ ctx->src[idx].flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_DONE;
+
+ /* Shift the origonal queue */
+ for (i = 1; i < FIMC_OUTBUFS; i++)
+ ctx->outq[i] = swap_queue[i-1];
+
+ spin_unlock_irqrestore(&ctrl->out->lock_out, spin_flags);
+
+ return 0;
+}
+
+int fimc_pop_outq(struct fimc_control *ctrl, struct fimc_ctx *ctx, int *idx)
+{
+ unsigned long spin_flags;
+ int i, ret = 0;
+
+ spin_lock_irqsave(&ctrl->out->lock_out, spin_flags);
+
+ /* Find last valid idx in outgoing queue. */
+ for (i = (FIMC_OUTBUFS-1); i >= 0; i--) {
+ if (ctx->outq[i] != -1) {
+ *idx = ctx->outq[i];
+ ctx->outq[i] = -1;
+ ctx->src[*idx].state = VIDEOBUF_IDLE;
+ ctx->src[*idx].flags = V4L2_BUF_FLAG_MAPPED;
+ break;
+ }
+ }
+
+ /* outgoing queue is empty. */
+ if (i < 0) {
+ ret = -EINVAL;
+ fimc_dbg("%s: outgoing queue : %d, %d, %d\n", __func__,
+ ctx->outq[0], ctx->outq[1], ctx->outq[2]);
+ } else
+ fimc_dbg("%s: idx = %d\n", __func__, *idx);
+
+
+ spin_unlock_irqrestore(&ctrl->out->lock_out, spin_flags);
+
+ return ret;
+}
+
+void fimc_dump_context(struct fimc_control *ctrl, struct fimc_ctx *ctx)
+{
+ int i = 0;
+
+ fimc_err("ctx%d, ctrl->status: %d, ctx->status: %d\n",
+ ctx->ctx_num, ctrl->status, ctx->status);
+
+ for (i = 0; i < FIMC_INQUEUES; i++)
+ fimc_err("ctrl->inq[%d]: ctx(%d) idx(%d)\n",
+ i, ctrl->out->inq[i].ctx, ctrl->out->inq[i].idx);
+
+ for (i = 0; i < FIMC_OUTBUFS; i++)
+ fimc_err("inq[%d] = %d\n", i, ctx->inq[i]);
+
+ for (i = 0; i < FIMC_OUTBUFS; i++)
+ fimc_err("outq[%d] = %d\n", i, ctx->outq[i]);
+
+ fimc_err("state : prev.ctx(%d), prev.idx(%d) "
+ "active.ctx(%d), active.idx(%d) "
+ "next.ctx(%d), next.idx(%d)\n",
+ ctrl->out->idxs.prev.ctx, ctrl->out->idxs.prev.idx,
+ ctrl->out->idxs.active.ctx, ctrl->out->idxs.active.idx,
+ ctrl->out->idxs.next.ctx, ctrl->out->idxs.next.idx);
+}
+
+void fimc_print_signal(struct fimc_control *ctrl)
+{
+ if (signal_pending(current)) {
+ fimc_dbg(".pend=%.8lx shpend=%.8lx\n",
+ current->pending.signal.sig[0],
+ current->signal->shared_pending.signal.sig[0]);
+ } else {
+ fimc_dbg(":pend=%.8lx shpend=%.8lx\n",
+ current->pending.signal.sig[0],
+ current->signal->shared_pending.signal.sig[0]);
+ }
+}
diff --git a/drivers/media/video/samsung/fimc/fimc_overlay.c b/drivers/media/video/samsung/fimc/fimc_overlay.c
new file mode 100644
index 0000000..ff43c2e
--- /dev/null
+++ b/drivers/media/video/samsung/fimc/fimc_overlay.c
@@ -0,0 +1,312 @@
+/* linux/drivers/media/video/samsung/fimc/fimc_overlay.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * V4L2 Overlay device support file for Samsung Camera Interface (FIMC) 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/slab.h>
+#include <linux/bootmem.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <plat/media.h>
+
+#include "fimc.h"
+
+int fimc_try_fmt_overlay(struct file *filp, void *fh, struct v4l2_format *f)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
+ struct fimc_ctx *ctx;
+
+ u32 is_rotate = 0;
+ ctx = &ctrl->out->ctx[ctx_id];
+
+ fimc_info1("%s: top(%d) left(%d) width(%d) height(%d)\n", __func__,
+ f->fmt.win.w.top, f->fmt.win.w.left,
+ f->fmt.win.w.width, f->fmt.win.w.height);
+
+ if (ctx->overlay.mode == FIMC_OVLY_NONE_SINGLE_BUF ||
+ (ctx->overlay.mode == FIMC_OVLY_NONE_MULTI_BUF))
+ return 0;
+
+ /* Check Overlay Size : Overlay size must be smaller than LCD size. */
+ is_rotate = fimc_mapping_rot_flip(ctx->rotate, ctx->flip);
+ if (is_rotate & FIMC_ROT) { /* Landscape mode */
+ if (f->fmt.win.w.width > ctrl->fb.lcd_vres) {
+ fimc_warn("The width is changed %d -> %d\n",
+ f->fmt.win.w.width, ctrl->fb.lcd_vres);
+ f->fmt.win.w.width = ctrl->fb.lcd_vres;
+ }
+
+ if (f->fmt.win.w.height > ctrl->fb.lcd_hres) {
+ fimc_warn("The height is changed %d -> %d\n",
+ f->fmt.win.w.height, ctrl->fb.lcd_hres);
+ f->fmt.win.w.height = ctrl->fb.lcd_hres;
+ }
+ } else { /* Portrait mode */
+ if (f->fmt.win.w.width > ctrl->fb.lcd_hres) {
+ fimc_warn("The width is changed %d -> %d\n",
+ f->fmt.win.w.width, ctrl->fb.lcd_hres);
+ f->fmt.win.w.width = ctrl->fb.lcd_hres;
+ }
+
+ if (f->fmt.win.w.height > ctrl->fb.lcd_vres) {
+ fimc_warn("The height is changed %d -> %d\n",
+ f->fmt.win.w.height, ctrl->fb.lcd_vres);
+ f->fmt.win.w.height = ctrl->fb.lcd_vres;
+ }
+ }
+
+ return 0;
+}
+
+int fimc_g_fmt_vid_overlay(struct file *filp, void *fh, struct v4l2_format *f)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
+ struct fimc_ctx *ctx;
+
+ ctx = &ctrl->out->ctx[ctx_id];
+
+ fimc_info1("%s: called\n", __func__);
+
+ f->fmt.win = ctx->win;
+
+ return 0;
+}
+
+static int fimc_check_pos(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx,
+ struct v4l2_format *f)
+{
+ if (ctx->win.w.width != f->fmt.win.w.width) {
+ fimc_err("%s: cannot change width\n", __func__);
+ return -EINVAL;
+ } else if (ctx->win.w.height != f->fmt.win.w.height) {
+ fimc_err("%s: cannot change height\n", __func__);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int fimc_change_fifo_position(struct fimc_control *ctrl,
+ struct fimc_ctx *ctx) {
+ struct v4l2_rect fimd_rect;
+ struct fb_info *fbinfo;
+ struct s3cfb_window *win;
+ int ret = -1;
+
+ fbinfo = registered_fb[ctx->overlay.fb_id];
+
+ memset(&fimd_rect, 0, sizeof(struct v4l2_rect));
+
+ ret = fimc_fimd_rect(ctrl, ctx, &fimd_rect);
+ if (ret < 0) {
+ fimc_err("fimc_fimd_rect fail\n");
+ return -EINVAL;
+ }
+
+ /* Update WIN position */
+ win->x = fimd_rect.left;
+ win->y = fimd_rect.top;
+
+ fbinfo->var.activate = FB_ACTIVATE_FORCE;
+ ret = fb_set_var(fbinfo, &fbinfo->var);
+ if (ret < 0) {
+ fimc_err("fb_set_var fail (ret=%d)\n", ret);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int fimc_s_fmt_vid_overlay(struct file *filp, void *fh, struct v4l2_format *f)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
+ struct fimc_ctx *ctx;
+ int ret = -1;
+ ctx = &ctrl->out->ctx[ctx_id];
+
+ fimc_info1("%s: called\n", __func__);
+
+ switch (ctx->status) {
+ case FIMC_STREAMON:
+ ret = fimc_check_pos(ctrl, ctx, f);
+ if (ret < 0) {
+ fimc_err("When FIMC is running, "
+ "you can only move the position.\n");
+ return -EBUSY;
+ }
+
+ ret = fimc_try_fmt_overlay(filp, fh, f);
+ if (ret < 0)
+ return ret;
+
+ ctx->win = f->fmt.win;
+ fimc_change_fifo_position(ctrl, ctx);
+
+ break;
+ case FIMC_STREAMOFF:
+ ret = fimc_try_fmt_overlay(filp, fh, f);
+ if (ret < 0)
+ return ret;
+ ctx->win = f->fmt.win;
+
+ break;
+
+ default:
+ fimc_err("FIMC is running\n");
+ return -EBUSY;
+ }
+
+ return ret;
+}
+
+int fimc_g_fbuf(struct file *filp, void *fh, struct v4l2_framebuffer *fb)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
+ struct fimc_ctx *ctx;
+ u32 bpp = 1, format;
+
+ ctx = &ctrl->out->ctx[ctx_id];
+
+ fimc_info1("%s: called\n", __func__);
+
+ fb->capability = ctx->fbuf.capability;
+ fb->flags = 0;
+ fb->base = ctx->fbuf.base;
+
+ fb->fmt.width = ctx->fbuf.fmt.width;
+ fb->fmt.height = ctx->fbuf.fmt.height;
+ fb->fmt.pixelformat = ctx->fbuf.fmt.pixelformat;
+ format = ctx->fbuf.fmt.pixelformat;
+
+ switch (format) {
+ case V4L2_PIX_FMT_YUV420: /* fall through */
+ case V4L2_PIX_FMT_NV12:
+ bpp = 1;
+ break;
+ case V4L2_PIX_FMT_RGB565:
+ bpp = 2;
+ break;
+ case V4L2_PIX_FMT_RGB32:
+ bpp = 4;
+ break;
+ }
+
+ ctx->fbuf.fmt.bytesperline = fb->fmt.width * bpp;
+ fb->fmt.bytesperline = ctx->fbuf.fmt.bytesperline;
+ fb->fmt.sizeimage = ctx->fbuf.fmt.sizeimage;
+ fb->fmt.colorspace = V4L2_COLORSPACE_SMPTE170M;
+ fb->fmt.priv = 0;
+
+ return 0;
+}
+
+int fimc_s_fbuf(struct file *filp, void *fh, struct v4l2_framebuffer *fb)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ctx_id = ((struct fimc_prv_data *)fh)->ctx_id;
+ struct fimc_ctx *ctx;
+ u32 bpp = 1;
+ u32 format = fb->fmt.pixelformat;
+ ctx = &ctrl->out->ctx[ctx_id];
+
+ fimc_info1("%s: called. width(%d), height(%d)\n",
+ __func__, fb->fmt.width, fb->fmt.height);
+
+ ctx->fbuf.capability = V4L2_FBUF_CAP_EXTERNOVERLAY;
+ ctx->fbuf.flags = 0;
+ ctx->fbuf.base = fb->base;
+
+ if (ctx->overlay.mode == FIMC_OVLY_NONE_MULTI_BUF) {
+ ctx->fbuf.fmt.width = fb->fmt.width;
+ ctx->fbuf.fmt.height = fb->fmt.height;
+ ctx->fbuf.fmt.pixelformat = fb->fmt.pixelformat;
+
+ switch (format) {
+ case V4L2_PIX_FMT_YUV420: /* fall through */
+ case V4L2_PIX_FMT_NV12:
+ bpp = 1;
+ break;
+ case V4L2_PIX_FMT_RGB565:
+ bpp = 2;
+ break;
+ case V4L2_PIX_FMT_RGB32:
+ bpp = 4;
+ break;
+ }
+
+ ctx->fbuf.fmt.bytesperline = fb->fmt.width * bpp;
+ ctx->fbuf.fmt.sizeimage = fb->fmt.sizeimage;
+ ctx->fbuf.fmt.colorspace = V4L2_COLORSPACE_SMPTE170M;
+ ctx->fbuf.fmt.priv = 0;
+ } else if (fb->base) {
+ ctx->fbuf.fmt.width = fb->fmt.width;
+ ctx->fbuf.fmt.height = fb->fmt.height;
+ ctx->fbuf.fmt.pixelformat = fb->fmt.pixelformat;
+
+ switch (format) {
+ case V4L2_PIX_FMT_YUV420: /* fall through */
+ case V4L2_PIX_FMT_NV12:
+ bpp = 1;
+ break;
+ case V4L2_PIX_FMT_RGB565:
+ bpp = 2;
+ break;
+ case V4L2_PIX_FMT_RGB32:
+ bpp = 4;
+ break;
+ }
+
+ ctx->fbuf.fmt.bytesperline = fb->fmt.width * bpp;
+ ctx->fbuf.fmt.sizeimage = fb->fmt.sizeimage;
+ ctx->fbuf.fmt.colorspace = V4L2_COLORSPACE_SMPTE170M;
+ ctx->fbuf.fmt.priv = 0;
+
+ ctx->overlay.mode = FIMC_OVLY_NONE_SINGLE_BUF;
+ } else {
+ int i;
+ struct s3cfb_window *win = NULL;
+ ctx->overlay.fb_id = -1;
+
+ for (i = 0; i < num_registered_fb; i++) {
+ win = (struct s3cfb_window *)registered_fb[i]->par;
+ if (win->id == ctrl->id) {
+ ctx->overlay.fb_id = i;
+ fimc_info2("%s: overlay.fb_id = %d\n",
+ __func__, ctx->overlay.fb_id);
+ break;
+ }
+ }
+
+ if (-1 == ctx->overlay.fb_id) {
+ fimc_err("%s: fb[%d] is not registered. " \
+ "must be registered for overlay\n",
+ __func__, ctrl->id);
+ return -1;
+ }
+
+ if (1 == win->enabled) {
+ fimc_err("%s: fb[%d] is already being used. " \
+ "must be not used for overlay\n",
+ __func__, ctrl->id);
+ return -1;
+ }
+
+ ctx->overlay.mode = FIMC_OVLY_NOT_FIXED;
+ }
+
+ return 0;
+}
diff --git a/drivers/media/video/samsung/fimc/fimc_regs.c b/drivers/media/video/samsung/fimc/fimc_regs.c
new file mode 100644
index 0000000..227945a
--- /dev/null
+++ b/drivers/media/video/samsung/fimc/fimc_regs.c
@@ -0,0 +1,1801 @@
+/* linux/drivers/media/video/samsung/fimc/fimc_regs.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Register interface file for Samsung Camera Interface (FIMC) 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/delay.h>
+#include <linux/gpio.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_samsung.h>
+#include <linux/io.h>
+#include <mach/map.h>
+#include <plat/regs-fimc.h>
+#include <plat/fimc.h>
+
+#include "fimc.h"
+
+/* struct fimc_limit: Limits for FIMC */
+struct fimc_limit fimc40_limits[FIMC_DEVICES] = {
+ {
+ .pre_dst_w = 3264,
+ .bypass_w = 8192,
+ .trg_h_no_rot = 3264,
+ .trg_h_rot = 1280,
+ .real_w_no_rot = 8192,
+ .real_h_rot = 1280,
+ }, {
+ .pre_dst_w = 1280,
+ .bypass_w = 8192,
+ .trg_h_no_rot = 1280,
+ .trg_h_rot = 8192,
+ .real_w_no_rot = 8192,
+ .real_h_rot = 768,
+ }, {
+ .pre_dst_w = 1440,
+ .bypass_w = 8192,
+ .trg_h_no_rot = 1440,
+ .trg_h_rot = 0,
+ .real_w_no_rot = 8192,
+ .real_h_rot = 0,
+ },
+};
+
+struct fimc_limit fimc43_limits[FIMC_DEVICES] = {
+ {
+ .pre_dst_w = 4224,
+ .bypass_w = 8192,
+ .trg_h_no_rot = 4224,
+ .trg_h_rot = 1920,
+ .real_w_no_rot = 8192,
+ .real_h_rot = 1920,
+ }, {
+ .pre_dst_w = 4224,
+ .bypass_w = 8192,
+ .trg_h_no_rot = 4224,
+ .trg_h_rot = 1920,
+ .real_w_no_rot = 8192,
+ .real_h_rot = 1920,
+ }, {
+ .pre_dst_w = 1920,
+ .bypass_w = 8192,
+ .trg_h_no_rot = 1920,
+ .trg_h_rot = 1280,
+ .real_w_no_rot = 8192,
+ .real_h_rot = 1280,
+ },
+};
+
+struct fimc_limit fimc50_limits[FIMC_DEVICES] = {
+ {
+ .pre_dst_w = 4224,
+ .bypass_w = 8192,
+ .trg_h_no_rot = 4224,
+ .trg_h_rot = 1920,
+ .real_w_no_rot = 8192,
+ .real_h_rot = 1920,
+ }, {
+ .pre_dst_w = 4224,
+ .bypass_w = 8192,
+ .trg_h_no_rot = 4224,
+ .trg_h_rot = 1920,
+ .real_w_no_rot = 8192,
+ .real_h_rot = 1920,
+ }, {
+ .pre_dst_w = 1920,
+ .bypass_w = 8192,
+ .trg_h_no_rot = 1920,
+ .trg_h_rot = 1280,
+ .real_w_no_rot = 8192,
+ .real_h_rot = 1280,
+ },
+};
+
+int fimc_hwset_camera_source(struct fimc_control *ctrl)
+{
+ struct s3c_platform_camera *cam = ctrl->cam;
+ u32 cfg = 0;
+
+ /* for now, we support only ITU601 8 bit mode */
+ cfg |= S3C_CISRCFMT_ITU601_8BIT;
+ cfg |= cam->order422;
+
+ if (cam->type == CAM_TYPE_ITU)
+ cfg |= cam->fmt;
+
+ cfg |= S3C_CISRCFMT_SOURCEHSIZE(cam->width);
+ cfg |= S3C_CISRCFMT_SOURCEVSIZE(cam->height);
+
+ writel(cfg, ctrl->regs + S3C_CISRCFMT);
+
+ return 0;
+}
+
+int fimc_hwset_enable_irq(struct fimc_control *ctrl, int overflow, int level)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CIGCTRL);
+
+ cfg &= ~(S3C_CIGCTRL_IRQ_OVFEN | S3C_CIGCTRL_IRQ_LEVEL);
+ cfg |= S3C_CIGCTRL_IRQ_ENABLE;
+
+ if (overflow)
+ cfg |= S3C_CIGCTRL_IRQ_OVFEN;
+
+ if (level)
+ cfg |= S3C_CIGCTRL_IRQ_LEVEL;
+
+ writel(cfg, ctrl->regs + S3C_CIGCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_disable_irq(struct fimc_control *ctrl)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CIGCTRL);
+
+ cfg &= ~(S3C_CIGCTRL_IRQ_OVFEN | S3C_CIGCTRL_IRQ_ENABLE);
+ writel(cfg, ctrl->regs + S3C_CIGCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_clear_irq(struct fimc_control *ctrl)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CIGCTRL);
+
+ cfg |= S3C_CIGCTRL_IRQ_CLR;
+
+ writel(cfg, ctrl->regs + S3C_CIGCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_output_area_size(struct fimc_control *ctrl, u32 size)
+{
+ u32 cfg = 0;
+
+ cfg = S3C_CITAREA_TARGET_AREA(size);
+
+ writel(cfg, ctrl->regs + S3C_CITAREA);
+
+ return 0;
+}
+
+void fimc_wait_disable_capture(struct fimc_control *ctrl)
+{
+ unsigned long timeo = jiffies + 20; /* timeout of 100 ms */
+ u32 cfg;
+
+ if (!ctrl || !ctrl->cap ||
+ ctrl->cap->fmt.colorspace == V4L2_COLORSPACE_JPEG)
+ return;
+
+ while (time_before(jiffies, timeo)) {
+ cfg = readl(ctrl->regs + S3C_CISTATUS);
+
+ if (0 == (cfg & S3C_CISTATUS_IMGCPTEN))
+ break;
+
+ msleep(10);
+ }
+
+ dev_dbg(ctrl->dev, "IMGCPTEN: Wait time = %d ms\n",
+ jiffies_to_msecs(jiffies - timeo + 20));
+
+ return;
+}
+
+int fimc_hwset_image_effect(struct fimc_control *ctrl)
+{
+ u32 cfg = 0;
+
+ if (ctrl->fe.ie_on) {
+ if (ctrl->fe.ie_after_sc)
+ cfg |= S3C_CIIMGEFF_IE_SC_AFTER;
+
+ cfg |= S3C_CIIMGEFF_FIN(ctrl->fe.fin);
+
+ if (ctrl->fe.fin == FIMC_EFFECT_FIN_ARBITRARY_CBCR)
+ cfg |= S3C_CIIMGEFF_PAT_CB(ctrl->fe.pat_cb) |
+ S3C_CIIMGEFF_PAT_CR(ctrl->fe.pat_cr);
+
+ cfg |= S3C_CIIMGEFF_IE_ENABLE;
+ }
+
+ writel(cfg, ctrl->regs + S3C_CIIMGEFF);
+
+ return 0;
+}
+
+int fimc_hwset_shadow_enable(struct fimc_control *ctrl)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CIGCTRL);
+
+ cfg &= ~S3C_CIGCTRL_SHADOW_DISABLE;
+
+ writel(cfg, ctrl->regs + S3C_CIGCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_shadow_disable(struct fimc_control *ctrl)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CIGCTRL);
+
+ cfg |= S3C_CIGCTRL_SHADOW_DISABLE;
+
+ writel(cfg, ctrl->regs + S3C_CIGCTRL);
+
+ return 0;
+}
+
+static void fimc_reset_cfg(struct fimc_control *ctrl)
+{
+ int i;
+ u32 cfg[][2] = {
+ { 0x018, 0x00000000 }, { 0x01c, 0x00000000 },
+ { 0x020, 0x00000000 }, { 0x024, 0x00000000 },
+ { 0x028, 0x00000000 }, { 0x02c, 0x00000000 },
+ { 0x030, 0x00000000 }, { 0x034, 0x00000000 },
+ { 0x038, 0x00000000 }, { 0x03c, 0x00000000 },
+ { 0x040, 0x00000000 }, { 0x044, 0x00000000 },
+ { 0x048, 0x00000000 }, { 0x04c, 0x00000000 },
+ { 0x050, 0x00000000 }, { 0x054, 0x00000000 },
+ { 0x058, 0x18000000 }, { 0x05c, 0x00000000 },
+ { 0x0c0, 0x00000000 }, { 0x0c4, 0xffffffff },
+ { 0x0d0, 0x00100080 }, { 0x0d4, 0x00000000 },
+ { 0x0d8, 0x00000000 }, { 0x0dc, 0x00000000 },
+ { 0x0f8, 0x00000000 }, { 0x0fc, 0x04000000 },
+ { 0x168, 0x00000000 }, { 0x16c, 0x00000000 },
+ { 0x170, 0x00000000 }, { 0x174, 0x00000000 },
+ { 0x178, 0x00000000 }, { 0x17c, 0x00000000 },
+ { 0x180, 0x00000000 }, { 0x184, 0x00000000 },
+ { 0x188, 0x00000000 }, { 0x18c, 0x00000000 },
+ { 0x194, 0x0000001e },
+ };
+
+ for (i = 0; i < sizeof(cfg) / 8; i++)
+ writel(cfg[i][1], ctrl->regs + cfg[i][0]);
+}
+
+int fimc_hwset_reset(struct fimc_control *ctrl)
+{
+ u32 cfg = 0;
+
+ cfg = readl(ctrl->regs + S3C_CISRCFMT);
+ cfg |= S3C_CISRCFMT_ITU601_8BIT;
+ writel(cfg, ctrl->regs + S3C_CISRCFMT);
+
+ /* s/w reset */
+ cfg = readl(ctrl->regs + S3C_CIGCTRL);
+ cfg |= (S3C_CIGCTRL_SWRST);
+ writel(cfg, ctrl->regs + S3C_CIGCTRL);
+ mdelay(1);
+
+ cfg = readl(ctrl->regs + S3C_CIGCTRL);
+ cfg &= ~S3C_CIGCTRL_SWRST;
+ writel(cfg, ctrl->regs + S3C_CIGCTRL);
+
+ /* in case of ITU656, CISRCFMT[31] should be 0 */
+ if ((ctrl->cap != NULL) && (ctrl->cam->fmt == ITU_656_YCBCR422_8BIT)) {
+ cfg = readl(ctrl->regs + S3C_CISRCFMT);
+ cfg &= ~S3C_CISRCFMT_ITU601_8BIT;
+ writel(cfg, ctrl->regs + S3C_CISRCFMT);
+ }
+
+ fimc_reset_cfg(ctrl);
+
+ return 0;
+}
+
+int fimc_hwset_sw_reset(struct fimc_control *ctrl)
+{
+ u32 cfg = 0;
+
+ /* s/w reset */
+ cfg = readl(ctrl->regs + S3C_CIGCTRL);
+ cfg |= (S3C_CIGCTRL_SWRST);
+ writel(cfg, ctrl->regs + S3C_CIGCTRL);
+
+ cfg = readl(ctrl->regs + S3C_CIGCTRL);
+ cfg &= ~S3C_CIGCTRL_SWRST;
+ writel(cfg, ctrl->regs + S3C_CIGCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_clksrc(struct fimc_control *ctrl, int src_clk)
+{
+ u32 cfg = readl(ctrl->regs + S3C_MISC_FIMC);
+ cfg &= ~S3C_CLKSRC_HCLK_MASK;
+
+ if (src_clk == FIMC_HCLK)
+ cfg |= S3C_CLKSRC_HCLK;
+ else if (src_clk == FIMC_SCLK)
+ cfg |= S3C_CLKSRC_SCLK;
+
+ writel(cfg, ctrl->regs + S3C_MISC_FIMC);
+ return 0;
+}
+
+int fimc_hwget_overflow_state(struct fimc_control *ctrl)
+{
+ u32 cfg, status, flag;
+
+ status = readl(ctrl->regs + S3C_CISTATUS);
+ flag = S3C_CISTATUS_OVFIY | S3C_CISTATUS_OVFICB | S3C_CISTATUS_OVFICR;
+
+ if (status & flag) {
+ cfg = readl(ctrl->regs + S3C_CIWDOFST);
+ cfg |= (S3C_CIWDOFST_CLROVFIY | S3C_CIWDOFST_CLROVFICB |
+ S3C_CIWDOFST_CLROVFICR);
+ writel(cfg, ctrl->regs + S3C_CIWDOFST);
+
+ cfg = readl(ctrl->regs + S3C_CIWDOFST);
+ cfg &= ~(S3C_CIWDOFST_CLROVFIY | S3C_CIWDOFST_CLROVFICB |
+ S3C_CIWDOFST_CLROVFICR);
+ writel(cfg, ctrl->regs + S3C_CIWDOFST);
+
+ return 1;
+ }
+
+ return 0;
+}
+
+int fimc_hwset_camera_offset(struct fimc_control *ctrl)
+{
+ struct s3c_platform_camera *cam = ctrl->cam;
+ struct v4l2_rect *rect = &cam->window;
+ u32 cfg, h1, h2, v1, v2;
+
+ if (!cam) {
+ fimc_err("%s: no active camera\n", __func__);
+ return -ENODEV;
+ }
+
+ h1 = rect->left;
+ h2 = cam->width - rect->width - rect->left;
+ v1 = rect->top;
+ v2 = cam->height - rect->height - rect->top;
+
+ cfg = readl(ctrl->regs + S3C_CIWDOFST);
+ cfg &= ~(S3C_CIWDOFST_WINHOROFST_MASK | S3C_CIWDOFST_WINVEROFST_MASK);
+ cfg |= S3C_CIWDOFST_WINHOROFST(h1);
+ cfg |= S3C_CIWDOFST_WINVEROFST(v1);
+ cfg |= S3C_CIWDOFST_WINOFSEN;
+ writel(cfg, ctrl->regs + S3C_CIWDOFST);
+
+ cfg = 0;
+ cfg |= S3C_CIWDOFST2_WINHOROFST2(h2);
+ cfg |= S3C_CIWDOFST2_WINVEROFST2(v2);
+ writel(cfg, ctrl->regs + S3C_CIWDOFST2);
+
+ return 0;
+}
+
+int fimc_hwset_camera_polarity(struct fimc_control *ctrl)
+{
+ struct s3c_platform_camera *cam = ctrl->cam;
+ u32 cfg;
+
+ if (!cam) {
+ fimc_err("%s: no active camera\n", __func__);
+ return -ENODEV;
+ }
+
+ cfg = readl(ctrl->regs + S3C_CIGCTRL);
+
+ cfg &= ~(S3C_CIGCTRL_INVPOLPCLK | S3C_CIGCTRL_INVPOLVSYNC |
+ S3C_CIGCTRL_INVPOLHREF | S3C_CIGCTRL_INVPOLHSYNC);
+
+ if (cam->inv_pclk)
+ cfg |= S3C_CIGCTRL_INVPOLPCLK;
+
+ if (cam->inv_vsync)
+ cfg |= S3C_CIGCTRL_INVPOLVSYNC;
+
+ if (cam->inv_href)
+ cfg |= S3C_CIGCTRL_INVPOLHREF;
+
+ if (cam->inv_hsync)
+ cfg |= S3C_CIGCTRL_INVPOLHSYNC;
+
+ writel(cfg, ctrl->regs + S3C_CIGCTRL);
+
+ return 0;
+}
+
+int fimc40_hwset_camera_type(struct fimc_control *ctrl)
+{
+ struct s3c_platform_camera *cam = ctrl->cam;
+ u32 cfg;
+
+ if (!cam) {
+ fimc_err("%s: no active camera\n", __func__);
+ return -ENODEV;
+ }
+
+ cfg = readl(ctrl->regs + S3C_CIGCTRL);
+ cfg &= ~(S3C_CIGCTRL_TESTPATTERN_MASK | S3C_CIGCTRL_SELCAM_ITU_MASK |
+ S3C_CIGCTRL_SELCAM_FIMC_MASK);
+
+ /* Interface selection */
+ if (cam->type == CAM_TYPE_MIPI) {
+ cfg |= S3C_CIGCTRL_SELCAM_FIMC_MIPI;
+ writel(cam->fmt, ctrl->regs + S3C_CSIIMGFMT);
+ } else if (cam->type == CAM_TYPE_ITU) {
+ if (cam->id == CAMERA_PAR_A)
+ cfg |= S3C_CIGCTRL_SELCAM_ITU_A;
+ else
+ cfg |= S3C_CIGCTRL_SELCAM_ITU_B;
+ /* switch to ITU interface */
+ cfg |= S3C_CIGCTRL_SELCAM_FIMC_ITU;
+ } else {
+ fimc_err("%s: invalid camera bus type selected\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ writel(cfg, ctrl->regs + S3C_CIGCTRL);
+
+ return 0;
+}
+
+int fimc43_hwset_camera_type(struct fimc_control *ctrl)
+{
+ struct s3c_platform_camera *cam = ctrl->cam;
+ u32 cfg;
+
+ if (!cam) {
+ fimc_err("%s: no active camera\n", __func__);
+ return -ENODEV;
+ }
+
+ cfg = readl(ctrl->regs + S3C_CIGCTRL);
+ cfg &= ~(S3C_CIGCTRL_TESTPATTERN_MASK | S3C_CIGCTRL_SELCAM_ITU_MASK |
+ S3C_CIGCTRL_SELCAM_MIPI_MASK | S3C_CIGCTRL_SELCAM_FIMC_MASK |
+ S3C_CIGCTRL_SELWB_CAMIF_MASK);
+
+ /* Interface selection */
+ if (cam->id == CAMERA_WB) {
+ cfg |= S3C_CIGCTRL_SELWB_CAMIF_WRITEBACK;
+ } else if (cam->type == CAM_TYPE_MIPI) {
+ cfg |= S3C_CIGCTRL_SELCAM_FIMC_MIPI;
+
+ /* C110/V210 Support only MIPI A support */
+ cfg |= S3C_CIGCTRL_SELCAM_MIPI_A;
+
+ /* FIXME: Temporary MIPI CSIS Data 32 bit aligned */
+ if (ctrl->cap->fmt.pixelformat == V4L2_PIX_FMT_JPEG)
+ writel((MIPI_USER_DEF_PACKET_1 | (0x1 << 8)),
+ ctrl->regs + S3C_CSIIMGFMT);
+ else
+ writel(cam->fmt | (0x1 << 8),
+ ctrl->regs + S3C_CSIIMGFMT);
+ } else if (cam->type == CAM_TYPE_ITU) {
+ if (cam->id == CAMERA_PAR_A)
+ cfg |= S3C_CIGCTRL_SELCAM_ITU_A;
+ else
+ cfg |= S3C_CIGCTRL_SELCAM_ITU_B;
+ /* switch to ITU interface */
+ cfg |= S3C_CIGCTRL_SELCAM_FIMC_ITU;
+ } else {
+ fimc_err("%s: invalid camera bus type selected\n", __func__);
+ return -EINVAL;
+ }
+
+ writel(cfg, ctrl->regs + S3C_CIGCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_camera_type(struct fimc_control *ctrl)
+{
+ struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
+
+ switch (pdata->hw_ver) {
+ case 0x40:
+ fimc40_hwset_camera_type(ctrl);
+ break;
+ case 0x43:
+ case 0x45:
+ fimc43_hwset_camera_type(ctrl);
+ break;
+ default:
+ fimc43_hwset_camera_type(ctrl);
+ break;
+ }
+
+ return 0;
+}
+
+
+int fimc_hwset_jpeg_mode(struct fimc_control *ctrl, bool enable)
+{
+ u32 cfg;
+ cfg = readl(ctrl->regs + S3C_CIGCTRL);
+
+ if (enable)
+ cfg |= S3C_CIGCTRL_CAM_JPEG;
+ else
+ cfg &= ~S3C_CIGCTRL_CAM_JPEG;
+
+ writel(cfg, ctrl->regs + S3C_CIGCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_output_size(struct fimc_control *ctrl, int width, int height)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CITRGFMT);
+
+ cfg &= ~(S3C_CITRGFMT_TARGETH_MASK | S3C_CITRGFMT_TARGETV_MASK);
+
+ cfg |= S3C_CITRGFMT_TARGETHSIZE(width);
+ cfg |= S3C_CITRGFMT_TARGETVSIZE(height);
+
+ writel(cfg, ctrl->regs + S3C_CITRGFMT);
+
+ return 0;
+}
+
+int fimc_hwset_output_colorspace(struct fimc_control *ctrl, u32 pixelformat)
+{
+ struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
+ u32 cfg;
+
+ if (pdata->hw_ver != 0x40) {
+ if (pixelformat == V4L2_PIX_FMT_YUV444) {
+ cfg = readl(ctrl->regs + S3C_CIEXTEN);
+ cfg |= S3C_CIEXTEN_YUV444_OUT;
+ writel(cfg, ctrl->regs + S3C_CIEXTEN);
+
+ return 0;
+ } else {
+ cfg = readl(ctrl->regs + S3C_CIEXTEN);
+ cfg &= ~S3C_CIEXTEN_YUV444_OUT;
+ writel(cfg, ctrl->regs + S3C_CIEXTEN);
+ }
+ }
+
+ cfg = readl(ctrl->regs + S3C_CITRGFMT);
+ cfg &= ~S3C_CITRGFMT_OUTFORMAT_MASK;
+
+ switch (pixelformat) {
+ case V4L2_PIX_FMT_JPEG:
+ break;
+ case V4L2_PIX_FMT_RGB565: /* fall through */
+ case V4L2_PIX_FMT_RGB32:
+ cfg |= S3C_CITRGFMT_OUTFORMAT_RGB;
+ break;
+
+ case V4L2_PIX_FMT_YUYV: /* fall through */
+ case V4L2_PIX_FMT_UYVY: /* fall through */
+ case V4L2_PIX_FMT_VYUY: /* fall through */
+ case V4L2_PIX_FMT_YVYU:
+ cfg |= S3C_CITRGFMT_OUTFORMAT_YCBCR422_1PLANE;
+ break;
+
+ case V4L2_PIX_FMT_NV16: /* fall through */
+ case V4L2_PIX_FMT_NV61: /* fall through */
+ case V4L2_PIX_FMT_YUV422P:
+ cfg |= S3C_CITRGFMT_OUTFORMAT_YCBCR422;
+ break;
+
+ case V4L2_PIX_FMT_YUV420: /* fall through */
+ case V4L2_PIX_FMT_NV12: /* fall through */
+ case V4L2_PIX_FMT_NV12T: /* fall through */
+ case V4L2_PIX_FMT_NV21:
+ cfg |= S3C_CITRGFMT_OUTFORMAT_YCBCR420;
+ break;
+
+ default:
+ fimc_err("%s: invalid pixel format\n", __func__);
+ break;
+ }
+
+ writel(cfg, ctrl->regs + S3C_CITRGFMT);
+
+ return 0;
+}
+
+int fimc_hwset_output_rot_flip(struct fimc_control *ctrl, u32 rot, u32 flip)
+{
+ u32 cfg, val;
+
+ cfg = readl(ctrl->regs + S3C_CITRGFMT);
+ cfg &= ~S3C_CITRGFMT_FLIP_MASK;
+ cfg &= ~S3C_CITRGFMT_OUTROT90_CLOCKWISE;
+
+ val = fimc_mapping_rot_flip(rot, flip);
+
+ if (val & FIMC_ROT)
+ cfg |= S3C_CITRGFMT_OUTROT90_CLOCKWISE;
+
+ if (val & FIMC_XFLIP)
+ cfg |= S3C_CITRGFMT_FLIP_X_MIRROR;
+
+ if (val & FIMC_YFLIP)
+ cfg |= S3C_CITRGFMT_FLIP_Y_MIRROR;
+
+ writel(cfg, ctrl->regs + S3C_CITRGFMT);
+
+ return 0;
+}
+
+int fimc_hwset_output_area(struct fimc_control *ctrl, u32 width, u32 height)
+{
+ u32 cfg = 0;
+
+ cfg = S3C_CITAREA_TARGET_AREA(width * height);
+ writel(cfg, ctrl->regs + S3C_CITAREA);
+
+ return 0;
+}
+
+int fimc_hwset_enable_lastirq(struct fimc_control *ctrl)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CIOCTRL);
+
+ cfg |= S3C_CIOCTRL_LASTIRQ_ENABLE;
+ writel(cfg, ctrl->regs + S3C_CIOCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_disable_lastirq(struct fimc_control *ctrl)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CIOCTRL);
+
+ cfg &= ~S3C_CIOCTRL_LASTIRQ_ENABLE;
+ writel(cfg, ctrl->regs + S3C_CIOCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_prescaler(struct fimc_control *ctrl, struct fimc_scaler *sc)
+{
+ u32 cfg = 0, shfactor;
+
+ shfactor = 10 - (sc->hfactor + sc->vfactor);
+
+ cfg |= S3C_CISCPRERATIO_SHFACTOR(shfactor);
+ cfg |= S3C_CISCPRERATIO_PREHORRATIO(sc->pre_hratio);
+ cfg |= S3C_CISCPRERATIO_PREVERRATIO(sc->pre_vratio);
+
+ writel(cfg, ctrl->regs + S3C_CISCPRERATIO);
+
+ cfg = 0;
+ cfg |= S3C_CISCPREDST_PREDSTWIDTH(sc->pre_dst_width);
+ cfg |= S3C_CISCPREDST_PREDSTHEIGHT(sc->pre_dst_height);
+
+ writel(cfg, ctrl->regs + S3C_CISCPREDST);
+
+ return 0;
+}
+
+int fimc_hwset_output_address(struct fimc_control *ctrl,
+ struct fimc_buf_set *bs, int id)
+{
+ writel(bs->base[FIMC_ADDR_Y], ctrl->regs + S3C_CIOYSA(id));
+ writel(bs->base[FIMC_ADDR_CB], ctrl->regs + S3C_CIOCBSA(id));
+ writel(bs->base[FIMC_ADDR_CR], ctrl->regs + S3C_CIOCRSA(id));
+
+ return 0;
+}
+
+int fimc_hwset_output_yuv(struct fimc_control *ctrl, u32 pixelformat)
+{
+ u32 cfg;
+
+ cfg = readl(ctrl->regs + S3C_CIOCTRL);
+ cfg &= ~(S3C_CIOCTRL_ORDER2P_MASK | S3C_CIOCTRL_ORDER422_MASK |
+ S3C_CIOCTRL_YCBCR_PLANE_MASK);
+
+ switch (pixelformat) {
+ /* 1 plane formats */
+ case V4L2_PIX_FMT_YUYV:
+ cfg |= S3C_CIOCTRL_ORDER422_YCBYCR;
+ break;
+
+ case V4L2_PIX_FMT_UYVY:
+ cfg |= S3C_CIOCTRL_ORDER422_CBYCRY;
+ break;
+
+ case V4L2_PIX_FMT_VYUY:
+ cfg |= S3C_CIOCTRL_ORDER422_CRYCBY;
+ break;
+
+ case V4L2_PIX_FMT_YVYU:
+ cfg |= S3C_CIOCTRL_ORDER422_YCRYCB;
+ break;
+
+ /* 2 plane formats */
+ case V4L2_PIX_FMT_NV12: /* fall through */
+ case V4L2_PIX_FMT_NV12T: /* fall through */
+ case V4L2_PIX_FMT_NV16:
+ cfg |= S3C_CIOCTRL_ORDER2P_LSB_CBCR;
+ cfg |= S3C_CIOCTRL_YCBCR_2PLANE;
+ break;
+
+ case V4L2_PIX_FMT_NV21: /* fall through */
+ case V4L2_PIX_FMT_NV61:
+ cfg |= S3C_CIOCTRL_ORDER2P_LSB_CRCB;
+ cfg |= S3C_CIOCTRL_YCBCR_2PLANE;
+ break;
+
+ /* 3 plane formats */
+ case V4L2_PIX_FMT_YUV422P: /* fall through */
+ case V4L2_PIX_FMT_YUV420:
+ cfg |= S3C_CIOCTRL_YCBCR_3PLANE;
+ break;
+ }
+
+ writel(cfg, ctrl->regs + S3C_CIOCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_output_scan(struct fimc_control *ctrl,
+ struct v4l2_pix_format *fmt)
+{
+ struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
+ u32 cfg;
+
+ /* nothing to do: FIMC40 not supported interlaced and weave output */
+ if (pdata->hw_ver == 0x40)
+ return 0;
+
+ cfg = readl(ctrl->regs + S3C_CISCCTRL);
+ cfg &= ~S3C_CISCCTRL_SCAN_MASK;
+
+ if (fmt->field == V4L2_FIELD_INTERLACED ||
+ fmt->field == V4L2_FIELD_INTERLACED_TB)
+ cfg |= S3C_CISCCTRL_INTERLACE;
+ else
+ cfg |= S3C_CISCCTRL_PROGRESSIVE;
+
+ writel(cfg, ctrl->regs + S3C_CISCCTRL);
+
+ cfg = readl(ctrl->regs + S3C_CIOCTRL);
+ cfg &= ~S3C_CIOCTRL_WEAVE_MASK;
+
+ if ((ctrl->cap) && (fmt->field == V4L2_FIELD_INTERLACED_TB))
+ cfg |= S3C_CIOCTRL_WEAVE_OUT;
+
+ writel(cfg, ctrl->regs + S3C_CIOCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_input_rot(struct fimc_control *ctrl, u32 rot, u32 flip)
+{
+ u32 cfg, val;
+
+ cfg = readl(ctrl->regs + S3C_CITRGFMT);
+ cfg &= ~S3C_CITRGFMT_INROT90_CLOCKWISE;
+
+ val = fimc_mapping_rot_flip(rot, flip);
+
+ if (val & FIMC_ROT)
+ cfg |= S3C_CITRGFMT_INROT90_CLOCKWISE;
+
+ writel(cfg, ctrl->regs + S3C_CITRGFMT);
+
+ return 0;
+}
+
+int fimc40_hwset_scaler(struct fimc_control *ctrl, struct fimc_scaler *sc)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CISCCTRL);
+
+ cfg &= ~(S3C_CISCCTRL_SCALERBYPASS |
+ S3C_CISCCTRL_SCALEUP_H | S3C_CISCCTRL_SCALEUP_V |
+ S3C_CISCCTRL_MAIN_V_RATIO_MASK |
+ S3C_CISCCTRL_MAIN_H_RATIO_MASK |
+ S3C_CISCCTRL_CSCR2Y_WIDE |
+ S3C_CISCCTRL_CSCY2R_WIDE);
+
+#ifdef CONFIG_VIDEO_FIMC_RANGE_WIDE
+ cfg |= (S3C_CISCCTRL_CSCR2Y_WIDE | S3C_CISCCTRL_CSCY2R_WIDE);
+#endif
+
+ if (sc->bypass)
+ cfg |= S3C_CISCCTRL_SCALERBYPASS;
+
+ if (sc->scaleup_h)
+ cfg |= S3C_CISCCTRL_SCALEUP_H;
+
+ if (sc->scaleup_v)
+ cfg |= S3C_CISCCTRL_SCALEUP_V;
+
+ cfg |= S3C_CISCCTRL_MAINHORRATIO(sc->main_hratio);
+ cfg |= S3C_CISCCTRL_MAINVERRATIO(sc->main_vratio);
+
+ writel(cfg, ctrl->regs + S3C_CISCCTRL);
+
+ return 0;
+}
+
+int fimc43_hwset_scaler(struct fimc_control *ctrl, struct fimc_scaler *sc)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CISCCTRL);
+ u32 cfg_ext = readl(ctrl->regs + S3C_CIEXTEN);
+
+ cfg &= ~(S3C_CISCCTRL_SCALERBYPASS |
+ S3C_CISCCTRL_SCALEUP_H | S3C_CISCCTRL_SCALEUP_V |
+ S3C_CISCCTRL_MAIN_V_RATIO_MASK |
+ S3C_CISCCTRL_MAIN_H_RATIO_MASK |
+ S3C_CISCCTRL_CSCR2Y_WIDE |
+ S3C_CISCCTRL_CSCY2R_WIDE);
+
+#ifdef CONFIG_VIDEO_FIMC_RANGE_WIDE
+ cfg |= (S3C_CISCCTRL_CSCR2Y_WIDE | S3C_CISCCTRL_CSCY2R_WIDE);
+#endif
+
+ if (sc->bypass)
+ cfg |= S3C_CISCCTRL_SCALERBYPASS;
+
+ if (sc->scaleup_h)
+ cfg |= S3C_CISCCTRL_SCALEUP_H;
+
+ if (sc->scaleup_v)
+ cfg |= S3C_CISCCTRL_SCALEUP_V;
+
+ cfg |= S3C_CISCCTRL_MAINHORRATIO(sc->main_hratio);
+ cfg |= S3C_CISCCTRL_MAINVERRATIO(sc->main_vratio);
+
+ writel(cfg, ctrl->regs + S3C_CISCCTRL);
+
+ cfg_ext &= ~S3C_CIEXTEN_MAINHORRATIO_EXT_MASK;
+ cfg_ext &= ~S3C_CIEXTEN_MAINVERRATIO_EXT_MASK;
+
+ cfg_ext |= S3C_CIEXTEN_MAINHORRATIO_EXT(sc->main_hratio);
+ cfg_ext |= S3C_CIEXTEN_MAINVERRATIO_EXT(sc->main_vratio);
+
+ writel(cfg_ext, ctrl->regs + S3C_CIEXTEN);
+
+ return 0;
+}
+
+int fimc50_hwset_scaler(struct fimc_control *ctrl, struct fimc_scaler *sc)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CISCCTRL);
+ u32 cfg_ext = readl(ctrl->regs + S3C_CIEXTEN);
+
+ cfg &= ~(S3C_CISCCTRL_SCALERBYPASS |
+ S3C_CISCCTRL_SCALEUP_H | S3C_CISCCTRL_SCALEUP_V |
+ S3C_CISCCTRL_MAIN_V_RATIO_MASK |
+ S3C_CISCCTRL_MAIN_H_RATIO_MASK |
+ S3C_CISCCTRL_CSCR2Y_WIDE |
+ S3C_CISCCTRL_CSCY2R_WIDE);
+
+#ifdef CONFIG_VIDEO_FIMC_RANGE_WIDE
+ cfg |= (S3C_CISCCTRL_CSCR2Y_WIDE | S3C_CISCCTRL_CSCY2R_WIDE);
+#endif
+
+ if (sc->bypass)
+ cfg |= S3C_CISCCTRL_SCALERBYPASS;
+
+ if (sc->scaleup_h)
+ cfg |= S3C_CISCCTRL_SCALEUP_H;
+
+ if (sc->scaleup_v)
+ cfg |= S3C_CISCCTRL_SCALEUP_V;
+
+ cfg |= S3C_CISCCTRL_MAINHORRATIO((sc->main_hratio >> 6));
+ cfg |= S3C_CISCCTRL_MAINVERRATIO((sc->main_vratio >> 6));
+
+ writel(cfg, ctrl->regs + S3C_CISCCTRL);
+
+ cfg_ext &= ~S3C_CIEXTEN_MAINHORRATIO_EXT_MASK;
+ cfg_ext &= ~S3C_CIEXTEN_MAINVERRATIO_EXT_MASK;
+
+ cfg_ext |= S3C_CIEXTEN_MAINHORRATIO_EXT(sc->main_hratio);
+ cfg_ext |= S3C_CIEXTEN_MAINVERRATIO_EXT(sc->main_vratio);
+
+ writel(cfg_ext, ctrl->regs + S3C_CIEXTEN);
+
+ return 0;
+}
+
+int fimc_hwset_scaler(struct fimc_control *ctrl, struct fimc_scaler *sc)
+{
+ struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
+
+ switch (pdata->hw_ver) {
+ case 0x40:
+ fimc40_hwset_scaler(ctrl, sc);
+ break;
+ case 0x43:
+ case 0x45:
+ fimc43_hwset_scaler(ctrl, sc);
+ break;
+ case 0x50:
+ fimc50_hwset_scaler(ctrl, sc);
+ break;
+ default:
+ fimc43_hwset_scaler(ctrl, sc);
+ break;
+ }
+
+ return 0;
+}
+
+
+int fimc_hwset_scaler_bypass(struct fimc_control *ctrl)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CISCCTRL);
+
+ cfg |= S3C_CISCCTRL_SCALERBYPASS;
+
+ writel(cfg, ctrl->regs + S3C_CISCCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_enable_lcdfifo(struct fimc_control *ctrl)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CISCCTRL);
+
+ cfg |= S3C_CISCCTRL_LCDPATHEN_FIFO;
+ writel(cfg, ctrl->regs + S3C_CISCCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_disable_lcdfifo(struct fimc_control *ctrl)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CISCCTRL);
+
+ cfg &= ~S3C_CISCCTRL_LCDPATHEN_FIFO;
+ writel(cfg, ctrl->regs + S3C_CISCCTRL);
+
+ return 0;
+}
+
+int fimc_hwget_frame_count(struct fimc_control *ctrl)
+{
+ return S3C_CISTATUS_GET_FRAME_COUNT(readl(ctrl->regs + S3C_CISTATUS));
+}
+
+int fimc_hwget_frame_end(struct fimc_control *ctrl)
+{
+ unsigned long timeo = jiffies;
+ u32 cfg;
+
+ timeo += 20; /* waiting for 100ms */
+ while (time_before(jiffies, timeo)) {
+ cfg = readl(ctrl->regs + S3C_CISTATUS);
+
+ if (S3C_CISTATUS_GET_FRAME_END(cfg)) {
+ cfg &= ~S3C_CISTATUS_FRAMEEND;
+ writel(cfg, ctrl->regs + S3C_CISTATUS);
+ break;
+ }
+ cond_resched();
+ }
+
+ return 0;
+}
+
+int fimc_hwget_last_frame_end(struct fimc_control *ctrl)
+{
+ unsigned long timeo = jiffies;
+ u32 cfg;
+
+ timeo += 20; /* waiting for 100ms */
+ while (time_before(jiffies, timeo)) {
+ cfg = readl(ctrl->regs + S3C_CISTATUS);
+
+ if (S3C_CISTATUS_GET_LAST_CAPTURE_END(cfg)) {
+ cfg &= ~S3C_CISTATUS_LASTCAPTUREEND;
+ writel(cfg, ctrl->regs + S3C_CISTATUS);
+ break;
+ }
+ cond_resched();
+ }
+
+ return 0;
+}
+
+int fimc_hwset_start_scaler(struct fimc_control *ctrl)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CISCCTRL);
+
+ cfg |= S3C_CISCCTRL_SCALERSTART;
+ writel(cfg, ctrl->regs + S3C_CISCCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_stop_scaler(struct fimc_control *ctrl)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CISCCTRL);
+
+ cfg &= ~S3C_CISCCTRL_SCALERSTART;
+ writel(cfg, ctrl->regs + S3C_CISCCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_input_rgb(struct fimc_control *ctrl, u32 pixelformat)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CISCCTRL);
+ cfg &= ~S3C_CISCCTRL_INRGB_FMT_RGB_MASK;
+
+ if (pixelformat == V4L2_PIX_FMT_RGB32)
+ cfg |= S3C_CISCCTRL_INRGB_FMT_RGB888;
+ else if (pixelformat == V4L2_PIX_FMT_RGB565)
+ cfg |= S3C_CISCCTRL_INRGB_FMT_RGB565;
+
+ writel(cfg, ctrl->regs + S3C_CISCCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_intput_field(struct fimc_control *ctrl, enum v4l2_field field)
+{
+ struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
+ u32 cfg;
+
+ if (pdata->hw_ver == 0x40)
+ return 0;
+
+ cfg = readl(ctrl->regs + S3C_MSCTRL);
+ cfg &= ~S3C_MSCTRL_FIELD_MASK;
+
+ if (field == V4L2_FIELD_NONE)
+ cfg |= S3C_MSCTRL_FIELD_NORMAL;
+ else if (field == V4L2_FIELD_INTERLACED_TB)
+ cfg |= S3C_MSCTRL_FIELD_WEAVE;
+
+ writel(cfg, ctrl->regs + S3C_MSCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_output_rgb(struct fimc_control *ctrl, u32 pixelformat)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CISCCTRL);
+ cfg &= ~S3C_CISCCTRL_OUTRGB_FMT_RGB_MASK;
+
+ if (pixelformat == V4L2_PIX_FMT_RGB32)
+ cfg |= S3C_CISCCTRL_OUTRGB_FMT_RGB888;
+ else if (pixelformat == V4L2_PIX_FMT_RGB565)
+ cfg |= S3C_CISCCTRL_OUTRGB_FMT_RGB565;
+
+ writel(cfg, ctrl->regs + S3C_CISCCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_ext_rgb(struct fimc_control *ctrl, int enable)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CISCCTRL);
+ cfg &= ~S3C_CISCCTRL_EXTRGB_EXTENSION;
+
+ if (enable)
+ cfg |= S3C_CISCCTRL_EXTRGB_EXTENSION;
+
+ writel(cfg, ctrl->regs + S3C_CISCCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_enable_capture(struct fimc_control *ctrl, u32 bypass)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CIIMGCPT);
+ cfg &= ~S3C_CIIMGCPT_IMGCPTEN_SC;
+ cfg |= S3C_CIIMGCPT_IMGCPTEN;
+
+ if (!bypass)
+ cfg |= S3C_CIIMGCPT_IMGCPTEN_SC;
+
+ writel(cfg, ctrl->regs + S3C_CIIMGCPT);
+
+ return 0;
+}
+
+int fimc_hwset_disable_capture(struct fimc_control *ctrl)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CIIMGCPT);
+
+ cfg &= ~(S3C_CIIMGCPT_IMGCPTEN_SC | S3C_CIIMGCPT_IMGCPTEN);
+
+ writel(cfg, ctrl->regs + S3C_CIIMGCPT);
+
+ return 0;
+}
+
+int fimc_hwset_input_address(struct fimc_control *ctrl, dma_addr_t *base)
+{
+ writel(base[FIMC_ADDR_Y], ctrl->regs + S3C_CIIYSA0);
+ writel(base[FIMC_ADDR_CB], ctrl->regs + S3C_CIICBSA0);
+ writel(base[FIMC_ADDR_CR], ctrl->regs + S3C_CIICRSA0);
+
+ return 0;
+}
+
+int fimc_hwset_enable_autoload(struct fimc_control *ctrl)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CIREAL_ISIZE);
+
+ cfg |= S3C_CIREAL_ISIZE_AUTOLOAD_ENABLE;
+
+ writel(cfg, ctrl->regs + S3C_CIREAL_ISIZE);
+
+ return 0;
+}
+
+int fimc_hwset_disable_autoload(struct fimc_control *ctrl)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CIREAL_ISIZE);
+
+ cfg &= ~S3C_CIREAL_ISIZE_AUTOLOAD_ENABLE;
+
+ writel(cfg, ctrl->regs + S3C_CIREAL_ISIZE);
+
+ return 0;
+}
+
+int fimc_hwset_real_input_size(struct fimc_control *ctrl, u32 width, u32 height)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CIREAL_ISIZE);
+ cfg &= ~(S3C_CIREAL_ISIZE_HEIGHT_MASK | S3C_CIREAL_ISIZE_WIDTH_MASK);
+
+ cfg |= S3C_CIREAL_ISIZE_WIDTH(width);
+ cfg |= S3C_CIREAL_ISIZE_HEIGHT(height);
+
+ writel(cfg, ctrl->regs + S3C_CIREAL_ISIZE);
+
+ return 0;
+}
+
+int fimc_hwset_addr_change_enable(struct fimc_control *ctrl)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CIREAL_ISIZE);
+
+ cfg &= ~S3C_CIREAL_ISIZE_ADDR_CH_DISABLE;
+
+ writel(cfg, ctrl->regs + S3C_CIREAL_ISIZE);
+
+ return 0;
+}
+
+int fimc_hwset_addr_change_disable(struct fimc_control *ctrl)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CIREAL_ISIZE);
+
+ cfg |= S3C_CIREAL_ISIZE_ADDR_CH_DISABLE;
+
+ writel(cfg, ctrl->regs + S3C_CIREAL_ISIZE);
+
+ return 0;
+}
+
+int fimc_hwset_input_burst_cnt(struct fimc_control *ctrl, u32 cnt)
+{
+ u32 cfg = readl(ctrl->regs + S3C_MSCTRL);
+ cfg &= ~S3C_MSCTRL_BURST_CNT_MASK;
+
+ if (cnt > 4)
+ cnt = 4;
+ else if (cnt == 0)
+ cnt = 4;
+
+ cfg |= S3C_MSCTRL_SUCCESSIVE_COUNT(cnt);
+ writel(cfg, ctrl->regs + S3C_MSCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_input_colorspace(struct fimc_control *ctrl, u32 pixelformat)
+{
+ u32 cfg = readl(ctrl->regs + S3C_MSCTRL);
+ cfg &= ~S3C_MSCTRL_INFORMAT_RGB;
+
+ /* Color format setting */
+ switch (pixelformat) {
+ case V4L2_PIX_FMT_YUV420: /* fall through */
+ case V4L2_PIX_FMT_NV12: /* fall through */
+ case V4L2_PIX_FMT_NV21: /* fall through */
+ case V4L2_PIX_FMT_NV12T:
+ cfg |= S3C_MSCTRL_INFORMAT_YCBCR420;
+ break;
+ case V4L2_PIX_FMT_YUYV: /* fall through */
+ case V4L2_PIX_FMT_UYVY: /* fall through */
+ case V4L2_PIX_FMT_YVYU: /* fall through */
+ case V4L2_PIX_FMT_VYUY:
+ cfg |= S3C_MSCTRL_INFORMAT_YCBCR422_1PLANE;
+ break;
+ case V4L2_PIX_FMT_NV16: /* fall through */
+ case V4L2_PIX_FMT_NV61:
+ cfg |= S3C_MSCTRL_INFORMAT_YCBCR422;
+ break;
+ case V4L2_PIX_FMT_RGB565: /* fall through */
+ case V4L2_PIX_FMT_RGB32:
+ cfg |= S3C_MSCTRL_INFORMAT_RGB;
+ break;
+ default:
+ fimc_err("%s: Invalid pixelformt : %d\n",
+ __func__, pixelformat);
+ return -EINVAL;
+ }
+
+ writel(cfg, ctrl->regs + S3C_MSCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_input_yuv(struct fimc_control *ctrl, u32 pixelformat)
+{
+ u32 cfg = readl(ctrl->regs + S3C_MSCTRL);
+ cfg &= ~(S3C_MSCTRL_ORDER2P_SHIFT_MASK | S3C_MSCTRL_C_INT_IN_2PLANE |
+ S3C_MSCTRL_ORDER422_YCBYCR);
+
+ switch (pixelformat) {
+ case V4L2_PIX_FMT_YUV420:
+ cfg |= S3C_MSCTRL_C_INT_IN_3PLANE;
+ break;
+ case V4L2_PIX_FMT_YUYV: /* fall through */
+ cfg |= S3C_MSCTRL_ORDER422_YCBYCR;
+ break;
+ case V4L2_PIX_FMT_UYVY:
+ cfg |= S3C_MSCTRL_ORDER422_CBYCRY;
+ break;
+ case V4L2_PIX_FMT_YVYU:
+ cfg |= S3C_MSCTRL_ORDER422_YCRYCB;
+ break;
+ case V4L2_PIX_FMT_VYUY:
+ cfg |= S3C_MSCTRL_ORDER422_CRYCBY;
+ break;
+ case V4L2_PIX_FMT_NV12: /* fall through */
+ case V4L2_PIX_FMT_NV12T:
+ cfg |= S3C_MSCTRL_ORDER2P_LSB_CBCR;
+ cfg |= S3C_MSCTRL_C_INT_IN_2PLANE;
+ break;
+ case V4L2_PIX_FMT_NV21:
+ cfg |= S3C_MSCTRL_ORDER2P_LSB_CRCB;
+ cfg |= S3C_MSCTRL_C_INT_IN_2PLANE;
+ break;
+ case V4L2_PIX_FMT_NV16:
+ cfg |= S3C_MSCTRL_ORDER2P_LSB_CBCR;
+ cfg |= S3C_MSCTRL_C_INT_IN_2PLANE;
+ break;
+ case V4L2_PIX_FMT_NV61:
+ cfg |= S3C_MSCTRL_ORDER2P_LSB_CRCB;
+ cfg |= S3C_MSCTRL_C_INT_IN_2PLANE;
+ break;
+ case V4L2_PIX_FMT_RGB565: /* fall through */
+ case V4L2_PIX_FMT_RGB32:
+ break;
+ default:
+ fimc_err("%s: Invalid pixelformt : %d\n",
+ __func__, pixelformat);
+ }
+
+ writel(cfg, ctrl->regs + S3C_MSCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_input_flip(struct fimc_control *ctrl, u32 rot, u32 flip)
+{
+ u32 cfg, val;
+
+ cfg = readl(ctrl->regs + S3C_MSCTRL);
+ cfg &= ~(S3C_MSCTRL_FLIP_X_MIRROR | S3C_MSCTRL_FLIP_Y_MIRROR);
+ val = fimc_mapping_rot_flip(rot, flip);
+
+ if (val & FIMC_XFLIP)
+ cfg |= S3C_MSCTRL_FLIP_X_MIRROR;
+
+ if (val & FIMC_YFLIP)
+ cfg |= S3C_MSCTRL_FLIP_Y_MIRROR;
+
+ writel(cfg, ctrl->regs + S3C_MSCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_input_source(struct fimc_control *ctrl, enum fimc_input path)
+{
+ u32 cfg = readl(ctrl->regs + S3C_MSCTRL);
+ cfg &= ~S3C_MSCTRL_INPUT_MASK;
+
+ if (path == FIMC_SRC_MSDMA)
+ cfg |= S3C_MSCTRL_INPUT_MEMORY;
+ else if (path == FIMC_SRC_CAM)
+ cfg |= S3C_MSCTRL_INPUT_EXTCAM;
+
+ writel(cfg, ctrl->regs + S3C_MSCTRL);
+
+ return 0;
+
+}
+
+int fimc_hwset_start_input_dma(struct fimc_control *ctrl)
+{
+ u32 cfg = readl(ctrl->regs + S3C_MSCTRL);
+ cfg |= S3C_MSCTRL_ENVID;
+
+ writel(cfg, ctrl->regs + S3C_MSCTRL);
+
+ return 0;
+}
+
+int fimc_hwset_stop_input_dma(struct fimc_control *ctrl)
+{
+ u32 cfg = readl(ctrl->regs + S3C_MSCTRL);
+ cfg &= ~S3C_MSCTRL_ENVID;
+
+ writel(cfg, ctrl->regs + S3C_MSCTRL);
+
+ return 0;
+}
+
+void fimc_wait_stop_processing(struct fimc_control *ctrl)
+{
+ fimc_hwget_frame_end(ctrl);
+ fimc_hwget_last_frame_end(ctrl);
+}
+
+void fimc_hwset_stop_processing(struct fimc_control *ctrl)
+{
+ fimc_wait_stop_processing(ctrl);
+
+ fimc_hwset_stop_scaler(ctrl);
+ fimc_hwset_disable_capture(ctrl);
+ fimc_hwset_stop_input_dma(ctrl);
+
+ /* We need to wait for sometime after processing is stopped.
+ * This is required for obtaining clean buffer for DMA processing. */
+ fimc_wait_stop_processing(ctrl);
+}
+
+int fimc40_hwset_output_offset(struct fimc_control *ctrl, u32 pixelformat,
+ struct v4l2_rect *bounds,
+ struct v4l2_rect *crop)
+{
+ u32 cfg_y = 0, cfg_cb = 0, cfg_cr = 0;
+
+ if (!crop->left && !crop->top && (bounds->width == crop->width) &&
+ (bounds->height == crop->height))
+ return -EINVAL;
+
+ fimc_dbg("%s: left: %d, top: %d, width: %d, height: %d\n",
+ __func__, crop->left, crop->top, crop->width, crop->height);
+
+ switch (pixelformat) {
+ /* 1 plane, 32 bits per pixel */
+ case V4L2_PIX_FMT_RGB32:
+ cfg_y |= S3C_CIOYOFF_HORIZONTAL(crop->left * 4);
+ cfg_y |= S3C_CIOYOFF_VERTICAL(crop->top);
+ break;
+
+ /* 1 plane, 16 bits per pixel */
+ case V4L2_PIX_FMT_YUYV: /* fall through */
+ case V4L2_PIX_FMT_UYVY: /* fall through */
+ case V4L2_PIX_FMT_VYUY: /* fall through */
+ case V4L2_PIX_FMT_YVYU: /* fall through */
+ case V4L2_PIX_FMT_RGB565:
+ cfg_y |= S3C_CIOYOFF_HORIZONTAL(crop->left * 2);
+ cfg_y |= S3C_CIOYOFF_VERTICAL(crop->top);
+ break;
+
+ /* 2 planes, 16 bits per pixel */
+ case V4L2_PIX_FMT_NV16: /* fall through */
+ case V4L2_PIX_FMT_NV61:
+ cfg_y |= S3C_CIOYOFF_HORIZONTAL(crop->left);
+ cfg_y |= S3C_CIOYOFF_VERTICAL(crop->top);
+ cfg_cb |= S3C_CIOCBOFF_HORIZONTAL(crop->left / 2);
+ cfg_cb |= S3C_CIOCBOFF_VERTICAL(crop->top / 2);
+ break;
+
+ /* 2 planes, 12 bits per pixel */
+ case V4L2_PIX_FMT_NV12: /* fall through */
+ case V4L2_PIX_FMT_NV12T: /* fall through */
+ case V4L2_PIX_FMT_NV21:
+ cfg_y |= S3C_CIOYOFF_HORIZONTAL(crop->left);
+ cfg_y |= S3C_CIOYOFF_VERTICAL(crop->top);
+ cfg_cb |= S3C_CIOCBOFF_HORIZONTAL(crop->left / 4);
+ cfg_cb |= S3C_CIOCBOFF_VERTICAL(crop->top / 4);
+ break;
+
+ /* 3 planes, 16 bits per pixel */
+ case V4L2_PIX_FMT_YUV422P:
+ cfg_y |= S3C_CIOYOFF_HORIZONTAL(crop->left);
+ cfg_y |= S3C_CIOYOFF_VERTICAL(crop->top);
+ cfg_cb |= S3C_CIOCBOFF_HORIZONTAL(crop->left / 2);
+ cfg_cb |= S3C_CIOCBOFF_VERTICAL(crop->top / 2);
+ cfg_cr |= S3C_CIOCROFF_HORIZONTAL(crop->left / 2);
+ cfg_cr |= S3C_CIOCROFF_VERTICAL(crop->top / 2);
+ break;
+
+ /* 3 planes, 12 bits per pixel */
+ case V4L2_PIX_FMT_YUV420:
+ cfg_y |= S3C_CIOYOFF_HORIZONTAL(crop->left);
+ cfg_y |= S3C_CIOYOFF_VERTICAL(crop->top);
+ cfg_cb |= S3C_CIOCBOFF_HORIZONTAL(crop->left / 4);
+ cfg_cb |= S3C_CIOCBOFF_VERTICAL(crop->top / 4);
+ cfg_cr |= S3C_CIOCROFF_HORIZONTAL(crop->left / 4);
+ cfg_cr |= S3C_CIOCROFF_VERTICAL(crop->top / 4);
+ break;
+
+ default:
+ break;
+ }
+
+ writel(cfg_y, ctrl->regs + S3C_CIOYOFF);
+ writel(cfg_cb, ctrl->regs + S3C_CIOCBOFF);
+ writel(cfg_cr, ctrl->regs + S3C_CIOCROFF);
+
+ return 0;
+}
+
+int fimc50_hwset_output_offset(struct fimc_control *ctrl, u32 pixelformat,
+ struct v4l2_rect *bounds,
+ struct v4l2_rect *crop)
+{
+ u32 cfg_y = 0, cfg_cb = 0, cfg_cr = 0;
+
+ if (!crop->left && !crop->top && (bounds->width == crop->width) &&
+ (bounds->height == crop->height))
+ return -EINVAL;
+
+ fimc_dbg("%s: left: %d, top: %d, width: %d, height: %d\n",
+ __func__, crop->left, crop->top, crop->width, crop->height);
+
+ switch (pixelformat) {
+ /* 1 plane, 32 bits per pixel */
+ case V4L2_PIX_FMT_RGB32:
+ cfg_y |= S3C_CIOYOFF_HORIZONTAL(crop->left);
+ cfg_y |= S3C_CIOYOFF_VERTICAL(crop->top);
+ break;
+
+ /* 1 plane, 16 bits per pixel */
+ case V4L2_PIX_FMT_YUYV: /* fall through */
+ case V4L2_PIX_FMT_UYVY: /* fall through */
+ case V4L2_PIX_FMT_VYUY: /* fall through */
+ case V4L2_PIX_FMT_YVYU: /* fall through */
+ case V4L2_PIX_FMT_RGB565:
+ cfg_y |= S3C_CIOYOFF_HORIZONTAL(crop->left);
+ cfg_y |= S3C_CIOYOFF_VERTICAL(crop->top);
+ break;
+
+ /* 2 planes, 16 bits per pixel */
+ case V4L2_PIX_FMT_NV16: /* fall through */
+ case V4L2_PIX_FMT_NV61:
+ cfg_y |= S3C_CIOYOFF_HORIZONTAL(crop->left);
+ cfg_y |= S3C_CIOYOFF_VERTICAL(crop->top);
+ cfg_cb |= S3C_CIOCBOFF_HORIZONTAL(crop->left);
+ cfg_cb |= S3C_CIOCBOFF_VERTICAL(crop->top);
+ break;
+
+ /* 2 planes, 12 bits per pixel */
+ case V4L2_PIX_FMT_NV12: /* fall through */
+ case V4L2_PIX_FMT_NV12T: /* fall through */
+ case V4L2_PIX_FMT_NV21:
+ cfg_y |= S3C_CIOYOFF_HORIZONTAL(crop->left);
+ cfg_y |= S3C_CIOYOFF_VERTICAL(crop->top);
+ cfg_cb |= S3C_CIOCBOFF_HORIZONTAL(crop->left);
+ cfg_cb |= S3C_CIOCBOFF_VERTICAL(crop->top);
+ break;
+
+ /* 3 planes, 16 bits per pixel */
+ case V4L2_PIX_FMT_YUV422P:
+ cfg_y |= S3C_CIOYOFF_HORIZONTAL(crop->left);
+ cfg_y |= S3C_CIOYOFF_VERTICAL(crop->top);
+ cfg_cb |= S3C_CIOCBOFF_HORIZONTAL(crop->left);
+ cfg_cb |= S3C_CIOCBOFF_VERTICAL(crop->top);
+ cfg_cr |= S3C_CIOCROFF_HORIZONTAL(crop->left);
+ cfg_cr |= S3C_CIOCROFF_VERTICAL(crop->top);
+ break;
+
+ /* 3 planes, 12 bits per pixel */
+ case V4L2_PIX_FMT_YUV420:
+ cfg_y |= S3C_CIOYOFF_HORIZONTAL(crop->left);
+ cfg_y |= S3C_CIOYOFF_VERTICAL(crop->top);
+ cfg_cb |= S3C_CIOCBOFF_HORIZONTAL(crop->left);
+ cfg_cb |= S3C_CIOCBOFF_VERTICAL(crop->top);
+ cfg_cr |= S3C_CIOCROFF_HORIZONTAL(crop->left);
+ cfg_cr |= S3C_CIOCROFF_VERTICAL(crop->top);
+ break;
+
+ default:
+ break;
+ }
+
+ writel(cfg_y, ctrl->regs + S3C_CIOYOFF);
+ writel(cfg_cb, ctrl->regs + S3C_CIOCBOFF);
+ writel(cfg_cr, ctrl->regs + S3C_CIOCROFF);
+
+ return 0;
+}
+
+int fimc_hwset_output_offset(struct fimc_control *ctrl, u32 pixelformat,
+ struct v4l2_rect *bounds,
+ struct v4l2_rect *crop)
+{
+ struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
+
+ if (pdata->hw_ver == 0x50 || pdata->hw_ver == 0x45)
+ fimc50_hwset_output_offset(ctrl, pixelformat, bounds, crop);
+ else
+ fimc40_hwset_output_offset(ctrl, pixelformat, bounds, crop);
+
+ return 0;
+}
+
+int fimc40_hwset_input_offset(struct fimc_control *ctrl, u32 pixelformat,
+ struct v4l2_rect *bounds,
+ struct v4l2_rect *crop)
+{
+ u32 cfg_y = 0, cfg_cb = 0;
+
+ if (crop->left || crop->top ||
+ (bounds->width != crop->width) ||
+ (bounds->height != crop->height)) {
+ switch (pixelformat) {
+ case V4L2_PIX_FMT_YUYV: /* fall through */
+ case V4L2_PIX_FMT_RGB565:
+ cfg_y |= S3C_CIIYOFF_HORIZONTAL(crop->left * 2);
+ cfg_y |= S3C_CIIYOFF_VERTICAL(crop->top);
+ break;
+ case V4L2_PIX_FMT_RGB32:
+ cfg_y |= S3C_CIIYOFF_HORIZONTAL(crop->left * 4);
+ cfg_y |= S3C_CIIYOFF_VERTICAL(crop->top);
+ break;
+ case V4L2_PIX_FMT_NV12: /* fall through */
+ case V4L2_PIX_FMT_NV12T:
+ cfg_y |= S3C_CIIYOFF_HORIZONTAL(crop->left);
+ cfg_y |= S3C_CIIYOFF_VERTICAL(crop->top);
+ cfg_cb |= S3C_CIICBOFF_HORIZONTAL(crop->left);
+ cfg_cb |= S3C_CIICBOFF_VERTICAL(crop->top / 2);
+
+ break;
+ default:
+ fimc_err("%s: Invalid pixelformt : %d\n",
+ __func__, pixelformat);
+ }
+ }
+
+ writel(cfg_y, ctrl->regs + S3C_CIIYOFF);
+ writel(cfg_cb, ctrl->regs + S3C_CIICBOFF);
+
+ return 0;
+}
+
+int fimc50_hwset_input_offset(struct fimc_control *ctrl, u32 pixelformat,
+ struct v4l2_rect *bounds,
+ struct v4l2_rect *crop)
+{
+ u32 cfg_y = 0, cfg_cb = 0, cfg_cr = 0;
+
+ if (crop->left || crop->top ||
+ (bounds->width != crop->width) ||
+ (bounds->height != crop->height)) {
+ switch (pixelformat) {
+ case V4L2_PIX_FMT_YUYV: /* fall through */
+ case V4L2_PIX_FMT_UYVY: /* fall through */
+ case V4L2_PIX_FMT_YVYU: /* fall through */
+ case V4L2_PIX_FMT_VYUY: /* fall through */
+ case V4L2_PIX_FMT_RGB565:
+ cfg_y |= S3C_CIIYOFF_HORIZONTAL(crop->left);
+ cfg_y |= S3C_CIIYOFF_VERTICAL(crop->top);
+ break;
+ case V4L2_PIX_FMT_RGB32:
+ cfg_y |= S3C_CIIYOFF_HORIZONTAL(crop->left);
+ cfg_y |= S3C_CIIYOFF_VERTICAL(crop->top);
+ break;
+ case V4L2_PIX_FMT_NV12: /* fall through*/
+ case V4L2_PIX_FMT_NV21: /* fall through*/
+ case V4L2_PIX_FMT_NV12T:
+ cfg_y |= S3C_CIIYOFF_HORIZONTAL(crop->left);
+ cfg_y |= S3C_CIIYOFF_VERTICAL(crop->top);
+ cfg_cb |= S3C_CIICBOFF_HORIZONTAL(crop->left);
+ cfg_cb |= S3C_CIICBOFF_VERTICAL(crop->top);
+ break;
+ case V4L2_PIX_FMT_NV16: /* fall through */
+ case V4L2_PIX_FMT_NV61:
+ cfg_y |= S3C_CIIYOFF_HORIZONTAL(crop->left);
+ cfg_y |= S3C_CIIYOFF_VERTICAL(crop->top);
+ cfg_cb |= S3C_CIICBOFF_HORIZONTAL(crop->left);
+ cfg_cb |= S3C_CIICBOFF_VERTICAL(crop->top);
+ break;
+ case V4L2_PIX_FMT_YUV420:
+ cfg_y |= S3C_CIIYOFF_HORIZONTAL(crop->left);
+ cfg_y |= S3C_CIIYOFF_VERTICAL(crop->top);
+ cfg_cb |= S3C_CIICBOFF_HORIZONTAL(crop->left);
+ cfg_cb |= S3C_CIICBOFF_VERTICAL(crop->top);
+ cfg_cr |= S3C_CIICROFF_HORIZONTAL(crop->left);
+ cfg_cr |= S3C_CIICROFF_VERTICAL(crop->top);
+ break;
+ default:
+ fimc_err("%s: Invalid pixelformt : %d\n",
+ __func__, pixelformat);
+ }
+ }
+
+ writel(cfg_y, ctrl->regs + S3C_CIIYOFF);
+ writel(cfg_cb, ctrl->regs + S3C_CIICBOFF);
+ writel(cfg_cr, ctrl->regs + S3C_CIICROFF);
+
+ return 0;
+}
+
+int fimc_hwset_input_offset(struct fimc_control *ctrl, u32 pixelformat,
+ struct v4l2_rect *bounds,
+ struct v4l2_rect *crop)
+{
+ struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
+
+ if (pdata->hw_ver == 0x50)
+ fimc50_hwset_input_offset(ctrl, pixelformat, bounds, crop);
+ else
+ fimc40_hwset_input_offset(ctrl, pixelformat, bounds, crop);
+
+ return 0;
+}
+
+int fimc_hwset_org_input_size(struct fimc_control *ctrl, u32 width, u32 height)
+{
+ u32 cfg = 0;
+
+ cfg |= S3C_ORGISIZE_HORIZONTAL(width);
+ cfg |= S3C_ORGISIZE_VERTICAL(height);
+
+ writel(cfg, ctrl->regs + S3C_ORGISIZE);
+
+ return 0;
+}
+
+int fimc_hwset_org_output_size(struct fimc_control *ctrl, u32 width, u32 height)
+{
+ struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
+ u32 cfg = 0;
+
+ cfg |= S3C_ORGOSIZE_HORIZONTAL(width);
+ cfg |= S3C_ORGOSIZE_VERTICAL(height);
+
+ writel(cfg, ctrl->regs + S3C_ORGOSIZE);
+
+ if (pdata->hw_ver != 0x40) {
+ cfg = readl(ctrl->regs + S3C_CIGCTRL);
+ cfg &= ~S3C_CIGCTRL_CSC_MASK;
+
+ if (width >= FIMC_HD_WIDTH)
+ cfg |= S3C_CIGCTRL_CSC_ITU709;
+ else
+ cfg |= S3C_CIGCTRL_CSC_ITU601;
+
+ writel(cfg, ctrl->regs + S3C_CIGCTRL);
+ }
+
+ return 0;
+}
+
+int fimc_hwset_ext_output_size(struct fimc_control *ctrl, u32 width, u32 height)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CIEXTEN);
+
+ cfg &= ~S3C_CIEXTEN_TARGETH_EXT_MASK;
+ cfg &= ~S3C_CIEXTEN_TARGETV_EXT_MASK;
+ cfg |= S3C_CIEXTEN_TARGETH_EXT(width);
+ cfg |= S3C_CIEXTEN_TARGETV_EXT(height);
+
+ writel(cfg, ctrl->regs + S3C_CIEXTEN);
+
+ return 0;
+}
+
+int fimc_hwset_input_addr_style(struct fimc_control *ctrl, u32 pixelformat)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CIDMAPARAM);
+ cfg &= ~S3C_CIDMAPARAM_R_MODE_MASK;
+
+ if (pixelformat == V4L2_PIX_FMT_NV12T)
+ cfg |= S3C_CIDMAPARAM_R_MODE_64X32;
+ else
+ cfg |= S3C_CIDMAPARAM_R_MODE_LINEAR;
+
+ writel(cfg, ctrl->regs + S3C_CIDMAPARAM);
+
+ return 0;
+}
+
+int fimc_hwset_output_addr_style(struct fimc_control *ctrl, u32 pixelformat)
+{
+ u32 cfg = readl(ctrl->regs + S3C_CIDMAPARAM);
+ cfg &= ~S3C_CIDMAPARAM_W_MODE_MASK;
+
+ if (pixelformat == V4L2_PIX_FMT_NV12T)
+ cfg |= S3C_CIDMAPARAM_W_MODE_64X32;
+ else
+ cfg |= S3C_CIDMAPARAM_W_MODE_LINEAR;
+
+ writel(cfg, ctrl->regs + S3C_CIDMAPARAM);
+
+ return 0;
+}
+
+int fimc_hw_wait_winoff(struct fimc_control *ctrl)
+{
+ struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
+ u32 cfg = readl(ctrl->regs + S3C_CISTATUS);
+ u32 status = S3C_CISTATUS_GET_LCD_STATUS(cfg);
+ int i = FIMC_FIFOOFF_CNT;
+
+ if (pdata->hw_ver == 0x40)
+ return 0;
+
+ while (status && i--) {
+ cfg = readl(ctrl->regs + S3C_CISTATUS);
+ status = S3C_CISTATUS_GET_LCD_STATUS(cfg);
+ }
+
+ if (i < 1) {
+ fimc_err("Fail : %s\n", __func__);
+ return -EBUSY;
+ } else
+ return 0;
+}
+
+int fimc_hw_wait_stop_input_dma(struct fimc_control *ctrl)
+{
+ struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
+ u32 cfg = readl(ctrl->regs + S3C_MSCTRL);
+ u32 status = S3C_MSCTRL_GET_INDMA_STATUS(cfg);
+ int i = FIMC_FIFOOFF_CNT, j = FIMC_FIFOOFF_CNT;
+
+ if (pdata->hw_ver == 0x40)
+ return 0;
+
+ while (status && i--) {
+ cfg = readl(ctrl->regs + S3C_MSCTRL);
+ status = S3C_MSCTRL_GET_INDMA_STATUS(cfg);
+ }
+
+ cfg = readl(ctrl->regs + S3C_CISTATUS);
+ status = S3C_CISTATUS_GET_ENVID_STATUS(cfg);
+ while (status && j--) {
+ cfg = readl(ctrl->regs + S3C_CISTATUS);
+ status = S3C_CISTATUS_GET_ENVID_STATUS(cfg);
+ }
+
+ if ((i < 1) || (j < 1)) {
+ fimc_err("Fail : %s\n", __func__);
+ return -EBUSY;
+ } else {
+ return 0;
+ }
+}
+
+int fimc_hwset_input_lineskip(struct fimc_control *ctrl)
+{
+ struct s3c_platform_fimc *pdata = to_fimc_plat(ctrl->dev);
+ u32 cfg = 0;
+
+ if (pdata->hw_ver == 0x40)
+ return 0;
+
+ cfg = S3C_CIILINESKIP(ctrl->sc.skipline);
+
+ writel(cfg, ctrl->regs + S3C_CIILINESKIP_Y);
+ writel(cfg, ctrl->regs + S3C_CIILINESKIP_CB);
+ writel(cfg, ctrl->regs + S3C_CIILINESKIP_CR);
+
+ return 0;
+}
+
+int fimc_hw_reset_camera(struct fimc_control *ctrl)
+{
+ return 0;
+}
diff --git a/drivers/media/video/samsung/fimc/fimc_v4l2.c b/drivers/media/video/samsung/fimc/fimc_v4l2.c
new file mode 100644
index 0000000..73202f4
--- /dev/null
+++ b/drivers/media/video/samsung/fimc/fimc_v4l2.c
@@ -0,0 +1,303 @@
+/* linux/drivers/media/video/samsung/fimc/fimc_v4l2.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * V4L2 interface support file for Samsung Camera Interface (FIMC) 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/fs.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/videodev2.h>
+#include <linux/videodev2_samsung.h>
+#include <media/v4l2-ioctl.h>
+#include <plat/fimc.h>
+#include <linux/clk.h>
+
+#include "fimc.h"
+
+static int fimc_querycap(struct file *filp, void *fh,
+ struct v4l2_capability *cap)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+
+ fimc_info1("%s: called\n", __func__);
+
+ strcpy(cap->driver, "Samsung FIMC Driver");
+ strlcpy(cap->card, ctrl->vd->name, sizeof(cap->card));
+ sprintf(cap->bus_info, "FIMC AHB-bus");
+
+ cap->version = 0;
+ cap->capabilities = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT |
+ V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_STREAMING);
+
+ return 0;
+}
+
+static int fimc_reqbufs(struct file *filp, void *fh,
+ struct v4l2_requestbuffers *b)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ret = -1;
+
+ if (b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ ret = fimc_reqbufs_capture(fh, b);
+ } else if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+ ret = fimc_reqbufs_output(fh, b);
+ } else {
+ fimc_err("V4L2_BUF_TYPE_VIDEO_CAPTURE and "
+ "V4L2_BUF_TYPE_VIDEO_OUTPUT are only supported\n");
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int fimc_querybuf(struct file *filp, void *fh, struct v4l2_buffer *b)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ret = -1;
+
+ if (b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ ret = fimc_querybuf_capture(fh, b);
+ } else if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+ ret = fimc_querybuf_output(fh, b);
+ } else {
+ fimc_err("V4L2_BUF_TYPE_VIDEO_CAPTURE and "
+ "V4L2_BUF_TYPE_VIDEO_OUTPUT are only supported\n");
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+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) {
+ ret = fimc_g_ctrl_output(fh, c);
+ } else {
+ fimc_err("%s: Invalid case\n", __func__);
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+static int fimc_s_ctrl(struct file *filp, void *fh, struct v4l2_control *c)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ret = -1;
+
+ if (ctrl->cap != NULL) {
+ ret = fimc_s_ctrl_capture(fh, c);
+ } else if (ctrl->out != NULL) {
+ ret = fimc_s_ctrl_output(filp, fh, c);
+ } else {
+ fimc_err("%s: Invalid case\n", __func__);
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+static int fimc_s_ext_ctrls(struct file *filp, void *fh,
+ struct v4l2_ext_controls *c)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ret = -1;
+
+ if (ctrl->cap != NULL) {
+ ret = fimc_s_ext_ctrls_capture(fh, c);
+ } else {
+ fimc_err("%s: Invalid case\n", __func__);
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+static int fimc_cropcap(struct file *filp, void *fh, struct v4l2_cropcap *a)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ret = -1;
+
+ if (a->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ ret = fimc_cropcap_capture(fh, a);
+ } else if (a->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+ ret = fimc_cropcap_output(fh, a);
+ } else {
+ fimc_err("V4L2_BUF_TYPE_VIDEO_CAPTURE and "
+ "V4L2_BUF_TYPE_VIDEO_OUTPUT are only supported\n");
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int fimc_g_crop(struct file *filp, void *fh, struct v4l2_crop *a)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ret = -1;
+
+ if (a->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ ret = fimc_g_crop_capture(fh, a);
+ } else if (a->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+ ret = fimc_g_crop_output(fh, a);
+ } else {
+ fimc_err("V4L2_BUF_TYPE_VIDEO_CAPTURE and "
+ "V4L2_BUF_TYPE_VIDEO_OUTPUT are only supported\n");
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int fimc_s_crop(struct file *filp, void *fh, struct v4l2_crop *a)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ret = -1;
+
+ if (a->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ ret = fimc_s_crop_capture(fh, a);
+ } else if (a->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+ ret = fimc_s_crop_output(fh, a);
+ } else {
+ fimc_err("V4L2_BUF_TYPE_VIDEO_CAPTURE and "
+ "V4L2_BUF_TYPE_VIDEO_OUTPUT are only supported\n");
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int fimc_streamon(struct file *filp, void *fh, enum v4l2_buf_type i)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ struct s3c_platform_fimc *pdata;
+ int ret = -1;
+
+ pdata = to_fimc_plat(ctrl->dev);
+
+ if (i == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ ret = fimc_streamon_capture(fh);
+ } else if (i == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+ ret = fimc_streamon_output(fh);
+ } else {
+ fimc_err("V4L2_BUF_TYPE_VIDEO_CAPTURE and "
+ "V4L2_BUF_TYPE_VIDEO_OUTPUT are only supported\n");
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int fimc_streamoff(struct file *filp, void *fh, enum v4l2_buf_type i)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ struct s3c_platform_fimc *pdata;
+ int ret = -1;
+
+ pdata = to_fimc_plat(ctrl->dev);
+
+ if (i == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ ret = fimc_streamoff_capture(fh);
+ } else if (i == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+ ret = fimc_streamoff_output(fh);
+ } else {
+ fimc_err("V4L2_BUF_TYPE_VIDEO_CAPTURE and "
+ "V4L2_BUF_TYPE_VIDEO_OUTPUT are only supported\n");
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int fimc_qbuf(struct file *filp, void *fh, struct v4l2_buffer *b)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ret = -1;
+
+ if (b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ ret = fimc_qbuf_capture(fh, b);
+ } else if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+ ret = fimc_qbuf_output(fh, b);
+ } else {
+ fimc_err("V4L2_BUF_TYPE_VIDEO_CAPTURE and "
+ "V4L2_BUF_TYPE_VIDEO_OUTPUT are only supported\n");
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int fimc_dqbuf(struct file *filp, void *fh, struct v4l2_buffer *b)
+{
+ struct fimc_control *ctrl = ((struct fimc_prv_data *)fh)->ctrl;
+ int ret = -1;
+
+ if (b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ ret = fimc_dqbuf_capture(fh, b);
+ } else if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+ ret = fimc_dqbuf_output(fh, b);
+ } else {
+ fimc_err("V4L2_BUF_TYPE_VIDEO_CAPTURE and "
+ "V4L2_BUF_TYPE_VIDEO_OUTPUT are only supported\n");
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+const struct v4l2_ioctl_ops fimc_v4l2_ops = {
+ .vidioc_querycap = fimc_querycap,
+ .vidioc_reqbufs = fimc_reqbufs,
+ .vidioc_querybuf = fimc_querybuf,
+ .vidioc_g_ctrl = fimc_g_ctrl,
+ .vidioc_s_ctrl = fimc_s_ctrl,
+ .vidioc_s_ext_ctrls = fimc_s_ext_ctrls,
+ .vidioc_cropcap = fimc_cropcap,
+ .vidioc_g_crop = fimc_g_crop,
+ .vidioc_s_crop = fimc_s_crop,
+ .vidioc_streamon = fimc_streamon,
+ .vidioc_streamoff = fimc_streamoff,
+ .vidioc_qbuf = fimc_qbuf,
+ .vidioc_dqbuf = fimc_dqbuf,
+ .vidioc_enum_fmt_vid_cap = fimc_enum_fmt_vid_capture,
+ .vidioc_g_fmt_vid_cap = fimc_g_fmt_vid_capture,
+ .vidioc_s_fmt_vid_cap = fimc_s_fmt_vid_capture,
+ .vidioc_try_fmt_vid_cap = fimc_try_fmt_vid_capture,
+ .vidioc_enum_input = fimc_enum_input,
+ .vidioc_g_input = fimc_g_input,
+ .vidioc_s_input = fimc_s_input,
+ .vidioc_g_parm = fimc_g_parm,
+ .vidioc_s_parm = fimc_s_parm,
+ .vidioc_queryctrl = fimc_queryctrl,
+ .vidioc_querymenu = fimc_querymenu,
+ .vidioc_g_fmt_vid_out = fimc_g_fmt_vid_out,
+ .vidioc_s_fmt_vid_out = fimc_s_fmt_vid_out,
+ .vidioc_try_fmt_vid_out = fimc_try_fmt_vid_out,
+ .vidioc_g_fbuf = fimc_g_fbuf,
+ .vidioc_s_fbuf = fimc_s_fbuf,
+ .vidioc_try_fmt_vid_overlay = fimc_try_fmt_overlay,
+ .vidioc_g_fmt_vid_overlay = fimc_g_fmt_vid_overlay,
+ .vidioc_s_fmt_vid_overlay = fimc_s_fmt_vid_overlay,
+};
diff --git a/drivers/media/video/samsung/jpeg_v2/Kconfig b/drivers/media/video/samsung/jpeg_v2/Kconfig
new file mode 100644
index 0000000..291aa90
--- /dev/null
+++ b/drivers/media/video/samsung/jpeg_v2/Kconfig
@@ -0,0 +1,15 @@
+#
+# Configuration for JPEG
+#
+
+config VIDEO_JPEG_V2
+ bool "Samsung JPEG driver"
+ depends on VIDEO_SAMSUNG
+ default n
+ ---help---
+ This is a JPEG for Samsung S5PV210
+
+config VIDEO_JPEG_DEBUG
+ bool "print JPEG debug message"
+ depends on VIDEO_JPEG_V2
+ default n
diff --git a/drivers/media/video/samsung/jpeg_v2/Makefile b/drivers/media/video/samsung/jpeg_v2/Makefile
new file mode 100644
index 0000000..b7db901
--- /dev/null
+++ b/drivers/media/video/samsung/jpeg_v2/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_VIDEO_JPEG_V2) += jpg_mem.o jpg_misc.o jpg_opr.o s3c-jpeg.o
+EXTRA_CFLAGS += -Idrivers/media/video
+
diff --git a/drivers/media/video/samsung/jpeg_v2/jpg_conf.h b/drivers/media/video/samsung/jpeg_v2/jpg_conf.h
new file mode 100644
index 0000000..99fcb0d
--- /dev/null
+++ b/drivers/media/video/samsung/jpeg_v2/jpg_conf.h
@@ -0,0 +1,282 @@
+/* linux/drivers/media/video/samsung/jpeg_v2/jpg-conf.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Definition Quantization Table for Jpeg encoder/docoder
+ *
+ * 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 __JPG_CONF_H__
+#define __JPG_CONF_H__
+
+
+const unsigned char qtbl_luminance[4][64] = {
+ /* level 1 - high quality */
+ {
+ 8, 6, 6, 8, 12, 14, 16, 17,
+ 6, 6, 6, 8, 10, 13, 12, 15,
+ 6, 6, 7, 8, 13, 14, 18, 24,
+ 8, 8, 8, 14, 13, 19, 24, 35,
+ 12, 10, 13, 13, 20, 26, 34, 39,
+ 14, 13, 14, 19, 26, 34, 39, 39,
+ 16, 12, 18, 24, 34, 39, 39, 39,
+ 17, 15, 24, 35, 39, 39, 39, 39
+ },
+
+ /* level 2 */
+ {
+ 12, 8, 8, 12, 17, 21, 24, 23,
+ 8, 9, 9, 11, 15, 19, 18, 23,
+ 8, 9, 10, 12, 19, 20, 27, 36,
+ 12, 11, 12, 21, 20, 28, 36, 53,
+ 17, 15, 19, 20, 30, 39, 51, 59,
+ 21, 19, 20, 28, 39, 51, 59, 59,
+ 24, 18, 27, 36, 51, 59, 59, 59,
+ 23, 23, 36, 53, 59, 59, 59, 59
+ },
+
+ /* level 3 */
+ {
+ 16, 11, 11, 16, 23, 27, 31, 30,
+ 11, 12, 12, 15, 20, 23, 23, 30,
+ 11, 12, 13, 16, 23, 26, 35, 47,
+ 16, 15, 16, 23, 26, 37, 47, 64,
+ 23, 20, 23, 26, 39, 51, 64, 64,
+ 27, 23, 26, 37, 51, 64, 64, 64,
+ 31, 23, 35, 47, 64, 64, 64, 64,
+ 30, 30, 47, 64, 64, 64, 64, 64
+
+ },
+
+ /* level 4 - low quality */
+ {
+ 20, 16, 25, 39, 50, 46, 62, 68,
+ 16, 18, 23, 38, 38, 53, 65, 68,
+ 25, 23, 31, 38, 53, 65, 68, 68,
+ 39, 38, 38, 53, 65, 68, 68, 68,
+ 50, 38, 53, 65, 68, 68, 68, 68,
+ 46, 53, 65, 68, 68, 68, 68, 68,
+ 62, 65, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68
+ }
+
+
+};
+
+const unsigned char qtbl_chrominance[4][64] = {
+ /* level 1 - high quality */
+ {
+ 9, 8, 9, 11, 14, 17, 19, 24,
+ 8, 10, 9, 11, 14, 13, 17, 22,
+ 9, 9, 13, 14, 13, 15, 23, 26,
+ 11, 11, 14, 14, 15, 20, 26, 33,
+ 14, 14, 13, 15, 20, 24, 33, 39,
+ 17, 13, 15, 20, 24, 32, 39, 39,
+ 19, 17, 23, 26, 33, 39, 39, 39,
+ 24, 22, 26, 33, 39, 39, 39, 39
+ },
+
+ /* level 2 */
+ {
+ 13, 11, 13, 16, 20, 20, 29, 37,
+ 11, 14, 14, 14, 16, 20, 26, 32,
+ 13, 14, 15, 17, 20, 23, 35, 40,
+ 16, 14, 17, 21, 23, 30, 40, 50,
+ 20, 16, 20, 23, 30, 37, 50, 59,
+ 20, 20, 23, 30, 37, 48, 59, 59,
+ 29, 26, 35, 40, 50, 59, 59, 59,
+ 37, 32, 40, 50, 59, 59, 59, 59
+ },
+
+
+ /* level 3 */
+ {
+ 17, 15, 17, 21, 20, 26, 38, 48,
+ 15, 19, 18, 17, 20, 26, 35, 43,
+ 17, 18, 20, 22, 26, 30, 46, 53,
+ 21, 17, 22, 28, 30, 39, 53, 64,
+ 20, 20, 26, 30, 39, 48, 64, 64,
+ 26, 26, 30, 39, 48, 63, 64, 64,
+ 38, 35, 46, 53, 64, 64, 64, 64,
+ 48, 43, 53, 64, 64, 64, 64, 64
+
+
+ },
+
+ /* level 4 - low quality */
+ {
+ 21, 25, 32, 38, 54, 68, 68, 68,
+ 25, 28, 24, 38, 54, 68, 68, 68,
+ 32, 24, 32, 43, 66, 68, 68, 68,
+ 38, 38, 43, 53, 68, 68, 68, 68,
+ 54, 54, 66, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, 68, 68
+
+ }
+
+};
+
+const unsigned char qtbl0[64] = {
+ 0x10, 0x0B, 0x0A, 0x10, 0x18, 0x28, 0x33, 0x3D,
+ 0x0C, 0x0C, 0x0E, 0x13, 0x1A, 0x3A, 0x3C, 0x37,
+ 0x0E, 0x0D, 0x10, 0x18, 0x28, 0x39, 0x45, 0x38,
+ 0x0E, 0x11, 0x16, 0x1D, 0x33, 0x57, 0x50, 0x3E,
+ 0x12, 0x16, 0x25, 0x38, 0x44, 0x6D, 0x67, 0x4D,
+ 0x18, 0x23, 0x37, 0x40, 0x51, 0x68, 0x71, 0x5C,
+ 0x31, 0x40, 0x4E, 0x57, 0x67, 0x79, 0x78, 0x65,
+ 0x48, 0x5C, 0x5F, 0x62, 0x70, 0x64, 0x67, 0x63
+};
+
+/* Added Quantization Table */
+const unsigned char std_chrominance_quant_tbl_plus[64] = {
+ 0x11, 0x12, 0x18, 0x2F, 0x63, 0x63, 0x63, 0x63,
+ 0x12, 0x15, 0x1A, 0x42, 0x63, 0x63, 0x63, 0x63,
+ 0x18, 0x1A, 0x38, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x2F, 0x42, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63
+};
+
+/* Quantization Table0 */
+unsigned char std_luminance_quant_tbl[64] = {
+ 1, 1, 2, 1, 1, 2, 2, 2,
+ 2, 3, 2, 2, 3, 3, 6, 4,
+ 3, 3, 3, 3, 7, 5, 8, 4,
+ 6, 8, 8, 10, 9, 8, 7, 11,
+ 8, 10, 14, 13, 11, 10, 10, 12,
+ 10, 8, 8, 11, 16, 12, 12, 13,
+ 15, 15, 15, 15, 9, 11, 16, 17,
+ 15, 14, 17, 13, 14, 14, 14, 1
+};
+
+/* Quantization Table1 */
+unsigned char std_chrominance_quant_tbl[64] = {
+ 4, 4, 4, 5, 4, 5, 9, 5,
+ 5, 9, 15, 10, 8, 10, 15, 26,
+ 19, 9, 9, 19, 26, 26, 26, 26,
+ 13, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26
+};
+
+/* Huffman Table */
+unsigned char hdctbl0[16] = {
+ 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0
+};
+
+unsigned char hdctblg0[12] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb
+};
+
+unsigned char hactbl0[16] = {
+ 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d
+};
+
+const unsigned char hactblg0[162] = {
+ 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
+ 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
+ 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
+ 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
+ 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
+ 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
+ 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+ 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
+ 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
+ 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
+ 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
+ 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
+ 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+ 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
+ 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
+ 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
+ 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
+ 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
+ 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+ 0xf9, 0xfa
+};
+
+/* Huffman Table0 */
+unsigned char len_dc_luminance[16] = {
+ 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0
+};
+
+unsigned char val_dc_luminance[12] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
+
+unsigned char len_ac_luminance[16] = {
+ 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d
+};
+
+unsigned char val_ac_luminance[162] = {
+ 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
+ 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
+ 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
+ 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
+ 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
+ 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
+ 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+ 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
+ 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
+ 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
+ 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
+ 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
+ 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+ 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
+ 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
+ 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
+ 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
+ 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
+ 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+ 0xf9, 0xfa
+};
+
+/* Huffman Table1 */
+unsigned char len_dc_chrominance[16] = {
+ 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0
+};
+
+unsigned char val_dc_chrominance[12] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
+};
+
+unsigned char len_ac_chrominance[16] = {
+ 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77
+};
+
+unsigned char val_ac_chrominance[162] = {
+ 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
+ 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
+ 0x13, 0x22, 0x32, 0x81, 0x81, 0x08, 0x14, 0x42,
+ 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52,
+ 0xf0, 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24,
+ 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a,
+ 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57,
+ 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77,
+ 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86,
+ 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95,
+ 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4,
+ 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3,
+ 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2,
+ 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca,
+ 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
+ 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
+ 0xe9, 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9
+};
+
+#endif
diff --git a/drivers/media/video/samsung/jpeg_v2/jpg_mem.c b/drivers/media/video/samsung/jpeg_v2/jpg_mem.c
new file mode 100644
index 0000000..5f46b8d
--- /dev/null
+++ b/drivers/media/video/samsung/jpeg_v2/jpg_mem.c
@@ -0,0 +1,61 @@
+/* linux/drivers/media/video/samsung/jpeg_v2/jpg_mem.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Operation for Jpeg encoder/docoder with memory
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/io.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/types.h>
+
+#include "jpg_mem.h"
+#include "jpg_misc.h"
+#include "jpg_opr.h"
+
+/*
+ * Function: phy_to_vir_addr
+ * Parameters: phy_addr, mem_size
+ * Return Value: vir_addr
+ * Implementation Notes: memory mapping from physical addr to virtual addr
+ */
+void *phy_to_vir_addr(unsigned int phy_addr, int mem_size)
+{
+ void *reserved_mem;
+
+ reserved_mem = (void *)ioremap((unsigned long)phy_addr, (int)mem_size);
+
+ if (reserved_mem == NULL) {
+ jpg_err("phyical to virtual memory mapping was failed!\r\n");
+ return NULL;
+ }
+
+ return reserved_mem;
+}
+
+void *mem_move(void *dst, const void *src, unsigned int size)
+{
+ return memmove(dst, src, size);
+}
+
+void *mem_alloc(unsigned int size)
+{
+ void *alloc_mem;
+
+ alloc_mem = kmalloc((int)size, GFP_KERNEL);
+
+ if (alloc_mem == NULL) {
+ jpg_err("memory allocation failed!\r\n");
+ return NULL;
+ }
+
+ return alloc_mem;
+}
diff --git a/drivers/media/video/samsung/jpeg_v2/jpg_mem.h b/drivers/media/video/samsung/jpeg_v2/jpg_mem.h
new file mode 100644
index 0000000..3beb549
--- /dev/null
+++ b/drivers/media/video/samsung/jpeg_v2/jpg_mem.h
@@ -0,0 +1,111 @@
+/* linux/drivers/media/video/samsung/jpeg_v2/jpg_mem.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Definition for Operation of Jpeg encoder/docoder with memory
+ *
+ * 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 __JPG_MEM_H__
+#define __JPG_MEM_H__
+
+#include "jpg_misc.h"
+
+#include <linux/version.h>
+#include <plat/media.h>
+#include <mach/media.h>
+
+#define JPG_REG_BASE_ADDR (0xFB600000)
+
+#define jpg_data_base_addr \
+ (unsigned int)s5p_get_media_memory_bank(S5P_MDEV_JPEG, 0)
+#define jpg_reserved_mem_size \
+ ((unsigned int)s5p_get_media_memsize_bank(S5P_MDEV_JPEG, 0))
+
+#define COEF1_RGB_2_YUV 0x4d971e
+#define COEF2_RGB_2_YUV 0x2c5783
+#define COEF3_RGB_2_YUV 0x836e13
+
+/*
+ * JPEG HW Register Macro Definition
+ */
+#define JPG_1BIT_MASK 1
+#define JPG_4BIT_MASK 0xF
+
+/* SubSampling_Mode Mask is JPGMOD Register [2:0] bits mask */
+#define JPG_SMPL_MODE_MASK 0x07
+
+/* Restart Interval value in JPGDRI Register is 2*/
+#define JPG_RESTART_INTRAVEL 2
+
+/* HCLK_JPEG is CLK_GATE_D1_1 Register 5th bit */
+#define JPG_HCLK_JPEG_BIT 5
+/* SubSampling_Mode is JPGMOD Register 0th bit */
+#define JPG_SMPL_MODE_BIT 0
+/* Quantization Table #1 is JPGQHNO Register 8th bit */
+#define JPG_QUANT_TABLE1_BIT 8
+/* Quantization Table #2 is JPGQHNO Register 10th bit */
+#define JPG_QUANT_TABLE2_BIT 10
+/* Quantization Table #3 is JPGQHNO Register 12th bit */
+#define JPG_QUANT_TABLE3_BIT 12
+/* Mode Sel is JPGCMOD Register 5th bit */
+#define JPG_MODE_SEL_BIT 5
+
+#define JPG_DECODE (0x1 << 3)
+#define JPG_ENCODE (0x0 << 3)
+
+#define JPG_RESERVE_ZERO (0b000 << 2)
+
+#define ENABLE_MOTION_ENC (0x1<<3)
+#define DISABLE_MOTION_ENC (0x0<<3)
+
+#define ENABLE_MOTION_DEC (0x1<<0)
+#define DISABLE_MOTION_DEC (0x0<<0)
+
+#define ENABLE_HW_DEC (0x1<<2)
+#define DISABLE_HW_DEC (0x0<<2)
+
+#define INCREMENTAL_DEC (0x1<<3)
+#define NORMAL_DEC (0x0<<3)
+#define YCBCR_MEMORY (0x1<<5)
+
+#define ENABLE_IRQ (0xf<<3)
+
+struct jpegv2_limits {
+ unsigned int max_main_width;
+ unsigned int max_main_height;
+ unsigned int max_thumb_width;
+ unsigned int max_thumb_height;
+};
+
+struct jpegv2_buf {
+ unsigned int main_stream_start;
+ unsigned int main_stream_size;
+ unsigned int main_frame_start;
+ unsigned int main_frame_size;
+ unsigned int thumb_stream_start;
+ unsigned int thumb_stream_size;
+ unsigned int thumb_frame_start;
+ unsigned int thumb_frame_size;
+ unsigned int total_buf_size;
+};
+
+struct s5pc110_jpg_ctx {
+ unsigned int jpg_data_addr;
+ unsigned int img_data_addr;
+ unsigned int jpg_thumb_data_addr;
+ unsigned int img_thumb_data_addr;
+ int caller_process;
+ struct jpegv2_limits *limits;
+ struct jpegv2_buf *bufinfo;
+};
+
+void *phy_to_vir_addr(unsigned int phy_addr, int mem_size);
+void *mem_move(void *dst, const void *src, unsigned int size);
+void *mem_alloc(unsigned int size);
+#endif
+
diff --git a/drivers/media/video/samsung/jpeg_v2/jpg_misc.c b/drivers/media/video/samsung/jpeg_v2/jpg_misc.c
new file mode 100644
index 0000000..964baf6
--- /dev/null
+++ b/drivers/media/video/samsung/jpeg_v2/jpg_misc.c
@@ -0,0 +1,81 @@
+/* linux/drivers/media/video/samsung/jpeg_v2/jpg_misc.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Operation for Jpeg encoder/docoder with mutex
+ *
+ * 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 <stdarg.h>
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+
+#include <linux/version.h>
+
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+
+#include "jpg_misc.h"
+#include "jpg_mem.h"
+
+static struct mutex *h_mutex;
+
+/*
+ * Function: create_jpg_mutex
+ * Implementation Notes: Create Mutex handle
+ */
+struct mutex *create_jpg_mutex(void)
+{
+ h_mutex = kmalloc(sizeof(struct mutex), GFP_KERNEL);
+
+ if (h_mutex == NULL)
+ return NULL;
+
+ mutex_init(h_mutex);
+
+ return h_mutex;
+}
+
+/*
+ * Function: lock_jpg_mutex
+ * Implementation Notes: lock mutex
+ */
+unsigned long lock_jpg_mutex(void)
+{
+ mutex_lock(h_mutex);
+ return 1;
+}
+
+/*
+ * Function: unlock_jpg_mutex
+ * Implementation Notes: unlock mutex
+*/
+unsigned long unlock_jpg_mutex(void)
+{
+ mutex_unlock(h_mutex);
+
+ return 1;
+}
+
+
+/*
+ * Function: delete_jpg_mutex
+ * Implementation Notes: delete mutex handle
+ */
+void delete_jpg_mutex(void)
+{
+ if (h_mutex == NULL)
+ return;
+
+ mutex_destroy(h_mutex);
+}
+
diff --git a/drivers/media/video/samsung/jpeg_v2/jpg_misc.h b/drivers/media/video/samsung/jpeg_v2/jpg_misc.h
new file mode 100644
index 0000000..31422d2
--- /dev/null
+++ b/drivers/media/video/samsung/jpeg_v2/jpg_misc.h
@@ -0,0 +1,27 @@
+/* linux/drivers/media/video/samsung/jpeg_v2/jpg_misc.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Definition for Operation of Jpeg encoder/docoder with mutex
+ *
+ * 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 __JPG_MISC_H__
+#define __JPG_MISC_H__
+
+#include <linux/types.h>
+
+enum BOOL {FALSE, TRUE};
+
+#define INT_TIMEOUT 1000
+
+struct mutex *create_jpg_mutex(void);
+unsigned long lock_jpg_mutex(void);
+unsigned long unlock_jpg_mutex(void);
+void delete_jpg_mutex(void);
+
+#endif
diff --git a/drivers/media/video/samsung/jpeg_v2/jpg_opr.c b/drivers/media/video/samsung/jpeg_v2/jpg_opr.c
new file mode 100644
index 0000000..51a7979
--- /dev/null
+++ b/drivers/media/video/samsung/jpeg_v2/jpg_opr.c
@@ -0,0 +1,320 @@
+/* linux/drivers/media/video/samsung/jpeg_v2/jpg_opr.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Operation for Jpeg encoder/docoder
+ *
+ * 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/delay.h>
+#include <linux/io.h>
+
+#include "jpg_mem.h"
+#include "jpg_misc.h"
+#include "jpg_opr.h"
+#include "jpg_conf.h"
+
+#include "regs-jpeg.h"
+
+enum {
+ UNKNOWN,
+ BASELINE = 0xC0,
+ EXTENDED_SEQ = 0xC1,
+ PROGRESSIVE = 0xC2
+} jpg_sof_marker;
+
+enum jpg_return_status wait_for_interrupt(void)
+{
+ if (interruptible_sleep_on_timeout(&wait_queue_jpeg, \
+ INT_TIMEOUT) == 0) {
+ jpg_err("waiting for interrupt is timeout\n");
+ }
+
+ return jpg_irq_reason;
+}
+
+enum jpg_return_status decode_jpg(struct s5pc110_jpg_ctx *jpg_ctx,
+ struct jpg_dec_proc_param *dec_param)
+{
+ int ret;
+ enum sample_mode sample_mode;
+ unsigned int width, height;
+ jpg_dbg("enter decode_jpg function\n");
+
+ if (jpg_ctx)
+ reset_jpg(jpg_ctx);
+ else {
+ jpg_err("jpg ctx is NULL\n");
+ return JPG_FAIL;
+ }
+
+/* set jpeg clock register : power on */
+ writel(readl(s3c_jpeg_base + S3C_JPEG_CLKCON_REG) |
+ (S3C_JPEG_CLKCON_REG_POWER_ON_ACTIVATE),
+ s3c_jpeg_base + S3C_JPEG_CLKCON_REG);
+ /* set jpeg mod register : decode */
+ writel(readl(s3c_jpeg_base + S3C_JPEG_MOD_REG) |
+ (S3C_JPEG_MOD_REG_PROC_DEC),
+ s3c_jpeg_base + S3C_JPEG_MOD_REG);
+ /* set jpeg interrupt setting register */
+ writel(readl(s3c_jpeg_base + S3C_JPEG_INTSE_REG) |
+ (S3C_JPEG_INTSE_REG_RSTM_INT_EN |
+ S3C_JPEG_INTSE_REG_DATA_NUM_INT_EN |
+ S3C_JPEG_INTSE_REG_FINAL_MCU_NUM_INT_EN),
+ s3c_jpeg_base + S3C_JPEG_INTSE_REG);
+ /* set jpeg deocde ouput format register */
+ writel(readl(s3c_jpeg_base + S3C_JPEG_OUTFORM_REG) &
+ ~(S3C_JPEG_OUTFORM_REG_YCBCY420),
+ s3c_jpeg_base + S3C_JPEG_OUTFORM_REG);
+ writel(readl(s3c_jpeg_base + S3C_JPEG_OUTFORM_REG) |
+ (dec_param->out_format << 0),
+ s3c_jpeg_base + S3C_JPEG_OUTFORM_REG);
+
+ /* set the address of compressed input data */
+ writel(jpg_ctx->img_data_addr, s3c_jpeg_base + S3C_JPEG_IMGADR_REG);
+
+ /* set the address of decompressed image */
+ writel(jpg_ctx->jpg_data_addr, s3c_jpeg_base + S3C_JPEG_JPGADR_REG);
+
+ /* start decoding */
+ writel(readl(s3c_jpeg_base + S3C_JPEG_JRSTART_REG) |
+ S3C_JPEG_JRSTART_REG_ENABLE,
+ s3c_jpeg_base + S3C_JPEG_JSTART_REG);
+
+ ret = wait_for_interrupt();
+
+ if (ret != OK_ENC_OR_DEC) {
+ jpg_err("jpg decode error(%d)\n", ret);
+ return JPG_FAIL;
+ }
+
+ sample_mode = get_sample_type(jpg_ctx);
+ jpg_dbg("sample_mode : %d\n", sample_mode);
+
+ if (sample_mode == JPG_SAMPLE_UNKNOWN) {
+ jpg_err("jpg has invalid sample_mode\r\n");
+ return JPG_FAIL;
+ }
+
+ dec_param->sample_mode = sample_mode;
+
+ get_xy(jpg_ctx, &width, &height);
+ jpg_dbg("decode size:: width : %d height : %d\n", width, height);
+
+ dec_param->data_size = get_yuv_size(dec_param->out_format,
+ width, height);
+ dec_param->width = width;
+ dec_param->height = height;
+
+ return JPG_SUCCESS;
+}
+
+void reset_jpg(struct s5pc110_jpg_ctx *jpg_ctx)
+{
+ jpg_dbg("s3c_jpeg_base %p\n", s3c_jpeg_base);
+ writel(S3C_JPEG_SW_RESET_REG_ENABLE,
+ s3c_jpeg_base + S3C_JPEG_SW_RESET_REG);
+
+ do {
+ writel(S3C_JPEG_SW_RESET_REG_ENABLE,
+ s3c_jpeg_base + S3C_JPEG_SW_RESET_REG);
+ } while (((readl(s3c_jpeg_base + S3C_JPEG_SW_RESET_REG))
+ & S3C_JPEG_SW_RESET_REG_ENABLE)
+ == S3C_JPEG_SW_RESET_REG_ENABLE);
+}
+
+enum sample_mode get_sample_type(struct s5pc110_jpg_ctx *jpg_ctx)
+{
+ unsigned long jpgMode;
+ enum sample_mode sample_mode = JPG_SAMPLE_UNKNOWN;
+
+ jpgMode = readl(s3c_jpeg_base + S3C_JPEG_MOD_REG);
+
+ sample_mode =
+ ((jpgMode & JPG_SMPL_MODE_MASK) == JPG_444) ? JPG_444 :
+ ((jpgMode & JPG_SMPL_MODE_MASK) == JPG_422) ? JPG_422 :
+ ((jpgMode & JPG_SMPL_MODE_MASK) == JPG_420) ? JPG_420 :
+ ((jpgMode & JPG_SMPL_MODE_MASK) == JPG_400) ? JPG_400 :
+ ((jpgMode & JPG_SMPL_MODE_MASK) == JPG_411) ? JPG_411 :
+ JPG_SAMPLE_UNKNOWN;
+
+ return sample_mode;
+}
+
+void get_xy(struct s5pc110_jpg_ctx *jpg_ctx, unsigned int *x, unsigned int *y)
+{
+ *x = (readl(s3c_jpeg_base + S3C_JPEG_X_U_REG)<<8)|
+ readl(s3c_jpeg_base + S3C_JPEG_X_L_REG);
+ *y = (readl(s3c_jpeg_base + S3C_JPEG_Y_U_REG)<<8)|
+ readl(s3c_jpeg_base + S3C_JPEG_Y_L_REG);
+}
+
+unsigned int get_yuv_size(enum out_mode out_format,
+ unsigned int width, unsigned int height)
+{
+ switch (out_format) {
+ case YCBCR_422:
+
+ if (width % 16 != 0)
+ width += 16 - (width % 16);
+
+ if (height % 8 != 0)
+ height += 8 - (height % 8);
+
+ break;
+
+ case YCBCR_420:
+
+ if (width % 16 != 0)
+ width += 16 - (width % 16);
+
+ if (height % 16 != 0)
+ height += 16 - (height % 16);
+
+ break;
+
+ case YCBCR_SAMPLE_UNKNOWN:
+ break;
+ }
+
+ jpg_dbg("get_yuv_size width(%d) height(%d)\n", width, height);
+
+ switch (out_format) {
+ case YCBCR_422:
+ return width * height * 2;
+ case YCBCR_420:
+ return (width * height) + (width * height >> 1);
+ default:
+ return 0;
+ }
+}
+
+enum jpg_return_status encode_jpg(struct s5pc110_jpg_ctx *jpg_ctx,
+ struct jpg_enc_proc_param *enc_param)
+{
+
+ unsigned int i, ret;
+ unsigned int cmd_val;
+
+ if (enc_param->width <= 0
+ || enc_param->width > jpg_ctx->limits->max_main_width
+ || enc_param->height <= 0
+ || enc_param->height > jpg_ctx->limits->max_main_height) {
+ jpg_err("::encoder : width: %d, height: %d\n",
+ enc_param->width, enc_param->height);
+ jpg_err("::encoder : invalid width/height\n");
+ return JPG_FAIL;
+ }
+
+ /* SW reset */
+ if (jpg_ctx)
+ reset_jpg(jpg_ctx);
+ else {
+ jpg_err("::jpg ctx is NULL\n");
+ return JPG_FAIL;
+ }
+ /* set jpeg clock register : power on */
+ writel(readl(s3c_jpeg_base + S3C_JPEG_CLKCON_REG) |
+ (S3C_JPEG_CLKCON_REG_POWER_ON_ACTIVATE),
+ s3c_jpeg_base + S3C_JPEG_CLKCON_REG);
+ /* set jpeg mod register : encode */
+ writel(readl(s3c_jpeg_base + S3C_JPEG_CMOD_REG) |
+ (enc_param->in_format << JPG_MODE_SEL_BIT),
+ s3c_jpeg_base + S3C_JPEG_CMOD_REG);
+ cmd_val = (enc_param->sample_mode == JPG_422) ?
+ (S3C_JPEG_MOD_REG_SUBSAMPLE_422) :
+ (S3C_JPEG_MOD_REG_SUBSAMPLE_420);
+
+ writel(cmd_val | S3C_JPEG_MOD_REG_PROC_ENC,
+ s3c_jpeg_base + S3C_JPEG_MOD_REG);
+
+ /* set DRI(Define Restart Interval) */
+ writel(JPG_RESTART_INTRAVEL, s3c_jpeg_base + S3C_JPEG_DRI_L_REG);
+ writel((JPG_RESTART_INTRAVEL>>8), s3c_jpeg_base + S3C_JPEG_DRI_U_REG);
+
+ writel(S3C_JPEG_QHTBL_REG_QT_NUM1, s3c_jpeg_base + S3C_JPEG_QTBL_REG);
+ writel(0x00, s3c_jpeg_base + S3C_JPEG_HTBL_REG);
+
+ /* Horizontal resolution */
+ writel((enc_param->width>>8), s3c_jpeg_base + S3C_JPEG_X_U_REG);
+ writel(enc_param->width, s3c_jpeg_base + S3C_JPEG_X_L_REG);
+
+ /* Vertical resolution */
+ writel((enc_param->height>>8), s3c_jpeg_base + S3C_JPEG_Y_U_REG);
+ writel(enc_param->height, s3c_jpeg_base + S3C_JPEG_Y_L_REG);
+
+ jpg_dbg("enc_param->enc_type : %d\n", enc_param->enc_type);
+
+ if (enc_param->enc_type == JPG_MAIN) {
+ jpg_dbg("encode image size width: %d, height: %d\n",
+ enc_param->width, enc_param->height);
+ writel(jpg_ctx->img_data_addr,
+ s3c_jpeg_base + S3C_JPEG_IMGADR_REG);
+ writel(jpg_ctx->jpg_data_addr,
+ s3c_jpeg_base + S3C_JPEG_JPGADR_REG);
+ } else { /* thumbnail encoding */
+ jpg_dbg("thumb image size width: %d, height: %d\n",
+ enc_param->width, enc_param->height);
+ writel(jpg_ctx->img_thumb_data_addr,
+ s3c_jpeg_base + S3C_JPEG_IMGADR_REG);
+ writel(jpg_ctx->jpg_thumb_data_addr,
+ s3c_jpeg_base + S3C_JPEG_JPGADR_REG);
+ }
+
+ /* Coefficient value 1~3 for RGB to YCbCr */
+ writel(COEF1_RGB_2_YUV, s3c_jpeg_base + S3C_JPEG_COEF1_REG);
+ writel(COEF2_RGB_2_YUV, s3c_jpeg_base + S3C_JPEG_COEF2_REG);
+ writel(COEF3_RGB_2_YUV, s3c_jpeg_base + S3C_JPEG_COEF3_REG);
+
+ /* Quantiazation and Huffman Table setting */
+ for (i = 0; i < 64; i++) {
+ writel((unsigned int)qtbl_luminance[enc_param->quality][i],
+ s3c_jpeg_base + S3C_JPEG_QTBL0_REG + (i*0x04));
+ }
+ for (i = 0; i < 64; i++) {
+ writel((unsigned int)qtbl_chrominance[enc_param->quality][i],
+ s3c_jpeg_base + S3C_JPEG_QTBL1_REG + (i*0x04));
+ }
+ for (i = 0; i < 16; i++) {
+ writel((unsigned int)hdctbl0[i],
+ s3c_jpeg_base + S3C_JPEG_HDCTBL0_REG + (i*0x04));
+ }
+ for (i = 0; i < 12; i++) {
+ writel((unsigned int)hdctblg0[i],
+ s3c_jpeg_base + S3C_JPEG_HDCTBLG0_REG + (i*0x04));
+ }
+ for (i = 0; i < 16; i++) {
+ writel((unsigned int)hactbl0[i],
+ s3c_jpeg_base + S3C_JPEG_HACTBL0_REG + (i*0x04));
+ }
+ for (i = 0; i < 162; i++) {
+ writel((unsigned int)hactblg0[i],
+ s3c_jpeg_base + S3C_JPEG_HACTBLG0_REG + (i*0x04));
+ }
+ writel(readl(s3c_jpeg_base + S3C_JPEG_INTSE_REG) |
+ (S3C_JPEG_INTSE_REG_RSTM_INT_EN |
+ S3C_JPEG_INTSE_REG_DATA_NUM_INT_EN |
+ S3C_JPEG_INTSE_REG_FINAL_MCU_NUM_INT_EN),
+ s3c_jpeg_base + S3C_JPEG_INTSE_REG);
+
+ writel(readl(s3c_jpeg_base + S3C_JPEG_JSTART_REG) |
+ S3C_JPEG_JSTART_REG_ENABLE,
+ s3c_jpeg_base + S3C_JPEG_JSTART_REG);
+ ret = wait_for_interrupt();
+
+ if (ret != OK_ENC_OR_DEC) {
+ jpg_err("jpeg encoding error(%d)\n", ret);
+ return JPG_FAIL;
+ }
+
+ enc_param->file_size = readl(s3c_jpeg_base + S3C_JPEG_CNT_U_REG) << 16;
+ enc_param->file_size |= readl(s3c_jpeg_base + S3C_JPEG_CNT_M_REG) << 8;
+ enc_param->file_size |= readl(s3c_jpeg_base + S3C_JPEG_CNT_L_REG);
+
+ return JPG_SUCCESS;
+
+}
diff --git a/drivers/media/video/samsung/jpeg_v2/jpg_opr.h b/drivers/media/video/samsung/jpeg_v2/jpg_opr.h
new file mode 100644
index 0000000..b8c21d0
--- /dev/null
+++ b/drivers/media/video/samsung/jpeg_v2/jpg_opr.h
@@ -0,0 +1,158 @@
+/* linux/drivers/media/video/samsung/jpeg_v2/jpg_opr.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Definition for Operation of Jpeg encoder/docoder
+ *
+ * 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 __JPG_OPR_H__
+#define __JPG_OPR_H__
+
+#include <linux/interrupt.h>
+
+extern void __iomem *s3c_jpeg_base;
+extern int jpg_irq_reason;
+
+/* debug macro */
+#define JPG_DEBUG(fmt, ...) \
+ do { \
+ printk(KERN_DEBUG \
+ "%s: " fmt, __func__, ##__VA_ARGS__); \
+ } while (0)
+
+
+#define JPG_WARN(fmt, ...) \
+ do { \
+ printk(KERN_WARNING \
+ fmt, ##__VA_ARGS__); \
+ } while (0)
+
+
+
+#define JPG_ERROR(fmt, ...) \
+ do { \
+ printk(KERN_ERR \
+ "%s: " fmt, __func__, ##__VA_ARGS__); \
+ } while (0)
+
+
+
+#ifdef CONFIG_VIDEO_JPEG_DEBUG
+#define jpg_dbg(fmt, ...) JPG_DEBUG(fmt, ##__VA_ARGS__)
+#else
+#define jpg_dbg(fmt, ...)
+#endif
+
+#define jpg_warn(fmt, ...) JPG_WARN(fmt, ##__VA_ARGS__)
+#define jpg_err(fmt, ...) JPG_ERROR(fmt, ##__VA_ARGS__)
+
+extern wait_queue_head_t wait_queue_jpeg;
+
+enum jpg_return_status {
+ JPG_FAIL,
+ JPG_SUCCESS,
+ OK_HD_PARSING,
+ ERR_HD_PARSING,
+ OK_ENC_OR_DEC,
+ ERR_ENC_OR_DEC,
+ ERR_UNKNOWN
+};
+
+enum image_type {
+ JPG_RGB16,
+ JPG_YCBYCR,
+ JPG_TYPE_UNKNOWN
+};
+
+enum sample_mode {
+ JPG_444,
+ JPG_422,
+ JPG_420,
+ JPG_400,
+ RESERVED1,
+ RESERVED2,
+ JPG_411,
+ JPG_SAMPLE_UNKNOWN
+};
+
+enum out_mode {
+ YCBCR_422,
+ YCBCR_420,
+ YCBCR_SAMPLE_UNKNOWN
+};
+
+enum in_mode {
+ JPG_MODESEL_YCBCR = 1,
+ JPG_MODESEL_RGB,
+ JPG_MODESEL_UNKNOWN
+};
+
+enum encode_type {
+ JPG_MAIN,
+ JPG_THUMBNAIL
+};
+
+enum image_quality_type {
+ JPG_QUALITY_LEVEL_1 = 0, /*high quality*/
+ JPG_QUALITY_LEVEL_2,
+ JPG_QUALITY_LEVEL_3,
+ JPG_QUALITY_LEVEL_4 /*low quality*/
+};
+
+struct jpg_dec_proc_param {
+ enum sample_mode sample_mode;
+ enum encode_type dec_type;
+ enum out_mode out_format;
+ unsigned int width;
+ unsigned int height;
+ unsigned int data_size;
+ unsigned int file_size;
+};
+
+struct jpg_enc_proc_param {
+ enum sample_mode sample_mode;
+ enum encode_type enc_type;
+ enum in_mode in_format;
+ enum image_quality_type quality;
+ unsigned int width;
+ unsigned int height;
+ unsigned int data_size;
+ unsigned int file_size;
+};
+
+struct jpg_args {
+ char *in_buf;
+ char *phy_in_buf;
+ int in_buf_size;
+ char *out_buf;
+ char *phy_out_buf;
+ int out_buf_size;
+ char *in_thumb_buf;
+ char *phy_in_thumb_buf;
+ int in_thumb_buf_size;
+ char *out_thumb_buf;
+ char *phy_out_thumb_buf;
+ int out_thumb_buf_size;
+ char *mapped_addr;
+ struct jpg_dec_proc_param *dec_param;
+ struct jpg_enc_proc_param *enc_param;
+ struct jpg_enc_proc_param *thumb_enc_param;
+};
+
+void reset_jpg(struct s5pc110_jpg_ctx *jpg_ctx);
+enum jpg_return_status decode_jpg(struct s5pc110_jpg_ctx *jpg_ctx, \
+ struct jpg_dec_proc_param *dec_param);
+enum jpg_return_status encode_jpg(struct s5pc110_jpg_ctx *jpg_ctx, \
+ struct jpg_enc_proc_param *enc_param);
+enum jpg_return_status wait_for_interrupt(void);
+enum sample_mode get_sample_type(struct s5pc110_jpg_ctx *jpg_ctx);
+void get_xy(struct s5pc110_jpg_ctx *jpg_ctx, unsigned int *x, unsigned int *y);
+unsigned int get_yuv_size(enum out_mode out_format, \
+ unsigned int width, unsigned int height);
+
+#endif
diff --git a/drivers/media/video/samsung/jpeg_v2/regs-jpeg.h b/drivers/media/video/samsung/jpeg_v2/regs-jpeg.h
new file mode 100644
index 0000000..55bd2eb
--- /dev/null
+++ b/drivers/media/video/samsung/jpeg_v2/regs-jpeg.h
@@ -0,0 +1,143 @@
+/* linux/drivers/media/video/samsung/jpeg/regs-jpeg.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Register definition file for Samsung JPEG Encoder/Decoder
+ *
+ * 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_ARM_REGS_S3C_JPEG_H
+#define __ASM_ARM_REGS_S3C_JPEG_H
+
+/* JPEG Registers part */
+#define S3C_JPEG_REG(x) ((x))
+
+/* Sub-sampling Mode Register */
+#define S3C_JPEG_MOD_REG S3C_JPEG_REG(0x00)
+/* Operation Status Register */
+#define S3C_JPEG_OPR_REG S3C_JPEG_REG(0x04)
+/* Quantization Table Number Register and Huffman Table Number Register */
+#define S3C_JPEG_QTBL_REG S3C_JPEG_REG(0x08)
+/* Huffman Table Number Register */
+#define S3C_JPEG_HTBL_REG S3C_JPEG_REG(0x0c)
+#define S3C_JPEG_DRI_U_REG S3C_JPEG_REG(0x10) /* MCU, which inserts RST marker(upper 8bit) */
+#define S3C_JPEG_DRI_L_REG S3C_JPEG_REG(0x14) /* MCU, which inserts RST marker(lower 8bit) */
+#define S3C_JPEG_Y_U_REG S3C_JPEG_REG(0x18) /* Vertical Resolution (upper 8bit) */
+#define S3C_JPEG_Y_L_REG S3C_JPEG_REG(0x1c) /* Vertical Resolution (lower 8bit) */
+#define S3C_JPEG_X_U_REG S3C_JPEG_REG(0x20) /* Horizontal Resolution (upper 8bit) */
+#define S3C_JPEG_X_L_REG S3C_JPEG_REG(0x24) /* Horizontal Resolution (lower 8bit) */
+#define S3C_JPEG_CNT_U_REG S3C_JPEG_REG(0x28) /* The amount of the compressed data in bytes (upper 8bit) */
+#define S3C_JPEG_CNT_M_REG S3C_JPEG_REG(0x2c) /* The amount of the compressed data in bytes (middle 8bit) */
+#define S3C_JPEG_CNT_L_REG S3C_JPEG_REG(0x30) /* The amount of the compressed data in bytes (lowerz 8bit) */
+#define S3C_JPEG_INTSE_REG S3C_JPEG_REG(0x34) /* Interrupt setting register */
+#define S3C_JPEG_INTST_REG S3C_JPEG_REG(0x38) /* Interrupt status */
+
+#define S3C_JPEG_COM_REG S3C_JPEG_REG(0x4c) /* Command register */
+
+#define S3C_JPEG_IMGADR_REG S3C_JPEG_REG(0x50) /* Source or destination image addresss */
+
+#define S3C_JPEG_JPGADR_REG S3C_JPEG_REG(0x58) /* Source or destination JPEG file address */
+#define S3C_JPEG_COEF1_REG S3C_JPEG_REG(0x5c) /* Coefficient values for RGB <-> YCbCr converter */
+#define S3C_JPEG_COEF2_REG S3C_JPEG_REG(0x60) /* Coefficient values for RGB <-> YCbCr converter */
+#define S3C_JPEG_COEF3_REG S3C_JPEG_REG(0x64) /* Coefficient values for RGB <-> YCbCr converter */
+
+#define S3C_JPEG_CMOD_REG S3C_JPEG_REG(0x68) /* Mode selection and core clock setting */
+#define S3C_JPEG_CLKCON_REG S3C_JPEG_REG(0x6c) /* Power on/off and clock down control */
+
+#define S3C_JPEG_JSTART_REG S3C_JPEG_REG(0x70) /* Start compression or decompression */
+#define S3C_JPEG_JRSTART_REG S3C_JPEG_REG(0x74) /* Restart decompression after header analysis */
+#define S3C_JPEG_SW_RESET_REG S3C_JPEG_REG(0x78) /* S/W reset */
+
+#define S3C_JPEG_TIMER_SE_REG S3C_JPEG_REG(0x7c) /* Internal timer setting register */
+#define S3C_JPEG_TIMER_ST_REG S3C_JPEG_REG(0x80) /* Internal timer status register */
+#define S3C_JPEG_COMSTAT_REG S3C_JPEG_REG(0x84) /* Command status register */
+#define S3C_JPEG_OUTFORM_REG S3C_JPEG_REG(0x88) /* Output color format of decompression */
+#define S3C_JPEG_VERSION_REG S3C_JPEG_REG(0x8c) /* Version register */
+
+#define S3C_JPEG_ENC_STREAM_INTSE_REG S3C_JPEG_REG(0x98) /* Compressed stream size interrupt setting register */
+#define S3C_JPEG_ENC_STREAM_INTST_REG S3C_JPEG_REG(0x9c) /* Compressed stream size interrupt status register */
+
+#define S3C_JPEG_QTBL0_REG S3C_JPEG_REG(0x400) /* Quantization table 0 */
+#define S3C_JPEG_QTBL1_REG S3C_JPEG_REG(0x500) /* Quantization table 1 */
+#define S3C_JPEG_QTBL2_REG S3C_JPEG_REG(0x600) /* Quantization table 2 */
+#define S3C_JPEG_QTBL3_REG S3C_JPEG_REG(0x700) /* Quantization table 3 */
+
+#define S3C_JPEG_HDCTBL0_REG S3C_JPEG_REG(0x800) /* DC huffman table 0 */
+#define S3C_JPEG_HDCTBLG0_REG S3C_JPEG_REG(0x840) /* DC huffman table group 0 */
+#define S3C_JPEG_HACTBL0_REG S3C_JPEG_REG(0x880) /* AC huffman table 0 */
+#define S3C_JPEG_HACTBLG0_REG S3C_JPEG_REG(0x8c0) /* AC huffman table group 0 */
+#define S3C_JPEG_HDCTBL1_REG S3C_JPEG_REG(0xc00) /* DC huffman table 1 */
+#define S3C_JPEG_HDCTBLG1_REG S3C_JPEG_REG(0xc40) /* DC huffman table group 1 */
+#define S3C_JPEG_HACTBL1_REG S3C_JPEG_REG(0xc80) /* AC huffman table 1 */
+#define S3C_JPEG_HACTBLG1_REG S3C_JPEG_REG(0xcc0) /* AC huffman table group 1 */
+
+/* JPEG Mode Register bit */
+#define S3C_JPEG_MOD_REG_PROC_ENC (0<<3)
+#define S3C_JPEG_MOD_REG_PROC_DEC (1<<3)
+
+#define S3C_JPEG_MOD_REG_SUBSAMPLE_444 (0<<0)
+#define S3C_JPEG_MOD_REG_SUBSAMPLE_422 (1<<0)
+#define S3C_JPEG_MOD_REG_SUBSAMPLE_420 (2<<0)
+#define S3C_JPEG_MOD_REG_SUBSAMPLE_GRAY (3<<0)
+
+/* JPEG Operation Status Register bit */
+#define S3C_JPEG_OPR_REG_OPERATE (1<<0)
+#define S3C_JPEG_OPR_REG_NO_OPERATE (0<<0)
+
+/* Quantization Table And Huffman Table Number Register bit */
+#define S3C_JPEG_QHTBL_REG_QT_NUM4 (1<<6)
+#define S3C_JPEG_QHTBL_REG_QT_NUM3 (1<<4)
+#define S3C_JPEG_QHTBL_REG_QT_NUM2 (1<<2)
+#define S3C_JPEG_QHTBL_REG_QT_NUM1 (1<<0)
+
+#define S3C_JPEG_QHTBL_REG_HT_NUM4_AC (1<<7)
+#define S3C_JPEG_QHTBL_REG_HT_NUM4_DC (1<<6)
+#define S3C_JPEG_QHTBL_REG_HT_NUM3_AC (1<<5)
+#define S3C_JPEG_QHTBL_REG_HT_NUM3_DC (1<<4)
+#define S3C_JPEG_QHTBL_REG_HT_NUM2_AC (1<<3)
+#define S3C_JPEG_QHTBL_REG_HT_NUM2_DC (1<<2)
+#define S3C_JPEG_QHTBL_REG_HT_NUM1_AC (1<<1)
+#define S3C_JPEG_QHTBL_REG_HT_NUM1_DC (1<<0)
+
+
+/* JPEG Color Mode Register bit */
+#define S3C_JPEG_CMOD_REG_MOD_SEL_RGB (2<<5)
+#define S3C_JPEG_CMOD_REG_MOD_SEL_YCBCR422 (1<<5)
+#define S3C_JPEG_CMOD_REG_MOD_MODE_Y16 (1<<1)
+#define S3C_JPEG_CMOD_REG_MOD_MODE_0 (0<<1)
+
+/* JPEG Clock Control Register bit */
+#define S3C_JPEG_CLKCON_REG_CLK_DOWN_READY_ENABLE (0<<1)
+#define S3C_JPEG_CLKCON_REG_CLK_DOWN_READY_DISABLE (1<<1)
+#define S3C_JPEG_CLKCON_REG_POWER_ON_ACTIVATE (1<<0)
+#define S3C_JPEG_CLKCON_REG_POWER_ON_DISABLE (0<<0)
+
+/* JPEG Start Register bit */
+#define S3C_JPEG_JSTART_REG_ENABLE (1<<0)
+
+/* JPEG Rdstart Register bit */
+#define S3C_JPEG_JRSTART_REG_ENABLE (1<<0)
+
+/* JPEG SW Reset Register bit */
+#define S3C_JPEG_SW_RESET_REG_ENABLE (1<<0)
+
+/* JPEG Interrupt Setting Register bit */
+#define S3C_JPEG_INTSE_REG_RSTM_INT_EN (1<<7)
+#define S3C_JPEG_INTSE_REG_DATA_NUM_INT_EN (1<<6)
+#define S3C_JPEG_INTSE_REG_FINAL_MCU_NUM_INT_EN (1<<5)
+
+/* JPEG Decompression Output Format Register bit */
+#define S3C_JPEG_OUTFORM_REG_YCBCY422 (0<<0)
+#define S3C_JPEG_OUTFORM_REG_YCBCY420 (1<<0)
+
+/* JPEG Decompression Input Stream Size Register bit */
+#define S3C_JPEG_DEC_STREAM_SIZE_REG_PROHIBIT (0x1FFFFFFF<<0)
+
+/* JPEG Command Register bit */
+#define S3C_JPEG_COM_INT_RELEASE (1<<2)
+
+#endif /*__ASM_ARM_REGS_S3C_JPEG_H */
diff --git a/drivers/media/video/samsung/jpeg_v2/s3c-jpeg.c b/drivers/media/video/samsung/jpeg_v2/s3c-jpeg.c
new file mode 100644
index 0000000..81408b4
--- /dev/null
+++ b/drivers/media/video/samsung/jpeg_v2/s3c-jpeg.c
@@ -0,0 +1,613 @@
+/* linux/drivers/media/video/samsung/jpeg_v2/s3c-jpeg.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Core file for Samsung Jpeg Interface 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/version.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/slab.h>
+#include <linux/poll.h>
+#include <linux/signal.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/kmod.h>
+#include <linux/vmalloc.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <asm/page.h>
+#include <mach/irqs.h>
+#include <linux/semaphore.h>
+#include <mach/map.h>
+#include <linux/miscdevice.h>
+#include <linux/vmalloc.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+
+#include <linux/version.h>
+#include <plat/media.h>
+#include <plat/jpeg.h>
+#include <mach/media.h>
+
+#include <linux/time.h>
+#include <linux/clk.h>
+
+#include <plat/clock.h>
+
+#include "s3c-jpeg.h"
+#include "jpg_mem.h"
+#include "jpg_misc.h"
+#include "jpg_opr.h"
+#include "regs-jpeg.h"
+
+static struct jpegv2_limits s3c_jpeg_limits;
+static struct jpegv2_buf s3c_jpeg_bufinfo;
+
+static struct clk *s3c_jpeg_clk;
+static struct regulator *jpeg_pd_regulator;
+
+static struct resource *s3c_jpeg_mem;
+void __iomem *s3c_jpeg_base;
+static int irq_no;
+static int instanceNo;;
+int jpg_irq_reason;
+wait_queue_head_t wait_queue_jpeg;
+
+
+DECLARE_WAIT_QUEUE_HEAD(WaitQueue_JPEG);
+
+static void jpeg_clock_enable(void)
+{
+ /* power domain enable */
+ regulator_enable(jpeg_pd_regulator);
+
+ /* clock enable */
+ clk_enable(s3c_jpeg_clk);
+}
+
+static void jpeg_clock_disable(void)
+{
+ /* clock disable */
+ clk_disable(s3c_jpeg_clk);
+
+ /* power domain disable */
+ regulator_disable(jpeg_pd_regulator);
+}
+
+irqreturn_t s3c_jpeg_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+ unsigned int int_status;
+ unsigned int status;
+
+ jpg_dbg("=====enter s3c_jpeg_irq===== \r\n");
+
+ int_status = readl(s3c_jpeg_base + S3C_JPEG_INTST_REG);
+
+ do {
+ status = readl(s3c_jpeg_base + S3C_JPEG_OPR_REG);
+ } while (status);
+
+ writel(S3C_JPEG_COM_INT_RELEASE, s3c_jpeg_base + S3C_JPEG_COM_REG);
+ jpg_dbg("int_status : 0x%08x status : 0x%08x\n", int_status, status);
+
+ if (int_status) {
+ switch (int_status) {
+ case 0x40:
+ jpg_irq_reason = OK_ENC_OR_DEC;
+ break;
+ case 0x20:
+ jpg_irq_reason = ERR_ENC_OR_DEC;
+ break;
+ default:
+ jpg_irq_reason = ERR_UNKNOWN;
+ }
+
+ wake_up_interruptible(&wait_queue_jpeg);
+ } else {
+ jpg_irq_reason = ERR_UNKNOWN;
+ wake_up_interruptible(&wait_queue_jpeg);
+ }
+
+ return IRQ_HANDLED;
+}
+static int s3c_jpeg_open(struct inode *inode, struct file *file)
+{
+ struct s5pc110_jpg_ctx *jpg_reg_ctx;
+ unsigned long ret;
+
+ jpg_dbg("JPG_open \r\n");
+
+ jpg_reg_ctx = (struct s5pc110_jpg_ctx *)
+ mem_alloc(sizeof(struct s5pc110_jpg_ctx));
+ memset(jpg_reg_ctx, 0x00, sizeof(struct s5pc110_jpg_ctx));
+
+ ret = lock_jpg_mutex();
+
+ if (!ret) {
+ jpg_err("JPG Mutex Lock Fail\r\n");
+ unlock_jpg_mutex();
+ kfree(jpg_reg_ctx);
+ return FALSE;
+ }
+
+ if (instanceNo > MAX_INSTANCE_NUM) {
+ jpg_err("Instance Number error-JPEG is running, \
+ instance number is %d\n", instanceNo);
+ unlock_jpg_mutex();
+ kfree(jpg_reg_ctx);
+ return FALSE;
+ }
+
+ instanceNo++;
+
+ /* Initialize the limits of the driver */
+ jpg_reg_ctx->limits = &s3c_jpeg_limits;
+ jpg_reg_ctx->bufinfo = &s3c_jpeg_bufinfo;
+
+ unlock_jpg_mutex();
+
+ file->private_data = (struct s5pc110_jpg_ctx *)jpg_reg_ctx;
+
+ return 0;
+}
+
+
+static int s3c_jpeg_release(struct inode *inode, struct file *file)
+{
+ unsigned long ret;
+ struct s5pc110_jpg_ctx *jpg_reg_ctx;
+
+ jpg_dbg("JPG_Close\n");
+
+ jpg_reg_ctx = (struct s5pc110_jpg_ctx *)file->private_data;
+
+ if (!jpg_reg_ctx) {
+ jpg_err("JPG Invalid Input Handle\r\n");
+ return FALSE;
+ }
+
+ ret = lock_jpg_mutex();
+
+ if (!ret) {
+ jpg_err("JPG Mutex Lock Fail\r\n");
+ return FALSE;
+ }
+
+ if ((--instanceNo) < 0)
+ instanceNo = 0;
+
+ unlock_jpg_mutex();
+ kfree(jpg_reg_ctx);
+
+ return 0;
+}
+
+
+static ssize_t s3c_jpeg_write(struct file *file, const char *buf,
+ size_t count, loff_t *pos)
+{
+ return 0;
+}
+
+static ssize_t s3c_jpeg_read(struct file *file, char *buf,
+ size_t count, loff_t *pos)
+{
+ return 0;
+}
+
+static long s3c_jpeg_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct s5pc110_jpg_ctx *jpg_reg_ctx;
+ struct jpg_args param;
+ enum BOOL result = TRUE;
+ unsigned long ret;
+ int out;
+
+ jpg_reg_ctx = (struct s5pc110_jpg_ctx *)file->private_data;
+
+ if (!jpg_reg_ctx) {
+ jpg_err("JPG Invalid Input Handle\r\n");
+ return FALSE;
+ }
+
+ ret = lock_jpg_mutex();
+
+ if (!ret) {
+ jpg_err("JPG Mutex Lock Fail\r\n");
+ return FALSE;
+ }
+
+ switch (cmd) {
+ case IOCTL_JPG_DECODE:
+
+ jpg_dbg("IOCTL_JPEG_DECODE\n");
+
+ out = copy_from_user(&param, (struct jpg_args *)arg,
+ sizeof(struct jpg_args));
+
+ jpg_reg_ctx->jpg_data_addr = (unsigned int)jpg_data_base_addr;
+ jpg_reg_ctx->img_data_addr =
+ (unsigned int)jpg_data_base_addr
+ + jpg_reg_ctx->bufinfo->main_frame_start;
+
+ jpeg_clock_enable();
+ result = decode_jpg(jpg_reg_ctx, param.dec_param);
+ jpeg_clock_disable();
+
+ out = copy_to_user((void *)arg,
+ (void *)&param, sizeof(struct jpg_args));
+ break;
+
+ case IOCTL_JPG_ENCODE:
+
+ jpg_dbg("IOCTL_JPEG_ENCODE\n");
+
+ out = copy_from_user(&param, (struct jpg_args *)arg,
+ sizeof(struct jpg_args));
+
+ jpg_dbg("encode size :: width : %d hegiht : %d\n",
+ param.enc_param->width, param.enc_param->height);
+
+ jpeg_clock_enable();
+ if (param.enc_param->enc_type == JPG_MAIN) {
+ jpg_reg_ctx->jpg_data_addr =
+ (unsigned int)jpg_data_base_addr;
+ jpg_reg_ctx->img_data_addr =
+ (unsigned int)jpg_data_base_addr
+ + jpg_reg_ctx->bufinfo->main_frame_start;
+ jpg_dbg("enc_img_data_addr=0x%08x,"
+ "enc_jpg_data_addr=0x%08x\n",
+ jpg_reg_ctx->img_data_addr,
+ jpg_reg_ctx->jpg_data_addr);
+
+ result = encode_jpg(jpg_reg_ctx, param.enc_param);
+ } else {
+ jpg_reg_ctx->jpg_thumb_data_addr =
+ (unsigned int)jpg_data_base_addr
+ + jpg_reg_ctx->bufinfo->thumb_stream_start;
+ jpg_reg_ctx->img_thumb_data_addr =
+ (unsigned int)jpg_data_base_addr
+ + jpg_reg_ctx->bufinfo->thumb_frame_start;
+
+ result = encode_jpg(jpg_reg_ctx, param.thumb_enc_param);
+ }
+ jpeg_clock_disable();
+
+ out = copy_to_user((void *)arg, (void *)&param,
+ sizeof(struct jpg_args));
+ break;
+
+ case IOCTL_JPG_GET_STRBUF:
+ jpg_dbg("IOCTL_JPG_GET_STRBUF\n");
+ unlock_jpg_mutex();
+ return arg + jpg_reg_ctx->bufinfo->main_stream_start;
+
+ case IOCTL_JPG_GET_THUMB_STRBUF:
+ jpg_dbg("IOCTL_JPG_GET_THUMB_STRBUF\n");
+ unlock_jpg_mutex();
+ return arg + jpg_reg_ctx->bufinfo->thumb_stream_start;
+
+ case IOCTL_JPG_GET_FRMBUF:
+ jpg_dbg("IOCTL_JPG_GET_FRMBUF\n");
+ unlock_jpg_mutex();
+ return arg + jpg_reg_ctx->bufinfo->main_frame_start;
+
+ case IOCTL_JPG_GET_THUMB_FRMBUF:
+ jpg_dbg("IOCTL_JPG_GET_THUMB_FRMBUF\n");
+ unlock_jpg_mutex();
+ return arg + jpg_reg_ctx->bufinfo->thumb_frame_start;
+
+ case IOCTL_JPG_GET_PHY_FRMBUF:
+ jpg_dbg("IOCTL_JPG_GET_PHY_FRMBUF\n");
+ unlock_jpg_mutex();
+ return jpg_data_base_addr + jpg_reg_ctx->bufinfo->main_frame_start;
+
+ case IOCTL_JPG_GET_PHY_THUMB_FRMBUF:
+ jpg_dbg("IOCTL_JPG_GET_PHY_THUMB_FRMBUF\n");
+ unlock_jpg_mutex();
+ return jpg_data_base_addr + jpg_reg_ctx->bufinfo->thumb_frame_start;
+
+ default:
+ jpg_dbg("JPG Invalid ioctl : 0x%X\n", cmd);
+ }
+
+ unlock_jpg_mutex();
+
+ return result;
+}
+
+static unsigned int s3c_jpeg_poll(struct file *file, poll_table *wait)
+{
+ unsigned int mask = 0;
+
+ jpg_dbg("enter poll\n");
+ poll_wait(file, &wait_queue_jpeg, wait);
+ mask = POLLOUT | POLLWRNORM;
+ return mask;
+}
+
+int s3c_jpeg_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+ unsigned long size = vma->vm_end - vma->vm_start;
+ unsigned long max_size;
+ unsigned long page_frame_no;
+
+ page_frame_no = __phys_to_pfn(jpg_data_base_addr);
+
+ max_size = jpg_reserved_mem_size;
+
+ if (size > max_size)
+ return -EINVAL;
+
+ vma->vm_flags |= VM_RESERVED | VM_IO;
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+ if (remap_pfn_range(vma, vma->vm_start, page_frame_no, size,
+ vma->vm_page_prot)) {
+ jpg_err("jpeg remap error");
+ return -EAGAIN;
+ }
+
+ return 0;
+}
+
+
+static const struct file_operations jpeg_fops = {
+ .owner = THIS_MODULE,
+ .open = s3c_jpeg_open,
+ .release = s3c_jpeg_release,
+ .unlocked_ioctl = s3c_jpeg_ioctl,
+ .read = s3c_jpeg_read,
+ .write = s3c_jpeg_write,
+ .mmap = s3c_jpeg_mmap,
+ .poll = s3c_jpeg_poll,
+};
+
+
+static struct miscdevice s3c_jpeg_miscdev = {
+ .minor = 254,
+ .name = "s3c-jpg",
+ .fops = &jpeg_fops
+};
+
+void s3c_jpg_plat_init(struct s3c_platform_jpeg *pdata)
+{
+ unsigned int main_pixels;
+ unsigned int thumb_pixels;
+
+ s3c_jpeg_limits.max_main_width = pdata->max_main_width;
+ s3c_jpeg_limits.max_main_height = pdata->max_main_height;
+ s3c_jpeg_limits.max_thumb_width = pdata->max_thumb_width;
+ s3c_jpeg_limits.max_thumb_height = pdata->max_thumb_height;
+
+ main_pixels = s3c_jpeg_limits.max_main_width *
+ s3c_jpeg_limits.max_main_height;
+ thumb_pixels = s3c_jpeg_limits.max_thumb_width *
+ s3c_jpeg_limits.max_thumb_height;
+
+ s3c_jpeg_bufinfo.main_stream_size = ALIGN(main_pixels, PAGE_SIZE);
+ /* Assuming JPEG V2 uses YCBCR422 output format */
+ s3c_jpeg_bufinfo.main_frame_size = ALIGN(main_pixels * 2, PAGE_SIZE);
+
+ s3c_jpeg_bufinfo.thumb_stream_size = ALIGN(thumb_pixels, PAGE_SIZE);
+ s3c_jpeg_bufinfo.thumb_frame_size = ALIGN(thumb_pixels * 2, PAGE_SIZE);
+
+ s3c_jpeg_bufinfo.total_buf_size = s3c_jpeg_bufinfo.main_stream_size +
+ s3c_jpeg_bufinfo.thumb_stream_size +
+ s3c_jpeg_bufinfo.main_frame_size +
+ s3c_jpeg_bufinfo.thumb_frame_size;
+
+ s3c_jpeg_bufinfo.main_stream_start = 0;
+ s3c_jpeg_bufinfo.thumb_stream_start =
+ s3c_jpeg_bufinfo.main_stream_start +
+ s3c_jpeg_bufinfo.main_stream_size;
+ s3c_jpeg_bufinfo.main_frame_start =
+ s3c_jpeg_bufinfo.thumb_stream_start +
+ s3c_jpeg_bufinfo.thumb_stream_size;
+ s3c_jpeg_bufinfo.thumb_frame_start =
+ s3c_jpeg_bufinfo.main_frame_start +
+ s3c_jpeg_bufinfo.main_frame_size;
+
+ jpg_dbg("Resolution: Main (%4d x %4d), Thumb (%4d x %4d)\n", \
+ s3c_jpeg_limits.max_main_width, \
+ s3c_jpeg_limits.max_main_height, \
+ s3c_jpeg_limits.max_thumb_width, \
+ s3c_jpeg_limits.max_thumb_height);
+
+ jpg_dbg("JPG Stream: Main(%d bytes @ 0x%x), Thumb(%d bytes @ 0x%x)\n",\
+ s3c_jpeg_bufinfo.main_stream_size, \
+ s3c_jpeg_bufinfo.main_stream_start, \
+ s3c_jpeg_bufinfo.thumb_stream_size, \
+ s3c_jpeg_bufinfo.thumb_stream_start);
+
+ jpg_dbg("YUV frame: Main(%d bytes @ 0x%x), Thumb(%d bytes @ 0x%x)\n",\
+ s3c_jpeg_bufinfo.main_frame_size, \
+ s3c_jpeg_bufinfo.main_frame_start, \
+ s3c_jpeg_bufinfo.thumb_frame_size, \
+ s3c_jpeg_bufinfo.thumb_frame_start);
+
+ jpg_dbg("Total buffer size : %d bytes\n", \
+ s3c_jpeg_bufinfo.total_buf_size);
+
+}
+
+static int s3c_jpeg_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ static int size;
+ static int ret;
+ struct mutex *h_mutex;
+ struct s3c_platform_jpeg *pdata;
+
+ pdata = to_jpeg_plat(&pdev->dev);
+
+ if (!pdata) {
+ jpg_err("Err: Platform data is not setup\n");
+ return -EINVAL;
+ }
+
+ s3c_jpg_plat_init(pdata);
+
+ if (s3c_jpeg_bufinfo.total_buf_size > jpg_reserved_mem_size) {
+ jpg_err("Err: Reserved memory (%d) is less than"
+ "required memory (%d)\n", \
+ jpg_reserved_mem_size, \
+ s3c_jpeg_bufinfo.total_buf_size);
+ return -ENOMEM;
+ }
+
+ /* Get jpeg power domain regulator */
+ jpeg_pd_regulator = regulator_get(&pdev->dev, "pd");
+ if (IS_ERR(jpeg_pd_regulator)) {
+ jpg_err("%s: failed to get resource %s\n",
+ __func__, "s3c-jpg");
+ return PTR_ERR(jpeg_pd_regulator);
+ }
+
+ s3c_jpeg_clk = clk_get(&pdev->dev, "jpeg");
+
+ if (IS_ERR(s3c_jpeg_clk)) {
+ jpg_err("failed to find jpeg clock source\n");
+ return -ENOENT;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ if (res == NULL) {
+ jpg_err("failed to get memory region resouce\n");
+ return -ENOENT;
+ }
+
+ size = (res->end - res->start) + 1;
+ s3c_jpeg_mem = request_mem_region(res->start, size, pdev->name);
+
+ if (s3c_jpeg_mem == NULL) {
+ jpg_err("failed to get memory region\n");
+ return -ENOENT;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+
+ if (res == NULL) {
+ jpg_err("failed to get irq resource\n");
+ return -ENOENT;
+ }
+
+ irq_no = res->start;
+ ret = request_irq(res->start, (void *)s3c_jpeg_irq, 0,
+ pdev->name, pdev);
+
+ if (ret != 0) {
+ jpg_err("failed to install irq (%d)\n", ret);
+ return ret;
+ }
+
+ s3c_jpeg_base = ioremap(s3c_jpeg_mem->start, size);
+
+ if (s3c_jpeg_base == 0) {
+ jpg_err("failed to ioremap() region\n");
+ return -EINVAL;
+ }
+
+ init_waitqueue_head(&wait_queue_jpeg);
+
+ jpg_dbg("JPG_Init\n");
+
+ /* Mutex initialization */
+ h_mutex = create_jpg_mutex();
+
+ if (h_mutex == NULL) {
+ jpg_err("JPG Mutex Initialize error\r\n");
+ return FALSE;
+ }
+
+ ret = lock_jpg_mutex();
+
+ if (!ret) {
+ jpg_err("JPG Mutex Lock Fail\n");
+ return FALSE;
+ }
+
+ instanceNo = 0;
+
+ unlock_jpg_mutex();
+
+ ret = misc_register(&s3c_jpeg_miscdev);
+
+ return 0;
+}
+
+static int s3c_jpeg_remove(struct platform_device *dev)
+{
+ if (s3c_jpeg_mem != NULL) {
+ release_resource(s3c_jpeg_mem);
+ kfree(s3c_jpeg_mem);
+ s3c_jpeg_mem = NULL;
+ }
+
+ free_irq(irq_no, dev);
+ misc_deregister(&s3c_jpeg_miscdev);
+ return 0;
+}
+
+static struct platform_driver s3c_jpeg_driver = {
+ .probe = s3c_jpeg_probe,
+ .remove = s3c_jpeg_remove,
+ .shutdown = NULL,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "s3c-jpg",
+ },
+};
+
+static char banner[] __initdata =
+ KERN_INFO "S3C JPEG Driver, (c) 2007 Samsung Electronics\n";
+
+static int __init s3c_jpeg_init(void)
+{
+ printk(banner);
+ printk(KERN_INFO "JPEG driver for S5PV210\n");
+ return platform_driver_register(&s3c_jpeg_driver);
+}
+
+static void __exit s3c_jpeg_exit(void)
+{
+ unsigned long ret;
+
+ jpg_dbg("JPG_Deinit\n");
+
+ ret = lock_jpg_mutex();
+
+ if (!ret)
+ jpg_err("JPG Mutex Lock Fail\r\n");
+
+ unlock_jpg_mutex();
+
+ delete_jpg_mutex();
+
+ platform_driver_unregister(&s3c_jpeg_driver);
+ jpg_dbg("S3C JPEG driver module exit\n");
+}
+
+module_init(s3c_jpeg_init);
+module_exit(s3c_jpeg_exit);
+
+MODULE_AUTHOR("Peter, Oh");
+MODULE_DESCRIPTION("S3C JPEG Encoder/Decoder Device Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/samsung/jpeg_v2/s3c-jpeg.h b/drivers/media/video/samsung/jpeg_v2/s3c-jpeg.h
new file mode 100644
index 0000000..dd5bc4c
--- /dev/null
+++ b/drivers/media/video/samsung/jpeg_v2/s3c-jpeg.h
@@ -0,0 +1,36 @@
+/* linux/drivers/media/video/samsung/jpeg_v2/s3c-jpeg.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Header file for Samsung Jpeg Interface driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+
+#ifndef __JPEG_DRIVER_H__
+#define __JPEG_DRIVER_H__
+
+
+#define MAX_INSTANCE_NUM 1
+#define MAX_PROCESSING_THRESHOLD 1000 /* 1Sec */
+
+#define JPEG_IOCTL_MAGIC 'J'
+
+#define IOCTL_JPG_DECODE _IO(JPEG_IOCTL_MAGIC, 1)
+#define IOCTL_JPG_ENCODE _IO(JPEG_IOCTL_MAGIC, 2)
+#define IOCTL_JPG_GET_STRBUF _IO(JPEG_IOCTL_MAGIC, 3)
+#define IOCTL_JPG_GET_FRMBUF _IO(JPEG_IOCTL_MAGIC, 4)
+#define IOCTL_JPG_GET_THUMB_STRBUF _IO(JPEG_IOCTL_MAGIC, 5)
+#define IOCTL_JPG_GET_THUMB_FRMBUF _IO(JPEG_IOCTL_MAGIC, 6)
+#define IOCTL_JPG_GET_PHY_FRMBUF _IO(JPEG_IOCTL_MAGIC, 7)
+#define IOCTL_JPG_GET_PHY_THUMB_FRMBUF _IO(JPEG_IOCTL_MAGIC, 8)
+#define JPG_CLOCK_DIVIDER_RATIO_QUARTER 4
+
+/* Driver Helper function */
+#define to_jpeg_plat(d) (to_platform_device(d)->dev.platform_data)
+
+#endif /*__JPEG_DRIVER_H__*/
diff --git a/drivers/media/video/samsung/mfc50/Kconfig b/drivers/media/video/samsung/mfc50/Kconfig
new file mode 100644
index 0000000..11d17c2
--- /dev/null
+++ b/drivers/media/video/samsung/mfc50/Kconfig
@@ -0,0 +1,23 @@
+#
+# Configuration for Multi Format Codecs (MFC)
+#
+#
+config VIDEO_MFC50
+ bool "Samsung MFC (Multi Format Codec - FIMV 5.0) Driver"
+ depends on VIDEO_SAMSUNG && CPU_S5PV210
+ default n
+ select S5P_SETUP_MFC
+ select S5P_DEV_MFC
+ ---help---
+ This is a Samsung Multi Format Codecs (MFC) FIMV V5.0 - driver for Samsung S5PC110
+
+config VIDEO_MFC_MAX_INSTANCE
+ int "Maximum size of MFC instance (1-4)"
+ range 1 4
+ depends on VIDEO_MFC50
+ default 4
+
+config VIDEO_MFC50_DEBUG
+ bool "print MFC debug message"
+ depends on VIDEO_MFC50
+ default n
diff --git a/drivers/media/video/samsung/mfc50/Makefile b/drivers/media/video/samsung/mfc50/Makefile
new file mode 100644
index 0000000..31f0499
--- /dev/null
+++ b/drivers/media/video/samsung/mfc50/Makefile
@@ -0,0 +1,7 @@
+obj-$(CONFIG_VIDEO_MFC50) += mfc.o mfc_buffer_manager.o mfc_intr.o mfc_memory.o mfc_opr.o mfc_shared_mem.o
+
+ifeq ($(CONFIG_VIDEO_MFC50_DEBUG),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
+
+#EXTRA_CFLAGS += -DMFC_REQUEST_TIME
diff --git a/drivers/media/video/samsung/mfc50/mfc.c b/drivers/media/video/samsung/mfc50/mfc.c
new file mode 100755
index 0000000..0e596c7
--- /dev/null
+++ b/drivers/media/video/samsung/mfc50/mfc.c
@@ -0,0 +1,835 @@
+/*
+ * drivers/media/video/samsung/mfc50/mfc.c
+ *
+ * C file for Samsung MFC (Multi Function Codec - FIMV) driver
+ *
+ * Jaeryul Oh, Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * Change Logs
+ * 2009.09.14 - Beautify source code (Key Young, Park)
+ * 2009.09.21 - Implement clock & power gating.
+ * including suspend & resume fuction. (Key Young, Park)
+ * 2009.10.08 - Apply 9/30 firmware (Key Young, Park)
+ * 2009.10.09 - Add error handling rountine (Key Young, Park)
+ * 2009.10.13 - move mfc interrupt routine into mfc_irq.c (Key Young, Park)
+ * 2009.10.27 - Update firmware (2009.10.15) (Key Young, Park)
+ * 2009.11.04 - get physical address via mfc_allocate_buffer (Key Young, Park)
+ * 2009.11.04 - remove mfc_common.[ch]
+ * seperate buffer alloc & set (Key Young, Park)
+ * 2009.11.24 - add state check when decoding & encoding (Key Young, Park)
+ *
+ * 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/mm.h>
+#include <linux/miscdevice.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/wait.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+
+#include <linux/sched.h>
+#include <linux/firmware.h>
+
+#include <linux/io.h>
+#include <linux/uaccess.h>
+
+#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"
+#include "mfc_opr.h"
+#include "mfc_memory.h"
+#include "mfc_buffer_manager.h"
+#include "mfc_intr.h"
+
+#define MFC_FW_NAME "samsung_mfc_fw.bin"
+
+static struct resource *mfc_mem;
+static struct mutex mfc_mutex;
+static struct clk *mfc_sclk;
+static struct regulator *mfc_pd_regulator;
+const struct firmware *mfc_fw_info;
+
+static int mfc_open(struct inode *inode, struct file *file)
+{
+ struct mfc_inst_ctx *mfc_ctx;
+ int ret;
+
+ mutex_lock(&mfc_mutex);
+
+ if (!mfc_is_running()) {
+ /* Turn on mfc power domain regulator */
+ ret = regulator_enable(mfc_pd_regulator);
+ if (ret < 0) {
+ mfc_err("MFC_RET_POWER_ENABLE_FAIL\n");
+ ret = -EINVAL;
+ 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);
+
+ if (mfc_init_hw() != true) {
+ clk_disable(mfc_sclk);
+ ret = -ENODEV;
+ goto err_regulator;
+ }
+ clk_disable(mfc_sclk);
+ }
+
+ mfc_ctx = (struct mfc_inst_ctx *)kmalloc(sizeof(struct mfc_inst_ctx), GFP_KERNEL);
+ if (mfc_ctx == NULL) {
+ mfc_err("MFCINST_MEMORY_ALLOC_FAIL\n");
+ ret = -ENOMEM;
+ goto err_regulator;
+ }
+
+ memset(mfc_ctx, 0, sizeof(struct mfc_inst_ctx));
+
+ /* get the inst no allocating some part of memory among reserved memory */
+ mfc_ctx->mem_inst_no = mfc_get_mem_inst_no();
+ mfc_ctx->InstNo = -1;
+ if (mfc_ctx->mem_inst_no < 0) {
+ mfc_err("MFCINST_INST_NUM_EXCEEDED\n");
+ ret = -EPERM;
+ goto err_mem_inst;
+ }
+
+ if (mfc_set_state(mfc_ctx, MFCINST_STATE_OPENED) < 0) {
+ mfc_err("MFCINST_ERR_STATE_INVALID\n");
+ ret = -ENODEV;
+ goto err_set_state;
+ }
+
+ /* Decoder only */
+ mfc_ctx->extraDPB = MFC_MAX_EXTRA_DPB;
+ mfc_ctx->FrameType = MFC_RET_FRAME_NOT_SET;
+
+ file->private_data = mfc_ctx;
+
+ mutex_unlock(&mfc_mutex);
+
+ return 0;
+
+err_set_state:
+ mfc_return_mem_inst_no(mfc_ctx->mem_inst_no);
+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)
+ mfc_err("MFC_RET_POWER_DISABLE_FAIL\n");
+ }
+err_open:
+ mutex_unlock(&mfc_mutex);
+
+ return ret;
+}
+
+static int mfc_release(struct inode *inode, struct file *file)
+{
+ struct mfc_inst_ctx *mfc_ctx;
+ int ret;
+
+ mutex_lock(&mfc_mutex);
+
+ mfc_ctx = (struct mfc_inst_ctx *)file->private_data;
+ if (mfc_ctx == NULL) {
+ mfc_err("MFCINST_ERR_INVALID_PARAM\n");
+ ret = -EIO;
+ goto out_release;
+ }
+
+ mfc_release_all_buffer(mfc_ctx->mem_inst_no);
+ mfc_merge_fragment(mfc_ctx->mem_inst_no);
+
+ mfc_return_mem_inst_no(mfc_ctx->mem_inst_no);
+
+ /* In case of no instance, we should not release codec instance */
+ if (mfc_ctx->InstNo >= 0) {
+ clk_enable(mfc_sclk);
+ mfc_return_inst_no(mfc_ctx->InstNo, mfc_ctx->MfcCodecType);
+ clk_disable(mfc_sclk);
+ }
+
+ kfree(mfc_ctx);
+
+ 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) {
+ mfc_err("MFC_RET_POWER_DISABLE_FAIL\n");
+ goto out_release;
+ }
+ }
+
+out_release:
+
+ mutex_unlock(&mfc_mutex);
+ return ret;
+}
+
+static long mfc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ int ret, ex_ret;
+ struct mfc_inst_ctx *mfc_ctx = NULL;
+ struct mfc_common_args in_param;
+
+ mutex_lock(&mfc_mutex);
+ clk_enable(mfc_sclk);
+
+ ret = copy_from_user(&in_param, (struct mfc_common_args *)arg, sizeof(struct mfc_common_args));
+ if (ret < 0) {
+ mfc_err("Inparm copy error\n");
+ ret = -EIO;
+ in_param.ret_code = MFCINST_ERR_INVALID_PARAM;
+ goto out_ioctl;
+ }
+
+ mfc_ctx = (struct mfc_inst_ctx *)file->private_data;
+ mutex_unlock(&mfc_mutex);
+
+ switch (cmd) {
+ case IOCTL_MFC_ENC_INIT:
+ mutex_lock(&mfc_mutex);
+
+ if (mfc_set_state(mfc_ctx, MFCINST_STATE_ENC_INITIALIZE) < 0) {
+ mfc_err("MFCINST_ERR_STATE_INVALID\n");
+ in_param.ret_code = MFCINST_ERR_STATE_INVALID;
+ ret = -EINVAL;
+ mutex_unlock(&mfc_mutex);
+ break;
+ }
+
+ /* MFC encode init */
+ in_param.ret_code = mfc_init_encode(mfc_ctx, &(in_param.args));
+ ret = in_param.ret_code;
+ mutex_unlock(&mfc_mutex);
+ break;
+
+ case IOCTL_MFC_ENC_EXE:
+ mutex_lock(&mfc_mutex);
+ if (mfc_ctx->MfcState < MFCINST_STATE_ENC_INITIALIZE) {
+ mfc_err("MFCINST_ERR_STATE_INVALID\n");
+ in_param.ret_code = MFCINST_ERR_STATE_INVALID;
+ ret = -EINVAL;
+ mutex_unlock(&mfc_mutex);
+ break;
+ }
+
+ if (mfc_set_state(mfc_ctx, MFCINST_STATE_ENC_EXE) < 0) {
+ mfc_err("MFCINST_ERR_STATE_INVALID\n");
+ in_param.ret_code = MFCINST_ERR_STATE_INVALID;
+ ret = -EINVAL;
+ mutex_unlock(&mfc_mutex);
+ break;
+ }
+
+ in_param.ret_code = mfc_exe_encode(mfc_ctx, &(in_param.args));
+ ret = in_param.ret_code;
+ mutex_unlock(&mfc_mutex);
+ break;
+
+ case IOCTL_MFC_DEC_INIT:
+ mutex_lock(&mfc_mutex);
+ if (mfc_set_state(mfc_ctx, MFCINST_STATE_DEC_INITIALIZE) < 0) {
+ mfc_err("MFCINST_ERR_STATE_INVALID\n");
+ in_param.ret_code = MFCINST_ERR_STATE_INVALID;
+ ret = -EINVAL;
+ mutex_unlock(&mfc_mutex);
+ break;
+ }
+
+ /* MFC decode init */
+ in_param.ret_code = mfc_init_decode(mfc_ctx, &(in_param.args));
+ if (in_param.ret_code < 0) {
+ ret = in_param.ret_code;
+ mutex_unlock(&mfc_mutex);
+ break;
+ }
+
+ if (in_param.args.dec_init.out_dpb_cnt <= 0) {
+ mfc_err("MFC out_dpb_cnt error\n");
+ mutex_unlock(&mfc_mutex);
+ break;
+ }
+
+ mutex_unlock(&mfc_mutex);
+ break;
+
+ case IOCTL_MFC_DEC_EXE:
+ mutex_lock(&mfc_mutex);
+ if (mfc_ctx->MfcState < MFCINST_STATE_DEC_INITIALIZE) {
+ mfc_err("MFCINST_ERR_STATE_INVALID\n");
+ in_param.ret_code = MFCINST_ERR_STATE_INVALID;
+ ret = -EINVAL;
+ mutex_unlock(&mfc_mutex);
+ break;
+ }
+
+ if (mfc_set_state(mfc_ctx, MFCINST_STATE_DEC_EXE) < 0) {
+ mfc_err("MFCINST_ERR_STATE_INVALID\n");
+ in_param.ret_code = MFCINST_ERR_STATE_INVALID;
+ ret = -EINVAL;
+ mutex_unlock(&mfc_mutex);
+ break;
+ }
+
+ in_param.ret_code = mfc_exe_decode(mfc_ctx, &(in_param.args));
+ ret = in_param.ret_code;
+ mutex_unlock(&mfc_mutex);
+ break;
+
+ case IOCTL_MFC_GET_CONFIG:
+ mutex_lock(&mfc_mutex);
+ if (mfc_ctx->MfcState < MFCINST_STATE_DEC_INITIALIZE) {
+ mfc_err("MFCINST_ERR_STATE_INVALID\n");
+ in_param.ret_code = MFCINST_ERR_STATE_INVALID;
+ ret = -EINVAL;
+ mutex_unlock(&mfc_mutex);
+ break;
+ }
+
+ in_param.ret_code = mfc_get_config(mfc_ctx, &(in_param.args));
+ ret = in_param.ret_code;
+ mutex_unlock(&mfc_mutex);
+ break;
+
+ case IOCTL_MFC_SET_CONFIG:
+ mutex_lock(&mfc_mutex);
+ in_param.ret_code = mfc_set_config(mfc_ctx, &(in_param.args));
+ ret = in_param.ret_code;
+ mutex_unlock(&mfc_mutex);
+ break;
+
+ case IOCTL_MFC_GET_IN_BUF:
+ mutex_lock(&mfc_mutex);
+ if (mfc_ctx->MfcState < MFCINST_STATE_OPENED) {
+ mfc_err("MFCINST_ERR_STATE_INVALID\n");
+ in_param.ret_code = MFCINST_ERR_STATE_INVALID;
+ ret = -EINVAL;
+ mutex_unlock(&mfc_mutex);
+ break;
+ }
+
+ if (in_param.args.mem_alloc.buff_size <= 0) {
+ mfc_err("MFCINST_ERR_INVALID_PARAM\n");
+ in_param.ret_code = MFCINST_ERR_INVALID_PARAM;
+ ret = -EINVAL;
+ mutex_unlock(&mfc_mutex);
+ break;
+ }
+
+ if ((is_dec_codec(in_param.args.mem_alloc.codec_type)) &&
+ (in_param.args.mem_alloc.buff_size < (CPB_BUF_SIZE + DESC_BUF_SIZE))) {
+ in_param.args.mem_alloc.buff_size = CPB_BUF_SIZE + DESC_BUF_SIZE;
+ }
+
+ /* Buffer manager should have 64KB alignment for MFC base addresses */
+ in_param.args.mem_alloc.buff_size = ALIGN_TO_8KB(in_param.args.mem_alloc.buff_size);
+
+ /* allocate stream buf for decoder & current YC buf for encoder */
+ if (is_dec_codec(in_param.args.mem_alloc.codec_type))
+ in_param.ret_code = mfc_allocate_buffer(mfc_ctx, &in_param.args, 0);
+ else
+ in_param.ret_code = mfc_allocate_buffer(mfc_ctx, &in_param.args, 1);
+
+ mfc_ctx->desc_buff_paddr = in_param.args.mem_alloc.out_paddr + CPB_BUF_SIZE;
+
+ ret = in_param.ret_code;
+ mutex_unlock(&mfc_mutex);
+ break;
+
+ case IOCTL_MFC_FREE_BUF:
+ mutex_lock(&mfc_mutex);
+ if (mfc_ctx->MfcState < MFCINST_STATE_OPENED) {
+ mfc_err("MFCINST_ERR_STATE_INVALID\n");
+ in_param.ret_code = MFCINST_ERR_STATE_INVALID;
+ ret = -EINVAL;
+ mutex_unlock(&mfc_mutex);
+ break;
+ }
+
+ in_param.ret_code = mfc_release_buffer((unsigned char *)in_param.args.mem_free.u_addr);
+ ret = in_param.ret_code;
+ mutex_unlock(&mfc_mutex);
+ break;
+
+ case IOCTL_MFC_GET_PHYS_ADDR:
+ mutex_lock(&mfc_mutex);
+ mfc_debug("IOCTL_MFC_GET_PHYS_ADDR\n");
+
+ if (mfc_ctx->MfcState < MFCINST_STATE_OPENED) {
+ mfc_err("MFCINST_ERR_STATE_INVALID\n");
+ in_param.ret_code = MFCINST_ERR_STATE_INVALID;
+ ret = -EINVAL;
+ mutex_unlock(&mfc_mutex);
+ break;
+ }
+
+ in_param.ret_code = mfc_get_phys_addr(mfc_ctx, &(in_param.args));
+ ret = in_param.ret_code;
+ mutex_unlock(&mfc_mutex);
+ break;
+
+ case IOCTL_MFC_GET_MMAP_SIZE:
+
+ if (mfc_ctx->MfcState < MFCINST_STATE_OPENED) {
+ mfc_err("MFC_RET_STATE_INVALID\n");
+ in_param.ret_code = MFCINST_ERR_STATE_INVALID;
+ ret = -EINVAL;
+
+ break;
+ }
+
+ in_param.ret_code = MFCINST_RET_OK;
+ ret = mfc_ctx->port0_mmap_size;
+
+ break;
+
+ case IOCTL_MFC_BUF_CACHE:
+ mutex_lock(&mfc_mutex);
+
+ in_param.ret_code = MFCINST_RET_OK;
+ mfc_ctx->buf_type = in_param.args.buf_type;
+
+ mutex_unlock(&mfc_mutex);
+ break;
+
+ default:
+ mfc_err("Requested ioctl command is not defined. (ioctl cmd=0x%08x)\n", cmd);
+ in_param.ret_code = MFCINST_ERR_INVALID_PARAM;
+ ret = -EINVAL;
+ }
+
+out_ioctl:
+ clk_disable(mfc_sclk);
+
+ ex_ret = copy_to_user((struct mfc_common_args *)arg, &in_param, sizeof(struct mfc_common_args));
+ if (ex_ret < 0) {
+ mfc_err("Outparm copy to user error\n");
+ ret = -EIO;
+ }
+
+ mfc_debug_L0("---------------IOCTL return = %d ---------------\n", ret);
+
+ return ret;
+}
+
+static int mfc_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+ unsigned long vir_size = vma->vm_end - vma->vm_start;
+ unsigned long phy_size, firmware_size;
+ unsigned long page_frame_no = 0;
+ struct mfc_inst_ctx *mfc_ctx;
+
+ mfc_debug("vma->vm_start = 0x%08x, vma->vm_end = 0x%08x\n",
+ (unsigned int)vma->vm_start,
+ (unsigned int)vma->vm_end);
+ mfc_debug("vma->vm_end - vma->vm_start = %ld\n", vir_size);
+
+ mfc_ctx = (struct mfc_inst_ctx *)filp->private_data;
+
+ firmware_size = mfc_get_port0_buff_paddr() - mfc_get_fw_buff_paddr();
+ phy_size = (unsigned long)(mfc_port0_memsize - firmware_size + mfc_port1_memsize);
+
+ /* if memory size required from appl. mmap() is bigger than max data memory
+ * size allocated in the driver */
+ if (vir_size > phy_size) {
+ mfc_err("virtual requested mem(%ld) is bigger than physical mem(%ld)\n",
+ vir_size, phy_size);
+ return -EINVAL;
+ }
+
+ mfc_ctx->port0_mmap_size = mfc_port0_memsize - firmware_size;
+
+ vma->vm_flags |= VM_RESERVED | VM_IO;
+ if (mfc_ctx->buf_type != MFC_BUFFER_CACHE)
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ /*
+ * port0 mapping for stream buf & frame buf (chroma + MV)
+ */
+ page_frame_no = __phys_to_pfn(mfc_get_port0_buff_paddr());
+ if (remap_pfn_range(vma, vma->vm_start, page_frame_no,
+ mfc_ctx->port0_mmap_size, vma->vm_page_prot)) {
+ mfc_err("mfc remap port0 error\n");
+ return -EAGAIN;
+ }
+
+ vma->vm_flags |= VM_RESERVED | VM_IO;
+ if (mfc_ctx->buf_type != MFC_BUFFER_CACHE)
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ /*
+ * port1 mapping for frame buf (luma)
+ */
+ page_frame_no = __phys_to_pfn(mfc_get_port1_buff_paddr());
+ if (remap_pfn_range(vma, vma->vm_start + mfc_ctx->port0_mmap_size,
+ page_frame_no, vir_size - mfc_ctx->port0_mmap_size, vma->vm_page_prot)) {
+ mfc_err("mfc remap port1 error\n");
+ return -EAGAIN;
+ }
+
+ mfc_debug("virtual requested mem = %ld, physical reserved data mem = %ld\n", vir_size, phy_size);
+
+ return 0;
+}
+
+static const struct file_operations mfc_fops = {
+ .owner = THIS_MODULE,
+ .open = mfc_open,
+ .release = mfc_release,
+ .unlocked_ioctl = mfc_ioctl,
+ .mmap = mfc_mmap
+};
+
+
+static struct miscdevice mfc_miscdev = {
+ .minor = 252,
+ .name = "s3c-mfc",
+ .fops = &mfc_fops,
+};
+
+static void mfc_firmware_request_complete_handler(const struct firmware *fw,
+ void *context)
+{
+ if (fw != NULL) {
+ mfc_load_firmware(fw->data, fw->size);
+ mfc_fw_info = fw;
+ } else {
+ mfc_err("failed to load MFC F/W, MFC will not working\n");
+ }
+}
+
+static int mfc_probe(struct platform_device *pdev)
+{
+ struct s3c_platform_mfc *pdata;
+ struct resource *res;
+ size_t size;
+ int ret;
+ unsigned int mfc_port1_alloc_paddr;
+
+ if (!pdev || !pdev->dev.platform_data) {
+ dev_err(&pdev->dev, "Unable to probe mfc!\n");
+ return -1;
+ }
+
+ pdata = pdev->dev.platform_data;
+
+ /* mfc clock enable should be here */
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res == NULL) {
+ dev_err(&pdev->dev, "failed to get memory region resource\n");
+ ret = -ENOENT;
+ goto probe_out;
+ }
+
+ /* 60K is required for mfc register (0x0 ~ 0xe008) */
+ size = (res->end - res->start) + 1;
+ mfc_mem = request_mem_region(res->start, size, pdev->name);
+ if (mfc_mem == NULL) {
+ dev_err(&pdev->dev, "failed to get memory region\n");
+ ret = -ENOENT;
+ goto err_mem_req;
+ }
+
+ mfc_sfr_base_vaddr = ioremap(mfc_mem->start, mfc_mem->end - mfc_mem->start + 1);
+ if (mfc_sfr_base_vaddr == NULL) {
+ dev_err(&pdev->dev, "failed to ioremap address region\n");
+ ret = -ENOENT;
+ goto err_mem_map;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (res == NULL) {
+ dev_err(&pdev->dev, "failed to get irq resource\n");
+ ret = -ENOENT;
+ goto err_irq_res;
+ }
+
+#if !defined(MFC_POLLING)
+ ret = request_irq(res->start, mfc_irq, IRQF_DISABLED, pdev->name, pdev);
+ if (ret != 0) {
+ dev_err(&pdev->dev, "failed to install irq (%d)\n", ret);
+ goto err_irq_req;
+ }
+#endif
+
+ mutex_init(&mfc_mutex);
+
+ /*
+ * buffer memory secure
+ */
+ mfc_port0_base_paddr =(unsigned int)pdata->buf_phy_base[0];
+ mfc_port0_memsize = (unsigned int)pdata->buf_phy_size[0];
+
+ mfc_debug(" mfc_port0_base_paddr= 0x%x \n", mfc_port0_base_paddr);
+ mfc_debug(" mfc_port0_memsize = 0x%x \n", mfc_port0_memsize);
+
+ mfc_port0_base_paddr = ALIGN_TO_128KB(mfc_port0_base_paddr);
+ mfc_port0_base_vaddr = phys_to_virt(mfc_port0_base_paddr);
+
+ if (mfc_port0_base_vaddr == NULL) {
+ mfc_err("fail to mapping port0 buffer\n");
+ ret = -EPERM;
+ goto err_vaddr_map;
+ }
+
+ mfc_port1_alloc_paddr = (unsigned int)pdata->buf_phy_base[1];
+ mfc_port1_memsize = (unsigned int)pdata->buf_phy_size[1];
+
+ mfc_port1_base_paddr = (unsigned int)s5p_get_media_membase_bank(1);
+ mfc_port1_base_paddr = ALIGN_TO_128KB(mfc_port1_base_paddr);
+
+ mfc_debug(" mfc_port1_base_paddr= 0x%x \n", mfc_port1_base_paddr);
+ mfc_debug(" mfc_port1_memsize = 0x%x \n", mfc_port1_memsize);
+
+ mfc_port1_alloc_paddr = ALIGN_TO_128KB(mfc_port1_alloc_paddr);
+ mfc_port1_base_vaddr = phys_to_virt(mfc_port1_alloc_paddr);
+
+ if (mfc_port1_base_vaddr == NULL) {
+ mfc_err("fail to mapping port1 buffer\n");
+ ret = -EPERM;
+ goto err_vaddr_map;
+ }
+
+ mfc_set_port1_buff_paddr(mfc_port1_alloc_paddr);
+
+ mfc_debug("mfc_port0_base_paddr = 0x%08x, mfc_port1_base_paddr = 0x%08x <<\n",
+ (unsigned int)mfc_port0_base_paddr, (unsigned int)mfc_port1_base_paddr);
+ mfc_debug("mfc_port0_base_vaddr = 0x%08x, mfc_port1_base_vaddr = 0x%08x <<\n",
+ (unsigned int)mfc_port0_base_vaddr, (unsigned int)mfc_port1_base_vaddr);
+ mfc_debug("mfc_port1_alloc_paddr = 0x%08x <<\n", (unsigned int)mfc_port1_alloc_paddr);
+
+ /* Get mfc power domain regulator */
+ mfc_pd_regulator = regulator_get(&pdev->dev, "pd");
+ if (IS_ERR(mfc_pd_regulator)) {
+ mfc_err("failed to find mfc power domain\n");
+ ret = PTR_ERR(mfc_pd_regulator);
+ goto err_regulator_get;
+ }
+
+ mfc_sclk = clk_get(&pdev->dev, "sclk_mfc");
+ if (IS_ERR(mfc_sclk)) {
+ mfc_err("failed to find mfc clock source\n");
+ ret = PTR_ERR(mfc_sclk);
+ goto err_clk_get;
+ }
+
+ mfc_init_mem_inst_no();
+ mfc_init_buffer();
+
+ ret = misc_register(&mfc_miscdev);
+ if (ret) {
+ mfc_err("MFC can't misc register on minor\n");
+ goto err_misc_reg;
+ }
+
+ /*
+ * MFC FW downloading
+ */
+ ret = request_firmware_nowait(THIS_MODULE,
+ FW_ACTION_HOTPLUG,
+ MFC_FW_NAME,
+ &pdev->dev,
+ GFP_KERNEL,
+ pdev,
+ mfc_firmware_request_complete_handler);
+ if (ret) {
+ mfc_err("MFCINST_ERR_FW_INIT_FAIL\n");
+ ret = -EPERM;
+ goto err_req_fw;
+ }
+
+ return 0;
+
+err_req_fw:
+ misc_deregister(&mfc_miscdev);
+err_misc_reg:
+ clk_put(mfc_sclk);
+err_clk_get:
+ regulator_put(mfc_pd_regulator);
+err_regulator_get:
+err_vaddr_map:
+ free_irq(res->start, pdev);
+ mutex_destroy(&mfc_mutex);
+err_irq_req:
+err_irq_res:
+ iounmap(mfc_sfr_base_vaddr);
+err_mem_map:
+ release_mem_region(mfc_mem, size);
+err_mem_req:
+probe_out:
+ dev_err(&pdev->dev, "not found (%d).\n", ret);
+ return ret;
+}
+
+static int mfc_remove(struct platform_device *pdev)
+{
+ iounmap(mfc_sfr_base_vaddr);
+ iounmap(mfc_port0_base_vaddr);
+
+ /* remove memory region */
+ if (mfc_mem != NULL) {
+ release_resource(mfc_mem);
+ kfree(mfc_mem);
+ mfc_mem = NULL;
+ }
+
+ free_irq(IRQ_MFC, pdev);
+
+ mutex_destroy(&mfc_mutex);
+
+ clk_put(mfc_sclk);
+
+ misc_deregister(&mfc_miscdev);
+
+ if (mfc_fw_info)
+ release_firmware(mfc_fw_info);
+
+ return 0;
+}
+
+static int mfc_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ int ret = 0;
+
+ mutex_lock(&mfc_mutex);
+
+ if (!mfc_is_running()) {
+ mutex_unlock(&mfc_mutex);
+ return 0;
+ }
+ clk_enable(mfc_sclk);
+
+ ret = mfc_set_sleep();
+ if (ret != MFCINST_RET_OK) {
+ clk_disable(mfc_sclk);
+ mutex_unlock(&mfc_mutex);
+ return ret;
+ }
+
+ clk_disable(mfc_sclk);
+
+ mutex_unlock(&mfc_mutex);
+
+ return 0;
+}
+
+static int mfc_resume(struct platform_device *pdev)
+{
+ int ret = 0;
+ unsigned int mc_status;
+
+ mutex_lock(&mfc_mutex);
+
+ if (!mfc_is_running()) {
+ mutex_unlock(&mfc_mutex);
+ return 0;
+ }
+
+ clk_enable(mfc_sclk);
+
+ /*
+ * 1. MFC reset
+ */
+ do {
+ mc_status = READL(MFC_MC_STATUS);
+ } while (mc_status != 0);
+
+ if (mfc_cmd_reset() == false) {
+ clk_disable(mfc_sclk);
+ mutex_unlock(&mfc_mutex);
+ mfc_err("MFCINST_ERR_INIT_FAIL\n");
+ return MFCINST_ERR_INIT_FAIL;
+ }
+
+ WRITEL(mfc_port0_base_paddr, MFC_MC_DRAMBASE_ADDR_A);
+ WRITEL(mfc_port1_base_paddr, MFC_MC_DRAMBASE_ADDR_B);
+ WRITEL(1, MFC_NUM_MASTER);
+
+ ret = mfc_set_wakeup();
+ if (ret != MFCINST_RET_OK) {
+ clk_disable(mfc_sclk);
+ mutex_unlock(&mfc_mutex);
+ return ret;
+ }
+
+ clk_disable(mfc_sclk);
+
+ mutex_unlock(&mfc_mutex);
+
+ return 0;
+}
+
+static struct platform_driver mfc_driver = {
+ .probe = mfc_probe,
+ .remove = mfc_remove,
+ .shutdown = NULL,
+ .suspend = mfc_suspend,
+ .resume = mfc_resume,
+
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "s3c-mfc",
+ },
+};
+
+static char banner[] __initdata = KERN_INFO "S5PC110 MFC Driver, (c) 2009 Samsung Electronics\n";
+
+static int __init mfc_init(void)
+{
+ mfc_info("%s\n", banner);
+
+ if (platform_driver_register(&mfc_driver) != 0) {
+ mfc_err(KERN_ERR "platform device registration failed..\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static void __exit mfc_exit(void)
+{
+ platform_driver_unregister(&mfc_driver);
+ mfc_info("S5PC110 MFC Driver exit.\n");
+}
+
+module_init(mfc_init);
+module_exit(mfc_exit);
+
+MODULE_AUTHOR("Jaeryul, Oh");
+MODULE_DESCRIPTION("S3C MFC (Multi Function Codec - FIMV5.0) Device Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/samsung/mfc50/mfc_buffer_manager.c b/drivers/media/video/samsung/mfc50/mfc_buffer_manager.c
new file mode 100644
index 0000000..c480cde
--- /dev/null
+++ b/drivers/media/video/samsung/mfc50/mfc_buffer_manager.c
@@ -0,0 +1,350 @@
+/*
+ * drivers/media/video/samsung/mfc50/mfc_buffer_manager.c
+ *
+ * C file for Samsung MFC (Multi Function Codec - FIMV) driver
+ *
+ * Key-Young Park, Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * Change Logs
+ * 2009.09.14 - use struct list_head for duble linked list
+ * 2009.11.04 - get physical address via mfc_allocate_buffer (Key Young, Park)
+ * 2009.11.13 - fix free buffer fragmentation (Key Young, Park)
+ *
+ * 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/mm.h>
+#include <linux/interrupt.h>
+#include <linux/miscdevice.h>
+#include <linux/platform_device.h>
+#include <linux/wait.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include <linux/io.h>
+#include <linux/uaccess.h>
+
+#include <plat/media.h>
+#include <mach/media.h>
+
+#include "mfc_buffer_manager.h"
+#include "mfc_errorno.h"
+#include "mfc_logmsg.h"
+#include "mfc_memory.h"
+
+static struct list_head mfc_alloc_mem_head[MFC_MAX_PORT_NUM];
+static struct list_head mfc_free_mem_head[MFC_MAX_PORT_NUM];
+
+void mfc_print_mem_list(void)
+{
+ struct list_head *pos;
+ struct mfc_alloc_mem *alloc_node;
+ struct mfc_free_mem *free_node;
+ int port_no;
+
+ for (port_no = 0; port_no < MFC_MAX_PORT_NUM; port_no++) {
+ mfc_info("===== %s port%d list =====\n", __func__, port_no);
+ list_for_each(pos, &mfc_alloc_mem_head[port_no])
+ {
+ alloc_node = list_entry(pos, struct mfc_alloc_mem, list);
+ mfc_info("[alloc_list] inst_no: %d, p_addr: 0x%08x, "
+ "u_addr: 0x%p, size: %d\n",
+ alloc_node->inst_no,
+ alloc_node->p_addr,
+ alloc_node->u_addr,
+ alloc_node->size);
+ }
+
+ list_for_each(pos, &mfc_free_mem_head[port_no])
+ {
+ free_node = list_entry(pos, struct mfc_free_mem, list);
+ mfc_info("[free_list] start_addr: 0x%08x size:%d\n",
+ free_node->start_addr , free_node->size);
+ }
+ }
+}
+
+void mfc_merge_fragment(int inst_no)
+{
+ struct list_head *pos, *n;
+ struct mfc_free_mem *node1, *node2;
+ int port_no;
+
+ for (port_no = 0; port_no < MFC_MAX_PORT_NUM; port_no++) {
+ list_for_each_safe(pos, n, &mfc_free_mem_head[port_no])
+ {
+ node1 = list_entry(pos, struct mfc_free_mem, list);
+ node2 = list_entry(n, struct mfc_free_mem, list);
+ if ((node1->start_addr + node1->size) == node2->start_addr) {
+ node2->start_addr = node1->start_addr;
+ node2->size += node1->size;
+ list_del(&(node1->list));
+ kfree(node1);
+ }
+ }
+ }
+
+#if defined(DEBUG)
+ mfc_print_mem_list();
+#endif
+}
+
+
+
+static unsigned int mfc_get_free_mem(int alloc_size, int inst_no, int port_no)
+{
+ struct list_head *pos;
+ struct mfc_free_mem *free_node, *match_node = NULL;
+ unsigned int alloc_addr = 0;
+
+ mfc_debug("request Size : %d\n", alloc_size);
+
+ if (list_empty(&mfc_free_mem_head[port_no])) {
+ mfc_err("all memory is gone\n");
+ return alloc_addr;
+ }
+ /* find best chunk of memory */
+ list_for_each(pos, &mfc_free_mem_head[port_no])
+ {
+ free_node = list_entry(pos, struct mfc_free_mem, list);
+
+ if (match_node != NULL) {
+ if ((free_node->size >= alloc_size) &&
+ (free_node->size < match_node->size))
+ match_node = free_node;
+ } else {
+ if (free_node->size >= alloc_size)
+ match_node = free_node;
+ }
+ }
+
+
+ if (match_node != NULL) {
+ mfc_debug("match : startAddr(0x%08x) size(%d)\n", match_node->start_addr, match_node->size);
+
+ alloc_addr = match_node->start_addr;
+ match_node->start_addr += alloc_size;
+ match_node->size -= alloc_size;
+
+ if (match_node->size < 0x1) /* delete match_node. */
+ mfc_err("there is no suitable chunk...[case 0]\n");
+ } else {
+ mfc_err("there is no suitable chunk....[case 1]\n");
+ return 0;
+ }
+
+ return alloc_addr;
+}
+
+
+int mfc_init_buffer(void)
+{
+ struct mfc_free_mem *free_node;
+ int port_no;
+
+ for (port_no = 0; port_no < MFC_MAX_PORT_NUM; port_no++) {
+ INIT_LIST_HEAD(&mfc_alloc_mem_head[port_no]);
+ INIT_LIST_HEAD(&mfc_free_mem_head[port_no]);
+ /* init free head node */
+ free_node =
+ (struct mfc_free_mem *)kmalloc(sizeof(struct mfc_free_mem), GFP_KERNEL);
+ memset(free_node, 0x00, sizeof(struct mfc_free_mem));
+
+ if (port_no) {
+ free_node->start_addr = mfc_get_port1_buff_paddr();
+ free_node->size = mfc_port1_memsize;
+ } else {
+ free_node->start_addr = mfc_get_port0_buff_paddr();
+ free_node->size = mfc_port0_memsize -
+ (mfc_get_port0_buff_paddr() - mfc_get_fw_buff_paddr());
+ }
+
+ list_add_tail(&(free_node->list), &mfc_free_mem_head[port_no]);
+ }
+
+#if defined(DEBUG)
+ mfc_print_mem_list();
+#endif
+ return 0;
+}
+
+enum mfc_error_code mfc_release_buffer(unsigned char *u_addr)
+{
+ struct list_head *pos;
+ int port_no;
+ struct mfc_alloc_mem *alloc_node;
+ bool found = false;
+
+ for (port_no = 0; port_no < MFC_MAX_PORT_NUM; port_no++) {
+ list_for_each(pos, &mfc_alloc_mem_head[port_no])
+ {
+ alloc_node = list_entry(pos, struct mfc_alloc_mem, list);
+ if (alloc_node->u_addr == u_addr) {
+ mfc_free_alloc_mem(alloc_node, port_no);
+ found = true;
+ break;
+ }
+ }
+ }
+
+#if defined(DEBUG)
+ mfc_print_mem_list();
+#endif
+
+ if (found)
+ return MFCINST_RET_OK;
+ else
+ return MFCINST_MEMORY_INVALID_ADDR;
+}
+
+void mfc_release_all_buffer(int inst_no)
+{
+ struct list_head *pos, *n;
+ int port_no;
+ struct mfc_alloc_mem *alloc_node;
+
+ for (port_no = 0; port_no < MFC_MAX_PORT_NUM; port_no++) {
+ list_for_each_safe(pos, n, &mfc_alloc_mem_head[port_no]) {
+ alloc_node = list_entry(pos, struct mfc_alloc_mem, list);
+ if (alloc_node->inst_no == inst_no) {
+ mfc_free_alloc_mem(alloc_node, port_no);
+ }
+ }
+ }
+
+#if defined(DEBUG)
+ mfc_print_mem_list();
+#endif
+}
+
+void mfc_free_alloc_mem(struct mfc_alloc_mem *alloc_node, int port_no)
+{
+ struct list_head *pos;
+ struct mfc_free_mem *free_node;
+ struct mfc_free_mem *target_node;
+
+ free_node = (struct mfc_free_mem *)kmalloc(sizeof(struct mfc_free_mem), GFP_KERNEL);
+ free_node->start_addr = alloc_node->p_addr;
+ free_node->size = alloc_node->size;
+
+ list_for_each(pos, &mfc_free_mem_head[port_no])
+ {
+ target_node = list_entry(pos, struct mfc_free_mem, list);
+ if (alloc_node->p_addr < target_node->start_addr)
+ break;
+ }
+
+ if (pos == &mfc_free_mem_head[port_no])
+ list_add_tail(&(free_node->list), &(mfc_free_mem_head[port_no]));
+ else
+ list_add_tail(&(free_node->list), pos);
+
+ list_del(&(alloc_node->list));
+ kfree(alloc_node);
+}
+
+enum mfc_error_code mfc_get_phys_addr(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args)
+{
+ int ret, port_no;
+ struct list_head *pos;
+ struct mfc_alloc_mem *alloc_node;
+ struct mfc_get_phys_addr_arg *phys_addr_arg;
+
+ phys_addr_arg = (struct mfc_get_phys_addr_arg *)args;
+ for (port_no = 0; port_no < MFC_MAX_PORT_NUM; port_no++) {
+ list_for_each(pos, &mfc_alloc_mem_head[port_no])
+ {
+ alloc_node = list_entry(pos, struct mfc_alloc_mem, list);
+ if (alloc_node->u_addr == (unsigned char *)phys_addr_arg->u_addr) {
+ mfc_debug("u_addr(0x%08x), p_addr(0x%08x) is found\n",
+ alloc_node->u_addr, alloc_node->p_addr);
+ goto found;
+ }
+ }
+ }
+
+ mfc_err("invalid virtual address(0x%08x)\r\n", phys_addr_arg->u_addr);
+ ret = MFCINST_MEMORY_INVALID_ADDR;
+ goto out_getphysaddr;
+
+found:
+ phys_addr_arg->p_addr = alloc_node->p_addr;
+ ret = MFCINST_RET_OK;
+
+out_getphysaddr:
+ return ret;
+}
+
+enum mfc_error_code mfc_allocate_buffer(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args, int port_no)
+{
+ int ret;
+ int inst_no = mfc_ctx->mem_inst_no;
+ unsigned int start_paddr;
+ struct mfc_mem_alloc_arg *in_param;
+ struct mfc_alloc_mem *alloc_node;
+
+ in_param = (struct mfc_mem_alloc_arg *)args;
+
+ alloc_node = (struct mfc_alloc_mem *)kmalloc(sizeof(struct mfc_alloc_mem), GFP_KERNEL);
+ if (!alloc_node) {
+ mfc_err("There is no more kernel memory");
+ ret = MFCINST_MEMORY_ALLOC_FAIL;
+ goto out_getcodecviraddr;
+ }
+ memset(alloc_node, 0x00, sizeof(struct mfc_alloc_mem));
+
+ /* if user request area, allocate from reserved area */
+ start_paddr = mfc_get_free_mem((int)in_param->buff_size, inst_no, port_no);
+ mfc_debug("start_paddr = 0x%X\n\r", start_paddr);
+
+ if (!start_paddr) {
+ mfc_err("There is no more memory\n\r");
+ in_param->out_uaddr = -1;
+ ret = MFCINST_MEMORY_ALLOC_FAIL;
+ kfree(alloc_node);
+ goto out_getcodecviraddr;
+ }
+
+ alloc_node->p_addr = start_paddr;
+ if (port_no) {
+ alloc_node->v_addr = (unsigned char *)(mfc_get_port1_buff_vaddr() +
+ (alloc_node->p_addr - mfc_get_port1_buff_paddr()));
+ alloc_node->u_addr = (unsigned char *)(in_param->mapped_addr +
+ mfc_ctx->port0_mmap_size +
+ (alloc_node->p_addr - mfc_get_port1_buff_paddr()));
+ } else {
+ alloc_node->v_addr = (unsigned char *)(mfc_get_port0_buff_vaddr() +
+ (alloc_node->p_addr - mfc_get_port0_buff_paddr()));
+ alloc_node->u_addr = (unsigned char *)(in_param->mapped_addr +
+ (alloc_node->p_addr - mfc_get_port0_buff_paddr()));
+ }
+
+ in_param->out_uaddr = (unsigned int)alloc_node->u_addr;
+ in_param->out_paddr = (unsigned int)alloc_node->p_addr;
+ mfc_debug("u_addr : 0x%08x v_addr : 0x%08x p_addr : 0x%08x\n",
+ (unsigned int)alloc_node->u_addr,
+ (unsigned int)alloc_node->v_addr,
+ alloc_node->p_addr);
+
+ alloc_node->size = (int)in_param->buff_size;
+ alloc_node->inst_no = inst_no;
+
+ list_add(&(alloc_node->list), &mfc_alloc_mem_head[port_no]);
+ ret = MFCINST_RET_OK;
+
+#if defined(DEBUG)
+ mfc_print_mem_list();
+#endif
+
+out_getcodecviraddr:
+ return ret;
+}
diff --git a/drivers/media/video/samsung/mfc50/mfc_buffer_manager.h b/drivers/media/video/samsung/mfc50/mfc_buffer_manager.h
new file mode 100644
index 0000000..d40bc04
--- /dev/null
+++ b/drivers/media/video/samsung/mfc50/mfc_buffer_manager.h
@@ -0,0 +1,56 @@
+/*
+ * drivers/media/video/samsung/mfc50/mfc_buffer_manager.h
+ *
+ * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
+ *
+ * Key-Young Park, Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * Change Logs
+ * 2009.11.04 - remove mfc_common.[ch]
+ * seperate buffer alloc & set (Key Young, Park)
+ *
+ * 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 _MFC_BUFFER_MANAGER_H_
+#define _MFC_BUFFER_MANAGER_H_
+
+#include <linux/list.h>
+#include "mfc_interface.h"
+#include "mfc_opr.h"
+
+#define MFC_MAX_PORT_NUM 2
+
+/* Struct Definition */
+struct mfc_alloc_mem {
+ struct list_head list; /* strcut list_head for alloc mem */
+ unsigned int p_addr; /* physical address */
+ unsigned char *v_addr; /* virtual address */
+ unsigned char *u_addr; /* virtual address for user mode process */
+ int size; /* memory size */
+ int inst_no; /* instance no */
+};
+
+
+struct mfc_free_mem {
+ struct list_head list; /* struct list_head for free mem */
+ unsigned int start_addr; /* start address of free mem */
+ unsigned int size; /* size of free mem */
+};
+
+
+/* Function Prototype */
+void mfc_print_mem_list(void);
+int mfc_init_buffer(void);
+void mfc_merge_fragment(int inst_no);
+void mfc_release_all_buffer(int inst_no);
+void mfc_free_alloc_mem(struct mfc_alloc_mem *alloc_node, int port_no);
+enum mfc_error_code mfc_release_buffer(unsigned char *u_addr);
+enum mfc_error_code mfc_get_phys_addr(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args);
+enum mfc_error_code mfc_allocate_buffer(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args, int port_no);
+
+#endif /* _MFC_BUFFER_MANAGER_H_ */
diff --git a/drivers/media/video/samsung/mfc50/mfc_errorno.h b/drivers/media/video/samsung/mfc50/mfc_errorno.h
new file mode 100644
index 0000000..7f27115
--- /dev/null
+++ b/drivers/media/video/samsung/mfc50/mfc_errorno.h
@@ -0,0 +1,83 @@
+/*
+ * drivers/media/video/samsung/mfc50/mfc_errorno.h
+ *
+ * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
+ *
+ * Jaeryul Oh, Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * Change Logs
+ * 2009.09.14 - Beautify source code (Key Young, Park)
+ * 2009.09.21 - Implement clock & power gating.
+ * including suspend & resume fuction. (Key Young, Park)
+ *
+ * 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 _MFC_ERRORNO_H_
+#define _MFC_ERRORNO_H_
+
+enum mfc_error_code {
+ MFCINST_RET_OK = 1,
+ MFCINST_ERR_INVALID_PARAM = -1001,
+ MFCINST_ERR_STATE_INVALID = -1002,
+ MFCINST_ERR_POWER_OFF = -1003,
+ MFCINST_ERR_WRONG_CODEC_MODE = -1004,
+ MFCINST_ERR_INIT_FAIL = -1005,
+ MFCINST_ERR_FILE_OPEN_FAIL = -1006,
+ MFCINST_ERR_INTR_TIME_OUT = -1007,
+ MFCINST_ERR_INTR_INIT_FAIL = -1008,
+ MFCINST_ERR_OPEN_FAIL = -1009,
+ MFCINST_ERR_CLOSE_FAIL = -1010,
+
+
+ MFCINST_ERR_DEC_INIT_CMD_FAIL = -2001,
+ MFCINST_ERR_DEC_HEADER_DECODE_FAIL = -2002,
+ MFCINST_ERR_DEC_INIT_BUFFER_FAIL = -2003,
+ MFCINST_ERR_DEC_DECODE_CMD_FAIL = -2004,
+ MFCINST_ERR_DEC_DECODE_DONE_FAIL = -2005,
+ MFCINST_ERR_DEC_INVALID_STRM = -2006,
+ MFCINST_ERR_DEC_STRM_SIZE_INVALID = -2007,
+ MFCINST_ERR_DEC_SEQ_DONE_FAIL = -2008,
+ MFCINST_ERR_DEC_NON_I_FRAME_START = -2009,
+
+ MFCINST_ERR_ENC_INIT_CMD_FAIL = -3001,
+ MFCINST_ERR_ENC_HEADER_DECODE_FAIL = -3002,
+ MFCINST_ERR_ENC_ENCODE_CMD_FAIL = -3003,
+ MFCINST_ERR_ENC_ENCODE_DONE_FAIL = -3004,
+ MFCINST_ERR_ENC_PARAM_INVALID_VALUE = -3005,
+
+ MFCINST_ERR_STRM_BUF_INVALID = -4001,
+ MFCINST_ERR_FRM_BUF_INVALID = -4002,
+ MFCINST_ERR_FRM_BUF_SIZE = -4003,
+
+ MFCINST_ERR_FW_LOAD_FAIL = -5001,
+ MFCINST_ERR_FW_MEMORY_INVALID = -5002,
+ MFCINST_ERR_FW_DMA_SET_FAIL = -5003,
+ MFCINST_ERR_FW_INIT_FAIL = -5004,
+ MFCINST_ERR_SEQ_START_FAIL = -5005,
+
+ MFCINST_INST_NUM_INVALID = -6001,
+ MFCINST_INST_NUM_EXCEEDED = -6002,
+ MFCINST_ERR_SET_CONF = -6003,
+ MFCINST_ERR_GET_CONF = -6004,
+
+ MFCINST_MEMORY_ALLOC_FAIL = -8001,
+ MFCINST_MUTEX_CREATE_FAIL = -8002,
+ MFCINST_POWER_INIT_FAIL = -8003,
+ MFCINST_POWER_ON_OFF_FAIL = -8004,
+ MFCINST_POWER_STATE_INVALID = -8005,
+ MFCINST_POWER_MANAGER_ERR = -8006,
+ MFCINST_SLEEP_FAIL = -8007,
+ MFCINST_WAKEUP_FAIL = -8008,
+
+ MFCINST_MEMORY_INVALID_ADDR = -8101,
+ MFCINST_MEMORY_MAPPING_FAIL = -8102,
+
+ MFCAPI_RET_FAIL = -9001,
+};
+
+#endif /* _MFC_ERRORNO_H_ */
+
diff --git a/drivers/media/video/samsung/mfc50/mfc_interface.h b/drivers/media/video/samsung/mfc50/mfc_interface.h
new file mode 100644
index 0000000..4da825a
--- /dev/null
+++ b/drivers/media/video/samsung/mfc50/mfc_interface.h
@@ -0,0 +1,340 @@
+/*
+ * drivers/media/video/samsung/mfc50/mfc_interface.h
+ *
+ * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
+ *
+ * Jaeryul Oh, Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * Change Logs
+ * 2009.09.14 - Beautify source code (Key Young, Park)
+ * 2009.10.22 - Change codec name VC1AP_DEC -> VC1_DEC (Key Young, Park)
+ * 2009.11.04 - get physical address via mfc_allocate_buffer (Key Young, Park)
+ * 2009.11.06 - Apply common MFC API (Key Young, Park)
+ *
+ * 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 _MFC_INTERFACE_H_
+#define _MFC_INTERFACE_H_
+
+#include "mfc_errorno.h"
+
+#define IOCTL_MFC_DEC_INIT 0x00800001
+#define IOCTL_MFC_ENC_INIT 0x00800002
+#define IOCTL_MFC_DEC_EXE 0x00800003
+#define IOCTL_MFC_ENC_EXE 0x00800004
+
+#define IOCTL_MFC_GET_IN_BUF 0x00800010
+#define IOCTL_MFC_FREE_BUF 0x00800011
+#define IOCTL_MFC_GET_PHYS_ADDR 0x00800012
+#define IOCTL_MFC_GET_MMAP_SIZE 0x00800014
+
+#define IOCTL_MFC_SET_CONFIG 0x00800101
+#define IOCTL_MFC_GET_CONFIG 0x00800102
+
+#define IOCTL_MFC_BUF_CACHE 0x00801000
+
+/* MFC H/W support maximum 32 extra DPB */
+#define MFC_MAX_EXTRA_DPB 4
+
+#define ENC_PROFILE_LEVEL(profile, level) ((profile) | ((level) << 8))
+
+#define ENC_PROFILE_MPEG4_SP 0
+#define ENC_PROFILE_MPEG4_ASP 1
+#define ENC_PROFILE_H264_BP 0
+#define ENC_PROFILE_H264_MAIN 1
+#define ENC_PROFILE_H264_HIGH 2
+
+#define ENC_RC_DISABLE 0
+#define ENC_RC_ENABLE_MACROBLOCK 1
+#define ENC_RC_ENABLE_FRAME 2
+
+#define ENC_RC_QBOUND(min_qp, max_qp) ((min_qp) | ((max_qp) << 8))
+#define ENC_RC_MB_CTRL_DARK_DISABLE (1 << 3)
+#define ENC_RC_MB_CTRL_SMOOTH_DISABLE (1 << 2)
+#define ENC_RC_MB_CTRL_STATIC_DISABLE (1 << 1)
+#define ENC_RC_MB_CTRL_ACTIVITY_DISABLE (1 << 0)
+
+
+enum ssbsip_mfc_codec_type {
+ H264_DEC,
+ VC1_DEC, /* VC1 advaced Profile decoding */
+ MPEG4_DEC,
+ XVID_DEC,
+ MPEG1_DEC,
+ MPEG2_DEC,
+ H263_DEC,
+ VC1RCV_DEC, /* VC1 simple/main profile decoding */
+ FIMV1_DEC,
+ FIMV2_DEC,
+ FIMV3_DEC,
+ FIMV4_DEC,
+ H264_ENC,
+ MPEG4_ENC,
+ H263_ENC,
+ UNKNOWN_TYPE
+};
+
+enum ssbsip_mfc_force_set_frame_type {
+ DONT_CARE = 0,
+ I_FRAME = 1,
+ NOT_CODED = 2
+};
+
+enum ssbsip_mfc_dec_conf {
+ MFC_DEC_SETCONF_POST_ENABLE = 1,
+ MFC_DEC_SETCONF_EXTRA_BUFFER_NUM,
+ MFC_DEC_SETCONF_DISPLAY_DELAY,
+ MFC_DEC_SETCONF_IS_LAST_FRAME,
+ MFC_DEC_SETCONF_SLICE_ENABLE,
+ MFC_DEC_SETCONF_CRC_ENABLE,
+ MFC_DEC_SETCONF_FIMV1_WIDTH_HEIGHT,
+ MFC_DEC_SETCONF_FRAME_TAG,
+ MFC_DEC_GETCONF_CRC_DATA,
+ MFC_DEC_GETCONF_BUF_WIDTH_HEIGHT,
+ FC_DEC_GETCONF_CROP_INFO,
+ MFC_DEC_GETCONF_FRAME_TAG
+};
+
+enum ssbsip_mfc_enc_conf {
+ MFC_ENC_SETCONF_FRAME_TYPE = 100,
+ MFC_ENC_SETCONF_CHANGE_FRAME_RATE,
+ MFC_ENC_SETCONF_CHANGE_BIT_RATE,
+ MFC_ENC_SETCONF_FRAME_TAG,
+ MFC_ENC_SETCONF_ALLOW_FRAME_SKIP,
+ MFC_ENC_GETCONF_FRAME_TAG
+};
+
+struct mfc_strm_ref_buf_arg {
+ unsigned int strm_ref_y;
+ unsigned int mv_ref_yc;
+};
+
+struct mfc_frame_buf_arg {
+ unsigned int luma;
+ unsigned int chroma;
+};
+
+struct mfc_enc_init_mpeg4_arg {
+ enum ssbsip_mfc_codec_type in_codec_type; /* [IN] codec type */
+ int in_width; /* [IN] width of YUV420 frame to be encoded */
+ int in_height; /* [IN] height of YUV420 frame to be encoded */
+ int in_profile_level; /* [IN] profile & level */
+ int in_gop_num; /* [IN] GOP Number (interval of I-frame) */
+ int in_frame_qp; /* [IN] the quantization parameter of the frame */
+ int in_frame_P_qp; /* [IN] the quantization parameter of the P frame */
+ int in_frame_B_qp; /* [IN] the quantization parameter of the B frame */
+
+ int in_RC_frm_enable; /* [IN] RC enable (0:disable, 1:frame level RC) */
+ int in_RC_framerate; /* [IN] RC parameter (framerate) */
+ int in_RC_bitrate; /* [IN] RC parameter (bitrate in kbps) */
+ int in_RC_qbound; /* [IN] RC parameter (Q bound) */
+ int in_RC_rpara; /* [IN] RC parameter (Reaction Coefficient) */
+
+ int in_MS_mode; /* [IN] Multi-slice mode (0:single, 1:multiple) */
+ int in_MS_size; /* [IN] Multi-slice size (in num. of mb or byte) */
+ int in_mb_refresh; /* [IN] Macroblock refresh */
+ int in_interlace_mode; /* [IN] interlace mode(0:progressive, 1:interlace) */
+ int in_BframeNum; /* [IN] B frame number */
+
+ int in_pad_ctrl_on; /* [IN] Enable (1) / Disable (0) padding */
+ int in_luma_pad_val; /* [IN] pad value if pad_ctrl_on is Enable */
+ int in_cb_pad_val;
+ int in_cr_pad_val;
+
+ int in_frame_map; /* [IN] Encoding input NV12 type linear(0) TILE(1) */
+
+ unsigned int in_mapped_addr;
+ struct mfc_strm_ref_buf_arg out_u_addr;
+ struct mfc_strm_ref_buf_arg out_p_addr;
+ struct mfc_strm_ref_buf_arg out_buf_size;
+ unsigned int out_header_size;
+
+ /* MPEG4 Only */
+ int in_qpelME_enable; /* [IN] Quarter-pel MC enable(1:enable, 0:disable) */
+ int in_time_increament_res; /* [IN] time increment resolution */
+ int in_time_vop_time_increament; /* [IN] time increment */
+};
+
+//struct mfc_enc_init_mpeg4_arg mfc_enc_init_h263_arg;
+
+struct mfc_enc_init_h264_arg {
+ enum ssbsip_mfc_codec_type in_codec_type; /* [IN] codec type */
+ int in_width; /* [IN] width of YUV420 frame to be encoded */
+ int in_height; /* [IN] height of YUV420 frame to be encoded */
+ int in_profile_level; /* [IN] profile & level */
+ int in_gop_num; /* [IN] GOP Number (interval of I-frame) */
+ int in_frame_qp; /* [IN] the quantization parameter of the frame */
+ int in_frame_P_qp; /* [IN] the quantization parameter of the P frame */
+ int in_frame_B_qp; /* [IN] the quantization parameter of the B frame */
+
+ int in_RC_frm_enable; /* [IN] RC enable (0:disable, 1:frame level RC) */
+ int in_RC_framerate; /* [IN] RC parameter (framerate) */
+ int in_RC_bitrate; /* [IN] RC parameter (bitrate in kbps) */
+ int in_RC_qbound; /* [IN] RC parameter (Q bound) */
+ int in_RC_rpara; /* [IN] RC parameter (Reaction Coefficient) */
+
+ int in_MS_mode; /* [IN] Multi-slice mode (0:single, 1:multiple) */
+ int in_MS_size; /* [IN] Multi-slice size (in num. of mb or byte) */
+ int in_mb_refresh; /* [IN] Macroblock refresh */
+ int in_interlace_mode; /* [IN] interlace mode(0:progressive, 1:interlace) */
+ int in_BframeNum;
+
+ int in_pad_ctrl_on; /* [IN] Enable padding control */
+ int in_luma_pad_val; /* [IN] Luma pel value used to fill padding area */
+ int in_cb_pad_val; /* [IN] CB pel value used to fill padding area */
+ int in_cr_pad_val; /* [IN] CR pel value used to fill padding area */
+
+ int in_frame_map; /* [IN] Encoding input NV12 type linear(0) TILE(1) */
+
+ unsigned int in_mapped_addr;
+ struct mfc_strm_ref_buf_arg out_u_addr;
+ struct mfc_strm_ref_buf_arg out_p_addr;
+ struct mfc_strm_ref_buf_arg out_buf_size;
+ unsigned int out_header_size;
+
+ /* H264 Only */
+ int in_RC_mb_enable; /* [IN] RC enable (0:disable, 1:MB level RC) */
+ int in_reference_num; /* [IN] The number of reference pictures used */
+ int in_ref_num_p; /* [IN] The number of reference pictures used for P pictures */
+ int in_RC_mb_dark_disable; /* [IN] Disable adaptive rate control on dark region */
+ int in_RC_mb_smooth_disable; /* [IN] Disable adaptive rate control on smooth region */
+ int in_RC_mb_static_disable; /* [IN] Disable adaptive rate control on static region */
+ int in_RC_mb_activity_disable; /* [IN] Disable adaptive rate control on static region */
+ int in_deblock_filt; /* [IN] disable the loop filter */
+ int in_deblock_alpha_C0; /* [IN] Alpha & C0 offset for H.264 loop filter */
+ int in_deblock_beta; /* [IN] Beta offset for H.264 loop filter */
+ int in_symbolmode; /* [IN] The mode of entropy coding(CABAC, CAVLC) */
+ int in_transform8x8_mode; /* [IN] Allow 8x8 transform(only for high profile) */
+ int in_md_interweight_pps; /* [IN] Inter weighted parameter for mode decision */
+ int in_md_intraweight_pps; /* [IN] Intra weighted parameter for mode decision */
+};
+
+struct mfc_enc_exe_arg {
+ enum ssbsip_mfc_codec_type in_codec_type; /* [IN] codec type */
+ unsigned int in_Y_addr; /* [IN] In-buffer addr of Y component */
+ unsigned int in_CbCr_addr; /* [IN] In-buffer addr of CbCr component */
+ unsigned int in_Y_addr_vir; /* [IN] In-buffer addr of Y component */
+ unsigned int in_CbCr_addr_vir; /* [IN] In-buffer addr of CbCr component */
+ unsigned int in_strm_st; /* [IN] Out-buffer start addr of encoded strm */
+ unsigned int in_strm_end; /* [IN] Out-buffer end addr of encoded strm */
+ int in_frametag; /* [IN] unique frame ID */
+
+ unsigned int out_frame_type; /* [OUT] frame type */
+ int out_encoded_size; /* [OUT] Length of Encoded video stream */
+ unsigned int out_encoded_Y_paddr; /* [OUT] physical Y address which is flushed */
+ unsigned int out_encoded_C_paddr; /* [OUT] physical C address which is flushed */
+ int out_frametag_top; /* [OUT] unique frame ID of an output frame or top field */
+ int out_frametag_bottom; /* [OUT] unique frame ID of bottom field */
+};
+
+struct mfc_dec_init_arg {
+ enum ssbsip_mfc_codec_type in_codec_type; /* [IN] codec type */
+ unsigned int in_strm_buf; /* [IN] the physical address of STRM_BUF */
+ int in_strm_size; /* [IN] size of video stream filled in STRM_BUF */
+ int in_packed_PB; /* [IN] Is packed PB frame or not, 1: packedPB 0: unpacked */
+
+ int out_img_width; /* [OUT] width of YUV420 frame */
+ int out_img_height; /* [OUT] height of YUV420 frame */
+ int out_buf_width; /* [OUT] width of YUV420 frame */
+ int out_buf_height; /* [OUT] height of YUV420 frame */
+ int out_dpb_cnt; /* [OUT] the number of buffers which is nessary during decoding */
+
+ int out_crop_top_offset; /* [OUT] crop information, top offset */
+ int out_crop_bottom_offset; /* [OUT] crop information, bottom offset */
+ int out_crop_left_offset; /* [OUT] crop information, left offset */
+ int out_crop_right_offset; /* [OUT] crop information, right offset */
+
+ struct mfc_frame_buf_arg in_frm_buf; /* [IN] the address of dpb FRAME_BUF */
+ struct mfc_frame_buf_arg in_frm_size; /* [IN] size of dpb FRAME_BUF */
+ unsigned int in_mapped_addr;
+
+ struct mfc_frame_buf_arg out_u_addr;
+ struct mfc_frame_buf_arg out_p_addr;
+ struct mfc_frame_buf_arg out_frame_buf_size;
+};
+
+struct mfc_dec_exe_arg {
+ enum ssbsip_mfc_codec_type in_codec_type; /* [IN] codec type */
+ unsigned int in_strm_buf; /* [IN] the physical address of STRM_BUF */
+ int in_strm_size; /* [IN] Size of video stream filled in STRM_BUF */
+ struct mfc_frame_buf_arg in_frm_buf; /* [IN] the address of dpb FRAME_BUF */
+ struct mfc_frame_buf_arg in_frm_size; /* [IN] size of dpb FRAME_BUF */
+ int in_frametag; /* [IN] unique frame ID */
+
+ unsigned int out_display_Y_addr; /* [OUT] the physical address of display buf */
+ unsigned int out_display_C_addr; /* [OUT] the physical address of display buf */
+ int out_display_status; /* [OUT] whether display frame exist or not. */
+ int out_timestamp_top; /* [OUT] presentation time of an output frame or top field */
+ int out_timestamp_bottom; /* [OUT] presentation time of bottom field */
+ int out_consume_bytes; /* [OUT] consumed bytes when decoding finished */
+ int out_frametag_top; /* [OUT] unique frame ID of an output frame or top field */
+ int out_frametag_bottom; /* [OUT] unique frame ID of bottom field */
+ int out_res_change; /* [OUT] whether resolution is changed or not (0, 1, 2) */
+ int out_crop_top_offset; /* [OUT] crop information, top offset */
+ int out_crop_bottom_offset; /* [OUT] crop information, bottom offset */
+ int out_crop_left_offset; /* [OUT] crop information, left offset */
+ int out_crop_right_offset; /* [OUT] crop information, right offset */
+};
+
+struct mfc_get_config_arg {
+ int in_config_param; /* [IN] Configurable parameter type */
+ int out_config_value[4]; /* [IN] Values to get for the configurable parameter. */
+};
+
+struct mfc_set_config_arg {
+ int in_config_param; /* [IN] Configurable parameter type */
+ int in_config_value[2]; /* [IN] Values to be set for the configurable parameter. */
+ int out_config_value_old[2]; /* [OUT] Old values of the configurable parameters */
+};
+
+struct mfc_get_phys_addr_arg {
+ unsigned int u_addr;
+ unsigned int p_addr;
+};
+
+struct mfc_mem_alloc_arg {
+ enum ssbsip_mfc_codec_type codec_type;
+ int buff_size;
+ unsigned int mapped_addr;
+ unsigned int out_uaddr;
+ unsigned int out_paddr;
+};
+
+struct mfc_mem_free_arg {
+ unsigned int u_addr;
+};
+
+enum mfc_buffer_type {
+ MFC_BUFFER_NO_CACHE = 0,
+ MFC_BUFFER_CACHE = 1
+};
+
+union mfc_args {
+ struct mfc_enc_init_mpeg4_arg enc_init_mpeg4;
+ struct mfc_enc_init_mpeg4_arg enc_init_h263;
+ struct mfc_enc_init_h264_arg enc_init_h264;
+ struct mfc_enc_exe_arg enc_exe;
+
+ struct mfc_dec_init_arg dec_init;
+ struct mfc_dec_exe_arg dec_exe;
+
+ struct mfc_get_config_arg get_config;
+ struct mfc_set_config_arg set_config;
+
+ struct mfc_mem_alloc_arg mem_alloc;
+ struct mfc_mem_free_arg mem_free;
+ struct mfc_get_phys_addr_arg get_phys_addr;
+
+ enum mfc_buffer_type buf_type;
+};
+
+struct mfc_common_args {
+ enum mfc_error_code ret_code; /* [OUT] error code */
+ union mfc_args args;
+};
+
+#endif /* _MFC_INTERFACE_H_ */
diff --git a/drivers/media/video/samsung/mfc50/mfc_intr.c b/drivers/media/video/samsung/mfc50/mfc_intr.c
new file mode 100644
index 0000000..035d460
--- /dev/null
+++ b/drivers/media/video/samsung/mfc50/mfc_intr.c
@@ -0,0 +1,202 @@
+/*
+ * drivers/media/video/samsung/mfc50/mfc_intr.c
+ *
+ * C file for Samsung MFC (Multi Function Codec - FIMV) driver
+ *
+ * Jaeryul Oh, Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * Change Logs
+ * 2009.09.14 - Beautify source code (Key Young, Park)
+ * 2009.09.21 - Implement clock & power gating.
+ * including suspend & resume fuction. (Key Young, Park)
+ * 2009.10.09 - Add error handling rountine (Key Young, Park)
+ * 2009.10.13 - Change wait_for_done (Key Young, Park)
+ * 2009.11.04 - remove mfc_common.[ch]
+ * seperate buffer alloc & set (Key Young, Park)
+ *
+ * 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/delay.h>
+#include <linux/errno.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/io.h>
+
+#include <plat/regs-mfc.h>
+
+#include "mfc_logmsg.h"
+#include "mfc_opr.h"
+#include "mfc_memory.h"
+#include "mfc_intr.h"
+
+
+#define MFC_WAIT_1_TIME 100
+#define MFC_WAIT_2_TIME 200
+#define MFC_WAIT_3_TIME 400
+#define MFC_WAIT_4_TIME 600
+#define MFC_WAIT_5_TIME 800
+#define MFC_WAIT_6_TIME 1000
+
+#define ENABLE_MFC_INTERRUPT_DEBUG 0 /* 0: Disable 1: Enable */
+
+#if defined(MFC_REQUEST_TIME)
+struct timeval mfc_wakeup_before;
+struct timeval mfc_wakeup_after;
+#endif
+
+static unsigned int mfc_int_type;
+static unsigned int mfc_disp_err_status;
+static unsigned int mfc_dec_err_status;
+static bool irq_sync;
+static DECLARE_WAIT_QUEUE_HEAD(mfc_wait_queue);
+static DEFINE_SPINLOCK(mfc_irq_lock);
+
+#if !defined(MFC_POLLING)
+irqreturn_t mfc_irq(int irq, void *dev_id)
+{
+ unsigned int int_reason;
+ unsigned int err_status;
+
+ int_reason = READL(MFC_RISC2HOST_COMMAND) & 0x1FFFF;
+ err_status = READL(MFC_RISC2HOST_ARG2);
+
+ mfc_disp_err_status = err_status >> 16;
+ mfc_dec_err_status = err_status & 0xFFFF;
+
+ mfc_debug_L0("mfc_irq() : Interrupt !! : %d\n", int_reason);
+
+ if (((int_reason & R2H_CMD_FRAME_DONE_RET) == R2H_CMD_FRAME_DONE_RET) ||
+ ((int_reason & R2H_CMD_SEQ_DONE_RET) == R2H_CMD_SEQ_DONE_RET) ||
+ ((int_reason & R2H_CMD_SYS_INIT_RET) == R2H_CMD_SYS_INIT_RET) ||
+ ((int_reason & R2H_CMD_OPEN_INSTANCE_RET) == R2H_CMD_OPEN_INSTANCE_RET) ||
+ ((int_reason & R2H_CMD_CLOSE_INSTANCE_RET) == R2H_CMD_CLOSE_INSTANCE_RET) ||
+ ((int_reason & R2H_CMD_INIT_BUFFERS_RET) == R2H_CMD_INIT_BUFFERS_RET) ||
+ ((int_reason & R2H_CMD_DECODE_ERR_RET) == R2H_CMD_DECODE_ERR_RET) ||
+ ((int_reason & R2H_CMD_SLICE_DONE_RET) == R2H_CMD_SLICE_DONE_RET) ||
+ ((int_reason & R2H_CMD_ERROR_RET) == R2H_CMD_ERROR_RET)) {
+ mfc_int_type = int_reason;
+ irq_sync = true;
+ wake_up(&mfc_wait_queue);
+ } else {
+ irq_sync = false;
+ mfc_info("Strange Interrupt !! : %d\n", int_reason);
+ }
+
+
+ WRITEL(0, MFC_RISC_HOST_INT);
+ WRITEL(0, MFC_RISC2HOST_COMMAND);
+ WRITEL(0xffff, MFC_SI_RTN_CHID);
+
+ return IRQ_HANDLED;
+}
+#endif
+
+void mfc_interrupt_debug(int nCnt)
+{
+ int nn = 0;
+ for (nn = 0; nn < nCnt; nn++) {
+ mdelay(100);
+ mfc_err("[%d] Timeout (0x64: 0x%08x) (0xF4: 0x%08x)\n", nn, READL(0x64), READL(0xF4));
+ }
+}
+
+int mfc_wait_for_done(enum mfc_wait_done_type command)
+{
+ unsigned int nwait_time = 100;
+ unsigned int ret_val = 1;
+ unsigned long flags;
+
+ if ((command == R2H_CMD_CLOSE_INSTANCE_RET) ||
+ (command == R2H_CMD_OPEN_INSTANCE_RET) ||
+ (command == R2H_CMD_SYS_INIT_RET) ||
+ (command == R2H_CMD_FW_STATUS_RET))
+ nwait_time = MFC_WAIT_6_TIME;
+ else
+ nwait_time = MFC_WAIT_2_TIME;
+
+
+#if defined(MFC_REQUEST_TIME)
+ long sec, msec;
+#endif
+
+#if defined(MFC_POLLING)
+ unsigned long timeo = jiffies;
+ timeo += 20; /* waiting for 100ms */
+#endif
+
+#if defined(MFC_REQUEST_TIME)
+ do_gettimeofday(&mfc_wakeup_before);
+ if (mfc_wakeup_before.tv_usec - mfc_wakeup_after.tv_usec < 0) {
+ msec = 1000000 + mfc_wakeup_before.tv_usec - mfc_wakeup_after.tv_usec;
+ sec = mfc_wakeup_before.tv_sec - mfc_wakeup_after.tv_sec - 1;
+ } else {
+ msec = mfc_wakeup_before.tv_usec - mfc_wakeup_after.tv_usec;
+ sec = mfc_wakeup_before.tv_sec - mfc_wakeup_after.tv_sec;
+ }
+#endif
+
+#if defined(MFC_POLLING)
+ while (time_before(jiffies, timeo))
+ ret_val = READL(MFC_RISC2HOST_COMMAND) & 0x1ffff;
+ if (ret_val != 0) {
+ WRITEL(0, MFC_RISC_HOST_INT);
+ WRITEL(0, MFC_RISC2HOST_COMMAND);
+ WRITEL(0xffff, MFC_SI_RTN_CHID);
+ mfc_int_type = ret_val;
+ break;
+ }
+ msleep_interruptible(2);
+ }
+
+ if (ret_val == 0)
+ printk(KERN_INFO "MFC timeouted!\n");
+#else
+ if (wait_event_timeout(mfc_wait_queue, irq_sync, nwait_time) == 0) {
+ ret_val = 0;
+ mfc_err("Interrupt Time Out(Cmd: %d) (Ver: 0x%08x) (0x64: 0x%08x) (0xF4: 0x%08x) (0x80: 0x%08x)\n", command, READL(0x58), READL(0x64), READL(0xF4), READL(0x80));
+
+#if ENABLE_MFC_INTERRUPT_DEBUG /* For MFC Interrupt Debugging. */
+ mfc_interrupt_debug(10);
+#endif
+
+ mfc_int_type = 0;
+ return ret_val;
+ } else if (mfc_int_type == R2H_CMD_DECODE_ERR_RET) {
+ mfc_err("Decode Error Returned Disp Error Status(%d), Dec Error Status(%d)\n", mfc_disp_err_status, mfc_dec_err_status);
+ } else if (command != mfc_int_type) {
+ mfc_err("Interrupt Error Returned (%d) waiting for (%d)\n", mfc_int_type, command);
+ }
+#endif
+ spin_lock_irqsave(&mfc_irq_lock, flags);
+ irq_sync = false;
+ spin_unlock_irqrestore(&mfc_irq_lock, flags);
+
+#if defined(MFC_REQUEST_TIME)
+ do_gettimeofday(&mfc_wakeup_after);
+ if (mfc_wakeup_after.tv_usec - mfc_wakeup_before.tv_usec < 0) {
+ msec = 1000000 + mfc_wakeup_after.tv_usec - mfc_wakeup_before.tv_usec;
+ sec = mfc_wakeup_after.tv_sec - mfc_wakeup_before.tv_sec - 1;
+ } else {
+ msec = mfc_wakeup_after.tv_usec - mfc_wakeup_before.tv_usec;
+ sec = mfc_wakeup_after.tv_sec - mfc_wakeup_before.tv_sec;
+ }
+
+ mfc_info("mfc_wait_for_done: mfc request interval time is %ld(sec), %ld(msec)\n", sec, msec);
+#endif
+
+ ret_val = mfc_int_type;
+ mfc_int_type = 0;
+
+ return ret_val;
+}
+
+
+int mfc_return_code(void)
+{
+ return mfc_dec_err_status;
+}
diff --git a/drivers/media/video/samsung/mfc50/mfc_intr.h b/drivers/media/video/samsung/mfc50/mfc_intr.h
new file mode 100644
index 0000000..ed156b9
--- /dev/null
+++ b/drivers/media/video/samsung/mfc50/mfc_intr.h
@@ -0,0 +1,25 @@
+/*
+ * drivers/media/video/samsung/mfc50/mfc_intr.h
+ *
+ * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
+ *
+ * Key-Young Park, Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * Change Logs
+ * 2009.10.13 - Separate from mfc_common.h(Key Young, Park)
+ *
+ * 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 _MFC_INTR_H_
+#define _MFC_INTR_H_
+
+#include <linux/interrupt.h>
+
+irqreturn_t mfc_irq(int irq, void *dev_id);
+int mfc_wait_for_done(enum mfc_wait_done_type command);
+int mfc_return_code(void);
+#endif
diff --git a/drivers/media/video/samsung/mfc50/mfc_logmsg.h b/drivers/media/video/samsung/mfc50/mfc_logmsg.h
new file mode 100644
index 0000000..881d733
--- /dev/null
+++ b/drivers/media/video/samsung/mfc50/mfc_logmsg.h
@@ -0,0 +1,72 @@
+/*
+ * drivers/media/video/samsung/mfc50/mfc_logmsg.h
+ *
+ * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
+ *
+ * Jaeryul Oh, Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * Change Logs
+ * 2009.09.14 - Beautify source code (Key Young, Park)
+ *
+ * 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 _MFC_LOGMSG_H_
+#define _MFC_LOGMSG_H_
+
+/* debug macros */
+#define MFC_DEBUG(fmt, ...) \
+ do { \
+ printk(KERN_DEBUG \
+ "%s: " fmt, __func__, ##__VA_ARGS__); \
+ } while (0)
+
+#define MFC_ERROR(fmt, ...) \
+ do { \
+ printk(KERN_ERR \
+ "%s: " fmt, __func__, ##__VA_ARGS__); \
+ } while (0)
+
+#define MFC_NOTICE(fmt, ...) \
+ do { \
+ printk(KERN_NOTICE \
+ "%s: " fmt, __func__, ##__VA_ARGS__); \
+ } while (0)
+
+#define MFC_INFO(fmt, ...) \
+ do { \
+ printk(KERN_INFO \
+ "%s: " fmt, __func__, ##__VA_ARGS__); \
+ } while (0)
+
+#define MFC_WARN(fmt, ...) \
+ do { \
+ printk(KERN_WARNING \
+ "%s: " fmt, __func__, ##__VA_ARGS__); \
+ } while (0)
+
+
+#ifdef CONFIG_VIDEO_MFC50_DEBUG
+#define mfc_debug(fmt, ...) MFC_INFO(fmt, ##__VA_ARGS__)
+#define mfc_debug_L0(fmt, ...) MFC_INFO(fmt, ##__VA_ARGS__)
+#else
+#define mfc_debug(fmt, ...)
+#define mfc_debug_L0(fmt, ...)
+#endif
+
+#if defined(DEBUG_LEVEL_0)
+#define mfc_debug_L0(fmt, ...) MFC_INFO(fmt, ##__VA_ARGS__)
+#define mfc_debug(fmt, ...) MFC_INFO(fmt, ##__VA_ARGS__)
+#elseif define(DEBUG_LEVEL_1)
+#define mfc_debug(fmt, ...) MFC_INFO(fmt, ##__VA_ARGS__)
+#endif
+
+#define mfc_err(fmt, ...) MFC_ERROR(fmt, ##__VA_ARGS__)
+#define mfc_notice(fmt, ...) MFC_NOTICE(fmt, ##__VA_ARGS__)
+#define mfc_info(fmt, ...) MFC_INFO(fmt, ##__VA_ARGS__)
+#define mfc_warn(fmt, ...) MFC_WARN(fmt, ##__VA_ARGS__)
+
+#endif /* _MFC_LOGMSG_H_ */
diff --git a/drivers/media/video/samsung/mfc50/mfc_memory.c b/drivers/media/video/samsung/mfc50/mfc_memory.c
new file mode 100644
index 0000000..a33dd9f
--- /dev/null
+++ b/drivers/media/video/samsung/mfc50/mfc_memory.c
@@ -0,0 +1,70 @@
+/*
+ * drivers/media/video/samsung/mfc50/mfc_memory.c
+ *
+ * C file for Samsung MFC (Multi Function Codec - FIMV) driver
+ *
+ * Jaeryul Oh, Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * Change Logs
+ * 2009.09.14 - Beautify source code (Key Young, Park)
+ *
+ * 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/mm.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <mach/map.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <asm/sizes.h>
+#include <linux/memory.h>
+#include <plat/media.h>
+
+#include "mfc_memory.h"
+#include "mfc_logmsg.h"
+#include "mfc_interface.h"
+
+void __iomem *mfc_sfr_base_vaddr;
+unsigned int mfc_port0_base_paddr, mfc_port1_base_paddr;
+unsigned char *mfc_port0_base_vaddr, *mfc_port1_base_vaddr;
+unsigned int mfc_port0_memsize, mfc_port1_memsize;
+unsigned int mfc_port1_alloc_base;
+
+unsigned int mfc_get_fw_buff_paddr(void)
+{
+ return mfc_port0_base_paddr;
+}
+
+unsigned char *mfc_get_fw_buff_vaddr(void)
+{
+ return mfc_port0_base_vaddr;
+}
+
+unsigned int mfc_get_port0_buff_paddr(void)
+{
+ return mfc_port0_base_paddr + MFC_FW_MAX_SIZE;
+}
+
+unsigned char *mfc_get_port0_buff_vaddr(void)
+{
+ return mfc_port0_base_vaddr + MFC_FW_MAX_SIZE;
+}
+
+unsigned char *mfc_get_port1_buff_vaddr(void)
+{
+ return mfc_port1_base_vaddr;
+}
+
+unsigned int mfc_get_port1_buff_paddr(void)
+{
+ return mfc_port1_alloc_base;
+}
+
+void mfc_set_port1_buff_paddr(unsigned int addr)
+{
+ mfc_port1_alloc_base = addr;
+}
diff --git a/drivers/media/video/samsung/mfc50/mfc_memory.h b/drivers/media/video/samsung/mfc50/mfc_memory.h
new file mode 100644
index 0000000..0d17a09
--- /dev/null
+++ b/drivers/media/video/samsung/mfc50/mfc_memory.h
@@ -0,0 +1,111 @@
+/*
+ * drivers/media/video/samsung/mfc50/mfc_memory.h
+ *
+ * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
+ *
+ * Jaeryul Oh, Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * Change Logs
+ * 2009.09.14 - Beautify source code (Key Young, Park)
+ * 2009.10.08 - Apply 9/30 firmware(Key Young, Park)
+ * 2009.11.04 - remove mfc_common.[ch]
+ * seperate buffer alloc & set (Key Young, Park)
+ *
+ * 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 _MFC_MEMORY_H_
+#define _MFC_MEMORY_H_
+
+#include "mfc_opr.h"
+
+#ifdef CONFIG_VIDEO_MFC_MAX_INSTANCE
+#define MFC_MAX_INSTANCE_NUM (CONFIG_VIDEO_MFC_MAX_INSTANCE)
+#endif
+
+#define SET_MEM_1080P 1
+#define SET_MEM_720P 0
+
+#if SET_MEM_1080P
+/*
+ * Memory Configuration for 1080P
+ * MFC_FW_TOTAL_BUF_SIZE should be aligned to 4KB (page size)
+ */
+#define MFC_FW_TOTAL_BUF_SIZE (ALIGN_TO_4KB(MFC_FW_MAX_SIZE + MFC_MAX_INSTANCE_NUM * MFC_FW_BUF_SIZE))
+#define MFC_FW_MAX_SIZE (512 * 1024) /* 512KB : 512x1024 */
+#define MFC_FW_BUF_SIZE (512 * 1024) /* 512KB : 512x1024 size per instance */
+
+#define RISC_BUF_SIZE (0x80000) /* 512KB : 512x1024 size per instance */
+#define CPB_BUF_SIZE (0x300000) /* 3MB : 3x1024x1024 for decoder */
+#define DESC_BUF_SIZE (0x20000) /* 128KB : 128x1024 */
+#define SHARED_BUF_SIZE (0x10000) /* 64KB : 64x1024 */
+#define PRED_BUF_SIZE (0x10000) /* 64KB : 64x1024 */
+#define DEC_CODEC_BUF_SIZE (0x80000) /* 512KB : 512x1024 size per instance */
+#define ENC_CODEC_BUF_SIZE (0x50000) /* 320KB : 512x1024 size per instance */
+
+#define STREAM_BUF_SIZE (0x300000) /* 3MB : 3x1024x1024 for encoder */
+#define MV_BUF_SIZE (0x10000) /* 64KB : 64x1024 for encoder */
+
+#define H264DEC_CONTEXT_SIZE (640 * 1024) /* 600KB -> 640KB for alignment */
+#define VC1DEC_CONTEXT_SIZE (64 * 1024) /* 10KB -> 64KB for alignment */
+#define MPEG2DEC_CONTEXT_SIZE (64 * 1024) /* 10KB -> 64KB for alignment */
+#define H263DEC_CONTEXT_SIZE (64 * 1024) /* 10KB -> 64KB for alignment */
+#define MPEG4DEC_CONTEXT_SIZE (64 * 1024) /* 10KB -> 64KB for alignment */
+#define H264ENC_CONTEXT_SIZE (640 * 1024) /* 64KB -> 640KB for alignment */
+#define MPEG4ENC_CONTEXT_SIZE (64 * 1024) /* 10KB -> 64KB for alignment */
+#define H263ENC_CONTEXT_SIZE (64 * 1024) /* 10KB -> 64KB for alignment */
+
+#else
+/* Memory Configuration for 720P */
+#define MFC_FW_TOTAL_BUF_SIZE (ALIGN_TO_4KB(MFC_FW_MAX_SIZE + MFC_MAX_INSTANCE_NUM * MFC_FW_BUF_SIZE))
+#define MFC_FW_MAX_SIZE (2 * 1024 * 1024) /* 2MB : 2x1024x1024 */
+#define MFC_FW_BUF_SIZE (512 * 1024) /* 512KB : 512x1024 size per instance */
+
+#define RISC_BUF_SIZE (0x80000) /* 512KB : 512x1024 size per instance */
+#define CPB_BUF_SIZE (0x300000) /* 3MB : 3x1024x1024 for decoder */
+#define DESC_BUF_SIZE (0x20000) /* 128KB : 128x1024 */
+#define SHARED_BUF_SIZE (0x10000) /* 64KB : 64x1024 */
+#define PRED_BUF_SIZE (0x10000) /* 64KB : 64x1024 */
+#define DEC_CODEC_BUF_SIZE (0x80000) /* 512KB : 512x1024 size per instance */
+#define ENC_CODEC_BUF_SIZE (0x50000) /* 320KB : 512x1024 size per instance */
+
+#define STREAM_BUF_SIZE (0x200000) /* 2MB : 2x1024x1024 for encoder */
+#define MV_BUF_SIZE (0x10000) /* 64KB : 64x1024 for encoder */
+
+#define H264DEC_CONTEXT_SIZE (640 * 1024) /* 600KB -> 640KB for alignment */
+#define VC1DEC_CONTEXT_SIZE (64 * 1024) /* 10KB -> 64KB for alignment */
+#define MPEG2DEC_CONTEXT_SIZE (64 * 1024) /* 10KB -> 64KB for alignment */
+#define H263DEC_CONTEXT_SIZE (64 * 1024) /* 10KB -> 64KB for alignment */
+#define MPEG4DEC_CONTEXT_SIZE (64 * 1024) /* 10KB -> 64KB for alignment */
+#define H264ENC_CONTEXT_SIZE (64 * 1024) /* 10KB -> 64KB for alignment */
+#define MPEG4ENC_CONTEXT_SIZE (64 * 1024) /* 10KB -> 64KB for alignment */
+#define H263ENC_CONTEXT_SIZE (64 * 1024) /* 10KB -> 64KB for alignment */
+
+#endif
+
+unsigned int mfc_get_fw_buf_phys_addr(void);
+unsigned int mfc_get_risc_buf_phys_addr(int instNo);
+
+extern unsigned char *mfc_port0_base_vaddr; /* port1 */
+extern unsigned char *mfc_port1_base_vaddr; /* port0 */
+extern unsigned int mfc_port0_base_paddr, mfc_port1_base_paddr;
+extern unsigned int mfc_port0_memsize, mfc_port1_memsize;
+
+unsigned int mfc_get_fw_buff_paddr(void);
+unsigned char *mfc_get_fw_buff_vaddr(void);
+unsigned int mfc_get_port0_buff_paddr(void);
+unsigned char *mfc_get_port0_buff_vaddr(void);
+unsigned int mfc_get_port1_buff_paddr(void);
+unsigned char *mfc_get_port1_buff_vaddr(void);
+void mfc_set_port1_buff_paddr(unsigned int addr);
+
+extern void __iomem *mfc_sfr_base_vaddr;
+
+#define READL(offset) readl(mfc_sfr_base_vaddr + (offset))
+#define WRITEL(data, offset) writel((data), mfc_sfr_base_vaddr + (offset))
+
+#endif /* _MFC_MEMORY_H_ */
diff --git a/drivers/media/video/samsung/mfc50/mfc_opr.c b/drivers/media/video/samsung/mfc50/mfc_opr.c
new file mode 100644
index 0000000..39ca126
--- /dev/null
+++ b/drivers/media/video/samsung/mfc50/mfc_opr.c
@@ -0,0 +1,2576 @@
+/*
+ * drivers/media/video/samsung/mfc50/mfc_opr.c
+ *
+ * C file for Samsung MFC (Multi Function Codec - FIMV) driver
+ *
+ * Jaeryul Oh, Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * Change Logs
+ * 2009.09.14 - Beautify source code. (Key Young, Park)
+ * 2009.09.21 - Implement clock & power gating.
+ * including suspend & resume fuction. (Key Young, Park)
+ * 2009.09.23 - Use TILE mode encoding / Move MFC reserved memory
+ * before FIMC reserved memory. (Key Young, Park)
+ * 2009.09.24 - Minor patch. (Key Young, Park)
+ * 2009.10.08 - Apply 9/30 firmware(Key Young, Park)
+ * 2009.10.13 - Change wait_for_done (Key Young, Park)
+ * 2009.10.17 - Add error handling routine for buffer allocation (Key Young, Park)
+ * 2009.10.22 - Change codec name VC1AP_DEC -> VC1_DEC (Key Young, Park)
+ * 2009.10.27 - Update firmware (2009.10.15) (Key Young, Park)
+ * 2009.11.04 - get physical address via mfc_allocate_buffer (Key Young, Park)
+ * 2009.11.04 - remove mfc_common.[ch]
+ * seperate buffer alloc & set (Key Young, Park)
+ * 2009.11.06 - Apply common MFC API (Key Young, Park)
+ * 2009.11.06 - memset shared_memory (Key Young, Park)
+ * 2009.11.09 - implement packed PB (Key Young, Park)
+ *
+ * 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/delay.h>
+#include <linux/mm.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/dma-mapping.h>
+#include <plat/regs-mfc.h>
+#include <asm/cacheflush.h>
+#include <mach/map.h>
+#include <plat/map-s5p.h>
+
+#include "mfc_opr.h"
+#include "mfc_logmsg.h"
+#include "mfc_memory.h"
+#include "mfc_buffer_manager.h"
+#include "mfc_interface.h"
+#include "mfc_shared_mem.h"
+#include "mfc_intr.h"
+
+
+/* DEBUG_MAKE_RAW is option to dump input stream data of MFC.*/
+#define DEBUG_MAKE_RAW 0 /* Making Dec/Enc Debugging Files */
+#define ENABLE_DEBUG_MFC_INIT 0
+#define ENABLE_MFC_REGISTER_DEBUG 0 /* 0: Disable 1: Enable */
+#define ENABLE_ENC_MB 1
+
+#define ENABLE_CHECK_START_CODE 1
+#define ENABLE_CHECK_NULL_STREAM 1
+#define ENABLE_CHECK_STREAM_SIZE 1
+#define ENABLE_CHECK_SEQ_HEADER 0
+
+#if DEBUG_MAKE_RAW
+#define ENABLE_DEBUG_DEC_EXE_INTR_ERR 1 /* You must make the "dec_in" folder in data folder.*/
+#define ENABLE_DEBUG_DEC_EXE_INTR_OK 1 /* Make log about Normal Interrupts.*/
+#define ENABLE_DEBUG_ENC_EXE_INTR_ERR 1 /* You must make the "enc_in" folder in data folder.*/
+#endif
+
+#ifdef ENABLE_DEBUG_DEC_EXE_INTR_ERR
+#if ENABLE_DEBUG_DEC_EXE_INTR_ERR
+#define ENABLE_DEBUG_DEC_EXE_PARSER_ERR 1 /* Firstly, Set ENABLE_DEBUG_DEC_EXE_INTR_ERR is "1". */
+#endif
+#endif
+
+#define WRITEL_SHARED_MEM(data, address) \
+ do { \
+ writel(data, address); \
+ dmac_flush_range((void *)address, (void *)(address + 4)); \
+ } while (0)
+
+#if DEBUG_MAKE_RAW
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/fcntl.h>
+#include <linux/uaccess.h>
+#endif
+
+
+static void mfc_backup_context(struct mfc_inst_ctx *mfc_ctx);
+static void mfc_restore_context(struct mfc_inst_ctx *mfc_ctx);
+static void mfc_set_encode_init_param(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args);
+static int mfc_get_inst_no(struct mfc_inst_ctx *mfc_ctx, unsigned int context_addr, int context_size);
+static enum mfc_error_code mfc_encode_header(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args);
+static enum mfc_error_code mfc_decode_one_frame(struct mfc_inst_ctx *mfc_ctx, struct mfc_dec_exe_arg *dec_arg, unsigned int *consumed_strm_size);
+
+static void mfc_set_codec_buffer(struct mfc_inst_ctx *mfc_ctx);
+static void mfc_set_dec_frame_buffer(struct mfc_inst_ctx *mfc_ctx);
+static void mfc_set_dec_stream_buffer(struct mfc_inst_ctx *mfc_ctx, int buf_addr, unsigned int buf_size);
+static void mfc_set_enc_ref_buffer(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args);
+
+static enum mfc_error_code mfc_alloc_codec_buffer(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args);
+static enum mfc_error_code mfc_alloc_dec_frame_buffer(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args);
+static enum mfc_error_code mfc_alloc_context_buffer(struct mfc_inst_ctx *mfc_ctx, unsigned int mapped_addr, unsigned int *context_addr, int *size);
+static enum mfc_error_code mfc_alloc_stream_ref_buffer(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args);
+
+static int CheckMPEG4StartCode(unsigned char *src_mem, unsigned int remainSize);
+static int CheckDecStartCode(unsigned char *src_mem, unsigned int nstreamSize, enum ssbsip_mfc_codec_type nCodecType);
+static int CheckNullStream(unsigned char *src_mem, unsigned int streamSize);
+
+static int mfc_mem_inst_no[MFC_MAX_INSTANCE_NUM];
+static bool mCheckType;
+
+
+/*
+ * Debugging Functions Definition
+ * tile_to_linear_4x2(..)
+ * calculate_seq_size(..)
+ * printk_mfc_init_info(..)
+ */
+#if DEBUG_MAKE_RAW
+static int mframe_cnt;
+static int mImgWidth;
+static int mImgHight;
+
+static void copy16(unsigned char *p_linear_addr, unsigned char *p_tiled_addr, int mm, int nn);
+static void write_file(char *filename, unsigned char *data, unsigned int nSize);
+static int tile_4x2_read(int x_size, int y_size, int x_pos, int y_pos);
+static void tile_to_linear_4x2(unsigned char *p_linear_addr, unsigned char *p_tiled_addr, unsigned int x_size, unsigned int y_size);
+#endif
+
+#if ENABLE_CHECK_SEQ_HEADER
+static int calculate_seq_size(mfc_args *args);
+#endif
+
+#if ENABLE_DEBUG_MFC_INIT
+void printk_mfc_init_info(struct mfc_inst_ctx *mfc_ctx, struct mfc_args *args);
+#endif
+
+#ifdef ENABLE_DEBUG_DEC_EXE_INTR_ERR
+#if ENABLE_DEBUG_DEC_EXE_INTR_ERR
+void printk_mfc_dec_exe_info(struct mfc_inst_ctx *mfc_ctx, struct mfc_dec_exe_arg *dec_arg);
+void makefile_mfc_dec_err_info(struct mfc_inst_ctx *mfc_ctx, struct mfc_dec_exe_arg *dec_arg, int nReturnErrCode);
+void makefile_mfc_decinit_err_info(struct mfc_inst_ctx *mfc_ctx, struct mfc_dec_init_arg *decinit_arg, int nReturnErrCode);
+
+static unsigned int mcontext_addr;
+static int mcontext_size;
+static int mIsDangerError;
+#endif
+#endif
+
+#ifdef ENABLE_DEBUG_DEC_EXE_INTR_ERR
+#if ENABLE_DEBUG_ENC_EXE_INTR_ERR
+void makefile_mfc_enc_err_info(struct mfc_enc_exe_arg *enc_arg);
+#endif
+#endif
+
+#if ENABLE_MFC_REGISTER_DEBUG
+void mfc_fw_debug(mfc_wait_done_type command);
+#endif
+
+#ifdef ENABLE_DEBUG_DEC_EXE_INTR_ERR
+#if ENABLE_DEBUG_ENC_EXE_INTR_ERR
+static unsigned char pResLinearbuf[1280*720*3/2];
+#endif
+#endif
+
+#define MC_STATUS_TIMEOUT 1000 /* ms */
+
+bool mfc_cmd_reset(void)
+{
+ unsigned int mc_status;
+ unsigned long timeo = jiffies;
+
+ timeo += msecs_to_jiffies(MC_STATUS_TIMEOUT);
+
+ /* Stop procedure */
+ WRITEL(0x3f6, MFC_SW_RESET); /* reset RISC */
+ WRITEL(0x3e2, MFC_SW_RESET); /* All reset except for MC */
+ mdelay(10);
+
+ /* Check MC status */
+ do {
+ mc_status = (READL(MFC_MC_STATUS) & 0x3);
+
+ if (mc_status == 0)
+ break;
+
+ schedule_timeout_uninterruptible(1);
+ } while (time_before(jiffies, timeo));
+
+ if (mc_status != 0)
+ return false;
+
+ WRITEL(0x0, MFC_SW_RESET);
+ WRITEL(0x3fe, MFC_SW_RESET);
+
+ return true;
+}
+
+static bool mfc_cmd_host2risc(enum mfc_facade_cmd cmd, int arg1, int arg2, int arg3, int arg4)
+{
+ enum mfc_facade_cmd cur_cmd = 0;
+ unsigned long timeo = jiffies;
+ timeo += 20; /* waiting for 100ms */
+
+ /* wait until host to risc command register becomes 'H2R_CMD_EMPTY' */
+ while (time_before(jiffies, timeo)) {
+ cur_cmd = READL(MFC_HOST2RISC_COMMAND);
+ if (cur_cmd == H2R_CMD_EMPTY)
+ break;
+ msleep_interruptible(2);
+ }
+
+ if (cur_cmd != H2R_CMD_EMPTY)
+ return false;
+
+ WRITEL(arg1, MFC_HOST2RISC_ARG1);
+ WRITEL(arg2, MFC_HOST2RISC_ARG2);
+ WRITEL(arg3, MFC_HOST2RISC_ARG3);
+ WRITEL(arg4, MFC_HOST2RISC_ARG4);
+ WRITEL(cmd, MFC_HOST2RISC_COMMAND);
+
+ return true;
+}
+
+static void mfc_backup_context(struct mfc_inst_ctx *mfc_ctx)
+{
+}
+
+static void mfc_restore_context(struct mfc_inst_ctx *mfc_ctx)
+{
+}
+
+static void mfc_set_dec_stream_buffer(struct mfc_inst_ctx *mfc_ctx, int buf_addr, unsigned int buf_size)
+{
+ unsigned int port0_base_paddr;
+
+ mfc_debug_L0("inst_no : %d, buf_addr : 0x%08x, buf_size : 0x%08x\n", mfc_ctx->InstNo, buf_addr, buf_size);
+ if (mfc_ctx->buf_type == MFC_BUFFER_CACHE) {
+ unsigned char *in_vir;
+ in_vir = phys_to_virt(buf_addr);
+ dma_map_single(NULL, in_vir, buf_size, DMA_TO_DEVICE);
+ }
+ port0_base_paddr = mfc_port0_base_paddr;
+
+ /* release buffer */
+ WRITEL(0xffffffff, MFC_SI_CH0_RELEASE_BUFFER);
+
+ /* Set stream & desc buffer */
+ WRITEL((buf_addr - port0_base_paddr) >> 11, MFC_SI_CH0_ES_ADDR);
+ WRITEL(buf_size, MFC_SI_CH0_ES_DEC_UNIT_SIZE);
+ WRITEL(CPB_BUF_SIZE, MFC_SI_CH0_CPB_SIZE);
+ WRITEL((mfc_ctx->desc_buff_paddr - port0_base_paddr) >> 11, MFC_SI_CH0_DESC_ADDR);
+ WRITEL(DESC_BUF_SIZE, MFC_SI_CH0_DESC_SIZE);
+
+ mfc_debug_L0("stream_paddr: 0x%08x, desc_paddr: 0x%08x\n", buf_addr, buf_addr + CPB_BUF_SIZE);
+}
+
+static enum mfc_error_code mfc_alloc_dec_frame_buffer(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args)
+{
+ struct mfc_dec_init_arg *init_arg;
+ enum mfc_error_code ret_code;
+ union mfc_args local_param;
+ struct mfc_frame_buf_arg buf_size;
+ unsigned int luma_size, chroma_size;
+ unsigned int luma_plane_sz, chroma_plane_sz, mv_plane_sz;
+
+ init_arg = (struct mfc_dec_init_arg *)args;
+
+ /* width : 128B align, height : 32B align, size: 8KB align */
+ luma_plane_sz = ALIGN_TO_128B(init_arg->out_img_width) * ALIGN_TO_32B(init_arg->out_img_height);
+ luma_plane_sz = ALIGN_TO_8KB(luma_plane_sz);
+ chroma_plane_sz = ALIGN_TO_128B(init_arg->out_img_width) * ALIGN_TO_32B(init_arg->out_img_height / 2);
+ chroma_plane_sz = ALIGN_TO_8KB(chroma_plane_sz);
+ mv_plane_sz = 0;
+
+ buf_size.luma = luma_plane_sz;
+ buf_size.chroma = chroma_plane_sz;
+
+ if (mfc_ctx->MfcCodecType == H264_DEC) {
+ /* width : 128B align, height : 32B align, size: 8KB align */
+ mv_plane_sz = ALIGN_TO_128B(init_arg->out_img_width) * ALIGN_TO_32B(init_arg->out_img_height / 4);
+ mv_plane_sz = ALIGN_TO_8KB(mv_plane_sz);
+ buf_size.luma += mv_plane_sz;
+ }
+
+ mfc_ctx->shared_mem.allocated_luma_dpb_size = luma_plane_sz;
+ mfc_ctx->shared_mem.allocated_chroma_dpb_size = chroma_plane_sz;
+ mfc_ctx->shared_mem.allocated_mv_size = mv_plane_sz;
+
+ luma_size = buf_size.luma * mfc_ctx->totalDPBCnt;
+ chroma_size = buf_size.chroma * mfc_ctx->totalDPBCnt;
+
+ /*
+ * Allocate chroma & (Mv in case of H264) buf
+ */
+ init_arg->out_frame_buf_size.chroma = chroma_size;
+
+ memset(&local_param, 0, sizeof(local_param));
+ local_param.mem_alloc.buff_size = chroma_size;
+ local_param.mem_alloc.mapped_addr = init_arg->in_mapped_addr;
+
+ ret_code = mfc_allocate_buffer(mfc_ctx, &(local_param), 0);
+ if (ret_code < 0)
+ return ret_code;
+
+ init_arg->out_u_addr.chroma = local_param.mem_alloc.out_uaddr;
+ init_arg->out_p_addr.chroma = local_param.mem_alloc.out_paddr;
+
+ /*
+ * Allocate luma buf
+ */
+ init_arg->out_frame_buf_size.luma = luma_size;
+
+ memset(&local_param, 0, sizeof(local_param));
+ local_param.mem_alloc.buff_size = luma_size;
+ local_param.mem_alloc.mapped_addr = init_arg->in_mapped_addr;
+
+ ret_code = mfc_allocate_buffer(mfc_ctx, &(local_param), 1);
+ if (ret_code < 0)
+ return ret_code;
+
+ init_arg->out_u_addr.luma = local_param.mem_alloc.out_uaddr;
+ init_arg->out_p_addr.luma = local_param.mem_alloc.out_paddr;
+
+ mfc_ctx->dec_dpb_buff_paddr = init_arg->out_p_addr;
+
+ return MFCINST_RET_OK;
+}
+
+
+
+static void mfc_set_dec_frame_buffer(struct mfc_inst_ctx *mfc_ctx)
+{
+ unsigned int port0_base_paddr, port1_base_paddr, i;
+ struct mfc_frame_buf_arg dpb_buff_addr;
+ unsigned int luma_plane_sz, chroma_plane_sz, mv_plane_sz;
+
+ dpb_buff_addr = mfc_ctx->dec_dpb_buff_paddr;
+ port0_base_paddr = mfc_port0_base_paddr;
+ port1_base_paddr = mfc_port1_base_paddr;
+
+ luma_plane_sz = mfc_ctx->shared_mem.allocated_luma_dpb_size;
+ chroma_plane_sz = mfc_ctx->shared_mem.allocated_chroma_dpb_size;
+ mv_plane_sz = mfc_ctx->shared_mem.allocated_mv_size;
+
+ mfc_debug("luma_buf_addr start : 0x%08x luma_buf_size : %d\n", dpb_buff_addr.luma, (luma_plane_sz + mv_plane_sz));
+ mfc_debug("chroma_buf_addr start : 0x%08x chroma_buf_size : %d\n", dpb_buff_addr.chroma, chroma_plane_sz);
+
+ if (mfc_ctx->MfcCodecType == H264_DEC) {
+ for (i = 0; i < mfc_ctx->totalDPBCnt; i++) {
+ mfc_debug("DPB[%d] luma_buf_addr : 0x%08x luma_buf_size : %d\n", i, dpb_buff_addr.luma, luma_plane_sz);
+ mfc_debug("DPB[%d] chroma_buf_addr : 0x%08x chroma_buf_size : %d\n", i, dpb_buff_addr.chroma, chroma_plane_sz);
+ mfc_debug("DPB[%d] mv_buf_addr : 0x%08x mv_plane_sz : %d\n", i, dpb_buff_addr.luma + luma_plane_sz, mv_plane_sz);
+
+ /* set Luma address */
+ WRITEL((dpb_buff_addr.luma - port1_base_paddr) >> 11, MFC_H264DEC_LUMA + (4 * i));
+ WRITEL((dpb_buff_addr.luma + luma_plane_sz - port1_base_paddr) >> 11, MFC_H264DEC_MV + (4 * i));
+ dpb_buff_addr.luma += (luma_plane_sz + mv_plane_sz);
+
+ /* set Chroma address & set MV address */
+ WRITEL((dpb_buff_addr.chroma - port0_base_paddr) >> 11, MFC_H264DEC_CHROMA + (4 * i));
+ dpb_buff_addr.chroma += chroma_plane_sz;
+ }
+ } else {
+ for (i = 0; i < mfc_ctx->totalDPBCnt; i++) {
+ mfc_debug("DPB[%d] luma_buf_addr : 0x%08x luma_buf_size : %d\n", i, dpb_buff_addr.luma, luma_plane_sz);
+ mfc_debug("DPB[%d] chroma_buf_addr : 0x%08x chroma_buf_size : %d\n", i, dpb_buff_addr.chroma, chroma_plane_sz);
+
+ /* set Luma address */
+ WRITEL((dpb_buff_addr.luma - port1_base_paddr) >> 11, MFC_DEC_LUMA + (4 * i));
+ dpb_buff_addr.luma += luma_plane_sz;
+
+ /* set Chroma address */
+ WRITEL((dpb_buff_addr.chroma - port0_base_paddr) >> 11, MFC_DEC_CHROMA + (4 * i));
+ dpb_buff_addr.chroma += chroma_plane_sz;
+ }
+ }
+
+ mfc_debug("luma_buf_addr end : 0x%08x\n", dpb_buff_addr.luma);
+ mfc_debug("chroma_buf_addr end : 0x%08x\n", dpb_buff_addr.chroma);
+}
+
+/* Allocate buffers for encoder */
+static enum mfc_error_code mfc_alloc_stream_ref_buffer(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args)
+{
+ struct mfc_enc_init_mpeg4_arg *init_arg;
+ union mfc_args local_param;
+ unsigned int luma_plane_sz, chroma_plane_sz;
+ enum mfc_error_code ret_code = MFCINST_RET_OK;
+ struct mfc_frame_buf_arg buf_size;
+
+ init_arg = (struct mfc_enc_init_mpeg4_arg *)args;
+
+ /* width : 128B align, height : 32B align, size: 8KB align */
+ luma_plane_sz = ALIGN_TO_128B(init_arg->in_width) * ALIGN_TO_32B(init_arg->in_height);
+ luma_plane_sz = ALIGN_TO_8KB(luma_plane_sz);
+ chroma_plane_sz = ALIGN_TO_128B(init_arg->in_width) * ALIGN_TO_32B(init_arg->in_height / 2);
+ chroma_plane_sz = ALIGN_TO_8KB(chroma_plane_sz);
+
+ buf_size.luma = luma_plane_sz;
+ buf_size.chroma = chroma_plane_sz;
+
+ /*
+ * Allocate stream ref Y0, Y1 buf
+ */
+ init_arg->out_buf_size.strm_ref_y = STREAM_BUF_SIZE + (buf_size.luma * 2);
+
+ memset(&local_param, 0, sizeof(local_param));
+ local_param.mem_alloc.buff_size = init_arg->out_buf_size.strm_ref_y;
+ local_param.mem_alloc.mapped_addr = init_arg->in_mapped_addr;
+
+ ret_code = mfc_allocate_buffer(mfc_ctx, &(local_param), 0);
+ if (ret_code < 0)
+ return ret_code;
+
+ init_arg->out_u_addr.strm_ref_y = local_param.mem_alloc.out_uaddr;
+ init_arg->out_p_addr.strm_ref_y = local_param.mem_alloc.out_paddr;
+
+ /*
+ * Allocate ref C0, C1, Y2, C2, Y3, C3 buf XXX : remove MV buffer
+ */
+ init_arg->out_buf_size.mv_ref_yc = (buf_size.luma * 2) + (buf_size.chroma * 4);
+
+ memset(&local_param, 0, sizeof(local_param));
+ local_param.mem_alloc.buff_size = init_arg->out_buf_size.mv_ref_yc;
+ local_param.mem_alloc.mapped_addr = init_arg->in_mapped_addr;
+
+ ret_code = mfc_allocate_buffer(mfc_ctx, &(local_param), 1);
+ if (ret_code < 0)
+ return ret_code;
+
+ init_arg->out_u_addr.mv_ref_yc = local_param.mem_alloc.out_uaddr;
+ init_arg->out_p_addr.mv_ref_yc = local_param.mem_alloc.out_paddr;
+
+ return ret_code;
+}
+
+static void mfc_set_enc_ref_buffer(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args)
+{
+ unsigned int port0_base_paddr, port1_base_paddr, i;
+ struct mfc_strm_ref_buf_arg ref_buf_addr;
+ unsigned int luma_plane_sz, chroma_plane_sz;
+ struct mfc_enc_init_mpeg4_arg *init_arg;
+
+ init_arg = (struct mfc_enc_init_mpeg4_arg *)args;
+
+ /* width : 128B align, height : 32B align, size: 8KB align */
+ luma_plane_sz = ALIGN_TO_128B(init_arg->in_width) * ALIGN_TO_32B(init_arg->in_height);
+ luma_plane_sz = ALIGN_TO_8KB(luma_plane_sz);
+ chroma_plane_sz = ALIGN_TO_128B(init_arg->in_width) * ALIGN_TO_32B(init_arg->in_height / 2);
+ chroma_plane_sz = ALIGN_TO_8KB(chroma_plane_sz);
+
+ ref_buf_addr = init_arg->out_p_addr;
+ mfc_debug("strm_ref_y_buf_addr : 0x%08x, strm_ref_y_buf_size : %d\n",
+ ref_buf_addr.strm_ref_y, init_arg->out_buf_size.strm_ref_y);
+ mfc_debug("mv_ref_yc_buf_addr : 0x%08x, mv_ref_yc_buf_size : %d\n",
+ ref_buf_addr.mv_ref_yc, init_arg->out_buf_size.mv_ref_yc);
+
+ port0_base_paddr = mfc_port0_base_paddr;
+ port1_base_paddr = mfc_port1_base_paddr;
+
+ mfc_debug("stream_buf_addr : 0x%08x\n", ref_buf_addr.strm_ref_y);
+ ref_buf_addr.strm_ref_y += STREAM_BUF_SIZE;
+
+ /* Set Y0, Y1 ref buffer address */
+ mfc_debug("REF[0] luma_buf_addr : 0x%08x luma_buf_size : %d\n", ref_buf_addr.strm_ref_y, luma_plane_sz);
+ WRITEL((ref_buf_addr.strm_ref_y - port0_base_paddr) >> 11, MFC_ENC_DPB_Y0_ADDR);
+ ref_buf_addr.strm_ref_y += luma_plane_sz;
+ mfc_debug("REF[1] luma_buf_addr : 0x%08x luma_buf_size : %d\n", ref_buf_addr.strm_ref_y, luma_plane_sz);
+ WRITEL((ref_buf_addr.strm_ref_y - port0_base_paddr) >> 11, MFC_ENC_DPB_Y1_ADDR);
+
+ /* Set Y2, Y3 ref buffer address */
+ mfc_debug("REF[2] luma_buf_addr : 0x%08x luma_buf_size : %d\n", ref_buf_addr.mv_ref_yc, luma_plane_sz);
+ WRITEL((ref_buf_addr.mv_ref_yc - port1_base_paddr) >> 11, MFC_ENC_DPB_Y2_ADDR);
+ ref_buf_addr.mv_ref_yc += luma_plane_sz;
+ mfc_debug("REF[3] luma_buf_addr : 0x%08x luma_buf_size : %d\n", ref_buf_addr.mv_ref_yc, luma_plane_sz);
+ WRITEL((ref_buf_addr.mv_ref_yc - port1_base_paddr) >> 11, MFC_ENC_DPB_Y3_ADDR);
+ ref_buf_addr.mv_ref_yc += luma_plane_sz;
+
+ /* Set C0, C1, C2, C3 ref buffer address */
+ for (i = 0; i < 4; i++) {
+ mfc_debug("REF[%d] chroma_buf_addr : 0x%08x chroma_buf_size : %d\n", i, ref_buf_addr.mv_ref_yc, chroma_plane_sz);
+ WRITEL((ref_buf_addr.mv_ref_yc - port1_base_paddr) >> 11, MFC_ENC_DPB_C0_ADDR + (4 * i));
+ ref_buf_addr.mv_ref_yc += chroma_plane_sz;
+ }
+}
+
+static enum mfc_error_code mfc_alloc_codec_buffer(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args)
+{
+ struct mfc_dec_init_arg *init_arg;
+ enum mfc_error_code ret_code;
+ union mfc_args local_param;
+
+ init_arg = (struct mfc_dec_init_arg *)args;
+
+ memset(&local_param, 0, sizeof(local_param));
+ if (is_dec_codec(mfc_ctx->MfcCodecType))
+ local_param.mem_alloc.buff_size = DEC_CODEC_BUF_SIZE + SHARED_BUF_SIZE;
+ else
+ local_param.mem_alloc.buff_size = ENC_CODEC_BUF_SIZE + SHARED_BUF_SIZE;
+
+ local_param.mem_alloc.mapped_addr = init_arg->in_mapped_addr;
+ ret_code = mfc_allocate_buffer(mfc_ctx, &(local_param), 0);
+ if (ret_code < 0)
+ return ret_code;
+
+ mfc_ctx->codec_buff_paddr = local_param.mem_alloc.out_paddr;
+ if (is_dec_codec(mfc_ctx->MfcCodecType))
+ mfc_ctx->shared_mem_paddr = mfc_ctx->codec_buff_paddr + DEC_CODEC_BUF_SIZE;
+ else
+ mfc_ctx->shared_mem_paddr = mfc_ctx->codec_buff_paddr + ENC_CODEC_BUF_SIZE;
+
+ mfc_ctx->shared_mem_vaddr = (unsigned int)mfc_get_fw_buff_vaddr() + (mfc_ctx->shared_mem_paddr - mfc_port0_base_paddr);
+ memset((void *)mfc_ctx->shared_mem_vaddr, 0x0, SHARED_MEM_MAX);
+
+ if (mfc_ctx->MfcCodecType == H264_ENC) {
+ memset(&local_param, 0, sizeof(local_param));
+ local_param.mem_alloc.buff_size = PRED_BUF_SIZE;
+ local_param.mem_alloc.mapped_addr = init_arg->in_mapped_addr;
+ ret_code = mfc_allocate_buffer(mfc_ctx, &(local_param), 1);
+ if (ret_code < 0)
+ return ret_code;
+
+ mfc_ctx->pred_buff_paddr = local_param.mem_alloc.out_paddr;
+ }
+
+ return MFCINST_RET_OK;
+}
+
+
+
+static void mfc_set_codec_buffer(struct mfc_inst_ctx *mfc_ctx)
+{
+ unsigned int codec_buff_paddr;
+ unsigned int pred_buff_paddr;
+ unsigned int port0_base_paddr;
+ unsigned int port1_base_paddr;
+
+ port0_base_paddr = mfc_port0_base_paddr;
+ port1_base_paddr = mfc_port1_base_paddr;
+ codec_buff_paddr = mfc_ctx->codec_buff_paddr;
+ pred_buff_paddr = mfc_ctx->pred_buff_paddr;
+
+ mfc_debug("inst_no : %d, codec_buf_start: 0x%08x\n", mfc_ctx->InstNo, codec_buff_paddr);
+
+ switch (mfc_ctx->MfcCodecType) {
+ case H264_DEC:
+ WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_H264DEC_VERT_NB_MV);
+ codec_buff_paddr += (16 << 10);
+ WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_H264DEC_NB_IP);
+ codec_buff_paddr += (32 << 10);
+ break;
+
+ case MPEG4_DEC:
+ case H263_DEC:
+ case XVID_DEC:
+ case FIMV1_DEC:
+ case FIMV2_DEC:
+ case FIMV3_DEC:
+ case FIMV4_DEC:
+ WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_NB_DCAC);
+ codec_buff_paddr += (16 << 10);
+ WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_UPNB_MV);
+ codec_buff_paddr += (68 << 10);
+ WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_SUB_ANCHOR_MV);
+ codec_buff_paddr += (136 << 10);
+ WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_OVERLAP_TRANSFORM);
+ codec_buff_paddr += (32 << 10);
+ WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_STX_PARSER);
+ codec_buff_paddr += (68 << 10);
+ break;
+
+ case VC1_DEC:
+ case VC1RCV_DEC:
+ WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_NB_DCAC);
+ codec_buff_paddr += (16 << 10);
+ WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_UPNB_MV);
+ codec_buff_paddr += (68 << 10);
+ WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_SUB_ANCHOR_MV);
+ codec_buff_paddr += (136 << 10);
+ WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_OVERLAP_TRANSFORM);
+ codec_buff_paddr += (32 << 10);
+ WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_BITPLANE3);
+ codec_buff_paddr += (8 << 10);
+ WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_BITPLANE2);
+ codec_buff_paddr += (8 << 10);
+ WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_BITPLANE1);
+ codec_buff_paddr += (8 << 10);
+ break;
+
+ case MPEG1_DEC:
+ case MPEG2_DEC:
+ break;
+
+ case H264_ENC:
+ case MPEG4_ENC:
+ case H263_ENC:
+ WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_UPPER_MV_ADDR);
+ codec_buff_paddr += (64 << 10);
+ WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_DIRECT_COLZERO_FLAG_ADDR);
+ codec_buff_paddr += (64 << 10);
+ WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_UPPER_INTRA_MD_ADDR);
+ codec_buff_paddr += (64 << 10);
+ if (mfc_ctx->MfcCodecType == H264_ENC) {
+ WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_NBOR_INFO_MPENC_ADDR);
+ WRITEL((pred_buff_paddr - port1_base_paddr) >> 11, MFC_UPPER_INTRA_PRED_ADDR);
+ } else {
+ WRITEL((codec_buff_paddr - port0_base_paddr) >> 11, MFC_ACDC_COEF_BASE_ADDR);
+ }
+ codec_buff_paddr += (64 << 10);
+ break;
+
+ default:
+ break;
+ }
+
+ mfc_debug("inst_no : %d, codec_buf_end : 0x%08x\n", mfc_ctx->InstNo, codec_buff_paddr);
+}
+
+/* This function sets the MFC SFR values according to the input arguments. */
+static void mfc_set_encode_init_param(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args)
+{
+ unsigned int ms_size;
+ struct mfc_enc_init_mpeg4_arg *enc_init_mpeg4_arg;
+ struct mfc_enc_init_h264_arg *enc_init_h264_arg;
+
+ enc_init_mpeg4_arg = (struct mfc_enc_init_mpeg4_arg *)args;
+ enc_init_h264_arg = (struct mfc_enc_init_h264_arg *)args;
+
+#if DEBUG_MAKE_RAW
+ mImgHight = enc_init_mpeg4_arg->in_height;
+ mImgWidth = enc_init_mpeg4_arg->in_width;
+#endif
+
+ mfc_debug("mfc_codec_type : %d\n", mfc_ctx->MfcCodecType);
+
+ WRITEL(enc_init_mpeg4_arg->in_width, MFC_HSIZE_PX);
+ if (enc_init_mpeg4_arg->in_interlace_mode)
+ WRITEL(enc_init_mpeg4_arg->in_height >> 1, MFC_VSIZE_PX);
+ else
+ WRITEL(enc_init_mpeg4_arg->in_height, MFC_VSIZE_PX);
+
+ /* H.263 does not support field picture */
+ WRITEL(enc_init_mpeg4_arg->in_interlace_mode, MFC_PICTURE_STRUCT);
+ WRITEL(0, MFC_ENC_INT_MASK); /* mask interrupt */
+ WRITEL(1, MFC_STR_BF_MODE_CTRL); /* stream buf frame mode */
+ WRITEL((1 << 18) | (enc_init_mpeg4_arg->in_BframeNum << 16) |
+ enc_init_mpeg4_arg->in_gop_num, MFC_ENC_PIC_TYPE_CTRL);
+
+ /* Multi-slice options */
+ if (enc_init_mpeg4_arg->in_MS_mode) {
+ ms_size = (mfc_ctx->MfcCodecType == H263_ENC) ? 0 : enc_init_mpeg4_arg->in_MS_size;
+ switch (enc_init_mpeg4_arg->in_MS_mode) {
+ case 1:
+ WRITEL(0x1, MFC_ENC_MSLICE_CTRL);
+ WRITEL(ms_size, MFC_ENC_MSLICE_MB);
+ break;
+
+ case 2:
+ WRITEL(0x3, MFC_ENC_MSLICE_CTRL);
+ WRITEL(ms_size, MFC_ENC_MSLICE_BYTE);
+ break;
+
+ default:
+ mfc_err("Invalid Multi-slice mode type\n");
+ break;
+ }
+ } else {
+ WRITEL(0, MFC_ENC_MSLICE_CTRL);
+ }
+
+ /* Set circular intra refresh MB count */
+ WRITEL(enc_init_mpeg4_arg->in_mb_refresh, MFC_ENC_CIR_CTRL);
+
+ if (enc_init_mpeg4_arg->in_frame_map == 1)
+ WRITEL(MEM_STRUCT_TILE_ENC, MFC_ENC_MAP_FOR_CUR);
+ else
+ WRITEL(MEM_STRUCT_LINEAR, MFC_ENC_MAP_FOR_CUR);
+
+ /* Set padding control */
+ WRITEL((enc_init_mpeg4_arg->in_pad_ctrl_on << 31) |
+ (enc_init_mpeg4_arg->in_cr_pad_val << 16) |
+ (enc_init_mpeg4_arg->in_cb_pad_val << 8) |
+ (enc_init_mpeg4_arg->in_luma_pad_val << 0), MFC_ENC_PADDING_CTRL);
+
+ /* Set Rate Control */
+ if (enc_init_mpeg4_arg->in_RC_frm_enable) {
+ WRITEL(enc_init_mpeg4_arg->in_RC_framerate, MFC_RC_FRAME_RATE);
+ WRITEL(enc_init_mpeg4_arg->in_RC_bitrate, MFC_RC_BIT_RATE);
+ WRITEL(enc_init_mpeg4_arg->in_RC_rpara, MFC_RC_RPARA);
+ }
+
+ WRITEL(enc_init_mpeg4_arg->in_RC_qbound, MFC_RC_QBOUND);
+
+ switch (mfc_ctx->MfcCodecType) {
+ case H264_ENC:
+ WRITEL(enc_init_h264_arg->in_profile_level, MFC_PROFILE);
+ WRITEL(enc_init_h264_arg->in_transform8x8_mode, MFC_H264_ENC_TRANS_8X8_FLAG);
+ WRITEL(enc_init_h264_arg->in_deblock_filt, MFC_LF_CONTROL);
+ WRITEL(((enc_init_h264_arg->in_deblock_alpha_C0 * 2) & 0x1f), MFC_LF_ALPHA_OFF);
+ WRITEL(((enc_init_h264_arg->in_deblock_beta * 2) & 0x1f), MFC_LF_BETA_OFF);
+ WRITEL(1, MFC_EDFU_SF_EPB_ON_CTRL); /* Auto EPB insertion on, only for h264 */
+
+ /* if in_RC_mb_enable is '1' */
+#if ENABLE_ENC_MB
+ if (enc_init_h264_arg->in_RC_frm_enable != 1)
+ enc_init_h264_arg->in_RC_frm_enable = 1;
+ if (enc_init_h264_arg->in_RC_mb_enable != 1)
+ enc_init_h264_arg->in_RC_mb_enable = 1;
+#endif
+
+ WRITEL((enc_init_h264_arg->in_RC_frm_enable << 9) |
+ (enc_init_h264_arg->in_RC_mb_enable << 8) |
+ (enc_init_h264_arg->in_frame_qp & 0x3f),
+ MFC_RC_CONFIG);
+
+ if (enc_init_h264_arg->in_RC_mb_enable) {
+ WRITEL((enc_init_h264_arg->in_RC_mb_dark_disable << 3)|
+ (enc_init_h264_arg->in_RC_mb_smooth_disable << 2)|
+ (enc_init_h264_arg->in_RC_mb_static_disable << 1)|
+ (enc_init_h264_arg->in_RC_mb_activity_disable << 0),
+ MFC_RC_MB_CTRL);
+ }
+
+ WRITEL((enc_init_h264_arg->in_symbolmode & 0x1), MFC_H264_ENC_ENTRP_MODE);
+
+ if (enc_init_h264_arg->in_reference_num > 2)
+ enc_init_h264_arg->in_reference_num = 2;
+ if (enc_init_h264_arg->in_ref_num_p > enc_init_h264_arg->in_reference_num)
+ enc_init_h264_arg->in_ref_num_p = enc_init_h264_arg->in_reference_num;
+ WRITEL((enc_init_h264_arg->in_ref_num_p << 5) |
+ (enc_init_h264_arg->in_reference_num),
+ MFC_H264_ENC_NUM_OF_REF);
+
+ WRITEL(enc_init_h264_arg->in_md_interweight_pps, MFC_H264_ENC_MDINTER_WEIGHT);
+ WRITEL(enc_init_h264_arg->in_md_intraweight_pps, MFC_H264_ENC_MDINTRA_WEIGHT);
+ break;
+
+ case MPEG4_ENC:
+ WRITEL(enc_init_mpeg4_arg->in_profile_level, MFC_PROFILE);
+ WRITEL((enc_init_mpeg4_arg->in_RC_frm_enable << 9) |
+ (enc_init_mpeg4_arg->in_frame_qp & 0x3f),
+ MFC_RC_CONFIG);
+ WRITEL(enc_init_mpeg4_arg->in_qpelME_enable, MFC_MPEG4_ENC_QUART_PXL);
+ if (enc_init_mpeg4_arg->in_time_increament_res) {
+ mfc_ctx->shared_mem.vop_timing = (1 << 31) |
+ (enc_init_mpeg4_arg->in_time_increament_res << 16) |
+ (enc_init_mpeg4_arg->in_time_vop_time_increament);
+ }
+ break;
+
+ case H263_ENC:
+ WRITEL(0x20, MFC_PROFILE);
+ WRITEL((enc_init_mpeg4_arg->in_RC_frm_enable << 9) |
+ (enc_init_mpeg4_arg->in_frame_qp & 0x3f),
+ MFC_RC_CONFIG);
+ break;
+
+ default:
+ mfc_err("Invalid MFC codec type\n");
+ }
+}
+
+int mfc_load_firmware(const unsigned char *data, size_t size)
+{
+ volatile unsigned char *fw_virbuf;
+
+ mfc_debug("mfc_load_firmware : MFC F/W Loading Start.................\n");
+
+ fw_virbuf = mfc_get_fw_buff_vaddr();
+ memset((void *)fw_virbuf, 0, MFC_FW_MAX_SIZE);
+
+ invalidate_kernel_vmap_range((void *)data, size);
+ memcpy((void *)fw_virbuf, data, size);
+ flush_kernel_vmap_range((void *)fw_virbuf, size);
+
+ mfc_debug("mfc_load_firmware : MFC F/W Loading Stop.................(fw_virbuf: 0x%08x)\n", fw_virbuf);
+
+ return 0;
+}
+
+enum mfc_error_code mfc_init_hw()
+{
+ int fw_buf_size;
+ unsigned int fw_version;
+ unsigned int mc_status;
+ unsigned long idcode;
+ int nIntrRet = 0;
+
+ mfc_debug("mfc_init_hw++\n");
+
+ /*
+ * 0-1. Check Type
+ */
+ idcode = readl(S5P_VA_CHIPID);
+ if ((idcode & 0x0F) == 0x02)
+ mCheckType = false;
+ else
+ mCheckType = true;
+
+ /*
+ * 1. MFC reset
+ */
+ do {
+ mc_status = READL(MFC_MC_STATUS);
+ } while (mc_status != 0);
+
+ if (mfc_cmd_reset() == false) {
+ mfc_err("MFCINST_ERR_INIT_FAIL\n");
+ return MFCINST_ERR_INIT_FAIL;
+ }
+
+ /*
+ * 2. Set DRAM base Addr
+ */
+ WRITEL(mfc_port0_base_paddr, MFC_MC_DRAMBASE_ADDR_A);
+ WRITEL(mfc_port1_base_paddr, MFC_MC_DRAMBASE_ADDR_B);
+ WRITEL(1, MFC_NUM_MASTER);
+
+ /*
+ * 3. Initialize registers of stream I/F for decoder
+ */
+ WRITEL(0xffff, MFC_SI_CH0_INST_ID);
+ WRITEL(0xffff, MFC_SI_CH1_INST_ID);
+
+ WRITEL(0, MFC_RISC2HOST_COMMAND);
+ WRITEL(0, MFC_HOST2RISC_COMMAND);
+
+ /*
+ * 4. Release reset signal to the RISC.
+ */
+ WRITEL(0x3ff, MFC_SW_RESET);
+ nIntrRet = mfc_wait_for_done(R2H_CMD_FW_STATUS_RET);
+ if (nIntrRet != R2H_CMD_FW_STATUS_RET) {
+ /*
+ * 4-1. MFC FW downloading
+ */
+
+ mfc_err("MFCINST_ERR_FW_LOAD_MFC_SW_RESET_FAIL............(Ret = %d)", nIntrRet);
+
+
+ mfc_err("MFCINST_ERR_FW_LOAD_FAIL\n");
+ return MFCINST_ERR_FW_LOAD_FAIL;
+ }
+
+ /*
+ * 5. Initialize firmware
+ */
+ fw_buf_size = MFC_FW_MAX_SIZE;
+ if (mfc_cmd_host2risc(H2R_CMD_SYS_INIT, fw_buf_size, 0, 0, 0) == false) {
+ mfc_err("R2H_CMD_SYS_INIT FAIL\n");
+ return MFCINST_ERR_FW_INIT_FAIL;
+ }
+
+ if (mfc_wait_for_done(R2H_CMD_SYS_INIT_RET) != R2H_CMD_SYS_INIT_RET) {
+ mfc_err("R2H_CMD_SYS_INIT_RET FAIL\n");
+ return MFCINST_ERR_FW_INIT_FAIL;
+ }
+
+ fw_version = READL(MFC_FW_VERSION);
+
+
+ mfc_debug("MFC FW version : %02xyy, %02xmm, %02xdd\n",
+ (fw_version >> 16) & 0xff, (fw_version >> 8) & 0xff, fw_version & 0xff);
+
+ mfc_debug("DRAM PORT0 BASE ADDRESS: 0x%08x\n", READL(MFC_MC_DRAMBASE_ADDR_A));
+ mfc_debug("DRAM PORT1 BASE ADDRESS: 0x%08x\n", READL(MFC_MC_DRAMBASE_ADDR_B));
+ mfc_debug("mfc_init_hw-\n");
+
+ return MFCINST_RET_OK;
+}
+
+static unsigned int mfc_get_codec_arg(enum ssbsip_mfc_codec_type codec_type)
+{
+ unsigned int codec_no = 99;
+
+ switch (codec_type) {
+ case H264_DEC:
+ codec_no = 0;
+ break;
+
+ case VC1_DEC:
+ codec_no = 1;
+ break;
+
+ case MPEG4_DEC:
+ case XVID_DEC:
+ codec_no = 2;
+ break;
+
+ case MPEG1_DEC:
+ case MPEG2_DEC:
+ codec_no = 3;
+ break;
+
+ case H263_DEC:
+ codec_no = 4;
+ break;
+
+ case VC1RCV_DEC:
+ codec_no = 5;
+ break;
+
+ case FIMV1_DEC:
+ codec_no = 6;
+ break;
+
+ case FIMV2_DEC:
+ codec_no = 7;
+ break;
+
+ case FIMV3_DEC:
+ codec_no = 8;
+ break;
+
+ case FIMV4_DEC:
+ codec_no = 9;
+ break;
+
+ case H264_ENC:
+ codec_no = 16;
+ break;
+
+ case MPEG4_ENC:
+ codec_no = 17;
+ break;
+
+ case H263_ENC:
+ codec_no = 18;
+ break;
+
+ default:
+ break;
+ }
+
+ return codec_no;
+}
+
+static int mfc_get_inst_no(struct mfc_inst_ctx *mfc_ctx, unsigned int context_addr, int context_size)
+{
+ unsigned int codec_no;
+ int inst_no;
+ unsigned int port0_base_paddr;
+ int mfc_wait_ret = 0;
+ port0_base_paddr = mfc_port0_base_paddr;
+
+ codec_no = (unsigned int)mfc_get_codec_arg(mfc_ctx->MfcCodecType);
+
+ if (mfc_cmd_host2risc(H2R_CMD_OPEN_INSTANCE,
+ codec_no,
+ (mfc_ctx->crcEnable << 31) | PIXEL_CACHE_ON_ONLY_P_PICTURE,
+ (context_addr - port0_base_paddr) >> 11,
+ context_size) == false) {
+ mfc_err("R2H_CMD_OPEN_INSTANCE FAIL\n");
+ return MFCINST_ERR_OPEN_FAIL;
+ }
+
+ mfc_wait_ret = mfc_wait_for_done(R2H_CMD_OPEN_INSTANCE_RET);
+ if (mfc_wait_ret != R2H_CMD_OPEN_INSTANCE_RET) {
+ mfc_err("R2H_CMD_OPEN_INSTANCE_RET FAIL..........(ret:%d)\n", mfc_wait_ret);
+ return MFCINST_ERR_OPEN_FAIL;
+ }
+
+ inst_no = READL(MFC_RISC2HOST_ARG1);
+ if (inst_no >= MFC_MAX_INSTANCE_NUM) {
+ mfc_err("mfc_get_inst_no() - INSTANCE NO : %d, CODEC_TYPE : %d --\n", inst_no, codec_no);
+ return -1;
+ } else {
+ mfc_debug("mfc_get_inst_no() - INSTANCE NO : %d, CODEC_TYPE : %d --\n", inst_no, codec_no);
+ return inst_no;
+ }
+}
+
+int mfc_return_inst_no(int inst_no, enum ssbsip_mfc_codec_type codec_type)
+{
+ unsigned int codec_no;
+ int mfc_wait_ret = 0;
+
+ codec_no = (unsigned int)mfc_get_codec_arg(codec_type);
+
+ if (mfc_cmd_host2risc(H2R_CMD_CLOSE_INSTANCE, inst_no, 0, 0, 0) == false) {
+ mfc_err("R2H_CMD_CLOSE_INSTANCE FAIL\n");
+ return MFCINST_ERR_CLOSE_FAIL;
+ }
+
+ mfc_wait_ret = mfc_wait_for_done(R2H_CMD_CLOSE_INSTANCE_RET);
+ if (mfc_wait_ret != R2H_CMD_CLOSE_INSTANCE_RET) {
+ mfc_err("R2H_CMD_CLOSE_INSTANCE_RET FAIL\n");
+ return MFCINST_ERR_CLOSE_FAIL;
+ }
+
+ mfc_debug("mfc_return_inst_no() - INSTANCE NO : %d, CODEC_TYPE : %d --\n", READL(MFC_RISC2HOST_ARG1), codec_no);
+ return MFCINST_RET_OK;
+}
+
+enum mfc_error_code mfc_init_encode(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args)
+{
+ struct mfc_enc_init_mpeg4_arg *enc_init_mpeg4_arg;
+ enum mfc_error_code ret_code;
+ unsigned int context_addr;
+ int context_size;
+ int frame_P_qp, frame_B_qp;
+ int nSize = 0;
+
+ enc_init_mpeg4_arg = (struct mfc_enc_init_mpeg4_arg *)args;
+
+ mfc_debug("++\n");
+ mfc_ctx->MfcCodecType = enc_init_mpeg4_arg->in_codec_type;
+ mfc_ctx->img_width = (unsigned int)enc_init_mpeg4_arg->in_width;
+ mfc_ctx->img_height = (unsigned int)enc_init_mpeg4_arg->in_height;
+ mfc_ctx->interlace_mode = enc_init_mpeg4_arg->in_interlace_mode;
+
+
+ /*
+ * Set Available Type
+ */
+ if (mCheckType == false) {
+ nSize = mfc_ctx->img_width * mfc_ctx->img_height;
+ mfc_ctx->shared_mem.p720_limit_enable = 49425;
+ if (nSize > BOUND_MEMORY_SIZE)
+ return MFCINST_ERR_FRM_BUF_SIZE;
+ } else {
+ mfc_ctx->shared_mem.p720_limit_enable = 49424;
+ }
+
+
+
+
+ /* OPEN CHANNEL
+ * - set open instance using codec_type
+ * - get the instance no
+ */
+ ret_code = mfc_alloc_context_buffer(mfc_ctx, enc_init_mpeg4_arg->in_mapped_addr, &context_addr, &context_size);
+ if (ret_code != MFCINST_RET_OK)
+ return ret_code;
+
+ mfc_ctx->InstNo = mfc_get_inst_no(mfc_ctx, context_addr, context_size);
+ if (mfc_ctx->InstNo < 0) {
+ mfc_err("MFCINST_INST_NUM_EXCEEDED\n");
+ return MFCINST_INST_NUM_EXCEEDED;
+ }
+
+ /* INIT CODEC
+ * - set init parameter
+ * - set init sequence done command
+ * - set codec buffer
+ * - set input risc buffer
+ */
+
+ mfc_set_encode_init_param(mfc_ctx, args);
+
+ ret_code = mfc_alloc_codec_buffer(mfc_ctx, args);
+ if (ret_code != MFCINST_RET_OK) {
+ /* In case of no instance, we should not release codec instance */
+ if (mfc_ctx->InstNo >= 0)
+ mfc_return_inst_no(mfc_ctx->InstNo, mfc_ctx->MfcCodecType);
+
+ return ret_code;
+ }
+
+ mfc_set_codec_buffer(mfc_ctx);
+
+ /* Set Ref YC0~3 & MV */
+ ret_code = mfc_alloc_stream_ref_buffer(mfc_ctx, args);
+ if (ret_code != MFCINST_RET_OK) {
+ /* In case of no instance, we should not release codec instance */
+ if (mfc_ctx->InstNo >= 0)
+ mfc_return_inst_no(mfc_ctx->InstNo, mfc_ctx->MfcCodecType);
+
+ return ret_code;
+ }
+
+ mfc_set_enc_ref_buffer(mfc_ctx, args);
+
+ if (enc_init_mpeg4_arg->in_frame_P_qp)
+ frame_P_qp = enc_init_mpeg4_arg->in_frame_P_qp;
+ else
+ frame_P_qp = enc_init_mpeg4_arg->in_frame_qp;
+
+ if (enc_init_mpeg4_arg->in_frame_B_qp)
+ frame_B_qp = enc_init_mpeg4_arg->in_frame_B_qp;
+ else
+ frame_B_qp = enc_init_mpeg4_arg->in_frame_qp;
+ mfc_ctx->shared_mem.P_B_frame_qp = (frame_B_qp << 6 | frame_P_qp);
+
+ if (enc_init_mpeg4_arg->in_RC_frm_enable)
+ mfc_ctx->shared_mem.vop_timing = ((1 << 31) | (enc_init_mpeg4_arg->in_RC_framerate << 16) | 1);
+
+
+ mfc_write_shared_mem(mfc_ctx->shared_mem_vaddr, &(mfc_ctx->shared_mem));
+
+ ret_code = mfc_encode_header(mfc_ctx, args);
+
+ mfc_read_shared_mem(mfc_ctx->shared_mem_vaddr, &(mfc_ctx->shared_mem));
+
+ mfc_backup_context(mfc_ctx);
+
+ mfc_debug_L0("--\n");
+
+ return ret_code;
+}
+
+static enum mfc_error_code mfc_encode_header(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args)
+{
+ struct mfc_enc_init_mpeg4_arg *init_arg;
+ unsigned int port0_base_paddr;
+ int nIntrRet = 0;
+ int nReturnErrCode = 0;
+
+ init_arg = (struct mfc_enc_init_mpeg4_arg *)args;
+
+ mfc_debug("++ enc_arg->in_strm_st : 0x%08x\n", init_arg->out_p_addr.strm_ref_y);
+
+ port0_base_paddr = mfc_port0_base_paddr;
+
+ /* Set share memory */
+ WRITEL((mfc_ctx->shared_mem_paddr - port0_base_paddr), MFC_SI_CH0_HOST_WR_ADR);
+
+ /* Set stream buffer addr */
+ WRITEL((init_arg->out_p_addr.strm_ref_y - port0_base_paddr) >> 11, MFC_SI_CH0_SB_U_ADDR);
+ WRITEL((init_arg->out_p_addr.strm_ref_y - port0_base_paddr) >> 11, MFC_SI_CH0_SB_L_ADDR);
+ WRITEL(STREAM_BUF_SIZE, MFC_SI_CH0_BUFFER_SIZE);
+
+ WRITEL(1, MFC_STR_BF_U_EMPTY);
+ WRITEL(1, MFC_STR_BF_L_EMPTY);
+
+ /* buf reset command if stream buffer is frame mode */
+ WRITEL(0x1 << 1, MFC_EDFU_SF_BUF_CTRL);
+
+ WRITEL((SEQ_HEADER << 16) | (mfc_ctx->InstNo), MFC_SI_CH0_INST_ID);
+ nIntrRet = mfc_wait_for_done(R2H_CMD_SEQ_DONE_RET);
+ nReturnErrCode = mfc_return_code();
+ if (nIntrRet == 0) {
+ mfc_err("MFCINST_ERR_ENC_EXE_TIME_OUT\n");
+ return MFCINST_ERR_INTR_TIME_OUT;
+ } else if ((nIntrRet != R2H_CMD_SEQ_DONE_RET) && (nReturnErrCode < MFC_WARN_START_NO)) {
+ mfc_err("MFCINST_ERR_ENC_SEQ_HEADER_FAIL ....Intr Code (%d)\n", nIntrRet);
+ return MFCINST_ERR_ENC_HEADER_DECODE_FAIL;
+ } else if (nIntrRet != R2H_CMD_SEQ_DONE_RET) {
+ mfc_warn("MFCINST_WARN_ENC_SEQ_HEADER.........(code: %d)\n", nIntrRet);
+ }
+
+
+ init_arg->out_header_size = READL(MFC_SI_ENC_STREAM_SIZE);
+
+ if (mfc_ctx->buf_type == MFC_BUFFER_CACHE) {
+ dma_unmap_single(NULL, init_arg->out_p_addr.strm_ref_y,
+ init_arg->out_header_size, DMA_FROM_DEVICE);
+ }
+ mfc_debug("encoded header size (%d)\n", init_arg->out_header_size);
+
+ return MFCINST_RET_OK;
+}
+
+static enum mfc_error_code mfc_encode_one_frame(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args)
+{
+ struct mfc_enc_exe_arg *enc_arg;
+ unsigned int port0_base_paddr, port1_base_paddr;
+ int interrupt_flag;
+ int nReturnErrCode;
+
+
+ enc_arg = (struct mfc_enc_exe_arg *)args;
+
+ mfc_debug("++ enc_arg->in_strm_st : 0x%08x enc_arg->in_strm_end :0x%08x \r\n",
+ enc_arg->in_strm_st, enc_arg->in_strm_end);
+ mfc_debug("enc_arg->in_Y_addr : 0x%08x enc_arg->in_CbCr_addr :0x%08x \r\n",
+ enc_arg->in_Y_addr, enc_arg->in_CbCr_addr);
+
+ mfc_restore_context(mfc_ctx);
+
+ port0_base_paddr = mfc_port0_base_paddr;
+ port1_base_paddr = mfc_port1_base_paddr;
+
+#ifdef ENABLE_DEBUG_ENC_EXE_INTR_ERR
+#if ENABLE_DEBUG_ENC_EXE_INTR_ERR
+ makefile_mfc_enc_err_info(enc_arg);
+#endif
+#endif
+
+ /* Set share memory */
+ WRITEL((mfc_ctx->shared_mem_paddr - port0_base_paddr), MFC_SI_CH0_HOST_WR_ADR);
+
+ /* Set stream buffer addr */
+ WRITEL((enc_arg->in_strm_st - port0_base_paddr) >> 11, MFC_SI_CH0_SB_U_ADDR);
+ WRITEL((enc_arg->in_strm_st - port0_base_paddr) >> 11, MFC_SI_CH0_SB_L_ADDR);
+ WRITEL(STREAM_BUF_SIZE, MFC_SI_CH0_BUFFER_SIZE);
+
+ /* Set current frame buffer addr */
+ WRITEL((enc_arg->in_Y_addr - port1_base_paddr) >> 11, MFC_SI_CH0_CURRENT_Y_ADDR);
+ WRITEL((enc_arg->in_CbCr_addr - port1_base_paddr) >> 11, MFC_SI_CH0_CURRENT_C_ADDR);
+
+ WRITEL(1, MFC_STR_BF_U_EMPTY);
+ WRITEL(1, MFC_STR_BF_L_EMPTY);
+
+ /* buf reset command if stream buffer is frame mode */
+ WRITEL(0x1 << 1, MFC_EDFU_SF_BUF_CTRL);
+
+ if (mfc_ctx->forceSetFrameType == NOT_CODED)
+ WRITEL((0x1 << 1), MFC_SI_CH0_ENC_PARA);
+ else if (mfc_ctx->forceSetFrameType == I_FRAME)
+ WRITEL(0x1, MFC_SI_CH0_ENC_PARA);
+
+ mfc_ctx->forceSetFrameType = DONT_CARE;
+
+ if (mfc_ctx->buf_type == MFC_BUFFER_CACHE) {
+ unsigned char *in_vir;
+ unsigned int aligned_width;
+ unsigned int aligned_height;
+
+ in_vir = phys_to_virt(enc_arg->in_Y_addr);
+ aligned_width = ALIGN_TO_128B(mfc_ctx->img_width);
+ aligned_height = ALIGN_TO_32B(mfc_ctx->img_height);
+ dma_map_single(NULL, in_vir, aligned_width*aligned_height,
+ DMA_TO_DEVICE);
+
+ in_vir = phys_to_virt(enc_arg->in_CbCr_addr);
+ aligned_height = ALIGN_TO_32B(mfc_ctx->img_height/2);
+ dma_map_single(NULL, in_vir, aligned_width*aligned_height,
+ DMA_TO_DEVICE);
+ }
+
+ /* Try frame encoding */
+ WRITEL((FRAME << 16) | (mfc_ctx->InstNo), MFC_SI_CH0_INST_ID);
+ interrupt_flag = mfc_wait_for_done(R2H_CMD_FRAME_DONE_RET);
+ nReturnErrCode = mfc_return_code();
+ if (interrupt_flag == 0) {
+ mfc_err("MFCINST_ERR_ENC_EXE_TIME_OUT\n");
+ return MFCINST_ERR_INTR_TIME_OUT;
+ } else if ((interrupt_flag != R2H_CMD_FRAME_DONE_RET) && (nReturnErrCode < MFC_WARN_START_NO)) {
+ mfc_err("MFCINST_ERR_ENC_DONE_FAIL\n");
+ return MFCINST_ERR_ENC_ENCODE_DONE_FAIL;
+ } else if (interrupt_flag != R2H_CMD_FRAME_DONE_RET) {
+ mfc_warn("MFCINST_WARN_ENC_EXE.........(code: %d)\n", interrupt_flag);
+ }
+
+ /* Get encoded infromation */
+ enc_arg->out_frame_type = READL(MFC_SI_ENC_SLICE_TYPE);
+ enc_arg->out_encoded_size = READL(MFC_SI_ENC_STREAM_SIZE);
+ enc_arg->out_encoded_Y_paddr = READL(MFC_SI_ENCODED_Y_ADDR);
+ enc_arg->out_encoded_C_paddr = READL(MFC_SI_ENCODED_C_ADDR);
+
+ if (mfc_ctx->buf_type == MFC_BUFFER_CACHE) {
+ dma_unmap_single(NULL, enc_arg->in_strm_st,
+ enc_arg->out_encoded_size, DMA_FROM_DEVICE);
+ }
+
+ mfc_debug("-- frame type(%d) encodedSize(%d)\r\n",
+ enc_arg->out_frame_type, enc_arg->out_encoded_size);
+
+ return MFCINST_RET_OK;
+}
+
+enum mfc_error_code mfc_exe_encode(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args)
+{
+ enum mfc_error_code ret_code;
+ struct mfc_enc_exe_arg *enc_arg;
+
+ enc_arg = (struct mfc_enc_exe_arg *)args;
+
+ mfc_ctx->shared_mem.set_frame_tag = enc_arg->in_frametag;
+ mfc_write_shared_mem(mfc_ctx->shared_mem_vaddr, &(mfc_ctx->shared_mem));
+
+ /* 5. Encode Frame */
+ ret_code = mfc_encode_one_frame(mfc_ctx, args);
+
+ if (ret_code != MFCINST_RET_OK) {
+ mfc_debug("mfc_exe_encode() : Encode Fail..(%d)\n", ret_code);
+ return ret_code;
+ }
+
+ mfc_read_shared_mem(mfc_ctx->shared_mem_vaddr, &(mfc_ctx->shared_mem));
+ enc_arg->out_frametag_top = mfc_ctx->shared_mem.get_frame_tag_top;
+ enc_arg->out_frametag_bottom = mfc_ctx->shared_mem.get_frame_tag_bot;
+
+ mfc_debug_L0("--\n");
+
+ return ret_code;
+}
+
+enum mfc_error_code mfc_init_decode(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args)
+{
+ enum mfc_error_code ret_code;
+ struct mfc_dec_init_arg *init_arg;
+ unsigned int context_addr;
+ int context_size;
+ int nSize;
+ int nIntrRet = 0;
+ int nReturnErrCode = 0;
+
+
+ mfc_debug("[%d] mfc_init_decode() start\n", current->pid);
+ init_arg = (struct mfc_dec_init_arg *)args;
+
+ /* Calculate stream header size */
+#if ENABLE_CHECK_SEQ_HEADER
+ init_arg->in_strm_size = calculate_seq_size(init_arg);
+#endif
+
+ /* Context setting from input param */
+ mfc_ctx->MfcCodecType = init_arg->in_codec_type;
+ mfc_ctx->IsPackedPB = init_arg->in_packed_PB;
+
+ /* OPEN CHANNEL
+ * - set open instance using codec_type
+ * - get the instance no
+ */
+ ret_code = mfc_alloc_context_buffer(mfc_ctx, init_arg->in_mapped_addr, &context_addr, &context_size);
+ if (ret_code != MFCINST_RET_OK)
+ return ret_code;
+
+ mfc_ctx->InstNo = mfc_get_inst_no(mfc_ctx, context_addr, context_size);
+ if (mfc_ctx->InstNo < 0) {
+ mfc_err("MFCINST_INST_NUM_EXCEEDED\n");
+ return MFCINST_INST_NUM_EXCEEDED;
+ }
+
+#ifdef ENABLE_DEBUG_DEC_EXE_INTR_ERR
+#if ENABLE_DEBUG_DEC_EXE_INTR_ERR
+ mcontext_addr = context_addr;
+ mcontext_size = context_size;
+#endif
+#endif
+
+ /*
+ * MFC_LF_CONTROL used both encoding and decoding
+ * H.264 encoding, MPEG4 decoding(post filter)
+ * should disable : need more DPB for loop filter
+ */
+
+ /* INIT CODEC
+ * set input stream buffer
+ * set sequence done command
+ * set NUM_EXTRA_DPB
+ */
+ if (mfc_ctx->MfcCodecType == FIMV1_DEC) {
+ WRITEL(mfc_ctx->widthFIMV1, MFC_SI_CH0_FIMV1_HRESOL);
+ WRITEL(mfc_ctx->heightFIMV1, MFC_SI_CH0_FIMV1_VRESOL);
+ }
+
+ ret_code = mfc_alloc_codec_buffer(mfc_ctx, args);
+ if (ret_code != MFCINST_RET_OK) {
+ /* In case of no instance, we should not release codec instance */
+ if (mfc_ctx->InstNo >= 0)
+ mfc_return_inst_no(mfc_ctx->InstNo, mfc_ctx->MfcCodecType);
+
+ return ret_code;
+ }
+
+ if (nReturnErrCode < 0)
+ return MFCINST_ERR_DEC_INVALID_STRM;
+
+ mfc_set_dec_stream_buffer(mfc_ctx, init_arg->in_strm_buf, init_arg->in_strm_size);
+
+ /* Set Display Delay and SliceEnable */
+ mfc_ctx->sliceEnable = 0;
+ WRITEL(((mfc_ctx->sliceEnable << 31) |
+ (mfc_ctx->displayDelay ? ((1 << 30) |
+ (mfc_ctx->displayDelay << 16)) : 0)),
+ MFC_SI_CH0_DPB_CONFIG_CTRL);
+
+ /* Set Available Type */
+ if (mCheckType == false) {
+ nSize = mfc_ctx->img_width * mfc_ctx->img_height;
+ mfc_ctx->shared_mem.p720_limit_enable = 49425;
+ if (nSize > BOUND_MEMORY_SIZE) {
+ /* In case of no instance, we should not release codec instance */
+ if (mfc_ctx->InstNo >= 0)
+ mfc_return_inst_no(mfc_ctx->InstNo, mfc_ctx->MfcCodecType);
+
+ return MFCINST_ERR_FRM_BUF_SIZE;
+ }
+ } else {
+ mfc_ctx->shared_mem.p720_limit_enable = 49424;
+ }
+
+ WRITEL_SHARED_MEM(mfc_ctx->shared_mem.p720_limit_enable,
+ mfc_ctx->shared_mem_vaddr + P720_LIMIT_ENABLE);
+ WRITEL((mfc_ctx->shared_mem_paddr - mfc_port0_base_paddr), MFC_SI_CH0_HOST_WR_ADR);
+
+ /* Codec Command : Decode a sequence header */
+ WRITEL((SEQ_HEADER << 16) | (mfc_ctx->InstNo), MFC_SI_CH0_INST_ID);
+
+ nIntrRet = mfc_wait_for_done(R2H_CMD_SEQ_DONE_RET);
+ nReturnErrCode = mfc_return_code();
+ if (nIntrRet == 0) {
+
+#ifdef ENABLE_DEBUG_DEC_EXE_INTR_ERR
+#if ENABLE_DEBUG_DEC_EXE_INTR_ERR
+ makefile_mfc_decinit_err_info(mfc_ctx, init_arg, 300);
+#endif
+#endif
+
+ mfc_err("MFCINST_ERR_DEC_INIT_TIME_OUT..........[#1]\n");
+ /* In case of no instance, we should not release codec instance */
+ if (mfc_ctx->InstNo >= 0)
+ mfc_return_inst_no(mfc_ctx->InstNo, mfc_ctx->MfcCodecType);
+
+ return MFCINST_ERR_INTR_TIME_OUT;
+ } else if ((nIntrRet != R2H_CMD_SEQ_DONE_RET) && (nReturnErrCode < MFC_WARN_START_NO)) {
+ mfc_err("MFCINST_ERR_DEC_SEQ_HEADER_FAIL ....Intr Code (%d)\n", nIntrRet);
+ /* In case of no instance, we should not release codec instance */
+ if (mfc_ctx->InstNo >= 0)
+ mfc_return_inst_no(mfc_ctx->InstNo, mfc_ctx->MfcCodecType);
+
+ return MFCINST_ERR_DEC_SEQ_DONE_FAIL;
+ } else if (nIntrRet != R2H_CMD_SEQ_DONE_RET) {
+ mfc_warn("MFCINST_WARN_DEC_INIT.........(code: %d)\n", nIntrRet);
+ }
+
+#ifdef ENABLE_DEBUG_DEC_EXE_INTR_OK
+ #if ENABLE_DEBUG_DEC_EXE_INTR_OK
+ makefile_mfc_decinit_err_info(mfc_ctx, init_arg, 1000);
+#endif
+#endif
+
+ /* out param & context setting from header decoding result */
+ mfc_ctx->img_width = READL(MFC_SI_HOR_RESOL);
+ mfc_ctx->img_height = READL(MFC_SI_VER_RESOL);
+
+ init_arg->out_img_width = READL(MFC_SI_HOR_RESOL);
+ init_arg->out_img_height = READL(MFC_SI_VER_RESOL);
+
+ /* in the case of VC1 interlace, height will be the multiple of 32
+ * otherwise, height and width is the mupltiple of 16
+ */
+ init_arg->out_buf_width = ALIGN_TO_128B(READL(MFC_SI_HOR_RESOL));
+ init_arg->out_buf_height = ALIGN_TO_32B(READL(MFC_SI_VER_RESOL));
+
+ if (mfc_ctx->MfcCodecType == FIMV1_DEC) {
+ mfc_ctx->img_width = mfc_ctx->widthFIMV1;
+ mfc_ctx->img_height = mfc_ctx->heightFIMV1;
+
+ init_arg->out_img_width = mfc_ctx->widthFIMV1;
+ init_arg->out_img_height = mfc_ctx->heightFIMV1;
+ init_arg->out_buf_width = ALIGN_TO_128B(mfc_ctx->widthFIMV1);
+ init_arg->out_buf_height = ALIGN_TO_32B(mfc_ctx->heightFIMV1);
+ }
+
+
+ /* Set totalDPB */
+ init_arg->out_dpb_cnt = READL(MFC_SI_MIN_NUM_DPB);
+ mfc_ctx->DPBCnt = READL(MFC_SI_MIN_NUM_DPB);
+
+ mfc_ctx->totalDPBCnt = init_arg->out_dpb_cnt;
+ mfc_ctx->totalDPBCnt = init_arg->out_dpb_cnt + mfc_ctx->extraDPB;
+ if (mfc_ctx->totalDPBCnt < mfc_ctx->displayDelay)
+ mfc_ctx->totalDPBCnt = mfc_ctx->displayDelay;
+
+ WRITEL(((mfc_ctx->sliceEnable << 31) |
+ (mfc_ctx->displayDelay ? ((1 << 30) |
+ (mfc_ctx->displayDelay << 16)) : 0) |
+ mfc_ctx->totalDPBCnt), MFC_SI_CH0_DPB_CONFIG_CTRL);
+
+ mfc_debug("buf_width : %d buf_height : %d out_dpb_cnt : %d mfc_ctx->DPBCnt : %d\n",
+ init_arg->out_img_width, init_arg->out_img_height, init_arg->out_dpb_cnt, mfc_ctx->DPBCnt);
+ mfc_debug("img_width : %d img_height : %d\n",
+ init_arg->out_img_width, init_arg->out_img_height);
+
+ mfc_set_codec_buffer(mfc_ctx);
+
+ ret_code = mfc_alloc_dec_frame_buffer(mfc_ctx, args);
+ if (ret_code != MFCINST_RET_OK) {
+ /* In case of no instance, we should not release codec instance */
+ if (mfc_ctx->InstNo >= 0)
+ mfc_return_inst_no(mfc_ctx->InstNo, mfc_ctx->MfcCodecType);
+
+ return ret_code;
+ }
+
+ mfc_set_dec_frame_buffer(mfc_ctx);
+
+#ifdef ENABLE_DEBUG_MFC_INIT
+#if ENABLE_DEBUG_MFC_INIT
+ printk_mfc_init_info(mfc_ctx, init_arg);
+#endif
+#endif
+
+ mfc_write_shared_mem(mfc_ctx->shared_mem_vaddr, &(mfc_ctx->shared_mem));
+ WRITEL((mfc_ctx->shared_mem_paddr - mfc_port0_base_paddr), MFC_SI_CH0_HOST_WR_ADR);
+ WRITEL((INIT_BUFFER << 16) | (mfc_ctx->InstNo), MFC_SI_CH0_INST_ID);
+
+ nIntrRet = mfc_wait_for_done(R2H_CMD_INIT_BUFFERS_RET);
+ nReturnErrCode = mfc_return_code();
+ if (nIntrRet == 0) {
+#ifdef ENABLE_DEBUG_DEC_EXE_INTR_ERR
+#if ENABLE_DEBUG_DEC_EXE_INTR_ERR
+ makefile_mfc_decinit_err_info(mfc_ctx, init_arg, 300);
+#endif
+#endif
+
+ mfc_err("MFCINST_ERR_DEC_INIT_TIME_OUT..............[#2]\n");
+ /* In case of no instance, we should not release codec instance */
+ if (mfc_ctx->InstNo >= 0)
+ mfc_return_inst_no(mfc_ctx->InstNo, mfc_ctx->MfcCodecType);
+
+ return MFCINST_ERR_INTR_TIME_OUT;
+ } else if ((nIntrRet != R2H_CMD_INIT_BUFFERS_RET) && (nReturnErrCode < MFC_WARN_START_NO)) {
+ mfc_err("MFCINST_ERR_DEC_INIT_BUFFER_FAIL ........(Intr Code : %d)\n", nIntrRet);
+ /* In case of no instance, we should not release codec instance */
+ if (mfc_ctx->InstNo >= 0)
+ mfc_return_inst_no(mfc_ctx->InstNo, mfc_ctx->MfcCodecType);
+
+ return MFCINST_ERR_DEC_INIT_BUFFER_FAIL;
+ } else if (nIntrRet != R2H_CMD_INIT_BUFFERS_RET) {
+ mfc_warn("MFCINST_WARN_DEC_INIT_BUFFER.........(Intr code: %d)\n", nIntrRet);
+ }
+
+ mfc_ctx->IsStartedIFrame = 0;
+
+ mfc_backup_context(mfc_ctx);
+
+ mfc_debug("[%d] mfc_init_decode() end\n", current->pid);
+
+ mfc_read_shared_mem(mfc_ctx->shared_mem_vaddr, &(mfc_ctx->shared_mem));
+ init_arg->out_crop_top_offset = (mfc_ctx->shared_mem.crop_info2 & 0xffff);
+ init_arg->out_crop_bottom_offset = (mfc_ctx->shared_mem.crop_info2 >> 16);
+ init_arg->out_crop_left_offset = (mfc_ctx->shared_mem.crop_info1 & 0xffff);
+ init_arg->out_crop_right_offset = (mfc_ctx->shared_mem.crop_info1 >> 16);
+ mfc_debug("out_crop_top_offset : %d out_crop_bottom_offset : %d\n", init_arg->out_crop_top_offset, init_arg->out_crop_bottom_offset);
+
+ return MFCINST_RET_OK;
+}
+
+static enum mfc_error_code mfc_decode_one_frame(struct mfc_inst_ctx *mfc_ctx, struct mfc_dec_exe_arg *dec_arg, unsigned int *consumed_strm_size)
+{
+ unsigned int frame_type;
+ static int count;
+ int interrupt_flag;
+ int nReturnErrCode = 0;
+ int nMaxFrameSize = 0;
+ int nOffSet = 0;
+ int nSum = 0;
+ unsigned char *stream_vir;
+
+ /* Check Invalid Stream Size */
+#if ENABLE_CHECK_STREAM_SIZE
+ nMaxFrameSize = mfc_ctx->img_height * mfc_ctx->img_width;
+ if ((dec_arg->in_strm_size < 1) || (dec_arg->in_strm_size > nMaxFrameSize) || (dec_arg->in_strm_size > STREAM_BUF_SIZE)) {
+ mfc_err("MFCINST_ERR_DEC_STRM_SIZE_INVALID : (stream size : %d), (resolution : %d)\n", dec_arg->in_strm_size, nMaxFrameSize);
+ return MFCINST_ERR_DEC_STRM_SIZE_INVALID;
+ }
+#endif
+
+ /* Check Invalid Null Stream */
+#if ENABLE_CHECK_NULL_STREAM
+ if ((dec_arg->in_strm_size > 10) && (!(mfc_ctx->IsPackedPB))) {
+ stream_vir = phys_to_virt(dec_arg->in_strm_buf);
+ nSum = CheckNullStream(stream_vir, dec_arg->in_strm_size);
+
+ if (nSum != 0) {
+#ifdef ENABLE_DEBUG_DEC_EXE_INTR_ERR
+ #if ENABLE_DEBUG_DEC_EXE_INTR_ERR
+ makefile_mfc_dec_err_info(mfc_ctx, dec_arg, 500);
+#endif
+#endif
+ return MFCINST_ERR_STRM_BUF_INVALID;
+ }
+ }
+#endif
+
+ /* Check H.263 Strat Code */
+#if ENABLE_CHECK_START_CODE
+ stream_vir = phys_to_virt(dec_arg->in_strm_buf);
+ nOffSet = CheckDecStartCode(stream_vir, dec_arg->in_strm_size, dec_arg->in_codec_type);
+
+ if (nOffSet < 0) {
+#ifdef ENABLE_DEBUG_DEC_EXE_INTR_ERR
+ #if ENABLE_DEBUG_DEC_EXE_INTR_ERR
+ makefile_mfc_dec_err_info(mfc_ctx, dec_arg, 400);
+#endif
+#endif
+ return MFCINST_ERR_STRM_BUF_INVALID;
+ }
+#endif
+
+ count++;
+ mfc_debug_L0("++ IntNo%d(%d)\r\n", mfc_ctx->InstNo, count);
+
+ WRITEL((mfc_ctx->shared_mem_paddr - mfc_port0_base_paddr), MFC_SI_CH0_HOST_WR_ADR);
+ mfc_set_dec_stream_buffer(mfc_ctx, dec_arg->in_strm_buf, dec_arg->in_strm_size);
+
+ if (mfc_ctx->endOfFrame) {
+ WRITEL((LAST_FRAME<<16) | (mfc_ctx->InstNo), MFC_SI_CH0_INST_ID);
+ mfc_ctx->endOfFrame = 0;
+ } else {
+ WRITEL((FRAME<<16) | (mfc_ctx->InstNo), MFC_SI_CH0_INST_ID);
+ }
+
+ interrupt_flag = mfc_wait_for_done(R2H_CMD_FRAME_DONE_RET);
+ nReturnErrCode = mfc_return_code();
+ if (interrupt_flag == 0) {
+#ifdef ENABLE_DEBUG_DEC_EXE_INTR_ERR
+ #if ENABLE_DEBUG_DEC_EXE_INTR_ERR
+ makefile_mfc_dec_err_info(mfc_ctx, dec_arg, 300);
+#endif
+#endif
+
+
+#if ENABLE_MFC_REGISTER_DEBUG
+ mfc_fw_debug(R2H_CMD_FRAME_DONE_RET);
+#endif
+
+ mfc_err("MFCINST_ERR_DEC_EXE_TIME_OUT\n");
+ return MFCINST_ERR_INTR_TIME_OUT;
+ } else if ((interrupt_flag != R2H_CMD_FRAME_DONE_RET) && (nReturnErrCode < MFC_WARN_START_NO)) {
+
+#ifdef ENABLE_DEBUG_DEC_EXE_PARSER_ERR
+ #if ENABLE_DEBUG_DEC_EXE_PARSER_ERR
+ makefile_mfc_dec_err_info(mfc_ctx, dec_arg, nReturnErrCode);
+#endif
+#endif
+ /* Clear start_byte_num in case of error */
+ mfc_ctx->shared_mem.start_byte_num = 0x0;
+ mfc_write_shared_mem(mfc_ctx->shared_mem_vaddr, &(mfc_ctx->shared_mem));
+
+#if ENABLE_MFC_REGISTER_DEBUG
+ mfc_fw_debug(R2H_CMD_FRAME_DONE_RET);
+#endif
+
+ mfc_err("MFCINST_ERR_DEC_DONE_FAIL.......(interrupt_flag: %d), (ERR Code: %d)\n", interrupt_flag, nReturnErrCode);
+ return MFCINST_ERR_DEC_DECODE_DONE_FAIL;
+
+ } else if (interrupt_flag != R2H_CMD_FRAME_DONE_RET) {
+ mfc_warn("MFCINST_WARN_DEC_EXE.........(interrupt_flag: %d), (WARN Code: %d)\n", interrupt_flag, nReturnErrCode);
+ }
+
+ mfc_read_shared_mem(mfc_ctx->shared_mem_vaddr, &(mfc_ctx->shared_mem));
+
+ dec_arg->out_res_change = (READL(MFC_SI_DISPLAY_STATUS) >> 4) & 0x3;
+
+ if (((READL(MFC_SI_DISPLAY_STATUS) & 0x3) != DECODING_DISPLAY) &&
+ ((READL(MFC_SI_DISPLAY_STATUS) & 0x3) != DISPLAY_ONLY)) {
+ dec_arg->out_display_Y_addr = 0;
+ dec_arg->out_display_C_addr = 0;
+ mfc_debug("DECODING_ONLY frame decoded\n");
+ } else {
+ /* address shift */
+ dec_arg->out_display_Y_addr = READL(MFC_SI_DISPLAY_Y_ADR) << 11;
+ dec_arg->out_display_C_addr = READL(MFC_SI_DISPLAY_C_ADR) << 11;
+ mfc_debug("DISPLAY Able frame decoded\n");
+ }
+
+ if ((READL(MFC_SI_DISPLAY_STATUS) & 0x3) == DECODING_EMPTY)
+ dec_arg->out_display_status = 0;
+ else if ((READL(MFC_SI_DISPLAY_STATUS) & 0x3) == DECODING_DISPLAY)
+ dec_arg->out_display_status = 1;
+ else if ((READL(MFC_SI_DISPLAY_STATUS) & 0x3) == DISPLAY_ONLY)
+ dec_arg->out_display_status = 2;
+ else
+ dec_arg->out_display_status = 3;
+
+ frame_type = READL(MFC_SI_FRAME_TYPE);
+ mfc_ctx->FrameType = (enum mfc_frame_type)(frame_type & 0x3);
+
+ mfc_debug_L0("(Y_ADDR : 0x%08x C_ADDR : 0x%08x)\r\n",
+ dec_arg->out_display_Y_addr, dec_arg->out_display_C_addr);
+
+ *consumed_strm_size = READL(MFC_SI_DEC_FRM_SIZE);
+
+ return MFCINST_RET_OK;
+}
+
+enum mfc_error_code mfc_exe_decode(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args)
+{
+ enum mfc_error_code ret_code;
+ struct mfc_dec_exe_arg *dec_arg;
+ int consumed_strm_size;
+
+ /* 6. Decode Frame */
+ mfc_debug_L0("[%d] mfc_exe_decode() start\n", current->pid);
+
+ dec_arg = (struct mfc_dec_exe_arg *)args;
+
+ mfc_ctx->shared_mem.set_frame_tag = dec_arg->in_frametag;
+
+ mfc_write_shared_mem(mfc_ctx->shared_mem_vaddr, &(mfc_ctx->shared_mem));
+
+ ret_code = mfc_decode_one_frame(mfc_ctx, dec_arg, &consumed_strm_size);
+
+ if (ret_code != MFCINST_RET_OK) {
+ mfc_debug("mfc_exe_decode() : Decode Fail..(%d)\n", ret_code);
+ return ret_code;
+ }
+
+ mfc_read_shared_mem(mfc_ctx->shared_mem_vaddr, &(mfc_ctx->shared_mem));
+ dec_arg->out_frametag_top = mfc_ctx->shared_mem.get_frame_tag_top;
+ dec_arg->out_frametag_bottom = mfc_ctx->shared_mem.get_frame_tag_bot;
+ dec_arg->out_timestamp_top = mfc_ctx->shared_mem.pic_time_top;
+ dec_arg->out_timestamp_bottom = mfc_ctx->shared_mem.pic_time_bot;
+ dec_arg->out_consume_bytes = consumed_strm_size;
+ dec_arg->out_crop_top_offset = (mfc_ctx->shared_mem.crop_info2 & 0xffff);
+ dec_arg->out_crop_bottom_offset = (mfc_ctx->shared_mem.crop_info2 >> 16);
+ dec_arg->out_crop_left_offset = (mfc_ctx->shared_mem.crop_info1 & 0xffff);
+ dec_arg->out_crop_right_offset = (mfc_ctx->shared_mem.crop_info1 >> 16);
+
+
+ /* PackedPB Stream Processing */
+ if ((mfc_ctx->IsPackedPB) &&
+ (mfc_ctx->FrameType == MFC_RET_FRAME_P_FRAME) &&
+ (dec_arg->in_strm_size - consumed_strm_size > 4)) {
+
+ unsigned char *stream_vir;
+ int offset = 0;
+
+ stream_vir = phys_to_virt(dec_arg->in_strm_buf);
+
+ invalidate_kernel_vmap_range((void *)stream_vir, dec_arg->in_strm_size);
+
+ offset = CheckMPEG4StartCode(stream_vir+consumed_strm_size , dec_arg->in_strm_size - consumed_strm_size);
+ if (offset > 4)
+ consumed_strm_size += offset;
+ dec_arg->in_strm_size -= consumed_strm_size;
+
+ mfc_ctx->shared_mem.set_frame_tag = dec_arg->in_frametag;
+ mfc_ctx->shared_mem.start_byte_num = consumed_strm_size;
+ mfc_write_shared_mem(mfc_ctx->shared_mem_vaddr, &(mfc_ctx->shared_mem));
+ ret_code = mfc_decode_one_frame(mfc_ctx, dec_arg, &consumed_strm_size);
+ if (ret_code != MFCINST_RET_OK)
+ return ret_code;
+
+ mfc_read_shared_mem(mfc_ctx->shared_mem_vaddr, &(mfc_ctx->shared_mem));
+ dec_arg->out_frametag_top = mfc_ctx->shared_mem.get_frame_tag_top;
+ dec_arg->out_frametag_bottom = mfc_ctx->shared_mem.get_frame_tag_bot;
+ dec_arg->out_timestamp_top = mfc_ctx->shared_mem.pic_time_top;
+ dec_arg->out_timestamp_bottom = mfc_ctx->shared_mem.pic_time_bot;
+ dec_arg->out_consume_bytes += consumed_strm_size;
+ dec_arg->out_crop_top_offset = (mfc_ctx->shared_mem.crop_info2 & 0xffff);
+ dec_arg->out_crop_bottom_offset = (mfc_ctx->shared_mem.crop_info2 >> 16);
+ dec_arg->out_crop_left_offset = (mfc_ctx->shared_mem.crop_info1 & 0xffff);
+ dec_arg->out_crop_right_offset = (mfc_ctx->shared_mem.crop_info1 >> 16);
+
+ mfc_ctx->shared_mem.start_byte_num = 0;
+
+ }
+
+ if (mfc_ctx->buf_type == MFC_BUFFER_CACHE) {
+ if (((READL(MFC_SI_DISPLAY_STATUS) & 0x3) == DECODING_DISPLAY) ||
+ ((READL(MFC_SI_DISPLAY_STATUS) & 0x3) == DISPLAY_ONLY)) {
+ unsigned int aligned_width;
+ unsigned int aligned_height;
+
+ aligned_width = ALIGN_TO_128B(mfc_ctx->img_width);
+ aligned_height = ALIGN_TO_32B(mfc_ctx->img_height);
+ dma_unmap_single(NULL, dec_arg->out_display_Y_addr,
+ aligned_width*aligned_height, DMA_FROM_DEVICE);
+
+ aligned_height = ALIGN_TO_32B(mfc_ctx->img_height/2);
+ dma_unmap_single(NULL, dec_arg->out_display_C_addr,
+ aligned_width*aligned_height, DMA_FROM_DEVICE);
+ }
+ }
+
+ mfc_debug_L0("--\n");
+
+ return ret_code;
+}
+
+enum mfc_error_code mfc_deinit_hw(struct mfc_inst_ctx *mfc_ctx)
+{
+ mfc_restore_context(mfc_ctx);
+
+ return MFCINST_RET_OK;
+}
+
+enum mfc_error_code mfc_get_config(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args)
+{
+ struct mfc_get_config_arg *get_cnf_arg;
+ get_cnf_arg = (struct mfc_get_config_arg *)args;
+
+ switch (get_cnf_arg->in_config_param) {
+ case MFC_DEC_GETCONF_CRC_DATA:
+ if (mfc_ctx->MfcState != MFCINST_STATE_DEC_EXE) {
+ mfc_err("MFC_DEC_GETCONF_CRC_DATA : state is invalid\n");
+ return MFC_DEC_GETCONF_CRC_DATA;
+ }
+ get_cnf_arg->out_config_value[0] = READL(MFC_CRC_LUMA0);
+ get_cnf_arg->out_config_value[1] = READL(MFC_CRC_CHROMA0);
+ break;
+
+ default:
+ mfc_err("invalid config param\n");
+ return MFCINST_ERR_GET_CONF; /* peter, it should be mod. */
+ }
+
+ return MFCINST_RET_OK;
+}
+
+enum mfc_error_code mfc_set_config(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args)
+{
+ struct mfc_set_config_arg *set_cnf_arg;
+ set_cnf_arg = (struct mfc_set_config_arg *)args;
+
+ switch (set_cnf_arg->in_config_param) {
+ case MFC_DEC_SETCONF_POST_ENABLE:
+ if (mfc_ctx->MfcState >= MFCINST_STATE_DEC_INITIALIZE) {
+ mfc_err("MFC_DEC_SETCONF_POST_ENABLE : state is invalid\n");
+ return MFCINST_ERR_STATE_INVALID;
+ }
+
+ if ((set_cnf_arg->in_config_value[0] == 0) || (set_cnf_arg->in_config_value[0] == 1)) {
+ mfc_ctx->postEnable = set_cnf_arg->in_config_value[0];
+ } else {
+ mfc_warn("POST_ENABLE should be 0 or 1\n");
+ mfc_ctx->postEnable = 0;
+ }
+ break;
+
+ case MFC_DEC_SETCONF_EXTRA_BUFFER_NUM:
+ if (mfc_ctx->MfcState >= MFCINST_STATE_DEC_INITIALIZE) {
+ mfc_err("MFC_DEC_SETCONF_EXTRA_BUFFER_NUM : state is invalid\n");
+ return MFCINST_ERR_STATE_INVALID;
+ }
+ if ((set_cnf_arg->in_config_value[0] >= 0) || (set_cnf_arg->in_config_value[0] <= MFC_MAX_EXTRA_DPB)) {
+ mfc_ctx->extraDPB = set_cnf_arg->in_config_value[0];
+ } else {
+ mfc_warn("EXTRA_BUFFER_NUM should be between 0 and 5...It will be set 5 by default\n");
+ mfc_ctx->extraDPB = MFC_MAX_EXTRA_DPB;
+ }
+ break;
+
+ case MFC_DEC_SETCONF_DISPLAY_DELAY:
+ if (mfc_ctx->MfcState >= MFCINST_STATE_DEC_INITIALIZE) {
+ mfc_err("MFC_DEC_SETCONF_DISPLAY_DELAY : state is invalid\n");
+ return MFCINST_ERR_STATE_INVALID;
+ }
+
+ if ((set_cnf_arg->in_config_value[0] >= 0) || (set_cnf_arg->in_config_value[0] < 16)) {
+ mfc_ctx->displayDelay = set_cnf_arg->in_config_value[0];
+ mfc_debug("DISPLAY_DELAY Number = %d\n", mfc_ctx->displayDelay);
+ } else {
+ mfc_warn("DISPLAY_DELAY should be between 0 and 16\n");
+ mfc_ctx->displayDelay = 0;
+ }
+ break;
+
+ case MFC_DEC_SETCONF_IS_LAST_FRAME:
+ if (mfc_ctx->MfcState != MFCINST_STATE_DEC_EXE) {
+ mfc_err("MFC_DEC_SETCONF_IS_LAST_FRAME : state is invalid\n");
+ return MFCINST_ERR_STATE_INVALID;
+ }
+
+ if ((set_cnf_arg->in_config_value[0] == 0) || (set_cnf_arg->in_config_value[0] == 1)) {
+ mfc_ctx->endOfFrame = set_cnf_arg->in_config_value[0];
+ } else {
+ mfc_warn("IS_LAST_FRAME should be 0 or 1\n");
+ mfc_ctx->endOfFrame = 0;
+ }
+ break;
+
+ case MFC_DEC_SETCONF_SLICE_ENABLE:
+ if (mfc_ctx->MfcState >= MFCINST_STATE_DEC_INITIALIZE) {
+ mfc_err("MFC_DEC_SETCONF_SLICE_ENABLE : state is invalid\n");
+ return MFCINST_ERR_STATE_INVALID;
+ }
+
+ if ((set_cnf_arg->in_config_value[0] == 0) || (set_cnf_arg->in_config_value[0] == 1)) {
+ mfc_ctx->sliceEnable = set_cnf_arg->in_config_value[0];
+ } else {
+ mfc_warn("SLICE_ENABLE should be 0 or 1\n");
+ mfc_ctx->sliceEnable = 0;
+ }
+ break;
+
+ case MFC_DEC_SETCONF_CRC_ENABLE:
+ if (mfc_ctx->MfcState >= MFCINST_STATE_DEC_INITIALIZE) {
+ mfc_err("MFC_DEC_SETCONF_CRC_ENABLE : state is invalid\n");
+ return MFCINST_ERR_STATE_INVALID;
+ }
+
+ if ((set_cnf_arg->in_config_value[0] == 0) || (set_cnf_arg->in_config_value[0] == 1)) {
+ mfc_ctx->crcEnable = set_cnf_arg->in_config_value[0];
+ } else {
+ mfc_warn("CRC_ENABLE should be 0 or 1\n");
+ mfc_ctx->crcEnable = 0;
+ }
+ break;
+
+ case MFC_DEC_SETCONF_FIMV1_WIDTH_HEIGHT:
+ if (mfc_ctx->MfcState >= MFCINST_STATE_DEC_INITIALIZE) {
+ mfc_err("MFC_DEC_SETCONF_FIMV1_WIDTH_HEIGHT : state is invalid\n");
+ return MFCINST_ERR_STATE_INVALID;
+ }
+
+ mfc_ctx->widthFIMV1 = set_cnf_arg->in_config_value[0];
+ mfc_ctx->heightFIMV1 = set_cnf_arg->in_config_value[1];
+ break;
+
+ case MFC_ENC_SETCONF_FRAME_TYPE:
+ if (mfc_ctx->MfcState != MFCINST_STATE_ENC_EXE) {
+ mfc_err("MFC_ENC_SETCONF_FRAME_TYPE : state is invalid\n");
+ return MFCINST_ERR_STATE_INVALID;
+ }
+
+ if ((set_cnf_arg->in_config_value[0] >= DONT_CARE) && (set_cnf_arg->in_config_value[0] <= NOT_CODED)) {
+ mfc_ctx->forceSetFrameType = set_cnf_arg->in_config_value[0];
+ } else {
+ mfc_warn("FRAME_TYPE should be between 0 and 2\n");
+ mfc_ctx->forceSetFrameType = DONT_CARE;
+ }
+ break;
+
+ case MFC_ENC_SETCONF_ALLOW_FRAME_SKIP:
+ if (mfc_ctx->MfcState >= MFCINST_STATE_ENC_INITIALIZE) {
+ mfc_err("MFC_ENC_SETCONF_ALLOW_FRAME_SKIP : state is invalid\n");
+ return MFCINST_ERR_STATE_INVALID;
+ }
+
+ if (set_cnf_arg->in_config_value[0])
+ mfc_ctx->shared_mem.ext_enc_control = (mfc_ctx->shared_mem.ext_enc_control | (0x1 << 1));
+ break;
+
+ /* XXX: need to implement */
+ case MFC_ENC_SETCONF_CHANGE_FRAME_RATE:
+ if (mfc_ctx->MfcState != MFCINST_STATE_ENC_EXE) {
+ mfc_err("MFC_ENC_SETCONF_FRAME_TYPE : state is invalid\n");
+ return MFCINST_ERR_STATE_INVALID;
+ }
+ break;
+
+ /* XXX: need to implement */
+ case MFC_ENC_SETCONF_CHANGE_BIT_RATE:
+ if (mfc_ctx->MfcState != MFCINST_STATE_ENC_EXE) {
+ mfc_err("MFC_ENC_SETCONF_FRAME_TYPE : state is invalid\n");
+ return MFCINST_ERR_STATE_INVALID;
+ }
+ break;
+
+ default:
+ mfc_err("invalid config param\n");
+ return MFCINST_ERR_SET_CONF;
+ }
+
+ return MFCINST_RET_OK;
+}
+
+enum mfc_error_code mfc_set_sleep()
+{
+ if (mfc_cmd_host2risc(H2R_CMD_SLEEP, 0, 0, 0, 0) == false) {
+ mfc_err("R2H_CMD_SLEEP FAIL\n");
+ return MFCINST_SLEEP_FAIL;
+ }
+
+ if (mfc_wait_for_done(R2H_CMD_SLEEP_RET) != R2H_CMD_SLEEP_RET) {
+ mfc_err("R2H_CMD_SLEEP_RET FAIL\n");
+ return MFCINST_SLEEP_FAIL;
+ }
+
+ return MFCINST_RET_OK;
+}
+
+enum mfc_error_code mfc_set_wakeup()
+{
+ int ret;
+
+ if (mfc_cmd_host2risc(H2R_CMD_WAKEUP, 0, 0, 0, 0) == false) {
+ mfc_err("R2H_CMD_WAKEUP FAIL\n");
+ return MFCINST_WAKEUP_FAIL;
+ }
+
+ WRITEL(0x3ff, MFC_SW_RESET);
+
+ ret = mfc_wait_for_done(R2H_CMD_WAKEUP_RET);
+ if ((ret != R2H_CMD_WAKEUP_RET) && (ret != R2H_CMD_FW_STATUS_RET)) {
+ mfc_err("R2H_CMD_WAKEUP_RET FAIL\n");
+ return MFCINST_WAKEUP_FAIL;
+ }
+
+ return MFCINST_RET_OK;
+}
+
+static enum
+mfc_error_code mfc_alloc_context_buffer(struct mfc_inst_ctx *mfc_ctx, unsigned int mapped_addr,
+ unsigned int *context_addr, int *size)
+{
+ union mfc_args local_param;
+ enum mfc_error_code ret_code;
+ unsigned char *context_vir;
+
+ switch (mfc_ctx->MfcCodecType) {
+ case H264_ENC:
+ *size = H264ENC_CONTEXT_SIZE;
+ break;
+
+ case MPEG4_ENC:
+ *size = MPEG4ENC_CONTEXT_SIZE;
+ break;
+
+ case H263_ENC:
+ *size = H263ENC_CONTEXT_SIZE;
+ break;
+
+ case H264_DEC:
+ *size = H264DEC_CONTEXT_SIZE;
+ break;
+
+ case H263_DEC:
+ *size = H263DEC_CONTEXT_SIZE;
+ break;
+
+ case MPEG2_DEC:
+ *size = MPEG2DEC_CONTEXT_SIZE;
+ break;
+
+ case MPEG4_DEC:
+ case FIMV1_DEC:
+ case FIMV2_DEC:
+ case FIMV3_DEC:
+ case FIMV4_DEC:
+ *size = MPEG4DEC_CONTEXT_SIZE;
+ break;
+
+ case VC1_DEC:
+ case VC1RCV_DEC:
+ *size = VC1DEC_CONTEXT_SIZE;
+ break;
+
+ default:
+ return MFCINST_ERR_WRONG_CODEC_MODE;
+ }
+
+ memset(&local_param, 0, sizeof(local_param));
+ local_param.mem_alloc.buff_size = *size;
+ local_param.mem_alloc.mapped_addr = mapped_addr;
+
+ ret_code = mfc_allocate_buffer(mfc_ctx, &(local_param), 0);
+ if (ret_code < 0)
+ return ret_code;
+
+ /* Set mfc context to "0". */
+ context_vir = phys_to_virt(local_param.mem_alloc.out_paddr);
+ memset(context_vir, 0x0, local_param.mem_alloc.buff_size);
+
+ dmac_flush_range(context_vir, context_vir + local_param.mem_alloc.buff_size);
+
+ *context_addr = local_param.mem_alloc.out_paddr;
+
+ return ret_code;
+}
+
+void mfc_init_mem_inst_no(void)
+{
+ memset(&mfc_mem_inst_no, 0x00, sizeof(mfc_mem_inst_no));
+}
+
+int mfc_get_mem_inst_no(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < MFC_MAX_INSTANCE_NUM; i++) {
+ if (mfc_mem_inst_no[i] == 0) {
+ mfc_mem_inst_no[i] = 1;
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+void mfc_return_mem_inst_no(int inst_no)
+{
+ if ((inst_no >= 0) && (inst_no < MFC_MAX_INSTANCE_NUM))
+ mfc_mem_inst_no[inst_no] = 0;
+}
+
+bool mfc_is_running(void)
+{
+ unsigned int i;
+ bool ret = false;
+
+ for (i = 0; i < MFC_MAX_INSTANCE_NUM; i++) {
+ mfc_debug("mfc_mem_inst_no[%d] = %d\n", i, mfc_mem_inst_no[i]);
+ if (mfc_mem_inst_no[i] == 1)
+ ret = true;
+ }
+
+ return ret;
+}
+
+int mfc_set_state(struct mfc_inst_ctx *ctx, enum mfc_inst_state state)
+{
+ if (ctx->MfcState > state)
+ return -1;
+
+ ctx->MfcState = state;
+ return 0;
+}
+
+bool is_dec_codec(enum ssbsip_mfc_codec_type codec_type)
+{
+ switch (codec_type) {
+ case H264_DEC:
+ case VC1_DEC:
+ case MPEG4_DEC:
+ case XVID_DEC:
+ case MPEG1_DEC:
+ case MPEG2_DEC:
+ case H263_DEC:
+ case VC1RCV_DEC:
+ case FIMV1_DEC:
+ case FIMV2_DEC:
+ case FIMV3_DEC:
+ case FIMV4_DEC:
+ return true;
+
+ case H264_ENC:
+ case MPEG4_ENC:
+ case H263_ENC:
+ return false;
+
+ default:
+ return false;
+ }
+}
+
+
+
+
+
+/*
+ * Debugging Functions Definition
+ * tile_to_linear_4x2(..)
+ * calculate_seq_size(..)
+ * printk_mfc_init_info(..)
+ */
+
+
+#if DEBUG_MAKE_RAW
+static void write_file(char *filename, unsigned char *data, unsigned int nSize)
+{
+ struct file *file;
+ loff_t pos = 0;
+ int fd;
+ mm_segment_t old_fs;
+
+ invalidate_kernel_vmap_range(data, nSize);
+
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ fd = sys_open(filename, O_WRONLY|O_CREAT, 0644);
+ if (fd >= 0) {
+ sys_write(fd, data, nSize);
+ file = fget(fd);
+ if (file) {
+ vfs_write(file, data, nSize, &pos);
+ fput(file);
+ }
+ sys_close(fd);
+ } else {
+ mfc_err("........Open fail : %d\n", fd);
+ }
+ set_fs(old_fs);
+
+ dmac_flush_range(data, data + nSize);
+
+}
+
+static int tile_4x2_read(int x_size, int y_size, int x_pos, int y_pos)
+{
+ int pixel_x_m1, pixel_y_m1;
+ int roundup_x, roundup_y;
+ int linear_addr0, linear_addr1, bank_addr ;
+ int x_addr;
+ int trans_addr;
+
+ pixel_x_m1 = x_size - 1;
+ pixel_y_m1 = y_size - 1;
+
+ roundup_x = ((pixel_x_m1 >> 7) + 1);
+ roundup_y = ((pixel_x_m1 >> 6) + 1);
+
+ x_addr = (x_pos >> 2);
+
+ if ((y_size <= y_pos+32) && (y_pos < y_size) &&
+ (((pixel_y_m1 >> 5) & 0x1) == 0) && (((y_pos >> 5) & 0x1) == 0)) {
+ linear_addr0 = (((y_pos & 0x1f) << 4) | (x_addr & 0xf));
+ linear_addr1 = (((y_pos >> 6) & 0xff) * roundup_x + ((x_addr >> 6) & 0x3f));
+
+ if (((x_addr >> 5) & 0x1) == ((y_pos >> 5) & 0x1))
+ bank_addr = ((x_addr >> 4) & 0x1);
+ else
+ bank_addr = 0x2 | ((x_addr >> 4) & 0x1);
+ } else {
+ linear_addr0 = (((y_pos & 0x1f) << 4) | (x_addr & 0xf));
+ linear_addr1 = (((y_pos >> 6) & 0xff) * roundup_x + ((x_addr >> 5) & 0x7f));
+
+ if (((x_addr >> 5) & 0x1) == ((y_pos >> 5) & 0x1))
+ bank_addr = ((x_addr >> 4) & 0x1);
+ else
+ bank_addr = 0x2 | ((x_addr >> 4) & 0x1);
+ }
+
+ linear_addr0 = linear_addr0 << 2;
+ trans_addr = (linear_addr1 << 13) | (bank_addr << 11) | linear_addr0;
+
+ return trans_addr;
+}
+
+
+static void copy16(unsigned char *p_linear_addr, unsigned char *p_tiled_addr, int mm, int nn)
+{
+ p_linear_addr[mm] = p_tiled_addr[nn];
+ p_linear_addr[mm + 1] = p_tiled_addr[nn + 1];
+ p_linear_addr[mm + 2] = p_tiled_addr[nn + 2];
+ p_linear_addr[mm + 3] = p_tiled_addr[nn + 3];
+
+ p_linear_addr[mm + 4] = p_tiled_addr[nn + 4];
+ p_linear_addr[mm + 5] = p_tiled_addr[nn + 5];
+ p_linear_addr[mm + 6] = p_tiled_addr[nn + 6];
+ p_linear_addr[mm + 7] = p_tiled_addr[nn + 7];
+
+ p_linear_addr[mm + 8] = p_tiled_addr[nn + 8];
+ p_linear_addr[mm + 9] = p_tiled_addr[nn + 9];
+ p_linear_addr[mm + 10] = p_tiled_addr[nn + 10];
+ p_linear_addr[mm + 11] = p_tiled_addr[nn + 11];
+
+ p_linear_addr[mm + 12] = p_tiled_addr[nn + 12];
+ p_linear_addr[mm + 13] = p_tiled_addr[nn + 13];
+ p_linear_addr[mm + 14] = p_tiled_addr[nn + 14];
+ p_linear_addr[mm + 15] = p_tiled_addr[nn + 15];
+}
+
+
+static void
+tile_to_linear_4x2(unsigned char *p_linear_addr, unsigned char *p_tiled_addr,
+ unsigned int x_size, unsigned int y_size)
+{
+ int trans_addr;
+ unsigned int i, j, k, nn, mm, index;
+
+ /*. TILE 4x2 test */
+ for (i = 0; i < y_size; i = i + 16) {
+ for (j = 0; j < x_size; j = j + 16) {
+ trans_addr = tile_4x2_read(x_size, y_size, j, i);
+ index = i*x_size + j;
+
+ k = 0; nn = trans_addr + (k << 6); mm = index;
+ copy16(p_linear_addr, p_tiled_addr, mm, nn);
+
+ k = 1; nn = trans_addr + (k << 6); mm += x_size;
+ copy16(p_linear_addr, p_tiled_addr, mm, nn);
+
+ k = 2; nn = trans_addr + (k << 6); mm += x_size;
+ copy16(p_linear_addr, p_tiled_addr, mm, nn);
+
+ k = 3; nn = trans_addr + (k << 6); mm += x_size;
+ copy16(p_linear_addr, p_tiled_addr, mm, nn);
+
+ k = 4; nn = trans_addr + (k << 6); mm += x_size;
+ copy16(p_linear_addr, p_tiled_addr, mm, nn);
+
+ k = 5; nn = trans_addr + (k << 6); mm += x_size;
+ copy16(p_linear_addr, p_tiled_addr, mm, nn);
+
+ k = 6; nn = trans_addr + (k << 6); mm += x_size;
+ copy16(p_linear_addr, p_tiled_addr, mm, nn);
+
+ k = 7; nn = trans_addr + (k << 6); mm += x_size;
+ copy16(p_linear_addr, p_tiled_addr, mm, nn);
+
+ k = 8; nn = trans_addr + (k << 6); mm += x_size;
+ copy16(p_linear_addr, p_tiled_addr, mm, nn);
+
+ k = 9; nn = trans_addr + (k << 6); mm += x_size;
+ copy16(p_linear_addr, p_tiled_addr, mm, nn);
+
+ k = 10; nn = trans_addr + (k << 6); mm += x_size;
+ copy16(p_linear_addr, p_tiled_addr, mm, nn);
+
+ k = 11; nn = trans_addr + (k << 6); mm += x_size;
+ copy16(p_linear_addr, p_tiled_addr, mm, nn);
+
+ k = 12; nn = trans_addr + (k << 6); mm += x_size;
+ copy16(p_linear_addr, p_tiled_addr, mm, nn);
+
+ k = 13; nn = trans_addr + (k << 6); mm += x_size;
+ copy16(p_linear_addr, p_tiled_addr, mm, nn);
+
+ k = 14; nn = trans_addr + (k << 6); mm += x_size;
+ copy16(p_linear_addr, p_tiled_addr, mm, nn);
+
+ k = 15; nn = trans_addr + (k << 6); mm += x_size;
+ copy16(p_linear_addr, p_tiled_addr, mm, nn);
+
+ }
+ }
+}
+#endif
+
+
+
+#if ENABLE_CHECK_SEQ_HEADER
+static int calculate_seq_size(mfc_args *args)
+{
+ int nn = 0;
+ int nCnt = 0;
+ unsigned char nSum = 0;
+ unsigned char *stream_vir;
+
+ stream_vir = phys_to_virt(args->dec_init.in_strm_buf);
+ if (args->dec_init.in_strm_size > 31) {
+ for (nn = 0; nn < args->dec_init.in_strm_size - 4; nn++) {
+ nSum = (unsigned char)(((*(stream_vir + nn)) << 1) + ((*(stream_vir + nn + 1)) << 1)
+ + ((*(stream_vir + nn + 2)) << 1) + (*(stream_vir+nn+3)));
+ if (nSum == 0x1) {
+ nCnt++;
+ }
+
+ if (nCnt == 3) {
+ mfc_info("After Stream Size : %d , nCnt = %d\n", args->dec_init.in_strm_size, nCnt);
+ return nn;
+ }
+ }
+ }
+
+ return args->dec_init.in_strm_size;
+}
+#endif
+
+
+#if ENABLE_DEBUG_MFC_INIT
+void printk_mfc_init_info(mfc_inst_ctx *mfc_ctx, mfc_args *args)
+{
+ int nn = 0;
+ unsigned char *stream_vir;
+
+ mfc_info("MFC Decoder/Encoder Init Information\n");
+ mfc_info("[InstNo : %d], [DPBCnt : %d], [totalDPBCnt : %d], [extraDPB : %d], [displayDelay : %d],\n",
+ mfc_ctx->InstNo, mfc_ctx->DPBCnt, mfc_ctx->totalDPBCnt, mfc_ctx->extraDPB, mfc_ctx->displayDelay);
+ mfc_info("[img_width : %d], [img_height : %d], [MfcCodecType : %d], [MfcState : %d]\n",
+ mfc_ctx->img_width, mfc_ctx->img_height, mfc_ctx->MfcCodecType, mfc_ctx->MfcState);
+
+ mfc_info("Input Stream Buffer Information\n");
+ mfc_info("[in_strm_size : %d], [in_strm_buf : %d]\n",
+ args->dec_init.in_strm_size, args->dec_init.in_strm_buf);
+
+ stream_vir = phys_to_virt(args->dec_init.in_strm_buf);
+ if (args->dec_init.in_strm_size > 0) {
+ mfc_info("Input Stream Buffer\n");
+ for (nn = 0; nn < 40; nn++)
+ printk("%02x ", *(stream_vir+nn));
+ printk("\n");
+ }
+
+}
+#endif
+
+
+#ifdef ENABLE_DEBUG_DEC_EXE_INTR_ERR
+#if ENABLE_DEBUG_DEC_EXE_INTR_ERR
+void printk_mfc_dec_exe_info(struct mfc_inst_ctx *mfc_ctx, struct mfc_dec_exe_arg *dec_arg)
+{
+ int nn = 0;
+ unsigned char *stream_vir;
+
+ mfc_info("MFC Decoder/Encoder Exe Information\n");
+ mfc_info("[InstNo : %d], [DPBCnt : %d], [totalDPBCnt : %d], [extraDPB : %d], [displayDelay : %d],\n",
+ mfc_ctx->InstNo, mfc_ctx->DPBCnt, mfc_ctx->totalDPBCnt, mfc_ctx->extraDPB, mfc_ctx->displayDelay);
+ mfc_info("[img_width : %d], [img_height : %d], [MfcCodecType : %d], [MfcState : %d], [FrameType: %d]\n",
+ mfc_ctx->img_width, mfc_ctx->img_height, mfc_ctx->MfcCodecType, mfc_ctx->MfcState, mfc_ctx->FrameType);
+
+ mfc_info("Input Stream Buffer Information\n");
+ mfc_info("[in_strm_size : %d], [in_strm_buf : %d]\n",
+ dec_arg->in_strm_size, dec_arg->in_strm_buf);
+
+ stream_vir = phys_to_virt(dec_arg->in_strm_buf);
+ if (dec_arg->in_strm_size > 0) {
+ mfc_info("Input Stream Buffer\n");
+ for (nn = 0; nn < 50; nn++)
+ printk("%02x ", *(stream_vir+nn));
+ printk("\n");
+ }
+}
+
+void
+makefile_mfc_dec_err_info(struct mfc_inst_ctx *mfc_ctx,
+ struct mfc_dec_exe_arg *dec_arg, int nReturnErrCode)
+{
+ char fileName0[50];
+ char fileName1[50];
+ unsigned char *ctx_virbuf;
+ unsigned char *mfc_dec_in_base_vaddr;
+
+ mframe_cnt++;
+
+ if ((nReturnErrCode < 145) || (nReturnErrCode == 300)) {
+ mIsDangerError = 1;
+ printk_mfc_dec_exe_info(mfc_ctx, dec_arg);
+ }
+
+ memset(fileName0, 0, 50);
+ memset(fileName1, 0, 50);
+
+ sprintf(fileName0, "/data/dec_in/mfc_decexe_instream_%d_%d.raw", nReturnErrCode, mframe_cnt);
+ sprintf(fileName1, "/data/dec_in/mfc_decexe_mfcctx_%d_%d.bin", nReturnErrCode, mframe_cnt);
+
+ mfc_dec_in_base_vaddr = phys_to_virt(dec_arg->in_strm_buf);
+ ctx_virbuf = phys_to_virt(mcontext_addr);
+
+ write_file(fileName0, mfc_dec_in_base_vaddr, dec_arg->in_strm_size);
+ write_file(fileName1, ctx_virbuf, mcontext_size);
+
+}
+
+
+void makefile_mfc_decinit_err_info(struct mfc_inst_ctx *mfc_ctx, struct mfc_dec_init_arg *decinit_arg, int nReturnErrCode)
+{
+ char fileName0[50];
+ char fileName1[50];
+ unsigned char *ctx_virbuf;
+ unsigned char *mfc_dec_in_base_vaddr;
+
+ mframe_cnt++;
+
+ pr_info("makefile_mfc_decinit_err_info : in_strm_size(%d)\n", decinit_arg->in_strm_size);
+
+ memset(fileName0, 0, 50);
+ memset(fileName1, 0, 50);
+
+ sprintf(fileName0, "/data/dec_in/mfc_decinit_instream_%d_%d.raw", nReturnErrCode, mframe_cnt);
+ sprintf(fileName1, "/data/dec_in/mfc_decinit_mfcctx_%d_%d.bin", nReturnErrCode, mframe_cnt);
+
+ mfc_dec_in_base_vaddr = phys_to_virt(decinit_arg->in_strm_buf);
+ ctx_virbuf = phys_to_virt(mcontext_addr);
+
+ write_file(fileName0, mfc_dec_in_base_vaddr, decinit_arg->in_strm_size);
+ write_file(fileName1, ctx_virbuf, mcontext_size);
+}
+#endif
+#endif
+
+#ifdef ENABLE_DEBUG_ENC_EXE_INTR_ERR
+#if ENABLE_DEBUG_ENC_EXE_INTR_ERR
+void makefile_mfc_enc_err_info(struct mfc_enc_exe_arg *enc_arg)
+{
+ int nFrameSize = 0;
+ char fileName[50];
+ unsigned char *mfc_enc_in_base_Y_vaddr;
+ unsigned char *mfc_enc_in_base_CbCr_vaddr;
+
+ mframe_cnt++;
+
+ memset(fileName, 0, 50);
+ sprintf(fileName, "/data/enc_in/mfc_in_%04d.yuv", mframe_cnt);
+ nFrameSize = mImgHight * mImgWidth * 3/2;
+
+ mfc_enc_in_base_Y_vaddr = phys_to_virt(enc_arg->in_Y_addr);
+ mfc_enc_in_base_CbCr_vaddr = phys_to_virt(enc_arg->in_CbCr_addr);
+
+ mfc_debug("enc_arg->in_Y_addr : 0x%08x enc_arg->in_Y_addr_vir :0x%08x\r\n",
+ enc_arg->in_Y_addr, mfc_enc_in_base_Y_vaddr);
+
+ tile_to_linear_4x2(pResLinearbuf, mfc_enc_in_base_Y_vaddr,
+ mImgWidth, mImgHight);
+ tile_to_linear_4x2(pResLinearbuf + (mImgHight * mImgWidth),
+ mfc_enc_in_base_CbCr_vaddr, mImgWidth, mImgHight/2);
+ write_file(fileName, pResLinearbuf, nFrameSize);
+
+}
+#endif
+#endif
+
+
+static int CheckMPEG4StartCode(unsigned char *src_mem, unsigned int remainSize)
+{
+ unsigned int index = 0;
+
+ for (index = 0; index < remainSize-3; index++) {
+ if ((src_mem[index] == 0x00)
+ && (src_mem[index+1] == 0x00)
+ && (src_mem[index+2] == 0x01))
+ return index;
+ }
+
+ return -1;
+}
+
+#if ENABLE_CHECK_START_CODE
+static int CheckDecStartCode(unsigned char *src_mem, unsigned int nstreamSize, enum ssbsip_mfc_codec_type nCodecType)
+{
+ unsigned int index = 0;
+ /* Check Start Code within "isearchSize" bytes. */
+ unsigned int isearchSize = 20;
+ unsigned int nShift = 0;
+ unsigned char nFlag = 0xFF;
+
+ if (nCodecType == H263_DEC) {
+ nFlag = 0x08;
+ nShift = 4;
+ } else if (nCodecType == MPEG4_DEC) {
+ nFlag = 0x01;
+ nShift = 0;
+ } else if (nCodecType == H264_DEC) {
+ nFlag = 0x01;
+ nShift = 0;
+ } else {
+ nFlag = 0xFF;
+ }
+
+ if (nFlag != 0xFF) {
+ if (nstreamSize > 3) {
+ if (nstreamSize > isearchSize) {
+ for (index = 0; index < isearchSize-3; index++) {
+ if ((src_mem[index] == 0x00)
+ && (src_mem[index+1] == 0x00)
+ && ((src_mem[index+2] >> nShift) == nFlag))
+ return index;
+ }
+ } else {
+ for (index = 0; index < nstreamSize - 3; index++) {
+ if ((src_mem[index] == 0x00)
+ && (src_mem[index+1] == 0x00)
+ && ((src_mem[index+2] >> nShift) == nFlag))
+ return index;
+ }
+ }
+ } else {
+ return -1;
+ }
+ } else {
+ return 0;
+ }
+
+ return -1;
+}
+#endif
+
+#if ENABLE_CHECK_NULL_STREAM
+static int CheckNullStream(unsigned char *src_mem, unsigned int streamSize)
+{
+ unsigned int temp = 0;
+ unsigned int nn;
+
+ if (streamSize < 30) {
+ for (nn = 0; nn < streamSize; nn++)
+ temp += src_mem[nn];
+ } else {
+ for (nn = 0; nn < 10; nn++)
+ temp += src_mem[nn];
+
+ if (temp == 0) {
+ for (nn = streamSize-10; nn < streamSize; nn++)
+ temp += src_mem[nn];
+ }
+ }
+
+ if (temp == 0) {
+ mfc_debug("Null Stream......Error\n");
+ return -1;
+ }
+
+ return 0;
+
+}
+#endif
+
+#if ENABLE_MFC_REGISTER_DEBUG
+void mfc_fw_debug(mfc_wait_done_type command)
+{
+ mfc_err("=== MFC FW Debug (Cmd: %d)"
+ "(Ver: 0x%08x) ===\n", command, READL(0x58));
+ mfc_err("=== (0x64: 0x%08x) (0x68: 0x%08x)"
+ "(0xE4: 0x%08x) (0xE8: 0x%08x)\n",
+ READL(0x64), READL(0x68), READL(0xe4), READL(0xe8));
+ mfc_err("=== (0xF0: 0x%08x) (0xF4: 0x%08x)"
+ "(0xF8: 0x%08x) (0xFC: 0x%08x)\n",
+ READL(0xf0), READL(0xf4), READL(0xf8), READL(0xfc));
+}
+#endif
diff --git a/drivers/media/video/samsung/mfc50/mfc_opr.h b/drivers/media/video/samsung/mfc50/mfc_opr.h
new file mode 100644
index 0000000..18cfe53
--- /dev/null
+++ b/drivers/media/video/samsung/mfc50/mfc_opr.h
@@ -0,0 +1,204 @@
+/*
+ * drivers/media/video/samsung/mfc50/mfc_opr.h
+ *
+ * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
+ *
+ * Jaeryul Oh, Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * Change Logs
+ * 2009.09.14 - Beautify source code (Key Young, Park)
+ * 2009.09.21 - Implement clock & power gating.
+ * including suspend & resume fuction. (Key Young, Park)
+ * 2009.11.04 - remove mfc_common.[ch]
+ * seperate buffer alloc & set (Key Young, Park)
+ *
+ * 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 _MFC_OPR_H_
+#define _MFC_OPR_H_
+
+#include <plat/regs-mfc.h>
+#include "mfc_errorno.h"
+#include "mfc_interface.h"
+#include "mfc_shared_mem.h"
+
+#define MFC_WARN_START_NO 145
+#define MFC_ERR_START_NO 1
+
+
+#define INT_MFC_FW_DONE (0x1 << 5)
+#define INT_MFC_DMA_DONE (0x1 << 7)
+#define INT_MFC_FRAME_DONE (0x1 << 8)
+/* Interrupt on/off (0x500) */
+#define INT_ENABLE_BIT (0 << 0)
+#define INT_DISABLE_BIT (1 << 0)
+/* Interrupt mode (0x504) */
+#define INT_LEVEL_BIT (0 << 0)
+#define INT_PULSE_BIT (1 << 0)
+
+/* Command Types */
+#define MFC_CHANNEL_SET 0
+#define MFC_CHANNEL_READ 1
+#define MFC_CHANNEL_END 2
+#define MFC_INIT_CODEC 3
+#define MFC_FRAME_RUN 4
+#define MFC_SLEEP 6
+#define MFC_WAKEUP 7
+
+/* DPB Count */
+#define NUM_MPEG4_DPB 2
+#define NUM_POST_DPB 3
+#define NUM_VC1_DPB 4
+
+#define ALIGN_TO_16B(x) ((((x) + (1 << 4) - 1) >> 4) << 4)
+#define ALIGN_TO_32B(x) ((((x) + (1 << 5) - 1) >> 5) << 5)
+#define ALIGN_TO_64B(x) ((((x) + (1 << 6) - 1) >> 6) << 6)
+#define ALIGN_TO_128B(x) ((((x) + (1 << 7) - 1) >> 7) << 7)
+#define ALIGN_TO_2KB(x) ((((x) + (1 << 11) - 1) >> 11) << 11)
+#define ALIGN_TO_4KB(x) ((((x) + (1 << 12) - 1) >> 12) << 12)
+#define ALIGN_TO_8KB(x) ((((x) + (1 << 13) - 1) >> 13) << 13)
+#define ALIGN_TO_64KB(x) ((((x) + (1 << 16) - 1) >> 16) << 16)
+#define ALIGN_TO_128KB(x) ((((x) + (1 << 17) - 1) >> 17) << 17)
+
+#define PIXEL_CACHE_ON_ONLY_P_PICTURE 0
+#define PIXEL_CACHE_ON_ONLY_B_PICTURE 1
+#define PIXEL_CACHE_ON_BOTH_P_B_PICTURE 2
+#define PIXEL_CACHE_DISABLE 3
+
+#define BOUND_MEMORY_SIZE 921600
+
+enum mfc_inst_state {
+ MFCINST_STATE_NULL = 0,
+
+ /* Instance is created */
+ MFCINST_STATE_OPENED = 10,
+
+ /* channel_set and init_codec is completed */
+ MFCINST_STATE_DEC_INITIALIZE = 20,
+
+ MFCINST_STATE_DEC_EXE = 30,
+ MFCINST_STATE_DEC_EXE_DONE,
+
+ /* Instance is initialized for encoding */
+ MFCINST_STATE_ENC_INITIALIZE = 40,
+ MFCINST_STATE_ENC_EXE,
+ MFCINST_STATE_ENC_EXE_DONE
+};
+
+enum mfc_mem_type {
+ MEM_STRUCT_LINEAR = 0,
+ MEM_STRUCT_TILE_ENC = 3 /* 64x32 */
+};
+
+enum mfc_dec_type {
+ SEQ_HEADER = 1,
+ FRAME = 2,
+ LAST_FRAME = 3,
+ INIT_BUFFER = 4,
+ FRAME_RUN_REALLOC = 5,
+};
+
+enum mfc_facade_cmd {
+ H2R_CMD_EMPTY = 0,
+ H2R_CMD_OPEN_INSTANCE = 1,
+ H2R_CMD_CLOSE_INSTANCE = 2,
+ H2R_CMD_SYS_INIT = 3,
+ H2R_CMD_SLEEP = 5,
+ H2R_CMD_WAKEUP = 6,
+};
+
+enum mfc_wait_done_type {
+ R2H_CMD_EMPTY = 0,
+ R2H_CMD_OPEN_INSTANCE_RET = 1,
+ R2H_CMD_CLOSE_INSTANCE_RET = 2,
+ R2H_CMD_ERROR_RET = 3,
+ R2H_CMD_SEQ_DONE_RET = 4,
+ R2H_CMD_FRAME_DONE_RET = 5,
+ R2H_CMD_SLICE_DONE_RET = 6,
+ R2H_CMD_ENC_COMPLETE_RET = 6,
+ R2H_CMD_SYS_INIT_RET = 8,
+ R2H_CMD_FW_STATUS_RET = 9,
+ R2H_CMD_SLEEP_RET = 10,
+ R2H_CMD_WAKEUP_RET = 11,
+ R2H_CMD_INIT_BUFFERS_RET = 15,
+ R2H_CMD_EDFU_INT_RET = 16,
+ R2H_CMD_DECODE_ERR_RET = 32
+};
+
+enum mfc_display_status {
+ DECODING_ONLY = 0,
+ DECODING_DISPLAY = 1,
+ DISPLAY_ONLY = 2,
+ DECODING_EMPTY = 3
+};
+
+/* In case of decoder */
+enum mfc_frame_type {
+ MFC_RET_FRAME_NOT_SET = 0,
+ MFC_RET_FRAME_I_FRAME = 1,
+ MFC_RET_FRAME_P_FRAME = 2,
+ MFC_RET_FRAME_B_FRAME = 3
+};
+
+struct mfc_inst_ctx {
+ int InstNo;
+ unsigned int DPBCnt;
+ unsigned int totalDPBCnt;
+ unsigned int extraDPB;
+ unsigned int displayDelay;
+ unsigned int postEnable;
+ unsigned int endOfFrame;
+ unsigned int forceSetFrameType;
+ unsigned int img_width;
+ unsigned int img_height;
+ unsigned int dwAccess; /* for Power Management. */
+ unsigned int IsPackedPB;
+ unsigned int interlace_mode;
+ unsigned int sliceEnable;
+ unsigned int crcEnable;
+ unsigned int widthFIMV1;
+ unsigned int heightFIMV1;
+ int mem_inst_no;
+ enum mfc_frame_type FrameType;
+ enum ssbsip_mfc_codec_type MfcCodecType;
+ enum mfc_inst_state MfcState;
+ unsigned int port0_mmap_size;
+ unsigned int codec_buff_paddr;
+ unsigned int pred_buff_paddr;
+ struct mfc_frame_buf_arg dec_dpb_buff_paddr;
+ unsigned int shared_mem_paddr;
+ unsigned int shared_mem_vaddr;
+ unsigned int IsStartedIFrame;
+ struct mfc_shared_mem shared_mem;
+ enum mfc_buffer_type buf_type;
+ unsigned int desc_buff_paddr;
+};
+
+int mfc_load_firmware(const unsigned char *data, size_t size);
+bool mfc_cmd_reset(void);
+
+enum mfc_error_code mfc_init_hw(void);
+enum mfc_error_code mfc_init_encode(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args);
+enum mfc_error_code mfc_exe_encode(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args);
+enum mfc_error_code mfc_init_decode(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args);
+enum mfc_error_code mfc_exe_decode(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args);
+enum mfc_error_code mfc_get_config(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args);
+enum mfc_error_code mfc_set_config(struct mfc_inst_ctx *mfc_ctx, union mfc_args *args);
+enum mfc_error_code mfc_deinit_hw(struct mfc_inst_ctx *mfc_ctx);
+enum mfc_error_code mfc_set_sleep(void);
+enum mfc_error_code mfc_set_wakeup(void);
+
+int mfc_return_inst_no(int inst_no, enum ssbsip_mfc_codec_type codec_type);
+int mfc_set_state(struct mfc_inst_ctx *ctx, enum mfc_inst_state state);
+void mfc_init_mem_inst_no(void);
+int mfc_get_mem_inst_no(void);
+void mfc_return_mem_inst_no(int inst_no);
+bool mfc_is_running(void);
+bool is_dec_codec(enum ssbsip_mfc_codec_type codec_type);
+
+
+#endif /* _MFC_OPR_H_ */
diff --git a/drivers/media/video/samsung/mfc50/mfc_shared_mem.c b/drivers/media/video/samsung/mfc50/mfc_shared_mem.c
new file mode 100644
index 0000000..813c2db
--- /dev/null
+++ b/drivers/media/video/samsung/mfc50/mfc_shared_mem.c
@@ -0,0 +1,123 @@
+/*
+ * drivers/media/video/samsung/mfc50/mfc_shared_mem.c
+ *
+ * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
+ *
+ * Key-Young Park, Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * Change Logs
+ * 2009.10.08 - Apply 9/30 firmware(Key Young, Park)
+ * 2009.11.06 - clean & invalidate shared mem area (Key Young, Park)
+ *
+ * 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/delay.h>
+#include <linux/errno.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/io.h>
+#include <asm/cacheflush.h>
+
+#include "mfc_shared_mem.h"
+#include "mfc_logmsg.h"
+
+#define DEBUG_ENABLE 0
+
+static inline void mfc_write_shared_mem_item(unsigned int host_wr_addr, unsigned int addr, unsigned int value)
+{
+ MEM_WRITE(host_wr_addr + addr, value);
+}
+
+static inline unsigned int mfc_read_shared_mem_item(unsigned int host_wr_addr, unsigned int addr)
+{
+ return MEM_READ(host_wr_addr + addr);
+}
+
+void mfc_write_shared_mem(unsigned int host_wr_addr, struct mfc_shared_mem *shared_mem)
+{
+ mfc_write_shared_mem_item(host_wr_addr, RC_CONTROL_ENABLE, 1);/* RC_CONTROL_CONFIG : enable (1), disable(0) */
+
+ mfc_write_shared_mem_item(host_wr_addr, SET_FRAME_TAG, shared_mem->set_frame_tag);
+ mfc_write_shared_mem_item(host_wr_addr, START_BYTE_NUM, shared_mem->start_byte_num);
+ mfc_write_shared_mem_item(host_wr_addr, EXT_ENC_CONTROL, shared_mem->ext_enc_control);
+ mfc_write_shared_mem_item(host_wr_addr, ENC_PARAM_CHANGE, shared_mem->enc_param_change);
+ mfc_write_shared_mem_item(host_wr_addr, VOP_TIMING, shared_mem->vop_timing);
+ mfc_write_shared_mem_item(host_wr_addr, HEC_PERIOD, shared_mem->hec_period);
+ mfc_write_shared_mem_item(host_wr_addr, P_B_FRAME_QP, shared_mem->P_B_frame_qp);
+ mfc_write_shared_mem_item(host_wr_addr, METADATA_ENABLE, shared_mem->metadata_enable);
+ mfc_write_shared_mem_item(host_wr_addr, EXT_METADATA_START_ADDR, shared_mem->ext_metadata_start_addr);
+ mfc_write_shared_mem_item(host_wr_addr, PUT_EXTRADATA, shared_mem->put_extradata);
+ mfc_write_shared_mem_item(host_wr_addr, DBG_INFO_INPUT0, shared_mem->dbg_info_input0);
+ mfc_write_shared_mem_item(host_wr_addr, DBG_INFO_INPUT1, shared_mem->dbg_info_input1);
+ mfc_write_shared_mem_item(host_wr_addr, ALLOCATED_LUMA_DPB_SIZE, shared_mem->allocated_luma_dpb_size);
+ mfc_write_shared_mem_item(host_wr_addr, ALLOCATED_CHROMA_DPB_SIZE, shared_mem->allocated_chroma_dpb_size);
+ mfc_write_shared_mem_item(host_wr_addr, ALLOCATED_MV_SIZE, shared_mem->allocated_mv_size);
+ mfc_write_shared_mem_item(host_wr_addr, P720_LIMIT_ENABLE, shared_mem->p720_limit_enable);
+
+ dmac_flush_range((void *)host_wr_addr, (void *)host_wr_addr + SHARED_MEM_MAX);
+
+#if DEBUG_ENABLE
+ mfc_print_shared_mem(host_wr_addr);
+#endif
+}
+
+void mfc_read_shared_mem(unsigned int host_wr_addr, struct mfc_shared_mem *shared_mem)
+{
+ invalidate_kernel_vmap_range((void *)host_wr_addr, SHARED_MEM_MAX);
+
+ shared_mem->extended_decode_status = mfc_read_shared_mem_item(host_wr_addr, EXTENEDED_DECODE_STATUS);
+ shared_mem->get_frame_tag_top = mfc_read_shared_mem_item(host_wr_addr, GET_FRAME_TAG_TOP);
+ shared_mem->get_frame_tag_bot = mfc_read_shared_mem_item(host_wr_addr, GET_FRAME_TAG_BOT);
+ shared_mem->pic_time_top = mfc_read_shared_mem_item(host_wr_addr, PIC_TIME_TOP);
+ shared_mem->pic_time_bot = mfc_read_shared_mem_item(host_wr_addr, PIC_TIME_BOT);
+ shared_mem->start_byte_num = mfc_read_shared_mem_item(host_wr_addr, START_BYTE_NUM);
+ shared_mem->dec_frm_size = mfc_read_shared_mem_item(host_wr_addr, DEC_FRM_SIZE);
+ shared_mem->crop_info1 = mfc_read_shared_mem_item(host_wr_addr, CROP_INFO1);
+ shared_mem->crop_info2 = mfc_read_shared_mem_item(host_wr_addr, CROP_INFO2);
+ shared_mem->metadata_status = mfc_read_shared_mem_item(host_wr_addr, METADATA_STATUS);
+ shared_mem->metadata_display_index = mfc_read_shared_mem_item(host_wr_addr, METADATA_DISPLAY_INDEX);
+ shared_mem->dbg_info_output0 = mfc_read_shared_mem_item(host_wr_addr, DBG_INFO_OUTPUT0);
+ shared_mem->dbg_info_output1 = mfc_read_shared_mem_item(host_wr_addr, DBG_INFO_OUTPUT1);
+
+#if DEBUG_ENABLE
+ mfc_print_shared_mem(host_wr_addr);
+#endif
+}
+
+void mfc_print_shared_mem(unsigned int host_wr_addr)
+{
+ mfc_info("set_frame_tag = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, SET_FRAME_TAG));
+ mfc_info("start_byte_num = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, START_BYTE_NUM));
+ mfc_info("ext_enc_control = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, EXT_ENC_CONTROL));
+ mfc_info("enc_param_change = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, ENC_PARAM_CHANGE));
+ mfc_info("vop_timing = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, VOP_TIMING));
+ mfc_info("hec_period = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, HEC_PERIOD));
+ mfc_info("p_b_frame_qp = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, P_B_FRAME_QP));
+ mfc_info("metadata_enable = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, METADATA_ENABLE));
+ mfc_info("ext_metadata_start_addr= 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, EXT_METADATA_START_ADDR));
+ mfc_info("put_extradata = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, PUT_EXTRADATA));
+ mfc_info("dbg_info_input0 = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, DBG_INFO_INPUT0));
+ mfc_info("dbg_info_input1 = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, DBG_INFO_INPUT1));
+ mfc_info("luma_dpb_size = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, ALLOCATED_LUMA_DPB_SIZE));
+ mfc_info("chroma_dpb_size = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, ALLOCATED_CHROMA_DPB_SIZE));
+ mfc_info("mv_size = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, ALLOCATED_MV_SIZE));
+ mfc_info("extended_decode_status = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, EXTENEDED_DECODE_STATUS));
+ mfc_info("get_frame_tag_top = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, GET_FRAME_TAG_TOP));
+ mfc_info("get_frame_tag_bot = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, GET_FRAME_TAG_BOT));
+ mfc_info("pic_time_top = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, PIC_TIME_TOP));
+ mfc_info("pic_time_bot = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, PIC_TIME_BOT));
+ mfc_info("start_byte_num = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, START_BYTE_NUM));
+ mfc_info("dec_frm_size = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, DEC_FRM_SIZE));
+ mfc_info("crop_info1 = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, CROP_INFO1));
+ mfc_info("crop_info2 = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, CROP_INFO2));
+ mfc_info("metadata_status = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, METADATA_STATUS));
+ mfc_info("metadata_display_index = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, METADATA_DISPLAY_INDEX));
+ mfc_info("dbg_info_output0 = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, DBG_INFO_OUTPUT0));
+ mfc_info("dbg_info_output1 = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, DBG_INFO_OUTPUT1));
+ mfc_info("720p_limit_enable = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, P720_LIMIT_ENABLE));
+ mfc_info("RC_CONTROL_ENABLE = 0x%08x\n", mfc_read_shared_mem_item(host_wr_addr, RC_CONTROL_ENABLE));
+}
diff --git a/drivers/media/video/samsung/mfc50/mfc_shared_mem.h b/drivers/media/video/samsung/mfc50/mfc_shared_mem.h
new file mode 100644
index 0000000..ca86876
--- /dev/null
+++ b/drivers/media/video/samsung/mfc50/mfc_shared_mem.h
@@ -0,0 +1,97 @@
+/*
+ * drivers/media/video/samsung/mfc50/mfc_shared_mem.h
+ *
+ * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
+ *
+ * Key-Young Park, Copyright (c) 2009 Samsung Electronics
+ * http://www.samsungsemi.com/
+ *
+ * Change Logs
+ * 2009.10.08 - Apply 9/30 firmware(Key Young, Park)
+ * 2009.11.06 - clean & invalidate shared mem area (Key Young, Park)
+ *
+ * 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 _MFC_SHARED_MEM_H_
+#define _MFC_SHARED_MEM_H_
+
+#define MEM_WRITE(ADDR, VALUE) (*(volatile unsigned int *)(ADDR) = (VALUE))
+#define MEM_READ(ADDR) (*(volatile unsigned int *)(ADDR))
+
+enum mfc_shared {
+ EXTENEDED_DECODE_STATUS = 0x0,
+ SET_FRAME_TAG = 0x4,
+ GET_FRAME_TAG_TOP = 0x8,
+ GET_FRAME_TAG_BOT = 0xC,
+ PIC_TIME_TOP = 0x10,
+ PIC_TIME_BOT = 0x14,
+ START_BYTE_NUM = 0x18,
+ DEC_FRM_SIZE = 0x1C,
+ CROP_INFO1 = 0x20,
+ CROP_INFO2 = 0x24,
+ EXT_ENC_CONTROL = 0x28,
+ ENC_PARAM_CHANGE = 0x2C,
+ VOP_TIMING = 0x30,
+ HEC_PERIOD = 0x34,
+ METADATA_ENABLE = 0x38,
+ METADATA_STATUS = 0x3C,
+ METADATA_DISPLAY_INDEX = 0x40,
+ EXT_METADATA_START_ADDR = 0x44,
+ PUT_EXTRADATA = 0x48,
+ DBG_INFO_OUTPUT0 = 0x4C,
+ DBG_INFO_OUTPUT1 = 0x50,
+ DBG_INFO_INPUT0 = 0x54,
+ DBG_INFO_INPUT1 = 0x58,
+ REF_L0_PHY_IDX = 0x5C,
+ REF_L1_PHY_IDX = 0x60,
+ ALLOCATED_LUMA_DPB_SIZE = 0x64,
+ ALLOCATED_CHROMA_DPB_SIZE = 0x68,
+ ALLOCATED_MV_SIZE = 0x6C,
+ P_B_FRAME_QP = 0x70,
+ RC_CONTROL_ENABLE = 0xA0,
+ P720_LIMIT_ENABLE = 0xB4,
+ SHARED_MEM_MAX = 0x1000,
+};
+
+struct mfc_shared_mem {
+ unsigned int num_dpb;
+ unsigned int allocated_dpb_size;
+ unsigned int extended_decode_status;
+ unsigned int set_frame_tag;
+ unsigned int get_frame_tag_top;
+ unsigned int get_frame_tag_bot;
+ unsigned int pic_time_top;
+ unsigned int pic_time_bot;
+ unsigned int start_byte_num;
+ unsigned int dec_frm_size;
+ unsigned int crop_info1;
+ unsigned int crop_info2;
+ unsigned int ext_enc_control;
+ unsigned int enc_param_change;
+ unsigned int vop_timing;
+ unsigned int hec_period;
+ unsigned int P_B_frame_qp;
+ unsigned int metadata_enable;
+ unsigned int metadata_status;
+ unsigned int metadata_display_index;
+ unsigned int ext_metadata_start_addr;
+ unsigned int put_extradata;
+ unsigned int dbg_info_output0;
+ unsigned int dbg_info_output1;
+ unsigned int dbg_info_input0;
+ unsigned int dbg_info_input1;
+ unsigned int ref_l0_phy_idx;
+ unsigned int ref_l1_phy_idx;
+ unsigned int allocated_luma_dpb_size;
+ unsigned int allocated_chroma_dpb_size;
+ unsigned int allocated_mv_size;
+ unsigned int p720_limit_enable;
+};
+
+void mfc_write_shared_mem(unsigned int host_wr_addr, struct mfc_shared_mem *shared_mem);
+void mfc_read_shared_mem(unsigned int host_wr_addr, struct mfc_shared_mem *shared_mem);
+void mfc_print_shared_mem(unsigned int host_wr_addr);
+#endif
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..9ed45c0
--- /dev/null
+++ b/drivers/media/video/samsung/tv20/s5p_stda_grp.c
@@ -0,0 +1,1102 @@
+/* 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
+ }
+
+ (s5ptv_status.fb->var).bits_per_pixel = (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;
+}
+