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