aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/boards
diff options
context:
space:
mode:
authorMagnus Damm <damm@igel.co.jp>2008-07-28 05:47:30 -0400
committerPaul Mundt <lethal@linux-sh.org>2008-07-28 05:48:06 -0400
commit8b1285f1c192e7e84ba28cc25eb0e9bcf2dadb17 (patch)
tree381a9ea288707cb19c66767d92b5a1ac63fcdbc7 /arch/sh/boards
parent761656e6beecb38c723f207d7408c753d3103ba8 (diff)
sh: Add SuperH Mobile LCDC platform data for Migo-R
Add WVGA and QVGA LCD panel support to Migo-R. Signed-off-by: Magnus Damm <damm@igel.co.jp> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/boards')
-rw-r--r--arch/sh/boards/renesas/migor/Kconfig15
-rw-r--r--arch/sh/boards/renesas/migor/Makefile1
-rw-r--r--arch/sh/boards/renesas/migor/lcd_qvga.c165
-rw-r--r--arch/sh/boards/renesas/migor/setup.c96
4 files changed, 277 insertions, 0 deletions
diff --git a/arch/sh/boards/renesas/migor/Kconfig b/arch/sh/boards/renesas/migor/Kconfig
new file mode 100644
index 000000000000..a7b3b728ec3c
--- /dev/null
+++ b/arch/sh/boards/renesas/migor/Kconfig
@@ -0,0 +1,15 @@
1if SH_MIGOR
2
3choice
4 prompt "Migo-R LCD Panel Board Selection"
5 default SH_MIGOR_QVGA
6
7config SH_MIGOR_QVGA
8 bool "QVGA (320x240)"
9
10config SH_MIGOR_RTA_WVGA
11 bool "RTA WVGA (800x480)"
12
13endchoice
14
15endif
diff --git a/arch/sh/boards/renesas/migor/Makefile b/arch/sh/boards/renesas/migor/Makefile
index 77037567633b..5f231dd25c0e 100644
--- a/arch/sh/boards/renesas/migor/Makefile
+++ b/arch/sh/boards/renesas/migor/Makefile
@@ -1 +1,2 @@
1obj-y := setup.o 1obj-y := setup.o
2obj-$(CONFIG_SH_MIGOR_QVGA) += lcd_qvga.o
diff --git a/arch/sh/boards/renesas/migor/lcd_qvga.c b/arch/sh/boards/renesas/migor/lcd_qvga.c
new file mode 100644
index 000000000000..6e9609596448
--- /dev/null
+++ b/arch/sh/boards/renesas/migor/lcd_qvga.c
@@ -0,0 +1,165 @@
1/*
2 * Support for SuperH MigoR Quarter VGA LCD Panel
3 *
4 * Copyright (C) 2008 Magnus Damm
5 *
6 * Based on lcd_powertip.c from Kenati Technologies Pvt Ltd.
7 * Copyright (c) 2007 Ujjwal Pande <ujjwal@kenati.com>,
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/delay.h>
15#include <linux/err.h>
16#include <linux/fb.h>
17#include <linux/init.h>
18#include <linux/kernel.h>
19#include <linux/module.h>
20#include <asm/sh_mobile_lcdc.h>
21#include <asm/migor.h>
22
23/* LCD Module is a PH240320T according to board schematics. This module
24 * is made up of a 240x320 LCD hooked up to a R61505U (or HX8347-A01?)
25 * Driver IC. This IC is connected to the SH7722 built-in LCDC using a
26 * SYS-80 interface configured in 16 bit mode.
27 *
28 * Index 0: "Device Code Read" returns 0x1505.
29 */
30
31static void reset_lcd_module(void)
32{
33 ctrl_outb(ctrl_inb(PORT_PHDR) & ~0x04, PORT_PHDR);
34 mdelay(2);
35 ctrl_outb(ctrl_inb(PORT_PHDR) | 0x04, PORT_PHDR);
36 mdelay(1);
37}
38
39/* DB0-DB7 are connected to D1-D8, and DB8-DB15 to D10-D17 */
40
41static unsigned long adjust_reg18(unsigned short data)
42{
43 unsigned long tmp1, tmp2;
44
45 tmp1 = (data<<1 | 0x00000001) & 0x000001FF;
46 tmp2 = (data<<2 | 0x00000200) & 0x0003FE00;
47 return tmp1 | tmp2;
48}
49
50static void write_reg(void *sys_ops_handle,
51 struct sh_mobile_lcdc_sys_bus_ops *sys_ops,
52 unsigned short reg, unsigned short data)
53{
54 sys_ops->write_index(sys_ops_handle, adjust_reg18(reg << 8 | data));
55}
56
57static void write_reg16(void *sys_ops_handle,
58 struct sh_mobile_lcdc_sys_bus_ops *sys_ops,
59 unsigned short reg, unsigned short data)
60{
61 sys_ops->write_index(sys_ops_handle, adjust_reg18(reg));
62 sys_ops->write_data(sys_ops_handle, adjust_reg18(data));
63}
64
65static unsigned long read_reg16(void *sys_ops_handle,
66 struct sh_mobile_lcdc_sys_bus_ops *sys_ops,
67 unsigned short reg)
68{
69 unsigned long data;
70
71 sys_ops->write_index(sys_ops_handle, adjust_reg18(reg));
72 data = sys_ops->read_data(sys_ops_handle);
73 return ((data >> 1) & 0xff) | ((data >> 2) & 0xff00);
74}
75
76static void migor_lcd_qvga_seq(void *sys_ops_handle,
77 struct sh_mobile_lcdc_sys_bus_ops *sys_ops,
78 unsigned short const *data, int no_data)
79{
80 int i;
81
82 for (i = 0; i < no_data; i += 2)
83 write_reg16(sys_ops_handle, sys_ops, data[i], data[i + 1]);
84}
85
86static const unsigned short sync_data[] = {
87 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
88};
89
90static const unsigned short magic0_data[] = {
91 0x0060, 0x2700, 0x0008, 0x0808, 0x0090, 0x001A, 0x0007, 0x0001,
92 0x0017, 0x0001, 0x0019, 0x0000, 0x0010, 0x17B0, 0x0011, 0x0116,
93 0x0012, 0x0198, 0x0013, 0x1400, 0x0029, 0x000C, 0x0012, 0x01B8,
94};
95
96static const unsigned short magic1_data[] = {
97 0x0030, 0x0307, 0x0031, 0x0303, 0x0032, 0x0603, 0x0033, 0x0202,
98 0x0034, 0x0202, 0x0035, 0x0202, 0x0036, 0x1F1F, 0x0037, 0x0303,
99 0x0038, 0x0303, 0x0039, 0x0603, 0x003A, 0x0202, 0x003B, 0x0102,
100 0x003C, 0x0204, 0x003D, 0x0000, 0x0001, 0x0100, 0x0002, 0x0300,
101 0x0003, 0x5028, 0x0020, 0x00ef, 0x0021, 0x0000, 0x0004, 0x0000,
102 0x0009, 0x0000, 0x000A, 0x0008, 0x000C, 0x0000, 0x000D, 0x0000,
103 0x0015, 0x8000,
104};
105
106static const unsigned short magic2_data[] = {
107 0x0061, 0x0001, 0x0092, 0x0100, 0x0093, 0x0001, 0x0007, 0x0021,
108};
109
110static const unsigned short magic3_data[] = {
111 0x0010, 0x16B0, 0x0011, 0x0111, 0x0007, 0x0061,
112};
113
114int migor_lcd_qvga_setup(void *board_data, void *sohandle,
115 struct sh_mobile_lcdc_sys_bus_ops *so)
116{
117 unsigned long xres = 320;
118 unsigned long yres = 240;
119 int k;
120
121 reset_lcd_module();
122 migor_lcd_qvga_seq(sohandle, so, sync_data, ARRAY_SIZE(sync_data));
123
124 if (read_reg16(sohandle, so, 0) != 0x1505)
125 return -ENODEV;
126
127 pr_info("Migo-R QVGA LCD Module detected.\n");
128
129 migor_lcd_qvga_seq(sohandle, so, sync_data, ARRAY_SIZE(sync_data));
130 write_reg16(sohandle, so, 0x00A4, 0x0001);
131 mdelay(10);
132
133 migor_lcd_qvga_seq(sohandle, so, magic0_data, ARRAY_SIZE(magic0_data));
134 mdelay(100);
135
136 migor_lcd_qvga_seq(sohandle, so, magic1_data, ARRAY_SIZE(magic1_data));
137 write_reg16(sohandle, so, 0x0050, 0xef - (yres - 1));
138 write_reg16(sohandle, so, 0x0051, 0x00ef);
139 write_reg16(sohandle, so, 0x0052, 0x0000);
140 write_reg16(sohandle, so, 0x0053, xres - 1);
141
142 migor_lcd_qvga_seq(sohandle, so, magic2_data, ARRAY_SIZE(magic2_data));
143 mdelay(10);
144
145 migor_lcd_qvga_seq(sohandle, so, magic3_data, ARRAY_SIZE(magic3_data));
146 mdelay(40);
147
148 /* clear GRAM to avoid displaying garbage */
149
150 write_reg16(sohandle, so, 0x0020, 0x0000); /* horiz addr */
151 write_reg16(sohandle, so, 0x0021, 0x0000); /* vert addr */
152
153 for (k = 0; k < (xres * 256); k++) /* yes, 256 words per line */
154 write_reg16(sohandle, so, 0x0022, 0x0000);
155
156 write_reg16(sohandle, so, 0x0020, 0x0000); /* reset horiz addr */
157 write_reg16(sohandle, so, 0x0021, 0x0000); /* reset vert addr */
158 write_reg16(sohandle, so, 0x0007, 0x0173);
159 mdelay(40);
160
161 /* enable display */
162 write_reg(sohandle, so, 0x00, 0x22);
163 mdelay(100);
164 return 0;
165}
diff --git a/arch/sh/boards/renesas/migor/setup.c b/arch/sh/boards/renesas/migor/setup.c
index 91819fb61b3e..28f7ab489c46 100644
--- a/arch/sh/boards/renesas/migor/setup.c
+++ b/arch/sh/boards/renesas/migor/setup.c
@@ -19,6 +19,7 @@
19#include <asm/machvec.h> 19#include <asm/machvec.h>
20#include <asm/io.h> 20#include <asm/io.h>
21#include <asm/sh_keysc.h> 21#include <asm/sh_keysc.h>
22#include <asm/sh_mobile_lcdc.h>
22#include <asm/migor.h> 23#include <asm/migor.h>
23 24
24/* Address IRQ Size Bus Description 25/* Address IRQ Size Bus Description
@@ -199,9 +200,80 @@ static struct platform_device migor_nand_flash_device = {
199 } 200 }
200}; 201};
201 202
203static struct sh_mobile_lcdc_info sh_mobile_lcdc_info = {
204#ifdef CONFIG_SH_MIGOR_RTA_WVGA
205 .clock_source = LCDC_CLK_BUS,
206 .ch[0] = {
207 .chan = LCDC_CHAN_MAINLCD,
208 .bpp = 16,
209 .interface_type = RGB16,
210 .clock_divider = 2,
211 .lcd_cfg = {
212 .name = "LB070WV1",
213 .xres = 800,
214 .yres = 480,
215 .left_margin = 64,
216 .right_margin = 16,
217 .hsync_len = 120,
218 .upper_margin = 1,
219 .lower_margin = 17,
220 .vsync_len = 2,
221 .sync = 0,
222 },
223 }
224#endif
225#ifdef CONFIG_SH_MIGOR_QVGA
226 .clock_source = LCDC_CLK_PERIPHERAL,
227 .ch[0] = {
228 .chan = LCDC_CHAN_MAINLCD,
229 .bpp = 16,
230 .interface_type = SYS16A,
231 .clock_divider = 10,
232 .lcd_cfg = {
233 .name = "PH240320T",
234 .xres = 320,
235 .yres = 240,
236 .left_margin = 0,
237 .right_margin = 16,
238 .hsync_len = 8,
239 .upper_margin = 1,
240 .lower_margin = 17,
241 .vsync_len = 2,
242 .sync = FB_SYNC_HOR_HIGH_ACT,
243 },
244 .board_cfg = {
245 .setup_sys = migor_lcd_qvga_setup,
246 },
247 .sys_bus_cfg = {
248 .ldmt2r = 0x06000a09,
249 .ldmt3r = 0x180e3418,
250 },
251 }
252#endif
253};
254
255static struct resource migor_lcdc_resources[] = {
256 [0] = {
257 .name = "LCDC",
258 .start = 0xfe940000, /* P4-only space */
259 .end = 0xfe941fff,
260 .flags = IORESOURCE_MEM,
261 },
262};
263
264static struct platform_device migor_lcdc_device = {
265 .name = "sh_mobile_lcdc_fb",
266 .num_resources = ARRAY_SIZE(migor_lcdc_resources),
267 .resource = migor_lcdc_resources,
268 .dev = {
269 .platform_data = &sh_mobile_lcdc_info,
270 },
271};
272
202static struct platform_device *migor_devices[] __initdata = { 273static struct platform_device *migor_devices[] __initdata = {
203 &smc91x_eth_device, 274 &smc91x_eth_device,
204 &sh_keysc_device, 275 &sh_keysc_device,
276 &migor_lcdc_device,
205 &migor_nor_flash_device, 277 &migor_nor_flash_device,
206 &migor_nand_flash_device, 278 &migor_nand_flash_device,
207}; 279};
@@ -219,6 +291,7 @@ static struct i2c_board_info __initdata migor_i2c_devices[] = {
219static int __init migor_devices_setup(void) 291static int __init migor_devices_setup(void)
220{ 292{
221 clk_always_enable("mstp214"); /* KEYSC */ 293 clk_always_enable("mstp214"); /* KEYSC */
294 clk_always_enable("mstp200"); /* LCDC */
222 295
223 i2c_register_board_info(0, migor_i2c_devices, 296 i2c_register_board_info(0, migor_i2c_devices,
224 ARRAY_SIZE(migor_i2c_devices)); 297 ARRAY_SIZE(migor_i2c_devices));
@@ -248,6 +321,29 @@ static void __init migor_setup(char **cmdline_p)
248 ctrl_outw(ctrl_inw(PORT_PZCR) & ~0xc, PORT_PZCR); 321 ctrl_outw(ctrl_inw(PORT_PZCR) & ~0xc, PORT_PZCR);
249 ctrl_outw((ctrl_inw(PORT_PSELA) | 0x8000), PORT_PSELA); 322 ctrl_outw((ctrl_inw(PORT_PSELA) | 0x8000), PORT_PSELA);
250 ctrl_outw((ctrl_inw(PORT_HIZCRC) & ~0x4000), PORT_HIZCRC); 323 ctrl_outw((ctrl_inw(PORT_HIZCRC) & ~0x4000), PORT_HIZCRC);
324
325#ifdef CONFIG_SH_MIGOR_RTA_WVGA
326 /* LCDC - WVGA - Enable RGB Interface signals */
327 ctrl_outw(ctrl_inw(PORT_PACR) & ~0x0003, PORT_PACR);
328 ctrl_outw(0x0000, PORT_PHCR);
329 ctrl_outw(0x0000, PORT_PLCR);
330 ctrl_outw(0x0000, PORT_PMCR);
331 ctrl_outw(ctrl_inw(PORT_PRCR) & ~0x000f, PORT_PRCR);
332 ctrl_outw((ctrl_inw(PORT_PSELD) & ~0x000d) | 0x0400, PORT_PSELD);
333 ctrl_outw(ctrl_inw(PORT_MSELCRB) & ~0x0100, PORT_MSELCRB);
334 ctrl_outw(ctrl_inw(PORT_HIZCRA) & ~0x01e0, PORT_HIZCRA);
335#endif
336#ifdef CONFIG_SH_MIGOR_QVGA
337 /* LCDC - QVGA - Enable SYS Interface signals */
338 ctrl_outw(ctrl_inw(PORT_PACR) & ~0x0003, PORT_PACR);
339 ctrl_outw((ctrl_inw(PORT_PHCR) & ~0xcfff) | 0x0010, PORT_PHCR);
340 ctrl_outw(0x0000, PORT_PLCR);
341 ctrl_outw(0x0000, PORT_PMCR);
342 ctrl_outw(ctrl_inw(PORT_PRCR) & ~0x030f, PORT_PRCR);
343 ctrl_outw((ctrl_inw(PORT_PSELD) & ~0x0001) | 0x0420, PORT_PSELD);
344 ctrl_outw(ctrl_inw(PORT_MSELCRB) | 0x0100, PORT_MSELCRB);
345 ctrl_outw(ctrl_inw(PORT_HIZCRA) & ~0x01e0, PORT_HIZCRA);
346#endif
251} 347}
252 348
253static struct sh_machine_vector mv_migor __initmv = { 349static struct sh_machine_vector mv_migor __initmv = {