ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / drivers / media / video / btcx-risc.c
1 /*
2     btcx-risc.c
3
4     bt848/bt878/cx2388x risc code generator.
5
6     (c) 2000-03 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
7
8     This program is free software; you can redistribute it and/or modify
9     it under the terms of the GNU General Public License as published by
10     the Free Software Foundation; either version 2 of the License, or
11     (at your option) any later version.
12
13     This program is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16     GNU General Public License for more details.
17
18     You should have received a copy of the GNU General Public License
19     along with this program; if not, write to the Free Software
20     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
22 */
23
24 #include <linux/module.h>
25 #include <linux/init.h>
26 #include <linux/pci.h>
27 #include <linux/interrupt.h>
28 #include <linux/videodev2.h>
29 #include <asm/page.h>
30 #include <asm/pgtable.h>
31
32 #include "btcx-risc.h"
33
34 MODULE_DESCRIPTION("some code shared by bttv and cx88xx drivers");
35 MODULE_AUTHOR("Gerd Knorr");
36 MODULE_LICENSE("GPL");
37
38 static unsigned int debug = 0;
39 MODULE_PARM(debug,"i");
40 MODULE_PARM_DESC(debug,"debug messages, default is 0 (no)");
41
42 /* ---------------------------------------------------------- */
43 /* allocate/free risc memory                                  */
44
45 static int memcnt;
46
47 void btcx_riscmem_free(struct pci_dev *pci,
48                        struct btcx_riscmem *risc)
49 {
50         if (NULL == risc->cpu)
51                 return;
52         pci_free_consistent(pci, risc->size, risc->cpu, risc->dma);
53         memset(risc,0,sizeof(*risc));
54         if (debug) {
55                 memcnt--;
56                 printk("btcx: riscmem free [%d]\n",memcnt);
57         }
58 }
59
60 int btcx_riscmem_alloc(struct pci_dev *pci,
61                        struct btcx_riscmem *risc,
62                        unsigned int size)
63 {
64         u32 *cpu;
65         dma_addr_t dma;
66
67         if (NULL != risc->cpu && risc->size < size)
68                 btcx_riscmem_free(pci,risc);
69         if (NULL == risc->cpu) {
70                 cpu = pci_alloc_consistent(pci, size, &dma);
71                 if (NULL == cpu)
72                         return -ENOMEM;
73                 risc->cpu  = cpu;
74                 risc->dma  = dma;
75                 risc->size = size;
76                 if (debug) {
77                         memcnt++;
78                         printk("btcx: riscmem alloc size=%d [%d]\n",size,memcnt);
79                 }
80         }
81         memset(risc->cpu,0,risc->size);
82         return 0;
83 }
84
85 /* ---------------------------------------------------------- */
86 /* screen overlay helpers                                     */
87
88 int
89 btcx_screen_clips(int swidth, int sheight, struct v4l2_rect *win,
90                   struct v4l2_clip *clips, unsigned int n)
91 {
92         if (win->left < 0) {
93                 /* left */
94                 clips[n].c.left = 0;
95                 clips[n].c.top = 0;
96                 clips[n].c.width  = -win->left;
97                 clips[n].c.height = win->height;
98                 n++;
99         }
100         if (win->left + win->width > swidth) {
101                 /* right */
102                 clips[n].c.left   = swidth - win->left;
103                 clips[n].c.top    = 0;
104                 clips[n].c.width  = win->width - clips[n].c.left;
105                 clips[n].c.height = win->height;
106                 n++;
107         }
108         if (win->top < 0) {
109                 /* top */
110                 clips[n].c.left = 0;
111                 clips[n].c.top = 0;
112                 clips[n].c.width  = win->width;
113                 clips[n].c.height = -win->top;
114                 n++;
115         }
116         if (win->top + win->height > sheight) {
117                 /* bottom */
118                 clips[n].c.left = 0;
119                 clips[n].c.top = sheight - win->top;
120                 clips[n].c.width  = win->width;
121                 clips[n].c.height = win->height - clips[n].c.top;
122                 n++;
123         }
124         return n;
125 }
126
127 int
128 btcx_align(struct v4l2_rect *win, struct v4l2_clip *clips, unsigned int n, int mask)
129 {
130         s32 nx,nw,dx;
131         unsigned int i;
132
133         /* fixup window */
134         nx = (win->left + mask) & ~mask;
135         nw = (win->width) & ~mask;
136         if (nx + nw > win->left + win->width)
137                 nw -= mask+1;
138         dx = nx - win->left;
139         win->left  = nx;
140         win->width = nw;
141         if (debug)
142                 printk(KERN_DEBUG "btcx: window align %dx%d+%d+%d [dx=%d]\n",
143                        win->width, win->height, win->left, win->top, dx);
144
145         /* fixup clips */
146         for (i = 0; i < n; i++) {
147                 nx = (clips[i].c.left-dx) & ~mask;
148                 nw = (clips[i].c.width) & ~mask;
149                 if (nx + nw < clips[i].c.left-dx + clips[i].c.width)
150                         nw += mask+1;
151                 clips[i].c.left  = nx;
152                 clips[i].c.width = nw;
153                 if (debug)
154                         printk(KERN_DEBUG "btcx:   clip align %dx%d+%d+%d\n",
155                                clips[i].c.width, clips[i].c.height,
156                                clips[i].c.left, clips[i].c.top);
157         }
158         return 0;
159 }
160
161 void
162 btcx_sort_clips(struct v4l2_clip *clips, unsigned int nclips)
163 {
164         struct v4l2_clip swap;
165         int i,j,n;
166
167         if (nclips < 2)
168                 return;
169         for (i = nclips-2; i >= 0; i--) {
170                 for (n = 0, j = 0; j <= i; j++) {
171                         if (clips[j].c.left > clips[j+1].c.left) {
172                                 swap = clips[j];
173                                 clips[j] = clips[j+1];
174                                 clips[j+1] = swap;
175                                 n++;
176                         }
177                 }
178                 if (0 == n)
179                         break;
180         }
181 }
182
183 void
184 btcx_calc_skips(int line, int width, unsigned int *maxy,
185                 struct btcx_skiplist *skips, unsigned int *nskips,
186                 const struct v4l2_clip *clips, unsigned int nclips)
187 {
188         unsigned int clip,skip;
189         int end,maxline;
190         
191         skip=0;
192         maxline = 9999;
193         for (clip = 0; clip < nclips; clip++) {
194
195                 /* sanity checks */
196                 if (clips[clip].c.left + clips[clip].c.width <= 0)
197                         continue;
198                 if (clips[clip].c.left > (signed)width)
199                         break;
200                 
201                 /* vertical range */
202                 if (line > clips[clip].c.top+clips[clip].c.height-1)
203                         continue;
204                 if (line < clips[clip].c.top) {
205                         if (maxline > clips[clip].c.top-1)
206                                 maxline = clips[clip].c.top-1;
207                         continue;
208                 }
209                 if (maxline > clips[clip].c.top+clips[clip].c.height-1)
210                         maxline = clips[clip].c.top+clips[clip].c.height-1;
211
212                 /* horizontal range */
213                 if (0 == skip || clips[clip].c.left > skips[skip-1].end) {
214                         /* new one */
215                         skips[skip].start = clips[clip].c.left;
216                         if (skips[skip].start < 0)
217                                 skips[skip].start = 0;
218                         skips[skip].end = clips[clip].c.left + clips[clip].c.width;
219                         if (skips[skip].end > width)
220                                 skips[skip].end = width;
221                         skip++;
222                 } else {
223                         /* overlaps -- expand last one */
224                         end = clips[clip].c.left + clips[clip].c.width;
225                         if (skips[skip-1].end < end)
226                                 skips[skip-1].end = end;
227                         if (skips[skip-1].end > width)
228                                 skips[skip-1].end = width;
229                 }
230         }
231         *nskips = skip;
232         *maxy = maxline;
233
234         if (debug) {
235                 printk(KERN_DEBUG "btcx: skips line %d-%d:",line,maxline);
236                 for (skip = 0; skip < *nskips; skip++) {
237                         printk(" %d-%d",skips[skip].start,skips[skip].end);
238                 }
239                 printk("\n");
240         }
241 }
242
243 /* ---------------------------------------------------------- */
244
245 EXPORT_SYMBOL(btcx_riscmem_alloc);
246 EXPORT_SYMBOL(btcx_riscmem_free);
247
248 EXPORT_SYMBOL(btcx_screen_clips);
249 EXPORT_SYMBOL(btcx_align);
250 EXPORT_SYMBOL(btcx_sort_clips);
251 EXPORT_SYMBOL(btcx_calc_skips);
252
253 /*
254  * Local variables:
255  * c-basic-offset: 8
256  * End:
257  */