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