2005-04-17 02:20:36 +04:00
/*
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 0213 9 , 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 " ) ;
2006-01-13 19:10:19 +03:00
static unsigned int debug ;
2005-04-17 02:20:36 +04:00
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 )
{
2008-05-21 07:31:51 +04:00
__le32 * cpu ;
2008-08-23 00:01:45 +04:00
dma_addr_t dma = 0 ;
2005-04-17 02:20:36 +04:00
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
2008-09-04 00:11:54 +04:00
btcx_calc_skips ( int line , int width , int * maxy ,
2005-04-17 02:20:36 +04:00
struct btcx_skiplist * skips , unsigned int * nskips ,
const struct v4l2_clip * clips , unsigned int nclips )
{
unsigned int clip , skip ;
2008-09-04 00:11:54 +04:00
int end , maxline ;
2005-04-17 02:20:36 +04:00
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 :
*/