1 /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
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.
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.
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
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>
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>
39 static int ebi2_lcd_probe(struct platform_device
*pdev
);
40 static int ebi2_lcd_remove(struct platform_device
*pdev
);
42 static struct platform_driver ebi2_lcd_driver
= {
43 .probe
= ebi2_lcd_probe
,
44 .remove
= ebi2_lcd_remove
,
55 static void *ebi2_base
;
56 static void *ebi2_lcd_cfg0
;
57 static void *ebi2_lcd_cfg1
;
58 static void __iomem
*lcd01_base
;
59 static void __iomem
*lcd02_base
;
60 static int ebi2_lcd_resource_initialized
;
62 static struct platform_device
*pdev_list
[MSM_FB_MAX_DEV_LIST
];
63 static int pdev_list_cnt
;
65 static int ebi2_lcd_probe(struct platform_device
*pdev
)
67 struct msm_fb_data_type
*mfd
;
68 struct platform_device
*mdp_dev
= NULL
;
69 struct msm_fb_panel_data
*pdata
= NULL
;
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);
80 "ebi2_base ioremap failed!\n");
83 ebi2_lcd_cfg0
= (void *)(ebi2_base
+ 0x20);
84 ebi2_lcd_cfg1
= (void *)(ebi2_base
+ 0x24);
85 } else if (!strncmp(pdev
->resource
[i
].name
,
87 lcd01_base
= ioremap(pdev
->resource
[i
].start
,
88 pdev
->resource
[i
].end
-
89 pdev
->resource
[i
].start
+ 1);
92 "lcd01_base ioremap failed!\n");
95 } else if (!strncmp(pdev
->resource
[i
].name
,
97 lcd02_base
= ioremap(pdev
->resource
[i
].start
,
98 pdev
->resource
[i
].end
-
99 pdev
->resource
[i
].start
+ 1);
102 "lcd02_base ioremap failed!\n");
107 ebi2_lcd_resource_initialized
= 1;
111 if (!ebi2_lcd_resource_initialized
)
114 mfd
= platform_get_drvdata(pdev
);
119 if (mfd
->key
!= MFD_KEY
)
122 if (pdev_list_cnt
>= MSM_FB_MAX_DEV_LIST
)
125 if (ebi2_base
== NULL
)
128 mdp_dev
= platform_device_alloc("mdp", pdev
->id
);
132 /* link to the latest pdev */
134 mfd
->dest
= DISPLAY_LCD
;
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
);
146 pdata
= mdp_dev
->dev
.platform_data
;
147 pdata
->on
= panel_next_on
;
148 pdata
->off
= panel_next_off
;
151 /* get/set panel specific fb info */
152 mfd
->panel_info
= pdata
->panel_info
;
154 if (mfd
->panel_info
.bpp
== 24)
155 mfd
->fb_imgType
= MDP_RGB_888
;
157 mfd
->fb_imgType
= MDP_RGB_565
;
159 /* config msm ebi2 lcd register */
160 if (mfd
->panel_info
.pdest
== DISPLAY_1
) {
162 (inp32(ebi2_base
) & (~(EBI2_PRIM_LCD_CLR
))) |
165 * current design has one set of cfg0/1 register to control
166 * both EBI2 channels. so, we're using the PRIM channel to
169 outp32(ebi2_lcd_cfg0
, mfd
->panel_info
.wait_cycle
);
170 if (mfd
->panel_info
.bpp
== 18)
171 outp32(ebi2_lcd_cfg1
, 0x01000000);
173 outp32(ebi2_lcd_cfg1
, 0x0);
175 #ifdef DEBUG_EBI2_LCD
177 * confliting with QCOM SURF FPGA CS.
178 * OEM should enable below for their CS mapping
180 outp32(ebi2_base
, (inp32(ebi2_base
)&(~(EBI2_SECD_LCD_CLR
)))
186 * map cs (chip select) address
188 if (mfd
->panel_info
.pdest
== DISPLAY_1
) {
189 mfd
->cmd_port
= lcd01_base
;
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
);
195 mfd
->cmd_port
= lcd01_base
;
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
);
205 platform_set_drvdata(mdp_dev
, mfd
);
208 * register in mdp driver
210 rc
= platform_device_add(mdp_dev
);
212 goto ebi2_lcd_probe_err
;
215 pdev_list
[pdev_list_cnt
++] = pdev
;
219 platform_device_put(mdp_dev
);
223 static int ebi2_lcd_remove(struct platform_device
*pdev
)
225 struct msm_fb_data_type
*mfd
;
227 mfd
= (struct msm_fb_data_type
*)platform_get_drvdata(pdev
);
232 if (mfd
->key
!= MFD_KEY
)
235 iounmap(mfd
->cmd_port
);
240 static int ebi2_lcd_register_driver(void)
242 return platform_driver_register(&ebi2_lcd_driver
);
245 static int __init
ebi2_lcd_driver_init(void)
247 return ebi2_lcd_register_driver();
250 module_init(ebi2_lcd_driver_init
);