 f1c50f2489
			
		
	
	
	f1c50f2489
	
	
	
		
			
			The btcx-risc module is a helper module for bttv/conexant based TV cards. It isn't an i2c module at all, instead it should be in common since it is used by 4 pci drivers. Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
		
			
				
	
	
		
			260 lines
		
	
	
	
		
			6.3 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			260 lines
		
	
	
	
		
			6.3 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
| 
 | |
|     btcx-risc.c
 | |
| 
 | |
|     bt848/bt878/cx2388x risc code generator.
 | |
| 
 | |
|     (c) 2000-03 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
 | |
| 
 | |
|     This program is free software; you can redistribute it and/or modify
 | |
|     it under the terms of the GNU General Public License as published by
 | |
|     the Free Software Foundation; either version 2 of the License, or
 | |
|     (at your option) any later version.
 | |
| 
 | |
|     This program is distributed in the hope that it will be useful,
 | |
|     but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
|     GNU General Public License for more details.
 | |
| 
 | |
|     You should have received a copy of the GNU General Public License
 | |
|     along with this program; if not, write to the Free Software
 | |
|     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 | |
| 
 | |
| */
 | |
| 
 | |
| #include <linux/module.h>
 | |
| #include <linux/init.h>
 | |
| #include <linux/pci.h>
 | |
| #include <linux/interrupt.h>
 | |
| #include <linux/videodev2.h>
 | |
| #include <asm/page.h>
 | |
| #include <asm/pgtable.h>
 | |
| 
 | |
| #include "btcx-risc.h"
 | |
| 
 | |
| MODULE_DESCRIPTION("some code shared by bttv and cx88xx drivers");
 | |
| MODULE_AUTHOR("Gerd Knorr");
 | |
| MODULE_LICENSE("GPL");
 | |
| 
 | |
| static unsigned int debug;
 | |
| module_param(debug, int, 0644);
 | |
| MODULE_PARM_DESC(debug,"debug messages, default is 0 (no)");
 | |
| 
 | |
| /* ---------------------------------------------------------- */
 | |
| /* allocate/free risc memory                                  */
 | |
| 
 | |
| static int memcnt;
 | |
| 
 | |
| void btcx_riscmem_free(struct pci_dev *pci,
 | |
| 		       struct btcx_riscmem *risc)
 | |
| {
 | |
| 	if (NULL == risc->cpu)
 | |
| 		return;
 | |
| 	if (debug) {
 | |
| 		memcnt--;
 | |
| 		printk("btcx: riscmem free [%d] dma=%lx\n",
 | |
| 		       memcnt, (unsigned long)risc->dma);
 | |
| 	}
 | |
| 	pci_free_consistent(pci, risc->size, risc->cpu, risc->dma);
 | |
| 	memset(risc,0,sizeof(*risc));
 | |
| }
 | |
| 
 | |
| int btcx_riscmem_alloc(struct pci_dev *pci,
 | |
| 		       struct btcx_riscmem *risc,
 | |
| 		       unsigned int size)
 | |
