patch-2.1.105 linux/drivers/char/bttv.c
Next file: linux/drivers/char/bttv.h
Previous file: linux/drivers/char/bt848.h
Back to the patch index
Back to the overall index
- Lines: 870
- Date:
Sun Jun 7 10:37:41 1998
- Orig file:
v2.1.104/linux/drivers/char/bttv.c
- Orig date:
Sun Jun 7 11:16:29 1998
diff -u --recursive --new-file v2.1.104/linux/drivers/char/bttv.c linux/drivers/char/bttv.c
@@ -24,12 +24,15 @@
TODO:
- * think of some good ioctls for Video4Linux to handle
- YUV, planar YUV, ... grabs and sell them to AC :-)
* move norm from tuner to channel struct!?
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?
+ * extra modules for tda9850, tda8425, any volunteers???
+ * support 15bpp
*/
#include <linux/module.h>
@@ -193,7 +196,7 @@
static int fbuffer_alloc(struct bttv *btv)
{
if(!btv->fbuffer)
- btv->fbuffer=(unsigned char *) rvmalloc(2*0x144000);
+ btv->fbuffer=(unsigned char *) rvmalloc(2*BTTV_MAX_FBUF);
else
printk(KERN_ERR "bttv: Double alloc of fbuffer!\n");
if(!btv->fbuffer)
@@ -393,6 +396,42 @@
/* ----------------------------------------------------------------------- */
+
+struct tvcard
+{
+ int inputs;
+ int tuner;
+ int svhs;
+ u32 gpiomask;
+ u32 muxsel[8];
+ u32 audiomux[6]; /* Tuner, Radio, internal, external, mute, stereo */
+};
+
+static struct tvcard tvcards[] =
+{
+ /* default */
+ { 3, 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}},
+ /* Hauppauge */
+ { 3, 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}},
+ /* Intel??? */
+ { 3, 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}},
+ /* AVerMedia TVPhone */
+ { 3, 0, 2,15, { 2, 3, 1, 1}, {12, 0,11,11, 0}},
+ /* Matrix Vision MV-Delta */
+ { 5,-1, 4, 0, { 2, 3, 1, 0, 0}},
+ /* Fly Video II */
+ { 3, 0, 2, 0xc00, { 2, 3, 1, 1},
+ {0, 0xc00, 0x800, 0x400, 0xc00, 0}},
+};
+#define TVCARDS (sizeof(tvcards)/sizeof(tvcard))
+
+
/*
* Tuner, Radio, internal, external and mute
*/
@@ -404,17 +443,14 @@
{ 0x00, 0x01, 0x02, 0x03, 0x04}, /* Hauppauge */
{ 0x04, 0x00, 0x02, 0x03, 0x01}, /* STB */
{ 0x00, 0x01, 0x02, 0x03, 0x04}, /* Intel??? */
- { 0x00, 0x01, 0x02, 0x03, 0x04}, /* Diamond DTV2000 */
+ { 0x00, 0x01, 0x00, 0x01, 0x03}, /* Diamond DTV2000 */
{ 0x0c, 0x00, 0x0b, 0x0b, 0x00}, /* AVerMedia TVPhone */
};
static void audio(struct bttv *btv, int mode)
{
- /* enable least significant GPIO output nibble */
- btwrite(0x0f, BT848_GPIO_OUT_EN);
-
- /* select direct input */
- btwrite(0x00, BT848_GPIO_REG_INP);
+ btaor(tvcards[btv->type].gpiomask, ~tvcards[btv->type].gpiomask,
+ BT848_GPIO_OUT_EN);
switch (mode)
{
@@ -437,12 +473,17 @@
break;
}
/* if audio mute or not in H-lock, turn audio off */
- if ((btv->audio&AUDIO_MUTE) ||
- (!btv->radio && !(btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC)))
+ if ((btv->audio&AUDIO_MUTE)
+#if 0
+ ||
+ (!btv->radio && !(btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC))
+#endif
+ )
mode=AUDIO_OFF;
if ((mode == 0) && (btv->radio))
mode = 1;
- btaor(audiomuxs[btv->type][mode] , ~0x0f, BT848_GPIO_DATA);
+ btaor(tvcards[btv->type].audiomux[mode],
+ ~tvcards[btv->type].gpiomask, BT848_GPIO_DATA);
}
@@ -469,14 +510,77 @@
}
}
-static void bt848_muxsel(struct bttv *btv, uint input)
+
+/* If Bt848a or Bt849, use PLL for PAL/SECAM and crystal for NTSC*/
+
+static int set_pll(struct bttv *btv)
+{
+ int i;
+
+ if (!btv->pll)
+ return 0;
+ if ((btread(BT848_IFORM)&BT848_IFORM_XT0))
+ {
+ /* printk ("switching PLL off\n");*/
+ btwrite(0x00,BT848_TGCTRL);
+ btwrite(0x00,BT848_PLL_XCI);
+ btv->pll&=~2;
+ return 0;
+ }
+
+ /* do not set pll again if already active */
+ if (btv->pll&2)
+ return 1;
+
+ /* printk ("setting PLL for PAL/SECAM\n");*/
+
+ btwrite(0x00,BT848_TGCTRL);
+ btwrite(0xf9,BT848_PLL_F_LO);
+ btwrite(0xdc,BT848_PLL_F_HI);
+ btwrite(0x8e,BT848_PLL_XCI);
+
+ /* Ugh ugh ugh .. schedule ? */
+ udelay(100000);
+ for (i=0; i<100; i++)
+ {
+ if ((btread(BT848_DSTATUS)&BT848_DSTATUS_PLOCK))
+ btwrite(0,BT848_DSTATUS);
+ else
+ {
+ btwrite(0x08,BT848_TGCTRL);
+ btv->pll|=2;
+ return 1;
+ }
+ udelay(10000);
+ }
+ return -1;
+}
+
+static void bt848_muxsel(struct bttv *btv, unsigned int input)
{
- input&=3;
+ btwrite(tvcards[btv->type].gpiomask, BT848_GPIO_OUT_EN);
/* This seems to get rid of some synchronization problems */
btand(~(3<<5), BT848_IFORM);
mdelay(10);
+ input %= tvcards[btv->type].inputs;
+ if (input==tvcards[btv->type].svhs)
+ {
+ btor(BT848_CONTROL_COMP, BT848_E_CONTROL);
+ btor(BT848_CONTROL_COMP, BT848_O_CONTROL);
+ }
+ else
+ {
+ btand(~BT848_CONTROL_COMP, BT848_E_CONTROL);
+ btand(~BT848_CONTROL_COMP, BT848_O_CONTROL);
+ }
+ btaor((tvcards[btv->type].muxsel[input&7]&3)<<5, ~(3<<5), BT848_IFORM);
+ audio(btv, (input!=tvcards[btv->type].tuner) ?
+ AUDIO_EXTERN : AUDIO_TUNER);
+ btaor(tvcards[btv->type].muxsel[input]>>4,
+ ~tvcards[btv->type].gpiomask, BT848_GPIO_DATA);
+#if 0
if (input==3)
{
btor(BT848_CONTROL_COMP, BT848_E_CONTROL);
@@ -491,6 +595,7 @@
input=3;
btaor(((input+2)&3)<<5, ~(3<<5), BT848_IFORM);
audio(btv, input ? AUDIO_EXTERN : AUDIO_TUNER);
+#endif
}
@@ -540,8 +645,51 @@
8, 6, 4, 4, 4, 3, 2, 2, 4, 3, 0, 0, 0, 0, 2, 0
};
-static int make_vrisctab(struct bttv *btv, unsigned int *ro, unsigned int *re,
- unsigned int *vbuf, unsigned short width, unsigned short height, unsigned short fmt)
+int palette2fmt[] = {
+ 0,
+ BT848_COLOR_FMT_Y8,
+ BT848_COLOR_FMT_RGB8,
+ BT848_COLOR_FMT_RGB16,
+ BT848_COLOR_FMT_RGB24,
+ BT848_COLOR_FMT_RGB32,
+ BT848_COLOR_FMT_RGB15,
+};
+
+static int make_rawrisctab(struct bttv *btv, unsigned int *ro,
+ unsigned int *re, unsigned int *vbuf)
+{
+ unsigned long line;
+ unsigned long bpl=1024;
+ unsigned long vadr=(unsigned long) vbuf;
+
+ *(ro++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(ro++)=0;
+ *(re++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(re++)=0;
+
+ /* In PAL 650 blocks of 256 DWORDs are sampled, but only if VDELAY
+ is 2. We'll have to handle this inside the IRQ handler ... */
+
+ for (line=0; line < 640; line++)
+ {
+ *(ro++)=BT848_RISC_WRITE|bpl|BT848_RISC_SOL|BT848_RISC_EOL;
+ *(ro++)=kvirt_to_bus(vadr);
+ *(re++)=BT848_RISC_WRITE|bpl|BT848_RISC_SOL|BT848_RISC_EOL;
+ *(re++)=kvirt_to_bus(vadr+BTTV_MAX_FBUF/2);
+ vadr+=bpl;
+ }
+
+ *(ro++)=BT848_RISC_JUMP;
+ *(ro++)=btv->bus_vbi_even;
+ *(re++)=BT848_RISC_JUMP|BT848_RISC_IRQ|(2<<16);
+ *(re++)=btv->bus_vbi_odd;
+
+ return 0;
+}
+
+
+static int make_vrisctab(struct bttv *btv, unsigned int *ro,
+ unsigned int *re,
+ unsigned int *vbuf, unsigned short width,
+ unsigned short height, unsigned short fmt)
{
unsigned long line;
unsigned long bpl; /* bytes per line */
@@ -551,6 +699,9 @@
int inter;
unsigned long vadr=(unsigned long) vbuf;
+ if (btv->gfmt==BT848_COLOR_FMT_RAW)
+ return make_rawrisctab(btv, ro, re, vbuf);
+
inter = (height>btv->win.cropheight/2) ? 1 : 0;
bpl=width*fmtbppx2[fmt&0xf]/2;
@@ -652,6 +803,151 @@
*x+=dx;
}
+static void make_clip_tab(struct bttv *btv, struct cliprec *cr, int count)
+{
+ int i,ncr;
+ int yy, y, x, dx;
+ struct cliprec first, *cur, *cur2, *nx, first2, *prev, *nx2;
+ int bpp, bpl, width, height, inter;
+ unsigned int **rp,*ro,*re;
+ unsigned long adr;
+ int cx,cx2,cy,cy2;
+
+ inter=(btv->win.interlace&1)^1;
+ bpp=btv->win.bpp;
+ bpl=btv->win.bpl;
+ ncr=btv->ncr;
+ ro=btv->risc_odd;
+ re=btv->risc_even;
+ width=btv->win.width;
+ height=btv->win.height;
+ adr=btv->win.vidadr+btv->win.x*bpp+btv->win.y*bpl;
+
+ /* clip clipping rects 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 (cr[i].y<cy)
+ {
+ if (cr[i].y2<cy)
+ continue;
+ cr[i].y=cy;
+ }
+ if (cr[i].y2>=cy2)
+ {
+ if (cr[i].y>=cy2)
+ continue;
+ cr[i].y2=cy2-1;
+ }
+ if (cr[i].x<cx)
+ {
+ if (cr[i].x2<cx)
+ continue;
+ cr[i].x=cx;
+ }
+ if (cr[i].x2>=cx2)
+ {
+ if (cr[i].x>=cx2)
+ continue;
+ cr[i].x2=cx2-1;
+ }
+ 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;
+
+ *(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++)
+ {
+ y=yy>>inter;
+ rp= (yy&1) ? &re : &ro;
+
+ /* remove rects with y2 > y */
+ if ((cur=first2.next))
+ {
+ prev=&first2;
+ do
+ {
+ if (cur->y2 < 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->x2-x+1;
+ }
+ else if (x+dx < cur2->x2)
+ dx=cur2->x2-x+1;
+ }
+ 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))
+ adr+=bpl;
+ }
+
+ *(ro++)=BT848_RISC_JUMP;
+ *(ro++)=btv->bus_vbi_even;
+ *(re++)=BT848_RISC_JUMP;
+ *(re++)=btv->bus_vbi_odd;
+}
+
/*
* Set the registers for the size we have specified. Don't bother
* trying to understand this without the BT848 manual in front of
@@ -683,10 +979,16 @@
944, 186, 922, 0x20},
/* PAL-M */
{ 640, 480, 910, 0x68, 0x5d, (BT848_IFORM_PAL_M|BT848_IFORM_XT0),
- 780, 186, 922, 0x16},
+ 780, 135, 754, 0x16},
/* PAL-N */
{ 768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_N|BT848_IFORM_XT1),
944, 186, 922, 0x20},
+ /* PAL-NC */
+ { 768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_NC|BT848_IFORM_XT0),
+ 944, 186, 922, 0x20},
+ /* NTSC-Japan */
+ { 640, 480, 910, 0x68, 0x5d, (BT848_IFORM_NTSC_J|BT848_IFORM_XT0),
+ 780, 135, 754, 0x16},
};
#define TVNORMS (sizeof(tvnorms)/sizeof(tvnorm))
@@ -709,7 +1011,7 @@
btwrite(vtc, BT848_E_VTC+off);
btwrite(hscale>>8, BT848_E_HSCALE_HI+off);
btwrite(hscale&0xff, BT848_E_HSCALE_LO+off);
- btaor((vscale>>8), 0xc0, BT848_E_VSCALE_HI+off);
+ btaor((vscale>>8), 0xe0, BT848_E_VSCALE_HI+off);
btwrite(vscale&0xff, BT848_E_VSCALE_LO+off);
btwrite(hactive&0xff, BT848_E_HACTIVE_LO+off);
btwrite(hdelay&0xff, BT848_E_HDELAY_LO+off);
@@ -747,6 +1049,8 @@
btwrite(tvn->adelay, BT848_ADELAY);
btwrite(tvn->bdelay, BT848_BDELAY);
btaor(tvn->iform,~(BT848_IFORM_NORM|BT848_IFORM_XTBOTH), BT848_IFORM);
+
+ set_pll(btv);
btwrite(fmt, BT848_COLOR_FMT);
hactive=width;
@@ -790,6 +1094,9 @@
unsigned short format;
int bpp;
+ btv->win.color_fmt=format= (btv->win.depth==15) ? BT848_COLOR_FMT_RGB15 :
+ bpp2fmt[(btv->win.bpp-1)&3];
+#if 0
bpp=fmtbppx2[btv->win.color_fmt&0x0f]/2;
if (btv->win.bpp == 0)
{
@@ -800,6 +1107,7 @@
btv->win.color_fmt=format=bpp2fmt[(btv->win.bpp-1)&3];
else
format=btv->win.color_fmt;
+#endif
/* RGB8 seems to be a 9x5x5 GRB color cube starting at
* color 16. Why the h... can't they even mention this in the
@@ -807,11 +1115,12 @@
* it never occured them]
* Enable dithering in this mode
*/
+#if 0
if (format==BT848_COLOR_FMT_RGB8)
btand(~0x10, BT848_CAP_CTL);
else
btor(0x10, BT848_CAP_CTL);
-
+#endif
bt848_set_geo(btv,btv->win.width, btv->win.height, format);
}
@@ -876,6 +1185,8 @@
if(fbuffer_alloc(btv))
return -ENOBUFS;
}
+ if(btv->grabbing>1)
+ return -ENOBUFS;
/*
* No grabbing past the end of the buffer!
@@ -887,7 +1198,7 @@
if(mp->height <0 || mp->width <0)
return -EINVAL;
- if(mp->height>480 || mp->width>640)
+ if(mp->height>576 || mp->width>768)
return -EINVAL;
/*
@@ -900,11 +1211,11 @@
* Ok load up the BT848
*/
- vbuf=(unsigned int *)(btv->fbuffer+0x144000*mp->frame);
+ vbuf=(unsigned int *)(btv->fbuffer+BTTV_MAX_FBUF*mp->frame);
if (!(btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC))
return -EAGAIN;
- ro=btv->grisc+(((btv->grabcount++)&1) ? 2048 :0);
- re=ro+1024;
+ ro=btv->grisc+(((btv->grabcount++)&1) ? 4096 :0);
+ re=ro+2048;
btv->gwidth=mp->width;
btv->gheight=mp->height;
btv->gfmt=mp->format;
@@ -912,8 +1223,13 @@
/* bt848_set_risc_jmps(btv); */
btor(3, BT848_CAP_CTL);
btor(3, BT848_GPIO_DMA_CTL);
- btv->gro=virt_to_bus(ro);
- btv->gre=virt_to_bus(re);
+ if (btv->grabbing) {
+ btv->gro_next=virt_to_bus(ro);
+ btv->gre_next=virt_to_bus(re);
+ } else {
+ btv->gro=virt_to_bus(ro);
+ btv->gre=virt_to_bus(re);
+ }
if (!(btv->grabbing++))
btv->risc_jmp[12]=BT848_RISC_JUMP|(0x8<<16)|BT848_RISC_IRQ;
/* interruptible_sleep_on(&btv->capq); */
@@ -990,7 +1306,7 @@
find_vga();
btv->fbuffer=NULL;
if (!btv->fbuffer)
- btv->fbuffer=(unsigned char *) rvmalloc(2*0x144000);
+ btv->fbuffer=(unsigned char *) rvmalloc(2*BTTV_MAX_FBUF);
if (!btv->fbuffer)
{
btv->user--;
@@ -1014,7 +1330,7 @@
bt848_set_risc_jmps(btv);
if(btv->fbuffer)
- rvfree((void *) btv->fbuffer, 2*0x144000);
+ rvfree((void *) btv->fbuffer, 2*BTTV_MAX_FBUF);
btv->fbuffer=0;
MOD_DEC_USE_COUNT;
}
@@ -1439,13 +1755,15 @@
case VIDIOCGPICT:
{
struct video_picture p=btv->picture;
- if(btv->win.bpp==1)
+ if(btv->win.depth==8)
p.palette=VIDEO_PALETTE_HI240;
- if(btv->win.bpp==2)
+ if(btv->win.depth==15)
+ p.palette=VIDEO_PALETTE_RGB555;
+ if(btv->win.depth==16)
p.palette=VIDEO_PALETTE_RGB565;
- if(btv->win.bpp==3)
+ if(btv->win.depth==24)
p.palette=VIDEO_PALETTE_RGB24;
- if(btv->win.bpp==4)
+ if(btv->win.depth==32)
p.palette=VIDEO_PALETTE_RGB32;
if(copy_to_user(arg, &p, sizeof(p)))
@@ -1455,6 +1773,7 @@
case VIDIOCSPICT:
{
struct video_picture p;
+ int format;
if(copy_from_user(&p, arg,sizeof(p)))
return -EFAULT;
/* We want -128 to 127 we get 0-65535 */
@@ -1466,8 +1785,15 @@
bt848_hue(btv, (p.hue>>8)-128);
/* 0-511 */
bt848_contrast(btv, p.contrast>>7);
- btv->picture=p;
- return 0;
+ btv->picture = p;
+
+ /* set palette if bpp matches */
+ if (p.palette < sizeof(palette2fmt)/sizeof(int)) {
+ format = palette2fmt[p.palette];
+ if (fmtbppx2[format&0x0f]/2 == btv->win.bpp)
+ btv->win.color_fmt = format;
+ }
+ return 0;
}
case VIDIOCSWIN:
{
@@ -1571,7 +1897,7 @@
v.base=(void *)btv->win.vidadr;
v.height=btv->win.sheight;
v.width=btv->win.swidth;
- v.depth=btv->win.bpp*8;
+ v.depth=btv->win.depth;
v.bytesperline=btv->win.bpl;
if(copy_to_user(arg, &v,sizeof(v)))
return -EFAULT;
@@ -1585,7 +1911,7 @@
return -EPERM;
if(copy_from_user(&v, arg,sizeof(v)))
return -EFAULT;
- if(v.depth!=8 && 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)
return -EINVAL;
if (v.base) {
/* also handle virtual base addresses */
@@ -1596,7 +1922,8 @@
}
btv->win.sheight=v.height;
btv->win.swidth=v.width;
- btv->win.bpp=v.depth/8;
++ btv->win.bpp=((v.depth+1)&0x18)/8;
+ btv->win.depth=v.depth;
btv->win.bpl=v.bytesperline;
DEBUG(printk("Display at %p is %d by %d, bytedepth %d, bpl %d\n",
@@ -1635,13 +1962,21 @@
strcpy(v.name,"TV");
if (btv->have_msp3400)
{
- v.flags|=VIDEO_AUDIO_VOLUME;
- i2c_control_device(&(btv->i2c),
- I2C_DRIVERID_MSP3400,
- MSP_GET_VOLUME,&(v.volume));
- i2c_control_device(&(btv->i2c),
- I2C_DRIVERID_MSP3400,
- MSP_GET_STEREO,&(v.mode));
+ v.flags|=VIDEO_AUDIO_VOLUME |
+ VIDEO_AUDIO_BASS |
+ VIDEO_AUDIO_TREBLE;
+ i2c_control_device(&(btv->i2c),
+ I2C_DRIVERID_MSP3400,
+ MSP_GET_VOLUME,&(v.volume));
+ i2c_control_device(&(btv->i2c),
+ I2C_DRIVERID_MSP3400,
+ MSP_GET_BASS,&(v.bass));
+ i2c_control_device(&(btv->i2c),
+ I2C_DRIVERID_MSP3400,
+ MSP_GET_TREBLE,&(v.treble));
+ i2c_control_device(&(btv->i2c),
+ I2C_DRIVERID_MSP3400,
+ MSP_GET_STEREO,&(v.mode));
}
else v.mode = VIDEO_SOUND_MONO;
if(copy_to_user(arg,&v,sizeof(v)))
@@ -1655,28 +1990,37 @@
return -EFAULT;
if(v.flags&VIDEO_AUDIO_MUTE)
audio(btv, AUDIO_MUTE);
- if(v.audio<0||v.audio>2)
+ /* One audio source per tuner */
+ if(v.audio!=0)
return -EINVAL;
bt848_muxsel(btv,v.audio);
if(!(v.flags&VIDEO_AUDIO_MUTE))
audio(btv, AUDIO_UNMUTE);
if (btv->have_msp3400)
{
- i2c_control_device(&(btv->i2c),
- I2C_DRIVERID_MSP3400,
- MSP_SET_VOLUME,&(v.volume));
- i2c_control_device(&(btv->i2c),
- I2C_DRIVERID_MSP3400,
- MSP_SET_STEREO,&(v.mode));
+ i2c_control_device(&(btv->i2c),
+ I2C_DRIVERID_MSP3400,
+ MSP_SET_VOLUME,&(v.volume));
+ i2c_control_device(&(btv->i2c),
+ I2C_DRIVERID_MSP3400,
+ MSP_SET_BASS,&(v.bass));
+ i2c_control_device(&(btv->i2c),
+ I2C_DRIVERID_MSP3400,
+ MSP_SET_TREBLE,&(v.treble));
+ i2c_control_device(&(btv->i2c),
+ I2C_DRIVERID_MSP3400,
+ MSP_SET_STEREO,&(v.mode));
}
btv->audio_dev=v;
return 0;
}
case VIDIOCSYNC:
- if (btv->grabbing && btv->grab==btv->lastgrab)
+ if (!btv->grabbing)
+ return -EAGAIN;
+ if (btv->grab==btv->lastgrab)
interruptible_sleep_on(&btv->capq);
- btv->lastgrab=btv->grab;
+ btv->lastgrab++;
return 0;
case BTTV_WRITEE:
@@ -1728,7 +2072,7 @@
unsigned long start=(unsigned long) adr;
unsigned long page,pos;
- if (size>2*0x144000)
+ if (size>2*BTTV_MAX_FBUF)
return -EINVAL;
if (!btv->fbuffer)
{
@@ -1960,18 +2304,20 @@
};
static struct vidbases vbs[] = {
- { PCI_VENDOR_ID_TSENG, 0, "TSENG", PCI_BASE_ADDRESS_0},
- { PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MIL,
- "Matrox Millennium", PCI_BASE_ADDRESS_1},
- { PCI_VENDOR_ID_MATROX, 0x051a, "Matrox Mystique", PCI_BASE_ADDRESS_1},
- { PCI_VENDOR_ID_S3, 0, "S3", PCI_BASE_ADDRESS_0},
{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_210888GX,
"ATI MACH64 Winturbo", PCI_BASE_ADDRESS_0},
+ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_215GT,
+ "ATI MACH64 GT", PCI_BASE_ADDRESS_0},
{ PCI_VENDOR_ID_CIRRUS, 0, "Cirrus Logic", PCI_BASE_ADDRESS_0},
- { PCI_VENDOR_ID_N9, PCI_DEVICE_ID_N9_I128,
- "Number Nine Imagine 128", PCI_BASE_ADDRESS_0},
{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA,
"DEC DC21030", PCI_BASE_ADDRESS_0},
+ { PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MIL,
+ "Matrox Millennium", PCI_BASE_ADDRESS_1},
+ { PCI_VENDOR_ID_MATROX, 0x051a, "Matrox Mystique", PCI_BASE_ADDRESS_1},
+ { PCI_VENDOR_ID_N9, PCI_DEVICE_ID_N9_I128,
+ "Number Nine Imagine 128", PCI_BASE_ADDRESS_0},
+ { PCI_VENDOR_ID_S3, 0, "S3", PCI_BASE_ADDRESS_0},
+ { PCI_VENDOR_ID_TSENG, 0, "TSENG", PCI_BASE_ADDRESS_0},
};
@@ -2159,6 +2505,15 @@
}
}
+static void init_tda8425(struct i2c_bus *bus)
+{
+ I2CWrite(bus, I2C_TDA8425, TDA8425_VL, 0xFC, 1); /* volume left 0dB */
+ I2CWrite(bus, I2C_TDA8425, TDA8425_VR, 0xFC, 1); /* volume right 0dB */
+ I2CWrite(bus, I2C_TDA8425, TDA8425_BA, 0xF6, 1); /* bass 0dB */
+ I2CWrite(bus, I2C_TDA8425, TDA8425_TR, 0xF6, 1); /* treble 0dB */
+ I2CWrite(bus, I2C_TDA8425, TDA8425_S1, 0xCE, 1); /* mute off */
+}
+
static void init_tda9850(struct i2c_bus *bus)
{
@@ -2198,10 +2553,27 @@
btv->type=BTTV_STB;
}
- btv->dbx = I2CRead(&(btv->i2c), I2C_TDA9850) ? 0 : 1;
+ if (I2CRead(&(btv->i2c), I2C_TDA9850) >=0)
+ {
+ btv->audio_chip = TDA9850;
+ printk(KERN_INFO "bttv: audio chip: TDA9850\n");
+ }
- if (btv->dbx)
- init_tda9850(&(btv->i2c));
+ if (I2CRead(&(btv->i2c), I2C_TDA8425) >=0)
+ {
+ btv->audio_chip = TDA8425;
+ printk("bttv: audio chip: TDA8425\n");
+ }
+
+ switch(btv->audio_chip)
+ {
+ case TDA9850:
+ init_tda9850(&(btv->i2c));
+ break;
+ case TDA8425:
+ init_tda8425(&(btv->i2c));
+ break;
+ }
/* How do I detect the tuner type for other cards but Miro ??? */
printk(KERN_INFO "bttv: model: ");
@@ -2238,6 +2610,10 @@
printk("AVerMedia\n");
strcpy(btv->video_dev.name,"BT848(AVerMedia)");
break;
+ case BTTV_MATRIX_VISION:
+ printk("MATRIX-Vision\n");
+ strcpy(btv->video_dev.name,"BT848(MATRIX-Vision)");
+ break;
}
audio(btv, AUDIO_MUTE);
}
@@ -2321,6 +2697,7 @@
btv->win.cropx=0;
btv->win.cropy=0;
btv->win.bpp=2;
+ btv->win.depth=16;
btv->win.color_fmt=BT848_COLOR_FMT_RGB16;
btv->win.bpl=1024*btv->win.bpp;
btv->win.swidth=1024;
@@ -2359,7 +2736,7 @@
btv->vbibuf=(unsigned char *) vmalloc(VBIBUF_SIZE);
if (!btv->vbibuf)
return -1;
- if (!(btv->grisc=(unsigned int *) kmalloc(16384, GFP_KERNEL)))
+ if (!(btv->grisc=(unsigned int *) kmalloc(32768, GFP_KERNEL)))
return -1;
btv->fbuffer=NULL;
@@ -2372,7 +2749,11 @@
btwrite(0x00, BT848_CAP_CTL);
btwrite(0xfc, BT848_GPIO_DMA_CTL);
- btwrite(0x0ff, BT848_VBI_PACK_SIZE);
+ /* select direct input */
+ btwrite(0x00, BT848_GPIO_REG_INP);
+
+
+ btwrite(0xff, BT848_VBI_PACK_SIZE);
btwrite(1, BT848_VBI_PACK_DEL);
@@ -2502,10 +2883,11 @@
/* captured full frame */
if (stat&(2<<28))
{
- btv->grab++;
wake_up_interruptible(&btv->capq);
if ((--btv->grabbing))
{
+ btv->gro = btv->gro_next;
+ btv->gre = btv->gre_next;
btv->risc_jmp[5]=btv->gro;
btv->risc_jmp[11]=btv->gre;
bt848_set_geo(btv, btv->gwidth,
@@ -2517,6 +2899,7 @@
btv->win.height,
btv->win.color_fmt);
}
+ wake_up_interruptible(&btv->capq);
break;
}
if (stat&(8<<28))
@@ -2647,12 +3030,21 @@
pcibios_read_config_byte(btv->bus, btv->devfn, PCI_CLASS_REVISION,
&btv->revision);
printk(KERN_INFO "bttv: Brooktree Bt%d (rev %d) ",
- btv->id, btv->revision);
+ btv->id, btv->revision);
printk("bus: %d, devfn: %d, ",
btv->bus, btv->devfn);
printk("irq: %d, ",btv->irq);
printk("memory: 0x%08x.\n", btv->bt848_adr);
+ btv->pll = 0;
+#ifdef USE_PLL
+ if (btv->id==849 || (btv->id==848 && btv->revision==0x12))
+ {
+ printk(KERN_INFO "bttv: internal PLL, single crystal operation enabled.\n");
+ btv->pll=1;
+ }
+#endif
+
btv->bt848_mem=ioremap(btv->bt848_adr, 0x1000);
result = request_irq(btv->irq, bttv_irq,
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov