diff options
author | Gerd Knorr <devnull@localhost> | 2005-02-22 14:06:32 +0000 |
---|---|---|
committer | Gerd Knorr <devnull@localhost> | 2005-02-22 14:06:32 +0000 |
commit | 396e51e220858c196614a95e21b12e433b3682cb (patch) | |
tree | 1aeef54335f13d2ee59d3dc22cd800d3923cb271 /linux | |
parent | a68e65b100156e8877696e02d27b7c6485a6a7e6 (diff) | |
download | mediapointer-dvb-s2-396e51e220858c196614a95e21b12e433b3682cb.tar.gz mediapointer-dvb-s2-396e51e220858c196614a95e21b12e433b3682cb.tar.bz2 |
- Kodicom-4400R support (by William M. Brack).
Diffstat (limited to 'linux')
-rw-r--r-- | linux/drivers/media/video/bttv-cards.c | 172 | ||||
-rw-r--r-- | linux/drivers/media/video/bttv.h | 3 |
2 files changed, 173 insertions, 2 deletions
diff --git a/linux/drivers/media/video/bttv-cards.c b/linux/drivers/media/video/bttv-cards.c index 9fb74a8b1..456b5d883 100644 --- a/linux/drivers/media/video/bttv-cards.c +++ b/linux/drivers/media/video/bttv-cards.c @@ -1,5 +1,5 @@ /* - $Id: bttv-cards.c,v 1.46 2005/02/21 13:57:59 kraxel Exp $ + $Id: bttv-cards.c,v 1.47 2005/02/22 14:06:32 kraxel Exp $ bttv-cards.c @@ -80,6 +80,9 @@ static void picolo_tetra_init(struct bttv *btv); static void tibetCS16_muxsel(struct bttv *btv, unsigned int input); static void tibetCS16_init(struct bttv *btv); +static void kodicom4400r_muxsel(struct bttv *btv, unsigned int input); +static void kodicom4400r_init(struct bttv *btv); + static void sigmaSLC_muxsel(struct bttv *btv, unsigned int input); static void sigmaSQ_muxsel(struct bttv *btv, unsigned int input); @@ -101,6 +104,7 @@ static unsigned int pll[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET }; static unsigned int tuner[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET }; static unsigned int svhs[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET }; static unsigned int remote[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = UNSET }; +static struct bttv *master[BTTV_MAX] = { [ 0 ... (BTTV_MAX-1) ] = NULL }; #ifdef MODULE static unsigned int autoload = 1; #else @@ -2201,6 +2205,63 @@ struct tvcard bttv_tvcards[] = { .no_tda7432 = 1, .tuner_type = -1, .muxsel_hook = tibetCS16_muxsel, +}, +{ + /* Bill Brack <wbrack@mmm.com.hk> */ + /* + * Note that, because of the card's wiring, the "master" + * BT878A chip (i.e. the one which controls the analog switch + * and must use this card type) is the 2nd one detected. The + * other 3 chips should use card type 0x85, whose description + * follows this one. There is a EEPROM on the card (which is + * connected to the I2C of one of those other chips), but is + * not currently handled. There is also a facility for a + * "monitor", which is also not currently implemented. + */ + .name = "Kodicom 4400R (master)", + .video_inputs = 16, + .audio_inputs = 0, + .tuner = -1, + .tuner_type = -1, + .svhs = -1, + /* GPIO bits 0-9 used for analog switch: + * 00 - 03: camera selector + * 04 - 06: channel (controller) selector + * 07: data (1->on, 0->off) + * 08: strobe + * 09: reset + * bit 16 is input from sync separator for the channel + */ + .gpiomask = 0x0003ff, + .no_gpioirq = 1, + .muxsel = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }, + .pll = PLL_28, + .no_msp34xx = 1, + .no_tda7432 = 1, + .no_tda9875 = 1, + .muxsel_hook = kodicom4400r_muxsel, +}, +{ + /* Bill Brack <wbrack@mmm.com.hk> */ + /* Note that, for reasons unknown, the "master" BT878A chip (i.e. the + * one which controls the analog switch, and must use the card type) + * is the 2nd one detected. The other 3 chips should use this card + * type + */ + .name = "Kodicom 4400R (slave)", + .video_inputs = 16, + .audio_inputs = 0, + .tuner = -1, + .tuner_type = -1, + .svhs = -1, + .gpiomask = 0x010000, + .no_gpioirq = 1, + .muxsel = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }, + .pll = PLL_28, + .no_msp34xx = 1, + .no_tda7432 = 1, + .no_tda9875 = 1, + .muxsel_hook = kodicom4400r_muxsel, }}; static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); @@ -2695,6 +2756,9 @@ void __devinit bttv_init_card2(struct bttv *btv) case BTTV_TIBET_CS16: tibetCS16_init(btv); break; + case BTTV_KODICOM_4400R: + kodicom4400r_init(btv); + break; } /* pll configuration */ @@ -3911,6 +3975,112 @@ static void tibetCS16_init(struct bttv *btv) gpio_write(0x0f7fff); } +/* + * The following routines for the Kodicom-4400r get a little mind-twisting. + * There is a "master" controller and three "slave" controllers, together + * an analog switch which connects any of 16 cameras to any of the BT87A's. + * The analog switch is controlled by the "master", but the detection order + * of the four BT878A chips is in an order which I just don't understand. + * The "master" is actually the second controller to be detected. The + * logic on the board uses logical numbers for the 4 controlers, but + * those numbers are different from the detection sequence. When working + * with the analog switch, we need to "map" from the detection sequence + * over to the board's logical controller number. This mapping sequence + * is {3, 0, 2, 1}, i.e. the first controller to be detected is logical + * unit 3, the second (which is the master) is logical unit 0, etc. + * We need to maintain the status of the analog switch (which of the 16 + * cameras is connected to which of the 4 controllers). Rather than + * add to the bttv structure for this, we use the data reserved for + * the mbox (unused for this card type). + */ + +/* + * First a routine to set the analog switch, which controls which camera + * is routed to which controller. The switch comprises an X-address + * (gpio bits 0-3, representing the camera, ranging from 0-15), and a + * Y-address (gpio bits 4-6, representing the controller, ranging from 0-3). + * A data value (gpio bit 7) of '1' enables the switch, and '0' disables + * the switch. A STROBE bit (gpio bit 8) latches the data value into the + * specified address. The idea is to set the address and data, then bring + * STROBE high, and finally bring STROBE back to low. + */ +static void kodicom4400r_write(struct bttv *btv, + unsigned char xaddr, + unsigned char yaddr, + unsigned char data) { + unsigned int udata; + + udata = (data << 7) | ((yaddr&3) << 4) | (xaddr&0xf); + gpio_bits(0x1ff, udata); /* write ADDR and DAT */ + gpio_bits(0x1ff, udata | (1 << 8)); /* strobe high */ + gpio_bits(0x1ff, udata); /* strobe low */ +} + +/* + * Next the mux select. Both the "master" and "slave" 'cards' (controllers) + * use this routine. The routine finds the "master" for the card, maps + * the controller number from the detected position over to the logical + * number, writes the appropriate data to the analog switch, and housekeeps + * the local copy of the switch information. The parameter 'input' is the + * requested camera number (0 - 15). + */ +static void kodicom4400r_muxsel(struct bttv *btv, unsigned int input) +{ + char *sw_status; + int xaddr, yaddr; + struct bttv *mctlr; + static unsigned char map[4] = {3, 0, 2, 1}; + + mctlr = master[btv->c.nr]; + if (mctlr == NULL) { /* ignore if master not yet detected */ + return; + } + yaddr = (btv->c.nr - mctlr->c.nr + 1) & 3; /* the '&' is for safety */ + yaddr = map[yaddr]; + sw_status = (char *)(&mctlr->mbox_we); + xaddr = input & 0xf; + /* Check if the controller/camera pair has changed, else ignore */ + if (sw_status[yaddr] != xaddr) + { + /* "open" the old switch, "close" the new one, save the new */ + kodicom4400r_write(mctlr, sw_status[yaddr], yaddr, 0); + sw_status[yaddr] = xaddr; + kodicom4400r_write(mctlr, xaddr, yaddr, 1); + } +} + +/* + * During initialisation, we need to reset the analog switch. We + * also preset the switch to map the 4 connectors on the card to the + * *user's* (see above description of kodicom4400r_muxsel) channels + * 0 through 3 + */ +static void kodicom4400r_init(struct bttv *btv) +{ + char *sw_status = (char *)(&btv->mbox_we); + int ix; + + gpio_inout(0x0003ff, 0x0003ff); + gpio_write(1 << 9); /* reset MUX */ + gpio_write(0); + /* Preset camera 0 to the 4 controllers */ + for (ix=0; ix<4; ix++) { + sw_status[ix] = ix; + kodicom4400r_write(btv, ix, ix, 1); + } + /* + * Since this is the "master", we need to set up the + * other three controller chips' pointers to this structure + * for later use in the muxsel routine. + */ + if ((btv->c.nr<1) || (btv->c.nr>BTTV_MAX-3)) + return; + master[btv->c.nr-1] = btv; + master[btv->c.nr] = btv; + master[btv->c.nr+1] = btv; + master[btv->c.nr+2] = btv; +} + // The Grandtec X-Guard framegrabber card uses two Dual 4-channel // video multiplexers to provide up to 16 video inputs. These // multiplexers are controlled by the lower 8 GPIO pins of the diff --git a/linux/drivers/media/video/bttv.h b/linux/drivers/media/video/bttv.h index 40d94f47e..81fc7ddc8 100644 --- a/linux/drivers/media/video/bttv.h +++ b/linux/drivers/media/video/bttv.h @@ -1,5 +1,5 @@ /* - * $Id: bttv.h,v 1.16 2005/02/16 12:14:10 kraxel Exp $ + * $Id: bttv.h,v 1.17 2005/02/22 14:06:32 kraxel Exp $ * * bttv - Bt848 frame grabber driver * @@ -134,6 +134,7 @@ #define BTTV_APAC_VIEWCOMP 0x7f #define BTTV_DVICO_DVBT_LITE 0x80 #define BTTV_TIBET_CS16 0x83 +#define BTTV_KODICOM_4400R 0x84 /* i2c address list */ #define I2C_TSA5522 0xc2 |