diff options
70 files changed, 30037 insertions, 0 deletions
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 883c88f3de7a..984a75440710 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig | |||
@@ -145,5 +145,7 @@ source "drivers/staging/xgifb/Kconfig" | |||
145 | 145 | ||
146 | source "drivers/staging/mrst-touchscreen/Kconfig" | 146 | source "drivers/staging/mrst-touchscreen/Kconfig" |
147 | 147 | ||
148 | source "drivers/staging/msm/Kconfig" | ||
149 | |||
148 | endif # !STAGING_EXCLUDE_BUILD | 150 | endif # !STAGING_EXCLUDE_BUILD |
149 | endif # STAGING | 151 | endif # STAGING |
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 352ca2a973c2..9fa25133874a 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile | |||
@@ -53,3 +53,4 @@ obj-$(CONFIG_TI_ST) += ti-st/ | |||
53 | obj-$(CONFIG_ADIS16255) += adis16255/ | 53 | obj-$(CONFIG_ADIS16255) += adis16255/ |
54 | obj-$(CONFIG_FB_XGI) += xgifb/ | 54 | obj-$(CONFIG_FB_XGI) += xgifb/ |
55 | obj-$(CONFIG_TOUCHSCREEN_MRSTOUCH) += mrst-touchscreen/ | 55 | obj-$(CONFIG_TOUCHSCREEN_MRSTOUCH) += mrst-touchscreen/ |
56 | obj-$(CONFIG_MSM_STAGING) += msm/ | ||
diff --git a/drivers/staging/msm/Kconfig b/drivers/staging/msm/Kconfig new file mode 100644 index 000000000000..c57039f2060b --- /dev/null +++ b/drivers/staging/msm/Kconfig | |||
@@ -0,0 +1,134 @@ | |||
1 | config MSM_STAGING | ||
2 | tristate "MSM Frame Buffer Support" | ||
3 | depends on FB && ARCH_MSM && !FB_MSM | ||
4 | select FB_BACKLIGHT if FB_MSM_BACKLIGHT | ||
5 | select NEW_LEDS | ||
6 | select LEDS_CLASS | ||
7 | select FB_CFB_FILLRECT | ||
8 | select FB_CFB_COPYAREA | ||
9 | select FB_CFB_IMAGEBLIT | ||
10 | ---help--- | ||
11 | Support for MSM Framebuffer. | ||
12 | |||
13 | if MSM_STAGING | ||
14 | |||
15 | config FB_MSM_LCDC_HW | ||
16 | bool | ||
17 | default n | ||
18 | |||
19 | choice | ||
20 | prompt "MDP HW version" | ||
21 | default FB_MSM_MDP31 | ||
22 | |||
23 | config FB_MSM_MDP31 | ||
24 | select FB_MSM_LCDC_HW | ||
25 | bool "MDP HW ver3.1" | ||
26 | ---help--- | ||
27 | Support for MSM MDP HW revision 3.1 | ||
28 | Say Y here if this is msm8x50 variant platform. | ||
29 | endchoice | ||
30 | |||
31 | config FB_MSM_LCDC | ||
32 | bool | ||
33 | default n | ||
34 | |||
35 | config FB_MSM_TVOUT | ||
36 | bool | ||
37 | default n | ||
38 | |||
39 | config FB_MSM_LCDC_PANEL | ||
40 | bool | ||
41 | select FB_MSM_LCDC | ||
42 | default n | ||
43 | |||
44 | config FB_MSM_LCDC_PRISM_WVGA | ||
45 | bool | ||
46 | select FB_MSM_LCDC_PANEL | ||
47 | default n | ||
48 | |||
49 | config FB_MSM_LCDC_ST1_WXGA | ||
50 | bool | ||
51 | select FB_MSM_LCDC_PANEL | ||
52 | default n | ||
53 | |||
54 | config FB_MSM_LCDC_ST15_WXGA | ||
55 | bool | ||
56 | select FB_MSM_LCDC_PANEL | ||
57 | default n | ||
58 | |||
59 | config FB_MSM_LCDC_WXGA | ||
60 | bool | ||
61 | select FB_MSM_LCDC_PANEL | ||
62 | default n | ||
63 | |||
64 | choice | ||
65 | prompt "LCD Panel" | ||
66 | default FB_MSM_LCDC_ST15_PANEL | ||
67 | |||
68 | config FB_MSM_LCDC_PRISM_WVGA_PANEL | ||
69 | depends on FB_MSM_LCDC_HW | ||
70 | bool "LCDC Prism WVGA Panel" | ||
71 | select FB_MSM_LCDC_PRISM_WVGA | ||
72 | ---help--- | ||
73 | Support for LCDC Prism WVGA (800x480) panel | ||
74 | |||
75 | |||
76 | config FB_MSM_LCDC_ST15_PANEL | ||
77 | depends on FB_MSM_LCDC_HW | ||
78 | bool "LCDC ST1.5 Panel" | ||
79 | select FB_MSM_LCDC_ST15_WXGA | ||
80 | ---help--- | ||
81 | Support for ST1.5 WXGA (1366x768) panel | ||
82 | |||
83 | config FB_MSM_PANEL_NONE | ||
84 | bool "NONE" | ||
85 | ---help--- | ||
86 | This will disable LCD panel | ||
87 | endchoice | ||
88 | |||
89 | choice | ||
90 | prompt "Secondary LCD Panel" | ||
91 | depends on FB_MSM_MDP31 | ||
92 | default FB_MSM_SECONDARY_PANEL_NONE | ||
93 | |||
94 | config FB_MSM_SECONDARY_PANEL_NONE | ||
95 | bool "NONE" | ||
96 | ---help--- | ||
97 | No secondary panel | ||
98 | endchoice | ||
99 | |||
100 | config FB_MSM_TVOUT_NTSC | ||
101 | bool | ||
102 | select FB_MSM_TVOUT | ||
103 | default n | ||
104 | |||
105 | config FB_MSM_TVOUT_PAL | ||
106 | bool | ||
107 | select FB_MSM_TVOUT | ||
108 | default n | ||
109 | |||
110 | choice | ||
111 | depends on (FB_MSM_MDP22 || FB_MSM_MDP31) | ||
112 | prompt "TVOut Region" | ||
113 | default FB_MSM_TVOUT_NTSC_M | ||
114 | |||
115 | config FB_MSM_TVOUT_NTSC_M | ||
116 | bool "NTSC M" | ||
117 | select FB_MSM_TVOUT_NTSC | ||
118 | ---help--- | ||
119 | Support for NTSC M region (North American and Korea) | ||
120 | |||
121 | config FB_MSM_TVOUT_NONE | ||
122 | bool "NONE" | ||
123 | ---help--- | ||
124 | This will disable TV Out functionality. | ||
125 | endchoice | ||
126 | |||
127 | config PMEM_KERNEL_SIZE | ||
128 | int "PMEM for kernel components (in MB)" | ||
129 | default 2 | ||
130 | depends on ARCH_QSD8X50 | ||
131 | help | ||
132 | Configures the amount of PMEM for use by kernel components | ||
133 | (in MB; minimum 2MB) | ||
134 | endif | ||
diff --git a/drivers/staging/msm/Makefile b/drivers/staging/msm/Makefile new file mode 100644 index 000000000000..98a0ce177cb2 --- /dev/null +++ b/drivers/staging/msm/Makefile | |||
@@ -0,0 +1,93 @@ | |||
1 | obj-y := msm_fb.o staging-devices.o memory.o | ||
2 | |||
3 | obj-$(CONFIG_FB_MSM_LOGO) += logo.o | ||
4 | obj-$(CONFIG_FB_BACKLIGHT) += msm_fb_bl.o | ||
5 | |||
6 | # MDP | ||
7 | obj-y += mdp.o | ||
8 | |||
9 | ifeq ($(CONFIG_FB_MSM_MDP40),y) | ||
10 | obj-y += mdp4_util.o | ||
11 | obj-$(CONFIG_DEBUG_FS) += mdp4_debugfs.o | ||
12 | else | ||
13 | obj-y += mdp_hw_init.o | ||
14 | obj-y += mdp_ppp.o | ||
15 | ifeq ($(CONFIG_FB_MSM_MDP31),y) | ||
16 | obj-y += mdp_ppp_v31.o | ||
17 | obj-$(CONFIG_MDP_PPP_ASYNC_OP) += mdp_ppp_dq.o | ||
18 | else | ||
19 | obj-y += mdp_ppp_v20.o | ||
20 | endif | ||
21 | endif | ||
22 | |||
23 | ifeq ($(CONFIG_FB_MSM_OVERLAY),y) | ||
24 | obj-y += mdp4_overlay.o | ||
25 | obj-y += mdp4_overlay_lcdc.o | ||
26 | obj-y += mdp4_overlay_mddi.o | ||
27 | else | ||
28 | obj-y += mdp_dma_lcdc.o | ||
29 | endif | ||
30 | |||
31 | obj-y += mdp_dma.o | ||
32 | obj-y += mdp_dma_s.o | ||
33 | obj-y += mdp_vsync.o | ||
34 | obj-y += mdp_cursor.o | ||
35 | obj-y += mdp_dma_tv.o | ||
36 | |||
37 | # EBI2 | ||
38 | obj-$(CONFIG_FB_MSM_EBI2) += ebi2_lcd.o | ||
39 | |||
40 | # LCDC | ||
41 | obj-$(CONFIG_FB_MSM_LCDC) += lcdc.o | ||
42 | |||
43 | # MDDI | ||
44 | msm_mddi-objs := mddi.o mddihost.o mddihosti.o | ||
45 | obj-$(CONFIG_FB_MSM_MDDI) += msm_mddi.o | ||
46 | |||
47 | # External MDDI | ||
48 | msm_mddi_ext-objs := mddihost_e.o mddi_ext.o | ||
49 | obj-$(CONFIG_FB_MSM_EXTMDDI) += msm_mddi_ext.o | ||
50 | |||
51 | # TVEnc | ||
52 | obj-$(CONFIG_FB_MSM_TVOUT) += tvenc.o | ||
53 | |||
54 | # MSM FB Panel | ||
55 | obj-y += msm_fb_panel.o | ||
56 | obj-$(CONFIG_FB_MSM_EBI2_TMD_QVGA_EPSON_QCIF) += ebi2_tmd20.o | ||
57 | obj-$(CONFIG_FB_MSM_EBI2_TMD_QVGA_EPSON_QCIF) += ebi2_l2f.o | ||
58 | |||
59 | ifeq ($(CONFIG_FB_MSM_MDDI_AUTO_DETECT),y) | ||
60 | obj-y += mddi_prism.o | ||
61 | obj-y += mddi_toshiba.o | ||
62 | obj-y += mddi_toshiba_vga.o | ||
63 | obj-y += mddi_toshiba_wvga_pt.o | ||
64 | obj-y += mddi_toshiba_wvga.o | ||
65 | obj-y += mddi_sharp.o | ||
66 | else | ||
67 | obj-$(CONFIG_FB_MSM_MDDI_PRISM_WVGA) += mddi_prism.o | ||
68 | obj-$(CONFIG_FB_MSM_MDDI_TOSHIBA_COMMON) += mddi_toshiba.o | ||
69 | obj-$(CONFIG_FB_MSM_MDDI_TOSHIBA_COMMON_VGA) += mddi_toshiba_vga.o | ||
70 | obj-$(CONFIG_FB_MSM_MDDI_TOSHIBA_WVGA_PORTRAIT) += mddi_toshiba_wvga_pt.o | ||
71 | obj-$(CONFIG_FB_MSM_MDDI_TOSHIBA_WVGA) += mddi_toshiba_wvga.o | ||
72 | obj-$(CONFIG_FB_MSM_MDDI_SHARP_QVGA_128x128) += mddi_sharp.o | ||
73 | endif | ||
74 | |||
75 | obj-$(CONFIG_FB_MSM_LCDC_PANEL) += lcdc_panel.o | ||
76 | obj-$(CONFIG_FB_MSM_LCDC_PRISM_WVGA) += lcdc_prism.o | ||
77 | obj-$(CONFIG_FB_MSM_LCDC_EXTERNAL_WXGA) += lcdc_external.o | ||
78 | obj-$(CONFIG_FB_MSM_LCDC_GORDON_VGA) += lcdc_gordon.o | ||
79 | obj-$(CONFIG_FB_MSM_LCDC_WXGA) += lcdc_wxga.o | ||
80 | obj-$(CONFIG_FB_MSM_LCDC_TOSHIBA_WVGA_PT) += lcdc_toshiba_wvga_pt.o | ||
81 | obj-$(CONFIG_FB_MSM_LCDC_SHARP_WVGA_PT) += lcdc_sharp_wvga_pt.o | ||
82 | obj-$(CONFIG_FB_MSM_LCDC_GRAPEFRUIT_VGA) += lcdc_grapefruit.o | ||
83 | obj-$(CONFIG_FB_MSM_LCDC_ST1_WXGA) += lcdc_st1_wxga.o | ||
84 | obj-$(CONFIG_FB_MSM_LCDC_ST15_WXGA) += lcdc_st15.o | ||
85 | obj-$(CONFIG_FB_MSM_HDMI_SII_EXTERNAL_720P) += hdmi_sii9022.o | ||
86 | |||
87 | obj-$(CONFIG_FB_MSM_TVOUT_NTSC) += tv_ntsc.o | ||
88 | obj-$(CONFIG_FB_MSM_TVOUT_PAL) += tv_pal.o | ||
89 | |||
90 | obj-$(CONFIG_FB_MSM_EXTMDDI_SVGA) += mddi_ext_lcd.o | ||
91 | |||
92 | clean: | ||
93 | rm *.o .*cmd | ||
diff --git a/drivers/staging/msm/TODO b/drivers/staging/msm/TODO new file mode 100644 index 000000000000..05107a7d516a --- /dev/null +++ b/drivers/staging/msm/TODO | |||
@@ -0,0 +1,3 @@ | |||
1 | - Merge this code with the existing MSM framebuffer | ||
2 | - General style clean ups. | ||
3 | |||
diff --git a/drivers/staging/msm/ebi2_l2f.c b/drivers/staging/msm/ebi2_l2f.c new file mode 100644 index 000000000000..eea891d8f0f8 --- /dev/null +++ b/drivers/staging/msm/ebi2_l2f.c | |||
@@ -0,0 +1,569 @@ | |||
1 | /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include "msm_fb.h" | ||
19 | |||
20 | #include <linux/memory.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/sched.h> | ||
23 | #include <linux/time.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/interrupt.h> | ||
26 | #include "linux/proc_fs.h" | ||
27 | |||
28 | #include <linux/delay.h> | ||
29 | |||
30 | #include <mach/hardware.h> | ||
31 | #include <linux/io.h> | ||
32 | |||
33 | #include <asm/system.h> | ||
34 | #include <asm/mach-types.h> | ||
35 | |||
36 | /* The following are for MSM5100 on Gator | ||
37 | */ | ||
38 | #ifdef FEATURE_PM1000 | ||
39 | #include "pm1000.h" | ||
40 | #endif /* FEATURE_PM1000 */ | ||
41 | /* The following are for MSM6050 on Bambi | ||
42 | */ | ||
43 | #ifdef FEATURE_PMIC_LCDKBD_LED_DRIVER | ||
44 | #include "pm.h" | ||
45 | #endif /* FEATURE_PMIC_LCDKBD_LED_DRIVER */ | ||
46 | |||
47 | #ifdef DISP_DEVICE_18BPP | ||
48 | #undef DISP_DEVICE_18BPP | ||
49 | #define DISP_DEVICE_16BPP | ||
50 | #endif | ||
51 | |||
52 | #define QCIF_WIDTH 176 | ||
53 | #define QCIF_HEIGHT 220 | ||
54 | |||
55 | static void *DISP_CMD_PORT; | ||
56 | static void *DISP_DATA_PORT; | ||
57 | |||
58 | #define DISP_CMD_DISON 0xaf | ||
59 | #define DISP_CMD_DISOFF 0xae | ||
60 | #define DISP_CMD_DISNOR 0xa6 | ||
61 | #define DISP_CMD_DISINV 0xa7 | ||
62 | #define DISP_CMD_DISCTL 0xca | ||
63 | #define DISP_CMD_GCP64 0xcb | ||
64 | #define DISP_CMD_GCP16 0xcc | ||
65 | #define DISP_CMD_GSSET 0xcd | ||
66 | #define DISP_GS_2 0x02 | ||
67 | #define DISP_GS_16 0x01 | ||
68 | #define DISP_GS_64 0x00 | ||
69 | #define DISP_CMD_SLPIN 0x95 | ||
70 | #define DISP_CMD_SLPOUT 0x94 | ||
71 | #define DISP_CMD_SD_PSET 0x75 | ||
72 | #define DISP_CMD_MD_PSET 0x76 | ||
73 | #define DISP_CMD_SD_CSET 0x15 | ||
74 | #define DISP_CMD_MD_CSET 0x16 | ||
75 | #define DISP_CMD_DATCTL 0xbc | ||
76 | #define DISP_DATCTL_666 0x08 | ||
77 | #define DISP_DATCTL_565 0x28 | ||
78 | #define DISP_DATCTL_444 0x38 | ||
79 | #define DISP_CMD_RAMWR 0x5c | ||
80 | #define DISP_CMD_RAMRD 0x5d | ||
81 | #define DISP_CMD_PTLIN 0xa8 | ||
82 | #define DISP_CMD_PTLOUT 0xa9 | ||
83 | #define DISP_CMD_ASCSET 0xaa | ||
84 | #define DISP_CMD_SCSTART 0xab | ||
85 | #define DISP_CMD_VOLCTL 0xc6 | ||
86 | #define DISP_VOLCTL_TONE 0x80 | ||
87 | #define DISP_CMD_NOp 0x25 | ||
88 | #define DISP_CMD_OSSEL 0xd0 | ||
89 | #define DISP_CMD_3500KSET 0xd1 | ||
90 | #define DISP_CMD_3500KEND 0xd2 | ||
91 | #define DISP_CMD_14MSET 0xd3 | ||
92 | #define DISP_CMD_14MEND 0xd4 | ||
93 | |||
94 | #define DISP_CMD_OUT(cmd) outpw(DISP_CMD_PORT, cmd); | ||
95 | |||
96 | #define DISP_DATA_OUT(data) outpw(DISP_DATA_PORT, data); | ||
97 | |||
98 | #define DISP_DATA_IN() inpw(DISP_DATA_PORT); | ||
99 | |||
100 | /* Epson device column number starts at 2 | ||
101 | */ | ||
102 | #define DISP_SET_RECT(ulhc_row, lrhc_row, ulhc_col, lrhc_col) \ | ||
103 | DISP_CMD_OUT(DISP_CMD_SD_PSET) \ | ||
104 | DISP_DATA_OUT((ulhc_row) & 0xFF) \ | ||
105 | DISP_DATA_OUT((ulhc_row) >> 8) \ | ||
106 | DISP_DATA_OUT((lrhc_row) & 0xFF) \ | ||
107 | DISP_DATA_OUT((lrhc_row) >> 8) \ | ||
108 | DISP_CMD_OUT(DISP_CMD_SD_CSET) \ | ||
109 | DISP_DATA_OUT(((ulhc_col)+2) & 0xFF) \ | ||
110 | DISP_DATA_OUT(((ulhc_col)+2) >> 8) \ | ||
111 | DISP_DATA_OUT(((lrhc_col)+2) & 0xFF) \ | ||
112 | DISP_DATA_OUT(((lrhc_col)+2) >> 8) | ||
113 | |||
114 | #define DISP_MIN_CONTRAST 0 | ||
115 | #define DISP_MAX_CONTRAST 127 | ||
116 | #define DISP_DEFAULT_CONTRAST 80 | ||
117 | |||
118 | #define DISP_MIN_BACKLIGHT 0 | ||
119 | #define DISP_MAX_BACKLIGHT 15 | ||
120 | #define DISP_DEFAULT_BACKLIGHT 2 | ||
121 | |||
122 | #define WAIT_SEC(sec) mdelay((sec)/1000) | ||
123 | |||
124 | static word disp_area_start_row; | ||
125 | static word disp_area_end_row; | ||
126 | static byte disp_contrast = DISP_DEFAULT_CONTRAST; | ||
127 | static boolean disp_powered_up; | ||
128 | static boolean disp_initialized = FALSE; | ||
129 | /* For some reason the contrast set at init time is not good. Need to do | ||
130 | * it again | ||
131 | */ | ||
132 | static boolean display_on = FALSE; | ||
133 | static void epsonQcif_disp_init(struct platform_device *pdev); | ||
134 | static void epsonQcif_disp_set_contrast(word contrast); | ||
135 | static void epsonQcif_disp_set_display_area(word start_row, word end_row); | ||
136 | static int epsonQcif_disp_off(struct platform_device *pdev); | ||
137 | static int epsonQcif_disp_on(struct platform_device *pdev); | ||
138 | static void epsonQcif_disp_set_rect(int x, int y, int xres, int yres); | ||
139 | |||
140 | volatile word databack; | ||
141 | static void epsonQcif_disp_init(struct platform_device *pdev) | ||
142 | { | ||
143 | struct msm_fb_data_type *mfd; | ||
144 | |||
145 | int i; | ||
146 | |||
147 | if (disp_initialized) | ||
148 | return; | ||
149 | |||
150 | mfd = platform_get_drvdata(pdev); | ||
151 | |||
152 | DISP_CMD_PORT = mfd->cmd_port; | ||
153 | DISP_DATA_PORT = mfd->data_port; | ||
154 | |||
155 | /* Sleep in */ | ||
156 | DISP_CMD_OUT(DISP_CMD_SLPIN); | ||
157 | |||
158 | /* Display off */ | ||
159 | DISP_CMD_OUT(DISP_CMD_DISOFF); | ||
160 | |||
161 | /* Display normal */ | ||
162 | DISP_CMD_OUT(DISP_CMD_DISNOR); | ||
163 | |||
164 | /* Set data mode */ | ||
165 | DISP_CMD_OUT(DISP_CMD_DATCTL); | ||
166 | DISP_DATA_OUT(DISP_DATCTL_565); | ||
167 | |||
168 | /* Set display timing */ | ||
169 | DISP_CMD_OUT(DISP_CMD_DISCTL); | ||
170 | DISP_DATA_OUT(0x1c); /* p1 */ | ||
171 | DISP_DATA_OUT(0x02); /* p1 */ | ||
172 | DISP_DATA_OUT(0x82); /* p2 */ | ||
173 | DISP_DATA_OUT(0x00); /* p3 */ | ||
174 | DISP_DATA_OUT(0x00); /* p4 */ | ||
175 | DISP_DATA_OUT(0xe0); /* p5 */ | ||
176 | DISP_DATA_OUT(0x00); /* p5 */ | ||
177 | DISP_DATA_OUT(0xdc); /* p6 */ | ||
178 | DISP_DATA_OUT(0x00); /* p6 */ | ||
179 | DISP_DATA_OUT(0x02); /* p7 */ | ||
180 | DISP_DATA_OUT(0x00); /* p8 */ | ||
181 | |||
182 | /* Set 64 gray scale level */ | ||
183 | DISP_CMD_OUT(DISP_CMD_GCP64); | ||
184 | DISP_DATA_OUT(0x08); /* p01 */ | ||
185 | DISP_DATA_OUT(0x00); | ||
186 | DISP_DATA_OUT(0x2a); /* p02 */ | ||
187 | DISP_DATA_OUT(0x00); | ||
188 | DISP_DATA_OUT(0x4e); /* p03 */ | ||
189 | DISP_DATA_OUT(0x00); | ||
190 | DISP_DATA_OUT(0x6b); /* p04 */ | ||
191 | DISP_DATA_OUT(0x00); | ||
192 | DISP_DATA_OUT(0x88); /* p05 */ | ||
193 | DISP_DATA_OUT(0x00); | ||
194 | DISP_DATA_OUT(0xa3); /* p06 */ | ||
195 | DISP_DATA_OUT(0x00); | ||
196 | DISP_DATA_OUT(0xba); /* p07 */ | ||
197 | DISP_DATA_OUT(0x00); | ||
198 | DISP_DATA_OUT(0xd1); /* p08 */ | ||
199 | DISP_DATA_OUT(0x00); | ||
200 | DISP_DATA_OUT(0xe5); /* p09 */ | ||
201 | DISP_DATA_OUT(0x00); | ||
202 | DISP_DATA_OUT(0xf3); /* p10 */ | ||
203 | DISP_DATA_OUT(0x00); | ||
204 | DISP_DATA_OUT(0x03); /* p11 */ | ||
205 | DISP_DATA_OUT(0x01); | ||
206 | DISP_DATA_OUT(0x13); /* p12 */ | ||
207 | DISP_DATA_OUT(0x01); | ||
208 | DISP_DATA_OUT(0x22); /* p13 */ | ||
209 | DISP_DATA_OUT(0x01); | ||
210 | DISP_DATA_OUT(0x2f); /* p14 */ | ||
211 | DISP_DATA_OUT(0x01); | ||
212 | DISP_DATA_OUT(0x3b); /* p15 */ | ||
213 | DISP_DATA_OUT(0x01); | ||
214 | DISP_DATA_OUT(0x46); /* p16 */ | ||
215 | DISP_DATA_OUT(0x01); | ||
216 | DISP_DATA_OUT(0x51); /* p17 */ | ||
217 | DISP_DATA_OUT(0x01); | ||
218 | DISP_DATA_OUT(0x5b); /* p18 */ | ||
219 | DISP_DATA_OUT(0x01); | ||
220 | DISP_DATA_OUT(0x64); /* p19 */ | ||
221 | DISP_DATA_OUT(0x01); | ||
222 | DISP_DATA_OUT(0x6c); /* p20 */ | ||
223 | DISP_DATA_OUT(0x01); | ||
224 | DISP_DATA_OUT(0x74); /* p21 */ | ||
225 | DISP_DATA_OUT(0x01); | ||
226 | DISP_DATA_OUT(0x7c); /* p22 */ | ||
227 | DISP_DATA_OUT(0x01); | ||
228 | DISP_DATA_OUT(0x83); /* p23 */ | ||
229 | DISP_DATA_OUT(0x01); | ||
230 | DISP_DATA_OUT(0x8a); /* p24 */ | ||
231 | DISP_DATA_OUT(0x01); | ||
232 | DISP_DATA_OUT(0x91); /* p25 */ | ||
233 | DISP_DATA_OUT(0x01); | ||
234 | DISP_DATA_OUT(0x98); /* p26 */ | ||
235 | DISP_DATA_OUT(0x01); | ||
236 | DISP_DATA_OUT(0x9f); /* p27 */ | ||
237 | DISP_DATA_OUT(0x01); | ||
238 | DISP_DATA_OUT(0xa6); /* p28 */ | ||
239 | DISP_DATA_OUT(0x01); | ||
240 | DISP_DATA_OUT(0xac); /* p29 */ | ||
241 | DISP_DATA_OUT(0x01); | ||
242 | DISP_DATA_OUT(0xb2); /* p30 */ | ||
243 | DISP_DATA_OUT(0x01); | ||
244 | DISP_DATA_OUT(0xb7); /* p31 */ | ||
245 | DISP_DATA_OUT(0x01); | ||
246 | DISP_DATA_OUT(0xbc); /* p32 */ | ||
247 | DISP_DATA_OUT(0x01); | ||
248 | DISP_DATA_OUT(0xc1); /* p33 */ | ||
249 | DISP_DATA_OUT(0x01); | ||
250 | DISP_DATA_OUT(0xc6); /* p34 */ | ||
251 | DISP_DATA_OUT(0x01); | ||
252 | DISP_DATA_OUT(0xcb); /* p35 */ | ||
253 | DISP_DATA_OUT(0x01); | ||
254 | DISP_DATA_OUT(0xd0); /* p36 */ | ||
255 | DISP_DATA_OUT(0x01); | ||
256 | DISP_DATA_OUT(0xd4); /* p37 */ | ||
257 | DISP_DATA_OUT(0x01); | ||
258 | DISP_DATA_OUT(0xd8); /* p38 */ | ||
259 | DISP_DATA_OUT(0x01); | ||
260 | DISP_DATA_OUT(0xdc); /* p39 */ | ||
261 | DISP_DATA_OUT(0x01); | ||
262 | DISP_DATA_OUT(0xe0); /* p40 */ | ||
263 | DISP_DATA_OUT(0x01); | ||
264 | DISP_DATA_OUT(0xe4); /* p41 */ | ||
265 | DISP_DATA_OUT(0x01); | ||
266 | DISP_DATA_OUT(0xe8); /* p42 */ | ||
267 | DISP_DATA_OUT(0x01); | ||
268 | DISP_DATA_OUT(0xec); /* p43 */ | ||
269 | DISP_DATA_OUT(0x01); | ||
270 | DISP_DATA_OUT(0xf0); /* p44 */ | ||
271 | DISP_DATA_OUT(0x01); | ||
272 | DISP_DATA_OUT(0xf4); /* p45 */ | ||
273 | DISP_DATA_OUT(0x01); | ||
274 | DISP_DATA_OUT(0xf8); /* p46 */ | ||
275 | DISP_DATA_OUT(0x01); | ||
276 | DISP_DATA_OUT(0xfb); /* p47 */ | ||
277 | DISP_DATA_OUT(0x01); | ||
278 | DISP_DATA_OUT(0xfe); /* p48 */ | ||
279 | DISP_DATA_OUT(0x01); | ||
280 | DISP_DATA_OUT(0x01); /* p49 */ | ||
281 | DISP_DATA_OUT(0x02); | ||
282 | DISP_DATA_OUT(0x03); /* p50 */ | ||
283 | DISP_DATA_OUT(0x02); | ||
284 | DISP_DATA_OUT(0x05); /* p51 */ | ||
285 | DISP_DATA_OUT(0x02); | ||
286 | DISP_DATA_OUT(0x07); /* p52 */ | ||
287 | DISP_DATA_OUT(0x02); | ||
288 | DISP_DATA_OUT(0x09); /* p53 */ | ||
289 | DISP_DATA_OUT(0x02); | ||
290 | DISP_DATA_OUT(0x0b); /* p54 */ | ||
291 | DISP_DATA_OUT(0x02); | ||
292 | DISP_DATA_OUT(0x0d); /* p55 */ | ||
293 | DISP_DATA_OUT(0x02); | ||
294 | DISP_DATA_OUT(0x0f); /* p56 */ | ||
295 | DISP_DATA_OUT(0x02); | ||
296 | DISP_DATA_OUT(0x11); /* p57 */ | ||
297 | DISP_DATA_OUT(0x02); | ||
298 | DISP_DATA_OUT(0x13); /* p58 */ | ||
299 | DISP_DATA_OUT(0x02); | ||
300 | DISP_DATA_OUT(0x15); /* p59 */ | ||
301 | DISP_DATA_OUT(0x02); | ||
302 | DISP_DATA_OUT(0x17); /* p60 */ | ||
303 | DISP_DATA_OUT(0x02); | ||
304 | DISP_DATA_OUT(0x19); /* p61 */ | ||
305 | DISP_DATA_OUT(0x02); | ||
306 | DISP_DATA_OUT(0x1b); /* p62 */ | ||
307 | DISP_DATA_OUT(0x02); | ||
308 | DISP_DATA_OUT(0x1c); /* p63 */ | ||
309 | DISP_DATA_OUT(0x02); | ||
310 | |||
311 | /* Set 16 gray scale level */ | ||
312 | DISP_CMD_OUT(DISP_CMD_GCP16); | ||
313 | DISP_DATA_OUT(0x1a); /* p01 */ | ||
314 | DISP_DATA_OUT(0x32); /* p02 */ | ||
315 | DISP_DATA_OUT(0x42); /* p03 */ | ||
316 | DISP_DATA_OUT(0x4c); /* p04 */ | ||
317 | DISP_DATA_OUT(0x58); /* p05 */ | ||
318 | DISP_DATA_OUT(0x5f); /* p06 */ | ||
319 | DISP_DATA_OUT(0x66); /* p07 */ | ||
320 | DISP_DATA_OUT(0x6b); /* p08 */ | ||
321 | DISP_DATA_OUT(0x70); /* p09 */ | ||
322 | DISP_DATA_OUT(0x74); /* p10 */ | ||
323 | DISP_DATA_OUT(0x78); /* p11 */ | ||
324 | DISP_DATA_OUT(0x7b); /* p12 */ | ||
325 | DISP_DATA_OUT(0x7e); /* p13 */ | ||
326 | DISP_DATA_OUT(0x80); /* p14 */ | ||
327 | DISP_DATA_OUT(0x82); /* p15 */ | ||
328 | |||
329 | /* Set DSP column */ | ||
330 | DISP_CMD_OUT(DISP_CMD_MD_CSET); | ||
331 | DISP_DATA_OUT(0xff); | ||
332 | DISP_DATA_OUT(0x03); | ||
333 | DISP_DATA_OUT(0xff); | ||
334 | DISP_DATA_OUT(0x03); | ||
335 | |||
336 | /* Set DSP page */ | ||
337 | DISP_CMD_OUT(DISP_CMD_MD_PSET); | ||
338 | DISP_DATA_OUT(0xff); | ||
339 | DISP_DATA_OUT(0x01); | ||
340 | DISP_DATA_OUT(0xff); | ||
341 | DISP_DATA_OUT(0x01); | ||
342 | |||
343 | /* Set ARM column */ | ||
344 | DISP_CMD_OUT(DISP_CMD_SD_CSET); | ||
345 | DISP_DATA_OUT(0x02); | ||
346 | DISP_DATA_OUT(0x00); | ||
347 | DISP_DATA_OUT((QCIF_WIDTH + 1) & 0xFF); | ||
348 | DISP_DATA_OUT((QCIF_WIDTH + 1) >> 8); | ||
349 | |||
350 | /* Set ARM page */ | ||
351 | DISP_CMD_OUT(DISP_CMD_SD_PSET); | ||
352 | DISP_DATA_OUT(0x00); | ||
353 | DISP_DATA_OUT(0x00); | ||
354 | DISP_DATA_OUT((QCIF_HEIGHT - 1) & 0xFF); | ||
355 | DISP_DATA_OUT((QCIF_HEIGHT - 1) >> 8); | ||
356 | |||
357 | /* Set 64 gray scales */ | ||
358 | DISP_CMD_OUT(DISP_CMD_GSSET); | ||
359 | DISP_DATA_OUT(DISP_GS_64); | ||
360 | |||
361 | DISP_CMD_OUT(DISP_CMD_OSSEL); | ||
362 | DISP_DATA_OUT(0); | ||
363 | |||
364 | /* Sleep out */ | ||
365 | DISP_CMD_OUT(DISP_CMD_SLPOUT); | ||
366 | |||
367 | WAIT_SEC(40000); | ||
368 | |||
369 | /* Initialize power IC */ | ||
370 | DISP_CMD_OUT(DISP_CMD_VOLCTL); | ||
371 | DISP_DATA_OUT(DISP_VOLCTL_TONE); | ||
372 | |||
373 | WAIT_SEC(40000); | ||
374 | |||
375 | /* Set electronic volume, d'xx */ | ||
376 | DISP_CMD_OUT(DISP_CMD_VOLCTL); | ||
377 | DISP_DATA_OUT(DISP_DEFAULT_CONTRAST); /* value from 0 to 127 */ | ||
378 | |||
379 | /* Initialize display data */ | ||
380 | DISP_SET_RECT(0, (QCIF_HEIGHT - 1), 0, (QCIF_WIDTH - 1)); | ||
381 | DISP_CMD_OUT(DISP_CMD_RAMWR); | ||
382 | for (i = 0; i < QCIF_HEIGHT * QCIF_WIDTH; i++) | ||
383 | DISP_DATA_OUT(0xffff); | ||
384 | |||
385 | DISP_CMD_OUT(DISP_CMD_RAMRD); | ||
386 | databack = DISP_DATA_IN(); | ||
387 | databack = DISP_DATA_IN(); | ||
388 | databack = DISP_DATA_IN(); | ||
389 | databack = DISP_DATA_IN(); | ||
390 | |||
391 | WAIT_SEC(80000); | ||
392 | |||
393 | DISP_CMD_OUT(DISP_CMD_DISON); | ||
394 | |||
395 | disp_area_start_row = 0; | ||
396 | disp_area_end_row = QCIF_HEIGHT - 1; | ||
397 | disp_powered_up = TRUE; | ||
398 | disp_initialized = TRUE; | ||
399 | epsonQcif_disp_set_display_area(0, QCIF_HEIGHT - 1); | ||
400 | display_on = TRUE; | ||
401 | } | ||
402 | |||
403 | static void epsonQcif_disp_set_rect(int x, int y, int xres, int yres) | ||
404 | { | ||
405 | if (!disp_initialized) | ||
406 | return; | ||
407 | |||
408 | DISP_SET_RECT(y, y + yres - 1, x, x + xres - 1); | ||
409 | DISP_CMD_OUT(DISP_CMD_RAMWR); | ||
410 | } | ||
411 | |||
412 | static void epsonQcif_disp_set_display_area(word start_row, word end_row) | ||
413 | { | ||
414 | if (!disp_initialized) | ||
415 | return; | ||
416 | |||
417 | if ((start_row == disp_area_start_row) | ||
418 | && (end_row == disp_area_end_row)) | ||
419 | return; | ||
420 | disp_area_start_row = start_row; | ||
421 | disp_area_end_row = end_row; | ||
422 | |||
423 | /* Range checking | ||
424 | */ | ||
425 | if (end_row >= QCIF_HEIGHT) | ||
426 | end_row = QCIF_HEIGHT - 1; | ||
427 | if (start_row > end_row) | ||
428 | start_row = end_row; | ||
429 | |||
430 | /* When display is not the full screen, gray scale is set to | ||
431 | ** 2; otherwise it is set to 64. | ||
432 | */ | ||
433 | if ((start_row == 0) && (end_row == (QCIF_HEIGHT - 1))) { | ||
434 | /* The whole screen */ | ||
435 | DISP_CMD_OUT(DISP_CMD_PTLOUT); | ||
436 | WAIT_SEC(10000); | ||
437 | DISP_CMD_OUT(DISP_CMD_DISOFF); | ||
438 | WAIT_SEC(100000); | ||
439 | DISP_CMD_OUT(DISP_CMD_GSSET); | ||
440 | DISP_DATA_OUT(DISP_GS_64); | ||
441 | WAIT_SEC(100000); | ||
442 | DISP_CMD_OUT(DISP_CMD_DISON); | ||
443 | } else { | ||
444 | /* partial screen */ | ||
445 | DISP_CMD_OUT(DISP_CMD_PTLIN); | ||
446 | DISP_DATA_OUT(start_row); | ||
447 | DISP_DATA_OUT(start_row >> 8); | ||
448 | DISP_DATA_OUT(end_row); | ||
449 | DISP_DATA_OUT(end_row >> 8); | ||
450 | DISP_CMD_OUT(DISP_CMD_GSSET); | ||
451 | DISP_DATA_OUT(DISP_GS_2); | ||
452 | } | ||
453 | } | ||
454 | |||
455 | static int epsonQcif_disp_off(struct platform_device *pdev) | ||
456 | { | ||
457 | if (!disp_initialized) | ||
458 | epsonQcif_disp_init(pdev); | ||
459 | |||
460 | if (display_on) { | ||
461 | DISP_CMD_OUT(DISP_CMD_DISOFF); | ||
462 | DISP_CMD_OUT(DISP_CMD_SLPIN); | ||
463 | display_on = FALSE; | ||
464 | } | ||
465 | |||
466 | return 0; | ||
467 | } | ||
468 | |||
469 | static int epsonQcif_disp_on(struct platform_device *pdev) | ||
470 | { | ||
471 | if (!disp_initialized) | ||
472 | epsonQcif_disp_init(pdev); | ||
473 | |||
474 | if (!display_on) { | ||
475 | DISP_CMD_OUT(DISP_CMD_SLPOUT); | ||
476 | WAIT_SEC(40000); | ||
477 | DISP_CMD_OUT(DISP_CMD_DISON); | ||
478 | epsonQcif_disp_set_contrast(disp_contrast); | ||
479 | display_on = TRUE; | ||
480 | } | ||
481 | |||
482 | return 0; | ||
483 | } | ||
484 | |||
485 | static void epsonQcif_disp_set_contrast(word contrast) | ||
486 | { | ||
487 | if (!disp_initialized) | ||
488 | return; | ||
489 | |||
490 | /* Initialize power IC, d'24 */ | ||
491 | DISP_CMD_OUT(DISP_CMD_VOLCTL); | ||
492 | DISP_DATA_OUT(DISP_VOLCTL_TONE); | ||
493 | |||
494 | WAIT_SEC(40000); | ||
495 | |||
496 | /* Set electronic volume, d'xx */ | ||
497 | DISP_CMD_OUT(DISP_CMD_VOLCTL); | ||
498 | if (contrast > 127) | ||
499 | contrast = 127; | ||
500 | DISP_DATA_OUT(contrast); /* value from 0 to 127 */ | ||
501 | disp_contrast = (byte) contrast; | ||
502 | } /* End disp_set_contrast */ | ||
503 | |||
504 | static void epsonQcif_disp_clear_screen_area( | ||
505 | word start_row, word end_row, word start_column, word end_column) { | ||
506 | int32 i; | ||
507 | |||
508 | /* Clear the display screen */ | ||
509 | DISP_SET_RECT(start_row, end_row, start_column, end_column); | ||
510 | DISP_CMD_OUT(DISP_CMD_RAMWR); | ||
511 | i = (end_row - start_row + 1) * (end_column - start_column + 1); | ||
512 | for (; i > 0; i--) | ||
513 | DISP_DATA_OUT(0xffff); | ||
514 | } | ||
515 | |||
516 | static int __init epsonQcif_probe(struct platform_device *pdev) | ||
517 | { | ||
518 | msm_fb_add_device(pdev); | ||
519 | |||
520 | return 0; | ||
521 | } | ||
522 | |||
523 | static struct platform_driver this_driver = { | ||
524 | .probe = epsonQcif_probe, | ||
525 | .driver = { | ||
526 | .name = "ebi2_epson_qcif", | ||
527 | }, | ||
528 | }; | ||
529 | |||
530 | static struct msm_fb_panel_data epsonQcif_panel_data = { | ||
531 | .on = epsonQcif_disp_on, | ||
532 | .off = epsonQcif_disp_off, | ||
533 | .set_rect = epsonQcif_disp_set_rect, | ||
534 | }; | ||
535 | |||
536 | static struct platform_device this_device = { | ||
537 | .name = "ebi2_epson_qcif", | ||
538 | .id = 0, | ||
539 | .dev = { | ||
540 | .platform_data = &epsonQcif_panel_data, | ||
541 | } | ||
542 | }; | ||
543 | |||
544 | static int __init epsonQcif_init(void) | ||
545 | { | ||
546 | int ret; | ||
547 | struct msm_panel_info *pinfo; | ||
548 | |||
549 | ret = platform_driver_register(&this_driver); | ||
550 | if (!ret) { | ||
551 | pinfo = &epsonQcif_panel_data.panel_info; | ||
552 | pinfo->xres = QCIF_WIDTH; | ||
553 | pinfo->yres = QCIF_HEIGHT; | ||
554 | pinfo->type = EBI2_PANEL; | ||
555 | pinfo->pdest = DISPLAY_2; | ||
556 | pinfo->wait_cycle = 0x808000; | ||
557 | pinfo->bpp = 16; | ||
558 | pinfo->fb_num = 2; | ||
559 | pinfo->lcd.vsync_enable = FALSE; | ||
560 | |||
561 | ret = platform_device_register(&this_device); | ||
562 | if (ret) | ||
563 | platform_driver_unregister(&this_driver); | ||
564 | } | ||
565 | |||
566 | return ret; | ||
567 | } | ||
568 | |||
569 | module_init(epsonQcif_init); | ||
diff --git a/drivers/staging/msm/ebi2_lcd.c b/drivers/staging/msm/ebi2_lcd.c new file mode 100644 index 000000000000..b41e1230ceca --- /dev/null +++ b/drivers/staging/msm/ebi2_lcd.c | |||
@@ -0,0 +1,250 @@ | |||
1 | /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/moduleparam.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <linux/mm.h> | ||
24 | #include <linux/fb.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/ioport.h> | ||
27 | #include <linux/device.h> | ||
28 | #include <linux/dma-mapping.h> | ||
29 | #include <linux/uaccess.h> | ||
30 | #include <linux/workqueue.h> | ||
31 | #include <linux/string.h> | ||
32 | #include <linux/version.h> | ||
33 | #include <linux/proc_fs.h> | ||
34 | #include <linux/vmalloc.h> | ||
35 | #include <linux/debugfs.h> | ||
36 | |||
37 | #include "msm_fb.h" | ||
38 | |||
39 | static int ebi2_lcd_probe(struct platform_device *pdev); | ||
40 | static int ebi2_lcd_remove(struct platform_device *pdev); | ||
41 | |||
42 | static struct platform_driver ebi2_lcd_driver = { | ||
43 | .probe = ebi2_lcd_probe, | ||
44 | .remove = ebi2_lcd_remove, | ||
45 | .suspend = NULL, | ||
46 | .suspend_late = NULL, | ||
47 | .resume_early = NULL, | ||
48 | .resume = NULL, | ||
49 | .shutdown = NULL, | ||
50 | .driver = { | ||
51 | .name = "ebi2_lcd", | ||
52 | }, | ||
53 | }; | ||
54 | |||
55 | static void *ebi2_base; | ||
56 | static void *ebi2_lcd_cfg0; | ||
57 | static void *ebi2_lcd_cfg1; | ||
58 | static void __iomem *lcd01_base; | ||
59 | static void __iomem *lcd02_base; | ||
60 | static int ebi2_lcd_resource_initialized; | ||
61 | |||
62 | static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST]; | ||
63 | static int pdev_list_cnt; | ||
64 | |||
65 | static int ebi2_lcd_probe(struct platform_device *pdev) | ||
66 | { | ||
67 | struct msm_fb_data_type *mfd; | ||
68 | struct platform_device *mdp_dev = NULL; | ||
69 | struct msm_fb_panel_data *pdata = NULL; | ||
70 | int rc, i; | ||
71 | |||
72 | if (pdev->id == 0) { | ||
73 | for (i = 0; i < pdev->num_resources; i++) { | ||
74 | if (!strncmp(pdev->resource[i].name, "base", 4)) { | ||
75 | ebi2_base = ioremap(pdev->resource[i].start, | ||
76 | pdev->resource[i].end - | ||
77 | pdev->resource[i].start + 1); | ||
78 | if (!ebi2_base) { | ||
79 | printk(KERN_ERR | ||
80 | "ebi2_base ioremap failed!\n"); | ||
81 | return -ENOMEM; | ||
82 | } | ||
83 | ebi2_lcd_cfg0 = (void *)(ebi2_base + 0x20); | ||
84 | ebi2_lcd_cfg1 = (void *)(ebi2_base + 0x24); | ||
85 | } else if (!strncmp(pdev->resource[i].name, | ||
86 | "lcd01", 5)) { | ||
87 | lcd01_base = ioremap(pdev->resource[i].start, | ||
88 | pdev->resource[i].end - | ||
89 | pdev->resource[i].start + 1); | ||
90 | if (!lcd01_base) { | ||
91 | printk(KERN_ERR | ||
92 | "lcd01_base ioremap failed!\n"); | ||
93 | return -ENOMEM; | ||
94 | } | ||
95 | } else if (!strncmp(pdev->resource[i].name, | ||
96 | "lcd02", 5)) { | ||
97 | lcd02_base = ioremap(pdev->resource[i].start, | ||
98 | pdev->resource[i].end - | ||
99 | pdev->resource[i].start + 1); | ||
100 | if (!lcd02_base) { | ||
101 | printk(KERN_ERR | ||
102 | "lcd02_base ioremap failed!\n"); | ||
103 | return -ENOMEM; | ||
104 | } | ||
105 | } | ||
106 | } | ||
107 | ebi2_lcd_resource_initialized = 1; | ||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | if (!ebi2_lcd_resource_initialized) | ||
112 | return -EPERM; | ||
113 | |||
114 | mfd = platform_get_drvdata(pdev); | ||
115 | |||
116 | if (!mfd) | ||
117 | return -ENODEV; | ||
118 | |||
119 | if (mfd->key != MFD_KEY) | ||
120 | return -EINVAL; | ||
121 | |||
122 | if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST) | ||
123 | return -ENOMEM; | ||
124 | |||
125 | if (ebi2_base == NULL) | ||
126 | return -ENOMEM; | ||
127 | |||
128 | mdp_dev = platform_device_alloc("mdp", pdev->id); | ||
129 | if (!mdp_dev) | ||
130 | return -ENOMEM; | ||
131 | |||
132 | /* link to the latest pdev */ | ||
133 | mfd->pdev = mdp_dev; | ||
134 | mfd->dest = DISPLAY_LCD; | ||
135 | |||
136 | /* add panel data */ | ||
137 | if (platform_device_add_data | ||
138 | (mdp_dev, pdev->dev.platform_data, | ||
139 | sizeof(struct msm_fb_panel_data))) { | ||
140 | printk(KERN_ERR "ebi2_lcd_probe: platform_device_add_data failed!\n"); | ||
141 | platform_device_put(mdp_dev); | ||
142 | return -ENOMEM; | ||
143 | } | ||
144 | |||
145 | /* data chain */ | ||
146 | pdata = mdp_dev->dev.platform_data; | ||
147 | pdata->on = panel_next_on; | ||
148 | pdata->off = panel_next_off; | ||
149 | pdata->next = pdev; | ||
150 | |||
151 | /* get/set panel specific fb info */ | ||
152 | mfd->panel_info = pdata->panel_info; | ||
153 | |||
154 | if (mfd->panel_info.bpp == 24) | ||
155 | mfd->fb_imgType = MDP_RGB_888; | ||
156 | else | ||
157 | mfd->fb_imgType = MDP_RGB_565; | ||
158 | |||
159 | /* config msm ebi2 lcd register */ | ||
160 | if (mfd->panel_info.pdest == DISPLAY_1) { | ||
161 | outp32(ebi2_base, | ||
162 | (inp32(ebi2_base) & (~(EBI2_PRIM_LCD_CLR))) | | ||
163 | EBI2_PRIM_LCD_SEL); | ||
164 | /* | ||
165 | * current design has one set of cfg0/1 register to control | ||
166 | * both EBI2 channels. so, we're using the PRIM channel to | ||
167 | * configure both. | ||
168 | */ | ||
169 | outp32(ebi2_lcd_cfg0, mfd->panel_info.wait_cycle); | ||
170 | if (mfd->panel_info.bpp == 18) | ||
171 | outp32(ebi2_lcd_cfg1, 0x01000000); | ||
172 | else | ||
173 | outp32(ebi2_lcd_cfg1, 0x0); | ||
174 | } else { | ||
175 | #ifdef DEBUG_EBI2_LCD | ||
176 | /* | ||
177 | * confliting with QCOM SURF FPGA CS. | ||
178 | * OEM should enable below for their CS mapping | ||
179 | */ | ||
180 | outp32(ebi2_base, (inp32(ebi2_base)&(~(EBI2_SECD_LCD_CLR))) | ||
181 | |EBI2_SECD_LCD_SEL); | ||
182 | #endif | ||
183 | } | ||
184 | |||
185 | /* | ||
186 | * map cs (chip select) address | ||
187 | */ | ||
188 | if (mfd->panel_info.pdest == DISPLAY_1) { | ||
189 | mfd->cmd_port = lcd01_base; | ||
190 | mfd->data_port = | ||
191 | (void *)((uint32) mfd->cmd_port + EBI2_PRIM_LCD_RS_PIN); | ||
192 | mfd->data_port_phys = | ||
193 | (void *)(LCD_PRIM_BASE_PHYS + EBI2_PRIM_LCD_RS_PIN); | ||
194 | } else { | ||
195 | mfd->cmd_port = lcd01_base; | ||
196 | mfd->data_port = | ||
197 | (void *)((uint32) mfd->cmd_port + EBI2_SECD_LCD_RS_PIN); | ||
198 | mfd->data_port_phys = | ||
199 | (void *)(LCD_SECD_BASE_PHYS + EBI2_SECD_LCD_RS_PIN); | ||
200 | } | ||
201 | |||
202 | /* | ||
203 | * set driver data | ||
204 | */ | ||
205 | platform_set_drvdata(mdp_dev, mfd); | ||
206 | |||
207 | /* | ||
208 | * register in mdp driver | ||
209 | */ | ||
210 | rc = platform_device_add(mdp_dev); | ||
211 | if (rc) { | ||
212 | goto ebi2_lcd_probe_err; | ||
213 | } | ||
214 | |||
215 | pdev_list[pdev_list_cnt++] = pdev; | ||
216 | return 0; | ||
217 | |||
218 | ebi2_lcd_probe_err: | ||
219 | platform_device_put(mdp_dev); | ||
220 | return rc; | ||
221 | } | ||
222 | |||
223 | static int ebi2_lcd_remove(struct platform_device *pdev) | ||
224 | { | ||
225 | struct msm_fb_data_type *mfd; | ||
226 | |||
227 | mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev); | ||
228 | |||
229 | if (!mfd) | ||
230 | return 0; | ||
231 | |||
232 | if (mfd->key != MFD_KEY) | ||
233 | return 0; | ||
234 | |||
235 | iounmap(mfd->cmd_port); | ||
236 | |||
237 | return 0; | ||
238 | } | ||
239 | |||
240 | static int ebi2_lcd_register_driver(void) | ||
241 | { | ||
242 | return platform_driver_register(&ebi2_lcd_driver); | ||
243 | } | ||
244 | |||
245 | static int __init ebi2_lcd_driver_init(void) | ||
246 | { | ||
247 | return ebi2_lcd_register_driver(); | ||
248 | } | ||
249 | |||
250 | module_init(ebi2_lcd_driver_init); \ No newline at end of file | ||
diff --git a/drivers/staging/msm/ebi2_tmd20.c b/drivers/staging/msm/ebi2_tmd20.c new file mode 100644 index 000000000000..d66d03978253 --- /dev/null +++ b/drivers/staging/msm/ebi2_tmd20.c | |||
@@ -0,0 +1,1122 @@ | |||
1 | /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include "msm_fb.h" | ||
19 | |||
20 | #include <linux/memory.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/sched.h> | ||
23 | #include <linux/time.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/interrupt.h> | ||
26 | #include "linux/proc_fs.h" | ||
27 | |||
28 | #include <linux/delay.h> | ||
29 | |||
30 | #include <mach/hardware.h> | ||
31 | #include <linux/io.h> | ||
32 | |||
33 | #include <asm/system.h> | ||
34 | #include <asm/mach-types.h> | ||
35 | |||
36 | /* #define TMD20QVGA_LCD_18BPP */ | ||
37 | #define QVGA_WIDTH 240 | ||
38 | #define QVGA_HEIGHT 320 | ||
39 | |||
40 | #ifdef TMD20QVGA_LCD_18BPP | ||
41 | #define DISP_QVGA_18BPP(x) ((((x)<<2) & 0x3FC00)|(( (x)<<1)& 0x1FE)) | ||
42 | #define DISP_REG(name) uint32 register_##name; | ||
43 | #define OUTPORT(x, y) outpdw(x, y) | ||
44 | #define INPORT(x) inpdw(x) | ||
45 | #else | ||
46 | #define DISP_QVGA_18BPP(x) (x) | ||
47 | #define DISP_REG(name) uint16 register_##name; | ||
48 | #define OUTPORT(x, y) outpw(x, y) | ||
49 | #define INPORT(x) intpw(x) | ||
50 | #endif | ||
51 | |||
52 | static void *DISP_CMD_PORT; | ||
53 | static void *DISP_DATA_PORT; | ||
54 | |||
55 | #define DISP_RNTI 0x10 | ||
56 | |||
57 | #define DISP_CMD_OUT(cmd) OUTPORT(DISP_CMD_PORT, DISP_QVGA_18BPP(cmd)) | ||
58 | #define DISP_DATA_OUT(data) OUTPORT(DISP_DATA_PORT, data) | ||
59 | #define DISP_DATA_IN() INPORT(DISP_DATA_PORT) | ||
60 | |||
61 | #if (defined(TMD20QVGA_LCD_18BPP)) | ||
62 | #define DISP_DATA_OUT_16TO18BPP(x) \ | ||
63 | DISP_DATA_OUT((((x)&0xf800)<<2|((x)&0x80000)>>3) \ | ||
64 | | (((x)&0x7e0)<<1) \ | ||
65 | | (((x)&0x1F)<<1|((x)&0x10)>>4)) | ||
66 | #else | ||
67 | #define DISP_DATA_OUT_16TO18BPP(x) \ | ||
68 | DISP_DATA_OUT(x) | ||
69 | #endif | ||
70 | |||
71 | #define DISP_WRITE_OUT(addr, data) \ | ||
72 | register_##addr = DISP_QVGA_18BPP(data); \ | ||
73 | DISP_CMD_OUT(addr); \ | ||
74 | DISP_DATA_OUT(register_##addr); | ||
75 | |||
76 | #define DISP_UPDATE_VALUE(addr, bitmask, data) \ | ||
77 | DISP_WRITE_OUT(##addr, (register_##addr & ~(bitmask)) | (data)); | ||
78 | |||
79 | #define DISP_VAL_IF(bitvalue, bitmask) \ | ||
80 | ((bitvalue) ? (bitmask) : 0) | ||
81 | |||
82 | /* QVGA = 256 x 320 */ | ||
83 | /* actual display is 240 x 320...offset by 0x10 */ | ||
84 | #define DISP_ROW_COL_TO_ADDR(row, col) ((row) * 0x100 + col) | ||
85 | #define DISP_SET_RECT(ulhc_row, lrhc_row, ulhc_col, lrhc_col) \ | ||
86 | { \ | ||
87 | DISP_WRITE_OUT(DISP_HORZ_RAM_ADDR_POS_1_ADDR, (ulhc_col) + tmd20qvga_panel_offset); \ | ||
88 | DISP_WRITE_OUT(DISP_HORZ_RAM_ADDR_POS_2_ADDR, (lrhc_col) + tmd20qvga_panel_offset); \ | ||
89 | DISP_WRITE_OUT(DISP_VERT_RAM_ADDR_POS_1_ADDR, (ulhc_row)); \ | ||
90 | DISP_WRITE_OUT(DISP_VERT_RAM_ADDR_POS_2_ADDR, (lrhc_row)); \ | ||
91 | DISP_WRITE_OUT(DISP_RAM_ADDR_SET_1_ADDR, (ulhc_col) + tmd20qvga_panel_offset); \ | ||
92 | DISP_WRITE_OUT(DISP_RAM_ADDR_SET_2_ADDR, (ulhc_row)); \ | ||
93 | } | ||
94 | |||
95 | #define WAIT_MSEC(msec) mdelay(msec) | ||
96 | |||
97 | /* | ||
98 | * TMD QVGA Address | ||
99 | */ | ||
100 | /* Display Control */ | ||
101 | #define DISP_START_OSCILLATION_ADDR 0x000 | ||
102 | DISP_REG(DISP_START_OSCILLATION_ADDR) | ||
103 | #define DISP_DRIVER_OUTPUT_CTL_ADDR 0x001 | ||
104 | DISP_REG(DISP_DRIVER_OUTPUT_CTL_ADDR) | ||
105 | #define DISP_LCD_DRIVING_SIG_ADDR 0x002 | ||
106 | DISP_REG(DISP_LCD_DRIVING_SIG_ADDR) | ||
107 | #define DISP_ENTRY_MODE_ADDR 0x003 | ||
108 | DISP_REG(DISP_ENTRY_MODE_ADDR) | ||
109 | #define DISP_DISPLAY_CTL_1_ADDR 0x007 | ||
110 | DISP_REG(DISP_DISPLAY_CTL_1_ADDR) | ||
111 | #define DISP_DISPLAY_CTL_2_ADDR 0x008 | ||
112 | DISP_REG(DISP_DISPLAY_CTL_2_ADDR) | ||
113 | |||
114 | /* DISPLAY MODE 0x009 partial display not supported */ | ||
115 | #define DISP_POWER_SUPPLY_INTF_ADDR 0x00A | ||
116 | DISP_REG(DISP_POWER_SUPPLY_INTF_ADDR) | ||
117 | |||
118 | /* DISPLAY MODE 0x00B xZoom feature is not supported */ | ||
119 | #define DISP_EXT_DISPLAY_CTL_1_ADDR 0x00C | ||
120 | DISP_REG(DISP_EXT_DISPLAY_CTL_1_ADDR) | ||
121 | |||
122 | #define DISP_FRAME_CYCLE_CTL_ADDR 0x00D | ||
123 | DISP_REG(DISP_FRAME_CYCLE_CTL_ADDR) | ||
124 | |||
125 | #define DISP_EXT_DISPLAY_CTL_2_ADDR 0x00E | ||
126 | DISP_REG(DISP_EXT_DISPLAY_CTL_2_ADDR) | ||
127 | |||
128 | #define DISP_EXT_DISPLAY_CTL_3_ADDR 0x00F | ||
129 | DISP_REG(DISP_EXT_DISPLAY_CTL_3_ADDR) | ||
130 | |||
131 | #define DISP_LTPS_CTL_1_ADDR 0x012 | ||
132 | DISP_REG(DISP_LTPS_CTL_1_ADDR) | ||
133 | #define DISP_LTPS_CTL_2_ADDR 0x013 | ||
134 | DISP_REG(DISP_LTPS_CTL_2_ADDR) | ||
135 | #define DISP_LTPS_CTL_3_ADDR 0x014 | ||
136 | DISP_REG(DISP_LTPS_CTL_3_ADDR) | ||
137 | #define DISP_LTPS_CTL_4_ADDR 0x018 | ||
138 | DISP_REG(DISP_LTPS_CTL_4_ADDR) | ||
139 | #define DISP_LTPS_CTL_5_ADDR 0x019 | ||
140 | DISP_REG(DISP_LTPS_CTL_5_ADDR) | ||
141 | #define DISP_LTPS_CTL_6_ADDR 0x01A | ||
142 | DISP_REG(DISP_LTPS_CTL_6_ADDR) | ||
143 | #define DISP_AMP_SETTING_ADDR 0x01C | ||
144 | DISP_REG(DISP_AMP_SETTING_ADDR) | ||
145 | #define DISP_MODE_SETTING_ADDR 0x01D | ||
146 | DISP_REG(DISP_MODE_SETTING_ADDR) | ||
147 | #define DISP_POFF_LN_SETTING_ADDR 0x01E | ||
148 | DISP_REG(DISP_POFF_LN_SETTING_ADDR) | ||
149 | /* Power Contol */ | ||
150 | #define DISP_POWER_CTL_1_ADDR 0x100 | ||
151 | DISP_REG(DISP_POWER_CTL_1_ADDR) | ||
152 | #define DISP_POWER_CTL_2_ADDR 0x101 | ||
153 | DISP_REG(DISP_POWER_CTL_2_ADDR) | ||
154 | #define DISP_POWER_CTL_3_ADDR 0x102 | ||
155 | DISP_REG(DISP_POWER_CTL_3_ADDR) | ||
156 | #define DISP_POWER_CTL_4_ADDR 0x103 | ||
157 | DISP_REG(DISP_POWER_CTL_4_ADDR) | ||
158 | #define DISP_POWER_CTL_5_ADDR 0x104 | ||
159 | DISP_REG(DISP_POWER_CTL_5_ADDR) | ||
160 | #define DISP_POWER_CTL_6_ADDR 0x105 | ||
161 | DISP_REG(DISP_POWER_CTL_6_ADDR) | ||
162 | #define DISP_POWER_CTL_7_ADDR 0x106 | ||
163 | DISP_REG(DISP_POWER_CTL_7_ADDR) | ||
164 | /* RAM Access */ | ||
165 | #define DISP_RAM_ADDR_SET_1_ADDR 0x200 | ||
166 | DISP_REG(DISP_RAM_ADDR_SET_1_ADDR) | ||
167 | #define DISP_RAM_ADDR_SET_2_ADDR 0x201 | ||
168 | DISP_REG(DISP_RAM_ADDR_SET_2_ADDR) | ||
169 | #define DISP_CMD_RAMRD DISP_CMD_RAMWR | ||
170 | #define DISP_CMD_RAMWR 0x202 | ||
171 | DISP_REG(DISP_CMD_RAMWR) | ||
172 | #define DISP_RAM_DATA_MASK_1_ADDR 0x203 | ||
173 | DISP_REG(DISP_RAM_DATA_MASK_1_ADDR) | ||
174 | #define DISP_RAM_DATA_MASK_2_ADDR 0x204 | ||
175 | DISP_REG(DISP_RAM_DATA_MASK_2_ADDR) | ||
176 | /* Gamma Control, Contrast, Gray Scale Setting */ | ||
177 | #define DISP_GAMMA_CONTROL_1_ADDR 0x300 | ||
178 | DISP_REG(DISP_GAMMA_CONTROL_1_ADDR) | ||
179 | #define DISP_GAMMA_CONTROL_2_ADDR 0x301 | ||
180 | DISP_REG(DISP_GAMMA_CONTROL_2_ADDR) | ||
181 | #define DISP_GAMMA_CONTROL_3_ADDR 0x302 | ||
182 | DISP_REG(DISP_GAMMA_CONTROL_3_ADDR) | ||
183 | #define DISP_GAMMA_CONTROL_4_ADDR 0x303 | ||
184 | DISP_REG(DISP_GAMMA_CONTROL_4_ADDR) | ||
185 | #define DISP_GAMMA_CONTROL_5_ADDR 0x304 | ||
186 | DISP_REG(DISP_GAMMA_CONTROL_5_ADDR) | ||
187 | /* Coordinate Control */ | ||
188 | #define DISP_VERT_SCROLL_CTL_1_ADDR 0x400 | ||
189 | DISP_REG(DISP_VERT_SCROLL_CTL_1_ADDR) | ||
190 | #define DISP_VERT_SCROLL_CTL_2_ADDR 0x401 | ||
191 | DISP_REG(DISP_VERT_SCROLL_CTL_2_ADDR) | ||
192 | #define DISP_SCREEN_1_DRV_POS_1_ADDR 0x402 | ||
193 | DISP_REG(DISP_SCREEN_1_DRV_POS_1_ADDR) | ||
194 | #define DISP_SCREEN_1_DRV_POS_2_ADDR 0x403 | ||
195 | DISP_REG(DISP_SCREEN_1_DRV_POS_2_ADDR) | ||
196 | #define DISP_SCREEN_2_DRV_POS_1_ADDR 0x404 | ||
197 | DISP_REG(DISP_SCREEN_2_DRV_POS_1_ADDR) | ||
198 | #define DISP_SCREEN_2_DRV_POS_2_ADDR 0x405 | ||
199 | DISP_REG(DISP_SCREEN_2_DRV_POS_2_ADDR) | ||
200 | #define DISP_HORZ_RAM_ADDR_POS_1_ADDR 0x406 | ||
201 | DISP_REG(DISP_HORZ_RAM_ADDR_POS_1_ADDR) | ||
202 | #define DISP_HORZ_RAM_ADDR_POS_2_ADDR 0x407 | ||
203 | DISP_REG(DISP_HORZ_RAM_ADDR_POS_2_ADDR) | ||
204 | #define DISP_VERT_RAM_ADDR_POS_1_ADDR 0x408 | ||
205 | DISP_REG(DISP_VERT_RAM_ADDR_POS_1_ADDR) | ||
206 | #define DISP_VERT_RAM_ADDR_POS_2_ADDR 0x409 | ||
207 | DISP_REG(DISP_VERT_RAM_ADDR_POS_2_ADDR) | ||
208 | #define DISP_TMD_700_ADDR 0x700 /* 0x700 */ | ||
209 | DISP_REG(DISP_TMD_700_ADDR) | ||
210 | #define DISP_TMD_015_ADDR 0x015 /* 0x700 */ | ||
211 | DISP_REG(DISP_TMD_015_ADDR) | ||
212 | #define DISP_TMD_305_ADDR 0x305 /* 0x700 */ | ||
213 | DISP_REG(DISP_TMD_305_ADDR) | ||
214 | |||
215 | /* | ||
216 | * TMD QVGA Bit Definations | ||
217 | */ | ||
218 | |||
219 | #define DISP_BIT_IB15 0x8000 | ||
220 | #define DISP_BIT_IB14 0x4000 | ||
221 | #define DISP_BIT_IB13 0x2000 | ||
222 | #define DISP_BIT_IB12 0x1000 | ||
223 | #define DISP_BIT_IB11 0x0800 | ||
224 | #define DISP_BIT_IB10 0x0400 | ||
225 | #define DISP_BIT_IB09 0x0200 | ||
226 | #define DISP_BIT_IB08 0x0100 | ||
227 | #define DISP_BIT_IB07 0x0080 | ||
228 | #define DISP_BIT_IB06 0x0040 | ||
229 | #define DISP_BIT_IB05 0x0020 | ||
230 | #define DISP_BIT_IB04 0x0010 | ||
231 | #define DISP_BIT_IB03 0x0008 | ||
232 | #define DISP_BIT_IB02 0x0004 | ||
233 | #define DISP_BIT_IB01 0x0002 | ||
234 | #define DISP_BIT_IB00 0x0001 | ||
235 | /* | ||
236 | * Display Control | ||
237 | * DISP_START_OSCILLATION_ADDR Start Oscillation | ||
238 | * DISP_DRIVER_OUTPUT_CTL_ADDR Driver Output Control | ||
239 | */ | ||
240 | #define DISP_BITMASK_SS DISP_BIT_IB08 | ||
241 | #define DISP_BITMASK_NL5 DISP_BIT_IB05 | ||
242 | #define DISP_BITMASK_NL4 DISP_BIT_IB04 | ||
243 | #define DISP_BITMASK_NL3 DISP_BIT_IB03 | ||
244 | #define DISP_BITMASK_NL2 DISP_BIT_IB02 | ||
245 | #define DISP_BITMASK_NL1 DISP_BIT_IB01 | ||
246 | #define DISP_BITMASK_NL0 DISP_BIT_IB00 | ||
247 | /* DISP_LCD_DRIVING_SIG_ADDR LCD Driving Signal Setting */ | ||
248 | #define DISP_BITMASK_BC DISP_BIT_IB09 | ||
249 | /* DISP_ENTRY_MODE_ADDR Entry Mode */ | ||
250 | #define DISP_BITMASK_TRI DISP_BIT_IB15 | ||
251 | #define DISP_BITMASK_DFM1 DISP_BIT_IB14 | ||
252 | #define DISP_BITMASK_DFM0 DISP_BIT_IB13 | ||
253 | #define DISP_BITMASK_BGR DISP_BIT_IB12 | ||
254 | #define DISP_BITMASK_HWM0 DISP_BIT_IB08 | ||
255 | #define DISP_BITMASK_ID1 DISP_BIT_IB05 | ||
256 | #define DISP_BITMASK_ID0 DISP_BIT_IB04 | ||
257 | #define DISP_BITMASK_AM DISP_BIT_IB03 | ||
258 | /* DISP_DISPLAY_CTL_1_ADDR Display Control (1) */ | ||
259 | #define DISP_BITMASK_COL1 DISP_BIT_IB15 | ||
260 | #define DISP_BITMASK_COL0 DISP_BIT_IB14 | ||
261 | #define DISP_BITMASK_VLE2 DISP_BIT_IB10 | ||
262 | #define DISP_BITMASK_VLE1 DISP_BIT_IB09 | ||
263 | #define DISP_BITMASK_SPT DISP_BIT_IB08 | ||
264 | #define DISP_BITMASK_PT1 DISP_BIT_IB07 | ||
265 | #define DISP_BITMASK_PT0 DISP_BIT_IB06 | ||
266 | #define DISP_BITMASK_REV DISP_BIT_IB02 | ||
267 | /* DISP_DISPLAY_CTL_2_ADDR Display Control (2) */ | ||
268 | #define DISP_BITMASK_FP3 DISP_BIT_IB11 | ||
269 | #define DISP_BITMASK_FP2 DISP_BIT_IB10 | ||
270 | #define DISP_BITMASK_FP1 DISP_BIT_IB09 | ||
271 | #define DISP_BITMASK_FP0 DISP_BIT_IB08 | ||
272 | #define DISP_BITMASK_BP3 DISP_BIT_IB03 | ||
273 | #define DISP_BITMASK_BP2 DISP_BIT_IB02 | ||
274 | #define DISP_BITMASK_BP1 DISP_BIT_IB01 | ||
275 | #define DISP_BITMASK_BP0 DISP_BIT_IB00 | ||
276 | /* DISP_POWER_SUPPLY_INTF_ADDR Power Supply IC Interface Control */ | ||
277 | #define DISP_BITMASK_CSE DISP_BIT_IB12 | ||
278 | #define DISP_BITMASK_TE DISP_BIT_IB08 | ||
279 | #define DISP_BITMASK_IX3 DISP_BIT_IB03 | ||
280 | #define DISP_BITMASK_IX2 DISP_BIT_IB02 | ||
281 | #define DISP_BITMASK_IX1 DISP_BIT_IB01 | ||
282 | #define DISP_BITMASK_IX0 DISP_BIT_IB00 | ||
283 | /* DISP_EXT_DISPLAY_CTL_1_ADDR External Display Interface Control (1) */ | ||
284 | #define DISP_BITMASK_RM DISP_BIT_IB08 | ||
285 | #define DISP_BITMASK_DM1 DISP_BIT_IB05 | ||
286 | #define DISP_BITMASK_DM0 DISP_BIT_IB04 | ||
287 | #define DISP_BITMASK_RIM1 DISP_BIT_IB01 | ||
288 | #define DISP_BITMASK_RIM0 DISP_BIT_IB00 | ||
289 | /* DISP_FRAME_CYCLE_CTL_ADDR Frame Frequency Adjustment Control */ | ||
290 | #define DISP_BITMASK_DIVI1 DISP_BIT_IB09 | ||
291 | #define DISP_BITMASK_DIVI0 DISP_BIT_IB08 | ||
292 | #define DISP_BITMASK_RTNI4 DISP_BIT_IB04 | ||
293 | #define DISP_BITMASK_RTNI3 DISP_BIT_IB03 | ||
294 | #define DISP_BITMASK_RTNI2 DISP_BIT_IB02 | ||
295 | #define DISP_BITMASK_RTNI1 DISP_BIT_IB01 | ||
296 | #define DISP_BITMASK_RTNI0 DISP_BIT_IB00 | ||
297 | /* DISP_EXT_DISPLAY_CTL_2_ADDR External Display Interface Control (2) */ | ||
298 | #define DISP_BITMASK_DIVE1 DISP_BIT_IB09 | ||
299 | #define DISP_BITMASK_DIVE0 DISP_BIT_IB08 | ||
300 | #define DISP_BITMASK_RTNE7 DISP_BIT_IB07 | ||
301 | #define DISP_BITMASK_RTNE6 DISP_BIT_IB06 | ||
302 | #define DISP_BITMASK_RTNE5 DISP_BIT_IB05 | ||
303 | #define DISP_BITMASK_RTNE4 DISP_BIT_IB04 | ||
304 | #define DISP_BITMASK_RTNE3 DISP_BIT_IB03 | ||
305 | #define DISP_BITMASK_RTNE2 DISP_BIT_IB02 | ||
306 | #define DISP_BITMASK_RTNE1 DISP_BIT_IB01 | ||
307 | #define DISP_BITMASK_RTNE0 DISP_BIT_IB00 | ||
308 | /* DISP_EXT_DISPLAY_CTL_3_ADDR External Display Interface Control (3) */ | ||
309 | #define DISP_BITMASK_VSPL DISP_BIT_IB04 | ||
310 | #define DISP_BITMASK_HSPL DISP_BIT_IB03 | ||
311 | #define DISP_BITMASK_VPL DISP_BIT_IB02 | ||
312 | #define DISP_BITMASK_EPL DISP_BIT_IB01 | ||
313 | #define DISP_BITMASK_DPL DISP_BIT_IB00 | ||
314 | /* DISP_LTPS_CTL_1_ADDR LTPS Interface Control (1) */ | ||
315 | #define DISP_BITMASK_CLWI3 DISP_BIT_IB11 | ||
316 | #define DISP_BITMASK_CLWI2 DISP_BIT_IB10 | ||
317 | #define DISP_BITMASK_CLWI1 DISP_BIT_IB09 | ||
318 | #define DISP_BITMASK_CLWI0 DISP_BIT_IB08 | ||
319 | #define DISP_BITMASK_CLTI1 DISP_BIT_IB01 | ||
320 | #define DISP_BITMASK_CLTI0 DISP_BIT_IB00 | ||
321 | /* DISP_LTPS_CTL_2_ADDR LTPS Interface Control (2) */ | ||
322 | #define DISP_BITMASK_OEVBI1 DISP_BIT_IB09 | ||
323 | #define DISP_BITMASK_OEVBI0 DISP_BIT_IB08 | ||
324 | #define DISP_BITMASK_OEVFI1 DISP_BIT_IB01 | ||
325 | #define DISP_BITMASK_OEVFI0 DISP_BIT_IB00 | ||
326 | /* DISP_LTPS_CTL_3_ADDR LTPS Interface Control (3) */ | ||
327 | #define DISP_BITMASK_SHI1 DISP_BIT_IB01 | ||
328 | #define DISP_BITMASK_SHI0 DISP_BIT_IB00 | ||
329 | /* DISP_LTPS_CTL_4_ADDR LTPS Interface Control (4) */ | ||
330 | #define DISP_BITMASK_CLWE5 DISP_BIT_IB13 | ||
331 | #define DISP_BITMASK_CLWE4 DISP_BIT_IB12 | ||
332 | #define DISP_BITMASK_CLWE3 DISP_BIT_IB11 | ||
333 | #define DISP_BITMASK_CLWE2 DISP_BIT_IB10 | ||
334 | #define DISP_BITMASK_CLWE1 DISP_BIT_IB09 | ||
335 | #define DISP_BITMASK_CLWE0 DISP_BIT_IB08 | ||
336 | #define DISP_BITMASK_CLTE3 DISP_BIT_IB03 | ||
337 | #define DISP_BITMASK_CLTE2 DISP_BIT_IB02 | ||
338 | #define DISP_BITMASK_CLTE1 DISP_BIT_IB01 | ||
339 | #define DISP_BITMASK_CLTE0 DISP_BIT_IB00 | ||
340 | /* DISP_LTPS_CTL_5_ADDR LTPS Interface Control (5) */ | ||
341 | #define DISP_BITMASK_OEVBE3 DISP_BIT_IB11 | ||
342 | #define DISP_BITMASK_OEVBE2 DISP_BIT_IB10 | ||
343 | #define DISP_BITMASK_OEVBE1 DISP_BIT_IB09 | ||
344 | #define DISP_BITMASK_OEVBE0 DISP_BIT_IB08 | ||
345 | #define DISP_BITMASK_OEVFE3 DISP_BIT_IB03 | ||
346 | #define DISP_BITMASK_OEVFE2 DISP_BIT_IB02 | ||
347 | #define DISP_BITMASK_OEVFE1 DISP_BIT_IB01 | ||
348 | #define DISP_BITMASK_OEVFE0 DISP_BIT_IB00 | ||
349 | /* DISP_LTPS_CTL_6_ADDR LTPS Interface Control (6) */ | ||
350 | #define DISP_BITMASK_SHE3 DISP_BIT_IB03 | ||
351 | #define DISP_BITMASK_SHE2 DISP_BIT_IB02 | ||
352 | #define DISP_BITMASK_SHE1 DISP_BIT_IB01 | ||
353 | #define DISP_BITMASK_SHE0 DISP_BIT_IB00 | ||
354 | /* DISP_AMP_SETTING_ADDR Amplify Setting */ | ||
355 | #define DISP_BITMASK_ABSW1 DISP_BIT_IB01 | ||
356 | #define DISP_BITMASK_ABSW0 DISP_BIT_IB00 | ||
357 | /* DISP_MODE_SETTING_ADDR Mode Setting */ | ||
358 | #define DISP_BITMASK_DSTB DISP_BIT_IB02 | ||
359 | #define DISP_BITMASK_STB DISP_BIT_IB00 | ||
360 | /* DISP_POFF_LN_SETTING_ADDR Power Off Line Setting */ | ||
361 | #define DISP_BITMASK_POFH3 DISP_BIT_IB03 | ||
362 | #define DISP_BITMASK_POFH2 DISP_BIT_IB02 | ||
363 | #define DISP_BITMASK_POFH1 DISP_BIT_IB01 | ||
364 | #define DISP_BITMASK_POFH0 DISP_BIT_IB00 | ||
365 | |||
366 | /* Power Contol */ | ||
367 | /* DISP_POWER_CTL_1_ADDR Power Control (1) */ | ||
368 | #define DISP_BITMASK_PO DISP_BIT_IB11 | ||
369 | #define DISP_BITMASK_VCD DISP_BIT_IB09 | ||
370 | #define DISP_BITMASK_VSC DISP_BIT_IB08 | ||
371 | #define DISP_BITMASK_CON DISP_BIT_IB07 | ||
372 | #define DISP_BITMASK_ASW1 DISP_BIT_IB06 | ||
373 | #define DISP_BITMASK_ASW0 DISP_BIT_IB05 | ||
374 | #define DISP_BITMASK_OEV DISP_BIT_IB04 | ||
375 | #define DISP_BITMASK_OEVE DISP_BIT_IB03 | ||
376 | #define DISP_BITMASK_FR DISP_BIT_IB02 | ||
377 | #define DISP_BITMASK_D1 DISP_BIT_IB01 | ||
378 | #define DISP_BITMASK_D0 DISP_BIT_IB00 | ||
379 | /* DISP_POWER_CTL_2_ADDR Power Control (2) */ | ||
380 | #define DISP_BITMASK_DC4 DISP_BIT_IB15 | ||
381 | #define DISP_BITMASK_DC3 DISP_BIT_IB14 | ||
382 | #define DISP_BITMASK_SAP2 DISP_BIT_IB13 | ||
383 | #define DISP_BITMASK_SAP1 DISP_BIT_IB12 | ||
384 | #define DISP_BITMASK_SAP0 DISP_BIT_IB11 | ||
385 | #define DISP_BITMASK_BT2 DISP_BIT_IB10 | ||
386 | #define DISP_BITMASK_BT1 DISP_BIT_IB09 | ||
387 | #define DISP_BITMASK_BT0 DISP_BIT_IB08 | ||
388 | #define DISP_BITMASK_DC2 DISP_BIT_IB07 | ||
389 | #define DISP_BITMASK_DC1 DISP_BIT_IB06 | ||
390 | #define DISP_BITMASK_DC0 DISP_BIT_IB05 | ||
391 | #define DISP_BITMASK_AP2 DISP_BIT_IB04 | ||
392 | #define DISP_BITMASK_AP1 DISP_BIT_IB03 | ||
393 | #define DISP_BITMASK_AP0 DISP_BIT_IB02 | ||
394 | /* DISP_POWER_CTL_3_ADDR Power Control (3) */ | ||
395 | #define DISP_BITMASK_VGL4 DISP_BIT_IB10 | ||
396 | #define DISP_BITMASK_VGL3 DISP_BIT_IB09 | ||
397 | #define DISP_BITMASK_VGL2 DISP_BIT_IB08 | ||
398 | #define DISP_BITMASK_VGL1 DISP_BIT_IB07 | ||
399 | #define DISP_BITMASK_VGL0 DISP_BIT_IB06 | ||
400 | #define DISP_BITMASK_VGH4 DISP_BIT_IB04 | ||
401 | #define DISP_BITMASK_VGH3 DISP_BIT_IB03 | ||
402 | #define DISP_BITMASK_VGH2 DISP_BIT_IB02 | ||
403 | #define DISP_BITMASK_VGH1 DISP_BIT_IB01 | ||
404 | #define DISP_BITMASK_VGH0 DISP_BIT_IB00 | ||
405 | /* DISP_POWER_CTL_4_ADDR Power Control (4) */ | ||
406 | #define DISP_BITMASK_VC2 DISP_BIT_IB02 | ||
407 | #define DISP_BITMASK_VC1 DISP_BIT_IB01 | ||
408 | #define DISP_BITMASK_VC0 DISP_BIT_IB00 | ||
409 | /* DISP_POWER_CTL_5_ADDR Power Control (5) */ | ||
410 | #define DISP_BITMASK_VRL3 DISP_BIT_IB11 | ||
411 | #define DISP_BITMASK_VRL2 DISP_BIT_IB10 | ||
412 | #define DISP_BITMASK_VRL1 DISP_BIT_IB09 | ||
413 | #define DISP_BITMASK_VRL0 DISP_BIT_IB08 | ||
414 | #define DISP_BITMASK_PON DISP_BIT_IB04 | ||
415 | #define DISP_BITMASK_VRH3 DISP_BIT_IB03 | ||
416 | #define DISP_BITMASK_VRH2 DISP_BIT_IB02 | ||
417 | #define DISP_BITMASK_VRH1 DISP_BIT_IB01 | ||
418 | #define DISP_BITMASK_VRH0 DISP_BIT_IB00 | ||
419 | /* DISP_POWER_CTL_6_ADDR Power Control (6) */ | ||
420 | #define DISP_BITMASK_VCOMG DISP_BIT_IB13 | ||
421 | #define DISP_BITMASK_VDV4 DISP_BIT_IB12 | ||
422 | #define DISP_BITMASK_VDV3 DISP_BIT_IB11 | ||
423 | #define DISP_BITMASK_VDV2 DISP_BIT_IB10 | ||
424 | #define DISP_BITMASK_VDV1 DISP_BIT_IB09 | ||
425 | #define DISP_BITMASK_VDV0 DISP_BIT_IB08 | ||
426 | #define DISP_BITMASK_VCM4 DISP_BIT_IB04 | ||
427 | #define DISP_BITMASK_VCM3 DISP_BIT_IB03 | ||
428 | #define DISP_BITMASK_VCM2 DISP_BIT_IB02 | ||
429 | #define DISP_BITMASK_VCM1 DISP_BIT_IB01 | ||
430 | #define DISP_BITMASK_VCM0 DISP_BIT_IB00 | ||
431 | /* RAM Access */ | ||
432 | /* DISP_RAM_ADDR_SET_1_ADDR RAM Address Set (1) */ | ||
433 | #define DISP_BITMASK_AD7 DISP_BIT_IB07 | ||
434 | #define DISP_BITMASK_AD6 DISP_BIT_IB06 | ||
435 | #define DISP_BITMASK_AD5 DISP_BIT_IB05 | ||
436 | #define DISP_BITMASK_AD4 DISP_BIT_IB04 | ||
437 | #define DISP_BITMASK_AD3 DISP_BIT_IB03 | ||
438 | #define DISP_BITMASK_AD2 DISP_BIT_IB02 | ||
439 | #define DISP_BITMASK_AD1 DISP_BIT_IB01 | ||
440 | #define DISP_BITMASK_AD0 DISP_BIT_IB00 | ||
441 | /* DISP_RAM_ADDR_SET_2_ADDR RAM Address Set (2) */ | ||
442 | #define DISP_BITMASK_AD16 DISP_BIT_IB08 | ||
443 | #define DISP_BITMASK_AD15 DISP_BIT_IB07 | ||
444 | #define DISP_BITMASK_AD14 DISP_BIT_IB06 | ||
445 | #define DISP_BITMASK_AD13 DISP_BIT_IB05 | ||
446 | #define DISP_BITMASK_AD12 DISP_BIT_IB04 | ||
447 | #define DISP_BITMASK_AD11 DISP_BIT_IB03 | ||
448 | #define DISP_BITMASK_AD10 DISP_BIT_IB02 | ||
449 | #define DISP_BITMASK_AD9 DISP_BIT_IB01 | ||
450 | #define DISP_BITMASK_AD8 DISP_BIT_IB00 | ||
451 | /* | ||
452 | * DISP_CMD_RAMWR RAM Data Read/Write | ||
453 | * Use Data Bit Configuration | ||
454 | */ | ||
455 | /* DISP_RAM_DATA_MASK_1_ADDR RAM Write Data Mask (1) */ | ||
456 | #define DISP_BITMASK_WM11 DISP_BIT_IB13 | ||
457 | #define DISP_BITMASK_WM10 DISP_BIT_IB12 | ||
458 | #define DISP_BITMASK_WM9 DISP_BIT_IB11 | ||
459 | #define DISP_BITMASK_WM8 DISP_BIT_IB10 | ||
460 | #define DISP_BITMASK_WM7 DISP_BIT_IB09 | ||
461 | #define DISP_BITMASK_WM6 DISP_BIT_IB08 | ||
462 | #define DISP_BITMASK_WM5 DISP_BIT_IB05 | ||
463 | #define DISP_BITMASK_WM4 DISP_BIT_IB04 | ||
464 | #define DISP_BITMASK_WM3 DISP_BIT_IB03 | ||
465 | #define DISP_BITMASK_WM2 DISP_BIT_IB02 | ||
466 | #define DISP_BITMASK_WM1 DISP_BIT_IB01 | ||
467 | #define DISP_BITMASK_WM0 DISP_BIT_IB00 | ||
468 | /* DISP_RAM_DATA_MASK_2_ADDR RAM Write Data Mask (2) */ | ||
469 | #define DISP_BITMASK_WM17 DISP_BIT_IB05 | ||
470 | #define DISP_BITMASK_WM16 DISP_BIT_IB04 | ||
471 | #define DISP_BITMASK_WM15 DISP_BIT_IB03 | ||
472 | #define DISP_BITMASK_WM14 DISP_BIT_IB02 | ||
473 | #define DISP_BITMASK_WM13 DISP_BIT_IB01 | ||
474 | #define DISP_BITMASK_WM12 DISP_BIT_IB00 | ||
475 | /*Gamma Control */ | ||
476 | /* DISP_GAMMA_CONTROL_1_ADDR Gamma Control (1) */ | ||
477 | #define DISP_BITMASK_PKP12 DISP_BIT_IB10 | ||
478 | #define DISP_BITMASK_PKP11 DISP_BIT_IB08 | ||
479 | #define DISP_BITMASK_PKP10 DISP_BIT_IB09 | ||
480 | #define DISP_BITMASK_PKP02 DISP_BIT_IB02 | ||
481 | #define DISP_BITMASK_PKP01 DISP_BIT_IB01 | ||
482 | #define DISP_BITMASK_PKP00 DISP_BIT_IB00 | ||
483 | /* DISP_GAMMA_CONTROL_2_ADDR Gamma Control (2) */ | ||
484 | #define DISP_BITMASK_PKP32 DISP_BIT_IB10 | ||
485 | #define DISP_BITMASK_PKP31 DISP_BIT_IB09 | ||
486 | #define DISP_BITMASK_PKP30 DISP_BIT_IB08 | ||
487 | #define DISP_BITMASK_PKP22 DISP_BIT_IB02 | ||
488 | #define DISP_BITMASK_PKP21 DISP_BIT_IB01 | ||
489 | #define DISP_BITMASK_PKP20 DISP_BIT_IB00 | ||
490 | /* DISP_GAMMA_CONTROL_3_ADDR Gamma Control (3) */ | ||
491 | #define DISP_BITMASK_PKP52 DISP_BIT_IB10 | ||
492 | #define DISP_BITMASK_PKP51 DISP_BIT_IB09 | ||
493 | #define DISP_BITMASK_PKP50 DISP_BIT_IB08 | ||
494 | #define DISP_BITMASK_PKP42 DISP_BIT_IB02 | ||
495 | #define DISP_BITMASK_PKP41 DISP_BIT_IB01 | ||
496 | #define DISP_BITMASK_PKP40 DISP_BIT_IB00 | ||
497 | /* DISP_GAMMA_CONTROL_4_ADDR Gamma Control (4) */ | ||
498 | #define DISP_BITMASK_PRP12 DISP_BIT_IB10 | ||
499 | #define DISP_BITMASK_PRP11 DISP_BIT_IB08 | ||
500 | #define DISP_BITMASK_PRP10 DISP_BIT_IB09 | ||
501 | #define DISP_BITMASK_PRP02 DISP_BIT_IB02 | ||
502 | #define DISP_BITMASK_PRP01 DISP_BIT_IB01 | ||
503 | #define DISP_BITMASK_PRP00 DISP_BIT_IB00 | ||
504 | /* DISP_GAMMA_CONTROL_5_ADDR Gamma Control (5) */ | ||
505 | #define DISP_BITMASK_VRP14 DISP_BIT_IB12 | ||
506 | #define DISP_BITMASK_VRP13 DISP_BIT_IB11 | ||
507 | #define DISP_BITMASK_VRP12 DISP_BIT_IB10 | ||
508 | #define DISP_BITMASK_VRP11 DISP_BIT_IB08 | ||
509 | #define DISP_BITMASK_VRP10 DISP_BIT_IB09 | ||
510 | #define DISP_BITMASK_VRP03 DISP_BIT_IB03 | ||
511 | #define DISP_BITMASK_VRP02 DISP_BIT_IB02 | ||
512 | #define DISP_BITMASK_VRP01 DISP_BIT_IB01 | ||
513 | #define DISP_BITMASK_VRP00 DISP_BIT_IB00 | ||
514 | /* DISP_GAMMA_CONTROL_6_ADDR Gamma Control (6) */ | ||
515 | #define DISP_BITMASK_PKN12 DISP_BIT_IB10 | ||
516 | #define DISP_BITMASK_PKN11 DISP_BIT_IB08 | ||
517 | #define DISP_BITMASK_PKN10 DISP_BIT_IB09 | ||
518 | #define DISP_BITMASK_PKN02 DISP_BIT_IB02 | ||
519 | #define DISP_BITMASK_PKN01 DISP_BIT_IB01 | ||
520 | #define DISP_BITMASK_PKN00 DISP_BIT_IB00 | ||
521 | /* DISP_GAMMA_CONTROL_7_ADDR Gamma Control (7) */ | ||
522 | #define DISP_BITMASK_PKN32 DISP_BIT_IB10 | ||
523 | #define DISP_BITMASK_PKN31 DISP_BIT_IB08 | ||
524 | #define DISP_BITMASK_PKN30 DISP_BIT_IB09 | ||
525 | #define DISP_BITMASK_PKN22 DISP_BIT_IB02 | ||
526 | #define DISP_BITMASK_PKN21 DISP_BIT_IB01 | ||
527 | #define DISP_BITMASK_PKN20 DISP_BIT_IB00 | ||
528 | /* DISP_GAMMA_CONTROL_8_ADDR Gamma Control (8) */ | ||
529 | #define DISP_BITMASK_PKN52 DISP_BIT_IB10 | ||
530 | #define DISP_BITMASK_PKN51 DISP_BIT_IB08 | ||
531 | #define DISP_BITMASK_PKN50 DISP_BIT_IB09 | ||
532 | #define DISP_BITMASK_PKN42 DISP_BIT_IB02 | ||
533 | #define DISP_BITMASK_PKN41 DISP_BIT_IB01 | ||
534 | #define DISP_BITMASK_PKN40 DISP_BIT_IB00 | ||
535 | /* DISP_GAMMA_CONTROL_9_ADDR Gamma Control (9) */ | ||
536 | #define DISP_BITMASK_PRN12 DISP_BIT_IB10 | ||
537 | #define DISP_BITMASK_PRN11 DISP_BIT_IB08 | ||
538 | #define DISP_BITMASK_PRN10 DISP_BIT_IB09 | ||
539 | #define DISP_BITMASK_PRN02 DISP_BIT_IB02 | ||
540 | #define DISP_BITMASK_PRN01 DISP_BIT_IB01 | ||
541 | #define DISP_BITMASK_PRN00 DISP_BIT_IB00 | ||
542 | /* DISP_GAMMA_CONTROL_10_ADDR Gamma Control (10) */ | ||
543 | #define DISP_BITMASK_VRN14 DISP_BIT_IB12 | ||
544 | #define DISP_BITMASK_VRN13 DISP_BIT_IB11 | ||
545 | #define DISP_BITMASK_VRN12 DISP_BIT_IB10 | ||
546 | #define DISP_BITMASK_VRN11 DISP_BIT_IB08 | ||
547 | #define DISP_BITMASK_VRN10 DISP_BIT_IB09 | ||
548 | #define DISP_BITMASK_VRN03 DISP_BIT_IB03 | ||
549 | #define DISP_BITMASK_VRN02 DISP_BIT_IB02 | ||
550 | #define DISP_BITMASK_VRN01 DISP_BIT_IB01 | ||
551 | #define DISP_BITMASK_VRN00 DISP_BIT_IB00 | ||
552 | /* Coordinate Control */ | ||
553 | /* DISP_VERT_SCROLL_CTL_1_ADDR Vertical Scroll Control (1) */ | ||
554 | #define DISP_BITMASK_VL18 DISP_BIT_IB08 | ||
555 | #define DISP_BITMASK_VL17 DISP_BIT_IB07 | ||
556 | #define DISP_BITMASK_VL16 DISP_BIT_IB06 | ||
557 | #define DISP_BITMASK_VL15 DISP_BIT_IB05 | ||
558 | #define DISP_BITMASK_VL14 DISP_BIT_IB04 | ||
559 | #define DISP_BITMASK_VL13 DISP_BIT_IB03 | ||
560 | #define DISP_BITMASK_VL12 DISP_BIT_IB02 | ||
561 | #define DISP_BITMASK_VL11 DISP_BIT_IB01 | ||
562 | #define DISP_BITMASK_VL10 DISP_BIT_IB00 | ||
563 | /* DISP_VERT_SCROLL_CTL_2_ADDR Vertical Scroll Control (2) */ | ||
564 | #define DISP_BITMASK_VL28 DISP_BIT_IB08 | ||
565 | #define DISP_BITMASK_VL27 DISP_BIT_IB07 | ||
566 | #define DISP_BITMASK_VL26 DISP_BIT_IB06 | ||
567 | #define DISP_BITMASK_VL25 DISP_BIT_IB05 | ||
568 | #define DISP_BITMASK_VL24 DISP_BIT_IB04 | ||
569 | #define DISP_BITMASK_VL23 DISP_BIT_IB03 | ||
570 | #define DISP_BITMASK_VL22 DISP_BIT_IB02 | ||
571 | #define DISP_BITMASK_VL21 DISP_BIT_IB01 | ||
572 | #define DISP_BITMASK_VL20 DISP_BIT_IB00 | ||
573 | /* DISP_SCREEN_1_DRV_POS_1_ADDR First Screen Driving Position (1) */ | ||
574 | #define DISP_BITMASK_SS18 DISP_BIT_IB08 | ||
575 | #define DISP_BITMASK_SS17 DISP_BIT_IB07 | ||
576 | #define DISP_BITMASK_SS16 DISP_BIT_IB06 | ||
577 | #define DISP_BITMASK_SS15 DISP_BIT_IB05 | ||
578 | #define DISP_BITMASK_SS14 DISP_BIT_IB04 | ||
579 | #define DISP_BITMASK_SS13 DISP_BIT_IB03 | ||
580 | #define DISP_BITMASK_SS12 DISP_BIT_IB02 | ||
581 | #define DISP_BITMASK_SS11 DISP_BIT_IB01 | ||
582 | #define DISP_BITMASK_SS10 DISP_BIT_IB00 | ||
583 | /* DISP_SCREEN_1_DRV_POS_2_ADDR First Screen Driving Position (2) */ | ||
584 | #define DISP_BITMASK_SE18 DISP_BIT_IB08 | ||
585 | #define DISP_BITMASK_SE17 DISP_BIT_IB07 | ||
586 | #define DISP_BITMASK_SE16 DISP_BIT_IB06 | ||
587 | #define DISP_BITMASK_SE15 DISP_BIT_IB05 | ||
588 | #define DISP_BITMASK_SE14 DISP_BIT_IB04 | ||
589 | #define DISP_BITMASK_SE13 DISP_BIT_IB03 | ||
590 | #define DISP_BITMASK_SE12 DISP_BIT_IB02 | ||
591 | #define DISP_BITMASK_SE11 DISP_BIT_IB01 | ||
592 | #define DISP_BITMASK_SE10 DISP_BIT_IB00 | ||
593 | /* DISP_SCREEN_2_DRV_POS_1_ADDR Second Screen Driving Position (1) */ | ||
594 | #define DISP_BITMASK_SS28 DISP_BIT_IB08 | ||
595 | #define DISP_BITMASK_SS27 DISP_BIT_IB07 | ||
596 | #define DISP_BITMASK_SS26 DISP_BIT_IB06 | ||
597 | #define DISP_BITMASK_SS25 DISP_BIT_IB05 | ||
598 | #define DISP_BITMASK_SS24 DISP_BIT_IB04 | ||
599 | #define DISP_BITMASK_SS23 DISP_BIT_IB03 | ||
600 | #define DISP_BITMASK_SS22 DISP_BIT_IB02 | ||
601 | #define DISP_BITMASK_SS21 DISP_BIT_IB01 | ||
602 | #define DISP_BITMASK_SS20 DISP_BIT_IB00 | ||
603 | /* DISP_SCREEN_3_DRV_POS_2_ADDR Second Screen Driving Position (2) */ | ||
604 | #define DISP_BITMASK_SE28 DISP_BIT_IB08 | ||
605 | #define DISP_BITMASK_SE27 DISP_BIT_IB07 | ||
606 | #define DISP_BITMASK_SE26 DISP_BIT_IB06 | ||
607 | #define DISP_BITMASK_SE25 DISP_BIT_IB05 | ||
608 | #define DISP_BITMASK_SE24 DISP_BIT_IB04 | ||
609 | #define DISP_BITMASK_SE23 DISP_BIT_IB03 | ||
610 | #define DISP_BITMASK_SE22 DISP_BIT_IB02 | ||
611 | #define DISP_BITMASK_SE21 DISP_BIT_IB01 | ||
612 | #define DISP_BITMASK_SE20 DISP_BIT_IB00 | ||
613 | /* DISP_HORZ_RAM_ADDR_POS_1_ADDR Horizontal RAM Address Position (1) */ | ||
614 | #define DISP_BITMASK_HSA7 DISP_BIT_IB07 | ||
615 | #define DISP_BITMASK_HSA6 DISP_BIT_IB06 | ||
616 | #define DISP_BITMASK_HSA5 DISP_BIT_IB05 | ||
617 | #define DISP_BITMASK_HSA4 DISP_BIT_IB04 | ||
618 | #define DISP_BITMASK_HSA3 DISP_BIT_IB03 | ||
619 | #define DISP_BITMASK_HSA2 DISP_BIT_IB02 | ||
620 | #define DISP_BITMASK_HSA1 DISP_BIT_IB01 | ||
621 | #define DISP_BITMASK_HSA0 DISP_BIT_IB00 | ||
622 | /* DISP_HORZ_RAM_ADDR_POS_2_ADDR Horizontal RAM Address Position (2) */ | ||
623 | #define DISP_BITMASK_HEA7 DISP_BIT_IB07 | ||
624 | #define DISP_BITMASK_HEA6 DISP_BIT_IB06 | ||
625 | #define DISP_BITMASK_HEA5 DISP_BIT_IB05 | ||
626 | #define DISP_BITMASK_HEA4 DISP_BIT_IB04 | ||
627 | #define DISP_BITMASK_HEA3 DISP_BIT_IB03 | ||
628 | #define DISP_BITMASK_HEA2 DISP_BIT_IB02 | ||
629 | #define DISP_BITMASK_HEA1 DISP_BIT_IB01 | ||
630 | #define DISP_BITMASK_HEA0 DISP_BIT_IB00 | ||
631 | /* DISP_VERT_RAM_ADDR_POS_1_ADDR Vertical RAM Address Position (1) */ | ||
632 | #define DISP_BITMASK_VSA8 DISP_BIT_IB08 | ||
633 | #define DISP_BITMASK_VSA7 DISP_BIT_IB07 | ||
634 | #define DISP_BITMASK_VSA6 DISP_BIT_IB06 | ||
635 | #define DISP_BITMASK_VSA5 DISP_BIT_IB05 | ||
636 | #define DISP_BITMASK_VSA4 DISP_BIT_IB04 | ||
637 | #define DISP_BITMASK_VSA3 DISP_BIT_IB03 | ||
638 | #define DISP_BITMASK_VSA2 DISP_BIT_IB02 | ||
639 | #define DISP_BITMASK_VSA1 DISP_BIT_IB01 | ||
640 | #define DISP_BITMASK_VSA0 DISP_BIT_IB00 | ||
641 | /* DISP_VERT_RAM_ADDR_POS_2_ADDR Vertical RAM Address Position (2) */ | ||
642 | #define DISP_BITMASK_VEA8 DISP_BIT_IB08 | ||
643 | #define DISP_BITMASK_VEA7 DISP_BIT_IB07 | ||
644 | #define DISP_BITMASK_VEA6 DISP_BIT_IB06 | ||
645 | #define DISP_BITMASK_VEA5 DISP_BIT_IB05 | ||
646 | #define DISP_BITMASK_VEA4 DISP_BIT_IB04 | ||
647 | #define DISP_BITMASK_VEA3 DISP_BIT_IB03 | ||
648 | #define DISP_BITMASK_VEA2 DISP_BIT_IB02 | ||
649 | #define DISP_BITMASK_VEA1 DISP_BIT_IB01 | ||
650 | #define DISP_BITMASK_VEA0 DISP_BIT_IB00 | ||
651 | static word disp_area_start_row; | ||
652 | static word disp_area_end_row; | ||
653 | static boolean disp_initialized = FALSE; | ||
654 | /* For some reason the contrast set at init time is not good. Need to do | ||
655 | * it again | ||
656 | */ | ||
657 | static boolean display_on = FALSE; | ||
658 | |||
659 | static uint32 tmd20qvga_lcd_rev; | ||
660 | uint16 tmd20qvga_panel_offset; | ||
661 | |||
662 | #ifdef DISP_DEVICE_8BPP | ||
663 | static word convert_8_to_16_tbl[256] = { | ||
664 | 0x0000, 0x2000, 0x4000, 0x6000, 0x8000, 0xA000, 0xC000, 0xE000, | ||
665 | 0x0100, 0x2100, 0x4100, 0x6100, 0x8100, 0xA100, 0xC100, 0xE100, | ||
666 | 0x0200, 0x2200, 0x4200, 0x6200, 0x8200, 0xA200, 0xC200, 0xE200, | ||
667 | 0x0300, 0x2300, 0x4300, 0x6300, 0x8300, 0xA300, 0xC300, 0xE300, | ||
668 | 0x0400, 0x2400, 0x4400, 0x6400, 0x8400, 0xA400, 0xC400, 0xE400, | ||
669 | 0x0500, 0x2500, 0x4500, 0x6500, 0x8500, 0xA500, 0xC500, 0xE500, | ||
670 | 0x0600, 0x2600, 0x4600, 0x6600, 0x8600, 0xA600, 0xC600, 0xE600, | ||
671 | 0x0700, 0x2700, 0x4700, 0x6700, 0x8700, 0xA700, 0xC700, 0xE700, | ||
672 | 0x0008, 0x2008, 0x4008, 0x6008, 0x8008, 0xA008, 0xC008, 0xE008, | ||
673 | 0x0108, 0x2108, 0x4108, 0x6108, 0x8108, 0xA108, 0xC108, 0xE108, | ||
674 | 0x0208, 0x2208, 0x4208, 0x6208, 0x8208, 0xA208, 0xC208, 0xE208, | ||
675 | 0x0308, 0x2308, 0x4308, 0x6308, 0x8308, 0xA308, 0xC308, 0xE308, | ||
676 | 0x0408, 0x2408, 0x4408, 0x6408, 0x8408, 0xA408, 0xC408, 0xE408, | ||
677 | 0x0508, 0x2508, 0x4508, 0x6508, 0x8508, 0xA508, 0xC508, 0xE508, | ||
678 | 0x0608, 0x2608, 0x4608, 0x6608, 0x8608, 0xA608, 0xC608, 0xE608, | ||
679 | 0x0708, 0x2708, 0x4708, 0x6708, 0x8708, 0xA708, 0xC708, 0xE708, | ||
680 | 0x0010, 0x2010, 0x4010, 0x6010, 0x8010, 0xA010, 0xC010, 0xE010, | ||
681 | 0x0110, 0x2110, 0x4110, 0x6110, 0x8110, 0xA110, 0xC110, 0xE110, | ||
682 | 0x0210, 0x2210, 0x4210, 0x6210, 0x8210, 0xA210, 0xC210, 0xE210, | ||
683 | 0x0310, 0x2310, 0x4310, 0x6310, 0x8310, 0xA310, 0xC310, 0xE310, | ||
684 | 0x0410, 0x2410, 0x4410, 0x6410, 0x8410, 0xA410, 0xC410, 0xE410, | ||
685 | 0x0510, 0x2510, 0x4510, 0x6510, 0x8510, 0xA510, 0xC510, 0xE510, | ||
686 | 0x0610, 0x2610, 0x4610, 0x6610, 0x8610, 0xA610, 0xC610, 0xE610, | ||
687 | 0x0710, 0x2710, 0x4710, 0x6710, 0x8710, 0xA710, 0xC710, 0xE710, | ||
688 | 0x0018, 0x2018, 0x4018, 0x6018, 0x8018, 0xA018, 0xC018, 0xE018, | ||
689 | 0x0118, 0x2118, 0x4118, 0x6118, 0x8118, 0xA118, 0xC118, 0xE118, | ||
690 | 0x0218, 0x2218, 0x4218, 0x6218, 0x8218, 0xA218, 0xC218, 0xE218, | ||
691 | 0x0318, 0x2318, 0x4318, 0x6318, 0x8318, 0xA318, 0xC318, 0xE318, | ||
692 | 0x0418, 0x2418, 0x4418, 0x6418, 0x8418, 0xA418, 0xC418, 0xE418, | ||
693 | 0x0518, 0x2518, 0x4518, 0x6518, 0x8518, 0xA518, 0xC518, 0xE518, | ||
694 | 0x0618, 0x2618, 0x4618, 0x6618, 0x8618, 0xA618, 0xC618, 0xE618, | ||
695 | 0x0718, 0x2718, 0x4718, 0x6718, 0x8718, 0xA718, 0xC718, 0xE718 | ||
696 | }; | ||
697 | #endif /* DISP_DEVICE_8BPP */ | ||
698 | |||
699 | static void tmd20qvga_disp_set_rect(int x, int y, int xres, int yres); | ||
700 | static void tmd20qvga_disp_init(struct platform_device *pdev); | ||
701 | static void tmd20qvga_disp_set_contrast(void); | ||
702 | static void tmd20qvga_disp_set_display_area(word start_row, word end_row); | ||
703 | static int tmd20qvga_disp_off(struct platform_device *pdev); | ||
704 | static int tmd20qvga_disp_on(struct platform_device *pdev); | ||
705 | static void tmd20qvga_set_revId(int); | ||
706 | |||
707 | /* future use */ | ||
708 | void tmd20qvga_disp_clear_screen_area(word start_row, word end_row, | ||
709 | word start_column, word end_column); | ||
710 | |||
711 | static void tmd20qvga_set_revId(int id) | ||
712 | { | ||
713 | |||
714 | tmd20qvga_lcd_rev = id; | ||
715 | |||
716 | if (tmd20qvga_lcd_rev == 1) | ||
717 | tmd20qvga_panel_offset = 0x10; | ||
718 | else | ||
719 | tmd20qvga_panel_offset = 0; | ||
720 | } | ||
721 | |||
722 | static void tmd20qvga_disp_init(struct platform_device *pdev) | ||
723 | { | ||
724 | struct msm_fb_data_type *mfd; | ||
725 | |||
726 | if (disp_initialized) | ||
727 | return; | ||
728 | |||
729 | mfd = platform_get_drvdata(pdev); | ||
730 | |||
731 | DISP_CMD_PORT = mfd->cmd_port; | ||
732 | DISP_DATA_PORT = mfd->data_port; | ||
733 | |||
734 | #ifdef TMD20QVGA_LCD_18BPP | ||
735 | tmd20qvga_set_revId(2); | ||
736 | #else | ||
737 | tmd20qvga_set_revId(1); | ||
738 | #endif | ||
739 | |||
740 | disp_initialized = TRUE; | ||
741 | tmd20qvga_disp_set_contrast(); | ||
742 | tmd20qvga_disp_set_display_area(0, QVGA_HEIGHT - 1); | ||
743 | } | ||
744 | |||
745 | static void tmd20qvga_disp_set_rect(int x, int y, int xres, int yres) | ||
746 | { | ||
747 | if (!disp_initialized) | ||
748 | return; | ||
749 | |||
750 | DISP_SET_RECT(y, y + yres - 1, x, x + xres - 1); | ||
751 | |||
752 | DISP_CMD_OUT(DISP_CMD_RAMWR); | ||
753 | } | ||
754 | |||
755 | static void tmd20qvga_disp_set_display_area(word start_row, word end_row) | ||
756 | { | ||
757 | word start_driving = start_row; | ||
758 | word end_driving = end_row; | ||
759 | |||
760 | if (!disp_initialized) | ||
761 | return; | ||
762 | |||
763 | /* Range checking | ||
764 | */ | ||
765 | if (end_driving >= QVGA_HEIGHT) | ||
766 | end_driving = QVGA_HEIGHT - 1; | ||
767 | if (start_driving > end_driving) { | ||
768 | /* Probably Backwards Switch */ | ||
769 | start_driving = end_driving; | ||
770 | end_driving = start_row; /* Has not changed */ | ||
771 | if (end_driving >= QVGA_HEIGHT) | ||
772 | end_driving = QVGA_HEIGHT - 1; | ||
773 | } | ||
774 | |||
775 | if ((start_driving == disp_area_start_row) | ||
776 | && (end_driving == disp_area_end_row)) | ||
777 | return; | ||
778 | |||
779 | disp_area_start_row = start_driving; | ||
780 | disp_area_end_row = end_driving; | ||
781 | |||
782 | DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_1_ADDR, | ||
783 | DISP_VAL_IF(start_driving & 0x100, | ||
784 | DISP_BITMASK_SS18) | | ||
785 | DISP_VAL_IF(start_driving & 0x080, | ||
786 | DISP_BITMASK_SS17) | | ||
787 | DISP_VAL_IF(start_driving & 0x040, | ||
788 | DISP_BITMASK_SS16) | | ||
789 | DISP_VAL_IF(start_driving & 0x020, | ||
790 | DISP_BITMASK_SS15) | | ||
791 | DISP_VAL_IF(start_driving & 0x010, | ||
792 | DISP_BITMASK_SS14) | | ||
793 | DISP_VAL_IF(start_driving & 0x008, | ||
794 | DISP_BITMASK_SS13) | | ||
795 | DISP_VAL_IF(start_driving & 0x004, | ||
796 | DISP_BITMASK_SS12) | | ||
797 | DISP_VAL_IF(start_driving & 0x002, | ||
798 | DISP_BITMASK_SS11) | | ||
799 | DISP_VAL_IF(start_driving & 0x001, DISP_BITMASK_SS10)); | ||
800 | |||
801 | DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_2_ADDR, | ||
802 | DISP_VAL_IF(end_driving & 0x100, DISP_BITMASK_SE18) | | ||
803 | DISP_VAL_IF(end_driving & 0x080, DISP_BITMASK_SE17) | | ||
804 | DISP_VAL_IF(end_driving & 0x040, DISP_BITMASK_SE16) | | ||
805 | DISP_VAL_IF(end_driving & 0x020, DISP_BITMASK_SE15) | | ||
806 | DISP_VAL_IF(end_driving & 0x010, DISP_BITMASK_SE14) | | ||
807 | DISP_VAL_IF(end_driving & 0x008, DISP_BITMASK_SE13) | | ||
808 | DISP_VAL_IF(end_driving & 0x004, DISP_BITMASK_SE12) | | ||
809 | DISP_VAL_IF(end_driving & 0x002, DISP_BITMASK_SE11) | | ||
810 | DISP_VAL_IF(end_driving & 0x001, DISP_BITMASK_SE10)); | ||
811 | } | ||
812 | |||
813 | static int tmd20qvga_disp_off(struct platform_device *pdev) | ||
814 | { | ||
815 | if (!disp_initialized) | ||
816 | tmd20qvga_disp_init(pdev); | ||
817 | |||
818 | if (display_on) { | ||
819 | if (tmd20qvga_lcd_rev == 2) { | ||
820 | DISP_WRITE_OUT(DISP_POFF_LN_SETTING_ADDR, 0x000A); | ||
821 | DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xFFEE); | ||
822 | WAIT_MSEC(40); | ||
823 | DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xF812); | ||
824 | WAIT_MSEC(40); | ||
825 | DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xE811); | ||
826 | WAIT_MSEC(40); | ||
827 | DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xC011); | ||
828 | WAIT_MSEC(40); | ||
829 | DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x4011); | ||
830 | WAIT_MSEC(20); | ||
831 | DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0010); | ||
832 | |||
833 | } else { | ||
834 | DISP_WRITE_OUT(DISP_POFF_LN_SETTING_ADDR, 0x000F); | ||
835 | DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0BFE); | ||
836 | DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100); | ||
837 | WAIT_MSEC(40); | ||
838 | DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0BED); | ||
839 | DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100); | ||
840 | WAIT_MSEC(40); | ||
841 | DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x00CD); | ||
842 | DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100); | ||
843 | WAIT_MSEC(20); | ||
844 | DISP_WRITE_OUT(DISP_START_OSCILLATION_ADDR, 0x0); | ||
845 | } | ||
846 | |||
847 | DISP_WRITE_OUT(DISP_MODE_SETTING_ADDR, 0x0004); | ||
848 | DISP_WRITE_OUT(DISP_MODE_SETTING_ADDR, 0x0000); | ||
849 | |||
850 | display_on = FALSE; | ||
851 | } | ||
852 | |||
853 | return 0; | ||
854 | } | ||
855 | |||
856 | static int tmd20qvga_disp_on(struct platform_device *pdev) | ||
857 | { | ||
858 | if (!disp_initialized) | ||
859 | tmd20qvga_disp_init(pdev); | ||
860 | |||
861 | if (!display_on) { | ||
862 | /* Deep Stand-by -> Stand-by */ | ||
863 | DISP_CMD_OUT(DISP_START_OSCILLATION_ADDR); | ||
864 | WAIT_MSEC(1); | ||
865 | DISP_CMD_OUT(DISP_START_OSCILLATION_ADDR); | ||
866 | WAIT_MSEC(1); | ||
867 | DISP_CMD_OUT(DISP_START_OSCILLATION_ADDR); | ||
868 | WAIT_MSEC(1); | ||
869 | |||
870 | /* OFF -> Deep Stan-By -> Stand-by */ | ||
871 | /* let's change the state from "Stand-by" to "Sleep" */ | ||
872 | DISP_WRITE_OUT(DISP_MODE_SETTING_ADDR, 0x0005); | ||
873 | WAIT_MSEC(1); | ||
874 | |||
875 | /* Sleep -> Displaying */ | ||
876 | DISP_WRITE_OUT(DISP_START_OSCILLATION_ADDR, 0x0001); | ||
877 | DISP_WRITE_OUT(DISP_DRIVER_OUTPUT_CTL_ADDR, 0x0127); | ||
878 | DISP_WRITE_OUT(DISP_LCD_DRIVING_SIG_ADDR, 0x200); | ||
879 | /* fast write mode */ | ||
880 | DISP_WRITE_OUT(DISP_ENTRY_MODE_ADDR, 0x0130); | ||
881 | if (tmd20qvga_lcd_rev == 2) | ||
882 | DISP_WRITE_OUT(DISP_TMD_700_ADDR, 0x0003); | ||
883 | /* back porch = 14 + front porch = 2 --> 16 lines */ | ||
884 | if (tmd20qvga_lcd_rev == 2) { | ||
885 | #ifdef TMD20QVGA_LCD_18BPP | ||
886 | /* 256k color */ | ||
887 | DISP_WRITE_OUT(DISP_DISPLAY_CTL_1_ADDR, 0x0000); | ||
888 | #else | ||
889 | /* 65k color */ | ||
890 | DISP_WRITE_OUT(DISP_DISPLAY_CTL_1_ADDR, 0x4000); | ||
891 | #endif | ||
892 | DISP_WRITE_OUT(DISP_DISPLAY_CTL_2_ADDR, 0x0302); | ||
893 | } else { | ||
894 | #ifdef TMD20QVGA_LCD_18BPP | ||
895 | /* 256k color */ | ||
896 | DISP_WRITE_OUT(DISP_DISPLAY_CTL_1_ADDR, 0x0004); | ||
897 | #else | ||
898 | /* 65k color */ | ||
899 | DISP_WRITE_OUT(DISP_DISPLAY_CTL_1_ADDR, 0x4004); | ||
900 | #endif | ||
901 | DISP_WRITE_OUT(DISP_DISPLAY_CTL_2_ADDR, 0x020E); | ||
902 | } | ||
903 | /* 16 bit one transfer */ | ||
904 | if (tmd20qvga_lcd_rev == 2) { | ||
905 | DISP_WRITE_OUT(DISP_EXT_DISPLAY_CTL_1_ADDR, 0x0000); | ||
906 | DISP_WRITE_OUT(DISP_FRAME_CYCLE_CTL_ADDR, 0x0010); | ||
907 | DISP_WRITE_OUT(DISP_LTPS_CTL_1_ADDR, 0x0302); | ||
908 | DISP_WRITE_OUT(DISP_LTPS_CTL_2_ADDR, 0x0102); | ||
909 | DISP_WRITE_OUT(DISP_LTPS_CTL_3_ADDR, 0x0000); | ||
910 | DISP_WRITE_OUT(DISP_TMD_015_ADDR, 0x2000); | ||
911 | |||
912 | DISP_WRITE_OUT(DISP_AMP_SETTING_ADDR, 0x0000); | ||
913 | DISP_WRITE_OUT(DISP_GAMMA_CONTROL_1_ADDR, 0x0403); | ||
914 | DISP_WRITE_OUT(DISP_GAMMA_CONTROL_2_ADDR, 0x0304); | ||
915 | DISP_WRITE_OUT(DISP_GAMMA_CONTROL_3_ADDR, 0x0403); | ||
916 | DISP_WRITE_OUT(DISP_GAMMA_CONTROL_4_ADDR, 0x0303); | ||
917 | DISP_WRITE_OUT(DISP_GAMMA_CONTROL_5_ADDR, 0x0101); | ||
918 | DISP_WRITE_OUT(DISP_TMD_305_ADDR, 0); | ||
919 | |||
920 | DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_1_ADDR, 0x0000); | ||
921 | DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_2_ADDR, 0x013F); | ||
922 | |||
923 | DISP_WRITE_OUT(DISP_POWER_CTL_3_ADDR, 0x077D); | ||
924 | |||
925 | DISP_WRITE_OUT(DISP_POWER_CTL_4_ADDR, 0x0005); | ||
926 | DISP_WRITE_OUT(DISP_POWER_CTL_5_ADDR, 0x0000); | ||
927 | DISP_WRITE_OUT(DISP_POWER_CTL_6_ADDR, 0x0015); | ||
928 | DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xC010); | ||
929 | WAIT_MSEC(1); | ||
930 | |||
931 | DISP_WRITE_OUT(DISP_POWER_CTL_2_ADDR, 0x0001); | ||
932 | DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0xFFFE); | ||
933 | WAIT_MSEC(60); | ||
934 | } else { | ||
935 | DISP_WRITE_OUT(DISP_EXT_DISPLAY_CTL_1_ADDR, 0x0001); | ||
936 | DISP_WRITE_OUT(DISP_FRAME_CYCLE_CTL_ADDR, 0x0010); | ||
937 | DISP_WRITE_OUT(DISP_LTPS_CTL_1_ADDR, 0x0301); | ||
938 | DISP_WRITE_OUT(DISP_LTPS_CTL_2_ADDR, 0x0001); | ||
939 | DISP_WRITE_OUT(DISP_LTPS_CTL_3_ADDR, 0x0000); | ||
940 | DISP_WRITE_OUT(DISP_AMP_SETTING_ADDR, 0x0000); | ||
941 | DISP_WRITE_OUT(DISP_GAMMA_CONTROL_1_ADDR, 0x0507); | ||
942 | DISP_WRITE_OUT(DISP_GAMMA_CONTROL_2_ADDR, 0x0405); | ||
943 | DISP_WRITE_OUT(DISP_GAMMA_CONTROL_3_ADDR, 0x0607); | ||
944 | DISP_WRITE_OUT(DISP_GAMMA_CONTROL_4_ADDR, 0x0502); | ||
945 | DISP_WRITE_OUT(DISP_GAMMA_CONTROL_5_ADDR, 0x0301); | ||
946 | DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_1_ADDR, 0x0000); | ||
947 | DISP_WRITE_OUT(DISP_SCREEN_1_DRV_POS_2_ADDR, 0x013F); | ||
948 | DISP_WRITE_OUT(DISP_POWER_CTL_3_ADDR, 0x0795); | ||
949 | |||
950 | DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0102); | ||
951 | WAIT_MSEC(1); | ||
952 | |||
953 | DISP_WRITE_OUT(DISP_POWER_CTL_4_ADDR, 0x0450); | ||
954 | DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0103); | ||
955 | WAIT_MSEC(1); | ||
956 | |||
957 | DISP_WRITE_OUT(DISP_POWER_CTL_5_ADDR, 0x0008); | ||
958 | DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0104); | ||
959 | WAIT_MSEC(1); | ||
960 | |||
961 | DISP_WRITE_OUT(DISP_POWER_CTL_6_ADDR, 0x0C00); | ||
962 | DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0105); | ||
963 | WAIT_MSEC(1); | ||
964 | |||
965 | DISP_WRITE_OUT(DISP_POWER_CTL_7_ADDR, 0x0000); | ||
966 | DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0106); | ||
967 | WAIT_MSEC(1); | ||
968 | |||
969 | DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0801); | ||
970 | DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100); | ||
971 | WAIT_MSEC(1); | ||
972 | |||
973 | DISP_WRITE_OUT(DISP_POWER_CTL_2_ADDR, 0x001F); | ||
974 | DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0101); | ||
975 | WAIT_MSEC(60); | ||
976 | |||
977 | DISP_WRITE_OUT(DISP_POWER_CTL_2_ADDR, 0x009F); | ||
978 | DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0101); | ||
979 | WAIT_MSEC(10); | ||
980 | |||
981 | DISP_WRITE_OUT(DISP_HORZ_RAM_ADDR_POS_1_ADDR, 0x0010); | ||
982 | DISP_WRITE_OUT(DISP_HORZ_RAM_ADDR_POS_2_ADDR, 0x00FF); | ||
983 | DISP_WRITE_OUT(DISP_VERT_RAM_ADDR_POS_1_ADDR, 0x0000); | ||
984 | DISP_WRITE_OUT(DISP_VERT_RAM_ADDR_POS_2_ADDR, 0x013F); | ||
985 | /* RAM starts at address 0x10 */ | ||
986 | DISP_WRITE_OUT(DISP_RAM_ADDR_SET_1_ADDR, 0x0010); | ||
987 | DISP_WRITE_OUT(DISP_RAM_ADDR_SET_2_ADDR, 0x0000); | ||
988 | |||
989 | /* lcd controller uses internal clock, not ext. vsync */ | ||
990 | DISP_CMD_OUT(DISP_CMD_RAMWR); | ||
991 | |||
992 | DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0881); | ||
993 | DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100); | ||
994 | WAIT_MSEC(40); | ||
995 | |||
996 | DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0BE1); | ||
997 | DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100); | ||
998 | WAIT_MSEC(40); | ||
999 | |||
1000 | DISP_WRITE_OUT(DISP_POWER_CTL_1_ADDR, 0x0BFF); | ||
1001 | DISP_WRITE_OUT(DISP_POWER_SUPPLY_INTF_ADDR, 0x0100); | ||
1002 | } | ||
1003 | display_on = TRUE; | ||
1004 | } | ||
1005 | |||
1006 | return 0; | ||
1007 | } | ||
1008 | |||
1009 | static void tmd20qvga_disp_set_contrast(void) | ||
1010 | { | ||
1011 | #if (defined(TMD20QVGA_LCD_18BPP)) | ||
1012 | |||
1013 | DISP_WRITE_OUT(DISP_GAMMA_CONTROL_1_ADDR, 0x0403); | ||
1014 | DISP_WRITE_OUT(DISP_GAMMA_CONTROL_2_ADDR, 0x0302); | ||
1015 | DISP_WRITE_OUT(DISP_GAMMA_CONTROL_3_ADDR, 0x0403); | ||
1016 | DISP_WRITE_OUT(DISP_GAMMA_CONTROL_4_ADDR, 0x0303); | ||
1017 | DISP_WRITE_OUT(DISP_GAMMA_CONTROL_5_ADDR, 0x0F07); | ||
1018 | |||
1019 | #else | ||
1020 | int newcontrast = 0x46; | ||
1021 | |||
1022 | DISP_WRITE_OUT(DISP_GAMMA_CONTROL_1_ADDR, 0x0403); | ||
1023 | |||
1024 | DISP_WRITE_OUT(DISP_GAMMA_CONTROL_2_ADDR, | ||
1025 | DISP_VAL_IF(newcontrast & 0x0001, DISP_BITMASK_PKP20) | | ||
1026 | DISP_VAL_IF(newcontrast & 0x0002, DISP_BITMASK_PKP21) | | ||
1027 | DISP_VAL_IF(newcontrast & 0x0004, DISP_BITMASK_PKP22) | | ||
1028 | DISP_VAL_IF(newcontrast & 0x0010, DISP_BITMASK_PKP30) | | ||
1029 | DISP_VAL_IF(newcontrast & 0x0020, DISP_BITMASK_PKP31) | | ||
1030 | DISP_VAL_IF(newcontrast & 0x0040, DISP_BITMASK_PKP32)); | ||
1031 | |||
1032 | DISP_WRITE_OUT(DISP_GAMMA_CONTROL_3_ADDR, | ||
1033 | DISP_VAL_IF(newcontrast & 0x0010, DISP_BITMASK_PKP40) | | ||
1034 | DISP_VAL_IF(newcontrast & 0x0020, DISP_BITMASK_PKP41) | | ||
1035 | DISP_VAL_IF(newcontrast & 0x0040, DISP_BITMASK_PKP42) | | ||
1036 | DISP_VAL_IF(newcontrast & 0x0001, DISP_BITMASK_PKP50) | | ||
1037 | DISP_VAL_IF(newcontrast & 0x0002, DISP_BITMASK_PKP51) | | ||
1038 | DISP_VAL_IF(newcontrast & 0x0004, DISP_BITMASK_PKP52)); | ||
1039 | |||
1040 | DISP_WRITE_OUT(DISP_GAMMA_CONTROL_4_ADDR, 0x0303); | ||
1041 | DISP_WRITE_OUT(DISP_GAMMA_CONTROL_5_ADDR, 0x0F07); | ||
1042 | |||
1043 | #endif /* defined(TMD20QVGA_LCD_18BPP) */ | ||
1044 | |||
1045 | } /* End disp_set_contrast */ | ||
1046 | |||
1047 | void tmd20qvga_disp_clear_screen_area | ||
1048 | (word start_row, word end_row, word start_column, word end_column) { | ||
1049 | int32 i; | ||
1050 | |||
1051 | /* Clear the display screen */ | ||
1052 | DISP_SET_RECT(start_row, end_row, start_column, end_column); | ||
1053 | DISP_CMD_OUT(DISP_CMD_RAMWR); | ||
1054 | i = (end_row - start_row + 1) * (end_column - start_column + 1); | ||
1055 | for (; i > 0; i--) | ||
1056 | DISP_DATA_OUT_16TO18BPP(0x0); | ||
1057 | } | ||
1058 | |||
1059 | static int __init tmd20qvga_probe(struct platform_device *pdev) | ||
1060 | { | ||
1061 | msm_fb_add_device(pdev); | ||
1062 | |||
1063 | return 0; | ||
1064 | } | ||
1065 | |||
1066 | static struct platform_driver this_driver = { | ||
1067 | .probe = tmd20qvga_probe, | ||
1068 | .driver = { | ||
1069 | .name = "ebi2_tmd_qvga", | ||
1070 | }, | ||
1071 | }; | ||
1072 | |||
1073 | static struct msm_fb_panel_data tmd20qvga_panel_data = { | ||
1074 | .on = tmd20qvga_disp_on, | ||
1075 | .off = tmd20qvga_disp_off, | ||
1076 | .set_rect = tmd20qvga_disp_set_rect, | ||
1077 | }; | ||
1078 | |||
1079 | static struct platform_device this_device = { | ||
1080 | .name = "ebi2_tmd_qvga", | ||
1081 | .id = 0, | ||
1082 | .dev = { | ||
1083 | .platform_data = &tmd20qvga_panel_data, | ||
1084 | } | ||
1085 | }; | ||
1086 | |||
1087 | static int __init tmd20qvga_init(void) | ||
1088 | { | ||
1089 | int ret; | ||
1090 | struct msm_panel_info *pinfo; | ||
1091 | |||
1092 | ret = platform_driver_register(&this_driver); | ||
1093 | if (!ret) { | ||
1094 | pinfo = &tmd20qvga_panel_data.panel_info; | ||
1095 | pinfo->xres = 240; | ||
1096 | pinfo->yres = 320; | ||
1097 | pinfo->type = EBI2_PANEL; | ||
1098 | pinfo->pdest = DISPLAY_1; | ||
1099 | pinfo->wait_cycle = 0x808000; | ||
1100 | #ifdef TMD20QVGA_LCD_18BPP | ||
1101 | pinfo->bpp = 18; | ||
1102 | #else | ||
1103 | pinfo->bpp = 16; | ||
1104 | #endif | ||
1105 | pinfo->fb_num = 2; | ||
1106 | pinfo->lcd.vsync_enable = TRUE; | ||
1107 | pinfo->lcd.refx100 = 6000; | ||
1108 | pinfo->lcd.v_back_porch = 16; | ||
1109 | pinfo->lcd.v_front_porch = 4; | ||
1110 | pinfo->lcd.v_pulse_width = 0; | ||
1111 | pinfo->lcd.hw_vsync_mode = FALSE; | ||
1112 | pinfo->lcd.vsync_notifier_period = 0; | ||
1113 | |||
1114 | ret = platform_device_register(&this_device); | ||
1115 | if (ret) | ||
1116 | platform_driver_unregister(&this_driver); | ||
1117 | } | ||
1118 | |||
1119 | return ret; | ||
1120 | } | ||
1121 | |||
1122 | module_init(tmd20qvga_init); | ||
diff --git a/drivers/staging/msm/hdmi_sii9022.c b/drivers/staging/msm/hdmi_sii9022.c new file mode 100644 index 000000000000..6b82b56a77b6 --- /dev/null +++ b/drivers/staging/msm/hdmi_sii9022.c | |||
@@ -0,0 +1,248 @@ | |||
1 | /* Copyright (c) 2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include <linux/i2c.h> | ||
19 | #include <linux/delay.h> | ||
20 | #include "msm_fb.h" | ||
21 | |||
22 | #define DEVICE_NAME "sii9022" | ||
23 | #define SII9022_DEVICE_ID 0xB0 | ||
24 | |||
25 | struct sii9022_i2c_addr_data{ | ||
26 | u8 addr; | ||
27 | u8 data; | ||
28 | }; | ||
29 | |||
30 | /* video mode data */ | ||
31 | static u8 video_mode_data[] = { | ||
32 | 0x00, | ||
33 | 0xF9, 0x1C, 0x70, 0x17, 0x72, 0x06, 0xEE, 0x02, | ||
34 | }; | ||
35 | |||
36 | static u8 avi_io_format[] = { | ||
37 | 0x09, | ||
38 | 0x00, 0x00, | ||
39 | }; | ||
40 | |||
41 | /* power state */ | ||
42 | static struct sii9022_i2c_addr_data regset0[] = { | ||
43 | { 0x60, 0x04 }, | ||
44 | { 0x63, 0x00 }, | ||
45 | { 0x1E, 0x00 }, | ||
46 | }; | ||
47 | |||
48 | static u8 video_infoframe[] = { | ||
49 | 0x0C, | ||
50 | 0xF0, 0x00, 0x68, 0x00, 0x04, 0x00, 0x19, 0x00, | ||
51 | 0xE9, 0x02, 0x04, 0x01, 0x04, 0x06, | ||
52 | }; | ||
53 | |||
54 | /* configure audio */ | ||
55 | static struct sii9022_i2c_addr_data regset1[] = { | ||
56 | { 0x26, 0x90 }, | ||
57 | { 0x20, 0x90 }, | ||
58 | { 0x1F, 0x80 }, | ||
59 | { 0x26, 0x80 }, | ||
60 | { 0x24, 0x02 }, | ||
61 | { 0x25, 0x0B }, | ||
62 | { 0xBC, 0x02 }, | ||
63 | { 0xBD, 0x24 }, | ||
64 | { 0xBE, 0x02 }, | ||
65 | }; | ||
66 | |||
67 | /* enable audio */ | ||
68 | static u8 misc_infoframe[] = { | ||
69 | 0xBF, | ||
70 | 0xC2, 0x84, 0x01, 0x0A, 0x6F, 0x02, 0x00, 0x00, | ||
71 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
72 | }; | ||
73 | |||
74 | /* set HDMI, active */ | ||
75 | static struct sii9022_i2c_addr_data regset2[] = { | ||
76 | { 0x1A, 0x01 }, | ||
77 | { 0x3D, 0x00 }, | ||
78 | }; | ||
79 | |||
80 | static int send_i2c_data(struct i2c_client *client, | ||
81 | struct sii9022_i2c_addr_data *regset, | ||
82 | int size) | ||
83 | { | ||
84 | int i; | ||
85 | int rc = 0; | ||
86 | |||
87 | for (i = 0; i < size; i++) { | ||
88 | rc = i2c_smbus_write_byte_data( | ||
89 | client, | ||
90 | regset[i].addr, regset[i].data); | ||
91 | if (rc) | ||
92 | break; | ||
93 | } | ||
94 | return rc; | ||
95 | } | ||
96 | |||
97 | static int hdmi_sii_enable(struct i2c_client *client) | ||
98 | { | ||
99 | int rc; | ||
100 | int retries = 10; | ||
101 | int count; | ||
102 | |||
103 | rc = i2c_smbus_write_byte_data(client, 0xC7, 0x00); | ||
104 | if (rc) | ||
105 | goto enable_exit; | ||
106 | |||
107 | do { | ||
108 | msleep(1); | ||
109 | rc = i2c_smbus_read_byte_data(client, 0x1B); | ||
110 | } while ((rc != SII9022_DEVICE_ID) && retries--); | ||
111 | |||
112 | if (rc != SII9022_DEVICE_ID) | ||
113 | return -ENODEV; | ||
114 | |||
115 | rc = i2c_smbus_write_byte_data(client, 0x1A, 0x11); | ||
116 | if (rc) | ||
117 | goto enable_exit; | ||
118 | |||
119 | count = ARRAY_SIZE(video_mode_data); | ||
120 | rc = i2c_master_send(client, video_mode_data, count); | ||
121 | if (rc != count) { | ||
122 | rc = -EIO; | ||
123 | goto enable_exit; | ||
124 | } | ||
125 | |||
126 | rc = i2c_smbus_write_byte_data(client, 0x08, 0x20); | ||
127 | if (rc) | ||
128 | goto enable_exit; | ||
129 | count = ARRAY_SIZE(avi_io_format); | ||
130 | rc = i2c_master_send(client, avi_io_format, count); | ||
131 | if (rc != count) { | ||
132 | rc = -EIO; | ||
133 | goto enable_exit; | ||
134 | } | ||
135 | |||
136 | rc = send_i2c_data(client, regset0, ARRAY_SIZE(regset0)); | ||
137 | if (rc) | ||
138 | goto enable_exit; | ||
139 | |||
140 | count = ARRAY_SIZE(video_infoframe); | ||
141 | rc = i2c_master_send(client, video_infoframe, count); | ||
142 | if (rc != count) { | ||
143 | rc = -EIO; | ||
144 | goto enable_exit; | ||
145 | } | ||
146 | |||
147 | rc = send_i2c_data(client, regset1, ARRAY_SIZE(regset1)); | ||
148 | if (rc) | ||
149 | goto enable_exit; | ||
150 | |||
151 | count = ARRAY_SIZE(misc_infoframe); | ||
152 | rc = i2c_master_send(client, misc_infoframe, count); | ||
153 | if (rc != count) { | ||
154 | rc = -EIO; | ||
155 | goto enable_exit; | ||
156 | } | ||
157 | |||
158 | rc = send_i2c_data(client, regset2, ARRAY_SIZE(regset2)); | ||
159 | if (rc) | ||
160 | goto enable_exit; | ||
161 | |||
162 | return 0; | ||
163 | enable_exit: | ||
164 | printk(KERN_ERR "%s: exited rc=%d\n", __func__, rc); | ||
165 | return rc; | ||
166 | } | ||
167 | |||
168 | static const struct i2c_device_id hmdi_sii_id[] = { | ||
169 | { DEVICE_NAME, 0 }, | ||
170 | { } | ||
171 | }; | ||
172 | |||
173 | static int hdmi_sii_probe(struct i2c_client *client, | ||
174 | const struct i2c_device_id *id) | ||
175 | { | ||
176 | int rc; | ||
177 | |||
178 | if (!i2c_check_functionality(client->adapter, | ||
179 | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_I2C)) | ||
180 | return -ENODEV; | ||
181 | rc = hdmi_sii_enable(client); | ||
182 | return rc; | ||
183 | } | ||
184 | |||
185 | |||
186 | static struct i2c_driver hdmi_sii_i2c_driver = { | ||
187 | .driver = { | ||
188 | .name = DEVICE_NAME, | ||
189 | .owner = THIS_MODULE, | ||
190 | }, | ||
191 | .probe = hdmi_sii_probe, | ||
192 | .remove = __exit_p(hdmi_sii_remove), | ||
193 | .id_table = hmdi_sii_id, | ||
194 | }; | ||
195 | |||
196 | static int __init hdmi_sii_init(void) | ||
197 | { | ||
198 | int ret; | ||
199 | struct msm_panel_info pinfo; | ||
200 | |||
201 | if (msm_fb_detect_client("hdmi_sii9022")) | ||
202 | return 0; | ||
203 | |||
204 | pinfo.xres = 1280; | ||
205 | pinfo.yres = 720; | ||
206 | pinfo.type = HDMI_PANEL; | ||
207 | pinfo.pdest = DISPLAY_1; | ||
208 | pinfo.wait_cycle = 0; | ||
209 | pinfo.bpp = 24; | ||
210 | pinfo.fb_num = 2; | ||
211 | pinfo.clk_rate = 74250000; | ||
212 | |||
213 | pinfo.lcdc.h_back_porch = 124; | ||
214 | pinfo.lcdc.h_front_porch = 110; | ||
215 | pinfo.lcdc.h_pulse_width = 136; | ||
216 | pinfo.lcdc.v_back_porch = 19; | ||
217 | pinfo.lcdc.v_front_porch = 5; | ||
218 | pinfo.lcdc.v_pulse_width = 6; | ||
219 | pinfo.lcdc.border_clr = 0; | ||
220 | pinfo.lcdc.underflow_clr = 0xff; | ||
221 | pinfo.lcdc.hsync_skew = 0; | ||
222 | |||
223 | ret = lcdc_device_register(&pinfo); | ||
224 | if (ret) { | ||
225 | printk(KERN_ERR "%s: failed to register device\n", __func__); | ||
226 | goto init_exit; | ||
227 | } | ||
228 | |||
229 | ret = i2c_add_driver(&hdmi_sii_i2c_driver); | ||
230 | if (ret) | ||
231 | printk(KERN_ERR "%s: failed to add i2c driver\n", __func__); | ||
232 | |||
233 | init_exit: | ||
234 | return ret; | ||
235 | } | ||
236 | |||
237 | static void __exit hdmi_sii_exit(void) | ||
238 | { | ||
239 | i2c_del_driver(&hdmi_sii_i2c_driver); | ||
240 | } | ||
241 | |||
242 | module_init(hdmi_sii_init); | ||
243 | module_exit(hdmi_sii_exit); | ||
244 | MODULE_LICENSE("GPL v2"); | ||
245 | MODULE_VERSION("0.1"); | ||
246 | MODULE_AUTHOR("Qualcomm Innovation Center, Inc."); | ||
247 | MODULE_DESCRIPTION("SiI9022 HDMI driver"); | ||
248 | MODULE_ALIAS("platform:hdmi-sii9022"); | ||
diff --git a/drivers/staging/msm/lcdc.c b/drivers/staging/msm/lcdc.c new file mode 100644 index 000000000000..735280ab72cb --- /dev/null +++ b/drivers/staging/msm/lcdc.c | |||
@@ -0,0 +1,239 @@ | |||
1 | /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/sched.h> | ||
21 | #include <linux/time.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/spinlock.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <mach/hardware.h> | ||
27 | #include <linux/io.h> | ||
28 | |||
29 | #include <asm/system.h> | ||
30 | #include <asm/mach-types.h> | ||
31 | #include <linux/semaphore.h> | ||
32 | #include <linux/uaccess.h> | ||
33 | #include <linux/clk.h> | ||
34 | #include <linux/platform_device.h> | ||
35 | #include <linux/pm_qos_params.h> | ||
36 | |||
37 | #include "msm_fb.h" | ||
38 | |||
39 | static int lcdc_probe(struct platform_device *pdev); | ||
40 | static int lcdc_remove(struct platform_device *pdev); | ||
41 | |||
42 | static int lcdc_off(struct platform_device *pdev); | ||
43 | static int lcdc_on(struct platform_device *pdev); | ||
44 | |||
45 | static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST]; | ||
46 | static int pdev_list_cnt; | ||
47 | |||
48 | static struct clk *mdp_lcdc_pclk_clk; | ||
49 | static struct clk *mdp_lcdc_pad_pclk_clk; | ||
50 | |||
51 | int mdp_lcdc_pclk_clk_rate; | ||
52 | int mdp_lcdc_pad_pclk_clk_rate; | ||
53 | |||
54 | static struct platform_driver lcdc_driver = { | ||
55 | .probe = lcdc_probe, | ||
56 | .remove = lcdc_remove, | ||
57 | .suspend = NULL, | ||
58 | .resume = NULL, | ||
59 | .shutdown = NULL, | ||
60 | .driver = { | ||
61 | .name = "lcdc", | ||
62 | }, | ||
63 | }; | ||
64 | |||
65 | static struct lcdc_platform_data *lcdc_pdata; | ||
66 | |||
67 | static int lcdc_off(struct platform_device *pdev) | ||
68 | { | ||
69 | int ret = 0; | ||
70 | |||
71 | ret = panel_next_off(pdev); | ||
72 | |||
73 | clk_disable(mdp_lcdc_pclk_clk); | ||
74 | clk_disable(mdp_lcdc_pad_pclk_clk); | ||
75 | |||
76 | if (lcdc_pdata && lcdc_pdata->lcdc_power_save) | ||
77 | lcdc_pdata->lcdc_power_save(0); | ||
78 | |||
79 | if (lcdc_pdata && lcdc_pdata->lcdc_gpio_config) | ||
80 | ret = lcdc_pdata->lcdc_gpio_config(0); | ||
81 | |||
82 | // pm_qos_update_requirement(PM_QOS_SYSTEM_BUS_FREQ , "lcdc", | ||
83 | // PM_QOS_DEFAULT_VALUE); | ||
84 | |||
85 | return ret; | ||
86 | } | ||
87 | |||
88 | static int lcdc_on(struct platform_device *pdev) | ||
89 | { | ||
90 | int ret = 0; | ||
91 | struct msm_fb_data_type *mfd; | ||
92 | unsigned long panel_pixclock_freq , pm_qos_freq; | ||
93 | |||
94 | mfd = platform_get_drvdata(pdev); | ||
95 | panel_pixclock_freq = mfd->fbi->var.pixclock; | ||
96 | |||
97 | if (panel_pixclock_freq > 58000000) | ||
98 | /* pm_qos_freq should be in Khz */ | ||
99 | pm_qos_freq = panel_pixclock_freq / 1000 ; | ||
100 | else | ||
101 | pm_qos_freq = 58000; | ||
102 | |||
103 | // pm_qos_update_requirement(PM_QOS_SYSTEM_BUS_FREQ , "lcdc", | ||
104 | // pm_qos_freq); | ||
105 | mfd = platform_get_drvdata(pdev); | ||
106 | |||
107 | clk_enable(mdp_lcdc_pclk_clk); | ||
108 | clk_enable(mdp_lcdc_pad_pclk_clk); | ||
109 | |||
110 | if (lcdc_pdata && lcdc_pdata->lcdc_power_save) | ||
111 | lcdc_pdata->lcdc_power_save(1); | ||
112 | if (lcdc_pdata && lcdc_pdata->lcdc_gpio_config) | ||
113 | ret = lcdc_pdata->lcdc_gpio_config(1); | ||
114 | |||
115 | clk_set_rate(mdp_lcdc_pclk_clk, mfd->fbi->var.pixclock); | ||
116 | clk_set_rate(mdp_lcdc_pad_pclk_clk, mfd->fbi->var.pixclock); | ||
117 | mdp_lcdc_pclk_clk_rate = clk_get_rate(mdp_lcdc_pclk_clk); | ||
118 | mdp_lcdc_pad_pclk_clk_rate = clk_get_rate(mdp_lcdc_pad_pclk_clk); | ||
119 | |||
120 | ret = panel_next_on(pdev); | ||
121 | return ret; | ||
122 | } | ||
123 | |||
124 | static int lcdc_probe(struct platform_device *pdev) | ||
125 | { | ||
126 | struct msm_fb_data_type *mfd; | ||
127 | struct fb_info *fbi; | ||
128 | struct platform_device *mdp_dev = NULL; | ||
129 | struct msm_fb_panel_data *pdata = NULL; | ||
130 | int rc; | ||
131 | |||
132 | if (pdev->id == 0) { | ||
133 | lcdc_pdata = pdev->dev.platform_data; | ||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | mfd = platform_get_drvdata(pdev); | ||
138 | |||
139 | if (!mfd) | ||
140 | return -ENODEV; | ||
141 | |||
142 | if (mfd->key != MFD_KEY) | ||
143 | return -EINVAL; | ||
144 | |||
145 | if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST) | ||
146 | return -ENOMEM; | ||
147 | |||
148 | mdp_dev = platform_device_alloc("mdp", pdev->id); | ||
149 | if (!mdp_dev) | ||
150 | return -ENOMEM; | ||
151 | |||
152 | /* | ||
153 | * link to the latest pdev | ||
154 | */ | ||
155 | mfd->pdev = mdp_dev; | ||
156 | mfd->dest = DISPLAY_LCDC; | ||
157 | |||
158 | /* | ||
159 | * alloc panel device data | ||
160 | */ | ||
161 | if (platform_device_add_data | ||
162 | (mdp_dev, pdev->dev.platform_data, | ||
163 | sizeof(struct msm_fb_panel_data))) { | ||
164 | printk(KERN_ERR "lcdc_probe: platform_device_add_data failed!\n"); | ||
165 | platform_device_put(mdp_dev); | ||
166 | return -ENOMEM; | ||
167 | } | ||
168 | /* | ||
169 | * data chain | ||
170 | */ | ||
171 | pdata = (struct msm_fb_panel_data *)mdp_dev->dev.platform_data; | ||
172 | pdata->on = lcdc_on; | ||
173 | pdata->off = lcdc_off; | ||
174 | pdata->next = pdev; | ||
175 | |||
176 | /* | ||
177 | * get/set panel specific fb info | ||
178 | */ | ||
179 | mfd->panel_info = pdata->panel_info; | ||
180 | mfd->fb_imgType = MDP_RGB_565; | ||
181 | |||
182 | fbi = mfd->fbi; | ||
183 | fbi->var.pixclock = mfd->panel_info.clk_rate; | ||
184 | fbi->var.left_margin = mfd->panel_info.lcdc.h_back_porch; | ||
185 | fbi->var.right_margin = mfd->panel_info.lcdc.h_front_porch; | ||
186 | fbi->var.upper_margin = mfd->panel_info.lcdc.v_back_porch; | ||
187 | fbi->var.lower_margin = mfd->panel_info.lcdc.v_front_porch; | ||
188 | fbi->var.hsync_len = mfd->panel_info.lcdc.h_pulse_width; | ||
189 | fbi->var.vsync_len = mfd->panel_info.lcdc.v_pulse_width; | ||
190 | |||
191 | /* | ||
192 | * set driver data | ||
193 | */ | ||
194 | platform_set_drvdata(mdp_dev, mfd); | ||
195 | |||
196 | /* | ||
197 | * register in mdp driver | ||
198 | */ | ||
199 | rc = platform_device_add(mdp_dev); | ||
200 | if (rc) | ||
201 | goto lcdc_probe_err; | ||
202 | |||
203 | pdev_list[pdev_list_cnt++] = pdev; | ||
204 | return 0; | ||
205 | |||
206 | lcdc_probe_err: | ||
207 | platform_device_put(mdp_dev); | ||
208 | return rc; | ||
209 | } | ||
210 | |||
211 | static int lcdc_remove(struct platform_device *pdev) | ||
212 | { | ||
213 | // pm_qos_remove_requirement(PM_QOS_SYSTEM_BUS_FREQ , "lcdc"); | ||
214 | return 0; | ||
215 | } | ||
216 | |||
217 | static int lcdc_register_driver(void) | ||
218 | { | ||
219 | return platform_driver_register(&lcdc_driver); | ||
220 | } | ||
221 | |||
222 | static int __init lcdc_driver_init(void) | ||
223 | { | ||
224 | mdp_lcdc_pclk_clk = clk_get(NULL, "mdp_lcdc_pclk_clk"); | ||
225 | if (IS_ERR(mdp_lcdc_pclk_clk)) { | ||
226 | printk(KERN_ERR "error: can't get mdp_lcdc_pclk_clk!\n"); | ||
227 | return IS_ERR(mdp_lcdc_pclk_clk); | ||
228 | } | ||
229 | mdp_lcdc_pad_pclk_clk = clk_get(NULL, "mdp_lcdc_pad_pclk_clk"); | ||
230 | if (IS_ERR(mdp_lcdc_pad_pclk_clk)) { | ||
231 | printk(KERN_ERR "error: can't get mdp_lcdc_pad_pclk_clk!\n"); | ||
232 | return IS_ERR(mdp_lcdc_pad_pclk_clk); | ||
233 | } | ||
234 | // pm_qos_add_requirement(PM_QOS_SYSTEM_BUS_FREQ , "lcdc", | ||
235 | // PM_QOS_DEFAULT_VALUE); | ||
236 | return lcdc_register_driver(); | ||
237 | } | ||
238 | |||
239 | module_init(lcdc_driver_init); | ||
diff --git a/drivers/staging/msm/lcdc_external.c b/drivers/staging/msm/lcdc_external.c new file mode 100644 index 000000000000..45ff78527111 --- /dev/null +++ b/drivers/staging/msm/lcdc_external.c | |||
@@ -0,0 +1,54 @@ | |||
1 | /* Copyright (c) 2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include "msm_fb.h" | ||
19 | |||
20 | static int __init lcdc_external_init(void) | ||
21 | { | ||
22 | int ret; | ||
23 | struct msm_panel_info pinfo; | ||
24 | |||
25 | if (msm_fb_detect_client("lcdc_external")) | ||
26 | return 0; | ||
27 | |||
28 | pinfo.xres = 1280; | ||
29 | pinfo.yres = 720; | ||
30 | pinfo.type = LCDC_PANEL; | ||
31 | pinfo.pdest = DISPLAY_1; | ||
32 | pinfo.wait_cycle = 0; | ||
33 | pinfo.bpp = 24; | ||
34 | pinfo.fb_num = 2; | ||
35 | pinfo.clk_rate = 74250000; | ||
36 | |||
37 | pinfo.lcdc.h_back_porch = 124; | ||
38 | pinfo.lcdc.h_front_porch = 110; | ||
39 | pinfo.lcdc.h_pulse_width = 136; | ||
40 | pinfo.lcdc.v_back_porch = 19; | ||
41 | pinfo.lcdc.v_front_porch = 5; | ||
42 | pinfo.lcdc.v_pulse_width = 6; | ||
43 | pinfo.lcdc.border_clr = 0; /* blk */ | ||
44 | pinfo.lcdc.underflow_clr = 0xff; /* blue */ | ||
45 | pinfo.lcdc.hsync_skew = 0; | ||
46 | |||
47 | ret = lcdc_device_register(&pinfo); | ||
48 | if (ret) | ||
49 | printk(KERN_ERR "%s: failed to register device!\n", __func__); | ||
50 | |||
51 | return ret; | ||
52 | } | ||
53 | |||
54 | module_init(lcdc_external_init); | ||
diff --git a/drivers/staging/msm/lcdc_gordon.c b/drivers/staging/msm/lcdc_gordon.c new file mode 100644 index 000000000000..399ec8c791ec --- /dev/null +++ b/drivers/staging/msm/lcdc_gordon.c | |||
@@ -0,0 +1,446 @@ | |||
1 | /* Copyright (c) 2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include <linux/delay.h> | ||
19 | #include <mach/gpio.h> | ||
20 | #include "msm_fb.h" | ||
21 | |||
22 | /* registers */ | ||
23 | #define GORDON_REG_NOP 0x00 | ||
24 | #define GORDON_REG_IMGCTL1 0x10 | ||
25 | #define GORDON_REG_IMGCTL2 0x11 | ||
26 | #define GORDON_REG_IMGSET1 0x12 | ||
27 | #define GORDON_REG_IMGSET2 0x13 | ||
28 | #define GORDON_REG_IVBP1 0x14 | ||
29 | #define GORDON_REG_IHBP1 0x15 | ||
30 | #define GORDON_REG_IVNUM1 0x16 | ||
31 | #define GORDON_REG_IHNUM1 0x17 | ||
32 | #define GORDON_REG_IVBP2 0x18 | ||
33 | #define GORDON_REG_IHBP2 0x19 | ||
34 | #define GORDON_REG_IVNUM2 0x1A | ||
35 | #define GORDON_REG_IHNUM2 0x1B | ||
36 | #define GORDON_REG_LCDIFCTL1 0x30 | ||
37 | #define GORDON_REG_VALTRAN 0x31 | ||
38 | #define GORDON_REG_AVCTL 0x33 | ||
39 | #define GORDON_REG_LCDIFCTL2 0x34 | ||
40 | #define GORDON_REG_LCDIFCTL3 0x35 | ||
41 | #define GORDON_REG_LCDIFSET1 0x36 | ||
42 | #define GORDON_REG_PCCTL 0x3C | ||
43 | #define GORDON_REG_TPARAM1 0x40 | ||
44 | #define GORDON_REG_TLCDIF1 0x41 | ||
45 | #define GORDON_REG_TSSPB_ST1 0x42 | ||
46 | #define GORDON_REG_TSSPB_ED1 0x43 | ||
47 | #define GORDON_REG_TSCK_ST1 0x44 | ||
48 | #define GORDON_REG_TSCK_WD1 0x45 | ||
49 | #define GORDON_REG_TGSPB_VST1 0x46 | ||
50 | #define GORDON_REG_TGSPB_VED1 0x47 | ||
51 | #define GORDON_REG_TGSPB_CH1 0x48 | ||
52 | #define GORDON_REG_TGCK_ST1 0x49 | ||
53 | #define GORDON_REG_TGCK_ED1 0x4A | ||
54 | #define GORDON_REG_TPCTL_ST1 0x4B | ||
55 | #define GORDON_REG_TPCTL_ED1 0x4C | ||
56 | #define GORDON_REG_TPCHG_ED1 0x4D | ||
57 | #define GORDON_REG_TCOM_CH1 0x4E | ||
58 | #define GORDON_REG_THBP1 0x4F | ||
59 | #define GORDON_REG_TPHCTL1 0x50 | ||
60 | #define GORDON_REG_EVPH1 0x51 | ||
61 | #define GORDON_REG_EVPL1 0x52 | ||
62 | #define GORDON_REG_EVNH1 0x53 | ||
63 | #define GORDON_REG_EVNL1 0x54 | ||
64 | #define GORDON_REG_TBIAS1 0x55 | ||
65 | #define GORDON_REG_TPARAM2 0x56 | ||
66 | #define GORDON_REG_TLCDIF2 0x57 | ||
67 | #define GORDON_REG_TSSPB_ST2 0x58 | ||
68 | #define GORDON_REG_TSSPB_ED2 0x59 | ||
69 | #define GORDON_REG_TSCK_ST2 0x5A | ||
70 | #define GORDON_REG_TSCK_WD2 0x5B | ||
71 | #define GORDON_REG_TGSPB_VST2 0x5C | ||
72 | #define GORDON_REG_TGSPB_VED2 0x5D | ||
73 | #define GORDON_REG_TGSPB_CH2 0x5E | ||
74 | #define GORDON_REG_TGCK_ST2 0x5F | ||
75 | #define GORDON_REG_TGCK_ED2 0x60 | ||
76 | #define GORDON_REG_TPCTL_ST2 0x61 | ||
77 | #define GORDON_REG_TPCTL_ED2 0x62 | ||
78 | #define GORDON_REG_TPCHG_ED2 0x63 | ||
79 | #define GORDON_REG_TCOM_CH2 0x64 | ||
80 | #define GORDON_REG_THBP2 0x65 | ||
81 | #define GORDON_REG_TPHCTL2 0x66 | ||
82 | #define GORDON_REG_POWCTL 0x80 | ||
83 | |||
84 | static int lcdc_gordon_panel_off(struct platform_device *pdev); | ||
85 | |||
86 | static int spi_cs; | ||
87 | static int spi_sclk; | ||
88 | static int spi_sdo; | ||
89 | static int spi_sdi; | ||
90 | static int spi_dac; | ||
91 | static unsigned char bit_shift[8] = { (1 << 7), /* MSB */ | ||
92 | (1 << 6), | ||
93 | (1 << 5), | ||
94 | (1 << 4), | ||
95 | (1 << 3), | ||
96 | (1 << 2), | ||
97 | (1 << 1), | ||
98 | (1 << 0) /* LSB */ | ||
99 | }; | ||
100 | |||
101 | struct gordon_state_type{ | ||
102 | boolean disp_initialized; | ||
103 | boolean display_on; | ||
104 | boolean disp_powered_up; | ||
105 | }; | ||
106 | |||
107 | static struct gordon_state_type gordon_state = { 0 }; | ||
108 | static struct msm_panel_common_pdata *lcdc_gordon_pdata; | ||
109 | |||
110 | static void serigo(uint16 reg, uint8 data) | ||
111 | { | ||
112 | unsigned int tx_val = ((0x00FF & reg) << 8) | data; | ||
113 | unsigned char i, val = 0; | ||
114 | |||
115 | /* Enable the Chip Select */ | ||
116 | gpio_set_value(spi_cs, 1); | ||
117 | udelay(33); | ||
118 | |||
119 | /* Transmit it in two parts, Higher Byte first, then Lower Byte */ | ||
120 | val = (unsigned char)((tx_val & 0xFF00) >> 8); | ||
121 | |||
122 | /* Clock should be Low before entering ! */ | ||
123 | for (i = 0; i < 8; i++) { | ||
124 | /* #1: Drive the Data (High or Low) */ | ||
125 | if (val & bit_shift[i]) | ||
126 | gpio_set_value(spi_sdi, 1); | ||
127 | else | ||
128 | gpio_set_value(spi_sdi, 0); | ||
129 | |||
130 | /* #2: Drive the Clk High and then Low */ | ||
131 | udelay(33); | ||
132 | gpio_set_value(spi_sclk, 1); | ||
133 | udelay(33); | ||
134 | gpio_set_value(spi_sclk, 0); | ||
135 | } | ||
136 | |||
137 | /* Idle state of SDO (MOSI) is Low */ | ||
138 | gpio_set_value(spi_sdi, 0); | ||
139 | /* ..then Lower Byte */ | ||
140 | val = (uint8) (tx_val & 0x00FF); | ||
141 | /* Before we enter here the Clock should be Low ! */ | ||
142 | |||
143 | for (i = 0; i < 8; i++) { | ||
144 | /* #1: Drive the Data (High or Low) */ | ||
145 | if (val & bit_shift[i]) | ||
146 | gpio_set_value(spi_sdi, 1); | ||
147 | else | ||
148 | gpio_set_value(spi_sdi, 0); | ||
149 | |||
150 | /* #2: Drive the Clk High and then Low */ | ||
151 | udelay(33); | ||
152 | |||
153 | gpio_set_value(spi_sclk, 1); | ||
154 | udelay(33); | ||
155 | gpio_set_value(spi_sclk, 0); | ||
156 | } | ||
157 | |||
158 | /* Idle state of SDO (MOSI) is Low */ | ||
159 | gpio_set_value(spi_sdi, 0); | ||
160 | |||
161 | /* Now Disable the Chip Select */ | ||
162 | udelay(33); | ||
163 | gpio_set_value(spi_cs, 0); | ||
164 | } | ||
165 | |||
166 | static void spi_init(void) | ||
167 | { | ||
168 | /* Setting the Default GPIO's */ | ||
169 | spi_sclk = *(lcdc_gordon_pdata->gpio_num); | ||
170 | spi_cs = *(lcdc_gordon_pdata->gpio_num + 1); | ||
171 | spi_sdi = *(lcdc_gordon_pdata->gpio_num + 2); | ||
172 | spi_sdo = *(lcdc_gordon_pdata->gpio_num + 3); | ||
173 | |||
174 | /* Set the output so that we dont disturb the slave device */ | ||
175 | gpio_set_value(spi_sclk, 0); | ||
176 | gpio_set_value(spi_sdi, 0); | ||
177 | |||
178 | /* Set the Chip Select De-asserted */ | ||
179 | gpio_set_value(spi_cs, 0); | ||
180 | |||
181 | } | ||
182 | |||
183 | static void gordon_disp_powerup(void) | ||
184 | { | ||
185 | if (!gordon_state.disp_powered_up && !gordon_state.display_on) { | ||
186 | /* Reset the hardware first */ | ||
187 | /* Include DAC power up implementation here */ | ||
188 | gordon_state.disp_powered_up = TRUE; | ||
189 | } | ||
190 | } | ||
191 | |||
192 | static void gordon_init(void) | ||
193 | { | ||
194 | /* Image interface settings */ | ||
195 | serigo(GORDON_REG_IMGCTL2, 0x00); | ||
196 | serigo(GORDON_REG_IMGSET1, 0x00); | ||
197 | |||
198 | /* Exchange the RGB signal for J510(Softbank mobile) */ | ||
199 | serigo(GORDON_REG_IMGSET2, 0x12); | ||
200 | serigo(GORDON_REG_LCDIFSET1, 0x00); | ||
201 | |||
202 | /* Pre-charge settings */ | ||
203 | serigo(GORDON_REG_PCCTL, 0x09); | ||
204 | serigo(GORDON_REG_LCDIFCTL2, 0x7B); | ||
205 | |||
206 | mdelay(1); | ||
207 | } | ||
208 | |||
209 | static void gordon_disp_on(void) | ||
210 | { | ||
211 | if (gordon_state.disp_powered_up && !gordon_state.display_on) { | ||
212 | gordon_init(); | ||
213 | mdelay(20); | ||
214 | /* gordon_dispmode setting */ | ||
215 | serigo(GORDON_REG_TPARAM1, 0x30); | ||
216 | serigo(GORDON_REG_TLCDIF1, 0x00); | ||
217 | serigo(GORDON_REG_TSSPB_ST1, 0x8B); | ||
218 | serigo(GORDON_REG_TSSPB_ED1, 0x93); | ||
219 | serigo(GORDON_REG_TSCK_ST1, 0x88); | ||
220 | serigo(GORDON_REG_TSCK_WD1, 0x00); | ||
221 | serigo(GORDON_REG_TGSPB_VST1, 0x01); | ||
222 | serigo(GORDON_REG_TGSPB_VED1, 0x02); | ||
223 | serigo(GORDON_REG_TGSPB_CH1, 0x5E); | ||
224 | serigo(GORDON_REG_TGCK_ST1, 0x80); | ||
225 | serigo(GORDON_REG_TGCK_ED1, 0x3C); | ||
226 | serigo(GORDON_REG_TPCTL_ST1, 0x50); | ||
227 | serigo(GORDON_REG_TPCTL_ED1, 0x74); | ||
228 | serigo(GORDON_REG_TPCHG_ED1, 0x78); | ||
229 | serigo(GORDON_REG_TCOM_CH1, 0x50); | ||
230 | serigo(GORDON_REG_THBP1, 0x84); | ||
231 | serigo(GORDON_REG_TPHCTL1, 0x00); | ||
232 | serigo(GORDON_REG_EVPH1, 0x70); | ||
233 | serigo(GORDON_REG_EVPL1, 0x64); | ||
234 | serigo(GORDON_REG_EVNH1, 0x56); | ||
235 | serigo(GORDON_REG_EVNL1, 0x48); | ||
236 | serigo(GORDON_REG_TBIAS1, 0x88); | ||
237 | |||
238 | /* QVGA settings */ | ||
239 | serigo(GORDON_REG_TPARAM2, 0x28); | ||
240 | serigo(GORDON_REG_TLCDIF2, 0x14); | ||
241 | serigo(GORDON_REG_TSSPB_ST2, 0x49); | ||
242 | serigo(GORDON_REG_TSSPB_ED2, 0x4B); | ||
243 | serigo(GORDON_REG_TSCK_ST2, 0x4A); | ||
244 | serigo(GORDON_REG_TSCK_WD2, 0x02); | ||
245 | serigo(GORDON_REG_TGSPB_VST2, 0x02); | ||
246 | serigo(GORDON_REG_TGSPB_VED2, 0x03); | ||
247 | serigo(GORDON_REG_TGSPB_CH2, 0x2F); | ||
248 | serigo(GORDON_REG_TGCK_ST2, 0x40); | ||
249 | serigo(GORDON_REG_TGCK_ED2, 0x1E); | ||
250 | serigo(GORDON_REG_TPCTL_ST2, 0x2C); | ||
251 | serigo(GORDON_REG_TPCTL_ED2, 0x3A); | ||
252 | serigo(GORDON_REG_TPCHG_ED2, 0x3C); | ||
253 | serigo(GORDON_REG_TCOM_CH2, 0x28); | ||
254 | serigo(GORDON_REG_THBP2, 0x4D); | ||
255 | serigo(GORDON_REG_TPHCTL2, 0x1A); | ||
256 | |||
257 | /* VGA settings */ | ||
258 | serigo(GORDON_REG_IVBP1, 0x02); | ||
259 | serigo(GORDON_REG_IHBP1, 0x90); | ||
260 | serigo(GORDON_REG_IVNUM1, 0xA0); | ||
261 | serigo(GORDON_REG_IHNUM1, 0x78); | ||
262 | |||
263 | /* QVGA settings */ | ||
264 | serigo(GORDON_REG_IVBP2, 0x02); | ||
265 | serigo(GORDON_REG_IHBP2, 0x48); | ||
266 | serigo(GORDON_REG_IVNUM2, 0x50); | ||
267 | serigo(GORDON_REG_IHNUM2, 0x3C); | ||
268 | |||
269 | /* Gordon Charge pump settings and ON */ | ||
270 | serigo(GORDON_REG_POWCTL, 0x03); | ||
271 | mdelay(15); | ||
272 | serigo(GORDON_REG_POWCTL, 0x07); | ||
273 | mdelay(15); | ||
274 | |||
275 | serigo(GORDON_REG_POWCTL, 0x0F); | ||
276 | mdelay(15); | ||
277 | |||
278 | serigo(GORDON_REG_AVCTL, 0x03); | ||
279 | mdelay(15); | ||
280 | |||
281 | serigo(GORDON_REG_POWCTL, 0x1F); | ||
282 | mdelay(15); | ||
283 | |||
284 | serigo(GORDON_REG_POWCTL, 0x5F); | ||
285 | mdelay(15); | ||
286 | |||
287 | serigo(GORDON_REG_POWCTL, 0x7F); | ||
288 | mdelay(15); | ||
289 | |||
290 | serigo(GORDON_REG_LCDIFCTL1, 0x02); | ||
291 | mdelay(15); | ||
292 | |||
293 | serigo(GORDON_REG_IMGCTL1, 0x00); | ||
294 | mdelay(15); | ||
295 | |||
296 | serigo(GORDON_REG_LCDIFCTL3, 0x00); | ||
297 | mdelay(15); | ||
298 | |||
299 | serigo(GORDON_REG_VALTRAN, 0x01); | ||
300 | mdelay(15); | ||
301 | |||
302 | serigo(GORDON_REG_LCDIFCTL1, 0x03); | ||
303 | mdelay(1); | ||
304 | gordon_state.display_on = TRUE; | ||
305 | } | ||
306 | } | ||
307 | |||
308 | static int lcdc_gordon_panel_on(struct platform_device *pdev) | ||
309 | { | ||
310 | if (!gordon_state.disp_initialized) { | ||
311 | /* Configure reset GPIO that drives DAC */ | ||
312 | lcdc_gordon_pdata->panel_config_gpio(1); | ||
313 | spi_dac = *(lcdc_gordon_pdata->gpio_num + 4); | ||
314 | gpio_set_value(spi_dac, 0); | ||
315 | udelay(15); | ||
316 | gpio_set_value(spi_dac, 1); | ||
317 | spi_init(); /* LCD needs SPI */ | ||
318 | gordon_disp_powerup(); | ||
319 | gordon_disp_on(); | ||
320 | gordon_state.disp_initialized = TRUE; | ||
321 | } | ||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | static int lcdc_gordon_panel_off(struct platform_device *pdev) | ||
326 | { | ||
327 | if (gordon_state.disp_powered_up && gordon_state.display_on) { | ||
328 | serigo(GORDON_REG_LCDIFCTL2, 0x7B); | ||
329 | serigo(GORDON_REG_VALTRAN, 0x01); | ||
330 | serigo(GORDON_REG_LCDIFCTL1, 0x02); | ||
331 | serigo(GORDON_REG_LCDIFCTL3, 0x01); | ||
332 | mdelay(20); | ||
333 | serigo(GORDON_REG_VALTRAN, 0x01); | ||
334 | serigo(GORDON_REG_IMGCTL1, 0x01); | ||
335 | serigo(GORDON_REG_LCDIFCTL1, 0x00); | ||
336 | mdelay(20); | ||
337 | |||
338 | serigo(GORDON_REG_POWCTL, 0x1F); | ||
339 | mdelay(40); | ||
340 | |||
341 | serigo(GORDON_REG_POWCTL, 0x07); | ||
342 | mdelay(40); | ||
343 | |||
344 | serigo(GORDON_REG_POWCTL, 0x03); | ||
345 | mdelay(40); | ||
346 | |||
347 | serigo(GORDON_REG_POWCTL, 0x00); | ||
348 | mdelay(40); | ||
349 | lcdc_gordon_pdata->panel_config_gpio(0); | ||
350 | gordon_state.display_on = FALSE; | ||
351 | gordon_state.disp_initialized = FALSE; | ||
352 | } | ||
353 | return 0; | ||
354 | } | ||
355 | |||
356 | static void lcdc_gordon_set_backlight(struct msm_fb_data_type *mfd) | ||
357 | { | ||
358 | int bl_level = mfd->bl_level; | ||
359 | |||
360 | if (bl_level <= 1) { | ||
361 | /* keep back light OFF */ | ||
362 | serigo(GORDON_REG_LCDIFCTL2, 0x0B); | ||
363 | udelay(15); | ||
364 | serigo(GORDON_REG_VALTRAN, 0x01); | ||
365 | } else { | ||
366 | /* keep back light ON */ | ||
367 | serigo(GORDON_REG_LCDIFCTL2, 0x7B); | ||
368 | udelay(15); | ||
369 | serigo(GORDON_REG_VALTRAN, 0x01); | ||
370 | } | ||
371 | } | ||
372 | |||
373 | static int __init gordon_probe(struct platform_device *pdev) | ||
374 | { | ||
375 | if (pdev->id == 0) { | ||
376 | lcdc_gordon_pdata = pdev->dev.platform_data; | ||
377 | return 0; | ||
378 | } | ||
379 | msm_fb_add_device(pdev); | ||
380 | return 0; | ||
381 | } | ||
382 | |||
383 | static struct platform_driver this_driver = { | ||
384 | .probe = gordon_probe, | ||
385 | .driver = { | ||
386 | .name = "lcdc_gordon_vga", | ||
387 | }, | ||
388 | }; | ||
389 | |||
390 | static struct msm_fb_panel_data gordon_panel_data = { | ||
391 | .on = lcdc_gordon_panel_on, | ||
392 | .off = lcdc_gordon_panel_off, | ||
393 | .set_backlight = lcdc_gordon_set_backlight, | ||
394 | }; | ||
395 | |||
396 | static struct platform_device this_device = { | ||
397 | .name = "lcdc_gordon_vga", | ||
398 | .id = 1, | ||
399 | .dev = { | ||
400 | .platform_data = &gordon_panel_data, | ||
401 | } | ||
402 | }; | ||
403 | |||
404 | static int __init lcdc_gordon_panel_init(void) | ||
405 | { | ||
406 | int ret; | ||
407 | struct msm_panel_info *pinfo; | ||
408 | |||
409 | #ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM | ||
410 | if (msm_fb_detect_client("lcdc_gordon_vga")) | ||
411 | return 0; | ||
412 | #endif | ||
413 | ret = platform_driver_register(&this_driver); | ||
414 | if (ret) | ||
415 | return ret; | ||
416 | |||
417 | pinfo = &gordon_panel_data.panel_info; | ||
418 | pinfo->xres = 480; | ||
419 | pinfo->yres = 640; | ||
420 | pinfo->type = LCDC_PANEL; | ||
421 | pinfo->pdest = DISPLAY_1; | ||
422 | pinfo->wait_cycle = 0; | ||
423 | pinfo->bpp = 24; | ||
424 | pinfo->fb_num = 2; | ||
425 | pinfo->clk_rate = 24500000; | ||
426 | pinfo->bl_max = 4; | ||
427 | pinfo->bl_min = 1; | ||
428 | |||
429 | pinfo->lcdc.h_back_porch = 84; | ||
430 | pinfo->lcdc.h_front_porch = 33; | ||
431 | pinfo->lcdc.h_pulse_width = 60; | ||
432 | pinfo->lcdc.v_back_porch = 0; | ||
433 | pinfo->lcdc.v_front_porch = 2; | ||
434 | pinfo->lcdc.v_pulse_width = 2; | ||
435 | pinfo->lcdc.border_clr = 0; /* blk */ | ||
436 | pinfo->lcdc.underflow_clr = 0xff; /* blue */ | ||
437 | pinfo->lcdc.hsync_skew = 0; | ||
438 | |||
439 | ret = platform_device_register(&this_device); | ||
440 | if (ret) | ||
441 | platform_driver_unregister(&this_driver); | ||
442 | |||
443 | return ret; | ||
444 | } | ||
445 | |||
446 | module_init(lcdc_gordon_panel_init); | ||
diff --git a/drivers/staging/msm/lcdc_grapefruit.c b/drivers/staging/msm/lcdc_grapefruit.c new file mode 100644 index 000000000000..7284649ea0ae --- /dev/null +++ b/drivers/staging/msm/lcdc_grapefruit.c | |||
@@ -0,0 +1,60 @@ | |||
1 | /* Copyright (c) 2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include "msm_fb.h" | ||
19 | |||
20 | #ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM | ||
21 | #include "mddihosti.h" | ||
22 | #endif | ||
23 | |||
24 | static int __init lcdc_grapefruit_init(void) | ||
25 | { | ||
26 | int ret; | ||
27 | struct msm_panel_info pinfo; | ||
28 | |||
29 | #ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM | ||
30 | if (msm_fb_detect_client("lcdc_grapefruit_vga")) | ||
31 | return 0; | ||
32 | #endif | ||
33 | |||
34 | pinfo.xres = 1024; | ||
35 | pinfo.yres = 600; | ||
36 | pinfo.type = LCDC_PANEL; | ||
37 | pinfo.pdest = DISPLAY_1; | ||
38 | pinfo.wait_cycle = 0; | ||
39 | pinfo.bpp = 18; | ||
40 | pinfo.fb_num = 2; | ||
41 | pinfo.clk_rate = 40000000; | ||
42 | |||
43 | pinfo.lcdc.h_back_porch = 88; | ||
44 | pinfo.lcdc.h_front_porch = 40; | ||
45 | pinfo.lcdc.h_pulse_width = 128; | ||
46 | pinfo.lcdc.v_back_porch = 23; | ||
47 | pinfo.lcdc.v_front_porch = 1; | ||
48 | pinfo.lcdc.v_pulse_width = 4; | ||
49 | pinfo.lcdc.border_clr = 0; /* blk */ | ||
50 | pinfo.lcdc.underflow_clr = 0xff; /* blue */ | ||
51 | pinfo.lcdc.hsync_skew = 0; | ||
52 | |||
53 | ret = lcdc_device_register(&pinfo); | ||
54 | if (ret) | ||
55 | printk(KERN_ERR "%s: failed to register device!\n", __func__); | ||
56 | |||
57 | return ret; | ||
58 | } | ||
59 | |||
60 | module_init(lcdc_grapefruit_init); | ||
diff --git a/drivers/staging/msm/lcdc_panel.c b/drivers/staging/msm/lcdc_panel.c new file mode 100644 index 000000000000..b40974e1f27c --- /dev/null +++ b/drivers/staging/msm/lcdc_panel.c | |||
@@ -0,0 +1,88 @@ | |||
1 | /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include "msm_fb.h" | ||
19 | |||
20 | static int lcdc_panel_on(struct platform_device *pdev) | ||
21 | { | ||
22 | return 0; | ||
23 | } | ||
24 | |||
25 | static int lcdc_panel_off(struct platform_device *pdev) | ||
26 | { | ||
27 | return 0; | ||
28 | } | ||
29 | |||
30 | static int __init lcdc_panel_probe(struct platform_device *pdev) | ||
31 | { | ||
32 | msm_fb_add_device(pdev); | ||
33 | |||
34 | return 0; | ||
35 | } | ||
36 | |||
37 | static struct platform_driver this_driver = { | ||
38 | .probe = lcdc_panel_probe, | ||
39 | .driver = { | ||
40 | .name = "lcdc_panel", | ||
41 | }, | ||
42 | }; | ||
43 | |||
44 | static struct msm_fb_panel_data lcdc_panel_data = { | ||
45 | .on = lcdc_panel_on, | ||
46 | .off = lcdc_panel_off, | ||
47 | }; | ||
48 | |||
49 | static int lcdc_dev_id; | ||
50 | |||
51 | int lcdc_device_register(struct msm_panel_info *pinfo) | ||
52 | { | ||
53 | struct platform_device *pdev = NULL; | ||
54 | int ret; | ||
55 | |||
56 | pdev = platform_device_alloc("lcdc_panel", ++lcdc_dev_id); | ||
57 | if (!pdev) | ||
58 | return -ENOMEM; | ||
59 | |||
60 | lcdc_panel_data.panel_info = *pinfo; | ||
61 | ret = platform_device_add_data(pdev, &lcdc_panel_data, | ||
62 | sizeof(lcdc_panel_data)); | ||
63 | if (ret) { | ||
64 | printk(KERN_ERR | ||
65 | "%s: platform_device_add_data failed!\n", __func__); | ||
66 | goto err_device_put; | ||
67 | } | ||
68 | |||
69 | ret = platform_device_add(pdev); | ||
70 | if (ret) { | ||
71 | printk(KERN_ERR | ||
72 | "%s: platform_device_register failed!\n", __func__); | ||
73 | goto err_device_put; | ||
74 | } | ||
75 | |||
76 | return 0; | ||
77 | |||
78 | err_device_put: | ||
79 | platform_device_put(pdev); | ||
80 | return ret; | ||
81 | } | ||
82 | |||
83 | static int __init lcdc_panel_init(void) | ||
84 | { | ||
85 | return platform_driver_register(&this_driver); | ||
86 | } | ||
87 | |||
88 | module_init(lcdc_panel_init); | ||
diff --git a/drivers/staging/msm/lcdc_prism.c b/drivers/staging/msm/lcdc_prism.c new file mode 100644 index 000000000000..d102c98447c1 --- /dev/null +++ b/drivers/staging/msm/lcdc_prism.c | |||
@@ -0,0 +1,64 @@ | |||
1 | /* Copyright (c) 2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include "msm_fb.h" | ||
19 | |||
20 | #ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM | ||
21 | #include "mddihosti.h" | ||
22 | #endif | ||
23 | |||
24 | static int __init lcdc_prism_init(void) | ||
25 | { | ||
26 | int ret; | ||
27 | struct msm_panel_info pinfo; | ||
28 | |||
29 | #ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM | ||
30 | ret = msm_fb_detect_client("lcdc_prism_wvga"); | ||
31 | if (ret == -ENODEV) | ||
32 | return 0; | ||
33 | |||
34 | if (ret && (mddi_get_client_id() != 0)) | ||
35 | return 0; | ||
36 | #endif | ||
37 | |||
38 | pinfo.xres = 800; | ||
39 | pinfo.yres = 480; | ||
40 | pinfo.type = LCDC_PANEL; | ||
41 | pinfo.pdest = DISPLAY_1; | ||
42 | pinfo.wait_cycle = 0; | ||
43 | pinfo.bpp = 24; | ||
44 | pinfo.fb_num = 2; | ||
45 | pinfo.clk_rate = 38460000; | ||
46 | |||
47 | pinfo.lcdc.h_back_porch = 21; | ||
48 | pinfo.lcdc.h_front_porch = 81; | ||
49 | pinfo.lcdc.h_pulse_width = 60; | ||
50 | pinfo.lcdc.v_back_porch = 18; | ||
51 | pinfo.lcdc.v_front_porch = 27; | ||
52 | pinfo.lcdc.v_pulse_width = 2; | ||
53 | pinfo.lcdc.border_clr = 0; /* blk */ | ||
54 | pinfo.lcdc.underflow_clr = 0xff; /* blue */ | ||
55 | pinfo.lcdc.hsync_skew = 0; | ||
56 | |||
57 | ret = lcdc_device_register(&pinfo); | ||
58 | if (ret) | ||
59 | printk(KERN_ERR "%s: failed to register device!\n", __func__); | ||
60 | |||
61 | return ret; | ||
62 | } | ||
63 | |||
64 | module_init(lcdc_prism_init); | ||
diff --git a/drivers/staging/msm/lcdc_sharp_wvga_pt.c b/drivers/staging/msm/lcdc_sharp_wvga_pt.c new file mode 100644 index 000000000000..1f08cf9bc217 --- /dev/null +++ b/drivers/staging/msm/lcdc_sharp_wvga_pt.c | |||
@@ -0,0 +1,290 @@ | |||
1 | /* Copyright (c) 2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include <linux/delay.h> | ||
19 | #ifdef CONFIG_ARCH_MSM7X30 | ||
20 | #include <linux/mfd/pmic8058.h> | ||
21 | #endif | ||
22 | #include <mach/gpio.h> | ||
23 | #include "msm_fb.h" | ||
24 | |||
25 | static int lcdc_sharp_panel_off(struct platform_device *pdev); | ||
26 | |||
27 | static int spi_cs; | ||
28 | static int spi_sclk; | ||
29 | static int spi_mosi; | ||
30 | static int spi_miso; | ||
31 | static unsigned char bit_shift[8] = { (1 << 7), /* MSB */ | ||
32 | (1 << 6), | ||
33 | (1 << 5), | ||
34 | (1 << 4), | ||
35 | (1 << 3), | ||
36 | (1 << 2), | ||
37 | (1 << 1), | ||
38 | (1 << 0) /* LSB */ | ||
39 | }; | ||
40 | |||
41 | struct sharp_state_type { | ||
42 | boolean disp_initialized; | ||
43 | boolean display_on; | ||
44 | boolean disp_powered_up; | ||
45 | }; | ||
46 | |||
47 | struct sharp_spi_data { | ||
48 | u8 addr; | ||
49 | u8 data; | ||
50 | }; | ||
51 | |||
52 | static struct sharp_spi_data init_sequence[] = { | ||
53 | { 15, 0x01 }, | ||
54 | { 5, 0x01 }, | ||
55 | { 7, 0x10 }, | ||
56 | { 9, 0x1E }, | ||
57 | { 10, 0x04 }, | ||
58 | { 17, 0xFF }, | ||
59 | { 21, 0x8A }, | ||
60 | { 22, 0x00 }, | ||
61 | { 23, 0x82 }, | ||
62 | { 24, 0x24 }, | ||
63 | { 25, 0x22 }, | ||
64 | { 26, 0x6D }, | ||
65 | { 27, 0xEB }, | ||
66 | { 28, 0xB9 }, | ||
67 | { 29, 0x3A }, | ||
68 | { 49, 0x1A }, | ||
69 | { 50, 0x16 }, | ||
70 | { 51, 0x05 }, | ||
71 | { 55, 0x7F }, | ||
72 | { 56, 0x15 }, | ||
73 | { 57, 0x7B }, | ||
74 | { 60, 0x05 }, | ||
75 | { 61, 0x0C }, | ||
76 | { 62, 0x80 }, | ||
77 | { 63, 0x00 }, | ||
78 | { 92, 0x90 }, | ||
79 | { 97, 0x01 }, | ||
80 | { 98, 0xFF }, | ||
81 | { 113, 0x11 }, | ||
82 | { 114, 0x02 }, | ||
83 | { 115, 0x08 }, | ||
84 | { 123, 0xAB }, | ||
85 | { 124, 0x04 }, | ||
86 | { 6, 0x02 }, | ||
87 | { 133, 0x00 }, | ||
88 | { 134, 0xFE }, | ||
89 | { 135, 0x22 }, | ||
90 | { 136, 0x0B }, | ||
91 | { 137, 0xFF }, | ||
92 | { 138, 0x0F }, | ||
93 | { 139, 0x00 }, | ||
94 | { 140, 0xFE }, | ||
95 | { 141, 0x22 }, | ||
96 | { 142, 0x0B }, | ||
97 | { 143, 0xFF }, | ||
98 | { 144, 0x0F }, | ||
99 | { 145, 0x00 }, | ||
100 | { 146, 0xFE }, | ||
101 | { 147, 0x22 }, | ||
102 | { 148, 0x0B }, | ||
103 | { 149, 0xFF }, | ||
104 | { 150, 0x0F }, | ||
105 | { 202, 0x30 }, | ||
106 | { 30, 0x01 }, | ||
107 | { 4, 0x01 }, | ||
108 | { 31, 0x41 }, | ||
109 | }; | ||
110 | |||
111 | static struct sharp_state_type sharp_state = { 0 }; | ||
112 | static struct msm_panel_common_pdata *lcdc_sharp_pdata; | ||
113 | |||
114 | static void sharp_spi_write_byte(u8 val) | ||
115 | { | ||
116 | int i; | ||
117 | |||
118 | /* Clock should be Low before entering */ | ||
119 | for (i = 0; i < 8; i++) { | ||
120 | /* #1: Drive the Data (High or Low) */ | ||
121 | if (val & bit_shift[i]) | ||
122 | gpio_set_value(spi_mosi, 1); | ||
123 | else | ||
124 | gpio_set_value(spi_mosi, 0); | ||
125 | |||
126 | /* #2: Drive the Clk High and then Low */ | ||
127 | gpio_set_value(spi_sclk, 1); | ||
128 | gpio_set_value(spi_sclk, 0); | ||
129 | } | ||
130 | } | ||
131 | |||
132 | static void serigo(u8 reg, u8 data) | ||
133 | { | ||
134 | /* Enable the Chip Select - low */ | ||
135 | gpio_set_value(spi_cs, 0); | ||
136 | udelay(1); | ||
137 | |||
138 | /* Transmit register address first, then data */ | ||
139 | sharp_spi_write_byte(reg); | ||
140 | |||
141 | /* Idle state of MOSI is Low */ | ||
142 | gpio_set_value(spi_mosi, 0); | ||
143 | udelay(1); | ||
144 | sharp_spi_write_byte(data); | ||
145 | |||
146 | gpio_set_value(spi_mosi, 0); | ||
147 | gpio_set_value(spi_cs, 1); | ||
148 | } | ||
149 | |||
150 | static void sharp_spi_init(void) | ||
151 | { | ||
152 | spi_sclk = *(lcdc_sharp_pdata->gpio_num); | ||
153 | spi_cs = *(lcdc_sharp_pdata->gpio_num + 1); | ||
154 | spi_mosi = *(lcdc_sharp_pdata->gpio_num + 2); | ||
155 | spi_miso = *(lcdc_sharp_pdata->gpio_num + 3); | ||
156 | |||
157 | /* Set the output so that we don't disturb the slave device */ | ||
158 | gpio_set_value(spi_sclk, 0); | ||
159 | gpio_set_value(spi_mosi, 0); | ||
160 | |||
161 | /* Set the Chip Select deasserted (active low) */ | ||
162 | gpio_set_value(spi_cs, 1); | ||
163 | } | ||
164 | |||
165 | static void sharp_disp_powerup(void) | ||
166 | { | ||
167 | if (!sharp_state.disp_powered_up && !sharp_state.display_on) | ||
168 | sharp_state.disp_powered_up = TRUE; | ||
169 | } | ||
170 | |||
171 | static void sharp_disp_on(void) | ||
172 | { | ||
173 | int i; | ||
174 | |||
175 | if (sharp_state.disp_powered_up && !sharp_state.display_on) { | ||
176 | for (i = 0; i < ARRAY_SIZE(init_sequence); i++) { | ||
177 | serigo(init_sequence[i].addr, | ||
178 | init_sequence[i].data); | ||
179 | } | ||
180 | mdelay(10); | ||
181 | serigo(31, 0xC1); | ||
182 | mdelay(10); | ||
183 | serigo(31, 0xD9); | ||
184 | serigo(31, 0xDF); | ||
185 | |||
186 | sharp_state.display_on = TRUE; | ||
187 | } | ||
188 | } | ||
189 | |||
190 | static int lcdc_sharp_panel_on(struct platform_device *pdev) | ||
191 | { | ||
192 | if (!sharp_state.disp_initialized) { | ||
193 | lcdc_sharp_pdata->panel_config_gpio(1); | ||
194 | sharp_spi_init(); | ||
195 | sharp_disp_powerup(); | ||
196 | sharp_disp_on(); | ||
197 | sharp_state.disp_initialized = TRUE; | ||
198 | } | ||
199 | return 0; | ||
200 | } | ||
201 | |||
202 | static int lcdc_sharp_panel_off(struct platform_device *pdev) | ||
203 | { | ||
204 | if (sharp_state.disp_powered_up && sharp_state.display_on) { | ||
205 | serigo(4, 0x00); | ||
206 | mdelay(40); | ||
207 | serigo(31, 0xC1); | ||
208 | mdelay(40); | ||
209 | serigo(31, 0x00); | ||
210 | mdelay(100); | ||
211 | sharp_state.display_on = FALSE; | ||
212 | sharp_state.disp_initialized = FALSE; | ||
213 | } | ||
214 | return 0; | ||
215 | } | ||
216 | |||
217 | static int __init sharp_probe(struct platform_device *pdev) | ||
218 | { | ||
219 | if (pdev->id == 0) { | ||
220 | lcdc_sharp_pdata = pdev->dev.platform_data; | ||
221 | return 0; | ||
222 | } | ||
223 | msm_fb_add_device(pdev); | ||
224 | return 0; | ||
225 | } | ||
226 | |||
227 | static struct platform_driver this_driver = { | ||
228 | .probe = sharp_probe, | ||
229 | .driver = { | ||
230 | .name = "lcdc_sharp_wvga", | ||
231 | }, | ||
232 | }; | ||
233 | |||
234 | static struct msm_fb_panel_data sharp_panel_data = { | ||
235 | .on = lcdc_sharp_panel_on, | ||
236 | .off = lcdc_sharp_panel_off, | ||
237 | }; | ||
238 | |||
239 | static struct platform_device this_device = { | ||
240 | .name = "lcdc_sharp_wvga", | ||
241 | .id = 1, | ||
242 | .dev = { | ||
243 | .platform_data = &sharp_panel_data, | ||
244 | } | ||
245 | }; | ||
246 | |||
247 | static int __init lcdc_sharp_panel_init(void) | ||
248 | { | ||
249 | int ret; | ||
250 | struct msm_panel_info *pinfo; | ||
251 | |||
252 | #ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT | ||
253 | if (msm_fb_detect_client("lcdc_sharp_wvga_pt")) | ||
254 | return 0; | ||
255 | #endif | ||
256 | |||
257 | ret = platform_driver_register(&this_driver); | ||
258 | if (ret) | ||
259 | return ret; | ||
260 | |||
261 | pinfo = &sharp_panel_data.panel_info; | ||
262 | pinfo->xres = 480; | ||
263 | pinfo->yres = 800; | ||
264 | pinfo->type = LCDC_PANEL; | ||
265 | pinfo->pdest = DISPLAY_1; | ||
266 | pinfo->wait_cycle = 0; | ||
267 | pinfo->bpp = 18; | ||
268 | pinfo->fb_num = 2; | ||
269 | pinfo->clk_rate = 24500000; | ||
270 | pinfo->bl_max = 4; | ||
271 | pinfo->bl_min = 1; | ||
272 | |||
273 | pinfo->lcdc.h_back_porch = 20; | ||
274 | pinfo->lcdc.h_front_porch = 10; | ||
275 | pinfo->lcdc.h_pulse_width = 10; | ||
276 | pinfo->lcdc.v_back_porch = 2; | ||
277 | pinfo->lcdc.v_front_porch = 2; | ||
278 | pinfo->lcdc.v_pulse_width = 2; | ||
279 | pinfo->lcdc.border_clr = 0; | ||
280 | pinfo->lcdc.underflow_clr = 0xff; | ||
281 | pinfo->lcdc.hsync_skew = 0; | ||
282 | |||
283 | ret = platform_device_register(&this_device); | ||
284 | if (ret) | ||
285 | platform_driver_unregister(&this_driver); | ||
286 | |||
287 | return ret; | ||
288 | } | ||
289 | |||
290 | module_init(lcdc_sharp_panel_init); | ||
diff --git a/drivers/staging/msm/lcdc_st15.c b/drivers/staging/msm/lcdc_st15.c new file mode 100644 index 000000000000..fed8278eb153 --- /dev/null +++ b/drivers/staging/msm/lcdc_st15.c | |||
@@ -0,0 +1,237 @@ | |||
1 | /* Copyright (c) 2010, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include <linux/i2c.h> | ||
19 | #include <linux/delay.h> | ||
20 | #include "msm_fb.h" | ||
21 | |||
22 | #define DEVICE_NAME "sii9022" | ||
23 | #define SII9022_DEVICE_ID 0xB0 | ||
24 | |||
25 | struct sii9022_i2c_addr_data{ | ||
26 | u8 addr; | ||
27 | u8 data; | ||
28 | }; | ||
29 | |||
30 | /* video mode data */ | ||
31 | static u8 video_mode_data[] = { | ||
32 | 0x00, | ||
33 | 0xF9, 0x1C, 0x70, 0x17, 0x72, 0x06, 0xEE, 0x02, | ||
34 | }; | ||
35 | |||
36 | static u8 avi_io_format[] = { | ||
37 | 0x09, | ||
38 | 0x00, 0x00, | ||
39 | }; | ||
40 | |||
41 | /* power state */ | ||
42 | static struct sii9022_i2c_addr_data regset0[] = { | ||
43 | { 0x60, 0x04 }, | ||
44 | { 0x63, 0x00 }, | ||
45 | { 0x1E, 0x00 }, | ||
46 | }; | ||
47 | |||
48 | static u8 video_infoframe[] = { | ||
49 | 0x0C, | ||
50 | 0xF0, 0x00, 0x68, 0x00, 0x04, 0x00, 0x19, 0x00, | ||
51 | 0xE9, 0x02, 0x04, 0x01, 0x04, 0x06, | ||
52 | }; | ||
53 | |||
54 | /* configure audio */ | ||
55 | static struct sii9022_i2c_addr_data regset1[] = { | ||
56 | { 0x26, 0x90 }, | ||
57 | { 0x20, 0x90 }, | ||
58 | { 0x1F, 0x80 }, | ||
59 | { 0x26, 0x80 }, | ||
60 | { 0x24, 0x02 }, | ||
61 | { 0x25, 0x0B }, | ||
62 | { 0xBC, 0x02 }, | ||
63 | { 0xBD, 0x24 }, | ||
64 | { 0xBE, 0x02 }, | ||
65 | }; | ||
66 | |||
67 | /* enable audio */ | ||
68 | static u8 misc_infoframe[] = { | ||
69 | 0xBF, | ||
70 | 0xC2, 0x84, 0x01, 0x0A, 0x6F, 0x02, 0x00, 0x00, | ||
71 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
72 | }; | ||
73 | |||
74 | /* set HDMI, active */ | ||
75 | static struct sii9022_i2c_addr_data regset2[] = { | ||
76 | { 0x1A, 0x01 }, | ||
77 | { 0x3D, 0x00 }, | ||
78 | }; | ||
79 | |||
80 | static int send_i2c_data(struct i2c_client *client, | ||
81 | struct sii9022_i2c_addr_data *regset, | ||
82 | int size) | ||
83 | { | ||
84 | int i; | ||
85 | int rc = 0; | ||
86 | |||
87 | for (i = 0; i < size; i++) { | ||
88 | rc = i2c_smbus_write_byte_data( | ||
89 | client, | ||
90 | regset[i].addr, regset[i].data); | ||
91 | if (rc) | ||
92 | break; | ||
93 | } | ||
94 | return rc; | ||
95 | } | ||
96 | |||
97 | static int hdmi_sii_enable(struct i2c_client *client) | ||
98 | { | ||
99 | int rc; | ||
100 | int retries = 10; | ||
101 | int count; | ||
102 | |||
103 | rc = i2c_smbus_write_byte_data(client, 0xC7, 0x00); | ||
104 | if (rc) | ||
105 | goto enable_exit; | ||
106 | |||
107 | do { | ||
108 | msleep(1); | ||
109 | rc = i2c_smbus_read_byte_data(client, 0x1B); | ||
110 | } while ((rc != SII9022_DEVICE_ID) && retries--); | ||
111 | |||
112 | if (rc != SII9022_DEVICE_ID) | ||
113 | return -ENODEV; | ||
114 | |||
115 | rc = i2c_smbus_write_byte_data(client, 0x1A, 0x11); | ||
116 | if (rc) | ||
117 | goto enable_exit; | ||
118 | |||
119 | count = ARRAY_SIZE(video_mode_data); | ||
120 | rc = i2c_master_send(client, video_mode_data, count); | ||
121 | if (rc != count) { | ||
122 | rc = -EIO; | ||
123 | goto enable_exit; | ||
124 | } | ||
125 | |||
126 | rc = i2c_smbus_write_byte_data(client, 0x08, 0x20); | ||
127 | if (rc) | ||
128 | goto enable_exit; | ||
129 | count = ARRAY_SIZE(avi_io_format); | ||
130 | rc = i2c_master_send(client, avi_io_format, count); | ||
131 | if (rc != count) { | ||
132 | rc = -EIO; | ||
133 | goto enable_exit; | ||
134 | } | ||
135 | |||
136 | rc = send_i2c_data(client, regset0, ARRAY_SIZE(regset0)); | ||
137 | if (rc) | ||
138 | goto enable_exit; | ||
139 | |||
140 | count = ARRAY_SIZE(video_infoframe); | ||
141 | rc = i2c_master_send(client, video_infoframe, count); | ||
142 | if (rc != count) { | ||
143 | rc = -EIO; | ||
144 | goto enable_exit; | ||
145 | } | ||
146 | |||
147 | rc = send_i2c_data(client, regset1, ARRAY_SIZE(regset1)); | ||
148 | if (rc) | ||
149 | goto enable_exit; | ||
150 | |||
151 | count = ARRAY_SIZE(misc_infoframe); | ||
152 | rc = i2c_master_send(client, misc_infoframe, count); | ||
153 | if (rc != count) { | ||
154 | rc = -EIO; | ||
155 | goto enable_exit; | ||
156 | } | ||
157 | |||
158 | rc = send_i2c_data(client, regset2, ARRAY_SIZE(regset2)); | ||
159 | if (rc) | ||
160 | goto enable_exit; | ||
161 | |||
162 | return 0; | ||
163 | enable_exit: | ||
164 | printk(KERN_ERR "%s: exited rc=%d\n", __func__, rc); | ||
165 | return rc; | ||
166 | } | ||
167 | |||
168 | static const struct i2c_device_id hmdi_sii_id[] = { | ||
169 | { DEVICE_NAME, 0 }, | ||
170 | { } | ||
171 | }; | ||
172 | |||
173 | static int hdmi_sii_probe(struct i2c_client *client, | ||
174 | const struct i2c_device_id *id) | ||
175 | { | ||
176 | int rc; | ||
177 | |||
178 | if (!i2c_check_functionality(client->adapter, | ||
179 | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_I2C)) | ||
180 | return -ENODEV; | ||
181 | rc = hdmi_sii_enable(client); | ||
182 | return rc; | ||
183 | } | ||
184 | |||
185 | |||
186 | static struct i2c_driver hdmi_sii_i2c_driver = { | ||
187 | .driver = { | ||
188 | .name = DEVICE_NAME, | ||
189 | .owner = THIS_MODULE, | ||
190 | }, | ||
191 | .probe = hdmi_sii_probe, | ||
192 | .remove = __exit_p(hdmi_sii_remove), | ||
193 | .id_table = hmdi_sii_id, | ||
194 | }; | ||
195 | |||
196 | static int __init lcdc_st15_init(void) | ||
197 | { | ||
198 | int ret; | ||
199 | struct msm_panel_info pinfo; | ||
200 | |||
201 | if (msm_fb_detect_client("lcdc_st15")) | ||
202 | return 0; | ||
203 | |||
204 | pinfo.xres = 1366; | ||
205 | pinfo.yres = 768; | ||
206 | pinfo.type = LCDC_PANEL; | ||
207 | pinfo.pdest = DISPLAY_1; | ||
208 | pinfo.wait_cycle = 0; | ||
209 | pinfo.bpp = 24; | ||
210 | pinfo.fb_num = 2; | ||
211 | pinfo.clk_rate = 74250000; | ||
212 | |||
213 | pinfo.lcdc.h_back_porch = 120; | ||
214 | pinfo.lcdc.h_front_porch = 20; | ||
215 | pinfo.lcdc.h_pulse_width = 40; | ||
216 | pinfo.lcdc.v_back_porch = 25; | ||
217 | pinfo.lcdc.v_front_porch = 1; | ||
218 | pinfo.lcdc.v_pulse_width = 7; | ||
219 | pinfo.lcdc.border_clr = 0; /* blk */ | ||
220 | pinfo.lcdc.underflow_clr = 0xff; /* blue */ | ||
221 | pinfo.lcdc.hsync_skew = 0; | ||
222 | |||
223 | ret = lcdc_device_register(&pinfo); | ||
224 | if (ret) { | ||
225 | printk(KERN_ERR "%s: failed to register device!\n", __func__); | ||
226 | goto init_exit; | ||
227 | } | ||
228 | |||
229 | ret = i2c_add_driver(&hdmi_sii_i2c_driver); | ||
230 | if (ret) | ||
231 | printk(KERN_ERR "%s: failed to add i2c driver\n", __func__); | ||
232 | |||
233 | init_exit: | ||
234 | return ret; | ||
235 | } | ||
236 | |||
237 | module_init(lcdc_st15_init); | ||
diff --git a/drivers/staging/msm/lcdc_st1_wxga.c b/drivers/staging/msm/lcdc_st1_wxga.c new file mode 100644 index 000000000000..73760019cf2e --- /dev/null +++ b/drivers/staging/msm/lcdc_st1_wxga.c | |||
@@ -0,0 +1,54 @@ | |||
1 | /* Copyright (c) 2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include "msm_fb.h" | ||
19 | |||
20 | static int __init lcdc_st1_wxga_init(void) | ||
21 | { | ||
22 | int ret; | ||
23 | struct msm_panel_info pinfo; | ||
24 | |||
25 | if (msm_fb_detect_client("lcdc_st1_wxga")) | ||
26 | return 0; | ||
27 | |||
28 | pinfo.xres = 1280; | ||
29 | pinfo.yres = 720; | ||
30 | pinfo.type = LCDC_PANEL; | ||
31 | pinfo.pdest = DISPLAY_1; | ||
32 | pinfo.wait_cycle = 0; | ||
33 | pinfo.bpp = 18; | ||
34 | pinfo.fb_num = 2; | ||
35 | pinfo.clk_rate = 74250000; | ||
36 | |||
37 | pinfo.lcdc.h_back_porch = 124; | ||
38 | pinfo.lcdc.h_front_porch = 110; | ||
39 | pinfo.lcdc.h_pulse_width = 136; | ||
40 | pinfo.lcdc.v_back_porch = 19; | ||
41 | pinfo.lcdc.v_front_porch = 5; | ||
42 | pinfo.lcdc.v_pulse_width = 6; | ||
43 | pinfo.lcdc.border_clr = 0; /* blk */ | ||
44 | pinfo.lcdc.underflow_clr = 0xff; /* blue */ | ||
45 | pinfo.lcdc.hsync_skew = 0; | ||
46 | |||
47 | ret = lcdc_device_register(&pinfo); | ||
48 | if (ret) | ||
49 | printk(KERN_ERR "%s: failed to register device!\n", __func__); | ||
50 | |||
51 | return ret; | ||
52 | } | ||
53 | |||
54 | module_init(lcdc_st1_wxga_init); | ||
diff --git a/drivers/staging/msm/lcdc_toshiba_wvga_pt.c b/drivers/staging/msm/lcdc_toshiba_wvga_pt.c new file mode 100644 index 000000000000..864d7c18913d --- /dev/null +++ b/drivers/staging/msm/lcdc_toshiba_wvga_pt.c | |||
@@ -0,0 +1,374 @@ | |||
1 | /* Copyright (c) 2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include <linux/delay.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <mach/gpio.h> | ||
21 | #include <mach/pmic.h> | ||
22 | #include "msm_fb.h" | ||
23 | |||
24 | #ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM | ||
25 | #include "mddihosti.h" | ||
26 | #endif | ||
27 | |||
28 | static int spi_cs; | ||
29 | static int spi_sclk; | ||
30 | static int spi_mosi; | ||
31 | static int spi_miso; | ||
32 | |||
33 | struct toshiba_state_type{ | ||
34 | boolean disp_initialized; | ||
35 | boolean display_on; | ||
36 | boolean disp_powered_up; | ||
37 | }; | ||
38 | |||
39 | static struct toshiba_state_type toshiba_state = { 0 }; | ||
40 | static struct msm_panel_common_pdata *lcdc_toshiba_pdata; | ||
41 | |||
42 | static void toshiba_spi_write_byte(char dc, uint8 data) | ||
43 | { | ||
44 | uint32 bit; | ||
45 | int bnum; | ||
46 | |||
47 | gpio_set_value(spi_sclk, 0); /* clk low */ | ||
48 | /* dc: 0 for command, 1 for parameter */ | ||
49 | gpio_set_value(spi_mosi, dc); | ||
50 | udelay(1); /* at least 20 ns */ | ||
51 | gpio_set_value(spi_sclk, 1); /* clk high */ | ||
52 | udelay(1); /* at least 20 ns */ | ||
53 | bnum = 8; /* 8 data bits */ | ||
54 | bit = 0x80; | ||
55 | while (bnum) { | ||
56 | gpio_set_value(spi_sclk, 0); /* clk low */ | ||
57 | if (data & bit) | ||
58 | gpio_set_value(spi_mosi, 1); | ||
59 | else | ||
60 | gpio_set_value(spi_mosi, 0); | ||
61 | udelay(1); | ||
62 | gpio_set_value(spi_sclk, 1); /* clk high */ | ||
63 | udelay(1); | ||
64 | bit >>= 1; | ||
65 | bnum--; | ||
66 | } | ||
67 | } | ||
68 | |||
69 | static void toshiba_spi_write(char cmd, uint32 data, int num) | ||
70 | { | ||
71 | char *bp; | ||
72 | |||
73 | gpio_set_value(spi_cs, 1); /* cs high */ | ||
74 | |||
75 | /* command byte first */ | ||
76 | toshiba_spi_write_byte(0, cmd); | ||
77 | |||
78 | /* followed by parameter bytes */ | ||
79 | if (num) { | ||
80 | bp = (char *)&data;; | ||
81 | bp += (num - 1); | ||
82 | while (num) { | ||
83 | toshiba_spi_write_byte(1, *bp); | ||
84 | num--; | ||
85 | bp--; | ||
86 | } | ||
87 | } | ||
88 | |||
89 | gpio_set_value(spi_cs, 0); /* cs low */ | ||
90 | udelay(1); | ||
91 | } | ||
92 | |||
93 | void toshiba_spi_read_bytes(char cmd, uint32 *data, int num) | ||
94 | { | ||
95 | uint32 dbit, bits; | ||
96 | int bnum; | ||
97 | |||
98 | gpio_set_value(spi_cs, 1); /* cs high */ | ||
99 | |||
100 | /* command byte first */ | ||
101 | toshiba_spi_write_byte(0, cmd); | ||
102 | |||
103 | if (num > 1) { | ||
104 | /* extra dc bit */ | ||
105 | gpio_set_value(spi_sclk, 0); /* clk low */ | ||
106 | udelay(1); | ||
107 | dbit = gpio_get_value(spi_miso);/* dc bit */ | ||
108 | udelay(1); | ||
109 | gpio_set_value(spi_sclk, 1); /* clk high */ | ||
110 | } | ||
111 | |||
112 | /* followed by data bytes */ | ||
113 | bnum = num * 8; /* number of bits */ | ||
114 | bits = 0; | ||
115 | while (bnum) { | ||
116 | bits <<= 1; | ||
117 | gpio_set_value(spi_sclk, 0); /* clk low */ | ||
118 | udelay(1); | ||
119 | dbit = gpio_get_value(spi_miso); | ||
120 | udelay(1); | ||
121 | gpio_set_value(spi_sclk, 1); /* clk high */ | ||
122 | bits |= dbit; | ||
123 | bnum--; | ||
124 | } | ||
125 | |||
126 | *data = bits; | ||
127 | |||
128 | udelay(1); | ||
129 | gpio_set_value(spi_cs, 0); /* cs low */ | ||
130 | udelay(1); | ||
131 | } | ||
132 | |||
133 | static void spi_pin_assign(void) | ||
134 | { | ||
135 | /* Setting the Default GPIO's */ | ||
136 | spi_sclk = *(lcdc_toshiba_pdata->gpio_num); | ||
137 | spi_cs = *(lcdc_toshiba_pdata->gpio_num + 1); | ||
138 | spi_mosi = *(lcdc_toshiba_pdata->gpio_num + 2); | ||
139 | spi_miso = *(lcdc_toshiba_pdata->gpio_num + 3); | ||
140 | } | ||
141 | |||
142 | static void toshiba_disp_powerup(void) | ||
143 | { | ||
144 | if (!toshiba_state.disp_powered_up && !toshiba_state.display_on) { | ||
145 | /* Reset the hardware first */ | ||
146 | /* Include DAC power up implementation here */ | ||
147 | toshiba_state.disp_powered_up = TRUE; | ||
148 | } | ||
149 | } | ||
150 | |||
151 | static void toshiba_disp_on(void) | ||
152 | { | ||
153 | uint32 data; | ||
154 | |||
155 | gpio_set_value(spi_cs, 0); /* low */ | ||
156 | gpio_set_value(spi_sclk, 1); /* high */ | ||
157 | gpio_set_value(spi_mosi, 0); | ||
158 | gpio_set_value(spi_miso, 0); | ||
159 | |||
160 | if (toshiba_state.disp_powered_up && !toshiba_state.display_on) { | ||
161 | toshiba_spi_write(0, 0, 0); | ||
162 | mdelay(7); | ||
163 | toshiba_spi_write(0, 0, 0); | ||
164 | mdelay(7); | ||
165 | toshiba_spi_write(0, 0, 0); | ||
166 | mdelay(7); | ||
167 | toshiba_spi_write(0xba, 0x11, 1); | ||
168 | toshiba_spi_write(0x36, 0x00, 1); | ||
169 | mdelay(1); | ||
170 | toshiba_spi_write(0x3a, 0x60, 1); | ||
171 | toshiba_spi_write(0xb1, 0x5d, 1); | ||
172 | mdelay(1); | ||
173 | toshiba_spi_write(0xb2, 0x33, 1); | ||
174 | toshiba_spi_write(0xb3, 0x22, 1); | ||
175 | mdelay(1); | ||
176 | toshiba_spi_write(0xb4, 0x02, 1); | ||
177 | toshiba_spi_write(0xb5, 0x1e, 1); /* vcs -- adjust brightness */ | ||
178 | mdelay(1); | ||
179 | toshiba_spi_write(0xb6, 0x27, 1); | ||
180 | toshiba_spi_write(0xb7, 0x03, 1); | ||
181 | mdelay(1); | ||
182 | toshiba_spi_write(0xb9, 0x24, 1); | ||
183 | toshiba_spi_write(0xbd, 0xa1, 1); | ||
184 | mdelay(1); | ||
185 | toshiba_spi_write(0xbb, 0x00, 1); | ||
186 | toshiba_spi_write(0xbf, 0x01, 1); | ||
187 | mdelay(1); | ||
188 | toshiba_spi_write(0xbe, 0x00, 1); | ||
189 | toshiba_spi_write(0xc0, 0x11, 1); | ||
190 | mdelay(1); | ||
191 | toshiba_spi_write(0xc1, 0x11, 1); | ||
192 | toshiba_spi_write(0xc2, 0x11, 1); | ||
193 | mdelay(1); | ||
194 | toshiba_spi_write(0xc3, 0x3232, 2); | ||
195 | mdelay(1); | ||
196 | toshiba_spi_write(0xc4, 0x3232, 2); | ||
197 | mdelay(1); | ||
198 | toshiba_spi_write(0xc5, 0x3232, 2); | ||
199 | mdelay(1); | ||
200 | toshiba_spi_write(0xc6, 0x3232, 2); | ||
201 | mdelay(1); | ||
202 | toshiba_spi_write(0xc7, 0x6445, 2); | ||
203 | mdelay(1); | ||
204 | toshiba_spi_write(0xc8, 0x44, 1); | ||
205 | toshiba_spi_write(0xc9, 0x52, 1); | ||
206 | mdelay(1); | ||
207 | toshiba_spi_write(0xca, 0x00, 1); | ||
208 | mdelay(1); | ||
209 | toshiba_spi_write(0xec, 0x02a4, 2); /* 0x02a4 */ | ||
210 | mdelay(1); | ||
211 | toshiba_spi_write(0xcf, 0x01, 1); | ||
212 | mdelay(1); | ||
213 | toshiba_spi_write(0xd0, 0xc003, 2); /* c003 */ | ||
214 | mdelay(1); | ||
215 | toshiba_spi_write(0xd1, 0x01, 1); | ||
216 | mdelay(1); | ||
217 | toshiba_spi_write(0xd2, 0x0028, 2); | ||
218 | mdelay(1); | ||
219 | toshiba_spi_write(0xd3, 0x0028, 2); | ||
220 | mdelay(1); | ||
221 | toshiba_spi_write(0xd4, 0x26a4, 2); | ||
222 | mdelay(1); | ||
223 | toshiba_spi_write(0xd5, 0x20, 1); | ||
224 | mdelay(1); | ||
225 | toshiba_spi_write(0xef, 0x3200, 2); | ||
226 | mdelay(32); | ||
227 | toshiba_spi_write(0xbc, 0x80, 1); /* wvga pass through */ | ||
228 | toshiba_spi_write(0x3b, 0x00, 1); | ||
229 | mdelay(1); | ||
230 | toshiba_spi_write(0xb0, 0x16, 1); | ||
231 | mdelay(1); | ||
232 | toshiba_spi_write(0xb8, 0xfff5, 2); | ||
233 | mdelay(1); | ||
234 | toshiba_spi_write(0x11, 0, 0); | ||
235 | mdelay(5); | ||
236 | toshiba_spi_write(0x29, 0, 0); | ||
237 | mdelay(5); | ||
238 | toshiba_state.display_on = TRUE; | ||
239 | } | ||
240 | |||
241 | data = 0; | ||
242 | toshiba_spi_read_bytes(0x04, &data, 3); | ||
243 | printk(KERN_INFO "toshiba_disp_on: id=%x\n", data); | ||
244 | |||
245 | } | ||
246 | |||
247 | static int lcdc_toshiba_panel_on(struct platform_device *pdev) | ||
248 | { | ||
249 | if (!toshiba_state.disp_initialized) { | ||
250 | /* Configure reset GPIO that drives DAC */ | ||
251 | if (lcdc_toshiba_pdata->panel_config_gpio) | ||
252 | lcdc_toshiba_pdata->panel_config_gpio(1); | ||
253 | toshiba_disp_powerup(); | ||
254 | toshiba_disp_on(); | ||
255 | toshiba_state.disp_initialized = TRUE; | ||
256 | } | ||
257 | return 0; | ||
258 | } | ||
259 | |||
260 | static int lcdc_toshiba_panel_off(struct platform_device *pdev) | ||
261 | { | ||
262 | if (toshiba_state.disp_powered_up && toshiba_state.display_on) { | ||
263 | /* Main panel power off (Deep standby in) */ | ||
264 | |||
265 | toshiba_spi_write(0x28, 0, 0); /* display off */ | ||
266 | mdelay(1); | ||
267 | toshiba_spi_write(0xb8, 0x8002, 2); /* output control */ | ||
268 | mdelay(1); | ||
269 | toshiba_spi_write(0x10, 0x00, 1); /* sleep mode in */ | ||
270 | mdelay(85); /* wait 85 msec */ | ||
271 | toshiba_spi_write(0xb0, 0x00, 1); /* deep standby in */ | ||
272 | mdelay(1); | ||
273 | if (lcdc_toshiba_pdata->panel_config_gpio) | ||
274 | lcdc_toshiba_pdata->panel_config_gpio(0); | ||
275 | toshiba_state.display_on = FALSE; | ||
276 | toshiba_state.disp_initialized = FALSE; | ||
277 | } | ||
278 | return 0; | ||
279 | } | ||
280 | |||
281 | static void lcdc_toshiba_set_backlight(struct msm_fb_data_type *mfd) | ||
282 | { | ||
283 | int bl_level; | ||
284 | int ret = -EPERM; | ||
285 | |||
286 | bl_level = mfd->bl_level; | ||
287 | ret = pmic_set_led_intensity(LED_LCD, bl_level); | ||
288 | |||
289 | if (ret) | ||
290 | printk(KERN_WARNING "%s: can't set lcd backlight!\n", | ||
291 | __func__); | ||
292 | } | ||
293 | |||
294 | static int __init toshiba_probe(struct platform_device *pdev) | ||
295 | { | ||
296 | if (pdev->id == 0) { | ||
297 | lcdc_toshiba_pdata = pdev->dev.platform_data; | ||
298 | spi_pin_assign(); | ||
299 | return 0; | ||
300 | } | ||
301 | msm_fb_add_device(pdev); | ||
302 | return 0; | ||
303 | } | ||
304 | |||
305 | static struct platform_driver this_driver = { | ||
306 | .probe = toshiba_probe, | ||
307 | .driver = { | ||
308 | .name = "lcdc_toshiba_wvga", | ||
309 | }, | ||
310 | }; | ||
311 | |||
312 | static struct msm_fb_panel_data toshiba_panel_data = { | ||
313 | .on = lcdc_toshiba_panel_on, | ||
314 | .off = lcdc_toshiba_panel_off, | ||
315 | .set_backlight = lcdc_toshiba_set_backlight, | ||
316 | }; | ||
317 | |||
318 | static struct platform_device this_device = { | ||
319 | .name = "lcdc_toshiba_wvga", | ||
320 | .id = 1, | ||
321 | .dev = { | ||
322 | .platform_data = &toshiba_panel_data, | ||
323 | } | ||
324 | }; | ||
325 | |||
326 | static int __init lcdc_toshiba_panel_init(void) | ||
327 | { | ||
328 | int ret; | ||
329 | struct msm_panel_info *pinfo; | ||
330 | #ifdef CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM | ||
331 | if (mddi_get_client_id() != 0) | ||
332 | return 0; | ||
333 | |||
334 | ret = msm_fb_detect_client("lcdc_toshiba_wvga_pt"); | ||
335 | if (ret) | ||
336 | return 0; | ||
337 | |||
338 | #endif | ||
339 | |||
340 | ret = platform_driver_register(&this_driver); | ||
341 | if (ret) | ||
342 | return ret; | ||
343 | |||
344 | pinfo = &toshiba_panel_data.panel_info; | ||
345 | pinfo->xres = 480; | ||
346 | pinfo->yres = 800; | ||
347 | pinfo->type = LCDC_PANEL; | ||
348 | pinfo->pdest = DISPLAY_1; | ||
349 | pinfo->wait_cycle = 0; | ||
350 | pinfo->bpp = 18; | ||
351 | pinfo->fb_num = 2; | ||
352 | /* 30Mhz mdp_lcdc_pclk and mdp_lcdc_pad_pcl */ | ||
353 | pinfo->clk_rate = 27648000; | ||
354 | pinfo->bl_max = 15; | ||
355 | pinfo->bl_min = 1; | ||
356 | |||
357 | pinfo->lcdc.h_back_porch = 184; /* hsw = 8 + hbp=184 */ | ||
358 | pinfo->lcdc.h_front_porch = 4; | ||
359 | pinfo->lcdc.h_pulse_width = 8; | ||
360 | pinfo->lcdc.v_back_porch = 2; /* vsw=1 + vbp = 2 */ | ||
361 | pinfo->lcdc.v_front_porch = 3; | ||
362 | pinfo->lcdc.v_pulse_width = 1; | ||
363 | pinfo->lcdc.border_clr = 0; /* blk */ | ||
364 | pinfo->lcdc.underflow_clr = 0xff; /* blue */ | ||
365 | pinfo->lcdc.hsync_skew = 0; | ||
366 | |||
367 | ret = platform_device_register(&this_device); | ||
368 | if (ret) | ||
369 | platform_driver_unregister(&this_driver); | ||
370 | |||
371 | return ret; | ||
372 | } | ||
373 | |||
374 | device_initcall(lcdc_toshiba_panel_init); | ||
diff --git a/drivers/staging/msm/lcdc_wxga.c b/drivers/staging/msm/lcdc_wxga.c new file mode 100644 index 000000000000..202c92c0ef54 --- /dev/null +++ b/drivers/staging/msm/lcdc_wxga.c | |||
@@ -0,0 +1,56 @@ | |||
1 | /* Copyright (c) 2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include "msm_fb.h" | ||
19 | |||
20 | static int __init lcdc_wxga_init(void) | ||
21 | { | ||
22 | int ret; | ||
23 | struct msm_panel_info pinfo; | ||
24 | |||
25 | #ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT | ||
26 | if (msm_fb_detect_client("lcdc_wxga")) | ||
27 | return 0; | ||
28 | #endif | ||
29 | |||
30 | pinfo.xres = 1280; | ||
31 | pinfo.yres = 720; | ||
32 | pinfo.type = LCDC_PANEL; | ||
33 | pinfo.pdest = DISPLAY_1; | ||
34 | pinfo.wait_cycle = 0; | ||
35 | pinfo.bpp = 24; | ||
36 | pinfo.fb_num = 2; | ||
37 | pinfo.clk_rate = 74250000; | ||
38 | |||
39 | pinfo.lcdc.h_back_porch = 124; | ||
40 | pinfo.lcdc.h_front_porch = 110; | ||
41 | pinfo.lcdc.h_pulse_width = 136; | ||
42 | pinfo.lcdc.v_back_porch = 19; | ||
43 | pinfo.lcdc.v_front_porch = 5; | ||
44 | pinfo.lcdc.v_pulse_width = 6; | ||
45 | pinfo.lcdc.border_clr = 0; /* blk */ | ||
46 | pinfo.lcdc.underflow_clr = 0xff; /* blue */ | ||
47 | pinfo.lcdc.hsync_skew = 0; | ||
48 | |||
49 | ret = lcdc_device_register(&pinfo); | ||
50 | if (ret) | ||
51 | printk(KERN_ERR "%s: failed to register device!\n", __func__); | ||
52 | |||
53 | return ret; | ||
54 | } | ||
55 | |||
56 | module_init(lcdc_wxga_init); | ||
diff --git a/drivers/staging/msm/logo.c b/drivers/staging/msm/logo.c new file mode 100644 index 000000000000..7272765f48cd --- /dev/null +++ b/drivers/staging/msm/logo.c | |||
@@ -0,0 +1,98 @@ | |||
1 | /* drivers/video/msm/logo.c | ||
2 | * | ||
3 | * Show Logo in RLE 565 format | ||
4 | * | ||
5 | * Copyright (C) 2008 Google Incorporated | ||
6 | * | ||
7 | * This software is licensed under the terms of the GNU General Public | ||
8 | * License version 2, as published by the Free Software Foundation, and | ||
9 | * may be copied, distributed, and modified under those terms. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | */ | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/types.h> | ||
19 | #include <linux/fb.h> | ||
20 | #include <linux/vt_kern.h> | ||
21 | #include <linux/unistd.h> | ||
22 | #include <linux/syscalls.h> | ||
23 | |||
24 | #include <linux/irq.h> | ||
25 | #include <asm/system.h> | ||
26 | |||
27 | #define fb_width(fb) ((fb)->var.xres) | ||
28 | #define fb_height(fb) ((fb)->var.yres) | ||
29 | #define fb_size(fb) ((fb)->var.xres * (fb)->var.yres * 2) | ||
30 | |||
31 | static void memset16(void *_ptr, unsigned short val, unsigned count) | ||
32 | { | ||
33 | unsigned short *ptr = _ptr; | ||
34 | count >>= 1; | ||
35 | while (count--) | ||
36 | *ptr++ = val; | ||
37 | } | ||
38 | |||
39 | /* 565RLE image format: [count(2 bytes), rle(2 bytes)] */ | ||
40 | int load_565rle_image(char *filename) | ||
41 | { | ||
42 | struct fb_info *info; | ||
43 | int fd, err = 0; | ||
44 | unsigned count, max; | ||
45 | unsigned short *data, *bits, *ptr; | ||
46 | |||
47 | info = registered_fb[0]; | ||
48 | if (!info) { | ||
49 | printk(KERN_WARNING "%s: Can not access framebuffer\n", | ||
50 | __func__); | ||
51 | return -ENODEV; | ||
52 | } | ||
53 | |||
54 | fd = sys_open(filename, O_RDONLY, 0); | ||
55 | if (fd < 0) { | ||
56 | printk(KERN_WARNING "%s: Can not open %s\n", | ||
57 | __func__, filename); | ||
58 | return -ENOENT; | ||
59 | } | ||
60 | count = (unsigned)sys_lseek(fd, (off_t)0, 2); | ||
61 | if (count == 0) { | ||
62 | sys_close(fd); | ||
63 | err = -EIO; | ||
64 | goto err_logo_close_file; | ||
65 | } | ||
66 | sys_lseek(fd, (off_t)0, 0); | ||
67 | data = kmalloc(count, GFP_KERNEL); | ||
68 | if (!data) { | ||
69 | printk(KERN_WARNING "%s: Can not alloc data\n", __func__); | ||
70 | err = -ENOMEM; | ||
71 | goto err_logo_close_file; | ||
72 | } | ||
73 | if ((unsigned)sys_read(fd, (char *)data, count) != count) { | ||
74 | err = -EIO; | ||
75 | goto err_logo_free_data; | ||
76 | } | ||
77 | |||
78 | max = fb_width(info) * fb_height(info); | ||
79 | ptr = data; | ||
80 | bits = (unsigned short *)(info->screen_base); | ||
81 | while (count > 3) { | ||
82 | unsigned n = ptr[0]; | ||
83 | if (n > max) | ||
84 | break; | ||
85 | memset16(bits, ptr[1], n << 1); | ||
86 | bits += n; | ||
87 | max -= n; | ||
88 | ptr += 2; | ||
89 | count -= 4; | ||
90 | } | ||
91 | |||
92 | err_logo_free_data: | ||
93 | kfree(data); | ||
94 | err_logo_close_file: | ||
95 | sys_close(fd); | ||
96 | return err; | ||
97 | } | ||
98 | EXPORT_SYMBOL(load_565rle_image); | ||
diff --git a/drivers/staging/msm/mddi.c b/drivers/staging/msm/mddi.c new file mode 100644 index 000000000000..132eb1adff16 --- /dev/null +++ b/drivers/staging/msm/mddi.c | |||
@@ -0,0 +1,375 @@ | |||
1 | /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/sched.h> | ||
21 | #include <linux/time.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/spinlock.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <mach/hardware.h> | ||
27 | #include <asm/io.h> | ||
28 | |||
29 | #include <asm/system.h> | ||
30 | #include <asm/mach-types.h> | ||
31 | #include <linux/semaphore.h> | ||
32 | #include <linux/uaccess.h> | ||
33 | #include <linux/clk.h> | ||
34 | #include <linux/platform_device.h> | ||
35 | |||
36 | #include "msm_fb.h" | ||
37 | #include "mddihosti.h" | ||
38 | #include "mddihost.h" | ||
39 | #include <mach/gpio.h> | ||
40 | #include <mach/clk.h> | ||
41 | |||
42 | static int mddi_probe(struct platform_device *pdev); | ||
43 | static int mddi_remove(struct platform_device *pdev); | ||
44 | |||
45 | static int mddi_off(struct platform_device *pdev); | ||
46 | static int mddi_on(struct platform_device *pdev); | ||
47 | |||
48 | static int mddi_suspend(struct platform_device *pdev, pm_message_t state); | ||
49 | static int mddi_resume(struct platform_device *pdev); | ||
50 | |||
51 | #ifdef CONFIG_HAS_EARLYSUSPEND | ||
52 | static void mddi_early_suspend(struct early_suspend *h); | ||
53 | static void mddi_early_resume(struct early_suspend *h); | ||
54 | #endif | ||
55 | |||
56 | static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST]; | ||
57 | static int pdev_list_cnt; | ||
58 | static struct clk *mddi_clk; | ||
59 | static struct clk *mddi_pclk; | ||
60 | static struct mddi_platform_data *mddi_pdata; | ||
61 | |||
62 | static struct platform_driver mddi_driver = { | ||
63 | .probe = mddi_probe, | ||
64 | .remove = mddi_remove, | ||
65 | #ifndef CONFIG_HAS_EARLYSUSPEND | ||
66 | #ifdef CONFIG_PM | ||
67 | .suspend = mddi_suspend, | ||
68 | .resume = mddi_resume, | ||
69 | #endif | ||
70 | #endif | ||
71 | .suspend_late = NULL, | ||
72 | .resume_early = NULL, | ||
73 | .shutdown = NULL, | ||
74 | .driver = { | ||
75 | .name = "mddi", | ||
76 | }, | ||
77 | }; | ||
78 | |||
79 | extern int int_mddi_pri_flag; | ||
80 | |||
81 | static int mddi_off(struct platform_device *pdev) | ||
82 | { | ||
83 | int ret = 0; | ||
84 | |||
85 | ret = panel_next_off(pdev); | ||
86 | |||
87 | if (mddi_pdata && mddi_pdata->mddi_power_save) | ||
88 | mddi_pdata->mddi_power_save(0); | ||
89 | |||
90 | return ret; | ||
91 | } | ||
92 | |||
93 | static int mddi_on(struct platform_device *pdev) | ||
94 | { | ||
95 | int ret = 0; | ||
96 | u32 clk_rate; | ||
97 | struct msm_fb_data_type *mfd; | ||
98 | |||
99 | mfd = platform_get_drvdata(pdev); | ||
100 | |||
101 | if (mddi_pdata && mddi_pdata->mddi_power_save) | ||
102 | mddi_pdata->mddi_power_save(1); | ||
103 | |||
104 | clk_rate = mfd->fbi->var.pixclock; | ||
105 | clk_rate = min(clk_rate, mfd->panel_info.clk_max); | ||
106 | |||
107 | if (mddi_pdata && | ||
108 | mddi_pdata->mddi_sel_clk && | ||
109 | mddi_pdata->mddi_sel_clk(&clk_rate)) | ||
110 | printk(KERN_ERR | ||
111 | "%s: can't select mddi io clk targate rate = %d\n", | ||
112 | __func__, clk_rate); | ||
113 | |||
114 | if (clk_set_min_rate(mddi_clk, clk_rate) < 0) | ||
115 | printk(KERN_ERR "%s: clk_set_min_rate failed\n", | ||
116 | __func__); | ||
117 | |||
118 | ret = panel_next_on(pdev); | ||
119 | |||
120 | return ret; | ||
121 | } | ||
122 | |||
123 | static int mddi_resource_initialized; | ||
124 | |||
125 | static int mddi_probe(struct platform_device *pdev) | ||
126 | { | ||
127 | struct msm_fb_data_type *mfd; | ||
128 | struct platform_device *mdp_dev = NULL; | ||
129 | struct msm_fb_panel_data *pdata = NULL; | ||
130 | int rc; | ||
131 | resource_size_t size ; | ||
132 | u32 clk_rate; | ||
133 | |||
134 | if ((pdev->id == 0) && (pdev->num_resources >= 0)) { | ||
135 | mddi_pdata = pdev->dev.platform_data; | ||
136 | |||
137 | size = resource_size(&pdev->resource[0]); | ||
138 | msm_pmdh_base = ioremap(pdev->resource[0].start, size); | ||
139 | |||
140 | MSM_FB_INFO("primary mddi base phy_addr = 0x%x virt = 0x%x\n", | ||
141 | pdev->resource[0].start, (int) msm_pmdh_base); | ||
142 | |||
143 | if (unlikely(!msm_pmdh_base)) | ||
144 | return -ENOMEM; | ||
145 | |||
146 | if (mddi_pdata && mddi_pdata->mddi_power_save) | ||
147 | mddi_pdata->mddi_power_save(1); | ||
148 | |||
149 | mddi_resource_initialized = 1; | ||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | if (!mddi_resource_initialized) | ||
154 | return -EPERM; | ||
155 | |||
156 | mfd = platform_get_drvdata(pdev); | ||
157 | |||
158 | if (!mfd) | ||
159 | return -ENODEV; | ||
160 | |||
161 | if (mfd->key != MFD_KEY) | ||
162 | return -EINVAL; | ||
163 | |||
164 | if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST) | ||
165 | return -ENOMEM; | ||
166 | |||
167 | mdp_dev = platform_device_alloc("mdp", pdev->id); | ||
168 | if (!mdp_dev) | ||
169 | return -ENOMEM; | ||
170 | |||
171 | /* | ||
172 | * link to the latest pdev | ||
173 | */ | ||
174 | mfd->pdev = mdp_dev; | ||
175 | mfd->dest = DISPLAY_LCD; | ||
176 | |||
177 | /* | ||
178 | * alloc panel device data | ||
179 | */ | ||
180 | if (platform_device_add_data | ||
181 | (mdp_dev, pdev->dev.platform_data, | ||
182 | sizeof(struct msm_fb_panel_data))) { | ||
183 | printk(KERN_ERR "mddi_probe: platform_device_add_data failed!\n"); | ||
184 | platform_device_put(mdp_dev); | ||
185 | return -ENOMEM; | ||
186 | } | ||
187 | /* | ||
188 | * data chain | ||
189 | */ | ||
190 | pdata = mdp_dev->dev.platform_data; | ||
191 | pdata->on = mddi_on; | ||
192 | pdata->off = mddi_off; | ||
193 | pdata->next = pdev; | ||
194 | |||
195 | /* | ||
196 | * get/set panel specific fb info | ||
197 | */ | ||
198 | mfd->panel_info = pdata->panel_info; | ||
199 | mfd->fb_imgType = MDP_RGB_565; | ||
200 | |||
201 | clk_rate = mfd->panel_info.clk_max; | ||
202 | if (mddi_pdata && | ||
203 | mddi_pdata->mddi_sel_clk && | ||
204 | mddi_pdata->mddi_sel_clk(&clk_rate)) | ||
205 | printk(KERN_ERR | ||
206 | "%s: can't select mddi io clk targate rate = %d\n", | ||
207 | __func__, clk_rate); | ||
208 | |||
209 | if (clk_set_max_rate(mddi_clk, clk_rate) < 0) | ||
210 | printk(KERN_ERR "%s: clk_set_max_rate failed\n", __func__); | ||
211 | mfd->panel_info.clk_rate = mfd->panel_info.clk_min; | ||
212 | |||
213 | /* | ||
214 | * set driver data | ||
215 | */ | ||
216 | platform_set_drvdata(mdp_dev, mfd); | ||
217 | |||
218 | /* | ||
219 | * register in mdp driver | ||
220 | */ | ||
221 | rc = platform_device_add(mdp_dev); | ||
222 | if (rc) | ||
223 | goto mddi_probe_err; | ||
224 | |||
225 | pdev_list[pdev_list_cnt++] = pdev; | ||
226 | |||
227 | #ifdef CONFIG_HAS_EARLYSUSPEND | ||
228 | mfd->mddi_early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB; | ||
229 | mfd->mddi_early_suspend.suspend = mddi_early_suspend; | ||
230 | mfd->mddi_early_suspend.resume = mddi_early_resume; | ||
231 | register_early_suspend(&mfd->mddi_early_suspend); | ||
232 | #endif | ||
233 | |||
234 | return 0; | ||
235 | |||
236 | mddi_probe_err: | ||
237 | platform_device_put(mdp_dev); | ||
238 | return rc; | ||
239 | } | ||
240 | |||
241 | static int mddi_pad_ctrl; | ||
242 | static int mddi_power_locked; | ||
243 | static int mddi_is_in_suspend; | ||
244 | |||
245 | void mddi_disable(int lock) | ||
246 | { | ||
247 | mddi_host_type host_idx = MDDI_HOST_PRIM; | ||
248 | |||
249 | if (mddi_power_locked) | ||
250 | return; | ||
251 | |||
252 | if (lock) | ||
253 | mddi_power_locked = 1; | ||
254 | |||
255 | if (mddi_host_timer.function) | ||
256 | del_timer_sync(&mddi_host_timer); | ||
257 | |||
258 | mddi_pad_ctrl = mddi_host_reg_in(PAD_CTL); | ||
259 | mddi_host_reg_out(PAD_CTL, 0x0); | ||
260 | |||
261 | if (clk_set_min_rate(mddi_clk, 0) < 0) | ||
262 | printk(KERN_ERR "%s: clk_set_min_rate failed\n", __func__); | ||
263 | |||
264 | clk_disable(mddi_clk); | ||
265 | if (mddi_pclk) | ||
266 | clk_disable(mddi_pclk); | ||
267 | disable_irq(INT_MDDI_PRI); | ||
268 | |||
269 | if (mddi_pdata && mddi_pdata->mddi_power_save) | ||
270 | mddi_pdata->mddi_power_save(0); | ||
271 | } | ||
272 | |||
273 | static int mddi_suspend(struct platform_device *pdev, pm_message_t state) | ||
274 | { | ||
275 | if (mddi_is_in_suspend) | ||
276 | return 0; | ||
277 | |||
278 | mddi_is_in_suspend = 1; | ||
279 | mddi_disable(0); | ||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | static int mddi_resume(struct platform_device *pdev) | ||
284 | { | ||
285 | mddi_host_type host_idx = MDDI_HOST_PRIM; | ||
286 | |||
287 | if (!mddi_is_in_suspend) | ||
288 | return 0; | ||
289 | |||
290 | mddi_is_in_suspend = 0; | ||
291 | |||
292 | if (mddi_power_locked) | ||
293 | return 0; | ||
294 | |||
295 | enable_irq(INT_MDDI_PRI); | ||
296 | clk_enable(mddi_clk); | ||
297 | if (mddi_pclk) | ||
298 | clk_enable(mddi_pclk); | ||
299 | mddi_host_reg_out(PAD_CTL, mddi_pad_ctrl); | ||
300 | |||
301 | if (mddi_host_timer.function) | ||
302 | mddi_host_timer_service(0); | ||
303 | |||
304 | return 0; | ||
305 | } | ||
306 | |||
307 | #ifdef CONFIG_HAS_EARLYSUSPEND | ||
308 | static void mddi_early_suspend(struct early_suspend *h) | ||
309 | { | ||
310 | pm_message_t state; | ||
311 | struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type, | ||
312 | mddi_early_suspend); | ||
313 | |||
314 | state.event = PM_EVENT_SUSPEND; | ||
315 | mddi_suspend(mfd->pdev, state); | ||
316 | } | ||
317 | |||
318 | static void mddi_early_resume(struct early_suspend *h) | ||
319 | { | ||
320 | struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type, | ||
321 | mddi_early_suspend); | ||
322 | mddi_resume(mfd->pdev); | ||
323 | } | ||
324 | #endif | ||
325 | |||
326 | static int mddi_remove(struct platform_device *pdev) | ||
327 | { | ||
328 | if (mddi_host_timer.function) | ||
329 | del_timer_sync(&mddi_host_timer); | ||
330 | |||
331 | iounmap(msm_pmdh_base); | ||
332 | |||
333 | return 0; | ||
334 | } | ||
335 | |||
336 | static int mddi_register_driver(void) | ||
337 | { | ||
338 | return platform_driver_register(&mddi_driver); | ||
339 | } | ||
340 | |||
341 | static int __init mddi_driver_init(void) | ||
342 | { | ||
343 | int ret; | ||
344 | |||
345 | mddi_clk = clk_get(NULL, "mddi_clk"); | ||
346 | if (IS_ERR(mddi_clk)) { | ||
347 | printk(KERN_ERR "can't find mddi_clk \n"); | ||
348 | return PTR_ERR(mddi_clk); | ||
349 | } | ||
350 | clk_enable(mddi_clk); | ||
351 | |||
352 | mddi_pclk = clk_get(NULL, "mddi_pclk"); | ||
353 | if (IS_ERR(mddi_pclk)) | ||
354 | mddi_pclk = NULL; | ||
355 | else | ||
356 | clk_enable(mddi_pclk); | ||
357 | |||
358 | ret = mddi_register_driver(); | ||
359 | if (ret) { | ||
360 | clk_disable(mddi_clk); | ||
361 | clk_put(mddi_clk); | ||
362 | if (mddi_pclk) { | ||
363 | clk_disable(mddi_pclk); | ||
364 | clk_put(mddi_pclk); | ||
365 | } | ||
366 | printk(KERN_ERR "mddi_register_driver() failed!\n"); | ||
367 | return ret; | ||
368 | } | ||
369 | |||
370 | mddi_init(); | ||
371 | |||
372 | return ret; | ||
373 | } | ||
374 | |||
375 | module_init(mddi_driver_init); | ||
diff --git a/drivers/staging/msm/mddi_ext.c b/drivers/staging/msm/mddi_ext.c new file mode 100644 index 000000000000..c0c168c7199d --- /dev/null +++ b/drivers/staging/msm/mddi_ext.c | |||
@@ -0,0 +1,320 @@ | |||
1 | /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/sched.h> | ||
21 | #include <linux/time.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/spinlock.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <mach/hardware.h> | ||
27 | #include <asm/io.h> | ||
28 | |||
29 | #include <asm/system.h> | ||
30 | #include <asm/mach-types.h> | ||
31 | #include <linux/semaphore.h> | ||
32 | #include <linux/uaccess.h> | ||
33 | #include <linux/clk.h> | ||
34 | #include <mach/clk.h> | ||
35 | #include <linux/platform_device.h> | ||
36 | |||
37 | #include "msm_fb.h" | ||
38 | #include "mddihosti.h" | ||
39 | |||
40 | static int mddi_ext_probe(struct platform_device *pdev); | ||
41 | static int mddi_ext_remove(struct platform_device *pdev); | ||
42 | |||
43 | static int mddi_ext_off(struct platform_device *pdev); | ||
44 | static int mddi_ext_on(struct platform_device *pdev); | ||
45 | |||
46 | static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST]; | ||
47 | static int pdev_list_cnt; | ||
48 | |||
49 | static int mddi_ext_suspend(struct platform_device *pdev, pm_message_t state); | ||
50 | static int mddi_ext_resume(struct platform_device *pdev); | ||
51 | |||
52 | #ifdef CONFIG_HAS_EARLYSUSPEND | ||
53 | static void mddi_ext_early_suspend(struct early_suspend *h); | ||
54 | static void mddi_ext_early_resume(struct early_suspend *h); | ||
55 | #endif | ||
56 | |||
57 | static struct platform_driver mddi_ext_driver = { | ||
58 | .probe = mddi_ext_probe, | ||
59 | .remove = mddi_ext_remove, | ||
60 | #ifndef CONFIG_HAS_EARLYSUSPEND | ||
61 | #ifdef CONFIG_PM | ||
62 | .suspend = mddi_ext_suspend, | ||
63 | .resume = mddi_ext_resume, | ||
64 | #endif | ||
65 | #endif | ||
66 | .resume_early = NULL, | ||
67 | .resume = NULL, | ||
68 | .shutdown = NULL, | ||
69 | .driver = { | ||
70 | .name = "mddi_ext", | ||
71 | }, | ||
72 | }; | ||
73 | |||
74 | static struct clk *mddi_ext_clk; | ||
75 | static struct mddi_platform_data *mddi_ext_pdata; | ||
76 | |||
77 | extern int int_mddi_ext_flag; | ||
78 | |||
79 | static int mddi_ext_off(struct platform_device *pdev) | ||
80 | { | ||
81 | int ret = 0; | ||
82 | |||
83 | ret = panel_next_off(pdev); | ||
84 | mddi_host_stop_ext_display(); | ||
85 | |||
86 | return ret; | ||
87 | } | ||
88 | |||
89 | static int mddi_ext_on(struct platform_device *pdev) | ||
90 | { | ||
91 | int ret = 0; | ||
92 | u32 clk_rate; | ||
93 | struct msm_fb_data_type *mfd; | ||
94 | |||
95 | mfd = platform_get_drvdata(pdev); | ||
96 | |||
97 | clk_rate = mfd->fbi->var.pixclock; | ||
98 | clk_rate = min(clk_rate, mfd->panel_info.clk_max); | ||
99 | |||
100 | if (mddi_ext_pdata && | ||
101 | mddi_ext_pdata->mddi_sel_clk && | ||
102 | mddi_ext_pdata->mddi_sel_clk(&clk_rate)) | ||
103 | printk(KERN_ERR | ||
104 | "%s: can't select mddi io clk targate rate = %d\n", | ||
105 | __func__, clk_rate); | ||
106 | |||
107 | if (clk_set_min_rate(mddi_ext_clk, clk_rate) < 0) | ||
108 | printk(KERN_ERR "%s: clk_set_min_rate failed\n", | ||
109 | __func__); | ||
110 | |||
111 | mddi_host_start_ext_display(); | ||
112 | ret = panel_next_on(pdev); | ||
113 | |||
114 | return ret; | ||
115 | } | ||
116 | |||
117 | static int mddi_ext_resource_initialized; | ||
118 | |||
119 | static int mddi_ext_probe(struct platform_device *pdev) | ||
120 | { | ||
121 | struct msm_fb_data_type *mfd; | ||
122 | struct platform_device *mdp_dev = NULL; | ||
123 | struct msm_fb_panel_data *pdata = NULL; | ||
124 | int rc; | ||
125 | resource_size_t size ; | ||
126 | u32 clk_rate; | ||
127 | |||
128 | if ((pdev->id == 0) && (pdev->num_resources >= 0)) { | ||
129 | mddi_ext_pdata = pdev->dev.platform_data; | ||
130 | |||
131 | size = resource_size(&pdev->resource[0]); | ||
132 | msm_emdh_base = ioremap(pdev->resource[0].start, size); | ||
133 | |||
134 | MSM_FB_INFO("external mddi base address = 0x%x\n", | ||
135 | pdev->resource[0].start); | ||
136 | |||
137 | if (unlikely(!msm_emdh_base)) | ||
138 | return -ENOMEM; | ||
139 | |||
140 | mddi_ext_resource_initialized = 1; | ||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | if (!mddi_ext_resource_initialized) | ||
145 | return -EPERM; | ||
146 | |||
147 | mfd = platform_get_drvdata(pdev); | ||
148 | |||
149 | if (!mfd) | ||
150 | return -ENODEV; | ||
151 | |||
152 | if (mfd->key != MFD_KEY) | ||
153 | return -EINVAL; | ||
154 | |||
155 | if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST) | ||
156 | return -ENOMEM; | ||
157 | |||
158 | mdp_dev = platform_device_alloc("mdp", pdev->id); | ||
159 | if (!mdp_dev) | ||
160 | return -ENOMEM; | ||
161 | |||
162 | /* | ||
163 | * link to the latest pdev | ||
164 | */ | ||
165 | mfd->pdev = mdp_dev; | ||
166 | mfd->dest = DISPLAY_EXT_MDDI; | ||
167 | |||
168 | /* | ||
169 | * alloc panel device data | ||
170 | */ | ||
171 | if (platform_device_add_data | ||
172 | (mdp_dev, pdev->dev.platform_data, | ||
173 | sizeof(struct msm_fb_panel_data))) { | ||
174 | printk(KERN_ERR "mddi_ext_probe: platform_device_add_data failed!\n"); | ||
175 | platform_device_put(mdp_dev); | ||
176 | return -ENOMEM; | ||
177 | } | ||
178 | /* | ||
179 | * data chain | ||
180 | */ | ||
181 | pdata = mdp_dev->dev.platform_data; | ||
182 | pdata->on = mddi_ext_on; | ||
183 | pdata->off = mddi_ext_off; | ||
184 | pdata->next = pdev; | ||
185 | |||
186 | /* | ||
187 | * get/set panel specific fb info | ||
188 | */ | ||
189 | mfd->panel_info = pdata->panel_info; | ||
190 | mfd->fb_imgType = MDP_RGB_565; | ||
191 | |||
192 | clk_rate = mfd->panel_info.clk_max; | ||
193 | if (mddi_ext_pdata && | ||
194 | mddi_ext_pdata->mddi_sel_clk && | ||
195 | mddi_ext_pdata->mddi_sel_clk(&clk_rate)) | ||
196 | printk(KERN_ERR | ||
197 | "%s: can't select mddi io clk targate rate = %d\n", | ||
198 | __func__, clk_rate); | ||
199 | |||
200 | if (clk_set_max_rate(mddi_ext_clk, clk_rate) < 0) | ||
201 | printk(KERN_ERR "%s: clk_set_max_rate failed\n", __func__); | ||
202 | mfd->panel_info.clk_rate = mfd->panel_info.clk_min; | ||
203 | |||
204 | /* | ||
205 | * set driver data | ||
206 | */ | ||
207 | platform_set_drvdata(mdp_dev, mfd); | ||
208 | |||
209 | /* | ||
210 | * register in mdp driver | ||
211 | */ | ||
212 | rc = platform_device_add(mdp_dev); | ||
213 | if (rc) | ||
214 | goto mddi_ext_probe_err; | ||
215 | |||
216 | pdev_list[pdev_list_cnt++] = pdev; | ||
217 | |||
218 | #ifdef CONFIG_HAS_EARLYSUSPEND | ||
219 | mfd->mddi_ext_early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB; | ||
220 | mfd->mddi_ext_early_suspend.suspend = mddi_ext_early_suspend; | ||
221 | mfd->mddi_ext_early_suspend.resume = mddi_ext_early_resume; | ||
222 | register_early_suspend(&mfd->mddi_ext_early_suspend); | ||
223 | #endif | ||
224 | |||
225 | return 0; | ||
226 | |||
227 | mddi_ext_probe_err: | ||
228 | platform_device_put(mdp_dev); | ||
229 | return rc; | ||
230 | } | ||
231 | |||
232 | static int mddi_ext_is_in_suspend; | ||
233 | |||
234 | static int mddi_ext_suspend(struct platform_device *pdev, pm_message_t state) | ||
235 | { | ||
236 | if (mddi_ext_is_in_suspend) | ||
237 | return 0; | ||
238 | |||
239 | mddi_ext_is_in_suspend = 1; | ||
240 | |||
241 | if (clk_set_min_rate(mddi_ext_clk, 0) < 0) | ||
242 | printk(KERN_ERR "%s: clk_set_min_rate failed\n", __func__); | ||
243 | |||
244 | clk_disable(mddi_ext_clk); | ||
245 | disable_irq(INT_MDDI_EXT); | ||
246 | |||
247 | return 0; | ||
248 | } | ||
249 | |||
250 | static int mddi_ext_resume(struct platform_device *pdev) | ||
251 | { | ||
252 | struct msm_fb_data_type *mfd; | ||
253 | |||
254 | mfd = platform_get_drvdata(pdev); | ||
255 | |||
256 | if (!mddi_ext_is_in_suspend) | ||
257 | return 0; | ||
258 | |||
259 | mddi_ext_is_in_suspend = 0; | ||
260 | enable_irq(INT_MDDI_EXT); | ||
261 | |||
262 | clk_enable(mddi_ext_clk); | ||
263 | |||
264 | return 0; | ||
265 | } | ||
266 | |||
267 | #ifdef CONFIG_HAS_EARLYSUSPEND | ||
268 | static void mddi_ext_early_suspend(struct early_suspend *h) | ||
269 | { | ||
270 | pm_message_t state; | ||
271 | struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type, | ||
272 | mddi_ext_early_suspend); | ||
273 | |||
274 | state.event = PM_EVENT_SUSPEND; | ||
275 | mddi_ext_suspend(mfd->pdev, state); | ||
276 | } | ||
277 | |||
278 | static void mddi_ext_early_resume(struct early_suspend *h) | ||
279 | { | ||
280 | struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type, | ||
281 | mddi_ext_early_suspend); | ||
282 | mddi_ext_resume(mfd->pdev); | ||
283 | } | ||
284 | #endif | ||
285 | |||
286 | static int mddi_ext_remove(struct platform_device *pdev) | ||
287 | { | ||
288 | iounmap(msm_emdh_base); | ||
289 | return 0; | ||
290 | } | ||
291 | |||
292 | static int mddi_ext_register_driver(void) | ||
293 | { | ||
294 | return platform_driver_register(&mddi_ext_driver); | ||
295 | } | ||
296 | |||
297 | static int __init mddi_ext_driver_init(void) | ||
298 | { | ||
299 | int ret; | ||
300 | |||
301 | mddi_ext_clk = clk_get(NULL, "emdh_clk"); | ||
302 | if (IS_ERR(mddi_ext_clk)) { | ||
303 | printk(KERN_ERR "can't find emdh_clk\n"); | ||
304 | return PTR_ERR(mddi_ext_clk); | ||
305 | } | ||
306 | clk_enable(mddi_ext_clk); | ||
307 | |||
308 | ret = mddi_ext_register_driver(); | ||
309 | if (ret) { | ||
310 | clk_disable(mddi_ext_clk); | ||
311 | clk_put(mddi_ext_clk); | ||
312 | printk(KERN_ERR "mddi_ext_register_driver() failed!\n"); | ||
313 | return ret; | ||
314 | } | ||
315 | mddi_init(); | ||
316 | |||
317 | return ret; | ||
318 | } | ||
319 | |||
320 | module_init(mddi_ext_driver_init); | ||
diff --git a/drivers/staging/msm/mddi_ext_lcd.c b/drivers/staging/msm/mddi_ext_lcd.c new file mode 100644 index 000000000000..502e80d17ec7 --- /dev/null +++ b/drivers/staging/msm/mddi_ext_lcd.c | |||
@@ -0,0 +1,91 @@ | |||
1 | /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include "msm_fb.h" | ||
19 | #include "mddihost.h" | ||
20 | #include "mddihosti.h" | ||
21 | |||
22 | static int mddi_ext_lcd_on(struct platform_device *pdev); | ||
23 | static int mddi_ext_lcd_off(struct platform_device *pdev); | ||
24 | |||
25 | static int mddi_ext_lcd_on(struct platform_device *pdev) | ||
26 | { | ||
27 | return 0; | ||
28 | } | ||
29 | |||
30 | static int mddi_ext_lcd_off(struct platform_device *pdev) | ||
31 | { | ||
32 | return 0; | ||
33 | } | ||
34 | |||
35 | static int __init mddi_ext_lcd_probe(struct platform_device *pdev) | ||
36 | { | ||
37 | msm_fb_add_device(pdev); | ||
38 | |||
39 | return 0; | ||
40 | } | ||
41 | |||
42 | static struct platform_driver this_driver = { | ||
43 | .probe = mddi_ext_lcd_probe, | ||
44 | .driver = { | ||
45 | .name = "extmddi_svga", | ||
46 | }, | ||
47 | }; | ||
48 | |||
49 | static struct msm_fb_panel_data mddi_ext_lcd_panel_data = { | ||
50 | .panel_info.xres = 800, | ||
51 | .panel_info.yres = 600, | ||
52 | .panel_info.type = EXT_MDDI_PANEL, | ||
53 | .panel_info.pdest = DISPLAY_1, | ||
54 | .panel_info.wait_cycle = 0, | ||
55 | .panel_info.bpp = 18, | ||
56 | .panel_info.fb_num = 2, | ||
57 | .panel_info.clk_rate = 122880000, | ||
58 | .panel_info.clk_min = 120000000, | ||
59 | .panel_info.clk_max = 125000000, | ||
60 | .on = mddi_ext_lcd_on, | ||
61 | .off = mddi_ext_lcd_off, | ||
62 | }; | ||
63 | |||
64 | static struct platform_device this_device = { | ||
65 | .name = "extmddi_svga", | ||
66 | .id = 0, | ||
67 | .dev = { | ||
68 | .platform_data = &mddi_ext_lcd_panel_data, | ||
69 | } | ||
70 | }; | ||
71 | |||
72 | static int __init mddi_ext_lcd_init(void) | ||
73 | { | ||
74 | int ret; | ||
75 | struct msm_panel_info *pinfo; | ||
76 | |||
77 | ret = platform_driver_register(&this_driver); | ||
78 | if (!ret) { | ||
79 | pinfo = &mddi_ext_lcd_panel_data.panel_info; | ||
80 | pinfo->lcd.vsync_enable = FALSE; | ||
81 | pinfo->mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR; | ||
82 | |||
83 | ret = platform_device_register(&this_device); | ||
84 | if (ret) | ||
85 | platform_driver_unregister(&this_driver); | ||
86 | } | ||
87 | |||
88 | return ret; | ||
89 | } | ||
90 | |||
91 | module_init(mddi_ext_lcd_init); | ||
diff --git a/drivers/staging/msm/mddi_prism.c b/drivers/staging/msm/mddi_prism.c new file mode 100644 index 000000000000..489d40405a5f --- /dev/null +++ b/drivers/staging/msm/mddi_prism.c | |||
@@ -0,0 +1,114 @@ | |||
1 | /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include "msm_fb.h" | ||
19 | #include "mddihost.h" | ||
20 | #include "mddihosti.h" | ||
21 | |||
22 | static int prism_lcd_on(struct platform_device *pdev); | ||
23 | static int prism_lcd_off(struct platform_device *pdev); | ||
24 | |||
25 | static int prism_lcd_on(struct platform_device *pdev) | ||
26 | { | ||
27 | /* Set the MDP pixel data attributes for Primary Display */ | ||
28 | mddi_host_write_pix_attr_reg(0x00C3); | ||
29 | |||
30 | return 0; | ||
31 | } | ||
32 | |||
33 | static int prism_lcd_off(struct platform_device *pdev) | ||
34 | { | ||
35 | return 0; | ||
36 | } | ||
37 | |||
38 | static int __init prism_probe(struct platform_device *pdev) | ||
39 | { | ||
40 | msm_fb_add_device(pdev); | ||
41 | |||
42 | return 0; | ||
43 | } | ||
44 | |||
45 | static struct platform_driver this_driver = { | ||
46 | .probe = prism_probe, | ||
47 | .driver = { | ||
48 | .name = "mddi_prism_wvga", | ||
49 | }, | ||
50 | }; | ||
51 | |||
52 | static struct msm_fb_panel_data prism_panel_data = { | ||
53 | .on = prism_lcd_on, | ||
54 | .off = prism_lcd_off, | ||
55 | }; | ||
56 | |||
57 | static struct platform_device this_device = { | ||
58 | .name = "mddi_prism_wvga", | ||
59 | .id = 0, | ||
60 | .dev = { | ||
61 | .platform_data = &prism_panel_data, | ||
62 | } | ||
63 | }; | ||
64 | |||
65 | static int __init prism_init(void) | ||
66 | { | ||
67 | int ret; | ||
68 | struct msm_panel_info *pinfo; | ||
69 | |||
70 | #ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT | ||
71 | u32 id; | ||
72 | |||
73 | ret = msm_fb_detect_client("mddi_prism_wvga"); | ||
74 | if (ret == -ENODEV) | ||
75 | return 0; | ||
76 | |||
77 | if (ret) { | ||
78 | id = mddi_get_client_id(); | ||
79 | |||
80 | if (((id >> 16) != 0x4474) || ((id & 0xffff) == 0x8960)) | ||
81 | return 0; | ||
82 | } | ||
83 | #endif | ||
84 | ret = platform_driver_register(&this_driver); | ||
85 | if (!ret) { | ||
86 | pinfo = &prism_panel_data.panel_info; | ||
87 | pinfo->xres = 800; | ||
88 | pinfo->yres = 480; | ||
89 | pinfo->type = MDDI_PANEL; | ||
90 | pinfo->pdest = DISPLAY_1; | ||
91 | pinfo->mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR; | ||
92 | pinfo->wait_cycle = 0; | ||
93 | pinfo->bpp = 18; | ||
94 | pinfo->fb_num = 2; | ||
95 | pinfo->clk_rate = 153600000; | ||
96 | pinfo->clk_min = 150000000; | ||
97 | pinfo->clk_max = 160000000; | ||
98 | pinfo->lcd.vsync_enable = TRUE; | ||
99 | pinfo->lcd.refx100 = 6050; | ||
100 | pinfo->lcd.v_back_porch = 23; | ||
101 | pinfo->lcd.v_front_porch = 20; | ||
102 | pinfo->lcd.v_pulse_width = 105; | ||
103 | pinfo->lcd.hw_vsync_mode = TRUE; | ||
104 | pinfo->lcd.vsync_notifier_period = 0; | ||
105 | |||
106 | ret = platform_device_register(&this_device); | ||
107 | if (ret) | ||
108 | platform_driver_unregister(&this_driver); | ||
109 | } | ||
110 | |||
111 | return ret; | ||
112 | } | ||
113 | |||
114 | module_init(prism_init); | ||
diff --git a/drivers/staging/msm/mddi_sharp.c b/drivers/staging/msm/mddi_sharp.c new file mode 100644 index 000000000000..1da1be4052d0 --- /dev/null +++ b/drivers/staging/msm/mddi_sharp.c | |||
@@ -0,0 +1,892 @@ | |||
1 | /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include "msm_fb.h" | ||
19 | #include "mddihost.h" | ||
20 | #include "mddihosti.h" | ||
21 | |||
22 | #define SHARP_QVGA_PRIM 1 | ||
23 | #define SHARP_128X128_SECD 2 | ||
24 | |||
25 | extern uint32 mddi_host_core_version; | ||
26 | static boolean mddi_debug_prim_wait = FALSE; | ||
27 | static boolean mddi_sharp_vsync_wake = TRUE; | ||
28 | static boolean mddi_sharp_monitor_refresh_value = TRUE; | ||
29 | static boolean mddi_sharp_report_refresh_measurements = FALSE; | ||
30 | static uint32 mddi_sharp_rows_per_second = 13830; /* 5200000/376 */ | ||
31 | static uint32 mddi_sharp_rows_per_refresh = 338; | ||
32 | static uint32 mddi_sharp_usecs_per_refresh = 24440; /* (376+338)/5200000 */ | ||
33 | static boolean mddi_sharp_debug_60hz_refresh = FALSE; | ||
34 | |||
35 | extern mddi_gpio_info_type mddi_gpio; | ||
36 | extern boolean mddi_vsync_detect_enabled; | ||
37 | static msm_fb_vsync_handler_type mddi_sharp_vsync_handler; | ||
38 | static void *mddi_sharp_vsync_handler_arg; | ||
39 | static uint16 mddi_sharp_vsync_attempts; | ||
40 | |||
41 | static void mddi_sharp_prim_lcd_init(void); | ||
42 | static void mddi_sharp_sub_lcd_init(void); | ||
43 | static void mddi_sharp_lcd_set_backlight(struct msm_fb_data_type *mfd); | ||
44 | static void mddi_sharp_vsync_set_handler(msm_fb_vsync_handler_type handler, | ||
45 | void *); | ||
46 | static void mddi_sharp_lcd_vsync_detected(boolean detected); | ||
47 | static struct msm_panel_common_pdata *mddi_sharp_pdata; | ||
48 | |||
49 | #define REG_SYSCTL 0x0000 | ||
50 | #define REG_INTR 0x0006 | ||
51 | #define REG_CLKCNF 0x000C | ||
52 | #define REG_CLKDIV1 0x000E | ||
53 | #define REG_CLKDIV2 0x0010 | ||
54 | |||
55 | #define REG_GIOD 0x0040 | ||
56 | #define REG_GIOA 0x0042 | ||
57 | |||
58 | #define REG_AGM 0x010A | ||
59 | #define REG_FLFT 0x0110 | ||
60 | #define REG_FRGT 0x0112 | ||
61 | #define REG_FTOP 0x0114 | ||
62 | #define REG_FBTM 0x0116 | ||
63 | #define REG_FSTRX 0x0118 | ||
64 | #define REG_FSTRY 0x011A | ||
65 | #define REG_VRAM 0x0202 | ||
66 | #define REG_SSDCTL 0x0330 | ||
67 | #define REG_SSD0 0x0332 | ||
68 | #define REG_PSTCTL1 0x0400 | ||
69 | #define REG_PSTCTL2 0x0402 | ||
70 | #define REG_PTGCTL 0x042A | ||
71 | #define REG_PTHP 0x042C | ||
72 | #define REG_PTHB 0x042E | ||
73 | #define REG_PTHW 0x0430 | ||
74 | #define REG_PTHF 0x0432 | ||
75 | #define REG_PTVP 0x0434 | ||
76 | #define REG_PTVB 0x0436 | ||
77 | #define REG_PTVW 0x0438 | ||
78 | #define REG_PTVF 0x043A | ||
79 | #define REG_VBLKS 0x0458 | ||
80 | #define REG_VBLKE 0x045A | ||
81 | #define REG_SUBCTL 0x0700 | ||
82 | #define REG_SUBTCMD 0x0702 | ||
83 | #define REG_SUBTCMDD 0x0704 | ||
84 | #define REG_REVBYTE 0x0A02 | ||
85 | #define REG_REVCNT 0x0A04 | ||
86 | #define REG_REVATTR 0x0A06 | ||
87 | #define REG_REVFMT 0x0A08 | ||
88 | |||
89 | #define SHARP_SUB_UNKNOWN 0xffffffff | ||
90 | #define SHARP_SUB_HYNIX 1 | ||
91 | #define SHARP_SUB_ROHM 2 | ||
92 | |||
93 | static uint32 sharp_subpanel_type = SHARP_SUB_UNKNOWN; | ||
94 | |||
95 | static void sub_through_write(int sub_rs, uint32 sub_data) | ||
96 | { | ||
97 | mddi_queue_register_write(REG_SUBTCMDD, sub_data, FALSE, 0); | ||
98 | |||
99 | /* CS=1,RD=1,WE=1,RS=sub_rs */ | ||
100 | mddi_queue_register_write(REG_SUBTCMD, 0x000e | sub_rs, FALSE, 0); | ||
101 | |||
102 | /* CS=0,RD=1,WE=1,RS=sub_rs */ | ||
103 | mddi_queue_register_write(REG_SUBTCMD, 0x0006 | sub_rs, FALSE, 0); | ||
104 | |||
105 | /* CS=0,RD=1,WE=0,RS=sub_rs */ | ||
106 | mddi_queue_register_write(REG_SUBTCMD, 0x0004 | sub_rs, FALSE, 0); | ||
107 | |||
108 | /* CS=0,RD=1,WE=1,RS=sub_rs */ | ||
109 | mddi_queue_register_write(REG_SUBTCMD, 0x0006 | sub_rs, FALSE, 0); | ||
110 | |||
111 | /* CS=1,RD=1,WE=1,RS=sub_rs */ | ||
112 | mddi_queue_register_write(REG_SUBTCMD, 0x000e | sub_rs, TRUE, 0); | ||
113 | } | ||
114 | |||
115 | static uint32 sub_through_read(int sub_rs) | ||
116 | { | ||
117 | uint32 sub_data; | ||
118 | |||
119 | /* CS=1,RD=1,WE=1,RS=sub_rs */ | ||
120 | mddi_queue_register_write(REG_SUBTCMD, 0x000e | sub_rs, FALSE, 0); | ||
121 | |||
122 | /* CS=0,RD=1,WE=1,RS=sub_rs */ | ||
123 | mddi_queue_register_write(REG_SUBTCMD, 0x0006 | sub_rs, FALSE, 0); | ||
124 | |||
125 | /* CS=0,RD=1,WE=0,RS=sub_rs */ | ||
126 | mddi_queue_register_write(REG_SUBTCMD, 0x0002 | sub_rs, TRUE, 0); | ||
127 | |||
128 | mddi_queue_register_read(REG_SUBTCMDD, &sub_data, TRUE, 0); | ||
129 | |||
130 | /* CS=0,RD=1,WE=1,RS=sub_rs */ | ||
131 | mddi_queue_register_write(REG_SUBTCMD, 0x0006 | sub_rs, FALSE, 0); | ||
132 | |||
133 | /* CS=1,RD=1,WE=1,RS=sub_rs */ | ||
134 | mddi_queue_register_write(REG_SUBTCMD, 0x000e | sub_rs, TRUE, 0); | ||
135 | |||
136 | return sub_data; | ||
137 | } | ||
138 | |||
139 | static void serigo(uint32 ssd) | ||
140 | { | ||
141 | uint32 ssdctl; | ||
142 | |||
143 | mddi_queue_register_read(REG_SSDCTL, &ssdctl, TRUE, 0); | ||
144 | ssdctl = ((ssdctl & 0xE7) | 0x02); | ||
145 | |||
146 | mddi_queue_register_write(REG_SSD0, ssd, FALSE, 0); | ||
147 | mddi_queue_register_write(REG_SSDCTL, ssdctl, TRUE, 0); | ||
148 | |||
149 | do { | ||
150 | mddi_queue_register_read(REG_SSDCTL, &ssdctl, TRUE, 0); | ||
151 | } while ((ssdctl & 0x0002) != 0); | ||
152 | |||
153 | if (mddi_debug_prim_wait) | ||
154 | mddi_wait(2); | ||
155 | } | ||
156 | |||
157 | static void mddi_sharp_lcd_powerdown(void) | ||
158 | { | ||
159 | serigo(0x0131); | ||
160 | serigo(0x0300); | ||
161 | mddi_wait(40); | ||
162 | serigo(0x0135); | ||
163 | mddi_wait(20); | ||
164 | serigo(0x2122); | ||
165 | mddi_wait(20); | ||
166 | serigo(0x0201); | ||
167 | mddi_wait(20); | ||
168 | serigo(0x2100); | ||
169 | mddi_wait(20); | ||
170 | serigo(0x2000); | ||
171 | mddi_wait(20); | ||
172 | |||
173 | mddi_queue_register_write(REG_PSTCTL1, 0x1, TRUE, 0); | ||
174 | mddi_wait(100); | ||
175 | mddi_queue_register_write(REG_PSTCTL1, 0x0, TRUE, 0); | ||
176 | mddi_wait(2); | ||
177 | mddi_queue_register_write(REG_SYSCTL, 0x1, TRUE, 0); | ||
178 | mddi_wait(2); | ||
179 | mddi_queue_register_write(REG_CLKDIV1, 0x3, TRUE, 0); | ||
180 | mddi_wait(2); | ||
181 | mddi_queue_register_write(REG_SSDCTL, 0x0000, TRUE, 0); /* SSDRESET */ | ||
182 | mddi_queue_register_write(REG_SYSCTL, 0x0, TRUE, 0); | ||
183 | mddi_wait(2); | ||
184 | } | ||
185 | |||
186 | static void mddi_sharp_lcd_set_backlight(struct msm_fb_data_type *mfd) | ||
187 | { | ||
188 | uint32 regdata; | ||
189 | int32 level; | ||
190 | int max = mfd->panel_info.bl_max; | ||
191 | int min = mfd->panel_info.bl_min; | ||
192 | |||
193 | if (mddi_sharp_pdata && mddi_sharp_pdata->backlight_level) { | ||
194 | level = mddi_sharp_pdata->backlight_level(mfd->bl_level, | ||
195 | max, | ||
196 | min); | ||
197 | |||
198 | if (level < 0) | ||
199 | return; | ||
200 | |||
201 | /* use Rodem GPIO(2:0) to give 8 levels of backlight (7-0) */ | ||
202 | /* Set lower 3 GPIOs as Outputs (set to 0) */ | ||
203 | mddi_queue_register_read(REG_GIOA, ®data, TRUE, 0); | ||
204 | mddi_queue_register_write(REG_GIOA, regdata & 0xfff8, TRUE, 0); | ||
205 | |||
206 | /* Set lower 3 GPIOs as level */ | ||
207 | mddi_queue_register_read(REG_GIOD, ®data, TRUE, 0); | ||
208 | mddi_queue_register_write(REG_GIOD, | ||
209 | (regdata & 0xfff8) | (0x07 & level), TRUE, 0); | ||
210 | } | ||
211 | } | ||
212 | |||
213 | static void mddi_sharp_prim_lcd_init(void) | ||
214 | { | ||
215 | mddi_queue_register_write(REG_SYSCTL, 0x4000, TRUE, 0); | ||
216 | mddi_wait(1); | ||
217 | mddi_queue_register_write(REG_SYSCTL, 0x0000, TRUE, 0); | ||
218 | mddi_wait(5); | ||
219 | mddi_queue_register_write(REG_SYSCTL, 0x0001, FALSE, 0); | ||
220 | mddi_queue_register_write(REG_CLKDIV1, 0x000b, FALSE, 0); | ||
221 | |||
222 | /* new reg write below */ | ||
223 | if (mddi_sharp_debug_60hz_refresh) | ||
224 | mddi_queue_register_write(REG_CLKCNF, 0x070d, FALSE, 0); | ||
225 | else | ||
226 | mddi_queue_register_write(REG_CLKCNF, 0x0708, FALSE, 0); | ||
227 | |||
228 | mddi_queue_register_write(REG_SYSCTL, 0x0201, FALSE, 0); | ||
229 | mddi_queue_register_write(REG_PTGCTL, 0x0010, FALSE, 0); | ||
230 | mddi_queue_register_write(REG_PTHP, 4, FALSE, 0); | ||
231 | mddi_queue_register_write(REG_PTHB, 40, FALSE, 0); | ||
232 | mddi_queue_register_write(REG_PTHW, 240, FALSE, 0); | ||
233 | if (mddi_sharp_debug_60hz_refresh) | ||
234 | mddi_queue_register_write(REG_PTHF, 12, FALSE, 0); | ||
235 | else | ||
236 | mddi_queue_register_write(REG_PTHF, 92, FALSE, 0); | ||
237 | |||
238 | mddi_wait(1); | ||
239 | |||
240 | mddi_queue_register_write(REG_PTVP, 1, FALSE, 0); | ||
241 | mddi_queue_register_write(REG_PTVB, 2, FALSE, 0); | ||
242 | mddi_queue_register_write(REG_PTVW, 320, FALSE, 0); | ||
243 | mddi_queue_register_write(REG_PTVF, 15, FALSE, 0); | ||
244 | |||
245 | mddi_wait(1); | ||
246 | |||
247 | /* vram_color set REG_AGM???? */ | ||
248 | mddi_queue_register_write(REG_AGM, 0x0000, TRUE, 0); | ||
249 | |||
250 | mddi_queue_register_write(REG_SSDCTL, 0x0000, FALSE, 0); | ||
251 | mddi_queue_register_write(REG_SSDCTL, 0x0001, TRUE, 0); | ||
252 | mddi_wait(1); | ||
253 | mddi_queue_register_write(REG_PSTCTL1, 0x0001, TRUE, 0); | ||
254 | mddi_wait(10); | ||
255 | |||
256 | serigo(0x0701); | ||
257 | /* software reset */ | ||
258 | mddi_wait(1); | ||
259 | /* Wait over 50us */ | ||
260 | |||
261 | serigo(0x0400); | ||
262 | /* DCLK~ACHSYNC~ACVSYNC polarity setting */ | ||
263 | serigo(0x2900); | ||
264 | /* EEPROM start read address setting */ | ||
265 | serigo(0x2606); | ||
266 | /* EEPROM start read register setting */ | ||
267 | mddi_wait(20); | ||
268 | /* Wait over 20ms */ | ||
269 | |||
270 | serigo(0x0503); | ||
271 | /* Horizontal timing setting */ | ||
272 | serigo(0x062C); | ||
273 | /* Veritical timing setting */ | ||
274 | serigo(0x2001); | ||
275 | /* power initialize setting(VDC2) */ | ||
276 | mddi_wait(20); | ||
277 | /* Wait over 20ms */ | ||
278 | |||
279 | serigo(0x2120); | ||
280 | /* Initialize power setting(CPS) */ | ||
281 | mddi_wait(20); | ||
282 | /* Wait over 20ms */ | ||
283 | |||
284 | serigo(0x2130); | ||
285 | /* Initialize power setting(CPS) */ | ||
286 | mddi_wait(20); | ||
287 | /* Wait over 20ms */ | ||
288 | |||
289 | serigo(0x2132); | ||
290 | /* Initialize power setting(CPS) */ | ||
291 | mddi_wait(10); | ||
292 | /* Wait over 10ms */ | ||
293 | |||
294 | serigo(0x2133); | ||
295 | /* Initialize power setting(CPS) */ | ||
296 | mddi_wait(20); | ||
297 | /* Wait over 20ms */ | ||
298 | |||
299 | serigo(0x0200); | ||
300 | /* Panel initialize release(INIT) */ | ||
301 | mddi_wait(1); | ||
302 | /* Wait over 1ms */ | ||
303 | |||
304 | serigo(0x0131); | ||
305 | /* Panel setting(CPS) */ | ||
306 | mddi_wait(1); | ||
307 | /* Wait over 1ms */ | ||
308 | |||
309 | mddi_queue_register_write(REG_PSTCTL1, 0x0003, TRUE, 0); | ||
310 | |||
311 | /* if (FFA LCD is upside down) -> serigo(0x0100); */ | ||
312 | serigo(0x0130); | ||
313 | |||
314 | /* Black mask release(display ON) */ | ||
315 | mddi_wait(1); | ||
316 | /* Wait over 1ms */ | ||
317 | |||
318 | if (mddi_sharp_vsync_wake) { | ||
319 | mddi_queue_register_write(REG_VBLKS, 0x1001, TRUE, 0); | ||
320 | mddi_queue_register_write(REG_VBLKE, 0x1002, TRUE, 0); | ||
321 | } | ||
322 | |||
323 | /* Set the MDP pixel data attributes for Primary Display */ | ||
324 | mddi_host_write_pix_attr_reg(0x00C3); | ||
325 | return; | ||
326 | |||
327 | } | ||
328 | |||
329 | void mddi_sharp_sub_lcd_init(void) | ||
330 | { | ||
331 | |||
332 | mddi_queue_register_write(REG_SYSCTL, 0x4000, FALSE, 0); | ||
333 | mddi_queue_register_write(REG_SYSCTL, 0x0000, TRUE, 0); | ||
334 | mddi_wait(100); | ||
335 | |||
336 | mddi_queue_register_write(REG_SYSCTL, 0x0001, FALSE, 0); | ||
337 | mddi_queue_register_write(REG_CLKDIV1, 0x000b, FALSE, 0); | ||
338 | mddi_queue_register_write(REG_CLKCNF, 0x0708, FALSE, 0); | ||
339 | mddi_queue_register_write(REG_SYSCTL, 0x0201, FALSE, 0); | ||
340 | mddi_queue_register_write(REG_PTGCTL, 0x0010, FALSE, 0); | ||
341 | mddi_queue_register_write(REG_PTHP, 4, FALSE, 0); | ||
342 | mddi_queue_register_write(REG_PTHB, 40, FALSE, 0); | ||
343 | mddi_queue_register_write(REG_PTHW, 128, FALSE, 0); | ||
344 | mddi_queue_register_write(REG_PTHF, 92, FALSE, 0); | ||
345 | mddi_queue_register_write(REG_PTVP, 1, FALSE, 0); | ||
346 | mddi_queue_register_write(REG_PTVB, 2, FALSE, 0); | ||
347 | mddi_queue_register_write(REG_PTVW, 128, FALSE, 0); | ||
348 | mddi_queue_register_write(REG_PTVF, 15, FALSE, 0); | ||
349 | |||
350 | /* Now the sub display..... */ | ||
351 | /* Reset High */ | ||
352 | mddi_queue_register_write(REG_SUBCTL, 0x0200, FALSE, 0); | ||
353 | /* CS=1,RD=1,WE=1,RS=1 */ | ||
354 | mddi_queue_register_write(REG_SUBTCMD, 0x000f, TRUE, 0); | ||
355 | mddi_wait(1); | ||
356 | /* Wait 5us */ | ||
357 | |||
358 | if (sharp_subpanel_type == SHARP_SUB_UNKNOWN) { | ||
359 | uint32 data; | ||
360 | |||
361 | sub_through_write(1, 0x05); | ||
362 | sub_through_write(1, 0x6A); | ||
363 | sub_through_write(1, 0x1D); | ||
364 | sub_through_write(1, 0x05); | ||
365 | data = sub_through_read(1); | ||
366 | if (data == 0x6A) { | ||
367 | sharp_subpanel_type = SHARP_SUB_HYNIX; | ||
368 | } else { | ||
369 | sub_through_write(0, 0x36); | ||
370 | sub_through_write(1, 0xA8); | ||
371 | sub_through_write(0, 0x09); | ||
372 | data = sub_through_read(1); | ||
373 | data = sub_through_read(1); | ||
374 | if (data == 0x54) { | ||
375 | sub_through_write(0, 0x36); | ||
376 | sub_through_write(1, 0x00); | ||
377 | sharp_subpanel_type = SHARP_SUB_ROHM; | ||
378 | } | ||
379 | } | ||
380 | } | ||
381 | |||
382 | if (sharp_subpanel_type == SHARP_SUB_HYNIX) { | ||
383 | sub_through_write(1, 0x00); /* Display setting 1 */ | ||
384 | sub_through_write(1, 0x04); | ||
385 | sub_through_write(1, 0x01); | ||
386 | sub_through_write(1, 0x05); | ||
387 | sub_through_write(1, 0x0280); | ||
388 | sub_through_write(1, 0x0301); | ||
389 | sub_through_write(1, 0x0402); | ||
390 | sub_through_write(1, 0x0500); | ||
391 | sub_through_write(1, 0x0681); | ||
392 | sub_through_write(1, 0x077F); | ||
393 | sub_through_write(1, 0x08C0); | ||
394 | sub_through_write(1, 0x0905); | ||
395 | sub_through_write(1, 0x0A02); | ||
396 | sub_through_write(1, 0x0B00); | ||
397 | sub_through_write(1, 0x0C00); | ||
398 | sub_through_write(1, 0x0D00); | ||
399 | sub_through_write(1, 0x0E00); | ||
400 | sub_through_write(1, 0x0F00); | ||
401 | |||
402 | sub_through_write(1, 0x100B); /* Display setting 2 */ | ||
403 | sub_through_write(1, 0x1103); | ||
404 | sub_through_write(1, 0x1237); | ||
405 | sub_through_write(1, 0x1300); | ||
406 | sub_through_write(1, 0x1400); | ||
407 | sub_through_write(1, 0x1500); | ||
408 | sub_through_write(1, 0x1605); | ||
409 | sub_through_write(1, 0x1700); | ||
410 | sub_through_write(1, 0x1800); | ||
411 | sub_through_write(1, 0x192E); | ||
412 | sub_through_write(1, 0x1A00); | ||
413 | sub_through_write(1, 0x1B00); | ||
414 | sub_through_write(1, 0x1C00); | ||
415 | |||
416 | sub_through_write(1, 0x151A); /* Power setting */ | ||
417 | |||
418 | sub_through_write(1, 0x2002); /* Gradation Palette setting */ | ||
419 | sub_through_write(1, 0x2107); | ||
420 | sub_through_write(1, 0x220C); | ||
421 | sub_through_write(1, 0x2310); | ||
422 | sub_through_write(1, 0x2414); | ||
423 | sub_through_write(1, 0x2518); | ||
424 | sub_through_write(1, 0x261C); | ||
425 | sub_through_write(1, 0x2720); | ||
426 | sub_through_write(1, 0x2824); | ||
427 | sub_through_write(1, 0x2928); | ||
428 | sub_through_write(1, 0x2A2B); | ||
429 | sub_through_write(1, 0x2B2E); | ||
430 | sub_through_write(1, 0x2C31); | ||
431 | sub_through_write(1, 0x2D34); | ||
432 | sub_through_write(1, 0x2E37); | ||
433 | sub_through_write(1, 0x2F3A); | ||
434 | sub_through_write(1, 0x303C); | ||
435 | sub_through_write(1, 0x313E); | ||
436 | sub_through_write(1, 0x323F); | ||
437 | sub_through_write(1, 0x3340); | ||
438 | sub_through_write(1, 0x3441); | ||
439 | sub_through_write(1, 0x3543); | ||
440 | sub_through_write(1, 0x3646); | ||
441 | sub_through_write(1, 0x3749); | ||
442 | sub_through_write(1, 0x384C); | ||
443 | sub_through_write(1, 0x394F); | ||
444 | sub_through_write(1, 0x3A52); | ||
445 | sub_through_write(1, 0x3B59); | ||
446 | sub_through_write(1, 0x3C60); | ||
447 | sub_through_write(1, 0x3D67); | ||
448 | sub_through_write(1, 0x3E6E); | ||
449 | sub_through_write(1, 0x3F7F); | ||
450 | sub_through_write(1, 0x4001); | ||
451 | sub_through_write(1, 0x4107); | ||
452 | sub_through_write(1, 0x420C); | ||
453 | sub_through_write(1, 0x4310); | ||
454 | sub_through_write(1, 0x4414); | ||
455 | sub_through_write(1, 0x4518); | ||
456 | sub_through_write(1, 0x461C); | ||
457 | sub_through_write(1, 0x4720); | ||
458 | sub_through_write(1, 0x4824); | ||
459 | sub_through_write(1, 0x4928); | ||
460 | sub_through_write(1, 0x4A2B); | ||
461 | sub_through_write(1, 0x4B2E); | ||
462 | sub_through_write(1, 0x4C31); | ||
463 | sub_through_write(1, 0x4D34); | ||
464 | sub_through_write(1, 0x4E37); | ||
465 | sub_through_write(1, 0x4F3A); | ||
466 | sub_through_write(1, 0x503C); | ||
467 | sub_through_write(1, 0x513E); | ||
468 | sub_through_write(1, 0x523F); | ||
469 | sub_through_write(1, 0x5340); | ||
470 | sub_through_write(1, 0x5441); | ||
471 | sub_through_write(1, 0x5543); | ||
472 | sub_through_write(1, 0x5646); | ||
473 | sub_through_write(1, 0x5749); | ||
474 | sub_through_write(1, 0x584C); | ||
475 | sub_through_write(1, 0x594F); | ||
476 | sub_through_write(1, 0x5A52); | ||
477 | sub_through_write(1, 0x5B59); | ||
478 | sub_through_write(1, 0x5C60); | ||
479 | sub_through_write(1, 0x5D67); | ||
480 | sub_through_write(1, 0x5E6E); | ||
481 | sub_through_write(1, 0x5F7E); | ||
482 | sub_through_write(1, 0x6000); | ||
483 | sub_through_write(1, 0x6107); | ||
484 | sub_through_write(1, 0x620C); | ||
485 | sub_through_write(1, 0x6310); | ||
486 | sub_through_write(1, 0x6414); | ||
487 | sub_through_write(1, 0x6518); | ||
488 | sub_through_write(1, 0x661C); | ||
489 | sub_through_write(1, 0x6720); | ||
490 | sub_through_write(1, 0x6824); | ||
491 | sub_through_write(1, 0x6928); | ||
492 | sub_through_write(1, 0x6A2B); | ||
493 | sub_through_write(1, 0x6B2E); | ||
494 | sub_through_write(1, 0x6C31); | ||
495 | sub_through_write(1, 0x6D34); | ||
496 | sub_through_write(1, 0x6E37); | ||
497 | sub_through_write(1, 0x6F3A); | ||
498 | sub_through_write(1, 0x703C); | ||
499 | sub_through_write(1, 0x713E); | ||
500 | sub_through_write(1, 0x723F); | ||
501 | sub_through_write(1, 0x7340); | ||
502 | sub_through_write(1, 0x7441); | ||
503 | sub_through_write(1, 0x7543); | ||
504 | sub_through_write(1, 0x7646); | ||
505 | sub_through_write(1, 0x7749); | ||
506 | sub_through_write(1, 0x784C); | ||
507 | sub_through_write(1, 0x794F); | ||
508 | sub_through_write(1, 0x7A52); | ||
509 | sub_through_write(1, 0x7B59); | ||
510 | sub_through_write(1, 0x7C60); | ||
511 | sub_through_write(1, 0x7D67); | ||
512 | sub_through_write(1, 0x7E6E); | ||
513 | sub_through_write(1, 0x7F7D); | ||
514 | |||
515 | sub_through_write(1, 0x1851); /* Display on */ | ||
516 | |||
517 | mddi_queue_register_write(REG_AGM, 0x0000, TRUE, 0); | ||
518 | |||
519 | /* 1 pixel / 1 post clock */ | ||
520 | mddi_queue_register_write(REG_CLKDIV2, 0x3b00, FALSE, 0); | ||
521 | |||
522 | /* SUB LCD select */ | ||
523 | mddi_queue_register_write(REG_PSTCTL2, 0x0080, FALSE, 0); | ||
524 | |||
525 | /* RS=0,command initiate number=0,select master mode */ | ||
526 | mddi_queue_register_write(REG_SUBCTL, 0x0202, FALSE, 0); | ||
527 | |||
528 | /* Sub LCD Data transform start */ | ||
529 | mddi_queue_register_write(REG_PSTCTL1, 0x0003, FALSE, 0); | ||
530 | |||
531 | } else if (sharp_subpanel_type == SHARP_SUB_ROHM) { | ||
532 | |||
533 | sub_through_write(0, 0x01); /* Display setting */ | ||
534 | sub_through_write(1, 0x00); | ||
535 | |||
536 | mddi_wait(1); | ||
537 | /* Wait 100us <----- ******* Update 2005/01/24 */ | ||
538 | |||
539 | sub_through_write(0, 0xB6); | ||
540 | sub_through_write(1, 0x0C); | ||
541 | sub_through_write(1, 0x4A); | ||
542 | sub_through_write(1, 0x20); | ||
543 | sub_through_write(0, 0x3A); | ||
544 | sub_through_write(1, 0x05); | ||
545 | sub_through_write(0, 0xB7); | ||
546 | sub_through_write(1, 0x01); | ||
547 | sub_through_write(0, 0xBA); | ||
548 | sub_through_write(1, 0x20); | ||
549 | sub_through_write(1, 0x02); | ||
550 | sub_through_write(0, 0x25); | ||
551 | sub_through_write(1, 0x4F); | ||
552 | sub_through_write(0, 0xBB); | ||
553 | sub_through_write(1, 0x00); | ||
554 | sub_through_write(0, 0x36); | ||
555 | sub_through_write(1, 0x00); | ||
556 | sub_through_write(0, 0xB1); | ||
557 | sub_through_write(1, 0x05); | ||
558 | sub_through_write(0, 0xBE); | ||
559 | sub_through_write(1, 0x80); | ||
560 | sub_through_write(0, 0x26); | ||
561 | sub_through_write(1, 0x01); | ||
562 | sub_through_write(0, 0x2A); | ||
563 | sub_through_write(1, 0x02); | ||
564 | sub_through_write(1, 0x81); | ||
565 | sub_through_write(0, 0x2B); | ||
566 | sub_through_write(1, 0x00); | ||
567 | sub_through_write(1, 0x7F); | ||
568 | |||
569 | sub_through_write(0, 0x2C); | ||
570 | sub_through_write(0, 0x11); /* Sleep mode off */ | ||
571 | |||
572 | mddi_wait(1); | ||
573 | /* Wait 100 ms <----- ******* Update 2005/01/24 */ | ||
574 | |||
575 | sub_through_write(0, 0x29); /* Display on */ | ||
576 | sub_through_write(0, 0xB3); | ||
577 | sub_through_write(1, 0x20); | ||
578 | sub_through_write(1, 0xAA); | ||
579 | sub_through_write(1, 0xA0); | ||
580 | sub_through_write(1, 0x20); | ||
581 | sub_through_write(1, 0x30); | ||
582 | sub_through_write(1, 0xA6); | ||
583 | sub_through_write(1, 0xFF); | ||
584 | sub_through_write(1, 0x9A); | ||
585 | sub_through_write(1, 0x9F); | ||
586 | sub_through_write(1, 0xAF); | ||
587 | sub_through_write(1, 0xBC); | ||
588 | sub_through_write(1, 0xCF); | ||
589 | sub_through_write(1, 0xDF); | ||
590 | sub_through_write(1, 0x20); | ||
591 | sub_through_write(1, 0x9C); | ||
592 | sub_through_write(1, 0x8A); | ||
593 | |||
594 | sub_through_write(0, 0x002C); /* Display on */ | ||
595 | |||
596 | /* 1 pixel / 2 post clock */ | ||
597 | mddi_queue_register_write(REG_CLKDIV2, 0x7b00, FALSE, 0); | ||
598 | |||
599 | /* SUB LCD select */ | ||
600 | mddi_queue_register_write(REG_PSTCTL2, 0x0080, FALSE, 0); | ||
601 | |||
602 | /* RS=1,command initiate number=0,select master mode */ | ||
603 | mddi_queue_register_write(REG_SUBCTL, 0x0242, FALSE, 0); | ||
604 | |||
605 | /* Sub LCD Data transform start */ | ||
606 | mddi_queue_register_write(REG_PSTCTL1, 0x0003, FALSE, 0); | ||
607 | |||
608 | } | ||
609 | |||
610 | /* Set the MDP pixel data attributes for Sub Display */ | ||
611 | mddi_host_write_pix_attr_reg(0x00C0); | ||
612 | } | ||
613 | |||
614 | void mddi_sharp_lcd_vsync_detected(boolean detected) | ||
615 | { | ||
616 | /* static timetick_type start_time = 0; */ | ||
617 | static struct timeval start_time; | ||
618 | static boolean first_time = TRUE; | ||
619 | /* uint32 mdp_cnt_val = 0; */ | ||
620 | /* timetick_type elapsed_us; */ | ||
621 | struct timeval now; | ||
622 | uint32 elapsed_us; | ||
623 | uint32 num_vsyncs; | ||
624 | |||
625 | if ((detected) || (mddi_sharp_vsync_attempts > 5)) { | ||
626 | if ((detected) && (mddi_sharp_monitor_refresh_value)) { | ||
627 | /* if (start_time != 0) */ | ||
628 | if (!first_time) { | ||
629 | jiffies_to_timeval(jiffies, &now); | ||
630 | elapsed_us = | ||
631 | (now.tv_sec - start_time.tv_sec) * 1000000 + | ||
632 | now.tv_usec - start_time.tv_usec; | ||
633 | /* | ||
634 | * LCD is configured for a refresh every usecs, | ||
635 | * so to determine the number of vsyncs that | ||
636 | * have occurred since the last measurement add | ||
637 | * half that to the time difference and divide | ||
638 | * by the refresh rate. | ||
639 | */ | ||
640 | num_vsyncs = (elapsed_us + | ||
641 | (mddi_sharp_usecs_per_refresh >> | ||
642 | 1)) / | ||
643 | mddi_sharp_usecs_per_refresh; | ||
644 | /* | ||
645 | * LCD is configured for * hsyncs (rows) per | ||
646 | * refresh cycle. Calculate new rows_per_second | ||
647 | * value based upon these new measurements. | ||
648 | * MDP can update with this new value. | ||
649 | */ | ||
650 | mddi_sharp_rows_per_second = | ||
651 | (mddi_sharp_rows_per_refresh * 1000 * | ||
652 | num_vsyncs) / (elapsed_us / 1000); | ||
653 | } | ||
654 | /* start_time = timetick_get(); */ | ||
655 | first_time = FALSE; | ||
656 | jiffies_to_timeval(jiffies, &start_time); | ||
657 | if (mddi_sharp_report_refresh_measurements) { | ||
658 | /* mdp_cnt_val = MDP_LINE_COUNT; */ | ||
659 | } | ||
660 | } | ||
661 | /* if detected = TRUE, client initiated wakeup was detected */ | ||
662 | if (mddi_sharp_vsync_handler != NULL) { | ||
663 | (*mddi_sharp_vsync_handler) | ||
664 | (mddi_sharp_vsync_handler_arg); | ||
665 | mddi_sharp_vsync_handler = NULL; | ||
666 | } | ||
667 | mddi_vsync_detect_enabled = FALSE; | ||
668 | mddi_sharp_vsync_attempts = 0; | ||
669 | /* need to clear this vsync wakeup */ | ||
670 | if (!mddi_queue_register_write_int(REG_INTR, 0x0000)) { | ||
671 | MDDI_MSG_ERR("Vsync interrupt clear failed!\n"); | ||
672 | } | ||
673 | if (!detected) { | ||
674 | /* give up after 5 failed attempts but show error */ | ||
675 | MDDI_MSG_NOTICE("Vsync detection failed!\n"); | ||
676 | } else if ((mddi_sharp_monitor_refresh_value) && | ||
677 | (mddi_sharp_report_refresh_measurements)) { | ||
678 | MDDI_MSG_NOTICE(" Lines Per Second=%d!\n", | ||
679 | mddi_sharp_rows_per_second); | ||
680 | } | ||
681 | } else | ||
682 | /* if detected = FALSE, we woke up from hibernation, but did not | ||
683 | * detect client initiated wakeup. | ||
684 | */ | ||
685 | mddi_sharp_vsync_attempts++; | ||
686 | } | ||
687 | |||
688 | /* ISR to be executed */ | ||
689 | void mddi_sharp_vsync_set_handler(msm_fb_vsync_handler_type handler, void *arg) | ||
690 | { | ||
691 | boolean error = FALSE; | ||
692 | unsigned long flags; | ||
693 | |||
694 | /* Disable interrupts */ | ||
695 | spin_lock_irqsave(&mddi_host_spin_lock, flags); | ||
696 | /* INTLOCK(); */ | ||
697 | |||
698 | if (mddi_sharp_vsync_handler != NULL) | ||
699 | error = TRUE; | ||
700 | |||
701 | /* Register the handler for this particular GROUP interrupt source */ | ||
702 | mddi_sharp_vsync_handler = handler; | ||
703 | mddi_sharp_vsync_handler_arg = arg; | ||
704 | |||
705 | /* Restore interrupts */ | ||
706 | spin_unlock_irqrestore(&mddi_host_spin_lock, flags); | ||
707 | /* INTFREE(); */ | ||
708 | |||
709 | if (error) | ||
710 | MDDI_MSG_ERR("MDDI: Previous Vsync handler never called\n"); | ||
711 | |||
712 | /* Enable the vsync wakeup */ | ||
713 | mddi_queue_register_write(REG_INTR, 0x8100, FALSE, 0); | ||
714 | |||
715 | mddi_sharp_vsync_attempts = 1; | ||
716 | mddi_vsync_detect_enabled = TRUE; | ||
717 | } /* mddi_sharp_vsync_set_handler */ | ||
718 | |||
719 | static int mddi_sharp_lcd_on(struct platform_device *pdev) | ||
720 | { | ||
721 | struct msm_fb_data_type *mfd; | ||
722 | |||
723 | mfd = platform_get_drvdata(pdev); | ||
724 | |||
725 | if (!mfd) | ||
726 | return -ENODEV; | ||
727 | |||
728 | if (mfd->key != MFD_KEY) | ||
729 | return -EINVAL; | ||
730 | |||
731 | if (mfd->panel.id == SHARP_QVGA_PRIM) | ||
732 | mddi_sharp_prim_lcd_init(); | ||
733 | else | ||
734 | mddi_sharp_sub_lcd_init(); | ||
735 | |||
736 | return 0; | ||
737 | } | ||
738 | |||
739 | static int mddi_sharp_lcd_off(struct platform_device *pdev) | ||
740 | { | ||
741 | mddi_sharp_lcd_powerdown(); | ||
742 | return 0; | ||
743 | } | ||
744 | |||
745 | static int __init mddi_sharp_probe(struct platform_device *pdev) | ||
746 | { | ||
747 | if (pdev->id == 0) { | ||
748 | mddi_sharp_pdata = pdev->dev.platform_data; | ||
749 | return 0; | ||
750 | } | ||
751 | |||
752 | msm_fb_add_device(pdev); | ||
753 | |||
754 | return 0; | ||
755 | } | ||
756 | |||
757 | static struct platform_driver this_driver = { | ||
758 | .probe = mddi_sharp_probe, | ||
759 | .driver = { | ||
760 | .name = "mddi_sharp_qvga", | ||
761 | }, | ||
762 | }; | ||
763 | |||
764 | static struct msm_fb_panel_data mddi_sharp_panel_data0 = { | ||
765 | .on = mddi_sharp_lcd_on, | ||
766 | .off = mddi_sharp_lcd_off, | ||
767 | .set_backlight = mddi_sharp_lcd_set_backlight, | ||
768 | .set_vsync_notifier = mddi_sharp_vsync_set_handler, | ||
769 | }; | ||
770 | |||
771 | static struct platform_device this_device_0 = { | ||
772 | .name = "mddi_sharp_qvga", | ||
773 | .id = SHARP_QVGA_PRIM, | ||
774 | .dev = { | ||
775 | .platform_data = &mddi_sharp_panel_data0, | ||
776 | } | ||
777 | }; | ||
778 | |||
779 | static struct msm_fb_panel_data mddi_sharp_panel_data1 = { | ||
780 | .on = mddi_sharp_lcd_on, | ||
781 | .off = mddi_sharp_lcd_off, | ||
782 | }; | ||
783 | |||
784 | static struct platform_device this_device_1 = { | ||
785 | .name = "mddi_sharp_qvga", | ||
786 | .id = SHARP_128X128_SECD, | ||
787 | .dev = { | ||
788 | .platform_data = &mddi_sharp_panel_data1, | ||
789 | } | ||
790 | }; | ||
791 | |||
792 | static int __init mddi_sharp_init(void) | ||
793 | { | ||
794 | int ret; | ||
795 | struct msm_panel_info *pinfo; | ||
796 | |||
797 | #ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT | ||
798 | u32 id; | ||
799 | |||
800 | ret = msm_fb_detect_client("mddi_sharp_qvga"); | ||
801 | if (ret == -ENODEV) | ||
802 | return 0; | ||
803 | |||
804 | if (ret) { | ||
805 | id = mddi_get_client_id(); | ||
806 | |||
807 | if (((id >> 16) != 0x0) || ((id & 0xffff) != 0x8835)) | ||
808 | return 0; | ||
809 | } | ||
810 | #endif | ||
811 | if (mddi_host_core_version > 8) { | ||
812 | /* can use faster refresh with newer hw revisions */ | ||
813 | mddi_sharp_debug_60hz_refresh = TRUE; | ||
814 | |||
815 | /* Timing variables for tracking vsync */ | ||
816 | /* dot_clock = 6.00MHz | ||
817 | * horizontal count = 296 | ||
818 | * vertical count = 338 | ||
819 | * refresh rate = 6000000/(296+338) = 60Hz | ||
820 | */ | ||
821 | mddi_sharp_rows_per_second = 20270; /* 6000000/296 */ | ||
822 | mddi_sharp_rows_per_refresh = 338; | ||
823 | mddi_sharp_usecs_per_refresh = 16674; /* (296+338)/6000000 */ | ||
824 | } else { | ||
825 | /* Timing variables for tracking vsync */ | ||
826 | /* dot_clock = 5.20MHz | ||
827 | * horizontal count = 376 | ||
828 | * vertical count = 338 | ||
829 | * refresh rate = 5200000/(376+338) = 41Hz | ||
830 | */ | ||
831 | mddi_sharp_rows_per_second = 13830; /* 5200000/376 */ | ||
832 | mddi_sharp_rows_per_refresh = 338; | ||
833 | mddi_sharp_usecs_per_refresh = 24440; /* (376+338)/5200000 */ | ||
834 | } | ||
835 | |||
836 | ret = platform_driver_register(&this_driver); | ||
837 | if (!ret) { | ||
838 | pinfo = &mddi_sharp_panel_data0.panel_info; | ||
839 | pinfo->xres = 240; | ||
840 | pinfo->yres = 320; | ||
841 | pinfo->type = MDDI_PANEL; | ||
842 | pinfo->pdest = DISPLAY_1; | ||
843 | pinfo->mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR; | ||
844 | pinfo->wait_cycle = 0; | ||
845 | pinfo->bpp = 18; | ||
846 | pinfo->fb_num = 2; | ||
847 | pinfo->clk_rate = 122880000; | ||
848 | pinfo->clk_min = 120000000; | ||
849 | pinfo->clk_max = 125000000; | ||
850 | pinfo->lcd.vsync_enable = TRUE; | ||
851 | pinfo->lcd.refx100 = | ||
852 | (mddi_sharp_rows_per_second * 100) / | ||
853 | mddi_sharp_rows_per_refresh; | ||
854 | pinfo->lcd.v_back_porch = 12; | ||
855 | pinfo->lcd.v_front_porch = 6; | ||
856 | pinfo->lcd.v_pulse_width = 0; | ||
857 | pinfo->lcd.hw_vsync_mode = FALSE; | ||
858 | pinfo->lcd.vsync_notifier_period = (1 * HZ); | ||
859 | pinfo->bl_max = 7; | ||
860 | pinfo->bl_min = 1; | ||
861 | |||
862 | ret = platform_device_register(&this_device_0); | ||
863 | if (ret) | ||
864 | platform_driver_unregister(&this_driver); | ||
865 | |||
866 | pinfo = &mddi_sharp_panel_data1.panel_info; | ||
867 | pinfo->xres = 128; | ||
868 | pinfo->yres = 128; | ||
869 | pinfo->type = MDDI_PANEL; | ||
870 | pinfo->pdest = DISPLAY_2; | ||
871 | pinfo->mddi.vdopkt = 0x400; | ||
872 | pinfo->wait_cycle = 0; | ||
873 | pinfo->bpp = 18; | ||
874 | pinfo->clk_rate = 122880000; | ||
875 | pinfo->clk_min = 120000000; | ||
876 | pinfo->clk_max = 125000000; | ||
877 | pinfo->fb_num = 2; | ||
878 | |||
879 | ret = platform_device_register(&this_device_1); | ||
880 | if (ret) { | ||
881 | platform_device_unregister(&this_device_0); | ||
882 | platform_driver_unregister(&this_driver); | ||
883 | } | ||
884 | } | ||
885 | |||
886 | if (!ret) | ||
887 | mddi_lcd.vsync_detected = mddi_sharp_lcd_vsync_detected; | ||
888 | |||
889 | return ret; | ||
890 | } | ||
891 | |||
892 | module_init(mddi_sharp_init); | ||
diff --git a/drivers/staging/msm/mddi_toshiba.c b/drivers/staging/msm/mddi_toshiba.c new file mode 100644 index 000000000000..e96342d477a2 --- /dev/null +++ b/drivers/staging/msm/mddi_toshiba.c | |||
@@ -0,0 +1,1741 @@ | |||
1 | /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include "msm_fb.h" | ||
19 | #include "mddihost.h" | ||
20 | #include "mddihosti.h" | ||
21 | #include "mddi_toshiba.h" | ||
22 | |||
23 | #define TM_GET_DID(id) ((id) & 0xff) | ||
24 | #define TM_GET_PID(id) (((id) & 0xff00)>>8) | ||
25 | |||
26 | #define MDDI_CLIENT_CORE_BASE 0x108000 | ||
27 | #define LCD_CONTROL_BLOCK_BASE 0x110000 | ||
28 | #define SPI_BLOCK_BASE 0x120000 | ||
29 | #define PWM_BLOCK_BASE 0x140000 | ||
30 | #define SYSTEM_BLOCK1_BASE 0x160000 | ||
31 | |||
32 | #define TTBUSSEL (MDDI_CLIENT_CORE_BASE|0x18) | ||
33 | #define DPSET0 (MDDI_CLIENT_CORE_BASE|0x1C) | ||
34 | #define DPSET1 (MDDI_CLIENT_CORE_BASE|0x20) | ||
35 | #define DPSUS (MDDI_CLIENT_CORE_BASE|0x24) | ||
36 | #define DPRUN (MDDI_CLIENT_CORE_BASE|0x28) | ||
37 | #define SYSCKENA (MDDI_CLIENT_CORE_BASE|0x2C) | ||
38 | |||
39 | #define BITMAP0 (MDDI_CLIENT_CORE_BASE|0x44) | ||
40 | #define BITMAP1 (MDDI_CLIENT_CORE_BASE|0x48) | ||
41 | #define BITMAP2 (MDDI_CLIENT_CORE_BASE|0x4C) | ||
42 | #define BITMAP3 (MDDI_CLIENT_CORE_BASE|0x50) | ||
43 | #define BITMAP4 (MDDI_CLIENT_CORE_BASE|0x54) | ||
44 | |||
45 | #define SRST (LCD_CONTROL_BLOCK_BASE|0x00) | ||
46 | #define PORT_ENB (LCD_CONTROL_BLOCK_BASE|0x04) | ||
47 | #define START (LCD_CONTROL_BLOCK_BASE|0x08) | ||
48 | #define PORT (LCD_CONTROL_BLOCK_BASE|0x0C) | ||
49 | |||
50 | #define INTFLG (LCD_CONTROL_BLOCK_BASE|0x18) | ||
51 | #define INTMSK (LCD_CONTROL_BLOCK_BASE|0x1C) | ||
52 | #define MPLFBUF (LCD_CONTROL_BLOCK_BASE|0x20) | ||
53 | |||
54 | #define PXL (LCD_CONTROL_BLOCK_BASE|0x30) | ||
55 | #define HCYCLE (LCD_CONTROL_BLOCK_BASE|0x34) | ||
56 | #define HSW (LCD_CONTROL_BLOCK_BASE|0x38) | ||
57 | #define HDE_START (LCD_CONTROL_BLOCK_BASE|0x3C) | ||
58 | #define HDE_SIZE (LCD_CONTROL_BLOCK_BASE|0x40) | ||
59 | #define VCYCLE (LCD_CONTROL_BLOCK_BASE|0x44) | ||
60 | #define VSW (LCD_CONTROL_BLOCK_BASE|0x48) | ||
61 | #define VDE_START (LCD_CONTROL_BLOCK_BASE|0x4C) | ||
62 | #define VDE_SIZE (LCD_CONTROL_BLOCK_BASE|0x50) | ||
63 | #define WAKEUP (LCD_CONTROL_BLOCK_BASE|0x54) | ||
64 | #define REGENB (LCD_CONTROL_BLOCK_BASE|0x5C) | ||
65 | #define VSYNIF (LCD_CONTROL_BLOCK_BASE|0x60) | ||
66 | #define WRSTB (LCD_CONTROL_BLOCK_BASE|0x64) | ||
67 | #define RDSTB (LCD_CONTROL_BLOCK_BASE|0x68) | ||
68 | #define ASY_DATA (LCD_CONTROL_BLOCK_BASE|0x6C) | ||
69 | #define ASY_DATB (LCD_CONTROL_BLOCK_BASE|0x70) | ||
70 | #define ASY_DATC (LCD_CONTROL_BLOCK_BASE|0x74) | ||
71 | #define ASY_DATD (LCD_CONTROL_BLOCK_BASE|0x78) | ||
72 | #define ASY_DATE (LCD_CONTROL_BLOCK_BASE|0x7C) | ||
73 | #define ASY_DATF (LCD_CONTROL_BLOCK_BASE|0x80) | ||
74 | #define ASY_DATG (LCD_CONTROL_BLOCK_BASE|0x84) | ||
75 | #define ASY_DATH (LCD_CONTROL_BLOCK_BASE|0x88) | ||
76 | #define ASY_CMDSET (LCD_CONTROL_BLOCK_BASE|0x8C) | ||
77 | #define MONI (LCD_CONTROL_BLOCK_BASE|0xB0) | ||
78 | #define VPOS (LCD_CONTROL_BLOCK_BASE|0xC0) | ||
79 | |||
80 | #define SSICTL (SPI_BLOCK_BASE|0x00) | ||
81 | #define SSITIME (SPI_BLOCK_BASE|0x04) | ||
82 | #define SSITX (SPI_BLOCK_BASE|0x08) | ||
83 | #define SSIINTS (SPI_BLOCK_BASE|0x14) | ||
84 | |||
85 | #define TIMER0LOAD (PWM_BLOCK_BASE|0x00) | ||
86 | #define TIMER0CTRL (PWM_BLOCK_BASE|0x08) | ||
87 | #define PWM0OFF (PWM_BLOCK_BASE|0x1C) | ||
88 | #define TIMER1LOAD (PWM_BLOCK_BASE|0x20) | ||
89 | #define TIMER1CTRL (PWM_BLOCK_BASE|0x28) | ||
90 | #define PWM1OFF (PWM_BLOCK_BASE|0x3C) | ||
91 | #define TIMER2LOAD (PWM_BLOCK_BASE|0x40) | ||
92 | #define TIMER2CTRL (PWM_BLOCK_BASE|0x48) | ||
93 | #define PWM2OFF (PWM_BLOCK_BASE|0x5C) | ||
94 | #define PWMCR (PWM_BLOCK_BASE|0x68) | ||
95 | |||
96 | #define GPIOIS (GPIO_BLOCK_BASE|0x08) | ||
97 | #define GPIOIEV (GPIO_BLOCK_BASE|0x10) | ||
98 | #define GPIOIC (GPIO_BLOCK_BASE|0x20) | ||
99 | |||
100 | #define WKREQ (SYSTEM_BLOCK1_BASE|0x00) | ||
101 | #define CLKENB (SYSTEM_BLOCK1_BASE|0x04) | ||
102 | #define DRAMPWR (SYSTEM_BLOCK1_BASE|0x08) | ||
103 | #define INTMASK (SYSTEM_BLOCK1_BASE|0x0C) | ||
104 | #define CNT_DIS (SYSTEM_BLOCK1_BASE|0x10) | ||
105 | |||
106 | typedef enum { | ||
107 | TOSHIBA_STATE_OFF, | ||
108 | TOSHIBA_STATE_PRIM_SEC_STANDBY, | ||
109 | TOSHIBA_STATE_PRIM_SEC_READY, | ||
110 | TOSHIBA_STATE_PRIM_NORMAL_MODE, | ||
111 | TOSHIBA_STATE_SEC_NORMAL_MODE | ||
112 | } mddi_toshiba_state_t; | ||
113 | |||
114 | static uint32 mddi_toshiba_curr_vpos; | ||
115 | static boolean mddi_toshiba_monitor_refresh_value = FALSE; | ||
116 | static boolean mddi_toshiba_report_refresh_measurements = FALSE; | ||
117 | |||
118 | boolean mddi_toshiba_61Hz_refresh = TRUE; | ||
119 | |||
120 | /* Modifications to timing to increase refresh rate to > 60Hz. | ||
121 | * 20MHz dot clock. | ||
122 | * 646 total rows. | ||
123 | * 506 total columns. | ||
124 | * refresh rate = 61.19Hz | ||
125 | */ | ||
126 | static uint32 mddi_toshiba_rows_per_second = 39526; | ||
127 | static uint32 mddi_toshiba_usecs_per_refresh = 16344; | ||
128 | static uint32 mddi_toshiba_rows_per_refresh = 646; | ||
129 | extern boolean mddi_vsync_detect_enabled; | ||
130 | |||
131 | static msm_fb_vsync_handler_type mddi_toshiba_vsync_handler; | ||
132 | static void *mddi_toshiba_vsync_handler_arg; | ||
133 | static uint16 mddi_toshiba_vsync_attempts; | ||
134 | |||
135 | static mddi_toshiba_state_t toshiba_state = TOSHIBA_STATE_OFF; | ||
136 | |||
137 | static struct msm_panel_common_pdata *mddi_toshiba_pdata; | ||
138 | |||
139 | static int mddi_toshiba_lcd_on(struct platform_device *pdev); | ||
140 | static int mddi_toshiba_lcd_off(struct platform_device *pdev); | ||
141 | |||
142 | static void mddi_toshiba_state_transition(mddi_toshiba_state_t a, | ||
143 | mddi_toshiba_state_t b) | ||
144 | { | ||
145 | if (toshiba_state != a) { | ||
146 | MDDI_MSG_ERR("toshiba state trans. (%d->%d) found %d\n", a, b, | ||
147 | toshiba_state); | ||
148 | } | ||
149 | toshiba_state = b; | ||
150 | } | ||
151 | |||
152 | #define GORDON_REG_IMGCTL1 0x10 /* Image interface control 1 */ | ||
153 | #define GORDON_REG_IMGCTL2 0x11 /* Image interface control 2 */ | ||
154 | #define GORDON_REG_IMGSET1 0x12 /* Image interface settings 1 */ | ||
155 | #define GORDON_REG_IMGSET2 0x13 /* Image interface settings 2 */ | ||
156 | #define GORDON_REG_IVBP1 0x14 /* DM0: Vert back porch */ | ||
157 | #define GORDON_REG_IHBP1 0x15 /* DM0: Horiz back porch */ | ||
158 | #define GORDON_REG_IVNUM1 0x16 /* DM0: Num of vert lines */ | ||
159 | #define GORDON_REG_IHNUM1 0x17 /* DM0: Num of pixels per line */ | ||
160 | #define GORDON_REG_IVBP2 0x18 /* DM1: Vert back porch */ | ||
161 | #define GORDON_REG_IHBP2 0x19 /* DM1: Horiz back porch */ | ||
162 | #define GORDON_REG_IVNUM2 0x1A /* DM1: Num of vert lines */ | ||
163 | #define GORDON_REG_IHNUM2 0x1B /* DM1: Num of pixels per line */ | ||
164 | #define GORDON_REG_LCDIFCTL1 0x30 /* LCD interface control 1 */ | ||
165 | #define GORDON_REG_VALTRAN 0x31 /* LCD IF ctl: VALTRAN sync flag */ | ||
166 | #define GORDON_REG_AVCTL 0x33 | ||
167 | #define GORDON_REG_LCDIFCTL2 0x34 /* LCD interface control 2 */ | ||
168 | #define GORDON_REG_LCDIFCTL3 0x35 /* LCD interface control 3 */ | ||
169 | #define GORDON_REG_LCDIFSET1 0x36 /* LCD interface settings 1 */ | ||
170 | #define GORDON_REG_PCCTL 0x3C | ||
171 | #define GORDON_REG_TPARAM1 0x40 | ||
172 | #define GORDON_REG_TLCDIF1 0x41 | ||
173 | #define GORDON_REG_TSSPB_ST1 0x42 | ||
174 | #define GORDON_REG_TSSPB_ED1 0x43 | ||
175 | #define GORDON_REG_TSCK_ST1 0x44 | ||
176 | #define GORDON_REG_TSCK_WD1 0x45 | ||
177 | #define GORDON_REG_TGSPB_VST1 0x46 | ||
178 | #define GORDON_REG_TGSPB_VED1 0x47 | ||
179 | #define GORDON_REG_TGSPB_CH1 0x48 | ||
180 | #define GORDON_REG_TGCK_ST1 0x49 | ||
181 | #define GORDON_REG_TGCK_ED1 0x4A | ||
182 | #define GORDON_REG_TPCTL_ST1 0x4B | ||
183 | #define GORDON_REG_TPCTL_ED1 0x4C | ||
184 | #define GORDON_REG_TPCHG_ED1 0x4D | ||
185 | #define GORDON_REG_TCOM_CH1 0x4E | ||
186 | #define GORDON_REG_THBP1 0x4F | ||
187 | #define GORDON_REG_TPHCTL1 0x50 | ||
188 | #define GORDON_REG_EVPH1 0x51 | ||
189 | #define GORDON_REG_EVPL1 0x52 | ||
190 | #define GORDON_REG_EVNH1 0x53 | ||
191 | #define GORDON_REG_EVNL1 0x54 | ||
192 | #define GORDON_REG_TBIAS1 0x55 | ||
193 | #define GORDON_REG_TPARAM2 0x56 | ||
194 | #define GORDON_REG_TLCDIF2 0x57 | ||
195 | #define GORDON_REG_TSSPB_ST2 0x58 | ||
196 | #define GORDON_REG_TSSPB_ED2 0x59 | ||
197 | #define GORDON_REG_TSCK_ST2 0x5A | ||
198 | #define GORDON_REG_TSCK_WD2 0x5B | ||
199 | #define GORDON_REG_TGSPB_VST2 0x5C | ||
200 | #define GORDON_REG_TGSPB_VED2 0x5D | ||
201 | #define GORDON_REG_TGSPB_CH2 0x5E | ||
202 | #define GORDON_REG_TGCK_ST2 0x5F | ||
203 | #define GORDON_REG_TGCK_ED2 0x60 | ||
204 | #define GORDON_REG_TPCTL_ST2 0x61 | ||
205 | #define GORDON_REG_TPCTL_ED2 0x62 | ||
206 | #define GORDON_REG_TPCHG_ED2 0x63 | ||
207 | #define GORDON_REG_TCOM_CH2 0x64 | ||
208 | #define GORDON_REG_THBP2 0x65 | ||
209 | #define GORDON_REG_TPHCTL2 0x66 | ||
210 | #define GORDON_REG_EVPH2 0x67 | ||
211 | #define GORDON_REG_EVPL2 0x68 | ||
212 | #define GORDON_REG_EVNH2 0x69 | ||
213 | #define GORDON_REG_EVNL2 0x6A | ||
214 | #define GORDON_REG_TBIAS2 0x6B | ||
215 | #define GORDON_REG_POWCTL 0x80 | ||
216 | #define GORDON_REG_POWOSC1 0x81 | ||
217 | #define GORDON_REG_POWOSC2 0x82 | ||
218 | #define GORDON_REG_POWSET 0x83 | ||
219 | #define GORDON_REG_POWTRM1 0x85 | ||
220 | #define GORDON_REG_POWTRM2 0x86 | ||
221 | #define GORDON_REG_POWTRM3 0x87 | ||
222 | #define GORDON_REG_POWTRMSEL 0x88 | ||
223 | #define GORDON_REG_POWHIZ 0x89 | ||
224 | |||
225 | void serigo(uint16 reg, uint8 data) | ||
226 | { | ||
227 | uint32 mddi_val = 0; | ||
228 | mddi_queue_register_read(SSIINTS, &mddi_val, TRUE, 0); | ||
229 | if (mddi_val & (1 << 8)) | ||
230 | mddi_wait(1); | ||
231 | /* No De-assert of CS and send 2 bytes */ | ||
232 | mddi_val = 0x90000 | ((0x00FF & reg) << 8) | data; | ||
233 | mddi_queue_register_write(SSITX, mddi_val, TRUE, 0); | ||
234 | } | ||
235 | |||
236 | void gordon_init(void) | ||
237 | { | ||
238 | /* Image interface settings ***/ | ||
239 | serigo(GORDON_REG_IMGCTL2, 0x00); | ||
240 | serigo(GORDON_REG_IMGSET1, 0x01); | ||
241 | |||
242 | /* Exchange the RGB signal for J510(Softbank mobile) */ | ||
243 | serigo(GORDON_REG_IMGSET2, 0x12); | ||
244 | serigo(GORDON_REG_LCDIFSET1, 0x00); | ||
245 | mddi_wait(2); | ||
246 | |||
247 | /* Pre-charge settings */ | ||
248 | serigo(GORDON_REG_PCCTL, 0x09); | ||
249 | serigo(GORDON_REG_LCDIFCTL2, 0x1B); | ||
250 | mddi_wait(1); | ||
251 | } | ||
252 | |||
253 | void gordon_disp_on(void) | ||
254 | { | ||
255 | /*gordon_dispmode setting */ | ||
256 | /*VGA settings */ | ||
257 | serigo(GORDON_REG_TPARAM1, 0x30); | ||
258 | serigo(GORDON_REG_TLCDIF1, 0x00); | ||
259 | serigo(GORDON_REG_TSSPB_ST1, 0x8B); | ||
260 | serigo(GORDON_REG_TSSPB_ED1, 0x93); | ||
261 | mddi_wait(2); | ||
262 | serigo(GORDON_REG_TSCK_ST1, 0x88); | ||
263 | serigo(GORDON_REG_TSCK_WD1, 0x00); | ||
264 | serigo(GORDON_REG_TGSPB_VST1, 0x01); | ||
265 | serigo(GORDON_REG_TGSPB_VED1, 0x02); | ||
266 | mddi_wait(2); | ||
267 | serigo(GORDON_REG_TGSPB_CH1, 0x5E); | ||
268 | serigo(GORDON_REG_TGCK_ST1, 0x80); | ||
269 | serigo(GORDON_REG_TGCK_ED1, 0x3C); | ||
270 | serigo(GORDON_REG_TPCTL_ST1, 0x50); | ||
271 | mddi_wait(2); | ||
272 | serigo(GORDON_REG_TPCTL_ED1, 0x74); | ||
273 | serigo(GORDON_REG_TPCHG_ED1, 0x78); | ||
274 | serigo(GORDON_REG_TCOM_CH1, 0x50); | ||
275 | serigo(GORDON_REG_THBP1, 0x84); | ||
276 | mddi_wait(2); | ||
277 | serigo(GORDON_REG_TPHCTL1, 0x00); | ||
278 | serigo(GORDON_REG_EVPH1, 0x70); | ||
279 | serigo(GORDON_REG_EVPL1, 0x64); | ||
280 | serigo(GORDON_REG_EVNH1, 0x56); | ||
281 | mddi_wait(2); | ||
282 | serigo(GORDON_REG_EVNL1, 0x48); | ||
283 | serigo(GORDON_REG_TBIAS1, 0x88); | ||
284 | mddi_wait(2); | ||
285 | serigo(GORDON_REG_TPARAM2, 0x28); | ||
286 | serigo(GORDON_REG_TLCDIF2, 0x14); | ||
287 | serigo(GORDON_REG_TSSPB_ST2, 0x49); | ||
288 | serigo(GORDON_REG_TSSPB_ED2, 0x4B); | ||
289 | mddi_wait(2); | ||
290 | serigo(GORDON_REG_TSCK_ST2, 0x4A); | ||
291 | serigo(GORDON_REG_TSCK_WD2, 0x02); | ||
292 | serigo(GORDON_REG_TGSPB_VST2, 0x02); | ||
293 | serigo(GORDON_REG_TGSPB_VED2, 0x03); | ||
294 | mddi_wait(2); | ||
295 | serigo(GORDON_REG_TGSPB_CH2, 0x2F); | ||
296 | serigo(GORDON_REG_TGCK_ST2, 0x40); | ||
297 | serigo(GORDON_REG_TGCK_ED2, 0x1E); | ||
298 | serigo(GORDON_REG_TPCTL_ST2, 0x2C); | ||
299 | mddi_wait(2); | ||
300 | serigo(GORDON_REG_TPCTL_ED2, 0x3A); | ||
301 | serigo(GORDON_REG_TPCHG_ED2, 0x3C); | ||
302 | serigo(GORDON_REG_TCOM_CH2, 0x28); | ||
303 | serigo(GORDON_REG_THBP2, 0x4D); | ||
304 | mddi_wait(2); | ||
305 | serigo(GORDON_REG_TPHCTL2, 0x1A); | ||
306 | mddi_wait(2); | ||
307 | serigo(GORDON_REG_IVBP1, 0x02); | ||
308 | serigo(GORDON_REG_IHBP1, 0x90); | ||
309 | serigo(GORDON_REG_IVNUM1, 0xA0); | ||
310 | serigo(GORDON_REG_IHNUM1, 0x78); | ||
311 | mddi_wait(2); | ||
312 | serigo(GORDON_REG_IVBP2, 0x02); | ||
313 | serigo(GORDON_REG_IHBP2, 0x48); | ||
314 | serigo(GORDON_REG_IVNUM2, 0x50); | ||
315 | serigo(GORDON_REG_IHNUM2, 0x3C); | ||
316 | mddi_wait(2); | ||
317 | serigo(GORDON_REG_POWCTL, 0x03); | ||
318 | mddi_wait(15); | ||
319 | serigo(GORDON_REG_POWCTL, 0x07); | ||
320 | mddi_wait(15); | ||
321 | serigo(GORDON_REG_POWCTL, 0x0F); | ||
322 | mddi_wait(15); | ||
323 | serigo(GORDON_REG_AVCTL, 0x03); | ||
324 | mddi_wait(15); | ||
325 | serigo(GORDON_REG_POWCTL, 0x1F); | ||
326 | mddi_wait(15); | ||
327 | serigo(GORDON_REG_POWCTL, 0x5F); | ||
328 | mddi_wait(15); | ||
329 | serigo(GORDON_REG_POWCTL, 0x7F); | ||
330 | mddi_wait(15); | ||
331 | serigo(GORDON_REG_LCDIFCTL1, 0x02); | ||
332 | mddi_wait(15); | ||
333 | serigo(GORDON_REG_IMGCTL1, 0x00); | ||
334 | mddi_wait(15); | ||
335 | serigo(GORDON_REG_LCDIFCTL3, 0x00); | ||
336 | mddi_wait(15); | ||
337 | serigo(GORDON_REG_VALTRAN, 0x01); | ||
338 | mddi_wait(15); | ||
339 | serigo(GORDON_REG_LCDIFCTL1, 0x03); | ||
340 | serigo(GORDON_REG_LCDIFCTL1, 0x03); | ||
341 | mddi_wait(1); | ||
342 | } | ||
343 | |||
344 | void gordon_disp_off(void) | ||
345 | { | ||
346 | serigo(GORDON_REG_LCDIFCTL2, 0x7B); | ||
347 | serigo(GORDON_REG_VALTRAN, 0x01); | ||
348 | serigo(GORDON_REG_LCDIFCTL1, 0x02); | ||
349 | serigo(GORDON_REG_LCDIFCTL3, 0x01); | ||
350 | mddi_wait(20); | ||
351 | serigo(GORDON_REG_VALTRAN, 0x01); | ||
352 | serigo(GORDON_REG_IMGCTL1, 0x01); | ||
353 | serigo(GORDON_REG_LCDIFCTL1, 0x00); | ||
354 | mddi_wait(20); | ||
355 | serigo(GORDON_REG_POWCTL, 0x1F); | ||
356 | mddi_wait(40); | ||
357 | serigo(GORDON_REG_POWCTL, 0x07); | ||
358 | mddi_wait(40); | ||
359 | serigo(GORDON_REG_POWCTL, 0x03); | ||
360 | mddi_wait(40); | ||
361 | serigo(GORDON_REG_POWCTL, 0x00); | ||
362 | mddi_wait(40); | ||
363 | } | ||
364 | |||
365 | void gordon_disp_init(void) | ||
366 | { | ||
367 | gordon_init(); | ||
368 | mddi_wait(20); | ||
369 | gordon_disp_on(); | ||
370 | } | ||
371 | |||
372 | static void toshiba_common_initial_setup(struct msm_fb_data_type *mfd) | ||
373 | { | ||
374 | if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT) { | ||
375 | write_client_reg(DPSET0 , 0x4bec0066, TRUE); | ||
376 | write_client_reg(DPSET1 , 0x00000113, TRUE); | ||
377 | write_client_reg(DPSUS , 0x00000000, TRUE); | ||
378 | write_client_reg(DPRUN , 0x00000001, TRUE); | ||
379 | mddi_wait(5); | ||
380 | write_client_reg(SYSCKENA , 0x00000001, TRUE); | ||
381 | write_client_reg(CLKENB , 0x0000a0e9, TRUE); | ||
382 | |||
383 | write_client_reg(GPIODATA , 0x03FF0000, TRUE); | ||
384 | write_client_reg(GPIODIR , 0x0000024D, TRUE); | ||
385 | write_client_reg(GPIOSEL , 0x00000173, TRUE); | ||
386 | write_client_reg(GPIOPC , 0x03C300C0, TRUE); | ||
387 | write_client_reg(WKREQ , 0x00000000, TRUE); | ||
388 | write_client_reg(GPIOIS , 0x00000000, TRUE); | ||
389 | write_client_reg(GPIOIEV , 0x00000001, TRUE); | ||
390 | write_client_reg(GPIOIC , 0x000003FF, TRUE); | ||
391 | write_client_reg(GPIODATA , 0x00040004, TRUE); | ||
392 | |||
393 | write_client_reg(GPIODATA , 0x00080008, TRUE); | ||
394 | write_client_reg(DRAMPWR , 0x00000001, TRUE); | ||
395 | write_client_reg(CLKENB , 0x0000a0eb, TRUE); | ||
396 | write_client_reg(PWMCR , 0x00000000, TRUE); | ||
397 | mddi_wait(1); | ||
398 | |||
399 | write_client_reg(SSICTL , 0x00060399, TRUE); | ||
400 | write_client_reg(SSITIME , 0x00000100, TRUE); | ||
401 | write_client_reg(CNT_DIS , 0x00000002, TRUE); | ||
402 | write_client_reg(SSICTL , 0x0006039b, TRUE); | ||
403 | |||
404 | write_client_reg(SSITX , 0x00000000, TRUE); | ||
405 | mddi_wait(7); | ||
406 | write_client_reg(SSITX , 0x00000000, TRUE); | ||
407 | mddi_wait(7); | ||
408 | write_client_reg(SSITX , 0x00000000, TRUE); | ||
409 | mddi_wait(7); | ||
410 | |||
411 | write_client_reg(SSITX , 0x000800BA, TRUE); | ||
412 | write_client_reg(SSITX , 0x00000111, TRUE); | ||
413 | write_client_reg(SSITX , 0x00080036, TRUE); | ||
414 | write_client_reg(SSITX , 0x00000100, TRUE); | ||
415 | mddi_wait(1); | ||
416 | write_client_reg(SSITX , 0x0008003A, TRUE); | ||
417 | write_client_reg(SSITX , 0x00000160, TRUE); | ||
418 | write_client_reg(SSITX , 0x000800B1, TRUE); | ||
419 | write_client_reg(SSITX , 0x0000015D, TRUE); | ||
420 | mddi_wait(1); | ||
421 | write_client_reg(SSITX , 0x000800B2, TRUE); | ||
422 | write_client_reg(SSITX , 0x00000133, TRUE); | ||
423 | write_client_reg(SSITX , 0x000800B3, TRUE); | ||
424 | write_client_reg(SSITX , 0x00000122, TRUE); | ||
425 | mddi_wait(1); | ||
426 | write_client_reg(SSITX , 0x000800B4, TRUE); | ||
427 | write_client_reg(SSITX , 0x00000102, TRUE); | ||
428 | write_client_reg(SSITX , 0x000800B5, TRUE); | ||
429 | write_client_reg(SSITX , 0x0000011E, TRUE); | ||
430 | mddi_wait(1); | ||
431 | write_client_reg(SSITX , 0x000800B6, TRUE); | ||
432 | write_client_reg(SSITX , 0x00000127, TRUE); | ||
433 | write_client_reg(SSITX , 0x000800B7, TRUE); | ||
434 | write_client_reg(SSITX , 0x00000103, TRUE); | ||
435 | mddi_wait(1); | ||
436 | write_client_reg(SSITX , 0x000800B9, TRUE); | ||
437 | write_client_reg(SSITX , 0x00000124, TRUE); | ||
438 | write_client_reg(SSITX , 0x000800BD, TRUE); | ||
439 | write_client_reg(SSITX , 0x000001A1, TRUE); | ||
440 | mddi_wait(1); | ||
441 | write_client_reg(SSITX , 0x000800BB, TRUE); | ||
442 | write_client_reg(SSITX , 0x00000100, TRUE); | ||
443 | write_client_reg(SSITX , 0x000800BF, TRUE); | ||
444 | write_client_reg(SSITX , 0x00000101, TRUE); | ||
445 | mddi_wait(1); | ||
446 | write_client_reg(SSITX , 0x000800BE, TRUE); | ||
447 | write_client_reg(SSITX , 0x00000100, TRUE); | ||
448 | write_client_reg(SSITX , 0x000800C0, TRUE); | ||
449 | write_client_reg(SSITX , 0x00000111, TRUE); | ||
450 | mddi_wait(1); | ||
451 | write_client_reg(SSITX , 0x000800C1, TRUE); | ||
452 | write_client_reg(SSITX , 0x00000111, TRUE); | ||
453 | write_client_reg(SSITX , 0x000800C2, TRUE); | ||
454 | write_client_reg(SSITX , 0x00000111, TRUE); | ||
455 | mddi_wait(1); | ||
456 | write_client_reg(SSITX , 0x000800C3, TRUE); | ||
457 | write_client_reg(SSITX , 0x00080132, TRUE); | ||
458 | write_client_reg(SSITX , 0x00000132, TRUE); | ||
459 | mddi_wait(1); | ||
460 | write_client_reg(SSITX , 0x000800C4, TRUE); | ||
461 | write_client_reg(SSITX , 0x00080132, TRUE); | ||
462 | write_client_reg(SSITX , 0x00000132, TRUE); | ||
463 | mddi_wait(1); | ||
464 | write_client_reg(SSITX , 0x000800C5, TRUE); | ||
465 | write_client_reg(SSITX , 0x00080132, TRUE); | ||
466 | write_client_reg(SSITX , 0x00000132, TRUE); | ||
467 | mddi_wait(1); | ||
468 | write_client_reg(SSITX , 0x000800C6, TRUE); | ||
469 | write_client_reg(SSITX , 0x00080132, TRUE); | ||
470 | write_client_reg(SSITX , 0x00000132, TRUE); | ||
471 | mddi_wait(1); | ||
472 | write_client_reg(SSITX , 0x000800C7, TRUE); | ||
473 | write_client_reg(SSITX , 0x00080164, TRUE); | ||
474 | write_client_reg(SSITX , 0x00000145, TRUE); | ||
475 | mddi_wait(1); | ||
476 | write_client_reg(SSITX , 0x000800C8, TRUE); | ||
477 | write_client_reg(SSITX , 0x00000144, TRUE); | ||
478 | write_client_reg(SSITX , 0x000800C9, TRUE); | ||
479 | write_client_reg(SSITX , 0x00000152, TRUE); | ||
480 | mddi_wait(1); | ||
481 | write_client_reg(SSITX , 0x000800CA, TRUE); | ||
482 | write_client_reg(SSITX , 0x00000100, TRUE); | ||
483 | mddi_wait(1); | ||
484 | write_client_reg(SSITX , 0x000800EC, TRUE); | ||
485 | write_client_reg(SSITX , 0x00080101, TRUE); | ||
486 | write_client_reg(SSITX , 0x000001FC, TRUE); | ||
487 | mddi_wait(1); | ||
488 | write_client_reg(SSITX , 0x000800CF, TRUE); | ||
489 | write_client_reg(SSITX , 0x00000101, TRUE); | ||
490 | mddi_wait(1); | ||
491 | write_client_reg(SSITX , 0x000800D0, TRUE); | ||
492 | write_client_reg(SSITX , 0x00080110, TRUE); | ||
493 | write_client_reg(SSITX , 0x00000104, TRUE); | ||
494 | mddi_wait(1); | ||
495 | write_client_reg(SSITX , 0x000800D1, TRUE); | ||
496 | write_client_reg(SSITX , 0x00000101, TRUE); | ||
497 | mddi_wait(1); | ||
498 | write_client_reg(SSITX , 0x000800D2, TRUE); | ||
499 | write_client_reg(SSITX , 0x00080100, TRUE); | ||
500 | write_client_reg(SSITX , 0x00000128, TRUE); | ||
501 | mddi_wait(1); | ||
502 | write_client_reg(SSITX , 0x000800D3, TRUE); | ||
503 | write_client_reg(SSITX , 0x00080100, TRUE); | ||
504 | write_client_reg(SSITX , 0x00000128, TRUE); | ||
505 | mddi_wait(1); | ||
506 | write_client_reg(SSITX , 0x000800D4, TRUE); | ||
507 | write_client_reg(SSITX , 0x00080126, TRUE); | ||
508 | write_client_reg(SSITX , 0x000001A4, TRUE); | ||
509 | mddi_wait(1); | ||
510 | write_client_reg(SSITX , 0x000800D5, TRUE); | ||
511 | write_client_reg(SSITX , 0x00000120, TRUE); | ||
512 | mddi_wait(1); | ||
513 | write_client_reg(SSITX , 0x000800EF, TRUE); | ||
514 | write_client_reg(SSITX , 0x00080132, TRUE); | ||
515 | write_client_reg(SSITX , 0x00000100, TRUE); | ||
516 | mddi_wait(1); | ||
517 | |||
518 | write_client_reg(BITMAP0 , 0x032001E0, TRUE); | ||
519 | write_client_reg(BITMAP1 , 0x032001E0, TRUE); | ||
520 | write_client_reg(BITMAP2 , 0x014000F0, TRUE); | ||
521 | write_client_reg(BITMAP3 , 0x014000F0, TRUE); | ||
522 | write_client_reg(BITMAP4 , 0x014000F0, TRUE); | ||
523 | write_client_reg(CLKENB , 0x0000A1EB, TRUE); | ||
524 | write_client_reg(PORT_ENB , 0x00000001, TRUE); | ||
525 | write_client_reg(PORT , 0x00000004, TRUE); | ||
526 | write_client_reg(PXL , 0x00000002, TRUE); | ||
527 | write_client_reg(MPLFBUF , 0x00000000, TRUE); | ||
528 | write_client_reg(HCYCLE , 0x000000FD, TRUE); | ||
529 | write_client_reg(HSW , 0x00000003, TRUE); | ||
530 | write_client_reg(HDE_START , 0x00000007, TRUE); | ||
531 | write_client_reg(HDE_SIZE , 0x000000EF, TRUE); | ||
532 | write_client_reg(VCYCLE , 0x00000325, TRUE); | ||
533 | write_client_reg(VSW , 0x00000001, TRUE); | ||
534 | write_client_reg(VDE_START , 0x00000003, TRUE); | ||
535 | write_client_reg(VDE_SIZE , 0x0000031F, TRUE); | ||
536 | write_client_reg(START , 0x00000001, TRUE); | ||
537 | mddi_wait(32); | ||
538 | write_client_reg(SSITX , 0x000800BC, TRUE); | ||
539 | write_client_reg(SSITX , 0x00000180, TRUE); | ||
540 | write_client_reg(SSITX , 0x0008003B, TRUE); | ||
541 | write_client_reg(SSITX , 0x00000100, TRUE); | ||
542 | mddi_wait(1); | ||
543 | write_client_reg(SSITX , 0x000800B0, TRUE); | ||
544 | write_client_reg(SSITX , 0x00000116, TRUE); | ||
545 | mddi_wait(1); | ||
546 | write_client_reg(SSITX , 0x000800B8, TRUE); | ||
547 | write_client_reg(SSITX , 0x000801FF, TRUE); | ||
548 | write_client_reg(SSITX , 0x000001F5, TRUE); | ||
549 | mddi_wait(1); | ||
550 | write_client_reg(SSITX , 0x00000011, TRUE); | ||
551 | mddi_wait(5); | ||
552 | write_client_reg(SSITX , 0x00000029, TRUE); | ||
553 | return; | ||
554 | } | ||
555 | |||
556 | if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA) { | ||
557 | write_client_reg(DPSET0, 0x4BEC0066, TRUE); | ||
558 | write_client_reg(DPSET1, 0x00000113, TRUE); | ||
559 | write_client_reg(DPSUS, 0x00000000, TRUE); | ||
560 | write_client_reg(DPRUN, 0x00000001, TRUE); | ||
561 | mddi_wait(14); | ||
562 | write_client_reg(SYSCKENA, 0x00000001, TRUE); | ||
563 | write_client_reg(CLKENB, 0x000000EF, TRUE); | ||
564 | write_client_reg(GPIO_BLOCK_BASE, 0x03FF0000, TRUE); | ||
565 | write_client_reg(GPIODIR, 0x0000024D, TRUE); | ||
566 | write_client_reg(SYSTEM_BLOCK2_BASE, 0x00000173, TRUE); | ||
567 | write_client_reg(GPIOPC, 0x03C300C0, TRUE); | ||
568 | write_client_reg(SYSTEM_BLOCK1_BASE, 0x00000000, TRUE); | ||
569 | write_client_reg(GPIOIS, 0x00000000, TRUE); | ||
570 | write_client_reg(GPIOIEV, 0x00000001, TRUE); | ||
571 | write_client_reg(GPIOIC, 0x000003FF, TRUE); | ||
572 | write_client_reg(GPIO_BLOCK_BASE, 0x00060006, TRUE); | ||
573 | write_client_reg(GPIO_BLOCK_BASE, 0x00080008, TRUE); | ||
574 | write_client_reg(GPIO_BLOCK_BASE, 0x02000200, TRUE); | ||
575 | write_client_reg(DRAMPWR, 0x00000001, TRUE); | ||
576 | write_client_reg(TIMER0CTRL, 0x00000060, TRUE); | ||
577 | write_client_reg(PWM_BLOCK_BASE, 0x00001388, TRUE); | ||
578 | write_client_reg(PWM0OFF, 0x00001387, TRUE); | ||
579 | write_client_reg(TIMER1CTRL, 0x00000060, TRUE); | ||
580 | write_client_reg(TIMER1LOAD, 0x00001388, TRUE); | ||
581 | write_client_reg(PWM1OFF, 0x00001387, TRUE); | ||
582 | write_client_reg(TIMER0CTRL, 0x000000E0, TRUE); | ||
583 | write_client_reg(TIMER1CTRL, 0x000000E0, TRUE); | ||
584 | write_client_reg(PWMCR, 0x00000003, TRUE); | ||
585 | mddi_wait(1); | ||
586 | write_client_reg(SPI_BLOCK_BASE, 0x00063111, TRUE); | ||
587 | write_client_reg(SSITIME, 0x00000100, TRUE); | ||
588 | write_client_reg(SPI_BLOCK_BASE, 0x00063113, TRUE); | ||
589 | mddi_wait(1); | ||
590 | write_client_reg(SSITX, 0x00000000, TRUE); | ||
591 | mddi_wait(1); | ||
592 | write_client_reg(SSITX, 0x00000000, TRUE); | ||
593 | mddi_wait(1); | ||
594 | write_client_reg(SSITX, 0x00000000, TRUE); | ||
595 | mddi_wait(1); | ||
596 | write_client_reg(CLKENB, 0x0000A1EF, TRUE); | ||
597 | write_client_reg(START, 0x00000000, TRUE); | ||
598 | write_client_reg(WRSTB, 0x0000003F, TRUE); | ||
599 | write_client_reg(RDSTB, 0x00000432, TRUE); | ||
600 | write_client_reg(PORT_ENB, 0x00000002, TRUE); | ||
601 | write_client_reg(VSYNIF, 0x00000000, TRUE); | ||
602 | write_client_reg(ASY_DATA, 0x80000000, TRUE); | ||
603 | write_client_reg(ASY_DATB, 0x00000001, TRUE); | ||
604 | write_client_reg(ASY_CMDSET, 0x00000005, TRUE); | ||
605 | write_client_reg(ASY_CMDSET, 0x00000004, TRUE); | ||
606 | mddi_wait(10); | ||
607 | write_client_reg(ASY_DATA, 0x80000000, TRUE); | ||
608 | write_client_reg(ASY_DATB, 0x80000000, TRUE); | ||
609 | write_client_reg(ASY_DATC, 0x80000000, TRUE); | ||
610 | write_client_reg(ASY_DATD, 0x80000000, TRUE); | ||
611 | write_client_reg(ASY_CMDSET, 0x00000009, TRUE); | ||
612 | write_client_reg(ASY_CMDSET, 0x00000008, TRUE); | ||
613 | write_client_reg(ASY_DATA, 0x80000007, TRUE); | ||
614 | write_client_reg(ASY_DATB, 0x00004005, TRUE); | ||
615 | write_client_reg(ASY_CMDSET, 0x00000005, TRUE); | ||
616 | write_client_reg(ASY_CMDSET, 0x00000004, TRUE); | ||
617 | mddi_wait(20); | ||
618 | write_client_reg(ASY_DATA, 0x80000059, TRUE); | ||
619 | write_client_reg(ASY_DATB, 0x00000000, TRUE); | ||
620 | write_client_reg(ASY_CMDSET, 0x00000005, TRUE); | ||
621 | write_client_reg(ASY_CMDSET, 0x00000004, TRUE); | ||
622 | |||
623 | write_client_reg(VSYNIF, 0x00000001, TRUE); | ||
624 | write_client_reg(PORT_ENB, 0x00000001, TRUE); | ||
625 | } else { | ||
626 | write_client_reg(DPSET0, 0x4BEC0066, TRUE); | ||
627 | write_client_reg(DPSET1, 0x00000113, TRUE); | ||
628 | write_client_reg(DPSUS, 0x00000000, TRUE); | ||
629 | write_client_reg(DPRUN, 0x00000001, TRUE); | ||
630 | mddi_wait(14); | ||
631 | write_client_reg(SYSCKENA, 0x00000001, TRUE); | ||
632 | write_client_reg(CLKENB, 0x000000EF, TRUE); | ||
633 | write_client_reg(GPIODATA, 0x03FF0000, TRUE); | ||
634 | write_client_reg(GPIODIR, 0x0000024D, TRUE); | ||
635 | write_client_reg(GPIOSEL, 0x00000173, TRUE); | ||
636 | write_client_reg(GPIOPC, 0x03C300C0, TRUE); | ||
637 | write_client_reg(WKREQ, 0x00000000, TRUE); | ||
638 | write_client_reg(GPIOIS, 0x00000000, TRUE); | ||
639 | write_client_reg(GPIOIEV, 0x00000001, TRUE); | ||
640 | write_client_reg(GPIOIC, 0x000003FF, TRUE); | ||
641 | write_client_reg(GPIODATA, 0x00060006, TRUE); | ||
642 | write_client_reg(GPIODATA, 0x00080008, TRUE); | ||
643 | write_client_reg(GPIODATA, 0x02000200, TRUE); | ||
644 | |||
645 | if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA) { | ||
646 | mddi_wait(400); | ||
647 | write_client_reg(DRAMPWR, 0x00000001, TRUE); | ||
648 | |||
649 | write_client_reg(CNT_DIS, 0x00000002, TRUE); | ||
650 | write_client_reg(BITMAP0, 0x01E00320, TRUE); | ||
651 | write_client_reg(PORT_ENB, 0x00000001, TRUE); | ||
652 | write_client_reg(PORT, 0x00000004, TRUE); | ||
653 | write_client_reg(PXL, 0x0000003A, TRUE); | ||
654 | write_client_reg(MPLFBUF, 0x00000000, TRUE); | ||
655 | write_client_reg(HCYCLE, 0x00000253, TRUE); | ||
656 | write_client_reg(HSW, 0x00000003, TRUE); | ||
657 | write_client_reg(HDE_START, 0x00000017, TRUE); | ||
658 | write_client_reg(HDE_SIZE, 0x0000018F, TRUE); | ||
659 | write_client_reg(VCYCLE, 0x000001FF, TRUE); | ||
660 | write_client_reg(VSW, 0x00000001, TRUE); | ||
661 | write_client_reg(VDE_START, 0x00000003, TRUE); | ||
662 | write_client_reg(VDE_SIZE, 0x000001DF, TRUE); | ||
663 | write_client_reg(START, 0x00000001, TRUE); | ||
664 | mddi_wait(1); | ||
665 | write_client_reg(TIMER0CTRL, 0x00000060, TRUE); | ||
666 | write_client_reg(TIMER0LOAD, 0x00001388, TRUE); | ||
667 | write_client_reg(TIMER1CTRL, 0x00000060, TRUE); | ||
668 | write_client_reg(TIMER1LOAD, 0x00001388, TRUE); | ||
669 | write_client_reg(PWM1OFF, 0x00000087, TRUE); | ||
670 | } else { | ||
671 | write_client_reg(DRAMPWR, 0x00000001, TRUE); | ||
672 | write_client_reg(TIMER0CTRL, 0x00000060, TRUE); | ||
673 | write_client_reg(TIMER0LOAD, 0x00001388, TRUE); | ||
674 | write_client_reg(TIMER1CTRL, 0x00000060, TRUE); | ||
675 | write_client_reg(TIMER1LOAD, 0x00001388, TRUE); | ||
676 | write_client_reg(PWM1OFF, 0x00001387, TRUE); | ||
677 | } | ||
678 | |||
679 | write_client_reg(TIMER0CTRL, 0x000000E0, TRUE); | ||
680 | write_client_reg(TIMER1CTRL, 0x000000E0, TRUE); | ||
681 | write_client_reg(PWMCR, 0x00000003, TRUE); | ||
682 | mddi_wait(1); | ||
683 | write_client_reg(SSICTL, 0x00000799, TRUE); | ||
684 | write_client_reg(SSITIME, 0x00000100, TRUE); | ||
685 | write_client_reg(SSICTL, 0x0000079b, TRUE); | ||
686 | write_client_reg(SSITX, 0x00000000, TRUE); | ||
687 | mddi_wait(1); | ||
688 | write_client_reg(SSITX, 0x00000000, TRUE); | ||
689 | mddi_wait(1); | ||
690 | write_client_reg(SSITX, 0x00000000, TRUE); | ||
691 | mddi_wait(1); | ||
692 | write_client_reg(SSITX, 0x000800BA, TRUE); | ||
693 | write_client_reg(SSITX, 0x00000111, TRUE); | ||
694 | write_client_reg(SSITX, 0x00080036, TRUE); | ||
695 | write_client_reg(SSITX, 0x00000100, TRUE); | ||
696 | mddi_wait(2); | ||
697 | write_client_reg(SSITX, 0x000800BB, TRUE); | ||
698 | write_client_reg(SSITX, 0x00000100, TRUE); | ||
699 | write_client_reg(SSITX, 0x0008003A, TRUE); | ||
700 | write_client_reg(SSITX, 0x00000160, TRUE); | ||
701 | mddi_wait(2); | ||
702 | write_client_reg(SSITX, 0x000800BF, TRUE); | ||
703 | write_client_reg(SSITX, 0x00000100, TRUE); | ||
704 | write_client_reg(SSITX, 0x000800B1, TRUE); | ||
705 | write_client_reg(SSITX, 0x0000015D, TRUE); | ||
706 | mddi_wait(2); | ||
707 | write_client_reg(SSITX, 0x000800B2, TRUE); | ||
708 | write_client_reg(SSITX, 0x00000133, TRUE); | ||
709 | write_client_reg(SSITX, 0x000800B3, TRUE); | ||
710 | write_client_reg(SSITX, 0x00000122, TRUE); | ||
711 | mddi_wait(2); | ||
712 | write_client_reg(SSITX, 0x000800B4, TRUE); | ||
713 | write_client_reg(SSITX, 0x00000102, TRUE); | ||
714 | write_client_reg(SSITX, 0x000800B5, TRUE); | ||
715 | write_client_reg(SSITX, 0x0000011F, TRUE); | ||
716 | mddi_wait(2); | ||
717 | write_client_reg(SSITX, 0x000800B6, TRUE); | ||
718 | write_client_reg(SSITX, 0x00000128, TRUE); | ||
719 | write_client_reg(SSITX, 0x000800B7, TRUE); | ||
720 | write_client_reg(SSITX, 0x00000103, TRUE); | ||
721 | mddi_wait(2); | ||
722 | write_client_reg(SSITX, 0x000800B9, TRUE); | ||
723 | write_client_reg(SSITX, 0x00000120, TRUE); | ||
724 | write_client_reg(SSITX, 0x000800BD, TRUE); | ||
725 | write_client_reg(SSITX, 0x00000102, TRUE); | ||
726 | mddi_wait(2); | ||
727 | write_client_reg(SSITX, 0x000800BE, TRUE); | ||
728 | write_client_reg(SSITX, 0x00000100, TRUE); | ||
729 | write_client_reg(SSITX, 0x000800C0, TRUE); | ||
730 | write_client_reg(SSITX, 0x00000111, TRUE); | ||
731 | mddi_wait(2); | ||
732 | write_client_reg(SSITX, 0x000800C1, TRUE); | ||
733 | write_client_reg(SSITX, 0x00000111, TRUE); | ||
734 | write_client_reg(SSITX, 0x000800C2, TRUE); | ||
735 | write_client_reg(SSITX, 0x00000111, TRUE); | ||
736 | mddi_wait(2); | ||
737 | write_client_reg(SSITX, 0x000800C3, TRUE); | ||
738 | write_client_reg(SSITX, 0x0008010A, TRUE); | ||
739 | write_client_reg(SSITX, 0x0000010A, TRUE); | ||
740 | mddi_wait(2); | ||
741 | write_client_reg(SSITX, 0x000800C4, TRUE); | ||
742 | write_client_reg(SSITX, 0x00080160, TRUE); | ||
743 | write_client_reg(SSITX, 0x00000160, TRUE); | ||
744 | mddi_wait(2); | ||
745 | write_client_reg(SSITX, 0x000800C5, TRUE); | ||
746 | write_client_reg(SSITX, 0x00080160, TRUE); | ||
747 | write_client_reg(SSITX, 0x00000160, TRUE); | ||
748 | mddi_wait(2); | ||
749 | write_client_reg(SSITX, 0x000800C6, TRUE); | ||
750 | write_client_reg(SSITX, 0x00080160, TRUE); | ||
751 | write_client_reg(SSITX, 0x00000160, TRUE); | ||
752 | mddi_wait(2); | ||
753 | write_client_reg(SSITX, 0x000800C7, TRUE); | ||
754 | write_client_reg(SSITX, 0x00080133, TRUE); | ||
755 | write_client_reg(SSITX, 0x00000143, TRUE); | ||
756 | mddi_wait(2); | ||
757 | write_client_reg(SSITX, 0x000800C8, TRUE); | ||
758 | write_client_reg(SSITX, 0x00000144, TRUE); | ||
759 | write_client_reg(SSITX, 0x000800C9, TRUE); | ||
760 | write_client_reg(SSITX, 0x00000133, TRUE); | ||
761 | mddi_wait(2); | ||
762 | write_client_reg(SSITX, 0x000800CA, TRUE); | ||
763 | write_client_reg(SSITX, 0x00000100, TRUE); | ||
764 | mddi_wait(2); | ||
765 | write_client_reg(SSITX, 0x000800EC, TRUE); | ||
766 | write_client_reg(SSITX, 0x00080102, TRUE); | ||
767 | write_client_reg(SSITX, 0x00000118, TRUE); | ||
768 | mddi_wait(2); | ||
769 | write_client_reg(SSITX, 0x000800CF, TRUE); | ||
770 | write_client_reg(SSITX, 0x00000101, TRUE); | ||
771 | mddi_wait(2); | ||
772 | write_client_reg(SSITX, 0x000800D0, TRUE); | ||
773 | write_client_reg(SSITX, 0x00080110, TRUE); | ||
774 | write_client_reg(SSITX, 0x00000104, TRUE); | ||
775 | mddi_wait(2); | ||
776 | write_client_reg(SSITX, 0x000800D1, TRUE); | ||
777 | write_client_reg(SSITX, 0x00000101, TRUE); | ||
778 | mddi_wait(2); | ||
779 | write_client_reg(SSITX, 0x000800D2, TRUE); | ||
780 | write_client_reg(SSITX, 0x00080100, TRUE); | ||
781 | write_client_reg(SSITX, 0x0000013A, TRUE); | ||
782 | mddi_wait(2); | ||
783 | write_client_reg(SSITX, 0x000800D3, TRUE); | ||
784 | write_client_reg(SSITX, 0x00080100, TRUE); | ||
785 | write_client_reg(SSITX, 0x0000013A, TRUE); | ||
786 | mddi_wait(2); | ||
787 | write_client_reg(SSITX, 0x000800D4, TRUE); | ||
788 | write_client_reg(SSITX, 0x00080124, TRUE); | ||
789 | write_client_reg(SSITX, 0x0000016E, TRUE); | ||
790 | mddi_wait(1); | ||
791 | write_client_reg(SSITX, 0x000800D5, TRUE); | ||
792 | write_client_reg(SSITX, 0x00000124, TRUE); | ||
793 | mddi_wait(2); | ||
794 | write_client_reg(SSITX, 0x000800ED, TRUE); | ||
795 | write_client_reg(SSITX, 0x00080101, TRUE); | ||
796 | write_client_reg(SSITX, 0x0000010A, TRUE); | ||
797 | mddi_wait(2); | ||
798 | write_client_reg(SSITX, 0x000800D6, TRUE); | ||
799 | write_client_reg(SSITX, 0x00000101, TRUE); | ||
800 | mddi_wait(2); | ||
801 | write_client_reg(SSITX, 0x000800D7, TRUE); | ||
802 | write_client_reg(SSITX, 0x00080110, TRUE); | ||
803 | write_client_reg(SSITX, 0x0000010A, TRUE); | ||
804 | mddi_wait(2); | ||
805 | write_client_reg(SSITX, 0x000800D8, TRUE); | ||
806 | write_client_reg(SSITX, 0x00000101, TRUE); | ||
807 | mddi_wait(2); | ||
808 | write_client_reg(SSITX, 0x000800D9, TRUE); | ||
809 | write_client_reg(SSITX, 0x00080100, TRUE); | ||
810 | write_client_reg(SSITX, 0x00000114, TRUE); | ||
811 | mddi_wait(2); | ||
812 | write_client_reg(SSITX, 0x000800DE, TRUE); | ||
813 | write_client_reg(SSITX, 0x00080100, TRUE); | ||
814 | write_client_reg(SSITX, 0x00000114, TRUE); | ||
815 | mddi_wait(2); | ||
816 | write_client_reg(SSITX, 0x000800DF, TRUE); | ||
817 | write_client_reg(SSITX, 0x00080112, TRUE); | ||
818 | write_client_reg(SSITX, 0x0000013F, TRUE); | ||
819 | mddi_wait(2); | ||
820 | write_client_reg(SSITX, 0x000800E0, TRUE); | ||
821 | write_client_reg(SSITX, 0x0000010B, TRUE); | ||
822 | write_client_reg(SSITX, 0x000800E2, TRUE); | ||
823 | write_client_reg(SSITX, 0x00000101, TRUE); | ||
824 | mddi_wait(2); | ||
825 | write_client_reg(SSITX, 0x000800E3, TRUE); | ||
826 | write_client_reg(SSITX, 0x00000136, TRUE); | ||
827 | mddi_wait(2); | ||
828 | write_client_reg(SSITX, 0x000800E4, TRUE); | ||
829 | write_client_reg(SSITX, 0x00080100, TRUE); | ||
830 | write_client_reg(SSITX, 0x00000103, TRUE); | ||
831 | mddi_wait(2); | ||
832 | write_client_reg(SSITX, 0x000800E5, TRUE); | ||
833 | write_client_reg(SSITX, 0x00080102, TRUE); | ||
834 | write_client_reg(SSITX, 0x00000104, TRUE); | ||
835 | mddi_wait(2); | ||
836 | write_client_reg(SSITX, 0x000800E6, TRUE); | ||
837 | write_client_reg(SSITX, 0x00000103, TRUE); | ||
838 | mddi_wait(2); | ||
839 | write_client_reg(SSITX, 0x000800E7, TRUE); | ||
840 | write_client_reg(SSITX, 0x00080104, TRUE); | ||
841 | write_client_reg(SSITX, 0x0000010A, TRUE); | ||
842 | mddi_wait(2); | ||
843 | write_client_reg(SSITX, 0x000800E8, TRUE); | ||
844 | write_client_reg(SSITX, 0x00000104, TRUE); | ||
845 | write_client_reg(CLKENB, 0x000001EF, TRUE); | ||
846 | write_client_reg(START, 0x00000000, TRUE); | ||
847 | write_client_reg(WRSTB, 0x0000003F, TRUE); | ||
848 | write_client_reg(RDSTB, 0x00000432, TRUE); | ||
849 | write_client_reg(PORT_ENB, 0x00000002, TRUE); | ||
850 | write_client_reg(VSYNIF, 0x00000000, TRUE); | ||
851 | write_client_reg(ASY_DATA, 0x80000000, TRUE); | ||
852 | write_client_reg(ASY_DATB, 0x00000001, TRUE); | ||
853 | write_client_reg(ASY_CMDSET, 0x00000005, TRUE); | ||
854 | write_client_reg(ASY_CMDSET, 0x00000004, TRUE); | ||
855 | mddi_wait(10); | ||
856 | write_client_reg(ASY_DATA, 0x80000000, TRUE); | ||
857 | write_client_reg(ASY_DATB, 0x80000000, TRUE); | ||
858 | write_client_reg(ASY_DATC, 0x80000000, TRUE); | ||
859 | write_client_reg(ASY_DATD, 0x80000000, TRUE); | ||
860 | write_client_reg(ASY_CMDSET, 0x00000009, TRUE); | ||
861 | write_client_reg(ASY_CMDSET, 0x00000008, TRUE); | ||
862 | write_client_reg(ASY_DATA, 0x80000007, TRUE); | ||
863 | write_client_reg(ASY_DATB, 0x00004005, TRUE); | ||
864 | write_client_reg(ASY_CMDSET, 0x00000005, TRUE); | ||
865 | write_client_reg(ASY_CMDSET, 0x00000004, TRUE); | ||
866 | mddi_wait(20); | ||
867 | write_client_reg(ASY_DATA, 0x80000059, TRUE); | ||
868 | write_client_reg(ASY_DATB, 0x00000000, TRUE); | ||
869 | write_client_reg(ASY_CMDSET, 0x00000005, TRUE); | ||
870 | write_client_reg(ASY_CMDSET, 0x00000004, TRUE); | ||
871 | write_client_reg(VSYNIF, 0x00000001, TRUE); | ||
872 | write_client_reg(PORT_ENB, 0x00000001, TRUE); | ||
873 | } | ||
874 | |||
875 | mddi_toshiba_state_transition(TOSHIBA_STATE_PRIM_SEC_STANDBY, | ||
876 | TOSHIBA_STATE_PRIM_SEC_READY); | ||
877 | } | ||
878 | |||
879 | static void toshiba_prim_start(struct msm_fb_data_type *mfd) | ||
880 | { | ||
881 | if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT) | ||
882 | return; | ||
883 | |||
884 | if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA) { | ||
885 | write_client_reg(BITMAP1, 0x01E000F0, TRUE); | ||
886 | write_client_reg(BITMAP2, 0x01E000F0, TRUE); | ||
887 | write_client_reg(BITMAP3, 0x01E000F0, TRUE); | ||
888 | write_client_reg(BITMAP4, 0x00DC00B0, TRUE); | ||
889 | write_client_reg(CLKENB, 0x000001EF, TRUE); | ||
890 | write_client_reg(PORT_ENB, 0x00000001, TRUE); | ||
891 | write_client_reg(PORT, 0x00000016, TRUE); | ||
892 | write_client_reg(PXL, 0x00000002, TRUE); | ||
893 | write_client_reg(MPLFBUF, 0x00000000, TRUE); | ||
894 | write_client_reg(HCYCLE, 0x00000185, TRUE); | ||
895 | write_client_reg(HSW, 0x00000018, TRUE); | ||
896 | write_client_reg(HDE_START, 0x0000004A, TRUE); | ||
897 | write_client_reg(HDE_SIZE, 0x000000EF, TRUE); | ||
898 | write_client_reg(VCYCLE, 0x0000028E, TRUE); | ||
899 | write_client_reg(VSW, 0x00000004, TRUE); | ||
900 | write_client_reg(VDE_START, 0x00000009, TRUE); | ||
901 | write_client_reg(VDE_SIZE, 0x0000027F, TRUE); | ||
902 | write_client_reg(START, 0x00000001, TRUE); | ||
903 | write_client_reg(SYSTEM_BLOCK1_BASE, 0x00000002, TRUE); | ||
904 | } else{ | ||
905 | |||
906 | write_client_reg(VSYNIF, 0x00000001, TRUE); | ||
907 | write_client_reg(PORT_ENB, 0x00000001, TRUE); | ||
908 | write_client_reg(BITMAP1, 0x01E000F0, TRUE); | ||
909 | write_client_reg(BITMAP2, 0x01E000F0, TRUE); | ||
910 | write_client_reg(BITMAP3, 0x01E000F0, TRUE); | ||
911 | write_client_reg(BITMAP4, 0x00DC00B0, TRUE); | ||
912 | write_client_reg(CLKENB, 0x000001EF, TRUE); | ||
913 | write_client_reg(PORT_ENB, 0x00000001, TRUE); | ||
914 | write_client_reg(PORT, 0x00000004, TRUE); | ||
915 | write_client_reg(PXL, 0x00000002, TRUE); | ||
916 | write_client_reg(MPLFBUF, 0x00000000, TRUE); | ||
917 | |||
918 | if (mddi_toshiba_61Hz_refresh) { | ||
919 | write_client_reg(HCYCLE, 0x000000FC, TRUE); | ||
920 | mddi_toshiba_rows_per_second = 39526; | ||
921 | mddi_toshiba_rows_per_refresh = 646; | ||
922 | mddi_toshiba_usecs_per_refresh = 16344; | ||
923 | } else { | ||
924 | write_client_reg(HCYCLE, 0x0000010b, TRUE); | ||
925 | mddi_toshiba_rows_per_second = 37313; | ||
926 | mddi_toshiba_rows_per_refresh = 646; | ||
927 | mddi_toshiba_usecs_per_refresh = 17313; | ||
928 | } | ||
929 | |||
930 | write_client_reg(HSW, 0x00000003, TRUE); | ||
931 | write_client_reg(HDE_START, 0x00000007, TRUE); | ||
932 | write_client_reg(HDE_SIZE, 0x000000EF, TRUE); | ||
933 | write_client_reg(VCYCLE, 0x00000285, TRUE); | ||
934 | write_client_reg(VSW, 0x00000001, TRUE); | ||
935 | write_client_reg(VDE_START, 0x00000003, TRUE); | ||
936 | write_client_reg(VDE_SIZE, 0x0000027F, TRUE); | ||
937 | write_client_reg(START, 0x00000001, TRUE); | ||
938 | mddi_wait(10); | ||
939 | write_client_reg(SSITX, 0x000800BC, TRUE); | ||
940 | write_client_reg(SSITX, 0x00000180, TRUE); | ||
941 | write_client_reg(SSITX, 0x0008003B, TRUE); | ||
942 | write_client_reg(SSITX, 0x00000100, TRUE); | ||
943 | mddi_wait(1); | ||
944 | write_client_reg(SSITX, 0x000800B0, TRUE); | ||
945 | write_client_reg(SSITX, 0x00000116, TRUE); | ||
946 | mddi_wait(1); | ||
947 | write_client_reg(SSITX, 0x000800B8, TRUE); | ||
948 | write_client_reg(SSITX, 0x000801FF, TRUE); | ||
949 | write_client_reg(SSITX, 0x000001F5, TRUE); | ||
950 | mddi_wait(1); | ||
951 | write_client_reg(SSITX, 0x00000011, TRUE); | ||
952 | write_client_reg(SSITX, 0x00000029, TRUE); | ||
953 | write_client_reg(WKREQ, 0x00000000, TRUE); | ||
954 | write_client_reg(WAKEUP, 0x00000000, TRUE); | ||
955 | write_client_reg(INTMSK, 0x00000001, TRUE); | ||
956 | } | ||
957 | |||
958 | mddi_toshiba_state_transition(TOSHIBA_STATE_PRIM_SEC_READY, | ||
959 | TOSHIBA_STATE_PRIM_NORMAL_MODE); | ||
960 | } | ||
961 | |||
962 | static void toshiba_sec_start(struct msm_fb_data_type *mfd) | ||
963 | { | ||
964 | if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT) | ||
965 | return; | ||
966 | |||
967 | write_client_reg(VSYNIF, 0x00000000, TRUE); | ||
968 | write_client_reg(PORT_ENB, 0x00000002, TRUE); | ||
969 | write_client_reg(CLKENB, 0x000011EF, TRUE); | ||
970 | write_client_reg(BITMAP0, 0x028001E0, TRUE); | ||
971 | write_client_reg(BITMAP1, 0x00000000, TRUE); | ||
972 | write_client_reg(BITMAP2, 0x00000000, TRUE); | ||
973 | write_client_reg(BITMAP3, 0x00000000, TRUE); | ||
974 | write_client_reg(BITMAP4, 0x00DC00B0, TRUE); | ||
975 | write_client_reg(PORT, 0x00000000, TRUE); | ||
976 | write_client_reg(PXL, 0x00000000, TRUE); | ||
977 | write_client_reg(MPLFBUF, 0x00000004, TRUE); | ||
978 | write_client_reg(HCYCLE, 0x0000006B, TRUE); | ||
979 | write_client_reg(HSW, 0x00000003, TRUE); | ||
980 | write_client_reg(HDE_START, 0x00000007, TRUE); | ||
981 | write_client_reg(HDE_SIZE, 0x00000057, TRUE); | ||
982 | write_client_reg(VCYCLE, 0x000000E6, TRUE); | ||
983 | write_client_reg(VSW, 0x00000001, TRUE); | ||
984 | write_client_reg(VDE_START, 0x00000003, TRUE); | ||
985 | write_client_reg(VDE_SIZE, 0x000000DB, TRUE); | ||
986 | write_client_reg(ASY_DATA, 0x80000001, TRUE); | ||
987 | write_client_reg(ASY_DATB, 0x0000011B, TRUE); | ||
988 | write_client_reg(ASY_DATC, 0x80000002, TRUE); | ||
989 | write_client_reg(ASY_DATD, 0x00000700, TRUE); | ||
990 | write_client_reg(ASY_DATE, 0x80000003, TRUE); | ||
991 | write_client_reg(ASY_DATF, 0x00000230, TRUE); | ||
992 | write_client_reg(ASY_DATG, 0x80000008, TRUE); | ||
993 | write_client_reg(ASY_DATH, 0x00000402, TRUE); | ||
994 | write_client_reg(ASY_CMDSET, 0x00000001, TRUE); | ||
995 | write_client_reg(ASY_CMDSET, 0x00000000, TRUE); | ||
996 | write_client_reg(ASY_DATA, 0x80000009, TRUE); | ||
997 | write_client_reg(ASY_DATB, 0x00000000, TRUE); | ||
998 | write_client_reg(ASY_DATC, 0x8000000B, TRUE); | ||
999 | write_client_reg(ASY_DATD, 0x00000000, TRUE); | ||
1000 | write_client_reg(ASY_DATE, 0x8000000C, TRUE); | ||
1001 | write_client_reg(ASY_DATF, 0x00000000, TRUE); | ||
1002 | write_client_reg(ASY_DATG, 0x8000000D, TRUE); | ||
1003 | write_client_reg(ASY_DATH, 0x00000409, TRUE); | ||
1004 | write_client_reg(ASY_CMDSET, 0x00000001, TRUE); | ||
1005 | write_client_reg(ASY_CMDSET, 0x00000000, TRUE); | ||
1006 | write_client_reg(ASY_DATA, 0x8000000E, TRUE); | ||
1007 | write_client_reg(ASY_DATB, 0x00000409, TRUE); | ||
1008 | write_client_reg(ASY_DATC, 0x80000030, TRUE); | ||
1009 | write_client_reg(ASY_DATD, 0x00000000, TRUE); | ||
1010 | write_client_reg(ASY_DATE, 0x80000031, TRUE); | ||
1011 | write_client_reg(ASY_DATF, 0x00000100, TRUE); | ||
1012 | write_client_reg(ASY_DATG, 0x80000032, TRUE); | ||
1013 | write_client_reg(ASY_DATH, 0x00000104, TRUE); | ||
1014 | write_client_reg(ASY_CMDSET, 0x00000001, TRUE); | ||
1015 | write_client_reg(ASY_CMDSET, 0x00000000, TRUE); | ||
1016 | write_client_reg(ASY_DATA, 0x80000033, TRUE); | ||
1017 | write_client_reg(ASY_DATB, 0x00000400, TRUE); | ||
1018 | write_client_reg(ASY_DATC, 0x80000034, TRUE); | ||
1019 | write_client_reg(ASY_DATD, 0x00000306, TRUE); | ||
1020 | write_client_reg(ASY_DATE, 0x80000035, TRUE); | ||
1021 | write_client_reg(ASY_DATF, 0x00000706, TRUE); | ||
1022 | write_client_reg(ASY_DATG, 0x80000036, TRUE); | ||
1023 | write_client_reg(ASY_DATH, 0x00000707, TRUE); | ||
1024 | write_client_reg(ASY_CMDSET, 0x00000001, TRUE); | ||
1025 | write_client_reg(ASY_CMDSET, 0x00000000, TRUE); | ||
1026 | write_client_reg(ASY_DATA, 0x80000037, TRUE); | ||
1027 | write_client_reg(ASY_DATB, 0x00000004, TRUE); | ||
1028 | write_client_reg(ASY_DATC, 0x80000038, TRUE); | ||
1029 | write_client_reg(ASY_DATD, 0x00000000, TRUE); | ||
1030 | write_client_reg(ASY_DATE, 0x80000039, TRUE); | ||
1031 | write_client_reg(ASY_DATF, 0x00000000, TRUE); | ||
1032 | write_client_reg(ASY_DATG, 0x8000003A, TRUE); | ||
1033 | write_client_reg(ASY_DATH, 0x00000001, TRUE); | ||
1034 | write_client_reg(ASY_CMDSET, 0x00000001, TRUE); | ||
1035 | write_client_reg(ASY_CMDSET, 0x00000000, TRUE); | ||
1036 | write_client_reg(ASY_DATA, 0x80000044, TRUE); | ||
1037 | write_client_reg(ASY_DATB, 0x0000AF00, TRUE); | ||
1038 | write_client_reg(ASY_DATC, 0x80000045, TRUE); | ||
1039 | write_client_reg(ASY_DATD, 0x0000DB00, TRUE); | ||
1040 | write_client_reg(ASY_DATE, 0x08000042, TRUE); | ||
1041 | write_client_reg(ASY_DATF, 0x0000DB00, TRUE); | ||
1042 | write_client_reg(ASY_DATG, 0x80000021, TRUE); | ||
1043 | write_client_reg(ASY_DATH, 0x00000000, TRUE); | ||
1044 | write_client_reg(ASY_CMDSET, 0x00000001, TRUE); | ||
1045 | write_client_reg(ASY_CMDSET, 0x00000000, TRUE); | ||
1046 | write_client_reg(PXL, 0x0000000C, TRUE); | ||
1047 | write_client_reg(VSYNIF, 0x00000001, TRUE); | ||
1048 | write_client_reg(ASY_DATA, 0x80000022, TRUE); | ||
1049 | write_client_reg(ASY_CMDSET, 0x00000003, TRUE); | ||
1050 | write_client_reg(START, 0x00000001, TRUE); | ||
1051 | mddi_wait(60); | ||
1052 | write_client_reg(PXL, 0x00000000, TRUE); | ||
1053 | write_client_reg(VSYNIF, 0x00000000, TRUE); | ||
1054 | write_client_reg(START, 0x00000000, TRUE); | ||
1055 | write_client_reg(ASY_CMDSET, 0x00000000, TRUE); | ||
1056 | write_client_reg(ASY_DATA, 0x80000050, TRUE); | ||
1057 | write_client_reg(ASY_DATB, 0x00000000, TRUE); | ||
1058 | write_client_reg(ASY_DATC, 0x80000051, TRUE); | ||
1059 | write_client_reg(ASY_DATD, 0x00000E00, TRUE); | ||
1060 | write_client_reg(ASY_DATE, 0x80000052, TRUE); | ||
1061 | write_client_reg(ASY_DATF, 0x00000D01, TRUE); | ||
1062 | write_client_reg(ASY_DATG, 0x80000053, TRUE); | ||
1063 | write_client_reg(ASY_DATH, 0x00000000, TRUE); | ||
1064 | write_client_reg(ASY_CMDSET, 0x00000001, TRUE); | ||
1065 | write_client_reg(ASY_CMDSET, 0x00000000, TRUE); | ||
1066 | write_client_reg(ASY_DATA, 0x80000058, TRUE); | ||
1067 | write_client_reg(ASY_DATB, 0x00000000, TRUE); | ||
1068 | write_client_reg(ASY_DATC, 0x8000005A, TRUE); | ||
1069 | write_client_reg(ASY_DATD, 0x00000E01, TRUE); | ||
1070 | write_client_reg(ASY_CMDSET, 0x00000009, TRUE); | ||
1071 | write_client_reg(ASY_CMDSET, 0x00000008, TRUE); | ||
1072 | write_client_reg(ASY_DATA, 0x80000011, TRUE); | ||
1073 | write_client_reg(ASY_DATB, 0x00000812, TRUE); | ||
1074 | write_client_reg(ASY_DATC, 0x80000012, TRUE); | ||
1075 | write_client_reg(ASY_DATD, 0x00000003, TRUE); | ||
1076 | write_client_reg(ASY_DATE, 0x80000013, TRUE); | ||
1077 | write_client_reg(ASY_DATF, 0x00000909, TRUE); | ||
1078 | write_client_reg(ASY_DATG, 0x80000010, TRUE); | ||
1079 | write_client_reg(ASY_DATH, 0x00000040, TRUE); | ||
1080 | write_client_reg(ASY_CMDSET, 0x00000001, TRUE); | ||
1081 | write_client_reg(ASY_CMDSET, 0x00000000, TRUE); | ||
1082 | mddi_wait(40); | ||
1083 | write_client_reg(ASY_DATA, 0x80000010, TRUE); | ||
1084 | write_client_reg(ASY_DATB, 0x00000340, TRUE); | ||
1085 | write_client_reg(ASY_CMDSET, 0x00000005, TRUE); | ||
1086 | write_client_reg(ASY_CMDSET, 0x00000004, TRUE); | ||
1087 | mddi_wait(60); | ||
1088 | write_client_reg(ASY_DATA, 0x80000010, TRUE); | ||
1089 | write_client_reg(ASY_DATB, 0x00003340, TRUE); | ||
1090 | write_client_reg(ASY_DATC, 0x80000007, TRUE); | ||
1091 | write_client_reg(ASY_DATD, 0x00004007, TRUE); | ||
1092 | write_client_reg(ASY_CMDSET, 0x00000009, TRUE); | ||
1093 | write_client_reg(ASY_CMDSET, 0x00000008, TRUE); | ||
1094 | mddi_wait(1); | ||
1095 | write_client_reg(ASY_DATA, 0x80000007, TRUE); | ||
1096 | write_client_reg(ASY_DATB, 0x00004017, TRUE); | ||
1097 | write_client_reg(ASY_DATC, 0x8000005B, TRUE); | ||
1098 | write_client_reg(ASY_DATD, 0x00000000, TRUE); | ||
1099 | write_client_reg(ASY_DATE, 0x80000059, TRUE); | ||
1100 | write_client_reg(ASY_DATF, 0x00000011, TRUE); | ||
1101 | write_client_reg(ASY_CMDSET, 0x0000000D, TRUE); | ||
1102 | write_client_reg(ASY_CMDSET, 0x0000000C, TRUE); | ||
1103 | mddi_wait(20); | ||
1104 | write_client_reg(ASY_DATA, 0x80000059, TRUE); | ||
1105 | /* LTPS I/F control */ | ||
1106 | write_client_reg(ASY_DATB, 0x00000019, TRUE); | ||
1107 | /* Direct cmd transfer enable */ | ||
1108 | write_client_reg(ASY_CMDSET, 0x00000005, TRUE); | ||
1109 | /* Direct cmd transfer disable */ | ||
1110 | write_client_reg(ASY_CMDSET, 0x00000004, TRUE); | ||
1111 | mddi_wait(20); | ||
1112 | /* Index setting of SUB LCDD */ | ||
1113 | write_client_reg(ASY_DATA, 0x80000059, TRUE); | ||
1114 | /* LTPS I/F control */ | ||
1115 | write_client_reg(ASY_DATB, 0x00000079, TRUE); | ||
1116 | /* Direct cmd transfer enable */ | ||
1117 | write_client_reg(ASY_CMDSET, 0x00000005, TRUE); | ||
1118 | /* Direct cmd transfer disable */ | ||
1119 | write_client_reg(ASY_CMDSET, 0x00000004, TRUE); | ||
1120 | mddi_wait(20); | ||
1121 | /* Index setting of SUB LCDD */ | ||
1122 | write_client_reg(ASY_DATA, 0x80000059, TRUE); | ||
1123 | /* LTPS I/F control */ | ||
1124 | write_client_reg(ASY_DATB, 0x000003FD, TRUE); | ||
1125 | /* Direct cmd transfer enable */ | ||
1126 | write_client_reg(ASY_CMDSET, 0x00000005, TRUE); | ||
1127 | /* Direct cmd transfer disable */ | ||
1128 | write_client_reg(ASY_CMDSET, 0x00000004, TRUE); | ||
1129 | mddi_wait(20); | ||
1130 | mddi_toshiba_state_transition(TOSHIBA_STATE_PRIM_SEC_READY, | ||
1131 | TOSHIBA_STATE_SEC_NORMAL_MODE); | ||
1132 | } | ||
1133 | |||
1134 | static void toshiba_prim_lcd_off(struct msm_fb_data_type *mfd) | ||
1135 | { | ||
1136 | if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA) { | ||
1137 | gordon_disp_off(); | ||
1138 | } else{ | ||
1139 | |||
1140 | /* Main panel power off (Deep standby in) */ | ||
1141 | write_client_reg(SSITX, 0x000800BC, TRUE); | ||
1142 | write_client_reg(SSITX, 0x00000100, TRUE); | ||
1143 | write_client_reg(SSITX, 0x00000028, TRUE); | ||
1144 | mddi_wait(1); | ||
1145 | write_client_reg(SSITX, 0x000800B8, TRUE); | ||
1146 | write_client_reg(SSITX, 0x00000180, TRUE); | ||
1147 | write_client_reg(SSITX, 0x00000102, TRUE); | ||
1148 | write_client_reg(SSITX, 0x00000010, TRUE); | ||
1149 | } | ||
1150 | write_client_reg(PORT, 0x00000003, TRUE); | ||
1151 | write_client_reg(REGENB, 0x00000001, TRUE); | ||
1152 | mddi_wait(1); | ||
1153 | write_client_reg(PXL, 0x00000000, TRUE); | ||
1154 | write_client_reg(START, 0x00000000, TRUE); | ||
1155 | write_client_reg(REGENB, 0x00000001, TRUE); | ||
1156 | mddi_wait(3); | ||
1157 | if (TM_GET_PID(mfd->panel.id) != LCD_SHARP_2P4_VGA) { | ||
1158 | write_client_reg(SSITX, 0x000800B0, TRUE); | ||
1159 | write_client_reg(SSITX, 0x00000100, TRUE); | ||
1160 | } | ||
1161 | mddi_toshiba_state_transition(TOSHIBA_STATE_PRIM_NORMAL_MODE, | ||
1162 | TOSHIBA_STATE_PRIM_SEC_STANDBY); | ||
1163 | } | ||
1164 | |||
1165 | static void toshiba_sec_lcd_off(struct msm_fb_data_type *mfd) | ||
1166 | { | ||
1167 | if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT) | ||
1168 | return; | ||
1169 | |||
1170 | write_client_reg(VSYNIF, 0x00000000, TRUE); | ||
1171 | write_client_reg(PORT_ENB, 0x00000002, TRUE); | ||
1172 | write_client_reg(ASY_DATA, 0x80000007, TRUE); | ||
1173 | write_client_reg(ASY_DATB, 0x00004016, TRUE); | ||
1174 | write_client_reg(ASY_CMDSET, 0x00000005, TRUE); | ||
1175 | write_client_reg(ASY_CMDSET, 0x00000004, TRUE); | ||
1176 | mddi_wait(2); | ||
1177 | write_client_reg(ASY_DATA, 0x80000059, TRUE); | ||
1178 | write_client_reg(ASY_DATB, 0x00000019, TRUE); | ||
1179 | write_client_reg(ASY_CMDSET, 0x00000005, TRUE); | ||
1180 | write_client_reg(ASY_CMDSET, 0x00000004, TRUE); | ||
1181 | mddi_wait(2); | ||
1182 | write_client_reg(ASY_DATA, 0x80000059, TRUE); | ||
1183 | write_client_reg(ASY_DATB, 0x0000000B, TRUE); | ||
1184 | write_client_reg(ASY_CMDSET, 0x00000005, TRUE); | ||
1185 | write_client_reg(ASY_CMDSET, 0x00000004, TRUE); | ||
1186 | mddi_wait(2); | ||
1187 | write_client_reg(ASY_DATA, 0x80000059, TRUE); | ||
1188 | write_client_reg(ASY_DATB, 0x00000002, TRUE); | ||
1189 | write_client_reg(ASY_CMDSET, 0x00000005, TRUE); | ||
1190 | write_client_reg(ASY_CMDSET, 0x00000004, TRUE); | ||
1191 | mddi_wait(4); | ||
1192 | write_client_reg(ASY_DATA, 0x80000010, TRUE); | ||
1193 | write_client_reg(ASY_DATB, 0x00000300, TRUE); | ||
1194 | write_client_reg(ASY_CMDSET, 0x00000005, TRUE); | ||
1195 | write_client_reg(ASY_CMDSET, 0x00000004, TRUE); | ||
1196 | mddi_wait(4); | ||
1197 | write_client_reg(ASY_DATA, 0x80000059, TRUE); | ||
1198 | write_client_reg(ASY_DATB, 0x00000000, TRUE); | ||
1199 | write_client_reg(ASY_CMDSET, 0x00000005, TRUE); | ||
1200 | write_client_reg(ASY_CMDSET, 0x00000004, TRUE); | ||
1201 | mddi_wait(2); | ||
1202 | write_client_reg(ASY_DATA, 0x80000007, TRUE); | ||
1203 | write_client_reg(ASY_DATB, 0x00004004, TRUE); | ||
1204 | write_client_reg(ASY_CMDSET, 0x00000005, TRUE); | ||
1205 | write_client_reg(ASY_CMDSET, 0x00000004, TRUE); | ||
1206 | mddi_wait(2); | ||
1207 | write_client_reg(PORT, 0x00000000, TRUE); | ||
1208 | write_client_reg(PXL, 0x00000000, TRUE); | ||
1209 | write_client_reg(START, 0x00000000, TRUE); | ||
1210 | write_client_reg(VSYNIF, 0x00000001, TRUE); | ||
1211 | write_client_reg(PORT_ENB, 0x00000001, TRUE); | ||
1212 | write_client_reg(REGENB, 0x00000001, TRUE); | ||
1213 | mddi_toshiba_state_transition(TOSHIBA_STATE_SEC_NORMAL_MODE, | ||
1214 | TOSHIBA_STATE_PRIM_SEC_STANDBY); | ||
1215 | } | ||
1216 | |||
1217 | static void toshiba_sec_cont_update_start(struct msm_fb_data_type *mfd) | ||
1218 | { | ||
1219 | |||
1220 | if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT) | ||
1221 | return; | ||
1222 | |||
1223 | write_client_reg(VSYNIF, 0x00000000, TRUE); | ||
1224 | write_client_reg(PORT_ENB, 0x00000002, TRUE); | ||
1225 | write_client_reg(INTMASK, 0x00000001, TRUE); | ||
1226 | write_client_reg(TTBUSSEL, 0x0000000B, TRUE); | ||
1227 | write_client_reg(MONI, 0x00000008, TRUE); | ||
1228 | write_client_reg(CLKENB, 0x000000EF, TRUE); | ||
1229 | write_client_reg(CLKENB, 0x000010EF, TRUE); | ||
1230 | write_client_reg(CLKENB, 0x000011EF, TRUE); | ||
1231 | write_client_reg(BITMAP4, 0x00DC00B0, TRUE); | ||
1232 | write_client_reg(HCYCLE, 0x0000006B, TRUE); | ||
1233 | write_client_reg(HSW, 0x00000003, TRUE); | ||
1234 | write_client_reg(HDE_START, 0x00000002, TRUE); | ||
1235 | write_client_reg(HDE_SIZE, 0x00000057, TRUE); | ||
1236 | write_client_reg(VCYCLE, 0x000000E6, TRUE); | ||
1237 | write_client_reg(VSW, 0x00000001, TRUE); | ||
1238 | write_client_reg(VDE_START, 0x00000003, TRUE); | ||
1239 | write_client_reg(VDE_SIZE, 0x000000DB, TRUE); | ||
1240 | write_client_reg(WRSTB, 0x00000015, TRUE); | ||
1241 | write_client_reg(MPLFBUF, 0x00000004, TRUE); | ||
1242 | write_client_reg(ASY_DATA, 0x80000021, TRUE); | ||
1243 | write_client_reg(ASY_DATB, 0x00000000, TRUE); | ||
1244 | write_client_reg(ASY_DATC, 0x80000022, TRUE); | ||
1245 | write_client_reg(ASY_CMDSET, 0x00000007, TRUE); | ||
1246 | write_client_reg(PXL, 0x00000089, TRUE); | ||
1247 | write_client_reg(VSYNIF, 0x00000001, TRUE); | ||
1248 | mddi_wait(2); | ||
1249 | } | ||
1250 | |||
1251 | static void toshiba_sec_cont_update_stop(struct msm_fb_data_type *mfd) | ||
1252 | { | ||
1253 | if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT) | ||
1254 | return; | ||
1255 | |||
1256 | write_client_reg(PXL, 0x00000000, TRUE); | ||
1257 | write_client_reg(VSYNIF, 0x00000000, TRUE); | ||
1258 | write_client_reg(START, 0x00000000, TRUE); | ||
1259 | write_client_reg(ASY_CMDSET, 0x00000000, TRUE); | ||
1260 | mddi_wait(3); | ||
1261 | write_client_reg(SRST, 0x00000002, TRUE); | ||
1262 | mddi_wait(3); | ||
1263 | write_client_reg(SRST, 0x00000003, TRUE); | ||
1264 | } | ||
1265 | |||
1266 | static void toshiba_sec_backlight_on(struct msm_fb_data_type *mfd) | ||
1267 | { | ||
1268 | if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT) | ||
1269 | return; | ||
1270 | |||
1271 | write_client_reg(TIMER0CTRL, 0x00000060, TRUE); | ||
1272 | write_client_reg(TIMER0LOAD, 0x00001388, TRUE); | ||
1273 | write_client_reg(PWM0OFF, 0x00000001, TRUE); | ||
1274 | write_client_reg(TIMER1CTRL, 0x00000060, TRUE); | ||
1275 | write_client_reg(TIMER1LOAD, 0x00001388, TRUE); | ||
1276 | write_client_reg(PWM1OFF, 0x00001387, TRUE); | ||
1277 | write_client_reg(TIMER0CTRL, 0x000000E0, TRUE); | ||
1278 | write_client_reg(TIMER1CTRL, 0x000000E0, TRUE); | ||
1279 | write_client_reg(PWMCR, 0x00000003, TRUE); | ||
1280 | } | ||
1281 | |||
1282 | static void toshiba_sec_sleep_in(struct msm_fb_data_type *mfd) | ||
1283 | { | ||
1284 | if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT) | ||
1285 | return; | ||
1286 | |||
1287 | write_client_reg(VSYNIF, 0x00000000, TRUE); | ||
1288 | write_client_reg(PORT_ENB, 0x00000002, TRUE); | ||
1289 | write_client_reg(ASY_DATA, 0x80000007, TRUE); | ||
1290 | write_client_reg(ASY_DATB, 0x00004016, TRUE); | ||
1291 | write_client_reg(ASY_CMDSET, 0x00000005, TRUE); | ||
1292 | write_client_reg(ASY_CMDSET, 0x00000004, TRUE); | ||
1293 | mddi_wait(2); | ||
1294 | write_client_reg(ASY_DATA, 0x80000059, TRUE); | ||
1295 | write_client_reg(ASY_DATB, 0x00000019, TRUE); | ||
1296 | write_client_reg(ASY_CMDSET, 0x00000005, TRUE); | ||
1297 | write_client_reg(ASY_CMDSET, 0x00000004, TRUE); | ||
1298 | mddi_wait(2); | ||
1299 | write_client_reg(ASY_DATA, 0x80000059, TRUE); | ||
1300 | write_client_reg(ASY_DATB, 0x0000000B, TRUE); | ||
1301 | write_client_reg(ASY_CMDSET, 0x00000005, TRUE); | ||
1302 | write_client_reg(ASY_CMDSET, 0x00000004, TRUE); | ||
1303 | mddi_wait(2); | ||
1304 | write_client_reg(ASY_DATA, 0x80000059, TRUE); | ||
1305 | write_client_reg(ASY_DATB, 0x00000002, TRUE); | ||
1306 | write_client_reg(ASY_CMDSET, 0x00000005, TRUE); | ||
1307 | write_client_reg(ASY_CMDSET, 0x00000004, TRUE); | ||
1308 | mddi_wait(4); | ||
1309 | write_client_reg(ASY_DATA, 0x80000010, TRUE); | ||
1310 | write_client_reg(ASY_DATB, 0x00000300, TRUE); | ||
1311 | write_client_reg(ASY_CMDSET, 0x00000005, TRUE); | ||
1312 | write_client_reg(ASY_CMDSET, 0x00000004, TRUE); | ||
1313 | mddi_wait(4); | ||
1314 | write_client_reg(ASY_DATA, 0x80000059, TRUE); | ||
1315 | write_client_reg(ASY_DATB, 0x00000000, TRUE); | ||
1316 | write_client_reg(ASY_CMDSET, 0x00000005, TRUE); | ||
1317 | write_client_reg(ASY_CMDSET, 0x00000004, TRUE); | ||
1318 | mddi_wait(2); | ||
1319 | write_client_reg(ASY_DATA, 0x80000007, TRUE); | ||
1320 | write_client_reg(ASY_DATB, 0x00004004, TRUE); | ||
1321 | write_client_reg(ASY_CMDSET, 0x00000005, TRUE); | ||
1322 | write_client_reg(ASY_CMDSET, 0x00000004, TRUE); | ||
1323 | mddi_wait(2); | ||
1324 | write_client_reg(PORT, 0x00000000, TRUE); | ||
1325 | write_client_reg(PXL, 0x00000000, TRUE); | ||
1326 | write_client_reg(START, 0x00000000, TRUE); | ||
1327 | write_client_reg(REGENB, 0x00000001, TRUE); | ||
1328 | /* Sleep in sequence */ | ||
1329 | write_client_reg(ASY_DATA, 0x80000010, TRUE); | ||
1330 | write_client_reg(ASY_DATB, 0x00000302, TRUE); | ||
1331 | write_client_reg(ASY_CMDSET, 0x00000005, TRUE); | ||
1332 | write_client_reg(ASY_CMDSET, 0x00000004, TRUE); | ||
1333 | } | ||
1334 | |||
1335 | static void toshiba_sec_sleep_out(struct msm_fb_data_type *mfd) | ||
1336 | { | ||
1337 | if (TM_GET_PID(mfd->panel.id) == LCD_TOSHIBA_2P4_WVGA_PT) | ||
1338 | return; | ||
1339 | |||
1340 | write_client_reg(VSYNIF, 0x00000000, TRUE); | ||
1341 | write_client_reg(PORT_ENB, 0x00000002, TRUE); | ||
1342 | write_client_reg(ASY_DATA, 0x80000010, TRUE); | ||
1343 | write_client_reg(ASY_DATB, 0x00000300, TRUE); | ||
1344 | write_client_reg(ASY_CMDSET, 0x00000005, TRUE); | ||
1345 | write_client_reg(ASY_CMDSET, 0x00000004, TRUE); | ||
1346 | /* Display ON sequence */ | ||
1347 | write_client_reg(ASY_DATA, 0x80000011, TRUE); | ||
1348 | write_client_reg(ASY_DATB, 0x00000812, TRUE); | ||
1349 | write_client_reg(ASY_DATC, 0x80000012, TRUE); | ||
1350 | write_client_reg(ASY_DATD, 0x00000003, TRUE); | ||
1351 | write_client_reg(ASY_DATE, 0x80000013, TRUE); | ||
1352 | write_client_reg(ASY_DATF, 0x00000909, TRUE); | ||
1353 | write_client_reg(ASY_DATG, 0x80000010, TRUE); | ||
1354 | write_client_reg(ASY_DATH, 0x00000040, TRUE); | ||
1355 | write_client_reg(ASY_CMDSET, 0x00000001, TRUE); | ||
1356 | write_client_reg(ASY_CMDSET, 0x00000000, TRUE); | ||
1357 | mddi_wait(4); | ||
1358 | write_client_reg(ASY_DATA, 0x80000010, TRUE); | ||
1359 | write_client_reg(ASY_DATB, 0x00000340, TRUE); | ||
1360 | write_client_reg(ASY_CMDSET, 0x00000005, TRUE); | ||
1361 | write_client_reg(ASY_CMDSET, 0x00000004, TRUE); | ||
1362 | mddi_wait(6); | ||
1363 | write_client_reg(ASY_DATA, 0x80000010, TRUE); | ||
1364 | write_client_reg(ASY_DATB, 0x00003340, TRUE); | ||
1365 | write_client_reg(ASY_DATC, 0x80000007, TRUE); | ||
1366 | write_client_reg(ASY_DATD, 0x00004007, TRUE); | ||
1367 | write_client_reg(ASY_CMDSET, 0x00000009, TRUE); | ||
1368 | write_client_reg(ASY_CMDSET, 0x00000008, TRUE); | ||
1369 | mddi_wait(1); | ||
1370 | write_client_reg(ASY_DATA, 0x80000007, TRUE); | ||
1371 | write_client_reg(ASY_DATB, 0x00004017, TRUE); | ||
1372 | write_client_reg(ASY_DATC, 0x8000005B, TRUE); | ||
1373 | write_client_reg(ASY_DATD, 0x00000000, TRUE); | ||
1374 | write_client_reg(ASY_DATE, 0x80000059, TRUE); | ||
1375 | write_client_reg(ASY_DATF, 0x00000011, TRUE); | ||
1376 | write_client_reg(ASY_CMDSET, 0x0000000D, TRUE); | ||
1377 | write_client_reg(ASY_CMDSET, 0x0000000C, TRUE); | ||
1378 | mddi_wait(2); | ||
1379 | write_client_reg(ASY_DATA, 0x80000059, TRUE); | ||
1380 | write_client_reg(ASY_DATB, 0x00000019, TRUE); | ||
1381 | write_client_reg(ASY_CMDSET, 0x00000005, TRUE); | ||
1382 | write_client_reg(ASY_CMDSET, 0x00000004, TRUE); | ||
1383 | mddi_wait(2); | ||
1384 | write_client_reg(ASY_DATA, 0x80000059, TRUE); | ||
1385 | write_client_reg(ASY_DATB, 0x00000079, TRUE); | ||
1386 | write_client_reg(ASY_CMDSET, 0x00000005, TRUE); | ||
1387 | write_client_reg(ASY_CMDSET, 0x00000004, TRUE); | ||
1388 | mddi_wait(2); | ||
1389 | write_client_reg(ASY_DATA, 0x80000059, TRUE); | ||
1390 | write_client_reg(ASY_DATB, 0x000003FD, TRUE); | ||
1391 | write_client_reg(ASY_CMDSET, 0x00000005, TRUE); | ||
1392 | write_client_reg(ASY_CMDSET, 0x00000004, TRUE); | ||
1393 | mddi_wait(2); | ||
1394 | } | ||
1395 | |||
1396 | static void mddi_toshiba_lcd_set_backlight(struct msm_fb_data_type *mfd) | ||
1397 | { | ||
1398 | int32 level; | ||
1399 | int ret = -EPERM; | ||
1400 | int max = mfd->panel_info.bl_max; | ||
1401 | int min = mfd->panel_info.bl_min; | ||
1402 | |||
1403 | if (mddi_toshiba_pdata && mddi_toshiba_pdata->pmic_backlight) { | ||
1404 | ret = mddi_toshiba_pdata->pmic_backlight(mfd->bl_level); | ||
1405 | if (!ret) | ||
1406 | return; | ||
1407 | } | ||
1408 | |||
1409 | if (ret && mddi_toshiba_pdata && mddi_toshiba_pdata->backlight_level) { | ||
1410 | level = mddi_toshiba_pdata->backlight_level(mfd->bl_level, | ||
1411 | max, min); | ||
1412 | |||
1413 | if (level < 0) | ||
1414 | return; | ||
1415 | |||
1416 | if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA) | ||
1417 | write_client_reg(TIMER0LOAD, 0x00001388, TRUE); | ||
1418 | } else { | ||
1419 | if (!max) | ||
1420 | level = 0; | ||
1421 | else | ||
1422 | level = (mfd->bl_level * 4999) / max; | ||
1423 | } | ||
1424 | |||
1425 | write_client_reg(PWM0OFF, level, TRUE); | ||
1426 | } | ||
1427 | |||
1428 | static void mddi_toshiba_vsync_set_handler(msm_fb_vsync_handler_type handler, /* ISR to be executed */ | ||
1429 | void *arg) | ||
1430 | { | ||
1431 | boolean error = FALSE; | ||
1432 | unsigned long flags; | ||
1433 | |||
1434 | /* Disable interrupts */ | ||
1435 | spin_lock_irqsave(&mddi_host_spin_lock, flags); | ||
1436 | /* INTLOCK(); */ | ||
1437 | |||
1438 | if (mddi_toshiba_vsync_handler != NULL) { | ||
1439 | error = TRUE; | ||
1440 | } else { | ||
1441 | /* Register the handler for this particular GROUP interrupt source */ | ||
1442 | mddi_toshiba_vsync_handler = handler; | ||
1443 | mddi_toshiba_vsync_handler_arg = arg; | ||
1444 | } | ||
1445 | |||
1446 | /* Restore interrupts */ | ||
1447 | spin_unlock_irqrestore(&mddi_host_spin_lock, flags); | ||
1448 | /* MDDI_INTFREE(); */ | ||
1449 | if (error) { | ||
1450 | MDDI_MSG_ERR("MDDI: Previous Vsync handler never called\n"); | ||
1451 | } else { | ||
1452 | /* Enable the vsync wakeup */ | ||
1453 | mddi_queue_register_write(INTMSK, 0x0000, FALSE, 0); | ||
1454 | |||
1455 | mddi_toshiba_vsync_attempts = 1; | ||
1456 | mddi_vsync_detect_enabled = TRUE; | ||
1457 | } | ||
1458 | } /* mddi_toshiba_vsync_set_handler */ | ||
1459 | |||
1460 | static void mddi_toshiba_lcd_vsync_detected(boolean detected) | ||
1461 | { | ||
1462 | /* static timetick_type start_time = 0; */ | ||
1463 | static struct timeval start_time; | ||
1464 | static boolean first_time = TRUE; | ||
1465 | /* uint32 mdp_cnt_val = 0; */ | ||
1466 | /* timetick_type elapsed_us; */ | ||
1467 | struct timeval now; | ||
1468 | uint32 elapsed_us; | ||
1469 | uint32 num_vsyncs; | ||
1470 | |||
1471 | if ((detected) || (mddi_toshiba_vsync_attempts > 5)) { | ||
1472 | if ((detected) && (mddi_toshiba_monitor_refresh_value)) { | ||
1473 | /* if (start_time != 0) */ | ||
1474 | if (!first_time) { | ||
1475 | jiffies_to_timeval(jiffies, &now); | ||
1476 | elapsed_us = | ||
1477 | (now.tv_sec - start_time.tv_sec) * 1000000 + | ||
1478 | now.tv_usec - start_time.tv_usec; | ||
1479 | /* | ||
1480 | * LCD is configured for a refresh every usecs, | ||
1481 | * so to determine the number of vsyncs that | ||
1482 | * have occurred since the last measurement | ||
1483 | * add half that to the time difference and | ||
1484 | * divide by the refresh rate. | ||
1485 | */ | ||
1486 | num_vsyncs = (elapsed_us + | ||
1487 | (mddi_toshiba_usecs_per_refresh >> | ||
1488 | 1)) / | ||
1489 | mddi_toshiba_usecs_per_refresh; | ||
1490 | /* | ||
1491 | * LCD is configured for * hsyncs (rows) per | ||
1492 | * refresh cycle. Calculate new rows_per_second | ||
1493 | * value based upon these new measurements. | ||
1494 | * MDP can update with this new value. | ||
1495 | */ | ||
1496 | mddi_toshiba_rows_per_second = | ||
1497 | (mddi_toshiba_rows_per_refresh * 1000 * | ||
1498 | num_vsyncs) / (elapsed_us / 1000); | ||
1499 | } | ||
1500 | /* start_time = timetick_get(); */ | ||
1501 | first_time = FALSE; | ||
1502 | jiffies_to_timeval(jiffies, &start_time); | ||
1503 | if (mddi_toshiba_report_refresh_measurements) { | ||
1504 | (void)mddi_queue_register_read_int(VPOS, | ||
1505 | &mddi_toshiba_curr_vpos); | ||
1506 | /* mdp_cnt_val = MDP_LINE_COUNT; */ | ||
1507 | } | ||
1508 | } | ||
1509 | /* if detected = TRUE, client initiated wakeup was detected */ | ||
1510 | if (mddi_toshiba_vsync_handler != NULL) { | ||
1511 | (*mddi_toshiba_vsync_handler) | ||
1512 | (mddi_toshiba_vsync_handler_arg); | ||
1513 | mddi_toshiba_vsync_handler = NULL; | ||
1514 | } | ||
1515 | mddi_vsync_detect_enabled = FALSE; | ||
1516 | mddi_toshiba_vsync_attempts = 0; | ||
1517 | /* need to disable the interrupt wakeup */ | ||
1518 | if (!mddi_queue_register_write_int(INTMSK, 0x0001)) | ||
1519 | MDDI_MSG_ERR("Vsync interrupt disable failed!\n"); | ||
1520 | if (!detected) { | ||
1521 | /* give up after 5 failed attempts but show error */ | ||
1522 | MDDI_MSG_NOTICE("Vsync detection failed!\n"); | ||
1523 | } else if ((mddi_toshiba_monitor_refresh_value) && | ||
1524 | (mddi_toshiba_report_refresh_measurements)) { | ||
1525 | MDDI_MSG_NOTICE(" Last Line Counter=%d!\n", | ||
1526 | mddi_toshiba_curr_vpos); | ||
1527 | /* MDDI_MSG_NOTICE(" MDP Line Counter=%d!\n",mdp_cnt_val); */ | ||
1528 | MDDI_MSG_NOTICE(" Lines Per Second=%d!\n", | ||
1529 | mddi_toshiba_rows_per_second); | ||
1530 | } | ||
1531 | /* clear the interrupt */ | ||
1532 | if (!mddi_queue_register_write_int(INTFLG, 0x0001)) | ||
1533 | MDDI_MSG_ERR("Vsync interrupt clear failed!\n"); | ||
1534 | } else { | ||
1535 | /* if detected = FALSE, we woke up from hibernation, but did not | ||
1536 | * detect client initiated wakeup. | ||
1537 | */ | ||
1538 | mddi_toshiba_vsync_attempts++; | ||
1539 | } | ||
1540 | } | ||
1541 | |||
1542 | static void mddi_toshiba_prim_init(struct msm_fb_data_type *mfd) | ||
1543 | { | ||
1544 | |||
1545 | switch (toshiba_state) { | ||
1546 | case TOSHIBA_STATE_PRIM_SEC_READY: | ||
1547 | break; | ||
1548 | case TOSHIBA_STATE_OFF: | ||
1549 | toshiba_state = TOSHIBA_STATE_PRIM_SEC_STANDBY; | ||
1550 | toshiba_common_initial_setup(mfd); | ||
1551 | break; | ||
1552 | case TOSHIBA_STATE_PRIM_SEC_STANDBY: | ||
1553 | toshiba_common_initial_setup(mfd); | ||
1554 | break; | ||
1555 | case TOSHIBA_STATE_SEC_NORMAL_MODE: | ||
1556 | toshiba_sec_cont_update_stop(mfd); | ||
1557 | toshiba_sec_sleep_in(mfd); | ||
1558 | toshiba_sec_sleep_out(mfd); | ||
1559 | toshiba_sec_lcd_off(mfd); | ||
1560 | toshiba_common_initial_setup(mfd); | ||
1561 | break; | ||
1562 | default: | ||
1563 | MDDI_MSG_ERR("mddi_toshiba_prim_init from state %d\n", | ||
1564 | toshiba_state); | ||
1565 | } | ||
1566 | |||
1567 | toshiba_prim_start(mfd); | ||
1568 | if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA) | ||
1569 | gordon_disp_init(); | ||
1570 | mddi_host_write_pix_attr_reg(0x00C3); | ||
1571 | } | ||
1572 | |||
1573 | static void mddi_toshiba_sec_init(struct msm_fb_data_type *mfd) | ||
1574 | { | ||
1575 | |||
1576 | switch (toshiba_state) { | ||
1577 | case TOSHIBA_STATE_PRIM_SEC_READY: | ||
1578 | break; | ||
1579 | case TOSHIBA_STATE_PRIM_SEC_STANDBY: | ||
1580 | toshiba_common_initial_setup(mfd); | ||
1581 | break; | ||
1582 | case TOSHIBA_STATE_PRIM_NORMAL_MODE: | ||
1583 | toshiba_prim_lcd_off(mfd); | ||
1584 | toshiba_common_initial_setup(mfd); | ||
1585 | break; | ||
1586 | default: | ||
1587 | MDDI_MSG_ERR("mddi_toshiba_sec_init from state %d\n", | ||
1588 | toshiba_state); | ||
1589 | } | ||
1590 | |||
1591 | toshiba_sec_start(mfd); | ||
1592 | toshiba_sec_backlight_on(mfd); | ||
1593 | toshiba_sec_cont_update_start(mfd); | ||
1594 | mddi_host_write_pix_attr_reg(0x0400); | ||
1595 | } | ||
1596 | |||
1597 | static void mddi_toshiba_lcd_powerdown(struct msm_fb_data_type *mfd) | ||
1598 | { | ||
1599 | switch (toshiba_state) { | ||
1600 | case TOSHIBA_STATE_PRIM_SEC_READY: | ||
1601 | mddi_toshiba_prim_init(mfd); | ||
1602 | mddi_toshiba_lcd_powerdown(mfd); | ||
1603 | return; | ||
1604 | case TOSHIBA_STATE_PRIM_SEC_STANDBY: | ||
1605 | break; | ||
1606 | case TOSHIBA_STATE_PRIM_NORMAL_MODE: | ||
1607 | toshiba_prim_lcd_off(mfd); | ||
1608 | break; | ||
1609 | case TOSHIBA_STATE_SEC_NORMAL_MODE: | ||
1610 | toshiba_sec_cont_update_stop(mfd); | ||
1611 | toshiba_sec_sleep_in(mfd); | ||
1612 | toshiba_sec_sleep_out(mfd); | ||
1613 | toshiba_sec_lcd_off(mfd); | ||
1614 | break; | ||
1615 | default: | ||
1616 | MDDI_MSG_ERR("mddi_toshiba_lcd_powerdown from state %d\n", | ||
1617 | toshiba_state); | ||
1618 | } | ||
1619 | } | ||
1620 | |||
1621 | static int mddi_sharpgordon_firsttime = 1; | ||
1622 | |||
1623 | static int mddi_toshiba_lcd_on(struct platform_device *pdev) | ||
1624 | { | ||
1625 | struct msm_fb_data_type *mfd; | ||
1626 | mfd = platform_get_drvdata(pdev); | ||
1627 | if (!mfd) | ||
1628 | return -ENODEV; | ||
1629 | if (mfd->key != MFD_KEY) | ||
1630 | return -EINVAL; | ||
1631 | |||
1632 | if (TM_GET_DID(mfd->panel.id) == TOSHIBA_VGA_PRIM) | ||
1633 | mddi_toshiba_prim_init(mfd); | ||
1634 | else | ||
1635 | mddi_toshiba_sec_init(mfd); | ||
1636 | if (TM_GET_PID(mfd->panel.id) == LCD_SHARP_2P4_VGA) { | ||
1637 | if (mddi_sharpgordon_firsttime) { | ||
1638 | mddi_sharpgordon_firsttime = 0; | ||
1639 | write_client_reg(REGENB, 0x00000001, TRUE); | ||
1640 | } | ||
1641 | } | ||
1642 | return 0; | ||
1643 | } | ||
1644 | |||
1645 | static int mddi_toshiba_lcd_off(struct platform_device *pdev) | ||
1646 | { | ||
1647 | mddi_toshiba_lcd_powerdown(platform_get_drvdata(pdev)); | ||
1648 | return 0; | ||
1649 | } | ||
1650 | |||
1651 | static int __init mddi_toshiba_lcd_probe(struct platform_device *pdev) | ||
1652 | { | ||
1653 | if (pdev->id == 0) { | ||
1654 | mddi_toshiba_pdata = pdev->dev.platform_data; | ||
1655 | return 0; | ||
1656 | } | ||
1657 | |||
1658 | msm_fb_add_device(pdev); | ||
1659 | |||
1660 | return 0; | ||
1661 | } | ||
1662 | |||
1663 | static struct platform_driver this_driver = { | ||
1664 | .probe = mddi_toshiba_lcd_probe, | ||
1665 | .driver = { | ||
1666 | .name = "mddi_toshiba", | ||
1667 | }, | ||
1668 | }; | ||
1669 | |||
1670 | static struct msm_fb_panel_data toshiba_panel_data = { | ||
1671 | .on = mddi_toshiba_lcd_on, | ||
1672 | .off = mddi_toshiba_lcd_off, | ||
1673 | }; | ||
1674 | |||
1675 | static int ch_used[3]; | ||
1676 | |||
1677 | int mddi_toshiba_device_register(struct msm_panel_info *pinfo, | ||
1678 | u32 channel, u32 panel) | ||
1679 | { | ||
1680 | struct platform_device *pdev = NULL; | ||
1681 | int ret; | ||
1682 | |||
1683 | if ((channel >= 3) || ch_used[channel]) | ||
1684 | return -ENODEV; | ||
1685 | |||
1686 | if ((channel != TOSHIBA_VGA_PRIM) && | ||
1687 | mddi_toshiba_pdata && mddi_toshiba_pdata->panel_num) | ||
1688 | if (mddi_toshiba_pdata->panel_num() < 2) | ||
1689 | return -ENODEV; | ||
1690 | |||
1691 | ch_used[channel] = TRUE; | ||
1692 | |||
1693 | pdev = platform_device_alloc("mddi_toshiba", (panel << 8)|channel); | ||
1694 | if (!pdev) | ||
1695 | return -ENOMEM; | ||
1696 | |||
1697 | if (channel == TOSHIBA_VGA_PRIM) { | ||
1698 | toshiba_panel_data.set_backlight = | ||
1699 | mddi_toshiba_lcd_set_backlight; | ||
1700 | |||
1701 | if (pinfo->lcd.vsync_enable) { | ||
1702 | toshiba_panel_data.set_vsync_notifier = | ||
1703 | mddi_toshiba_vsync_set_handler; | ||
1704 | mddi_lcd.vsync_detected = | ||
1705 | mddi_toshiba_lcd_vsync_detected; | ||
1706 | } | ||
1707 | } else { | ||
1708 | toshiba_panel_data.set_backlight = NULL; | ||
1709 | toshiba_panel_data.set_vsync_notifier = NULL; | ||
1710 | } | ||
1711 | |||
1712 | toshiba_panel_data.panel_info = *pinfo; | ||
1713 | |||
1714 | ret = platform_device_add_data(pdev, &toshiba_panel_data, | ||
1715 | sizeof(toshiba_panel_data)); | ||
1716 | if (ret) { | ||
1717 | printk(KERN_ERR | ||
1718 | "%s: platform_device_add_data failed!\n", __func__); | ||
1719 | goto err_device_put; | ||
1720 | } | ||
1721 | |||
1722 | ret = platform_device_add(pdev); | ||
1723 | if (ret) { | ||
1724 | printk(KERN_ERR | ||
1725 | "%s: platform_device_register failed!\n", __func__); | ||
1726 | goto err_device_put; | ||
1727 | } | ||
1728 | |||
1729 | return 0; | ||
1730 | |||
1731 | err_device_put: | ||
1732 | platform_device_put(pdev); | ||
1733 | return ret; | ||
1734 | } | ||
1735 | |||
1736 | static int __init mddi_toshiba_lcd_init(void) | ||
1737 | { | ||
1738 | return platform_driver_register(&this_driver); | ||
1739 | } | ||
1740 | |||
1741 | module_init(mddi_toshiba_lcd_init); | ||
diff --git a/drivers/staging/msm/mddi_toshiba.h b/drivers/staging/msm/mddi_toshiba.h new file mode 100644 index 000000000000..2d22b9a2c413 --- /dev/null +++ b/drivers/staging/msm/mddi_toshiba.h | |||
@@ -0,0 +1,52 @@ | |||
1 | /* Copyright (c) 2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * Redistribution and use in source and binary forms, with or without | ||
4 | * modification, are permitted provided that the following conditions are met: | ||
5 | * * Redistributions of source code must retain the above copyright | ||
6 | * notice, this list of conditions and the following disclaimer. | ||
7 | * * Redistributions in binary form must reproduce the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer in the | ||
9 | * documentation and/or other materials provided with the distribution. | ||
10 | * * Neither the name of Code Aurora nor | ||
11 | * the names of its contributors may be used to endorse or promote | ||
12 | * products derived from this software without specific prior written | ||
13 | * permission. | ||
14 | * | ||
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
17 | * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
18 | * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||
19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||
20 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||
21 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | ||
22 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | ||
23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||
24 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | ||
25 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | * | ||
27 | */ | ||
28 | |||
29 | #ifndef MDDI_TOSHIBA_H | ||
30 | #define MDDI_TOSHIBA_H | ||
31 | |||
32 | #define TOSHIBA_VGA_PRIM 1 | ||
33 | #define TOSHIBA_VGA_SECD 2 | ||
34 | |||
35 | #define LCD_TOSHIBA_2P4_VGA 0 | ||
36 | #define LCD_TOSHIBA_2P4_WVGA 1 | ||
37 | #define LCD_TOSHIBA_2P4_WVGA_PT 2 | ||
38 | #define LCD_SHARP_2P4_VGA 3 | ||
39 | |||
40 | #define GPIO_BLOCK_BASE 0x150000 | ||
41 | #define SYSTEM_BLOCK2_BASE 0x170000 | ||
42 | |||
43 | #define GPIODIR (GPIO_BLOCK_BASE|0x04) | ||
44 | #define GPIOSEL (SYSTEM_BLOCK2_BASE|0x00) | ||
45 | #define GPIOPC (GPIO_BLOCK_BASE|0x28) | ||
46 | #define GPIODATA (GPIO_BLOCK_BASE|0x00) | ||
47 | |||
48 | #define write_client_reg(__X, __Y, __Z) {\ | ||
49 | mddi_queue_register_write(__X, __Y, TRUE, 0);\ | ||
50 | } | ||
51 | |||
52 | #endif /* MDDI_TOSHIBA_H */ | ||
diff --git a/drivers/staging/msm/mddi_toshiba_vga.c b/drivers/staging/msm/mddi_toshiba_vga.c new file mode 100644 index 000000000000..7e61d3a5b8f1 --- /dev/null +++ b/drivers/staging/msm/mddi_toshiba_vga.c | |||
@@ -0,0 +1,136 @@ | |||
1 | /* Copyright (c) 2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include "msm_fb.h" | ||
19 | #include "mddihost.h" | ||
20 | #include "mddihosti.h" | ||
21 | #include "mddi_toshiba.h" | ||
22 | |||
23 | static uint32 read_client_reg(uint32 addr) | ||
24 | { | ||
25 | uint32 val; | ||
26 | mddi_queue_register_read(addr, &val, TRUE, 0); | ||
27 | return val; | ||
28 | } | ||
29 | |||
30 | static uint32 toshiba_lcd_gpio_read(void) | ||
31 | { | ||
32 | uint32 val; | ||
33 | |||
34 | write_client_reg(GPIODIR, 0x0000000C, TRUE); | ||
35 | write_client_reg(GPIOSEL, 0x00000000, TRUE); | ||
36 | write_client_reg(GPIOSEL, 0x00000000, TRUE); | ||
37 | write_client_reg(GPIOPC, 0x03CF00C0, TRUE); | ||
38 | val = read_client_reg(GPIODATA) & 0x2C0; | ||
39 | |||
40 | return val; | ||
41 | } | ||
42 | |||
43 | static u32 mddi_toshiba_panel_detect(void) | ||
44 | { | ||
45 | mddi_host_type host_idx = MDDI_HOST_PRIM; | ||
46 | uint32 lcd_gpio; | ||
47 | u32 mddi_toshiba_lcd = LCD_TOSHIBA_2P4_VGA; | ||
48 | |||
49 | /* Toshiba display requires larger drive_lo value */ | ||
50 | mddi_host_reg_out(DRIVE_LO, 0x0050); | ||
51 | |||
52 | lcd_gpio = toshiba_lcd_gpio_read(); | ||
53 | switch (lcd_gpio) { | ||
54 | case 0x0080: | ||
55 | mddi_toshiba_lcd = LCD_SHARP_2P4_VGA; | ||
56 | break; | ||
57 | |||
58 | case 0x00C0: | ||
59 | default: | ||
60 | mddi_toshiba_lcd = LCD_TOSHIBA_2P4_VGA; | ||
61 | break; | ||
62 | } | ||
63 | |||
64 | return mddi_toshiba_lcd; | ||
65 | } | ||
66 | |||
67 | static int __init mddi_toshiba_vga_init(void) | ||
68 | { | ||
69 | int ret; | ||
70 | struct msm_panel_info pinfo; | ||
71 | u32 panel; | ||
72 | |||
73 | #ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT | ||
74 | u32 id; | ||
75 | |||
76 | ret = msm_fb_detect_client("mddi_toshiba_vga"); | ||
77 | if (ret == -ENODEV) | ||
78 | return 0; | ||
79 | |||
80 | if (ret) { | ||
81 | id = mddi_get_client_id(); | ||
82 | if ((id >> 16) != 0xD263) | ||
83 | return 0; | ||
84 | } | ||
85 | #endif | ||
86 | |||
87 | panel = mddi_toshiba_panel_detect(); | ||
88 | |||
89 | pinfo.xres = 480; | ||
90 | pinfo.yres = 640; | ||
91 | pinfo.type = MDDI_PANEL; | ||
92 | pinfo.pdest = DISPLAY_1; | ||
93 | pinfo.mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR; | ||
94 | pinfo.wait_cycle = 0; | ||
95 | pinfo.bpp = 18; | ||
96 | pinfo.lcd.vsync_enable = TRUE; | ||
97 | pinfo.lcd.refx100 = 6118; | ||
98 | pinfo.lcd.v_back_porch = 6; | ||
99 | pinfo.lcd.v_front_porch = 0; | ||
100 | pinfo.lcd.v_pulse_width = 0; | ||
101 | pinfo.lcd.hw_vsync_mode = FALSE; | ||
102 | pinfo.lcd.vsync_notifier_period = (1 * HZ); | ||
103 | pinfo.bl_max = 99; | ||
104 | pinfo.bl_min = 1; | ||
105 | pinfo.clk_rate = 122880000; | ||
106 | pinfo.clk_min = 120000000; | ||
107 | pinfo.clk_max = 200000000; | ||
108 | pinfo.fb_num = 2; | ||
109 | |||
110 | ret = mddi_toshiba_device_register(&pinfo, TOSHIBA_VGA_PRIM, panel); | ||
111 | if (ret) { | ||
112 | printk(KERN_ERR "%s: failed to register device!\n", __func__); | ||
113 | return ret; | ||
114 | } | ||
115 | |||
116 | pinfo.xres = 176; | ||
117 | pinfo.yres = 220; | ||
118 | pinfo.type = MDDI_PANEL; | ||
119 | pinfo.pdest = DISPLAY_2; | ||
120 | pinfo.mddi.vdopkt = 0x400; | ||
121 | pinfo.wait_cycle = 0; | ||
122 | pinfo.bpp = 18; | ||
123 | pinfo.clk_rate = 122880000; | ||
124 | pinfo.clk_min = 120000000; | ||
125 | pinfo.clk_max = 200000000; | ||
126 | pinfo.fb_num = 2; | ||
127 | |||
128 | ret = mddi_toshiba_device_register(&pinfo, TOSHIBA_VGA_SECD, panel); | ||
129 | if (ret) | ||
130 | printk(KERN_WARNING | ||
131 | "%s: failed to register device!\n", __func__); | ||
132 | |||
133 | return ret; | ||
134 | } | ||
135 | |||
136 | module_init(mddi_toshiba_vga_init); | ||
diff --git a/drivers/staging/msm/mddi_toshiba_wvga.c b/drivers/staging/msm/mddi_toshiba_wvga.c new file mode 100644 index 000000000000..557b0f08faf8 --- /dev/null +++ b/drivers/staging/msm/mddi_toshiba_wvga.c | |||
@@ -0,0 +1,63 @@ | |||
1 | /* Copyright (c) 2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include "msm_fb.h" | ||
19 | #include "mddihost.h" | ||
20 | #include "mddi_toshiba.h" | ||
21 | |||
22 | static int __init mddi_toshiba_wvga_init(void) | ||
23 | { | ||
24 | int ret; | ||
25 | struct msm_panel_info pinfo; | ||
26 | |||
27 | #ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT | ||
28 | if (msm_fb_detect_client("mddi_toshiba_wvga")) | ||
29 | return 0; | ||
30 | #endif | ||
31 | |||
32 | pinfo.xres = 800; | ||
33 | pinfo.yres = 480; | ||
34 | pinfo.pdest = DISPLAY_2; | ||
35 | pinfo.type = MDDI_PANEL; | ||
36 | pinfo.mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR; | ||
37 | pinfo.wait_cycle = 0; | ||
38 | pinfo.bpp = 18; | ||
39 | pinfo.lcd.vsync_enable = TRUE; | ||
40 | pinfo.lcd.refx100 = 6118; | ||
41 | pinfo.lcd.v_back_porch = 6; | ||
42 | pinfo.lcd.v_front_porch = 0; | ||
43 | pinfo.lcd.v_pulse_width = 0; | ||
44 | pinfo.lcd.hw_vsync_mode = FALSE; | ||
45 | pinfo.lcd.vsync_notifier_period = (1 * HZ); | ||
46 | pinfo.bl_max = 4; | ||
47 | pinfo.bl_min = 1; | ||
48 | pinfo.clk_rate = 192000000; | ||
49 | pinfo.clk_min = 190000000; | ||
50 | pinfo.clk_max = 200000000; | ||
51 | pinfo.fb_num = 2; | ||
52 | |||
53 | ret = mddi_toshiba_device_register(&pinfo, TOSHIBA_VGA_PRIM, | ||
54 | LCD_TOSHIBA_2P4_WVGA); | ||
55 | if (ret) { | ||
56 | printk(KERN_ERR "%s: failed to register device!\n", __func__); | ||
57 | return ret; | ||
58 | } | ||
59 | |||
60 | return ret; | ||
61 | } | ||
62 | |||
63 | module_init(mddi_toshiba_wvga_init); | ||
diff --git a/drivers/staging/msm/mddi_toshiba_wvga_pt.c b/drivers/staging/msm/mddi_toshiba_wvga_pt.c new file mode 100644 index 000000000000..fc7d4e0d294f --- /dev/null +++ b/drivers/staging/msm/mddi_toshiba_wvga_pt.c | |||
@@ -0,0 +1,64 @@ | |||
1 | /* Copyright (c) 2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include "msm_fb.h" | ||
19 | #include "mddihost.h" | ||
20 | #include "mddihosti.h" | ||
21 | #include "mddi_toshiba.h" | ||
22 | |||
23 | static int __init mddi_toshiba_wvga_pt_init(void) | ||
24 | { | ||
25 | int ret; | ||
26 | struct msm_panel_info pinfo; | ||
27 | #ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT | ||
28 | uint id; | ||
29 | |||
30 | ret = msm_fb_detect_client("mddi_toshiba_wvga_pt"); | ||
31 | if (ret == -ENODEV) | ||
32 | return 0; | ||
33 | |||
34 | if (ret) { | ||
35 | id = mddi_get_client_id(); | ||
36 | if (id != 0xd2638722) | ||
37 | return 0; | ||
38 | } | ||
39 | #endif | ||
40 | |||
41 | pinfo.xres = 480; | ||
42 | pinfo.yres = 800; | ||
43 | pinfo.type = MDDI_PANEL; | ||
44 | pinfo.pdest = DISPLAY_1; | ||
45 | pinfo.mddi.vdopkt = MDDI_DEFAULT_PRIM_PIX_ATTR; | ||
46 | pinfo.wait_cycle = 0; | ||
47 | pinfo.bpp = 18; | ||
48 | pinfo.lcd.vsync_enable = FALSE; | ||
49 | pinfo.bl_max = 15; | ||
50 | pinfo.bl_min = 1; | ||
51 | pinfo.clk_rate = 192000000; | ||
52 | pinfo.clk_min = 190000000; | ||
53 | pinfo.clk_max = 200000000; | ||
54 | pinfo.fb_num = 2; | ||
55 | |||
56 | ret = mddi_toshiba_device_register(&pinfo, TOSHIBA_VGA_PRIM, | ||
57 | LCD_TOSHIBA_2P4_WVGA_PT); | ||
58 | if (ret) | ||
59 | printk(KERN_ERR "%s: failed to register device!\n", __func__); | ||
60 | |||
61 | return ret; | ||
62 | } | ||
63 | |||
64 | module_init(mddi_toshiba_wvga_pt_init); | ||
diff --git a/drivers/staging/msm/mddihost.c b/drivers/staging/msm/mddihost.c new file mode 100644 index 000000000000..c6c1ee4eda05 --- /dev/null +++ b/drivers/staging/msm/mddihost.c | |||
@@ -0,0 +1,377 @@ | |||
1 | /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/delay.h> | ||
22 | #include <linux/mm.h> | ||
23 | #include <linux/fb.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/ioport.h> | ||
26 | #include <linux/device.h> | ||
27 | #include <linux/dma-mapping.h> | ||
28 | |||
29 | #include "msm_fb.h" | ||
30 | #include "mddihost.h" | ||
31 | #include "mddihosti.h" | ||
32 | |||
33 | #include <linux/clk.h> | ||
34 | #include <mach/clk.h> | ||
35 | |||
36 | struct semaphore mddi_host_mutex; | ||
37 | |||
38 | struct clk *mddi_io_clk; | ||
39 | static boolean mddi_host_powered = FALSE; | ||
40 | static boolean mddi_host_initialized = FALSE; | ||
41 | extern uint32 *mddi_reg_read_value_ptr; | ||
42 | |||
43 | mddi_lcd_func_type mddi_lcd; | ||
44 | |||
45 | extern mddi_client_capability_type mddi_client_capability_pkt; | ||
46 | |||
47 | #ifdef FEATURE_MDDI_HITACHI | ||
48 | extern void mddi_hitachi_window_adjust(uint16 x1, | ||
49 | uint16 x2, uint16 y1, uint16 y2); | ||
50 | #endif | ||
51 | |||
52 | extern void mddi_toshiba_lcd_init(void); | ||
53 | |||
54 | #ifdef FEATURE_MDDI_S6D0142 | ||
55 | extern void mddi_s6d0142_lcd_init(void); | ||
56 | extern void mddi_s6d0142_window_adjust(uint16 x1, | ||
57 | uint16 x2, | ||
58 | uint16 y1, | ||
59 | uint16 y2, | ||
60 | mddi_llist_done_cb_type done_cb); | ||
61 | #endif | ||
62 | |||
63 | void mddi_init(void) | ||
64 | { | ||
65 | if (mddi_host_initialized) | ||
66 | return; | ||
67 | |||
68 | mddi_host_initialized = TRUE; | ||
69 | |||
70 | init_MUTEX(&mddi_host_mutex); | ||
71 | |||
72 | if (!mddi_host_powered) { | ||
73 | down(&mddi_host_mutex); | ||
74 | mddi_host_init(MDDI_HOST_PRIM); | ||
75 | mddi_host_powered = TRUE; | ||
76 | up(&mddi_host_mutex); | ||
77 | mdelay(10); | ||
78 | } | ||
79 | } | ||
80 | |||
81 | int mddi_host_register_read(uint32 reg_addr, | ||
82 | uint32 *reg_value_ptr, boolean wait, mddi_host_type host) { | ||
83 | mddi_linked_list_type *curr_llist_ptr; | ||
84 | mddi_register_access_packet_type *regacc_pkt_ptr; | ||
85 | uint16 curr_llist_idx; | ||
86 | int ret = 0; | ||
87 | |||
88 | if (in_interrupt()) | ||
89 | MDDI_MSG_CRIT("Called from ISR context\n"); | ||
90 | |||
91 | if (!mddi_host_powered) { | ||
92 | MDDI_MSG_ERR("MDDI powered down!\n"); | ||
93 | mddi_init(); | ||
94 | } | ||
95 | |||
96 | down(&mddi_host_mutex); | ||
97 | |||
98 | mddi_reg_read_value_ptr = reg_value_ptr; | ||
99 | curr_llist_idx = mddi_get_reg_read_llist_item(host, TRUE); | ||
100 | if (curr_llist_idx == UNASSIGNED_INDEX) { | ||
101 | up(&mddi_host_mutex); | ||
102 | |||
103 | /* need to change this to some sort of wait */ | ||
104 | MDDI_MSG_ERR("Attempting to queue up more than 1 reg read\n"); | ||
105 | return -EINVAL; | ||
106 | } | ||
107 | |||
108 | curr_llist_ptr = &llist_extern[host][curr_llist_idx]; | ||
109 | curr_llist_ptr->link_controller_flags = 0x11; | ||
110 | curr_llist_ptr->packet_header_count = 14; | ||
111 | curr_llist_ptr->packet_data_count = 0; | ||
112 | |||
113 | curr_llist_ptr->next_packet_pointer = NULL; | ||
114 | curr_llist_ptr->packet_data_pointer = NULL; | ||
115 | curr_llist_ptr->reserved = 0; | ||
116 | |||
117 | regacc_pkt_ptr = &curr_llist_ptr->packet_header.register_pkt; | ||
118 | |||
119 | regacc_pkt_ptr->packet_length = curr_llist_ptr->packet_header_count; | ||
120 | regacc_pkt_ptr->packet_type = 146; /* register access packet */ | ||
121 | regacc_pkt_ptr->bClient_ID = 0; | ||
122 | regacc_pkt_ptr->read_write_info = 0x8001; | ||
123 | regacc_pkt_ptr->register_address = reg_addr; | ||
124 | |||
125 | /* now adjust pointers */ | ||
126 | mddi_queue_forward_packets(curr_llist_idx, curr_llist_idx, wait, | ||
127 | NULL, host); | ||
128 | /* need to check if we can write the pointer or not */ | ||
129 | |||
130 | up(&mddi_host_mutex); | ||
131 | |||
132 | if (wait) { | ||
133 | int wait_ret; | ||
134 | |||
135 | mddi_linked_list_notify_type *llist_notify_ptr; | ||
136 | llist_notify_ptr = &llist_extern_notify[host][curr_llist_idx]; | ||
137 | wait_ret = wait_for_completion_timeout( | ||
138 | &(llist_notify_ptr->done_comp), 5 * HZ); | ||
139 | |||
140 | if (wait_ret <= 0) | ||
141 | ret = -EBUSY; | ||
142 | |||
143 | if (wait_ret < 0) | ||
144 | printk(KERN_ERR "%s: failed to wait for completion!\n", | ||
145 | __func__); | ||
146 | else if (!wait_ret) | ||
147 | printk(KERN_ERR "%s: Timed out waiting!\n", __func__); | ||
148 | } | ||
149 | |||
150 | MDDI_MSG_DEBUG("Reg Read value=0x%x\n", *reg_value_ptr); | ||
151 | |||
152 | return ret; | ||
153 | } /* mddi_host_register_read */ | ||
154 | |||
155 | int mddi_host_register_write(uint32 reg_addr, | ||
156 | uint32 reg_val, enum mddi_data_packet_size_type packet_size, | ||
157 | boolean wait, mddi_llist_done_cb_type done_cb, mddi_host_type host) { | ||
158 | mddi_linked_list_type *curr_llist_ptr; | ||
159 | mddi_linked_list_type *curr_llist_dma_ptr; | ||
160 | mddi_register_access_packet_type *regacc_pkt_ptr; | ||
161 | uint16 curr_llist_idx; | ||
162 | int ret = 0; | ||
163 | |||
164 | if (in_interrupt()) | ||
165 | MDDI_MSG_CRIT("Called from ISR context\n"); | ||
166 | |||
167 | if (!mddi_host_powered) { | ||
168 | MDDI_MSG_ERR("MDDI powered down!\n"); | ||
169 | mddi_init(); | ||
170 | } | ||
171 | |||
172 | down(&mddi_host_mutex); | ||
173 | |||
174 | curr_llist_idx = mddi_get_next_free_llist_item(host, TRUE); | ||
175 | curr_llist_ptr = &llist_extern[host][curr_llist_idx]; | ||
176 | curr_llist_dma_ptr = &llist_dma_extern[host][curr_llist_idx]; | ||
177 | |||
178 | curr_llist_ptr->link_controller_flags = 1; | ||
179 | curr_llist_ptr->packet_header_count = 14; | ||
180 | curr_llist_ptr->packet_data_count = 4; | ||
181 | |||
182 | curr_llist_ptr->next_packet_pointer = NULL; | ||
183 | curr_llist_ptr->reserved = 0; | ||
184 | |||
185 | regacc_pkt_ptr = &curr_llist_ptr->packet_header.register_pkt; | ||
186 | |||
187 | regacc_pkt_ptr->packet_length = curr_llist_ptr->packet_header_count + | ||
188 | (uint16)packet_size; | ||
189 | regacc_pkt_ptr->packet_type = 146; /* register access packet */ | ||
190 | regacc_pkt_ptr->bClient_ID = 0; | ||
191 | regacc_pkt_ptr->read_write_info = 0x0001; | ||
192 | regacc_pkt_ptr->register_address = reg_addr; | ||
193 | regacc_pkt_ptr->register_data_list = reg_val; | ||
194 | |||
195 | MDDI_MSG_DEBUG("Reg Access write reg=0x%x, value=0x%x\n", | ||
196 | regacc_pkt_ptr->register_address, | ||
197 | regacc_pkt_ptr->register_data_list); | ||
198 | |||
199 | regacc_pkt_ptr = &curr_llist_dma_ptr->packet_header.register_pkt; | ||
200 | curr_llist_ptr->packet_data_pointer = | ||
201 | (void *)(®acc_pkt_ptr->register_data_list); | ||
202 | |||
203 | /* now adjust pointers */ | ||
204 | mddi_queue_forward_packets(curr_llist_idx, curr_llist_idx, wait, | ||
205 | done_cb, host); | ||
206 | |||
207 | up(&mddi_host_mutex); | ||
208 | |||
209 | if (wait) { | ||
210 | int wait_ret; | ||
211 | |||
212 | mddi_linked_list_notify_type *llist_notify_ptr; | ||
213 | llist_notify_ptr = &llist_extern_notify[host][curr_llist_idx]; | ||
214 | wait_ret = wait_for_completion_timeout( | ||
215 | &(llist_notify_ptr->done_comp), 5 * HZ); | ||
216 | |||
217 | if (wait_ret <= 0) | ||
218 | ret = -EBUSY; | ||
219 | |||
220 | if (wait_ret < 0) | ||
221 | printk(KERN_ERR "%s: failed to wait for completion!\n", | ||
222 | __func__); | ||
223 | else if (!wait_ret) | ||
224 | printk(KERN_ERR "%s: Timed out waiting!\n", __func__); | ||
225 | } | ||
226 | |||
227 | return ret; | ||
228 | } /* mddi_host_register_write */ | ||
229 | |||
230 | boolean mddi_host_register_read_int | ||
231 | (uint32 reg_addr, uint32 *reg_value_ptr, mddi_host_type host) { | ||
232 | mddi_linked_list_type *curr_llist_ptr; | ||
233 | mddi_register_access_packet_type *regacc_pkt_ptr; | ||
234 | uint16 curr_llist_idx; | ||
235 | |||
236 | if (!in_interrupt()) | ||
237 | MDDI_MSG_CRIT("Called from TASK context\n"); | ||
238 | |||
239 | if (!mddi_host_powered) { | ||
240 | MDDI_MSG_ERR("MDDI powered down!\n"); | ||
241 | return FALSE; | ||
242 | } | ||
243 | |||
244 | if (down_trylock(&mddi_host_mutex) != 0) | ||
245 | return FALSE; | ||
246 | |||
247 | mddi_reg_read_value_ptr = reg_value_ptr; | ||
248 | curr_llist_idx = mddi_get_reg_read_llist_item(host, FALSE); | ||
249 | if (curr_llist_idx == UNASSIGNED_INDEX) { | ||
250 | up(&mddi_host_mutex); | ||
251 | return FALSE; | ||
252 | } | ||
253 | |||
254 | curr_llist_ptr = &llist_extern[host][curr_llist_idx]; | ||
255 | curr_llist_ptr->link_controller_flags = 0x11; | ||
256 | curr_llist_ptr->packet_header_count = 14; | ||
257 | curr_llist_ptr->packet_data_count = 0; | ||
258 | |||
259 | curr_llist_ptr->next_packet_pointer = NULL; | ||
260 | curr_llist_ptr->packet_data_pointer = NULL; | ||
261 | curr_llist_ptr->reserved = 0; | ||
262 | |||
263 | regacc_pkt_ptr = &curr_llist_ptr->packet_header.register_pkt; | ||
264 | |||
265 | regacc_pkt_ptr->packet_length = curr_llist_ptr->packet_header_count; | ||
266 | regacc_pkt_ptr->packet_type = 146; /* register access packet */ | ||
267 | regacc_pkt_ptr->bClient_ID = 0; | ||
268 | regacc_pkt_ptr->read_write_info = 0x8001; | ||
269 | regacc_pkt_ptr->register_address = reg_addr; | ||
270 | |||
271 | /* now adjust pointers */ | ||
272 | mddi_queue_forward_packets(curr_llist_idx, curr_llist_idx, FALSE, | ||
273 | NULL, host); | ||
274 | /* need to check if we can write the pointer or not */ | ||
275 | |||
276 | up(&mddi_host_mutex); | ||
277 | |||
278 | return TRUE; | ||
279 | |||
280 | } /* mddi_host_register_read */ | ||
281 | |||
282 | boolean mddi_host_register_write_int | ||
283 | (uint32 reg_addr, | ||
284 | uint32 reg_val, mddi_llist_done_cb_type done_cb, mddi_host_type host) { | ||
285 | mddi_linked_list_type *curr_llist_ptr; | ||
286 | mddi_linked_list_type *curr_llist_dma_ptr; | ||
287 | mddi_register_access_packet_type *regacc_pkt_ptr; | ||
288 | uint16 curr_llist_idx; | ||
289 | |||
290 | if (!in_interrupt()) | ||
291 | MDDI_MSG_CRIT("Called from TASK context\n"); | ||
292 | |||
293 | if (!mddi_host_powered) { | ||
294 | MDDI_MSG_ERR("MDDI powered down!\n"); | ||
295 | return FALSE; | ||
296 | } | ||
297 | |||
298 | if (down_trylock(&mddi_host_mutex) != 0) | ||
299 | return FALSE; | ||
300 | |||
301 | curr_llist_idx = mddi_get_next_free_llist_item(host, FALSE); | ||
302 | if (curr_llist_idx == UNASSIGNED_INDEX) { | ||
303 | up(&mddi_host_mutex); | ||
304 | return FALSE; | ||
305 | } | ||
306 | |||
307 | curr_llist_ptr = &llist_extern[host][curr_llist_idx]; | ||
308 | curr_llist_dma_ptr = &llist_dma_extern[host][curr_llist_idx]; | ||
309 | |||
310 | curr_llist_ptr->link_controller_flags = 1; | ||
311 | curr_llist_ptr->packet_header_count = 14; | ||
312 | curr_llist_ptr->packet_data_count = 4; | ||
313 | |||
314 | curr_llist_ptr->next_packet_pointer = NULL; | ||
315 | curr_llist_ptr->reserved = 0; | ||
316 | |||
317 | regacc_pkt_ptr = &curr_llist_ptr->packet_header.register_pkt; | ||
318 | |||
319 | regacc_pkt_ptr->packet_length = curr_llist_ptr->packet_header_count + 4; | ||
320 | regacc_pkt_ptr->packet_type = 146; /* register access packet */ | ||
321 | regacc_pkt_ptr->bClient_ID = 0; | ||
322 | regacc_pkt_ptr->read_write_info = 0x0001; | ||
323 | regacc_pkt_ptr->register_address = reg_addr; | ||
324 | regacc_pkt_ptr->register_data_list = reg_val; | ||
325 | |||
326 | regacc_pkt_ptr = &curr_llist_dma_ptr->packet_header.register_pkt; | ||
327 | curr_llist_ptr->packet_data_pointer = | ||
328 | (void *)(&(regacc_pkt_ptr->register_data_list)); | ||
329 | |||
330 | /* now adjust pointers */ | ||
331 | mddi_queue_forward_packets(curr_llist_idx, curr_llist_idx, FALSE, | ||
332 | done_cb, host); | ||
333 | up(&mddi_host_mutex); | ||
334 | |||
335 | return TRUE; | ||
336 | |||
337 | } /* mddi_host_register_write */ | ||
338 | |||
339 | void mddi_wait(uint16 time_ms) | ||
340 | { | ||
341 | mdelay(time_ms); | ||
342 | } | ||
343 | |||
344 | void mddi_client_lcd_vsync_detected(boolean detected) | ||
345 | { | ||
346 | if (mddi_lcd.vsync_detected) | ||
347 | (*mddi_lcd.vsync_detected) (detected); | ||
348 | } | ||
349 | |||
350 | /* extended version of function includes done callback */ | ||
351 | void mddi_window_adjust_ext(struct msm_fb_data_type *mfd, | ||
352 | uint16 x1, | ||
353 | uint16 x2, | ||
354 | uint16 y1, | ||
355 | uint16 y2, mddi_llist_done_cb_type done_cb) | ||
356 | { | ||
357 | #ifdef FEATURE_MDDI_HITACHI | ||
358 | if (mfd->panel.id == HITACHI) | ||
359 | mddi_hitachi_window_adjust(x1, x2, y1, y2); | ||
360 | #elif defined(FEATURE_MDDI_S6D0142) | ||
361 | if (mfd->panel.id == MDDI_LCD_S6D0142) | ||
362 | mddi_s6d0142_window_adjust(x1, x2, y1, y2, done_cb); | ||
363 | #else | ||
364 | /* Do nothing then... except avoid lint/compiler warnings */ | ||
365 | (void)x1; | ||
366 | (void)x2; | ||
367 | (void)y1; | ||
368 | (void)y2; | ||
369 | (void)done_cb; | ||
370 | #endif | ||
371 | } | ||
372 | |||
373 | void mddi_window_adjust(struct msm_fb_data_type *mfd, | ||
374 | uint16 x1, uint16 x2, uint16 y1, uint16 y2) | ||
375 | { | ||
376 | mddi_window_adjust_ext(mfd, x1, x2, y1, y2, NULL); | ||
377 | } | ||
diff --git a/drivers/staging/msm/mddihost.h b/drivers/staging/msm/mddihost.h new file mode 100644 index 000000000000..20b817841c4a --- /dev/null +++ b/drivers/staging/msm/mddihost.h | |||
@@ -0,0 +1,225 @@ | |||
1 | /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * Redistribution and use in source and binary forms, with or without | ||
4 | * modification, are permitted provided that the following conditions are met: | ||
5 | * * Redistributions of source code must retain the above copyright | ||
6 | * notice, this list of conditions and the following disclaimer. | ||
7 | * * Redistributions in binary form must reproduce the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer in the | ||
9 | * documentation and/or other materials provided with the distribution. | ||
10 | * * Neither the name of Code Aurora nor | ||
11 | * the names of its contributors may be used to endorse or promote | ||
12 | * products derived from this software without specific prior written | ||
13 | * permission. | ||
14 | * | ||
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
17 | * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
18 | * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||
19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||
20 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||
21 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | ||
22 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | ||
23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||
24 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | ||
25 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | * | ||
27 | */ | ||
28 | |||
29 | #ifndef MDDIHOST_H | ||
30 | #define MDDIHOST_H | ||
31 | |||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/sched.h> | ||
34 | #include <linux/time.h> | ||
35 | #include <linux/init.h> | ||
36 | #include <linux/interrupt.h> | ||
37 | #include "linux/proc_fs.h" | ||
38 | #include <linux/types.h> | ||
39 | #include <linux/dma-mapping.h> | ||
40 | #include <linux/clk.h> | ||
41 | |||
42 | #include <mach/hardware.h> | ||
43 | #include <linux/io.h> | ||
44 | |||
45 | #include <asm/system.h> | ||
46 | #include <asm/mach-types.h> | ||
47 | #include <linux/types.h> | ||
48 | #include <linux/dma-mapping.h> | ||
49 | |||
50 | #include "msm_fb_panel.h" | ||
51 | |||
52 | #undef FEATURE_MDDI_MC4 | ||
53 | #undef FEATURE_MDDI_S6D0142 | ||
54 | #undef FEATURE_MDDI_HITACHI | ||
55 | #define FEATURE_MDDI_SHARP | ||
56 | #define FEATURE_MDDI_TOSHIBA | ||
57 | #undef FEATURE_MDDI_E751 | ||
58 | #define FEATURE_MDDI_CORONA | ||
59 | #define FEATURE_MDDI_PRISM | ||
60 | |||
61 | #define T_MSM7500 | ||
62 | |||
63 | typedef enum { | ||
64 | format_16bpp, | ||
65 | format_18bpp, | ||
66 | format_24bpp | ||
67 | } mddi_video_format; | ||
68 | |||
69 | typedef enum { | ||
70 | MDDI_LCD_NONE = 0, | ||
71 | MDDI_LCD_MC4, | ||
72 | MDDI_LCD_S6D0142, | ||
73 | MDDI_LCD_SHARP, | ||
74 | MDDI_LCD_E751, | ||
75 | MDDI_LCD_CORONA, | ||
76 | MDDI_LCD_HITACHI, | ||
77 | MDDI_LCD_TOSHIBA, | ||
78 | MDDI_LCD_PRISM, | ||
79 | MDDI_LCD_TP2, | ||
80 | MDDI_NUM_LCD_TYPES, | ||
81 | MDDI_LCD_DEFAULT = MDDI_LCD_TOSHIBA | ||
82 | } mddi_lcd_type; | ||
83 | |||
84 | typedef enum { | ||
85 | MDDI_HOST_PRIM = 0, | ||
86 | MDDI_HOST_EXT, | ||
87 | MDDI_NUM_HOST_CORES | ||
88 | } mddi_host_type; | ||
89 | |||
90 | typedef enum { | ||
91 | MDDI_DRIVER_RESET, /* host core registers have not been written. */ | ||
92 | MDDI_DRIVER_DISABLED, /* registers written, interrupts disabled. */ | ||
93 | MDDI_DRIVER_ENABLED /* registers written, interrupts enabled. */ | ||
94 | } mddi_host_driver_state_type; | ||
95 | |||
96 | typedef enum { | ||
97 | MDDI_GPIO_INT_0 = 0, | ||
98 | MDDI_GPIO_INT_1, | ||
99 | MDDI_GPIO_INT_2, | ||
100 | MDDI_GPIO_INT_3, | ||
101 | MDDI_GPIO_INT_4, | ||
102 | MDDI_GPIO_INT_5, | ||
103 | MDDI_GPIO_INT_6, | ||
104 | MDDI_GPIO_INT_7, | ||
105 | MDDI_GPIO_INT_8, | ||
106 | MDDI_GPIO_INT_9, | ||
107 | MDDI_GPIO_INT_10, | ||
108 | MDDI_GPIO_INT_11, | ||
109 | MDDI_GPIO_INT_12, | ||
110 | MDDI_GPIO_INT_13, | ||
111 | MDDI_GPIO_INT_14, | ||
112 | MDDI_GPIO_INT_15, | ||
113 | MDDI_GPIO_NUM_INTS | ||
114 | } mddi_gpio_int_type; | ||
115 | |||
116 | enum mddi_data_packet_size_type { | ||
117 | MDDI_DATA_PACKET_4_BYTES = 4, | ||
118 | MDDI_DATA_PACKET_8_BYTES = 8, | ||
119 | MDDI_DATA_PACKET_12_BYTES = 12, | ||
120 | MDDI_DATA_PACKET_16_BYTES = 16, | ||
121 | MDDI_DATA_PACKET_24_BYTES = 24 | ||
122 | }; | ||
123 | |||
124 | typedef struct { | ||
125 | uint32 addr; | ||
126 | uint32 value; | ||
127 | } mddi_reg_write_type; | ||
128 | |||
129 | boolean mddi_vsync_set_handler(msm_fb_vsync_handler_type handler, void *arg); | ||
130 | |||
131 | typedef void (*mddi_llist_done_cb_type) (void); | ||
132 | |||
133 | typedef void (*mddi_rev_handler_type) (void *); | ||
134 | |||
135 | boolean mddi_set_rev_handler(mddi_rev_handler_type handler, uint16 pkt_type); | ||
136 | |||
137 | #define MDDI_DEFAULT_PRIM_PIX_ATTR 0xC3 | ||
138 | #define MDDI_DEFAULT_SECD_PIX_ATTR 0xC0 | ||
139 | |||
140 | typedef int gpio_int_polarity_type; | ||
141 | typedef int gpio_int_handler_type; | ||
142 | |||
143 | typedef struct { | ||
144 | void (*vsync_detected) (boolean); | ||
145 | } mddi_lcd_func_type; | ||
146 | |||
147 | extern mddi_lcd_func_type mddi_lcd; | ||
148 | void mddi_init(void); | ||
149 | |||
150 | void mddi_powerdown(void); | ||
151 | |||
152 | void mddi_host_start_ext_display(void); | ||
153 | void mddi_host_stop_ext_display(void); | ||
154 | |||
155 | extern spinlock_t mddi_host_spin_lock; | ||
156 | #ifdef T_MSM7500 | ||
157 | void mddi_reset(void); | ||
158 | #ifdef FEATURE_DUAL_PROC_MODEM_DISPLAY | ||
159 | void mddi_host_switch_proc_control(boolean on); | ||
160 | #endif | ||
161 | #endif | ||
162 | void mddi_host_exit_power_collapse(void); | ||
163 | |||
164 | void mddi_queue_splash_screen | ||
165 | (void *buf_ptr, | ||
166 | boolean clear_area, | ||
167 | int16 src_width, | ||
168 | int16 src_starting_row, | ||
169 | int16 src_starting_column, | ||
170 | int16 num_of_rows, | ||
171 | int16 num_of_columns, int16 dst_starting_row, int16 dst_starting_column); | ||
172 | |||
173 | void mddi_queue_image | ||
174 | (void *buf_ptr, | ||
175 | uint8 stereo_video, | ||
176 | boolean clear_area, | ||
177 | int16 src_width, | ||
178 | int16 src_starting_row, | ||
179 | int16 src_starting_column, | ||
180 | int16 num_of_rows, | ||
181 | int16 num_of_columns, int16 dst_starting_row, int16 dst_starting_column); | ||
182 | |||
183 | int mddi_host_register_read | ||
184 | (uint32 reg_addr, | ||
185 | uint32 *reg_value_ptr, boolean wait, mddi_host_type host_idx); | ||
186 | int mddi_host_register_write | ||
187 | (uint32 reg_addr, uint32 reg_val, | ||
188 | enum mddi_data_packet_size_type packet_size, | ||
189 | boolean wait, mddi_llist_done_cb_type done_cb, mddi_host_type host); | ||
190 | boolean mddi_host_register_write_int | ||
191 | (uint32 reg_addr, | ||
192 | uint32 reg_val, mddi_llist_done_cb_type done_cb, mddi_host_type host); | ||
193 | boolean mddi_host_register_read_int | ||
194 | (uint32 reg_addr, uint32 *reg_value_ptr, mddi_host_type host_idx); | ||
195 | void mddi_queue_register_write_static | ||
196 | (uint32 reg_addr, | ||
197 | uint32 reg_val, boolean wait, mddi_llist_done_cb_type done_cb); | ||
198 | void mddi_queue_static_window_adjust | ||
199 | (const mddi_reg_write_type *reg_write, | ||
200 | uint16 num_writes, mddi_llist_done_cb_type done_cb); | ||
201 | |||
202 | #define mddi_queue_register_read(reg, val_ptr, wait, sig) \ | ||
203 | mddi_host_register_read(reg, val_ptr, wait, MDDI_HOST_PRIM) | ||
204 | #define mddi_queue_register_write(reg, val, wait, sig) \ | ||
205 | mddi_host_register_write(reg, val, MDDI_DATA_PACKET_4_BYTES,\ | ||
206 | wait, NULL, MDDI_HOST_PRIM) | ||
207 | #define mddi_queue_register_write_extn(reg, val, pkt_size, wait, sig) \ | ||
208 | mddi_host_register_write(reg, val, pkt_size, \ | ||
209 | wait, NULL, MDDI_HOST_PRIM) | ||
210 | #define mddi_queue_register_write_int(reg, val) \ | ||
211 | mddi_host_register_write_int(reg, val, NULL, MDDI_HOST_PRIM) | ||
212 | #define mddi_queue_register_read_int(reg, val_ptr) \ | ||
213 | mddi_host_register_read_int(reg, val_ptr, MDDI_HOST_PRIM) | ||
214 | #define mddi_queue_register_writes(reg_ptr, val, wait, sig) \ | ||
215 | mddi_host_register_writes(reg_ptr, val, wait, sig, MDDI_HOST_PRIM) | ||
216 | |||
217 | void mddi_wait(uint16 time_ms); | ||
218 | void mddi_assign_max_pkt_dimensions(uint16 image_cols, | ||
219 | uint16 image_rows, | ||
220 | uint16 bpp, | ||
221 | uint16 *max_cols, uint16 * max_rows); | ||
222 | uint16 mddi_assign_pkt_height(uint16 pkt_width, uint16 pkt_height, uint16 bpp); | ||
223 | void mddi_queue_reverse_encapsulation(boolean wait); | ||
224 | void mddi_disable(int lock); | ||
225 | #endif /* MDDIHOST_H */ | ||
diff --git a/drivers/staging/msm/mddihost_e.c b/drivers/staging/msm/mddihost_e.c new file mode 100644 index 000000000000..7de5eda71ce3 --- /dev/null +++ b/drivers/staging/msm/mddihost_e.c | |||
@@ -0,0 +1,63 @@ | |||
1 | /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/delay.h> | ||
22 | #include <linux/mm.h> | ||
23 | #include <linux/fb.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/ioport.h> | ||
26 | #include <linux/device.h> | ||
27 | #include <linux/dma-mapping.h> | ||
28 | |||
29 | #include "msm_fb.h" | ||
30 | #include "mddihost.h" | ||
31 | #include "mddihosti.h" | ||
32 | |||
33 | #include <linux/clk.h> | ||
34 | #include <mach/clk.h> | ||
35 | |||
36 | extern struct semaphore mddi_host_mutex; | ||
37 | static boolean mddi_host_ext_powered = FALSE; | ||
38 | |||
39 | void mddi_host_start_ext_display(void) | ||
40 | { | ||
41 | down(&mddi_host_mutex); | ||
42 | |||
43 | if (!mddi_host_ext_powered) { | ||
44 | mddi_host_init(MDDI_HOST_EXT); | ||
45 | |||
46 | mddi_host_ext_powered = TRUE; | ||
47 | } | ||
48 | |||
49 | up(&mddi_host_mutex); | ||
50 | } | ||
51 | |||
52 | void mddi_host_stop_ext_display(void) | ||
53 | { | ||
54 | down(&mddi_host_mutex); | ||
55 | |||
56 | if (mddi_host_ext_powered) { | ||
57 | mddi_host_powerdown(MDDI_HOST_EXT); | ||
58 | |||
59 | mddi_host_ext_powered = FALSE; | ||
60 | } | ||
61 | |||
62 | up(&mddi_host_mutex); | ||
63 | } | ||
diff --git a/drivers/staging/msm/mddihosti.c b/drivers/staging/msm/mddihosti.c new file mode 100644 index 000000000000..f9d6e91e8d5d --- /dev/null +++ b/drivers/staging/msm/mddihosti.c | |||
@@ -0,0 +1,2239 @@ | |||
1 | /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/delay.h> | ||
22 | #include <linux/mm.h> | ||
23 | #include <linux/fb.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/ioport.h> | ||
26 | #include <linux/device.h> | ||
27 | #include <linux/dma-mapping.h> | ||
28 | |||
29 | #include "msm_fb_panel.h" | ||
30 | #include "mddihost.h" | ||
31 | #include "mddihosti.h" | ||
32 | |||
33 | #define FEATURE_MDDI_UNDERRUN_RECOVERY | ||
34 | #ifndef FEATURE_MDDI_DISABLE_REVERSE | ||
35 | static void mddi_read_rev_packet(byte *data_ptr); | ||
36 | #endif | ||
37 | |||
38 | struct timer_list mddi_host_timer; | ||
39 | |||
40 | #define MDDI_DEFAULT_TIMER_LENGTH 5000 /* 5 seconds */ | ||
41 | uint32 mddi_rtd_frequency = 60000; /* send RTD every 60 seconds */ | ||
42 | uint32 mddi_client_status_frequency = 60000; /* get status pkt every 60 secs */ | ||
43 | |||
44 | boolean mddi_vsync_detect_enabled = FALSE; | ||
45 | mddi_gpio_info_type mddi_gpio; | ||
46 | |||
47 | uint32 mddi_host_core_version; | ||
48 | boolean mddi_debug_log_statistics = FALSE; | ||
49 | /* #define FEATURE_MDDI_HOST_ENABLE_EARLY_HIBERNATION */ | ||
50 | /* default to TRUE in case MDP does not vote */ | ||
51 | static boolean mddi_host_mdp_active_flag = TRUE; | ||
52 | static uint32 mddi_log_stats_counter; | ||
53 | uint32 mddi_log_stats_frequency = 4000; | ||
54 | |||
55 | #define MDDI_DEFAULT_REV_PKT_SIZE 0x20 | ||
56 | |||
57 | #ifndef FEATURE_MDDI_DISABLE_REVERSE | ||
58 | static boolean mddi_rev_ptr_workaround = TRUE; | ||
59 | static uint32 mddi_reg_read_retry; | ||
60 | static uint32 mddi_reg_read_retry_max = 20; | ||
61 | static boolean mddi_enable_reg_read_retry = TRUE; | ||
62 | static boolean mddi_enable_reg_read_retry_once = FALSE; | ||
63 | |||
64 | #define MDDI_MAX_REV_PKT_SIZE 0x60 | ||
65 | |||
66 | #define MDDI_CLIENT_CAPABILITY_REV_PKT_SIZE 0x60 | ||
67 | |||
68 | #define MDDI_VIDEO_REV_PKT_SIZE 0x40 | ||
69 | #define MDDI_REV_BUFFER_SIZE MDDI_MAX_REV_PKT_SIZE | ||
70 | static byte rev_packet_data[MDDI_MAX_REV_PKT_SIZE]; | ||
71 | #endif /* FEATURE_MDDI_DISABLE_REVERSE */ | ||
72 | /* leave these variables so graphics will compile */ | ||
73 | |||
74 | #define MDDI_MAX_REV_DATA_SIZE 128 | ||
75 | /*lint -d__align(x) */ | ||
76 | boolean mddi_debug_clear_rev_data = TRUE; | ||
77 | |||
78 | uint32 *mddi_reg_read_value_ptr; | ||
79 | |||
80 | mddi_client_capability_type mddi_client_capability_pkt; | ||
81 | static boolean mddi_client_capability_request = FALSE; | ||
82 | |||
83 | #ifndef FEATURE_MDDI_DISABLE_REVERSE | ||
84 | |||
85 | #define MAX_MDDI_REV_HANDLERS 2 | ||
86 | #define INVALID_PKT_TYPE 0xFFFF | ||
87 | |||
88 | typedef struct { | ||
89 | mddi_rev_handler_type handler; /* ISR to be executed */ | ||
90 | uint16 pkt_type; | ||
91 | } mddi_rev_pkt_handler_type; | ||
92 | static mddi_rev_pkt_handler_type mddi_rev_pkt_handler[MAX_MDDI_REV_HANDLERS] = | ||
93 | { {NULL, INVALID_PKT_TYPE}, {NULL, INVALID_PKT_TYPE} }; | ||
94 | |||
95 | static boolean mddi_rev_encap_user_request = FALSE; | ||
96 | static mddi_linked_list_notify_type mddi_rev_user; | ||
97 | |||
98 | spinlock_t mddi_host_spin_lock; | ||
99 | extern uint32 mdp_in_processing; | ||
100 | #endif | ||
101 | |||
102 | typedef enum { | ||
103 | MDDI_REV_IDLE | ||
104 | #ifndef FEATURE_MDDI_DISABLE_REVERSE | ||
105 | , MDDI_REV_REG_READ_ISSUED, | ||
106 | MDDI_REV_REG_READ_SENT, | ||
107 | MDDI_REV_ENCAP_ISSUED, | ||
108 | MDDI_REV_STATUS_REQ_ISSUED, | ||
109 | MDDI_REV_CLIENT_CAP_ISSUED | ||
110 | #endif | ||
111 | } mddi_rev_link_state_type; | ||
112 | |||
113 | typedef enum { | ||
114 | MDDI_LINK_DISABLED, | ||
115 | MDDI_LINK_HIBERNATING, | ||
116 | MDDI_LINK_ACTIVATING, | ||
117 | MDDI_LINK_ACTIVE | ||
118 | } mddi_host_link_state_type; | ||
119 | |||
120 | typedef struct { | ||
121 | uint32 count; | ||
122 | uint32 in_count; | ||
123 | uint32 disp_req_count; | ||
124 | uint32 state_change_count; | ||
125 | uint32 ll_done_count; | ||
126 | uint32 rev_avail_count; | ||
127 | uint32 error_count; | ||
128 | uint32 rev_encap_count; | ||
129 | uint32 llist_ptr_write_1; | ||
130 | uint32 llist_ptr_write_2; | ||
131 | } mddi_host_int_type; | ||
132 | |||
133 | typedef struct { | ||
134 | uint32 fwd_crc_count; | ||
135 | uint32 rev_crc_count; | ||
136 | uint32 pri_underflow; | ||
137 | uint32 sec_underflow; | ||
138 | uint32 rev_overflow; | ||
139 | uint32 pri_overwrite; | ||
140 | uint32 sec_overwrite; | ||
141 | uint32 rev_overwrite; | ||
142 | uint32 dma_failure; | ||
143 | uint32 rtd_failure; | ||
144 | uint32 reg_read_failure; | ||
145 | #ifdef FEATURE_MDDI_UNDERRUN_RECOVERY | ||
146 | uint32 pri_underrun_detected; | ||
147 | #endif | ||
148 | } mddi_host_stat_type; | ||
149 | |||
150 | typedef struct { | ||
151 | uint32 rtd_cnt; | ||
152 | uint32 rev_enc_cnt; | ||
153 | uint32 vid_cnt; | ||
154 | uint32 reg_acc_cnt; | ||
155 | uint32 cli_stat_cnt; | ||
156 | uint32 cli_cap_cnt; | ||
157 | uint32 reg_read_cnt; | ||
158 | uint32 link_active_cnt; | ||
159 | uint32 link_hibernate_cnt; | ||
160 | uint32 vsync_response_cnt; | ||
161 | uint32 fwd_crc_cnt; | ||
162 | uint32 rev_crc_cnt; | ||
163 | } mddi_log_params_struct_type; | ||
164 | |||
165 | typedef struct { | ||
166 | uint32 rtd_value; | ||
167 | uint32 rtd_counter; | ||
168 | uint32 client_status_cnt; | ||
169 | boolean rev_ptr_written; | ||
170 | uint8 *rev_ptr_start; | ||
171 | uint8 *rev_ptr_curr; | ||
172 | uint32 mddi_rev_ptr_write_val; | ||
173 | dma_addr_t rev_data_dma_addr; | ||
174 | uint16 rev_pkt_size; | ||
175 | mddi_rev_link_state_type rev_state; | ||
176 | mddi_host_link_state_type link_state; | ||
177 | mddi_host_driver_state_type driver_state; | ||
178 | boolean disable_hibernation; | ||
179 | uint32 saved_int_reg; | ||
180 | uint32 saved_int_en; | ||
181 | mddi_linked_list_type *llist_ptr; | ||
182 | dma_addr_t llist_dma_addr; | ||
183 | mddi_linked_list_type *llist_dma_ptr; | ||
184 | uint32 *rev_data_buf; | ||
185 | struct completion mddi_llist_avail_comp; | ||
186 | boolean mddi_waiting_for_llist_avail; | ||
187 | mddi_host_int_type int_type; | ||
188 | mddi_host_stat_type stats; | ||
189 | mddi_log_params_struct_type log_parms; | ||
190 | mddi_llist_info_type llist_info; | ||
191 | mddi_linked_list_notify_type llist_notify[MDDI_MAX_NUM_LLIST_ITEMS]; | ||
192 | } mddi_host_cntl_type; | ||
193 | |||
194 | static mddi_host_type mddi_curr_host = MDDI_HOST_PRIM; | ||
195 | static mddi_host_cntl_type mhctl[MDDI_NUM_HOST_CORES]; | ||
196 | mddi_linked_list_type *llist_extern[MDDI_NUM_HOST_CORES]; | ||
197 | mddi_linked_list_type *llist_dma_extern[MDDI_NUM_HOST_CORES]; | ||
198 | mddi_linked_list_notify_type *llist_extern_notify[MDDI_NUM_HOST_CORES]; | ||
199 | static mddi_log_params_struct_type prev_parms[MDDI_NUM_HOST_CORES]; | ||
200 | |||
201 | extern uint32 mdp_total_vdopkts; | ||
202 | |||
203 | static boolean mddi_host_io_clock_on = FALSE; | ||
204 | static boolean mddi_host_hclk_on = FALSE; | ||
205 | |||
206 | int int_mddi_pri_flag = FALSE; | ||
207 | int int_mddi_ext_flag = FALSE; | ||
208 | |||
209 | static void mddi_report_errors(uint32 int_reg) | ||
210 | { | ||
211 | mddi_host_type host_idx = mddi_curr_host; | ||
212 | mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); | ||
213 | |||
214 | if (int_reg & MDDI_INT_PRI_UNDERFLOW) { | ||
215 | pmhctl->stats.pri_underflow++; | ||
216 | MDDI_MSG_ERR("!!! MDDI Primary Underflow !!!\n"); | ||
217 | } | ||
218 | if (int_reg & MDDI_INT_SEC_UNDERFLOW) { | ||
219 | pmhctl->stats.sec_underflow++; | ||
220 | MDDI_MSG_ERR("!!! MDDI Secondary Underflow !!!\n"); | ||
221 | } | ||
222 | #ifndef FEATURE_MDDI_DISABLE_REVERSE | ||
223 | if (int_reg & MDDI_INT_REV_OVERFLOW) { | ||
224 | pmhctl->stats.rev_overflow++; | ||
225 | MDDI_MSG_ERR("!!! MDDI Reverse Overflow !!!\n"); | ||
226 | pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start; | ||
227 | mddi_host_reg_out(REV_PTR, pmhctl->mddi_rev_ptr_write_val); | ||
228 | |||
229 | } | ||
230 | if (int_reg & MDDI_INT_CRC_ERROR) | ||
231 | MDDI_MSG_ERR("!!! MDDI Reverse CRC Error !!!\n"); | ||
232 | #endif | ||
233 | if (int_reg & MDDI_INT_PRI_OVERWRITE) { | ||
234 | pmhctl->stats.pri_overwrite++; | ||
235 | MDDI_MSG_ERR("!!! MDDI Primary Overwrite !!!\n"); | ||
236 | } | ||
237 | if (int_reg & MDDI_INT_SEC_OVERWRITE) { | ||
238 | pmhctl->stats.sec_overwrite++; | ||
239 | MDDI_MSG_ERR("!!! MDDI Secondary Overwrite !!!\n"); | ||
240 | } | ||
241 | #ifndef FEATURE_MDDI_DISABLE_REVERSE | ||
242 | if (int_reg & MDDI_INT_REV_OVERWRITE) { | ||
243 | pmhctl->stats.rev_overwrite++; | ||
244 | /* This will show up normally and is not a problem */ | ||
245 | MDDI_MSG_DEBUG("MDDI Reverse Overwrite!\n"); | ||
246 | } | ||
247 | if (int_reg & MDDI_INT_RTD_FAILURE) { | ||
248 | mddi_host_reg_outm(INTEN, MDDI_INT_RTD_FAILURE, 0); | ||
249 | pmhctl->stats.rtd_failure++; | ||
250 | MDDI_MSG_ERR("!!! MDDI RTD Failure !!!\n"); | ||
251 | } | ||
252 | #endif | ||
253 | if (int_reg & MDDI_INT_DMA_FAILURE) { | ||
254 | pmhctl->stats.dma_failure++; | ||
255 | MDDI_MSG_ERR("!!! MDDI DMA Abort !!!\n"); | ||
256 | } | ||
257 | } | ||
258 | |||
259 | static void mddi_host_enable_io_clock(void) | ||
260 | { | ||
261 | if (!MDDI_HOST_IS_IO_CLOCK_ON) | ||
262 | MDDI_HOST_ENABLE_IO_CLOCK; | ||
263 | } | ||
264 | |||
265 | static void mddi_host_enable_hclk(void) | ||
266 | { | ||
267 | |||
268 | if (!MDDI_HOST_IS_HCLK_ON) | ||
269 | MDDI_HOST_ENABLE_HCLK; | ||
270 | } | ||
271 | |||
272 | static void mddi_host_disable_io_clock(void) | ||
273 | { | ||
274 | #ifndef FEATURE_MDDI_HOST_IO_CLOCK_CONTROL_DISABLE | ||
275 | if (MDDI_HOST_IS_IO_CLOCK_ON) | ||
276 | MDDI_HOST_DISABLE_IO_CLOCK; | ||
277 | #endif | ||
278 | } | ||
279 | |||
280 | static void mddi_host_disable_hclk(void) | ||
281 | { | ||
282 | #ifndef FEATURE_MDDI_HOST_HCLK_CONTROL_DISABLE | ||
283 | if (MDDI_HOST_IS_HCLK_ON) | ||
284 | MDDI_HOST_DISABLE_HCLK; | ||
285 | #endif | ||
286 | } | ||
287 | |||
288 | static void mddi_vote_to_sleep(mddi_host_type host_idx, boolean sleep) | ||
289 | { | ||
290 | uint16 vote_mask; | ||
291 | |||
292 | if (host_idx == MDDI_HOST_PRIM) | ||
293 | vote_mask = 0x01; | ||
294 | else | ||
295 | vote_mask = 0x02; | ||
296 | } | ||
297 | |||
298 | static void mddi_report_state_change(uint32 int_reg) | ||
299 | { | ||
300 | mddi_host_type host_idx = mddi_curr_host; | ||
301 | mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); | ||
302 | |||
303 | if ((pmhctl->saved_int_reg & MDDI_INT_IN_HIBERNATION) && | ||
304 | (pmhctl->saved_int_reg & MDDI_INT_LINK_ACTIVE)) { | ||
305 | /* recover from condition where the io_clock was turned off by the | ||
306 | clock driver during a transition to hibernation. The io_clock | ||
307 | disable is to prevent MDP/MDDI underruns when changing ARM | ||
308 | clock speeds. In the process of halting the ARM, the hclk | ||
309 | divider needs to be set to 1. When it is set to 1, there is | ||
310 | a small time (usecs) when hclk is off or slow, and this can | ||
311 | cause an underrun. To prevent the underrun, clock driver turns | ||
312 | off the MDDI io_clock before making the change. */ | ||
313 | mddi_host_reg_out(CMD, MDDI_CMD_POWERUP); | ||
314 | } | ||
315 | |||
316 | if (int_reg & MDDI_INT_LINK_ACTIVE) { | ||
317 | pmhctl->link_state = MDDI_LINK_ACTIVE; | ||
318 | pmhctl->log_parms.link_active_cnt++; | ||
319 | pmhctl->rtd_value = mddi_host_reg_in(RTD_VAL); | ||
320 | MDDI_MSG_DEBUG("!!! MDDI Active RTD:0x%x!!!\n", | ||
321 | pmhctl->rtd_value); | ||
322 | /* now interrupt on hibernation */ | ||
323 | mddi_host_reg_outm(INTEN, | ||
324 | (MDDI_INT_IN_HIBERNATION | | ||
325 | MDDI_INT_LINK_ACTIVE), | ||
326 | MDDI_INT_IN_HIBERNATION); | ||
327 | |||
328 | #ifdef DEBUG_MDDIHOSTI | ||
329 | /* if gpio interrupt is enabled, start polling at fastest | ||
330 | * registered rate | ||
331 | */ | ||
332 | if (mddi_gpio.polling_enabled) { | ||
333 | timer_reg(&mddi_gpio_poll_timer, | ||
334 | mddi_gpio_poll_timer_cb, 0, mddi_gpio.polling_interval, 0); | ||
335 | } | ||
336 | #endif | ||
337 | #ifndef FEATURE_MDDI_DISABLE_REVERSE | ||
338 | if (mddi_rev_ptr_workaround) { | ||
339 | /* HW CR: need to reset reverse register stuff */ | ||
340 | pmhctl->rev_ptr_written = FALSE; | ||
341 | pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start; | ||
342 | } | ||
343 | #endif | ||
344 | /* vote on sleep */ | ||
345 | mddi_vote_to_sleep(host_idx, FALSE); | ||
346 | |||
347 | if (host_idx == MDDI_HOST_PRIM) { | ||
348 | if (mddi_vsync_detect_enabled) { | ||
349 | /* | ||
350 | * Indicate to client specific code that vsync | ||
351 | * was enabled, but we did not detect a client | ||
352 | * intiated wakeup. The client specific | ||
353 | * handler can either reassert vsync detection, | ||
354 | * or treat this as a valid vsync. | ||
355 | */ | ||
356 | mddi_client_lcd_vsync_detected(FALSE); | ||
357 | pmhctl->log_parms.vsync_response_cnt++; | ||
358 | } | ||
359 | } | ||
360 | } | ||
361 | if (int_reg & MDDI_INT_IN_HIBERNATION) { | ||
362 | pmhctl->link_state = MDDI_LINK_HIBERNATING; | ||
363 | pmhctl->log_parms.link_hibernate_cnt++; | ||
364 | MDDI_MSG_DEBUG("!!! MDDI Hibernating !!!\n"); | ||
365 | /* now interrupt on link_active */ | ||
366 | #ifdef FEATURE_MDDI_DISABLE_REVERSE | ||
367 | mddi_host_reg_outm(INTEN, | ||
368 | (MDDI_INT_MDDI_IN | | ||
369 | MDDI_INT_IN_HIBERNATION | | ||
370 | MDDI_INT_LINK_ACTIVE), | ||
371 | MDDI_INT_LINK_ACTIVE); | ||
372 | #else | ||
373 | mddi_host_reg_outm(INTEN, | ||
374 | (MDDI_INT_MDDI_IN | | ||
375 | MDDI_INT_IN_HIBERNATION | | ||
376 | MDDI_INT_LINK_ACTIVE), | ||
377 | (MDDI_INT_MDDI_IN | MDDI_INT_LINK_ACTIVE)); | ||
378 | |||
379 | pmhctl->rtd_counter = mddi_rtd_frequency; | ||
380 | |||
381 | if (pmhctl->rev_state != MDDI_REV_IDLE) { | ||
382 | /* a rev_encap will not wake up the link, so we do that here */ | ||
383 | pmhctl->link_state = MDDI_LINK_ACTIVATING; | ||
384 | mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE); | ||
385 | } | ||
386 | #endif | ||
387 | |||
388 | if (pmhctl->disable_hibernation) { | ||
389 | mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE); | ||
390 | mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE); | ||
391 | pmhctl->link_state = MDDI_LINK_ACTIVATING; | ||
392 | } | ||
393 | #ifdef FEATURE_MDDI_UNDERRUN_RECOVERY | ||
394 | if ((pmhctl->llist_info.transmitting_start_idx != | ||
395 | UNASSIGNED_INDEX) | ||
396 | && | ||
397 | ((pmhctl-> | ||
398 | saved_int_reg & (MDDI_INT_PRI_LINK_LIST_DONE | | ||
399 | MDDI_INT_PRI_PTR_READ)) == | ||
400 | MDDI_INT_PRI_PTR_READ)) { | ||
401 | mddi_linked_list_type *llist_dma; | ||
402 | llist_dma = pmhctl->llist_dma_ptr; | ||
403 | /* | ||
404 | * All indications are that we have not received a | ||
405 | * linked list done interrupt, due to an underrun | ||
406 | * condition. Recovery attempt is to send again. | ||
407 | */ | ||
408 | dma_coherent_pre_ops(); | ||
409 | /* Write to primary pointer register again */ | ||
410 | mddi_host_reg_out(PRI_PTR, | ||
411 | &llist_dma[pmhctl->llist_info. | ||
412 | transmitting_start_idx]); | ||
413 | pmhctl->stats.pri_underrun_detected++; | ||
414 | } | ||
415 | #endif | ||
416 | |||
417 | /* vote on sleep */ | ||
418 | if (pmhctl->link_state == MDDI_LINK_HIBERNATING) { | ||
419 | mddi_vote_to_sleep(host_idx, TRUE); | ||
420 | } | ||
421 | |||
422 | #ifdef DEBUG_MDDIHOSTI | ||
423 | /* need to stop polling timer */ | ||
424 | if (mddi_gpio.polling_enabled) { | ||
425 | (void) timer_clr(&mddi_gpio_poll_timer, T_NONE); | ||
426 | } | ||
427 | #endif | ||
428 | } | ||
429 | } | ||
430 | |||
431 | void mddi_host_timer_service(unsigned long data) | ||
432 | { | ||
433 | #ifndef FEATURE_MDDI_DISABLE_REVERSE | ||
434 | unsigned long flags; | ||
435 | #endif | ||
436 | mddi_host_type host_idx; | ||
437 | mddi_host_cntl_type *pmhctl; | ||
438 | |||
439 | unsigned long time_ms = MDDI_DEFAULT_TIMER_LENGTH; | ||
440 | init_timer(&mddi_host_timer); | ||
441 | mddi_host_timer.function = mddi_host_timer_service; | ||
442 | mddi_host_timer.data = 0; | ||
443 | |||
444 | mddi_host_timer.expires = jiffies + ((time_ms * HZ) / 1000); | ||
445 | add_timer(&mddi_host_timer); | ||
446 | |||
447 | for (host_idx = MDDI_HOST_PRIM; host_idx < MDDI_NUM_HOST_CORES; | ||
448 | host_idx++) { | ||
449 | pmhctl = &(mhctl[host_idx]); | ||
450 | mddi_log_stats_counter += (uint32) time_ms; | ||
451 | #ifndef FEATURE_MDDI_DISABLE_REVERSE | ||
452 | pmhctl->rtd_counter += (uint32) time_ms; | ||
453 | pmhctl->client_status_cnt += (uint32) time_ms; | ||
454 | |||
455 | if (host_idx == MDDI_HOST_PRIM) { | ||
456 | if (pmhctl->client_status_cnt >= | ||
457 | mddi_client_status_frequency) { | ||
458 | if ((pmhctl->link_state == | ||
459 | MDDI_LINK_HIBERNATING) | ||
460 | && (pmhctl->client_status_cnt > | ||
461 | mddi_client_status_frequency)) { | ||
462 | /* | ||
463 | * special case where we are hibernating | ||
464 | * and mddi_host_isr is not firing, so | ||
465 | * kick the link so that the status can | ||
466 | * be retrieved | ||
467 | */ | ||
468 | |||
469 | /* need to wake up link before issuing | ||
470 | * rev encap command | ||
471 | */ | ||
472 | MDDI_MSG_INFO("wake up link!\n"); | ||
473 | spin_lock_irqsave(&mddi_host_spin_lock, | ||
474 | flags); | ||
475 | mddi_host_enable_hclk(); | ||
476 | mddi_host_enable_io_clock(); | ||
477 | pmhctl->link_state = | ||
478 | MDDI_LINK_ACTIVATING; | ||
479 | mddi_host_reg_out(CMD, | ||
480 | MDDI_CMD_LINK_ACTIVE); | ||
481 | spin_unlock_irqrestore | ||
482 | (&mddi_host_spin_lock, flags); | ||
483 | } else | ||
484 | if ((pmhctl->link_state == MDDI_LINK_ACTIVE) | ||
485 | && pmhctl->disable_hibernation) { | ||
486 | /* | ||
487 | * special case where we have disabled | ||
488 | * hibernation and mddi_host_isr | ||
489 | * is not firing, so enable interrupt | ||
490 | * for no pkts pending, which will | ||
491 | * generate an interrupt | ||
492 | */ | ||
493 | MDDI_MSG_INFO("kick isr!\n"); | ||
494 | spin_lock_irqsave(&mddi_host_spin_lock, | ||
495 | flags); | ||
496 | mddi_host_enable_hclk(); | ||
497 | mddi_host_reg_outm(INTEN, | ||
498 | MDDI_INT_NO_CMD_PKTS_PEND, | ||
499 | MDDI_INT_NO_CMD_PKTS_PEND); | ||
500 | spin_unlock_irqrestore | ||
501 | (&mddi_host_spin_lock, flags); | ||
502 | } | ||
503 | } | ||
504 | } | ||
505 | #endif /* #ifndef FEATURE_MDDI_DISABLE_REVERSE */ | ||
506 | } | ||
507 | |||
508 | /* Check if logging is turned on */ | ||
509 | for (host_idx = MDDI_HOST_PRIM; host_idx < MDDI_NUM_HOST_CORES; | ||
510 | host_idx++) { | ||
511 | mddi_log_params_struct_type *prev_ptr = &(prev_parms[host_idx]); | ||
512 | pmhctl = &(mhctl[host_idx]); | ||
513 | |||
514 | if (mddi_debug_log_statistics) { | ||
515 | |||
516 | /* get video pkt count from MDP, since MDDI sw cannot know this */ | ||
517 | pmhctl->log_parms.vid_cnt = mdp_total_vdopkts; | ||
518 | |||
519 | if (mddi_log_stats_counter >= mddi_log_stats_frequency) { | ||
520 | /* mddi_log_stats_counter = 0; */ | ||
521 | if (mddi_debug_log_statistics) { | ||
522 | MDDI_MSG_NOTICE | ||
523 | ("MDDI Statistics since last report:\n"); | ||
524 | MDDI_MSG_NOTICE(" Packets sent:\n"); | ||
525 | MDDI_MSG_NOTICE | ||
526 | (" %d RTD packet(s)\n", | ||
527 | pmhctl->log_parms.rtd_cnt - | ||
528 | prev_ptr->rtd_cnt); | ||
529 | if (prev_ptr->rtd_cnt != | ||
530 | pmhctl->log_parms.rtd_cnt) { | ||
531 | unsigned long flags; | ||
532 | spin_lock_irqsave | ||
533 | (&mddi_host_spin_lock, | ||
534 | flags); | ||
535 | mddi_host_enable_hclk(); | ||
536 | pmhctl->rtd_value = | ||
537 | mddi_host_reg_in(RTD_VAL); | ||
538 | spin_unlock_irqrestore | ||
539 | (&mddi_host_spin_lock, | ||
540 | flags); | ||
541 | MDDI_MSG_NOTICE | ||
542 | (" RTD value=%d\n", | ||
543 | pmhctl->rtd_value); | ||
544 | } | ||
545 | MDDI_MSG_NOTICE | ||
546 | (" %d VIDEO packets\n", | ||
547 | pmhctl->log_parms.vid_cnt - | ||
548 | prev_ptr->vid_cnt); | ||
549 | MDDI_MSG_NOTICE | ||
550 | (" %d Register Access packets\n", | ||
551 | pmhctl->log_parms.reg_acc_cnt - | ||
552 | prev_ptr->reg_acc_cnt); | ||
553 | MDDI_MSG_NOTICE | ||
554 | (" %d Reverse Encapsulation packet(s)\n", | ||
555 | pmhctl->log_parms.rev_enc_cnt - | ||
556 | prev_ptr->rev_enc_cnt); | ||
557 | if (prev_ptr->rev_enc_cnt != | ||
558 | pmhctl->log_parms.rev_enc_cnt) { | ||
559 | /* report # of reverse CRC errors */ | ||
560 | MDDI_MSG_NOTICE | ||
561 | (" %d reverse CRC errors detected\n", | ||
562 | pmhctl->log_parms. | ||
563 | rev_crc_cnt - | ||
564 | prev_ptr->rev_crc_cnt); | ||
565 | } | ||
566 | MDDI_MSG_NOTICE | ||
567 | (" Packets received:\n"); | ||
568 | MDDI_MSG_NOTICE | ||
569 | (" %d Client Status packets", | ||
570 | pmhctl->log_parms.cli_stat_cnt - | ||
571 | prev_ptr->cli_stat_cnt); | ||
572 | if (prev_ptr->cli_stat_cnt != | ||
573 | pmhctl->log_parms.cli_stat_cnt) { | ||
574 | MDDI_MSG_NOTICE | ||
575 | (" %d forward CRC errors reported\n", | ||
576 | pmhctl->log_parms. | ||
577 | fwd_crc_cnt - | ||
578 | prev_ptr->fwd_crc_cnt); | ||
579 | } | ||
580 | MDDI_MSG_NOTICE | ||
581 | (" %d Register Access Read packets\n", | ||
582 | pmhctl->log_parms.reg_read_cnt - | ||
583 | prev_ptr->reg_read_cnt); | ||
584 | |||
585 | if (pmhctl->link_state == | ||
586 | MDDI_LINK_ACTIVE) { | ||
587 | MDDI_MSG_NOTICE | ||
588 | (" Current Link Status: Active\n"); | ||
589 | } else | ||
590 | if ((pmhctl->link_state == | ||
591 | MDDI_LINK_HIBERNATING) | ||
592 | || (pmhctl->link_state == | ||
593 | MDDI_LINK_ACTIVATING)) { | ||
594 | MDDI_MSG_NOTICE | ||
595 | (" Current Link Status: Hibernation\n"); | ||
596 | } else { | ||
597 | MDDI_MSG_NOTICE | ||
598 | (" Current Link Status: Inactive\n"); | ||
599 | } | ||
600 | MDDI_MSG_NOTICE | ||
601 | (" Active state entered %d times\n", | ||
602 | pmhctl->log_parms.link_active_cnt - | ||
603 | prev_ptr->link_active_cnt); | ||
604 | MDDI_MSG_NOTICE | ||
605 | (" Hibernation state entered %d times\n", | ||
606 | pmhctl->log_parms. | ||
607 | link_hibernate_cnt - | ||
608 | prev_ptr->link_hibernate_cnt); | ||
609 | } | ||
610 | } | ||
611 | prev_parms[host_idx] = pmhctl->log_parms; | ||
612 | } | ||
613 | } | ||
614 | if (mddi_log_stats_counter >= mddi_log_stats_frequency) | ||
615 | mddi_log_stats_counter = 0; | ||
616 | |||
617 | return; | ||
618 | } /* mddi_host_timer_cb */ | ||
619 | |||
620 | static void mddi_process_link_list_done(void) | ||
621 | { | ||
622 | mddi_host_type host_idx = mddi_curr_host; | ||
623 | mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); | ||
624 | |||
625 | /* normal forward linked list packet(s) were sent */ | ||
626 | if (pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) { | ||
627 | MDDI_MSG_ERR("**** getting LL done, but no list ****\n"); | ||
628 | } else { | ||
629 | uint16 idx; | ||
630 | |||
631 | #ifndef FEATURE_MDDI_DISABLE_REVERSE | ||
632 | if (pmhctl->rev_state == MDDI_REV_REG_READ_ISSUED) { | ||
633 | /* special case where a register read packet was sent */ | ||
634 | pmhctl->rev_state = MDDI_REV_REG_READ_SENT; | ||
635 | if (pmhctl->llist_info.reg_read_idx == UNASSIGNED_INDEX) { | ||
636 | MDDI_MSG_ERR | ||
637 | ("**** getting LL done, but no list ****\n"); | ||
638 | } | ||
639 | } | ||
640 | #endif | ||
641 | for (idx = pmhctl->llist_info.transmitting_start_idx;;) { | ||
642 | uint16 next_idx = pmhctl->llist_notify[idx].next_idx; | ||
643 | /* with reg read we don't release the waiting tcb until after | ||
644 | * the reverse encapsulation has completed. | ||
645 | */ | ||
646 | if (idx != pmhctl->llist_info.reg_read_idx) { | ||
647 | /* notify task that may be waiting on this completion */ | ||
648 | if (pmhctl->llist_notify[idx].waiting) { | ||
649 | complete(& | ||
650 | (pmhctl->llist_notify[idx]. | ||
651 | done_comp)); | ||
652 | } | ||
653 | if (pmhctl->llist_notify[idx].done_cb != NULL) { | ||
654 | (*(pmhctl->llist_notify[idx].done_cb)) | ||
655 | (); | ||
656 | } | ||
657 | |||
658 | pmhctl->llist_notify[idx].in_use = FALSE; | ||
659 | pmhctl->llist_notify[idx].waiting = FALSE; | ||
660 | pmhctl->llist_notify[idx].done_cb = NULL; | ||
661 | if (idx < MDDI_NUM_DYNAMIC_LLIST_ITEMS) { | ||
662 | /* static LLIST items are configured only once */ | ||
663 | pmhctl->llist_notify[idx].next_idx = | ||
664 | UNASSIGNED_INDEX; | ||
665 | } | ||
666 | /* | ||
667 | * currently, all linked list packets are | ||
668 | * register access, so we can increment the | ||
669 | * counter for that packet type here. | ||
670 | */ | ||
671 | pmhctl->log_parms.reg_acc_cnt++; | ||
672 | } | ||
673 | if (idx == pmhctl->llist_info.transmitting_end_idx) | ||
674 | break; | ||
675 | idx = next_idx; | ||
676 | if (idx == UNASSIGNED_INDEX) | ||
677 | MDDI_MSG_CRIT("MDDI linked list corruption!\n"); | ||
678 | } | ||
679 | |||
680 | pmhctl->llist_info.transmitting_start_idx = UNASSIGNED_INDEX; | ||
681 | pmhctl->llist_info.transmitting_end_idx = UNASSIGNED_INDEX; | ||
682 | |||
683 | if (pmhctl->mddi_waiting_for_llist_avail) { | ||
684 | if (! | ||
685 | (pmhctl-> | ||
686 | llist_notify[pmhctl->llist_info.next_free_idx]. | ||
687 | in_use)) { | ||
688 | pmhctl->mddi_waiting_for_llist_avail = FALSE; | ||
689 | complete(&(pmhctl->mddi_llist_avail_comp)); | ||
690 | } | ||
691 | } | ||
692 | } | ||
693 | |||
694 | /* Turn off MDDI_INT_PRI_LINK_LIST_DONE interrupt */ | ||
695 | mddi_host_reg_outm(INTEN, MDDI_INT_PRI_LINK_LIST_DONE, 0); | ||
696 | |||
697 | } | ||
698 | |||
699 | static void mddi_queue_forward_linked_list(void) | ||
700 | { | ||
701 | uint16 first_pkt_index; | ||
702 | mddi_linked_list_type *llist_dma; | ||
703 | mddi_host_type host_idx = mddi_curr_host; | ||
704 | mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); | ||
705 | llist_dma = pmhctl->llist_dma_ptr; | ||
706 | |||
707 | first_pkt_index = UNASSIGNED_INDEX; | ||
708 | |||
709 | if (pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) { | ||
710 | #ifndef FEATURE_MDDI_DISABLE_REVERSE | ||
711 | if (pmhctl->llist_info.reg_read_waiting) { | ||
712 | if (pmhctl->rev_state == MDDI_REV_IDLE) { | ||
713 | /* | ||
714 | * we have a register read to send and | ||
715 | * can send it now | ||
716 | */ | ||
717 | pmhctl->rev_state = MDDI_REV_REG_READ_ISSUED; | ||
718 | mddi_reg_read_retry = 0; | ||
719 | first_pkt_index = | ||
720 | pmhctl->llist_info.waiting_start_idx; | ||
721 | pmhctl->llist_info.reg_read_waiting = FALSE; | ||
722 | } | ||
723 | } else | ||
724 | #endif | ||
725 | { | ||
726 | /* | ||
727 | * not register read to worry about, go ahead and write | ||
728 | * anything that may be on the waiting list. | ||
729 | */ | ||
730 | first_pkt_index = pmhctl->llist_info.waiting_start_idx; | ||
731 | } | ||
732 | } | ||
733 | |||
734 | if (first_pkt_index != UNASSIGNED_INDEX) { | ||
735 | pmhctl->llist_info.transmitting_start_idx = | ||
736 | pmhctl->llist_info.waiting_start_idx; | ||
737 | pmhctl->llist_info.transmitting_end_idx = | ||
738 | pmhctl->llist_info.waiting_end_idx; | ||
739 | pmhctl->llist_info.waiting_start_idx = UNASSIGNED_INDEX; | ||
740 | pmhctl->llist_info.waiting_end_idx = UNASSIGNED_INDEX; | ||
741 | |||
742 | /* write to the primary pointer register */ | ||
743 | MDDI_MSG_DEBUG("MDDI writing primary ptr with idx=%d\n", | ||
744 | first_pkt_index); | ||
745 | |||
746 | pmhctl->int_type.llist_ptr_write_2++; | ||
747 | |||
748 | dma_coherent_pre_ops(); | ||
749 | mddi_host_reg_out(PRI_PTR, &llist_dma[first_pkt_index]); | ||
750 | |||
751 | /* enable interrupt when complete */ | ||
752 | mddi_host_reg_outm(INTEN, MDDI_INT_PRI_LINK_LIST_DONE, | ||
753 | MDDI_INT_PRI_LINK_LIST_DONE); | ||
754 | |||
755 | } | ||
756 | |||
757 | } | ||
758 | |||
759 | #ifndef FEATURE_MDDI_DISABLE_REVERSE | ||
760 | static void mddi_read_rev_packet(byte *data_ptr) | ||
761 | { | ||
762 | uint16 i, length; | ||
763 | mddi_host_type host_idx = mddi_curr_host; | ||
764 | mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); | ||
765 | |||
766 | uint8 *rev_ptr_overflow = | ||
767 | (pmhctl->rev_ptr_start + MDDI_REV_BUFFER_SIZE); | ||
768 | |||
769 | /* first determine the length and handle invalid lengths */ | ||
770 | length = *pmhctl->rev_ptr_curr++; | ||
771 | if (pmhctl->rev_ptr_curr >= rev_ptr_overflow) | ||
772 | pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start; | ||
773 | length |= ((*pmhctl->rev_ptr_curr++) << 8); | ||
774 | if (pmhctl->rev_ptr_curr >= rev_ptr_overflow) | ||
775 | pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start; | ||
776 | if (length > (pmhctl->rev_pkt_size - 2)) { | ||
777 | MDDI_MSG_ERR("Invalid rev pkt length %d\n", length); | ||
778 | /* rev_pkt_size should always be <= rev_ptr_size so limit to packet size */ | ||
779 | length = pmhctl->rev_pkt_size - 2; | ||
780 | } | ||
781 | |||
782 | /* If the data pointer is NULL, just increment the pmhctl->rev_ptr_curr. | ||
783 | * Loop around if necessary. Don't bother reading the data. | ||
784 | */ | ||
785 | if (data_ptr == NULL) { | ||
786 | pmhctl->rev_ptr_curr += length; | ||
787 | if (pmhctl->rev_ptr_curr >= rev_ptr_overflow) | ||
788 | pmhctl->rev_ptr_curr -= MDDI_REV_BUFFER_SIZE; | ||
789 | return; | ||
790 | } | ||
791 | |||
792 | data_ptr[0] = length & 0x0ff; | ||
793 | data_ptr[1] = length >> 8; | ||
794 | data_ptr += 2; | ||
795 | /* copy the data to data_ptr byte-at-a-time */ | ||
796 | for (i = 0; (i < length) && (pmhctl->rev_ptr_curr < rev_ptr_overflow); | ||
797 | i++) | ||
798 | *data_ptr++ = *pmhctl->rev_ptr_curr++; | ||
799 | if (pmhctl->rev_ptr_curr >= rev_ptr_overflow) | ||
800 | pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start; | ||
801 | for (; (i < length) && (pmhctl->rev_ptr_curr < rev_ptr_overflow); i++) | ||
802 | *data_ptr++ = *pmhctl->rev_ptr_curr++; | ||
803 | } | ||
804 | |||
805 | static void mddi_process_rev_packets(void) | ||
806 | { | ||
807 | uint32 rev_packet_count; | ||
808 | word i; | ||
809 | uint32 crc_errors; | ||
810 | boolean mddi_reg_read_successful = FALSE; | ||
811 | mddi_host_type host_idx = mddi_curr_host; | ||
812 | mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); | ||
813 | |||
814 | pmhctl->log_parms.rev_enc_cnt++; | ||
815 | if ((pmhctl->rev_state != MDDI_REV_ENCAP_ISSUED) && | ||
816 | (pmhctl->rev_state != MDDI_REV_STATUS_REQ_ISSUED) && | ||
817 | (pmhctl->rev_state != MDDI_REV_CLIENT_CAP_ISSUED)) { | ||
818 | MDDI_MSG_ERR("Wrong state %d for reverse int\n", | ||
819 | pmhctl->rev_state); | ||
820 | } | ||
821 | /* Turn off MDDI_INT_REV_AVAIL interrupt */ | ||
822 | mddi_host_reg_outm(INTEN, MDDI_INT_REV_DATA_AVAIL, 0); | ||
823 | |||
824 | /* Clear rev data avail int */ | ||
825 | mddi_host_reg_out(INT, MDDI_INT_REV_DATA_AVAIL); | ||
826 | |||
827 | /* Get Number of packets */ | ||
828 | rev_packet_count = mddi_host_reg_in(REV_PKT_CNT); | ||
829 | |||
830 | #ifndef T_MSM7500 | ||
831 | /* Clear out rev packet counter */ | ||
832 | mddi_host_reg_out(REV_PKT_CNT, 0x0000); | ||
833 | #endif | ||
834 | |||
835 | #if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40) | ||
836 | if ((pmhctl->rev_state == MDDI_REV_CLIENT_CAP_ISSUED) && | ||
837 | (rev_packet_count > 0) && | ||
838 | (mddi_host_core_version == 0x28 || | ||
839 | mddi_host_core_version == 0x30)) { | ||
840 | |||
841 | uint32 int_reg; | ||
842 | uint32 max_count = 0; | ||
843 | |||
844 | mddi_host_reg_out(REV_PTR, pmhctl->mddi_rev_ptr_write_val); | ||
845 | int_reg = mddi_host_reg_in(INT); | ||
846 | while ((int_reg & 0x100000) == 0) { | ||
847 | udelay(3); | ||
848 | int_reg = mddi_host_reg_in(INT); | ||
849 | if (++max_count > 100) | ||
850 | break; | ||
851 | } | ||
852 | } | ||
853 | #endif | ||
854 | |||
855 | /* Get CRC error count */ | ||
856 | crc_errors = mddi_host_reg_in(REV_CRC_ERR); | ||
857 | if (crc_errors != 0) { | ||
858 | pmhctl->log_parms.rev_crc_cnt += crc_errors; | ||
859 | pmhctl->stats.rev_crc_count += crc_errors; | ||
860 | MDDI_MSG_ERR("!!! MDDI %d Reverse CRC Error(s) !!!\n", | ||
861 | crc_errors); | ||
862 | #ifndef T_MSM7500 | ||
863 | /* Clear CRC error count */ | ||
864 | mddi_host_reg_out(REV_CRC_ERR, 0x0000); | ||
865 | #endif | ||
866 | /* also issue an RTD to attempt recovery */ | ||
867 | pmhctl->rtd_counter = mddi_rtd_frequency; | ||
868 | } | ||
869 | |||
870 | pmhctl->rtd_value = mddi_host_reg_in(RTD_VAL); | ||
871 | |||
872 | MDDI_MSG_DEBUG("MDDI rev pkt cnt=%d, ptr=0x%x, RTD:0x%x\n", | ||
873 | rev_packet_count, | ||
874 | pmhctl->rev_ptr_curr - pmhctl->rev_ptr_start, | ||
875 | pmhctl->rtd_value); | ||
876 | |||
877 | if (rev_packet_count >= 1) { | ||
878 | mddi_invalidate_cache_lines((uint32 *) pmhctl->rev_ptr_start, | ||
879 | MDDI_REV_BUFFER_SIZE); | ||
880 | } | ||
881 | /* order the reads */ | ||
882 | dma_coherent_post_ops(); | ||
883 | for (i = 0; i < rev_packet_count; i++) { | ||
884 | mddi_rev_packet_type *rev_pkt_ptr; | ||
885 | |||
886 | mddi_read_rev_packet(rev_packet_data); | ||
887 | |||
888 | rev_pkt_ptr = (mddi_rev_packet_type *) rev_packet_data; | ||
889 | |||
890 | if (rev_pkt_ptr->packet_length > pmhctl->rev_pkt_size) { | ||
891 | MDDI_MSG_ERR("!!!invalid packet size: %d\n", | ||
892 | rev_pkt_ptr->packet_length); | ||
893 | } | ||
894 | |||
895 | MDDI_MSG_DEBUG("MDDI rev pkt 0x%x size 0x%x\n", | ||
896 | rev_pkt_ptr->packet_type, | ||
897 | rev_pkt_ptr->packet_length); | ||
898 | |||
899 | /* Do whatever you want to do with the data based on the packet type */ | ||
900 | switch (rev_pkt_ptr->packet_type) { | ||
901 | case 66: /* Client Capability */ | ||
902 | { | ||
903 | mddi_client_capability_type | ||
904 | *client_capability_pkt_ptr; | ||
905 | |||
906 | client_capability_pkt_ptr = | ||
907 | (mddi_client_capability_type *) | ||
908 | rev_packet_data; | ||
909 | MDDI_MSG_NOTICE | ||
910 | ("Client Capability: Week=%d, Year=%d\n", | ||
911 | client_capability_pkt_ptr-> | ||
912 | Week_of_Manufacture, | ||
913 | client_capability_pkt_ptr-> | ||
914 | Year_of_Manufacture); | ||
915 | memcpy((void *)&mddi_client_capability_pkt, | ||
916 | (void *)rev_packet_data, | ||
917 | sizeof(mddi_client_capability_type)); | ||
918 | pmhctl->log_parms.cli_cap_cnt++; | ||
919 | } | ||
920 | break; | ||
921 | |||
922 | case 70: /* Display Status */ | ||
923 | { | ||
924 | mddi_client_status_type *client_status_pkt_ptr; | ||
925 | |||
926 | client_status_pkt_ptr = | ||
927 | (mddi_client_status_type *) rev_packet_data; | ||
928 | if ((client_status_pkt_ptr->crc_error_count != | ||
929 | 0) | ||
930 | || (client_status_pkt_ptr-> | ||
931 | reverse_link_request != 0)) { | ||
932 | MDDI_MSG_ERR | ||
933 | ("Client Status: RevReq=%d, CrcErr=%d\n", | ||
934 | client_status_pkt_ptr-> | ||
935 | reverse_link_request, | ||
936 | client_status_pkt_ptr-> | ||
937 | crc_error_count); | ||
938 | } else { | ||
939 | MDDI_MSG_DEBUG | ||
940 | ("Client Status: RevReq=%d, CrcErr=%d\n", | ||
941 | client_status_pkt_ptr-> | ||
942 | reverse_link_request, | ||
943 | client_status_pkt_ptr-> | ||
944 | crc_error_count); | ||
945 | } | ||
946 | pmhctl->log_parms.fwd_crc_cnt += | ||
947 | client_status_pkt_ptr->crc_error_count; | ||
948 | pmhctl->stats.fwd_crc_count += | ||
949 | client_status_pkt_ptr->crc_error_count; | ||
950 | pmhctl->log_parms.cli_stat_cnt++; | ||
951 | } | ||
952 | break; | ||
953 | |||
954 | case 146: /* register access packet */ | ||
955 | { | ||
956 | mddi_register_access_packet_type | ||
957 | * regacc_pkt_ptr; | ||
958 | |||
959 | regacc_pkt_ptr = | ||
960 | (mddi_register_access_packet_type *) | ||
961 | rev_packet_data; | ||
962 | |||
963 | MDDI_MSG_DEBUG | ||
964 | ("Reg Acc parse reg=0x%x, value=0x%x\n", | ||
965 | regacc_pkt_ptr->register_address, | ||
966 | regacc_pkt_ptr->register_data_list); | ||
967 | |||
968 | /* Copy register value to location passed in */ | ||
969 | if (mddi_reg_read_value_ptr) { | ||
970 | #if defined(T_MSM6280) && !defined(T_MSM7200) | ||
971 | /* only least significant 16 bits are valid with 6280 */ | ||
972 | *mddi_reg_read_value_ptr = | ||
973 | regacc_pkt_ptr-> | ||
974 | register_data_list & 0x0000ffff; | ||
975 | #else | ||
976 | *mddi_reg_read_value_ptr = | ||
977 | regacc_pkt_ptr->register_data_list; | ||
978 | #endif | ||
979 | mddi_reg_read_successful = TRUE; | ||
980 | mddi_reg_read_value_ptr = NULL; | ||
981 | } | ||
982 | |||
983 | #ifdef DEBUG_MDDIHOSTI | ||
984 | if ((mddi_gpio.polling_enabled) && | ||
985 | (regacc_pkt_ptr->register_address == | ||
986 | mddi_gpio.polling_reg)) { | ||
987 | /* | ||
988 | * ToDo: need to call Linux GPIO call | ||
989 | * here... | ||
990 | */ | ||
991 | mddi_client_lcd_gpio_poll( | ||
992 | regacc_pkt_ptr->register_data_list); | ||
993 | } | ||
994 | #endif | ||
995 | pmhctl->log_parms.reg_read_cnt++; | ||
996 | } | ||
997 | break; | ||
998 | |||
999 | default: /* any other packet */ | ||
1000 | { | ||
1001 | uint16 hdlr; | ||
1002 | |||
1003 | for (hdlr = 0; hdlr < MAX_MDDI_REV_HANDLERS; | ||
1004 | hdlr++) { | ||
1005 | if (mddi_rev_pkt_handler[hdlr]. | ||
1006 | pkt_type == | ||
1007 | rev_pkt_ptr->packet_type) { | ||
1008 | (* | ||
1009 | (mddi_rev_pkt_handler[hdlr]. | ||
1010 | handler)) (rev_pkt_ptr); | ||
1011 | /* pmhctl->rev_state = MDDI_REV_IDLE; */ | ||
1012 | break; | ||
1013 | } | ||
1014 | } | ||
1015 | if (hdlr >= MAX_MDDI_REV_HANDLERS) | ||
1016 | MDDI_MSG_ERR("MDDI unknown rev pkt\n"); | ||
1017 | } | ||
1018 | break; | ||
1019 | } | ||
1020 | } | ||
1021 | if ((pmhctl->rev_ptr_curr + pmhctl->rev_pkt_size) >= | ||
1022 | (pmhctl->rev_ptr_start + MDDI_REV_BUFFER_SIZE)) { | ||
1023 | pmhctl->rev_ptr_written = FALSE; | ||
1024 | } | ||
1025 | |||
1026 | if (pmhctl->rev_state == MDDI_REV_ENCAP_ISSUED) { | ||
1027 | pmhctl->rev_state = MDDI_REV_IDLE; | ||
1028 | if (mddi_rev_user.waiting) { | ||
1029 | mddi_rev_user.waiting = FALSE; | ||
1030 | complete(&(mddi_rev_user.done_comp)); | ||
1031 | } else if (pmhctl->llist_info.reg_read_idx == UNASSIGNED_INDEX) { | ||
1032 | MDDI_MSG_ERR | ||
1033 | ("Reverse Encap state, but no reg read in progress\n"); | ||
1034 | } else { | ||
1035 | if ((!mddi_reg_read_successful) && | ||
1036 | (mddi_reg_read_retry < mddi_reg_read_retry_max) && | ||
1037 | (mddi_enable_reg_read_retry)) { | ||
1038 | /* | ||
1039 | * There is a race condition that can happen | ||
1040 | * where the reverse encapsulation message is | ||
1041 | * sent out by the MDDI host before the register | ||
1042 | * read packet is sent. As a work-around for | ||
1043 | * that problem we issue the reverse | ||
1044 | * encapsulation one more time before giving up. | ||
1045 | */ | ||
1046 | if (mddi_enable_reg_read_retry_once) | ||
1047 | mddi_reg_read_retry = | ||
1048 | mddi_reg_read_retry_max; | ||
1049 | pmhctl->rev_state = MDDI_REV_REG_READ_SENT; | ||
1050 | pmhctl->stats.reg_read_failure++; | ||
1051 | } else { | ||
1052 | uint16 reg_read_idx = | ||
1053 | pmhctl->llist_info.reg_read_idx; | ||
1054 | |||
1055 | mddi_reg_read_retry = 0; | ||
1056 | if (pmhctl->llist_notify[reg_read_idx].waiting) { | ||
1057 | complete(& | ||
1058 | (pmhctl-> | ||
1059 | llist_notify[reg_read_idx]. | ||
1060 | done_comp)); | ||
1061 | } | ||
1062 | pmhctl->llist_info.reg_read_idx = | ||
1063 | UNASSIGNED_INDEX; | ||
1064 | if (pmhctl->llist_notify[reg_read_idx]. | ||
1065 | done_cb != NULL) { | ||
1066 | (* | ||
1067 | (pmhctl->llist_notify[reg_read_idx]. | ||
1068 | done_cb)) (); | ||
1069 | } | ||
1070 | pmhctl->llist_notify[reg_read_idx].next_idx = | ||
1071 | UNASSIGNED_INDEX; | ||
1072 | pmhctl->llist_notify[reg_read_idx].in_use = | ||
1073 | FALSE; | ||
1074 | pmhctl->llist_notify[reg_read_idx].waiting = | ||
1075 | FALSE; | ||
1076 | pmhctl->llist_notify[reg_read_idx].done_cb = | ||
1077 | NULL; | ||
1078 | if (!mddi_reg_read_successful) | ||
1079 | pmhctl->stats.reg_read_failure++; | ||
1080 | } | ||
1081 | } | ||
1082 | } else if (pmhctl->rev_state == MDDI_REV_CLIENT_CAP_ISSUED) { | ||
1083 | #if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40) | ||
1084 | if (mddi_host_core_version == 0x28 || | ||
1085 | mddi_host_core_version == 0x30) { | ||
1086 | mddi_host_reg_out(FIFO_ALLOC, 0x00); | ||
1087 | pmhctl->rev_ptr_written = TRUE; | ||
1088 | mddi_host_reg_out(REV_PTR, | ||
1089 | pmhctl->mddi_rev_ptr_write_val); | ||
1090 | pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start; | ||
1091 | mddi_host_reg_out(CMD, 0xC00); | ||
1092 | } | ||
1093 | #endif | ||
1094 | |||
1095 | if (mddi_rev_user.waiting) { | ||
1096 | mddi_rev_user.waiting = FALSE; | ||
1097 | complete(&(mddi_rev_user.done_comp)); | ||
1098 | } | ||
1099 | pmhctl->rev_state = MDDI_REV_IDLE; | ||
1100 | } else { | ||
1101 | pmhctl->rev_state = MDDI_REV_IDLE; | ||
1102 | } | ||
1103 | |||
1104 | /* pmhctl->rev_state = MDDI_REV_IDLE; */ | ||
1105 | |||
1106 | /* Re-enable interrupt */ | ||
1107 | mddi_host_reg_outm(INTEN, MDDI_INT_REV_DATA_AVAIL, | ||
1108 | MDDI_INT_REV_DATA_AVAIL); | ||
1109 | |||
1110 | } | ||
1111 | |||
1112 | static void mddi_issue_reverse_encapsulation(void) | ||
1113 | { | ||
1114 | mddi_host_type host_idx = mddi_curr_host; | ||
1115 | mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); | ||
1116 | /* Only issue a reverse encapsulation packet if: | ||
1117 | * 1) another reverse is not in progress (MDDI_REV_IDLE). | ||
1118 | * 2) a register read has been sent (MDDI_REV_REG_READ_SENT). | ||
1119 | * 3) forward is not in progress, because of a hw bug in client that | ||
1120 | * causes forward crc errors on packet immediately after rev encap. | ||
1121 | */ | ||
1122 | if (((pmhctl->rev_state == MDDI_REV_IDLE) || | ||
1123 | (pmhctl->rev_state == MDDI_REV_REG_READ_SENT)) && | ||
1124 | (pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) && | ||
1125 | (!mdp_in_processing)) { | ||
1126 | uint32 mddi_command = MDDI_CMD_SEND_REV_ENCAP; | ||
1127 | |||
1128 | if ((pmhctl->rev_state == MDDI_REV_REG_READ_SENT) || | ||
1129 | (mddi_rev_encap_user_request == TRUE)) { | ||
1130 | mddi_host_enable_io_clock(); | ||
1131 | if (pmhctl->link_state == MDDI_LINK_HIBERNATING) { | ||
1132 | /* need to wake up link before issuing rev encap command */ | ||
1133 | MDDI_MSG_DEBUG("wake up link!\n"); | ||
1134 | pmhctl->link_state = MDDI_LINK_ACTIVATING; | ||
1135 | mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE); | ||
1136 | } else { | ||
1137 | if (pmhctl->rtd_counter >= mddi_rtd_frequency) { | ||
1138 | MDDI_MSG_DEBUG | ||
1139 | ("mddi sending RTD command!\n"); | ||
1140 | mddi_host_reg_out(CMD, | ||
1141 | MDDI_CMD_SEND_RTD); | ||
1142 | pmhctl->rtd_counter = 0; | ||
1143 | pmhctl->log_parms.rtd_cnt++; | ||
1144 | } | ||
1145 | if (pmhctl->rev_state != MDDI_REV_REG_READ_SENT) { | ||
1146 | /* this is generic reverse request by user, so | ||
1147 | * reset the waiting flag. */ | ||
1148 | mddi_rev_encap_user_request = FALSE; | ||
1149 | } | ||
1150 | /* link is active so send reverse encap to get register read results */ | ||
1151 | pmhctl->rev_state = MDDI_REV_ENCAP_ISSUED; | ||
1152 | mddi_command = MDDI_CMD_SEND_REV_ENCAP; | ||
1153 | MDDI_MSG_DEBUG("sending rev encap!\n"); | ||
1154 | } | ||
1155 | } else | ||
1156 | if ((pmhctl->client_status_cnt >= | ||
1157 | mddi_client_status_frequency) | ||
1158 | || mddi_client_capability_request) { | ||
1159 | mddi_host_enable_io_clock(); | ||
1160 | if (pmhctl->link_state == MDDI_LINK_HIBERNATING) { | ||
1161 | /* only wake up the link if it client status is overdue */ | ||
1162 | if ((pmhctl->client_status_cnt >= | ||
1163 | (mddi_client_status_frequency * 2)) | ||
1164 | || mddi_client_capability_request) { | ||
1165 | /* need to wake up link before issuing rev encap command */ | ||
1166 | MDDI_MSG_DEBUG("wake up link!\n"); | ||
1167 | pmhctl->link_state = | ||
1168 | MDDI_LINK_ACTIVATING; | ||
1169 | mddi_host_reg_out(CMD, | ||
1170 | MDDI_CMD_LINK_ACTIVE); | ||
1171 | } | ||
1172 | } else { | ||
1173 | if (pmhctl->rtd_counter >= mddi_rtd_frequency) { | ||
1174 | MDDI_MSG_DEBUG | ||
1175 | ("mddi sending RTD command!\n"); | ||
1176 | mddi_host_reg_out(CMD, | ||
1177 | MDDI_CMD_SEND_RTD); | ||
1178 | pmhctl->rtd_counter = 0; | ||
1179 | pmhctl->log_parms.rtd_cnt++; | ||
1180 | } | ||
1181 | /* periodically get client status */ | ||
1182 | MDDI_MSG_DEBUG | ||
1183 | ("mddi sending rev enc! (get status)\n"); | ||
1184 | if (mddi_client_capability_request) { | ||
1185 | pmhctl->rev_state = | ||
1186 | MDDI_REV_CLIENT_CAP_ISSUED; | ||
1187 | mddi_command = MDDI_CMD_GET_CLIENT_CAP; | ||
1188 | mddi_client_capability_request = FALSE; | ||
1189 | } else { | ||
1190 | pmhctl->rev_state = | ||
1191 | MDDI_REV_STATUS_REQ_ISSUED; | ||
1192 | pmhctl->client_status_cnt = 0; | ||
1193 | mddi_command = | ||
1194 | MDDI_CMD_GET_CLIENT_STATUS; | ||
1195 | } | ||
1196 | } | ||
1197 | } | ||
1198 | if ((pmhctl->rev_state == MDDI_REV_ENCAP_ISSUED) || | ||
1199 | (pmhctl->rev_state == MDDI_REV_STATUS_REQ_ISSUED) || | ||
1200 | (pmhctl->rev_state == MDDI_REV_CLIENT_CAP_ISSUED)) { | ||
1201 | pmhctl->int_type.rev_encap_count++; | ||
1202 | #if defined(T_MSM6280) && !defined(T_MSM7200) | ||
1203 | mddi_rev_pointer_written = TRUE; | ||
1204 | mddi_host_reg_out(REV_PTR, mddi_rev_ptr_write_val); | ||
1205 | mddi_rev_ptr_curr = mddi_rev_ptr_start; | ||
1206 | /* force new rev ptr command */ | ||
1207 | mddi_host_reg_out(CMD, 0xC00); | ||
1208 | #else | ||
1209 | if (!pmhctl->rev_ptr_written) { | ||
1210 | MDDI_MSG_DEBUG("writing reverse pointer!\n"); | ||
1211 | pmhctl->rev_ptr_written = TRUE; | ||
1212 | #if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40) | ||
1213 | if ((pmhctl->rev_state == | ||
1214 | MDDI_REV_CLIENT_CAP_ISSUED) && | ||
1215 | (mddi_host_core_version == 0x28 || | ||
1216 | mddi_host_core_version == 0x30)) { | ||
1217 | pmhctl->rev_ptr_written = FALSE; | ||
1218 | mddi_host_reg_out(FIFO_ALLOC, 0x02); | ||
1219 | } else | ||
1220 | mddi_host_reg_out(REV_PTR, | ||
1221 | pmhctl-> | ||
1222 | mddi_rev_ptr_write_val); | ||
1223 | #else | ||
1224 | mddi_host_reg_out(REV_PTR, | ||
1225 | pmhctl-> | ||
1226 | mddi_rev_ptr_write_val); | ||
1227 | #endif | ||
1228 | } | ||
1229 | #endif | ||
1230 | if (mddi_debug_clear_rev_data) { | ||
1231 | uint16 i; | ||
1232 | for (i = 0; i < MDDI_MAX_REV_DATA_SIZE / 4; i++) | ||
1233 | pmhctl->rev_data_buf[i] = 0xdddddddd; | ||
1234 | /* clean cache */ | ||
1235 | mddi_flush_cache_lines(pmhctl->rev_data_buf, | ||
1236 | MDDI_MAX_REV_DATA_SIZE); | ||
1237 | } | ||
1238 | |||
1239 | /* send reverse encapsulation to get needed data */ | ||
1240 | mddi_host_reg_out(CMD, mddi_command); | ||
1241 | } | ||
1242 | } | ||
1243 | |||
1244 | } | ||
1245 | |||
1246 | static void mddi_process_client_initiated_wakeup(void) | ||
1247 | { | ||
1248 | mddi_host_type host_idx = mddi_curr_host; | ||
1249 | mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); | ||
1250 | |||
1251 | /* Disable MDDI_INT Interrupt, we detect client initiated wakeup one | ||
1252 | * time for each entry into hibernation */ | ||
1253 | mddi_host_reg_outm(INTEN, MDDI_INT_MDDI_IN, 0); | ||
1254 | |||
1255 | if (host_idx == MDDI_HOST_PRIM) { | ||
1256 | if (mddi_vsync_detect_enabled) { | ||
1257 | mddi_host_enable_io_clock(); | ||
1258 | #ifndef MDDI_HOST_DISP_LISTEN | ||
1259 | /* issue command to bring up link */ | ||
1260 | /* need to do this to clear the vsync condition */ | ||
1261 | if (pmhctl->link_state == MDDI_LINK_HIBERNATING) { | ||
1262 | pmhctl->link_state = MDDI_LINK_ACTIVATING; | ||
1263 | mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE); | ||
1264 | } | ||
1265 | #endif | ||
1266 | /* | ||
1267 | * Indicate to client specific code that vsync was | ||
1268 | * enabled, and we did not detect a client initiated | ||
1269 | * wakeup. The client specific handler can clear the | ||
1270 | * condition if necessary to prevent subsequent | ||
1271 | * client initiated wakeups. | ||
1272 | */ | ||
1273 | mddi_client_lcd_vsync_detected(TRUE); | ||
1274 | pmhctl->log_parms.vsync_response_cnt++; | ||
1275 | MDDI_MSG_NOTICE("MDDI_INT_IN condition\n"); | ||
1276 | |||
1277 | } | ||
1278 | } | ||
1279 | |||
1280 | if (mddi_gpio.polling_enabled) { | ||
1281 | mddi_host_enable_io_clock(); | ||
1282 | /* check interrupt status now */ | ||
1283 | (void)mddi_queue_register_read_int(mddi_gpio.polling_reg, | ||
1284 | &mddi_gpio.polling_val); | ||
1285 | } | ||
1286 | } | ||
1287 | #endif /* FEATURE_MDDI_DISABLE_REVERSE */ | ||
1288 | |||
1289 | static void mddi_host_isr(void) | ||
1290 | { | ||
1291 | uint32 int_reg, int_en; | ||
1292 | #ifndef FEATURE_MDDI_DISABLE_REVERSE | ||
1293 | uint32 status_reg; | ||
1294 | #endif | ||
1295 | mddi_host_type host_idx = mddi_curr_host; | ||
1296 | mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); | ||
1297 | |||
1298 | if (!MDDI_HOST_IS_HCLK_ON) { | ||
1299 | MDDI_HOST_ENABLE_HCLK; | ||
1300 | MDDI_MSG_DEBUG("HCLK disabled, but isr is firing\n"); | ||
1301 | } | ||
1302 | int_reg = mddi_host_reg_in(INT); | ||
1303 | int_en = mddi_host_reg_in(INTEN); | ||
1304 | pmhctl->saved_int_reg = int_reg; | ||
1305 | pmhctl->saved_int_en = int_en; | ||
1306 | int_reg = int_reg & int_en; | ||
1307 | pmhctl->int_type.count++; | ||
1308 | |||
1309 | |||
1310 | #ifndef FEATURE_MDDI_DISABLE_REVERSE | ||
1311 | status_reg = mddi_host_reg_in(STAT); | ||
1312 | |||
1313 | if ((int_reg & MDDI_INT_MDDI_IN) || | ||
1314 | ((int_en & MDDI_INT_MDDI_IN) && | ||
1315 | ((int_reg == 0) || (status_reg & MDDI_STAT_CLIENT_WAKEUP_REQ)))) { | ||
1316 | /* | ||
1317 | * The MDDI_IN condition will clear itself, and so it is | ||
1318 | * possible that MDDI_IN was the reason for the isr firing, | ||
1319 | * even though the interrupt register does not have the | ||
1320 | * MDDI_IN bit set. To check if this was the case we need to | ||
1321 | * look at the status register bit that signifies a client | ||
1322 | * initiated wakeup. If the status register bit is set, as well | ||
1323 | * as the MDDI_IN interrupt enabled, then we treat this as a | ||
1324 | * client initiated wakeup. | ||
1325 | */ | ||
1326 | if (int_reg & MDDI_INT_MDDI_IN) | ||
1327 | pmhctl->int_type.in_count++; | ||
1328 | mddi_process_client_initiated_wakeup(); | ||
1329 | } | ||
1330 | #endif | ||
1331 | |||
1332 | if (int_reg & MDDI_INT_LINK_STATE_CHANGES) { | ||
1333 | pmhctl->int_type.state_change_count++; | ||
1334 | mddi_report_state_change(int_reg); | ||
1335 | } | ||
1336 | |||
1337 | if (int_reg & MDDI_INT_PRI_LINK_LIST_DONE) { | ||
1338 | pmhctl->int_type.ll_done_count++; | ||
1339 | mddi_process_link_list_done(); | ||
1340 | } | ||
1341 | #ifndef FEATURE_MDDI_DISABLE_REVERSE | ||
1342 | if (int_reg & MDDI_INT_REV_DATA_AVAIL) { | ||
1343 | pmhctl->int_type.rev_avail_count++; | ||
1344 | mddi_process_rev_packets(); | ||
1345 | } | ||
1346 | #endif | ||
1347 | |||
1348 | if (int_reg & MDDI_INT_ERROR_CONDITIONS) { | ||
1349 | pmhctl->int_type.error_count++; | ||
1350 | mddi_report_errors(int_reg); | ||
1351 | |||
1352 | mddi_host_reg_out(INT, int_reg & MDDI_INT_ERROR_CONDITIONS); | ||
1353 | } | ||
1354 | #ifndef FEATURE_MDDI_DISABLE_REVERSE | ||
1355 | mddi_issue_reverse_encapsulation(); | ||
1356 | |||
1357 | if ((pmhctl->rev_state != MDDI_REV_ENCAP_ISSUED) && | ||
1358 | (pmhctl->rev_state != MDDI_REV_STATUS_REQ_ISSUED)) | ||
1359 | #endif | ||
1360 | /* don't want simultaneous reverse and forward with Eagle */ | ||
1361 | mddi_queue_forward_linked_list(); | ||
1362 | |||
1363 | if (int_reg & MDDI_INT_NO_CMD_PKTS_PEND) { | ||
1364 | /* this interrupt is used to kick the isr when hibernation is disabled */ | ||
1365 | mddi_host_reg_outm(INTEN, MDDI_INT_NO_CMD_PKTS_PEND, 0); | ||
1366 | } | ||
1367 | |||
1368 | if ((!mddi_host_mdp_active_flag) && | ||
1369 | (!mddi_vsync_detect_enabled) && | ||
1370 | (pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) && | ||
1371 | (pmhctl->llist_info.waiting_start_idx == UNASSIGNED_INDEX) && | ||
1372 | (pmhctl->rev_state == MDDI_REV_IDLE)) { | ||
1373 | if (pmhctl->link_state == MDDI_LINK_HIBERNATING) { | ||
1374 | mddi_host_disable_io_clock(); | ||
1375 | mddi_host_disable_hclk(); | ||
1376 | } | ||
1377 | #ifdef FEATURE_MDDI_HOST_ENABLE_EARLY_HIBERNATION | ||
1378 | else if ((pmhctl->link_state == MDDI_LINK_ACTIVE) && | ||
1379 | (!pmhctl->disable_hibernation)) { | ||
1380 | mddi_host_reg_out(CMD, MDDI_CMD_POWERDOWN); | ||
1381 | } | ||
1382 | #endif | ||
1383 | } | ||
1384 | } | ||
1385 | |||
1386 | static void mddi_host_isr_primary(void) | ||
1387 | { | ||
1388 | mddi_curr_host = MDDI_HOST_PRIM; | ||
1389 | mddi_host_isr(); | ||
1390 | } | ||
1391 | |||
1392 | irqreturn_t mddi_pmdh_isr_proxy(int irq, void *ptr) | ||
1393 | { | ||
1394 | mddi_host_isr_primary(); | ||
1395 | return IRQ_HANDLED; | ||
1396 | } | ||
1397 | |||
1398 | static void mddi_host_isr_external(void) | ||
1399 | { | ||
1400 | mddi_curr_host = MDDI_HOST_EXT; | ||
1401 | mddi_host_isr(); | ||
1402 | mddi_curr_host = MDDI_HOST_PRIM; | ||
1403 | } | ||
1404 | |||
1405 | irqreturn_t mddi_emdh_isr_proxy(int irq, void *ptr) | ||
1406 | { | ||
1407 | mddi_host_isr_external(); | ||
1408 | return IRQ_HANDLED; | ||
1409 | } | ||
1410 | |||
1411 | static void mddi_host_initialize_registers(mddi_host_type host_idx) | ||
1412 | { | ||
1413 | uint32 pad_reg_val; | ||
1414 | mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); | ||
1415 | |||
1416 | if (pmhctl->driver_state == MDDI_DRIVER_ENABLED) | ||
1417 | return; | ||
1418 | |||
1419 | /* turn on HCLK to MDDI host core */ | ||
1420 | mddi_host_enable_hclk(); | ||
1421 | |||
1422 | /* MDDI Reset command */ | ||
1423 | mddi_host_reg_out(CMD, MDDI_CMD_RESET); | ||
1424 | |||
1425 | /* Version register (= 0x01) */ | ||
1426 | mddi_host_reg_out(VERSION, 0x0001); | ||
1427 | |||
1428 | /* Bytes per subframe register */ | ||
1429 | mddi_host_reg_out(BPS, MDDI_HOST_BYTES_PER_SUBFRAME); | ||
1430 | |||
1431 | /* Subframes per media frames register (= 0x03) */ | ||
1432 | mddi_host_reg_out(SPM, 0x0003); | ||
1433 | |||
1434 | /* Turn Around 1 register (= 0x05) */ | ||
1435 | mddi_host_reg_out(TA1_LEN, 0x0005); | ||
1436 | |||
1437 | /* Turn Around 2 register (= 0x0C) */ | ||
1438 | mddi_host_reg_out(TA2_LEN, MDDI_HOST_TA2_LEN); | ||
1439 | |||
1440 | /* Drive hi register (= 0x96) */ | ||
1441 | mddi_host_reg_out(DRIVE_HI, 0x0096); | ||
1442 | |||
1443 | /* Drive lo register (= 0x32) */ | ||
1444 | mddi_host_reg_out(DRIVE_LO, 0x0032); | ||
1445 | |||
1446 | /* Display wakeup count register (= 0x3c) */ | ||
1447 | mddi_host_reg_out(DISP_WAKE, 0x003c); | ||
1448 | |||
1449 | /* Reverse Rate Divisor register (= 0x2) */ | ||
1450 | mddi_host_reg_out(REV_RATE_DIV, MDDI_HOST_REV_RATE_DIV); | ||
1451 | |||
1452 | #ifndef FEATURE_MDDI_DISABLE_REVERSE | ||
1453 | /* Reverse Pointer Size */ | ||
1454 | mddi_host_reg_out(REV_SIZE, MDDI_REV_BUFFER_SIZE); | ||
1455 | |||
1456 | /* Rev Encap Size */ | ||
1457 | mddi_host_reg_out(REV_ENCAP_SZ, pmhctl->rev_pkt_size); | ||
1458 | #endif | ||
1459 | |||
1460 | /* Periodic Rev Encap */ | ||
1461 | /* don't send periodically */ | ||
1462 | mddi_host_reg_out(CMD, MDDI_CMD_PERIODIC_REV_ENCAP); | ||
1463 | |||
1464 | pad_reg_val = mddi_host_reg_in(PAD_CTL); | ||
1465 | if (pad_reg_val == 0) { | ||
1466 | /* If we are turning on band gap, need to wait 5us before turning | ||
1467 | * on the rest of the PAD */ | ||
1468 | mddi_host_reg_out(PAD_CTL, 0x08000); | ||
1469 | udelay(5); | ||
1470 | } | ||
1471 | #ifdef T_MSM7200 | ||
1472 | /* Recommendation from PAD hw team */ | ||
1473 | mddi_host_reg_out(PAD_CTL, 0xa850a); | ||
1474 | #else | ||
1475 | /* Recommendation from PAD hw team */ | ||
1476 | mddi_host_reg_out(PAD_CTL, 0xa850f); | ||
1477 | #endif | ||
1478 | |||
1479 | #if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40) | ||
1480 | mddi_host_reg_out(PAD_IO_CTL, 0x00320000); | ||
1481 | mddi_host_reg_out(PAD_CAL, 0x00220020); | ||
1482 | #endif | ||
1483 | |||
1484 | mddi_host_core_version = mddi_host_reg_inm(CORE_VER, 0xffff); | ||
1485 | |||
1486 | #ifndef FEATURE_MDDI_DISABLE_REVERSE | ||
1487 | if (mddi_host_core_version >= 8) | ||
1488 | mddi_rev_ptr_workaround = FALSE; | ||
1489 | pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start; | ||
1490 | #endif | ||
1491 | |||
1492 | if ((mddi_host_core_version > 8) && (mddi_host_core_version < 0x19)) | ||
1493 | mddi_host_reg_out(TEST, 0x2); | ||
1494 | |||
1495 | /* Need an even number for counts */ | ||
1496 | mddi_host_reg_out(DRIVER_START_CNT, 0x60006); | ||
1497 | |||
1498 | #ifndef T_MSM7500 | ||
1499 | /* Setup defaults for MDP related register */ | ||
1500 | mddi_host_reg_out(MDP_VID_FMT_DES, 0x5666); | ||
1501 | mddi_host_reg_out(MDP_VID_PIX_ATTR, 0x00C3); | ||
1502 | mddi_host_reg_out(MDP_VID_CLIENTID, 0); | ||
1503 | #endif | ||
1504 | |||
1505 | /* automatically hibernate after 1 empty subframe */ | ||
1506 | if (pmhctl->disable_hibernation) | ||
1507 | mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE); | ||
1508 | else | ||
1509 | mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE | 1); | ||
1510 | |||
1511 | /* Bring up link if display (client) requests it */ | ||
1512 | #ifdef MDDI_HOST_DISP_LISTEN | ||
1513 | mddi_host_reg_out(CMD, MDDI_CMD_DISP_LISTEN); | ||
1514 | #else | ||
1515 | mddi_host_reg_out(CMD, MDDI_CMD_DISP_IGNORE); | ||
1516 | #endif | ||
1517 | |||
1518 | } | ||
1519 | |||
1520 | void mddi_host_configure_interrupts(mddi_host_type host_idx, boolean enable) | ||
1521 | { | ||
1522 | unsigned long flags; | ||
1523 | mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); | ||
1524 | |||
1525 | spin_lock_irqsave(&mddi_host_spin_lock, flags); | ||
1526 | |||
1527 | /* turn on HCLK to MDDI host core if it has been disabled */ | ||
1528 | mddi_host_enable_hclk(); | ||
1529 | /* Clear MDDI Interrupt enable reg */ | ||
1530 | mddi_host_reg_out(INTEN, 0); | ||
1531 | |||
1532 | spin_unlock_irqrestore(&mddi_host_spin_lock, flags); | ||
1533 | |||
1534 | if (enable) { | ||
1535 | pmhctl->driver_state = MDDI_DRIVER_ENABLED; | ||
1536 | |||
1537 | if (host_idx == MDDI_HOST_PRIM) { | ||
1538 | if (request_irq | ||
1539 | (INT_MDDI_PRI, mddi_pmdh_isr_proxy, IRQF_DISABLED, | ||
1540 | "PMDH", 0) != 0) | ||
1541 | printk(KERN_ERR | ||
1542 | "a mddi: unable to request_irq\n"); | ||
1543 | else | ||
1544 | int_mddi_pri_flag = TRUE; | ||
1545 | } else { | ||
1546 | if (request_irq | ||
1547 | (INT_MDDI_EXT, mddi_emdh_isr_proxy, IRQF_DISABLED, | ||
1548 | "EMDH", 0) != 0) | ||
1549 | printk(KERN_ERR | ||
1550 | "b mddi: unable to request_irq\n"); | ||
1551 | else | ||
1552 | int_mddi_ext_flag = TRUE; | ||
1553 | } | ||
1554 | |||
1555 | /* Set MDDI Interrupt enable reg -- Enable Reverse data avail */ | ||
1556 | #ifdef FEATURE_MDDI_DISABLE_REVERSE | ||
1557 | mddi_host_reg_out(INTEN, | ||
1558 | MDDI_INT_ERROR_CONDITIONS | | ||
1559 | MDDI_INT_LINK_STATE_CHANGES); | ||
1560 | #else | ||
1561 | /* Reverse Pointer register */ | ||
1562 | pmhctl->rev_ptr_written = FALSE; | ||
1563 | |||
1564 | mddi_host_reg_out(INTEN, | ||
1565 | MDDI_INT_REV_DATA_AVAIL | | ||
1566 | MDDI_INT_ERROR_CONDITIONS | | ||
1567 | MDDI_INT_LINK_STATE_CHANGES); | ||
1568 | pmhctl->rtd_counter = mddi_rtd_frequency; | ||
1569 | pmhctl->client_status_cnt = 0; | ||
1570 | #endif | ||
1571 | } else { | ||
1572 | if (pmhctl->driver_state == MDDI_DRIVER_ENABLED) | ||
1573 | pmhctl->driver_state = MDDI_DRIVER_DISABLED; | ||
1574 | } | ||
1575 | |||
1576 | } | ||
1577 | |||
1578 | static void mddi_host_powerup(mddi_host_type host_idx) | ||
1579 | { | ||
1580 | mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); | ||
1581 | |||
1582 | if (pmhctl->link_state != MDDI_LINK_DISABLED) | ||
1583 | return; | ||
1584 | |||
1585 | /* enable IO_CLK and hclk to MDDI host core */ | ||
1586 | mddi_host_enable_io_clock(); | ||
1587 | |||
1588 | mddi_host_initialize_registers(host_idx); | ||
1589 | mddi_host_configure_interrupts(host_idx, TRUE); | ||
1590 | |||
1591 | pmhctl->link_state = MDDI_LINK_ACTIVATING; | ||
1592 | |||
1593 | /* Link activate command */ | ||
1594 | mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE); | ||
1595 | |||
1596 | #ifdef CLKRGM_MDDI_IO_CLOCK_IN_MHZ | ||
1597 | MDDI_MSG_NOTICE("MDDI Host: Activating Link %d Mbps\n", | ||
1598 | CLKRGM_MDDI_IO_CLOCK_IN_MHZ * 2); | ||
1599 | #else | ||
1600 | MDDI_MSG_NOTICE("MDDI Host: Activating Link\n"); | ||
1601 | #endif | ||
1602 | |||
1603 | /* Initialize the timer */ | ||
1604 | if (host_idx == MDDI_HOST_PRIM) | ||
1605 | mddi_host_timer_service(0); | ||
1606 | } | ||
1607 | |||
1608 | void mddi_host_init(mddi_host_type host_idx) | ||
1609 | /* Write out the MDDI configuration registers */ | ||
1610 | { | ||
1611 | static boolean initialized = FALSE; | ||
1612 | mddi_host_cntl_type *pmhctl; | ||
1613 | |||
1614 | if (host_idx >= MDDI_NUM_HOST_CORES) { | ||
1615 | MDDI_MSG_ERR("Invalid host core index\n"); | ||
1616 | return; | ||
1617 | } | ||
1618 | |||
1619 | if (!initialized) { | ||
1620 | uint16 idx; | ||
1621 | mddi_host_type host; | ||
1622 | for (host = MDDI_HOST_PRIM; host < MDDI_NUM_HOST_CORES; host++) { | ||
1623 | pmhctl = &(mhctl[host]); | ||
1624 | initialized = TRUE; | ||
1625 | |||
1626 | pmhctl->llist_ptr = | ||
1627 | dma_alloc_coherent(NULL, MDDI_LLIST_POOL_SIZE, | ||
1628 | &(pmhctl->llist_dma_addr), | ||
1629 | GFP_KERNEL); | ||
1630 | pmhctl->llist_dma_ptr = | ||
1631 | (mddi_linked_list_type *) (void *)pmhctl-> | ||
1632 | llist_dma_addr; | ||
1633 | #ifdef FEATURE_MDDI_DISABLE_REVERSE | ||
1634 | pmhctl->rev_data_buf = NULL; | ||
1635 | if (pmhctl->llist_ptr == NULL) | ||
1636 | #else | ||
1637 | mddi_rev_user.waiting = FALSE; | ||
1638 | init_completion(&(mddi_rev_user.done_comp)); | ||
1639 | pmhctl->rev_data_buf = | ||
1640 | dma_alloc_coherent(NULL, MDDI_MAX_REV_DATA_SIZE, | ||
1641 | &(pmhctl->rev_data_dma_addr), | ||
1642 | GFP_KERNEL); | ||
1643 | if ((pmhctl->llist_ptr == NULL) | ||
1644 | || (pmhctl->rev_data_buf == NULL)) | ||
1645 | #endif | ||
1646 | { | ||
1647 | MDDI_MSG_CRIT | ||
1648 | ("unable to alloc non-cached memory\n"); | ||
1649 | } | ||
1650 | llist_extern[host] = pmhctl->llist_ptr; | ||
1651 | llist_dma_extern[host] = pmhctl->llist_dma_ptr; | ||
1652 | llist_extern_notify[host] = pmhctl->llist_notify; | ||
1653 | |||
1654 | for (idx = 0; idx < UNASSIGNED_INDEX; idx++) { | ||
1655 | init_completion(& | ||
1656 | (pmhctl->llist_notify[idx]. | ||
1657 | done_comp)); | ||
1658 | } | ||
1659 | init_completion(&(pmhctl->mddi_llist_avail_comp)); | ||
1660 | spin_lock_init(&mddi_host_spin_lock); | ||
1661 | pmhctl->mddi_waiting_for_llist_avail = FALSE; | ||
1662 | pmhctl->mddi_rev_ptr_write_val = | ||
1663 | (uint32) (void *)(pmhctl->rev_data_dma_addr); | ||
1664 | pmhctl->rev_ptr_start = (void *)pmhctl->rev_data_buf; | ||
1665 | |||
1666 | pmhctl->rev_pkt_size = MDDI_DEFAULT_REV_PKT_SIZE; | ||
1667 | pmhctl->rev_state = MDDI_REV_IDLE; | ||
1668 | #ifdef IMAGE_MODEM_PROC | ||
1669 | /* assume hibernation state is last state from APPS proc, so that | ||
1670 | * we don't reinitialize the host core */ | ||
1671 | pmhctl->link_state = MDDI_LINK_HIBERNATING; | ||
1672 | #else | ||
1673 | pmhctl->link_state = MDDI_LINK_DISABLED; | ||
1674 | #endif | ||
1675 | pmhctl->driver_state = MDDI_DRIVER_DISABLED; | ||
1676 | pmhctl->disable_hibernation = FALSE; | ||
1677 | |||
1678 | /* initialize llist variables */ | ||
1679 | pmhctl->llist_info.transmitting_start_idx = | ||
1680 | UNASSIGNED_INDEX; | ||
1681 | pmhctl->llist_info.transmitting_end_idx = | ||
1682 | UNASSIGNED_INDEX; | ||
1683 | pmhctl->llist_info.waiting_start_idx = UNASSIGNED_INDEX; | ||
1684 | pmhctl->llist_info.waiting_end_idx = UNASSIGNED_INDEX; | ||
1685 | pmhctl->llist_info.reg_read_idx = UNASSIGNED_INDEX; | ||
1686 | pmhctl->llist_info.next_free_idx = | ||
1687 | MDDI_FIRST_DYNAMIC_LLIST_IDX; | ||
1688 | pmhctl->llist_info.reg_read_waiting = FALSE; | ||
1689 | |||
1690 | mddi_vsync_detect_enabled = FALSE; | ||
1691 | mddi_gpio.polling_enabled = FALSE; | ||
1692 | |||
1693 | pmhctl->int_type.count = 0; | ||
1694 | pmhctl->int_type.in_count = 0; | ||
1695 | pmhctl->int_type.disp_req_count = 0; | ||
1696 | pmhctl->int_type.state_change_count = 0; | ||
1697 | pmhctl->int_type.ll_done_count = 0; | ||
1698 | pmhctl->int_type.rev_avail_count = 0; | ||
1699 | pmhctl->int_type.error_count = 0; | ||
1700 | pmhctl->int_type.rev_encap_count = 0; | ||
1701 | pmhctl->int_type.llist_ptr_write_1 = 0; | ||
1702 | pmhctl->int_type.llist_ptr_write_2 = 0; | ||
1703 | |||
1704 | pmhctl->stats.fwd_crc_count = 0; | ||
1705 | pmhctl->stats.rev_crc_count = 0; | ||
1706 | pmhctl->stats.pri_underflow = 0; | ||
1707 | pmhctl->stats.sec_underflow = 0; | ||
1708 | pmhctl->stats.rev_overflow = 0; | ||
1709 | pmhctl->stats.pri_overwrite = 0; | ||
1710 | pmhctl->stats.sec_overwrite = 0; | ||
1711 | pmhctl->stats.rev_overwrite = 0; | ||
1712 | pmhctl->stats.dma_failure = 0; | ||
1713 | pmhctl->stats.rtd_failure = 0; | ||
1714 | pmhctl->stats.reg_read_failure = 0; | ||
1715 | #ifdef FEATURE_MDDI_UNDERRUN_RECOVERY | ||
1716 | pmhctl->stats.pri_underrun_detected = 0; | ||
1717 | #endif | ||
1718 | |||
1719 | pmhctl->log_parms.rtd_cnt = 0; | ||
1720 | pmhctl->log_parms.rev_enc_cnt = 0; | ||
1721 | pmhctl->log_parms.vid_cnt = 0; | ||
1722 | pmhctl->log_parms.reg_acc_cnt = 0; | ||
1723 | pmhctl->log_parms.cli_stat_cnt = 0; | ||
1724 | pmhctl->log_parms.cli_cap_cnt = 0; | ||
1725 | pmhctl->log_parms.reg_read_cnt = 0; | ||
1726 | pmhctl->log_parms.link_active_cnt = 0; | ||
1727 | pmhctl->log_parms.link_hibernate_cnt = 0; | ||
1728 | pmhctl->log_parms.fwd_crc_cnt = 0; | ||
1729 | pmhctl->log_parms.rev_crc_cnt = 0; | ||
1730 | pmhctl->log_parms.vsync_response_cnt = 0; | ||
1731 | |||
1732 | prev_parms[host_idx] = pmhctl->log_parms; | ||
1733 | mddi_client_capability_pkt.packet_length = 0; | ||
1734 | } | ||
1735 | |||
1736 | #ifndef T_MSM7500 | ||
1737 | /* tell clock driver we are user of this PLL */ | ||
1738 | MDDI_HOST_ENABLE_IO_CLOCK; | ||
1739 | #endif | ||
1740 | } | ||
1741 | |||
1742 | mddi_host_powerup(host_idx); | ||
1743 | pmhctl = &(mhctl[host_idx]); | ||
1744 | } | ||
1745 | |||
1746 | #ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT | ||
1747 | static uint32 mddi_client_id; | ||
1748 | |||
1749 | uint32 mddi_get_client_id(void) | ||
1750 | { | ||
1751 | |||
1752 | #ifndef FEATURE_MDDI_DISABLE_REVERSE | ||
1753 | mddi_host_type host_idx = MDDI_HOST_PRIM; | ||
1754 | static boolean client_detection_try = FALSE; | ||
1755 | mddi_host_cntl_type *pmhctl; | ||
1756 | unsigned long flags; | ||
1757 | uint16 saved_rev_pkt_size; | ||
1758 | |||
1759 | if (!client_detection_try) { | ||
1760 | /* Toshiba display requires larger drive_lo value */ | ||
1761 | mddi_host_reg_out(DRIVE_LO, 0x0050); | ||
1762 | |||
1763 | pmhctl = &(mhctl[MDDI_HOST_PRIM]); | ||
1764 | |||
1765 | saved_rev_pkt_size = pmhctl->rev_pkt_size; | ||
1766 | |||
1767 | /* Increase Rev Encap Size */ | ||
1768 | pmhctl->rev_pkt_size = MDDI_CLIENT_CAPABILITY_REV_PKT_SIZE; | ||
1769 | mddi_host_reg_out(REV_ENCAP_SZ, pmhctl->rev_pkt_size); | ||
1770 | |||
1771 | /* disable hibernation temporarily */ | ||
1772 | if (!pmhctl->disable_hibernation) | ||
1773 | mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE); | ||
1774 | |||
1775 | mddi_rev_user.waiting = TRUE; | ||
1776 | INIT_COMPLETION(mddi_rev_user.done_comp); | ||
1777 | |||
1778 | spin_lock_irqsave(&mddi_host_spin_lock, flags); | ||
1779 | |||
1780 | /* turn on clock(s), if they have been disabled */ | ||
1781 | mddi_host_enable_hclk(); | ||
1782 | mddi_host_enable_io_clock(); | ||
1783 | |||
1784 | mddi_client_capability_request = TRUE; | ||
1785 | |||
1786 | if (pmhctl->rev_state == MDDI_REV_IDLE) { | ||
1787 | /* attempt to send the reverse encapsulation now */ | ||
1788 | mddi_issue_reverse_encapsulation(); | ||
1789 | } | ||
1790 | spin_unlock_irqrestore(&mddi_host_spin_lock, flags); | ||
1791 | |||
1792 | wait_for_completion_killable(&(mddi_rev_user.done_comp)); | ||
1793 | |||
1794 | /* Set Rev Encap Size back to its original value */ | ||
1795 | pmhctl->rev_pkt_size = saved_rev_pkt_size; | ||
1796 | mddi_host_reg_out(REV_ENCAP_SZ, pmhctl->rev_pkt_size); | ||
1797 | |||
1798 | /* reenable auto-hibernate */ | ||
1799 | if (!pmhctl->disable_hibernation) | ||
1800 | mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE | 1); | ||
1801 | |||
1802 | mddi_host_reg_out(DRIVE_LO, 0x0032); | ||
1803 | client_detection_try = TRUE; | ||
1804 | |||
1805 | mddi_client_id = (mddi_client_capability_pkt.Mfr_Name<<16) | | ||
1806 | mddi_client_capability_pkt.Product_Code; | ||
1807 | |||
1808 | if (!mddi_client_id) | ||
1809 | mddi_disable(1); | ||
1810 | } | ||
1811 | |||
1812 | #if 0 | ||
1813 | switch (mddi_client_capability_pkt.Mfr_Name) { | ||
1814 | case 0x4474: | ||
1815 | if ((mddi_client_capability_pkt.Product_Code != 0x8960) && | ||
1816 | (target == DISPLAY_1)) { | ||
1817 | ret = PRISM_WVGA; | ||
1818 | } | ||
1819 | break; | ||
1820 | |||
1821 | case 0xD263: | ||
1822 | if (target == DISPLAY_1) | ||
1823 | ret = TOSHIBA_VGA_PRIM; | ||
1824 | else if (target == DISPLAY_2) | ||
1825 | ret = TOSHIBA_QCIF_SECD; | ||
1826 | break; | ||
1827 | |||
1828 | case 0: | ||
1829 | if (mddi_client_capability_pkt.Product_Code == 0x8835) { | ||
1830 | if (target == DISPLAY_1) | ||
1831 | ret = SHARP_QVGA_PRIM; | ||
1832 | else if (target == DISPLAY_2) | ||
1833 | ret = SHARP_128x128_SECD; | ||
1834 | } | ||
1835 | break; | ||
1836 | |||
1837 | default: | ||
1838 | break; | ||
1839 | } | ||
1840 | |||
1841 | if ((!client_detection_try) && (ret != TOSHIBA_VGA_PRIM) | ||
1842 | && (ret != TOSHIBA_QCIF_SECD)) { | ||
1843 | /* Not a Toshiba display, so change drive_lo back to default value */ | ||
1844 | mddi_host_reg_out(DRIVE_LO, 0x0032); | ||
1845 | } | ||
1846 | #endif | ||
1847 | |||
1848 | #endif | ||
1849 | |||
1850 | return mddi_client_id; | ||
1851 | } | ||
1852 | #endif | ||
1853 | |||
1854 | void mddi_host_powerdown(mddi_host_type host_idx) | ||
1855 | { | ||
1856 | mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); | ||
1857 | |||
1858 | if (host_idx >= MDDI_NUM_HOST_CORES) { | ||
1859 | MDDI_MSG_ERR("Invalid host core index\n"); | ||
1860 | return; | ||
1861 | } | ||
1862 | |||
1863 | if (pmhctl->driver_state == MDDI_DRIVER_RESET) { | ||
1864 | return; | ||
1865 | } | ||
1866 | |||
1867 | if (host_idx == MDDI_HOST_PRIM) { | ||
1868 | /* disable timer */ | ||
1869 | del_timer(&mddi_host_timer); | ||
1870 | } | ||
1871 | |||
1872 | mddi_host_configure_interrupts(host_idx, FALSE); | ||
1873 | |||
1874 | /* turn on HCLK to MDDI host core if it has been disabled */ | ||
1875 | mddi_host_enable_hclk(); | ||
1876 | |||
1877 | /* MDDI Reset command */ | ||
1878 | mddi_host_reg_out(CMD, MDDI_CMD_RESET); | ||
1879 | |||
1880 | /* Pad Control Register */ | ||
1881 | mddi_host_reg_out(PAD_CTL, 0x0); | ||
1882 | |||
1883 | /* disable IO_CLK and hclk to MDDI host core */ | ||
1884 | mddi_host_disable_io_clock(); | ||
1885 | mddi_host_disable_hclk(); | ||
1886 | |||
1887 | pmhctl->link_state = MDDI_LINK_DISABLED; | ||
1888 | pmhctl->driver_state = MDDI_DRIVER_RESET; | ||
1889 | |||
1890 | MDDI_MSG_NOTICE("MDDI Host: Disabling Link\n"); | ||
1891 | |||
1892 | } | ||
1893 | |||
1894 | uint16 mddi_get_next_free_llist_item(mddi_host_type host_idx, boolean wait) | ||
1895 | { | ||
1896 | unsigned long flags; | ||
1897 | uint16 ret_idx; | ||
1898 | boolean forced_wait = FALSE; | ||
1899 | mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); | ||
1900 | |||
1901 | ret_idx = pmhctl->llist_info.next_free_idx; | ||
1902 | |||
1903 | pmhctl->llist_info.next_free_idx++; | ||
1904 | if (pmhctl->llist_info.next_free_idx >= MDDI_NUM_DYNAMIC_LLIST_ITEMS) | ||
1905 | pmhctl->llist_info.next_free_idx = MDDI_FIRST_DYNAMIC_LLIST_IDX; | ||
1906 | spin_lock_irqsave(&mddi_host_spin_lock, flags); | ||
1907 | if (pmhctl->llist_notify[ret_idx].in_use) { | ||
1908 | if (!wait) { | ||
1909 | pmhctl->llist_info.next_free_idx = ret_idx; | ||
1910 | ret_idx = UNASSIGNED_INDEX; | ||
1911 | } else { | ||
1912 | forced_wait = TRUE; | ||
1913 | INIT_COMPLETION(pmhctl->mddi_llist_avail_comp); | ||
1914 | } | ||
1915 | } | ||
1916 | spin_unlock_irqrestore(&mddi_host_spin_lock, flags); | ||
1917 | |||
1918 | if (forced_wait) { | ||
1919 | wait_for_completion_killable(& | ||
1920 | (pmhctl-> | ||
1921 | mddi_llist_avail_comp)); | ||
1922 | MDDI_MSG_ERR("task waiting on mddi llist item\n"); | ||
1923 | } | ||
1924 | |||
1925 | if (ret_idx != UNASSIGNED_INDEX) { | ||
1926 | pmhctl->llist_notify[ret_idx].waiting = FALSE; | ||
1927 | pmhctl->llist_notify[ret_idx].done_cb = NULL; | ||
1928 | pmhctl->llist_notify[ret_idx].in_use = TRUE; | ||
1929 | pmhctl->llist_notify[ret_idx].next_idx = UNASSIGNED_INDEX; | ||
1930 | } | ||
1931 | |||
1932 | return ret_idx; | ||
1933 | } | ||
1934 | |||
1935 | uint16 mddi_get_reg_read_llist_item(mddi_host_type host_idx, boolean wait) | ||
1936 | { | ||
1937 | #ifdef FEATURE_MDDI_DISABLE_REVERSE | ||
1938 | MDDI_MSG_CRIT("No reverse link available\n"); | ||
1939 | (void)wait; | ||
1940 | return FALSE; | ||
1941 | #else | ||
1942 | unsigned long flags; | ||
1943 | uint16 ret_idx; | ||
1944 | boolean error = FALSE; | ||
1945 | mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); | ||
1946 | |||
1947 | spin_lock_irqsave(&mddi_host_spin_lock, flags); | ||
1948 | if (pmhctl->llist_info.reg_read_idx != UNASSIGNED_INDEX) { | ||
1949 | /* need to block here or is this an error condition? */ | ||
1950 | error = TRUE; | ||
1951 | ret_idx = UNASSIGNED_INDEX; | ||
1952 | } | ||
1953 | spin_unlock_irqrestore(&mddi_host_spin_lock, flags); | ||
1954 | |||
1955 | if (!error) { | ||
1956 | ret_idx = pmhctl->llist_info.reg_read_idx = | ||
1957 | mddi_get_next_free_llist_item(host_idx, wait); | ||
1958 | /* clear the reg_read_waiting flag */ | ||
1959 | pmhctl->llist_info.reg_read_waiting = FALSE; | ||
1960 | } | ||
1961 | |||
1962 | if (error) | ||
1963 | MDDI_MSG_ERR("***** Reg read still in progress! ****\n"); | ||
1964 | return ret_idx; | ||
1965 | #endif | ||
1966 | |||
1967 | } | ||
1968 | |||
1969 | void mddi_queue_forward_packets(uint16 first_llist_idx, | ||
1970 | uint16 last_llist_idx, | ||
1971 | boolean wait, | ||
1972 | mddi_llist_done_cb_type llist_done_cb, | ||
1973 | mddi_host_type host_idx) | ||
1974 | { | ||
1975 | unsigned long flags; | ||
1976 | mddi_linked_list_type *llist; | ||
1977 | mddi_linked_list_type *llist_dma; | ||
1978 | mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); | ||
1979 | |||
1980 | if ((first_llist_idx >= UNASSIGNED_INDEX) || | ||
1981 | (last_llist_idx >= UNASSIGNED_INDEX)) { | ||
1982 | MDDI_MSG_ERR("MDDI queueing invalid linked list\n"); | ||
1983 | return; | ||
1984 | } | ||
1985 | |||
1986 | if (pmhctl->link_state == MDDI_LINK_DISABLED) | ||
1987 | MDDI_MSG_CRIT("MDDI host powered down!\n"); | ||
1988 | |||
1989 | llist = pmhctl->llist_ptr; | ||
1990 | llist_dma = pmhctl->llist_dma_ptr; | ||
1991 | |||
1992 | /* clean cache so MDDI host can read data */ | ||
1993 | memory_barrier(); | ||
1994 | |||
1995 | pmhctl->llist_notify[last_llist_idx].waiting = wait; | ||
1996 | if (wait) | ||
1997 | INIT_COMPLETION(pmhctl->llist_notify[last_llist_idx].done_comp); | ||
1998 | pmhctl->llist_notify[last_llist_idx].done_cb = llist_done_cb; | ||
1999 | |||
2000 | spin_lock_irqsave(&mddi_host_spin_lock, flags); | ||
2001 | |||
2002 | if ((pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) && | ||
2003 | (pmhctl->llist_info.waiting_start_idx == UNASSIGNED_INDEX) && | ||
2004 | (pmhctl->rev_state == MDDI_REV_IDLE)) { | ||
2005 | /* no packets are currently transmitting */ | ||
2006 | #ifndef FEATURE_MDDI_DISABLE_REVERSE | ||
2007 | if (first_llist_idx == pmhctl->llist_info.reg_read_idx) { | ||
2008 | /* This is the special case where the packet is a register read. */ | ||
2009 | pmhctl->rev_state = MDDI_REV_REG_READ_ISSUED; | ||
2010 | mddi_reg_read_retry = 0; | ||
2011 | /* mddi_rev_reg_read_attempt = 1; */ | ||
2012 | } | ||
2013 | #endif | ||
2014 | /* assign transmitting index values */ | ||
2015 | pmhctl->llist_info.transmitting_start_idx = first_llist_idx; | ||
2016 | pmhctl->llist_info.transmitting_end_idx = last_llist_idx; | ||
2017 | |||
2018 | /* turn on clock(s), if they have been disabled */ | ||
2019 | mddi_host_enable_hclk(); | ||
2020 | mddi_host_enable_io_clock(); | ||
2021 | pmhctl->int_type.llist_ptr_write_1++; | ||
2022 | /* Write to primary pointer register */ | ||
2023 | dma_coherent_pre_ops(); | ||
2024 | mddi_host_reg_out(PRI_PTR, &llist_dma[first_llist_idx]); | ||
2025 | |||
2026 | /* enable interrupt when complete */ | ||
2027 | mddi_host_reg_outm(INTEN, MDDI_INT_PRI_LINK_LIST_DONE, | ||
2028 | MDDI_INT_PRI_LINK_LIST_DONE); | ||
2029 | |||
2030 | } else if (pmhctl->llist_info.waiting_start_idx == UNASSIGNED_INDEX) { | ||
2031 | #ifndef FEATURE_MDDI_DISABLE_REVERSE | ||
2032 | if (first_llist_idx == pmhctl->llist_info.reg_read_idx) { | ||
2033 | /* | ||
2034 | * we have a register read to send but need to wait | ||
2035 | * for current reverse activity to end or there are | ||
2036 | * packets currently transmitting | ||
2037 | */ | ||
2038 | /* mddi_rev_reg_read_attempt = 0; */ | ||
2039 | pmhctl->llist_info.reg_read_waiting = TRUE; | ||
2040 | } | ||
2041 | #endif | ||
2042 | |||
2043 | /* assign waiting index values */ | ||
2044 | pmhctl->llist_info.waiting_start_idx = first_llist_idx; | ||
2045 | pmhctl->llist_info.waiting_end_idx = last_llist_idx; | ||
2046 | } else { | ||
2047 | uint16 prev_end_idx = pmhctl->llist_info.waiting_end_idx; | ||
2048 | #ifndef FEATURE_MDDI_DISABLE_REVERSE | ||
2049 | if (first_llist_idx == pmhctl->llist_info.reg_read_idx) { | ||
2050 | /* | ||
2051 | * we have a register read to send but need to wait | ||
2052 | * for current reverse activity to end or there are | ||
2053 | * packets currently transmitting | ||
2054 | */ | ||
2055 | /* mddi_rev_reg_read_attempt = 0; */ | ||
2056 | pmhctl->llist_info.reg_read_waiting = TRUE; | ||
2057 | } | ||
2058 | #endif | ||
2059 | |||
2060 | llist = pmhctl->llist_ptr; | ||
2061 | |||
2062 | /* clear end flag in previous last packet */ | ||
2063 | llist[prev_end_idx].link_controller_flags = 0; | ||
2064 | pmhctl->llist_notify[prev_end_idx].next_idx = first_llist_idx; | ||
2065 | |||
2066 | /* set the next_packet_pointer of the previous last packet */ | ||
2067 | llist[prev_end_idx].next_packet_pointer = | ||
2068 | (void *)(&llist_dma[first_llist_idx]); | ||
2069 | |||
2070 | /* clean cache so MDDI host can read data */ | ||
2071 | memory_barrier(); | ||
2072 | |||
2073 | /* assign new waiting last index value */ | ||
2074 | pmhctl->llist_info.waiting_end_idx = last_llist_idx; | ||
2075 | } | ||
2076 | |||
2077 | spin_unlock_irqrestore(&mddi_host_spin_lock, flags); | ||
2078 | |||
2079 | } | ||
2080 | |||
2081 | void mddi_host_write_pix_attr_reg(uint32 value) | ||
2082 | { | ||
2083 | (void)value; | ||
2084 | } | ||
2085 | |||
2086 | void mddi_queue_reverse_encapsulation(boolean wait) | ||
2087 | { | ||
2088 | #ifdef FEATURE_MDDI_DISABLE_REVERSE | ||
2089 | MDDI_MSG_CRIT("No reverse link available\n"); | ||
2090 | (void)wait; | ||
2091 | #else | ||
2092 | unsigned long flags; | ||
2093 | boolean error = FALSE; | ||
2094 | mddi_host_type host_idx = MDDI_HOST_PRIM; | ||
2095 | mddi_host_cntl_type *pmhctl = &(mhctl[MDDI_HOST_PRIM]); | ||
2096 | |||
2097 | spin_lock_irqsave(&mddi_host_spin_lock, flags); | ||
2098 | |||
2099 | /* turn on clock(s), if they have been disabled */ | ||
2100 | mddi_host_enable_hclk(); | ||
2101 | mddi_host_enable_io_clock(); | ||
2102 | |||
2103 | if (wait) { | ||
2104 | if (!mddi_rev_user.waiting) { | ||
2105 | mddi_rev_user.waiting = TRUE; | ||
2106 | INIT_COMPLETION(mddi_rev_user.done_comp); | ||
2107 | } else | ||
2108 | error = TRUE; | ||
2109 | } | ||
2110 | mddi_rev_encap_user_request = TRUE; | ||
2111 | |||
2112 | if (pmhctl->rev_state == MDDI_REV_IDLE) { | ||
2113 | /* attempt to send the reverse encapsulation now */ | ||
2114 | mddi_host_type orig_host_idx = mddi_curr_host; | ||
2115 | mddi_curr_host = host_idx; | ||
2116 | mddi_issue_reverse_encapsulation(); | ||
2117 | mddi_curr_host = orig_host_idx; | ||
2118 | } | ||
2119 | spin_unlock_irqrestore(&mddi_host_spin_lock, flags); | ||
2120 | |||
2121 | if (error) { | ||
2122 | MDDI_MSG_ERR("Reverse Encap request already in progress\n"); | ||
2123 | } else if (wait) | ||
2124 | wait_for_completion_killable(&(mddi_rev_user.done_comp)); | ||
2125 | #endif | ||
2126 | } | ||
2127 | |||
2128 | /* ISR to be executed */ | ||
2129 | boolean mddi_set_rev_handler(mddi_rev_handler_type handler, uint16 pkt_type) | ||
2130 | { | ||
2131 | #ifdef FEATURE_MDDI_DISABLE_REVERSE | ||
2132 | MDDI_MSG_CRIT("No reverse link available\n"); | ||
2133 | (void)handler; | ||
2134 | (void)pkt_type; | ||
2135 | return (FALSE); | ||
2136 | #else | ||
2137 | unsigned long flags; | ||
2138 | uint16 hdlr; | ||
2139 | boolean handler_set = FALSE; | ||
2140 | boolean overwrite = FALSE; | ||
2141 | mddi_host_type host_idx = MDDI_HOST_PRIM; | ||
2142 | mddi_host_cntl_type *pmhctl = &(mhctl[MDDI_HOST_PRIM]); | ||
2143 | |||
2144 | /* Disable interrupts */ | ||
2145 | spin_lock_irqsave(&mddi_host_spin_lock, flags); | ||
2146 | |||
2147 | for (hdlr = 0; hdlr < MAX_MDDI_REV_HANDLERS; hdlr++) { | ||
2148 | if (mddi_rev_pkt_handler[hdlr].pkt_type == pkt_type) { | ||
2149 | mddi_rev_pkt_handler[hdlr].handler = handler; | ||
2150 | if (handler == NULL) { | ||
2151 | /* clearing handler from table */ | ||
2152 | mddi_rev_pkt_handler[hdlr].pkt_type = | ||
2153 | INVALID_PKT_TYPE; | ||
2154 | handler_set = TRUE; | ||
2155 | if (pkt_type == 0x10) { /* video stream packet */ | ||
2156 | /* ensure HCLK on to MDDI host core before register write */ | ||
2157 | mddi_host_enable_hclk(); | ||
2158 | /* No longer getting video, so reset rev encap size to default */ | ||
2159 | pmhctl->rev_pkt_size = | ||
2160 | MDDI_DEFAULT_REV_PKT_SIZE; | ||
2161 | mddi_host_reg_out(REV_ENCAP_SZ, | ||
2162 | pmhctl->rev_pkt_size); | ||
2163 | } | ||
2164 | } else { | ||
2165 | /* already a handler for this packet */ | ||
2166 | overwrite = TRUE; | ||
2167 | } | ||
2168 | break; | ||
2169 | } | ||
2170 | } | ||
2171 | if ((hdlr >= MAX_MDDI_REV_HANDLERS) && (handler != NULL)) { | ||
2172 | /* assigning new handler */ | ||
2173 | for (hdlr = 0; hdlr < MAX_MDDI_REV_HANDLERS; hdlr++) { | ||
2174 | if (mddi_rev_pkt_handler[hdlr].pkt_type == | ||
2175 | INVALID_PKT_TYPE) { | ||
2176 | if ((pkt_type == 0x10) && /* video stream packet */ | ||
2177 | (pmhctl->rev_pkt_size < | ||
2178 | MDDI_VIDEO_REV_PKT_SIZE)) { | ||
2179 | /* ensure HCLK on to MDDI host core before register write */ | ||
2180 | mddi_host_enable_hclk(); | ||
2181 | /* Increase Rev Encap Size */ | ||
2182 | pmhctl->rev_pkt_size = | ||
2183 | MDDI_VIDEO_REV_PKT_SIZE; | ||
2184 | mddi_host_reg_out(REV_ENCAP_SZ, | ||
2185 | pmhctl->rev_pkt_size); | ||
2186 | } | ||
2187 | mddi_rev_pkt_handler[hdlr].handler = handler; | ||
2188 | mddi_rev_pkt_handler[hdlr].pkt_type = pkt_type; | ||
2189 | handler_set = TRUE; | ||
2190 | break; | ||
2191 | } | ||
2192 | } | ||
2193 | } | ||
2194 | |||
2195 | /* Restore interrupts */ | ||
2196 | spin_unlock_irqrestore(&mddi_host_spin_lock, flags); | ||
2197 | |||
2198 | if (overwrite) | ||
2199 | MDDI_MSG_ERR("Overwriting previous rev packet handler\n"); | ||
2200 | |||
2201 | return handler_set; | ||
2202 | |||
2203 | #endif | ||
2204 | } /* mddi_set_rev_handler */ | ||
2205 | |||
2206 | void mddi_host_disable_hibernation(boolean disable) | ||
2207 | { | ||
2208 | mddi_host_type host_idx = MDDI_HOST_PRIM; | ||
2209 | mddi_host_cntl_type *pmhctl = &(mhctl[MDDI_HOST_PRIM]); | ||
2210 | |||
2211 | if (disable) { | ||
2212 | pmhctl->disable_hibernation = TRUE; | ||
2213 | /* hibernation will be turned off by isr next time it is entered */ | ||
2214 | } else { | ||
2215 | if (pmhctl->disable_hibernation) { | ||
2216 | unsigned long flags; | ||
2217 | spin_lock_irqsave(&mddi_host_spin_lock, flags); | ||
2218 | if (!MDDI_HOST_IS_HCLK_ON) | ||
2219 | MDDI_HOST_ENABLE_HCLK; | ||
2220 | mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE | 1); | ||
2221 | spin_unlock_irqrestore(&mddi_host_spin_lock, flags); | ||
2222 | pmhctl->disable_hibernation = FALSE; | ||
2223 | } | ||
2224 | } | ||
2225 | } | ||
2226 | |||
2227 | void mddi_mhctl_remove(mddi_host_type host_idx) | ||
2228 | { | ||
2229 | mddi_host_cntl_type *pmhctl; | ||
2230 | |||
2231 | pmhctl = &(mhctl[host_idx]); | ||
2232 | |||
2233 | dma_free_coherent(NULL, MDDI_LLIST_POOL_SIZE, (void *)pmhctl->llist_ptr, | ||
2234 | pmhctl->llist_dma_addr); | ||
2235 | |||
2236 | dma_free_coherent(NULL, MDDI_MAX_REV_DATA_SIZE, | ||
2237 | (void *)pmhctl->rev_data_buf, | ||
2238 | pmhctl->rev_data_dma_addr); | ||
2239 | } | ||
diff --git a/drivers/staging/msm/mddihosti.h b/drivers/staging/msm/mddihosti.h new file mode 100644 index 000000000000..7b26a4253896 --- /dev/null +++ b/drivers/staging/msm/mddihosti.h | |||
@@ -0,0 +1,547 @@ | |||
1 | /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * Redistribution and use in source and binary forms, with or without | ||
4 | * modification, are permitted provided that the following conditions are met: | ||
5 | * * Redistributions of source code must retain the above copyright | ||
6 | * notice, this list of conditions and the following disclaimer. | ||
7 | * * Redistributions in binary form must reproduce the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer in the | ||
9 | * documentation and/or other materials provided with the distribution. | ||
10 | * * Neither the name of Code Aurora nor | ||
11 | * the names of its contributors may be used to endorse or promote | ||
12 | * products derived from this software without specific prior written | ||
13 | * permission. | ||
14 | * | ||
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
17 | * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
18 | * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||
19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||
20 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||
21 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | ||
22 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | ||
23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||
24 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | ||
25 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | * | ||
27 | */ | ||
28 | |||
29 | #ifndef MDDIHOSTI_H | ||
30 | #define MDDIHOSTI_H | ||
31 | |||
32 | #include "msm_fb.h" | ||
33 | #include "mddihost.h" | ||
34 | #include <linux/clk.h> | ||
35 | |||
36 | /* Register offsets in MDDI, applies to both msm_pmdh_base and | ||
37 | * (u32)msm_emdh_base. */ | ||
38 | #define MDDI_CMD 0x0000 | ||
39 | #define MDDI_VERSION 0x0004 | ||
40 | #define MDDI_PRI_PTR 0x0008 | ||
41 | #define MDDI_BPS 0x0010 | ||
42 | #define MDDI_SPM 0x0014 | ||
43 | #define MDDI_INT 0x0018 | ||
44 | #define MDDI_INTEN 0x001c | ||
45 | #define MDDI_REV_PTR 0x0020 | ||
46 | #define MDDI_REV_SIZE 0x0024 | ||
47 | #define MDDI_STAT 0x0028 | ||
48 | #define MDDI_REV_RATE_DIV 0x002c | ||
49 | #define MDDI_REV_CRC_ERR 0x0030 | ||
50 | #define MDDI_TA1_LEN 0x0034 | ||
51 | #define MDDI_TA2_LEN 0x0038 | ||
52 | #define MDDI_TEST 0x0040 | ||
53 | #define MDDI_REV_PKT_CNT 0x0044 | ||
54 | #define MDDI_DRIVE_HI 0x0048 | ||
55 | #define MDDI_DRIVE_LO 0x004c | ||
56 | #define MDDI_DISP_WAKE 0x0050 | ||
57 | #define MDDI_REV_ENCAP_SZ 0x0054 | ||
58 | #define MDDI_RTD_VAL 0x0058 | ||
59 | #define MDDI_PAD_CTL 0x0068 | ||
60 | #define MDDI_DRIVER_START_CNT 0x006c | ||
61 | #define MDDI_CORE_VER 0x008c | ||
62 | #define MDDI_FIFO_ALLOC 0x0090 | ||
63 | #define MDDI_PAD_IO_CTL 0x00a0 | ||
64 | #define MDDI_PAD_CAL 0x00a4 | ||
65 | |||
66 | extern u32 mddi_msg_level; | ||
67 | |||
68 | /* No longer need to write to clear these registers */ | ||
69 | #define xxxx_mddi_host_reg_outm(reg, mask, val) \ | ||
70 | do { \ | ||
71 | if (host_idx == MDDI_HOST_PRIM) \ | ||
72 | mddi_host_reg_outm_pmdh(reg, mask, val); \ | ||
73 | else \ | ||
74 | mddi_host_reg_outm_emdh(reg, mask, val); \ | ||
75 | } while (0) | ||
76 | |||
77 | #define mddi_host_reg_outm(reg, mask, val) \ | ||
78 | do { \ | ||
79 | unsigned long __addr; \ | ||
80 | if (host_idx == MDDI_HOST_PRIM) \ | ||
81 | __addr = (u32)msm_pmdh_base + MDDI_##reg; \ | ||
82 | else \ | ||
83 | __addr = (u32)msm_emdh_base + MDDI_##reg; \ | ||
84 | writel((readl(__addr) & ~(mask)) | ((val) & (mask)), __addr); \ | ||
85 | } while (0) | ||
86 | |||
87 | #define xxxx_mddi_host_reg_out(reg, val) \ | ||
88 | do { \ | ||
89 | if (host_idx == MDDI_HOST_PRIM) \ | ||
90 | mddi_host_reg_out_pmdh(reg, val); \ | ||
91 | else \ | ||
92 | mddi_host_reg_out_emdh(reg, val); \ | ||
93 | } while (0) | ||
94 | |||
95 | #define mddi_host_reg_out(reg, val) \ | ||
96 | do { \ | ||
97 | if (host_idx == MDDI_HOST_PRIM) \ | ||
98 | writel(val, (u32)msm_pmdh_base + MDDI_##reg); \ | ||
99 | else \ | ||
100 | writel(val, (u32)msm_emdh_base + MDDI_##reg); \ | ||
101 | } while (0) | ||
102 | |||
103 | #define xxxx_mddi_host_reg_in(reg) \ | ||
104 | ((host_idx) ? \ | ||
105 | mddi_host_reg_in_emdh(reg) : mddi_host_reg_in_pmdh(reg)); | ||
106 | |||
107 | #define mddi_host_reg_in(reg) \ | ||
108 | ((host_idx) ? \ | ||
109 | readl((u32)msm_emdh_base + MDDI_##reg) : \ | ||
110 | readl((u32)msm_pmdh_base + MDDI_##reg)) \ | ||
111 | |||
112 | #define xxxx_mddi_host_reg_inm(reg, mask) \ | ||
113 | ((host_idx) ? \ | ||
114 | mddi_host_reg_inm_emdh(reg, mask) : \ | ||
115 | mddi_host_reg_inm_pmdh(reg, mask);) | ||
116 | |||
117 | #define mddi_host_reg_inm(reg, mask) \ | ||
118 | ((host_idx) ? \ | ||
119 | readl((u32)msm_emdh_base + MDDI_##reg) & (mask) : \ | ||
120 | readl((u32)msm_pmdh_base + MDDI_##reg) & (mask)) \ | ||
121 | |||
122 | /* Using non-cacheable pmem, so do nothing */ | ||
123 | #define mddi_invalidate_cache_lines(addr_start, num_bytes) | ||
124 | /* | ||
125 | * Using non-cacheable pmem, so do nothing with cache | ||
126 | * but, ensure write goes out to memory | ||
127 | */ | ||
128 | #define mddi_flush_cache_lines(addr_start, num_bytes) \ | ||
129 | (void) addr_start; \ | ||
130 | (void) num_bytes; \ | ||
131 | memory_barrier() | ||
132 | |||
133 | /* Since this translates to Remote Procedure Calls to check on clock status | ||
134 | * just use a local variable to keep track of io_clock */ | ||
135 | #define MDDI_HOST_IS_IO_CLOCK_ON mddi_host_io_clock_on | ||
136 | #define MDDI_HOST_ENABLE_IO_CLOCK | ||
137 | #define MDDI_HOST_DISABLE_IO_CLOCK | ||
138 | #define MDDI_HOST_IS_HCLK_ON mddi_host_hclk_on | ||
139 | #define MDDI_HOST_ENABLE_HCLK | ||
140 | #define MDDI_HOST_DISABLE_HCLK | ||
141 | #define FEATURE_MDDI_HOST_IO_CLOCK_CONTROL_DISABLE | ||
142 | #define FEATURE_MDDI_HOST_HCLK_CONTROL_DISABLE | ||
143 | |||
144 | #define TRAMP_MDDI_HOST_ISR TRAMP_MDDI_PRI_ISR | ||
145 | #define TRAMP_MDDI_HOST_EXT_ISR TRAMP_MDDI_EXT_ISR | ||
146 | #define MDP_LINE_COUNT_BMSK 0x3ff | ||
147 | #define MDP_SYNC_STATUS 0x000c | ||
148 | #define MDP_LINE_COUNT \ | ||
149 | (readl(msm_mdp_base + MDP_SYNC_STATUS) & MDP_LINE_COUNT_BMSK) | ||
150 | |||
151 | /* MDP sends 256 pixel packets, so lower value hibernates more without | ||
152 | * significantly increasing latency of waiting for next subframe */ | ||
153 | #define MDDI_HOST_BYTES_PER_SUBFRAME 0x3C00 | ||
154 | |||
155 | #if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40) | ||
156 | #define MDDI_HOST_TA2_LEN 0x001a | ||
157 | #define MDDI_HOST_REV_RATE_DIV 0x0004 | ||
158 | #else | ||
159 | #define MDDI_HOST_TA2_LEN 0x000c | ||
160 | #define MDDI_HOST_REV_RATE_DIV 0x0002 | ||
161 | #endif | ||
162 | |||
163 | #define MDDI_MSG_EMERG(msg, ...) \ | ||
164 | if (mddi_msg_level > 0) \ | ||
165 | printk(KERN_EMERG msg, ## __VA_ARGS__); | ||
166 | #define MDDI_MSG_ALERT(msg, ...) \ | ||
167 | if (mddi_msg_level > 1) \ | ||
168 | printk(KERN_ALERT msg, ## __VA_ARGS__); | ||
169 | #define MDDI_MSG_CRIT(msg, ...) \ | ||
170 | if (mddi_msg_level > 2) \ | ||
171 | printk(KERN_CRIT msg, ## __VA_ARGS__); | ||
172 | #define MDDI_MSG_ERR(msg, ...) \ | ||
173 | if (mddi_msg_level > 3) \ | ||
174 | printk(KERN_ERR msg, ## __VA_ARGS__); | ||
175 | #define MDDI_MSG_WARNING(msg, ...) \ | ||
176 | if (mddi_msg_level > 4) \ | ||
177 | printk(KERN_WARNING msg, ## __VA_ARGS__); | ||
178 | #define MDDI_MSG_NOTICE(msg, ...) \ | ||
179 | if (mddi_msg_level > 5) \ | ||
180 | printk(KERN_NOTICE msg, ## __VA_ARGS__); | ||
181 | #define MDDI_MSG_INFO(msg, ...) \ | ||
182 | if (mddi_msg_level > 6) \ | ||
183 | printk(KERN_INFO msg, ## __VA_ARGS__); | ||
184 | #define MDDI_MSG_DEBUG(msg, ...) \ | ||
185 | if (mddi_msg_level > 7) \ | ||
186 | printk(KERN_DEBUG msg, ## __VA_ARGS__); | ||
187 | |||
188 | #define GCC_PACKED __attribute__((packed)) | ||
189 | typedef struct GCC_PACKED { | ||
190 | uint16 packet_length; | ||
191 | /* total # of bytes in the packet not including | ||
192 | the packet_length field. */ | ||
193 | |||
194 | uint16 packet_type; | ||
195 | /* A Packet Type of 70 identifies the packet as | ||
196 | a Client status Packet. */ | ||
197 | |||
198 | uint16 bClient_ID; | ||
199 | /* This field is reserved for future use and shall | ||
200 | be set to zero. */ | ||
201 | |||
202 | } mddi_rev_packet_type; | ||
203 | |||
204 | typedef struct GCC_PACKED { | ||
205 | uint16 packet_length; | ||
206 | /* total # of bytes in the packet not including | ||
207 | the packet_length field. */ | ||
208 | |||
209 | uint16 packet_type; | ||
210 | /* A Packet Type of 70 identifies the packet as | ||
211 | a Client status Packet. */ | ||
212 | |||
213 | uint16 bClient_ID; | ||
214 | /* This field is reserved for future use and shall | ||
215 | be set to zero. */ | ||
216 | |||
217 | uint16 reverse_link_request; | ||
218 | /* 16 bit unsigned integer with number of bytes client | ||
219 | needs in the * reverse encapsulation message | ||
220 | to transmit data. */ | ||
221 | |||
222 | uint8 crc_error_count; | ||
223 | uint8 capability_change; | ||
224 | uint16 graphics_busy_flags; | ||
225 | |||
226 | uint16 parameter_CRC; | ||
227 | /* 16-bit CRC of all the bytes in the packet | ||
228 | including Packet Length. */ | ||
229 | |||
230 | } mddi_client_status_type; | ||
231 | |||
232 | typedef struct GCC_PACKED { | ||
233 | uint16 packet_length; | ||
234 | /* total # of bytes in the packet not including | ||
235 | the packet_length field. */ | ||
236 | |||
237 | uint16 packet_type; | ||
238 | /* A Packet Type of 66 identifies the packet as | ||
239 | a Client Capability Packet. */ | ||
240 | |||
241 | uint16 bClient_ID; | ||
242 | /* This field is reserved for future use and | ||
243 | shall be set to zero. */ | ||
244 | |||
245 | uint16 Protocol_Version; | ||
246 | uint16 Minimum_Protocol_Version; | ||
247 | uint16 Data_Rate_Capability; | ||
248 | uint8 Interface_Type_Capability; | ||
249 | uint8 Number_of_Alt_Displays; | ||
250 | uint16 PostCal_Data_Rate; | ||
251 | uint16 Bitmap_Width; | ||
252 | uint16 Bitmap_Height; | ||
253 | uint16 Display_Window_Width; | ||
254 | uint16 Display_Window_Height; | ||
255 | uint32 Color_Map_Size; | ||
256 | uint16 Color_Map_RGB_Width; | ||
257 | uint16 RGB_Capability; | ||
258 | uint8 Monochrome_Capability; | ||
259 | uint8 Reserved_1; | ||
260 | uint16 Y_Cb_Cr_Capability; | ||
261 | uint16 Bayer_Capability; | ||
262 | uint16 Alpha_Cursor_Image_Planes; | ||
263 | uint32 Client_Feature_Capability_Indicators; | ||
264 | uint8 Maximum_Video_Frame_Rate_Capability; | ||
265 | uint8 Minimum_Video_Frame_Rate_Capability; | ||
266 | uint16 Minimum_Sub_frame_Rate; | ||
267 | uint16 Audio_Buffer_Depth; | ||
268 | uint16 Audio_Channel_Capability; | ||
269 | uint16 Audio_Sample_Rate_Capability; | ||
270 | uint8 Audio_Sample_Resolution; | ||
271 | uint8 Mic_Audio_Sample_Resolution; | ||
272 | uint16 Mic_Sample_Rate_Capability; | ||
273 | uint8 Keyboard_Data_Format; | ||
274 | uint8 pointing_device_data_format; | ||
275 | uint16 content_protection_type; | ||
276 | uint16 Mfr_Name; | ||
277 | uint16 Product_Code; | ||
278 | uint16 Reserved_3; | ||
279 | uint32 Serial_Number; | ||
280 | uint8 Week_of_Manufacture; | ||
281 | uint8 Year_of_Manufacture; | ||
282 | |||
283 | uint16 parameter_CRC; | ||
284 | /* 16-bit CRC of all the bytes in the packet including Packet Length. */ | ||
285 | |||
286 | } mddi_client_capability_type; | ||
287 | |||
288 | typedef struct GCC_PACKED { | ||
289 | uint16 packet_length; | ||
290 | /* total # of bytes in the packet not including the packet_length field. */ | ||
291 | |||
292 | uint16 packet_type; | ||
293 | /* A Packet Type of 16 identifies the packet as a Video Stream Packet. */ | ||
294 | |||
295 | uint16 bClient_ID; | ||
296 | /* This field is reserved for future use and shall be set to zero. */ | ||
297 | |||
298 | uint16 video_data_format_descriptor; | ||
299 | /* format of each pixel in the Pixel Data in the present stream in the | ||
300 | * present packet. | ||
301 | * If bits [15:13] = 000 monochrome | ||
302 | * If bits [15:13] = 001 color pixels (palette). | ||
303 | * If bits [15:13] = 010 color pixels in raw RGB | ||
304 | * If bits [15:13] = 011 data in 4:2:2 Y Cb Cr format | ||
305 | * If bits [15:13] = 100 Bayer pixels | ||
306 | */ | ||
307 | |||
308 | uint16 pixel_data_attributes; | ||
309 | /* interpreted as follows: | ||
310 | * Bits [1:0] = 11 pixel data is displayed to both eyes | ||
311 | * Bits [1:0] = 10 pixel data is routed to the left eye only. | ||
312 | * Bits [1:0] = 01 pixel data is routed to the right eye only. | ||
313 | * Bits [1:0] = 00 pixel data is routed to the alternate display. | ||
314 | * Bit 2 is 0 Pixel Data is in the standard progressive format. | ||
315 | * Bit 2 is 1 Pixel Data is in interlace format. | ||
316 | * Bit 3 is 0 Pixel Data is in the standard progressive format. | ||
317 | * Bit 3 is 1 Pixel Data is in alternate pixel format. | ||
318 | * Bit 4 is 0 Pixel Data is to or from the display frame buffer. | ||
319 | * Bit 4 is 1 Pixel Data is to or from the camera. | ||
320 | * Bit 5 is 0 pixel data contains the next consecutive row of pixels. | ||
321 | * Bit 5 is 1 X Left Edge, Y Top Edge, X Right Edge, Y Bottom Edge, | ||
322 | * X Start, and Y Start parameters are not defined and | ||
323 | * shall be ignored by the client. | ||
324 | * Bits [7:6] = 01 Pixel data is written to the offline image buffer. | ||
325 | * Bits [7:6] = 00 Pixel data is written to the buffer to refresh display. | ||
326 | * Bits [7:6] = 11 Pixel data is written to all image buffers. | ||
327 | * Bits [7:6] = 10 Invalid. Reserved for future use. | ||
328 | * Bits 8 through 11 alternate display number. | ||
329 | * Bits 12 through 14 are reserved for future use and shall be set to zero. | ||
330 | * Bit 15 is 1 the row of pixels is the last row of pixels in a frame. | ||
331 | */ | ||
332 | |||
333 | uint16 x_left_edge; | ||
334 | uint16 y_top_edge; | ||
335 | /* X,Y coordinate of the top left edge of the screen window */ | ||
336 | |||
337 | uint16 x_right_edge; | ||
338 | uint16 y_bottom_edge; | ||
339 | /* X,Y coordinate of the bottom right edge of the window being updated. */ | ||
340 | |||
341 | uint16 x_start; | ||
342 | uint16 y_start; | ||
343 | /* (X Start, Y Start) is the first pixel in the Pixel Data field below. */ | ||
344 | |||
345 | uint16 pixel_count; | ||
346 | /* number of pixels in the Pixel Data field below. */ | ||
347 | |||
348 | uint16 parameter_CRC; | ||
349 | /* 16-bit CRC of all bytes from the Packet Length to the Pixel Count. */ | ||
350 | |||
351 | uint16 reserved; | ||
352 | /* 16-bit variable to make structure align on 4 byte boundary */ | ||
353 | |||
354 | } mddi_video_stream_packet_type; | ||
355 | |||
356 | typedef struct GCC_PACKED { | ||
357 | uint16 packet_length; | ||
358 | /* total # of bytes in the packet not including the packet_length field. */ | ||
359 | |||
360 | uint16 packet_type; | ||
361 | /* A Packet Type of 146 identifies the packet as a Register Access Packet. */ | ||
362 | |||
363 | uint16 bClient_ID; | ||
364 | /* This field is reserved for future use and shall be set to zero. */ | ||
365 | |||
366 | uint16 read_write_info; | ||
367 | /* Bits 13:0 a 14-bit unsigned integer that specifies the number of | ||
368 | * 32-bit Register Data List items to be transferred in the | ||
369 | * Register Data List field. | ||
370 | * Bits[15:14] = 00 Write to register(s); | ||
371 | * Bits[15:14] = 10 Read from register(s); | ||
372 | * Bits[15:14] = 11 Response to a Read. | ||
373 | * Bits[15:14] = 01 this value is reserved for future use. */ | ||
374 | |||
375 | uint32 register_address; | ||
376 | /* the register address that is to be written to or read from. */ | ||
377 | |||
378 | uint16 parameter_CRC; | ||
379 | /* 16-bit CRC of all bytes from the Packet Length to the Register Address. */ | ||
380 | |||
381 | uint32 register_data_list; | ||
382 | /* list of 4-byte register data values for/from client registers */ | ||
383 | |||
384 | } mddi_register_access_packet_type; | ||
385 | |||
386 | typedef union GCC_PACKED { | ||
387 | mddi_video_stream_packet_type video_pkt; | ||
388 | mddi_register_access_packet_type register_pkt; | ||
389 | /* add 48 byte pad to ensure 64 byte llist struct, that can be | ||
390 | * manipulated easily with cache */ | ||
391 | uint32 alignment_pad[12]; /* 48 bytes */ | ||
392 | } mddi_packet_header_type; | ||
393 | |||
394 | typedef struct GCC_PACKED mddi_host_llist_struct { | ||
395 | uint16 link_controller_flags; | ||
396 | uint16 packet_header_count; | ||
397 | uint16 packet_data_count; | ||
398 | void *packet_data_pointer; | ||
399 | struct mddi_host_llist_struct *next_packet_pointer; | ||
400 | uint16 reserved; | ||
401 | mddi_packet_header_type packet_header; | ||
402 | } mddi_linked_list_type; | ||
403 | |||
404 | typedef struct { | ||
405 | struct completion done_comp; | ||
406 | mddi_llist_done_cb_type done_cb; | ||
407 | uint16 next_idx; | ||
408 | boolean waiting; | ||
409 | boolean in_use; | ||
410 | } mddi_linked_list_notify_type; | ||
411 | |||
412 | #define MDDI_LLIST_POOL_SIZE 0x1000 | ||
413 | #define MDDI_MAX_NUM_LLIST_ITEMS (MDDI_LLIST_POOL_SIZE / \ | ||
414 | sizeof(mddi_linked_list_type)) | ||
415 | #define UNASSIGNED_INDEX MDDI_MAX_NUM_LLIST_ITEMS | ||
416 | #define MDDI_FIRST_DYNAMIC_LLIST_IDX 0 | ||
417 | |||
418 | /* Static llist items can be used for applications that frequently send | ||
419 | * the same set of packets using the linked list interface. */ | ||
420 | /* Here we configure for 6 static linked list items: | ||
421 | * The 1st is used for a the adaptive backlight setting. | ||
422 | * and the remaining 5 are used for sending window adjustments for | ||
423 | * MDDI clients that need windowing info sent separate from video | ||
424 | * packets. */ | ||
425 | #define MDDI_NUM_STATIC_ABL_ITEMS 1 | ||
426 | #define MDDI_NUM_STATIC_WINDOW_ITEMS 5 | ||
427 | #define MDDI_NUM_STATIC_LLIST_ITEMS (MDDI_NUM_STATIC_ABL_ITEMS + \ | ||
428 | MDDI_NUM_STATIC_WINDOW_ITEMS) | ||
429 | #define MDDI_NUM_DYNAMIC_LLIST_ITEMS (MDDI_MAX_NUM_LLIST_ITEMS - \ | ||
430 | MDDI_NUM_STATIC_LLIST_ITEMS) | ||
431 | |||
432 | #define MDDI_FIRST_STATIC_LLIST_IDX MDDI_NUM_DYNAMIC_LLIST_ITEMS | ||
433 | #define MDDI_FIRST_STATIC_ABL_IDX MDDI_FIRST_STATIC_LLIST_IDX | ||
434 | #define MDDI_FIRST_STATIC_WINDOW_IDX (MDDI_FIRST_STATIC_LLIST_IDX + \ | ||
435 | MDDI_NUM_STATIC_ABL_ITEMS) | ||
436 | |||
437 | /* GPIO registers */ | ||
438 | #define VSYNC_WAKEUP_REG 0x80 | ||
439 | #define GPIO_REG 0x81 | ||
440 | #define GPIO_OUTPUT_REG 0x82 | ||
441 | #define GPIO_INTERRUPT_REG 0x83 | ||
442 | #define GPIO_INTERRUPT_ENABLE_REG 0x84 | ||
443 | #define GPIO_POLARITY_REG 0x85 | ||
444 | |||
445 | /* Interrupt Bits */ | ||
446 | #define MDDI_INT_PRI_PTR_READ 0x0001 | ||
447 | #define MDDI_INT_SEC_PTR_READ 0x0002 | ||
448 | #define MDDI_INT_REV_DATA_AVAIL 0x0004 | ||
449 | #define MDDI_INT_DISP_REQ 0x0008 | ||
450 | #define MDDI_INT_PRI_UNDERFLOW 0x0010 | ||
451 | #define MDDI_INT_SEC_UNDERFLOW 0x0020 | ||
452 | #define MDDI_INT_REV_OVERFLOW 0x0040 | ||
453 | #define MDDI_INT_CRC_ERROR 0x0080 | ||
454 | #define MDDI_INT_MDDI_IN 0x0100 | ||
455 | #define MDDI_INT_PRI_OVERWRITE 0x0200 | ||
456 | #define MDDI_INT_SEC_OVERWRITE 0x0400 | ||
457 | #define MDDI_INT_REV_OVERWRITE 0x0800 | ||
458 | #define MDDI_INT_DMA_FAILURE 0x1000 | ||
459 | #define MDDI_INT_LINK_ACTIVE 0x2000 | ||
460 | #define MDDI_INT_IN_HIBERNATION 0x4000 | ||
461 | #define MDDI_INT_PRI_LINK_LIST_DONE 0x8000 | ||
462 | #define MDDI_INT_SEC_LINK_LIST_DONE 0x10000 | ||
463 | #define MDDI_INT_NO_CMD_PKTS_PEND 0x20000 | ||
464 | #define MDDI_INT_RTD_FAILURE 0x40000 | ||
465 | |||
466 | #define MDDI_INT_ERROR_CONDITIONS ( \ | ||
467 | MDDI_INT_PRI_UNDERFLOW | MDDI_INT_SEC_UNDERFLOW | \ | ||
468 | MDDI_INT_REV_OVERFLOW | MDDI_INT_CRC_ERROR | \ | ||
469 | MDDI_INT_PRI_OVERWRITE | MDDI_INT_SEC_OVERWRITE | \ | ||
470 | MDDI_INT_RTD_FAILURE | \ | ||
471 | MDDI_INT_REV_OVERWRITE | MDDI_INT_DMA_FAILURE) | ||
472 | |||
473 | #define MDDI_INT_LINK_STATE_CHANGES ( \ | ||
474 | MDDI_INT_LINK_ACTIVE | MDDI_INT_IN_HIBERNATION) | ||
475 | |||
476 | /* Status Bits */ | ||
477 | #define MDDI_STAT_LINK_ACTIVE 0x0001 | ||
478 | #define MDDI_STAT_NEW_REV_PTR 0x0002 | ||
479 | #define MDDI_STAT_NEW_PRI_PTR 0x0004 | ||
480 | #define MDDI_STAT_NEW_SEC_PTR 0x0008 | ||
481 | #define MDDI_STAT_IN_HIBERNATION 0x0010 | ||
482 | #define MDDI_STAT_PRI_LINK_LIST_DONE 0x0020 | ||
483 | #define MDDI_STAT_SEC_LINK_LIST_DONE 0x0040 | ||
484 | #define MDDI_STAT_PENDING_TIMING_PKT 0x0080 | ||
485 | #define MDDI_STAT_PENDING_REV_ENCAP 0x0100 | ||
486 | #define MDDI_STAT_PENDING_POWERDOWN 0x0200 | ||
487 | #define MDDI_STAT_RTD_MEAS_FAIL 0x0800 | ||
488 | #define MDDI_STAT_CLIENT_WAKEUP_REQ 0x1000 | ||
489 | |||
490 | /* Command Bits */ | ||
491 | #define MDDI_CMD_POWERDOWN 0x0100 | ||
492 | #define MDDI_CMD_POWERUP 0x0200 | ||
493 | #define MDDI_CMD_HIBERNATE 0x0300 | ||
494 | #define MDDI_CMD_RESET 0x0400 | ||
495 | #define MDDI_CMD_DISP_IGNORE 0x0501 | ||
496 | #define MDDI_CMD_DISP_LISTEN 0x0500 | ||
497 | #define MDDI_CMD_SEND_REV_ENCAP 0x0600 | ||
498 | #define MDDI_CMD_GET_CLIENT_CAP 0x0601 | ||
499 | #define MDDI_CMD_GET_CLIENT_STATUS 0x0602 | ||
500 | #define MDDI_CMD_SEND_RTD 0x0700 | ||
501 | #define MDDI_CMD_LINK_ACTIVE 0x0900 | ||
502 | #define MDDI_CMD_PERIODIC_REV_ENCAP 0x0A00 | ||
503 | |||
504 | extern void mddi_host_init(mddi_host_type host); | ||
505 | extern void mddi_host_powerdown(mddi_host_type host); | ||
506 | extern uint16 mddi_get_next_free_llist_item(mddi_host_type host, boolean wait); | ||
507 | extern uint16 mddi_get_reg_read_llist_item(mddi_host_type host, boolean wait); | ||
508 | extern void mddi_queue_forward_packets(uint16 first_llist_idx, | ||
509 | uint16 last_llist_idx, | ||
510 | boolean wait, | ||
511 | mddi_llist_done_cb_type llist_done_cb, | ||
512 | mddi_host_type host); | ||
513 | |||
514 | extern void mddi_host_write_pix_attr_reg(uint32 value); | ||
515 | extern void mddi_client_lcd_gpio_poll(uint32 poll_reg_val); | ||
516 | extern void mddi_client_lcd_vsync_detected(boolean detected); | ||
517 | extern void mddi_host_disable_hibernation(boolean disable); | ||
518 | |||
519 | extern mddi_linked_list_type *llist_extern[]; | ||
520 | extern mddi_linked_list_type *llist_dma_extern[]; | ||
521 | extern mddi_linked_list_notify_type *llist_extern_notify[]; | ||
522 | extern struct timer_list mddi_host_timer; | ||
523 | |||
524 | typedef struct { | ||
525 | uint16 transmitting_start_idx; | ||
526 | uint16 transmitting_end_idx; | ||
527 | uint16 waiting_start_idx; | ||
528 | uint16 waiting_end_idx; | ||
529 | uint16 reg_read_idx; | ||
530 | uint16 next_free_idx; | ||
531 | boolean reg_read_waiting; | ||
532 | } mddi_llist_info_type; | ||
533 | |||
534 | extern mddi_llist_info_type mddi_llist; | ||
535 | |||
536 | #define MDDI_GPIO_DEFAULT_POLLING_INTERVAL 200 | ||
537 | typedef struct { | ||
538 | uint32 polling_reg; | ||
539 | uint32 polling_val; | ||
540 | uint32 polling_interval; | ||
541 | boolean polling_enabled; | ||
542 | } mddi_gpio_info_type; | ||
543 | |||
544 | uint32 mddi_get_client_id(void); | ||
545 | void mddi_mhctl_remove(mddi_host_type host_idx); | ||
546 | void mddi_host_timer_service(unsigned long data); | ||
547 | #endif /* MDDIHOSTI_H */ | ||
diff --git a/drivers/staging/msm/mdp.c b/drivers/staging/msm/mdp.c new file mode 100644 index 000000000000..36053afdebe2 --- /dev/null +++ b/drivers/staging/msm/mdp.c | |||
@@ -0,0 +1,1113 @@ | |||
1 | /* Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/sched.h> | ||
21 | #include <linux/time.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/spinlock.h> | ||
25 | #include <linux/hrtimer.h> | ||
26 | #include <linux/clk.h> | ||
27 | #include <mach/hardware.h> | ||
28 | #include <linux/io.h> | ||
29 | #include <linux/debugfs.h> | ||
30 | #include <linux/delay.h> | ||
31 | #include <linux/mutex.h> | ||
32 | |||
33 | #include <asm/system.h> | ||
34 | #include <asm/mach-types.h> | ||
35 | #include <linux/semaphore.h> | ||
36 | #include <linux/uaccess.h> | ||
37 | |||
38 | #include "mdp.h" | ||
39 | #include "msm_fb.h" | ||
40 | #ifdef CONFIG_FB_MSM_MDP40 | ||
41 | #include "mdp4.h" | ||
42 | #endif | ||
43 | |||
44 | static struct clk *mdp_clk; | ||
45 | static struct clk *mdp_pclk; | ||
46 | |||
47 | struct completion mdp_ppp_comp; | ||
48 | struct semaphore mdp_ppp_mutex; | ||
49 | struct semaphore mdp_pipe_ctrl_mutex; | ||
50 | |||
51 | unsigned long mdp_timer_duration = (HZ); /* 1 sec */ | ||
52 | /* unsigned long mdp_mdp_timer_duration=0; */ | ||
53 | |||
54 | boolean mdp_ppp_waiting = FALSE; | ||
55 | uint32 mdp_tv_underflow_cnt; | ||
56 | uint32 mdp_lcdc_underflow_cnt; | ||
57 | |||
58 | boolean mdp_current_clk_on = FALSE; | ||
59 | boolean mdp_is_in_isr = FALSE; | ||
60 | |||
61 | /* | ||
62 | * legacy mdp_in_processing is only for DMA2-MDDI | ||
63 | * this applies to DMA2 block only | ||
64 | */ | ||
65 | uint32 mdp_in_processing = FALSE; | ||
66 | |||
67 | #ifdef CONFIG_FB_MSM_MDP40 | ||
68 | uint32 mdp_intr_mask = MDP4_ANY_INTR_MASK; | ||
69 | #else | ||
70 | uint32 mdp_intr_mask = MDP_ANY_INTR_MASK; | ||
71 | #endif | ||
72 | |||
73 | MDP_BLOCK_TYPE mdp_debug[MDP_MAX_BLOCK]; | ||
74 | |||
75 | int32 mdp_block_power_cnt[MDP_MAX_BLOCK]; | ||
76 | |||
77 | spinlock_t mdp_spin_lock; | ||
78 | struct workqueue_struct *mdp_dma_wq; /*mdp dma wq */ | ||
79 | struct workqueue_struct *mdp_vsync_wq; /*mdp vsync wq */ | ||
80 | |||
81 | static struct workqueue_struct *mdp_pipe_ctrl_wq; /* mdp mdp pipe ctrl wq */ | ||
82 | static struct delayed_work mdp_pipe_ctrl_worker; | ||
83 | |||
84 | #ifdef CONFIG_FB_MSM_MDP40 | ||
85 | struct mdp_dma_data dma2_data; | ||
86 | struct mdp_dma_data dma_s_data; | ||
87 | struct mdp_dma_data dma_e_data; | ||
88 | #else | ||
89 | static struct mdp_dma_data dma2_data; | ||
90 | static struct mdp_dma_data dma_s_data; | ||
91 | static struct mdp_dma_data dma_e_data; | ||
92 | #endif | ||
93 | static struct mdp_dma_data dma3_data; | ||
94 | |||
95 | extern ktime_t mdp_dma2_last_update_time; | ||
96 | |||
97 | extern uint32 mdp_dma2_update_time_in_usec; | ||
98 | extern int mdp_lcd_rd_cnt_offset_slow; | ||
99 | extern int mdp_lcd_rd_cnt_offset_fast; | ||
100 | extern int mdp_usec_diff_threshold; | ||
101 | |||
102 | #ifdef CONFIG_FB_MSM_LCDC | ||
103 | extern int mdp_lcdc_pclk_clk_rate; | ||
104 | extern int mdp_lcdc_pad_pclk_clk_rate; | ||
105 | extern int first_pixel_start_x; | ||
106 | extern int first_pixel_start_y; | ||
107 | #endif | ||
108 | |||
109 | #ifdef MSM_FB_ENABLE_DBGFS | ||
110 | struct dentry *mdp_dir; | ||
111 | #endif | ||
112 | |||
113 | #if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND) | ||
114 | static int mdp_suspend(struct platform_device *pdev, pm_message_t state); | ||
115 | #else | ||
116 | #define mdp_suspend NULL | ||
117 | #endif | ||
118 | |||
119 | struct timeval mdp_dma2_timeval; | ||
120 | struct timeval mdp_ppp_timeval; | ||
121 | |||
122 | #ifdef CONFIG_HAS_EARLYSUSPEND | ||
123 | static struct early_suspend early_suspend; | ||
124 | #endif | ||
125 | |||
126 | #ifndef CONFIG_FB_MSM_MDP22 | ||
127 | DEFINE_MUTEX(mdp_lut_push_sem); | ||
128 | static int mdp_lut_i; | ||
129 | static int mdp_lut_hw_update(struct fb_cmap *cmap) | ||
130 | { | ||
131 | int i; | ||
132 | u16 *c[3]; | ||
133 | u16 r, g, b; | ||
134 | |||
135 | c[0] = cmap->green; | ||
136 | c[1] = cmap->blue; | ||
137 | c[2] = cmap->red; | ||
138 | |||
139 | for (i = 0; i < cmap->len; i++) { | ||
140 | if (copy_from_user(&r, cmap->red++, sizeof(r)) || | ||
141 | copy_from_user(&g, cmap->green++, sizeof(g)) || | ||
142 | copy_from_user(&b, cmap->blue++, sizeof(b))) | ||
143 | return -EFAULT; | ||
144 | |||
145 | #ifdef CONFIG_FB_MSM_MDP40 | ||
146 | MDP_OUTP(MDP_BASE + 0x94800 + | ||
147 | #else | ||
148 | MDP_OUTP(MDP_BASE + 0x93800 + | ||
149 | #endif | ||
150 | (0x400*mdp_lut_i) + cmap->start*4 + i*4, | ||
151 | ((g & 0xff) | | ||
152 | ((b & 0xff) << 8) | | ||
153 | ((r & 0xff) << 16))); | ||
154 | } | ||
155 | |||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | static int mdp_lut_push; | ||
160 | static int mdp_lut_push_i; | ||
161 | static int mdp_lut_update_nonlcdc(struct fb_info *info, struct fb_cmap *cmap) | ||
162 | { | ||
163 | int ret; | ||
164 | |||
165 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); | ||
166 | ret = mdp_lut_hw_update(cmap); | ||
167 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); | ||
168 | |||
169 | if (ret) | ||
170 | return ret; | ||
171 | |||
172 | mutex_lock(&mdp_lut_push_sem); | ||
173 | mdp_lut_push = 1; | ||
174 | mdp_lut_push_i = mdp_lut_i; | ||
175 | mutex_unlock(&mdp_lut_push_sem); | ||
176 | |||
177 | mdp_lut_i = (mdp_lut_i + 1)%2; | ||
178 | |||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | static int mdp_lut_update_lcdc(struct fb_info *info, struct fb_cmap *cmap) | ||
183 | { | ||
184 | int ret; | ||
185 | |||
186 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); | ||
187 | ret = mdp_lut_hw_update(cmap); | ||
188 | |||
189 | if (ret) { | ||
190 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); | ||
191 | return ret; | ||
192 | } | ||
193 | |||
194 | MDP_OUTP(MDP_BASE + 0x90070, (mdp_lut_i << 10) | 0x17); | ||
195 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); | ||
196 | mdp_lut_i = (mdp_lut_i + 1)%2; | ||
197 | |||
198 | return 0; | ||
199 | } | ||
200 | |||
201 | #define MDP_HIST_MAX_BIN 32 | ||
202 | static __u32 mdp_hist_r[MDP_HIST_MAX_BIN]; | ||
203 | static __u32 mdp_hist_g[MDP_HIST_MAX_BIN]; | ||
204 | static __u32 mdp_hist_b[MDP_HIST_MAX_BIN]; | ||
205 | |||
206 | #ifdef CONFIG_FB_MSM_MDP40 | ||
207 | struct mdp_histogram mdp_hist; | ||
208 | struct completion mdp_hist_comp; | ||
209 | #else | ||
210 | static struct mdp_histogram mdp_hist; | ||
211 | static struct completion mdp_hist_comp; | ||
212 | #endif | ||
213 | |||
214 | static int mdp_do_histogram(struct fb_info *info, struct mdp_histogram *hist) | ||
215 | { | ||
216 | int ret = 0; | ||
217 | |||
218 | if (!hist->frame_cnt || (hist->bin_cnt == 0) || | ||
219 | (hist->bin_cnt > MDP_HIST_MAX_BIN)) | ||
220 | return -EINVAL; | ||
221 | |||
222 | INIT_COMPLETION(mdp_hist_comp); | ||
223 | |||
224 | mdp_hist.bin_cnt = hist->bin_cnt; | ||
225 | mdp_hist.r = (hist->r) ? mdp_hist_r : 0; | ||
226 | mdp_hist.g = (hist->g) ? mdp_hist_g : 0; | ||
227 | mdp_hist.b = (hist->b) ? mdp_hist_b : 0; | ||
228 | |||
229 | #ifdef CONFIG_FB_MSM_MDP40 | ||
230 | MDP_OUTP(MDP_BASE + 0x95004, hist->frame_cnt); | ||
231 | MDP_OUTP(MDP_BASE + 0x95000, 1); | ||
232 | #else | ||
233 | MDP_OUTP(MDP_BASE + 0x94004, hist->frame_cnt); | ||
234 | MDP_OUTP(MDP_BASE + 0x94000, 1); | ||
235 | #endif | ||
236 | wait_for_completion_killable(&mdp_hist_comp); | ||
237 | |||
238 | if (hist->r) { | ||
239 | ret = copy_to_user(hist->r, mdp_hist.r, hist->bin_cnt*4); | ||
240 | if (ret) | ||
241 | goto hist_err; | ||
242 | } | ||
243 | if (hist->g) { | ||
244 | ret = copy_to_user(hist->g, mdp_hist.g, hist->bin_cnt*4); | ||
245 | if (ret) | ||
246 | goto hist_err; | ||
247 | } | ||
248 | if (hist->b) { | ||
249 | ret = copy_to_user(hist->b, mdp_hist.b, hist->bin_cnt*4); | ||
250 | if (ret) | ||
251 | goto hist_err; | ||
252 | } | ||
253 | return 0; | ||
254 | |||
255 | hist_err: | ||
256 | printk(KERN_ERR "%s: invalid hist buffer\n", __func__); | ||
257 | return ret; | ||
258 | } | ||
259 | #endif | ||
260 | |||
261 | /* Returns < 0 on error, 0 on timeout, or > 0 on successful wait */ | ||
262 | |||
263 | int mdp_ppp_pipe_wait(void) | ||
264 | { | ||
265 | int ret = 1; | ||
266 | |||
267 | /* wait 5 seconds for the operation to complete before declaring | ||
268 | the MDP hung */ | ||
269 | |||
270 | if (mdp_ppp_waiting == TRUE) { | ||
271 | ret = wait_for_completion_interruptible_timeout(&mdp_ppp_comp, | ||
272 | 5 * HZ); | ||
273 | |||
274 | if (!ret) | ||
275 | printk(KERN_ERR "%s: Timed out waiting for the MDP.\n", | ||
276 | __func__); | ||
277 | } | ||
278 | |||
279 | return ret; | ||
280 | } | ||
281 | |||
282 | static DEFINE_SPINLOCK(mdp_lock); | ||
283 | static int mdp_irq_mask; | ||
284 | static int mdp_irq_enabled; | ||
285 | |||
286 | void mdp_enable_irq(uint32 term) | ||
287 | { | ||
288 | unsigned long irq_flags; | ||
289 | |||
290 | spin_lock_irqsave(&mdp_lock, irq_flags); | ||
291 | if (mdp_irq_mask & term) { | ||
292 | printk(KERN_ERR "MDP IRQ term-0x%x is already set\n", term); | ||
293 | } else { | ||
294 | mdp_irq_mask |= term; | ||
295 | if (mdp_irq_mask && !mdp_irq_enabled) { | ||
296 | mdp_irq_enabled = 1; | ||
297 | enable_irq(INT_MDP); | ||
298 | } | ||
299 | } | ||
300 | spin_unlock_irqrestore(&mdp_lock, irq_flags); | ||
301 | } | ||
302 | |||
303 | void mdp_disable_irq(uint32 term) | ||
304 | { | ||
305 | unsigned long irq_flags; | ||
306 | |||
307 | spin_lock_irqsave(&mdp_lock, irq_flags); | ||
308 | if (!(mdp_irq_mask & term)) { | ||
309 | printk(KERN_ERR "MDP IRQ term-0x%x is not set\n", term); | ||
310 | } else { | ||
311 | mdp_irq_mask &= ~term; | ||
312 | if (!mdp_irq_mask && mdp_irq_enabled) { | ||
313 | mdp_irq_enabled = 0; | ||
314 | disable_irq(INT_MDP); | ||
315 | } | ||
316 | } | ||
317 | spin_unlock_irqrestore(&mdp_lock, irq_flags); | ||
318 | } | ||
319 | |||
320 | void mdp_disable_irq_nolock(uint32 term) | ||
321 | { | ||
322 | |||
323 | if (!(mdp_irq_mask & term)) { | ||
324 | printk(KERN_ERR "MDP IRQ term-0x%x is not set\n", term); | ||
325 | } else { | ||
326 | mdp_irq_mask &= ~term; | ||
327 | if (!mdp_irq_mask && mdp_irq_enabled) { | ||
328 | mdp_irq_enabled = 0; | ||
329 | disable_irq(INT_MDP); | ||
330 | } | ||
331 | } | ||
332 | } | ||
333 | |||
334 | void mdp_pipe_kickoff(uint32 term, struct msm_fb_data_type *mfd) | ||
335 | { | ||
336 | |||
337 | dmb(); /* memory barrier */ | ||
338 | |||
339 | /* kick off PPP engine */ | ||
340 | if (term == MDP_PPP_TERM) { | ||
341 | if (mdp_debug[MDP_PPP_BLOCK]) | ||
342 | jiffies_to_timeval(jiffies, &mdp_ppp_timeval); | ||
343 | |||
344 | /* let's turn on PPP block */ | ||
345 | mdp_pipe_ctrl(MDP_PPP_BLOCK, MDP_BLOCK_POWER_ON, FALSE); | ||
346 | |||
347 | mdp_enable_irq(term); | ||
348 | INIT_COMPLETION(mdp_ppp_comp); | ||
349 | mdp_ppp_waiting = TRUE; | ||
350 | outpdw(MDP_BASE + 0x30, 0x1000); | ||
351 | wait_for_completion_killable(&mdp_ppp_comp); | ||
352 | mdp_disable_irq(term); | ||
353 | |||
354 | if (mdp_debug[MDP_PPP_BLOCK]) { | ||
355 | struct timeval now; | ||
356 | |||
357 | jiffies_to_timeval(jiffies, &now); | ||
358 | mdp_ppp_timeval.tv_usec = | ||
359 | now.tv_usec - mdp_ppp_timeval.tv_usec; | ||
360 | MSM_FB_INFO("MDP-PPP: %d\n", | ||
361 | (int)mdp_ppp_timeval.tv_usec); | ||
362 | } | ||
363 | } else if (term == MDP_DMA2_TERM) { | ||
364 | if (mdp_debug[MDP_DMA2_BLOCK]) { | ||
365 | MSM_FB_INFO("MDP-DMA2: %d\n", | ||
366 | (int)mdp_dma2_timeval.tv_usec); | ||
367 | jiffies_to_timeval(jiffies, &mdp_dma2_timeval); | ||
368 | } | ||
369 | /* DMA update timestamp */ | ||
370 | mdp_dma2_last_update_time = ktime_get_real(); | ||
371 | /* let's turn on DMA2 block */ | ||
372 | #if 0 | ||
373 | mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_ON, FALSE); | ||
374 | #endif | ||
375 | #ifdef CONFIG_FB_MSM_MDP22 | ||
376 | outpdw(MDP_CMD_DEBUG_ACCESS_BASE + 0x0044, 0x0);/* start DMA */ | ||
377 | #else | ||
378 | if (mdp_lut_push) { | ||
379 | mutex_lock(&mdp_lut_push_sem); | ||
380 | mdp_lut_push = 0; | ||
381 | MDP_OUTP(MDP_BASE + 0x90070, | ||
382 | (mdp_lut_push_i << 10) | 0x17); | ||
383 | mutex_unlock(&mdp_lut_push_sem); | ||
384 | } | ||
385 | #ifdef CONFIG_FB_MSM_MDP40 | ||
386 | outpdw(MDP_BASE + 0x000c, 0x0); /* start DMA */ | ||
387 | #else | ||
388 | outpdw(MDP_BASE + 0x0044, 0x0); /* start DMA */ | ||
389 | #endif | ||
390 | #endif | ||
391 | #ifdef CONFIG_FB_MSM_MDP40 | ||
392 | } else if (term == MDP_DMA_S_TERM) { | ||
393 | mdp_pipe_ctrl(MDP_DMA_S_BLOCK, MDP_BLOCK_POWER_ON, FALSE); | ||
394 | outpdw(MDP_BASE + 0x0010, 0x0); /* start DMA */ | ||
395 | } else if (term == MDP_DMA_E_TERM) { | ||
396 | mdp_pipe_ctrl(MDP_DMA_E_BLOCK, MDP_BLOCK_POWER_ON, FALSE); | ||
397 | outpdw(MDP_BASE + 0x0014, 0x0); /* start DMA */ | ||
398 | } else if (term == MDP_OVERLAY0_TERM) { | ||
399 | mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_ON, FALSE); | ||
400 | outpdw(MDP_BASE + 0x0004, 0); | ||
401 | } else if (term == MDP_OVERLAY1_TERM) { | ||
402 | mdp_pipe_ctrl(MDP_OVERLAY1_BLOCK, MDP_BLOCK_POWER_ON, FALSE); | ||
403 | outpdw(MDP_BASE + 0x0008, 0); | ||
404 | } | ||
405 | #else | ||
406 | } else if (term == MDP_DMA_S_TERM) { | ||
407 | mdp_pipe_ctrl(MDP_DMA_S_BLOCK, MDP_BLOCK_POWER_ON, FALSE); | ||
408 | outpdw(MDP_BASE + 0x0048, 0x0); /* start DMA */ | ||
409 | } | ||
410 | #endif | ||
411 | } | ||
412 | |||
413 | static void mdp_pipe_ctrl_workqueue_handler(struct work_struct *work) | ||
414 | { | ||
415 | mdp_pipe_ctrl(MDP_MASTER_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); | ||
416 | } | ||
417 | |||
418 | void mdp_pipe_ctrl(MDP_BLOCK_TYPE block, MDP_BLOCK_POWER_STATE state, | ||
419 | boolean isr) | ||
420 | { | ||
421 | boolean mdp_all_blocks_off = TRUE; | ||
422 | int i; | ||
423 | unsigned long flag; | ||
424 | |||
425 | spin_lock_irqsave(&mdp_spin_lock, flag); | ||
426 | if (MDP_BLOCK_POWER_ON == state) { | ||
427 | mdp_block_power_cnt[block]++; | ||
428 | |||
429 | if (MDP_DMA2_BLOCK == block) | ||
430 | mdp_in_processing = TRUE; | ||
431 | } else { | ||
432 | mdp_block_power_cnt[block]--; | ||
433 | |||
434 | if (mdp_block_power_cnt[block] < 0) { | ||
435 | /* | ||
436 | * Master has to serve a request to power off MDP always | ||
437 | * It also has a timer to power off. So, in case of | ||
438 | * timer expires first and DMA2 finishes later, | ||
439 | * master has to power off two times | ||
440 | * There shouldn't be multiple power-off request for | ||
441 | * other blocks | ||
442 | */ | ||
443 | if (block != MDP_MASTER_BLOCK) { | ||
444 | MSM_FB_INFO("mdp_block_power_cnt[block=%d] \ | ||
445 | multiple power-off request\n", block); | ||
446 | } | ||
447 | mdp_block_power_cnt[block] = 0; | ||
448 | } | ||
449 | |||
450 | if (MDP_DMA2_BLOCK == block) | ||
451 | mdp_in_processing = FALSE; | ||
452 | } | ||
453 | spin_unlock_irqrestore(&mdp_spin_lock, flag); | ||
454 | |||
455 | /* | ||
456 | * If it's in isr, we send our request to workqueue. | ||
457 | * Otherwise, processing happens in the current context | ||
458 | */ | ||
459 | if (isr) { | ||
460 | /* checking all blocks power state */ | ||
461 | for (i = 0; i < MDP_MAX_BLOCK; i++) { | ||
462 | if (mdp_block_power_cnt[i] > 0) | ||
463 | mdp_all_blocks_off = FALSE; | ||
464 | } | ||
465 | |||
466 | if ((mdp_all_blocks_off) && (mdp_current_clk_on)) { | ||
467 | /* send workqueue to turn off mdp power */ | ||
468 | queue_delayed_work(mdp_pipe_ctrl_wq, | ||
469 | &mdp_pipe_ctrl_worker, | ||
470 | mdp_timer_duration); | ||
471 | } | ||
472 | } else { | ||
473 | down(&mdp_pipe_ctrl_mutex); | ||
474 | /* checking all blocks power state */ | ||
475 | for (i = 0; i < MDP_MAX_BLOCK; i++) { | ||
476 | if (mdp_block_power_cnt[i] > 0) | ||
477 | mdp_all_blocks_off = FALSE; | ||
478 | } | ||
479 | |||
480 | /* | ||
481 | * find out whether a delayable work item is currently | ||
482 | * pending | ||
483 | */ | ||
484 | |||
485 | if (delayed_work_pending(&mdp_pipe_ctrl_worker)) { | ||
486 | /* | ||
487 | * try to cancel the current work if it fails to | ||
488 | * stop (which means del_timer can't delete it | ||
489 | * from the list, it's about to expire and run), | ||
490 | * we have to let it run. queue_delayed_work won't | ||
491 | * accept the next job which is same as | ||
492 | * queue_delayed_work(mdp_timer_duration = 0) | ||
493 | */ | ||
494 | cancel_delayed_work(&mdp_pipe_ctrl_worker); | ||
495 | } | ||
496 | |||
497 | if ((mdp_all_blocks_off) && (mdp_current_clk_on)) { | ||
498 | if (block == MDP_MASTER_BLOCK) { | ||
499 | mdp_current_clk_on = FALSE; | ||
500 | /* turn off MDP clks */ | ||
501 | if (mdp_clk != NULL) { | ||
502 | clk_disable(mdp_clk); | ||
503 | MSM_FB_DEBUG("MDP CLK OFF\n"); | ||
504 | } | ||
505 | if (mdp_pclk != NULL) { | ||
506 | clk_disable(mdp_pclk); | ||
507 | MSM_FB_DEBUG("MDP PCLK OFF\n"); | ||
508 | } | ||
509 | } else { | ||
510 | /* send workqueue to turn off mdp power */ | ||
511 | queue_delayed_work(mdp_pipe_ctrl_wq, | ||
512 | &mdp_pipe_ctrl_worker, | ||
513 | mdp_timer_duration); | ||
514 | } | ||
515 | } else if ((!mdp_all_blocks_off) && (!mdp_current_clk_on)) { | ||
516 | mdp_current_clk_on = TRUE; | ||
517 | /* turn on MDP clks */ | ||
518 | if (mdp_clk != NULL) { | ||
519 | clk_enable(mdp_clk); | ||
520 | MSM_FB_DEBUG("MDP CLK ON\n"); | ||
521 | } | ||
522 | if (mdp_pclk != NULL) { | ||
523 | clk_enable(mdp_pclk); | ||
524 | MSM_FB_DEBUG("MDP PCLK ON\n"); | ||
525 | } | ||
526 | } | ||
527 | up(&mdp_pipe_ctrl_mutex); | ||
528 | } | ||
529 | } | ||
530 | |||
531 | #ifndef CONFIG_FB_MSM_MDP40 | ||
532 | irqreturn_t mdp_isr(int irq, void *ptr) | ||
533 | { | ||
534 | uint32 mdp_interrupt = 0; | ||
535 | struct mdp_dma_data *dma; | ||
536 | |||
537 | mdp_is_in_isr = TRUE; | ||
538 | do { | ||
539 | mdp_interrupt = inp32(MDP_INTR_STATUS); | ||
540 | outp32(MDP_INTR_CLEAR, mdp_interrupt); | ||
541 | |||
542 | mdp_interrupt &= mdp_intr_mask; | ||
543 | |||
544 | if (mdp_interrupt & TV_ENC_UNDERRUN) { | ||
545 | mdp_interrupt &= ~(TV_ENC_UNDERRUN); | ||
546 | mdp_tv_underflow_cnt++; | ||
547 | } | ||
548 | |||
549 | if (!mdp_interrupt) | ||
550 | break; | ||
551 | |||
552 | /* DMA3 TV-Out Start */ | ||
553 | if (mdp_interrupt & TV_OUT_DMA3_START) { | ||
554 | /* let's disable TV out interrupt */ | ||
555 | mdp_intr_mask &= ~TV_OUT_DMA3_START; | ||
556 | outp32(MDP_INTR_ENABLE, mdp_intr_mask); | ||
557 | |||
558 | dma = &dma3_data; | ||
559 | if (dma->waiting) { | ||
560 | dma->waiting = FALSE; | ||
561 | complete(&dma->comp); | ||
562 | } | ||
563 | } | ||
564 | #ifndef CONFIG_FB_MSM_MDP22 | ||
565 | if (mdp_interrupt & MDP_HIST_DONE) { | ||
566 | outp32(MDP_BASE + 0x94018, 0x3); | ||
567 | outp32(MDP_INTR_CLEAR, MDP_HIST_DONE); | ||
568 | if (mdp_hist.r) | ||
569 | memcpy(mdp_hist.r, MDP_BASE + 0x94100, | ||
570 | mdp_hist.bin_cnt*4); | ||
571 | if (mdp_hist.g) | ||
572 | memcpy(mdp_hist.g, MDP_BASE + 0x94200, | ||
573 | mdp_hist.bin_cnt*4); | ||
574 | if (mdp_hist.b) | ||
575 | memcpy(mdp_hist.b, MDP_BASE + 0x94300, | ||
576 | mdp_hist.bin_cnt*4); | ||
577 | complete(&mdp_hist_comp); | ||
578 | } | ||
579 | |||
580 | /* LCDC UnderFlow */ | ||
581 | if (mdp_interrupt & LCDC_UNDERFLOW) { | ||
582 | mdp_lcdc_underflow_cnt++; | ||
583 | } | ||
584 | /* LCDC Frame Start */ | ||
585 | if (mdp_interrupt & LCDC_FRAME_START) { | ||
586 | /* let's disable LCDC interrupt */ | ||
587 | mdp_intr_mask &= ~LCDC_FRAME_START; | ||
588 | outp32(MDP_INTR_ENABLE, mdp_intr_mask); | ||
589 | |||
590 | dma = &dma2_data; | ||
591 | if (dma->waiting) { | ||
592 | dma->waiting = FALSE; | ||
593 | complete(&dma->comp); | ||
594 | } | ||
595 | } | ||
596 | |||
597 | /* DMA2 LCD-Out Complete */ | ||
598 | if (mdp_interrupt & MDP_DMA_S_DONE) { | ||
599 | dma = &dma_s_data; | ||
600 | dma->busy = FALSE; | ||
601 | mdp_pipe_ctrl(MDP_DMA_S_BLOCK, MDP_BLOCK_POWER_OFF, | ||
602 | TRUE); | ||
603 | complete(&dma->comp); | ||
604 | } | ||
605 | #endif | ||
606 | |||
607 | /* DMA2 LCD-Out Complete */ | ||
608 | if (mdp_interrupt & MDP_DMA_P_DONE) { | ||
609 | struct timeval now; | ||
610 | ktime_t now_k; | ||
611 | |||
612 | now_k = ktime_get_real(); | ||
613 | mdp_dma2_last_update_time.tv.sec = | ||
614 | now_k.tv.sec - mdp_dma2_last_update_time.tv.sec; | ||
615 | mdp_dma2_last_update_time.tv.nsec = | ||
616 | now_k.tv.nsec - mdp_dma2_last_update_time.tv.nsec; | ||
617 | |||
618 | if (mdp_debug[MDP_DMA2_BLOCK]) { | ||
619 | jiffies_to_timeval(jiffies, &now); | ||
620 | mdp_dma2_timeval.tv_usec = | ||
621 | now.tv_usec - mdp_dma2_timeval.tv_usec; | ||
622 | } | ||
623 | |||
624 | dma = &dma2_data; | ||
625 | dma->busy = FALSE; | ||
626 | mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_OFF, | ||
627 | TRUE); | ||
628 | complete(&dma->comp); | ||
629 | } | ||
630 | /* PPP Complete */ | ||
631 | if (mdp_interrupt & MDP_PPP_DONE) { | ||
632 | #ifdef CONFIG_MDP_PPP_ASYNC_OP | ||
633 | mdp_ppp_djob_done(); | ||
634 | #else | ||
635 | mdp_pipe_ctrl(MDP_PPP_BLOCK, | ||
636 | MDP_BLOCK_POWER_OFF, TRUE); | ||
637 | if (mdp_ppp_waiting) { | ||
638 | mdp_ppp_waiting = FALSE; | ||
639 | complete(&mdp_ppp_comp); | ||
640 | } | ||
641 | #endif | ||
642 | } | ||
643 | } while (1); | ||
644 | |||
645 | mdp_is_in_isr = FALSE; | ||
646 | |||
647 | return IRQ_HANDLED; | ||
648 | } | ||
649 | #endif | ||
650 | |||
651 | static void mdp_drv_init(void) | ||
652 | { | ||
653 | int i; | ||
654 | |||
655 | for (i = 0; i < MDP_MAX_BLOCK; i++) { | ||
656 | mdp_debug[i] = 0; | ||
657 | } | ||
658 | |||
659 | /* initialize spin lock and workqueue */ | ||
660 | spin_lock_init(&mdp_spin_lock); | ||
661 | mdp_dma_wq = create_singlethread_workqueue("mdp_dma_wq"); | ||
662 | mdp_vsync_wq = create_singlethread_workqueue("mdp_vsync_wq"); | ||
663 | mdp_pipe_ctrl_wq = create_singlethread_workqueue("mdp_pipe_ctrl_wq"); | ||
664 | INIT_DELAYED_WORK(&mdp_pipe_ctrl_worker, | ||
665 | mdp_pipe_ctrl_workqueue_handler); | ||
666 | #ifdef CONFIG_MDP_PPP_ASYNC_OP | ||
667 | mdp_ppp_dq_init(); | ||
668 | #endif | ||
669 | |||
670 | /* initialize semaphore */ | ||
671 | init_completion(&mdp_ppp_comp); | ||
672 | init_MUTEX(&mdp_ppp_mutex); | ||
673 | init_MUTEX(&mdp_pipe_ctrl_mutex); | ||
674 | |||
675 | dma2_data.busy = FALSE; | ||
676 | dma2_data.waiting = FALSE; | ||
677 | init_completion(&dma2_data.comp); | ||
678 | init_MUTEX(&dma2_data.mutex); | ||
679 | mutex_init(&dma2_data.ov_mutex); | ||
680 | |||
681 | dma3_data.busy = FALSE; | ||
682 | dma3_data.waiting = FALSE; | ||
683 | init_completion(&dma3_data.comp); | ||
684 | init_MUTEX(&dma3_data.mutex); | ||
685 | |||
686 | dma_s_data.busy = FALSE; | ||
687 | dma_s_data.waiting = FALSE; | ||
688 | init_completion(&dma_s_data.comp); | ||
689 | init_MUTEX(&dma_s_data.mutex); | ||
690 | |||
691 | dma_e_data.busy = FALSE; | ||
692 | dma_e_data.waiting = FALSE; | ||
693 | init_completion(&dma_e_data.comp); | ||
694 | |||
695 | #ifndef CONFIG_FB_MSM_MDP22 | ||
696 | init_completion(&mdp_hist_comp); | ||
697 | #endif | ||
698 | |||
699 | /* initializing mdp power block counter to 0 */ | ||
700 | for (i = 0; i < MDP_MAX_BLOCK; i++) { | ||
701 | mdp_block_power_cnt[i] = 0; | ||
702 | } | ||
703 | |||
704 | #ifdef MSM_FB_ENABLE_DBGFS | ||
705 | { | ||
706 | struct dentry *root; | ||
707 | char sub_name[] = "mdp"; | ||
708 | |||
709 | root = msm_fb_get_debugfs_root(); | ||
710 | if (root != NULL) { | ||
711 | mdp_dir = debugfs_create_dir(sub_name, root); | ||
712 | |||
713 | if (mdp_dir) { | ||
714 | msm_fb_debugfs_file_create(mdp_dir, | ||
715 | "dma2_update_time_in_usec", | ||
716 | (u32 *) &mdp_dma2_update_time_in_usec); | ||
717 | msm_fb_debugfs_file_create(mdp_dir, | ||
718 | "vs_rdcnt_slow", | ||
719 | (u32 *) &mdp_lcd_rd_cnt_offset_slow); | ||
720 | msm_fb_debugfs_file_create(mdp_dir, | ||
721 | "vs_rdcnt_fast", | ||
722 | (u32 *) &mdp_lcd_rd_cnt_offset_fast); | ||
723 | msm_fb_debugfs_file_create(mdp_dir, | ||
724 | "mdp_usec_diff_threshold", | ||
725 | (u32 *) &mdp_usec_diff_threshold); | ||
726 | msm_fb_debugfs_file_create(mdp_dir, | ||
727 | "mdp_current_clk_on", | ||
728 | (u32 *) &mdp_current_clk_on); | ||
729 | #ifdef CONFIG_FB_MSM_LCDC | ||
730 | msm_fb_debugfs_file_create(mdp_dir, | ||
731 | "lcdc_start_x", | ||
732 | (u32 *) &first_pixel_start_x); | ||
733 | msm_fb_debugfs_file_create(mdp_dir, | ||
734 | "lcdc_start_y", | ||
735 | (u32 *) &first_pixel_start_y); | ||
736 | msm_fb_debugfs_file_create(mdp_dir, | ||
737 | "mdp_lcdc_pclk_clk_rate", | ||
738 | (u32 *) &mdp_lcdc_pclk_clk_rate); | ||
739 | msm_fb_debugfs_file_create(mdp_dir, | ||
740 | "mdp_lcdc_pad_pclk_clk_rate", | ||
741 | (u32 *) &mdp_lcdc_pad_pclk_clk_rate); | ||
742 | #endif | ||
743 | } | ||
744 | } | ||
745 | } | ||
746 | #endif | ||
747 | } | ||
748 | |||
749 | static int mdp_probe(struct platform_device *pdev); | ||
750 | static int mdp_remove(struct platform_device *pdev); | ||
751 | |||
752 | static struct platform_driver mdp_driver = { | ||
753 | .probe = mdp_probe, | ||
754 | .remove = mdp_remove, | ||
755 | #ifndef CONFIG_HAS_EARLYSUSPEND | ||
756 | .suspend = mdp_suspend, | ||
757 | .resume = NULL, | ||
758 | #endif | ||
759 | .shutdown = NULL, | ||
760 | .driver = { | ||
761 | /* | ||
762 | * Driver name must match the device name added in | ||
763 | * platform.c. | ||
764 | */ | ||
765 | .name = "mdp", | ||
766 | }, | ||
767 | }; | ||
768 | |||
769 | static int mdp_off(struct platform_device *pdev) | ||
770 | { | ||
771 | int ret = 0; | ||
772 | |||
773 | #ifdef MDP_HW_VSYNC | ||
774 | struct msm_fb_data_type *mfd = platform_get_drvdata(pdev); | ||
775 | #endif | ||
776 | |||
777 | ret = panel_next_off(pdev); | ||
778 | |||
779 | #ifdef MDP_HW_VSYNC | ||
780 | mdp_hw_vsync_clk_disable(mfd); | ||
781 | #endif | ||
782 | |||
783 | return ret; | ||
784 | } | ||
785 | |||
786 | static int mdp_on(struct platform_device *pdev) | ||
787 | { | ||
788 | #ifdef MDP_HW_VSYNC | ||
789 | struct msm_fb_data_type *mfd = platform_get_drvdata(pdev); | ||
790 | #endif | ||
791 | |||
792 | int ret = 0; | ||
793 | |||
794 | #ifdef MDP_HW_VSYNC | ||
795 | mdp_hw_vsync_clk_enable(mfd); | ||
796 | #endif | ||
797 | |||
798 | ret = panel_next_on(pdev); | ||
799 | |||
800 | return ret; | ||
801 | } | ||
802 | |||
803 | static int mdp_irq_clk_setup(void) | ||
804 | { | ||
805 | int ret; | ||
806 | |||
807 | #ifdef CONFIG_FB_MSM_MDP40 | ||
808 | ret = request_irq(INT_MDP, mdp4_isr, IRQF_DISABLED, "MDP", 0); | ||
809 | #else | ||
810 | ret = request_irq(INT_MDP, mdp_isr, IRQF_DISABLED, "MDP", 0); | ||
811 | #endif | ||
812 | if (ret) { | ||
813 | printk(KERN_ERR "mdp request_irq() failed!\n"); | ||
814 | return ret; | ||
815 | } | ||
816 | disable_irq(INT_MDP); | ||
817 | |||
818 | mdp_clk = clk_get(NULL, "mdp_clk"); | ||
819 | |||
820 | if (IS_ERR(mdp_clk)) { | ||
821 | ret = PTR_ERR(mdp_clk); | ||
822 | printk(KERN_ERR "can't get mdp_clk error:%d!\n", ret); | ||
823 | free_irq(INT_MDP, 0); | ||
824 | return ret; | ||
825 | } | ||
826 | |||
827 | mdp_pclk = clk_get(NULL, "mdp_pclk"); | ||
828 | if (IS_ERR(mdp_pclk)) | ||
829 | mdp_pclk = NULL; | ||
830 | |||
831 | |||
832 | #ifdef CONFIG_FB_MSM_MDP40 | ||
833 | /* | ||
834 | * mdp_clk should greater than mdp_pclk always | ||
835 | */ | ||
836 | clk_set_rate(mdp_clk, 122880000); /* 122.88 Mhz */ | ||
837 | printk(KERN_INFO "mdp_clk: mdp_clk=%d mdp_pclk=%d\n", | ||
838 | (int)clk_get_rate(mdp_clk), (int)clk_get_rate(mdp_pclk)); | ||
839 | #endif | ||
840 | |||
841 | return 0; | ||
842 | } | ||
843 | |||
844 | static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST]; | ||
845 | static int pdev_list_cnt; | ||
846 | static int mdp_resource_initialized; | ||
847 | static struct msm_panel_common_pdata *mdp_pdata; | ||
848 | |||
849 | static int mdp_probe(struct platform_device *pdev) | ||
850 | { | ||
851 | struct platform_device *msm_fb_dev = NULL; | ||
852 | struct msm_fb_data_type *mfd; | ||
853 | struct msm_fb_panel_data *pdata = NULL; | ||
854 | int rc; | ||
855 | resource_size_t size ; | ||
856 | #ifdef CONFIG_FB_MSM_MDP40 | ||
857 | int intf, if_no; | ||
858 | #else | ||
859 | unsigned long flag; | ||
860 | #endif | ||
861 | |||
862 | if ((pdev->id == 0) && (pdev->num_resources > 0)) { | ||
863 | mdp_pdata = pdev->dev.platform_data; | ||
864 | |||
865 | size = resource_size(&pdev->resource[0]); | ||
866 | msm_mdp_base = ioremap(pdev->resource[0].start, size); | ||
867 | |||
868 | MSM_FB_INFO("MDP HW Base phy_Address = 0x%x virt = 0x%x\n", | ||
869 | (int)pdev->resource[0].start, (int)msm_mdp_base); | ||
870 | |||
871 | if (unlikely(!msm_mdp_base)) | ||
872 | return -ENOMEM; | ||
873 | |||
874 | printk("irq clk setup\n"); | ||
875 | rc = mdp_irq_clk_setup(); | ||
876 | printk("irq clk setup done\n"); | ||
877 | if (rc) | ||
878 | return rc; | ||
879 | |||
880 | /* initializing mdp hw */ | ||
881 | #ifdef CONFIG_FB_MSM_MDP40 | ||
882 | mdp4_hw_init(); | ||
883 | #else | ||
884 | mdp_hw_init(); | ||
885 | #endif | ||
886 | |||
887 | mdp_resource_initialized = 1; | ||
888 | return 0; | ||
889 | } | ||
890 | |||
891 | if (!mdp_resource_initialized) | ||
892 | return -EPERM; | ||
893 | |||
894 | mfd = platform_get_drvdata(pdev); | ||
895 | |||
896 | if (!mfd) | ||
897 | return -ENODEV; | ||
898 | |||
899 | if (mfd->key != MFD_KEY) | ||
900 | return -EINVAL; | ||
901 | |||
902 | if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST) | ||
903 | return -ENOMEM; | ||
904 | |||
905 | msm_fb_dev = platform_device_alloc("msm_fb", pdev->id); | ||
906 | if (!msm_fb_dev) | ||
907 | return -ENOMEM; | ||
908 | |||
909 | /* link to the latest pdev */ | ||
910 | mfd->pdev = msm_fb_dev; | ||
911 | |||
912 | /* add panel data */ | ||
913 | if (platform_device_add_data | ||
914 | (msm_fb_dev, pdev->dev.platform_data, | ||
915 | sizeof(struct msm_fb_panel_data))) { | ||
916 | printk(KERN_ERR "mdp_probe: platform_device_add_data failed!\n"); | ||
917 | rc = -ENOMEM; | ||
918 | goto mdp_probe_err; | ||
919 | } | ||
920 | /* data chain */ | ||
921 | pdata = msm_fb_dev->dev.platform_data; | ||
922 | pdata->on = mdp_on; | ||
923 | pdata->off = mdp_off; | ||
924 | pdata->next = pdev; | ||
925 | |||
926 | switch (mfd->panel.type) { | ||
927 | case EXT_MDDI_PANEL: | ||
928 | case MDDI_PANEL: | ||
929 | case EBI2_PANEL: | ||
930 | INIT_WORK(&mfd->dma_update_worker, | ||
931 | mdp_lcd_update_workqueue_handler); | ||
932 | INIT_WORK(&mfd->vsync_resync_worker, | ||
933 | mdp_vsync_resync_workqueue_handler); | ||
934 | mfd->hw_refresh = FALSE; | ||
935 | |||
936 | if (mfd->panel.type == EXT_MDDI_PANEL) { | ||
937 | /* 15 fps -> 66 msec */ | ||
938 | mfd->refresh_timer_duration = (66 * HZ / 1000); | ||
939 | } else { | ||
940 | /* 24 fps -> 42 msec */ | ||
941 | mfd->refresh_timer_duration = (42 * HZ / 1000); | ||
942 | } | ||
943 | |||
944 | #ifdef CONFIG_FB_MSM_MDP22 | ||
945 | mfd->dma_fnc = mdp_dma2_update; | ||
946 | mfd->dma = &dma2_data; | ||
947 | #else | ||
948 | if (mfd->panel_info.pdest == DISPLAY_1) { | ||
949 | #ifdef CONFIG_FB_MSM_OVERLAY | ||
950 | mfd->dma_fnc = mdp4_mddi_overlay; | ||
951 | #else | ||
952 | mfd->dma_fnc = mdp_dma2_update; | ||
953 | #endif | ||
954 | mfd->dma = &dma2_data; | ||
955 | mfd->lut_update = mdp_lut_update_nonlcdc; | ||
956 | mfd->do_histogram = mdp_do_histogram; | ||
957 | } else { | ||
958 | mfd->dma_fnc = mdp_dma_s_update; | ||
959 | mfd->dma = &dma_s_data; | ||
960 | } | ||
961 | #endif | ||
962 | if (mdp_pdata) | ||
963 | mfd->vsync_gpio = mdp_pdata->gpio; | ||
964 | else | ||
965 | mfd->vsync_gpio = -1; | ||
966 | |||
967 | #ifdef CONFIG_FB_MSM_MDP40 | ||
968 | if (mfd->panel.type == EBI2_PANEL) | ||
969 | intf = EBI2_INTF; | ||
970 | else | ||
971 | intf = MDDI_INTF; | ||
972 | |||
973 | if (mfd->panel_info.pdest == DISPLAY_1) | ||
974 | if_no = PRIMARY_INTF_SEL; | ||
975 | else | ||
976 | if_no = SECONDARY_INTF_SEL; | ||
977 | |||
978 | mdp4_display_intf_sel(if_no, intf); | ||
979 | #endif | ||
980 | mdp_config_vsync(mfd); | ||
981 | break; | ||
982 | |||
983 | case HDMI_PANEL: | ||
984 | case LCDC_PANEL: | ||
985 | pdata->on = mdp_lcdc_on; | ||
986 | pdata->off = mdp_lcdc_off; | ||
987 | mfd->hw_refresh = TRUE; | ||
988 | mfd->cursor_update = mdp_hw_cursor_update; | ||
989 | #ifndef CONFIG_FB_MSM_MDP22 | ||
990 | mfd->lut_update = mdp_lut_update_lcdc; | ||
991 | mfd->do_histogram = mdp_do_histogram; | ||
992 | #endif | ||
993 | #ifdef CONFIG_FB_MSM_OVERLAY | ||
994 | mfd->dma_fnc = mdp4_lcdc_overlay; | ||
995 | #else | ||
996 | mfd->dma_fnc = mdp_lcdc_update; | ||
997 | #endif | ||
998 | |||
999 | #ifdef CONFIG_FB_MSM_MDP40 | ||
1000 | if (mfd->panel.type == HDMI_PANEL) { | ||
1001 | mfd->dma = &dma_e_data; | ||
1002 | mdp4_display_intf_sel(EXTERNAL_INTF_SEL, LCDC_RGB_INTF); | ||
1003 | } else { | ||
1004 | mfd->dma = &dma2_data; | ||
1005 | mdp4_display_intf_sel(PRIMARY_INTF_SEL, LCDC_RGB_INTF); | ||
1006 | } | ||
1007 | #else | ||
1008 | mfd->dma = &dma2_data; | ||
1009 | spin_lock_irqsave(&mdp_spin_lock, flag); | ||
1010 | mdp_intr_mask &= ~MDP_DMA_P_DONE; | ||
1011 | outp32(MDP_INTR_ENABLE, mdp_intr_mask); | ||
1012 | spin_unlock_irqrestore(&mdp_spin_lock, flag); | ||
1013 | #endif | ||
1014 | break; | ||
1015 | |||
1016 | case TV_PANEL: | ||
1017 | pdata->on = mdp_dma3_on; | ||
1018 | pdata->off = mdp_dma3_off; | ||
1019 | mfd->hw_refresh = TRUE; | ||
1020 | mfd->dma_fnc = mdp_dma3_update; | ||
1021 | mfd->dma = &dma3_data; | ||
1022 | break; | ||
1023 | |||
1024 | default: | ||
1025 | printk(KERN_ERR "mdp_probe: unknown device type!\n"); | ||
1026 | rc = -ENODEV; | ||
1027 | goto mdp_probe_err; | ||
1028 | } | ||
1029 | |||
1030 | /* set driver data */ | ||
1031 | platform_set_drvdata(msm_fb_dev, mfd); | ||
1032 | |||
1033 | rc = platform_device_add(msm_fb_dev); | ||
1034 | if (rc) { | ||
1035 | goto mdp_probe_err; | ||
1036 | } | ||
1037 | |||
1038 | pdev_list[pdev_list_cnt++] = pdev; | ||
1039 | return 0; | ||
1040 | |||
1041 | mdp_probe_err: | ||
1042 | platform_device_put(msm_fb_dev); | ||
1043 | return rc; | ||
1044 | } | ||
1045 | |||
1046 | static void mdp_suspend_sub(void) | ||
1047 | { | ||
1048 | /* cancel pipe ctrl worker */ | ||
1049 | cancel_delayed_work(&mdp_pipe_ctrl_worker); | ||
1050 | |||
1051 | /* for workder can't be cancelled... */ | ||
1052 | flush_workqueue(mdp_pipe_ctrl_wq); | ||
1053 | |||
1054 | /* let's wait for PPP completion */ | ||
1055 | while (mdp_block_power_cnt[MDP_PPP_BLOCK] > 0) ; | ||
1056 | |||
1057 | /* try to power down */ | ||
1058 | mdp_pipe_ctrl(MDP_MASTER_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); | ||
1059 | } | ||
1060 | |||
1061 | #if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND) | ||
1062 | static int mdp_suspend(struct platform_device *pdev, pm_message_t state) | ||
1063 | { | ||
1064 | mdp_suspend_sub(); | ||
1065 | return 0; | ||
1066 | } | ||
1067 | #endif | ||
1068 | |||
1069 | #ifdef CONFIG_HAS_EARLYSUSPEND | ||
1070 | static void mdp_early_suspend(struct early_suspend *h) | ||
1071 | { | ||
1072 | mdp_suspend_sub(); | ||
1073 | } | ||
1074 | #endif | ||
1075 | |||
1076 | static int mdp_remove(struct platform_device *pdev) | ||
1077 | { | ||
1078 | iounmap(msm_mdp_base); | ||
1079 | return 0; | ||
1080 | } | ||
1081 | |||
1082 | static int mdp_register_driver(void) | ||
1083 | { | ||
1084 | #ifdef CONFIG_HAS_EARLYSUSPEND | ||
1085 | early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 1; | ||
1086 | early_suspend.suspend = mdp_early_suspend; | ||
1087 | register_early_suspend(&early_suspend); | ||
1088 | #endif | ||
1089 | |||
1090 | return platform_driver_register(&mdp_driver); | ||
1091 | } | ||
1092 | |||
1093 | static int __init mdp_driver_init(void) | ||
1094 | { | ||
1095 | int ret; | ||
1096 | |||
1097 | mdp_drv_init(); | ||
1098 | |||
1099 | ret = mdp_register_driver(); | ||
1100 | if (ret) { | ||
1101 | printk(KERN_ERR "mdp_register_driver() failed!\n"); | ||
1102 | return ret; | ||
1103 | } | ||
1104 | |||
1105 | #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_FB_MSM_MDP40) | ||
1106 | mdp4_debugfs_init(); | ||
1107 | #endif | ||
1108 | |||
1109 | return 0; | ||
1110 | |||
1111 | } | ||
1112 | |||
1113 | module_init(mdp_driver_init); | ||
diff --git a/drivers/staging/msm/mdp.h b/drivers/staging/msm/mdp.h new file mode 100644 index 000000000000..0a5d6ac386ac --- /dev/null +++ b/drivers/staging/msm/mdp.h | |||
@@ -0,0 +1,695 @@ | |||
1 | /* Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * Redistribution and use in source and binary forms, with or without | ||
4 | * modification, are permitted provided that the following conditions are met: | ||
5 | * * Redistributions of source code must retain the above copyright | ||
6 | * notice, this list of conditions and the following disclaimer. | ||
7 | * * Redistributions in binary form must reproduce the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer in the | ||
9 | * documentation and/or other materials provided with the distribution. | ||
10 | * * Neither the name of Code Aurora nor | ||
11 | * the names of its contributors may be used to endorse or promote | ||
12 | * products derived from this software without specific prior written | ||
13 | * permission. | ||
14 | * | ||
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
17 | * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
18 | * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||
19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||
20 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||
21 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | ||
22 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | ||
23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||
24 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | ||
25 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | * | ||
27 | */ | ||
28 | |||
29 | #ifndef MDP_H | ||
30 | #define MDP_H | ||
31 | |||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/sched.h> | ||
34 | #include <linux/time.h> | ||
35 | #include <linux/init.h> | ||
36 | #include <linux/interrupt.h> | ||
37 | #include <linux/fb.h> | ||
38 | #include <linux/hrtimer.h> | ||
39 | #include "msm_mdp.h" | ||
40 | |||
41 | #include <mach/hardware.h> | ||
42 | #include <linux/io.h> | ||
43 | |||
44 | #include <asm/system.h> | ||
45 | #include <asm/mach-types.h> | ||
46 | |||
47 | #include "msm_fb_panel.h" | ||
48 | |||
49 | #ifdef CONFIG_MDP_PPP_ASYNC_OP | ||
50 | #include "mdp_ppp_dq.h" | ||
51 | #endif | ||
52 | |||
53 | #ifdef BIT | ||
54 | #undef BIT | ||
55 | #endif | ||
56 | |||
57 | #define BIT(x) (1<<(x)) | ||
58 | |||
59 | #define MDPOP_NOP 0 | ||
60 | #define MDPOP_LR BIT(0) /* left to right flip */ | ||
61 | #define MDPOP_UD BIT(1) /* up and down flip */ | ||
62 | #define MDPOP_ROT90 BIT(2) /* rotate image to 90 degree */ | ||
63 | #define MDPOP_ROT180 (MDPOP_UD|MDPOP_LR) | ||
64 | #define MDPOP_ROT270 (MDPOP_ROT90|MDPOP_UD|MDPOP_LR) | ||
65 | #define MDPOP_ASCALE BIT(7) | ||
66 | #define MDPOP_ALPHAB BIT(8) /* enable alpha blending */ | ||
67 | #define MDPOP_TRANSP BIT(9) /* enable transparency */ | ||
68 | #define MDPOP_DITHER BIT(10) /* enable dither */ | ||
69 | #define MDPOP_SHARPENING BIT(11) /* enable sharpening */ | ||
70 | #define MDPOP_BLUR BIT(12) /* enable blur */ | ||
71 | #define MDPOP_FG_PM_ALPHA BIT(13) | ||
72 | |||
73 | struct mdp_table_entry { | ||
74 | uint32_t reg; | ||
75 | uint32_t val; | ||
76 | }; | ||
77 | |||
78 | extern struct mdp_ccs mdp_ccs_yuv2rgb ; | ||
79 | extern struct mdp_ccs mdp_ccs_rgb2yuv ; | ||
80 | |||
81 | /* | ||
82 | * MDP Image Structure | ||
83 | */ | ||
84 | typedef struct mdpImg_ { | ||
85 | uint32 imgType; /* Image type */ | ||
86 | uint32 *bmy_addr; /* bitmap or y addr */ | ||
87 | uint32 *cbcr_addr; /* cbcr addr */ | ||
88 | uint32 width; /* image width */ | ||
89 | uint32 mdpOp; /* image opertion (rotation,flip up/down, alpha/tp) */ | ||
90 | uint32 tpVal; /* transparency color */ | ||
91 | uint32 alpha; /* alpha percentage 0%(0x0) ~ 100%(0x100) */ | ||
92 | int sp_value; /* sharpening strength */ | ||
93 | } MDPIMG; | ||
94 | |||
95 | #ifdef CONFIG_MDP_PPP_ASYNC_OP | ||
96 | #define MDP_OUTP(addr, data) mdp_ppp_outdw((uint32_t)(addr), \ | ||
97 | (uint32_t)(data)) | ||
98 | #else | ||
99 | #define MDP_OUTP(addr, data) outpdw((addr), (data)) | ||
100 | #endif | ||
101 | |||
102 | #define MDP_KTIME2USEC(kt) (kt.tv.sec*1000000 + kt.tv.nsec/1000) | ||
103 | |||
104 | #define MDP_BASE msm_mdp_base | ||
105 | |||
106 | typedef enum { | ||
107 | MDP_BC_SCALE_POINT2_POINT4, | ||
108 | MDP_BC_SCALE_POINT4_POINT6, | ||
109 | MDP_BC_SCALE_POINT6_POINT8, | ||
110 | MDP_BC_SCALE_POINT8_1, | ||
111 | MDP_BC_SCALE_UP, | ||
112 | MDP_PR_SCALE_POINT2_POINT4, | ||
113 | MDP_PR_SCALE_POINT4_POINT6, | ||
114 | MDP_PR_SCALE_POINT6_POINT8, | ||
115 | MDP_PR_SCALE_POINT8_1, | ||
116 | MDP_PR_SCALE_UP, | ||
117 | MDP_SCALE_BLUR, | ||
118 | MDP_INIT_SCALE | ||
119 | } MDP_SCALE_MODE; | ||
120 | |||
121 | typedef enum { | ||
122 | MDP_BLOCK_POWER_OFF, | ||
123 | MDP_BLOCK_POWER_ON | ||
124 | } MDP_BLOCK_POWER_STATE; | ||
125 | |||
126 | typedef enum { | ||
127 | MDP_MASTER_BLOCK, | ||
128 | MDP_CMD_BLOCK, | ||
129 | MDP_PPP_BLOCK, | ||
130 | MDP_DMA2_BLOCK, | ||
131 | MDP_DMA3_BLOCK, | ||
132 | MDP_DMA_S_BLOCK, | ||
133 | MDP_DMA_E_BLOCK, | ||
134 | MDP_OVERLAY0_BLOCK, | ||
135 | MDP_OVERLAY1_BLOCK, | ||
136 | MDP_MAX_BLOCK | ||
137 | } MDP_BLOCK_TYPE; | ||
138 | |||
139 | /* Let's keep Q Factor power of 2 for optimization */ | ||
140 | #define MDP_SCALE_Q_FACTOR 512 | ||
141 | |||
142 | #ifdef CONFIG_FB_MSM_MDP31 | ||
143 | #define MDP_MAX_X_SCALE_FACTOR (MDP_SCALE_Q_FACTOR*8) | ||
144 | #define MDP_MIN_X_SCALE_FACTOR (MDP_SCALE_Q_FACTOR/8) | ||
145 | #define MDP_MAX_Y_SCALE_FACTOR (MDP_SCALE_Q_FACTOR*8) | ||
146 | #define MDP_MIN_Y_SCALE_FACTOR (MDP_SCALE_Q_FACTOR/8) | ||
147 | #else | ||
148 | #define MDP_MAX_X_SCALE_FACTOR (MDP_SCALE_Q_FACTOR*4) | ||
149 | #define MDP_MIN_X_SCALE_FACTOR (MDP_SCALE_Q_FACTOR/4) | ||
150 | #define MDP_MAX_Y_SCALE_FACTOR (MDP_SCALE_Q_FACTOR*4) | ||
151 | #define MDP_MIN_Y_SCALE_FACTOR (MDP_SCALE_Q_FACTOR/4) | ||
152 | #endif | ||
153 | |||
154 | /* SHIM Q Factor */ | ||
155 | #define PHI_Q_FACTOR 29 | ||
156 | #define PQF_PLUS_5 (PHI_Q_FACTOR + 5) /* due to 32 phases */ | ||
157 | #define PQF_PLUS_4 (PHI_Q_FACTOR + 4) | ||
158 | #define PQF_PLUS_2 (PHI_Q_FACTOR + 2) /* to get 4.0 */ | ||
159 | #define PQF_MINUS_2 (PHI_Q_FACTOR - 2) /* to get 0.25 */ | ||
160 | #define PQF_PLUS_5_PLUS_2 (PQF_PLUS_5 + 2) | ||
161 | #define PQF_PLUS_5_MINUS_2 (PQF_PLUS_5 - 2) | ||
162 | |||
163 | #define MDP_CONVTP(tpVal) (((tpVal&0xF800)<<8)|((tpVal&0x7E0)<<5)|((tpVal&0x1F)<<3)) | ||
164 | |||
165 | #define MDPOP_ROTATION (MDPOP_ROT90|MDPOP_LR|MDPOP_UD) | ||
166 | #define MDP_CHKBIT(val, bit) ((bit) == ((val) & (bit))) | ||
167 | |||
168 | /* overlay interface API defines */ | ||
169 | typedef enum { | ||
170 | MORE_IBUF, | ||
171 | FINAL_IBUF, | ||
172 | COMPLETE_IBUF | ||
173 | } MDP_IBUF_STATE; | ||
174 | |||
175 | struct mdp_dirty_region { | ||
176 | __u32 xoffset; /* source origin in the x-axis */ | ||
177 | __u32 yoffset; /* source origin in the y-axis */ | ||
178 | __u32 width; /* number of pixels in the x-axis */ | ||
179 | __u32 height; /* number of pixels in the y-axis */ | ||
180 | }; | ||
181 | |||
182 | /* | ||
183 | * MDP extended data types | ||
184 | */ | ||
185 | typedef struct mdp_roi_s { | ||
186 | uint32 x; | ||
187 | uint32 y; | ||
188 | uint32 width; | ||
189 | uint32 height; | ||
190 | int32 lcd_x; | ||
191 | int32 lcd_y; | ||
192 | uint32 dst_width; | ||
193 | uint32 dst_height; | ||
194 | } MDP_ROI; | ||
195 | |||
196 | typedef struct mdp_ibuf_s { | ||
197 | uint8 *buf; | ||
198 | uint32 bpp; | ||
199 | uint32 ibuf_type; | ||
200 | uint32 ibuf_width; | ||
201 | uint32 ibuf_height; | ||
202 | |||
203 | MDP_ROI roi; | ||
204 | MDPIMG mdpImg; | ||
205 | |||
206 | int32 dma_x; | ||
207 | int32 dma_y; | ||
208 | uint32 dma_w; | ||
209 | uint32 dma_h; | ||
210 | |||
211 | uint32 vsync_enable; | ||
212 | uint32 visible_swapped; | ||
213 | } MDPIBUF; | ||
214 | |||
215 | struct mdp_dma_data { | ||
216 | boolean busy; | ||
217 | boolean waiting; | ||
218 | struct mutex ov_mutex; | ||
219 | struct semaphore mutex; | ||
220 | struct completion comp; | ||
221 | }; | ||
222 | |||
223 | #define MDP_CMD_DEBUG_ACCESS_BASE (MDP_BASE+0x10000) | ||
224 | |||
225 | #define MDP_DMA2_TERM 0x1 | ||
226 | #define MDP_DMA3_TERM 0x2 | ||
227 | #define MDP_PPP_TERM 0x4 | ||
228 | #define MDP_DMA_S_TERM 0x8 | ||
229 | #ifdef CONFIG_FB_MSM_MDP40 | ||
230 | #define MDP_DMA_E_TERM 0x10 | ||
231 | #define MDP_OVERLAY0_TERM 0x20 | ||
232 | #define MDP_OVERLAY1_TERM 0x40 | ||
233 | #endif | ||
234 | |||
235 | #define ACTIVE_START_X_EN BIT(31) | ||
236 | #define ACTIVE_START_Y_EN BIT(31) | ||
237 | #define ACTIVE_HIGH 0 | ||
238 | #define ACTIVE_LOW 1 | ||
239 | #define MDP_DMA_S_DONE BIT(2) | ||
240 | #define LCDC_FRAME_START BIT(15) | ||
241 | #define LCDC_UNDERFLOW BIT(16) | ||
242 | |||
243 | #ifdef CONFIG_FB_MSM_MDP22 | ||
244 | #define MDP_DMA_P_DONE BIT(2) | ||
245 | #else | ||
246 | #define MDP_DMA_P_DONE BIT(14) | ||
247 | #endif | ||
248 | |||
249 | #define MDP_PPP_DONE BIT(0) | ||
250 | #define TV_OUT_DMA3_DONE BIT(6) | ||
251 | #define TV_ENC_UNDERRUN BIT(7) | ||
252 | #define TV_OUT_DMA3_START BIT(13) | ||
253 | #define MDP_HIST_DONE BIT(20) | ||
254 | |||
255 | #ifdef CONFIG_FB_MSM_MDP22 | ||
256 | #define MDP_ANY_INTR_MASK (MDP_PPP_DONE| \ | ||
257 | MDP_DMA_P_DONE| \ | ||
258 | TV_ENC_UNDERRUN) | ||
259 | #else | ||
260 | #define MDP_ANY_INTR_MASK (MDP_PPP_DONE| \ | ||
261 | MDP_DMA_P_DONE| \ | ||
262 | MDP_DMA_S_DONE| \ | ||
263 | LCDC_UNDERFLOW| \ | ||
264 | MDP_HIST_DONE| \ | ||
265 | TV_ENC_UNDERRUN) | ||
266 | #endif | ||
267 | |||
268 | #define MDP_TOP_LUMA 16 | ||
269 | #define MDP_TOP_CHROMA 0 | ||
270 | #define MDP_BOTTOM_LUMA 19 | ||
271 | #define MDP_BOTTOM_CHROMA 3 | ||
272 | #define MDP_LEFT_LUMA 22 | ||
273 | #define MDP_LEFT_CHROMA 6 | ||
274 | #define MDP_RIGHT_LUMA 25 | ||
275 | #define MDP_RIGHT_CHROMA 9 | ||
276 | |||
277 | #define CLR_G 0x0 | ||
278 | #define CLR_B 0x1 | ||
279 | #define CLR_R 0x2 | ||
280 | #define CLR_ALPHA 0x3 | ||
281 | |||
282 | #define CLR_Y CLR_G | ||
283 | #define CLR_CB CLR_B | ||
284 | #define CLR_CR CLR_R | ||
285 | |||
286 | /* from lsb to msb */ | ||
287 | #define MDP_GET_PACK_PATTERN(a,x,y,z,bit) (((a)<<(bit*3))|((x)<<(bit*2))|((y)<<bit)|(z)) | ||
288 | |||
289 | /* | ||
290 | * 0x0000 0x0004 0x0008 MDP sync config | ||
291 | */ | ||
292 | #ifdef CONFIG_FB_MSM_MDP22 | ||
293 | #define MDP_SYNCFG_HGT_LOC 22 | ||
294 | #define MDP_SYNCFG_VSYNC_EXT_EN BIT(21) | ||
295 | #define MDP_SYNCFG_VSYNC_INT_EN BIT(20) | ||
296 | #else | ||
297 | #define MDP_SYNCFG_HGT_LOC 21 | ||
298 | #define MDP_SYNCFG_VSYNC_EXT_EN BIT(20) | ||
299 | #define MDP_SYNCFG_VSYNC_INT_EN BIT(19) | ||
300 | #define MDP_HW_VSYNC | ||
301 | #endif | ||
302 | |||
303 | /* | ||
304 | * 0x0018 MDP VSYNC THREASH | ||
305 | */ | ||
306 | #define MDP_PRIM_BELOW_LOC 0 | ||
307 | #define MDP_PRIM_ABOVE_LOC 8 | ||
308 | |||
309 | /* | ||
310 | * MDP_PRIMARY_VSYNC_OUT_CTRL | ||
311 | * 0x0080,84,88 internal vsync pulse config | ||
312 | */ | ||
313 | #define VSYNC_PULSE_EN BIT(31) | ||
314 | #define VSYNC_PULSE_INV BIT(30) | ||
315 | |||
316 | /* | ||
317 | * 0x008c MDP VSYNC CONTROL | ||
318 | */ | ||
319 | #define DISP0_VSYNC_MAP_VSYNC0 0 | ||
320 | #define DISP0_VSYNC_MAP_VSYNC1 BIT(0) | ||
321 | #define DISP0_VSYNC_MAP_VSYNC2 BIT(0)|BIT(1) | ||
322 | |||
323 | #define DISP1_VSYNC_MAP_VSYNC0 0 | ||
324 | #define DISP1_VSYNC_MAP_VSYNC1 BIT(2) | ||
325 | #define DISP1_VSYNC_MAP_VSYNC2 BIT(2)|BIT(3) | ||
326 | |||
327 | #define PRIMARY_LCD_SYNC_EN BIT(4) | ||
328 | #define PRIMARY_LCD_SYNC_DISABLE 0 | ||
329 | |||
330 | #define SECONDARY_LCD_SYNC_EN BIT(5) | ||
331 | #define SECONDARY_LCD_SYNC_DISABLE 0 | ||
332 | |||
333 | #define EXTERNAL_LCD_SYNC_EN BIT(6) | ||
334 | #define EXTERNAL_LCD_SYNC_DISABLE 0 | ||
335 | |||
336 | /* | ||
337 | * 0x101f0 MDP VSYNC Threshold | ||
338 | */ | ||
339 | #define VSYNC_THRESHOLD_ABOVE_LOC 0 | ||
340 | #define VSYNC_THRESHOLD_BELOW_LOC 16 | ||
341 | #define VSYNC_ANTI_TEAR_EN BIT(31) | ||
342 | |||
343 | /* | ||
344 | * 0x10004 command config | ||
345 | */ | ||
346 | #define MDP_CMD_DBGBUS_EN BIT(0) | ||
347 | |||
348 | /* | ||
349 | * 0x10124 or 0x101d4PPP source config | ||
350 | */ | ||
351 | #define PPP_SRC_C0G_8BITS (BIT(1)|BIT(0)) | ||
352 | #define PPP_SRC_C1B_8BITS (BIT(3)|BIT(2)) | ||
353 | #define PPP_SRC_C2R_8BITS (BIT(5)|BIT(4)) | ||
354 | #define PPP_SRC_C3A_8BITS (BIT(7)|BIT(6)) | ||
355 | |||
356 | #define PPP_SRC_C0G_6BITS BIT(1) | ||
357 | #define PPP_SRC_C1B_6BITS BIT(3) | ||
358 | #define PPP_SRC_C2R_6BITS BIT(5) | ||
359 | |||
360 | #define PPP_SRC_C0G_5BITS BIT(0) | ||
361 | #define PPP_SRC_C1B_5BITS BIT(2) | ||
362 | #define PPP_SRC_C2R_5BITS BIT(4) | ||
363 | |||
364 | #define PPP_SRC_C3_ALPHA_EN BIT(8) | ||
365 | |||
366 | #define PPP_SRC_BPP_INTERLVD_1BYTES 0 | ||
367 | #define PPP_SRC_BPP_INTERLVD_2BYTES BIT(9) | ||
368 | #define PPP_SRC_BPP_INTERLVD_3BYTES BIT(10) | ||
369 | #define PPP_SRC_BPP_INTERLVD_4BYTES (BIT(10)|BIT(9)) | ||
370 | |||
371 | #define PPP_SRC_BPP_ROI_ODD_X BIT(11) | ||
372 | #define PPP_SRC_BPP_ROI_ODD_Y BIT(12) | ||
373 | #define PPP_SRC_INTERLVD_2COMPONENTS BIT(13) | ||
374 | #define PPP_SRC_INTERLVD_3COMPONENTS BIT(14) | ||
375 | #define PPP_SRC_INTERLVD_4COMPONENTS (BIT(14)|BIT(13)) | ||
376 | |||
377 | /* | ||
378 | * RGB666 unpack format | ||
379 | * TIGHT means R6+G6+B6 together | ||
380 | * LOOSE means R6+2 +G6+2+ B6+2 (with MSB) | ||
381 | * or 2+R6 +2+G6 +2+B6 (with LSB) | ||
382 | */ | ||
383 | #define PPP_SRC_UNPACK_TIGHT BIT(17) | ||
384 | #define PPP_SRC_UNPACK_LOOSE 0 | ||
385 | #define PPP_SRC_UNPACK_ALIGN_LSB 0 | ||
386 | #define PPP_SRC_UNPACK_ALIGN_MSB BIT(18) | ||
387 | |||
388 | #define PPP_SRC_FETCH_PLANES_INTERLVD 0 | ||
389 | #define PPP_SRC_FETCH_PLANES_PSEUDOPLNR BIT(20) | ||
390 | |||
391 | #define PPP_SRC_WMV9_MODE BIT(21) /* window media version 9 */ | ||
392 | |||
393 | /* | ||
394 | * 0x10138 PPP operation config | ||
395 | */ | ||
396 | #define PPP_OP_SCALE_X_ON BIT(0) | ||
397 | #define PPP_OP_SCALE_Y_ON BIT(1) | ||
398 | |||
399 | #define PPP_OP_CONVERT_RGB2YCBCR 0 | ||
400 | #define PPP_OP_CONVERT_YCBCR2RGB BIT(2) | ||
401 | #define PPP_OP_CONVERT_ON BIT(3) | ||
402 | |||
403 | #define PPP_OP_CONVERT_MATRIX_PRIMARY 0 | ||
404 | #define PPP_OP_CONVERT_MATRIX_SECONDARY BIT(4) | ||
405 | |||
406 | #define PPP_OP_LUT_C0_ON BIT(5) | ||
407 | #define PPP_OP_LUT_C1_ON BIT(6) | ||
408 | #define PPP_OP_LUT_C2_ON BIT(7) | ||
409 | |||
410 | /* rotate or blend enable */ | ||
411 | #define PPP_OP_ROT_ON BIT(8) | ||
412 | |||
413 | #define PPP_OP_ROT_90 BIT(9) | ||
414 | #define PPP_OP_FLIP_LR BIT(10) | ||
415 | #define PPP_OP_FLIP_UD BIT(11) | ||
416 | |||
417 | #define PPP_OP_BLEND_ON BIT(12) | ||
418 | |||
419 | #define PPP_OP_BLEND_SRCPIXEL_ALPHA 0 | ||
420 | #define PPP_OP_BLEND_DSTPIXEL_ALPHA BIT(13) | ||
421 | #define PPP_OP_BLEND_CONSTANT_ALPHA BIT(14) | ||
422 | #define PPP_OP_BLEND_SRCPIXEL_TRANSP (BIT(13)|BIT(14)) | ||
423 | |||
424 | #define PPP_OP_BLEND_ALPHA_BLEND_NORMAL 0 | ||
425 | #define PPP_OP_BLEND_ALPHA_BLEND_REVERSE BIT(15) | ||
426 | |||
427 | #define PPP_OP_DITHER_EN BIT(16) | ||
428 | |||
429 | #define PPP_OP_COLOR_SPACE_RGB 0 | ||
430 | #define PPP_OP_COLOR_SPACE_YCBCR BIT(17) | ||
431 | |||
432 | #define PPP_OP_SRC_CHROMA_RGB 0 | ||
433 | #define PPP_OP_SRC_CHROMA_H2V1 BIT(18) | ||
434 | #define PPP_OP_SRC_CHROMA_H1V2 BIT(19) | ||
435 | #define PPP_OP_SRC_CHROMA_420 (BIT(18)|BIT(19)) | ||
436 | #define PPP_OP_SRC_CHROMA_COSITE 0 | ||
437 | #define PPP_OP_SRC_CHROMA_OFFSITE BIT(20) | ||
438 | |||
439 | #define PPP_OP_DST_CHROMA_RGB 0 | ||
440 | #define PPP_OP_DST_CHROMA_H2V1 BIT(21) | ||
441 | #define PPP_OP_DST_CHROMA_H1V2 BIT(22) | ||
442 | #define PPP_OP_DST_CHROMA_420 (BIT(21)|BIT(22)) | ||
443 | #define PPP_OP_DST_CHROMA_COSITE 0 | ||
444 | #define PPP_OP_DST_CHROMA_OFFSITE BIT(23) | ||
445 | |||
446 | #define PPP_BLEND_CALPHA_TRNASP BIT(24) | ||
447 | |||
448 | #define PPP_OP_BG_CHROMA_RGB 0 | ||
449 | #define PPP_OP_BG_CHROMA_H2V1 BIT(25) | ||
450 | #define PPP_OP_BG_CHROMA_H1V2 BIT(26) | ||
451 | #define PPP_OP_BG_CHROMA_420 BIT(25)|BIT(26) | ||
452 | #define PPP_OP_BG_CHROMA_SITE_COSITE 0 | ||
453 | #define PPP_OP_BG_CHROMA_SITE_OFFSITE BIT(27) | ||
454 | #define PPP_OP_DEINT_EN BIT(29) | ||
455 | |||
456 | #define PPP_BLEND_BG_USE_ALPHA_SEL (1 << 0) | ||
457 | #define PPP_BLEND_BG_ALPHA_REVERSE (1 << 3) | ||
458 | #define PPP_BLEND_BG_SRCPIXEL_ALPHA (0 << 1) | ||
459 | #define PPP_BLEND_BG_DSTPIXEL_ALPHA (1 << 1) | ||
460 | #define PPP_BLEND_BG_CONSTANT_ALPHA (2 << 1) | ||
461 | #define PPP_BLEND_BG_CONST_ALPHA_VAL(x) ((x) << 24) | ||
462 | |||
463 | #define PPP_OP_DST_RGB 0 | ||
464 | #define PPP_OP_DST_YCBCR BIT(30) | ||
465 | /* | ||
466 | * 0x10150 PPP destination config | ||
467 | */ | ||
468 | #define PPP_DST_C0G_8BIT (BIT(0)|BIT(1)) | ||
469 | #define PPP_DST_C1B_8BIT (BIT(3)|BIT(2)) | ||
470 | #define PPP_DST_C2R_8BIT (BIT(5)|BIT(4)) | ||
471 | #define PPP_DST_C3A_8BIT (BIT(7)|BIT(6)) | ||
472 | |||
473 | #define PPP_DST_C0G_6BIT BIT(1) | ||
474 | #define PPP_DST_C1B_6BIT BIT(3) | ||
475 | #define PPP_DST_C2R_6BIT BIT(5) | ||
476 | |||
477 | #define PPP_DST_C0G_5BIT BIT(0) | ||
478 | #define PPP_DST_C1B_5BIT BIT(2) | ||
479 | #define PPP_DST_C2R_5BIT BIT(4) | ||
480 | |||
481 | #define PPP_DST_C3A_8BIT (BIT(7)|BIT(6)) | ||
482 | #define PPP_DST_C3ALPHA_EN BIT(8) | ||
483 | |||
484 | #define PPP_DST_PACKET_CNT_INTERLVD_2ELEM BIT(9) | ||
485 | #define PPP_DST_PACKET_CNT_INTERLVD_3ELEM BIT(10) | ||
486 | #define PPP_DST_PACKET_CNT_INTERLVD_4ELEM (BIT(10)|BIT(9)) | ||
487 | #define PPP_DST_PACKET_CNT_INTERLVD_6ELEM (BIT(11)|BIT(9)) | ||
488 | |||
489 | #define PPP_DST_PACK_LOOSE 0 | ||
490 | #define PPP_DST_PACK_TIGHT BIT(13) | ||
491 | #define PPP_DST_PACK_ALIGN_LSB 0 | ||
492 | #define PPP_DST_PACK_ALIGN_MSB BIT(14) | ||
493 | |||
494 | #define PPP_DST_OUT_SEL_AXI 0 | ||
495 | #define PPP_DST_OUT_SEL_MDDI BIT(15) | ||
496 | |||
497 | #define PPP_DST_BPP_2BYTES BIT(16) | ||
498 | #define PPP_DST_BPP_3BYTES BIT(17) | ||
499 | #define PPP_DST_BPP_4BYTES (BIT(17)|BIT(16)) | ||
500 | |||
501 | #define PPP_DST_PLANE_INTERLVD 0 | ||
502 | #define PPP_DST_PLANE_PLANAR BIT(18) | ||
503 | #define PPP_DST_PLANE_PSEUDOPLN BIT(19) | ||
504 | |||
505 | #define PPP_DST_TO_TV BIT(20) | ||
506 | |||
507 | #define PPP_DST_MDDI_PRIMARY 0 | ||
508 | #define PPP_DST_MDDI_SECONDARY BIT(21) | ||
509 | #define PPP_DST_MDDI_EXTERNAL BIT(22) | ||
510 | |||
511 | /* | ||
512 | * 0x10180 DMA config | ||
513 | */ | ||
514 | #define DMA_DSTC0G_8BITS (BIT(1)|BIT(0)) | ||
515 | #define DMA_DSTC1B_8BITS (BIT(3)|BIT(2)) | ||
516 | #define DMA_DSTC2R_8BITS (BIT(5)|BIT(4)) | ||
517 | |||
518 | #define DMA_DSTC0G_6BITS BIT(1) | ||
519 | #define DMA_DSTC1B_6BITS BIT(3) | ||
520 | #define DMA_DSTC2R_6BITS BIT(5) | ||
521 | |||
522 | #define DMA_DSTC0G_5BITS BIT(0) | ||
523 | #define DMA_DSTC1B_5BITS BIT(2) | ||
524 | #define DMA_DSTC2R_5BITS BIT(4) | ||
525 | |||
526 | #define DMA_PACK_TIGHT BIT(6) | ||
527 | #define DMA_PACK_LOOSE 0 | ||
528 | #define DMA_PACK_ALIGN_LSB 0 | ||
529 | /* | ||
530 | * use DMA_PACK_ALIGN_MSB if the upper 6 bits from 8 bits output | ||
531 | * from LCDC block maps into 6 pins out to the panel | ||
532 | */ | ||
533 | #define DMA_PACK_ALIGN_MSB BIT(7) | ||
534 | #define DMA_PACK_PATTERN_RGB \ | ||
535 | (MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 2)<<8) | ||
536 | #define DMA_PACK_PATTERN_BGR \ | ||
537 | (MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 2)<<8) | ||
538 | #define DMA_OUT_SEL_AHB 0 | ||
539 | #define DMA_OUT_SEL_LCDC BIT(20) | ||
540 | #define DMA_IBUF_FORMAT_RGB888 0 | ||
541 | #define DMA_IBUF_FORMAT_xRGB8888_OR_ARGB8888 BIT(26) | ||
542 | |||
543 | #ifdef CONFIG_FB_MSM_MDP22 | ||
544 | #define DMA_OUT_SEL_MDDI BIT(14) | ||
545 | #define DMA_AHBM_LCD_SEL_PRIMARY 0 | ||
546 | #define DMA_AHBM_LCD_SEL_SECONDARY BIT(15) | ||
547 | #define DMA_IBUF_C3ALPHA_EN BIT(16) | ||
548 | #define DMA_DITHER_EN BIT(17) | ||
549 | #define DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY 0 | ||
550 | #define DMA_MDDI_DMAOUT_LCD_SEL_SECONDARY BIT(18) | ||
551 | #define DMA_MDDI_DMAOUT_LCD_SEL_EXTERNAL BIT(19) | ||
552 | #define DMA_IBUF_FORMAT_RGB565 BIT(20) | ||
553 | #define DMA_IBUF_FORMAT_RGB888_OR_ARGB8888 0 | ||
554 | #define DMA_IBUF_NONCONTIGUOUS BIT(21) | ||
555 | #else | ||
556 | #define DMA_OUT_SEL_MDDI BIT(19) | ||
557 | #define DMA_AHBM_LCD_SEL_PRIMARY 0 | ||
558 | #define DMA_AHBM_LCD_SEL_SECONDARY 0 | ||
559 | #define DMA_IBUF_C3ALPHA_EN 0 | ||
560 | #define DMA_DITHER_EN BIT(24) | ||
561 | #define DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY 0 | ||
562 | #define DMA_MDDI_DMAOUT_LCD_SEL_SECONDARY 0 | ||
563 | #define DMA_MDDI_DMAOUT_LCD_SEL_EXTERNAL 0 | ||
564 | #define DMA_IBUF_FORMAT_RGB565 BIT(25) | ||
565 | #define DMA_IBUF_NONCONTIGUOUS 0 | ||
566 | #endif | ||
567 | |||
568 | /* | ||
569 | * MDDI Register | ||
570 | */ | ||
571 | #define MDDI_VDO_PACKET_DESC 0x5666 | ||
572 | |||
573 | #ifdef CONFIG_FB_MSM_MDP40 | ||
574 | #define MDP_INTR_ENABLE (msm_mdp_base + 0x0050) | ||
575 | #define MDP_INTR_STATUS (msm_mdp_base + 0x0054) | ||
576 | #define MDP_INTR_CLEAR (msm_mdp_base + 0x0058) | ||
577 | #define MDP_EBI2_LCD0 (msm_mdp_base + 0x0060) | ||
578 | #define MDP_EBI2_LCD1 (msm_mdp_base + 0x0064) | ||
579 | #define MDP_EBI2_PORTMAP_MODE (msm_mdp_base + 0x0070) | ||
580 | |||
581 | #define MDP_DMA_P_HIST_INTR_STATUS (msm_mdp_base + 0x95014) | ||
582 | #define MDP_DMA_P_HIST_INTR_CLEAR (msm_mdp_base + 0x95018) | ||
583 | #define MDP_DMA_P_HIST_INTR_ENABLE (msm_mdp_base + 0x9501C) | ||
584 | #else | ||
585 | #define MDP_INTR_ENABLE (msm_mdp_base + 0x0020) | ||
586 | #define MDP_INTR_STATUS (msm_mdp_base + 0x0024) | ||
587 | #define MDP_INTR_CLEAR (msm_mdp_base + 0x0028) | ||
588 | #define MDP_EBI2_LCD0 (msm_mdp_base + 0x003c) | ||
589 | #define MDP_EBI2_LCD1 (msm_mdp_base + 0x0040) | ||
590 | #define MDP_EBI2_PORTMAP_MODE (msm_mdp_base + 0x005c) | ||
591 | #endif | ||
592 | |||
593 | #define MDP_FULL_BYPASS_WORD43 (msm_mdp_base + 0x101ac) | ||
594 | |||
595 | #define MDP_CSC_PFMVn(n) (msm_mdp_base + 0x40400 + 4 * (n)) | ||
596 | #define MDP_CSC_PRMVn(n) (msm_mdp_base + 0x40440 + 4 * (n)) | ||
597 | #define MDP_CSC_PRE_BV1n(n) (msm_mdp_base + 0x40500 + 4 * (n)) | ||
598 | #define MDP_CSC_PRE_BV2n(n) (msm_mdp_base + 0x40540 + 4 * (n)) | ||
599 | #define MDP_CSC_POST_BV1n(n) (msm_mdp_base + 0x40580 + 4 * (n)) | ||
600 | #define MDP_CSC_POST_BV2n(n) (msm_mdp_base + 0x405c0 + 4 * (n)) | ||
601 | |||
602 | #ifdef CONFIG_FB_MSM_MDP31 | ||
603 | #define MDP_CSC_PRE_LV1n(n) (msm_mdp_base + 0x40600 + 4 * (n)) | ||
604 | #define MDP_CSC_PRE_LV2n(n) (msm_mdp_base + 0x40640 + 4 * (n)) | ||
605 | #define MDP_CSC_POST_LV1n(n) (msm_mdp_base + 0x40680 + 4 * (n)) | ||
606 | #define MDP_CSC_POST_LV2n(n) (msm_mdp_base + 0x406c0 + 4 * (n)) | ||
607 | #define MDP_PPP_SCALE_COEFF_LSBn(n) (msm_mdp_base + 0x50400 + 8 * (n)) | ||
608 | #define MDP_PPP_SCALE_COEFF_MSBn(n) (msm_mdp_base + 0x50404 + 8 * (n)) | ||
609 | |||
610 | #define SCALE_D0_SET 0 | ||
611 | #define SCALE_D1_SET BIT(0) | ||
612 | #define SCALE_D2_SET BIT(1) | ||
613 | #define SCALE_U1_SET (BIT(0)|BIT(1)) | ||
614 | |||
615 | #else | ||
616 | #define MDP_CSC_PRE_LV1n(n) (msm_mdp_base + 0x40580 + 4 * (n)) | ||
617 | #endif | ||
618 | |||
619 | #define MDP_CURSOR_WIDTH 64 | ||
620 | #define MDP_CURSOR_HEIGHT 64 | ||
621 | #define MDP_CURSOR_SIZE (MDP_CURSOR_WIDTH*MDP_CURSOR_WIDTH*4) | ||
622 | |||
623 | #define MDP_DMA_P_LUT_C0_EN BIT(0) | ||
624 | #define MDP_DMA_P_LUT_C1_EN BIT(1) | ||
625 | #define MDP_DMA_P_LUT_C2_EN BIT(2) | ||
626 | #define MDP_DMA_P_LUT_POST BIT(4) | ||
627 | |||
628 | void mdp_hw_init(void); | ||
629 | int mdp_ppp_pipe_wait(void); | ||
630 | void mdp_pipe_kickoff(uint32 term, struct msm_fb_data_type *mfd); | ||
631 | void mdp_pipe_ctrl(MDP_BLOCK_TYPE block, MDP_BLOCK_POWER_STATE state, | ||
632 | boolean isr); | ||
633 | void mdp_set_dma_pan_info(struct fb_info *info, struct mdp_dirty_region *dirty, | ||
634 | boolean sync); | ||
635 | void mdp_dma_pan_update(struct fb_info *info); | ||
636 | void mdp_refresh_screen(unsigned long data); | ||
637 | int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req, | ||
638 | struct file **pp_src, struct file **pp_dest); | ||
639 | void mdp_lcd_update_workqueue_handler(struct work_struct *work); | ||
640 | void mdp_vsync_resync_workqueue_handler(struct work_struct *work); | ||
641 | void mdp_dma2_update(struct msm_fb_data_type *mfd); | ||
642 | void mdp_config_vsync(struct msm_fb_data_type *); | ||
643 | uint32 mdp_get_lcd_line_counter(struct msm_fb_data_type *mfd); | ||
644 | enum hrtimer_restart mdp_dma2_vsync_hrtimer_handler(struct hrtimer *ht); | ||
645 | void mdp_set_scale(MDPIBUF *iBuf, | ||
646 | uint32 dst_roi_width, | ||
647 | uint32 dst_roi_height, | ||
648 | boolean inputRGB, boolean outputRGB, uint32 *pppop_reg_ptr); | ||
649 | void mdp_init_scale_table(void); | ||
650 | void mdp_adjust_start_addr(uint8 **src0, | ||
651 | uint8 **src1, | ||
652 | int v_slice, | ||
653 | int h_slice, | ||
654 | int x, | ||
655 | int y, | ||
656 | uint32 width, | ||
657 | uint32 height, int bpp, MDPIBUF *iBuf, int layer); | ||
658 | void mdp_set_blend_attr(MDPIBUF *iBuf, | ||
659 | uint32 *alpha, | ||
660 | uint32 *tpVal, | ||
661 | uint32 perPixelAlpha, uint32 *pppop_reg_ptr); | ||
662 | |||
663 | int mdp_dma3_on(struct platform_device *pdev); | ||
664 | int mdp_dma3_off(struct platform_device *pdev); | ||
665 | void mdp_dma3_update(struct msm_fb_data_type *mfd); | ||
666 | |||
667 | int mdp_lcdc_on(struct platform_device *pdev); | ||
668 | int mdp_lcdc_off(struct platform_device *pdev); | ||
669 | void mdp_lcdc_update(struct msm_fb_data_type *mfd); | ||
670 | int mdp_hw_cursor_update(struct fb_info *info, struct fb_cursor *cursor); | ||
671 | void mdp_enable_irq(uint32 term); | ||
672 | void mdp_disable_irq(uint32 term); | ||
673 | void mdp_disable_irq_nolock(uint32 term); | ||
674 | uint32_t mdp_get_bytes_per_pixel(uint32_t format); | ||
675 | |||
676 | #ifdef MDP_HW_VSYNC | ||
677 | void mdp_hw_vsync_clk_enable(struct msm_fb_data_type *mfd); | ||
678 | void mdp_hw_vsync_clk_disable(struct msm_fb_data_type *mfd); | ||
679 | #endif | ||
680 | |||
681 | void mdp_dma_s_update(struct msm_fb_data_type *mfd); | ||
682 | |||
683 | /* Added to support flipping */ | ||
684 | void mdp_set_offset_info(struct fb_info *info, uint32 address, uint32 interval); | ||
685 | |||
686 | int get_gem_img(struct mdp_img *img, unsigned long *start, | ||
687 | unsigned long *len); | ||
688 | int get_img(struct mdp_img *img, struct fb_info *info, | ||
689 | unsigned long *start, unsigned long *len, | ||
690 | struct file **pp_file); | ||
691 | |||
692 | |||
693 | /*int get_img(struct msmfb_data *img, struct fb_info *info, | ||
694 | unsigned long *start, unsigned long *len, struct file **pp_file);*/ | ||
695 | #endif /* MDP_H */ | ||
diff --git a/drivers/staging/msm/mdp4.h b/drivers/staging/msm/mdp4.h new file mode 100644 index 000000000000..26ec8f12cf64 --- /dev/null +++ b/drivers/staging/msm/mdp4.h | |||
@@ -0,0 +1,352 @@ | |||
1 | /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * Redistribution and use in source and binary forms, with or without | ||
4 | * modification, are permitted provided that the following conditions are met: | ||
5 | * * Redistributions of source code must retain the above copyright | ||
6 | * notice, this list of conditions and the following disclaimer. | ||
7 | * * Redistributions in binary form must reproduce the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer in the | ||
9 | * documentation and/or other materials provided with the distribution. | ||
10 | * * Neither the name of Code Aurora nor | ||
11 | * the names of its contributors may be used to endorse or promote | ||
12 | * products derived from this software without specific prior written | ||
13 | * permission. | ||
14 | * | ||
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
17 | * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
18 | * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||
19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||
20 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||
21 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | ||
22 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | ||
23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||
24 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | ||
25 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | * | ||
27 | */ | ||
28 | |||
29 | #ifndef MDP4_H | ||
30 | #define MDP4_H | ||
31 | |||
32 | extern struct mdp_dma_data dma2_data; | ||
33 | extern struct mdp_dma_data dma_s_data; | ||
34 | extern struct mdp_dma_data dma_e_data; | ||
35 | extern struct mdp_histogram mdp_hist; | ||
36 | extern struct completion mdp_hist_comp; | ||
37 | extern boolean mdp_is_in_isr; | ||
38 | extern uint32 mdp_intr_mask; | ||
39 | extern spinlock_t mdp_spin_lock; | ||
40 | |||
41 | |||
42 | #define MDP4_NONBLOCKING /* enable non blocking ioctl */ | ||
43 | |||
44 | #define MDP4_OVERLAYPROC0_BASE 0x10000 | ||
45 | #define MDP4_OVERLAYPROC1_BASE 0x18000 | ||
46 | |||
47 | #define MDP4_VIDEO_BASE 0x20000 | ||
48 | #define MDP4_VIDEO_OFF 0x10000 | ||
49 | |||
50 | #define MDP4_RGB_BASE 0x40000 | ||
51 | #define MDP4_RGB_OFF 0x10000 | ||
52 | |||
53 | enum { /* display */ | ||
54 | PRIMARY_INTF_SEL, | ||
55 | SECONDARY_INTF_SEL, | ||
56 | EXTERNAL_INTF_SEL | ||
57 | }; | ||
58 | |||
59 | enum { | ||
60 | LCDC_RGB_INTF, | ||
61 | DTV_INTF = LCDC_RGB_INTF, | ||
62 | MDDI_LCDC_INTF, | ||
63 | MDDI_INTF, | ||
64 | EBI2_INTF | ||
65 | }; | ||
66 | |||
67 | enum { | ||
68 | MDDI_PRIMARY_SET, | ||
69 | MDDI_SECONDARY_SET, | ||
70 | MDDI_EXTERNAL_SET | ||
71 | }; | ||
72 | |||
73 | enum { | ||
74 | EBI2_LCD0, | ||
75 | EBI2_LCD1 | ||
76 | }; | ||
77 | |||
78 | enum { | ||
79 | OVERLAY_MODE_NONE, | ||
80 | OVERLAY_MODE_BLT | ||
81 | }; | ||
82 | |||
83 | enum { | ||
84 | OVERLAY_REFRESH_ON_DEMAND, | ||
85 | OVERLAY_REFRESH_VSYNC, | ||
86 | OVERLAY_REFRESH_VSYNC_HALF, | ||
87 | OVERLAY_REFRESH_VSYNC_QUARTER | ||
88 | }; | ||
89 | |||
90 | enum { | ||
91 | OVERLAY_FRAMEBUF, | ||
92 | OVERLAY_DIRECTOUT | ||
93 | }; | ||
94 | |||
95 | /* system interrupts */ | ||
96 | #define INTR_OVERLAY0_DONE BIT(0) | ||
97 | #define INTR_OVERLAY1_DONE BIT(1) | ||
98 | #define INTR_DMA_S_DONE BIT(2) | ||
99 | #define INTR_DMA_E_DONE BIT(3) | ||
100 | #define INTR_DMA_P_DONE BIT(4) | ||
101 | #define INTR_VG1_HISTOGRAM BIT(5) | ||
102 | #define INTR_VG2_HISTOGRAM BIT(6) | ||
103 | #define INTR_PRIMARY_VSYNC BIT(7) | ||
104 | #define INTR_PRIMARY_INTF_UDERRUN BIT(8) | ||
105 | #define INTR_EXTERNAL_VSYNC BIT(9) | ||
106 | #define INTR_EXTERNAL_INTF_UDERRUN BIT(10) | ||
107 | #define INTR_DMA_P_HISTOGRAM BIT(17) | ||
108 | |||
109 | /* histogram interrupts */ | ||
110 | #define INTR_HIST_DONE BIT(0) | ||
111 | #define INTR_HIST_RESET_SEQ_DONE BIT(1) | ||
112 | |||
113 | |||
114 | #ifdef CONFIG_FB_MSM_OVERLAY | ||
115 | #define MDP4_ANY_INTR_MASK (INTR_OVERLAY0_DONE) | ||
116 | #else | ||
117 | #define MDP4_ANY_INTR_MASK (INTR_DMA_P_DONE) | ||
118 | #endif | ||
119 | |||
120 | enum { | ||
121 | OVERLAY_PIPE_RGB1, | ||
122 | OVERLAY_PIPE_RGB2, | ||
123 | }; | ||
124 | |||
125 | enum { | ||
126 | OVERLAY_PIPE_VG1, /* video/graphic */ | ||
127 | OVERLAY_PIPE_VG2 | ||
128 | }; | ||
129 | |||
130 | enum { | ||
131 | OVERLAY_TYPE_RGB, | ||
132 | OVERLAY_TYPE_VG /* video/graphic */ | ||
133 | }; | ||
134 | |||
135 | enum { | ||
136 | MDP4_MIXER0, | ||
137 | MDP4_MIXER1 | ||
138 | }; | ||
139 | |||
140 | #define MDP4_MAX_MIXER 2 | ||
141 | |||
142 | enum { | ||
143 | OVERLAY_PLANE_INTERLEAVED, | ||
144 | OVERLAY_PLANE_PLANAR, | ||
145 | OVERLAY_PLANE_PSEUDO_PLANAR | ||
146 | }; | ||
147 | |||
148 | enum { | ||
149 | MDP4_MIXER_STAGE_UNUNSED, /* pipe not used */ | ||
150 | MDP4_MIXER_STAGE_BASE, | ||
151 | MDP4_MIXER_STAGE0, /* zorder 0 */ | ||
152 | MDP4_MIXER_STAGE1, /* zorder 1 */ | ||
153 | MDP4_MIXER_STAGE2 /* zorder 2 */ | ||
154 | }; | ||
155 | |||
156 | #define MDP4_MAX_STAGE 4 | ||
157 | |||
158 | enum { | ||
159 | MDP4_FRAME_FORMAT_LINEAR, | ||
160 | MDP4_FRAME_FORMAT_ARGB_TILE, | ||
161 | MDP4_FRAME_FORMAT_VIDEO_SUPERTILE | ||
162 | }; | ||
163 | |||
164 | enum { | ||
165 | MDP4_CHROMA_RGB, | ||
166 | MDP4_CHROMA_H2V1, | ||
167 | MDP4_CHROMA_H1V2, | ||
168 | MDP4_CHROMA_420 | ||
169 | }; | ||
170 | |||
171 | #define MDP4_BLEND_BG_TRANSP_EN BIT(9) | ||
172 | #define MDP4_BLEND_FG_TRANSP_EN BIT(8) | ||
173 | #define MDP4_BLEND_BG_MOD_ALPHA BIT(7) | ||
174 | #define MDP4_BLEND_BG_INV_ALPHA BIT(6) | ||
175 | #define MDP4_BLEND_BG_ALPHA_FG_CONST (0 << 4) | ||
176 | #define MDP4_BLEND_BG_ALPHA_BG_CONST (1 << 4) | ||
177 | #define MDP4_BLEND_BG_ALPHA_FG_PIXEL (2 << 4) | ||
178 | #define MDP4_BLEND_BG_ALPHA_BG_PIXEL (3 << 4) | ||
179 | #define MDP4_BLEND_FG_MOD_ALPHA BIT(3) | ||
180 | #define MDP4_BLEND_FG_INV_ALPHA BIT(2) | ||
181 | #define MDP4_BLEND_FG_ALPHA_FG_CONST (0 << 0) | ||
182 | #define MDP4_BLEND_FG_ALPHA_BG_CONST (1 << 0) | ||
183 | #define MDP4_BLEND_FG_ALPHA_FG_PIXEL (2 << 0) | ||
184 | #define MDP4_BLEND_FG_ALPHA_BG_PIXEL (3 << 0) | ||
185 | |||
186 | #define MDP4_FORMAT_SOLID_FILL BIT(22) | ||
187 | #define MDP4_FORMAT_UNPACK_ALIGN_MSB BIT(18) | ||
188 | #define MDP4_FORMAT_UNPACK_TIGHT BIT(17) | ||
189 | #define MDP4_FORMAT_90_ROTATED BIT(12) | ||
190 | #define MDP4_FORMAT_ALPHA_ENABLE BIT(8) | ||
191 | |||
192 | #define MDP4_OP_DEINT_ODD_REF BIT(19) | ||
193 | #define MDP4_OP_IGC_LUT_EN BIT(16) | ||
194 | #define MDP4_OP_DITHER_EN BIT(15) | ||
195 | #define MDP4_OP_FLIP_UD BIT(14) | ||
196 | #define MDP4_OP_FLIP_LR BIT(13) | ||
197 | #define MDP4_OP_CSC_EN BIT(11) | ||
198 | #define MDP4_OP_SRC_DATA_YCBCR BIT(9) | ||
199 | #define MDP4_OP_SCALEY_FIR (0 << 4) | ||
200 | #define MDP4_OP_SCALEY_MN_PHASE (1 << 4) | ||
201 | #define MDP4_OP_SCALEY_PIXEL_RPT (2 << 4) | ||
202 | #define MDP4_OP_SCALEX_FIR (0 << 2) | ||
203 | #define MDP4_OP_SCALEX_MN_PHASE (1 << 2) | ||
204 | #define MDP4_OP_SCALEX_PIXEL_RPT (2 << 2) | ||
205 | #define MDP4_OP_SCALEY_EN BIT(1) | ||
206 | #define MDP4_OP_SCALEX_EN BIT(0) | ||
207 | |||
208 | #define MDP4_PIPE_PER_MIXER 2 | ||
209 | |||
210 | #define MDP4_MAX_PLANE 4 | ||
211 | |||
212 | #define MDP4_MAX_VIDEO_PIPE 2 | ||
213 | #define MDP4_MAX_RGB_PIPE 2 | ||
214 | #define MDP4_MAX_OVERLAY_PIPE 16 | ||
215 | |||
216 | |||
217 | struct mdp4_overlay_pipe { | ||
218 | uint32 pipe_type; /* rgb, video/graphic */ | ||
219 | uint32 pipe_num; | ||
220 | uint32 pipe_ndx; | ||
221 | uint32 mixer_num; /* which mixer used */ | ||
222 | uint32 mixer_stage; /* which stage of mixer used */ | ||
223 | uint32 src_format; | ||
224 | uint32 src_width; /* source img width */ | ||
225 | uint32 src_height; /* source img height */ | ||
226 | uint32 src_w; /* roi */ | ||
227 | uint32 src_h; /* roi */ | ||
228 | uint32 src_x; /* roi */ | ||
229 | uint32 src_y; /* roi */ | ||
230 | uint32 dst_w; /* roi */ | ||
231 | uint32 dst_h; /* roi */ | ||
232 | uint32 dst_x; /* roi */ | ||
233 | uint32 dst_y; /* roi */ | ||
234 | uint32 op_mode; | ||
235 | uint32 transp; | ||
236 | uint32 blend_op; | ||
237 | uint32 phasex_step; | ||
238 | uint32 phasey_step; | ||
239 | uint32 alpha; | ||
240 | uint32 is_fg; /* control alpha & color key */ | ||
241 | uint32 srcp0_addr; /* interleave, luma */ | ||
242 | uint32 srcp0_ystride; | ||
243 | uint32 srcp1_addr; /* pseudoplanar, chroma plane */ | ||
244 | uint32 srcp1_ystride; | ||
245 | uint32 srcp2_addr; /* planar color 2*/ | ||
246 | uint32 srcp2_ystride; | ||
247 | uint32 srcp3_addr; /* alpha/color 3 */ | ||
248 | uint32 srcp3_ystride; | ||
249 | uint32 fetch_plane; | ||
250 | uint32 frame_format; /* video */ | ||
251 | uint32 chroma_site; /* video */ | ||
252 | uint32 chroma_sample; /* video */ | ||
253 | uint32 solid_fill; | ||
254 | uint32 vc1_reduce; /* video */ | ||
255 | uint32 fatch_planes; /* video */ | ||
256 | uint32 unpack_align_msb;/* 0 to LSB, 1 to MSB */ | ||
257 | uint32 unpack_tight;/* 0 for loose, 1 for tight */ | ||
258 | uint32 unpack_count;/* 0 = 1 component, 1 = 2 component ... */ | ||
259 | uint32 rotated_90; /* has been rotated 90 degree */ | ||
260 | uint32 bpp; /* byte per pixel */ | ||
261 | uint32 alpha_enable;/* source has alpha */ | ||
262 | /* | ||
263 | * number of bits for source component, | ||
264 | * 0 = 1 bit, 1 = 2 bits, 2 = 6 bits, 3 = 8 bits | ||
265 | */ | ||
266 | uint32 a_bit; /* component 3, alpha */ | ||
267 | uint32 r_bit; /* component 2, R_Cr */ | ||
268 | uint32 b_bit; /* component 1, B_Cb */ | ||
269 | uint32 g_bit; /* component 0, G_lumz */ | ||
270 | /* | ||
271 | * unpack pattern | ||
272 | * A = C3, R = C2, B = C1, G = C0 | ||
273 | */ | ||
274 | uint32 element3; /* 0 = C0, 1 = C1, 2 = C2, 3 = C3 */ | ||
275 | uint32 element2; /* 0 = C0, 1 = C1, 2 = C2, 3 = C3 */ | ||
276 | uint32 element1; /* 0 = C0, 1 = C1, 2 = C2, 3 = C3 */ | ||
277 | uint32 element0; /* 0 = C0, 1 = C1, 2 = C2, 3 = C3 */ | ||
278 | struct completion comp; | ||
279 | struct mdp_overlay req_data; | ||
280 | }; | ||
281 | |||
282 | void mdp4_sw_reset(unsigned long bits); | ||
283 | void mdp4_display_intf_sel(int output, unsigned long intf); | ||
284 | void mdp4_overlay_cfg(int layer, int blt_mode, int refresh, int direct_out); | ||
285 | void mdp4_ebi2_lcd_setup(int lcd, unsigned long base, int ystride); | ||
286 | void mdp4_mddi_setup(int which, unsigned long id); | ||
287 | unsigned long mdp4_display_status(void); | ||
288 | void mdp4_enable_clk_irq(void); | ||
289 | void mdp4_disable_clk_irq(void); | ||
290 | void mdp4_dma_p_update(struct msm_fb_data_type *mfd); | ||
291 | void mdp4_dma_s_update(struct msm_fb_data_type *mfd); | ||
292 | void mdp_pipe_ctrl(MDP_BLOCK_TYPE block, MDP_BLOCK_POWER_STATE state, | ||
293 | boolean isr); | ||
294 | void mdp4_pipe_kickoff(uint32 pipe, struct msm_fb_data_type *mfd); | ||
295 | int mdp4_lcdc_on(struct platform_device *pdev); | ||
296 | int mdp4_lcdc_off(struct platform_device *pdev); | ||
297 | void mdp4_lcdc_update(struct msm_fb_data_type *mfd); | ||
298 | void mdp4_intr_clear_set(ulong clear, ulong set); | ||
299 | void mdp4_dma_p_cfg(void); | ||
300 | void mdp4_hw_init(void); | ||
301 | void mdp4_isr_read(int); | ||
302 | void mdp4_clear_lcdc(void); | ||
303 | void mdp4_mixer_blend_init(int mixer_num); | ||
304 | void mdp4_vg_qseed_init(int vg_num); | ||
305 | void mdp4_vg_csc_mv_setup(int vp_num); | ||
306 | void mdp4_vg_csc_pre_bv_setup(int vp_num); | ||
307 | void mdp4_vg_csc_post_bv_setup(int vp_num); | ||
308 | void mdp4_vg_csc_pre_lv_setup(int vp_num); | ||
309 | void mdp4_vg_csc_post_lv_setup(int vp_num); | ||
310 | irqreturn_t mdp4_isr(int irq, void *ptr); | ||
311 | void mdp4_overlay_format_to_pipe(uint32 format, struct mdp4_overlay_pipe *pipe); | ||
312 | uint32 mdp4_overlay_format(struct mdp4_overlay_pipe *pipe); | ||
313 | uint32 mdp4_overlay_unpack_pattern(struct mdp4_overlay_pipe *pipe); | ||
314 | uint32 mdp4_overlay_op_mode(struct mdp4_overlay_pipe *pipe); | ||
315 | void mdp4_lcdc_overlay(struct msm_fb_data_type *mfd); | ||
316 | void mdp4_overlay_rgb_setup(struct mdp4_overlay_pipe *pipe); | ||
317 | void mdp4_overlay_reg_flush(struct mdp4_overlay_pipe *pipe, int all); | ||
318 | void mdp4_mixer_blend_setup(struct mdp4_overlay_pipe *pipe); | ||
319 | void mdp4_mixer_stage_up(struct mdp4_overlay_pipe *pipe); | ||
320 | void mdp4_mixer_stage_down(struct mdp4_overlay_pipe *pipe); | ||
321 | int mdp4_mixer_stage_can_run(struct mdp4_overlay_pipe *pipe); | ||
322 | void mdp4_overlayproc_cfg(struct mdp4_overlay_pipe *pipe); | ||
323 | void mdp4_mddi_overlay(struct msm_fb_data_type *mfd); | ||
324 | int mdp4_overlay_format2type(uint32 format); | ||
325 | int mdp4_overlay_format2pipe(struct mdp4_overlay_pipe *pipe); | ||
326 | int mdp4_overlay_get(struct fb_info *info, struct mdp_overlay *req); | ||
327 | int mdp4_overlay_set(struct fb_info *info, struct mdp_overlay *req); | ||
328 | int mdp4_overlay_unset(struct fb_info *info, int ndx); | ||
329 | int mdp4_overlay_play(struct fb_info *info, struct msmfb_overlay_data *req, | ||
330 | struct file **pp_src_file); | ||
331 | struct mdp4_overlay_pipe *mdp4_overlay_pipe_alloc(void); | ||
332 | void mdp4_overlay_pipe_free(struct mdp4_overlay_pipe *pipe); | ||
333 | void mdp4_overlay_dmap_cfg(struct msm_fb_data_type *mfd, int lcdc); | ||
334 | void mdp4_overlay_dmap_xy(struct mdp4_overlay_pipe *pipe); | ||
335 | int mdp4_overlay_active(int mixer); | ||
336 | void mdp4_overlay0_done_lcdc(void); | ||
337 | void mdp4_overlay0_done_mddi(void); | ||
338 | void mdp4_mddi_overlay_restore(void); | ||
339 | void mdp4_mddi_overlay_kickoff(struct msm_fb_data_type *mfd, | ||
340 | struct mdp4_overlay_pipe *pipe); | ||
341 | void mdp4_rgb_igc_lut_setup(int num); | ||
342 | void mdp4_vg_igc_lut_setup(int num); | ||
343 | void mdp4_mixer_gc_lut_setup(int mixer_num); | ||
344 | |||
345 | #ifdef CONFIG_DEBUG_FS | ||
346 | int mdp4_debugfs_init(void); | ||
347 | #endif | ||
348 | |||
349 | int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req, | ||
350 | struct file **pp_src_file, struct file **pp_dst_file); | ||
351 | |||
352 | #endif /* MDP_H */ | ||
diff --git a/drivers/staging/msm/mdp4_debugfs.c b/drivers/staging/msm/mdp4_debugfs.c new file mode 100644 index 000000000000..844d46775ecd --- /dev/null +++ b/drivers/staging/msm/mdp4_debugfs.c | |||
@@ -0,0 +1,181 @@ | |||
1 | /* Copyright (c) 2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/sched.h> | ||
20 | #include <linux/time.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/interrupt.h> | ||
23 | #include <linux/spinlock.h> | ||
24 | #include <linux/hrtimer.h> | ||
25 | #include <linux/clk.h> | ||
26 | #include <mach/hardware.h> | ||
27 | #include <linux/io.h> | ||
28 | #include <linux/debugfs.h> | ||
29 | |||
30 | #include <asm/system.h> | ||
31 | #include <asm/mach-types.h> | ||
32 | #include <linux/semaphore.h> | ||
33 | #include <linux/uaccess.h> | ||
34 | |||
35 | #include "mdp.h" | ||
36 | #include "msm_fb.h" | ||
37 | #include "mdp4.h" | ||
38 | |||
39 | |||
40 | #define MDP4_DEBUG_BUF 128 | ||
41 | |||
42 | |||
43 | static char mdp4_debug_buf[MDP4_DEBUG_BUF]; | ||
44 | static ulong mdp4_debug_offset; | ||
45 | static ulong mdp4_base_addr; | ||
46 | |||
47 | static int mdp4_offset_set(void *data, u64 val) | ||
48 | { | ||
49 | mdp4_debug_offset = (int)val; | ||
50 | return 0; | ||
51 | } | ||
52 | |||
53 | static int mdp4_offset_get(void *data, u64 *val) | ||
54 | { | ||
55 | *val = (u64)mdp4_debug_offset; | ||
56 | return 0; | ||
57 | } | ||
58 | |||
59 | DEFINE_SIMPLE_ATTRIBUTE( | ||
60 | mdp4_offset_fops, | ||
61 | mdp4_offset_get, | ||
62 | mdp4_offset_set, | ||
63 | "%llx\n"); | ||
64 | |||
65 | |||
66 | static int mdp4_debugfs_open(struct inode *inode, struct file *file) | ||
67 | { | ||
68 | /* non-seekable */ | ||
69 | file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE); | ||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | static int mdp4_debugfs_release(struct inode *inode, struct file *file) | ||
74 | { | ||
75 | return 0; | ||
76 | } | ||
77 | |||
78 | static ssize_t mdp4_debugfs_write( | ||
79 | struct file *file, | ||
80 | const char __user *buff, | ||
81 | size_t count, | ||
82 | loff_t *ppos) | ||
83 | { | ||
84 | int cnt; | ||
85 | unsigned int data; | ||
86 | |||
87 | printk(KERN_INFO "%s: offset=%d count=%d *ppos=%d\n", | ||
88 | __func__, (int)mdp4_debug_offset, (int)count, (int)*ppos); | ||
89 | |||
90 | if (count > sizeof(mdp4_debug_buf)) | ||
91 | return -EFAULT; | ||
92 | |||
93 | if (copy_from_user(mdp4_debug_buf, buff, count)) | ||
94 | return -EFAULT; | ||
95 | |||
96 | |||
97 | mdp4_debug_buf[count] = 0; /* end of string */ | ||
98 | |||
99 | cnt = sscanf(mdp4_debug_buf, "%x", &data); | ||
100 | if (cnt < 1) { | ||
101 | printk(KERN_ERR "%s: sscanf failed cnt=%d" , __func__, cnt); | ||
102 | return -EINVAL; | ||
103 | } | ||
104 | |||
105 | writel(&data, mdp4_base_addr + mdp4_debug_offset); | ||
106 | |||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | static ssize_t mdp4_debugfs_read( | ||
111 | struct file *file, | ||
112 | char __user *buff, | ||
113 | size_t count, | ||
114 | loff_t *ppos) | ||
115 | { | ||
116 | int len = 0; | ||
117 | unsigned int data; | ||
118 | |||
119 | printk(KERN_INFO "%s: offset=%d count=%d *ppos=%d\n", | ||
120 | __func__, (int)mdp4_debug_offset, (int)count, (int)*ppos); | ||
121 | |||
122 | if (*ppos) | ||
123 | return 0; /* the end */ | ||
124 | |||
125 | data = readl(mdp4_base_addr + mdp4_debug_offset); | ||
126 | |||
127 | len = snprintf(mdp4_debug_buf, 4, "%x\n", data); | ||
128 | |||
129 | if (len > 0) { | ||
130 | if (len > count) | ||
131 | len = count; | ||
132 | if (copy_to_user(buff, mdp4_debug_buf, len)) | ||
133 | return -EFAULT; | ||
134 | } | ||
135 | |||
136 | printk(KERN_INFO "%s: len=%d\n", __func__, len); | ||
137 | |||
138 | if (len < 0) | ||
139 | return 0; | ||
140 | |||
141 | *ppos += len; /* increase offset */ | ||
142 | |||
143 | return len; | ||
144 | } | ||
145 | |||
146 | static const struct file_operations mdp4_debugfs_fops = { | ||
147 | .open = mdp4_debugfs_open, | ||
148 | .release = mdp4_debugfs_release, | ||
149 | .read = mdp4_debugfs_read, | ||
150 | .write = mdp4_debugfs_write, | ||
151 | }; | ||
152 | |||
153 | int mdp4_debugfs_init(void) | ||
154 | { | ||
155 | struct dentry *dent = debugfs_create_dir("mdp4", NULL); | ||
156 | |||
157 | if (IS_ERR(dent)) { | ||
158 | printk(KERN_ERR "%s(%d): debugfs_create_dir fail, error %ld\n", | ||
159 | __FILE__, __LINE__, PTR_ERR(dent)); | ||
160 | return -1; | ||
161 | } | ||
162 | |||
163 | if (debugfs_create_file("offset", 0644, dent, 0, &mdp4_offset_fops) | ||
164 | == NULL) { | ||
165 | printk(KERN_ERR "%s(%d): debugfs_create_file: offset fail\n", | ||
166 | __FILE__, __LINE__); | ||
167 | return -1; | ||
168 | } | ||
169 | |||
170 | if (debugfs_create_file("regs", 0644, dent, 0, &mdp4_debugfs_fops) | ||
171 | == NULL) { | ||
172 | printk(KERN_ERR "%s(%d): debugfs_create_file: regs fail\n", | ||
173 | __FILE__, __LINE__); | ||
174 | return -1; | ||
175 | } | ||
176 | |||
177 | mdp4_debug_offset = 0; | ||
178 | mdp4_base_addr = (ulong) msm_mdp_base; /* defined at msm_fb_def.h */ | ||
179 | |||
180 | return 0; | ||
181 | } | ||
diff --git a/drivers/staging/msm/mdp4_overlay.c b/drivers/staging/msm/mdp4_overlay.c new file mode 100644 index 000000000000..304bb8297635 --- /dev/null +++ b/drivers/staging/msm/mdp4_overlay.c | |||
@@ -0,0 +1,1259 @@ | |||
1 | /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/sched.h> | ||
21 | #include <linux/time.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/spinlock.h> | ||
25 | #include <linux/hrtimer.h> | ||
26 | #include <linux/clk.h> | ||
27 | #include <mach/hardware.h> | ||
28 | #include <linux/io.h> | ||
29 | #include <linux/debugfs.h> | ||
30 | #include <linux/fb.h> | ||
31 | #include <msm_mdp.h> | ||
32 | #include <linux/file.h> | ||
33 | #include "android_pmem.h" | ||
34 | #include <linux/major.h> | ||
35 | #include <asm/system.h> | ||
36 | #include <asm/mach-types.h> | ||
37 | #include <linux/semaphore.h> | ||
38 | #include <linux/uaccess.h> | ||
39 | #include <linux/mutex.h> | ||
40 | |||
41 | #include "mdp.h" | ||
42 | #include "msm_fb.h" | ||
43 | #include "mdp4.h" | ||
44 | |||
45 | |||
46 | struct mdp4_overlay_ctrl { | ||
47 | struct mdp4_overlay_pipe plist[MDP4_MAX_OVERLAY_PIPE]; | ||
48 | struct mdp4_overlay_pipe *stage[MDP4_MAX_MIXER][MDP4_MAX_STAGE]; | ||
49 | } mdp4_overlay_db; | ||
50 | |||
51 | static struct mdp4_overlay_ctrl *ctrl = &mdp4_overlay_db; | ||
52 | |||
53 | |||
54 | void mdp4_overlay_dmap_cfg(struct msm_fb_data_type *mfd, int lcdc) | ||
55 | { | ||
56 | uint32 dma2_cfg_reg; | ||
57 | |||
58 | dma2_cfg_reg = DMA_DITHER_EN; | ||
59 | |||
60 | if (mfd->fb_imgType == MDP_BGR_565) | ||
61 | dma2_cfg_reg |= DMA_PACK_PATTERN_BGR; | ||
62 | else | ||
63 | dma2_cfg_reg |= DMA_PACK_PATTERN_RGB; | ||
64 | |||
65 | |||
66 | if (mfd->panel_info.bpp == 18) { | ||
67 | dma2_cfg_reg |= DMA_DSTC0G_6BITS | /* 666 18BPP */ | ||
68 | DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS; | ||
69 | } else if (mfd->panel_info.bpp == 16) { | ||
70 | dma2_cfg_reg |= DMA_DSTC0G_6BITS | /* 565 16BPP */ | ||
71 | DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS; | ||
72 | } else { | ||
73 | dma2_cfg_reg |= DMA_DSTC0G_8BITS | /* 888 16BPP */ | ||
74 | DMA_DSTC1B_8BITS | DMA_DSTC2R_8BITS; | ||
75 | } | ||
76 | |||
77 | if (lcdc) | ||
78 | dma2_cfg_reg |= DMA_PACK_ALIGN_MSB; | ||
79 | |||
80 | /* dma2 config register */ | ||
81 | MDP_OUTP(MDP_BASE + 0x90000, dma2_cfg_reg); | ||
82 | |||
83 | } | ||
84 | |||
85 | void mdp4_overlay_dmap_xy(struct mdp4_overlay_pipe *pipe) | ||
86 | { | ||
87 | |||
88 | /* dma_p source */ | ||
89 | MDP_OUTP(MDP_BASE + 0x90004, | ||
90 | (pipe->src_height << 16 | pipe->src_width)); | ||
91 | MDP_OUTP(MDP_BASE + 0x90008, pipe->srcp0_addr); | ||
92 | MDP_OUTP(MDP_BASE + 0x9000c, pipe->srcp0_ystride); | ||
93 | |||
94 | /* dma_p dest */ | ||
95 | MDP_OUTP(MDP_BASE + 0x90010, (pipe->dst_y << 16 | pipe->dst_x)); | ||
96 | } | ||
97 | |||
98 | #define MDP4_VG_PHASE_STEP_DEFAULT 0x20000000 | ||
99 | #define MDP4_VG_PHASE_STEP_SHIFT 29 | ||
100 | |||
101 | static int mdp4_leading_0(uint32 num) | ||
102 | { | ||
103 | uint32 bit = 0x80000000; | ||
104 | int i; | ||
105 | |||
106 | for (i = 0; i < 32; i++) { | ||
107 | if (bit & num) | ||
108 | return i; | ||
109 | bit >>= 1; | ||
110 | } | ||
111 | |||
112 | return i; | ||
113 | } | ||
114 | |||
115 | static uint32 mdp4_scale_phase_step(int f_num, uint32 src, uint32 dst) | ||
116 | { | ||
117 | uint32 val; | ||
118 | int n; | ||
119 | |||
120 | n = mdp4_leading_0(src); | ||
121 | if (n > f_num) | ||
122 | n = f_num; | ||
123 | val = src << n; /* maximum to reduce lose of resolution */ | ||
124 | val /= dst; | ||
125 | if (n < f_num) { | ||
126 | n = f_num - n; | ||
127 | val <<= n; | ||
128 | } | ||
129 | |||
130 | return val; | ||
131 | } | ||
132 | |||
133 | static void mdp4_scale_setup(struct mdp4_overlay_pipe *pipe) | ||
134 | { | ||
135 | |||
136 | pipe->phasex_step = MDP4_VG_PHASE_STEP_DEFAULT; | ||
137 | pipe->phasey_step = MDP4_VG_PHASE_STEP_DEFAULT; | ||
138 | |||
139 | if (pipe->dst_h && pipe->src_h != pipe->dst_h) { | ||
140 | if (pipe->dst_h >= pipe->src_h * 8) /* too much */ | ||
141 | return; | ||
142 | pipe->op_mode |= MDP4_OP_SCALEY_EN; | ||
143 | |||
144 | if (pipe->pipe_type == OVERLAY_TYPE_VG) { | ||
145 | if (pipe->dst_h <= (pipe->src_h / 4)) | ||
146 | pipe->op_mode |= MDP4_OP_SCALEY_MN_PHASE; | ||
147 | else | ||
148 | pipe->op_mode |= MDP4_OP_SCALEY_FIR; | ||
149 | } | ||
150 | |||
151 | pipe->phasey_step = mdp4_scale_phase_step(29, | ||
152 | pipe->src_h, pipe->dst_h); | ||
153 | } | ||
154 | |||
155 | if (pipe->dst_w && pipe->src_w != pipe->dst_w) { | ||
156 | if (pipe->dst_w >= pipe->src_w * 8) /* too much */ | ||
157 | return; | ||
158 | pipe->op_mode |= MDP4_OP_SCALEX_EN; | ||
159 | |||
160 | if (pipe->pipe_type == OVERLAY_TYPE_VG) { | ||
161 | if (pipe->dst_w <= (pipe->src_w / 4)) | ||
162 | pipe->op_mode |= MDP4_OP_SCALEY_MN_PHASE; | ||
163 | else | ||
164 | pipe->op_mode |= MDP4_OP_SCALEY_FIR; | ||
165 | } | ||
166 | |||
167 | pipe->phasex_step = mdp4_scale_phase_step(29, | ||
168 | pipe->src_w, pipe->dst_w); | ||
169 | } | ||
170 | } | ||
171 | |||
172 | void mdp4_overlay_rgb_setup(struct mdp4_overlay_pipe *pipe) | ||
173 | { | ||
174 | char *rgb_base; | ||
175 | uint32 src_size, src_xy, dst_size, dst_xy; | ||
176 | uint32 format, pattern; | ||
177 | |||
178 | rgb_base = MDP_BASE + MDP4_RGB_BASE; | ||
179 | rgb_base += (MDP4_RGB_OFF * pipe->pipe_num); | ||
180 | |||
181 | src_size = ((pipe->src_h << 16) | pipe->src_w); | ||
182 | src_xy = ((pipe->src_y << 16) | pipe->src_x); | ||
183 | dst_size = ((pipe->dst_h << 16) | pipe->dst_w); | ||
184 | dst_xy = ((pipe->dst_y << 16) | pipe->dst_x); | ||
185 | |||
186 | format = mdp4_overlay_format(pipe); | ||
187 | pattern = mdp4_overlay_unpack_pattern(pipe); | ||
188 | |||
189 | pipe->op_mode |= MDP4_OP_IGC_LUT_EN; | ||
190 | |||
191 | mdp4_scale_setup(pipe); | ||
192 | |||
193 | outpdw(rgb_base + 0x0000, src_size); /* MDP_RGB_SRC_SIZE */ | ||
194 | outpdw(rgb_base + 0x0004, src_xy); /* MDP_RGB_SRC_XY */ | ||
195 | outpdw(rgb_base + 0x0008, dst_size); /* MDP_RGB_DST_SIZE */ | ||
196 | outpdw(rgb_base + 0x000c, dst_xy); /* MDP_RGB_DST_XY */ | ||
197 | |||
198 | outpdw(rgb_base + 0x0010, pipe->srcp0_addr); | ||
199 | outpdw(rgb_base + 0x0040, pipe->srcp0_ystride); | ||
200 | |||
201 | outpdw(rgb_base + 0x0050, format);/* MDP_RGB_SRC_FORMAT */ | ||
202 | outpdw(rgb_base + 0x0054, pattern);/* MDP_RGB_SRC_UNPACK_PATTERN */ | ||
203 | outpdw(rgb_base + 0x0058, pipe->op_mode);/* MDP_RGB_OP_MODE */ | ||
204 | outpdw(rgb_base + 0x005c, pipe->phasex_step); | ||
205 | outpdw(rgb_base + 0x0060, pipe->phasey_step); | ||
206 | |||
207 | /* 16 bytes-burst x 3 req <= 48 bytes */ | ||
208 | outpdw(rgb_base + 0x1004, 0xc2); /* MDP_RGB_FETCH_CFG */ | ||
209 | } | ||
210 | |||
211 | void mdp4_overlay_vg_setup(struct mdp4_overlay_pipe *pipe) | ||
212 | { | ||
213 | char *vg_base; | ||
214 | uint32 frame_size, src_size, src_xy, dst_size, dst_xy; | ||
215 | uint32 format, pattern; | ||
216 | |||
217 | vg_base = MDP_BASE + MDP4_VIDEO_BASE; | ||
218 | vg_base += (MDP4_VIDEO_OFF * pipe->pipe_num); | ||
219 | |||
220 | frame_size = ((pipe->src_height << 16) | pipe->src_width); | ||
221 | src_size = ((pipe->src_h << 16) | pipe->src_w); | ||
222 | src_xy = ((pipe->src_y << 16) | pipe->src_x); | ||
223 | dst_size = ((pipe->dst_h << 16) | pipe->dst_w); | ||
224 | dst_xy = ((pipe->dst_y << 16) | pipe->dst_x); | ||
225 | |||
226 | format = mdp4_overlay_format(pipe); | ||
227 | pattern = mdp4_overlay_unpack_pattern(pipe); | ||
228 | |||
229 | pipe->op_mode |= (MDP4_OP_CSC_EN | MDP4_OP_SRC_DATA_YCBCR | | ||
230 | MDP4_OP_IGC_LUT_EN); | ||
231 | |||
232 | mdp4_scale_setup(pipe); | ||
233 | |||
234 | outpdw(vg_base + 0x0000, src_size); /* MDP_RGB_SRC_SIZE */ | ||
235 | outpdw(vg_base + 0x0004, src_xy); /* MDP_RGB_SRC_XY */ | ||
236 | outpdw(vg_base + 0x0008, dst_size); /* MDP_RGB_DST_SIZE */ | ||
237 | outpdw(vg_base + 0x000c, dst_xy); /* MDP_RGB_DST_XY */ | ||
238 | outpdw(vg_base + 0x0048, frame_size); /* TILE frame size */ | ||
239 | |||
240 | /* luma component plane */ | ||
241 | outpdw(vg_base + 0x0010, pipe->srcp0_addr); | ||
242 | |||
243 | /* chroma component plane */ | ||
244 | outpdw(vg_base + 0x0014, pipe->srcp1_addr); | ||
245 | |||
246 | outpdw(vg_base + 0x0040, | ||
247 | pipe->srcp1_ystride << 16 | pipe->srcp0_ystride); | ||
248 | |||
249 | outpdw(vg_base + 0x0050, format); /* MDP_RGB_SRC_FORMAT */ | ||
250 | outpdw(vg_base + 0x0054, pattern); /* MDP_RGB_SRC_UNPACK_PATTERN */ | ||
251 | outpdw(vg_base + 0x0058, pipe->op_mode);/* MDP_RGB_OP_MODE */ | ||
252 | outpdw(vg_base + 0x005c, pipe->phasex_step); | ||
253 | outpdw(vg_base + 0x0060, pipe->phasey_step); | ||
254 | |||
255 | if (pipe->op_mode & MDP4_OP_DITHER_EN) { | ||
256 | outpdw(vg_base + 0x0068, | ||
257 | pipe->r_bit << 4 | pipe->b_bit << 2 | pipe->g_bit); | ||
258 | } | ||
259 | |||
260 | /* 16 bytes-burst x 3 req <= 48 bytes */ | ||
261 | outpdw(vg_base + 0x1004, 0xc2); /* MDP_VG_FETCH_CFG */ | ||
262 | } | ||
263 | |||
264 | int mdp4_overlay_format2type(uint32 format) | ||
265 | { | ||
266 | switch (format) { | ||
267 | case MDP_RGB_565: | ||
268 | case MDP_RGB_888: | ||
269 | case MDP_BGR_565: | ||
270 | case MDP_ARGB_8888: | ||
271 | case MDP_RGBA_8888: | ||
272 | case MDP_BGRA_8888: | ||
273 | return OVERLAY_TYPE_RGB; | ||
274 | case MDP_YCRYCB_H2V1: | ||
275 | case MDP_Y_CRCB_H2V1: | ||
276 | case MDP_Y_CBCR_H2V1: | ||
277 | case MDP_Y_CRCB_H2V2: | ||
278 | case MDP_Y_CBCR_H2V2: | ||
279 | case MDP_Y_CBCR_H2V2_TILE: | ||
280 | case MDP_Y_CRCB_H2V2_TILE: | ||
281 | return OVERLAY_TYPE_VG; | ||
282 | default: | ||
283 | return -ERANGE; | ||
284 | } | ||
285 | |||
286 | } | ||
287 | |||
288 | #define C3_ALPHA 3 /* alpha */ | ||
289 | #define C2_R_Cr 2 /* R/Cr */ | ||
290 | #define C1_B_Cb 1 /* B/Cb */ | ||
291 | #define C0_G_Y 0 /* G/luma */ | ||
292 | |||
293 | int mdp4_overlay_format2pipe(struct mdp4_overlay_pipe *pipe) | ||
294 | { | ||
295 | switch (pipe->src_format) { | ||
296 | case MDP_RGB_565: | ||
297 | pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR; | ||
298 | pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED; | ||
299 | pipe->a_bit = 0; | ||
300 | pipe->r_bit = 1; /* R, 5 bits */ | ||
301 | pipe->b_bit = 1; /* B, 5 bits */ | ||
302 | pipe->g_bit = 2; /* G, 6 bits */ | ||
303 | pipe->alpha_enable = 0; | ||
304 | pipe->unpack_tight = 1; | ||
305 | pipe->unpack_align_msb = 0; | ||
306 | pipe->unpack_count = 2; | ||
307 | pipe->element2 = C2_R_Cr; /* R */ | ||
308 | pipe->element1 = C0_G_Y; /* G */ | ||
309 | pipe->element0 = C1_B_Cb; /* B */ | ||
310 | pipe->bpp = 2; /* 2 bpp */ | ||
311 | break; | ||
312 | case MDP_RGB_888: | ||
313 | pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR; | ||
314 | pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED; | ||
315 | pipe->a_bit = 0; | ||
316 | pipe->r_bit = 3; /* R, 8 bits */ | ||
317 | pipe->b_bit = 3; /* B, 8 bits */ | ||
318 | pipe->g_bit = 3; /* G, 8 bits */ | ||
319 | pipe->alpha_enable = 0; | ||
320 | pipe->unpack_tight = 1; | ||
321 | pipe->unpack_align_msb = 0; | ||
322 | pipe->unpack_count = 2; | ||
323 | pipe->element2 = C2_R_Cr; /* R */ | ||
324 | pipe->element1 = C0_G_Y; /* G */ | ||
325 | pipe->element0 = C1_B_Cb; /* B */ | ||
326 | pipe->bpp = 3; /* 3 bpp */ | ||
327 | break; | ||
328 | case MDP_BGR_565: | ||
329 | pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR; | ||
330 | pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED; | ||
331 | pipe->a_bit = 0; | ||
332 | pipe->r_bit = 1; /* R, 5 bits */ | ||
333 | pipe->b_bit = 1; /* B, 5 bits */ | ||
334 | pipe->g_bit = 2; /* G, 6 bits */ | ||
335 | pipe->alpha_enable = 0; | ||
336 | pipe->unpack_tight = 1; | ||
337 | pipe->unpack_align_msb = 0; | ||
338 | pipe->unpack_count = 2; | ||
339 | pipe->element2 = C1_B_Cb; /* B */ | ||
340 | pipe->element1 = C0_G_Y; /* G */ | ||
341 | pipe->element0 = C2_R_Cr; /* R */ | ||
342 | pipe->bpp = 2; /* 2 bpp */ | ||
343 | break; | ||
344 | case MDP_ARGB_8888: | ||
345 | pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR; | ||
346 | pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED; | ||
347 | pipe->a_bit = 3; /* alpha, 4 bits */ | ||
348 | pipe->r_bit = 3; /* R, 8 bits */ | ||
349 | pipe->b_bit = 3; /* B, 8 bits */ | ||
350 | pipe->g_bit = 3; /* G, 8 bits */ | ||
351 | pipe->alpha_enable = 1; | ||
352 | pipe->unpack_tight = 1; | ||
353 | pipe->unpack_align_msb = 0; | ||
354 | pipe->unpack_count = 3; | ||
355 | pipe->element3 = C3_ALPHA; /* alpha */ | ||
356 | pipe->element2 = C2_R_Cr; /* R */ | ||
357 | pipe->element1 = C0_G_Y; /* G */ | ||
358 | pipe->element0 = C1_B_Cb; /* B */ | ||
359 | pipe->bpp = 4; /* 4 bpp */ | ||
360 | break; | ||
361 | case MDP_RGBA_8888: | ||
362 | pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR; | ||
363 | pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED; | ||
364 | pipe->a_bit = 3; /* alpha, 4 bits */ | ||
365 | pipe->r_bit = 3; /* R, 8 bits */ | ||
366 | pipe->b_bit = 3; /* B, 8 bits */ | ||
367 | pipe->g_bit = 3; /* G, 8 bits */ | ||
368 | pipe->alpha_enable = 1; | ||
369 | pipe->unpack_tight = 1; | ||
370 | pipe->unpack_align_msb = 0; | ||
371 | pipe->unpack_count = 3; | ||
372 | pipe->element3 = C2_R_Cr; /* R */ | ||
373 | pipe->element2 = C0_G_Y; /* G */ | ||
374 | pipe->element1 = C1_B_Cb; /* B */ | ||
375 | pipe->element0 = C3_ALPHA; /* alpha */ | ||
376 | pipe->bpp = 4; /* 4 bpp */ | ||
377 | break; | ||
378 | case MDP_BGRA_8888: | ||
379 | pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR; | ||
380 | pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED; | ||
381 | pipe->a_bit = 3; /* alpha, 4 bits */ | ||
382 | pipe->r_bit = 3; /* R, 8 bits */ | ||
383 | pipe->b_bit = 3; /* B, 8 bits */ | ||
384 | pipe->g_bit = 3; /* G, 8 bits */ | ||
385 | pipe->alpha_enable = 1; | ||
386 | pipe->unpack_tight = 1; | ||
387 | pipe->unpack_align_msb = 0; | ||
388 | pipe->unpack_count = 3; | ||
389 | pipe->element3 = C1_B_Cb; /* B */ | ||
390 | pipe->element2 = C0_G_Y; /* G */ | ||
391 | pipe->element1 = C2_R_Cr; /* R */ | ||
392 | pipe->element0 = C3_ALPHA; /* alpha */ | ||
393 | pipe->bpp = 4; /* 4 bpp */ | ||
394 | break; | ||
395 | case MDP_YCRYCB_H2V1: | ||
396 | pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR; | ||
397 | pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED; | ||
398 | pipe->a_bit = 0; /* alpha, 4 bits */ | ||
399 | pipe->r_bit = 3; /* R, 8 bits */ | ||
400 | pipe->b_bit = 3; /* B, 8 bits */ | ||
401 | pipe->g_bit = 3; /* G, 8 bits */ | ||
402 | pipe->alpha_enable = 0; | ||
403 | pipe->unpack_tight = 1; | ||
404 | pipe->unpack_align_msb = 0; | ||
405 | pipe->unpack_count = 3; | ||
406 | pipe->element3 = C0_G_Y; /* G */ | ||
407 | pipe->element2 = C2_R_Cr; /* R */ | ||
408 | pipe->element1 = C0_G_Y; /* G */ | ||
409 | pipe->element0 = C1_B_Cb; /* B */ | ||
410 | pipe->bpp = 2; /* 2 bpp */ | ||
411 | pipe->chroma_sample = MDP4_CHROMA_H2V1; | ||
412 | break; | ||
413 | case MDP_Y_CRCB_H2V1: | ||
414 | case MDP_Y_CBCR_H2V1: | ||
415 | case MDP_Y_CRCB_H2V2: | ||
416 | case MDP_Y_CBCR_H2V2: | ||
417 | pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR; | ||
418 | pipe->fetch_plane = OVERLAY_PLANE_PSEUDO_PLANAR; | ||
419 | pipe->a_bit = 0; | ||
420 | pipe->r_bit = 3; /* R, 8 bits */ | ||
421 | pipe->b_bit = 3; /* B, 8 bits */ | ||
422 | pipe->g_bit = 3; /* G, 8 bits */ | ||
423 | pipe->alpha_enable = 0; | ||
424 | pipe->unpack_tight = 1; | ||
425 | pipe->unpack_align_msb = 0; | ||
426 | pipe->unpack_count = 1; /* 2 */ | ||
427 | pipe->element3 = C0_G_Y; /* not used */ | ||
428 | pipe->element2 = C0_G_Y; /* not used */ | ||
429 | if (pipe->src_format == MDP_Y_CRCB_H2V1) { | ||
430 | pipe->element1 = C2_R_Cr; /* R */ | ||
431 | pipe->element0 = C1_B_Cb; /* B */ | ||
432 | pipe->chroma_sample = MDP4_CHROMA_H2V1; | ||
433 | } else if (pipe->src_format == MDP_Y_CBCR_H2V1) { | ||
434 | pipe->element1 = C1_B_Cb; /* B */ | ||
435 | pipe->element0 = C2_R_Cr; /* R */ | ||
436 | pipe->chroma_sample = MDP4_CHROMA_H2V1; | ||
437 | } else if (pipe->src_format == MDP_Y_CRCB_H2V2) { | ||
438 | pipe->element1 = C2_R_Cr; /* R */ | ||
439 | pipe->element0 = C1_B_Cb; /* B */ | ||
440 | pipe->chroma_sample = MDP4_CHROMA_420; | ||
441 | } else if (pipe->src_format == MDP_Y_CBCR_H2V2) { | ||
442 | pipe->element1 = C1_B_Cb; /* B */ | ||
443 | pipe->element0 = C2_R_Cr; /* R */ | ||
444 | pipe->chroma_sample = MDP4_CHROMA_420; | ||
445 | } | ||
446 | pipe->bpp = 2; /* 2 bpp */ | ||
447 | break; | ||
448 | case MDP_Y_CBCR_H2V2_TILE: | ||
449 | case MDP_Y_CRCB_H2V2_TILE: | ||
450 | pipe->frame_format = MDP4_FRAME_FORMAT_VIDEO_SUPERTILE; | ||
451 | pipe->fetch_plane = OVERLAY_PLANE_PSEUDO_PLANAR; | ||
452 | pipe->a_bit = 0; | ||
453 | pipe->r_bit = 3; /* R, 8 bits */ | ||
454 | pipe->b_bit = 3; /* B, 8 bits */ | ||
455 | pipe->g_bit = 3; /* G, 8 bits */ | ||
456 | pipe->alpha_enable = 0; | ||
457 | pipe->unpack_tight = 1; | ||
458 | pipe->unpack_align_msb = 0; | ||
459 | pipe->unpack_count = 1; /* 2 */ | ||
460 | pipe->element3 = C0_G_Y; /* not used */ | ||
461 | pipe->element2 = C0_G_Y; /* not used */ | ||
462 | if (pipe->src_format == MDP_Y_CRCB_H2V2_TILE) { | ||
463 | pipe->element1 = C2_R_Cr; /* R */ | ||
464 | pipe->element0 = C1_B_Cb; /* B */ | ||
465 | pipe->chroma_sample = MDP4_CHROMA_420; | ||
466 | } else if (pipe->src_format == MDP_Y_CBCR_H2V2_TILE) { | ||
467 | pipe->element1 = C1_B_Cb; /* B */ | ||
468 | pipe->element0 = C2_R_Cr; /* R */ | ||
469 | pipe->chroma_sample = MDP4_CHROMA_420; | ||
470 | } | ||
471 | pipe->bpp = 2; /* 2 bpp */ | ||
472 | break; | ||
473 | default: | ||
474 | /* not likely */ | ||
475 | return -ERANGE; | ||
476 | } | ||
477 | |||
478 | return 0; | ||
479 | } | ||
480 | |||
481 | /* | ||
482 | * color_key_convert: output with 12 bits color key | ||
483 | */ | ||
484 | static uint32 color_key_convert(int start, int num, uint32 color) | ||
485 | { | ||
486 | |||
487 | uint32 data; | ||
488 | |||
489 | data = (color >> start) & ((1 << num) - 1); | ||
490 | |||
491 | if (num == 5) | ||
492 | data = (data << 7) + (data << 2) + (data >> 3); | ||
493 | else if (num == 6) | ||
494 | data = (data << 6) + data; | ||
495 | else /* 8 bits */ | ||
496 | data = (data << 4) + (data >> 4); | ||
497 | |||
498 | return data; | ||
499 | |||
500 | } | ||
501 | |||
502 | void transp_color_key(int format, uint32 transp, | ||
503 | uint32 *c0, uint32 *c1, uint32 *c2) | ||
504 | { | ||
505 | int b_start, g_start, r_start; | ||
506 | int b_num, g_num, r_num; | ||
507 | |||
508 | switch (format) { | ||
509 | case MDP_RGB_565: | ||
510 | b_start = 0; | ||
511 | g_start = 5; | ||
512 | r_start = 11; | ||
513 | r_num = 5; | ||
514 | g_num = 6; | ||
515 | b_num = 5; | ||
516 | break; | ||
517 | case MDP_RGB_888: | ||
518 | case MDP_XRGB_8888: | ||
519 | case MDP_ARGB_8888: | ||
520 | b_start = 0; | ||
521 | g_start = 8; | ||
522 | r_start = 16; | ||
523 | r_num = 8; | ||
524 | g_num = 8; | ||
525 | b_num = 8; | ||
526 | break; | ||
527 | case MDP_BGR_565: | ||
528 | b_start = 11; | ||
529 | g_start = 5; | ||
530 | r_start = 0; | ||
531 | r_num = 5; | ||
532 | g_num = 6; | ||
533 | b_num = 5; | ||
534 | break; | ||
535 | case MDP_Y_CBCR_H2V2: | ||
536 | case MDP_Y_CBCR_H2V1: | ||
537 | b_start = 8; | ||
538 | g_start = 16; | ||
539 | r_start = 0; | ||
540 | r_num = 8; | ||
541 | g_num = 8; | ||
542 | b_num = 8; | ||
543 | break; | ||
544 | case MDP_Y_CRCB_H2V2: | ||
545 | case MDP_Y_CRCB_H2V1: | ||
546 | b_start = 0; | ||
547 | g_start = 16; | ||
548 | r_start = 8; | ||
549 | r_num = 8; | ||
550 | g_num = 8; | ||
551 | b_num = 8; | ||
552 | break; | ||
553 | default: | ||
554 | b_start = 0; | ||
555 | g_start = 8; | ||
556 | r_start = 16; | ||
557 | r_num = 8; | ||
558 | g_num = 8; | ||
559 | b_num = 8; | ||
560 | break; | ||
561 | } | ||
562 | |||
563 | *c0 = color_key_convert(g_start, g_num, transp); | ||
564 | *c1 = color_key_convert(b_start, b_num, transp); | ||
565 | *c2 = color_key_convert(r_start, r_num, transp); | ||
566 | } | ||
567 | |||
568 | uint32 mdp4_overlay_format(struct mdp4_overlay_pipe *pipe) | ||
569 | { | ||
570 | uint32 format; | ||
571 | |||
572 | format = 0; | ||
573 | |||
574 | if (pipe->solid_fill) | ||
575 | format |= MDP4_FORMAT_SOLID_FILL; | ||
576 | |||
577 | if (pipe->unpack_align_msb) | ||
578 | format |= MDP4_FORMAT_UNPACK_ALIGN_MSB; | ||
579 | |||
580 | if (pipe->unpack_tight) | ||
581 | format |= MDP4_FORMAT_UNPACK_TIGHT; | ||
582 | |||
583 | if (pipe->alpha_enable) | ||
584 | format |= MDP4_FORMAT_ALPHA_ENABLE; | ||
585 | |||
586 | format |= (pipe->unpack_count << 13); | ||
587 | format |= ((pipe->bpp - 1) << 9); | ||
588 | format |= (pipe->a_bit << 6); | ||
589 | format |= (pipe->r_bit << 4); | ||
590 | format |= (pipe->b_bit << 2); | ||
591 | format |= pipe->g_bit; | ||
592 | |||
593 | format |= (pipe->frame_format << 29); | ||
594 | |||
595 | if (pipe->fetch_plane == OVERLAY_PLANE_PSEUDO_PLANAR) { | ||
596 | /* video/graphic */ | ||
597 | format |= (pipe->fetch_plane << 19); | ||
598 | format |= (pipe->chroma_site << 28); | ||
599 | format |= (pipe->chroma_sample << 26); | ||
600 | } | ||
601 | |||
602 | return format; | ||
603 | } | ||
604 | |||
605 | uint32 mdp4_overlay_unpack_pattern(struct mdp4_overlay_pipe *pipe) | ||
606 | { | ||
607 | return (pipe->element3 << 24) | (pipe->element2 << 16) | | ||
608 | (pipe->element1 << 8) | pipe->element0; | ||
609 | } | ||
610 | |||
611 | void mdp4_overlayproc_cfg(struct mdp4_overlay_pipe *pipe) | ||
612 | { | ||
613 | uint32 data; | ||
614 | char *overlay_base; | ||
615 | |||
616 | if (pipe->mixer_num == MDP4_MIXER1) | ||
617 | overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */ | ||
618 | else | ||
619 | overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */ | ||
620 | |||
621 | /* MDP_OVERLAYPROC_CFG */ | ||
622 | outpdw(overlay_base + 0x0004, 0x01); /* directout */ | ||
623 | data = pipe->src_height; | ||
624 | data <<= 16; | ||
625 | data |= pipe->src_width; | ||
626 | outpdw(overlay_base + 0x0008, data); /* ROI, height + width */ | ||
627 | outpdw(overlay_base + 0x000c, pipe->srcp0_addr); | ||
628 | outpdw(overlay_base + 0x0010, pipe->srcp0_ystride); | ||
629 | outpdw(overlay_base + 0x0014, 0x4); /* GC_LUT_EN, 888 */ | ||
630 | } | ||
631 | |||
632 | int mdp4_overlay_active(int mixer) | ||
633 | { | ||
634 | uint32 data, mask, i; | ||
635 | int p1, p2; | ||
636 | |||
637 | data = inpdw(MDP_BASE + 0x10100); | ||
638 | p1 = 0; | ||
639 | p2 = 0; | ||
640 | for (i = 0; i < 8; i++) { | ||
641 | mask = data & 0x0f; | ||
642 | if (mask) { | ||
643 | if (mask <= 4) | ||
644 | p1++; | ||
645 | else | ||
646 | p2++; | ||
647 | } | ||
648 | data >>= 4; | ||
649 | } | ||
650 | |||
651 | if (mixer) | ||
652 | return p2; | ||
653 | else | ||
654 | return p1; | ||
655 | } | ||
656 | |||
657 | void mdp4_mixer_stage_up(struct mdp4_overlay_pipe *pipe) | ||
658 | { | ||
659 | uint32 data, mask, snum, stage, mixer; | ||
660 | |||
661 | stage = pipe->mixer_stage; | ||
662 | mixer = pipe->mixer_num; | ||
663 | |||
664 | /* MDP_LAYERMIXER_IN_CFG, shard by both mixer 0 and 1 */ | ||
665 | data = inpdw(MDP_BASE + 0x10100); | ||
666 | |||
667 | if (mixer == MDP4_MIXER1) | ||
668 | stage += 8; | ||
669 | |||
670 | if (pipe->pipe_type == OVERLAY_TYPE_VG) {/* VG1 and VG2 */ | ||
671 | snum = 0; | ||
672 | snum += (4 * pipe->pipe_num); | ||
673 | } else { | ||
674 | snum = 8; | ||
675 | snum += (4 * pipe->pipe_num); /* RGB1 and RGB2 */ | ||
676 | } | ||
677 | |||
678 | mask = 0x0f; | ||
679 | mask <<= snum; | ||
680 | stage <<= snum; | ||
681 | data &= ~mask; /* clear old bits */ | ||
682 | |||
683 | data |= stage; | ||
684 | |||
685 | outpdw(MDP_BASE + 0x10100, data); /* MDP_LAYERMIXER_IN_CFG */ | ||
686 | |||
687 | data = inpdw(MDP_BASE + 0x10100); | ||
688 | |||
689 | ctrl->stage[pipe->mixer_num][pipe->mixer_stage] = pipe; /* keep it */ | ||
690 | } | ||
691 | |||
692 | void mdp4_mixer_stage_down(struct mdp4_overlay_pipe *pipe) | ||
693 | { | ||
694 | uint32 data, mask, snum, stage, mixer; | ||
695 | |||
696 | stage = pipe->mixer_stage; | ||
697 | mixer = pipe->mixer_num; | ||
698 | |||
699 | if (pipe != ctrl->stage[mixer][stage]) /* not runing */ | ||
700 | return; | ||
701 | |||
702 | /* MDP_LAYERMIXER_IN_CFG, shard by both mixer 0 and 1 */ | ||
703 | data = inpdw(MDP_BASE + 0x10100); | ||
704 | |||
705 | if (mixer == MDP4_MIXER1) | ||
706 | stage += 8; | ||
707 | |||
708 | if (pipe->pipe_type == OVERLAY_TYPE_VG) {/* VG1 and VG2 */ | ||
709 | snum = 0; | ||
710 | snum += (4 * pipe->pipe_num); | ||
711 | } else { | ||
712 | snum = 8; | ||
713 | snum += (4 * pipe->pipe_num); /* RGB1 and RGB2 */ | ||
714 | } | ||
715 | |||
716 | mask = 0x0f; | ||
717 | mask <<= snum; | ||
718 | data &= ~mask; /* clear old bits */ | ||
719 | |||
720 | outpdw(MDP_BASE + 0x10100, data); /* MDP_LAYERMIXER_IN_CFG */ | ||
721 | |||
722 | data = inpdw(MDP_BASE + 0x10100); | ||
723 | |||
724 | ctrl->stage[pipe->mixer_num][pipe->mixer_stage] = NULL; /* clear it */ | ||
725 | } | ||
726 | |||
727 | void mdp4_mixer_blend_setup(struct mdp4_overlay_pipe *pipe) | ||
728 | { | ||
729 | unsigned char *overlay_base; | ||
730 | uint32 c0, c1, c2, blend_op; | ||
731 | int off; | ||
732 | |||
733 | if (pipe->mixer_num) /* mixer number, /dev/fb0, /dev/fb1 */ | ||
734 | overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */ | ||
735 | else | ||
736 | overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */ | ||
737 | |||
738 | /* stage 0 to stage 2 */ | ||
739 | off = 0x20 * (pipe->mixer_stage - MDP4_MIXER_STAGE0); | ||
740 | |||
741 | blend_op = 0; | ||
742 | if (pipe->alpha_enable) /* ARGB */ | ||
743 | blend_op = MDP4_BLEND_FG_ALPHA_FG_PIXEL | | ||
744 | MDP4_BLEND_BG_ALPHA_FG_PIXEL; | ||
745 | else | ||
746 | blend_op = (MDP4_BLEND_BG_ALPHA_BG_CONST | | ||
747 | MDP4_BLEND_FG_ALPHA_FG_CONST); | ||
748 | |||
749 | |||
750 | if (pipe->alpha_enable == 0) { /* not ARGB */ | ||
751 | if (pipe->is_fg) { | ||
752 | outpdw(overlay_base + off + 0x108, pipe->alpha); | ||
753 | outpdw(overlay_base + off + 0x10c, 0xff - pipe->alpha); | ||
754 | } else { | ||
755 | outpdw(overlay_base + off + 0x108, 0xff - pipe->alpha); | ||
756 | outpdw(overlay_base + off + 0x10c, pipe->alpha); | ||
757 | } | ||
758 | } | ||
759 | |||
760 | if (pipe->transp != MDP_TRANSP_NOP) { | ||
761 | transp_color_key(pipe->src_format, pipe->transp, &c0, &c1, &c2); | ||
762 | if (pipe->is_fg) { | ||
763 | blend_op |= MDP4_BLEND_FG_TRANSP_EN; /* Fg blocked */ | ||
764 | /* lower limit */ | ||
765 | if (c0 > 0x10) | ||
766 | c0 -= 0x10; | ||
767 | if (c1 > 0x10) | ||
768 | c1 -= 0x10; | ||
769 | if (c2 > 0x10) | ||
770 | c2 -= 0x10; | ||
771 | outpdw(overlay_base + off + 0x110, | ||
772 | (c1 << 16 | c0));/* low */ | ||
773 | outpdw(overlay_base + off + 0x114, c2);/* low */ | ||
774 | /* upper limit */ | ||
775 | if ((c0 + 0x20) < 0x0fff) | ||
776 | c0 += 0x20; | ||
777 | else | ||
778 | c0 = 0x0fff; | ||
779 | if ((c1 + 0x20) < 0x0fff) | ||
780 | c1 += 0x20; | ||
781 | else | ||
782 | c1 = 0x0fff; | ||
783 | if ((c2 + 0x20) < 0x0fff) | ||
784 | c2 += 0x20; | ||
785 | else | ||
786 | c2 = 0x0fff; | ||
787 | outpdw(overlay_base + off + 0x118, | ||
788 | (c1 << 16 | c0));/* high */ | ||
789 | outpdw(overlay_base + off + 0x11c, c2);/* high */ | ||
790 | } else { | ||
791 | blend_op |= MDP4_BLEND_BG_TRANSP_EN; /* bg blocked */ | ||
792 | /* lower limit */ | ||
793 | if (c0 > 0x10) | ||
794 | c0 -= 0x10; | ||
795 | if (c1 > 0x10) | ||
796 | c1 -= 0x10; | ||
797 | if (c2 > 0x10) | ||
798 | c2 -= 0x10; | ||
799 | outpdw(overlay_base + 0x180, | ||
800 | (c1 << 16 | c0));/* low */ | ||
801 | outpdw(overlay_base + 0x184, c2);/* low */ | ||
802 | /* upper limit */ | ||
803 | if ((c0 + 0x20) < 0x0fff) | ||
804 | c0 += 0x20; | ||
805 | else | ||
806 | c0 = 0x0fff; | ||
807 | if ((c1 + 0x20) < 0x0fff) | ||
808 | c1 += 0x20; | ||
809 | else | ||
810 | c1 = 0x0fff; | ||
811 | if ((c2 + 0x20) < 0x0fff) | ||
812 | c2 += 0x20; | ||
813 | else | ||
814 | c2 = 0x0fff; | ||
815 | outpdw(overlay_base + 0x188, | ||
816 | (c1 << 16 | c0));/* high */ | ||
817 | outpdw(overlay_base + 0x18c, c2);/* high */ | ||
818 | } | ||
819 | } | ||
820 | outpdw(overlay_base + off + 0x104, blend_op); | ||
821 | } | ||
822 | |||
823 | void mdp4_overlay_reg_flush(struct mdp4_overlay_pipe *pipe, int all) | ||
824 | { | ||
825 | uint32 bits = 0; | ||
826 | |||
827 | if (pipe->mixer_num == MDP4_MIXER1) | ||
828 | bits |= 0x02; | ||
829 | else | ||
830 | bits |= 0x01; | ||
831 | |||
832 | if (all) { | ||
833 | if (pipe->pipe_type == OVERLAY_TYPE_RGB) { | ||
834 | if (pipe->pipe_num == OVERLAY_PIPE_RGB2) | ||
835 | bits |= 0x20; | ||
836 | else | ||
837 | bits |= 0x10; | ||
838 | } else { | ||
839 | if (pipe->pipe_num == OVERLAY_PIPE_VG2) | ||
840 | bits |= 0x08; | ||
841 | else | ||
842 | bits |= 0x04; | ||
843 | } | ||
844 | } | ||
845 | |||
846 | outpdw(MDP_BASE + 0x18000, bits); /* MDP_OVERLAY_REG_FLUSH */ | ||
847 | |||
848 | while (inpdw(MDP_BASE + 0x18000) & bits) /* self clear when complete */ | ||
849 | ; | ||
850 | } | ||
851 | |||
852 | struct mdp4_overlay_pipe *mdp4_overlay_ndx2pipe(int ndx) | ||
853 | { | ||
854 | struct mdp4_overlay_pipe *pipe; | ||
855 | |||
856 | if (ndx == 0 || ndx >= MDP4_MAX_OVERLAY_PIPE) | ||
857 | return NULL; | ||
858 | |||
859 | pipe = &ctrl->plist[ndx - 1]; /* ndx start from 1 */ | ||
860 | |||
861 | if (pipe->pipe_ndx == 0) | ||
862 | return NULL; | ||
863 | |||
864 | return pipe; | ||
865 | } | ||
866 | |||
867 | struct mdp4_overlay_pipe *mdp4_overlay_pipe_alloc(void) | ||
868 | { | ||
869 | int i; | ||
870 | struct mdp4_overlay_pipe *pipe; | ||
871 | |||
872 | pipe = &ctrl->plist[0]; | ||
873 | for (i = 0; i < MDP4_MAX_OVERLAY_PIPE; i++) { | ||
874 | if (pipe->pipe_ndx == 0) { | ||
875 | pipe->pipe_ndx = i + 1; /* start from 1 */ | ||
876 | init_completion(&pipe->comp); | ||
877 | printk(KERN_INFO "mdp4_overlay_pipe_alloc: pipe=%x ndx=%d\n", | ||
878 | (int)pipe, pipe->pipe_ndx); | ||
879 | return pipe; | ||
880 | } | ||
881 | pipe++; | ||
882 | } | ||
883 | |||
884 | return NULL; | ||
885 | } | ||
886 | |||
887 | |||
888 | void mdp4_overlay_pipe_free(struct mdp4_overlay_pipe *pipe) | ||
889 | { | ||
890 | printk(KERN_INFO "mdp4_overlay_pipe_free: pipe=%x ndx=%d\n", | ||
891 | (int)pipe, pipe->pipe_ndx); | ||
892 | memset(pipe, 0, sizeof(*pipe)); | ||
893 | } | ||
894 | |||
895 | static int get_pipe_num(int ptype, int stage) | ||
896 | { | ||
897 | if (ptype == OVERLAY_TYPE_RGB) { | ||
898 | if (stage == MDP4_MIXER_STAGE_BASE) | ||
899 | return OVERLAY_PIPE_RGB1; | ||
900 | else | ||
901 | return OVERLAY_PIPE_RGB2; | ||
902 | } else { | ||
903 | if (stage == MDP4_MIXER_STAGE0) | ||
904 | return OVERLAY_PIPE_VG1; | ||
905 | else | ||
906 | return OVERLAY_PIPE_VG2; | ||
907 | } | ||
908 | } | ||
909 | |||
910 | int mdp4_overlay_req_check(uint32 id, uint32 z_order, uint32 mixer) | ||
911 | { | ||
912 | struct mdp4_overlay_pipe *pipe; | ||
913 | |||
914 | pipe = ctrl->stage[mixer][z_order]; | ||
915 | |||
916 | if (pipe == NULL) | ||
917 | return 0; | ||
918 | |||
919 | if (pipe->pipe_ndx == id) /* same req, recycle */ | ||
920 | return 0; | ||
921 | |||
922 | return -EPERM; | ||
923 | } | ||
924 | |||
925 | static int mdp4_overlay_req2pipe(struct mdp_overlay *req, int mixer, | ||
926 | struct mdp4_overlay_pipe **ppipe) | ||
927 | { | ||
928 | struct mdp4_overlay_pipe *pipe; | ||
929 | int ret, ptype; | ||
930 | |||
931 | if (mixer >= MDP4_MAX_MIXER) { | ||
932 | printk(KERN_ERR "mpd_overlay_req2pipe: mixer out of range!\n"); | ||
933 | return -ERANGE; | ||
934 | } | ||
935 | |||
936 | if (req->z_order < 0 || req->z_order > 2) { | ||
937 | printk(KERN_ERR "mpd_overlay_req2pipe: z_order=%d out of range!\n", | ||
938 | req->z_order); | ||
939 | return -ERANGE; | ||
940 | } | ||
941 | |||
942 | if (req->src_rect.h == 0 || req->src_rect.w == 0) { | ||
943 | printk(KERN_ERR "mpd_overlay_req2pipe: src img of zero size!\n"); | ||
944 | return -EINVAL; | ||
945 | } | ||
946 | |||
947 | ret = mdp4_overlay_req_check(req->id, req->z_order, mixer); | ||
948 | if (ret < 0) | ||
949 | return ret; | ||
950 | |||
951 | ptype = mdp4_overlay_format2type(req->src.format); | ||
952 | if (ptype < 0) | ||
953 | return ptype; | ||
954 | |||
955 | if (req->id == MSMFB_NEW_REQUEST) /* new request */ | ||
956 | pipe = mdp4_overlay_pipe_alloc(); | ||
957 | else | ||
958 | pipe = mdp4_overlay_ndx2pipe(req->id); | ||
959 | |||
960 | if (pipe == NULL) | ||
961 | return -ENOMEM; | ||
962 | |||
963 | pipe->src_format = req->src.format; | ||
964 | ret = mdp4_overlay_format2pipe(pipe); | ||
965 | |||
966 | if (ret < 0) | ||
967 | return ret; | ||
968 | |||
969 | /* | ||
970 | * base layer == 1, reserved for frame buffer | ||
971 | * zorder 0 == stage 0 == 2 | ||
972 | * zorder 1 == stage 1 == 3 | ||
973 | * zorder 2 == stage 2 == 4 | ||
974 | */ | ||
975 | if (req->id == MSMFB_NEW_REQUEST) { /* new request */ | ||
976 | pipe->mixer_stage = req->z_order + MDP4_MIXER_STAGE0; | ||
977 | pipe->pipe_type = ptype; | ||
978 | pipe->pipe_num = get_pipe_num(ptype, pipe->mixer_stage); | ||
979 | printk(KERN_INFO "mpd4_overlay_req2pipe: zorder=%d pipe_num=%d\n", | ||
980 | req->z_order, pipe->pipe_num); | ||
981 | } | ||
982 | |||
983 | pipe->src_width = req->src.width & 0x07ff; /* source img width */ | ||
984 | pipe->src_height = req->src.height & 0x07ff; /* source img height */ | ||
985 | pipe->src_h = req->src_rect.h & 0x07ff; | ||
986 | pipe->src_w = req->src_rect.w & 0x07ff; | ||
987 | pipe->src_y = req->src_rect.y & 0x07ff; | ||
988 | pipe->src_x = req->src_rect.x & 0x07ff; | ||
989 | pipe->dst_h = req->dst_rect.h & 0x07ff; | ||
990 | pipe->dst_w = req->dst_rect.w & 0x07ff; | ||
991 | pipe->dst_y = req->dst_rect.y & 0x07ff; | ||
992 | pipe->dst_x = req->dst_rect.x & 0x07ff; | ||
993 | |||
994 | if (req->flags & MDP_FLIP_LR) | ||
995 | pipe->op_mode |= MDP4_OP_FLIP_LR; | ||
996 | |||
997 | if (req->flags & MDP_FLIP_UD) | ||
998 | pipe->op_mode |= MDP4_OP_FLIP_UD; | ||
999 | |||
1000 | if (req->flags & MDP_DITHER) | ||
1001 | pipe->op_mode |= MDP4_OP_DITHER_EN; | ||
1002 | |||
1003 | if (req->flags & MDP_DEINTERLACE) | ||
1004 | pipe->op_mode |= MDP4_OP_DEINT_ODD_REF; | ||
1005 | |||
1006 | pipe->is_fg = req->is_fg;/* control alpha and color key */ | ||
1007 | |||
1008 | pipe->alpha = req->alpha & 0x0ff; | ||
1009 | |||
1010 | pipe->transp = req->transp_mask; | ||
1011 | |||
1012 | *ppipe = pipe; | ||
1013 | |||
1014 | return 0; | ||
1015 | } | ||
1016 | |||
1017 | int get_img(struct msmfb_data *img, struct fb_info *info, | ||
1018 | unsigned long *start, unsigned long *len, struct file **pp_file) | ||
1019 | { | ||
1020 | int put_needed, ret = 0; | ||
1021 | struct file *file; | ||
1022 | #ifdef CONFIG_ANDROID_PMEM | ||
1023 | unsigned long vstart; | ||
1024 | #endif | ||
1025 | |||
1026 | #ifdef CONFIG_ANDROID_PMEM | ||
1027 | if (!get_pmem_file(img->memory_id, start, &vstart, len, pp_file)) | ||
1028 | return 0; | ||
1029 | #endif | ||
1030 | file = fget_light(img->memory_id, &put_needed); | ||
1031 | if (file == NULL) | ||
1032 | return -1; | ||
1033 | |||
1034 | if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) { | ||
1035 | *start = info->fix.smem_start; | ||
1036 | *len = info->fix.smem_len; | ||
1037 | *pp_file = file; | ||
1038 | } else { | ||
1039 | ret = -1; | ||
1040 | fput_light(file, put_needed); | ||
1041 | } | ||
1042 | return ret; | ||
1043 | } | ||
1044 | int mdp4_overlay_get(struct fb_info *info, struct mdp_overlay *req) | ||
1045 | { | ||
1046 | struct mdp4_overlay_pipe *pipe; | ||
1047 | |||
1048 | pipe = mdp4_overlay_ndx2pipe(req->id); | ||
1049 | if (pipe == NULL) | ||
1050 | return -ENODEV; | ||
1051 | |||
1052 | *req = pipe->req_data; | ||
1053 | |||
1054 | return 0; | ||
1055 | } | ||
1056 | |||
1057 | int mdp4_overlay_set(struct fb_info *info, struct mdp_overlay *req) | ||
1058 | { | ||
1059 | struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; | ||
1060 | int ret, mixer; | ||
1061 | struct mdp4_overlay_pipe *pipe; | ||
1062 | int lcdc; | ||
1063 | |||
1064 | if (mfd == NULL) | ||
1065 | return -ENODEV; | ||
1066 | |||
1067 | if (req->src.format == MDP_FB_FORMAT) | ||
1068 | req->src.format = mfd->fb_imgType; | ||
1069 | |||
1070 | if (mutex_lock_interruptible(&mfd->dma->ov_mutex)) | ||
1071 | return -EINTR; | ||
1072 | |||
1073 | mixer = info->node; /* minor number of char device */ | ||
1074 | |||
1075 | ret = mdp4_overlay_req2pipe(req, mixer, &pipe); | ||
1076 | if (ret < 0) { | ||
1077 | mutex_unlock(&mfd->dma->ov_mutex); | ||
1078 | return ret; | ||
1079 | } | ||
1080 | |||
1081 | lcdc = inpdw(MDP_BASE + 0xc0000); | ||
1082 | |||
1083 | if (lcdc == 0) { /* mddi */ | ||
1084 | /* MDP cmd block enable */ | ||
1085 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); | ||
1086 | } | ||
1087 | |||
1088 | /* return id back to user */ | ||
1089 | req->id = pipe->pipe_ndx; /* pipe_ndx start from 1 */ | ||
1090 | pipe->req_data = *req; /* keep original req */ | ||
1091 | |||
1092 | mutex_unlock(&mfd->dma->ov_mutex); | ||
1093 | |||
1094 | return 0; | ||
1095 | } | ||
1096 | |||
1097 | int mdp4_overlay_unset(struct fb_info *info, int ndx) | ||
1098 | { | ||
1099 | struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; | ||
1100 | struct mdp4_overlay_pipe *pipe; | ||
1101 | int lcdc; | ||
1102 | |||
1103 | if (mfd == NULL) | ||
1104 | return -ENODEV; | ||
1105 | |||
1106 | if (mutex_lock_interruptible(&mfd->dma->ov_mutex)) | ||
1107 | return -EINTR; | ||
1108 | |||
1109 | pipe = mdp4_overlay_ndx2pipe(ndx); | ||
1110 | |||
1111 | if (pipe == NULL) { | ||
1112 | mutex_unlock(&mfd->dma->ov_mutex); | ||
1113 | return -ENODEV; | ||
1114 | } | ||
1115 | |||
1116 | lcdc = inpdw(MDP_BASE + 0xc0000); | ||
1117 | |||
1118 | mdp4_mixer_stage_down(pipe); | ||
1119 | |||
1120 | if (lcdc == 0) { /* mddi */ | ||
1121 | /* MDP cmd block disable */ | ||
1122 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); | ||
1123 | } | ||
1124 | |||
1125 | if (lcdc) /* LCDC mode */ | ||
1126 | mdp4_overlay_reg_flush(pipe, 0); | ||
1127 | |||
1128 | mdp4_overlay_pipe_free(pipe); | ||
1129 | |||
1130 | if (lcdc == 0) { /* mddi */ | ||
1131 | mdp4_mddi_overlay_restore(); | ||
1132 | } | ||
1133 | |||
1134 | mutex_unlock(&mfd->dma->ov_mutex); | ||
1135 | |||
1136 | return 0; | ||
1137 | } | ||
1138 | |||
1139 | struct tile_desc { | ||
1140 | uint32 width; /* tile's width */ | ||
1141 | uint32 height; /* tile's height */ | ||
1142 | uint32 row_tile_w; /* tiles per row's width */ | ||
1143 | uint32 row_tile_h; /* tiles per row's height */ | ||
1144 | }; | ||
1145 | |||
1146 | void tile_samsung(struct tile_desc *tp) | ||
1147 | { | ||
1148 | /* | ||
1149 | * each row of samsung tile consists of two tiles in height | ||
1150 | * and two tiles in width which means width should align to | ||
1151 | * 64 x 2 bytes and height should align to 32 x 2 bytes. | ||
1152 | * video decoder generate two tiles in width and one tile | ||
1153 | * in height which ends up height align to 32 X 1 bytes. | ||
1154 | */ | ||
1155 | tp->width = 64; /* 64 bytes */ | ||
1156 | tp->row_tile_w = 2; /* 2 tiles per row's width */ | ||
1157 | tp->height = 32; /* 32 bytes */ | ||
1158 | tp->row_tile_h = 1; /* 1 tiles per row's height */ | ||
1159 | } | ||
1160 | |||
1161 | uint32 tile_mem_size(struct mdp4_overlay_pipe *pipe, struct tile_desc *tp) | ||
1162 | { | ||
1163 | uint32 tile_w, tile_h; | ||
1164 | uint32 row_num_w, row_num_h; | ||
1165 | |||
1166 | |||
1167 | tile_w = tp->width * tp->row_tile_w; | ||
1168 | tile_h = tp->height * tp->row_tile_h; | ||
1169 | |||
1170 | row_num_w = (pipe->src_width + tile_w - 1) / tile_w; | ||
1171 | row_num_h = (pipe->src_height + tile_h - 1) / tile_h; | ||
1172 | |||
1173 | return row_num_w * row_num_h * tile_w * tile_h; | ||
1174 | } | ||
1175 | |||
1176 | int mdp4_overlay_play(struct fb_info *info, struct msmfb_overlay_data *req, | ||
1177 | struct file **pp_src_file) | ||
1178 | { | ||
1179 | struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; | ||
1180 | struct msmfb_data *img; | ||
1181 | struct mdp4_overlay_pipe *pipe; | ||
1182 | ulong start, addr; | ||
1183 | ulong len = 0; | ||
1184 | struct file *p_src_file = 0; | ||
1185 | int lcdc; | ||
1186 | |||
1187 | if (mfd == NULL) | ||
1188 | return -ENODEV; | ||
1189 | |||
1190 | pipe = mdp4_overlay_ndx2pipe(req->id); | ||
1191 | if (pipe == NULL) | ||
1192 | return -ENODEV; | ||
1193 | |||
1194 | if (mutex_lock_interruptible(&mfd->dma->ov_mutex)) | ||
1195 | return -EINTR; | ||
1196 | |||
1197 | img = &req->data; | ||
1198 | get_img(img, info, &start, &len, &p_src_file); | ||
1199 | if (len == 0) { | ||
1200 | mutex_unlock(&mfd->dma->ov_mutex); | ||
1201 | printk(KERN_ERR "mdp_overlay_play: could not retrieve" | ||
1202 | " image from memory\n"); | ||
1203 | return -1; | ||
1204 | } | ||
1205 | *pp_src_file = p_src_file; | ||
1206 | |||
1207 | addr = start + img->offset; | ||
1208 | pipe->srcp0_addr = addr; | ||
1209 | pipe->srcp0_ystride = pipe->src_width * pipe->bpp; | ||
1210 | |||
1211 | if (pipe->fetch_plane == OVERLAY_PLANE_PSEUDO_PLANAR) { | ||
1212 | if (pipe->frame_format == MDP4_FRAME_FORMAT_VIDEO_SUPERTILE) { | ||
1213 | struct tile_desc tile; | ||
1214 | |||
1215 | tile_samsung(&tile); | ||
1216 | pipe->srcp1_addr = addr + tile_mem_size(pipe, &tile); | ||
1217 | } else | ||
1218 | pipe->srcp1_addr = addr + | ||
1219 | pipe->src_width * pipe->src_height; | ||
1220 | |||
1221 | pipe->srcp0_ystride = pipe->src_width; | ||
1222 | pipe->srcp1_ystride = pipe->src_width; | ||
1223 | } | ||
1224 | |||
1225 | lcdc = inpdw(MDP_BASE + 0xc0000); | ||
1226 | lcdc &= 0x01; /* LCDC mode */ | ||
1227 | |||
1228 | if (pipe->pipe_type == OVERLAY_TYPE_VG) | ||
1229 | mdp4_overlay_vg_setup(pipe); /* video/graphic pipe */ | ||
1230 | else | ||
1231 | mdp4_overlay_rgb_setup(pipe); /* rgb pipe */ | ||
1232 | |||
1233 | mdp4_mixer_blend_setup(pipe); | ||
1234 | mdp4_mixer_stage_up(pipe); | ||
1235 | |||
1236 | if (lcdc) { /* LCDC mode */ | ||
1237 | mdp4_overlay_reg_flush(pipe, 1); | ||
1238 | } | ||
1239 | |||
1240 | if (lcdc) { /* LCDC mode */ | ||
1241 | if (pipe->mixer_stage != MDP4_MIXER_STAGE_BASE) { /* done */ | ||
1242 | mutex_unlock(&mfd->dma->ov_mutex); | ||
1243 | return 0; | ||
1244 | } | ||
1245 | } | ||
1246 | |||
1247 | if (lcdc == 0) { /* MDDI mode */ | ||
1248 | #ifdef MDP4_NONBLOCKING | ||
1249 | if (mfd->panel_power_on) | ||
1250 | #else | ||
1251 | if (!mfd->dma->busy && mfd->panel_power_on) | ||
1252 | #endif | ||
1253 | mdp4_mddi_overlay_kickoff(mfd, pipe); | ||
1254 | } | ||
1255 | |||
1256 | mutex_unlock(&mfd->dma->ov_mutex); | ||
1257 | |||
1258 | return 0; | ||
1259 | } | ||
diff --git a/drivers/staging/msm/mdp4_overlay_lcdc.c b/drivers/staging/msm/mdp4_overlay_lcdc.c new file mode 100644 index 000000000000..a6ab8ec83f55 --- /dev/null +++ b/drivers/staging/msm/mdp4_overlay_lcdc.c | |||
@@ -0,0 +1,313 @@ | |||
1 | /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/sched.h> | ||
21 | #include <linux/time.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/hrtimer.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <mach/hardware.h> | ||
27 | #include <linux/io.h> | ||
28 | |||
29 | #include <asm/system.h> | ||
30 | #include <asm/mach-types.h> | ||
31 | #include <linux/semaphore.h> | ||
32 | #include <linux/spinlock.h> | ||
33 | |||
34 | #include <linux/fb.h> | ||
35 | |||
36 | #include "mdp.h" | ||
37 | #include "msm_fb.h" | ||
38 | #include "mdp4.h" | ||
39 | |||
40 | #ifdef CONFIG_FB_MSM_MDP40 | ||
41 | #define LCDC_BASE 0xC0000 | ||
42 | #else | ||
43 | #define LCDC_BASE 0xE0000 | ||
44 | #endif | ||
45 | |||
46 | int first_pixel_start_x; | ||
47 | int first_pixel_start_y; | ||
48 | |||
49 | static struct mdp4_overlay_pipe *lcdc_pipe; | ||
50 | |||
51 | int mdp_lcdc_on(struct platform_device *pdev) | ||
52 | { | ||
53 | int lcdc_width; | ||
54 | int lcdc_height; | ||
55 | int lcdc_bpp; | ||
56 | int lcdc_border_clr; | ||
57 | int lcdc_underflow_clr; | ||
58 | int lcdc_hsync_skew; | ||
59 | |||
60 | int hsync_period; | ||
61 | int hsync_ctrl; | ||
62 | int vsync_period; | ||
63 | int display_hctl; | ||
64 | int display_v_start; | ||
65 | int display_v_end; | ||
66 | int active_hctl; | ||
67 | int active_h_start; | ||
68 | int active_h_end; | ||
69 | int active_v_start; | ||
70 | int active_v_end; | ||
71 | int ctrl_polarity; | ||
72 | int h_back_porch; | ||
73 | int h_front_porch; | ||
74 | int v_back_porch; | ||
75 | int v_front_porch; | ||
76 | int hsync_pulse_width; | ||
77 | int vsync_pulse_width; | ||
78 | int hsync_polarity; | ||
79 | int vsync_polarity; | ||
80 | int data_en_polarity; | ||
81 | int hsync_start_x; | ||
82 | int hsync_end_x; | ||
83 | uint8 *buf; | ||
84 | int bpp, ptype; | ||
85 | uint32 format; | ||
86 | struct fb_info *fbi; | ||
87 | struct fb_var_screeninfo *var; | ||
88 | struct msm_fb_data_type *mfd; | ||
89 | struct mdp4_overlay_pipe *pipe; | ||
90 | int ret; | ||
91 | |||
92 | mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev); | ||
93 | |||
94 | if (!mfd) | ||
95 | return -ENODEV; | ||
96 | |||
97 | if (mfd->key != MFD_KEY) | ||
98 | return -EINVAL; | ||
99 | |||
100 | fbi = mfd->fbi; | ||
101 | var = &fbi->var; | ||
102 | |||
103 | /* MDP cmd block enable */ | ||
104 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); | ||
105 | |||
106 | bpp = fbi->var.bits_per_pixel / 8; | ||
107 | buf = (uint8 *) fbi->fix.smem_start; | ||
108 | buf += fbi->var.xoffset * bpp + | ||
109 | fbi->var.yoffset * fbi->fix.line_length; | ||
110 | |||
111 | if (bpp == 2) | ||
112 | format = MDP_RGB_565; | ||
113 | else if (bpp == 3) | ||
114 | format = MDP_RGB_888; | ||
115 | else | ||
116 | format = MDP_ARGB_8888; | ||
117 | |||
118 | |||
119 | if (lcdc_pipe == NULL) { | ||
120 | ptype = mdp4_overlay_format2type(format); | ||
121 | pipe = mdp4_overlay_pipe_alloc(); | ||
122 | pipe->pipe_type = ptype; | ||
123 | /* use RGB1 pipe */ | ||
124 | pipe->pipe_num = OVERLAY_PIPE_RGB1; | ||
125 | pipe->mixer_stage = MDP4_MIXER_STAGE_BASE; | ||
126 | pipe->mixer_num = MDP4_MIXER0; | ||
127 | pipe->src_format = format; | ||
128 | mdp4_overlay_format2pipe(pipe); | ||
129 | |||
130 | lcdc_pipe = pipe; /* keep it */ | ||
131 | } else { | ||
132 | pipe = lcdc_pipe; | ||
133 | } | ||
134 | |||
135 | pipe->src_height = fbi->var.yres; | ||
136 | pipe->src_width = fbi->var.xres; | ||
137 | pipe->src_h = fbi->var.yres; | ||
138 | pipe->src_w = fbi->var.xres; | ||
139 | pipe->src_y = 0; | ||
140 | pipe->src_x = 0; | ||
141 | pipe->srcp0_addr = (uint32) buf; | ||
142 | pipe->srcp0_ystride = fbi->fix.line_length; | ||
143 | |||
144 | mdp4_overlay_dmap_xy(pipe); | ||
145 | mdp4_overlay_dmap_cfg(mfd, 1); | ||
146 | |||
147 | mdp4_overlay_rgb_setup(pipe); | ||
148 | |||
149 | mdp4_mixer_stage_up(pipe); | ||
150 | |||
151 | mdp4_overlayproc_cfg(pipe); | ||
152 | |||
153 | /* | ||
154 | * LCDC timing setting | ||
155 | */ | ||
156 | h_back_porch = var->left_margin; | ||
157 | h_front_porch = var->right_margin; | ||
158 | v_back_porch = var->upper_margin; | ||
159 | v_front_porch = var->lower_margin; | ||
160 | hsync_pulse_width = var->hsync_len; | ||
161 | vsync_pulse_width = var->vsync_len; | ||
162 | lcdc_border_clr = mfd->panel_info.lcdc.border_clr; | ||
163 | lcdc_underflow_clr = mfd->panel_info.lcdc.underflow_clr; | ||
164 | lcdc_hsync_skew = mfd->panel_info.lcdc.hsync_skew; | ||
165 | |||
166 | lcdc_width = mfd->panel_info.xres; | ||
167 | lcdc_height = mfd->panel_info.yres; | ||
168 | lcdc_bpp = mfd->panel_info.bpp; | ||
169 | |||
170 | hsync_period = | ||
171 | hsync_pulse_width + h_back_porch + lcdc_width + h_front_porch; | ||
172 | hsync_ctrl = (hsync_period << 16) | hsync_pulse_width; | ||
173 | hsync_start_x = hsync_pulse_width + h_back_porch; | ||
174 | hsync_end_x = hsync_period - h_front_porch - 1; | ||
175 | display_hctl = (hsync_end_x << 16) | hsync_start_x; | ||
176 | |||
177 | vsync_period = | ||
178 | (vsync_pulse_width + v_back_porch + lcdc_height + | ||
179 | v_front_porch) * hsync_period; | ||
180 | display_v_start = | ||
181 | (vsync_pulse_width + v_back_porch) * hsync_period + lcdc_hsync_skew; | ||
182 | display_v_end = | ||
183 | vsync_period - (v_front_porch * hsync_period) + lcdc_hsync_skew - 1; | ||
184 | |||
185 | if (lcdc_width != var->xres) { | ||
186 | active_h_start = hsync_start_x + first_pixel_start_x; | ||
187 | active_h_end = active_h_start + var->xres - 1; | ||
188 | active_hctl = | ||
189 | ACTIVE_START_X_EN | (active_h_end << 16) | active_h_start; | ||
190 | } else { | ||
191 | active_hctl = 0; | ||
192 | } | ||
193 | |||
194 | if (lcdc_height != var->yres) { | ||
195 | active_v_start = | ||
196 | display_v_start + first_pixel_start_y * hsync_period; | ||
197 | active_v_end = active_v_start + (var->yres) * hsync_period - 1; | ||
198 | active_v_start |= ACTIVE_START_Y_EN; | ||
199 | } else { | ||
200 | active_v_start = 0; | ||
201 | active_v_end = 0; | ||
202 | } | ||
203 | |||
204 | |||
205 | #ifdef CONFIG_FB_MSM_MDP40 | ||
206 | hsync_polarity = 1; | ||
207 | vsync_polarity = 1; | ||
208 | lcdc_underflow_clr |= 0x80000000; /* enable recovery */ | ||
209 | #else | ||
210 | hsync_polarity = 0; | ||
211 | vsync_polarity = 0; | ||
212 | #endif | ||
213 | data_en_polarity = 0; | ||
214 | |||
215 | ctrl_polarity = | ||
216 | (data_en_polarity << 2) | (vsync_polarity << 1) | (hsync_polarity); | ||
217 | |||
218 | MDP_OUTP(MDP_BASE + LCDC_BASE + 0x4, hsync_ctrl); | ||
219 | MDP_OUTP(MDP_BASE + LCDC_BASE + 0x8, vsync_period); | ||
220 | MDP_OUTP(MDP_BASE + LCDC_BASE + 0xc, vsync_pulse_width * hsync_period); | ||
221 | MDP_OUTP(MDP_BASE + LCDC_BASE + 0x10, display_hctl); | ||
222 | MDP_OUTP(MDP_BASE + LCDC_BASE + 0x14, display_v_start); | ||
223 | MDP_OUTP(MDP_BASE + LCDC_BASE + 0x18, display_v_end); | ||
224 | MDP_OUTP(MDP_BASE + LCDC_BASE + 0x28, lcdc_border_clr); | ||
225 | MDP_OUTP(MDP_BASE + LCDC_BASE + 0x2c, lcdc_underflow_clr); | ||
226 | MDP_OUTP(MDP_BASE + LCDC_BASE + 0x30, lcdc_hsync_skew); | ||
227 | MDP_OUTP(MDP_BASE + LCDC_BASE + 0x38, ctrl_polarity); | ||
228 | MDP_OUTP(MDP_BASE + LCDC_BASE + 0x1c, active_hctl); | ||
229 | MDP_OUTP(MDP_BASE + LCDC_BASE + 0x20, active_v_start); | ||
230 | MDP_OUTP(MDP_BASE + LCDC_BASE + 0x24, active_v_end); | ||
231 | |||
232 | ret = panel_next_on(pdev); | ||
233 | if (ret == 0) { | ||
234 | /* enable LCDC block */ | ||
235 | MDP_OUTP(MDP_BASE + LCDC_BASE, 1); | ||
236 | mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_ON, FALSE); | ||
237 | } | ||
238 | /* MDP cmd block disable */ | ||
239 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); | ||
240 | |||
241 | return ret; | ||
242 | } | ||
243 | |||
244 | int mdp_lcdc_off(struct platform_device *pdev) | ||
245 | { | ||
246 | int ret = 0; | ||
247 | struct mdp4_overlay_pipe *pipe; | ||
248 | |||
249 | /* MDP cmd block enable */ | ||
250 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); | ||
251 | MDP_OUTP(MDP_BASE + LCDC_BASE, 0); | ||
252 | /* MDP cmd block disable */ | ||
253 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); | ||
254 | mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); | ||
255 | |||
256 | ret = panel_next_off(pdev); | ||
257 | |||
258 | /* delay to make sure the last frame finishes */ | ||
259 | mdelay(100); | ||
260 | |||
261 | /* dis-engage rgb0 from mixer */ | ||
262 | pipe = lcdc_pipe; | ||
263 | mdp4_mixer_stage_down(pipe); | ||
264 | |||
265 | return ret; | ||
266 | } | ||
267 | |||
268 | /* | ||
269 | * mdp4_overlay0_done_lcdc: called from isr | ||
270 | */ | ||
271 | void mdp4_overlay0_done_lcdc() | ||
272 | { | ||
273 | complete(&lcdc_pipe->comp); | ||
274 | } | ||
275 | |||
276 | void mdp4_lcdc_overlay(struct msm_fb_data_type *mfd) | ||
277 | { | ||
278 | struct fb_info *fbi = mfd->fbi; | ||
279 | uint8 *buf; | ||
280 | int bpp; | ||
281 | unsigned long flag; | ||
282 | struct mdp4_overlay_pipe *pipe; | ||
283 | |||
284 | if (!mfd->panel_power_on) | ||
285 | return; | ||
286 | |||
287 | /* no need to power on cmd block since it's lcdc mode */ | ||
288 | bpp = fbi->var.bits_per_pixel / 8; | ||
289 | buf = (uint8 *) fbi->fix.smem_start; | ||
290 | buf += fbi->var.xoffset * bpp + | ||
291 | fbi->var.yoffset * fbi->fix.line_length; | ||
292 | |||
293 | mutex_lock(&mfd->dma->ov_mutex); | ||
294 | |||
295 | pipe = lcdc_pipe; | ||
296 | pipe->srcp0_addr = (uint32) buf; | ||
297 | mdp4_overlay_rgb_setup(pipe); | ||
298 | mdp4_overlay_reg_flush(pipe, 1); /* rgb1 and mixer0 */ | ||
299 | |||
300 | /* enable irq */ | ||
301 | spin_lock_irqsave(&mdp_spin_lock, flag); | ||
302 | mdp_enable_irq(MDP_OVERLAY0_TERM); | ||
303 | INIT_COMPLETION(lcdc_pipe->comp); | ||
304 | mfd->dma->waiting = TRUE; | ||
305 | outp32(MDP_INTR_CLEAR, INTR_OVERLAY0_DONE); | ||
306 | mdp_intr_mask |= INTR_OVERLAY0_DONE; | ||
307 | outp32(MDP_INTR_ENABLE, mdp_intr_mask); | ||
308 | spin_unlock_irqrestore(&mdp_spin_lock, flag); | ||
309 | wait_for_completion_killable(&lcdc_pipe->comp); | ||
310 | mdp_disable_irq(MDP_OVERLAY0_TERM); | ||
311 | |||
312 | mutex_unlock(&mfd->dma->ov_mutex); | ||
313 | } | ||
diff --git a/drivers/staging/msm/mdp4_overlay_mddi.c b/drivers/staging/msm/mdp4_overlay_mddi.c new file mode 100644 index 000000000000..be1b2874185b --- /dev/null +++ b/drivers/staging/msm/mdp4_overlay_mddi.c | |||
@@ -0,0 +1,254 @@ | |||
1 | /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/sched.h> | ||
21 | #include <linux/time.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/hrtimer.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <mach/hardware.h> | ||
27 | #include <linux/io.h> | ||
28 | |||
29 | #include <asm/system.h> | ||
30 | #include <asm/mach-types.h> | ||
31 | #include <linux/semaphore.h> | ||
32 | #include <linux/spinlock.h> | ||
33 | |||
34 | #include <linux/fb.h> | ||
35 | |||
36 | #include "mdp.h" | ||
37 | #include "msm_fb.h" | ||
38 | #include "mdp4.h" | ||
39 | |||
40 | static struct mdp4_overlay_pipe *mddi_pipe; | ||
41 | static struct mdp4_overlay_pipe *pending_pipe; | ||
42 | static struct msm_fb_data_type *mddi_mfd; | ||
43 | |||
44 | #define WHOLESCREEN | ||
45 | |||
46 | void mdp4_overlay_update_lcd(struct msm_fb_data_type *mfd) | ||
47 | { | ||
48 | MDPIBUF *iBuf = &mfd->ibuf; | ||
49 | uint8 *src; | ||
50 | int bpp, ptype; | ||
51 | uint32 format; | ||
52 | uint32 mddi_ld_param; | ||
53 | uint16 mddi_vdo_packet_reg; | ||
54 | struct mdp4_overlay_pipe *pipe; | ||
55 | |||
56 | if (mfd->key != MFD_KEY) | ||
57 | return; | ||
58 | |||
59 | mddi_mfd = mfd; /* keep it */ | ||
60 | |||
61 | bpp = iBuf->bpp; | ||
62 | |||
63 | if (bpp == 2) | ||
64 | format = MDP_RGB_565; | ||
65 | else if (bpp == 3) | ||
66 | format = MDP_RGB_888; | ||
67 | else | ||
68 | format = MDP_ARGB_8888; | ||
69 | |||
70 | /* MDP cmd block enable */ | ||
71 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); | ||
72 | |||
73 | if (mddi_pipe == NULL) { | ||
74 | ptype = mdp4_overlay_format2type(format); | ||
75 | pipe = mdp4_overlay_pipe_alloc(); | ||
76 | pipe->pipe_type = ptype; | ||
77 | /* use RGB1 pipe */ | ||
78 | pipe->pipe_num = OVERLAY_PIPE_RGB1; | ||
79 | pipe->mixer_num = MDP4_MIXER0; | ||
80 | pipe->src_format = format; | ||
81 | mdp4_overlay_format2pipe(pipe); | ||
82 | |||
83 | mddi_pipe = pipe; /* keep it */ | ||
84 | |||
85 | mddi_ld_param = 0; | ||
86 | mddi_vdo_packet_reg = mfd->panel_info.mddi.vdopkt; | ||
87 | |||
88 | if (mfd->panel_info.type == MDDI_PANEL) { | ||
89 | if (mfd->panel_info.pdest == DISPLAY_1) | ||
90 | mddi_ld_param = 0; | ||
91 | else | ||
92 | mddi_ld_param = 1; | ||
93 | } else { | ||
94 | mddi_ld_param = 2; | ||
95 | } | ||
96 | |||
97 | MDP_OUTP(MDP_BASE + 0x00090, mddi_ld_param); | ||
98 | MDP_OUTP(MDP_BASE + 0x00094, | ||
99 | (MDDI_VDO_PACKET_DESC << 16) | mddi_vdo_packet_reg); | ||
100 | } else { | ||
101 | pipe = mddi_pipe; | ||
102 | } | ||
103 | |||
104 | |||
105 | src = (uint8 *) iBuf->buf; | ||
106 | |||
107 | #ifdef WHOLESCREEN | ||
108 | { | ||
109 | struct fb_info *fbi; | ||
110 | |||
111 | fbi = mfd->fbi; | ||
112 | pipe->src_height = fbi->var.yres; | ||
113 | pipe->src_width = fbi->var.xres; | ||
114 | pipe->src_h = fbi->var.yres; | ||
115 | pipe->src_w = fbi->var.xres; | ||
116 | pipe->src_y = 0; | ||
117 | pipe->src_x = 0; | ||
118 | pipe->dst_h = fbi->var.yres; | ||
119 | pipe->dst_w = fbi->var.xres; | ||
120 | pipe->dst_y = 0; | ||
121 | pipe->dst_x = 0; | ||
122 | pipe->srcp0_addr = (uint32)src; | ||
123 | pipe->srcp0_ystride = fbi->var.xres_virtual * bpp; | ||
124 | } | ||
125 | |||
126 | #else | ||
127 | if (mdp4_overlay_active(MDP4_MIXER0)) { | ||
128 | struct fb_info *fbi; | ||
129 | |||
130 | fbi = mfd->fbi; | ||
131 | pipe->src_height = fbi->var.yres; | ||
132 | pipe->src_width = fbi->var.xres; | ||
133 | pipe->src_h = fbi->var.yres; | ||
134 | pipe->src_w = fbi->var.xres; | ||
135 | pipe->src_y = 0; | ||
136 | pipe->src_x = 0; | ||
137 | pipe->dst_h = fbi->var.yres; | ||
138 | pipe->dst_w = fbi->var.xres; | ||
139 | pipe->dst_y = 0; | ||
140 | pipe->dst_x = 0; | ||
141 | pipe->srcp0_addr = (uint32) src; | ||
142 | pipe->srcp0_ystride = fbi->var.xres_virtual * bpp; | ||
143 | } else { | ||
144 | /* starting input address */ | ||
145 | src += (iBuf->dma_x + iBuf->dma_y * iBuf->ibuf_width) * bpp; | ||
146 | |||
147 | pipe->src_height = iBuf->dma_h; | ||
148 | pipe->src_width = iBuf->dma_w; | ||
149 | pipe->src_h = iBuf->dma_h; | ||
150 | pipe->src_w = iBuf->dma_w; | ||
151 | pipe->src_y = 0; | ||
152 | pipe->src_x = 0; | ||
153 | pipe->dst_h = iBuf->dma_h; | ||
154 | pipe->dst_w = iBuf->dma_w; | ||
155 | pipe->dst_y = iBuf->dma_y; | ||
156 | pipe->dst_x = iBuf->dma_x; | ||
157 | pipe->srcp0_addr = (uint32) src; | ||
158 | pipe->srcp0_ystride = iBuf->ibuf_width * bpp; | ||
159 | } | ||
160 | #endif | ||
161 | |||
162 | pipe->mixer_stage = MDP4_MIXER_STAGE_BASE; | ||
163 | |||
164 | mdp4_overlay_rgb_setup(pipe); | ||
165 | |||
166 | mdp4_mixer_stage_up(pipe); | ||
167 | |||
168 | mdp4_overlayproc_cfg(pipe); | ||
169 | |||
170 | mdp4_overlay_dmap_xy(pipe); | ||
171 | |||
172 | mdp4_overlay_dmap_cfg(mfd, 0); | ||
173 | |||
174 | /* MDP cmd block disable */ | ||
175 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); | ||
176 | |||
177 | } | ||
178 | |||
179 | /* | ||
180 | * mdp4_overlay0_done_mddi: called from isr | ||
181 | */ | ||
182 | void mdp4_overlay0_done_mddi() | ||
183 | { | ||
184 | if (pending_pipe) | ||
185 | complete(&pending_pipe->comp); | ||
186 | } | ||
187 | |||
188 | void mdp4_mddi_overlay_restore(void) | ||
189 | { | ||
190 | /* mutex holded by caller */ | ||
191 | mdp4_overlay_update_lcd(mddi_mfd); | ||
192 | mdp4_mddi_overlay_kickoff(mddi_mfd, mddi_pipe); | ||
193 | } | ||
194 | |||
195 | void mdp4_mddi_overlay_kickoff(struct msm_fb_data_type *mfd, | ||
196 | struct mdp4_overlay_pipe *pipe) | ||
197 | { | ||
198 | #ifdef MDP4_NONBLOCKING | ||
199 | unsigned long flag; | ||
200 | |||
201 | spin_lock_irqsave(&mdp_spin_lock, flag); | ||
202 | if (mfd->dma->busy == TRUE) { | ||
203 | INIT_COMPLETION(pipe->comp); | ||
204 | pending_pipe = pipe; | ||
205 | } | ||
206 | spin_unlock_irqrestore(&mdp_spin_lock, flag); | ||
207 | |||
208 | if (pending_pipe != NULL) { | ||
209 | /* wait until DMA finishes the current job */ | ||
210 | wait_for_completion_killable(&pipe->comp); | ||
211 | pending_pipe = NULL; | ||
212 | } | ||
213 | down(&mfd->sem); | ||
214 | mdp_enable_irq(MDP_OVERLAY0_TERM); | ||
215 | mfd->dma->busy = TRUE; | ||
216 | /* start OVERLAY pipe */ | ||
217 | mdp_pipe_kickoff(MDP_OVERLAY0_TERM, mfd); | ||
218 | up(&mfd->sem); | ||
219 | #else | ||
220 | down(&mfd->sem); | ||
221 | mdp_enable_irq(MDP_OVERLAY0_TERM); | ||
222 | mfd->dma->busy = TRUE; | ||
223 | INIT_COMPLETION(pipe->comp); | ||
224 | pending_pipe = pipe; | ||
225 | |||
226 | /* start OVERLAY pipe */ | ||
227 | mdp_pipe_kickoff(MDP_OVERLAY0_TERM, mfd); | ||
228 | up(&mfd->sem); | ||
229 | |||
230 | /* wait until DMA finishes the current job */ | ||
231 | wait_for_completion_killable(&pipe->comp); | ||
232 | mdp_disable_irq(MDP_OVERLAY0_TERM); | ||
233 | #endif | ||
234 | |||
235 | } | ||
236 | |||
237 | void mdp4_mddi_overlay(struct msm_fb_data_type *mfd) | ||
238 | { | ||
239 | mutex_lock(&mfd->dma->ov_mutex); | ||
240 | |||
241 | if ((mfd) && (!mfd->dma->busy) && (mfd->panel_power_on)) { | ||
242 | mdp4_overlay_update_lcd(mfd); | ||
243 | |||
244 | mdp4_mddi_overlay_kickoff(mfd, mddi_pipe); | ||
245 | |||
246 | /* signal if pan function is waiting for the update completion */ | ||
247 | if (mfd->pan_waiting) { | ||
248 | mfd->pan_waiting = FALSE; | ||
249 | complete(&mfd->pan_comp); | ||
250 | } | ||
251 | } | ||
252 | |||
253 | mutex_unlock(&mfd->dma->ov_mutex); | ||
254 | } | ||
diff --git a/drivers/staging/msm/mdp4_util.c b/drivers/staging/msm/mdp4_util.c new file mode 100644 index 000000000000..fd97f5205992 --- /dev/null +++ b/drivers/staging/msm/mdp4_util.c | |||
@@ -0,0 +1,1686 @@ | |||
1 | |||
2 | /* Copyright (c) 2009, Code Aurora Forum. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 and | ||
6 | * only version 2 as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, write to the Free Software | ||
15 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
16 | * 02110-1301, USA. | ||
17 | */ | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/sched.h> | ||
21 | #include <linux/time.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/spinlock.h> | ||
25 | #include <linux/hrtimer.h> | ||
26 | #include <linux/clk.h> | ||
27 | #include <mach/hardware.h> | ||
28 | #include <linux/io.h> | ||
29 | #include <linux/debugfs.h> | ||
30 | |||
31 | #include <asm/system.h> | ||
32 | #include <asm/mach-types.h> | ||
33 | #include <linux/semaphore.h> | ||
34 | #include <linux/uaccess.h> | ||
35 | |||
36 | #include "mdp.h" | ||
37 | #include "msm_fb.h" | ||
38 | #include "mdp4.h" | ||
39 | |||
40 | void mdp4_sw_reset(ulong bits) | ||
41 | { | ||
42 | bits &= 0x1f; /* 5 bits */ | ||
43 | outpdw(MDP_BASE + 0x001c, bits); /* MDP_SW_RESET */ | ||
44 | |||
45 | while (inpdw(MDP_BASE + 0x001c) & bits) /* self clear when complete */ | ||
46 | ; | ||
47 | MSM_FB_INFO("mdp4_sw_reset: 0x%x\n", (int)bits); | ||
48 | } | ||
49 | |||
50 | void mdp4_overlay_cfg(int overlayer, int blt_mode, int refresh, int direct_out) | ||
51 | { | ||
52 | ulong bits = 0; | ||
53 | |||
54 | if (blt_mode) | ||
55 | bits |= (1 << 3); | ||
56 | refresh &= 0x03; /* 2 bites */ | ||
57 | bits |= (refresh << 1); | ||
58 | direct_out &= 0x01; | ||
59 | bits |= direct_out; | ||
60 | |||
61 | if (overlayer == MDP4_MIXER0) | ||
62 | outpdw(MDP_BASE + 0x10004, bits); /* MDP_OVERLAY0_CFG */ | ||
63 | else | ||
64 | outpdw(MDP_BASE + 0x18004, bits); /* MDP_OVERLAY1_CFG */ | ||
65 | |||
66 | MSM_FB_INFO("mdp4_overlay_cfg: 0x%x\n", (int)inpdw(MDP_BASE + 0x10004)); | ||
67 | } | ||
68 | |||
69 | void mdp4_display_intf_sel(int output, ulong intf) | ||
70 | { | ||
71 | ulong bits, mask; | ||
72 | |||
73 | bits = inpdw(MDP_BASE + 0x0038); /* MDP_DISP_INTF_SEL */ | ||
74 | |||
75 | mask = 0x03; /* 2 bits */ | ||
76 | intf &= 0x03; /* 2 bits */ | ||
77 | |||
78 | switch (output) { | ||
79 | case EXTERNAL_INTF_SEL: | ||
80 | intf <<= 4; | ||
81 | mask <<= 4; | ||
82 | break; | ||
83 | case SECONDARY_INTF_SEL: | ||
84 | intf &= 0x02; /* only MDDI and EBI2 support */ | ||
85 | intf <<= 2; | ||
86 | mask <<= 2; | ||
87 | break; | ||
88 | default: | ||
89 | break; | ||
90 | } | ||
91 | |||
92 | |||
93 | bits &= ~mask; | ||
94 | bits |= intf; | ||
95 | |||
96 | outpdw(MDP_BASE + 0x0038, bits); /* MDP_DISP_INTF_SEL */ | ||
97 | |||
98 | MSM_FB_INFO("mdp4_display_intf_sel: 0x%x\n", (int)inpdw(MDP_BASE + 0x0038)); | ||
99 | } | ||
100 | |||
101 | unsigned long mdp4_display_status(void) | ||
102 | { | ||
103 | return inpdw(MDP_BASE + 0x0018) & 0x3ff; /* MDP_DISPLAY_STATUS */ | ||
104 | } | ||
105 | |||
106 | void mdp4_ebi2_lcd_setup(int lcd, ulong base, int ystride) | ||
107 | { | ||
108 | /* always use memory map */ | ||
109 | ystride &= 0x01fff; /* 13 bits */ | ||
110 | if (lcd == EBI2_LCD0) { | ||
111 | outpdw(MDP_BASE + 0x0060, base);/* MDP_EBI2_LCD0 */ | ||
112 | outpdw(MDP_BASE + 0x0068, ystride);/* MDP_EBI2_LCD0_YSTRIDE */ | ||
113 | } else { | ||
114 | outpdw(MDP_BASE + 0x0064, base);/* MDP_EBI2_LCD1 */ | ||
115 | outpdw(MDP_BASE + 0x006c, ystride);/* MDP_EBI2_LCD1_YSTRIDE */ | ||
116 | } | ||
117 | } | ||
118 | |||
119 | void mdp4_mddi_setup(int mddi, unsigned long id) | ||
120 | { | ||
121 | ulong bits; | ||
122 | |||
123 | if (mddi == MDDI_EXTERNAL_SET) | ||
124 | bits = 0x02; | ||
125 | else if (mddi == MDDI_SECONDARY_SET) | ||
126 | bits = 0x01; | ||
127 | else | ||
128 | bits = 0; /* PRIMARY_SET */ | ||
129 | |||
130 | id <<= 16; | ||
131 | |||
132 | bits |= id; | ||
133 | |||
134 | outpdw(MDP_BASE + 0x0090, bits); /* MDP_MDDI_PARAM_WR_SEL */ | ||
135 | } | ||
136 | |||
137 | int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req, | ||
138 | struct file **pp_src_file, struct file **pp_dst_file) | ||
139 | { | ||
140 | |||
141 | /* not implemented yet */ | ||
142 | return -1; | ||
143 | } | ||
144 | |||
145 | void mdp4_hw_init(void) | ||
146 | { | ||
147 | ulong bits; | ||
148 | |||
149 | /* MDP cmd block enable */ | ||
150 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); | ||
151 | |||
152 | #ifdef MDP4_ERROR | ||
153 | /* | ||
154 | * Issue software reset on DMA_P will casue DMA_P dma engine stall | ||
155 | * on LCDC mode. However DMA_P does not stall at MDDI mode. | ||
156 | * This need further investigation. | ||
157 | */ | ||
158 | mdp4_sw_reset(0x17); | ||
159 | #endif | ||
160 | |||
161 | mdp4_clear_lcdc(); | ||
162 | |||
163 | mdp4_mixer_blend_init(0); | ||
164 | mdp4_mixer_blend_init(1); | ||
165 | mdp4_vg_qseed_init(0); | ||
166 | mdp4_vg_qseed_init(1); | ||
167 | mdp4_vg_csc_mv_setup(0); | ||
168 | mdp4_vg_csc_mv_setup(1); | ||
169 | mdp4_vg_csc_pre_bv_setup(0); | ||
170 | mdp4_vg_csc_pre_bv_setup(1); | ||
171 | mdp4_vg_csc_post_bv_setup(0); | ||
172 | mdp4_vg_csc_post_bv_setup(1); | ||
173 | mdp4_vg_csc_pre_lv_setup(0); | ||
174 | mdp4_vg_csc_pre_lv_setup(1); | ||
175 | mdp4_vg_csc_post_lv_setup(0); | ||
176 | mdp4_vg_csc_post_lv_setup(1); | ||
177 | |||
178 | mdp4_mixer_gc_lut_setup(0); | ||
179 | mdp4_mixer_gc_lut_setup(1); | ||
180 | |||
181 | mdp4_vg_igc_lut_setup(0); | ||
182 | mdp4_vg_igc_lut_setup(1); | ||
183 | |||
184 | mdp4_rgb_igc_lut_setup(0); | ||
185 | mdp4_rgb_igc_lut_setup(1); | ||
186 | |||
187 | outp32(MDP_EBI2_PORTMAP_MODE, 0x3); | ||
188 | |||
189 | /* system interrupts */ | ||
190 | |||
191 | bits = mdp_intr_mask; | ||
192 | outpdw(MDP_BASE + 0x0050, bits);/* enable specififed interrupts */ | ||
193 | |||
194 | /* histogram */ | ||
195 | MDP_OUTP(MDP_BASE + 0x95010, 1); /* auto clear HIST */ | ||
196 | |||
197 | /* enable histogram interrupts */ | ||
198 | outpdw(MDP_BASE + 0x9501c, INTR_HIST_DONE); | ||
199 | |||
200 | /* For the max read pending cmd config below, if the MDP clock */ | ||
201 | /* is less than the AXI clock, then we must use 3 pending */ | ||
202 | /* pending requests. Otherwise, we should use 8 pending requests. */ | ||
203 | /* In the future we should do this detection automatically. */ | ||
204 | |||
205 | /* max read pending cmd config */ | ||
206 | outpdw(MDP_BASE + 0x004c, 0x02222); /* 3 pending requests */ | ||
207 | |||
208 | /* dma_p fetch config */ | ||
209 | outpdw(MDP_BASE + 0x91004, 0x27); /* burst size of 8 */ | ||
210 | |||
211 | #ifndef CONFIG_FB_MSM_OVERLAY | ||
212 | /* both REFRESH_MODE and DIRECT_OUT are ignored at BLT mode */ | ||
213 | mdp4_overlay_cfg(MDP4_MIXER0, OVERLAY_MODE_BLT, 0, 0); | ||
214 | mdp4_overlay_cfg(MDP4_MIXER1, OVERLAY_MODE_BLT, 0, 0); | ||
215 | #endif | ||
216 | |||
217 | /* MDP cmd block disable */ | ||
218 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); | ||
219 | } | ||
220 | |||
221 | |||
222 | void mdp4_clear_lcdc(void) | ||
223 | { | ||
224 | uint32 bits; | ||
225 | |||
226 | bits = inpdw(MDP_BASE + 0xc0000); | ||
227 | if (bits & 0x01) /* enabled already */ | ||
228 | return; | ||
229 | |||
230 | outpdw(MDP_BASE + 0xc0004, 0); /* vsync ctrl out */ | ||
231 | outpdw(MDP_BASE + 0xc0008, 0); /* vsync period */ | ||
232 | outpdw(MDP_BASE + 0xc000c, 0); /* vsync pusle width */ | ||
233 | outpdw(MDP_BASE + 0xc0010, 0); /* lcdc display HCTL */ | ||
234 | outpdw(MDP_BASE + 0xc0014, 0); /* lcdc display v start */ | ||
235 | outpdw(MDP_BASE + 0xc0018, 0); /* lcdc display v end */ | ||
236 | outpdw(MDP_BASE + 0xc001c, 0); /* lcdc active hctl */ | ||
237 | outpdw(MDP_BASE + 0xc0020, 0); /* lcdc active v start */ | ||
238 | outpdw(MDP_BASE + 0xc0024, 0); /* lcdc active v end */ | ||
239 | outpdw(MDP_BASE + 0xc0028, 0); /* lcdc board color */ | ||
240 | outpdw(MDP_BASE + 0xc002c, 0); /* lcdc underflow ctrl */ | ||
241 | outpdw(MDP_BASE + 0xc0030, 0); /* lcdc hsync skew */ | ||
242 | outpdw(MDP_BASE + 0xc0034, 0); /* lcdc test ctl */ | ||
243 | outpdw(MDP_BASE + 0xc0038, 0); /* lcdc ctl polarity */ | ||
244 | } | ||
245 | |||
246 | static struct mdp_dma_data overlay1_data; | ||
247 | static int intr_dma_p; | ||
248 | static int intr_dma_s; | ||
249 | static int intr_dma_e; | ||
250 | static int intr_overlay0; | ||
251 | static int intr_overlay1; | ||
252 | |||
253 | irqreturn_t mdp4_isr(int irq, void *ptr) | ||
254 | { | ||
255 | uint32 isr, mask, lcdc; | ||
256 | struct mdp_dma_data *dma; | ||
257 | |||
258 | mdp_is_in_isr = TRUE; | ||
259 | |||
260 | while (1) { | ||
261 | isr = inpdw(MDP_INTR_STATUS); | ||
262 | if (isr == 0) | ||
263 | break; | ||
264 | |||
265 | mask = inpdw(MDP_INTR_ENABLE); | ||
266 | outpdw(MDP_INTR_CLEAR, isr); | ||
267 | |||
268 | isr &= mask; | ||
269 | |||
270 | if (unlikely(isr == 0)) | ||
271 | break; | ||
272 | |||
273 | if (isr & INTR_DMA_P_DONE) { | ||
274 | intr_dma_p++; | ||
275 | lcdc = inpdw(MDP_BASE + 0xc0000); | ||
276 | dma = &dma2_data; | ||
277 | if (lcdc & 0x01) { /* LCDC enable */ | ||
278 | /* disable LCDC interrupt */ | ||
279 | mdp_intr_mask &= ~INTR_DMA_P_DONE; | ||
280 | outp32(MDP_INTR_ENABLE, mdp_intr_mask); | ||
281 | dma->waiting = FALSE; | ||
282 | } else { | ||
283 | dma->busy = FALSE; | ||
284 | mdp_pipe_ctrl(MDP_DMA2_BLOCK, | ||
285 | MDP_BLOCK_POWER_OFF, TRUE); | ||
286 | } | ||
287 | complete(&dma->comp); | ||
288 | } | ||
289 | if (isr & INTR_DMA_S_DONE) { | ||
290 | intr_dma_s++; | ||
291 | dma = &dma_s_data; | ||
292 | dma->busy = FALSE; | ||
293 | mdp_pipe_ctrl(MDP_DMA_S_BLOCK, | ||
294 | MDP_BLOCK_POWER_OFF, TRUE); | ||
295 | complete(&dma->comp); | ||
296 | } | ||
297 | if (isr & INTR_DMA_E_DONE) { | ||
298 | intr_dma_e++; | ||
299 | dma = &dma_e_data; | ||
300 | mdp_intr_mask &= ~INTR_DMA_E_DONE; | ||
301 | outp32(MDP_INTR_ENABLE, mdp_intr_mask); | ||
302 | dma->busy = FALSE; | ||
303 | |||
304 | if (dma->waiting) { | ||
305 | dma->waiting = FALSE; | ||
306 | complete(&dma->comp); | ||
307 | } | ||
308 | } | ||
309 | if (isr & INTR_OVERLAY0_DONE) { | ||
310 | intr_overlay0++; | ||
311 | lcdc = inpdw(MDP_BASE + 0xc0000); | ||
312 | dma = &dma2_data; | ||
313 | if (lcdc & 0x01) { /* LCDC enable */ | ||
314 | /* disable LCDC interrupt */ | ||
315 | mdp_intr_mask &= ~INTR_OVERLAY0_DONE; | ||
316 | outp32(MDP_INTR_ENABLE, mdp_intr_mask); | ||
317 | dma->waiting = FALSE; | ||
318 | mdp4_overlay0_done_lcdc(); | ||
319 | } else { /* MDDI */ | ||
320 | dma->busy = FALSE; | ||
321 | #ifdef MDP4_NONBLOCKING | ||
322 | mdp_disable_irq_nolock(MDP_OVERLAY0_TERM); | ||
323 | #endif | ||
324 | mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, | ||
325 | MDP_BLOCK_POWER_OFF, TRUE); | ||
326 | mdp4_overlay0_done_mddi(); | ||
327 | } | ||
328 | } | ||
329 | if (isr & INTR_OVERLAY1_DONE) { | ||
330 | intr_overlay1++; | ||
331 | dma = &overlay1_data; | ||
332 | dma->busy = FALSE; | ||
333 | mdp_pipe_ctrl(MDP_OVERLAY1_BLOCK, | ||
334 | MDP_BLOCK_POWER_OFF, TRUE); | ||
335 | complete(&dma->comp); | ||
336 | } | ||
337 | if (isr & INTR_DMA_P_HISTOGRAM) { | ||
338 | isr = inpdw(MDP_DMA_P_HIST_INTR_STATUS); | ||
339 | mask = inpdw(MDP_DMA_P_HIST_INTR_ENABLE); | ||
340 | outpdw(MDP_DMA_P_HIST_INTR_CLEAR, isr); | ||
341 | isr &= mask; | ||
342 | if (isr & INTR_HIST_DONE) { | ||
343 | if (mdp_hist.r) | ||
344 | memcpy(mdp_hist.r, MDP_BASE + 0x95100, | ||
345 | mdp_hist.bin_cnt*4); | ||
346 | if (mdp_hist.g) | ||
347 | memcpy(mdp_hist.g, MDP_BASE + 0x95200, | ||
348 | mdp_hist.bin_cnt*4); | ||
349 | if (mdp_hist.b) | ||
350 | memcpy(mdp_hist.b, MDP_BASE + 0x95300, | ||
351 | mdp_hist.bin_cnt*4); | ||
352 | complete(&mdp_hist_comp); | ||
353 | } | ||
354 | } | ||
355 | } | ||
356 | |||
357 | mdp_is_in_isr = FALSE; | ||
358 | |||
359 | return IRQ_HANDLED; | ||
360 | } | ||
361 | |||
362 | |||
363 | /* | ||
364 | * QSEED tables | ||
365 | */ | ||
366 | |||
367 | static uint32 vg_qseed_table0[] = { | ||
368 | 0x5556aaff, 0x00000000, 0x00000000, 0x00000000 | ||
369 | }; | ||
370 | |||
371 | static uint32 vg_qseed_table1[] = { | ||
372 | 0x76543210, 0xfedcba98 | ||
373 | }; | ||
374 | |||
375 | static uint32 vg_qseed_table2[] = { | ||
376 | 0x02000000, 0x00000000, 0x02060ff2, 0x00000008, | ||
377 | 0x02090fe4, 0x00000013, 0x020a0fd9, 0x0ffc0021, | ||
378 | 0x02080fce, 0x0ffa0030, 0x02030fc5, 0x0ff60042, | ||
379 | 0x01fd0fbe, 0x0ff10054, 0x01f50fb6, 0x0fed0068, | ||
380 | 0x01e90fb1, 0x0fe60080, 0x01dc0fae, 0x0fe10095, | ||
381 | 0x01ca0fae, 0x0fda00ae, 0x01b70fad, 0x0fd600c6, | ||
382 | 0x01a40fad, 0x0fcf00e0, 0x018f0faf, 0x0fc800fa, | ||
383 | 0x01780fb1, 0x0fc30114, 0x015f0fb5, 0x0fbf012d, | ||
384 | 0x01490fb7, 0x0fb70149, 0x012d0fbf, 0x0fb5015f, | ||
385 | 0x01140fc3, 0x0fb10178, 0x00fa0fc8, 0x0faf018f, | ||
386 | 0x00e00fcf, 0x0fad01a4, 0x00c60fd6, 0x0fad01b7, | ||
387 | 0x00ae0fda, 0x0fae01ca, 0x00950fe1, 0x0fae01dc, | ||
388 | 0x00800fe6, 0x0fb101e9, 0x00680fed, 0x0fb601f5, | ||
389 | 0x00540ff1, 0x0fbe01fd, 0x00420ff6, 0x0fc50203, | ||
390 | 0x00300ffa, 0x0fce0208, 0x00210ffc, 0x0fd9020a, | ||
391 | 0x00130000, 0x0fe40209, 0x00080000, 0x0ff20206, | ||
392 | 0x02000000, 0x00000000, 0x02040ff2, 0x0000000a, | ||
393 | 0x02040fe4, 0x00000018, 0x02010fda, 0x0ffc0029, | ||
394 | 0x01fc0fcf, 0x0ffa003b, 0x01f30fc7, 0x0ff60050, | ||
395 | 0x01e90fc0, 0x0ff20065, 0x01dc0fba, 0x0fee007c, | ||
396 | 0x01cc0fb6, 0x0fe80096, 0x01ba0fb4, 0x0fe400ae, | ||
397 | 0x01a70fb4, 0x0fdd00c8, 0x018f0fb5, 0x0fda00e2, | ||
398 | 0x017a0fb5, 0x0fd400fd, 0x01630fb8, 0x0fce0117, | ||
399 | 0x014c0fba, 0x0fca0130, 0x01320fbf, 0x0fc70148, | ||
400 | 0x011b0fc1, 0x0fc10163, 0x01010fc8, 0x0fc00177, | ||
401 | 0x00e90fcd, 0x0fbd018d, 0x00d10fd1, 0x0fbc01a2, | ||
402 | 0x00ba0fd7, 0x0fbb01b4, 0x00a30fdd, 0x0fbc01c4, | ||
403 | 0x008e0fe1, 0x0fbd01d4, 0x00790fe7, 0x0fbe01e2, | ||
404 | 0x00670feb, 0x0fc001ee, 0x00540ff1, 0x0fc501f6, | ||
405 | 0x00430ff4, 0x0fcb01fe, 0x00340ff8, 0x0fd10203, | ||
406 | 0x00260ffb, 0x0fd80207, 0x001a0ffd, 0x0fe10208, | ||
407 | 0x000f0000, 0x0fea0207, 0x00060000, 0x0ff50205, | ||
408 | 0x02000000, 0x00000000, 0x02020ff2, 0x0000000c, | ||
409 | 0x02000fe4, 0x0000001c, 0x01fa0fda, 0x0ffc0030, | ||
410 | 0x01f10fd0, 0x0ffa0045, 0x01e50fc8, 0x0ff6005d, | ||
411 | 0x01d60fc3, 0x0ff30074, 0x01c60fbd, 0x0fef008e, | ||
412 | 0x01b30fba, 0x0fe900aa, 0x019e0fb9, 0x0fe500c4, | ||
413 | 0x01870fba, 0x0fe000df, 0x016f0fbb, 0x0fdd00f9, | ||
414 | 0x01580fbc, 0x0fd80114, 0x01400fbf, 0x0fd3012e, | ||
415 | 0x01280fc2, 0x0fd00146, 0x010f0fc6, 0x0fce015d, | ||
416 | 0x00f90fc9, 0x0fc90175, 0x00e00fcf, 0x0fc90188, | ||
417 | 0x00ca0fd4, 0x0fc6019c, 0x00b40fd8, 0x0fc601ae, | ||
418 | 0x009f0fdd, 0x0fc501bf, 0x008b0fe3, 0x0fc601cc, | ||
419 | 0x00780fe6, 0x0fc701db, 0x00660feb, 0x0fc801e7, | ||
420 | 0x00560fef, 0x0fcb01f0, 0x00460ff3, 0x0fcf01f8, | ||
421 | 0x00380ff6, 0x0fd401fe, 0x002c0ff9, 0x0fd90202, | ||
422 | 0x00200ffc, 0x0fdf0205, 0x00160ffe, 0x0fe60206, | ||
423 | 0x000c0000, 0x0fed0207, 0x00050000, 0x0ff70204, | ||
424 | 0x02000000, 0x00000000, 0x01fe0ff3, 0x0000000f, | ||
425 | 0x01f60fe5, 0x00000025, 0x01ea0fdb, 0x0ffd003e, | ||
426 | 0x01db0fd2, 0x0ffb0058, 0x01c80fcc, 0x0ff70075, | ||
427 | 0x01b50fc7, 0x0ff40090, 0x01a00fc3, 0x0ff000ad, | ||
428 | 0x01880fc1, 0x0feb00cc, 0x01700fc1, 0x0fe800e7, | ||
429 | 0x01550fc3, 0x0fe40104, 0x013b0fc5, 0x0fe2011e, | ||
430 | 0x01240fc6, 0x0fde0138, 0x010c0fca, 0x0fda0150, | ||
431 | 0x00f40fcd, 0x0fd90166, 0x00dd0fd1, 0x0fd7017b, | ||
432 | 0x00c80fd4, 0x0fd40190, 0x00b20fd9, 0x0fd401a1, | ||
433 | 0x009f0fdd, 0x0fd301b1, 0x008c0fe1, 0x0fd301c0, | ||
434 | 0x007b0fe5, 0x0fd301cd, 0x006a0fea, 0x0fd401d8, | ||
435 | 0x005c0fec, 0x0fd501e3, 0x004d0ff0, 0x0fd601ed, | ||
436 | 0x00410ff3, 0x0fd801f4, 0x00340ff7, 0x0fdb01fa, | ||
437 | 0x002a0ff9, 0x0fdf01fe, 0x00200ffb, 0x0fe30202, | ||
438 | 0x00180ffd, 0x0fe70204, 0x00100ffe, 0x0fed0205, | ||
439 | 0x00090000, 0x0ff20205, 0x00040000, 0x0ff90203, | ||
440 | 0x02000000, 0x00000000, 0x02050ff5, 0x00000006, | ||
441 | 0x02070fea, 0x0000000f, 0x02080fe1, 0x0ffd001a, | ||
442 | 0x02070fd8, 0x0ffb0026, 0x02030fd1, 0x0ff80034, | ||
443 | 0x01fe0fcb, 0x0ff40043, 0x01f60fc5, 0x0ff10054, | ||
444 | 0x01ee0fc0, 0x0feb0067, 0x01e20fbe, 0x0fe70079, | ||
445 | 0x01d40fbd, 0x0fe1008e, 0x01c40fbc, 0x0fdd00a3, | ||
446 | 0x01b40fbb, 0x0fd700ba, 0x01a20fbc, 0x0fd100d1, | ||
447 | 0x018d0fbd, 0x0fcd00e9, 0x01770fc0, 0x0fc80101, | ||
448 | 0x01630fc1, 0x0fc1011b, 0x01480fc7, 0x0fbf0132, | ||
449 | 0x01300fca, 0x0fba014c, 0x01170fce, 0x0fb80163, | ||
450 | 0x00fd0fd4, 0x0fb5017a, 0x00e20fda, 0x0fb5018f, | ||
451 | 0x00c80fdd, 0x0fb401a7, 0x00ae0fe4, 0x0fb401ba, | ||
452 | 0x00960fe8, 0x0fb601cc, 0x007c0fee, 0x0fba01dc, | ||
453 | 0x00650ff2, 0x0fc001e9, 0x00500ff6, 0x0fc701f3, | ||
454 | 0x003b0ffa, 0x0fcf01fc, 0x00290ffc, 0x0fda0201, | ||
455 | 0x00180000, 0x0fe40204, 0x000a0000, 0x0ff20204, | ||
456 | 0x02000000, 0x00000000, 0x02030ff5, 0x00000008, | ||
457 | 0x02030fea, 0x00000013, 0x02020fe1, 0x0ffd0020, | ||
458 | 0x01fc0fd9, 0x0ffc002f, 0x01f60fd2, 0x0ff80040, | ||
459 | 0x01ed0fcd, 0x0ff50051, 0x01e30fc7, 0x0ff10065, | ||
460 | 0x01d70fc3, 0x0fec007a, 0x01c60fc2, 0x0fe9008f, | ||
461 | 0x01b60fc1, 0x0fe300a6, 0x01a20fc1, 0x0fe000bd, | ||
462 | 0x018f0fc1, 0x0fdb00d5, 0x017b0fc2, 0x0fd500ee, | ||
463 | 0x01640fc4, 0x0fd20106, 0x014d0fc8, 0x0fce011d, | ||
464 | 0x01370fc9, 0x0fc90137, 0x011d0fce, 0x0fc8014d, | ||
465 | 0x01060fd2, 0x0fc40164, 0x00ee0fd5, 0x0fc2017b, | ||
466 | 0x00d50fdb, 0x0fc1018f, 0x00bd0fe0, 0x0fc101a2, | ||
467 | 0x00a60fe3, 0x0fc101b6, 0x008f0fe9, 0x0fc201c6, | ||
468 | 0x007a0fec, 0x0fc301d7, 0x00650ff1, 0x0fc701e3, | ||
469 | 0x00510ff5, 0x0fcd01ed, 0x00400ff8, 0x0fd201f6, | ||
470 | 0x002f0ffc, 0x0fd901fc, 0x00200ffd, 0x0fe10202, | ||
471 | 0x00130000, 0x0fea0203, 0x00080000, 0x0ff50203, | ||
472 | 0x02000000, 0x00000000, 0x02020ff5, 0x00000009, | ||
473 | 0x01ff0fea, 0x00000017, 0x01fb0fe2, 0x0ffd0026, | ||
474 | 0x01f30fda, 0x0ffc0037, 0x01ea0fd3, 0x0ff8004b, | ||
475 | 0x01df0fce, 0x0ff5005e, 0x01d10fc9, 0x0ff20074, | ||
476 | 0x01c10fc6, 0x0fed008c, 0x01ae0fc5, 0x0fea00a3, | ||
477 | 0x019b0fc5, 0x0fe500bb, 0x01850fc6, 0x0fe200d3, | ||
478 | 0x01700fc6, 0x0fde00ec, 0x015a0fc8, 0x0fd90105, | ||
479 | 0x01430fca, 0x0fd6011d, 0x012b0fcd, 0x0fd30135, | ||
480 | 0x01150fcf, 0x0fcf014d, 0x00fc0fd4, 0x0fce0162, | ||
481 | 0x00e50fd8, 0x0fcc0177, 0x00cf0fdb, 0x0fca018c, | ||
482 | 0x00b80fe0, 0x0fc9019f, 0x00a20fe5, 0x0fca01af, | ||
483 | 0x008e0fe8, 0x0fcb01bf, 0x00790fec, 0x0fcb01d0, | ||
484 | 0x00670fef, 0x0fcd01dd, 0x00550ff4, 0x0fd001e7, | ||
485 | 0x00440ff7, 0x0fd501f0, 0x00350ffa, 0x0fda01f7, | ||
486 | 0x00270ffc, 0x0fdf01fe, 0x001b0ffe, 0x0fe70200, | ||
487 | 0x00100000, 0x0fee0202, 0x00060000, 0x0ff70203, | ||
488 | 0x02000000, 0x00000000, 0x01ff0ff5, 0x0000000c, | ||
489 | 0x01f80fea, 0x0000001e, 0x01ef0fe2, 0x0ffd0032, | ||
490 | 0x01e20fdb, 0x0ffc0047, 0x01d30fd5, 0x0ff9005f, | ||
491 | 0x01c20fd1, 0x0ff60077, 0x01b00fcd, 0x0ff30090, | ||
492 | 0x019b0fcb, 0x0fef00ab, 0x01850fcb, 0x0fec00c4, | ||
493 | 0x016e0fcc, 0x0fe800de, 0x01550fcd, 0x0fe600f8, | ||
494 | 0x013f0fce, 0x0fe20111, 0x01280fd0, 0x0fdf0129, | ||
495 | 0x01110fd2, 0x0fdd0140, 0x00f90fd6, 0x0fdb0156, | ||
496 | 0x00e40fd8, 0x0fd8016c, 0x00cd0fdd, 0x0fd8017e, | ||
497 | 0x00b80fe0, 0x0fd60192, 0x00a40fe3, 0x0fd601a3, | ||
498 | 0x00910fe7, 0x0fd501b3, 0x007f0feb, 0x0fd601c0, | ||
499 | 0x006e0fed, 0x0fd701ce, 0x005d0ff1, 0x0fd701db, | ||
500 | 0x004f0ff3, 0x0fd901e5, 0x00400ff7, 0x0fdc01ed, | ||
501 | 0x00330ff9, 0x0fe001f4, 0x00280ffb, 0x0fe301fa, | ||
502 | 0x001d0ffd, 0x0fe801fe, 0x00140ffe, 0x0fed0201, | ||
503 | 0x000c0000, 0x0ff20202, 0x00050000, 0x0ff90202, | ||
504 | 0x02000000, 0x00000000, 0x02040ff7, 0x00000005, | ||
505 | 0x02070fed, 0x0000000c, 0x02060fe6, 0x0ffe0016, | ||
506 | 0x02050fdf, 0x0ffc0020, 0x02020fd9, 0x0ff9002c, | ||
507 | 0x01fe0fd4, 0x0ff60038, 0x01f80fcf, 0x0ff30046, | ||
508 | 0x01f00fcb, 0x0fef0056, 0x01e70fc8, 0x0feb0066, | ||
509 | 0x01db0fc7, 0x0fe60078, 0x01cc0fc6, 0x0fe3008b, | ||
510 | 0x01bf0fc5, 0x0fdd009f, 0x01ae0fc6, 0x0fd800b4, | ||
511 | 0x019c0fc6, 0x0fd400ca, 0x01880fc9, 0x0fcf00e0, | ||
512 | 0x01750fc9, 0x0fc900f9, 0x015d0fce, 0x0fc6010f, | ||
513 | 0x01460fd0, 0x0fc20128, 0x012e0fd3, 0x0fbf0140, | ||
514 | 0x01140fd8, 0x0fbc0158, 0x00f90fdd, 0x0fbb016f, | ||
515 | 0x00df0fe0, 0x0fba0187, 0x00c40fe5, 0x0fb9019e, | ||
516 | 0x00aa0fe9, 0x0fba01b3, 0x008e0fef, 0x0fbd01c6, | ||
517 | 0x00740ff3, 0x0fc301d6, 0x005d0ff6, 0x0fc801e5, | ||
518 | 0x00450ffa, 0x0fd001f1, 0x00300ffc, 0x0fda01fa, | ||
519 | 0x001c0000, 0x0fe40200, 0x000c0000, 0x0ff20202, | ||
520 | 0x02000000, 0x00000000, 0x02030ff7, 0x00000006, | ||
521 | 0x02020fee, 0x00000010, 0x02000fe7, 0x0ffe001b, | ||
522 | 0x01fe0fdf, 0x0ffc0027, 0x01f70fda, 0x0ffa0035, | ||
523 | 0x01f00fd5, 0x0ff70044, 0x01e70fd0, 0x0ff40055, | ||
524 | 0x01dd0fcd, 0x0fef0067, 0x01d00fcb, 0x0fec0079, | ||
525 | 0x01bf0fcb, 0x0fe8008e, 0x01af0fca, 0x0fe500a2, | ||
526 | 0x019f0fc9, 0x0fe000b8, 0x018c0fca, 0x0fdb00cf, | ||
527 | 0x01770fcc, 0x0fd800e5, 0x01620fce, 0x0fd400fc, | ||
528 | 0x014d0fcf, 0x0fcf0115, 0x01350fd3, 0x0fcd012b, | ||
529 | 0x011d0fd6, 0x0fca0143, 0x01050fd9, 0x0fc8015a, | ||
530 | 0x00ec0fde, 0x0fc60170, 0x00d30fe2, 0x0fc60185, | ||
531 | 0x00bb0fe5, 0x0fc5019b, 0x00a30fea, 0x0fc501ae, | ||
532 | 0x008c0fed, 0x0fc601c1, 0x00740ff2, 0x0fc901d1, | ||
533 | 0x005e0ff5, 0x0fce01df, 0x004b0ff8, 0x0fd301ea, | ||
534 | 0x00370ffc, 0x0fda01f3, 0x00260ffd, 0x0fe201fb, | ||
535 | 0x00170000, 0x0fea01ff, 0x00090000, 0x0ff50202, | ||
536 | 0x02000000, 0x00000000, 0x02010ff7, 0x00000008, | ||
537 | 0x01ff0fee, 0x00000013, 0x01fb0fe7, 0x0ffe0020, | ||
538 | 0x01f60fe0, 0x0ffc002e, 0x01ed0fda, 0x0ffa003f, | ||
539 | 0x01e40fd6, 0x0ff7004f, 0x01d80fd2, 0x0ff40062, | ||
540 | 0x01ca0fcf, 0x0ff00077, 0x01bb0fcd, 0x0fed008b, | ||
541 | 0x01a90fcd, 0x0fe900a1, 0x01960fcd, 0x0fe600b7, | ||
542 | 0x01830fcd, 0x0fe200ce, 0x016d0fcf, 0x0fde00e6, | ||
543 | 0x01580fd0, 0x0fdb00fd, 0x01410fd3, 0x0fd80114, | ||
544 | 0x012c0fd4, 0x0fd4012c, 0x01140fd8, 0x0fd30141, | ||
545 | 0x00fd0fdb, 0x0fd00158, 0x00e60fde, 0x0fcf016d, | ||
546 | 0x00ce0fe2, 0x0fcd0183, 0x00b70fe6, 0x0fcd0196, | ||
547 | 0x00a10fe9, 0x0fcd01a9, 0x008b0fed, 0x0fcd01bb, | ||
548 | 0x00770ff0, 0x0fcf01ca, 0x00620ff4, 0x0fd201d8, | ||
549 | 0x004f0ff7, 0x0fd601e4, 0x003f0ffa, 0x0fda01ed, | ||
550 | 0x002e0ffc, 0x0fe001f6, 0x00200ffe, 0x0fe701fb, | ||
551 | 0x00130000, 0x0fee01ff, 0x00080000, 0x0ff70201, | ||
552 | 0x02000000, 0x00000000, 0x01ff0ff7, 0x0000000a, | ||
553 | 0x01f90fee, 0x00000019, 0x01f10fe7, 0x0ffe002a, | ||
554 | 0x01e60fe1, 0x0ffd003c, 0x01d90fdc, 0x0ffa0051, | ||
555 | 0x01cc0fd8, 0x0ff70065, 0x01bb0fd5, 0x0ff5007b, | ||
556 | 0x01a80fd3, 0x0ff10094, 0x01950fd2, 0x0fef00aa, | ||
557 | 0x01800fd2, 0x0feb00c3, 0x016a0fd3, 0x0fe900da, | ||
558 | 0x01540fd3, 0x0fe600f3, 0x013f0fd5, 0x0fe2010a, | ||
559 | 0x01280fd7, 0x0fe00121, 0x01100fda, 0x0fde0138, | ||
560 | 0x00fb0fdb, 0x0fdb014f, 0x00e40fdf, 0x0fdb0162, | ||
561 | 0x00ce0fe2, 0x0fd90177, 0x00b90fe4, 0x0fd8018b, | ||
562 | 0x00a50fe8, 0x0fd8019b, 0x00910fec, 0x0fd801ab, | ||
563 | 0x007e0fee, 0x0fd801bc, 0x006c0ff2, 0x0fd901c9, | ||
564 | 0x005c0ff4, 0x0fda01d6, 0x004b0ff7, 0x0fdd01e1, | ||
565 | 0x003c0ff9, 0x0fe001eb, 0x002f0ffb, 0x0fe401f2, | ||
566 | 0x00230ffd, 0x0fe801f8, 0x00180ffe, 0x0fed01fd, | ||
567 | 0x000e0000, 0x0ff20200, 0x00060000, 0x0ff90201, | ||
568 | 0x02000000, 0x00000000, 0x02030ff9, 0x00000004, | ||
569 | 0x02050ff2, 0x00000009, 0x02050fed, 0x0ffe0010, | ||
570 | 0x02040fe7, 0x0ffd0018, 0x02020fe3, 0x0ffb0020, | ||
571 | 0x01fe0fdf, 0x0ff9002a, 0x01fa0fdb, 0x0ff70034, | ||
572 | 0x01f40fd8, 0x0ff30041, 0x01ed0fd6, 0x0ff0004d, | ||
573 | 0x01e30fd5, 0x0fec005c, 0x01d80fd4, 0x0fea006a, | ||
574 | 0x01cd0fd3, 0x0fe5007b, 0x01c00fd3, 0x0fe1008c, | ||
575 | 0x01b10fd3, 0x0fdd009f, 0x01a10fd4, 0x0fd900b2, | ||
576 | 0x01900fd4, 0x0fd400c8, 0x017b0fd7, 0x0fd100dd, | ||
577 | 0x01660fd9, 0x0fcd00f4, 0x01500fda, 0x0fca010c, | ||
578 | 0x01380fde, 0x0fc60124, 0x011e0fe2, 0x0fc5013b, | ||
579 | 0x01040fe4, 0x0fc30155, 0x00e70fe8, 0x0fc10170, | ||
580 | 0x00cc0feb, 0x0fc10188, 0x00ad0ff0, 0x0fc301a0, | ||
581 | 0x00900ff4, 0x0fc701b5, 0x00750ff7, 0x0fcc01c8, | ||
582 | 0x00580ffb, 0x0fd201db, 0x003e0ffd, 0x0fdb01ea, | ||
583 | 0x00250000, 0x0fe501f6, 0x000f0000, 0x0ff301fe, | ||
584 | 0x02000000, 0x00000000, 0x02020ff9, 0x00000005, | ||
585 | 0x02020ff2, 0x0000000c, 0x02010fed, 0x0ffe0014, | ||
586 | 0x01fe0fe8, 0x0ffd001d, 0x01fa0fe3, 0x0ffb0028, | ||
587 | 0x01f40fe0, 0x0ff90033, 0x01ed0fdc, 0x0ff70040, | ||
588 | 0x01e50fd9, 0x0ff3004f, 0x01db0fd7, 0x0ff1005d, | ||
589 | 0x01ce0fd7, 0x0fed006e, 0x01c00fd6, 0x0feb007f, | ||
590 | 0x01b30fd5, 0x0fe70091, 0x01a30fd6, 0x0fe300a4, | ||
591 | 0x01920fd6, 0x0fe000b8, 0x017e0fd8, 0x0fdd00cd, | ||
592 | 0x016c0fd8, 0x0fd800e4, 0x01560fdb, 0x0fd600f9, | ||
593 | 0x01400fdd, 0x0fd20111, 0x01290fdf, 0x0fd00128, | ||
594 | 0x01110fe2, 0x0fce013f, 0x00f80fe6, 0x0fcd0155, | ||
595 | 0x00de0fe8, 0x0fcc016e, 0x00c40fec, 0x0fcb0185, | ||
596 | 0x00ab0fef, 0x0fcb019b, 0x00900ff3, 0x0fcd01b0, | ||
597 | 0x00770ff6, 0x0fd101c2, 0x005f0ff9, 0x0fd501d3, | ||
598 | 0x00470ffc, 0x0fdb01e2, 0x00320ffd, 0x0fe201ef, | ||
599 | 0x001e0000, 0x0fea01f8, 0x000c0000, 0x0ff501ff, | ||
600 | 0x02000000, 0x00000000, 0x02010ff9, 0x00000006, | ||
601 | 0x02000ff2, 0x0000000e, 0x01fd0fed, 0x0ffe0018, | ||
602 | 0x01f80fe8, 0x0ffd0023, 0x01f20fe4, 0x0ffb002f, | ||
603 | 0x01eb0fe0, 0x0ff9003c, 0x01e10fdd, 0x0ff7004b, | ||
604 | 0x01d60fda, 0x0ff4005c, 0x01c90fd9, 0x0ff2006c, | ||
605 | 0x01bc0fd8, 0x0fee007e, 0x01ab0fd8, 0x0fec0091, | ||
606 | 0x019b0fd8, 0x0fe800a5, 0x018b0fd8, 0x0fe400b9, | ||
607 | 0x01770fd9, 0x0fe200ce, 0x01620fdb, 0x0fdf00e4, | ||
608 | 0x014f0fdb, 0x0fdb00fb, 0x01380fde, 0x0fda0110, | ||
609 | 0x01210fe0, 0x0fd70128, 0x010a0fe2, 0x0fd5013f, | ||
610 | 0x00f30fe6, 0x0fd30154, 0x00da0fe9, 0x0fd3016a, | ||
611 | 0x00c30feb, 0x0fd20180, 0x00aa0fef, 0x0fd20195, | ||
612 | 0x00940ff1, 0x0fd301a8, 0x007b0ff5, 0x0fd501bb, | ||
613 | 0x00650ff7, 0x0fd801cc, 0x00510ffa, 0x0fdc01d9, | ||
614 | 0x003c0ffd, 0x0fe101e6, 0x002a0ffe, 0x0fe701f1, | ||
615 | 0x00190000, 0x0fee01f9, 0x000a0000, 0x0ff701ff, | ||
616 | 0x02000000, 0x00000000, 0x01ff0ff9, 0x00000008, | ||
617 | 0x01fb0ff2, 0x00000013, 0x01f50fed, 0x0ffe0020, | ||
618 | 0x01ed0fe8, 0x0ffd002e, 0x01e30fe4, 0x0ffb003e, | ||
619 | 0x01d80fe1, 0x0ff9004e, 0x01cb0fde, 0x0ff70060, | ||
620 | 0x01bc0fdc, 0x0ff40074, 0x01ac0fdb, 0x0ff20087, | ||
621 | 0x019a0fdb, 0x0fef009c, 0x01870fdb, 0x0fed00b1, | ||
622 | 0x01740fdb, 0x0fea00c7, 0x01600fdc, 0x0fe700dd, | ||
623 | 0x014b0fdd, 0x0fe500f3, 0x01350fdf, 0x0fe30109, | ||
624 | 0x01200fe0, 0x0fe00120, 0x01090fe3, 0x0fdf0135, | ||
625 | 0x00f30fe5, 0x0fdd014b, 0x00dd0fe7, 0x0fdc0160, | ||
626 | 0x00c70fea, 0x0fdb0174, 0x00b10fed, 0x0fdb0187, | ||
627 | 0x009c0fef, 0x0fdb019a, 0x00870ff2, 0x0fdb01ac, | ||
628 | 0x00740ff4, 0x0fdc01bc, 0x00600ff7, 0x0fde01cb, | ||
629 | 0x004e0ff9, 0x0fe101d8, 0x003e0ffb, 0x0fe401e3, | ||
630 | 0x002e0ffd, 0x0fe801ed, 0x00200ffe, 0x0fed01f5, | ||
631 | 0x00130000, 0x0ff201fb, 0x00080000, 0x0ff901ff, | ||
632 | 0x02000000, 0x00000000, 0x02060ff2, 0x00000008, | ||
633 | 0x02090fe4, 0x00000013, 0x020a0fd9, 0x0ffc0021, | ||
634 | 0x02080fce, 0x0ffa0030, 0x02030fc5, 0x0ff60042, | ||
635 | 0x01fd0fbe, 0x0ff10054, 0x01f50fb6, 0x0fed0068, | ||
636 | 0x01e90fb1, 0x0fe60080, 0x01dc0fae, 0x0fe10095, | ||
637 | 0x01ca0fae, 0x0fda00ae, 0x01b70fad, 0x0fd600c6, | ||
638 | 0x01a40fad, 0x0fcf00e0, 0x018f0faf, 0x0fc800fa, | ||
639 | 0x01780fb1, 0x0fc30114, 0x015f0fb5, 0x0fbf012d, | ||
640 | 0x01490fb7, 0x0fb70149, 0x012d0fbf, 0x0fb5015f, | ||
641 | 0x01140fc3, 0x0fb10178, 0x00fa0fc8, 0x0faf018f, | ||
642 | 0x00e00fcf, 0x0fad01a4, 0x00c60fd6, 0x0fad01b7, | ||
643 | 0x00ae0fda, 0x0fae01ca, 0x00950fe1, 0x0fae01dc, | ||
644 | 0x00800fe6, 0x0fb101e9, 0x00680fed, 0x0fb601f5, | ||
645 | 0x00540ff1, 0x0fbe01fd, 0x00420ff6, 0x0fc50203, | ||
646 | 0x00300ffa, 0x0fce0208, 0x00210ffc, 0x0fd9020a, | ||
647 | 0x00130000, 0x0fe40209, 0x00080000, 0x0ff20206, | ||
648 | 0x02000000, 0x00000000, 0x02040ff2, 0x0000000a, | ||
649 | 0x02040fe4, 0x00000018, 0x02010fda, 0x0ffc0029, | ||
650 | 0x01fc0fcf, 0x0ffa003b, 0x01f30fc7, 0x0ff60050, | ||
651 | 0x01e90fc0, 0x0ff20065, 0x01dc0fba, 0x0fee007c, | ||
652 | 0x01cc0fb6, 0x0fe80096, 0x01ba0fb4, 0x0fe400ae, | ||
653 | 0x01a70fb4, 0x0fdd00c8, 0x018f0fb5, 0x0fda00e2, | ||
654 | 0x017a0fb5, 0x0fd400fd, 0x01630fb8, 0x0fce0117, | ||
655 | 0x014c0fba, 0x0fca0130, 0x01320fbf, 0x0fc70148, | ||
656 | 0x011b0fc1, 0x0fc10163, 0x01010fc8, 0x0fc00177, | ||
657 | 0x00e90fcd, 0x0fbd018d, 0x00d10fd1, 0x0fbc01a2, | ||
658 | 0x00ba0fd7, 0x0fbb01b4, 0x00a30fdd, 0x0fbc01c4, | ||
659 | 0x008e0fe1, 0x0fbd01d4, 0x00790fe7, 0x0fbe01e2, | ||
660 | 0x00670feb, 0x0fc001ee, 0x00540ff1, 0x0fc501f6, | ||
661 | 0x00430ff4, 0x0fcb01fe, 0x00340ff8, 0x0fd10203, | ||
662 | 0x00260ffb, 0x0fd80207, 0x001a0ffd, 0x0fe10208, | ||
663 | 0x000f0000, 0x0fea0207, 0x00060000, 0x0ff50205, | ||
664 | 0x02000000, 0x00000000, 0x02020ff2, 0x0000000c, | ||
665 | 0x02000fe4, 0x0000001c, 0x01fa0fda, 0x0ffc0030, | ||
666 | 0x01f10fd0, 0x0ffa0045, 0x01e50fc8, 0x0ff6005d, | ||
667 | 0x01d60fc3, 0x0ff30074, 0x01c60fbd, 0x0fef008e, | ||
668 | 0x01b30fba, 0x0fe900aa, 0x019e0fb9, 0x0fe500c4, | ||
669 | 0x01870fba, 0x0fe000df, 0x016f0fbb, 0x0fdd00f9, | ||
670 | 0x01580fbc, 0x0fd80114, 0x01400fbf, 0x0fd3012e, | ||
671 | 0x01280fc2, 0x0fd00146, 0x010f0fc6, 0x0fce015d, | ||
672 | 0x00f90fc9, 0x0fc90175, 0x00e00fcf, 0x0fc90188, | ||
673 | 0x00ca0fd4, 0x0fc6019c, 0x00b40fd8, 0x0fc601ae, | ||
674 | 0x009f0fdd, 0x0fc501bf, 0x008b0fe3, 0x0fc601cc, | ||
675 | 0x00780fe6, 0x0fc701db, 0x00660feb, 0x0fc801e7, | ||
676 | 0x00560fef, 0x0fcb01f0, 0x00460ff3, 0x0fcf01f8, | ||
677 | 0x00380ff6, 0x0fd401fe, 0x002c0ff9, 0x0fd90202, | ||
678 | 0x00200ffc, 0x0fdf0205, 0x00160ffe, 0x0fe60206, | ||
679 | 0x000c0000, 0x0fed0207, 0x00050000, 0x0ff70204, | ||
680 | 0x02000000, 0x00000000, 0x01fe0ff3, 0x0000000f, | ||
681 | 0x01f60fe5, 0x00000025, 0x01ea0fdb, 0x0ffd003e, | ||
682 | 0x01db0fd2, 0x0ffb0058, 0x01c80fcc, 0x0ff70075, | ||
683 | 0x01b50fc7, 0x0ff40090, 0x01a00fc3, 0x0ff000ad, | ||
684 | 0x01880fc1, 0x0feb00cc, 0x01700fc1, 0x0fe800e7, | ||
685 | 0x01550fc3, 0x0fe40104, 0x013b0fc5, 0x0fe2011e, | ||
686 | 0x01240fc6, 0x0fde0138, 0x010c0fca, 0x0fda0150, | ||
687 | 0x00f40fcd, 0x0fd90166, 0x00dd0fd1, 0x0fd7017b, | ||
688 | 0x00c80fd4, 0x0fd40190, 0x00b20fd9, 0x0fd401a1, | ||
689 | 0x009f0fdd, 0x0fd301b1, 0x008c0fe1, 0x0fd301c0, | ||
690 | 0x007b0fe5, 0x0fd301cd, 0x006a0fea, 0x0fd401d8, | ||
691 | 0x005c0fec, 0x0fd501e3, 0x004d0ff0, 0x0fd601ed, | ||
692 | 0x00410ff3, 0x0fd801f4, 0x00340ff7, 0x0fdb01fa, | ||
693 | 0x002a0ff9, 0x0fdf01fe, 0x00200ffb, 0x0fe30202, | ||
694 | 0x00180ffd, 0x0fe70204, 0x00100ffe, 0x0fed0205, | ||
695 | 0x00090000, 0x0ff20205, 0x00040000, 0x0ff90203, | ||
696 | 0x02000000, 0x00000000, 0x02050ff5, 0x00000006, | ||
697 | 0x02070fea, 0x0000000f, 0x02080fe1, 0x0ffd001a, | ||
698 | 0x02070fd8, 0x0ffb0026, 0x02030fd1, 0x0ff80034, | ||
699 | 0x01fe0fcb, 0x0ff40043, 0x01f60fc5, 0x0ff10054, | ||
700 | 0x01ee0fc0, 0x0feb0067, 0x01e20fbe, 0x0fe70079, | ||
701 | 0x01d40fbd, 0x0fe1008e, 0x01c40fbc, 0x0fdd00a3, | ||
702 | 0x01b40fbb, 0x0fd700ba, 0x01a20fbc, 0x0fd100d1, | ||
703 | 0x018d0fbd, 0x0fcd00e9, 0x01770fc0, 0x0fc80101, | ||
704 | 0x01630fc1, 0x0fc1011b, 0x01480fc7, 0x0fbf0132, | ||
705 | 0x01300fca, 0x0fba014c, 0x01170fce, 0x0fb80163, | ||
706 | 0x00fd0fd4, 0x0fb5017a, 0x00e20fda, 0x0fb5018f, | ||
707 | 0x00c80fdd, 0x0fb401a7, 0x00ae0fe4, 0x0fb401ba, | ||
708 | 0x00960fe8, 0x0fb601cc, 0x007c0fee, 0x0fba01dc, | ||
709 | 0x00650ff2, 0x0fc001e9, 0x00500ff6, 0x0fc701f3, | ||
710 | 0x003b0ffa, 0x0fcf01fc, 0x00290ffc, 0x0fda0201, | ||
711 | 0x00180000, 0x0fe40204, 0x000a0000, 0x0ff20204, | ||
712 | 0x02000000, 0x00000000, 0x02030ff5, 0x00000008, | ||
713 | 0x02030fea, 0x00000013, 0x02020fe1, 0x0ffd0020, | ||
714 | 0x01fc0fd9, 0x0ffc002f, 0x01f60fd2, 0x0ff80040, | ||
715 | 0x01ed0fcd, 0x0ff50051, 0x01e30fc7, 0x0ff10065, | ||
716 | 0x01d70fc3, 0x0fec007a, 0x01c60fc2, 0x0fe9008f, | ||
717 | 0x01b60fc1, 0x0fe300a6, 0x01a20fc1, 0x0fe000bd, | ||
718 | 0x018f0fc1, 0x0fdb00d5, 0x017b0fc2, 0x0fd500ee, | ||
719 | 0x01640fc4, 0x0fd20106, 0x014d0fc8, 0x0fce011d, | ||
720 | 0x01370fc9, 0x0fc90137, 0x011d0fce, 0x0fc8014d, | ||
721 | 0x01060fd2, 0x0fc40164, 0x00ee0fd5, 0x0fc2017b, | ||
722 | 0x00d50fdb, 0x0fc1018f, 0x00bd0fe0, 0x0fc101a2, | ||
723 | 0x00a60fe3, 0x0fc101b6, 0x008f0fe9, 0x0fc201c6, | ||
724 | 0x007a0fec, 0x0fc301d7, 0x00650ff1, 0x0fc701e3, | ||
725 | 0x00510ff5, 0x0fcd01ed, 0x00400ff8, 0x0fd201f6, | ||
726 | 0x002f0ffc, 0x0fd901fc, 0x00200ffd, 0x0fe10202, | ||
727 | 0x00130000, 0x0fea0203, 0x00080000, 0x0ff50203, | ||
728 | 0x02000000, 0x00000000, 0x02020ff5, 0x00000009, | ||
729 | 0x01ff0fea, 0x00000017, 0x01fb0fe2, 0x0ffd0026, | ||
730 | 0x01f30fda, 0x0ffc0037, 0x01ea0fd3, 0x0ff8004b, | ||
731 | 0x01df0fce, 0x0ff5005e, 0x01d10fc9, 0x0ff20074, | ||
732 | 0x01c10fc6, 0x0fed008c, 0x01ae0fc5, 0x0fea00a3, | ||
733 | 0x019b0fc5, 0x0fe500bb, 0x01850fc6, 0x0fe200d3, | ||
734 | 0x01700fc6, 0x0fde00ec, 0x015a0fc8, 0x0fd90105, | ||
735 | 0x01430fca, 0x0fd6011d, 0x012b0fcd, 0x0fd30135, | ||
736 | 0x01150fcf, 0x0fcf014d, 0x00fc0fd4, 0x0fce0162, | ||
737 | 0x00e50fd8, 0x0fcc0177, 0x00cf0fdb, 0x0fca018c, | ||
738 | 0x00b80fe0, 0x0fc9019f, 0x00a20fe5, 0x0fca01af, | ||
739 | 0x008e0fe8, 0x0fcb01bf, 0x00790fec, 0x0fcb01d0, | ||
740 | 0x00670fef, 0x0fcd01dd, 0x00550ff4, 0x0fd001e7, | ||
741 | 0x00440ff7, 0x0fd501f0, 0x00350ffa, 0x0fda01f7, | ||
742 | 0x00270ffc, 0x0fdf01fe, 0x001b0ffe, 0x0fe70200, | ||
743 | 0x00100000, 0x0fee0202, 0x00060000, 0x0ff70203, | ||
744 | 0x02000000, 0x00000000, 0x01ff0ff5, 0x0000000c, | ||
745 | 0x01f80fea, 0x0000001e, 0x01ef0fe2, 0x0ffd0032, | ||
746 | 0x01e20fdb, 0x0ffc0047, 0x01d30fd5, 0x0ff9005f, | ||
747 | 0x01c20fd1, 0x0ff60077, 0x01b00fcd, 0x0ff30090, | ||
748 | 0x019b0fcb, 0x0fef00ab, 0x01850fcb, 0x0fec00c4, | ||
749 | 0x016e0fcc, 0x0fe800de, 0x01550fcd, 0x0fe600f8, | ||
750 | 0x013f0fce, 0x0fe20111, 0x01280fd0, 0x0fdf0129, | ||
751 | 0x01110fd2, 0x0fdd0140, 0x00f90fd6, 0x0fdb0156, | ||
752 | 0x00e40fd8, 0x0fd8016c, 0x00cd0fdd, 0x0fd8017e, | ||
753 | 0x00b80fe0, 0x0fd60192, 0x00a40fe3, 0x0fd601a3, | ||
754 | 0x00910fe7, 0x0fd501b3, 0x007f0feb, 0x0fd601c0, | ||
755 | 0x006e0fed, 0x0fd701ce, 0x005d0ff1, 0x0fd701db, | ||
756 | 0x004f0ff3, 0x0fd901e5, 0x00400ff7, 0x0fdc01ed, | ||
757 | 0x00330ff9, 0x0fe001f4, 0x00280ffb, 0x0fe301fa, | ||
758 | 0x001d0ffd, 0x0fe801fe, 0x00140ffe, 0x0fed0201, | ||
759 | 0x000c0000, 0x0ff20202, 0x00050000, 0x0ff90202, | ||
760 | 0x02000000, 0x00000000, 0x02040ff7, 0x00000005, | ||
761 | 0x02070fed, 0x0000000c, 0x02060fe6, 0x0ffe0016, | ||
762 | 0x02050fdf, 0x0ffc0020, 0x02020fd9, 0x0ff9002c, | ||
763 | 0x01fe0fd4, 0x0ff60038, 0x01f80fcf, 0x0ff30046, | ||
764 | 0x01f00fcb, 0x0fef0056, 0x01e70fc8, 0x0feb0066, | ||
765 | 0x01db0fc7, 0x0fe60078, 0x01cc0fc6, 0x0fe3008b, | ||
766 | 0x01bf0fc5, 0x0fdd009f, 0x01ae0fc6, 0x0fd800b4, | ||
767 | 0x019c0fc6, 0x0fd400ca, 0x01880fc9, 0x0fcf00e0, | ||
768 | 0x01750fc9, 0x0fc900f9, 0x015d0fce, 0x0fc6010f, | ||
769 | 0x01460fd0, 0x0fc20128, 0x012e0fd3, 0x0fbf0140, | ||
770 | 0x01140fd8, 0x0fbc0158, 0x00f90fdd, 0x0fbb016f, | ||
771 | 0x00df0fe0, 0x0fba0187, 0x00c40fe5, 0x0fb9019e, | ||
772 | 0x00aa0fe9, 0x0fba01b3, 0x008e0fef, 0x0fbd01c6, | ||
773 | 0x00740ff3, 0x0fc301d6, 0x005d0ff6, 0x0fc801e5, | ||
774 | 0x00450ffa, 0x0fd001f1, 0x00300ffc, 0x0fda01fa, | ||
775 | 0x001c0000, 0x0fe40200, 0x000c0000, 0x0ff20202, | ||
776 | 0x02000000, 0x00000000, 0x02030ff7, 0x00000006, | ||
777 | 0x02020fee, 0x00000010, 0x02000fe7, 0x0ffe001b, | ||
778 | 0x01fe0fdf, 0x0ffc0027, 0x01f70fda, 0x0ffa0035, | ||
779 | 0x01f00fd5, 0x0ff70044, 0x01e70fd0, 0x0ff40055, | ||
780 | 0x01dd0fcd, 0x0fef0067, 0x01d00fcb, 0x0fec0079, | ||
781 | 0x01bf0fcb, 0x0fe8008e, 0x01af0fca, 0x0fe500a2, | ||
782 | 0x019f0fc9, 0x0fe000b8, 0x018c0fca, 0x0fdb00cf, | ||
783 | 0x01770fcc, 0x0fd800e5, 0x01620fce, 0x0fd400fc, | ||
784 | 0x014d0fcf, 0x0fcf0115, 0x01350fd3, 0x0fcd012b, | ||
785 | 0x011d0fd6, 0x0fca0143, 0x01050fd9, 0x0fc8015a, | ||
786 | 0x00ec0fde, 0x0fc60170, 0x00d30fe2, 0x0fc60185, | ||
787 | 0x00bb0fe5, 0x0fc5019b, 0x00a30fea, 0x0fc501ae, | ||
788 | 0x008c0fed, 0x0fc601c1, 0x00740ff2, 0x0fc901d1, | ||
789 | 0x005e0ff5, 0x0fce01df, 0x004b0ff8, 0x0fd301ea, | ||
790 | 0x00370ffc, 0x0fda01f3, 0x00260ffd, 0x0fe201fb, | ||
791 | 0x00170000, 0x0fea01ff, 0x00090000, 0x0ff50202, | ||
792 | 0x02000000, 0x00000000, 0x02010ff7, 0x00000008, | ||
793 | 0x01ff0fee, 0x00000013, 0x01fb0fe7, 0x0ffe0020, | ||
794 | 0x01f60fe0, 0x0ffc002e, 0x01ed0fda, 0x0ffa003f, | ||
795 | 0x01e40fd6, 0x0ff7004f, 0x01d80fd2, 0x0ff40062, | ||
796 | 0x01ca0fcf, 0x0ff00077, 0x01bb0fcd, 0x0fed008b, | ||
797 | 0x01a90fcd, 0x0fe900a1, 0x01960fcd, 0x0fe600b7, | ||
798 | 0x01830fcd, 0x0fe200ce, 0x016d0fcf, 0x0fde00e6, | ||
799 | 0x01580fd0, 0x0fdb00fd, 0x01410fd3, 0x0fd80114, | ||
800 | 0x012c0fd4, 0x0fd4012c, 0x01140fd8, 0x0fd30141, | ||
801 | 0x00fd0fdb, 0x0fd00158, 0x00e60fde, 0x0fcf016d, | ||
802 | 0x00ce0fe2, 0x0fcd0183, 0x00b70fe6, 0x0fcd0196, | ||
803 | 0x00a10fe9, 0x0fcd01a9, 0x008b0fed, 0x0fcd01bb, | ||
804 | 0x00770ff0, 0x0fcf01ca, 0x00620ff4, 0x0fd201d8, | ||
805 | 0x004f0ff7, 0x0fd601e4, 0x003f0ffa, 0x0fda01ed, | ||
806 | 0x002e0ffc, 0x0fe001f6, 0x00200ffe, 0x0fe701fb, | ||
807 | 0x00130000, 0x0fee01ff, 0x00080000, 0x0ff70201, | ||
808 | 0x02000000, 0x00000000, 0x01ff0ff7, 0x0000000a, | ||
809 | 0x01f90fee, 0x00000019, 0x01f10fe7, 0x0ffe002a, | ||
810 | 0x01e60fe1, 0x0ffd003c, 0x01d90fdc, 0x0ffa0051, | ||
811 | 0x01cc0fd8, 0x0ff70065, 0x01bb0fd5, 0x0ff5007b, | ||
812 | 0x01a80fd3, 0x0ff10094, 0x01950fd2, 0x0fef00aa, | ||
813 | 0x01800fd2, 0x0feb00c3, 0x016a0fd3, 0x0fe900da, | ||
814 | 0x01540fd3, 0x0fe600f3, 0x013f0fd5, 0x0fe2010a, | ||
815 | 0x01280fd7, 0x0fe00121, 0x01100fda, 0x0fde0138, | ||
816 | 0x00fb0fdb, 0x0fdb014f, 0x00e40fdf, 0x0fdb0162, | ||
817 | 0x00ce0fe2, 0x0fd90177, 0x00b90fe4, 0x0fd8018b, | ||
818 | 0x00a50fe8, 0x0fd8019b, 0x00910fec, 0x0fd801ab, | ||
819 | 0x007e0fee, 0x0fd801bc, 0x006c0ff2, 0x0fd901c9, | ||
820 | 0x005c0ff4, 0x0fda01d6, 0x004b0ff7, 0x0fdd01e1, | ||
821 | 0x003c0ff9, 0x0fe001eb, 0x002f0ffb, 0x0fe401f2, | ||
822 | 0x00230ffd, 0x0fe801f8, 0x00180ffe, 0x0fed01fd, | ||
823 | 0x000e0000, 0x0ff20200, 0x00060000, 0x0ff90201, | ||
824 | 0x02000000, 0x00000000, 0x02030ff9, 0x00000004, | ||
825 | 0x02050ff2, 0x00000009, 0x02050fed, 0x0ffe0010, | ||
826 | 0x02040fe7, 0x0ffd0018, 0x02020fe3, 0x0ffb0020, | ||
827 | 0x01fe0fdf, 0x0ff9002a, 0x01fa0fdb, 0x0ff70034, | ||
828 | 0x01f40fd8, 0x0ff30041, 0x01ed0fd6, 0x0ff0004d, | ||
829 | 0x01e30fd5, 0x0fec005c, 0x01d80fd4, 0x0fea006a, | ||
830 | 0x01cd0fd3, 0x0fe5007b, 0x01c00fd3, 0x0fe1008c, | ||
831 | 0x01b10fd3, 0x0fdd009f, 0x01a10fd4, 0x0fd900b2, | ||
832 | 0x01900fd4, 0x0fd400c8, 0x017b0fd7, 0x0fd100dd, | ||
833 | 0x01660fd9, 0x0fcd00f4, 0x01500fda, 0x0fca010c, | ||
834 | 0x01380fde, 0x0fc60124, 0x011e0fe2, 0x0fc5013b, | ||
835 | 0x01040fe4, 0x0fc30155, 0x00e70fe8, 0x0fc10170, | ||
836 | 0x00cc0feb, 0x0fc10188, 0x00ad0ff0, 0x0fc301a0, | ||
837 | 0x00900ff4, 0x0fc701b5, 0x00750ff7, 0x0fcc01c8, | ||
838 | 0x00580ffb, 0x0fd201db, 0x003e0ffd, 0x0fdb01ea, | ||
839 | 0x00250000, 0x0fe501f6, 0x000f0000, 0x0ff301fe, | ||
840 | 0x02000000, 0x00000000, 0x02020ff9, 0x00000005, | ||
841 | 0x02020ff2, 0x0000000c, 0x02010fed, 0x0ffe0014, | ||
842 | 0x01fe0fe8, 0x0ffd001d, 0x01fa0fe3, 0x0ffb0028, | ||
843 | 0x01f40fe0, 0x0ff90033, 0x01ed0fdc, 0x0ff70040, | ||
844 | 0x01e50fd9, 0x0ff3004f, 0x01db0fd7, 0x0ff1005d, | ||
845 | 0x01ce0fd7, 0x0fed006e, 0x01c00fd6, 0x0feb007f, | ||
846 | 0x01b30fd5, 0x0fe70091, 0x01a30fd6, 0x0fe300a4, | ||
847 | 0x01920fd6, 0x0fe000b8, 0x017e0fd8, 0x0fdd00cd, | ||
848 | 0x016c0fd8, 0x0fd800e4, 0x01560fdb, 0x0fd600f9, | ||
849 | 0x01400fdd, 0x0fd20111, 0x01290fdf, 0x0fd00128, | ||
850 | 0x01110fe2, 0x0fce013f, 0x00f80fe6, 0x0fcd0155, | ||
851 | 0x00de0fe8, 0x0fcc016e, 0x00c40fec, 0x0fcb0185, | ||
852 | 0x00ab0fef, 0x0fcb019b, 0x00900ff3, 0x0fcd01b0, | ||
853 | 0x00770ff6, 0x0fd101c2, 0x005f0ff9, 0x0fd501d3, | ||
854 | 0x00470ffc, 0x0fdb01e2, 0x00320ffd, 0x0fe201ef, | ||
855 | 0x001e0000, 0x0fea01f8, 0x000c0000, 0x0ff501ff, | ||
856 | 0x02000000, 0x00000000, 0x02010ff9, 0x00000006, | ||
857 | 0x02000ff2, 0x0000000e, 0x01fd0fed, 0x0ffe0018, | ||
858 | 0x01f80fe8, 0x0ffd0023, 0x01f20fe4, 0x0ffb002f, | ||
859 | 0x01eb0fe0, 0x0ff9003c, 0x01e10fdd, 0x0ff7004b, | ||
860 | 0x01d60fda, 0x0ff4005c, 0x01c90fd9, 0x0ff2006c, | ||
861 | 0x01bc0fd8, 0x0fee007e, 0x01ab0fd8, 0x0fec0091, | ||
862 | 0x019b0fd8, 0x0fe800a5, 0x018b0fd8, 0x0fe400b9, | ||
863 | 0x01770fd9, 0x0fe200ce, 0x01620fdb, 0x0fdf00e4, | ||
864 | 0x014f0fdb, 0x0fdb00fb, 0x01380fde, 0x0fda0110, | ||
865 | 0x01210fe0, 0x0fd70128, 0x010a0fe2, 0x0fd5013f, | ||
866 | 0x00f30fe6, 0x0fd30154, 0x00da0fe9, 0x0fd3016a, | ||
867 | 0x00c30feb, 0x0fd20180, 0x00aa0fef, 0x0fd20195, | ||
868 | 0x00940ff1, 0x0fd301a8, 0x007b0ff5, 0x0fd501bb, | ||
869 | 0x00650ff7, 0x0fd801cc, 0x00510ffa, 0x0fdc01d9, | ||
870 | 0x003c0ffd, 0x0fe101e6, 0x002a0ffe, 0x0fe701f1, | ||
871 | 0x00190000, 0x0fee01f9, 0x000a0000, 0x0ff701ff, | ||
872 | 0x02000000, 0x00000000, 0x01ff0ff9, 0x00000008, | ||
873 | 0x01fb0ff2, 0x00000013, 0x01f50fed, 0x0ffe0020, | ||
874 | 0x01ed0fe8, 0x0ffd002e, 0x01e30fe4, 0x0ffb003e, | ||
875 | 0x01d80fe1, 0x0ff9004e, 0x01cb0fde, 0x0ff70060, | ||
876 | 0x01bc0fdc, 0x0ff40074, 0x01ac0fdb, 0x0ff20087, | ||
877 | 0x019a0fdb, 0x0fef009c, 0x01870fdb, 0x0fed00b1, | ||
878 | 0x01740fdb, 0x0fea00c7, 0x01600fdc, 0x0fe700dd, | ||
879 | 0x014b0fdd, 0x0fe500f3, 0x01350fdf, 0x0fe30109, | ||
880 | 0x01200fe0, 0x0fe00120, 0x01090fe3, 0x0fdf0135, | ||
881 | 0x00f30fe5, 0x0fdd014b, 0x00dd0fe7, 0x0fdc0160, | ||
882 | 0x00c70fea, 0x0fdb0174, 0x00b10fed, 0x0fdb0187, | ||
883 | 0x009c0fef, 0x0fdb019a, 0x00870ff2, 0x0fdb01ac, | ||
884 | 0x00740ff4, 0x0fdc01bc, 0x00600ff7, 0x0fde01cb, | ||
885 | 0x004e0ff9, 0x0fe101d8, 0x003e0ffb, 0x0fe401e3, | ||
886 | 0x002e0ffd, 0x0fe801ed, 0x00200ffe, 0x0fed01f5, | ||
887 | 0x00130000, 0x0ff201fb, 0x00080000, 0x0ff901ff | ||
888 | }; | ||
889 | |||
890 | |||
891 | #define MDP4_QSEED_TABLE0_OFF 0x8100 | ||
892 | #define MDP4_QSEED_TABLE1_OFF 0x8200 | ||
893 | #define MDP4_QSEED_TABLE2_OFF 0x9000 | ||
894 | |||
895 | void mdp4_vg_qseed_init(int vp_num) | ||
896 | { | ||
897 | uint32 *off; | ||
898 | int i, voff; | ||
899 | |||
900 | voff = MDP4_VIDEO_OFF * vp_num; | ||
901 | off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff + | ||
902 | MDP4_QSEED_TABLE0_OFF); | ||
903 | for (i = 0; i < (sizeof(vg_qseed_table0) / sizeof(uint32)); i++) { | ||
904 | outpdw(off, vg_qseed_table0[i]); | ||
905 | off++; | ||
906 | } | ||
907 | |||
908 | off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff + | ||
909 | MDP4_QSEED_TABLE1_OFF); | ||
910 | for (i = 0; i < (sizeof(vg_qseed_table1) / sizeof(uint32)); i++) { | ||
911 | outpdw(off, vg_qseed_table1[i]); | ||
912 | off++; | ||
913 | } | ||
914 | |||
915 | off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff + | ||
916 | MDP4_QSEED_TABLE2_OFF); | ||
917 | for (i = 0; i < (sizeof(vg_qseed_table2) / sizeof(uint32)); i++) { | ||
918 | outpdw(off, vg_qseed_table2[i]); | ||
919 | off++; | ||
920 | } | ||
921 | |||
922 | } | ||
923 | |||
924 | void mdp4_mixer_blend_init(mixer_num) | ||
925 | { | ||
926 | unsigned char *overlay_base; | ||
927 | int off; | ||
928 | |||
929 | if (mixer_num) /* mixer number, /dev/fb0, /dev/fb1 */ | ||
930 | overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */ | ||
931 | else | ||
932 | overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */ | ||
933 | |||
934 | /* stage 0 to stage 2 */ | ||
935 | off = 0; | ||
936 | outpdw(overlay_base + off + 0x104, 0x010); | ||
937 | outpdw(overlay_base + off + 0x108, 0xff);/* FG */ | ||
938 | outpdw(overlay_base + off + 0x10c, 0x00);/* BG */ | ||
939 | |||
940 | off += 0x20; | ||
941 | outpdw(overlay_base + off + 0x104, 0x010); | ||
942 | outpdw(overlay_base + off + 0x108, 0xff);/* FG */ | ||
943 | outpdw(overlay_base + off + 0x10c, 0x00);/* BG */ | ||
944 | |||
945 | off += 0x20; | ||
946 | outpdw(overlay_base + off + 0x104, 0x010); | ||
947 | outpdw(overlay_base + off + 0x108, 0xff);/* FG */ | ||
948 | outpdw(overlay_base + off + 0x10c, 0x00);/* BG */ | ||
949 | } | ||
950 | |||
951 | |||
952 | static uint32 csc_matrix_tab[9] = { | ||
953 | 0x0254, 0x0000, 0x0331, | ||
954 | 0x0254, 0xff37, 0xfe60, | ||
955 | 0x0254, 0x0409, 0x0000 | ||
956 | }; | ||
957 | |||
958 | static uint32 csc_pre_bv_tab[3] = {0xfff0, 0xff80, 0xff80 }; | ||
959 | static uint32 csc_post_bv_tab[3] = {0, 0, 0 }; | ||
960 | |||
961 | static uint32 csc_pre_lv_tab[6] = {0, 0xff, 0, 0xff, 0, 0xff }; | ||
962 | static uint32 csc_post_lv_tab[6] = {0, 0xff, 0, 0xff, 0, 0xff }; | ||
963 | |||
964 | #define MDP4_CSC_MV_OFF 0x4400 | ||
965 | #define MDP4_CSC_PRE_BV_OFF 0x4500 | ||
966 | #define MDP4_CSC_POST_BV_OFF 0x4580 | ||
967 | #define MDP4_CSC_PRE_LV_OFF 0x4600 | ||
968 | #define MDP4_CSC_POST_LV_OFF 0x4680 | ||
969 | |||
970 | void mdp4_vg_csc_mv_setup(int vp_num) | ||
971 | { | ||
972 | uint32 *off; | ||
973 | int i, voff; | ||
974 | |||
975 | voff = MDP4_VIDEO_OFF * vp_num; | ||
976 | off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff + | ||
977 | MDP4_CSC_MV_OFF); | ||
978 | for (i = 0; i < 9; i++) { | ||
979 | outpdw(off, csc_matrix_tab[i]); | ||
980 | off++; | ||
981 | } | ||
982 | } | ||
983 | |||
984 | void mdp4_vg_csc_pre_bv_setup(int vp_num) | ||
985 | { | ||
986 | uint32 *off; | ||
987 | int i, voff; | ||
988 | |||
989 | voff = MDP4_VIDEO_OFF * vp_num; | ||
990 | off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff + | ||
991 | MDP4_CSC_PRE_BV_OFF); | ||
992 | for (i = 0; i < 3; i++) { | ||
993 | outpdw(off, csc_pre_bv_tab[i]); | ||
994 | off++; | ||
995 | } | ||
996 | } | ||
997 | |||
998 | void mdp4_vg_csc_post_bv_setup(int vp_num) | ||
999 | { | ||
1000 | uint32 *off; | ||
1001 | int i, voff; | ||
1002 | |||
1003 | voff = MDP4_VIDEO_OFF * vp_num; | ||
1004 | off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff + | ||
1005 | MDP4_CSC_POST_BV_OFF); | ||
1006 | for (i = 0; i < 3; i++) { | ||
1007 | outpdw(off, csc_post_bv_tab[i]); | ||
1008 | off++; | ||
1009 | } | ||
1010 | } | ||
1011 | |||
1012 | void mdp4_vg_csc_pre_lv_setup(int vp_num) | ||
1013 | { | ||
1014 | uint32 *off; | ||
1015 | int i, voff; | ||
1016 | |||
1017 | voff = MDP4_VIDEO_OFF * vp_num; | ||
1018 | off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff + | ||
1019 | MDP4_CSC_PRE_LV_OFF); | ||
1020 | |||
1021 | for (i = 0; i < 6; i++) { | ||
1022 | outpdw(off, csc_pre_lv_tab[i]); | ||
1023 | off++; | ||
1024 | } | ||
1025 | } | ||
1026 | |||
1027 | void mdp4_vg_csc_post_lv_setup(int vp_num) | ||
1028 | { | ||
1029 | uint32 *off; | ||
1030 | int i, voff; | ||
1031 | |||
1032 | voff = MDP4_VIDEO_OFF * vp_num; | ||
1033 | off = (uint32 *)(MDP_BASE + MDP4_VIDEO_BASE + voff + | ||
1034 | MDP4_CSC_POST_LV_OFF); | ||
1035 | |||
1036 | for (i = 0; i < 6; i++) { | ||
1037 | outpdw(off, csc_post_lv_tab[i]); | ||
1038 | off++; | ||
1039 | } | ||
1040 | } | ||
1041 | |||
1042 | char gc_lut[] = { | ||
1043 | 0x0, 0x1, 0x2, 0x2, 0x3, 0x4, 0x5, 0x6, | ||
1044 | 0x6, 0x7, 0x8, 0x9, 0xA, 0xA, 0xB, 0xC, | ||
1045 | 0xD, 0xD, 0xE, 0xF, 0xF, 0x10, 0x10, 0x11, | ||
1046 | 0x12, 0x12, 0x13, 0x13, 0x14, 0x14, 0x15, 0x15, | ||
1047 | 0x16, 0x16, 0x17, 0x17, 0x17, 0x18, 0x18, 0x19, | ||
1048 | 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B, 0x1B, 0x1C, | ||
1049 | 0x1C, 0x1D, 0x1D, 0x1D, 0x1E, 0x1E, 0x1E, 0x1F, | ||
1050 | 0x1F, 0x1F, 0x20, 0x20, 0x20, 0x21, 0x21, 0x21, | ||
1051 | 0x22, 0x22, 0x22, 0x22, 0x23, 0x23, 0x23, 0x24, | ||
1052 | 0x24, 0x24, 0x25, 0x25, 0x25, 0x25, 0x26, 0x26, | ||
1053 | 0x26, 0x26, 0x27, 0x27, 0x27, 0x28, 0x28, 0x28, | ||
1054 | 0x28, 0x29, 0x29, 0x29, 0x29, 0x2A, 0x2A, 0x2A, | ||
1055 | 0x2A, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2C, 0x2C, | ||
1056 | 0x2C, 0x2C, 0x2D, 0x2D, 0x2D, 0x2D, 0x2E, 0x2E, | ||
1057 | 0x2E, 0x2E, 0x2E, 0x2F, 0x2F, 0x2F, 0x2F, 0x30, | ||
1058 | 0x30, 0x30, 0x30, 0x30, 0x31, 0x31, 0x31, 0x31, | ||
1059 | 0x31, 0x32, 0x32, 0x32, 0x32, 0x32, 0x33, 0x33, | ||
1060 | 0x33, 0x33, 0x33, 0x34, 0x34, 0x34, 0x34, 0x34, | ||
1061 | 0x35, 0x35, 0x35, 0x35, 0x35, 0x36, 0x36, 0x36, | ||
1062 | 0x36, 0x36, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, | ||
1063 | 0x38, 0x38, 0x38, 0x38, 0x38, 0x39, 0x39, 0x39, | ||
1064 | 0x39, 0x39, 0x39, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A, | ||
1065 | 0x3A, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3C, | ||
1066 | 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3D, 0x3D, 0x3D, | ||
1067 | 0x3D, 0x3D, 0x3D, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, | ||
1068 | 0x3E, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x40, | ||
1069 | 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x41, 0x41, | ||
1070 | 0x41, 0x41, 0x41, 0x41, 0x42, 0x42, 0x42, 0x42, | ||
1071 | 0x42, 0x42, 0x42, 0x43, 0x43, 0x43, 0x43, 0x43, | ||
1072 | 0x43, 0x43, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, | ||
1073 | 0x44, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, | ||
1074 | 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x47, | ||
1075 | 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x48, 0x48, | ||
1076 | 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x49, 0x49, | ||
1077 | 0x49, 0x49, 0x49, 0x49, 0x49, 0x4A, 0x4A, 0x4A, | ||
1078 | 0x4A, 0x4A, 0x4A, 0x4A, 0x4A, 0x4B, 0x4B, 0x4B, | ||
1079 | 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4C, 0x4C, 0x4C, | ||
1080 | 0x4C, 0x4C, 0x4C, 0x4C, 0x4D, 0x4D, 0x4D, 0x4D, | ||
1081 | 0x4D, 0x4D, 0x4D, 0x4D, 0x4E, 0x4E, 0x4E, 0x4E, | ||
1082 | 0x4E, 0x4E, 0x4E, 0x4E, 0x4E, 0x4F, 0x4F, 0x4F, | ||
1083 | 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x50, 0x50, 0x50, | ||
1084 | 0x50, 0x50, 0x50, 0x50, 0x50, 0x51, 0x51, 0x51, | ||
1085 | 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x52, 0x52, | ||
1086 | 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x53, 0x53, | ||
1087 | 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x54, | ||
1088 | 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, | ||
1089 | 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, | ||
1090 | 0x55, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, | ||
1091 | 0x56, 0x56, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, | ||
1092 | 0x57, 0x57, 0x57, 0x58, 0x58, 0x58, 0x58, 0x58, | ||
1093 | 0x58, 0x58, 0x58, 0x58, 0x58, 0x59, 0x59, 0x59, | ||
1094 | 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x5A, 0x5A, | ||
1095 | 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, | ||
1096 | 0x5B, 0x5B, 0x5B, 0x5B, 0x5B, 0x5B, 0x5B, 0x5B, | ||
1097 | 0x5B, 0x5B, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, | ||
1098 | 0x5C, 0x5C, 0x5C, 0x5C, 0x5D, 0x5D, 0x5D, 0x5D, | ||
1099 | 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5E, 0x5E, | ||
1100 | 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, | ||
1101 | 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, 0x5F, | ||
1102 | 0x5F, 0x5F, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, | ||
1103 | 0x60, 0x60, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61, | ||
1104 | 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x62, | ||
1105 | 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, | ||
1106 | 0x62, 0x62, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, | ||
1107 | 0x63, 0x63, 0x63, 0x63, 0x63, 0x64, 0x64, 0x64, | ||
1108 | 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, | ||
1109 | 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, | ||
1110 | 0x65, 0x65, 0x65, 0x66, 0x66, 0x66, 0x66, 0x66, | ||
1111 | 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x67, 0x67, | ||
1112 | 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, | ||
1113 | 0x67, 0x67, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, | ||
1114 | 0x68, 0x68, 0x68, 0x68, 0x68, 0x69, 0x69, 0x69, | ||
1115 | 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, | ||
1116 | 0x69, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, | ||
1117 | 0x6A, 0x6A, 0x6A, 0x6A, 0x6A, 0x6B, 0x6B, 0x6B, | ||
1118 | 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, 0x6B, | ||
1119 | 0x6B, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, | ||
1120 | 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6D, 0x6D, 0x6D, | ||
1121 | 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, | ||
1122 | 0x6D, 0x6E, 0x6E, 0x6E, 0x6E, 0x6E, 0x6E, 0x6E, | ||
1123 | 0x6E, 0x6E, 0x6E, 0x6E, 0x6E, 0x6F, 0x6F, 0x6F, | ||
1124 | 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, | ||
1125 | 0x6F, 0x6F, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, | ||
1126 | 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x71, 0x71, | ||
1127 | 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, | ||
1128 | 0x71, 0x71, 0x71, 0x72, 0x72, 0x72, 0x72, 0x72, | ||
1129 | 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, | ||
1130 | 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, | ||
1131 | 0x73, 0x73, 0x73, 0x73, 0x73, 0x74, 0x74, 0x74, | ||
1132 | 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, | ||
1133 | 0x74, 0x74, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, | ||
1134 | 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, | ||
1135 | 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, | ||
1136 | 0x76, 0x76, 0x76, 0x76, 0x76, 0x77, 0x77, 0x77, | ||
1137 | 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, | ||
1138 | 0x77, 0x77, 0x77, 0x78, 0x78, 0x78, 0x78, 0x78, | ||
1139 | 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, | ||
1140 | 0x78, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, | ||
1141 | 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x7A, 0x7A, | ||
1142 | 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, | ||
1143 | 0x7A, 0x7A, 0x7A, 0x7A, 0x7A, 0x7B, 0x7B, 0x7B, | ||
1144 | 0x7B, 0x7B, 0x7B, 0x7B, 0x7B, 0x7B, 0x7B, 0x7B, | ||
1145 | 0x7B, 0x7B, 0x7B, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, | ||
1146 | 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, | ||
1147 | 0x7C, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, | ||
1148 | 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, 0x7D, | ||
1149 | 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, | ||
1150 | 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7F, 0x7F, | ||
1151 | 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, | ||
1152 | 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x80, 0x80, 0x80, | ||
1153 | 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, | ||
1154 | 0x80, 0x80, 0x80, 0x80, 0x81, 0x81, 0x81, 0x81, | ||
1155 | 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, | ||
1156 | 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82, 0x82, | ||
1157 | 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, | ||
1158 | 0x82, 0x82, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, | ||
1159 | 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, | ||
1160 | 0x83, 0x83, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, | ||
1161 | 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, | ||
1162 | 0x84, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, | ||
1163 | 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, | ||
1164 | 0x85, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, | ||
1165 | 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, | ||
1166 | 0x86, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, | ||
1167 | 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, | ||
1168 | 0x87, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, | ||
1169 | 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, | ||
1170 | 0x88, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, | ||
1171 | 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, | ||
1172 | 0x89, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, | ||
1173 | 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, | ||
1174 | 0x8A, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, | ||
1175 | 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, | ||
1176 | 0x8B, 0x8B, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, | ||
1177 | 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, | ||
1178 | 0x8C, 0x8C, 0x8C, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, | ||
1179 | 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, | ||
1180 | 0x8D, 0x8D, 0x8D, 0x8D, 0x8E, 0x8E, 0x8E, 0x8E, | ||
1181 | 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, | ||
1182 | 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8F, 0x8F, 0x8F, | ||
1183 | 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, | ||
1184 | 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x90, 0x90, | ||
1185 | 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, | ||
1186 | 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x91, | ||
1187 | 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, | ||
1188 | 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, | ||
1189 | 0x91, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, | ||
1190 | 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, | ||
1191 | 0x92, 0x92, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, | ||
1192 | 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, | ||
1193 | 0x93, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x94, | ||
1194 | 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, | ||
1195 | 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x95, 0x95, | ||
1196 | 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, | ||
1197 | 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, | ||
1198 | 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, | ||
1199 | 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, | ||
1200 | 0x96, 0x96, 0x96, 0x97, 0x97, 0x97, 0x97, 0x97, | ||
1201 | 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, | ||
1202 | 0x97, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98, | ||
1203 | 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, | ||
1204 | 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, | ||
1205 | 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, | ||
1206 | 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, | ||
1207 | 0x99, 0x99, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, | ||
1208 | 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, | ||
1209 | 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9B, 0x9B, 0x9B, | ||
1210 | 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, | ||
1211 | 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, | ||
1212 | 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, | ||
1213 | 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, | ||
1214 | 0x9C, 0x9C, 0x9C, 0x9C, 0x9D, 0x9D, 0x9D, 0x9D, | ||
1215 | 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, | ||
1216 | 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9E, | ||
1217 | 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, | ||
1218 | 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, | ||
1219 | 0x9E, 0x9E, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, | ||
1220 | 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, | ||
1221 | 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0xA0, 0xA0, | ||
1222 | 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, | ||
1223 | 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, | ||
1224 | 0xA0, 0xA0, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, | ||
1225 | 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, | ||
1226 | 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA2, 0xA2, | ||
1227 | 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, | ||
1228 | 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, | ||
1229 | 0xA2, 0xA2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, | ||
1230 | 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, | ||
1231 | 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA4, 0xA4, | ||
1232 | 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, | ||
1233 | 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, | ||
1234 | 0xA4, 0xA4, 0xA4, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, | ||
1235 | 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, | ||
1236 | 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, | ||
1237 | 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, | ||
1238 | 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, | ||
1239 | 0xA6, 0xA6, 0xA6, 0xA6, 0xA7, 0xA7, 0xA7, 0xA7, | ||
1240 | 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, | ||
1241 | 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, | ||
1242 | 0xA7, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, | ||
1243 | 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, | ||
1244 | 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA9, | ||
1245 | 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, | ||
1246 | 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, | ||
1247 | 0xA9, 0xA9, 0xA9, 0xA9, 0xAA, 0xAA, 0xAA, 0xAA, | ||
1248 | 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, | ||
1249 | 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, | ||
1250 | 0xAA, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, | ||
1251 | 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, | ||
1252 | 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAC, | ||
1253 | 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, | ||
1254 | 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, | ||
1255 | 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAD, 0xAD, 0xAD, | ||
1256 | 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, | ||
1257 | 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, | ||
1258 | 0xAD, 0xAD, 0xAD, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, | ||
1259 | 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, | ||
1260 | 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, | ||
1261 | 0xAE, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, | ||
1262 | 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, | ||
1263 | 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xB0, | ||
1264 | 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, | ||
1265 | 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, | ||
1266 | 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB1, 0xB1, | ||
1267 | 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, | ||
1268 | 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, | ||
1269 | 0xB1, 0xB1, 0xB1, 0xB1, 0xB2, 0xB2, 0xB2, 0xB2, | ||
1270 | 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, | ||
1271 | 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, | ||
1272 | 0xB2, 0xB2, 0xB2, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, | ||
1273 | 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, | ||
1274 | 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, | ||
1275 | 0xB3, 0xB3, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, | ||
1276 | 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, | ||
1277 | 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, | ||
1278 | 0xB4, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, | ||
1279 | 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, | ||
1280 | 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, | ||
1281 | 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, | ||
1282 | 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, | ||
1283 | 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, | ||
1284 | 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, | ||
1285 | 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, | ||
1286 | 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB8, | ||
1287 | 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, | ||
1288 | 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, | ||
1289 | 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB9, | ||
1290 | 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, | ||
1291 | 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, | ||
1292 | 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xBA, | ||
1293 | 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, | ||
1294 | 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, | ||
1295 | 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBB, | ||
1296 | 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, | ||
1297 | 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, | ||
1298 | 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, | ||
1299 | 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, | ||
1300 | 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, | ||
1301 | 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, | ||
1302 | 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, | ||
1303 | 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, | ||
1304 | 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, | ||
1305 | 0xBD, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, | ||
1306 | 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, | ||
1307 | 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, | ||
1308 | 0xBE, 0xBE, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, | ||
1309 | 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, | ||
1310 | 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, | ||
1311 | 0xBF, 0xBF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, | ||
1312 | 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, | ||
1313 | 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, | ||
1314 | 0xC0, 0xC0, 0xC0, 0xC0, 0xC1, 0xC1, 0xC1, 0xC1, | ||
1315 | 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, | ||
1316 | 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, | ||
1317 | 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC2, 0xC2, 0xC2, | ||
1318 | 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, | ||
1319 | 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, | ||
1320 | 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC3, 0xC3, | ||
1321 | 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, | ||
1322 | 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, | ||
1323 | 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, | ||
1324 | 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, | ||
1325 | 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, | ||
1326 | 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, | ||
1327 | 0xC4, 0xC4, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, | ||
1328 | 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, | ||
1329 | 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, | ||
1330 | 0xC5, 0xC5, 0xC5, 0xC5, 0xC6, 0xC6, 0xC6, 0xC6, | ||
1331 | 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, | ||
1332 | 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, | ||
1333 | 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC7, 0xC7, | ||
1334 | 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, | ||
1335 | 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, | ||
1336 | 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, | ||
1337 | 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, | ||
1338 | 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, | ||
1339 | 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, | ||
1340 | 0xC8, 0xC8, 0xC8, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, | ||
1341 | 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, | ||
1342 | 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, | ||
1343 | 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xCA, 0xCA, | ||
1344 | 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, | ||
1345 | 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, | ||
1346 | 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, | ||
1347 | 0xCA, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, | ||
1348 | 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, | ||
1349 | 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, | ||
1350 | 0xCB, 0xCB, 0xCB, 0xCB, 0xCC, 0xCC, 0xCC, 0xCC, | ||
1351 | 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, | ||
1352 | 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, | ||
1353 | 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCD, | ||
1354 | 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, | ||
1355 | 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, | ||
1356 | 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, | ||
1357 | 0xCD, 0xCD, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, | ||
1358 | 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, | ||
1359 | 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, | ||
1360 | 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCF, 0xCF, | ||
1361 | 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, | ||
1362 | 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, | ||
1363 | 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, | ||
1364 | 0xCF, 0xCF, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, | ||
1365 | 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, | ||
1366 | 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, | ||
1367 | 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD1, 0xD1, 0xD1, | ||
1368 | 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, | ||
1369 | 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, | ||
1370 | 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, | ||
1371 | 0xD1, 0xD1, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, | ||
1372 | 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, | ||
1373 | 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, | ||
1374 | 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD3, 0xD3, | ||
1375 | 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, | ||
1376 | 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, | ||
1377 | 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, | ||
1378 | 0xD3, 0xD3, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, | ||
1379 | 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, | ||
1380 | 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, | ||
1381 | 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD5, | ||
1382 | 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, | ||
1383 | 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, | ||
1384 | 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, | ||
1385 | 0xD5, 0xD5, 0xD5, 0xD5, 0xD6, 0xD6, 0xD6, 0xD6, | ||
1386 | 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, | ||
1387 | 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, | ||
1388 | 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, | ||
1389 | 0xD6, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, | ||
1390 | 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, | ||
1391 | 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, | ||
1392 | 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD8, 0xD8, | ||
1393 | 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, | ||
1394 | 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, | ||
1395 | 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, | ||
1396 | 0xD8, 0xD8, 0xD8, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, | ||
1397 | 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, | ||
1398 | 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, | ||
1399 | 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, | ||
1400 | 0xD9, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, | ||
1401 | 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, | ||
1402 | 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, | ||
1403 | 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDB, 0xDB, | ||
1404 | 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, | ||
1405 | 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, | ||
1406 | 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, | ||
1407 | 0xDB, 0xDB, 0xDB, 0xDB, 0xDC, 0xDC, 0xDC, 0xDC, | ||
1408 | 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, | ||
1409 | 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, | ||
1410 | 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, | ||
1411 | 0xDC, 0xDC, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, | ||
1412 | 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, | ||
1413 | 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, | ||
1414 | 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, | ||
1415 | 0xDD, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, | ||
1416 | 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, | ||
1417 | 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, | ||
1418 | 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDF, | ||
1419 | 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, | ||
1420 | 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, | ||
1421 | 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, | ||
1422 | 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xE0, 0xE0, | ||
1423 | 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, | ||
1424 | 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, | ||
1425 | 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, | ||
1426 | 0xE0, 0xE0, 0xE0, 0xE0, 0xE1, 0xE1, 0xE1, 0xE1, | ||
1427 | 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, | ||
1428 | 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, | ||
1429 | 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, 0xE1, | ||
1430 | 0xE1, 0xE1, 0xE1, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, | ||
1431 | 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, | ||
1432 | 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, | ||
1433 | 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, 0xE2, | ||
1434 | 0xE2, 0xE2, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, | ||
1435 | 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, | ||
1436 | 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, | ||
1437 | 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, | ||
1438 | 0xE3, 0xE3, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, | ||
1439 | 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, | ||
1440 | 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, | ||
1441 | 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, 0xE4, | ||
1442 | 0xE4, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, | ||
1443 | 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, | ||
1444 | 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, | ||
1445 | 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, | ||
1446 | 0xE5, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, | ||
1447 | 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, | ||
1448 | 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, | ||
1449 | 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, 0xE6, | ||
1450 | 0xE6, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, | ||
1451 | 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, | ||
1452 | 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, | ||
1453 | 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, | ||
1454 | 0xE7, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, | ||
1455 | 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, | ||
1456 | 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, | ||
1457 | 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, 0xE8, | ||
1458 | 0xE8, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, | ||
1459 | 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, | ||
1460 | 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, | ||
1461 | 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, 0xE9, | ||
1462 | 0xE9, 0xE9, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, | ||
1463 | 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, | ||
1464 | 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, | ||
1465 | 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, 0xEA, | ||
1466 | 0xEA, 0xEA, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, | ||
1467 | 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, | ||
1468 | 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, | ||
1469 | 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, | ||
1470 | 0xEB, 0xEB, 0xEB, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, | ||
1471 | 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, | ||
1472 | 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, | ||
1473 | 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, 0xEC, | ||
1474 | 0xEC, 0xEC, 0xEC, 0xEC, 0xED, 0xED, 0xED, 0xED, | ||
1475 | 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, | ||
1476 | 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, | ||
1477 | 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, | ||
1478 | 0xED, 0xED, 0xED, 0xED, 0xED, 0xEE, 0xEE, 0xEE, | ||
1479 | 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, | ||
1480 | 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, | ||
1481 | 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, | ||
1482 | 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEF, 0xEF, | ||
1483 | 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, | ||
1484 | 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, | ||
1485 | 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, | ||
1486 | 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, | ||
1487 | 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, | ||
1488 | 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, | ||
1489 | 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, | ||
1490 | 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, | ||
1491 | 0xF0, 0xF0, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, | ||
1492 | 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, | ||
1493 | 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, | ||
1494 | 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, | ||
1495 | 0xF1, 0xF1, 0xF1, 0xF1, 0xF2, 0xF2, 0xF2, 0xF2, | ||
1496 | 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, | ||
1497 | 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, | ||
1498 | 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, | ||
1499 | 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF3, 0xF3, | ||
1500 | 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, | ||
1501 | 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, | ||
1502 | 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, | ||
1503 | 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, | ||
1504 | 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, | ||
1505 | 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, | ||
1506 | 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, | ||
1507 | 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, | ||
1508 | 0xF4, 0xF4, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, | ||
1509 | 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, | ||
1510 | 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, | ||
1511 | 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, | ||
1512 | 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF6, 0xF6, 0xF6, | ||
1513 | 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, | ||
1514 | 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, | ||
1515 | 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, | ||
1516 | 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, 0xF6, | ||
1517 | 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, | ||
1518 | 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, | ||
1519 | 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, | ||
1520 | 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, | ||
1521 | 0xF7, 0xF7, 0xF7, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, | ||
1522 | 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, | ||
1523 | 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, | ||
1524 | 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, | ||
1525 | 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF9, 0xF9, | ||
1526 | 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, | ||
1527 | 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, | ||
1528 | 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, | ||
1529 | 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, | ||
1530 | 0xF9, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, | ||
1531 | 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, | ||
1532 | 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, | ||
1533 | 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, | ||
1534 | 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFB, 0xFB, 0xFB, | ||
1535 | 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, | ||
1536 | 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, | ||
1537 | 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, | ||
1538 | 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, | ||
1539 | 0xFB, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, | ||
1540 | 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, | ||
1541 | 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, | ||
1542 | 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, | ||
1543 | 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFD, 0xFD, 0xFD, | ||
1544 | 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, | ||
1545 | 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, | ||
1546 | 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, | ||
1547 | 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, 0xFD, | ||
1548 | 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, | ||
1549 | 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, | ||
1550 | 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, | ||
1551 | 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, | ||
1552 | 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, | ||
1553 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
1554 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
1555 | }; | ||
1556 | |||
1557 | void mdp4_mixer_gc_lut_setup(int mixer_num) | ||
1558 | { | ||
1559 | unsigned char *base; | ||
1560 | uint32 data; | ||
1561 | char val; | ||
1562 | int i, off; | ||
1563 | |||
1564 | if (mixer_num) /* mixer number, /dev/fb0, /dev/fb1 */ | ||
1565 | base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */ | ||
1566 | else | ||
1567 | base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */ | ||
1568 | |||
1569 | base += 0x4000; /* GC_LUT offset */ | ||
1570 | |||
1571 | off = 0; | ||
1572 | for (i = 0; i < 4096; i++) { | ||
1573 | val = gc_lut[i]; | ||
1574 | data = (val << 16 | val << 8 | val); /* R, B, and G are same */ | ||
1575 | outpdw(base + off, data); | ||
1576 | off += 4; | ||
1577 | } | ||
1578 | } | ||
1579 | |||
1580 | uint32 igc_video_lut[] = { /* non linear */ | ||
1581 | 0x0, 0x1, 0x2, 0x4, 0x5, 0x6, 0x7, 0x9, | ||
1582 | 0xA, 0xB, 0xC, 0xE, 0xF, 0x10, 0x12, 0x14, | ||
1583 | 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F, 0x21, 0x23, | ||
1584 | 0x25, 0x28, 0x2A, 0x2D, 0x30, 0x32, 0x35, 0x38, | ||
1585 | 0x3B, 0x3E, 0x42, 0x45, 0x48, 0x4C, 0x4F, 0x53, | ||
1586 | 0x57, 0x5B, 0x5F, 0x63, 0x67, 0x6B, 0x70, 0x74, | ||
1587 | 0x79, 0x7E, 0x83, 0x88, 0x8D, 0x92, 0x97, 0x9C, | ||
1588 | 0xA2, 0xA8, 0xAD, 0xB3, 0xB9, 0xBF, 0xC5, 0xCC, | ||
1589 | 0xD2, 0xD8, 0xDF, 0xE6, 0xED, 0xF4, 0xFB, 0x102, | ||
1590 | 0x109, 0x111, 0x118, 0x120, 0x128, 0x130, 0x138, 0x140, | ||
1591 | 0x149, 0x151, 0x15A, 0x162, 0x16B, 0x174, 0x17D, 0x186, | ||
1592 | 0x190, 0x199, 0x1A3, 0x1AC, 0x1B6, 0x1C0, 0x1CA, 0x1D5, | ||
1593 | 0x1DF, 0x1EA, 0x1F4, 0x1FF, 0x20A, 0x215, 0x220, 0x22B, | ||
1594 | 0x237, 0x242, 0x24E, 0x25A, 0x266, 0x272, 0x27F, 0x28B, | ||
1595 | 0x298, 0x2A4, 0x2B1, 0x2BE, 0x2CB, 0x2D8, 0x2E6, 0x2F3, | ||
1596 | 0x301, 0x30F, 0x31D, 0x32B, 0x339, 0x348, 0x356, 0x365, | ||
1597 | 0x374, 0x383, 0x392, 0x3A1, 0x3B1, 0x3C0, 0x3D0, 0x3E0, | ||
1598 | 0x3F0, 0x400, 0x411, 0x421, 0x432, 0x443, 0x454, 0x465, | ||
1599 | 0x476, 0x487, 0x499, 0x4AB, 0x4BD, 0x4CF, 0x4E1, 0x4F3, | ||
1600 | 0x506, 0x518, 0x52B, 0x53E, 0x551, 0x565, 0x578, 0x58C, | ||
1601 | 0x5A0, 0x5B3, 0x5C8, 0x5DC, 0x5F0, 0x605, 0x61A, 0x62E, | ||
1602 | 0x643, 0x659, 0x66E, 0x684, 0x699, 0x6AF, 0x6C5, 0x6DB, | ||
1603 | 0x6F2, 0x708, 0x71F, 0x736, 0x74D, 0x764, 0x77C, 0x793, | ||
1604 | 0x7AB, 0x7C3, 0x7DB, 0x7F3, 0x80B, 0x824, 0x83D, 0x855, | ||
1605 | 0x86F, 0x888, 0x8A1, 0x8BB, 0x8D4, 0x8EE, 0x908, 0x923, | ||
1606 | 0x93D, 0x958, 0x973, 0x98E, 0x9A9, 0x9C4, 0x9DF, 0x9FB, | ||
1607 | 0xA17, 0xA33, 0xA4F, 0xA6C, 0xA88, 0xAA5, 0xAC2, 0xADF, | ||
1608 | 0xAFC, 0xB19, 0xB37, 0xB55, 0xB73, 0xB91, 0xBAF, 0xBCE, | ||
1609 | 0xBEC, 0xC0B, 0xC2A, 0xC4A, 0xC69, 0xC89, 0xCA8, 0xCC8, | ||
1610 | 0xCE8, 0xD09, 0xD29, 0xD4A, 0xD6B, 0xD8C, 0xDAD, 0xDCF, | ||
1611 | 0xDF0, 0xE12, 0xE34, 0xE56, 0xE79, 0xE9B, 0xEBE, 0xEE1, | ||
1612 | 0xF04, 0xF27, 0xF4B, 0xF6E, 0xF92, 0xFB6, 0xFDB, 0xFFF, | ||
1613 | }; | ||
1614 | |||
1615 | void mdp4_vg_igc_lut_setup(int vp_num) | ||
1616 | { | ||
1617 | unsigned char *base; | ||
1618 | int i, voff, off; | ||
1619 | uint32 data, val; | ||
1620 | |||
1621 | voff = MDP4_VIDEO_OFF * vp_num; | ||
1622 | base = MDP_BASE + MDP4_VIDEO_BASE + voff + 0x5000; | ||
1623 | |||
1624 | off = 0; | ||
1625 | for (i = 0; i < 256; i++) { | ||
1626 | val = igc_video_lut[i]; | ||
1627 | data = (val << 16 | val); /* color 0 and 1 */ | ||
1628 | outpdw(base + off, data); | ||
1629 | outpdw(base + off + 0x800, val); /* color 2 */ | ||
1630 | off += 4; | ||
1631 | } | ||
1632 | } | ||
1633 | |||
1634 | uint32 igc_rgb_lut[] = { /* linear */ | ||
1635 | 0x0, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, | ||
1636 | 0x80, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1, | ||
1637 | 0x101, 0x111, 0x121, 0x131, 0x141, 0x151, 0x161, 0x171, | ||
1638 | 0x181, 0x191, 0x1A2, 0x1B2, 0x1C2, 0x1D2, 0x1E2, 0x1F2, | ||
1639 | 0x202, 0x212, 0x222, 0x232, 0x242, 0x252, 0x262, 0x272, | ||
1640 | 0x282, 0x292, 0x2A2, 0x2B3, 0x2C3, 0x2D3, 0x2E3, 0x2F3, | ||
1641 | 0x303, 0x313, 0x323, 0x333, 0x343, 0x353, 0x363, 0x373, | ||
1642 | 0x383, 0x393, 0x3A3, 0x3B3, 0x3C4, 0x3D4, 0x3E4, 0x3F4, | ||
1643 | 0x404, 0x414, 0x424, 0x434, 0x444, 0x454, 0x464, 0x474, | ||
1644 | 0x484, 0x494, 0x4A4, 0x4B4, 0x4C4, 0x4D5, 0x4E5, 0x4F5, | ||
1645 | 0x505, 0x515, 0x525, 0x535, 0x545, 0x555, 0x565, 0x575, | ||
1646 | 0x585, 0x595, 0x5A5, 0x5B5, 0x5C5, 0x5D5, 0x5E6, 0x5F6, | ||
1647 | 0x606, 0x616, 0x626, 0x636, 0x646, 0x656, 0x666, 0x676, | ||
1648 | 0x686, 0x696, 0x6A6, 0x6B6, 0x6C6, 0x6D6, 0x6E6, 0x6F7, | ||
1649 | 0x707, 0x717, 0x727, 0x737, 0x747, 0x757, 0x767, 0x777, | ||
1650 | 0x787, 0x797, 0x7A7, 0x7B7, 0x7C7, 0x7D7, 0x7E7, 0x7F7, | ||
1651 | 0x808, 0x818, 0x828, 0x838, 0x848, 0x858, 0x868, 0x878, | ||
1652 | 0x888, 0x898, 0x8A8, 0x8B8, 0x8C8, 0x8D8, 0x8E8, 0x8F8, | ||
1653 | 0x908, 0x919, 0x929, 0x939, 0x949, 0x959, 0x969, 0x979, | ||
1654 | 0x989, 0x999, 0x9A9, 0x9B9, 0x9C9, 0x9D9, 0x9E9, 0x9F9, | ||
1655 | 0xA09, 0xA19, 0xA2A, 0xA3A, 0xA4A, 0xA5A, 0xA6A, 0xA7A, | ||
1656 | 0xA8A, 0xA9A, 0xAAA, 0xABA, 0xACA, 0xADA, 0xAEA, 0xAFA, | ||
1657 | 0xB0A, 0xB1A, 0xB2A, 0xB3B, 0xB4B, 0xB5B, 0xB6B, 0xB7B, | ||
1658 | 0xB8B, 0xB9B, 0xBAB, 0xBBB, 0xBCB, 0xBDB, 0xBEB, 0xBFB, | ||
1659 | 0xC0B, 0xC1B, 0xC2B, 0xC3B, 0xC4C, 0xC5C, 0xC6C, 0xC7C, | ||
1660 | 0xC8C, 0xC9C, 0xCAC, 0xCBC, 0xCCC, 0xCDC, 0xCEC, 0xCFC, | ||
1661 | 0xD0C, 0xD1C, 0xD2C, 0xD3C, 0xD4C, 0xD5D, 0xD6D, 0xD7D, | ||
1662 | 0xD8D, 0xD9D, 0xDAD, 0xDBD, 0xDCD, 0xDDD, 0xDED, 0xDFD, | ||
1663 | 0xE0D, 0xE1D, 0xE2D, 0xE3D, 0xE4D, 0xE5D, 0xE6E, 0xE7E, | ||
1664 | 0xE8E, 0xE9E, 0xEAE, 0xEBE, 0xECE, 0xEDE, 0xEEE, 0xEFE, | ||
1665 | 0xF0E, 0xF1E, 0xF2E, 0xF3E, 0xF4E, 0xF5E, 0xF6E, 0xF7F, | ||
1666 | 0xF8F, 0xF9F, 0xFAF, 0xFBF, 0xFCF, 0xFDF, 0xFEF, 0xFFF, | ||
1667 | }; | ||
1668 | |||
1669 | void mdp4_rgb_igc_lut_setup(int num) | ||
1670 | { | ||
1671 | unsigned char *base; | ||
1672 | int i, voff, off; | ||
1673 | uint32 data, val; | ||
1674 | |||
1675 | voff = MDP4_RGB_OFF * num; | ||
1676 | base = MDP_BASE + MDP4_RGB_BASE + voff + 0x5000; | ||
1677 | |||
1678 | off = 0; | ||
1679 | for (i = 0; i < 256; i++) { | ||
1680 | val = igc_rgb_lut[i]; | ||
1681 | data = (val << 16 | val); /* color 0 and 1 */ | ||
1682 | outpdw(base + off, data); | ||
1683 | outpdw(base + off + 0x800, val); /* color 2 */ | ||
1684 | off += 4; | ||
1685 | } | ||
1686 | } | ||
diff --git a/drivers/staging/msm/mdp_cursor.c b/drivers/staging/msm/mdp_cursor.c new file mode 100644 index 000000000000..7d28f30d9313 --- /dev/null +++ b/drivers/staging/msm/mdp_cursor.c | |||
@@ -0,0 +1,104 @@ | |||
1 | /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/sched.h> | ||
21 | #include <linux/time.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/hrtimer.h> | ||
25 | |||
26 | #include <mach/hardware.h> | ||
27 | #include <asm/io.h> | ||
28 | |||
29 | #include <asm/system.h> | ||
30 | #include <asm/mach-types.h> | ||
31 | #include <linux/semaphore.h> | ||
32 | #include <linux/spinlock.h> | ||
33 | |||
34 | #include <linux/fb.h> | ||
35 | |||
36 | #include "mdp.h" | ||
37 | #include "msm_fb.h" | ||
38 | |||
39 | static int cursor_enabled; | ||
40 | |||
41 | int mdp_hw_cursor_update(struct fb_info *info, struct fb_cursor *cursor) | ||
42 | { | ||
43 | struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; | ||
44 | struct fb_image *img = &cursor->image; | ||
45 | int calpha_en, transp_en; | ||
46 | int alpha; | ||
47 | int ret = 0; | ||
48 | |||
49 | if ((img->width > MDP_CURSOR_WIDTH) || | ||
50 | (img->height > MDP_CURSOR_HEIGHT) || | ||
51 | (img->depth != 32)) | ||
52 | return -EINVAL; | ||
53 | |||
54 | if (cursor->set & FB_CUR_SETPOS) | ||
55 | MDP_OUTP(MDP_BASE + 0x9004c, (img->dy << 16) | img->dx); | ||
56 | |||
57 | if (cursor->set & FB_CUR_SETIMAGE) { | ||
58 | ret = copy_from_user(mfd->cursor_buf, img->data, | ||
59 | img->width*img->height*4); | ||
60 | if (ret) | ||
61 | return ret; | ||
62 | |||
63 | if (img->bg_color == 0xffffffff) | ||
64 | transp_en = 0; | ||
65 | else | ||
66 | transp_en = 1; | ||
67 | |||
68 | alpha = (img->fg_color & 0xff000000) >> 24; | ||
69 | |||
70 | if (alpha) | ||
71 | calpha_en = 0x2; /* xrgb */ | ||
72 | else | ||
73 | calpha_en = 0x1; /* argb */ | ||
74 | |||
75 | MDP_OUTP(MDP_BASE + 0x90044, (img->height << 16) | img->width); | ||
76 | MDP_OUTP(MDP_BASE + 0x90048, mfd->cursor_buf_phys); | ||
77 | /* order the writes the cursor_buf before updating the | ||
78 | * hardware */ | ||
79 | // dma_coherent_pre_ops(); | ||
80 | MDP_OUTP(MDP_BASE + 0x90060, | ||
81 | (transp_en << 3) | (calpha_en << 1) | | ||
82 | (inp32(MDP_BASE + 0x90060) & 0x1)); | ||
83 | #ifdef CONFIG_FB_MSM_MDP40 | ||
84 | MDP_OUTP(MDP_BASE + 0x90064, (alpha << 24)); | ||
85 | MDP_OUTP(MDP_BASE + 0x90068, (0xffffff & img->bg_color)); | ||
86 | MDP_OUTP(MDP_BASE + 0x9006C, (0xffffff & img->bg_color)); | ||
87 | #else | ||
88 | MDP_OUTP(MDP_BASE + 0x90064, | ||
89 | (alpha << 24) | (0xffffff & img->bg_color)); | ||
90 | MDP_OUTP(MDP_BASE + 0x90068, 0); | ||
91 | #endif | ||
92 | } | ||
93 | |||
94 | if ((cursor->enable) && (!cursor_enabled)) { | ||
95 | cursor_enabled = 1; | ||
96 | MDP_OUTP(MDP_BASE + 0x90060, inp32(MDP_BASE + 0x90060) | 0x1); | ||
97 | } else if ((!cursor->enable) && (cursor_enabled)) { | ||
98 | cursor_enabled = 0; | ||
99 | MDP_OUTP(MDP_BASE + 0x90060, | ||
100 | inp32(MDP_BASE + 0x90060) & (~0x1)); | ||
101 | } | ||
102 | |||
103 | return 0; | ||
104 | } | ||
diff --git a/drivers/staging/msm/mdp_dma.c b/drivers/staging/msm/mdp_dma.c new file mode 100644 index 000000000000..639918b143b4 --- /dev/null +++ b/drivers/staging/msm/mdp_dma.c | |||
@@ -0,0 +1,561 @@ | |||
1 | /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/sched.h> | ||
21 | #include <linux/time.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/hrtimer.h> | ||
25 | |||
26 | #include <mach/hardware.h> | ||
27 | #include <linux/io.h> | ||
28 | |||
29 | #include <asm/system.h> | ||
30 | #include <asm/mach-types.h> | ||
31 | #include <linux/semaphore.h> | ||
32 | #include <linux/spinlock.h> | ||
33 | |||
34 | #include <linux/fb.h> | ||
35 | |||
36 | #include "mdp.h" | ||
37 | #include "msm_fb.h" | ||
38 | #include "mddihost.h" | ||
39 | |||
40 | static uint32 mdp_last_dma2_update_width; | ||
41 | static uint32 mdp_last_dma2_update_height; | ||
42 | static uint32 mdp_curr_dma2_update_width; | ||
43 | static uint32 mdp_curr_dma2_update_height; | ||
44 | |||
45 | ktime_t mdp_dma2_last_update_time = { 0 }; | ||
46 | |||
47 | int mdp_lcd_rd_cnt_offset_slow = 20; | ||
48 | int mdp_lcd_rd_cnt_offset_fast = 20; | ||
49 | int mdp_vsync_usec_wait_line_too_short = 5; | ||
50 | uint32 mdp_dma2_update_time_in_usec; | ||
51 | uint32 mdp_total_vdopkts; | ||
52 | |||
53 | extern u32 msm_fb_debug_enabled; | ||
54 | extern struct workqueue_struct *mdp_dma_wq; | ||
55 | |||
56 | int vsync_start_y_adjust = 4; | ||
57 | |||
58 | static void mdp_dma2_update_lcd(struct msm_fb_data_type *mfd) | ||
59 | { | ||
60 | MDPIBUF *iBuf = &mfd->ibuf; | ||
61 | int mddi_dest = FALSE; | ||
62 | uint32 outBpp = iBuf->bpp; | ||
63 | uint32 dma2_cfg_reg; | ||
64 | uint8 *src; | ||
65 | uint32 mddi_ld_param; | ||
66 | uint16 mddi_vdo_packet_reg; | ||
67 | struct msm_fb_panel_data *pdata = | ||
68 | (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data; | ||
69 | uint32 ystride = mfd->fbi->fix.line_length; | ||
70 | |||
71 | dma2_cfg_reg = DMA_PACK_TIGHT | DMA_PACK_ALIGN_LSB | | ||
72 | DMA_OUT_SEL_AHB | DMA_IBUF_NONCONTIGUOUS; | ||
73 | |||
74 | #ifdef CONFIG_FB_MSM_MDP30 | ||
75 | /* | ||
76 | * Software workaround: On 7x25/7x27, the MDP will not | ||
77 | * respond if dma_w is 1 pixel. Set the update width to | ||
78 | * 2 pixels and adjust the x offset if needed. | ||
79 | */ | ||
80 | if (iBuf->dma_w == 1) { | ||
81 | iBuf->dma_w = 2; | ||
82 | if (iBuf->dma_x == (iBuf->ibuf_width - 2)) | ||
83 | iBuf->dma_x--; | ||
84 | } | ||
85 | #endif | ||
86 | |||
87 | if (mfd->fb_imgType == MDP_BGR_565) | ||
88 | dma2_cfg_reg |= DMA_PACK_PATTERN_BGR; | ||
89 | else | ||
90 | dma2_cfg_reg |= DMA_PACK_PATTERN_RGB; | ||
91 | |||
92 | if (outBpp == 4) | ||
93 | dma2_cfg_reg |= DMA_IBUF_C3ALPHA_EN; | ||
94 | |||
95 | if (outBpp == 2) | ||
96 | dma2_cfg_reg |= DMA_IBUF_FORMAT_RGB565; | ||
97 | |||
98 | mddi_ld_param = 0; | ||
99 | mddi_vdo_packet_reg = mfd->panel_info.mddi.vdopkt; | ||
100 | |||
101 | if ((mfd->panel_info.type == MDDI_PANEL) || | ||
102 | (mfd->panel_info.type == EXT_MDDI_PANEL)) { | ||
103 | dma2_cfg_reg |= DMA_OUT_SEL_MDDI; | ||
104 | mddi_dest = TRUE; | ||
105 | |||
106 | if (mfd->panel_info.type == MDDI_PANEL) { | ||
107 | mdp_total_vdopkts++; | ||
108 | if (mfd->panel_info.pdest == DISPLAY_1) { | ||
109 | dma2_cfg_reg |= DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY; | ||
110 | mddi_ld_param = 0; | ||
111 | #ifdef MDDI_HOST_WINDOW_WORKAROUND | ||
112 | mddi_window_adjust(mfd, iBuf->dma_x, | ||
113 | iBuf->dma_w - 1, iBuf->dma_y, | ||
114 | iBuf->dma_h - 1); | ||
115 | #endif | ||
116 | } else { | ||
117 | dma2_cfg_reg |= | ||
118 | DMA_MDDI_DMAOUT_LCD_SEL_SECONDARY; | ||
119 | mddi_ld_param = 1; | ||
120 | #ifdef MDDI_HOST_WINDOW_WORKAROUND | ||
121 | mddi_window_adjust(mfd, iBuf->dma_x, | ||
122 | iBuf->dma_w - 1, iBuf->dma_y, | ||
123 | iBuf->dma_h - 1); | ||
124 | #endif | ||
125 | } | ||
126 | } else { | ||
127 | dma2_cfg_reg |= DMA_MDDI_DMAOUT_LCD_SEL_EXTERNAL; | ||
128 | mddi_ld_param = 2; | ||
129 | } | ||
130 | } else { | ||
131 | if (mfd->panel_info.pdest == DISPLAY_1) { | ||
132 | dma2_cfg_reg |= DMA_AHBM_LCD_SEL_PRIMARY; | ||
133 | outp32(MDP_EBI2_LCD0, mfd->data_port_phys); | ||
134 | } else { | ||
135 | dma2_cfg_reg |= DMA_AHBM_LCD_SEL_SECONDARY; | ||
136 | outp32(MDP_EBI2_LCD1, mfd->data_port_phys); | ||
137 | } | ||
138 | } | ||
139 | |||
140 | dma2_cfg_reg |= DMA_DITHER_EN; | ||
141 | |||
142 | src = (uint8 *) iBuf->buf; | ||
143 | /* starting input address */ | ||
144 | src += iBuf->dma_x * outBpp + iBuf->dma_y * ystride; | ||
145 | |||
146 | mdp_curr_dma2_update_width = iBuf->dma_w; | ||
147 | mdp_curr_dma2_update_height = iBuf->dma_h; | ||
148 | |||
149 | /* MDP cmd block enable */ | ||
150 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); | ||
151 | |||
152 | #ifdef CONFIG_FB_MSM_MDP22 | ||
153 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0184, | ||
154 | (iBuf->dma_h << 16 | iBuf->dma_w)); | ||
155 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0188, src); | ||
156 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x018C, ystride); | ||
157 | #else | ||
158 | MDP_OUTP(MDP_BASE + 0x90004, (iBuf->dma_h << 16 | iBuf->dma_w)); | ||
159 | MDP_OUTP(MDP_BASE + 0x90008, src); | ||
160 | MDP_OUTP(MDP_BASE + 0x9000c, ystride); | ||
161 | #endif | ||
162 | |||
163 | if (mfd->panel_info.bpp == 18) { | ||
164 | dma2_cfg_reg |= DMA_DSTC0G_6BITS | /* 666 18BPP */ | ||
165 | DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS; | ||
166 | } else { | ||
167 | dma2_cfg_reg |= DMA_DSTC0G_6BITS | /* 565 16BPP */ | ||
168 | DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS; | ||
169 | } | ||
170 | |||
171 | if (mddi_dest) { | ||
172 | #ifdef CONFIG_FB_MSM_MDP22 | ||
173 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0194, | ||
174 | (iBuf->dma_y << 16) | iBuf->dma_x); | ||
175 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01a0, mddi_ld_param); | ||
176 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01a4, | ||
177 | (MDDI_VDO_PACKET_DESC << 16) | mddi_vdo_packet_reg); | ||
178 | #else | ||
179 | MDP_OUTP(MDP_BASE + 0x90010, (iBuf->dma_y << 16) | iBuf->dma_x); | ||
180 | MDP_OUTP(MDP_BASE + 0x00090, mddi_ld_param); | ||
181 | MDP_OUTP(MDP_BASE + 0x00094, | ||
182 | (MDDI_VDO_PACKET_DESC << 16) | mddi_vdo_packet_reg); | ||
183 | #endif | ||
184 | } else { | ||
185 | /* setting EBI2 LCDC write window */ | ||
186 | pdata->set_rect(iBuf->dma_x, iBuf->dma_y, iBuf->dma_w, | ||
187 | iBuf->dma_h); | ||
188 | } | ||
189 | |||
190 | /* dma2 config register */ | ||
191 | #ifdef MDP_HW_VSYNC | ||
192 | MDP_OUTP(MDP_BASE + 0x90000, dma2_cfg_reg); | ||
193 | |||
194 | if ((mfd->use_mdp_vsync) && | ||
195 | (mfd->ibuf.vsync_enable) && (mfd->panel_info.lcd.vsync_enable)) { | ||
196 | uint32 start_y; | ||
197 | |||
198 | if (vsync_start_y_adjust <= iBuf->dma_y) | ||
199 | start_y = iBuf->dma_y - vsync_start_y_adjust; | ||
200 | else | ||
201 | start_y = | ||
202 | (mfd->total_lcd_lines - 1) - (vsync_start_y_adjust - | ||
203 | iBuf->dma_y); | ||
204 | |||
205 | /* | ||
206 | * MDP VSYNC clock must be On by now so, we don't have to | ||
207 | * re-enable it | ||
208 | */ | ||
209 | MDP_OUTP(MDP_BASE + 0x210, start_y); | ||
210 | MDP_OUTP(MDP_BASE + 0x20c, 1); /* enable prim vsync */ | ||
211 | } else { | ||
212 | MDP_OUTP(MDP_BASE + 0x20c, 0); /* disable prim vsync */ | ||
213 | } | ||
214 | #else | ||
215 | #ifdef CONFIG_FB_MSM_MDP22 | ||
216 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0180, dma2_cfg_reg); | ||
217 | #else | ||
218 | MDP_OUTP(MDP_BASE + 0x90000, dma2_cfg_reg); | ||
219 | #endif | ||
220 | #endif /* MDP_HW_VSYNC */ | ||
221 | |||
222 | /* MDP cmd block disable */ | ||
223 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); | ||
224 | } | ||
225 | |||
226 | static ktime_t vt = { 0 }; | ||
227 | int mdp_usec_diff_threshold = 100; | ||
228 | int mdp_expected_usec_wait; | ||
229 | |||
230 | enum hrtimer_restart mdp_dma2_vsync_hrtimer_handler(struct hrtimer *ht) | ||
231 | { | ||
232 | struct msm_fb_data_type *mfd = NULL; | ||
233 | |||
234 | mfd = container_of(ht, struct msm_fb_data_type, dma_hrtimer); | ||
235 | |||
236 | mdp_pipe_kickoff(MDP_DMA2_TERM, mfd); | ||
237 | |||
238 | if (msm_fb_debug_enabled) { | ||
239 | ktime_t t; | ||
240 | int usec_diff; | ||
241 | int actual_wait; | ||
242 | |||
243 | t = ktime_get_real(); | ||
244 | |||
245 | actual_wait = | ||
246 | (t.tv.sec - vt.tv.sec) * 1000000 + (t.tv.nsec - | ||
247 | vt.tv.nsec) / 1000; | ||
248 | usec_diff = actual_wait - mdp_expected_usec_wait; | ||
249 | |||
250 | if ((mdp_usec_diff_threshold < usec_diff) || (usec_diff < 0)) | ||
251 | MSM_FB_DEBUG | ||
252 | ("HRT Diff = %d usec Exp=%d usec Act=%d usec\n", | ||
253 | usec_diff, mdp_expected_usec_wait, actual_wait); | ||
254 | } | ||
255 | |||
256 | return HRTIMER_NORESTART; | ||
257 | } | ||
258 | |||
259 | static void mdp_dma_schedule(struct msm_fb_data_type *mfd, uint32 term) | ||
260 | { | ||
261 | /* | ||
262 | * dma2 configure VSYNC block | ||
263 | * vsync supported on Primary LCD only for now | ||
264 | */ | ||
265 | int32 mdp_lcd_rd_cnt; | ||
266 | uint32 usec_wait_time; | ||
267 | uint32 start_y; | ||
268 | |||
269 | /* | ||
270 | * ToDo: if we can move HRT timer callback to workqueue, we can | ||
271 | * move DMA2 power on under mdp_pipe_kickoff(). | ||
272 | * This will save a power for hrt time wait. | ||
273 | * However if the latency for context switch (hrt irq -> workqueue) | ||
274 | * is too big, we will miss the vsync timing. | ||
275 | */ | ||
276 | if (term == MDP_DMA2_TERM) | ||
277 | mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_ON, FALSE); | ||
278 | |||
279 | mdp_dma2_update_time_in_usec = | ||
280 | MDP_KTIME2USEC(mdp_dma2_last_update_time); | ||
281 | |||
282 | if ((!mfd->ibuf.vsync_enable) || (!mfd->panel_info.lcd.vsync_enable) | ||
283 | || (mfd->use_mdp_vsync)) { | ||
284 | mdp_pipe_kickoff(term, mfd); | ||
285 | return; | ||
286 | } | ||
287 | /* SW vsync logic starts here */ | ||
288 | |||
289 | /* get current rd counter */ | ||
290 | mdp_lcd_rd_cnt = mdp_get_lcd_line_counter(mfd); | ||
291 | if (mdp_dma2_update_time_in_usec != 0) { | ||
292 | uint32 num, den; | ||
293 | |||
294 | /* | ||
295 | * roi width boundary calculation to know the size of pixel | ||
296 | * width that MDP can send faster or slower than LCD read | ||
297 | * pointer | ||
298 | */ | ||
299 | |||
300 | num = mdp_last_dma2_update_width * mdp_last_dma2_update_height; | ||
301 | den = | ||
302 | (((mfd->panel_info.lcd.refx100 * mfd->total_lcd_lines) / | ||
303 | 1000) * (mdp_dma2_update_time_in_usec / 100)) / 1000; | ||
304 | |||
305 | if (den == 0) | ||
306 | mfd->vsync_width_boundary[mdp_last_dma2_update_width] = | ||
307 | mfd->panel_info.xres + 1; | ||
308 | else | ||
309 | mfd->vsync_width_boundary[mdp_last_dma2_update_width] = | ||
310 | (int)(num / den); | ||
311 | } | ||
312 | |||
313 | if (mfd->vsync_width_boundary[mdp_last_dma2_update_width] > | ||
314 | mdp_curr_dma2_update_width) { | ||
315 | /* MDP wrp is faster than LCD rdp */ | ||
316 | mdp_lcd_rd_cnt += mdp_lcd_rd_cnt_offset_fast; | ||
317 | } else { | ||
318 | /* MDP wrp is slower than LCD rdp */ | ||
319 | mdp_lcd_rd_cnt -= mdp_lcd_rd_cnt_offset_slow; | ||
320 | } | ||
321 | |||
322 | if (mdp_lcd_rd_cnt < 0) | ||
323 | mdp_lcd_rd_cnt = mfd->total_lcd_lines + mdp_lcd_rd_cnt; | ||
324 | else if (mdp_lcd_rd_cnt > mfd->total_lcd_lines) | ||
325 | mdp_lcd_rd_cnt = mdp_lcd_rd_cnt - mfd->total_lcd_lines - 1; | ||
326 | |||
327 | /* get wrt pointer position */ | ||
328 | start_y = mfd->ibuf.dma_y; | ||
329 | |||
330 | /* measure line difference between start_y and rd counter */ | ||
331 | if (start_y > mdp_lcd_rd_cnt) { | ||
332 | /* | ||
333 | * *100 for lcd_ref_hzx100 was already multiplied by 100 | ||
334 | * *1000000 is for usec conversion | ||
335 | */ | ||
336 | |||
337 | if ((start_y - mdp_lcd_rd_cnt) <= | ||
338 | mdp_vsync_usec_wait_line_too_short) | ||
339 | usec_wait_time = 0; | ||
340 | else | ||
341 | usec_wait_time = | ||
342 | ((start_y - | ||
343 | mdp_lcd_rd_cnt) * 1000000) / | ||
344 | ((mfd->total_lcd_lines * | ||
345 | mfd->panel_info.lcd.refx100) / 100); | ||
346 | } else { | ||
347 | if ((start_y + (mfd->total_lcd_lines - mdp_lcd_rd_cnt)) <= | ||
348 | mdp_vsync_usec_wait_line_too_short) | ||
349 | usec_wait_time = 0; | ||
350 | else | ||
351 | usec_wait_time = | ||
352 | ((start_y + | ||
353 | (mfd->total_lcd_lines - | ||
354 | mdp_lcd_rd_cnt)) * 1000000) / | ||
355 | ((mfd->total_lcd_lines * | ||
356 | mfd->panel_info.lcd.refx100) / 100); | ||
357 | } | ||
358 | |||
359 | mdp_last_dma2_update_width = mdp_curr_dma2_update_width; | ||
360 | mdp_last_dma2_update_height = mdp_curr_dma2_update_height; | ||
361 | |||
362 | if (usec_wait_time == 0) { | ||
363 | mdp_pipe_kickoff(term, mfd); | ||
364 | } else { | ||
365 | ktime_t wait_time; | ||
366 | |||
367 | wait_time.tv.sec = 0; | ||
368 | wait_time.tv.nsec = usec_wait_time * 1000; | ||
369 | |||
370 | if (msm_fb_debug_enabled) { | ||
371 | vt = ktime_get_real(); | ||
372 | mdp_expected_usec_wait = usec_wait_time; | ||
373 | } | ||
374 | hrtimer_start(&mfd->dma_hrtimer, wait_time, HRTIMER_MODE_REL); | ||
375 | } | ||
376 | } | ||
377 | |||
378 | #ifdef MDDI_HOST_WINDOW_WORKAROUND | ||
379 | void mdp_dma2_update(struct msm_fb_data_type *mfd) | ||
380 | { | ||
381 | MDPIBUF *iBuf; | ||
382 | uint32 upper_height; | ||
383 | |||
384 | if (mfd->panel.type == EXT_MDDI_PANEL) { | ||
385 | mdp_dma2_update_sub(mfd); | ||
386 | return; | ||
387 | } | ||
388 | |||
389 | iBuf = &mfd->ibuf; | ||
390 | |||
391 | upper_height = | ||
392 | (uint32) mddi_assign_pkt_height((uint16) iBuf->dma_w, | ||
393 | (uint16) iBuf->dma_h, 18); | ||
394 | |||
395 | if (upper_height >= iBuf->dma_h) { | ||
396 | mdp_dma2_update_sub(mfd); | ||
397 | } else { | ||
398 | MDPIBUF lower_height; | ||
399 | |||
400 | /* sending the upper region first */ | ||
401 | lower_height = iBuf->dma_h - upper_height; | ||
402 | iBuf->dma_h = upper_height; | ||
403 | mdp_dma2_update_sub(mfd); | ||
404 | |||
405 | /* sending the lower region second */ | ||
406 | iBuf->dma_h = lower_height; | ||
407 | iBuf->dma_y += lower_height; | ||
408 | iBuf->vsync_enable = FALSE; | ||
409 | mdp_dma2_update_sub(mfd); | ||
410 | } | ||
411 | } | ||
412 | |||
413 | void mdp_dma2_update_sub(struct msm_fb_data_type *mfd) | ||
414 | #else | ||
415 | void mdp_dma2_update(struct msm_fb_data_type *mfd) | ||
416 | #endif | ||
417 | { | ||
418 | down(&mfd->dma->mutex); | ||
419 | if ((mfd) && (!mfd->dma->busy) && (mfd->panel_power_on)) { | ||
420 | down(&mfd->sem); | ||
421 | mfd->ibuf_flushed = TRUE; | ||
422 | mdp_dma2_update_lcd(mfd); | ||
423 | |||
424 | mdp_enable_irq(MDP_DMA2_TERM); | ||
425 | mfd->dma->busy = TRUE; | ||
426 | INIT_COMPLETION(mfd->dma->comp); | ||
427 | |||
428 | /* schedule DMA to start */ | ||
429 | mdp_dma_schedule(mfd, MDP_DMA2_TERM); | ||
430 | up(&mfd->sem); | ||
431 | |||
432 | /* wait until DMA finishes the current job */ | ||
433 | wait_for_completion_killable(&mfd->dma->comp); | ||
434 | mdp_disable_irq(MDP_DMA2_TERM); | ||
435 | |||
436 | /* signal if pan function is waiting for the update completion */ | ||
437 | if (mfd->pan_waiting) { | ||
438 | mfd->pan_waiting = FALSE; | ||
439 | complete(&mfd->pan_comp); | ||
440 | } | ||
441 | } | ||
442 | up(&mfd->dma->mutex); | ||
443 | } | ||
444 | |||
445 | void mdp_lcd_update_workqueue_handler(struct work_struct *work) | ||
446 | { | ||
447 | struct msm_fb_data_type *mfd = NULL; | ||
448 | |||
449 | mfd = container_of(work, struct msm_fb_data_type, dma_update_worker); | ||
450 | if (mfd) | ||
451 | mfd->dma_fnc(mfd); | ||
452 | } | ||
453 | |||
454 | void mdp_set_dma_pan_info(struct fb_info *info, struct mdp_dirty_region *dirty, | ||
455 | boolean sync) | ||
456 | { | ||
457 | struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; | ||
458 | MDPIBUF *iBuf; | ||
459 | int bpp = info->var.bits_per_pixel / 8; | ||
460 | |||
461 | down(&mfd->sem); | ||
462 | iBuf = &mfd->ibuf; | ||
463 | iBuf->buf = (uint8 *) info->fix.smem_start; | ||
464 | iBuf->buf += info->var.xoffset * bpp + | ||
465 | info->var.yoffset * info->fix.line_length; | ||
466 | |||
467 | iBuf->ibuf_width = info->var.xres_virtual; | ||
468 | iBuf->bpp = bpp; | ||
469 | |||
470 | iBuf->vsync_enable = sync; | ||
471 | |||
472 | if (dirty) { | ||
473 | /* | ||
474 | * ToDo: dirty region check inside var.xoffset+xres | ||
475 | * <-> var.yoffset+yres | ||
476 | */ | ||
477 | iBuf->dma_x = dirty->xoffset % info->var.xres; | ||
478 | iBuf->dma_y = dirty->yoffset % info->var.yres; | ||
479 | iBuf->dma_w = dirty->width; | ||
480 | iBuf->dma_h = dirty->height; | ||
481 | } else { | ||
482 | iBuf->dma_x = 0; | ||
483 | iBuf->dma_y = 0; | ||
484 | iBuf->dma_w = info->var.xres; | ||
485 | iBuf->dma_h = info->var.yres; | ||
486 | } | ||
487 | mfd->ibuf_flushed = FALSE; | ||
488 | up(&mfd->sem); | ||
489 | } | ||
490 | |||
491 | void mdp_set_offset_info(struct fb_info *info, uint32 addr, uint32 sync) | ||
492 | { | ||
493 | struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; | ||
494 | MDPIBUF *iBuf; | ||
495 | |||
496 | int bpp = info->var.bits_per_pixel / 8; | ||
497 | |||
498 | down(&mfd->sem); | ||
499 | iBuf = &mfd->ibuf; | ||
500 | iBuf->ibuf_width = info->var.xres_virtual; | ||
501 | iBuf->bpp = bpp; | ||
502 | iBuf->vsync_enable = sync; | ||
503 | iBuf->dma_x = 0; | ||
504 | iBuf->dma_y = 0; | ||
505 | iBuf->dma_w = info->var.xres; | ||
506 | iBuf->dma_h = info->var.yres; | ||
507 | iBuf->buf = (uint8 *) addr; | ||
508 | |||
509 | mfd->ibuf_flushed = FALSE; | ||
510 | up(&mfd->sem); | ||
511 | } | ||
512 | |||
513 | void mdp_dma_pan_update(struct fb_info *info) | ||
514 | { | ||
515 | struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; | ||
516 | MDPIBUF *iBuf; | ||
517 | |||
518 | iBuf = &mfd->ibuf; | ||
519 | |||
520 | if (mfd->sw_currently_refreshing) { | ||
521 | /* we need to wait for the pending update */ | ||
522 | mfd->pan_waiting = TRUE; | ||
523 | if (!mfd->ibuf_flushed) { | ||
524 | wait_for_completion_killable(&mfd->pan_comp); | ||
525 | } | ||
526 | /* waiting for this update to complete */ | ||
527 | mfd->pan_waiting = TRUE; | ||
528 | wait_for_completion_killable(&mfd->pan_comp); | ||
529 | } else | ||
530 | mfd->dma_fnc(mfd); | ||
531 | } | ||
532 | |||
533 | void mdp_refresh_screen(unsigned long data) | ||
534 | { | ||
535 | struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)data; | ||
536 | |||
537 | if ((mfd->sw_currently_refreshing) && (mfd->sw_refreshing_enable)) { | ||
538 | init_timer(&mfd->refresh_timer); | ||
539 | mfd->refresh_timer.function = mdp_refresh_screen; | ||
540 | mfd->refresh_timer.data = data; | ||
541 | |||
542 | if (mfd->dma->busy) | ||
543 | /* come back in 1 msec */ | ||
544 | mfd->refresh_timer.expires = jiffies + (HZ / 1000); | ||
545 | else | ||
546 | mfd->refresh_timer.expires = | ||
547 | jiffies + mfd->refresh_timer_duration; | ||
548 | |||
549 | add_timer(&mfd->refresh_timer); | ||
550 | |||
551 | if (!mfd->dma->busy) { | ||
552 | if (!queue_work(mdp_dma_wq, &mfd->dma_update_worker)) { | ||
553 | MSM_FB_DEBUG("mdp_dma: can't queue_work! -> \ | ||
554 | MDP/MDDI/LCD clock speed needs to be increased\n"); | ||
555 | } | ||
556 | } | ||
557 | } else { | ||
558 | if (!mfd->hw_refresh) | ||
559 | complete(&mfd->refresher_comp); | ||
560 | } | ||
561 | } | ||
diff --git a/drivers/staging/msm/mdp_dma_lcdc.c b/drivers/staging/msm/mdp_dma_lcdc.c new file mode 100644 index 000000000000..b57fa1a0ceb0 --- /dev/null +++ b/drivers/staging/msm/mdp_dma_lcdc.c | |||
@@ -0,0 +1,379 @@ | |||
1 | /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/sched.h> | ||
21 | #include <linux/time.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/hrtimer.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <mach/hardware.h> | ||
27 | #include <linux/io.h> | ||
28 | |||
29 | #include <asm/system.h> | ||
30 | #include <asm/mach-types.h> | ||
31 | #include <linux/semaphore.h> | ||
32 | #include <linux/spinlock.h> | ||
33 | |||
34 | #include <linux/fb.h> | ||
35 | |||
36 | #include "mdp.h" | ||
37 | #include "msm_fb.h" | ||
38 | #include "mdp4.h" | ||
39 | |||
40 | #ifdef CONFIG_FB_MSM_MDP40 | ||
41 | #define LCDC_BASE 0xC0000 | ||
42 | #define DTV_BASE 0xD0000 | ||
43 | #define DMA_E_BASE 0xB0000 | ||
44 | #else | ||
45 | #define LCDC_BASE 0xE0000 | ||
46 | #endif | ||
47 | |||
48 | #define DMA_P_BASE 0x90000 | ||
49 | |||
50 | extern spinlock_t mdp_spin_lock; | ||
51 | #ifndef CONFIG_FB_MSM_MDP40 | ||
52 | extern uint32 mdp_intr_mask; | ||
53 | #endif | ||
54 | |||
55 | int first_pixel_start_x; | ||
56 | int first_pixel_start_y; | ||
57 | |||
58 | int mdp_lcdc_on(struct platform_device *pdev) | ||
59 | { | ||
60 | int lcdc_width; | ||
61 | int lcdc_height; | ||
62 | int lcdc_bpp; | ||
63 | int lcdc_border_clr; | ||
64 | int lcdc_underflow_clr; | ||
65 | int lcdc_hsync_skew; | ||
66 | |||
67 | int hsync_period; | ||
68 | int hsync_ctrl; | ||
69 | int vsync_period; | ||
70 | int display_hctl; | ||
71 | int display_v_start; | ||
72 | int display_v_end; | ||
73 | int active_hctl; | ||
74 | int active_h_start; | ||
75 | int active_h_end; | ||
76 | int active_v_start; | ||
77 | int active_v_end; | ||
78 | int ctrl_polarity; | ||
79 | int h_back_porch; | ||
80 | int h_front_porch; | ||
81 | int v_back_porch; | ||
82 | int v_front_porch; | ||
83 | int hsync_pulse_width; | ||
84 | int vsync_pulse_width; | ||
85 | int hsync_polarity; | ||
86 | int vsync_polarity; | ||
87 | int data_en_polarity; | ||
88 | int hsync_start_x; | ||
89 | int hsync_end_x; | ||
90 | uint8 *buf; | ||
91 | int bpp; | ||
92 | uint32 dma2_cfg_reg; | ||
93 | struct fb_info *fbi; | ||
94 | struct fb_var_screeninfo *var; | ||
95 | struct msm_fb_data_type *mfd; | ||
96 | uint32 dma_base; | ||
97 | uint32 timer_base = LCDC_BASE; | ||
98 | uint32 block = MDP_DMA2_BLOCK; | ||
99 | int ret; | ||
100 | |||
101 | mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev); | ||
102 | |||
103 | if (!mfd) | ||
104 | return -ENODEV; | ||
105 | |||
106 | if (mfd->key != MFD_KEY) | ||
107 | return -EINVAL; | ||
108 | |||
109 | fbi = mfd->fbi; | ||
110 | var = &fbi->var; | ||
111 | |||
112 | /* MDP cmd block enable */ | ||
113 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); | ||
114 | |||
115 | bpp = fbi->var.bits_per_pixel / 8; | ||
116 | buf = (uint8 *) fbi->fix.smem_start; | ||
117 | buf += fbi->var.xoffset * bpp + fbi->var.yoffset * fbi->fix.line_length; | ||
118 | |||
119 | dma2_cfg_reg = DMA_PACK_ALIGN_LSB | DMA_DITHER_EN | DMA_OUT_SEL_LCDC; | ||
120 | |||
121 | if (mfd->fb_imgType == MDP_BGR_565) | ||
122 | dma2_cfg_reg |= DMA_PACK_PATTERN_BGR; | ||
123 | else | ||
124 | dma2_cfg_reg |= DMA_PACK_PATTERN_RGB; | ||
125 | |||
126 | if (bpp == 2) | ||
127 | dma2_cfg_reg |= DMA_IBUF_FORMAT_RGB565; | ||
128 | else if (bpp == 3) | ||
129 | dma2_cfg_reg |= DMA_IBUF_FORMAT_RGB888; | ||
130 | else | ||
131 | dma2_cfg_reg |= DMA_IBUF_FORMAT_xRGB8888_OR_ARGB8888; | ||
132 | |||
133 | switch (mfd->panel_info.bpp) { | ||
134 | case 24: | ||
135 | dma2_cfg_reg |= DMA_DSTC0G_8BITS | | ||
136 | DMA_DSTC1B_8BITS | DMA_DSTC2R_8BITS; | ||
137 | break; | ||
138 | |||
139 | case 18: | ||
140 | dma2_cfg_reg |= DMA_DSTC0G_6BITS | | ||
141 | DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS; | ||
142 | break; | ||
143 | |||
144 | case 16: | ||
145 | dma2_cfg_reg |= DMA_DSTC0G_6BITS | | ||
146 | DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS; | ||
147 | break; | ||
148 | |||
149 | default: | ||
150 | printk(KERN_ERR "mdp lcdc can't support format %d bpp!\n", | ||
151 | mfd->panel_info.bpp); | ||
152 | return -ENODEV; | ||
153 | } | ||
154 | |||
155 | /* DMA register config */ | ||
156 | |||
157 | dma_base = DMA_P_BASE; | ||
158 | |||
159 | #ifdef CONFIG_FB_MSM_MDP40 | ||
160 | if (mfd->panel.type == HDMI_PANEL) | ||
161 | dma_base = DMA_E_BASE; | ||
162 | #endif | ||
163 | |||
164 | /* starting address */ | ||
165 | MDP_OUTP(MDP_BASE + dma_base + 0x8, (uint32) buf); | ||
166 | /* active window width and height */ | ||
167 | MDP_OUTP(MDP_BASE + dma_base + 0x4, ((fbi->var.yres) << 16) | | ||
168 | (fbi->var.xres)); | ||
169 | /* buffer ystride */ | ||
170 | MDP_OUTP(MDP_BASE + dma_base + 0xc, fbi->fix.line_length); | ||
171 | /* x/y coordinate = always 0 for lcdc */ | ||
172 | MDP_OUTP(MDP_BASE + dma_base + 0x10, 0); | ||
173 | /* dma config */ | ||
174 | MDP_OUTP(MDP_BASE + dma_base, dma2_cfg_reg); | ||
175 | |||
176 | /* | ||
177 | * LCDC timing setting | ||
178 | */ | ||
179 | h_back_porch = var->left_margin; | ||
180 | h_front_porch = var->right_margin; | ||
181 | v_back_porch = var->upper_margin; | ||
182 | v_front_porch = var->lower_margin; | ||
183 | hsync_pulse_width = var->hsync_len; | ||
184 | vsync_pulse_width = var->vsync_len; | ||
185 | lcdc_border_clr = mfd->panel_info.lcdc.border_clr; | ||
186 | lcdc_underflow_clr = mfd->panel_info.lcdc.underflow_clr; | ||
187 | lcdc_hsync_skew = mfd->panel_info.lcdc.hsync_skew; | ||
188 | |||
189 | lcdc_width = mfd->panel_info.xres; | ||
190 | lcdc_height = mfd->panel_info.yres; | ||
191 | lcdc_bpp = mfd->panel_info.bpp; | ||
192 | |||
193 | hsync_period = | ||
194 | hsync_pulse_width + h_back_porch + lcdc_width + h_front_porch; | ||
195 | hsync_ctrl = (hsync_period << 16) | hsync_pulse_width; | ||
196 | hsync_start_x = hsync_pulse_width + h_back_porch; | ||
197 | hsync_end_x = hsync_period - h_front_porch - 1; | ||
198 | display_hctl = (hsync_end_x << 16) | hsync_start_x; | ||
199 | |||
200 | vsync_period = | ||
201 | (vsync_pulse_width + v_back_porch + lcdc_height + | ||
202 | v_front_porch) * hsync_period; | ||
203 | display_v_start = | ||
204 | (vsync_pulse_width + v_back_porch) * hsync_period + lcdc_hsync_skew; | ||
205 | display_v_end = | ||
206 | vsync_period - (v_front_porch * hsync_period) + lcdc_hsync_skew - 1; | ||
207 | |||
208 | if (lcdc_width != var->xres) { | ||
209 | active_h_start = hsync_start_x + first_pixel_start_x; | ||
210 | active_h_end = active_h_start + var->xres - 1; | ||
211 | active_hctl = | ||
212 | ACTIVE_START_X_EN | (active_h_end << 16) | active_h_start; | ||
213 | } else { | ||
214 | active_hctl = 0; | ||
215 | } | ||
216 | |||
217 | if (lcdc_height != var->yres) { | ||
218 | active_v_start = | ||
219 | display_v_start + first_pixel_start_y * hsync_period; | ||
220 | active_v_end = active_v_start + (var->yres) * hsync_period - 1; | ||
221 | active_v_start |= ACTIVE_START_Y_EN; | ||
222 | } else { | ||
223 | active_v_start = 0; | ||
224 | active_v_end = 0; | ||
225 | } | ||
226 | |||
227 | |||
228 | #ifdef CONFIG_FB_MSM_MDP40 | ||
229 | if (mfd->panel.type == HDMI_PANEL) { | ||
230 | block = MDP_DMA_E_BLOCK; | ||
231 | timer_base = DTV_BASE; | ||
232 | hsync_polarity = 0; | ||
233 | vsync_polarity = 0; | ||
234 | } else { | ||
235 | hsync_polarity = 1; | ||
236 | vsync_polarity = 1; | ||
237 | } | ||
238 | |||
239 | lcdc_underflow_clr |= 0x80000000; /* enable recovery */ | ||
240 | #else | ||
241 | hsync_polarity = 0; | ||
242 | vsync_polarity = 0; | ||
243 | #endif | ||
244 | data_en_polarity = 0; | ||
245 | |||
246 | ctrl_polarity = | ||
247 | (data_en_polarity << 2) | (vsync_polarity << 1) | (hsync_polarity); | ||
248 | |||
249 | MDP_OUTP(MDP_BASE + timer_base + 0x4, hsync_ctrl); | ||
250 | MDP_OUTP(MDP_BASE + timer_base + 0x8, vsync_period); | ||
251 | MDP_OUTP(MDP_BASE + timer_base + 0xc, vsync_pulse_width * hsync_period); | ||
252 | if (timer_base == LCDC_BASE) { | ||
253 | MDP_OUTP(MDP_BASE + timer_base + 0x10, display_hctl); | ||
254 | MDP_OUTP(MDP_BASE + timer_base + 0x14, display_v_start); | ||
255 | MDP_OUTP(MDP_BASE + timer_base + 0x18, display_v_end); | ||
256 | MDP_OUTP(MDP_BASE + timer_base + 0x28, lcdc_border_clr); | ||
257 | MDP_OUTP(MDP_BASE + timer_base + 0x2c, lcdc_underflow_clr); | ||
258 | MDP_OUTP(MDP_BASE + timer_base + 0x30, lcdc_hsync_skew); | ||
259 | MDP_OUTP(MDP_BASE + timer_base + 0x38, ctrl_polarity); | ||
260 | MDP_OUTP(MDP_BASE + timer_base + 0x1c, active_hctl); | ||
261 | MDP_OUTP(MDP_BASE + timer_base + 0x20, active_v_start); | ||
262 | MDP_OUTP(MDP_BASE + timer_base + 0x24, active_v_end); | ||
263 | } else { | ||
264 | MDP_OUTP(MDP_BASE + timer_base + 0x18, display_hctl); | ||
265 | MDP_OUTP(MDP_BASE + timer_base + 0x1c, display_v_start); | ||
266 | MDP_OUTP(MDP_BASE + timer_base + 0x20, display_v_end); | ||
267 | MDP_OUTP(MDP_BASE + timer_base + 0x40, lcdc_border_clr); | ||
268 | MDP_OUTP(MDP_BASE + timer_base + 0x44, lcdc_underflow_clr); | ||
269 | MDP_OUTP(MDP_BASE + timer_base + 0x48, lcdc_hsync_skew); | ||
270 | MDP_OUTP(MDP_BASE + timer_base + 0x50, ctrl_polarity); | ||
271 | MDP_OUTP(MDP_BASE + timer_base + 0x2c, active_hctl); | ||
272 | MDP_OUTP(MDP_BASE + timer_base + 0x30, active_v_start); | ||
273 | MDP_OUTP(MDP_BASE + timer_base + 0x38, active_v_end); | ||
274 | } | ||
275 | |||
276 | ret = panel_next_on(pdev); | ||
277 | if (ret == 0) { | ||
278 | /* enable LCDC block */ | ||
279 | MDP_OUTP(MDP_BASE + timer_base, 1); | ||
280 | mdp_pipe_ctrl(block, MDP_BLOCK_POWER_ON, FALSE); | ||
281 | } | ||
282 | /* MDP cmd block disable */ | ||
283 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); | ||
284 | |||
285 | return ret; | ||
286 | } | ||
287 | |||
288 | int mdp_lcdc_off(struct platform_device *pdev) | ||
289 | { | ||
290 | int ret = 0; | ||
291 | struct msm_fb_data_type *mfd; | ||
292 | uint32 timer_base = LCDC_BASE; | ||
293 | uint32 block = MDP_DMA2_BLOCK; | ||
294 | |||
295 | mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev); | ||
296 | |||
297 | #ifdef CONFIG_FB_MSM_MDP40 | ||
298 | if (mfd->panel.type == HDMI_PANEL) { | ||
299 | block = MDP_DMA_E_BLOCK; | ||
300 | timer_base = DTV_BASE; | ||
301 | } | ||
302 | #endif | ||
303 | |||
304 | /* MDP cmd block enable */ | ||
305 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); | ||
306 | MDP_OUTP(MDP_BASE + timer_base, 0); | ||
307 | /* MDP cmd block disable */ | ||
308 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); | ||
309 | mdp_pipe_ctrl(block, MDP_BLOCK_POWER_OFF, FALSE); | ||
310 | |||
311 | ret = panel_next_off(pdev); | ||
312 | |||
313 | /* delay to make sure the last frame finishes */ | ||
314 | mdelay(100); | ||
315 | |||
316 | return ret; | ||
317 | } | ||
318 | |||
319 | void mdp_lcdc_update(struct msm_fb_data_type *mfd) | ||
320 | { | ||
321 | struct fb_info *fbi = mfd->fbi; | ||
322 | uint8 *buf; | ||
323 | int bpp; | ||
324 | unsigned long flag; | ||
325 | uint32 dma_base; | ||
326 | int irq_block = MDP_DMA2_TERM; | ||
327 | #ifdef CONFIG_FB_MSM_MDP40 | ||
328 | int intr = INTR_DMA_P_DONE; | ||
329 | #endif | ||
330 | |||
331 | if (!mfd->panel_power_on) | ||
332 | return; | ||
333 | |||
334 | /* no need to power on cmd block since it's lcdc mode */ | ||
335 | |||
336 | if (!mfd->ibuf.visible_swapped) { | ||
337 | bpp = fbi->var.bits_per_pixel / 8; | ||
338 | buf = (uint8 *) fbi->fix.smem_start; | ||
339 | buf += fbi->var.xoffset * bpp + | ||
340 | fbi->var.yoffset * fbi->fix.line_length; | ||
341 | } else { | ||
342 | /* we've done something to update the pointer. */ | ||
343 | bpp = mfd->ibuf.bpp; | ||
344 | buf = mfd->ibuf.buf; | ||
345 | } | ||
346 | |||
347 | dma_base = DMA_P_BASE; | ||
348 | |||
349 | #ifdef CONFIG_FB_MSM_MDP40 | ||
350 | if (mfd->panel.type == HDMI_PANEL) { | ||
351 | intr = INTR_DMA_E_DONE; | ||
352 | irq_block = MDP_DMA_E_TERM; | ||
353 | dma_base = DMA_E_BASE; | ||
354 | } | ||
355 | #endif | ||
356 | |||
357 | /* starting address */ | ||
358 | MDP_OUTP(MDP_BASE + dma_base + 0x8, (uint32) buf); | ||
359 | |||
360 | /* enable LCDC irq */ | ||
361 | spin_lock_irqsave(&mdp_spin_lock, flag); | ||
362 | mdp_enable_irq(irq_block); | ||
363 | INIT_COMPLETION(mfd->dma->comp); | ||
364 | mfd->dma->waiting = TRUE; | ||
365 | #ifdef CONFIG_FB_MSM_MDP40 | ||
366 | outp32(MDP_INTR_CLEAR, intr); | ||
367 | mdp_intr_mask |= intr; | ||
368 | outp32(MDP_INTR_ENABLE, mdp_intr_mask); | ||
369 | #else | ||
370 | outp32(MDP_INTR_CLEAR, LCDC_FRAME_START); | ||
371 | mdp_intr_mask |= LCDC_FRAME_START; | ||
372 | outp32(MDP_INTR_ENABLE, mdp_intr_mask); | ||
373 | #endif | ||
374 | spin_unlock_irqrestore(&mdp_spin_lock, flag); | ||
375 | |||
376 | if (mfd->ibuf.vsync_enable) | ||
377 | wait_for_completion_killable(&mfd->dma->comp); | ||
378 | mdp_disable_irq(irq_block); | ||
379 | } | ||
diff --git a/drivers/staging/msm/mdp_dma_s.c b/drivers/staging/msm/mdp_dma_s.c new file mode 100644 index 000000000000..0c34a1010f17 --- /dev/null +++ b/drivers/staging/msm/mdp_dma_s.c | |||
@@ -0,0 +1,139 @@ | |||
1 | /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/sched.h> | ||
21 | #include <linux/time.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/hrtimer.h> | ||
25 | |||
26 | #include <mach/hardware.h> | ||
27 | #include <linux/io.h> | ||
28 | |||
29 | #include <asm/system.h> | ||
30 | #include <asm/mach-types.h> | ||
31 | #include <linux/semaphore.h> | ||
32 | #include <linux/spinlock.h> | ||
33 | |||
34 | #include <linux/fb.h> | ||
35 | |||
36 | #include "mdp.h" | ||
37 | #include "msm_fb.h" | ||
38 | |||
39 | static void mdp_dma_s_update_lcd(struct msm_fb_data_type *mfd) | ||
40 | { | ||
41 | MDPIBUF *iBuf = &mfd->ibuf; | ||
42 | int mddi_dest = FALSE; | ||
43 | uint32 outBpp = iBuf->bpp; | ||
44 | uint32 dma_s_cfg_reg; | ||
45 | uint8 *src; | ||
46 | struct msm_fb_panel_data *pdata = | ||
47 | (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data; | ||
48 | |||
49 | dma_s_cfg_reg = DMA_PACK_TIGHT | DMA_PACK_ALIGN_LSB | | ||
50 | DMA_OUT_SEL_AHB | DMA_IBUF_NONCONTIGUOUS; | ||
51 | |||
52 | if (mfd->fb_imgType == MDP_BGR_565) | ||
53 | dma_s_cfg_reg |= DMA_PACK_PATTERN_BGR; | ||
54 | else | ||
55 | dma_s_cfg_reg |= DMA_PACK_PATTERN_RGB; | ||
56 | |||
57 | if (outBpp == 4) | ||
58 | dma_s_cfg_reg |= DMA_IBUF_C3ALPHA_EN; | ||
59 | |||
60 | if (outBpp == 2) | ||
61 | dma_s_cfg_reg |= DMA_IBUF_FORMAT_RGB565; | ||
62 | |||
63 | if (mfd->panel_info.pdest != DISPLAY_2) { | ||
64 | printk(KERN_ERR "error: non-secondary type through dma_s!\n"); | ||
65 | return; | ||
66 | } | ||
67 | |||
68 | if (mfd->panel_info.type == MDDI_PANEL) { | ||
69 | dma_s_cfg_reg |= DMA_OUT_SEL_MDDI; | ||
70 | mddi_dest = TRUE; | ||
71 | } else { | ||
72 | dma_s_cfg_reg |= DMA_AHBM_LCD_SEL_SECONDARY; | ||
73 | outp32(MDP_EBI2_LCD1, mfd->data_port_phys); | ||
74 | } | ||
75 | |||
76 | dma_s_cfg_reg |= DMA_DITHER_EN; | ||
77 | |||
78 | src = (uint8 *) iBuf->buf; | ||
79 | /* starting input address */ | ||
80 | src += (iBuf->dma_x + iBuf->dma_y * iBuf->ibuf_width) * outBpp; | ||
81 | |||
82 | /* MDP cmd block enable */ | ||
83 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); | ||
84 | /* PIXELSIZE */ | ||
85 | MDP_OUTP(MDP_BASE + 0xa0004, (iBuf->dma_h << 16 | iBuf->dma_w)); | ||
86 | MDP_OUTP(MDP_BASE + 0xa0008, src); /* ibuf address */ | ||
87 | MDP_OUTP(MDP_BASE + 0xa000c, iBuf->ibuf_width * outBpp);/* ystride */ | ||
88 | |||
89 | if (mfd->panel_info.bpp == 18) { | ||
90 | dma_s_cfg_reg |= DMA_DSTC0G_6BITS | /* 666 18BPP */ | ||
91 | DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS; | ||
92 | } else { | ||
93 | dma_s_cfg_reg |= DMA_DSTC0G_6BITS | /* 565 16BPP */ | ||
94 | DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS; | ||
95 | } | ||
96 | |||
97 | if (mddi_dest) { | ||
98 | MDP_OUTP(MDP_BASE + 0xa0010, (iBuf->dma_y << 16) | iBuf->dma_x); | ||
99 | MDP_OUTP(MDP_BASE + 0x00090, 1); | ||
100 | MDP_OUTP(MDP_BASE + 0x00094, | ||
101 | (MDDI_VDO_PACKET_DESC << 16) | | ||
102 | mfd->panel_info.mddi.vdopkt); | ||
103 | } else { | ||
104 | /* setting LCDC write window */ | ||
105 | pdata->set_rect(iBuf->dma_x, iBuf->dma_y, iBuf->dma_w, | ||
106 | iBuf->dma_h); | ||
107 | } | ||
108 | |||
109 | MDP_OUTP(MDP_BASE + 0xa0000, dma_s_cfg_reg); | ||
110 | |||
111 | /* MDP cmd block disable */ | ||
112 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); | ||
113 | mdp_pipe_kickoff(MDP_DMA_S_TERM, mfd); | ||
114 | } | ||
115 | |||
116 | void mdp_dma_s_update(struct msm_fb_data_type *mfd) | ||
117 | { | ||
118 | down(&mfd->dma->mutex); | ||
119 | if ((mfd) && (!mfd->dma->busy) && (mfd->panel_power_on)) { | ||
120 | down(&mfd->sem); | ||
121 | mdp_enable_irq(MDP_DMA_S_TERM); | ||
122 | mfd->dma->busy = TRUE; | ||
123 | INIT_COMPLETION(mfd->dma->comp); | ||
124 | mfd->ibuf_flushed = TRUE; | ||
125 | mdp_dma_s_update_lcd(mfd); | ||
126 | up(&mfd->sem); | ||
127 | |||
128 | /* wait until DMA finishes the current job */ | ||
129 | wait_for_completion_killable(&mfd->dma->comp); | ||
130 | mdp_disable_irq(MDP_DMA_S_TERM); | ||
131 | |||
132 | /* signal if pan function is waiting for the update completion */ | ||
133 | if (mfd->pan_waiting) { | ||
134 | mfd->pan_waiting = FALSE; | ||
135 | complete(&mfd->pan_comp); | ||
136 | } | ||
137 | } | ||
138 | up(&mfd->dma->mutex); | ||
139 | } | ||
diff --git a/drivers/staging/msm/mdp_dma_tv.c b/drivers/staging/msm/mdp_dma_tv.c new file mode 100644 index 000000000000..70989fb32c1d --- /dev/null +++ b/drivers/staging/msm/mdp_dma_tv.c | |||
@@ -0,0 +1,142 @@ | |||
1 | /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/sched.h> | ||
21 | #include <linux/time.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/hrtimer.h> | ||
25 | #include <linux/delay.h> | ||
26 | |||
27 | #include <mach/hardware.h> | ||
28 | #include <linux/io.h> | ||
29 | |||
30 | #include <asm/system.h> | ||
31 | #include <asm/mach-types.h> | ||
32 | #include <linux/semaphore.h> | ||
33 | #include <linux/spinlock.h> | ||
34 | |||
35 | #include <linux/fb.h> | ||
36 | |||
37 | #include "mdp.h" | ||
38 | #include "msm_fb.h" | ||
39 | |||
40 | extern spinlock_t mdp_spin_lock; | ||
41 | extern uint32 mdp_intr_mask; | ||
42 | |||
43 | int mdp_dma3_on(struct platform_device *pdev) | ||
44 | { | ||
45 | struct msm_fb_data_type *mfd; | ||
46 | struct fb_info *fbi; | ||
47 | uint8 *buf; | ||
48 | int bpp; | ||
49 | int ret = 0; | ||
50 | |||
51 | mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev); | ||
52 | |||
53 | if (!mfd) | ||
54 | return -ENODEV; | ||
55 | |||
56 | if (mfd->key != MFD_KEY) | ||
57 | return -EINVAL; | ||
58 | |||
59 | fbi = mfd->fbi; | ||
60 | /* MDP cmd block enable */ | ||
61 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); | ||
62 | |||
63 | bpp = fbi->var.bits_per_pixel / 8; | ||
64 | buf = (uint8 *) fbi->fix.smem_start; | ||
65 | buf += fbi->var.xoffset * bpp + | ||
66 | fbi->var.yoffset * fbi->fix.line_length; | ||
67 | |||
68 | /* starting address[31..8] of Video frame buffer is CS0 */ | ||
69 | MDP_OUTP(MDP_BASE + 0xC0008, (uint32) buf >> 3); | ||
70 | |||
71 | mdp_pipe_ctrl(MDP_DMA3_BLOCK, MDP_BLOCK_POWER_ON, FALSE); | ||
72 | |||
73 | MDP_OUTP(MDP_BASE + 0xC0004, 0x4c60674); /* flicker filter enabled */ | ||
74 | MDP_OUTP(MDP_BASE + 0xC0010, 0x20); /* sobel treshold */ | ||
75 | |||
76 | MDP_OUTP(MDP_BASE + 0xC0018, 0xeb0010); /* Y Max, Y min */ | ||
77 | MDP_OUTP(MDP_BASE + 0xC001C, 0xf00010); /* Cb Max, Cb min */ | ||
78 | MDP_OUTP(MDP_BASE + 0xC0020, 0xf00010); /* Cb Max, Cb min */ | ||
79 | |||
80 | MDP_OUTP(MDP_BASE + 0xC000C, 0x67686970); /* add a few chars for CC */ | ||
81 | MDP_OUTP(MDP_BASE + 0xC0000, 0x1); /* MDP tv out enable */ | ||
82 | |||
83 | /* MDP cmd block disable */ | ||
84 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); | ||
85 | |||
86 | ret = panel_next_on(pdev); | ||
87 | |||
88 | return ret; | ||
89 | } | ||
90 | |||
91 | int mdp_dma3_off(struct platform_device *pdev) | ||
92 | { | ||
93 | int ret = 0; | ||
94 | |||
95 | ret = panel_next_off(pdev); | ||
96 | if (ret) | ||
97 | return ret; | ||
98 | |||
99 | /* MDP cmd block enable */ | ||
100 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); | ||
101 | MDP_OUTP(MDP_BASE + 0xC0000, 0x0); | ||
102 | /* MDP cmd block disable */ | ||
103 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); | ||
104 | |||
105 | mdp_pipe_ctrl(MDP_DMA3_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); | ||
106 | |||
107 | /* delay to make sure the last frame finishes */ | ||
108 | mdelay(100); | ||
109 | |||
110 | return ret; | ||
111 | } | ||
112 | |||
113 | void mdp_dma3_update(struct msm_fb_data_type *mfd) | ||
114 | { | ||
115 | struct fb_info *fbi = mfd->fbi; | ||
116 | uint8 *buf; | ||
117 | int bpp; | ||
118 | unsigned long flag; | ||
119 | |||
120 | if (!mfd->panel_power_on) | ||
121 | return; | ||
122 | |||
123 | /* no need to power on cmd block since dma3 is running */ | ||
124 | bpp = fbi->var.bits_per_pixel / 8; | ||
125 | buf = (uint8 *) fbi->fix.smem_start; | ||
126 | buf += fbi->var.xoffset * bpp + | ||
127 | fbi->var.yoffset * fbi->fix.line_length; | ||
128 | MDP_OUTP(MDP_BASE + 0xC0008, (uint32) buf >> 3); | ||
129 | |||
130 | spin_lock_irqsave(&mdp_spin_lock, flag); | ||
131 | mdp_enable_irq(MDP_DMA3_TERM); | ||
132 | INIT_COMPLETION(mfd->dma->comp); | ||
133 | mfd->dma->waiting = TRUE; | ||
134 | |||
135 | outp32(MDP_INTR_CLEAR, TV_OUT_DMA3_START); | ||
136 | mdp_intr_mask |= TV_OUT_DMA3_START; | ||
137 | outp32(MDP_INTR_ENABLE, mdp_intr_mask); | ||
138 | spin_unlock_irqrestore(&mdp_spin_lock, flag); | ||
139 | |||
140 | wait_for_completion_killable(&mfd->dma->comp); | ||
141 | mdp_disable_irq(MDP_DMA3_TERM); | ||
142 | } | ||
diff --git a/drivers/staging/msm/mdp_hw_init.c b/drivers/staging/msm/mdp_hw_init.c new file mode 100644 index 000000000000..807362ac592c --- /dev/null +++ b/drivers/staging/msm/mdp_hw_init.c | |||
@@ -0,0 +1,720 @@ | |||
1 | /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include "mdp.h" | ||
19 | |||
20 | /* mdp primary csc limit vector */ | ||
21 | uint32 mdp_plv[] = { 0x10, 0xeb, 0x10, 0xf0 }; | ||
22 | |||
23 | /* Color Coefficient matrix for YUV -> RGB */ | ||
24 | struct mdp_ccs mdp_ccs_yuv2rgb = { | ||
25 | MDP_CCS_YUV2RGB, | ||
26 | { | ||
27 | 0x254, | ||
28 | 0x000, | ||
29 | 0x331, | ||
30 | 0x254, | ||
31 | 0xff38, | ||
32 | 0xfe61, | ||
33 | 0x254, | ||
34 | 0x409, | ||
35 | 0x000, | ||
36 | }, | ||
37 | { | ||
38 | #ifdef CONFIG_FB_MSM_MDP31 | ||
39 | 0x1f0, | ||
40 | 0x180, | ||
41 | 0x180 | ||
42 | #else | ||
43 | 0x10, | ||
44 | 0x80, | ||
45 | 0x80 | ||
46 | #endif | ||
47 | } | ||
48 | }; | ||
49 | |||
50 | /* Color Coefficient matrix for RGB -> YUV */ | ||
51 | struct mdp_ccs mdp_ccs_rgb2yuv = { | ||
52 | MDP_CCS_RGB2YUV, | ||
53 | { | ||
54 | 0x83, | ||
55 | 0x102, | ||
56 | 0x32, | ||
57 | 0xffb5, | ||
58 | 0xff6c, | ||
59 | 0xe1, | ||
60 | 0xe1, | ||
61 | 0xff45, | ||
62 | 0xffdc, | ||
63 | }, | ||
64 | #ifdef CONFIG_FB_MSM_MDP31 | ||
65 | { | ||
66 | 0x10, | ||
67 | 0x80, | ||
68 | 0x80 | ||
69 | } | ||
70 | #endif | ||
71 | }; | ||
72 | |||
73 | static void mdp_load_lut_param(void) | ||
74 | { | ||
75 | outpdw(MDP_BASE + 0x40800, 0x0); | ||
76 | outpdw(MDP_BASE + 0x40804, 0x151515); | ||
77 | outpdw(MDP_BASE + 0x40808, 0x1d1d1d); | ||
78 | outpdw(MDP_BASE + 0x4080c, 0x232323); | ||
79 | outpdw(MDP_BASE + 0x40810, 0x272727); | ||
80 | outpdw(MDP_BASE + 0x40814, 0x2b2b2b); | ||
81 | outpdw(MDP_BASE + 0x40818, 0x2f2f2f); | ||
82 | outpdw(MDP_BASE + 0x4081c, 0x333333); | ||
83 | outpdw(MDP_BASE + 0x40820, 0x363636); | ||
84 | outpdw(MDP_BASE + 0x40824, 0x393939); | ||
85 | outpdw(MDP_BASE + 0x40828, 0x3b3b3b); | ||
86 | outpdw(MDP_BASE + 0x4082c, 0x3e3e3e); | ||
87 | outpdw(MDP_BASE + 0x40830, 0x404040); | ||
88 | outpdw(MDP_BASE + 0x40834, 0x434343); | ||
89 | outpdw(MDP_BASE + 0x40838, 0x454545); | ||
90 | outpdw(MDP_BASE + 0x4083c, 0x474747); | ||
91 | outpdw(MDP_BASE + 0x40840, 0x494949); | ||
92 | outpdw(MDP_BASE + 0x40844, 0x4b4b4b); | ||
93 | outpdw(MDP_BASE + 0x40848, 0x4d4d4d); | ||
94 | outpdw(MDP_BASE + 0x4084c, 0x4f4f4f); | ||
95 | outpdw(MDP_BASE + 0x40850, 0x515151); | ||
96 | outpdw(MDP_BASE + 0x40854, 0x535353); | ||
97 | outpdw(MDP_BASE + 0x40858, 0x555555); | ||
98 | outpdw(MDP_BASE + 0x4085c, 0x565656); | ||
99 | outpdw(MDP_BASE + 0x40860, 0x585858); | ||
100 | outpdw(MDP_BASE + 0x40864, 0x5a5a5a); | ||
101 | outpdw(MDP_BASE + 0x40868, 0x5b5b5b); | ||
102 | outpdw(MDP_BASE + 0x4086c, 0x5d5d5d); | ||
103 | outpdw(MDP_BASE + 0x40870, 0x5e5e5e); | ||
104 | outpdw(MDP_BASE + 0x40874, 0x606060); | ||
105 | outpdw(MDP_BASE + 0x40878, 0x616161); | ||
106 | outpdw(MDP_BASE + 0x4087c, 0x636363); | ||
107 | outpdw(MDP_BASE + 0x40880, 0x646464); | ||
108 | outpdw(MDP_BASE + 0x40884, 0x666666); | ||
109 | outpdw(MDP_BASE + 0x40888, 0x676767); | ||
110 | outpdw(MDP_BASE + 0x4088c, 0x686868); | ||
111 | outpdw(MDP_BASE + 0x40890, 0x6a6a6a); | ||
112 | outpdw(MDP_BASE + 0x40894, 0x6b6b6b); | ||
113 | outpdw(MDP_BASE + 0x40898, 0x6c6c6c); | ||
114 | outpdw(MDP_BASE + 0x4089c, 0x6e6e6e); | ||
115 | outpdw(MDP_BASE + 0x408a0, 0x6f6f6f); | ||
116 | outpdw(MDP_BASE + 0x408a4, 0x707070); | ||
117 | outpdw(MDP_BASE + 0x408a8, 0x717171); | ||
118 | outpdw(MDP_BASE + 0x408ac, 0x727272); | ||
119 | outpdw(MDP_BASE + 0x408b0, 0x747474); | ||
120 | outpdw(MDP_BASE + 0x408b4, 0x757575); | ||
121 | outpdw(MDP_BASE + 0x408b8, 0x767676); | ||
122 | outpdw(MDP_BASE + 0x408bc, 0x777777); | ||
123 | outpdw(MDP_BASE + 0x408c0, 0x787878); | ||
124 | outpdw(MDP_BASE + 0x408c4, 0x797979); | ||
125 | outpdw(MDP_BASE + 0x408c8, 0x7a7a7a); | ||
126 | outpdw(MDP_BASE + 0x408cc, 0x7c7c7c); | ||
127 | outpdw(MDP_BASE + 0x408d0, 0x7d7d7d); | ||
128 | outpdw(MDP_BASE + 0x408d4, 0x7e7e7e); | ||
129 | outpdw(MDP_BASE + 0x408d8, 0x7f7f7f); | ||
130 | outpdw(MDP_BASE + 0x408dc, 0x808080); | ||
131 | outpdw(MDP_BASE + 0x408e0, 0x818181); | ||
132 | outpdw(MDP_BASE + 0x408e4, 0x828282); | ||
133 | outpdw(MDP_BASE + 0x408e8, 0x838383); | ||
134 | outpdw(MDP_BASE + 0x408ec, 0x848484); | ||
135 | outpdw(MDP_BASE + 0x408f0, 0x858585); | ||
136 | outpdw(MDP_BASE + 0x408f4, 0x868686); | ||
137 | outpdw(MDP_BASE + 0x408f8, 0x878787); | ||
138 | outpdw(MDP_BASE + 0x408fc, 0x888888); | ||
139 | outpdw(MDP_BASE + 0x40900, 0x898989); | ||
140 | outpdw(MDP_BASE + 0x40904, 0x8a8a8a); | ||
141 | outpdw(MDP_BASE + 0x40908, 0x8b8b8b); | ||
142 | outpdw(MDP_BASE + 0x4090c, 0x8c8c8c); | ||
143 | outpdw(MDP_BASE + 0x40910, 0x8d8d8d); | ||
144 | outpdw(MDP_BASE + 0x40914, 0x8e8e8e); | ||
145 | outpdw(MDP_BASE + 0x40918, 0x8f8f8f); | ||
146 | outpdw(MDP_BASE + 0x4091c, 0x8f8f8f); | ||
147 | outpdw(MDP_BASE + 0x40920, 0x909090); | ||
148 | outpdw(MDP_BASE + 0x40924, 0x919191); | ||
149 | outpdw(MDP_BASE + 0x40928, 0x929292); | ||
150 | outpdw(MDP_BASE + 0x4092c, 0x939393); | ||
151 | outpdw(MDP_BASE + 0x40930, 0x949494); | ||
152 | outpdw(MDP_BASE + 0x40934, 0x959595); | ||
153 | outpdw(MDP_BASE + 0x40938, 0x969696); | ||
154 | outpdw(MDP_BASE + 0x4093c, 0x969696); | ||
155 | outpdw(MDP_BASE + 0x40940, 0x979797); | ||
156 | outpdw(MDP_BASE + 0x40944, 0x989898); | ||
157 | outpdw(MDP_BASE + 0x40948, 0x999999); | ||
158 | outpdw(MDP_BASE + 0x4094c, 0x9a9a9a); | ||
159 | outpdw(MDP_BASE + 0x40950, 0x9b9b9b); | ||
160 | outpdw(MDP_BASE + 0x40954, 0x9c9c9c); | ||
161 | outpdw(MDP_BASE + 0x40958, 0x9c9c9c); | ||
162 | outpdw(MDP_BASE + 0x4095c, 0x9d9d9d); | ||
163 | outpdw(MDP_BASE + 0x40960, 0x9e9e9e); | ||
164 | outpdw(MDP_BASE + 0x40964, 0x9f9f9f); | ||
165 | outpdw(MDP_BASE + 0x40968, 0xa0a0a0); | ||
166 | outpdw(MDP_BASE + 0x4096c, 0xa0a0a0); | ||
167 | outpdw(MDP_BASE + 0x40970, 0xa1a1a1); | ||
168 | outpdw(MDP_BASE + 0x40974, 0xa2a2a2); | ||
169 | outpdw(MDP_BASE + 0x40978, 0xa3a3a3); | ||
170 | outpdw(MDP_BASE + 0x4097c, 0xa4a4a4); | ||
171 | outpdw(MDP_BASE + 0x40980, 0xa4a4a4); | ||
172 | outpdw(MDP_BASE + 0x40984, 0xa5a5a5); | ||
173 | outpdw(MDP_BASE + 0x40988, 0xa6a6a6); | ||
174 | outpdw(MDP_BASE + 0x4098c, 0xa7a7a7); | ||
175 | outpdw(MDP_BASE + 0x40990, 0xa7a7a7); | ||
176 | outpdw(MDP_BASE + 0x40994, 0xa8a8a8); | ||
177 | outpdw(MDP_BASE + 0x40998, 0xa9a9a9); | ||
178 | outpdw(MDP_BASE + 0x4099c, 0xaaaaaa); | ||
179 | outpdw(MDP_BASE + 0x409a0, 0xaaaaaa); | ||
180 | outpdw(MDP_BASE + 0x409a4, 0xababab); | ||
181 | outpdw(MDP_BASE + 0x409a8, 0xacacac); | ||
182 | outpdw(MDP_BASE + 0x409ac, 0xadadad); | ||
183 | outpdw(MDP_BASE + 0x409b0, 0xadadad); | ||
184 | outpdw(MDP_BASE + 0x409b4, 0xaeaeae); | ||
185 | outpdw(MDP_BASE + 0x409b8, 0xafafaf); | ||
186 | outpdw(MDP_BASE + 0x409bc, 0xafafaf); | ||
187 | outpdw(MDP_BASE + 0x409c0, 0xb0b0b0); | ||
188 | outpdw(MDP_BASE + 0x409c4, 0xb1b1b1); | ||
189 | outpdw(MDP_BASE + 0x409c8, 0xb2b2b2); | ||
190 | outpdw(MDP_BASE + 0x409cc, 0xb2b2b2); | ||
191 | outpdw(MDP_BASE + 0x409d0, 0xb3b3b3); | ||
192 | outpdw(MDP_BASE + 0x409d4, 0xb4b4b4); | ||
193 | outpdw(MDP_BASE + 0x409d8, 0xb4b4b4); | ||
194 | outpdw(MDP_BASE + 0x409dc, 0xb5b5b5); | ||
195 | outpdw(MDP_BASE + 0x409e0, 0xb6b6b6); | ||
196 | outpdw(MDP_BASE + 0x409e4, 0xb6b6b6); | ||
197 | outpdw(MDP_BASE + 0x409e8, 0xb7b7b7); | ||
198 | outpdw(MDP_BASE + 0x409ec, 0xb8b8b8); | ||
199 | outpdw(MDP_BASE + 0x409f0, 0xb8b8b8); | ||
200 | outpdw(MDP_BASE + 0x409f4, 0xb9b9b9); | ||
201 | outpdw(MDP_BASE + 0x409f8, 0xbababa); | ||
202 | outpdw(MDP_BASE + 0x409fc, 0xbababa); | ||
203 | outpdw(MDP_BASE + 0x40a00, 0xbbbbbb); | ||
204 | outpdw(MDP_BASE + 0x40a04, 0xbcbcbc); | ||
205 | outpdw(MDP_BASE + 0x40a08, 0xbcbcbc); | ||
206 | outpdw(MDP_BASE + 0x40a0c, 0xbdbdbd); | ||
207 | outpdw(MDP_BASE + 0x40a10, 0xbebebe); | ||
208 | outpdw(MDP_BASE + 0x40a14, 0xbebebe); | ||
209 | outpdw(MDP_BASE + 0x40a18, 0xbfbfbf); | ||
210 | outpdw(MDP_BASE + 0x40a1c, 0xc0c0c0); | ||
211 | outpdw(MDP_BASE + 0x40a20, 0xc0c0c0); | ||
212 | outpdw(MDP_BASE + 0x40a24, 0xc1c1c1); | ||
213 | outpdw(MDP_BASE + 0x40a28, 0xc1c1c1); | ||
214 | outpdw(MDP_BASE + 0x40a2c, 0xc2c2c2); | ||
215 | outpdw(MDP_BASE + 0x40a30, 0xc3c3c3); | ||
216 | outpdw(MDP_BASE + 0x40a34, 0xc3c3c3); | ||
217 | outpdw(MDP_BASE + 0x40a38, 0xc4c4c4); | ||
218 | outpdw(MDP_BASE + 0x40a3c, 0xc5c5c5); | ||
219 | outpdw(MDP_BASE + 0x40a40, 0xc5c5c5); | ||
220 | outpdw(MDP_BASE + 0x40a44, 0xc6c6c6); | ||
221 | outpdw(MDP_BASE + 0x40a48, 0xc6c6c6); | ||
222 | outpdw(MDP_BASE + 0x40a4c, 0xc7c7c7); | ||
223 | outpdw(MDP_BASE + 0x40a50, 0xc8c8c8); | ||
224 | outpdw(MDP_BASE + 0x40a54, 0xc8c8c8); | ||
225 | outpdw(MDP_BASE + 0x40a58, 0xc9c9c9); | ||
226 | outpdw(MDP_BASE + 0x40a5c, 0xc9c9c9); | ||
227 | outpdw(MDP_BASE + 0x40a60, 0xcacaca); | ||
228 | outpdw(MDP_BASE + 0x40a64, 0xcbcbcb); | ||
229 | outpdw(MDP_BASE + 0x40a68, 0xcbcbcb); | ||
230 | outpdw(MDP_BASE + 0x40a6c, 0xcccccc); | ||
231 | outpdw(MDP_BASE + 0x40a70, 0xcccccc); | ||
232 | outpdw(MDP_BASE + 0x40a74, 0xcdcdcd); | ||
233 | outpdw(MDP_BASE + 0x40a78, 0xcecece); | ||
234 | outpdw(MDP_BASE + 0x40a7c, 0xcecece); | ||
235 | outpdw(MDP_BASE + 0x40a80, 0xcfcfcf); | ||
236 | outpdw(MDP_BASE + 0x40a84, 0xcfcfcf); | ||
237 | outpdw(MDP_BASE + 0x40a88, 0xd0d0d0); | ||
238 | outpdw(MDP_BASE + 0x40a8c, 0xd0d0d0); | ||
239 | outpdw(MDP_BASE + 0x40a90, 0xd1d1d1); | ||
240 | outpdw(MDP_BASE + 0x40a94, 0xd2d2d2); | ||
241 | outpdw(MDP_BASE + 0x40a98, 0xd2d2d2); | ||
242 | outpdw(MDP_BASE + 0x40a9c, 0xd3d3d3); | ||
243 | outpdw(MDP_BASE + 0x40aa0, 0xd3d3d3); | ||
244 | outpdw(MDP_BASE + 0x40aa4, 0xd4d4d4); | ||
245 | outpdw(MDP_BASE + 0x40aa8, 0xd4d4d4); | ||
246 | outpdw(MDP_BASE + 0x40aac, 0xd5d5d5); | ||
247 | outpdw(MDP_BASE + 0x40ab0, 0xd6d6d6); | ||
248 | outpdw(MDP_BASE + 0x40ab4, 0xd6d6d6); | ||
249 | outpdw(MDP_BASE + 0x40ab8, 0xd7d7d7); | ||
250 | outpdw(MDP_BASE + 0x40abc, 0xd7d7d7); | ||
251 | outpdw(MDP_BASE + 0x40ac0, 0xd8d8d8); | ||
252 | outpdw(MDP_BASE + 0x40ac4, 0xd8d8d8); | ||
253 | outpdw(MDP_BASE + 0x40ac8, 0xd9d9d9); | ||
254 | outpdw(MDP_BASE + 0x40acc, 0xd9d9d9); | ||
255 | outpdw(MDP_BASE + 0x40ad0, 0xdadada); | ||
256 | outpdw(MDP_BASE + 0x40ad4, 0xdbdbdb); | ||
257 | outpdw(MDP_BASE + 0x40ad8, 0xdbdbdb); | ||
258 | outpdw(MDP_BASE + 0x40adc, 0xdcdcdc); | ||
259 | outpdw(MDP_BASE + 0x40ae0, 0xdcdcdc); | ||
260 | outpdw(MDP_BASE + 0x40ae4, 0xdddddd); | ||
261 | outpdw(MDP_BASE + 0x40ae8, 0xdddddd); | ||
262 | outpdw(MDP_BASE + 0x40aec, 0xdedede); | ||
263 | outpdw(MDP_BASE + 0x40af0, 0xdedede); | ||
264 | outpdw(MDP_BASE + 0x40af4, 0xdfdfdf); | ||
265 | outpdw(MDP_BASE + 0x40af8, 0xdfdfdf); | ||
266 | outpdw(MDP_BASE + 0x40afc, 0xe0e0e0); | ||
267 | outpdw(MDP_BASE + 0x40b00, 0xe0e0e0); | ||
268 | outpdw(MDP_BASE + 0x40b04, 0xe1e1e1); | ||
269 | outpdw(MDP_BASE + 0x40b08, 0xe1e1e1); | ||
270 | outpdw(MDP_BASE + 0x40b0c, 0xe2e2e2); | ||
271 | outpdw(MDP_BASE + 0x40b10, 0xe3e3e3); | ||
272 | outpdw(MDP_BASE + 0x40b14, 0xe3e3e3); | ||
273 | outpdw(MDP_BASE + 0x40b18, 0xe4e4e4); | ||
274 | outpdw(MDP_BASE + 0x40b1c, 0xe4e4e4); | ||
275 | outpdw(MDP_BASE + 0x40b20, 0xe5e5e5); | ||
276 | outpdw(MDP_BASE + 0x40b24, 0xe5e5e5); | ||
277 | outpdw(MDP_BASE + 0x40b28, 0xe6e6e6); | ||
278 | outpdw(MDP_BASE + 0x40b2c, 0xe6e6e6); | ||
279 | outpdw(MDP_BASE + 0x40b30, 0xe7e7e7); | ||
280 | outpdw(MDP_BASE + 0x40b34, 0xe7e7e7); | ||
281 | outpdw(MDP_BASE + 0x40b38, 0xe8e8e8); | ||
282 | outpdw(MDP_BASE + 0x40b3c, 0xe8e8e8); | ||
283 | outpdw(MDP_BASE + 0x40b40, 0xe9e9e9); | ||
284 | outpdw(MDP_BASE + 0x40b44, 0xe9e9e9); | ||
285 | outpdw(MDP_BASE + 0x40b48, 0xeaeaea); | ||
286 | outpdw(MDP_BASE + 0x40b4c, 0xeaeaea); | ||
287 | outpdw(MDP_BASE + 0x40b50, 0xebebeb); | ||
288 | outpdw(MDP_BASE + 0x40b54, 0xebebeb); | ||
289 | outpdw(MDP_BASE + 0x40b58, 0xececec); | ||
290 | outpdw(MDP_BASE + 0x40b5c, 0xececec); | ||
291 | outpdw(MDP_BASE + 0x40b60, 0xededed); | ||
292 | outpdw(MDP_BASE + 0x40b64, 0xededed); | ||
293 | outpdw(MDP_BASE + 0x40b68, 0xeeeeee); | ||
294 | outpdw(MDP_BASE + 0x40b6c, 0xeeeeee); | ||
295 | outpdw(MDP_BASE + 0x40b70, 0xefefef); | ||
296 | outpdw(MDP_BASE + 0x40b74, 0xefefef); | ||
297 | outpdw(MDP_BASE + 0x40b78, 0xf0f0f0); | ||
298 | outpdw(MDP_BASE + 0x40b7c, 0xf0f0f0); | ||
299 | outpdw(MDP_BASE + 0x40b80, 0xf1f1f1); | ||
300 | outpdw(MDP_BASE + 0x40b84, 0xf1f1f1); | ||
301 | outpdw(MDP_BASE + 0x40b88, 0xf2f2f2); | ||
302 | outpdw(MDP_BASE + 0x40b8c, 0xf2f2f2); | ||
303 | outpdw(MDP_BASE + 0x40b90, 0xf2f2f2); | ||
304 | outpdw(MDP_BASE + 0x40b94, 0xf3f3f3); | ||
305 | outpdw(MDP_BASE + 0x40b98, 0xf3f3f3); | ||
306 | outpdw(MDP_BASE + 0x40b9c, 0xf4f4f4); | ||
307 | outpdw(MDP_BASE + 0x40ba0, 0xf4f4f4); | ||
308 | outpdw(MDP_BASE + 0x40ba4, 0xf5f5f5); | ||
309 | outpdw(MDP_BASE + 0x40ba8, 0xf5f5f5); | ||
310 | outpdw(MDP_BASE + 0x40bac, 0xf6f6f6); | ||
311 | outpdw(MDP_BASE + 0x40bb0, 0xf6f6f6); | ||
312 | outpdw(MDP_BASE + 0x40bb4, 0xf7f7f7); | ||
313 | outpdw(MDP_BASE + 0x40bb8, 0xf7f7f7); | ||
314 | outpdw(MDP_BASE + 0x40bbc, 0xf8f8f8); | ||
315 | outpdw(MDP_BASE + 0x40bc0, 0xf8f8f8); | ||
316 | outpdw(MDP_BASE + 0x40bc4, 0xf9f9f9); | ||
317 | outpdw(MDP_BASE + 0x40bc8, 0xf9f9f9); | ||
318 | outpdw(MDP_BASE + 0x40bcc, 0xfafafa); | ||
319 | outpdw(MDP_BASE + 0x40bd0, 0xfafafa); | ||
320 | outpdw(MDP_BASE + 0x40bd4, 0xfafafa); | ||
321 | outpdw(MDP_BASE + 0x40bd8, 0xfbfbfb); | ||
322 | outpdw(MDP_BASE + 0x40bdc, 0xfbfbfb); | ||
323 | outpdw(MDP_BASE + 0x40be0, 0xfcfcfc); | ||
324 | outpdw(MDP_BASE + 0x40be4, 0xfcfcfc); | ||
325 | outpdw(MDP_BASE + 0x40be8, 0xfdfdfd); | ||
326 | outpdw(MDP_BASE + 0x40bec, 0xfdfdfd); | ||
327 | outpdw(MDP_BASE + 0x40bf0, 0xfefefe); | ||
328 | outpdw(MDP_BASE + 0x40bf4, 0xfefefe); | ||
329 | outpdw(MDP_BASE + 0x40bf8, 0xffffff); | ||
330 | outpdw(MDP_BASE + 0x40bfc, 0xffffff); | ||
331 | outpdw(MDP_BASE + 0x40c00, 0x0); | ||
332 | outpdw(MDP_BASE + 0x40c04, 0x0); | ||
333 | outpdw(MDP_BASE + 0x40c08, 0x0); | ||
334 | outpdw(MDP_BASE + 0x40c0c, 0x0); | ||
335 | outpdw(MDP_BASE + 0x40c10, 0x0); | ||
336 | outpdw(MDP_BASE + 0x40c14, 0x0); | ||
337 | outpdw(MDP_BASE + 0x40c18, 0x0); | ||
338 | outpdw(MDP_BASE + 0x40c1c, 0x0); | ||
339 | outpdw(MDP_BASE + 0x40c20, 0x0); | ||
340 | outpdw(MDP_BASE + 0x40c24, 0x0); | ||
341 | outpdw(MDP_BASE + 0x40c28, 0x0); | ||
342 | outpdw(MDP_BASE + 0x40c2c, 0x0); | ||
343 | outpdw(MDP_BASE + 0x40c30, 0x0); | ||
344 | outpdw(MDP_BASE + 0x40c34, 0x0); | ||
345 | outpdw(MDP_BASE + 0x40c38, 0x0); | ||
346 | outpdw(MDP_BASE + 0x40c3c, 0x0); | ||
347 | outpdw(MDP_BASE + 0x40c40, 0x10101); | ||
348 | outpdw(MDP_BASE + 0x40c44, 0x10101); | ||
349 | outpdw(MDP_BASE + 0x40c48, 0x10101); | ||
350 | outpdw(MDP_BASE + 0x40c4c, 0x10101); | ||
351 | outpdw(MDP_BASE + 0x40c50, 0x10101); | ||
352 | outpdw(MDP_BASE + 0x40c54, 0x10101); | ||
353 | outpdw(MDP_BASE + 0x40c58, 0x10101); | ||
354 | outpdw(MDP_BASE + 0x40c5c, 0x10101); | ||
355 | outpdw(MDP_BASE + 0x40c60, 0x10101); | ||
356 | outpdw(MDP_BASE + 0x40c64, 0x10101); | ||
357 | outpdw(MDP_BASE + 0x40c68, 0x20202); | ||
358 | outpdw(MDP_BASE + 0x40c6c, 0x20202); | ||
359 | outpdw(MDP_BASE + 0x40c70, 0x20202); | ||
360 | outpdw(MDP_BASE + 0x40c74, 0x20202); | ||
361 | outpdw(MDP_BASE + 0x40c78, 0x20202); | ||
362 | outpdw(MDP_BASE + 0x40c7c, 0x20202); | ||
363 | outpdw(MDP_BASE + 0x40c80, 0x30303); | ||
364 | outpdw(MDP_BASE + 0x40c84, 0x30303); | ||
365 | outpdw(MDP_BASE + 0x40c88, 0x30303); | ||
366 | outpdw(MDP_BASE + 0x40c8c, 0x30303); | ||
367 | outpdw(MDP_BASE + 0x40c90, 0x30303); | ||
368 | outpdw(MDP_BASE + 0x40c94, 0x40404); | ||
369 | outpdw(MDP_BASE + 0x40c98, 0x40404); | ||
370 | outpdw(MDP_BASE + 0x40c9c, 0x40404); | ||
371 | outpdw(MDP_BASE + 0x40ca0, 0x40404); | ||
372 | outpdw(MDP_BASE + 0x40ca4, 0x40404); | ||
373 | outpdw(MDP_BASE + 0x40ca8, 0x50505); | ||
374 | outpdw(MDP_BASE + 0x40cac, 0x50505); | ||
375 | outpdw(MDP_BASE + 0x40cb0, 0x50505); | ||
376 | outpdw(MDP_BASE + 0x40cb4, 0x50505); | ||
377 | outpdw(MDP_BASE + 0x40cb8, 0x60606); | ||
378 | outpdw(MDP_BASE + 0x40cbc, 0x60606); | ||
379 | outpdw(MDP_BASE + 0x40cc0, 0x60606); | ||
380 | outpdw(MDP_BASE + 0x40cc4, 0x70707); | ||
381 | outpdw(MDP_BASE + 0x40cc8, 0x70707); | ||
382 | outpdw(MDP_BASE + 0x40ccc, 0x70707); | ||
383 | outpdw(MDP_BASE + 0x40cd0, 0x70707); | ||
384 | outpdw(MDP_BASE + 0x40cd4, 0x80808); | ||
385 | outpdw(MDP_BASE + 0x40cd8, 0x80808); | ||
386 | outpdw(MDP_BASE + 0x40cdc, 0x80808); | ||
387 | outpdw(MDP_BASE + 0x40ce0, 0x90909); | ||
388 | outpdw(MDP_BASE + 0x40ce4, 0x90909); | ||
389 | outpdw(MDP_BASE + 0x40ce8, 0xa0a0a); | ||
390 | outpdw(MDP_BASE + 0x40cec, 0xa0a0a); | ||
391 | outpdw(MDP_BASE + 0x40cf0, 0xa0a0a); | ||
392 | outpdw(MDP_BASE + 0x40cf4, 0xb0b0b); | ||
393 | outpdw(MDP_BASE + 0x40cf8, 0xb0b0b); | ||
394 | outpdw(MDP_BASE + 0x40cfc, 0xb0b0b); | ||
395 | outpdw(MDP_BASE + 0x40d00, 0xc0c0c); | ||
396 | outpdw(MDP_BASE + 0x40d04, 0xc0c0c); | ||
397 | outpdw(MDP_BASE + 0x40d08, 0xd0d0d); | ||
398 | outpdw(MDP_BASE + 0x40d0c, 0xd0d0d); | ||
399 | outpdw(MDP_BASE + 0x40d10, 0xe0e0e); | ||
400 | outpdw(MDP_BASE + 0x40d14, 0xe0e0e); | ||
401 | outpdw(MDP_BASE + 0x40d18, 0xe0e0e); | ||
402 | outpdw(MDP_BASE + 0x40d1c, 0xf0f0f); | ||
403 | outpdw(MDP_BASE + 0x40d20, 0xf0f0f); | ||
404 | outpdw(MDP_BASE + 0x40d24, 0x101010); | ||
405 | outpdw(MDP_BASE + 0x40d28, 0x101010); | ||
406 | outpdw(MDP_BASE + 0x40d2c, 0x111111); | ||
407 | outpdw(MDP_BASE + 0x40d30, 0x111111); | ||
408 | outpdw(MDP_BASE + 0x40d34, 0x121212); | ||
409 | outpdw(MDP_BASE + 0x40d38, 0x121212); | ||
410 | outpdw(MDP_BASE + 0x40d3c, 0x131313); | ||
411 | outpdw(MDP_BASE + 0x40d40, 0x131313); | ||
412 | outpdw(MDP_BASE + 0x40d44, 0x141414); | ||
413 | outpdw(MDP_BASE + 0x40d48, 0x151515); | ||
414 | outpdw(MDP_BASE + 0x40d4c, 0x151515); | ||
415 | outpdw(MDP_BASE + 0x40d50, 0x161616); | ||
416 | outpdw(MDP_BASE + 0x40d54, 0x161616); | ||
417 | outpdw(MDP_BASE + 0x40d58, 0x171717); | ||
418 | outpdw(MDP_BASE + 0x40d5c, 0x171717); | ||
419 | outpdw(MDP_BASE + 0x40d60, 0x181818); | ||
420 | outpdw(MDP_BASE + 0x40d64, 0x191919); | ||
421 | outpdw(MDP_BASE + 0x40d68, 0x191919); | ||
422 | outpdw(MDP_BASE + 0x40d6c, 0x1a1a1a); | ||
423 | outpdw(MDP_BASE + 0x40d70, 0x1b1b1b); | ||
424 | outpdw(MDP_BASE + 0x40d74, 0x1b1b1b); | ||
425 | outpdw(MDP_BASE + 0x40d78, 0x1c1c1c); | ||
426 | outpdw(MDP_BASE + 0x40d7c, 0x1c1c1c); | ||
427 | outpdw(MDP_BASE + 0x40d80, 0x1d1d1d); | ||
428 | outpdw(MDP_BASE + 0x40d84, 0x1e1e1e); | ||
429 | outpdw(MDP_BASE + 0x40d88, 0x1f1f1f); | ||
430 | outpdw(MDP_BASE + 0x40d8c, 0x1f1f1f); | ||
431 | outpdw(MDP_BASE + 0x40d90, 0x202020); | ||
432 | outpdw(MDP_BASE + 0x40d94, 0x212121); | ||
433 | outpdw(MDP_BASE + 0x40d98, 0x212121); | ||
434 | outpdw(MDP_BASE + 0x40d9c, 0x222222); | ||
435 | outpdw(MDP_BASE + 0x40da0, 0x232323); | ||
436 | outpdw(MDP_BASE + 0x40da4, 0x242424); | ||
437 | outpdw(MDP_BASE + 0x40da8, 0x242424); | ||
438 | outpdw(MDP_BASE + 0x40dac, 0x252525); | ||
439 | outpdw(MDP_BASE + 0x40db0, 0x262626); | ||
440 | outpdw(MDP_BASE + 0x40db4, 0x272727); | ||
441 | outpdw(MDP_BASE + 0x40db8, 0x272727); | ||
442 | outpdw(MDP_BASE + 0x40dbc, 0x282828); | ||
443 | outpdw(MDP_BASE + 0x40dc0, 0x292929); | ||
444 | outpdw(MDP_BASE + 0x40dc4, 0x2a2a2a); | ||
445 | outpdw(MDP_BASE + 0x40dc8, 0x2b2b2b); | ||
446 | outpdw(MDP_BASE + 0x40dcc, 0x2c2c2c); | ||
447 | outpdw(MDP_BASE + 0x40dd0, 0x2c2c2c); | ||
448 | outpdw(MDP_BASE + 0x40dd4, 0x2d2d2d); | ||
449 | outpdw(MDP_BASE + 0x40dd8, 0x2e2e2e); | ||
450 | outpdw(MDP_BASE + 0x40ddc, 0x2f2f2f); | ||
451 | outpdw(MDP_BASE + 0x40de0, 0x303030); | ||
452 | outpdw(MDP_BASE + 0x40de4, 0x313131); | ||
453 | outpdw(MDP_BASE + 0x40de8, 0x323232); | ||
454 | outpdw(MDP_BASE + 0x40dec, 0x333333); | ||
455 | outpdw(MDP_BASE + 0x40df0, 0x333333); | ||
456 | outpdw(MDP_BASE + 0x40df4, 0x343434); | ||
457 | outpdw(MDP_BASE + 0x40df8, 0x353535); | ||
458 | outpdw(MDP_BASE + 0x40dfc, 0x363636); | ||
459 | outpdw(MDP_BASE + 0x40e00, 0x373737); | ||
460 | outpdw(MDP_BASE + 0x40e04, 0x383838); | ||
461 | outpdw(MDP_BASE + 0x40e08, 0x393939); | ||
462 | outpdw(MDP_BASE + 0x40e0c, 0x3a3a3a); | ||
463 | outpdw(MDP_BASE + 0x40e10, 0x3b3b3b); | ||
464 | outpdw(MDP_BASE + 0x40e14, 0x3c3c3c); | ||
465 | outpdw(MDP_BASE + 0x40e18, 0x3d3d3d); | ||
466 | outpdw(MDP_BASE + 0x40e1c, 0x3e3e3e); | ||
467 | outpdw(MDP_BASE + 0x40e20, 0x3f3f3f); | ||
468 | outpdw(MDP_BASE + 0x40e24, 0x404040); | ||
469 | outpdw(MDP_BASE + 0x40e28, 0x414141); | ||
470 | outpdw(MDP_BASE + 0x40e2c, 0x424242); | ||
471 | outpdw(MDP_BASE + 0x40e30, 0x434343); | ||
472 | outpdw(MDP_BASE + 0x40e34, 0x444444); | ||
473 | outpdw(MDP_BASE + 0x40e38, 0x464646); | ||
474 | outpdw(MDP_BASE + 0x40e3c, 0x474747); | ||
475 | outpdw(MDP_BASE + 0x40e40, 0x484848); | ||
476 | outpdw(MDP_BASE + 0x40e44, 0x494949); | ||
477 | outpdw(MDP_BASE + 0x40e48, 0x4a4a4a); | ||
478 | outpdw(MDP_BASE + 0x40e4c, 0x4b4b4b); | ||
479 | outpdw(MDP_BASE + 0x40e50, 0x4c4c4c); | ||
480 | outpdw(MDP_BASE + 0x40e54, 0x4d4d4d); | ||
481 | outpdw(MDP_BASE + 0x40e58, 0x4f4f4f); | ||
482 | outpdw(MDP_BASE + 0x40e5c, 0x505050); | ||
483 | outpdw(MDP_BASE + 0x40e60, 0x515151); | ||
484 | outpdw(MDP_BASE + 0x40e64, 0x525252); | ||
485 | outpdw(MDP_BASE + 0x40e68, 0x535353); | ||
486 | outpdw(MDP_BASE + 0x40e6c, 0x545454); | ||
487 | outpdw(MDP_BASE + 0x40e70, 0x565656); | ||
488 | outpdw(MDP_BASE + 0x40e74, 0x575757); | ||
489 | outpdw(MDP_BASE + 0x40e78, 0x585858); | ||
490 | outpdw(MDP_BASE + 0x40e7c, 0x595959); | ||
491 | outpdw(MDP_BASE + 0x40e80, 0x5b5b5b); | ||
492 | outpdw(MDP_BASE + 0x40e84, 0x5c5c5c); | ||
493 | outpdw(MDP_BASE + 0x40e88, 0x5d5d5d); | ||
494 | outpdw(MDP_BASE + 0x40e8c, 0x5e5e5e); | ||
495 | outpdw(MDP_BASE + 0x40e90, 0x606060); | ||
496 | outpdw(MDP_BASE + 0x40e94, 0x616161); | ||
497 | outpdw(MDP_BASE + 0x40e98, 0x626262); | ||
498 | outpdw(MDP_BASE + 0x40e9c, 0x646464); | ||
499 | outpdw(MDP_BASE + 0x40ea0, 0x656565); | ||
500 | outpdw(MDP_BASE + 0x40ea4, 0x666666); | ||
501 | outpdw(MDP_BASE + 0x40ea8, 0x686868); | ||
502 | outpdw(MDP_BASE + 0x40eac, 0x696969); | ||
503 | outpdw(MDP_BASE + 0x40eb0, 0x6a6a6a); | ||
504 | outpdw(MDP_BASE + 0x40eb4, 0x6c6c6c); | ||
505 | outpdw(MDP_BASE + 0x40eb8, 0x6d6d6d); | ||
506 | outpdw(MDP_BASE + 0x40ebc, 0x6f6f6f); | ||
507 | outpdw(MDP_BASE + 0x40ec0, 0x707070); | ||
508 | outpdw(MDP_BASE + 0x40ec4, 0x717171); | ||
509 | outpdw(MDP_BASE + 0x40ec8, 0x737373); | ||
510 | outpdw(MDP_BASE + 0x40ecc, 0x747474); | ||
511 | outpdw(MDP_BASE + 0x40ed0, 0x767676); | ||
512 | outpdw(MDP_BASE + 0x40ed4, 0x777777); | ||
513 | outpdw(MDP_BASE + 0x40ed8, 0x797979); | ||
514 | outpdw(MDP_BASE + 0x40edc, 0x7a7a7a); | ||
515 | outpdw(MDP_BASE + 0x40ee0, 0x7c7c7c); | ||
516 | outpdw(MDP_BASE + 0x40ee4, 0x7d7d7d); | ||
517 | outpdw(MDP_BASE + 0x40ee8, 0x7f7f7f); | ||
518 | outpdw(MDP_BASE + 0x40eec, 0x808080); | ||
519 | outpdw(MDP_BASE + 0x40ef0, 0x828282); | ||
520 | outpdw(MDP_BASE + 0x40ef4, 0x838383); | ||
521 | outpdw(MDP_BASE + 0x40ef8, 0x858585); | ||
522 | outpdw(MDP_BASE + 0x40efc, 0x868686); | ||
523 | outpdw(MDP_BASE + 0x40f00, 0x888888); | ||
524 | outpdw(MDP_BASE + 0x40f04, 0x898989); | ||
525 | outpdw(MDP_BASE + 0x40f08, 0x8b8b8b); | ||
526 | outpdw(MDP_BASE + 0x40f0c, 0x8d8d8d); | ||
527 | outpdw(MDP_BASE + 0x40f10, 0x8e8e8e); | ||
528 | outpdw(MDP_BASE + 0x40f14, 0x909090); | ||
529 | outpdw(MDP_BASE + 0x40f18, 0x919191); | ||
530 | outpdw(MDP_BASE + 0x40f1c, 0x939393); | ||
531 | outpdw(MDP_BASE + 0x40f20, 0x959595); | ||
532 | outpdw(MDP_BASE + 0x40f24, 0x969696); | ||
533 | outpdw(MDP_BASE + 0x40f28, 0x989898); | ||
534 | outpdw(MDP_BASE + 0x40f2c, 0x9a9a9a); | ||
535 | outpdw(MDP_BASE + 0x40f30, 0x9b9b9b); | ||
536 | outpdw(MDP_BASE + 0x40f34, 0x9d9d9d); | ||
537 | outpdw(MDP_BASE + 0x40f38, 0x9f9f9f); | ||
538 | outpdw(MDP_BASE + 0x40f3c, 0xa1a1a1); | ||
539 | outpdw(MDP_BASE + 0x40f40, 0xa2a2a2); | ||
540 | outpdw(MDP_BASE + 0x40f44, 0xa4a4a4); | ||
541 | outpdw(MDP_BASE + 0x40f48, 0xa6a6a6); | ||
542 | outpdw(MDP_BASE + 0x40f4c, 0xa7a7a7); | ||
543 | outpdw(MDP_BASE + 0x40f50, 0xa9a9a9); | ||
544 | outpdw(MDP_BASE + 0x40f54, 0xababab); | ||
545 | outpdw(MDP_BASE + 0x40f58, 0xadadad); | ||
546 | outpdw(MDP_BASE + 0x40f5c, 0xafafaf); | ||
547 | outpdw(MDP_BASE + 0x40f60, 0xb0b0b0); | ||
548 | outpdw(MDP_BASE + 0x40f64, 0xb2b2b2); | ||
549 | outpdw(MDP_BASE + 0x40f68, 0xb4b4b4); | ||
550 | outpdw(MDP_BASE + 0x40f6c, 0xb6b6b6); | ||
551 | outpdw(MDP_BASE + 0x40f70, 0xb8b8b8); | ||
552 | outpdw(MDP_BASE + 0x40f74, 0xbababa); | ||
553 | outpdw(MDP_BASE + 0x40f78, 0xbbbbbb); | ||
554 | outpdw(MDP_BASE + 0x40f7c, 0xbdbdbd); | ||
555 | outpdw(MDP_BASE + 0x40f80, 0xbfbfbf); | ||
556 | outpdw(MDP_BASE + 0x40f84, 0xc1c1c1); | ||
557 | outpdw(MDP_BASE + 0x40f88, 0xc3c3c3); | ||
558 | outpdw(MDP_BASE + 0x40f8c, 0xc5c5c5); | ||
559 | outpdw(MDP_BASE + 0x40f90, 0xc7c7c7); | ||
560 | outpdw(MDP_BASE + 0x40f94, 0xc9c9c9); | ||
561 | outpdw(MDP_BASE + 0x40f98, 0xcbcbcb); | ||
562 | outpdw(MDP_BASE + 0x40f9c, 0xcdcdcd); | ||
563 | outpdw(MDP_BASE + 0x40fa0, 0xcfcfcf); | ||
564 | outpdw(MDP_BASE + 0x40fa4, 0xd1d1d1); | ||
565 | outpdw(MDP_BASE + 0x40fa8, 0xd3d3d3); | ||
566 | outpdw(MDP_BASE + 0x40fac, 0xd5d5d5); | ||
567 | outpdw(MDP_BASE + 0x40fb0, 0xd7d7d7); | ||
568 | outpdw(MDP_BASE + 0x40fb4, 0xd9d9d9); | ||
569 | outpdw(MDP_BASE + 0x40fb8, 0xdbdbdb); | ||
570 | outpdw(MDP_BASE + 0x40fbc, 0xdddddd); | ||
571 | outpdw(MDP_BASE + 0x40fc0, 0xdfdfdf); | ||
572 | outpdw(MDP_BASE + 0x40fc4, 0xe1e1e1); | ||
573 | outpdw(MDP_BASE + 0x40fc8, 0xe3e3e3); | ||
574 | outpdw(MDP_BASE + 0x40fcc, 0xe5e5e5); | ||
575 | outpdw(MDP_BASE + 0x40fd0, 0xe7e7e7); | ||
576 | outpdw(MDP_BASE + 0x40fd4, 0xe9e9e9); | ||
577 | outpdw(MDP_BASE + 0x40fd8, 0xebebeb); | ||
578 | outpdw(MDP_BASE + 0x40fdc, 0xeeeeee); | ||
579 | outpdw(MDP_BASE + 0x40fe0, 0xf0f0f0); | ||
580 | outpdw(MDP_BASE + 0x40fe4, 0xf2f2f2); | ||
581 | outpdw(MDP_BASE + 0x40fe8, 0xf4f4f4); | ||
582 | outpdw(MDP_BASE + 0x40fec, 0xf6f6f6); | ||
583 | outpdw(MDP_BASE + 0x40ff0, 0xf8f8f8); | ||
584 | outpdw(MDP_BASE + 0x40ff4, 0xfbfbfb); | ||
585 | outpdw(MDP_BASE + 0x40ff8, 0xfdfdfd); | ||
586 | outpdw(MDP_BASE + 0x40ffc, 0xffffff); | ||
587 | } | ||
588 | |||
589 | #define IRQ_EN_1__MDP_IRQ___M 0x00000800 | ||
590 | |||
591 | void mdp_hw_init(void) | ||
592 | { | ||
593 | int i; | ||
594 | |||
595 | /* MDP cmd block enable */ | ||
596 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); | ||
597 | |||
598 | /* debug interface write access */ | ||
599 | outpdw(MDP_BASE + 0x60, 1); | ||
600 | |||
601 | outp32(MDP_INTR_ENABLE, MDP_ANY_INTR_MASK); | ||
602 | outp32(MDP_EBI2_PORTMAP_MODE, 0x3); | ||
603 | outpdw(MDP_CMD_DEBUG_ACCESS_BASE + 0x01f8, 0x0); | ||
604 | outpdw(MDP_CMD_DEBUG_ACCESS_BASE + 0x01fc, 0x0); | ||
605 | outpdw(MDP_BASE + 0x60, 0x1); | ||
606 | mdp_load_lut_param(); | ||
607 | |||
608 | /* | ||
609 | * clear up unused fg/main registers | ||
610 | */ | ||
611 | /* comp.plane 2&3 ystride */ | ||
612 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0120, 0x0); | ||
613 | /* unpacked pattern */ | ||
614 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x012c, 0x0); | ||
615 | /* unpacked pattern */ | ||
616 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0130, 0x0); | ||
617 | /* unpacked pattern */ | ||
618 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0134, 0x0); | ||
619 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0158, 0x0); | ||
620 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x15c, 0x0); | ||
621 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0160, 0x0); | ||
622 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0170, 0x0); | ||
623 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0174, 0x0); | ||
624 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x017c, 0x0); | ||
625 | |||
626 | /* comp.plane 2 */ | ||
627 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0114, 0x0); | ||
628 | /* comp.plane 3 */ | ||
629 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0118, 0x0); | ||
630 | |||
631 | /* clear up unused bg registers */ | ||
632 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01c8, 0); | ||
633 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01d0, 0); | ||
634 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01dc, 0); | ||
635 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01e0, 0); | ||
636 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01e4, 0); | ||
637 | |||
638 | #ifndef CONFIG_FB_MSM_MDP22 | ||
639 | MDP_OUTP(MDP_BASE + 0xE0000, 0); | ||
640 | MDP_OUTP(MDP_BASE + 0x100, 0xffffffff); | ||
641 | MDP_OUTP(MDP_BASE + 0x90070, 0); | ||
642 | MDP_OUTP(MDP_BASE + 0x94010, 1); | ||
643 | MDP_OUTP(MDP_BASE + 0x9401c, 2); | ||
644 | #endif | ||
645 | |||
646 | /* | ||
647 | * limit vector | ||
648 | * pre gets applied before color matrix conversion | ||
649 | * post is after ccs | ||
650 | */ | ||
651 | writel(mdp_plv[0], MDP_CSC_PRE_LV1n(0)); | ||
652 | writel(mdp_plv[1], MDP_CSC_PRE_LV1n(1)); | ||
653 | writel(mdp_plv[2], MDP_CSC_PRE_LV1n(2)); | ||
654 | writel(mdp_plv[3], MDP_CSC_PRE_LV1n(3)); | ||
655 | |||
656 | #ifdef CONFIG_FB_MSM_MDP31 | ||
657 | writel(mdp_plv[2], MDP_CSC_PRE_LV1n(4)); | ||
658 | writel(mdp_plv[3], MDP_CSC_PRE_LV1n(5)); | ||
659 | |||
660 | writel(0, MDP_CSC_POST_LV1n(0)); | ||
661 | writel(0xff, MDP_CSC_POST_LV1n(1)); | ||
662 | writel(0, MDP_CSC_POST_LV1n(2)); | ||
663 | writel(0xff, MDP_CSC_POST_LV1n(3)); | ||
664 | writel(0, MDP_CSC_POST_LV1n(4)); | ||
665 | writel(0xff, MDP_CSC_POST_LV1n(5)); | ||
666 | |||
667 | writel(0, MDP_CSC_PRE_LV2n(0)); | ||
668 | writel(0xff, MDP_CSC_PRE_LV2n(1)); | ||
669 | writel(0, MDP_CSC_PRE_LV2n(2)); | ||
670 | writel(0xff, MDP_CSC_PRE_LV2n(3)); | ||
671 | writel(0, MDP_CSC_PRE_LV2n(4)); | ||
672 | writel(0xff, MDP_CSC_PRE_LV2n(5)); | ||
673 | |||
674 | writel(mdp_plv[0], MDP_CSC_POST_LV2n(0)); | ||
675 | writel(mdp_plv[1], MDP_CSC_POST_LV2n(1)); | ||
676 | writel(mdp_plv[2], MDP_CSC_POST_LV2n(2)); | ||
677 | writel(mdp_plv[3], MDP_CSC_POST_LV2n(3)); | ||
678 | writel(mdp_plv[2], MDP_CSC_POST_LV2n(4)); | ||
679 | writel(mdp_plv[3], MDP_CSC_POST_LV2n(5)); | ||
680 | #endif | ||
681 | |||
682 | /* primary forward matrix */ | ||
683 | for (i = 0; i < MDP_CCS_SIZE; i++) | ||
684 | writel(mdp_ccs_rgb2yuv.ccs[i], MDP_CSC_PFMVn(i)); | ||
685 | |||
686 | #ifdef CONFIG_FB_MSM_MDP31 | ||
687 | for (i = 0; i < MDP_BV_SIZE; i++) | ||
688 | writel(mdp_ccs_rgb2yuv.bv[i], MDP_CSC_POST_BV2n(i)); | ||
689 | |||
690 | writel(0, MDP_CSC_PRE_BV2n(0)); | ||
691 | writel(0, MDP_CSC_PRE_BV2n(1)); | ||
692 | writel(0, MDP_CSC_PRE_BV2n(2)); | ||
693 | #endif | ||
694 | /* primary reverse matrix */ | ||
695 | for (i = 0; i < MDP_CCS_SIZE; i++) | ||
696 | writel(mdp_ccs_yuv2rgb.ccs[i], MDP_CSC_PRMVn(i)); | ||
697 | |||
698 | for (i = 0; i < MDP_BV_SIZE; i++) | ||
699 | writel(mdp_ccs_yuv2rgb.bv[i], MDP_CSC_PRE_BV1n(i)); | ||
700 | |||
701 | #ifdef CONFIG_FB_MSM_MDP31 | ||
702 | writel(0, MDP_CSC_POST_BV1n(0)); | ||
703 | writel(0, MDP_CSC_POST_BV1n(1)); | ||
704 | writel(0, MDP_CSC_POST_BV1n(2)); | ||
705 | |||
706 | outpdw(MDP_BASE + 0x30010, 0x03e0); | ||
707 | outpdw(MDP_BASE + 0x30014, 0x0360); | ||
708 | outpdw(MDP_BASE + 0x30018, 0x0120); | ||
709 | outpdw(MDP_BASE + 0x3001c, 0x0140); | ||
710 | #endif | ||
711 | mdp_init_scale_table(); | ||
712 | |||
713 | #ifndef CONFIG_FB_MSM_MDP31 | ||
714 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0104, | ||
715 | ((16 << 6) << 16) | (16) << 6); | ||
716 | #endif | ||
717 | |||
718 | /* MDP cmd block disable */ | ||
719 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); | ||
720 | } \ No newline at end of file | ||
diff --git a/drivers/staging/msm/mdp_ppp.c b/drivers/staging/msm/mdp_ppp.c new file mode 100644 index 000000000000..c35a6aebca14 --- /dev/null +++ b/drivers/staging/msm/mdp_ppp.c | |||
@@ -0,0 +1,1502 @@ | |||
1 | /* drivers/video/msm/src/drv/mdp/mdp_ppp.c | ||
2 | * | ||
3 | * Copyright (C) 2007 Google Incorporated | ||
4 | * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved. | ||
5 | * | ||
6 | * This software is licensed under the terms of the GNU General Public | ||
7 | * License version 2, as published by the Free Software Foundation, and | ||
8 | * may be copied, distributed, and modified under those terms. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | */ | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/sched.h> | ||
19 | #include <linux/time.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/fb.h> | ||
23 | #include <msm_mdp.h> | ||
24 | #include <linux/file.h> | ||
25 | #include <linux/major.h> | ||
26 | |||
27 | #include "linux/proc_fs.h" | ||
28 | |||
29 | #include <mach/hardware.h> | ||
30 | #include <linux/io.h> | ||
31 | |||
32 | #include <asm/system.h> | ||
33 | #include <asm/mach-types.h> | ||
34 | #include <linux/semaphore.h> | ||
35 | |||
36 | #include "mdp.h" | ||
37 | #include "msm_fb.h" | ||
38 | |||
39 | #define MDP_IS_IMGTYPE_BAD(x) (((x) >= MDP_IMGTYPE_LIMIT) && \ | ||
40 | (((x) < MDP_IMGTYPE2_START) || \ | ||
41 | ((x) >= MDP_IMGTYPE_LIMIT2))) | ||
42 | |||
43 | static uint32_t bytes_per_pixel[] = { | ||
44 | [MDP_RGB_565] = 2, | ||
45 | [MDP_RGB_888] = 3, | ||
46 | [MDP_XRGB_8888] = 4, | ||
47 | [MDP_ARGB_8888] = 4, | ||
48 | [MDP_RGBA_8888] = 4, | ||
49 | [MDP_BGRA_8888] = 4, | ||
50 | [MDP_Y_CBCR_H2V1] = 1, | ||
51 | [MDP_Y_CBCR_H2V2] = 1, | ||
52 | [MDP_Y_CRCB_H2V1] = 1, | ||
53 | [MDP_Y_CRCB_H2V2] = 1, | ||
54 | [MDP_YCRYCB_H2V1] = 2, | ||
55 | [MDP_BGR_565] = 2 | ||
56 | }; | ||
57 | |||
58 | extern uint32 mdp_plv[]; | ||
59 | extern struct semaphore mdp_ppp_mutex; | ||
60 | |||
61 | uint32_t mdp_get_bytes_per_pixel(uint32_t format) | ||
62 | { | ||
63 | uint32_t bpp = 0; | ||
64 | if (format < ARRAY_SIZE(bytes_per_pixel)) | ||
65 | bpp = bytes_per_pixel[format]; | ||
66 | |||
67 | BUG_ON(!bpp); | ||
68 | return bpp; | ||
69 | } | ||
70 | |||
71 | static uint32 mdp_conv_matx_rgb2yuv(uint32 input_pixel, | ||
72 | uint16 *matrix_and_bias_vector, | ||
73 | uint32 *clamp_vector, | ||
74 | uint32 *look_up_table) | ||
75 | { | ||
76 | uint8 input_C2, input_C0, input_C1; | ||
77 | uint32 output; | ||
78 | int32 comp_C2, comp_C1, comp_C0, temp; | ||
79 | int32 temp1, temp2, temp3; | ||
80 | int32 matrix[9]; | ||
81 | int32 bias_vector[3]; | ||
82 | int32 Y_low_limit, Y_high_limit, C_low_limit, C_high_limit; | ||
83 | int32 i; | ||
84 | uint32 _is_lookup_table_enabled; | ||
85 | |||
86 | input_C2 = (input_pixel >> 16) & 0xFF; | ||
87 | input_C1 = (input_pixel >> 8) & 0xFF; | ||
88 | input_C0 = (input_pixel >> 0) & 0xFF; | ||
89 | |||
90 | comp_C0 = input_C0; | ||
91 | comp_C1 = input_C1; | ||
92 | comp_C2 = input_C2; | ||
93 | |||
94 | for (i = 0; i < 9; i++) | ||
95 | matrix[i] = | ||
96 | ((int32) (((int32) matrix_and_bias_vector[i]) << 20)) >> 20; | ||
97 | |||
98 | bias_vector[0] = (int32) (matrix_and_bias_vector[9] & 0xFF); | ||
99 | bias_vector[1] = (int32) (matrix_and_bias_vector[10] & 0xFF); | ||
100 | bias_vector[2] = (int32) (matrix_and_bias_vector[11] & 0xFF); | ||
101 | |||
102 | Y_low_limit = (int32) clamp_vector[0]; | ||
103 | Y_high_limit = (int32) clamp_vector[1]; | ||
104 | C_low_limit = (int32) clamp_vector[2]; | ||
105 | C_high_limit = (int32) clamp_vector[3]; | ||
106 | |||
107 | if (look_up_table == 0) /* check for NULL point */ | ||
108 | _is_lookup_table_enabled = 0; | ||
109 | else | ||
110 | _is_lookup_table_enabled = 1; | ||
111 | |||
112 | if (_is_lookup_table_enabled == 1) { | ||
113 | comp_C2 = (look_up_table[comp_C2] >> 16) & 0xFF; | ||
114 | comp_C1 = (look_up_table[comp_C1] >> 8) & 0xFF; | ||
115 | comp_C0 = (look_up_table[comp_C0] >> 0) & 0xFF; | ||
116 | } | ||
117 | /* | ||
118 | * Color Conversion | ||
119 | * reorder input colors | ||
120 | */ | ||
121 | temp = comp_C2; | ||
122 | comp_C2 = comp_C1; | ||
123 | comp_C1 = comp_C0; | ||
124 | comp_C0 = temp; | ||
125 | |||
126 | /* matrix multiplication */ | ||
127 | temp1 = comp_C0 * matrix[0] + comp_C1 * matrix[1] + comp_C2 * matrix[2]; | ||
128 | temp2 = comp_C0 * matrix[3] + comp_C1 * matrix[4] + comp_C2 * matrix[5]; | ||
129 | temp3 = comp_C0 * matrix[6] + comp_C1 * matrix[7] + comp_C2 * matrix[8]; | ||
130 | |||
131 | comp_C0 = temp1 + 0x100; | ||
132 | comp_C1 = temp2 + 0x100; | ||
133 | comp_C2 = temp3 + 0x100; | ||
134 | |||
135 | /* take interger part */ | ||
136 | comp_C0 >>= 9; | ||
137 | comp_C1 >>= 9; | ||
138 | comp_C2 >>= 9; | ||
139 | |||
140 | /* post bias (+) */ | ||
141 | comp_C0 += bias_vector[0]; | ||
142 | comp_C1 += bias_vector[1]; | ||
143 | comp_C2 += bias_vector[2]; | ||
144 | |||
145 | /* limit pixel to 8-bit */ | ||
146 | if (comp_C0 < 0) | ||
147 | comp_C0 = 0; | ||
148 | |||
149 | if (comp_C0 > 255) | ||
150 | comp_C0 = 255; | ||
151 | |||
152 | if (comp_C1 < 0) | ||
153 | comp_C1 = 0; | ||
154 | |||
155 | if (comp_C1 > 255) | ||
156 | comp_C1 = 255; | ||
157 | |||
158 | if (comp_C2 < 0) | ||
159 | comp_C2 = 0; | ||
160 | |||
161 | if (comp_C2 > 255) | ||
162 | comp_C2 = 255; | ||
163 | |||
164 | /* clamp */ | ||
165 | if (comp_C0 < Y_low_limit) | ||
166 | comp_C0 = Y_low_limit; | ||
167 | |||
168 | if (comp_C0 > Y_high_limit) | ||
169 | comp_C0 = Y_high_limit; | ||
170 | |||
171 | if (comp_C1 < C_low_limit) | ||
172 | comp_C1 = C_low_limit; | ||
173 | |||
174 | if (comp_C1 > C_high_limit) | ||
175 | comp_C1 = C_high_limit; | ||
176 | |||
177 | if (comp_C2 < C_low_limit) | ||
178 | comp_C2 = C_low_limit; | ||
179 | |||
180 | if (comp_C2 > C_high_limit) | ||
181 | comp_C2 = C_high_limit; | ||
182 | |||
183 | output = (comp_C2 << 16) | (comp_C1 << 8) | comp_C0; | ||
184 | return output; | ||
185 | } | ||
186 | |||
187 | uint32 mdp_conv_matx_yuv2rgb(uint32 input_pixel, | ||
188 | uint16 *matrix_and_bias_vector, | ||
189 | uint32 *clamp_vector, uint32 *look_up_table) | ||
190 | { | ||
191 | uint8 input_C2, input_C0, input_C1; | ||
192 | uint32 output; | ||
193 | int32 comp_C2, comp_C1, comp_C0, temp; | ||
194 | int32 temp1, temp2, temp3; | ||
195 | int32 matrix[9]; | ||
196 | int32 bias_vector[3]; | ||
197 | int32 Y_low_limit, Y_high_limit, C_low_limit, C_high_limit; | ||
198 | int32 i; | ||
199 | uint32 _is_lookup_table_enabled; | ||
200 | |||
201 | input_C2 = (input_pixel >> 16) & 0xFF; | ||
202 | input_C1 = (input_pixel >> 8) & 0xFF; | ||
203 | input_C0 = (input_pixel >> 0) & 0xFF; | ||
204 | |||
205 | comp_C0 = input_C0; | ||
206 | comp_C1 = input_C1; | ||
207 | comp_C2 = input_C2; | ||
208 | |||
209 | for (i = 0; i < 9; i++) | ||
210 | matrix[i] = | ||
211 | ((int32) (((int32) matrix_and_bias_vector[i]) << 20)) >> 20; | ||
212 | |||
213 | bias_vector[0] = (int32) (matrix_and_bias_vector[9] & 0xFF); | ||
214 | bias_vector[1] = (int32) (matrix_and_bias_vector[10] & 0xFF); | ||
215 | bias_vector[2] = (int32) (matrix_and_bias_vector[11] & 0xFF); | ||
216 | |||
217 | Y_low_limit = (int32) clamp_vector[0]; | ||
218 | Y_high_limit = (int32) clamp_vector[1]; | ||
219 | C_low_limit = (int32) clamp_vector[2]; | ||
220 | C_high_limit = (int32) clamp_vector[3]; | ||
221 | |||
222 | if (look_up_table == 0) /* check for NULL point */ | ||
223 | _is_lookup_table_enabled = 0; | ||
224 | else | ||
225 | _is_lookup_table_enabled = 1; | ||
226 | |||
227 | /* clamp */ | ||
228 | if (comp_C0 < Y_low_limit) | ||
229 | comp_C0 = Y_low_limit; | ||
230 | |||
231 | if (comp_C0 > Y_high_limit) | ||
232 | comp_C0 = Y_high_limit; | ||
233 | |||
234 | if (comp_C1 < C_low_limit) | ||
235 | comp_C1 = C_low_limit; | ||
236 | |||
237 | if (comp_C1 > C_high_limit) | ||
238 | comp_C1 = C_high_limit; | ||
239 | |||
240 | if (comp_C2 < C_low_limit) | ||
241 | comp_C2 = C_low_limit; | ||
242 | |||
243 | if (comp_C2 > C_high_limit) | ||
244 | comp_C2 = C_high_limit; | ||
245 | |||
246 | /* | ||
247 | * Color Conversion | ||
248 | * pre bias (-) | ||
249 | */ | ||
250 | comp_C0 -= bias_vector[0]; | ||
251 | comp_C1 -= bias_vector[1]; | ||
252 | comp_C2 -= bias_vector[2]; | ||
253 | |||
254 | /* matrix multiplication */ | ||
255 | temp1 = comp_C0 * matrix[0] + comp_C1 * matrix[1] + comp_C2 * matrix[2]; | ||
256 | temp2 = comp_C0 * matrix[3] + comp_C1 * matrix[4] + comp_C2 * matrix[5]; | ||
257 | temp3 = comp_C0 * matrix[6] + comp_C1 * matrix[7] + comp_C2 * matrix[8]; | ||
258 | |||
259 | comp_C0 = temp1 + 0x100; | ||
260 | comp_C1 = temp2 + 0x100; | ||
261 | comp_C2 = temp3 + 0x100; | ||
262 | |||
263 | /* take interger part */ | ||
264 | comp_C0 >>= 9; | ||
265 | comp_C1 >>= 9; | ||
266 | comp_C2 >>= 9; | ||
267 | |||
268 | /* reorder output colors */ | ||
269 | temp = comp_C0; | ||
270 | comp_C0 = comp_C1; | ||
271 | comp_C1 = comp_C2; | ||
272 | comp_C2 = temp; | ||
273 | |||
274 | /* limit pixel to 8-bit */ | ||
275 | if (comp_C0 < 0) | ||
276 | comp_C0 = 0; | ||
277 | |||
278 | if (comp_C0 > 255) | ||
279 | comp_C0 = 255; | ||
280 | |||
281 | if (comp_C1 < 0) | ||
282 | comp_C1 = 0; | ||
283 | |||
284 | if (comp_C1 > 255) | ||
285 | comp_C1 = 255; | ||
286 | |||
287 | if (comp_C2 < 0) | ||
288 | comp_C2 = 0; | ||
289 | |||
290 | if (comp_C2 > 255) | ||
291 | comp_C2 = 255; | ||
292 | |||
293 | /* Look-up table */ | ||
294 | if (_is_lookup_table_enabled == 1) { | ||
295 | comp_C2 = (look_up_table[comp_C2] >> 16) & 0xFF; | ||
296 | comp_C1 = (look_up_table[comp_C1] >> 8) & 0xFF; | ||
297 | comp_C0 = (look_up_table[comp_C0] >> 0) & 0xFF; | ||
298 | } | ||
299 | |||
300 | output = (comp_C2 << 16) | (comp_C1 << 8) | comp_C0; | ||
301 | return output; | ||
302 | } | ||
303 | |||
304 | static uint32 mdp_calc_tpval(MDPIMG *mdpImg) | ||
305 | { | ||
306 | uint32 tpVal; | ||
307 | uint8 plane_tp; | ||
308 | |||
309 | tpVal = 0; | ||
310 | if ((mdpImg->imgType == MDP_RGB_565) | ||
311 | || (mdpImg->imgType == MDP_BGR_565)) { | ||
312 | /* | ||
313 | * transparent color conversion into 24 bpp | ||
314 | * | ||
315 | * C2R_8BIT | ||
316 | * left shift the entire bit and or it with the upper most bits | ||
317 | */ | ||
318 | plane_tp = (uint8) ((mdpImg->tpVal & 0xF800) >> 11); | ||
319 | tpVal |= ((plane_tp << 3) | ((plane_tp & 0x1C) >> 2)) << 16; | ||
320 | |||
321 | /* C1B_8BIT */ | ||
322 | plane_tp = (uint8) (mdpImg->tpVal & 0x1F); | ||
323 | tpVal |= ((plane_tp << 3) | ((plane_tp & 0x1C) >> 2)) << 8; | ||
324 | |||
325 | /* C0G_8BIT */ | ||
326 | plane_tp = (uint8) ((mdpImg->tpVal & 0x7E0) >> 5); | ||
327 | tpVal |= ((plane_tp << 2) | ((plane_tp & 0x30) >> 4)); | ||
328 | } else { | ||
329 | /* 24bit RGB to RBG conversion */ | ||
330 | |||
331 | tpVal = (mdpImg->tpVal & 0xFF00) >> 8; | ||
332 | tpVal |= (mdpImg->tpVal & 0xFF) << 8; | ||
333 | tpVal |= (mdpImg->tpVal & 0xFF0000); | ||
334 | } | ||
335 | |||
336 | return tpVal; | ||
337 | } | ||
338 | |||
339 | static uint8 *mdp_get_chroma_addr(MDPIBUF *iBuf) | ||
340 | { | ||
341 | uint8 *dest1; | ||
342 | |||
343 | dest1 = NULL; | ||
344 | switch (iBuf->ibuf_type) { | ||
345 | case MDP_Y_CBCR_H2V2: | ||
346 | case MDP_Y_CRCB_H2V2: | ||
347 | case MDP_Y_CBCR_H2V1: | ||
348 | case MDP_Y_CRCB_H2V1: | ||
349 | dest1 = (uint8 *) iBuf->buf; | ||
350 | dest1 += iBuf->ibuf_width * iBuf->ibuf_height * iBuf->bpp; | ||
351 | break; | ||
352 | |||
353 | default: | ||
354 | break; | ||
355 | } | ||
356 | |||
357 | return dest1; | ||
358 | } | ||
359 | |||
360 | static void mdp_ppp_setbg(MDPIBUF *iBuf) | ||
361 | { | ||
362 | uint8 *bg0_addr; | ||
363 | uint8 *bg1_addr; | ||
364 | uint32 bg0_ystride, bg1_ystride; | ||
365 | uint32 ppp_src_cfg_reg, unpack_pattern; | ||
366 | int v_slice, h_slice; | ||
367 | |||
368 | v_slice = h_slice = 1; | ||
369 | bg0_addr = (uint8 *) iBuf->buf; | ||
370 | bg1_addr = mdp_get_chroma_addr(iBuf); | ||
371 | |||
372 | bg0_ystride = iBuf->ibuf_width * iBuf->bpp; | ||
373 | bg1_ystride = iBuf->ibuf_width * iBuf->bpp; | ||
374 | |||
375 | switch (iBuf->ibuf_type) { | ||
376 | case MDP_BGR_565: | ||
377 | case MDP_RGB_565: | ||
378 | /* 888 = 3bytes | ||
379 | * RGB = 3Components | ||
380 | * RGB interleaved | ||
381 | */ | ||
382 | ppp_src_cfg_reg = PPP_SRC_C2R_5BITS | PPP_SRC_C0G_6BITS | | ||
383 | PPP_SRC_C1B_5BITS | PPP_SRC_BPP_INTERLVD_2BYTES | | ||
384 | PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT | | ||
385 | PPP_SRC_UNPACK_ALIGN_LSB | | ||
386 | PPP_SRC_FETCH_PLANES_INTERLVD; | ||
387 | |||
388 | if (iBuf->ibuf_type == MDP_RGB_565) | ||
389 | unpack_pattern = | ||
390 | MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8); | ||
391 | else | ||
392 | unpack_pattern = | ||
393 | MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8); | ||
394 | break; | ||
395 | |||
396 | case MDP_RGB_888: | ||
397 | /* | ||
398 | * 888 = 3bytes | ||
399 | * RGB = 3Components | ||
400 | * RGB interleaved | ||
401 | */ | ||
402 | ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS | | ||
403 | PPP_SRC_C1B_8BITS | PPP_SRC_BPP_INTERLVD_3BYTES | | ||
404 | PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT | | ||
405 | PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_INTERLVD; | ||
406 | |||
407 | unpack_pattern = | ||
408 | MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8); | ||
409 | break; | ||
410 | |||
411 | case MDP_BGRA_8888: | ||
412 | case MDP_RGBA_8888: | ||
413 | case MDP_ARGB_8888: | ||
414 | case MDP_XRGB_8888: | ||
415 | /* | ||
416 | * 8888 = 4bytes | ||
417 | * ARGB = 4Components | ||
418 | * ARGB interleaved | ||
419 | */ | ||
420 | ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS | | ||
421 | PPP_SRC_C1B_8BITS | PPP_SRC_C3A_8BITS | PPP_SRC_C3_ALPHA_EN | | ||
422 | PPP_SRC_BPP_INTERLVD_4BYTES | PPP_SRC_INTERLVD_4COMPONENTS | | ||
423 | PPP_SRC_UNPACK_TIGHT | PPP_SRC_UNPACK_ALIGN_LSB | | ||
424 | PPP_SRC_FETCH_PLANES_INTERLVD; | ||
425 | |||
426 | if (iBuf->ibuf_type == MDP_BGRA_8888) | ||
427 | unpack_pattern = | ||
428 | MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B, | ||
429 | 8); | ||
430 | else if (iBuf->ibuf_type == MDP_RGBA_8888) | ||
431 | unpack_pattern = | ||
432 | MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R, | ||
433 | 8); | ||
434 | else | ||
435 | unpack_pattern = | ||
436 | MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B, | ||
437 | 8); | ||
438 | break; | ||
439 | |||
440 | case MDP_Y_CBCR_H2V2: | ||
441 | case MDP_Y_CRCB_H2V2: | ||
442 | ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | | ||
443 | PPP_SRC_C0G_8BITS | | ||
444 | PPP_SRC_C1B_8BITS | | ||
445 | PPP_SRC_C3A_8BITS | | ||
446 | PPP_SRC_BPP_INTERLVD_2BYTES | | ||
447 | PPP_SRC_INTERLVD_2COMPONENTS | | ||
448 | PPP_SRC_UNPACK_TIGHT | | ||
449 | PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_PSEUDOPLNR; | ||
450 | |||
451 | if (iBuf->ibuf_type == MDP_Y_CBCR_H2V1) | ||
452 | unpack_pattern = | ||
453 | MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8); | ||
454 | else | ||
455 | unpack_pattern = | ||
456 | MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8); | ||
457 | v_slice = h_slice = 2; | ||
458 | break; | ||
459 | |||
460 | case MDP_YCRYCB_H2V1: | ||
461 | ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | | ||
462 | PPP_SRC_C0G_8BITS | | ||
463 | PPP_SRC_C1B_8BITS | | ||
464 | PPP_SRC_C3A_8BITS | | ||
465 | PPP_SRC_BPP_INTERLVD_2BYTES | | ||
466 | PPP_SRC_INTERLVD_4COMPONENTS | | ||
467 | PPP_SRC_UNPACK_TIGHT | PPP_SRC_UNPACK_ALIGN_LSB; | ||
468 | |||
469 | unpack_pattern = | ||
470 | MDP_GET_PACK_PATTERN(CLR_Y, CLR_CR, CLR_Y, CLR_CB, 8); | ||
471 | h_slice = 2; | ||
472 | break; | ||
473 | |||
474 | case MDP_Y_CBCR_H2V1: | ||
475 | case MDP_Y_CRCB_H2V1: | ||
476 | ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | | ||
477 | PPP_SRC_C0G_8BITS | | ||
478 | PPP_SRC_C1B_8BITS | | ||
479 | PPP_SRC_C3A_8BITS | | ||
480 | PPP_SRC_BPP_INTERLVD_2BYTES | | ||
481 | PPP_SRC_INTERLVD_2COMPONENTS | | ||
482 | PPP_SRC_UNPACK_TIGHT | | ||
483 | PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_PSEUDOPLNR; | ||
484 | |||
485 | if (iBuf->ibuf_type == MDP_Y_CBCR_H2V1) | ||
486 | unpack_pattern = | ||
487 | MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8); | ||
488 | else | ||
489 | unpack_pattern = | ||
490 | MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8); | ||
491 | h_slice = 2; | ||
492 | break; | ||
493 | |||
494 | default: | ||
495 | return; | ||
496 | } | ||
497 | |||
498 | /* starting input address adjustment */ | ||
499 | mdp_adjust_start_addr(&bg0_addr, &bg1_addr, v_slice, h_slice, | ||
500 | iBuf->roi.lcd_x, iBuf->roi.lcd_y, | ||
501 | iBuf->ibuf_width, iBuf->ibuf_height, iBuf->bpp, | ||
502 | iBuf, 1); | ||
503 | |||
504 | /* | ||
505 | * 0x01c0: background plane 0 addr | ||
506 | * 0x01c4: background plane 1 addr | ||
507 | * 0x01c8: background plane 2 addr | ||
508 | * 0x01cc: bg y stride for plane 0 and 1 | ||
509 | * 0x01d0: bg y stride for plane 2 | ||
510 | * 0x01d4: bg src PPP config | ||
511 | * 0x01d8: unpack pattern | ||
512 | */ | ||
513 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01c0, bg0_addr); | ||
514 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01c4, bg1_addr); | ||
515 | |||
516 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01cc, | ||
517 | (bg1_ystride << 16) | bg0_ystride); | ||
518 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01d4, ppp_src_cfg_reg); | ||
519 | |||
520 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01d8, unpack_pattern); | ||
521 | } | ||
522 | |||
523 | #define IS_PSEUDOPLNR(img) ((img == MDP_Y_CRCB_H2V2) | \ | ||
524 | (img == MDP_Y_CBCR_H2V2) | \ | ||
525 | (img == MDP_Y_CRCB_H2V1) | \ | ||
526 | (img == MDP_Y_CBCR_H2V1)) | ||
527 | |||
528 | #define IMG_LEN(rect_h, w, rect_w, bpp) (((rect_h) * w) * bpp) | ||
529 | |||
530 | #define Y_TO_CRCB_RATIO(format) \ | ||
531 | ((format == MDP_Y_CBCR_H2V2 || format == MDP_Y_CRCB_H2V2) ? 2 :\ | ||
532 | (format == MDP_Y_CBCR_H2V1 || format == MDP_Y_CRCB_H2V1) ? 1 : 1) | ||
533 | |||
534 | static void get_len(struct mdp_img *img, struct mdp_rect *rect, uint32_t bpp, | ||
535 | uint32_t *len0, uint32_t *len1) | ||
536 | { | ||
537 | *len0 = IMG_LEN(rect->h, img->width, rect->w, bpp); | ||
538 | if (IS_PSEUDOPLNR(img->format)) | ||
539 | *len1 = *len0/Y_TO_CRCB_RATIO(img->format); | ||
540 | else | ||
541 | *len1 = 0; | ||
542 | } | ||
543 | |||
544 | static void flush_imgs(struct mdp_blit_req *req, int src_bpp, int dst_bpp, | ||
545 | struct file *p_src_file, struct file *p_dst_file) | ||
546 | { | ||
547 | #ifdef CONFIG_ANDROID_PMEM | ||
548 | uint32_t src0_len, src1_len, dst0_len, dst1_len; | ||
549 | |||
550 | /* flush src images to memory before dma to mdp */ | ||
551 | get_len(&req->src, &req->src_rect, src_bpp, | ||
552 | &src0_len, &src1_len); | ||
553 | |||
554 | flush_pmem_file(p_src_file, | ||
555 | req->src.offset, src0_len); | ||
556 | |||
557 | if (IS_PSEUDOPLNR(req->src.format)) | ||
558 | flush_pmem_file(p_src_file, | ||
559 | req->src.offset + src0_len, src1_len); | ||
560 | |||
561 | get_len(&req->dst, &req->dst_rect, dst_bpp, &dst0_len, &dst1_len); | ||
562 | flush_pmem_file(p_dst_file, req->dst.offset, dst0_len); | ||
563 | |||
564 | if (IS_PSEUDOPLNR(req->dst.format)) | ||
565 | flush_pmem_file(p_dst_file, | ||
566 | req->dst.offset + dst0_len, dst1_len); | ||
567 | #endif | ||
568 | } | ||
569 | |||
570 | static void mdp_start_ppp(struct msm_fb_data_type *mfd, MDPIBUF *iBuf, | ||
571 | struct mdp_blit_req *req, struct file *p_src_file, struct file *p_dst_file) | ||
572 | { | ||
573 | uint8 *src0, *src1; | ||
574 | uint8 *dest0, *dest1; | ||
575 | uint16 inpBpp; | ||
576 | uint32 dest0_ystride; | ||
577 | uint32 src_width; | ||
578 | uint32 src_height; | ||
579 | uint32 src0_ystride; | ||
580 | uint32 dst_roi_width; | ||
581 | uint32 dst_roi_height; | ||
582 | uint32 ppp_src_cfg_reg, ppp_operation_reg, ppp_dst_cfg_reg; | ||
583 | uint32 alpha, tpVal; | ||
584 | uint32 packPattern; | ||
585 | uint32 dst_packPattern; | ||
586 | boolean inputRGB, outputRGB, pseudoplanr_output; | ||
587 | int sv_slice, sh_slice; | ||
588 | int dv_slice, dh_slice; | ||
589 | boolean perPixelAlpha = FALSE; | ||
590 | boolean ppp_lookUp_enable = FALSE; | ||
591 | |||
592 | sv_slice = sh_slice = dv_slice = dh_slice = 1; | ||
593 | alpha = tpVal = 0; | ||
594 | src_width = iBuf->mdpImg.width; | ||
595 | src_height = iBuf->roi.y + iBuf->roi.height; | ||
596 | src1 = NULL; | ||
597 | dest1 = NULL; | ||
598 | |||
599 | inputRGB = outputRGB = TRUE; | ||
600 | pseudoplanr_output = FALSE; | ||
601 | ppp_operation_reg = 0; | ||
602 | ppp_dst_cfg_reg = 0; | ||
603 | ppp_src_cfg_reg = 0; | ||
604 | |||
605 | /* Wait for the pipe to clear */ | ||
606 | do { } while (mdp_ppp_pipe_wait() <= 0); | ||
607 | |||
608 | /* | ||
609 | * destination config | ||
610 | */ | ||
611 | switch (iBuf->ibuf_type) { | ||
612 | case MDP_RGB_888: | ||
613 | dst_packPattern = | ||
614 | MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8); | ||
615 | ppp_dst_cfg_reg = | ||
616 | PPP_DST_C0G_8BIT | PPP_DST_C1B_8BIT | PPP_DST_C2R_8BIT | | ||
617 | PPP_DST_PACKET_CNT_INTERLVD_3ELEM | PPP_DST_PACK_TIGHT | | ||
618 | PPP_DST_PACK_ALIGN_LSB | PPP_DST_OUT_SEL_AXI | | ||
619 | PPP_DST_BPP_3BYTES | PPP_DST_PLANE_INTERLVD; | ||
620 | break; | ||
621 | |||
622 | case MDP_XRGB_8888: | ||
623 | case MDP_ARGB_8888: | ||
624 | case MDP_RGBA_8888: | ||
625 | if (iBuf->ibuf_type == MDP_BGRA_8888) | ||
626 | dst_packPattern = | ||
627 | MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B, | ||
628 | 8); | ||
629 | else if (iBuf->ibuf_type == MDP_RGBA_8888) | ||
630 | dst_packPattern = | ||
631 | MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R, | ||
632 | 8); | ||
633 | else | ||
634 | dst_packPattern = | ||
635 | MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B, | ||
636 | 8); | ||
637 | |||
638 | ppp_dst_cfg_reg = PPP_DST_C0G_8BIT | | ||
639 | PPP_DST_C1B_8BIT | | ||
640 | PPP_DST_C2R_8BIT | | ||
641 | PPP_DST_C3A_8BIT | | ||
642 | PPP_DST_C3ALPHA_EN | | ||
643 | PPP_DST_PACKET_CNT_INTERLVD_4ELEM | | ||
644 | PPP_DST_PACK_TIGHT | | ||
645 | PPP_DST_PACK_ALIGN_LSB | | ||
646 | PPP_DST_OUT_SEL_AXI | | ||
647 | PPP_DST_BPP_4BYTES | PPP_DST_PLANE_INTERLVD; | ||
648 | break; | ||
649 | |||
650 | case MDP_Y_CBCR_H2V2: | ||
651 | case MDP_Y_CRCB_H2V2: | ||
652 | if (iBuf->ibuf_type == MDP_Y_CBCR_H2V2) | ||
653 | dst_packPattern = | ||
654 | MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8); | ||
655 | else | ||
656 | dst_packPattern = | ||
657 | MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8); | ||
658 | |||
659 | ppp_dst_cfg_reg = PPP_DST_C2R_8BIT | | ||
660 | PPP_DST_C0G_8BIT | | ||
661 | PPP_DST_C1B_8BIT | | ||
662 | PPP_DST_C3A_8BIT | | ||
663 | PPP_DST_PACKET_CNT_INTERLVD_2ELEM | | ||
664 | PPP_DST_PACK_TIGHT | | ||
665 | PPP_DST_PACK_ALIGN_LSB | | ||
666 | PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_2BYTES; | ||
667 | |||
668 | ppp_operation_reg |= PPP_OP_DST_CHROMA_420; | ||
669 | outputRGB = FALSE; | ||
670 | pseudoplanr_output = TRUE; | ||
671 | /* | ||
672 | * vertically (y direction) and horizontally (x direction) | ||
673 | * sample reduction by 2 | ||
674 | */ | ||
675 | |||
676 | /* | ||
677 | * H2V2(YUV420) Cosite | ||
678 | * | ||
679 | * Y Y Y Y | ||
680 | * CbCr CbCr | ||
681 | * Y Y Y Y | ||
682 | * Y Y Y Y | ||
683 | * CbCr CbCr | ||
684 | * Y Y Y Y | ||
685 | */ | ||
686 | dv_slice = dh_slice = 2; | ||
687 | |||
688 | /* (x,y) and (width,height) must be even numbern */ | ||
689 | iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2; | ||
690 | iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2; | ||
691 | iBuf->roi.x = (iBuf->roi.x / 2) * 2; | ||
692 | iBuf->roi.width = (iBuf->roi.width / 2) * 2; | ||
693 | |||
694 | iBuf->roi.lcd_y = (iBuf->roi.lcd_y / 2) * 2; | ||
695 | iBuf->roi.dst_height = (iBuf->roi.dst_height / 2) * 2; | ||
696 | iBuf->roi.y = (iBuf->roi.y / 2) * 2; | ||
697 | iBuf->roi.height = (iBuf->roi.height / 2) * 2; | ||
698 | break; | ||
699 | |||
700 | case MDP_YCRYCB_H2V1: | ||
701 | dst_packPattern = | ||
702 | MDP_GET_PACK_PATTERN(CLR_Y, CLR_CR, CLR_Y, CLR_CB, 8); | ||
703 | ppp_dst_cfg_reg = | ||
704 | PPP_DST_C2R_8BIT | PPP_DST_C0G_8BIT | PPP_DST_C1B_8BIT | | ||
705 | PPP_DST_C3A_8BIT | PPP_DST_PACKET_CNT_INTERLVD_4ELEM | | ||
706 | PPP_DST_PACK_TIGHT | PPP_DST_PACK_ALIGN_LSB | | ||
707 | PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_2BYTES | | ||
708 | PPP_DST_PLANE_INTERLVD; | ||
709 | |||
710 | ppp_operation_reg |= PPP_OP_DST_CHROMA_H2V1; | ||
711 | outputRGB = FALSE; | ||
712 | /* | ||
713 | * horizontally (x direction) sample reduction by 2 | ||
714 | * | ||
715 | * H2V1(YUV422) Cosite | ||
716 | * | ||
717 | * YCbCr Y YCbCr Y | ||
718 | * YCbCr Y YCbCr Y | ||
719 | * YCbCr Y YCbCr Y | ||
720 | * YCbCr Y YCbCr Y | ||
721 | */ | ||
722 | dh_slice = 2; | ||
723 | |||
724 | /* | ||
725 | * if it's TV-Out/MDP_YCRYCB_H2V1, let's go through the | ||
726 | * preloaded gamma setting of 2.2 when the content is | ||
727 | * non-linear ppp_lookUp_enable = TRUE; | ||
728 | */ | ||
729 | |||
730 | /* x and width must be even number */ | ||
731 | iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2; | ||
732 | iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2; | ||
733 | iBuf->roi.x = (iBuf->roi.x / 2) * 2; | ||
734 | iBuf->roi.width = (iBuf->roi.width / 2) * 2; | ||
735 | break; | ||
736 | |||
737 | case MDP_Y_CBCR_H2V1: | ||
738 | case MDP_Y_CRCB_H2V1: | ||
739 | if (iBuf->ibuf_type == MDP_Y_CBCR_H2V1) | ||
740 | dst_packPattern = | ||
741 | MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8); | ||
742 | else | ||
743 | dst_packPattern = | ||
744 | MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8); | ||
745 | |||
746 | ppp_dst_cfg_reg = PPP_DST_C2R_8BIT | | ||
747 | PPP_DST_C0G_8BIT | | ||
748 | PPP_DST_C1B_8BIT | | ||
749 | PPP_DST_C3A_8BIT | | ||
750 | PPP_DST_PACKET_CNT_INTERLVD_2ELEM | | ||
751 | PPP_DST_PACK_TIGHT | | ||
752 | PPP_DST_PACK_ALIGN_LSB | | ||
753 | PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_2BYTES; | ||
754 | |||
755 | ppp_operation_reg |= PPP_OP_DST_CHROMA_H2V1; | ||
756 | outputRGB = FALSE; | ||
757 | pseudoplanr_output = TRUE; | ||
758 | /* horizontally (x direction) sample reduction by 2 */ | ||
759 | dh_slice = 2; | ||
760 | |||
761 | /* x and width must be even number */ | ||
762 | iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2; | ||
763 | iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2; | ||
764 | iBuf->roi.x = (iBuf->roi.x / 2) * 2; | ||
765 | iBuf->roi.width = (iBuf->roi.width / 2) * 2; | ||
766 | break; | ||
767 | |||
768 | case MDP_BGR_565: | ||
769 | case MDP_RGB_565: | ||
770 | default: | ||
771 | if (iBuf->ibuf_type == MDP_RGB_565) | ||
772 | dst_packPattern = | ||
773 | MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8); | ||
774 | else | ||
775 | dst_packPattern = | ||
776 | MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8); | ||
777 | |||
778 | ppp_dst_cfg_reg = PPP_DST_C0G_6BIT | | ||
779 | PPP_DST_C1B_5BIT | | ||
780 | PPP_DST_C2R_5BIT | | ||
781 | PPP_DST_PACKET_CNT_INTERLVD_3ELEM | | ||
782 | PPP_DST_PACK_TIGHT | | ||
783 | PPP_DST_PACK_ALIGN_LSB | | ||
784 | PPP_DST_OUT_SEL_AXI | | ||
785 | PPP_DST_BPP_2BYTES | PPP_DST_PLANE_INTERLVD; | ||
786 | break; | ||
787 | } | ||
788 | |||
789 | /* source config */ | ||
790 | switch (iBuf->mdpImg.imgType) { | ||
791 | case MDP_RGB_888: | ||
792 | inpBpp = 3; | ||
793 | /* | ||
794 | * 565 = 2bytes | ||
795 | * RGB = 3Components | ||
796 | * RGB interleaved | ||
797 | */ | ||
798 | ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS | | ||
799 | PPP_SRC_C1B_8BITS | PPP_SRC_BPP_INTERLVD_3BYTES | | ||
800 | PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT | | ||
801 | PPP_SRC_UNPACK_ALIGN_LSB | | ||
802 | PPP_SRC_FETCH_PLANES_INTERLVD; | ||
803 | |||
804 | packPattern = MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8); | ||
805 | |||
806 | ppp_operation_reg |= PPP_OP_COLOR_SPACE_RGB | | ||
807 | PPP_OP_SRC_CHROMA_RGB | PPP_OP_DST_CHROMA_RGB; | ||
808 | break; | ||
809 | |||
810 | case MDP_BGRA_8888: | ||
811 | case MDP_RGBA_8888: | ||
812 | case MDP_ARGB_8888: | ||
813 | perPixelAlpha = TRUE; | ||
814 | case MDP_XRGB_8888: | ||
815 | inpBpp = 4; | ||
816 | /* | ||
817 | * 8888 = 4bytes | ||
818 | * ARGB = 4Components | ||
819 | * ARGB interleaved | ||
820 | */ | ||
821 | ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS | | ||
822 | PPP_SRC_C1B_8BITS | PPP_SRC_C3A_8BITS | | ||
823 | PPP_SRC_C3_ALPHA_EN | PPP_SRC_BPP_INTERLVD_4BYTES | | ||
824 | PPP_SRC_INTERLVD_4COMPONENTS | PPP_SRC_UNPACK_TIGHT | | ||
825 | PPP_SRC_UNPACK_ALIGN_LSB | | ||
826 | PPP_SRC_FETCH_PLANES_INTERLVD; | ||
827 | |||
828 | if (iBuf->mdpImg.imgType == MDP_BGRA_8888) | ||
829 | packPattern = | ||
830 | MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B, | ||
831 | 8); | ||
832 | else if (iBuf->mdpImg.imgType == MDP_RGBA_8888) | ||
833 | packPattern = | ||
834 | MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R, | ||
835 | 8); | ||
836 | else | ||
837 | packPattern = | ||
838 | MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B, | ||
839 | 8); | ||
840 | |||
841 | ppp_operation_reg |= PPP_OP_COLOR_SPACE_RGB | | ||
842 | PPP_OP_SRC_CHROMA_RGB | PPP_OP_DST_CHROMA_RGB; | ||
843 | break; | ||
844 | |||
845 | case MDP_Y_CBCR_H2V2: | ||
846 | case MDP_Y_CRCB_H2V2: | ||
847 | inpBpp = 1; | ||
848 | src1 = (uint8 *) iBuf->mdpImg.cbcr_addr; | ||
849 | |||
850 | /* | ||
851 | * CbCr = 2bytes | ||
852 | * CbCr = 2Components | ||
853 | * Y+CbCr | ||
854 | */ | ||
855 | ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS | | ||
856 | PPP_SRC_C1B_8BITS | PPP_SRC_BPP_INTERLVD_2BYTES | | ||
857 | PPP_SRC_INTERLVD_2COMPONENTS | PPP_SRC_UNPACK_TIGHT | | ||
858 | PPP_SRC_UNPACK_ALIGN_LSB | | ||
859 | PPP_SRC_FETCH_PLANES_PSEUDOPLNR; | ||
860 | |||
861 | if (iBuf->mdpImg.imgType == MDP_Y_CRCB_H2V2) | ||
862 | packPattern = | ||
863 | MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8); | ||
864 | else | ||
865 | packPattern = | ||
866 | MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8); | ||
867 | |||
868 | ppp_operation_reg |= PPP_OP_COLOR_SPACE_YCBCR | | ||
869 | PPP_OP_SRC_CHROMA_420 | | ||
870 | PPP_OP_SRC_CHROMA_COSITE | | ||
871 | PPP_OP_DST_CHROMA_RGB | PPP_OP_DST_CHROMA_COSITE; | ||
872 | |||
873 | inputRGB = FALSE; | ||
874 | sh_slice = sv_slice = 2; | ||
875 | break; | ||
876 | |||
877 | case MDP_YCRYCB_H2V1: | ||
878 | inpBpp = 2; | ||
879 | ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | | ||
880 | PPP_SRC_C0G_8BITS | | ||
881 | PPP_SRC_C1B_8BITS | | ||
882 | PPP_SRC_C3A_8BITS | | ||
883 | PPP_SRC_BPP_INTERLVD_2BYTES | | ||
884 | PPP_SRC_INTERLVD_4COMPONENTS | | ||
885 | PPP_SRC_UNPACK_TIGHT | PPP_SRC_UNPACK_ALIGN_LSB; | ||
886 | |||
887 | packPattern = | ||
888 | MDP_GET_PACK_PATTERN(CLR_Y, CLR_CR, CLR_Y, CLR_CB, 8); | ||
889 | |||
890 | ppp_operation_reg |= PPP_OP_SRC_CHROMA_H2V1 | | ||
891 | PPP_OP_SRC_CHROMA_COSITE | PPP_OP_DST_CHROMA_COSITE; | ||
892 | |||
893 | /* | ||
894 | * if it's TV-Out/MDP_YCRYCB_H2V1, let's go through the | ||
895 | * preloaded inverse gamma setting of 2.2 since they're | ||
896 | * symetric when the content is non-linear | ||
897 | * ppp_lookUp_enable = TRUE; | ||
898 | */ | ||
899 | |||
900 | /* x and width must be even number */ | ||
901 | iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2; | ||
902 | iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2; | ||
903 | iBuf->roi.x = (iBuf->roi.x / 2) * 2; | ||
904 | iBuf->roi.width = (iBuf->roi.width / 2) * 2; | ||
905 | |||
906 | inputRGB = FALSE; | ||
907 | sh_slice = 2; | ||
908 | break; | ||
909 | |||
910 | case MDP_Y_CBCR_H2V1: | ||
911 | case MDP_Y_CRCB_H2V1: | ||
912 | inpBpp = 1; | ||
913 | src1 = (uint8 *) iBuf->mdpImg.cbcr_addr; | ||
914 | |||
915 | ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | | ||
916 | PPP_SRC_C0G_8BITS | | ||
917 | PPP_SRC_C1B_8BITS | | ||
918 | PPP_SRC_C3A_8BITS | | ||
919 | PPP_SRC_BPP_INTERLVD_2BYTES | | ||
920 | PPP_SRC_INTERLVD_2COMPONENTS | | ||
921 | PPP_SRC_UNPACK_TIGHT | | ||
922 | PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_PSEUDOPLNR; | ||
923 | |||
924 | if (iBuf->mdpImg.imgType == MDP_Y_CBCR_H2V1) | ||
925 | packPattern = | ||
926 | MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8); | ||
927 | else | ||
928 | packPattern = | ||
929 | MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8); | ||
930 | |||
931 | ppp_operation_reg |= PPP_OP_SRC_CHROMA_H2V1 | | ||
932 | PPP_OP_SRC_CHROMA_COSITE | PPP_OP_DST_CHROMA_COSITE; | ||
933 | inputRGB = FALSE; | ||
934 | sh_slice = 2; | ||
935 | break; | ||
936 | |||
937 | case MDP_BGR_565: | ||
938 | case MDP_RGB_565: | ||
939 | default: | ||
940 | inpBpp = 2; | ||
941 | /* | ||
942 | * 565 = 2bytes | ||
943 | * RGB = 3Components | ||
944 | * RGB interleaved | ||
945 | */ | ||
946 | ppp_src_cfg_reg = PPP_SRC_C2R_5BITS | PPP_SRC_C0G_6BITS | | ||
947 | PPP_SRC_C1B_5BITS | PPP_SRC_BPP_INTERLVD_2BYTES | | ||
948 | PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT | | ||
949 | PPP_SRC_UNPACK_ALIGN_LSB | | ||
950 | PPP_SRC_FETCH_PLANES_INTERLVD; | ||
951 | |||
952 | if (iBuf->mdpImg.imgType == MDP_RGB_565) | ||
953 | packPattern = | ||
954 | MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8); | ||
955 | else | ||
956 | packPattern = | ||
957 | MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8); | ||
958 | |||
959 | ppp_operation_reg |= PPP_OP_COLOR_SPACE_RGB | | ||
960 | PPP_OP_SRC_CHROMA_RGB | PPP_OP_DST_CHROMA_RGB; | ||
961 | break; | ||
962 | |||
963 | } | ||
964 | |||
965 | if (pseudoplanr_output) | ||
966 | ppp_dst_cfg_reg |= PPP_DST_PLANE_PSEUDOPLN; | ||
967 | |||
968 | /* YCbCr to RGB color conversion flag */ | ||
969 | if ((!inputRGB) && (outputRGB)) { | ||
970 | ppp_operation_reg |= PPP_OP_CONVERT_YCBCR2RGB | | ||
971 | PPP_OP_CONVERT_ON; | ||
972 | |||
973 | /* | ||
974 | * primary/secondary is sort of misleading term...but | ||
975 | * in mdp2.2/3.0 we only use primary matrix (forward/rev) | ||
976 | * in mdp3.1 we use set1(prim) and set2(secd) | ||
977 | */ | ||
978 | #ifdef CONFIG_FB_MSM_MDP31 | ||
979 | ppp_operation_reg |= PPP_OP_CONVERT_MATRIX_SECONDARY | | ||
980 | PPP_OP_DST_RGB; | ||
981 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0240, 0); | ||
982 | #endif | ||
983 | |||
984 | if (ppp_lookUp_enable) { | ||
985 | ppp_operation_reg |= PPP_OP_LUT_C0_ON | | ||
986 | PPP_OP_LUT_C1_ON | PPP_OP_LUT_C2_ON; | ||
987 | } | ||
988 | } | ||
989 | /* RGB to YCbCr color conversion flag */ | ||
990 | if ((inputRGB) && (!outputRGB)) { | ||
991 | ppp_operation_reg |= PPP_OP_CONVERT_RGB2YCBCR | | ||
992 | PPP_OP_CONVERT_ON; | ||
993 | |||
994 | #ifdef CONFIG_FB_MSM_MDP31 | ||
995 | ppp_operation_reg |= PPP_OP_CONVERT_MATRIX_PRIMARY | | ||
996 | PPP_OP_DST_YCBCR; | ||
997 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0240, 0x1e); | ||
998 | #endif | ||
999 | |||
1000 | if (ppp_lookUp_enable) { | ||
1001 | ppp_operation_reg |= PPP_OP_LUT_C0_ON | | ||
1002 | PPP_OP_LUT_C1_ON | PPP_OP_LUT_C2_ON; | ||
1003 | } | ||
1004 | } | ||
1005 | /* YCbCr to YCbCr color conversion flag */ | ||
1006 | if ((!inputRGB) && (!outputRGB)) { | ||
1007 | if ((ppp_lookUp_enable) && | ||
1008 | (iBuf->mdpImg.imgType != iBuf->ibuf_type)) { | ||
1009 | ppp_operation_reg |= PPP_OP_LUT_C0_ON; | ||
1010 | } | ||
1011 | } | ||
1012 | |||
1013 | ppp_src_cfg_reg |= (iBuf->roi.x % 2) ? PPP_SRC_BPP_ROI_ODD_X : 0; | ||
1014 | ppp_src_cfg_reg |= (iBuf->roi.y % 2) ? PPP_SRC_BPP_ROI_ODD_Y : 0; | ||
1015 | |||
1016 | if (req->flags & MDP_DEINTERLACE) | ||
1017 | ppp_operation_reg |= PPP_OP_DEINT_EN; | ||
1018 | |||
1019 | /* Dither at DMA side only since iBuf format is RGB888 */ | ||
1020 | if (iBuf->mdpImg.mdpOp & MDPOP_DITHER) | ||
1021 | ppp_operation_reg |= PPP_OP_DITHER_EN; | ||
1022 | |||
1023 | if (iBuf->mdpImg.mdpOp & MDPOP_ROTATION) { | ||
1024 | ppp_operation_reg |= PPP_OP_ROT_ON; | ||
1025 | |||
1026 | if (iBuf->mdpImg.mdpOp & MDPOP_ROT90) { | ||
1027 | ppp_operation_reg |= PPP_OP_ROT_90; | ||
1028 | } | ||
1029 | if (iBuf->mdpImg.mdpOp & MDPOP_LR) { | ||
1030 | ppp_operation_reg |= PPP_OP_FLIP_LR; | ||
1031 | } | ||
1032 | if (iBuf->mdpImg.mdpOp & MDPOP_UD) { | ||
1033 | ppp_operation_reg |= PPP_OP_FLIP_UD; | ||
1034 | } | ||
1035 | } | ||
1036 | |||
1037 | src0_ystride = src_width * inpBpp; | ||
1038 | dest0_ystride = iBuf->ibuf_width * iBuf->bpp; | ||
1039 | |||
1040 | /* no need to care about rotation since it's the real-XY. */ | ||
1041 | dst_roi_width = iBuf->roi.dst_width; | ||
1042 | dst_roi_height = iBuf->roi.dst_height; | ||
1043 | |||
1044 | src0 = (uint8 *) iBuf->mdpImg.bmy_addr; | ||
1045 | dest0 = (uint8 *) iBuf->buf; | ||
1046 | |||
1047 | /* Jumping from Y-Plane to Chroma Plane */ | ||
1048 | dest1 = mdp_get_chroma_addr(iBuf); | ||
1049 | |||
1050 | /* first pixel addr calculation */ | ||
1051 | mdp_adjust_start_addr(&src0, &src1, sv_slice, sh_slice, iBuf->roi.x, | ||
1052 | iBuf->roi.y, src_width, src_height, inpBpp, iBuf, | ||
1053 | 0); | ||
1054 | mdp_adjust_start_addr(&dest0, &dest1, dv_slice, dh_slice, | ||
1055 | iBuf->roi.lcd_x, iBuf->roi.lcd_y, | ||
1056 | iBuf->ibuf_width, iBuf->ibuf_height, iBuf->bpp, | ||
1057 | iBuf, 2); | ||
1058 | |||
1059 | /* set scale operation */ | ||
1060 | mdp_set_scale(iBuf, dst_roi_width, dst_roi_height, | ||
1061 | inputRGB, outputRGB, &ppp_operation_reg); | ||
1062 | |||
1063 | /* | ||
1064 | * setting background source for blending | ||
1065 | */ | ||
1066 | mdp_set_blend_attr(iBuf, &alpha, &tpVal, perPixelAlpha, | ||
1067 | &ppp_operation_reg); | ||
1068 | |||
1069 | if (ppp_operation_reg & PPP_OP_BLEND_ON) { | ||
1070 | mdp_ppp_setbg(iBuf); | ||
1071 | |||
1072 | if (iBuf->ibuf_type == MDP_YCRYCB_H2V1) { | ||
1073 | ppp_operation_reg |= PPP_OP_BG_CHROMA_H2V1; | ||
1074 | |||
1075 | if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP) { | ||
1076 | tpVal = mdp_conv_matx_rgb2yuv(tpVal, | ||
1077 | (uint16 *) & | ||
1078 | mdp_ccs_rgb2yuv, | ||
1079 | &mdp_plv[0], NULL); | ||
1080 | } | ||
1081 | } | ||
1082 | } | ||
1083 | |||
1084 | /* | ||
1085 | * 0x0004: enable dbg bus | ||
1086 | * 0x0100: "don't care" Edge Condit until scaling is on | ||
1087 | * 0x0104: xrc tile x&y size u7.6 format = 7bit.6bit | ||
1088 | * 0x0108: src pixel size | ||
1089 | * 0x010c: component plane 0 starting address | ||
1090 | * 0x011c: component plane 0 ystride | ||
1091 | * 0x0124: PPP source config register | ||
1092 | * 0x0128: unpacked pattern from lsb to msb (eg. RGB->BGR) | ||
1093 | */ | ||
1094 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0108, (iBuf->roi.height << 16 | | ||
1095 | iBuf->roi.width)); | ||
1096 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x010c, src0); /* comp.plane 0 */ | ||
1097 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0110, src1); /* comp.plane 1 */ | ||
1098 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x011c, | ||
1099 | (src0_ystride << 16 | src0_ystride)); | ||
1100 | |||
1101 | /* setup for rgb 565 */ | ||
1102 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0124, ppp_src_cfg_reg); | ||
1103 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0128, packPattern); | ||
1104 | /* | ||
1105 | * 0x0138: PPP destination operation register | ||
1106 | * 0x014c: constant_alpha|transparent_color | ||
1107 | * 0x0150: PPP destination config register | ||
1108 | * 0x0154: PPP packing pattern | ||
1109 | */ | ||
1110 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0138, ppp_operation_reg); | ||
1111 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x014c, alpha << 24 | tpVal); | ||
1112 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0150, ppp_dst_cfg_reg); | ||
1113 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0154, dst_packPattern); | ||
1114 | |||
1115 | /* | ||
1116 | * 0x0164: ROI height and width | ||
1117 | * 0x0168: Component Plane 0 starting addr | ||
1118 | * 0x016c: Component Plane 1 starting addr | ||
1119 | * 0x0178: Component Plane 1/0 y stride | ||
1120 | */ | ||
1121 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0164, | ||
1122 | (dst_roi_height << 16 | dst_roi_width)); | ||
1123 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0168, dest0); | ||
1124 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x016c, dest1); | ||
1125 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0178, | ||
1126 | (dest0_ystride << 16 | dest0_ystride)); | ||
1127 | |||
1128 | flush_imgs(req, inpBpp, iBuf->bpp, p_src_file, p_dst_file); | ||
1129 | #ifdef CONFIG_MDP_PPP_ASYNC_OP | ||
1130 | mdp_ppp_process_curr_djob(); | ||
1131 | #else | ||
1132 | mdp_pipe_kickoff(MDP_PPP_TERM, mfd); | ||
1133 | #endif | ||
1134 | } | ||
1135 | |||
1136 | static int mdp_ppp_verify_req(struct mdp_blit_req *req) | ||
1137 | { | ||
1138 | u32 src_width, src_height, dst_width, dst_height; | ||
1139 | |||
1140 | if (req == NULL) | ||
1141 | return -1; | ||
1142 | |||
1143 | if (MDP_IS_IMGTYPE_BAD(req->src.format) || | ||
1144 | MDP_IS_IMGTYPE_BAD(req->dst.format)) | ||
1145 | return -1; | ||
1146 | |||
1147 | if ((req->src.width == 0) || (req->src.height == 0) || | ||
1148 | (req->src_rect.w == 0) || (req->src_rect.h == 0) || | ||
1149 | (req->dst.width == 0) || (req->dst.height == 0) || | ||
1150 | (req->dst_rect.w == 0) || (req->dst_rect.h == 0)) | ||
1151 | |||
1152 | return -1; | ||
1153 | |||
1154 | if (((req->src_rect.x + req->src_rect.w) > req->src.width) || | ||
1155 | ((req->src_rect.y + req->src_rect.h) > req->src.height)) | ||
1156 | return -1; | ||
1157 | |||
1158 | if (((req->dst_rect.x + req->dst_rect.w) > req->dst.width) || | ||
1159 | ((req->dst_rect.y + req->dst_rect.h) > req->dst.height)) | ||
1160 | return -1; | ||
1161 | |||
1162 | /* | ||
1163 | * scaling range check | ||
1164 | */ | ||
1165 | src_width = req->src_rect.w; | ||
1166 | src_height = req->src_rect.h; | ||
1167 | |||
1168 | if (req->flags & MDP_ROT_90) { | ||
1169 | dst_width = req->dst_rect.h; | ||
1170 | dst_height = req->dst_rect.w; | ||
1171 | } else { | ||
1172 | dst_width = req->dst_rect.w; | ||
1173 | dst_height = req->dst_rect.h; | ||
1174 | } | ||
1175 | |||
1176 | switch (req->dst.format) { | ||
1177 | case MDP_Y_CRCB_H2V2: | ||
1178 | case MDP_Y_CBCR_H2V2: | ||
1179 | src_width = (src_width / 2) * 2; | ||
1180 | src_height = (src_height / 2) * 2; | ||
1181 | dst_width = (src_width / 2) * 2; | ||
1182 | dst_height = (src_height / 2) * 2; | ||
1183 | break; | ||
1184 | |||
1185 | case MDP_Y_CRCB_H2V1: | ||
1186 | case MDP_Y_CBCR_H2V1: | ||
1187 | case MDP_YCRYCB_H2V1: | ||
1188 | src_width = (src_width / 2) * 2; | ||
1189 | dst_width = (src_width / 2) * 2; | ||
1190 | break; | ||
1191 | |||
1192 | default: | ||
1193 | break; | ||
1194 | } | ||
1195 | |||
1196 | if (((MDP_SCALE_Q_FACTOR * dst_width) / src_width > | ||
1197 | MDP_MAX_X_SCALE_FACTOR) | ||
1198 | || ((MDP_SCALE_Q_FACTOR * dst_width) / src_width < | ||
1199 | MDP_MIN_X_SCALE_FACTOR)) | ||
1200 | return -1; | ||
1201 | |||
1202 | if (((MDP_SCALE_Q_FACTOR * dst_height) / src_height > | ||
1203 | MDP_MAX_Y_SCALE_FACTOR) | ||
1204 | || ((MDP_SCALE_Q_FACTOR * dst_height) / src_height < | ||
1205 | MDP_MIN_Y_SCALE_FACTOR)) | ||
1206 | return -1; | ||
1207 | |||
1208 | return 0; | ||
1209 | } | ||
1210 | |||
1211 | /** | ||
1212 | * get_gem_img() - retrieve drm obj's start address and size | ||
1213 | * @img: contains drm file descriptor and gem handle | ||
1214 | * @start: repository of starting address of drm obj allocated memory | ||
1215 | * @len: repository of size of drm obj alloacted memory | ||
1216 | * | ||
1217 | **/ | ||
1218 | int get_gem_img(struct mdp_img *img, unsigned long *start, unsigned long *len) | ||
1219 | { | ||
1220 | panic("waaaaaaaah"); | ||
1221 | //return kgsl_gem_obj_addr(img->memory_id, (int)img->priv, start, len); | ||
1222 | } | ||
1223 | |||
1224 | int get_img(struct mdp_img *img, struct fb_info *info, unsigned long *start, | ||
1225 | unsigned long *len, struct file **pp_file) | ||
1226 | { | ||
1227 | int put_needed, ret = 0; | ||
1228 | struct file *file; | ||
1229 | unsigned long vstart; | ||
1230 | #ifdef CONFIG_ANDROID_PMEM | ||
1231 | if (!get_pmem_file(img->memory_id, start, &vstart, len, pp_file)) | ||
1232 | return 0; | ||
1233 | #endif | ||
1234 | file = fget_light(img->memory_id, &put_needed); | ||
1235 | if (file == NULL) | ||
1236 | return -1; | ||
1237 | |||
1238 | if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) { | ||
1239 | *start = info->fix.smem_start; | ||
1240 | *len = info->fix.smem_len; | ||
1241 | *pp_file = file; | ||
1242 | } else { | ||
1243 | ret = -1; | ||
1244 | fput_light(file, put_needed); | ||
1245 | } | ||
1246 | return ret; | ||
1247 | } | ||
1248 | |||
1249 | int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req, | ||
1250 | struct file **pp_src_file, struct file **pp_dst_file) | ||
1251 | { | ||
1252 | unsigned long src_start, dst_start; | ||
1253 | unsigned long src_len = 0; | ||
1254 | unsigned long dst_len = 0; | ||
1255 | MDPIBUF iBuf; | ||
1256 | u32 dst_width, dst_height; | ||
1257 | struct file *p_src_file = 0 , *p_dst_file = 0; | ||
1258 | struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; | ||
1259 | |||
1260 | if (req->dst.format == MDP_FB_FORMAT) | ||
1261 | req->dst.format = mfd->fb_imgType; | ||
1262 | if (req->src.format == MDP_FB_FORMAT) | ||
1263 | req->src.format = mfd->fb_imgType; | ||
1264 | |||
1265 | if (req->flags & MDP_BLIT_SRC_GEM) { | ||
1266 | if (get_gem_img(&req->src, &src_start, &src_len) < 0) | ||
1267 | return -1; | ||
1268 | } else { | ||
1269 | get_img(&req->src, info, &src_start, &src_len, &p_src_file); | ||
1270 | } | ||
1271 | if (src_len == 0) { | ||
1272 | printk(KERN_ERR "mdp_ppp: could not retrieve image from " | ||
1273 | "memory\n"); | ||
1274 | return -1; | ||
1275 | } | ||
1276 | |||
1277 | if (req->flags & MDP_BLIT_DST_GEM) { | ||
1278 | if (get_gem_img(&req->dst, &dst_start, &dst_len) < 0) | ||
1279 | return -1; | ||
1280 | } else { | ||
1281 | get_img(&req->dst, info, &dst_start, &dst_len, &p_dst_file); | ||
1282 | } | ||
1283 | if (dst_len == 0) { | ||
1284 | printk(KERN_ERR "mdp_ppp: could not retrieve image from " | ||
1285 | "memory\n"); | ||
1286 | return -1; | ||
1287 | } | ||
1288 | *pp_src_file = p_src_file; | ||
1289 | *pp_dst_file = p_dst_file; | ||
1290 | if (mdp_ppp_verify_req(req)) { | ||
1291 | printk(KERN_ERR "mdp_ppp: invalid image!\n"); | ||
1292 | return -1; | ||
1293 | } | ||
1294 | |||
1295 | iBuf.ibuf_width = req->dst.width; | ||
1296 | iBuf.ibuf_height = req->dst.height; | ||
1297 | iBuf.bpp = bytes_per_pixel[req->dst.format]; | ||
1298 | |||
1299 | iBuf.ibuf_type = req->dst.format; | ||
1300 | iBuf.buf = (uint8 *) dst_start; | ||
1301 | iBuf.buf += req->dst.offset; | ||
1302 | |||
1303 | iBuf.roi.lcd_x = req->dst_rect.x; | ||
1304 | iBuf.roi.lcd_y = req->dst_rect.y; | ||
1305 | iBuf.roi.dst_width = req->dst_rect.w; | ||
1306 | iBuf.roi.dst_height = req->dst_rect.h; | ||
1307 | |||
1308 | iBuf.roi.x = req->src_rect.x; | ||
1309 | iBuf.roi.width = req->src_rect.w; | ||
1310 | iBuf.roi.y = req->src_rect.y; | ||
1311 | iBuf.roi.height = req->src_rect.h; | ||
1312 | |||
1313 | iBuf.mdpImg.width = req->src.width; | ||
1314 | iBuf.mdpImg.imgType = req->src.format; | ||
1315 | |||
1316 | iBuf.mdpImg.bmy_addr = (uint32 *) (src_start + req->src.offset); | ||
1317 | iBuf.mdpImg.cbcr_addr = | ||
1318 | (uint32 *) ((uint32) iBuf.mdpImg.bmy_addr + | ||
1319 | req->src.width * req->src.height); | ||
1320 | |||
1321 | iBuf.mdpImg.mdpOp = MDPOP_NOP; | ||
1322 | |||
1323 | /* blending check */ | ||
1324 | if (req->transp_mask != MDP_TRANSP_NOP) { | ||
1325 | iBuf.mdpImg.mdpOp |= MDPOP_TRANSP; | ||
1326 | iBuf.mdpImg.tpVal = req->transp_mask; | ||
1327 | iBuf.mdpImg.tpVal = mdp_calc_tpval(&iBuf.mdpImg); | ||
1328 | } | ||
1329 | |||
1330 | req->alpha &= 0xff; | ||
1331 | if (req->alpha < MDP_ALPHA_NOP) { | ||
1332 | iBuf.mdpImg.mdpOp |= MDPOP_ALPHAB; | ||
1333 | iBuf.mdpImg.alpha = req->alpha; | ||
1334 | } | ||
1335 | |||
1336 | /* rotation check */ | ||
1337 | if (req->flags & MDP_FLIP_LR) | ||
1338 | iBuf.mdpImg.mdpOp |= MDPOP_LR; | ||
1339 | if (req->flags & MDP_FLIP_UD) | ||
1340 | iBuf.mdpImg.mdpOp |= MDPOP_UD; | ||
1341 | if (req->flags & MDP_ROT_90) | ||
1342 | iBuf.mdpImg.mdpOp |= MDPOP_ROT90; | ||
1343 | if (req->flags & MDP_DITHER) | ||
1344 | iBuf.mdpImg.mdpOp |= MDPOP_DITHER; | ||
1345 | |||
1346 | if (req->flags & MDP_BLEND_FG_PREMULT) { | ||
1347 | #ifdef CONFIG_FB_MSM_MDP31 | ||
1348 | iBuf.mdpImg.mdpOp |= MDPOP_FG_PM_ALPHA; | ||
1349 | #else | ||
1350 | return -EINVAL; | ||
1351 | #endif | ||
1352 | } | ||
1353 | |||
1354 | if (req->flags & MDP_DEINTERLACE) { | ||
1355 | #ifdef CONFIG_FB_MSM_MDP31 | ||
1356 | if ((req->src.format != MDP_Y_CBCR_H2V2) && | ||
1357 | (req->src.format != MDP_Y_CRCB_H2V2)) | ||
1358 | #endif | ||
1359 | return -EINVAL; | ||
1360 | } | ||
1361 | |||
1362 | /* scale check */ | ||
1363 | if (req->flags & MDP_ROT_90) { | ||
1364 | dst_width = req->dst_rect.h; | ||
1365 | dst_height = req->dst_rect.w; | ||
1366 | } else { | ||
1367 | dst_width = req->dst_rect.w; | ||
1368 | dst_height = req->dst_rect.h; | ||
1369 | } | ||
1370 | |||
1371 | if ((iBuf.roi.width != dst_width) || (iBuf.roi.height != dst_height)) | ||
1372 | iBuf.mdpImg.mdpOp |= MDPOP_ASCALE; | ||
1373 | |||
1374 | if (req->flags & MDP_BLUR) { | ||
1375 | #ifdef CONFIG_FB_MSM_MDP31 | ||
1376 | if (req->flags & MDP_SHARPENING) | ||
1377 | printk(KERN_WARNING | ||
1378 | "mdp: MDP_SHARPENING is set with MDP_BLUR!\n"); | ||
1379 | req->flags |= MDP_SHARPENING; | ||
1380 | req->sharpening_strength = -127; | ||
1381 | #else | ||
1382 | iBuf.mdpImg.mdpOp |= MDPOP_ASCALE | MDPOP_BLUR; | ||
1383 | |||
1384 | #endif | ||
1385 | } | ||
1386 | |||
1387 | if (req->flags & MDP_SHARPENING) { | ||
1388 | #ifdef CONFIG_FB_MSM_MDP31 | ||
1389 | if ((req->sharpening_strength > 127) || | ||
1390 | (req->sharpening_strength < -127)) { | ||
1391 | printk(KERN_ERR | ||
1392 | "%s: sharpening strength out of range\n", | ||
1393 | __func__); | ||
1394 | return -EINVAL; | ||
1395 | } | ||
1396 | |||
1397 | iBuf.mdpImg.mdpOp |= MDPOP_ASCALE | MDPOP_SHARPENING; | ||
1398 | iBuf.mdpImg.sp_value = req->sharpening_strength & 0xff; | ||
1399 | #else | ||
1400 | return -EINVAL; | ||
1401 | #endif | ||
1402 | } | ||
1403 | |||
1404 | down(&mdp_ppp_mutex); | ||
1405 | /* MDP cmd block enable */ | ||
1406 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); | ||
1407 | |||
1408 | #ifdef CONFIG_FB_MSM_MDP31 | ||
1409 | mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file); | ||
1410 | #else | ||
1411 | /* bg tile fetching HW workaround */ | ||
1412 | if (((iBuf.mdpImg.mdpOp & (MDPOP_TRANSP | MDPOP_ALPHAB)) || | ||
1413 | (req->src.format == MDP_ARGB_8888) || | ||
1414 | (req->src.format == MDP_BGRA_8888) || | ||
1415 | (req->src.format == MDP_RGBA_8888)) && | ||
1416 | (iBuf.mdpImg.mdpOp & MDPOP_ROT90) && (req->dst_rect.w <= 16)) { | ||
1417 | int dst_h, src_w, i; | ||
1418 | |||
1419 | src_w = req->src_rect.w; | ||
1420 | dst_h = iBuf.roi.dst_height; | ||
1421 | |||
1422 | for (i = 0; i < (req->dst_rect.h / 16); i++) { | ||
1423 | /* this tile size */ | ||
1424 | iBuf.roi.dst_height = 16; | ||
1425 | iBuf.roi.width = | ||
1426 | (16 * req->src_rect.w) / req->dst_rect.h; | ||
1427 | |||
1428 | /* if it's out of scale range... */ | ||
1429 | if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) / | ||
1430 | iBuf.roi.width) > MDP_MAX_X_SCALE_FACTOR) | ||
1431 | iBuf.roi.width = | ||
1432 | (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) / | ||
1433 | MDP_MAX_X_SCALE_FACTOR; | ||
1434 | else if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) / | ||
1435 | iBuf.roi.width) < MDP_MIN_X_SCALE_FACTOR) | ||
1436 | iBuf.roi.width = | ||
1437 | (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) / | ||
1438 | MDP_MIN_X_SCALE_FACTOR; | ||
1439 | |||
1440 | mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file); | ||
1441 | |||
1442 | /* next tile location */ | ||
1443 | iBuf.roi.lcd_y += 16; | ||
1444 | iBuf.roi.x += iBuf.roi.width; | ||
1445 | |||
1446 | /* this is for a remainder update */ | ||
1447 | dst_h -= 16; | ||
1448 | src_w -= iBuf.roi.width; | ||
1449 | } | ||
1450 | |||
1451 | if ((dst_h < 0) || (src_w < 0)) | ||
1452 | printk | ||
1453 | ("msm_fb: mdp_blt_ex() unexpected result! line:%d\n", | ||
1454 | __LINE__); | ||
1455 | |||
1456 | /* remainder update */ | ||
1457 | if ((dst_h > 0) && (src_w > 0)) { | ||
1458 | u32 tmp_v; | ||
1459 | |||
1460 | iBuf.roi.dst_height = dst_h; | ||
1461 | iBuf.roi.width = src_w; | ||
1462 | |||
1463 | if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) / | ||
1464 | iBuf.roi.width) > MDP_MAX_X_SCALE_FACTOR) { | ||
1465 | tmp_v = | ||
1466 | (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) / | ||
1467 | MDP_MAX_X_SCALE_FACTOR + | ||
1468 | (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) % | ||
1469 | MDP_MAX_X_SCALE_FACTOR ? 1 : 0; | ||
1470 | |||
1471 | /* move x location as roi width gets bigger */ | ||
1472 | iBuf.roi.x -= tmp_v - iBuf.roi.width; | ||
1473 | iBuf.roi.width = tmp_v; | ||
1474 | } else | ||
1475 | if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) / | ||
1476 | iBuf.roi.width) < MDP_MIN_X_SCALE_FACTOR) { | ||
1477 | tmp_v = | ||
1478 | (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) / | ||
1479 | MDP_MIN_X_SCALE_FACTOR + | ||
1480 | (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) % | ||
1481 | MDP_MIN_X_SCALE_FACTOR ? 1 : 0; | ||
1482 | |||
1483 | /* | ||
1484 | * we don't move x location for continuity of | ||
1485 | * source image | ||
1486 | */ | ||
1487 | iBuf.roi.width = tmp_v; | ||
1488 | } | ||
1489 | |||
1490 | mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file); | ||
1491 | } | ||
1492 | } else { | ||
1493 | mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file); | ||
1494 | } | ||
1495 | #endif | ||
1496 | |||
1497 | /* MDP cmd block disable */ | ||
1498 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); | ||
1499 | up(&mdp_ppp_mutex); | ||
1500 | |||
1501 | return 0; | ||
1502 | } | ||
diff --git a/drivers/staging/msm/mdp_ppp_dq.c b/drivers/staging/msm/mdp_ppp_dq.c new file mode 100644 index 000000000000..3dc1c0cc61f9 --- /dev/null +++ b/drivers/staging/msm/mdp_ppp_dq.c | |||
@@ -0,0 +1,347 @@ | |||
1 | /* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include "mdp.h" | ||
19 | |||
20 | static boolean mdp_ppp_intr_flag = FALSE; | ||
21 | static boolean mdp_ppp_busy_flag = FALSE; | ||
22 | |||
23 | /* Queue to keep track of the completed jobs for cleaning */ | ||
24 | static LIST_HEAD(mdp_ppp_djob_clnrq); | ||
25 | static DEFINE_SPINLOCK(mdp_ppp_djob_clnrq_lock); | ||
26 | |||
27 | /* Worker to cleanup Display Jobs */ | ||
28 | static struct workqueue_struct *mdp_ppp_djob_clnr; | ||
29 | |||
30 | /* Display Queue (DQ) for MDP PPP Block */ | ||
31 | static LIST_HEAD(mdp_ppp_dq); | ||
32 | static DEFINE_SPINLOCK(mdp_ppp_dq_lock); | ||
33 | |||
34 | /* Current Display Job for MDP PPP */ | ||
35 | static struct mdp_ppp_djob *curr_djob; | ||
36 | |||
37 | /* Track ret code for the last opeartion */ | ||
38 | static int mdp_ppp_ret_code; | ||
39 | |||
40 | inline int mdp_ppp_get_ret_code(void) | ||
41 | { | ||
42 | return mdp_ppp_ret_code; | ||
43 | } | ||
44 | |||
45 | /* Push <Reg, Val> pair into DQ (if available) to later | ||
46 | * program the MDP PPP Block */ | ||
47 | inline void mdp_ppp_outdw(uint32_t addr, uint32_t data) | ||
48 | { | ||
49 | if (curr_djob) { | ||
50 | |||
51 | /* get the last node of the list. */ | ||
52 | struct mdp_ppp_roi_cmd_set *node = | ||
53 | list_entry(curr_djob->roi_cmd_list.prev, | ||
54 | struct mdp_ppp_roi_cmd_set, node); | ||
55 | |||
56 | /* If a node is already full, create a new one and add it to | ||
57 | * the list (roi_cmd_list). | ||
58 | */ | ||
59 | if (node->ncmds == MDP_PPP_ROI_NODE_SIZE) { | ||
60 | node = kmalloc(sizeof(struct mdp_ppp_roi_cmd_set), | ||
61 | GFP_KERNEL); | ||
62 | if (!node) { | ||
63 | printk(KERN_ERR | ||
64 | "MDP_PPP: not enough memory.\n"); | ||
65 | mdp_ppp_ret_code = -EINVAL; | ||
66 | return; | ||
67 | } | ||
68 | |||
69 | /* no ROI commands initially */ | ||
70 | node->ncmds = 0; | ||
71 | |||
72 | /* add one node to roi_cmd_list. */ | ||
73 | list_add_tail(&node->node, &curr_djob->roi_cmd_list); | ||
74 | } | ||
75 | |||
76 | /* register ROI commands */ | ||
77 | node->cmd[node->ncmds].reg = addr; | ||
78 | node->cmd[node->ncmds].val = data; | ||
79 | node->ncmds++; | ||
80 | } else | ||
81 | /* program MDP PPP block now */ | ||
82 | outpdw((addr), (data)); | ||
83 | } | ||
84 | |||
85 | /* Initialize DQ */ | ||
86 | inline void mdp_ppp_dq_init(void) | ||
87 | { | ||
88 | mdp_ppp_djob_clnr = create_singlethread_workqueue("MDPDJobClnrThrd"); | ||
89 | } | ||
90 | |||
91 | /* Release resources of a job (DJob). */ | ||
92 | static void mdp_ppp_del_djob(struct mdp_ppp_djob *job) | ||
93 | { | ||
94 | struct mdp_ppp_roi_cmd_set *node, *tmp; | ||
95 | |||
96 | /* release mem */ | ||
97 | mdp_ppp_put_img(job->p_src_file, job->p_dst_file); | ||
98 | |||
99 | /* release roi_cmd_list */ | ||
100 | list_for_each_entry_safe(node, tmp, &job->roi_cmd_list, node) { | ||
101 | list_del(&node->node); | ||
102 | kfree(node); | ||
103 | } | ||
104 | |||
105 | /* release job struct */ | ||
106 | kfree(job); | ||
107 | } | ||
108 | |||
109 | /* Worker thread to reclaim resources once a display job is done */ | ||
110 | static void mdp_ppp_djob_cleaner(struct work_struct *work) | ||
111 | { | ||
112 | struct mdp_ppp_djob *job; | ||
113 | |||
114 | MDP_PPP_DEBUG_MSG("mdp ppp display job cleaner started \n"); | ||
115 | |||
116 | /* cleanup display job */ | ||
117 | job = container_of(work, struct mdp_ppp_djob, cleaner.work); | ||
118 | if (likely(work && job)) | ||
119 | mdp_ppp_del_djob(job); | ||
120 | } | ||
121 | |||
122 | /* Create a new Display Job (DJob) */ | ||
123 | inline struct mdp_ppp_djob *mdp_ppp_new_djob(void) | ||
124 | { | ||
125 | struct mdp_ppp_djob *job; | ||
126 | struct mdp_ppp_roi_cmd_set *node; | ||
127 | |||
128 | /* create a new djob */ | ||
129 | job = kmalloc(sizeof(struct mdp_ppp_djob), GFP_KERNEL); | ||
130 | if (!job) | ||
131 | return NULL; | ||
132 | |||
133 | /* add the first node to curr_djob->roi_cmd_list */ | ||
134 | node = kmalloc(sizeof(struct mdp_ppp_roi_cmd_set), GFP_KERNEL); | ||
135 | if (!node) { | ||
136 | kfree(job); | ||
137 | return NULL; | ||
138 | } | ||
139 | |||
140 | /* make this current djob container to keep track of the curr djob not | ||
141 | * used in the async path i.e. no sync needed | ||
142 | * | ||
143 | * Should not contain any references from the past djob | ||
144 | */ | ||
145 | BUG_ON(curr_djob); | ||
146 | curr_djob = job; | ||
147 | INIT_LIST_HEAD(&curr_djob->roi_cmd_list); | ||
148 | |||
149 | /* no ROI commands initially */ | ||
150 | node->ncmds = 0; | ||
151 | INIT_LIST_HEAD(&node->node); | ||
152 | list_add_tail(&node->node, &curr_djob->roi_cmd_list); | ||
153 | |||
154 | /* register this djob with the djob cleaner | ||
155 | * initializes 'work' data struct | ||
156 | */ | ||
157 | INIT_DELAYED_WORK(&curr_djob->cleaner, mdp_ppp_djob_cleaner); | ||
158 | INIT_LIST_HEAD(&curr_djob->entry); | ||
159 | |||
160 | curr_djob->p_src_file = 0; | ||
161 | curr_djob->p_dst_file = 0; | ||
162 | |||
163 | return job; | ||
164 | } | ||
165 | |||
166 | /* Undo the effect of mdp_ppp_new_djob() */ | ||
167 | inline void mdp_ppp_clear_curr_djob(void) | ||
168 | { | ||
169 | if (likely(curr_djob)) { | ||
170 | mdp_ppp_del_djob(curr_djob); | ||
171 | curr_djob = NULL; | ||
172 | } | ||
173 | } | ||
174 | |||
175 | /* Cleanup dirty djobs */ | ||
176 | static void mdp_ppp_flush_dirty_djobs(void *cond) | ||
177 | { | ||
178 | unsigned long flags; | ||
179 | struct mdp_ppp_djob *job; | ||
180 | |||
181 | /* Flush the jobs from the djob clnr queue */ | ||
182 | while (cond && test_bit(0, (unsigned long *)cond)) { | ||
183 | |||
184 | /* Until we are done with the cleanup queue */ | ||
185 | spin_lock_irqsave(&mdp_ppp_djob_clnrq_lock, flags); | ||
186 | if (list_empty(&mdp_ppp_djob_clnrq)) { | ||
187 | spin_unlock_irqrestore(&mdp_ppp_djob_clnrq_lock, flags); | ||
188 | break; | ||
189 | } | ||
190 | |||
191 | MDP_PPP_DEBUG_MSG("flushing djobs ... loop \n"); | ||
192 | |||
193 | /* Retrieve the job that needs to be cleaned */ | ||
194 | job = list_entry(mdp_ppp_djob_clnrq.next, | ||
195 | struct mdp_ppp_djob, entry); | ||
196 | list_del_init(&job->entry); | ||
197 | spin_unlock_irqrestore(&mdp_ppp_djob_clnrq_lock, flags); | ||
198 | |||
199 | /* Keep mem state coherent */ | ||
200 | msm_fb_ensure_mem_coherency_after_dma(job->info, &job->req, 1); | ||
201 | |||
202 | /* Schedule jobs for cleanup | ||
203 | * A seperate worker thread does this */ | ||
204 | queue_delayed_work(mdp_ppp_djob_clnr, &job->cleaner, | ||
205 | mdp_timer_duration); | ||
206 | } | ||
207 | } | ||
208 | |||
209 | /* If MDP PPP engine is busy, wait until it is available again */ | ||
210 | void mdp_ppp_wait(void) | ||
211 | { | ||
212 | unsigned long flags; | ||
213 | int cond = 1; | ||
214 | |||
215 | /* keep flushing dirty djobs as long as MDP PPP engine is busy */ | ||
216 | mdp_ppp_flush_dirty_djobs(&mdp_ppp_busy_flag); | ||
217 | |||
218 | /* block if MDP PPP engine is still busy */ | ||
219 | spin_lock_irqsave(&mdp_ppp_dq_lock, flags); | ||
220 | if (test_bit(0, (unsigned long *)&mdp_ppp_busy_flag)) { | ||
221 | |||
222 | /* prepare for the wakeup event */ | ||
223 | test_and_set_bit(0, (unsigned long *)&mdp_ppp_waiting); | ||
224 | INIT_COMPLETION(mdp_ppp_comp); | ||
225 | spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags); | ||
226 | |||
227 | /* block uninterruptibly until available */ | ||
228 | MDP_PPP_DEBUG_MSG("waiting for mdp... \n"); | ||
229 | wait_for_completion_killable(&mdp_ppp_comp); | ||
230 | |||
231 | /* if MDP PPP engine is still free, | ||
232 | * disable INT_MDP if enabled | ||
233 | */ | ||
234 | spin_lock_irqsave(&mdp_ppp_dq_lock, flags); | ||
235 | if (!test_bit(0, (unsigned long *)&mdp_ppp_busy_flag) && | ||
236 | test_and_clear_bit(0, (unsigned long *)&mdp_ppp_intr_flag)) | ||
237 | mdp_disable_irq(MDP_PPP_TERM); | ||
238 | } | ||
239 | spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags); | ||
240 | |||
241 | /* flush remaining dirty djobs, if any */ | ||
242 | mdp_ppp_flush_dirty_djobs(&cond); | ||
243 | } | ||
244 | |||
245 | /* Program MDP PPP block to process this ROI */ | ||
246 | static void mdp_ppp_process_roi(struct list_head *roi_cmd_list) | ||
247 | { | ||
248 | |||
249 | /* program PPP engine with registered ROI commands */ | ||
250 | struct mdp_ppp_roi_cmd_set *node; | ||
251 | list_for_each_entry(node, roi_cmd_list, node) { | ||
252 | int i = 0; | ||
253 | for (; i < node->ncmds; i++) { | ||
254 | MDP_PPP_DEBUG_MSG("%d: reg: 0x%x val: 0x%x \n", | ||
255 | i, node->cmd[i].reg, node->cmd[i].val); | ||
256 | outpdw(node->cmd[i].reg, node->cmd[i].val); | ||
257 | } | ||
258 | } | ||
259 | |||
260 | /* kickoff MDP PPP engine */ | ||
261 | MDP_PPP_DEBUG_MSG("kicking off mdp \n"); | ||
262 | outpdw(MDP_BASE + 0x30, 0x1000); | ||
263 | } | ||
264 | |||
265 | /* Submit this display job to MDP PPP engine */ | ||
266 | static void mdp_ppp_dispatch_djob(struct mdp_ppp_djob *job) | ||
267 | { | ||
268 | /* enable INT_MDP if disabled */ | ||
269 | if (!test_and_set_bit(0, (unsigned long *)&mdp_ppp_intr_flag)) | ||
270 | mdp_enable_irq(MDP_PPP_TERM); | ||
271 | |||
272 | /* turn on PPP and CMD blocks */ | ||
273 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); | ||
274 | mdp_pipe_ctrl(MDP_PPP_BLOCK, MDP_BLOCK_POWER_ON, FALSE); | ||
275 | |||
276 | /* process this ROI */ | ||
277 | mdp_ppp_process_roi(&job->roi_cmd_list); | ||
278 | } | ||
279 | |||
280 | /* Enqueue this display job to be cleaned up later in "mdp_ppp_djob_done" */ | ||
281 | static inline void mdp_ppp_enqueue_djob(struct mdp_ppp_djob *job) | ||
282 | { | ||
283 | unsigned long flags; | ||
284 | |||
285 | spin_lock_irqsave(&mdp_ppp_dq_lock, flags); | ||
286 | list_add_tail(&job->entry, &mdp_ppp_dq); | ||
287 | spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags); | ||
288 | } | ||
289 | |||
290 | /* First enqueue display job for cleanup and dispatch immediately | ||
291 | * if MDP PPP engine is free */ | ||
292 | void mdp_ppp_process_curr_djob(void) | ||
293 | { | ||
294 | /* enqueue djob */ | ||
295 | mdp_ppp_enqueue_djob(curr_djob); | ||
296 | |||
297 | /* dispatch now if MDP PPP engine is free */ | ||
298 | if (!test_and_set_bit(0, (unsigned long *)&mdp_ppp_busy_flag)) | ||
299 | mdp_ppp_dispatch_djob(curr_djob); | ||
300 | |||
301 | /* done with the current djob */ | ||
302 | curr_djob = NULL; | ||
303 | } | ||
304 | |||
305 | /* Called from mdp_isr - cleanup finished job and start with next | ||
306 | * if available else set MDP PPP engine free */ | ||
307 | void mdp_ppp_djob_done(void) | ||
308 | { | ||
309 | struct mdp_ppp_djob *curr, *next; | ||
310 | unsigned long flags; | ||
311 | |||
312 | /* dequeue current */ | ||
313 | spin_lock_irqsave(&mdp_ppp_dq_lock, flags); | ||
314 | curr = list_entry(mdp_ppp_dq.next, struct mdp_ppp_djob, entry); | ||
315 | list_del_init(&curr->entry); | ||
316 | spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags); | ||
317 | |||
318 | /* cleanup current - enqueue in the djob clnr queue */ | ||
319 | spin_lock_irqsave(&mdp_ppp_djob_clnrq_lock, flags); | ||
320 | list_add_tail(&curr->entry, &mdp_ppp_djob_clnrq); | ||
321 | spin_unlock_irqrestore(&mdp_ppp_djob_clnrq_lock, flags); | ||
322 | |||
323 | /* grab next pending */ | ||
324 | spin_lock_irqsave(&mdp_ppp_dq_lock, flags); | ||
325 | if (!list_empty(&mdp_ppp_dq)) { | ||
326 | next = list_entry(mdp_ppp_dq.next, struct mdp_ppp_djob, | ||
327 | entry); | ||
328 | spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags); | ||
329 | |||
330 | /* process next in the queue */ | ||
331 | mdp_ppp_process_roi(&next->roi_cmd_list); | ||
332 | } else { | ||
333 | /* no pending display job */ | ||
334 | spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags); | ||
335 | |||
336 | /* turn off PPP and CMD blocks - "in_isr" is TRUE */ | ||
337 | mdp_pipe_ctrl(MDP_PPP_BLOCK, MDP_BLOCK_POWER_OFF, TRUE); | ||
338 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, TRUE); | ||
339 | |||
340 | /* notify if waiting */ | ||
341 | if (test_and_clear_bit(0, (unsigned long *)&mdp_ppp_waiting)) | ||
342 | complete(&mdp_ppp_comp); | ||
343 | |||
344 | /* set free */ | ||
345 | test_and_clear_bit(0, (unsigned long *)&mdp_ppp_busy_flag); | ||
346 | } | ||
347 | } | ||
diff --git a/drivers/staging/msm/mdp_ppp_dq.h b/drivers/staging/msm/mdp_ppp_dq.h new file mode 100644 index 000000000000..03e4e9a5f234 --- /dev/null +++ b/drivers/staging/msm/mdp_ppp_dq.h | |||
@@ -0,0 +1,86 @@ | |||
1 | /* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * Redistribution and use in source and binary forms, with or without | ||
4 | * modification, are permitted provided that the following conditions are | ||
5 | * met: | ||
6 | * * Redistributions of source code must retain the above copyright | ||
7 | * notice, this list of conditions and the following disclaimer. | ||
8 | * * Redistributions in binary form must reproduce the above | ||
9 | * copyright notice, this list of conditions and the following | ||
10 | * disclaimer in the documentation and/or other materials provided | ||
11 | * with the distribution. | ||
12 | * * Neither the name of Code Aurora Forum, Inc. nor the names of its | ||
13 | * contributors may be used to endorse or promote products derived | ||
14 | * from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED | ||
17 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT | ||
19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS | ||
20 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | ||
23 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | ||
24 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE | ||
25 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN | ||
26 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
27 | * | ||
28 | */ | ||
29 | |||
30 | #ifndef MDP_PPP_DQ_H | ||
31 | #define MDP_PPP_DQ_H | ||
32 | |||
33 | #include "msm_fb_def.h" | ||
34 | |||
35 | #define MDP_PPP_DEBUG_MSG MSM_FB_DEBUG | ||
36 | |||
37 | /* The maximum number of <Reg,Val> pairs in an mdp_ppp_roi_cmd_set structure (a | ||
38 | * node) | ||
39 | */ | ||
40 | #define MDP_PPP_ROI_NODE_SIZE 32 | ||
41 | |||
42 | /* ROI config command (<Reg,Val> pair) for MDP PPP block */ | ||
43 | struct mdp_ppp_roi_cmd { | ||
44 | uint32_t reg; | ||
45 | uint32_t val; | ||
46 | }; | ||
47 | |||
48 | /* ROI config commands for MDP PPP block are stored in a list of | ||
49 | * mdp_ppp_roi_cmd_set structures (nodes). | ||
50 | */ | ||
51 | struct mdp_ppp_roi_cmd_set { | ||
52 | struct list_head node; | ||
53 | uint32_t ncmds; /* number of commands in this set (node). */ | ||
54 | struct mdp_ppp_roi_cmd cmd[MDP_PPP_ROI_NODE_SIZE]; | ||
55 | }; | ||
56 | |||
57 | /* MDP PPP Display Job (DJob) */ | ||
58 | struct mdp_ppp_djob { | ||
59 | struct list_head entry; | ||
60 | /* One ROI per MDP PPP DJob */ | ||
61 | struct list_head roi_cmd_list; | ||
62 | struct mdp_blit_req req; | ||
63 | struct fb_info *info; | ||
64 | struct delayed_work cleaner; | ||
65 | struct file *p_src_file, *p_dst_file; | ||
66 | }; | ||
67 | |||
68 | extern struct completion mdp_ppp_comp; | ||
69 | extern boolean mdp_ppp_waiting; | ||
70 | extern unsigned long mdp_timer_duration; | ||
71 | |||
72 | unsigned int mdp_ppp_async_op_get(void); | ||
73 | void mdp_ppp_async_op_set(unsigned int flag); | ||
74 | void msm_fb_ensure_mem_coherency_after_dma(struct fb_info *info, | ||
75 | struct mdp_blit_req *req_list, int req_list_count); | ||
76 | void mdp_ppp_put_img(struct file *p_src_file, struct file *p_dst_file); | ||
77 | void mdp_ppp_dq_init(void); | ||
78 | void mdp_ppp_outdw(uint32_t addr, uint32_t data); | ||
79 | struct mdp_ppp_djob *mdp_ppp_new_djob(void); | ||
80 | void mdp_ppp_clear_curr_djob(void); | ||
81 | void mdp_ppp_process_curr_djob(void); | ||
82 | int mdp_ppp_get_ret_code(void); | ||
83 | void mdp_ppp_djob_done(void); | ||
84 | void mdp_ppp_wait(void); | ||
85 | |||
86 | #endif /* MDP_PPP_DQ_H */ | ||
diff --git a/drivers/staging/msm/mdp_ppp_v20.c b/drivers/staging/msm/mdp_ppp_v20.c new file mode 100644 index 000000000000..b5b7271921e0 --- /dev/null +++ b/drivers/staging/msm/mdp_ppp_v20.c | |||
@@ -0,0 +1,2486 @@ | |||
1 | /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/sched.h> | ||
21 | #include <linux/time.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/fb.h> | ||
25 | #include "linux/proc_fs.h" | ||
26 | |||
27 | #include <mach/hardware.h> | ||
28 | #include <linux/io.h> | ||
29 | |||
30 | #include <asm/system.h> | ||
31 | #include <asm/mach-types.h> | ||
32 | #include <linux/semaphore.h> | ||
33 | #include <asm/div64.h> | ||
34 | |||
35 | #include "mdp.h" | ||
36 | #include "msm_fb.h" | ||
37 | |||
38 | static MDP_SCALE_MODE mdp_curr_up_scale_xy; | ||
39 | static MDP_SCALE_MODE mdp_curr_down_scale_x; | ||
40 | static MDP_SCALE_MODE mdp_curr_down_scale_y; | ||
41 | |||
42 | static long long mdp_do_div(long long num, long long den) | ||
43 | { | ||
44 | do_div(num, den); | ||
45 | return num; | ||
46 | } | ||
47 | |||
48 | struct mdp_table_entry mdp_gaussian_blur_table[] = { | ||
49 | /* max variance */ | ||
50 | { 0x5fffc, 0x20000080 }, | ||
51 | { 0x50280, 0x20000080 }, | ||
52 | { 0x5fffc, 0x20000080 }, | ||
53 | { 0x50284, 0x20000080 }, | ||
54 | { 0x5fffc, 0x20000080 }, | ||
55 | { 0x50288, 0x20000080 }, | ||
56 | { 0x5fffc, 0x20000080 }, | ||
57 | { 0x5028c, 0x20000080 }, | ||
58 | { 0x5fffc, 0x20000080 }, | ||
59 | { 0x50290, 0x20000080 }, | ||
60 | { 0x5fffc, 0x20000080 }, | ||
61 | { 0x50294, 0x20000080 }, | ||
62 | { 0x5fffc, 0x20000080 }, | ||
63 | { 0x50298, 0x20000080 }, | ||
64 | { 0x5fffc, 0x20000080 }, | ||
65 | { 0x5029c, 0x20000080 }, | ||
66 | { 0x5fffc, 0x20000080 }, | ||
67 | { 0x502a0, 0x20000080 }, | ||
68 | { 0x5fffc, 0x20000080 }, | ||
69 | { 0x502a4, 0x20000080 }, | ||
70 | { 0x5fffc, 0x20000080 }, | ||
71 | { 0x502a8, 0x20000080 }, | ||
72 | { 0x5fffc, 0x20000080 }, | ||
73 | { 0x502ac, 0x20000080 }, | ||
74 | { 0x5fffc, 0x20000080 }, | ||
75 | { 0x502b0, 0x20000080 }, | ||
76 | { 0x5fffc, 0x20000080 }, | ||
77 | { 0x502b4, 0x20000080 }, | ||
78 | { 0x5fffc, 0x20000080 }, | ||
79 | { 0x502b8, 0x20000080 }, | ||
80 | { 0x5fffc, 0x20000080 }, | ||
81 | { 0x502bc, 0x20000080 }, | ||
82 | { 0x5fffc, 0x20000080 }, | ||
83 | { 0x502c0, 0x20000080 }, | ||
84 | { 0x5fffc, 0x20000080 }, | ||
85 | { 0x502c4, 0x20000080 }, | ||
86 | { 0x5fffc, 0x20000080 }, | ||
87 | { 0x502c8, 0x20000080 }, | ||
88 | { 0x5fffc, 0x20000080 }, | ||
89 | { 0x502cc, 0x20000080 }, | ||
90 | { 0x5fffc, 0x20000080 }, | ||
91 | { 0x502d0, 0x20000080 }, | ||
92 | { 0x5fffc, 0x20000080 }, | ||
93 | { 0x502d4, 0x20000080 }, | ||
94 | { 0x5fffc, 0x20000080 }, | ||
95 | { 0x502d8, 0x20000080 }, | ||
96 | { 0x5fffc, 0x20000080 }, | ||
97 | { 0x502dc, 0x20000080 }, | ||
98 | { 0x5fffc, 0x20000080 }, | ||
99 | { 0x502e0, 0x20000080 }, | ||
100 | { 0x5fffc, 0x20000080 }, | ||
101 | { 0x502e4, 0x20000080 }, | ||
102 | { 0x5fffc, 0x20000080 }, | ||
103 | { 0x502e8, 0x20000080 }, | ||
104 | { 0x5fffc, 0x20000080 }, | ||
105 | { 0x502ec, 0x20000080 }, | ||
106 | { 0x5fffc, 0x20000080 }, | ||
107 | { 0x502f0, 0x20000080 }, | ||
108 | { 0x5fffc, 0x20000080 }, | ||
109 | { 0x502f4, 0x20000080 }, | ||
110 | { 0x5fffc, 0x20000080 }, | ||
111 | { 0x502f8, 0x20000080 }, | ||
112 | { 0x5fffc, 0x20000080 }, | ||
113 | { 0x502fc, 0x20000080 }, | ||
114 | { 0x5fffc, 0x20000080 }, | ||
115 | { 0x50300, 0x20000080 }, | ||
116 | { 0x5fffc, 0x20000080 }, | ||
117 | { 0x50304, 0x20000080 }, | ||
118 | { 0x5fffc, 0x20000080 }, | ||
119 | { 0x50308, 0x20000080 }, | ||
120 | { 0x5fffc, 0x20000080 }, | ||
121 | { 0x5030c, 0x20000080 }, | ||
122 | { 0x5fffc, 0x20000080 }, | ||
123 | { 0x50310, 0x20000080 }, | ||
124 | { 0x5fffc, 0x20000080 }, | ||
125 | { 0x50314, 0x20000080 }, | ||
126 | { 0x5fffc, 0x20000080 }, | ||
127 | { 0x50318, 0x20000080 }, | ||
128 | { 0x5fffc, 0x20000080 }, | ||
129 | { 0x5031c, 0x20000080 }, | ||
130 | { 0x5fffc, 0x20000080 }, | ||
131 | { 0x50320, 0x20000080 }, | ||
132 | { 0x5fffc, 0x20000080 }, | ||
133 | { 0x50324, 0x20000080 }, | ||
134 | { 0x5fffc, 0x20000080 }, | ||
135 | { 0x50328, 0x20000080 }, | ||
136 | { 0x5fffc, 0x20000080 }, | ||
137 | { 0x5032c, 0x20000080 }, | ||
138 | { 0x5fffc, 0x20000080 }, | ||
139 | { 0x50330, 0x20000080 }, | ||
140 | { 0x5fffc, 0x20000080 }, | ||
141 | { 0x50334, 0x20000080 }, | ||
142 | { 0x5fffc, 0x20000080 }, | ||
143 | { 0x50338, 0x20000080 }, | ||
144 | { 0x5fffc, 0x20000080 }, | ||
145 | { 0x5033c, 0x20000080 }, | ||
146 | { 0x5fffc, 0x20000080 }, | ||
147 | { 0x50340, 0x20000080 }, | ||
148 | { 0x5fffc, 0x20000080 }, | ||
149 | { 0x50344, 0x20000080 }, | ||
150 | { 0x5fffc, 0x20000080 }, | ||
151 | { 0x50348, 0x20000080 }, | ||
152 | { 0x5fffc, 0x20000080 }, | ||
153 | { 0x5034c, 0x20000080 }, | ||
154 | { 0x5fffc, 0x20000080 }, | ||
155 | { 0x50350, 0x20000080 }, | ||
156 | { 0x5fffc, 0x20000080 }, | ||
157 | { 0x50354, 0x20000080 }, | ||
158 | { 0x5fffc, 0x20000080 }, | ||
159 | { 0x50358, 0x20000080 }, | ||
160 | { 0x5fffc, 0x20000080 }, | ||
161 | { 0x5035c, 0x20000080 }, | ||
162 | { 0x5fffc, 0x20000080 }, | ||
163 | { 0x50360, 0x20000080 }, | ||
164 | { 0x5fffc, 0x20000080 }, | ||
165 | { 0x50364, 0x20000080 }, | ||
166 | { 0x5fffc, 0x20000080 }, | ||
167 | { 0x50368, 0x20000080 }, | ||
168 | { 0x5fffc, 0x20000080 }, | ||
169 | { 0x5036c, 0x20000080 }, | ||
170 | { 0x5fffc, 0x20000080 }, | ||
171 | { 0x50370, 0x20000080 }, | ||
172 | { 0x5fffc, 0x20000080 }, | ||
173 | { 0x50374, 0x20000080 }, | ||
174 | { 0x5fffc, 0x20000080 }, | ||
175 | { 0x50378, 0x20000080 }, | ||
176 | { 0x5fffc, 0x20000080 }, | ||
177 | { 0x5037c, 0x20000080 }, | ||
178 | }; | ||
179 | |||
180 | static void load_scale_table( | ||
181 | struct mdp_table_entry *table, int len) | ||
182 | { | ||
183 | int i; | ||
184 | for (i = 0; i < len; i++) | ||
185 | MDP_OUTP(MDP_BASE + table[i].reg, table[i].val); | ||
186 | } | ||
187 | |||
188 | static void mdp_load_pr_upscale_table(void) | ||
189 | { | ||
190 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
191 | MDP_OUTP(MDP_BASE + 0x50200, 0x7fc00000); | ||
192 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
193 | MDP_OUTP(MDP_BASE + 0x50204, 0x7fc00000); | ||
194 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
195 | MDP_OUTP(MDP_BASE + 0x50208, 0x7fc00000); | ||
196 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
197 | MDP_OUTP(MDP_BASE + 0x5020c, 0x7fc00000); | ||
198 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
199 | MDP_OUTP(MDP_BASE + 0x50210, 0x7fc00000); | ||
200 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
201 | MDP_OUTP(MDP_BASE + 0x50214, 0x7fc00000); | ||
202 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
203 | MDP_OUTP(MDP_BASE + 0x50218, 0x7fc00000); | ||
204 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
205 | MDP_OUTP(MDP_BASE + 0x5021c, 0x7fc00000); | ||
206 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
207 | MDP_OUTP(MDP_BASE + 0x50220, 0x7fc00000); | ||
208 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
209 | MDP_OUTP(MDP_BASE + 0x50224, 0x7fc00000); | ||
210 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
211 | MDP_OUTP(MDP_BASE + 0x50228, 0x7fc00000); | ||
212 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
213 | MDP_OUTP(MDP_BASE + 0x5022c, 0x7fc00000); | ||
214 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
215 | MDP_OUTP(MDP_BASE + 0x50230, 0x7fc00000); | ||
216 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
217 | MDP_OUTP(MDP_BASE + 0x50234, 0x7fc00000); | ||
218 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
219 | MDP_OUTP(MDP_BASE + 0x50238, 0x7fc00000); | ||
220 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
221 | MDP_OUTP(MDP_BASE + 0x5023c, 0x7fc00000); | ||
222 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
223 | MDP_OUTP(MDP_BASE + 0x50240, 0x0); | ||
224 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
225 | MDP_OUTP(MDP_BASE + 0x50244, 0x0); | ||
226 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
227 | MDP_OUTP(MDP_BASE + 0x50248, 0x0); | ||
228 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
229 | MDP_OUTP(MDP_BASE + 0x5024c, 0x0); | ||
230 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
231 | MDP_OUTP(MDP_BASE + 0x50250, 0x0); | ||
232 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
233 | MDP_OUTP(MDP_BASE + 0x50254, 0x0); | ||
234 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
235 | MDP_OUTP(MDP_BASE + 0x50258, 0x0); | ||
236 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
237 | MDP_OUTP(MDP_BASE + 0x5025c, 0x0); | ||
238 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
239 | MDP_OUTP(MDP_BASE + 0x50260, 0x0); | ||
240 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
241 | MDP_OUTP(MDP_BASE + 0x50264, 0x0); | ||
242 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
243 | MDP_OUTP(MDP_BASE + 0x50268, 0x0); | ||
244 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
245 | MDP_OUTP(MDP_BASE + 0x5026c, 0x0); | ||
246 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
247 | MDP_OUTP(MDP_BASE + 0x50270, 0x0); | ||
248 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
249 | MDP_OUTP(MDP_BASE + 0x50274, 0x0); | ||
250 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
251 | MDP_OUTP(MDP_BASE + 0x50278, 0x0); | ||
252 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
253 | MDP_OUTP(MDP_BASE + 0x5027c, 0x0); | ||
254 | } | ||
255 | |||
256 | static void mdp_load_pr_downscale_table_x_point2TOpoint4(void) | ||
257 | { | ||
258 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
259 | MDP_OUTP(MDP_BASE + 0x50280, 0x7fc00000); | ||
260 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
261 | MDP_OUTP(MDP_BASE + 0x50284, 0x7fc00000); | ||
262 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
263 | MDP_OUTP(MDP_BASE + 0x50288, 0x7fc00000); | ||
264 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
265 | MDP_OUTP(MDP_BASE + 0x5028c, 0x7fc00000); | ||
266 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
267 | MDP_OUTP(MDP_BASE + 0x50290, 0x7fc00000); | ||
268 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
269 | MDP_OUTP(MDP_BASE + 0x50294, 0x7fc00000); | ||
270 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
271 | MDP_OUTP(MDP_BASE + 0x50298, 0x7fc00000); | ||
272 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
273 | MDP_OUTP(MDP_BASE + 0x5029c, 0x7fc00000); | ||
274 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
275 | MDP_OUTP(MDP_BASE + 0x502a0, 0x7fc00000); | ||
276 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
277 | MDP_OUTP(MDP_BASE + 0x502a4, 0x7fc00000); | ||
278 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
279 | MDP_OUTP(MDP_BASE + 0x502a8, 0x7fc00000); | ||
280 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
281 | MDP_OUTP(MDP_BASE + 0x502ac, 0x7fc00000); | ||
282 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
283 | MDP_OUTP(MDP_BASE + 0x502b0, 0x7fc00000); | ||
284 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
285 | MDP_OUTP(MDP_BASE + 0x502b4, 0x7fc00000); | ||
286 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
287 | MDP_OUTP(MDP_BASE + 0x502b8, 0x7fc00000); | ||
288 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
289 | MDP_OUTP(MDP_BASE + 0x502bc, 0x7fc00000); | ||
290 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
291 | MDP_OUTP(MDP_BASE + 0x502c0, 0x0); | ||
292 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
293 | MDP_OUTP(MDP_BASE + 0x502c4, 0x0); | ||
294 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
295 | MDP_OUTP(MDP_BASE + 0x502c8, 0x0); | ||
296 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
297 | MDP_OUTP(MDP_BASE + 0x502cc, 0x0); | ||
298 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
299 | MDP_OUTP(MDP_BASE + 0x502d0, 0x0); | ||
300 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
301 | MDP_OUTP(MDP_BASE + 0x502d4, 0x0); | ||
302 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
303 | MDP_OUTP(MDP_BASE + 0x502d8, 0x0); | ||
304 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
305 | MDP_OUTP(MDP_BASE + 0x502dc, 0x0); | ||
306 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
307 | MDP_OUTP(MDP_BASE + 0x502e0, 0x0); | ||
308 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
309 | MDP_OUTP(MDP_BASE + 0x502e4, 0x0); | ||
310 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
311 | MDP_OUTP(MDP_BASE + 0x502e8, 0x0); | ||
312 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
313 | MDP_OUTP(MDP_BASE + 0x502ec, 0x0); | ||
314 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
315 | MDP_OUTP(MDP_BASE + 0x502f0, 0x0); | ||
316 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
317 | MDP_OUTP(MDP_BASE + 0x502f4, 0x0); | ||
318 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
319 | MDP_OUTP(MDP_BASE + 0x502f8, 0x0); | ||
320 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
321 | MDP_OUTP(MDP_BASE + 0x502fc, 0x0); | ||
322 | } | ||
323 | |||
324 | static void mdp_load_pr_downscale_table_y_point2TOpoint4(void) | ||
325 | { | ||
326 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
327 | MDP_OUTP(MDP_BASE + 0x50300, 0x7fc00000); | ||
328 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
329 | MDP_OUTP(MDP_BASE + 0x50304, 0x7fc00000); | ||
330 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
331 | MDP_OUTP(MDP_BASE + 0x50308, 0x7fc00000); | ||
332 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
333 | MDP_OUTP(MDP_BASE + 0x5030c, 0x7fc00000); | ||
334 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
335 | MDP_OUTP(MDP_BASE + 0x50310, 0x7fc00000); | ||
336 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
337 | MDP_OUTP(MDP_BASE + 0x50314, 0x7fc00000); | ||
338 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
339 | MDP_OUTP(MDP_BASE + 0x50318, 0x7fc00000); | ||
340 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
341 | MDP_OUTP(MDP_BASE + 0x5031c, 0x7fc00000); | ||
342 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
343 | MDP_OUTP(MDP_BASE + 0x50320, 0x7fc00000); | ||
344 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
345 | MDP_OUTP(MDP_BASE + 0x50324, 0x7fc00000); | ||
346 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
347 | MDP_OUTP(MDP_BASE + 0x50328, 0x7fc00000); | ||
348 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
349 | MDP_OUTP(MDP_BASE + 0x5032c, 0x7fc00000); | ||
350 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
351 | MDP_OUTP(MDP_BASE + 0x50330, 0x7fc00000); | ||
352 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
353 | MDP_OUTP(MDP_BASE + 0x50334, 0x7fc00000); | ||
354 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
355 | MDP_OUTP(MDP_BASE + 0x50338, 0x7fc00000); | ||
356 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
357 | MDP_OUTP(MDP_BASE + 0x5033c, 0x7fc00000); | ||
358 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
359 | MDP_OUTP(MDP_BASE + 0x50340, 0x0); | ||
360 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
361 | MDP_OUTP(MDP_BASE + 0x50344, 0x0); | ||
362 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
363 | MDP_OUTP(MDP_BASE + 0x50348, 0x0); | ||
364 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
365 | MDP_OUTP(MDP_BASE + 0x5034c, 0x0); | ||
366 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
367 | MDP_OUTP(MDP_BASE + 0x50350, 0x0); | ||
368 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
369 | MDP_OUTP(MDP_BASE + 0x50354, 0x0); | ||
370 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
371 | MDP_OUTP(MDP_BASE + 0x50358, 0x0); | ||
372 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
373 | MDP_OUTP(MDP_BASE + 0x5035c, 0x0); | ||
374 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
375 | MDP_OUTP(MDP_BASE + 0x50360, 0x0); | ||
376 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
377 | MDP_OUTP(MDP_BASE + 0x50364, 0x0); | ||
378 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
379 | MDP_OUTP(MDP_BASE + 0x50368, 0x0); | ||
380 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
381 | MDP_OUTP(MDP_BASE + 0x5036c, 0x0); | ||
382 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
383 | MDP_OUTP(MDP_BASE + 0x50370, 0x0); | ||
384 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
385 | MDP_OUTP(MDP_BASE + 0x50374, 0x0); | ||
386 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
387 | MDP_OUTP(MDP_BASE + 0x50378, 0x0); | ||
388 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
389 | MDP_OUTP(MDP_BASE + 0x5037c, 0x0); | ||
390 | } | ||
391 | |||
392 | static void mdp_load_pr_downscale_table_x_point4TOpoint6(void) | ||
393 | { | ||
394 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
395 | MDP_OUTP(MDP_BASE + 0x50280, 0x7fc00000); | ||
396 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
397 | MDP_OUTP(MDP_BASE + 0x50284, 0x7fc00000); | ||
398 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
399 | MDP_OUTP(MDP_BASE + 0x50288, 0x7fc00000); | ||
400 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
401 | MDP_OUTP(MDP_BASE + 0x5028c, 0x7fc00000); | ||
402 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
403 | MDP_OUTP(MDP_BASE + 0x50290, 0x7fc00000); | ||
404 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
405 | MDP_OUTP(MDP_BASE + 0x50294, 0x7fc00000); | ||
406 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
407 | MDP_OUTP(MDP_BASE + 0x50298, 0x7fc00000); | ||
408 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
409 | MDP_OUTP(MDP_BASE + 0x5029c, 0x7fc00000); | ||
410 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
411 | MDP_OUTP(MDP_BASE + 0x502a0, 0x7fc00000); | ||
412 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
413 | MDP_OUTP(MDP_BASE + 0x502a4, 0x7fc00000); | ||
414 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
415 | MDP_OUTP(MDP_BASE + 0x502a8, 0x7fc00000); | ||
416 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
417 | MDP_OUTP(MDP_BASE + 0x502ac, 0x7fc00000); | ||
418 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
419 | MDP_OUTP(MDP_BASE + 0x502b0, 0x7fc00000); | ||
420 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
421 | MDP_OUTP(MDP_BASE + 0x502b4, 0x7fc00000); | ||
422 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
423 | MDP_OUTP(MDP_BASE + 0x502b8, 0x7fc00000); | ||
424 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
425 | MDP_OUTP(MDP_BASE + 0x502bc, 0x7fc00000); | ||
426 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
427 | MDP_OUTP(MDP_BASE + 0x502c0, 0x0); | ||
428 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
429 | MDP_OUTP(MDP_BASE + 0x502c4, 0x0); | ||
430 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
431 | MDP_OUTP(MDP_BASE + 0x502c8, 0x0); | ||
432 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
433 | MDP_OUTP(MDP_BASE + 0x502cc, 0x0); | ||
434 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
435 | MDP_OUTP(MDP_BASE + 0x502d0, 0x0); | ||
436 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
437 | MDP_OUTP(MDP_BASE + 0x502d4, 0x0); | ||
438 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
439 | MDP_OUTP(MDP_BASE + 0x502d8, 0x0); | ||
440 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
441 | MDP_OUTP(MDP_BASE + 0x502dc, 0x0); | ||
442 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
443 | MDP_OUTP(MDP_BASE + 0x502e0, 0x0); | ||
444 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
445 | MDP_OUTP(MDP_BASE + 0x502e4, 0x0); | ||
446 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
447 | MDP_OUTP(MDP_BASE + 0x502e8, 0x0); | ||
448 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
449 | MDP_OUTP(MDP_BASE + 0x502ec, 0x0); | ||
450 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
451 | MDP_OUTP(MDP_BASE + 0x502f0, 0x0); | ||
452 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
453 | MDP_OUTP(MDP_BASE + 0x502f4, 0x0); | ||
454 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
455 | MDP_OUTP(MDP_BASE + 0x502f8, 0x0); | ||
456 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
457 | MDP_OUTP(MDP_BASE + 0x502fc, 0x0); | ||
458 | } | ||
459 | |||
460 | static void mdp_load_pr_downscale_table_y_point4TOpoint6(void) | ||
461 | { | ||
462 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
463 | MDP_OUTP(MDP_BASE + 0x50300, 0x7fc00000); | ||
464 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
465 | MDP_OUTP(MDP_BASE + 0x50304, 0x7fc00000); | ||
466 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
467 | MDP_OUTP(MDP_BASE + 0x50308, 0x7fc00000); | ||
468 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
469 | MDP_OUTP(MDP_BASE + 0x5030c, 0x7fc00000); | ||
470 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
471 | MDP_OUTP(MDP_BASE + 0x50310, 0x7fc00000); | ||
472 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
473 | MDP_OUTP(MDP_BASE + 0x50314, 0x7fc00000); | ||
474 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
475 | MDP_OUTP(MDP_BASE + 0x50318, 0x7fc00000); | ||
476 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
477 | MDP_OUTP(MDP_BASE + 0x5031c, 0x7fc00000); | ||
478 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
479 | MDP_OUTP(MDP_BASE + 0x50320, 0x7fc00000); | ||
480 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
481 | MDP_OUTP(MDP_BASE + 0x50324, 0x7fc00000); | ||
482 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
483 | MDP_OUTP(MDP_BASE + 0x50328, 0x7fc00000); | ||
484 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
485 | MDP_OUTP(MDP_BASE + 0x5032c, 0x7fc00000); | ||
486 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
487 | MDP_OUTP(MDP_BASE + 0x50330, 0x7fc00000); | ||
488 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
489 | MDP_OUTP(MDP_BASE + 0x50334, 0x7fc00000); | ||
490 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
491 | MDP_OUTP(MDP_BASE + 0x50338, 0x7fc00000); | ||
492 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
493 | MDP_OUTP(MDP_BASE + 0x5033c, 0x7fc00000); | ||
494 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
495 | MDP_OUTP(MDP_BASE + 0x50340, 0x0); | ||
496 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
497 | MDP_OUTP(MDP_BASE + 0x50344, 0x0); | ||
498 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
499 | MDP_OUTP(MDP_BASE + 0x50348, 0x0); | ||
500 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
501 | MDP_OUTP(MDP_BASE + 0x5034c, 0x0); | ||
502 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
503 | MDP_OUTP(MDP_BASE + 0x50350, 0x0); | ||
504 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
505 | MDP_OUTP(MDP_BASE + 0x50354, 0x0); | ||
506 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
507 | MDP_OUTP(MDP_BASE + 0x50358, 0x0); | ||
508 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
509 | MDP_OUTP(MDP_BASE + 0x5035c, 0x0); | ||
510 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
511 | MDP_OUTP(MDP_BASE + 0x50360, 0x0); | ||
512 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
513 | MDP_OUTP(MDP_BASE + 0x50364, 0x0); | ||
514 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
515 | MDP_OUTP(MDP_BASE + 0x50368, 0x0); | ||
516 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
517 | MDP_OUTP(MDP_BASE + 0x5036c, 0x0); | ||
518 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
519 | MDP_OUTP(MDP_BASE + 0x50370, 0x0); | ||
520 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
521 | MDP_OUTP(MDP_BASE + 0x50374, 0x0); | ||
522 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
523 | MDP_OUTP(MDP_BASE + 0x50378, 0x0); | ||
524 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
525 | MDP_OUTP(MDP_BASE + 0x5037c, 0x0); | ||
526 | } | ||
527 | |||
528 | static void mdp_load_pr_downscale_table_x_point6TOpoint8(void) | ||
529 | { | ||
530 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
531 | MDP_OUTP(MDP_BASE + 0x50280, 0x7fc00000); | ||
532 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
533 | MDP_OUTP(MDP_BASE + 0x50284, 0x7fc00000); | ||
534 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
535 | MDP_OUTP(MDP_BASE + 0x50288, 0x7fc00000); | ||
536 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
537 | MDP_OUTP(MDP_BASE + 0x5028c, 0x7fc00000); | ||
538 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
539 | MDP_OUTP(MDP_BASE + 0x50290, 0x7fc00000); | ||
540 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
541 | MDP_OUTP(MDP_BASE + 0x50294, 0x7fc00000); | ||
542 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
543 | MDP_OUTP(MDP_BASE + 0x50298, 0x7fc00000); | ||
544 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
545 | MDP_OUTP(MDP_BASE + 0x5029c, 0x7fc00000); | ||
546 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
547 | MDP_OUTP(MDP_BASE + 0x502a0, 0x7fc00000); | ||
548 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
549 | MDP_OUTP(MDP_BASE + 0x502a4, 0x7fc00000); | ||
550 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
551 | MDP_OUTP(MDP_BASE + 0x502a8, 0x7fc00000); | ||
552 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
553 | MDP_OUTP(MDP_BASE + 0x502ac, 0x7fc00000); | ||
554 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
555 | MDP_OUTP(MDP_BASE + 0x502b0, 0x7fc00000); | ||
556 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
557 | MDP_OUTP(MDP_BASE + 0x502b4, 0x7fc00000); | ||
558 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
559 | MDP_OUTP(MDP_BASE + 0x502b8, 0x7fc00000); | ||
560 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
561 | MDP_OUTP(MDP_BASE + 0x502bc, 0x7fc00000); | ||
562 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
563 | MDP_OUTP(MDP_BASE + 0x502c0, 0x0); | ||
564 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
565 | MDP_OUTP(MDP_BASE + 0x502c4, 0x0); | ||
566 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
567 | MDP_OUTP(MDP_BASE + 0x502c8, 0x0); | ||
568 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
569 | MDP_OUTP(MDP_BASE + 0x502cc, 0x0); | ||
570 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
571 | MDP_OUTP(MDP_BASE + 0x502d0, 0x0); | ||
572 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
573 | MDP_OUTP(MDP_BASE + 0x502d4, 0x0); | ||
574 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
575 | MDP_OUTP(MDP_BASE + 0x502d8, 0x0); | ||
576 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
577 | MDP_OUTP(MDP_BASE + 0x502dc, 0x0); | ||
578 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
579 | MDP_OUTP(MDP_BASE + 0x502e0, 0x0); | ||
580 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
581 | MDP_OUTP(MDP_BASE + 0x502e4, 0x0); | ||
582 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
583 | MDP_OUTP(MDP_BASE + 0x502e8, 0x0); | ||
584 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
585 | MDP_OUTP(MDP_BASE + 0x502ec, 0x0); | ||
586 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
587 | MDP_OUTP(MDP_BASE + 0x502f0, 0x0); | ||
588 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
589 | MDP_OUTP(MDP_BASE + 0x502f4, 0x0); | ||
590 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
591 | MDP_OUTP(MDP_BASE + 0x502f8, 0x0); | ||
592 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
593 | MDP_OUTP(MDP_BASE + 0x502fc, 0x0); | ||
594 | } | ||
595 | |||
596 | static void mdp_load_pr_downscale_table_y_point6TOpoint8(void) | ||
597 | { | ||
598 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
599 | MDP_OUTP(MDP_BASE + 0x50300, 0x7fc00000); | ||
600 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
601 | MDP_OUTP(MDP_BASE + 0x50304, 0x7fc00000); | ||
602 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
603 | MDP_OUTP(MDP_BASE + 0x50308, 0x7fc00000); | ||
604 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
605 | MDP_OUTP(MDP_BASE + 0x5030c, 0x7fc00000); | ||
606 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
607 | MDP_OUTP(MDP_BASE + 0x50310, 0x7fc00000); | ||
608 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
609 | MDP_OUTP(MDP_BASE + 0x50314, 0x7fc00000); | ||
610 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
611 | MDP_OUTP(MDP_BASE + 0x50318, 0x7fc00000); | ||
612 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
613 | MDP_OUTP(MDP_BASE + 0x5031c, 0x7fc00000); | ||
614 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
615 | MDP_OUTP(MDP_BASE + 0x50320, 0x7fc00000); | ||
616 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
617 | MDP_OUTP(MDP_BASE + 0x50324, 0x7fc00000); | ||
618 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
619 | MDP_OUTP(MDP_BASE + 0x50328, 0x7fc00000); | ||
620 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
621 | MDP_OUTP(MDP_BASE + 0x5032c, 0x7fc00000); | ||
622 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
623 | MDP_OUTP(MDP_BASE + 0x50330, 0x7fc00000); | ||
624 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
625 | MDP_OUTP(MDP_BASE + 0x50334, 0x7fc00000); | ||
626 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
627 | MDP_OUTP(MDP_BASE + 0x50338, 0x7fc00000); | ||
628 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
629 | MDP_OUTP(MDP_BASE + 0x5033c, 0x7fc00000); | ||
630 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
631 | MDP_OUTP(MDP_BASE + 0x50340, 0x0); | ||
632 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
633 | MDP_OUTP(MDP_BASE + 0x50344, 0x0); | ||
634 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
635 | MDP_OUTP(MDP_BASE + 0x50348, 0x0); | ||
636 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
637 | MDP_OUTP(MDP_BASE + 0x5034c, 0x0); | ||
638 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
639 | MDP_OUTP(MDP_BASE + 0x50350, 0x0); | ||
640 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
641 | MDP_OUTP(MDP_BASE + 0x50354, 0x0); | ||
642 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
643 | MDP_OUTP(MDP_BASE + 0x50358, 0x0); | ||
644 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
645 | MDP_OUTP(MDP_BASE + 0x5035c, 0x0); | ||
646 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
647 | MDP_OUTP(MDP_BASE + 0x50360, 0x0); | ||
648 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
649 | MDP_OUTP(MDP_BASE + 0x50364, 0x0); | ||
650 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
651 | MDP_OUTP(MDP_BASE + 0x50368, 0x0); | ||
652 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
653 | MDP_OUTP(MDP_BASE + 0x5036c, 0x0); | ||
654 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
655 | MDP_OUTP(MDP_BASE + 0x50370, 0x0); | ||
656 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
657 | MDP_OUTP(MDP_BASE + 0x50374, 0x0); | ||
658 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
659 | MDP_OUTP(MDP_BASE + 0x50378, 0x0); | ||
660 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
661 | MDP_OUTP(MDP_BASE + 0x5037c, 0x0); | ||
662 | } | ||
663 | |||
664 | static void mdp_load_pr_downscale_table_x_point8TO1(void) | ||
665 | { | ||
666 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
667 | MDP_OUTP(MDP_BASE + 0x50280, 0x7fc00000); | ||
668 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
669 | MDP_OUTP(MDP_BASE + 0x50284, 0x7fc00000); | ||
670 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
671 | MDP_OUTP(MDP_BASE + 0x50288, 0x7fc00000); | ||
672 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
673 | MDP_OUTP(MDP_BASE + 0x5028c, 0x7fc00000); | ||
674 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
675 | MDP_OUTP(MDP_BASE + 0x50290, 0x7fc00000); | ||
676 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
677 | MDP_OUTP(MDP_BASE + 0x50294, 0x7fc00000); | ||
678 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
679 | MDP_OUTP(MDP_BASE + 0x50298, 0x7fc00000); | ||
680 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
681 | MDP_OUTP(MDP_BASE + 0x5029c, 0x7fc00000); | ||
682 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
683 | MDP_OUTP(MDP_BASE + 0x502a0, 0x7fc00000); | ||
684 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
685 | MDP_OUTP(MDP_BASE + 0x502a4, 0x7fc00000); | ||
686 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
687 | MDP_OUTP(MDP_BASE + 0x502a8, 0x7fc00000); | ||
688 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
689 | MDP_OUTP(MDP_BASE + 0x502ac, 0x7fc00000); | ||
690 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
691 | MDP_OUTP(MDP_BASE + 0x502b0, 0x7fc00000); | ||
692 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
693 | MDP_OUTP(MDP_BASE + 0x502b4, 0x7fc00000); | ||
694 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
695 | MDP_OUTP(MDP_BASE + 0x502b8, 0x7fc00000); | ||
696 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
697 | MDP_OUTP(MDP_BASE + 0x502bc, 0x7fc00000); | ||
698 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
699 | MDP_OUTP(MDP_BASE + 0x502c0, 0x0); | ||
700 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
701 | MDP_OUTP(MDP_BASE + 0x502c4, 0x0); | ||
702 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
703 | MDP_OUTP(MDP_BASE + 0x502c8, 0x0); | ||
704 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
705 | MDP_OUTP(MDP_BASE + 0x502cc, 0x0); | ||
706 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
707 | MDP_OUTP(MDP_BASE + 0x502d0, 0x0); | ||
708 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
709 | MDP_OUTP(MDP_BASE + 0x502d4, 0x0); | ||
710 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
711 | MDP_OUTP(MDP_BASE + 0x502d8, 0x0); | ||
712 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
713 | MDP_OUTP(MDP_BASE + 0x502dc, 0x0); | ||
714 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
715 | MDP_OUTP(MDP_BASE + 0x502e0, 0x0); | ||
716 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
717 | MDP_OUTP(MDP_BASE + 0x502e4, 0x0); | ||
718 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
719 | MDP_OUTP(MDP_BASE + 0x502e8, 0x0); | ||
720 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
721 | MDP_OUTP(MDP_BASE + 0x502ec, 0x0); | ||
722 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
723 | MDP_OUTP(MDP_BASE + 0x502f0, 0x0); | ||
724 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
725 | MDP_OUTP(MDP_BASE + 0x502f4, 0x0); | ||
726 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
727 | MDP_OUTP(MDP_BASE + 0x502f8, 0x0); | ||
728 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
729 | MDP_OUTP(MDP_BASE + 0x502fc, 0x0); | ||
730 | } | ||
731 | |||
732 | static void mdp_load_pr_downscale_table_y_point8TO1(void) | ||
733 | { | ||
734 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
735 | MDP_OUTP(MDP_BASE + 0x50300, 0x7fc00000); | ||
736 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
737 | MDP_OUTP(MDP_BASE + 0x50304, 0x7fc00000); | ||
738 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
739 | MDP_OUTP(MDP_BASE + 0x50308, 0x7fc00000); | ||
740 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
741 | MDP_OUTP(MDP_BASE + 0x5030c, 0x7fc00000); | ||
742 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
743 | MDP_OUTP(MDP_BASE + 0x50310, 0x7fc00000); | ||
744 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
745 | MDP_OUTP(MDP_BASE + 0x50314, 0x7fc00000); | ||
746 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
747 | MDP_OUTP(MDP_BASE + 0x50318, 0x7fc00000); | ||
748 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
749 | MDP_OUTP(MDP_BASE + 0x5031c, 0x7fc00000); | ||
750 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
751 | MDP_OUTP(MDP_BASE + 0x50320, 0x7fc00000); | ||
752 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
753 | MDP_OUTP(MDP_BASE + 0x50324, 0x7fc00000); | ||
754 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
755 | MDP_OUTP(MDP_BASE + 0x50328, 0x7fc00000); | ||
756 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
757 | MDP_OUTP(MDP_BASE + 0x5032c, 0x7fc00000); | ||
758 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
759 | MDP_OUTP(MDP_BASE + 0x50330, 0x7fc00000); | ||
760 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
761 | MDP_OUTP(MDP_BASE + 0x50334, 0x7fc00000); | ||
762 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
763 | MDP_OUTP(MDP_BASE + 0x50338, 0x7fc00000); | ||
764 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
765 | MDP_OUTP(MDP_BASE + 0x5033c, 0x7fc00000); | ||
766 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
767 | MDP_OUTP(MDP_BASE + 0x50340, 0x0); | ||
768 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
769 | MDP_OUTP(MDP_BASE + 0x50344, 0x0); | ||
770 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
771 | MDP_OUTP(MDP_BASE + 0x50348, 0x0); | ||
772 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
773 | MDP_OUTP(MDP_BASE + 0x5034c, 0x0); | ||
774 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
775 | MDP_OUTP(MDP_BASE + 0x50350, 0x0); | ||
776 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
777 | MDP_OUTP(MDP_BASE + 0x50354, 0x0); | ||
778 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
779 | MDP_OUTP(MDP_BASE + 0x50358, 0x0); | ||
780 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
781 | MDP_OUTP(MDP_BASE + 0x5035c, 0x0); | ||
782 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
783 | MDP_OUTP(MDP_BASE + 0x50360, 0x0); | ||
784 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
785 | MDP_OUTP(MDP_BASE + 0x50364, 0x0); | ||
786 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
787 | MDP_OUTP(MDP_BASE + 0x50368, 0x0); | ||
788 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
789 | MDP_OUTP(MDP_BASE + 0x5036c, 0x0); | ||
790 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
791 | MDP_OUTP(MDP_BASE + 0x50370, 0x0); | ||
792 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
793 | MDP_OUTP(MDP_BASE + 0x50374, 0x0); | ||
794 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
795 | MDP_OUTP(MDP_BASE + 0x50378, 0x0); | ||
796 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ff); | ||
797 | MDP_OUTP(MDP_BASE + 0x5037c, 0x0); | ||
798 | } | ||
799 | |||
800 | static void mdp_load_bc_upscale_table(void) | ||
801 | { | ||
802 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
803 | MDP_OUTP(MDP_BASE + 0x50200, 0x7fc00000); | ||
804 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xff80000d); | ||
805 | MDP_OUTP(MDP_BASE + 0x50204, 0x7ec003f9); | ||
806 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfec0001c); | ||
807 | MDP_OUTP(MDP_BASE + 0x50208, 0x7d4003f3); | ||
808 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe40002b); | ||
809 | MDP_OUTP(MDP_BASE + 0x5020c, 0x7b8003ed); | ||
810 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfd80003c); | ||
811 | MDP_OUTP(MDP_BASE + 0x50210, 0x794003e8); | ||
812 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc0004d); | ||
813 | MDP_OUTP(MDP_BASE + 0x50214, 0x76c003e4); | ||
814 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfc40005f); | ||
815 | MDP_OUTP(MDP_BASE + 0x50218, 0x73c003e0); | ||
816 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb800071); | ||
817 | MDP_OUTP(MDP_BASE + 0x5021c, 0x708003de); | ||
818 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfac00085); | ||
819 | MDP_OUTP(MDP_BASE + 0x50220, 0x6d0003db); | ||
820 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa000098); | ||
821 | MDP_OUTP(MDP_BASE + 0x50224, 0x698003d9); | ||
822 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf98000ac); | ||
823 | MDP_OUTP(MDP_BASE + 0x50228, 0x654003d8); | ||
824 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf8c000c1); | ||
825 | MDP_OUTP(MDP_BASE + 0x5022c, 0x610003d7); | ||
826 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf84000d5); | ||
827 | MDP_OUTP(MDP_BASE + 0x50230, 0x5c8003d7); | ||
828 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf7c000e9); | ||
829 | MDP_OUTP(MDP_BASE + 0x50234, 0x580003d7); | ||
830 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf74000fd); | ||
831 | MDP_OUTP(MDP_BASE + 0x50238, 0x534003d8); | ||
832 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c00112); | ||
833 | MDP_OUTP(MDP_BASE + 0x5023c, 0x4e8003d8); | ||
834 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6800126); | ||
835 | MDP_OUTP(MDP_BASE + 0x50240, 0x494003da); | ||
836 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600013a); | ||
837 | MDP_OUTP(MDP_BASE + 0x50244, 0x448003db); | ||
838 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600014d); | ||
839 | MDP_OUTP(MDP_BASE + 0x50248, 0x3f4003dd); | ||
840 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00160); | ||
841 | MDP_OUTP(MDP_BASE + 0x5024c, 0x3a4003df); | ||
842 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00172); | ||
843 | MDP_OUTP(MDP_BASE + 0x50250, 0x354003e1); | ||
844 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00184); | ||
845 | MDP_OUTP(MDP_BASE + 0x50254, 0x304003e3); | ||
846 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6000195); | ||
847 | MDP_OUTP(MDP_BASE + 0x50258, 0x2b0003e6); | ||
848 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf64001a6); | ||
849 | MDP_OUTP(MDP_BASE + 0x5025c, 0x260003e8); | ||
850 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c001b4); | ||
851 | MDP_OUTP(MDP_BASE + 0x50260, 0x214003eb); | ||
852 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf78001c2); | ||
853 | MDP_OUTP(MDP_BASE + 0x50264, 0x1c4003ee); | ||
854 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf80001cf); | ||
855 | MDP_OUTP(MDP_BASE + 0x50268, 0x17c003f1); | ||
856 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf90001db); | ||
857 | MDP_OUTP(MDP_BASE + 0x5026c, 0x134003f3); | ||
858 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa0001e5); | ||
859 | MDP_OUTP(MDP_BASE + 0x50270, 0xf0003f6); | ||
860 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb4001ee); | ||
861 | MDP_OUTP(MDP_BASE + 0x50274, 0xac003f9); | ||
862 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc001f5); | ||
863 | MDP_OUTP(MDP_BASE + 0x50278, 0x70003fb); | ||
864 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe4001fb); | ||
865 | MDP_OUTP(MDP_BASE + 0x5027c, 0x34003fe); | ||
866 | } | ||
867 | |||
868 | static void mdp_load_bc_downscale_table_x_point2TOpoint4(void) | ||
869 | { | ||
870 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ac00084); | ||
871 | MDP_OUTP(MDP_BASE + 0x50280, 0x23400083); | ||
872 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b000084); | ||
873 | MDP_OUTP(MDP_BASE + 0x50284, 0x23000083); | ||
874 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b400084); | ||
875 | MDP_OUTP(MDP_BASE + 0x50288, 0x23000082); | ||
876 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b400085); | ||
877 | MDP_OUTP(MDP_BASE + 0x5028c, 0x23000081); | ||
878 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b800085); | ||
879 | MDP_OUTP(MDP_BASE + 0x50290, 0x23000080); | ||
880 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1bc00086); | ||
881 | MDP_OUTP(MDP_BASE + 0x50294, 0x22c0007f); | ||
882 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c000086); | ||
883 | MDP_OUTP(MDP_BASE + 0x50298, 0x2280007f); | ||
884 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c400086); | ||
885 | MDP_OUTP(MDP_BASE + 0x5029c, 0x2280007e); | ||
886 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c800086); | ||
887 | MDP_OUTP(MDP_BASE + 0x502a0, 0x2280007d); | ||
888 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc00086); | ||
889 | MDP_OUTP(MDP_BASE + 0x502a4, 0x2240007d); | ||
890 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc00087); | ||
891 | MDP_OUTP(MDP_BASE + 0x502a8, 0x2240007c); | ||
892 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d000087); | ||
893 | MDP_OUTP(MDP_BASE + 0x502ac, 0x2240007b); | ||
894 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d400087); | ||
895 | MDP_OUTP(MDP_BASE + 0x502b0, 0x2200007b); | ||
896 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d400088); | ||
897 | MDP_OUTP(MDP_BASE + 0x502b4, 0x22400079); | ||
898 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d800088); | ||
899 | MDP_OUTP(MDP_BASE + 0x502b8, 0x22400078); | ||
900 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc00088); | ||
901 | MDP_OUTP(MDP_BASE + 0x502bc, 0x22400077); | ||
902 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc00089); | ||
903 | MDP_OUTP(MDP_BASE + 0x502c0, 0x22000077); | ||
904 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1e000089); | ||
905 | MDP_OUTP(MDP_BASE + 0x502c4, 0x22000076); | ||
906 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1e400089); | ||
907 | MDP_OUTP(MDP_BASE + 0x502c8, 0x22000075); | ||
908 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec00088); | ||
909 | MDP_OUTP(MDP_BASE + 0x502cc, 0x21c00075); | ||
910 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec00089); | ||
911 | MDP_OUTP(MDP_BASE + 0x502d0, 0x21c00074); | ||
912 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f000089); | ||
913 | MDP_OUTP(MDP_BASE + 0x502d4, 0x21c00073); | ||
914 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f400089); | ||
915 | MDP_OUTP(MDP_BASE + 0x502d8, 0x21800073); | ||
916 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f40008a); | ||
917 | MDP_OUTP(MDP_BASE + 0x502dc, 0x21800072); | ||
918 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f80008a); | ||
919 | MDP_OUTP(MDP_BASE + 0x502e0, 0x21800071); | ||
920 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1fc0008a); | ||
921 | MDP_OUTP(MDP_BASE + 0x502e4, 0x21800070); | ||
922 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1fc0008b); | ||
923 | MDP_OUTP(MDP_BASE + 0x502e8, 0x2180006f); | ||
924 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x2000008c); | ||
925 | MDP_OUTP(MDP_BASE + 0x502ec, 0x2140006e); | ||
926 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x2040008c); | ||
927 | MDP_OUTP(MDP_BASE + 0x502f0, 0x2140006d); | ||
928 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x2080008c); | ||
929 | MDP_OUTP(MDP_BASE + 0x502f4, 0x2100006d); | ||
930 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x20c0008c); | ||
931 | MDP_OUTP(MDP_BASE + 0x502f8, 0x2100006c); | ||
932 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x20c0008d); | ||
933 | MDP_OUTP(MDP_BASE + 0x502fc, 0x2100006b); | ||
934 | } | ||
935 | |||
936 | static void mdp_load_bc_downscale_table_y_point2TOpoint4(void) | ||
937 | { | ||
938 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ac00084); | ||
939 | MDP_OUTP(MDP_BASE + 0x50300, 0x23400083); | ||
940 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b000084); | ||
941 | MDP_OUTP(MDP_BASE + 0x50304, 0x23000083); | ||
942 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b400084); | ||
943 | MDP_OUTP(MDP_BASE + 0x50308, 0x23000082); | ||
944 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b400085); | ||
945 | MDP_OUTP(MDP_BASE + 0x5030c, 0x23000081); | ||
946 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1b800085); | ||
947 | MDP_OUTP(MDP_BASE + 0x50310, 0x23000080); | ||
948 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1bc00086); | ||
949 | MDP_OUTP(MDP_BASE + 0x50314, 0x22c0007f); | ||
950 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c000086); | ||
951 | MDP_OUTP(MDP_BASE + 0x50318, 0x2280007f); | ||
952 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c400086); | ||
953 | MDP_OUTP(MDP_BASE + 0x5031c, 0x2280007e); | ||
954 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1c800086); | ||
955 | MDP_OUTP(MDP_BASE + 0x50320, 0x2280007d); | ||
956 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc00086); | ||
957 | MDP_OUTP(MDP_BASE + 0x50324, 0x2240007d); | ||
958 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc00087); | ||
959 | MDP_OUTP(MDP_BASE + 0x50328, 0x2240007c); | ||
960 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d000087); | ||
961 | MDP_OUTP(MDP_BASE + 0x5032c, 0x2240007b); | ||
962 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d400087); | ||
963 | MDP_OUTP(MDP_BASE + 0x50330, 0x2200007b); | ||
964 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d400088); | ||
965 | MDP_OUTP(MDP_BASE + 0x50334, 0x22400079); | ||
966 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1d800088); | ||
967 | MDP_OUTP(MDP_BASE + 0x50338, 0x22400078); | ||
968 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc00088); | ||
969 | MDP_OUTP(MDP_BASE + 0x5033c, 0x22400077); | ||
970 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc00089); | ||
971 | MDP_OUTP(MDP_BASE + 0x50340, 0x22000077); | ||
972 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1e000089); | ||
973 | MDP_OUTP(MDP_BASE + 0x50344, 0x22000076); | ||
974 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1e400089); | ||
975 | MDP_OUTP(MDP_BASE + 0x50348, 0x22000075); | ||
976 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec00088); | ||
977 | MDP_OUTP(MDP_BASE + 0x5034c, 0x21c00075); | ||
978 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec00089); | ||
979 | MDP_OUTP(MDP_BASE + 0x50350, 0x21c00074); | ||
980 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f000089); | ||
981 | MDP_OUTP(MDP_BASE + 0x50354, 0x21c00073); | ||
982 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f400089); | ||
983 | MDP_OUTP(MDP_BASE + 0x50358, 0x21800073); | ||
984 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f40008a); | ||
985 | MDP_OUTP(MDP_BASE + 0x5035c, 0x21800072); | ||
986 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1f80008a); | ||
987 | MDP_OUTP(MDP_BASE + 0x50360, 0x21800071); | ||
988 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1fc0008a); | ||
989 | MDP_OUTP(MDP_BASE + 0x50364, 0x21800070); | ||
990 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1fc0008b); | ||
991 | MDP_OUTP(MDP_BASE + 0x50368, 0x2180006f); | ||
992 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x2000008c); | ||
993 | MDP_OUTP(MDP_BASE + 0x5036c, 0x2140006e); | ||
994 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x2040008c); | ||
995 | MDP_OUTP(MDP_BASE + 0x50370, 0x2140006d); | ||
996 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x2080008c); | ||
997 | MDP_OUTP(MDP_BASE + 0x50374, 0x2100006d); | ||
998 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x20c0008c); | ||
999 | MDP_OUTP(MDP_BASE + 0x50378, 0x2100006c); | ||
1000 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x20c0008d); | ||
1001 | MDP_OUTP(MDP_BASE + 0x5037c, 0x2100006b); | ||
1002 | } | ||
1003 | |||
1004 | static void mdp_load_bc_downscale_table_x_point4TOpoint6(void) | ||
1005 | { | ||
1006 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x740008c); | ||
1007 | MDP_OUTP(MDP_BASE + 0x50280, 0x33800088); | ||
1008 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x800008e); | ||
1009 | MDP_OUTP(MDP_BASE + 0x50284, 0x33400084); | ||
1010 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x8400092); | ||
1011 | MDP_OUTP(MDP_BASE + 0x50288, 0x33000080); | ||
1012 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x9000094); | ||
1013 | MDP_OUTP(MDP_BASE + 0x5028c, 0x3300007b); | ||
1014 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x9c00098); | ||
1015 | MDP_OUTP(MDP_BASE + 0x50290, 0x32400077); | ||
1016 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xa40009b); | ||
1017 | MDP_OUTP(MDP_BASE + 0x50294, 0x32000073); | ||
1018 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xb00009d); | ||
1019 | MDP_OUTP(MDP_BASE + 0x50298, 0x31c0006f); | ||
1020 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xbc000a0); | ||
1021 | MDP_OUTP(MDP_BASE + 0x5029c, 0x3140006b); | ||
1022 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xc8000a2); | ||
1023 | MDP_OUTP(MDP_BASE + 0x502a0, 0x31000067); | ||
1024 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xd8000a5); | ||
1025 | MDP_OUTP(MDP_BASE + 0x502a4, 0x30800062); | ||
1026 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xe4000a8); | ||
1027 | MDP_OUTP(MDP_BASE + 0x502a8, 0x2fc0005f); | ||
1028 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xec000aa); | ||
1029 | MDP_OUTP(MDP_BASE + 0x502ac, 0x2fc0005b); | ||
1030 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf8000ad); | ||
1031 | MDP_OUTP(MDP_BASE + 0x502b0, 0x2f400057); | ||
1032 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x108000b0); | ||
1033 | MDP_OUTP(MDP_BASE + 0x502b4, 0x2e400054); | ||
1034 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x114000b2); | ||
1035 | MDP_OUTP(MDP_BASE + 0x502b8, 0x2e000050); | ||
1036 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x124000b4); | ||
1037 | MDP_OUTP(MDP_BASE + 0x502bc, 0x2d80004c); | ||
1038 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x130000b6); | ||
1039 | MDP_OUTP(MDP_BASE + 0x502c0, 0x2d000049); | ||
1040 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x140000b8); | ||
1041 | MDP_OUTP(MDP_BASE + 0x502c4, 0x2c800045); | ||
1042 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x150000b9); | ||
1043 | MDP_OUTP(MDP_BASE + 0x502c8, 0x2c000042); | ||
1044 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x15c000bd); | ||
1045 | MDP_OUTP(MDP_BASE + 0x502cc, 0x2b40003e); | ||
1046 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x16c000bf); | ||
1047 | MDP_OUTP(MDP_BASE + 0x502d0, 0x2a80003b); | ||
1048 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x17c000bf); | ||
1049 | MDP_OUTP(MDP_BASE + 0x502d4, 0x2a000039); | ||
1050 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x188000c2); | ||
1051 | MDP_OUTP(MDP_BASE + 0x502d8, 0x29400036); | ||
1052 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x19c000c4); | ||
1053 | MDP_OUTP(MDP_BASE + 0x502dc, 0x28800032); | ||
1054 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ac000c5); | ||
1055 | MDP_OUTP(MDP_BASE + 0x502e0, 0x2800002f); | ||
1056 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1bc000c7); | ||
1057 | MDP_OUTP(MDP_BASE + 0x502e4, 0x2740002c); | ||
1058 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc000c8); | ||
1059 | MDP_OUTP(MDP_BASE + 0x502e8, 0x26c00029); | ||
1060 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc000c9); | ||
1061 | MDP_OUTP(MDP_BASE + 0x502ec, 0x26000027); | ||
1062 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec000cc); | ||
1063 | MDP_OUTP(MDP_BASE + 0x502f0, 0x25000024); | ||
1064 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x200000cc); | ||
1065 | MDP_OUTP(MDP_BASE + 0x502f4, 0x24800021); | ||
1066 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x210000cd); | ||
1067 | MDP_OUTP(MDP_BASE + 0x502f8, 0x23800020); | ||
1068 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x220000ce); | ||
1069 | MDP_OUTP(MDP_BASE + 0x502fc, 0x2300001d); | ||
1070 | } | ||
1071 | |||
1072 | static void mdp_load_bc_downscale_table_y_point4TOpoint6(void) | ||
1073 | { | ||
1074 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x740008c); | ||
1075 | MDP_OUTP(MDP_BASE + 0x50300, 0x33800088); | ||
1076 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x800008e); | ||
1077 | MDP_OUTP(MDP_BASE + 0x50304, 0x33400084); | ||
1078 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x8400092); | ||
1079 | MDP_OUTP(MDP_BASE + 0x50308, 0x33000080); | ||
1080 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x9000094); | ||
1081 | MDP_OUTP(MDP_BASE + 0x5030c, 0x3300007b); | ||
1082 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x9c00098); | ||
1083 | MDP_OUTP(MDP_BASE + 0x50310, 0x32400077); | ||
1084 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xa40009b); | ||
1085 | MDP_OUTP(MDP_BASE + 0x50314, 0x32000073); | ||
1086 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xb00009d); | ||
1087 | MDP_OUTP(MDP_BASE + 0x50318, 0x31c0006f); | ||
1088 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xbc000a0); | ||
1089 | MDP_OUTP(MDP_BASE + 0x5031c, 0x3140006b); | ||
1090 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xc8000a2); | ||
1091 | MDP_OUTP(MDP_BASE + 0x50320, 0x31000067); | ||
1092 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xd8000a5); | ||
1093 | MDP_OUTP(MDP_BASE + 0x50324, 0x30800062); | ||
1094 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xe4000a8); | ||
1095 | MDP_OUTP(MDP_BASE + 0x50328, 0x2fc0005f); | ||
1096 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xec000aa); | ||
1097 | MDP_OUTP(MDP_BASE + 0x5032c, 0x2fc0005b); | ||
1098 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf8000ad); | ||
1099 | MDP_OUTP(MDP_BASE + 0x50330, 0x2f400057); | ||
1100 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x108000b0); | ||
1101 | MDP_OUTP(MDP_BASE + 0x50334, 0x2e400054); | ||
1102 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x114000b2); | ||
1103 | MDP_OUTP(MDP_BASE + 0x50338, 0x2e000050); | ||
1104 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x124000b4); | ||
1105 | MDP_OUTP(MDP_BASE + 0x5033c, 0x2d80004c); | ||
1106 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x130000b6); | ||
1107 | MDP_OUTP(MDP_BASE + 0x50340, 0x2d000049); | ||
1108 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x140000b8); | ||
1109 | MDP_OUTP(MDP_BASE + 0x50344, 0x2c800045); | ||
1110 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x150000b9); | ||
1111 | MDP_OUTP(MDP_BASE + 0x50348, 0x2c000042); | ||
1112 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x15c000bd); | ||
1113 | MDP_OUTP(MDP_BASE + 0x5034c, 0x2b40003e); | ||
1114 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x16c000bf); | ||
1115 | MDP_OUTP(MDP_BASE + 0x50350, 0x2a80003b); | ||
1116 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x17c000bf); | ||
1117 | MDP_OUTP(MDP_BASE + 0x50354, 0x2a000039); | ||
1118 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x188000c2); | ||
1119 | MDP_OUTP(MDP_BASE + 0x50358, 0x29400036); | ||
1120 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x19c000c4); | ||
1121 | MDP_OUTP(MDP_BASE + 0x5035c, 0x28800032); | ||
1122 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ac000c5); | ||
1123 | MDP_OUTP(MDP_BASE + 0x50360, 0x2800002f); | ||
1124 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1bc000c7); | ||
1125 | MDP_OUTP(MDP_BASE + 0x50364, 0x2740002c); | ||
1126 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1cc000c8); | ||
1127 | MDP_OUTP(MDP_BASE + 0x50368, 0x26c00029); | ||
1128 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1dc000c9); | ||
1129 | MDP_OUTP(MDP_BASE + 0x5036c, 0x26000027); | ||
1130 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1ec000cc); | ||
1131 | MDP_OUTP(MDP_BASE + 0x50370, 0x25000024); | ||
1132 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x200000cc); | ||
1133 | MDP_OUTP(MDP_BASE + 0x50374, 0x24800021); | ||
1134 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x210000cd); | ||
1135 | MDP_OUTP(MDP_BASE + 0x50378, 0x23800020); | ||
1136 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x220000ce); | ||
1137 | MDP_OUTP(MDP_BASE + 0x5037c, 0x2300001d); | ||
1138 | } | ||
1139 | |||
1140 | static void mdp_load_bc_downscale_table_x_point6TOpoint8(void) | ||
1141 | { | ||
1142 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000070); | ||
1143 | MDP_OUTP(MDP_BASE + 0x50280, 0x4bc00068); | ||
1144 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000078); | ||
1145 | MDP_OUTP(MDP_BASE + 0x50284, 0x4bc00060); | ||
1146 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000080); | ||
1147 | MDP_OUTP(MDP_BASE + 0x50288, 0x4b800059); | ||
1148 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000089); | ||
1149 | MDP_OUTP(MDP_BASE + 0x5028c, 0x4b000052); | ||
1150 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe400091); | ||
1151 | MDP_OUTP(MDP_BASE + 0x50290, 0x4a80004b); | ||
1152 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe40009a); | ||
1153 | MDP_OUTP(MDP_BASE + 0x50294, 0x4a000044); | ||
1154 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe8000a3); | ||
1155 | MDP_OUTP(MDP_BASE + 0x50298, 0x4940003d); | ||
1156 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfec000ac); | ||
1157 | MDP_OUTP(MDP_BASE + 0x5029c, 0x48400037); | ||
1158 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xff0000b4); | ||
1159 | MDP_OUTP(MDP_BASE + 0x502a0, 0x47800031); | ||
1160 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xff8000bd); | ||
1161 | MDP_OUTP(MDP_BASE + 0x502a4, 0x4640002b); | ||
1162 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xc5); | ||
1163 | MDP_OUTP(MDP_BASE + 0x502a8, 0x45000026); | ||
1164 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x8000ce); | ||
1165 | MDP_OUTP(MDP_BASE + 0x502ac, 0x43800021); | ||
1166 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x10000d6); | ||
1167 | MDP_OUTP(MDP_BASE + 0x502b0, 0x4240001c); | ||
1168 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x18000df); | ||
1169 | MDP_OUTP(MDP_BASE + 0x502b4, 0x40800018); | ||
1170 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x24000e6); | ||
1171 | MDP_OUTP(MDP_BASE + 0x502b8, 0x3f000014); | ||
1172 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x30000ee); | ||
1173 | MDP_OUTP(MDP_BASE + 0x502bc, 0x3d400010); | ||
1174 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x40000f5); | ||
1175 | MDP_OUTP(MDP_BASE + 0x502c0, 0x3b80000c); | ||
1176 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x50000fc); | ||
1177 | MDP_OUTP(MDP_BASE + 0x502c4, 0x39800009); | ||
1178 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x6000102); | ||
1179 | MDP_OUTP(MDP_BASE + 0x502c8, 0x37c00006); | ||
1180 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x7000109); | ||
1181 | MDP_OUTP(MDP_BASE + 0x502cc, 0x35800004); | ||
1182 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x840010e); | ||
1183 | MDP_OUTP(MDP_BASE + 0x502d0, 0x33800002); | ||
1184 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x9800114); | ||
1185 | MDP_OUTP(MDP_BASE + 0x502d4, 0x31400000); | ||
1186 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xac00119); | ||
1187 | MDP_OUTP(MDP_BASE + 0x502d8, 0x2f4003fe); | ||
1188 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xc40011e); | ||
1189 | MDP_OUTP(MDP_BASE + 0x502dc, 0x2d0003fc); | ||
1190 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xdc00121); | ||
1191 | MDP_OUTP(MDP_BASE + 0x502e0, 0x2b0003fb); | ||
1192 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf400125); | ||
1193 | MDP_OUTP(MDP_BASE + 0x502e4, 0x28c003fa); | ||
1194 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x11000128); | ||
1195 | MDP_OUTP(MDP_BASE + 0x502e8, 0x268003f9); | ||
1196 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x12c0012a); | ||
1197 | MDP_OUTP(MDP_BASE + 0x502ec, 0x244003f9); | ||
1198 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1480012c); | ||
1199 | MDP_OUTP(MDP_BASE + 0x502f0, 0x224003f8); | ||
1200 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1640012e); | ||
1201 | MDP_OUTP(MDP_BASE + 0x502f4, 0x200003f8); | ||
1202 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1800012f); | ||
1203 | MDP_OUTP(MDP_BASE + 0x502f8, 0x1e0003f8); | ||
1204 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1a00012f); | ||
1205 | MDP_OUTP(MDP_BASE + 0x502fc, 0x1c0003f8); | ||
1206 | } | ||
1207 | |||
1208 | static void mdp_load_bc_downscale_table_y_point6TOpoint8(void) | ||
1209 | { | ||
1210 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000070); | ||
1211 | MDP_OUTP(MDP_BASE + 0x50300, 0x4bc00068); | ||
1212 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000078); | ||
1213 | MDP_OUTP(MDP_BASE + 0x50304, 0x4bc00060); | ||
1214 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000080); | ||
1215 | MDP_OUTP(MDP_BASE + 0x50308, 0x4b800059); | ||
1216 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe000089); | ||
1217 | MDP_OUTP(MDP_BASE + 0x5030c, 0x4b000052); | ||
1218 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe400091); | ||
1219 | MDP_OUTP(MDP_BASE + 0x50310, 0x4a80004b); | ||
1220 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe40009a); | ||
1221 | MDP_OUTP(MDP_BASE + 0x50314, 0x4a000044); | ||
1222 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe8000a3); | ||
1223 | MDP_OUTP(MDP_BASE + 0x50318, 0x4940003d); | ||
1224 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfec000ac); | ||
1225 | MDP_OUTP(MDP_BASE + 0x5031c, 0x48400037); | ||
1226 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xff0000b4); | ||
1227 | MDP_OUTP(MDP_BASE + 0x50320, 0x47800031); | ||
1228 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xff8000bd); | ||
1229 | MDP_OUTP(MDP_BASE + 0x50324, 0x4640002b); | ||
1230 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xc5); | ||
1231 | MDP_OUTP(MDP_BASE + 0x50328, 0x45000026); | ||
1232 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x8000ce); | ||
1233 | MDP_OUTP(MDP_BASE + 0x5032c, 0x43800021); | ||
1234 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x10000d6); | ||
1235 | MDP_OUTP(MDP_BASE + 0x50330, 0x4240001c); | ||
1236 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x18000df); | ||
1237 | MDP_OUTP(MDP_BASE + 0x50334, 0x40800018); | ||
1238 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x24000e6); | ||
1239 | MDP_OUTP(MDP_BASE + 0x50338, 0x3f000014); | ||
1240 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x30000ee); | ||
1241 | MDP_OUTP(MDP_BASE + 0x5033c, 0x3d400010); | ||
1242 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x40000f5); | ||
1243 | MDP_OUTP(MDP_BASE + 0x50340, 0x3b80000c); | ||
1244 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x50000fc); | ||
1245 | MDP_OUTP(MDP_BASE + 0x50344, 0x39800009); | ||
1246 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x6000102); | ||
1247 | MDP_OUTP(MDP_BASE + 0x50348, 0x37c00006); | ||
1248 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x7000109); | ||
1249 | MDP_OUTP(MDP_BASE + 0x5034c, 0x35800004); | ||
1250 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x840010e); | ||
1251 | MDP_OUTP(MDP_BASE + 0x50350, 0x33800002); | ||
1252 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x9800114); | ||
1253 | MDP_OUTP(MDP_BASE + 0x50354, 0x31400000); | ||
1254 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xac00119); | ||
1255 | MDP_OUTP(MDP_BASE + 0x50358, 0x2f4003fe); | ||
1256 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xc40011e); | ||
1257 | MDP_OUTP(MDP_BASE + 0x5035c, 0x2d0003fc); | ||
1258 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xdc00121); | ||
1259 | MDP_OUTP(MDP_BASE + 0x50360, 0x2b0003fb); | ||
1260 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf400125); | ||
1261 | MDP_OUTP(MDP_BASE + 0x50364, 0x28c003fa); | ||
1262 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x11000128); | ||
1263 | MDP_OUTP(MDP_BASE + 0x50368, 0x268003f9); | ||
1264 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x12c0012a); | ||
1265 | MDP_OUTP(MDP_BASE + 0x5036c, 0x244003f9); | ||
1266 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1480012c); | ||
1267 | MDP_OUTP(MDP_BASE + 0x50370, 0x224003f8); | ||
1268 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1640012e); | ||
1269 | MDP_OUTP(MDP_BASE + 0x50374, 0x200003f8); | ||
1270 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1800012f); | ||
1271 | MDP_OUTP(MDP_BASE + 0x50378, 0x1e0003f8); | ||
1272 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x1a00012f); | ||
1273 | MDP_OUTP(MDP_BASE + 0x5037c, 0x1c0003f8); | ||
1274 | } | ||
1275 | |||
1276 | static void mdp_load_bc_downscale_table_x_point8TO1(void) | ||
1277 | { | ||
1278 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
1279 | MDP_OUTP(MDP_BASE + 0x50280, 0x7fc00000); | ||
1280 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xff80000d); | ||
1281 | MDP_OUTP(MDP_BASE + 0x50284, 0x7ec003f9); | ||
1282 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfec0001c); | ||
1283 | MDP_OUTP(MDP_BASE + 0x50288, 0x7d4003f3); | ||
1284 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe40002b); | ||
1285 | MDP_OUTP(MDP_BASE + 0x5028c, 0x7b8003ed); | ||
1286 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfd80003c); | ||
1287 | MDP_OUTP(MDP_BASE + 0x50290, 0x794003e8); | ||
1288 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc0004d); | ||
1289 | MDP_OUTP(MDP_BASE + 0x50294, 0x76c003e4); | ||
1290 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfc40005f); | ||
1291 | MDP_OUTP(MDP_BASE + 0x50298, 0x73c003e0); | ||
1292 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb800071); | ||
1293 | MDP_OUTP(MDP_BASE + 0x5029c, 0x708003de); | ||
1294 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfac00085); | ||
1295 | MDP_OUTP(MDP_BASE + 0x502a0, 0x6d0003db); | ||
1296 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa000098); | ||
1297 | MDP_OUTP(MDP_BASE + 0x502a4, 0x698003d9); | ||
1298 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf98000ac); | ||
1299 | MDP_OUTP(MDP_BASE + 0x502a8, 0x654003d8); | ||
1300 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf8c000c1); | ||
1301 | MDP_OUTP(MDP_BASE + 0x502ac, 0x610003d7); | ||
1302 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf84000d5); | ||
1303 | MDP_OUTP(MDP_BASE + 0x502b0, 0x5c8003d7); | ||
1304 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf7c000e9); | ||
1305 | MDP_OUTP(MDP_BASE + 0x502b4, 0x580003d7); | ||
1306 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf74000fd); | ||
1307 | MDP_OUTP(MDP_BASE + 0x502b8, 0x534003d8); | ||
1308 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c00112); | ||
1309 | MDP_OUTP(MDP_BASE + 0x502bc, 0x4e8003d8); | ||
1310 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6800126); | ||
1311 | MDP_OUTP(MDP_BASE + 0x502c0, 0x494003da); | ||
1312 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600013a); | ||
1313 | MDP_OUTP(MDP_BASE + 0x502c4, 0x448003db); | ||
1314 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600014d); | ||
1315 | MDP_OUTP(MDP_BASE + 0x502c8, 0x3f4003dd); | ||
1316 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00160); | ||
1317 | MDP_OUTP(MDP_BASE + 0x502cc, 0x3a4003df); | ||
1318 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00172); | ||
1319 | MDP_OUTP(MDP_BASE + 0x502d0, 0x354003e1); | ||
1320 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00184); | ||
1321 | MDP_OUTP(MDP_BASE + 0x502d4, 0x304003e3); | ||
1322 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6000195); | ||
1323 | MDP_OUTP(MDP_BASE + 0x502d8, 0x2b0003e6); | ||
1324 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf64001a6); | ||
1325 | MDP_OUTP(MDP_BASE + 0x502dc, 0x260003e8); | ||
1326 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c001b4); | ||
1327 | MDP_OUTP(MDP_BASE + 0x502e0, 0x214003eb); | ||
1328 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf78001c2); | ||
1329 | MDP_OUTP(MDP_BASE + 0x502e4, 0x1c4003ee); | ||
1330 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf80001cf); | ||
1331 | MDP_OUTP(MDP_BASE + 0x502e8, 0x17c003f1); | ||
1332 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf90001db); | ||
1333 | MDP_OUTP(MDP_BASE + 0x502ec, 0x134003f3); | ||
1334 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa0001e5); | ||
1335 | MDP_OUTP(MDP_BASE + 0x502f0, 0xf0003f6); | ||
1336 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb4001ee); | ||
1337 | MDP_OUTP(MDP_BASE + 0x502f4, 0xac003f9); | ||
1338 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc001f5); | ||
1339 | MDP_OUTP(MDP_BASE + 0x502f8, 0x70003fb); | ||
1340 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe4001fb); | ||
1341 | MDP_OUTP(MDP_BASE + 0x502fc, 0x34003fe); | ||
1342 | } | ||
1343 | |||
1344 | static void mdp_load_bc_downscale_table_y_point8TO1(void) | ||
1345 | { | ||
1346 | MDP_OUTP(MDP_BASE + 0x5fffc, 0x0); | ||
1347 | MDP_OUTP(MDP_BASE + 0x50300, 0x7fc00000); | ||
1348 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xff80000d); | ||
1349 | MDP_OUTP(MDP_BASE + 0x50304, 0x7ec003f9); | ||
1350 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfec0001c); | ||
1351 | MDP_OUTP(MDP_BASE + 0x50308, 0x7d4003f3); | ||
1352 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe40002b); | ||
1353 | MDP_OUTP(MDP_BASE + 0x5030c, 0x7b8003ed); | ||
1354 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfd80003c); | ||
1355 | MDP_OUTP(MDP_BASE + 0x50310, 0x794003e8); | ||
1356 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc0004d); | ||
1357 | MDP_OUTP(MDP_BASE + 0x50314, 0x76c003e4); | ||
1358 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfc40005f); | ||
1359 | MDP_OUTP(MDP_BASE + 0x50318, 0x73c003e0); | ||
1360 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb800071); | ||
1361 | MDP_OUTP(MDP_BASE + 0x5031c, 0x708003de); | ||
1362 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfac00085); | ||
1363 | MDP_OUTP(MDP_BASE + 0x50320, 0x6d0003db); | ||
1364 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa000098); | ||
1365 | MDP_OUTP(MDP_BASE + 0x50324, 0x698003d9); | ||
1366 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf98000ac); | ||
1367 | MDP_OUTP(MDP_BASE + 0x50328, 0x654003d8); | ||
1368 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf8c000c1); | ||
1369 | MDP_OUTP(MDP_BASE + 0x5032c, 0x610003d7); | ||
1370 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf84000d5); | ||
1371 | MDP_OUTP(MDP_BASE + 0x50330, 0x5c8003d7); | ||
1372 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf7c000e9); | ||
1373 | MDP_OUTP(MDP_BASE + 0x50334, 0x580003d7); | ||
1374 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf74000fd); | ||
1375 | MDP_OUTP(MDP_BASE + 0x50338, 0x534003d8); | ||
1376 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c00112); | ||
1377 | MDP_OUTP(MDP_BASE + 0x5033c, 0x4e8003d8); | ||
1378 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6800126); | ||
1379 | MDP_OUTP(MDP_BASE + 0x50340, 0x494003da); | ||
1380 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600013a); | ||
1381 | MDP_OUTP(MDP_BASE + 0x50344, 0x448003db); | ||
1382 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf600014d); | ||
1383 | MDP_OUTP(MDP_BASE + 0x50348, 0x3f4003dd); | ||
1384 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00160); | ||
1385 | MDP_OUTP(MDP_BASE + 0x5034c, 0x3a4003df); | ||
1386 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00172); | ||
1387 | MDP_OUTP(MDP_BASE + 0x50350, 0x354003e1); | ||
1388 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf5c00184); | ||
1389 | MDP_OUTP(MDP_BASE + 0x50354, 0x304003e3); | ||
1390 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6000195); | ||
1391 | MDP_OUTP(MDP_BASE + 0x50358, 0x2b0003e6); | ||
1392 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf64001a6); | ||
1393 | MDP_OUTP(MDP_BASE + 0x5035c, 0x260003e8); | ||
1394 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf6c001b4); | ||
1395 | MDP_OUTP(MDP_BASE + 0x50360, 0x214003eb); | ||
1396 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf78001c2); | ||
1397 | MDP_OUTP(MDP_BASE + 0x50364, 0x1c4003ee); | ||
1398 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf80001cf); | ||
1399 | MDP_OUTP(MDP_BASE + 0x50368, 0x17c003f1); | ||
1400 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xf90001db); | ||
1401 | MDP_OUTP(MDP_BASE + 0x5036c, 0x134003f3); | ||
1402 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfa0001e5); | ||
1403 | MDP_OUTP(MDP_BASE + 0x50370, 0xf0003f6); | ||
1404 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfb4001ee); | ||
1405 | MDP_OUTP(MDP_BASE + 0x50374, 0xac003f9); | ||
1406 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfcc001f5); | ||
1407 | MDP_OUTP(MDP_BASE + 0x50378, 0x70003fb); | ||
1408 | MDP_OUTP(MDP_BASE + 0x5fffc, 0xfe4001fb); | ||
1409 | MDP_OUTP(MDP_BASE + 0x5037c, 0x34003fe); | ||
1410 | } | ||
1411 | |||
1412 | static int mdp_get_edge_cond(MDPIBUF *iBuf, uint32 *dup, uint32 *dup2) | ||
1413 | { | ||
1414 | uint32 reg; | ||
1415 | uint32 dst_roi_width; /* Dimensions of DST ROI. */ | ||
1416 | uint32 dst_roi_height; /* Used to calculate scaling ratios. */ | ||
1417 | |||
1418 | /* | ||
1419 | * positions of the luma pixel(relative to the image ) required for | ||
1420 | * scaling the ROI | ||
1421 | */ | ||
1422 | int32 luma_interp_point_left = 0; /* left-most luma pixel needed */ | ||
1423 | int32 luma_interp_point_right = 0; /* right-most luma pixel needed */ | ||
1424 | int32 luma_interp_point_top = 0; /* top-most luma pixel needed */ | ||
1425 | int32 luma_interp_point_bottom = 0; /* bottom-most luma pixel needed */ | ||
1426 | |||
1427 | /* | ||
1428 | * positions of the chroma pixel(relative to the image ) required for | ||
1429 | * interpolating a chroma value at all required luma positions | ||
1430 | */ | ||
1431 | /* left-most chroma pixel needed */ | ||
1432 | int32 chroma_interp_point_left = 0; | ||
1433 | /* right-most chroma pixel needed */ | ||
1434 | int32 chroma_interp_point_right = 0; | ||
1435 | /* top-most chroma pixel needed */ | ||
1436 | int32 chroma_interp_point_top = 0; | ||
1437 | /* bottom-most chroma pixel needed */ | ||
1438 | int32 chroma_interp_point_bottom = 0; | ||
1439 | |||
1440 | /* | ||
1441 | * a rectangular region within the chroma plane of the "image". | ||
1442 | * Chroma pixels falling inside of this rectangle belongs to the ROI | ||
1443 | */ | ||
1444 | int32 chroma_bound_left = 0; | ||
1445 | int32 chroma_bound_right = 0; | ||
1446 | int32 chroma_bound_top = 0; | ||
1447 | int32 chroma_bound_bottom = 0; | ||
1448 | |||
1449 | /* | ||
1450 | * number of chroma pixels to replicate on the left, right, | ||
1451 | * top and bottom edge of the ROI. | ||
1452 | */ | ||
1453 | int32 chroma_repeat_left = 0; | ||
1454 | int32 chroma_repeat_right = 0; | ||
1455 | int32 chroma_repeat_top = 0; | ||
1456 | int32 chroma_repeat_bottom = 0; | ||
1457 | |||
1458 | /* | ||
1459 | * number of luma pixels to replicate on the left, right, | ||
1460 | * top and bottom edge of the ROI. | ||
1461 | */ | ||
1462 | int32 luma_repeat_left = 0; | ||
1463 | int32 luma_repeat_right = 0; | ||
1464 | int32 luma_repeat_top = 0; | ||
1465 | int32 luma_repeat_bottom = 0; | ||
1466 | |||
1467 | boolean chroma_edge_enable; | ||
1468 | |||
1469 | uint32 _is_scale_enabled = 0; | ||
1470 | uint32 _is_yuv_offsite_vertical = 0; | ||
1471 | |||
1472 | /* fg edge duplicate */ | ||
1473 | reg = 0x0; | ||
1474 | |||
1475 | if (iBuf->mdpImg.mdpOp & MDPOP_ASCALE) { /* if scaling enabled */ | ||
1476 | |||
1477 | _is_scale_enabled = 1; | ||
1478 | |||
1479 | /* | ||
1480 | * if rotation mode involves a 90 deg rotation, flip | ||
1481 | * dst_roi_width with dst_roi_height. | ||
1482 | * Scaling ratios is based on source ROI dimensions, and | ||
1483 | * dst ROI dimensions before rotation. | ||
1484 | */ | ||
1485 | if (iBuf->mdpImg.mdpOp & MDPOP_ROT90) { | ||
1486 | dst_roi_width = iBuf->roi.dst_height; | ||
1487 | dst_roi_height = iBuf->roi.dst_width; | ||
1488 | } else { | ||
1489 | dst_roi_width = iBuf->roi.dst_width; | ||
1490 | dst_roi_height = iBuf->roi.dst_height; | ||
1491 | } | ||
1492 | |||
1493 | /* | ||
1494 | * Find out the luma pixels needed for scaling in the | ||
1495 | * x direction (LEFT and RIGHT). Locations of pixels are | ||
1496 | * relative to the ROI. Upper-left corner of ROI corresponds | ||
1497 | * to coordinates (0,0). Also set the number of luma pixel | ||
1498 | * to repeat. | ||
1499 | */ | ||
1500 | if (iBuf->roi.width > 3 * dst_roi_width) { | ||
1501 | /* scale factor < 1/3 */ | ||
1502 | luma_interp_point_left = 0; | ||
1503 | luma_interp_point_right = (iBuf->roi.width - 1); | ||
1504 | luma_repeat_left = 0; | ||
1505 | luma_repeat_right = 0; | ||
1506 | } else if (iBuf->roi.width == 3 * dst_roi_width) { | ||
1507 | /* scale factor == 1/3 */ | ||
1508 | luma_interp_point_left = 0; | ||
1509 | luma_interp_point_right = (iBuf->roi.width - 1) + 1; | ||
1510 | luma_repeat_left = 0; | ||
1511 | luma_repeat_right = 1; | ||
1512 | } else if ((iBuf->roi.width > dst_roi_width) && | ||
1513 | (iBuf->roi.width < 3 * dst_roi_width)) { | ||
1514 | /* 1/3 < scale factor < 1 */ | ||
1515 | luma_interp_point_left = -1; | ||
1516 | luma_interp_point_right = (iBuf->roi.width - 1) + 1; | ||
1517 | luma_repeat_left = 1; | ||
1518 | luma_repeat_right = 1; | ||
1519 | } | ||
1520 | |||
1521 | else if (iBuf->roi.width == dst_roi_width) { | ||
1522 | /* scale factor == 1 */ | ||
1523 | luma_interp_point_left = -1; | ||
1524 | luma_interp_point_right = (iBuf->roi.width - 1) + 2; | ||
1525 | luma_repeat_left = 1; | ||
1526 | luma_repeat_right = 2; | ||
1527 | } else { /* (iBuf->roi.width < dst_roi_width) */ | ||
1528 | /* scale factor > 1 */ | ||
1529 | luma_interp_point_left = -2; | ||
1530 | luma_interp_point_right = (iBuf->roi.width - 1) + 2; | ||
1531 | luma_repeat_left = 2; | ||
1532 | luma_repeat_right = 2; | ||
1533 | } | ||
1534 | |||
1535 | /* | ||
1536 | * Find out the number of pixels needed for scaling in the | ||
1537 | * y direction (TOP and BOTTOM). Locations of pixels are | ||
1538 | * relative to the ROI. Upper-left corner of ROI corresponds | ||
1539 | * to coordinates (0,0). Also set the number of luma pixel | ||
1540 | * to repeat. | ||
1541 | */ | ||
1542 | if (iBuf->roi.height > 3 * dst_roi_height) { | ||
1543 | /* scale factor < 1/3 */ | ||
1544 | luma_interp_point_top = 0; | ||
1545 | luma_interp_point_bottom = (iBuf->roi.height - 1); | ||
1546 | luma_repeat_top = 0; | ||
1547 | luma_repeat_bottom = 0; | ||
1548 | } else if (iBuf->roi.height == 3 * dst_roi_height) { | ||
1549 | /* scale factor == 1/3 */ | ||
1550 | luma_interp_point_top = 0; | ||
1551 | luma_interp_point_bottom = (iBuf->roi.height - 1) + 1; | ||
1552 | luma_repeat_top = 0; | ||
1553 | luma_repeat_bottom = 1; | ||
1554 | } else if ((iBuf->roi.height > dst_roi_height) && | ||
1555 | (iBuf->roi.height < 3 * dst_roi_height)) { | ||
1556 | /* 1/3 < scale factor < 1 */ | ||
1557 | luma_interp_point_top = -1; | ||
1558 | luma_interp_point_bottom = (iBuf->roi.height - 1) + 1; | ||
1559 | luma_repeat_top = 1; | ||
1560 | luma_repeat_bottom = 1; | ||
1561 | } else if (iBuf->roi.height == dst_roi_height) { | ||
1562 | /* scale factor == 1 */ | ||
1563 | luma_interp_point_top = -1; | ||
1564 | luma_interp_point_bottom = (iBuf->roi.height - 1) + 2; | ||
1565 | luma_repeat_top = 1; | ||
1566 | luma_repeat_bottom = 2; | ||
1567 | } else { /* (iBuf->roi.height < dst_roi_height) */ | ||
1568 | /* scale factor > 1 */ | ||
1569 | luma_interp_point_top = -2; | ||
1570 | luma_interp_point_bottom = (iBuf->roi.height - 1) + 2; | ||
1571 | luma_repeat_top = 2; | ||
1572 | luma_repeat_bottom = 2; | ||
1573 | } | ||
1574 | } /* if (iBuf->scale.scale_flag) */ | ||
1575 | else { /* scaling disabled */ | ||
1576 | /* | ||
1577 | * Since no scaling needed, Tile Fetch does not require any | ||
1578 | * more luma pixel than what the ROI contains. | ||
1579 | */ | ||
1580 | luma_interp_point_left = (int32) 0; | ||
1581 | luma_interp_point_right = (int32) (iBuf->roi.width - 1); | ||
1582 | luma_interp_point_top = (int32) 0; | ||
1583 | luma_interp_point_bottom = (int32) (iBuf->roi.height - 1); | ||
1584 | |||
1585 | luma_repeat_left = 0; | ||
1586 | luma_repeat_right = 0; | ||
1587 | luma_repeat_top = 0; | ||
1588 | luma_repeat_bottom = 0; | ||
1589 | } | ||
1590 | |||
1591 | /* After adding the ROI offsets, we have locations of | ||
1592 | * luma_interp_points relative to the image. | ||
1593 | */ | ||
1594 | luma_interp_point_left += (int32) (iBuf->roi.x); | ||
1595 | luma_interp_point_right += (int32) (iBuf->roi.x); | ||
1596 | luma_interp_point_top += (int32) (iBuf->roi.y); | ||
1597 | luma_interp_point_bottom += (int32) (iBuf->roi.y); | ||
1598 | |||
1599 | /* | ||
1600 | * After adding the ROI offsets, we have locations of | ||
1601 | * chroma_interp_points relative to the image. | ||
1602 | */ | ||
1603 | chroma_interp_point_left = luma_interp_point_left; | ||
1604 | chroma_interp_point_right = luma_interp_point_right; | ||
1605 | chroma_interp_point_top = luma_interp_point_top; | ||
1606 | chroma_interp_point_bottom = luma_interp_point_bottom; | ||
1607 | |||
1608 | chroma_edge_enable = TRUE; | ||
1609 | /* find out which chroma pixels are needed for chroma upsampling. */ | ||
1610 | switch (iBuf->mdpImg.imgType) { | ||
1611 | /* | ||
1612 | * cosite in horizontal axis | ||
1613 | * fully sampled in vertical axis | ||
1614 | */ | ||
1615 | case MDP_Y_CBCR_H2V1: | ||
1616 | case MDP_Y_CRCB_H2V1: | ||
1617 | case MDP_YCRYCB_H2V1: | ||
1618 | /* floor( luma_interp_point_left / 2 ); */ | ||
1619 | chroma_interp_point_left = luma_interp_point_left >> 1; | ||
1620 | /* floor( ( luma_interp_point_right + 1 ) / 2 ); */ | ||
1621 | chroma_interp_point_right = (luma_interp_point_right + 1) >> 1; | ||
1622 | |||
1623 | chroma_interp_point_top = luma_interp_point_top; | ||
1624 | chroma_interp_point_bottom = luma_interp_point_bottom; | ||
1625 | break; | ||
1626 | |||
1627 | /* | ||
1628 | * cosite in horizontal axis | ||
1629 | * offsite in vertical axis | ||
1630 | */ | ||
1631 | case MDP_Y_CBCR_H2V2: | ||
1632 | case MDP_Y_CRCB_H2V2: | ||
1633 | /* floor( luma_interp_point_left / 2) */ | ||
1634 | chroma_interp_point_left = luma_interp_point_left >> 1; | ||
1635 | |||
1636 | /* floor( ( luma_interp_point_right + 1 )/ 2 ) */ | ||
1637 | chroma_interp_point_right = (luma_interp_point_right + 1) >> 1; | ||
1638 | |||
1639 | /* floor( (luma_interp_point_top - 1 ) / 2 ) */ | ||
1640 | chroma_interp_point_top = (luma_interp_point_top - 1) >> 1; | ||
1641 | |||
1642 | /* floor( ( luma_interp_point_bottom + 1 ) / 2 ) */ | ||
1643 | chroma_interp_point_bottom = | ||
1644 | (luma_interp_point_bottom + 1) >> 1; | ||
1645 | |||
1646 | _is_yuv_offsite_vertical = 1; | ||
1647 | break; | ||
1648 | |||
1649 | default: | ||
1650 | chroma_edge_enable = FALSE; | ||
1651 | chroma_interp_point_left = luma_interp_point_left; | ||
1652 | chroma_interp_point_right = luma_interp_point_right; | ||
1653 | chroma_interp_point_top = luma_interp_point_top; | ||
1654 | chroma_interp_point_bottom = luma_interp_point_bottom; | ||
1655 | |||
1656 | break; | ||
1657 | } | ||
1658 | |||
1659 | /* only if the image type is in YUV domain, we calculate chroma edge */ | ||
1660 | if (chroma_edge_enable) { | ||
1661 | /* Defines which chroma pixels belongs to the roi */ | ||
1662 | switch (iBuf->mdpImg.imgType) { | ||
1663 | /* | ||
1664 | * Cosite in horizontal direction, and fully sampled | ||
1665 | * in vertical direction. | ||
1666 | */ | ||
1667 | case MDP_Y_CBCR_H2V1: | ||
1668 | case MDP_Y_CRCB_H2V1: | ||
1669 | case MDP_YCRYCB_H2V1: | ||
1670 | /* | ||
1671 | * width of chroma ROI is 1/2 of size of luma ROI | ||
1672 | * height of chroma ROI same as size of luma ROI | ||
1673 | */ | ||
1674 | chroma_bound_left = iBuf->roi.x / 2; | ||
1675 | |||
1676 | /* there are half as many chroma pixel as luma pixels */ | ||
1677 | chroma_bound_right = | ||
1678 | (iBuf->roi.width + iBuf->roi.x - 1) / 2; | ||
1679 | chroma_bound_top = iBuf->roi.y; | ||
1680 | chroma_bound_bottom = | ||
1681 | (iBuf->roi.height + iBuf->roi.y - 1); | ||
1682 | break; | ||
1683 | |||
1684 | case MDP_Y_CBCR_H2V2: | ||
1685 | case MDP_Y_CRCB_H2V2: | ||
1686 | /* | ||
1687 | * cosite in horizontal dir, and offsite in vertical dir | ||
1688 | * width of chroma ROI is 1/2 of size of luma ROI | ||
1689 | * height of chroma ROI is 1/2 of size of luma ROI | ||
1690 | */ | ||
1691 | |||
1692 | chroma_bound_left = iBuf->roi.x / 2; | ||
1693 | chroma_bound_right = | ||
1694 | (iBuf->roi.width + iBuf->roi.x - 1) / 2; | ||
1695 | chroma_bound_top = iBuf->roi.y / 2; | ||
1696 | chroma_bound_bottom = | ||
1697 | (iBuf->roi.height + iBuf->roi.y - 1) / 2; | ||
1698 | break; | ||
1699 | |||
1700 | default: | ||
1701 | /* | ||
1702 | * If no valid chroma sub-sampling format specified, | ||
1703 | * assume 4:4:4 ( i.e. fully sampled). Set ROI | ||
1704 | * boundaries for chroma same as ROI boundaries for | ||
1705 | * luma. | ||
1706 | */ | ||
1707 | chroma_bound_left = iBuf->roi.x; | ||
1708 | chroma_bound_right = iBuf->roi.width + iBuf->roi.x - 1; | ||
1709 | chroma_bound_top = iBuf->roi.y; | ||
1710 | chroma_bound_bottom = | ||
1711 | (iBuf->roi.height + iBuf->roi.y - 1); | ||
1712 | break; | ||
1713 | } | ||
1714 | |||
1715 | /* | ||
1716 | * Knowing which chroma pixels are needed, and which chroma | ||
1717 | * pixels belong to the ROI (i.e. available for fetching ), | ||
1718 | * calculate how many chroma pixels Tile Fetch needs to | ||
1719 | * duplicate. If any required chroma pixels falls outside | ||
1720 | * of the ROI, Tile Fetch must obtain them by replicating | ||
1721 | * pixels. | ||
1722 | */ | ||
1723 | if (chroma_bound_left > chroma_interp_point_left) | ||
1724 | chroma_repeat_left = | ||
1725 | chroma_bound_left - chroma_interp_point_left; | ||
1726 | else | ||
1727 | chroma_repeat_left = 0; | ||
1728 | |||
1729 | if (chroma_interp_point_right > chroma_bound_right) | ||
1730 | chroma_repeat_right = | ||
1731 | chroma_interp_point_right - chroma_bound_right; | ||
1732 | else | ||
1733 | chroma_repeat_right = 0; | ||
1734 | |||
1735 | if (chroma_bound_top > chroma_interp_point_top) | ||
1736 | chroma_repeat_top = | ||
1737 | chroma_bound_top - chroma_interp_point_top; | ||
1738 | else | ||
1739 | chroma_repeat_top = 0; | ||
1740 | |||
1741 | if (chroma_interp_point_bottom > chroma_bound_bottom) | ||
1742 | chroma_repeat_bottom = | ||
1743 | chroma_interp_point_bottom - chroma_bound_bottom; | ||
1744 | else | ||
1745 | chroma_repeat_bottom = 0; | ||
1746 | |||
1747 | if (_is_scale_enabled && (iBuf->roi.height == 1) | ||
1748 | && _is_yuv_offsite_vertical) { | ||
1749 | chroma_repeat_bottom = 3; | ||
1750 | chroma_repeat_top = 0; | ||
1751 | } | ||
1752 | } | ||
1753 | /* make sure chroma repeats are non-negative */ | ||
1754 | if ((chroma_repeat_left < 0) || (chroma_repeat_right < 0) || | ||
1755 | (chroma_repeat_top < 0) || (chroma_repeat_bottom < 0)) | ||
1756 | return -1; | ||
1757 | |||
1758 | /* make sure chroma repeats are no larger than 3 pixels */ | ||
1759 | if ((chroma_repeat_left > 3) || (chroma_repeat_right > 3) || | ||
1760 | (chroma_repeat_top > 3) || (chroma_repeat_bottom > 3)) | ||
1761 | return -1; | ||
1762 | |||
1763 | /* make sure luma repeats are non-negative */ | ||
1764 | if ((luma_repeat_left < 0) || (luma_repeat_right < 0) || | ||
1765 | (luma_repeat_top < 0) || (luma_repeat_bottom < 0)) | ||
1766 | return -1; | ||
1767 | |||
1768 | /* make sure luma repeats are no larger than 3 pixels */ | ||
1769 | if ((luma_repeat_left > 3) || (luma_repeat_right > 3) || | ||
1770 | (luma_repeat_top > 3) || (luma_repeat_bottom > 3)) | ||
1771 | return -1; | ||
1772 | |||
1773 | /* write chroma_repeat_left to register */ | ||
1774 | reg |= (chroma_repeat_left & 3) << MDP_LEFT_CHROMA; | ||
1775 | |||
1776 | /* write chroma_repeat_right to register */ | ||
1777 | reg |= (chroma_repeat_right & 3) << MDP_RIGHT_CHROMA; | ||
1778 | |||
1779 | /* write chroma_repeat_top to register */ | ||
1780 | reg |= (chroma_repeat_top & 3) << MDP_TOP_CHROMA; | ||
1781 | |||
1782 | /* write chroma_repeat_bottom to register */ | ||
1783 | reg |= (chroma_repeat_bottom & 3) << MDP_BOTTOM_CHROMA; | ||
1784 | |||
1785 | /* write luma_repeat_left to register */ | ||
1786 | reg |= (luma_repeat_left & 3) << MDP_LEFT_LUMA; | ||
1787 | |||
1788 | /* write luma_repeat_right to register */ | ||
1789 | reg |= (luma_repeat_right & 3) << MDP_RIGHT_LUMA; | ||
1790 | |||
1791 | /* write luma_repeat_top to register */ | ||
1792 | reg |= (luma_repeat_top & 3) << MDP_TOP_LUMA; | ||
1793 | |||
1794 | /* write luma_repeat_bottom to register */ | ||
1795 | reg |= (luma_repeat_bottom & 3) << MDP_BOTTOM_LUMA; | ||
1796 | |||
1797 | /* done with reg */ | ||
1798 | *dup = reg; | ||
1799 | |||
1800 | /* bg edge duplicate */ | ||
1801 | reg = 0x0; | ||
1802 | |||
1803 | switch (iBuf->ibuf_type) { | ||
1804 | case MDP_Y_CBCR_H2V2: | ||
1805 | case MDP_Y_CRCB_H2V2: | ||
1806 | /* | ||
1807 | * Edge condition for MDP_Y_CRCB/CBCR_H2V2 cosite only. | ||
1808 | * For 420 cosite, 1 chroma replicated on all sides except | ||
1809 | * left, so reg 101b8 should be 0x0209. For 420 offsite, | ||
1810 | * 1 chroma replicated all sides. | ||
1811 | */ | ||
1812 | if (iBuf->roi.lcd_y == 0) { | ||
1813 | reg |= BIT(MDP_TOP_CHROMA); | ||
1814 | } | ||
1815 | |||
1816 | if ((iBuf->roi.lcd_y + iBuf->roi.dst_height) == | ||
1817 | iBuf->ibuf_height) { | ||
1818 | reg |= BIT(MDP_BOTTOM_CHROMA); | ||
1819 | } | ||
1820 | |||
1821 | if (((iBuf->roi.lcd_x + iBuf->roi.dst_width) == | ||
1822 | iBuf->ibuf_width) && ((iBuf->roi.dst_width % 2) == 0)) { | ||
1823 | reg |= BIT(MDP_RIGHT_CHROMA); | ||
1824 | } | ||
1825 | |||
1826 | break; | ||
1827 | |||
1828 | case MDP_Y_CBCR_H2V1: | ||
1829 | case MDP_Y_CRCB_H2V1: | ||
1830 | case MDP_YCRYCB_H2V1: | ||
1831 | if (((iBuf->roi.lcd_x + iBuf->roi.dst_width) == | ||
1832 | iBuf->ibuf_width) && ((iBuf->roi.dst_width % 2) == 0)) { | ||
1833 | reg |= BIT(MDP_RIGHT_CHROMA); | ||
1834 | } | ||
1835 | break; | ||
1836 | default: | ||
1837 | break; | ||
1838 | } | ||
1839 | |||
1840 | *dup2 = reg; | ||
1841 | |||
1842 | return 0; | ||
1843 | } | ||
1844 | |||
1845 | #define ADJUST_IP /* for 1/3 scale factor fix */ | ||
1846 | |||
1847 | static int mdp_calc_scale_params( | ||
1848 | /* ROI origin coordinate for the dimension */ | ||
1849 | uint32 org, | ||
1850 | /* src ROI dimension */ | ||
1851 | uint32 dim_in, | ||
1852 | /* scaled ROI dimension*/ | ||
1853 | uint32 dim_out, | ||
1854 | /* is this ROI width dimension? */ | ||
1855 | boolean is_W, | ||
1856 | /* initial phase location address */ | ||
1857 | int32 *phase_init_ptr, | ||
1858 | /* phase increment location address */ | ||
1859 | uint32 *phase_step_ptr, | ||
1860 | /* ROI start over-fetch location address */ | ||
1861 | uint32 *num_repl_beg_ptr, | ||
1862 | /* ROI end over-fetch location address */ | ||
1863 | uint32 *num_repl_end_ptr) | ||
1864 | { | ||
1865 | boolean rpa_on = FALSE; | ||
1866 | int init_phase = 0; | ||
1867 | uint32 beg_of = 0; | ||
1868 | uint32 end_of = 0; | ||
1869 | uint64 numer = 0; | ||
1870 | uint64 denom = 0; | ||
1871 | /*uint64 inverter = 1; */ | ||
1872 | int64 point5 = 1; | ||
1873 | int64 one = 1; | ||
1874 | int64 k1, k2, k3, k4; /* linear equation coefficients */ | ||
1875 | uint64 int_mask; | ||
1876 | uint64 fract_mask; | ||
1877 | uint64 Os; | ||
1878 | int64 Osprime; | ||
1879 | int64 Od; | ||
1880 | int64 Odprime; | ||
1881 | int64 Oreq; | ||
1882 | uint64 Es; | ||
1883 | uint64 Ed; | ||
1884 | uint64 Ereq; | ||
1885 | #ifdef ADJUST_IP | ||
1886 | int64 IP64; | ||
1887 | int64 delta; | ||
1888 | #endif | ||
1889 | uint32 mult; | ||
1890 | |||
1891 | /* | ||
1892 | * The phase accumulator should really be rational for all cases in a | ||
1893 | * general purpose polyphase scaler for a tiled architecture with | ||
1894 | * non-zero * origin capability because there is no way to represent | ||
1895 | * certain scale factors in fixed point regardless of precision. | ||
1896 | * The error incurred in attempting to use fixed point is most | ||
1897 | * eggregious for SF where 1/SF is an integral multiple of 1/3. | ||
1898 | * | ||
1899 | * However, since the MDP2 has already been committed to HW, we | ||
1900 | * only use the rational phase accumulator (RPA) when 1/SF is an | ||
1901 | * integral multiple of 1/3. This will help minimize regressions in | ||
1902 | * matching the HW to the C-Sim. | ||
1903 | */ | ||
1904 | /* | ||
1905 | * Set the RPA flag for this dimension. | ||
1906 | * | ||
1907 | * In order for 1/SF (dim_in/dim_out) to be an integral multiple of | ||
1908 | * 1/3, dim_out must be an integral multiple of 3. | ||
1909 | */ | ||
1910 | if (!(dim_out % 3)) { | ||
1911 | mult = dim_out / 3; | ||
1912 | rpa_on = (!(dim_in % mult)); | ||
1913 | } | ||
1914 | |||
1915 | numer = dim_out; | ||
1916 | denom = dim_in; | ||
1917 | |||
1918 | /* | ||
1919 | * convert to U30.34 before division | ||
1920 | * | ||
1921 | * The K vectors carry 4 extra bits of precision | ||
1922 | * and are rounded. | ||
1923 | * | ||
1924 | * We initially go 5 bits over then round by adding | ||
1925 | * 1 and right shifting by 1 | ||
1926 | * so final result is U31.33 | ||
1927 | */ | ||
1928 | numer <<= PQF_PLUS_5; | ||
1929 | |||
1930 | /* now calculate the scale factor (aka k3) */ | ||
1931 | k3 = ((mdp_do_div(numer, denom) + 1) >> 1); | ||
1932 | |||
1933 | /* check scale factor for legal range [0.25 - 4.0] */ | ||
1934 | if (((k3 >> 4) < (1LL << PQF_MINUS_2)) || | ||
1935 | ((k3 >> 4) > (1LL << PQF_PLUS_2))) { | ||
1936 | return -1; | ||
1937 | } | ||
1938 | |||
1939 | /* calculate inverse scale factor (aka k1) for phase init */ | ||
1940 | numer = dim_in; | ||
1941 | denom = dim_out; | ||
1942 | numer <<= PQF_PLUS_5; | ||
1943 | k1 = ((mdp_do_div(numer, denom) + 1) >> 1); | ||
1944 | |||
1945 | /* | ||
1946 | * calculate initial phase and ROI overfetch | ||
1947 | */ | ||
1948 | /* convert point5 & one to S39.24 (will always be positive) */ | ||
1949 | point5 <<= (PQF_PLUS_4 - 1); | ||
1950 | one <<= PQF_PLUS_4; | ||
1951 | k2 = ((k1 - one) >> 1); | ||
1952 | init_phase = (int)(k2 >> 4); | ||
1953 | k4 = ((k3 - one) >> 1); | ||
1954 | if (k3 == one) { | ||
1955 | /* the simple case; SF = 1.0 */ | ||
1956 | beg_of = 1; | ||
1957 | end_of = 2; | ||
1958 | } else { | ||
1959 | /* calculate the masks */ | ||
1960 | fract_mask = one - 1; | ||
1961 | int_mask = ~fract_mask; | ||
1962 | |||
1963 | if (!rpa_on) { | ||
1964 | /* | ||
1965 | * FIXED POINT IMPLEMENTATION | ||
1966 | */ | ||
1967 | if (!org) { | ||
1968 | /* A fairly simple case; ROI origin = 0 */ | ||
1969 | if (k1 < one) { | ||
1970 | /* upscaling */ | ||
1971 | beg_of = end_of = 2; | ||
1972 | } | ||
1973 | /* 0.33 <= SF < 1.0 */ | ||
1974 | else if (k1 < (3LL << PQF_PLUS_4)) | ||
1975 | beg_of = end_of = 1; | ||
1976 | /* 0.33 == SF */ | ||
1977 | else if (k1 == (3LL << PQF_PLUS_4)) { | ||
1978 | beg_of = 0; | ||
1979 | end_of = 1; | ||
1980 | } | ||
1981 | /* 0.25 <= SF < 0.33 */ | ||
1982 | else | ||
1983 | beg_of = end_of = 0; | ||
1984 | } else { | ||
1985 | /* | ||
1986 | * The complicated case; ROI origin != 0 | ||
1987 | * init_phase needs to be adjusted | ||
1988 | * OF is also position dependent | ||
1989 | */ | ||
1990 | |||
1991 | /* map (org - .5) into destination space */ | ||
1992 | Os = ((uint64) org << 1) - 1; | ||
1993 | Od = ((k3 * Os) >> 1) + k4; | ||
1994 | |||
1995 | /* take the ceiling */ | ||
1996 | Odprime = (Od & int_mask); | ||
1997 | if (Odprime != Od) | ||
1998 | Odprime += one; | ||
1999 | |||
2000 | /* now map that back to source space */ | ||
2001 | Osprime = (k1 * (Odprime >> PQF_PLUS_4)) + k2; | ||
2002 | |||
2003 | /* then floor & decrement to calculate the required | ||
2004 | starting coordinate */ | ||
2005 | Oreq = (Osprime & int_mask) - one; | ||
2006 | |||
2007 | /* calculate end coord in destination space then map to | ||
2008 | source space */ | ||
2009 | Ed = Odprime + | ||
2010 | ((uint64) dim_out << PQF_PLUS_4) - one; | ||
2011 | Es = (k1 * (Ed >> PQF_PLUS_4)) + k2; | ||
2012 | |||
2013 | /* now floor & increment by 2 to calculate the required | ||
2014 | ending coordinate */ | ||
2015 | Ereq = (Es & int_mask) + (one << 1); | ||
2016 | |||
2017 | /* calculate initial phase */ | ||
2018 | #ifdef ADJUST_IP | ||
2019 | |||
2020 | IP64 = Osprime - Oreq; | ||
2021 | delta = ((int64) (org) << PQF_PLUS_4) - Oreq; | ||
2022 | IP64 -= delta; | ||
2023 | |||
2024 | /* limit to valid range before the left shift */ | ||
2025 | delta = (IP64 & (1LL << 63)) ? 4 : -4; | ||
2026 | delta <<= PQF_PLUS_4; | ||
2027 | while (abs((int)(IP64 >> PQF_PLUS_4)) > 4) | ||
2028 | IP64 += delta; | ||
2029 | |||
2030 | /* right shift to account for extra bits of precision */ | ||
2031 | init_phase = (int)(IP64 >> 4); | ||
2032 | |||
2033 | #else /* ADJUST_IP */ | ||
2034 | |||
2035 | /* just calculate the real initial phase */ | ||
2036 | init_phase = (int)((Osprime - Oreq) >> 4); | ||
2037 | |||
2038 | #endif /* ADJUST_IP */ | ||
2039 | |||
2040 | /* calculate the overfetch */ | ||
2041 | beg_of = org - (uint32) (Oreq >> PQF_PLUS_4); | ||
2042 | end_of = | ||
2043 | (uint32) (Ereq >> PQF_PLUS_4) - (org + | ||
2044 | dim_in - | ||
2045 | 1); | ||
2046 | } | ||
2047 | } else { | ||
2048 | /* | ||
2049 | * RPA IMPLEMENTATION | ||
2050 | * | ||
2051 | * init_phase needs to be calculated in all RPA_on cases | ||
2052 | * because it's a numerator, not a fixed point value. | ||
2053 | */ | ||
2054 | |||
2055 | /* map (org - .5) into destination space */ | ||
2056 | Os = ((uint64) org << PQF_PLUS_4) - point5; | ||
2057 | Od = mdp_do_div((dim_out * (Os + point5)), | ||
2058 | dim_in) - point5; | ||
2059 | |||
2060 | /* take the ceiling */ | ||
2061 | Odprime = (Od & int_mask); | ||
2062 | if (Odprime != Od) | ||
2063 | Odprime += one; | ||
2064 | |||
2065 | /* now map that back to source space */ | ||
2066 | Osprime = | ||
2067 | mdp_do_div((dim_in * (Odprime + point5)), | ||
2068 | dim_out) - point5; | ||
2069 | |||
2070 | /* then floor & decrement to calculate the required | ||
2071 | starting coordinate */ | ||
2072 | Oreq = (Osprime & int_mask) - one; | ||
2073 | |||
2074 | /* calculate end coord in destination space then map to | ||
2075 | source space */ | ||
2076 | Ed = Odprime + ((uint64) dim_out << PQF_PLUS_4) - one; | ||
2077 | Es = mdp_do_div((dim_in * (Ed + point5)), | ||
2078 | dim_out) - point5; | ||
2079 | |||
2080 | /* now floor & increment by 2 to calculate the required | ||
2081 | ending coordinate */ | ||
2082 | Ereq = (Es & int_mask) + (one << 1); | ||
2083 | |||
2084 | /* calculate initial phase */ | ||
2085 | |||
2086 | #ifdef ADJUST_IP | ||
2087 | |||
2088 | IP64 = Osprime - Oreq; | ||
2089 | delta = ((int64) (org) << PQF_PLUS_4) - Oreq; | ||
2090 | IP64 -= delta; | ||
2091 | |||
2092 | /* limit to valid range before the left shift */ | ||
2093 | delta = (IP64 & (1LL << 63)) ? 4 : -4; | ||
2094 | delta <<= PQF_PLUS_4; | ||
2095 | while (abs((int)(IP64 >> PQF_PLUS_4)) > 4) | ||
2096 | IP64 += delta; | ||
2097 | |||
2098 | /* right shift to account for extra bits of precision */ | ||
2099 | init_phase = (int)(IP64 >> 4); | ||
2100 | |||
2101 | #else /* ADJUST_IP */ | ||
2102 | |||
2103 | /* just calculate the real initial phase */ | ||
2104 | init_phase = (int)((Osprime - Oreq) >> 4); | ||
2105 | |||
2106 | #endif /* ADJUST_IP */ | ||
2107 | |||
2108 | /* calculate the overfetch */ | ||
2109 | beg_of = org - (uint32) (Oreq >> PQF_PLUS_4); | ||
2110 | end_of = | ||
2111 | (uint32) (Ereq >> PQF_PLUS_4) - (org + dim_in - 1); | ||
2112 | } | ||
2113 | } | ||
2114 | |||
2115 | /* return the scale parameters */ | ||
2116 | *phase_init_ptr = init_phase; | ||
2117 | *phase_step_ptr = (uint32) (k1 >> 4); | ||
2118 | *num_repl_beg_ptr = beg_of; | ||
2119 | *num_repl_end_ptr = end_of; | ||
2120 | |||
2121 | return 0; | ||
2122 | } | ||
2123 | |||
2124 | static uint8 *mdp_adjust_rot_addr(MDPIBUF *iBuf, uint8 *addr, uint32 uv) | ||
2125 | { | ||
2126 | uint32 dest_ystride = iBuf->ibuf_width * iBuf->bpp; | ||
2127 | uint32 h_slice = 1; | ||
2128 | |||
2129 | if (uv && ((iBuf->ibuf_type == MDP_Y_CBCR_H2V2) || | ||
2130 | (iBuf->ibuf_type == MDP_Y_CRCB_H2V2))) | ||
2131 | h_slice = 2; | ||
2132 | |||
2133 | if (MDP_CHKBIT(iBuf->mdpImg.mdpOp, MDPOP_ROT90) ^ | ||
2134 | MDP_CHKBIT(iBuf->mdpImg.mdpOp, MDPOP_LR)) { | ||
2135 | addr = | ||
2136 | addr + (iBuf->roi.dst_width - | ||
2137 | MIN(16, iBuf->roi.dst_width)) * iBuf->bpp; | ||
2138 | } | ||
2139 | if (MDP_CHKBIT(iBuf->mdpImg.mdpOp, MDPOP_UD)) { | ||
2140 | addr = | ||
2141 | addr + ((iBuf->roi.dst_height - | ||
2142 | MIN(16, iBuf->roi.dst_height))/h_slice) * dest_ystride; | ||
2143 | } | ||
2144 | |||
2145 | return addr; | ||
2146 | } | ||
2147 | |||
2148 | void mdp_set_scale(MDPIBUF *iBuf, | ||
2149 | uint32 dst_roi_width, | ||
2150 | uint32 dst_roi_height, | ||
2151 | boolean inputRGB, boolean outputRGB, uint32 *pppop_reg_ptr) | ||
2152 | { | ||
2153 | uint32 dst_roi_width_scale; | ||
2154 | uint32 dst_roi_height_scale; | ||
2155 | boolean use_pr; | ||
2156 | uint32 phasex_step = 0; | ||
2157 | uint32 phasey_step = 0; | ||
2158 | int32 phasex_init = 0; | ||
2159 | int32 phasey_init = 0; | ||
2160 | uint32 lines_dup = 0; | ||
2161 | uint32 lines_dup_bg = 0; | ||
2162 | uint32 dummy; | ||
2163 | uint32 mdp_blur = 0; | ||
2164 | |||
2165 | if (iBuf->mdpImg.mdpOp & MDPOP_ASCALE) { | ||
2166 | if (iBuf->mdpImg.mdpOp & MDPOP_ROT90) { | ||
2167 | dst_roi_width_scale = dst_roi_height; | ||
2168 | dst_roi_height_scale = dst_roi_width; | ||
2169 | } else { | ||
2170 | dst_roi_width_scale = dst_roi_width; | ||
2171 | dst_roi_height_scale = dst_roi_height; | ||
2172 | } | ||
2173 | |||
2174 | mdp_blur = iBuf->mdpImg.mdpOp & MDPOP_BLUR; | ||
2175 | |||
2176 | if ((dst_roi_width_scale != iBuf->roi.width) || | ||
2177 | (dst_roi_height_scale != iBuf->roi.height) || | ||
2178 | mdp_blur) { | ||
2179 | *pppop_reg_ptr |= | ||
2180 | (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON); | ||
2181 | |||
2182 | /* let's use SHIM logic to calculate the partial ROI scaling */ | ||
2183 | #if 0 | ||
2184 | phasex_step = | ||
2185 | (uint32) mdp_do_div(0x20000000 * iBuf->roi.width, | ||
2186 | dst_roi_width_scale); | ||
2187 | phasey_step = | ||
2188 | (uint32) mdp_do_div(0x20000000 * iBuf->roi.height, | ||
2189 | dst_roi_height_scale); | ||
2190 | |||
2191 | /* | ||
2192 | phasex_step= ((long long) iBuf->roi.width * 0x20000000)/dst_roi_width_scale; | ||
2193 | phasey_step= ((long long)iBuf->roi.height * 0x20000000)/dst_roi_height_scale; | ||
2194 | */ | ||
2195 | |||
2196 | phasex_init = | ||
2197 | (((long long)phasex_step - 0x20000000) >> 1); | ||
2198 | phasey_init = | ||
2199 | (((long long)phasey_step - 0x20000000) >> 1); | ||
2200 | |||
2201 | #else | ||
2202 | mdp_calc_scale_params(iBuf->roi.x, iBuf->roi.width, | ||
2203 | dst_roi_width_scale, 1, | ||
2204 | &phasex_init, &phasex_step, | ||
2205 | &dummy, &dummy); | ||
2206 | mdp_calc_scale_params(iBuf->roi.y, iBuf->roi.height, | ||
2207 | dst_roi_height_scale, 0, | ||
2208 | &phasey_init, &phasey_step, | ||
2209 | &dummy, &dummy); | ||
2210 | #endif | ||
2211 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x013c, | ||
2212 | phasex_init); | ||
2213 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0140, | ||
2214 | phasey_init); | ||
2215 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0144, | ||
2216 | phasex_step); | ||
2217 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0148, | ||
2218 | phasey_step); | ||
2219 | |||
2220 | use_pr = (inputRGB) && (outputRGB); | ||
2221 | |||
2222 | if ((dst_roi_width_scale > iBuf->roi.width) || | ||
2223 | (dst_roi_height_scale > iBuf->roi.height)) { | ||
2224 | if ((use_pr) | ||
2225 | && (mdp_curr_up_scale_xy != | ||
2226 | MDP_PR_SCALE_UP)) { | ||
2227 | mdp_load_pr_upscale_table(); | ||
2228 | mdp_curr_up_scale_xy = MDP_PR_SCALE_UP; | ||
2229 | } else if ((!use_pr) | ||
2230 | && (mdp_curr_up_scale_xy != | ||
2231 | MDP_BC_SCALE_UP)) { | ||
2232 | mdp_load_bc_upscale_table(); | ||
2233 | mdp_curr_up_scale_xy = MDP_BC_SCALE_UP; | ||
2234 | } | ||
2235 | } | ||
2236 | |||
2237 | if (mdp_blur) { | ||
2238 | load_scale_table(mdp_gaussian_blur_table, | ||
2239 | ARRAY_SIZE(mdp_gaussian_blur_table)); | ||
2240 | mdp_curr_down_scale_x = MDP_SCALE_BLUR; | ||
2241 | mdp_curr_down_scale_y = MDP_SCALE_BLUR; | ||
2242 | } | ||
2243 | |||
2244 | /* 0.2 < x <= 1 scaling factor */ | ||
2245 | if ((dst_roi_width_scale <= iBuf->roi.width) && | ||
2246 | !mdp_blur) { | ||
2247 | if (((dst_roi_width_scale * 10) / | ||
2248 | iBuf->roi.width) > 8) { | ||
2249 | if ((use_pr) | ||
2250 | && (mdp_curr_down_scale_x != | ||
2251 | MDP_PR_SCALE_POINT8_1)) { | ||
2252 | mdp_load_pr_downscale_table_x_point8TO1 | ||
2253 | (); | ||
2254 | mdp_curr_down_scale_x = | ||
2255 | MDP_PR_SCALE_POINT8_1; | ||
2256 | } else if ((!use_pr) | ||
2257 | && (mdp_curr_down_scale_x != | ||
2258 | MDP_BC_SCALE_POINT8_1)) { | ||
2259 | mdp_load_bc_downscale_table_x_point8TO1 | ||
2260 | (); | ||
2261 | mdp_curr_down_scale_x = | ||
2262 | MDP_BC_SCALE_POINT8_1; | ||
2263 | } | ||
2264 | } else | ||
2265 | if (((dst_roi_width_scale * 10) / | ||
2266 | iBuf->roi.width) > 6) { | ||
2267 | if ((use_pr) | ||
2268 | && (mdp_curr_down_scale_x != | ||
2269 | MDP_PR_SCALE_POINT6_POINT8)) { | ||
2270 | mdp_load_pr_downscale_table_x_point6TOpoint8 | ||
2271 | (); | ||
2272 | mdp_curr_down_scale_x = | ||
2273 | MDP_PR_SCALE_POINT6_POINT8; | ||
2274 | } else if ((!use_pr) | ||
2275 | && (mdp_curr_down_scale_x != | ||
2276 | MDP_BC_SCALE_POINT6_POINT8)) | ||
2277 | { | ||
2278 | mdp_load_bc_downscale_table_x_point6TOpoint8 | ||
2279 | (); | ||
2280 | mdp_curr_down_scale_x = | ||
2281 | MDP_BC_SCALE_POINT6_POINT8; | ||
2282 | } | ||
2283 | } else | ||
2284 | if (((dst_roi_width_scale * 10) / | ||
2285 | iBuf->roi.width) > 4) { | ||
2286 | if ((use_pr) | ||
2287 | && (mdp_curr_down_scale_x != | ||
2288 | MDP_PR_SCALE_POINT4_POINT6)) { | ||
2289 | mdp_load_pr_downscale_table_x_point4TOpoint6 | ||
2290 | (); | ||
2291 | mdp_curr_down_scale_x = | ||
2292 | MDP_PR_SCALE_POINT4_POINT6; | ||
2293 | } else if ((!use_pr) | ||
2294 | && (mdp_curr_down_scale_x != | ||
2295 | MDP_BC_SCALE_POINT4_POINT6)) | ||
2296 | { | ||
2297 | mdp_load_bc_downscale_table_x_point4TOpoint6 | ||
2298 | (); | ||
2299 | mdp_curr_down_scale_x = | ||
2300 | MDP_BC_SCALE_POINT4_POINT6; | ||
2301 | } | ||
2302 | } else { | ||
2303 | if ((use_pr) | ||
2304 | && (mdp_curr_down_scale_x != | ||
2305 | MDP_PR_SCALE_POINT2_POINT4)) { | ||
2306 | mdp_load_pr_downscale_table_x_point2TOpoint4 | ||
2307 | (); | ||
2308 | mdp_curr_down_scale_x = | ||
2309 | MDP_PR_SCALE_POINT2_POINT4; | ||
2310 | } else if ((!use_pr) | ||
2311 | && (mdp_curr_down_scale_x != | ||
2312 | MDP_BC_SCALE_POINT2_POINT4)) | ||
2313 | { | ||
2314 | mdp_load_bc_downscale_table_x_point2TOpoint4 | ||
2315 | (); | ||
2316 | mdp_curr_down_scale_x = | ||
2317 | MDP_BC_SCALE_POINT2_POINT4; | ||
2318 | } | ||
2319 | } | ||
2320 | } | ||
2321 | /* 0.2 < y <= 1 scaling factor */ | ||
2322 | if ((dst_roi_height_scale <= iBuf->roi.height) && | ||
2323 | !mdp_blur) { | ||
2324 | if (((dst_roi_height_scale * 10) / | ||
2325 | iBuf->roi.height) > 8) { | ||
2326 | if ((use_pr) | ||
2327 | && (mdp_curr_down_scale_y != | ||
2328 | MDP_PR_SCALE_POINT8_1)) { | ||
2329 | mdp_load_pr_downscale_table_y_point8TO1 | ||
2330 | (); | ||
2331 | mdp_curr_down_scale_y = | ||
2332 | MDP_PR_SCALE_POINT8_1; | ||
2333 | } else if ((!use_pr) | ||
2334 | && (mdp_curr_down_scale_y != | ||
2335 | MDP_BC_SCALE_POINT8_1)) { | ||
2336 | mdp_load_bc_downscale_table_y_point8TO1 | ||
2337 | (); | ||
2338 | mdp_curr_down_scale_y = | ||
2339 | MDP_BC_SCALE_POINT8_1; | ||
2340 | } | ||
2341 | } else | ||
2342 | if (((dst_roi_height_scale * 10) / | ||
2343 | iBuf->roi.height) > 6) { | ||
2344 | if ((use_pr) | ||
2345 | && (mdp_curr_down_scale_y != | ||
2346 | MDP_PR_SCALE_POINT6_POINT8)) { | ||
2347 | mdp_load_pr_downscale_table_y_point6TOpoint8 | ||
2348 | (); | ||
2349 | mdp_curr_down_scale_y = | ||
2350 | MDP_PR_SCALE_POINT6_POINT8; | ||
2351 | } else if ((!use_pr) | ||
2352 | && (mdp_curr_down_scale_y != | ||
2353 | MDP_BC_SCALE_POINT6_POINT8)) | ||
2354 | { | ||
2355 | mdp_load_bc_downscale_table_y_point6TOpoint8 | ||
2356 | (); | ||
2357 | mdp_curr_down_scale_y = | ||
2358 | MDP_BC_SCALE_POINT6_POINT8; | ||
2359 | } | ||
2360 | } else | ||
2361 | if (((dst_roi_height_scale * 10) / | ||
2362 | iBuf->roi.height) > 4) { | ||
2363 | if ((use_pr) | ||
2364 | && (mdp_curr_down_scale_y != | ||
2365 | MDP_PR_SCALE_POINT4_POINT6)) { | ||
2366 | mdp_load_pr_downscale_table_y_point4TOpoint6 | ||
2367 | (); | ||
2368 | mdp_curr_down_scale_y = | ||
2369 | MDP_PR_SCALE_POINT4_POINT6; | ||
2370 | } else if ((!use_pr) | ||
2371 | && (mdp_curr_down_scale_y != | ||
2372 | MDP_BC_SCALE_POINT4_POINT6)) | ||
2373 | { | ||
2374 | mdp_load_bc_downscale_table_y_point4TOpoint6 | ||
2375 | (); | ||
2376 | mdp_curr_down_scale_y = | ||
2377 | MDP_BC_SCALE_POINT4_POINT6; | ||
2378 | } | ||
2379 | } else { | ||
2380 | if ((use_pr) | ||
2381 | && (mdp_curr_down_scale_y != | ||
2382 | MDP_PR_SCALE_POINT2_POINT4)) { | ||
2383 | mdp_load_pr_downscale_table_y_point2TOpoint4 | ||
2384 | (); | ||
2385 | mdp_curr_down_scale_y = | ||
2386 | MDP_PR_SCALE_POINT2_POINT4; | ||
2387 | } else if ((!use_pr) | ||
2388 | && (mdp_curr_down_scale_y != | ||
2389 | MDP_BC_SCALE_POINT2_POINT4)) | ||
2390 | { | ||
2391 | mdp_load_bc_downscale_table_y_point2TOpoint4 | ||
2392 | (); | ||
2393 | mdp_curr_down_scale_y = | ||
2394 | MDP_BC_SCALE_POINT2_POINT4; | ||
2395 | } | ||
2396 | } | ||
2397 | } | ||
2398 | } else { | ||
2399 | iBuf->mdpImg.mdpOp &= ~(MDPOP_ASCALE); | ||
2400 | } | ||
2401 | } | ||
2402 | /* setting edge condition here after scaling check */ | ||
2403 | if (mdp_get_edge_cond(iBuf, &lines_dup, &lines_dup_bg)) | ||
2404 | printk(KERN_ERR "msm_fb: mdp_get_edge_cond() error!\n"); | ||
2405 | |||
2406 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01b8, lines_dup); | ||
2407 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01bc, lines_dup_bg); | ||
2408 | } | ||
2409 | |||
2410 | void mdp_init_scale_table(void) | ||
2411 | { | ||
2412 | mdp_curr_up_scale_xy = MDP_INIT_SCALE; | ||
2413 | mdp_curr_down_scale_x = MDP_INIT_SCALE; | ||
2414 | mdp_curr_down_scale_y = MDP_INIT_SCALE; | ||
2415 | } | ||
2416 | |||
2417 | void mdp_adjust_start_addr(uint8 **src0, | ||
2418 | uint8 **src1, | ||
2419 | int v_slice, | ||
2420 | int h_slice, | ||
2421 | int x, | ||
2422 | int y, | ||
2423 | uint32 width, | ||
2424 | uint32 height, int bpp, MDPIBUF *iBuf, int layer) | ||
2425 | { | ||
2426 | *src0 += (x + y * width) * bpp; | ||
2427 | |||
2428 | /* if it's dest/bg buffer, we need to adjust it for rotation */ | ||
2429 | if (layer != 0) | ||
2430 | *src0 = mdp_adjust_rot_addr(iBuf, *src0, 0); | ||
2431 | |||
2432 | if (*src1) { | ||
2433 | /* | ||
2434 | * MDP_Y_CBCR_H2V2/MDP_Y_CRCB_H2V2 cosite for now | ||
2435 | * we need to shift x direction same as y dir for offsite | ||
2436 | */ | ||
2437 | *src1 += | ||
2438 | ((x / h_slice) * h_slice + | ||
2439 | ((y == 0) ? 0 : ((y + 1) / v_slice - 1) * width)) * bpp; | ||
2440 | |||
2441 | /* if it's dest/bg buffer, we need to adjust it for rotation */ | ||
2442 | if (layer != 0) | ||
2443 | *src1 = mdp_adjust_rot_addr(iBuf, *src1, 1); | ||
2444 | } | ||
2445 | } | ||
2446 | |||
2447 | void mdp_set_blend_attr(MDPIBUF *iBuf, | ||
2448 | uint32 *alpha, | ||
2449 | uint32 *tpVal, | ||
2450 | uint32 perPixelAlpha, uint32 *pppop_reg_ptr) | ||
2451 | { | ||
2452 | if (perPixelAlpha) { | ||
2453 | *pppop_reg_ptr |= PPP_OP_ROT_ON | | ||
2454 | PPP_OP_BLEND_ON | PPP_OP_BLEND_SRCPIXEL_ALPHA; | ||
2455 | } else { | ||
2456 | if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB) | ||
2457 | && (iBuf->mdpImg.alpha == 0xff)) { | ||
2458 | iBuf->mdpImg.mdpOp &= ~(MDPOP_ALPHAB); | ||
2459 | } | ||
2460 | |||
2461 | if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB) | ||
2462 | && (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)) { | ||
2463 | *pppop_reg_ptr |= | ||
2464 | PPP_OP_ROT_ON | PPP_OP_BLEND_ON | | ||
2465 | PPP_OP_BLEND_CONSTANT_ALPHA | | ||
2466 | PPP_OP_BLEND_ALPHA_BLEND_NORMAL | | ||
2467 | PPP_BLEND_CALPHA_TRNASP; | ||
2468 | |||
2469 | *alpha = iBuf->mdpImg.alpha; | ||
2470 | *tpVal = iBuf->mdpImg.tpVal; | ||
2471 | } else { | ||
2472 | if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP) { | ||
2473 | *pppop_reg_ptr |= PPP_OP_ROT_ON | | ||
2474 | PPP_OP_BLEND_ON | | ||
2475 | PPP_OP_BLEND_SRCPIXEL_TRANSP; | ||
2476 | *tpVal = iBuf->mdpImg.tpVal; | ||
2477 | } else if (iBuf->mdpImg.mdpOp & MDPOP_ALPHAB) { | ||
2478 | *pppop_reg_ptr |= PPP_OP_ROT_ON | | ||
2479 | PPP_OP_BLEND_ON | | ||
2480 | PPP_OP_BLEND_ALPHA_BLEND_NORMAL | | ||
2481 | PPP_OP_BLEND_CONSTANT_ALPHA; | ||
2482 | *alpha = iBuf->mdpImg.alpha; | ||
2483 | } | ||
2484 | } | ||
2485 | } | ||
2486 | } | ||
diff --git a/drivers/staging/msm/mdp_ppp_v31.c b/drivers/staging/msm/mdp_ppp_v31.c new file mode 100644 index 000000000000..76495dbe4e64 --- /dev/null +++ b/drivers/staging/msm/mdp_ppp_v31.c | |||
@@ -0,0 +1,828 @@ | |||
1 | /* Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/sched.h> | ||
21 | #include <linux/time.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/fb.h> | ||
25 | #include "linux/proc_fs.h" | ||
26 | |||
27 | #include <mach/hardware.h> | ||
28 | #include <linux/io.h> | ||
29 | |||
30 | #include <asm/system.h> | ||
31 | #include <asm/mach-types.h> | ||
32 | #include <linux/semaphore.h> | ||
33 | #include <asm/div64.h> | ||
34 | |||
35 | #include "mdp.h" | ||
36 | #include "msm_fb.h" | ||
37 | |||
38 | #define MDP_SCALE_COEFF_NUM 32 | ||
39 | #define MDP_SCALE_0P2_TO_0P4_INDEX 0 | ||
40 | #define MDP_SCALE_0P4_TO_0P6_INDEX 32 | ||
41 | #define MDP_SCALE_0P6_TO_0P8_INDEX 64 | ||
42 | #define MDP_SCALE_0P8_TO_8P0_INDEX 96 | ||
43 | #define MDP_SCALE_COEFF_MASK 0x3ff | ||
44 | |||
45 | #define MDP_SCALE_PR 0 | ||
46 | #define MDP_SCALE_FIR 1 | ||
47 | |||
48 | static uint32 mdp_scale_0p8_to_8p0_mode; | ||
49 | static uint32 mdp_scale_0p6_to_0p8_mode; | ||
50 | static uint32 mdp_scale_0p4_to_0p6_mode; | ||
51 | static uint32 mdp_scale_0p2_to_0p4_mode; | ||
52 | |||
53 | /* -------- All scaling range, "pixel repeat" -------- */ | ||
54 | static int16 mdp_scale_pixel_repeat_C0[MDP_SCALE_COEFF_NUM] = { | ||
55 | 0, 0, 0, 0, 0, 0, 0, 0, | ||
56 | 0, 0, 0, 0, 0, 0, 0, 0, | ||
57 | 0, 0, 0, 0, 0, 0, 0, 0, | ||
58 | 0, 0, 0, 0, 0, 0, 0, 0 | ||
59 | }; | ||
60 | |||
61 | static int16 mdp_scale_pixel_repeat_C1[MDP_SCALE_COEFF_NUM] = { | ||
62 | 511, 511, 511, 511, 511, 511, 511, 511, | ||
63 | 511, 511, 511, 511, 511, 511, 511, 511, | ||
64 | 511, 511, 511, 511, 511, 511, 511, 511, | ||
65 | 511, 511, 511, 511, 511, 511, 511, 511 | ||
66 | }; | ||
67 | |||
68 | static int16 mdp_scale_pixel_repeat_C2[MDP_SCALE_COEFF_NUM] = { | ||
69 | 0, 0, 0, 0, 0, 0, 0, 0, | ||
70 | 0, 0, 0, 0, 0, 0, 0, 0, | ||
71 | 0, 0, 0, 0, 0, 0, 0, 0, | ||
72 | 0, 0, 0, 0, 0, 0, 0, 0 | ||
73 | }; | ||
74 | |||
75 | static int16 mdp_scale_pixel_repeat_C3[MDP_SCALE_COEFF_NUM] = { | ||
76 | 0, 0, 0, 0, 0, 0, 0, 0, | ||
77 | 0, 0, 0, 0, 0, 0, 0, 0, | ||
78 | 0, 0, 0, 0, 0, 0, 0, 0, | ||
79 | 0, 0, 0, 0, 0, 0, 0, 0 | ||
80 | }; | ||
81 | |||
82 | /* --------------------------- FIR ------------------------------------- */ | ||
83 | /* -------- Downscale, ranging from 0.8x to 8.0x of original size -------- */ | ||
84 | |||
85 | static int16 mdp_scale_0p8_to_8p0_C0[MDP_SCALE_COEFF_NUM] = { | ||
86 | 0, -7, -13, -19, -24, -28, -32, -34, -37, -39, | ||
87 | -40, -41, -41, -41, -40, -40, -38, -37, -35, -33, | ||
88 | -31, -29, -26, -24, -21, -18, -15, -13, -10, -7, | ||
89 | -5, -2 | ||
90 | }; | ||
91 | |||
92 | static int16 mdp_scale_0p8_to_8p0_C1[MDP_SCALE_COEFF_NUM] = { | ||
93 | 511, 507, 501, 494, 485, 475, 463, 450, 436, 422, | ||
94 | 405, 388, 370, 352, 333, 314, 293, 274, 253, 233, | ||
95 | 213, 193, 172, 152, 133, 113, 95, 77, 60, 43, | ||
96 | 28, 13 | ||
97 | }; | ||
98 | |||
99 | static int16 mdp_scale_0p8_to_8p0_C2[MDP_SCALE_COEFF_NUM] = { | ||
100 | 0, 13, 28, 43, 60, 77, 95, 113, 133, 152, | ||
101 | 172, 193, 213, 233, 253, 274, 294, 314, 333, 352, | ||
102 | 370, 388, 405, 422, 436, 450, 463, 475, 485, 494, | ||
103 | 501, 507, | ||
104 | }; | ||
105 | |||
106 | static int16 mdp_scale_0p8_to_8p0_C3[MDP_SCALE_COEFF_NUM] = { | ||
107 | 0, -2, -5, -7, -10, -13, -15, -18, -21, -24, | ||
108 | -26, -29, -31, -33, -35, -37, -38, -40, -40, -41, | ||
109 | -41, -41, -40, -39, -37, -34, -32, -28, -24, -19, | ||
110 | -13, -7 | ||
111 | }; | ||
112 | |||
113 | /* -------- Downscale, ranging from 0.6x to 0.8x of original size -------- */ | ||
114 | |||
115 | static int16 mdp_scale_0p6_to_0p8_C0[MDP_SCALE_COEFF_NUM] = { | ||
116 | 104, 96, 89, 82, 75, 68, 61, 55, 49, 43, | ||
117 | 38, 33, 28, 24, 20, 16, 12, 9, 6, 4, | ||
118 | 2, 0, -2, -4, -5, -6, -7, -7, -8, -8, | ||
119 | -8, -8 | ||
120 | }; | ||
121 | |||
122 | static int16 mdp_scale_0p6_to_0p8_C1[MDP_SCALE_COEFF_NUM] = { | ||
123 | 303, 303, 302, 300, 298, 296, 293, 289, 286, 281, | ||
124 | 276, 270, 265, 258, 252, 245, 238, 230, 223, 214, | ||
125 | 206, 197, 189, 180, 172, 163, 154, 145, 137, 128, | ||
126 | 120, 112 | ||
127 | }; | ||
128 | |||
129 | static int16 mdp_scale_0p6_to_0p8_C2[MDP_SCALE_COEFF_NUM] = { | ||
130 | 112, 120, 128, 137, 145, 154, 163, 172, 180, 189, | ||
131 | 197, 206, 214, 223, 230, 238, 245, 252, 258, 265, | ||
132 | 270, 276, 281, 286, 289, 293, 296, 298, 300, 302, | ||
133 | 303, 303 | ||
134 | }; | ||
135 | |||
136 | static int16 mdp_scale_0p6_to_0p8_C3[MDP_SCALE_COEFF_NUM] = { | ||
137 | -8, -8, -8, -8, -7, -7, -6, -5, -4, -2, | ||
138 | 0, 2, 4, 6, 9, 12, 16, 20, 24, 28, | ||
139 | 33, 38, 43, 49, 55, 61, 68, 75, 82, 89, | ||
140 | 96, 104 | ||
141 | }; | ||
142 | |||
143 | /* -------- Downscale, ranging from 0.4x to 0.6x of original size -------- */ | ||
144 | |||
145 | static int16 mdp_scale_0p4_to_0p6_C0[MDP_SCALE_COEFF_NUM] = { | ||
146 | 136, 132, 128, 123, 119, 115, 111, 107, 103, 98, | ||
147 | 95, 91, 87, 84, 80, 76, 73, 69, 66, 62, | ||
148 | 59, 57, 54, 50, 47, 44, 41, 39, 36, 33, | ||
149 | 32, 29 | ||
150 | }; | ||
151 | |||
152 | static int16 mdp_scale_0p4_to_0p6_C1[MDP_SCALE_COEFF_NUM] = { | ||
153 | 206, 205, 204, 204, 201, 200, 199, 197, 196, 194, | ||
154 | 191, 191, 189, 185, 184, 182, 180, 178, 176, 173, | ||
155 | 170, 168, 165, 162, 160, 157, 155, 152, 148, 146, | ||
156 | 142, 140 | ||
157 | }; | ||
158 | |||
159 | static int16 mdp_scale_0p4_to_0p6_C2[MDP_SCALE_COEFF_NUM] = { | ||
160 | 140, 142, 146, 148, 152, 155, 157, 160, 162, 165, | ||
161 | 168, 170, 173, 176, 178, 180, 182, 184, 185, 189, | ||
162 | 191, 191, 194, 196, 197, 199, 200, 201, 204, 204, | ||
163 | 205, 206 | ||
164 | }; | ||
165 | |||
166 | static int16 mdp_scale_0p4_to_0p6_C3[MDP_SCALE_COEFF_NUM] = { | ||
167 | 29, 32, 33, 36, 39, 41, 44, 47, 50, 54, | ||
168 | 57, 59, 62, 66, 69, 73, 76, 80, 84, 87, | ||
169 | 91, 95, 98, 103, 107, 111, 115, 119, 123, 128, | ||
170 | 132, 136 | ||
171 | }; | ||
172 | |||
173 | /* -------- Downscale, ranging from 0.2x to 0.4x of original size -------- */ | ||
174 | |||
175 | static int16 mdp_scale_0p2_to_0p4_C0[MDP_SCALE_COEFF_NUM] = { | ||
176 | 131, 131, 130, 129, 128, 127, 127, 126, 125, 125, | ||
177 | 124, 123, 123, 121, 120, 119, 119, 118, 117, 117, | ||
178 | 116, 115, 115, 114, 113, 112, 111, 110, 109, 109, | ||
179 | 108, 107 | ||
180 | }; | ||
181 | |||
182 | static int16 mdp_scale_0p2_to_0p4_C1[MDP_SCALE_COEFF_NUM] = { | ||
183 | 141, 140, 140, 140, 140, 139, 138, 138, 138, 137, | ||
184 | 137, 137, 136, 137, 137, 137, 136, 136, 136, 135, | ||
185 | 135, 135, 134, 134, 134, 134, 134, 133, 133, 132, | ||
186 | 132, 132 | ||
187 | }; | ||
188 | |||
189 | static int16 mdp_scale_0p2_to_0p4_C2[MDP_SCALE_COEFF_NUM] = { | ||
190 | 132, 132, 132, 133, 133, 134, 134, 134, 134, 134, | ||
191 | 135, 135, 135, 136, 136, 136, 137, 137, 137, 136, | ||
192 | 137, 137, 137, 138, 138, 138, 139, 140, 140, 140, | ||
193 | 140, 141 | ||
194 | }; | ||
195 | |||
196 | static int16 mdp_scale_0p2_to_0p4_C3[MDP_SCALE_COEFF_NUM] = { | ||
197 | 107, 108, 109, 109, 110, 111, 112, 113, 114, 115, | ||
198 | 115, 116, 117, 117, 118, 119, 119, 120, 121, 123, | ||
199 | 123, 124, 125, 125, 126, 127, 127, 128, 129, 130, | ||
200 | 131, 131 | ||
201 | }; | ||
202 | |||
203 | static void mdp_update_scale_table(int index, int16 *c0, int16 *c1, | ||
204 | int16 *c2, int16 *c3) | ||
205 | { | ||
206 | int i, val; | ||
207 | |||
208 | for (i = 0; i < MDP_SCALE_COEFF_NUM; i++) { | ||
209 | val = | ||
210 | ((MDP_SCALE_COEFF_MASK & c1[i]) << 16) | | ||
211 | (MDP_SCALE_COEFF_MASK & c0[i]); | ||
212 | MDP_OUTP(MDP_PPP_SCALE_COEFF_LSBn(index), val); | ||
213 | val = | ||
214 | ((MDP_SCALE_COEFF_MASK & c3[i]) << 16) | | ||
215 | (MDP_SCALE_COEFF_MASK & c2[i]); | ||
216 | MDP_OUTP(MDP_PPP_SCALE_COEFF_MSBn(index), val); | ||
217 | index++; | ||
218 | } | ||
219 | } | ||
220 | |||
221 | void mdp_init_scale_table(void) | ||
222 | { | ||
223 | mdp_scale_0p2_to_0p4_mode = MDP_SCALE_FIR; | ||
224 | mdp_update_scale_table(MDP_SCALE_0P2_TO_0P4_INDEX, | ||
225 | mdp_scale_0p2_to_0p4_C0, | ||
226 | mdp_scale_0p2_to_0p4_C1, | ||
227 | mdp_scale_0p2_to_0p4_C2, | ||
228 | mdp_scale_0p2_to_0p4_C3); | ||
229 | |||
230 | mdp_scale_0p4_to_0p6_mode = MDP_SCALE_FIR; | ||
231 | mdp_update_scale_table(MDP_SCALE_0P4_TO_0P6_INDEX, | ||
232 | mdp_scale_0p4_to_0p6_C0, | ||
233 | mdp_scale_0p4_to_0p6_C1, | ||
234 | mdp_scale_0p4_to_0p6_C2, | ||
235 | mdp_scale_0p4_to_0p6_C3); | ||
236 | |||
237 | mdp_scale_0p6_to_0p8_mode = MDP_SCALE_FIR; | ||
238 | mdp_update_scale_table(MDP_SCALE_0P6_TO_0P8_INDEX, | ||
239 | mdp_scale_0p6_to_0p8_C0, | ||
240 | mdp_scale_0p6_to_0p8_C1, | ||
241 | mdp_scale_0p6_to_0p8_C2, | ||
242 | mdp_scale_0p6_to_0p8_C3); | ||
243 | |||
244 | mdp_scale_0p8_to_8p0_mode = MDP_SCALE_FIR; | ||
245 | mdp_update_scale_table(MDP_SCALE_0P8_TO_8P0_INDEX, | ||
246 | mdp_scale_0p8_to_8p0_C0, | ||
247 | mdp_scale_0p8_to_8p0_C1, | ||
248 | mdp_scale_0p8_to_8p0_C2, | ||
249 | mdp_scale_0p8_to_8p0_C3); | ||
250 | } | ||
251 | |||
252 | static long long mdp_do_div(long long num, long long den) | ||
253 | { | ||
254 | do_div(num, den); | ||
255 | return num; | ||
256 | } | ||
257 | |||
258 | #define SCALER_PHASE_BITS 29 | ||
259 | #define HAL_MDP_PHASE_STEP_2P50 0x50000000 | ||
260 | #define HAL_MDP_PHASE_STEP_1P66 0x35555555 | ||
261 | #define HAL_MDP_PHASE_STEP_1P25 0x28000000 | ||
262 | |||
263 | struct phase_val { | ||
264 | int phase_init_x; | ||
265 | int phase_init_y; | ||
266 | int phase_step_x; | ||
267 | int phase_step_y; | ||
268 | }; | ||
269 | |||
270 | static void mdp_calc_scaleInitPhase_3p1(uint32 in_w, | ||
271 | uint32 in_h, | ||
272 | uint32 out_w, | ||
273 | uint32 out_h, | ||
274 | boolean is_rotate, | ||
275 | boolean is_pp_x, | ||
276 | boolean is_pp_y, struct phase_val *pval) | ||
277 | { | ||
278 | uint64 dst_ROI_width; | ||
279 | uint64 dst_ROI_height; | ||
280 | uint64 src_ROI_width; | ||
281 | uint64 src_ROI_height; | ||
282 | |||
283 | /* | ||
284 | * phase_step_x, phase_step_y, phase_init_x and phase_init_y | ||
285 | * are represented in fixed-point, unsigned 3.29 format | ||
286 | */ | ||
287 | uint32 phase_step_x = 0; | ||
288 | uint32 phase_step_y = 0; | ||
289 | uint32 phase_init_x = 0; | ||
290 | uint32 phase_init_y = 0; | ||
291 | uint32 yscale_filter_sel, xscale_filter_sel; | ||
292 | uint32 scale_unit_sel_x, scale_unit_sel_y; | ||
293 | |||
294 | uint64 numerator, denominator; | ||
295 | uint64 temp_dim; | ||
296 | |||
297 | src_ROI_width = in_w; | ||
298 | src_ROI_height = in_h; | ||
299 | dst_ROI_width = out_w; | ||
300 | dst_ROI_height = out_h; | ||
301 | |||
302 | /* if there is a 90 degree rotation */ | ||
303 | if (is_rotate) { | ||
304 | /* decide whether to use FIR or M/N for scaling */ | ||
305 | |||
306 | /* if down-scaling by a factor smaller than 1/4 */ | ||
307 | if (src_ROI_width > (4 * dst_ROI_height)) | ||
308 | scale_unit_sel_x = 1; /* use M/N scalar */ | ||
309 | else | ||
310 | scale_unit_sel_x = 0; /* use FIR scalar */ | ||
311 | |||
312 | /* if down-scaling by a factor smaller than 1/4 */ | ||
313 | if (src_ROI_height > (4 * dst_ROI_width)) | ||
314 | scale_unit_sel_y = 1; /* use M/N scalar */ | ||
315 | else | ||
316 | scale_unit_sel_y = 0; /* use FIR scalar */ | ||
317 | } else { | ||
318 | /* decide whether to use FIR or M/N for scaling */ | ||
319 | |||
320 | if (src_ROI_width > (4 * dst_ROI_width)) | ||
321 | scale_unit_sel_x = 1; /* use M/N scalar */ | ||
322 | else | ||
323 | scale_unit_sel_x = 0; /* use FIR scalar */ | ||
324 | |||
325 | if (src_ROI_height > (4 * dst_ROI_height)) | ||
326 | scale_unit_sel_y = 1; /* use M/N scalar */ | ||
327 | else | ||
328 | scale_unit_sel_y = 0; /* use FIR scalar */ | ||
329 | |||
330 | } | ||
331 | |||
332 | /* if there is a 90 degree rotation */ | ||
333 | if (is_rotate) { | ||
334 | /* swap the width and height of dst ROI */ | ||
335 | temp_dim = dst_ROI_width; | ||
336 | dst_ROI_width = dst_ROI_height; | ||
337 | dst_ROI_height = temp_dim; | ||
338 | } | ||
339 | |||
340 | /* calculate phase step for the x direction */ | ||
341 | |||
342 | /* if destination is only 1 pixel wide, the value of phase_step_x | ||
343 | is unimportant. Assigning phase_step_x to src ROI width | ||
344 | as an arbitrary value. */ | ||
345 | if (dst_ROI_width == 1) | ||
346 | phase_step_x = (uint32) ((src_ROI_width) << SCALER_PHASE_BITS); | ||
347 | |||
348 | /* if using FIR scalar */ | ||
349 | else if (scale_unit_sel_x == 0) { | ||
350 | |||
351 | /* Calculate the quotient ( src_ROI_width - 1 ) / ( dst_ROI_width - 1) | ||
352 | with u3.29 precision. Quotient is rounded up to the larger | ||
353 | 29th decimal point. */ | ||
354 | numerator = (src_ROI_width - 1) << SCALER_PHASE_BITS; | ||
355 | denominator = (dst_ROI_width - 1); /* never equals to 0 because of the "( dst_ROI_width == 1 ) case" */ | ||
356 | phase_step_x = (uint32) mdp_do_div((numerator + denominator - 1), denominator); /* divide and round up to the larger 29th decimal point. */ | ||
357 | |||
358 | } | ||
359 | |||
360 | /* if M/N scalar */ | ||
361 | else if (scale_unit_sel_x == 1) { | ||
362 | /* Calculate the quotient ( src_ROI_width ) / ( dst_ROI_width) | ||
363 | with u3.29 precision. Quotient is rounded down to the | ||
364 | smaller 29th decimal point. */ | ||
365 | numerator = (src_ROI_width) << SCALER_PHASE_BITS; | ||
366 | denominator = (dst_ROI_width); | ||
367 | phase_step_x = (uint32) mdp_do_div(numerator, denominator); | ||
368 | } | ||
369 | /* calculate phase step for the y direction */ | ||
370 | |||
371 | /* if destination is only 1 pixel wide, the value of | ||
372 | phase_step_x is unimportant. Assigning phase_step_x | ||
373 | to src ROI width as an arbitrary value. */ | ||
374 | if (dst_ROI_height == 1) | ||
375 | phase_step_y = (uint32) ((src_ROI_height) << SCALER_PHASE_BITS); | ||
376 | |||
377 | /* if FIR scalar */ | ||
378 | else if (scale_unit_sel_y == 0) { | ||
379 | /* Calculate the quotient ( src_ROI_height - 1 ) / ( dst_ROI_height - 1) | ||
380 | with u3.29 precision. Quotient is rounded up to the larger | ||
381 | 29th decimal point. */ | ||
382 | numerator = (src_ROI_height - 1) << SCALER_PHASE_BITS; | ||
383 | denominator = (dst_ROI_height - 1); /* never equals to 0 because of the "( dst_ROI_height == 1 )" case */ | ||
384 | phase_step_y = (uint32) mdp_do_div((numerator + denominator - 1), denominator); /* Quotient is rounded up to the larger 29th decimal point. */ | ||
385 | |||
386 | } | ||
387 | |||
388 | /* if M/N scalar */ | ||
389 | else if (scale_unit_sel_y == 1) { | ||
390 | /* Calculate the quotient ( src_ROI_height ) / ( dst_ROI_height) | ||
391 | with u3.29 precision. Quotient is rounded down to the smaller | ||
392 | 29th decimal point. */ | ||
393 | numerator = (src_ROI_height) << SCALER_PHASE_BITS; | ||
394 | denominator = (dst_ROI_height); | ||
395 | phase_step_y = (uint32) mdp_do_div(numerator, denominator); | ||
396 | } | ||
397 | |||
398 | /* decide which set of FIR coefficients to use */ | ||
399 | if (phase_step_x > HAL_MDP_PHASE_STEP_2P50) | ||
400 | xscale_filter_sel = 0; | ||
401 | else if (phase_step_x > HAL_MDP_PHASE_STEP_1P66) | ||
402 | xscale_filter_sel = 1; | ||
403 | else if (phase_step_x > HAL_MDP_PHASE_STEP_1P25) | ||
404 | xscale_filter_sel = 2; | ||
405 | else | ||
406 | xscale_filter_sel = 3; | ||
407 | |||
408 | if (phase_step_y > HAL_MDP_PHASE_STEP_2P50) | ||
409 | yscale_filter_sel = 0; | ||
410 | else if (phase_step_y > HAL_MDP_PHASE_STEP_1P66) | ||
411 | yscale_filter_sel = 1; | ||
412 | else if (phase_step_y > HAL_MDP_PHASE_STEP_1P25) | ||
413 | yscale_filter_sel = 2; | ||
414 | else | ||
415 | yscale_filter_sel = 3; | ||
416 | |||
417 | /* calculate phase init for the x direction */ | ||
418 | |||
419 | /* if using FIR scalar */ | ||
420 | if (scale_unit_sel_x == 0) { | ||
421 | if (dst_ROI_width == 1) | ||
422 | phase_init_x = | ||
423 | (uint32) ((src_ROI_width - 1) << SCALER_PHASE_BITS); | ||
424 | else | ||
425 | phase_init_x = 0; | ||
426 | |||
427 | } | ||
428 | /* M over N scalar */ | ||
429 | else if (scale_unit_sel_x == 1) | ||
430 | phase_init_x = 0; | ||
431 | |||
432 | /* calculate phase init for the y direction | ||
433 | if using FIR scalar */ | ||
434 | if (scale_unit_sel_y == 0) { | ||
435 | if (dst_ROI_height == 1) | ||
436 | phase_init_y = | ||
437 | (uint32) ((src_ROI_height - | ||
438 | 1) << SCALER_PHASE_BITS); | ||
439 | else | ||
440 | phase_init_y = 0; | ||
441 | |||
442 | } | ||
443 | /* M over N scalar */ | ||
444 | else if (scale_unit_sel_y == 1) | ||
445 | phase_init_y = 0; | ||
446 | |||
447 | /* write registers */ | ||
448 | pval->phase_step_x = (uint32) phase_step_x; | ||
449 | pval->phase_step_y = (uint32) phase_step_y; | ||
450 | pval->phase_init_x = (uint32) phase_init_x; | ||
451 | pval->phase_init_y = (uint32) phase_init_y; | ||
452 | |||
453 | return; | ||
454 | } | ||
455 | |||
456 | void mdp_set_scale(MDPIBUF *iBuf, | ||
457 | uint32 dst_roi_width, | ||
458 | uint32 dst_roi_height, | ||
459 | boolean inputRGB, boolean outputRGB, uint32 *pppop_reg_ptr) | ||
460 | { | ||
461 | uint32 dst_roi_width_scale; | ||
462 | uint32 dst_roi_height_scale; | ||
463 | struct phase_val pval; | ||
464 | boolean use_pr; | ||
465 | uint32 ppp_scale_config = 0; | ||
466 | |||
467 | if (!inputRGB) | ||
468 | ppp_scale_config |= BIT(6); | ||
469 | |||
470 | if (iBuf->mdpImg.mdpOp & MDPOP_ASCALE) { | ||
471 | if (iBuf->mdpImg.mdpOp & MDPOP_ROT90) { | ||
472 | dst_roi_width_scale = dst_roi_height; | ||
473 | dst_roi_height_scale = dst_roi_width; | ||
474 | } else { | ||
475 | dst_roi_width_scale = dst_roi_width; | ||
476 | dst_roi_height_scale = dst_roi_height; | ||
477 | } | ||
478 | |||
479 | if ((dst_roi_width_scale != iBuf->roi.width) || | ||
480 | (dst_roi_height_scale != iBuf->roi.height) || | ||
481 | (iBuf->mdpImg.mdpOp & MDPOP_SHARPENING)) { | ||
482 | *pppop_reg_ptr |= | ||
483 | (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON); | ||
484 | |||
485 | mdp_calc_scaleInitPhase_3p1(iBuf->roi.width, | ||
486 | iBuf->roi.height, | ||
487 | dst_roi_width, | ||
488 | dst_roi_height, | ||
489 | iBuf->mdpImg. | ||
490 | mdpOp & MDPOP_ROT90, 1, 1, | ||
491 | &pval); | ||
492 | |||
493 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x013c, | ||
494 | pval.phase_init_x); | ||
495 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0140, | ||
496 | pval.phase_init_y); | ||
497 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0144, | ||
498 | pval.phase_step_x); | ||
499 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0148, | ||
500 | pval.phase_step_y); | ||
501 | |||
502 | use_pr = (inputRGB) && (outputRGB); | ||
503 | |||
504 | /* x-direction */ | ||
505 | if ((dst_roi_width_scale == iBuf->roi.width) && | ||
506 | !(iBuf->mdpImg.mdpOp & MDPOP_SHARPENING)) { | ||
507 | *pppop_reg_ptr &= ~PPP_OP_SCALE_X_ON; | ||
508 | } else | ||
509 | if (((dst_roi_width_scale * 10) / iBuf->roi.width) > | ||
510 | 8) { | ||
511 | if ((use_pr) | ||
512 | && (mdp_scale_0p8_to_8p0_mode != | ||
513 | MDP_SCALE_PR)) { | ||
514 | mdp_scale_0p8_to_8p0_mode = | ||
515 | MDP_SCALE_PR; | ||
516 | mdp_update_scale_table | ||
517 | (MDP_SCALE_0P8_TO_8P0_INDEX, | ||
518 | mdp_scale_pixel_repeat_C0, | ||
519 | mdp_scale_pixel_repeat_C1, | ||
520 | mdp_scale_pixel_repeat_C2, | ||
521 | mdp_scale_pixel_repeat_C3); | ||
522 | } else if ((!use_pr) | ||
523 | && (mdp_scale_0p8_to_8p0_mode != | ||
524 | MDP_SCALE_FIR)) { | ||
525 | mdp_scale_0p8_to_8p0_mode = | ||
526 | MDP_SCALE_FIR; | ||
527 | mdp_update_scale_table | ||
528 | (MDP_SCALE_0P8_TO_8P0_INDEX, | ||
529 | mdp_scale_0p8_to_8p0_C0, | ||
530 | mdp_scale_0p8_to_8p0_C1, | ||
531 | mdp_scale_0p8_to_8p0_C2, | ||
532 | mdp_scale_0p8_to_8p0_C3); | ||
533 | } | ||
534 | ppp_scale_config |= (SCALE_U1_SET << 2); | ||
535 | } else | ||
536 | if (((dst_roi_width_scale * 10) / iBuf->roi.width) > | ||
537 | 6) { | ||
538 | if ((use_pr) | ||
539 | && (mdp_scale_0p6_to_0p8_mode != | ||
540 | MDP_SCALE_PR)) { | ||
541 | mdp_scale_0p6_to_0p8_mode = | ||
542 | MDP_SCALE_PR; | ||
543 | mdp_update_scale_table | ||
544 | (MDP_SCALE_0P6_TO_0P8_INDEX, | ||
545 | mdp_scale_pixel_repeat_C0, | ||
546 | mdp_scale_pixel_repeat_C1, | ||
547 | mdp_scale_pixel_repeat_C2, | ||
548 | mdp_scale_pixel_repeat_C3); | ||
549 | } else if ((!use_pr) | ||
550 | && (mdp_scale_0p6_to_0p8_mode != | ||
551 | MDP_SCALE_FIR)) { | ||
552 | mdp_scale_0p6_to_0p8_mode = | ||
553 | MDP_SCALE_FIR; | ||
554 | mdp_update_scale_table | ||
555 | (MDP_SCALE_0P6_TO_0P8_INDEX, | ||
556 | mdp_scale_0p6_to_0p8_C0, | ||
557 | mdp_scale_0p6_to_0p8_C1, | ||
558 | mdp_scale_0p6_to_0p8_C2, | ||
559 | mdp_scale_0p6_to_0p8_C3); | ||
560 | } | ||
561 | ppp_scale_config |= (SCALE_D2_SET << 2); | ||
562 | } else | ||
563 | if (((dst_roi_width_scale * 10) / iBuf->roi.width) > | ||
564 | 4) { | ||
565 | if ((use_pr) | ||
566 | && (mdp_scale_0p4_to_0p6_mode != | ||
567 | MDP_SCALE_PR)) { | ||
568 | mdp_scale_0p4_to_0p6_mode = | ||
569 | MDP_SCALE_PR; | ||
570 | mdp_update_scale_table | ||
571 | (MDP_SCALE_0P4_TO_0P6_INDEX, | ||
572 | mdp_scale_pixel_repeat_C0, | ||
573 | mdp_scale_pixel_repeat_C1, | ||
574 | mdp_scale_pixel_repeat_C2, | ||
575 | mdp_scale_pixel_repeat_C3); | ||
576 | } else if ((!use_pr) | ||
577 | && (mdp_scale_0p4_to_0p6_mode != | ||
578 | MDP_SCALE_FIR)) { | ||
579 | mdp_scale_0p4_to_0p6_mode = | ||
580 | MDP_SCALE_FIR; | ||
581 | mdp_update_scale_table | ||
582 | (MDP_SCALE_0P4_TO_0P6_INDEX, | ||
583 | mdp_scale_0p4_to_0p6_C0, | ||
584 | mdp_scale_0p4_to_0p6_C1, | ||
585 | mdp_scale_0p4_to_0p6_C2, | ||
586 | mdp_scale_0p4_to_0p6_C3); | ||
587 | } | ||
588 | ppp_scale_config |= (SCALE_D1_SET << 2); | ||
589 | } else | ||
590 | if (((dst_roi_width_scale * 4) / iBuf->roi.width) >= | ||
591 | 1) { | ||
592 | if ((use_pr) | ||
593 | && (mdp_scale_0p2_to_0p4_mode != | ||
594 | MDP_SCALE_PR)) { | ||
595 | mdp_scale_0p2_to_0p4_mode = | ||
596 | MDP_SCALE_PR; | ||
597 | mdp_update_scale_table | ||
598 | (MDP_SCALE_0P2_TO_0P4_INDEX, | ||
599 | mdp_scale_pixel_repeat_C0, | ||
600 | mdp_scale_pixel_repeat_C1, | ||
601 | mdp_scale_pixel_repeat_C2, | ||
602 | mdp_scale_pixel_repeat_C3); | ||
603 | } else if ((!use_pr) | ||
604 | && (mdp_scale_0p2_to_0p4_mode != | ||
605 | MDP_SCALE_FIR)) { | ||
606 | mdp_scale_0p2_to_0p4_mode = | ||
607 | MDP_SCALE_FIR; | ||
608 | mdp_update_scale_table | ||
609 | (MDP_SCALE_0P2_TO_0P4_INDEX, | ||
610 | mdp_scale_0p2_to_0p4_C0, | ||
611 | mdp_scale_0p2_to_0p4_C1, | ||
612 | mdp_scale_0p2_to_0p4_C2, | ||
613 | mdp_scale_0p2_to_0p4_C3); | ||
614 | } | ||
615 | ppp_scale_config |= (SCALE_D0_SET << 2); | ||
616 | } else | ||
617 | ppp_scale_config |= BIT(0); | ||
618 | |||
619 | /* y-direction */ | ||
620 | if ((dst_roi_height_scale == iBuf->roi.height) && | ||
621 | !(iBuf->mdpImg.mdpOp & MDPOP_SHARPENING)) { | ||
622 | *pppop_reg_ptr &= ~PPP_OP_SCALE_Y_ON; | ||
623 | } else if (((dst_roi_height_scale * 10) / | ||
624 | iBuf->roi.height) > 8) { | ||
625 | if ((use_pr) | ||
626 | && (mdp_scale_0p8_to_8p0_mode != | ||
627 | MDP_SCALE_PR)) { | ||
628 | mdp_scale_0p8_to_8p0_mode = | ||
629 | MDP_SCALE_PR; | ||
630 | mdp_update_scale_table | ||
631 | (MDP_SCALE_0P8_TO_8P0_INDEX, | ||
632 | mdp_scale_pixel_repeat_C0, | ||
633 | mdp_scale_pixel_repeat_C1, | ||
634 | mdp_scale_pixel_repeat_C2, | ||
635 | mdp_scale_pixel_repeat_C3); | ||
636 | } else if ((!use_pr) | ||
637 | && (mdp_scale_0p8_to_8p0_mode != | ||
638 | MDP_SCALE_FIR)) { | ||
639 | mdp_scale_0p8_to_8p0_mode = | ||
640 | MDP_SCALE_FIR; | ||
641 | mdp_update_scale_table | ||
642 | (MDP_SCALE_0P8_TO_8P0_INDEX, | ||
643 | mdp_scale_0p8_to_8p0_C0, | ||
644 | mdp_scale_0p8_to_8p0_C1, | ||
645 | mdp_scale_0p8_to_8p0_C2, | ||
646 | mdp_scale_0p8_to_8p0_C3); | ||
647 | } | ||
648 | ppp_scale_config |= (SCALE_U1_SET << 4); | ||
649 | } else | ||
650 | if (((dst_roi_height_scale * 10) / | ||
651 | iBuf->roi.height) > 6) { | ||
652 | if ((use_pr) | ||
653 | && (mdp_scale_0p6_to_0p8_mode != | ||
654 | MDP_SCALE_PR)) { | ||
655 | mdp_scale_0p6_to_0p8_mode = | ||
656 | MDP_SCALE_PR; | ||
657 | mdp_update_scale_table | ||
658 | (MDP_SCALE_0P6_TO_0P8_INDEX, | ||
659 | mdp_scale_pixel_repeat_C0, | ||
660 | mdp_scale_pixel_repeat_C1, | ||
661 | mdp_scale_pixel_repeat_C2, | ||
662 | mdp_scale_pixel_repeat_C3); | ||
663 | } else if ((!use_pr) | ||
664 | && (mdp_scale_0p6_to_0p8_mode != | ||
665 | MDP_SCALE_FIR)) { | ||
666 | mdp_scale_0p6_to_0p8_mode = | ||
667 | MDP_SCALE_FIR; | ||
668 | mdp_update_scale_table | ||
669 | (MDP_SCALE_0P6_TO_0P8_INDEX, | ||
670 | mdp_scale_0p6_to_0p8_C0, | ||
671 | mdp_scale_0p6_to_0p8_C1, | ||
672 | mdp_scale_0p6_to_0p8_C2, | ||
673 | mdp_scale_0p6_to_0p8_C3); | ||
674 | } | ||
675 | ppp_scale_config |= (SCALE_D2_SET << 4); | ||
676 | } else | ||
677 | if (((dst_roi_height_scale * 10) / | ||
678 | iBuf->roi.height) > 4) { | ||
679 | if ((use_pr) | ||
680 | && (mdp_scale_0p4_to_0p6_mode != | ||
681 | MDP_SCALE_PR)) { | ||
682 | mdp_scale_0p4_to_0p6_mode = | ||
683 | MDP_SCALE_PR; | ||
684 | mdp_update_scale_table | ||
685 | (MDP_SCALE_0P4_TO_0P6_INDEX, | ||
686 | mdp_scale_pixel_repeat_C0, | ||
687 | mdp_scale_pixel_repeat_C1, | ||
688 | mdp_scale_pixel_repeat_C2, | ||
689 | mdp_scale_pixel_repeat_C3); | ||
690 | } else if ((!use_pr) | ||
691 | && (mdp_scale_0p4_to_0p6_mode != | ||
692 | MDP_SCALE_FIR)) { | ||
693 | mdp_scale_0p4_to_0p6_mode = | ||
694 | MDP_SCALE_FIR; | ||
695 | mdp_update_scale_table | ||
696 | (MDP_SCALE_0P4_TO_0P6_INDEX, | ||
697 | mdp_scale_0p4_to_0p6_C0, | ||
698 | mdp_scale_0p4_to_0p6_C1, | ||
699 | mdp_scale_0p4_to_0p6_C2, | ||
700 | mdp_scale_0p4_to_0p6_C3); | ||
701 | } | ||
702 | ppp_scale_config |= (SCALE_D1_SET << 4); | ||
703 | } else | ||
704 | if (((dst_roi_height_scale * 4) / | ||
705 | iBuf->roi.height) >= 1) { | ||
706 | if ((use_pr) | ||
707 | && (mdp_scale_0p2_to_0p4_mode != | ||
708 | MDP_SCALE_PR)) { | ||
709 | mdp_scale_0p2_to_0p4_mode = | ||
710 | MDP_SCALE_PR; | ||
711 | mdp_update_scale_table | ||
712 | (MDP_SCALE_0P2_TO_0P4_INDEX, | ||
713 | mdp_scale_pixel_repeat_C0, | ||
714 | mdp_scale_pixel_repeat_C1, | ||
715 | mdp_scale_pixel_repeat_C2, | ||
716 | mdp_scale_pixel_repeat_C3); | ||
717 | } else if ((!use_pr) | ||
718 | && (mdp_scale_0p2_to_0p4_mode != | ||
719 | MDP_SCALE_FIR)) { | ||
720 | mdp_scale_0p2_to_0p4_mode = | ||
721 | MDP_SCALE_FIR; | ||
722 | mdp_update_scale_table | ||
723 | (MDP_SCALE_0P2_TO_0P4_INDEX, | ||
724 | mdp_scale_0p2_to_0p4_C0, | ||
725 | mdp_scale_0p2_to_0p4_C1, | ||
726 | mdp_scale_0p2_to_0p4_C2, | ||
727 | mdp_scale_0p2_to_0p4_C3); | ||
728 | } | ||
729 | ppp_scale_config |= (SCALE_D0_SET << 4); | ||
730 | } else | ||
731 | ppp_scale_config |= BIT(1); | ||
732 | |||
733 | if (iBuf->mdpImg.mdpOp & MDPOP_SHARPENING) { | ||
734 | ppp_scale_config |= BIT(7); | ||
735 | MDP_OUTP(MDP_BASE + 0x50020, | ||
736 | iBuf->mdpImg.sp_value); | ||
737 | } | ||
738 | |||
739 | MDP_OUTP(MDP_BASE + 0x10230, ppp_scale_config); | ||
740 | } else { | ||
741 | iBuf->mdpImg.mdpOp &= ~(MDPOP_ASCALE); | ||
742 | } | ||
743 | } | ||
744 | } | ||
745 | |||
746 | void mdp_adjust_start_addr(uint8 **src0, | ||
747 | uint8 **src1, | ||
748 | int v_slice, | ||
749 | int h_slice, | ||
750 | int x, | ||
751 | int y, | ||
752 | uint32 width, | ||
753 | uint32 height, int bpp, MDPIBUF *iBuf, int layer) | ||
754 | { | ||
755 | switch (layer) { | ||
756 | case 0: | ||
757 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0200, (y << 16) | (x)); | ||
758 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0208, | ||
759 | (height << 16) | (width)); | ||
760 | break; | ||
761 | |||
762 | case 1: | ||
763 | /* MDP 3.1 HW bug workaround */ | ||
764 | if (iBuf->ibuf_type == MDP_YCRYCB_H2V1) { | ||
765 | *src0 += (x + y * width) * bpp; | ||
766 | x = y = 0; | ||
767 | width = iBuf->roi.dst_width; | ||
768 | height = iBuf->roi.dst_height; | ||
769 | } | ||
770 | |||
771 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0204, (y << 16) | (x)); | ||
772 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x020c, | ||
773 | (height << 16) | (width)); | ||
774 | break; | ||
775 | |||
776 | case 2: | ||
777 | MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x019c, (y << 16) | (x)); | ||
778 | break; | ||
779 | } | ||
780 | } | ||
781 | |||
782 | void mdp_set_blend_attr(MDPIBUF *iBuf, | ||
783 | uint32 *alpha, | ||
784 | uint32 *tpVal, | ||
785 | uint32 perPixelAlpha, uint32 *pppop_reg_ptr) | ||
786 | { | ||
787 | int bg_alpha; | ||
788 | |||
789 | *alpha = iBuf->mdpImg.alpha; | ||
790 | *tpVal = iBuf->mdpImg.tpVal; | ||
791 | |||
792 | if (iBuf->mdpImg.mdpOp & MDPOP_FG_PM_ALPHA) { | ||
793 | *pppop_reg_ptr |= PPP_OP_ROT_ON | | ||
794 | PPP_OP_BLEND_ON | PPP_OP_BLEND_CONSTANT_ALPHA; | ||
795 | |||
796 | bg_alpha = PPP_BLEND_BG_USE_ALPHA_SEL | | ||
797 | PPP_BLEND_BG_ALPHA_REVERSE; | ||
798 | |||
799 | if (perPixelAlpha) | ||
800 | bg_alpha |= PPP_BLEND_BG_SRCPIXEL_ALPHA; | ||
801 | else | ||
802 | bg_alpha |= PPP_BLEND_BG_CONSTANT_ALPHA; | ||
803 | |||
804 | outpdw(MDP_BASE + 0x70010, bg_alpha); | ||
805 | |||
806 | if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP) | ||
807 | *pppop_reg_ptr |= PPP_BLEND_CALPHA_TRNASP; | ||
808 | } else if (perPixelAlpha) { | ||
809 | *pppop_reg_ptr |= PPP_OP_ROT_ON | | ||
810 | PPP_OP_BLEND_ON | PPP_OP_BLEND_SRCPIXEL_ALPHA; | ||
811 | } else { | ||
812 | if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB) | ||
813 | && (iBuf->mdpImg.alpha == 0xff)) { | ||
814 | iBuf->mdpImg.mdpOp &= ~(MDPOP_ALPHAB); | ||
815 | } | ||
816 | |||
817 | if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB) | ||
818 | || (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)) { | ||
819 | *pppop_reg_ptr |= | ||
820 | PPP_OP_ROT_ON | PPP_OP_BLEND_ON | | ||
821 | PPP_OP_BLEND_CONSTANT_ALPHA | | ||
822 | PPP_OP_BLEND_ALPHA_BLEND_NORMAL; | ||
823 | } | ||
824 | |||
825 | if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP) | ||
826 | *pppop_reg_ptr |= PPP_BLEND_CALPHA_TRNASP; | ||
827 | } | ||
828 | } | ||
diff --git a/drivers/staging/msm/mdp_vsync.c b/drivers/staging/msm/mdp_vsync.c new file mode 100644 index 000000000000..bbd456044356 --- /dev/null +++ b/drivers/staging/msm/mdp_vsync.c | |||
@@ -0,0 +1,389 @@ | |||
1 | /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/sched.h> | ||
21 | #include <linux/time.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/spinlock.h> | ||
25 | #include <linux/hrtimer.h> | ||
26 | #include <linux/vmalloc.h> | ||
27 | #include <linux/clk.h> | ||
28 | |||
29 | #include <mach/hardware.h> | ||
30 | #include <linux/io.h> | ||
31 | |||
32 | #include <asm/system.h> | ||
33 | #include <asm/mach-types.h> | ||
34 | #include <linux/semaphore.h> | ||
35 | #include <linux/uaccess.h> | ||
36 | #include <mach/gpio.h> | ||
37 | |||
38 | #include "mdp.h" | ||
39 | #include "msm_fb.h" | ||
40 | #include "mddihost.h" | ||
41 | |||
42 | #ifdef CONFIG_FB_MSM_MDP40 | ||
43 | #define MDP_SYNC_CFG_0 0x100 | ||
44 | #define MDP_SYNC_STATUS_0 0x10c | ||
45 | #define MDP_PRIM_VSYNC_OUT_CTRL 0x118 | ||
46 | #define MDP_PRIM_VSYNC_INIT_VAL 0x128 | ||
47 | #else | ||
48 | #define MDP_SYNC_CFG_0 0x300 | ||
49 | #define MDP_SYNC_STATUS_0 0x30c | ||
50 | #define MDP_PRIM_VSYNC_OUT_CTRL 0x318 | ||
51 | #define MDP_PRIM_VSYNC_INIT_VAL 0x328 | ||
52 | #endif | ||
53 | |||
54 | extern mddi_lcd_type mddi_lcd_idx; | ||
55 | extern spinlock_t mdp_spin_lock; | ||
56 | extern struct workqueue_struct *mdp_vsync_wq; | ||
57 | extern int lcdc_mode; | ||
58 | extern int vsync_mode; | ||
59 | |||
60 | #ifdef MDP_HW_VSYNC | ||
61 | int vsync_above_th = 4; | ||
62 | int vsync_start_th = 1; | ||
63 | int vsync_load_cnt; | ||
64 | |||
65 | struct clk *mdp_vsync_clk; | ||
66 | |||
67 | void mdp_hw_vsync_clk_enable(struct msm_fb_data_type *mfd) | ||
68 | { | ||
69 | if (mfd->use_mdp_vsync) | ||
70 | clk_enable(mdp_vsync_clk); | ||
71 | } | ||
72 | |||
73 | void mdp_hw_vsync_clk_disable(struct msm_fb_data_type *mfd) | ||
74 | { | ||
75 | if (mfd->use_mdp_vsync) | ||
76 | clk_disable(mdp_vsync_clk); | ||
77 | } | ||
78 | #endif | ||
79 | |||
80 | static void mdp_set_vsync(unsigned long data) | ||
81 | { | ||
82 | struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)data; | ||
83 | struct msm_fb_panel_data *pdata = NULL; | ||
84 | |||
85 | pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data; | ||
86 | |||
87 | if ((pdata) && (pdata->set_vsync_notifier == NULL)) | ||
88 | return; | ||
89 | |||
90 | init_timer(&mfd->vsync_resync_timer); | ||
91 | mfd->vsync_resync_timer.function = mdp_set_vsync; | ||
92 | mfd->vsync_resync_timer.data = data; | ||
93 | mfd->vsync_resync_timer.expires = | ||
94 | jiffies + mfd->panel_info.lcd.vsync_notifier_period; | ||
95 | add_timer(&mfd->vsync_resync_timer); | ||
96 | |||
97 | if ((mfd->panel_info.lcd.vsync_enable) && (mfd->panel_power_on) | ||
98 | && (!mfd->vsync_handler_pending)) { | ||
99 | mfd->vsync_handler_pending = TRUE; | ||
100 | if (!queue_work(mdp_vsync_wq, &mfd->vsync_resync_worker)) { | ||
101 | MSM_FB_INFO | ||
102 | ("mdp_set_vsync: can't queue_work! -> needs to increase vsync_resync_timer_duration\n"); | ||
103 | } | ||
104 | } else { | ||
105 | MSM_FB_DEBUG | ||
106 | ("mdp_set_vsync failed! EN:%d PWR:%d PENDING:%d\n", | ||
107 | mfd->panel_info.lcd.vsync_enable, mfd->panel_power_on, | ||
108 | mfd->vsync_handler_pending); | ||
109 | } | ||
110 | } | ||
111 | |||
112 | static void mdp_vsync_handler(void *data) | ||
113 | { | ||
114 | struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)data; | ||
115 | |||
116 | if (mfd->use_mdp_vsync) { | ||
117 | #ifdef MDP_HW_VSYNC | ||
118 | if (mfd->panel_power_on) | ||
119 | MDP_OUTP(MDP_BASE + MDP_SYNC_STATUS_0, vsync_load_cnt); | ||
120 | |||
121 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, TRUE); | ||
122 | #endif | ||
123 | } else { | ||
124 | mfd->last_vsync_timetick = ktime_get_real(); | ||
125 | } | ||
126 | |||
127 | mfd->vsync_handler_pending = FALSE; | ||
128 | } | ||
129 | |||
130 | irqreturn_t mdp_hw_vsync_handler_proxy(int irq, void *data) | ||
131 | { | ||
132 | /* | ||
133 | * ToDo: tried enabling/disabling GPIO MDP HW VSYNC interrupt | ||
134 | * but getting inaccurate timing in mdp_vsync_handler() | ||
135 | * disable_irq(MDP_HW_VSYNC_IRQ); | ||
136 | */ | ||
137 | mdp_vsync_handler(data); | ||
138 | |||
139 | return IRQ_HANDLED; | ||
140 | } | ||
141 | |||
142 | #ifdef MDP_HW_VSYNC | ||
143 | static void mdp_set_sync_cfg_0(struct msm_fb_data_type *mfd, int vsync_cnt) | ||
144 | { | ||
145 | unsigned long cfg; | ||
146 | |||
147 | cfg = mfd->total_lcd_lines - 1; | ||
148 | cfg <<= MDP_SYNCFG_HGT_LOC; | ||
149 | if (mfd->panel_info.lcd.hw_vsync_mode) | ||
150 | cfg |= MDP_SYNCFG_VSYNC_EXT_EN; | ||
151 | cfg |= (MDP_SYNCFG_VSYNC_INT_EN | vsync_cnt); | ||
152 | |||
153 | MDP_OUTP(MDP_BASE + MDP_SYNC_CFG_0, cfg); | ||
154 | } | ||
155 | #endif | ||
156 | |||
157 | void mdp_config_vsync(struct msm_fb_data_type *mfd) | ||
158 | { | ||
159 | |||
160 | /* vsync on primary lcd only for now */ | ||
161 | if ((mfd->dest != DISPLAY_LCD) || (mfd->panel_info.pdest != DISPLAY_1) | ||
162 | || (!vsync_mode)) { | ||
163 | goto err_handle; | ||
164 | } | ||
165 | |||
166 | if (mfd->panel_info.lcd.vsync_enable) { | ||
167 | mfd->total_porch_lines = mfd->panel_info.lcd.v_back_porch + | ||
168 | mfd->panel_info.lcd.v_front_porch + | ||
169 | mfd->panel_info.lcd.v_pulse_width; | ||
170 | mfd->total_lcd_lines = | ||
171 | mfd->panel_info.yres + mfd->total_porch_lines; | ||
172 | mfd->lcd_ref_usec_time = | ||
173 | 100000000 / mfd->panel_info.lcd.refx100; | ||
174 | mfd->vsync_handler_pending = FALSE; | ||
175 | mfd->last_vsync_timetick.tv.sec = 0; | ||
176 | mfd->last_vsync_timetick.tv.nsec = 0; | ||
177 | |||
178 | #ifdef MDP_HW_VSYNC | ||
179 | if (mdp_vsync_clk == NULL) | ||
180 | mdp_vsync_clk = clk_get(NULL, "mdp_vsync_clk"); | ||
181 | |||
182 | if (IS_ERR(mdp_vsync_clk)) { | ||
183 | printk(KERN_ERR "error: can't get mdp_vsync_clk!\n"); | ||
184 | mfd->use_mdp_vsync = 0; | ||
185 | } else | ||
186 | mfd->use_mdp_vsync = 1; | ||
187 | |||
188 | if (mfd->use_mdp_vsync) { | ||
189 | uint32 vsync_cnt_cfg, vsync_cnt_cfg_dem; | ||
190 | uint32 mdp_vsync_clk_speed_hz; | ||
191 | |||
192 | mdp_vsync_clk_speed_hz = clk_get_rate(mdp_vsync_clk); | ||
193 | |||
194 | if (mdp_vsync_clk_speed_hz == 0) { | ||
195 | mfd->use_mdp_vsync = 0; | ||
196 | } else { | ||
197 | /* | ||
198 | * Do this calculation in 2 steps for | ||
199 | * rounding uint32 properly. | ||
200 | */ | ||
201 | vsync_cnt_cfg_dem = | ||
202 | (mfd->panel_info.lcd.refx100 * | ||
203 | mfd->total_lcd_lines) / 100; | ||
204 | vsync_cnt_cfg = | ||
205 | (mdp_vsync_clk_speed_hz) / | ||
206 | vsync_cnt_cfg_dem; | ||
207 | |||
208 | /* MDP cmd block enable */ | ||
209 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, | ||
210 | FALSE); | ||
211 | mdp_hw_vsync_clk_enable(mfd); | ||
212 | |||
213 | mdp_set_sync_cfg_0(mfd, vsync_cnt_cfg); | ||
214 | |||
215 | /* | ||
216 | * load the last line + 1 to be in the | ||
217 | * safety zone | ||
218 | */ | ||
219 | vsync_load_cnt = mfd->panel_info.yres; | ||
220 | |||
221 | /* line counter init value at the next pulse */ | ||
222 | MDP_OUTP(MDP_BASE + MDP_PRIM_VSYNC_INIT_VAL, | ||
223 | vsync_load_cnt); | ||
224 | |||
225 | /* | ||
226 | * external vsync source pulse width and | ||
227 | * polarity flip | ||
228 | */ | ||
229 | MDP_OUTP(MDP_BASE + MDP_PRIM_VSYNC_OUT_CTRL, | ||
230 | BIT(30) | BIT(0)); | ||
231 | |||
232 | |||
233 | /* threshold */ | ||
234 | MDP_OUTP(MDP_BASE + 0x200, | ||
235 | (vsync_above_th << 16) | | ||
236 | (vsync_start_th)); | ||
237 | |||
238 | mdp_hw_vsync_clk_disable(mfd); | ||
239 | /* MDP cmd block disable */ | ||
240 | mdp_pipe_ctrl(MDP_CMD_BLOCK, | ||
241 | MDP_BLOCK_POWER_OFF, FALSE); | ||
242 | } | ||
243 | } | ||
244 | #else | ||
245 | mfd->use_mdp_vsync = 0; | ||
246 | hrtimer_init(&mfd->dma_hrtimer, CLOCK_MONOTONIC, | ||
247 | HRTIMER_MODE_REL); | ||
248 | mfd->dma_hrtimer.function = mdp_dma2_vsync_hrtimer_handler; | ||
249 | mfd->vsync_width_boundary = vmalloc(mfd->panel_info.xres * 4); | ||
250 | #endif | ||
251 | |||
252 | mfd->channel_irq = 0; | ||
253 | if (mfd->panel_info.lcd.hw_vsync_mode) { | ||
254 | u32 vsync_gpio = mfd->vsync_gpio; | ||
255 | u32 ret; | ||
256 | |||
257 | if (vsync_gpio == -1) { | ||
258 | MSM_FB_INFO("vsync_gpio not defined!\n"); | ||
259 | goto err_handle; | ||
260 | } | ||
261 | |||
262 | ret = gpio_tlmm_config(GPIO_CFG | ||
263 | (vsync_gpio, | ||
264 | (mfd->use_mdp_vsync) ? 1 : 0, | ||
265 | GPIO_INPUT, | ||
266 | GPIO_PULL_DOWN, | ||
267 | GPIO_2MA), | ||
268 | GPIO_ENABLE); | ||
269 | if (ret) | ||
270 | goto err_handle; | ||
271 | |||
272 | if (!mfd->use_mdp_vsync) { | ||
273 | mfd->channel_irq = MSM_GPIO_TO_INT(vsync_gpio); | ||
274 | if (request_irq | ||
275 | (mfd->channel_irq, | ||
276 | &mdp_hw_vsync_handler_proxy, | ||
277 | IRQF_TRIGGER_FALLING, "VSYNC_GPIO", | ||
278 | (void *)mfd)) { | ||
279 | MSM_FB_INFO | ||
280 | ("irq=%d failed! vsync_gpio=%d\n", | ||
281 | mfd->channel_irq, | ||
282 | vsync_gpio); | ||
283 | goto err_handle; | ||
284 | } | ||
285 | } | ||
286 | } | ||
287 | |||
288 | mdp_set_vsync((unsigned long)mfd); | ||
289 | } | ||
290 | |||
291 | return; | ||
292 | |||
293 | err_handle: | ||
294 | if (mfd->vsync_width_boundary) | ||
295 | vfree(mfd->vsync_width_boundary); | ||
296 | mfd->panel_info.lcd.vsync_enable = FALSE; | ||
297 | printk(KERN_ERR "%s: failed!\n", __func__); | ||
298 | } | ||
299 | |||
300 | void mdp_vsync_resync_workqueue_handler(struct work_struct *work) | ||
301 | { | ||
302 | struct msm_fb_data_type *mfd = NULL; | ||
303 | int vsync_fnc_enabled = FALSE; | ||
304 | struct msm_fb_panel_data *pdata = NULL; | ||
305 | |||
306 | mfd = container_of(work, struct msm_fb_data_type, vsync_resync_worker); | ||
307 | |||
308 | if (mfd) { | ||
309 | if (mfd->panel_power_on) { | ||
310 | pdata = | ||
311 | (struct msm_fb_panel_data *)mfd->pdev->dev. | ||
312 | platform_data; | ||
313 | |||
314 | /* | ||
315 | * we need to turn on MDP power if it uses MDP vsync | ||
316 | * HW block in SW mode | ||
317 | */ | ||
318 | if ((!mfd->panel_info.lcd.hw_vsync_mode) && | ||
319 | (mfd->use_mdp_vsync) && | ||
320 | (pdata) && (pdata->set_vsync_notifier != NULL)) { | ||
321 | /* | ||
322 | * enable pwr here since we can't enable it in | ||
323 | * vsync callback in isr mode | ||
324 | */ | ||
325 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, | ||
326 | FALSE); | ||
327 | } | ||
328 | |||
329 | if (pdata->set_vsync_notifier != NULL) { | ||
330 | vsync_fnc_enabled = TRUE; | ||
331 | pdata->set_vsync_notifier(mdp_vsync_handler, | ||
332 | (void *)mfd); | ||
333 | } | ||
334 | } | ||
335 | } | ||
336 | |||
337 | if ((mfd) && (!vsync_fnc_enabled)) | ||
338 | mfd->vsync_handler_pending = FALSE; | ||
339 | } | ||
340 | |||
341 | boolean mdp_hw_vsync_set_handler(msm_fb_vsync_handler_type handler, void *data) | ||
342 | { | ||
343 | /* | ||
344 | * ToDo: tried enabling/disabling GPIO MDP HW VSYNC interrupt | ||
345 | * but getting inaccurate timing in mdp_vsync_handler() | ||
346 | * enable_irq(MDP_HW_VSYNC_IRQ); | ||
347 | */ | ||
348 | |||
349 | return TRUE; | ||
350 | } | ||
351 | |||
352 | uint32 mdp_get_lcd_line_counter(struct msm_fb_data_type *mfd) | ||
353 | { | ||
354 | uint32 elapsed_usec_time; | ||
355 | uint32 lcd_line; | ||
356 | ktime_t last_vsync_timetick_local; | ||
357 | ktime_t curr_time; | ||
358 | unsigned long flag; | ||
359 | |||
360 | if ((!mfd->panel_info.lcd.vsync_enable) || (!vsync_mode)) | ||
361 | return 0; | ||
362 | |||
363 | spin_lock_irqsave(&mdp_spin_lock, flag); | ||
364 | last_vsync_timetick_local = mfd->last_vsync_timetick; | ||
365 | spin_unlock_irqrestore(&mdp_spin_lock, flag); | ||
366 | |||
367 | curr_time = ktime_get_real(); | ||
368 | elapsed_usec_time = | ||
369 | ((curr_time.tv.sec - last_vsync_timetick_local.tv.sec) * 1000000) + | ||
370 | ((curr_time.tv.nsec - last_vsync_timetick_local.tv.nsec) / 1000); | ||
371 | |||
372 | elapsed_usec_time = elapsed_usec_time % mfd->lcd_ref_usec_time; | ||
373 | |||
374 | /* lcd line calculation referencing to line counter = 0 */ | ||
375 | lcd_line = | ||
376 | (elapsed_usec_time * mfd->total_lcd_lines) / mfd->lcd_ref_usec_time; | ||
377 | |||
378 | /* lcd line adjusment referencing to the actual line counter at vsync */ | ||
379 | lcd_line = | ||
380 | (mfd->total_lcd_lines - mfd->panel_info.lcd.v_back_porch + | ||
381 | lcd_line) % (mfd->total_lcd_lines + 1); | ||
382 | |||
383 | if (lcd_line > mfd->total_lcd_lines) { | ||
384 | MSM_FB_INFO | ||
385 | ("mdp_get_lcd_line_counter: mdp_lcd_rd_cnt >= mfd->total_lcd_lines error!\n"); | ||
386 | } | ||
387 | |||
388 | return lcd_line; | ||
389 | } | ||
diff --git a/drivers/staging/msm/memory.c b/drivers/staging/msm/memory.c new file mode 100644 index 000000000000..cc80fdf17d61 --- /dev/null +++ b/drivers/staging/msm/memory.c | |||
@@ -0,0 +1,214 @@ | |||
1 | /* arch/arm/mach-msm/memory.c | ||
2 | * | ||
3 | * Copyright (C) 2007 Google, Inc. | ||
4 | * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved. | ||
5 | * | ||
6 | * This software is licensed under the terms of the GNU General Public | ||
7 | * License version 2, as published by the Free Software Foundation, and | ||
8 | * may be copied, distributed, and modified under those terms. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #include <linux/mm.h> | ||
18 | #include <linux/mm_types.h> | ||
19 | #include <linux/bootmem.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <asm/pgtable.h> | ||
22 | #include <asm/io.h> | ||
23 | #include <asm/mach/map.h> | ||
24 | #include "memory_ll.h" | ||
25 | #include <asm/cacheflush.h> | ||
26 | #if defined(CONFIG_MSM_NPA_REMOTE) | ||
27 | #include "npa_remote.h" | ||
28 | #include <linux/completion.h> | ||
29 | #include <linux/err.h> | ||
30 | #endif | ||
31 | |||
32 | int arch_io_remap_pfn_range(struct vm_area_struct *vma, unsigned long addr, | ||
33 | unsigned long pfn, unsigned long size, pgprot_t prot) | ||
34 | { | ||
35 | unsigned long pfn_addr = pfn << PAGE_SHIFT; | ||
36 | /* | ||
37 | if ((pfn_addr >= 0x88000000) && (pfn_addr < 0xD0000000)) { | ||
38 | prot = pgprot_device(prot); | ||
39 | printk("remapping device %lx\n", prot); | ||
40 | } | ||
41 | */ | ||
42 | panic("Memory remap PFN stuff not done\n"); | ||
43 | return remap_pfn_range(vma, addr, pfn, size, prot); | ||
44 | } | ||
45 | |||
46 | void *zero_page_strongly_ordered; | ||
47 | |||
48 | static void map_zero_page_strongly_ordered(void) | ||
49 | { | ||
50 | if (zero_page_strongly_ordered) | ||
51 | return; | ||
52 | /* | ||
53 | zero_page_strongly_ordered = | ||
54 | ioremap_strongly_ordered(page_to_pfn(empty_zero_page) | ||
55 | << PAGE_SHIFT, PAGE_SIZE); | ||
56 | */ | ||
57 | panic("Strongly ordered memory functions not implemented\n"); | ||
58 | } | ||
59 | |||
60 | void write_to_strongly_ordered_memory(void) | ||
61 | { | ||
62 | map_zero_page_strongly_ordered(); | ||
63 | *(int *)zero_page_strongly_ordered = 0; | ||
64 | } | ||
65 | EXPORT_SYMBOL(write_to_strongly_ordered_memory); | ||
66 | |||
67 | void flush_axi_bus_buffer(void) | ||
68 | { | ||
69 | __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" \ | ||
70 | : : "r" (0) : "memory"); | ||
71 | write_to_strongly_ordered_memory(); | ||
72 | } | ||
73 | |||
74 | #define CACHE_LINE_SIZE 32 | ||
75 | |||
76 | /* These cache related routines make the assumption that the associated | ||
77 | * physical memory is contiguous. They will operate on all (L1 | ||
78 | * and L2 if present) caches. | ||
79 | */ | ||
80 | void clean_and_invalidate_caches(unsigned long vstart, | ||
81 | unsigned long length, unsigned long pstart) | ||
82 | { | ||
83 | unsigned long vaddr; | ||
84 | |||
85 | for (vaddr = vstart; vaddr < vstart + length; vaddr += CACHE_LINE_SIZE) | ||
86 | asm ("mcr p15, 0, %0, c7, c14, 1" : : "r" (vaddr)); | ||
87 | #ifdef CONFIG_OUTER_CACHE | ||
88 | outer_flush_range(pstart, pstart + length); | ||
89 | #endif | ||
90 | asm ("mcr p15, 0, %0, c7, c10, 4" : : "r" (0)); | ||
91 | asm ("mcr p15, 0, %0, c7, c5, 0" : : "r" (0)); | ||
92 | |||
93 | flush_axi_bus_buffer(); | ||
94 | } | ||
95 | |||
96 | void clean_caches(unsigned long vstart, | ||
97 | unsigned long length, unsigned long pstart) | ||
98 | { | ||
99 | unsigned long vaddr; | ||
100 | |||
101 | for (vaddr = vstart; vaddr < vstart + length; vaddr += CACHE_LINE_SIZE) | ||
102 | asm ("mcr p15, 0, %0, c7, c10, 1" : : "r" (vaddr)); | ||
103 | #ifdef CONFIG_OUTER_CACHE | ||
104 | outer_clean_range(pstart, pstart + length); | ||
105 | #endif | ||
106 | asm ("mcr p15, 0, %0, c7, c10, 4" : : "r" (0)); | ||
107 | asm ("mcr p15, 0, %0, c7, c5, 0" : : "r" (0)); | ||
108 | |||
109 | flush_axi_bus_buffer(); | ||
110 | } | ||
111 | |||
112 | void invalidate_caches(unsigned long vstart, | ||
113 | unsigned long length, unsigned long pstart) | ||
114 | { | ||
115 | unsigned long vaddr; | ||
116 | |||
117 | for (vaddr = vstart; vaddr < vstart + length; vaddr += CACHE_LINE_SIZE) | ||
118 | asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (vaddr)); | ||
119 | #ifdef CONFIG_OUTER_CACHE | ||
120 | outer_inv_range(pstart, pstart + length); | ||
121 | #endif | ||
122 | asm ("mcr p15, 0, %0, c7, c10, 4" : : "r" (0)); | ||
123 | asm ("mcr p15, 0, %0, c7, c5, 0" : : "r" (0)); | ||
124 | |||
125 | flush_axi_bus_buffer(); | ||
126 | } | ||
127 | |||
128 | void *alloc_bootmem_aligned(unsigned long size, unsigned long alignment) | ||
129 | { | ||
130 | void *unused_addr = NULL; | ||
131 | unsigned long addr, tmp_size, unused_size; | ||
132 | |||
133 | /* Allocate maximum size needed, see where it ends up. | ||
134 | * Then free it -- in this path there are no other allocators | ||
135 | * so we can depend on getting the same address back | ||
136 | * when we allocate a smaller piece that is aligned | ||
137 | * at the end (if necessary) and the piece we really want, | ||
138 | * then free the unused first piece. | ||
139 | */ | ||
140 | |||
141 | tmp_size = size + alignment - PAGE_SIZE; | ||
142 | addr = (unsigned long)alloc_bootmem(tmp_size); | ||
143 | free_bootmem(__pa(addr), tmp_size); | ||
144 | |||
145 | unused_size = alignment - (addr % alignment); | ||
146 | if (unused_size) | ||
147 | unused_addr = alloc_bootmem(unused_size); | ||
148 | |||
149 | addr = (unsigned long)alloc_bootmem(size); | ||
150 | if (unused_size) | ||
151 | free_bootmem(__pa(unused_addr), unused_size); | ||
152 | |||
153 | return (void *)addr; | ||
154 | } | ||
155 | |||
156 | #if defined(CONFIG_MSM_NPA_REMOTE) | ||
157 | struct npa_client *npa_memory_client; | ||
158 | #endif | ||
159 | |||
160 | static int change_memory_power_state(unsigned long start_pfn, | ||
161 | unsigned long nr_pages, int state) | ||
162 | { | ||
163 | #if defined(CONFIG_MSM_NPA_REMOTE) | ||
164 | static atomic_t node_created_flag = ATOMIC_INIT(1); | ||
165 | #else | ||
166 | unsigned long start; | ||
167 | unsigned long size; | ||
168 | unsigned long virtual; | ||
169 | #endif | ||
170 | int rc = 0; | ||
171 | |||
172 | #if defined(CONFIG_MSM_NPA_REMOTE) | ||
173 | if (atomic_dec_and_test(&node_created_flag)) { | ||
174 | /* Create NPA 'required' client. */ | ||
175 | npa_memory_client = npa_create_sync_client(NPA_MEMORY_NODE_NAME, | ||
176 | "memory node", NPA_CLIENT_REQUIRED); | ||
177 | if (IS_ERR(npa_memory_client)) { | ||
178 | rc = PTR_ERR(npa_memory_client); | ||
179 | return rc; | ||
180 | } | ||
181 | } | ||
182 | |||
183 | rc = npa_issue_required_request(npa_memory_client, state); | ||
184 | #else | ||
185 | if (state == MEMORY_DEEP_POWERDOWN) { | ||
186 | /* simulate turning off memory by writing bit pattern into it */ | ||
187 | start = start_pfn << PAGE_SHIFT; | ||
188 | size = nr_pages << PAGE_SHIFT; | ||
189 | virtual = __phys_to_virt(start); | ||
190 | memset((void *)virtual, 0x27, size); | ||
191 | } | ||
192 | #endif | ||
193 | return rc; | ||
194 | } | ||
195 | |||
196 | int platform_physical_remove_pages(unsigned long start_pfn, | ||
197 | unsigned long nr_pages) | ||
198 | { | ||
199 | return change_memory_power_state(start_pfn, nr_pages, | ||
200 | MEMORY_DEEP_POWERDOWN); | ||
201 | } | ||
202 | |||
203 | int platform_physical_add_pages(unsigned long start_pfn, | ||
204 | unsigned long nr_pages) | ||
205 | { | ||
206 | return change_memory_power_state(start_pfn, nr_pages, MEMORY_ACTIVE); | ||
207 | } | ||
208 | |||
209 | int platform_physical_low_power_pages(unsigned long start_pfn, | ||
210 | unsigned long nr_pages) | ||
211 | { | ||
212 | return change_memory_power_state(start_pfn, nr_pages, | ||
213 | MEMORY_SELF_REFRESH); | ||
214 | } | ||
diff --git a/drivers/staging/msm/memory_ll.h b/drivers/staging/msm/memory_ll.h new file mode 100644 index 000000000000..18a239a89a78 --- /dev/null +++ b/drivers/staging/msm/memory_ll.h | |||
@@ -0,0 +1,61 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007 Google, Inc. | ||
3 | * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved. | ||
4 | * | ||
5 | * This software is licensed under the terms of the GNU General Public | ||
6 | * License version 2, as published by the Free Software Foundation, and | ||
7 | * may be copied, distributed, and modified under those terms. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | */ | ||
15 | #ifndef __ASM_ARCH_MEMORY_LL_H | ||
16 | #define __ASM_ARCH_MEMORY_LL_H | ||
17 | |||
18 | #define MAX_PHYSMEM_BITS 32 | ||
19 | #define SECTION_SIZE_BITS 25 | ||
20 | |||
21 | #define HAS_ARCH_IO_REMAP_PFN_RANGE | ||
22 | |||
23 | #ifndef __ASSEMBLY__ | ||
24 | void *alloc_bootmem_aligned(unsigned long size, unsigned long alignment); | ||
25 | void clean_and_invalidate_caches(unsigned long, unsigned long, unsigned long); | ||
26 | void clean_caches(unsigned long, unsigned long, unsigned long); | ||
27 | void invalidate_caches(unsigned long, unsigned long, unsigned long); | ||
28 | int platform_physical_remove_pages(unsigned long, unsigned long); | ||
29 | int platform_physical_add_pages(unsigned long, unsigned long); | ||
30 | int platform_physical_low_power_pages(unsigned long, unsigned long); | ||
31 | |||
32 | #ifdef CONFIG_ARCH_MSM_ARM11 | ||
33 | void write_to_strongly_ordered_memory(void); | ||
34 | |||
35 | #include <asm/mach-types.h> | ||
36 | |||
37 | #define arch_barrier_extra() do \ | ||
38 | { if (machine_is_msm7x27_surf() || machine_is_msm7x27_ffa()) \ | ||
39 | write_to_strongly_ordered_memory(); \ | ||
40 | } while (0) | ||
41 | #endif | ||
42 | |||
43 | #ifdef CONFIG_CACHE_L2X0 | ||
44 | extern void l2x0_cache_sync(void); | ||
45 | #define finish_arch_switch(prev) do { l2x0_cache_sync(); } while (0) | ||
46 | #endif | ||
47 | |||
48 | #endif | ||
49 | |||
50 | #ifdef CONFIG_ARCH_MSM_SCORPION | ||
51 | #define arch_has_speculative_dfetch() 1 | ||
52 | #endif | ||
53 | |||
54 | #endif | ||
55 | |||
56 | /* these correspond to values known by the modem */ | ||
57 | #define MEMORY_DEEP_POWERDOWN 0 | ||
58 | #define MEMORY_SELF_REFRESH 1 | ||
59 | #define MEMORY_ACTIVE 2 | ||
60 | |||
61 | #define NPA_MEMORY_NODE_NAME "/mem/ebi1/cs1" | ||
diff --git a/drivers/staging/msm/msm_fb.c b/drivers/staging/msm/msm_fb.c new file mode 100644 index 000000000000..af5620e4eee1 --- /dev/null +++ b/drivers/staging/msm/msm_fb.c | |||
@@ -0,0 +1,2354 @@ | |||
1 | /* | ||
2 | * | ||
3 | * Core MSM framebuffer driver. | ||
4 | * | ||
5 | * Copyright (C) 2007 Google Incorporated | ||
6 | * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved. | ||
7 | * | ||
8 | * This software is licensed under the terms of the GNU General Public | ||
9 | * License version 2, as published by the Free Software Foundation, and | ||
10 | * may be copied, distributed, and modified under those terms. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/moduleparam.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <linux/mm.h> | ||
24 | #include <linux/fb.h> | ||
25 | #include "msm_mdp.h" | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/ioport.h> | ||
28 | #include <linux/device.h> | ||
29 | #include <linux/dma-mapping.h> | ||
30 | #include <mach/board.h> | ||
31 | #include <linux/uaccess.h> | ||
32 | |||
33 | #include <linux/workqueue.h> | ||
34 | #include <linux/string.h> | ||
35 | #include <linux/version.h> | ||
36 | #include <linux/proc_fs.h> | ||
37 | #include <linux/vmalloc.h> | ||
38 | #include <linux/debugfs.h> | ||
39 | #include <linux/console.h> | ||
40 | #include <linux/leds.h> | ||
41 | #include <asm/dma-mapping.h> | ||
42 | |||
43 | |||
44 | #define MSM_FB_C | ||
45 | #include "msm_fb.h" | ||
46 | #include "mddihosti.h" | ||
47 | #include "tvenc.h" | ||
48 | #include "mdp.h" | ||
49 | #include "mdp4.h" | ||
50 | |||
51 | #ifdef CONFIG_FB_MSM_LOGO | ||
52 | #define INIT_IMAGE_FILE "/logo.rle" | ||
53 | extern int load_565rle_image(char *filename); | ||
54 | #endif | ||
55 | |||
56 | |||
57 | #define pgprot_noncached(prot) \ | ||
58 | __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED) | ||
59 | #define pgprot_writecombine(prot) \ | ||
60 | __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE) | ||
61 | #define pgprot_device(prot) \ | ||
62 | __pgprot_modify(prot, L_PTE_MT_MASK|L_PTE_EXEC, L_PTE_MT_DEV_NONSHARED) | ||
63 | #define pgprot_writethroughcache(prot) \ | ||
64 | __pgprot((pgprot_val(prot) & ~L_PTE_MT_MASK) | L_PTE_MT_WRITETHROUGH) | ||
65 | #define pgprot_writebackcache(prot) \ | ||
66 | __pgprot((pgprot_val(prot) & ~L_PTE_MT_MASK) | L_PTE_MT_WRITEBACK) | ||
67 | #define pgprot_writebackwacache(prot) \ | ||
68 | __pgprot((pgprot_val(prot) & ~L_PTE_MT_MASK) | L_PTE_MT_WRITEALLOC) | ||
69 | |||
70 | static unsigned char *fbram; | ||
71 | static unsigned char *fbram_phys; | ||
72 | static int fbram_size; | ||
73 | |||
74 | static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST]; | ||
75 | static int pdev_list_cnt; | ||
76 | |||
77 | int vsync_mode = 1; | ||
78 | |||
79 | #define MAX_FBI_LIST 32 | ||
80 | static struct fb_info *fbi_list[MAX_FBI_LIST]; | ||
81 | static int fbi_list_index; | ||
82 | |||
83 | static struct msm_fb_data_type *mfd_list[MAX_FBI_LIST]; | ||
84 | static int mfd_list_index; | ||
85 | |||
86 | static u32 msm_fb_pseudo_palette[16] = { | ||
87 | 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, | ||
88 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
89 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
90 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff | ||
91 | }; | ||
92 | |||
93 | u32 msm_fb_debug_enabled; | ||
94 | /* Setting msm_fb_msg_level to 8 prints out ALL messages */ | ||
95 | u32 msm_fb_msg_level = 7; | ||
96 | |||
97 | /* Setting mddi_msg_level to 8 prints out ALL messages */ | ||
98 | u32 mddi_msg_level = 5; | ||
99 | |||
100 | extern int32 mdp_block_power_cnt[MDP_MAX_BLOCK]; | ||
101 | extern unsigned long mdp_timer_duration; | ||
102 | |||
103 | static int msm_fb_register(struct msm_fb_data_type *mfd); | ||
104 | static int msm_fb_open(struct fb_info *info, int user); | ||
105 | static int msm_fb_release(struct fb_info *info, int user); | ||
106 | static int msm_fb_pan_display(struct fb_var_screeninfo *var, | ||
107 | struct fb_info *info); | ||
108 | static int msm_fb_stop_sw_refresher(struct msm_fb_data_type *mfd); | ||
109 | int msm_fb_resume_sw_refresher(struct msm_fb_data_type *mfd); | ||
110 | static int msm_fb_check_var(struct fb_var_screeninfo *var, | ||
111 | struct fb_info *info); | ||
112 | static int msm_fb_set_par(struct fb_info *info); | ||
113 | static int msm_fb_blank_sub(int blank_mode, struct fb_info *info, | ||
114 | boolean op_enable); | ||
115 | static int msm_fb_suspend_sub(struct msm_fb_data_type *mfd); | ||
116 | static int msm_fb_resume_sub(struct msm_fb_data_type *mfd); | ||
117 | static int msm_fb_ioctl(struct fb_info *info, unsigned int cmd, | ||
118 | unsigned long arg); | ||
119 | static int msm_fb_mmap(struct fb_info *info, struct vm_area_struct * vma); | ||
120 | |||
121 | #ifdef MSM_FB_ENABLE_DBGFS | ||
122 | |||
123 | #define MSM_FB_MAX_DBGFS 1024 | ||
124 | #define MAX_BACKLIGHT_BRIGHTNESS 255 | ||
125 | |||
126 | int msm_fb_debugfs_file_index; | ||
127 | struct dentry *msm_fb_debugfs_root; | ||
128 | struct dentry *msm_fb_debugfs_file[MSM_FB_MAX_DBGFS]; | ||
129 | |||
130 | struct dentry *msm_fb_get_debugfs_root(void) | ||
131 | { | ||
132 | if (msm_fb_debugfs_root == NULL) | ||
133 | msm_fb_debugfs_root = debugfs_create_dir("msm_fb", NULL); | ||
134 | |||
135 | return msm_fb_debugfs_root; | ||
136 | } | ||
137 | |||
138 | void msm_fb_debugfs_file_create(struct dentry *root, const char *name, | ||
139 | u32 *var) | ||
140 | { | ||
141 | if (msm_fb_debugfs_file_index >= MSM_FB_MAX_DBGFS) | ||
142 | return; | ||
143 | |||
144 | msm_fb_debugfs_file[msm_fb_debugfs_file_index++] = | ||
145 | debugfs_create_u32(name, S_IRUGO | S_IWUSR, root, var); | ||
146 | } | ||
147 | #endif | ||
148 | |||
149 | int msm_fb_cursor(struct fb_info *info, struct fb_cursor *cursor) | ||
150 | { | ||
151 | struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; | ||
152 | |||
153 | if (!mfd->cursor_update) | ||
154 | return -ENODEV; | ||
155 | |||
156 | return mfd->cursor_update(info, cursor); | ||
157 | } | ||
158 | |||
159 | static int msm_fb_resource_initialized; | ||
160 | |||
161 | #ifndef CONFIG_FB_BACKLIGHT | ||
162 | static int lcd_backlight_registered; | ||
163 | |||
164 | static void msm_fb_set_bl_brightness(struct led_classdev *led_cdev, | ||
165 | enum led_brightness value) | ||
166 | { | ||
167 | struct msm_fb_data_type *mfd = dev_get_drvdata(led_cdev->dev->parent); | ||
168 | int bl_lvl; | ||
169 | |||
170 | if (value > MAX_BACKLIGHT_BRIGHTNESS) | ||
171 | value = MAX_BACKLIGHT_BRIGHTNESS; | ||
172 | |||
173 | /* This maps android backlight level 0 to 255 into | ||
174 | driver backlight level 0 to bl_max with rounding */ | ||
175 | bl_lvl = (2 * value * mfd->panel_info.bl_max + MAX_BACKLIGHT_BRIGHTNESS) | ||
176 | /(2 * MAX_BACKLIGHT_BRIGHTNESS); | ||
177 | |||
178 | if (!bl_lvl && value) | ||
179 | bl_lvl = 1; | ||
180 | |||
181 | msm_fb_set_backlight(mfd, bl_lvl, 1); | ||
182 | } | ||
183 | |||
184 | static struct led_classdev backlight_led = { | ||
185 | .name = "lcd-backlight", | ||
186 | .brightness = MAX_BACKLIGHT_BRIGHTNESS, | ||
187 | .brightness_set = msm_fb_set_bl_brightness, | ||
188 | }; | ||
189 | #endif | ||
190 | |||
191 | static struct msm_fb_platform_data *msm_fb_pdata; | ||
192 | |||
193 | int msm_fb_detect_client(const char *name) | ||
194 | { | ||
195 | int ret = -EPERM; | ||
196 | #ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT | ||
197 | u32 id; | ||
198 | #endif | ||
199 | |||
200 | if (msm_fb_pdata && msm_fb_pdata->detect_client) { | ||
201 | ret = msm_fb_pdata->detect_client(name); | ||
202 | |||
203 | /* if it's non mddi panel, we need to pre-scan | ||
204 | mddi client to see if we can disable mddi host */ | ||
205 | |||
206 | #ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT | ||
207 | if (!ret && msm_fb_pdata->mddi_prescan) | ||
208 | id = mddi_get_client_id(); | ||
209 | #endif | ||
210 | } | ||
211 | |||
212 | return ret; | ||
213 | } | ||
214 | |||
215 | static int msm_fb_probe(struct platform_device *pdev) | ||
216 | { | ||
217 | struct msm_fb_data_type *mfd; | ||
218 | int rc; | ||
219 | |||
220 | MSM_FB_DEBUG("msm_fb_probe\n"); | ||
221 | |||
222 | if ((pdev->id == 0) && (pdev->num_resources > 0)) { | ||
223 | msm_fb_pdata = pdev->dev.platform_data; | ||
224 | fbram_size = | ||
225 | pdev->resource[0].end - pdev->resource[0].start + 1; | ||
226 | fbram_phys = (char *)pdev->resource[0].start; | ||
227 | fbram = ioremap((unsigned long)fbram_phys, fbram_size); | ||
228 | |||
229 | if (!fbram) { | ||
230 | printk(KERN_ERR "fbram ioremap failed!\n"); | ||
231 | return -ENOMEM; | ||
232 | } | ||
233 | MSM_FB_INFO("msm_fb_probe: phy_Addr = 0x%x virt = 0x%x\n", | ||
234 | (int)fbram_phys, (int)fbram); | ||
235 | |||
236 | msm_fb_resource_initialized = 1; | ||
237 | return 0; | ||
238 | } | ||
239 | |||
240 | if (!msm_fb_resource_initialized) | ||
241 | return -EPERM; | ||
242 | |||
243 | mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev); | ||
244 | |||
245 | if (!mfd) | ||
246 | return -ENODEV; | ||
247 | |||
248 | if (mfd->key != MFD_KEY) | ||
249 | return -EINVAL; | ||
250 | |||
251 | if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST) | ||
252 | return -ENOMEM; | ||
253 | |||
254 | mfd->panel_info.frame_count = 0; | ||
255 | mfd->bl_level = mfd->panel_info.bl_max; | ||
256 | |||
257 | if (mfd->panel_info.type == LCDC_PANEL) | ||
258 | mfd->allow_set_offset = | ||
259 | msm_fb_pdata->allow_set_offset != NULL ? | ||
260 | msm_fb_pdata->allow_set_offset() : 0; | ||
261 | else | ||
262 | mfd->allow_set_offset = 0; | ||
263 | |||
264 | rc = msm_fb_register(mfd); | ||
265 | if (rc) | ||
266 | return rc; | ||
267 | |||
268 | #ifdef CONFIG_FB_BACKLIGHT | ||
269 | msm_fb_config_backlight(mfd); | ||
270 | #else | ||
271 | /* android supports only one lcd-backlight/lcd for now */ | ||
272 | if (!lcd_backlight_registered) { | ||
273 | if (led_classdev_register(&pdev->dev, &backlight_led)) | ||
274 | printk(KERN_ERR "led_classdev_register failed\n"); | ||
275 | else | ||
276 | lcd_backlight_registered = 1; | ||
277 | } | ||
278 | #endif | ||
279 | |||
280 | pdev_list[pdev_list_cnt++] = pdev; | ||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | static int msm_fb_remove(struct platform_device *pdev) | ||
285 | { | ||
286 | struct msm_fb_data_type *mfd; | ||
287 | |||
288 | MSM_FB_DEBUG("msm_fb_remove\n"); | ||
289 | |||
290 | mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev); | ||
291 | |||
292 | if (!mfd) | ||
293 | return -ENODEV; | ||
294 | |||
295 | if (mfd->key != MFD_KEY) | ||
296 | return -EINVAL; | ||
297 | |||
298 | if (msm_fb_suspend_sub(mfd)) | ||
299 | printk(KERN_ERR "msm_fb_remove: can't stop the device %d\n", mfd->index); | ||
300 | |||
301 | if (mfd->channel_irq != 0) | ||
302 | free_irq(mfd->channel_irq, (void *)mfd); | ||
303 | |||
304 | if (mfd->vsync_width_boundary) | ||
305 | vfree(mfd->vsync_width_boundary); | ||
306 | |||
307 | if (mfd->vsync_resync_timer.function) | ||
308 | del_timer(&mfd->vsync_resync_timer); | ||
309 | |||
310 | if (mfd->refresh_timer.function) | ||
311 | del_timer(&mfd->refresh_timer); | ||
312 | |||
313 | if (mfd->dma_hrtimer.function) | ||
314 | hrtimer_cancel(&mfd->dma_hrtimer); | ||
315 | |||
316 | /* remove /dev/fb* */ | ||
317 | unregister_framebuffer(mfd->fbi); | ||
318 | |||
319 | #ifdef CONFIG_FB_BACKLIGHT | ||
320 | /* remove /sys/class/backlight */ | ||
321 | backlight_device_unregister(mfd->fbi->bl_dev); | ||
322 | #else | ||
323 | if (lcd_backlight_registered) { | ||
324 | lcd_backlight_registered = 0; | ||
325 | led_classdev_unregister(&backlight_led); | ||
326 | } | ||
327 | #endif | ||
328 | |||
329 | #ifdef MSM_FB_ENABLE_DBGFS | ||
330 | if (mfd->sub_dir) | ||
331 | debugfs_remove(mfd->sub_dir); | ||
332 | #endif | ||
333 | |||
334 | return 0; | ||
335 | } | ||
336 | |||
337 | #if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND) | ||
338 | static int msm_fb_suspend(struct platform_device *pdev, pm_message_t state) | ||
339 | { | ||
340 | struct msm_fb_data_type *mfd; | ||
341 | int ret = 0; | ||
342 | |||
343 | MSM_FB_DEBUG("msm_fb_suspend\n"); | ||
344 | |||
345 | mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev); | ||
346 | |||
347 | if ((!mfd) || (mfd->key != MFD_KEY)) | ||
348 | return 0; | ||
349 | |||
350 | acquire_console_sem(); | ||
351 | fb_set_suspend(mfd->fbi, 1); | ||
352 | |||
353 | ret = msm_fb_suspend_sub(mfd); | ||
354 | if (ret != 0) { | ||
355 | printk(KERN_ERR "msm_fb: failed to suspend! %d\n", ret); | ||
356 | fb_set_suspend(mfd->fbi, 0); | ||
357 | } else { | ||
358 | pdev->dev.power.power_state = state; | ||
359 | } | ||
360 | |||
361 | release_console_sem(); | ||
362 | return ret; | ||
363 | } | ||
364 | #else | ||
365 | #define msm_fb_suspend NULL | ||
366 | #endif | ||
367 | |||
368 | static int msm_fb_suspend_sub(struct msm_fb_data_type *mfd) | ||
369 | { | ||
370 | int ret = 0; | ||
371 | |||
372 | if ((!mfd) || (mfd->key != MFD_KEY)) | ||
373 | return 0; | ||
374 | |||
375 | /* | ||
376 | * suspend this channel | ||
377 | */ | ||
378 | mfd->suspend.sw_refreshing_enable = mfd->sw_refreshing_enable; | ||
379 | mfd->suspend.op_enable = mfd->op_enable; | ||
380 | mfd->suspend.panel_power_on = mfd->panel_power_on; | ||
381 | |||
382 | if (mfd->op_enable) { | ||
383 | ret = | ||
384 | msm_fb_blank_sub(FB_BLANK_POWERDOWN, mfd->fbi, | ||
385 | mfd->suspend.op_enable); | ||
386 | if (ret) { | ||
387 | MSM_FB_INFO | ||
388 | ("msm_fb_suspend: can't turn off display!\n"); | ||
389 | return ret; | ||
390 | } | ||
391 | mfd->op_enable = FALSE; | ||
392 | } | ||
393 | /* | ||
394 | * try to power down | ||
395 | */ | ||
396 | mdp_pipe_ctrl(MDP_MASTER_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); | ||
397 | |||
398 | /* | ||
399 | * detach display channel irq if there's any | ||
400 | * or wait until vsync-resync completes | ||
401 | */ | ||
402 | if ((mfd->dest == DISPLAY_LCD)) { | ||
403 | if (mfd->panel_info.lcd.vsync_enable) { | ||
404 | if (mfd->panel_info.lcd.hw_vsync_mode) { | ||
405 | if (mfd->channel_irq != 0) | ||
406 | disable_irq(mfd->channel_irq); | ||
407 | } else { | ||
408 | volatile boolean vh_pending; | ||
409 | do { | ||
410 | vh_pending = mfd->vsync_handler_pending; | ||
411 | } while (vh_pending); | ||
412 | } | ||
413 | } | ||
414 | } | ||
415 | |||
416 | return 0; | ||
417 | } | ||
418 | |||
419 | #if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND) | ||
420 | static int msm_fb_resume(struct platform_device *pdev) | ||
421 | { | ||
422 | /* This resume function is called when interrupt is enabled. | ||
423 | */ | ||
424 | int ret = 0; | ||
425 | struct msm_fb_data_type *mfd; | ||
426 | |||
427 | MSM_FB_DEBUG("msm_fb_resume\n"); | ||
428 | |||
429 | mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev); | ||
430 | |||
431 | if ((!mfd) || (mfd->key != MFD_KEY)) | ||
432 | return 0; | ||
433 | |||
434 | acquire_console_sem(); | ||
435 | ret = msm_fb_resume_sub(mfd); | ||
436 | pdev->dev.power.power_state = PMSG_ON; | ||
437 | fb_set_suspend(mfd->fbi, 1); | ||
438 | release_console_sem(); | ||
439 | |||
440 | return ret; | ||
441 | } | ||
442 | #else | ||
443 | #define msm_fb_resume NULL | ||
444 | #endif | ||
445 | |||
446 | static int msm_fb_resume_sub(struct msm_fb_data_type *mfd) | ||
447 | { | ||
448 | int ret = 0; | ||
449 | |||
450 | if ((!mfd) || (mfd->key != MFD_KEY)) | ||
451 | return 0; | ||
452 | |||
453 | /* attach display channel irq if there's any */ | ||
454 | if (mfd->channel_irq != 0) | ||
455 | enable_irq(mfd->channel_irq); | ||
456 | |||
457 | /* resume state var recover */ | ||
458 | mfd->sw_refreshing_enable = mfd->suspend.sw_refreshing_enable; | ||
459 | mfd->op_enable = mfd->suspend.op_enable; | ||
460 | |||
461 | if (mfd->suspend.panel_power_on) { | ||
462 | ret = | ||
463 | msm_fb_blank_sub(FB_BLANK_UNBLANK, mfd->fbi, | ||
464 | mfd->op_enable); | ||
465 | if (ret) | ||
466 | MSM_FB_INFO("msm_fb_resume: can't turn on display!\n"); | ||
467 | } | ||
468 | |||
469 | return ret; | ||
470 | } | ||
471 | |||
472 | static struct platform_driver msm_fb_driver = { | ||
473 | .probe = msm_fb_probe, | ||
474 | .remove = msm_fb_remove, | ||
475 | #ifndef CONFIG_HAS_EARLYSUSPEND | ||
476 | .suspend = msm_fb_suspend, | ||
477 | .resume = msm_fb_resume, | ||
478 | #endif | ||
479 | .shutdown = NULL, | ||
480 | .driver = { | ||
481 | /* Driver name must match the device name added in platform.c. */ | ||
482 | .name = "msm_fb", | ||
483 | }, | ||
484 | }; | ||
485 | |||
486 | #ifdef CONFIG_HAS_EARLYSUSPEND | ||
487 | static void msmfb_early_suspend(struct early_suspend *h) | ||
488 | { | ||
489 | struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type, | ||
490 | early_suspend); | ||
491 | msm_fb_suspend_sub(mfd); | ||
492 | } | ||
493 | |||
494 | static void msmfb_early_resume(struct early_suspend *h) | ||
495 | { | ||
496 | struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type, | ||
497 | early_suspend); | ||
498 | msm_fb_resume_sub(mfd); | ||
499 | } | ||
500 | #endif | ||
501 | |||
502 | void msm_fb_set_backlight(struct msm_fb_data_type *mfd, __u32 bkl_lvl, u32 save) | ||
503 | { | ||
504 | struct msm_fb_panel_data *pdata; | ||
505 | |||
506 | pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data; | ||
507 | |||
508 | if ((pdata) && (pdata->set_backlight)) { | ||
509 | down(&mfd->sem); | ||
510 | if ((bkl_lvl != mfd->bl_level) || (!save)) { | ||
511 | u32 old_lvl; | ||
512 | |||
513 | old_lvl = mfd->bl_level; | ||
514 | mfd->bl_level = bkl_lvl; | ||
515 | pdata->set_backlight(mfd); | ||
516 | |||
517 | if (!save) | ||
518 | mfd->bl_level = old_lvl; | ||
519 | } | ||
520 | up(&mfd->sem); | ||
521 | } | ||
522 | } | ||
523 | |||
524 | static int msm_fb_blank_sub(int blank_mode, struct fb_info *info, | ||
525 | boolean op_enable) | ||
526 | { | ||
527 | struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; | ||
528 | struct msm_fb_panel_data *pdata = NULL; | ||
529 | int ret = 0; | ||
530 | |||
531 | if (!op_enable) | ||
532 | return -EPERM; | ||
533 | |||
534 | pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data; | ||
535 | if ((!pdata) || (!pdata->on) || (!pdata->off)) { | ||
536 | printk(KERN_ERR "msm_fb_blank_sub: no panel operation detected!\n"); | ||
537 | return -ENODEV; | ||
538 | } | ||
539 | |||
540 | switch (blank_mode) { | ||
541 | case FB_BLANK_UNBLANK: | ||
542 | if (!mfd->panel_power_on) { | ||
543 | mdelay(100); | ||
544 | ret = pdata->on(mfd->pdev); | ||
545 | if (ret == 0) { | ||
546 | mfd->panel_power_on = TRUE; | ||
547 | |||
548 | msm_fb_set_backlight(mfd, | ||
549 | mfd->bl_level, 0); | ||
550 | |||
551 | /* ToDo: possible conflict with android which doesn't expect sw refresher */ | ||
552 | /* | ||
553 | if (!mfd->hw_refresh) | ||
554 | { | ||
555 | if ((ret = msm_fb_resume_sw_refresher(mfd)) != 0) | ||
556 | { | ||
557 | MSM_FB_INFO("msm_fb_blank_sub: msm_fb_resume_sw_refresher failed = %d!\n",ret); | ||
558 | } | ||
559 | } | ||
560 | */ | ||
561 | } | ||
562 | } | ||
563 | break; | ||
564 | |||
565 | case FB_BLANK_VSYNC_SUSPEND: | ||
566 | case FB_BLANK_HSYNC_SUSPEND: | ||
567 | case FB_BLANK_NORMAL: | ||
568 | case FB_BLANK_POWERDOWN: | ||
569 | default: | ||
570 | if (mfd->panel_power_on) { | ||
571 | int curr_pwr_state; | ||
572 | |||
573 | mfd->op_enable = FALSE; | ||
574 | curr_pwr_state = mfd->panel_power_on; | ||
575 | mfd->panel_power_on = FALSE; | ||
576 | |||
577 | mdelay(100); | ||
578 | ret = pdata->off(mfd->pdev); | ||
579 | if (ret) | ||
580 | mfd->panel_power_on = curr_pwr_state; | ||
581 | |||
582 | msm_fb_set_backlight(mfd, 0, 0); | ||
583 | mfd->op_enable = TRUE; | ||
584 | } | ||
585 | break; | ||
586 | } | ||
587 | |||
588 | return ret; | ||
589 | } | ||
590 | |||
591 | static void msm_fb_fillrect(struct fb_info *info, | ||
592 | const struct fb_fillrect *rect) | ||
593 | { | ||
594 | struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; | ||
595 | |||
596 | cfb_fillrect(info, rect); | ||
597 | if (!mfd->hw_refresh && (info->var.yoffset == 0) && | ||
598 | !mfd->sw_currently_refreshing) { | ||
599 | struct fb_var_screeninfo var; | ||
600 | |||
601 | var = info->var; | ||
602 | var.reserved[0] = 0x54445055; | ||
603 | var.reserved[1] = (rect->dy << 16) | (rect->dx); | ||
604 | var.reserved[2] = ((rect->dy + rect->height) << 16) | | ||
605 | (rect->dx + rect->width); | ||
606 | |||
607 | msm_fb_pan_display(&var, info); | ||
608 | } | ||
609 | } | ||
610 | |||
611 | static void msm_fb_copyarea(struct fb_info *info, | ||
612 | const struct fb_copyarea *area) | ||
613 | { | ||
614 | struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; | ||
615 | |||
616 | cfb_copyarea(info, area); | ||
617 | if (!mfd->hw_refresh && (info->var.yoffset == 0) && | ||
618 | !mfd->sw_currently_refreshing) { | ||
619 | struct fb_var_screeninfo var; | ||
620 | |||
621 | var = info->var; | ||
622 | var.reserved[0] = 0x54445055; | ||
623 | var.reserved[1] = (area->dy << 16) | (area->dx); | ||
624 | var.reserved[2] = ((area->dy + area->height) << 16) | | ||
625 | (area->dx + area->width); | ||
626 | |||
627 | msm_fb_pan_display(&var, info); | ||
628 | } | ||
629 | } | ||
630 | |||
631 | static void msm_fb_imageblit(struct fb_info *info, const struct fb_image *image) | ||
632 | { | ||
633 | struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; | ||
634 | |||
635 | cfb_imageblit(info, image); | ||
636 | if (!mfd->hw_refresh && (info->var.yoffset == 0) && | ||
637 | !mfd->sw_currently_refreshing) { | ||
638 | struct fb_var_screeninfo var; | ||
639 | |||
640 | var = info->var; | ||
641 | var.reserved[0] = 0x54445055; | ||
642 | var.reserved[1] = (image->dy << 16) | (image->dx); | ||
643 | var.reserved[2] = ((image->dy + image->height) << 16) | | ||
644 | (image->dx + image->width); | ||
645 | |||
646 | msm_fb_pan_display(&var, info); | ||
647 | } | ||
648 | } | ||
649 | |||
650 | static int msm_fb_blank(int blank_mode, struct fb_info *info) | ||
651 | { | ||
652 | struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; | ||
653 | return msm_fb_blank_sub(blank_mode, info, mfd->op_enable); | ||
654 | } | ||
655 | |||
656 | static int msm_fb_set_lut(struct fb_cmap *cmap, struct fb_info *info) | ||
657 | { | ||
658 | struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; | ||
659 | |||
660 | if (!mfd->lut_update) | ||
661 | return -ENODEV; | ||
662 | |||
663 | mfd->lut_update(info, cmap); | ||
664 | return 0; | ||
665 | } | ||
666 | |||
667 | /* | ||
668 | * Custom Framebuffer mmap() function for MSM driver. | ||
669 | * Differs from standard mmap() function by allowing for customized | ||
670 | * page-protection. | ||
671 | */ | ||
672 | static int msm_fb_mmap(struct fb_info *info, struct vm_area_struct * vma) | ||
673 | { | ||
674 | /* Get frame buffer memory range. */ | ||
675 | unsigned long start = info->fix.smem_start; | ||
676 | u32 len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len); | ||
677 | unsigned long off = vma->vm_pgoff << PAGE_SHIFT; | ||
678 | struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; | ||
679 | if (off >= len) { | ||
680 | /* memory mapped io */ | ||
681 | off -= len; | ||
682 | if (info->var.accel_flags) { | ||
683 | mutex_unlock(&info->lock); | ||
684 | return -EINVAL; | ||
685 | } | ||
686 | start = info->fix.mmio_start; | ||
687 | len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len); | ||
688 | } | ||
689 | |||
690 | /* Set VM flags. */ | ||
691 | start &= PAGE_MASK; | ||
692 | if ((vma->vm_end - vma->vm_start + off) > len) | ||
693 | return -EINVAL; | ||
694 | off += start; | ||
695 | vma->vm_pgoff = off >> PAGE_SHIFT; | ||
696 | /* This is an IO map - tell maydump to skip this VMA */ | ||
697 | vma->vm_flags |= VM_IO | VM_RESERVED; | ||
698 | |||
699 | /* Set VM page protection */ | ||
700 | if (mfd->mdp_fb_page_protection == MDP_FB_PAGE_PROTECTION_WRITECOMBINE) | ||
701 | vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); | ||
702 | else if (mfd->mdp_fb_page_protection == | ||
703 | MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE) | ||
704 | vma->vm_page_prot = pgprot_writethroughcache(vma->vm_page_prot); | ||
705 | else if (mfd->mdp_fb_page_protection == | ||
706 | MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE) | ||
707 | vma->vm_page_prot = pgprot_writebackcache(vma->vm_page_prot); | ||
708 | else if (mfd->mdp_fb_page_protection == | ||
709 | MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE) | ||
710 | vma->vm_page_prot = pgprot_writebackwacache(vma->vm_page_prot); | ||
711 | else | ||
712 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | ||
713 | |||
714 | /* Remap the frame buffer I/O range */ | ||
715 | if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, | ||
716 | vma->vm_end - vma->vm_start, | ||
717 | vma->vm_page_prot)) | ||
718 | return -EAGAIN; | ||
719 | |||
720 | return 0; | ||
721 | } | ||
722 | |||
723 | static struct fb_ops msm_fb_ops = { | ||
724 | .owner = THIS_MODULE, | ||
725 | .fb_open = msm_fb_open, | ||
726 | .fb_release = msm_fb_release, | ||
727 | .fb_read = NULL, | ||
728 | .fb_write = NULL, | ||
729 | .fb_cursor = NULL, | ||
730 | .fb_check_var = msm_fb_check_var, /* vinfo check */ | ||
731 | .fb_set_par = msm_fb_set_par, /* set the video mode according to info->var */ | ||
732 | .fb_setcolreg = NULL, /* set color register */ | ||
733 | .fb_blank = msm_fb_blank, /* blank display */ | ||
734 | .fb_pan_display = msm_fb_pan_display, /* pan display */ | ||
735 | .fb_fillrect = msm_fb_fillrect, /* Draws a rectangle */ | ||
736 | .fb_copyarea = msm_fb_copyarea, /* Copy data from area to another */ | ||
737 | .fb_imageblit = msm_fb_imageblit, /* Draws a image to the display */ | ||
738 | .fb_rotate = NULL, | ||
739 | .fb_sync = NULL, /* wait for blit idle, optional */ | ||
740 | .fb_ioctl = msm_fb_ioctl, /* perform fb specific ioctl (optional) */ | ||
741 | .fb_mmap = msm_fb_mmap, | ||
742 | }; | ||
743 | |||
744 | static int msm_fb_register(struct msm_fb_data_type *mfd) | ||
745 | { | ||
746 | int ret = -ENODEV; | ||
747 | int bpp; | ||
748 | struct msm_panel_info *panel_info = &mfd->panel_info; | ||
749 | struct fb_info *fbi = mfd->fbi; | ||
750 | struct fb_fix_screeninfo *fix; | ||
751 | struct fb_var_screeninfo *var; | ||
752 | int *id; | ||
753 | int fbram_offset; | ||
754 | |||
755 | /* | ||
756 | * fb info initialization | ||
757 | */ | ||
758 | fix = &fbi->fix; | ||
759 | var = &fbi->var; | ||
760 | |||
761 | fix->type_aux = 0; /* if type == FB_TYPE_INTERLEAVED_PLANES */ | ||
762 | fix->visual = FB_VISUAL_TRUECOLOR; /* True Color */ | ||
763 | fix->ywrapstep = 0; /* No support */ | ||
764 | fix->mmio_start = 0; /* No MMIO Address */ | ||
765 | fix->mmio_len = 0; /* No MMIO Address */ | ||
766 | fix->accel = FB_ACCEL_NONE;/* FB_ACCEL_MSM needes to be added in fb.h */ | ||
767 | |||
768 | var->xoffset = 0, /* Offset from virtual to visible */ | ||
769 | var->yoffset = 0, /* resolution */ | ||
770 | var->grayscale = 0, /* No graylevels */ | ||
771 | var->nonstd = 0, /* standard pixel format */ | ||
772 | var->activate = FB_ACTIVATE_VBL, /* activate it at vsync */ | ||
773 | var->height = -1, /* height of picture in mm */ | ||
774 | var->width = -1, /* width of picture in mm */ | ||
775 | var->accel_flags = 0, /* acceleration flags */ | ||
776 | var->sync = 0, /* see FB_SYNC_* */ | ||
777 | var->rotate = 0, /* angle we rotate counter clockwise */ | ||
778 | mfd->op_enable = FALSE; | ||
779 | |||
780 | switch (mfd->fb_imgType) { | ||
781 | case MDP_RGB_565: | ||
782 | fix->type = FB_TYPE_PACKED_PIXELS; | ||
783 | fix->xpanstep = 1; | ||
784 | fix->ypanstep = 1; | ||
785 | var->vmode = FB_VMODE_NONINTERLACED; | ||
786 | var->blue.offset = 0; | ||
787 | var->green.offset = 5; | ||
788 | var->red.offset = 11; | ||
789 | var->blue.length = 5; | ||
790 | var->green.length = 6; | ||
791 | var->red.length = 5; | ||
792 | var->blue.msb_right = 0; | ||
793 | var->green.msb_right = 0; | ||
794 | var->red.msb_right = 0; | ||
795 | var->transp.offset = 0; | ||
796 | var->transp.length = 0; | ||
797 | bpp = 2; | ||
798 | break; | ||
799 | |||
800 | case MDP_RGB_888: | ||
801 | fix->type = FB_TYPE_PACKED_PIXELS; | ||
802 | fix->xpanstep = 1; | ||
803 | fix->ypanstep = 1; | ||
804 | var->vmode = FB_VMODE_NONINTERLACED; | ||
805 | var->blue.offset = 0; | ||
806 | var->green.offset = 8; | ||
807 | var->red.offset = 16; | ||
808 | var->blue.length = 8; | ||
809 | var->green.length = 8; | ||
810 | var->red.length = 8; | ||
811 | var->blue.msb_right = 0; | ||
812 | var->green.msb_right = 0; | ||
813 | var->red.msb_right = 0; | ||
814 | var->transp.offset = 0; | ||
815 | var->transp.length = 0; | ||
816 | bpp = 3; | ||
817 | break; | ||
818 | |||
819 | case MDP_ARGB_8888: | ||
820 | fix->type = FB_TYPE_PACKED_PIXELS; | ||
821 | fix->xpanstep = 1; | ||
822 | fix->ypanstep = 1; | ||
823 | var->vmode = FB_VMODE_NONINTERLACED; | ||
824 | var->blue.offset = 0; | ||
825 | var->green.offset = 8; | ||
826 | var->red.offset = 16; | ||
827 | var->blue.length = 8; | ||
828 | var->green.length = 8; | ||
829 | var->red.length = 8; | ||
830 | var->blue.msb_right = 0; | ||
831 | var->green.msb_right = 0; | ||
832 | var->red.msb_right = 0; | ||
833 | var->transp.offset = 24; | ||
834 | var->transp.length = 8; | ||
835 | bpp = 3; | ||
836 | break; | ||
837 | |||
838 | case MDP_YCRYCB_H2V1: | ||
839 | /* ToDo: need to check TV-Out YUV422i framebuffer format */ | ||
840 | /* we might need to create new type define */ | ||
841 | fix->type = FB_TYPE_INTERLEAVED_PLANES; | ||
842 | fix->xpanstep = 2; | ||
843 | fix->ypanstep = 1; | ||
844 | var->vmode = FB_VMODE_NONINTERLACED; | ||
845 | |||
846 | /* how about R/G/B offset? */ | ||
847 | var->blue.offset = 0; | ||
848 | var->green.offset = 5; | ||
849 | var->red.offset = 11; | ||
850 | var->blue.length = 5; | ||
851 | var->green.length = 6; | ||
852 | var->red.length = 5; | ||
853 | var->blue.msb_right = 0; | ||
854 | var->green.msb_right = 0; | ||
855 | var->red.msb_right = 0; | ||
856 | var->transp.offset = 0; | ||
857 | var->transp.length = 0; | ||
858 | bpp = 2; | ||
859 | break; | ||
860 | |||
861 | default: | ||
862 | MSM_FB_ERR("msm_fb_init: fb %d unkown image type!\n", | ||
863 | mfd->index); | ||
864 | return ret; | ||
865 | } | ||
866 | |||
867 | /* The adreno GPU hardware requires that the pitch be aligned to | ||
868 | 32 pixels for color buffers, so for the cases where the GPU | ||
869 | is writing directly to fb0, the framebuffer pitch | ||
870 | also needs to be 32 pixel aligned */ | ||
871 | |||
872 | if (mfd->index == 0) | ||
873 | fix->line_length = ALIGN(panel_info->xres * bpp, 32); | ||
874 | else | ||
875 | fix->line_length = panel_info->xres * bpp; | ||
876 | |||
877 | fix->smem_len = fix->line_length * panel_info->yres * mfd->fb_page; | ||
878 | |||
879 | mfd->var_xres = panel_info->xres; | ||
880 | mfd->var_yres = panel_info->yres; | ||
881 | |||
882 | var->pixclock = mfd->panel_info.clk_rate; | ||
883 | mfd->var_pixclock = var->pixclock; | ||
884 | |||
885 | var->xres = panel_info->xres; | ||
886 | var->yres = panel_info->yres; | ||
887 | var->xres_virtual = panel_info->xres; | ||
888 | var->yres_virtual = panel_info->yres * mfd->fb_page; | ||
889 | var->bits_per_pixel = bpp * 8, /* FrameBuffer color depth */ | ||
890 | /* | ||
891 | * id field for fb app | ||
892 | */ | ||
893 | id = (int *)&mfd->panel; | ||
894 | |||
895 | #if defined(CONFIG_FB_MSM_MDP22) | ||
896 | snprintf(fix->id, sizeof(fix->id), "msmfb22_%x", (__u32) *id); | ||
897 | #elif defined(CONFIG_FB_MSM_MDP30) | ||
898 | snprintf(fix->id, sizeof(fix->id), "msmfb30_%x", (__u32) *id); | ||
899 | #elif defined(CONFIG_FB_MSM_MDP31) | ||
900 | snprintf(fix->id, sizeof(fix->id), "msmfb31_%x", (__u32) *id); | ||
901 | #elif defined(CONFIG_FB_MSM_MDP40) | ||
902 | snprintf(fix->id, sizeof(fix->id), "msmfb40_%x", (__u32) *id); | ||
903 | #else | ||
904 | error CONFIG_FB_MSM_MDP undefined ! | ||
905 | #endif | ||
906 | fbi->fbops = &msm_fb_ops; | ||
907 | fbi->flags = FBINFO_FLAG_DEFAULT; | ||
908 | fbi->pseudo_palette = msm_fb_pseudo_palette; | ||
909 | |||
910 | mfd->ref_cnt = 0; | ||
911 | mfd->sw_currently_refreshing = FALSE; | ||
912 | mfd->sw_refreshing_enable = TRUE; | ||
913 | mfd->panel_power_on = FALSE; | ||
914 | |||
915 | mfd->pan_waiting = FALSE; | ||
916 | init_completion(&mfd->pan_comp); | ||
917 | init_completion(&mfd->refresher_comp); | ||
918 | init_MUTEX(&mfd->sem); | ||
919 | |||
920 | fbram_offset = PAGE_ALIGN((int)fbram)-(int)fbram; | ||
921 | fbram += fbram_offset; | ||
922 | fbram_phys += fbram_offset; | ||
923 | fbram_size -= fbram_offset; | ||
924 | |||
925 | if (fbram_size < fix->smem_len) { | ||
926 | printk(KERN_ERR "error: no more framebuffer memory!\n"); | ||
927 | return -ENOMEM; | ||
928 | } | ||
929 | |||
930 | fbi->screen_base = fbram; | ||
931 | fbi->fix.smem_start = (unsigned long)fbram_phys; | ||
932 | |||
933 | memset(fbi->screen_base, 0x0, fix->smem_len); | ||
934 | |||
935 | mfd->op_enable = TRUE; | ||
936 | mfd->panel_power_on = FALSE; | ||
937 | |||
938 | /* cursor memory allocation */ | ||
939 | if (mfd->cursor_update) { | ||
940 | mfd->cursor_buf = dma_alloc_coherent(NULL, | ||
941 | MDP_CURSOR_SIZE, | ||
942 | (dma_addr_t *) &mfd->cursor_buf_phys, | ||
943 | GFP_KERNEL); | ||
944 | if (!mfd->cursor_buf) | ||
945 | mfd->cursor_update = 0; | ||
946 | } | ||
947 | |||
948 | if (mfd->lut_update) { | ||
949 | ret = fb_alloc_cmap(&fbi->cmap, 256, 0); | ||
950 | if (ret) | ||
951 | printk(KERN_ERR "%s: fb_alloc_cmap() failed!\n", | ||
952 | __func__); | ||
953 | } | ||
954 | |||
955 | if (register_framebuffer(fbi) < 0) { | ||
956 | if (mfd->lut_update) | ||
957 | fb_dealloc_cmap(&fbi->cmap); | ||
958 | |||
959 | if (mfd->cursor_buf) | ||
960 | dma_free_coherent(NULL, | ||
961 | MDP_CURSOR_SIZE, | ||
962 | mfd->cursor_buf, | ||
963 | (dma_addr_t) mfd->cursor_buf_phys); | ||
964 | |||
965 | mfd->op_enable = FALSE; | ||
966 | return -EPERM; | ||
967 | } | ||
968 | |||
969 | fbram += fix->smem_len; | ||
970 | fbram_phys += fix->smem_len; | ||
971 | fbram_size -= fix->smem_len; | ||
972 | |||
973 | MSM_FB_INFO | ||
974 | ("FrameBuffer[%d] %dx%d size=%d bytes is registered successfully!\n", | ||
975 | mfd->index, fbi->var.xres, fbi->var.yres, fbi->fix.smem_len); | ||
976 | |||
977 | #ifdef CONFIG_FB_MSM_LOGO | ||
978 | if (!load_565rle_image(INIT_IMAGE_FILE)) ; /* Flip buffer */ | ||
979 | #endif | ||
980 | ret = 0; | ||
981 | |||
982 | #ifdef CONFIG_HAS_EARLYSUSPEND | ||
983 | mfd->early_suspend.suspend = msmfb_early_suspend; | ||
984 | mfd->early_suspend.resume = msmfb_early_resume; | ||
985 | mfd->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 2; | ||
986 | register_early_suspend(&mfd->early_suspend); | ||
987 | #endif | ||
988 | |||
989 | #ifdef MSM_FB_ENABLE_DBGFS | ||
990 | { | ||
991 | struct dentry *root; | ||
992 | struct dentry *sub_dir; | ||
993 | char sub_name[2]; | ||
994 | |||
995 | root = msm_fb_get_debugfs_root(); | ||
996 | if (root != NULL) { | ||
997 | sub_name[0] = (char)(mfd->index + 0x30); | ||
998 | sub_name[1] = '\0'; | ||
999 | sub_dir = debugfs_create_dir(sub_name, root); | ||
1000 | } else { | ||
1001 | sub_dir = NULL; | ||
1002 | } | ||
1003 | |||
1004 | mfd->sub_dir = sub_dir; | ||
1005 | |||
1006 | if (sub_dir) { | ||
1007 | msm_fb_debugfs_file_create(sub_dir, "op_enable", | ||
1008 | (u32 *) &mfd->op_enable); | ||
1009 | msm_fb_debugfs_file_create(sub_dir, "panel_power_on", | ||
1010 | (u32 *) &mfd-> | ||
1011 | panel_power_on); | ||
1012 | msm_fb_debugfs_file_create(sub_dir, "ref_cnt", | ||
1013 | (u32 *) &mfd->ref_cnt); | ||
1014 | msm_fb_debugfs_file_create(sub_dir, "fb_imgType", | ||
1015 | (u32 *) &mfd->fb_imgType); | ||
1016 | msm_fb_debugfs_file_create(sub_dir, | ||
1017 | "sw_currently_refreshing", | ||
1018 | (u32 *) &mfd-> | ||
1019 | sw_currently_refreshing); | ||
1020 | msm_fb_debugfs_file_create(sub_dir, | ||
1021 | "sw_refreshing_enable", | ||
1022 | (u32 *) &mfd-> | ||
1023 | sw_refreshing_enable); | ||
1024 | |||
1025 | msm_fb_debugfs_file_create(sub_dir, "xres", | ||
1026 | (u32 *) &mfd->panel_info. | ||
1027 | xres); | ||
1028 | msm_fb_debugfs_file_create(sub_dir, "yres", | ||
1029 | (u32 *) &mfd->panel_info. | ||
1030 | yres); | ||
1031 | msm_fb_debugfs_file_create(sub_dir, "bpp", | ||
1032 | (u32 *) &mfd->panel_info. | ||
1033 | bpp); | ||
1034 | msm_fb_debugfs_file_create(sub_dir, "type", | ||
1035 | (u32 *) &mfd->panel_info. | ||
1036 | type); | ||
1037 | msm_fb_debugfs_file_create(sub_dir, "wait_cycle", | ||
1038 | (u32 *) &mfd->panel_info. | ||
1039 | wait_cycle); | ||
1040 | msm_fb_debugfs_file_create(sub_dir, "pdest", | ||
1041 | (u32 *) &mfd->panel_info. | ||
1042 | pdest); | ||
1043 | msm_fb_debugfs_file_create(sub_dir, "backbuff", | ||
1044 | (u32 *) &mfd->panel_info. | ||
1045 | fb_num); | ||
1046 | msm_fb_debugfs_file_create(sub_dir, "clk_rate", | ||
1047 | (u32 *) &mfd->panel_info. | ||
1048 | clk_rate); | ||
1049 | msm_fb_debugfs_file_create(sub_dir, "frame_count", | ||
1050 | (u32 *) &mfd->panel_info. | ||
1051 | frame_count); | ||
1052 | |||
1053 | |||
1054 | switch (mfd->dest) { | ||
1055 | case DISPLAY_LCD: | ||
1056 | msm_fb_debugfs_file_create(sub_dir, | ||
1057 | "vsync_enable", | ||
1058 | (u32 *)&mfd->panel_info.lcd.vsync_enable); | ||
1059 | msm_fb_debugfs_file_create(sub_dir, | ||
1060 | "refx100", | ||
1061 | (u32 *) &mfd->panel_info.lcd. refx100); | ||
1062 | msm_fb_debugfs_file_create(sub_dir, | ||
1063 | "v_back_porch", | ||
1064 | (u32 *) &mfd->panel_info.lcd.v_back_porch); | ||
1065 | msm_fb_debugfs_file_create(sub_dir, | ||
1066 | "v_front_porch", | ||
1067 | (u32 *) &mfd->panel_info.lcd.v_front_porch); | ||
1068 | msm_fb_debugfs_file_create(sub_dir, | ||
1069 | "v_pulse_width", | ||
1070 | (u32 *) &mfd->panel_info.lcd.v_pulse_width); | ||
1071 | msm_fb_debugfs_file_create(sub_dir, | ||
1072 | "hw_vsync_mode", | ||
1073 | (u32 *) &mfd->panel_info.lcd.hw_vsync_mode); | ||
1074 | msm_fb_debugfs_file_create(sub_dir, | ||
1075 | "vsync_notifier_period", (u32 *) | ||
1076 | &mfd->panel_info.lcd.vsync_notifier_period); | ||
1077 | break; | ||
1078 | |||
1079 | case DISPLAY_LCDC: | ||
1080 | msm_fb_debugfs_file_create(sub_dir, | ||
1081 | "h_back_porch", | ||
1082 | (u32 *) &mfd->panel_info.lcdc.h_back_porch); | ||
1083 | msm_fb_debugfs_file_create(sub_dir, | ||
1084 | "h_front_porch", | ||
1085 | (u32 *) &mfd->panel_info.lcdc.h_front_porch); | ||
1086 | msm_fb_debugfs_file_create(sub_dir, | ||
1087 | "h_pulse_width", | ||
1088 | (u32 *) &mfd->panel_info.lcdc.h_pulse_width); | ||
1089 | msm_fb_debugfs_file_create(sub_dir, | ||
1090 | "v_back_porch", | ||
1091 | (u32 *) &mfd->panel_info.lcdc.v_back_porch); | ||
1092 | msm_fb_debugfs_file_create(sub_dir, | ||
1093 | "v_front_porch", | ||
1094 | (u32 *) &mfd->panel_info.lcdc.v_front_porch); | ||
1095 | msm_fb_debugfs_file_create(sub_dir, | ||
1096 | "v_pulse_width", | ||
1097 | (u32 *) &mfd->panel_info.lcdc.v_pulse_width); | ||
1098 | msm_fb_debugfs_file_create(sub_dir, | ||
1099 | "border_clr", | ||
1100 | (u32 *) &mfd->panel_info.lcdc.border_clr); | ||
1101 | msm_fb_debugfs_file_create(sub_dir, | ||
1102 | "underflow_clr", | ||
1103 | (u32 *) &mfd->panel_info.lcdc.underflow_clr); | ||
1104 | msm_fb_debugfs_file_create(sub_dir, | ||
1105 | "hsync_skew", | ||
1106 | (u32 *) &mfd->panel_info.lcdc.hsync_skew); | ||
1107 | break; | ||
1108 | |||
1109 | default: | ||
1110 | break; | ||
1111 | } | ||
1112 | } | ||
1113 | } | ||
1114 | #endif /* MSM_FB_ENABLE_DBGFS */ | ||
1115 | |||
1116 | return ret; | ||
1117 | } | ||
1118 | |||
1119 | static int msm_fb_open(struct fb_info *info, int user) | ||
1120 | { | ||
1121 | struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; | ||
1122 | |||
1123 | if (!mfd->ref_cnt) { | ||
1124 | mdp_set_dma_pan_info(info, NULL, TRUE); | ||
1125 | |||
1126 | if (msm_fb_blank_sub(FB_BLANK_UNBLANK, info, mfd->op_enable)) { | ||
1127 | printk(KERN_ERR "msm_fb_open: can't turn on display!\n"); | ||
1128 | return -1; | ||
1129 | } | ||
1130 | } | ||
1131 | |||
1132 | mfd->ref_cnt++; | ||
1133 | return 0; | ||
1134 | } | ||
1135 | |||
1136 | static int msm_fb_release(struct fb_info *info, int user) | ||
1137 | { | ||
1138 | struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; | ||
1139 | int ret = 0; | ||
1140 | |||
1141 | if (!mfd->ref_cnt) { | ||
1142 | MSM_FB_INFO("msm_fb_release: try to close unopened fb %d!\n", | ||
1143 | mfd->index); | ||
1144 | return -EINVAL; | ||
1145 | } | ||
1146 | |||
1147 | mfd->ref_cnt--; | ||
1148 | |||
1149 | if (!mfd->ref_cnt) { | ||
1150 | if ((ret = | ||
1151 | msm_fb_blank_sub(FB_BLANK_POWERDOWN, info, | ||
1152 | mfd->op_enable)) != 0) { | ||
1153 | printk(KERN_ERR "msm_fb_release: can't turn off display!\n"); | ||
1154 | return ret; | ||
1155 | } | ||
1156 | } | ||
1157 | |||
1158 | return ret; | ||
1159 | } | ||
1160 | |||
1161 | DECLARE_MUTEX(msm_fb_pan_sem); | ||
1162 | |||
1163 | static int msm_fb_pan_display(struct fb_var_screeninfo *var, | ||
1164 | struct fb_info *info) | ||
1165 | { | ||
1166 | struct mdp_dirty_region dirty; | ||
1167 | struct mdp_dirty_region *dirtyPtr = NULL; | ||
1168 | struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; | ||
1169 | |||
1170 | if ((!mfd->op_enable) || (!mfd->panel_power_on)) | ||
1171 | return -EPERM; | ||
1172 | |||
1173 | if (var->xoffset > (info->var.xres_virtual - info->var.xres)) | ||
1174 | return -EINVAL; | ||
1175 | |||
1176 | if (var->yoffset > (info->var.yres_virtual - info->var.yres)) | ||
1177 | return -EINVAL; | ||
1178 | |||
1179 | if (info->fix.xpanstep) | ||
1180 | info->var.xoffset = | ||
1181 | (var->xoffset / info->fix.xpanstep) * info->fix.xpanstep; | ||
1182 | |||
1183 | if (info->fix.ypanstep) | ||
1184 | info->var.yoffset = | ||
1185 | (var->yoffset / info->fix.ypanstep) * info->fix.ypanstep; | ||
1186 | |||
1187 | /* "UPDT" */ | ||
1188 | if (var->reserved[0] == 0x54445055) { | ||
1189 | dirty.xoffset = var->reserved[1] & 0xffff; | ||
1190 | dirty.yoffset = (var->reserved[1] >> 16) & 0xffff; | ||
1191 | |||
1192 | if ((var->reserved[2] & 0xffff) <= dirty.xoffset) | ||
1193 | return -EINVAL; | ||
1194 | if (((var->reserved[2] >> 16) & 0xffff) <= dirty.yoffset) | ||
1195 | return -EINVAL; | ||
1196 | |||
1197 | dirty.width = (var->reserved[2] & 0xffff) - dirty.xoffset; | ||
1198 | dirty.height = | ||
1199 | ((var->reserved[2] >> 16) & 0xffff) - dirty.yoffset; | ||
1200 | info->var.yoffset = var->yoffset; | ||
1201 | |||
1202 | if (dirty.xoffset < 0) | ||
1203 | return -EINVAL; | ||
1204 | |||
1205 | if (dirty.yoffset < 0) | ||
1206 | return -EINVAL; | ||
1207 | |||
1208 | if ((dirty.xoffset + dirty.width) > info->var.xres) | ||
1209 | return -EINVAL; | ||
1210 | |||
1211 | if ((dirty.yoffset + dirty.height) > info->var.yres) | ||
1212 | return -EINVAL; | ||
1213 | |||
1214 | if ((dirty.width <= 0) || (dirty.height <= 0)) | ||
1215 | return -EINVAL; | ||
1216 | |||
1217 | dirtyPtr = &dirty; | ||
1218 | } | ||
1219 | |||
1220 | /* Flip */ | ||
1221 | /* A constant value is used to indicate that we should change the DMA | ||
1222 | output buffer instead of just panning */ | ||
1223 | |||
1224 | if (var->reserved[0] == 0x466c6970) { | ||
1225 | unsigned long length, address; | ||
1226 | struct file *p_src_file; | ||
1227 | struct mdp_img imgdata; | ||
1228 | int bpp; | ||
1229 | |||
1230 | if (mfd->allow_set_offset) { | ||
1231 | imgdata.memory_id = var->reserved[1]; | ||
1232 | imgdata.priv = var->reserved[2]; | ||
1233 | |||
1234 | /* If there is no memory ID then we want to reset back | ||
1235 | to the original fb visibility */ | ||
1236 | if (var->reserved[1]) { | ||
1237 | if (var->reserved[4] == MDP_BLIT_SRC_GEM) { | ||
1238 | panic("waaaaaaaaaaaaaah"); | ||
1239 | if ( /*get_gem_img(&imgdata, | ||
1240 | (unsigned long *) &address, | ||
1241 | &length)*/ -1 < 0) { | ||
1242 | return -1; | ||
1243 | } | ||
1244 | } else { | ||
1245 | /*get_img(&imgdata, info, &address, | ||
1246 | &length, &p_src_file);*/ | ||
1247 | panic("waaaaaah"); | ||
1248 | } | ||
1249 | mfd->ibuf.visible_swapped = TRUE; | ||
1250 | } else { | ||
1251 | /* Flip back to the original address | ||
1252 | adjusted for xoffset and yoffset */ | ||
1253 | |||
1254 | bpp = info->var.bits_per_pixel / 8; | ||
1255 | address = (unsigned long) info->fix.smem_start; | ||
1256 | address += info->var.xoffset * bpp + | ||
1257 | info->var.yoffset * info->fix.line_length; | ||
1258 | |||
1259 | mfd->ibuf.visible_swapped = FALSE; | ||
1260 | } | ||
1261 | |||
1262 | mdp_set_offset_info(info, address, | ||
1263 | (var->activate == FB_ACTIVATE_VBL)); | ||
1264 | |||
1265 | mfd->dma_fnc(mfd); | ||
1266 | return 0; | ||
1267 | } else | ||
1268 | return -EINVAL; | ||
1269 | } | ||
1270 | |||
1271 | down(&msm_fb_pan_sem); | ||
1272 | mdp_set_dma_pan_info(info, dirtyPtr, | ||
1273 | (var->activate == FB_ACTIVATE_VBL)); | ||
1274 | mdp_dma_pan_update(info); | ||
1275 | up(&msm_fb_pan_sem); | ||
1276 | |||
1277 | ++mfd->panel_info.frame_count; | ||
1278 | return 0; | ||
1279 | } | ||
1280 | |||
1281 | static int msm_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | ||
1282 | { | ||
1283 | struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; | ||
1284 | |||
1285 | if (var->rotate != FB_ROTATE_UR) | ||
1286 | return -EINVAL; | ||
1287 | if (var->grayscale != info->var.grayscale) | ||
1288 | return -EINVAL; | ||
1289 | |||
1290 | switch (var->bits_per_pixel) { | ||
1291 | case 16: | ||
1292 | if ((var->green.offset != 5) || | ||
1293 | !((var->blue.offset == 11) | ||
1294 | || (var->blue.offset == 0)) || | ||
1295 | !((var->red.offset == 11) | ||
1296 | || (var->red.offset == 0)) || | ||
1297 | (var->blue.length != 5) || | ||
1298 | (var->green.length != 6) || | ||
1299 | (var->red.length != 5) || | ||
1300 | (var->blue.msb_right != 0) || | ||
1301 | (var->green.msb_right != 0) || | ||
1302 | (var->red.msb_right != 0) || | ||
1303 | (var->transp.offset != 0) || | ||
1304 | (var->transp.length != 0)) | ||
1305 | return -EINVAL; | ||
1306 | break; | ||
1307 | |||
1308 | case 24: | ||
1309 | if ((var->blue.offset != 0) || | ||
1310 | (var->green.offset != 8) || | ||
1311 | (var->red.offset != 16) || | ||
1312 | (var->blue.length != 8) || | ||
1313 | (var->green.length != 8) || | ||
1314 | (var->red.length != 8) || | ||
1315 | (var->blue.msb_right != 0) || | ||
1316 | (var->green.msb_right != 0) || | ||
1317 | (var->red.msb_right != 0) || | ||
1318 | !(((var->transp.offset == 0) && | ||
1319 | (var->transp.length == 0)) || | ||
1320 | ((var->transp.offset == 24) && | ||
1321 | (var->transp.length == 8)))) | ||
1322 | return -EINVAL; | ||
1323 | break; | ||
1324 | |||
1325 | default: | ||
1326 | return -EINVAL; | ||
1327 | } | ||
1328 | |||
1329 | if ((var->xres_virtual <= 0) || (var->yres_virtual <= 0)) | ||
1330 | return -EINVAL; | ||
1331 | |||
1332 | if (info->fix.smem_len < | ||
1333 | (var->xres_virtual*var->yres_virtual*(var->bits_per_pixel/8))) | ||
1334 | return -EINVAL; | ||
1335 | |||
1336 | if ((var->xres == 0) || (var->yres == 0)) | ||
1337 | return -EINVAL; | ||
1338 | |||
1339 | if ((var->xres > mfd->panel_info.xres) || | ||
1340 | (var->yres > mfd->panel_info.yres)) | ||
1341 | return -EINVAL; | ||
1342 | |||
1343 | if (var->xoffset > (var->xres_virtual - var->xres)) | ||
1344 | return -EINVAL; | ||
1345 | |||
1346 | if (var->yoffset > (var->yres_virtual - var->yres)) | ||
1347 | return -EINVAL; | ||
1348 | |||
1349 | return 0; | ||
1350 | } | ||
1351 | |||
1352 | static int msm_fb_set_par(struct fb_info *info) | ||
1353 | { | ||
1354 | struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; | ||
1355 | struct fb_var_screeninfo *var = &info->var; | ||
1356 | int old_imgType; | ||
1357 | int blank = 0; | ||
1358 | |||
1359 | old_imgType = mfd->fb_imgType; | ||
1360 | switch (var->bits_per_pixel) { | ||
1361 | case 16: | ||
1362 | if (var->red.offset == 0) | ||
1363 | mfd->fb_imgType = MDP_BGR_565; | ||
1364 | else | ||
1365 | mfd->fb_imgType = MDP_RGB_565; | ||
1366 | break; | ||
1367 | |||
1368 | case 24: | ||
1369 | if ((var->transp.offset == 0) && (var->transp.length == 0)) | ||
1370 | mfd->fb_imgType = MDP_RGB_888; | ||
1371 | else if ((var->transp.offset == 24) && | ||
1372 | (var->transp.length == 8)) { | ||
1373 | mfd->fb_imgType = MDP_ARGB_8888; | ||
1374 | info->var.bits_per_pixel = 32; | ||
1375 | } | ||
1376 | break; | ||
1377 | |||
1378 | default: | ||
1379 | return -EINVAL; | ||
1380 | } | ||
1381 | |||
1382 | if ((mfd->var_pixclock != var->pixclock) || | ||
1383 | (mfd->hw_refresh && ((mfd->fb_imgType != old_imgType) || | ||
1384 | (mfd->var_pixclock != var->pixclock) || | ||
1385 | (mfd->var_xres != var->xres) || | ||
1386 | (mfd->var_yres != var->yres)))) { | ||
1387 | mfd->var_xres = var->xres; | ||
1388 | mfd->var_yres = var->yres; | ||
1389 | mfd->var_pixclock = var->pixclock; | ||
1390 | blank = 1; | ||
1391 | } | ||
1392 | |||
1393 | if (blank) { | ||
1394 | msm_fb_blank_sub(FB_BLANK_POWERDOWN, info, mfd->op_enable); | ||
1395 | msm_fb_blank_sub(FB_BLANK_UNBLANK, info, mfd->op_enable); | ||
1396 | } | ||
1397 | |||
1398 | return 0; | ||
1399 | } | ||
1400 | |||
1401 | static int msm_fb_stop_sw_refresher(struct msm_fb_data_type *mfd) | ||
1402 | { | ||
1403 | if (mfd->hw_refresh) | ||
1404 | return -EPERM; | ||
1405 | |||
1406 | if (mfd->sw_currently_refreshing) { | ||
1407 | down(&mfd->sem); | ||
1408 | mfd->sw_currently_refreshing = FALSE; | ||
1409 | up(&mfd->sem); | ||
1410 | |||
1411 | /* wait until the refresher finishes the last job */ | ||
1412 | wait_for_completion_killable(&mfd->refresher_comp); | ||
1413 | } | ||
1414 | |||
1415 | return 0; | ||
1416 | } | ||
1417 | |||
1418 | int msm_fb_resume_sw_refresher(struct msm_fb_data_type *mfd) | ||
1419 | { | ||
1420 | boolean do_refresh; | ||
1421 | |||
1422 | if (mfd->hw_refresh) | ||
1423 | return -EPERM; | ||
1424 | |||
1425 | down(&mfd->sem); | ||
1426 | if ((!mfd->sw_currently_refreshing) && (mfd->sw_refreshing_enable)) { | ||
1427 | do_refresh = TRUE; | ||
1428 | mfd->sw_currently_refreshing = TRUE; | ||
1429 | } else { | ||
1430 | do_refresh = FALSE; | ||
1431 | } | ||
1432 | up(&mfd->sem); | ||
1433 | |||
1434 | if (do_refresh) | ||
1435 | mdp_refresh_screen((unsigned long)mfd); | ||
1436 | |||
1437 | return 0; | ||
1438 | } | ||
1439 | |||
1440 | void mdp_ppp_put_img(struct file *p_src_file, struct file *p_dst_file) | ||
1441 | { | ||
1442 | #ifdef CONFIG_ANDROID_PMEM | ||
1443 | if (p_src_file) | ||
1444 | put_pmem_file(p_src_file); | ||
1445 | if (p_dst_file) | ||
1446 | put_pmem_file(p_dst_file); | ||
1447 | #endif | ||
1448 | } | ||
1449 | |||
1450 | int mdp_blit(struct fb_info *info, struct mdp_blit_req *req) | ||
1451 | { | ||
1452 | int ret; | ||
1453 | struct file *p_src_file = 0, *p_dst_file = 0; | ||
1454 | if (unlikely(req->src_rect.h == 0 || req->src_rect.w == 0)) { | ||
1455 | printk(KERN_ERR "mpd_ppp: src img of zero size!\n"); | ||
1456 | return -EINVAL; | ||
1457 | } | ||
1458 | if (unlikely(req->dst_rect.h == 0 || req->dst_rect.w == 0)) | ||
1459 | return 0; | ||
1460 | |||
1461 | ret = mdp_ppp_blit(info, req, &p_src_file, &p_dst_file); | ||
1462 | mdp_ppp_put_img(p_src_file, p_dst_file); | ||
1463 | return ret; | ||
1464 | } | ||
1465 | |||
1466 | typedef void (*msm_dma_barrier_function_pointer) (void *, size_t); | ||
1467 | |||
1468 | static inline void msm_fb_dma_barrier_for_rect(struct fb_info *info, | ||
1469 | struct mdp_img *img, struct mdp_rect *rect, | ||
1470 | msm_dma_barrier_function_pointer dma_barrier_fp | ||
1471 | ) | ||
1472 | { | ||
1473 | /* | ||
1474 | * Compute the start and end addresses of the rectangles. | ||
1475 | * NOTE: As currently implemented, the data between | ||
1476 | * the end of one row and the start of the next is | ||
1477 | * included in the address range rather than | ||
1478 | * doing multiple calls for each row. | ||
1479 | */ | ||
1480 | |||
1481 | char * const pmem_start = info->screen_base; | ||
1482 | /* int bytes_per_pixel = mdp_get_bytes_per_pixel(img->format); | ||
1483 | unsigned long start = (unsigned long)pmem_start + img->offset + | ||
1484 | (img->width * rect->y + rect->x) * bytes_per_pixel; | ||
1485 | size_t size = ((rect->h - 1) * img->width + rect->w) * bytes_per_pixel; | ||
1486 | (*dma_barrier_fp) ((void *) start, size); | ||
1487 | */ | ||
1488 | panic("waaaaah"); | ||
1489 | } | ||
1490 | |||
1491 | static inline void msm_dma_nc_pre(void) | ||
1492 | { | ||
1493 | dmb(); | ||
1494 | } | ||
1495 | static inline void msm_dma_wt_pre(void) | ||
1496 | { | ||
1497 | dmb(); | ||
1498 | } | ||
1499 | static inline void msm_dma_todevice_wb_pre(void *start, size_t size) | ||
1500 | { | ||
1501 | #warning this | ||
1502 | // dma_cache_pre_ops(start, size, DMA_TO_DEVICE); | ||
1503 | } | ||
1504 | |||
1505 | static inline void msm_dma_fromdevice_wb_pre(void *start, size_t size) | ||
1506 | { | ||
1507 | #warning this | ||
1508 | // dma_cache_pre_ops(start, size, DMA_FROM_DEVICE); | ||
1509 | } | ||
1510 | |||
1511 | static inline void msm_dma_nc_post(void) | ||
1512 | { | ||
1513 | dmb(); | ||
1514 | } | ||
1515 | |||
1516 | static inline void msm_dma_fromdevice_wt_post(void *start, size_t size) | ||
1517 | { | ||
1518 | #warning this | ||
1519 | // dma_cache_post_ops(start, size, DMA_FROM_DEVICE); | ||
1520 | } | ||
1521 | |||
1522 | static inline void msm_dma_todevice_wb_post(void *start, size_t size) | ||
1523 | { | ||
1524 | #warning this | ||
1525 | // dma_cache_post_ops(start, size, DMA_TO_DEVICE); | ||
1526 | } | ||
1527 | |||
1528 | static inline void msm_dma_fromdevice_wb_post(void *start, size_t size) | ||
1529 | { | ||
1530 | #warning this | ||
1531 | // dma_cache_post_ops(start, size, DMA_FROM_DEVICE); | ||
1532 | } | ||
1533 | |||
1534 | /* | ||
1535 | * Do the write barriers required to guarantee data is committed to RAM | ||
1536 | * (from CPU cache or internal buffers) before a DMA operation starts. | ||
1537 | * NOTE: As currently implemented, the data between | ||
1538 | * the end of one row and the start of the next is | ||
1539 | * included in the address range rather than | ||
1540 | * doing multiple calls for each row. | ||
1541 | */ | ||
1542 | static void msm_fb_ensure_memory_coherency_before_dma(struct fb_info *info, | ||
1543 | struct mdp_blit_req *req_list, | ||
1544 | int req_list_count) | ||
1545 | { | ||
1546 | #ifdef CONFIG_ARCH_QSD8X50 | ||
1547 | int i; | ||
1548 | |||
1549 | /* | ||
1550 | * Normally, do the requested barriers for each address | ||
1551 | * range that corresponds to a rectangle. | ||
1552 | * | ||
1553 | * But if at least one write barrier is requested for data | ||
1554 | * going to or from the device but no address range is | ||
1555 | * needed for that barrier, then do the barrier, but do it | ||
1556 | * only once, no matter how many requests there are. | ||
1557 | */ | ||
1558 | struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; | ||
1559 | switch (mfd->mdp_fb_page_protection) { | ||
1560 | default: | ||
1561 | case MDP_FB_PAGE_PROTECTION_NONCACHED: | ||
1562 | case MDP_FB_PAGE_PROTECTION_WRITECOMBINE: | ||
1563 | /* | ||
1564 | * The following barrier is only done at most once, | ||
1565 | * since further calls would be redundant. | ||
1566 | */ | ||
1567 | for (i = 0; i < req_list_count; i++) { | ||
1568 | if (!(req_list[i].flags | ||
1569 | & MDP_NO_DMA_BARRIER_START)) { | ||
1570 | msm_dma_nc_pre(); | ||
1571 | break; | ||
1572 | } | ||
1573 | } | ||
1574 | break; | ||
1575 | |||
1576 | case MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE: | ||
1577 | /* | ||
1578 | * The following barrier is only done at most once, | ||
1579 | * since further calls would be redundant. | ||
1580 | */ | ||
1581 | for (i = 0; i < req_list_count; i++) { | ||
1582 | if (!(req_list[i].flags | ||
1583 | & MDP_NO_DMA_BARRIER_START)) { | ||
1584 | msm_dma_wt_pre(); | ||
1585 | break; | ||
1586 | } | ||
1587 | } | ||
1588 | break; | ||
1589 | |||
1590 | case MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE: | ||
1591 | case MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE: | ||
1592 | for (i = 0; i < req_list_count; i++) { | ||
1593 | if (!(req_list[i].flags & | ||
1594 | MDP_NO_DMA_BARRIER_START)) { | ||
1595 | |||
1596 | msm_fb_dma_barrier_for_rect(info, | ||
1597 | &(req_list[i].src), | ||
1598 | &(req_list[i].src_rect), | ||
1599 | msm_dma_todevice_wb_pre | ||
1600 | ); | ||
1601 | |||
1602 | msm_fb_dma_barrier_for_rect(info, | ||
1603 | &(req_list[i].dst), | ||
1604 | &(req_list[i].dst_rect), | ||
1605 | msm_dma_todevice_wb_pre | ||
1606 | ); | ||
1607 | } | ||
1608 | } | ||
1609 | break; | ||
1610 | } | ||
1611 | #else | ||
1612 | dmb(); | ||
1613 | #endif | ||
1614 | } | ||
1615 | |||
1616 | |||
1617 | /* | ||
1618 | * Do the write barriers required to guarantee data will be re-read from RAM by | ||
1619 | * the CPU after a DMA operation ends. | ||
1620 | * NOTE: As currently implemented, the data between | ||
1621 | * the end of one row and the start of the next is | ||
1622 | * included in the address range rather than | ||
1623 | * doing multiple calls for each row. | ||
1624 | */ | ||
1625 | static void msm_fb_ensure_memory_coherency_after_dma(struct fb_info *info, | ||
1626 | struct mdp_blit_req *req_list, | ||
1627 | int req_list_count) | ||
1628 | { | ||
1629 | #ifdef CONFIG_ARCH_QSD8X50 | ||
1630 | int i; | ||
1631 | |||
1632 | struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; | ||
1633 | switch (mfd->mdp_fb_page_protection) { | ||
1634 | default: | ||
1635 | case MDP_FB_PAGE_PROTECTION_NONCACHED: | ||
1636 | case MDP_FB_PAGE_PROTECTION_WRITECOMBINE: | ||
1637 | /* | ||
1638 | * The following barrier is only done at most once, | ||
1639 | * since further calls would be redundant. | ||
1640 | */ | ||
1641 | for (i = 0; i < req_list_count; i++) { | ||
1642 | if (!(req_list[i].flags | ||
1643 | & MDP_NO_DMA_BARRIER_END)) { | ||
1644 | msm_dma_nc_post(); | ||
1645 | break; | ||
1646 | } | ||
1647 | } | ||
1648 | break; | ||
1649 | |||
1650 | case MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE: | ||
1651 | for (i = 0; i < req_list_count; i++) { | ||
1652 | if (!(req_list[i].flags & | ||
1653 | MDP_NO_DMA_BARRIER_END)) { | ||
1654 | |||
1655 | msm_fb_dma_barrier_for_rect(info, | ||
1656 | &(req_list[i].dst), | ||
1657 | &(req_list[i].dst_rect), | ||
1658 | msm_dma_fromdevice_wt_post | ||
1659 | ); | ||
1660 | } | ||
1661 | } | ||
1662 | break; | ||
1663 | case MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE: | ||
1664 | case MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE: | ||
1665 | for (i = 0; i < req_list_count; i++) { | ||
1666 | if (!(req_list[i].flags & | ||
1667 | MDP_NO_DMA_BARRIER_END)) { | ||
1668 | |||
1669 | msm_fb_dma_barrier_for_rect(info, | ||
1670 | &(req_list[i].dst), | ||
1671 | &(req_list[i].dst_rect), | ||
1672 | msm_dma_fromdevice_wb_post | ||
1673 | ); | ||
1674 | } | ||
1675 | } | ||
1676 | break; | ||
1677 | } | ||
1678 | #else | ||
1679 | dmb(); | ||
1680 | #endif | ||
1681 | } | ||
1682 | |||
1683 | #ifdef CONFIG_MDP_PPP_ASYNC_OP | ||
1684 | void msm_fb_ensure_mem_coherency_after_dma(struct fb_info *info, | ||
1685 | struct mdp_blit_req *req_list, int req_list_count) | ||
1686 | { | ||
1687 | BUG_ON(!info); | ||
1688 | |||
1689 | /* | ||
1690 | * Ensure that CPU cache and other internal CPU state is | ||
1691 | * updated to reflect any change in memory modified by MDP blit | ||
1692 | * DMA. | ||
1693 | */ | ||
1694 | msm_fb_ensure_memory_coherency_after_dma(info, | ||
1695 | req_list, req_list_count); | ||
1696 | } | ||
1697 | |||
1698 | static int msmfb_async_blit(struct fb_info *info, void __user *p) | ||
1699 | { | ||
1700 | /* | ||
1701 | * CAUTION: The names of the struct types intentionally *DON'T* match | ||
1702 | * the names of the variables declared -- they appear to be swapped. | ||
1703 | * Read the code carefully and you should see that the variable names | ||
1704 | * make sense. | ||
1705 | */ | ||
1706 | const int MAX_LIST_WINDOW = 16; | ||
1707 | struct mdp_blit_req req_list[MAX_LIST_WINDOW]; | ||
1708 | struct mdp_blit_req_list req_list_header; | ||
1709 | |||
1710 | int count, i, req_list_count; | ||
1711 | |||
1712 | /* Get the count size for the total BLIT request. */ | ||
1713 | if (copy_from_user(&req_list_header, p, sizeof(req_list_header))) | ||
1714 | return -EFAULT; | ||
1715 | p += sizeof(req_list_header); | ||
1716 | count = req_list_header.count; | ||
1717 | while (count > 0) { | ||
1718 | /* | ||
1719 | * Access the requests through a narrow window to decrease copy | ||
1720 | * overhead and make larger requests accessible to the | ||
1721 | * coherency management code. | ||
1722 | * NOTE: The window size is intended to be larger than the | ||
1723 | * typical request size, but not require more than 2 | ||
1724 | * kbytes of stack storage. | ||
1725 | */ | ||
1726 | req_list_count = count; | ||
1727 | if (req_list_count > MAX_LIST_WINDOW) | ||
1728 | req_list_count = MAX_LIST_WINDOW; | ||
1729 | if (copy_from_user(&req_list, p, | ||
1730 | sizeof(struct mdp_blit_req)*req_list_count)) | ||
1731 | return -EFAULT; | ||
1732 | |||
1733 | /* | ||
1734 | * Ensure that any data CPU may have previously written to | ||
1735 | * internal state (but not yet committed to memory) is | ||
1736 | * guaranteed to be committed to memory now. | ||
1737 | */ | ||
1738 | msm_fb_ensure_memory_coherency_before_dma(info, | ||
1739 | req_list, req_list_count); | ||
1740 | |||
1741 | /* | ||
1742 | * Do the blit DMA, if required -- returning early only if | ||
1743 | * there is a failure. | ||
1744 | */ | ||
1745 | for (i = 0; i < req_list_count; i++) { | ||
1746 | if (!(req_list[i].flags & MDP_NO_BLIT)) { | ||
1747 | int ret = 0; | ||
1748 | struct mdp_ppp_djob *job = NULL; | ||
1749 | |||
1750 | if (unlikely(req_list[i].src_rect.h == 0 || | ||
1751 | req_list[i].src_rect.w == 0)) { | ||
1752 | MSM_FB_ERR("mpd_ppp: " | ||
1753 | "src img of zero size!\n"); | ||
1754 | return -EINVAL; | ||
1755 | } | ||
1756 | |||
1757 | if (unlikely(req_list[i].dst_rect.h == 0 || | ||
1758 | req_list[i].dst_rect.w == 0)) | ||
1759 | continue; | ||
1760 | |||
1761 | /* create a new display job */ | ||
1762 | job = mdp_ppp_new_djob(); | ||
1763 | if (unlikely(!job)) | ||
1764 | return -ENOMEM; | ||
1765 | |||
1766 | job->info = info; | ||
1767 | memcpy(&job->req, &req_list[i], | ||
1768 | sizeof(struct mdp_blit_req)); | ||
1769 | |||
1770 | /* Do the actual blit. */ | ||
1771 | ret = mdp_ppp_blit(info, &job->req, | ||
1772 | &job->p_src_file, &job->p_dst_file); | ||
1773 | |||
1774 | /* | ||
1775 | * Note that early returns don't guarantee | ||
1776 | * memory coherency. | ||
1777 | */ | ||
1778 | if (ret || mdp_ppp_get_ret_code()) { | ||
1779 | mdp_ppp_clear_curr_djob(); | ||
1780 | return ret; | ||
1781 | } | ||
1782 | } | ||
1783 | } | ||
1784 | |||
1785 | /* Go to next window of requests. */ | ||
1786 | count -= req_list_count; | ||
1787 | p += sizeof(struct mdp_blit_req)*req_list_count; | ||
1788 | } | ||
1789 | return 0; | ||
1790 | } | ||
1791 | #else | ||
1792 | |||
1793 | /* | ||
1794 | * NOTE: The userspace issues blit operations in a sequence, the sequence | ||
1795 | * start with a operation marked START and ends in an operation marked | ||
1796 | * END. It is guranteed by the userspace that all the blit operations | ||
1797 | * between START and END are only within the regions of areas designated | ||
1798 | * by the START and END operations and that the userspace doesnt modify | ||
1799 | * those areas. Hence it would be enough to perform barrier/cache operations | ||
1800 | * only on the START and END operations. | ||
1801 | */ | ||
1802 | static int msmfb_blit(struct fb_info *info, void __user *p) | ||
1803 | { | ||
1804 | /* | ||
1805 | * CAUTION: The names of the struct types intentionally *DON'T* match | ||
1806 | * the names of the variables declared -- they appear to be swapped. | ||
1807 | * Read the code carefully and you should see that the variable names | ||
1808 | * make sense. | ||
1809 | */ | ||
1810 | const int MAX_LIST_WINDOW = 16; | ||
1811 | struct mdp_blit_req req_list[MAX_LIST_WINDOW]; | ||
1812 | struct mdp_blit_req_list req_list_header; | ||
1813 | |||
1814 | int count, i, req_list_count; | ||
1815 | |||
1816 | /* Get the count size for the total BLIT request. */ | ||
1817 | if (copy_from_user(&req_list_header, p, sizeof(req_list_header))) | ||
1818 | return -EFAULT; | ||
1819 | p += sizeof(req_list_header); | ||
1820 | count = req_list_header.count; | ||
1821 | while (count > 0) { | ||
1822 | /* | ||
1823 | * Access the requests through a narrow window to decrease copy | ||
1824 | * overhead and make larger requests accessible to the | ||
1825 | * coherency management code. | ||
1826 | * NOTE: The window size is intended to be larger than the | ||
1827 | * typical request size, but not require more than 2 | ||
1828 | * kbytes of stack storage. | ||
1829 | */ | ||
1830 | req_list_count = count; | ||
1831 | if (req_list_count > MAX_LIST_WINDOW) | ||
1832 | req_list_count = MAX_LIST_WINDOW; | ||
1833 | if (copy_from_user(&req_list, p, | ||
1834 | sizeof(struct mdp_blit_req)*req_list_count)) | ||
1835 | return -EFAULT; | ||
1836 | |||
1837 | /* | ||
1838 | * Ensure that any data CPU may have previously written to | ||
1839 | * internal state (but not yet committed to memory) is | ||
1840 | * guaranteed to be committed to memory now. | ||
1841 | */ | ||
1842 | msm_fb_ensure_memory_coherency_before_dma(info, | ||
1843 | req_list, req_list_count); | ||
1844 | |||
1845 | /* | ||
1846 | * Do the blit DMA, if required -- returning early only if | ||
1847 | * there is a failure. | ||
1848 | */ | ||
1849 | for (i = 0; i < req_list_count; i++) { | ||
1850 | if (!(req_list[i].flags & MDP_NO_BLIT)) { | ||
1851 | /* Do the actual blit. */ | ||
1852 | int ret = mdp_blit(info, &(req_list[i])); | ||
1853 | |||
1854 | /* | ||
1855 | * Note that early returns don't guarantee | ||
1856 | * memory coherency. | ||
1857 | */ | ||
1858 | if (ret) | ||
1859 | return ret; | ||
1860 | } | ||
1861 | } | ||
1862 | |||
1863 | /* | ||
1864 | * Ensure that CPU cache and other internal CPU state is | ||
1865 | * updated to reflect any change in memory modified by MDP blit | ||
1866 | * DMA. | ||
1867 | */ | ||
1868 | msm_fb_ensure_memory_coherency_after_dma(info, | ||
1869 | req_list, | ||
1870 | req_list_count); | ||
1871 | |||
1872 | /* Go to next window of requests. */ | ||
1873 | count -= req_list_count; | ||
1874 | p += sizeof(struct mdp_blit_req)*req_list_count; | ||
1875 | } | ||
1876 | return 0; | ||
1877 | } | ||
1878 | #endif | ||
1879 | |||
1880 | #ifdef CONFIG_FB_MSM_OVERLAY | ||
1881 | static int msmfb_overlay_get(struct fb_info *info, void __user *p) | ||
1882 | { | ||
1883 | struct mdp_overlay req; | ||
1884 | int ret; | ||
1885 | |||
1886 | if (copy_from_user(&req, p, sizeof(req))) | ||
1887 | return -EFAULT; | ||
1888 | |||
1889 | ret = mdp4_overlay_get(info, &req); | ||
1890 | if (ret) { | ||
1891 | printk(KERN_ERR "%s: ioctl failed \n", | ||
1892 | __func__); | ||
1893 | return ret; | ||
1894 | } | ||
1895 | if (copy_to_user(p, &req, sizeof(req))) { | ||
1896 | printk(KERN_ERR "%s: copy2user failed \n", | ||
1897 | __func__); | ||
1898 | return -EFAULT; | ||
1899 | } | ||
1900 | |||
1901 | return 0; | ||
1902 | } | ||
1903 | |||
1904 | static int msmfb_overlay_set(struct fb_info *info, void __user *p) | ||
1905 | { | ||
1906 | struct mdp_overlay req; | ||
1907 | int ret; | ||
1908 | |||
1909 | if (copy_from_user(&req, p, sizeof(req))) | ||
1910 | return -EFAULT; | ||
1911 | |||
1912 | ret = mdp4_overlay_set(info, &req); | ||
1913 | if (ret) { | ||
1914 | printk(KERN_ERR "%s:ioctl failed \n", | ||
1915 | __func__); | ||
1916 | return ret; | ||
1917 | } | ||
1918 | |||
1919 | if (copy_to_user(p, &req, sizeof(req))) { | ||
1920 | printk(KERN_ERR "%s: copy2user failed \n", | ||
1921 | __func__); | ||
1922 | return -EFAULT; | ||
1923 | } | ||
1924 | |||
1925 | return 0; | ||
1926 | } | ||
1927 | |||
1928 | static int msmfb_overlay_unset(struct fb_info *info, unsigned long *argp) | ||
1929 | { | ||
1930 | int ret, ndx; | ||
1931 | |||
1932 | ret = copy_from_user(&ndx, argp, sizeof(ndx)); | ||
1933 | if (ret) { | ||
1934 | printk(KERN_ERR "%s:msmfb_overlay_unset ioctl failed \n", | ||
1935 | __func__); | ||
1936 | return ret; | ||
1937 | } | ||
1938 | |||
1939 | return mdp4_overlay_unset(info, ndx); | ||
1940 | } | ||
1941 | |||
1942 | static int msmfb_overlay_play(struct fb_info *info, unsigned long *argp) | ||
1943 | { | ||
1944 | int ret; | ||
1945 | struct msmfb_overlay_data req; | ||
1946 | struct file *p_src_file = 0; | ||
1947 | |||
1948 | ret = copy_from_user(&req, argp, sizeof(req)); | ||
1949 | if (ret) { | ||
1950 | printk(KERN_ERR "%s:msmfb_overlay_play ioctl failed \n", | ||
1951 | __func__); | ||
1952 | return ret; | ||
1953 | } | ||
1954 | |||
1955 | ret = mdp4_overlay_play(info, &req, &p_src_file); | ||
1956 | |||
1957 | if (p_src_file) | ||
1958 | put_pmem_file(p_src_file); | ||
1959 | |||
1960 | return ret; | ||
1961 | } | ||
1962 | |||
1963 | #endif | ||
1964 | |||
1965 | DECLARE_MUTEX(msm_fb_ioctl_ppp_sem); | ||
1966 | DEFINE_MUTEX(msm_fb_ioctl_lut_sem); | ||
1967 | DEFINE_MUTEX(msm_fb_ioctl_hist_sem); | ||
1968 | |||
1969 | /* Set color conversion matrix from user space */ | ||
1970 | |||
1971 | #ifndef CONFIG_FB_MSM_MDP40 | ||
1972 | static void msmfb_set_color_conv(struct mdp_ccs *p) | ||
1973 | { | ||
1974 | int i; | ||
1975 | |||
1976 | if (p->direction == MDP_CCS_RGB2YUV) { | ||
1977 | /* MDP cmd block enable */ | ||
1978 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); | ||
1979 | |||
1980 | /* RGB->YUV primary forward matrix */ | ||
1981 | for (i = 0; i < MDP_CCS_SIZE; i++) | ||
1982 | writel(p->ccs[i], MDP_CSC_PFMVn(i)); | ||
1983 | |||
1984 | #ifdef CONFIG_FB_MSM_MDP31 | ||
1985 | for (i = 0; i < MDP_BV_SIZE; i++) | ||
1986 | writel(p->bv[i], MDP_CSC_POST_BV2n(i)); | ||
1987 | #endif | ||
1988 | |||
1989 | /* MDP cmd block disable */ | ||
1990 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); | ||
1991 | } else { | ||
1992 | /* MDP cmd block enable */ | ||
1993 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); | ||
1994 | |||
1995 | /* YUV->RGB primary reverse matrix */ | ||
1996 | for (i = 0; i < MDP_CCS_SIZE; i++) | ||
1997 | writel(p->ccs[i], MDP_CSC_PRMVn(i)); | ||
1998 | for (i = 0; i < MDP_BV_SIZE; i++) | ||
1999 | writel(p->bv[i], MDP_CSC_PRE_BV1n(i)); | ||
2000 | |||
2001 | /* MDP cmd block disable */ | ||
2002 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); | ||
2003 | } | ||
2004 | } | ||
2005 | #endif | ||
2006 | |||
2007 | |||
2008 | static int msm_fb_ioctl(struct fb_info *info, unsigned int cmd, | ||
2009 | unsigned long arg) | ||
2010 | { | ||
2011 | struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; | ||
2012 | void __user *argp = (void __user *)arg; | ||
2013 | struct fb_cursor cursor; | ||
2014 | struct fb_cmap cmap; | ||
2015 | struct mdp_histogram hist; | ||
2016 | #ifndef CONFIG_FB_MSM_MDP40 | ||
2017 | struct mdp_ccs ccs_matrix; | ||
2018 | #endif | ||
2019 | struct mdp_page_protection fb_page_protection; | ||
2020 | int ret = 0; | ||
2021 | |||
2022 | if (!mfd->op_enable) | ||
2023 | return -EPERM; | ||
2024 | |||
2025 | switch (cmd) { | ||
2026 | #ifdef CONFIG_FB_MSM_OVERLAY | ||
2027 | case MSMFB_OVERLAY_GET: | ||
2028 | down(&msm_fb_ioctl_ppp_sem); | ||
2029 | ret = msmfb_overlay_get(info, argp); | ||
2030 | up(&msm_fb_ioctl_ppp_sem); | ||
2031 | break; | ||
2032 | case MSMFB_OVERLAY_SET: | ||
2033 | down(&msm_fb_ioctl_ppp_sem); | ||
2034 | ret = msmfb_overlay_set(info, argp); | ||
2035 | up(&msm_fb_ioctl_ppp_sem); | ||
2036 | break; | ||
2037 | case MSMFB_OVERLAY_UNSET: | ||
2038 | down(&msm_fb_ioctl_ppp_sem); | ||
2039 | ret = msmfb_overlay_unset(info, argp); | ||
2040 | up(&msm_fb_ioctl_ppp_sem); | ||
2041 | break; | ||
2042 | case MSMFB_OVERLAY_PLAY: | ||
2043 | down(&msm_fb_ioctl_ppp_sem); | ||
2044 | ret = msmfb_overlay_play(info, argp); | ||
2045 | up(&msm_fb_ioctl_ppp_sem); | ||
2046 | break; | ||
2047 | #endif | ||
2048 | case MSMFB_BLIT: | ||
2049 | down(&msm_fb_ioctl_ppp_sem); | ||
2050 | #ifdef CONFIG_MDP_PPP_ASYNC_OP | ||
2051 | ret = msmfb_async_blit(info, argp); | ||
2052 | mdp_ppp_wait(); /* Wait for all blits to be finished. */ | ||
2053 | #else | ||
2054 | ret = msmfb_blit(info, argp); | ||
2055 | #endif | ||
2056 | up(&msm_fb_ioctl_ppp_sem); | ||
2057 | |||
2058 | break; | ||
2059 | |||
2060 | /* Ioctl for setting ccs matrix from user space */ | ||
2061 | case MSMFB_SET_CCS_MATRIX: | ||
2062 | #ifndef CONFIG_FB_MSM_MDP40 | ||
2063 | ret = copy_from_user(&ccs_matrix, argp, sizeof(ccs_matrix)); | ||
2064 | if (ret) { | ||
2065 | printk(KERN_ERR | ||
2066 | "%s:MSMFB_SET_CCS_MATRIX ioctl failed \n", | ||
2067 | __func__); | ||
2068 | return ret; | ||
2069 | } | ||
2070 | |||
2071 | down(&msm_fb_ioctl_ppp_sem); | ||
2072 | if (ccs_matrix.direction == MDP_CCS_RGB2YUV) | ||
2073 | mdp_ccs_rgb2yuv = ccs_matrix; | ||
2074 | else | ||
2075 | mdp_ccs_yuv2rgb = ccs_matrix; | ||
2076 | |||
2077 | msmfb_set_color_conv(&ccs_matrix) ; | ||
2078 | up(&msm_fb_ioctl_ppp_sem); | ||
2079 | #else | ||
2080 | ret = -EINVAL; | ||
2081 | #endif | ||
2082 | |||
2083 | break; | ||
2084 | |||
2085 | /* Ioctl for getting ccs matrix to user space */ | ||
2086 | case MSMFB_GET_CCS_MATRIX: | ||
2087 | #ifndef CONFIG_FB_MSM_MDP40 | ||
2088 | ret = copy_from_user(&ccs_matrix, argp, sizeof(ccs_matrix)) ; | ||
2089 | if (ret) { | ||
2090 | printk(KERN_ERR | ||
2091 | "%s:MSMFB_GET_CCS_MATRIX ioctl failed \n", | ||
2092 | __func__); | ||
2093 | return ret; | ||
2094 | } | ||
2095 | |||
2096 | down(&msm_fb_ioctl_ppp_sem); | ||
2097 | if (ccs_matrix.direction == MDP_CCS_RGB2YUV) | ||
2098 | ccs_matrix = mdp_ccs_rgb2yuv; | ||
2099 | else | ||
2100 | ccs_matrix = mdp_ccs_yuv2rgb; | ||
2101 | |||
2102 | ret = copy_to_user(argp, &ccs_matrix, sizeof(ccs_matrix)); | ||
2103 | |||
2104 | if (ret) { | ||
2105 | printk(KERN_ERR | ||
2106 | "%s:MSMFB_GET_CCS_MATRIX ioctl failed \n", | ||
2107 | __func__); | ||
2108 | return ret ; | ||
2109 | } | ||
2110 | up(&msm_fb_ioctl_ppp_sem); | ||
2111 | #else | ||
2112 | ret = -EINVAL; | ||
2113 | #endif | ||
2114 | |||
2115 | break; | ||
2116 | |||
2117 | #ifdef CONFIG_MDP_PPP_ASYNC_OP | ||
2118 | case MSMFB_ASYNC_BLIT: | ||
2119 | down(&msm_fb_ioctl_ppp_sem); | ||
2120 | ret = msmfb_async_blit(info, argp); | ||
2121 | up(&msm_fb_ioctl_ppp_sem); | ||
2122 | break; | ||
2123 | |||
2124 | case MSMFB_BLIT_FLUSH: | ||
2125 | down(&msm_fb_ioctl_ppp_sem); | ||
2126 | mdp_ppp_wait(); | ||
2127 | up(&msm_fb_ioctl_ppp_sem); | ||
2128 | break; | ||
2129 | #endif | ||
2130 | |||
2131 | case MSMFB_GRP_DISP: | ||
2132 | #ifdef CONFIG_FB_MSM_MDP22 | ||
2133 | { | ||
2134 | unsigned long grp_id; | ||
2135 | |||
2136 | ret = copy_from_user(&grp_id, argp, sizeof(grp_id)); | ||
2137 | if (ret) | ||
2138 | return ret; | ||
2139 | |||
2140 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); | ||
2141 | writel(grp_id, MDP_FULL_BYPASS_WORD43); | ||
2142 | mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, | ||
2143 | FALSE); | ||
2144 | break; | ||
2145 | } | ||
2146 | #else | ||
2147 | return -EFAULT; | ||
2148 | #endif | ||
2149 | case MSMFB_SUSPEND_SW_REFRESHER: | ||
2150 | if (!mfd->panel_power_on) | ||
2151 | return -EPERM; | ||
2152 | |||
2153 | mfd->sw_refreshing_enable = FALSE; | ||
2154 | ret = msm_fb_stop_sw_refresher(mfd); | ||
2155 | break; | ||
2156 | |||
2157 | case MSMFB_RESUME_SW_REFRESHER: | ||
2158 | if (!mfd->panel_power_on) | ||
2159 | return -EPERM; | ||
2160 | |||
2161 | mfd->sw_refreshing_enable = TRUE; | ||
2162 | ret = msm_fb_resume_sw_refresher(mfd); | ||
2163 | break; | ||
2164 | |||
2165 | case MSMFB_CURSOR: | ||
2166 | ret = copy_from_user(&cursor, argp, sizeof(cursor)); | ||
2167 | if (ret) | ||
2168 | return ret; | ||
2169 | |||
2170 | ret = msm_fb_cursor(info, &cursor); | ||
2171 | break; | ||
2172 | |||
2173 | case MSMFB_SET_LUT: | ||
2174 | ret = copy_from_user(&cmap, argp, sizeof(cmap)); | ||
2175 | if (ret) | ||
2176 | return ret; | ||
2177 | |||
2178 | mutex_lock(&msm_fb_ioctl_lut_sem); | ||
2179 | ret = msm_fb_set_lut(&cmap, info); | ||
2180 | mutex_unlock(&msm_fb_ioctl_lut_sem); | ||
2181 | break; | ||
2182 | |||
2183 | case MSMFB_HISTOGRAM: | ||
2184 | if (!mfd->do_histogram) | ||
2185 | return -ENODEV; | ||
2186 | |||
2187 | ret = copy_from_user(&hist, argp, sizeof(hist)); | ||
2188 | if (ret) | ||
2189 | return ret; | ||
2190 | |||
2191 | mutex_lock(&msm_fb_ioctl_hist_sem); | ||
2192 | ret = mfd->do_histogram(info, &hist); | ||
2193 | mutex_unlock(&msm_fb_ioctl_hist_sem); | ||
2194 | break; | ||
2195 | |||
2196 | case MSMFB_GET_PAGE_PROTECTION: | ||
2197 | fb_page_protection.page_protection | ||
2198 | = mfd->mdp_fb_page_protection; | ||
2199 | ret = copy_to_user(argp, &fb_page_protection, | ||
2200 | sizeof(fb_page_protection)); | ||
2201 | if (ret) | ||
2202 | return ret; | ||
2203 | break; | ||
2204 | |||
2205 | case MSMFB_SET_PAGE_PROTECTION: | ||
2206 | #ifdef CONFIG_ARCH_QSD8X50 | ||
2207 | ret = copy_from_user(&fb_page_protection, argp, | ||
2208 | sizeof(fb_page_protection)); | ||
2209 | if (ret) | ||
2210 | return ret; | ||
2211 | |||
2212 | /* Validate the proposed page protection settings. */ | ||
2213 | switch (fb_page_protection.page_protection) { | ||
2214 | case MDP_FB_PAGE_PROTECTION_NONCACHED: | ||
2215 | case MDP_FB_PAGE_PROTECTION_WRITECOMBINE: | ||
2216 | case MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE: | ||
2217 | /* Write-back cache (read allocate) */ | ||
2218 | case MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE: | ||
2219 | /* Write-back cache (write allocate) */ | ||
2220 | case MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE: | ||
2221 | mfd->mdp_fb_page_protection = | ||
2222 | fb_page_protection.page_protection; | ||
2223 | break; | ||
2224 | default: | ||
2225 | ret = -EINVAL; | ||
2226 | break; | ||
2227 | } | ||
2228 | #else | ||
2229 | /* | ||
2230 | * Don't allow caching until 7k DMA cache operations are | ||
2231 | * available. | ||
2232 | */ | ||
2233 | ret = -EINVAL; | ||
2234 | #endif | ||
2235 | break; | ||
2236 | |||
2237 | default: | ||
2238 | MSM_FB_INFO("MDP: unknown ioctl (cmd=%d) received!\n", cmd); | ||
2239 | ret = -EINVAL; | ||
2240 | break; | ||
2241 | } | ||
2242 | |||
2243 | return ret; | ||
2244 | } | ||
2245 | |||
2246 | static int msm_fb_register_driver(void) | ||
2247 | { | ||
2248 | return platform_driver_register(&msm_fb_driver); | ||
2249 | } | ||
2250 | |||
2251 | void msm_fb_add_device(struct platform_device *pdev) | ||
2252 | { | ||
2253 | struct msm_fb_panel_data *pdata; | ||
2254 | struct platform_device *this_dev = NULL; | ||
2255 | struct fb_info *fbi; | ||
2256 | struct msm_fb_data_type *mfd = NULL; | ||
2257 | u32 type, id, fb_num; | ||
2258 | |||
2259 | if (!pdev) | ||
2260 | return; | ||
2261 | id = pdev->id; | ||
2262 | |||
2263 | pdata = pdev->dev.platform_data; | ||
2264 | if (!pdata) | ||
2265 | return; | ||
2266 | type = pdata->panel_info.type; | ||
2267 | fb_num = pdata->panel_info.fb_num; | ||
2268 | |||
2269 | if (fb_num <= 0) | ||
2270 | return; | ||
2271 | |||
2272 | if (fbi_list_index >= MAX_FBI_LIST) { | ||
2273 | printk(KERN_ERR "msm_fb: no more framebuffer info list!\n"); | ||
2274 | return; | ||
2275 | } | ||
2276 | /* | ||
2277 | * alloc panel device data | ||
2278 | */ | ||
2279 | this_dev = msm_fb_device_alloc(pdata, type, id); | ||
2280 | |||
2281 | if (!this_dev) { | ||
2282 | printk(KERN_ERR | ||
2283 | "%s: msm_fb_device_alloc failed!\n", __func__); | ||
2284 | return; | ||
2285 | } | ||
2286 | |||
2287 | /* | ||
2288 | * alloc framebuffer info + par data | ||
2289 | */ | ||
2290 | fbi = framebuffer_alloc(sizeof(struct msm_fb_data_type), NULL); | ||
2291 | if (fbi == NULL) { | ||
2292 | platform_device_put(this_dev); | ||
2293 | printk(KERN_ERR "msm_fb: can't alloca framebuffer info data!\n"); | ||
2294 | return; | ||
2295 | } | ||
2296 | |||
2297 | mfd = (struct msm_fb_data_type *)fbi->par; | ||
2298 | mfd->key = MFD_KEY; | ||
2299 | mfd->fbi = fbi; | ||
2300 | mfd->panel.type = type; | ||
2301 | mfd->panel.id = id; | ||
2302 | mfd->fb_page = fb_num; | ||
2303 | mfd->index = fbi_list_index; | ||
2304 | mfd->mdp_fb_page_protection = MDP_FB_PAGE_PROTECTION_WRITECOMBINE; | ||
2305 | |||
2306 | /* link to the latest pdev */ | ||
2307 | mfd->pdev = this_dev; | ||
2308 | |||
2309 | mfd_list[mfd_list_index++] = mfd; | ||
2310 | fbi_list[fbi_list_index++] = fbi; | ||
2311 | |||
2312 | /* | ||
2313 | * set driver data | ||
2314 | */ | ||
2315 | platform_set_drvdata(this_dev, mfd); | ||
2316 | |||
2317 | if (platform_device_add(this_dev)) { | ||
2318 | printk(KERN_ERR "msm_fb: platform_device_add failed!\n"); | ||
2319 | platform_device_put(this_dev); | ||
2320 | framebuffer_release(fbi); | ||
2321 | fbi_list_index--; | ||
2322 | return; | ||
2323 | } | ||
2324 | } | ||
2325 | EXPORT_SYMBOL(msm_fb_add_device); | ||
2326 | |||
2327 | int __init msm_fb_init(void) | ||
2328 | { | ||
2329 | int rc = -ENODEV; | ||
2330 | |||
2331 | if (msm_fb_register_driver()) | ||
2332 | return rc; | ||
2333 | |||
2334 | #ifdef MSM_FB_ENABLE_DBGFS | ||
2335 | { | ||
2336 | struct dentry *root; | ||
2337 | |||
2338 | if ((root = msm_fb_get_debugfs_root()) != NULL) { | ||
2339 | msm_fb_debugfs_file_create(root, | ||
2340 | "msm_fb_msg_printing_level", | ||
2341 | (u32 *) &msm_fb_msg_level); | ||
2342 | msm_fb_debugfs_file_create(root, | ||
2343 | "mddi_msg_printing_level", | ||
2344 | (u32 *) &mddi_msg_level); | ||
2345 | msm_fb_debugfs_file_create(root, "msm_fb_debug_enabled", | ||
2346 | (u32 *) &msm_fb_debug_enabled); | ||
2347 | } | ||
2348 | } | ||
2349 | #endif | ||
2350 | |||
2351 | return 0; | ||
2352 | } | ||
2353 | |||
2354 | module_init(msm_fb_init); | ||
diff --git a/drivers/staging/msm/msm_fb.h b/drivers/staging/msm/msm_fb.h new file mode 100644 index 000000000000..f93913800475 --- /dev/null +++ b/drivers/staging/msm/msm_fb.h | |||
@@ -0,0 +1,174 @@ | |||
1 | /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * Redistribution and use in source and binary forms, with or without | ||
4 | * modification, are permitted provided that the following conditions are met: | ||
5 | * * Redistributions of source code must retain the above copyright | ||
6 | * notice, this list of conditions and the following disclaimer. | ||
7 | * * Redistributions in binary form must reproduce the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer in the | ||
9 | * documentation and/or other materials provided with the distribution. | ||
10 | * * Neither the name of Code Aurora nor | ||
11 | * the names of its contributors may be used to endorse or promote | ||
12 | * products derived from this software without specific prior written | ||
13 | * permission. | ||
14 | * | ||
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
17 | * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
18 | * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||
19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||
20 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||
21 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | ||
22 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | ||
23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||
24 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | ||
25 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | * | ||
27 | */ | ||
28 | |||
29 | #ifndef MSM_FB_H | ||
30 | #define MSM_FB_H | ||
31 | |||
32 | #include <linux/module.h> | ||
33 | #include <linux/kernel.h> | ||
34 | #include <linux/sched.h> | ||
35 | #include <linux/time.h> | ||
36 | #include <linux/init.h> | ||
37 | #include <linux/interrupt.h> | ||
38 | #include "linux/proc_fs.h" | ||
39 | |||
40 | #include <mach/hardware.h> | ||
41 | #include <linux/io.h> | ||
42 | #include <mach/board.h> | ||
43 | |||
44 | #include <asm/system.h> | ||
45 | #include <asm/mach-types.h> | ||
46 | #include <mach/memory.h> | ||
47 | #include <linux/semaphore.h> | ||
48 | #include <linux/spinlock.h> | ||
49 | #include <linux/workqueue.h> | ||
50 | #include <linux/hrtimer.h> | ||
51 | |||
52 | #include <linux/fb.h> | ||
53 | |||
54 | #ifdef CONFIG_HAS_EARLYSUSPEND | ||
55 | #include <linux/earlysuspend.h> | ||
56 | #endif | ||
57 | |||
58 | #include "msm_fb_panel.h" | ||
59 | #include "mdp.h" | ||
60 | |||
61 | #define MSM_FB_DEFAULT_PAGE_SIZE 2 | ||
62 | #define MFD_KEY 0x11161126 | ||
63 | #define MSM_FB_MAX_DEV_LIST 32 | ||
64 | |||
65 | struct disp_info_type_suspend { | ||
66 | boolean op_enable; | ||
67 | boolean sw_refreshing_enable; | ||
68 | boolean panel_power_on; | ||
69 | }; | ||
70 | |||
71 | struct msm_fb_data_type { | ||
72 | __u32 key; | ||
73 | __u32 index; | ||
74 | __u32 ref_cnt; | ||
75 | __u32 fb_page; | ||
76 | |||
77 | panel_id_type panel; | ||
78 | struct msm_panel_info panel_info; | ||
79 | |||
80 | DISP_TARGET dest; | ||
81 | struct fb_info *fbi; | ||
82 | |||
83 | boolean op_enable; | ||
84 | uint32 fb_imgType; | ||
85 | boolean sw_currently_refreshing; | ||
86 | boolean sw_refreshing_enable; | ||
87 | boolean hw_refresh; | ||
88 | |||
89 | MDPIBUF ibuf; | ||
90 | boolean ibuf_flushed; | ||
91 | struct timer_list refresh_timer; | ||
92 | struct completion refresher_comp; | ||
93 | |||
94 | boolean pan_waiting; | ||
95 | struct completion pan_comp; | ||
96 | |||
97 | /* vsync */ | ||
98 | boolean use_mdp_vsync; | ||
99 | __u32 vsync_gpio; | ||
100 | __u32 total_lcd_lines; | ||
101 | __u32 total_porch_lines; | ||
102 | __u32 lcd_ref_usec_time; | ||
103 | __u32 refresh_timer_duration; | ||
104 | |||
105 | struct hrtimer dma_hrtimer; | ||
106 | |||
107 | boolean panel_power_on; | ||
108 | struct work_struct dma_update_worker; | ||
109 | struct semaphore sem; | ||
110 | |||
111 | struct timer_list vsync_resync_timer; | ||
112 | boolean vsync_handler_pending; | ||
113 | struct work_struct vsync_resync_worker; | ||
114 | |||
115 | ktime_t last_vsync_timetick; | ||
116 | |||
117 | __u32 *vsync_width_boundary; | ||
118 | |||
119 | unsigned int pmem_id; | ||
120 | struct disp_info_type_suspend suspend; | ||
121 | |||
122 | __u32 channel_irq; | ||
123 | |||
124 | struct mdp_dma_data *dma; | ||
125 | void (*dma_fnc) (struct msm_fb_data_type *mfd); | ||
126 | int (*cursor_update) (struct fb_info *info, | ||
127 | struct fb_cursor *cursor); | ||
128 | int (*lut_update) (struct fb_info *info, | ||
129 | struct fb_cmap *cmap); | ||
130 | int (*do_histogram) (struct fb_info *info, | ||
131 | struct mdp_histogram *hist); | ||
132 | void *cursor_buf; | ||
133 | void *cursor_buf_phys; | ||
134 | |||
135 | void *cmd_port; | ||
136 | void *data_port; | ||
137 | void *data_port_phys; | ||
138 | |||
139 | __u32 bl_level; | ||
140 | |||
141 | struct platform_device *pdev; | ||
142 | |||
143 | __u32 var_xres; | ||
144 | __u32 var_yres; | ||
145 | __u32 var_pixclock; | ||
146 | |||
147 | #ifdef MSM_FB_ENABLE_DBGFS | ||
148 | struct dentry *sub_dir; | ||
149 | #endif | ||
150 | |||
151 | #ifdef CONFIG_HAS_EARLYSUSPEND | ||
152 | struct early_suspend early_suspend; | ||
153 | struct early_suspend mddi_early_suspend; | ||
154 | struct early_suspend mddi_ext_early_suspend; | ||
155 | #endif | ||
156 | u32 mdp_fb_page_protection; | ||
157 | int allow_set_offset; | ||
158 | }; | ||
159 | |||
160 | struct dentry *msm_fb_get_debugfs_root(void); | ||
161 | void msm_fb_debugfs_file_create(struct dentry *root, const char *name, | ||
162 | u32 *var); | ||
163 | void msm_fb_set_backlight(struct msm_fb_data_type *mfd, __u32 bkl_lvl, | ||
164 | u32 save); | ||
165 | |||
166 | void msm_fb_add_device(struct platform_device *pdev); | ||
167 | |||
168 | int msm_fb_detect_client(const char *name); | ||
169 | |||
170 | #ifdef CONFIG_FB_BACKLIGHT | ||
171 | void msm_fb_config_backlight(struct msm_fb_data_type *mfd); | ||
172 | #endif | ||
173 | |||
174 | #endif /* MSM_FB_H */ | ||
diff --git a/drivers/staging/msm/msm_fb_bl.c b/drivers/staging/msm/msm_fb_bl.c new file mode 100644 index 000000000000..033fc9486e01 --- /dev/null +++ b/drivers/staging/msm/msm_fb_bl.c | |||
@@ -0,0 +1,79 @@ | |||
1 | /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/moduleparam.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <linux/fb.h> | ||
23 | #include <linux/string.h> | ||
24 | #include <linux/version.h> | ||
25 | #include <linux/backlight.h> | ||
26 | |||
27 | #include "msm_fb.h" | ||
28 | |||
29 | static int msm_fb_bl_get_brightness(struct backlight_device *pbd) | ||
30 | { | ||
31 | return pbd->props.brightness; | ||
32 | } | ||
33 | |||
34 | static int msm_fb_bl_update_status(struct backlight_device *pbd) | ||
35 | { | ||
36 | struct msm_fb_data_type *mfd = bl_get_data(pbd); | ||
37 | __u32 bl_lvl; | ||
38 | |||
39 | bl_lvl = pbd->props.brightness; | ||
40 | bl_lvl = mfd->fbi->bl_curve[bl_lvl]; | ||
41 | msm_fb_set_backlight(mfd, bl_lvl, 1); | ||
42 | return 0; | ||
43 | } | ||
44 | |||
45 | static struct backlight_ops msm_fb_bl_ops = { | ||
46 | .get_brightness = msm_fb_bl_get_brightness, | ||
47 | .update_status = msm_fb_bl_update_status, | ||
48 | }; | ||
49 | |||
50 | void msm_fb_config_backlight(struct msm_fb_data_type *mfd) | ||
51 | { | ||
52 | struct msm_fb_panel_data *pdata; | ||
53 | struct backlight_device *pbd; | ||
54 | struct fb_info *fbi; | ||
55 | char name[16]; | ||
56 | |||
57 | fbi = mfd->fbi; | ||
58 | pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data; | ||
59 | |||
60 | if ((pdata) && (pdata->set_backlight)) { | ||
61 | snprintf(name, sizeof(name), "msmfb_bl%d", mfd->index); | ||
62 | pbd = | ||
63 | backlight_device_register(name, fbi->dev, mfd, | ||
64 | &msm_fb_bl_ops); | ||
65 | if (!IS_ERR(pbd)) { | ||
66 | fbi->bl_dev = pbd; | ||
67 | fb_bl_default_curve(fbi, | ||
68 | 0, | ||
69 | mfd->panel_info.bl_min, | ||
70 | mfd->panel_info.bl_max); | ||
71 | pbd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1; | ||
72 | pbd->props.brightness = FB_BACKLIGHT_LEVELS - 1; | ||
73 | backlight_update_status(pbd); | ||
74 | } else { | ||
75 | fbi->bl_dev = NULL; | ||
76 | printk(KERN_ERR "msm_fb: backlight_device_register failed!\n"); | ||
77 | } | ||
78 | } | ||
79 | } | ||
diff --git a/drivers/staging/msm/msm_fb_def.h b/drivers/staging/msm/msm_fb_def.h new file mode 100644 index 000000000000..6de440937422 --- /dev/null +++ b/drivers/staging/msm/msm_fb_def.h | |||
@@ -0,0 +1,201 @@ | |||
1 | /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * Redistribution and use in source and binary forms, with or without | ||
4 | * modification, are permitted provided that the following conditions are met: | ||
5 | * * Redistributions of source code must retain the above copyright | ||
6 | * notice, this list of conditions and the following disclaimer. | ||
7 | * * Redistributions in binary form must reproduce the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer in the | ||
9 | * documentation and/or other materials provided with the distribution. | ||
10 | * * Neither the name of Code Aurora nor | ||
11 | * the names of its contributors may be used to endorse or promote | ||
12 | * products derived from this software without specific prior written | ||
13 | * permission. | ||
14 | * | ||
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
17 | * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
18 | * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||
19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||
20 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||
21 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | ||
22 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | ||
23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||
24 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | ||
25 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | * | ||
27 | */ | ||
28 | |||
29 | #ifndef MSM_FB_DEF_H | ||
30 | #define MSM_FB_DEF_H | ||
31 | |||
32 | #include <linux/module.h> | ||
33 | #include <linux/moduleparam.h> | ||
34 | #include <linux/kernel.h> | ||
35 | #include <linux/slab.h> | ||
36 | #include <linux/delay.h> | ||
37 | #include <linux/mm.h> | ||
38 | #include <linux/fb.h> | ||
39 | #include "msm_mdp.h" | ||
40 | #include <linux/init.h> | ||
41 | #include <linux/ioport.h> | ||
42 | #include <linux/device.h> | ||
43 | #include <linux/dma-mapping.h> | ||
44 | #include <linux/uaccess.h> | ||
45 | #include <linux/workqueue.h> | ||
46 | #include <linux/string.h> | ||
47 | #include <linux/version.h> | ||
48 | #include <linux/proc_fs.h> | ||
49 | #include <linux/vmalloc.h> | ||
50 | #include <linux/debugfs.h> | ||
51 | #include <linux/console.h> | ||
52 | |||
53 | #include <linux/kernel.h> | ||
54 | #include <linux/sched.h> | ||
55 | #include <linux/time.h> | ||
56 | #include <linux/init.h> | ||
57 | #include <linux/interrupt.h> | ||
58 | #include "linux/proc_fs.h" | ||
59 | #include <mach/hardware.h> | ||
60 | #include <linux/io.h> | ||
61 | #include <linux/fb.h> | ||
62 | #include <asm/system.h> | ||
63 | #include <asm/mach-types.h> | ||
64 | #include <linux/platform_device.h> | ||
65 | |||
66 | typedef s64 int64; | ||
67 | typedef s32 int32; | ||
68 | typedef s16 int16; | ||
69 | typedef s8 int8; | ||
70 | |||
71 | typedef u64 uint64; | ||
72 | typedef u32 uint32; | ||
73 | typedef u16 uint16; | ||
74 | typedef u8 uint8; | ||
75 | |||
76 | typedef s32 int4; | ||
77 | typedef s16 int2; | ||
78 | typedef s8 int1; | ||
79 | |||
80 | typedef u32 uint4; | ||
81 | typedef u16 uint2; | ||
82 | typedef u8 uint1; | ||
83 | |||
84 | typedef u32 dword; | ||
85 | typedef u16 word; | ||
86 | typedef u8 byte; | ||
87 | |||
88 | typedef unsigned int boolean; | ||
89 | |||
90 | #ifndef TRUE | ||
91 | #define TRUE 1 | ||
92 | #endif | ||
93 | |||
94 | #ifndef FALSE | ||
95 | #define FALSE 0 | ||
96 | #endif | ||
97 | |||
98 | #define MSM_FB_ENABLE_DBGFS | ||
99 | #define FEATURE_MDDI | ||
100 | |||
101 | #define outp32(addr, val) writel(val, addr) | ||
102 | #define outp16(addr, val) writew(val, addr) | ||
103 | #define outp8(addr, val) writeb(val, addr) | ||
104 | #define outp(addr, val) outp32(addr, val) | ||
105 | |||
106 | #ifndef MAX | ||
107 | #define MAX( x, y ) (((x) > (y)) ? (x) : (y)) | ||
108 | #endif | ||
109 | |||
110 | #ifndef MIN | ||
111 | #define MIN( x, y ) (((x) < (y)) ? (x) : (y)) | ||
112 | #endif | ||
113 | |||
114 | /*--------------------------------------------------------------------------*/ | ||
115 | |||
116 | #define inp32(addr) readl(addr) | ||
117 | #define inp16(addr) readw(addr) | ||
118 | #define inp8(addr) readb(addr) | ||
119 | #define inp(addr) inp32(addr) | ||
120 | |||
121 | #define inpw(port) readw(port) | ||
122 | #define outpw(port, val) writew(val, port) | ||
123 | #define inpdw(port) readl(port) | ||
124 | #define outpdw(port, val) writel(val, port) | ||
125 | |||
126 | |||
127 | #define clk_busy_wait(x) msleep_interruptible((x)/1000) | ||
128 | |||
129 | #define memory_barrier() | ||
130 | |||
131 | #define assert(expr) \ | ||
132 | if(!(expr)) { \ | ||
133 | printk(KERN_ERR "msm_fb: assertion failed! %s,%s,%s,line=%d\n",\ | ||
134 | #expr, __FILE__, __func__, __LINE__); \ | ||
135 | } | ||
136 | |||
137 | #define ASSERT(x) assert(x) | ||
138 | |||
139 | #define DISP_EBI2_LOCAL_DEFINE | ||
140 | #ifdef DISP_EBI2_LOCAL_DEFINE | ||
141 | #define LCD_PRIM_BASE_PHYS 0x98000000 | ||
142 | #define LCD_SECD_BASE_PHYS 0x9c000000 | ||
143 | #define EBI2_PRIM_LCD_RS_PIN 0x20000 | ||
144 | #define EBI2_SECD_LCD_RS_PIN 0x20000 | ||
145 | |||
146 | #define EBI2_PRIM_LCD_CLR 0xC0 | ||
147 | #define EBI2_PRIM_LCD_SEL 0x40 | ||
148 | |||
149 | #define EBI2_SECD_LCD_CLR 0x300 | ||
150 | #define EBI2_SECD_LCD_SEL 0x100 | ||
151 | #endif | ||
152 | |||
153 | extern u32 msm_fb_msg_level; | ||
154 | |||
155 | /* | ||
156 | * Message printing priorities: | ||
157 | * LEVEL 0 KERN_EMERG (highest priority) | ||
158 | * LEVEL 1 KERN_ALERT | ||
159 | * LEVEL 2 KERN_CRIT | ||
160 | * LEVEL 3 KERN_ERR | ||
161 | * LEVEL 4 KERN_WARNING | ||
162 | * LEVEL 5 KERN_NOTICE | ||
163 | * LEVEL 6 KERN_INFO | ||
164 | * LEVEL 7 KERN_DEBUG (Lowest priority) | ||
165 | */ | ||
166 | #define MSM_FB_EMERG(msg, ...) \ | ||
167 | if (msm_fb_msg_level > 0) \ | ||
168 | printk(KERN_EMERG msg, ## __VA_ARGS__); | ||
169 | #define MSM_FB_ALERT(msg, ...) \ | ||
170 | if (msm_fb_msg_level > 1) \ | ||
171 | printk(KERN_ALERT msg, ## __VA_ARGS__); | ||
172 | #define MSM_FB_CRIT(msg, ...) \ | ||
173 | if (msm_fb_msg_level > 2) \ | ||
174 | printk(KERN_CRIT msg, ## __VA_ARGS__); | ||
175 | #define MSM_FB_ERR(msg, ...) \ | ||
176 | if (msm_fb_msg_level > 3) \ | ||
177 | printk(KERN_ERR msg, ## __VA_ARGS__); | ||
178 | #define MSM_FB_WARNING(msg, ...) \ | ||
179 | if (msm_fb_msg_level > 4) \ | ||
180 | printk(KERN_WARNING msg, ## __VA_ARGS__); | ||
181 | #define MSM_FB_NOTICE(msg, ...) \ | ||
182 | if (msm_fb_msg_level > 5) \ | ||
183 | printk(KERN_NOTICE msg, ## __VA_ARGS__); | ||
184 | #define MSM_FB_INFO(msg, ...) \ | ||
185 | if (msm_fb_msg_level > 6) \ | ||
186 | printk(KERN_INFO msg, ## __VA_ARGS__); | ||
187 | #define MSM_FB_DEBUG(msg, ...) \ | ||
188 | if (msm_fb_msg_level > 7) \ | ||
189 | printk(KERN_DEBUG msg, ## __VA_ARGS__); | ||
190 | |||
191 | #ifdef MSM_FB_C | ||
192 | unsigned char *msm_mdp_base; | ||
193 | unsigned char *msm_pmdh_base; | ||
194 | unsigned char *msm_emdh_base; | ||
195 | #else | ||
196 | extern unsigned char *msm_mdp_base; | ||
197 | extern unsigned char *msm_pmdh_base; | ||
198 | extern unsigned char *msm_emdh_base; | ||
199 | #endif | ||
200 | |||
201 | #endif /* MSM_FB_DEF_H */ | ||
diff --git a/drivers/staging/msm/msm_fb_panel.c b/drivers/staging/msm/msm_fb_panel.c new file mode 100644 index 000000000000..b17a239a1bc7 --- /dev/null +++ b/drivers/staging/msm/msm_fb_panel.c | |||
@@ -0,0 +1,136 @@ | |||
1 | /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/moduleparam.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <linux/mm.h> | ||
24 | #include <linux/fb.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/ioport.h> | ||
27 | #include <linux/device.h> | ||
28 | #include <linux/dma-mapping.h> | ||
29 | #include <linux/uaccess.h> | ||
30 | #include <linux/workqueue.h> | ||
31 | #include <linux/string.h> | ||
32 | #include <linux/version.h> | ||
33 | #include <linux/proc_fs.h> | ||
34 | #include <linux/vmalloc.h> | ||
35 | #include <linux/debugfs.h> | ||
36 | |||
37 | #include "msm_fb_panel.h" | ||
38 | |||
39 | int panel_next_on(struct platform_device *pdev) | ||
40 | { | ||
41 | int ret = 0; | ||
42 | struct msm_fb_panel_data *pdata; | ||
43 | struct msm_fb_panel_data *next_pdata; | ||
44 | struct platform_device *next_pdev; | ||
45 | |||
46 | pdata = (struct msm_fb_panel_data *)pdev->dev.platform_data; | ||
47 | |||
48 | if (pdata) { | ||
49 | next_pdev = pdata->next; | ||
50 | if (next_pdev) { | ||
51 | next_pdata = | ||
52 | (struct msm_fb_panel_data *)next_pdev->dev. | ||
53 | platform_data; | ||
54 | if ((next_pdata) && (next_pdata->on)) | ||
55 | ret = next_pdata->on(next_pdev); | ||
56 | } | ||
57 | } | ||
58 | |||
59 | return ret; | ||
60 | } | ||
61 | |||
62 | int panel_next_off(struct platform_device *pdev) | ||
63 | { | ||
64 | int ret = 0; | ||
65 | struct msm_fb_panel_data *pdata; | ||
66 | struct msm_fb_panel_data *next_pdata; | ||
67 | struct platform_device *next_pdev; | ||
68 | |||
69 | pdata = (struct msm_fb_panel_data *)pdev->dev.platform_data; | ||
70 | |||
71 | if (pdata) { | ||
72 | next_pdev = pdata->next; | ||
73 | if (next_pdev) { | ||
74 | next_pdata = | ||
75 | (struct msm_fb_panel_data *)next_pdev->dev. | ||
76 | platform_data; | ||
77 | if ((next_pdata) && (next_pdata->on)) | ||
78 | ret = next_pdata->off(next_pdev); | ||
79 | } | ||
80 | } | ||
81 | |||
82 | return ret; | ||
83 | } | ||
84 | |||
85 | struct platform_device *msm_fb_device_alloc(struct msm_fb_panel_data *pdata, | ||
86 | u32 type, u32 id) | ||
87 | { | ||
88 | struct platform_device *this_dev = NULL; | ||
89 | char dev_name[16]; | ||
90 | |||
91 | switch (type) { | ||
92 | case EBI2_PANEL: | ||
93 | snprintf(dev_name, sizeof(dev_name), "ebi2_lcd"); | ||
94 | break; | ||
95 | |||
96 | case MDDI_PANEL: | ||
97 | snprintf(dev_name, sizeof(dev_name), "mddi"); | ||
98 | break; | ||
99 | |||
100 | case EXT_MDDI_PANEL: | ||
101 | snprintf(dev_name, sizeof(dev_name), "mddi_ext"); | ||
102 | break; | ||
103 | |||
104 | case TV_PANEL: | ||
105 | snprintf(dev_name, sizeof(dev_name), "tvenc"); | ||
106 | break; | ||
107 | |||
108 | case HDMI_PANEL: | ||
109 | case LCDC_PANEL: | ||
110 | snprintf(dev_name, sizeof(dev_name), "lcdc"); | ||
111 | break; | ||
112 | |||
113 | default: | ||
114 | return NULL; | ||
115 | } | ||
116 | |||
117 | if (pdata != NULL) | ||
118 | pdata->next = NULL; | ||
119 | else | ||
120 | return NULL; | ||
121 | |||
122 | this_dev = | ||
123 | platform_device_alloc(dev_name, ((u32) type << 16) | (u32) id); | ||
124 | |||
125 | if (this_dev) { | ||
126 | if (platform_device_add_data | ||
127 | (this_dev, pdata, sizeof(struct msm_fb_panel_data))) { | ||
128 | printk | ||
129 | ("msm_fb_device_alloc: platform_device_add_data failed!\n"); | ||
130 | platform_device_put(this_dev); | ||
131 | return NULL; | ||
132 | } | ||
133 | } | ||
134 | |||
135 | return this_dev; | ||
136 | } | ||
diff --git a/drivers/staging/msm/msm_fb_panel.h b/drivers/staging/msm/msm_fb_panel.h new file mode 100644 index 000000000000..ab458310c3a2 --- /dev/null +++ b/drivers/staging/msm/msm_fb_panel.h | |||
@@ -0,0 +1,145 @@ | |||
1 | /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * Redistribution and use in source and binary forms, with or without | ||
4 | * modification, are permitted provided that the following conditions are met: | ||
5 | * * Redistributions of source code must retain the above copyright | ||
6 | * notice, this list of conditions and the following disclaimer. | ||
7 | * * Redistributions in binary form must reproduce the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer in the | ||
9 | * documentation and/or other materials provided with the distribution. | ||
10 | * * Neither the name of Code Aurora nor | ||
11 | * the names of its contributors may be used to endorse or promote | ||
12 | * products derived from this software without specific prior written | ||
13 | * permission. | ||
14 | * | ||
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
17 | * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
18 | * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||
19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||
20 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||
21 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | ||
22 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | ||
23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||
24 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | ||
25 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | * | ||
27 | */ | ||
28 | |||
29 | #ifndef MSM_FB_PANEL_H | ||
30 | #define MSM_FB_PANEL_H | ||
31 | |||
32 | #include "msm_fb_def.h" | ||
33 | |||
34 | struct msm_fb_data_type; | ||
35 | |||
36 | typedef void (*msm_fb_vsync_handler_type) (void *arg); | ||
37 | |||
38 | /* panel id type */ | ||
39 | typedef struct panel_id_s { | ||
40 | uint16 id; | ||
41 | uint16 type; | ||
42 | } panel_id_type; | ||
43 | |||
44 | /* panel type list */ | ||
45 | #define NO_PANEL 0xffff /* No Panel */ | ||
46 | #define MDDI_PANEL 1 /* MDDI */ | ||
47 | #define EBI2_PANEL 2 /* EBI2 */ | ||
48 | #define LCDC_PANEL 3 /* internal LCDC type */ | ||
49 | #define EXT_MDDI_PANEL 4 /* Ext.MDDI */ | ||
50 | #define TV_PANEL 5 /* TV */ | ||
51 | #define HDMI_PANEL 6 /* HDMI TV */ | ||
52 | |||
53 | /* panel class */ | ||
54 | typedef enum { | ||
55 | DISPLAY_LCD = 0, /* lcd = ebi2/mddi */ | ||
56 | DISPLAY_LCDC, /* lcdc */ | ||
57 | DISPLAY_TV, /* TV Out */ | ||
58 | DISPLAY_EXT_MDDI, /* External MDDI */ | ||
59 | } DISP_TARGET; | ||
60 | |||
61 | /* panel device locaiton */ | ||
62 | typedef enum { | ||
63 | DISPLAY_1 = 0, /* attached as first device */ | ||
64 | DISPLAY_2, /* attached on second device */ | ||
65 | MAX_PHYS_TARGET_NUM, | ||
66 | } DISP_TARGET_PHYS; | ||
67 | |||
68 | /* panel info type */ | ||
69 | struct lcd_panel_info { | ||
70 | __u32 vsync_enable; | ||
71 | __u32 refx100; | ||
72 | __u32 v_back_porch; | ||
73 | __u32 v_front_porch; | ||
74 | __u32 v_pulse_width; | ||
75 | __u32 hw_vsync_mode; | ||
76 | __u32 vsync_notifier_period; | ||
77 | }; | ||
78 | |||
79 | struct lcdc_panel_info { | ||
80 | __u32 h_back_porch; | ||
81 | __u32 h_front_porch; | ||
82 | __u32 h_pulse_width; | ||
83 | __u32 v_back_porch; | ||
84 | __u32 v_front_porch; | ||
85 | __u32 v_pulse_width; | ||
86 | __u32 border_clr; | ||
87 | __u32 underflow_clr; | ||
88 | __u32 hsync_skew; | ||
89 | }; | ||
90 | |||
91 | struct mddi_panel_info { | ||
92 | __u32 vdopkt; | ||
93 | }; | ||
94 | |||
95 | struct msm_panel_info { | ||
96 | __u32 xres; | ||
97 | __u32 yres; | ||
98 | __u32 bpp; | ||
99 | __u32 type; | ||
100 | __u32 wait_cycle; | ||
101 | DISP_TARGET_PHYS pdest; | ||
102 | __u32 bl_max; | ||
103 | __u32 bl_min; | ||
104 | __u32 fb_num; | ||
105 | __u32 clk_rate; | ||
106 | __u32 clk_min; | ||
107 | __u32 clk_max; | ||
108 | __u32 frame_count; | ||
109 | |||
110 | union { | ||
111 | struct mddi_panel_info mddi; | ||
112 | }; | ||
113 | |||
114 | union { | ||
115 | struct lcd_panel_info lcd; | ||
116 | struct lcdc_panel_info lcdc; | ||
117 | }; | ||
118 | }; | ||
119 | |||
120 | struct msm_fb_panel_data { | ||
121 | struct msm_panel_info panel_info; | ||
122 | void (*set_rect) (int x, int y, int xres, int yres); | ||
123 | void (*set_vsync_notifier) (msm_fb_vsync_handler_type, void *arg); | ||
124 | void (*set_backlight) (struct msm_fb_data_type *); | ||
125 | |||
126 | /* function entry chain */ | ||
127 | int (*on) (struct platform_device *pdev); | ||
128 | int (*off) (struct platform_device *pdev); | ||
129 | struct platform_device *next; | ||
130 | }; | ||
131 | |||
132 | /*=========================================================================== | ||
133 | FUNCTIONS PROTOTYPES | ||
134 | ============================================================================*/ | ||
135 | struct platform_device *msm_fb_device_alloc(struct msm_fb_panel_data *pdata, | ||
136 | u32 type, u32 id); | ||
137 | int panel_next_on(struct platform_device *pdev); | ||
138 | int panel_next_off(struct platform_device *pdev); | ||
139 | |||
140 | int lcdc_device_register(struct msm_panel_info *pinfo); | ||
141 | |||
142 | int mddi_toshiba_device_register(struct msm_panel_info *pinfo, | ||
143 | u32 channel, u32 panel); | ||
144 | |||
145 | #endif /* MSM_FB_PANEL_H */ | ||
diff --git a/drivers/staging/msm/msm_mdp.h b/drivers/staging/msm/msm_mdp.h new file mode 100644 index 000000000000..2d5323f5b62d --- /dev/null +++ b/drivers/staging/msm/msm_mdp.h | |||
@@ -0,0 +1,245 @@ | |||
1 | /* include/linux/msm_mdp.h | ||
2 | * | ||
3 | * Copyright (C) 2007 Google Incorporated | ||
4 | * Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved. | ||
5 | * | ||
6 | * This software is licensed under the terms of the GNU General Public | ||
7 | * License version 2, as published by the Free Software Foundation, and | ||
8 | * may be copied, distributed, and modified under those terms. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | */ | ||
15 | #ifndef _MSM_MDP_H_ | ||
16 | #define _MSM_MDP_H_ | ||
17 | |||
18 | #include <linux/types.h> | ||
19 | #include <linux/fb.h> | ||
20 | |||
21 | #define MSMFB_IOCTL_MAGIC 'm' | ||
22 | #define MSMFB_GRP_DISP _IOW(MSMFB_IOCTL_MAGIC, 1, unsigned int) | ||
23 | #define MSMFB_BLIT _IOW(MSMFB_IOCTL_MAGIC, 2, unsigned int) | ||
24 | #define MSMFB_SUSPEND_SW_REFRESHER _IOW(MSMFB_IOCTL_MAGIC, 128, unsigned int) | ||
25 | #define MSMFB_RESUME_SW_REFRESHER _IOW(MSMFB_IOCTL_MAGIC, 129, unsigned int) | ||
26 | #define MSMFB_CURSOR _IOW(MSMFB_IOCTL_MAGIC, 130, struct fb_cursor) | ||
27 | #define MSMFB_SET_LUT _IOW(MSMFB_IOCTL_MAGIC, 131, struct fb_cmap) | ||
28 | #define MSMFB_HISTOGRAM _IOWR(MSMFB_IOCTL_MAGIC, 132, struct mdp_histogram) | ||
29 | /* new ioctls's for set/get ccs matrix */ | ||
30 | #define MSMFB_GET_CCS_MATRIX _IOWR(MSMFB_IOCTL_MAGIC, 133, struct mdp_ccs) | ||
31 | #define MSMFB_SET_CCS_MATRIX _IOW(MSMFB_IOCTL_MAGIC, 134, struct mdp_ccs) | ||
32 | #define MSMFB_OVERLAY_SET _IOWR(MSMFB_IOCTL_MAGIC, 135, \ | ||
33 | struct mdp_overlay) | ||
34 | #define MSMFB_OVERLAY_UNSET _IOW(MSMFB_IOCTL_MAGIC, 136, unsigned int) | ||
35 | #define MSMFB_OVERLAY_PLAY _IOW(MSMFB_IOCTL_MAGIC, 137, \ | ||
36 | struct msmfb_overlay_data) | ||
37 | #define MSMFB_GET_PAGE_PROTECTION _IOR(MSMFB_IOCTL_MAGIC, 138, \ | ||
38 | struct mdp_page_protection) | ||
39 | #define MSMFB_SET_PAGE_PROTECTION _IOW(MSMFB_IOCTL_MAGIC, 139, \ | ||
40 | struct mdp_page_protection) | ||
41 | #define MSMFB_OVERLAY_GET _IOR(MSMFB_IOCTL_MAGIC, 140, \ | ||
42 | struct mdp_overlay) | ||
43 | |||
44 | /* new ioctls for async MDP ops */ | ||
45 | #define MSMFB_ASYNC_BLIT _IOW(MSMFB_IOCTL_MAGIC, 141, unsigned int) | ||
46 | #define MSMFB_BLIT_FLUSH _IOR(MSMFB_IOCTL_MAGIC, 142, unsigned int) | ||
47 | |||
48 | #define MDP_IMGTYPE2_START 0x10000 | ||
49 | |||
50 | enum { | ||
51 | MDP_RGB_565, /* RGB 565 planer */ | ||
52 | MDP_XRGB_8888, /* RGB 888 padded */ | ||
53 | MDP_Y_CBCR_H2V2, /* Y and CbCr, pseudo planer w/ Cb is in MSB */ | ||
54 | MDP_ARGB_8888, /* ARGB 888 */ | ||
55 | MDP_RGB_888, /* RGB 888 planer */ | ||
56 | MDP_Y_CRCB_H2V2, /* Y and CrCb, pseudo planer w/ Cr is in MSB */ | ||
57 | MDP_YCRYCB_H2V1, /* YCrYCb interleave */ | ||
58 | MDP_Y_CRCB_H2V1, /* Y and CrCb, pseduo planer w/ Cr is in MSB */ | ||
59 | MDP_Y_CBCR_H2V1, /* Y and CrCb, pseduo planer w/ Cr is in MSB */ | ||
60 | MDP_RGBA_8888, /* ARGB 888 */ | ||
61 | MDP_BGRA_8888, /* ABGR 888 */ | ||
62 | MDP_Y_CRCB_H2V2_TILE, /* Y and CrCb, pseudo planer tile */ | ||
63 | MDP_Y_CBCR_H2V2_TILE, /* Y and CbCr, pseudo planer tile */ | ||
64 | MDP_IMGTYPE_LIMIT, | ||
65 | MDP_BGR_565 = MDP_IMGTYPE2_START, /* BGR 565 planer */ | ||
66 | MDP_FB_FORMAT, /* framebuffer format */ | ||
67 | MDP_IMGTYPE_LIMIT2 /* Non valid image type after this enum */ | ||
68 | }; | ||
69 | |||
70 | enum { | ||
71 | PMEM_IMG, | ||
72 | FB_IMG, | ||
73 | }; | ||
74 | |||
75 | /* mdp_blit_req flag values */ | ||
76 | #define MDP_ROT_NOP 0 | ||
77 | #define MDP_FLIP_LR 0x1 | ||
78 | #define MDP_FLIP_UD 0x2 | ||
79 | #define MDP_ROT_90 0x4 | ||
80 | #define MDP_ROT_180 (MDP_FLIP_UD|MDP_FLIP_LR) | ||
81 | #define MDP_ROT_270 (MDP_ROT_90|MDP_FLIP_UD|MDP_FLIP_LR) | ||
82 | #define MDP_DITHER 0x8 | ||
83 | #define MDP_BLUR 0x10 | ||
84 | #define MDP_BLEND_FG_PREMULT 0x20000 | ||
85 | |||
86 | #define MDP_DEINTERLACE 0x80000000 | ||
87 | #define MDP_SHARPENING 0x40000000 | ||
88 | |||
89 | #define MDP_NO_DMA_BARRIER_START 0x20000000 | ||
90 | #define MDP_NO_DMA_BARRIER_END 0x10000000 | ||
91 | #define MDP_NO_BLIT 0x08000000 | ||
92 | #define MDP_BLIT_WITH_DMA_BARRIERS 0x000 | ||
93 | #define MDP_BLIT_WITH_NO_DMA_BARRIERS \ | ||
94 | (MDP_NO_DMA_BARRIER_START | MDP_NO_DMA_BARRIER_END) | ||
95 | #define MDP_TRANSP_NOP 0xffffffff | ||
96 | #define MDP_ALPHA_NOP 0xff | ||
97 | |||
98 | #define MDP_BLIT_SRC_GEM 0x02000000 /* set for GEM, clear for PMEM */ | ||
99 | #define MDP_BLIT_DST_GEM 0x01000000 /* set for GEM, clear for PMEM */ | ||
100 | |||
101 | #define MDP_FB_PAGE_PROTECTION_NONCACHED (0) | ||
102 | #define MDP_FB_PAGE_PROTECTION_WRITECOMBINE (1) | ||
103 | #define MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE (2) | ||
104 | #define MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE (3) | ||
105 | #define MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE (4) | ||
106 | /* Sentinel: Don't use! */ | ||
107 | #define MDP_FB_PAGE_PROTECTION_INVALID (5) | ||
108 | /* Count of the number of MDP_FB_PAGE_PROTECTION_... values. */ | ||
109 | #define MDP_NUM_FB_PAGE_PROTECTION_VALUES (5) | ||
110 | |||
111 | struct mdp_rect { | ||
112 | uint32_t x; | ||
113 | uint32_t y; | ||
114 | uint32_t w; | ||
115 | uint32_t h; | ||
116 | }; | ||
117 | |||
118 | struct mdp_img { | ||
119 | uint32_t width; | ||
120 | uint32_t height; | ||
121 | uint32_t format; | ||
122 | uint32_t offset; | ||
123 | int memory_id; /* the file descriptor */ | ||
124 | uint32_t priv; | ||
125 | }; | ||
126 | |||
127 | /* | ||
128 | * {3x3} + {3} ccs matrix | ||
129 | */ | ||
130 | |||
131 | #define MDP_CCS_RGB2YUV 0 | ||
132 | #define MDP_CCS_YUV2RGB 1 | ||
133 | |||
134 | #define MDP_CCS_SIZE 9 | ||
135 | #define MDP_BV_SIZE 3 | ||
136 | |||
137 | struct mdp_ccs { | ||
138 | int direction; /* MDP_CCS_RGB2YUV or YUV2RGB */ | ||
139 | uint16_t ccs[MDP_CCS_SIZE]; /* 3x3 color coefficients */ | ||
140 | uint16_t bv[MDP_BV_SIZE]; /* 1x3 bias vector */ | ||
141 | }; | ||
142 | |||
143 | /* The version of the mdp_blit_req structure so that | ||
144 | * user applications can selectively decide which functionality | ||
145 | * to include | ||
146 | */ | ||
147 | |||
148 | #define MDP_BLIT_REQ_VERSION 2 | ||
149 | |||
150 | struct mdp_blit_req { | ||
151 | struct mdp_img src; | ||
152 | struct mdp_img dst; | ||
153 | struct mdp_rect src_rect; | ||
154 | struct mdp_rect dst_rect; | ||
155 | uint32_t alpha; | ||
156 | uint32_t transp_mask; | ||
157 | uint32_t flags; | ||
158 | int sharpening_strength; /* -127 <--> 127, default 64 */ | ||
159 | }; | ||
160 | |||
161 | struct mdp_blit_req_list { | ||
162 | uint32_t count; | ||
163 | struct mdp_blit_req req[]; | ||
164 | }; | ||
165 | |||
166 | struct msmfb_data { | ||
167 | uint32_t offset; | ||
168 | int memory_id; | ||
169 | int id; | ||
170 | }; | ||
171 | |||
172 | #define MSMFB_NEW_REQUEST -1 | ||
173 | |||
174 | struct msmfb_overlay_data { | ||
175 | uint32_t id; | ||
176 | struct msmfb_data data; | ||
177 | }; | ||
178 | |||
179 | struct msmfb_img { | ||
180 | uint32_t width; | ||
181 | uint32_t height; | ||
182 | uint32_t format; | ||
183 | }; | ||
184 | |||
185 | struct mdp_overlay { | ||
186 | struct msmfb_img src; | ||
187 | struct mdp_rect src_rect; | ||
188 | struct mdp_rect dst_rect; | ||
189 | uint32_t z_order; /* stage number */ | ||
190 | uint32_t is_fg; /* control alpha & transp */ | ||
191 | uint32_t alpha; | ||
192 | uint32_t transp_mask; | ||
193 | uint32_t flags; | ||
194 | uint32_t id; | ||
195 | uint32_t user_data[8]; | ||
196 | }; | ||
197 | |||
198 | struct mdp_histogram { | ||
199 | uint32_t frame_cnt; | ||
200 | uint32_t bin_cnt; | ||
201 | uint32_t *r; | ||
202 | uint32_t *g; | ||
203 | uint32_t *b; | ||
204 | }; | ||
205 | |||
206 | struct mdp_page_protection { | ||
207 | uint32_t page_protection; | ||
208 | }; | ||
209 | |||
210 | |||
211 | struct msm_panel_common_pdata { | ||
212 | int gpio; | ||
213 | int (*backlight_level)(int level, int max, int min); | ||
214 | int (*pmic_backlight)(int level); | ||
215 | int (*panel_num)(void); | ||
216 | void (*panel_config_gpio)(int); | ||
217 | int *gpio_num; | ||
218 | }; | ||
219 | |||
220 | struct lcdc_platform_data { | ||
221 | int (*lcdc_gpio_config)(int on); | ||
222 | void (*lcdc_power_save)(int); | ||
223 | }; | ||
224 | |||
225 | struct tvenc_platform_data { | ||
226 | int (*pm_vid_en)(int on); | ||
227 | }; | ||
228 | |||
229 | struct mddi_platform_data { | ||
230 | void (*mddi_power_save)(int on); | ||
231 | int (*mddi_sel_clk)(u32 *clk_rate); | ||
232 | }; | ||
233 | |||
234 | struct msm_fb_platform_data { | ||
235 | int (*detect_client)(const char *name); | ||
236 | int mddi_prescan; | ||
237 | int (*allow_set_offset)(void); | ||
238 | }; | ||
239 | |||
240 | struct msm_hdmi_platform_data { | ||
241 | int irq; | ||
242 | int (*cable_detect)(int insert); | ||
243 | }; | ||
244 | |||
245 | #endif /*_MSM_MDP_H_*/ | ||
diff --git a/drivers/staging/msm/staging-devices.c b/drivers/staging/msm/staging-devices.c new file mode 100644 index 000000000000..0f8ec3e26013 --- /dev/null +++ b/drivers/staging/msm/staging-devices.c | |||
@@ -0,0 +1,323 @@ | |||
1 | #include <linux/kernel.h> | ||
2 | #include <linux/irq.h> | ||
3 | #include <linux/gpio.h> | ||
4 | #include <linux/platform_device.h> | ||
5 | #include <linux/bootmem.h> | ||
6 | #include <linux/delay.h> | ||
7 | |||
8 | #include <asm/mach-types.h> | ||
9 | #include <asm/mach/arch.h> | ||
10 | #include <asm/io.h> | ||
11 | #include <asm/setup.h> | ||
12 | |||
13 | #include <mach/board.h> | ||
14 | #include <mach/irqs.h> | ||
15 | #include <mach/sirc.h> | ||
16 | #include <mach/gpio.h> | ||
17 | |||
18 | #include "msm_mdp.h" | ||
19 | #include "memory_ll.h" | ||
20 | //#include "android_pmem.h" | ||
21 | #include <mach/board.h> | ||
22 | |||
23 | #ifdef CONFIG_MSM_SOC_REV_A | ||
24 | #define MSM_SMI_BASE 0xE0000000 | ||
25 | #else | ||
26 | #define MSM_SMI_BASE 0x00000000 | ||
27 | #endif | ||
28 | |||
29 | |||
30 | #define TOUCHPAD_SUSPEND 34 | ||
31 | #define TOUCHPAD_IRQ 38 | ||
32 | |||
33 | #define MSM_PMEM_MDP_SIZE 0x1591000 | ||
34 | |||
35 | #ifdef CONFIG_MSM_SOC_REV_A | ||
36 | #define SMEM_SPINLOCK_I2C "D:I2C02000021" | ||
37 | #else | ||
38 | #define SMEM_SPINLOCK_I2C "S:6" | ||
39 | #endif | ||
40 | |||
41 | #define MSM_PMEM_ADSP_SIZE 0x1C00000 | ||
42 | |||
43 | #define MSM_FB_SIZE 0x500000 | ||
44 | #define MSM_FB_SIZE_ST15 0x800000 | ||
45 | #define MSM_AUDIO_SIZE 0x80000 | ||
46 | #define MSM_GPU_PHYS_SIZE SZ_2M | ||
47 | |||
48 | #ifdef CONFIG_MSM_SOC_REV_A | ||
49 | #define MSM_SMI_BASE 0xE0000000 | ||
50 | #else | ||
51 | #define MSM_SMI_BASE 0x00000000 | ||
52 | #endif | ||
53 | |||
54 | #define MSM_SHARED_RAM_PHYS (MSM_SMI_BASE + 0x00100000) | ||
55 | |||
56 | #define MSM_PMEM_SMI_BASE (MSM_SMI_BASE + 0x02B00000) | ||
57 | #define MSM_PMEM_SMI_SIZE 0x01500000 | ||
58 | |||
59 | #define MSM_FB_BASE MSM_PMEM_SMI_BASE | ||
60 | #define MSM_GPU_PHYS_BASE (MSM_FB_BASE + MSM_FB_SIZE) | ||
61 | #define MSM_PMEM_SMIPOOL_BASE (MSM_GPU_PHYS_BASE + MSM_GPU_PHYS_SIZE) | ||
62 | #define MSM_PMEM_SMIPOOL_SIZE (MSM_PMEM_SMI_SIZE - MSM_FB_SIZE \ | ||
63 | - MSM_GPU_PHYS_SIZE) | ||
64 | |||
65 | #if defined(CONFIG_FB_MSM_MDP40) | ||
66 | #define MDP_BASE 0xA3F00000 | ||
67 | #define PMDH_BASE 0xAD600000 | ||
68 | #define EMDH_BASE 0xAD700000 | ||
69 | #define TVENC_BASE 0xAD400000 | ||
70 | #else | ||
71 | #define MDP_BASE 0xAA200000 | ||
72 | #define PMDH_BASE 0xAA600000 | ||
73 | #define EMDH_BASE 0xAA700000 | ||
74 | #define TVENC_BASE 0xAA400000 | ||
75 | #endif | ||
76 | |||
77 | #define PMEM_KERNEL_EBI1_SIZE (CONFIG_PMEM_KERNEL_SIZE * 1024 * 1024) | ||
78 | |||
79 | static struct resource msm_fb_resources[] = { | ||
80 | { | ||
81 | .flags = IORESOURCE_DMA, | ||
82 | } | ||
83 | }; | ||
84 | |||
85 | static struct resource msm_mdp_resources[] = { | ||
86 | { | ||
87 | .name = "mdp", | ||
88 | .start = MDP_BASE, | ||
89 | .end = MDP_BASE + 0x000F0000 - 1, | ||
90 | .flags = IORESOURCE_MEM, | ||
91 | } | ||
92 | }; | ||
93 | |||
94 | static struct platform_device msm_mdp_device = { | ||
95 | .name = "mdp", | ||
96 | .id = 0, | ||
97 | .num_resources = ARRAY_SIZE(msm_mdp_resources), | ||
98 | .resource = msm_mdp_resources, | ||
99 | }; | ||
100 | |||
101 | static struct platform_device msm_lcdc_device = { | ||
102 | .name = "lcdc", | ||
103 | .id = 0, | ||
104 | }; | ||
105 | |||
106 | static int msm_fb_detect_panel(const char *name) | ||
107 | { | ||
108 | int ret = -EPERM; | ||
109 | |||
110 | if (machine_is_qsd8x50_ffa() || machine_is_qsd8x50a_ffa()) { | ||
111 | if (!strncmp(name, "mddi_toshiba_wvga_pt", 20)) | ||
112 | ret = 0; | ||
113 | else | ||
114 | ret = -ENODEV; | ||
115 | } else if ((machine_is_qsd8x50_surf() || machine_is_qsd8x50a_surf()) | ||
116 | && !strcmp(name, "lcdc_external")) | ||
117 | ret = 0; | ||
118 | else if (0 /*machine_is_qsd8x50_grapefruit() */) { | ||
119 | if (!strcmp(name, "lcdc_grapefruit_vga")) | ||
120 | ret = 0; | ||
121 | else | ||
122 | ret = -ENODEV; | ||
123 | } else if (machine_is_qsd8x50_st1()) { | ||
124 | if (!strcmp(name, "lcdc_st1_wxga")) | ||
125 | ret = 0; | ||
126 | else | ||
127 | ret = -ENODEV; | ||
128 | } else if (machine_is_qsd8x50a_st1_5()) { | ||
129 | if (!strcmp(name, "lcdc_st15") || | ||
130 | !strcmp(name, "hdmi_sii9022")) | ||
131 | ret = 0; | ||
132 | else | ||
133 | ret = -ENODEV; | ||
134 | } | ||
135 | |||
136 | return ret; | ||
137 | } | ||
138 | |||
139 | /* Only allow a small subset of machines to set the offset via | ||
140 | FB PAN_DISPLAY */ | ||
141 | |||
142 | static int msm_fb_allow_set_offset(void) | ||
143 | { | ||
144 | return (machine_is_qsd8x50_st1() || | ||
145 | machine_is_qsd8x50a_st1_5()) ? 1 : 0; | ||
146 | } | ||
147 | |||
148 | |||
149 | static struct msm_fb_platform_data msm_fb_pdata = { | ||
150 | .detect_client = msm_fb_detect_panel, | ||
151 | .allow_set_offset = msm_fb_allow_set_offset, | ||
152 | }; | ||
153 | |||
154 | static struct platform_device msm_fb_device = { | ||
155 | .name = "msm_fb", | ||
156 | .id = 0, | ||
157 | .num_resources = ARRAY_SIZE(msm_fb_resources), | ||
158 | .resource = msm_fb_resources, | ||
159 | .dev = { | ||
160 | .platform_data = &msm_fb_pdata, | ||
161 | } | ||
162 | }; | ||
163 | |||
164 | static void __init qsd8x50_allocate_memory_regions(void) | ||
165 | { | ||
166 | void *addr; | ||
167 | unsigned long size; | ||
168 | if (machine_is_qsd8x50a_st1_5()) | ||
169 | size = MSM_FB_SIZE_ST15; | ||
170 | else | ||
171 | size = MSM_FB_SIZE; | ||
172 | |||
173 | addr = alloc_bootmem(size); // (void *)MSM_FB_BASE; | ||
174 | if (!addr) | ||
175 | printk("Failed to allocate bootmem for framebuffer\n"); | ||
176 | |||
177 | |||
178 | msm_fb_resources[0].start = __pa(addr); | ||
179 | msm_fb_resources[0].end = msm_fb_resources[0].start + size - 1; | ||
180 | pr_info(KERN_ERR "using %lu bytes of SMI at %lx physical for fb\n", | ||
181 | size, (unsigned long)addr); | ||
182 | } | ||
183 | |||
184 | static int msm_fb_lcdc_gpio_config(int on) | ||
185 | { | ||
186 | // return 0; | ||
187 | if (machine_is_qsd8x50_st1()) { | ||
188 | if (on) { | ||
189 | gpio_set_value(32, 1); | ||
190 | mdelay(100); | ||
191 | gpio_set_value(20, 1); | ||
192 | gpio_set_value(17, 1); | ||
193 | gpio_set_value(19, 1); | ||
194 | } else { | ||
195 | gpio_set_value(17, 0); | ||
196 | gpio_set_value(19, 0); | ||
197 | gpio_set_value(20, 0); | ||
198 | mdelay(100); | ||
199 | gpio_set_value(32, 0); | ||
200 | } | ||
201 | } else if (machine_is_qsd8x50a_st1_5()) { | ||
202 | if (on) { | ||
203 | gpio_set_value(17, 1); | ||
204 | gpio_set_value(19, 1); | ||
205 | gpio_set_value(20, 1); | ||
206 | gpio_set_value(22, 0); | ||
207 | gpio_set_value(32, 1); | ||
208 | gpio_set_value(155, 1); | ||
209 | //st15_hdmi_power(1); | ||
210 | gpio_set_value(22, 1); | ||
211 | |||
212 | } else { | ||
213 | gpio_set_value(17, 0); | ||
214 | gpio_set_value(19, 0); | ||
215 | gpio_set_value(22, 0); | ||
216 | gpio_set_value(32, 0); | ||
217 | gpio_set_value(155, 0); | ||
218 | // st15_hdmi_power(0); | ||
219 | } | ||
220 | } | ||
221 | return 0; | ||
222 | } | ||
223 | |||
224 | |||
225 | static struct lcdc_platform_data lcdc_pdata = { | ||
226 | .lcdc_gpio_config = msm_fb_lcdc_gpio_config, | ||
227 | }; | ||
228 | |||
229 | static struct msm_gpio msm_fb_st15_gpio_config_data[] = { | ||
230 | { GPIO_CFG(17, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA), "lcdc_en0" }, | ||
231 | { GPIO_CFG(19, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA), "dat_pwr_sv" }, | ||
232 | { GPIO_CFG(20, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA), "lvds_pwr_dn" }, | ||
233 | { GPIO_CFG(22, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA), "lcdc_en1" }, | ||
234 | { GPIO_CFG(32, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA), "lcdc_en2" }, | ||
235 | { GPIO_CFG(103, 0, GPIO_INPUT, GPIO_NO_PULL, GPIO_2MA), "hdmi_irq" }, | ||
236 | { GPIO_CFG(155, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA), "hdmi_3v3" }, | ||
237 | }; | ||
238 | |||
239 | static struct msm_panel_common_pdata mdp_pdata = { | ||
240 | .gpio = 98, | ||
241 | }; | ||
242 | |||
243 | static struct platform_device *devices[] __initdata = { | ||
244 | &msm_fb_device, | ||
245 | }; | ||
246 | |||
247 | |||
248 | static void __init msm_register_device(struct platform_device *pdev, void *data) | ||
249 | { | ||
250 | int ret; | ||
251 | |||
252 | pdev->dev.platform_data = data; | ||
253 | |||
254 | ret = platform_device_register(pdev); | ||
255 | if (ret) | ||
256 | dev_err(&pdev->dev, | ||
257 | "%s: platform_device_register() failed = %d\n", | ||
258 | __func__, ret); | ||
259 | } | ||
260 | |||
261 | void __init msm_fb_register_device(char *name, void *data) | ||
262 | { | ||
263 | if (!strncmp(name, "mdp", 3)) | ||
264 | msm_register_device(&msm_mdp_device, data); | ||
265 | /* | ||
266 | else if (!strncmp(name, "pmdh", 4)) | ||
267 | msm_register_device(&msm_mddi_device, data); | ||
268 | else if (!strncmp(name, "emdh", 4)) | ||
269 | msm_register_device(&msm_mddi_ext_device, data); | ||
270 | else if (!strncmp(name, "ebi2", 4)) | ||
271 | msm_register_device(&msm_ebi2_lcd_device, data); | ||
272 | else if (!strncmp(name, "tvenc", 5)) | ||
273 | msm_register_device(&msm_tvenc_device, data); | ||
274 | else */ | ||
275 | |||
276 | if (!strncmp(name, "lcdc", 4)) | ||
277 | msm_register_device(&msm_lcdc_device, data); | ||
278 | /*else | ||
279 | printk(KERN_ERR "%s: unknown device! %s\n", __func__, name); | ||
280 | */ | ||
281 | } | ||
282 | |||
283 | static void __init msm_fb_add_devices(void) | ||
284 | { | ||
285 | int rc; | ||
286 | msm_fb_register_device("mdp", &mdp_pdata); | ||
287 | // msm_fb_register_device("pmdh", &mddi_pdata); | ||
288 | // msm_fb_register_device("emdh", &mddi_pdata); | ||
289 | // msm_fb_register_device("tvenc", 0); | ||
290 | |||
291 | if (machine_is_qsd8x50a_st1_5()) { | ||
292 | /* rc = st15_hdmi_vreg_init(); | ||
293 | if (rc) | ||
294 | return; | ||
295 | */ | ||
296 | rc = msm_gpios_request_enable( | ||
297 | msm_fb_st15_gpio_config_data, | ||
298 | ARRAY_SIZE(msm_fb_st15_gpio_config_data)); | ||
299 | if (rc) { | ||
300 | printk(KERN_ERR "%s: unable to init lcdc gpios\n", | ||
301 | __func__); | ||
302 | return; | ||
303 | } | ||
304 | msm_fb_register_device("lcdc", &lcdc_pdata); | ||
305 | } else | ||
306 | msm_fb_register_device("lcdc", 0); | ||
307 | } | ||
308 | |||
309 | int __init staging_init_pmem(void) | ||
310 | { | ||
311 | qsd8x50_allocate_memory_regions(); | ||
312 | return 0; | ||
313 | } | ||
314 | |||
315 | int __init staging_init_devices(void) | ||
316 | { | ||
317 | platform_add_devices(devices, ARRAY_SIZE(devices)); | ||
318 | msm_fb_add_devices(); | ||
319 | return 0; | ||
320 | } | ||
321 | |||
322 | arch_initcall(staging_init_pmem); | ||
323 | arch_initcall(staging_init_devices); | ||
diff --git a/drivers/staging/msm/tv_ntsc.c b/drivers/staging/msm/tv_ntsc.c new file mode 100644 index 000000000000..5eb67611661a --- /dev/null +++ b/drivers/staging/msm/tv_ntsc.c | |||
@@ -0,0 +1,163 @@ | |||
1 | /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/sched.h> | ||
21 | #include <linux/time.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/spinlock.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <mach/hardware.h> | ||
27 | #include <linux/io.h> | ||
28 | |||
29 | #include <asm/system.h> | ||
30 | #include <asm/mach-types.h> | ||
31 | #include <linux/semaphore.h> | ||
32 | #include <linux/uaccess.h> | ||
33 | #include <linux/clk.h> | ||
34 | |||
35 | #include "msm_fb.h" | ||
36 | #include "tvenc.h" | ||
37 | |||
38 | #define NTSC_TV_DIMENSION_WIDTH 720 | ||
39 | #define NTSC_TV_DIMENSION_HEIGHT 480 | ||
40 | |||
41 | static int ntsc_off(struct platform_device *pdev); | ||
42 | static int ntsc_on(struct platform_device *pdev); | ||
43 | |||
44 | static int ntsc_on(struct platform_device *pdev) | ||
45 | { | ||
46 | uint32 reg = 0; | ||
47 | int ret = 0; | ||
48 | struct msm_fb_data_type *mfd; | ||
49 | |||
50 | mfd = platform_get_drvdata(pdev); | ||
51 | |||
52 | if (!mfd) | ||
53 | return -ENODEV; | ||
54 | |||
55 | if (mfd->key != MFD_KEY) | ||
56 | return -EINVAL; | ||
57 | |||
58 | TV_OUT(TV_ENC_CTL, 0); /* disable TV encoder */ | ||
59 | |||
60 | if (mfd->panel.id == NTSC_M) { | ||
61 | /* Cr gain 11, Cb gain C6, y_gain 97 */ | ||
62 | TV_OUT(TV_GAIN, 0x0081B697); | ||
63 | } else { | ||
64 | /* Cr gain 11, Cb gain C6, y_gain 97 */ | ||
65 | TV_OUT(TV_GAIN, 0x008bc4a3); | ||
66 | reg |= TVENC_CTL_NTSCJ_MODE; | ||
67 | } | ||
68 | |||
69 | TV_OUT(TV_CGMS, 0x0); | ||
70 | /* NTSC Timing */ | ||
71 | TV_OUT(TV_SYNC_1, 0x0020009e); | ||
72 | TV_OUT(TV_SYNC_2, 0x011306B4); | ||
73 | TV_OUT(TV_SYNC_3, 0x0006000C); | ||
74 | TV_OUT(TV_SYNC_4, 0x0028020D); | ||
75 | TV_OUT(TV_SYNC_5, 0x005E02FB); | ||
76 | TV_OUT(TV_SYNC_6, 0x0006000C); | ||
77 | TV_OUT(TV_SYNC_7, 0x00000012); | ||
78 | TV_OUT(TV_BURST_V1, 0x0013020D); | ||
79 | TV_OUT(TV_BURST_V2, 0x0014020C); | ||
80 | TV_OUT(TV_BURST_V3, 0x0013020D); | ||
81 | TV_OUT(TV_BURST_V4, 0x0014020C); | ||
82 | TV_OUT(TV_BURST_H, 0x00AE00F2); | ||
83 | TV_OUT(TV_SOL_REQ_ODD, 0x00280208); | ||
84 | TV_OUT(TV_SOL_REQ_EVEN, 0x00290209); | ||
85 | |||
86 | reg |= TVENC_CTL_TV_MODE_NTSC_M_PAL60; | ||
87 | |||
88 | reg |= TVENC_CTL_Y_FILTER_EN | | ||
89 | TVENC_CTL_CR_FILTER_EN | | ||
90 | TVENC_CTL_CB_FILTER_EN | TVENC_CTL_SINX_FILTER_EN; | ||
91 | #ifdef CONFIG_FB_MSM_TVOUT_SVIDEO | ||
92 | reg |= TVENC_CTL_S_VIDEO_EN; | ||
93 | #endif | ||
94 | |||
95 | TV_OUT(TV_LEVEL, 0x00000000); /* DC offset to 0. */ | ||
96 | TV_OUT(TV_OFFSET, 0x008080f0); | ||
97 | |||
98 | #ifdef CONFIG_FB_MSM_MDP31 | ||
99 | TV_OUT(TV_DAC_INTF, 0x29); | ||
100 | #endif | ||
101 | TV_OUT(TV_ENC_CTL, reg); | ||
102 | |||
103 | reg |= TVENC_CTL_ENC_EN; | ||
104 | TV_OUT(TV_ENC_CTL, reg); | ||
105 | |||
106 | return ret; | ||
107 | } | ||
108 | |||
109 | static int ntsc_off(struct platform_device *pdev) | ||
110 | { | ||
111 | TV_OUT(TV_ENC_CTL, 0); /* disable TV encoder */ | ||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | static int __init ntsc_probe(struct platform_device *pdev) | ||
116 | { | ||
117 | msm_fb_add_device(pdev); | ||
118 | |||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | static struct platform_driver this_driver = { | ||
123 | .probe = ntsc_probe, | ||
124 | .driver = { | ||
125 | .name = "tv_ntsc", | ||
126 | }, | ||
127 | }; | ||
128 | |||
129 | static struct msm_fb_panel_data ntsc_panel_data = { | ||
130 | .panel_info.xres = NTSC_TV_DIMENSION_WIDTH, | ||
131 | .panel_info.yres = NTSC_TV_DIMENSION_HEIGHT, | ||
132 | .panel_info.type = TV_PANEL, | ||
133 | .panel_info.pdest = DISPLAY_1, | ||
134 | .panel_info.wait_cycle = 0, | ||
135 | .panel_info.bpp = 16, | ||
136 | .panel_info.fb_num = 2, | ||
137 | .on = ntsc_on, | ||
138 | .off = ntsc_off, | ||
139 | }; | ||
140 | |||
141 | static struct platform_device this_device = { | ||
142 | .name = "tv_ntsc", | ||
143 | .id = 0, | ||
144 | .dev = { | ||
145 | .platform_data = &ntsc_panel_data, | ||
146 | } | ||
147 | }; | ||
148 | |||
149 | static int __init ntsc_init(void) | ||
150 | { | ||
151 | int ret; | ||
152 | |||
153 | ret = platform_driver_register(&this_driver); | ||
154 | if (!ret) { | ||
155 | ret = platform_device_register(&this_device); | ||
156 | if (ret) | ||
157 | platform_driver_unregister(&this_driver); | ||
158 | } | ||
159 | |||
160 | return ret; | ||
161 | } | ||
162 | |||
163 | module_init(ntsc_init); \ No newline at end of file | ||
diff --git a/drivers/staging/msm/tv_pal.c b/drivers/staging/msm/tv_pal.c new file mode 100644 index 000000000000..204da514660e --- /dev/null +++ b/drivers/staging/msm/tv_pal.c | |||
@@ -0,0 +1,213 @@ | |||
1 | /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/sched.h> | ||
20 | #include <linux/time.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/interrupt.h> | ||
23 | #include <linux/spinlock.h> | ||
24 | #include <linux/delay.h> | ||
25 | #include <mach/hardware.h> | ||
26 | #include <linux/io.h> | ||
27 | |||
28 | #include <asm/system.h> | ||
29 | #include <asm/mach-types.h> | ||
30 | #include <linux/semaphore.h> | ||
31 | #include <linux/uaccess.h> | ||
32 | #include <linux/clk.h> | ||
33 | |||
34 | #include "msm_fb.h" | ||
35 | #include "tvenc.h" | ||
36 | |||
37 | #ifdef CONFIG_FB_MSM_TVOUT_PAL_M | ||
38 | #define PAL_TV_DIMENSION_WIDTH 720 | ||
39 | #define PAL_TV_DIMENSION_HEIGHT 480 | ||
40 | #else | ||
41 | #define PAL_TV_DIMENSION_WIDTH 720 | ||
42 | #define PAL_TV_DIMENSION_HEIGHT 576 | ||
43 | #endif | ||
44 | |||
45 | static int pal_on(struct platform_device *pdev) | ||
46 | { | ||
47 | uint32 reg = 0; | ||
48 | int ret = 0; | ||
49 | struct msm_fb_data_type *mfd; | ||
50 | |||
51 | mfd = platform_get_drvdata(pdev); | ||
52 | |||
53 | if (!mfd) | ||
54 | return -ENODEV; | ||
55 | |||
56 | if (mfd->key != MFD_KEY) | ||
57 | return -EINVAL; | ||
58 | |||
59 | TV_OUT(TV_ENC_CTL, 0); /* disable TV encoder */ | ||
60 | |||
61 | switch (mfd->panel.id) { | ||
62 | case PAL_BDGHIN: | ||
63 | /* Cr gain 11, Cb gain C6, y_gain 97 */ | ||
64 | TV_OUT(TV_GAIN, 0x0088c1a0); | ||
65 | TV_OUT(TV_CGMS, 0x00012345); | ||
66 | TV_OUT(TV_TEST_MUX, 0x0); | ||
67 | /* PAL Timing */ | ||
68 | TV_OUT(TV_SYNC_1, 0x00180097); | ||
69 | TV_OUT(TV_SYNC_2, 0x011f06c0); | ||
70 | TV_OUT(TV_SYNC_3, 0x0005000a); | ||
71 | TV_OUT(TV_SYNC_4, 0x00320271); | ||
72 | TV_OUT(TV_SYNC_5, 0x005602f9); | ||
73 | TV_OUT(TV_SYNC_6, 0x0005000a); | ||
74 | TV_OUT(TV_SYNC_7, 0x0000000f); | ||
75 | TV_OUT(TV_BURST_V1, 0x0012026e); | ||
76 | TV_OUT(TV_BURST_V2, 0x0011026d); | ||
77 | TV_OUT(TV_BURST_V3, 0x00100270); | ||
78 | TV_OUT(TV_BURST_V4, 0x0013026f); | ||
79 | TV_OUT(TV_BURST_H, 0x00af00ea); | ||
80 | TV_OUT(TV_SOL_REQ_ODD, 0x0030026e); | ||
81 | TV_OUT(TV_SOL_REQ_EVEN, 0x0031026f); | ||
82 | |||
83 | reg |= TVENC_CTL_TV_MODE_PAL_BDGHIN; | ||
84 | break; | ||
85 | case PAL_M: | ||
86 | /* Cr gain 11, Cb gain C6, y_gain 97 */ | ||
87 | TV_OUT(TV_GAIN, 0x0081b697); | ||
88 | TV_OUT(TV_CGMS, 0x000af317); | ||
89 | TV_OUT(TV_TEST_MUX, 0x000001c3); | ||
90 | TV_OUT(TV_TEST_MODE, 0x00000002); | ||
91 | /* PAL Timing */ | ||
92 | TV_OUT(TV_SYNC_1, 0x0020009e); | ||
93 | TV_OUT(TV_SYNC_2, 0x011306b4); | ||
94 | TV_OUT(TV_SYNC_3, 0x0006000c); | ||
95 | TV_OUT(TV_SYNC_4, 0x0028020D); | ||
96 | TV_OUT(TV_SYNC_5, 0x005e02fb); | ||
97 | TV_OUT(TV_SYNC_6, 0x0006000c); | ||
98 | TV_OUT(TV_SYNC_7, 0x00000012); | ||
99 | TV_OUT(TV_BURST_V1, 0x0012020b); | ||
100 | TV_OUT(TV_BURST_V2, 0x0016020c); | ||
101 | TV_OUT(TV_BURST_V3, 0x00150209); | ||
102 | TV_OUT(TV_BURST_V4, 0x0013020c); | ||
103 | TV_OUT(TV_BURST_H, 0x00bf010b); | ||
104 | TV_OUT(TV_SOL_REQ_ODD, 0x00280208); | ||
105 | TV_OUT(TV_SOL_REQ_EVEN, 0x00290209); | ||
106 | |||
107 | reg |= TVENC_CTL_TV_MODE_PAL_M; | ||
108 | break; | ||
109 | case PAL_N: | ||
110 | /* Cr gain 11, Cb gain C6, y_gain 97 */ | ||
111 | TV_OUT(TV_GAIN, 0x0081b697); | ||
112 | TV_OUT(TV_CGMS, 0x000af317); | ||
113 | TV_OUT(TV_TEST_MUX, 0x000001c3); | ||
114 | TV_OUT(TV_TEST_MODE, 0x00000002); | ||
115 | /* PAL Timing */ | ||
116 | TV_OUT(TV_SYNC_1, 0x00180097); | ||
117 | TV_OUT(TV_SYNC_2, 0x12006c0); | ||
118 | TV_OUT(TV_SYNC_3, 0x0005000a); | ||
119 | TV_OUT(TV_SYNC_4, 0x00320271); | ||
120 | TV_OUT(TV_SYNC_5, 0x005602f9); | ||
121 | TV_OUT(TV_SYNC_6, 0x0005000a); | ||
122 | TV_OUT(TV_SYNC_7, 0x0000000f); | ||
123 | TV_OUT(TV_BURST_V1, 0x0012026e); | ||
124 | TV_OUT(TV_BURST_V2, 0x0011026d); | ||
125 | TV_OUT(TV_BURST_V3, 0x00100270); | ||
126 | TV_OUT(TV_BURST_V4, 0x0013026f); | ||
127 | TV_OUT(TV_BURST_H, 0x00af00fa); | ||
128 | TV_OUT(TV_SOL_REQ_ODD, 0x0030026e); | ||
129 | TV_OUT(TV_SOL_REQ_EVEN, 0x0031026f); | ||
130 | |||
131 | reg |= TVENC_CTL_TV_MODE_PAL_N; | ||
132 | break; | ||
133 | |||
134 | default: | ||
135 | return -ENODEV; | ||
136 | } | ||
137 | |||
138 | reg |= TVENC_CTL_Y_FILTER_EN | | ||
139 | TVENC_CTL_CR_FILTER_EN | | ||
140 | TVENC_CTL_CB_FILTER_EN | TVENC_CTL_SINX_FILTER_EN; | ||
141 | #ifdef CONFIG_FB_MSM_TVOUT_SVIDEO | ||
142 | reg |= TVENC_CTL_S_VIDEO_EN; | ||
143 | #endif | ||
144 | |||
145 | TV_OUT(TV_LEVEL, 0x00000000); /* DC offset to 0. */ | ||
146 | TV_OUT(TV_OFFSET, 0x008080f0); | ||
147 | |||
148 | #ifdef CONFIG_FB_MSM_MDP31 | ||
149 | TV_OUT(TV_DAC_INTF, 0x29); | ||
150 | #endif | ||
151 | TV_OUT(TV_ENC_CTL, reg); | ||
152 | |||
153 | reg |= TVENC_CTL_ENC_EN; | ||
154 | TV_OUT(TV_ENC_CTL, reg); | ||
155 | |||
156 | return ret; | ||
157 | } | ||
158 | |||
159 | static int pal_off(struct platform_device *pdev) | ||
160 | { | ||
161 | TV_OUT(TV_ENC_CTL, 0); /* disable TV encoder */ | ||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | static int __init pal_probe(struct platform_device *pdev) | ||
166 | { | ||
167 | msm_fb_add_device(pdev); | ||
168 | |||
169 | return 0; | ||
170 | } | ||
171 | |||
172 | static struct platform_driver this_driver = { | ||
173 | .probe = pal_probe, | ||
174 | .driver = { | ||
175 | .name = "tv_pal", | ||
176 | }, | ||
177 | }; | ||
178 | |||
179 | static struct msm_fb_panel_data pal_panel_data = { | ||
180 | .panel_info.xres = PAL_TV_DIMENSION_WIDTH, | ||
181 | .panel_info.yres = PAL_TV_DIMENSION_HEIGHT, | ||
182 | .panel_info.type = TV_PANEL, | ||
183 | .panel_info.pdest = DISPLAY_1, | ||
184 | .panel_info.wait_cycle = 0, | ||
185 | .panel_info.bpp = 16, | ||
186 | .panel_info.fb_num = 2, | ||
187 | .on = pal_on, | ||
188 | .off = pal_off, | ||
189 | }; | ||
190 | |||
191 | static struct platform_device this_device = { | ||
192 | .name = "tv_pal", | ||
193 | .id = 0, | ||
194 | .dev = { | ||
195 | .platform_data = &pal_panel_data, | ||
196 | } | ||
197 | }; | ||
198 | |||
199 | static int __init pal_init(void) | ||
200 | { | ||
201 | int ret; | ||
202 | |||
203 | ret = platform_driver_register(&this_driver); | ||
204 | if (!ret) { | ||
205 | ret = platform_device_register(&this_device); | ||
206 | if (ret) | ||
207 | platform_driver_unregister(&this_driver); | ||
208 | } | ||
209 | |||
210 | return ret; | ||
211 | } | ||
212 | |||
213 | module_init(pal_init); | ||
diff --git a/drivers/staging/msm/tvenc.c b/drivers/staging/msm/tvenc.c new file mode 100644 index 000000000000..f41c5ac22f25 --- /dev/null +++ b/drivers/staging/msm/tvenc.c | |||
@@ -0,0 +1,295 @@ | |||
1 | /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
15 | * 02110-1301, USA. | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/sched.h> | ||
21 | #include <linux/time.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/spinlock.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <mach/hardware.h> | ||
27 | #include <linux/io.h> | ||
28 | |||
29 | #include <asm/system.h> | ||
30 | #include <asm/mach-types.h> | ||
31 | #include <linux/semaphore.h> | ||
32 | #include <linux/uaccess.h> | ||
33 | #include <linux/clk.h> | ||
34 | #include <linux/platform_device.h> | ||
35 | #include <linux/pm_qos_params.h> | ||
36 | |||
37 | #define TVENC_C | ||
38 | #include "tvenc.h" | ||
39 | #include "msm_fb.h" | ||
40 | |||
41 | static int tvenc_probe(struct platform_device *pdev); | ||
42 | static int tvenc_remove(struct platform_device *pdev); | ||
43 | |||
44 | static int tvenc_off(struct platform_device *pdev); | ||
45 | static int tvenc_on(struct platform_device *pdev); | ||
46 | |||
47 | static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST]; | ||
48 | static int pdev_list_cnt; | ||
49 | |||
50 | static struct clk *tvenc_clk; | ||
51 | static struct clk *tvdac_clk; | ||
52 | |||
53 | static struct platform_driver tvenc_driver = { | ||
54 | .probe = tvenc_probe, | ||
55 | .remove = tvenc_remove, | ||
56 | .suspend = NULL, | ||
57 | // .suspend_late = NULL, | ||
58 | // .resume_early = NULL, | ||
59 | .resume = NULL, | ||
60 | .shutdown = NULL, | ||
61 | .driver = { | ||
62 | .name = "tvenc", | ||
63 | }, | ||
64 | }; | ||
65 | |||
66 | static struct tvenc_platform_data *tvenc_pdata; | ||
67 | |||
68 | static int tvenc_off(struct platform_device *pdev) | ||
69 | { | ||
70 | int ret = 0; | ||
71 | |||
72 | ret = panel_next_off(pdev); | ||
73 | |||
74 | clk_disable(tvenc_clk); | ||
75 | clk_disable(tvdac_clk); | ||
76 | |||
77 | if (tvenc_pdata && tvenc_pdata->pm_vid_en) | ||
78 | ret = tvenc_pdata->pm_vid_en(0); | ||
79 | |||
80 | //pm_qos_update_requirement(PM_QOS_SYSTEM_BUS_FREQ , "tvenc", | ||
81 | // PM_QOS_DEFAULT_VALUE); | ||
82 | |||
83 | if (ret) | ||
84 | printk(KERN_ERR "%s: pm_vid_en(off) failed! %d\n", | ||
85 | __func__, ret); | ||
86 | |||
87 | return ret; | ||
88 | } | ||
89 | |||
90 | static int tvenc_on(struct platform_device *pdev) | ||
91 | { | ||
92 | int ret = 0; | ||
93 | |||
94 | // pm_qos_update_requirement(PM_QOS_SYSTEM_BUS_FREQ , "tvenc", | ||
95 | // 128000); | ||
96 | if (tvenc_pdata && tvenc_pdata->pm_vid_en) | ||
97 | ret = tvenc_pdata->pm_vid_en(1); | ||
98 | |||
99 | if (ret) { | ||
100 | printk(KERN_ERR "%s: pm_vid_en(on) failed! %d\n", | ||
101 | __func__, ret); | ||
102 | return ret; | ||
103 | } | ||
104 | |||
105 | clk_enable(tvenc_clk); | ||
106 | clk_enable(tvdac_clk); | ||
107 | |||
108 | ret = panel_next_on(pdev); | ||
109 | |||
110 | return ret; | ||
111 | } | ||
112 | |||
113 | void tvenc_gen_test_pattern(struct msm_fb_data_type *mfd) | ||
114 | { | ||
115 | uint32 reg = 0, i; | ||
116 | |||
117 | reg = readl(MSM_TV_ENC_CTL); | ||
118 | reg |= TVENC_CTL_TEST_PATT_EN; | ||
119 | |||
120 | for (i = 0; i < 3; i++) { | ||
121 | TV_OUT(TV_ENC_CTL, 0); /* disable TV encoder */ | ||
122 | |||
123 | switch (i) { | ||
124 | /* | ||
125 | * TV Encoder - Color Bar Test Pattern | ||
126 | */ | ||
127 | case 0: | ||
128 | reg |= TVENC_CTL_TPG_CLRBAR; | ||
129 | break; | ||
130 | /* | ||
131 | * TV Encoder - Red Frame Test Pattern | ||
132 | */ | ||
133 | case 1: | ||
134 | reg |= TVENC_CTL_TPG_REDCLR; | ||
135 | break; | ||
136 | /* | ||
137 | * TV Encoder - Modulated Ramp Test Pattern | ||
138 | */ | ||
139 | default: | ||
140 | reg |= TVENC_CTL_TPG_MODRAMP; | ||
141 | break; | ||
142 | } | ||
143 | |||
144 | TV_OUT(TV_ENC_CTL, reg); | ||
145 | mdelay(5000); | ||
146 | |||
147 | switch (i) { | ||
148 | /* | ||
149 | * TV Encoder - Color Bar Test Pattern | ||
150 | */ | ||
151 | case 0: | ||
152 | reg &= ~TVENC_CTL_TPG_CLRBAR; | ||
153 | break; | ||
154 | /* | ||
155 | * TV Encoder - Red Frame Test Pattern | ||
156 | */ | ||
157 | case 1: | ||
158 | reg &= ~TVENC_CTL_TPG_REDCLR; | ||
159 | break; | ||
160 | /* | ||
161 | * TV Encoder - Modulated Ramp Test Pattern | ||
162 | */ | ||
163 | default: | ||
164 | reg &= ~TVENC_CTL_TPG_MODRAMP; | ||
165 | break; | ||
166 | } | ||
167 | } | ||
168 | } | ||
169 | |||
170 | static int tvenc_resource_initialized; | ||
171 | |||
172 | static int tvenc_probe(struct platform_device *pdev) | ||
173 | { | ||
174 | struct msm_fb_data_type *mfd; | ||
175 | struct platform_device *mdp_dev = NULL; | ||
176 | struct msm_fb_panel_data *pdata = NULL; | ||
177 | int rc; | ||
178 | |||
179 | if (pdev->id == 0) { | ||
180 | tvenc_base = ioremap(pdev->resource[0].start, | ||
181 | pdev->resource[0].end - | ||
182 | pdev->resource[0].start + 1); | ||
183 | if (!tvenc_base) { | ||
184 | printk(KERN_ERR | ||
185 | "tvenc_base ioremap failed!\n"); | ||
186 | return -ENOMEM; | ||
187 | } | ||
188 | tvenc_pdata = pdev->dev.platform_data; | ||
189 | tvenc_resource_initialized = 1; | ||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | if (!tvenc_resource_initialized) | ||
194 | return -EPERM; | ||
195 | |||
196 | mfd = platform_get_drvdata(pdev); | ||
197 | |||
198 | if (!mfd) | ||
199 | return -ENODEV; | ||
200 | |||
201 | if (mfd->key != MFD_KEY) | ||
202 | return -EINVAL; | ||
203 | |||
204 | if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST) | ||
205 | return -ENOMEM; | ||
206 | |||
207 | if (tvenc_base == NULL) | ||
208 | return -ENOMEM; | ||
209 | |||
210 | mdp_dev = platform_device_alloc("mdp", pdev->id); | ||
211 | if (!mdp_dev) | ||
212 | return -ENOMEM; | ||
213 | |||
214 | /* | ||
215 | * link to the latest pdev | ||
216 | */ | ||
217 | mfd->pdev = mdp_dev; | ||
218 | mfd->dest = DISPLAY_TV; | ||
219 | |||
220 | /* | ||
221 | * alloc panel device data | ||
222 | */ | ||
223 | if (platform_device_add_data | ||
224 | (mdp_dev, pdev->dev.platform_data, | ||
225 | sizeof(struct msm_fb_panel_data))) { | ||
226 | printk(KERN_ERR "tvenc_probe: platform_device_add_data failed!\n"); | ||
227 | platform_device_put(mdp_dev); | ||
228 | return -ENOMEM; | ||
229 | } | ||
230 | /* | ||
231 | * data chain | ||
232 | */ | ||
233 | pdata = mdp_dev->dev.platform_data; | ||
234 | pdata->on = tvenc_on; | ||
235 | pdata->off = tvenc_off; | ||
236 | pdata->next = pdev; | ||
237 | |||
238 | /* | ||
239 | * get/set panel specific fb info | ||
240 | */ | ||
241 | mfd->panel_info = pdata->panel_info; | ||
242 | mfd->fb_imgType = MDP_YCRYCB_H2V1; | ||
243 | |||
244 | /* | ||
245 | * set driver data | ||
246 | */ | ||
247 | platform_set_drvdata(mdp_dev, mfd); | ||
248 | |||
249 | /* | ||
250 | * register in mdp driver | ||
251 | */ | ||
252 | rc = platform_device_add(mdp_dev); | ||
253 | if (rc) | ||
254 | goto tvenc_probe_err; | ||
255 | |||
256 | pdev_list[pdev_list_cnt++] = pdev; | ||
257 | return 0; | ||
258 | |||
259 | tvenc_probe_err: | ||
260 | platform_device_put(mdp_dev); | ||
261 | return rc; | ||
262 | } | ||
263 | |||
264 | static int tvenc_remove(struct platform_device *pdev) | ||
265 | { | ||
266 | // pm_qos_remove_requirement(PM_QOS_SYSTEM_BUS_FREQ , "tvenc"); | ||
267 | return 0; | ||
268 | } | ||
269 | |||
270 | static int tvenc_register_driver(void) | ||
271 | { | ||
272 | return platform_driver_register(&tvenc_driver); | ||
273 | } | ||
274 | |||
275 | static int __init tvenc_driver_init(void) | ||
276 | { | ||
277 | tvenc_clk = clk_get(NULL, "tv_enc_clk"); | ||
278 | tvdac_clk = clk_get(NULL, "tv_dac_clk"); | ||
279 | |||
280 | if (IS_ERR(tvenc_clk)) { | ||
281 | printk(KERN_ERR "error: can't get tvenc_clk!\n"); | ||
282 | return IS_ERR(tvenc_clk); | ||
283 | } | ||
284 | |||
285 | if (IS_ERR(tvdac_clk)) { | ||
286 | printk(KERN_ERR "error: can't get tvdac_clk!\n"); | ||
287 | return IS_ERR(tvdac_clk); | ||
288 | } | ||
289 | |||
290 | // pm_qos_add_requirement(PM_QOS_SYSTEM_BUS_FREQ , "tvenc", | ||
291 | // PM_QOS_DEFAULT_VALUE); | ||
292 | return tvenc_register_driver(); | ||
293 | } | ||
294 | |||
295 | module_init(tvenc_driver_init); | ||
diff --git a/drivers/staging/msm/tvenc.h b/drivers/staging/msm/tvenc.h new file mode 100644 index 000000000000..a682dbebcf7d --- /dev/null +++ b/drivers/staging/msm/tvenc.h | |||
@@ -0,0 +1,117 @@ | |||
1 | /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. | ||
2 | * | ||
3 | * Redistribution and use in source and binary forms, with or without | ||
4 | * modification, are permitted provided that the following conditions are met: | ||
5 | * * Redistributions of source code must retain the above copyright | ||
6 | * notice, this list of conditions and the following disclaimer. | ||
7 | * * Redistributions in binary form must reproduce the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer in the | ||
9 | * documentation and/or other materials provided with the distribution. | ||
10 | * * Neither the name of Code Aurora nor | ||
11 | * the names of its contributors may be used to endorse or promote | ||
12 | * products derived from this software without specific prior written | ||
13 | * permission. | ||
14 | * | ||
15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
17 | * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
18 | * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||
19 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||
20 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||
21 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | ||
22 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | ||
23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||
24 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | ||
25 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | * | ||
27 | */ | ||
28 | |||
29 | #ifndef TVENC_H | ||
30 | #define TVENC_H | ||
31 | |||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/sched.h> | ||
34 | #include <linux/time.h> | ||
35 | #include <linux/init.h> | ||
36 | #include <linux/interrupt.h> | ||
37 | #include <linux/fb.h> | ||
38 | |||
39 | #include <mach/hardware.h> | ||
40 | #include <linux/io.h> | ||
41 | |||
42 | #include <asm/system.h> | ||
43 | #include <asm/mach-types.h> | ||
44 | |||
45 | #include "msm_fb_panel.h" | ||
46 | |||
47 | #define NTSC_M 0 /* North America, Korea */ | ||
48 | #define NTSC_J 1 /* Japan */ | ||
49 | #define PAL_BDGHIN 2 /* Non-argentina PAL-N */ | ||
50 | #define PAL_M 3 /* PAL-M */ | ||
51 | #define PAL_N 4 /* Argentina PAL-N */ | ||
52 | |||
53 | /* 3.57954545 Mhz */ | ||
54 | #define TVENC_CTL_TV_MODE_NTSC_M_PAL60 0 | ||
55 | /* 3.57961149 Mhz */ | ||
56 | #define TVENC_CTL_TV_MODE_PAL_M BIT(0) | ||
57 | /*non-Argintina = 4.3361875 Mhz */ | ||
58 | #define TVENC_CTL_TV_MODE_PAL_BDGHIN BIT(1) | ||
59 | /*Argentina = 3.582055625 Mhz */ | ||
60 | #define TVENC_CTL_TV_MODE_PAL_N (BIT(1)|BIT(0)) | ||
61 | |||
62 | #define TVENC_CTL_ENC_EN BIT(2) | ||
63 | #define TVENC_CTL_CC_EN BIT(3) | ||
64 | #define TVENC_CTL_CGMS_EN BIT(4) | ||
65 | #define TVENC_CTL_MACRO_EN BIT(5) | ||
66 | #define TVENC_CTL_Y_FILTER_W_NOTCH BIT(6) | ||
67 | #define TVENC_CTL_Y_FILTER_WO_NOTCH 0 | ||
68 | #define TVENC_CTL_Y_FILTER_EN BIT(7) | ||
69 | #define TVENC_CTL_CR_FILTER_EN BIT(8) | ||
70 | #define TVENC_CTL_CB_FILTER_EN BIT(9) | ||
71 | #define TVENC_CTL_SINX_FILTER_EN BIT(10) | ||
72 | #define TVENC_CTL_TEST_PATT_EN BIT(11) | ||
73 | #define TVENC_CTL_OUTPUT_INV BIT(12) | ||
74 | #define TVENC_CTL_PAL60_MODE BIT(13) | ||
75 | #define TVENC_CTL_NTSCJ_MODE BIT(14) | ||
76 | #define TVENC_CTL_TPG_CLRBAR 0 | ||
77 | #define TVENC_CTL_TPG_MODRAMP BIT(15) | ||
78 | #define TVENC_CTL_TPG_REDCLR BIT(16) | ||
79 | #define TVENC_CTL_S_VIDEO_EN BIT(19) | ||
80 | |||
81 | #ifdef TVENC_C | ||
82 | void *tvenc_base; | ||
83 | #else | ||
84 | extern void *tvenc_base; | ||
85 | #endif | ||
86 | |||
87 | #define TV_OUT(reg, v) writel(v, tvenc_base + MSM_##reg) | ||
88 | |||
89 | #define MSM_TV_ENC_CTL 0x00 | ||
90 | #define MSM_TV_LEVEL 0x04 | ||
91 | #define MSM_TV_GAIN 0x08 | ||
92 | #define MSM_TV_OFFSET 0x0c | ||
93 | #define MSM_TV_CGMS 0x10 | ||
94 | #define MSM_TV_SYNC_1 0x14 | ||
95 | #define MSM_TV_SYNC_2 0x18 | ||
96 | #define MSM_TV_SYNC_3 0x1c | ||
97 | #define MSM_TV_SYNC_4 0x20 | ||
98 | #define MSM_TV_SYNC_5 0x24 | ||
99 | #define MSM_TV_SYNC_6 0x28 | ||
100 | #define MSM_TV_SYNC_7 0x2c | ||
101 | #define MSM_TV_BURST_V1 0x30 | ||
102 | #define MSM_TV_BURST_V2 0x34 | ||
103 | #define MSM_TV_BURST_V3 0x38 | ||
104 | #define MSM_TV_BURST_V4 0x3c | ||
105 | #define MSM_TV_BURST_H 0x40 | ||
106 | #define MSM_TV_SOL_REQ_ODD 0x44 | ||
107 | #define MSM_TV_SOL_REQ_EVEN 0x48 | ||
108 | #define MSM_TV_DAC_CTL 0x4c | ||
109 | #define MSM_TV_TEST_MUX 0x50 | ||
110 | #define MSM_TV_TEST_MODE 0x54 | ||
111 | #define MSM_TV_TEST_MISR_RESET 0x58 | ||
112 | #define MSM_TV_TEST_EXPORT_MISR 0x5c | ||
113 | #define MSM_TV_TEST_MISR_CURR_VAL 0x60 | ||
114 | #define MSM_TV_TEST_SOF_CFG 0x64 | ||
115 | #define MSM_TV_DAC_INTF 0x100 | ||
116 | |||
117 | #endif /* TVENC_H */ | ||