1/* 2 3 btcx-risc.c 4 5 bt848/bt878/cx2388x risc code generator. 6 7 (c) 2000-03 Gerd Knorr <kraxel@bytesex.org> [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 35MODULE_DESCRIPTION("some code shared by bttv and cx88xx drivers"); 36MODULE_AUTHOR("Gerd Knorr"); 37MODULE_LICENSE("GPL"); 38 39static unsigned int debug; 40module_param(debug, int, 0644); 41MODULE_PARM_DESC(debug,"debug messages, default is 0 (no)"); 42 43/* ---------------------------------------------------------- */ 44/* allocate/free risc memory */ 45 46static int memcnt; 47 48void 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 62int 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 91int 92btcx_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 130int 131btcx_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 164void 165btcx_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 186void 187btcx_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 248EXPORT_SYMBOL(btcx_riscmem_alloc); 249EXPORT_SYMBOL(btcx_riscmem_free); 250 251EXPORT_SYMBOL(btcx_screen_clips); 252EXPORT_SYMBOL(btcx_align); 253EXPORT_SYMBOL(btcx_sort_clips); 254EXPORT_SYMBOL(btcx_calc_skips); 255 256/* 257 * Local variables: 258 * c-basic-offset: 8 259 * End: 260 */ 261