summaryrefslogtreecommitdiffstats
path: root/drivers/char/bttv.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-01-04 16:03:48 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-01-04 16:03:48 +0000
commit78c388aed2b7184182c08428db1de6c872d815f5 (patch)
tree4b2003b1b4ceb241a17faa995da8dd1004bb8e45 /drivers/char/bttv.c
parenteb7a5bf93aaa4be1d7c6181100ab7639e74d67f7 (diff)
Merge with Linux 2.1.131 and more MIPS goodies.
(Did I mention that CVS is buggy ...)
Diffstat (limited to 'drivers/char/bttv.c')
-rw-r--r--drivers/char/bttv.c625
1 files changed, 306 insertions, 319 deletions
diff --git a/drivers/char/bttv.c b/drivers/char/bttv.c
index 19c30d6fd..de2d25b0e 100644
--- a/drivers/char/bttv.c
+++ b/drivers/char/bttv.c
@@ -28,11 +28,10 @@
composite source from a satellite tuner can deliver different norms
depending on tuned channel
* mmap VBI data?
- * use new PCI routines
* fix RAW Composite grabbing for NTSC
- * allow for different VDELAY in RAW grabbing?
+ * fix VBI reading double frames when grabbing is active
+ * allow for different VDELAYs
* extra modules for tda9850, tda8425, any volunteers???
- * support 15bpp
*/
#include <linux/module.h>
@@ -80,12 +79,20 @@ static void bt848_set_risc_jmps(struct bttv *btv);
static unsigned int vidmem=0; /* manually set video mem address */
static int triton1=0;
+#ifndef USE_PLL
+/* 0=no pll, 1=28MHz, 2=34MHz */
+#define USE_PLL 0
+#endif
+#ifndef CARD_DEFAULT
+/* card type (see bttv.h) 0=autodetect */
+#define CARD_DEFAULT 0
+#endif
static unsigned int remap[BTTV_MAX]; /* remap Bt848 */
static unsigned int radio[BTTV_MAX];
-static unsigned int card[BTTV_MAX] = { 0, 0,
- 0, 0 };
-static unsigned int pll[BTTV_MAX] = { 0, 0, 0, 0 };
+static unsigned int card[BTTV_MAX] = { CARD_DEFAULT, CARD_DEFAULT,
+ CARD_DEFAULT, CARD_DEFAULT };
+static unsigned int pll[BTTV_MAX] = { USE_PLL, USE_PLL, USE_PLL, USE_PLL };
static int bttv_num; /* number of Bt848s in use */
static struct bttv bttvs[BTTV_MAX];
@@ -96,9 +103,8 @@ static struct bttv bttvs[BTTV_MAX];
{ btwrite((CTRL<<1)|(DATA), BT848_I2C); udelay(I2C_DELAY); }
#define I2C_GET() (btread(BT848_I2C)&1)
-#define AUDIO_MUTE_DELAY 10000
-#define FREQ_CHANGE_DELAY 20000
#define EEPROM_WRITE_DELAY 20000
+#define BURSTOFFSET 76
/*******************************/
/* Memory management functions */
@@ -344,7 +350,6 @@ static void writeee(struct i2c_bus *bus, unsigned char *eedata)
void attach_inform(struct i2c_bus *bus, int id)
{
struct bttv *btv = (struct bttv*)bus->data;
- int tunertype;
switch (id)
{
@@ -354,12 +359,9 @@ void attach_inform(struct i2c_bus *bus, int id)
case I2C_DRIVERID_TUNER:
btv->have_tuner = 1;
if (btv->tuner_type != -1)
- {
- tunertype=btv->tuner_type;
i2c_control_device(&(btv->i2c),
I2C_DRIVERID_TUNER,
- TUNER_SET_TYPE,&tunertype);
- }
+ TUNER_SET_TYPE,&btv->tuner_type);
break;
}
}
@@ -401,7 +403,8 @@ static struct i2c_bus bttv_i2c_bus_template =
struct tvcard
{
- int inputs;
+ int video_inputs;
+ int audio_inputs;
int tuner;
int svhs;
u32 gpiomask;
@@ -413,29 +416,37 @@ struct tvcard
static struct tvcard tvcards[] =
{
/* default */
- { 3, 0, 2, 0, { 2, 3, 1, 1}, { 0, 0, 0, 0, 0}},
+ { 3, 1, 0, 2, 0, { 2, 3, 1, 1}, { 0, 0, 0, 0, 0}},
/* MIRO */
- { 4, 0, 2,15, { 2, 3, 1, 1}, { 2, 0, 0, 0,10}},
+ { 4, 1, 0, 2,15, { 2, 3, 1, 1}, { 2, 0, 0, 0,10}},
/* Hauppauge */
- { 3, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4}},
+ { 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4}},
/* STB */
- { 3, 0, 2, 7, { 2, 3, 1, 1}, { 4, 0, 2, 3, 1}},
+ { 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 4, 0, 2, 3, 1}},
/* Intel??? */
- { 3, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4}},
+ { 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4}},
/* Diamond DTV2000 */
- { 3, 0, 2, 3, { 2, 3, 1, 1}, { 0, 1, 0, 1, 3}},
+ { 3, 1, 0, 2, 3, { 2, 3, 1, 1}, { 0, 1, 0, 1, 3}},
/* AVerMedia TVPhone */
- { 3, 0, 3,15, { 2, 3, 1, 1}, {12, 0,11,11, 0}},
+ { 3, 1, 0, 3,15, { 2, 3, 1, 1}, {12, 0,11,11, 0}},
/* Matrix Vision MV-Delta */
- { 5,-1, 3, 0, { 2, 3, 1, 0, 0}},
+ { 5, 1, -1, 3, 0, { 2, 3, 1, 0, 0}},
/* Fly Video II */
- { 3, 0, 2, 0xc00, { 2, 3, 1, 1},
+ { 3, 1, 0, 2, 0xc00, { 2, 3, 1, 1},
{0, 0xc00, 0x800, 0x400, 0xc00, 0}},
/* TurboTV */
- { 3, 0, 2, 3, { 2, 3, 1, 1}, { 1, 1, 2, 3, 0}},
- /* Newer Hauppauge */
- { 2, 0, 2, 1, { 2, 0, 0, 0}, {0, 1, 2, 3, 4}},
-
+ { 3, 1, 0, 2, 3, { 2, 3, 1, 1}, { 1, 1, 2, 3, 0}},
+ /* Newer Hauppauge (bt878) */
+ { 3, 1, 0, 2, 7, { 2, 0, 1, 1}, { 0, 1, 2, 3, 4}},
+ /* MIRO PCTV pro */
+ { 3, 1, 0, 2, 65551, { 2, 3, 1, 1}, {1,65537, 0, 0,10}},
+ /* ADS Technologies Channel Surfer TV (and maybe TV+FM) */
+ {
+ 3, 4, 0, 2, 0x0F,
+ { 0x02, 0x03, 0x01, 0x01},
+ { 0x0D, 0x0E, 0x0B, 0x07, 0x00, 0x00},
+ 0x00
+ },
};
#define TVCARDS (sizeof(tvcards)/sizeof(tvcard))
@@ -546,32 +557,36 @@ static void set_pll_freq(struct bttv *btv, unsigned int fin, unsigned int fout)
static int set_pll(struct bttv *btv)
{
int i;
- unsigned long tv;
+ unsigned long tv;
if (!btv->pll.pll_crystal)
- return 0;
- if ((btread(BT848_IFORM)&btv->pll.pll_crystal))
- {
- /* printk ("switching PLL off\n");*/
+ return 0;
+
+ if (btv->pll.pll_ifreq == btv->pll.pll_ofreq) {
+ /* no PLL needed */
+ if (btv->pll.pll_current == 0) {
+ /* printk ("bttv%d: PLL: is off\n",btv->nr); */
+ return 0;
+ }
+ printk ("bttv%d: PLL: switching off\n",btv->nr);
btwrite(0x00,BT848_TGCTRL);
btwrite(0x00,BT848_PLL_XCI);
- btv->pll.pll_crystal&=~2;
+ btv->pll.pll_current = 0;
return 0;
}
-
- /* do not set pll again if already active */
- if (btv->pll.pll_crystal&2)
+
+ if (btv->pll.pll_ofreq == btv->pll.pll_current) {
+ /* printk("bttv%d: PLL: no change required\n",btv->nr); */
return 1;
+ }
- /* printk ("setting PLL for PAL/SECAM\n");*/
+ printk("bttv%d: PLL: %d => %d ... ",btv->nr,
+ btv->pll.pll_ifreq, btv->pll.pll_ofreq);
set_pll_freq(btv, btv->pll.pll_ifreq, btv->pll.pll_ofreq);
- /*
- * Let other people run while the PLL stabilizes
- */
-
- tv=jiffies+HZ/10; /* .1 seconds */
+ /* Let other people run while the PLL stabilizes */
+ tv=jiffies+HZ/10; /* .1 seconds */
do
{
schedule();
@@ -585,11 +600,14 @@ static int set_pll(struct bttv *btv)
else
{
btwrite(0x08,BT848_TGCTRL);
- btv->pll.pll_crystal|=2;
- return 1;
+ btv->pll.pll_current = btv->pll.pll_ofreq;
+ printk("ok\n");
+ return 1;
}
- udelay(10000);
+ mdelay(10);
}
+ btv->pll.pll_current = 0;
+ printk("oops\n");
return -1;
}
@@ -602,7 +620,7 @@ static void bt848_muxsel(struct bttv *btv, unsigned int input)
btand(~(3<<5), BT848_IFORM);
mdelay(10);
- input %= tvcards[btv->type].inputs;
+ input %= tvcards[btv->type].video_inputs;
if (input==tvcards[btv->type].svhs)
{
btor(BT848_CONTROL_COMP, BT848_E_CONTROL);
@@ -623,8 +641,9 @@ static void bt848_muxsel(struct bttv *btv, unsigned int input)
#define VBIBUF_SIZE 65536
-/* Maximum sample number per VBI line is 2044, can NTSC deliver this?
+/* Maximum sample number per VBI line is 2044, NTSC delivers 1600
Note that we write 2048-aligned to keep alignment to memory pages
+ VBI_RISC is written so that it applies to either 2044 or 1600
*/
#define VBI_SPL 2044
@@ -684,7 +703,7 @@ int palette2fmt[] = {
BT848_COLOR_FMT_YCrCb422,
BT848_COLOR_FMT_YCrCb411,
};
-#define PALETTEFMT_MAX 11
+#define PALETTEFMT_MAX (sizeof(palette2fmt)/sizeof(int))
static int make_rawrisctab(struct bttv *btv, unsigned int *ro,
unsigned int *re, unsigned int *vbuf)
@@ -783,199 +802,102 @@ static int make_vrisctab(struct bttv *btv, unsigned int *ro,
return 0;
}
-/* does this really make a difference ???? */
-#define BURST_MAX 4096
-
-static inline void write_risc_segment(unsigned int **rp, unsigned long line_adr, unsigned int command,
- int *x, uint dx, uint bpp, uint width)
+static void clip_draw_rectangle(unsigned char *clipmap, int x, int y, int w, int h)
{
- unsigned int flags, len;
-
- if (!dx)
- return;
- len=dx*bpp;
-
-#ifdef LIMIT_DMA
- if (command==BT848_RISC_WRITEC)
- {
- unsigned int dx2=BURST_MAX/bpp;
- while (len>BURST_MAX)
- {
- write_risc_segment(rp, line_adr, command,
- &x,dx2, bpp, width);
- dx-=dx2;
- len=dx*bpp;
- }
- }
-#endif
-
- /* mask upper 8 bits for 24+8 bit overlay modes */
- flags = ((bpp==4) ? BT848_RISC_BYTE3 : 0);
-
- if (*x==0)
- {
- if (command==BT848_RISC_SKIP)
- {
- if (dx<width)
- {
- flags|=BT848_RISC_BYTE_ALL;
- command=BT848_RISC_WRITE;
- }
- }
- else
- if (command==BT848_RISC_WRITEC)
- command=BT848_RISC_WRITE;
- flags|=BT848_RISC_SOL;
- }
- if (*x+dx==width)
- flags|=BT848_RISC_EOL;
- *((*rp)++)=command|flags|len;
- if (command==BT848_RISC_WRITE)
- *((*rp)++)=line_adr+*x*bpp;
- *x+=dx;
+ int i, j;
+ /* bitmap is fixed width, 128 bytes (1024 pixels represented) */
+ if (x < 0 || y < 0 || w < 0 || h < 0) /* catch bad clips */
+ return;
+ /* out of range data should just fall through */
+ for (i = y; i < y + h && i < 625; i++)
+ for (j = x; j < x + w && j < 1024; j++)
+ clipmap[(i<<7)+(j>>3)] |= (1<<(j&7));
}
static void make_clip_tab(struct bttv *btv, struct video_clip *cr, int ncr)
{
- int i,t;
- int yy, y, x, dx;
- struct video_clip first, *cur, *cur2, *nx, first2, *prev, *nx2;
- int bpp, bpl, width, height, inter;
- unsigned int **rp,*ro,*re;
+ int i, line, x, y, bpl, width, height, inter;
+ unsigned int bpp, dx, sx, **rp, *ro, *re, flags, len;
unsigned long adr;
- int cx,cx2,cy,cy2;
+ unsigned char *clipmap, cbit, lastbit, outofmem;
inter=(btv->win.interlace&1)^1;
bpp=btv->win.bpp;
+ if (bpp==15) /* handle 15bpp as 16bpp in calculations */
+ bpp++;
bpl=btv->win.bpl;
ro=btv->risc_odd;
re=btv->risc_even;
- width=btv->win.width;
- height=btv->win.height;
+ if((width=btv->win.width)>1023)
+ width = 1023; /* sanity check */
+ if((height=btv->win.height)>625)
+ height = 625; /* sanity check */
adr=btv->win.vidadr+btv->win.x*bpp+btv->win.y*bpl;
-
- /* clip clipping rects against viewing window AND screen
+ if ((clipmap=vmalloc(VIDEO_CLIPMAP_SIZE))==NULL) {
+ /* can't clip, don't generate any risc code */
+ *(ro++)=BT848_RISC_JUMP;
+ *(ro++)=btv->bus_vbi_even;
+ *(re++)=BT848_RISC_JUMP;
+ *(re++)=btv->bus_vbi_odd;
+ }
+ if (ncr < 0) { /* bitmap was pased */
+ memcpy(clipmap, (unsigned char *)cr, VIDEO_CLIPMAP_SIZE);
+ } else { /* convert rectangular clips to a bitmap */
+ memset(clipmap, 0, VIDEO_CLIPMAP_SIZE); /* clear map */
+ for (i=0; i<ncr; i++)
+ clip_draw_rectangle(clipmap, cr[i].x, cr[i].y,
+ cr[i].width, cr[i].height);
+ }
+ /* clip against viewing window AND screen
so we do not have to rely on the user program
*/
- cx=(btv->win.x<0) ? (-btv->win.x) : 0;
- cy=(btv->win.y<0) ? (-btv->win.y) : 0;
- cx2=(btv->win.x+width>btv->win.swidth) ?
- (btv->win.swidth-btv->win.x) : width;
- cy2=(btv->win.y+height>btv->win.sheight) ?
- (btv->win.sheight-btv->win.y) : height;
- first.next=NULL;
- for (i=0; i<ncr; i++)
- {
- if ((t=cy-cr[i].y)>0)
- {
- if (cr[i].height<=t)
- continue;
- cr[i].height-=t;
- cr[i].y=cy;
- }
- if ((t=cy2-cr[i].y)<cr[i].height)
- {
- if (t<=0)
- continue;
- cr[i].height=t;
- }
- if ((t=cx-cr[i].x)>0)
- {
- if (cr[i].width<=t)
- continue;
- cr[i].width-=t;
- cr[i].x=cx;
- }
- if ((t=cx2-cr[i].x)<cr[i].width)
- {
- if (t<=0)
- continue;
- cr[i].width=t;
- }
- cur=&first;
- while ((nx=cur->next) && (cr[i].y > cur->next->y))
- cur=nx;
- cur->next=&(cr[i]);
- cr[i].next=nx;
- }
- first2.next=NULL;
+ clip_draw_rectangle(clipmap,(btv->win.x+width>btv->win.swidth) ?
+ (btv->win.swidth-btv->win.x) : width, 0, 1024, 768);
+ clip_draw_rectangle(clipmap,0,(btv->win.y+height>btv->win.sheight) ?
+ (btv->win.sheight-btv->win.y) : height,1024,768);
+ if (btv->win.x<0)
+ clip_draw_rectangle(clipmap, 0, 0, -(btv->win.x), 768);
+ if (btv->win.y<0)
+ clip_draw_rectangle(clipmap, 0, 0, 1024, -(btv->win.y));
*(ro++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(ro++)=0;
*(re++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(re++)=0;
- /* loop through all lines */
- for (yy=0; yy<(height<<inter); yy++)
+ /* translate bitmap to risc code */
+ for (line=outofmem=0; line < (height<<inter) && !outofmem; line++)
{
- y=yy>>inter;
- rp= (yy&1) ? &re : &ro;
-
- /* remove rects with y2 > y */
- if ((cur=first2.next))
- {
- prev=&first2;
- do
- {
- if (cur->y+cur->height <= y)
- prev->next=cur->next;
- else
- prev=cur;
- }
- while ((cur=cur->next));
- }
-
- /* add rect to second (x-sorted) list if rect.y == y */
- if ((cur=first.next))
- {
- while ((cur) && (cur->y == y))
- {
- first.next=cur->next;
- cur2=&first2;
- while ((nx2=cur2->next) && (cur->x > cur2->next->x))
- cur2=nx2;
- cur2->next=cur;
- cur->next=nx2;
- cur=first.next;
- }
- }
- x=0;
- if ((btv->win.y+y<=0)||(btv->win.y+y>=btv->win.sheight))
- write_risc_segment(rp, adr, BT848_RISC_SKIP, &x,
- width, bpp, width);
- else
- {
- dx=cx;
- for (cur2=first2.next; cur2; cur2=cur2->next)
- {
- if (x+dx < cur2->x)
- {
- write_risc_segment(rp, adr, BT848_RISC_SKIP,
- &x, dx, bpp, width);
- dx=cur2->x-x;
- write_risc_segment(rp, adr, BT848_RISC_WRITEC,
- &x, dx, bpp, width);
- dx=cur2->width;
- }
- else if (x+dx < cur2->x+cur2->width)
- dx=cur2->x+cur2->width-x;
- }
- if (cx2<width)
- {
- write_risc_segment(rp, adr, BT848_RISC_SKIP,
- &x, dx, bpp, width);
- write_risc_segment(rp, adr, BT848_RISC_WRITEC,
- &x, cx2-x, bpp, width);
- dx=width-x;
- }
- write_risc_segment(rp, adr, BT848_RISC_SKIP,
- &x, dx, bpp, width);
- write_risc_segment(rp, adr, BT848_RISC_WRITEC,
- &x, width-x, bpp, width);
- }
- if ((!inter)||(yy&1))
+ y = line>>inter;
+ rp= (line&1) ? &re : &ro;
+ lastbit=(clipmap[y<<7]&1);
+ for(x=dx=1,sx=0; x<=width && !outofmem; x++) {
+ cbit = (clipmap[(y<<7)+(x>>3)] & (1<<(x&7)));
+ if (x < width && !lastbit == !cbit)
+ dx++;
+ else { /* generate the dma controller code */
+ len = dx * bpp;
+ flags = ((bpp==4) ? BT848_RISC_BYTE3 : 0);
+ flags |= ((!sx) ? BT848_RISC_SOL : 0);
+ flags |= ((sx + dx == width) ? BT848_RISC_EOL : 0);
+ if (!lastbit) {
+ *((*rp)++)=BT848_RISC_WRITE|flags|len;
+ *((*rp)++)=adr + bpp * sx;
+ } else
+ *((*rp)++)=BT848_RISC_SKIP|flags|len;
+ lastbit=cbit;
+ sx += dx;
+ dx = 1;
+ if (ro - btv->risc_odd > RISCMEM_LEN/2 - 16)
+ outofmem++;
+ if (re - btv->risc_even > RISCMEM_LEN/2 - 16)
+ outofmem++;
+ }
+ }
+ if ((!inter)||(line&1))
adr+=bpl;
}
-
- *(ro++)=BT848_RISC_JUMP;
+ vfree(clipmap);
+ /* outofmem flag relies on the following code to discard extra data */
+ *(ro++)=BT848_RISC_JUMP;
*(ro++)=btv->bus_vbi_even;
*(re++)=BT848_RISC_JUMP;
*(re++)=btv->bus_vbi_odd;
@@ -999,44 +921,51 @@ struct tvnorm
u8 adelay, bdelay, iform;
u32 scaledtwidth;
u16 hdelayx1, hactivex1;
- u16 vdelay, fporch;
+ u16 vdelay;
+ u8 vbipack;
};
static struct tvnorm tvnorms[] = {
/* PAL-BDGHI */
- /* max. active video is actually 922, but 924 is divisible by 4 and 3! */
+ /* max pal/secam is actually 922, but 924 is divisible by 4 and 3! */
+ /* actually, max active PAL with HSCALE=0 is 948, NTSC is 768 - nil */
{ 35468950,
924, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
- 1135, 186, 924, 0x20},
+ 1135, 178, 924, 0x20, 255},
/*
{ 35468950,
768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
- 944, 186, 922, 0x20},
+ 944, 178, 922, 0x20, 255},
*/
/* NTSC */
{ 28636363,
+ 768, 480, 910, 0x68, 0x5d, (BT848_IFORM_NTSC|BT848_IFORM_XT0),
+ 910, 128, 754, 0x1a, 144},
+/*
+ { 28636363,
640, 480, 910, 0x68, 0x5d, (BT848_IFORM_NTSC|BT848_IFORM_XT0),
- 780, 135, 754, 0x1a},
- /* SECAM */
- { 28636363,
- 640, 480, 910, 0x68, 0x5d, (BT848_IFORM_PAL_M|BT848_IFORM_XT0),
- 780, 135, 754, 0x16},
+ 780, 122, 754, 0x1a, 144},
+*/
+ /* SECAM - phase means nothing in SECAM, bdelay is useless */
+ { 35468950,
+ 924, 576,1135, 0x7f, 0xb0, (BT848_IFORM_SECAM|BT848_IFORM_XT1),
+ 1135, 178, 924, 0x20, 255},
/* PAL-M */
{ 28636363,
640, 480, 910, 0x68, 0x5d, (BT848_IFORM_PAL_M|BT848_IFORM_XT0),
- 780, 135, 754, 0x16},
+ 780, 122, 754, 0x1a, 144},
/* PAL-N */
{ 35468950,
768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_N|BT848_IFORM_XT1),
- 944, 186, 922, 0x20},
+ 944, 178, 922, 0x20, 255},
/* PAL-NC */
{ 35468950,
768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_NC|BT848_IFORM_XT0),
- 944, 186, 922, 0x20},
+ 944, 178, 922, 0x20, 255},
/* NTSC-Japan */
{ 28636363,
640, 480, 910, 0x68, 0x5d, (BT848_IFORM_NTSC_J|BT848_IFORM_XT0),
- 780, 135, 754, 0x16},
+ 780, 122, 754, 0x1a, 144},
};
#define TVNORMS (sizeof(tvnorms)/sizeof(tvnorm))
@@ -1101,6 +1030,8 @@ static void bt848_set_geo(struct bttv *btv, u16 width, u16 height, u16 fmt)
btwrite(tvn->adelay, BT848_ADELAY);
btwrite(tvn->bdelay, BT848_BDELAY);
btaor(tvn->iform,~(BT848_IFORM_NORM|BT848_IFORM_XTBOTH), BT848_IFORM);
+ btwrite(1, BT848_VBI_PACK_DEL);
+ btwrite(tvn->vbipack, BT848_VBI_PACK_SIZE);
set_pll(btv);
@@ -1172,11 +1103,7 @@ static void bt848_set_winsize(struct bttv *btv)
static void set_freq(struct bttv *btv, unsigned short freq)
{
int fixme = freq; /* XXX */
- int oldAudio = btv->audio;
- audio(btv, AUDIO_MUTE);
- udelay(AUDIO_MUTE_DELAY);
-
if (btv->radio)
{
if (btv->have_tuner)
@@ -1204,10 +1131,6 @@ static void set_freq(struct bttv *btv, unsigned short freq)
}
}
- if (!(oldAudio & AUDIO_MUTE)) {
- udelay(FREQ_CHANGE_DELAY);
- audio(btv, AUDIO_UNMUTE);
- }
}
@@ -1243,10 +1166,15 @@ static int vgrab(struct bttv *btv, struct video_mmap *mp)
So, better check the total image size ...
*/
/*
- if(mp->height>576 || mp->width>768)
+ if(mp->height>576 || mp->width>768+BURSTOFFSET)
return -EINVAL;
*/
- if (mp->height*mp->width*fmtbppx2[mp->format&0x0f]/2>BTTV_MAX_FBUF)
+ if (mp->format >= PALETTEFMT_MAX)
+ return -EINVAL;
+ if (mp->height*mp->width*fmtbppx2[palette2fmt[mp->format]&0x0f]/2
+ > BTTV_MAX_FBUF)
+ return -EINVAL;
+ if (!palette2fmt[mp->format])
return -EINVAL;
/*
@@ -1264,31 +1192,28 @@ static int vgrab(struct bttv *btv, struct video_mmap *mp)
return -EAGAIN;*/
ro=btv->grisc+(((btv->grabcount++)&1) ? 4096 :0);
re=ro+2048;
- btv->gwidth=mp->width;
- btv->gheight=mp->height;
-
- if (mp->format > PALETTEFMT_MAX)
- return -EINVAL;
- btv->gfmt=palette2fmt[mp->format];
- if(btv->gfmt==0)
- return -EINVAL;
-
- make_vrisctab(btv, ro, re, vbuf, btv->gwidth, btv->gheight, btv->gfmt);
+ make_vrisctab(btv, ro, re, vbuf, mp->width, mp->height, palette2fmt[mp->format]);
/* bt848_set_risc_jmps(btv); */
- btor(3, BT848_CAP_CTL);
- btor(3, BT848_GPIO_DMA_CTL);
btv->frame_stat[mp->frame] = GBUFFER_GRABBING;
if (btv->grabbing) {
+ btv->gfmt_next=palette2fmt[mp->format];
+ btv->gwidth_next=mp->width;
+ btv->gheight_next=mp->height;
btv->gro_next=virt_to_bus(ro);
btv->gre_next=virt_to_bus(re);
btv->grf_next=mp->frame;
} else {
+ btv->gfmt=palette2fmt[mp->format];
+ btv->gwidth=mp->width;
+ btv->gheight=mp->height;
btv->gro=virt_to_bus(ro);
btv->gre=virt_to_bus(re);
btv->grf=mp->frame;
}
if (!(btv->grabbing++))
btv->risc_jmp[12]=BT848_RISC_JUMP|(0x8<<16)|BT848_RISC_IRQ;
+ btor(3, BT848_CAP_CTL);
+ btor(3, BT848_GPIO_DMA_CTL);
/* interruptible_sleep_on(&btv->capq); */
return 0;
}
@@ -1387,7 +1312,7 @@ static void bttv_close(struct video_device *dev)
struct bttv *btv=(struct bttv *)dev;
btv->user--;
- audio(btv, AUDIO_MUTE);
+ audio(btv, AUDIO_INTERN);
btv->cap&=~3;
bt848_set_risc_jmps(btv);
@@ -1466,8 +1391,8 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
VID_TYPE_CLIPPING|
VID_TYPE_FRAMERAM|
VID_TYPE_SCALES;
- b.channels = tvcards[btv->type].inputs;
- b.audios = tvcards[btv->type].inputs;
+ b.channels = tvcards[btv->type].video_inputs;
+ b.audios = tvcards[btv->type].audio_inputs;
b.maxwidth = 768;
b.maxheight = 576;
b.minwidth = 32;
@@ -1485,7 +1410,7 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
v.tuners=0;
v.type=VIDEO_TYPE_CAMERA;
v.norm = btv->win.norm;
- if (v.channel>=tvcards[btv->type].inputs)
+ if (v.channel>=tvcards[btv->type].video_inputs)
return -EINVAL;
if(v.channel==tvcards[btv->type].tuner)
{
@@ -1512,13 +1437,14 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
if(copy_from_user(&v, arg,sizeof(v)))
return -EFAULT;
- if (v.channel>tvcards[btv->type].inputs)
+ if (v.channel>=tvcards[btv->type].video_inputs)
return -EINVAL;
bt848_muxsel(btv, v.channel);
if(v.norm!=VIDEO_MODE_PAL&&v.norm!=VIDEO_MODE_NTSC
&&v.norm!=VIDEO_MODE_SECAM)
return -EOPNOTSUPP;
btv->win.norm = v.norm;
+ make_vbitab(btv);
bt848_set_winsize(btv);
btv->channel=v.channel;
return 0;
@@ -1604,15 +1530,20 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
case VIDIOCSWIN:
{
struct video_window vw;
- struct video_clip *vcp;
+ struct video_clip *vcp = NULL;
int on;
if(copy_from_user(&vw,arg,sizeof(vw)))
return -EFAULT;
- if(vw.flags)
+ if(vw.flags || vw.width < 16 || vw.height < 16) {
+ bt848_cap(btv,0);
return -EINVAL;
-
+ }
+ if (btv->win.bpp < 4) { /* adjust and align writes */
+ vw.x = (vw.x + 3) & ~3;
+ vw.width = (vw.width - 3) & ~3;
+ }
btv->win.x=vw.x;
btv->win.y=vw.y;
btv->win.width=vw.width;
@@ -1623,26 +1554,37 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
else
btv->win.interlace=0;
- on=(btv->cap&3)?1:0;
+ on=(btv->cap&3);
bt848_cap(btv,0);
bt848_set_winsize(btv);
- if(vw.clipcount>256)
- return -EDOM; /* Too many! */
-
/*
* Do any clips.
*/
-
- vcp=vmalloc(sizeof(struct video_clip)*(vw.clipcount+4));
- if(vcp==NULL)
- return -ENOMEM;
- if(vw.clipcount && copy_from_user(vcp,vw.clips,sizeof(struct video_clip)*vw.clipcount))
- return -EFAULT;
- make_clip_tab(btv,vcp, vw.clipcount);
- vfree(vcp);
- if(on && btv->win.vidadr!=0)
+ if(vw.clipcount<0) {
+ if((vcp=vmalloc(VIDEO_CLIPMAP_SIZE))==NULL)
+ return -ENOMEM;
+ if(copy_from_user(vcp, vw.clips,
+ VIDEO_CLIPMAP_SIZE)) {
+ vfree(vcp);
+ return -EFAULT;
+ }
+ } else if (vw.clipcount) {
+ if((vcp=vmalloc(sizeof(struct video_clip)*
+ (vw.clipcount))) == NULL)
+ return -ENOMEM;
+ if(copy_from_user(vcp,vw.clips,
+ sizeof(struct video_clip)*
+ vw.clipcount)) {
+ vfree(vcp);
+ return -EFAULT;
+ }
+ }
+ make_clip_tab(btv, vcp, vw.clipcount);
+ if (vw.clipcount != 0)
+ vfree(vcp);
+ if(on && btv->win.vidadr != 0)
bt848_cap(btv,1);
return 0;
}
@@ -1700,7 +1642,9 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
return -EPERM;
if(copy_from_user(&v, arg,sizeof(v)))
return -EFAULT;
- if(v.depth!=8 && v.depth!=15 && v.depth!=16 && v.depth!=24 && v.depth!=32)
+ if(v.depth!=8 && v.depth!=15 && v.depth!=16 &&
+ v.depth!=24 && v.depth!=32 && v.width > 16 &&
+ v.height > 16 && v.bytesperline > 16)
return -EINVAL;
btv->win.vidadr=(unsigned long)v.base;
btv->win.sheight=v.height;
@@ -1774,7 +1718,10 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
if(v.flags&VIDEO_AUDIO_MUTE)
audio(btv, AUDIO_MUTE);
/* One audio source per tuner */
- if(v.audio!=0)
+ /* if(v.audio!=0) */
+ /* Nope... I have three on my ADSTech TV card. The*/
+ /* ADSTech TV+FM prolly has 4 <rriggs@tesser.com> */
+ if(v.audio<0 || v.audio >= tvcards[btv->type].audio_inputs)
return -EINVAL;
bt848_muxsel(btv,v.audio);
if(!(v.flags&VIDEO_AUDIO_MUTE))
@@ -1801,9 +1748,8 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
case VIDIOCSYNC:
if(copy_from_user((void *)&i,arg,sizeof(int)))
return -EFAULT;
- if(i>1 || i<0)
- return -EINVAL;
-
+ if (i>1 || i<0)
+ return -EINVAL;
switch (btv->frame_stat[i]) {
case GBUFFER_UNUSED:
return -EINVAL;
@@ -1832,24 +1778,25 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
return -EFAULT;
break;
- case BTTV_FIELDNR:
+ case BTTV_FIELDNR:
if(copy_to_user((void *) arg, (void *) &btv->last_field,
sizeof(btv->last_field)))
return -EFAULT;
break;
-
- case BTTV_PLLSET: {
- struct bttv_pll_info p;
- if(!capable(CAP_SYS_ADMIN))
- return -EPERM;
- if(copy_from_user(&p , (void *) arg, sizeof(btv->pll)))
- return -EFAULT;
- btv->pll.pll_ifreq = p.pll_ifreq;
- btv->pll.pll_ofreq = p.pll_ofreq;
- btv->pll.pll_crystal = p.pll_crystal;
+ case BTTV_PLLSET:
+ {
+ struct bttv_pll_info p;
+ if(!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ if(copy_from_user(&p , (void *) arg, sizeof(btv->pll)))
+ return -EFAULT;
+ btv->pll.pll_ifreq = p.pll_ifreq;
+ btv->pll.pll_ofreq = p.pll_ofreq;
+ btv->pll.pll_crystal = p.pll_crystal;
break;
- }
+ }
+
case VIDIOCMCAPTURE:
{
struct video_mmap vm;
@@ -1893,7 +1840,27 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
return -EFAULT;
return 0;
}
-
+
+ case BTTV_BURST_ON:
+ {
+ tvnorms[0].scaledtwidth=1135-BURSTOFFSET-2;
+ tvnorms[0].hdelayx1=186-BURSTOFFSET;
+ return 0;
+ }
+
+ case BTTV_BURST_OFF:
+ {
+ tvnorms[0].scaledtwidth=1135;
+ tvnorms[0].hdelayx1=186;
+ return 0;
+ }
+
+ case BTTV_PICNR:
+ {
+ /* return picture */
+ return 0;
+ }
+
default:
return -ENOIOCTLCMD;
}
@@ -2182,6 +2149,8 @@ struct vidbases
};
static struct vidbases vbs[] = {
+ { PCI_VENDOR_ID_ALLIANCE, PCI_DEVICE_ID_ALLIANCE_AT3D,
+ "Alliance AT3D", PCI_BASE_ADDRESS_0},
{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_215CT222,
"ATI MACH64 CT", PCI_BASE_ADDRESS_0},
{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_210888GX,
@@ -2418,12 +2387,11 @@ static void idcard(int i)
{
btv->type=BTTV_MIRO;
- if (I2CRead(&(btv->i2c), I2C_HAUPEE)>=0)
- {
+ if (I2CRead(&(btv->i2c), I2C_HAUPEE)>=0) {
if(btv->id>849)
btv->type=BTTV_HAUPPAUGE878;
else
- btv->type=BTTV_HAUPPAUGE;
+ btv->type=BTTV_HAUPPAUGE;
}
else
if (I2CRead(&(btv->i2c), I2C_STBEE)>=0)
@@ -2443,8 +2411,8 @@ static void idcard(int i)
if (I2CRead(&(btv->i2c), I2C_TDA8425) >=0)
{
- btv->audio_chip = TDA8425;
- printk("bttv%d: audio chip: TDA8425\n", i);
+ btv->audio_chip = TDA8425;
+ printk("bttv%d: audio chip: TDA8425\n", i);
}
switch(btv->audio_chip)
@@ -2459,11 +2427,11 @@ static void idcard(int i)
/* How do I detect the tuner type for other cards but Miro ??? */
printk(KERN_INFO "bttv%d: model: ", btv->nr);
-
sprintf(btv->video_dev.name,"BT%d",btv->id);
switch (btv->type)
{
case BTTV_MIRO:
+ case BTTV_MIROPRO:
printk("MIRO\n");
if (btv->have_tuner)
{
@@ -2472,7 +2440,7 @@ static void idcard(int i)
I2C_DRIVERID_TUNER,
TUNER_SET_TYPE,&tunertype);
}
- strcat(btv->video_dev.name, "(Miro)");
+ strcat(btv->video_dev.name,"(Miro)");
break;
case BTTV_HAUPPAUGE:
case BTTV_HAUPPAUGE878:
@@ -2499,8 +2467,13 @@ static void idcard(int i)
printk("MATRIX-Vision\n");
strcat(btv->video_dev.name,"(MATRIX-Vision)");
break;
+ case BTTV_ADSTECH_TV:
+ printk("ADSTech Channel Surfer TV\n");
+ strcat(btv->video_dev.name,"(ADSTech Channel Surfer TV)");
+ btv->tuner_type=8;
+ break;
}
- audio(btv, AUDIO_MUTE);
+ audio(btv, AUDIO_INTERN);
}
@@ -2609,7 +2582,10 @@ static int init_bt848(int i)
btv->grabcount=0;
btv->grab=0;
btv->lastgrab=0;
- btv->field=btv->last_field=0;
+ btv->field=btv->last_field=0;
+ btv->video_dev.minor = -1;
+ btv->vbi_dev.minor = -1;
+ btv->radio_dev.minor = -1;
/* i2c */
memcpy(&(btv->i2c),&bttv_i2c_bus_template,sizeof(struct i2c_bus));
@@ -2650,11 +2626,6 @@ static int init_bt848(int i)
/* select direct input */
btwrite(0x00, BT848_GPIO_REG_INP);
-
- btwrite(0xff, BT848_VBI_PACK_SIZE);
- btwrite(1, BT848_VBI_PACK_DEL);
-
-
btwrite(BT848_IFORM_MUX1 | BT848_IFORM_XTAUTO | BT848_IFORM_PAL_BDGHI,
BT848_IFORM);
@@ -2759,6 +2730,7 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs)
if (astat&BT848_INT_VSYNC)
{
IDEBUG(printk ("bttv%d: IRQ_VSYNC\n", btv->nr));
+ btv->field++;
}
if (astat&BT848_INT_SCERR) {
IDEBUG(printk ("bttv%d: IRQ_SCERR\n", btv->nr));
@@ -2776,18 +2748,22 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs)
if (stat&(1<<28))
{
btv->vbip=0;
+ /* inc vbi frame count for detecting drops */
+ (*(u32 *)&(btv->vbibuf[VBIBUF_SIZE - 4]))++;
wake_up_interruptible(&btv->vbiq);
}
/* captured full frame */
if (stat&(2<<28))
{
- wake_up_interruptible(&btv->capq);
btv->last_field=btv->field;
btv->grab++;
btv->frame_stat[btv->grf] = GBUFFER_DONE;
if ((--btv->grabbing))
{
+ btv->gfmt = btv->gfmt_next;
+ btv->gwidth = btv->gwidth_next;
+ btv->gheight = btv->gheight_next;
btv->gro = btv->gro_next;
btv->gre = btv->gre_next;
btv->grf = btv->grf_next;
@@ -2844,10 +2820,12 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs)
}
if (astat&BT848_INT_HLOCK)
{
+#if 0
if ((dstat&BT848_DSTATUS_HLOC) || (btv->radio))
audio(btv, AUDIO_ON);
else
audio(btv, AUDIO_OFF);
+#endif
}
if (astat&BT848_INT_I2CDONE)
@@ -2923,18 +2901,28 @@ int configure_bt848(struct pci_dev *dev, int bttv_num)
printk("irq: %d, ",btv->irq);
printk("memory: 0x%08x.\n", btv->bt848_adr);
- btv->pll.pll_ifreq=0;
- btv->pll.pll_ifreq=0;
- btv->pll.pll_crystal=0;
- if(pll[btv->nr])
- if (!(btv->id==848 && btv->revision==0x11))
- {
- printk(KERN_INFO "bttv%d: internal PLL, single crystal operation enabled\n",bttv_num);
- btv->pll.pll_ofreq=28636363;
+ btv->pll.pll_ifreq=0;
+ btv->pll.pll_ofreq=0;
+ btv->pll.pll_crystal=0;
+ btv->pll.pll_current=0;
+ if (!(btv->id==848 && btv->revision==0x11)) {
+ switch (pll[btv->nr]) {
+ case 0:
+ /* off */
+ break;
+ case 1:
+ /* 28 MHz crystal installed */
+ btv->pll.pll_ifreq=28636363;
+ btv->pll.pll_crystal=BT848_IFORM_XT0;
+ break;
+ case 2:
+ /* 35 MHz crystal installed */
btv->pll.pll_ifreq=35468950;
btv->pll.pll_crystal=BT848_IFORM_XT1;
+ break;
}
-
+ }
+
btv->bt848_mem=ioremap(btv->bt848_adr, 0x1000);
/* clear interrupt mask */
@@ -2997,7 +2985,7 @@ static int find_bt848(void)
dev = dev->next;
}
if(bttv_num)
- printk(KERN_INFO "bttv: %d BT8xx card(s) found.\n", bttv_num);
+ printk(KERN_INFO "bttv: %d Bt8xx card(s) found.\n", bttv_num);
return bttv_num;
}
@@ -3113,4 +3101,3 @@ void cleanup_module(void)
* tab-width: 8
* End:
*/
-