DSS2: OMAP2/3 Display Subsystem driver
[pandora-kernel.git] / arch / arm / plat-omap / vram.c
1 /*
2  * linux/arch/arm/plat-omap/vram.c
3  *
4  * Copyright (C) 2008 Nokia Corporation
5  * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
6  *
7  * Some code and ideas taken from drivers/video/omap/ driver
8  * by Imre Deak.
9  *
10  * This program is free software; you can redistribute it and/or modify it
11  * under the terms of the GNU General Public License version 2 as published by
12  * the Free Software Foundation.
13  *
14  * This program is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
17  * more details.
18  *
19  * You should have received a copy of the GNU General Public License along with
20  * this program.  If not, see <http://www.gnu.org/licenses/>.
21  */
22
23 /*#define DEBUG*/
24
25 #include <linux/vmalloc.h>
26 #include <linux/kernel.h>
27 #include <linux/mm.h>
28 #include <linux/list.h>
29 #include <linux/dma-mapping.h>
30 #include <linux/proc_fs.h>
31 #include <linux/seq_file.h>
32 #include <linux/bootmem.h>
33 #include <linux/omapfb.h>
34
35 #include <asm/setup.h>
36
37 #include <mach/sram.h>
38 #include <mach/vram.h>
39
40 #ifdef DEBUG
41 #define DBG(format, ...) printk(KERN_DEBUG "VRAM: " format, ## __VA_ARGS__)
42 #else
43 #define DBG(format, ...)
44 #endif
45
46 #define OMAP2_SRAM_START                0x40200000
47 /* Maximum size, in reality this is smaller if SRAM is partially locked. */
48 #define OMAP2_SRAM_SIZE                 0xa0000         /* 640k */
49
50 #define REG_MAP_SIZE(_page_cnt) \
51         ((_page_cnt + (sizeof(unsigned long) * 8) - 1) / 8)
52 #define REG_MAP_PTR(_rg, _page_nr) \
53         (((_rg)->map) + (_page_nr) / (sizeof(unsigned long) * 8))
54 #define REG_MAP_MASK(_page_nr) \
55         (1 << ((_page_nr) & (sizeof(unsigned long) * 8 - 1)))
56
57 #if defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE)
58
59 /* postponed regions are used to temporarily store region information at boot
60  * time when we cannot yet allocate the region list */
61 #define MAX_POSTPONED_REGIONS 10
62
63 static int postponed_cnt __initdata;
64 static struct {
65         unsigned long paddr;
66         size_t size;
67 } postponed_regions[MAX_POSTPONED_REGIONS] __initdata;
68
69 struct vram_alloc {
70         struct list_head list;
71         unsigned long paddr;
72         unsigned pages;
73 };
74
75 struct vram_region {
76         struct list_head list;
77         struct list_head alloc_list;
78         unsigned long paddr;
79         unsigned pages;
80 };
81
82 static DEFINE_MUTEX(region_mutex);
83 static LIST_HEAD(region_list);
84
85 static inline int region_mem_type(unsigned long paddr)
86 {
87         if (paddr >= OMAP2_SRAM_START &&
88             paddr < OMAP2_SRAM_START + OMAP2_SRAM_SIZE)
89                 return OMAPFB_MEMTYPE_SRAM;
90         else
91                 return OMAPFB_MEMTYPE_SDRAM;
92 }
93
94 static struct vram_region *omap_vram_create_region(unsigned long paddr,
95                 unsigned pages)
96 {
97         struct vram_region *rm;
98
99         rm = kzalloc(sizeof(*rm), GFP_KERNEL);
100
101         if (rm) {
102                 INIT_LIST_HEAD(&rm->alloc_list);
103                 rm->paddr = paddr;
104                 rm->pages = pages;
105         }
106
107         return rm;
108 }
109
110 #if 0
111 static void omap_vram_free_region(struct vram_region *vr)
112 {
113         list_del(&vr->list);
114         kfree(vr);
115 }
116 #endif
117
118 static struct vram_alloc *omap_vram_create_allocation(struct vram_region *vr,
119                 unsigned long paddr, unsigned pages)
120 {
121         struct vram_alloc *va;
122         struct vram_alloc *new;
123
124         new = kzalloc(sizeof(*va), GFP_KERNEL);
125
126         if (!new)
127                 return NULL;
128
129         new->paddr = paddr;
130         new->pages = pages;
131
132         list_for_each_entry(va, &vr->alloc_list, list) {
133                 if (va->paddr > new->paddr)
134                         break;
135         }
136
137         list_add_tail(&new->list, &va->list);
138
139         return new;
140 }
141
142 static void omap_vram_free_allocation(struct vram_alloc *va)
143 {
144         list_del(&va->list);
145         kfree(va);
146 }
147
148 static __init int omap_vram_add_region_postponed(unsigned long paddr,
149                 size_t size)
150 {
151         if (postponed_cnt == MAX_POSTPONED_REGIONS)
152                 return -ENOMEM;
153
154         postponed_regions[postponed_cnt].paddr = paddr;
155         postponed_regions[postponed_cnt].size = size;
156
157         ++postponed_cnt;
158
159         return 0;
160 }
161
162 /* add/remove_region can be exported if there's need to add/remove regions
163  * runtime */
164 static int omap_vram_add_region(unsigned long paddr, size_t size)
165 {
166         struct vram_region *rm;
167         unsigned pages;
168
169         DBG("adding region paddr %08lx size %d\n",
170                         paddr, size);
171
172         size &= PAGE_MASK;
173         pages = size >> PAGE_SHIFT;
174
175         rm = omap_vram_create_region(paddr, pages);
176         if (rm == NULL)
177                 return -ENOMEM;
178
179         list_add(&rm->list, &region_list);
180
181         return 0;
182 }
183
184 int omap_vram_free(unsigned long paddr, size_t size)
185 {
186         struct vram_region *rm;
187         struct vram_alloc *alloc;
188         unsigned start, end;
189
190         DBG("free mem paddr %08lx size %d\n", paddr, size);
191
192         size = PAGE_ALIGN(size);
193
194         mutex_lock(&region_mutex);
195
196         list_for_each_entry(rm, &region_list, list) {
197                 list_for_each_entry(alloc, &rm->alloc_list, list) {
198                         start = alloc->paddr;
199                         end = alloc->paddr + (alloc->pages >> PAGE_SHIFT);
200
201                         if (start >= paddr && end < paddr + size)
202                                 goto found;
203                 }
204         }
205
206         mutex_unlock(&region_mutex);
207         return -EINVAL;
208
209 found:
210         omap_vram_free_allocation(alloc);
211
212         mutex_unlock(&region_mutex);
213         return 0;
214 }
215 EXPORT_SYMBOL(omap_vram_free);
216
217 static int _omap_vram_reserve(unsigned long paddr, unsigned pages)
218 {
219         struct vram_region *rm;
220         struct vram_alloc *alloc;
221         size_t size;
222
223         size = pages << PAGE_SHIFT;
224
225         list_for_each_entry(rm, &region_list, list) {
226                 unsigned long start, end;
227
228                 DBG("checking region %lx %d\n", rm->paddr, rm->pages);
229
230                 if (region_mem_type(rm->paddr) != region_mem_type(paddr))
231                         continue;
232
233                 start = rm->paddr;
234                 end = start + (rm->pages << PAGE_SHIFT) - 1;
235                 if (start > paddr || end < paddr + size - 1)
236                         continue;
237
238                 DBG("block ok, checking allocs\n");
239
240                 list_for_each_entry(alloc, &rm->alloc_list, list) {
241                         end = alloc->paddr - 1;
242
243                         if (start <= paddr && end >= paddr + size - 1)
244                                 goto found;
245
246                         start = alloc->paddr + (alloc->pages << PAGE_SHIFT);
247                 }
248
249                 end = rm->paddr + (rm->pages << PAGE_SHIFT) - 1;
250
251                 if (!(start <= paddr && end >= paddr + size - 1))
252                         continue;
253 found:
254                 DBG("FOUND area start %lx, end %lx\n", start, end);
255
256                 if (omap_vram_create_allocation(rm, paddr, pages) == NULL)
257                         return -ENOMEM;
258
259                 return 0;
260         }
261
262         return -ENOMEM;
263 }
264
265 int omap_vram_reserve(unsigned long paddr, size_t size)
266 {
267         unsigned pages;
268         int r;
269
270         DBG("reserve mem paddr %08lx size %d\n", paddr, size);
271
272         size = PAGE_ALIGN(size);
273         pages = size >> PAGE_SHIFT;
274
275         mutex_lock(&region_mutex);
276
277         r = _omap_vram_reserve(paddr, pages);
278
279         mutex_unlock(&region_mutex);
280
281         return r;
282 }
283 EXPORT_SYMBOL(omap_vram_reserve);
284
285 static int _omap_vram_alloc(int mtype, unsigned pages, unsigned long *paddr)
286 {
287         struct vram_region *rm;
288         struct vram_alloc *alloc;
289
290         list_for_each_entry(rm, &region_list, list) {
291                 unsigned long start, end;
292
293                 DBG("checking region %lx %d\n", rm->paddr, rm->pages);
294
295                 if (region_mem_type(rm->paddr) != mtype)
296                         continue;
297
298                 start = rm->paddr;
299
300                 list_for_each_entry(alloc, &rm->alloc_list, list) {
301                         end = alloc->paddr;
302
303                         if (end - start >= pages << PAGE_SHIFT)
304                                 goto found;
305
306                         start = alloc->paddr + (alloc->pages << PAGE_SHIFT);
307                 }
308
309                 end = rm->paddr + (rm->pages << PAGE_SHIFT);
310 found:
311                 if (end - start < pages << PAGE_SHIFT)
312                         continue;
313
314                 DBG("FOUND %lx, end %lx\n", start, end);
315
316                 alloc = omap_vram_create_allocation(rm, start, pages);
317                 if (alloc == NULL)
318                         return -ENOMEM;
319
320                 *paddr = start;
321
322                 return 0;
323         }
324
325         return -ENOMEM;
326 }
327
328 int omap_vram_alloc(int mtype, size_t size, unsigned long *paddr)
329 {
330         unsigned pages;
331         int r;
332
333         BUG_ON(mtype > OMAPFB_MEMTYPE_MAX || !size);
334
335         DBG("alloc mem type %d size %d\n", mtype, size);
336
337         size = PAGE_ALIGN(size);
338         pages = size >> PAGE_SHIFT;
339
340         mutex_lock(&region_mutex);
341
342         r = _omap_vram_alloc(mtype, pages, paddr);
343
344         mutex_unlock(&region_mutex);
345
346         return r;
347 }
348 EXPORT_SYMBOL(omap_vram_alloc);
349
350 #ifdef CONFIG_PROC_FS
351 static void *r_next(struct seq_file *m, void *v, loff_t *pos)
352 {
353         struct list_head *l = v;
354
355         (*pos)++;
356
357         if (list_is_last(l, &region_list))
358                 return NULL;
359
360         return l->next;
361 }
362
363 static void *r_start(struct seq_file *m, loff_t *pos)
364 {
365         loff_t p = *pos;
366         struct list_head *l = &region_list;
367
368         mutex_lock(&region_mutex);
369
370         do {
371                 l = l->next;
372                 if (l == &region_list)
373                         return NULL;
374         } while (p--);
375
376         return l;
377 }
378
379 static void r_stop(struct seq_file *m, void *v)
380 {
381         mutex_unlock(&region_mutex);
382 }
383
384 static int r_show(struct seq_file *m, void *v)
385 {
386         struct vram_region *vr;
387         struct vram_alloc *va;
388         unsigned size;
389
390         vr = list_entry(v, struct vram_region, list);
391
392         size = vr->pages << PAGE_SHIFT;
393
394         seq_printf(m, "%08lx-%08lx (%d bytes)\n",
395                         vr->paddr, vr->paddr + size - 1,
396                         size);
397
398         list_for_each_entry(va, &vr->alloc_list, list) {
399                 size = va->pages << PAGE_SHIFT;
400                 seq_printf(m, "    %08lx-%08lx (%d bytes)\n",
401                                 va->paddr, va->paddr + size - 1,
402                                 size);
403         }
404
405
406
407         return 0;
408 }
409
410 static const struct seq_operations resource_op = {
411         .start  = r_start,
412         .next   = r_next,
413         .stop   = r_stop,
414         .show   = r_show,
415 };
416
417 static int vram_open(struct inode *inode, struct file *file)
418 {
419         return seq_open(file, &resource_op);
420 }
421
422 static const struct file_operations proc_vram_operations = {
423         .open           = vram_open,
424         .read           = seq_read,
425         .llseek         = seq_lseek,
426         .release        = seq_release,
427 };
428
429 static int __init omap_vram_create_proc(void)
430 {
431         proc_create("omap-vram", 0, NULL, &proc_vram_operations);
432
433         return 0;
434 }
435 #endif
436
437 static __init int omap_vram_init(void)
438 {
439         int i, r;
440
441         for (i = 0; i < postponed_cnt; i++)
442                 omap_vram_add_region(postponed_regions[i].paddr,
443                                 postponed_regions[i].size);
444
445 #ifdef CONFIG_PROC_FS
446         r = omap_vram_create_proc();
447         if (r)
448                 return -ENOMEM;
449 #endif
450
451         return 0;
452 }
453
454 arch_initcall(omap_vram_init);
455
456 /* boottime vram alloc stuff */
457
458 /* set from board file */
459 static u32 omapfb_sram_vram_start __initdata;
460 static u32 omapfb_sram_vram_size __initdata;
461
462 /* set from board file */
463 static u32 omapfb_sdram_vram_start __initdata;
464 static u32 omapfb_sdram_vram_size __initdata;
465
466 /* set from kernel cmdline */
467 static u32 omapfb_def_sdram_vram_size __initdata;
468 static u32 omapfb_def_sdram_vram_start __initdata;
469
470 static void __init omapfb_early_vram(char **p)
471 {
472         omapfb_def_sdram_vram_size = memparse(*p, p);
473         if (**p == ',')
474                 omapfb_def_sdram_vram_start = simple_strtoul((*p) + 1, p, 16);
475
476         printk("omapfb_early_vram, %d, 0x%x\n",
477                         omapfb_def_sdram_vram_size,
478                         omapfb_def_sdram_vram_start);
479 }
480 __early_param("vram=", omapfb_early_vram);
481
482 /*
483  * Called from map_io. We need to call to this early enough so that we
484  * can reserve the fixed SDRAM regions before VM could get hold of them.
485  */
486 void __init omapfb_reserve_sdram(void)
487 {
488         struct bootmem_data     *bdata;
489         unsigned long           sdram_start, sdram_size;
490         u32 paddr;
491         u32 size = 0;
492
493         /* cmdline arg overrides the board file definition */
494         if (omapfb_def_sdram_vram_size) {
495                 size = omapfb_def_sdram_vram_size;
496                 paddr = omapfb_def_sdram_vram_start;
497         }
498
499         if (!size) {
500                 size = omapfb_sdram_vram_size;
501                 paddr = omapfb_sdram_vram_start;
502         }
503
504 #ifdef CONFIG_OMAP2_DSS_VRAM_SIZE
505         if (!size) {
506                 size = CONFIG_OMAP2_DSS_VRAM_SIZE * 1024 * 1024;
507                 paddr = 0;
508         }
509 #endif
510
511         if (!size)
512                 return;
513
514         size = PAGE_ALIGN(size);
515
516         bdata = NODE_DATA(0)->bdata;
517         sdram_start = bdata->node_min_pfn << PAGE_SHIFT;
518         sdram_size = (bdata->node_low_pfn << PAGE_SHIFT) - sdram_start;
519
520         if (paddr) {
521                 if ((paddr & ~PAGE_MASK) || paddr < sdram_start ||
522                                 paddr + size > sdram_start + sdram_size) {
523                         printk(KERN_ERR "Illegal SDRAM region for VRAM\n");
524                         return;
525                 }
526
527                 reserve_bootmem(paddr, size, BOOTMEM_DEFAULT);
528         } else {
529                 if (size > sdram_size) {
530                         printk(KERN_ERR "Illegal SDRAM size for VRAM\n");
531                         return;
532                 }
533
534                 paddr = virt_to_phys(alloc_bootmem_pages(size));
535                 BUG_ON(paddr & ~PAGE_MASK);
536         }
537
538         omap_vram_add_region_postponed(paddr, size);
539
540         pr_info("Reserving %u bytes SDRAM for VRAM\n", size);
541 }
542
543 /*
544  * Called at sram init time, before anything is pushed to the SRAM stack.
545  * Because of the stack scheme, we will allocate everything from the
546  * start of the lowest address region to the end of SRAM. This will also
547  * include padding for page alignment and possible holes between regions.
548  *
549  * As opposed to the SDRAM case, we'll also do any dynamic allocations at
550  * this point, since the driver built as a module would have problem with
551  * freeing / reallocating the regions.
552  */
553 unsigned long __init omapfb_reserve_sram(unsigned long sram_pstart,
554                                   unsigned long sram_vstart,
555                                   unsigned long sram_size,
556                                   unsigned long pstart_avail,
557                                   unsigned long size_avail)
558 {
559         unsigned long                   pend_avail;
560         unsigned long                   reserved;
561         u32 paddr;
562         u32 size;
563
564         paddr = omapfb_sram_vram_start;
565         size = omapfb_sram_vram_size;
566
567         if (!size)
568                 return 0;
569
570         reserved = 0;
571         pend_avail = pstart_avail + size_avail;
572
573         if (!paddr) {
574                 /* Dynamic allocation */
575                 if ((size_avail & PAGE_MASK) < size) {
576                         printk(KERN_ERR "Not enough SRAM for VRAM\n");
577                         return 0;
578                 }
579                 size_avail = (size_avail - size) & PAGE_MASK;
580                 paddr = pstart_avail + size_avail;
581         }
582
583         if (paddr < sram_pstart ||
584                         paddr + size > sram_pstart + sram_size) {
585                 printk(KERN_ERR "Illegal SRAM region for VRAM\n");
586                 return 0;
587         }
588
589         /* Reserve everything above the start of the region. */
590         if (pend_avail - paddr > reserved)
591                 reserved = pend_avail - paddr;
592         size_avail = pend_avail - reserved - pstart_avail;
593
594         omap_vram_add_region_postponed(paddr, size);
595
596         if (reserved)
597                 pr_info("Reserving %lu bytes SRAM for VRAM\n", reserved);
598
599         return reserved;
600 }
601
602 void __init omap2_set_sdram_vram(u32 size, u32 start)
603 {
604         omapfb_sdram_vram_start = start;
605         omapfb_sdram_vram_size = size;
606 }
607
608 void __init omap2_set_sram_vram(u32 size, u32 start)
609 {
610         omapfb_sram_vram_start = start;
611         omapfb_sram_vram_size = size;
612 }
613
614 #endif
615