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
25 #include <linux/module.h>
28 #include <linux/proc_fs.h>
33 #define VIDMEM_SZ 0x400000
37 static int vidbufsize
= VIDMEM_SZ
;
40 module_param(vidbufsize
, int, 0644);
41 MODULE_PARM_DESC(vidbufsize
, "Size of the video buffer (default=" _x(VIDMEM_SZ
) ")");
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
; }
60 proc_vm_read(char *page
, char **start
, off_t off
, int count
,
64 vid_mem
*vp
= vm_head
;
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
);
78 vid_mem_alloc(const char *name
, unsigned long size
, int flags
)
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;
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
) {
97 rp
= kmalloc(sizeof(*rp
), GFP_KERNEL
);
98 if( rp
== NULL
) goto xit
;
101 if( (flags
&VID_ALLOC_TOP
) != 0 ) {
102 rp
->phys_addr
= vp
->phys_addr
+ (vp
->size
-size
);
105 *(vp
->next
? &vp
->next
->prev
: &vm_tail
) = rp
;
110 rp
->phys_addr
= vp
->phys_addr
;
113 *(vp
->prev
? &vp
->prev
->next
: &vm_head
) = rp
;
114 vp
->phys_addr
+= size
;
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
;
128 vid_mem_free(vid_mem
*bp
)
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
;
137 *(bp
->next
? &bp
->next
->prev
: &vm_tail
) = 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
;
147 *(vp
->next
? &vp
->next
->prev
: &vm_tail
) = bp
;
151 bp
->flags
= VID_F_FREE
;
156 vid_mem_free_phys_addr(unsigned long phys_addr
)
159 for( vp
=vm_head
; vp
!=NULL
&& vp
->phys_addr
!=phys_addr
; vp
=vp
->next
);
167 unsigned long phys_addr
;
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");
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
);
186 vm_size
= vidbufsize
;
188 vm_ofst
= phys_addr
- cim_get_fb_base();
189 vm_addr
= (unsigned long)(cim_get_fb_ptr() + vm_ofst
);
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;
205 vid_mem_avail(unsigned long blksz
)
208 unsigned long avail
= 0;
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
;
220 is_vid_addr(unsigned long adr
)
222 return adr
>=vm_base
&& adr
<(vm_base
+vm_size
) ? 1 : 0;