| {
 | |
| 	__le32 *cpu;
 | |
| 	dma_addr_t dma = 0;
 | |
| 
 | |
| 	if (NULL != risc->cpu && risc->size < size)
 | |
| 		btcx_riscmem_free(pci,risc);
 | |
| 	if (NULL == risc->cpu) {
 | |
| 		cpu = pci_alloc_consistent(pci, size, &dma);
 | |
| 		if (NULL == cpu)
 | |
| 			return -ENOMEM;
 | |
| 		risc->cpu  = cpu;
 | |
| 		risc->dma  = dma;
 | |
| 		risc->size = size;
 | |
| 		if (debug) {
 | |
| 			memcnt++;
 | |
| 			printk("btcx: riscmem alloc [%d] dma=%lx cpu=%p size=%d\n",
 | |
| 			       memcnt, (unsigned long)dma, cpu, size);
 | |
| 		}
 | |
| 	}
 | |
| 	memset(risc->cpu,0,risc->size);
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| /* ---------------------------------------------------------- */
 | |
| /* screen overlay helpers                                     */
 | |
| 
 | |
| int
 | |
| btcx_screen_clips(int swidth, int sheight, struct v4l2_rect *win,
 | |
| 		  struct v4l2_clip *clips, unsigned int n)
 | |
| {
 | |
| 	if (win->left < 0) {
 | |
| 		/* left */
 | |
| 		clips[n].c.left = 0;
 | |
| 		clips[n].c.top = 0;
 | |
| 		clips[n].c.width  = -win->left;
 | |
| 		clips[n].c.height = win->height;
 | |
| 		n++;
 | |
| 	}
 | |
| 	if (win->left + win->width > swidth) {
 | |
| 		/* right */
 | |
| 		clips[n].c.left   = swidth - win->left;
 | |
| 		clips[n].c.top    = 0;
 | |
| 		clips[n].c.width  = win->width - clips[n].c.left;
 | |
| 		clips[n].c.height = win->height;
 | |
| 		n++;
 | |
| 	}
 | |
| 	if (win->top < 0) {
 | |
| 		/* top */
 | |
| 		clips[n].c.left = 0;
 | |
| 		clips[n].c.top = 0;
 | |
| 		clips[n].c.width  = win->width;
 | |
| 		clips[n].c.height = -win->top;
 | |
| 		n++;
 | |
| 	}
 | |
| 	if (win->top + win->height > sheight) {
 | |
| 		/* bottom */
 | |
| 		clips[n].c.left = 0;
 | |
| 		clips[n].c.top = sheight - win->top;
 | |
| 		clips[n].c.width  = win->width;
 | |
| 		clips[n].c.height = win->height - clips[n].c.top;
 | |
| 		n++;
 | |
| 	}
 | |
| 	return n;
 | |
| }
 | |
| 
 | |
| int
 | |
| btcx_align(struct v4l2_rect *win, struct v4l2_clip *clips, unsigned int n, int mask)
 | |
| {
 | |
| 	s32 nx,nw,dx;
 | |
| 	unsigned int i;
 | |
| 
 | |
| 	/* fixup window */
 | |
| 	nx = (win->left + mask) & ~mask;
 | |
| 	nw = (win->width) & ~mask;
 | |
| 	if (nx + nw > win->left + win->width)
 | |
| 		nw -= mask+1;
 | |
| 	dx = nx - win->left;
 | |
| 	win->left  = nx;
 | |
| 	win->width = nw;
 | |
| 	if (debug)
 | |
| 		printk(KERN_DEBUG "btcx: window align %dx%d+%d+%d [dx=%d]\n",
 | |
| 		       win->width, win->height, win->left, win->top, dx);
 | |
| 
 | |
| 	/* fixup clips */
 | |
| 	for (i = 0; i < n; i++) {
 | |
| 		nx = (clips[i].c.left-dx) & ~mask;
 | |
| 		nw = (clips[i].c.width) & ~mask;
 | |
| 		if (nx + nw < clips[i].c.left-dx + clips[i].c.width)
 | |
| 			nw += mask+1;
 | |
| 		clips[i].c.left  = nx;
 | |
| 		clips[i].c.width = nw;
 | |
| 		if (debug)
 | |
| 			printk(KERN_DEBUG "btcx:   clip align %dx%d+%d+%d\n",
 | |
| 			       clips[i].c.width, clips[i].c.height,
 | |
| 			       clips[i].c.left, clips[i].c.top);
 | |
| 	}
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| void
 | |
| btcx_sort_clips(struct v4l2_clip *clips, unsigned int nclips)
 | |
| {
 | |
| 	struct v4l2_clip swap;
 | |
| 	int i,j,n;
 | |
| 
 | |
| 	if (nclips < 2)
 | |
| 		return;
 | |
| 	for (i = nclips-2; i >= 0; i--) {
 | |
| 		for (n = 0, j = 0; j <= i; j++) {
 | |
| 			if (clips[j].c.left > clips[j+1].c.left) {
 | |
| 				swap = clips[j];
 | |
| 				clips[j] = clips[j+1];
 | |
| 				clips[j+1] = swap;
 | |
| 				n++;
 | |
| 			}
 | |
| 		}
 | |
| 		if (0 == n)
 | |
| 			break;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void
 | |
| btcx_calc_skips(int line, int width, int *maxy,
 | |
| 		struct btcx_skiplist *skips, unsigned int *nskips,
 | |
| 		const struct v4l2_clip *clips, unsigned int nclips)
 | |
| {
 | |
| 	unsigned int clip,skip;
 | |
| 	int end, maxline;
 | |
| 
 | |
| 	skip=0;
 | |
| 	maxline = 9999;
 | |
| 	for (clip = 0; clip < nclips; clip++) {
 | |
| 
 | |
| 		/* sanity checks */
 | |
| 		if (clips[clip].c.left + clips[clip].c.width <= 0)
 | |
| 			continue;
 | |
| 		if (clips[clip].c.left > (signed)width)
 | |
| 			break;
 | |
| 
 | |
| 		/* vertical range */
 | |
| 		if (line > clips[clip].c.top+clips[clip].c.height-1)
 | |
| 			continue;
 | |
| 		if (line < clips[clip].c.top) {
 | |
| 			if (maxline > clips[clip].c.top-1)
 | |
| 				maxline = clips[clip].c.top-1;
 | |
| 			continue;
 | |
| 		}
 | |
| 		if (maxline > clips[clip].c.top+clips[clip].c.height-1)
 | |
| 			maxline = clips[clip].c.top+clips[clip].c.height-1;
 | |
| 
 | |
| 		/* horizontal range */
 | |
| 		if (0 == skip || clips[clip].c.left > skips[skip-1].end) {
 | |
| 			/* new one */
 | |
| 			skips[skip].start = clips[clip].c.left;
 | |
| 			if (skips[skip].start < 0)
 | |
| 				skips[skip].start = 0;
 | |
| 			skips[skip].end = clips[clip].c.left + clips[clip].c.width;
 | |
| 			if (skips[skip].end > width)
 | |
| 				skips[skip].end = width;
 | |
| 			skip++;
 | |
| 		} else {
 | |
| 			/* overlaps -- expand last one */
 | |
| 			end = clips[clip].c.left + clips[clip].c.width;
 | |
| 			if (skips[skip-1].end < end)
 | |
| 				skips[skip-1].end = end;
 | |
| 			if (skips[skip-1].end > width)
 | |
| 				skips[skip-1].end = width;
 | |
| 		}
 | |
| 	}
 | |
| 	*nskips = skip;
 | |
| 	*maxy = maxline;
 | |
| 
 | |
| 	if (debug) {
 | |
| 		printk(KERN_DEBUG "btcx: skips line %d-%d:",line,maxline);
 | |
| 		for (skip = 0; skip < *nskips; skip++) {
 | |
| 			printk(" %d-%d",skips[skip].start,skips[skip].end);
 | |
| 		}
 | |
| 		printk("\n");
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /* ---------------------------------------------------------- */
 | |
| 
 | |
| EXPORT_SYMBOL(btcx_riscmem_alloc);
 | |
| EXPORT_SYMBOL(btcx_riscmem_free);
 | |
| 
 | |
| EXPORT_SYMBOL(btcx_screen_clips);
 | |
| EXPORT_SYMBOL(btcx_align);
 | |
| EXPORT_SYMBOL(btcx_sort_clips);
 | |
| EXPORT_SYMBOL(btcx_calc_skips);
 | |
| 
 | |
| /*
 | |
|  * Local variables:
 | |
|  * c-basic-offset: 8
 | |
|  * End:
 | |
|  */
 |