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 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 26 27 #include <linux/module.h> 28 #include <linux/init.h> 29 #include <linux/pci.h> 30 #include <linux/interrupt.h> 31 #include <linux/videodev2.h> 32 #include <asm/page.h> 33 #include <asm/pgtable.h> 34 35 #include "btcx-risc.h" 36 37 static unsigned int btcx_debug; 38 module_param(btcx_debug, int, 0644); 39 MODULE_PARM_DESC(btcx_debug,"debug messages, default is 0 (no)"); 40 41 #define dprintk(fmt, arg...) do { \ 42 if (btcx_debug) \ 43 printk(KERN_DEBUG pr_fmt("%s: " fmt), \ 44 __func__, ##arg); \ 45 } while (0) 46 47 48 /* ---------------------------------------------------------- */ 49 /* allocate/free risc memory */ 50 51 static int memcnt; 52 53 void btcx_riscmem_free(struct pci_dev *pci, 54 struct btcx_riscmem *risc) 55 { 56 if (NULL == risc->cpu) 57 return; 58 59 memcnt--; 60 dprintk("btcx: riscmem free [%d] dma=%lx\n", 61 memcnt, (unsigned long)risc->dma); 62 63 pci_free_consistent(pci, risc->size, risc->cpu, risc->dma); 64 memset(risc,0,sizeof(*risc)); 65 } 66 67 int btcx_riscmem_alloc(struct pci_dev *pci, 68 struct btcx_riscmem *risc, 69 unsigned int size) 70 { 71 __le32 *cpu; 72 dma_addr_t dma = 0; 73 74 if (NULL != risc->cpu && risc->size < size) 75 btcx_riscmem_free(pci,risc); 76 if (NULL == risc->cpu) { 77 cpu = pci_alloc_consistent(pci, size, &dma); 78 if (NULL == cpu) 79 return -ENOMEM; 80 risc->cpu = cpu; 81 risc->dma = dma; 82 risc->size = size; 83 84 memcnt++; 85 dprintk("btcx: riscmem alloc [%d] dma=%lx cpu=%p size=%d\n", 86 memcnt, (unsigned long)dma, cpu, size); 87 } 88 memset(risc->cpu,0,risc->size); 89 return 0; 90 } 91 92 /* ---------------------------------------------------------- */ 93 /* screen overlay helpers */ 94 95 int 96 btcx_screen_clips(int swidth, int sheight, struct v4l2_rect *win, 97 struct v4l2_clip *clips, unsigned int n) 98 { 99 if (win->left < 0) { 100 /* left */ 101 clips[n].c.left = 0; 102 clips[n].c.top = 0; 103 clips[n].c.width = -win->left; 104 clips[n].c.height = win->height; 105 n++; 106 } 107 if (win->left + win->width > swidth) { 108 /* right */ 109 clips[n].c.left = swidth - win->left; 110 clips[n].c.top = 0; 111 clips[n].c.width = win->width - clips[n].c.left; 112 clips[n].c.height = win->height; 113 n++; 114 } 115 if (win->top < 0) { 116 /* top */ 117 clips[n].c.left = 0; 118 clips[n].c.top = 0; 119 clips[n].c.width = win->width; 120 clips[n].c.height = -win->top; 121 n++; 122 } 123 if (win->top + win->height > sheight) { 124 /* bottom */ 125 clips[n].c.left = 0; 126 clips[n].c.top = sheight - win->top; 127 clips[n].c.width = win->width; 128 clips[n].c.height = win->height - clips[n].c.top; 129 n++; 130 } 131 return n; 132 } 133 134 int 135 btcx_align(struct v4l2_rect *win, struct v4l2_clip *clips, unsigned int n, int mask) 136 { 137 s32 nx,nw,dx; 138 unsigned int i; 139 140 /* fixup window */ 141 nx = (win->left + mask) & ~mask; 142 nw = (win->width) & ~mask; 143 if (nx + nw > win->left + win->width) 144 nw -= mask+1; 145 dx = nx - win->left; 146 win->left = nx; 147 win->width = nw; 148 dprintk("btcx: window align %dx%d+%d+%d [dx=%d]\n", 149 win->width, win->height, win->left, win->top, dx); 150 151 /* fixup clips */ 152 for (i = 0; i < n; i++) { 153 nx = (clips[i].c.left-dx) & ~mask; 154 nw = (clips[i].c.width) & ~mask; 155 if (nx + nw < clips[i].c.left-dx + clips[i].c.width) 156 nw += mask+1; 157 clips[i].c.left = nx; 158 clips[i].c.width = nw; 159 dprintk("btcx: clip align %dx%d+%d+%d\n", 160 clips[i].c.width, clips[i].c.height, 161 clips[i].c.left, clips[i].c.top); 162 } 163 return 0; 164 } 165 166 void 167 btcx_sort_clips(struct v4l2_clip *clips, unsigned int nclips) 168 { 169 int i,j,n; 170 171 if (nclips < 2) 172 return; 173 for (i = nclips-2; i >= 0; i--) { 174 for (n = 0, j = 0; j <= i; j++) { 175 if (clips[j].c.left > clips[j+1].c.left) { 176 swap(clips[j], clips[j + 1]); 177 n++; 178 } 179 } 180 if (0 == n) 181 break; 182 } 183 } 184 185 void 186 btcx_calc_skips(int line, int width, int *maxy, 187 struct btcx_skiplist *skips, unsigned int *nskips, 188 const struct v4l2_clip *clips, unsigned int nclips) 189 { 190 unsigned int clip,skip; 191 int end, maxline; 192 193 skip=0; 194 maxline = 9999; 195 for (clip = 0; clip < nclips; clip++) { 196 197 /* sanity checks */ 198 if (clips[clip].c.left + clips[clip].c.width <= 0) 199 continue; 200 if (clips[clip].c.left > (signed)width) 201 break; 202 203 /* vertical range */ 204 if (line > clips[clip].c.top+clips[clip].c.height-1) 205 continue; 206 if (line < clips[clip].c.top) { 207 if (maxline > clips[clip].c.top-1) 208 maxline = clips[clip].c.top-1; 209 continue; 210 } 211 if (maxline > clips[clip].c.top+clips[clip].c.height-1) 212 maxline = clips[clip].c.top+clips[clip].c.height-1; 213 214 /* horizontal range */ 215 if (0 == skip || clips[clip].c.left > skips[skip-1].end) { 216 /* new one */ 217 skips[skip].start = clips[clip].c.left; 218 if (skips[skip].start < 0) 219 skips[skip].start = 0; 220 skips[skip].end = clips[clip].c.left + clips[clip].c.width; 221 if (skips[skip].end > width) 222 skips[skip].end = width; 223 skip++; 224 } else { 225 /* overlaps -- expand last one */ 226 end = clips[clip].c.left + clips[clip].c.width; 227 if (skips[skip-1].end < end) 228 skips[skip-1].end = end; 229 if (skips[skip-1].end > width) 230 skips[skip-1].end = width; 231 } 232 } 233 *nskips = skip; 234 *maxy = maxline; 235 236 if (btcx_debug) { 237 dprintk("btcx: skips line %d-%d:", line, maxline); 238 for (skip = 0; skip < *nskips; skip++) { 239 pr_cont(" %d-%d", skips[skip].start, skips[skip].end); 240 } 241 pr_cont("\n"); 242 } 243 } 244