added 2.6.29.6 aldebaran kernel
[nao-ulib.git] / kernel / 2.6.29.6-aldebaran-rt / drivers / media / video / lxv4l2 / vid_mem.c
blobbf7d7212833d363c51a46a2458002aff7d856c77
1 /* <LIC_AMD_STD>
2 * Copyright (c) 2005 Advanced Micro Devices, Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
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.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 * The full GNU General Public License is included in this distribution in the
19 * file called COPYING
20 * </LIC_AMD_STD> */
21 /* <CTL_AMD_STD>
22 * </CTL_AMD_STD> */
23 /* <DOC_AMD_STD>
24 * </DOC_AMD_STD> */
25 #include <linux/module.h>
27 #ifdef CONFIG_PROC_FS
28 #include <linux/proc_fs.h>
29 #endif
31 #include "v4l.h"
33 #define VIDMEM_SZ 0x400000
34 #define _x(s) _s(s)
35 #define _s(s) #s
37 static int vidbufsize = VIDMEM_SZ;
39 #ifdef MODULE
40 module_param(vidbufsize, int, 0644);
41 MODULE_PARM_DESC(vidbufsize, "Size of the video buffer (default=" _x(VIDMEM_SZ) ")");
42 #endif
44 static vid_mem *vm_head = 0;
45 static vid_mem *vm_tail = 0;
47 static unsigned long vm_base = 0;
48 static unsigned long vm_ofst = 0;
49 static unsigned long vm_addr = 0;
50 static unsigned long vm_size = 0;
52 unsigned long vid_mem_base(void) { return vm_base; }
53 unsigned long vid_mem_ofst(void) { return vm_ofst; }
54 unsigned long vid_mem_addr(void) { return vm_addr; }
55 unsigned long vid_mem_size(void) { return vm_size; }
57 #ifdef CONFIG_PROC_FS
59 static int
60 proc_vm_read(char *page, char **start, off_t off, int count,
61 int *eof, void *data)
63 int len = 0;
64 vid_mem *vp = vm_head;
65 while( vp != NULL ) {
66 len += sprintf(page+len,"%-15s {",
67 vp->flags & VID_F_FREE ? "_free_" : vp->name);
68 len += sprintf(page+len,"flags 0x%02lx phys_addr 0x%08lx size 0x%08lx}\n",
69 vp->flags, vp->phys_addr, vp->size);
70 vp = vp->next;
72 return len;
75 #endif
77 vid_mem *
78 vid_mem_alloc(const char *name, unsigned long size, int flags)
80 vid_mem *vp, *rp;
81 if( (flags&VID_ALLOC_TOP) == 0 ) {
82 for( rp=vm_head; rp!=NULL; rp=rp->next ) {
83 if( (rp->flags&VID_F_FREE) == 0 ) continue;
84 if( rp->size >= size ) break;
87 else {
88 for( rp=vm_tail; rp!=NULL; rp=rp->prev ) {
89 if( (rp->flags&VID_F_FREE) == 0 ) continue;
90 if( rp->size >= size ) break;
93 if( rp == NULL ) goto xit;
95 if( rp->size != size ) {
96 vp = rp;
97 rp = kmalloc(sizeof(*rp), GFP_KERNEL);
98 if( rp == NULL ) goto xit;
99 rp->flags = 0;
100 rp->size = size;
101 if( (flags&VID_ALLOC_TOP) != 0 ) {
102 rp->phys_addr = vp->phys_addr + (vp->size-size);
103 rp->next = vp->next;
104 rp->prev = vp;
105 *(vp->next ? &vp->next->prev : &vm_tail) = rp;
106 vp->size -= size;
107 vp->next = rp;
109 else {
110 rp->phys_addr = vp->phys_addr;
111 rp->next = vp;
112 rp->prev = vp->prev;
113 *(vp->prev ? &vp->prev->next : &vm_head) = rp;
114 vp->phys_addr += size;
115 vp->size -= size;
116 vp->prev = rp;
120 strncpy(&rp->name[0],&name[0],sizeof(rp->name)-1);
121 rp->name[sizeof(rp->name)-1] = 0;
122 rp->flags &= ~VID_F_FREE;
123 xit:
124 return rp;
127 void
128 vid_mem_free(vid_mem *bp)
130 vid_mem *vp;
132 if( (vp=bp->prev) != NULL &&
133 (vp->flags&VID_F_FREE) != 0 &&
134 (vp->phys_addr+vp->size) == bp->phys_addr ) {
135 vp->size += bp->size;
136 vp->next = bp->next;
137 *(bp->next ? &bp->next->prev : &vm_tail) = vp;
138 kfree(bp);
139 bp = vp;
142 if( (vp=bp->next) != NULL &&
143 (vp->flags&VID_F_FREE) != 0 &&
144 (bp->phys_addr+bp->size) == vp->phys_addr ) {
145 bp->size += vp->size;
146 bp->next = vp->next;
147 *(vp->next ? &vp->next->prev : &vm_tail) = bp;
148 kfree(vp);
151 bp->flags = VID_F_FREE;
152 bp->name[0] = 0;
155 void
156 vid_mem_free_phys_addr(unsigned long phys_addr)
158 vid_mem *vp;
159 for( vp=vm_head; vp!=NULL && vp->phys_addr!=phys_addr; vp=vp->next );
160 if( vp != NULL )
161 vid_mem_free(vp);
165 vid_mem_init(void)
167 unsigned long phys_addr;
168 vid_mem *vp;
169 if( vm_size != 0 ) return 0;
170 phys_addr = cim_get_memory(v4l_name(),"video",vidbufsize,0);
171 if( phys_addr == 0 ) {
172 printk("cant allocate video memory\n");
173 return -ENODEV;
175 vp = kmalloc(sizeof(*vp), GFP_KERNEL);
176 if( vp == NULL ) return -ENOMEM;
177 memset(vp,0,sizeof(*vp));
178 vp->phys_addr = phys_addr;
179 vp->size = vidbufsize;
180 vp->flags = VID_F_FREE;
181 vm_head = vm_tail = vp;
182 #ifdef CONFIG_PROC_FS
183 if( lx_dev != NULL && lx_dev->proc != NULL )
184 create_proc_read_entry("map", 0, lx_dev->proc, proc_vm_read, NULL);
185 #endif
186 vm_size = vidbufsize;
187 vm_base = phys_addr;
188 vm_ofst = phys_addr - cim_get_fb_base();
189 vm_addr = (unsigned long)(cim_get_fb_ptr() + vm_ofst);
190 return 0;
193 void
194 vid_mem_exit(void)
196 vid_mem *vp, *np;
197 for( vp=vm_head; vp!=NULL; vp=np )
198 kfree((np=vp->next, vp));
199 vm_head = vm_tail = NULL;
200 cim_free_memory(v4l_name(),vm_base);
201 vm_size = vm_base = vm_ofst = vm_addr = 0;
204 unsigned long
205 vid_mem_avail(unsigned long blksz)
207 unsigned long blks;
208 unsigned long avail = 0;
209 vid_mem *vp;
210 if( blksz == 0 ) return 0;
211 for( vp=vm_head; vp!=NULL; vp=vp->next ) {
212 if( (vp->flags&VID_F_FREE) == 0 ) continue;
213 blks = vp->size / blksz;
214 avail += blks;
216 return avail;
220 is_vid_addr(unsigned long adr)
222 return adr>=vm_base && adr<(vm_base+vm_size) ? 1 : 0;