aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging
diff options
context:
space:
mode:
authorStepan Moskovchenko <stepanm@codeaurora.org>2010-05-19 14:03:30 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-06-04 16:38:54 -0400
commit9d20015391dfc47f6371492925cc0333ac403414 (patch)
treea3c376e4b042f7280d2c1c12f054c8810dc67fe4 /drivers/staging
parent34ef545aa8c68d91e2e503ac05c129094772afb4 (diff)
Staging: add MSM framebuffer driver
Qualcomm development of the MSM SOC framebuffer driver has diverged significantly from the driver used by Android. This is a snapshot of our current driver, in all it's agony. We are putting this in staging to help with the process of converging the two drivers. At this point, the driver has been tested only in dumb framebuffer mode. Signed-off-by: Stepan Moskovchenko <stepanm@codeaurora.org> Signed-off-by: David Brown <davidb@codeaurora.org> Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org> [dwalker@codeaurora.org: added a small compile fix and TODO.] Signed-off-by: Daniel Walker <dwalker@codeaurora.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging')
-rw-r--r--drivers/staging/Kconfig2
-rw-r--r--drivers/staging/Makefile1
-rw-r--r--drivers/staging/msm/Kconfig134
-rw-r--r--drivers/staging/msm/Makefile93
-rw-r--r--drivers/staging/msm/TODO3
-rw-r--r--drivers/staging/msm/ebi2_l2f.c569
-rw-r--r--drivers/staging/msm/ebi2_lcd.c250
-rw-r--r--drivers/staging/msm/ebi2_tmd20.c1122
-rw-r--r--drivers/staging/msm/hdmi_sii9022.c248
-rw-r--r--drivers/staging/msm/lcdc.c239
-rw-r--r--drivers/staging/msm/lcdc_external.c54
-rw-r--r--drivers/staging/msm/lcdc_gordon.c446
-rw-r--r--drivers/staging/msm/lcdc_grapefruit.c60
-rw-r--r--drivers/staging/msm/lcdc_panel.c88
-rw-r--r--drivers/staging/msm/lcdc_prism.c64
-rw-r--r--drivers/staging/msm/lcdc_sharp_wvga_pt.c290
-rw-r--r--drivers/staging/msm/lcdc_st15.c237
-rw-r--r--drivers/staging/msm/lcdc_st1_wxga.c54
-rw-r--r--drivers/staging/msm/lcdc_toshiba_wvga_pt.c374
-rw-r--r--drivers/staging/msm/lcdc_wxga.c56
-rw-r--r--drivers/staging/msm/logo.c98
-rw-r--r--drivers/staging/msm/mddi.c375
-rw-r--r--drivers/staging/msm/mddi_ext.c320
-rw-r--r--drivers/staging/msm/mddi_ext_lcd.c91
-rw-r--r--drivers/staging/msm/mddi_prism.c114
-rw-r--r--drivers/staging/msm/mddi_sharp.c892
-rw-r--r--drivers/staging/msm/mddi_toshiba.c1741
-rw-r--r--drivers/staging/msm/mddi_toshiba.h52
-rw-r--r--drivers/staging/msm/mddi_toshiba_vga.c136
-rw-r--r--drivers/staging/msm/mddi_toshiba_wvga.c63
-rw-r--r--drivers/staging/msm/mddi_toshiba_wvga_pt.c64
-rw-r--r--drivers/staging/msm/mddihost.c377
-rw-r--r--drivers/staging/msm/mddihost.h225
-rw-r--r--drivers/staging/msm/mddihost_e.c63
-rw-r--r--drivers/staging/msm/mddihosti.c2239
-rw-r--r--drivers/staging/msm/mddihosti.h547
-rw-r--r--drivers/staging/msm/mdp.c1113
-rw-r--r--drivers/staging/msm/mdp.h695
-rw-r--r--drivers/staging/msm/mdp4.h352
-rw-r--r--drivers/staging/msm/mdp4_debugfs.c181
-rw-r--r--drivers/staging/msm/mdp4_overlay.c1259
-rw-r--r--drivers/staging/msm/mdp4_overlay_lcdc.c313
-rw-r--r--drivers/staging/msm/mdp4_overlay_mddi.c254
-rw-r--r--drivers/staging/msm/mdp4_util.c1686
-rw-r--r--drivers/staging/msm/mdp_cursor.c104
-rw-r--r--drivers/staging/msm/mdp_dma.c561
-rw-r--r--drivers/staging/msm/mdp_dma_lcdc.c379
-rw-r--r--drivers/staging/msm/mdp_dma_s.c139
-rw-r--r--drivers/staging/msm/mdp_dma_tv.c142
-rw-r--r--drivers/staging/msm/mdp_hw_init.c720
-rw-r--r--drivers/staging/msm/mdp_ppp.c1502
-rw-r--r--drivers/staging/msm/mdp_ppp_dq.c347
-rw-r--r--drivers/staging/msm/mdp_ppp_dq.h86
-rw-r--r--drivers/staging/msm/mdp_ppp_v20.c2486
-rw-r--r--drivers/staging/msm/mdp_ppp_v31.c828
-rw-r--r--drivers/staging/msm/mdp_vsync.c389
-rw-r--r--drivers/staging/msm/memory.c214
-rw-r--r--drivers/staging/msm/memory_ll.h61
-rw-r--r--drivers/staging/msm/msm_fb.c2354
-rw-r--r--drivers/staging/msm/msm_fb.h174
-rw-r--r--drivers/staging/msm/msm_fb_bl.c79
-rw-r--r--drivers/staging/msm/msm_fb_def.h201
-rw-r--r--drivers/staging/msm/msm_fb_panel.c136
-rw-r--r--drivers/staging/msm/msm_fb_panel.h145
-rw-r--r--drivers/staging/msm/msm_mdp.h245
-rw-r--r--drivers/staging/msm/staging-devices.c323
-rw-r--r--drivers/staging/msm/tv_ntsc.c163
-rw-r--r--drivers/staging/msm/tv_pal.c213
-rw-r--r--drivers/staging/msm/tvenc.c295
-rw-r--r--drivers/staging/msm/tvenc.h117
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
146source "drivers/staging/mrst-touchscreen/Kconfig" 146source "drivers/staging/mrst-touchscreen/Kconfig"
147 147
148source "drivers/staging/msm/Kconfig"
149
148endif # !STAGING_EXCLUDE_BUILD 150endif # !STAGING_EXCLUDE_BUILD
149endif # STAGING 151endif # 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/
53obj-$(CONFIG_ADIS16255) += adis16255/ 53obj-$(CONFIG_ADIS16255) += adis16255/
54obj-$(CONFIG_FB_XGI) += xgifb/ 54obj-$(CONFIG_FB_XGI) += xgifb/
55obj-$(CONFIG_TOUCHSCREEN_MRSTOUCH) += mrst-touchscreen/ 55obj-$(CONFIG_TOUCHSCREEN_MRSTOUCH) += mrst-touchscreen/
56obj-$(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 @@
1config 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
13if MSM_STAGING
14
15config FB_MSM_LCDC_HW
16 bool
17 default n
18
19choice
20 prompt "MDP HW version"
21 default FB_MSM_MDP31
22
23config 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.
29endchoice
30
31config FB_MSM_LCDC
32 bool
33 default n
34
35config FB_MSM_TVOUT
36 bool
37 default n
38
39config FB_MSM_LCDC_PANEL
40 bool
41 select FB_MSM_LCDC
42 default n
43
44config FB_MSM_LCDC_PRISM_WVGA
45 bool
46 select FB_MSM_LCDC_PANEL
47 default n
48
49config FB_MSM_LCDC_ST1_WXGA
50 bool
51 select FB_MSM_LCDC_PANEL
52 default n
53
54config FB_MSM_LCDC_ST15_WXGA
55 bool
56 select FB_MSM_LCDC_PANEL
57 default n
58
59config FB_MSM_LCDC_WXGA
60 bool
61 select FB_MSM_LCDC_PANEL
62 default n
63
64choice
65 prompt "LCD Panel"
66 default FB_MSM_LCDC_ST15_PANEL
67
68config 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
76config 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
83config FB_MSM_PANEL_NONE
84 bool "NONE"
85 ---help---
86 This will disable LCD panel
87endchoice
88
89choice
90 prompt "Secondary LCD Panel"
91 depends on FB_MSM_MDP31
92 default FB_MSM_SECONDARY_PANEL_NONE
93
94config FB_MSM_SECONDARY_PANEL_NONE
95 bool "NONE"
96 ---help---
97 No secondary panel
98endchoice
99
100config FB_MSM_TVOUT_NTSC
101 bool
102 select FB_MSM_TVOUT
103 default n
104
105config FB_MSM_TVOUT_PAL
106 bool
107 select FB_MSM_TVOUT
108 default n
109
110choice
111 depends on (FB_MSM_MDP22 || FB_MSM_MDP31)
112 prompt "TVOut Region"
113 default FB_MSM_TVOUT_NTSC_M
114
115config 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
121config FB_MSM_TVOUT_NONE
122 bool "NONE"
123 ---help---
124 This will disable TV Out functionality.
125endchoice
126
127config 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)
134endif
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 @@
1obj-y := msm_fb.o staging-devices.o memory.o
2
3obj-$(CONFIG_FB_MSM_LOGO) += logo.o
4obj-$(CONFIG_FB_BACKLIGHT) += msm_fb_bl.o
5
6# MDP
7obj-y += mdp.o
8
9ifeq ($(CONFIG_FB_MSM_MDP40),y)
10obj-y += mdp4_util.o
11obj-$(CONFIG_DEBUG_FS) += mdp4_debugfs.o
12else
13obj-y += mdp_hw_init.o
14obj-y += mdp_ppp.o
15ifeq ($(CONFIG_FB_MSM_MDP31),y)
16obj-y += mdp_ppp_v31.o
17obj-$(CONFIG_MDP_PPP_ASYNC_OP) += mdp_ppp_dq.o
18else
19obj-y += mdp_ppp_v20.o
20endif
21endif
22
23ifeq ($(CONFIG_FB_MSM_OVERLAY),y)
24obj-y += mdp4_overlay.o
25obj-y += mdp4_overlay_lcdc.o
26obj-y += mdp4_overlay_mddi.o
27else
28obj-y += mdp_dma_lcdc.o
29endif
30
31obj-y += mdp_dma.o
32obj-y += mdp_dma_s.o
33obj-y += mdp_vsync.o
34obj-y += mdp_cursor.o
35obj-y += mdp_dma_tv.o
36
37# EBI2
38obj-$(CONFIG_FB_MSM_EBI2) += ebi2_lcd.o
39
40# LCDC
41obj-$(CONFIG_FB_MSM_LCDC) += lcdc.o
42
43# MDDI
44msm_mddi-objs := mddi.o mddihost.o mddihosti.o
45obj-$(CONFIG_FB_MSM_MDDI) += msm_mddi.o
46
47# External MDDI
48msm_mddi_ext-objs := mddihost_e.o mddi_ext.o
49obj-$(CONFIG_FB_MSM_EXTMDDI) += msm_mddi_ext.o
50
51# TVEnc
52obj-$(CONFIG_FB_MSM_TVOUT) += tvenc.o
53
54# MSM FB Panel
55obj-y += msm_fb_panel.o
56obj-$(CONFIG_FB_MSM_EBI2_TMD_QVGA_EPSON_QCIF) += ebi2_tmd20.o
57obj-$(CONFIG_FB_MSM_EBI2_TMD_QVGA_EPSON_QCIF) += ebi2_l2f.o
58
59ifeq ($(CONFIG_FB_MSM_MDDI_AUTO_DETECT),y)
60obj-y += mddi_prism.o
61obj-y += mddi_toshiba.o
62obj-y += mddi_toshiba_vga.o
63obj-y += mddi_toshiba_wvga_pt.o
64obj-y += mddi_toshiba_wvga.o
65obj-y += mddi_sharp.o
66else
67obj-$(CONFIG_FB_MSM_MDDI_PRISM_WVGA) += mddi_prism.o
68obj-$(CONFIG_FB_MSM_MDDI_TOSHIBA_COMMON) += mddi_toshiba.o
69obj-$(CONFIG_FB_MSM_MDDI_TOSHIBA_COMMON_VGA) += mddi_toshiba_vga.o
70obj-$(CONFIG_FB_MSM_MDDI_TOSHIBA_WVGA_PORTRAIT) += mddi_toshiba_wvga_pt.o
71obj-$(CONFIG_FB_MSM_MDDI_TOSHIBA_WVGA) += mddi_toshiba_wvga.o
72obj-$(CONFIG_FB_MSM_MDDI_SHARP_QVGA_128x128) += mddi_sharp.o
73endif
74
75obj-$(CONFIG_FB_MSM_LCDC_PANEL) += lcdc_panel.o
76obj-$(CONFIG_FB_MSM_LCDC_PRISM_WVGA) += lcdc_prism.o
77obj-$(CONFIG_FB_MSM_LCDC_EXTERNAL_WXGA) += lcdc_external.o
78obj-$(CONFIG_FB_MSM_LCDC_GORDON_VGA) += lcdc_gordon.o
79obj-$(CONFIG_FB_MSM_LCDC_WXGA) += lcdc_wxga.o
80obj-$(CONFIG_FB_MSM_LCDC_TOSHIBA_WVGA_PT) += lcdc_toshiba_wvga_pt.o
81obj-$(CONFIG_FB_MSM_LCDC_SHARP_WVGA_PT) += lcdc_sharp_wvga_pt.o
82obj-$(CONFIG_FB_MSM_LCDC_GRAPEFRUIT_VGA) += lcdc_grapefruit.o
83obj-$(CONFIG_FB_MSM_LCDC_ST1_WXGA) += lcdc_st1_wxga.o
84obj-$(CONFIG_FB_MSM_LCDC_ST15_WXGA) += lcdc_st15.o
85obj-$(CONFIG_FB_MSM_HDMI_SII_EXTERNAL_720P) += hdmi_sii9022.o
86
87obj-$(CONFIG_FB_MSM_TVOUT_NTSC) += tv_ntsc.o
88obj-$(CONFIG_FB_MSM_TVOUT_PAL) += tv_pal.o
89
90obj-$(CONFIG_FB_MSM_EXTMDDI_SVGA) += mddi_ext_lcd.o
91
92clean:
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
55static void *DISP_CMD_PORT;
56static 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
124static word disp_area_start_row;
125static word disp_area_end_row;
126static byte disp_contrast = DISP_DEFAULT_CONTRAST;
127static boolean disp_powered_up;
128static boolean disp_initialized = FALSE;
129/* For some reason the contrast set at init time is not good. Need to do
130 * it again
131 */
132static boolean display_on = FALSE;
133static void epsonQcif_disp_init(struct platform_device *pdev);
134static void epsonQcif_disp_set_contrast(word contrast);
135static void epsonQcif_disp_set_display_area(word start_row, word end_row);
136static int epsonQcif_disp_off(struct platform_device *pdev);
137static int epsonQcif_disp_on(struct platform_device *pdev);
138static void epsonQcif_disp_set_rect(int x, int y, int xres, int yres);
139
140volatile word databack;
141static 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
403static 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
412static 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
455static 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
469static 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
485static 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
504static 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
516static int __init epsonQcif_probe(struct platform_device *pdev)
517{
518 msm_fb_add_device(pdev);
519
520 return 0;
521}
522
523static struct platform_driver this_driver = {
524 .probe = epsonQcif_probe,
525 .driver = {
526 .name = "ebi2_epson_qcif",
527 },
528};
529
530static 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
536static struct platform_device this_device = {
537 .name = "ebi2_epson_qcif",
538 .id = 0,
539 .dev = {
540 .platform_data = &epsonQcif_panel_data,
541 }
542};
543
544static 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
569module_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
39static int ebi2_lcd_probe(struct platform_device *pdev);
40static int ebi2_lcd_remove(struct platform_device *pdev);
41
42static 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
55static void *ebi2_base;
56static void *ebi2_lcd_cfg0;
57static void *ebi2_lcd_cfg1;
58static void __iomem *lcd01_base;
59static void __iomem *lcd02_base;
60static int ebi2_lcd_resource_initialized;
61
62static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
63static int pdev_list_cnt;
64
65static 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
223static 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
240static int ebi2_lcd_register_driver(void)
241{
242 return platform_driver_register(&ebi2_lcd_driver);
243}
244
245static int __init ebi2_lcd_driver_init(void)
246{
247 return ebi2_lcd_register_driver();
248}
249
250module_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
52static void *DISP_CMD_PORT;
53static 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
102DISP_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
651static word disp_area_start_row;
652static word disp_area_end_row;
653static boolean disp_initialized = FALSE;
654/* For some reason the contrast set at init time is not good. Need to do
655* it again
656*/
657static boolean display_on = FALSE;
658
659static uint32 tmd20qvga_lcd_rev;
660uint16 tmd20qvga_panel_offset;
661
662#ifdef DISP_DEVICE_8BPP
663static 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
699static void tmd20qvga_disp_set_rect(int x, int y, int xres, int yres);
700static void tmd20qvga_disp_init(struct platform_device *pdev);
701static void tmd20qvga_disp_set_contrast(void);
702static void tmd20qvga_disp_set_display_area(word start_row, word end_row);
703static int tmd20qvga_disp_off(struct platform_device *pdev);
704static int tmd20qvga_disp_on(struct platform_device *pdev);
705static void tmd20qvga_set_revId(int);
706
707/* future use */
708void tmd20qvga_disp_clear_screen_area(word start_row, word end_row,
709 word start_column, word end_column);
710
711static 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
722static 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
745static 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
755static 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
813static 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
856static 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
1009static 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
1047void 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
1059static int __init tmd20qvga_probe(struct platform_device *pdev)
1060{
1061 msm_fb_add_device(pdev);
1062
1063 return 0;
1064}
1065
1066static struct platform_driver this_driver = {
1067 .probe = tmd20qvga_probe,
1068 .driver = {
1069 .name = "ebi2_tmd_qvga",
1070 },
1071};
1072
1073static 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
1079static struct platform_device this_device = {
1080 .name = "ebi2_tmd_qvga",
1081 .id = 0,
1082 .dev = {
1083 .platform_data = &tmd20qvga_panel_data,
1084 }
1085};
1086
1087static 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
1122module_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
25struct sii9022_i2c_addr_data{
26 u8 addr;
27 u8 data;
28};
29
30/* video mode data */
31static u8 video_mode_data[] = {
32 0x00,
33 0xF9, 0x1C, 0x70, 0x17, 0x72, 0x06, 0xEE, 0x02,
34};
35
36static u8 avi_io_format[] = {
37 0x09,
38 0x00, 0x00,
39};
40
41/* power state */
42static struct sii9022_i2c_addr_data regset0[] = {
43 { 0x60, 0x04 },
44 { 0x63, 0x00 },
45 { 0x1E, 0x00 },
46};
47
48static 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 */
55static 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 */
68static 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 */
75static struct sii9022_i2c_addr_data regset2[] = {
76 { 0x1A, 0x01 },
77 { 0x3D, 0x00 },
78};
79
80static 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
97static 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;
163enable_exit:
164 printk(KERN_ERR "%s: exited rc=%d\n", __func__, rc);
165 return rc;
166}
167
168static const struct i2c_device_id hmdi_sii_id[] = {
169 { DEVICE_NAME, 0 },
170 { }
171};
172
173static 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
186static 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
196static 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
233init_exit:
234 return ret;
235}
236
237static void __exit hdmi_sii_exit(void)
238{
239 i2c_del_driver(&hdmi_sii_i2c_driver);
240}
241
242module_init(hdmi_sii_init);
243module_exit(hdmi_sii_exit);
244MODULE_LICENSE("GPL v2");
245MODULE_VERSION("0.1");
246MODULE_AUTHOR("Qualcomm Innovation Center, Inc.");
247MODULE_DESCRIPTION("SiI9022 HDMI driver");
248MODULE_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
39static int lcdc_probe(struct platform_device *pdev);
40static int lcdc_remove(struct platform_device *pdev);
41
42static int lcdc_off(struct platform_device *pdev);
43static int lcdc_on(struct platform_device *pdev);
44
45static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
46static int pdev_list_cnt;
47
48static struct clk *mdp_lcdc_pclk_clk;
49static struct clk *mdp_lcdc_pad_pclk_clk;
50
51int mdp_lcdc_pclk_clk_rate;
52int mdp_lcdc_pad_pclk_clk_rate;
53
54static 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
65static struct lcdc_platform_data *lcdc_pdata;
66
67static 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
88static 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
124static 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
206lcdc_probe_err:
207 platform_device_put(mdp_dev);
208 return rc;
209}
210
211static int lcdc_remove(struct platform_device *pdev)
212{
213// pm_qos_remove_requirement(PM_QOS_SYSTEM_BUS_FREQ , "lcdc");
214 return 0;
215}
216
217static int lcdc_register_driver(void)
218{
219 return platform_driver_register(&lcdc_driver);
220}
221
222static 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
239module_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
20static 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
54module_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
84static int lcdc_gordon_panel_off(struct platform_device *pdev);
85
86static int spi_cs;
87static int spi_sclk;
88static int spi_sdo;
89static int spi_sdi;
90static int spi_dac;
91static 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
101struct gordon_state_type{
102 boolean disp_initialized;
103 boolean display_on;
104 boolean disp_powered_up;
105};
106
107static struct gordon_state_type gordon_state = { 0 };
108static struct msm_panel_common_pdata *lcdc_gordon_pdata;
109
110static 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
166static 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
183static 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
192static 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
209static 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
308static 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
325static 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
356static 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
373static 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
383static struct platform_driver this_driver = {
384 .probe = gordon_probe,
385 .driver = {
386 .name = "lcdc_gordon_vga",
387 },
388};
389
390static 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
396static struct platform_device this_device = {
397 .name = "lcdc_gordon_vga",
398 .id = 1,
399 .dev = {
400 .platform_data = &gordon_panel_data,
401 }
402};
403
404static 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
446module_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
24static 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
60module_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
20static int lcdc_panel_on(struct platform_device *pdev)
21{
22 return 0;
23}
24
25static int lcdc_panel_off(struct platform_device *pdev)
26{
27 return 0;
28}
29
30static int __init lcdc_panel_probe(struct platform_device *pdev)
31{
32 msm_fb_add_device(pdev);
33
34 return 0;
35}
36
37static struct platform_driver this_driver = {
38 .probe = lcdc_panel_probe,
39 .driver = {
40 .name = "lcdc_panel",
41 },
42};
43
44static struct msm_fb_panel_data lcdc_panel_data = {
45 .on = lcdc_panel_on,
46 .off = lcdc_panel_off,
47};
48
49static int lcdc_dev_id;
50
51int 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
78err_device_put:
79 platform_device_put(pdev);
80 return ret;
81}
82
83static int __init lcdc_panel_init(void)
84{
85 return platform_driver_register(&this_driver);
86}
87
88module_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
24static 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
64module_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
25static int lcdc_sharp_panel_off(struct platform_device *pdev);
26
27static int spi_cs;
28static int spi_sclk;
29static int spi_mosi;
30static int spi_miso;
31static 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
41struct sharp_state_type {
42 boolean disp_initialized;
43 boolean display_on;
44 boolean disp_powered_up;
45};
46
47struct sharp_spi_data {
48 u8 addr;
49 u8 data;
50};
51
52static 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
111static struct sharp_state_type sharp_state = { 0 };
112static struct msm_panel_common_pdata *lcdc_sharp_pdata;
113
114static 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
132static 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
150static 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
165static 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
171static 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
190static 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
202static 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
217static 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
227static struct platform_driver this_driver = {
228 .probe = sharp_probe,
229 .driver = {
230 .name = "lcdc_sharp_wvga",
231 },
232};
233
234static struct msm_fb_panel_data sharp_panel_data = {
235 .on = lcdc_sharp_panel_on,
236 .off = lcdc_sharp_panel_off,
237};
238
239static struct platform_device this_device = {
240 .name = "lcdc_sharp_wvga",
241 .id = 1,
242 .dev = {
243 .platform_data = &sharp_panel_data,
244 }
245};
246
247static 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
290module_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
25struct sii9022_i2c_addr_data{
26 u8 addr;
27 u8 data;
28};
29
30/* video mode data */
31static u8 video_mode_data[] = {
32 0x00,
33 0xF9, 0x1C, 0x70, 0x17, 0x72, 0x06, 0xEE, 0x02,
34};
35
36static u8 avi_io_format[] = {
37 0x09,
38 0x00, 0x00,
39};
40
41/* power state */
42static struct sii9022_i2c_addr_data regset0[] = {
43 { 0x60, 0x04 },
44 { 0x63, 0x00 },
45 { 0x1E, 0x00 },
46};
47
48static 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 */
55static 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 */
68static 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 */
75static struct sii9022_i2c_addr_data regset2[] = {
76 { 0x1A, 0x01 },
77 { 0x3D, 0x00 },
78};
79
80static 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
97static 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;
163enable_exit:
164 printk(KERN_ERR "%s: exited rc=%d\n", __func__, rc);
165 return rc;
166}
167
168static const struct i2c_device_id hmdi_sii_id[] = {
169 { DEVICE_NAME, 0 },
170 { }
171};
172
173static 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
186static 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
196static 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
233init_exit:
234 return ret;
235}
236
237module_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
20static 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
54module_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
28static int spi_cs;
29static int spi_sclk;
30static int spi_mosi;
31static int spi_miso;
32
33struct toshiba_state_type{
34 boolean disp_initialized;
35 boolean display_on;
36 boolean disp_powered_up;
37};
38
39static struct toshiba_state_type toshiba_state = { 0 };
40static struct msm_panel_common_pdata *lcdc_toshiba_pdata;
41
42static 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
69static 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
93void 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
133static 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
142static 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
151static 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
247static 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
260static 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
281static 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
294static 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
305static struct platform_driver this_driver = {
306 .probe = toshiba_probe,
307 .driver = {
308 .name = "lcdc_toshiba_wvga",
309 },
310};
311
312static 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
318static struct platform_device this_device = {
319 .name = "lcdc_toshiba_wvga",
320 .id = 1,
321 .dev = {
322 .platform_data = &toshiba_panel_data,
323 }
324};
325
326static 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
374device_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
20static 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
56module_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
31static 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)] */
40int 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
92err_logo_free_data:
93 kfree(data);
94err_logo_close_file:
95 sys_close(fd);
96 return err;
97}
98EXPORT_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
42static int mddi_probe(struct platform_device *pdev);
43static int mddi_remove(struct platform_device *pdev);
44
45static int mddi_off(struct platform_device *pdev);
46static int mddi_on(struct platform_device *pdev);
47
48static int mddi_suspend(struct platform_device *pdev, pm_message_t state);
49static int mddi_resume(struct platform_device *pdev);
50
51#ifdef CONFIG_HAS_EARLYSUSPEND
52static void mddi_early_suspend(struct early_suspend *h);
53static void mddi_early_resume(struct early_suspend *h);
54#endif
55
56static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
57static int pdev_list_cnt;
58static struct clk *mddi_clk;
59static struct clk *mddi_pclk;
60static struct mddi_platform_data *mddi_pdata;
61
62static 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
79extern int int_mddi_pri_flag;
80
81static 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
93static 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
123static int mddi_resource_initialized;
124
125static 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
236mddi_probe_err:
237 platform_device_put(mdp_dev);
238 return rc;
239}
240
241static int mddi_pad_ctrl;
242static int mddi_power_locked;
243static int mddi_is_in_suspend;
244
245void 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
273static 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
283static 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
308static 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
318static 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
326static 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
336static int mddi_register_driver(void)
337{
338 return platform_driver_register(&mddi_driver);
339}
340
341static 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
375module_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
40static int mddi_ext_probe(struct platform_device *pdev);
41static int mddi_ext_remove(struct platform_device *pdev);
42
43static int mddi_ext_off(struct platform_device *pdev);
44static int mddi_ext_on(struct platform_device *pdev);
45
46static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
47static int pdev_list_cnt;
48
49static int mddi_ext_suspend(struct platform_device *pdev, pm_message_t state);
50static int mddi_ext_resume(struct platform_device *pdev);
51
52#ifdef CONFIG_HAS_EARLYSUSPEND
53static void mddi_ext_early_suspend(struct early_suspend *h);
54static void mddi_ext_early_resume(struct early_suspend *h);
55#endif
56
57static 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
74static struct clk *mddi_ext_clk;
75static struct mddi_platform_data *mddi_ext_pdata;
76
77extern int int_mddi_ext_flag;
78
79static 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
89static 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
117static int mddi_ext_resource_initialized;
118
119static 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
227mddi_ext_probe_err:
228 platform_device_put(mdp_dev);
229 return rc;
230}
231
232static int mddi_ext_is_in_suspend;
233
234static 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
250static 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
268static 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
278static 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
286static int mddi_ext_remove(struct platform_device *pdev)
287{
288 iounmap(msm_emdh_base);
289 return 0;
290}
291
292static int mddi_ext_register_driver(void)
293{
294 return platform_driver_register(&mddi_ext_driver);
295}
296
297static 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
320module_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
22static int mddi_ext_lcd_on(struct platform_device *pdev);
23static int mddi_ext_lcd_off(struct platform_device *pdev);
24
25static int mddi_ext_lcd_on(struct platform_device *pdev)
26{
27 return 0;
28}
29
30static int mddi_ext_lcd_off(struct platform_device *pdev)
31{
32 return 0;
33}
34
35static int __init mddi_ext_lcd_probe(struct platform_device *pdev)
36{
37 msm_fb_add_device(pdev);
38
39 return 0;
40}
41
42static struct platform_driver this_driver = {
43 .probe = mddi_ext_lcd_probe,
44 .driver = {
45 .name = "extmddi_svga",
46 },
47};
48
49static 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
64static 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
72static 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
91module_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
22static int prism_lcd_on(struct platform_device *pdev);
23static int prism_lcd_off(struct platform_device *pdev);
24
25static 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
33static int prism_lcd_off(struct platform_device *pdev)
34{
35 return 0;
36}
37
38static int __init prism_probe(struct platform_device *pdev)
39{
40 msm_fb_add_device(pdev);
41
42 return 0;
43}
44
45static struct platform_driver this_driver = {
46 .probe = prism_probe,
47 .driver = {
48 .name = "mddi_prism_wvga",
49 },
50};
51
52static struct msm_fb_panel_data prism_panel_data = {
53 .on = prism_lcd_on,
54 .off = prism_lcd_off,
55};
56
57static struct platform_device this_device = {
58 .name = "mddi_prism_wvga",
59 .id = 0,
60 .dev = {
61 .platform_data = &prism_panel_data,
62 }
63};
64
65static 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
114module_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
25extern uint32 mddi_host_core_version;
26static boolean mddi_debug_prim_wait = FALSE;
27static boolean mddi_sharp_vsync_wake = TRUE;
28static boolean mddi_sharp_monitor_refresh_value = TRUE;
29static boolean mddi_sharp_report_refresh_measurements = FALSE;
30static uint32 mddi_sharp_rows_per_second = 13830; /* 5200000/376 */
31static uint32 mddi_sharp_rows_per_refresh = 338;
32static uint32 mddi_sharp_usecs_per_refresh = 24440; /* (376+338)/5200000 */
33static boolean mddi_sharp_debug_60hz_refresh = FALSE;
34
35extern mddi_gpio_info_type mddi_gpio;
36extern boolean mddi_vsync_detect_enabled;
37static msm_fb_vsync_handler_type mddi_sharp_vsync_handler;
38static void *mddi_sharp_vsync_handler_arg;
39static uint16 mddi_sharp_vsync_attempts;
40
41static void mddi_sharp_prim_lcd_init(void);
42static void mddi_sharp_sub_lcd_init(void);
43static void mddi_sharp_lcd_set_backlight(struct msm_fb_data_type *mfd);
44static void mddi_sharp_vsync_set_handler(msm_fb_vsync_handler_type handler,
45 void *);
46static void mddi_sharp_lcd_vsync_detected(boolean detected);
47static 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
93static uint32 sharp_subpanel_type = SHARP_SUB_UNKNOWN;
94
95static 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
115static 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
139static 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
157static 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
186static 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, &regdata, 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, &regdata, TRUE, 0);
208 mddi_queue_register_write(REG_GIOD,
209 (regdata & 0xfff8) | (0x07 & level), TRUE, 0);
210 }
211}
212
213static 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
329void 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
614void 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 */
689void 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
719static 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
739static int mddi_sharp_lcd_off(struct platform_device *pdev)
740{
741 mddi_sharp_lcd_powerdown();
742 return 0;
743}
744
745static 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
757static struct platform_driver this_driver = {
758 .probe = mddi_sharp_probe,
759 .driver = {
760 .name = "mddi_sharp_qvga",
761 },
762};
763
764static 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
771static 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
779static struct msm_fb_panel_data mddi_sharp_panel_data1 = {
780 .on = mddi_sharp_lcd_on,
781 .off = mddi_sharp_lcd_off,
782};
783
784static 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
792static 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
892module_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
106typedef 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
114static uint32 mddi_toshiba_curr_vpos;
115static boolean mddi_toshiba_monitor_refresh_value = FALSE;
116static boolean mddi_toshiba_report_refresh_measurements = FALSE;
117
118boolean 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 */
126static uint32 mddi_toshiba_rows_per_second = 39526;
127static uint32 mddi_toshiba_usecs_per_refresh = 16344;
128static uint32 mddi_toshiba_rows_per_refresh = 646;
129extern boolean mddi_vsync_detect_enabled;
130
131static msm_fb_vsync_handler_type mddi_toshiba_vsync_handler;
132static void *mddi_toshiba_vsync_handler_arg;
133static uint16 mddi_toshiba_vsync_attempts;
134
135static mddi_toshiba_state_t toshiba_state = TOSHIBA_STATE_OFF;
136
137static struct msm_panel_common_pdata *mddi_toshiba_pdata;
138
139static int mddi_toshiba_lcd_on(struct platform_device *pdev);
140static int mddi_toshiba_lcd_off(struct platform_device *pdev);
141
142static 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
225void 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
236void 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
253void 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
344void 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
365void gordon_disp_init(void)
366{
367 gordon_init();
368 mddi_wait(20);
369 gordon_disp_on();
370}
371
372static 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
879static 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
962static 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
1134static 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
1165static 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
1217static 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
1251static 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
1266static 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
1282static 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
1335static 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
1396static 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
1428static 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
1460static 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
1542static 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
1573static 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
1597static 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
1621static int mddi_sharpgordon_firsttime = 1;
1622
1623static 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
1645static int mddi_toshiba_lcd_off(struct platform_device *pdev)
1646{
1647 mddi_toshiba_lcd_powerdown(platform_get_drvdata(pdev));
1648 return 0;
1649}
1650
1651static 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
1663static struct platform_driver this_driver = {
1664 .probe = mddi_toshiba_lcd_probe,
1665 .driver = {
1666 .name = "mddi_toshiba",
1667 },
1668};
1669
1670static struct msm_fb_panel_data toshiba_panel_data = {
1671 .on = mddi_toshiba_lcd_on,
1672 .off = mddi_toshiba_lcd_off,
1673};
1674
1675static int ch_used[3];
1676
1677int 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
1731err_device_put:
1732 platform_device_put(pdev);
1733 return ret;
1734}
1735
1736static int __init mddi_toshiba_lcd_init(void)
1737{
1738 return platform_driver_register(&this_driver);
1739}
1740
1741module_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
23static uint32 read_client_reg(uint32 addr)
24{
25 uint32 val;
26 mddi_queue_register_read(addr, &val, TRUE, 0);
27 return val;
28}
29
30static 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
43static 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
67static 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
136module_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
22static 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
63module_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
23static 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
64module_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
36struct semaphore mddi_host_mutex;
37
38struct clk *mddi_io_clk;
39static boolean mddi_host_powered = FALSE;
40static boolean mddi_host_initialized = FALSE;
41extern uint32 *mddi_reg_read_value_ptr;
42
43mddi_lcd_func_type mddi_lcd;
44
45extern mddi_client_capability_type mddi_client_capability_pkt;
46
47#ifdef FEATURE_MDDI_HITACHI
48extern void mddi_hitachi_window_adjust(uint16 x1,
49 uint16 x2, uint16 y1, uint16 y2);
50#endif
51
52extern void mddi_toshiba_lcd_init(void);
53
54#ifdef FEATURE_MDDI_S6D0142
55extern void mddi_s6d0142_lcd_init(void);
56extern 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
63void 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
81int 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
155int 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 *)(&regacc_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
230boolean 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
282boolean 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
339void mddi_wait(uint16 time_ms)
340{
341 mdelay(time_ms);
342}
343
344void 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 */
351void 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
373void 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
63typedef enum {
64 format_16bpp,
65 format_18bpp,
66 format_24bpp
67} mddi_video_format;
68
69typedef 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
84typedef enum {
85 MDDI_HOST_PRIM = 0,
86 MDDI_HOST_EXT,
87 MDDI_NUM_HOST_CORES
88} mddi_host_type;
89
90typedef 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
96typedef 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
116enum 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
124typedef struct {
125 uint32 addr;
126 uint32 value;
127} mddi_reg_write_type;
128
129boolean mddi_vsync_set_handler(msm_fb_vsync_handler_type handler, void *arg);
130
131typedef void (*mddi_llist_done_cb_type) (void);
132
133typedef void (*mddi_rev_handler_type) (void *);
134
135boolean 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
140typedef int gpio_int_polarity_type;
141typedef int gpio_int_handler_type;
142
143typedef struct {
144 void (*vsync_detected) (boolean);
145} mddi_lcd_func_type;
146
147extern mddi_lcd_func_type mddi_lcd;
148void mddi_init(void);
149
150void mddi_powerdown(void);
151
152void mddi_host_start_ext_display(void);
153void mddi_host_stop_ext_display(void);
154
155extern spinlock_t mddi_host_spin_lock;
156#ifdef T_MSM7500
157void mddi_reset(void);
158#ifdef FEATURE_DUAL_PROC_MODEM_DISPLAY
159void mddi_host_switch_proc_control(boolean on);
160#endif
161#endif
162void mddi_host_exit_power_collapse(void);
163
164void 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
173void 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
183int mddi_host_register_read
184 (uint32 reg_addr,
185 uint32 *reg_value_ptr, boolean wait, mddi_host_type host_idx);
186int 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);
190boolean mddi_host_register_write_int
191 (uint32 reg_addr,
192 uint32 reg_val, mddi_llist_done_cb_type done_cb, mddi_host_type host);
193boolean mddi_host_register_read_int
194 (uint32 reg_addr, uint32 *reg_value_ptr, mddi_host_type host_idx);
195void mddi_queue_register_write_static
196 (uint32 reg_addr,
197 uint32 reg_val, boolean wait, mddi_llist_done_cb_type done_cb);
198void 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
217void mddi_wait(uint16 time_ms);
218void mddi_assign_max_pkt_dimensions(uint16 image_cols,
219 uint16 image_rows,
220 uint16 bpp,
221 uint16 *max_cols, uint16 * max_rows);
222uint16 mddi_assign_pkt_height(uint16 pkt_width, uint16 pkt_height, uint16 bpp);
223void mddi_queue_reverse_encapsulation(boolean wait);
224void 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
36extern struct semaphore mddi_host_mutex;
37static boolean mddi_host_ext_powered = FALSE;
38
39void 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
52void 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
35static void mddi_read_rev_packet(byte *data_ptr);
36#endif
37
38struct timer_list mddi_host_timer;
39
40#define MDDI_DEFAULT_TIMER_LENGTH 5000 /* 5 seconds */
41uint32 mddi_rtd_frequency = 60000; /* send RTD every 60 seconds */
42uint32 mddi_client_status_frequency = 60000; /* get status pkt every 60 secs */
43
44boolean mddi_vsync_detect_enabled = FALSE;
45mddi_gpio_info_type mddi_gpio;
46
47uint32 mddi_host_core_version;
48boolean mddi_debug_log_statistics = FALSE;
49/* #define FEATURE_MDDI_HOST_ENABLE_EARLY_HIBERNATION */
50/* default to TRUE in case MDP does not vote */
51static boolean mddi_host_mdp_active_flag = TRUE;
52static uint32 mddi_log_stats_counter;
53uint32 mddi_log_stats_frequency = 4000;
54
55#define MDDI_DEFAULT_REV_PKT_SIZE 0x20
56
57#ifndef FEATURE_MDDI_DISABLE_REVERSE
58static boolean mddi_rev_ptr_workaround = TRUE;
59static uint32 mddi_reg_read_retry;
60static uint32 mddi_reg_read_retry_max = 20;
61static boolean mddi_enable_reg_read_retry = TRUE;
62static 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
70static 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) */
76boolean mddi_debug_clear_rev_data = TRUE;
77
78uint32 *mddi_reg_read_value_ptr;
79
80mddi_client_capability_type mddi_client_capability_pkt;
81static 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
88typedef struct {
89 mddi_rev_handler_type handler; /* ISR to be executed */
90 uint16 pkt_type;
91} mddi_rev_pkt_handler_type;
92static mddi_rev_pkt_handler_type mddi_rev_pkt_handler[MAX_MDDI_REV_HANDLERS] =
93 { {NULL, INVALID_PKT_TYPE}, {NULL, INVALID_PKT_TYPE} };
94
95static boolean mddi_rev_encap_user_request = FALSE;
96static mddi_linked_list_notify_type mddi_rev_user;
97
98spinlock_t mddi_host_spin_lock;
99extern uint32 mdp_in_processing;
100#endif
101
102typedef 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
113typedef enum {
114 MDDI_LINK_DISABLED,
115 MDDI_LINK_HIBERNATING,
116 MDDI_LINK_ACTIVATING,
117 MDDI_LINK_ACTIVE
118} mddi_host_link_state_type;
119
120typedef 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
133typedef 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
150typedef 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
165typedef 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
194static mddi_host_type mddi_curr_host = MDDI_HOST_PRIM;
195static mddi_host_cntl_type mhctl[MDDI_NUM_HOST_CORES];
196mddi_linked_list_type *llist_extern[MDDI_NUM_HOST_CORES];
197mddi_linked_list_type *llist_dma_extern[MDDI_NUM_HOST_CORES];
198mddi_linked_list_notify_type *llist_extern_notify[MDDI_NUM_HOST_CORES];
199static mddi_log_params_struct_type prev_parms[MDDI_NUM_HOST_CORES];
200
201extern uint32 mdp_total_vdopkts;
202
203static boolean mddi_host_io_clock_on = FALSE;
204static boolean mddi_host_hclk_on = FALSE;
205
206int int_mddi_pri_flag = FALSE;
207int int_mddi_ext_flag = FALSE;
208
209static 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
259static void mddi_host_enable_io_clock(void)
260{
261 if (!MDDI_HOST_IS_IO_CLOCK_ON)
262 MDDI_HOST_ENABLE_IO_CLOCK;
263}
264
265static void mddi_host_enable_hclk(void)
266{
267
268 if (!MDDI_HOST_IS_HCLK_ON)
269 MDDI_HOST_ENABLE_HCLK;
270}
271
272static 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
280static 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
288static 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
298static 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
431void 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
620static 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
699static 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
760static 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
805static 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
1112static 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
1246static 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
1289static 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
1386static void mddi_host_isr_primary(void)
1387{
1388 mddi_curr_host = MDDI_HOST_PRIM;
1389 mddi_host_isr();
1390}
1391
1392irqreturn_t mddi_pmdh_isr_proxy(int irq, void *ptr)
1393{
1394 mddi_host_isr_primary();
1395 return IRQ_HANDLED;
1396}
1397
1398static 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
1405irqreturn_t mddi_emdh_isr_proxy(int irq, void *ptr)
1406{
1407 mddi_host_isr_external();
1408 return IRQ_HANDLED;
1409}
1410
1411static 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
1520void 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
1578static 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
1608void 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
1747static uint32 mddi_client_id;
1748
1749uint32 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
1854void 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
1894uint16 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
1935uint16 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
1969void 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
2081void mddi_host_write_pix_attr_reg(uint32 value)
2082{
2083 (void)value;
2084}
2085
2086void 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 */
2129boolean 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
2206void 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
2227void 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
66extern 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) \
70do { \
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) \
78do { \
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) \
88do { \
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) \
96do { \
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))
189typedef 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
204typedef 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
232typedef 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
288typedef 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
356typedef 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
386typedef 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
394typedef 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
404typedef 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
504extern void mddi_host_init(mddi_host_type host);
505extern void mddi_host_powerdown(mddi_host_type host);
506extern uint16 mddi_get_next_free_llist_item(mddi_host_type host, boolean wait);
507extern uint16 mddi_get_reg_read_llist_item(mddi_host_type host, boolean wait);
508extern 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
514extern void mddi_host_write_pix_attr_reg(uint32 value);
515extern void mddi_client_lcd_gpio_poll(uint32 poll_reg_val);
516extern void mddi_client_lcd_vsync_detected(boolean detected);
517extern void mddi_host_disable_hibernation(boolean disable);
518
519extern mddi_linked_list_type *llist_extern[];
520extern mddi_linked_list_type *llist_dma_extern[];
521extern mddi_linked_list_notify_type *llist_extern_notify[];
522extern struct timer_list mddi_host_timer;
523
524typedef 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
534extern mddi_llist_info_type mddi_llist;
535
536#define MDDI_GPIO_DEFAULT_POLLING_INTERVAL 200
537typedef struct {
538 uint32 polling_reg;
539 uint32 polling_val;
540 uint32 polling_interval;
541 boolean polling_enabled;
542} mddi_gpio_info_type;
543
544uint32 mddi_get_client_id(void);
545void mddi_mhctl_remove(mddi_host_type host_idx);
546void 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
44static struct clk *mdp_clk;
45static struct clk *mdp_pclk;
46
47struct completion mdp_ppp_comp;
48struct semaphore mdp_ppp_mutex;
49struct semaphore mdp_pipe_ctrl_mutex;
50
51unsigned long mdp_timer_duration = (HZ); /* 1 sec */
52/* unsigned long mdp_mdp_timer_duration=0; */
53
54boolean mdp_ppp_waiting = FALSE;
55uint32 mdp_tv_underflow_cnt;
56uint32 mdp_lcdc_underflow_cnt;
57
58boolean mdp_current_clk_on = FALSE;
59boolean 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 */
65uint32 mdp_in_processing = FALSE;
66
67#ifdef CONFIG_FB_MSM_MDP40
68uint32 mdp_intr_mask = MDP4_ANY_INTR_MASK;
69#else
70uint32 mdp_intr_mask = MDP_ANY_INTR_MASK;
71#endif
72
73MDP_BLOCK_TYPE mdp_debug[MDP_MAX_BLOCK];
74
75int32 mdp_block_power_cnt[MDP_MAX_BLOCK];
76
77spinlock_t mdp_spin_lock;
78struct workqueue_struct *mdp_dma_wq; /*mdp dma wq */
79struct workqueue_struct *mdp_vsync_wq; /*mdp vsync wq */
80
81static struct workqueue_struct *mdp_pipe_ctrl_wq; /* mdp mdp pipe ctrl wq */
82static struct delayed_work mdp_pipe_ctrl_worker;
83
84#ifdef CONFIG_FB_MSM_MDP40
85struct mdp_dma_data dma2_data;
86struct mdp_dma_data dma_s_data;
87struct mdp_dma_data dma_e_data;
88#else
89static struct mdp_dma_data dma2_data;
90static struct mdp_dma_data dma_s_data;
91static struct mdp_dma_data dma_e_data;
92#endif
93static struct mdp_dma_data dma3_data;
94
95extern ktime_t mdp_dma2_last_update_time;
96
97extern uint32 mdp_dma2_update_time_in_usec;
98extern int mdp_lcd_rd_cnt_offset_slow;
99extern int mdp_lcd_rd_cnt_offset_fast;
100extern int mdp_usec_diff_threshold;
101
102#ifdef CONFIG_FB_MSM_LCDC
103extern int mdp_lcdc_pclk_clk_rate;
104extern int mdp_lcdc_pad_pclk_clk_rate;
105extern int first_pixel_start_x;
106extern int first_pixel_start_y;
107#endif
108
109#ifdef MSM_FB_ENABLE_DBGFS
110struct dentry *mdp_dir;
111#endif
112
113#if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND)
114static int mdp_suspend(struct platform_device *pdev, pm_message_t state);
115#else
116#define mdp_suspend NULL
117#endif
118
119struct timeval mdp_dma2_timeval;
120struct timeval mdp_ppp_timeval;
121
122#ifdef CONFIG_HAS_EARLYSUSPEND
123static struct early_suspend early_suspend;
124#endif
125
126#ifndef CONFIG_FB_MSM_MDP22
127DEFINE_MUTEX(mdp_lut_push_sem);
128static int mdp_lut_i;
129static 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
159static int mdp_lut_push;
160static int mdp_lut_push_i;
161static 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
182static 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
202static __u32 mdp_hist_r[MDP_HIST_MAX_BIN];
203static __u32 mdp_hist_g[MDP_HIST_MAX_BIN];
204static __u32 mdp_hist_b[MDP_HIST_MAX_BIN];
205
206#ifdef CONFIG_FB_MSM_MDP40
207struct mdp_histogram mdp_hist;
208struct completion mdp_hist_comp;
209#else
210static struct mdp_histogram mdp_hist;
211static struct completion mdp_hist_comp;
212#endif
213
214static 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
255hist_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
263int 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
282static DEFINE_SPINLOCK(mdp_lock);
283static int mdp_irq_mask;
284static int mdp_irq_enabled;
285
286void 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
303void 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
320void 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
334void 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
413static 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
418void 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
532irqreturn_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
651static 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
749static int mdp_probe(struct platform_device *pdev);
750static int mdp_remove(struct platform_device *pdev);
751
752static 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
769static 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
786static 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
803static 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
844static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
845static int pdev_list_cnt;
846static int mdp_resource_initialized;
847static struct msm_panel_common_pdata *mdp_pdata;
848
849static 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
1046static 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)
1062static 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
1070static void mdp_early_suspend(struct early_suspend *h)
1071{
1072 mdp_suspend_sub();
1073}
1074#endif
1075
1076static int mdp_remove(struct platform_device *pdev)
1077{
1078 iounmap(msm_mdp_base);
1079 return 0;
1080}
1081
1082static 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
1093static 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
1113module_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
73struct mdp_table_entry {
74 uint32_t reg;
75 uint32_t val;
76};
77
78extern struct mdp_ccs mdp_ccs_yuv2rgb ;
79extern struct mdp_ccs mdp_ccs_rgb2yuv ;
80
81/*
82 * MDP Image Structure
83 */
84typedef 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
106typedef 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
121typedef enum {
122 MDP_BLOCK_POWER_OFF,
123 MDP_BLOCK_POWER_ON
124} MDP_BLOCK_POWER_STATE;
125
126typedef 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 */
169typedef enum {
170 MORE_IBUF,
171 FINAL_IBUF,
172 COMPLETE_IBUF
173} MDP_IBUF_STATE;
174
175struct 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 */
185typedef 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
196typedef 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
215struct 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
628void mdp_hw_init(void);
629int mdp_ppp_pipe_wait(void);
630void mdp_pipe_kickoff(uint32 term, struct msm_fb_data_type *mfd);
631void mdp_pipe_ctrl(MDP_BLOCK_TYPE block, MDP_BLOCK_POWER_STATE state,
632 boolean isr);
633void mdp_set_dma_pan_info(struct fb_info *info, struct mdp_dirty_region *dirty,
634 boolean sync);
635void mdp_dma_pan_update(struct fb_info *info);
636void mdp_refresh_screen(unsigned long data);
637int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req,
638 struct file **pp_src, struct file **pp_dest);
639void mdp_lcd_update_workqueue_handler(struct work_struct *work);
640void mdp_vsync_resync_workqueue_handler(struct work_struct *work);
641void mdp_dma2_update(struct msm_fb_data_type *mfd);
642void mdp_config_vsync(struct msm_fb_data_type *);
643uint32 mdp_get_lcd_line_counter(struct msm_fb_data_type *mfd);
644enum hrtimer_restart mdp_dma2_vsync_hrtimer_handler(struct hrtimer *ht);
645void mdp_set_scale(MDPIBUF *iBuf,
646 uint32 dst_roi_width,
647 uint32 dst_roi_height,
648 boolean inputRGB, boolean outputRGB, uint32 *pppop_reg_ptr);
649void mdp_init_scale_table(void);
650void 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);
658void mdp_set_blend_attr(MDPIBUF *iBuf,
659 uint32 *alpha,
660 uint32 *tpVal,
661 uint32 perPixelAlpha, uint32 *pppop_reg_ptr);
662
663int mdp_dma3_on(struct platform_device *pdev);
664int mdp_dma3_off(struct platform_device *pdev);
665void mdp_dma3_update(struct msm_fb_data_type *mfd);
666
667int mdp_lcdc_on(struct platform_device *pdev);
668int mdp_lcdc_off(struct platform_device *pdev);
669void mdp_lcdc_update(struct msm_fb_data_type *mfd);
670int mdp_hw_cursor_update(struct fb_info *info, struct fb_cursor *cursor);
671void mdp_enable_irq(uint32 term);
672void mdp_disable_irq(uint32 term);
673void mdp_disable_irq_nolock(uint32 term);
674uint32_t mdp_get_bytes_per_pixel(uint32_t format);
675
676#ifdef MDP_HW_VSYNC
677void mdp_hw_vsync_clk_enable(struct msm_fb_data_type *mfd);
678void mdp_hw_vsync_clk_disable(struct msm_fb_data_type *mfd);
679#endif
680
681void mdp_dma_s_update(struct msm_fb_data_type *mfd);
682
683/* Added to support flipping */
684void mdp_set_offset_info(struct fb_info *info, uint32 address, uint32 interval);
685
686int get_gem_img(struct mdp_img *img, unsigned long *start,
687 unsigned long *len);
688int 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
32extern struct mdp_dma_data dma2_data;
33extern struct mdp_dma_data dma_s_data;
34extern struct mdp_dma_data dma_e_data;
35extern struct mdp_histogram mdp_hist;
36extern struct completion mdp_hist_comp;
37extern boolean mdp_is_in_isr;
38extern uint32 mdp_intr_mask;
39extern 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
53enum { /* display */
54 PRIMARY_INTF_SEL,
55 SECONDARY_INTF_SEL,
56 EXTERNAL_INTF_SEL
57};
58
59enum {
60 LCDC_RGB_INTF,
61 DTV_INTF = LCDC_RGB_INTF,
62 MDDI_LCDC_INTF,
63 MDDI_INTF,
64 EBI2_INTF
65};
66
67enum {
68 MDDI_PRIMARY_SET,
69 MDDI_SECONDARY_SET,
70 MDDI_EXTERNAL_SET
71};
72
73enum {
74 EBI2_LCD0,
75 EBI2_LCD1
76};
77
78enum {
79 OVERLAY_MODE_NONE,
80 OVERLAY_MODE_BLT
81};
82
83enum {
84 OVERLAY_REFRESH_ON_DEMAND,
85 OVERLAY_REFRESH_VSYNC,
86 OVERLAY_REFRESH_VSYNC_HALF,
87 OVERLAY_REFRESH_VSYNC_QUARTER
88};
89
90enum {
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
120enum {
121 OVERLAY_PIPE_RGB1,
122 OVERLAY_PIPE_RGB2,
123};
124
125enum {
126 OVERLAY_PIPE_VG1, /* video/graphic */
127 OVERLAY_PIPE_VG2
128};
129
130enum {
131 OVERLAY_TYPE_RGB,
132 OVERLAY_TYPE_VG /* video/graphic */
133};
134
135enum {
136 MDP4_MIXER0,
137 MDP4_MIXER1
138};
139
140#define MDP4_MAX_MIXER 2
141
142enum {
143 OVERLAY_PLANE_INTERLEAVED,
144 OVERLAY_PLANE_PLANAR,
145 OVERLAY_PLANE_PSEUDO_PLANAR
146};
147
148enum {
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
158enum {
159 MDP4_FRAME_FORMAT_LINEAR,
160 MDP4_FRAME_FORMAT_ARGB_TILE,
161 MDP4_FRAME_FORMAT_VIDEO_SUPERTILE
162};
163
164enum {
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
217struct 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
282void mdp4_sw_reset(unsigned long bits);
283void mdp4_display_intf_sel(int output, unsigned long intf);
284void mdp4_overlay_cfg(int layer, int blt_mode, int refresh, int direct_out);
285void mdp4_ebi2_lcd_setup(int lcd, unsigned long base, int ystride);
286void mdp4_mddi_setup(int which, unsigned long id);
287unsigned long mdp4_display_status(void);
288void mdp4_enable_clk_irq(void);
289void mdp4_disable_clk_irq(void);
290void mdp4_dma_p_update(struct msm_fb_data_type *mfd);
291void mdp4_dma_s_update(struct msm_fb_data_type *mfd);
292void mdp_pipe_ctrl(MDP_BLOCK_TYPE block, MDP_BLOCK_POWER_STATE state,
293 boolean isr);
294void mdp4_pipe_kickoff(uint32 pipe, struct msm_fb_data_type *mfd);
295int mdp4_lcdc_on(struct platform_device *pdev);
296int mdp4_lcdc_off(struct platform_device *pdev);
297void mdp4_lcdc_update(struct msm_fb_data_type *mfd);
298void mdp4_intr_clear_set(ulong clear, ulong set);
299void mdp4_dma_p_cfg(void);
300void mdp4_hw_init(void);
301void mdp4_isr_read(int);
302void mdp4_clear_lcdc(void);
303void mdp4_mixer_blend_init(int mixer_num);
304void mdp4_vg_qseed_init(int vg_num);
305void mdp4_vg_csc_mv_setup(int vp_num);
306void mdp4_vg_csc_pre_bv_setup(int vp_num);
307void mdp4_vg_csc_post_bv_setup(int vp_num);
308void mdp4_vg_csc_pre_lv_setup(int vp_num);
309void mdp4_vg_csc_post_lv_setup(int vp_num);
310irqreturn_t mdp4_isr(int irq, void *ptr);
311void mdp4_overlay_format_to_pipe(uint32 format, struct mdp4_overlay_pipe *pipe);
312uint32 mdp4_overlay_format(struct mdp4_overlay_pipe *pipe);
313uint32 mdp4_overlay_unpack_pattern(struct mdp4_overlay_pipe *pipe);
314uint32 mdp4_overlay_op_mode(struct mdp4_overlay_pipe *pipe);
315void mdp4_lcdc_overlay(struct msm_fb_data_type *mfd);
316void mdp4_overlay_rgb_setup(struct mdp4_overlay_pipe *pipe);
317void mdp4_overlay_reg_flush(struct mdp4_overlay_pipe *pipe, int all);
318void mdp4_mixer_blend_setup(struct mdp4_overlay_pipe *pipe);
319void mdp4_mixer_stage_up(struct mdp4_overlay_pipe *pipe);
320void mdp4_mixer_stage_down(struct mdp4_overlay_pipe *pipe);
321int mdp4_mixer_stage_can_run(struct mdp4_overlay_pipe *pipe);
322void mdp4_overlayproc_cfg(struct mdp4_overlay_pipe *pipe);
323void mdp4_mddi_overlay(struct msm_fb_data_type *mfd);
324int mdp4_overlay_format2type(uint32 format);
325int mdp4_overlay_format2pipe(struct mdp4_overlay_pipe *pipe);
326int mdp4_overlay_get(struct fb_info *info, struct mdp_overlay *req);
327int mdp4_overlay_set(struct fb_info *info, struct mdp_overlay *req);
328int mdp4_overlay_unset(struct fb_info *info, int ndx);
329int mdp4_overlay_play(struct fb_info *info, struct msmfb_overlay_data *req,
330 struct file **pp_src_file);
331struct mdp4_overlay_pipe *mdp4_overlay_pipe_alloc(void);
332void mdp4_overlay_pipe_free(struct mdp4_overlay_pipe *pipe);
333void mdp4_overlay_dmap_cfg(struct msm_fb_data_type *mfd, int lcdc);
334void mdp4_overlay_dmap_xy(struct mdp4_overlay_pipe *pipe);
335int mdp4_overlay_active(int mixer);
336void mdp4_overlay0_done_lcdc(void);
337void mdp4_overlay0_done_mddi(void);
338void mdp4_mddi_overlay_restore(void);
339void mdp4_mddi_overlay_kickoff(struct msm_fb_data_type *mfd,
340 struct mdp4_overlay_pipe *pipe);
341void mdp4_rgb_igc_lut_setup(int num);
342void mdp4_vg_igc_lut_setup(int num);
343void mdp4_mixer_gc_lut_setup(int mixer_num);
344
345#ifdef CONFIG_DEBUG_FS
346int mdp4_debugfs_init(void);
347#endif
348
349int 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
43static char mdp4_debug_buf[MDP4_DEBUG_BUF];
44static ulong mdp4_debug_offset;
45static ulong mdp4_base_addr;
46
47static int mdp4_offset_set(void *data, u64 val)
48{
49 mdp4_debug_offset = (int)val;
50 return 0;
51}
52
53static int mdp4_offset_get(void *data, u64 *val)
54{
55 *val = (u64)mdp4_debug_offset;
56 return 0;
57}
58
59DEFINE_SIMPLE_ATTRIBUTE(
60 mdp4_offset_fops,
61 mdp4_offset_get,
62 mdp4_offset_set,
63 "%llx\n");
64
65
66static 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
73static int mdp4_debugfs_release(struct inode *inode, struct file *file)
74{
75 return 0;
76}
77
78static 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
110static 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
146static 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
153int 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
46struct 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
51static struct mdp4_overlay_ctrl *ctrl = &mdp4_overlay_db;
52
53
54void 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
85void 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
101static 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
115static 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
133static 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
172void 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
211void 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
264int 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
293int 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 */
484static 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
502void 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
568uint32 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
605uint32 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
611void 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
632int 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
657void 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
692void 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
727void 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
823void 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
852struct 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
867struct 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
888void 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
895static 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
910int 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
925static 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
1017int 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}
1044int 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
1057int 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
1097int 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
1139struct 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
1146void 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
1161uint32 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
1176int 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
46int first_pixel_start_x;
47int first_pixel_start_y;
48
49static struct mdp4_overlay_pipe *lcdc_pipe;
50
51int 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
244int 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 */
271void mdp4_overlay0_done_lcdc()
272{
273 complete(&lcdc_pipe->comp);
274}
275
276void 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
40static struct mdp4_overlay_pipe *mddi_pipe;
41static struct mdp4_overlay_pipe *pending_pipe;
42static struct msm_fb_data_type *mddi_mfd;
43
44#define WHOLESCREEN
45
46void 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 */
182void mdp4_overlay0_done_mddi()
183{
184 if (pending_pipe)
185 complete(&pending_pipe->comp);
186}
187
188void 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
195void 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
237void 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
40void 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
50void 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
69void 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
101unsigned long mdp4_display_status(void)
102{
103 return inpdw(MDP_BASE + 0x0018) & 0x3ff; /* MDP_DISPLAY_STATUS */
104}
105
106void 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
119void 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
137int 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
145void 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
222void 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
246static struct mdp_dma_data overlay1_data;
247static int intr_dma_p;
248static int intr_dma_s;
249static int intr_dma_e;
250static int intr_overlay0;
251static int intr_overlay1;
252
253irqreturn_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
367static uint32 vg_qseed_table0[] = {
368 0x5556aaff, 0x00000000, 0x00000000, 0x00000000
369};
370
371static uint32 vg_qseed_table1[] = {
372 0x76543210, 0xfedcba98
373};
374
375static 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
895void 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
924void 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
952static uint32 csc_matrix_tab[9] = {
953 0x0254, 0x0000, 0x0331,
954 0x0254, 0xff37, 0xfe60,
955 0x0254, 0x0409, 0x0000
956};
957
958static uint32 csc_pre_bv_tab[3] = {0xfff0, 0xff80, 0xff80 };
959static uint32 csc_post_bv_tab[3] = {0, 0, 0 };
960
961static uint32 csc_pre_lv_tab[6] = {0, 0xff, 0, 0xff, 0, 0xff };
962static 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
970void 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
984void 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
998void 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
1012void 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
1027void 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
1042char 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
1557void 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
1580uint32 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
1615void 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
1634uint32 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
1669void 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
39static int cursor_enabled;
40
41int 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
40static uint32 mdp_last_dma2_update_width;
41static uint32 mdp_last_dma2_update_height;
42static uint32 mdp_curr_dma2_update_width;
43static uint32 mdp_curr_dma2_update_height;
44
45ktime_t mdp_dma2_last_update_time = { 0 };
46
47int mdp_lcd_rd_cnt_offset_slow = 20;
48int mdp_lcd_rd_cnt_offset_fast = 20;
49int mdp_vsync_usec_wait_line_too_short = 5;
50uint32 mdp_dma2_update_time_in_usec;
51uint32 mdp_total_vdopkts;
52
53extern u32 msm_fb_debug_enabled;
54extern struct workqueue_struct *mdp_dma_wq;
55
56int vsync_start_y_adjust = 4;
57
58static 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
226static ktime_t vt = { 0 };
227int mdp_usec_diff_threshold = 100;
228int mdp_expected_usec_wait;
229
230enum 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
259static 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
379void 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
413void mdp_dma2_update_sub(struct msm_fb_data_type *mfd)
414#else
415void 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
445void 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
454void 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
491void 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
513void 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
533void 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
50extern spinlock_t mdp_spin_lock;
51#ifndef CONFIG_FB_MSM_MDP40
52extern uint32 mdp_intr_mask;
53#endif
54
55int first_pixel_start_x;
56int first_pixel_start_y;
57
58int 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
288int 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
319void 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
39static 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
116void 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
40extern spinlock_t mdp_spin_lock;
41extern uint32 mdp_intr_mask;
42
43int 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
91int 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
113void 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 */
21uint32 mdp_plv[] = { 0x10, 0xeb, 0x10, 0xf0 };
22
23/* Color Coefficient matrix for YUV -> RGB */
24struct 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 */
51struct 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
73static 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
591void 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
43static 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
58extern uint32 mdp_plv[];
59extern struct semaphore mdp_ppp_mutex;
60
61uint32_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
71static 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
187uint32 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
304static 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
339static 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
360static 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
534static 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
544static 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
570static void mdp_start_ppp(struct msm_fb_data_type *mfd, MDPIBUF *iBuf,
571struct 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
1136static 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 **/
1218int 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
1224int 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
1249int 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
20static boolean mdp_ppp_intr_flag = FALSE;
21static boolean mdp_ppp_busy_flag = FALSE;
22
23/* Queue to keep track of the completed jobs for cleaning */
24static LIST_HEAD(mdp_ppp_djob_clnrq);
25static DEFINE_SPINLOCK(mdp_ppp_djob_clnrq_lock);
26
27/* Worker to cleanup Display Jobs */
28static struct workqueue_struct *mdp_ppp_djob_clnr;
29
30/* Display Queue (DQ) for MDP PPP Block */
31static LIST_HEAD(mdp_ppp_dq);
32static DEFINE_SPINLOCK(mdp_ppp_dq_lock);
33
34/* Current Display Job for MDP PPP */
35static struct mdp_ppp_djob *curr_djob;
36
37/* Track ret code for the last opeartion */
38static int mdp_ppp_ret_code;
39
40inline 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 */
47inline 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 */
86inline 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). */
92static 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 */
110static 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) */
123inline 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() */
167inline 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 */
176static 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 */
210void 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 */
246static 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 */
266static 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" */
281static 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 */
292void 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 */
307void 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 */
43struct 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 */
51struct 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) */
58struct 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
68extern struct completion mdp_ppp_comp;
69extern boolean mdp_ppp_waiting;
70extern unsigned long mdp_timer_duration;
71
72unsigned int mdp_ppp_async_op_get(void);
73void mdp_ppp_async_op_set(unsigned int flag);
74void msm_fb_ensure_mem_coherency_after_dma(struct fb_info *info,
75 struct mdp_blit_req *req_list, int req_list_count);
76void mdp_ppp_put_img(struct file *p_src_file, struct file *p_dst_file);
77void mdp_ppp_dq_init(void);
78void mdp_ppp_outdw(uint32_t addr, uint32_t data);
79struct mdp_ppp_djob *mdp_ppp_new_djob(void);
80void mdp_ppp_clear_curr_djob(void);
81void mdp_ppp_process_curr_djob(void);
82int mdp_ppp_get_ret_code(void);
83void mdp_ppp_djob_done(void);
84void 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
38static MDP_SCALE_MODE mdp_curr_up_scale_xy;
39static MDP_SCALE_MODE mdp_curr_down_scale_x;
40static MDP_SCALE_MODE mdp_curr_down_scale_y;
41
42static long long mdp_do_div(long long num, long long den)
43{
44 do_div(num, den);
45 return num;
46}
47
48struct 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
180static 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
188static 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
256static 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
324static 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
392static 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
460static 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
528static 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
596static 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
664static 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
732static 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
800static 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
868static 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
936static 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
1004static 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
1072static 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
1140static 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
1208static 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
1276static 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
1344static 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
1412static 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
1847static 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
2124static 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
2148void 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
2410void 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
2417void 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
2447void 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
48static uint32 mdp_scale_0p8_to_8p0_mode;
49static uint32 mdp_scale_0p6_to_0p8_mode;
50static uint32 mdp_scale_0p4_to_0p6_mode;
51static uint32 mdp_scale_0p2_to_0p4_mode;
52
53/* -------- All scaling range, "pixel repeat" -------- */
54static 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
61static 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
68static 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
75static 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
85static 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
92static 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
99static 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
106static 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
115static 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
122static 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
129static 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
136static 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
145static 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
152static 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
159static 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
166static 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
175static 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
182static 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
189static 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
196static 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
203static 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
221void 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
252static 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
263struct phase_val {
264 int phase_init_x;
265 int phase_init_y;
266 int phase_step_x;
267 int phase_step_y;
268};
269
270static 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
456void 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
746void 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
782void 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
54extern mddi_lcd_type mddi_lcd_idx;
55extern spinlock_t mdp_spin_lock;
56extern struct workqueue_struct *mdp_vsync_wq;
57extern int lcdc_mode;
58extern int vsync_mode;
59
60#ifdef MDP_HW_VSYNC
61int vsync_above_th = 4;
62int vsync_start_th = 1;
63int vsync_load_cnt;
64
65struct clk *mdp_vsync_clk;
66
67void 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
73void 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
80static 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
112static 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
130irqreturn_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
143static 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
157void 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
293err_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
300void 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
341boolean 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
352uint32 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
32int 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
46void *zero_page_strongly_ordered;
47
48static 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
60void write_to_strongly_ordered_memory(void)
61{
62 map_zero_page_strongly_ordered();
63 *(int *)zero_page_strongly_ordered = 0;
64}
65EXPORT_SYMBOL(write_to_strongly_ordered_memory);
66
67void 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 */
80void 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
96void 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
112void 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
128void *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)
157struct npa_client *npa_memory_client;
158#endif
159
160static 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
196int 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
203int 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
209int 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__
24void *alloc_bootmem_aligned(unsigned long size, unsigned long alignment);
25void clean_and_invalidate_caches(unsigned long, unsigned long, unsigned long);
26void clean_caches(unsigned long, unsigned long, unsigned long);
27void invalidate_caches(unsigned long, unsigned long, unsigned long);
28int platform_physical_remove_pages(unsigned long, unsigned long);
29int platform_physical_add_pages(unsigned long, unsigned long);
30int platform_physical_low_power_pages(unsigned long, unsigned long);
31
32#ifdef CONFIG_ARCH_MSM_ARM11
33void 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
44extern 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"
53extern 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
70static unsigned char *fbram;
71static unsigned char *fbram_phys;
72static int fbram_size;
73
74static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
75static int pdev_list_cnt;
76
77int vsync_mode = 1;
78
79#define MAX_FBI_LIST 32
80static struct fb_info *fbi_list[MAX_FBI_LIST];
81static int fbi_list_index;
82
83static struct msm_fb_data_type *mfd_list[MAX_FBI_LIST];
84static int mfd_list_index;
85
86static 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
93u32 msm_fb_debug_enabled;
94/* Setting msm_fb_msg_level to 8 prints out ALL messages */
95u32 msm_fb_msg_level = 7;
96
97/* Setting mddi_msg_level to 8 prints out ALL messages */
98u32 mddi_msg_level = 5;
99
100extern int32 mdp_block_power_cnt[MDP_MAX_BLOCK];
101extern unsigned long mdp_timer_duration;
102
103static int msm_fb_register(struct msm_fb_data_type *mfd);
104static int msm_fb_open(struct fb_info *info, int user);
105static int msm_fb_release(struct fb_info *info, int user);
106static int msm_fb_pan_display(struct fb_var_screeninfo *var,
107 struct fb_info *info);
108static int msm_fb_stop_sw_refresher(struct msm_fb_data_type *mfd);
109int msm_fb_resume_sw_refresher(struct msm_fb_data_type *mfd);
110static int msm_fb_check_var(struct fb_var_screeninfo *var,
111 struct fb_info *info);
112static int msm_fb_set_par(struct fb_info *info);
113static int msm_fb_blank_sub(int blank_mode, struct fb_info *info,
114 boolean op_enable);
115static int msm_fb_suspend_sub(struct msm_fb_data_type *mfd);
116static int msm_fb_resume_sub(struct msm_fb_data_type *mfd);
117static int msm_fb_ioctl(struct fb_info *info, unsigned int cmd,
118 unsigned long arg);
119static 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
126int msm_fb_debugfs_file_index;
127struct dentry *msm_fb_debugfs_root;
128struct dentry *msm_fb_debugfs_file[MSM_FB_MAX_DBGFS];
129
130struct 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
138void 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
149int 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
159static int msm_fb_resource_initialized;
160
161#ifndef CONFIG_FB_BACKLIGHT
162static int lcd_backlight_registered;
163
164static 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
184static 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
191static struct msm_fb_platform_data *msm_fb_pdata;
192
193int 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
215static 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
284static 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)
338static 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
368static 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)
420static 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
446static 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
472static 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
487static 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
494static 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
502void 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
524static 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
591static 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
611static 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
631static 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
650static 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
656static 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 */
672static 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
723static 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
744static 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
1119static 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
1136static 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
1161DECLARE_MUTEX(msm_fb_pan_sem);
1162
1163static 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
1281static 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
1352static 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
1401static 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
1418int 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
1440void 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
1450int 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
1466typedef void (*msm_dma_barrier_function_pointer) (void *, size_t);
1467
1468static 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
1491static inline void msm_dma_nc_pre(void)
1492{
1493 dmb();
1494}
1495static inline void msm_dma_wt_pre(void)
1496{
1497 dmb();
1498}
1499static 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
1505static 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
1511static inline void msm_dma_nc_post(void)
1512{
1513 dmb();
1514}
1515
1516static 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
1522static 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
1528static 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*/
1542static 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*/
1625static 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
1684void 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
1698static 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 */
1802static 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
1881static 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
1904static 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
1928static 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
1942static 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
1965DECLARE_MUTEX(msm_fb_ioctl_ppp_sem);
1966DEFINE_MUTEX(msm_fb_ioctl_lut_sem);
1967DEFINE_MUTEX(msm_fb_ioctl_hist_sem);
1968
1969/* Set color conversion matrix from user space */
1970
1971#ifndef CONFIG_FB_MSM_MDP40
1972static 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
2008static 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
2246static int msm_fb_register_driver(void)
2247{
2248 return platform_driver_register(&msm_fb_driver);
2249}
2250
2251void 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}
2325EXPORT_SYMBOL(msm_fb_add_device);
2326
2327int __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
2354module_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
65struct disp_info_type_suspend {
66 boolean op_enable;
67 boolean sw_refreshing_enable;
68 boolean panel_power_on;
69};
70
71struct 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
160struct dentry *msm_fb_get_debugfs_root(void);
161void msm_fb_debugfs_file_create(struct dentry *root, const char *name,
162 u32 *var);
163void msm_fb_set_backlight(struct msm_fb_data_type *mfd, __u32 bkl_lvl,
164 u32 save);
165
166void msm_fb_add_device(struct platform_device *pdev);
167
168int msm_fb_detect_client(const char *name);
169
170#ifdef CONFIG_FB_BACKLIGHT
171void 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
29static int msm_fb_bl_get_brightness(struct backlight_device *pbd)
30{
31 return pbd->props.brightness;
32}
33
34static 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
45static 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
50void 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
66typedef s64 int64;
67typedef s32 int32;
68typedef s16 int16;
69typedef s8 int8;
70
71typedef u64 uint64;
72typedef u32 uint32;
73typedef u16 uint16;
74typedef u8 uint8;
75
76typedef s32 int4;
77typedef s16 int2;
78typedef s8 int1;
79
80typedef u32 uint4;
81typedef u16 uint2;
82typedef u8 uint1;
83
84typedef u32 dword;
85typedef u16 word;
86typedef u8 byte;
87
88typedef 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
153extern 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
192unsigned char *msm_mdp_base;
193unsigned char *msm_pmdh_base;
194unsigned char *msm_emdh_base;
195#else
196extern unsigned char *msm_mdp_base;
197extern unsigned char *msm_pmdh_base;
198extern 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
39int 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
62int 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
85struct 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
34struct msm_fb_data_type;
35
36typedef void (*msm_fb_vsync_handler_type) (void *arg);
37
38/* panel id type */
39typedef 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 */
54typedef 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 */
62typedef 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 */
69struct 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
79struct 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
91struct mddi_panel_info {
92 __u32 vdopkt;
93};
94
95struct 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
120struct 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============================================================================*/
135struct platform_device *msm_fb_device_alloc(struct msm_fb_panel_data *pdata,
136 u32 type, u32 id);
137int panel_next_on(struct platform_device *pdev);
138int panel_next_off(struct platform_device *pdev);
139
140int lcdc_device_register(struct msm_panel_info *pinfo);
141
142int 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
50enum {
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
70enum {
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
111struct mdp_rect {
112 uint32_t x;
113 uint32_t y;
114 uint32_t w;
115 uint32_t h;
116};
117
118struct 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
137struct 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
150struct 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
161struct mdp_blit_req_list {
162 uint32_t count;
163 struct mdp_blit_req req[];
164};
165
166struct msmfb_data {
167 uint32_t offset;
168 int memory_id;
169 int id;
170};
171
172#define MSMFB_NEW_REQUEST -1
173
174struct msmfb_overlay_data {
175 uint32_t id;
176 struct msmfb_data data;
177};
178
179struct msmfb_img {
180 uint32_t width;
181 uint32_t height;
182 uint32_t format;
183};
184
185struct 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
198struct 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
206struct mdp_page_protection {
207 uint32_t page_protection;
208};
209
210
211struct 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
220struct lcdc_platform_data {
221 int (*lcdc_gpio_config)(int on);
222 void (*lcdc_power_save)(int);
223};
224
225struct tvenc_platform_data {
226 int (*pm_vid_en)(int on);
227};
228
229struct mddi_platform_data {
230 void (*mddi_power_save)(int on);
231 int (*mddi_sel_clk)(u32 *clk_rate);
232};
233
234struct msm_fb_platform_data {
235 int (*detect_client)(const char *name);
236 int mddi_prescan;
237 int (*allow_set_offset)(void);
238};
239
240struct 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
79static struct resource msm_fb_resources[] = {
80 {
81 .flags = IORESOURCE_DMA,
82 }
83};
84
85static 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
94static 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
101static struct platform_device msm_lcdc_device = {
102 .name = "lcdc",
103 .id = 0,
104};
105
106static 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
142static 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
149static 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
154static 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
164static 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
184static 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
225static struct lcdc_platform_data lcdc_pdata = {
226 .lcdc_gpio_config = msm_fb_lcdc_gpio_config,
227};
228
229static 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
239static struct msm_panel_common_pdata mdp_pdata = {
240 .gpio = 98,
241};
242
243static struct platform_device *devices[] __initdata = {
244 &msm_fb_device,
245};
246
247
248static 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
261void __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
283static 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
309int __init staging_init_pmem(void)
310{
311 qsd8x50_allocate_memory_regions();
312 return 0;
313}
314
315int __init staging_init_devices(void)
316{
317 platform_add_devices(devices, ARRAY_SIZE(devices));
318 msm_fb_add_devices();
319 return 0;
320}
321
322arch_initcall(staging_init_pmem);
323arch_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
41static int ntsc_off(struct platform_device *pdev);
42static int ntsc_on(struct platform_device *pdev);
43
44static 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
109static int ntsc_off(struct platform_device *pdev)
110{
111 TV_OUT(TV_ENC_CTL, 0); /* disable TV encoder */
112 return 0;
113}
114
115static int __init ntsc_probe(struct platform_device *pdev)
116{
117 msm_fb_add_device(pdev);
118
119 return 0;
120}
121
122static struct platform_driver this_driver = {
123 .probe = ntsc_probe,
124 .driver = {
125 .name = "tv_ntsc",
126 },
127};
128
129static 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
141static struct platform_device this_device = {
142 .name = "tv_ntsc",
143 .id = 0,
144 .dev = {
145 .platform_data = &ntsc_panel_data,
146 }
147};
148
149static 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
163module_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
45static 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
159static int pal_off(struct platform_device *pdev)
160{
161 TV_OUT(TV_ENC_CTL, 0); /* disable TV encoder */
162 return 0;
163}
164
165static int __init pal_probe(struct platform_device *pdev)
166{
167 msm_fb_add_device(pdev);
168
169 return 0;
170}
171
172static struct platform_driver this_driver = {
173 .probe = pal_probe,
174 .driver = {
175 .name = "tv_pal",
176 },
177};
178
179static 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
191static struct platform_device this_device = {
192 .name = "tv_pal",
193 .id = 0,
194 .dev = {
195 .platform_data = &pal_panel_data,
196 }
197};
198
199static 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
213module_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
41static int tvenc_probe(struct platform_device *pdev);
42static int tvenc_remove(struct platform_device *pdev);
43
44static int tvenc_off(struct platform_device *pdev);
45static int tvenc_on(struct platform_device *pdev);
46
47static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
48static int pdev_list_cnt;
49
50static struct clk *tvenc_clk;
51static struct clk *tvdac_clk;
52
53static 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
66static struct tvenc_platform_data *tvenc_pdata;
67
68static 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
90static 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
113void 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
170static int tvenc_resource_initialized;
171
172static 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
259tvenc_probe_err:
260 platform_device_put(mdp_dev);
261 return rc;
262}
263
264static int tvenc_remove(struct platform_device *pdev)
265{
266// pm_qos_remove_requirement(PM_QOS_SYSTEM_BUS_FREQ , "tvenc");
267 return 0;
268}
269
270static int tvenc_register_driver(void)
271{
272 return platform_driver_register(&tvenc_driver);
273}
274
275static 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
295module_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
82void *tvenc_base;
83#else
84extern 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 */