1 /* linux/arch/arm/mach-vt8500/devices.c
2  *
3  * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
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 
16 #include <linux/kernel.h>
17 #include <linux/io.h>
18 #include <linux/device.h>
19 #include <linux/dma-mapping.h>
20 #include <linux/platform_device.h>
21 #include <linux/pwm_backlight.h>
22 #include <linux/memblock.h>
23 
24 #include <asm/mach/arch.h>
25 
26 #include <mach/vt8500fb.h>
27 #include <mach/i8042.h>
28 #include "devices.h"
29 
30 /* These can't use resources currently */
31 unsigned long wmt_ic_base __initdata;
32 unsigned long wmt_sic_base __initdata;
33 unsigned long wmt_gpio_base __initdata;
34 unsigned long wmt_pmc_base __initdata;
35 unsigned long wmt_i8042_base __initdata;
36 
37 int wmt_nr_irqs __initdata;
38 int wmt_timer_irq __initdata;
39 int wmt_gpio_ext_irq[8] __initdata;
40 
41 /* Should remain accessible after init.
42  * i8042 driver desperately calls for attention...
43  */
44 int wmt_i8042_kbd_irq;
45 int wmt_i8042_aux_irq;
46 
47 static u64 fb_dma_mask = DMA_BIT_MASK(32);
48 
49 struct platform_device vt8500_device_lcdc = {
50 	.name           = "vt8500-lcd",
51 	.id             = 0,
52 	.dev		= {
53 		.dma_mask	= &fb_dma_mask,
54 		.coherent_dma_mask = DMA_BIT_MASK(32),
55 	},
56 };
57 
58 struct platform_device vt8500_device_wm8505_fb = {
59 	.name           = "wm8505-fb",
60 	.id             = 0,
61 };
62 
63 /* Smallest to largest */
64 static struct vt8500fb_platform_data panels[] = {
65 #ifdef CONFIG_WMT_PANEL_800X480
66 {
67 	.xres_virtual	= 800,
68 	.yres_virtual	= 480 * 2,
69 	.mode		= {
70 		.name		= "800x480",
71 		.xres		= 800,
72 		.yres		= 480,
73 		.left_margin	= 88,
74 		.right_margin	= 40,
75 		.upper_margin	= 32,
76 		.lower_margin	= 11,
77 		.hsync_len	= 0,
78 		.vsync_len	= 1,
79 		.vmode		= FB_VMODE_NONINTERLACED,
80 	},
81 },
82 #endif
83 #ifdef CONFIG_WMT_PANEL_800X600
84 {
85 	.xres_virtual	= 800,
86 	.yres_virtual	= 600 * 2,
87 	.mode		= {
88 		.name		= "800x600",
89 		.xres		= 800,
90 		.yres		= 600,
91 		.left_margin	= 88,
92 		.right_margin	= 40,
93 		.upper_margin	= 32,
94 		.lower_margin	= 11,
95 		.hsync_len	= 0,
96 		.vsync_len	= 1,
97 		.vmode		= FB_VMODE_NONINTERLACED,
98 	},
99 },
100 #endif
101 #ifdef CONFIG_WMT_PANEL_1024X576
102 {
103 	.xres_virtual	= 1024,
104 	.yres_virtual	= 576 * 2,
105 	.mode		= {
106 		.name		= "1024x576",
107 		.xres		= 1024,
108 		.yres		= 576,
109 		.left_margin	= 40,
110 		.right_margin	= 24,
111 		.upper_margin	= 32,
112 		.lower_margin	= 11,
113 		.hsync_len	= 96,
114 		.vsync_len	= 2,
115 		.vmode		= FB_VMODE_NONINTERLACED,
116 	},
117 },
118 #endif
119 #ifdef CONFIG_WMT_PANEL_1024X600
120 {
121 	.xres_virtual	= 1024,
122 	.yres_virtual	= 600 * 2,
123 	.mode		= {
124 		.name		= "1024x600",
125 		.xres		= 1024,
126 		.yres		= 600,
127 		.left_margin	= 66,
128 		.right_margin	= 2,
129 		.upper_margin	= 19,
130 		.lower_margin	= 1,
131 		.hsync_len	= 23,
132 		.vsync_len	= 8,
133 		.vmode		= FB_VMODE_NONINTERLACED,
134 	},
135 },
136 #endif
137 };
138 
139 static int current_panel_idx __initdata = ARRAY_SIZE(panels) - 1;
140 
panel_setup(char * str)141 static int __init panel_setup(char *str)
142 {
143 	int i;
144 
145 	for (i = 0; i < ARRAY_SIZE(panels); i++) {
146 		if (strcmp(panels[i].mode.name, str) == 0) {
147 			current_panel_idx = i;
148 			break;
149 		}
150 	}
151 	return 0;
152 }
153 
154 early_param("panel", panel_setup);
155 
preallocate_fb(struct vt8500fb_platform_data * p,unsigned long align)156 static inline void preallocate_fb(struct vt8500fb_platform_data *p,
157 				  unsigned long align) {
158 	p->video_mem_len = (p->xres_virtual * p->yres_virtual * 4) >>
159 			(p->bpp > 16 ? 0 : (p->bpp > 8 ? 1 :
160 					(8 / p->bpp) + 1));
161 	p->video_mem_phys = (unsigned long)memblock_alloc(p->video_mem_len,
162 							  align);
163 	p->video_mem_virt = phys_to_virt(p->video_mem_phys);
164 }
165 
166 struct platform_device vt8500_device_uart0 = {
167 	.name		= "vt8500_serial",
168 	.id		= 0,
169 };
170 
171 struct platform_device vt8500_device_uart1 = {
172 	.name		= "vt8500_serial",
173 	.id		= 1,
174 };
175 
176 struct platform_device vt8500_device_uart2 = {
177 	.name		= "vt8500_serial",
178 	.id		= 2,
179 };
180 
181 struct platform_device vt8500_device_uart3 = {
182 	.name		= "vt8500_serial",
183 	.id		= 3,
184 };
185 
186 struct platform_device vt8500_device_uart4 = {
187 	.name		= "vt8500_serial",
188 	.id		= 4,
189 };
190 
191 struct platform_device vt8500_device_uart5 = {
192 	.name		= "vt8500_serial",
193 	.id		= 5,
194 };
195 
196 static u64 ehci_dma_mask = DMA_BIT_MASK(32);
197 
198 struct platform_device vt8500_device_ehci = {
199 	.name		= "vt8500-ehci",
200 	.id		= 0,
201 	.dev		= {
202 		.dma_mask	= &ehci_dma_mask,
203 		.coherent_dma_mask = DMA_BIT_MASK(32),
204 	},
205 };
206 
207 struct platform_device vt8500_device_ge_rops = {
208 	.name		= "wmt_ge_rops",
209 	.id		= -1,
210 };
211 
212 struct platform_device vt8500_device_pwm = {
213 	.name		= "vt8500-pwm",
214 	.id		= 0,
215 };
216 
217 static struct platform_pwm_backlight_data vt8500_pwmbl_data = {
218 	.pwm_id		= 0,
219 	.max_brightness	= 128,
220 	.dft_brightness = 70,
221 	.pwm_period_ns	= 250000, /* revisit when clocks are implemented */
222 };
223 
224 struct platform_device vt8500_device_pwmbl = {
225 	.name		= "pwm-backlight",
226 	.id		= 0,
227 	.dev		= {
228 		.platform_data = &vt8500_pwmbl_data,
229 	},
230 };
231 
232 struct platform_device vt8500_device_rtc = {
233 	.name		= "vt8500-rtc",
234 	.id		= 0,
235 };
236 
237 struct map_desc wmt_io_desc[] __initdata = {
238 	/* SoC MMIO registers */
239 	[0] = {
240 		.virtual	= 0xf8000000,
241 		.pfn		= __phys_to_pfn(0xd8000000),
242 		.length		= 0x00390000, /* max of all chip variants */
243 		.type		= MT_DEVICE
244 	},
245 	/* PCI I/O space, numbers tied to those in <mach/io.h> */
246 	[1] = {
247 		.virtual	= 0xf0000000,
248 		.pfn		= __phys_to_pfn(0xc0000000),
249 		.length		= SZ_64K,
250 		.type		= MT_DEVICE
251 	},
252 };
253 
vt8500_reserve_mem(void)254 void __init vt8500_reserve_mem(void)
255 {
256 #ifdef CONFIG_FB_VT8500
257 	panels[current_panel_idx].bpp = 16; /* Always use RGB565 */
258 	preallocate_fb(&panels[current_panel_idx], SZ_4M);
259 	vt8500_device_lcdc.dev.platform_data = &panels[current_panel_idx];
260 #endif
261 }
262 
wm8505_reserve_mem(void)263 void __init wm8505_reserve_mem(void)
264 {
265 #if defined CONFIG_FB_WM8505
266 	panels[current_panel_idx].bpp = 32; /* Always use RGB888 */
267 	preallocate_fb(&panels[current_panel_idx], 32);
268 	vt8500_device_wm8505_fb.dev.platform_data = &panels[current_panel_idx];
269 #endif
270 }
271