*** sys/dev/bktr/bktr_core.c.orig Fri Sep 1 12:26:08 2006 --- sys/dev/bktr/bktr_core.c Tue Jan 30 08:32:11 2007 *************** *** 2503,2508 **** --- 2503,2582 ---- } #endif /* STATUS_SUM */ + case KODICOM_SET_IN: + mtx_lock(&bktr->kmaster->kmutex); + temp = *(unsigned char *)arg; + if (temp < 0 || temp > 15 || bktr->kmaster == NULL) { + mtx_unlock(&bktr->kmaster->kmutex); + return( EINVAL ); + } /* XXX should we stop the FIFO? XXX */ + if (temp != bktr->kinput) { + kodicom_setgpioen(bktr->kmaster); + + /* remove the old input */ + kodicom_setcamera(bktr->kmaster, bktr->kunit, + bktr->kinput, 0); + kodicom_setcamera(bktr->kmaster, bktr->kunit, + bktr->kinput, KODICOM_STROBE); + kodicom_setcamera(bktr->kmaster, bktr->kunit, + bktr->kinput, 0); + bktr->kinput = temp; + /* add the new input */ + kodicom_setcamera(bktr->kmaster, bktr->kunit, + bktr->kinput, KODICOM_ACTIVE); + kodicom_setcamera(bktr->kmaster, bktr->kunit, + bktr->kinput, KODICOM_ACTIVE | KODICOM_STROBE); + kodicom_setcamera(bktr->kmaster, bktr->kunit, + bktr->kinput, KODICOM_ACTIVE); + } + mtx_unlock(&bktr->kmaster->kmutex); + break; + + case KODICOM_GET_IN: + if (bktr->kmaster == NULL) + return( EINVAL ); + *(unsigned char *)arg = bktr->kinput; + break; + + case KODICOM_SET_OUT: + mtx_lock(&bktr->kmaster->kmutex); + temp = *(unsigned char *)arg; + if ((temp != 255 && (temp < 0 || temp > 15)) || + bktr->kmaster == NULL) { + mtx_unlock(&bktr->kmaster->kmutex); + return( EINVAL ); + } + if (temp != bktr->kmaster->koutput) { + kodicom_setgpioen(bktr->kmaster); + /* remove the old input */ + if (bktr->kmaster->koutput != 255) { + kodicom_setcamera(bktr->kmaster, KODICOM_OUTPUT, + bktr->koutput, 0); + kodicom_setcamera(bktr->kmaster, KODICOM_OUTPUT, + bktr->koutput, KODICOM_STROBE); + kodicom_setcamera(bktr->kmaster, KODICOM_OUTPUT, + bktr->koutput, 0); + } + if (temp != 255) { + bktr->kmaster->koutput = temp; + kodicom_setgpioen(bktr->kmaster); + kodicom_setcamera(bktr->kmaster, KODICOM_OUTPUT, + bktr->koutput, KODICOM_ACTIVE); + kodicom_setcamera(bktr->kmaster, KODICOM_OUTPUT, + bktr->koutput, KODICOM_ACTIVE | KODICOM_STROBE); + kodicom_setcamera(bktr->kmaster, KODICOM_OUTPUT, + bktr->koutput, KODICOM_ACTIVE); + + } + } + mtx_unlock(&bktr->kmaster->kmutex); + break; + + case KODICOM_GET_OUT: + if (bktr->kmaster == NULL) + return( EINVAL ); + *(unsigned char *)arg = bktr->kmaster->koutput; + break; default: return( ENOTTY ); } *** sys/dev/bktr/bktr_core.h.orig Wed Jan 5 19:42:31 2005 --- sys/dev/bktr/bktr_core.h Wed Nov 29 14:46:01 2006 *************** *** 94,96 **** --- 94,104 ---- int vbi_close( bktr_ptr_t bktr ); int vbi_read( bktr_ptr_t bktr, struct uio *uio, int ioflag ); + /* kodicom routines */ + #define KODICOM_RESET (1 << 9) + #define KODICOM_STROBE 0x100 + #define KODICOM_ACTIVE 0x80 + #define KODICOM_OUTPUT 0x4 + void kodicom_setcamera(struct bktr_softc *m, int device, int camera, int control); + void kodicom_setgpioen(struct bktr_softc *m); + *** sys/dev/bktr/bktr_os.c.orig Thu Aug 31 11:42:22 2006 --- sys/dev/bktr/bktr_os.c Tue Jan 30 07:45:56 2007 *************** *** 455,460 **** --- 455,533 ---- } #endif + #define PCI_VENDOR_PLX 0x3388 + #define PCI_PRODUCT_PLX_PCITOPCIBRIDGE 0x0021 + { + device_t parent, child; + unsigned int type = 0; + struct bktr_softc *mbktr, *sbktr; + int i; + /* bktr are detected out of order */ + static unsigned korder[4] = {3, 0, 2, 1}; + + /* see if grandparent is a PLX PCI-PCI bridge */ + if ((parent = device_get_parent(dev)) != NULL && + (child = device_get_parent(parent)) != NULL) + type = pci_get_devid(child); + + if (type != 0 && PCI_VENDOR(type) == PCI_VENDOR_PLX && + (PCI_PRODUCT(type) == PCI_PRODUCT_PLX_PCITOPCIBRIDGE) && + pci_get_slot(dev) == 15 && unit > 2) { + /* locate a master candidate (will be second device) */ + if ((child = device_find_child(parent, "bktr", unit-2)) == NULL) + goto notkodicom; + mbktr = device_get_softc(child); + /* intitialize the 4 sibling bktr devices */ + for (i=3; i >= 0; --i) { + if ((child = device_find_child(parent, "bktr", unit-i)) + == NULL) { + /* remove old settings, should not be used */ + while (++i < 4) { + /* child was found before */ + if ((child = device_find_child(parent, + "bktr", unit-i)) == NULL) + continue; /* XXX! */ + sbktr = device_get_softc(child); + sbktr->kmaster = NULL; + sbktr->kunit = sbktr->kinput = 0; + } + goto notkodicom; + } + sbktr = device_get_softc(child); + sbktr->kmaster = mbktr; /* save the master device */ + /* there are 4 BKTR per kodicom 4400 */ + sbktr->kunit = korder[3 - i]; + sbktr->kinput = 3 - i; + mtx_init(&sbktr->kmutex, "bktr crossbar", NULL, MTX_DEF); + } + mbktr->koutput = 255; /* no output yet */ + + /* initialize the kodicom 4400 crossbar. + * bit 9 is RESET. + * bit 8 is STROBE value in. + * bit 7 is active the crossbar rule. + * bits 4-6 is OUTPUT selection: + * values of 0-3 selects the BT878s. + * value of 4 selects the OUTPUT port. + * values of 5-7 are not used. + * bits 0-3 selects the 16 CAMERA inputs. + * cameras 0-3 are shared on the edge pins and + * on the external jacks. + * + * the second bktr device is the master. + */ + printf("kodicom master is %s\n", bktr_name(mbktr)); + kodicom_setgpioen(mbktr); + OUTL(mbktr, BKTR_GPIO_DATA, KODICOM_RESET); /* reset MUX */ + OUTL(mbktr, BKTR_GPIO_DATA, 0); + for (i=0; i<4; i++) { + kodicom_setcamera(mbktr, korder[i], i, KODICOM_ACTIVE); + kodicom_setcamera(mbktr, korder[i], i, (KODICOM_STROBE | KODICOM_ACTIVE)); + kodicom_setcamera(mbktr, korder[i], i, KODICOM_ACTIVE); + } + } + } + notkodicom: return 0; fail: *************** *** 492,497 **** --- 565,571 ---- #ifdef USE_VBIMUTEX mtx_destroy(&bktr->vbimutex); #endif + mtx_destroy(&bktr->kmutex); /* Note: We do not free memory for RISC programs, grab buffer, vbi buffers */ /* The memory is retained by the bktr_mem module so we can unload and */ *************** *** 844,849 **** --- 918,942 ---- UNLOCK_VBI(bktr); return (revents); + } + + void + kodicom_setcamera(struct bktr_softc *m, int device, int camera, int control) + { + int tmp; + if (device > 4 || camera > 15) + return; + tmp = (INL(m, BKTR_GPIO_DATA) & ~0x1ff) | control | (device << 4) | + camera; + OUTL(m, BKTR_GPIO_DATA, tmp); + } + + void + kodicom_setgpioen(struct bktr_softc *m) + { + int tmp; + tmp = INL(m, BKTR_GPIO_OUT_EN) | 0x0003ff; + OUTL(m, BKTR_GPIO_OUT_EN, tmp); } /*****************/ *** sys/dev/bktr/bktr_reg.h.orig Fri Sep 1 12:26:48 2006 --- sys/dev/bktr/bktr_reg.h Tue Jan 30 07:39:55 2007 *************** *** 698,703 **** --- 698,711 ---- int mspsimple; int dolby; #endif + + struct bktr_softc *kmaster; + unsigned char kunit; + unsigned char kinput; + unsigned char koutput; + #if (__FreeBSD_version >= 500000) + struct mtx kmutex; /* per card crossbar changing Mutex */ + #endif }; typedef struct bktr_softc bktr_reg_t; *** sys/dev/bktr/ioctl_bt848.h.orig Wed Nov 29 14:56:31 2006 --- sys/dev/bktr/ioctl_bt848.h Wed Nov 29 14:53:36 2006 *************** *** 293,296 **** --- 293,301 ---- # define BT848_IFORM_F_NTSCM (0x1) # define BT848_IFORM_F_AUTO (0x0) + #define KODICOM_SET_IN _IOW('x', 76, unsigned char) + #define KODICOM_GET_IN _IOR('x', 76, unsigned char) + #define KODICOM_SET_OUT _IOW('x', 77, unsigned char) + #define KODICOM_GET_OUT _IOR('x', 77, unsigned char) + #endif /* _DEV_BKTR_IOCTL_BT848_H_ */ *** /dev/null Wed Nov 29 13:44:00 2006 --- sys/dev/bktr/README.kodicom Fri Nov 10 07:47:12 2006 *************** *** 0 **** --- 1,37 ---- + + The Kodicom 4400 has 4 camera ports on the back of the card and 4 BT878 capture + devices. Initially the onboard input crossbar is set to input camera 1 to + the first BT878; input camera 2 to the second BT878, etc. + + Using the "KODICOM_SET_IN" ioctl(), one can change the input camera for + that BT878. An example of switching the camera to input 10: + + int i; + unsigned char c; + + if ((i = open("/dev/bktr0", O_RDONLY)) < 0) { + printf("open failed\n"); + exit(1); + } + + c = 10; /* valid cameras are 0 to 15 */ + + if (ioctl(i, KODICOM_SET_IN, &c) < 0) { + printf("setting camera failed: %d\n", errno); + exit(1); + } + + Using the "KODICOM_SET_OUT" ioctl(), one can change the output camera + for the Kodicom card (red RCA jack). Initially, the output port is not + active. Any BT878 device on the card can specify the source of the output + camera. After an output is specified, the output port remains on. In + the future, the API, may use the input value of 255 to turn off the + output port. An example of switching the output camera to input 0: + + c = 0; /* valid cameras are 0 to 15 */ + + if (ioctl(i, KODICOM_SET_OUT, &c) < 0) { + printf("setting camera failed: %d\n", errno); + exit(1); + } +