]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/arm_drivers/lcd/src/lcd-s3c2410.c
f37c1f0c39c17c7d467fe459dad0e688378bbccc
[l4.git] / l4 / pkg / arm_drivers / lcd / src / lcd-s3c2410.c
1 /*
2  * LCD driver for s3c2410
3  */
4
5 #include <l4/arm_drivers/lcd.h>
6 #include <stdlib.h>
7 #include <stdio.h>
8
9 #include <l4/re/c/dataspace.h>
10 #include <l4/re/c/rm.h>
11 #include <l4/re/c/util/cap_alloc.h>
12 #include <l4/re/c/mem_alloc.h>
13 #include <l4/io/io.h>
14
15 #define LCD_NAME "LCD s3c2410"
16
17 static void *fb_vaddr;
18 static l4_addr_t fb_paddr;
19
20 enum {
21   LCDCON1   = 0x00,
22   LCDCON2   = 0x04,
23   LCDCON3   = 0x08,
24   LCDCON4   = 0x0c,
25   LCDCON5   = 0x10,
26   LCDSADDR1 = 0x14,
27   LCDSADDR2 = 0x18,
28   LCDSADDR3 = 0x1c,
29
30   WIDTH = 480,
31   HEIGHT = 640,
32
33   LCDCON1_ENABLE_BIT    = 1,
34   LCDCON1_BPPMODE_16BPP = 0xc << 1,
35   LCDCON1_PNRMODE_LCD   = 3 << 5,
36   LCDCON1_CLKVAL        = 0,
37   LCDCON1_ENABLE_VALUE  = LCDCON1_ENABLE_BIT | LCDCON1_BPPMODE_16BPP
38                              | LCDCON1_PNRMODE_LCD | LCDCON1_CLKVAL,
39
40   LCDCON2_LINEVAL = (HEIGHT-1) << 14,
41   LCDCON2_ENABLE_VALUE = LCDCON2_LINEVAL,
42
43   LCDCON3_HOZVAL = (WIDTH-1) << 8,
44   LCDCON3_ENABLE_VALUE = LCDCON3_HOZVAL,
45
46   LCDCON4_ENABLE_VALUE = 7,
47
48   LCDCON5_PWREN  = 1 << 3,
49   LCDCON5_FRM565 = 1 << 11,
50   LCDCON5_ENABLE_VALUE = LCDCON5_PWREN | LCDCON5_FRM565 | 1,
51
52
53 //  wr(0x00000179 & ~LCDCON1_ENABLE_BIT, LCDCON1);
54 //  wr(0x019fc3c1, LCDCON2);
55 //  wr(0x0039df67, LCDCON3);
56 //  wr(0x00000007, LCDCON4);
57 //  wr(0x00000f09, LCDCON5);
58 };
59
60 static const char *arm_lcd_get_info(void)
61 { return "S3C2410"; }
62
63 static int probe(const char *configstr)
64 {
65   (void)configstr;
66   return !l4io_lookup_device(LCD_NAME, NULL, 0, 0);
67 }
68
69 static unsigned int fbmem_size(void) { return (1 << 22); } //height() * bpl(); }
70
71 static unsigned long lcd_control_virt_base;
72
73 static int get_fbinfo(l4re_video_view_info_t *vinfo)
74 {
75   vinfo->width          = 480;
76   vinfo->width          = 640;
77   vinfo->bytes_per_line = 2 * vinfo->width;
78
79   vinfo->pixel_info.bytes_per_pixel = 2;
80   vinfo->pixel_info.r.shift         = 0;
81   vinfo->pixel_info.r.size          = 5;
82   vinfo->pixel_info.g.shift         = 5;
83   vinfo->pixel_info.g.size          = 6;
84   vinfo->pixel_info.b.shift         = 11;
85   vinfo->pixel_info.b.size          = 5;
86   vinfo->pixel_info.a.shift         = 0;
87   vinfo->pixel_info.a.size          = 0;
88
89   return 0;
90 }
91
92
93 static void setup_memory(void)
94 {
95   l4_size_t phys_size;
96   l4io_device_handle_t dh;
97   l4io_resource_handle_t hdl;
98
99
100   if (fb_vaddr)
101     return;
102
103   if (l4io_lookup_device(LCD_NAME, &dh, 0, &hdl))
104     {
105       printf("Could not get s3c2410fb\n");
106       return;
107     }
108   lcd_control_virt_base = l4io_request_resource_iomem(dh, &hdl);
109
110   if (lcd_control_virt_base == 0)
111     {
112       printf("Could not map controller space for '%s'\n", arm_lcd_get_info());
113       return;
114     }
115
116   // get some frame buffer
117   l4re_ds_t mem = l4re_util_cap_alloc();
118   if (l4_is_invalid_cap(mem))
119     return;
120
121   if (l4re_ma_alloc(fbmem_size(), mem, L4RE_MA_CONTINUOUS | L4RE_MA_PINNED))
122     {
123       printf("Could not get video memory.\n");
124       return;
125     }
126
127   fb_vaddr = 0;
128   if (l4re_rm_attach(&fb_vaddr, fbmem_size(),
129                      L4RE_RM_SEARCH_ADDR | L4RE_RM_EAGER_MAP,
130                      mem, 0, L4_PAGESHIFT))
131
132     {
133       printf("Could not map fb\n");
134       return;
135     }
136
137   printf("Video memory is at virtual %p (size: 0x%x Bytes)\n",
138          fb_vaddr, fbmem_size());
139
140   // get physical address
141   if (l4re_ds_phys(mem, 0, &fb_paddr, &phys_size)
142       || phys_size != fbmem_size())
143     {
144       printf("Getting the physical address failed or not contiguous\n");
145       return;
146     }
147   printf("Physical video memory is at %p\n", (void *)fb_paddr);
148 }
149
150 static inline void wr(unsigned long val, unsigned long regoff)
151 { *(volatile unsigned long *)(lcd_control_virt_base + regoff) = val; }
152 static inline unsigned long rd(unsigned long regoff)
153 { return *(volatile unsigned long *)(lcd_control_virt_base + regoff); }
154
155 static void *fb(void)
156 {
157   if (!fb_vaddr)
158     setup_memory();
159
160   return fb_vaddr;
161 }
162
163 #if 0
164 s3c2410fb: devinit
165 s3c2410fb: got LCD region
166 s3c2410fb: got and enabled clock
167 s3c2410fb: map_video_memory(fbi=c04ce274)
168   s3c2410fb: map_video_memory: clear ffc00000:0012c000
169   s3c2410fb: map_video_memory: dma=30600000 cpu=ffc00000 size=0012c000
170   s3c2410fb: got video memory
171   s3c2410fb: LCDSADDR1 = 0x18300000
172   s3c2410fb: LCDSADDR2 = 0x1834b000
173   s3c2410fb: LCDSADDR3 = 0x000001e0
174   s3c2410fb: LPCSEL    = 0x00000cf0
175   s3c2410fb: replacing TPAL 00000000
176   s3c2410fb: check_var(var=c04ce008, info=c04ce000)
177   s3c2410fb: s3c2410fb_activate_var: var->xres  = 480
178   s3c2410fb: s3c2410fb_activate_var: var->yres  = 640
179   s3c2410fb: s3c2410fb_activate_var: var->bpp   = 16
180   s3c2410fb: setting vert: up=2, low=16, sync=2
181   s3c2410fb: setting horz: lft=104, rt=8, sync=8
182   s3c2410fb: new register set:
183   s3c2410fb: lcdcon[1] = 0x00000179
184   s3c2410fb: lcdcon[2] = 0x019fc3c1
185   s3c2410fb: lcdcon[3] = 0x0039df67
186   s3c2410fb: lcdcon[4] = 0x00000007
187   s3c2410fb: lcdcon[5] = 0x00000f09
188   s3c2410fb: LCDSADDR1 = 0x18300000
189   s3c2410fb: LCDSADDR2 = 0x1834b000
190   s3c2410fb: LCDSADDR3 = 0x000001e0
191   Console: switching to colour frame buffer device 80x58
192   fb0: s3c2410fb frame buffer device
193 #endif
194
195 static void pl110_enable(void)
196 {
197   setup_memory();
198
199   wr(0x00000179 & ~LCDCON1_ENABLE_BIT, LCDCON1);
200   wr(0x019fc3c1, LCDCON2);
201   wr(0x0039df67, LCDCON3);
202   wr(0x00000007, LCDCON4);
203   wr(0x00000f09, LCDCON5);
204 #if 0
205   wr(LCDCON1_ENABLE_VALUE & ~LCDCON1_ENABLE_BIT, LCDCON1);
206   wr(LCDCON2_ENABLE_VALUE, LCDCON2);
207   wr(LCDCON3_ENABLE_VALUE, LCDCON3);
208   wr(LCDCON4_ENABLE_VALUE, LCDCON4);
209   wr(LCDCON5_ENABLE_VALUE, LCDCON5);
210 #endif
211
212
213   wr(fb_paddr >> 1, LCDSADDR1);
214   wr((fb_paddr + 640*480*2) >> 1, LCDSADDR2);
215   wr(480, LCDSADDR3);
216
217   wr(0x00000179, LCDCON1);
218   {
219 //    int i = 0;
220  //   for (; i < 0x20; i+=4)
221   //    printf("%02x: %08lx\n", i, rd(i));
222   }
223 }
224
225 static void pl110_disable(void)
226 {
227 }
228 static struct arm_lcd_ops arm_lcd_ops_pl110 = {
229   .probe              = probe,
230   .get_fb             = fb,
231   .get_fbinfo         = get_fbinfo,
232   .get_video_mem_size = fbmem_size,
233   .get_info           = arm_lcd_get_info,
234   .enable             = pl110_enable,
235   .disable            = pl110_disable,
236 };
237
238 arm_lcd_register(&arm_lcd_ops_pl110);