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 <linux/pgtable.h> 21 #include <asm/page.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 dma_free_coherent(&pci->dev, 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 = dma_alloc_coherent(&pci->dev, size, &dma, GFP_KERNEL); 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 return 0; 77 } 78 79 /* ---------------------------------------------------------- */ 80 /* screen overlay helpers */ 81 82 int 83 btcx_screen_clips(int swidth, int sheight, struct v4l2_rect *win, 84 struct v4l2_clip *clips, unsigned int n) 85 { 86 if (win->left < 0) { 87 /* left */ 88 clips[n].c.left = 0; 89 clips[n].c.top = 0; 90 clips[n].c.width = -win->left; 91 clips[n].c.height = win->height; 92 n++; 93 } 94 if (win->left + win->width > swidth) { 95 /* right */ 96 clips[n].c.left = swidth - win->left; 97 clips[n].c.top = 0; 98 clips[n].c.width = win->width - clips[n].c.left; 99 clips[n].c.height = win->height; 100 n++; 101 } 102 if (win->top < 0) { 103 /* top */ 104 clips[n].c.left = 0; 105 clips[n].c.top = 0; 106 clips[n].c.width = win->width; 107 clips[n].c.height = -win->top; 108 n++; 109 } 110 if (win->top + win->height > sheight) { 111 /* bottom */ 112 clips[n].c.left = 0; 113 clips[n].c.top = sheight - win->top; 114 clips[n].c.width = win->width; 115 clips[n].c.height = win->height - clips[n].c.top; 116 n++; 117 } 118 return n; 119 } 120 121 int 122 btcx_align(struct v4l2_rect *win, struct v4l2_clip *clips, unsigned int n, int mask) 123 { 124 s32 nx,nw,dx; 125 unsigned int i; 126 127 /* fixup window */ 128 nx = (win->left + mask) & ~mask; 129 nw = (win->width) & ~mask; 130 if (nx + nw > win->left + win->width) 131 nw -= mask+1; 132 dx = nx - win->left; 133 win->left = nx; 134 win->width = nw; 135 dprintk("btcx: window align %dx%d+%d+%d [dx=%d]\n", 136 win->width, win->height, win->left, win->top, dx); 137 138 /* fixup clips */ 139 for (i = 0; i < n; i++) { 140 nx = (clips[i].c.left-dx) & ~mask; 141 nw = (clips[i].c.width) & ~mask; 142 if (nx + nw < clips[i].c.left-dx + clips[i].c.width) 143 nw += mask+1; 144 clips[i].c.left = nx; 145 clips[i].c.width = nw; 146 dprintk("btcx: clip align %dx%d+%d+%d\n", 147 clips[i].c.width, clips[i].c.height, 148 clips[i].c.left, clips[i].c.top); 149 } 150 return 0; 151 } 152 153 void 154 btcx_sort_clips(struct v4l2_clip *clips, unsigned int nclips) 155 { 156 int i,j,n; 157 158 if (nclips < 2) 159 return; 160 for (i = nclips-2; i >= 0; i--) { 161 for (n = 0, j = 0; j <= i; j++) { 162 if (clips[j].c.left > clips[j+1].c.left) { 163 swap(clips[j], clips[j + 1]); 164 n++; 165 } 166 } 167 if (0 == n) 168 break; 169 } 170 } 171 172 void 173 btcx_calc_skips(int line, int width, int *maxy, 174 struct btcx_skiplist *skips, unsigned int *nskips, 175 const struct v4l2_clip *clips, unsigned int nclips) 176 { 177 unsigned int clip,skip; 178 int end, maxline; 179 180 skip=0; 181 maxline = 9999; 182 for (clip = 0; clip < nclips; clip++) { 183 184 /* sanity checks */ 185 if (clips[clip].c.left + clips[clip].c.width <= 0) 186 continue; 187 if (clips[clip].c.left > (signed)width) 188 break; 189 190 /* vertical range */ 191 if (line > clips[clip].c.top+clips[clip].c.height-1) 192 continue; 193 if (line < clips[clip].c.top) { 194 if (maxline > clips[clip].c.top-1) 195 maxline = clips[clip].c.top-1; 196 continue; 197 } 198 if (maxline > clips[clip].c.top+clips[clip].c.height-1) 199 maxline = clips[clip].c.top+clips[clip].c.height-1; 200 201 /* horizontal range */ 202 if (0 == skip || clips[clip].c.left > skips[skip-1].end) { 203 /* new one */ 204 skips[skip].start = clips[clip].c.left; 205 if (skips[skip].start < 0) 206 skips[skip].start = 0; 207 skips[skip].end = clips[clip].c.left + clips[clip].c.width; 208 if (skips[skip].end > width) 209 skips[skip].end = width; 210 skip++; 211 } else { 212 /* overlaps -- expand last one */ 213 end = clips[clip].c.left + clips[clip].c.width; 214 if (skips[skip-1].end < end) 215 skips[skip-1].end = end; 216 if (skips[skip-1].end > width) 217 skips[skip-1].end = width; 218 } 219 } 220 *nskips = skip; 221 *maxy = maxline; 222 223 if (btcx_debug) { 224 dprintk("btcx: skips line %d-%d:", line, maxline); 225 for (skip = 0; skip < *nskips; skip++) { 226 pr_cont(" %d-%d", skips[skip].start, skips[skip].end); 227 } 228 pr_cont("\n"); 229 } 230 } 231