diff options
Diffstat (limited to 'drivers/video/samsung')
43 files changed, 15383 insertions, 782 deletions
diff --git a/drivers/video/samsung/Kconfig b/drivers/video/samsung/Kconfig index 3cb946f..09711d3 100644 --- a/drivers/video/samsung/Kconfig +++ b/drivers/video/samsung/Kconfig @@ -7,11 +7,19 @@ config FB_S5P select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT + select SYNC + select SW_SYNC + select SW_SYNC_USER depends on FB && (ARCH_S5PV210 || ARCH_EXYNOS4) && !FB_S3C default n help This enables support for Samsung Display Controller (FIMD) +config FB_S5P_SYSMMU + bool "S5P FIMD SYSMMU enable" + depends on FB_S5P + default n + config FB_S5P_SPLASH_SCREEN bool "SPLASH_SCREEN on LCD" depends on FB_S5P @@ -26,6 +34,10 @@ config FB_S5P_DEBUG bool "S5P Framebuffer debug messages" depends on FB_S5P +config FB_S5P_VSYNC_THREAD + bool "S5P Framebuffer vsync thread" + depends on FB_S5P + config FB_S5P_TRACE_UNDERRUN bool "S5P Framebuffer FIFO underrun trace" depends on FB_S5P @@ -111,6 +123,21 @@ endif # FIMD_EXT_SUPPORT choice depends on FB_S5P +prompt "Select RGB Order" +default FB_BGRA_ORDER +config FB_BGRA_ORDER + bool "BGRA8888" + help + This enables use BGRA order. + +config FB_RGBA_ORDER + bool "RGBA8888" + help + This enables use RGBA order. +endchoice + +choice +depends on FB_S5P prompt "Select LCD Type" default FB_S5P_AMS369FG06 config FB_S5P_LTE480WV @@ -180,6 +207,12 @@ config FB_S5P_LMS501KF03 help This enables support for Samsung LMS501KF03 5.01" WVGA TFT LCD panel +config FB_S5P_LMS501XX + bool "LMS501XX MIPI LCD" + depends on FB_S5P_MIPI_DSIM + help + This enables support for Samsung LMS501XX 5.01" WVGA TFT LCD panel + config FB_S5P_DUMMY_MIPI_LCD bool "DUMMY MIPI LCD" depends on FB_S5P_MIPI_DSIM @@ -192,6 +225,18 @@ config FB_S5P_S6E8AA0 ---help--- This enables support for Samsung S6E8AA0 MIPI LCD +config FB_S5P_EA8061 + bool "EA8061 MIPI LCD" + depends on FB_S5P_MIPI_DSIM + ---help--- + This enables support for Samsung EA8061 MIPI LCD + +config FB_S5P_S6EVR02 + bool "S6EVR02 MIPI LCD" + depends on FB_S5P_MIPI_DSIM + ---help--- + This enables support for Samsung S6EVR02 MIPI LCD + config FB_S5P_S6E8AB0 bool "S6E8AB0 MIPI LCD" depends on MACH_PX && FB_S5P_MIPI_DSIM @@ -199,7 +244,7 @@ config FB_S5P_S6E8AB0 This enables support for Samsung S6E8AB0 MIPI LCD config FB_S5P_S6D6AA1 - bool "S6E8AB0 MIPI LCD" + bool "S6D6AA1 MIPI LCD" depends on FB_S5P_MIPI_DSIM ---help--- This enables support for Samsung S6D6AA1 MIPI LCD diff --git a/drivers/video/samsung/Makefile b/drivers/video/samsung/Makefile index 16ed689..75995be 100644 --- a/drivers/video/samsung/Makefile +++ b/drivers/video/samsung/Makefile @@ -17,10 +17,14 @@ obj-$(CONFIG_FB_S5P_LD9040) += ld9040.o smart_dimming_ld9042.o obj-$(CONFIG_FB_S5P_NT35560) += nt35560.o obj-$(CONFIG_FB_S5P_MDNIE) += s3cfb_mdnie.o s3cfb_ielcd.o mdnie.o mdnie_tunning.o obj-$(CONFIG_FB_S5P_LMS501KF03) += s3cfb_lms501kf03.o +obj-$(CONFIG_FB_S5P_LMS501XX) += s3cfb_lms501xx.o obj-$(CONFIG_FB_S5P_DUMMY_MIPI_LCD) += s3cfb_dummymipilcd.o obj-$(CONFIG_FB_S5P_S6E8AA0) += s3cfb_s6e8aa0.o smart_dimming.o +obj-$(CONFIG_FB_S5P_EA8061) += s3cfb_ea8061.o smart_dimming_ea8061.o +obj-$(CONFIG_FB_S5P_S6EVR02) += s3cfb_s6evr02.o smart_dimming_s6evr02.o s3cfb_ea8061.o smart_dimming_ea8061.o obj-$(CONFIG_FB_S5P_S6E8AB0) += s3cfb_s6e8ab0.o smart_dimming_s6e8ab0.o obj-$(CONFIG_FB_S5P_S6E39A0) += s3cfb_s6e39a0.o smart_dimming.o +obj-$(CONFIG_FB_S5P_S6E63M0) += s3cfb_s6e63m0.o smart_dimming.o obj-$(CONFIG_FB_S5P_S6D6AA1) += s6d6aa1.o obj-$(CONFIG_FB_S5P_MIPI_DSIM) += s5p_dsim_lowlevel.o obj-$(CONFIG_FB_S5P_MIPI_DSIM) += s5p-dsim.o diff --git a/drivers/video/samsung/aid_ea8061.h b/drivers/video/samsung/aid_ea8061.h new file mode 100644 index 0000000..9b92d80 --- /dev/null +++ b/drivers/video/samsung/aid_ea8061.h @@ -0,0 +1,337 @@ +#ifndef __AID_EA8061_H__ +#define __AID_EA8061_H__ + +#include "smart_dimming_ea8061.h" + +#define aid_300nit_260nit_B3_1st 0x00 +#define aid_300nit_260nit_B3_2nd 0x0A +#define aid_250nit_190nit_B3_1st 0x00 +#define aid_250nit_190nit_B3_2nd 0x0A +#define aid_188nit_186nit_B3_1st 0x00 +#define aid_184nit_182nit_B3_1st 0x01 +#define aid_188nit_B3_2nd 0x68 +#define aid_186nit_B3_2nd 0xCF +#define aid_184nit_B3_2nd 0x37 +#define aid_182nit_B3_2nd 0x9F +#define aid_180nit_110nit_B3_1st 0x02 +#define aid_180nit_110nit_B3_2nd 0x06 +#define aid_102nit_B3_1st 0x00 +#define aid_108nit_104nit_B3_1st 0x01 +#define aid_108nit_B3_2nd 0xC4 +#define aid_106nit_B3_2nd 0x82 +#define aid_104nit_B3_2nd 0x40 +#define aid_102nit_B3_2nd 0xFE +#define aid_100nit_B3_1st 0x00 +#define aid_90nit_80nit_B3_1st 0x01 +#define aid_70nit_60nit_B3_1st 0x02 +#define aid_50nit_30nit_B3_1st 0x03 +#define aid_20nit_B3_1st 0x04 +#define aid_100nit_B3_2nd 0xBC +#define aid_90nit_B3_2nd 0x36 +#define aid_80nit_B3_2nd 0xAB +#define aid_70nit_B3_2nd 0x25 +#define aid_60nit_B3_2nd 0x95 +#define aid_50nit_B3_2nd 0x0A +#define aid_40nit_B3_2nd 0x74 +#define aid_30nit_B3_2nd 0xDF +#define aid_20nit_B3_2nd 0x45 +#define AOR40_BASE_188 202 +#define AOR40_BASE_186 215 +#define AOR40_BASE_184 230 +#define AOR40_BASE_182 250 +#define AOR40_BASE_180 275 +#define AOR40_BASE_170 260 +#define AOR40_BASE_160 246 +#define AOR40_BASE_150 230 +#define AOR40_BASE_140 217 +#define AOR40_BASE_130 202 +#define AOR40_BASE_120 184 +#define AOR40_BASE_110 169 +#define AOR40_BASE_108 154 +#define AOR40_BASE_106 141 +#define AOR40_BASE_104 130 +#define AOR40_BASE_102 120 +#define base_20to100 110 + +static const struct rgb_offset_info aid_rgb_fix_table_SM2[] = { + {GAMMA_184CD, IV_11, CI_BLUE, 1}, + {GAMMA_182CD, IV_11, CI_GREEN, -1}, {GAMMA_182CD, IV_11, CI_BLUE, 2}, + {GAMMA_180CD, IV_11, CI_RED, -1}, {GAMMA_180CD, IV_11, CI_GREEN, -2}, {GAMMA_180CD, IV_11, CI_BLUE, 3}, + {GAMMA_170CD, IV_11, CI_RED, -1}, {GAMMA_170CD, IV_11, CI_GREEN, -2}, {GAMMA_170CD, IV_11, CI_BLUE, 3}, + {GAMMA_160CD, IV_11, CI_RED, -1}, {GAMMA_160CD, IV_11, CI_GREEN, -2}, {GAMMA_160CD, IV_11, CI_BLUE, 3}, + {GAMMA_150CD, IV_11, CI_RED, -1}, {GAMMA_150CD, IV_11, CI_GREEN, -2}, {GAMMA_150CD, IV_11, CI_BLUE, 3}, + {GAMMA_140CD, IV_11, CI_RED, -1}, {GAMMA_140CD, IV_11, CI_GREEN, -2}, {GAMMA_140CD, IV_11, CI_BLUE, 3}, + {GAMMA_130CD, IV_11, CI_RED, -1}, {GAMMA_130CD, IV_11, CI_GREEN, -2}, {GAMMA_130CD, IV_11, CI_BLUE, 3}, + {GAMMA_120CD, IV_11, CI_RED, -1}, {GAMMA_120CD, IV_11, CI_GREEN, -2}, {GAMMA_120CD, IV_11, CI_BLUE, 3}, + {GAMMA_110CD, IV_11, CI_RED, -1}, {GAMMA_110CD, IV_11, CI_GREEN, -2}, {GAMMA_110CD, IV_11, CI_BLUE, 3}, + {GAMMA_108CD, IV_11, CI_RED, -1}, {GAMMA_108CD, IV_11, CI_GREEN, -2}, {GAMMA_108CD, IV_11, CI_BLUE, 3}, + {GAMMA_106CD, IV_11, CI_RED, -1}, {GAMMA_106CD, IV_11, CI_GREEN, -1}, {GAMMA_106CD, IV_11, CI_BLUE, 3}, + {GAMMA_104CD, IV_11, CI_RED, -2}, {GAMMA_104CD, IV_11, CI_GREEN, -1}, {GAMMA_104CD, IV_11, CI_BLUE, 4}, + {GAMMA_102CD, IV_11, CI_RED, -2}, {GAMMA_102CD, IV_11, CI_BLUE, 4}, + {GAMMA_100CD, IV_11, CI_RED, -2}, {GAMMA_100CD, IV_11, CI_BLUE, 5}, + {GAMMA_90CD, IV_11, CI_RED, -5}, {GAMMA_90CD, IV_11, CI_BLUE, 6}, + {GAMMA_80CD, IV_11, CI_RED, -6}, {GAMMA_80CD, IV_11, CI_BLUE, 8}, + {GAMMA_70CD, IV_11, CI_RED, -7}, {GAMMA_70CD, IV_11, CI_BLUE, 11}, + {GAMMA_60CD, IV_11, CI_RED, -10}, {GAMMA_60CD, IV_11, CI_BLUE, 14}, + {GAMMA_50CD, IV_11, CI_RED, -12}, {GAMMA_50CD, IV_11, CI_BLUE, 19}, + {GAMMA_40CD, IV_11, CI_RED, -18}, {GAMMA_40CD, IV_11, CI_BLUE, 24}, + {GAMMA_30CD, IV_11, CI_RED, -18}, {GAMMA_30CD, IV_11, CI_BLUE, 31}, + {GAMMA_20CD, IV_11, CI_RED, -18}, {GAMMA_20CD, IV_11, CI_BLUE, 39}, + {GAMMA_90CD, IV_23, CI_GREEN, -3}, + {GAMMA_80CD, IV_23, CI_RED, -1}, {GAMMA_80CD, IV_23, CI_GREEN, -4}, + {GAMMA_70CD, IV_23, CI_RED, -3}, {GAMMA_70CD, IV_23, CI_GREEN, -6}, + {GAMMA_60CD, IV_23, CI_RED, -4}, {GAMMA_60CD, IV_23, CI_GREEN, -9}, + {GAMMA_50CD, IV_23, CI_RED, -7}, {GAMMA_50CD, IV_23, CI_GREEN, -9}, + {GAMMA_40CD, IV_23, CI_RED, -12}, {GAMMA_40CD, IV_23, CI_GREEN, -16}, + {GAMMA_30CD, IV_23, CI_RED, -17}, {GAMMA_30CD, IV_23, CI_GREEN, -16}, {GAMMA_30CD, IV_23, CI_BLUE, 2}, + {GAMMA_20CD, IV_23, CI_RED, -22}, {GAMMA_20CD, IV_23, CI_GREEN, -16}, {GAMMA_20CD, IV_23, CI_BLUE, 9}, + {GAMMA_30CD, IV_35, CI_RED, -3}, {GAMMA_30CD, IV_35, CI_GREEN, -14}, + {GAMMA_20CD, IV_35, CI_RED, -11}, {GAMMA_20CD, IV_35, CI_GREEN, -30}, +}; + +static const struct rgb_offset_info aid_rgb_fix_table_M4[] = { + {GAMMA_180CD, IV_11, CI_GREEN, 1}, + {GAMMA_170CD, IV_11, CI_GREEN, 1}, + {GAMMA_160CD, IV_11, CI_GREEN, 1}, + {GAMMA_150CD, IV_11, CI_GREEN, 1}, + {GAMMA_140CD, IV_11, CI_GREEN, 1}, + {GAMMA_130CD, IV_11, CI_GREEN, 1}, + {GAMMA_120CD, IV_11, CI_GREEN, 1}, + {GAMMA_110CD, IV_11, CI_GREEN, 1}, + {GAMMA_180CD, IV_23, CI_GREEN, 1}, + {GAMMA_170CD, IV_23, CI_GREEN, 1}, + {GAMMA_160CD, IV_23, CI_GREEN, 1}, + {GAMMA_150CD, IV_23, CI_GREEN, 1}, + {GAMMA_140CD, IV_23, CI_GREEN, 1}, + {GAMMA_130CD, IV_23, CI_GREEN, 1}, + {GAMMA_120CD, IV_23, CI_GREEN, 1}, + {GAMMA_110CD, IV_23, CI_GREEN, 1}, + {GAMMA_180CD, IV_35, CI_RED, -10}, {GAMMA_180CD, IV_35, CI_GREEN, 2}, + {GAMMA_170CD, IV_35, CI_RED, -11}, {GAMMA_170CD, IV_35, CI_GREEN, 2}, + {GAMMA_160CD, IV_35, CI_RED, -12}, {GAMMA_160CD, IV_35, CI_GREEN, 2}, + {GAMMA_150CD, IV_35, CI_RED, -13}, {GAMMA_150CD, IV_35, CI_GREEN, 2}, + {GAMMA_140CD, IV_35, CI_RED, -14}, {GAMMA_140CD, IV_35, CI_GREEN, 2}, + {GAMMA_130CD, IV_35, CI_RED, -15}, {GAMMA_130CD, IV_35, CI_GREEN, 2}, + {GAMMA_120CD, IV_35, CI_RED, -16}, {GAMMA_120CD, IV_35, CI_GREEN, 2}, + {GAMMA_110CD, IV_35, CI_RED, -17}, {GAMMA_110CD, IV_35, CI_GREEN, 2}, + {GAMMA_90CD, IV_11, CI_GREEN, 12}, {GAMMA_90CD, IV_11, CI_BLUE, -7}, + {GAMMA_80CD, IV_11, CI_GREEN, 20}, {GAMMA_80CD, IV_11, CI_BLUE, 2}, + {GAMMA_70CD, IV_11, CI_RED, -17}, {GAMMA_70CD, IV_11, CI_GREEN, 20}, {GAMMA_70CD, IV_11, CI_BLUE, 5}, + {GAMMA_60CD, IV_11, CI_RED, -17}, {GAMMA_60CD, IV_11, CI_GREEN, 29}, {GAMMA_60CD, IV_11, CI_BLUE, 16}, + {GAMMA_50CD, IV_11, CI_RED, -17}, {GAMMA_50CD, IV_11, CI_GREEN, 39}, {GAMMA_50CD, IV_11, CI_BLUE, 27}, + {GAMMA_40CD, IV_11, CI_RED, -17}, {GAMMA_40CD, IV_11, CI_GREEN, 49}, {GAMMA_40CD, IV_11, CI_BLUE, 37}, + {GAMMA_30CD, IV_11, CI_RED, -52}, {GAMMA_30CD, IV_11, CI_GREEN, 60}, {GAMMA_30CD, IV_11, CI_BLUE, 52}, + {GAMMA_20CD, IV_11, CI_RED, -56}, {GAMMA_20CD, IV_11, CI_GREEN, 76}, {GAMMA_20CD, IV_11, CI_BLUE, 72}, + {GAMMA_70CD, IV_23, CI_RED, -6}, {GAMMA_70CD, IV_23, CI_GREEN, 3}, + {GAMMA_60CD, IV_23, CI_RED, -13}, {GAMMA_60CD, IV_23, CI_GREEN, 4}, + {GAMMA_50CD, IV_23, CI_RED, -20}, {GAMMA_50CD, IV_23, CI_GREEN, 5}, + {GAMMA_40CD, IV_23, CI_RED, -30}, {GAMMA_40CD, IV_23, CI_GREEN, 6}, + {GAMMA_30CD, IV_23, CI_RED, -35}, {GAMMA_30CD, IV_23, CI_GREEN, -2}, + {GAMMA_20CD, IV_23, CI_RED, -46}, {GAMMA_20CD, IV_23, CI_GREEN, -6}, {GAMMA_20CD, IV_23, CI_BLUE, 11}, + {GAMMA_30CD, IV_35, CI_RED, -23}, {GAMMA_30CD, IV_35, CI_GREEN, 11}, + {GAMMA_20CD, IV_35, CI_RED, -39}, {GAMMA_20CD, IV_35, CI_GREEN, 26}, +}; + +static unsigned char aid_command_20[] = { + aid_20nit_B3_1st, + aid_20nit_B3_2nd, +}; + +static unsigned char aid_command_30[] = { + aid_50nit_30nit_B3_1st, + aid_30nit_B3_2nd, +}; + +static unsigned char aid_command_40[] = { + aid_50nit_30nit_B3_1st, + aid_40nit_B3_2nd, +}; + +static unsigned char aid_command_50[] = { + aid_50nit_30nit_B3_1st, + aid_50nit_B3_2nd, +}; + +static unsigned char aid_command_60[] = { + aid_70nit_60nit_B3_1st, + aid_60nit_B3_2nd, +}; + +static unsigned char aid_command_70[] = { + aid_70nit_60nit_B3_1st, + aid_70nit_B3_2nd, +}; + +static unsigned char aid_command_80[] = { + aid_90nit_80nit_B3_1st, + aid_80nit_B3_2nd, +}; + +static unsigned char aid_command_90[] = { + aid_90nit_80nit_B3_1st, + aid_90nit_B3_2nd, +}; + +static unsigned char aid_command_100[] = { + aid_100nit_B3_1st, + aid_100nit_B3_2nd, +}; + +static unsigned char aid_command_102[] = { + aid_102nit_B3_1st, + aid_102nit_B3_2nd, +}; + +static unsigned char aid_command_104[] = { + aid_108nit_104nit_B3_1st, + aid_104nit_B3_2nd, +}; + +static unsigned char aid_command_106[] = { + aid_108nit_104nit_B3_1st, + aid_106nit_B3_2nd, +}; + +static unsigned char aid_command_108[] = { + aid_108nit_104nit_B3_1st, + aid_108nit_B3_2nd, +}; + +static unsigned char aid_command_110[] = { + aid_180nit_110nit_B3_1st, + aid_180nit_110nit_B3_2nd, +}; + +static unsigned char aid_command_120[] = { + aid_180nit_110nit_B3_1st, + aid_180nit_110nit_B3_2nd, +}; + +static unsigned char aid_command_130[] = { + aid_180nit_110nit_B3_1st, + aid_180nit_110nit_B3_2nd, +}; + +static unsigned char aid_command_140[] = { + aid_180nit_110nit_B3_1st, + aid_180nit_110nit_B3_2nd, +}; + +static unsigned char aid_command_150[] = { + aid_180nit_110nit_B3_1st, + aid_180nit_110nit_B3_2nd, +}; + +static unsigned char aid_command_160[] = { + aid_180nit_110nit_B3_1st, + aid_180nit_110nit_B3_2nd, +}; + +static unsigned char aid_command_170[] = { + aid_180nit_110nit_B3_1st, + aid_180nit_110nit_B3_2nd, +}; + +static unsigned char aid_command_180[] = { + aid_180nit_110nit_B3_1st, + aid_180nit_110nit_B3_2nd, +}; + +static unsigned char aid_command_182[] = { + aid_184nit_182nit_B3_1st, + aid_182nit_B3_2nd, +}; + +static unsigned char aid_command_184[] = { + aid_184nit_182nit_B3_1st, + aid_184nit_B3_2nd, +}; + +static unsigned char aid_command_186[] = { + aid_188nit_186nit_B3_1st, + aid_186nit_B3_2nd, +}; + +static unsigned char aid_command_188[] = { + aid_188nit_186nit_B3_1st, + aid_188nit_B3_2nd, +}; + +static unsigned char aid_command_190[] = { + aid_250nit_190nit_B3_1st, + aid_250nit_190nit_B3_2nd, +}; + +static unsigned char aid_command_200[] = { + aid_250nit_190nit_B3_1st, + aid_250nit_190nit_B3_2nd, +}; + +static unsigned char aid_command_210[] = { + aid_250nit_190nit_B3_1st, + aid_250nit_190nit_B3_2nd, +}; + +static unsigned char aid_command_220[] = { + aid_250nit_190nit_B3_1st, + aid_250nit_190nit_B3_2nd, +}; + +static unsigned char aid_command_230[] = { + aid_250nit_190nit_B3_1st, + aid_250nit_190nit_B3_2nd, +}; + +static unsigned char aid_command_240[] = { + aid_250nit_190nit_B3_1st, + aid_250nit_190nit_B3_2nd, +}; + +static unsigned char aid_command_250[] = { + aid_250nit_190nit_B3_1st, + aid_250nit_190nit_B3_2nd, +}; + +static unsigned char aid_command_300[] = { + aid_300nit_260nit_B3_1st, + aid_300nit_260nit_B3_2nd, + +}; + +static unsigned char *aid_command_table[GAMMA_MAX] = { + aid_command_20, + aid_command_30, + aid_command_40, + aid_command_50, + aid_command_60, + aid_command_70, + aid_command_80, + aid_command_90, + aid_command_100, + aid_command_102, + aid_command_104, + aid_command_106, + aid_command_108, + aid_command_110, + aid_command_120, + aid_command_130, + aid_command_140, + aid_command_150, + aid_command_160, + aid_command_170, + aid_command_180, + aid_command_182, + aid_command_184, + aid_command_186, + aid_command_188, + aid_command_190, + aid_command_200, + aid_command_210, + aid_command_220, + aid_command_230, + aid_command_240, + aid_command_250, + aid_command_300 +}; + +#endif diff --git a/drivers/video/samsung/aid_s6e8aa0.h b/drivers/video/samsung/aid_s6e8aa0.h index cf8058a..c06eaf8 100644 --- a/drivers/video/samsung/aid_s6e8aa0.h +++ b/drivers/video/samsung/aid_s6e8aa0.h @@ -15,6 +15,10 @@ #define aid_180nit_110nit_F8_18th 0x42 #define aid_180nit_110nit_F8_1st 0x59 #define aid_100nit_20nit_F8_1st 0x59 +#define aid_108nit_F8_18th 0x38 +#define aid_106nit_F8_18th 0x2F +#define aid_104nit_F8_18th 0x25 +#define aid_102nit_F8_18th 0x1C #define aid_100nit_F8_18th 0x12 #define aid_90nit_F8_18th 0x22 #define aid_80nit_F8_18th 0x32 @@ -36,6 +40,10 @@ #define AOR40_BASE_130 200 #define AOR40_BASE_120 186 #define AOR40_BASE_110 171 +#define AOR40_BASE_108 156 +#define AOR40_BASE_106 143 +#define AOR40_BASE_104 130 +#define AOR40_BASE_102 120 #define base_20to100 110 const struct rgb_offset_info aid_rgb_fix_table[] = { @@ -47,6 +55,10 @@ const struct rgb_offset_info aid_rgb_fix_table[] = { {GAMMA_130CD, IV_15, CI_RED, 1}, {GAMMA_130CD, IV_15, CI_GREEN, -1}, {GAMMA_130CD, IV_15, CI_BLUE, 5}, {GAMMA_120CD, IV_15, CI_RED, 1}, {GAMMA_120CD, IV_15, CI_GREEN, -1}, {GAMMA_120CD, IV_15, CI_BLUE, 5}, {GAMMA_110CD, IV_15, CI_RED, 1}, {GAMMA_110CD, IV_15, CI_GREEN, -1}, {GAMMA_110CD, IV_15, CI_BLUE, 5}, + {GAMMA_108CD, IV_15, CI_RED, 1}, {GAMMA_110CD, IV_15, CI_GREEN, -1}, {GAMMA_110CD, IV_15, CI_BLUE, 5}, + {GAMMA_106CD, IV_15, CI_RED, 1}, {GAMMA_110CD, IV_15, CI_GREEN, -1}, {GAMMA_110CD, IV_15, CI_BLUE, 5}, + {GAMMA_104CD, IV_15, CI_RED, 1}, {GAMMA_110CD, IV_15, CI_GREEN, -1}, {GAMMA_110CD, IV_15, CI_BLUE, 5}, + {GAMMA_102CD, IV_15, CI_RED, 1}, {GAMMA_110CD, IV_15, CI_GREEN, -1}, {GAMMA_110CD, IV_15, CI_BLUE, 5}, {GAMMA_100CD, IV_15, CI_RED, -2}, {GAMMA_100CD, IV_15, CI_GREEN, -3}, {GAMMA_90CD, IV_15, CI_RED, -6}, {GAMMA_90CD, IV_15, CI_GREEN, -7}, {GAMMA_80CD, IV_15, CI_RED, -10}, {GAMMA_80CD, IV_15, CI_GREEN, -12}, @@ -104,6 +116,26 @@ static unsigned char aid_command_100[] = { aid_100nit_20nit_F8_1st, }; +static unsigned char aid_command_102[] = { + aid_102nit_F8_18th, + aid_100nit_20nit_F8_1st, +}; + +static unsigned char aid_command_104[] = { + aid_104nit_F8_18th, + aid_100nit_20nit_F8_1st, +}; + +static unsigned char aid_command_106[] = { + aid_106nit_F8_18th, + aid_100nit_20nit_F8_1st, +}; + +static unsigned char aid_command_108[] = { + aid_108nit_F8_18th, + aid_100nit_20nit_F8_1st, +}; + static unsigned char aid_command_110[] = { aid_180nit_110nit_F8_18th, aid_180nit_110nit_F8_1st, @@ -214,6 +246,10 @@ static unsigned char *aid_command_table[GAMMA_MAX] = { aid_command_80, aid_command_90, aid_command_100, + aid_command_102, + aid_command_104, + aid_command_106, + aid_command_108, aid_command_110, aid_command_120, aid_command_130, diff --git a/drivers/video/samsung/aid_s6evr02.h b/drivers/video/samsung/aid_s6evr02.h new file mode 100644 index 0000000..2adf731 --- /dev/null +++ b/drivers/video/samsung/aid_s6evr02.h @@ -0,0 +1,248 @@ +#ifndef __AID_S6EVR02_H__ +#define __AID_S6EVR02_H__ + +#include "smart_dimming_s6evr02.h" + +#define aid_300nit 0xFF +#define aid_190nit_250nit 0xFF +#define aid_188nit 0xEA +#define aid_186nit 0xD6 +#define aid_184nit 0xC2 +#define aid_182nit 0xAD +#define aid_110nit_180nit 0x99 +#define aid_108nit 0xF6 +#define aid_106nit 0xEF +#define aid_104nit 0xE8 +#define aid_102nit 0xE1 +#define aid_100nit 0xDA +#define aid_90nit 0xC2 +#define aid_80nit 0xAB +#define aid_70nit 0x93 +#define aid_60nit 0x7D +#define aid_50nit 0x66 +#define aid_40nit 0x51 +#define aid_30nit 0x3C +#define aid_20nit 0x28 +#define AOR40_BASE_188 202 +#define AOR40_BASE_186 215 +#define AOR40_BASE_184 230 +#define AOR40_BASE_182 250 +#define AOR40_BASE_180 275 +#define AOR40_BASE_170 260 +#define AOR40_BASE_160 246 +#define AOR40_BASE_150 231 +#define AOR40_BASE_140 217 +#define AOR40_BASE_130 202 +#define AOR40_BASE_120 188 +#define AOR40_BASE_110 169 +#define AOR40_BASE_108 110 +#define AOR40_BASE_106 110 +#define AOR40_BASE_104 110 +#define AOR40_BASE_102 110 +#define base_20to100 110 + +static const struct rgb_offset_info aid_rgb_fix_table[] = { + {GAMMA_184CD, IV_11, CI_BLUE, 1}, + {GAMMA_182CD, IV_11, CI_GREEN, -1}, {GAMMA_182CD, IV_11, CI_BLUE, 2}, + {GAMMA_180CD, IV_11, CI_RED, -1}, {GAMMA_180CD, IV_11, CI_GREEN, -2}, {GAMMA_180CD, IV_11, CI_BLUE, 3}, + {GAMMA_170CD, IV_11, CI_RED, -1}, {GAMMA_170CD, IV_11, CI_GREEN, -2}, {GAMMA_170CD, IV_11, CI_BLUE, 3}, + {GAMMA_160CD, IV_11, CI_RED, -1}, {GAMMA_160CD, IV_11, CI_GREEN, -2}, {GAMMA_160CD, IV_11, CI_BLUE, 3}, + {GAMMA_150CD, IV_11, CI_RED, -1}, {GAMMA_150CD, IV_11, CI_GREEN, -2}, {GAMMA_150CD, IV_11, CI_BLUE, 3}, + {GAMMA_140CD, IV_11, CI_RED, -1}, {GAMMA_140CD, IV_11, CI_GREEN, -2}, {GAMMA_140CD, IV_11, CI_BLUE, 3}, + {GAMMA_130CD, IV_11, CI_RED, -1}, {GAMMA_130CD, IV_11, CI_GREEN, -2}, {GAMMA_130CD, IV_11, CI_BLUE, 3}, + {GAMMA_120CD, IV_11, CI_RED, -1}, {GAMMA_120CD, IV_11, CI_GREEN, -2}, {GAMMA_120CD, IV_11, CI_BLUE, 3}, + {GAMMA_110CD, IV_11, CI_RED, -1}, {GAMMA_110CD, IV_11, CI_GREEN, -2}, {GAMMA_110CD, IV_11, CI_BLUE, 3}, + {GAMMA_108CD, IV_11, CI_RED, -1}, {GAMMA_108CD, IV_11, CI_GREEN, -2}, {GAMMA_104CD, IV_11, CI_BLUE, 3}, + {GAMMA_106CD, IV_11, CI_RED, -1}, {GAMMA_106CD, IV_11, CI_GREEN, -1}, {GAMMA_104CD, IV_11, CI_BLUE, 3}, + {GAMMA_104CD, IV_11, CI_RED, -2}, {GAMMA_104CD, IV_11, CI_GREEN, -1}, {GAMMA_104CD, IV_11, CI_BLUE, 4}, + {GAMMA_102CD, IV_11, CI_RED, -2}, {GAMMA_102CD, IV_11, CI_BLUE, 4}, + {GAMMA_100CD, IV_11, CI_RED, -2}, {GAMMA_100CD, IV_11, CI_BLUE, 5}, + {GAMMA_90CD, IV_11, CI_RED, -5}, {GAMMA_90CD, IV_11, CI_BLUE, 6}, + {GAMMA_80CD, IV_11, CI_RED, -6}, {GAMMA_80CD, IV_11, CI_BLUE, 8}, + {GAMMA_70CD, IV_11, CI_RED, -7}, {GAMMA_70CD, IV_11, CI_BLUE, 11}, + {GAMMA_60CD, IV_11, CI_RED, -10}, {GAMMA_60CD, IV_11, CI_BLUE, 14}, + {GAMMA_50CD, IV_11, CI_RED, -12}, {GAMMA_50CD, IV_11, CI_BLUE, 19}, + {GAMMA_40CD, IV_11, CI_RED, -18}, {GAMMA_40CD, IV_11, CI_BLUE, 24}, + {GAMMA_30CD, IV_11, CI_RED, -18}, {GAMMA_30CD, IV_11, CI_BLUE, 31}, + {GAMMA_20CD, IV_11, CI_RED, -18}, {GAMMA_20CD, IV_11, CI_BLUE, 39}, + {GAMMA_90CD, IV_23, CI_GREEN, -3}, + {GAMMA_80CD, IV_23, CI_RED, -1}, {GAMMA_80CD, IV_23, CI_GREEN, -4}, + {GAMMA_70CD, IV_23, CI_RED, -3}, {GAMMA_70CD, IV_23, CI_GREEN, -6}, + {GAMMA_60CD, IV_23, CI_RED, -4}, {GAMMA_60CD, IV_23, CI_GREEN, -9}, + {GAMMA_50CD, IV_23, CI_RED, -7}, {GAMMA_50CD, IV_23, CI_GREEN, -9}, + {GAMMA_40CD, IV_23, CI_RED, -12}, {GAMMA_40CD, IV_23, CI_GREEN, -16}, + {GAMMA_30CD, IV_23, CI_RED, -17}, {GAMMA_30CD, IV_23, CI_GREEN, -16}, {GAMMA_30CD, IV_23, CI_BLUE, 2}, + {GAMMA_20CD, IV_23, CI_RED, -22}, {GAMMA_20CD, IV_23, CI_GREEN, -16}, {GAMMA_20CD, IV_23, CI_BLUE, 9}, + {GAMMA_30CD, IV_35, CI_RED, -3}, {GAMMA_30CD, IV_35, CI_GREEN, -14}, + {GAMMA_20CD, IV_35, CI_RED, -11}, {GAMMA_20CD, IV_35, CI_GREEN, -30}, +}; + +static unsigned char aid_command_20[] = { + aid_20nit +}; + +static unsigned char aid_command_30[] = { + aid_30nit +}; + +static unsigned char aid_command_40[] = { + aid_40nit +}; + +static unsigned char aid_command_50[] = { + aid_50nit +}; + +static unsigned char aid_command_60[] = { + aid_60nit +}; + +static unsigned char aid_command_70[] = { + aid_70nit +}; + +static unsigned char aid_command_80[] = { + aid_80nit +}; + +static unsigned char aid_command_90[] = { + aid_90nit +}; + +static unsigned char aid_command_100[] = { + aid_100nit +}; + +static unsigned char aid_command_102[] = { + aid_102nit +}; + +static unsigned char aid_command_104[] = { + aid_104nit +}; + +static unsigned char aid_command_106[] = { + aid_106nit +}; + +static unsigned char aid_command_108[] = { + aid_108nit +}; + +static unsigned char aid_command_110[] = { + aid_110nit_180nit +}; + +static unsigned char aid_command_120[] = { + aid_110nit_180nit +}; + +static unsigned char aid_command_130[] = { + aid_110nit_180nit +}; + +static unsigned char aid_command_140[] = { + aid_110nit_180nit +}; + +static unsigned char aid_command_150[] = { + aid_110nit_180nit +}; + +static unsigned char aid_command_160[] = { + aid_110nit_180nit +}; + +static unsigned char aid_command_170[] = { + aid_110nit_180nit +}; + +static unsigned char aid_command_180[] = { + aid_110nit_180nit +}; + +static unsigned char aid_command_182[] = { + aid_182nit +}; + +static unsigned char aid_command_184[] = { + aid_184nit +}; + +static unsigned char aid_command_186[] = { + aid_186nit +}; + +static unsigned char aid_command_188[] = { + aid_188nit +}; + +static unsigned char aid_command_190[] = { + aid_190nit_250nit +}; + +static unsigned char aid_command_200[] = { + aid_190nit_250nit +}; + +static unsigned char aid_command_210[] = { + aid_190nit_250nit +}; + +static unsigned char aid_command_220[] = { + aid_190nit_250nit +}; + +static unsigned char aid_command_230[] = { + aid_190nit_250nit +}; + +static unsigned char aid_command_240[] = { + aid_190nit_250nit +}; + +static unsigned char aid_command_250[] = { + aid_190nit_250nit +}; + +static unsigned char aid_command_300[] = { + aid_300nit +}; + +static unsigned char *aid_command_table[GAMMA_MAX] = { + aid_command_20, + aid_command_30, + aid_command_40, + aid_command_50, + aid_command_60, + aid_command_70, + aid_command_80, + aid_command_90, + aid_command_100, + aid_command_102, + aid_command_104, + aid_command_106, + aid_command_108, + aid_command_110, + aid_command_120, + aid_command_130, + aid_command_140, + aid_command_150, + aid_command_160, + aid_command_170, + aid_command_180, + aid_command_182, + aid_command_184, + aid_command_186, + aid_command_188, + aid_command_190, + aid_command_200, + aid_command_210, + aid_command_220, + aid_command_230, + aid_command_240, + aid_command_250, + aid_command_300 +}; + +#endif diff --git a/drivers/video/samsung/ea8061_param.h b/drivers/video/samsung/ea8061_param.h new file mode 100644 index 0000000..e40a3d9 --- /dev/null +++ b/drivers/video/samsung/ea8061_param.h @@ -0,0 +1,391 @@ +#ifndef __EA8061_PARAM_H__ +#define __EA8061_PARAM_H__ + +#define GAMMA_PARAM_SIZE 34 +#define ACL_PARAM_SIZE ARRAY_SIZE(acl_cutoff_33) +#define ELVSS_PARAM_SIZE ARRAY_SIZE(elvss_control_set_20) +#define AID_PARAM_SIZE ARRAY_SIZE(SEQ_LTPS_AID) + +enum { + GAMMA_20CD, + GAMMA_30CD, + GAMMA_40CD, + GAMMA_50CD, + GAMMA_60CD, + GAMMA_70CD, + GAMMA_80CD, + GAMMA_90CD, + GAMMA_100CD, + GAMMA_102CD, + GAMMA_104CD, + GAMMA_106CD, + GAMMA_108CD, + GAMMA_110CD, + GAMMA_120CD, + GAMMA_130CD, + GAMMA_140CD, + GAMMA_150CD, + GAMMA_160CD, + GAMMA_170CD, + GAMMA_180CD, + GAMMA_182CD, + GAMMA_184CD, + GAMMA_186CD, + GAMMA_188CD, + GAMMA_190CD, + GAMMA_200CD, + GAMMA_210CD, + GAMMA_220CD, + GAMMA_230CD, + GAMMA_240CD, + GAMMA_250CD, + GAMMA_300CD, + GAMMA_MAX +}; + +static const unsigned char SEQ_APPLY_LEVEL_2_KEY_ENABLE[] = { + 0xF0, + 0x5A, 0x5A +}; + +static const unsigned char SEQ_APPLY_LEVEL_2_KEY_DISABLE[] = { + 0xF0, + 0xA5, 0xA5 +}; + +static const unsigned char SEQ_APPLY_LEVEL_3_KEY[] = { + 0xFC, + 0x5A, 0x5A +}; + +static const unsigned char SEQ_FRAME_GAMMA_UPDATE_KEY[] = { + 0xF7, + 0x5A, 0x5A +}; + +static const unsigned char SEQ_FRAME_GAMMA_UPDATE_KEY2[] = { + 0xF7, + 0xA5, 0xA5 +}; + +static const unsigned char SEQ_SLEEP_OUT[] = { + 0x11, + 0x00, 0x00 +}; + +static const unsigned char SEQ_SLEEP_IN[] = { + 0x10, + 0x00, 0x00 +}; + +static const unsigned char SEQ_PANEL_CONDITION_SET[] = { + 0xC4, + 0x4E, 0xBD, 0x00, 0x00, 0x58, 0xA7, 0x0B, 0x34, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0B, 0x92, 0x0B, 0x92, 0x08, 0x08, 0x07, + 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, + 0x04, +}; + +static const unsigned char SEQ_M4_PANEL_CONDITION_SET[] = { + 0xC4, + 0x4E, 0xBD, 0x00, 0x00, 0x58, 0xA7, 0x0B, 0x34, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0B, 0x92, 0x0B, 0x92, 0x08, 0x08, 0x07, + 0x30, 0x50, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, + 0x04, +}; + +static const unsigned char SEQ_GAMMA_CONDITION_SET[] = { + 0xCA, + 0x00, 0xE8, 0x00, 0xF7, 0x01, 0x03, 0xDB, 0xDB, 0xDC, 0xD9, + 0xD8, 0xDA, 0xCB, 0xC8, 0xCB, 0xD4, 0xD3, 0xD7, 0xE6, 0xE6, + 0xEA, 0xE2, 0xE4, 0xE5, 0xCE, 0xC3, 0xCF, 0xB9, 0x9D, 0xDE, + 0x11, 0x00 +}; + +static const unsigned char SEQ_M4_GAMMA_CONDITION_SET[] = { + 0xCA, + 0x00, 0xB6, 0x00, 0xB7, 0x00, 0xD5, 0xD7, 0xDA, 0xDC, 0xD3, + 0xD6, 0xD8, 0xBC, 0xC0, 0xC3, 0xBF, 0xC5, 0xCC, 0xD0, 0xD5, + 0xE0, 0xC8, 0xD1, 0xD8, 0x96, 0xAF, 0xB9, 0x82, 0xB6, 0xC2, + 0x11, 0x00, +}; + +static const unsigned char SEQ_LTPS_AID[] = { + 0xB3, + 0x00, 0x0A, +}; + +static const unsigned char ELVSS_CONTROL_SET[] = { + 0xB2, 0x0E, + 0xB4, 0xA0, 0x00, 0x00, 0x00, 0x00 +}; + +static const unsigned char SEQ_DISPLAY_CONDITION_SET[] = { + 0x36, + 0x02, 0x00 +}; + +static const unsigned char SEQ_ETC_WCABC_CONTROL[] = { + 0x55, + 0x00, 0x00 +}; + +static const unsigned char SEQ_SLEW_REV00[] = { + 0xB4, + 0x33, 0x0E, 0x00 +}; + +static const unsigned char SEQ_SLEW_REV01[] = { + 0xB4, + 0x33, 0x0E, 0x00 +}; + +static const unsigned char SEQ_SLEW_REV02[] = { + 0xB4, + 0x33, 0x09, 0x00 +}; + +static const unsigned char SEQ_SLEW_REV03[] = { + 0xB4, + 0x33, 0x0D, 0x00 +}; + +static const unsigned char SEQ_SLEW_REV04[] = { + 0xB4, + 0x33, 0x0A, 0x00 +}; + +static const unsigned char SEQ_M4_SLEW[] = { + 0xB4, + 0x33, 0x0D, 0x00 +}; + +static const unsigned char SEQ_DISPLAY_ON[] = { + 0x29, + 0x00, 0x00 +}; + +static const unsigned char SEQ_DISPLAY_OFF[] = { + 0x28, + 0x00, 0x00 +}; + +enum { + ELVSS_STATUS_20, + ELVSS_STATUS_30, + ELVSS_STATUS_40, + ELVSS_STATUS_50, + ELVSS_STATUS_60, + ELVSS_STATUS_70, + ELVSS_STATUS_80, + ELVSS_STATUS_90, + ELVSS_STATUS_100, + ELVSS_STATUS_110, + ELVSS_STATUS_120, + ELVSS_STATUS_130, + ELVSS_STATUS_140, + ELVSS_STATUS_150, + ELVSS_STATUS_160, + ELVSS_STATUS_170, + ELVSS_STATUS_180, + ELVSS_STATUS_190, + ELVSS_STATUS_200, + ELVSS_STATUS_210, + ELVSS_STATUS_220, + ELVSS_STATUS_230, + ELVSS_STATUS_240, + ELVSS_STATUS_250, + ELVSS_STATUS_300, + ELVSS_STATUS_MAX +}; + +static const unsigned char elvss_control_set_20[] = { + 0xB2, 0x20, + 0xB4, 0xA0, 0x00, 0x00, 0x00, 0x00 +}; + +static const unsigned char elvss_control_set_30[] = { + 0xB2, 0x20, + 0xB4, 0xA0, 0x00, 0x00, 0x00, 0x00 +}; + +static const unsigned char elvss_control_set_40[] = { + 0xB2, 0x20, + 0xB4, 0xA0, 0x00, 0x00, 0x00, 0x00 +}; + +static const unsigned char elvss_control_set_50[] = { + 0xB2, 0x1F, + 0xB4, 0xA0, 0x00, 0x00, 0x00, 0x00 +}; + +static const unsigned char elvss_control_set_60[] = { + 0xB2, 0x1F, + 0xB4, 0xA0, 0x00, 0x00, 0x00, 0x00 +}; + +static const unsigned char elvss_control_set_70[] = { + 0xB2, 0x1F, + 0xB4, 0xA0, 0x00, 0x00, 0x00, 0x00 +}; + +static const unsigned char elvss_control_set_80[] = { + 0xB2, 0x1E, + 0xB4, 0xA0, 0x00, 0x00, 0x00, 0x00 +}; + +static const unsigned char elvss_control_set_90[] = { + 0xB2, 0x1E, + 0xB4, 0xA0, 0x00, 0x00, 0x00, 0x00 +}; + +static const unsigned char elvss_control_set_100[] = { + 0xB2, 0x1C, + 0xB4, 0xA0, 0x00, 0x00, 0x00, 0x00 +}; + +static const unsigned char elvss_control_set_110[] = { + 0xB2, 0x1B, + 0xB4, 0xA0, 0x00, 0x00, 0x00, 0x00 +}; + +static const unsigned char elvss_control_set_120[] = { + 0xB2, 0x19, + 0xB4, 0xA0, 0x00, 0x00, 0x00, 0x00 +}; + +static const unsigned char elvss_control_set_130[] = { + 0xB2, 0x17, + 0xB4, 0xA0, 0x00, 0x00, 0x00, 0x00 +}; + +static const unsigned char elvss_control_set_140[] = { + 0xB2, 0x16, + 0xB4, 0xA0, 0x00, 0x00, 0x00, 0x00 +}; + +static const unsigned char elvss_control_set_150[] = { + 0xB2, 0x14, + 0xB4, 0xA0, 0x00, 0x00, 0x00, 0x00 +}; + +static const unsigned char elvss_control_set_160[] = { + 0xB2, 0x12, + 0xB4, 0xA0, 0x00, 0x00, 0x00, 0x00 +}; + +static const unsigned char elvss_control_set_170[] = { + 0xB2, 0x10, + 0xB4, 0xA0, 0x00, 0x00, 0x00, 0x00 +}; + +static const unsigned char elvss_control_set_180[] = { + 0xB2, 0x0F, + 0xB4, 0xA0, 0x00, 0x00, 0x00, 0x00 +}; + +static const unsigned char elvss_control_set_190[] = { + 0xB2, 0x15, + 0xB4, 0xA0, 0x00, 0x00, 0x00, 0x00 +}; + +static const unsigned char elvss_control_set_200[] = { + 0xB2, 0x14, + 0xB4, 0xA0, 0x00, 0x00, 0x00, 0x00 +}; + +static const unsigned char elvss_control_set_210[] = { + 0xB2, 0x13, + 0xB4, 0xA0, 0x00, 0x00, 0x00, 0x00 +}; + +static const unsigned char elvss_control_set_220[] = { + 0xB2, 0x12, + 0xB4, 0xA0, 0x00, 0x00, 0x00, 0x00 +}; + +static const unsigned char elvss_control_set_230[] = { + 0xB2, 0x11, + 0xB4, 0xA0, 0x00, 0x00, 0x00, 0x00 +}; + +static const unsigned char elvss_control_set_240[] = { + 0xB2, 0x10, + 0xB4, 0xA0, 0x00, 0x00, 0x00, 0x00 +}; + +static const unsigned char elvss_control_set_250[] = { + 0xB2, 0x10, + 0xB4, 0xA0, 0x00, 0x00, 0x00, 0x00 +}; + +static const unsigned char elvss_control_set_300[] = { + 0xB2, 0x0B, + 0xB4, 0xA0, 0x00, 0x00, 0x00, 0x00 +}; + + +const unsigned char *ELVSS_CONTROL_TABLE[ELVSS_STATUS_MAX] = { + elvss_control_set_20, + elvss_control_set_30, + elvss_control_set_40, + elvss_control_set_50, + elvss_control_set_60, + elvss_control_set_70, + elvss_control_set_80, + elvss_control_set_90, + elvss_control_set_100, + elvss_control_set_110, + elvss_control_set_120, + elvss_control_set_130, + elvss_control_set_140, + elvss_control_set_150, + elvss_control_set_160, + elvss_control_set_170, + elvss_control_set_180, + elvss_control_set_190, + elvss_control_set_200, + elvss_control_set_210, + elvss_control_set_220, + elvss_control_set_230, + elvss_control_set_240, + elvss_control_set_250, + elvss_control_set_300 +}; + + +enum { + ACL_STATUS_0P = 0, + ACL_STATUS_33P, + ACL_STATUS_40P, + ACL_STATUS_50P, + ACL_STATUS_MAX +}; + +static const unsigned char SEQ_ACL_OFF[] = { + 0x55, 0x00, + 0x00 +}; + +static const unsigned char acl_cutoff_33[] = { + 0x55, 0x01, + 0x00 +}; + +static const unsigned char acl_cutoff_40[] = { + 0x55, 0x02, + 0x00 +}; + +static const unsigned char acl_cutoff_50[] = { + 0x55, 0x03, + 0x00 +}; + +static const unsigned char *ACL_CUTOFF_TABLE[ACL_STATUS_MAX] = { + SEQ_ACL_OFF, + acl_cutoff_33, + acl_cutoff_40, + acl_cutoff_50, +}; +#endif /* __EA8061_PARAM_H__ */ diff --git a/drivers/video/samsung/ea8061_volt_tbl.h b/drivers/video/samsung/ea8061_volt_tbl.h new file mode 100644 index 0000000..990e80e --- /dev/null +++ b/drivers/video/samsung/ea8061_volt_tbl.h @@ -0,0 +1,667 @@ +#ifndef __REF_VOLT_TABLE_H__ +#define __REF_VOLT_TABLE_H__ + + +static u32 volt_table_vt[16] = { + 399769600, 391840286, 383910971, 375981657, + 368052342, 360123028, 352193714, 344264399, + 336335085, 328405771, 308582485, 301974723, + 295366961, 288759199, 282151437, 276865227, +}; + +static u32 volt_table_v255[505] = { + 369373895, 368713119, 368052342, 367391566, 366730790, 366070014, 365409238, 364748461, + 364087685, 363426909, 362766133, 362105357, 361444580, 360783804, 360123028, 359462252, + 358801476, 358140700, 357479923, 356819147, 356158371, 355497595, 354836819, 354176042, + 353515266, 352854490, 352193714, 351532938, 350872161, 350211385, 349550609, 348889833, + 348229057, 347568280, 346907504, 346246728, 345585952, 344925176, 344264399, 343603623, + 342942847, 342282071, 341621295, 340960518, 340299742, 339638966, 338978190, 338317414, + 337656637, 336995861, 336335085, 335674309, 335013533, 334352756, 333691980, 333031204, + 332370428, 331709652, 331048875, 330388099, 329727323, 329066547, 328405771, 327744994, + 327084218, 326423442, 325762666, 325101890, 324441113, 323780337, 323119561, 322458785, + 321798009, 321137232, 320476456, 319815680, 319154904, 318494128, 317833351, 317172575, + 316511799, 315851023, 315190247, 314529470, 313868694, 313207918, 312547142, 311886366, + 311225589, 310564813, 309904037, 309243261, 308582485, 307921708, 307260932, 306600156, + 305939380, 305278604, 304617827, 303957051, 303296275, 302635499, 301974723, 301313946, + 300653170, 299992394, 299331618, 298670842, 298010065, 297349289, 296688513, 296027737, + 295366961, 294706184, 294045408, 293384632, 292723856, 292063080, 291402303, 290741527, + 290080751, 289419975, 288759199, 288098422, 287437646, 286776870, 286116094, 285455318, + 284794541, 284133765, 283472989, 282812213, 282151437, 281490660, 280829884, 280169108, + 279508332, 278847556, 278186780, 277526003, 276865227, 276204451, 275543675, 274882899, + 274222122, 273561346, 272900570, 272239794, 271579018, 270918241, 270257465, 269596689, + 268935913, 268275137, 267614360, 266953584, 266292808, 265632032, 264971256, 264310479, + 263649703, 262988927, 262328151, 261667375, 261006598, 260345822, 259685046, 259024270, + 258363494, 257702717, 257041941, 256381165, 255720389, 255059613, 254398836, 253738060, + 253077284, 252416508, 251755732, 251094955, 250434179, 249773403, 249112627, 248451851, + 247791074, 247130298, 246469522, 245808746, 245147970, 244487193, 243826417, 243165641, + 242504865, 241844089, 241183312, 240522536, 239861760, 239200984, 238540208, 237879431, + 237218655, 236557879, 235897103, 235236327, 234575550, 233914774, 233253998, 232593222, + 231932446, 231271669, 230610893, 229950117, 229289341, 228628565, 227967788, 227307012, + 226646236, 225985460, 225324684, 224663907, 224003131, 223342355, 222681579, 222020803, + 221360026, 220699250, 220038474, 219377698, 218716922, 218056145, 217395369, 216734593, + 216073817, 215413041, 214752264, 214091488, 213430712, 212769936, 212109160, 211448383, + 210787607, 210126831, 209466055, 208805279, 208144502, 207483726, 206822950, 206162174, + 205501398, 204840621, 204179845, 203519069, 202858293, 202197517, 201536740, 200875964, + 200215188, 199554412, 198893636, 198232860, 197572083, 196911307, 196250531, 195589755, + 194928979, 194268202, 193607426, 192946650, 192285874, 191625098, 190964321, 190303545, + 189642769, 188981993, 188321217, 187660440, 186999664, 186338888, 185678112, 185017336, + 184356559, 183695783, 183035007, 182374231, 181713455, 181052678, 180391902, 179731126, + 179070350, 178409574, 177748797, 177088021, 176427245, 175766469, 175105693, 174444916, + 173784140, 173123364, 172462588, 171801812, 171141035, 170480259, 169819483, 169158707, + 168497931, 167837154, 167176378, 166515602, 165854826, 165194050, 164533273, 163872497, + 163211721, 162550945, 161890169, 161229392, 160568616, 159907840, 159247064, 158586288, + 157925511, 157264735, 156603959, 155943183, 155282407, 154621630, 153960854, 153300078, + 152639302, 151978526, 151317749, 150656973, 149996197, 149335421, 148674645, 148013868, + 147353092, 146692316, 146031540, 145370764, 144709987, 144049211, 143388435, 142727659, + 142066883, 141406106, 140745330, 140084554, 139423778, 138763002, 138102225, 137441449, + 136780673, 136119897, 135459121, 134798344, 134137568, 133476792, 132816016, 132155240, + 131494463, 130833687, 130172911, 129512135, 128851359, 128190582, 127529806, 126869030, + 126208254, 125547478, 124886701, 124225925, 123565149, 122904373, 122243597, 121582820, + 120922044, 120261268, 119600492, 118939716, 118278940, 117618163, 116957387, 116296611, + 115635835, 114975059, 114314282, 113653506, 112992730, 112331954, 111671178, 111010401, + 110349625, 109688849, 109028073, 108367297, 107706520, 107045744, 106384968, 105724192, + 105063416, 104402639, 103741863, 103081087, 102420311, 101759535, 101098758, 100437982, + 99777206, 99116430, 98455654, 97794877, 97134101, 96473325, 95812549, 95151773, + 94490996, 93830220, 93169444, 92508668, 91847892, 91187115, 90526339, 89865563, + 89204787, 88544011, 87883234, 87222458, 86561682, 85900906, 85240130, 84579353, + 83918577, 83257801, 82597025, 81936249, 81275472, 80614696, 79953920, 79293144, + 78632368, 77971591, 77310815, 76650039, 75989263, 75328487, 74667710, 74006934, + 73346158, 72685382, 72024606, 71363829, 70703053, 70042277, 69381501, 68720725, + 68059948, 67399172, 66738396, 66077620, 65416844, 64756067, 64095291, 63434515, + 62773739, 62112963, 61452186, 60791410, 60130634, 59469858, 58809082, 58148305, + 57487529, 56826753, 56165977, 55505201, 54844424, 54183648, 53522872, 52862096, + 52201320, 51540543, 50879767, 50218991, 49558215, 48897439, 48236662, 47575886, + 46915110, 46254334, 45593558, 44932781, 44272005, 43611229, 42950453, 42289677, + 41628900, 40968124, 40307348, 39646572, 38985796, 38325020, 37664243, 37003467, + 36342691 +}; + +static u32 volt_table_cv_64_dv_320[256] = { + 13107, 13312, 13516, 13721, 13926, 14131, 14336, 14540, + 14745, 14950, 15155, 15360, 15564, 15769, 15974, 16179, + 16384, 16588, 16793, 16998, 17203, 17408, 17612, 17817, + 18022, 18227, 18432, 18636, 18841, 19046, 19251, 19456, + 19660, 19865, 20070, 20275, 20480, 20684, 20889, 21094, + 21299, 21504, 21708, 21913, 22118, 22323, 22528, 22732, + 22937, 23142, 23347, 23552, 23756, 23961, 24166, 24371, + 24576, 24780, 24985, 25190, 25395, 25600, 25804, 26009, + 26214, 26419, 26624, 26828, 27033, 27238, 27443, 27648, + 27852, 28057, 28262, 28467, 28672, 28876, 29081, 29286, + 29491, 29696, 29900, 30105, 30310, 30515, 30720, 30924, + 31129, 31334, 31539, 31744, 31948, 32153, 32358, 32563, + 32768, 32972, 33177, 33382, 33587, 33792, 33996, 34201, + 34406, 34611, 34816, 35020, 35225, 35430, 35635, 35840, + 36044, 36249, 36454, 36659, 36864, 37068, 37273, 37478, + 37683, 37888, 38092, 38297, 38502, 38707, 38912, 39116, + 39321, 39526, 39731, 39936, 40140, 40345, 40550, 40755, + 40960, 41164, 41369, 41574, 41779, 41984, 42188, 42393, + 42598, 42803, 43008, 43212, 43417, 43622, 43827, 44032, + 44236, 44441, 44646, 44851, 45056, 45260, 45465, 45670, + 45875, 46080, 46284, 46489, 46694, 46899, 47104, 47308, + 47513, 47718, 47923, 48128, 48332, 48537, 48742, 48947, + 49152, 49356, 49561, 49766, 49971, 50176, 50380, 50585, + 50790, 50995, 51200, 51404, 51609, 51814, 52019, 52224, + 52428, 52633, 52838, 53043, 53248, 53452, 53657, 53862, + 54067, 54272, 54476, 54681, 54886, 55091, 55296, 55500, + 55705, 55910, 56115, 56320, 56524, 56729, 56934, 57139, + 57344, 57548, 57753, 57958, 58163, 58368, 58572, 58777, + 58982, 59187, 59392, 59596, 59801, 60006, 60211, 60416, + 60620, 60825, 61030, 61235, 61440, 61644, 61849, 62054, + 62259, 62464, 62668, 62873, 63078, 63283, 63488, 63692, + 63897, 64102, 64307, 64512, 64716, 64921, 65126, 65331, +}; + +static const u32 gamma_300_gra_table[256] = { + 0, 2, 7, 17, 32, 53, 78, 110, + 148, 191, 241, 298, 361, 430, 506, 589, + 679, 776, 880, 991, 1109, 1235, 1368, 1508, + 1657, 1812, 1975, 2147, 2325, 2512, 2706, 2909, + 3119, 3338, 3564, 3799, 4042, 4293, 4553, 4820, + 5096, 5381, 5674, 5975, 6285, 6604, 6931, 7267, + 7611, 7965, 8327, 8697, 9077, 9465, 9863, 10269, + 10684, 11109, 11542, 11984, 12436, 12896, 13366, 13845, + 14333, 14830, 15337, 15852, 16378, 16912, 17456, 18009, + 18572, 19144, 19726, 20317, 20918, 21528, 22148, 22778, + 23417, 24066, 24724, 25392, 26070, 26758, 27456, 28163, + 28880, 29607, 30344, 31090, 31847, 32613, 33390, 34176, + 34973, 35779, 36596, 37422, 38259, 39106, 39963, 40830, + 41707, 42594, 43492, 44399, 45317, 46246, 47184, 48133, + 49092, 50062, 51042, 52032, 53032, 54043, 55065, 56097, + 57139, 58192, 59255, 60329, 61413, 62508, 63613, 64729, + 65856, 66993, 68141, 69299, 70469, 71648, 72839, 74040, + 75252, 76475, 77708, 78952, 80207, 81473, 82750, 84037, + 85336, 86645, 87965, 89296, 90638, 91990, 93354, 94729, + 96114, 97511, 98919, 100337, 101767, 103208, 104659, 106122, + 107596, 109081, 110577, 112085, 113603, 115132, 116673, 118225, + 119788, 121362, 122948, 124544, 126152, 127772, 129402, 131044, + 132697, 134361, 136037, 137724, 139422, 141132, 142853, 144586, + 146330, 148085, 149852, 151630, 153419, 155220, 157033, 158857, + 160692, 162540, 164398, 166268, 168150, 170043, 171948, 173864, + 175792, 177731, 179683, 181645, 183620, 185606, 187603, 189613, + 191634, 193667, 195711, 197767, 199835, 201915, 204006, 206109, + 208224, 210351, 212489, 214640, 216802, 218976, 221161, 223359, + 225569, 227790, 230023, 232268, 234525, 236794, 239075, 241368, + 243672, 245989, 248318, 250658, 253011, 255375, 257752, 260141, + 262541, 264954, 267379, 269815, 272264, 274725, 277198, 279683, + 282180, 284689, 287211, 289744, 292290, 294848, 297418, 300000 +}; + +static const u32 gamma_control_set_21[] = { + 0, 9, 38, 89, 163, 260, 381, 526, + 697, 892, 1113, 1359, 1632, 1930, 2255, 2607, + 2985, 3391, 3823, 4283, 4770, 5284, 5826, 6396, + 6994, 7620, 8274, 8957, 9668, 10407, 11175, 11971, + 12797, 13651, 14534, 15446, 16388, 17358, 18358, 19387, + 20446, 21534, 22652, 23799, 24976, 26183, 27420, 28687, + 29983, 31310, 32667, 34054, 35471, 36919, 38397, 39905, + 41444, 43014, 44614, 46244, 47906, 49598, 51321, 53074, + 54859, 56674, 58521, 60399, 62307, 64247, 66218, 68220, + 70253, 72318, 74414, 76542, 78700, 80891, 83113, 85366, + 87651, 89968, 92316, 94696, 97108, 99551, 102027, 104534, + 107073, 109644, 112248, 114883, 117550, 120249, 122980, 125744, + 128540, 131367, 134228, 137120, 140045, 143002, 145991, 149013, + 152068, 155155, 158274, 161426, 164610, 167827, 171077, 174359, + 177674, 181022, 184403, 187816, 191262, 194741, 198253, 201797, + 205375, 208985, 212629, 216305, 220015, 223758, 227533, 231342, + 235184, 239059, 242967, 246909, 250883, 254891, 258932, 263007, + 267115, 271256, 275431, 279639, 283880, 288155, 292464, 296806, + 301181, 305590, 310033, 314509, 319019, 323562, 328139, 332750, + 337394, 342073, 346785, 351530, 356310, 361123, 365971, 370852, + 375767, 380715, 385698, 390715, 395766, 400851, 405969, 411122, + 416309, 421530, 426785, 432074, 437397, 442754, 448146, 453572, + 459032, 464526, 470054, 475617, 481214, 486845, 492511, 498211, + 503945, 509714, 515517, 521355, 527227, 533133, 539074, 545050, + 551060, 557104, 563183, 569297, 575445, 581628, 587845, 594097, + 600384, 606705, 613061, 619452, 625877, 632338, 638833, 645362, + 651927, 658526, 665161, 671830, 678533, 685272, 692046, 698854, + 705698, 712576, 719490, 726438, 733421, 740440, 747493, 754581, + 761705, 768863, 776057, 783286, 790550, 797848, 805183, 812552, + 819956, 827396, 834871, 842381, 849926, 857506, 865122, 872773, + 880460, 888181, 895938, 903731, 911558, 919421, 927320, 935254, + 943223, 951228, 959268, 967343, 975454, 983601, 991783, 1000000 +}; + +static const u32 gamma_control_set_213[] = { + 0, 8, 33, 78, 144, 231, 341, 473, + 628, 807, 1010, 1237, 1489, 1766, 2067, 2395, + 2747, 3126, 3531, 3962, 4419, 4903, 5413, 5951, + 6516, 7107, 7727, 8373, 9048, 9750, 10480, 11238, + 12024, 12839, 13682, 14553, 15453, 16381, 17339, 18325, + 19341, 20385, 21459, 22561, 23694, 24855, 26047, 27268, + 28518, 29798, 31109, 32449, 33819, 35219, 36650, 38111, + 39602, 41123, 42675, 44258, 45871, 47515, 49189, 50894, + 52630, 54397, 56196, 58025, 59885, 61776, 63699, 65653, + 67638, 69655, 71703, 73782, 75894, 78036, 80211, 82417, + 84655, 86925, 89227, 91560, 93926, 96324, 98754, 101216, + 103710, 106236, 108795, 111386, 114009, 116665, 119353, 122074, + 124827, 127613, 130432, 133283, 136167, 139083, 142033, 145015, + 148031, 151079, 154160, 157274, 160422, 163602, 166816, 170063, + 173343, 176656, 180002, 183382, 186795, 190242, 193722, 197236, + 200783, 204363, 207978, 211626, 215307, 219023, 222772, 226554, + 230371, 234221, 238106, 242024, 245976, 249962, 253982, 258037, + 262125, 266247, 270404, 274594, 278819, 283079, 287372, 291700, + 296062, 300458, 304889, 309354, 313854, 318388, 322957, 327560, + 332198, 336870, 341577, 346319, 351096, 355907, 360753, 365633, + 370549, 375499, 380484, 385505, 390560, 395650, 400775, 405935, + 411130, 416360, 421625, 426925, 432260, 437631, 443037, 448478, + 453954, 459466, 465012, 470594, 476212, 481865, 487553, 493277, + 499036, 504831, 510661, 516526, 522428, 528364, 534337, 540345, + 546388, 552468, 558583, 564733, 570920, 577142, 583400, 589694, + 596024, 602389, 608791, 615228, 621702, 628211, 634756, 641337, + 647955, 654608, 661297, 668023, 674785, 681582, 688416, 695286, + 702193, 709135, 716114, 723129, 730180, 737268, 744392, 751552, + 758749, 765982, 773251, 780557, 787900, 795279, 802694, 810146, + 817634, 825159, 832721, 840319, 847954, 855625, 863333, 871078, + 878860, 886678, 894533, 902425, 910353, 918319, 926321, 934360, + 942436, 950548, 958698, 966885, 975108, 983369, 991666, 1000000 +}; + +static const u32 gamma_control_set_215[] = { + 0, 7, 30, 72, 132, 214, 316, 440, + 586, 755, 947, 1162, 1401, 1664, 1951, 2263, + 2599, 2961, 3348, 3761, 4200, 4664, 5155, 5671, + 6215, 6785, 7382, 8006, 8657, 9335, 10041, 10774, + 11535, 12324, 13141, 13986, 14859, 15761, 16691, 17650, + 18637, 19653, 20698, 21772, 22876, 24008, 25170, 26361, + 27581, 28832, 30111, 31421, 32761, 34130, 35530, 36959, + 38419, 39909, 41430, 42981, 44562, 46175, 47817, 49491, + 51195, 52931, 54697, 56494, 58323, 60182, 62073, 63995, + 65949, 67934, 69950, 71998, 74078, 76190, 78333, 80508, + 82715, 84954, 87225, 89528, 91863, 94231, 96630, 99062, + 101526, 104023, 106552, 109114, 111708, 114335, 116994, 119687, + 122412, 125170, 127961, 130784, 133641, 136531, 139454, 142410, + 145399, 148422, 151477, 154566, 157689, 160845, 164034, 167257, + 170513, 173803, 177127, 180485, 183876, 187301, 190759, 194252, + 197779, 201339, 204934, 208562, 212225, 215922, 219653, 223418, + 227217, 231051, 234919, 238821, 242758, 246729, 250735, 254775, + 258850, 262959, 267103, 271282, 275496, 279744, 284027, 288345, + 292697, 297085, 301507, 305965, 310457, 314985, 319548, 324145, + 328778, 333446, 338150, 342888, 347662, 352471, 357316, 362195, + 367111, 372062, 377048, 382070, 387127, 392220, 397348, 402513, + 407713, 412948, 418220, 423527, 428870, 434248, 439663, 445114, + 450600, 456123, 461681, 467276, 472906, 478573, 484276, 490014, + 495790, 501601, 507448, 513332, 519252, 525209, 531201, 537231, + 543296, 549398, 555537, 561712, 567923, 574171, 580456, 586777, + 593135, 599529, 605961, 612429, 618933, 625475, 632053, 638668, + 645320, 652009, 658735, 665497, 672297, 679133, 686007, 692918, + 699865, 706850, 713872, 720931, 728027, 735161, 742331, 749539, + 756784, 764067, 771387, 778744, 786138, 793570, 801039, 808546, + 816090, 823672, 831291, 838947, 846642, 854374, 862143, 869950, + 877795, 885677, 893597, 901555, 909551, 917584, 925655, 933764, + 941911, 950096, 958318, 966579, 974877, 983214, 991588, 1000000 +}; + +static const u32 gamma_control_set_218[] = { + 0 , 6, 26, 63, 117, 190, 282, 395, + 528, 683, 859, 1057, 1278, 1522, 1788, 2078, + 2392, 2730, 3092, 3479, 3891, 4327, 4789, 5277, + 5789, 6328, 6893, 7484, 8102, 8746, 9417, 10114, + 10839, 11591, 12370, 13177, 14012, 14874, 15765, 16683, + 17630, 18605, 19608, 20640, 21701, 22791, 23909, 25057, + 26234, 27440, 28675, 29940, 31235, 32559, 33913, 35297, + 36711, 38155, 39630, 41134, 42669, 44235, 45831, 47458, + 49116, 50804, 52523, 54274, 56055, 57868, 59712, 61587, + 63494, 65432, 67402, 69403, 71436, 73501, 75598, 77727, + 79888, 82081, 84306, 86564, 88853, 91175, 93530, 95917, + 98337, 100789, 103275, 105792, 108343, 110927, 113544, 116193, + 118876, 121592, 124342, 127124, 129940, 132790, 135673, 138589, + 141539, 144523, 147540, 150592, 153677, 156795, 159948, 163135, + 166356, 169611, 172900, 176224, 179582, 182974, 186400, 189861, + 193356, 196886, 200451, 204050, 207684, 211352, 215056, 218794, + 222567, 226375, 230218, 234096, 238010, 241958, 245941, 249960, + 254014, 258104, 262228, 266389, 270584, 274815, 279082, 283384, + 287722, 292096, 296505, 300950, 305431, 309948, 314501, 319090, + 323714, 328375, 333072, 337805, 342574, 347380, 352221, 357099, + 362013, 366964, 371951, 376974, 382034, 387131, 392264, 397434, + 402640, 407883, 413163, 418480, 423833, 429223, 434651, 440115, + 445616, 451154, 456729, 462341, 467990, 473677, 479401, 485161, + 490960, 496795, 502668, 508578, 514526, 520511, 526533, 532593, + 538691, 544826, 550999, 557209, 563457, 569743, 576067, 582428, + 588828, 595265, 601740, 608253, 614804, 621393, 628020, 634685, + 641388, 648129, 654909, 661726, 668582, 675477, 682409, 689380, + 696389, 703437, 710523, 717647, 724810, 732011, 739251, 746530, + 753847, 761203, 768598, 776031, 783503, 791014, 798563, 806152, + 813779, 821445, 829150, 836894, 844677, 852499, 860360, 868261, + 876200, 884178, 892196, 900252, 908348, 916484, 924658, 932872, + 941125, 949417, 957749, 966121, 974531, 982982, 991471, 1000000 +}; + +static const u32 gamma_control_set_22[] = { + 0, 6, 24, 57, 108, 176, 262, 368, + 493, 639, 805, 993, 1202, 1434, 1687, 1964, + 2263, 2586, 2933, 3303, 3698, 4117, 4560, 5029, + 5522, 6041, 6585, 7156, 7752, 8374, 9022, 9697, + 10398, 11127, 11882, 12664, 13474, 14311, 15176, 16068, + 16989, 17937, 18913, 19918, 20952, 22013, 23104, 24223, + 25372, 26549, 27756, 28992, 30257, 31552, 32876, 34231, + 35615, 37029, 38473, 39948, 41452, 42988, 44553, 46149, + 47776, 49434, 51123, 52842, 54593, 56375, 58188, 60032, + 61908, 63815, 65754, 67725, 69728, 71762, 73828, 75927, + 78057, 80220, 82415, 84642, 86902, 89194, 91519, 93876, + 96267, 98690, 101146, 103635, 106157, 108712, 111300, 113921, + 116576, 119265, 121986, 124741, 127530, 130353, 133209, 136099, + 139023, 141981, 144973, 147999, 151059, 154153, 157281, 160444, + 163641, 166873, 170139, 173440, 176775, 180145, 183549, 186989, + 190463, 193973, 197517, 201096, 204711, 208360, 212045, 215765, + 219520, 223311, 227137, 230999, 234896, 238828, 242797, 246801, + 250841, 254916, 259028, 263175, 267359, 271578, 275833, 280125, + 284453, 288816, 293217, 297653, 302126, 306635, 311181, 315763, + 320382, 325037, 329730, 334458, 339224, 344026, 348865, 353741, + 358654, 363604, 368591, 373616, 378677, 383775, 388911, 394084, + 399294, 404541, 409826, 415149, 420508, 425906, 431341, 436813, + 442323, 447871, 453457, 459080, 464742, 470441, 476178, 481953, + 487766, 493617, 499506, 505433, 511398, 517402, 523444, 529524, + 535642, 541799, 547994, 554228, 560500, 566810, 573159, 579547, + 585973, 592439, 598942, 605485, 612066, 618686, 625345, 632043, + 638780, 645556, 652371, 659224, 666117, 673050, 680021, 687031, + 694081, 701170, 708298, 715466, 722673, 729919, 737205, 744531, + 751896, 759300, 766744, 774228, 781751, 789314, 796917, 804560, + 812242, 819964, 827726, 835528, 843370, 851252, 859174, 867136, + 875138, 883180, 891263, 899385, 907548, 915751, 923994, 932277, + 940601, 948965, 957370, 965815, 974301, 982827, 991393, 1000000 +}; + +static const u32 gamma_control_set_221[] = { + 0, 5, 23, 55, 103, 169, 252, 355, + 476, 618, 780, 962, 1166, 1392, 1639, 1909, + 2202, 2517, 2856, 3219, 3605, 4015, 4450, 4909, + 5393, 5902, 6437, 6997, 7582, 8194, 8831, 9495, + 10185, 10901, 11645, 12415, 13213, 14037, 14890, 15769, + 16677, 17612, 18575, 19567, 20587, 21635, 22712, 23817, + 24952, 26115, 27307, 28529, 29780, 31060, 32370, 33710, + 35079, 36478, 37908, 39367, 40857, 42377, 43928, 45509, + 47120, 48763, 50436, 52141, 53876, 55642, 57440, 59269, + 61130, 63022, 64946, 66901, 68889, 70908, 72959, 75042, + 77157, 79305, 81485, 83697, 85942, 88219, 90530, 92872, + 95248, 97656, 100098, 102572, 105080, 107621, 110195, 112802, + 115443, 118117, 120825, 123567, 126342, 129151, 131994, 134871, + 137782, 140727, 143706, 146719, 149766, 152848, 155964, 159115, + 162300, 165520, 168775, 172064, 175388, 178747, 182141, 185569, + 189033, 192532, 196066, 199635, 203240, 206880, 210555, 214266, + 218012, 221794, 225612, 229465, 233354, 237279, 241240, 245236, + 249269, 253338, 257442, 261583, 265760, 269974, 274223, 278509, + 282832, 287191, 291586, 296018, 300487, 304992, 309534, 314113, + 318729, 323381, 328071, 332797, 337561, 342362, 347199, 352074, + 356987, 361936, 366923, 371947, 377009, 382108, 387245, 392419, + 397631, 402881, 408168, 413493, 418856, 424257, 429695, 435172, + 440686, 446239, 451830, 457459, 463126, 468831, 474575, 480356, + 486177, 492035, 497932, 503868, 509842, 515854, 521906, 527996, + 534124, 540292, 546498, 552743, 559027, 565349, 571711, 578112, + 584552, 591030, 597548, 604106, 610702, 617337, 624012, 630726, + 637480, 644273, 651105, 657977, 664888, 671839, 678830, 685860, + 692930, 700039, 707189, 714378, 721607, 728876, 736184, 743533, + 750922, 758350, 765819, 773328, 780877, 788466, 796095, 803765, + 811475, 819225, 827015, 834846, 842717, 850629, 858582, 866574, + 874608, 882682, 890796, 898952, 907148, 915384, 923662, 931980, + 940339, 948740, 957181, 965662, 974185, 982749, 991354, 1000000 +}; + +static const u32 gamma_control_set_222[] = { + 0, 5, 22, 53, 99, 162, 243, 342, + 460, 597, 755, 932, 1131, 1351, 1592, 1856, + 2142, 2450, 2781, 3136, 3514, 3916, 4342, 4792, + 5267, 5767, 6292, 6841, 7417, 8017, 8644, 9297, + 9976, 10681, 11413, 12171, 12957, 13769, 14609, 15476, + 16371, 17293, 18243, 19222, 20228, 21263, 22326, 23418, + 24538, 25688, 26866, 28073, 29310, 30576, 31871, 33197, + 34551, 35936, 37351, 38795, 40270, 41775, 43311, 44877, + 46473, 48101, 49759, 51448, 53169, 54920, 56703, 58516, + 60362, 62239, 64147, 66088, 68060, 70064, 72100, 74168, + 76268, 78401, 80566, 82763, 84993, 87256, 89551, 91879, + 94240, 96634, 99061, 101521, 104014, 106541, 109100, 111694, + 114321, 116981, 119675, 122403, 125165, 127961, 130790, 133654, + 136551, 139483, 142450, 145450, 148485, 151555, 154659, 157797, + 160970, 164178, 167421, 170699, 174012, 177360, 180742, 184160, + 187614, 191102, 194626, 198185, 201780, 205410, 209076, 212778, + 216515, 220288, 224097, 227942, 231823, 235740, 239692, 243682, + 247707, 251768, 255866, 260001, 264171, 268379, 272623, 276903, + 281220, 285574, 289965, 294392, 298856, 303358, 307896, 312471, + 317084, 321734, 326421, 331145, 335906, 340705, 345541, 350415, + 355327, 360276, 365262, 370286, 375349, 380448, 385586, 390762, + 395975, 401227, 406516, 411844, 417210, 422614, 428056, 433537, + 439055, 444613, 450208, 455843, 461515, 467227, 472977, 478765, + 484593, 490459, 496364, 502307, 508290, 514312, 520372, 526472, + 532611, 538789, 545006, 551262, 557558, 563892, 570267, 576680, + 583133, 589626, 596158, 602729, 609341, 615992, 622682, 629412, + 636183, 642992, 649842, 656732, 663662, 670631, 677641, 684691, + 691781, 698911, 706081, 713291, 720542, 727833, 735165, 742537, + 749949, 757402, 764895, 772429, 780003, 787618, 795274, 802971, + 810708, 818486, 826305, 834165, 842065, 850007, 857989, 866013, + 874078, 882183, 890330, 898518, 906748, 915018, 923330, 931683, + 940078, 948514, 956991, 965510, 974070, 982672, 991315, 1000000 +}; + +static const u32 gamma_control_set_223[] = { + 0, 5, 21, 50, 95, 156, 234, 330, + 444, 578, 731, 904, 1097, 1311, 1547, 1804, + 2083, 2385, 2709, 3056, 3426, 3820, 4237, 4679, + 5144, 5635, 6150, 6689, 7255, 7845, 8461, 9103, + 9771, 10465, 11185, 11932, 12705, 13506, 14333, 15188, + 16070, 16980, 17917, 18883, 19876, 20897, 21947, 23025, + 24132, 25267, 26432, 27625, 28848, 30099, 31381, 32691, + 34031, 35402, 36802, 38231, 39692, 41182, 42703, 44254, + 45835, 47448, 49091, 50765, 52470, 54207, 55974, 57773, + 59603, 61465, 63359, 65284, 67241, 69230, 71251, 73304, + 75389, 77507, 79657, 81839, 84054, 86302, 88583, 90896, + 93243, 95622, 98034, 100480, 102959, 105471, 108017, 110596, + 113209, 115856, 118536, 121251, 123999, 126781, 129597, 132448, + 135332, 138251, 141205, 144193, 147215, 150272, 153364, 156490, + 159651, 162848, 166079, 169345, 172647, 175983, 179355, 182762, + 186205, 189683, 193196, 196746, 200330, 203951, 207607, 211300, + 215028, 218792, 222592, 226429, 230301, 234210, 238155, 242137, + 246155, 250209, 254300, 258428, 262592, 266793, 271031, 275306, + 279618, 283966, 288352, 292775, 297235, 301732, 306267, 310838, + 315448, 320094, 324779, 329500, 334260, 339057, 343891, 348764, + 353674, 358623, 363609, 368633, 373695, 378796, 383934, 389111, + 394326, 399580, 404871, 410202, 415570, 420977, 426423, 431908, + 437431, 442992, 448593, 454232, 459911, 465628, 471384, 477180, + 483014, 488887, 494800, 500752, 506743, 512774, 518843, 524953, + 531102, 537290, 543518, 549785, 556092, 562439, 568826, 575252, + 581718, 588224, 594770, 601356, 607982, 614649, 621355, 628101, + 634888, 641715, 648582, 655489, 662437, 669425, 676454, 683524, + 690633, 697784, 704975, 712207, 719479, 726793, 734147, 741542, + 748977, 756454, 763972, 771531, 779131, 786772, 794454, 802177, + 809942, 817748, 825595, 833483, 841413, 849385, 857398, 865452, + 873548, 881685, 889865, 898085, 906348, 914652, 922998, 931386, + 939816, 948288, 956801, 965357, 973955, 982595, 991276, 1000000 +}; + +static const u32 gamma_control_set_224[] = { + 0, 5, 20, 48, 91, 150, 226, 318, + 429, 559, 707, 876, 1064, 1273, 1503, 1754, + 2026, 2321, 2638, 2977, 3340, 3725, 4135, 4567, + 5024, 5505, 6011, 6541, 7096, 7676, 8282, 8913, + 9570, 10253, 10962, 11697, 12459, 13248, 14063, 14906, + 15775, 16672, 17597, 18549, 19530, 20538, 21574, 22639, + 23732, 24854, 26005, 27184, 28393, 29630, 30897, 32194, + 33520, 34875, 36261, 37676, 39121, 40597, 42103, 43639, + 45206, 46804, 48432, 50091, 51781, 53503, 55255, 57039, + 58854, 60701, 62580, 64490, 66432, 68406, 70412, 72450, + 74520, 76623, 78758, 80926, 83126, 85359, 87625, 89924, + 92256, 94621, 97019, 99450, 101915, 104413, 106944, 109510, + 112109, 114742, 117408, 120109, 122843, 125612, 128415, 131252, + 134124, 137030, 139971, 142946, 145956, 149000, 152080, 155194, + 158343, 161528, 164747, 168002, 171292, 174617, 177978, 181375, + 184806, 188274, 191777, 195316, 198891, 202502, 206149, 209832, + 213551, 217306, 221098, 224925, 228790, 232690, 236628, 240602, + 244612, 248659, 252744, 256864, 261022, 265217, 269449, 273718, + 278024, 282368, 286748, 291167, 295622, 300115, 304646, 309214, + 313820, 318463, 323145, 327864, 332621, 337416, 342249, 347120, + 352030, 356977, 361963, 366987, 372050, 377150, 382290, 387468, + 392684, 397939, 403233, 408566, 413937, 419347, 424796, 430285, + 435812, 441378, 446983, 452628, 458312, 464035, 469797, 475599, + 481440, 487321, 493241, 499201, 505201, 511240, 517319, 523438, + 529597, 535795, 542034, 548312, 554631, 560989, 567388, 573827, + 580307, 586826, 593386, 599987, 606627, 613309, 620030, 626793, + 633596, 640439, 647324, 654249, 661215, 668222, 675270, 682358, + 689488, 696659, 703871, 711124, 718418, 725753, 733130, 740548, + 748007, 755508, 763050, 770634, 778259, 785926, 793635, 801385, + 809177, 817010, 824886, 832803, 840762, 848763, 856806, 864891, + 873018, 881188, 889399, 897653, 905948, 914286, 922667, 931089, + 939555, 948062, 956612, 965205, 973840, 982517, 991238, 1000000 +}; + +static const u32 gamma_control_set_225[] = { + 0, 4, 19, 46, 88, 144, 217, 307, + 415, 540, 685, 849, 1032, 1235, 1460, 1705, + 1971, 2259, 2569, 2901, 3256, 3634, 4034, 4459, + 4907, 5379, 5875, 6396, 6941, 7511, 8107, 8727, + 9373, 10045, 10743, 11467, 12218, 12994, 13798, 14628, + 15486, 16370, 17283, 18222, 19190, 20185, 21208, 22259, + 23339, 24448, 25584, 26750, 27945, 29168, 30421, 31704, + 33015, 34357, 35728, 37129, 38559, 40020, 41512, 43033, + 44586, 46168, 47782, 49426, 51102, 52808, 54546, 56314, + 58115, 59947, 61810, 63705, 65632, 67591, 69583, 71606, + 73661, 75749, 77870, 80023, 82208, 84427, 86678, 88962, + 91279, 93630, 96014, 98431, 100881, 103365, 105883, 108434, + 111019, 113638, 116291, 118978, 121699, 124454, 127244, 130068, + 132926, 135819, 138747, 141710, 144707, 147739, 150806, 153909, + 157046, 160218, 163426, 166669, 169948, 173262, 176612, 179997, + 183419, 186876, 190369, 193898, 197462, 201063, 204701, 208374, + 212084, 215830, 219613, 223432, 227288, 231181, 235110, 239076, + 243079, 247119, 251196, 255311, 259462, 263650, 267876, 272139, + 276440, 280778, 285154, 289567, 294018, 298507, 303034, 307598, + 312200, 316841, 321519, 326236, 330991, 335784, 340615, 345485, + 350393, 355339, 360325, 365348, 370411, 375512, 380652, 385831, + 391049, 396306, 401601, 406936, 412310, 417723, 423176, 428668, + 434199, 439769, 445379, 451029, 456718, 462447, 468215, 474024, + 479872, 485760, 491687, 497655, 503663, 509711, 515799, 521927, + 528096, 534305, 540554, 546843, 553173, 559544, 565955, 572406, + 578899, 585432, 592005, 598620, 605275, 611971, 618709, 625487, + 632306, 639167, 646068, 653011, 659995, 667020, 674087, 681195, + 688345, 695536, 702768, 710042, 717358, 724715, 732115, 739556, + 747038, 754563, 762130, 769738, 777389, 785081, 792816, 800593, + 808412, 816273, 824177, 832123, 840111, 848142, 856215, 864331, + 872489, 880690, 888934, 897220, 905549, 913921, 922335, 930793, + 939293, 947836, 956423, 965052, 973724, 982440, 991199, 1000000 +}; + +static const u32 *GAMMA_CONTROL_TABLE[G_MAX] = { + gamma_control_set_21, + gamma_control_set_213, + gamma_control_set_215, + gamma_control_set_218, + gamma_control_set_22, + gamma_control_set_221, + gamma_control_set_222, + gamma_control_set_223, + gamma_control_set_224, + gamma_control_set_225 +}; + +static const struct str_flookup_table flookup_table[302] = { + { 0, 0}, { 1, 20}, + { 20, 7}, { 27, 5}, + { 32, 4}, { 36, 4}, + { 40, 4}, { 44, 3}, + { 47, 3}, { 50, 2}, + { 52, 3}, { 55, 2}, + { 57, 3}, { 60, 2}, + { 62, 2}, { 64, 2}, + { 66, 2}, { 68, 2}, + { 70, 1}, { 71, 2}, + { 73, 2}, { 75, 2}, + { 77, 1}, { 78, 2}, + { 80, 1}, { 81, 2}, + { 83, 1}, { 84, 2}, + { 86, 1}, { 87, 2}, + { 89, 1}, { 90, 1}, + { 91, 2}, { 93, 1}, + { 94, 1}, { 95, 2}, + { 97, 1}, { 98, 1}, + { 99, 1}, {100, 1}, + {101, 2}, {103, 1}, + {104, 1}, {105, 1}, + {106, 1}, {107, 1}, + {108, 1}, {109, 1}, + {110, 1}, {111, 1}, + {112, 1}, {113, 1}, + {114, 1}, {115, 1}, + {116, 1}, {117, 1}, + {118, 1}, {119, 1}, + {120, 1}, {121, 1}, + {122, 1}, {123, 1}, + {124, 1}, {125, 1}, + {126, 1}, {127, 1}, + {128, 1}, {129, 1}, + { 0, 0}, {130, 1}, + {131, 1}, {132, 1}, + {133, 1}, {134, 1}, + { 0, 0}, {135, 1}, + {136, 1}, {137, 1}, + {138, 1}, {139, 1}, + { 0, 0}, {140, 1}, + {141, 1}, {142, 1}, + { 0, 0}, {143, 1}, + {144, 1}, {145, 1}, + {146, 1}, { 0, 0}, + {147, 1}, {148, 1}, + {149, 1}, { 0, 0}, + {150, 1}, {151, 1}, + { 0, 0}, {152, 1}, + {153, 1}, {154, 1}, + { 0, 0}, {155, 1}, + {156, 1}, { 0, 0}, + {157, 1}, {158, 1}, + { 0, 0}, {159, 1}, + {160, 1}, { 0, 0}, + {161, 1}, {162, 1}, + { 0, 0}, {163, 1}, + {164, 1}, { 0, 0}, + {165, 1}, {166, 1}, + { 0, 0}, {167, 1}, + {168, 1}, { 0, 0}, + {169, 1}, {170, 1}, + { 0, 0}, {171, 1}, + { 0, 0}, {172, 1}, + {173, 1}, { 0, 0}, + {174, 1}, { 0, 0}, + {175, 1}, {176, 1}, + { 0, 0}, {177, 1}, + { 0, 0}, {178, 1}, + {179, 1}, { 0, 0}, + {180, 1}, { 0, 0}, + {181, 1}, {182, 1}, + { 0, 0}, {183, 1}, + { 0, 0}, {184, 1}, + { 0, 0}, {185, 1}, + {186, 1}, { 0, 0}, + {187, 1}, { 0, 0}, + {188, 1}, { 0, 0}, + {189, 1}, { 0, 0}, + {190, 1}, {191, 1}, + { 0, 0}, {192, 1}, + { 0, 0}, {193, 1}, + { 0, 0}, {194, 1}, + { 0, 0}, {195, 1}, + { 0, 0}, {196, 1}, + { 0, 0}, {197, 1}, + {198, 1}, { 0, 0}, + {199, 1}, { 0, 0}, + {200, 1}, { 0, 0}, + {201, 1}, { 0, 0}, + {202, 1}, { 0, 0}, + {203, 1}, { 0, 0}, + {204, 1}, { 0, 0}, + {205, 1}, { 0, 0}, + {206, 1}, { 0, 0}, + {207, 1}, { 0, 0}, + {208, 1}, { 0, 0}, + {209, 1}, { 0, 0}, + {210, 1}, { 0, 0}, + {211, 1}, { 0, 0}, + {212, 1}, { 0, 0}, + {213, 1}, { 0, 0}, + { 0, 0}, {214, 1}, + { 0, 0}, {215, 1}, + { 0, 0}, {216, 1}, + { 0, 0}, {217, 1}, + { 0, 0}, {218, 1}, + { 0, 0}, {219, 1}, + { 0, 0}, {220, 1}, + { 0, 0}, {221, 1}, + { 0, 0}, { 0, 0}, + {222, 1}, { 0, 0}, + {223, 1}, { 0, 0}, + {224, 1}, { 0, 0}, + {225, 1}, { 0, 0}, + { 0, 0}, {226, 1}, + { 0, 0}, {227, 1}, + { 0, 0}, {228, 1}, + { 0, 0}, {229, 1}, + { 0, 0}, { 0, 0}, + {230, 1}, { 0, 0}, + {231, 1}, { 0, 0}, + {232, 1}, { 0, 0}, + {233, 1}, { 0, 0}, + { 0, 0}, {234, 1}, + { 0, 0}, {235, 1}, + { 0, 0}, { 0, 0}, + {236, 1}, { 0, 0}, + {237, 1}, { 0, 0}, + {238, 1}, { 0, 0}, + { 0, 0}, {239, 1}, + { 0, 0}, {240, 1}, + { 0, 0}, {241, 1}, + { 0, 0}, { 0, 0}, + {242, 1}, { 0, 0}, + {243, 1}, { 0, 0}, + { 0, 0}, {244, 1}, + { 0, 0}, {245, 1}, + { 0, 0}, { 0, 0}, + {246, 1}, { 0, 0}, + {247, 1}, { 0, 0}, + { 0, 0}, {248, 1}, + { 0, 0}, {249, 1}, + { 0, 0}, { 0, 0}, + {250, 1}, { 0, 0}, + {251, 1}, { 0, 0}, + { 0, 0}, {252, 1}, + { 0, 0}, {253, 1}, + { 0, 0}, { 0, 0}, + {254, 1}, { 0, 0}, + { 0, 0}, {255, 1}, +}; + +#endif + diff --git a/drivers/video/samsung/lcdfreq.c b/drivers/video/samsung/lcdfreq.c index 8c25c22..7e4af07 100644 --- a/drivers/video/samsung/lcdfreq.c +++ b/drivers/video/samsung/lcdfreq.c @@ -21,8 +21,6 @@ #include "s3cfb.h" -#define LCDFREQ_LIMIT_HZ 40 - enum lcdfreq_level_idx { LEVEL_NORMAL, LEVEL_LIMIT, @@ -217,30 +215,44 @@ int get_divider(struct fb_info *fb) fimd_div = gcd(lcdfreq->table[LEVEL_NORMAL].cmu_clkdiv, lcdfreq->table[LEVEL_LIMIT].cmu_clkdiv); + if ((!fimd_div) || (fimd_div > 16)) { + dev_info(fb->dev, "%s skip, %d\n", __func__, __LINE__); + goto err; + } + lcdfreq->table[LEVEL_NORMAL].cmu_clkdiv /= fimd_div; lcdfreq->table[LEVEL_LIMIT].cmu_clkdiv /= fimd_div; dev_info(fb->dev, "%s rate is %d, fimd divider=%d\n", clk->name, rate, fimd_div); + fimd_div--; for (i = 0; i < LCDFREQ_LEVEL_END; i++) { - lcdfreq->table[i].cmu_clkdiv--; - dev_info(fb->dev, "%dHZ divider is %d\n", + if (lcdfreq->table[i].cmu_clkdiv > 16) { + dev_info(fb->dev, "%s skip, %d\n", __func__, __LINE__); + goto err; + } + dev_info(fb->dev, "%dhz div is %d\n", lcdfreq->table[i].hz, lcdfreq->table[i].cmu_clkdiv); + lcdfreq->table[i].cmu_clkdiv--; } reg = (readl(fbdev->regs + S3C_VIDCON0) & (S3C_VIDCON0_CLKVAL_F(0xff))) >> 6; - reg++; - - if (fimd_div != reg) - return -EINVAL; + if (fimd_div != reg) { + dev_info(fb->dev, "%s skip, %d\n", __func__, __LINE__); + goto err; + } reg = (readl(sclk->reg_div.reg)) >> sclk->reg_div.shift; reg &= 0xf; - - if (lcdfreq->table[LEVEL_NORMAL].cmu_clkdiv != reg) - return -EINVAL; + if (lcdfreq->table[LEVEL_NORMAL].cmu_clkdiv != reg) { + dev_info(fb->dev, "%s skip, %d\n", __func__, __LINE__); + goto err; + } return 0; + +err: + return -EINVAL; } static ssize_t level_show(struct device *dev, @@ -256,7 +268,7 @@ static ssize_t level_show(struct device *dev, return -EINVAL; } - return sprintf(buf, "%dHZ, div=%d\n", lcdfreq->table[lcdfreq->level].hz, get_div(fbdev)); + return sprintf(buf, "%dhz, div=%d\n", lcdfreq->table[lcdfreq->level].hz, get_div(fbdev)); } static ssize_t level_store(struct device *dev, @@ -296,12 +308,61 @@ static ssize_t usage_show(struct device *dev, return sprintf(buf, "%d\n", atomic_read(&lcdfreq->usage)); } +#if 0 +static ssize_t freq_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct fb_info *fb = dev_get_drvdata(dev); + struct s3cfb_window *win = fb->par; + struct s3cfb_global *fbdev = get_fimd_global(win->id); + struct s3cfb_lcd *lcd = fbdev->lcd; + + return sprintf(buf, "%dhz, hfp=%d, hbp=%d, hsw=%d, div=%d\n", lcd->freq, + lcd->timing.h_fp, lcd->timing.h_bp, lcd->timing.h_sw, get_div(fbdev)+1); +} + +extern void s5p_dsim_set_lcd_freq_change(struct s3cfb_lcd_timing *timing); + +static ssize_t freq_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct fb_info *fb = dev_get_drvdata(dev); + struct s3cfb_window *win = fb->par; + struct s3cfb_global *fbdev = get_fimd_global(win->id); + struct s3cfb_lcd *lcd = fbdev->lcd; + struct s3cfb_lcd_timing *timing = &lcd->timing; + struct fb_var_screeninfo *var = &fb->var; + + lcd->freq_limit = 0; + sscanf(buf, "%d %d %d %d", &lcd->freq, + &timing->h_fp, &timing->h_bp, &timing->h_sw); + + var->hsync_len = timing->h_sw; + var->left_margin = timing->h_bp; + var->right_margin = timing->h_fp; + + 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)); + var->pixclock = KHZ2PICOS(var->pixclock/1000); + + s5p_dsim_set_lcd_freq_change(timing); + + return count; +} + +static DEVICE_ATTR(freq, S_IRUGO|S_IWUSR, freq_show, freq_store); +#endif + static DEVICE_ATTR(level, S_IRUGO|S_IWUSR, level_show, level_store); static DEVICE_ATTR(usage, S_IRUGO, usage_show, NULL); static struct attribute *lcdfreq_attributes[] = { &dev_attr_level.attr, &dev_attr_usage.attr, +/* &dev_attr_freq.attr, */ NULL, }; @@ -323,7 +384,7 @@ static void lcdfreq_early_suspend(struct early_suspend *h) atomic_set(&lcdfreq->usage, 0); mutex_unlock(&lcdfreq->lock); - return ; + return; } static void lcdfreq_late_resume(struct early_suspend *h) @@ -392,7 +453,7 @@ static void lcdfreq_status_work(struct work_struct *work) cancel_delayed_work(&lcdfreq->work); - dev_info(lcdfreq->dev, "\tHZ=%d, usage=%d\n", hz, atomic_read(&lcdfreq->usage)); + dev_info(lcdfreq->dev, "\thz=%d, usage=%d\n", hz, atomic_read(&lcdfreq->usage)); schedule_delayed_work(&lcdfreq->work, HZ*120); } @@ -405,8 +466,8 @@ int lcdfreq_init(struct fb_info *fb) struct fb_var_screeninfo *var = &fb->var; struct lcdfreq_info *lcdfreq = NULL; - u32 vclk = 0; - int ret; + u32 vclk; + int ret = 0; lcdfreq = kzalloc(sizeof(struct lcdfreq_info), GFP_KERNEL); if (!lcdfreq) { @@ -415,6 +476,11 @@ int lcdfreq_init(struct fb_info *fb) goto err_1; } + if (!lcd->freq_limit) { + ret = -EINVAL; + goto err_2; + } + fbdev->data = lcdfreq; lcdfreq->dev = fb->dev; @@ -430,7 +496,7 @@ int lcdfreq_init(struct fb_info *fb) lcdfreq->table[LEVEL_NORMAL].pixclock = var->pixclock; lcdfreq->table[LEVEL_NORMAL].hz = lcd->freq; - vclk = (LCDFREQ_LIMIT_HZ * + vclk = (lcd->freq_limit * (var->left_margin + var->right_margin + var->hsync_len + var->xres) * (var->upper_margin + var->lower_margin @@ -438,11 +504,11 @@ int lcdfreq_init(struct fb_info *fb) lcdfreq->table[LEVEL_LIMIT].level = LEVEL_LIMIT; lcdfreq->table[LEVEL_LIMIT].vclk = vclk; lcdfreq->table[LEVEL_LIMIT].pixclock = KHZ2PICOS(vclk/1000); - lcdfreq->table[LEVEL_LIMIT].hz = LCDFREQ_LIMIT_HZ; + lcdfreq->table[LEVEL_LIMIT].hz = lcd->freq_limit; ret = get_divider(fb); if (ret < 0) { - pr_err("fail to init lcd freq switch"); + pr_err("skip lcd freq switch init"); fbdev->data = NULL; goto err_1; } @@ -489,4 +555,3 @@ err_1: return ret; } - diff --git a/drivers/video/samsung/ld9040.c b/drivers/video/samsung/ld9040.c index 2ff3af0..9c75788 100644 --- a/drivers/video/samsung/ld9040.c +++ b/drivers/video/samsung/ld9040.c @@ -75,7 +75,7 @@ struct lcd_info { unsigned int auto_brightness; unsigned int ldi_enable; unsigned int acl_enable; - unsigned int cur_acl; + unsigned int current_acl; struct mutex lock; struct mutex bl_lock; struct lcd_device *ld; @@ -461,56 +461,49 @@ elvss_err: return ret; } -static int ld9040_set_acl(struct lcd_info *lcd) +static int ld9040_set_acl(struct lcd_info *lcd, u8 force) { - int ret = 0; + int ret = 0, enable, level; + u32 candela = candela_table[lcd->bl]; struct ld9040_panel_data *pdata = lcd->lcd_pd->pdata; - if (lcd->acl_enable) { - if (lcd->cur_acl == 0) { - if (lcd->bl == 0 || lcd->bl == 1) { - ret = ld9040_panel_send_sequence(lcd, pdata->acl_table[0]); - dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d, acl_off\n", __func__, lcd->cur_acl); - } else { - ret = ld9040_panel_send_sequence(lcd, pdata->acl_on); - dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d, acl_on\n", __func__, lcd->cur_acl); - } - } - switch (lcd->bl) { - case GAMMA_30CD ... GAMMA_40CD: /* 30cd ~ 40cd */ - if (lcd->cur_acl != 0) { - ret = ld9040_panel_send_sequence(lcd, pdata->acl_table[0]); - lcd->cur_acl = 0; - dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d\n", __func__, lcd->cur_acl); - } - break; - case GAMMA_70CD ... GAMMA_250CD: /* 70cd ~ 250cd */ - if (lcd->cur_acl != 40) { - ret = ld9040_panel_send_sequence(lcd, pdata->acl_table[1]); - lcd->cur_acl = 40; - dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d\n", __func__, lcd->cur_acl); - } - break; - default: - if (lcd->cur_acl != 50) { - ret = ld9040_panel_send_sequence(lcd, pdata->acl_table[2]); - lcd->cur_acl = 50; - dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d\n", __func__, lcd->cur_acl); - } - break; - } - } else { - ret = ld9040_panel_send_sequence(lcd, pdata->acl_table[0]); - lcd->cur_acl = 0; - dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d\n", __func__, lcd->cur_acl); + switch (candela) { + case 0 ... 69: + level = ACL_STATUS_0P; + break; + case 70 ... 250: + level = ACL_STATUS_40P; + break; + default: + level = ACL_STATUS_50P; + break; } - if (ret) { + if (!lcd->acl_enable) + level = ACL_STATUS_0P; + + enable = !!level; + + //if (force || lcd->acl_enable != enable) { + dev_dbg(&lcd->ld->dev, "acl turn %s\n", enable ? "on" : "off"); + if (enable) + ret = ld9040_panel_send_sequence(lcd, pdata->acl_on); + else { + ret = ld9040_panel_send_sequence(lcd, pdata->acl_table[ACL_STATUS_0P]); + goto exit; + } + //} + + //if (force || lcd->current_acl != level) { + ret = ld9040_panel_send_sequence(lcd, pdata->acl_table[level]); + lcd->current_acl = level; + dev_dbg(&lcd->ld->dev, "current_acl = %d\n", lcd->current_acl); + //} + + if (ret) ret = -EPERM; - goto acl_err; - } -acl_err: +exit: return ret; } @@ -578,7 +571,7 @@ static int update_brightness(struct lcd_info *lcd, u8 force) ret = ld9040_gamma_ctl(lcd); - ret |= ld9040_set_acl(lcd); + ret |= ld9040_set_acl(lcd, force); ret |= ld9040_set_elvss(lcd); @@ -836,7 +829,7 @@ device_attribute *attr, const char *buf, size_t size) mutex_lock(&lcd->bl_lock); lcd->acl_enable = value; if (lcd->ldi_enable) - ld9040_set_acl(lcd); + ld9040_set_acl(lcd, 0); mutex_unlock(&lcd->bl_lock); } } @@ -1076,7 +1069,7 @@ static int ld9040_probe(struct spi_device *spi) lcd->current_gamma_mode = 0; lcd->acl_enable = 0; - lcd->cur_acl = 0; + lcd->current_acl = 0; lcd->auto_brightness = 1; diff --git a/drivers/video/samsung/lms501xx.h b/drivers/video/samsung/lms501xx.h new file mode 100644 index 0000000..0d5ca54 --- /dev/null +++ b/drivers/video/samsung/lms501xx.h @@ -0,0 +1,156 @@ +#ifndef __LMS501XX_H__ +#define __LMS501XX_H__ + +const unsigned char SEQ_SET_EXTC[] = { + 0xB9, + 0xFF, 0x83, 0x69, +}; + +const unsigned char SEQ_SET_MIPI_DSI[] = { + 0xBA, + 0x11, 0x00, 0x16, 0xC6, 0x80, 0x0A, 0x00, 0x10, 0x24, 0x02, + 0x21, 0x21, 0x9A, 0x11, 0x14, +}; + +const unsigned char SEQ_SET_GIP[] = { + 0xD5, + 0x00, 0x00, 0x09, 0x03, 0x2D, 0x00, 0x00, 0x12, 0x31, 0x23, + 0x00, 0x00, 0x10, 0x70, 0x37, 0x00, 0x00, 0x0D, 0x01, 0x40, + 0x37, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0xEF, 0x00, 0x13, 0x57, + 0x71, 0x00, 0x00, 0x00, 0xEF, 0xEF, 0x00, 0x64, 0x20, 0x06, + 0x00, 0x00, 0x00, 0xEF, 0xEF, 0x00, 0x02, 0x46, 0x60, 0x00, + 0x00, 0x00, 0xEF, 0xEF, 0x00, 0x75, 0x31, 0x17, 0x00, 0x00, + 0x00, 0xEF, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0F, + 0xFC, 0x0C, 0xFC, 0xFF, 0x0F, 0xFC, 0x0C, 0xFC, 0xFF, 0x00, + 0x00, 0x5A, +}; + +const unsigned char SEQ_SET_POWER[] = { + 0xB1, + 0x0A, 0x83, 0x77, 0x00, 0x91, 0x0F, 0x1C, 0x1C, 0x0C, 0x2A, + 0x20, 0x4E, +}; + +const unsigned char SEQ_SET_RGB[] = { + 0xB3, + 0x03, 0x00, 0x30, 0x0B, +}; + +const unsigned char SEQ_SET_CYC[] = { + 0xB4, 0x02, +}; + +const unsigned char SEQ_SET_VCOM[] = { + 0xB6, + 0xB1, 0xa8, 0x00, +}; + +const unsigned char SEQ_SET_PTBA[] = { + 0xBF, + 0x5F, 0x00, 0x00, 0x06, +}; + +const unsigned char SEQ_SET_PANEL[] = { + 0xCC, 0x0e, +}; + +const unsigned char SEQ_SET_DGC[] = { + 0xC1, 0x00, +}; + +const unsigned char SEQ_SET_STBA[] = { + 0xC0, + 0x73, 0x50, 0x00, 0x1f, 0x04, 0x04, +}; + +const unsigned char SEQ_SET_EQ[] = { + 0xE3, + 0x03, 0x03, 0x03, 0x03, +}; + +const unsigned char SEQ_SET_VCOM_POWER[] = { + 0xEA, 0x7A, +}; + +const unsigned char SEQ_SET_ECO[] = { + 0xC6, 0x40, +}; + +const unsigned char SEQ_SET_GAMMA[] = { + 0xE0, + 0x00, 0x1C, 0x20, 0x35, 0x3A, 0x3F, 0x31, 0x4c, 0x08, 0x0E, + 0x0E, 0x12, 0x13, 0x11, 0x13, 0x18, 0x1D, 0x00, 0x1C, 0x20, + 0x35, 0x3A, 0x3F, 0x31, 0x4c, 0x08, 0x0E, 0x0E, 0x12, 0x13, + 0x11, 0x13, 0x18, 0x1D, 0x01, +}; + +const unsigned char SEQ_SET_CABC_PWM[] = { + 0xC9, + 0x0F, 0x00, +}; + +unsigned char SEQ_SET_BL[] = { + 0x51, 0xFF, +}; + +const unsigned char SEQ_SET_DISP[] = { + 0x53, 0x24, +}; + +const unsigned char SEQ_SET_CABC_ON[] = { + 0x55, 0x02, +}; + +const unsigned char SEQ_SET_CABC_OFF[] = { + 0x55, 0x00, +}; + +const unsigned char SEQ_SLEEP_IN[] = { + 0x10, +}; + +const unsigned char SEQ_SLEEP_OUT[] = { + 0x11, +}; + +const unsigned char SEQ_DISPLAY_ON[] = { + 0x29, +}; + +const unsigned char SEQ_DISPLAY_OFF[] = { + 0x28, +}; + +enum { + GAMMA_30CD = 0, + GAMMA_40CD, + GAMMA_70CD, + GAMMA_90CD, + GAMMA_100CD, + GAMMA_110CD, + GAMMA_120CD, + GAMMA_130CD, + GAMMA_140CD, + GAMMA_150CD, + GAMMA_160CD, + GAMMA_170CD, + GAMMA_180CD, + GAMMA_190CD, + GAMMA_200CD, + GAMMA_210CD, + GAMMA_220CD, + GAMMA_230CD, + GAMMA_240CD, + GAMMA_250CD, + GAMMA_260CD, + GAMMA_270CD, + GAMMA_280CD, + GAMMA_290CD, + GAMMA_300CD = 24, + GAMMA_MAX +}; + +#define GAMMA_PARAM_SIZE 26 + +#endif /* __LMS501XX_H__ */ diff --git a/drivers/video/samsung/mdnie_table_baffin.h b/drivers/video/samsung/mdnie_table_baffin.h new file mode 100644 index 0000000..a3df222 --- /dev/null +++ b/drivers/video/samsung/mdnie_table_baffin.h @@ -0,0 +1,803 @@ +#ifndef __MDNIE_TABLE_H__ +#define __MDNIE_TABLE_H__ + +#include "mdnie.h" + + +static const unsigned short tune_dynamic_gallery[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x008c, + /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x0092, 0x0080, /*DE pe*/ + 0x0093, 0x0080, /*DE pf*/ + 0x0094, 0x0080, /*DE pb*/ + 0x0095, 0x0080, /*DE ne*/ + 0x0096, 0x0080, /*DE nf*/ + 0x0097, 0x0080, /*DE nb*/ + 0x0098, 0x1000, /*DE max ratio*/ + 0x0099, 0x0100, /*DE min ratio*/ + 0x00b0, 0x1010, /*CS hg ry*/ + 0x00b1, 0x1010, /*CS hg gc*/ + 0x00b2, 0x1010, /*CS hg bm*/ + 0x00b3, 0x1404, /*CS weight grayTH*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x001f, 0x0080, /*CC chsel strength*/ + 0x0020, 0x0000, /*CC lut r 0*/ + 0x0021, 0x0293, /*CC lut r 16 144*/ + 0x0022, 0x1aa5, /*CC lut r 32 160*/ + 0x0023, 0x29b7, /*CC lut r 48 176*/ + 0x0024, 0x39c8, /*CC lut r 64 192*/ + 0x0025, 0x4bd8, /*CC lut r 80 208*/ + 0x0026, 0x5de6, /*CC lut r 96 224*/ + 0x0027, 0x6ff4, /*CC lut r 112 240*/ + 0x0028, 0x81ff, /*CC lut r 128 255*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_dynamic_ui[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x008c, + /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x0092, 0x0040, /*DE pe*/ + 0x0093, 0x0040, /*DE pf*/ + 0x0094, 0x0040, /*DE pb*/ + 0x0095, 0x0040, /*DE ne*/ + 0x0096, 0x0040, /*DE nf*/ + 0x0097, 0x0040, /*DE nb*/ + 0x0098, 0x1000, /*DE max ratio*/ + 0x0099, 0x0100, /*DE min ratio*/ + 0x00b0, 0x1010, /*CS hg ry*/ + 0x00b1, 0x1010, /*CS hg gc*/ + 0x00b2, 0x1010, /*CS hg bm*/ + 0x00b3, 0x1804, /*CS weight grayTH*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x001f, 0x0080, /*CC chsel strength*/ + 0x0020, 0x0000, /*CC lut r 0*/ + 0x0021, 0x0293, /*CC lut r 16 144*/ + 0x0022, 0x1aa5, /*CC lut r 32 160*/ + 0x0023, 0x29b7, /*CC lut r 48 176*/ + 0x0024, 0x39c8, /*CC lut r 64 192*/ + 0x0025, 0x4bd8, /*CC lut r 80 208*/ + 0x0026, 0x5de6, /*CC lut r 96 224*/ + 0x0027, 0x6ff4, /*CC lut r 112 240*/ + 0x0028, 0x81ff, /*CC lut r 128 255*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_dynamic_video[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x008c, + /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x0092, 0x0080, /*DE pe*/ + 0x0093, 0x0080, /*DE pf*/ + 0x0094, 0x0080, /*DE pb*/ + 0x0095, 0x0080, /*DE ne*/ + 0x0096, 0x0080, /*DE nf*/ + 0x0097, 0x0080, /*DE nb*/ + 0x0098, 0x1000, /*DE max ratio*/ + 0x0099, 0x0100, /*DE min ratio*/ + 0x00b0, 0x1010, /*CS hg ry*/ + 0x00b1, 0x1010, /*CS hg gc*/ + 0x00b2, 0x1010, /*CS hg bm*/ + 0x00b3, 0x1404, /*CS weight grayTH*/ + 0x00e1, 0xff00, /*SCR RrCr*/ + 0x00e2, 0x00ff, /*SCR RgCg*/ + 0x00e3, 0x00ff, /*SCR RbCb*/ + 0x00e4, 0x00ff, /*SCR GrMr*/ + 0x00e5, 0xff00, /*SCR GgMg*/ + 0x00e6, 0x00ff, /*SCR GbMb*/ + 0x00e7, 0x00ff, /*SCR BrYr*/ + 0x00e8, 0x00ff, /*SCR BgYg*/ + 0x00e9, 0xff00, /*SCR BbYb*/ + 0x00ea, 0x00ff, /*SCR KrWr*/ + 0x00eb, 0x00ff, /*SCR KgWg*/ + 0x00ec, 0x00ff, /*SCR KbWb*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x001f, 0x0080, /*CC chsel strength*/ + 0x0020, 0x0000, /*CC lut r 0*/ + 0x0021, 0x0293, /*CC lut r 16 144*/ + 0x0022, 0x1aa5, /*CC lut r 32 160*/ + 0x0023, 0x29b7, /*CC lut r 48 176*/ + 0x0024, 0x39c8, /*CC lut r 64 192*/ + 0x0025, 0x4bd8, /*CC lut r 80 208*/ + 0x0026, 0x5de6, /*CC lut r 96 224*/ + 0x0027, 0x6ff4, /*CC lut r 112 240*/ + 0x0028, 0x81ff, /*CC lut r 128 255*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_dynamic_vt[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x008e, + /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0005, /*FA cs1 | de8 dnr4 hdr2 fa1*/ + 0x0039, 0x0080, /*FA dnrWeight*/ + 0x0080, 0x0fff, /*DNR dirTh*/ + 0x0081, 0x19ff, /*DNR dirnumTh decon7Th*/ + 0x0082, 0xff16, /*DNR decon5Th maskTh*/ + 0x0083, 0x0000, /*DNR blTh*/ + 0x0092, 0x00e0, /*DE pe*/ + 0x0093, 0x00e0, /*DE pf*/ + 0x0094, 0x00e0, /*DE pb*/ + 0x0095, 0x00e0, /*DE ne*/ + 0x0096, 0x00e0, /*DE nf*/ + 0x0097, 0x00e0, /*DE nb*/ + 0x0098, 0x1000, /*DE max ratio*/ + 0x0099, 0x0010, /*DE min ratio*/ + 0x00b0, 0x1010, /*CS hg ry*/ + 0x00b1, 0x1010, /*CS hg gc*/ + 0x00b2, 0x1010, /*CS hg bm*/ + 0x00b3, 0x1a04, /*CS weight grayTH*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x001f, 0x0080, /*CC chsel strength*/ + 0x0020, 0x0000, /*CC lut r 0*/ + 0x0021, 0x0293, /*CC lut r 16 144*/ + 0x0022, 0x1aa5, /*CC lut r 32 160*/ + 0x0023, 0x29b7, /*CC lut r 48 176*/ + 0x0024, 0x39c8, /*CC lut r 64 192*/ + 0x0025, 0x4bd8, /*CC lut r 80 208*/ + 0x0026, 0x5de6, /*CC lut r 96 224*/ + 0x0027, 0x6ff4, /*CC lut r 112 240*/ + 0x0028, 0x81ff, /*CC lut r 128 255*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_movie_gallery[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x00a0, + /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x00e1, 0xd6ac, /*SCR RrCr*/ + 0x00e2, 0x32ff, /*SCR RgCg*/ + 0x00e3, 0x2ef0, /*SCR RbCb*/ + 0x00e4, 0xa5fa, /*SCR GrMr*/ + 0x00e5, 0xff4d, /*SCR GgMg*/ + 0x00e6, 0x59ff, /*SCR GbMb*/ + 0x00e7, 0x00ff, /*SCR BrYr*/ + 0x00e8, 0x00fb, /*SCR BgYg*/ + 0x00e9, 0xff61, /*SCR BbYb*/ + 0x00ea, 0x00ff, /*SCR KrWr*/ + 0x00eb, 0x00f8, /*SCR KgWg*/ + 0x00ec, 0x00f1, /*SCR KbWb*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x001f, 0x0080, /*CC chsel strength*/ + 0x0020, 0x0000, /*CC lut r 0*/ + 0x0021, 0x0290, /*CC lut r 16 144*/ + 0x0022, 0x20a0, /*CC lut r 32 160*/ + 0x0023, 0x30b0, /*CC lut r 48 176*/ + 0x0024, 0x40c0, /*CC lut r 64 192*/ + 0x0025, 0x50d0, /*CC lut r 80 208*/ + 0x0026, 0x60e0, /*CC lut r 96 224*/ + 0x0027, 0x70f0, /*CC lut r 112 240*/ + 0x0028, 0x80ff, /*CC lut r 128 255*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_movie_ui[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x00a0, + /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x00e1, 0xd6ac, /*SCR RrCr*/ + 0x00e2, 0x32ff, /*SCR RgCg*/ + 0x00e3, 0x2ef0, /*SCR RbCb*/ + 0x00e4, 0xa5fa, /*SCR GrMr*/ + 0x00e5, 0xff4d, /*SCR GgMg*/ + 0x00e6, 0x59ff, /*SCR GbMb*/ + 0x00e7, 0x00ff, /*SCR BrYr*/ + 0x00e8, 0x00fb, /*SCR BgYg*/ + 0x00e9, 0xff61, /*SCR BbYb*/ + 0x00ea, 0x00ff, /*SCR KrWr*/ + 0x00eb, 0x00f8, /*SCR KgWg*/ + 0x00ec, 0x00f1, /*SCR KbWb*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x001f, 0x0080, /*CC chsel strength*/ + 0x0020, 0x0000, /*CC lut r 0*/ + 0x0021, 0x0290, /*CC lut r 16 144*/ + 0x0022, 0x20a0, /*CC lut r 32 160*/ + 0x0023, 0x30b0, /*CC lut r 48 176*/ + 0x0024, 0x40c0, /*CC lut r 64 192*/ + 0x0025, 0x50d0, /*CC lut r 80 208*/ + 0x0026, 0x60e0, /*CC lut r 96 224*/ + 0x0027, 0x70f0, /*CC lut r 112 240*/ + 0x0028, 0x80ff, /*CC lut r 128 255*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_movie_video[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x00a0, + /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x0092, 0x0000, /*DE pe*/ + 0x0093, 0x0000, /*DE pf*/ + 0x0094, 0x0000, /*DE pb*/ + 0x0095, 0x0000, /*DE ne*/ + 0x0096, 0x0000, /*DE nf*/ + 0x0097, 0x0000, /*DE nb*/ + 0x00b0, 0x1010, /*CS hg ry*/ + 0x00b1, 0x1010, /*CS hg gc*/ + 0x00b2, 0x1010, /*CS hg bm*/ + 0x00b3, 0x1004, /*CS weight grayTH*/ + 0x00e1, 0xd6ac, /*SCR RrCr*/ + 0x00e2, 0x32ff, /*SCR RgCg*/ + 0x00e3, 0x2ef0, /*SCR RbCb*/ + 0x00e4, 0xa5fa, /*SCR GrMr*/ + 0x00e5, 0xff4d, /*SCR GgMg*/ + 0x00e6, 0x59ff, /*SCR GbMb*/ + 0x00e7, 0x00ff, /*SCR BrYr*/ + 0x00e8, 0x00fb, /*SCR BgYg*/ + 0x00e9, 0xff61, /*SCR BbYb*/ + 0x00ea, 0x00ff, /*SCR KrWr*/ + 0x00eb, 0x00f8, /*SCR KgWg*/ + 0x00ec, 0x00f1, /*SCR KbWb*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x001f, 0x0080, /*CC chsel strength*/ + 0x0020, 0x0000, /*CC lut r 0*/ + 0x0021, 0x0290, /*CC lut r 16 144*/ + 0x0022, 0x20a0, /*CC lut r 32 160*/ + 0x0023, 0x30b0, /*CC lut r 48 176*/ + 0x0024, 0x40c0, /*CC lut r 64 192*/ + 0x0025, 0x50d0, /*CC lut r 80 208*/ + 0x0026, 0x60e0, /*CC lut r 96 224*/ + 0x0027, 0x70f0, /*CC lut r 112 240*/ + 0x0028, 0x80ff, /*CC lut r 128 255*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_movie_vt[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x00ae, + /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0005, /*FA cs1 | de8 dnr4 hdr2 fa1*/ + 0x0039, 0x0080, /*FA dnrWeight*/ + 0x0080, 0x0fff, /*DNR dirTh*/ + 0x0081, 0x19ff, /*DNR dirnumTh decon7Th*/ + 0x0082, 0xff16, /*DNR decon5Th maskTh*/ + 0x0083, 0x0000, /*DNR blTh*/ + 0x0092, 0x0040, /*DE pe*/ + 0x0093, 0x0040, /*DE pf*/ + 0x0094, 0x0040, /*DE pb*/ + 0x0095, 0x0040, /*DE ne*/ + 0x0096, 0x0040, /*DE nf*/ + 0x0097, 0x0040, /*DE nb*/ + 0x0098, 0x1000, /*DE max ratio*/ + 0x0099, 0x0010, /*DE min ratio*/ + 0x00b0, 0x1010, /*CS hg ry*/ + 0x00b1, 0x1010, /*CS hg gc*/ + 0x00b2, 0x1010, /*CS hg bm*/ + 0x00b3, 0x1204, /*CS weight grayTH*/ + 0x00e1, 0xd6ac, /*SCR RrCr*/ + 0x00e2, 0x32ff, /*SCR RgCg*/ + 0x00e3, 0x2ef0, /*SCR RbCb*/ + 0x00e4, 0xa5fa, /*SCR GrMr*/ + 0x00e5, 0xff4d, /*SCR GgMg*/ + 0x00e6, 0x59ff, /*SCR GbMb*/ + 0x00e7, 0x00ff, /*SCR BrYr*/ + 0x00e8, 0x00fb, /*SCR BgYg*/ + 0x00e9, 0xff61, /*SCR BbYb*/ + 0x00ea, 0x00ff, /*SCR KrWr*/ + 0x00eb, 0x00f8, /*SCR KgWg*/ + 0x00ec, 0x00f1, /*SCR KbWb*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x001f, 0x0080, /*CC chsel strength*/ + 0x0020, 0x0000, /*CC lut r 0*/ + 0x0021, 0x0290, /*CC lut r 16 144*/ + 0x0022, 0x20a0, /*CC lut r 32 160*/ + 0x0023, 0x30b0, /*CC lut r 48 176*/ + 0x0024, 0x40c0, /*CC lut r 64 192*/ + 0x0025, 0x50d0, /*CC lut r 80 208*/ + 0x0026, 0x60e0, /*CC lut r 96 224*/ + 0x0027, 0x70f0, /*CC lut r 112 240*/ + 0x0028, 0x80ff, /*CC lut r 128 255*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_standard_gallery[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x008c, + /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x0092, 0x0060, /*DE pe*/ + 0x0093, 0x0060, /*DE pf*/ + 0x0094, 0x0060, /*DE pb*/ + 0x0095, 0x0060, /*DE ne*/ + 0x0096, 0x0060, /*DE nf*/ + 0x0097, 0x0060, /*DE nb*/ + 0x0098, 0x1000, /*DE max ratio*/ + 0x0099, 0x0100, /*DE min ratio*/ + 0x00b0, 0x1010, /*CS hg ry*/ + 0x00b1, 0x1010, /*CS hg gc*/ + 0x00b2, 0x1010, /*CS hg bm*/ + 0x00b3, 0x1204, /*CS weight grayTH*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x001f, 0x0080, /*CC chsel strength*/ + 0x0020, 0x0000, /*CC lut r 0*/ + 0x0021, 0x0290, /*CC lut r 16 144*/ + 0x0022, 0x20a0, /*CC lut r 32 160*/ + 0x0023, 0x30b0, /*CC lut r 48 176*/ + 0x0024, 0x40c0, /*CC lut r 64 192*/ + 0x0025, 0x50d0, /*CC lut r 80 208*/ + 0x0026, 0x60e0, /*CC lut r 96 224*/ + 0x0027, 0x70f0, /*CC lut r 112 240*/ + 0x0028, 0x80ff, /*CC lut r 128 255*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_standard_ui[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x008c, + /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x0092, 0x0020, /*DE pe*/ + 0x0093, 0x0020, /*DE pf*/ + 0x0094, 0x0020, /*DE pb*/ + 0x0095, 0x0020, /*DE ne*/ + 0x0096, 0x0020, /*DE nf*/ + 0x0097, 0x0020, /*DE nb*/ + 0x0098, 0x1000, /*DE max ratio*/ + 0x0099, 0x0100, /*DE min ratio*/ + 0x00b0, 0x1010, /*CS hg ry*/ + 0x00b1, 0x1010, /*CS hg gc*/ + 0x00b2, 0x1010, /*CS hg bm*/ + 0x00b3, 0x1604, /*CS weight grayTH*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x001f, 0x0080, /*CC chsel strength*/ + 0x0020, 0x0000, /*CC lut r 0*/ + 0x0021, 0x0290, /*CC lut r 16 144*/ + 0x0022, 0x20a0, /*CC lut r 32 160*/ + 0x0023, 0x30b0, /*CC lut r 48 176*/ + 0x0024, 0x40c0, /*CC lut r 64 192*/ + 0x0025, 0x50d0, /*CC lut r 80 208*/ + 0x0026, 0x60e0, /*CC lut r 96 224*/ + 0x0027, 0x70f0, /*CC lut r 112 240*/ + 0x0028, 0x80ff, /*CC lut r 128 255*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_standard_video[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x008c, + /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x0092, 0x0060, /*DE pe*/ + 0x0093, 0x0060, /*DE pf*/ + 0x0094, 0x0060, /*DE pb*/ + 0x0095, 0x0060, /*DE ne*/ + 0x0096, 0x0060, /*DE nf*/ + 0x0097, 0x0060, /*DE nb*/ + 0x0098, 0x1000, /*DE max ratio*/ + 0x0099, 0x0100, /*DE min ratio*/ + 0x00b0, 0x1010, /*CS hg ry*/ + 0x00b1, 0x1010, /*CS hg gc*/ + 0x00b2, 0x1010, /*CS hg bm*/ + 0x00b3, 0x1204, /*CS weight grayTH*/ + 0x00e1, 0xff00, /*SCR RrCr*/ + 0x00e2, 0x00ff, /*SCR RgCg*/ + 0x00e3, 0x00ff, /*SCR RbCb*/ + 0x00e4, 0x00ff, /*SCR GrMr*/ + 0x00e5, 0xff00, /*SCR GgMg*/ + 0x00e6, 0x00ff, /*SCR GbMb*/ + 0x00e7, 0x00ff, /*SCR BrYr*/ + 0x00e8, 0x00ff, /*SCR BgYg*/ + 0x00e9, 0xff00, /*SCR BbYb*/ + 0x00ea, 0x00ff, /*SCR KrWr*/ + 0x00eb, 0x00ff, /*SCR KgWg*/ + 0x00ec, 0x00ff, /*SCR KbWb*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x001f, 0x0080, /*CC chsel strength*/ + 0x0020, 0x0000, /*CC lut r 0*/ + 0x0021, 0x0290, /*CC lut r 16 144*/ + 0x0022, 0x20a0, /*CC lut r 32 160*/ + 0x0023, 0x30b0, /*CC lut r 48 176*/ + 0x0024, 0x40c0, /*CC lut r 64 192*/ + 0x0025, 0x50d0, /*CC lut r 80 208*/ + 0x0026, 0x60e0, /*CC lut r 96 224*/ + 0x0027, 0x70f0, /*CC lut r 112 240*/ + 0x0028, 0x80ff, /*CC lut r 128 255*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_standard_vt[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x008e, + /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0005, /*FA cs1 | de8 dnr4 hdr2 fa1*/ + 0x0039, 0x0080, /*FA dnrWeight*/ + 0x0080, 0x0fff, /*DNR dirTh*/ + 0x0081, 0x19ff, /*DNR dirnumTh decon7Th*/ + 0x0082, 0xff16, /*DNR decon5Th maskTh*/ + 0x0083, 0x0000, /*DNR blTh*/ + 0x0092, 0x00c0, /*DE pe*/ + 0x0093, 0x00c0, /*DE pf*/ + 0x0094, 0x00c0, /*DE pb*/ + 0x0095, 0x00c0, /*DE ne*/ + 0x0096, 0x00c0, /*DE nf*/ + 0x0097, 0x00c0, /*DE nb*/ + 0x0098, 0x1000, /*DE max ratio*/ + 0x0099, 0x0010, /*DE min ratio*/ + 0x00b0, 0x1010, /*CS hg ry*/ + 0x00b1, 0x1010, /*CS hg gc*/ + 0x00b2, 0x1010, /*CS hg bm*/ + 0x00b3, 0x1804, /*CS weight grayTH*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x001f, 0x0080, /*CC chsel strength*/ + 0x0020, 0x0000, /*CC lut r 0*/ + 0x0021, 0x0290, /*CC lut r 16 144*/ + 0x0022, 0x20a0, /*CC lut r 32 160*/ + 0x0023, 0x30b0, /*CC lut r 48 176*/ + 0x0024, 0x40c0, /*CC lut r 64 192*/ + 0x0025, 0x50d0, /*CC lut r 80 208*/ + 0x0026, 0x60e0, /*CC lut r 96 224*/ + 0x0027, 0x70f0, /*CC lut r 112 240*/ + 0x0028, 0x80ff, /*CC lut r 128 255*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_natural_gallery[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x00ac, + /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x0092, 0x0060, /*DE pe*/ + 0x0093, 0x0060, /*DE pf*/ + 0x0094, 0x0060, /*DE pb*/ + 0x0095, 0x0060, /*DE ne*/ + 0x0096, 0x0060, /*DE nf*/ + 0x0097, 0x0060, /*DE nb*/ + 0x0098, 0x1000, /*DE max ratio*/ + 0x0099, 0x0100, /*DE min ratio*/ + 0x00b0, 0x1010, /*CS hg ry*/ + 0x00b1, 0x1010, /*CS hg gc*/ + 0x00b2, 0x1010, /*CS hg bm*/ + 0x00b3, 0x1804, /*CS weight grayTH*/ + 0x00e1, 0xd6ac, /*SCR RrCr*/ + 0x00e2, 0x32ff, /*SCR RgCg*/ + 0x00e3, 0x2ef0, /*SCR RbCb*/ + 0x00e4, 0xa5fa, /*SCR GrMr*/ + 0x00e5, 0xff4d, /*SCR GgMg*/ + 0x00e6, 0x59ff, /*SCR GbMb*/ + 0x00e7, 0x00ff, /*SCR BrYr*/ + 0x00e8, 0x00fb, /*SCR BgYg*/ + 0x00e9, 0xff61, /*SCR BbYb*/ + 0x00ea, 0x00ff, /*SCR KrWr*/ + 0x00eb, 0x00fa, /*SCR KgWg*/ + 0x00ec, 0x00f8, /*SCR KbWb*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x001f, 0x0080, /*CC chsel strength*/ + 0x0020, 0x0000, /*CC lut r 0*/ + 0x0021, 0x0290, /*CC lut r 16 144*/ + 0x0022, 0x20a0, /*CC lut r 32 160*/ + 0x0023, 0x30b0, /*CC lut r 48 176*/ + 0x0024, 0x40c0, /*CC lut r 64 192*/ + 0x0025, 0x50d0, /*CC lut r 80 208*/ + 0x0026, 0x60e0, /*CC lut r 96 224*/ + 0x0027, 0x70f0, /*CC lut r 112 240*/ + 0x0028, 0x80ff, /*CC lut r 128 255*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_natural_ui[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x00ac, + /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x0092, 0x0020, /*DE pe*/ + 0x0093, 0x0020, /*DE pf*/ + 0x0094, 0x0020, /*DE pb*/ + 0x0095, 0x0020, /*DE ne*/ + 0x0096, 0x0020, /*DE nf*/ + 0x0097, 0x0020, /*DE nb*/ + 0x0098, 0x1000, /*DE max ratio*/ + 0x0099, 0x0100, /*DE min ratio*/ + 0x00b0, 0x1010, /*CS hg ry*/ + 0x00b1, 0x1010, /*CS hg gc*/ + 0x00b2, 0x1010, /*CS hg bm*/ + 0x00b3, 0x1804, /*CS weight grayTH*/ + 0x00e1, 0xd6ac, /*SCR RrCr*/ + 0x00e2, 0x32ff, /*SCR RgCg*/ + 0x00e3, 0x2ef0, /*SCR RbCb*/ + 0x00e4, 0xa5fa, /*SCR GrMr*/ + 0x00e5, 0xff4d, /*SCR GgMg*/ + 0x00e6, 0x59ff, /*SCR GbMb*/ + 0x00e7, 0x00ff, /*SCR BrYr*/ + 0x00e8, 0x00fb, /*SCR BgYg*/ + 0x00e9, 0xff61, /*SCR BbYb*/ + 0x00ea, 0x00ff, /*SCR KrWr*/ + 0x00eb, 0x00fa, /*SCR KgWg*/ + 0x00ec, 0x00f8, /*SCR KbWb*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x001f, 0x0080, /*CC chsel strength*/ + 0x0020, 0x0000, /*CC lut r 0*/ + 0x0021, 0x0290, /*CC lut r 16 144*/ + 0x0022, 0x20a0, /*CC lut r 32 160*/ + 0x0023, 0x30b0, /*CC lut r 48 176*/ + 0x0024, 0x40c0, /*CC lut r 64 192*/ + 0x0025, 0x50d0, /*CC lut r 80 208*/ + 0x0026, 0x60e0, /*CC lut r 96 224*/ + 0x0027, 0x70f0, /*CC lut r 112 240*/ + 0x0028, 0x80ff, /*CC lut r 128 255*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_natural_video[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x00ac, + /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x0092, 0x0060, /*DE pe*/ + 0x0093, 0x0060, /*DE pf*/ + 0x0094, 0x0060, /*DE pb*/ + 0x0095, 0x0060, /*DE ne*/ + 0x0096, 0x0060, /*DE nf*/ + 0x0097, 0x0060, /*DE nb*/ + 0x0098, 0x1000, /*DE max ratio*/ + 0x0099, 0x0100, /*DE min ratio*/ + 0x00b0, 0x1010, /*CS hg ry*/ + 0x00b1, 0x1010, /*CS hg gc*/ + 0x00b2, 0x1010, /*CS hg bm*/ + 0x00b3, 0x1804, /*CS weight grayTH*/ + 0x00e1, 0xd6ac, /*SCR RrCr*/ + 0x00e2, 0x32ff, /*SCR RgCg*/ + 0x00e3, 0x2ef0, /*SCR RbCb*/ + 0x00e4, 0xa5fa, /*SCR GrMr*/ + 0x00e5, 0xff4d, /*SCR GgMg*/ + 0x00e6, 0x59ff, /*SCR GbMb*/ + 0x00e7, 0x00ff, /*SCR BrYr*/ + 0x00e8, 0x00fb, /*SCR BgYg*/ + 0x00e9, 0xff61, /*SCR BbYb*/ + 0x00ea, 0x00ff, /*SCR KrWr*/ + 0x00eb, 0x00fa, /*SCR KgWg*/ + 0x00ec, 0x00f8, /*SCR KbWb*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x001f, 0x0080, /*CC chsel strength*/ + 0x0020, 0x0000, /*CC lut r 0*/ + 0x0021, 0x0290, /*CC lut r 16 144*/ + 0x0022, 0x20a0, /*CC lut r 32 160*/ + 0x0023, 0x30b0, /*CC lut r 48 176*/ + 0x0024, 0x40c0, /*CC lut r 64 192*/ + 0x0025, 0x50d0, /*CC lut r 80 208*/ + 0x0026, 0x60e0, /*CC lut r 96 224*/ + 0x0027, 0x70f0, /*CC lut r 112 240*/ + 0x0028, 0x80ff, /*CC lut r 128 255*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_natural_vt[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x00ae, + /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0005, /*FA cs1 | de8 dnr4 hdr2 fa1*/ + 0x0039, 0x0080, /*FA dnrWeight*/ + 0x0080, 0x0fff, /*DNR dirTh*/ + 0x0081, 0x19ff, /*DNR dirnumTh decon7Th*/ + 0x0082, 0xff16, /*DNR decon5Th maskTh*/ + 0x0083, 0x0000, /*DNR blTh*/ + 0x0092, 0x00c0, /*DE pe*/ + 0x0093, 0x00c0, /*DE pf*/ + 0x0094, 0x00c0, /*DE pb*/ + 0x0095, 0x00c0, /*DE ne*/ + 0x0096, 0x00c0, /*DE nf*/ + 0x0097, 0x00c0, /*DE nb*/ + 0x0098, 0x1000, /*DE max ratio*/ + 0x0099, 0x0010, /*DE min ratio*/ + 0x00b0, 0x1010, /*CS hg ry*/ + 0x00b1, 0x1010, /*CS hg gc*/ + 0x00b2, 0x1010, /*CS hg bm*/ + 0x00b3, 0x1804, /*CS weight grayTH*/ + 0x00e1, 0xd6ac, /*SCR RrCr*/ + 0x00e2, 0x32ff, /*SCR RgCg*/ + 0x00e3, 0x2ef0, /*SCR RbCb*/ + 0x00e4, 0xa5fa, /*SCR GrMr*/ + 0x00e5, 0xff4d, /*SCR GgMg*/ + 0x00e6, 0x59ff, /*SCR GbMb*/ + 0x00e7, 0x00ff, /*SCR BrYr*/ + 0x00e8, 0x00fb, /*SCR BgYg*/ + 0x00e9, 0xff61, /*SCR BbYb*/ + 0x00ea, 0x00ff, /*SCR KrWr*/ + 0x00eb, 0x00fa, /*SCR KgWg*/ + 0x00ec, 0x00f8, /*SCR KbWb*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x001f, 0x0080, /*CC chsel strength*/ + 0x0020, 0x0000, /*CC lut r 0*/ + 0x0021, 0x0290, /*CC lut r 16 144*/ + 0x0022, 0x20a0, /*CC lut r 32 160*/ + 0x0023, 0x30b0, /*CC lut r 48 176*/ + 0x0024, 0x40c0, /*CC lut r 64 192*/ + 0x0025, 0x50d0, /*CC lut r 80 208*/ + 0x0026, 0x60e0, /*CC lut r 96 224*/ + 0x0027, 0x70f0, /*CC lut r 112 240*/ + 0x0028, 0x80ff, /*CC lut r 128 255*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_camera[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x000c, + /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x0092, 0x0060, /*DE pe*/ + 0x0093, 0x0060, /*DE pf*/ + 0x0094, 0x0060, /*DE pb*/ + 0x0095, 0x0060, /*DE ne*/ + 0x0096, 0x0060, /*DE nf*/ + 0x0097, 0x0060, /*DE nb*/ + 0x0098, 0x1000, /*DE max ratio*/ + 0x0099, 0x0100, /*DE min ratio*/ + 0x00b0, 0x1010, /*CS hg ry*/ + 0x00b1, 0x1010, /*CS hg gc*/ + 0x00b2, 0x1010, /*CS hg bm*/ + 0x00b3, 0x1204, /*CS weight grayTH*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_camera_outdoor[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x040c, + /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x0092, 0x0060, /*DE pe*/ + 0x0093, 0x0060, /*DE pf*/ + 0x0094, 0x0060, /*DE pb*/ + 0x0095, 0x0060, /*DE ne*/ + 0x0096, 0x0060, /*DE nf*/ + 0x0097, 0x0060, /*DE nb*/ + 0x0098, 0x1000, /*DE max ratio*/ + 0x0099, 0x0100, /*DE min ratio*/ + 0x00b0, 0x1010, /*CS hg RY*/ + 0x00b1, 0x1010, /*CS hg GC*/ + 0x00b2, 0x1010, /*CS hg BM*/ + 0x00b3, 0x1204, /*CS weight grayTH*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x00d0, 0x01c0, /*UC y*/ + 0x00d1, 0x01ff, /*UC cs*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_cold[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x00ec, + /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x0001, 0x0064, /*MCM 10000K*/ + 0x0009, 0xa08b, /*MCM 5cb 1cr W*/ + 0x000b, 0x7a7a, /*MCM 4cr 5cr W*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_cold_outdoor[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x04ec, + /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x0001, 0x0064, /*MCM 10000K*/ + 0x0009, 0xa08b, /*MCM 5cb 1cr W*/ + 0x000b, 0x7a7a, /*MCM 4cr 5cr W*/ + 0x00d0, 0x01c0, /*UC y*/ + 0x00d1, 0x01ff, /*UC cs*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_normal_outdoor[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x04ac, + /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x00d0, 0x01c0, /*UC y*/ + 0x00d1, 0x01ff, /*UC cs*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_warm[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x00ec, + /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x0001, 0x0028, /*MCM 4000K*/ + 0x0007, 0x7878, /*MCM 1cb 2cb W*/ + 0x0009, 0xa08b, /*MCM 5cb 1cr W*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_warm_outdoor[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x04ec, + /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x0001, 0x0028, /*MCM 4000K*/ + 0x0007, 0x7878, /*MCM 1cb 2cb W*/ + 0x0009, 0xa08b, /*MCM 5cb 1cr W*/ + 0x00d0, 0x01c0, /*UC y*/ + 0x00d1, 0x01ff, /*UC cs*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +struct mdnie_tunning_info etc_table[CABC_MAX][OUTDOOR_MAX][TONE_MAX] = { + { + { + {"NORMAL", NULL}, + {"WARM", tune_warm}, + {"COLD", tune_cold}, + }, + { + {"NORMAL_OUTDOOR", tune_normal_outdoor}, + {"WARM_OUTDOOR", tune_warm_outdoor}, + {"COLD_OUTDOOR", tune_cold_outdoor}, + }, + } +}; + +struct mdnie_tunning_info tunning_table[CABC_MAX][MODE_MAX][SCENARIO_MAX] = { + { + { + {"DYNAMIC_UI", tune_dynamic_ui}, + {"DYNAMIC_VIDEO", tune_dynamic_video}, + {"DYNAMIC_VIDEO", tune_dynamic_video}, + {"DYNAMIC_VIDEO", tune_dynamic_video}, + {"CAMERA", NULL}, + {"DYNAMIC_UI", tune_dynamic_ui}, + {"DYNAMIC_GALLERY", tune_dynamic_gallery}, + {"DYNAMIC_VT", tune_dynamic_vt}, + }, { + {"STANDARD_UI", tune_standard_ui}, + {"STANDARD_VIDEO", tune_standard_video}, + {"STANDARD_VIDEO", tune_standard_video}, + {"STANDARD_VIDEO", tune_standard_video}, + {"CAMERA", NULL}, + {"STANDARD_UI", tune_standard_ui}, + {"STANDARD_GALLERY", tune_standard_gallery}, + {"STANDARD_VT", tune_standard_vt}, + }, { + {"NATURAL_UI", tune_natural_ui}, + {"NATURAL_VIDEO", tune_natural_video}, + {"NATURAL_VIDEO_WARM", tune_natural_video}, + {"NATURAL_VIDEO_COLD", tune_natural_video}, + {"CAMERA", NULL}, + {"NATURAL_UI", tune_natural_ui}, + {"NATURAL_GALLERY", tune_natural_gallery}, + {"NATURAL_VT", tune_natural_vt}, + }, { + {"MOVIE_UI", tune_movie_ui}, + {"MOVIE_VIDEO", tune_movie_video}, + {"MOVIE_VIDEO", tune_movie_video}, + {"MOVIE_VIDEO", tune_movie_video}, + {"CAMERA", NULL}, + {"MOVIE_UI", tune_movie_ui}, + {"MOVIE_GALLERY", tune_movie_gallery}, + {"MOVIE_VT", tune_movie_vt}, + }, + } +}; + +struct mdnie_tunning_info camera_table[OUTDOOR_MAX] = { + {"CAMERA", tune_camera}, + {"CAMERA_OUTDOOR", tune_camera_outdoor}, +}; + +#endif/* __MDNIE_TABLE_H__ */ diff --git a/drivers/video/samsung/mdnie_table_t0.h b/drivers/video/samsung/mdnie_table_t0.h new file mode 100644 index 0000000..a3e9325 --- /dev/null +++ b/drivers/video/samsung/mdnie_table_t0.h @@ -0,0 +1,763 @@ +#ifndef __MDNIE_TABLE_H__ +#define __MDNIE_TABLE_H__ + +#include "mdnie.h" + + +static const unsigned short tune_dynamic_gallery[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x008c, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x0090, 0x0080, /*DE egth*/ + 0x0092, 0x0030, /*DE pe*/ + 0x0093, 0x0080, /*DE pf*/ + 0x0094, 0x0080, /*DE pb*/ + 0x0095, 0x0030, /*DE ne*/ + 0x0096, 0x0080, /*DE nf*/ + 0x0097, 0x0080, /*DE nb*/ + 0x0098, 0x1000, /*DE max ratio*/ + 0x0099, 0x0100, /*DE min ratio*/ + 0x00b0, 0x1010, /*CS hg ry*/ + 0x00b1, 0x1010, /*CS hg gc*/ + 0x00b2, 0x1010, /*CS hg bm*/ + 0x00b3, 0x1404, /*CS weight grayTH*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x001f, 0x0080, /*CC chsel strength*/ + 0x0020, 0x0000, /*CC lut r 0*/ + 0x0021, 0x0d93, /*CC lut r 16 144*/ + 0x0022, 0x1aa5, /*CC lut r 32 160*/ + 0x0023, 0x29b7, /*CC lut r 48 176*/ + 0x0024, 0x39c8, /*CC lut r 64 192*/ + 0x0025, 0x4bd8, /*CC lut r 80 208*/ + 0x0026, 0x5de6, /*CC lut r 96 224*/ + 0x0027, 0x6ff4, /*CC lut r 112 240*/ + 0x0028, 0x81ff, /*CC lut r 128 255*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_dynamic_ui[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x0088, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x00b0, 0x1010, /*CS hg ry*/ + 0x00b1, 0x1010, /*CS hg gc*/ + 0x00b2, 0x1010, /*CS hg bm*/ + 0x00b3, 0x1804, /*CS weight grayTH*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x001f, 0x0080, /*CC chsel strength*/ + 0x0020, 0x0000, /*CC lut r 0*/ + 0x0021, 0x0d93, /*CC lut r 16 144*/ + 0x0022, 0x1aa5, /*CC lut r 32 160*/ + 0x0023, 0x29b7, /*CC lut r 48 176*/ + 0x0024, 0x39c8, /*CC lut r 64 192*/ + 0x0025, 0x4bd8, /*CC lut r 80 208*/ + 0x0026, 0x5de6, /*CC lut r 96 224*/ + 0x0027, 0x6ff4, /*CC lut r 112 240*/ + 0x0028, 0x81ff, /*CC lut r 128 255*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_dynamic_video[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x008c, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x0092, 0x0080, /*DE pe*/ + 0x0093, 0x0080, /*DE pf*/ + 0x0094, 0x0080, /*DE pb*/ + 0x0095, 0x0080, /*DE ne*/ + 0x0096, 0x0080, /*DE nf*/ + 0x0097, 0x0080, /*DE nb*/ + 0x0098, 0x1000, /*DE max ratio*/ + 0x0099, 0x0100, /*DE min ratio*/ + 0x00b0, 0x1010, /*CS hg ry*/ + 0x00b1, 0x1010, /*CS hg gc*/ + 0x00b2, 0x1010, /*CS hg bm*/ + 0x00b3, 0x1404, /*CS weight grayTH*/ + 0x00e1, 0xff00, /*SCR RrCr*/ + 0x00e2, 0x00ff, /*SCR RgCg*/ + 0x00e3, 0x00ff, /*SCR RbCb*/ + 0x00e4, 0x00ff, /*SCR GrMr*/ + 0x00e5, 0xff00, /*SCR GgMg*/ + 0x00e6, 0x00ff, /*SCR GbMb*/ + 0x00e7, 0x00ff, /*SCR BrYr*/ + 0x00e8, 0x00ff, /*SCR BgYg*/ + 0x00e9, 0xff00, /*SCR BbYb*/ + 0x00ea, 0x00ff, /*SCR KrWr*/ + 0x00eb, 0x00ff, /*SCR KgWg*/ + 0x00ec, 0x00ff, /*SCR KbWb*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x001f, 0x0080, /*CC chsel strength*/ + 0x0020, 0x0000, /*CC lut r 0*/ + 0x0021, 0x0d93, /*CC lut r 16 144*/ + 0x0022, 0x1aa5, /*CC lut r 32 160*/ + 0x0023, 0x29b7, /*CC lut r 48 176*/ + 0x0024, 0x39c8, /*CC lut r 64 192*/ + 0x0025, 0x4bd8, /*CC lut r 80 208*/ + 0x0026, 0x5de6, /*CC lut r 96 224*/ + 0x0027, 0x6ff4, /*CC lut r 112 240*/ + 0x0028, 0x81ff, /*CC lut r 128 255*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_dynamic_vt[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x008e, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0005, /*FA cs1 | de8 dnr4 hdr2 fa1*/ + 0x0039, 0x0080, /*FA dnrWeight*/ + 0x0080, 0x0fff, /*DNR dirTh*/ + 0x0081, 0x19ff, /*DNR dirnumTh decon7Th*/ + 0x0082, 0xff16, /*DNR decon5Th maskTh*/ + 0x0083, 0x0000, /*DNR blTh*/ + 0x0092, 0x00e0, /*DE pe*/ + 0x0093, 0x00e0, /*DE pf*/ + 0x0094, 0x00e0, /*DE pb*/ + 0x0095, 0x00e0, /*DE ne*/ + 0x0096, 0x00e0, /*DE nf*/ + 0x0097, 0x00e0, /*DE nb*/ + 0x0098, 0x1000, /*DE max ratio*/ + 0x0099, 0x0010, /*DE min ratio*/ + 0x00b0, 0x1010, /*CS hg ry*/ + 0x00b1, 0x1010, /*CS hg gc*/ + 0x00b2, 0x1010, /*CS hg bm*/ + 0x00b3, 0x1a04, /*CS weight grayTH*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x001f, 0x0080, /*CC chsel strength*/ + 0x0020, 0x0000, /*CC lut r 0*/ + 0x0021, 0x0d93, /*CC lut r 16 144*/ + 0x0022, 0x1aa5, /*CC lut r 32 160*/ + 0x0023, 0x29b7, /*CC lut r 48 176*/ + 0x0024, 0x39c8, /*CC lut r 64 192*/ + 0x0025, 0x4bd8, /*CC lut r 80 208*/ + 0x0026, 0x5de6, /*CC lut r 96 224*/ + 0x0027, 0x6ff4, /*CC lut r 112 240*/ + 0x0028, 0x81ff, /*CC lut r 128 255*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_movie_gallery[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x00a0, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x00e1, 0xd6ac, /*SCR RrCr*/ + 0x00e2, 0x32ff, /*SCR RgCg*/ + 0x00e3, 0x2ef0, /*SCR RbCb*/ + 0x00e4, 0xa5fa, /*SCR GrMr*/ + 0x00e5, 0xff4d, /*SCR GgMg*/ + 0x00e6, 0x59ff, /*SCR GbMb*/ + 0x00e7, 0x00ff, /*SCR BrYr*/ + 0x00e8, 0x00fb, /*SCR BgYg*/ + 0x00e9, 0xff61, /*SCR BbYb*/ + 0x00ea, 0x00ff, /*SCR KrWr*/ + 0x00eb, 0x00f8, /*SCR KgWg*/ + 0x00ec, 0x00f1, /*SCR KbWb*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x001f, 0x0080, /*CC chsel strength*/ + 0x0020, 0x0000, /*CC lut r 0*/ + 0x0021, 0x1090, /*CC lut r 16 144*/ + 0x0022, 0x20a0, /*CC lut r 32 160*/ + 0x0023, 0x30b0, /*CC lut r 48 176*/ + 0x0024, 0x40c0, /*CC lut r 64 192*/ + 0x0025, 0x50d0, /*CC lut r 80 208*/ + 0x0026, 0x60e0, /*CC lut r 96 224*/ + 0x0027, 0x70f0, /*CC lut r 112 240*/ + 0x0028, 0x80ff, /*CC lut r 128 255*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_movie_ui[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x00a0, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x00e1, 0xd6ac, /*SCR RrCr*/ + 0x00e2, 0x32ff, /*SCR RgCg*/ + 0x00e3, 0x2ef0, /*SCR RbCb*/ + 0x00e4, 0xa5fa, /*SCR GrMr*/ + 0x00e5, 0xff4d, /*SCR GgMg*/ + 0x00e6, 0x59ff, /*SCR GbMb*/ + 0x00e7, 0x00ff, /*SCR BrYr*/ + 0x00e8, 0x00fb, /*SCR BgYg*/ + 0x00e9, 0xff61, /*SCR BbYb*/ + 0x00ea, 0x00ff, /*SCR KrWr*/ + 0x00eb, 0x00f8, /*SCR KgWg*/ + 0x00ec, 0x00f1, /*SCR KbWb*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x001f, 0x0080, /*CC chsel strength*/ + 0x0020, 0x0000, /*CC lut r 0*/ + 0x0021, 0x1090, /*CC lut r 16 144*/ + 0x0022, 0x20a0, /*CC lut r 32 160*/ + 0x0023, 0x30b0, /*CC lut r 48 176*/ + 0x0024, 0x40c0, /*CC lut r 64 192*/ + 0x0025, 0x50d0, /*CC lut r 80 208*/ + 0x0026, 0x60e0, /*CC lut r 96 224*/ + 0x0027, 0x70f0, /*CC lut r 112 240*/ + 0x0028, 0x80ff, /*CC lut r 128 255*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_movie_video[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x00a0, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x0092, 0x0000, /*DE pe*/ + 0x0093, 0x0000, /*DE pf*/ + 0x0094, 0x0000, /*DE pb*/ + 0x0095, 0x0000, /*DE ne*/ + 0x0096, 0x0000, /*DE nf*/ + 0x0097, 0x0000, /*DE nb*/ + 0x00b0, 0x1010, /*CS hg ry*/ + 0x00b1, 0x1010, /*CS hg gc*/ + 0x00b2, 0x1010, /*CS hg bm*/ + 0x00b3, 0x1004, /*CS weight grayTH*/ + 0x00e1, 0xd6ac, /*SCR RrCr*/ + 0x00e2, 0x32ff, /*SCR RgCg*/ + 0x00e3, 0x2ef0, /*SCR RbCb*/ + 0x00e4, 0xa5fa, /*SCR GrMr*/ + 0x00e5, 0xff4d, /*SCR GgMg*/ + 0x00e6, 0x59ff, /*SCR GbMb*/ + 0x00e7, 0x00ff, /*SCR BrYr*/ + 0x00e8, 0x00fb, /*SCR BgYg*/ + 0x00e9, 0xff61, /*SCR BbYb*/ + 0x00ea, 0x00ff, /*SCR KrWr*/ + 0x00eb, 0x00f8, /*SCR KgWg*/ + 0x00ec, 0x00f1, /*SCR KbWb*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x001f, 0x0080, /*CC chsel strength*/ + 0x0020, 0x0000, /*CC lut r 0*/ + 0x0021, 0x1090, /*CC lut r 16 144*/ + 0x0022, 0x20a0, /*CC lut r 32 160*/ + 0x0023, 0x30b0, /*CC lut r 48 176*/ + 0x0024, 0x40c0, /*CC lut r 64 192*/ + 0x0025, 0x50d0, /*CC lut r 80 208*/ + 0x0026, 0x60e0, /*CC lut r 96 224*/ + 0x0027, 0x70f0, /*CC lut r 112 240*/ + 0x0028, 0x80ff, /*CC lut r 128 255*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_movie_vt[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x00ae, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0005, /*FA cs1 | de8 dnr4 hdr2 fa1*/ + 0x0039, 0x0080, /*FA dnrWeight*/ + 0x0080, 0x0fff, /*DNR dirTh*/ + 0x0081, 0x19ff, /*DNR dirnumTh decon7Th*/ + 0x0082, 0xff16, /*DNR decon5Th maskTh*/ + 0x0083, 0x0000, /*DNR blTh*/ + 0x0092, 0x0042, /*DE pe*/ + 0x0093, 0x0042, /*DE pf*/ + 0x0094, 0x0042, /*DE pb*/ + 0x0095, 0x0042, /*DE ne*/ + 0x0096, 0x0042, /*DE nf*/ + 0x0097, 0x0042, /*DE nb*/ + 0x0098, 0x1000, /*DE max ratio*/ + 0x0099, 0x0010, /*DE min ratio*/ + 0x00b0, 0x1010, /*CS hg ry*/ + 0x00b1, 0x1010, /*CS hg gc*/ + 0x00b2, 0x1010, /*CS hg bm*/ + 0x00b3, 0x1204, /*CS weight grayTH*/ + 0x00e1, 0xd6ac, /*SCR RrCr*/ + 0x00e2, 0x32ff, /*SCR RgCg*/ + 0x00e3, 0x2ef0, /*SCR RbCb*/ + 0x00e4, 0xa5fa, /*SCR GrMr*/ + 0x00e5, 0xff4d, /*SCR GgMg*/ + 0x00e6, 0x59ff, /*SCR GbMb*/ + 0x00e7, 0x00ff, /*SCR BrYr*/ + 0x00e8, 0x00fb, /*SCR BgYg*/ + 0x00e9, 0xff61, /*SCR BbYb*/ + 0x00ea, 0x00ff, /*SCR KrWr*/ + 0x00eb, 0x00f8, /*SCR KgWg*/ + 0x00ec, 0x00f1, /*SCR KbWb*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x001f, 0x0080, /*CC chsel strength*/ + 0x0020, 0x0000, /*CC lut r 0*/ + 0x0021, 0x1090, /*CC lut r 16 144*/ + 0x0022, 0x20a0, /*CC lut r 32 160*/ + 0x0023, 0x30b0, /*CC lut r 48 176*/ + 0x0024, 0x40c0, /*CC lut r 64 192*/ + 0x0025, 0x50d0, /*CC lut r 80 208*/ + 0x0026, 0x60e0, /*CC lut r 96 224*/ + 0x0027, 0x70f0, /*CC lut r 112 240*/ + 0x0028, 0x80ff, /*CC lut r 128 255*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_standard_gallery[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x008c, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x0090, 0x0080, /*DE egth*/ + 0x0092, 0x0030, /*DE pe*/ + 0x0093, 0x0060, /*DE pf*/ + 0x0094, 0x0060, /*DE pb*/ + 0x0095, 0x0030, /*DE ne*/ + 0x0096, 0x0060, /*DE nf*/ + 0x0097, 0x0060, /*DE nb*/ + 0x0098, 0x1000, /*DE max ratio*/ + 0x0099, 0x0100, /*DE min ratio*/ + 0x00b0, 0x1010, /*CS hg ry*/ + 0x00b1, 0x1010, /*CS hg gc*/ + 0x00b2, 0x1010, /*CS hg bm*/ + 0x00b3, 0x1204, /*CS weight grayTH*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x001f, 0x0080, /*CC chsel strength*/ + 0x0020, 0x0000, /*CC lut r 0*/ + 0x0021, 0x1090, /*CC lut r 16 144*/ + 0x0022, 0x20a0, /*CC lut r 32 160*/ + 0x0023, 0x30b0, /*CC lut r 48 176*/ + 0x0024, 0x40c0, /*CC lut r 64 192*/ + 0x0025, 0x50d0, /*CC lut r 80 208*/ + 0x0026, 0x60e0, /*CC lut r 96 224*/ + 0x0027, 0x70f0, /*CC lut r 112 240*/ + 0x0028, 0x80ff, /*CC lut r 128 255*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_standard_ui[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x0088, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x00b0, 0x1010, /*CS hg ry*/ + 0x00b1, 0x1010, /*CS hg gc*/ + 0x00b2, 0x1010, /*CS hg bm*/ + 0x00b3, 0x1604, /*CS weight grayTH*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x001f, 0x0080, /*CC chsel strength*/ + 0x0020, 0x0000, /*CC lut r 0*/ + 0x0021, 0x1090, /*CC lut r 16 144*/ + 0x0022, 0x20a0, /*CC lut r 32 160*/ + 0x0023, 0x30b0, /*CC lut r 48 176*/ + 0x0024, 0x40c0, /*CC lut r 64 192*/ + 0x0025, 0x50d0, /*CC lut r 80 208*/ + 0x0026, 0x60e0, /*CC lut r 96 224*/ + 0x0027, 0x70f0, /*CC lut r 112 240*/ + 0x0028, 0x80ff, /*CC lut r 128 255*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_standard_video[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x008c, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x0092, 0x0060, /*DE pe*/ + 0x0093, 0x0060, /*DE pf*/ + 0x0094, 0x0060, /*DE pb*/ + 0x0095, 0x0060, /*DE ne*/ + 0x0096, 0x0060, /*DE nf*/ + 0x0097, 0x0060, /*DE nb*/ + 0x0098, 0x1000, /*DE max ratio*/ + 0x0099, 0x0100, /*DE min ratio*/ + 0x00b0, 0x1010, /*CS hg ry*/ + 0x00b1, 0x1010, /*CS hg gc*/ + 0x00b2, 0x1010, /*CS hg bm*/ + 0x00b3, 0x1204, /*CS weight grayTH*/ + 0x00e1, 0xff00, /*SCR RrCr*/ + 0x00e2, 0x00ff, /*SCR RgCg*/ + 0x00e3, 0x00ff, /*SCR RbCb*/ + 0x00e4, 0x00ff, /*SCR GrMr*/ + 0x00e5, 0xff00, /*SCR GgMg*/ + 0x00e6, 0x00ff, /*SCR GbMb*/ + 0x00e7, 0x00ff, /*SCR BrYr*/ + 0x00e8, 0x00ff, /*SCR BgYg*/ + 0x00e9, 0xff00, /*SCR BbYb*/ + 0x00ea, 0x00ff, /*SCR KrWr*/ + 0x00eb, 0x00ff, /*SCR KgWg*/ + 0x00ec, 0x00ff, /*SCR KbWb*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x001f, 0x0080, /*CC chsel strength*/ + 0x0020, 0x0000, /*CC lut r 0*/ + 0x0021, 0x1090, /*CC lut r 16 144*/ + 0x0022, 0x20a0, /*CC lut r 32 160*/ + 0x0023, 0x30b0, /*CC lut r 48 176*/ + 0x0024, 0x40c0, /*CC lut r 64 192*/ + 0x0025, 0x50d0, /*CC lut r 80 208*/ + 0x0026, 0x60e0, /*CC lut r 96 224*/ + 0x0027, 0x70f0, /*CC lut r 112 240*/ + 0x0028, 0x80ff, /*CC lut r 128 255*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_standard_vt[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x008e, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0005, /*FA cs1 | de8 dnr4 hdr2 fa1*/ + 0x0039, 0x0080, /*FA dnrWeight*/ + 0x0080, 0x0fff, /*DNR dirTh*/ + 0x0081, 0x19ff, /*DNR dirnumTh decon7Th*/ + 0x0082, 0xff16, /*DNR decon5Th maskTh*/ + 0x0083, 0x0000, /*DNR blTh*/ + 0x0092, 0x00c0, /*DE pe*/ + 0x0093, 0x00c0, /*DE pf*/ + 0x0094, 0x00c0, /*DE pb*/ + 0x0095, 0x00c0, /*DE ne*/ + 0x0096, 0x00c0, /*DE nf*/ + 0x0097, 0x00c0, /*DE nb*/ + 0x0098, 0x1000, /*DE max ratio*/ + 0x0099, 0x0010, /*DE min ratio*/ + 0x00b0, 0x1010, /*CS hg ry*/ + 0x00b1, 0x1010, /*CS hg gc*/ + 0x00b2, 0x1010, /*CS hg bm*/ + 0x00b3, 0x1804, /*CS weight grayTH*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x001f, 0x0080, /*CC chsel strength*/ + 0x0020, 0x0000, /*CC lut r 0*/ + 0x0021, 0x1090, /*CC lut r 16 144*/ + 0x0022, 0x20a0, /*CC lut r 32 160*/ + 0x0023, 0x30b0, /*CC lut r 48 176*/ + 0x0024, 0x40c0, /*CC lut r 64 192*/ + 0x0025, 0x50d0, /*CC lut r 80 208*/ + 0x0026, 0x60e0, /*CC lut r 96 224*/ + 0x0027, 0x70f0, /*CC lut r 112 240*/ + 0x0028, 0x80ff, /*CC lut r 128 255*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_natural_gallery[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x00ac, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x0090, 0x0080, /*DE egth*/ + 0x0092, 0x0030, /*DE pe*/ + 0x0093, 0x0060, /*DE pf*/ + 0x0094, 0x0060, /*DE pb*/ + 0x0095, 0x0030, /*DE ne*/ + 0x0096, 0x0060, /*DE nf*/ + 0x0097, 0x0060, /*DE nb*/ + 0x0098, 0x1000, /*DE max ratio*/ + 0x0099, 0x0100, /*DE min ratio*/ + 0x00b0, 0x1010, /*CS hg ry*/ + 0x00b1, 0x1010, /*CS hg gc*/ + 0x00b2, 0x1010, /*CS hg bm*/ + 0x00b3, 0x1804, /*CS weight grayTH*/ + 0x00e1, 0xd6ac, /*SCR RrCr*/ + 0x00e2, 0x32ff, /*SCR RgCg*/ + 0x00e3, 0x2ef0, /*SCR RbCb*/ + 0x00e4, 0xa5fa, /*SCR GrMr*/ + 0x00e5, 0xff4d, /*SCR GgMg*/ + 0x00e6, 0x59ff, /*SCR GbMb*/ + 0x00e7, 0x00ff, /*SCR BrYr*/ + 0x00e8, 0x00fb, /*SCR BgYg*/ + 0x00e9, 0xff61, /*SCR BbYb*/ + 0x00ea, 0x00ff, /*SCR KrWr*/ + 0x00eb, 0x00fa, /*SCR KgWg*/ + 0x00ec, 0x00f8, /*SCR KbWb*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x001f, 0x0080, /*CC chsel strength*/ + 0x0020, 0x0000, /*CC lut r 0*/ + 0x0021, 0x1090, /*CC lut r 16 144*/ + 0x0022, 0x20a0, /*CC lut r 32 160*/ + 0x0023, 0x30b0, /*CC lut r 48 176*/ + 0x0024, 0x40c0, /*CC lut r 64 192*/ + 0x0025, 0x50d0, /*CC lut r 80 208*/ + 0x0026, 0x60e0, /*CC lut r 96 224*/ + 0x0027, 0x70f0, /*CC lut r 112 240*/ + 0x0028, 0x80ff, /*CC lut r 128 255*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_natural_ui[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x00a8, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x00b0, 0x1010, /*CS hg ry*/ + 0x00b1, 0x1010, /*CS hg gc*/ + 0x00b2, 0x1010, /*CS hg bm*/ + 0x00b3, 0x1804, /*CS weight grayTH*/ + 0x00e1, 0xd6ac, /*SCR RrCr*/ + 0x00e2, 0x32ff, /*SCR RgCg*/ + 0x00e3, 0x2ef0, /*SCR RbCb*/ + 0x00e4, 0xa5fa, /*SCR GrMr*/ + 0x00e5, 0xff4d, /*SCR GgMg*/ + 0x00e6, 0x59ff, /*SCR GbMb*/ + 0x00e7, 0x00ff, /*SCR BrYr*/ + 0x00e8, 0x00fb, /*SCR BgYg*/ + 0x00e9, 0xff61, /*SCR BbYb*/ + 0x00ea, 0x00ff, /*SCR KrWr*/ + 0x00eb, 0x00fa, /*SCR KgWg*/ + 0x00ec, 0x00f8, /*SCR KbWb*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x001f, 0x0080, /*CC chsel strength*/ + 0x0020, 0x0000, /*CC lut r 0*/ + 0x0021, 0x1090, /*CC lut r 16 144*/ + 0x0022, 0x20a0, /*CC lut r 32 160*/ + 0x0023, 0x30b0, /*CC lut r 48 176*/ + 0x0024, 0x40c0, /*CC lut r 64 192*/ + 0x0025, 0x50d0, /*CC lut r 80 208*/ + 0x0026, 0x60e0, /*CC lut r 96 224*/ + 0x0027, 0x70f0, /*CC lut r 112 240*/ + 0x0028, 0x80ff, /*CC lut r 128 255*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_natural_video[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x00ac, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x0090, 0x0080, /*DE egth*/ + 0x0092, 0x0030, /*DE pe*/ + 0x0093, 0x0060, /*DE pf*/ + 0x0094, 0x0060, /*DE pb*/ + 0x0095, 0x0030, /*DE ne*/ + 0x0096, 0x0060, /*DE nf*/ + 0x0097, 0x0060, /*DE nb*/ + 0x0098, 0x1000, /*DE max ratio*/ + 0x0099, 0x0100, /*DE min ratio*/ + 0x00b0, 0x1010, /*CS hg ry*/ + 0x00b1, 0x1010, /*CS hg gc*/ + 0x00b2, 0x1010, /*CS hg bm*/ + 0x00b3, 0x1804, /*CS weight grayTH*/ + 0x00e1, 0xd6ac, /*SCR RrCr*/ + 0x00e2, 0x32ff, /*SCR RgCg*/ + 0x00e3, 0x2ef0, /*SCR RbCb*/ + 0x00e4, 0xa5fa, /*SCR GrMr*/ + 0x00e5, 0xff4d, /*SCR GgMg*/ + 0x00e6, 0x59ff, /*SCR GbMb*/ + 0x00e7, 0x00ff, /*SCR BrYr*/ + 0x00e8, 0x00fb, /*SCR BgYg*/ + 0x00e9, 0xff61, /*SCR BbYb*/ + 0x00ea, 0x00ff, /*SCR KrWr*/ + 0x00eb, 0x00fa, /*SCR KgWg*/ + 0x00ec, 0x00f8, /*SCR KbWb*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x001f, 0x0080, /*CC chsel strength*/ + 0x0020, 0x0000, /*CC lut r 0*/ + 0x0021, 0x1090, /*CC lut r 16 144*/ + 0x0022, 0x20a0, /*CC lut r 32 160*/ + 0x0023, 0x30b0, /*CC lut r 48 176*/ + 0x0024, 0x40c0, /*CC lut r 64 192*/ + 0x0025, 0x50d0, /*CC lut r 80 208*/ + 0x0026, 0x60e0, /*CC lut r 96 224*/ + 0x0027, 0x70f0, /*CC lut r 112 240*/ + 0x0028, 0x80ff, /*CC lut r 128 255*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_natural_vt[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x00ae, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0005, /*FA cs1 | de8 dnr4 hdr2 fa1*/ + 0x0039, 0x0080, /*FA dnrWeight*/ + 0x0080, 0x0fff, /*DNR dirTh*/ + 0x0081, 0x19ff, /*DNR dirnumTh decon7Th*/ + 0x0082, 0xff16, /*DNR decon5Th maskTh*/ + 0x0083, 0x0000, /*DNR blTh*/ + 0x0092, 0x00c0, /*DE pe*/ + 0x0093, 0x00c0, /*DE pf*/ + 0x0094, 0x00c0, /*DE pb*/ + 0x0095, 0x00c0, /*DE ne*/ + 0x0096, 0x00c0, /*DE nf*/ + 0x0097, 0x00c0, /*DE nb*/ + 0x0098, 0x1000, /*DE max ratio*/ + 0x0099, 0x0010, /*DE min ratio*/ + 0x00b0, 0x1010, /*CS hg ry*/ + 0x00b1, 0x1010, /*CS hg gc*/ + 0x00b2, 0x1010, /*CS hg bm*/ + 0x00b3, 0x1804, /*CS weight grayTH*/ + 0x00e1, 0xd6ac, /*SCR RrCr*/ + 0x00e2, 0x32ff, /*SCR RgCg*/ + 0x00e3, 0x2ef0, /*SCR RbCb*/ + 0x00e4, 0xa5fa, /*SCR GrMr*/ + 0x00e5, 0xff4d, /*SCR GgMg*/ + 0x00e6, 0x59ff, /*SCR GbMb*/ + 0x00e7, 0x00ff, /*SCR BrYr*/ + 0x00e8, 0x00fb, /*SCR BgYg*/ + 0x00e9, 0xff61, /*SCR BbYb*/ + 0x00ea, 0x00ff, /*SCR KrWr*/ + 0x00eb, 0x00fa, /*SCR KgWg*/ + 0x00ec, 0x00f8, /*SCR KbWb*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x001f, 0x0080, /*CC chsel strength*/ + 0x0020, 0x0000, /*CC lut r 0*/ + 0x0021, 0x1090, /*CC lut r 16 144*/ + 0x0022, 0x20a0, /*CC lut r 32 160*/ + 0x0023, 0x30b0, /*CC lut r 48 176*/ + 0x0024, 0x40c0, /*CC lut r 64 192*/ + 0x0025, 0x50d0, /*CC lut r 80 208*/ + 0x0026, 0x60e0, /*CC lut r 96 224*/ + 0x0027, 0x70f0, /*CC lut r 112 240*/ + 0x0028, 0x80ff, /*CC lut r 128 255*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_camera[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x000c, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x0090, 0x0080, /*DE egth*/ + 0x0092, 0x0030, /*DE pe*/ + 0x0093, 0x0060, /*DE pf*/ + 0x0094, 0x0060, /*DE pb*/ + 0x0095, 0x0030, /*DE ne*/ + 0x0096, 0x0060, /*DE nf*/ + 0x0097, 0x0060, /*DE nb*/ + 0x0098, 0x1000, /*DE max ratio*/ + 0x0099, 0x0100, /*DE min ratio*/ + 0x00b0, 0x1010, /*CS hg ry*/ + 0x00b1, 0x1010, /*CS hg gc*/ + 0x00b2, 0x1010, /*CS hg bm*/ + 0x00b3, 0x1204, /*CS weight grayTH*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_camera_outdoor[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x040c, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0030, 0x0000, /*FA cs1 de8 hdr2 fa1*/ + 0x0090, 0x0080, /*DE egth*/ + 0x0092, 0x0030, /*DE pe*/ + 0x0093, 0x0060, /*DE pf*/ + 0x0094, 0x0060, /*DE pb*/ + 0x0095, 0x0030, /*DE ne*/ + 0x0096, 0x0060, /*DE nf*/ + 0x0097, 0x0060, /*DE nb*/ + 0x0098, 0x1000, /*DE max ratio*/ + 0x0099, 0x0100, /*DE min ratio*/ + 0x00b0, 0x1010, /*CS hg RY*/ + 0x00b1, 0x1010, /*CS hg GC*/ + 0x00b2, 0x1010, /*CS hg BM*/ + 0x00b3, 0x1204, /*CS weight grayTH*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x00d0, 0x01c0, /*UC y*/ + 0x00d1, 0x01ff, /*UC cs*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_cold[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x00ec, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x0001, 0x0064, /*MCM 10000K*/ + 0x0009, 0xa08b, /*MCM 5cb 1cr W*/ + 0x000b, 0x7a7a, /*MCM 4cr 5cr W*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_cold_outdoor[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x04ec, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x0001, 0x0064, /*MCM 10000K*/ + 0x0009, 0xa08b, /*MCM 5cb 1cr W*/ + 0x000b, 0x7a7a, /*MCM 4cr 5cr W*/ + 0x00d0, 0x01c0, /*UC y*/ + 0x00d1, 0x01ff, /*UC cs*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_normal_outdoor[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x04ac, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x00d0, 0x01c0, /*UC y*/ + 0x00d1, 0x01ff, /*UC cs*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_warm[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x00ec, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x0001, 0x0028, /*MCM 4000K*/ + 0x0007, 0x7878, /*MCM 1cb 2cb W*/ + 0x0009, 0xa08b, /*MCM 5cb 1cr W*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +static const unsigned short tune_warm_outdoor[] = { + 0x0000, 0x0000, /*BANK 0*/ + 0x0008, 0x04ec, /*Dither8 UC4 ABC2 CP1 | CC8 MCM4 SCR2 SCC1 | CS8 DE4 DNR2 HDR1*/ + 0x0000, 0x0001, /*BANK 1*/ + 0x0001, 0x0028, /*MCM 4000K*/ + 0x0007, 0x7878, /*MCM 1cb 2cb W*/ + 0x0009, 0xa08b, /*MCM 5cb 1cr W*/ + 0x00d0, 0x01c0, /*UC y*/ + 0x00d1, 0x01ff, /*UC cs*/ + 0x00ff, 0x0000, /*Mask Release*/ + END_SEQ, 0x0000, +}; + +struct mdnie_tunning_info etc_table[CABC_MAX][OUTDOOR_MAX][TONE_MAX] = { + { + { + {"NORMAL", NULL}, + {"WARM", tune_warm}, + {"COLD", tune_cold}, + }, + { + {"NORMAL_OUTDOOR", tune_normal_outdoor}, + {"WARM_OUTDOOR", tune_warm_outdoor}, + {"COLD_OUTDOOR", tune_cold_outdoor}, + }, + } +}; + +struct mdnie_tunning_info tunning_table[CABC_MAX][MODE_MAX][SCENARIO_MAX] = { + { + { + {"DYNAMIC_UI", tune_dynamic_ui}, + {"DYNAMIC_VIDEO", tune_dynamic_video}, + {"DYNAMIC_VIDEO", tune_dynamic_video}, + {"DYNAMIC_VIDEO", tune_dynamic_video}, + {"CAMERA", NULL}, + {"DYNAMIC_UI", tune_dynamic_ui}, + {"DYNAMIC_GALLERY", tune_dynamic_gallery}, + {"DYNAMIC_VT", tune_dynamic_vt}, + }, { + {"STANDARD_UI", tune_standard_ui}, + {"STANDARD_VIDEO", tune_standard_video}, + {"STANDARD_VIDEO", tune_standard_video}, + {"STANDARD_VIDEO", tune_standard_video}, + {"CAMERA", NULL}, + {"STANDARD_UI", tune_standard_ui}, + {"STANDARD_GALLERY", tune_standard_gallery}, + {"STANDARD_VT", tune_standard_vt}, + }, { + {"NATURAL_UI", tune_natural_ui}, + {"NATURAL_VIDEO", tune_natural_video}, + {"NATURAL_VIDEO_WARM", tune_natural_video}, + {"NATURAL_VIDEO_COLD", tune_natural_video}, + {"CAMERA", NULL}, + {"NATURAL_UI", tune_natural_ui}, + {"NATURAL_GALLERY", tune_natural_gallery}, + {"NATURAL_VT", tune_natural_vt}, + }, { + {"MOVIE_UI", tune_movie_ui}, + {"MOVIE_VIDEO", tune_movie_video}, + {"MOVIE_VIDEO", tune_movie_video}, + {"MOVIE_VIDEO", tune_movie_video}, + {"CAMERA", NULL}, + {"MOVIE_UI", tune_movie_ui}, + {"MOVIE_GALLERY", tune_movie_gallery}, + {"MOVIE_VT", tune_movie_vt}, + }, + } +}; + +struct mdnie_tunning_info camera_table[OUTDOOR_MAX] = { + {"CAMERA", tune_camera}, + {"CAMERA_OUTDOOR", tune_camera_outdoor}, +}; + +#endif/* __MDNIE_TABLE_H__ */ + diff --git a/drivers/video/samsung/s3cfb.h b/drivers/video/samsung/s3cfb.h index b278184..0831ac8 100644 --- a/drivers/video/samsung/s3cfb.h +++ b/drivers/video/samsung/s3cfb.h @@ -22,6 +22,7 @@ #endif #include <plat/fb-s5p.h> #endif +#include <linux/kthread.h> #include <mach/cpufreq.h> #define S3CFB_NAME "s3cfb" @@ -42,10 +43,19 @@ #define POWER_ON 1 #define POWER_OFF 0 +#define VSYNC_TIMEOUT_MSEC 50 + #if defined(CONFIG_MACH_PX) || defined(CONFIG_MACH_Q1_BD) #define FEATURE_BUSFREQ_LOCK /* Now, this feature only avaliable in 4210 */ #endif +/* S3C_FB_MAX_WIN + * Set to the maximum number of windows that any of the supported hardware + * can use. Since the platform data uses this for an array size, having it + * set to the maximum of any version of the hardware can do is safe. + */ +#define S3C_FB_MAX_WIN (5) + enum s3cfb_data_path_t { DATA_PATH_FIFO = 0, DATA_PATH_DMA = 1, @@ -145,6 +155,7 @@ struct s3cfb_lcd { int p_height; int bpp; int freq; + int freq_limit; int vclk; struct s3cfb_lcd_timing timing; struct s3cfb_lcd_polarity polarity; @@ -161,6 +172,32 @@ struct s3cfb_fimd_desc { struct s3cfb_global *fbdev[FIMD_MAX]; }; +/** + * struct s3cfb_vsync - vsync information+ + * @wait: a queue for processes waiting for vsync + * @timestamp: the time of the last vsync interrupt + * @active: whether userspace is requesting vsync uevents + * @irq_refcount: reference count for the underlying irq + * @irq_lock: mutex protecting the irq refcount and register + * @thread: uevent-generating thread + */ +struct s3cfb_vsync { + wait_queue_head_t wait; + ktime_t timestamp; + bool active; + int irq_refcount; + struct mutex irq_lock; + struct task_struct *thread; +}; + +#ifdef CONFIG_FB_S5P_SYSMMU +struct sysmmu_flag { + bool enabled; + unsigned long default_fb_addr; + unsigned long pgd; +}; +#endif + struct s3cfb_global { void __iomem *regs; void __iomem *regs_org; @@ -172,21 +209,29 @@ struct s3cfb_global { #ifdef CONFIG_BUSFREQ_OPP struct device *bus_dev; #endif + spinlock_t vsync_slock; struct clk *clock; int irq; wait_queue_head_t wq; unsigned int wq_count; struct fb_info **fb; - - ktime_t vsync_timestamp; - int vsync_state; - struct task_struct *vsync_thread; + struct s3cfb_vsync vsync_info; atomic_t enabled_win; enum s3cfb_output_t output; enum s3cfb_rgb_mode_t rgb_mode; struct s3cfb_lcd *lcd; int system_state; + + /* New added */ + struct list_head update_regs_list; + struct mutex update_regs_list_lock; + struct kthread_worker update_regs_worker; + struct task_struct *update_regs_thread; + struct kthread_work update_regs_work; + + struct sw_sync_timeline *timeline; + int timeline_max; #ifdef CONFIG_HAS_WAKELOCK struct early_suspend early_suspend; struct wake_lock idle_lock; @@ -195,6 +240,9 @@ struct s3cfb_global { atomic_t busfreq_lock_cnt; /* Bus frequency Lock count */ int busfreq_flag; /* context bus frequency flag*/ #endif +#ifdef CONFIG_FB_S5P_SYSMMU + struct sysmmu_flag sysmmu; +#endif }; struct s3cfb_window { @@ -232,6 +280,61 @@ struct s3cfb_user_chroma { unsigned char blue; }; +enum s3c_fb_pixel_format { + S3C_FB_PIXEL_FORMAT_RGBA_8888 = 0, + S3C_FB_PIXEL_FORMAT_RGB_888 = 1, + S3C_FB_PIXEL_FORMAT_BGRA_8888 = 2, + S3C_FB_PIXEL_FORMAT_RGB_565 = 3, + S3C_FB_PIXEL_FORMAT_RGBX_8888 = 4, + S3C_FB_PIXEL_FORMAT_RGBA_5551 = 5, + S3C_FB_PIXEL_FORMAT_RGBA_4444 = 6, + S3C_FB_PIXEL_FORMAT_MAX = 7, +}; + +struct s3c_fb_win_config { + enum { + S3C_FB_WIN_STATE_DISABLED = 0, + S3C_FB_WIN_STATE_COLOR, + S3C_FB_WIN_STATE_BUFFER, + } state; + + union { + __u32 color; + struct { + int fd; + __u32 phys_addr; + __u32 virt_addr; + __u32 offset; + __u32 stride; + enum s3c_fb_pixel_format format; + }; + }; + + int x; + int y; + __u32 w; + __u32 h; +}; + +struct s3c_fb_win_config_data { + int fence; + struct s3c_fb_win_config config[S3C_FB_MAX_WIN]; +}; + +struct s3c_reg_data { + struct list_head list; + u32 shadowcon; + u32 wincon[S3C_FB_MAX_WIN]; + u32 winmap[S3C_FB_MAX_WIN]; + u32 vidosd_a[S3C_FB_MAX_WIN]; + u32 vidosd_b[S3C_FB_MAX_WIN]; + u32 vidosd_c[S3C_FB_MAX_WIN]; + u32 vidosd_d[S3C_FB_MAX_WIN]; + u32 vidw_buf_start[S3C_FB_MAX_WIN]; + u32 vidw_buf_end[S3C_FB_MAX_WIN]; + u32 vidw_buf_size[S3C_FB_MAX_WIN]; +}; + #define BLENDING_NONE 0x0100 #define BLENDING_PREMULT 0x0105 #define BLENDING_COVERAGE 0x0405 @@ -245,6 +348,8 @@ struct s3cfb_user_chroma { struct s3cfb_user_chroma) #define S3CFB_SET_VSYNC_INT _IOW('F', 206, u32) #define S3CFB_GET_VSYNC_INT_STATUS _IOR('F', 207, u32) +#define S3CFB_GET_ION_USER_HANDLE _IOWR('F', 208, struct s3c_fb_user_ion_client) +#define S3CFB_WIN_CONFIG _IOW('F', 209, struct s3c_fb_win_config_data) #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) @@ -342,8 +447,17 @@ extern int s3cfb_set_buffer_size(struct s3cfb_global *ctrl, int id); extern int s3cfb_set_chroma_key(struct s3cfb_global *ctrl, int id); extern int s3cfb_channel_localpath_on(struct s3cfb_global *ctrl, int id); extern int s3cfb_channel_localpath_off(struct s3cfb_global *ctrl, int id); +extern int s3cfb_set_vsync_int(struct fb_info *info, bool active); extern int s3cfb_check_vsync_status(struct s3cfb_global *ctrl); extern int s3cfb_set_dualrgb(struct s3cfb_global *ctrl, int mode); +extern int s3cfb_set_window_protect(struct s3cfb_global *ctrl, int id, bool protect); +extern void s3c_fb_update_regs(struct s3cfb_global *fbdev, struct s3c_reg_data *regs); +#ifdef CONFIG_FB_S5P_SYSMMU +extern void s3cfb_clean_outer_pagetable(unsigned long vaddr, size_t size); +#endif +#if defined(CONFIG_FB_S5P_VSYNC_THREAD) +extern int s3cfb_wait_for_vsync(struct s3cfb_global *fbdev, u32 timeout); +#endif #ifdef CONFIG_FB_S5P_MIPI_DSIM extern int s3cfb_vsync_status_check(void); #endif diff --git a/drivers/video/samsung/s3cfb_ea8061.c b/drivers/video/samsung/s3cfb_ea8061.c new file mode 100644 index 0000000..5edeaaf --- /dev/null +++ b/drivers/video/samsung/s3cfb_ea8061.c @@ -0,0 +1,1289 @@ +/* linux/drivers/video/samsung/s3cfb_ea8061.c + * + * MIPI-DSI based AMS555HBxx AMOLED lcd panel 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/mutex.h> +#include <linux/wait.h> +#include <linux/ctype.h> +#include <linux/io.h> +#include <linux/delay.h> +#include <linux/irq.h> +#include <linux/interrupt.h> +#include <linux/gpio.h> +#include <linux/workqueue.h> +#include <linux/backlight.h> +#include <linux/lcd.h> +#include <plat/gpio-cfg.h> +#include <plat/regs-dsim.h> +#include <mach/dsim.h> +#include <mach/mipi_ddi.h> +#ifdef CONFIG_HAS_EARLYSUSPEND +#include <linux/earlysuspend.h> +#endif + +#include "s5p-dsim.h" +#include "s3cfb.h" +#include "ea8061_param.h" + +#define SMART_DIMMING +#undef SMART_DIMMING_DEBUG + +#ifdef SMART_DIMMING +#include "smart_dimming_ea8061.h" +#include "aid_ea8061.h" +#endif + + +#define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL) + +#define MIN_BRIGHTNESS 0 +#define MAX_BRIGHTNESS 255 +#define MAX_GAMMA 300 +#define DEFAULT_BRIGHTNESS 130 +#define DEFAULT_GAMMA_LEVEL GAMMA_130CD + +#define LDI_ID_REG 0xD1 +#define LDI_ID_LEN 3 +#ifdef SMART_DIMMING +#define LDI_MTP_LENGTH 32 +#define LDI_MTP_ADDR 0xDA +#endif + +struct lcd_info { + unsigned int bl; + unsigned int auto_brightness; + unsigned int acl_enable; + unsigned int current_acl; + unsigned int current_bl; + unsigned int current_elvss; + unsigned int ldi_enable; + unsigned int power; + struct mutex lock; + struct mutex bl_lock; + struct device *dev; + struct lcd_device *ld; + struct backlight_device *bd; + struct lcd_platform_data *lcd_pd; + struct early_suspend early_suspend; + unsigned char id[LDI_ID_LEN]; + unsigned char **gamma_table; + unsigned char **elvss_table; +#ifdef SMART_DIMMING + struct str_smart_dim smart; + unsigned char b3[GAMMA_MAX][ARRAY_SIZE(SEQ_LTPS_AID)]; +#endif + unsigned int irq; + unsigned int connected; + +#if defined(GPIO_OLED_DET) + struct delayed_work oled_detection; + unsigned int oled_detection_count; +#endif + + struct dsim_global *dsim; +}; + +static const unsigned int candela_table[GAMMA_MAX] = { + 20, 30, 40, 50, 60, 70, 80, 90, 100, + 102, 104, 106, 108, + 110, 120, 130, 140, 150, 160, 170, 180, + 182, 184, 186, 188, + 190, 200, 210, 220, 230, 240, 250, MAX_GAMMA-1 +}; + +#ifdef SMART_DIMMING +static unsigned int aid_candela_table[GAMMA_MAX] = { + base_20to100, base_20to100, base_20to100, base_20to100, base_20to100, base_20to100, base_20to100, base_20to100, base_20to100, + AOR40_BASE_102, AOR40_BASE_104, AOR40_BASE_106, AOR40_BASE_108, + AOR40_BASE_110, AOR40_BASE_120, AOR40_BASE_130, AOR40_BASE_140, AOR40_BASE_150, + AOR40_BASE_160, AOR40_BASE_170, AOR40_BASE_180, AOR40_BASE_182, AOR40_BASE_184, + AOR40_BASE_186, AOR40_BASE_188, + 190, 200, 210, 220, 230, 240, 250, MAX_GAMMA-1 +}; +#endif + +extern void (*lcd_early_suspend)(void); +extern void (*lcd_late_resume)(void); + +#if defined(GPIO_OLED_DET) +static void oled_detection_work(struct work_struct *work) +{ + struct lcd_info *lcd = + container_of(work, struct lcd_info, oled_detection.work); + + int oled_det_level = gpio_get_value(GPIO_OLED_DET); + + dev_info(&lcd->ld->dev, "%s, %d, %d\n", __func__, lcd->oled_detection_count, oled_det_level); + + if (!oled_det_level) { + if (lcd->oled_detection_count < 10) { + schedule_delayed_work(&lcd->oled_detection, HZ/8); + lcd->oled_detection_count++; + set_dsim_hs_clk_toggle_count(15); + } else + set_dsim_hs_clk_toggle_count(0); + } else + set_dsim_hs_clk_toggle_count(0); + +} + +static irqreturn_t oled_detection_int(int irq, void *_lcd) +{ + struct lcd_info *lcd = _lcd; + + dev_info(&lcd->ld->dev, "%s\n", __func__); + + lcd->oled_detection_count = 0; + schedule_delayed_work(&lcd->oled_detection, HZ/16); + + return IRQ_HANDLED; +} +#endif + +static int _ea8061_write(struct lcd_info *lcd, const unsigned char *seq, int len) +{ + int size; + const unsigned char *wbuf; + int ret = 0; + + if (!lcd->connected) + return 0; + + mutex_lock(&lcd->lock); + + size = len; + wbuf = seq; + + if (size == 1) + ret = lcd->dsim->ops->cmd_write(lcd->dsim, DCS_WR_NO_PARA, wbuf[0], 0); + else if (size == 2) + ret = lcd->dsim->ops->cmd_write(lcd->dsim, DCS_WR_1_PARA, wbuf[0], wbuf[1]); + else + ret = lcd->dsim->ops->cmd_write(lcd->dsim, DCS_LONG_WR, (unsigned int)wbuf, size); + + mutex_unlock(&lcd->lock); + + return ret; +} + +static int ea8061_write(struct lcd_info *lcd, const unsigned char *seq, int len) +{ + int ret = 0; + int retry_cnt = 1; + +retry: + ret = _ea8061_write(lcd, seq, len); + if (!ret) { + if (retry_cnt) { + dev_dbg(&lcd->ld->dev, "%s :: retry: %d\n", __func__, retry_cnt); + retry_cnt--; + goto retry; + } else + dev_dbg(&lcd->ld->dev, "%s :: 0x%02x\n", __func__, seq[1]); + } + + return ret; +} + +static int _ea8061_read(struct lcd_info *lcd, const u8 addr, u16 count, u8 *buf) +{ + int ret = 0; + + if (!lcd->connected) + return ret; + + mutex_lock(&lcd->lock); + + if (lcd->dsim->ops->cmd_dcs_read) + ret = lcd->dsim->ops->cmd_dcs_read(lcd->dsim, addr, count, buf); + + mutex_unlock(&lcd->lock); + + return ret; +} + +static int ea8061_read(struct lcd_info *lcd, const u8 addr, u16 count, u8 *buf, u8 retry_cnt) +{ + int ret = 0; + +retry: + ret = _ea8061_read(lcd, addr, count, buf); + if (!ret) { + if (retry_cnt) { + dev_dbg(&lcd->ld->dev, "%s :: retry: %d\n", __func__, retry_cnt); + retry_cnt--; + goto retry; + } else + dev_dbg(&lcd->ld->dev, "%s :: 0x%02x\n", __func__, addr); + } + + return ret; +} + +static int get_backlight_level_from_brightness(int brightness) +{ + int backlightlevel; + + /* brightness setting from platform is from 0 to 255 + * But in this driver, brightness is only supported from 0 to 24 */ + + switch (brightness) { + case 0 ... 29: + backlightlevel = GAMMA_20CD; + break; + case 30 ... 39: + backlightlevel = GAMMA_30CD; + break; + case 40 ... 49: + backlightlevel = GAMMA_40CD; + break; + case 50 ... 59: + backlightlevel = GAMMA_50CD; + break; + case 60 ... 69: + backlightlevel = GAMMA_60CD; + break; + case 70 ... 79: + backlightlevel = GAMMA_70CD; + break; + case 80 ... 89: + backlightlevel = GAMMA_80CD; + break; + case 90 ... 99: + backlightlevel = GAMMA_90CD; + break; + case 100 ... 101: + backlightlevel = GAMMA_100CD; + break; + case 102 ... 103: + backlightlevel = GAMMA_102CD; + break; + case 104 ... 105: + backlightlevel = GAMMA_104CD; + break; + case 106 ... 107: + backlightlevel = GAMMA_106CD; + break; + case 108 ... 109: + backlightlevel = GAMMA_108CD; + break; + case 110 ... 119: + backlightlevel = GAMMA_110CD; + break; + case 120 ... 129: + backlightlevel = GAMMA_120CD; + break; + case 130 ... 139: + backlightlevel = GAMMA_130CD; + break; + case 140 ... 149: + backlightlevel = GAMMA_140CD; + break; + case 150 ... 159: + backlightlevel = GAMMA_150CD; + break; + case 160 ... 169: + backlightlevel = GAMMA_160CD; + break; + case 170 ... 179: + backlightlevel = GAMMA_170CD; + break; + case 180 ... 181: + backlightlevel = GAMMA_180CD; + break; + case 182 ... 183: + backlightlevel = GAMMA_182CD; + break; + case 184 ... 185: + backlightlevel = GAMMA_184CD; + break; + case 186 ... 187: + backlightlevel = GAMMA_186CD; + break; + case 188 ... 189: + backlightlevel = GAMMA_188CD; + break; + case 190 ... 199: + backlightlevel = GAMMA_190CD; + break; + case 200 ... 209: + backlightlevel = GAMMA_200CD; + break; + case 210 ... 219: + backlightlevel = GAMMA_210CD; + break; + case 220 ... 229: + backlightlevel = GAMMA_220CD; + break; + case 230 ... 239: + backlightlevel = GAMMA_230CD; + break; + case 240 ... 249: + backlightlevel = GAMMA_240CD; + break; + case 250 ... 254: + backlightlevel = GAMMA_250CD; + break; + case 255: + backlightlevel = GAMMA_300CD; + break; + default: + backlightlevel = DEFAULT_GAMMA_LEVEL; + break; + } + return backlightlevel; +} + +#ifdef SMART_DIMMING +static int ea8061_aid_parameter_ctl(struct lcd_info *lcd, u8 force) +{ + if (force) + goto aor_update; + else if (aid_command_table[lcd->bl][0] != aid_command_table[lcd->current_bl][0]) + goto aor_update; + else if (aid_command_table[lcd->bl][1] != aid_command_table[lcd->current_bl][1]) + goto aor_update; + else + goto exit; + +aor_update: + ea8061_write(lcd, lcd->b3[lcd->bl], AID_PARAM_SIZE); + +exit: + return 0; +} +#endif + +static int ea8061_gamma_ctl(struct lcd_info *lcd) +{ + /* ea8061_write(lcd, SEQ_APPLY_LEVEL_2_KEY_ENABLE, ARRAY_SIZE(SEQ_APPLY_LEVEL_2_KEY_ENABLE)); */ + ea8061_write(lcd, SEQ_FRAME_GAMMA_UPDATE_KEY, ARRAY_SIZE(SEQ_FRAME_GAMMA_UPDATE_KEY)); + ea8061_write(lcd, lcd->gamma_table[lcd->bl], GAMMA_PARAM_SIZE-1); + ea8061_write(lcd, SEQ_FRAME_GAMMA_UPDATE_KEY2, ARRAY_SIZE(SEQ_FRAME_GAMMA_UPDATE_KEY2)); + + return 0; +} + +static int ea8061_set_acl(struct lcd_info *lcd, u8 force) +{ + int ret = 0, level = 0; + u32 candela = candela_table[lcd->bl]; + + switch (candela) { + case 0 ... 29: + level = ACL_STATUS_0P; + break; + case 30 ... 39: + level = ACL_STATUS_33P; + break; + default: + level = ACL_STATUS_40P; + break; + } + + if ((!lcd->acl_enable) || (lcd->auto_brightness >= 5)) + level = ACL_STATUS_0P; + + if (force || lcd->current_acl != ACL_CUTOFF_TABLE[level][1]) { + ret = ea8061_write(lcd, ACL_CUTOFF_TABLE[level], ACL_PARAM_SIZE); + lcd->current_acl = ACL_CUTOFF_TABLE[level][1]; + dev_dbg(&lcd->ld->dev, "current_acl = %d\n", lcd->current_acl); + } + + if (ret) + ret = -EPERM; + + return ret; +} + +static int ea8061_set_elvss(struct lcd_info *lcd, u8 force) +{ + int ret = 0, elvss_level = 0; + u32 candela = candela_table[lcd->bl]; + + switch (candela) { + case 0 ... 49: + elvss_level = ELVSS_STATUS_20; + break; + case 50 ... 79: + elvss_level = ELVSS_STATUS_50; + break; + case 80 ... 99: + elvss_level = ELVSS_STATUS_80; + break; + case 100 ... 109: + elvss_level = ELVSS_STATUS_100; + break; + case 110 ... 119: + elvss_level = ELVSS_STATUS_110; + break; + case 120 ... 129: + elvss_level = ELVSS_STATUS_120; + break; + case 130 ... 139: + elvss_level = ELVSS_STATUS_130; + break; + case 140 ... 149: + elvss_level = ELVSS_STATUS_140; + break; + case 150 ... 159: + elvss_level = ELVSS_STATUS_150; + break; + case 160 ... 169: + elvss_level = ELVSS_STATUS_160; + break; + case 170 ... 179: + elvss_level = ELVSS_STATUS_170; + break; + case 180 ... 189: + elvss_level = ELVSS_STATUS_180; + break; + case 190 ... 199: + elvss_level = ELVSS_STATUS_190; + break; + case 200 ... 209: + elvss_level = ELVSS_STATUS_200; + break; + case 210 ... 219: + elvss_level = ELVSS_STATUS_210; + break; + case 220 ... 229: + elvss_level = ELVSS_STATUS_220; + break; + case 230 ... 239: + elvss_level = ELVSS_STATUS_230; + break; + case 240 ... 250: + elvss_level = ELVSS_STATUS_240; + break; + case 299: + elvss_level = ELVSS_STATUS_300; + break; + } + + if (force || lcd->current_elvss != lcd->elvss_table[elvss_level][1]) { + ret = ea8061_write(lcd, lcd->elvss_table[elvss_level], ELVSS_PARAM_SIZE); + lcd->current_elvss = lcd->elvss_table[elvss_level][1]; + } + + dev_dbg(&lcd->ld->dev, "elvss = %x\n", lcd->elvss_table[elvss_level][1]); + + if (ret) { + ret = -EPERM; + goto elvss_err; + } + +elvss_err: + return ret; +} + +static int init_elvss_table(struct lcd_info *lcd) +{ + int i, ret = 0; +#ifdef SMART_DIMMING_DEBUG + int j; +#endif + lcd->elvss_table = (unsigned char **)ELVSS_CONTROL_TABLE; + +#ifdef SMART_DIMMING_DEBUG + for (i = 0; i < ELVSS_STATUS_MAX; i++) { + for (j = 0; j < ELVSS_PARAM_SIZE; j++) + printk("0x%02x, ", lcd->elvss_table[i][j]); + printk("\n"); + } +#endif + + return 0; + +err_alloc_elvss: + while (i > 0) { + kfree(lcd->elvss_table[i-1]); + i--; + } + kfree(lcd->elvss_table); +err_alloc_elvss_table: + return ret; +} + +#ifdef SMART_DIMMING +static int init_gamma_table(struct lcd_info *lcd , const u8 *mtp_data) +{ + int i, ret = 0; + + lcd->gamma_table = kzalloc(GAMMA_MAX * sizeof(u8 *), GFP_KERNEL); + if (IS_ERR_OR_NULL(lcd->gamma_table)) { + pr_err("failed to allocate gamma table\n"); + ret = -ENOMEM; + goto err_alloc_gamma_table; + } + + for (i = 0; i < GAMMA_MAX; i++) { + lcd->gamma_table[i] = kzalloc(GAMMA_PARAM_SIZE * sizeof(u8), GFP_KERNEL); + if (IS_ERR_OR_NULL(lcd->gamma_table[i])) { + pr_err("failed to allocate gamma\n"); + ret = -ENOMEM; + goto err_alloc_gamma; + } + lcd->gamma_table[i][0] = 0xCA; + } + + for (i = 0; i < GAMMA_MAX; i++) { + + if (candela_table[i] == 20) + calc_gamma_table_20_100_ea8061(&lcd->smart, aid_candela_table[i], &lcd->gamma_table[i][1], G_21, mtp_data); + else if (candela_table[i] == 30) + calc_gamma_table_20_100_ea8061(&lcd->smart, aid_candela_table[i], &lcd->gamma_table[i][1], G_213, mtp_data); + else if (candela_table[i] == 40) + calc_gamma_table_20_100_ea8061(&lcd->smart, aid_candela_table[i], &lcd->gamma_table[i][1], G_215, mtp_data); + else if (candela_table[i] == 50) + calc_gamma_table_20_100_ea8061(&lcd->smart, aid_candela_table[i], &lcd->gamma_table[i][1], G_218, mtp_data); + else if (candela_table[i] == 60) + calc_gamma_table_20_100_ea8061(&lcd->smart, aid_candela_table[i], &lcd->gamma_table[i][1], G_22, mtp_data); + else if (candela_table[i] == 70) + calc_gamma_table_20_100_ea8061(&lcd->smart, aid_candela_table[i], &lcd->gamma_table[i][1], G_222, mtp_data); + else if (candela_table[i] == 80) + calc_gamma_table_20_100_ea8061(&lcd->smart, aid_candela_table[i], &lcd->gamma_table[i][1], G_223, mtp_data); + else if (candela_table[i] == 90) + calc_gamma_table_20_100_ea8061(&lcd->smart, aid_candela_table[i], &lcd->gamma_table[i][1], G_224, mtp_data); + else if (candela_table[i] == 100) + calc_gamma_table_20_100_ea8061(&lcd->smart, aid_candela_table[i], &lcd->gamma_table[i][1], G_225, mtp_data); + else if (candela_table[i] == 102) + calc_gamma_table_ea8061(&lcd->smart, aid_candela_table[i], &lcd->gamma_table[i][1], G_224, mtp_data); + else if (candela_table[i] == 104) + calc_gamma_table_ea8061(&lcd->smart, aid_candela_table[i], &lcd->gamma_table[i][1], G_223, mtp_data); + else if (candela_table[i] == 106) + calc_gamma_table_ea8061(&lcd->smart, aid_candela_table[i], &lcd->gamma_table[i][1], G_222, mtp_data); + else if (candela_table[i] == 108) + calc_gamma_table_ea8061(&lcd->smart, aid_candela_table[i], &lcd->gamma_table[i][1], G_221, mtp_data); + else if (candela_table[i] == 182) + calc_gamma_table_ea8061(&lcd->smart, aid_candela_table[i], &lcd->gamma_table[i][1], G_221, mtp_data); + else if (candela_table[i] == 184) + calc_gamma_table_ea8061(&lcd->smart, aid_candela_table[i], &lcd->gamma_table[i][1], G_222, mtp_data); + else if (candela_table[i] == 186) + calc_gamma_table_ea8061(&lcd->smart, aid_candela_table[i], &lcd->gamma_table[i][1], G_223, mtp_data); + else if (candela_table[i] == 188) + calc_gamma_table_ea8061(&lcd->smart, aid_candela_table[i], &lcd->gamma_table[i][1], G_224, mtp_data); + else if (candela_table[i] == 190) + calc_gamma_table_190_ea8061(&lcd->smart, aid_candela_table[i], &lcd->gamma_table[i][1], G_225, mtp_data); + else if ((candela_table[i] > 190) && (candela_table[i] < MAX_GAMMA-1)) + calc_gamma_table_ea8061(&lcd->smart, aid_candela_table[i], &lcd->gamma_table[i][1], G_225 , mtp_data); + else if (candela_table[i] == MAX_GAMMA-1) + calc_gamma_table_ea8061(&lcd->smart, aid_candela_table[i], &lcd->gamma_table[i][1], G_22, mtp_data); + else + calc_gamma_table_ea8061(&lcd->smart, aid_candela_table[i], &lcd->gamma_table[i][1], G_22, mtp_data); + } + +#ifdef SMART_DIMMING_DEBUG + for (i = 0; i < GAMMA_MAX; i++) { + for (j = 0; j < GAMMA_PARAM_SIZE; j++) + printk("%d,", lcd->gamma_table[i][j]); + printk("\n"); + } +#endif + return 0; + +err_alloc_gamma: + while (i > 0) { + kfree(lcd->gamma_table[i-1]); + i--; + } + kfree(lcd->gamma_table); +err_alloc_gamma_table: + return ret; +} + +static int init_aid_dimming_table(struct lcd_info *lcd) +{ + unsigned int i, j, c; + u16 reverse_seq[] = {0, 28, 29, 30, 31, 32, 33, 25, 26, 27, 22, 23, 24, 19, 20, 21, 16, 17, 18, 13, 14, 15, 10, 11, 12, 7, 8, 9, 4, 5, 6, 1, 2, 3}; + u16 temp[GAMMA_PARAM_SIZE]; + + if ((lcd->id[1] == 0x12) || (lcd->id[1] == 0x16)) { + for (i = 0; i < ARRAY_SIZE(aid_rgb_fix_table_SM2); i++) { + j = (aid_rgb_fix_table_SM2[i].gray * 3 + aid_rgb_fix_table_SM2[i].rgb) + 1; + c = lcd->gamma_table[aid_rgb_fix_table_SM2[i].candela_idx][j] + aid_rgb_fix_table_SM2[i].offset; + if (c > 0xff) + lcd->gamma_table[aid_rgb_fix_table_SM2[i].candela_idx][j] = 0xff; + else + lcd->gamma_table[aid_rgb_fix_table_SM2[i].candela_idx][j] += aid_rgb_fix_table_SM2[i].offset; + } + } + + if (lcd->id[1] == 0x13) { + for (i = 0; i < ARRAY_SIZE(aid_rgb_fix_table_M4); i++) { + j = (aid_rgb_fix_table_M4[i].gray * 3 + aid_rgb_fix_table_M4[i].rgb) + 1; + c = lcd->gamma_table[aid_rgb_fix_table_M4[i].candela_idx][j] + aid_rgb_fix_table_M4[i].offset; + if (c > 0xff) + lcd->gamma_table[aid_rgb_fix_table_M4[i].candela_idx][j] = 0xff; + else + lcd->gamma_table[aid_rgb_fix_table_M4[i].candela_idx][j] += aid_rgb_fix_table_M4[i].offset; + } + } + + for (i = 0; i < GAMMA_MAX; i++) { + memcpy(lcd->b3[i], SEQ_LTPS_AID, AID_PARAM_SIZE); + lcd->b3[i][0x02] = aid_command_table[i][1]; + lcd->b3[i][0x01] = aid_command_table[i][0]; + } +#ifdef SMART_DIMMING_DEBUG + for (i = 0; i < GAMMA_MAX; i++) { + for (j = 0; j < GAMMA_PARAM_SIZE; j++) + printk("%d,", lcd->gamma_table[i][j]); + printk("\n"); + } + printk("\n"); +#endif + + + for (i = 0; i < GAMMA_MAX; i++) { + for (j = 0; j < GAMMA_PARAM_SIZE; j++) + temp[j] = lcd->gamma_table[i][reverse_seq[j]]; + + for (j = 0; j < GAMMA_PARAM_SIZE; j++) + lcd->gamma_table[i][j] = temp[j]; + + lcd->gamma_table[i][31] = lcd->smart.default_gamma[31]<<4|lcd->smart.default_gamma[30]; + /*default_gamma 30,31th range 0000~1111 */ + /*31,30th gamma need to reverse order , because of normal order is R,G,B + but Magna DDI VT G,R,B so R,G order change to G,R order*/ + lcd->gamma_table[i][32] = lcd->smart.default_gamma[32]; + } + +#ifdef SMART_DIMMING_DEBUG + for (i = 0; i < GAMMA_MAX; i++) { + for (j = 0; j < GAMMA_PARAM_SIZE-1; j++) + printk("0x%x,", lcd->gamma_table[i][j]); + printk("\n"); + } +#endif + + return 0; +} +#endif + +static int update_brightness(struct lcd_info *lcd, u8 force) +{ + u32 brightness; + + mutex_lock(&lcd->bl_lock); + + brightness = lcd->bd->props.brightness; + + if (unlikely(!lcd->auto_brightness && brightness > 250)) + brightness = 250; + + lcd->bl = get_backlight_level_from_brightness(brightness); + + if ((force) || ((lcd->ldi_enable) && (lcd->current_bl != lcd->bl))) { + + ea8061_gamma_ctl(lcd); + + ea8061_aid_parameter_ctl(lcd, force); + + ea8061_set_acl(lcd, force); + + ea8061_set_elvss(lcd, force); + + lcd->current_bl = lcd->bl; + + dev_info(&lcd->ld->dev, "brightness=%d, bl=%d, candela=%d\n", brightness, lcd->bl, candela_table[lcd->bl]); + } + + mutex_unlock(&lcd->bl_lock); + + return 0; +} + +static int slew_rev_control_set(struct lcd_info *lcd) +{ + if (lcd->id[2] == 0x00) + ea8061_write(lcd, SEQ_SLEW_REV00, ARRAY_SIZE(SEQ_SLEW_REV00)); + else if (lcd->id[2] == 0x01) + ea8061_write(lcd, SEQ_SLEW_REV01, ARRAY_SIZE(SEQ_SLEW_REV01)); + else if (lcd->id[2] == 0x02) + ea8061_write(lcd, SEQ_SLEW_REV02, ARRAY_SIZE(SEQ_SLEW_REV02)); + else if (lcd->id[2] == 0x03) + ea8061_write(lcd, SEQ_SLEW_REV03, ARRAY_SIZE(SEQ_SLEW_REV03)); + else + ea8061_write(lcd, SEQ_SLEW_REV04, ARRAY_SIZE(SEQ_SLEW_REV04)); + return 0; +} + +static int ea8061_ldi_init(struct lcd_info *lcd) +{ + int ret = 0; + ea8061_write(lcd, SEQ_APPLY_LEVEL_2_KEY_ENABLE, ARRAY_SIZE(SEQ_APPLY_LEVEL_2_KEY_ENABLE)); + ea8061_write(lcd, SEQ_APPLY_LEVEL_3_KEY, ARRAY_SIZE(SEQ_APPLY_LEVEL_3_KEY)); + if (lcd->id[1] == 0x13) { /* M4 */ + ea8061_write(lcd, SEQ_M4_PANEL_CONDITION_SET, ARRAY_SIZE(SEQ_M4_PANEL_CONDITION_SET)); + ea8061_write(lcd, SEQ_DISPLAY_CONDITION_SET, ARRAY_SIZE(SEQ_DISPLAY_CONDITION_SET)); +/* ea8061_write(lcd, SEQ_FRAME_GAMMA_UPDATE_KEY, ARRAY_SIZE(SEQ_FRAME_GAMMA_UPDATE_KEY)); + ea8061_write(lcd, SEQ_M4_GAMMA_CONDITION_SET, ARRAY_SIZE(SEQ_M4_GAMMA_CONDITION_SET)); + ea8061_write(lcd, SEQ_FRAME_GAMMA_UPDATE_KEY2, ARRAY_SIZE(SEQ_FRAME_GAMMA_UPDATE_KEY2)); */ + ea8061_gamma_ctl(lcd); + ea8061_write(lcd, SEQ_LTPS_AID, ARRAY_SIZE(SEQ_LTPS_AID)); + ea8061_write(lcd, ELVSS_CONTROL_SET, ARRAY_SIZE(ELVSS_CONTROL_SET)); + ea8061_write(lcd, SEQ_ETC_WCABC_CONTROL, ARRAY_SIZE(SEQ_ETC_WCABC_CONTROL)); + ea8061_write(lcd, SEQ_M4_SLEW, ARRAY_SIZE(SEQ_M4_SLEW)); + } else { /* SM2 */ + ea8061_write(lcd, SEQ_PANEL_CONDITION_SET, ARRAY_SIZE(SEQ_PANEL_CONDITION_SET)); + ea8061_write(lcd, SEQ_DISPLAY_CONDITION_SET, ARRAY_SIZE(SEQ_DISPLAY_CONDITION_SET)); +/* ea8061_write(lcd, SEQ_FRAME_GAMMA_UPDATE_KEY, ARRAY_SIZE(SEQ_FRAME_GAMMA_UPDATE_KEY)); + ea8061_write(lcd, SEQ_GAMMA_CONDITION_SET, ARRAY_SIZE(SEQ_GAMMA_CONDITION_SET)); + ea8061_write(lcd, SEQ_FRAME_GAMMA_UPDATE_KEY2, ARRAY_SIZE(SEQ_FRAME_GAMMA_UPDATE_KEY2)); */ + ea8061_gamma_ctl(lcd); + ea8061_write(lcd, SEQ_LTPS_AID, ARRAY_SIZE(SEQ_LTPS_AID)); + ea8061_write(lcd, ELVSS_CONTROL_SET, ARRAY_SIZE(ELVSS_CONTROL_SET)); + ea8061_write(lcd, SEQ_ETC_WCABC_CONTROL, ARRAY_SIZE(SEQ_ETC_WCABC_CONTROL)); + slew_rev_control_set(lcd); + } + + ea8061_write(lcd, SEQ_SLEEP_OUT, ARRAY_SIZE(SEQ_SLEEP_OUT)); + + return ret; +} + +static int ea8061_ldi_enable(struct lcd_info *lcd) +{ + int ret = 0; + + ea8061_write(lcd, SEQ_DISPLAY_ON, ARRAY_SIZE(SEQ_DISPLAY_ON)); + + return ret; +} + +static int ea8061_ldi_disable(struct lcd_info *lcd) +{ + int ret = 0; + + ea8061_write(lcd, SEQ_DISPLAY_OFF, ARRAY_SIZE(SEQ_DISPLAY_OFF)); + + msleep(35); + + ea8061_write(lcd, SEQ_SLEEP_IN, ARRAY_SIZE(SEQ_SLEEP_IN)); + + msleep(100); + + return ret; +} + +static int ea8061_power_on(struct lcd_info *lcd) +{ + int ret = 0; + struct lcd_platform_data *pd = NULL; + pd = lcd->lcd_pd; + + dev_info(&lcd->ld->dev, "%s\n", __func__); + + ret = ea8061_ldi_init(lcd); + if (ret) { + dev_err(&lcd->ld->dev, "failed to initialize ldi.\n"); + goto err; + } + + msleep(120); + + ret = ea8061_ldi_enable(lcd); + if (ret) { + dev_err(&lcd->ld->dev, "failed to enable ldi.\n"); + goto err; + } + + lcd->ldi_enable = 1; + + update_brightness(lcd, 1); +err: + return ret; +} + +static int ea8061_power_off(struct lcd_info *lcd) +{ + int ret = 0; + + dev_info(&lcd->ld->dev, "%s\n", __func__); + + lcd->ldi_enable = 0; + + ret = ea8061_ldi_disable(lcd); + + msleep(135); + + return ret; +} + +static int ea8061_power(struct lcd_info *lcd, int power) +{ + int ret = 0; + + if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->power)) + ret = ea8061_power_on(lcd); + else if (!POWER_IS_ON(power) && POWER_IS_ON(lcd->power)) + ret = ea8061_power_off(lcd); + + if (!ret) + lcd->power = power; + + return ret; +} + +static int ea8061_set_power(struct lcd_device *ld, int power) +{ + struct lcd_info *lcd = lcd_get_data(ld); + + if (power != FB_BLANK_UNBLANK && power != FB_BLANK_POWERDOWN && + power != FB_BLANK_NORMAL) { + dev_err(&lcd->ld->dev, "power value should be 0, 1 or 4.\n"); + return -EINVAL; + } + + return ea8061_power(lcd, power); +} + +static int ea8061_get_power(struct lcd_device *ld) +{ + struct lcd_info *lcd = lcd_get_data(ld); + + return lcd->power; +} + + +static int ea8061_set_brightness(struct backlight_device *bd) +{ + int ret = 0; + int brightness = bd->props.brightness; + struct lcd_info *lcd = bl_get_data(bd); + + /* dev_info(&lcd->ld->dev, "%s: brightness=%d\n", __func__, brightness); */ + + if (brightness < MIN_BRIGHTNESS || + brightness > bd->props.max_brightness) { + dev_err(&bd->dev, "lcd brightness should be %d to %d. now %d\n", + MIN_BRIGHTNESS, MAX_BRIGHTNESS, brightness); + return -EINVAL; + } + + if (lcd->ldi_enable) { + ret = update_brightness(lcd, 0); + if (ret < 0) { + dev_err(lcd->dev, "err in %s\n", __func__); + return -EINVAL; + } + } + + return ret; +} + +static int ea8061_get_brightness(struct backlight_device *bd) +{ + struct lcd_info *lcd = bl_get_data(bd); + + return candela_table[lcd->bl]; +} + +static int ea8061_check_fb(struct lcd_device *ld, struct fb_info *fb) +{ + struct s3cfb_window *win = fb->par; + struct lcd_info *lcd = lcd_get_data(ld); + + dev_info(&lcd->ld->dev, "%s, fb%d\n", __func__, win->id); + + return 0; +} + +static struct lcd_ops ea8061_lcd_ops = { + .set_power = ea8061_set_power, + .get_power = ea8061_get_power, + .check_fb = ea8061_check_fb, +}; + +static const struct backlight_ops ea8061_backlight_ops = { + .get_brightness = ea8061_get_brightness, + .update_status = ea8061_set_brightness, +}; + +static ssize_t power_reduce_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct lcd_info *lcd = dev_get_drvdata(dev); + char temp[3]; + + sprintf(temp, "%d\n", lcd->acl_enable); + strcpy(buf, temp); + + return strlen(buf); +} + +static ssize_t power_reduce_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + struct lcd_info *lcd = dev_get_drvdata(dev); + int value; + int rc; + + rc = strict_strtoul(buf, (unsigned int)0, (unsigned long *)&value); + if (rc < 0) + return rc; + else { + if (lcd->acl_enable != value) { + dev_info(dev, "%s - %d, %d\n", __func__, lcd->acl_enable, value); + mutex_lock(&lcd->bl_lock); + lcd->acl_enable = value; + mutex_unlock(&lcd->bl_lock); + if (lcd->ldi_enable) + update_brightness(lcd, 1); + } + } + return size; +} + +static DEVICE_ATTR(power_reduce, 0664, power_reduce_show, power_reduce_store); + +static ssize_t lcd_type_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + char temp[15]; + sprintf(temp, "SMD_AMS555HBxx\n"); + + strcat(buf, temp); + return strlen(buf); +} + +static DEVICE_ATTR(lcd_type, 0444, lcd_type_show, NULL); + +static ssize_t window_type_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct lcd_info *lcd = dev_get_drvdata(dev); + char temp[15]; + + sprintf(temp, "%x %x %x\n", lcd->id[0], lcd->id[1], lcd->id[2]); + + strcat(buf, temp); + return strlen(buf); +} + +static DEVICE_ATTR(window_type, 0444, window_type_show, NULL); + +static ssize_t gamma_table_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct lcd_info *lcd = dev_get_drvdata(dev); + int i, j; + + for (i = 0; i < GAMMA_MAX; i++) { + for (j = 0; j < GAMMA_PARAM_SIZE; j++) + printk("0x%02x, ", lcd->gamma_table[i][j]); + printk("\n"); + } + + for (i = 0; i < ELVSS_STATUS_MAX; i++) { + for (j = 0; j < ELVSS_PARAM_SIZE; j++) + printk("0x%02x, ", lcd->elvss_table[i][j]); + printk("\n"); + } + + return strlen(buf); +} +static DEVICE_ATTR(gamma_table, 0444, gamma_table_show, NULL); + +static ssize_t auto_brightness_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct lcd_info *lcd = dev_get_drvdata(dev); + char temp[3]; + + sprintf(temp, "%d\n", lcd->auto_brightness); + strcpy(buf, temp); + + return strlen(buf); +} + +static ssize_t auto_brightness_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + struct lcd_info *lcd = dev_get_drvdata(dev); + int value; + int rc; + + rc = strict_strtoul(buf, (unsigned int)0, (unsigned long *)&value); + if (rc < 0) + return rc; + else { + if (lcd->auto_brightness != value) { + dev_info(dev, "%s - %d, %d\n", __func__, lcd->auto_brightness, value); + mutex_lock(&lcd->bl_lock); + lcd->auto_brightness = value; + mutex_unlock(&lcd->bl_lock); + if (lcd->ldi_enable) + update_brightness(lcd, 1); + } + } + return size; +} + +static DEVICE_ATTR(auto_brightness, 0644, auto_brightness_show, auto_brightness_store); + +#ifdef CONFIG_HAS_EARLYSUSPEND +static struct lcd_info *g_lcd; + +void ea8061_early_suspend(void) +{ + struct lcd_info *lcd = g_lcd; + + set_dsim_lcd_enabled(0); + + dev_info(&lcd->ld->dev, "+%s\n", __func__); + +#if defined(GPIO_OLED_DET) + disable_irq(lcd->irq); + gpio_request(GPIO_OLED_DET, "OLED_DET"); + s3c_gpio_cfgpin(GPIO_OLED_DET, S3C_GPIO_OUTPUT); + s3c_gpio_setpull(GPIO_OLED_DET, S3C_GPIO_PULL_NONE); + gpio_direction_output(GPIO_OLED_DET, GPIO_LEVEL_LOW); + gpio_free(GPIO_OLED_DET); +#endif + + ea8061_power(lcd, FB_BLANK_POWERDOWN); + dev_info(&lcd->ld->dev, "-%s\n", __func__); + + return ; +} + +void ea8061_late_resume(void) +{ + struct lcd_info *lcd = g_lcd; + + dev_info(&lcd->ld->dev, "+%s\n", __func__); + ea8061_power(lcd, FB_BLANK_UNBLANK); + +#if defined(GPIO_OLED_DET) + s3c_gpio_cfgpin(GPIO_OLED_DET, S3C_GPIO_SFN(0xf)); + s3c_gpio_setpull(GPIO_OLED_DET, S3C_GPIO_PULL_NONE); + enable_irq(lcd->irq); +#endif + + dev_info(&lcd->ld->dev, "-%s\n", __func__); + + set_dsim_lcd_enabled(1); + + return ; +} +#endif + + +static void ea8061_read_id(struct lcd_info *lcd, u8 *buf) +{ + int ret = 0; + unsigned char wbuf[] = {0xFD, LDI_ID_REG}; + + ea8061_write(lcd, wbuf, ARRAY_SIZE(wbuf)); + + ret = ea8061_read(lcd, 0xFE, LDI_ID_LEN, buf, 2); + if (!ret) { + lcd->connected = 0; + dev_info(&lcd->ld->dev, "panel is not connected well\n"); + } +} + +#ifdef SMART_DIMMING +static int ea8061_read_mtp(struct lcd_info *lcd, u8 *mtp_data) +{ + int ret; + + unsigned char wbuf[] = {0xFD, LDI_MTP_ADDR}; + + ea8061_write(lcd, wbuf, ARRAY_SIZE(wbuf)); + + ret = ea8061_read(lcd, 0xFE, LDI_MTP_LENGTH, mtp_data, 1); + return ret; +} +#endif + +static int ea8061_probe(struct device *dev) +{ + int ret = 0, i; + struct lcd_info *lcd; + +#ifdef SMART_DIMMING + u8 mtp_data[LDI_MTP_LENGTH] = {0,}; +#endif + + lcd = kzalloc(sizeof(struct lcd_info), GFP_KERNEL); + if (!lcd) { + pr_err("failed to allocate for lcd\n"); + ret = -ENOMEM; + goto err_alloc; + } + + g_lcd = lcd; + + lcd->ld = lcd_device_register("panel", dev, lcd, &ea8061_lcd_ops); + if (IS_ERR(lcd->ld)) { + pr_err("failed to register lcd device\n"); + ret = PTR_ERR(lcd->ld); + goto out_free_lcd; + } + + lcd->bd = backlight_device_register("panel", dev, lcd, &ea8061_backlight_ops, NULL); + if (IS_ERR(lcd->bd)) { + pr_err("failed to register backlight device\n"); + ret = PTR_ERR(lcd->bd); + goto out_free_backlight; + } + + lcd->dev = dev; + lcd->dsim = (struct dsim_global *)dev_get_drvdata(dev->parent); + lcd->bd->props.max_brightness = MAX_BRIGHTNESS; + lcd->bd->props.brightness = DEFAULT_BRIGHTNESS; + lcd->bl = DEFAULT_GAMMA_LEVEL; + lcd->current_bl = lcd->bl; + lcd->acl_enable = 0; + lcd->current_acl = 0; + lcd->power = FB_BLANK_UNBLANK; + lcd->ldi_enable = 1; + lcd->connected = 1; + lcd->auto_brightness = 0; + + ret = device_create_file(&lcd->ld->dev, &dev_attr_power_reduce); + if (ret < 0) + dev_err(&lcd->ld->dev, "failed to add sysfs entries, %d\n", __LINE__); + + ret = device_create_file(&lcd->ld->dev, &dev_attr_lcd_type); + if (ret < 0) + dev_err(&lcd->ld->dev, "failed to add sysfs entries, %d\n", __LINE__); + + ret = device_create_file(&lcd->ld->dev, &dev_attr_window_type); + if (ret < 0) + dev_err(&lcd->ld->dev, "failed to add sysfs entries, %d\n", __LINE__); + + ret = device_create_file(&lcd->ld->dev, &dev_attr_gamma_table); + if (ret < 0) + dev_err(&lcd->ld->dev, "failed to add sysfs entries, %d\n", __LINE__); + + ret = device_create_file(&lcd->bd->dev, &dev_attr_auto_brightness); + if (ret < 0) + dev_err(&lcd->ld->dev, "failed to add sysfs entries, %d\n", __LINE__); + + dev_set_drvdata(dev, lcd); + + mutex_init(&lcd->lock); + mutex_init(&lcd->bl_lock); + + ea8061_read_id(lcd, lcd->id); + + dev_info(&lcd->ld->dev, "ID: %x, %x, %x\n", lcd->id[0], lcd->id[1], lcd->id[2]); + + dev_info(&lcd->ld->dev, "%s lcd panel driver has been probed.\n", dev_name(dev)); + +#ifdef SMART_DIMMING + for (i = 0; i < LDI_ID_LEN; i++) + lcd->smart.panelid[i] = lcd->id[i]; + + init_table_info_ea8061(&lcd->smart); + + ret = ea8061_read_mtp(lcd, mtp_data); +/* + for (i = 0; i < LDI_MTP_LENGTH ; i++) + printk(" %dth mtp value is %x\n", i, mtp_data[i]); +*/ + if (!ret) + printk(KERN_ERR "[LCD:ERROR] : %s read mtp failed\n", __func__); + + calc_voltage_table_ea8061(&lcd->smart, mtp_data); + + ret = init_elvss_table(lcd); + ret += init_gamma_table(lcd, mtp_data); + ret += init_aid_dimming_table(lcd); + + if (ret) + printk(KERN_ERR "gamma table generation is failed\n"); + + update_brightness(lcd, 1); +#endif + +#if defined(GPIO_OLED_DET) + if (lcd->connected) { + INIT_DELAYED_WORK(&lcd->oled_detection, oled_detection_work); + + lcd->irq = gpio_to_irq(GPIO_OLED_DET); + + s3c_gpio_cfgpin(GPIO_OLED_DET, S3C_GPIO_SFN(0xf)); + s3c_gpio_setpull(GPIO_OLED_DET, S3C_GPIO_PULL_NONE); + + if (request_irq(lcd->irq, oled_detection_int, + IRQF_TRIGGER_FALLING, "oled_detection", lcd)) + pr_err("failed to reqeust irq. %d\n", lcd->irq); + } +#endif + + lcd_early_suspend = ea8061_early_suspend; + lcd_late_resume = ea8061_late_resume; + + return 0; + +out_free_backlight: + lcd_device_unregister(lcd->ld); + kfree(lcd); + return ret; + +out_free_lcd: + kfree(lcd); + return ret; + +err_alloc: + return ret; +} + +static int __devexit ea8061_remove(struct device *dev) +{ + struct lcd_info *lcd = dev_get_drvdata(dev); + + ea8061_power(lcd, FB_BLANK_POWERDOWN); + lcd_device_unregister(lcd->ld); + backlight_device_unregister(lcd->bd); + kfree(lcd); + + return 0; +} + +/* Power down all displays on reboot, poweroff or halt. */ +static void ea8061_shutdown(struct device *dev) +{ + struct lcd_info *lcd = dev_get_drvdata(dev); + + dev_info(&lcd->ld->dev, "%s\n", __func__); + + ea8061_power(lcd, FB_BLANK_POWERDOWN); +} + +static struct mipi_lcd_driver ea8061_mipi_driver = { + .name = "ea8061", + .probe = ea8061_probe, + .remove = __devexit_p(ea8061_remove), + .shutdown = ea8061_shutdown, +}; + +static int ea8061_init(void) +{ + return s5p_dsim_register_lcd_driver(&ea8061_mipi_driver); +} + +static void ea8061_exit(void) +{ + return; +} + +module_init(ea8061_init); +module_exit(ea8061_exit); + +MODULE_DESCRIPTION("MIPI-DSI EA8061:AMS555HBXX (720x1280) Panel Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/samsung/s3cfb_fimd6x.c b/drivers/video/samsung/s3cfb_fimd6x.c index 71a24ae..02c75e6 100644 --- a/drivers/video/samsung/s3cfb_fimd6x.c +++ b/drivers/video/samsung/s3cfb_fimd6x.c @@ -22,6 +22,11 @@ #include "s3cfb.h" +#ifdef CONFIG_FB_S5P_SYSMMU +#include <asm/cacheflush.h> +#include <plat/s5p-sysmmu.h> +#endif + void s3cfb_check_line_count(struct s3cfb_global *ctrl) { int timeout = 30 * 5300; @@ -111,6 +116,12 @@ int s3cfb_set_output(struct s3cfb_global *ctrl) return -EINVAL; } +#if defined(CONFIG_FB_RGBA_ORDER) + /* Change format to BGR order */ + cfg &= ~(0x3F0000); + cfg |= 0x240000; +#endif + writel(cfg, ctrl->regs + S3C_VIDCON2); if (ctrl->output == OUTPUT_I80LDI0) { @@ -210,7 +221,7 @@ int s3cfb_set_clock(struct s3cfb_global *ctrl) S3C_VIDCON0_VCLKEN_FREERUN); src_clk = clk_get_rate(ctrl->clock); - printk(KERN_DEBUG "FIMD src sclk = %d\n", src_clk); + dev_dbg(ctrl->dev, "FIMD src sclk = %d\n", src_clk); } else { cfg &= ~(S3C_VIDCON0_CLKSEL_MASK | S3C_VIDCON0_CLKVALUP_MASK | @@ -223,12 +234,12 @@ int s3cfb_set_clock(struct s3cfb_global *ctrl) if (strcmp(pdata->clk_name, "sclk_fimd") == 0) { cfg |= S3C_VIDCON0_CLKSEL_SCLK; src_clk = clk_get_rate(ctrl->clock); - printk(KERN_DEBUG "FIMD src sclk = %d\n", src_clk); + dev_dbg(ctrl->dev, "FIMD src sclk = %d\n", src_clk); } else { cfg |= S3C_VIDCON0_CLKSEL_HCLK; src_clk = ctrl->clock->parent->rate; - printk(KERN_DEBUG "FIMD src hclk = %d\n", src_clk); + dev_dbg(ctrl->dev, "FIMD src hclk = %d\n", src_clk); } } @@ -555,6 +566,23 @@ int s3cfb_win_map_off(struct s3cfb_global *ctrl, int id) return 0; } +int s3cfb_set_window_protect(struct s3cfb_global *ctrl, int id, bool protect) +{ + struct s3c_platform_fb *pdata = to_fb_plat(ctrl->dev); + u32 shw; + + if ((pdata->hw_ver == 0x62) || (pdata->hw_ver == 0x70)) { + shw = readl(ctrl->regs + S3C_WINSHMAP); + if (protect) + shw |= S3C_WINSHMAP_PROTECT(id); + else + shw &= ~(S3C_WINSHMAP_PROTECT(id)); + writel(shw, ctrl->regs + S3C_WINSHMAP); + } + + return 0; +} + int s3cfb_set_window_control(struct s3cfb_global *ctrl, int id) { struct s3c_platform_fb *pdata = to_fb_plat(ctrl->dev); @@ -677,6 +705,38 @@ int s3cfb_get_win_cur_buf_addr(struct s3cfb_global *ctrl, int id) return start_addr; } +#ifdef CONFIG_FB_S5P_SYSMMU +#define LV1_SHIFT 20 +#define LV1_PT_SIZE SZ_1M +#define LV2_PT_SIZE SZ_1K +#define LV2_BASE_MASK 0x3ff + +void s3cfb_clean_outer_pagetable(unsigned long vaddr, size_t size) +{ + unsigned long *pgd; + unsigned long *lv1, *lv1end; + unsigned long lv2pa; + + if (!current->mm) + return; + + pgd = (unsigned long *)current->mm->pgd; + + lv1 = pgd + (vaddr >> LV1_SHIFT); + lv1end = pgd + ((vaddr + size + LV1_PT_SIZE-1) >> LV1_SHIFT); + + /* clean level1 page table */ + outer_clean_range(virt_to_phys(lv1), virt_to_phys(lv1end)); + + do { + lv2pa = *lv1 & ~LV2_BASE_MASK; /* lv2 pt base */ + /* clean level2 page table */ + outer_clean_range(lv2pa, lv2pa + LV2_PT_SIZE); + lv1++; + } while (lv1 != lv1end); +} +#endif + int s3cfb_set_buffer_address(struct s3cfb_global *ctrl, int id) { struct fb_fix_screeninfo *fix = &ctrl->fb[id]->fix; diff --git a/drivers/video/samsung/s3cfb_ielcd.c b/drivers/video/samsung/s3cfb_ielcd.c index b86d6f5..f8c90d2 100644 --- a/drivers/video/samsung/s3cfb_ielcd.c +++ b/drivers/video/samsung/s3cfb_ielcd.c @@ -59,7 +59,7 @@ int s3c_ielcd_hw_init(void) return -ENOENT; } - printk(KERN_INFO "%s : 0x%p\n", __func__, s3c_ielcd_base); + /* printk(KERN_INFO "%s : 0x%p\n", __func__, s3c_ielcd_base); */ ielcd_fbdev = &ielcd_fb; diff --git a/drivers/video/samsung/s3cfb_lms501xx.c b/drivers/video/samsung/s3cfb_lms501xx.c new file mode 100644 index 0000000..c57a8be --- /dev/null +++ b/drivers/video/samsung/s3cfb_lms501xx.c @@ -0,0 +1,737 @@ +/* linux/drivers/video/samsung/s3cfb_lms501xx.c + * + * MIPI-DSI based LMS501XX TFT lcd panel 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/mutex.h> +#include <linux/wait.h> +#include <linux/ctype.h> +#include <linux/io.h> +#include <linux/delay.h> +#include <linux/irq.h> +#include <linux/interrupt.h> +#include <linux/gpio.h> +#include <linux/workqueue.h> +#include <linux/backlight.h> +#include <linux/lcd.h> +#include <plat/gpio-cfg.h> +#include <plat/regs-dsim.h> +#include <mach/dsim.h> +#include <mach/mipi_ddi.h> +#ifdef CONFIG_HAS_EARLYSUSPEND +#include <linux/earlysuspend.h> +#endif + +#include "s5p-dsim.h" +#include "s3cfb.h" +#include "lms501xx.h" + +#define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL) + +#define MIN_BRIGHTNESS 0 +#define MAX_BRIGHTNESS 255 +#define MAX_GAMMA 255 +#define DEFAULT_BRIGHTNESS 160 +#define DEFAULT_GAMMA_LEVEL GAMMA_160CD + +#define LDI_ID_REG 0xD1 +#define LDI_ID_LEN 3 + +struct lcd_info { + unsigned int bl; + unsigned int auto_brightness; + unsigned int current_cabc; + unsigned int current_bl; + + unsigned int ldi_enable; + unsigned int power; + struct mutex lock; + struct mutex bl_lock; + + struct device *dev; + struct lcd_device *ld; + struct backlight_device *bd; + struct lcd_platform_data *lcd_pd; + struct early_suspend early_suspend; + + unsigned char id[LDI_ID_LEN]; + + unsigned char **gamma_table; + unsigned char **elvss_table; + + unsigned int irq; + unsigned int connected; + +#if defined(GPIO_OLED_DET) + struct delayed_work oled_detection; + unsigned int oled_detection_count; +#endif + struct dsim_global *dsim; +}; + +static const unsigned int candela_table[GAMMA_MAX] = { + 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, + 130, 140, 150, 160, 170, 180, 190, 200, 210, 220, + 230, 240, 250, MAX_GAMMA +}; + +extern void (*lcd_early_suspend)(void); +extern void (*lcd_late_resume)(void); + +#if defined(GPIO_OLED_DET) +static void oled_detection_work(struct work_struct *work) +{ + struct lcd_info *lcd = + container_of(work, struct lcd_info, oled_detection.work); + + int oled_det_level = gpio_get_value(GPIO_OLED_DET); + + dev_info(&lcd->ld->dev, "%s, %d, %d\n", + __func__, lcd->oled_detection_count, oled_det_level); + + if (!oled_det_level) { + if (lcd->oled_detection_count < 10) { + schedule_delayed_work(&lcd->oled_detection, HZ/8); + lcd->oled_detection_count++; + set_dsim_hs_clk_toggle_count(15); + } else + set_dsim_hs_clk_toggle_count(0); + } else + set_dsim_hs_clk_toggle_count(0); + +} + +static irqreturn_t oled_detection_int(int irq, void *_lcd) +{ + struct lcd_info *lcd = _lcd; + + dev_info(&lcd->ld->dev, "%s\n", __func__); + + lcd->oled_detection_count = 0; + schedule_delayed_work(&lcd->oled_detection, HZ/16); + + return IRQ_HANDLED; +} +#endif + +static int lms501xx_write(struct lcd_info *lcd, + const unsigned char *seq, int len) +{ + int size; + const unsigned char *wbuf; + + if (!lcd->connected) + return 0; + + mutex_lock(&lcd->lock); + + size = len; + wbuf = seq; + + if (size == 1) + lcd->dsim->ops->cmd_write(lcd->dsim, + DCS_WR_NO_PARA, wbuf[0], 0); + else if (size == 2) + lcd->dsim->ops->cmd_write(lcd->dsim, + DCS_WR_1_PARA, wbuf[0], wbuf[1]); + else + lcd->dsim->ops->cmd_write(lcd->dsim, + DCS_LONG_WR, (unsigned int)wbuf, size); + + mutex_unlock(&lcd->lock); + + return 0; +} + +static int _lms501xx_read(struct lcd_info *lcd, + const u8 addr, u16 count, u8 *buf) +{ + int ret = 0; + + if (!lcd->connected) + return ret; + + mutex_lock(&lcd->lock); + + if (lcd->dsim->ops->cmd_read) + ret = lcd->dsim->ops->cmd_read(lcd->dsim, addr, count, buf); + + mutex_unlock(&lcd->lock); + + return ret; +} + +static int lms501xx_read(struct lcd_info *lcd, + const u8 addr, u16 count, u8 *buf, u8 retry_cnt) +{ + int ret = 0; + +read_retry: + ret = _lms501xx_read(lcd, addr, count, buf); + if (!ret) { + if (retry_cnt) { + printk(KERN_WARNING + "[WARN:LCD] %s : retry cnt : %d\n", + __func__, retry_cnt); + retry_cnt--; + goto read_retry; + } else + printk(KERN_ERR + "[ERROR:LCD] %s : 0x%02x read failed\n", + __func__, addr); + } + + return ret; +} + +static int get_backlight_level_from_brightness(int brightness) +{ + int backlightlevel; + + /* brightness setting from platform is from 0 to 255 + * But in this driver, brightness is only supported from 0 to 24 */ + + switch (brightness) { + case 0 ... 29: + backlightlevel = GAMMA_30CD; + break; + case 30 ... 254: + backlightlevel = (brightness - candela_table[0]) / 10; + break; + case 255: + backlightlevel = ARRAY_SIZE(candela_table) - 1; + break; + default: + backlightlevel = DEFAULT_GAMMA_LEVEL; + break; + } + return backlightlevel; +} + +static int lms501xx_gamma_ctl(struct lcd_info *lcd) +{ + SEQ_SET_BL[1] = candela_table[lcd->bl]; + lms501xx_write(lcd, SEQ_SET_BL, ARRAY_SIZE(SEQ_SET_BL)); + lms501xx_write(lcd, SEQ_SET_DISP, ARRAY_SIZE(SEQ_SET_DISP)); + return 0; +} + +static int lms501xx_set_cabc(struct lcd_info *lcd) +{ + int ret = 0; + + dev_info(&lcd->ld->dev, "%s - %d\n", __func__, lcd->current_cabc); + if (lcd->current_cabc) + lms501xx_write(lcd, + SEQ_SET_CABC_ON, ARRAY_SIZE(SEQ_SET_CABC_ON)); + else + lms501xx_write(lcd, + SEQ_SET_CABC_OFF, ARRAY_SIZE(SEQ_SET_CABC_OFF)); + + mdelay(5); + + return ret; +} + +static int update_brightness(struct lcd_info *lcd, u8 force) +{ + u32 brightness; + + mutex_lock(&lcd->bl_lock); + + brightness = lcd->bd->props.brightness; + + if (unlikely(!lcd->auto_brightness && brightness > 250)) + brightness = 250; + + lcd->bl = get_backlight_level_from_brightness(brightness); + + if ((force) || ((lcd->ldi_enable) && (lcd->current_bl != lcd->bl))) { + + lms501xx_gamma_ctl(lcd); + lms501xx_set_cabc(lcd); + + lcd->current_bl = lcd->bl; + + dev_info(&lcd->ld->dev, "brightness=%d, bl=%d, candela=%d\n", + brightness, lcd->bl, candela_table[lcd->bl]); + } + + mutex_unlock(&lcd->bl_lock); + + return 0; +} + +static int lms501xx_ldi_init(struct lcd_info *lcd) +{ + int ret = 0; + + dev_info(&lcd->ld->dev, "%s\n", __func__); + + lms501xx_write(lcd, SEQ_SET_EXTC, ARRAY_SIZE(SEQ_SET_EXTC)); + mdelay(5); + lms501xx_write(lcd, SEQ_SET_MIPI_DSI, ARRAY_SIZE(SEQ_SET_MIPI_DSI)); + lms501xx_write(lcd, SEQ_SET_GIP, ARRAY_SIZE(SEQ_SET_GIP)); + lms501xx_write(lcd, SEQ_SET_POWER, ARRAY_SIZE(SEQ_SET_POWER)); + mdelay(5); + lms501xx_write(lcd, SEQ_SLEEP_OUT, ARRAY_SIZE(SEQ_SLEEP_OUT)); + msleep(125); + lms501xx_write(lcd, SEQ_SET_RGB, ARRAY_SIZE(SEQ_SET_RGB)); + lms501xx_write(lcd, SEQ_SET_CYC, ARRAY_SIZE(SEQ_SET_CYC)); + lms501xx_write(lcd, SEQ_SET_VCOM, ARRAY_SIZE(SEQ_SET_VCOM)); + lms501xx_write(lcd, SEQ_SET_PTBA, ARRAY_SIZE(SEQ_SET_PTBA)); + lms501xx_write(lcd, SEQ_SET_PANEL, ARRAY_SIZE(SEQ_SET_PANEL)); + lms501xx_write(lcd, SEQ_SET_DGC, ARRAY_SIZE(SEQ_SET_DGC)); + lms501xx_write(lcd, SEQ_SET_STBA, ARRAY_SIZE(SEQ_SET_STBA)); + lms501xx_write(lcd, SEQ_SET_EQ, ARRAY_SIZE(SEQ_SET_EQ)); + lms501xx_write(lcd, SEQ_SET_VCOM_POWER, ARRAY_SIZE(SEQ_SET_VCOM_POWER)); + lms501xx_write(lcd, SEQ_SET_ECO, ARRAY_SIZE(SEQ_SET_ECO)); + lms501xx_write(lcd, SEQ_SET_GAMMA, ARRAY_SIZE(SEQ_SET_GAMMA)); + lms501xx_write(lcd, SEQ_SET_CABC_PWM, ARRAY_SIZE(SEQ_SET_CABC_PWM)); + + return ret; +} + +static int lms501xx_ldi_enable(struct lcd_info *lcd) +{ + int ret = 0; + + lms501xx_write(lcd, SEQ_DISPLAY_ON, ARRAY_SIZE(SEQ_DISPLAY_ON)); + msleep(100); + + return ret; +} + +static int lms501xx_ldi_disable(struct lcd_info *lcd) +{ + int ret = 0; + + lms501xx_write(lcd, SEQ_DISPLAY_OFF, ARRAY_SIZE(SEQ_DISPLAY_OFF)); + lms501xx_write(lcd, SEQ_SLEEP_IN, ARRAY_SIZE(SEQ_SLEEP_IN)); + + return ret; +} + +static int lms501xx_power_on(struct lcd_info *lcd) +{ + int ret = 0; + struct lcd_platform_data *pd = NULL; + pd = lcd->lcd_pd; + + dev_info(&lcd->ld->dev, "%s\n", __func__); + + ret = lms501xx_ldi_init(lcd); + if (ret) { + dev_err(&lcd->ld->dev, "failed to initialize ldi.\n"); + goto err; + } + + msleep(120); + + ret = lms501xx_ldi_enable(lcd); + if (ret) { + dev_err(&lcd->ld->dev, "failed to enable ldi.\n"); + goto err; + } + + lcd->ldi_enable = 1; + + update_brightness(lcd, 1); +err: + return ret; +} + +static int lms501xx_power_off(struct lcd_info *lcd) +{ + int ret = 0; + + dev_info(&lcd->ld->dev, "%s\n", __func__); + + lcd->ldi_enable = 0; + + ret = lms501xx_ldi_disable(lcd); + + msleep(135); + + return ret; +} + +static int lms501xx_power(struct lcd_info *lcd, int power) +{ + int ret = 0; + + if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->power)) + ret = lms501xx_power_on(lcd); + else if (!POWER_IS_ON(power) && POWER_IS_ON(lcd->power)) + ret = lms501xx_power_off(lcd); + + if (!ret) + lcd->power = power; + + return ret; +} + +static int lms501xx_set_power(struct lcd_device *ld, int power) +{ + struct lcd_info *lcd = lcd_get_data(ld); + + if (power != FB_BLANK_UNBLANK && power != FB_BLANK_POWERDOWN && + power != FB_BLANK_NORMAL) { + dev_err(&lcd->ld->dev, "power value should be 0, 1 or 4.\n"); + return -EINVAL; + } + + return lms501xx_power(lcd, power); +} + +static int lms501xx_get_power(struct lcd_device *ld) +{ + struct lcd_info *lcd = lcd_get_data(ld); + + return lcd->power; +} + +static int lms501xx_check_fb(struct lcd_device *ld, struct fb_info *fb) +{ + struct s3cfb_window *win = fb->par; + struct lcd_info *lcd = lcd_get_data(ld); + + dev_info(&lcd->ld->dev, "%s, fb%d\n", __func__, win->id); + + return 0; +} + +static int lms501xx_set_brightness(struct backlight_device *bd) +{ + int ret = 0; + int brightness = bd->props.brightness; + struct lcd_info *lcd = bl_get_data(bd); + + if (brightness < MIN_BRIGHTNESS || + brightness > bd->props.max_brightness) { + dev_err(&bd->dev, "lcd brightness should be %d to %d. now %d\n", + MIN_BRIGHTNESS, MAX_BRIGHTNESS, brightness); + return -EINVAL; + } + + if (lcd->ldi_enable) { + ret = update_brightness(lcd, 0); + if (ret < 0) { + dev_err(lcd->dev, "err in %s\n", __func__); + return -EINVAL; + } + } + + return ret; +} + +static int lms501xx_get_brightness(struct backlight_device *bd) +{ + struct lcd_info *lcd = bl_get_data(bd); + + return candela_table[lcd->bl]; +} + +static struct lcd_ops lms501xx_lcd_ops = { + .set_power = lms501xx_set_power, + .get_power = lms501xx_get_power, + .check_fb = lms501xx_check_fb, +}; + +static const struct backlight_ops lms501xx_backlight_ops = { + .get_brightness = lms501xx_get_brightness, + .update_status = lms501xx_set_brightness, +}; + +static ssize_t power_reduce_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct lcd_info *lcd = dev_get_drvdata(dev); + char temp[3]; + + sprintf(temp, "%d\n", lcd->current_cabc); + strcpy(buf, temp); + + return strlen(buf); +} + +static ssize_t power_reduce_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + struct lcd_info *lcd = dev_get_drvdata(dev); + int value; + int rc; + + rc = strict_strtoul(buf, (unsigned int)0, (unsigned long *)&value); + if (rc < 0) + return rc; + else { + if (lcd->current_cabc != value) { + dev_info(dev, "%s - %d, %d\n", + __func__, lcd->current_cabc, value); + mutex_lock(&lcd->bl_lock); + lcd->current_cabc = value; + if (lcd->ldi_enable) + lms501xx_set_cabc(lcd); + mutex_unlock(&lcd->bl_lock); + } + } + return size; +} + +static DEVICE_ATTR(power_reduce, 0664, power_reduce_show, power_reduce_store); + +static ssize_t lcd_type_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + char temp[15]; + sprintf(temp, "SMD_LMS501KF06\n"); + strcat(buf, temp); + return strlen(buf); +} + +static DEVICE_ATTR(lcd_type, 0444, lcd_type_show, NULL); + +static ssize_t auto_brightness_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct lcd_info *lcd = dev_get_drvdata(dev); + char temp[3]; + + sprintf(temp, "%d\n", lcd->auto_brightness); + strcpy(buf, temp); + + return strlen(buf); +} + +static ssize_t auto_brightness_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + struct lcd_info *lcd = dev_get_drvdata(dev); + int value; + int rc; + + rc = strict_strtoul(buf, (unsigned int)0, (unsigned long *)&value); + if (rc < 0) + return rc; + else { + if (lcd->auto_brightness != value) { + dev_info(dev, "%s - %d, %d\n", + __func__, lcd->auto_brightness, value); + mutex_lock(&lcd->bl_lock); + lcd->auto_brightness = value; + mutex_unlock(&lcd->bl_lock); + if (lcd->ldi_enable) + update_brightness(lcd, 0); + } + } + return size; +} + +static DEVICE_ATTR(auto_brightness, 0644, + auto_brightness_show, auto_brightness_store); + +#ifdef CONFIG_HAS_EARLYSUSPEND +struct lcd_info *g_lcd; + +void lms501xx_early_suspend(void) +{ + struct lcd_info *lcd = g_lcd; + + set_dsim_lcd_enabled(0); + + dev_info(&lcd->ld->dev, "+%s\n", __func__); +#if defined(GPIO_OLED_DET) + disable_irq(lcd->irq); + gpio_request(GPIO_OLED_DET, "OLED_DET"); + s3c_gpio_cfgpin(GPIO_OLED_DET, S3C_GPIO_OUTPUT); + s3c_gpio_setpull(GPIO_OLED_DET, S3C_GPIO_PULL_NONE); + gpio_direction_output(GPIO_OLED_DET, GPIO_LEVEL_LOW); + gpio_free(GPIO_OLED_DET); +#endif + lms501xx_power(lcd, FB_BLANK_POWERDOWN); + dev_info(&lcd->ld->dev, "-%s\n", __func__); + + return ; +} + +void lms501xx_late_resume(void) +{ + struct lcd_info *lcd = g_lcd; + + dev_info(&lcd->ld->dev, "+%s\n", __func__); + lms501xx_power(lcd, FB_BLANK_UNBLANK); +#if defined(GPIO_OLED_DET) + s3c_gpio_cfgpin(GPIO_OLED_DET, S3C_GPIO_SFN(0xf)); + s3c_gpio_setpull(GPIO_OLED_DET, S3C_GPIO_PULL_NONE); + enable_irq(lcd->irq); +#endif + dev_info(&lcd->ld->dev, "-%s\n", __func__); + + set_dsim_lcd_enabled(1); + + return ; +} +#endif + +static void lms501xx_read_id(struct lcd_info *lcd, u8 *buf) +{ + int ret = 0; + + ret = lms501xx_read(lcd, LDI_ID_REG, LDI_ID_LEN, buf, 3); + if (!ret) { + lcd->connected = 0; + dev_info(&lcd->ld->dev, "panel is not connected well\n"); + } +} + +static int lms501xx_probe(struct device *dev) +{ + int ret = 0; + struct lcd_info *lcd; + + lcd = kzalloc(sizeof(struct lcd_info), GFP_KERNEL); + if (!lcd) { + pr_err("failed to allocate for lcd\n"); + ret = -ENOMEM; + goto err_alloc; + } + + g_lcd = lcd; + + lcd->ld = lcd_device_register("panel", dev, lcd, &lms501xx_lcd_ops); + if (IS_ERR(lcd->ld)) { + pr_err("failed to register lcd device\n"); + ret = PTR_ERR(lcd->ld); + goto out_free_lcd; + } + + lcd->bd = backlight_device_register("panel", + dev, lcd, &lms501xx_backlight_ops, NULL); + if (IS_ERR(lcd->bd)) { + pr_err("failed to register backlight device\n"); + ret = PTR_ERR(lcd->bd); + goto out_free_backlight; + } + + lcd->dev = dev; + lcd->dsim = (struct dsim_global *)dev_get_drvdata(dev->parent); + lcd->bd->props.max_brightness = MAX_BRIGHTNESS; + lcd->bd->props.brightness = DEFAULT_BRIGHTNESS; + lcd->bl = DEFAULT_GAMMA_LEVEL; + lcd->current_bl = lcd->bl; + lcd->current_cabc = 0; + + lcd->power = FB_BLANK_UNBLANK; + lcd->ldi_enable = 1; + lcd->connected = 1; + lcd->auto_brightness = 0; + + ret = device_create_file(&lcd->ld->dev, &dev_attr_power_reduce); + if (ret < 0) + dev_err(&lcd->ld->dev, + "failed to add sysfs entries, %d\n", __LINE__); + + ret = device_create_file(&lcd->ld->dev, &dev_attr_lcd_type); + if (ret < 0) + dev_err(&lcd->ld->dev, + "failed to add sysfs entries, %d\n", __LINE__); + + ret = device_create_file(&lcd->bd->dev, &dev_attr_auto_brightness); + if (ret < 0) + dev_err(&lcd->ld->dev, + "failed to add sysfs entries, %d\n", __LINE__); + + dev_set_drvdata(dev, lcd); + + mutex_init(&lcd->lock); + mutex_init(&lcd->bl_lock); + + dev_info(&lcd->ld->dev, "lms501xx lcd panel driver has been probed.\n"); + + update_brightness(lcd, 1); + +#if defined(GPIO_OLED_DET) + if (lcd->connected) { + INIT_DELAYED_WORK(&lcd->oled_detection, oled_detection_work); + + lcd->irq = gpio_to_irq(GPIO_OLED_DET); + + s3c_gpio_cfgpin(GPIO_OLED_DET, S3C_GPIO_SFN(0xf)); + s3c_gpio_setpull(GPIO_OLED_DET, S3C_GPIO_PULL_NONE); + if (request_irq(lcd->irq, oled_detection_int, + IRQF_TRIGGER_FALLING, "oled_detection", lcd)) + pr_err("failed to reqeust irq. %d\n", lcd->irq); + } +#endif + + lcd_early_suspend = lms501xx_early_suspend; + lcd_late_resume = lms501xx_late_resume; + + return 0; + +out_free_backlight: + lcd_device_unregister(lcd->ld); + kfree(lcd); + return ret; + +out_free_lcd: + kfree(lcd); + return ret; + +err_alloc: + return ret; +} + +static int __devexit lms501xx_remove(struct device *dev) +{ + struct lcd_info *lcd = dev_get_drvdata(dev); + + lms501xx_power(lcd, FB_BLANK_POWERDOWN); + lcd_device_unregister(lcd->ld); + backlight_device_unregister(lcd->bd); + kfree(lcd); + + return 0; +} + +/* Power down all displays on reboot, poweroff or halt. */ +static void lms501xx_shutdown(struct device *dev) +{ + struct lcd_info *lcd = dev_get_drvdata(dev); + + dev_info(&lcd->ld->dev, "%s\n", __func__); + + lms501xx_power(lcd, FB_BLANK_POWERDOWN); +} + +static struct mipi_lcd_driver lms501xx_mipi_driver = { + .name = "lms501xx", + .probe = lms501xx_probe, + .remove = __devexit_p(lms501xx_remove), + .shutdown = lms501xx_shutdown, +}; + +static int lms501xx_init(void) +{ + return s5p_dsim_register_lcd_driver(&lms501xx_mipi_driver); +} + +static void lms501xx_exit(void) +{ + return; +} + +module_init(lms501xx_init); +module_exit(lms501xx_exit); + +MODULE_DESCRIPTION("MIPI-DSI LMS501XX WVGA (480x800) Panel Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/samsung/s3cfb_main.c b/drivers/video/samsung/s3cfb_main.c index 2cb7c86..a723306 100644 --- a/drivers/video/samsung/s3cfb_main.c +++ b/drivers/video/samsung/s3cfb_main.c @@ -29,7 +29,7 @@ #include <linux/memory.h> #include <linux/pm_runtime.h> #include <linux/delay.h> -#include <linux/kthread.h> +#include <linux/sw_sync.h> #include <plat/clock.h> #include <plat/media.h> #include <mach/media.h> @@ -58,11 +58,13 @@ #include <mach/regs-pmu.h> #include <plat/regs-fb-s5p.h> -extern int s3cfb_vsync_timestamp_changed(struct s3cfb_global *fbdev, ktime_t prev_timestamp); +#ifdef CONFIG_FB_S5P_SYSMMU +#include <plat/s5p-sysmmu.h> +#endif struct s3cfb_fimd_desc *fbfimd; -inline struct s3cfb_global *get_fimd_global(int id) +struct s3cfb_global *get_fimd_global(int id) { struct s3cfb_global *fbdev; @@ -85,17 +87,57 @@ int s3cfb_vsync_status_check(void) return 0; } +#if defined(CONFIG_FB_S5P_VSYNC_THREAD) +static void s3cfb_activate_vsync(struct s3cfb_global *fbdev) +{ + int prev_refcount; + + mutex_lock(&fbdev->vsync_info.irq_lock); + prev_refcount = fbdev->vsync_info.irq_refcount++; + if (!prev_refcount) { + s3cfb_set_global_interrupt(fbdev, 1); + s3cfb_set_vsync_interrupt(fbdev, 1); + } + + mutex_unlock(&fbdev->vsync_info.irq_lock); +} + +static void s3cfb_deactivate_vsync(struct s3cfb_global *fbdev) +{ + int new_refcount; + + mutex_lock(&fbdev->vsync_info.irq_lock); + + new_refcount = --fbdev->vsync_info.irq_refcount; + WARN_ON(new_refcount < 0); + if (!new_refcount) { + s3cfb_set_global_interrupt(fbdev, 0); + s3cfb_set_vsync_interrupt(fbdev, 0); + } + + mutex_unlock(&fbdev->vsync_info.irq_lock); +} +#endif + static irqreturn_t s3cfb_irq_frame(int irq, void *dev_id) { struct s3cfb_global *fbdev[2]; fbdev[0] = fbfimd->fbdev[0]; + spin_lock(&fbdev[0]->vsync_slock); + if (fbdev[0]->regs != 0) s3cfb_clear_interrupt(fbdev[0]); +#if defined(CONFIG_FB_S5P_VSYNC_THREAD) + fbdev[0]->vsync_info.timestamp = ktime_get(); + wake_up_interruptible_all(&fbdev[0]->vsync_info.wait); +#endif + fbdev[0]->wq_count++; - fbdev[0]->vsync_timestamp = ktime_get(); - wake_up_interruptible(&fbdev[0]->wq); + wake_up(&fbdev[0]->wq); + + spin_unlock(&fbdev[0]->vsync_slock); return IRQ_HANDLED; } @@ -113,6 +155,57 @@ static irqreturn_t s3cfb_irq_fifo(int irq, void *dev_id) } #endif +#if defined(CONFIG_FB_S5P_VSYNC_THREAD) +int s3cfb_set_vsync_int(struct fb_info *info, bool active) +{ + struct s3cfb_global *fbdev = fbfimd->fbdev[0]; + bool prev_active = fbdev->vsync_info.active; + + fbdev->vsync_info.active = active; + + if (active && !prev_active) + s3cfb_activate_vsync(fbdev); + else if (!active && prev_active) + s3cfb_deactivate_vsync(fbdev); + + return 0; +} + +/** + * s3cfb_wait_for_vsync() - sleep until next VSYNC interrupt or timeout + * @sfb: main hardware state + * @timeout: timeout in msecs, or 0 to wait indefinitely. + */ +int s3cfb_wait_for_vsync(struct s3cfb_global *fbdev, u32 timeout) +{ + ktime_t timestamp; + int ret; + + pm_runtime_get_sync(fbdev->dev); + + timestamp = fbdev->vsync_info.timestamp; + s3cfb_activate_vsync(fbdev); + if (timeout) { + ret = wait_event_interruptible_timeout(fbdev->vsync_info.wait, + !ktime_equal(timestamp, + fbdev->vsync_info.timestamp), + msecs_to_jiffies(timeout)); + } else { + ret = wait_event_interruptible(fbdev->vsync_info.wait, + !ktime_equal(timestamp, + fbdev->vsync_info.timestamp)); + } + s3cfb_deactivate_vsync(fbdev); + + pm_runtime_put_sync(fbdev->dev); + + if (timeout && ret == 0) + return -ETIMEDOUT; + + return 0; +} +#endif + int s3cfb_register_framebuffer(struct s3cfb_global *fbdev) { struct s3c_platform_fb *pdata = to_fb_plat(fbdev->dev); @@ -322,30 +415,53 @@ void s3cfb_trigger(void) EXPORT_SYMBOL(s3cfb_trigger); #endif +#if defined(CONFIG_FB_S5P_VSYNC_THREAD) static int s3cfb_wait_for_vsync_thread(void *data) { - struct s3cfb_global *fbdev = data; - - while (!kthread_should_stop()) { - ktime_t prev_timestamp = fbdev->vsync_timestamp; - - int ret = wait_event_interruptible_timeout(fbdev->wq, - s3cfb_vsync_timestamp_changed(fbdev, prev_timestamp), - msecs_to_jiffies(100)); - - if (ret > 0) { - char *envp[2]; - char buf[64]; + struct s3cfb_global *fbdev = data; + + while (!kthread_should_stop()) { + ktime_t timestamp = fbdev->vsync_info.timestamp; + int ret = wait_event_interruptible_timeout( + fbdev->vsync_info.wait, + !ktime_equal(timestamp, + fbdev->vsync_info.timestamp) && + fbdev->vsync_info.active, + msecs_to_jiffies(VSYNC_TIMEOUT_MSEC)); + + if (ret > 0) { + char *envp[2]; + char buf[64]; + snprintf(buf, sizeof(buf), "VSYNC=%llu", + ktime_to_ns(fbdev->vsync_info.timestamp)); + envp[0] = buf; + envp[1] = NULL; + kobject_uevent_env(&fbdev->dev->kobj, KOBJ_CHANGE, + envp); + } + } - snprintf(buf, sizeof(buf), "VSYNC=%llu", - ktime_to_ns(fbdev->vsync_timestamp)); - envp[0] = buf; - envp[1] = NULL; - kobject_uevent_env(&fbdev->dev->kobj, KOBJ_CHANGE, envp); - } - } + return 0; +} +#endif - return 0; +static void s3c_fb_update_regs_handler(struct kthread_work *work) +{ + struct s3cfb_global *fbdev = + container_of(work, struct s3cfb_global, update_regs_work); + struct s3c_reg_data *data, *next; + struct list_head saved_list; + + mutex_lock(&fbdev->update_regs_list_lock); + saved_list = fbdev->update_regs_list; + list_replace_init(&fbdev->update_regs_list, &saved_list); + mutex_unlock(&fbdev->update_regs_list_lock); + + list_for_each_entry_safe(data, next, &saved_list, list) { + s3c_fb_update_regs(fbdev, data); + list_del(&data->list); + kfree(data); + } } static int s3cfb_probe(struct platform_device *pdev) @@ -362,7 +478,13 @@ static int s3cfb_probe(struct platform_device *pdev) /* enable the power domain */ pm_runtime_get_sync(&pdev->dev); #endif + fbfimd = kzalloc(sizeof(struct s3cfb_fimd_desc), GFP_KERNEL); + if (!fbfimd) { + printk(KERN_ERR "failed to allocate for fimd fb descriptor\n"); + ret = -ENOMEM; + goto err_fimd_desc; + } if (FIMD_MAX == 2) fbfimd->dual = 1; @@ -418,9 +540,30 @@ static int s3cfb_probe(struct platform_device *pdev) if (!fbdev[i]->regs) { dev_err(fbdev[i]->dev, "failed to remap io region\n"); ret = -EINVAL; - goto err1; + goto err_ioremap; } + spin_lock_init(&fbdev[i]->vsync_slock); + +#if defined(CONFIG_FB_S5P_VSYNC_THREAD) + INIT_LIST_HEAD(&fbdev[i]->update_regs_list); + mutex_init(&fbdev[i]->update_regs_list_lock); + init_kthread_worker(&fbdev[i]->update_regs_worker); + + fbdev[i]->update_regs_thread = kthread_run(kthread_worker_fn, + &fbdev[i]->update_regs_worker, "s3c-fb"); + if (IS_ERR(fbdev[i]->update_regs_thread)) { + int err = PTR_ERR(fbdev[i]->update_regs_thread); + fbdev[i]->update_regs_thread = NULL; + + dev_err(fbdev[i]->dev, "failed to run update_regs thread\n"); + return err; + } + init_kthread_work(&fbdev[i]->update_regs_work, s3c_fb_update_regs_handler); + fbdev[i]->timeline = sw_sync_timeline_create("s3c-fb"); + fbdev[i]->timeline_max = 0; +#endif + /* irq */ fbdev[i]->irq = platform_get_irq(pdev, 0); if (request_irq(fbdev[i]->irq, s3cfb_irq_frame, IRQF_SHARED, @@ -463,7 +606,7 @@ static int s3cfb_probe(struct platform_device *pdev) /* register fb_info */ if (s3cfb_register_framebuffer(fbdev[i])) { dev_err(fbdev[i]->dev, "register error fimd[%d]\n", i); - return -EINVAL; + ret = -EINVAL; goto err3; } @@ -506,6 +649,20 @@ static int s3cfb_probe(struct platform_device *pdev) register_early_suspend(&fbdev[i]->early_suspend); #endif #endif +#if defined(CONFIG_FB_S5P_VSYNC_THREAD) + init_waitqueue_head(&fbdev[i]->vsync_info.wait); + + /* Create vsync thread */ + mutex_init(&fbdev[i]->vsync_info.irq_lock); + + fbdev[i]->vsync_info.thread = kthread_run( + s3cfb_wait_for_vsync_thread, + fbdev[i], "s3c-fb-vsync"); + if (fbdev[i]->vsync_info.thread == ERR_PTR(-ENOMEM)) { + dev_err(fbdev[i]->dev, "failed to run vsync thread\n"); + fbdev[i]->vsync_info.thread = NULL; + } +#endif ret = device_create_file(fbdev[i]->dev, &dev_attr_fimd_dump); if (ret < 0) dev_err(fbdev[0]->dev, "failed to add sysfs entries\n"); @@ -524,12 +681,6 @@ static int s3cfb_probe(struct platform_device *pdev) pdata->lcd_on(pdev); #endif - fbdev[0]->vsync_thread = kthread_run(s3cfb_wait_for_vsync_thread, fbdev[0], "s3cfb-vsync"); - if (fbdev[0]->vsync_thread == ERR_PTR(-ENOMEM)) { - dev_err(fbdev[0]->dev, "failed to run vsync thread\n"); - fbdev[0]->vsync_thread = NULL; - } - ret = device_create_file(&(pdev->dev), &dev_attr_win_power); if (ret < 0) dev_err(fbdev[0]->dev, "failed to add sysfs entries\n"); @@ -557,10 +708,18 @@ err3: err2: for (i = 0; i < FIMD_MAX; i++) iounmap(fbdev[i]->regs); + +err_ioremap: + release_mem_region(res->start, res->end - res->start + 1); + err1: - for (i = 0; i < FIMD_MAX; i++) + for (i = 0; i < FIMD_MAX; i++) { pdata->clk_off(pdev, &fbdev[i]->clock); + kfree(fbfimd->fbdev[i]); + } err0: + kfree(fbfimd); +err_fimd_desc: return ret; } @@ -600,9 +759,10 @@ static int s3cfb_remove(struct platform_device *pdev) framebuffer_release(fb); } } - - if (fbdev[i]->vsync_thread) - kthread_stop(fbdev[i]->vsync_thread); +#if defined(CONFIG_FB_S5P_VSYNC_THREAD) + if (fbdev[i]->vsync_info.thread) + kthread_stop(fbdev[i]->vsync_info.thread); +#endif kfree(fbdev[i]->fb); kfree(fbdev[i]); @@ -694,6 +854,9 @@ void s3cfb_lcd0_pmu_off(void) #ifdef CONFIG_PM #ifdef CONFIG_HAS_EARLYSUSPEND +void (*lcd_early_suspend)(void); +void (*lcd_late_resume)(void); + void s3cfb_early_suspend(struct early_suspend *h) { struct s3cfb_global *info = container_of(h, struct s3cfb_global, early_suspend); @@ -705,11 +868,8 @@ void s3cfb_early_suspend(struct early_suspend *h) printk(KERN_INFO "+%s\n", __func__); #ifdef CONFIG_FB_S5P_MIPI_DSIM -#if defined(CONFIG_FB_S5P_S6E63M0) - s6e63m0_early_suspend(); -#else - s6e8ax0_early_suspend(); -#endif + if (lcd_early_suspend) + lcd_early_suspend(); #endif for (i = 0; i < FIMD_MAX; i++) { @@ -765,8 +925,15 @@ void s3cfb_early_suspend(struct early_suspend *h) pm_runtime_put_sync(&pdev->dev); #endif - printk(KERN_INFO "-%s\n", __func__); +#ifdef CONFIG_FB_S5P_SYSMMU + if (fbdev[0]->sysmmu.enabled == true) { + fbdev[0]->sysmmu.enabled = false; + fbdev[0]->sysmmu.pgd = 0; + s5p_sysmmu_disable(fbdev[0]->dev); + } +#endif + printk(KERN_INFO "-%s\n", __func__); return ; } @@ -780,28 +947,18 @@ void s3cfb_late_resume(struct early_suspend *h) int i, j; struct platform_device *pdev = to_platform_device(info->dev); - printk(KERN_INFO "+%s\n", __func__); + dev_info(info->dev, "+%s\n", __func__); dev_dbg(info->dev, "wake up from suspend\n"); #ifdef CONFIG_EXYNOS_DEV_PD /* enable the power domain */ - printk(KERN_DEBUG "s3cfb - enable power domain\n"); + dev_dbg(info->dev, "s3cfb - enable power domain\n"); pm_runtime_get_sync(&pdev->dev); #endif #ifdef CONFIG_FB_S5P_MIPI_DSIM s5p_dsim_late_resume(); - - if (s5p_dsim_fifo_clear() == 0) { - s5p_dsim_early_suspend(); - usleep_range(10000, 10000); - s5p_dsim_late_resume(); - if (s5p_dsim_fifo_clear() == 0) - pr_info("dsim resume fail!!!\n"); - } - - usleep_range(10000, 10000); #endif #if defined(CONFIG_FB_S5P_DUMMYLCD) @@ -819,6 +976,10 @@ void s3cfb_late_resume(struct early_suspend *h) /* fbdev[i]->regs_org should be non-zero value */ BUG(); +#if defined(CONFIG_FB_MDNIE_PWM) + set_mdnie_pwm_value(g_mdnie, 0); +#endif + if (pdata->set_display_path) pdata->set_display_path(); @@ -848,6 +1009,9 @@ void s3cfb_late_resume(struct early_suspend *h) /* Set alpha value width to 8-bit */ s3cfb_set_alpha_value_width(fbdev[i], i); +#if defined(CONFIG_FB_RGBA_ORDER) + s3cfb_set_output(fbdev[i]); +#else for (j = 0; j < pdata->nr_wins; j++) { fb = fbdev[i]->fb[j]; win = fb->par; @@ -857,6 +1021,7 @@ void s3cfb_late_resume(struct early_suspend *h) s3cfb_enable_window(fbdev[i], win->id); } } +#endif if (pdata->cfg_gpio) pdata->cfg_gpio(pdev); @@ -869,17 +1034,23 @@ void s3cfb_late_resume(struct early_suspend *h) if (pdata->backlight_on) pdata->backlight_on(pdev); + +#if defined(CONFIG_FB_S5P_VSYNC_THREAD) + mutex_lock(&fbdev[i]->vsync_info.irq_lock); + if (fbdev[i]->vsync_info.irq_refcount) { + s3cfb_set_global_interrupt(fbdev[i], 1); + s3cfb_set_vsync_interrupt(fbdev[i], 1); + } + mutex_unlock(&fbdev[i]->vsync_info.irq_lock); +#endif } #ifdef CONFIG_FB_S5P_MIPI_DSIM -#if defined(CONFIG_FB_S5P_S6E63M0) - s6e63m0_late_resume(); -#else - s6e8ax0_late_resume(); -#endif + if (lcd_late_resume) + lcd_late_resume(); #endif - printk(KERN_INFO "-%s\n", __func__); + dev_info(info->dev, "-%s\n", __func__); return; } diff --git a/drivers/video/samsung/s3cfb_mdnie.c b/drivers/video/samsung/s3cfb_mdnie.c index 0fa2f60..a578dac 100644 --- a/drivers/video/samsung/s3cfb_mdnie.c +++ b/drivers/video/samsung/s3cfb_mdnie.c @@ -188,7 +188,7 @@ int s3c_mdnie_hw_init(void) return -ENOENT; } - printk(KERN_INFO "%s : 0x%p\n", __func__, s3c_mdnie_base); + /* printk(KERN_INFO "%s : 0x%p\n", __func__, s3c_mdnie_base); */ return 0; } diff --git a/drivers/video/samsung/s3cfb_ops.c b/drivers/video/samsung/s3cfb_ops.c index 82ece16..759fb63 100644 --- a/drivers/video/samsung/s3cfb_ops.c +++ b/drivers/video/samsung/s3cfb_ops.c @@ -15,6 +15,12 @@ #include <linux/platform_device.h> #include <linux/pm_runtime.h> +#include <linux/file.h> +#include <linux/fs.h> +#include <linux/sw_sync.h> +#include <plat/regs-fb.h> +#include <plat/regs-fb-s5p.h> + #if defined(CONFIG_CMA) #include <linux/cma.h> #elif defined(CONFIG_S5P_MEM_BOOTMEM) @@ -43,6 +49,10 @@ #include <mach/dev.h> #endif +#ifdef CONFIG_FB_S5P_SYSMMU +#include <plat/s5p-sysmmu.h> +#endif + struct s3c_platform_fb *to_fb_plat(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); @@ -183,7 +193,10 @@ int s3cfb_enable_window(struct s3cfb_global *fbdev, int id) #endif #if defined(CONFIG_CPU_EXYNOS4212) || defined(CONFIG_CPU_EXYNOS4412) #ifdef CONFIG_BUSFREQ_OPP - if (id != CONFIG_FB_S5P_DEFAULT_WINDOW) + if (CONFIG_FB_S5P_DEFAULT_WINDOW == 3 && + id == CONFIG_FB_S5P_DEFAULT_WINDOW-1) + dev_lock(fbdev->bus_dev, fbdev->dev, 267160); + else if (id != CONFIG_FB_S5P_DEFAULT_WINDOW) dev_lock(fbdev->bus_dev, fbdev->dev, 133133); #endif #endif @@ -394,6 +407,10 @@ int s3cfb_map_default_video_memory(struct s3cfb_global *fbdev, memset(fb->screen_base, 0, fix->smem_len); win->owner = DMA_MEM_FIMD; +#ifdef CONFIG_FB_S5P_SYSMMU + fbdev->sysmmu.default_fb_addr = fix->smem_start; +#endif + return 0; } @@ -457,11 +474,19 @@ int s3cfb_set_bitfield(struct fb_var_screeninfo *var) break; case 32: +#if defined(CONFIG_FB_RGBA_ORDER) + var->red.offset = 0; +#else var->red.offset = 16; +#endif var->red.length = 8; var->green.offset = 8; var->green.length = 8; +#if defined(CONFIG_FB_RGBA_ORDER) + var->blue.offset = 16; +#else var->blue.offset = 0; +#endif var->blue.length = 8; var->transp.offset = 24; var->transp.length = 8; /* added for LCD RGB32 */ @@ -1082,30 +1107,631 @@ int s3cfb_cursor(struct fb_info *fb, struct fb_cursor *cursor) return 0; } -int s3cfb_vsync_timestamp_changed(struct s3cfb_global *fbdev, ktime_t prev_timestamp) +#if !defined(CONFIG_FB_S5P_VSYNC_THREAD) +int s3cfb_wait_for_vsync(struct s3cfb_global *fbdev) { - return !ktime_equal(prev_timestamp, fbdev->vsync_timestamp); + dev_dbg(fbdev->dev, "waiting for VSYNC interrupt\n"); + + sleep_on_timeout(&fbdev->wq, HZ / 10); + + dev_dbg(fbdev->dev, "got a VSYNC interrupt\n"); + + return 0; } +#endif -int s3cfb_wait_for_vsync(struct s3cfb_global *fbdev) + +/** + * s3c_fb_align_word() - align pixel count to word boundary + * @bpp: The number of bits per pixel + * @pix: The value to be aligned. + * + * Align the given pixel count so that it will start on an 32bit word + * boundary. + */ +static int s3c_fb_align_word(unsigned int bpp, unsigned int pix) +{ + int pix_per_word; + + if (bpp > 16) + return pix; + + pix_per_word = (8 * 32) / bpp; + return ALIGN(pix, pix_per_word); +} + +static u32 s3c_fb_red_length(int format) +{ + switch (format) { + case S3C_FB_PIXEL_FORMAT_RGBA_8888: + case S3C_FB_PIXEL_FORMAT_RGBX_8888: + case S3C_FB_PIXEL_FORMAT_RGB_888: + case S3C_FB_PIXEL_FORMAT_BGRA_8888: + return 8; + + case S3C_FB_PIXEL_FORMAT_RGB_565: + case S3C_FB_PIXEL_FORMAT_RGBA_5551: + return 5; + + case S3C_FB_PIXEL_FORMAT_RGBA_4444: + return 4; + + default: + pr_warn("s3c-fb: unrecognized pixel format %u\n", format); + return 0; + } +} + +static u32 s3c_fb_red_offset(int format) +{ + switch (format) { + case S3C_FB_PIXEL_FORMAT_RGBA_8888: + case S3C_FB_PIXEL_FORMAT_RGBX_8888: + case S3C_FB_PIXEL_FORMAT_RGB_888: + case S3C_FB_PIXEL_FORMAT_RGB_565: + case S3C_FB_PIXEL_FORMAT_RGBA_5551: + case S3C_FB_PIXEL_FORMAT_RGBA_4444: + return 0; + + case S3C_FB_PIXEL_FORMAT_BGRA_8888: + return 16; + + default: + pr_warn("s3c-fb: unrecognized pixel format %u\n", format); + return 0; + } +} + +static u32 s3c_fb_green_length(int format) +{ + if (format == S3C_FB_PIXEL_FORMAT_RGB_565) + return 6; + + return s3c_fb_red_length(format); +} + +static u32 s3c_fb_green_offset(int format) +{ + switch (format) { + case S3C_FB_PIXEL_FORMAT_RGBA_8888: + case S3C_FB_PIXEL_FORMAT_RGB_888: + case S3C_FB_PIXEL_FORMAT_BGRA_8888: + case S3C_FB_PIXEL_FORMAT_RGBX_8888: + return 8; + + case S3C_FB_PIXEL_FORMAT_RGB_565: + case S3C_FB_PIXEL_FORMAT_RGBA_5551: + return 5; + + case S3C_FB_PIXEL_FORMAT_RGBA_4444: + return 4; + + default: + pr_warn("s3c-fb: unrecognized pixel format %u\n", format); + return 0; + } +} + +static u32 s3c_fb_blue_length(int format) +{ + return s3c_fb_red_length(format); +} + +static u32 s3c_fb_blue_offset(int format) +{ + switch (format) { + case S3C_FB_PIXEL_FORMAT_RGBA_8888: + case S3C_FB_PIXEL_FORMAT_RGB_888: + case S3C_FB_PIXEL_FORMAT_RGBX_8888: + return 16; + + case S3C_FB_PIXEL_FORMAT_RGB_565: + return 11; + + case S3C_FB_PIXEL_FORMAT_RGBA_5551: + return 10; + + case S3C_FB_PIXEL_FORMAT_RGBA_4444: + return 8; + + case S3C_FB_PIXEL_FORMAT_BGRA_8888: + return 0; + + default: + pr_warn("s3c-fb: unrecognized pixel format %u\n", format); + return 0; + } +} + +static u32 s3c_fb_transp_length(int format) +{ + switch (format) { + case S3C_FB_PIXEL_FORMAT_RGBA_8888: + case S3C_FB_PIXEL_FORMAT_BGRA_8888: + return 8; + + case S3C_FB_PIXEL_FORMAT_RGBA_5551: + return 1; + + case S3C_FB_PIXEL_FORMAT_RGBA_4444: + return 4; + + case S3C_FB_PIXEL_FORMAT_RGB_888: + case S3C_FB_PIXEL_FORMAT_RGB_565: + case S3C_FB_PIXEL_FORMAT_RGBX_8888: + return 0; + + default: + pr_warn("s3c-fb: unrecognized pixel format %u\n", format); + return 0; + } +} + +static u32 s3c_fb_transp_offset(int format) +{ + switch (format) { + case S3C_FB_PIXEL_FORMAT_RGBA_8888: + case S3C_FB_PIXEL_FORMAT_BGRA_8888: + return 24; + + case S3C_FB_PIXEL_FORMAT_RGBA_5551: + return 15; + + case S3C_FB_PIXEL_FORMAT_RGBA_4444: + return 12; + + case S3C_FB_PIXEL_FORMAT_RGB_888: + case S3C_FB_PIXEL_FORMAT_RGB_565: + case S3C_FB_PIXEL_FORMAT_RGBX_8888: + return s3c_fb_blue_offset(format); + + default: + pr_warn("s3c-fb: unrecognized pixel format %u\n", format); + return 0; + } +} + +static u32 s3c_fb_padding(int format) +{ + switch (format) { + case S3C_FB_PIXEL_FORMAT_RGBX_8888: + return 8; + + case S3C_FB_PIXEL_FORMAT_RGB_565: + case S3C_FB_PIXEL_FORMAT_RGBA_8888: + case S3C_FB_PIXEL_FORMAT_RGBA_5551: + case S3C_FB_PIXEL_FORMAT_RGBA_4444: + return 0; + + default: + pr_warn("s3c-fb: unrecognized pixel format %u\n", format); + return 0; + } + +} + +static inline u32 fb_visual(u32 bits_per_pixel, unsigned short palette_sz) +{ + switch (bits_per_pixel) { + case 32: + case 24: + case 16: + case 12: + return FB_VISUAL_TRUECOLOR; + case 8: + if (palette_sz >= 256) + return FB_VISUAL_PSEUDOCOLOR; + else + return FB_VISUAL_TRUECOLOR; + case 1: + return FB_VISUAL_MONO01; + default: + return FB_VISUAL_PSEUDOCOLOR; + } +} + + +static inline u32 fb_linelength(u32 xres_virtual, u32 bits_per_pixel) +{ + return (xres_virtual * bits_per_pixel) / 8; +} + +static inline u16 fb_panstep(u32 res, u32 res_virtual) +{ + return res_virtual > res ? 1 : 0; +} + +static inline u32 vidw_buf_size(u32 xres, u32 line_length, u32 bits_per_pixel) +{ + u32 pagewidth = (xres * bits_per_pixel) >> 3; + return VIDW_BUF_SIZE_OFFSET(line_length - pagewidth) | + VIDW_BUF_SIZE_PAGEWIDTH(pagewidth) | + VIDW_BUF_SIZE_OFFSET_E(line_length - pagewidth) | + VIDW_BUF_SIZE_PAGEWIDTH_E(pagewidth); +} + +inline u32 vidosd_a(int x, int y) +{ + return VIDOSDxA_TOPLEFT_X(x) | + VIDOSDxA_TOPLEFT_Y(y) | + VIDOSDxA_TOPLEFT_X_E(x) | + VIDOSDxA_TOPLEFT_Y_E(y); +} + +inline u32 vidosd_b(int x, int y, u32 xres, u32 yres, u32 bits_per_pixel) +{ + return VIDOSDxB_BOTRIGHT_X(s3c_fb_align_word(bits_per_pixel, + x + xres - 1)) | + VIDOSDxB_BOTRIGHT_Y(y + yres - 1) | + VIDOSDxB_BOTRIGHT_X_E(s3c_fb_align_word(bits_per_pixel, + x + xres - 1)) | + VIDOSDxB_BOTRIGHT_Y_E(y + yres - 1); +} + +static inline u32 wincon(u32 bits_per_pixel, u32 transp_length, u32 red_length) +{ + u32 data = 0; + + switch (bits_per_pixel) { + case 1: + data |= WINCON0_BPPMODE_1BPP; + data |= WINCONx_BITSWP; + data |= WINCONx_BURSTLEN_4WORD; + break; + case 2: + data |= WINCON0_BPPMODE_2BPP; + data |= WINCONx_BITSWP; + data |= WINCONx_BURSTLEN_8WORD; + break; + case 4: + data |= WINCON0_BPPMODE_4BPP; + data |= WINCONx_BITSWP; + data |= WINCONx_BURSTLEN_8WORD; + break; + case 8: + if (transp_length != 0) + data |= WINCON1_BPPMODE_8BPP_1232; + else + data |= WINCON0_BPPMODE_8BPP_PALETTE; + data |= WINCONx_BURSTLEN_8WORD; + data |= WINCONx_BYTSWP; + break; + case 16: + if (transp_length != 0) + data |= WINCON1_BPPMODE_16BPP_A1555; + else + data |= WINCON0_BPPMODE_16BPP_565; + data |= WINCONx_HAWSWP; + data |= WINCONx_BURSTLEN_16WORD; + break; + case 24: + case 32: + if (red_length == 6) { + if (transp_length != 0) + data |= WINCON1_BPPMODE_19BPP_A1666; + else + data |= WINCON1_BPPMODE_18BPP_666; + } else if (transp_length == 1) + data |= WINCON1_BPPMODE_25BPP_A1888 + | WINCON1_BLD_PIX; + else if ((transp_length == 4) || + (transp_length == 8)) + data |= WINCON1_BPPMODE_28BPP_A4888 + | WINCON1_BLD_PIX | WINCON1_ALPHA_SEL; + else + data |= WINCON0_BPPMODE_24BPP_888; + + data |= WINCONx_WSWP; + data |= WINCONx_BURSTLEN_16WORD; + break; + } + + return data; +} + +void s3c_fb_update_regs(struct s3cfb_global *fbdev, struct s3c_reg_data *regs) { - ktime_t prev_timestamp; + struct s3c_platform_fb *pdata = to_fb_plat(fbdev->dev); + unsigned short i; + bool wait_for_vsync; + struct s3cfb_window *win; + +#if defined(CONFIG_CPU_EXYNOS4212) || defined(CONFIG_CPU_EXYNOS4412) +#ifdef CONFIG_BUSFREQ_OPP + unsigned int new_num_of_win = 0; + unsigned int pre_num_of_win = 0; + unsigned int shadow_regs = 0; + unsigned int clkval = 0; + + for (i = 0; i < pdata->nr_wins; i++) + if (regs->shadowcon & SHADOWCON_CHx_ENABLE(i)) + new_num_of_win++; + shadow_regs = readl(fbdev->regs + S3C_WINSHMAP); + for (i = 0; i < pdata->nr_wins; i++) + if (shadow_regs & SHADOWCON_CHx_ENABLE(i)) + pre_num_of_win++; + + if (pre_num_of_win < new_num_of_win) { + switch(new_num_of_win) { + case 0: + case 1: + clkval = 100100; + break; + case 2: + clkval = 133133; + break; + case 3: + clkval = 133133; + break; + case 4: + clkval = 133133; + break; + case 5: + clkval = 133133; + break; + } + dev_lock(fbdev->bus_dev, fbdev->dev, clkval); + } +#endif +#endif + + for (i = 0; i < pdata->nr_wins; i++) + s3cfb_set_window_protect(fbdev, i, 1); + + for (i = 0; i < pdata->nr_wins; i++) { + win = fbdev->fb[i]->par; + writel(regs->wincon[i], fbdev->regs + S3C_WINCON(i)); + writel(regs->vidosd_a[i], fbdev->regs + S3C_VIDOSD_A(i)); + writel(regs->vidosd_b[i], fbdev->regs + S3C_VIDOSD_B(i)); + writel(regs->vidosd_c[i], fbdev->regs + S3C_VIDOSD_C(i)); + if (i == 1 || i == 2) + writel(regs->vidosd_d[i], fbdev->regs + S3C_VIDOSD_D(i)); + writel(regs->vidw_buf_start[i], + fbdev->regs + S3C_VIDADDR_START0(i)); + writel(regs->vidw_buf_end[i], + fbdev->regs + S3C_VIDADDR_END0(i)); + writel(regs->vidw_buf_size[i], + fbdev->regs + S3C_VIDADDR_SIZE(i)); + + win->enabled = !!(regs->wincon[i] & WINCONx_ENWIN); + } + + writel(regs->shadowcon, fbdev->regs + S3C_WINSHMAP); + + for (i = 0; i < pdata->nr_wins; i++) + s3cfb_set_window_protect(fbdev, i, 0); + + do { +#if defined(CONFIG_FB_S5P_VSYNC_THREAD) + s3cfb_wait_for_vsync(fbdev, 0); +#else + s3cfb_wait_for_vsync(fbdev); +#endif + wait_for_vsync = false; + + for (i = 0; i < pdata->nr_wins; i++) { + u32 new_start = regs->vidw_buf_start[i]; + u32 shadow_start = s3cfb_get_win_cur_buf_addr(fbdev, i); + if (unlikely(new_start != shadow_start)) { + wait_for_vsync = true; + break; + } + } + } while (wait_for_vsync); + + sw_sync_timeline_inc(fbdev->timeline, 1); + +#ifdef CONFIG_FB_S5P_SYSMMU + if ((fbdev->sysmmu.enabled == false) && + (fbdev->sysmmu.pgd)) { + fbdev->sysmmu.enabled = true; + s5p_sysmmu_enable(fbdev->dev, + (unsigned long)virt_to_phys((unsigned int*)fbdev->sysmmu.pgd)); + } +#endif + +#if defined(CONFIG_CPU_EXYNOS4212) || defined(CONFIG_CPU_EXYNOS4412) +#ifdef CONFIG_BUSFREQ_OPP + if (pre_num_of_win > new_num_of_win) { + switch(new_num_of_win) { + case 0: + case 1: + clkval = 100100; + break; + case 2: + clkval = 133133; + break; + case 3: + clkval = 133133; + break; + case 4: + clkval = 133133; + break; + case 5: + clkval = 133133; + break; + } + dev_lock(fbdev->bus_dev, fbdev->dev, clkval); + } +#endif +#endif +} + +static int s3c_fb_set_win_buffer(struct s3cfb_global *fbdev, + struct fb_info *fb, struct s3c_fb_win_config *win_config, + struct s3c_reg_data *regs) +{ + struct s3cfb_window *win = fb->par; + struct fb_fix_screeninfo prev_fix = fb->fix; + struct fb_var_screeninfo prev_var = fb->var; + unsigned short win_no = win->id; int ret; + size_t window_size; + u32 alpha, size; - dev_dbg(fbdev->dev, "waiting for VSYNC interrupt\n"); + if (win_config->format >= S3C_FB_PIXEL_FORMAT_MAX) { + dev_err(fbdev->dev, "unknown pixel format %u\n", + win_config->format); + return -EINVAL; + } - prev_timestamp = fbdev->vsync_timestamp; + fb->var.red.length = s3c_fb_red_length(win_config->format); + fb->var.red.offset = s3c_fb_red_offset(win_config->format); + fb->var.green.length = s3c_fb_green_length(win_config->format); + fb->var.green.offset = s3c_fb_green_offset(win_config->format); + fb->var.blue.length = s3c_fb_blue_length(win_config->format); + fb->var.blue.offset = s3c_fb_blue_offset(win_config->format); + fb->var.transp.length = s3c_fb_transp_length(win_config->format); + fb->var.transp.offset = s3c_fb_transp_offset(win_config->format); + fb->var.bits_per_pixel = fb->var.red.length + + fb->var.green.length + + fb->var.blue.length + + fb->var.transp.length + + s3c_fb_padding(win_config->format); + + window_size = win_config->stride * win_config->h; + + if (win_config->phys_addr != 0) + fb->fix.smem_start = win_config->phys_addr + win_config->offset; + else + fb->fix.smem_start = win_config->virt_addr + win_config->offset; + fb->fix.smem_len = window_size; + fb->var.xres = win_config->w; + fb->var.xres_virtual = win_config->stride * 8 / + fb->var.bits_per_pixel; + fb->var.yres = fb->var.yres_virtual = win_config->h; + fb->var.xoffset = win_config->offset % win_config->stride; + fb->var.yoffset = win_config->offset / win_config->stride; + + fb->fix.visual = fb_visual(fb->var.bits_per_pixel, 256); + fb->fix.line_length = win_config->stride; + fb->fix.xpanstep = fb_panstep(win_config->w, + fb->var.xres_virtual); + fb->fix.ypanstep = fb_panstep(win_config->h, win_config->h); + +#ifdef CONFIG_FB_S5P_SYSMMU + if ((fbdev->sysmmu.enabled == false) && + (current->mm)) + fbdev->sysmmu.pgd = (unsigned int)current->mm->pgd; +#endif - ret = wait_event_interruptible_timeout(fbdev->wq, - s3cfb_vsync_timestamp_changed(fbdev, prev_timestamp), - msecs_to_jiffies(100)); +#ifdef CONFIG_FB_S5P_SYSMMU + if (win_config->phys_addr != 0) + regs->vidw_buf_start[win_no] = (u32)phys_to_virt(fb->fix.smem_start); + else +#endif + regs->vidw_buf_start[win_no] = fb->fix.smem_start; - if (ret == 0) - return -ETIMEDOUT; - if (ret < 0) - return ret; + regs->vidw_buf_end[win_no] = regs->vidw_buf_start[win_no] + + window_size; - dev_dbg(fbdev->dev, "got a VSYNC interrupt\n"); + regs->vidw_buf_size[win_no] = vidw_buf_size(win_config->w, + fb->fix.line_length, + fb->var.bits_per_pixel); + +#ifdef CONFIG_FB_S5P_SYSMMU + if ((fb->fix.smem_start) && + (fb->fix.smem_start != fbdev->sysmmu.default_fb_addr)) + s3cfb_clean_outer_pagetable(regs->vidw_buf_start[win_no], + regs->vidw_buf_end[win_no] - regs->vidw_buf_start[win_no]); +#endif + + + regs->vidosd_a[win_no] = vidosd_a(win_config->x, win_config->y); + regs->vidosd_b[win_no] = vidosd_b(win_config->x, win_config->y, + win_config->w, win_config->h, + fb->var.bits_per_pixel); + + alpha = VIDISD14C_ALPHA1_R(0xf) | + VIDISD14C_ALPHA1_G(0xf) | + VIDISD14C_ALPHA1_B(0xf); + regs->vidosd_c[win_no] = alpha; + + if (win_no <= 2) { + size = win_config->w * win_config->h; + regs->vidosd_d[win_no] = size; + } + + regs->shadowcon |= SHADOWCON_CHx_ENABLE(win_no); + + regs->wincon[win_no] = wincon(fb->var.bits_per_pixel, + fb->var.transp.length, + fb->var.red.length); + + return 0; +} + +static int s3c_fb_set_win_config(struct s3cfb_global *fbdev, + struct s3c_fb_win_config_data *win_data) +{ + struct fb_info *fb; + struct s3c_platform_fb *pdata = to_fb_plat(fbdev->dev); + struct s3c_fb_win_config *win_config = win_data->config; + int ret = 0; + unsigned short i; + struct s3c_reg_data *regs = kzalloc(sizeof(struct s3c_reg_data), + GFP_KERNEL); + struct sync_fence *fence; + struct sync_pt *pt; + int fd; + + if (!regs) { + dev_err(fbdev->dev, "could not allocate s3c_reg_data"); + return -ENOMEM; + } + + fd = get_unused_fd(); + + for (i = 0; i < pdata->nr_wins && !ret; i++) { + struct s3c_fb_win_config *config = &win_config[i]; + bool enabled = 0; + u32 color_map = WINxMAP_MAP | WINxMAP_MAP_COLOUR(0); + + fb = fbdev->fb[i]; + + switch (config->state) { + case S3C_FB_WIN_STATE_DISABLED: + break; + case S3C_FB_WIN_STATE_COLOR: + enabled = 1; + color_map |= WINxMAP_MAP_COLOUR(config->color); + break; + case S3C_FB_WIN_STATE_BUFFER: + ret = s3c_fb_set_win_buffer(fbdev, fb, config, regs); + if (!ret) { + enabled = 1; + color_map = 0; + } + break; + default: + dev_warn(fbdev->dev, "unrecognized window state %u", + config->state); + ret = -EINVAL; + break; + } + + if (enabled) + regs->wincon[i] |= WINCONx_ENWIN; + else + regs->wincon[i] &= ~WINCONx_ENWIN; + regs->winmap[i] = color_map; + } + + if (ret) { + put_unused_fd(fd); + kfree(regs); + } else { + mutex_lock(&fbdev->update_regs_list_lock); + fbdev->timeline_max++; + pt = sw_sync_pt_create(fbdev->timeline, fbdev->timeline_max); + fence = sync_fence_create("display", pt); + sync_fence_install(fence, fd); + win_data->fence = fd; + + list_add_tail(®s->list, &fbdev->update_regs_list); + mutex_unlock(&fbdev->update_regs_list_lock); + queue_kthread_work(&fbdev->update_regs_worker, &fbdev->update_regs_work); + } return ret; } @@ -1128,6 +1754,7 @@ int s3cfb_ioctl(struct fb_info *fb, unsigned int cmd, unsigned long arg) struct s3cfb_user_window user_window; struct s3cfb_user_plane_alpha user_alpha; struct s3cfb_user_chroma user_chroma; + struct s3c_fb_win_config_data win_data; int vsync; unsigned int alpha_mode; } p; @@ -1149,23 +1776,31 @@ int s3cfb_ioctl(struct fb_info *fb, unsigned int cmd, unsigned long arg) if (fbdev->regs == 0) return 0; #if defined(CONFIG_CPU_EXYNOS4212) || defined(CONFIG_CPU_EXYNOS4412) - /* Enable Vsync */ #ifdef CONFIG_CPU_EXYNOS4412 if (!fbdev->regs) return ret; #endif +#if !defined(CONFIG_FB_S5P_VSYNC_THREAD) + /* Enable Vsync */ s3cfb_set_global_interrupt(fbdev, 1); s3cfb_set_vsync_interrupt(fbdev, 1); #endif +#endif /* Wait for Vsync */ +#if defined(CONFIG_FB_S5P_VSYNC_THREAD) + s3cfb_wait_for_vsync(fbdev, HZ/10); +#else s3cfb_wait_for_vsync(fbdev); +#endif if (fbdev->regs == 0) return 0; #if defined(CONFIG_CPU_EXYNOS4212) || defined(CONFIG_CPU_EXYNOS4412) +#if !defined(CONFIG_FB_S5P_VSYNC_THREAD) /* Disable Vsync */ s3cfb_set_global_interrupt(fbdev, 0); s3cfb_set_vsync_interrupt(fbdev, 0); #endif +#endif break; case S3CFB_WIN_POSITION: @@ -1238,8 +1873,12 @@ int s3cfb_ioctl(struct fb_info *fb, unsigned int cmd, unsigned long arg) if (!fbdev->regs) return ret; #endif +#if defined(CONFIG_FB_S5P_VSYNC_THREAD) + ret = s3cfb_set_vsync_int(fb, p.vsync); +#else s3cfb_set_global_interrupt(fbdev, p.vsync); s3cfb_set_vsync_interrupt(fbdev, p.vsync); +#endif } break; @@ -1293,7 +1932,30 @@ int s3cfb_ioctl(struct fb_info *fb, unsigned int cmd, unsigned long arg) else s3cfb_set_alpha_mode(fbdev, win->id, p.alpha_mode); break; + +#if defined(CONFIG_CPU_EXYNOS4212) || defined(CONFIG_CPU_EXYNOS4412) + case S3CFB_WIN_CONFIG: + if (copy_from_user(&p.win_data, + (struct s3c_fb_win_config_data __user *)arg, + sizeof(p.win_data))) { + ret = -EFAULT; + break; + } + + ret = s3c_fb_set_win_config(fbdev, &p.win_data); + if (ret) + break; + + if (copy_to_user((struct s3c_fb_win_config_data __user *)arg, + &p.win_data, + sizeof(p.win_data))) { + ret = -EFAULT; + break; + } + break; +#endif } + return ret; } diff --git a/drivers/video/samsung/s3cfb_s6c1372.c b/drivers/video/samsung/s3cfb_s6c1372.c index 46c35ca..4d23708 100644 --- a/drivers/video/samsung/s3cfb_s6c1372.c +++ b/drivers/video/samsung/s3cfb_s6c1372.c @@ -83,8 +83,18 @@ static DEVICE_ATTR(lcd_type, 0664, lcdtype_show, NULL); void s5c1372_ldi_enable(void) { +#if defined(CONFIG_FB_S5P_S6C1372) + gpio_set_value(GPIO_LCD_EN, GPIO_LEVEL_HIGH); + msleep(40); +#else /* defined(CONFIG_FB_S5P_S6F1202A ) */ gpio_set_value(GPIO_LCD_EN, GPIO_LEVEL_HIGH); + gpio_set_value(GPIO_LCD_LDO_EN, GPIO_LEVEL_HIGH); msleep(40); + + /* Enable backlight PWM GPIO for P2 device. */ + gpio_set_value(GPIO_LCD_BACKLIGHT_PWM, 0); + s3c_gpio_cfgpin(GPIO_LCD_BACKLIGHT_PWM, S3C_GPIO_SFN(3)); +#endif } void s5c1372_ldi_disable(void) @@ -93,12 +103,21 @@ void s5c1372_ldi_disable(void) s3c_gpio_cfgpin(GPIO_LCD_PCLK, S3C_GPIO_OUTPUT); s3c_gpio_setpull(GPIO_LCD_PCLK, S3C_GPIO_PULL_NONE); gpio_set_value(GPIO_LCD_PCLK, GPIO_LEVEL_LOW); -#endif msleep(40); gpio_set_value(GPIO_LCD_EN, GPIO_LEVEL_LOW); msleep(600); +#else /* defined(CONFIG_FB_S5P_S6F1202A ) */ + /* Disable backlight PWM GPIO for P2 device. */ + gpio_set_value(GPIO_LCD_BACKLIGHT_PWM, GPIO_LEVEL_LOW); + s3c_gpio_cfgpin(GPIO_LCD_BACKLIGHT_PWM, S3C_GPIO_OUTPUT); + + /* Disable LVDS Panel Power, 1.2, 1.8, display 3.3V */ + gpio_set_value(GPIO_LCD_LDO_EN, GPIO_LEVEL_LOW); + gpio_set_value(GPIO_LCD_EN, GPIO_LEVEL_LOW); + msleep(300); +#endif } static int __init s6c1372_probe(struct platform_device *pdev) diff --git a/drivers/video/samsung/s3cfb_s6e39a0.c b/drivers/video/samsung/s3cfb_s6e39a0.c index 3d0f534..a07e455 100644 --- a/drivers/video/samsung/s3cfb_s6e39a0.c +++ b/drivers/video/samsung/s3cfb_s6e39a0.c @@ -110,7 +110,10 @@ struct lcd_info { struct dsim_global *dsim; }; -static int s6e8ax0_write(struct lcd_info *lcd, const unsigned char *seq, int len) +extern void (*lcd_early_suspend)(void); +extern void (*lcd_late_resume)(void); + +static int s6e39a0_write(struct lcd_info *lcd, const unsigned char *seq, int len) { int size; const unsigned char *wbuf; @@ -135,7 +138,7 @@ static int s6e8ax0_write(struct lcd_info *lcd, const unsigned char *seq, int len return 0; } -static int s6e8ax0_read(struct lcd_info *lcd, const u8 addr, u16 count, u8 *buf) +static int s6e39a0_read(struct lcd_info *lcd, const u8 addr, u16 count, u8 *buf) { int ret = 0; @@ -245,69 +248,69 @@ static int get_backlight_level_from_brightness(int brightness) return backlightlevel; } -static int s6e8ax0_set_acl(struct lcd_info *lcd) +static int s6e39a0_set_acl(struct lcd_info *lcd) { if (lcd->acl_enable) { if (lcd->cur_acl == 0) { if (lcd->bl == 0 || lcd->bl == 1) { - s6e8ax0_write(lcd, SEQ_ACL_OFF, ARRAY_SIZE(SEQ_ACL_OFF)); + s6e39a0_write(lcd, SEQ_ACL_OFF, ARRAY_SIZE(SEQ_ACL_OFF)); dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d\n", __func__, lcd->cur_acl); } else - s6e8ax0_write(lcd, SEQ_ACL_ON, ARRAY_SIZE(SEQ_ACL_ON)); + s6e39a0_write(lcd, SEQ_ACL_ON, ARRAY_SIZE(SEQ_ACL_ON)); } switch (lcd->bl) { case 0 ... 1: /* 30cd ~ 40cd - 0%*/ if (lcd->cur_acl != 0) { - s6e8ax0_write(lcd, SEQ_ACL_OFF, ARRAY_SIZE(SEQ_ACL_OFF)); + s6e39a0_write(lcd, SEQ_ACL_OFF, ARRAY_SIZE(SEQ_ACL_OFF)); lcd->cur_acl = 0; dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d\n", __func__, lcd->cur_acl); } break; case 2 ... 12: /* 70cd ~ 180cd -40%*/ if (lcd->cur_acl != 40) { - s6e8ax0_write(lcd, acl_cutoff_table[1], ACL_PARAM_SIZE); + s6e39a0_write(lcd, acl_cutoff_table[1], ACL_PARAM_SIZE); lcd->cur_acl = 40; dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d\n", __func__, lcd->cur_acl); } break; case 13: /* 190cd - 43% */ if (lcd->cur_acl != 43) { - s6e8ax0_write(lcd, acl_cutoff_table[2], ACL_PARAM_SIZE); + s6e39a0_write(lcd, acl_cutoff_table[2], ACL_PARAM_SIZE); lcd->cur_acl = 43; dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d\n", __func__, lcd->cur_acl); } break; case 14: /* 200cd - 45% */ if (lcd->cur_acl != 45) { - s6e8ax0_write(lcd, acl_cutoff_table[3], ACL_PARAM_SIZE); + s6e39a0_write(lcd, acl_cutoff_table[3], ACL_PARAM_SIZE); lcd->cur_acl = 45; dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d\n", __func__, lcd->cur_acl); } break; case 15: /* 210cd - 47% */ if (lcd->cur_acl != 47) { - s6e8ax0_write(lcd, acl_cutoff_table[4], ACL_PARAM_SIZE); + s6e39a0_write(lcd, acl_cutoff_table[4], ACL_PARAM_SIZE); lcd->cur_acl = 47; dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d\n", __func__, lcd->cur_acl); } break; case 16: /* 220cd - 48% */ if (lcd->cur_acl != 48) { - s6e8ax0_write(lcd, acl_cutoff_table[5], ACL_PARAM_SIZE); + s6e39a0_write(lcd, acl_cutoff_table[5], ACL_PARAM_SIZE); lcd->cur_acl = 48; dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d\n", __func__, lcd->cur_acl); } break; default: if (lcd->cur_acl != 50) { - s6e8ax0_write(lcd, acl_cutoff_table[6], ACL_PARAM_SIZE); + s6e39a0_write(lcd, acl_cutoff_table[6], ACL_PARAM_SIZE); lcd->cur_acl = 50; dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d\n", __func__, lcd->cur_acl); } break; } } else { - s6e8ax0_write(lcd, SEQ_ACL_OFF, ARRAY_SIZE(SEQ_ACL_OFF)); + s6e39a0_write(lcd, SEQ_ACL_OFF, ARRAY_SIZE(SEQ_ACL_OFF)); lcd->cur_acl = 0; dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d\n", __func__, lcd->cur_acl); } @@ -316,12 +319,12 @@ static int s6e8ax0_set_acl(struct lcd_info *lcd) } #ifndef SMART_DIMMING -static int s6e8ax0_gamma_ctl(struct lcd_info *lcd) +static int s6e39a0_gamma_ctl(struct lcd_info *lcd) { - s6e8ax0_write(lcd, gamma22_table[lcd->bl], GAMMA_PARAM_SIZE); + s6e39a0_write(lcd, gamma22_table[lcd->bl], GAMMA_PARAM_SIZE); /* Gamma Set Update */ - s6e8ax0_write(lcd, SEQ_GAMMA_UPDATE, ARRAY_SIZE(SEQ_GAMMA_UPDATE)); + s6e39a0_write(lcd, SEQ_GAMMA_UPDATE, ARRAY_SIZE(SEQ_GAMMA_UPDATE)); lcd->current_bl = lcd->bl; @@ -332,20 +335,21 @@ static int update_brightness(struct lcd_info *lcd) { int ret; -#if defined(CONFIG_MACH_C1) || defined(CONFIG_MACH_C1VZW) || \ +#if defined(CONFIG_MACH_C1) || \ + defined(CONFIG_MACH_M3) || \ defined(CONFIG_MACH_M0) || defined(CONFIG_MACH_SLP_PQ) || \ - defined(CONFIG_MACH_SLP_PQ_LTE) || defined(CONFIG_MACH_M3) + defined(CONFIG_MACH_SLP_PQ_LTE) #else - ret = s6e8ax0_gamma_ctl(lcd); + ret = s6e39a0_gamma_ctl(lcd); if (ret) return -EPERM; /* - ret = s6e8ax0_set_elvss(lcd); + ret = s6e39a0_set_elvss(lcd); if (ret) return -EPERM; - ret = s6e8ax0_set_acl(lcd); + ret = s6e39a0_set_acl(lcd); if (ret) return -EPERM; */ @@ -356,13 +360,13 @@ static int update_brightness(struct lcd_info *lcd) #endif #ifdef SMART_DIMMING -static int s6e8ax0_read_mtp(struct lcd_info *lcd, u8 *mtp_data) +static int s6e39a0_read_mtp(struct lcd_info *lcd, u8 *mtp_data) { int ret; u8 retry_cnt = 3; read_retry: - ret = s6e8ax0_read(lcd, LDI_MTP_ADDR, LDI_MTP_LENGTH, mtp_data); + ret = s6e39a0_read(lcd, LDI_MTP_ADDR, LDI_MTP_LENGTH, mtp_data); if (!ret) { if (retry_cnt) { printk(KERN_WARNING "[WARN:LCD] : %s : retry cnt : %d\n", __func__, retry_cnt); @@ -481,9 +485,9 @@ static int s6e8aa0_update_brightness(struct lcd_info *lcd, u32 brightness) calc_gamma_table(&lcd->smart, gamma, gamma_regs+2); - s6e8ax0_write(lcd, gamma_regs, GAMMA_PARAM_SIZE); + s6e39a0_write(lcd, gamma_regs, GAMMA_PARAM_SIZE); - s6e8ax0_write(lcd, SEQ_GAMMA_UPDATE, sizeof(SEQ_GAMMA_UPDATE)); + s6e39a0_write(lcd, SEQ_GAMMA_UPDATE, sizeof(SEQ_GAMMA_UPDATE)); #if 0 printk(KERN_INFO "##### print gamma reg #####\n"); @@ -553,12 +557,12 @@ static int s6e8aa0_update_elvss(struct lcd_info *lcd, u32 candela) elvss_cmd[2] = elvss; printk(KERN_DEBUG "elvss reg : %02x\n", elvss_cmd[2]); - s6e8ax0_write(lcd, elvss_cmd, sizeof(elvss_cmd)); + s6e39a0_write(lcd, elvss_cmd, sizeof(elvss_cmd)); return 0; } -static int s6e8ax0_adb_brightness_update(struct lcd_info *lcd, u32 br, u32 force) +static int s6e39a0_adb_brightness_update(struct lcd_info *lcd, u32 br, u32 force) { u32 gamma; int ret = 0; @@ -572,7 +576,7 @@ static int s6e8ax0_adb_brightness_update(struct lcd_info *lcd, u32 br, u32 force ret = s6e8aa0_update_brightness(lcd, gamma); - ret = s6e8ax0_set_acl(lcd); + ret = s6e39a0_set_acl(lcd); if (lcd->support_elvss) ret = s6e8aa0_update_elvss(lcd, gamma); @@ -587,82 +591,82 @@ static int s6e8ax0_adb_brightness_update(struct lcd_info *lcd, u32 br, u32 force } #endif -static int s6e8ax0_ldi_init(struct lcd_info *lcd) +static int s6e39a0_ldi_init(struct lcd_info *lcd) { int ret = 0; - s6e8ax0_write(lcd, SEQ_APPLY_LEVEL_2_KEY, \ + s6e39a0_write(lcd, SEQ_APPLY_LEVEL_2_KEY, \ ARRAY_SIZE(SEQ_APPLY_LEVEL_2_KEY)); - s6e8ax0_write(lcd, SEQ_APPLY_LEVEL_3_KEY, \ + s6e39a0_write(lcd, SEQ_APPLY_LEVEL_3_KEY, \ ARRAY_SIZE(SEQ_APPLY_LEVEL_3_KEY)); - s6e8ax0_write(lcd, SEQ_APPLY_LEVEL_4_KEY, \ + s6e39a0_write(lcd, SEQ_APPLY_LEVEL_4_KEY, \ ARRAY_SIZE(SEQ_APPLY_LEVEL_4_KEY)); - s6e8ax0_write(lcd, SEQ_GAMMA_CONDITION_SET, \ + s6e39a0_write(lcd, SEQ_GAMMA_CONDITION_SET, \ ARRAY_SIZE(SEQ_GAMMA_CONDITION_SET)); - s6e8ax0_write(lcd, SEQ_GAMMA_UPDATE,\ + s6e39a0_write(lcd, SEQ_GAMMA_UPDATE,\ ARRAY_SIZE(SEQ_GAMMA_UPDATE)); - s6e8ax0_write(lcd, SEQ_PANEL_CONDITION_SET, \ + s6e39a0_write(lcd, SEQ_PANEL_CONDITION_SET, \ ARRAY_SIZE(SEQ_PANEL_CONDITION_SET)); - s6e8ax0_write(lcd, SEQ_ETC_CONDITION_SET_2_0, \ + s6e39a0_write(lcd, SEQ_ETC_CONDITION_SET_2_0, \ ARRAY_SIZE(SEQ_ETC_CONDITION_SET_2_0)); - s6e8ax0_write(lcd, SEQ_ETC_CONDITION_SET_2_1, \ + s6e39a0_write(lcd, SEQ_ETC_CONDITION_SET_2_1, \ ARRAY_SIZE(SEQ_ETC_CONDITION_SET_2_1)); - s6e8ax0_write(lcd, SEQ_ETC_CONDITION_SET_2_2, \ + s6e39a0_write(lcd, SEQ_ETC_CONDITION_SET_2_2, \ ARRAY_SIZE(SEQ_ETC_CONDITION_SET_2_2)); - s6e8ax0_write(lcd, SEQ_ETC_CONDITION_SET_2_3, \ + s6e39a0_write(lcd, SEQ_ETC_CONDITION_SET_2_3, \ ARRAY_SIZE(SEQ_ETC_CONDITION_SET_2_3)); - s6e8ax0_write(lcd, SEQ_ETC_CONDITION_SET_2_4, \ + s6e39a0_write(lcd, SEQ_ETC_CONDITION_SET_2_4, \ ARRAY_SIZE(SEQ_ETC_CONDITION_SET_2_4)); - s6e8ax0_write(lcd, SEQ_ETC_CONDITION_SET_2_5, \ + s6e39a0_write(lcd, SEQ_ETC_CONDITION_SET_2_5, \ ARRAY_SIZE(SEQ_ETC_CONDITION_SET_2_5)); - s6e8ax0_write(lcd, SEQ_ETC_CONDITION_SET_2_6, \ + s6e39a0_write(lcd, SEQ_ETC_CONDITION_SET_2_6, \ ARRAY_SIZE(SEQ_ETC_CONDITION_SET_2_6)); - s6e8ax0_write(lcd, SEQ_ETC_CONDITION_SET_2_7, \ + s6e39a0_write(lcd, SEQ_ETC_CONDITION_SET_2_7, \ ARRAY_SIZE(SEQ_ETC_CONDITION_SET_2_7)); - s6e8ax0_write(lcd, SEQ_ETC_CONDITION_SET_2_8, \ + s6e39a0_write(lcd, SEQ_ETC_CONDITION_SET_2_8, \ ARRAY_SIZE(SEQ_ETC_CONDITION_SET_2_8)); - s6e8ax0_write(lcd, SEQ_ETC_CONDITION_SET_2_9, \ + s6e39a0_write(lcd, SEQ_ETC_CONDITION_SET_2_9, \ ARRAY_SIZE(SEQ_ETC_CONDITION_SET_2_9)); - s6e8ax0_write(lcd, SEQ_ETC_CONDITION_SET_2_10, \ + s6e39a0_write(lcd, SEQ_ETC_CONDITION_SET_2_10, \ ARRAY_SIZE(SEQ_ETC_CONDITION_SET_2_10)); - s6e8ax0_write(lcd, SEQ_SLEEP_OUT, \ + s6e39a0_write(lcd, SEQ_SLEEP_OUT, \ ARRAY_SIZE(SEQ_SLEEP_OUT)); mdelay(120); - s6e8ax0_write(lcd, SEQ_MEMORY_WINDOW_SET_1_0, \ + s6e39a0_write(lcd, SEQ_MEMORY_WINDOW_SET_1_0, \ ARRAY_SIZE(SEQ_MEMORY_WINDOW_SET_1_0)); - s6e8ax0_write(lcd, SEQ_MEMORY_WINDOW_SET_1_1, \ + s6e39a0_write(lcd, SEQ_MEMORY_WINDOW_SET_1_1, \ ARRAY_SIZE(SEQ_MEMORY_WINDOW_SET_1_1)); mdelay(1); - s6e8ax0_write(lcd, SEQ_MEMORY_WINDOW_SET_2_1, \ + s6e39a0_write(lcd, SEQ_MEMORY_WINDOW_SET_2_1, \ ARRAY_SIZE(SEQ_MEMORY_WINDOW_SET_2_1)); - s6e8ax0_write(lcd, SEQ_MEMORY_WINDOW_SET_2_2, \ + s6e39a0_write(lcd, SEQ_MEMORY_WINDOW_SET_2_2, \ ARRAY_SIZE(SEQ_MEMORY_WINDOW_SET_2_2)); - s6e8ax0_write(lcd, SEQ_MEMORY_WINDOW_SET_2_3, \ + s6e39a0_write(lcd, SEQ_MEMORY_WINDOW_SET_2_3, \ ARRAY_SIZE(SEQ_MEMORY_WINDOW_SET_2_3)); - s6e8ax0_write(lcd, SEQ_MEMORY_WINDOW_SET_2_4, \ + s6e39a0_write(lcd, SEQ_MEMORY_WINDOW_SET_2_4, \ ARRAY_SIZE(SEQ_MEMORY_WINDOW_SET_2_4)); return ret; } -static int s6e8ax0_ldi_enable(struct lcd_info *lcd) +static int s6e39a0_ldi_enable(struct lcd_info *lcd) { int ret = 0; - s6e8ax0_write(lcd, SEQ_DISPLAY_ON, ARRAY_SIZE(SEQ_DISPLAY_ON)); + s6e39a0_write(lcd, SEQ_DISPLAY_ON, ARRAY_SIZE(SEQ_DISPLAY_ON)); return ret; } -static int s6e8ax0_ldi_disable(struct lcd_info *lcd) +static int s6e39a0_ldi_disable(struct lcd_info *lcd) { int ret = 0; - s6e8ax0_write(lcd, SEQ_DISPLAY_OFF, ARRAY_SIZE(SEQ_DISPLAY_OFF)); - s6e8ax0_write(lcd, SEQ_STANDBY_ON, ARRAY_SIZE(SEQ_STANDBY_ON)); + s6e39a0_write(lcd, SEQ_DISPLAY_OFF, ARRAY_SIZE(SEQ_DISPLAY_OFF)); + s6e39a0_write(lcd, SEQ_STANDBY_ON, ARRAY_SIZE(SEQ_STANDBY_ON)); return ret; } -static int s6e8ax0_power_on(struct lcd_info *lcd) +static int s6e39a0_power_on(struct lcd_info *lcd) { int ret = 0; struct lcd_platform_data *pd = NULL; @@ -670,7 +674,7 @@ static int s6e8ax0_power_on(struct lcd_info *lcd) /* dev_info(&lcd->ld->dev, "%s\n", __func__); */ - ret = s6e8ax0_ldi_init(lcd); + ret = s6e39a0_ldi_init(lcd); if (ret) { dev_err(&lcd->ld->dev, "failed to initialize ldi.\n"); @@ -679,7 +683,7 @@ static int s6e8ax0_power_on(struct lcd_info *lcd) msleep(120); - ret = s6e8ax0_ldi_enable(lcd); + ret = s6e39a0_ldi_enable(lcd); if (ret) { dev_err(&lcd->ld->dev, "failed to enable ldi.\n"); goto err; @@ -688,7 +692,7 @@ static int s6e8ax0_power_on(struct lcd_info *lcd) #ifdef SMART_DIMMING lcd->ldi_enable = 1; - s6e8ax0_adb_brightness_update(lcd, lcd->bd->props.brightness, 1); + s6e39a0_adb_brightness_update(lcd, lcd->bd->props.brightness, 1); #else update_brightness(lcd); @@ -699,7 +703,7 @@ err: return ret; } -static int s6e8ax0_power_off(struct lcd_info *lcd) +static int s6e39a0_power_off(struct lcd_info *lcd) { int ret = 0; @@ -707,21 +711,21 @@ static int s6e8ax0_power_off(struct lcd_info *lcd) lcd->ldi_enable = 0; - ret = s6e8ax0_ldi_disable(lcd); + ret = s6e39a0_ldi_disable(lcd); msleep(120); return ret; } -static int s6e8ax0_power(struct lcd_info *lcd, int power) +static int s6e39a0_power(struct lcd_info *lcd, int power) { int ret = 0; if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->power)) - ret = s6e8ax0_power_on(lcd); + ret = s6e39a0_power_on(lcd); else if (!POWER_IS_ON(power) && POWER_IS_ON(lcd->power)) - ret = s6e8ax0_power_off(lcd); + ret = s6e39a0_power_off(lcd); if (!ret) lcd->power = power; @@ -729,7 +733,7 @@ static int s6e8ax0_power(struct lcd_info *lcd, int power) return ret; } -static int s6e8ax0_set_power(struct lcd_device *ld, int power) +static int s6e39a0_set_power(struct lcd_device *ld, int power) { struct lcd_info *lcd = lcd_get_data(ld); @@ -739,10 +743,10 @@ static int s6e8ax0_set_power(struct lcd_device *ld, int power) return -EINVAL; } - return s6e8ax0_power(lcd, power); + return s6e39a0_power(lcd, power); } -static int s6e8ax0_get_power(struct lcd_device *ld) +static int s6e39a0_get_power(struct lcd_device *ld) { struct lcd_info *lcd = lcd_get_data(ld); @@ -750,7 +754,7 @@ static int s6e8ax0_get_power(struct lcd_device *ld) } #ifdef SMART_DIMMING -static int s6e8ax0_set_brightness(struct backlight_device *bd) +static int s6e39a0_set_brightness(struct backlight_device *bd) { int ret = 0; u32 brightness = (u32)bd->props.brightness; @@ -766,12 +770,12 @@ static int s6e8ax0_set_brightness(struct backlight_device *bd) /* dev_info(&lcd->ld->dev, "[%s] brightness=%d\n", __func__, brightness); */ - ret = s6e8ax0_adb_brightness_update(lcd, brightness, 0); + ret = s6e39a0_adb_brightness_update(lcd, brightness, 0); return ret; } #else -static int s6e8ax0_set_brightness(struct backlight_device *bd) +static int s6e39a0_set_brightness(struct backlight_device *bd) { int ret = 0; int brightness = bd->props.brightness; @@ -802,19 +806,19 @@ static int s6e8ax0_set_brightness(struct backlight_device *bd) } #endif -static int s6e8ax0_get_brightness(struct backlight_device *bd) +static int s6e39a0_get_brightness(struct backlight_device *bd) { return bd->props.brightness; } -static struct lcd_ops s6e8ax0_lcd_ops = { - .set_power = s6e8ax0_set_power, - .get_power = s6e8ax0_get_power, +static struct lcd_ops s6e39a0_lcd_ops = { + .set_power = s6e39a0_set_power, + .get_power = s6e39a0_get_power, }; -static const struct backlight_ops s6e8ax0_backlight_ops = { - .get_brightness = s6e8ax0_get_brightness, - .update_status = s6e8ax0_set_brightness, +static const struct backlight_ops s6e39a0_backlight_ops = { + .get_brightness = s6e39a0_get_brightness, + .update_status = s6e39a0_set_brightness, }; static ssize_t lcd_type_show(struct device *dev, @@ -855,7 +859,7 @@ static ssize_t power_reduce_store(struct device *dev, lcd->acl_enable, value); lcd->acl_enable = value; if (lcd->ldi_enable) - s6e8ax0_set_acl(lcd); + s6e39a0_set_acl(lcd); } return size; } @@ -865,36 +869,36 @@ static DEVICE_ATTR(power_reduce, 0664, power_reduce_show, power_reduce_store); #ifdef CONFIG_HAS_EARLYSUSPEND struct lcd_info *g_lcd; -void s6e8ax0_early_suspend(void) +void s6e39a0_early_suspend(void) { struct lcd_info *lcd = g_lcd; dev_info(&lcd->ld->dev, "+%s\n", __func__); - s6e8ax0_power(lcd, FB_BLANK_POWERDOWN); + s6e39a0_power(lcd, FB_BLANK_POWERDOWN); dev_info(&lcd->ld->dev, "-%s\n", __func__); return ; } -void s6e8ax0_late_resume(void) +void s6e39a0_late_resume(void) { struct lcd_info *lcd = g_lcd; dev_info(&lcd->ld->dev, "+%s\n", __func__); - s6e8ax0_power(lcd, FB_BLANK_UNBLANK); + s6e39a0_power(lcd, FB_BLANK_UNBLANK); dev_info(&lcd->ld->dev, "-%s\n", __func__); return ; } #endif -static void s6e8ax0_read_id(struct lcd_info *lcd, u8 *buf) +static void s6e39a0_read_id(struct lcd_info *lcd, u8 *buf) { int ret = 0; u8 retry_cnt = 3; read_retry: - ret = s6e8ax0_read(lcd, LDI_ID_REG, LDI_ID_LEN, buf); + ret = s6e39a0_read(lcd, LDI_ID_REG, LDI_ID_LEN, buf); if (!ret) { if (retry_cnt) { printk(KERN_WARNING "[WARN:LCD] : %s : retry cnt : %d\n",\ @@ -936,7 +940,7 @@ static void s6e8aa0_check_id(struct lcd_info *lcd, u8 *idbuf) } #endif -static int s6e8ax0_probe(struct device *dev) +static int s6e39a0_probe(struct device *dev) { int ret = 0; struct lcd_info *lcd; @@ -955,7 +959,7 @@ static int s6e8ax0_probe(struct device *dev) g_lcd = lcd; lcd->ld = lcd_device_register("panel", dev, \ - lcd, &s6e8ax0_lcd_ops); + lcd, &s6e39a0_lcd_ops); if (IS_ERR(lcd->ld)) { pr_err("failed to register lcd device\n"); ret = PTR_ERR(lcd->ld); @@ -963,7 +967,7 @@ static int s6e8ax0_probe(struct device *dev) } lcd->bd = backlight_device_register("panel", \ - dev, lcd, &s6e8ax0_backlight_ops, NULL); + dev, lcd, &s6e39a0_backlight_ops, NULL); if (IS_ERR(lcd->bd)) { pr_err("failed to register backlight device\n"); ret = PTR_ERR(lcd->bd); @@ -999,8 +1003,8 @@ static int s6e8ax0_probe(struct device *dev) #if 0 #ifdef CONFIG_HAS_EARLYSUSPEND - lcd->early_suspend.suspend = s6e8ax0_early_suspend; - lcd->early_suspend.resume = s6e8ax0_late_resume; + lcd->early_suspend.suspend = s6e39a0_early_suspend; + lcd->early_suspend.resume = s6e39a0_late_resume; lcd->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 2; register_early_suspend(&lcd->early_suspend); #endif @@ -1008,7 +1012,7 @@ static int s6e8ax0_probe(struct device *dev) mutex_init(&lcd->lock); - s6e8ax0_read_id(lcd, idbuf); + s6e39a0_read_id(lcd, idbuf); dev_info(&lcd->ld->dev, "ID : %x, %x, %x\n", idbuf[0], idbuf[1], idbuf[2]); @@ -1020,7 +1024,7 @@ static int s6e8ax0_probe(struct device *dev) init_table_info(&lcd->smart); - ret = s6e8ax0_read_mtp(lcd, mtp_data); + ret = s6e39a0_read_mtp(lcd, mtp_data); if (!ret) { printk(KERN_ERR "[LCD:ERROR] : %s read mtp failed\n", __func__); /*return -EPERM;*/ @@ -1030,9 +1034,12 @@ static int s6e8ax0_probe(struct device *dev) mutex_init(&lcd->bl_lock); - s6e8ax0_adb_brightness_update(lcd, lcd->bd->props.brightness, 1); + s6e39a0_adb_brightness_update(lcd, lcd->bd->props.brightness, 1); #endif + lcd_early_suspend = s6e39a0_early_suspend; + lcd_late_resume = s6e39a0_late_resume; + return 0; out_free_backlight: @@ -1048,11 +1055,11 @@ err_alloc: return ret; } -static int __devexit s6e8ax0_remove(struct device *dev) +static int __devexit s6e39a0_remove(struct device *dev) { struct lcd_info *lcd = dev_get_drvdata(dev); - s6e8ax0_power(lcd, FB_BLANK_POWERDOWN); + s6e39a0_power(lcd, FB_BLANK_POWERDOWN); lcd_device_unregister(lcd->ld); backlight_device_unregister(lcd->bd); kfree(lcd); @@ -1061,34 +1068,34 @@ static int __devexit s6e8ax0_remove(struct device *dev) } /* Power down all displays on reboot, poweroff or halt. */ -static void s6e8ax0_shutdown(struct device *dev) +static void s6e39a0_shutdown(struct device *dev) { struct lcd_info *lcd = dev_get_drvdata(dev); dev_info(&lcd->ld->dev, "%s\n", __func__); - s6e8ax0_power(lcd, FB_BLANK_POWERDOWN); + s6e39a0_power(lcd, FB_BLANK_POWERDOWN); } -static struct mipi_lcd_driver s6e8ax0_mipi_driver = { +static struct mipi_lcd_driver s6e39a0_mipi_driver = { .name = "s6e8aa0", - .probe = s6e8ax0_probe, - .remove = __devexit_p(s6e8ax0_remove), - .shutdown = s6e8ax0_shutdown, + .probe = s6e39a0_probe, + .remove = __devexit_p(s6e39a0_remove), + .shutdown = s6e39a0_shutdown, }; -static int s6e8ax0_init(void) +static int s6e39a0_init(void) { - return s5p_dsim_register_lcd_driver(&s6e8ax0_mipi_driver); + return s5p_dsim_register_lcd_driver(&s6e39a0_mipi_driver); } -static void s6e8ax0_exit(void) +static void s6e39a0_exit(void) { return; } -module_init(s6e8ax0_init); -module_exit(s6e8ax0_exit); +module_init(s6e39a0_init); +module_exit(s6e39a0_exit); MODULE_DESCRIPTION("MIPI-DSI S6E8AA0:AMS529HA01 (800x1280) Panel Driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/video/samsung/s3cfb_s6e63m0.c b/drivers/video/samsung/s3cfb_s6e63m0.c new file mode 100644 index 0000000..0babb31 --- /dev/null +++ b/drivers/video/samsung/s3cfb_s6e63m0.c @@ -0,0 +1,1718 @@ +/* linux/drivers/video/samsung/s3cfb_s6e63m0.c + * + * MIPI-DSI based AMS529HA01 AMOLED lcd panel 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/mutex.h> +#include <linux/wait.h> +#include <linux/ctype.h> +#include <linux/io.h> +#include <linux/delay.h> +#include <linux/irq.h> +#include <linux/interrupt.h> +#include <linux/gpio.h> +#include <linux/workqueue.h> +#include <linux/backlight.h> +#include <linux/lcd.h> +#include <plat/gpio-cfg.h> +#include <plat/regs-dsim.h> +#include <mach/dsim.h> +#include <mach/mipi_ddi.h> +#ifdef CONFIG_HAS_EARLYSUSPEND +#include <linux/earlysuspend.h> +#endif + +#include "s5p-dsim.h" +#include "s3cfb.h" +#include "s6e63m0_gamma_l.h" + +#if defined(CONFIG_MACH_Q1_BD) +#include "s6e8aa0_gamma_q1.h" +#define SMART_DIMMING +#else +#include "s6e63m0_gamma_grande.h" +#define SMART_DIMMING +#endif + +#ifdef SMART_DIMMING +#include "smart_dimming.h" +#ifdef CONFIG_AID_DIMMING +#include "aid_s6e8aa0.h" +#endif +#endif + +#define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL) + +#define MIN_BRIGHTNESS 0 +#define MAX_BRIGHTNESS 255 +#if defined(CONFIG_MACH_Q1_BD) +#define MAX_GAMMA 290 +#define DEFAULT_BRIGHTNESS 150 +#define DEFAULT_GAMMA_LEVEL GAMMA_150CD +#else +#define MAX_GAMMA 300 +#define DEFAULT_BRIGHTNESS 160 +#define DEFAULT_GAMMA_LEVEL GAMMA_160CD +#endif + +#define LDI_ID_REG 0xD1 +#define LDI_ID_LEN 3 + +#ifdef SMART_DIMMING +#define PANEL_A1_M3 0xA1 + +#define LDI_MTP_LENGTH 24 +#define LDI_MTP_ADDR 0xD3 + +#define DYNAMIC_ELVSS_MIN_VALUE 0x81 +#define DYNAMIC_ELVSS_MAX_VALUE 0x9F + +#define ELVSS_MODE0_MIN_VOLTAGE 62 +#define ELVSS_MODE1_MIN_VOLTAGE 52 + +struct str_elvss { + u8 reference; + u8 limit; +}; +#endif + +struct lcd_info { + unsigned int bl; + unsigned int auto_brightness; + unsigned int acl_enable; + unsigned int cur_acl; + unsigned int current_bl; + unsigned int current_elvss; + + unsigned int ldi_enable; + unsigned int power; + struct mutex lock; + struct mutex bl_lock; + + struct device *dev; + struct lcd_device *ld; + struct backlight_device *bd; + struct lcd_platform_data *lcd_pd; + struct early_suspend early_suspend; + + unsigned char id[LDI_ID_LEN]; + + unsigned char **gamma_table; + unsigned char **elvss_table; + +#ifdef SMART_DIMMING + unsigned int support_elvss; + + struct str_smart_dim smart; + struct str_elvss elvss; +#endif +#ifdef CONFIG_AID_DIMMING + unsigned int support_aid; + unsigned char f8[ARRAY_SIZE( + SEQ_PANEL_CONDITION_SET_500MBPS)]; +#endif + unsigned int irq; + unsigned int connected; + + struct dsim_global *dsim; +}; + +#ifdef CONFIG_AID_DIMMING +static const unsigned int candela_table[GAMMA_MAX] = { + 20, 30, 40, 50, 60, 70, 80, 90, 100, + 110, 120, 130, 140, 150, 160, 170, 180, + 182, 184, 186, 188, + 190, 200, 210, 220, 230, 240, 250, MAX_GAMMA-1 +}; + +static unsigned int aid_candela_table[GAMMA_MAX] = { + base_20to100, base_20to100, base_20to100, base_20to100, + base_20to100, base_20to100, base_20to100, base_20to100, + base_20to100, + AOR40_BASE_110, AOR40_BASE_120, AOR40_BASE_130, AOR40_BASE_140, + AOR40_BASE_150, AOR40_BASE_160, AOR40_BASE_170, AOR40_BASE_180, + AOR40_BASE_182, AOR40_BASE_184, AOR40_BASE_186, AOR40_BASE_188, + 190, 200, 210, 220, 230, 240, 250, MAX_GAMMA-1 +}; + +static unsigned int elvss_offset_table[ELVSS_STATUS_MAX] = { + ELVSS_OFFSET_110, + ELVSS_OFFSET_120, + ELVSS_OFFSET_130, + ELVSS_OFFSET_140, + ELVSS_OFFSET_150, + ELVSS_OFFSET_160, + ELVSS_OFFSET_170, + ELVSS_OFFSET_180, + ELVSS_OFFSET_190, + ELVSS_OFFSET_200, + ELVSS_OFFSET_210, + ELVSS_OFFSET_220, + ELVSS_OFFSET_230, + ELVSS_OFFSET_240, + ELVSS_OFFSET_250, + ELVSS_OFFSET_260, + ELVSS_OFFSET_270, + ELVSS_OFFSET_280, + ELVSS_OFFSET_290, + ELVSS_OFFSET_300 +}; +#else +static const unsigned int candela_table[GAMMA_MAX] = { + 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, + 130, 140, 150, 160, 170, 180, 190, 200, 210, 220, + 230, 240, 250, MAX_GAMMA +}; + +static unsigned int elvss_offset_table[ELVSS_STATUS_MAX] = { + ELVSS_OFFSET_MIN, + ELVSS_OFFSET_1, + ELVSS_OFFSET_2, + ELVSS_OFFSET_MAX +}; +#endif + +extern void (*lcd_early_suspend)(void); +extern void (*lcd_late_resume)(void); + +#if defined(GPIO_OLED_DET) +struct delayed_work hs_clk_re_try; +unsigned int count_dsim; + +static void hs_clk_re_try_work(struct work_struct *work) +{ + int read_oled_det; + + read_oled_det = gpio_get_value(GPIO_OLED_DET); + + printk(KERN_INFO "%s, %d, %d\n", __func__, + count_dsim, read_oled_det); + + if (read_oled_det == 0) { + if (count_dsim < 10) { + schedule_delayed_work(&hs_clk_re_try, HZ/8); + count_dsim++; + set_dsim_hs_clk_toggle_count(15); + } else + set_dsim_hs_clk_toggle_count(0); + } else + set_dsim_hs_clk_toggle_count(0); +} + +static irqreturn_t oled_det_int(int irq, void *dev_id) +{ + printk(KERN_INFO "[DSIM] %s\n", __func__); + + schedule_delayed_work(&hs_clk_re_try, HZ/16); + + count_dsim = 0; + + return IRQ_HANDLED; +} +#endif + +static int s6e63m0_write(struct lcd_info *lcd, + const unsigned char *seq, int len) +{ + int size; + const unsigned char *wbuf; + + if (!lcd->connected) + return 0; + + mutex_lock(&lcd->lock); + + size = len; + wbuf = seq; + + if (size == 1) + lcd->dsim->ops->cmd_write(lcd->dsim, DCS_WR_NO_PARA, wbuf[0], 0); + else if (size == 2) + lcd->dsim->ops->cmd_write(lcd->dsim, DCS_WR_1_PARA, wbuf[0], wbuf[1]); + else + lcd->dsim->ops->cmd_write(lcd->dsim, DCS_LONG_WR, (unsigned int)wbuf, size); + + mutex_unlock(&lcd->lock); + + return 0; +} + +static int _s6e63m0_read(struct lcd_info *lcd, const u8 addr, + u16 count, u8 *buf) +{ + int ret = 0; + + if (!lcd->connected) + return ret; + + mutex_lock(&lcd->lock); + + if (lcd->dsim->ops->cmd_read) + ret = lcd->dsim->ops->cmd_read(lcd->dsim, addr, count, buf); + + mutex_unlock(&lcd->lock); + + return ret; +} + +static int s6e63m0_read(struct lcd_info *lcd, const u8 addr, + u16 count, u8 *buf, u8 retry_cnt) +{ + int ret = 0; + +read_retry: + ret = _s6e63m0_read(lcd, addr, count, buf); + if (!ret) { + if (retry_cnt) { + printk(KERN_WARNING "[WARN:LCD] %s : retry cnt : %d\n", + __func__, retry_cnt); + retry_cnt--; + goto read_retry; + } else + printk(KERN_ERR "[ERROR:LCD] %s : 0x%02x read failed\n", + __func__, addr); + } + + return ret; +} + +#ifdef CONFIG_AID_DIMMING +static int get_backlight_level_from_brightness(int brightness) +{ + int backlightlevel; + + /* brightness setting from platform is from 0 to 255 + * But in this driver, brightness is + only supported from 0 to 24 */ + + switch (brightness) { + case 0 ... 29: + backlightlevel = GAMMA_20CD; + break; + case 30 ... 39: + backlightlevel = GAMMA_30CD; + break; + case 40 ... 49: + backlightlevel = GAMMA_40CD; + break; + case 50 ... 59: + backlightlevel = GAMMA_50CD; + break; + case 60 ... 69: + backlightlevel = GAMMA_60CD; + break; + case 70 ... 79: + backlightlevel = GAMMA_70CD; + break; + case 80 ... 89: + backlightlevel = GAMMA_80CD; + break; + case 90 ... 99: + backlightlevel = GAMMA_90CD; + break; + case 100 ... 109: + backlightlevel = GAMMA_100CD; + break; + case 110 ... 119: + backlightlevel = GAMMA_110CD; + break; + case 120 ... 129: + backlightlevel = GAMMA_120CD; + break; + case 130 ... 139: + backlightlevel = GAMMA_130CD; + break; + case 140 ... 149: + backlightlevel = GAMMA_140CD; + break; + case 150 ... 159: + backlightlevel = GAMMA_150CD; + break; + case 160 ... 169: + backlightlevel = GAMMA_160CD; + break; + case 170 ... 179: + backlightlevel = GAMMA_170CD; + break; + case 180 ... 181: + backlightlevel = GAMMA_180CD; + break; + case 182 ... 183: + backlightlevel = GAMMA_182CD; + break; + case 184 ... 185: + backlightlevel = GAMMA_184CD; + break; + case 186 ... 187: + backlightlevel = GAMMA_186CD; + break; + case 188 ... 189: + backlightlevel = GAMMA_188CD; + break; + case 190 ... 199: + backlightlevel = GAMMA_190CD; + break; + case 200 ... 209: + backlightlevel = GAMMA_200CD; + break; + case 210 ... 219: + backlightlevel = GAMMA_210CD; + break; + case 220 ... 229: + backlightlevel = GAMMA_220CD; + break; + case 230 ... 239: + backlightlevel = GAMMA_230CD; + break; + case 240 ... 249: + backlightlevel = GAMMA_240CD; + break; + case 250 ... 254: + backlightlevel = GAMMA_250CD; + break; + case 255: + backlightlevel = GAMMA_300CD; + break; + default: + backlightlevel = DEFAULT_GAMMA_LEVEL; + break; + } + return backlightlevel; +} + +static int s6e63m0_gamma_ctl(struct lcd_info *lcd) +{ + lcd->f8[0x12] = aid_command_table[lcd->bl][0]; + lcd->f8[0x01] = aid_command_table[lcd->bl][1]; + + s6e63m0_write(lcd, lcd->gamma_table[lcd->bl], + GAMMA_PARAM_SIZE); + s6e63m0_write(lcd, SEQ_GAMMA_UPDATE, + ARRAY_SIZE(SEQ_GAMMA_UPDATE)); + + if (likely(lcd->support_aid)) + s6e63m0_write(lcd, lcd->f8, AID_PARAM_SIZE); + + return 0; +} +#else +static int get_backlight_level_from_brightness(int brightness) +{ + int backlightlevel; + + /* brightness setting from platform is from 0 to 255 + * But in this driver, brightness is + only supported from 0 to 24 */ + + switch (brightness) { + case 0 ... 29: + backlightlevel = GAMMA_30CD; + break; + case 30 ... 254: + backlightlevel = (brightness - candela_table[0]) / 10; + break; + case 255: + backlightlevel = ARRAY_SIZE(candela_table) - 1; + break; + default: + backlightlevel = DEFAULT_GAMMA_LEVEL; + break; + } + return backlightlevel; +} + +static int s6e63m0_gamma_ctl(struct lcd_info *lcd) +{ +#if defined(CONFIG_MACH_M0_GRANDECTC) || defined(CONFIG_MACH_IRON) + s6e63m0_write(lcd, SEQ_GAMMA_CONDITION_SET, + ARRAY_SIZE(SEQ_GAMMA_CONDITION_SET)); +#else + s6e63m0_write(lcd, lcd->gamma_table[lcd->bl], + GAMMA_PARAM_SIZE); +#endif + + /* Gamma Set Update */ + s6e63m0_write(lcd, SEQ_GAMMA_UPDATE, + ARRAY_SIZE(SEQ_GAMMA_UPDATE)); + + return 0; +} +#endif + +#if defined(CONFIG_MACH_Q1_BD) +static int s6e63m0_set_acl(struct lcd_info *lcd) +{ + int ret = 0; + + if (lcd->acl_enable) { + if (lcd->cur_acl == 0) { + if (lcd->bl == 0 || lcd->bl == 1) { + s6e63m0_write(lcd, SEQ_ACL_OFF, + ARRAY_SIZE(SEQ_ACL_OFF)); + dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d, acl_off\n", + __func__, lcd->cur_acl); + } else { + s6e63m0_write(lcd, SEQ_ACL_ON, + ARRAY_SIZE(SEQ_ACL_ON)); + dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d, acl_on\n", + __func__, lcd->cur_acl); + } + } + switch (lcd->bl) { + case GAMMA_30CD... GAMMA_40CD: + if (lcd->cur_acl != 0) { + s6e63m0_write(lcd, SEQ_ACL_OFF, + ARRAY_SIZE(SEQ_ACL_OFF)); + lcd->cur_acl = 0; + dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d\n", + __func__, lcd->cur_acl); + } + break; + case GAMMA_50CD: + if (lcd->cur_acl != 200) { + s6e63m0_write(lcd, ACL_CUTOFF_TABLE[ACL_STATUS_20P], + ACL_PARAM_SIZE); + lcd->cur_acl = 200; + dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d\n", + __func__, lcd->cur_acl); + } + break; + case GAMMA_60CD: + if (lcd->cur_acl != 330) { + s6e63m0_write(lcd, ACL_CUTOFF_TABLE[ACL_STATUS_33P], + ACL_PARAM_SIZE); + lcd->cur_acl = 330; + dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d\n", + __func__, lcd->cur_acl); + } + break; + case GAMMA_70CD: + if (lcd->cur_acl != 430) { + s6e63m0_write(lcd, ACL_CUTOFF_TABLE[ACL_STATUS_43P], + ACL_PARAM_SIZE); + lcd->cur_acl = 430; + dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d\n", + __func__, lcd->cur_acl); + } + break; + case GAMMA_80CD: + if (lcd->cur_acl != 450) { + s6e63m0_write(lcd, ACL_CUTOFF_TABLE[ACL_STATUS_45P_80CD], + ACL_PARAM_SIZE); + lcd->cur_acl = 450; + dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d\n", + __func__, lcd->cur_acl); + } + break; + case GAMMA_90CD ... GAMMA_150CD: + if (lcd->cur_acl != 451) { + s6e63m0_write(lcd, ACL_CUTOFF_TABLE[ACL_STATUS_45P], + ACL_PARAM_SIZE); + lcd->cur_acl = 451; + dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d\n", + __func__, lcd->cur_acl); + } + break; + case GAMMA_160CD: /* 160cd */ + if (lcd->cur_acl != 460) { + s6e63m0_write(lcd, ACL_CUTOFF_TABLE[ACL_STATUS_46P_160CD], + ACL_PARAM_SIZE); + lcd->cur_acl = 460; + dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d\n", + __func__, lcd->cur_acl); + } + break; + case GAMMA_170CD ... GAMMA_250CD: + if (lcd->cur_acl != 461) { + s6e63m0_write(lcd, ACL_CUTOFF_TABLE[ACL_STATUS_46P], + `ACL_PARAM_SIZE); + lcd->cur_acl = 461; + dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d\n", + __func__, lcd->cur_acl); + } + break; + default: + if (lcd->cur_acl != 550) { + s6e63m0_write(lcd, ACL_CUTOFF_TABLE[ACL_STATUS_50P], + ACL_PARAM_SIZE); + lcd->cur_acl = 550; + dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d\n", + __func__, lcd->cur_acl); + } + break; + } + } else { + s6e63m0_write(lcd, SEQ_ACL_OFF, ARRAY_SIZE(SEQ_ACL_OFF)); + lcd->cur_acl = 0; + dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d, acl_off\n", + __func__, lcd->cur_acl); + } + + if (ret) { + ret = -EPERM; + goto acl_err; + } + +acl_err: + return ret; +} +#else +static int s6e63m0_set_acl(struct lcd_info *lcd) +{ +#if !defined(CONFIG_MACH_M0_GRANDECTC) && !defined(CONFIG_MACH_IRON) + if (lcd->acl_enable) { + if (lcd->cur_acl == 0) { + if (lcd->bl == 0 || lcd->bl == 1) { + s6e63m0_write(lcd, SEQ_ACL_OFF, ARRAY_SIZE(SEQ_ACL_OFF)); + dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d, acl_off\n", + __func__, lcd->cur_acl); + } else { + s6e63m0_write(lcd, SEQ_ACL_ON, ARRAY_SIZE(SEQ_ACL_ON)); + dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d, acl_on\n", + __func__, lcd->cur_acl); + } + } + switch (lcd->bl) { + case GAMMA_20CD ... GAMMA_40CD: /* 30cd ~ 40cd - 0%*/ + if (lcd->cur_acl != 0) { + s6e63m0_write(lcd, SEQ_ACL_OFF, ARRAY_SIZE(SEQ_ACL_OFF)); + lcd->cur_acl = 0; + dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d\n", + __func__, lcd->cur_acl); + } + break; + case GAMMA_50CD: /* 50cd - 20%*/ + if (lcd->cur_acl != 20) { + s6e63m0_write(lcd, ACL_CUTOFF_TABLE[ACL_STATUS_20P], + ACL_PARAM_SIZE); + lcd->cur_acl = 20; + dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d\n", + __func__, lcd->cur_acl); + } + break; + case GAMMA_60CD: /* 60cd - 33%*/ + if (lcd->cur_acl != 33) { + s6e63m0_write(lcd, ACL_CUTOFF_TABLE[ACL_STATUS_33P], + ACL_PARAM_SIZE); + lcd->cur_acl = 33; + dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d\n", + __func__, lcd->cur_acl); + } + break; + case GAMMA_70CD ... GAMMA_250CD: /*70cd ~ 250cd - 40%*/ + if (lcd->cur_acl != 40) { + s6e63m0_write(lcd, ACL_CUTOFF_TABLE[ACL_STATUS_40P], + ACL_PARAM_SIZE); + lcd->cur_acl = 40; + dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d\n", + __func__, lcd->cur_acl); + } + break; + default: + if (lcd->cur_acl != 50) { + s6e63m0_write(lcd, ACL_CUTOFF_TABLE[ACL_STATUS_50P], + ACL_PARAM_SIZE); + lcd->cur_acl = 50; + dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d\n", + __func__, lcd->cur_acl); + } + break; + } + } else { + s6e63m0_write(lcd, SEQ_ACL_OFF, ARRAY_SIZE(SEQ_ACL_OFF)); + lcd->cur_acl = 0; + dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d, acl_off\n", + __func__, lcd->cur_acl); + } +#endif + + return 0; +} +#endif + +#ifdef SMART_DIMMING +#ifdef CONFIG_AID_DIMMING +static int s6e63m0_set_elvss(struct lcd_info *lcd) +{ + int ret = 0, elvss_level = 0; + u32 candela = aid_candela_table[lcd->bl]; + + switch (candela) { + case 0 ... 110: + elvss_level = ELVSS_110; + break; + case 111 ... 120: + elvss_level = ELVSS_120; + break; + case 121 ... 130: + elvss_level = ELVSS_130; + break; + case 131 ... 140: + elvss_level = ELVSS_140; + break; + case 141 ... 150: + elvss_level = ELVSS_150; + break; + case 151 ... 160: + elvss_level = ELVSS_160; + break; + case 161 ... 170: + elvss_level = ELVSS_170; + break; + case 171 ... 180: + elvss_level = ELVSS_180; + break; + case 181 ... 190: + elvss_level = ELVSS_190; + break; + case 191 ... 200: + elvss_level = ELVSS_200; + break; + case 201 ... 210: + elvss_level = ELVSS_210; + break; + case 211 ... 220: + elvss_level = ELVSS_220; + break; + case 221 ... 230: + elvss_level = ELVSS_230; + break; + case 231 ... 240: + elvss_level = ELVSS_240; + break; + case 241 ... 250: + elvss_level = ELVSS_250; + break; + case 251 ... 260: + elvss_level = ELVSS_260; + break; + case 261 ... 270: + elvss_level = ELVSS_270; + break; + case 271 ... 280: + elvss_level = ELVSS_280; + break; + case 281 ... 290: + elvss_level = ELVSS_290; + break; + case 291 ... 300: + elvss_level = ELVSS_300; + break; + } + + if (lcd->current_elvss != lcd->elvss_table[elvss_level][2]) { + ret = s6e63m0_write(lcd, lcd->elvss_table[elvss_level], + ELVSS_PARAM_SIZE); + lcd->current_elvss = lcd->elvss_table[elvss_level][2]; + } + + dev_dbg(&lcd->ld->dev, "elvss = %x\n", + lcd->elvss_table[elvss_level][2]); + + if (ret) { + ret = -EPERM; + goto elvss_err; + } + +elvss_err: + return ret; +} +#else +static int s6e63m0_set_elvss(struct lcd_info *lcd) +{ + int ret = 0, elvss_level = 0; + u32 candela = candela_table[lcd->bl]; + + switch (candela) { + case 0 ... 100: + elvss_level = ELVSS_MIN; + break; + case 101 ... 160: + elvss_level = ELVSS_1; + break; + case 161 ... 200: + elvss_level = ELVSS_2; + break; + case 201 ... 300: + elvss_level = ELVSS_MAX; + break; + default: + break; + } + + if (lcd->current_elvss != lcd->elvss_table[elvss_level][2]) { + ret = s6e63m0_write(lcd, lcd->elvss_table[elvss_level], + ELVSS_PARAM_SIZE); + lcd->current_elvss = lcd->elvss_table[elvss_level][2]; + } + + dev_dbg(&lcd->ld->dev, "elvss = %x\n", + lcd->elvss_table[elvss_level][2]); + + if (ret) { + ret = -EPERM; + goto elvss_err; + } + +elvss_err: + return ret; +} +#endif +static u8 get_elvss_value(struct lcd_info *lcd, u8 elvss_level) +{ + u8 ref = 0; + u8 offset; + + if (lcd->elvss.limit == 0x00) + ref = (lcd->elvss.reference | 0x80); + else if (lcd->elvss.limit == 0x01) + ref = (lcd->elvss.reference + 0x40); + else { + printk(KERN_ERR "[ERROR:ELVSS]:%s undefined elvss limit value :%x\n", + __func__, lcd->elvss.limit); + return 0; + } + + offset = elvss_offset_table[elvss_level]; + ref += offset; + + if (ref < DYNAMIC_ELVSS_MIN_VALUE) + ref = DYNAMIC_ELVSS_MIN_VALUE; + else if (ref > DYNAMIC_ELVSS_MAX_VALUE) + ref = DYNAMIC_ELVSS_MAX_VALUE; + + return ref; +} + +static int init_elvss_table(struct lcd_info *lcd) +{ + int i, ret = 0; +#ifdef SMART_DIMMING_DEBUG + int j; +#endif + + lcd->elvss_table = kzalloc(ELVSS_STATUS_MAX * sizeof(u8 *), GFP_KERNEL); + + if (IS_ERR_OR_NULL(lcd->elvss_table)) { + pr_err("failed to allocate elvss table\n"); + ret = -ENOMEM; + goto err_alloc_elvss_table; + } + + for (i = 0; i < ELVSS_STATUS_MAX; i++) { + lcd->elvss_table[i] = kzalloc(ELVSS_PARAM_SIZE * sizeof(u8), + GFP_KERNEL); + if (IS_ERR_OR_NULL(lcd->elvss_table[i])) { + pr_err("failed to allocate elvss\n"); + ret = -ENOMEM; + goto err_alloc_elvss; + } + lcd->elvss_table[i][0] = 0xB1; + lcd->elvss_table[i][1] = 0x04; + lcd->elvss_table[i][2] = get_elvss_value(lcd, i); + } + +#ifdef SMART_DIMMING_DEBUG + for (i = 0; i < ELVSS_STATUS_MAX; i++) { + for (j = 0; j < ELVSS_PARAM_SIZE; j++) + pr_info("0x%02x, ", lcd->elvss_table[i][j]); + pr_info("\n"); + } +#endif + + return 0; + +err_alloc_elvss: + while (i > 0) { + kfree(lcd->elvss_table[i-1]); + i--; + } + kfree(lcd->elvss_table); +err_alloc_elvss_table: + return ret; +} + +#ifdef CONFIG_AID_DIMMING +static int init_gamma_table(struct lcd_info *lcd) +{ + int i, ret = 0; + + lcd->gamma_table = kzalloc(GAMMA_MAX * sizeof(u8 *), + GFP_KERNEL); + if (IS_ERR_OR_NULL(lcd->gamma_table)) { + pr_err("failed to allocate gamma table\n"); + ret = -ENOMEM; + goto err_alloc_gamma_table; + } + + for (i = 0; i < GAMMA_MAX; i++) { + lcd->gamma_table[i] = kzalloc(GAMMA_PARAM_SIZE * sizeof(u8), + GFP_KERNEL); + if (IS_ERR_OR_NULL(lcd->gamma_table[i])) { + pr_err("failed to allocate gamma\n"); + ret = -ENOMEM; + goto err_alloc_gamma; + } + lcd->gamma_table[i][0] = 0xFA; + lcd->gamma_table[i][1] = 0x01; + } + + for (i = GAMMA_20CD; i <= GAMMA_180CD; i++) + calc_gamma_table(&lcd->smart, aid_candela_table[i], + &lcd->gamma_table[i][2], G_21); + + for (i = GAMMA_182CD; i < GAMMA_MAX; i++) { + if ((i > GAMMA_188CD) && (i < GAMMA_200CD)) + calc_gamma_table_215_190(&lcd->smart, + aid_candela_table[i], &lcd->gamma_table[i][2]); + if ((i > GAMMA_250CD) && (i < GAMMA_MAX)) + calc_gamma_table(&lcd->smart, aid_candela_table[i], + &lcd->gamma_table[i][2], G_22); + else + calc_gamma_table(&lcd->smart, aid_candela_table[i], + &lcd->gamma_table[i][2], G_215); + } + +#ifdef SMART_DIMMING_DEBUG + for (i = 0; i < GAMMA_MAX; i++) { + for (j = 0; j < GAMMA_PARAM_SIZE; j++) + pr_info("%d, ", lcd->gamma_table[i][j]); + pr_info("\n"); + } +#endif + return 0; + +err_alloc_gamma: + while (i > 0) { + kfree(lcd->gamma_table[i-1]); + i--; + } + kfree(lcd->gamma_table); +err_alloc_gamma_table: + return ret; +} + +static int init_aid_dimming_table(struct lcd_info *lcd) +{ + unsigned int i, j; + + for (i = 0; i < ARRAY_SIZE(aid_rgb_fix_table); i++) { + j = (aid_rgb_fix_table[i].gray * 3 + + aid_rgb_fix_table[i].rgb) + 2; + lcd->gamma_table[aid_rgb_fix_table[i].candela_idx][j] + += aid_rgb_fix_table[i].offset; + } + +#ifdef SMART_DIMMING_DEBUG + for (i = 0; i < GAMMA_MAX; i++) { + for (j = 0; j < GAMMA_PARAM_SIZE; j++) + pr_info("%d, ", lcd->gamma_table[i][j]); + pr_info("\n"); + } +#endif + return 0; +} +#else +static int init_gamma_table(struct lcd_info *lcd) +{ + int i, ret = 0; + + lcd->gamma_table = kzalloc(GAMMA_MAX * sizeof(u8 *), + GFP_KERNEL); + if (IS_ERR_OR_NULL(lcd->gamma_table)) { + pr_err("failed to allocate gamma table\n"); + ret = -ENOMEM; + goto err_alloc_gamma_table; + } + + for (i = 0; i < GAMMA_MAX; i++) { + lcd->gamma_table[i] = kzalloc(GAMMA_PARAM_SIZE * sizeof(u8), + GFP_KERNEL); + if (IS_ERR_OR_NULL(lcd->gamma_table[i])) { + pr_err("failed to allocate gamma\n"); + ret = -ENOMEM; + goto err_alloc_gamma; + } + lcd->gamma_table[i][0] = 0xFA; + lcd->gamma_table[i][1] = 0x01; + calc_gamma_table(&lcd->smart, candela_table[i]-1, + lcd->gamma_table[i]+2); + } + +#ifdef SMART_DIMMING_DEBUG + for (i = 0; i < GAMMA_MAX; i++) { + for (j = 0; j < GAMMA_PARAM_SIZE; j++) + pr_info("0x%02x, ", lcd->gamma_table[i][j]); + pr_info("\n"); + } +#endif + return 0; + +err_alloc_gamma: + while (i > 0) { + kfree(lcd->gamma_table[i-1]); + i--; + } + kfree(lcd->gamma_table); +err_alloc_gamma_table: + return ret; +} +#endif +#endif + +static int update_brightness(struct lcd_info *lcd, u8 force) +{ + int ret; + u32 brightness; + + mutex_lock(&lcd->bl_lock); + + brightness = lcd->bd->props.brightness; + + if (unlikely(!lcd->auto_brightness && brightness > 250)) + brightness = 250; + + lcd->bl = get_backlight_level_from_brightness(brightness); + + if ((force) || ((lcd->ldi_enable) && + (lcd->current_bl != lcd->bl))) { + + ret = s6e63m0_gamma_ctl(lcd); + /*ret = s6e63m0_set_acl(lcd);*/ + /* W2013 temp block */ + /*ret = s6e63m0_set_elvss(lcd);*/ + /* W2013 temp block */ + + lcd->current_bl = lcd->bl; + + dev_info(&lcd->ld->dev, "brightness=%d, bl=%d, candela=%d\n", + brightness, lcd->bl, candela_table[lcd->bl]); + } + + mutex_unlock(&lcd->bl_lock); + + return 0; +} + +static int s6e63m0_ldi_init(struct lcd_info *lcd) +{ + int ret = 0; + +#if defined(CONFIG_MACH_M0_GRANDECTC) || defined(CONFIG_MACH_IRON) + mdelay(25); /* 25ms */ + s6e63m0_write(lcd, SEQ_SW_RESET, + ARRAY_SIZE(SEQ_SW_RESET)); /* SW Reset */ + mdelay(5); /* Wait 5ms more */ + s6e63m0_write(lcd, SEQ_APPLY_LEVEL2_KEY_ENABLE, + ARRAY_SIZE(SEQ_APPLY_LEVEL2_KEY_ENABLE)); + s6e63m0_write(lcd, SEQ_APPLY_MTP_KEY_ENABLE, + ARRAY_SIZE(SEQ_APPLY_MTP_KEY_ENABLE)); + s6e63m0_write(lcd, SEQ_SLEEP_OUT, + ARRAY_SIZE(SEQ_SLEEP_OUT)); + mdelay(10); /* 10ms */ + s6e63m0_write(lcd, SEQ_PANEL_CONDITION_SET, + ARRAY_SIZE(SEQ_PANEL_CONDITION_SET)); + s6e63m0_write(lcd, SEQ_DISPLAY_CONDITION_SET1, + ARRAY_SIZE(SEQ_DISPLAY_CONDITION_SET1)); + s6e63m0_write(lcd, SEQ_DISPLAY_CONDITION_SET2, + ARRAY_SIZE(SEQ_DISPLAY_CONDITION_SET2)); + s6e63m0_write(lcd, SEQ_GAMMA_CONDITION_SET, + ARRAY_SIZE(SEQ_GAMMA_CONDITION_SET)); + s6e63m0_write(lcd, SEQ_GAMMA_UPDATE, + ARRAY_SIZE(SEQ_GAMMA_UPDATE)); + s6e63m0_write(lcd, SEQ_ETC_SOURCE_CONTROL, + ARRAY_SIZE(SEQ_ETC_SOURCE_CONTROL)); + s6e63m0_write(lcd, SEQ_ETC_CONTROL_B3h, + ARRAY_SIZE(SEQ_ETC_CONTROL_B3h)); +#if !defined(CONFIG_MACH_M0_GRANDECTC) && !defined(CONFIG_MACH_IRON) + s6e63m0_write(lcd, SEQ_ETC_CONTROL_B5h, + ARRAY_SIZE(SEQ_ETC_CONTROL_B5h)); + s6e63m0_write(lcd, SEQ_ETC_CONTROL_B6h, + ARRAY_SIZE(SEQ_ETC_CONTROL_B6h)); + s6e63m0_write(lcd, SEQ_ETC_CONTROL_B7h, + ARRAY_SIZE(SEQ_ETC_CONTROL_B7h)); + s6e63m0_write(lcd, SEQ_ETC_CONTROL_B8h, + ARRAY_SIZE(SEQ_ETC_CONTROL_B8h)); + s6e63m0_write(lcd, SEQ_ETC_CONTROL_B9h, + ARRAY_SIZE(SEQ_ETC_CONTROL_B9h)); + s6e63m0_write(lcd, SEQ_ETC_CONTROL_BAh, + ARRAY_SIZE(SEQ_ETC_CONTROL_BAh)); +#endif + s6e63m0_write(lcd, SEQ_ELVSS_SET, ARRAY_SIZE(SEQ_ELVSS_SET)); + s6e63m0_write(lcd, SEQ_ELVSS_ON, ARRAY_SIZE(SEQ_ELVSS_ON)); + +#elif defined(CONFIG_MACH_Q1_BD) + s6e63m0_write(lcd, SEQ_APPLY_LEVEL_2_KEY, + ARRAY_SIZE(SEQ_APPLY_LEVEL_2_KEY)); + msleep(20); + s6e63m0_write(lcd, SEQ_SLEEP_OUT, ARRAY_SIZE(SEQ_SLEEP_OUT)); + msleep(5); + s6e63m0_write(lcd, SEQ_PANEL_CONDITION_SET, + ARRAY_SIZE(SEQ_PANEL_CONDITION_SET)); + s6e63m0_write(lcd, SEQ_DISPLAY_CONDITION_SET, + ARRAY_SIZE(SEQ_DISPLAY_CONDITION_SET)); + s6e63m0_gamma_ctl(lcd); + s6e63m0_write(lcd, SEQ_ETC_SOURCE_CONTROL, + ARRAY_SIZE(SEQ_ETC_SOURCE_CONTROL)); + s6e63m0_write(lcd, SEQ_ETC_PENTILE_CONTROL, + ARRAY_SIZE(SEQ_ETC_PENTILE_CONTROL)); + s6e63m0_write(lcd, SEQ_ETC_POWER_CONTROL, + ARRAY_SIZE(SEQ_ETC_POWER_CONTROL)); + s6e63m0_write(lcd, SEQ_ELVSS_NVM_SETTING, + ARRAY_SIZE(SEQ_ELVSS_NVM_SETTING)); + s6e63m0_write(lcd, SEQ_ELVSS_CONTROL, + ARRAY_SIZE(SEQ_ELVSS_CONTROL)); +#else + s6e63m0_write(lcd, SEQ_APPLY_LEVEL_2, + ARRAY_SIZE(SEQ_APPLY_LEVEL_2)); + s6e63m0_write(lcd, SEQ_APPLY_MTP_KEY_ENABLE, + ARRAY_SIZE(SEQ_APPLY_MTP_KEY_ENABLE)); + s6e63m0_write(lcd, SEQ_SLEEP_OUT, ARRAY_SIZE(SEQ_SLEEP_OUT)); + msleep(5); + + if (lcd->id[1] == 0x20) { /* 4.8" HD for M0/C1*/ + s6e63m0_write(lcd, SEQ_PANEL_CONDITION_SET_500MBPS, + ARRAY_SIZE(SEQ_PANEL_CONDITION_SET_500MBPS)); + s6e63m0_write(lcd, SEQ_DISPLAY_CONDITION_SET, + ARRAY_SIZE(SEQ_DISPLAY_CONDITION_SET)); + s6e63m0_gamma_ctl(lcd); + s6e63m0_write(lcd, SEQ_ETC_SOURCE_CONTROL, + ARRAY_SIZE(SEQ_ETC_SOURCE_CONTROL)); + s6e63m0_write(lcd, SEQ_ETC_PENTILE_CONTROL, + ARRAY_SIZE(SEQ_ETC_PENTILE_CONTROL)); + s6e63m0_write(lcd, SEQ_ETC_NVM_SETTING, + ARRAY_SIZE(SEQ_ETC_NVM_SETTING)); + s6e63m0_write(lcd, SEQ_ETC_POWER_CONTROL, + ARRAY_SIZE(SEQ_ETC_POWER_CONTROL)); + } else if (lcd->id[1] == 0xae) { + s6e63m0_write(lcd, SEQ_PANEL_CONDITION_SET_480MBPS_46, + ARRAY_SIZE(SEQ_PANEL_CONDITION_SET_480MBPS_46)); + s6e63m0_write(lcd, SEQ_DISPLAY_CONDITION_SET, + ARRAY_SIZE(SEQ_DISPLAY_CONDITION_SET)); + s6e63m0_gamma_ctl(lcd); + s6e63m0_write(lcd, SEQ_ETC_SOURCE_CONTROL, + ARRAY_SIZE(SEQ_ETC_SOURCE_CONTROL)); + s6e63m0_write(lcd, SEQ_ETC_PENTILE_CONTROL_46, + ARRAY_SIZE(SEQ_ETC_PENTILE_CONTROL_46)); + s6e63m0_write(lcd, SEQ_ETC_NVM_SETTING_46, + ARRAY_SIZE(SEQ_ETC_NVM_SETTING_46)); + s6e63m0_write(lcd, SEQ_ETC_POWER_CONTROL_46, + ARRAY_SIZE(SEQ_ETC_POWER_CONTROL_46)); + } else { + s6e63m0_write(lcd, SEQ_PANEL_CONDITION_SET_500MBPS_46, + ARRAY_SIZE(SEQ_PANEL_CONDITION_SET_500MBPS_46)); + s6e63m0_write(lcd, SEQ_DISPLAY_CONDITION_SET, + ARRAY_SIZE(SEQ_DISPLAY_CONDITION_SET)); + s6e63m0_gamma_ctl(lcd); + s6e63m0_write(lcd, SEQ_ETC_SOURCE_CONTROL, + ARRAY_SIZE(SEQ_ETC_SOURCE_CONTROL)); + s6e63m0_write(lcd, SEQ_ETC_PENTILE_CONTROL_46, + ARRAY_SIZE(SEQ_ETC_PENTILE_CONTROL_46)); + s6e63m0_write(lcd, SEQ_ETC_NVM_SETTING_46, + ARRAY_SIZE(SEQ_ETC_NVM_SETTING_46)); + s6e63m0_write(lcd, SEQ_ETC_POWER_CONTROL_46, + ARRAY_SIZE(SEQ_ETC_POWER_CONTROL_46)); + } + + s6e63m0_write(lcd, SEQ_ELVSS_CONTROL, + ARRAY_SIZE(SEQ_ELVSS_CONTROL)); +#endif + + return ret; +} + +static int s6e63m0_ldi_enable(struct lcd_info *lcd) +{ + int ret = 0; + + s6e63m0_write(lcd, SEQ_DISPLAY_ON, ARRAY_SIZE(SEQ_DISPLAY_ON)); + + return ret; +} + +static int s6e63m0_ldi_disable(struct lcd_info *lcd) +{ + int ret = 0; + + s6e63m0_write(lcd, SEQ_DISPLAY_OFF, + ARRAY_SIZE(SEQ_DISPLAY_OFF)); + s6e63m0_write(lcd, SEQ_STANDBY_ON, + ARRAY_SIZE(SEQ_STANDBY_ON)); + + return ret; +} + +static int s6e63m0_power_on(struct lcd_info *lcd) +{ + int ret = 0; + struct lcd_platform_data *pd = NULL; + pd = lcd->lcd_pd; + + /* dev_info(&lcd->ld->dev, "%s\n", __func__); */ + + ret = s6e63m0_ldi_init(lcd); + if (ret) { + dev_err(&lcd->ld->dev, "failed to initialize ldi.\n"); + goto err; + } + + msleep(120); + + ret = s6e63m0_ldi_enable(lcd); + if (ret) { + dev_err(&lcd->ld->dev, "failed to enable ldi.\n"); + goto err; + } + + lcd->ldi_enable = 1; + + update_brightness(lcd, 1); +err: + return ret; +} + +static int s6e63m0_power_off(struct lcd_info *lcd) +{ + int ret = 0; + + dev_info(&lcd->ld->dev, "%s\n", __func__); + + lcd->ldi_enable = 0; + + ret = s6e63m0_ldi_disable(lcd); + + msleep(135); + + return ret; +} + +static int s6e63m0_power(struct lcd_info *lcd, int power) +{ + int ret = 0; + + if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->power)) + ret = s6e63m0_power_on(lcd); + else if (!POWER_IS_ON(power) && POWER_IS_ON(lcd->power)) + ret = s6e63m0_power_off(lcd); + + if (!ret) + lcd->power = power; + + return ret; +} + +static int s6e63m0_set_power(struct lcd_device *ld, int power) +{ + struct lcd_info *lcd = lcd_get_data(ld); + + if (power != FB_BLANK_UNBLANK && power != FB_BLANK_POWERDOWN && + power != FB_BLANK_NORMAL) { + dev_err(&lcd->ld->dev, "power value should be 0, 1 or 4.\n"); + return -EINVAL; + } + + return s6e63m0_power(lcd, power); +} + +static int s6e63m0_get_power(struct lcd_device *ld) +{ + struct lcd_info *lcd = lcd_get_data(ld); + + return lcd->power; +} + +static int s6e63m0_set_brightness(struct backlight_device *bd) +{ + int ret = 0; + int brightness = bd->props.brightness; + struct lcd_info *lcd = bl_get_data(bd); + + /* dev_info(&lcd->ld->dev, "%s: brightness=%d\n", + __func__, brightness); */ + + if (brightness < MIN_BRIGHTNESS || + brightness > bd->props.max_brightness) { + dev_err(&bd->dev, "lcd brightness should be %d to %d. now %d\n", + MIN_BRIGHTNESS, MAX_BRIGHTNESS, brightness); + return -EINVAL; + } + + if (lcd->ldi_enable) { + ret = update_brightness(lcd, 0); + if (ret < 0) { + dev_err(lcd->dev, "err in %s\n", __func__); + return -EINVAL; + } + } + + return ret; +} + +static int s6e63m0_get_brightness(struct backlight_device *bd) +{ + struct lcd_info *lcd = bl_get_data(bd); + + return candela_table[lcd->bl]; +} + +static struct lcd_ops s6e63m0_lcd_ops = { + .set_power = s6e63m0_set_power, + .get_power = s6e63m0_get_power, +}; + +static const struct backlight_ops s6e63m0_backlight_ops = { + .get_brightness = s6e63m0_get_brightness, + .update_status = s6e63m0_set_brightness, +}; + +static ssize_t power_reduce_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct lcd_info *lcd = dev_get_drvdata(dev); + char temp[3]; + + sprintf(temp, "%d\n", lcd->acl_enable); + strcpy(buf, temp); + + return strlen(buf); +} + +static ssize_t power_reduce_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + struct lcd_info *lcd = dev_get_drvdata(dev); + int value; + int rc; + + rc = strict_strtoul(buf, (unsigned int)0, + (unsigned long *)&value); + if (rc < 0) + return rc; + else { + if (lcd->acl_enable != value) { + dev_info(dev, "%s - %d, %d\n", + __func__, lcd->acl_enable, value); + mutex_lock(&lcd->bl_lock); + lcd->acl_enable = value; + if (lcd->ldi_enable) + s6e63m0_set_acl(lcd); + mutex_unlock(&lcd->bl_lock); + } + } + return size; +} + +static DEVICE_ATTR(power_reduce, 0664, power_reduce_show, + power_reduce_store); + +static ssize_t lcd_type_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + char temp[15]; +#if defined(CONFIG_MACH_Q1_BD) + sprintf(temp, "SMD_AMS529HA01\n"); +#else + sprintf(temp, "SMD_AMS480GYXX\n"); +#endif + strcat(buf, temp); + return strlen(buf); +} + +static DEVICE_ATTR(lcd_type, 0444, lcd_type_show, NULL); + +static ssize_t gamma_table_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct lcd_info *lcd = dev_get_drvdata(dev); + int i, j; + + for (i = 0; i < GAMMA_MAX; i++) { + for (j = 0; j < GAMMA_PARAM_SIZE; j++) + pr_info("0x%02x, ", lcd->gamma_table[i][j]); + pr_info("\n"); + } + + for (i = 0; i < ELVSS_STATUS_MAX; i++) { + for (j = 0; j < ELVSS_PARAM_SIZE; j++) + pr_info("0x%02x, ", lcd->elvss_table[i][j]); + pr_info("\n"); + } + + return strlen(buf); +} +static DEVICE_ATTR(gamma_table, 0444, gamma_table_show, NULL); + +static ssize_t auto_brightness_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct lcd_info *lcd = dev_get_drvdata(dev); + char temp[3]; + + sprintf(temp, "%d\n", lcd->auto_brightness); + strcpy(buf, temp); + + return strlen(buf); +} + +static ssize_t auto_brightness_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + struct lcd_info *lcd = dev_get_drvdata(dev); + int value; + int rc; + + rc = strict_strtoul(buf, (unsigned int)0, (unsigned long *)&value); + if (rc < 0) + return rc; + else { + if (lcd->auto_brightness != value) { + dev_info(dev, "%s - %d, %d\n", + __func__, lcd->auto_brightness, value); + mutex_lock(&lcd->bl_lock); + lcd->auto_brightness = value; + mutex_unlock(&lcd->bl_lock); + if (lcd->ldi_enable) + update_brightness(lcd, 0); + } + } + return size; +} + +static DEVICE_ATTR(auto_brightness, 0644, auto_brightness_show, + auto_brightness_store); + +#ifdef CONFIG_HAS_EARLYSUSPEND +struct lcd_info *g_lcd; + +void s6e63m0_early_suspend(void) +{ + struct lcd_info *lcd = g_lcd; + + set_dsim_lcd_enabled(0); + + dev_info(&lcd->ld->dev, "+%s\n", __func__); +#if defined(GPIO_OLED_DET) + disable_irq(lcd->irq); + gpio_request(GPIO_OLED_DET, "OLED_DET"); + s3c_gpio_cfgpin(GPIO_OLED_DET, S3C_GPIO_OUTPUT); + s3c_gpio_setpull(GPIO_OLED_DET, S3C_GPIO_PULL_NONE); + gpio_direction_output(GPIO_OLED_DET, GPIO_LEVEL_LOW); + gpio_free(GPIO_OLED_DET); +#endif + s6e63m0_power(lcd, FB_BLANK_POWERDOWN); + dev_info(&lcd->ld->dev, "-%s\n", __func__); + + return ; +} + +void s6e63m0_late_resume(void) +{ + struct lcd_info *lcd = g_lcd; + + dev_info(&lcd->ld->dev, "+%s\n", __func__); + s6e63m0_power(lcd, FB_BLANK_UNBLANK); +#if defined(GPIO_OLED_DET) + s3c_gpio_cfgpin(GPIO_OLED_DET, S3C_GPIO_SFN(0xf)); + s3c_gpio_setpull(GPIO_OLED_DET, S3C_GPIO_PULL_NONE); + enable_irq(lcd->irq); +#endif + dev_info(&lcd->ld->dev, "-%s\n", __func__); + + set_dsim_lcd_enabled(1); + + return ; +} +#endif + +#ifdef CONFIG_INPUT_FLIP +void samsung_switching_lcd_suspend(int init, int flip) +{ + pr_info("%s: flip %s\n", __func__, (flip) ? "OPEN" : "CLOSE"); + s6e63m0_early_suspend();/*LCD suspend*/ + s5p_dsim_early_suspend();/*MIPI suspend*/ +} +EXPORT_SYMBOL(samsung_switching_lcd_suspend); + +void samsung_switching_lcd_resume(int init, int flip) +{ + pr_info("%s: flip %s\n", __func__, (flip) ? "OPEN" : "CLOSE"); + s5p_dsim_late_resume();/*MIPI wakeup*/ +#if 0 + if (s5p_dsim_fifo_clear() == 0) { + s5p_dsim_early_suspend(); + msleep(10); + s5p_dsim_late_resume(); + if (s5p_dsim_fifo_clear() == 0) + pr_info("dsim resume fail!!!\n"); + } +#endif + s6e63m0_late_resume();/*LCD wakeup*/ +} +EXPORT_SYMBOL(samsung_switching_lcd_resume); +#endif + +static void s6e63m0_read_id(struct lcd_info *lcd, u8 *buf) +{ + int ret = 0; + + ret = s6e63m0_read(lcd, LDI_ID_REG, LDI_ID_LEN, buf, 3); + if (!ret) { + lcd->connected = 0; + dev_info(&lcd->ld->dev, "panel is not connected well\n"); + } +} + +#ifdef SMART_DIMMING +static int s6e63m0_read_mtp(struct lcd_info *lcd, u8 *mtp_data) +{ + int ret; + + ret = s6e63m0_read(lcd, LDI_MTP_ADDR, LDI_MTP_LENGTH, mtp_data, 0); + + return ret; +} + +#if defined(CONFIG_MACH_Q1_BD) +static void s6e63m0_check_id(struct lcd_info *lcd, u8 *idbuf) +{ + u32 i; + + for (i = 0; i < LDI_ID_LEN; i++) + lcd->smart.panelid[i] = idbuf[i]; + + if (idbuf[2] == 0x33) + lcd->support_elvss = 0; + else { + lcd->support_elvss = 1; + lcd->elvss.limit = (idbuf[2] & 0xc0) >> 6; + lcd->elvss.reference = idbuf[2] & 0x3f; + printk(KERN_DEBUG "Dynamic ELVSS Information, 0x%x\n", + lcd->elvss.reference); + } +} +#else +static void s6e63m0_check_id(struct lcd_info *lcd, u8 *idbuf) +{ + int i; + + for (i = 0; i < LDI_ID_LEN; i++) + lcd->smart.panelid[i] = idbuf[i]; + + if (idbuf[0] == PANEL_A1_M3) + lcd->support_elvss = 0; + else { + lcd->support_elvss = 1; + lcd->elvss.reference = idbuf[2] & (BIT(0) | BIT(1) | + BIT(2) | BIT(3) | BIT(4)); + printk(KERN_DEBUG "Dynamic ELVSS Information, 0x%x\n", + lcd->elvss.reference); + } +} +#endif +#endif + +static int s6e63m0_probe(struct device *dev) +{ + int ret = 0; + struct lcd_info *lcd; +#ifdef SMART_DIMMING + u8 mtp_data[LDI_MTP_LENGTH] = {0,}; +#endif + + lcd = kzalloc(sizeof(struct lcd_info), GFP_KERNEL); + if (!lcd) { + pr_err("failed to allocate for lcd\n"); + ret = -ENOMEM; + goto err_alloc; + } + + g_lcd = lcd; + + lcd->ld = lcd_device_register("panel", dev, lcd, &s6e63m0_lcd_ops); + if (IS_ERR(lcd->ld)) { + pr_err("failed to register lcd device\n"); + ret = PTR_ERR(lcd->ld); + goto out_free_lcd; + } + + lcd->bd = backlight_device_register("panel", dev, lcd, + &s6e63m0_backlight_ops, NULL); + if (IS_ERR(lcd->bd)) { + pr_err("failed to register backlight device\n"); + ret = PTR_ERR(lcd->bd); + goto out_free_backlight; + } + + lcd->dev = dev; + lcd->dsim = (struct dsim_global *)dev_get_drvdata(dev->parent); + lcd->bd->props.max_brightness = MAX_BRIGHTNESS; + lcd->bd->props.brightness = DEFAULT_BRIGHTNESS; + lcd->bl = DEFAULT_GAMMA_LEVEL; + lcd->current_bl = lcd->bl; + + lcd->acl_enable = 0; + lcd->cur_acl = 0; + + lcd->power = FB_BLANK_UNBLANK; + lcd->ldi_enable = 1; + lcd->connected = 1; + lcd->auto_brightness = 0; + + ret = device_create_file(&lcd->ld->dev, &dev_attr_power_reduce); + if (ret < 0) + dev_err(&lcd->ld->dev, "failed to add sysfs entries, %d\n", + __LINE__); + + ret = device_create_file(&lcd->ld->dev, &dev_attr_lcd_type); + if (ret < 0) + dev_err(&lcd->ld->dev, "failed to add sysfs entries, %d\n", + __LINE__); + + ret = device_create_file(&lcd->ld->dev, &dev_attr_gamma_table); + if (ret < 0) + dev_err(&lcd->ld->dev, "failed to add sysfs entries, %d\n", + __LINE__); + + ret = device_create_file(&lcd->bd->dev, &dev_attr_auto_brightness); + if (ret < 0) + dev_err(&lcd->ld->dev, "failed to add sysfs entries, %d\n", + __LINE__); + + dev_set_drvdata(dev, lcd); + + mutex_init(&lcd->lock); + mutex_init(&lcd->bl_lock); +#if !defined(CONFIG_MACH_M0_GRANDECTC) && !defined(CONFIG_MACH_IRON) + s6e63m0_read_id(lcd, lcd->id); + + dev_info(&lcd->ld->dev, "ID: %x, %x, %x\n", lcd->id[0], + lcd->id[1], lcd->id[2]); +#endif + + dev_info(&lcd->ld->dev, "s6e63m0 lcd panel driver has been probed.\n"); + +#ifdef SMART_DIMMING +#if !defined(CONFIG_MACH_M0_GRANDECTC) && !defined(CONFIG_MACH_IRON) + s6e63m0_check_id(lcd, lcd->id); +#endif + + init_table_info(&lcd->smart); +#if !defined(CONFIG_MACH_M0_GRANDECTC) && !defined(CONFIG_MACH_IRON) + ret = s6e63m0_read_mtp(lcd, mtp_data); + if (!ret) { + printk(KERN_ERR "[LCD:ERROR] : %s read mtp failed\n", __func__); + /*return -EPERM;*/ + } +#endif + + calc_voltage_table(&lcd->smart, mtp_data); + + if (lcd->support_elvss) + ret = init_elvss_table(lcd); + + ret = init_gamma_table(lcd); + +#ifdef CONFIG_AID_DIMMING +#if !defined(CONFIG_MACH_M0_GRANDECTC) && !defined(CONFIG_MACH_IRON) + if (lcd->id[1] == 0x20) { + printk(KERN_INFO "AID Dimming is started\n"); + lcd->support_aid = 1; + ret += init_aid_dimming_table(lcd); + memcpy(lcd->f8, SEQ_PANEL_CONDITION_SET_500MBPS, + AID_PARAM_SIZE); + } +#endif +#endif + + if (ret) { + lcd->gamma_table = (unsigned char **)gamma22_table; + lcd->elvss_table = (unsigned char **)ELVSS_TABLE; + } + + update_brightness(lcd, 1); +#endif + +#if defined(GPIO_OLED_DET) + if (lcd->connected) { + INIT_DELAYED_WORK(&hs_clk_re_try, hs_clk_re_try_work); + + lcd->irq = gpio_to_irq(GPIO_OLED_DET); + + s3c_gpio_cfgpin(GPIO_OLED_DET, S3C_GPIO_SFN(0xf)); + s3c_gpio_setpull(GPIO_OLED_DET, S3C_GPIO_PULL_NONE); + if (request_irq(lcd->irq, oled_det_int, + IRQF_TRIGGER_FALLING, "esd_detection", 0)) + pr_err("failed to reqeust irq. %d\n", lcd->irq); + } +#endif + + lcd_early_suspend = s6e63m0_early_suspend; + lcd_late_resume = s6e63m0_late_resume; + + return 0; + +out_free_backlight: + lcd_device_unregister(lcd->ld); + kfree(lcd); + return ret; + +out_free_lcd: + kfree(lcd); + return ret; + +err_alloc: + return ret; +} + +static int __devexit s6e63m0_remove(struct device *dev) +{ + struct lcd_info *lcd = dev_get_drvdata(dev); + + s6e63m0_power(lcd, FB_BLANK_POWERDOWN); + lcd_device_unregister(lcd->ld); + backlight_device_unregister(lcd->bd); + kfree(lcd); + + return 0; +} + +/* Power down all displays on reboot, poweroff or halt. */ +static void s6e63m0_shutdown(struct device *dev) +{ + struct lcd_info *lcd = dev_get_drvdata(dev); + + dev_info(&lcd->ld->dev, "%s\n", __func__); + + s6e63m0_power(lcd, FB_BLANK_POWERDOWN); +} + +static struct mipi_lcd_driver s6e63m0_mipi_driver = { + .name = "s6e63m0", + .probe = s6e63m0_probe, + .remove = __devexit_p(s6e63m0_remove), + .shutdown = s6e63m0_shutdown, +}; + +static int s6e63m0_init(void) +{ + return s5p_dsim_register_lcd_driver(&s6e63m0_mipi_driver); +} + +static void s6e63m0_exit(void) +{ + return; +} + +module_init(s6e63m0_init); +module_exit(s6e63m0_exit); + +MODULE_DESCRIPTION("MIPI-DSI S6E63M0:AMS397GEXX (480X800) Panel Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/samsung/s3cfb_s6e8aa0.c b/drivers/video/samsung/s3cfb_s6e8aa0.c index ff94492..00b543e 100644 --- a/drivers/video/samsung/s3cfb_s6e8aa0.c +++ b/drivers/video/samsung/s3cfb_s6e8aa0.c @@ -88,7 +88,7 @@ struct lcd_info { unsigned int bl; unsigned int auto_brightness; unsigned int acl_enable; - unsigned int cur_acl; + unsigned int current_acl; unsigned int current_bl; unsigned int current_elvss; @@ -131,6 +131,7 @@ struct lcd_info { #ifdef CONFIG_AID_DIMMING static const unsigned int candela_table[GAMMA_MAX] = { 20, 30, 40, 50, 60, 70, 80, 90, 100, + 102, 104, 106, 108, 110, 120, 130, 140, 150, 160, 170, 180, 182, 184, 186, 188, 190, 200, 210, 220, 230, 240, 250, MAX_GAMMA-1 @@ -138,9 +139,9 @@ static const unsigned int candela_table[GAMMA_MAX] = { static unsigned int aid_candela_table[GAMMA_MAX] = { base_20to100, base_20to100, base_20to100, base_20to100, base_20to100, base_20to100, base_20to100, base_20to100, base_20to100, - AOR40_BASE_110, AOR40_BASE_120, AOR40_BASE_130, AOR40_BASE_140, AOR40_BASE_150, - AOR40_BASE_160, AOR40_BASE_170, AOR40_BASE_180, AOR40_BASE_182, AOR40_BASE_184, - AOR40_BASE_186, AOR40_BASE_188, + AOR40_BASE_102, AOR40_BASE_104, AOR40_BASE_106, AOR40_BASE_108, + AOR40_BASE_110, AOR40_BASE_120, AOR40_BASE_130, AOR40_BASE_140, AOR40_BASE_150, AOR40_BASE_160, AOR40_BASE_170, AOR40_BASE_180, + AOR40_BASE_182, AOR40_BASE_184, AOR40_BASE_186, AOR40_BASE_188, 190, 200, 210, 220, 230, 240, 250, MAX_GAMMA-1 }; @@ -181,6 +182,9 @@ static unsigned int elvss_offset_table[ELVSS_STATUS_MAX] = { }; #endif +extern void (*lcd_early_suspend)(void); +extern void (*lcd_late_resume)(void); + #if defined(GPIO_OLED_DET) static void oled_detection_work(struct work_struct *work) { @@ -286,76 +290,100 @@ static int get_backlight_level_from_brightness(int brightness) switch (brightness) { case 0 ... 29: - backlightlevel = GAMMA_30CD; //GAMMA_20CD; + backlightlevel = GAMMA_20CD; break; case 30 ... 39: - backlightlevel = GAMMA_40CD; //GAMMA_30CD; + backlightlevel = GAMMA_30CD; break; case 40 ... 49: - backlightlevel = GAMMA_50CD; //GAMMA_40CD; + backlightlevel = GAMMA_40CD; break; case 50 ... 59: - backlightlevel = GAMMA_60CD; //GAMMA_50CD; + backlightlevel = GAMMA_50CD; break; case 60 ... 69: - backlightlevel = GAMMA_70CD; //GAMMA_60CD; + backlightlevel = GAMMA_60CD; break; case 70 ... 79: - backlightlevel = GAMMA_80CD; //GAMMA_70CD; + backlightlevel = GAMMA_70CD; break; case 80 ... 89: - backlightlevel = GAMMA_90CD; //GAMMA_80CD; + backlightlevel = GAMMA_80CD; break; case 90 ... 99: - backlightlevel = GAMMA_100CD; //GAMMA_90CD; + backlightlevel = GAMMA_90CD; + break; + case 100 ... 101: + backlightlevel = GAMMA_100CD; + break; + case 102 ... 103: + backlightlevel = GAMMA_102CD; + break; + case 104 ... 105: + backlightlevel = GAMMA_104CD; + break; + case 106 ... 107: + backlightlevel = GAMMA_106CD; break; - case 100 ... 109: - backlightlevel = GAMMA_110CD; //GAMMA_100CD; + case 108 ... 109: + backlightlevel = GAMMA_108CD; break; case 110 ... 119: - backlightlevel = GAMMA_130CD; //GAMMA_110CD; + backlightlevel = GAMMA_110CD; break; case 120 ... 129: - backlightlevel = GAMMA_140CD; //GAMMA_120CD; + backlightlevel = GAMMA_120CD; break; case 130 ... 139: - backlightlevel = GAMMA_150CD; //GAMMA_130CD; + backlightlevel = GAMMA_130CD; break; case 140 ... 149: - backlightlevel = GAMMA_160CD; //GAMMA_140CD; + backlightlevel = GAMMA_140CD; break; case 150 ... 159: - backlightlevel = GAMMA_180CD; //GAMMA_150CD; + backlightlevel = GAMMA_150CD; break; case 160 ... 169: - backlightlevel = GAMMA_190CD; //GAMMA_160CD; + backlightlevel = GAMMA_160CD; break; case 170 ... 179: - backlightlevel = GAMMA_200CD; //GAMMA_170CD; + backlightlevel = GAMMA_170CD; break; - case 180 ... 189: - backlightlevel = GAMMA_210CD; + case 180 ... 181: + backlightlevel = GAMMA_180CD; + break; + case 182 ... 183: + backlightlevel = GAMMA_182CD; + break; + case 184 ... 185: + backlightlevel = GAMMA_184CD; + break; + case 186 ... 187: + backlightlevel = GAMMA_186CD; + break; + case 188 ... 189: + backlightlevel = GAMMA_188CD; break; case 190 ... 199: - backlightlevel = GAMMA_220CD; //GAMMA_190CD; + backlightlevel = GAMMA_190CD; break; case 200 ... 209: - backlightlevel = GAMMA_230CD; //GAMMA_200CD; + backlightlevel = GAMMA_200CD; break; case 210 ... 219: - backlightlevel = GAMMA_240CD; //GAMMA_210CD; + backlightlevel = GAMMA_210CD; break; case 220 ... 229: - backlightlevel = GAMMA_240CD; //GAMMA_220CD; + backlightlevel = GAMMA_220CD; break; case 230 ... 239: - backlightlevel = GAMMA_250CD; //GAMMA_230CD; + backlightlevel = GAMMA_230CD; break; case 240 ... 249: - backlightlevel = GAMMA_250CD; //GAMMA_240CD; + backlightlevel = GAMMA_240CD; break; case 250 ... 254: - backlightlevel = GAMMA_300CD; //GAMMA_250CD; + backlightlevel = GAMMA_250CD; break; case 255: backlightlevel = GAMMA_300CD; @@ -367,14 +395,24 @@ static int get_backlight_level_from_brightness(int brightness) return backlightlevel; } -static int s6e8ax0_aid_parameter_ctl(struct lcd_info *lcd , u8 force) +static int s6e8ax0_aid_parameter_ctl(struct lcd_info *lcd, u8 force) { - if (likely(lcd->support_aid)) { - if ((lcd->f8[lcd->bl][0x12] != lcd->f8[lcd->current_bl][0x12]) || - (lcd->f8[lcd->bl][0x01] != lcd->f8[lcd->current_bl][0x01]) || (force)) - s6e8ax0_write(lcd, lcd->f8[lcd->bl], AID_PARAM_SIZE); - } + if (unlikely(!lcd->support_aid)) + goto exit; + + if (force) + goto aid_update; + else if (aid_command_table[lcd->bl][0] != aid_command_table[lcd->current_bl][0]) + goto aid_update; + else if (aid_command_table[lcd->bl][1] != aid_command_table[lcd->current_bl][1]) + goto aid_update; + else + goto exit; +aid_update: + s6e8ax0_write(lcd, lcd->f8[lcd->bl], AID_PARAM_SIZE); + +exit: return 0; } #else @@ -414,149 +452,112 @@ static int s6e8ax0_gamma_ctl(struct lcd_info *lcd) } #if defined(CONFIG_S6E8AA0_AMS529HA01) -static int s6e8ax0_set_acl(struct lcd_info *lcd) +static int s6e8ax0_set_acl(struct lcd_info *lcd, u8 force) { - int ret = 0; + int ret = 0, enable, level; + u32 candela = candela_table[lcd->bl]; - if (lcd->acl_enable) { - if (lcd->cur_acl == 0) { - if (lcd->bl == 0 || lcd->bl == 1) { - s6e8ax0_write(lcd, SEQ_ACL_OFF, ARRAY_SIZE(SEQ_ACL_OFF)); - dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d, acl_off\n", __func__, lcd->cur_acl); - } else { - s6e8ax0_write(lcd, SEQ_ACL_ON, ARRAY_SIZE(SEQ_ACL_ON)); - dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d, acl_on\n", __func__, lcd->cur_acl); - } - } - switch (lcd->bl) { - case GAMMA_30CD... GAMMA_40CD: - if (lcd->cur_acl != 0) { - s6e8ax0_write(lcd, SEQ_ACL_OFF, ARRAY_SIZE(SEQ_ACL_OFF)); - lcd->cur_acl = 0; - dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d\n", __func__, lcd->cur_acl); - } - break; - case GAMMA_50CD: - if (lcd->cur_acl != 200) { - s6e8ax0_write(lcd, ACL_CUTOFF_TABLE[ACL_STATUS_20P], ACL_PARAM_SIZE); - lcd->cur_acl = 200; - dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d\n", __func__, lcd->cur_acl); - } - break; - case GAMMA_60CD: - if (lcd->cur_acl != 330) { - s6e8ax0_write(lcd, ACL_CUTOFF_TABLE[ACL_STATUS_33P], ACL_PARAM_SIZE); - lcd->cur_acl = 330; - dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d\n", __func__, lcd->cur_acl); - } - break; - case GAMMA_70CD: - if (lcd->cur_acl != 430) { - s6e8ax0_write(lcd, ACL_CUTOFF_TABLE[ACL_STATUS_43P], ACL_PARAM_SIZE); - lcd->cur_acl = 430; - dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d\n", __func__, lcd->cur_acl); - } - break; - case GAMMA_80CD: - if (lcd->cur_acl != 450) { - s6e8ax0_write(lcd, ACL_CUTOFF_TABLE[ACL_STATUS_45P_80CD], ACL_PARAM_SIZE); - lcd->cur_acl = 450; - dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d\n", __func__, lcd->cur_acl); - } - break; - case GAMMA_90CD ... GAMMA_150CD: - if (lcd->cur_acl != 451) { - s6e8ax0_write(lcd, ACL_CUTOFF_TABLE[ACL_STATUS_45P], ACL_PARAM_SIZE); - lcd->cur_acl = 451; - dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d\n", __func__, lcd->cur_acl); - } - break; - case GAMMA_160CD: /* 160cd */ - if (lcd->cur_acl != 460) { - s6e8ax0_write(lcd, ACL_CUTOFF_TABLE[ACL_STATUS_46P_160CD], ACL_PARAM_SIZE); - lcd->cur_acl = 460; - dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d\n", __func__, lcd->cur_acl); - } - break; - case GAMMA_170CD ... GAMMA_250CD: - if (lcd->cur_acl != 461) { - s6e8ax0_write(lcd, ACL_CUTOFF_TABLE[ACL_STATUS_46P], ACL_PARAM_SIZE); - lcd->cur_acl = 461; - dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d\n", __func__, lcd->cur_acl); - } - break; - default: - if (lcd->cur_acl != 550) { - s6e8ax0_write(lcd, ACL_CUTOFF_TABLE[ACL_STATUS_50P], ACL_PARAM_SIZE); - lcd->cur_acl = 550; - dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d\n", __func__, lcd->cur_acl); - } - break; - } - } else { - s6e8ax0_write(lcd, SEQ_ACL_OFF, ARRAY_SIZE(SEQ_ACL_OFF)); - lcd->cur_acl = 0; - dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d, acl_off\n", __func__, lcd->cur_acl); + switch (candela) { + case 0 ... 49: + level = ACL_STATUS_0P; + break; + case 50 ... 59: + level = ACL_STATUS_20P; + break; + case 60 ... 69: + level = ACL_STATUS_33P; + break; + case 70 ... 79: + level = ACL_STATUS_43P; + break; + case 80 ... 89: + level = ACL_STATUS_45P_80CD; + break; + case 90 ... 159: + level = ACL_STATUS_45P; + break; + case 160 ... 169: + level = ACL_STATUS_46P_160CD; + break; + case 170 ... 250: + level = ACL_STATUS_46P; + break; + default: + level = ACL_STATUS_50P; + break; } - if (ret) { + if (!lcd->acl_enable) + level = ACL_STATUS_0P; + + enable = !!level; + + //if (force || lcd->acl_enable != enable) { + dev_dbg(&lcd->ld->dev, "acl turn %s\n", enable ? "on" : "off"); + if (enable) + ret = s6e8ax0_write(lcd, SEQ_ACL_ON, ARRAY_SIZE(SEQ_ACL_ON)); + else { + ret = s6e8ax0_write(lcd, SEQ_ACL_OFF, ARRAY_SIZE(SEQ_ACL_OFF)); + goto exit; + } + //} + + //if (force || lcd->current_acl != level) { + ret = s6e8ax0_write(lcd, ACL_CUTOFF_TABLE[level], ACL_PARAM_SIZE); + lcd->current_acl = level; + dev_dbg(&lcd->ld->dev, "current_acl = %d\n", lcd->current_acl); + //} + + if (ret) ret = -EPERM; - goto acl_err; - } -acl_err: +exit: return ret; } #else -static int s6e8ax0_set_acl(struct lcd_info *lcd) +static int s6e8ax0_set_acl(struct lcd_info *lcd, u8 force) { - if (lcd->acl_enable) { - if (lcd->cur_acl == 0) { - if (lcd->bl == 0) { - s6e8ax0_write(lcd, SEQ_ACL_OFF, ARRAY_SIZE(SEQ_ACL_OFF)); - dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d, acl_off\n", __func__, lcd->cur_acl); - } else { - s6e8ax0_write(lcd, SEQ_ACL_ON, ARRAY_SIZE(SEQ_ACL_ON)); - dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d, acl_on\n", __func__, lcd->cur_acl); - } - } - switch (lcd->bl) { - case 0: - if (lcd->cur_acl != 0) { - s6e8ax0_write(lcd, SEQ_ACL_OFF, ARRAY_SIZE(SEQ_ACL_OFF)); - lcd->cur_acl = 0; - dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d\n", __func__, lcd->cur_acl); - } - break; - case 1: - if (lcd->cur_acl != 33) { - s6e8ax0_write(lcd, ACL_CUTOFF_TABLE[ACL_STATUS_33P], ACL_PARAM_SIZE); - lcd->cur_acl = 33; - dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d\n", __func__, lcd->cur_acl); - } - break; - case 2 ... GAMMA_250CD: - if (lcd->cur_acl != 40) { - s6e8ax0_write(lcd, ACL_CUTOFF_TABLE[ACL_STATUS_40P], ACL_PARAM_SIZE); - lcd->cur_acl = 40; - dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d\n", __func__, lcd->cur_acl); - } - break; - default: - if (lcd->cur_acl != 50) { - s6e8ax0_write(lcd, ACL_CUTOFF_TABLE[ACL_STATUS_50P], ACL_PARAM_SIZE); - lcd->cur_acl = 50; - dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d\n", __func__, lcd->cur_acl); - } - break; - } - } else { - s6e8ax0_write(lcd, SEQ_ACL_OFF, ARRAY_SIZE(SEQ_ACL_OFF)); - lcd->cur_acl = 0; - dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d, acl_off\n", __func__, lcd->cur_acl); + int ret = 0, enable, level; + u32 candela = candela_table[lcd->bl]; + + switch (candela) { + case 0 ... 29: + level = ACL_STATUS_0P; + break; + case 30 ... 39: + level = ACL_STATUS_33P; + break; + default: + level = ACL_STATUS_40P; + break; } - return 0; + if ((!lcd->acl_enable) || (lcd->auto_brightness >= 5)) + level = ACL_STATUS_0P; + + enable = !!level; + + //if (force || lcd->acl_enable != enable) { + dev_dbg(&lcd->ld->dev, "acl turn %s\n", enable ? "on" : "off"); + if (enable) + ret = s6e8ax0_write(lcd, SEQ_ACL_ON, ARRAY_SIZE(SEQ_ACL_ON)); + else { + ret = s6e8ax0_write(lcd, SEQ_ACL_OFF, ARRAY_SIZE(SEQ_ACL_OFF)); + goto exit; + } + //} + + //if (force || lcd->current_acl != level) { + ret = s6e8ax0_write(lcd, ACL_CUTOFF_TABLE[level], ACL_PARAM_SIZE); + lcd->current_acl = level; + dev_dbg(&lcd->ld->dev, "current_acl = %d\n", lcd->current_acl); + //} + + if (ret) + ret = -EPERM; + +exit: + return ret; } #endif @@ -630,7 +631,7 @@ static int s6e8ax0_set_elvss(struct lcd_info *lcd, u8 force) break; } - if ((lcd->current_elvss != lcd->elvss_table[elvss_level][2]) || force) { + if (force || lcd->current_elvss != lcd->elvss_table[elvss_level][2]) { ret = s6e8ax0_write(lcd, lcd->elvss_table[elvss_level], ELVSS_PARAM_SIZE); lcd->current_elvss = lcd->elvss_table[elvss_level][2]; } @@ -668,7 +669,7 @@ static int s6e8ax0_set_elvss(struct lcd_info *lcd, u8 force) break; } - if ((lcd->current_elvss != lcd->elvss_table[elvss_level][2]) || force) { + if (force || lcd->current_elvss != lcd->elvss_table[elvss_level][2]) { ret = s6e8ax0_write(lcd, lcd->elvss_table[elvss_level], ELVSS_PARAM_SIZE); lcd->current_elvss = lcd->elvss_table[elvss_level][2]; } @@ -893,16 +894,12 @@ static int update_brightness(struct lcd_info *lcd, u8 force) lcd->bl = get_backlight_level_from_brightness(brightness); if ((force) || ((lcd->ldi_enable) && (lcd->current_bl != lcd->bl))) { + s6e8ax0_gamma_ctl(lcd); #ifdef CONFIG_AID_DIMMING - if ((force) || unlikely(aid_candela_table[lcd->bl] != aid_candela_table[lcd->current_bl])) -#endif - s6e8ax0_gamma_ctl(lcd); - -#ifdef CONFIG_AID_DIMMING - s6e8ax0_aid_parameter_ctl(lcd , force); + s6e8ax0_aid_parameter_ctl(lcd, force); #endif - s6e8ax0_set_acl(lcd); + s6e8ax0_set_acl(lcd, force); s6e8ax0_set_elvss(lcd, force); @@ -1152,9 +1149,9 @@ static ssize_t power_reduce_store(struct device *dev, dev_info(dev, "%s - %d, %d\n", __func__, lcd->acl_enable, value); mutex_lock(&lcd->bl_lock); lcd->acl_enable = value; - if (lcd->ldi_enable) - s6e8ax0_set_acl(lcd); mutex_unlock(&lcd->bl_lock); + if (lcd->ldi_enable) + update_brightness(lcd, 1); } } return size; @@ -1228,7 +1225,7 @@ static ssize_t auto_brightness_store(struct device *dev, lcd->auto_brightness = value; mutex_unlock(&lcd->bl_lock); if (lcd->ldi_enable) - update_brightness(lcd, 0); + update_brightness(lcd, 1); } } return size; @@ -1336,6 +1333,29 @@ static void s6e8aa0_check_id(struct lcd_info *lcd, u8 *idbuf) #endif #endif +static ssize_t read_acl_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct lcd_info *lcd = dev_get_drvdata(dev); + char *pos = buf; + char temp[ACL_PARAM_SIZE] = {0,}; + u32 i; + + s6e8ax0_read(lcd, 0xC0, 3, temp, 0); + pos += sprintf(pos, "0xC0=0x%02x, 0x%02x\n", temp[0], temp[1]); + + s6e8ax0_read(lcd, 0xC1, ACL_PARAM_SIZE, temp, 0); + for (i = 0; i < ACL_PARAM_SIZE; i++) { + pos += sprintf(pos, "0x%02x, ", temp[i]); + if ((i % 5) == 0) + pos += sprintf(pos, "\n"); + } + pos += sprintf(pos, "\n"); + + return pos - buf; +} +static DEVICE_ATTR(read_acl, 0444, read_acl_show, NULL); + static int s6e8ax0_probe(struct device *dev) { int ret = 0; @@ -1375,7 +1395,7 @@ static int s6e8ax0_probe(struct device *dev) lcd->current_bl = lcd->bl; lcd->acl_enable = 0; - lcd->cur_acl = 0; + lcd->current_acl = 0; lcd->power = FB_BLANK_UNBLANK; lcd->ldi_enable = 1; @@ -1394,6 +1414,10 @@ static int s6e8ax0_probe(struct device *dev) if (ret < 0) dev_err(&lcd->ld->dev, "failed to add sysfs entries, %d\n", __LINE__); + ret = device_create_file(&lcd->ld->dev, &dev_attr_read_acl); + if (ret < 0) + dev_err(&lcd->ld->dev, "failed to add sysfs entries, %d\n", __LINE__); + ret = device_create_file(&lcd->bd->dev, &dev_attr_auto_brightness); if (ret < 0) dev_err(&lcd->ld->dev, "failed to add sysfs entries, %d\n", __LINE__); @@ -1461,6 +1485,10 @@ static int s6e8ax0_probe(struct device *dev) pr_err("failed to reqeust irq. %d\n", lcd->irq); } #endif + + lcd_early_suspend = s6e8ax0_early_suspend; + lcd_late_resume = s6e8ax0_late_resume; + return 0; out_free_backlight: @@ -1518,5 +1546,5 @@ static void s6e8ax0_exit(void) module_init(s6e8ax0_init); module_exit(s6e8ax0_exit); -MODULE_DESCRIPTION("MIPI-DSI S6E8AA0:AMS529HA01 (800x1280) Panel Driver"); +MODULE_DESCRIPTION("MIPI-DSI S6E8AA0: AMS529HA01 (800x1280) / AMS480GYXX (720x1280) Panel Driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/video/samsung/s3cfb_s6e8ab0.c b/drivers/video/samsung/s3cfb_s6e8ab0.c index bc47c37..76a98d9 100644 --- a/drivers/video/samsung/s3cfb_s6e8ab0.c +++ b/drivers/video/samsung/s3cfb_s6e8ab0.c @@ -75,7 +75,7 @@ struct str_elvss { struct lcd_info { unsigned int bl; unsigned int acl_enable; - unsigned int cur_acl; + unsigned int current_acl; unsigned int current_bl; unsigned int ldi_enable; @@ -105,6 +105,9 @@ struct lcd_info { struct dsim_global *dsim; }; +extern void (*lcd_early_suspend)(void); +extern void (*lcd_late_resume)(void); + static int s6e8ax0_write(struct lcd_info *lcd, const unsigned char *seq, int len) { int size; @@ -165,101 +168,6 @@ read_retry: return ret; } -#if 0 -static int get_backlight_level_from_brightness(int brightness) -{ - int backlightlevel; - - /* brightness setting from platform is from 0 to 255 - * But in this driver, brightness is only supported from 0 to 24 */ - - switch (brightness) { - case 0: - backlightlevel = GAMMA_30CD; - break; - case 1 ... 29: - backlightlevel = GAMMA_30CD; - break; - case 30 ... 34: - backlightlevel = GAMMA_40CD; - break; - case 35 ... 44: - backlightlevel = GAMMA_50CD; - break; - case 45 ... 54: - backlightlevel = GAMMA_60CD; - break; - case 55 ... 64: - backlightlevel = GAMMA_70CD; - break; - case 65 ... 74: - backlightlevel = GAMMA_80CD; - break; - case 75 ... 83: - backlightlevel = GAMMA_90CD; - break; - case 84 ... 93: - backlightlevel = GAMMA_100CD; - break; - case 94 ... 103: - backlightlevel = GAMMA_105CD; - break; - case 104 ... 113: - backlightlevel = GAMMA_110CD; - break; - case 114 ... 122: - backlightlevel = GAMMA_120CD; - break; - case 123 ... 132: - backlightlevel = GAMMA_130CD; - break; - case 133 ... 142: - backlightlevel = GAMMA_140CD; - break; - case 143 ... 152: - backlightlevel = GAMMA_150CD; - break; - case 153 ... 162: - backlightlevel = GAMMA_160CD; - break; - case 163 ... 171: - backlightlevel = GAMMA_170CD; - break; - case 172 ... 181: - backlightlevel = GAMMA_180CD; - break; - case 182 ... 191: - backlightlevel = GAMMA_190CD; - break; - case 192 ... 201: - backlightlevel = GAMMA_200CD; - break; - case 202 ... 210: - backlightlevel = GAMMA_205CD; - break; - case 211 ... 220: - backlightlevel = GAMMA_210CD; - break; - case 221 ... 230: - backlightlevel = GAMMA_220CD; - break; - case 231 ... 240: - backlightlevel = GAMMA_230CD; - break; - case 241 ... 250: - backlightlevel = GAMMA_240CD; - break; - case 251 ... 255: - backlightlevel = GAMMA_250CD; - break; - default: - backlightlevel = DEFAULT_GAMMA_LEVEL; - break; - } - return backlightlevel; -} -#endif - static int s6e8ax0_gamma_ctl(struct lcd_info *lcd) { /* Gamma Select */ @@ -273,47 +181,45 @@ static int s6e8ax0_gamma_ctl(struct lcd_info *lcd) return 0; } -static int s6e8ax0_set_acl(struct lcd_info *lcd) +static int s6e8ax0_set_acl(struct lcd_info *lcd, u8 force) { - int ret = 0; + int ret = 0, enable, level; + u32 candela = candela_table[lcd->bl]; - if (lcd->acl_enable) { - if (lcd->cur_acl == 0) { - if (lcd->bl == 0 || lcd->bl == 1) { - s6e8ax0_write(lcd, SEQ_ACL_OFF, ARRAY_SIZE(SEQ_ACL_OFF)); - dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d, acl_off\n", __func__, lcd->cur_acl); - } else - s6e8ax0_write(lcd, SEQ_ACL_ON, ARRAY_SIZE(SEQ_ACL_ON)); - dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d, acl_on\n", __func__, lcd->cur_acl); - } - switch (lcd->bl) { - case GAMMA_30CD ... GAMMA_40CD: /* 30cd ~ 40cd */ - if (lcd->cur_acl != 0) { - s6e8ax0_write(lcd, SEQ_ACL_OFF, ARRAY_SIZE(SEQ_ACL_OFF)); - lcd->cur_acl = 0; - dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d\n", __func__, lcd->cur_acl); - } - break; - default: - if (lcd->cur_acl != 40) { - s6e8ax0_write(lcd, ACL_CUTOFF_TABLE[1], ACL_PARAM_SIZE); - lcd->cur_acl = 40; - dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d\n", __func__, lcd->cur_acl); - } - break; - } - } else { - s6e8ax0_write(lcd, SEQ_ACL_OFF, ARRAY_SIZE(SEQ_ACL_OFF)); - lcd->cur_acl = 0; - dev_dbg(&lcd->ld->dev, "%s : cur_acl=%d, acl_off\n", __func__, lcd->cur_acl); + switch (candela) { + case 0 ... 49: + level = ACL_STATUS_0P; + break; + default: + level = ACL_STATUS_40P; + break; } - if (ret) { + if (!lcd->acl_enable) + level = ACL_STATUS_0P; + + enable = !!level; + + //if (force || lcd->acl_enable != enable) { + dev_dbg(&lcd->ld->dev, "acl turn %s\n", enable ? "on" : "off"); + if (enable) + ret = s6e8ax0_write(lcd, SEQ_ACL_ON, ARRAY_SIZE(SEQ_ACL_ON)); + else { + ret = s6e8ax0_write(lcd, SEQ_ACL_OFF, ARRAY_SIZE(SEQ_ACL_OFF)); + goto exit; + } + //} + + //if (force || lcd->current_acl != level) { + ret = s6e8ax0_write(lcd, ACL_CUTOFF_TABLE[level], ACL_PARAM_SIZE); + lcd->current_acl = level; + dev_dbg(&lcd->ld->dev, "current_acl = %d\n", lcd->current_acl); + //} + + if (ret) ret = -EPERM; - goto acl_err; - } -acl_err: +exit: return ret; } @@ -499,7 +405,7 @@ static int update_brightness(struct lcd_info *lcd, u8 force) ret = s6e8ax0_gamma_ctl(lcd); - ret = s6e8ax0_set_acl(lcd); + ret = s6e8ax0_set_acl(lcd, force); ret = s6e8ax0_set_elvss(lcd); @@ -720,7 +626,7 @@ static ssize_t power_reduce_store(struct device *dev, dev_info(dev, "%s - %d, %d\n", __func__, lcd->acl_enable, value); lcd->acl_enable = value; if (lcd->ldi_enable) - s6e8ax0_set_acl(lcd); + s6e8ax0_set_acl(lcd, 0); } } return size; @@ -863,7 +769,7 @@ static int s6e8ax0_probe(struct device *dev) lcd->current_bl = lcd->bl; lcd->acl_enable = 0; - lcd->cur_acl = 0; + lcd->current_acl = 0; lcd->power = FB_BLANK_UNBLANK; lcd->ldi_enable = 1; @@ -924,6 +830,9 @@ static int s6e8ax0_probe(struct device *dev) update_brightness(lcd, 1); #endif + lcd_early_suspend = s6e8ax0_early_suspend; + lcd_late_resume = s6e8ax0_late_resume; + return 0; out_free_backlight: diff --git a/drivers/video/samsung/s3cfb_s6evr02.c b/drivers/video/samsung/s3cfb_s6evr02.c new file mode 100644 index 0000000..dc94822 --- /dev/null +++ b/drivers/video/samsung/s3cfb_s6evr02.c @@ -0,0 +1,1352 @@ +/* linux/drivers/video/samsung/s3cfb_s6evr02.c + * + * MIPI-DSI based AMS555HBxx AMOLED lcd panel 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/mutex.h> +#include <linux/wait.h> +#include <linux/ctype.h> +#include <linux/io.h> +#include <linux/delay.h> +#include <linux/irq.h> +#include <linux/interrupt.h> +#include <linux/gpio.h> +#include <linux/workqueue.h> +#include <linux/backlight.h> +#include <linux/lcd.h> +#include <linux/rtc.h> +#include <linux/reboot.h> +#include <linux/syscalls.h> /* sys_sync */ +#include <plat/gpio-cfg.h> +#include <plat/regs-dsim.h> +#include <mach/dsim.h> +#include <mach/mipi_ddi.h> +#ifdef CONFIG_HAS_EARLYSUSPEND +#include <linux/earlysuspend.h> +#endif + +#include "s5p-dsim.h" +#include "s3cfb.h" +#include "s6evr02_param.h" + +#define SMART_DIMMING +#undef SMART_DIMMING_DEBUG + +#ifdef SMART_DIMMING +#include "smart_dimming_s6evr02.h" +#include "aid_s6evr02.h" +#endif + + +#define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL) + +#define MIN_BRIGHTNESS 0 +#define MAX_BRIGHTNESS 255 +#define MAX_GAMMA 300 +#define DEFAULT_BRIGHTNESS 130 +#define DEFAULT_GAMMA_LEVEL GAMMA_130CD + +#define LDI_ID_REG 0xD7 +#define LDI_ID_LEN 3 +#ifdef SMART_DIMMING +#define LDI_MTP_LENGTH 33 +#define LDI_MTP_ADDR 0xC8 +#endif + +struct lcd_info { + unsigned int bl; + unsigned int auto_brightness; + unsigned int acl_enable; + unsigned int current_acl; + unsigned int current_bl; + unsigned int current_elvss; + unsigned int ldi_enable; + unsigned int power; + struct mutex lock; + struct mutex bl_lock; + struct device *dev; + struct lcd_device *ld; + struct backlight_device *bd; + struct lcd_platform_data *lcd_pd; + struct early_suspend early_suspend; + unsigned char id[LDI_ID_LEN]; + unsigned char **gamma_table; + unsigned char **elvss_table; +#ifdef SMART_DIMMING + struct str_smart_dim smart; + unsigned char aor[GAMMA_MAX][ARRAY_SIZE(SEQ_AOR_CONTROL)]; +#endif + unsigned int irq; + unsigned int connected; + +#if defined(GPIO_ERR_FG) + struct delayed_work err_fg_detection; + unsigned int err_fg_detection_count; +#endif +#if defined(GPIO_OLED_DET) + struct delayed_work oled_detection; + unsigned int oled_detection_count; +#endif + + struct dsim_global *dsim; +}; + +static const unsigned int candela_table[GAMMA_MAX] = { + 20, 30, 40, 50, 60, 70, 80, 90, 100, + 102, 104, 106, 108, + 110, 120, 130, 140, 150, 160, 170, 180, + 182, 184, 186, 188, + 190, 200, 210, 220, 230, 240, 250, MAX_GAMMA-1 +}; + +#ifdef SMART_DIMMING +static unsigned int aid_candela_table[GAMMA_MAX] = { + base_20to100, base_20to100, base_20to100, base_20to100, base_20to100, base_20to100, base_20to100, base_20to100, base_20to100, + AOR40_BASE_102, AOR40_BASE_104, AOR40_BASE_106, AOR40_BASE_108, + AOR40_BASE_110, AOR40_BASE_120, AOR40_BASE_130, AOR40_BASE_140, AOR40_BASE_150, + AOR40_BASE_160, AOR40_BASE_170, AOR40_BASE_180, + AOR40_BASE_182, AOR40_BASE_184, AOR40_BASE_186, AOR40_BASE_188, + 190, 200, 210, 220, 230, 240, 250, MAX_GAMMA-1 +}; +#endif + +extern void (*lcd_early_suspend)(void); +extern void (*lcd_late_resume)(void); + +#if defined(GPIO_ERR_FG) +static void err_fg_detection_work(struct work_struct *work) +{ + struct lcd_info *lcd = + container_of(work, struct lcd_info, err_fg_detection.work); + + int err_fg_level = gpio_get_value(GPIO_ERR_FG); + + dev_info(&lcd->ld->dev, "%s, %d, %d\n", __func__, lcd->err_fg_detection_count, err_fg_level); + + if (!err_fg_level) { + if (lcd->err_fg_detection_count < 10) { + schedule_delayed_work(&lcd->err_fg_detection, HZ/8); + lcd->err_fg_detection_count++; + set_dsim_hs_clk_toggle_count(15); + } else + set_dsim_hs_clk_toggle_count(0); + } else + set_dsim_hs_clk_toggle_count(0); + +} + +static irqreturn_t err_fg_detection_int(int irq, void *_lcd) +{ + struct lcd_info *lcd = _lcd; + + dev_info(&lcd->ld->dev, "\t\t%s\n", __func__); + + lcd->err_fg_detection_count = 0; + schedule_delayed_work(&lcd->err_fg_detection, HZ/16); + + return IRQ_HANDLED; +} +#endif + +#if defined(GPIO_OLED_DET) +static void oled_detection_work(struct work_struct *work) +{ + struct lcd_info *lcd = + container_of(work, struct lcd_info, oled_detection.work); + + struct file *fp; + char name[128]; + struct timespec ts; + struct rtc_time tm; + + int oled_det_level = gpio_get_value(GPIO_OLED_DET); + + dev_info(&lcd->ld->dev, "%s, GPIO_OLED_DET is %s\n", __func__, oled_det_level ? "high" : "low"); + + if (!oled_det_level) { + if (lcd->oled_detection_count < 3) { + getnstimeofday(&ts); + rtc_time_to_tm(ts.tv_sec, &tm); + sprintf(name, "%s%02d-%02d_%02d:%02d:%02d_%02d", + "/sdcard/", tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, lcd->oled_detection_count); + fp = filp_open(name, O_CREAT, S_IRWXU | S_IRWXG | S_IRWXO); + + if (IS_ERR_OR_NULL(fp)) + dev_info(&lcd->ld->dev, "fail to create vgh detection log file, %s\n", name); + + schedule_delayed_work(&lcd->oled_detection, msecs_to_jiffies(10)); + lcd->oled_detection_count++; + } else { + dev_info(&lcd->ld->dev, "VGH IS NOT OK! LCD SMASH!!!\n"); + getnstimeofday(&ts); + rtc_time_to_tm(ts.tv_sec, &tm); + sprintf(name, "%s%02d-%02d_%02d:%02d:%02d_POWEROFF", + "/sdcard/", tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); + fp = filp_open(name, O_CREAT, S_IRWXU | S_IRWXG | S_IRWXO); + + if (IS_ERR_OR_NULL(fp)) + dev_info(&lcd->ld->dev, "fail to create vgh detection log file, %s\n", name); + + sys_sync(); + kernel_power_off(); + } + } else + dev_info(&lcd->ld->dev, "VGH IS OK\n"); + +} + +static irqreturn_t oled_detection_int(int irq, void *_lcd) +{ + struct lcd_info *lcd = _lcd; + + dev_info(&lcd->ld->dev, "\t\t%s\n", __func__); + + schedule_delayed_work(&lcd->oled_detection, msecs_to_jiffies(10)); + + return IRQ_HANDLED; +} +#endif + +static int _s6evr02_write(struct lcd_info *lcd, const unsigned char *seq, int len) +{ + int size; + const unsigned char *wbuf; + int ret = 0; + + if (!lcd->connected) + return 0; + + mutex_lock(&lcd->lock); + + size = len; + wbuf = seq; + + if (size == 1) + ret = lcd->dsim->ops->cmd_write(lcd->dsim, DCS_WR_NO_PARA, wbuf[0], 0); + else if (size == 2) + ret = lcd->dsim->ops->cmd_write(lcd->dsim, DCS_WR_1_PARA, wbuf[0], wbuf[1]); + else + ret = lcd->dsim->ops->cmd_write(lcd->dsim, DCS_LONG_WR, (unsigned int)wbuf, size); + + mutex_unlock(&lcd->lock); + + return ret; +} + +static int s6evr02_write(struct lcd_info *lcd, const unsigned char *seq, int len) +{ + int ret = 0; + int retry_cnt = 1; + +retry: + ret = _s6evr02_write(lcd, seq, len); + if (!ret) { + if (retry_cnt) { + dev_dbg(&lcd->ld->dev, "%s :: retry: %d\n", __func__, retry_cnt); + retry_cnt--; + goto retry; + } else + dev_dbg(&lcd->ld->dev, "%s :: 0x%02x\n", __func__, seq[1]); + } + + return ret; +} + +static int _s6evr02_read(struct lcd_info *lcd, const u8 addr, u16 count, u8 *buf) +{ + int ret = 0; + + if (!lcd->connected) + return ret; + + mutex_lock(&lcd->lock); + + if (lcd->dsim->ops->cmd_read) + ret = lcd->dsim->ops->cmd_read(lcd->dsim, addr, count, buf); + + mutex_unlock(&lcd->lock); + + return ret; +} + +static int s6evr02_read(struct lcd_info *lcd, const u8 addr, u16 count, u8 *buf, u8 retry_cnt) +{ + int ret = 0; + +retry: + ret = _s6evr02_read(lcd, addr, count, buf); + if (!ret) { + if (retry_cnt) { + dev_dbg(&lcd->ld->dev, "%s :: retry: %d\n", __func__, retry_cnt); + retry_cnt--; + goto retry; + } else + dev_dbg(&lcd->ld->dev, "%s :: 0x%02x\n", __func__, addr); + } + + return ret; +} + +static int get_backlight_level_from_brightness(int brightness) +{ + int backlightlevel; + + /* brightness setting from platform is from 0 to 255 + * But in this driver, brightness is only supported from 0 to 24 */ + + switch (brightness) { + case 0 ... 29: + backlightlevel = GAMMA_20CD; + break; + case 30 ... 39: + backlightlevel = GAMMA_30CD; + break; + case 40 ... 49: + backlightlevel = GAMMA_40CD; + break; + case 50 ... 59: + backlightlevel = GAMMA_50CD; + break; + case 60 ... 69: + backlightlevel = GAMMA_60CD; + break; + case 70 ... 79: + backlightlevel = GAMMA_70CD; + break; + case 80 ... 89: + backlightlevel = GAMMA_80CD; + break; + case 90 ... 99: + backlightlevel = GAMMA_90CD; + break; + case 100 ... 101: + backlightlevel = GAMMA_100CD; + break; + case 102 ... 103: + backlightlevel = GAMMA_102CD; + break; + case 104 ... 105: + backlightlevel = GAMMA_104CD; + break; + case 106 ... 107: + backlightlevel = GAMMA_106CD; + break; + case 108 ... 109: + backlightlevel = GAMMA_108CD; + break; + case 110 ... 119: + backlightlevel = GAMMA_110CD; + break; + case 120 ... 129: + backlightlevel = GAMMA_120CD; + break; + case 130 ... 139: + backlightlevel = GAMMA_130CD; + break; + case 140 ... 149: + backlightlevel = GAMMA_140CD; + break; + case 150 ... 159: + backlightlevel = GAMMA_150CD; + break; + case 160 ... 169: + backlightlevel = GAMMA_160CD; + break; + case 170 ... 179: + backlightlevel = GAMMA_170CD; + break; + case 180 ... 181: + backlightlevel = GAMMA_180CD; + break; + case 182 ... 183: + backlightlevel = GAMMA_182CD; + break; + case 184 ... 185: + backlightlevel = GAMMA_184CD; + break; + case 186 ... 187: + backlightlevel = GAMMA_186CD; + break; + case 188 ... 189: + backlightlevel = GAMMA_188CD; + break; + case 190 ... 199: + backlightlevel = GAMMA_190CD; + break; + case 200 ... 209: + backlightlevel = GAMMA_200CD; + break; + case 210 ... 219: + backlightlevel = GAMMA_210CD; + break; + case 220 ... 229: + backlightlevel = GAMMA_220CD; + break; + case 230 ... 239: + backlightlevel = GAMMA_230CD; + break; + case 240 ... 249: + backlightlevel = GAMMA_240CD; + break; + case 250 ... 254: + backlightlevel = GAMMA_250CD; + break; + case 255: + backlightlevel = GAMMA_300CD; + break; + default: + backlightlevel = DEFAULT_GAMMA_LEVEL; + break; + } + return backlightlevel; +} + +#ifdef SMART_DIMMING +static int s6evr02_aid_parameter_ctl(struct lcd_info *lcd, u8 force) +{ + if ((aid_command_table[lcd->bl][0] != aid_command_table[lcd->current_bl][0]) || force) + s6evr02_write(lcd, lcd->aor[lcd->bl], AID_PARAM_SIZE); + + return 0; +} +#endif + +static int s6evr02_gamma_ctl(struct lcd_info *lcd) +{ + /* s6evr02_write(lcd, SEQ_APPLY_LEVEL_2_KEY, ARRAY_SIZE(SEQ_APPLY_LEVEL_2_KEY)); */ + s6evr02_write(lcd, lcd->gamma_table[lcd->bl], GAMMA_PARAM_SIZE); + s6evr02_write(lcd, SEQ_GAMMA_UPDATE, ARRAY_SIZE(SEQ_GAMMA_UPDATE)); + /* s6evr02_write(lcd, SEQ_BRIGHTNESS_CONTROL_ON, ARRAY_SIZE(SEQ_BRIGHTNESS_CONTROL_ON)); */ + + return 0; +} + +static int s6evr02_set_acl(struct lcd_info *lcd, u8 force) +{ + int ret = 0, level = 0; + u32 candela = candela_table[lcd->bl]; + + switch (candela) { + case 0 ... 29: + level = ACL_STATUS_0P; + break; + case 30 ... 39: + level = ACL_STATUS_33P; + break; + default: + level = ACL_STATUS_40P; + break; + } + + if ((!lcd->acl_enable) || (lcd->auto_brightness >= 5)) + level = ACL_STATUS_0P; + + if (force || lcd->current_acl != ACL_CUTOFF_TABLE[level][1]) { + ret = s6evr02_write(lcd, ACL_CUTOFF_TABLE[level], ACL_PARAM_SIZE); + lcd->current_acl = ACL_CUTOFF_TABLE[level][1]; + dev_dbg(&lcd->ld->dev, "current_acl = %d\n", lcd->current_acl); + } + + if (ret) + ret = -EPERM; + + return ret; +} + +static int s6evr02_set_elvss(struct lcd_info *lcd, u8 force) +{ + int ret = 0, elvss_level = 0; + u32 candela = candela_table[lcd->bl]; + + switch (candela) { + case 0 ... 49: + elvss_level = ELVSS_STATUS_20; + break; + case 50 ... 79: + elvss_level = ELVSS_STATUS_50; + break; + case 80 ... 99: + elvss_level = ELVSS_STATUS_80; + break; + case 100 ... 109: + elvss_level = ELVSS_STATUS_100; + break; + case 110 ... 119: + elvss_level = ELVSS_STATUS_110; + break; + case 120 ... 129: + elvss_level = ELVSS_STATUS_120; + break; + case 130 ... 139: + elvss_level = ELVSS_STATUS_130; + break; + case 140 ... 149: + elvss_level = ELVSS_STATUS_140; + break; + case 150 ... 159: + elvss_level = ELVSS_STATUS_150; + break; + case 160 ... 169: + elvss_level = ELVSS_STATUS_160; + break; + case 170 ... 179: + elvss_level = ELVSS_STATUS_170; + break; + case 180 ... 189: + elvss_level = ELVSS_STATUS_180; + break; + case 190 ... 199: + elvss_level = ELVSS_STATUS_190; + break; + case 200 ... 209: + elvss_level = ELVSS_STATUS_200; + break; + case 210 ... 219: + elvss_level = ELVSS_STATUS_210; + break; + case 220 ... 229: + elvss_level = ELVSS_STATUS_220; + break; + case 230 ... 239: + elvss_level = ELVSS_STATUS_230; + break; + case 240 ... 250: + elvss_level = ELVSS_STATUS_240; + break; + case 299: + elvss_level = ELVSS_STATUS_300; + break; + } + + if (force || lcd->current_elvss != lcd->elvss_table[elvss_level][2]) { + ret = s6evr02_write(lcd, lcd->elvss_table[elvss_level], ELVSS_PARAM_SIZE); + lcd->current_elvss = lcd->elvss_table[elvss_level][2]; + } + + dev_dbg(&lcd->ld->dev, "elvss = %x\n", lcd->elvss_table[elvss_level][2]); + + if (ret) { + ret = -EPERM; + goto elvss_err; + } + +elvss_err: + return ret; +} + +static int init_elvss_table(struct lcd_info *lcd) +{ + int i, ret = 0; +#ifdef SMART_DIMMING_DEBUG + int j; +#endif + + lcd->elvss_table = kzalloc(ELVSS_STATUS_MAX * sizeof(u8 *), GFP_KERNEL); + + if (IS_ERR_OR_NULL(lcd->elvss_table)) { + pr_err("failed to allocate elvss table\n"); + ret = -ENOMEM; + goto err_alloc_elvss_table; + } + + for (i = 0; i < ELVSS_STATUS_MAX; i++) { + lcd->elvss_table[i] = kzalloc(ELVSS_PARAM_SIZE * sizeof(u8), GFP_KERNEL); + if (IS_ERR_OR_NULL(lcd->elvss_table[i])) { + pr_err("failed to allocate elvss\n"); + ret = -ENOMEM; + goto err_alloc_elvss; + } + lcd->elvss_table[i][0] = 0xB6; + lcd->elvss_table[i][1] = 0x08; + lcd->elvss_table[i][2] = ELVSS_CONTROL_TABLE[i][2]; + } + +#ifdef SMART_DIMMING_DEBUG + for (i = 0; i < ELVSS_STATUS_MAX; i++) { + for (j = 0; j < ELVSS_PARAM_SIZE; j++) + printk("0x%02x, ", lcd->elvss_table[i][j]); + printk("\n"); + } +#endif + + return 0; + +err_alloc_elvss: + while (i > 0) { + kfree(lcd->elvss_table[i-1]); + i--; + } + kfree(lcd->elvss_table); +err_alloc_elvss_table: + return ret; +} + +#ifdef SMART_DIMMING +static int init_gamma_table(struct lcd_info *lcd , const u8 *mtp_data) +{ + int i, ret = 0; + + lcd->gamma_table = kzalloc(GAMMA_MAX * sizeof(u8 *), GFP_KERNEL); + if (IS_ERR_OR_NULL(lcd->gamma_table)) { + pr_err("failed to allocate gamma table\n"); + ret = -ENOMEM; + goto err_alloc_gamma_table; + } + + for (i = 0; i < GAMMA_MAX; i++) { + lcd->gamma_table[i] = kzalloc(GAMMA_PARAM_SIZE * sizeof(u8), GFP_KERNEL); + if (IS_ERR_OR_NULL(lcd->gamma_table[i])) { + pr_err("failed to allocate gamma\n"); + ret = -ENOMEM; + goto err_alloc_gamma; + } + lcd->gamma_table[i][0] = 0xCA; + } + + for (i = 0; i < GAMMA_MAX; i++) { + if (candela_table[i] == 20) + calc_gamma_table_210_20_100(&lcd->smart, aid_candela_table[i], &lcd->gamma_table[i][1], G_21, mtp_data); + else if (candela_table[i] == 30) + calc_gamma_table_210_20_100(&lcd->smart, aid_candela_table[i], &lcd->gamma_table[i][1], G_213, mtp_data); + else if (candela_table[i] == 40) + calc_gamma_table_210_20_100(&lcd->smart, aid_candela_table[i], &lcd->gamma_table[i][1], G_215, mtp_data); + else if (candela_table[i] == 50) + calc_gamma_table_210_20_100(&lcd->smart, aid_candela_table[i], &lcd->gamma_table[i][1], G_218, mtp_data); + else if (candela_table[i] == 60) + calc_gamma_table_210_20_100(&lcd->smart, aid_candela_table[i], &lcd->gamma_table[i][1], G_22, mtp_data); + else if (candela_table[i] == 70) + calc_gamma_table_210_20_100(&lcd->smart, aid_candela_table[i], &lcd->gamma_table[i][1], G_222, mtp_data); + else if (candela_table[i] == 80) + calc_gamma_table_210_20_100(&lcd->smart, aid_candela_table[i], &lcd->gamma_table[i][1], G_223, mtp_data); + else if (candela_table[i] == 90) + calc_gamma_table_210_20_100(&lcd->smart, aid_candela_table[i], &lcd->gamma_table[i][1], G_224, mtp_data); + else if (candela_table[i] == 100) + calc_gamma_table_210_20_100(&lcd->smart, aid_candela_table[i], &lcd->gamma_table[i][1], G_225, mtp_data); + else if (candela_table[i] == 102) + calc_gamma_table(&lcd->smart, aid_candela_table[i], &lcd->gamma_table[i][1], G_224, mtp_data); + else if (candela_table[i] == 104) + calc_gamma_table(&lcd->smart, aid_candela_table[i], &lcd->gamma_table[i][1], G_223, mtp_data); + else if (candela_table[i] == 106) + calc_gamma_table(&lcd->smart, aid_candela_table[i], &lcd->gamma_table[i][1], G_222, mtp_data); + else if (candela_table[i] == 108) + calc_gamma_table(&lcd->smart, aid_candela_table[i], &lcd->gamma_table[i][1], G_221, mtp_data); + else if (candela_table[i] == 182) + calc_gamma_table(&lcd->smart, aid_candela_table[i], &lcd->gamma_table[i][1], G_221, mtp_data); + else if (candela_table[i] == 184) + calc_gamma_table(&lcd->smart, aid_candela_table[i], &lcd->gamma_table[i][1], G_222, mtp_data); + else if (candela_table[i] == 186) + calc_gamma_table(&lcd->smart, aid_candela_table[i], &lcd->gamma_table[i][1], G_223, mtp_data); + else if (candela_table[i] == 188) + calc_gamma_table(&lcd->smart, aid_candela_table[i], &lcd->gamma_table[i][1], G_224, mtp_data); + else if (candela_table[i] == 190) + calc_gamma_table_215_190(&lcd->smart, aid_candela_table[i], &lcd->gamma_table[i][1], G_225, mtp_data); + else if ((candela_table[i] > 190) && (candela_table[i] < MAX_GAMMA-1)) + calc_gamma_table(&lcd->smart, aid_candela_table[i], &lcd->gamma_table[i][1], G_225 , mtp_data); + else if (candela_table[i] == MAX_GAMMA-1) + calc_gamma_table(&lcd->smart, aid_candela_table[i], &lcd->gamma_table[i][1], G_22, mtp_data); + else + calc_gamma_table(&lcd->smart, aid_candela_table[i], &lcd->gamma_table[i][1], G_22, mtp_data); + } + + +#ifdef SMART_DIMMING_DEBUG + for (i = 0; i < GAMMA_MAX; i++) { + for (j = 0; j < GAMMA_PARAM_SIZE; j++) + printk("%d,", lcd->gamma_table[i][j]); + printk("\n"); + } +#endif + return 0; + +err_alloc_gamma: + while (i > 0) { + kfree(lcd->gamma_table[i-1]); + i--; + } + kfree(lcd->gamma_table); +err_alloc_gamma_table: + return ret; +} + +static int init_aid_dimming_table(struct lcd_info *lcd) +{ + unsigned int i, j, c; + u16 reverse_seq[] = {0, 28, 29, 30, 31, 32, 33, 25, 26, 27, 22, 23, 24, 19, 20, 21, 16, 17, 18, 13, 14, 15, 10, 11, 12, 7, 8, 9, 4, 5, 6, 1, 2, 3}; + u16 temp[GAMMA_PARAM_SIZE]; + + for (i = 0; i < ARRAY_SIZE(aid_rgb_fix_table); i++) { + j = (aid_rgb_fix_table[i].gray * 3 + aid_rgb_fix_table[i].rgb) + 1; + c = lcd->gamma_table[aid_rgb_fix_table[i].candela_idx][j] + aid_rgb_fix_table[i].offset; + if (c > 0xff) + lcd->gamma_table[aid_rgb_fix_table[i].candela_idx][j] = 0xff; + else + lcd->gamma_table[aid_rgb_fix_table[i].candela_idx][j] += aid_rgb_fix_table[i].offset; + } + + for (i = 0; i < GAMMA_MAX; i++) { + memcpy(lcd->aor[i], SEQ_AOR_CONTROL, AID_PARAM_SIZE); + lcd->aor[i][0x01] = aid_command_table[i][0]; + } + +#ifdef SMART_DIMMING_DEBUG + for (i = 0; i < GAMMA_MAX; i++) { + for (j = 0; j < GAMMA_PARAM_SIZE; j++) + printk("%d,", lcd->gamma_table[i][j]); + printk("\n"); + } + printk("\n"); +#endif + + for (i = 0; i < GAMMA_MAX; i++) { + for (j = 0; j < GAMMA_PARAM_SIZE; j++) + temp[j] = lcd->gamma_table[i][reverse_seq[j]]; + + for (j = 0; j < GAMMA_PARAM_SIZE; j++) + lcd->gamma_table[i][j] = temp[j]; + + for (c = CI_RED; c < CI_MAX ; c++) + lcd->gamma_table[i][31+c] = lcd->smart.default_gamma[30+c]; + } + +#ifdef SMART_DIMMING_DEBUG + for (i = 0; i < GAMMA_MAX; i++) { + for (j = 0; j < GAMMA_PARAM_SIZE; j++) + printk("%d,", lcd->gamma_table[i][j]); + printk("\n"); + } +#endif + + return 0; +} +#endif + +static int update_brightness(struct lcd_info *lcd, u8 force) +{ + u32 brightness; + + mutex_lock(&lcd->bl_lock); + + brightness = lcd->bd->props.brightness; + + if (unlikely(!lcd->auto_brightness && brightness > 250)) + brightness = 250; + + lcd->bl = get_backlight_level_from_brightness(brightness); + + if ((force) || ((lcd->ldi_enable) && (lcd->current_bl != lcd->bl))) { + s6evr02_gamma_ctl(lcd); + + s6evr02_aid_parameter_ctl(lcd, force); + + s6evr02_set_acl(lcd, force); + + s6evr02_set_elvss(lcd, force); + + lcd->current_bl = lcd->bl; + + dev_info(&lcd->ld->dev, "brightness=%d, bl=%d, candela=%d\n", brightness, lcd->bl, candela_table[lcd->bl]); + } + + mutex_unlock(&lcd->bl_lock); + + return 0; +} + +static int s6evr02_ldi_init(struct lcd_info *lcd) +{ + int ret = 0; + s6evr02_write(lcd, SEQ_APPLY_LEVEL_2_KEY, ARRAY_SIZE(SEQ_APPLY_LEVEL_2_KEY)); + s6evr02_write(lcd, SEQ_SLEEP_OUT, ARRAY_SIZE(SEQ_SLEEP_OUT)); + + if (lcd->id[1] == 0x10) { /* for S.LSI UB(YOUM) */ + msleep(20); + s6evr02_write(lcd, SEQ_GAMMA_CONDITION_SET_UB, ARRAY_SIZE(SEQ_GAMMA_CONDITION_SET_UB)); + s6evr02_write(lcd, SEQ_GAMMA_UPDATE, ARRAY_SIZE(SEQ_GAMMA_UPDATE)); + s6evr02_write(lcd, SEQ_BRIGHTNESS_CONTROL_ON, ARRAY_SIZE(SEQ_BRIGHTNESS_CONTROL_ON)); + s6evr02_write(lcd, SEQ_AOR_CONTROL, ARRAY_SIZE(SEQ_AOR_CONTROL)); + s6evr02_write(lcd, SEQ_ELVSS_CONDITION_SET_UB, ARRAY_SIZE(SEQ_ELVSS_CONDITION_SET_UB)); + s6evr02_write(lcd, SEQ_ACL_OFF, ARRAY_SIZE(SEQ_ACL_OFF)); + } else { + msleep(20); + s6evr02_gamma_ctl(lcd); + s6evr02_write(lcd, SEQ_BRIGHTNESS_CONTROL_ON, ARRAY_SIZE(SEQ_BRIGHTNESS_CONTROL_ON)); + s6evr02_write(lcd, SEQ_AOR_CONTROL, ARRAY_SIZE(SEQ_AOR_CONTROL)); + s6evr02_write(lcd, SEQ_ELVSS_CONDITION_SET, ARRAY_SIZE(SEQ_ELVSS_CONDITION_SET)); + s6evr02_write(lcd, SEQ_ACL_OFF, ARRAY_SIZE(SEQ_ACL_OFF)); + } + + return ret; +} + +static int s6evr02_ldi_enable(struct lcd_info *lcd) +{ + int ret = 0; + + s6evr02_write(lcd, SEQ_DISPLAY_ON, ARRAY_SIZE(SEQ_DISPLAY_ON)); + + return ret; +} + +static int s6evr02_ldi_disable(struct lcd_info *lcd) +{ + int ret = 0; + + s6evr02_write(lcd, SEQ_DISPLAY_OFF, ARRAY_SIZE(SEQ_DISPLAY_OFF)); + + msleep(35); + + s6evr02_write(lcd, SEQ_SLEEP_IN, ARRAY_SIZE(SEQ_SLEEP_IN)); + + msleep(100); + + return ret; +} + +static int s6evr02_power_on(struct lcd_info *lcd) +{ + int ret = 0; + struct lcd_platform_data *pd = NULL; + pd = lcd->lcd_pd; + + dev_info(&lcd->ld->dev, "%s\n", __func__); + + ret = s6evr02_ldi_init(lcd); + if (ret) { + dev_err(&lcd->ld->dev, "failed to initialize ldi.\n"); + goto err; + } + + msleep(120); + + ret = s6evr02_ldi_enable(lcd); + if (ret) { + dev_err(&lcd->ld->dev, "failed to enable ldi.\n"); + goto err; + } + + lcd->ldi_enable = 1; + + update_brightness(lcd, 1); +err: + return ret; +} + +static int s6evr02_power_off(struct lcd_info *lcd) +{ + int ret = 0; + + dev_info(&lcd->ld->dev, "%s\n", __func__); + + lcd->ldi_enable = 0; + + ret = s6evr02_ldi_disable(lcd); + + msleep(135); + + return ret; +} + +static int s6evr02_power(struct lcd_info *lcd, int power) +{ + int ret = 0; + + if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->power)) + ret = s6evr02_power_on(lcd); + else if (!POWER_IS_ON(power) && POWER_IS_ON(lcd->power)) + ret = s6evr02_power_off(lcd); + + if (!ret) + lcd->power = power; + + return ret; +} + +static int s6evr02_set_power(struct lcd_device *ld, int power) +{ + struct lcd_info *lcd = lcd_get_data(ld); + + if (power != FB_BLANK_UNBLANK && power != FB_BLANK_POWERDOWN && + power != FB_BLANK_NORMAL) { + dev_err(&lcd->ld->dev, "power value should be 0, 1 or 4.\n"); + return -EINVAL; + } + + return s6evr02_power(lcd, power); +} + +static int s6evr02_get_power(struct lcd_device *ld) +{ + struct lcd_info *lcd = lcd_get_data(ld); + + return lcd->power; +} + + +static int s6evr02_set_brightness(struct backlight_device *bd) +{ + int ret = 0; + int brightness = bd->props.brightness; + struct lcd_info *lcd = bl_get_data(bd); + + /* dev_info(&lcd->ld->dev, "%s: brightness=%d\n", __func__, brightness); */ + + if (brightness < MIN_BRIGHTNESS || + brightness > bd->props.max_brightness) { + dev_err(&bd->dev, "lcd brightness should be %d to %d. now %d\n", + MIN_BRIGHTNESS, MAX_BRIGHTNESS, brightness); + return -EINVAL; + } + + if (lcd->ldi_enable) { + ret = update_brightness(lcd, 0); + if (ret < 0) { + dev_err(lcd->dev, "err in %s\n", __func__); + return -EINVAL; + } + } + + return ret; +} + +static int s6evr02_get_brightness(struct backlight_device *bd) +{ + struct lcd_info *lcd = bl_get_data(bd); + + return candela_table[lcd->bl]; +} + +static int s6evr02_check_fb(struct lcd_device *ld, struct fb_info *fb) +{ + struct s3cfb_window *win = fb->par; + struct lcd_info *lcd = lcd_get_data(ld); + + dev_info(&lcd->ld->dev, "%s, fb%d\n", __func__, win->id); + + return 0; +} + +static struct lcd_ops s6evr02_lcd_ops = { + .set_power = s6evr02_set_power, + .get_power = s6evr02_get_power, + .check_fb = s6evr02_check_fb, +}; + +static const struct backlight_ops s6evr02_backlight_ops = { + .get_brightness = s6evr02_get_brightness, + .update_status = s6evr02_set_brightness, +}; + +static ssize_t power_reduce_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct lcd_info *lcd = dev_get_drvdata(dev); + char temp[3]; + + sprintf(temp, "%d\n", lcd->acl_enable); + strcpy(buf, temp); + + return strlen(buf); +} + +static ssize_t power_reduce_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + struct lcd_info *lcd = dev_get_drvdata(dev); + int value; + int rc; + + rc = strict_strtoul(buf, (unsigned int)0, (unsigned long *)&value); + if (rc < 0) + return rc; + else { + if (lcd->acl_enable != value) { + dev_info(dev, "%s - %d, %d\n", __func__, lcd->acl_enable, value); + mutex_lock(&lcd->bl_lock); + lcd->acl_enable = value; + mutex_unlock(&lcd->bl_lock); + if (lcd->ldi_enable) + update_brightness(lcd, 1); + } + } + return size; +} + +static DEVICE_ATTR(power_reduce, 0664, power_reduce_show, power_reduce_store); + +static ssize_t lcd_type_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + char temp[15]; + + sprintf(temp, "SMD_AMS555HBxx\n"); + strcat(buf, temp); + return strlen(buf); +} + +static DEVICE_ATTR(lcd_type, 0444, lcd_type_show, NULL); + +static ssize_t window_type_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct lcd_info *lcd = dev_get_drvdata(dev); + char temp[15]; + + sprintf(temp, "%x %x %x\n", lcd->id[0], lcd->id[1], lcd->id[2]); + + strcat(buf, temp); + return strlen(buf); +} + +static DEVICE_ATTR(window_type, 0444, window_type_show, NULL); + +static ssize_t gamma_table_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct lcd_info *lcd = dev_get_drvdata(dev); + int i, j; + + for (i = 0; i < GAMMA_MAX; i++) { + for (j = 0; j < GAMMA_PARAM_SIZE; j++) + printk("0x%02x, ", lcd->gamma_table[i][j]); + printk("\n"); + } + + for (i = 0; i < ELVSS_STATUS_MAX; i++) { + for (j = 0; j < ELVSS_PARAM_SIZE; j++) + printk("0x%02x, ", lcd->elvss_table[i][j]); + printk("\n"); + } + + return strlen(buf); +} +static DEVICE_ATTR(gamma_table, 0444, gamma_table_show, NULL); + +static ssize_t auto_brightness_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct lcd_info *lcd = dev_get_drvdata(dev); + char temp[3]; + + sprintf(temp, "%d\n", lcd->auto_brightness); + strcpy(buf, temp); + + return strlen(buf); +} + +static ssize_t auto_brightness_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + struct lcd_info *lcd = dev_get_drvdata(dev); + int value; + int rc; + + rc = strict_strtoul(buf, (unsigned int)0, (unsigned long *)&value); + if (rc < 0) + return rc; + else { + if (lcd->auto_brightness != value) { + dev_info(dev, "%s - %d, %d\n", __func__, lcd->auto_brightness, value); + mutex_lock(&lcd->bl_lock); + lcd->auto_brightness = value; + mutex_unlock(&lcd->bl_lock); + if (lcd->ldi_enable) + update_brightness(lcd, 1); + } + } + return size; +} + +static DEVICE_ATTR(auto_brightness, 0644, auto_brightness_show, auto_brightness_store); + +#ifdef CONFIG_HAS_EARLYSUSPEND +static struct lcd_info *g_lcd; + +void s6evr02_early_suspend(void) +{ + struct lcd_info *lcd = g_lcd; + + set_dsim_lcd_enabled(0); + + dev_info(&lcd->ld->dev, "+%s\n", __func__); + +#if defined(GPIO_ERR_FG) + disable_irq(lcd->irq); + gpio_request(GPIO_ERR_FG, "OLED_DET"); + s3c_gpio_cfgpin(GPIO_ERR_FG, S3C_GPIO_OUTPUT); + s3c_gpio_setpull(GPIO_ERR_FG, S3C_GPIO_PULL_NONE); + gpio_direction_output(GPIO_ERR_FG, GPIO_LEVEL_LOW); + gpio_free(GPIO_ERR_FG); +#endif +#if defined(GPIO_OLED_DET) + disable_irq(gpio_to_irq(GPIO_OLED_DET)); + gpio_request(GPIO_OLED_DET, "OLED_DET"); + s3c_gpio_cfgpin(GPIO_OLED_DET, S3C_GPIO_OUTPUT); + s3c_gpio_setpull(GPIO_OLED_DET, S3C_GPIO_PULL_NONE); + gpio_direction_output(GPIO_OLED_DET, GPIO_LEVEL_LOW); + gpio_free(GPIO_OLED_DET); +#endif + + s6evr02_power(lcd, FB_BLANK_POWERDOWN); + dev_info(&lcd->ld->dev, "-%s\n", __func__); + + return ; +} + +void s6evr02_late_resume(void) +{ + struct lcd_info *lcd = g_lcd; + + dev_info(&lcd->ld->dev, "+%s\n", __func__); + s6evr02_power(lcd, FB_BLANK_UNBLANK); + +#if defined(GPIO_ERR_FG) + s3c_gpio_cfgpin(GPIO_ERR_FG, S3C_GPIO_SFN(0xf)); + s3c_gpio_setpull(GPIO_ERR_FG, S3C_GPIO_PULL_NONE); + enable_irq(lcd->irq); +#endif +#if defined(GPIO_OLED_DET) + s3c_gpio_cfgpin(GPIO_OLED_DET, S3C_GPIO_SFN(0xf)); + s3c_gpio_setpull(GPIO_OLED_DET, S3C_GPIO_PULL_NONE); + enable_irq(gpio_to_irq(GPIO_OLED_DET)); +#endif + + dev_info(&lcd->ld->dev, "-%s\n", __func__); + + set_dsim_lcd_enabled(1); + + return ; +} +#endif + + +static void s6evr02_read_id(struct lcd_info *lcd, u8 *buf) +{ + int ret = 0; + + ret = s6evr02_read(lcd, LDI_ID_REG, LDI_ID_LEN, buf, 2); + if (!ret) { + lcd->connected = 0; + dev_info(&lcd->ld->dev, "panel is not connected well\n"); + } +} + +#ifdef SMART_DIMMING +static int s6evr02_read_mtp(struct lcd_info *lcd, u8 *mtp_data) +{ + int ret; + s6evr02_write(lcd, SEQ_APPLY_LEVEL_2_KEY, ARRAY_SIZE(SEQ_APPLY_LEVEL_2_KEY)); + s6evr02_write(lcd, SEQ_APPLY_LEVEL_3_KEY, ARRAY_SIZE(SEQ_APPLY_LEVEL_3_KEY)); + msleep(20); /* one frame delay befor reading MTP. */ + ret = s6evr02_read(lcd, LDI_MTP_ADDR, LDI_MTP_LENGTH, mtp_data, 1); + s6evr02_write(lcd, SEQ_APPLY_LEVEL_3_KEY_DISABLE, ARRAY_SIZE(SEQ_APPLY_LEVEL_3_KEY_DISABLE)); + /* s6evr02_write(lcd, SEQ_APPLY_LEVEL_2_KEY_DISABLE, ARRAY_SIZE(SEQ_APPLY_LEVEL_2_KEY_DISABLE)); */ + + return ret; +} +#endif + +static int s6evr02_probe(struct device *dev) +{ + int ret = 0, i; + struct lcd_info *lcd; + +#ifdef SMART_DIMMING + u8 mtp_data[LDI_MTP_LENGTH] = {0,}; +#endif + + lcd = kzalloc(sizeof(struct lcd_info), GFP_KERNEL); + if (!lcd) { + pr_err("failed to allocate for lcd\n"); + ret = -ENOMEM; + goto err_alloc; + } + + g_lcd = lcd; + + lcd->ld = lcd_device_register("panel", dev, lcd, &s6evr02_lcd_ops); + if (IS_ERR(lcd->ld)) { + pr_err("failed to register lcd device\n"); + ret = PTR_ERR(lcd->ld); + goto out_free_lcd; + } + + lcd->bd = backlight_device_register("panel", dev, lcd, &s6evr02_backlight_ops, NULL); + if (IS_ERR(lcd->bd)) { + pr_err("failed to register backlight device\n"); + ret = PTR_ERR(lcd->bd); + goto out_free_backlight; + } + + lcd->dev = dev; + lcd->dsim = (struct dsim_global *)dev_get_drvdata(dev->parent); + lcd->bd->props.max_brightness = MAX_BRIGHTNESS; + lcd->bd->props.brightness = DEFAULT_BRIGHTNESS; + lcd->bl = DEFAULT_GAMMA_LEVEL; + lcd->current_bl = lcd->bl; + lcd->acl_enable = 0; + lcd->current_acl = 0; + lcd->power = FB_BLANK_UNBLANK; + lcd->ldi_enable = 1; + lcd->connected = 1; + lcd->auto_brightness = 0; + + ret = device_create_file(&lcd->ld->dev, &dev_attr_power_reduce); + if (ret < 0) + dev_err(&lcd->ld->dev, "failed to add sysfs entries, %d\n", __LINE__); + + ret = device_create_file(&lcd->ld->dev, &dev_attr_lcd_type); + if (ret < 0) + dev_err(&lcd->ld->dev, "failed to add sysfs entries, %d\n", __LINE__); + + ret = device_create_file(&lcd->ld->dev, &dev_attr_window_type); + if (ret < 0) + dev_err(&lcd->ld->dev, "failed to add sysfs entries, %d\n", __LINE__); + + ret = device_create_file(&lcd->ld->dev, &dev_attr_gamma_table); + if (ret < 0) + dev_err(&lcd->ld->dev, "failed to add sysfs entries, %d\n", __LINE__); + + ret = device_create_file(&lcd->bd->dev, &dev_attr_auto_brightness); + if (ret < 0) + dev_err(&lcd->ld->dev, "failed to add sysfs entries, %d\n", __LINE__); + + dev_set_drvdata(dev, lcd); + + mutex_init(&lcd->lock); + mutex_init(&lcd->bl_lock); + + s6evr02_read_id(lcd, lcd->id); + + dev_info(&lcd->ld->dev, "ID: %x, %x, %x\n", lcd->id[0], lcd->id[1], lcd->id[2]); + + dev_info(&lcd->ld->dev, "%s lcd panel driver has been probed.\n", dev_name(dev)); + +#ifdef SMART_DIMMING + for (i = 0; i < LDI_ID_LEN; i++) { + lcd->smart.panelid[i] = lcd->id[i]; + } + + init_table_info(&lcd->smart); + + ret = s6evr02_read_mtp(lcd, mtp_data); +/* + for (i = 0; i < LDI_MTP_LENGTH ; i++) + printk(" %dth mtp value is %x\n", i, mtp_data[i]); +*/ + if (!ret) { + printk(KERN_ERR "[LCD:ERROR] : %s read mtp failed\n", __func__); + /*return -EPERM;*/ + } + + calc_voltage_table(&lcd->smart, mtp_data); + + ret = init_elvss_table(lcd); + ret += init_gamma_table(lcd, mtp_data); + ret += init_aid_dimming_table(lcd); + + if (ret) + printk(KERN_ERR "gamma table generation is failed\n"); + + + update_brightness(lcd, 1); +#endif + +#if defined(GPIO_ERR_FG) + if (lcd->connected) { + INIT_DELAYED_WORK(&lcd->err_fg_detection, err_fg_detection_work); + + lcd->irq = gpio_to_irq(GPIO_ERR_FG); + + irq_set_irq_type(lcd->irq, IRQ_TYPE_EDGE_RISING); + + s3c_gpio_cfgpin(GPIO_ERR_FG, S3C_GPIO_SFN(0xf)); + s3c_gpio_setpull(GPIO_ERR_FG, S3C_GPIO_PULL_NONE); + + if (request_irq(lcd->irq, err_fg_detection_int, + IRQF_TRIGGER_RISING, "err_fg_detection", lcd)) + pr_err("failed to reqeust irq. %d\n", lcd->irq); + } +#endif +#if defined(GPIO_OLED_DET) + if (lcd->connected) { + INIT_DELAYED_WORK(&lcd->oled_detection, oled_detection_work); + + s3c_gpio_cfgpin(GPIO_OLED_DET, S3C_GPIO_SFN(0xf)); + s3c_gpio_setpull(GPIO_OLED_DET, S3C_GPIO_PULL_NONE); + + if (request_irq(gpio_to_irq(GPIO_OLED_DET), oled_detection_int, + IRQF_TRIGGER_FALLING, "oled_detection", lcd)) + pr_err("failed to reqeust irq. %d\n", gpio_to_irq(GPIO_OLED_DET)); + } +#endif + + lcd_early_suspend = s6evr02_early_suspend; + lcd_late_resume = s6evr02_late_resume; + + return 0; + +out_free_backlight: + lcd_device_unregister(lcd->ld); + kfree(lcd); + return ret; + +out_free_lcd: + kfree(lcd); + return ret; + +err_alloc: + return ret; +} + +static int __devexit s6evr02_remove(struct device *dev) +{ + struct lcd_info *lcd = dev_get_drvdata(dev); + + s6evr02_power(lcd, FB_BLANK_POWERDOWN); + lcd_device_unregister(lcd->ld); + backlight_device_unregister(lcd->bd); + kfree(lcd); + + return 0; +} + +/* Power down all displays on reboot, poweroff or halt. */ +static void s6evr02_shutdown(struct device *dev) +{ + struct lcd_info *lcd = dev_get_drvdata(dev); + + dev_info(&lcd->ld->dev, "%s\n", __func__); + + s6evr02_power(lcd, FB_BLANK_POWERDOWN); +} + +static struct mipi_lcd_driver s6evr02_mipi_driver = { + .name = "s6evr02", + .probe = s6evr02_probe, + .remove = __devexit_p(s6evr02_remove), + .shutdown = s6evr02_shutdown, +}; + +static int s6evr02_init(void) +{ + return s5p_dsim_register_lcd_driver(&s6evr02_mipi_driver); +} + +static void s6evr02_exit(void) +{ + return; +} + +module_init(s6evr02_init); +module_exit(s6evr02_exit); + +MODULE_DESCRIPTION("MIPI-DSI S6EVER02:AMS555HBXX (720x1280) Panel Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/samsung/s5p-dsim.c b/drivers/video/samsung/s5p-dsim.c index d128618..e206cf8 100644 --- a/drivers/video/samsung/s5p-dsim.c +++ b/drivers/video/samsung/s5p-dsim.c @@ -23,6 +23,7 @@ #include <linux/fb.h> #include <linux/ctype.h> #include <linux/platform_device.h> +#include <linux/spinlock.h> #include <linux/io.h> #include <linux/irq.h> #include <linux/memory.h> @@ -240,7 +241,12 @@ unsigned char s5p_dsim_wr_data(void *ptr, { u32 uCnt = 0; u32* pWordPtr = (u32 *)data0; + unsigned long flags; + + spin_lock_irqsave(&dsim->slock, flags); + INIT_COMPLETION(dsim_wr_comp); + s5p_dsim_clear_interrupt(dsim_base, 0x01<<S5P_DSIM_INT_SFR_FIFO_EMPTY); do { s5p_dsim_wr_tx_data(dsim_base, pWordPtr[uCnt]); @@ -251,6 +257,17 @@ unsigned char s5p_dsim_wr_data(void *ptr, (unsigned char) (((unsigned short) data1) & 0xff), (unsigned char) ((((unsigned short) data1) & 0xff00) >> 8)); + /* check interrupt source if fifo empty interrupt source is rised directly after writing tx header. + if yes, we consider tx_data as fail. */ + if (readl(dsim->reg_base + S5P_DSIM_INTSRC) & 0x01<<S5P_DSIM_INT_SFR_FIFO_EMPTY) { + dev_err(dsim->dev, "%s fifo empty is founded\n", __func__); + spin_unlock_irqrestore(&dsim->slock, flags); + mutex_unlock(&dsim_rd_wr_mutex); + return DSIM_FALSE; + } + + spin_unlock_irqrestore(&dsim->slock, flags); + if (!wait_for_completion_interruptible_timeout(&dsim_wr_comp, DSIM_TIMEOUT)) { dev_err(dsim->dev, "[DSIM:ERROR] %s Timeout\n", __func__); mutex_unlock(&dsim_rd_wr_mutex); @@ -386,6 +403,102 @@ clear_rx_fifo: } +int s5p_dsim_dcs_rd_data(void *ptr, u8 addr, u16 count, u8 *buf) +{ + u32 i, temp; + u8 response = 0; + u16 rxsize; + u32 txhd; + u32 rxhd; + int j; + struct dsim_global *dsim = ptr; + unsigned int reg_base = dsim->reg_base; + + if (dsim->mipi_ddi_pd->resume_complete == 0) { + dev_err(dsim->dev, "DSIM Status: SUSPEND\n"); + return DSIM_FALSE; + } + + mutex_lock(&dsim_rd_wr_mutex); + INIT_COMPLETION(dsim_rd_comp); + + switch (count) { + case 1: + response = MIPI_RESP_DCS_RD_1; + break; + case 2: + response = MIPI_RESP_DCS_RD_2; + break; + default: + response = MIPI_RESP_DCS_RD_LONG; + break; + } + + /* set return packet size */ + txhd = MIPI_CMD_DSI_SET_PKT_SZ | count << 8; + + writel(txhd, reg_base + S5P_DSIM_PKTHDR); + + /* set address to read */ + txhd = MIPI_CMD_DSI_RD_0 | addr << 8; + + writel(txhd, reg_base + S5P_DSIM_PKTHDR); + + if (!wait_for_completion_interruptible_timeout(&dsim_rd_comp, DSIM_TIMEOUT)) { + dev_err(dsim->dev, "ERROR:%s timout\n", __func__); + mutex_unlock(&dsim_rd_wr_mutex); + return 0; + } + + rxhd = readl(reg_base + S5P_DSIM_RXFIFO); + dev_info(dsim->dev, "rxhd : %x\n", rxhd); + if ((u8)(rxhd & 0xff) != response) { + dev_err(dsim->dev, "[DSIM:ERROR]:%s wrong response rxhd : %x, response:%x\n" + , __func__, rxhd, response); + goto error_read; + } + /* for short packet */ + if (count <= 2) { + for (i = 0; i < count; i++) + buf[i] = (rxhd >> (8+(i*8))) & 0xff; + rxsize = count; + } else { + /* for long packet */ + rxsize = (u16)((rxhd & 0x00ffff00) >> 8); + dev_info(dsim->dev, "rcv size : %d\n", rxsize); + if (rxsize != count) { + dev_err(dsim->dev, "[DSIM:ERROR]:%s received data size mismatch received : %d, requested : %d\n", + __func__, rxsize, count); + goto error_read; + } + + for (i = 0; i < rxsize>>2; i++) { + temp = readl(reg_base + S5P_DSIM_RXFIFO); + dev_info(dsim->dev, "pkt : %08x\n", temp); + for (j = 0; j < 4; j++) { + buf[(i*4)+j] = (u8)(temp>>(j*8))&0xff; + /* printk("Value : %02x\n",(temp>>(j*8))&0xff); */ + } + } + if (rxsize % 4) { + temp = readl(reg_base + S5P_DSIM_RXFIFO); + dev_info(dsim->dev, "pkt-l : %08x\n", temp); + for (j = 0; j < rxsize%4; j++) { + buf[(i*4)+j] = (u8)(temp>>(j*8))&0xff; + /* printk("Value : %02x\n",(temp>>(j*8))&0xff); */ + } + } + } + + mutex_unlock(&dsim_rd_wr_mutex); + return rxsize; + +error_read: + mutex_unlock(&dsim_rd_wr_mutex); + return 0; + +} + static irqreturn_t s5p_dsim_isr(int irq, void *dev_id) { int i; @@ -457,7 +570,7 @@ static irqreturn_t s5p_dsim_isr(int irq, void *dev_id) } } /* clear irq */ - writel(intsrc, dsim->reg_base + S5P_DSIM_INTSRC); + writel(intmsk, dsim->reg_base + S5P_DSIM_INTSRC); return IRQ_HANDLED; } @@ -737,6 +850,24 @@ static int s5p_dsim_init_dsim(struct dsim_global *dsim) } #endif +#if 0 +void s5p_dsim_set_lcd_freq_change(struct s3cfb_lcd_timing *timing) +{ + struct dsim_global *dsim = g_dsim; + struct dsim_lcd_config *main_lcd = dsim->dsim_lcd_info; + struct s3cfb_lcd *main_lcd_panel_info = NULL; + struct s3cfb_lcd_timing *main_timing = NULL; + + main_lcd_panel_info = (struct s3cfb_lcd *)main_lcd->lcd_panel_info; + main_timing = &main_lcd_panel_info->timing; + + main_timing->h_sw = timing->h_sw; + main_timing->h_bp = timing->h_bp; + main_timing->h_fp = timing->h_fp; +} +EXPORT_SYMBOL(s5p_dsim_set_lcd_freq_change); +#endif + static void s5p_dsim_set_display_mode(struct dsim_global *dsim, struct dsim_lcd_config *main_lcd, struct dsim_lcd_config *sub_lcd) { @@ -770,11 +901,11 @@ static void s5p_dsim_set_display_mode(struct dsim_global *dsim, s5p_dsim_set_main_disp_vporch(dsim_base, main_timing->cmd_allow_len, - main_timing->stable_vfp, (u16) main_timing->v_bp); + main_timing->stable_vfp, (u16)main_timing->v_bp); s5p_dsim_set_main_disp_hporch(dsim_base, - main_timing->h_fp, (u16) main_timing->h_bp); + main_timing->h_fp, (u16)main_timing->h_bp); s5p_dsim_set_main_disp_sync_area(dsim_base, - main_timing->v_sw, (u16) main_timing->h_sw); + main_timing->v_sw, (u16)main_timing->h_sw); /* in case of COMMAND MODE (CPU or I80 INTERFACE) */ } else { @@ -990,10 +1121,10 @@ static void s5p_dsim_interrupt_mask_set(struct dsim_global *dsim) writel(int_stat, dsim->reg_base + S5P_DSIM_INTMSK); } -int s5p_dsim_fifo_clear(void) +#if defined(CONFIG_CPU_EXYNOS4210) +static int s5p_dsim_fifo_clear(struct dsim_global *dsim) { int dsim_count = 0, ret; - struct dsim_global *dsim = g_dsim; writel(SwRstRelease, dsim->reg_base + S5P_DSIM_INTSRC); @@ -1007,7 +1138,6 @@ int s5p_dsim_fifo_clear(void) } if (readl(dsim->reg_base + S5P_DSIM_INTSRC) & SwRstRelease) { - s5p_dsim_interrupt_mask_set(dsim); ret = 1; break; } @@ -1015,6 +1145,7 @@ int s5p_dsim_fifo_clear(void) return ret; } +#endif #ifdef CONFIG_HAS_EARLYSUSPEND void s5p_dsim_early_suspend(void) @@ -1087,19 +1218,27 @@ void s5p_dsim_late_resume(void) dsim->mipi_ddi_pd->lcd_power_on(dsim->dev, 1); usleep_range(25000, 25000); + s5p_dsim_late_resume_init_dsim(dsim); + s5p_dsim_init_link(dsim); + usleep_range(10000, 10000); + if (dsim->mipi_ddi_pd->lcd_reset) dsim->mipi_ddi_pd->lcd_reset(); usleep_range(5000, 5000); - s5p_dsim_late_resume_init_dsim(dsim); - s5p_dsim_init_link(dsim); - usleep_range(10000, 10000); s5p_dsim_set_hs_enable(dsim); s5p_dsim_set_data_transfer_mode(dsim, DSIM_TRANSFER_BYCPU, 1); s5p_dsim_set_display_mode(dsim, dsim->dsim_lcd_info, NULL); s5p_dsim_set_data_transfer_mode(dsim, DSIM_TRANSFER_BYLCDC, 1); /* s5p_dsim_set_interrupt_mask(dsim->reg_base, AllDsimIntr, 0); */ +#if defined(CONFIG_CPU_EXYNOS4210) + if (s5p_dsim_fifo_clear(dsim) == 0) + dev_err(dsim->dev, "dsim fifo clear fail!!!\n"); +#endif + + s5p_dsim_interrupt_mask_set(dsim); + dsim->mipi_ddi_pd->resume_complete = 1; dev_info(dsim->dev, "-%s\n", __func__); @@ -1254,6 +1393,7 @@ static DEVICE_ATTR(dsim_dump, 0444, dsim_dump_show, NULL); static struct dsim_ops s5p_dsim_ops = { .cmd_write = s5p_dsim_wr_data, .cmd_read = s5p_dsim_rd_data, + .cmd_dcs_read = s5p_dsim_dcs_rd_data, .suspend = s5p_dsim_early_suspend, .resume = s5p_dsim_late_resume, }; @@ -1277,7 +1417,8 @@ static int s5p_dsim_probe(struct platform_device *pdev) dsim->pd = to_dsim_plat(&pdev->dev); if (!dsim->pd) { dev_err(&pdev->dev, "platform data is NULL\n"); - return -EINVAL; + ret = -EINVAL; + goto err_plat; } dsim->dev = &pdev->dev; @@ -1298,7 +1439,8 @@ static int s5p_dsim_probe(struct platform_device *pdev) dsim->clock = clk_get(&pdev->dev, dsim->pd->clk_name); if (IS_ERR(dsim->clock)) { dev_err(&pdev->dev, "failed to get dsim clock source\n"); - return -EINVAL; + ret = -EINVAL; + goto err_clk_get; } clk_enable(dsim->clock); @@ -1343,9 +1485,9 @@ static int s5p_dsim_probe(struct platform_device *pdev) writel(int_stat, dsim->reg_base + S5P_DSIM_INTSRC); /* enable interrupts */ - int_stat = readl(dsim->reg_base + S5P_DSIM_INTMSK); + /* int_stat = readl(dsim->reg_base + S5P_DSIM_INTMSK); */ - int_stat &= ~((0x01<<S5P_DSIM_INT_BTA) | (0x01<<S5P_DSIM_INT_RX_TIMEOUT) | + int_stat = ~((0x01<<S5P_DSIM_INT_BTA) | (0x01<<S5P_DSIM_INT_RX_TIMEOUT) | (0x01<<S5P_DSIM_INT_BTA_TIMEOUT) | (0x01 << S5P_DSIM_INT_RX_DONE) | (0x01<<S5P_DSIM_INT_RX_TE) | (0x01<<S5P_DSIM_INT_RX_ACK) | (0x01<<S5P_DSIM_INT_RX_ECC_ERR) | (0x01<<S5P_DSIM_IMT_RX_CRC_ERR) | @@ -1356,6 +1498,7 @@ static int s5p_dsim_probe(struct platform_device *pdev) init_completion(&dsim_rd_comp); init_completion(&dsim_wr_comp); mutex_init(&dsim_rd_wr_mutex); + spin_lock_init(&dsim->slock); dsim->mipi_ddi_pd->resume_complete = 1; dsim->dsim_lcd_info->lcd_enabled = 1; @@ -1433,6 +1576,11 @@ mipi_drv_err: err_clk_disable: clk_disable(dsim->clock); + +err_clk_get: +err_plat: + kfree(dsim); + err_alloc: return ret; } diff --git a/drivers/video/samsung/s5p-dsim.h b/drivers/video/samsung/s5p-dsim.h index baf8f66..049e066 100644 --- a/drivers/video/samsung/s5p-dsim.h +++ b/drivers/video/samsung/s5p-dsim.h @@ -44,6 +44,7 @@ struct mipi_lcd_driver { struct dsim_ops { u8 (*cmd_write)(void *ptr, u32 data0, u32 data1, u32 data2); int (*cmd_read)(void *ptr, u8 addr, u16 count, u8 *buf); + int (*cmd_dcs_read)(void *ptr, u8 addr, u16 count, u8 *buf); void (*suspend)(void); void (*resume)(void); }; @@ -79,6 +80,8 @@ struct dsim_global { struct delayed_work check_hs_toggle_work; unsigned int dsim_toggle_per_frame_count; + spinlock_t slock; + struct dsim_ops *ops; }; diff --git a/drivers/video/samsung/s6d6aa1.c b/drivers/video/samsung/s6d6aa1.c index 2a4c4ad..e974b0a 100644 --- a/drivers/video/samsung/s6d6aa1.c +++ b/drivers/video/samsung/s6d6aa1.c @@ -37,13 +37,13 @@ #define MIN_BRIGHTNESS 0 #define MAX_BRIGHTNESS 255 -#define DEFAULT_BRIGHTNESS 170 +#define DEFAULT_BRIGHTNESS 160 + struct lcd_info { unsigned int bl; unsigned int current_bl; - unsigned int acl_enable; - + unsigned int auto_brightness; unsigned int ldi_enable; unsigned int power; struct mutex lock; @@ -57,10 +57,69 @@ struct lcd_info { unsigned int irq; unsigned int connected; +#if defined(GPIO_OLED_DET) + struct delayed_work oled_detection; + unsigned int oled_detection_count; +#endif struct dsim_global *dsim; }; +static const unsigned char SEQ_PASSWD1[] = { + 0xF0, + 0x5A, 0x5A +}; + +static const unsigned char SEQ_PASSWD2[] = { + 0xF1, + 0x5A, 0x5A +}; + +static const unsigned char SEQ_SONY_IP_SET1[] = { + 0xC4, + 0x7C, 0xE6, 0x7C, 0xE6, 0x7C, 0xE6, 0x7C, 0x7C, + 0x05, 0x0F, 0x1F, 0x01, 0x00, 0x00, +}; + +static const unsigned char SEQ_SONY_IP_SET2[] = { + 0xC5, + 0x80, 0x80, 0x80, 0x41, 0x43, 0x34, 0x80, 0x80, + 0x01, 0xFF, 0x25, 0x58, 0x50 +}; + +/* Should be removed when panel nvm is updated */ +static const unsigned char SEQ_PGAMMACTL[] = { + 0xFA, 0x9C, 0xBF, 0x1A, 0xD6, 0xE3, 0xE3, 0x1B, + 0xDA, 0x9B, 0x16, 0x51, 0x12, 0x15, 0xD9, 0x9B, + 0x1A, 0xDD, 0x62, 0x2D, 0x79, 0x6A, 0x2C, 0x7F, + 0x11, 0x09, 0x53, 0x91, 0x09, 0x08, 0xCA, 0x06, + 0x04, 0x87, 0x0B, 0x4E, 0xD2, 0x13, 0xD7, 0x18, + 0x1A, 0x9A, 0xC1, 0x0F, 0xFF, 0xD7, 0x53, 0x61, + 0xE2, 0x5A, 0x9A, 0xDC, 0x59, 0x96, 0x98, 0x5C, + 0x1F, 0xE3, 0x25, 0xE6, 0x27, 0x23, 0x23, 0x4C, +}; + +static const unsigned char SEQ_NGAMMACTL[] = { + 0xFB, 0x9C, 0xBF, 0x1A, 0xD6, 0xE3, 0xE3, 0x1B, + 0xDA, 0x9B, 0x16, 0x51, 0x12, 0x15, 0xD9, 0x9B, + 0x1A, 0xDD, 0x62, 0x2D, 0x79, 0x6A, 0x2C, 0x7F, + 0x11, 0x09, 0x53, 0x91, 0x09, 0x08, 0xCA, 0x06, + 0x04, 0x87, 0x0B, 0x4E, 0xD2, 0x13, 0xD7, 0x18, + 0x1A, 0x9A, 0xC1, 0x0F, 0xFF, 0xD7, 0x53, 0x61, + 0xE2, 0x5A, 0x9A, 0xDC, 0x59, 0x96, 0x98, 0x5C, + 0x1F, 0xE3, 0x25, 0xE6, 0x27, 0x23, 0x23, 0x4C, +}; + +static const unsigned char SEQ_PASSWD1_DISABLE[] = { + 0xF0, + 0xA5, 0xA5 +}; + +static const unsigned char SEQ_PASSWD2_DISABLE[] = { + 0xF1, + 0xA5, 0xA5 +}; + static const unsigned char SEQ_SLPOUT[] = { 0x11, 0x00, @@ -73,12 +132,6 @@ static const unsigned char SEQ_DSCTL[] = { 0x00 }; -static const unsigned char SEQ_WRDISBV[] = { - 0x51, - 0xFF, - 0x00 -}; - static const unsigned char SEQ_WRCTRLD[] = { 0x53, 0x2C, @@ -91,6 +144,12 @@ static const unsigned char SEQ_WRCABC[] = { 0x00 }; +static const unsigned char SEQ_WRCABC_OUTDOOR[] = { + 0x55, + 0x04, + 0x00 +}; + static const unsigned char SEQ_DISPON[] = { 0x29, 0x00, @@ -115,8 +174,85 @@ static unsigned char SEQ_WRDISBV_CTL[] = { 0x00 }; +static unsigned char TRANS_BRIGHTNESS[] = { + 0, 1, 1, 2, 2, 3, 3, 4, + 4, 5, 5, 6, 6, 7, 7, 8, + 8, 9, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 23, + 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 48, + 49, 50, 51, 52, 53, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 72, 73, + 74, 75, 76, 77, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, 92, 93, 94, 95, 97, 98, + 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, + 115, 116, 117, 118, 119, 121, 122, 123, + 124, 125, 126, 127, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, 138, 139, + 140, 141, 142, 143, 144, 146, 147, 148, + 149, 150, 151, 152, 153, 154, 155, 156, + 157, 158, 159, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 170, 171, 172, 173, + 174, 175, 176, 177, 178, 179, 180, 181, + 182, 183, 184, 185, 186, 187, 188, 189, + 190, 191, 192, 193, 195, 196, 197, 198, + 199, 200, 201, 202, 203, 204, 205, 206, + 207, 208, 209, 210, 211, 212, 213, 214, + 215, 216, 217, 219, 220, 221, 222, 223, + 224, 225, 226, 227, 228, 229, 230, 231, + 232, 233, 234, 235, 236, 237, 238, 239, + 240, 241, 242, 244, 245, 246, 247, 248, + 249, 250, 251, 252, 253, 254, 255, 255, +}; + +extern void (*lcd_early_suspend)(void); +extern void (*lcd_late_resume)(void); + +#if defined(GPIO_OLED_DET) +static void esd_reset_lcd(struct lcd_info *lcd) +{ + dev_info(&lcd->ld->dev, "++%s\n", __func__); + if (lcd_early_suspend) + lcd_early_suspend(); + lcd->dsim->ops->suspend(); + + lcd->dsim->ops->resume(); + if (lcd_late_resume) + lcd_late_resume(); + dev_info(&lcd->ld->dev, "--%s\n", __func__); +} + +static void oled_detection_work(struct work_struct *work) +{ + struct lcd_info *lcd = + container_of(work, struct lcd_info, oled_detection.work); + + int oled_det_level = gpio_get_value(GPIO_OLED_DET); + + dev_info(&lcd->ld->dev, "%s, %d, %d\n", __func__, lcd->oled_detection_count, oled_det_level); + if (!oled_det_level) + esd_reset_lcd(lcd); +} + +static irqreturn_t oled_detection_int(int irq, void *_lcd) +{ + struct lcd_info *lcd = _lcd; + + dev_info(&lcd->ld->dev, "%s\n", __func__); + + lcd->oled_detection_count = 0; + schedule_delayed_work(&lcd->oled_detection, HZ/16); + + return IRQ_HANDLED; +} +#endif -static int s6e8ax0_write(struct lcd_info *lcd, const unsigned char *seq, int len) + +static int s6d6aa1_write(struct lcd_info *lcd, const unsigned char *seq, int len) { int size; const unsigned char *wbuf; @@ -141,7 +277,7 @@ static int s6e8ax0_write(struct lcd_info *lcd, const unsigned char *seq, int len return 0; } -static int _s6e8ax0_read(struct lcd_info *lcd, const u8 addr, u16 count, u8 *buf) +static int _s6d6aa1_read(struct lcd_info *lcd, const u8 addr, u16 count, u8 *buf) { int ret = 0; @@ -158,12 +294,12 @@ static int _s6e8ax0_read(struct lcd_info *lcd, const u8 addr, u16 count, u8 *buf return ret; } -static int s6e8ax0_read(struct lcd_info *lcd, const u8 addr, u16 count, u8 *buf, u8 retry_cnt) +static int s6d6aa1_read(struct lcd_info *lcd, const u8 addr, u16 count, u8 *buf, u8 retry_cnt) { int ret = 0; read_retry: - ret = _s6e8ax0_read(lcd, addr, count, buf); + ret = _s6d6aa1_read(lcd, addr, count, buf); if (!ret) { if (retry_cnt) { printk(KERN_WARNING "[WARN:LCD] %s : retry cnt : %d\n", __func__, retry_cnt); @@ -180,23 +316,13 @@ static int get_backlight_level_from_brightness(int brightness) { int backlightlevel; - /* brightness setting from platform is from 0 to 255 - * But in this driver, brightness is only supported from 0 to 24 */ + backlightlevel = TRANS_BRIGHTNESS[brightness]; - switch (brightness) { - case 0 ... 255: - backlightlevel = brightness; - break; - default: - backlightlevel = brightness; - break; - } return backlightlevel; } static int update_brightness(struct lcd_info *lcd, u8 force) { - int ret; u32 brightness; mutex_lock(&lcd->bl_lock); @@ -209,7 +335,7 @@ static int update_brightness(struct lcd_info *lcd, u8 force) lcd->current_bl = lcd->bl; SEQ_WRDISBV_CTL[1] = lcd->bl; - s6e8ax0_write(lcd, SEQ_WRDISBV_CTL, \ + s6d6aa1_write(lcd, SEQ_WRDISBV_CTL, \ ARRAY_SIZE(SEQ_WRDISBV_CTL)); dev_info(&lcd->ld->dev, "brightness=%d, bl=%d\n", brightness, lcd->bl); @@ -220,43 +346,52 @@ static int update_brightness(struct lcd_info *lcd, u8 force) return 0; } -static int s6e8ax0_ldi_init(struct lcd_info *lcd) +static int s6d6aa1_ldi_init(struct lcd_info *lcd) { int ret = 0; - s6e8ax0_write(lcd, SEQ_SLPOUT, ARRAY_SIZE(SEQ_SLPOUT)); + msleep(15); + + s6d6aa1_write(lcd, SEQ_SLPOUT, ARRAY_SIZE(SEQ_SLPOUT)); - msleep(200); + msleep(145); - s6e8ax0_write(lcd, SEQ_DSCTL, ARRAY_SIZE(SEQ_DSCTL)); - s6e8ax0_write(lcd, SEQ_WRDISBV, ARRAY_SIZE(SEQ_WRDISBV)); - s6e8ax0_write(lcd, SEQ_WRCTRLD, ARRAY_SIZE(SEQ_WRCTRLD)); - s6e8ax0_write(lcd, SEQ_WRCABC, ARRAY_SIZE(SEQ_WRCABC)); + s6d6aa1_write(lcd, SEQ_PASSWD1, ARRAY_SIZE(SEQ_PASSWD1)); + s6d6aa1_write(lcd, SEQ_PASSWD2, ARRAY_SIZE(SEQ_PASSWD2)); + s6d6aa1_write(lcd, SEQ_SONY_IP_SET1, ARRAY_SIZE(SEQ_SONY_IP_SET1)); + s6d6aa1_write(lcd, SEQ_SONY_IP_SET2, ARRAY_SIZE(SEQ_SONY_IP_SET2)); + s6d6aa1_write(lcd, SEQ_PGAMMACTL, ARRAY_SIZE(SEQ_PGAMMACTL)); + s6d6aa1_write(lcd, SEQ_NGAMMACTL, ARRAY_SIZE(SEQ_NGAMMACTL)); + s6d6aa1_write(lcd, SEQ_PASSWD1_DISABLE, ARRAY_SIZE(SEQ_PASSWD1_DISABLE)); + s6d6aa1_write(lcd, SEQ_PASSWD2_DISABLE, ARRAY_SIZE(SEQ_PASSWD2_DISABLE)); + s6d6aa1_write(lcd, SEQ_DSCTL, ARRAY_SIZE(SEQ_DSCTL)); + s6d6aa1_write(lcd, SEQ_WRCTRLD, ARRAY_SIZE(SEQ_WRCTRLD)); + s6d6aa1_write(lcd, SEQ_WRCABC, ARRAY_SIZE(SEQ_WRCABC)); return ret; } -static int s6e8ax0_ldi_enable(struct lcd_info *lcd) +static int s6d6aa1_ldi_enable(struct lcd_info *lcd) { int ret = 0; - s6e8ax0_write(lcd, SEQ_DISPON, ARRAY_SIZE(SEQ_DISPON)); + s6d6aa1_write(lcd, SEQ_DISPON, ARRAY_SIZE(SEQ_DISPON)); return ret; } -static int s6e8ax0_ldi_disable(struct lcd_info *lcd) +static int s6d6aa1_ldi_disable(struct lcd_info *lcd) { int ret = 0; - s6e8ax0_write(lcd, SEQ_DISPOFF, ARRAY_SIZE(SEQ_DISPOFF)); - s6e8ax0_write(lcd, SEQ_SLPIN, ARRAY_SIZE(SEQ_SLPIN)); + s6d6aa1_write(lcd, SEQ_DISPOFF, ARRAY_SIZE(SEQ_DISPOFF)); + s6d6aa1_write(lcd, SEQ_SLPIN, ARRAY_SIZE(SEQ_SLPIN)); return ret; } -static int s6e8ax0_power_on(struct lcd_info *lcd) +static int s6d6aa1_power_on(struct lcd_info *lcd) { int ret = 0; struct lcd_platform_data *pd = NULL; @@ -264,15 +399,14 @@ static int s6e8ax0_power_on(struct lcd_info *lcd) /* dev_info(&lcd->ld->dev, "%s\n", __func__); */ - ret = s6e8ax0_ldi_init(lcd); + ret = s6d6aa1_ldi_init(lcd); if (ret) { dev_err(&lcd->ld->dev, "failed to initialize ldi.\n"); goto err; } - msleep(120); - ret = s6e8ax0_ldi_enable(lcd); + ret = s6d6aa1_ldi_enable(lcd); if (ret) { dev_err(&lcd->ld->dev, "failed to enable ldi.\n"); goto err; @@ -285,7 +419,7 @@ err: return ret; } -static int s6e8ax0_power_off(struct lcd_info *lcd) +static int s6d6aa1_power_off(struct lcd_info *lcd) { int ret = 0; @@ -293,21 +427,21 @@ static int s6e8ax0_power_off(struct lcd_info *lcd) lcd->ldi_enable = 0; - ret = s6e8ax0_ldi_disable(lcd); + ret = s6d6aa1_ldi_disable(lcd); msleep(135); return ret; } -static int s6e8ax0_power(struct lcd_info *lcd, int power) +static int s6d6aa1_power(struct lcd_info *lcd, int power) { int ret = 0; if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->power)) - ret = s6e8ax0_power_on(lcd); + ret = s6d6aa1_power_on(lcd); else if (!POWER_IS_ON(power) && POWER_IS_ON(lcd->power)) - ret = s6e8ax0_power_off(lcd); + ret = s6d6aa1_power_off(lcd); if (!ret) lcd->power = power; @@ -315,7 +449,7 @@ static int s6e8ax0_power(struct lcd_info *lcd, int power) return ret; } -static int s6e8ax0_set_power(struct lcd_device *ld, int power) +static int s6d6aa1_set_power(struct lcd_device *ld, int power) { struct lcd_info *lcd = lcd_get_data(ld); @@ -325,17 +459,27 @@ static int s6e8ax0_set_power(struct lcd_device *ld, int power) return -EINVAL; } - return s6e8ax0_power(lcd, power); + return s6d6aa1_power(lcd, power); +} + + static int s6d6aa1_check_fb(struct lcd_device *ld, struct fb_info *fb) +{ + struct s3cfb_window *win = fb->par; + struct lcd_info *lcd = lcd_get_data(ld); + + dev_info(&lcd->ld->dev, "%s, fb%d\n", __func__, win->id); + + return 0; } -static int s6e8ax0_get_power(struct lcd_device *ld) +static int s6d6aa1_get_power(struct lcd_device *ld) { struct lcd_info *lcd = lcd_get_data(ld); return lcd->power; } -static int s6e8ax0_set_brightness(struct backlight_device *bd) +static int s6d6aa1_set_brightness(struct backlight_device *bd) { int ret = 0; int brightness = bd->props.brightness; @@ -361,7 +505,7 @@ static int s6e8ax0_set_brightness(struct backlight_device *bd) return ret; } -static int s6e8ax0_get_brightness(struct backlight_device *bd) +static int s6d6aa1_get_brightness(struct backlight_device *bd) { struct lcd_info *lcd = bl_get_data(bd); @@ -369,28 +513,43 @@ static int s6e8ax0_get_brightness(struct backlight_device *bd) } static struct lcd_ops panel_lcd_ops = { - .set_power = s6e8ax0_set_power, - .get_power = s6e8ax0_get_power, + .set_power = s6d6aa1_set_power, + .get_power = s6d6aa1_get_power, + .check_fb = s6d6aa1_check_fb, }; static const struct backlight_ops panel_backlight_ops = { - .get_brightness = s6e8ax0_get_brightness, - .update_status = s6e8ax0_set_brightness, + .get_brightness = s6d6aa1_get_brightness, + .update_status = s6d6aa1_set_brightness, }; -static ssize_t power_reduce_show(struct device *dev, +static ssize_t lcd_type_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + char temp[15]; + + sprintf(temp, "JDI_ACX445BLN\n"); + + strcat(buf, temp); + + return strlen(buf); +} + +static DEVICE_ATTR(lcd_type, 0444, lcd_type_show, NULL); + +static ssize_t auto_brightness_show(struct device *dev, struct device_attribute *attr, char *buf) { struct lcd_info *lcd = dev_get_drvdata(dev); char temp[3]; - sprintf(temp, "%d\n", lcd->acl_enable); + sprintf(temp, "%d\n", lcd->auto_brightness); strcpy(buf, temp); return strlen(buf); } -static ssize_t power_reduce_store(struct device *dev, +static ssize_t auto_brightness_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct lcd_info *lcd = dev_get_drvdata(dev); @@ -401,39 +560,21 @@ static ssize_t power_reduce_store(struct device *dev, if (rc < 0) return rc; else { - if (lcd->acl_enable != value) { - dev_info(dev, "%s - %d, %d\n", __func__, lcd->acl_enable, value); - mutex_lock(&lcd->bl_lock); - lcd->acl_enable = value; - if (lcd->ldi_enable) - /*s6e8ax0_set_acl(lcd);*/ - mutex_unlock(&lcd->bl_lock); - } + lcd->auto_brightness = value; + if (lcd->auto_brightness < 4) + s6d6aa1_write(lcd, SEQ_WRCABC, ARRAY_SIZE(SEQ_WRCABC)); + else + s6d6aa1_write(lcd, SEQ_WRCABC_OUTDOOR, ARRAY_SIZE(SEQ_WRCABC_OUTDOOR)); } return size; } -static DEVICE_ATTR(power_reduce, 0664, power_reduce_show, power_reduce_store); - -static ssize_t lcd_type_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - char temp[15]; - - sprintf(temp, "SMD_AMS480GYXX\n"); - - strcat(buf, temp); - - return strlen(buf); -} - -static DEVICE_ATTR(lcd_type, 0444, lcd_type_show, NULL); - +static DEVICE_ATTR(auto_brightness, 0644, auto_brightness_show, auto_brightness_store); #ifdef CONFIG_HAS_EARLYSUSPEND struct lcd_info *g_lcd; -void s6e8ax0_early_suspend(void) +void s6d6aa1_early_suspend(void) { struct lcd_info *lcd = g_lcd; @@ -441,21 +582,33 @@ void s6e8ax0_early_suspend(void) dev_info(&lcd->ld->dev, "+%s\n", __func__); - s6e8ax0_power(lcd, FB_BLANK_POWERDOWN); +#if defined(GPIO_OLED_DET) + disable_irq(lcd->irq); + gpio_request(GPIO_OLED_DET, "OLED_DET"); + s3c_gpio_cfgpin(GPIO_OLED_DET, S3C_GPIO_OUTPUT); + s3c_gpio_setpull(GPIO_OLED_DET, S3C_GPIO_PULL_NONE); + gpio_direction_output(GPIO_OLED_DET, GPIO_LEVEL_LOW); + gpio_free(GPIO_OLED_DET); +#endif + s6d6aa1_power(lcd, FB_BLANK_POWERDOWN); dev_info(&lcd->ld->dev, "-%s\n", __func__); return ; } -void s6e8ax0_late_resume(void) +void s6d6aa1_late_resume(void) { struct lcd_info *lcd = g_lcd; dev_info(&lcd->ld->dev, "+%s\n", __func__); - s6e8ax0_power(lcd, FB_BLANK_UNBLANK); - + s6d6aa1_power(lcd, FB_BLANK_UNBLANK); +#if defined(GPIO_OLED_DET) + s3c_gpio_cfgpin(GPIO_OLED_DET, S3C_GPIO_SFN(0xf)); + s3c_gpio_setpull(GPIO_OLED_DET, S3C_GPIO_PULL_NONE); + enable_irq(lcd->irq); +#endif dev_info(&lcd->ld->dev, "-%s\n", __func__); set_dsim_lcd_enabled(1); @@ -464,20 +617,7 @@ void s6e8ax0_late_resume(void) } #endif -#if 0 -static void s6e8ax0_read_id(struct lcd_info *lcd, u8 *buf) -{ - int ret = 0; - - ret = s6e8ax0_read(lcd, LDI_ID_REG, LDI_ID_LEN, buf, 3); - if (!ret) { - lcd->connected = 0; - dev_info(&lcd->ld->dev, "panel is not connected well\n"); - } -} -#endif - -static int s6e8ax0_probe(struct device *dev) +static int s6d6aa1_probe(struct device *dev) { int ret = 0; struct lcd_info *lcd; @@ -512,17 +652,15 @@ static int s6e8ax0_probe(struct device *dev) lcd->bl = 0; lcd->current_bl = lcd->bl; - lcd->acl_enable = 0; - lcd->power = FB_BLANK_UNBLANK; lcd->ldi_enable = 1; lcd->connected = 1; - ret = device_create_file(&lcd->ld->dev, &dev_attr_power_reduce); + ret = device_create_file(&lcd->ld->dev, &dev_attr_lcd_type); if (ret < 0) dev_err(&lcd->ld->dev, "failed to add sysfs entries, %d\n", __LINE__); - ret = device_create_file(&lcd->ld->dev, &dev_attr_lcd_type); + ret = device_create_file(&lcd->bd->dev, &dev_attr_auto_brightness); if (ret < 0) dev_err(&lcd->ld->dev, "failed to add sysfs entries, %d\n", __LINE__); @@ -533,6 +671,23 @@ static int s6e8ax0_probe(struct device *dev) dev_info(&lcd->ld->dev, "s6e8aa0 lcd panel driver has been probed.\n"); +#if defined(GPIO_OLED_DET) + if (lcd->connected) { + INIT_DELAYED_WORK(&lcd->oled_detection, oled_detection_work); + + lcd->irq = gpio_to_irq(GPIO_OLED_DET); + + s3c_gpio_cfgpin(GPIO_OLED_DET, S3C_GPIO_SFN(0xf)); + s3c_gpio_setpull(GPIO_OLED_DET, S3C_GPIO_PULL_NONE); + if (request_irq(lcd->irq, oled_detection_int, + IRQF_TRIGGER_FALLING, "oled_detection", lcd)) + pr_err("failed to reqeust irq. %d\n", lcd->irq); + } +#endif + + lcd_early_suspend = s6d6aa1_early_suspend; + lcd_late_resume = s6d6aa1_late_resume; + return 0; out_free_backlight: @@ -548,11 +703,11 @@ err_alloc: return ret; } -static int __devexit s6e8ax0_remove(struct device *dev) +static int __devexit s6d6aa1_remove(struct device *dev) { struct lcd_info *lcd = dev_get_drvdata(dev); - s6e8ax0_power(lcd, FB_BLANK_POWERDOWN); + s6d6aa1_power(lcd, FB_BLANK_POWERDOWN); lcd_device_unregister(lcd->ld); backlight_device_unregister(lcd->bd); kfree(lcd); @@ -561,35 +716,35 @@ static int __devexit s6e8ax0_remove(struct device *dev) } /* Power down all displays on reboot, poweroff or halt. */ -static void s6e8ax0_shutdown(struct device *dev) +static void s6d6aa1_shutdown(struct device *dev) { struct lcd_info *lcd = dev_get_drvdata(dev); dev_info(&lcd->ld->dev, "%s\n", __func__); - s6e8ax0_power(lcd, FB_BLANK_POWERDOWN); + s6d6aa1_power(lcd, FB_BLANK_POWERDOWN); } -static struct mipi_lcd_driver s6e8ax0_mipi_driver = { +static struct mipi_lcd_driver s6d6aa1_mipi_driver = { .name = "s6d6aa1", - .probe = s6e8ax0_probe, - .remove = __devexit_p(s6e8ax0_remove), - .shutdown = s6e8ax0_shutdown, + .probe = s6d6aa1_probe, + .remove = __devexit_p(s6d6aa1_remove), + .shutdown = s6d6aa1_shutdown, }; -static int s6e8ax0_init(void) +static int s6d6aa1_init(void) { - return s5p_dsim_register_lcd_driver(&s6e8ax0_mipi_driver); + return s5p_dsim_register_lcd_driver(&s6d6aa1_mipi_driver); } -static void s6e8ax0_exit(void) +static void s6d6aa1_exit(void) { return; } -module_init(s6e8ax0_init); -module_exit(s6e8ax0_exit); +module_init(s6d6aa1_init); +module_exit(s6d6aa1_exit); -MODULE_DESCRIPTION("MIPI-DSI S6E8AA0:AMS529HA01 (800x1280) Panel Driver"); +MODULE_DESCRIPTION("MIPI-DSI S6D6AA1:ACX445BLN SCLCD (720x1280) Panel Driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/video/samsung/s6dr171.c b/drivers/video/samsung/s6dr171.c index 167f658..868c006 100644 --- a/drivers/video/samsung/s6dr171.c +++ b/drivers/video/samsung/s6dr171.c @@ -79,7 +79,10 @@ struct lcd_info { struct dsim_global *dsim; }; -static int s6e8ax0_write(struct lcd_info *lcd, const unsigned char *seq, int len) +extern void (*lcd_early_suspend)(void); +extern void (*lcd_late_resume)(void); + +static int s6dr171_write(struct lcd_info *lcd, const unsigned char *seq, int len) { int size; const unsigned char *wbuf; @@ -104,7 +107,7 @@ static int s6e8ax0_write(struct lcd_info *lcd, const unsigned char *seq, int len return 0; } -static int _s6e8ax0_read(struct lcd_info *lcd, const u8 addr, u16 count, u8 *buf) +static int _s6dr171_read(struct lcd_info *lcd, const u8 addr, u16 count, u8 *buf) { int ret = 0; @@ -121,12 +124,12 @@ static int _s6e8ax0_read(struct lcd_info *lcd, const u8 addr, u16 count, u8 *buf return ret; } -static int s6e8ax0_read(struct lcd_info *lcd, const u8 addr, u16 count, u8 *buf, u8 retry_cnt) +static int s6dr171_read(struct lcd_info *lcd, const u8 addr, u16 count, u8 *buf, u8 retry_cnt) { int ret = 0; read_retry: - ret = _s6e8ax0_read(lcd, addr, count, buf); + ret = _s6dr171_read(lcd, addr, count, buf); if (!ret) { if (retry_cnt) { printk(KERN_WARNING "[WARN:LCD] %s : retry cnt : %d\n", __func__, retry_cnt); @@ -139,55 +142,55 @@ read_retry: return ret; } -static int s6e8ax0_ldi_init(struct lcd_info *lcd) +static int s6dr171_ldi_init(struct lcd_info *lcd) { int ret = 0; - s6e8ax0_write(lcd, SEQ_APPLY_LEVEL_1_KEY, ARRAY_SIZE(SEQ_APPLY_LEVEL_1_KEY)); - s6e8ax0_write(lcd, SEQ_APPLY_MTP_KEY_ENABLE, ARRAY_SIZE(SEQ_APPLY_MTP_KEY_ENABLE)); - s6e8ax0_write(lcd, SEQ_PWRSEQCTL, ARRAY_SIZE(SEQ_PWRSEQCTL)); - s6e8ax0_write(lcd, SEQ_DISPLAY_BRIGHTNESSS, ARRAY_SIZE(SEQ_DISPLAY_BRIGHTNESSS)); - s6e8ax0_write(lcd, SEQ_CONTROL_DISPLAY, ARRAY_SIZE(SEQ_CONTROL_DISPLAY)); - s6e8ax0_write(lcd, SEQ_SLEEP_OUT, ARRAY_SIZE(SEQ_SLEEP_OUT)); + s6dr171_write(lcd, SEQ_APPLY_LEVEL_1_KEY, ARRAY_SIZE(SEQ_APPLY_LEVEL_1_KEY)); + s6dr171_write(lcd, SEQ_APPLY_MTP_KEY_ENABLE, ARRAY_SIZE(SEQ_APPLY_MTP_KEY_ENABLE)); + s6dr171_write(lcd, SEQ_PWRSEQCTL, ARRAY_SIZE(SEQ_PWRSEQCTL)); + s6dr171_write(lcd, SEQ_DISPLAY_BRIGHTNESSS, ARRAY_SIZE(SEQ_DISPLAY_BRIGHTNESSS)); + s6dr171_write(lcd, SEQ_CONTROL_DISPLAY, ARRAY_SIZE(SEQ_CONTROL_DISPLAY)); + s6dr171_write(lcd, SEQ_SLEEP_OUT, ARRAY_SIZE(SEQ_SLEEP_OUT)); msleep(120); - s6e8ax0_write(lcd, SEQ_PANEL_CONDITION_SET, ARRAY_SIZE(SEQ_PANEL_CONDITION_SET)); - s6e8ax0_write(lcd, SEQ_DISPLAY_CONDITION_SET, ARRAY_SIZE(SEQ_DISPLAY_CONDITION_SET)); - s6e8ax0_write(lcd, SEQ_GAMMA_CONDITION_SET, ARRAY_SIZE(SEQ_GAMMA_CONDITION_SET)); - s6e8ax0_write(lcd, SEQ_GAMMA_UPDATE, ARRAY_SIZE(SEQ_GAMMA_UPDATE)); + s6dr171_write(lcd, SEQ_PANEL_CONDITION_SET, ARRAY_SIZE(SEQ_PANEL_CONDITION_SET)); + s6dr171_write(lcd, SEQ_DISPLAY_CONDITION_SET, ARRAY_SIZE(SEQ_DISPLAY_CONDITION_SET)); + s6dr171_write(lcd, SEQ_GAMMA_CONDITION_SET, ARRAY_SIZE(SEQ_GAMMA_CONDITION_SET)); + s6dr171_write(lcd, SEQ_GAMMA_UPDATE, ARRAY_SIZE(SEQ_GAMMA_UPDATE)); msleep(20); - s6e8ax0_write(lcd, SEQ_GAMMA_UPDATE2, ARRAY_SIZE(SEQ_GAMMA_UPDATE2)); + s6dr171_write(lcd, SEQ_GAMMA_UPDATE2, ARRAY_SIZE(SEQ_GAMMA_UPDATE2)); msleep(20); - s6e8ax0_write(lcd, SEQ_ETC_SOURCE_CONTROL, ARRAY_SIZE(SEQ_ETC_SOURCE_CONTROL)); - s6e8ax0_write(lcd, SEQ_ETC_NVM_SETTING, ARRAY_SIZE(SEQ_ETC_NVM_SETTING)); - s6e8ax0_write(lcd, SEQ_ETC_POWER_CONTROL, ARRAY_SIZE(SEQ_ETC_POWER_CONTROL)); + s6dr171_write(lcd, SEQ_ETC_SOURCE_CONTROL, ARRAY_SIZE(SEQ_ETC_SOURCE_CONTROL)); + s6dr171_write(lcd, SEQ_ETC_NVM_SETTING, ARRAY_SIZE(SEQ_ETC_NVM_SETTING)); + s6dr171_write(lcd, SEQ_ETC_POWER_CONTROL, ARRAY_SIZE(SEQ_ETC_POWER_CONTROL)); - s6e8ax0_write(lcd, SEQ_ELVSS_CONTROL, ARRAY_SIZE(SEQ_ELVSS_CONTROL)); + s6dr171_write(lcd, SEQ_ELVSS_CONTROL, ARRAY_SIZE(SEQ_ELVSS_CONTROL)); return ret; } -static int s6e8ax0_ldi_enable(struct lcd_info *lcd) +static int s6dr171_ldi_enable(struct lcd_info *lcd) { int ret = 0; - s6e8ax0_write(lcd, SEQ_DISPLAY_ON, ARRAY_SIZE(SEQ_DISPLAY_ON)); + s6dr171_write(lcd, SEQ_DISPLAY_ON, ARRAY_SIZE(SEQ_DISPLAY_ON)); return ret; } -static int s6e8ax0_ldi_disable(struct lcd_info *lcd) +static int s6dr171_ldi_disable(struct lcd_info *lcd) { int ret = 0; - s6e8ax0_write(lcd, SEQ_DISPLAY_OFF, ARRAY_SIZE(SEQ_DISPLAY_OFF)); - s6e8ax0_write(lcd, SEQ_STANDBY_ON, ARRAY_SIZE(SEQ_STANDBY_ON)); + s6dr171_write(lcd, SEQ_DISPLAY_OFF, ARRAY_SIZE(SEQ_DISPLAY_OFF)); + s6dr171_write(lcd, SEQ_STANDBY_ON, ARRAY_SIZE(SEQ_STANDBY_ON)); return ret; } -static int s6e8ax0_power_on(struct lcd_info *lcd) +static int s6dr171_power_on(struct lcd_info *lcd) { int ret = 0; struct lcd_platform_data *pd = NULL; @@ -195,7 +198,7 @@ static int s6e8ax0_power_on(struct lcd_info *lcd) /* dev_info(&lcd->ld->dev, "%s\n", __func__); */ - ret = s6e8ax0_ldi_init(lcd); + ret = s6dr171_ldi_init(lcd); if (ret) { dev_err(&lcd->ld->dev, "failed to initialize ldi.\n"); goto err; @@ -203,7 +206,7 @@ static int s6e8ax0_power_on(struct lcd_info *lcd) msleep(120); - ret = s6e8ax0_ldi_enable(lcd); + ret = s6dr171_ldi_enable(lcd); if (ret) { dev_err(&lcd->ld->dev, "failed to enable ldi.\n"); goto err; @@ -216,7 +219,7 @@ err: return ret; } -static int s6e8ax0_power_off(struct lcd_info *lcd) +static int s6dr171_power_off(struct lcd_info *lcd) { int ret = 0; @@ -224,21 +227,21 @@ static int s6e8ax0_power_off(struct lcd_info *lcd) lcd->ldi_enable = 0; - ret = s6e8ax0_ldi_disable(lcd); + ret = s6dr171_ldi_disable(lcd); msleep(135); return ret; } -static int s6e8ax0_power(struct lcd_info *lcd, int power) +static int s6dr171_power(struct lcd_info *lcd, int power) { int ret = 0; if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->power)) - ret = s6e8ax0_power_on(lcd); + ret = s6dr171_power_on(lcd); else if (!POWER_IS_ON(power) && POWER_IS_ON(lcd->power)) - ret = s6e8ax0_power_off(lcd); + ret = s6dr171_power_off(lcd); if (!ret) lcd->power = power; @@ -246,7 +249,7 @@ static int s6e8ax0_power(struct lcd_info *lcd, int power) return ret; } -static int s6e8ax0_set_power(struct lcd_device *ld, int power) +static int s6dr171_set_power(struct lcd_device *ld, int power) { struct lcd_info *lcd = lcd_get_data(ld); @@ -256,17 +259,17 @@ static int s6e8ax0_set_power(struct lcd_device *ld, int power) return -EINVAL; } - return s6e8ax0_power(lcd, power); + return s6dr171_power(lcd, power); } -static int s6e8ax0_get_power(struct lcd_device *ld) +static int s6dr171_get_power(struct lcd_device *ld) { struct lcd_info *lcd = lcd_get_data(ld); return lcd->power; } -static int s6e8ax0_set_brightness(struct backlight_device *bd) +static int s6dr171_set_brightness(struct backlight_device *bd) { int ret = 0; int brightness = bd->props.brightness; @@ -292,13 +295,13 @@ static int s6e8ax0_set_brightness(struct backlight_device *bd) return ret; } -static struct lcd_ops s6e8ax0_lcd_ops = { - .set_power = s6e8ax0_set_power, - .get_power = s6e8ax0_get_power, +static struct lcd_ops s6dr171_lcd_ops = { + .set_power = s6dr171_set_power, + .get_power = s6dr171_get_power, }; -static const struct backlight_ops s6e8ax0_backlight_ops = { - .update_status = s6e8ax0_set_brightness, +static const struct backlight_ops s6dr171_backlight_ops = { + .update_status = s6dr171_set_brightness, }; static ssize_t power_reduce_show(struct device *dev, @@ -329,7 +332,7 @@ static ssize_t power_reduce_store(struct device *dev, mutex_lock(&lcd->bl_lock); lcd->acl_enable = value; /* if (lcd->ldi_enable) - s6e8ax0_set_acl(lcd); */ + s6dr171_set_acl(lcd); */ mutex_unlock(&lcd->bl_lock); } } @@ -389,25 +392,25 @@ static DEVICE_ATTR(auto_brightness, 0644, auto_brightness_show, auto_brightness_ #ifdef CONFIG_HAS_EARLYSUSPEND struct lcd_info *g_lcd; -void s6e8ax0_early_suspend(void) +void s6dr171_early_suspend(void) { struct lcd_info *lcd = g_lcd; set_dsim_lcd_enabled(0); dev_info(&lcd->ld->dev, "+%s\n", __func__); - s6e8ax0_power(lcd, FB_BLANK_POWERDOWN); + s6dr171_power(lcd, FB_BLANK_POWERDOWN); dev_info(&lcd->ld->dev, "-%s\n", __func__); return ; } -void s6e8ax0_late_resume(void) +void s6dr171_late_resume(void) { struct lcd_info *lcd = g_lcd; dev_info(&lcd->ld->dev, "+%s\n", __func__); - s6e8ax0_power(lcd, FB_BLANK_UNBLANK); + s6dr171_power(lcd, FB_BLANK_UNBLANK); dev_info(&lcd->ld->dev, "-%s\n", __func__); set_dsim_lcd_enabled(1); @@ -416,28 +419,28 @@ void s6e8ax0_late_resume(void) } #endif -static int s6e8ax0_read_mtp(struct lcd_info *lcd, u8 *mtp_data) +static int s6dr171_read_mtp(struct lcd_info *lcd, u8 *mtp_data) { int ret, i; for (i = 0; i < 3; i++) - ret = s6e8ax0_read(lcd, LDI_MTP_ADDR+i, LDI_MTP_LENGTH, mtp_data, 0); + ret = s6dr171_read(lcd, LDI_MTP_ADDR+i, LDI_MTP_LENGTH, mtp_data, 0); return ret; } -static void s6e8ax0_read_id(struct lcd_info *lcd, u8 *buf) +static void s6dr171_read_id(struct lcd_info *lcd, u8 *buf) { int ret = 0; - ret = s6e8ax0_read(lcd, LDI_ID_REG, LDI_ID_LEN, buf, 3); + ret = s6dr171_read(lcd, LDI_ID_REG, LDI_ID_LEN, buf, 3); if (!ret) { lcd->connected = 0; dev_info(&lcd->ld->dev, "panel is not connected well\n"); } } -static int s6e8ax0_probe(struct device *dev) +static int s6dr171_probe(struct device *dev) { int ret = 0; struct lcd_info *lcd; @@ -452,14 +455,14 @@ static int s6e8ax0_probe(struct device *dev) g_lcd = lcd; - lcd->ld = lcd_device_register("panel", dev, lcd, &s6e8ax0_lcd_ops); + lcd->ld = lcd_device_register("panel", dev, lcd, &s6dr171_lcd_ops); if (IS_ERR(lcd->ld)) { pr_err("failed to register lcd device\n"); ret = PTR_ERR(lcd->ld); goto out_free_lcd; } - lcd->bd = backlight_device_register("panel", dev, lcd, &s6e8ax0_backlight_ops, NULL); + lcd->bd = backlight_device_register("panel", dev, lcd, &s6dr171_backlight_ops, NULL); if (IS_ERR(lcd->bd)) { pr_err("failed to register backlight device\n"); ret = PTR_ERR(lcd->bd); @@ -498,18 +501,21 @@ static int s6e8ax0_probe(struct device *dev) mutex_init(&lcd->lock); mutex_init(&lcd->bl_lock); - s6e8ax0_read_id(lcd, lcd->id); + s6dr171_read_id(lcd, lcd->id); dev_info(&lcd->ld->dev, "ID: %x, %x, %x\n", lcd->id[0], lcd->id[1], lcd->id[2]); dev_info(&lcd->ld->dev, "lcd panel driver has been probed.\n"); - ret = s6e8ax0_read_mtp(lcd, mtp_data); + ret = s6dr171_read_mtp(lcd, mtp_data); if (!ret) { printk(KERN_ERR "[LCD:ERROR] : %s read mtp failed\n", __func__); /*return -EPERM;*/ } + lcd_early_suspend = s6dr171_early_suspend; + lcd_late_resume = s6dr171_late_resume; + return 0; out_free_backlight: @@ -525,11 +531,11 @@ err_alloc: return ret; } -static int __devexit s6e8ax0_remove(struct device *dev) +static int __devexit s6dr171_remove(struct device *dev) { struct lcd_info *lcd = dev_get_drvdata(dev); - s6e8ax0_power(lcd, FB_BLANK_POWERDOWN); + s6dr171_power(lcd, FB_BLANK_POWERDOWN); lcd_device_unregister(lcd->ld); backlight_device_unregister(lcd->bd); kfree(lcd); @@ -538,34 +544,34 @@ static int __devexit s6e8ax0_remove(struct device *dev) } /* Power down all displays on reboot, poweroff or halt. */ -static void s6e8ax0_shutdown(struct device *dev) +static void s6dr171_shutdown(struct device *dev) { struct lcd_info *lcd = dev_get_drvdata(dev); dev_info(&lcd->ld->dev, "%s\n", __func__); - s6e8ax0_power(lcd, FB_BLANK_POWERDOWN); + s6dr171_power(lcd, FB_BLANK_POWERDOWN); } -static struct mipi_lcd_driver s6e8ax0_mipi_driver = { +static struct mipi_lcd_driver s6dr171_mipi_driver = { .name = "s6e8aa0", - .probe = s6e8ax0_probe, - .remove = __devexit_p(s6e8ax0_remove), - .shutdown = s6e8ax0_shutdown, + .probe = s6dr171_probe, + .remove = __devexit_p(s6dr171_remove), + .shutdown = s6dr171_shutdown, }; -static int s6e8ax0_init(void) +static int s6dr171_init(void) { - return s5p_dsim_register_lcd_driver(&s6e8ax0_mipi_driver); + return s5p_dsim_register_lcd_driver(&s6dr171_mipi_driver); } -static void s6e8ax0_exit(void) +static void s6dr171_exit(void) { return; } -module_init(s6e8ax0_init); -module_exit(s6e8ax0_exit); +module_init(s6dr171_init); +module_exit(s6dr171_exit); -MODULE_DESCRIPTION("MIPI-DSI S6E8AA0:AMS529HA01 (800x1280) Panel Driver"); +MODULE_DESCRIPTION("MIPI-DSI S6DR171:AMS480GZ01-0 (720x1280) Panel Driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/video/samsung/s6e63m0_gamma_grande.h b/drivers/video/samsung/s6e63m0_gamma_grande.h new file mode 100644 index 0000000..4692a78 --- /dev/null +++ b/drivers/video/samsung/s6e63m0_gamma_grande.h @@ -0,0 +1,229 @@ +#ifndef __S6E63M0_GAMMA_H__ +#define __S6E63M0_GAMMA_H__ + +#include "s6e63m0_param.h" + +#define ACL_PARAM_SIZE ARRAY_SIZE(acl_cutoff_50) +#define AID_PARAM_SIZE ARRAY_SIZE(SEQ_PANEL_CONDITION_SET_500MBPS) + +static const unsigned char SEQ_PANEL_CONDITION_SET_500MBPS[] = { + 0xF8, + 0x19, 0x35, 0x00, 0x00, 0x00, 0x94, 0x00, 0x3C, 0x7D, 0x10, + 0x27, 0x08, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0x6E, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x23, 0x6E, 0xC0, 0xC1, + 0x01, 0x81, 0xC1, 0x00, 0xC3, 0xF6, 0xF6, 0xC1 +}; + +static const unsigned char SEQ_PANEL_CONDITION_SET_500MBPS_46[] = { + 0xF8, + 0x3D, 0x35, 0x00, 0x00, 0x00, 0x93, 0x00, 0x3C, 0x7D, 0x08, + 0x27, 0x7D, 0x3F, 0x00, 0x00, 0x00, 0x20, 0x04, 0x08, 0x6E, + 0x00, 0x00, 0x00, 0x02, 0x08, 0x08, 0x23, 0x23, 0xC0, 0xC8, + 0x08, 0x48, 0xC1, 0x00, 0xC1, 0xFF, 0xFF, 0xC8 +}; + +static const unsigned char SEQ_PANEL_CONDITION_SET_480MBPS_46[] = { + 0xF8, + 0x3D, 0x32, 0x00, 0x00, 0x00, 0x8D, 0x00, 0x39, 0x78, 0x08, + 0x26, 0x78, 0x3C, 0x00, 0x00, 0x00, 0x20, 0x04, 0x08, 0x69, + 0x00, 0x00, 0x00, 0x02, 0x07, 0x07, 0x21, 0x21, 0xC0, 0xC8, + 0x08, 0x48, 0xC1, 0x00, 0xC1, 0xFF, 0xFF, 0xC8 +}; +#if !defined(CONFIG_MACH_M0_GRANDECTC) && !defined(CONFIG_MACH_IRON) +static const unsigned char SEQ_GAMMA_CONDITION_SET[] = { + 0xFA, + 0x01, 0x58, 0x1F, 0x63, 0xAC, 0xB4, 0x99, 0xAD, 0xBA, 0xA3, + 0xC0, 0xCB, 0xBB, 0x93, 0x9F, 0x8B, 0xAD, 0xB4, 0xA7, 0x00, + 0xBE, 0x00, 0xAB, 0x00, 0xE7 +}; +#endif +static const unsigned char SEQ_GAMMA_CONDITION_SET_A1_SM2[] = { + 0xFA, + 0x01, 0x71, 0x31, 0x7B, 0xA4, 0xB6, + 0x95, 0xA9, 0xBC, 0xA2, 0xBB, 0xC9, + 0xB6, 0x91, 0xA3, 0x8B, 0xAD, 0xB6, + 0xA9, 0x00, 0xD6, 0x00, 0xBE, 0x00, + 0xFC, +}; + +static const unsigned char SEQ_GAMMA_CONDITION_SET_A2_SM2[] = { + 0xFA, + 0x01, 0x5F, 0x2E, 0x67, 0xAA, 0xC6, + 0xAC, 0xB0, 0xC8, 0xBB, 0xBE, 0xCB, + 0xBD, 0x97, 0xA5, 0x91, 0xAF, 0xB8, + 0xAB, 0x00, 0xC2, 0x00, 0xBA, 0x00, 0xE2, +}; +#if !defined(CONFIG_MACH_M0_GRANDECTC) && !defined(CONFIG_MACH_IRON) +static const unsigned char SEQ_ETC_SOURCE_CONTROL[] = { + 0xF6, + 0x00, 0x02, 0x00 +}; +#endif + +static const unsigned char SEQ_ETC_PENTILE_CONTROL[] = { + 0xB6, + 0x0C, 0x02, 0x03, 0x32, 0xC0, + 0x44, 0x44, 0xC0, 0x00 +}; + +static const unsigned char SEQ_ETC_PENTILE_CONTROL_46[] = { + 0xB6, + 0x0C, 0x02, 0x03, 0x32, 0xFF, + 0x44, 0x44, 0xC0, 0x00 +}; + +static const unsigned char SEQ_ETC_NVM_SETTING[] = { + 0xD9, + 0x14, 0x40, 0x0C, 0xCB, 0xCE, + 0x6E, 0xC4, 0x07, 0xC0, 0x41, + 0xC1, 0x00, 0x60, 0x19 +}; + +static const unsigned char SEQ_ETC_NVM_SETTING_46[] = { + 0xD9, + 0x14, 0x40, 0x0C, 0xCB, 0xCE, + 0x6E, 0xC4, 0x07, 0xC0, 0x41, + 0xD0, 0x00, 0x60, 0x19 +}; + +static const unsigned char SEQ_ETC_POWER_CONTROL[] = { + 0xF4, + 0xCF, 0x0A, 0x15, 0x10, 0x19, 0x33, 0x02 +}; + +static const unsigned char SEQ_ETC_POWER_CONTROL_46[] = { + 0xF4, + 0xCF, 0x0A, 0x12, 0x10, 0x1E, 0x33, 0x02 +}; + + +enum { + ACL_STATUS_0P = 0, + ACL_STATUS_20P, + ACL_STATUS_33P, + ACL_STATUS_40P, + ACL_STATUS_43P, + ACL_STATUS_45P, + ACL_STATUS_48P, + ACL_STATUS_50P, + ACL_STATUS_52P, + ACL_STATUS_53P, + ACL_STATUS_55P, + ACL_STATUS_MAX +} ACL_STATUS; + +const unsigned char acl_cutoff_20[] = { + 0xC1, + 0x47, 0x53, 0x13, 0x53, 0x00, 0x00, + 0x02, 0xCF, 0x00, 0x00, 0x04, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x01, 0x04, 0x07, 0x0A, 0x0D, 0x10, + 0x12, 0x15, 0x18, 0x1B, 0x1E +}; + +const unsigned char acl_cutoff_33[] = { + 0xC1, + 0x47, 0x53, 0x13, 0x53, 0x00, 0x00, + 0x02, 0xCF, 0x00, 0x00, 0x04, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x01, 0x06, 0x0A, 0x0F, 0x14, 0x19, + 0x1D, 0x22, 0x27, 0x2B, 0x30 +}; + +const unsigned char acl_cutoff_40[] = { + 0xC1, + 0x47, 0x53, 0x13, 0x53, 0x00, 0x00, + 0x02, 0xCF, 0x00, 0x00, 0x04, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x01, 0x08, 0x0F, 0x15, 0x1C, 0x23, + 0x2A, 0x31, 0x37, 0x3E, 0x45 +}; + +const unsigned char acl_cutoff_43[] = { + 0xC1, + 0x47, 0x53, 0x13, 0x53, 0x00, 0x00, + 0x02, 0xCF, 0x00, 0x00, 0x04, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x01, 0x07, 0x0D, 0x14, 0x1A, 0x20, + 0x26, 0x2C, 0x33, 0x39, 0x3F +}; + +const unsigned char acl_cutoff_45[] = { + 0xC1, + 0x47, 0x53, 0x13, 0x53, 0x00, 0x00, + 0x02, 0xCF, 0x00, 0x00, 0x04, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x01, 0x07, 0x0E, 0x14, 0x1B, 0x21, + 0x27, 0x2E, 0x34, 0x3B, 0x41 +}; + +const unsigned char acl_cutoff_48[] = { + 0xC1, + 0x47, 0x53, 0x13, 0x53, 0x00, 0x00, + 0x02, 0xCF, 0x00, 0x00, 0x04, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x01, 0x08, 0x0F, 0x17, 0x1E, 0x25, + 0x2C, 0x33, 0x3B, 0x42, 0x49 +}; + +const unsigned char acl_cutoff_50[] = { + 0xC1, + 0x47, 0x53, 0x13, 0x53, 0x00, 0x00, + 0x02, 0xCF, 0x00, 0x00, 0x04, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x01, 0x09, 0x10, 0x18, 0x1F, 0x27, + 0x2E, 0x36, 0x3D, 0x45, 0x4C +}; + +const unsigned char acl_cutoff_52[] = { + 0xC1, + 0x47, 0x53, 0x13, 0x53, 0x00, 0x00, + 0x02, 0xCF, 0x00, 0x00, 0x04, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x01, 0x09, 0x11, 0x19, 0x21, 0x29, + 0x31, 0x39, 0x41, 0x49, 0x51 +}; + +const unsigned char acl_cutoff_53[] = { + 0xC1, + 0x47, 0x53, 0x13, 0x53, 0x00, 0x00, + 0x02, 0xCF, 0x00, 0x00, 0x04, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x01, 0x09, 0x11, 0x1A, 0x22, 0x2A, + 0x32, 0x3A, 0x43, 0x4B, 0x53 +}; + +const unsigned char acl_cutoff_55[] = { + 0xC1, + 0x47, 0x53, 0x13, 0x53, 0x00, 0x00, + 0x02, 0xCF, 0x00, 0x00, 0x04, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x01, 0x0A, 0x12, 0x1B, 0x23, 0x2C, + 0x35, 0x3D, 0x46, 0x4E, 0x57 +}; + +const unsigned char *ACL_CUTOFF_TABLE[ACL_STATUS_MAX] = { + SEQ_ACL_OFF, + acl_cutoff_20, + acl_cutoff_33, + acl_cutoff_40, + acl_cutoff_43, + acl_cutoff_45, + acl_cutoff_48, + acl_cutoff_50, + acl_cutoff_52, + acl_cutoff_53, + acl_cutoff_55, +}; + +#endif /* __S6E63M0_GAMMA_H__ */ diff --git a/drivers/video/samsung/s6e63m0_gamma_l.h b/drivers/video/samsung/s6e63m0_gamma_l.h new file mode 100644 index 0000000..8d57c5a --- /dev/null +++ b/drivers/video/samsung/s6e63m0_gamma_l.h @@ -0,0 +1,311 @@ +#ifndef __S6E63M0_GAMMA_L_H__ +#define __S6E63M0_GAMMA_L_H__ + +#include "s6e63m0_param.h" +#ifdef CONFIG_AID_DIMMING +#include "aid_s6e8aa0.h" +#endif + +static const unsigned char gamma22_20[] = { + 0xFA, 0x01, + 0x1F, 0x1F, 0x1F, 0xDF, 0x86, 0xF5, + 0xD5, 0xC7, 0xCF, 0xDF, 0xE0, 0xE0, + 0xC9, 0xC9, 0xCC, 0xD7, 0xD6, 0xD5, + 0x00, 0x68, 0x00, 0x68, 0x00, 0x75, +}; + +static const unsigned char gamma22_30[] = { + 0xFA, 0x01, + 0x1F, 0x1F, 0x1F, 0xDF, 0x86, 0xF5, + 0xD5, 0xC7, 0xCF, 0xDF, 0xE0, 0xE0, + 0xC9, 0xC9, 0xCC, 0xD7, 0xD6, 0xD5, + 0x00, 0x68, 0x00, 0x68, 0x00, 0x75, +}; + +static const unsigned char gamma22_40[] = { + 0xFA, 0x01, + 0x1F, 0x1F, 0x1F, 0xE5, 0xAA, 0xF2, + 0xD6, 0xCC, 0xCF, 0xE0, 0xE2, 0xE2, + 0xC8, 0xC9, 0xCA, 0xD2, 0xD2, 0xCF, + 0x00, 0x71, 0x00, 0x70, 0x00, 0x80, +}; + +static const unsigned char gamma22_50[] = { + 0xFA, 0x01, + 0x1F, 0x1F, 0x1F, 0xE7, 0xBB, 0xEE, + 0xD6, 0xCE, 0xD0, 0xE0, 0xE3, 0xE4, + 0xC5, 0xC4, 0xC5, 0xD2, 0xD2, 0xCF, + 0x00, 0x78, 0x00, 0x78, 0x00, 0x88, +}; + +static const unsigned char gamma22_60[] = { + 0xFA, 0x01, + 0x1F, 0x1F, 0x1F, 0xE9, 0xC4, 0xEB, + 0xD6, 0xD0, 0xD1, 0xE0, 0xE3, 0xE4, + 0xC3, 0xC2, 0xC2, 0xD2, 0xD1, 0xCF, + 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x8F, +}; + +static const unsigned char gamma22_70[] = { + 0xFA, 0x01, + 0x1F, 0x1F, 0x1F, 0xEA, 0xC9, 0xEA, + 0xD6, 0xD2, 0xD2, 0xDF, 0xE1, 0xE3, + 0xC2, 0xC1, 0xC0, 0xD1, 0xD0, 0xCE, + 0x00, 0x84, 0x00, 0x84, 0x00, 0x96, +}; + +static const unsigned char gamma22_80[] = { + 0xFA, 0x01, + 0x1F, 0x1F, 0x1F, 0xEB, 0xCC, 0xE9, + 0xD5, 0xD4, 0xD3, 0xDE, 0xE1, 0xE2, + 0xC2, 0xBF, 0xBF, 0xCF, 0xCF, 0xCC, + 0x00, 0x89, 0x00, 0x89, 0x00, 0x9C, +}; + +static const unsigned char gamma22_90[] = { + 0xFA, 0x01, + 0x1F, 0x1F, 0x1F, 0xEB, 0xD0, 0xE9, + 0xD4, 0xD5, 0xD4, 0xDF, 0xE0, 0xE1, + 0xC1, 0xBE, 0xBD, 0xCD, 0xCD, 0xCA, + 0x00, 0x8E, 0x00, 0x8F, 0x00, 0xA2, +}; + +static const unsigned char gamma22_100[] = { + 0xFA, 0x01, + 0x1F, 0x1F, 0x1F, 0xEA, 0xD2, 0xE7, + 0xD7, 0xD6, 0xD6, 0xDF, 0xDF, 0xE2, + 0xBF, 0xBD, 0xBC, 0xCD, 0xCD, 0xC9, + 0x00, 0x92, 0x00, 0x93, 0x00, 0xA7, +}; + +static const unsigned char gamma22_110[] = { + 0xFA, 0x01, + 0x1F, 0x1F, 0x1F, 0xEB, 0xD4, 0xE5, + 0xD6, 0xD6, 0xD7, 0xDE, 0xDF, 0xE0, + 0xBE, 0xBC, 0xBB, 0xCE, 0xCC, 0xC9, + 0x00, 0x96, 0x00, 0x97, 0x00, 0xAC, +}; + +static const unsigned char gamma22_120[] = { + 0xFA, 0x01, + 0x1F, 0x1F, 0x1F, 0xED, 0xD6, 0xE6, + 0xD6, 0xD7, 0xD8, 0xDE, 0xDE, 0xE0, + 0xBC, 0xBC, 0xB9, 0xCD, 0xCA, 0xC8, + 0x00, 0x9A, 0x00, 0x9C, 0x00, 0xB1, +}; + +static const unsigned char gamma22_130[] = { + 0xFA, 0x01, + 0x1F, 0x1F, 0x1F, 0xEC, 0xD7, 0xE6, + 0xD3, 0xD8, 0xD7, 0xDE, 0xDD, 0xDF, + 0xBD, 0xBB, 0xB8, 0xCA, 0xC9, 0xC6, + 0x00, 0x9F, 0x00, 0xA0, 0x00, 0xB7, +}; + +static const unsigned char gamma22_140[] = { + 0xFA, 0x01, + 0x1F, 0x1F, 0x1F, 0xEC, 0xD9, 0xE5, + 0xD4, 0xD8, 0xD9, 0xDE, 0xDD, 0xDF, + 0xBB, 0xB9, 0xB7, 0xCA, 0xC9, 0xC5, + 0x00, 0xA3, 0x00, 0xA4, 0x00, 0xBB, +}; + +static const unsigned char gamma22_150[] = { + 0xFA, 0x01, + 0x1F, 0x1F, 0x1F, 0xEC, 0xDA, 0xE5, + 0xD4, 0xD8, 0xD9, 0xDD, 0xDD, 0xDD, + 0xBB, 0xB9, 0xB6, 0xC9, 0xC7, 0xC5, + 0x00, 0xA6, 0x00, 0xA8, 0x00, 0xBF, +}; + +static const unsigned char gamma22_160[] = { + 0xFA, 0x01, + 0x1F, 0x1F, 0x1F, 0xED, 0xDB, 0xE6, + 0xD4, 0xD7, 0xD9, 0xDC, 0xDD, 0xDD, + 0xB9, 0xB8, 0xB4, 0xC9, 0xC6, 0xC4, + 0x00, 0xAA, 0x00, 0xAC, 0x00, 0xC4, +}; + +static const unsigned char gamma22_170[] = { + 0xFA, 0x01, + 0x1F, 0x1F, 0x1F, 0xEC, 0xDC, 0xE5, + 0xD5, 0xD8, 0xD9, 0xDD, 0xDC, 0xDD, + 0xBA, 0xB7, 0xB5, 0xC7, 0xC6, 0xC3, + 0x00, 0xAD, 0x00, 0xAF, 0x00, 0xC7, +}; + +static const unsigned char gamma22_180[] = { + 0xFA, 0x01, + 0x1F, 0x1F, 0x1F, 0xEE, 0xDD, 0xE6, + 0xD4, 0xD7, 0xD9, 0xDB, 0xDC, 0xDB, + 0xB9, 0xB7, 0xB4, 0xC6, 0xC4, 0xC2, + 0x00, 0xB1, 0x00, 0xB3, 0x00, 0xCC, +}; + +#ifdef CONFIG_AID_DIMMING +static const unsigned char gamma22_182[] = { + 0xFA, 0x01, + 0x1F, 0x1F, 0x1F, 0xEE, 0xDD, 0xE6, + 0xD4, 0xD7, 0xD9, 0xDB, 0xDC, 0xDB, + 0xB9, 0xB7, 0xB4, 0xC6, 0xC4, 0xC2, + 0x00, 0xB1, 0x00, 0xB3, 0x00, 0xCC, +}; + +static const unsigned char gamma22_184[] = { + 0xFA, 0x01, + 0x1F, 0x1F, 0x1F, 0xEE, 0xDD, 0xE6, + 0xD4, 0xD7, 0xD9, 0xDB, 0xDC, 0xDB, + 0xB9, 0xB7, 0xB4, 0xC6, 0xC4, 0xC2, + 0x00, 0xB1, 0x00, 0xB3, 0x00, 0xCC, +}; + +static const unsigned char gamma22_186[] = { + 0xFA, 0x01, + 0x1F, 0x1F, 0x1F, 0xEE, 0xDD, 0xE6, + 0xD4, 0xD7, 0xD9, 0xDB, 0xDC, 0xDB, + 0xB9, 0xB7, 0xB4, 0xC6, 0xC4, 0xC2, + 0x00, 0xB1, 0x00, 0xB3, 0x00, 0xCC, +}; + +static const unsigned char gamma22_188[] = { + 0xFA, 0x01, + 0x1F, 0x1F, 0x1F, 0xEE, 0xDD, 0xE6, + 0xD4, 0xD7, 0xD9, 0xDB, 0xDC, 0xDB, + 0xB9, 0xB7, 0xB4, 0xC6, 0xC4, 0xC2, + 0x00, 0xB1, 0x00, 0xB3, 0x00, 0xCC, +}; +#endif + +static const unsigned char gamma22_190[] = { + 0xFA, 0x01, + 0x1F, 0x1F, 0x1F, 0xED, 0xDE, 0xE6, + 0xD3, 0xD8, 0xD8, 0xDD, 0xDB, 0xDC, + 0xB9, 0xB6, 0xB4, 0xC5, 0xC4, 0xC0, + 0x00, 0xB4, 0x00, 0xB6, 0x00, 0xD0, +}; + +static const unsigned char gamma22_200[] = { + 0xFA, 0x01, + 0x1F, 0x1F, 0x1F, 0xED, 0xDF, 0xE6, + 0xD3, 0xD7, 0xD8, 0xDB, 0xDB, 0xDA, + 0xB8, 0xB6, 0xB3, 0xC4, 0xC3, 0xC0, + 0x00, 0xB8, 0x00, 0xB9, 0x00, 0xD4, +}; + +static const unsigned char gamma22_210[] = { + 0xFA, 0x01, + 0x1F, 0x1F, 0x1F, 0xEC, 0xE0, 0xE5, + 0xD5, 0xD7, 0xD9, 0xDB, 0xDA, 0xDA, + 0xB7, 0xB5, 0xB1, 0xC4, 0xC2, 0xC0, + 0x00, 0xBA, 0x00, 0xBD, 0x00, 0xD7, +}; + +static const unsigned char gamma22_220[] = { + 0xFA, 0x01, + 0x1F, 0x1F, 0x1F, 0xED, 0xE0, 0xE6, + 0xD4, 0xD7, 0xD9, 0xDA, 0xDA, 0xD9, + 0xB7, 0xB4, 0xB1, 0xC2, 0xC2, 0xBE, + 0x00, 0xBE, 0x00, 0xC0, 0x00, 0xDC, +}; + +static const unsigned char gamma22_230[] = { + 0xFA, 0x01, + 0x1F, 0x1F, 0x1F, 0xEC, 0xE2, 0xE6, + 0xD3, 0xD6, 0xD8, 0xDC, 0xD9, 0xD9, + 0xB6, 0xB4, 0xB1, 0xC1, 0xC1, 0xBD, + 0x00, 0xC1, 0x00, 0xC3, 0x00, 0xDF, +}; + +static const unsigned char gamma22_240[] = { + 0xFA, 0x01, + 0x1F, 0x1F, 0x1F, 0xED, 0xE2, 0xE6, + 0xD4, 0xD6, 0xD8, 0xDA, 0xDA, 0xDA, + 0xB6, 0xB3, 0xB0, 0xC1, 0xBF, 0xBC, + 0x00, 0xC4, 0x00, 0xC7, 0x00, 0xE3, +}; + +static const unsigned char gamma22_250[] = { + 0xFA, 0x01, + 0x1F, 0x1F, 0x1F, 0xED, 0xE3, 0xE7, + 0xD4, 0xD6, 0xD8, 0xDB, 0xD9, 0xD9, + 0xB3, 0xB2, 0xAE, 0xC1, 0xC0, 0xBC, + 0x00, 0xC7, 0x00, 0xC9, 0x00, 0xE7, +}; + +static const unsigned char gamma22_260[] = { + 0xFA, 0x01, + 0x1F, 0x1F, 0x1F, 0xED, 0xE4, 0xE7, + 0xD4, 0xD5, 0xD7, 0xDA, 0xD9, 0xD9, + 0xB3, 0xB2, 0xAD, 0xC1, 0xBE, 0xBC, + 0x00, 0xC9, 0x00, 0xCD, 0x00, 0xEA, +}; + +static const unsigned char gamma22_270[] = { + 0xFA, 0x01, + 0x1F, 0x1F, 0x1F, 0xED, 0xE5, 0xE8, + 0xD3, 0xD5, 0xD5, 0xDB, 0xD9, 0xD9, + 0xB3, 0xB1, 0xAE, 0xBF, 0xBE, 0xBA, + 0x00, 0xCC, 0x00, 0xD0, 0x00, 0xEE, +}; + +static const unsigned char gamma22_280[] = { + 0xFA, 0x01, + 0x1F, 0x1F, 0x1F, 0xEC, 0xE5, 0xE6, + 0xD2, 0xD4, 0xD6, 0xDA, 0xD9, 0xD8, + 0xB3, 0xB1, 0xAD, 0xBF, 0xBD, 0xBA, + 0x00, 0xCF, 0x00, 0xD3, 0x00, 0xF1, +}; + +static const unsigned char gamma22_290[] = { + 0xFA, 0x01, + 0x1F, 0x1F, 0x1F, 0xEC, 0xE6, 0xE7, + 0xD2, 0xD4, 0xD5, 0xDB, 0xD8, 0xD8, + 0xB1, 0xB0, 0xAC, 0xBE, 0xBD, 0xB9, + 0x00, 0xD3, 0x00, 0xD6, 0x00, 0xF5, +}; + +static const unsigned char gamma22_300[] = { + 0xFA, 0x01, + 0x1F, 0x1F, 0x1F, 0xED, 0xE6, 0xE7, + 0xD1, 0xD3, 0xD4, 0xDA, 0xD8, 0xD7, + 0xB1, 0xAF, 0xAB, 0xBD, 0xBB, 0xB8, + 0x00, 0xD6, 0x00, 0xDA, 0x00, 0xFA, +}; + +static const unsigned char *gamma22_table[GAMMA_MAX] = { +#ifdef CONFIG_AID_DIMMING + gamma22_20, +#endif + gamma22_30, + gamma22_40, + gamma22_50, + gamma22_60, + gamma22_70, + gamma22_80, + gamma22_90, + gamma22_100, + gamma22_110, + gamma22_120, + gamma22_130, + gamma22_140, + gamma22_150, + gamma22_160, + gamma22_170, + gamma22_180, +#ifdef CONFIG_AID_DIMMING + gamma22_182, + gamma22_184, + gamma22_186, + gamma22_188, +#endif + gamma22_190, + gamma22_200, + gamma22_210, + gamma22_220, + gamma22_230, + gamma22_240, + gamma22_250, + gamma22_300, +}; + +#endif /* __S6E63M0_GAMMA_L_H__ */ diff --git a/drivers/video/samsung/s6e63m0_param.h b/drivers/video/samsung/s6e63m0_param.h new file mode 100644 index 0000000..c69ed45b --- /dev/null +++ b/drivers/video/samsung/s6e63m0_param.h @@ -0,0 +1,375 @@ +#ifndef __S6E63M0_PARAM_H__ +#define __S6E63M0_PARAM_H__ + +#define GAMMA_PARAM_SIZE 26 +#define ELVSS_PARAM_SIZE 3 + +#define ELVSS_OFFSET_300 0x00 +#define ELVSS_OFFSET_290 0x01 +#define ELVSS_OFFSET_280 0x02 +#define ELVSS_OFFSET_270 0x03 +#define ELVSS_OFFSET_260 0x04 +#define ELVSS_OFFSET_250 0x05 +#define ELVSS_OFFSET_240 0x06 +#define ELVSS_OFFSET_230 0x06 +#define ELVSS_OFFSET_220 0x07 +#define ELVSS_OFFSET_210 0x08 +#define ELVSS_OFFSET_200 0x09 +#define ELVSS_OFFSET_190 0x05 +#define ELVSS_OFFSET_180 0x05 +#define ELVSS_OFFSET_170 0x06 +#define ELVSS_OFFSET_160 0x07 +#define ELVSS_OFFSET_150 0x08 +#define ELVSS_OFFSET_140 0x09 +#define ELVSS_OFFSET_130 0x0A +#define ELVSS_OFFSET_120 0x0B +#define ELVSS_OFFSET_110 0x0C +#define ELVSS_OFFSET_100 0x0D +#define ELVSS_OFFSET_090 0x0E +#define ELVSS_OFFSET_080 0x0F +#define ELVSS_OFFSET_070 0x10 +#define ELVSS_OFFSET_060 0x11 +#define ELVSS_OFFSET_050 0x12 + +#if defined(CONFIG_MACH_Q1_BD) +#define ELVSS_OFFSET_MAX ELVSS_OFFSET_300 +#define ELVSS_OFFSET_1 ELVSS_OFFSET_210 +#define ELVSS_OFFSET_2 ELVSS_OFFSET_100 +#define ELVSS_OFFSET_MIN ELVSS_OFFSET_060 +#else +#define ELVSS_OFFSET_MAX ELVSS_OFFSET_300 +#define ELVSS_OFFSET_1 ELVSS_OFFSET_210 +#define ELVSS_OFFSET_2 ELVSS_OFFSET_1 +#define ELVSS_OFFSET_MIN ELVSS_OFFSET_050 +#endif + +#ifdef CONFIG_AID_DIMMING +enum { + ELVSS_110 = 0, + ELVSS_120, + ELVSS_130, + ELVSS_140, + ELVSS_150, + ELVSS_160, + ELVSS_170, + ELVSS_180, + ELVSS_190, + ELVSS_200, + ELVSS_210, + ELVSS_220, + ELVSS_230, + ELVSS_240, + ELVSS_250, + ELVSS_260, + ELVSS_270, + ELVSS_280, + ELVSS_290, + ELVSS_300, + ELVSS_STATUS_MAX, +}; + +#else +enum { + ELVSS_MIN = 0, + ELVSS_1, + ELVSS_2, + ELVSS_MAX, + ELVSS_STATUS_MAX, +}; +#endif + +enum { + GAMMA_20CD, +#ifdef CONFIG_AID_DIMMING + GAMMA_30CD, +#else + GAMMA_30CD = GAMMA_20CD, +#endif + GAMMA_40CD, + GAMMA_50CD, + GAMMA_60CD, + GAMMA_70CD, + GAMMA_80CD, + GAMMA_90CD, + GAMMA_100CD, + GAMMA_110CD, + GAMMA_120CD, + GAMMA_130CD, + GAMMA_140CD, + GAMMA_150CD, + GAMMA_160CD, + GAMMA_170CD, + GAMMA_180CD, +#ifdef CONFIG_AID_DIMMING + GAMMA_182CD, + GAMMA_184CD, + GAMMA_186CD, + GAMMA_188CD, +#endif + GAMMA_190CD, + GAMMA_200CD, + GAMMA_210CD, + GAMMA_220CD, + GAMMA_230CD, + GAMMA_240CD, + GAMMA_250CD, + GAMMA_290CD, + GAMMA_300CD = GAMMA_290CD, + GAMMA_MAX +}; + +#if 0 +static const unsigned char SEQ_APPLY_LEVEL_2_KEY[] = { + 0xFC, + 0x5A, 0x5A +}; + +static const unsigned char SEQ_APPLY_LEVEL_2[] = { + 0xF0, + 0x5A, 0x5A +}; + +static const unsigned char SEQ_APPLY_MTP_KEY_ENABLE[] = { + 0xF1, + 0x5A, 0x5A +}; + +static const unsigned char SEQ_SLEEP_OUT[] = { + 0x11, + 0x00, 0x00 +}; + +static const unsigned char SEQ_DISPLAY_CONDITION_SET[] = { + 0xF2, + 0x80, 0x03, 0x0D +}; + +static const unsigned char SEQ_GAMMA_UPDATE[] = { + 0xF7, 0x03, + 0x00 +}; + +static const unsigned char SEQ_ELVSS_CONTROL[] = { + 0xB1, + 0x04, 0x00 +}; + +static const unsigned char SEQ_DISPLAY_ON[] = { + 0x29, + 0x00, 0x00 +}; + +static const unsigned char SEQ_DISPLAY_OFF[] = { + 0x28, + 0x00, 0x00 +}; + +static const unsigned char SEQ_STANDBY_ON[] = { + 0x01, + 0x00, 0x00 +}; + +static const unsigned char SEQ_ACL_ON[] = { + 0xC0, 0x01, + 0x00 +}; + +static const unsigned char SEQ_ACL_OFF[] = { + 0xC0, 0x00, + 0x00 +}; + +static const unsigned char SEQ_ELVSS_32[] = { + 0xB1, + 0x04, 0x9F +}; + +static const unsigned char SEQ_ELVSS_34[] = { + 0xB1, + 0x04, 0x9D +}; + +static const unsigned char SEQ_ELVSS_38[] = { + 0xB1, + 0x04, 0x99 +}; + +static const unsigned char SEQ_ELVSS_47[] = { + 0xB1, + 0x04, 0x90 +}; + +static const unsigned char *ELVSS_TABLE[] = { + SEQ_ELVSS_32, + SEQ_ELVSS_34, + SEQ_ELVSS_38, + SEQ_ELVSS_47, +}; +#endif + +#if defined(CONFIG_MACH_M0_GRANDECTC) || defined(CONFIG_MACH_IRON) +static const unsigned char SEQ_SW_RESET[] = { + 0x01, + 0x00, 0x00 +}; +#endif + +static const unsigned char SEQ_APPLY_LEVEL2_KEY_ENABLE[] = { + 0xF0, + 0x5A, 0x5A +}; + +static const unsigned char SEQ_APPLY_MTP_KEY_ENABLE[] = { + 0xF1, + 0x5A, 0x5A +}; + +static const unsigned char SEQ_SLEEP_OUT[] = { + 0x11, + 0x00, 0x00 +}; + +static const unsigned char SEQ_GAMMA_CONDITION_SET[] = { + 0xFA, + 0x02, 0x18, 0x08, 0x24, 0x6B, 0x76, 0x57, 0xBD, 0xC3, 0xB5, + 0xB4, 0xBB, 0xAC, 0xC5, 0xC9, 0xC0, 0x00, 0xB7, 0x00, 0xAB, + 0x00, 0xCF, +}; + +const unsigned char SEQ_PANEL_CONDITION_SET[] = { + 0xF8, + 0x01, 0x27, 0x27, 0x07, 0x07, 0x54, 0x9F, 0x63, 0x86, 0x1A, + 0x33, 0x0D, 0x00, 0x00, +}; + +const unsigned char SEQ_DISPLAY_CONDITION_SET1[] = { + 0xF2, + 0x02, 0x03, 0x1C, 0x10, 0x10, +}; + +const unsigned char SEQ_DISPLAY_CONDITION_SET2[] = { + 0xF7, + 0x10, 0x00, 0x00, +}; + +static const unsigned char SEQ_GAMMA_UPDATE[] = { + 0xFA, 0x03, +}; + +static const unsigned char SEQ_ETC_SOURCE_CONTROL[] = { + 0xF6, + 0x00, 0x8E, 0x07, +}; + +static const unsigned char SEQ_ETC_CONTROL_B3h[] = { + 0xB3, 0x0C, +}; + +#if 0 +static const unsigned char SEQ_ETC_CONTROL_B5h[] = { + 0xB5, + 0x2C, 0x12, 0x0C, 0x0A, 0x10, 0x0E, 0x17, 0x13, + 0x1F, 0x1A, 0x2A, 0x24, 0x1F, 0x1B, 0x1A, 0x17, + 0x2B, 0x26, 0x22, 0x20, 0x3A, 0x34, 0x30, 0x2C, + 0x29, 0x26, 0x25, 0x23, 0x21, 0x20, 0x1E, 0x1E, +}; + +static const unsigned char SEQ_ETC_CONTROL_B6h[] = { + 0xB6, + 0x00, 0x00, 0x11, 0x22, 0x33, 0x44, 0x44, 0x44, + 0x55, 0x55, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, +}; + +static const unsigned char SEQ_ETC_CONTROL_B7h[] = { + 0xB7, + 0x2C, 0x12, 0x0C, 0x0A, 0x10, 0x0E, 0x17, 0x13, + 0x1F, 0x1A, 0x2A, 0x24, 0x1F, 0x1B, 0x1A, 0x17, + 0x2B, 0x26, 0x22, 0x20, 0x3A, 0x34, 0x30, 0x2C, + 0x29, 0x26, 0x25, 0x23, 0x21, 0x20, 0x1E, 0x1E, +}; + +static const unsigned char SEQ_ETC_CONTROL_B8h[] = { + 0xB8, + 0x00, 0x00, 0x11, 0x22, 0x33, 0x44, 0x44, 0x44, + 0x55, 0x55, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, +}; + +static const unsigned char SEQ_ETC_CONTROL_B9h[] = { + 0xB9, + 0x2C, 0x12, 0x0C, 0x0A, 0x10, 0x0E, 0x17, 0x13, + 0x1F, 0x1A, 0x2A, 0x24, 0x1F, 0x1B, 0x1A, 0x17, + 0x2B, 0x26, 0x22, 0x20, 0x3A, 0x34, 0x30, 0x2C, + 0x29, 0x26, 0x25, 0x23, 0x21, 0x20, 0x1E, 0x1E, +}; + +static const unsigned char SEQ_ETC_CONTROL_BAh[] = { + 0xBA, + 0x00, 0x00, 0x11, 0x22, 0x33, 0x44, 0x44, 0x44, + 0x55, 0x55, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, +}; +#endif + +const unsigned char SEQ_STANDBY_ON[] = { + 0x10, + 0x00, 0x00 +}; + +const unsigned char SEQ_DISPLAY_ON[] = { + 0x29, + 0x00, 0x00 +}; + +const unsigned char SEQ_DISPLAY_OFF[] = { + 0x28, + 0x00, 0x00 +}; + +const unsigned char SEQ_ELVSS_SET[] = { + 0xB2, + 0x17, 0x17, 0x17, 0x17, +}; + +const unsigned char SEQ_ELVSS_ON[] = { + 0xB1, 0x0B, + 0x00, +}; + + +static const unsigned char SEQ_ACL_ON[] = { + 0xC0, 0x01, + 0x00 +}; + +static const unsigned char SEQ_ACL_OFF[] = { + 0xC0, 0x00, + 0x00 +}; + +static const unsigned char SEQ_ELVSS_32[] = { + 0xB1, + 0x04, 0x9F +}; + +static const unsigned char SEQ_ELVSS_34[] = { + 0xB1, + 0x04, 0x9D +}; + +static const unsigned char SEQ_ELVSS_38[] = { + 0xB1, + 0x04, 0x99 +}; + +static const unsigned char SEQ_ELVSS_47[] = { + 0xB1, + 0x04, 0x90 +}; + +static const unsigned char *ELVSS_TABLE[] = { + SEQ_ELVSS_32, + SEQ_ELVSS_34, + SEQ_ELVSS_38, + SEQ_ELVSS_47, +}; + +#endif /* __S6E63M0_PARAM_H__ */ diff --git a/drivers/video/samsung/s6e8aa0_gamma_q1.h b/drivers/video/samsung/s6e8aa0_gamma_q1.h index 075f66e4..b0b5f0d 100644 --- a/drivers/video/samsung/s6e8aa0_gamma_q1.h +++ b/drivers/video/samsung/s6e8aa0_gamma_q1.h @@ -29,7 +29,6 @@ static const unsigned char SEQ_PANEL_CONDITION_SET[] = { 0x01, 0x81, 0xC1, 0x00, 0xC8, 0xC1, 0xD3, 0x01 }; - static const unsigned char SEQ_ETC_SOURCE_CONTROL[] = { 0xF6, 0x00, 0x02, 0x00 @@ -54,6 +53,11 @@ static const unsigned char SEQ_ELVSS_NVM_SETTING[] = { 0xD9, 0x00, 0x00, 0x00 }; +static const unsigned char SEQ_LTPS_DELAY[] = { + 0xFE, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x0B, 0x53, 0x3C +}; static const unsigned char SEQ_ACL_CUTOFF_20[] = { 0xC1, diff --git a/drivers/video/samsung/s6e8aa0_param.h b/drivers/video/samsung/s6e8aa0_param.h index 3ac11ad..8db68a6 100644 --- a/drivers/video/samsung/s6e8aa0_param.h +++ b/drivers/video/samsung/s6e8aa0_param.h @@ -96,6 +96,12 @@ enum { GAMMA_80CD, GAMMA_90CD, GAMMA_100CD, +#ifdef CONFIG_AID_DIMMING + GAMMA_102CD, + GAMMA_104CD, + GAMMA_106CD, + GAMMA_108CD, +#endif GAMMA_110CD, GAMMA_120CD, GAMMA_130CD, diff --git a/drivers/video/samsung/s6e8aa1.c b/drivers/video/samsung/s6e8aa1.c new file mode 100644 index 0000000..82effe4 --- /dev/null +++ b/drivers/video/samsung/s6e8aa1.c @@ -0,0 +1,568 @@ +/* linux/drivers/video/samsung/s6e8aa1.c + * + * MIPI-DSI based AMS529HA01 AMOLED lcd panel 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/mutex.h> +#include <linux/wait.h> +#include <linux/ctype.h> +#include <linux/io.h> +#include <linux/delay.h> +#include <linux/irq.h> +#include <linux/interrupt.h> +#include <linux/gpio.h> +#include <linux/workqueue.h> +#include <linux/backlight.h> +#include <linux/lcd.h> +#include <plat/gpio-cfg.h> +#include <plat/regs-dsim.h> +#include <mach/dsim.h> +#include <mach/mipi_ddi.h> +#ifdef CONFIG_HAS_EARLYSUSPEND +#include <linux/earlysuspend.h> +#endif + +#include "s5p-dsim.h" +#include "s3cfb.h" + +#include "s6e8aa1_param.h" + +#define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL) + +#define MIN_BRIGHTNESS 0 +#define MAX_BRIGHTNESS 255 +#define MAX_GAMMA 300 +#define DEFAULT_BRIGHTNESS 160 +#define DEFAULT_GAMMA_LEVEL 0 + +#define LDI_ID_REG 0xD1 +#define LDI_ID_LEN 3 + +#define LDI_MTP_ADDR 0xCB +#define LDI_MTP_LENGTH 63 + +struct lcd_info { + unsigned int bl; + unsigned int auto_brightness; + unsigned int acl_enable; + unsigned int cur_acl; + unsigned int current_bl; + unsigned int current_elvss; + + unsigned int ldi_enable; + unsigned int power; + struct mutex lock; + struct mutex bl_lock; + + struct device *dev; + struct lcd_device *ld; + struct backlight_device *bd; + struct lcd_platform_data *lcd_pd; + struct early_suspend early_suspend; + + unsigned char id[LDI_ID_LEN]; + + unsigned char **gamma_table; + unsigned char **elvss_table; + + unsigned int irq; + unsigned int connected; + + struct dsim_global *dsim; +}; + +static int s6e8ax0_write(struct lcd_info *lcd, const unsigned char *seq, int len) +{ + int size; + const unsigned char *wbuf; + + if (!lcd->connected) + return 0; + + mutex_lock(&lcd->lock); + + size = len; + wbuf = seq; + + if (size == 1) + lcd->dsim->ops->cmd_write(lcd->dsim, DCS_WR_NO_PARA, wbuf[0], 0); + else if (size == 2) + lcd->dsim->ops->cmd_write(lcd->dsim, DCS_WR_1_PARA, wbuf[0], wbuf[1]); + else + lcd->dsim->ops->cmd_write(lcd->dsim, DCS_LONG_WR, (unsigned int)wbuf, size); + + mutex_unlock(&lcd->lock); + + return 0; +} + +static int _s6e8ax0_read(struct lcd_info *lcd, const u8 addr, u16 count, u8 *buf) +{ + int ret = 0; + + if (!lcd->connected) + return ret; + + mutex_lock(&lcd->lock); + + if (lcd->dsim->ops->cmd_read) + ret = lcd->dsim->ops->cmd_read(lcd->dsim, addr, count, buf); + + mutex_unlock(&lcd->lock); + + return ret; +} + +static int s6e8ax0_read(struct lcd_info *lcd, const u8 addr, u16 count, u8 *buf, u8 retry_cnt) +{ + int ret = 0; + +read_retry: + ret = _s6e8ax0_read(lcd, addr, count, buf); + if (!ret) { + if (retry_cnt) { + printk(KERN_WARNING "[WARN:LCD] %s : retry cnt : %d\n", __func__, retry_cnt); + retry_cnt--; + goto read_retry; + } else + printk(KERN_ERR "[ERROR:LCD] %s : 0x%02x read failed\n", __func__, addr); + } + + return ret; +} + +static int s6e8ax0_ldi_init(struct lcd_info *lcd) +{ + int ret = 0; + + s6e8ax0_write(lcd, SEQ_APPLY_MTP_KEY_ENABLE, ARRAY_SIZE(SEQ_APPLY_MTP_KEY_ENABLE)); + s6e8ax0_write(lcd, SEQ_SLEEP_OUT, ARRAY_SIZE(SEQ_SLEEP_OUT)); + msleep(22); + + s6e8ax0_write(lcd, SEQ_PANEL_CONDITION_SET, ARRAY_SIZE(SEQ_PANEL_CONDITION_SET)); + s6e8ax0_write(lcd, SEQ_DISPLAY_CONDITION_SET, ARRAY_SIZE(SEQ_DISPLAY_CONDITION_SET)); + s6e8ax0_write(lcd, SEQ_GAMMA_CONDITION_SET, ARRAY_SIZE(SEQ_GAMMA_CONDITION_SET)); + s6e8ax0_write(lcd, SEQ_GAMMA_UPDATE, ARRAY_SIZE(SEQ_GAMMA_UPDATE)); + + s6e8ax0_write(lcd, SEQ_ETC_SOURCE_CONTROL, ARRAY_SIZE(SEQ_ETC_SOURCE_CONTROL)); + s6e8ax0_write(lcd, SEQ_ETC_PENTILE_CONTROL, ARRAY_SIZE(SEQ_ETC_PENTILE_CONTROL)); + s6e8ax0_write(lcd, SEQ_ELVSS_CONTROL, ARRAY_SIZE(SEQ_ELVSS_CONTROL)); + s6e8ax0_write(lcd, SEQ_ETC_NVM_SETTING, ARRAY_SIZE(SEQ_ETC_NVM_SETTING)); + + return ret; +} + +static int s6e8ax0_ldi_enable(struct lcd_info *lcd) +{ + int ret = 0; + + s6e8ax0_write(lcd, SEQ_DISPLAY_ON, ARRAY_SIZE(SEQ_DISPLAY_ON)); + + return ret; +} + +static int s6e8ax0_ldi_disable(struct lcd_info *lcd) +{ + int ret = 0; + + s6e8ax0_write(lcd, SEQ_DISPLAY_OFF, ARRAY_SIZE(SEQ_DISPLAY_OFF)); + s6e8ax0_write(lcd, SEQ_STANDBY_ON, ARRAY_SIZE(SEQ_STANDBY_ON)); + + return ret; +} + +static int s6e8ax0_power_on(struct lcd_info *lcd) +{ + int ret = 0; + struct lcd_platform_data *pd = NULL; + pd = lcd->lcd_pd; + + /* dev_info(&lcd->ld->dev, "%s\n", __func__); */ + + ret = s6e8ax0_ldi_init(lcd); + if (ret) { + dev_err(&lcd->ld->dev, "failed to initialize ldi.\n"); + goto err; + } + + msleep(120); + + ret = s6e8ax0_ldi_enable(lcd); + if (ret) { + dev_err(&lcd->ld->dev, "failed to enable ldi.\n"); + goto err; + } + + lcd->ldi_enable = 1; + + /* update_brightness(lcd, 1); */ +err: + return ret; +} + +static int s6e8ax0_power_off(struct lcd_info *lcd) +{ + int ret = 0; + + dev_info(&lcd->ld->dev, "%s\n", __func__); + + lcd->ldi_enable = 0; + + ret = s6e8ax0_ldi_disable(lcd); + + msleep(135); + + return ret; +} + +static int s6e8ax0_power(struct lcd_info *lcd, int power) +{ + int ret = 0; + + if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->power)) + ret = s6e8ax0_power_on(lcd); + else if (!POWER_IS_ON(power) && POWER_IS_ON(lcd->power)) + ret = s6e8ax0_power_off(lcd); + + if (!ret) + lcd->power = power; + + return ret; +} + +static int s6e8ax0_set_power(struct lcd_device *ld, int power) +{ + struct lcd_info *lcd = lcd_get_data(ld); + + if (power != FB_BLANK_UNBLANK && power != FB_BLANK_POWERDOWN && + power != FB_BLANK_NORMAL) { + dev_err(&lcd->ld->dev, "power value should be 0, 1 or 4.\n"); + return -EINVAL; + } + + return s6e8ax0_power(lcd, power); +} + +static int s6e8ax0_get_power(struct lcd_device *ld) +{ + struct lcd_info *lcd = lcd_get_data(ld); + + return lcd->power; +} + +static int s6e8ax0_set_brightness(struct backlight_device *bd) +{ + int ret = 0; + int brightness = bd->props.brightness; + struct lcd_info *lcd = bl_get_data(bd); + + /* dev_info(&lcd->ld->dev, "%s: brightness=%d\n", __func__, brightness); */ + + if (brightness < MIN_BRIGHTNESS || + brightness > bd->props.max_brightness) { + dev_err(&bd->dev, "lcd brightness should be %d to %d. now %d\n", + MIN_BRIGHTNESS, MAX_BRIGHTNESS, brightness); + return -EINVAL; + } + + if (lcd->ldi_enable) { + /* ret = update_brightness(lcd, 0); */ + if (ret < 0) { + dev_err(lcd->dev, "err in %s\n", __func__); + return -EINVAL; + } + } + + return ret; +} + +static int s6e8ax0_check_fb(struct lcd_device *ld, struct fb_info *fb) +{ + struct s3cfb_window *win = fb->par; + struct lcd_info *lcd = lcd_get_data(ld); + + dev_info(&lcd->ld->dev, "%s, fb%d\n", __func__, win->id); + + return 0; +} + +static struct lcd_ops s6e8ax0_lcd_ops = { + .set_power = s6e8ax0_set_power, + .get_power = s6e8ax0_get_power, + .check_fb = s6e8ax0_check_fb, +}; + +static const struct backlight_ops s6e8ax0_backlight_ops = { + .update_status = s6e8ax0_set_brightness, +}; + +static ssize_t power_reduce_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct lcd_info *lcd = dev_get_drvdata(dev); + char temp[3]; + + sprintf(temp, "%d\n", lcd->acl_enable); + strcpy(buf, temp); + + return strlen(buf); +} + +static ssize_t power_reduce_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + struct lcd_info *lcd = dev_get_drvdata(dev); + int value; + int rc; + + rc = strict_strtoul(buf, (unsigned int)0, (unsigned long *)&value); + if (rc < 0) + return rc; + else { + if (lcd->acl_enable != value) { + dev_info(dev, "%s - %d, %d\n", __func__, lcd->acl_enable, value); + mutex_lock(&lcd->bl_lock); + lcd->acl_enable = value; + /* if (lcd->ldi_enable) + s6e8ax0_set_acl(lcd); */ + mutex_unlock(&lcd->bl_lock); + } + } + return size; +} + +static DEVICE_ATTR(power_reduce, 0664, power_reduce_show, power_reduce_store); + +static ssize_t lcd_type_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + char temp[15]; + sprintf(temp, "SMD_AMS480GZ01-0\n"); + strcat(buf, temp); + return strlen(buf); +} + +static DEVICE_ATTR(lcd_type, 0444, lcd_type_show, NULL); + +static ssize_t auto_brightness_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct lcd_info *lcd = dev_get_drvdata(dev); + char temp[3]; + + sprintf(temp, "%d\n", lcd->auto_brightness); + strcpy(buf, temp); + + return strlen(buf); +} + +static ssize_t auto_brightness_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + struct lcd_info *lcd = dev_get_drvdata(dev); + int value; + int rc; + + rc = strict_strtoul(buf, (unsigned int)0, (unsigned long *)&value); + if (rc < 0) + return rc; + else { + if (lcd->auto_brightness != value) { + dev_info(dev, "%s - %d, %d\n", __func__, lcd->auto_brightness, value); + mutex_lock(&lcd->bl_lock); + lcd->auto_brightness = value; + mutex_unlock(&lcd->bl_lock); + /* if (lcd->ldi_enable) + update_brightness(lcd, 0); */ + } + } + return size; +} + +static DEVICE_ATTR(auto_brightness, 0644, auto_brightness_show, auto_brightness_store); + +#ifdef CONFIG_HAS_EARLYSUSPEND +struct lcd_info *g_lcd; + +void s6e8ax0_early_suspend(void) +{ + struct lcd_info *lcd = g_lcd; + + set_dsim_lcd_enabled(0); + + dev_info(&lcd->ld->dev, "+%s\n", __func__); + s6e8ax0_power(lcd, FB_BLANK_POWERDOWN); + dev_info(&lcd->ld->dev, "-%s\n", __func__); + + return ; +} + +void s6e8ax0_late_resume(void) +{ + struct lcd_info *lcd = g_lcd; + + dev_info(&lcd->ld->dev, "+%s\n", __func__); + s6e8ax0_power(lcd, FB_BLANK_UNBLANK); + dev_info(&lcd->ld->dev, "-%s\n", __func__); + + set_dsim_lcd_enabled(1); + + return ; +} +#endif + +static int s6e8ax0_read_mtp(struct lcd_info *lcd, u8 *mtp_data) +{ + int ret, i; + + for (i = 0; i < 3; i++) + ret = s6e8ax0_read(lcd, LDI_MTP_ADDR+i, LDI_MTP_LENGTH, mtp_data, 0); + + return ret; +} + +static void s6e8ax0_read_id(struct lcd_info *lcd, u8 *buf) +{ + int ret = 0; + + ret = s6e8ax0_read(lcd, LDI_ID_REG, LDI_ID_LEN, buf, 3); + if (!ret) { + lcd->connected = 0; + dev_info(&lcd->ld->dev, "panel is not connected well\n"); + } +} + +static int s6e8ax0_probe(struct device *dev) +{ + int ret = 0; + struct lcd_info *lcd; + u8 mtp_data[LDI_MTP_LENGTH] = {0,}; + + lcd = kzalloc(sizeof(struct lcd_info), GFP_KERNEL); + if (!lcd) { + pr_err("failed to allocate for lcd\n"); + ret = -ENOMEM; + goto err_alloc; + } + + g_lcd = lcd; + + lcd->ld = lcd_device_register("panel", dev, lcd, &s6e8ax0_lcd_ops); + if (IS_ERR(lcd->ld)) { + pr_err("failed to register lcd device\n"); + ret = PTR_ERR(lcd->ld); + goto out_free_lcd; + } + + lcd->bd = backlight_device_register("panel", dev, lcd, &s6e8ax0_backlight_ops, NULL); + if (IS_ERR(lcd->bd)) { + pr_err("failed to register backlight device\n"); + ret = PTR_ERR(lcd->bd); + goto out_free_backlight; + } + + lcd->dev = dev; + lcd->dsim = (struct dsim_global *)dev_get_drvdata(dev->parent); + lcd->bd->props.max_brightness = MAX_BRIGHTNESS; + lcd->bd->props.brightness = DEFAULT_BRIGHTNESS; + lcd->bl = DEFAULT_GAMMA_LEVEL; + lcd->current_bl = lcd->bl; + + lcd->acl_enable = 0; + lcd->cur_acl = 0; + + lcd->power = FB_BLANK_UNBLANK; + lcd->ldi_enable = 1; + lcd->connected = 1; + lcd->auto_brightness = 0; + + ret = device_create_file(&lcd->ld->dev, &dev_attr_power_reduce); + if (ret < 0) + dev_err(&lcd->ld->dev, "failed to add sysfs entries, %d\n", __LINE__); + + ret = device_create_file(&lcd->ld->dev, &dev_attr_lcd_type); + if (ret < 0) + dev_err(&lcd->ld->dev, "failed to add sysfs entries, %d\n", __LINE__); + + ret = device_create_file(&lcd->bd->dev, &dev_attr_auto_brightness); + if (ret < 0) + dev_err(&lcd->ld->dev, "failed to add sysfs entries, %d\n", __LINE__); + + dev_set_drvdata(dev, lcd); + + mutex_init(&lcd->lock); + mutex_init(&lcd->bl_lock); + + s6e8ax0_read_id(lcd, lcd->id); + + dev_info(&lcd->ld->dev, "ID: %x, %x, %x\n", lcd->id[0], lcd->id[1], lcd->id[2]); + + dev_info(&lcd->ld->dev, "lcd panel driver has been probed.\n"); + + return 0; + +out_free_backlight: + lcd_device_unregister(lcd->ld); + kfree(lcd); + return ret; + +out_free_lcd: + kfree(lcd); + return ret; + +err_alloc: + return ret; +} + +static int __devexit s6e8ax0_remove(struct device *dev) +{ + struct lcd_info *lcd = dev_get_drvdata(dev); + + s6e8ax0_power(lcd, FB_BLANK_POWERDOWN); + lcd_device_unregister(lcd->ld); + backlight_device_unregister(lcd->bd); + kfree(lcd); + + return 0; +} + +/* Power down all displays on reboot, poweroff or halt. */ +static void s6e8ax0_shutdown(struct device *dev) +{ + struct lcd_info *lcd = dev_get_drvdata(dev); + + dev_info(&lcd->ld->dev, "%s\n", __func__); + + s6e8ax0_power(lcd, FB_BLANK_POWERDOWN); +} + +static struct mipi_lcd_driver s6e8ax0_mipi_driver = { + .name = "s6e8aa0", + .probe = s6e8ax0_probe, + .remove = __devexit_p(s6e8ax0_remove), + .shutdown = s6e8ax0_shutdown, +}; + +static int s6e8ax0_init(void) +{ + return s5p_dsim_register_lcd_driver(&s6e8ax0_mipi_driver); +} + +static void s6e8ax0_exit(void) +{ + return; +} + +module_init(s6e8ax0_init); +module_exit(s6e8ax0_exit); + +MODULE_DESCRIPTION("MIPI-DSI S6E8AA0:AMS529HA01 (800x1280) Panel Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/samsung/s6e8aa1_param.h b/drivers/video/samsung/s6e8aa1_param.h new file mode 100644 index 0000000..3232b88 --- /dev/null +++ b/drivers/video/samsung/s6e8aa1_param.h @@ -0,0 +1,74 @@ +#ifndef __S6E8AA1_PARAM_H__ +#define __S6E8AA1_PARAM_H__ + +static const unsigned char SEQ_APPLY_MTP_KEY_ENABLE[] = { + 0xF1, + 0x5A, 0x5A +}; + +static const unsigned char SEQ_SLEEP_OUT[] = { + 0x11, + 0x00, 0x00 +}; + +static const unsigned char SEQ_PANEL_CONDITION_SET[] = { + 0xF8, + 0x3D, 0x35, 0x00, 0x00, 0x00, 0x94, 0x00, 0x3C, 0x7D, 0x08, + 0x27, 0x08, 0x7D, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0x7D, + 0x00, 0x00, 0x00, 0x02, 0x08, 0x08, 0x23, 0x66, 0xC0, 0xC1, + 0x01, 0x81, 0xC1, 0x00, 0xC1, 0xF6, 0xF6, 0xC1 +}; + +static const unsigned char SEQ_DISPLAY_CONDITION_SET[] = { + 0xF2, + 0x80, 0x03, 0x0D +}; + +static const unsigned char SEQ_GAMMA_CONDITION_SET[] = { + 0xFA, + 0x01, 0x40, 0x32, 0x49, 0xC5, 0xBB, 0xB6, 0xBC, 0xC5, 0xC0, + 0xC9, 0xC9, 0xC5, 0xA0, 0x9F, 0x98, 0xB3, 0xB3, 0xAF, 0x00, + 0xD0, 0x00, 0xCF, 0x00, 0xE7 +}; + +static const unsigned char SEQ_GAMMA_UPDATE[] = { + 0xF7, 0x03, + 0x00 +}; + +static const unsigned char SEQ_ETC_SOURCE_CONTROL[] = { + 0xF6, + 0x00, 0x02, 0x00 +}; + +static const unsigned char SEQ_ETC_PENTILE_CONTROL[] = { + 0xB6, + 0x0C, 0x02, 0x03, 0x32, 0xFF, 0x44, 0x44, 0xC0, 0x10 +}; + +static const unsigned char SEQ_ELVSS_CONTROL[] = { + 0xB1, + 0x08, 0x95, 0x41, 0xC4 +}; + +static const unsigned char SEQ_ETC_NVM_SETTING[] = { + 0xD9, + 0x14, 0x40, 0x0C, 0xCB, 0xCE, 0x6E, 0xC4, 0x07, 0x40 +}; + +static const unsigned char SEQ_DISPLAY_ON[] = { + 0x29, + 0x00, 0x00 +}; + +static const unsigned char SEQ_DISPLAY_OFF[] = { + 0x28, + 0x00, 0x00 +}; + +static const unsigned char SEQ_STANDBY_ON[] = { + 0x01, + 0x00, 0x00 +}; + +#endif /* __S6E8AA1_PARAM_H__ */ diff --git a/drivers/video/samsung/s6evr02_param.h b/drivers/video/samsung/s6evr02_param.h new file mode 100644 index 0000000..edc7a4e --- /dev/null +++ b/drivers/video/samsung/s6evr02_param.h @@ -0,0 +1,351 @@ +#ifndef __S6EVR02_PARAM_H__ +#define __S6EVR02_PARAM_H__ + +#define GAMMA_PARAM_SIZE 34 +#define ACL_PARAM_SIZE ARRAY_SIZE(acl_cutoff_33) +#define ELVSS_PARAM_SIZE ARRAY_SIZE(elvss_control_set_20) +#define AID_PARAM_SIZE ARRAY_SIZE(SEQ_AOR_CONTROL) + +enum { + GAMMA_20CD, + GAMMA_30CD, + GAMMA_40CD, + GAMMA_50CD, + GAMMA_60CD, + GAMMA_70CD, + GAMMA_80CD, + GAMMA_90CD, + GAMMA_100CD, + GAMMA_102CD, + GAMMA_104CD, + GAMMA_106CD, + GAMMA_108CD, + GAMMA_110CD, + GAMMA_120CD, + GAMMA_130CD, + GAMMA_140CD, + GAMMA_150CD, + GAMMA_160CD, + GAMMA_170CD, + GAMMA_180CD, + GAMMA_182CD, + GAMMA_184CD, + GAMMA_186CD, + GAMMA_188CD, + GAMMA_190CD, + GAMMA_200CD, + GAMMA_210CD, + GAMMA_220CD, + GAMMA_230CD, + GAMMA_240CD, + GAMMA_250CD, + GAMMA_300CD, + GAMMA_MAX +}; + +static const unsigned char SEQ_APPLY_LEVEL_2_KEY[] = { + 0xF0, + 0x5A, 0x5A +}; + +static const unsigned char SEQ_APPLY_LEVEL_2_KEY_DISABLE[] = { + 0xF0, + 0xA5, 0xA5 +}; + +static const unsigned char SEQ_APPLY_LEVEL_3_KEY[] = { + 0xFC, + 0x5A, 0x5A +}; + +static const unsigned char SEQ_APPLY_LEVEL_3_KEY_DISABLE[] = { + 0xFC, + 0xA5, 0xA5 +}; + +static const unsigned char SEQ_SLEEP_OUT[] = { + 0x11, + 0x00, 0x00 +}; + +static const unsigned char SEQ_SLEEP_IN[] = { + 0x10, + 0x00, 0x00 +}; + +static const unsigned char SEQ_GAMMA_CONDITION_SET[] = { + 0xCA, + 0x00, 0xFF, 0x01, 0x1C, 0x01, 0x2C, 0xDA, 0xD7, 0xDA, 0xD5, + 0xD2, 0xD6, 0xC1, 0xBC, 0xC2, 0xCA, 0xB9, 0xCB, 0xDC, 0xE5, + 0xDD, 0xDA, 0xD8, 0xDD, 0xBA, 0xA8, 0xC1, 0x6B, 0x20, 0xD7, + 0x02, 0x03, 0x02 +}; + +static const unsigned char SEQ_GAMMA_CONDITION_SET_UB[] = { + 0xCA, + 0x01, 0x27, 0x01, 0x3D, 0x01, 0x47, 0xD1, 0xD7, 0xD1, 0xCA, + 0xCE, 0xCC, 0xC4, 0xB3, 0xB1, 0xA1, 0xB9, 0xB8, 0xA2, 0xCE, + 0xBA, 0xC8, 0xC9, 0xAD, 0x9B, 0x85, 0x53, 0x6A, 0x7E, 0xE3, + 0x09, 0x09, 0x0B +}; + +static const unsigned char SEQ_GAMMA_UPDATE[] = { + 0xF7, + 0x03, 0x00 +}; + +static const unsigned char SEQ_BRIGHTNESS_CONTROL_ON[] = { + 0x53, + 0x20, 0x00 +}; + +static const unsigned char SEQ_AOR_CONTROL[] = { + 0x51, + 0xFF, 0x00 +}; + +static const unsigned char SEQ_ELVSS_CONDITION_SET_UB[] = { + 0xB6, + 0x08, 0x07 +}; + +static const unsigned char SEQ_AVC2_SET[] = { + 0xF4, + 0x6B, 0x18, 0x95, 0x02, 0x11, 0x8C, 0x77, 0x01, 0x01 +}; + +static const unsigned char SEQ_ELVSS_CONDITION_SET[] = { + 0xB6, + 0x08, 0x07 +}; + +static const unsigned char SEQ_DISPLAY_ON[] = { + 0x29, + 0x00, 0x00 +}; + +static const unsigned char SEQ_DISPLAY_OFF[] = { + 0x28, + 0x00, 0x00 +}; + + +enum { + ELVSS_STATUS_20, + ELVSS_STATUS_30, + ELVSS_STATUS_40, + ELVSS_STATUS_50, + ELVSS_STATUS_60, + ELVSS_STATUS_70, + ELVSS_STATUS_80, + ELVSS_STATUS_90, + ELVSS_STATUS_100, + ELVSS_STATUS_110, + ELVSS_STATUS_120, + ELVSS_STATUS_130, + ELVSS_STATUS_140, + ELVSS_STATUS_150, + ELVSS_STATUS_160, + ELVSS_STATUS_170, + ELVSS_STATUS_180, + ELVSS_STATUS_190, + ELVSS_STATUS_200, + ELVSS_STATUS_210, + ELVSS_STATUS_220, + ELVSS_STATUS_230, + ELVSS_STATUS_240, + ELVSS_STATUS_250, + ELVSS_STATUS_300, + ELVSS_STATUS_MAX +}; + +static const unsigned char elvss_control_set_20[] = { + 0xB6, 0x08, + 0x20 +}; + +static const unsigned char elvss_control_set_30[] = { + 0xB6, 0x08, + 0x20 +}; + +static const unsigned char elvss_control_set_40[] = { + 0xB6, 0x08, + 0x20 +}; + +static const unsigned char elvss_control_set_50[] = { + 0xB6, 0x08, + 0x1F +}; + +static const unsigned char elvss_control_set_60[] = { + 0xB6, 0x08, + 0x1F +}; + +static const unsigned char elvss_control_set_70[] = { + 0xB6, 0x08, + 0x1F +}; + +static const unsigned char elvss_control_set_80[] = { + 0xB6, 0x08, + 0x1E +}; + +static const unsigned char elvss_control_set_90[] = { + 0xB6, 0x08, + 0x1E +}; + +static const unsigned char elvss_control_set_100[] = { + 0xB6, 0x08, + 0x1C +}; + +static const unsigned char elvss_control_set_110[] = { + 0xB6, 0x08, + 0x1B +}; + +static const unsigned char elvss_control_set_120[] = { + 0xB6, 0x08, + 0x19 +}; + +static const unsigned char elvss_control_set_130[] = { + 0xB6, 0x08, + 0x17 +}; + +static const unsigned char elvss_control_set_140[] = { + 0xB6, 0x08, + 0x16 +}; + +static const unsigned char elvss_control_set_150[] = { + 0xB6, 0x08, + 0x14 +}; + +static const unsigned char elvss_control_set_160[] = { + 0xB6, 0x08, + 0x12 +}; + +static const unsigned char elvss_control_set_170[] = { + 0xB6, 0x08, + 0x10 +}; + +static const unsigned char elvss_control_set_180[] = { + 0xB6, 0x08, + 0x0F +}; + +static const unsigned char elvss_control_set_190[] = { + 0xB6, 0x08, + 0x15 +}; + +static const unsigned char elvss_control_set_200[] = { + 0xB6, 0x08, + 0x14 +}; + +static const unsigned char elvss_control_set_210[] = { + 0xB6, 0x08, + 0x13 +}; + +static const unsigned char elvss_control_set_220[] = { + 0xB6, 0x08, + 0x12 +}; + +static const unsigned char elvss_control_set_230[] = { + 0xB6, 0x08, + 0x11 +}; + +static const unsigned char elvss_control_set_240[] = { + 0xB6, 0x08, + 0x10 +}; + +static const unsigned char elvss_control_set_250[] = { + 0xB6, 0x08, + 0x10 +}; + +static const unsigned char elvss_control_set_300[] = { + 0xB6, 0x08, + 0x0B +}; + + +static const unsigned char *ELVSS_CONTROL_TABLE[ELVSS_STATUS_MAX] = { + elvss_control_set_20, + elvss_control_set_30, + elvss_control_set_40, + elvss_control_set_50, + elvss_control_set_60, + elvss_control_set_70, + elvss_control_set_80, + elvss_control_set_90, + elvss_control_set_100, + elvss_control_set_110, + elvss_control_set_120, + elvss_control_set_130, + elvss_control_set_140, + elvss_control_set_150, + elvss_control_set_160, + elvss_control_set_170, + elvss_control_set_180, + elvss_control_set_190, + elvss_control_set_200, + elvss_control_set_210, + elvss_control_set_220, + elvss_control_set_230, + elvss_control_set_240, + elvss_control_set_250, + elvss_control_set_300 +}; + + +enum { + ACL_STATUS_0P = 0, + ACL_STATUS_33P, + ACL_STATUS_40P, + ACL_STATUS_50P, + ACL_STATUS_MAX +}; + +static const unsigned char SEQ_ACL_OFF[] = { + 0x55, 0x00, + 0x00 +}; + +static const unsigned char acl_cutoff_33[] = { + 0x55, 0x01, + 0x00 +}; + +static const unsigned char acl_cutoff_40[] = { + 0x55, 0x02, + 0x00 +}; + +static const unsigned char acl_cutoff_50[] = { + 0x55, 0x03, + 0x00 +}; + +static const unsigned char *ACL_CUTOFF_TABLE[ACL_STATUS_MAX] = { + SEQ_ACL_OFF, + acl_cutoff_33, + acl_cutoff_40, + acl_cutoff_50, +}; +#endif /* __S6EVR02_PARAM_H__ */ diff --git a/drivers/video/samsung/s6evr02_volt_tbl.h b/drivers/video/samsung/s6evr02_volt_tbl.h new file mode 100644 index 0000000..0706964 --- /dev/null +++ b/drivers/video/samsung/s6evr02_volt_tbl.h @@ -0,0 +1,665 @@ +#ifndef __REF_VOLT_TABLE_H__ +#define __REF_VOLT_TABLE_H__ + +u32 volt_table_vt[16] = { + 399769600, 394199040, 388628480, 383057920, + 377487360, 371851264, 366280704, 360710144, + 355139584, 349569024, 335609856, 330956800, + 326303744, 321650688, 316997632, 313327616, +}; + +u32 volt_table_v255[505] = { + 366300517, 365835669, 365370820, 364905972, 364441124, 363976275, 363511427, 363046579, + 362581730, 362116882, 361652033, 361187185, 360722337, 360257488, 359792640, 359327792, + 358862943, 358398095, 357933247, 357468398, 357003550, 356538701, 356073853, 355609005, + 355144156, 354679308, 354214460, 353749611, 353284763, 352819914, 352355066, 351890218, + 351425369, 350960521, 350495673, 350030824, 349565976, 349101127, 348636279, 348171431, + 347706582, 347241734, 346776886, 346312037, 345847189, 345382340, 344917492, 344452644, + 343987795, 343522947, 343058099, 342593250, 342128402, 341663553, 341198705, 340733857, + 340269008, 339804160, 339339312, 338874463, 338409615, 337944767, 337479918, 337015070, + 336550221, 336085373, 335620525, 335155676, 334690828, 334225980, 333761131, 333296283, + 332831434, 332366586, 331901738, 331436889, 330972041, 330507193, 330042344, 329577496, + 329112647, 328647799, 328182951, 327718102, 327253254, 326788406, 326323557, 325858709, + 325393860, 324929012, 324464164, 323999315, 323534467, 323069619, 322604770, 322139922, + 321675073, 321210225, 320745377, 320280528, 319815680, 319350832, 318885983, 318421135, + 317956287, 317491438, 317026590, 316561741, 316096893, 315632045, 315167196, 314702348, + 314237500, 313772651, 313307803, 312842954, 312378106, 311913258, 311448409, 310983561, + 310518713, 310053864, 309589016, 309124167, 308659319, 308194471, 307729622, 307264774, + 306799926, 306335077, 305870229, 305405380, 304940532, 304475684, 304010835, 303545987, + 303081139, 302616290, 302151442, 301686593, 301221745, 300756897, 300292048, 299827200, + 299362352, 298897503, 298432655, 297967807, 297502958, 297038110, 296573261, 296108413, + 295643565, 295178716, 294713868, 294249020, 293784171, 293319323, 292854474, 292389626, + 291924778, 291459929, 290995081, 290530233, 290065384, 289600536, 289135687, 288670839, + 288205991, 287741142, 287276294, 286811446, 286346597, 285881749, 285416900, 284952052, + 284487204, 284022355, 283557507, 283092659, 282627810, 282162962, 281698113, 281233265, + 280768417, 280303568, 279838720, 279373872, 278909023, 278444175, 277979327, 277514478, + 277049630, 276584781, 276119933, 275655085, 275190236, 274725388, 274260540, 273795691, + 273330843, 272865994, 272401146, 271936298, 271471449, 271006601, 270541753, 270076904, + 269612056, 269147207, 268682359, 268217511, 267752662, 267287814, 266822966, 266358117, + 265893269, 265428420, 264963572, 264498724, 264033875, 263569027, 263104179, 262639330, + 262174482, 261709633, 261244785, 260779937, 260315088, 259850240, 259385392, 258920543, + 258455695, 257990847, 257525998, 257061150, 256596301, 256131453, 255666605, 255201756, + 254736908, 254272060, 253807211, 253342363, 252877514, 252412666, 251947818, 251482969, + 251018121, 250553273, 250088424, 249623576, 249158727, 248693879, 248229031, 247764182, + 247299334, 246834486, 246369637, 245904789, 245439940, 244975092, 244510244, 244045395, + 243580547, 243115699, 242650850, 242186002, 241721153, 241256305, 240791457, 240326608, + 239861760, 239396912, 238932063, 238467215, 238002367, 237537518, 237072670, 236607821, + 236142973, 235678125, 235213276, 234748428, 234283580, 233818731, 233353883, 232889034, + 232424186, 231959338, 231494489, 231029641, 230564793, 230099944, 229635096, 229170247, + 228705399, 228240551, 227775702, 227310854, 226846006, 226381157, 225916309, 225451460, + 224986612, 224521764, 224056915, 223592067, 223127219, 222662370, 222197522, 221732673, + 221267825, 220802977, 220338128, 219873280, 219408432, 218943583, 218478735, 218013887, + 217549038, 217084190, 216619341, 216154493, 215689645, 215224796, 214759948, 214295100, + 213830251, 213365403, 212900554, 212435706, 211970858, 211506009, 211041161, 210576313, + 210111464, 209646616, 209181767, 208716919, 208252071, 207787222, 207322374, 206857526, + 206392677, 205927829, 205462980, 204998132, 204533284, 204068435, 203603587, 203138739, + 202673890, 202209042, 201744193, 201279345, 200814497, 200349648, 199884800, 199419952, + 198955103, 198490255, 198025407, 197560558, 197095710, 196630861, 196166013, 195701165, + 195236316, 194771468, 194306620, 193841771, 193376923, 192912074, 192447226, 191982378, + 191517529, 191052681, 190587833, 190122984, 189658136, 189193287, 188728439, 188263591, + 187798742, 187333894, 186869046, 186404197, 185939349, 185474500, 185009652, 184544804, + 184079955, 183615107, 183150259, 182685410, 182220562, 181755713, 181290865, 180826017, + 180361168, 179896320, 179431472, 178966623, 178501775, 178036927, 177572078, 177107230, + 176642381, 176177533, 175712685, 175247836, 174782988, 174318140, 173853291, 173388443, + 172923594, 172458746, 171993898, 171529049, 171064201, 170599353, 170134504, 169669656, + 169204807, 168739959, 168275111, 167810262, 167345414, 166880566, 166415717, 165950869, + 165486020, 165021172, 164556324, 164091475, 163626627, 163161779, 162696930, 162232082, + 161767233, 161302385, 160837537, 160372688, 159907840, 159442992, 158978143, 158513295, + 158048447, 157583598, 157118750, 156653901, 156189053, 155724205, 155259356, 154794508, + 154329660, 153864811, 153399963, 152935114, 152470266, 152005418, 151540569, 151075721, + 150610873, 150146024, 149681176, 149216327, 148751479, 148286631, 147821782, 147356934, + 146892086, 146427237, 145962389, 145497540, 145032692, 144567844, 144102995, 143638147, + 143173299, 142708450, 142243602, 141778753, 141313905, 140849057, 140384208, 139919360, + 139454512, 138989663, 138524815, 138059967, 137595118, 137130270, 136665421, 136200573, + 135735725, 135270876, 134806028, 134341180, 133876331, 133411483, 132946634, 132481786, + 132016938, +}; + +u32 volt_table_cv_64_dv_320[256] = { + 13104, 13308, 13513, 13718, 13923, 14127, 14332, 14537, + 14742, 14946, 15151, 15356, 15561, 15765, 15970, 16175, + 16380, 16585, 16789, 16994, 17199, 17404, 17608, 17813, + 18018, 18223, 18427, 18632, 18837, 19042, 19246, 19451, + 19656, 19861, 20065, 20270, 20475, 20680, 20884, 21089, + 21294, 21499, 21703, 21908, 22113, 22318, 22522, 22727, + 22932, 23137, 23341, 23546, 23751, 23956, 24160, 24365, + 24570, 24775, 24979, 25184, 25389, 25594, 25798, 26003, + 26208, 26413, 26617, 26822, 27027, 27232, 27436, 27641, + 27846, 28051, 28255, 28460, 28665, 28870, 29074, 29279, + 29484, 29689, 29893, 30098, 30303, 30508, 30712, 30917, + 31122, 31327, 31531, 31736, 31941, 32146, 32350, 32555, + 32760, 32965, 33170, 33374, 33579, 33784, 33989, 34193, + 34398, 34603, 34808, 35012, 35217, 35422, 35627, 35831, + 36036, 36241, 36446, 36650, 36855, 37060, 37265, 37469, + 37674, 37879, 38084, 38288, 38493, 38698, 38903, 39107, + 39312, 39517, 39722, 39926, 40131, 40336, 40541, 40745, + 40950, 41155, 41360, 41564, 41769, 41974, 42179, 42383, + 42588, 42793, 42998, 43202, 43407, 43612, 43817, 44021, + 44226, 44431, 44636, 44840, 45045, 45250, 45455, 45659, + 45864, 46069, 46274, 46478, 46683, 46888, 47093, 47297, + 47502, 47707, 47912, 48116, 48321, 48526, 48731, 48935, + 49140, 49345, 49550, 49755, 49959, 50164, 50369, 50574, + 50778, 50983, 51188, 51393, 51597, 51802, 52007, 52212, + 52416, 52621, 52826, 53031, 53235, 53440, 53645, 53850, + 54054, 54259, 54464, 54669, 54873, 55078, 55283, 55488, + 55692, 55897, 56102, 56307, 56511, 56716, 56921, 57126, + 57330, 57535, 57740, 57945, 58149, 58354, 58559, 58764, + 58968, 59173, 59378, 59583, 59787, 59992, 60197, 60402, + 60606, 60811, 61016, 61221, 61425, 61630, 61835, 62040, + 62244, 62449, 62654, 62859, 63063, 63268, 63473, 63678, + 63882, 64087, 64292, 64497, 64701, 64906, 65111, 65316 +}; + +const u32 gamma_300_gra_table[256] = { + 0, 2, 7, 17, 32, 53, 78, 110, + 148, 191, 241, 298, 361, 430, 506, 589, + 679, 776, 880, 991, 1109, 1235, 1368, 1508, + 1657, 1812, 1975, 2147, 2325, 2512, 2706, 2909, + 3119, 3338, 3564, 3799, 4042, 4293, 4553, 4820, + 5096, 5381, 5674, 5975, 6285, 6604, 6931, 7267, + 7611, 7965, 8327, 8697, 9077, 9465, 9863, 10269, + 10684, 11109, 11542, 11984, 12436, 12896, 13366, 13845, + 14333, 14830, 15337, 15852, 16378, 16912, 17456, 18009, + 18572, 19144, 19726, 20317, 20918, 21528, 22148, 22778, + 23417, 24066, 24724, 25392, 26070, 26758, 27456, 28163, + 28880, 29607, 30344, 31090, 31847, 32613, 33390, 34176, + 34973, 35779, 36596, 37422, 38259, 39106, 39963, 40830, + 41707, 42594, 43492, 44399, 45317, 46246, 47184, 48133, + 49092, 50062, 51042, 52032, 53032, 54043, 55065, 56097, + 57139, 58192, 59255, 60329, 61413, 62508, 63613, 64729, + 65856, 66993, 68141, 69299, 70469, 71648, 72839, 74040, + 75252, 76475, 77708, 78952, 80207, 81473, 82750, 84037, + 85336, 86645, 87965, 89296, 90638, 91990, 93354, 94729, + 96114, 97511, 98919, 100337, 101767, 103208, 104659, 106122, + 107596, 109081, 110577, 112085, 113603, 115132, 116673, 118225, + 119788, 121362, 122948, 124544, 126152, 127772, 129402, 131044, + 132697, 134361, 136037, 137724, 139422, 141132, 142853, 144586, + 146330, 148085, 149852, 151630, 153419, 155220, 157033, 158857, + 160692, 162540, 164398, 166268, 168150, 170043, 171948, 173864, + 175792, 177731, 179683, 181645, 183620, 185606, 187603, 189613, + 191634, 193667, 195711, 197767, 199835, 201915, 204006, 206109, + 208224, 210351, 212489, 214640, 216802, 218976, 221161, 223359, + 225569, 227790, 230023, 232268, 234525, 236794, 239075, 241368, + 243672, 245989, 248318, 250658, 253011, 255375, 257752, 260141, + 262541, 264954, 267379, 269815, 272264, 274725, 277198, 279683, + 282180, 284689, 287211, 289744, 292290, 294848, 297418, 300000 +}; + +const u32 gamma_control_set_21[] = { + 0, 9, 38, 89, 163, 260, 381, 526, + 697, 892, 1113, 1359, 1632, 1930, 2255, 2607, + 2985, 3391, 3823, 4283, 4770, 5284, 5826, 6396, + 6994, 7620, 8274, 8957, 9668, 10407, 11175, 11971, + 12797, 13651, 14534, 15446, 16388, 17358, 18358, 19387, + 20446, 21534, 22652, 23799, 24976, 26183, 27420, 28687, + 29983, 31310, 32667, 34054, 35471, 36919, 38397, 39905, + 41444, 43014, 44614, 46244, 47906, 49598, 51321, 53074, + 54859, 56674, 58521, 60399, 62307, 64247, 66218, 68220, + 70253, 72318, 74414, 76542, 78700, 80891, 83113, 85366, + 87651, 89968, 92316, 94696, 97108, 99551, 102027, 104534, + 107073, 109644, 112248, 114883, 117550, 120249, 122980, 125744, + 128540, 131367, 134228, 137120, 140045, 143002, 145991, 149013, + 152068, 155155, 158274, 161426, 164610, 167827, 171077, 174359, + 177674, 181022, 184403, 187816, 191262, 194741, 198253, 201797, + 205375, 208985, 212629, 216305, 220015, 223758, 227533, 231342, + 235184, 239059, 242967, 246909, 250883, 254891, 258932, 263007, + 267115, 271256, 275431, 279639, 283880, 288155, 292464, 296806, + 301181, 305590, 310033, 314509, 319019, 323562, 328139, 332750, + 337394, 342073, 346785, 351530, 356310, 361123, 365971, 370852, + 375767, 380715, 385698, 390715, 395766, 400851, 405969, 411122, + 416309, 421530, 426785, 432074, 437397, 442754, 448146, 453572, + 459032, 464526, 470054, 475617, 481214, 486845, 492511, 498211, + 503945, 509714, 515517, 521355, 527227, 533133, 539074, 545050, + 551060, 557104, 563183, 569297, 575445, 581628, 587845, 594097, + 600384, 606705, 613061, 619452, 625877, 632338, 638833, 645362, + 651927, 658526, 665161, 671830, 678533, 685272, 692046, 698854, + 705698, 712576, 719490, 726438, 733421, 740440, 747493, 754581, + 761705, 768863, 776057, 783286, 790550, 797848, 805183, 812552, + 819956, 827396, 834871, 842381, 849926, 857506, 865122, 872773, + 880460, 888181, 895938, 903731, 911558, 919421, 927320, 935254, + 943223, 951228, 959268, 967343, 975454, 983601, 991783, 1000000 +}; + +const u32 gamma_control_set_213[] = { + 0, 8, 33, 78, 144, 231, 341, 473, + 628, 807, 1010, 1237, 1489, 1766, 2067, 2395, + 2747, 3126, 3531, 3962, 4419, 4903, 5413, 5951, + 6516, 7107, 7727, 8373, 9048, 9750, 10480, 11238, + 12024, 12839, 13682, 14553, 15453, 16381, 17339, 18325, + 19341, 20385, 21459, 22561, 23694, 24855, 26047, 27268, + 28518, 29798, 31109, 32449, 33819, 35219, 36650, 38111, + 39602, 41123, 42675, 44258, 45871, 47515, 49189, 50894, + 52630, 54397, 56196, 58025, 59885, 61776, 63699, 65653, + 67638, 69655, 71703, 73782, 75894, 78036, 80211, 82417, + 84655, 86925, 89227, 91560, 93926, 96324, 98754, 101216, + 103710, 106236, 108795, 111386, 114009, 116665, 119353, 122074, + 124827, 127613, 130432, 133283, 136167, 139083, 142033, 145015, + 148031, 151079, 154160, 157274, 160422, 163602, 166816, 170063, + 173343, 176656, 180002, 183382, 186795, 190242, 193722, 197236, + 200783, 204363, 207978, 211626, 215307, 219023, 222772, 226554, + 230371, 234221, 238106, 242024, 245976, 249962, 253982, 258037, + 262125, 266247, 270404, 274594, 278819, 283079, 287372, 291700, + 296062, 300458, 304889, 309354, 313854, 318388, 322957, 327560, + 332198, 336870, 341577, 346319, 351096, 355907, 360753, 365633, + 370549, 375499, 380484, 385505, 390560, 395650, 400775, 405935, + 411130, 416360, 421625, 426925, 432260, 437631, 443037, 448478, + 453954, 459466, 465012, 470594, 476212, 481865, 487553, 493277, + 499036, 504831, 510661, 516526, 522428, 528364, 534337, 540345, + 546388, 552468, 558583, 564733, 570920, 577142, 583400, 589694, + 596024, 602389, 608791, 615228, 621702, 628211, 634756, 641337, + 647955, 654608, 661297, 668023, 674785, 681582, 688416, 695286, + 702193, 709135, 716114, 723129, 730180, 737268, 744392, 751552, + 758749, 765982, 773251, 780557, 787900, 795279, 802694, 810146, + 817634, 825159, 832721, 840319, 847954, 855625, 863333, 871078, + 878860, 886678, 894533, 902425, 910353, 918319, 926321, 934360, + 942436, 950548, 958698, 966885, 975108, 983369, 991666, 1000000 +}; + +const u32 gamma_control_set_215[] = { + 0, 7, 30, 72, 132, 214, 316, 440, + 586, 755, 947, 1162, 1401, 1664, 1951, 2263, + 2599, 2961, 3348, 3761, 4200, 4664, 5155, 5671, + 6215, 6785, 7382, 8006, 8657, 9335, 10041, 10774, + 11535, 12324, 13141, 13986, 14859, 15761, 16691, 17650, + 18637, 19653, 20698, 21772, 22876, 24008, 25170, 26361, + 27581, 28832, 30111, 31421, 32761, 34130, 35530, 36959, + 38419, 39909, 41430, 42981, 44562, 46175, 47817, 49491, + 51195, 52931, 54697, 56494, 58323, 60182, 62073, 63995, + 65949, 67934, 69950, 71998, 74078, 76190, 78333, 80508, + 82715, 84954, 87225, 89528, 91863, 94231, 96630, 99062, + 101526, 104023, 106552, 109114, 111708, 114335, 116994, 119687, + 122412, 125170, 127961, 130784, 133641, 136531, 139454, 142410, + 145399, 148422, 151477, 154566, 157689, 160845, 164034, 167257, + 170513, 173803, 177127, 180485, 183876, 187301, 190759, 194252, + 197779, 201339, 204934, 208562, 212225, 215922, 219653, 223418, + 227217, 231051, 234919, 238821, 242758, 246729, 250735, 254775, + 258850, 262959, 267103, 271282, 275496, 279744, 284027, 288345, + 292697, 297085, 301507, 305965, 310457, 314985, 319548, 324145, + 328778, 333446, 338150, 342888, 347662, 352471, 357316, 362195, + 367111, 372062, 377048, 382070, 387127, 392220, 397348, 402513, + 407713, 412948, 418220, 423527, 428870, 434248, 439663, 445114, + 450600, 456123, 461681, 467276, 472906, 478573, 484276, 490014, + 495790, 501601, 507448, 513332, 519252, 525209, 531201, 537231, + 543296, 549398, 555537, 561712, 567923, 574171, 580456, 586777, + 593135, 599529, 605961, 612429, 618933, 625475, 632053, 638668, + 645320, 652009, 658735, 665497, 672297, 679133, 686007, 692918, + 699865, 706850, 713872, 720931, 728027, 735161, 742331, 749539, + 756784, 764067, 771387, 778744, 786138, 793570, 801039, 808546, + 816090, 823672, 831291, 838947, 846642, 854374, 862143, 869950, + 877795, 885677, 893597, 901555, 909551, 917584, 925655, 933764, + 941911, 950096, 958318, 966579, 974877, 983214, 991588, 1000000 +}; + +const u32 gamma_control_set_218[] = { + 0 , 6, 26, 63, 117, 190, 282, 395, + 528, 683, 859, 1057, 1278, 1522, 1788, 2078, + 2392, 2730, 3092, 3479, 3891, 4327, 4789, 5277, + 5789, 6328, 6893, 7484, 8102, 8746, 9417, 10114, + 10839, 11591, 12370, 13177, 14012, 14874, 15765, 16683, + 17630, 18605, 19608, 20640, 21701, 22791, 23909, 25057, + 26234, 27440, 28675, 29940, 31235, 32559, 33913, 35297, + 36711, 38155, 39630, 41134, 42669, 44235, 45831, 47458, + 49116, 50804, 52523, 54274, 56055, 57868, 59712, 61587, + 63494, 65432, 67402, 69403, 71436, 73501, 75598, 77727, + 79888, 82081, 84306, 86564, 88853, 91175, 93530, 95917, + 98337, 100789, 103275, 105792, 108343, 110927, 113544, 116193, + 118876, 121592, 124342, 127124, 129940, 132790, 135673, 138589, + 141539, 144523, 147540, 150592, 153677, 156795, 159948, 163135, + 166356, 169611, 172900, 176224, 179582, 182974, 186400, 189861, + 193356, 196886, 200451, 204050, 207684, 211352, 215056, 218794, + 222567, 226375, 230218, 234096, 238010, 241958, 245941, 249960, + 254014, 258104, 262228, 266389, 270584, 274815, 279082, 283384, + 287722, 292096, 296505, 300950, 305431, 309948, 314501, 319090, + 323714, 328375, 333072, 337805, 342574, 347380, 352221, 357099, + 362013, 366964, 371951, 376974, 382034, 387131, 392264, 397434, + 402640, 407883, 413163, 418480, 423833, 429223, 434651, 440115, + 445616, 451154, 456729, 462341, 467990, 473677, 479401, 485161, + 490960, 496795, 502668, 508578, 514526, 520511, 526533, 532593, + 538691, 544826, 550999, 557209, 563457, 569743, 576067, 582428, + 588828, 595265, 601740, 608253, 614804, 621393, 628020, 634685, + 641388, 648129, 654909, 661726, 668582, 675477, 682409, 689380, + 696389, 703437, 710523, 717647, 724810, 732011, 739251, 746530, + 753847, 761203, 768598, 776031, 783503, 791014, 798563, 806152, + 813779, 821445, 829150, 836894, 844677, 852499, 860360, 868261, + 876200, 884178, 892196, 900252, 908348, 916484, 924658, 932872, + 941125, 949417, 957749, 966121, 974531, 982982, 991471, 1000000 +}; + +const u32 gamma_control_set_22[] = { + 0, 6, 24, 57, 108, 176, 262, 368, + 493, 639, 805, 993, 1202, 1434, 1687, 1964, + 2263, 2586, 2933, 3303, 3698, 4117, 4560, 5029, + 5522, 6041, 6585, 7156, 7752, 8374, 9022, 9697, + 10398, 11127, 11882, 12664, 13474, 14311, 15176, 16068, + 16989, 17937, 18913, 19918, 20952, 22013, 23104, 24223, + 25372, 26549, 27756, 28992, 30257, 31552, 32876, 34231, + 35615, 37029, 38473, 39948, 41452, 42988, 44553, 46149, + 47776, 49434, 51123, 52842, 54593, 56375, 58188, 60032, + 61908, 63815, 65754, 67725, 69728, 71762, 73828, 75927, + 78057, 80220, 82415, 84642, 86902, 89194, 91519, 93876, + 96267, 98690, 101146, 103635, 106157, 108712, 111300, 113921, + 116576, 119265, 121986, 124741, 127530, 130353, 133209, 136099, + 139023, 141981, 144973, 147999, 151059, 154153, 157281, 160444, + 163641, 166873, 170139, 173440, 176775, 180145, 183549, 186989, + 190463, 193973, 197517, 201096, 204711, 208360, 212045, 215765, + 219520, 223311, 227137, 230999, 234896, 238828, 242797, 246801, + 250841, 254916, 259028, 263175, 267359, 271578, 275833, 280125, + 284453, 288816, 293217, 297653, 302126, 306635, 311181, 315763, + 320382, 325037, 329730, 334458, 339224, 344026, 348865, 353741, + 358654, 363604, 368591, 373616, 378677, 383775, 388911, 394084, + 399294, 404541, 409826, 415149, 420508, 425906, 431341, 436813, + 442323, 447871, 453457, 459080, 464742, 470441, 476178, 481953, + 487766, 493617, 499506, 505433, 511398, 517402, 523444, 529524, + 535642, 541799, 547994, 554228, 560500, 566810, 573159, 579547, + 585973, 592439, 598942, 605485, 612066, 618686, 625345, 632043, + 638780, 645556, 652371, 659224, 666117, 673050, 680021, 687031, + 694081, 701170, 708298, 715466, 722673, 729919, 737205, 744531, + 751896, 759300, 766744, 774228, 781751, 789314, 796917, 804560, + 812242, 819964, 827726, 835528, 843370, 851252, 859174, 867136, + 875138, 883180, 891263, 899385, 907548, 915751, 923994, 932277, + 940601, 948965, 957370, 965815, 974301, 982827, 991393, 1000000 +}; + +const u32 gamma_control_set_221[] = { + 0, 5, 23, 55, 103, 169, 252, 355, + 476, 618, 780, 962, 1166, 1392, 1639, 1909, + 2202, 2517, 2856, 3219, 3605, 4015, 4450, 4909, + 5393, 5902, 6437, 6997, 7582, 8194, 8831, 9495, + 10185, 10901, 11645, 12415, 13213, 14037, 14890, 15769, + 16677, 17612, 18575, 19567, 20587, 21635, 22712, 23817, + 24952, 26115, 27307, 28529, 29780, 31060, 32370, 33710, + 35079, 36478, 37908, 39367, 40857, 42377, 43928, 45509, + 47120, 48763, 50436, 52141, 53876, 55642, 57440, 59269, + 61130, 63022, 64946, 66901, 68889, 70908, 72959, 75042, + 77157, 79305, 81485, 83697, 85942, 88219, 90530, 92872, + 95248, 97656, 100098, 102572, 105080, 107621, 110195, 112802, + 115443, 118117, 120825, 123567, 126342, 129151, 131994, 134871, + 137782, 140727, 143706, 146719, 149766, 152848, 155964, 159115, + 162300, 165520, 168775, 172064, 175388, 178747, 182141, 185569, + 189033, 192532, 196066, 199635, 203240, 206880, 210555, 214266, + 218012, 221794, 225612, 229465, 233354, 237279, 241240, 245236, + 249269, 253338, 257442, 261583, 265760, 269974, 274223, 278509, + 282832, 287191, 291586, 296018, 300487, 304992, 309534, 314113, + 318729, 323381, 328071, 332797, 337561, 342362, 347199, 352074, + 356987, 361936, 366923, 371947, 377009, 382108, 387245, 392419, + 397631, 402881, 408168, 413493, 418856, 424257, 429695, 435172, + 440686, 446239, 451830, 457459, 463126, 468831, 474575, 480356, + 486177, 492035, 497932, 503868, 509842, 515854, 521906, 527996, + 534124, 540292, 546498, 552743, 559027, 565349, 571711, 578112, + 584552, 591030, 597548, 604106, 610702, 617337, 624012, 630726, + 637480, 644273, 651105, 657977, 664888, 671839, 678830, 685860, + 692930, 700039, 707189, 714378, 721607, 728876, 736184, 743533, + 750922, 758350, 765819, 773328, 780877, 788466, 796095, 803765, + 811475, 819225, 827015, 834846, 842717, 850629, 858582, 866574, + 874608, 882682, 890796, 898952, 907148, 915384, 923662, 931980, + 940339, 948740, 957181, 965662, 974185, 982749, 991354, 1000000 +}; + +const u32 gamma_control_set_222[] = { + 0, 5, 22, 53, 99, 162, 243, 342, + 460, 597, 755, 932, 1131, 1351, 1592, 1856, + 2142, 2450, 2781, 3136, 3514, 3916, 4342, 4792, + 5267, 5767, 6292, 6841, 7417, 8017, 8644, 9297, + 9976, 10681, 11413, 12171, 12957, 13769, 14609, 15476, + 16371, 17293, 18243, 19222, 20228, 21263, 22326, 23418, + 24538, 25688, 26866, 28073, 29310, 30576, 31871, 33197, + 34551, 35936, 37351, 38795, 40270, 41775, 43311, 44877, + 46473, 48101, 49759, 51448, 53169, 54920, 56703, 58516, + 60362, 62239, 64147, 66088, 68060, 70064, 72100, 74168, + 76268, 78401, 80566, 82763, 84993, 87256, 89551, 91879, + 94240, 96634, 99061, 101521, 104014, 106541, 109100, 111694, + 114321, 116981, 119675, 122403, 125165, 127961, 130790, 133654, + 136551, 139483, 142450, 145450, 148485, 151555, 154659, 157797, + 160970, 164178, 167421, 170699, 174012, 177360, 180742, 184160, + 187614, 191102, 194626, 198185, 201780, 205410, 209076, 212778, + 216515, 220288, 224097, 227942, 231823, 235740, 239692, 243682, + 247707, 251768, 255866, 260001, 264171, 268379, 272623, 276903, + 281220, 285574, 289965, 294392, 298856, 303358, 307896, 312471, + 317084, 321734, 326421, 331145, 335906, 340705, 345541, 350415, + 355327, 360276, 365262, 370286, 375349, 380448, 385586, 390762, + 395975, 401227, 406516, 411844, 417210, 422614, 428056, 433537, + 439055, 444613, 450208, 455843, 461515, 467227, 472977, 478765, + 484593, 490459, 496364, 502307, 508290, 514312, 520372, 526472, + 532611, 538789, 545006, 551262, 557558, 563892, 570267, 576680, + 583133, 589626, 596158, 602729, 609341, 615992, 622682, 629412, + 636183, 642992, 649842, 656732, 663662, 670631, 677641, 684691, + 691781, 698911, 706081, 713291, 720542, 727833, 735165, 742537, + 749949, 757402, 764895, 772429, 780003, 787618, 795274, 802971, + 810708, 818486, 826305, 834165, 842065, 850007, 857989, 866013, + 874078, 882183, 890330, 898518, 906748, 915018, 923330, 931683, + 940078, 948514, 956991, 965510, 974070, 982672, 991315, 1000000 +}; + +const u32 gamma_control_set_223[] = { + 0, 5, 21, 50, 95, 156, 234, 330, + 444, 578, 731, 904, 1097, 1311, 1547, 1804, + 2083, 2385, 2709, 3056, 3426, 3820, 4237, 4679, + 5144, 5635, 6150, 6689, 7255, 7845, 8461, 9103, + 9771, 10465, 11185, 11932, 12705, 13506, 14333, 15188, + 16070, 16980, 17917, 18883, 19876, 20897, 21947, 23025, + 24132, 25267, 26432, 27625, 28848, 30099, 31381, 32691, + 34031, 35402, 36802, 38231, 39692, 41182, 42703, 44254, + 45835, 47448, 49091, 50765, 52470, 54207, 55974, 57773, + 59603, 61465, 63359, 65284, 67241, 69230, 71251, 73304, + 75389, 77507, 79657, 81839, 84054, 86302, 88583, 90896, + 93243, 95622, 98034, 100480, 102959, 105471, 108017, 110596, + 113209, 115856, 118536, 121251, 123999, 126781, 129597, 132448, + 135332, 138251, 141205, 144193, 147215, 150272, 153364, 156490, + 159651, 162848, 166079, 169345, 172647, 175983, 179355, 182762, + 186205, 189683, 193196, 196746, 200330, 203951, 207607, 211300, + 215028, 218792, 222592, 226429, 230301, 234210, 238155, 242137, + 246155, 250209, 254300, 258428, 262592, 266793, 271031, 275306, + 279618, 283966, 288352, 292775, 297235, 301732, 306267, 310838, + 315448, 320094, 324779, 329500, 334260, 339057, 343891, 348764, + 353674, 358623, 363609, 368633, 373695, 378796, 383934, 389111, + 394326, 399580, 404871, 410202, 415570, 420977, 426423, 431908, + 437431, 442992, 448593, 454232, 459911, 465628, 471384, 477180, + 483014, 488887, 494800, 500752, 506743, 512774, 518843, 524953, + 531102, 537290, 543518, 549785, 556092, 562439, 568826, 575252, + 581718, 588224, 594770, 601356, 607982, 614649, 621355, 628101, + 634888, 641715, 648582, 655489, 662437, 669425, 676454, 683524, + 690633, 697784, 704975, 712207, 719479, 726793, 734147, 741542, + 748977, 756454, 763972, 771531, 779131, 786772, 794454, 802177, + 809942, 817748, 825595, 833483, 841413, 849385, 857398, 865452, + 873548, 881685, 889865, 898085, 906348, 914652, 922998, 931386, + 939816, 948288, 956801, 965357, 973955, 982595, 991276, 1000000 +}; + +const u32 gamma_control_set_224[] = { + 0, 5, 20, 48, 91, 150, 226, 318, + 429, 559, 707, 876, 1064, 1273, 1503, 1754, + 2026, 2321, 2638, 2977, 3340, 3725, 4135, 4567, + 5024, 5505, 6011, 6541, 7096, 7676, 8282, 8913, + 9570, 10253, 10962, 11697, 12459, 13248, 14063, 14906, + 15775, 16672, 17597, 18549, 19530, 20538, 21574, 22639, + 23732, 24854, 26005, 27184, 28393, 29630, 30897, 32194, + 33520, 34875, 36261, 37676, 39121, 40597, 42103, 43639, + 45206, 46804, 48432, 50091, 51781, 53503, 55255, 57039, + 58854, 60701, 62580, 64490, 66432, 68406, 70412, 72450, + 74520, 76623, 78758, 80926, 83126, 85359, 87625, 89924, + 92256, 94621, 97019, 99450, 101915, 104413, 106944, 109510, + 112109, 114742, 117408, 120109, 122843, 125612, 128415, 131252, + 134124, 137030, 139971, 142946, 145956, 149000, 152080, 155194, + 158343, 161528, 164747, 168002, 171292, 174617, 177978, 181375, + 184806, 188274, 191777, 195316, 198891, 202502, 206149, 209832, + 213551, 217306, 221098, 224925, 228790, 232690, 236628, 240602, + 244612, 248659, 252744, 256864, 261022, 265217, 269449, 273718, + 278024, 282368, 286748, 291167, 295622, 300115, 304646, 309214, + 313820, 318463, 323145, 327864, 332621, 337416, 342249, 347120, + 352030, 356977, 361963, 366987, 372050, 377150, 382290, 387468, + 392684, 397939, 403233, 408566, 413937, 419347, 424796, 430285, + 435812, 441378, 446983, 452628, 458312, 464035, 469797, 475599, + 481440, 487321, 493241, 499201, 505201, 511240, 517319, 523438, + 529597, 535795, 542034, 548312, 554631, 560989, 567388, 573827, + 580307, 586826, 593386, 599987, 606627, 613309, 620030, 626793, + 633596, 640439, 647324, 654249, 661215, 668222, 675270, 682358, + 689488, 696659, 703871, 711124, 718418, 725753, 733130, 740548, + 748007, 755508, 763050, 770634, 778259, 785926, 793635, 801385, + 809177, 817010, 824886, 832803, 840762, 848763, 856806, 864891, + 873018, 881188, 889399, 897653, 905948, 914286, 922667, 931089, + 939555, 948062, 956612, 965205, 973840, 982517, 991238, 1000000 +}; + +const u32 gamma_control_set_225[] = { + 0, 4, 19, 46, 88, 144, 217, 307, + 415, 540, 685, 849, 1032, 1235, 1460, 1705, + 1971, 2259, 2569, 2901, 3256, 3634, 4034, 4459, + 4907, 5379, 5875, 6396, 6941, 7511, 8107, 8727, + 9373, 10045, 10743, 11467, 12218, 12994, 13798, 14628, + 15486, 16370, 17283, 18222, 19190, 20185, 21208, 22259, + 23339, 24448, 25584, 26750, 27945, 29168, 30421, 31704, + 33015, 34357, 35728, 37129, 38559, 40020, 41512, 43033, + 44586, 46168, 47782, 49426, 51102, 52808, 54546, 56314, + 58115, 59947, 61810, 63705, 65632, 67591, 69583, 71606, + 73661, 75749, 77870, 80023, 82208, 84427, 86678, 88962, + 91279, 93630, 96014, 98431, 100881, 103365, 105883, 108434, + 111019, 113638, 116291, 118978, 121699, 124454, 127244, 130068, + 132926, 135819, 138747, 141710, 144707, 147739, 150806, 153909, + 157046, 160218, 163426, 166669, 169948, 173262, 176612, 179997, + 183419, 186876, 190369, 193898, 197462, 201063, 204701, 208374, + 212084, 215830, 219613, 223432, 227288, 231181, 235110, 239076, + 243079, 247119, 251196, 255311, 259462, 263650, 267876, 272139, + 276440, 280778, 285154, 289567, 294018, 298507, 303034, 307598, + 312200, 316841, 321519, 326236, 330991, 335784, 340615, 345485, + 350393, 355339, 360325, 365348, 370411, 375512, 380652, 385831, + 391049, 396306, 401601, 406936, 412310, 417723, 423176, 428668, + 434199, 439769, 445379, 451029, 456718, 462447, 468215, 474024, + 479872, 485760, 491687, 497655, 503663, 509711, 515799, 521927, + 528096, 534305, 540554, 546843, 553173, 559544, 565955, 572406, + 578899, 585432, 592005, 598620, 605275, 611971, 618709, 625487, + 632306, 639167, 646068, 653011, 659995, 667020, 674087, 681195, + 688345, 695536, 702768, 710042, 717358, 724715, 732115, 739556, + 747038, 754563, 762130, 769738, 777389, 785081, 792816, 800593, + 808412, 816273, 824177, 832123, 840111, 848142, 856215, 864331, + 872489, 880690, 888934, 897220, 905549, 913921, 922335, 930793, + 939293, 947836, 956423, 965052, 973724, 982440, 991199, 1000000 +}; + +const u32 *GAMMA_CONTROL_TABLE[G_MAX] = { + gamma_control_set_21, + gamma_control_set_213, + gamma_control_set_215, + gamma_control_set_218, + gamma_control_set_22, + gamma_control_set_221, + gamma_control_set_222, + gamma_control_set_223, + gamma_control_set_224, + gamma_control_set_225 +}; + +const struct str_flookup_table flookup_table[302] = { + { 0, 0}, { 1, 20}, + { 20, 7}, { 27, 5}, + { 32, 4}, { 36, 4}, + { 40, 4}, { 44, 3}, + { 47, 3}, { 50, 2}, + { 52, 3}, { 55, 2}, + { 57, 3}, { 60, 2}, + { 62, 2}, { 64, 2}, + { 66, 2}, { 68, 2}, + { 70, 1}, { 71, 2}, + { 73, 2}, { 75, 2}, + { 77, 1}, { 78, 2}, + { 80, 1}, { 81, 2}, + { 83, 1}, { 84, 2}, + { 86, 1}, { 87, 2}, + { 89, 1}, { 90, 1}, + { 91, 2}, { 93, 1}, + { 94, 1}, { 95, 2}, + { 97, 1}, { 98, 1}, + { 99, 1}, {100, 1}, + {101, 2}, {103, 1}, + {104, 1}, {105, 1}, + {106, 1}, {107, 1}, + {108, 1}, {109, 1}, + {110, 1}, {111, 1}, + {112, 1}, {113, 1}, + {114, 1}, {115, 1}, + {116, 1}, {117, 1}, + {118, 1}, {119, 1}, + {120, 1}, {121, 1}, + {122, 1}, {123, 1}, + {124, 1}, {125, 1}, + {126, 1}, {127, 1}, + {128, 1}, {129, 1}, + { 0, 0}, {130, 1}, + {131, 1}, {132, 1}, + {133, 1}, {134, 1}, + { 0, 0}, {135, 1}, + {136, 1}, {137, 1}, + {138, 1}, {139, 1}, + { 0, 0}, {140, 1}, + {141, 1}, {142, 1}, + { 0, 0}, {143, 1}, + {144, 1}, {145, 1}, + {146, 1}, { 0, 0}, + {147, 1}, {148, 1}, + {149, 1}, { 0, 0}, + {150, 1}, {151, 1}, + { 0, 0}, {152, 1}, + {153, 1}, {154, 1}, + { 0, 0}, {155, 1}, + {156, 1}, { 0, 0}, + {157, 1}, {158, 1}, + { 0, 0}, {159, 1}, + {160, 1}, { 0, 0}, + {161, 1}, {162, 1}, + { 0, 0}, {163, 1}, + {164, 1}, { 0, 0}, + {165, 1}, {166, 1}, + { 0, 0}, {167, 1}, + {168, 1}, { 0, 0}, + {169, 1}, {170, 1}, + { 0, 0}, {171, 1}, + { 0, 0}, {172, 1}, + {173, 1}, { 0, 0}, + {174, 1}, { 0, 0}, + {175, 1}, {176, 1}, + { 0, 0}, {177, 1}, + { 0, 0}, {178, 1}, + {179, 1}, { 0, 0}, + {180, 1}, { 0, 0}, + {181, 1}, {182, 1}, + { 0, 0}, {183, 1}, + { 0, 0}, {184, 1}, + { 0, 0}, {185, 1}, + {186, 1}, { 0, 0}, + {187, 1}, { 0, 0}, + {188, 1}, { 0, 0}, + {189, 1}, { 0, 0}, + {190, 1}, {191, 1}, + { 0, 0}, {192, 1}, + { 0, 0}, {193, 1}, + { 0, 0}, {194, 1}, + { 0, 0}, {195, 1}, + { 0, 0}, {196, 1}, + { 0, 0}, {197, 1}, + {198, 1}, { 0, 0}, + {199, 1}, { 0, 0}, + {200, 1}, { 0, 0}, + {201, 1}, { 0, 0}, + {202, 1}, { 0, 0}, + {203, 1}, { 0, 0}, + {204, 1}, { 0, 0}, + {205, 1}, { 0, 0}, + {206, 1}, { 0, 0}, + {207, 1}, { 0, 0}, + {208, 1}, { 0, 0}, + {209, 1}, { 0, 0}, + {210, 1}, { 0, 0}, + {211, 1}, { 0, 0}, + {212, 1}, { 0, 0}, + {213, 1}, { 0, 0}, + { 0, 0}, {214, 1}, + { 0, 0}, {215, 1}, + { 0, 0}, {216, 1}, + { 0, 0}, {217, 1}, + { 0, 0}, {218, 1}, + { 0, 0}, {219, 1}, + { 0, 0}, {220, 1}, + { 0, 0}, {221, 1}, + { 0, 0}, { 0, 0}, + {222, 1}, { 0, 0}, + {223, 1}, { 0, 0}, + {224, 1}, { 0, 0}, + {225, 1}, { 0, 0}, + { 0, 0}, {226, 1}, + { 0, 0}, {227, 1}, + { 0, 0}, {228, 1}, + { 0, 0}, {229, 1}, + { 0, 0}, { 0, 0}, + {230, 1}, { 0, 0}, + {231, 1}, { 0, 0}, + {232, 1}, { 0, 0}, + {233, 1}, { 0, 0}, + { 0, 0}, {234, 1}, + { 0, 0}, {235, 1}, + { 0, 0}, { 0, 0}, + {236, 1}, { 0, 0}, + {237, 1}, { 0, 0}, + {238, 1}, { 0, 0}, + { 0, 0}, {239, 1}, + { 0, 0}, {240, 1}, + { 0, 0}, {241, 1}, + { 0, 0}, { 0, 0}, + {242, 1}, { 0, 0}, + {243, 1}, { 0, 0}, + { 0, 0}, {244, 1}, + { 0, 0}, {245, 1}, + { 0, 0}, { 0, 0}, + {246, 1}, { 0, 0}, + {247, 1}, { 0, 0}, + { 0, 0}, {248, 1}, + { 0, 0}, {249, 1}, + { 0, 0}, { 0, 0}, + {250, 1}, { 0, 0}, + {251, 1}, { 0, 0}, + { 0, 0}, {252, 1}, + { 0, 0}, {253, 1}, + { 0, 0}, { 0, 0}, + {254, 1}, { 0, 0}, + { 0, 0}, {255, 1}, +}; + +#endif diff --git a/drivers/video/samsung/smart_dimming_ea8061.c b/drivers/video/samsung/smart_dimming_ea8061.c new file mode 100644 index 0000000..7a9175c --- /dev/null +++ b/drivers/video/samsung/smart_dimming_ea8061.c @@ -0,0 +1,918 @@ +/* linux/drivers/video/samsung/smartdimming.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + + * Samsung Smart Dimming for OCTA + * + * Minwoo Kim, <minwoo7945.kim@samsung.com> + * +*/ + +#include "smart_dimming_ea8061.h" +#include "ea8061_volt_tbl.h" + +#define VALUE_DIM_1000 1000 +#define VT_255_div_1000 605000 +#define VREG_OUT_1000 6100 +#define VREG_OUT_1000_1024 6246400 +#define VT_255_calc_param (VT_255_div_1000 / VREG_OUT_1000) + +static const u8 range_table_count[IV_TABLE_MAX] = { + 3, 8, 12, 12, 16, 36, 64, 52, 52, 1 +}; + +static const u32 table_radio[IV_TABLE_MAX] = { + 16384, 4138, 2763, 2763, 2080, 918, 516, 636, 636, 0 +}; + +static const u32 dv_value[IV_MAX] = { + 0, 3, 11, 23, 35, 51, 87, 151, 203, 255 +}; + +static const char color_name[3] = {'R', 'G', 'B'}; + +static const u8 *offset_table[IV_TABLE_MAX] = { + NULL, /*V3*/ + NULL, /*V11*/ + NULL, /*V23*/ + NULL, /*V23*/ + NULL, /*V35*/ + NULL, /*V51*/ + NULL, /*V87*/ + NULL, /*V151*/ + NULL, /*V203*/ + NULL /*V255*/ +}; + +static const unsigned char gamma_300cd_00[] = { + 0x00, 0xE8, 0x00, 0xF7, 0x01, 0x03, + 0xDB, 0xDB, 0xDC, 0xD9, 0xD8, 0xDA, 0xCB, 0xC8, 0xCB, + 0xD4, 0xD3, 0xD7, 0xE6, 0xE6, 0xEA, 0xE2, 0xE4, 0xE5, + 0xCE, 0xC3, 0xCF, 0xB9, 0x9D, 0xDE, 0x01, 0x01, 0x00 +}; + +static const unsigned char gamma_300cd_02[] = { + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x01, 0x03, 0x02 +}; + +static const unsigned char *gamma_300cd_list[GAMMA_300CD_MAX] = { + gamma_300cd_00, + gamma_300cd_00, + gamma_300cd_02, + gamma_300cd_02, + gamma_300cd_02, + gamma_300cd_02, + gamma_300cd_02, + gamma_300cd_02, + gamma_300cd_02, +}; + +static const unsigned char gamma_id_list[GAMMA_300CD_MAX] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x25, 0x26, +}; + +static s16 s9_to_s16(s16 v) +{ + return (s16)(v << 7) >> 7; +} + +static u32 calc_vt_volt(s16 gamma, int rgb_index, u32 adjust_volt[CI_MAX][AD_IVMAX]) +{ + u32 ret = 0; + + ret = volt_table_vt[gamma] >> 16; + + return ret; +} + +static u32 calc_v3_volt(s16 gamma, int rgb_index, u32 adjust_volt[CI_MAX][AD_IVMAX]) +{ + /* for CV : 64, DV :320 */ + int ret = 0; + u32 v0 = VREG_OUT_1000, v11; + u32 ratio = 0; + + /*vt = adjust_volt[rgb_index][AD_IVT];*/ + v11 = adjust_volt[rgb_index][AD_IV11]; + ratio = volt_table_cv_64_dv_320[gamma]; + + ret = (v0 << 16) - ((v0-v11)*ratio); + ret = ret >> 16; + + return ret; +} + +static u32 calc_v11_volt(s16 gamma, int rgb_index, u32 adjust_volt[CI_MAX][AD_IVMAX]) +{ + /* for CV : 64, DV :320*/ + int ret = 0; + u32 vt, v23; + u32 ratio = 0; + + vt = adjust_volt[rgb_index][AD_IVT]; + v23 = adjust_volt[rgb_index][AD_IV23]; + ratio = volt_table_cv_64_dv_320[gamma]; + + ret = (vt << 16) - ((vt-v23)*ratio); + ret = ret >> 16; + + return ret; +} + +static u32 calc_v23_volt(s16 gamma, int rgb_index, u32 adjust_volt[CI_MAX][AD_IVMAX]) +{ + /* for CV : 64, DV :319 */ + int ret = 0; + u32 vt, v35; + u32 ratio = 0; + + vt = adjust_volt[rgb_index][AD_IVT]; + v35 = adjust_volt[rgb_index][AD_IV35]; + ratio = volt_table_cv_64_dv_320[gamma]; + + ret = (vt << 16) - ((vt-v35)*ratio); + ret = ret >> 16; + + return ret; +} + +static u32 calc_v35_volt(s16 gamma, int rgb_index, u32 adjust_volt[CI_MAX][AD_IVMAX]) +{ + /* for CV : 65, DV :319 */ + int ret = 0; + u32 vt, v51; + u32 ratio = 0; + + vt = adjust_volt[rgb_index][AD_IVT]; + v51 = adjust_volt[rgb_index][AD_IV51]; + ratio = volt_table_cv_64_dv_320[gamma]; + + ret = (vt << 16) - ((vt-v51)*ratio); + ret = ret >> 16; + + return ret; +} + +static u32 calc_v51_volt(s16 gamma, int rgb_index, u32 adjust_volt[CI_MAX][AD_IVMAX]) +{ + /* for CV : 65, DV :319 */ + int ret = 0; + u32 vt, v87; + u32 ratio = 0; + + vt = adjust_volt[rgb_index][AD_IVT]; + v87 = adjust_volt[rgb_index][AD_IV87]; + ratio = volt_table_cv_64_dv_320[gamma]; + + ret = (vt << 16) - ((vt-v87)*ratio); + ret = ret >> 16; + + return ret; + +} + +static u32 calc_v87_volt(s16 gamma, int rgb_index, u32 adjust_volt[CI_MAX][AD_IVMAX]) +{ + /* for CV : 64, DV :319 */ + int ret = 0; + u32 vt, v151; + u32 ratio = 0; + + vt = adjust_volt[rgb_index][AD_IVT]; + v151 = adjust_volt[rgb_index][AD_IV151]; + ratio = volt_table_cv_64_dv_320[gamma]; + + ret = (vt << 16) - ((vt-v151)*ratio); + ret = ret >> 16; + + return ret; +} + +static u32 calc_v151_volt(s16 gamma, int rgb_index, u32 adjust_volt[CI_MAX][AD_IVMAX]) +{ + /* for CV : 64, DV :319 */ + int ret = 0; + u32 vt, v203; + u32 ratio = 0; + + vt = adjust_volt[rgb_index][AD_IVT]; + v203 = adjust_volt[rgb_index][AD_IV203]; + ratio = volt_table_cv_64_dv_320[gamma]; + + ret = (vt << 16) - ((vt-v203)*ratio); + ret = ret >> 16; + + return ret; +} + +static u32 calc_v203_volt(s16 gamma, int rgb_index, u32 adjust_volt[CI_MAX][AD_IVMAX]) +{ + /* for CV : 64, DV :319 */ + int ret = 0; + u32 vt, v255; + u32 ratio = 0; + + vt = adjust_volt[rgb_index][AD_IVT]; + v255 = adjust_volt[rgb_index][AD_IV255]; + ratio = volt_table_cv_64_dv_320[gamma]; + + ret = (vt << 16) - ((vt-v255)*ratio); + ret = ret >> 16; + + return ret; +} + +static u32 calc_v255_volt(s16 gamma, int rgb_index, u32 adjust_volt[CI_MAX][AD_IVMAX]) +{ + u32 ret = 0; + + ret = volt_table_v255[gamma] >> 16; + + return ret; +} + +u8 calc_voltage_table_ea8061(struct str_smart_dim *smart, const u8 *mtp) +{ + int c, i, j; +#if defined(MTP_REVERSE) + int offset1 = 0; +#endif + int offset = 0; + s16 t1, t2; + s16 adjust_mtp[CI_MAX][IV_MAX]; + u8 range_index; + u8 table_index = 0; + u32 v1, v2; + u32 ratio; + u32(*calc_volt[IV_MAX])(s16 gamma, int rgb_index, u32 adjust_volt[CI_MAX][AD_IVMAX]) = { + calc_vt_volt, + calc_v3_volt, + calc_v11_volt, + calc_v23_volt, + calc_v35_volt, + calc_v51_volt, + calc_v87_volt, + calc_v151_volt, + calc_v203_volt, + calc_v255_volt, + }; + u8 calc_seq[9] = { IV_VT, IV_203, IV_151, IV_87, IV_51, IV_35, IV_23, IV_11, IV_3}; + u8 ad_seq[9] = {AD_IVT, AD_IV203, AD_IV151, AD_IV87, AD_IV51, AD_IV35, AD_IV23, AD_IV11, AD_IV3}; + + memset(adjust_mtp, 0, sizeof(adjust_mtp)); + + for (c = CI_RED; c < CI_MAX; c++) { + offset = c*2; + t1 = s9_to_s16(mtp[offset]<<8|mtp[offset+1]); + t2 = (smart->default_gamma[offset]<<8|smart->default_gamma[offset+1]) + t1; + smart->mtp[c][IV_255] = t1; + adjust_mtp[c][IV_255] = t2; + smart->adjust_volt[c][AD_IV255] = calc_volt[IV_255](t2, c, smart->adjust_volt); + /* for V0 All RGB Voltage Value is Reference Voltage */ + smart->adjust_volt[c][AD_IVT] = VREG_OUT_1000; + } + + for (i = IV_VT; i < IV_255; i++) { + for (c = CI_RED; c < CI_MAX; c++) { + if (i < IV_3) { + t1 = 0; + t2 = smart->default_gamma[CI_MAX*(10-calc_seq[i])+c] + t1; + smart->mtp[c][calc_seq[i]] = t1; + adjust_mtp[c][calc_seq[i]] = t2; + smart->adjust_volt[c][ad_seq[i]] = calc_volt[calc_seq[i]](t2, c, smart->adjust_volt); + } else { + t1 = (s8)mtp[CI_MAX*(10-calc_seq[i])+c]; + t2 = smart->default_gamma[CI_MAX*(10-calc_seq[i])+c] + t1; + smart->mtp[c][calc_seq[i]] = t1; + adjust_mtp[c][calc_seq[i]] = t2; + smart->adjust_volt[c][ad_seq[i]] = calc_volt[calc_seq[i]](t2, c, smart->adjust_volt); + } + } + } + + for (i = AD_IVT; i < AD_IVMAX; i++) { + for (c = CI_RED; c < CI_MAX; c++) { + if (i == 0) + smart->ve[table_index].v[c] = VREG_OUT_1000; + else + smart->ve[table_index].v[c] = smart->adjust_volt[c][i]; + } + range_index = 0; + + for (j = table_index+1; j < table_index+range_table_count[i]; j++) { + for (c = CI_RED; c < CI_MAX; c++) { + if (smart->t_info[i].offset_table != NULL) + ratio = smart->t_info[i].offset_table[range_index] * smart->t_info[i].rv; + else + ratio = (range_table_count[i]-(range_index+1)) * smart->t_info[i].rv; + + v1 = smart->adjust_volt[c][i+1] << 15; + v2 = (smart->adjust_volt[c][i] - smart->adjust_volt[c][i+1])*ratio; + smart->ve[j].v[c] = ((v1+v2) >> 15); + } + range_index++; + } + table_index = j; + } + + for (i = 1; i < 3; i++) { + for (c = CI_RED; c < CI_MAX; c++) + smart->ve[i].v[c] = smart->ve[3].v[c]+((smart->ve[0].v[c]-smart->ve[3].v[c])*(3-i)/3); + } + +#if 0 + printk(KERN_INFO "++++++++++++++++++++++++++++++ MTP VALUE ++++++++++++++++++++++++++++++\n"); + for (i = IV_VT; i < IV_MAX; i++) { + printk("V Level : %d - ", i); + for (c = CI_RED; c < CI_MAX; c++) + printk(" %c : 0x%08x(%04d)", color_name[c], smart->mtp[c][i], smart->mtp[c][i]); + printk("\n"); + } + + printk(KERN_INFO "\n\n++++++++++++++++++++++++++++++ ADJUST VALUE ++++++++++++++++++++++++++++++\n"); + for (i = IV_VT; i < IV_MAX; i++) { + printk("V Level : %d - ", i); + for (c = CI_RED; c < CI_MAX; c++) + printk(" %c : 0x%08x(%04d)", color_name[c], + adjust_mtp[c][i], adjust_mtp[c][i]); + printk("\n"); + } + + printk(KERN_INFO "\n\n++++++++++++++++++++++++++++++ ADJUST VOLTAGE ++++++++++++++++++++++++++++++\n"); + for (i = AD_IVT; i < AD_IVMAX; i++) { + printk("V Level : %d - ", i); + for (c = CI_RED; c < CI_MAX; c++) + printk(" %c : %04dV", color_name[c], smart->adjust_volt[c][i]); + printk("\n"); + } + + printk(KERN_INFO "\n\n++++++++++++++++++++++++++++++++++++++ VOLTAGE TABLE ++++++++++++++++++++++++++++++++++++++\n"); + for (i = 0; i < 256; i++) { + printk("Gray Level : %03d - ", i); + for (c = CI_RED; c < CI_MAX; c++) + printk(" %c : %04dV", color_name[c], smart->ve[i].v[c]); + printk("\n"); + } +#endif + return 0; +} + + +int init_table_info_ea8061(struct str_smart_dim *smart) +{ + int i; + int offset = 0; + + for (i = 0; i < IV_TABLE_MAX; i++) { + smart->t_info[i].count = (u8)range_table_count[i]; + smart->t_info[i].offset_table = offset_table[i]; + smart->t_info[i].rv = table_radio[i]; + offset += range_table_count[i]; + } + + smart->flooktbl = flookup_table; + smart->g300_gra_tbl = gamma_300_gra_table; + smart->gamma_table[G_21] = GAMMA_CONTROL_TABLE[G_21]; + smart->gamma_table[G_213] = GAMMA_CONTROL_TABLE[G_213]; + smart->gamma_table[G_215] = GAMMA_CONTROL_TABLE[G_215]; + smart->gamma_table[G_218] = GAMMA_CONTROL_TABLE[G_218]; + smart->gamma_table[G_22] = GAMMA_CONTROL_TABLE[G_22]; + smart->gamma_table[G_221] = GAMMA_CONTROL_TABLE[G_221]; + smart->gamma_table[G_222] = GAMMA_CONTROL_TABLE[G_222]; + smart->gamma_table[G_223] = GAMMA_CONTROL_TABLE[G_223]; + smart->gamma_table[G_224] = GAMMA_CONTROL_TABLE[G_224]; + smart->gamma_table[G_225] = GAMMA_CONTROL_TABLE[G_225]; + + for (i = 0; i < GAMMA_300CD_MAX; i++) { + if (smart->panelid[2] == gamma_id_list[i]) + break; + } + + if (i >= GAMMA_300CD_MAX) { + printk(KERN_ERR "[SMART DIMMING-WARNING] %s Can't found default gamma table\n", __func__); + smart->default_gamma = gamma_300cd_list[GAMMA_300CD_MAX-1]; + } else + smart->default_gamma = gamma_300cd_list[i]; + + return 0; +} + +static u32 lookup_vtbl_idx(struct str_smart_dim *smart, u32 gamma) +{ + u32 lookup_index; + u16 table_count, table_index; + u32 gap, i; + u32 minimum = smart->g300_gra_tbl[255]; + u32 candidate = 0; + u32 offset = 0; + + lookup_index = (gamma/VALUE_DIM_1000)+1; + if (lookup_index > MAX_GRADATION) { + /*printk(KERN_ERR "ERROR Wrong input value LOOKUP INDEX : %d\n", lookup_index);*/ + return 0; + } + + if (smart->flooktbl[lookup_index].count) { + if (smart->flooktbl[lookup_index-1].count) { + table_index = smart->flooktbl[lookup_index-1].entry; + table_count = smart->flooktbl[lookup_index].count + smart->flooktbl[lookup_index-1].count; + } else { + table_index = smart->flooktbl[lookup_index].entry; + table_count = smart->flooktbl[lookup_index].count; + } + } else { + offset += 1; + while (!(smart->flooktbl[lookup_index+offset].count || smart->flooktbl[lookup_index-offset].count)) + offset++; + + if (smart->flooktbl[lookup_index-offset].count) + table_index = smart->flooktbl[lookup_index-offset].entry; + else + table_index = smart->flooktbl[lookup_index+offset].entry; + + table_count = smart->flooktbl[lookup_index+offset].count + smart->flooktbl[lookup_index-offset].count; + } + + for (i = 0; i < table_count; i++) { + if (gamma > smart->g300_gra_tbl[table_index]) + gap = gamma - smart->g300_gra_tbl[table_index]; + else + gap = smart->g300_gra_tbl[table_index] - gamma; + + if (gap == 0) { + candidate = table_index; + break; + } + + if (gap < minimum) { + minimum = gap; + candidate = table_index; + } + table_index++; + } + +#if 0 + printk(KERN_INFO "cal : found index : %d\n", candidate); + printk(KERN_INFO "gamma : %d, found index : %d found gamma : %d\n", + gamma, candidate, smart->g300_gra_tbl[candidate]); +#endif + return candidate; +} + +static u32 calc_vt_reg(int ci, u32 dv[CI_MAX][IV_MAX], u32 adjust_volt[CI_MAX][AD_IVMAX]) +{ + return 0; +} + +static u32 calc_v3_reg(int ci, u32 dv[CI_MAX][IV_MAX], u32 adjust_volt[CI_MAX][AD_IVMAX]) +{ + u32 t1, t2; + u32 v0 = VREG_OUT_1000, v3, v11; + u32 ret; + + /*v0 = dv[ci][IV_0];*/ + v3 = dv[ci][IV_3]; + v11 = dv[ci][IV_11]; + + t1 = (v0 - v3) << 10; + t2 = (v0 - v11) ? (v0 - v11) : (v0) ? v0 : 1; + ret = (320 * (t1/t2)) - (64 << 10); + ret >>= 10; + + return ret; +} + +static u32 calc_v11_reg(int ci, u32 dv[CI_MAX][IV_MAX], u32 adjust_volt[CI_MAX][AD_IVMAX]) +{ + u32 t1, t2; + u32 vt, v11, v23; + u32 ret; + + vt = adjust_volt[ci][AD_IVT]; + v11 = dv[ci][IV_11]; + v23 = dv[ci][IV_23]; + t1 = (vt - v11) << 10; + t2 = (vt - v23) ? (vt - v23) : (vt) ? vt : 1; + ret = (320 * (t1/t2)) - (64 << 10); + ret >>= 10; + + return ret; +} + +static u32 calc_v23_reg(int ci, u32 dv[CI_MAX][IV_MAX], u32 adjust_volt[CI_MAX][AD_IVMAX]) +{ + u32 t1, t2; + u32 vt, v23, v35; + u32 ret; + + /*vt = dv[ci][IV_VT];*/ + vt = adjust_volt[ci][AD_IVT]; + v23 = dv[ci][IV_23]; + v35 = dv[ci][IV_35]; + + t1 = (vt - v23) << 10; + t2 = (vt - v35) ? (vt - v35) : (vt) ? vt : 1; + ret = (320 * (t1/t2)) - (64 << 10); + ret >>= 10; + + return ret; +} + +static u32 calc_v35_reg(int ci, u32 dv[CI_MAX][IV_MAX], u32 adjust_volt[CI_MAX][AD_IVMAX]) +{ + u32 t1, t2; + u32 vt, v35, v51; + u32 ret; + + /*vt = dv[ci][IV_VT];*/ + vt = adjust_volt[ci][AD_IVT]; + v35 = dv[ci][IV_35]; + v51 = dv[ci][IV_51]; + + t1 = (vt - v35) << 10; + t2 = (vt - v51) ? (vt - v51) : (vt) ? vt : 1; + ret = (320 * (t1/t2)) - (64 << 10); + ret >>= 10; + + return ret; +} + +static u32 calc_v51_reg(int ci, u32 dv[CI_MAX][IV_MAX], u32 adjust_volt[CI_MAX][AD_IVMAX]) +{ + u32 t1, t2; + u32 vt, v51, v87; + u32 ret; + + /*vt = dv[ci][IV_VT];*/ + vt = adjust_volt[ci][AD_IVT]; + v51 = dv[ci][IV_51]; + v87 = dv[ci][IV_87]; + + t1 = (vt - v51) << 10; + t2 = (vt - v87) ? (vt - v87) : (vt) ? vt : 1; + ret = (320 * (t1/t2)) - (64 << 10); + ret >>= 10; + + return ret; +} + + +static u32 calc_v87_reg(int ci, u32 dv[CI_MAX][IV_MAX], u32 adjust_volt[CI_MAX][AD_IVMAX]) +{ + u32 t1, t2; + u32 vt, v87, v151; + u32 ret; + + /*vt = dv[ci][IV_VT];*/ + vt = adjust_volt[ci][AD_IVT]; + v87 = dv[ci][IV_87]; + v151 = dv[ci][IV_151]; + + t1 = (vt - v87) << 10; + t2 = (vt - v151) ? (vt - v151) : (vt) ? vt : 1; + ret = (320 * (t1/t2)) - (64 << 10); + ret >>= 10; + + return ret; +} + +static u32 calc_v151_reg(int ci, u32 dv[CI_MAX][IV_MAX], u32 adjust_volt[CI_MAX][AD_IVMAX]) +{ + u32 t1, t2; + u32 vt, v151, v203; + u32 ret; + + /*vt = dv[ci][IV_VT];*/ + vt = adjust_volt[ci][AD_IVT]; + v151 = dv[ci][IV_151]; + v203 = dv[ci][IV_203]; + + t1 = (vt - v151) << 10; + t2 = (vt - v203) ? (vt - v203) : (vt) ? vt : 1; + ret = (320 * (t1/t2)) - (64 << 10); + ret >>= 10; + + return ret; +} + +static u32 calc_v203_reg(int ci, u32 dv[CI_MAX][IV_MAX], u32 adjust_volt[CI_MAX][AD_IVMAX]) +{ + u32 t1, t2; + u32 vt, v151, v255; + u32 ret; + + /*vt = dv[ci][IV_VT];*/ + vt = adjust_volt[ci][IV_VT]; + v151 = dv[ci][IV_203]; + v255 = dv[ci][IV_255]; + + t1 = (vt - v151) << 10; + t2 = (vt - v255) ? (vt - v255) : (vt) ? vt : 1; + ret = (320 * (t1/t2)) - (64 << 10); + ret >>= 10; + + return ret; +} + +static u32 calc_v255_reg(int ci, u32 dv[CI_MAX][IV_MAX], u32 adjust_volt[CI_MAX][AD_IVMAX]) +{ + u32 ret; + u32 v255; + v255 = dv[ci][IV_255]; + + ret = (559 * 1000) - (VT_255_calc_param * v255); + ret = ret / 1000; + + return ret; +} + +u32 calc_gamma_table_ea8061(struct str_smart_dim *smart, u32 gv, u8 result[], u8 gamma_curve, const u8 *mtp) +{ + u32 i, c, t1; + u32 temp; + u32 lidx; + u32 dv[CI_MAX][IV_MAX]; + s16 gamma[CI_MAX][IV_MAX]; + u16 offset; + u32(*calc_reg[IV_MAX])(int ci, u32 dv[CI_MAX][IV_MAX], u32 adjust_volt[CI_MAX][AD_IVMAX]) = { + calc_vt_reg, + calc_v3_reg, + calc_v11_reg, + calc_v23_reg, + calc_v35_reg, + calc_v51_reg, + calc_v87_reg, + calc_v151_reg, + calc_v203_reg, + calc_v255_reg, + }; + +memset(gamma, 0, sizeof(gamma)); + +#if 0 + for (c = CI_RED; c < CI_MAX; c++) + dv[c][IV_VT] = smart->ve[AD_IVT].v[c]; /* not use V1 calculate value*/ +#endif + + for (i = IV_3 ; i < IV_MAX; i++) { + temp = (smart->gamma_table[gamma_curve][dv_value[i]] * gv) / 1000; + lidx = lookup_vtbl_idx(smart, temp); + for (c = CI_RED; c < CI_MAX; c++) + dv[c][i] = smart->ve[lidx].v[c]; + } + + for (c = CI_RED; c < CI_MAX; c++) { + offset = c*2; + t1 = s9_to_s16(mtp[offset]<<8|mtp[offset+1]); + smart->mtp[c][IV_255] = t1; + } + + for (i = 1; i < 10; i++) { + for (c = CI_RED; c < CI_MAX; c++) { + t1 = (s8)mtp[CI_MAX*(i + 1)+c]; + smart->mtp[c][IV_255 - i] = t1; + } + } + + /* for IV_1 does not calculate value */ + /* Do not use gamma value (IV_1) */ +#if 0 + for (c = CI_RED; c < CI_MAX; c++) + gamma[c][IV_VT] = smart->default_gamma[c]; +#endif + + for (i = IV_3; i < IV_MAX; i++) { + for (c = CI_RED; c < CI_MAX; c++) + gamma[c][i] = (s16)calc_reg[i](c, dv, smart->adjust_volt) - smart->mtp[c][i]; + } + + for (c = CI_RED; c < CI_MAX; c++) { + offset = IV_255*CI_MAX+c*2; + result[offset+1] = gamma[c][IV_255] & 0xff; + result[offset] = (u8)((gamma[c][IV_255] >> 8) & 0xff); + } + + for (c = CI_RED; c < CI_MAX; c++) { + for (i = IV_VT; i < IV_255; i++) + result[(CI_MAX*i)+c] = gamma[c][i]; + } + +#if 0 + +printk(KERN_INFO "\n\n++++++++++++++++++++++++++++++ FOUND VOLTAGE ++++++++++++++++++++++++++++++\n"); +for (i = IV_VT; i < IV_255; i++) { + printk("V Level : %d - ", i); + for (c = CI_RED; c < CI_MAX; c++) + printk("%c : %04dV", color_name[c], dv[c][i]); + printk("\n"); +} + +printk(KERN_INFO "\n\n++++++++++++++++++++++++++++++ FOUND REG ++++++++++++++++++++++++++++++\n"); +for (i = IV_VT; i < IV_255; i++) { + printk("V Level : %d - ", i); + for (c = CI_RED; c < CI_MAX; c++) + printk("%c : %3d, 0x%2x", color_name[c], gamma[c][i], gamma[c][i]); + printk("\n"); +} +#endif +return 0; +} + +u32 calc_gamma_table_190_ea8061(struct str_smart_dim *smart, u32 gv, u8 result[], u8 gamma_curve, const u8 *mtp) +{ + u32 i, c, t1; + u32 temp; + u32 lidx_215_190; + u32 dv[CI_MAX][IV_MAX]; + s16 gamma_215_190[CI_MAX][IV_MAX]; + u16 offset; + u32(*calc_reg[IV_MAX])(int ci, u32 dv[CI_MAX][IV_MAX], u32 adjust_volt[CI_MAX][AD_IVMAX]) = { + calc_vt_reg, + calc_v3_reg, + calc_v11_reg, + calc_v23_reg, + calc_v35_reg, + calc_v51_reg, + calc_v87_reg, + calc_v151_reg, + calc_v203_reg, + calc_v255_reg, + }; + memset(gamma_215_190, 0, sizeof(gamma_215_190)); + +#if 0 + for (c = CI_RED; c < CI_MAX; c++) + dv[c][IV_1] = smart->ve[AD_IV1].v[c]; +#endif + + for (i = IV_3; i < IV_MAX; i++) { + if (i == IV_151) { + temp = (smart->gamma_table[gamma_curve][dv_value[i]] * gv)/1000; + lidx_215_190 = lookup_vtbl_idx(smart, temp)-1; + } else if ((i == IV_203) || (i == IV_255)) { + temp = (smart->gamma_table[gamma_curve][dv_value[i]] * gv)/1000; + lidx_215_190 = lookup_vtbl_idx(smart, temp)-2; + } else { + temp = (smart->gamma_table[gamma_curve][dv_value[i]] * gv)/1000; + lidx_215_190 = lookup_vtbl_idx(smart, temp); + } + + for (c = CI_RED; c < CI_MAX; c++) + dv[c][i] = smart->ve[lidx_215_190].v[c]; + } + + for (c = CI_RED; c < CI_MAX; c++) { + offset = c*2; + t1 = s9_to_s16(mtp[offset]<<8|mtp[offset+1]); + smart->mtp[c][IV_255] = t1; + } + + for (i = 1; i < 10; i++) { + for (c = CI_RED; c < CI_MAX; c++) { + t1 = (s8)mtp[CI_MAX*(i + 1)+c]; + smart->mtp[c][IV_255 - i] = t1; + } + } + + /* for IV1 does not calculate value */ + /* just use default gamma value (IV1) */ +#if 0 + for (c = CI_RED; c < CI_MAX; c++) + gamma_215_190[c][IV_VT] = smart->default_gamma[c]; +#endif + + for (i = IV_3; i < IV_MAX; i++) { + for (c = CI_RED; c < CI_MAX; c++) + gamma_215_190[c][i] = (s16)calc_reg[i](c, dv, smart->adjust_volt) - smart->mtp[c][i]; + } + + for (c = CI_RED; c < CI_MAX; c++) { + offset = IV_255*CI_MAX+c*2; + result[offset+1] = gamma_215_190[c][IV_255] & 0xff; + result[offset] = (u8)((gamma_215_190[c][IV_255] >> 8) & 0xff); + } + + for (c = CI_RED; c < CI_MAX; c++) { + for (i = IV_VT; i < IV_255; i++) + result[(CI_MAX*i)+c] = gamma_215_190[c][i]; + } + +#if 0 + printk(KERN_INFO "\n\n++++++++++++++++++++++++++++++ FOUND VOLTAGE ++++++++++++++++++++++++++++++\n"); + for (i = IV_VT; i < IV_255; i++) { + printk("V Level : %d - ", i); + for (c = CI_RED; c < CI_MAX; c++) + printk("%c : %04dV", color_name[c], dv[c][i]); + printk("\n"); + } + + printk(KERN_INFO "\n\n++++++++++++++++++++++++++++++ FOUND REG ++++++++++++++++++++++++++++++\n"); + for (i = IV_VT; i < IV_255; i++) { + printk("V Level : %d - ", i); + for (c = CI_RED; c < CI_MAX; c++) + printk("2.15Gamma %c : %3d, 0x%2x", color_name[c], gamma_215_190[c][i], gamma_215_190[c][i]); + printk("\n"); + } +#endif + return 0; +} + +u32 calc_gamma_table_20_100_ea8061(struct str_smart_dim *smart, u32 gv, u8 result[], u8 gamma_curve, const u8 *mtp) +{ + u32 i, c, t1; + u32 temp; + u32 lidx_110; + u32 dv[CI_MAX][IV_MAX]; + s16 gamma_110[CI_MAX][IV_MAX]; + u16 offset; + u32(*calc_reg[IV_MAX])(int ci, u32 dv[CI_MAX][IV_MAX], u32 adjust_volt[CI_MAX][AD_IVMAX]) = { + calc_vt_reg, + calc_v3_reg, + calc_v11_reg, + calc_v23_reg, + calc_v35_reg, + calc_v51_reg, + calc_v87_reg, + calc_v151_reg, + calc_v203_reg, + calc_v255_reg, + }; + memset(gamma_110, 0, sizeof(gamma_110)); + +#if 0 + for (c = CI_RED; c < CI_MAX; c++) + dv[c][IV_1] = smart->ve[AD_IV1].v[c]; +#endif + + for (i = IV_3; i < IV_MAX; i++) { + if (i == IV_11) { + temp = (smart->gamma_table[gamma_curve][dv_value[i]] * gv)/1000; + lidx_110 = lookup_vtbl_idx(smart, temp)-1; + } else { + temp = (smart->gamma_table[gamma_curve][dv_value[i]] * gv)/1000; + lidx_110 = lookup_vtbl_idx(smart, temp); + } + + for (c = CI_RED; c < CI_MAX; c++) + dv[c][i] = smart->ve[lidx_110].v[c]; + } + + for (c = CI_RED; c < CI_MAX; c++) { + offset = c*2; + t1 = s9_to_s16(mtp[offset]<<8|mtp[offset+1]); + smart->mtp[c][IV_255] = t1; + } + + for (i = 1; i < 10; i++) { + for (c = CI_RED; c < CI_MAX; c++) { + t1 = (s8)mtp[CI_MAX*(i + 1)+c]; + smart->mtp[c][IV_255 - i] = t1; + } + } + + /* for IV1 does not calculate value */ + /* just use default gamma value (IV1) */ +#if 0 + for (c = CI_RED; c < CI_MAX; c++) + gamma_210_110[c][IV_VT] = smart->default_gamma[c]; +#endif + + for (i = IV_3; i < IV_MAX; i++) { + for (c = CI_RED; c < CI_MAX; c++) + gamma_110[c][i] = (s16)calc_reg[i](c, dv, smart->adjust_volt) - smart->mtp[c][i]; + } + + for (c = CI_RED; c < CI_MAX; c++) { + offset = IV_255*CI_MAX+c*2; + result[offset+1] = gamma_110[c][IV_255] & 0xff; + result[offset] = (u8)((gamma_110[c][IV_255] >> 8) & 0xff); + } + + for (c = CI_RED; c < CI_MAX; c++) { + for (i = IV_VT; i < IV_255; i++) + result[(CI_MAX*i)+c] = gamma_110[c][i]; + } + +#if 0 + printk(KERN_INFO "\n\n++++++++++++++++++++++++++++++ FOUND VOLTAGE ++++++++++++++++++++++++++++++\n"); + for (i = IV_VT; i < IV_MAX; i++) { + printk("V Level : %d - ", i); + for (c = CI_RED; c < CI_MAX; c++) + printk("%c : %04dV", color_name[c], dv[c][i]); + printk("\n"); + } + + printk(KERN_INFO "\n\n++++++++++++++++++++++++++++++ FOUND REG ++++++++++++++++++++++++++++++\n"); + for (i = IV_VT; i < IV_MAX; i++) { + printk("V Level : %d - ", i); + for (c = CI_RED; c < CI_MAX; c++) + printk("2.15Gamma %c : %3d, 0x%2x", color_name[c], gamma_110[c][i], gamma_210_110[c][i]); + printk("\n"); + } +#endif + return 0; +} diff --git a/drivers/video/samsung/smart_dimming_ea8061.h b/drivers/video/samsung/smart_dimming_ea8061.h new file mode 100644 index 0000000..263c2e2 --- /dev/null +++ b/drivers/video/samsung/smart_dimming_ea8061.h @@ -0,0 +1,133 @@ +/* linux/drivers/video/samsung/smartdimming.h + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + + * Samsung Smart Dimming for OCTA + * + * Minwoo Kim, <minwoo7945.kim@samsung.com> + * +*/ + + +#ifndef __SMART_DIMMING_H__ +#define __SMART_DIMMING_H__ + + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/mutex.h> +#include <linux/wait.h> +#include <linux/ctype.h> + +#define MAX_GRADATION 300 +#define PANEL_ID_MAX 3 +#define GAMMA_300CD_MAX 9 + + +enum { + CI_RED = 0, + CI_GREEN = 1, + CI_BLUE = 2, + CI_MAX = 3, +}; + + +enum { + IV_VT , + IV_3 , + IV_11 , + IV_23 , + IV_35 , + IV_51, + IV_87 , + IV_151, + IV_203, + IV_255, + IV_MAX, + IV_TABLE_MAX, +}; + + +enum { + AD_IVT, + AD_IV3, + AD_IV11, + AD_IV23 , + AD_IV35, + AD_IV51 , + AD_IV87 , + AD_IV151 , + AD_IV203 , + AD_IV255 , + AD_IVMAX , +}; + + +enum { + G_21, + G_213, + G_215, + G_218, + G_22, + G_221, + G_222, + G_223, + G_224, + G_225, + G_MAX, +}; + + +struct str_voltage_entry { + u32 v[CI_MAX]; +}; + + +struct str_table_info { + /* et : start gray value */ + u8 st; + /* end gray value, st + count */ + u8 et; + u8 count; + const u8 *offset_table; + /* rv : ratio value */ + u32 rv; +}; + + +struct str_flookup_table { + u16 entry; + u16 count; +}; + + +struct str_smart_dim { + u8 panelid[PANEL_ID_MAX]; + s16 mtp[CI_MAX][IV_MAX]; + struct str_voltage_entry ve[256]; + const u8 *default_gamma; + struct str_table_info t_info[IV_TABLE_MAX]; + const struct str_flookup_table *flooktbl; + const u32 *g22_tbl; + const u32 *gamma_table[G_MAX]; + const u32 *g300_gra_tbl; + u32 adjust_volt[CI_MAX][AD_IVMAX]; +}; + +struct rgb_offset_info { + unsigned int candela_idx; + unsigned int gray; + unsigned int rgb; + int offset; +}; + + +int init_table_info_ea8061(struct str_smart_dim *smart); +u8 calc_voltage_table_ea8061(struct str_smart_dim *smart, const u8 *mtp); +u32 calc_gamma_table_ea8061(struct str_smart_dim *smart, u32 gv, u8 result[], u8 gamma_curve, const u8 *mtp); +u32 calc_gamma_table_190_ea8061(struct str_smart_dim *smart, u32 gv, u8 result[], u8 gamma_curve, const u8 *mtp); +u32 calc_gamma_table_20_100_ea8061(struct str_smart_dim *smart, u32 gv, u8 result[], u8 gamma_curve, const u8 *mtp); + +#endif diff --git a/drivers/video/samsung/smart_dimming_s6evr02.c b/drivers/video/samsung/smart_dimming_s6evr02.c new file mode 100644 index 0000000..9c0af0a --- /dev/null +++ b/drivers/video/samsung/smart_dimming_s6evr02.c @@ -0,0 +1,948 @@ +/* linux/drivers/video/samsung/smartdimming.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + + * Samsung Smart Dimming for OCTA + * + * Minwoo Kim, <minwoo7945.kim@samsung.com> + * +*/ + +#include "smart_dimming_s6evr02.h" +#include "s6evr02_volt_tbl.h" + +#define VALUE_DIM_1000 1000 +#define VT_255_div_1000 860000 +#define VREG_OUT_1000 6100 +#define VREG_OUT_1000_1024 6246400 +#define VT_255_calc_param (VT_255_div_1000 / VREG_OUT_1000) + +static const u8 range_table_count[IV_TABLE_MAX] = { + 3, 8, 12, 12, 16, 36, 64, 52, 52, 1 +}; + +static const u32 table_radio[IV_TABLE_MAX] = { + 16384, 4138, 2763, 2763, 2080, 918, 516, 636, 636, 0 +}; + +static const u32 dv_value[IV_MAX] = { + 0, 3, 11, 23, 35, 51, 87, 151, 203, 255 +}; + +static const char color_name[3] = {'R', 'G', 'B'}; + +static const u8 *offset_table[IV_TABLE_MAX] = { + NULL, /*V3*/ + NULL, /*V11*/ + NULL, /*V23*/ + NULL, /*V23*/ + NULL, /*V35*/ + NULL, /*V51*/ + NULL, /*V87*/ + NULL, /*V151*/ + NULL, /*V203*/ + NULL /*V255*/ +}; + +static const unsigned char gamma_300cd_80[] = { + 0x00, 0xFF, 0x01, 0x1C, 0x01, 0x2C, + 0xDA, 0xD7, 0xDA, 0xD5, 0xD2, 0xD6, 0xC1, 0xBC, 0xC2, + 0xCA, 0xB9, 0xCB, 0xDC, 0xE5, 0xDD, 0xDA, 0xD8, 0xDD, + 0xBA, 0xA8, 0xC1, 0x6B, 0x20, 0xD7, 0x02, 0x03, 0x02 +}; + +static const unsigned char gamma_300cd_81[] = { + 0x00, 0xFF, 0x01, 0x1D, 0x01, 0x2D, + 0xDA, 0xD7, 0xDA, 0xD6, 0xD3, 0xD7, 0xC1, 0xBC, 0xC1, + 0xCB, 0xC6, 0xCC, 0xDC, 0xD9, 0xDD, 0xDA, 0xD8, 0xDE, + 0xBB, 0xAB, 0xC1, 0xC7, 0xBD, 0xE2, 0x02, 0x03, 0x02 +}; + +static const unsigned char gamma_300cd_82[] = { + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x02, 0x03, 0x02 +}; + +static const unsigned char *gamma_300cd_list[GAMMA_300CD_MAX] = { + gamma_300cd_80, + gamma_300cd_81, + gamma_300cd_82, + gamma_300cd_82, +}; + +static const unsigned char gamma_id_list[GAMMA_300CD_MAX] = { + 0x80, 0x81, 0x82, 0xA2 +}; + +static s16 s9_to_s16(s16 v) +{ + return (s16)(v << 7) >> 7; +} + +static u32 calc_vt_volt(s16 gamma, int rgb_index, u32 adjust_volt[CI_MAX][AD_IVMAX]) +{ + u32 ret = 0; + + ret = volt_table_vt[gamma] >> 16; + + return ret; +} + +static u32 calc_v3_volt(s16 gamma, int rgb_index, u32 adjust_volt[CI_MAX][AD_IVMAX]) +{ + /* for CV : 64, DV :320 */ + int ret = 0; + u32 v0 = VREG_OUT_1000, v11; + u32 ratio = 0; + + /*vt = adjust_volt[rgb_index][AD_IVT];*/ + v11 = adjust_volt[rgb_index][AD_IV11]; + ratio = volt_table_cv_64_dv_320[gamma]; + + ret = (v0 << 16) - ((v0-v11)*ratio); + ret = ret >> 16; + + return ret; +} + +static u32 calc_v11_volt(s16 gamma, int rgb_index, u32 adjust_volt[CI_MAX][AD_IVMAX]) +{ + /* for CV : 64, DV :320*/ + int ret = 0; + u32 vt, v23; + u32 ratio = 0; + + vt = adjust_volt[rgb_index][AD_IVT]; + v23 = adjust_volt[rgb_index][AD_IV23]; + ratio = volt_table_cv_64_dv_320[gamma]; + + ret = (vt << 16) - ((vt-v23)*ratio); + ret = ret >> 16; + + return ret; +} + +static u32 calc_v23_volt(s16 gamma, int rgb_index, u32 adjust_volt[CI_MAX][AD_IVMAX]) +{ + /* for CV : 64, DV :319 */ + int ret = 0; + u32 vt, v35; + u32 ratio = 0; + + vt = adjust_volt[rgb_index][AD_IVT]; + v35 = adjust_volt[rgb_index][AD_IV35]; + ratio = volt_table_cv_64_dv_320[gamma]; + + ret = (vt << 16) - ((vt-v35)*ratio); + ret = ret >> 16; + + return ret; +} + +static u32 calc_v35_volt(s16 gamma, int rgb_index, u32 adjust_volt[CI_MAX][AD_IVMAX]) +{ + /* for CV : 65, DV :319 */ + int ret = 0; + u32 vt, v51; + u32 ratio = 0; + + vt = adjust_volt[rgb_index][AD_IVT]; + v51 = adjust_volt[rgb_index][AD_IV51]; + ratio = volt_table_cv_64_dv_320[gamma]; + + ret = (vt << 16) - ((vt-v51)*ratio); + ret = ret >> 16; + + return ret; +} + +static u32 calc_v51_volt(s16 gamma, int rgb_index, u32 adjust_volt[CI_MAX][AD_IVMAX]) +{ + /* for CV : 65, DV :319 */ + int ret = 0; + u32 vt, v87; + u32 ratio = 0; + + vt = adjust_volt[rgb_index][AD_IVT]; + v87 = adjust_volt[rgb_index][AD_IV87]; + ratio = volt_table_cv_64_dv_320[gamma]; + + ret = (vt << 16) - ((vt-v87)*ratio); + ret = ret >> 16; + + return ret; + +} + +static u32 calc_v87_volt(s16 gamma, int rgb_index, u32 adjust_volt[CI_MAX][AD_IVMAX]) +{ + /* for CV : 64, DV :319 */ + int ret = 0; + u32 vt, v151; + u32 ratio = 0; + + vt = adjust_volt[rgb_index][AD_IVT]; + v151 = adjust_volt[rgb_index][AD_IV151]; + ratio = volt_table_cv_64_dv_320[gamma]; + + ret = (vt << 16) - ((vt-v151)*ratio); + ret = ret >> 16; + + return ret; +} + +static u32 calc_v151_volt(s16 gamma, int rgb_index, u32 adjust_volt[CI_MAX][AD_IVMAX]) +{ + /* for CV : 64, DV :319 */ + int ret = 0; + u32 vt, v203; + u32 ratio = 0; + + vt = adjust_volt[rgb_index][AD_IVT]; + v203 = adjust_volt[rgb_index][AD_IV203]; + ratio = volt_table_cv_64_dv_320[gamma]; + + ret = (vt << 16) - ((vt-v203)*ratio); + ret = ret >> 16; + + return ret; +} + +static u32 calc_v203_volt(s16 gamma, int rgb_index, u32 adjust_volt[CI_MAX][AD_IVMAX]) +{ + /* for CV : 64, DV :319 */ + int ret = 0; + u32 vt, v255; + u32 ratio = 0; + + vt = adjust_volt[rgb_index][AD_IVT]; + v255 = adjust_volt[rgb_index][AD_IV255]; + ratio = volt_table_cv_64_dv_320[gamma]; + + ret = (vt << 16) - ((vt-v255)*ratio); + ret = ret >> 16; + + return ret; +} + +static u32 calc_v255_volt(s16 gamma, int rgb_index, u32 adjust_volt[CI_MAX][AD_IVMAX]) +{ + u32 ret = 0; + + ret = volt_table_v255[gamma] >> 16; + + return ret; +} + +u8 calc_voltage_table(struct str_smart_dim *smart, const u8 *mtp) +{ + int c, i, j; +#if defined(MTP_REVERSE) + int offset1 = 0; +#endif + int offset = 0; + s16 t1, t2; + s16 adjust_mtp[CI_MAX][IV_MAX]; + u8 range_index; + u8 table_index = 0; + u32 v1, v2; + u32 ratio; + u32(*calc_volt[IV_MAX])(s16 gamma, int rgb_index, u32 adjust_volt[CI_MAX][AD_IVMAX]) = { + calc_vt_volt, + calc_v3_volt, + calc_v11_volt, + calc_v23_volt, + calc_v35_volt, + calc_v51_volt, + calc_v87_volt, + calc_v151_volt, + calc_v203_volt, + calc_v255_volt, + }; + u8 calc_seq[9] = { IV_VT, IV_203, IV_151, IV_87, IV_51, IV_35, IV_23, IV_11, IV_3}; + u8 ad_seq[9] = {AD_IVT, AD_IV203, AD_IV151, AD_IV87, AD_IV51, AD_IV35, AD_IV23, AD_IV11, AD_IV3}; + + memset(adjust_mtp, 0, sizeof(adjust_mtp)); + + for (c = CI_RED; c < CI_MAX; c++) { + offset = c*2; + if (mtp[offset] & 0x01) + t1 = mtp[offset + 1] * -1; + else + t1 = mtp[offset + 1]; + t2 = (smart->default_gamma[offset]<<8|smart->default_gamma[offset+1]) + t1; + smart->mtp[c][IV_255] = t1; + adjust_mtp[c][IV_255] = t2; + smart->adjust_volt[c][AD_IV255] = calc_volt[IV_255](t2, c, smart->adjust_volt); + /* for V0 All RGB Voltage Value is Reference Voltage */ + smart->adjust_volt[c][AD_IVT] = VREG_OUT_1000; + } + + for (i = IV_VT; i < IV_255; i++) { + for (c = CI_RED; c < CI_MAX; c++) { + if (i < IV_3) { + t1 = 0; + t2 = smart->default_gamma[CI_MAX*(10-calc_seq[i])+c] + t1; + smart->mtp[c][calc_seq[i]] = t1; + adjust_mtp[c][calc_seq[i]] = t2; + smart->adjust_volt[c][ad_seq[i]] = calc_volt[calc_seq[i]](t2, c, smart->adjust_volt); + } else { + if (mtp[CI_MAX*(10-calc_seq[i])+c] & 0x80) + t1 = (mtp[CI_MAX*(10-calc_seq[i])+c] & 0x7f) * (-1); + else + t1 = (mtp[CI_MAX*(10-calc_seq[i])+c] & 0x7f); + t2 = smart->default_gamma[CI_MAX*(10-calc_seq[i])+c] + t1; + smart->mtp[c][calc_seq[i]] = t1; + adjust_mtp[c][calc_seq[i]] = t2; + smart->adjust_volt[c][ad_seq[i]] = calc_volt[calc_seq[i]](t2, c, smart->adjust_volt); + } + } + } + + for (i = AD_IVT; i < AD_IVMAX; i++) { + for (c = CI_RED; c < CI_MAX; c++) { + if (i == 0) + smart->ve[table_index].v[c] = VREG_OUT_1000; + else + smart->ve[table_index].v[c] = smart->adjust_volt[c][i]; + } + range_index = 0; + + for (j = table_index+1; j < table_index+range_table_count[i]; j++) { + for (c = CI_RED; c < CI_MAX; c++) { + if (smart->t_info[i].offset_table != NULL) + ratio = smart->t_info[i].offset_table[range_index] * smart->t_info[i].rv; + else + ratio = (range_table_count[i]-(range_index+1)) * smart->t_info[i].rv; + + v1 = smart->adjust_volt[c][i+1] << 15; + v2 = (smart->adjust_volt[c][i] - smart->adjust_volt[c][i+1])*ratio; + smart->ve[j].v[c] = ((v1+v2) >> 15); + } + range_index++; + } + table_index = j; + } + + for (i = 1; i < 3; i++) { + for (c = CI_RED; c < CI_MAX; c++) + smart->ve[i].v[c] = smart->ve[3].v[c]+((smart->ve[0].v[c]-smart->ve[3].v[c])*(3-i)/3); + } + +#if 0 + printk(KERN_INFO "++++++++++++++++++++++++++++++ MTP VALUE ++++++++++++++++++++++++++++++\n"); + for (i = IV_VT; i < IV_MAX; i++) { + printk("V Level : %d - ", i); + for (c = CI_RED; c < CI_MAX; c++) + printk("%c : 0x%08x(%04d)", color_name[c], smart->mtp[c][i], smart->mtp[c][i]); + printk("\n"); + } + + printk(KERN_INFO "\n\n++++++++++++++++++++++++++++++ ADJUST VALUE ++++++++++++++++++++++++++++++\n"); + for (i = IV_VT; i < IV_MAX; i++) { + printk("V Level : %d - ", i); + for (c = CI_RED; c < CI_MAX; c++) + printk("%c : 0x%08x(%04d)", color_name[c], adjust_mtp[c][i], adjust_mtp[c][i]); + printk("\n"); + } + + printk(KERN_INFO "\n\n++++++++++++++++++++++++++++++ ADJUST VOLTAGE ++++++++++++++++++++++++++++++\n"); + for (i = AD_IVT; i < AD_IVMAX; i++) { + printk("V Level : %d - ", i); + for (c = CI_RED; c < CI_MAX; c++) + printk("%c : %04dV", color_name[c], smart->adjust_volt[c][i]); + printk("\n"); + } + + printk(KERN_INFO "\n\n++++++++++++++++++++++++++++++++++++++ VOLTAGE TABLE ++++++++++++++++++++++++++++++++++++++\n"); + for (i = 0; i < 256; i++) { + printk("Gray Level : %03d - ", i); + for (c = CI_RED; c < CI_MAX; c++) + printk("%c : %04dV", color_name[c], smart->ve[i].v[c]); + printk("\n"); + } +#endif + return 0; +} + + +int init_table_info(struct str_smart_dim *smart) +{ + int i; + int offset = 0; + + for (i = 0; i < IV_TABLE_MAX; i++) { + smart->t_info[i].count = (u8)range_table_count[i]; + smart->t_info[i].offset_table = offset_table[i]; + smart->t_info[i].rv = table_radio[i]; + offset += range_table_count[i]; + } + + smart->flooktbl = flookup_table; + smart->g300_gra_tbl = gamma_300_gra_table; + smart->gamma_table[G_21] = GAMMA_CONTROL_TABLE[G_21]; + smart->gamma_table[G_213] = GAMMA_CONTROL_TABLE[G_213]; + smart->gamma_table[G_215] = GAMMA_CONTROL_TABLE[G_215]; + smart->gamma_table[G_218] = GAMMA_CONTROL_TABLE[G_218]; + smart->gamma_table[G_22] = GAMMA_CONTROL_TABLE[G_22]; + smart->gamma_table[G_221] = GAMMA_CONTROL_TABLE[G_221]; + smart->gamma_table[G_222] = GAMMA_CONTROL_TABLE[G_222]; + smart->gamma_table[G_223] = GAMMA_CONTROL_TABLE[G_223]; + smart->gamma_table[G_224] = GAMMA_CONTROL_TABLE[G_224]; + smart->gamma_table[G_225] = GAMMA_CONTROL_TABLE[G_225]; + + for (i = 0; i < GAMMA_300CD_MAX; i++) { + if (smart->panelid[2] == gamma_id_list[i]) + break; + } + + if (i >= GAMMA_300CD_MAX) { + printk(KERN_ERR "[SMART DIMMING-WARNING] %s Can't found default gamma table\n", __func__); + smart->default_gamma = gamma_300cd_list[GAMMA_300CD_MAX-1]; + } else + smart->default_gamma = gamma_300cd_list[i]; + + return 0; +} + +static u32 lookup_vtbl_idx(struct str_smart_dim *smart, u32 gamma) +{ + u32 lookup_index; + u16 table_count, table_index; + u32 gap, i; + u32 minimum = smart->g300_gra_tbl[255]; + u32 candidate = 0; + u32 offset = 0; + + lookup_index = (gamma/VALUE_DIM_1000)+1; + if (lookup_index > MAX_GRADATION) { + /*printk(KERN_ERR "ERROR Wrong input value LOOKUP INDEX : %d\n", lookup_index);*/ + return 0; + } + + if (smart->flooktbl[lookup_index].count) { + if (smart->flooktbl[lookup_index-1].count) { + table_index = smart->flooktbl[lookup_index-1].entry; + table_count = smart->flooktbl[lookup_index].count + smart->flooktbl[lookup_index-1].count; + } else { + table_index = smart->flooktbl[lookup_index].entry; + table_count = smart->flooktbl[lookup_index].count; + } + } else { + offset += 1; + while (!(smart->flooktbl[lookup_index+offset].count || smart->flooktbl[lookup_index-offset].count)) + offset++; + + if (smart->flooktbl[lookup_index-offset].count) + table_index = smart->flooktbl[lookup_index-offset].entry; + else + table_index = smart->flooktbl[lookup_index+offset].entry; + + table_count = smart->flooktbl[lookup_index+offset].count + smart->flooktbl[lookup_index-offset].count; + } + + for (i = 0; i < table_count; i++) { + if (gamma > smart->g300_gra_tbl[table_index]) + gap = gamma - smart->g300_gra_tbl[table_index]; + else + gap = smart->g300_gra_tbl[table_index] - gamma; + + if (gap == 0) { + candidate = table_index; + break; + } + + if (gap < minimum) { + minimum = gap; + candidate = table_index; + } + table_index++; + } + +#if 0 + printk(KERN_INFO "cal : found index : %d\n", candidate); + printk(KERN_INFO "gamma : %d, found index : %d found gamma : %d\n", + gamma, candidate, smart->g300_gra_tbl[candidate]); +#endif + return candidate; +} + +static u32 calc_vt_reg(int ci, u32 dv[CI_MAX][IV_MAX], u32 adjust_volt[CI_MAX][AD_IVMAX]) +{ + return 0; +} + +static u32 calc_v3_reg(int ci, u32 dv[CI_MAX][IV_MAX], u32 adjust_volt[CI_MAX][AD_IVMAX]) +{ + u32 t1, t2; + u32 v0 = VREG_OUT_1000, v3, v11; + u32 ret; + + /*v0 = dv[ci][IV_0];*/ + v3 = dv[ci][IV_3]; + v11 = dv[ci][IV_11]; + + t1 = (v0 - v3) << 10; + t2 = (v0 - v11) ? (v0 - v11) : (v0) ? v0 : 1; + ret = (320 * (t1/t2)) - (64 << 10); + ret >>= 10; + + return ret; +} + +static u32 calc_v11_reg(int ci, u32 dv[CI_MAX][IV_MAX], u32 adjust_volt[CI_MAX][AD_IVMAX]) +{ + u32 t1, t2; + u32 vt, v11, v23; + u32 ret; + + vt = adjust_volt[ci][AD_IVT]; + v11 = dv[ci][IV_11]; + v23 = dv[ci][IV_23]; + t1 = (vt - v11) << 10; + t2 = (vt - v23) ? (vt - v23) : (vt) ? vt : 1; + ret = (320 * (t1/t2)) - (64 << 10); + ret >>= 10; + + return ret; +} + +static u32 calc_v23_reg(int ci, u32 dv[CI_MAX][IV_MAX], u32 adjust_volt[CI_MAX][AD_IVMAX]) +{ + u32 t1, t2; + u32 vt, v23, v35; + u32 ret; + + /*vt = dv[ci][IV_VT];*/ + vt = adjust_volt[ci][AD_IVT]; + v23 = dv[ci][IV_23]; + v35 = dv[ci][IV_35]; + + t1 = (vt - v23) << 10; + t2 = (vt - v35) ? (vt - v35) : (vt) ? vt : 1; + ret = (320 * (t1/t2)) - (64 << 10); + ret >>= 10; + + return ret; +} + +static u32 calc_v35_reg(int ci, u32 dv[CI_MAX][IV_MAX], u32 adjust_volt[CI_MAX][AD_IVMAX]) +{ + u32 t1, t2; + u32 vt, v35, v51; + u32 ret; + + /*vt = dv[ci][IV_VT];*/ + vt = adjust_volt[ci][AD_IVT]; + v35 = dv[ci][IV_35]; + v51 = dv[ci][IV_51]; + + t1 = (vt - v35) << 10; + t2 = (vt - v51) ? (vt - v51) : (vt) ? vt : 1; + ret = (320 * (t1/t2)) - (64 << 10); + ret >>= 10; + + return ret; +} + +static u32 calc_v51_reg(int ci, u32 dv[CI_MAX][IV_MAX], u32 adjust_volt[CI_MAX][AD_IVMAX]) +{ + u32 t1, t2; + u32 vt, v51, v87; + u32 ret; + + /*vt = dv[ci][IV_VT];*/ + vt = adjust_volt[ci][AD_IVT]; + v51 = dv[ci][IV_51]; + v87 = dv[ci][IV_87]; + + t1 = (vt - v51) << 10; + t2 = (vt - v87) ? (vt - v87) : (vt) ? vt : 1; + ret = (320 * (t1/t2)) - (64 << 10); + ret >>= 10; + + return ret; +} + + +static u32 calc_v87_reg(int ci, u32 dv[CI_MAX][IV_MAX], u32 adjust_volt[CI_MAX][AD_IVMAX]) +{ + u32 t1, t2; + u32 vt, v87, v151; + u32 ret; + + /*vt = dv[ci][IV_VT];*/ + vt = adjust_volt[ci][AD_IVT]; + v87 = dv[ci][IV_87]; + v151 = dv[ci][IV_151]; + + t1 = (vt - v87) << 10; + t2 = (vt - v151) ? (vt - v151) : (vt) ? vt : 1; + ret = (320 * (t1/t2)) - (64 << 10); + ret >>= 10; + + return ret; +} + +static u32 calc_v151_reg(int ci, u32 dv[CI_MAX][IV_MAX], u32 adjust_volt[CI_MAX][AD_IVMAX]) +{ + u32 t1, t2; + u32 vt, v151, v203; + u32 ret; + + /*vt = dv[ci][IV_VT];*/ + vt = adjust_volt[ci][AD_IVT]; + v151 = dv[ci][IV_151]; + v203 = dv[ci][IV_203]; + + t1 = (vt - v151) << 10; + t2 = (vt - v203) ? (vt - v203) : (vt) ? vt : 1; + ret = (320 * (t1/t2)) - (65 << 10); + ret >>= 10; + + return ret; +} + +static u32 calc_v203_reg(int ci, u32 dv[CI_MAX][IV_MAX], u32 adjust_volt[CI_MAX][AD_IVMAX]) +{ + u32 t1, t2; + u32 vt, v151, v255; + u32 ret; + + /*vt = dv[ci][IV_VT];*/ + vt = adjust_volt[ci][IV_VT]; + v151 = dv[ci][IV_203]; + v255 = dv[ci][IV_255]; + + t1 = (vt - v151) << 10; + t2 = (vt - v255) ? (vt - v255) : (vt) ? vt : 1; + ret = (320 * (t1/t2)) - (64 << 10); + ret >>= 10; + + return ret; +} + +static u32 calc_v255_reg(int ci, u32 dv[CI_MAX][IV_MAX], u32 adjust_volt[CI_MAX][AD_IVMAX]) +{ + u32 ret; + u32 v255; + v255 = dv[ci][IV_255]; + + ret = (788 * 1000) - (141 * v255); + ret = ret / 1000; + + return ret; +} + +u32 calc_gamma_table(struct str_smart_dim *smart, u32 gv, u8 result[], u8 gamma_curve, const u8 *mtp) +{ + u32 i, c, t1; + u32 temp; + u32 lidx; + u32 dv[CI_MAX][IV_MAX]; + s16 gamma[CI_MAX][IV_MAX]; + u16 offset; + u32(*calc_reg[IV_MAX])(int ci, u32 dv[CI_MAX][IV_MAX], u32 adjust_volt[CI_MAX][AD_IVMAX]) = { + calc_vt_reg, + calc_v3_reg, + calc_v11_reg, + calc_v23_reg, + calc_v35_reg, + calc_v51_reg, + calc_v87_reg, + calc_v151_reg, + calc_v203_reg, + calc_v255_reg, + }; + +memset(gamma, 0, sizeof(gamma)); + +#if 0 + for (c = CI_RED; c < CI_MAX; c++) + dv[c][IV_VT] = smart->ve[AD_IVT].v[c]; /* not use V1 calculate value*/ +#endif + + for (i = IV_3 ; i < IV_MAX; i++) { + temp = (smart->gamma_table[gamma_curve][dv_value[i]] * gv) / 1000; + lidx = lookup_vtbl_idx(smart, temp); + for (c = CI_RED; c < CI_MAX; c++) + dv[c][i] = smart->ve[lidx].v[c]; + } + + for (c = CI_RED; c < CI_MAX; c++) { + offset = c*2; + if (mtp[offset] & 0x01) + t1 = mtp[offset + 1] * -1; + else + t1 = mtp[offset + 1]; + + smart->mtp[c][IV_255] = t1; + } + + for (i = 1; i < 10; i++) { + for (c = CI_RED; c < CI_MAX; c++) { + if (mtp[CI_MAX*(i + 1)+c] & 0x80) + t1 = (mtp[CI_MAX*(i + 1)+c] & 0x7f) * (-1); + else + t1 = (mtp[CI_MAX*(i + 1)+c] & 0x7f); + + smart->mtp[c][IV_255 - i] = t1; + } + } + + /* for IV_1 does not calculate value */ + /* Do not use gamma value (IV_1) */ +#if 0 + for (c = CI_RED; c < CI_MAX; c++) + gamma[c][IV_VT] = smart->default_gamma[c]; +#endif + + for (i = IV_3; i < IV_MAX; i++) { + for (c = CI_RED; c < CI_MAX; c++) + gamma[c][i] = (s16)calc_reg[i](c, dv, smart->adjust_volt) - smart->mtp[c][i]; + } + + for (c = CI_RED; c < CI_MAX; c++) { + offset = IV_255*CI_MAX+c*2; + result[offset+1] = gamma[c][IV_255] & 0xff; + result[offset] = (u8)((gamma[c][IV_255] >> 8) & 0xff); + } + + for (c = CI_RED; c < CI_MAX; c++) { + for (i = IV_VT; i < IV_255; i++) + result[(CI_MAX*i)+c] = gamma[c][i]; + } + +#if 0 + printk(KERN_INFO "\n\n++++++++++++++++++++++++++++++ FOUND VOLTAGE ++++++++++++++++++++++++++++++\n"); + for (i = IV_3; i < IV_MAX; i++) { + printk("V Level : %d - ", i); + for (c = CI_RED; c < CI_MAX; c++) + printk("%c : %04dV", color_name[c], dv[c][i]); + printk("\n"); + } + +printk(KERN_INFO "\n\n++++++++++++++++++++++++++++++ FOUND REG ++++++++++++++++++++++++++++++\n"); + for (i = IV_3; i < IV_MAX; i++) { + printk("V Level : %d - ", i); + for (c = CI_RED; c < CI_MAX; c++) + printk("%c : %3d, 0x%2x", color_name[c], gamma[c][i], gamma[c][i]); + printk("\n"); + } +#endif +return 0; +} + +u32 calc_gamma_table_215_190(struct str_smart_dim *smart, u32 gv, u8 result[], u8 gamma_curve, const u8 *mtp) +{ + u32 i, c, t1; + u32 temp; + u32 lidx_215_190; + u32 dv[CI_MAX][IV_MAX]; + s16 gamma_215_190[CI_MAX][IV_MAX]; + u16 offset; + u32(*calc_reg[IV_MAX])(int ci, u32 dv[CI_MAX][IV_MAX], u32 adjust_volt[CI_MAX][AD_IVMAX]) = { + calc_vt_reg, + calc_v3_reg, + calc_v11_reg, + calc_v23_reg, + calc_v35_reg, + calc_v51_reg, + calc_v87_reg, + calc_v151_reg, + calc_v203_reg, + calc_v255_reg, + }; + memset(gamma_215_190, 0, sizeof(gamma_215_190)); + +#if 0 + for (c = CI_RED; c < CI_MAX; c++) + dv[c][IV_1] = smart->ve[AD_IV1].v[c]; +#endif + + for (i = IV_3; i < IV_MAX; i++) { + if (i == IV_151) { + temp = (smart->gamma_table[gamma_curve][dv_value[i]] * gv)/1000; + lidx_215_190 = lookup_vtbl_idx(smart, temp)-1; + } else if ((i == IV_203) || (i == IV_255)) { + temp = (smart->gamma_table[gamma_curve][dv_value[i]] * gv)/1000; + lidx_215_190 = lookup_vtbl_idx(smart, temp)-2; + } else { + temp = (smart->gamma_table[gamma_curve][dv_value[i]] * gv)/1000; + lidx_215_190 = lookup_vtbl_idx(smart, temp); + } + + for (c = CI_RED; c < CI_MAX; c++) + dv[c][i] = smart->ve[lidx_215_190].v[c]; + } + + for (c = CI_RED; c < CI_MAX; c++) { + offset = c*2; + if (mtp[offset] & 0x01) + t1 = mtp[offset + 1] * -1; + else + t1 = mtp[offset + 1]; + + smart->mtp[c][IV_255] = t1; + } + + for (i = 1; i < 10; i++) { + for (c = CI_RED; c < CI_MAX; c++) { + if (mtp[CI_MAX*(i + 1)+c] & 0x80) + t1 = (mtp[CI_MAX*(i + 1)+c] & 0x7f) * (-1); + else + t1 = (mtp[CI_MAX*(i + 1)+c] & 0x7f); + + smart->mtp[c][IV_255 - i] = t1; + } + } + + /* for IV1 does not calculate value */ + /* just use default gamma value (IV1) */ +#if 0 + for (c = CI_RED; c < CI_MAX; c++) + gamma_215_190[c][IV_VT] = smart->default_gamma[c]; +#endif + + for (i = IV_3; i < IV_MAX; i++) { + for (c = CI_RED; c < CI_MAX; c++) + gamma_215_190[c][i] = (s16)calc_reg[i](c, dv, smart->adjust_volt) - smart->mtp[c][i]; + } + + for (c = CI_RED; c < CI_MAX; c++) { + offset = IV_255*CI_MAX+c*2; + result[offset+1] = gamma_215_190[c][IV_255] & 0xff; + result[offset] = (u8)((gamma_215_190[c][IV_255] >> 8) & 0xff); + } + + for (c = CI_RED; c < CI_MAX; c++) { + for (i = IV_VT; i < IV_255; i++) + result[(CI_MAX*i)+c] = gamma_215_190[c][i]; + } + +#if 0 + printk(KERN_INFO "\n\n++++++++++++++++++++++++++++++ FOUND VOLTAGE ++++++++++++++++++++++++++++++\n"); + for (i = IV_3; i < IV_MAX; i++) { + printk("V Level : %d - ", i); + for (c = CI_RED; c < CI_MAX; c++) + printk("%c : %04dV", color_name[c], dv[c][i]); + printk("\n"); + } + + printk(KERN_INFO "\n\n++++++++++++++++++++++++++++++ FOUND REG ++++++++++++++++++++++++++++++\n"); + for (i = IV_3; i < IV_MAX; i++) { + printk("V Level : %d - ", i); + for (c = CI_RED; c < CI_MAX; c++) + printk("2.15Gamma %c : %3d, 0x%2x", color_name[c], gamma_215_190[c][i], gamma_215_190[c][i]); + printk("\n"); + } +#endif + return 0; +} + +u32 calc_gamma_table_210_20_100(struct str_smart_dim *smart, u32 gv, u8 result[], u8 gamma_curve, const u8 *mtp) +{ + u32 i, c, t1; + u32 temp; + u32 lidx_210_110; + u32 dv[CI_MAX][IV_MAX]; + s16 gamma_210_110[CI_MAX][IV_MAX]; + u16 offset; + u32(*calc_reg[IV_MAX])(int ci, u32 dv[CI_MAX][IV_MAX], u32 adjust_volt[CI_MAX][AD_IVMAX]) = { + calc_vt_reg, + calc_v3_reg, + calc_v11_reg, + calc_v23_reg, + calc_v35_reg, + calc_v51_reg, + calc_v87_reg, + calc_v151_reg, + calc_v203_reg, + calc_v255_reg, + }; + memset(gamma_210_110, 0, sizeof(gamma_210_110)); + +#if 0 + for (c = CI_RED; c < CI_MAX; c++) + dv[c][IV_1] = smart->ve[AD_IV1].v[c]; +#endif + + for (i = IV_3; i < IV_MAX; i++) { + if (i == IV_11) { + temp = (smart->gamma_table[gamma_curve][dv_value[i]] * gv)/1000; + lidx_210_110 = lookup_vtbl_idx(smart, temp)-1; + } else { + temp = (smart->gamma_table[gamma_curve][dv_value[i]] * gv)/1000; + lidx_210_110 = lookup_vtbl_idx(smart, temp); + } + + for (c = CI_RED; c < CI_MAX; c++) + dv[c][i] = smart->ve[lidx_210_110].v[c]; + } + + for (c = CI_RED; c < CI_MAX; c++) { + offset = c*2; + if (mtp[offset] & 0x01) + t1 = mtp[offset + 1] * -1; + else + t1 = mtp[offset + 1]; + + smart->mtp[c][IV_255] = t1; + } + + for (i = 1; i < 10; i++) { + for (c = CI_RED; c < CI_MAX; c++) { + if (mtp[CI_MAX*(i + 1)+c] & 0x80) + t1 = (mtp[CI_MAX*(i + 1)+c] & 0x7f) * (-1); + else + t1 = (mtp[CI_MAX*(i + 1)+c] & 0x7f); + + smart->mtp[c][IV_255 - i] = t1; + } + } + + /* for IV1 does not calculate value */ + /* just use default gamma value (IV1) */ +#if 0 + for (c = CI_RED; c < CI_MAX; c++) + gamma_210_110[c][IV_VT] = smart->default_gamma[c]; +#endif + + for (i = IV_3; i < IV_MAX; i++) { + for (c = CI_RED; c < CI_MAX; c++) + gamma_210_110[c][i] = (s16)calc_reg[i](c, dv, smart->adjust_volt) - smart->mtp[c][i]; + } + + for (c = CI_RED; c < CI_MAX; c++) { + offset = IV_255*CI_MAX+c*2; + result[offset+1] = gamma_210_110[c][IV_255] & 0xff; + result[offset] = (u8)((gamma_210_110[c][IV_255] >> 8) & 0xff); + } + + for (c = CI_RED; c < CI_MAX; c++) { + for (i = IV_VT; i < IV_255; i++) + result[(CI_MAX*i)+c] = gamma_210_110[c][i]; + } + +#if 0 + printk(KERN_INFO "\n\n++++++++++++++++++++++++++++++ FOUND VOLTAGE ++++++++++++++++++++++++++++++\n"); + for (i = IV_VT; i < IV_MAX; i++) { + printk("V Level : %d - ", i); + for (c = CI_RED; c < CI_MAX; c++) + printk("%c : %04dV", color_name[c], dv[c][i]); + printk("\n"); + } + + printk(KERN_INFO "\n\n++++++++++++++++++++++++++++++ FOUND REG ++++++++++++++++++++++++++++++\n"); + for (i = IV_VT; i < IV_MAX; i++) { + printk("V Level : %d - ", i); + for (c = CI_RED; c < CI_MAX; c++) + printk("2.15Gamma %c : %3d, 0x%2x", color_name[c], gamma_210_110[c][i], gamma_210_110[c][i]); + printk("\n"); + } +#endif + return 0; +} diff --git a/drivers/video/samsung/smart_dimming_s6evr02.h b/drivers/video/samsung/smart_dimming_s6evr02.h new file mode 100644 index 0000000..28fd3c0 --- /dev/null +++ b/drivers/video/samsung/smart_dimming_s6evr02.h @@ -0,0 +1,133 @@ +/* linux/drivers/video/samsung/smartdimming.h + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com + + * Samsung Smart Dimming for OCTA + * + * Minwoo Kim, <minwoo7945.kim@samsung.com> + * +*/ + + +#ifndef __SMART_DIMMING_H__ +#define __SMART_DIMMING_H__ + + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/mutex.h> +#include <linux/wait.h> +#include <linux/ctype.h> + +#define MAX_GRADATION 300 +#define PANEL_ID_MAX 3 +#define GAMMA_300CD_MAX 4 + + +enum { + CI_RED = 0, + CI_GREEN = 1, + CI_BLUE = 2, + CI_MAX = 3, +}; + + +enum { + IV_VT , + IV_3 , + IV_11 , + IV_23 , + IV_35 , + IV_51, + IV_87 , + IV_151, + IV_203, + IV_255, + IV_MAX, + IV_TABLE_MAX, +}; + + +enum { + AD_IVT, + AD_IV3, + AD_IV11, + AD_IV23 , + AD_IV35, + AD_IV51 , + AD_IV87 , + AD_IV151 , + AD_IV203 , + AD_IV255 , + AD_IVMAX , +}; + + +enum { + G_21, + G_213, + G_215, + G_218, + G_22, + G_221, + G_222, + G_223, + G_224, + G_225, + G_MAX, +}; + + +struct str_voltage_entry { + u32 v[CI_MAX]; +}; + + +struct str_table_info { + /* et : start gray value */ + u8 st; + /* end gray value, st + count */ + u8 et; + u8 count; + const u8 *offset_table; + /* rv : ratio value */ + u32 rv; +}; + + +struct str_flookup_table { + u16 entry; + u16 count; +}; + + +struct str_smart_dim { + u8 panelid[PANEL_ID_MAX]; + s16 mtp[CI_MAX][IV_MAX]; + struct str_voltage_entry ve[256]; + const u8 *default_gamma; + struct str_table_info t_info[IV_TABLE_MAX]; + const struct str_flookup_table *flooktbl; + const u32 *g22_tbl; + const u32 *gamma_table[G_MAX]; + const u32 *g300_gra_tbl; + u32 adjust_volt[CI_MAX][AD_IVMAX]; +}; + +struct rgb_offset_info { + unsigned int candela_idx; + unsigned int gray; + unsigned int rgb; + int offset; +}; + + +int init_table_info(struct str_smart_dim *smart); +u8 calc_voltage_table(struct str_smart_dim *smart, const u8 *mtp); +u32 calc_gamma_table(struct str_smart_dim *smart, u32 gv, u8 result[], u8 gamma_curve, const u8 *mtp); +u32 calc_gamma_table_215_190(struct str_smart_dim *smart, u32 gv, u8 result[], u8 gamma_curve, const u8 *mtp); +u32 calc_gamma_table_210_20_100(struct str_smart_dim *smart, u32 gv, u8 result[], u8 gamma_curve, const u8 *mtp); + +#endif |