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 .
*/
2016-10-14 12:33:25 +03:00
# define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
2005-04-17 02:20:36 +04:00
# 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"
2014-12-12 16:27:56 +03:00
static unsigned int btcx_debug ;
module_param ( btcx_debug , int , 0644 ) ;
MODULE_PARM_DESC ( btcx_debug , " debug messages, default is 0 (no) " ) ;
2005-04-17 02:20:36 +04:00
2016-10-14 12:33:25 +03:00
# define dprintk(fmt, arg...) do { \
if ( btcx_debug ) \
printk ( KERN_DEBUG pr_fmt ( " %s: " fmt ) , \
__func__ , # # arg ) ; \
} while ( 0 )
2005-04-17 02:20:36 +04:00
/* ---------------------------------------------------------- */
/* allocate/free risc memory */
static int memcnt ;
void btcx_riscmem_free ( struct pci_dev * pci ,
struct btcx_riscmem * risc )
{
if ( NULL = = risc - > cpu )
return ;
2016-10-14 12:33:25 +03:00
memcnt - - ;
dprintk ( " btcx: riscmem free [%d] dma=%lx \n " ,
memcnt , ( unsigned long ) risc - > dma ) ;
2005-04-17 02:20:36 +04:00
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 ;
2016-10-14 12:33:25 +03:00
memcnt + + ;
dprintk ( " btcx: riscmem alloc [%d] dma=%lx cpu=%p size=%d \n " ,
memcnt , ( unsigned long ) dma , cpu , size ) ;
2005-04-17 02:20:36 +04:00
}
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 ;
2016-10-14 12:33:25 +03:00
dprintk ( " btcx: window align %dx%d+%d+%d [dx=%d] \n " ,
win - > width , win - > height , win - > left , win - > top , dx ) ;
2005-04-17 02:20:36 +04:00
/* 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 ;
2016-10-14 12:33:25 +03:00
dprintk ( " btcx: clip align %dx%d+%d+%d \n " ,
clips [ i ] . c . width , clips [ i ] . c . height ,
clips [ i ] . c . left , clips [ i ] . c . top ) ;
2005-04-17 02:20:36 +04:00
}
return 0 ;
}
void
btcx_sort_clips ( struct v4l2_clip * clips , unsigned int nclips )
{
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 ) {
2015-06-10 19:33:45 +03:00
swap ( clips [ j ] , clips [ j + 1 ] ) ;
2005-04-17 02:20:36 +04:00
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 ;
2014-12-12 16:27:56 +03:00
if ( btcx_debug ) {
2016-10-14 12:33:25 +03:00
dprintk ( " btcx: skips line %d-%d: " , line , maxline ) ;
2005-04-17 02:20:36 +04:00
for ( skip = 0 ; skip < * nskips ; skip + + ) {
2016-10-14 12:33:25 +03:00
pr_cont ( " %d-%d " , skips [ skip ] . start , skips [ skip ] . end ) ;
2005-04-17 02:20:36 +04:00
}
2016-10-14 12:33:25 +03:00
pr_cont ( " \n " ) ;
2005-04-17 02:20:36 +04:00
}
}